看了很多书上写的44b0的IIC的驱动都是很难理解的那种,都是照抄三星的程序的,于是就自己改写了IIC的驱动,我认为这样有助于理解执行的过程,很简单易懂. /* *iic.c: * read and write only one byte for AT24C04 */ #i nclude <asm/hardware.h> #i nclude <linux/module.h> #i nclude <linux/fs.h> #i nclude <linux/types.h> #i nclude <linux/malloc.h> #i nclude <asm/uaccess.h> #i nclude <asm/page.h> #i nclude <linux/errno.h> #i nclude <linux/config.h> #i nclude "IIC.h" void vdelay(unsigned short i); static DECLARE_WAIT_QUEUE_HEAD(wait); unsigned char WrData= 0 ; unsigned char RecvData[2] = {0,0}; volatile static unsigned char ack_tag; volatile static unsigned int addr; static int IIC_read(struct file *filp,char *buf,size_t count,loff_t *f_pos) //count读取的数量; { //printk("read addr %d /n",addr); /****************** 读** 写入设备地址 **********************/ ack_tag = 0; CSR_WRITE(rIICDS,0xa0); //设备地址 CSR_WRITE(rIICSTAT,0xf0); //MasTx,start,En Tx/Rx, wait_event_interruptible(wait, (ack_tag != 0)); //wait the trans complete ack_tag = 0; /***************** 读**写入读取的低地址 ************/ CSR_WRITE(rIICDS,(char)addr); //the read address CSR_WRITE(rIICCON,0xaf); //resume iic operation wait_event_interruptible(wait, (ack_tag != 0)); //wait the trans complete ack_tag = 0; /****************** 读**再次写入设备地址 **********************/ CSR_WRITE(rIICDS,0xa0); //设备地址 CSR_WRITE(rIICSTAT,0xb0); //MasRx,start,En Tx/Rx, CSR_WRITE(rIICCON,0xaf); //resume iic operation wait_event_interruptible(wait, (ack_tag != 0)); //wait the trans complete ack_tag = 0; /***************** read the data ************************************/ RecvData[1]=CSR_READ(rIICDS); //这次读到的没有用 CSR_WRITE(rIICCON,0x2f); //只读一位 wait_event_interruptible(wait, (ack_tag != 0)); //wait the trans complete ack_tag = 0; RecvData[0]=CSR_READ(rIICDS); printk("read data %d /n",RecvData[0]); /***************** stop trans ***************************************/ CSR_WRITE(rIICSTAT,0x90); //MasRx,stop,En Tx/Rx, CSR_WRITE(rIICCON,0xaf); //resume iic operation vdelay(100); copy_to_user(buf, &RecvData, sizeof(char)); return (1); } static int IIC_write(struct file *filp,char *buf,size_t count,loff_t *f_pos) { //unsigned int i; if(copy_from_user(&WrData, buf, sizeof(char))) { printk("error writing, copy_from_user/n"); return -EFAULT; } printk("write address %d /n",addr); printk("write data %d /n",WrData); /****************** 写** 写入设备地址 **********************/ ack_tag = 0; CSR_WRITE(rIICDS,0xa0); CSR_WRITE(rIICSTAT,0xf0); //MasTx,start,En Tx/Rx, wait_event_interruptible(wait, (ack_tag != 0)); //wait the trans complete ack_tag = 0; /***************** 写** 写入存储器的内部地址低位 ************/ CSR_WRITE(rIICDS,(char)addr); //the write high address CSR_WRITE(rIICCON,0xaf); //resume iic operation wait_event_interruptible(wait, (ack_tag != 0)); //wait the trans complete ack_tag = 0; /***************** write the data ************************************/ CSR_WRITE(rIICDS,WrData); //the write high address CSR_WRITE(rIICCON,0xaf); //resume iic operation wait_event_interruptible(wait, (ack_tag != 0)); //wait the trans complete ack_tag = 0; /***************** stop trans ***************************************/ CSR_WRITE(rIICSTAT,0xd0); //MasTx,stop,En Tx/Rx, CSR_WRITE(rIICCON,0xaf); //resume iic operation vdelay(100); return (1); } static int IIC_ioctl(struct inode *inode,struct file *filp,unsigned int cmd,unsigned long arg) { addr = arg; return 1; } static int IIC_open(struct inode *inode,struct file *filp) { MOD_INC_USE_COUNT; printk("<>someone open iic!/n"); return 0; } static int IIC_release(struct inode *inode,struct file *filp) { MOD_DEC_USE_COUNT; printk("<>someone close iic/n"); return 0; } static int IIC_select(struct file *file,struct poll_table_struct *wait) { return 0; } void IIC_handle(int irq,void *dev_id,struct pt_regs *regs) { //char rec; //rec = CSR_READ(rIICDS); //printk(" /n %d / n",rec); CSR_WRITE(rI_ISPC,(CSR_READ(rI_ISPC)|BIT_IIC)); // Clear IIC Pending Bit ack_tag = 1; wake_up_interruptible(&wait); } void IIC_init(void) { int ret; CSR_WRITE(rPCONF,((CSR_READ(rPCONF)&0xfffffff0)|0xa)); //PF0:IICSCL,PF1:IICSDA CSR_WRITE(rPUPF,(CSR_READ(rPUPF)|0x3));//禁止内部上拉 CSR_WRITE(rIICCON,0xaf);//(1<<7)|(0<<6)|(1<<5)|(0xf)); //Enable interrupt, IICCLK=MCLK/16, Enable ACK //40Mhz/16/(15+1) = 257Khz CSR_WRITE(rIICADD,0x10); // S3C44B0X slave address CSR_WRITE(rIICSTAT,0x10); CSR_WRITE(rI_ISPC,(CSR_READ(rI_ISPC)|BIT_IIC)); // Clear EINT's Pending Bit CSR_WRITE(rINTMSK,(CSR_READ(rINTMSK)&(~BIT_IIC))); // Enable interrupt ret = register_chrdev(IIC_MAJOR,"iic",&IIC_fops); if(ret<0) { printk("fail to register/n"); } CLEAR_PEND_INT(IIC_IRQ); if(IIC_IRQ >=0){ ret = request_irq(IIC_IRQ,IIC_handle,SA_INTERRUPT,"IICS",NULL); if(ret){ printk("IIC:cant get assigned irq %i/n",IIC_IRQ); } else{ printk("IIC:request external interrupt %i/n",IIC_IRQ); INT_ENABLE(IIC_IRQ); } } } void vdelay(unsigned short i) { ushort cm=0; while(cm<i) { cm++; } }
|