阅读:2268回复:0
帮忙看一下我的iic驱动,根据demo改写,scl和sda一直保持为高
我用的是2410的板子
问题: 当调用写函数的时候,根本没有中断产生,但是请求中断是成功的。 不知道是那里的原因。请大家帮我看一下。 #include <linux/config.h> #include <linux/module.h> #include <linux/kernel.h> #include <linux/init.h> #include <asm/io.h> #include <linux/miscdevice.h> #include <linux/sched.h> #include <linux/delay.h> #include <linux/poll.h> #include <linux/spinlock.h> #include <linux/irq.h> #include <asm/arch/irqs.h> #include <asm/delay.h> #include <asm/arch/S3C2410.h> #include <asm/hardware.h> #define DEVICE_NAME "IIC" #define IIC_MAJOR 233 #define IICBUFSIZE 20 #define IICCON __REG2(0x54000000,4) #define IICSTAT __REG2(0x54000004,4) #define IICADD __REG2(0x54000008,4) #define IICDS __REG2(0x5400000c,4) #define WRDATA (1) #define POLLACK (2) #define RDDATA (3) #define SETRDADDR (4) #define BIT_IIC (0x1<<27) #define IOCTL_SLAVE_ADDR 1 static DECLARE_WAIT_QUEUE_HEAD(iic_wait); static char iic_Data[IICBUFSIZE]; static volatile int iic_DataCount; static volatile int iic_Mode; static volatile int iic_Status; static int iic_Pt; static unsigned int old_gpecon,old_gpeup; //use to save GPECON GPEUP static int slave_addr=0xA0; static void iic_port_init(void) { old_gpecon = GPECON; old_gpeup = GPEUP; printk("IIC INIT\nIICON=%x, IICSTAT=%x\n",IICCON,IICSTAT); GPEUP |= 0xc000; //Pull-up disable GPECON |= 0xa0000000; //GPE15:IICSDA , GPE14:IICSCL INTMSK &= ~(BIT_IIC); IICCON = (1<<7) | (0<<6) | (1<<5) | (0xf); IICADD = 0x10; //2410 slave address = [7:1] IICSTAT = 0x10; //IIC bus data output enable(Rx/Tx) } static void iic_irq(int irq, void *dev_id, struct pt_regs *reg) { int iicSt,i; printk("IIC IRQ\n"); SRCPND = BIT_IIC; //Clear pending bit INTPND = BIT_IIC; iicSt =IICSTAT; if(iicSt & 0x8){} //When bus arbitration is failed. if(iicSt & 0x4){} //When a slave address is matched with IICADD if(iicSt & 0x2){} //When a slave address is 0000000b if(iicSt & 0x1){} //When ACK isn't received switch(iic_Mode) { case POLLACK: iic_Status = iicSt; break; case WRDATA: if((iic_DataCount--)==0) { IICSTAT = 0xd0; //Stop MasTx condition IICCON = 0xaf; //Resumes IIC operation. udelay(1); //Wait until stop condtion is in effect. //The pending bit will not be set after issuing stop condition. break; } IICDS = iic_Data[iic_Pt++]; //iic_Data[0] has dummy. for(i=0;i<10;i++); //for setup time until rising edge of IICSCL IICCON = 0xaf; //resumes IIC operation. break; default: break; } } static int iic_write(struct file * file,const char * buffer, size_t count, loff_t *ppos) { printk("IIC WRITE\n"); iic_Mode = WRDATA; iic_Pt = 1; iic_DataCount = count-1; copy_from_user(iic_Data,buffer,count); IICDS = iic_Data[0]; IICSTAT = 0xf0; //MasTx,Start //Clearing the pending bit isn't needed because the pending bit has been cleared. printk("ready to cycle\n"); while(iic_DataCount!=-1) { printk("IICCON=%x,IICSTAT=%x\n",IICCON,IICSTAT); } iic_Mode = POLLACK; while(1) { IICDS = iic_Data[0]; iic_Status = 0x100; IICSTAT = 0xf0; //MasTx,Start IICCON = 0xaf; //Resumes IIC operation. while(iic_Status==0x100); if(!(iic_Status&0x1)) break; //When ACK is received } IICSTAT = 0xd0; //Stop MasTx condition IICCON = 0xaf; //Resumes IIC operation. udelay(1); //Wait until stop condtion is in effect. //Write is completed return 0; } static int iic_open(struct inode *inode, struct file *file) { iic_port_init(); return 0; } static struct file_operations iic_fops = { owner: THIS_MODULE, read: iic_read, write: iic_write, open: iic_open, }; static devfs_handle_t devfs_handle; static int __init iic_init(void) { int ret; ret = register_chrdev(IIC_MAJOR, DEVICE_NAME, &iic_fops); if (ret < 0) { printk(DEVICE_NAME " can't register major number\n"); return ret; } set_external_irq(IRQ_IIC, EXT_FALLING_EDGE, GPIO_PULLUP_DIS); ret = request_irq(IRQ_IIC, &iic_irq, SA_INTERRUPT, DEVICE_NAME, &iic_irq); if (ret<0) { unregister_chrdev(IIC_MAJOR, DEVICE_NAME); printk(DEVICE_NAME " can't request irq %d\n", IRQ_IIC); return ret; } printk("request IIC IRQ success\n"); devfs_handle = devfs_register(NULL, DEVICE_NAME, DEVFS_FL_DEFAULT,IIC_MAJOR, 0, S_IFCHR | S_IRUSR | S_IWUSR,&iic_fops, NULL); iic_port_init(); return 0; } static void __exit iic_exit(void) { INTMSK |= BIT_IIC; GPEUP = old_gpeup; GPECON = old_gpecon; devfs_unregister(devfs_handle); free_irq(IRQ_IIC, iic_irq); unregister_chrdev(IIC_MAJOR, DEVICE_NAME); } module_init(iic_init); module_exit(iic_exit); |
|