?? s3c44b0iic.c
字號:
#include <linux/config.h>#include <linux/module.h>#include <linux/kernel.h>#include <linux/init.h>#include <linux/miscdevice.h>#include <linux/sched.h>#include <linux/delay.h>#include <linux/poll.h>#include <linux/spinlock.h>#include <linux/delay.h>#include <asm/irq.h>#include <asm/hardware.h>#define U32 unsigned int#define U16 unsigned short#define S32 int#define S16 short int#define U8 unsigned char/* I/O PORT */#define PCONF (*(volatile unsigned *)0x1d20034)#define PDATF (*(volatile unsigned *)0x1d20038)#define PUPF (*(volatile unsigned *)0x1d2003c)#define IICCON (*(volatile unsigned *)0x1d60000)#define IICSTAT (*(volatile unsigned *)0x1d60004)#define IICADD (*(volatile unsigned *)0x1d60008)#define IICDS (*(volatile unsigned *)0x1d6000c)#ifdef CONFIG_DEVFS_FSstatic devfs_handle_t devfs_iic_dir, devfs_iicraw;#endif#define SKQ_IIC_MODULE_NAME "IICBUS"/*60--63,120--127,240--254*/#define IICBUS_MAJOR 240#define IICBUSRAW_MINOR 1#define IICBUS_INT INT_IICstatic char *IICBUD_id = "SKQ IICBUS driver v1.0 (2005-06-02)<psc@hualiangtech.com>";/* debug macros */#undef DEBUG//#define DEBUG#ifdef DEBUG#define DPRINTK( x... ) printk("SKQ IICBUS: " ##x)#else#define DPRINTK( x... )#endif#define WRDATA (1)#define POLLACK (2)#define RDDATA (3)#define SETRDADDR (4)#define IICBUFSIZE 2048char IICBUS_Buf[IICBUFSIZE];static int opencount=0;static int tsMajor = 0;static loff_t newpos=0;int WriteFM24CL16(char * buffer, size_t count,int address) { unsigned long timeo; U16 i; U16 PageAdd; char slvAddr,tempIICCON,tempIICSTAT; IICCON=(1<<7)|(0<<6)|(1<<5)|(0xf); IICSTAT=0x10; slvAddr=0xa0; PageAdd=address; /*發(fā)送起始位和設(shè)備地址和頁地址*/ PageAdd>>=7; PageAdd&=0x0e; slvAddr=(char )PageAdd; slvAddr|=0xa0; IICDS=slvAddr;//0xa0 IICSTAT=0xf0; //MasTx,Start timeo = jiffies + (HZ/100); while(1) { tempIICCON=IICCON; tempIICCON&=0x10; /*pending*/ tempIICSTAT=IICSTAT; tempIICSTAT&=0x01;/*ack*/ if((tempIICCON==0x10)) break ;//&&(tempIICSTAT==0x00) if(time_after(jiffies, timeo)) { IICSTAT=0xd0; IICCON=0xaf; udelay(200); IICCON=0xaf; IICSTAT=0x10; return -1; } }; IICCON=0xaf;/*clr pending*/ IICDS=(char )address;//0xa0 timeo = jiffies + (HZ/100); while(1){ tempIICCON=IICCON; tempIICCON&=0x10; tempIICSTAT=IICSTAT; tempIICSTAT&=0x01; if((tempIICCON==0x10)) break ;//&&(tempIICSTAT==0x00) if(time_after(jiffies, timeo)) { IICSTAT=0xd0; IICCON=0xaf; udelay(200); IICCON=0xaf; IICSTAT=0x10; return -1; } }; IICCON=0xaf; for(i=0;i<count;i++) { IICDS=buffer[i]; timeo = jiffies + (HZ/100); while(1){ tempIICCON=IICCON; tempIICCON&=0x10; tempIICSTAT=IICSTAT; tempIICSTAT&=0x01; if((tempIICCON==0x10)&&(tempIICSTAT==0x00)) break ; if(time_after(jiffies, timeo)) { IICSTAT=0xd0; IICCON=0xaf; udelay(200); IICCON=0xaf; IICSTAT=0x10; return -1; } }; IICCON=0xaf;/*clr pending*/ } IICSTAT=0xd0; IICCON=0xaf; udelay(200); IICCON=0xaf;IICSTAT=0x10; return count; }int ReadFM24CL16(char * buffer, size_t count,int address) { unsigned long timeo; U16 i; U8 slvAddr,tempIICCON,tempIICSTAT; U16 PageAdd; PageAdd=address; /*發(fā)送起始位和設(shè)備地址和頁地址*/ PageAdd>>=7; PageAdd&=0x0e; slvAddr=(char )PageAdd; slvAddr|=0xa0; IICDS=slvAddr;//0xa0 IICSTAT=0xf0; //MasTx,Start timeo = jiffies + (HZ/100); while(1){ tempIICCON=IICCON; tempIICCON&=0x10; //tempIICSTAT=rIICSTAT; //tempIICSTAT&=0x01; if((tempIICCON==0x10)) break ;//&&(tempIICSTAT==0x00) if(time_after(jiffies, timeo)) { IICSTAT=0x90; IICCON=0xaf; udelay(200); IICCON=0xaf; IICSTAT=0x10; return -1; } }; IICCON=0xaf; /*發(fā)送地址低8位*/ IICDS=(char )address; timeo = jiffies + (HZ/100); while(1){ tempIICCON=IICCON; tempIICCON&=0x10; tempIICSTAT=IICSTAT; tempIICSTAT&=0x01; if((tempIICCON==0x10)) break ;//&&(tempIICSTAT==0x00) if(time_after(jiffies, timeo)) { IICSTAT=0x90; IICCON=0xaf; udelay(200); IICCON=0xaf; IICSTAT=0x10; return -1; } }; IICCON=0xaf; //IICSTAT&=0xef; /*發(fā)送起始位和設(shè)備地址和頁地址*/ PageAdd>>=7; PageAdd&=0x0e; slvAddr=(char )PageAdd; slvAddr|=0xa1; IICDS=slvAddr; IICSTAT=0xb0;//MasRx,Start timeo = jiffies + (HZ/100); while(1){ tempIICCON=IICCON; tempIICCON&=0x10; tempIICSTAT=IICSTAT; tempIICSTAT&=0x01; if((tempIICCON==0x10)) break ;//&&(tempIICSTAT==0x00) if(time_after(jiffies, timeo)) { IICSTAT=0x90; IICCON=0xaf; udelay(200); IICCON=0xaf; IICSTAT=0x10; return -1; } }; IICCON=0xaf; for(i=0;i<count;i++) { IICDS=slvAddr; //timeo = jiffies + (HZ/100); while(1){ tempIICCON=IICCON; tempIICCON&=0x10; tempIICSTAT=IICSTAT; tempIICSTAT&=0x01; if((tempIICCON==0x10)) break ;//&&(tempIICSTAT==0x00) //else // { // if((tempIICCON==0x10)&&(i==count-1) ) break ; // } if(time_after(jiffies, timeo)) { IICSTAT=0x90; IICCON=0xaf; udelay(200); IICCON=0xaf; IICSTAT=0x10; return -1; } }; buffer[i]=IICDS; if(i==count-1) IICCON=0x2f; else IICCON=0xaf; } IICSTAT=0x90; IICCON=0xaf; udelay(200); IICCON=0xaf; IICSTAT=0x10; return count; }loff_t IICBUS_llseek(struct file *filp, loff_t off, int whence){ switch(whence) { case 0: /* SEEK_SET */ newpos = off; break; default: /* can't happen */ return -EINVAL; } if (newpos<0) return -EINVAL; return newpos;} static ssize_t IICBUS_write(struct file *file, const char *buffer, size_t count, loff_t * ppos){ int ret; int address=(int)newpos; if(count>2048) return 0; ///copy_from_user(&address, ppos, sizeof(loff_t)); //address=(int )*ppos; //printk("IICBUS_write address=%ld\n",address); if(address+count>2048) return 0; copy_from_user(IICBUS_Buf,buffer, count); ret=WriteFM24CL16(IICBUS_Buf, count,address); return ret;}static ssize_t IICBUS_read(struct file *filp, char *buffer, size_t count, loff_t *ppos){ int len; int address=(int)newpos; //int address1; if(count>2048) return 0; //copy_from_user(&address, ppos, sizeof(loff_t)); //address=(int )*ppos; //printk("IICBUS_read address=%d\n",address); if(address+count>2048) return 0; //address1=(int)*ppos; //printk("IICBUS_read address1=%ld\n",address); //printk("IICBUS_read ppos=%ld\n",ppos); len=ReadFM24CL16(IICBUS_Buf, count,address); copy_to_user(buffer,IICBUS_Buf,len); DPRINTK("read data=%d\n", data); return len;}static int IICBUS_open(struct inode *inode, struct file *file){ //if(opencount==1) // return -EBUSY; opencount++; MOD_INC_USE_COUNT; DPRINTK("device open\n"); return 0;}static int IICBUS_release(struct inode *inode, struct file *filp){ opencount--; MOD_DEC_USE_COUNT; DPRINTK("device release\n"); return 0;}static struct file_operations s3c44b0_iicbus_fops = { owner: THIS_MODULE, llseek: IICBUS_llseek, write: IICBUS_write, read: IICBUS_read, open: IICBUS_open, release:IICBUS_release,};static int __init IICBUS_init(void){ int ret; int flags; local_irq_save(flags); /* Port F */ /* Bit8 7 6 5 4 3 2 1 0 */ /* SPICLK SPIMISO SPICS SPIMOSI INCARD2 NC NC IICSDA IICSCL */ PCONF |=0x0a; //PF0:IICSCL, PF1:IICSDA PUPF |=0x03; //pull-up disable IICCON=(1<<7)|(0<<6)|(0<<5)|(0xf); //Enable interrupt, IICCLK=MCLK/16, Enable ACK //40Mhz/16/(15+1) = 257Khz IICADD=0x10; // S3C44B0X slave address IICSTAT=0x10; local_irq_restore(flags); opencount=0; ret = register_chrdev(IICBUS_MAJOR, SKQ_IIC_MODULE_NAME, &s3c44b0_iicbus_fops); if (ret < 0) { printk(__FUNCTION__ ": can't get major number\n"); return -1; } tsMajor = ret;#if 0 if ( 0 != request_irq(IICBUS_INT, IICBUS_isr ,SA_INTERRUPT,IICBUD_id, NULL)) { printk(KERN_WARNING "tce44b0_usb: failed to get IRQ\n"); return 1; }#endif #ifdef CONFIG_DEVFS_FS devfs_iic_dir = devfs_mk_dir(NULL, SKQ_IIC_MODULE_NAME, NULL); devfs_iicraw = devfs_register(devfs_iic_dir, "0", DEVFS_FL_DEFAULT, tsMajor, IICBUSRAW_MINOR, S_IFCHR | S_IRUSR | S_IWUSR, &s3c44b0_iicbus_fops , NULL);#endif printk(SKQ_IIC_MODULE_NAME " initialized\n"); return 0;}static void __exit IICBUS_exit(void){ printk(__FUNCTION__ ": SKQ IIC Exit.\n"); free_irq(IICBUS_INT,IICBUD_id); devfs_unregister_chrdev(IICBUS_MAJOR, SKQ_IIC_MODULE_NAME );}module_init(IICBUS_init);module_exit(IICBUS_exit);MODULE_DESCRIPTION("SKQ IIC driver");MODULE_AUTHOR("pengshicao <psc@hualiangtech.com>");MODULE_LICENSE("GPL");
?? 快捷鍵說明
復(fù)制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -