struct IIC_dev{
wait_queue_head_t rq; // 读取等待队列
uint8_t *buffer;
uint32_t size;
uint32_t index;
struct semaphore sem;
struct cdev cdev;
};
struct IIC_dev *my_dev;
static int __init IIC_init(void)
{
// 1. 分配主设备号
dev_t devno = MKDEV( major, minor );
int ret = register_chrdev_region( devno, 1, DEVICE );//(设备号,注册号,名称)
if( ret < 0 )
{
printk(KERN_DEBUG "register major number failed with %d\n", ret);
return ret;
}
printk(KERN_DEBUG "%s:register major number OK\n",DEVICE);
// 2. 注册设备
my_dev = kmalloc(sizeof(struct IIC_dev), GFP_KERNEL);
memset( my_dev, 0, sizeof(struct IIC_dev) );
cdev_init( &my_dev->cdev, &fops );
my_dev->cdev.ops = &fops;
my_dev->cdev.owner = THIS_MODULE;
ret = cdev_add( &my_dev->cdev, devno, 1 );
if( ret < 0 )
{
printk(KERN_DEBUG "register device failed with %d\n", ret);
return ret;
}
printk(KERN_DEBUG "%s:register device OK\n",DEVICE);
// 3. 分配本驱动要使用的内存
my_dev->index = 0;
my_dev->size = 128;
my_dev->buffer = kmalloc( my_dev->size, GFP_KERNEL );
if( NULL == my_dev->buffer )
{
printk(KERN_DEBUG "kmalloc failed\n");
return -ENOMEM;
}
printk(KERN_DEBUG "%s:kmalloc buffer OK\n",DEVICE);
// 4. 初始化信号量
init_MUTEX( &(my_dev->sem) );
printk(KERN_DEBUG "%s:init semaphore OK\n",DEVICE);
// 5. 初始化等待队列头
init_waitqueue_head(&my_dev->rq);
// 6. Remap IIC 寄存器
address_map();
// 7. 设置 s3c2410 IIC
unsigned int tmp = ioread32( R_GPEUP );
tmp |= 0xc000; //Pull-up disable
iowrite32( tmp, R_GPEUP );
tmp = ioread32( R_GPECON );
tmp |= 0xa0000000; //GPE15:IICSDA , GPE14:IICSCL
iowrite32( tmp, R_GPECON );
return 0;
}
static void __exit IIC_exit(void)
{
dev_t devno = MKDEV( major, minor );
// 以相反的顺序清除
address_unmap();
kfree( my_dev->buffer );
cdev_del( &my_dev->cdev );
kfree( my_dev );
printk(KERN_DEBUG "%s:kfree OK\n",DEVICE);
unregister_chrdev_region( devno, 1 );
printk(KERN_DEBUG "%s:unregister device OK\n",DEVICE);
}
static void set_slave_recv_mode(void)
{
iowrite8( 0xE2, R_IICCON ); // 使能ACK,使能中断
iowrite8( 0xAA, R_IICADD ); // 从器件地址
iowrite8( 0x10, R_IICSTAT); // 设置从器件接收模式
barrier(); // 强制写入寄存器
}
int IIC_open(struct inode *inode, struct file *file)
{
struct IIC_dev *dev = container_of(inode->i_cdev, struct IIC_dev, cdev);
file->private_data = dev;
if( down_interruptible(&dev->sem) )
return -ERESTARTSYS;
set_slave_recv_mode();
int ret = request_irq( IRQ_IIC, interrupt_handle,SA_INTERRUPT, DEVICE, (void*)dev );
if( ret )
{
printk( KERN_INFO "I2C: can't get assigned irq %d\n", IRQ_IIC );
}
return 0;
}
阅读(804) | 评论(0) | 转发(0) |