分类: LINUX
2010-03-12 20:07:37
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. 设置 s 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 "I } return 0; } |