⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 s3c44b0iic.c

📁 S3C44B0 I2C的uCLINUX的驱动程序(铁电存储器FM24系列
💻 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;	/*发送起始位和设备地址和页地址*/	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;	/*发送起始位和设备地址和页地址*/	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;  /*发送地址低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;   /*发送起始位和设备地址和页地址*/  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");                                                                                                                                                                                 

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -