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

📄 i2c-algo-gm.c

📁 基于GM8180,NSF2200F的I2C驱动,LINUX平台
💻 C
📖 第 1 页 / 共 2 页
字号:
/*   -------------------------------------------------------------------------   i2c-algo-GM.c i2c driver algorithms for GM adapters	    	learned from the original source - i2c-algo-ite.c   Copyright 2006 GM Inc.   ---------------------------------------------------------------------------   This file was highly leveraged from i2c-algo-pcf.c, which was created   by Simon G. Vogl and Hans Berglund:     Copyright (C) 1995-1997 Simon G. Vogl                   1998-2000 Hans Berglund    This program is free software; you can redistribute it and/or modify    it under the terms of the GNU General Public License as published by    the Free Software Foundation; either version 2 of the License, or    (at your option) any later version.    This program is distributed in the hope that it will be useful,    but WITHOUT ANY WARRANTY; without even the implied warranty of    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the    GNU General Public License for more details.    You should have received a copy of the GNU General Public License    along with this program; if not, write to the Free Software    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.		     *//* ------------------------------------------------------------------------- *//* With some changes from Ky?sti M?lkki <kmalkki@cc.hut.fi> and    Frodo Looijaard <frodol@dds.nl> ,and also from Martin Bailey   <mbailey@littlefeet-inc.com> */#include <linux/kernel.h>#include <linux/module.h>#include <linux/delay.h>#include <linux/slab.h>#include <linux/init.h>#include <asm/uaccess.h>#include <linux/ioport.h>#include <linux/errno.h>#include <linux/sched.h>#include <linux/i2c.h>#include "i2c-algo-GM.h"/* ----- global defines ----------------------------------------------- */#define DEB2(x) if (i2c_debug>=2) x#define DEB3(x) if (i2c_debug>=3) x /* print several statistical values*/#define DEF_TIMEOUT 16/* module parameters: */static int i2c_debug=1;static int iic_test=1;#define I2C_Status                  0x4/* I2C Status Register */#define I2C_CLRAL                   0x400#define I2C_CLRGC                   0x200#define I2C_CLRSAM                  0x100#define I2C_CLRSTOP                 0x80#define I2C_CLRBERR                 0x40#define I2C_DR                      0x20#define I2C_DT                      0x10#define I2C_BB                      0x8#define I2C_BUSY                    0x4#define I2C_NACK                    0x2#define I2C_RW                      0x1/* exclusive access to the bus *///#define I2C_LOCK(adap) down(&adap->lock)//#define I2C_UNLOCK(adap) up(&adap->lock)//#define ADAP_LOCK()     down(&adap_lock)//#define ADAP_UNLOCK()   up(&adap_lock)//#define DRV_LOCK()      down(&driver_lock)//#define DRV_UNLOCK()    up(&driver_lock)#define I2C_LOCK(adap) #define I2C_UNLOCK(adap) #define ADAP_LOCK()     #define ADAP_UNLOCK()   #define DRV_LOCK()      #define DRV_UNLOCK()    //#define DEB(x) if (i2c_debug>=1) x;//#define DEB2(x) if (i2c_debug>=2) x;//#define DEBUG 1/* --- setting states on the bus with the right timing: ---------------	*/#define get_clock(adap) adap->getclock(adap->data)#define iic_outw(adap, reg, val) adap->setiic(adap->data, reg, val)#define iic_inw(adap, reg) adap->getiic(adap->data, reg)//Add By Ken.Hsieh//static wid =EEPROM_ID_WRITE ; 	//replace with adapter->id//static rid =EEPROM_ID_READ ; 		//replave with adapter->id+1#define I2C_ALGO_GM_VERSION	"0.2"/* --- other auxiliary functions --------------------------------------	*/void I2C_WriteData(unsigned char dat){    *(volatile unsigned int *)(I2C_ADDR+0xc)=dat;//	printk("i2c wd : %02x\n", dat);}unsigned char I2C_ReadData(void){	unsigned char ret;	ret = *(volatile unsigned int *)(I2C_ADDR+0xc);//	printk("i2c rd : %02x\n", ret);	return ret;//	return *(volatile unsigned int *)(I2C_ADDR+0xc);}void I2C_IOCtrl(unsigned int dat){    *(volatile unsigned int *)(I2C_ADDR)=dat;//	printk("i2c wc : %02x\n", dat);}unsigned int I2C_ReadStatus(void){	unsigned int ret;    ret = *(volatile unsigned int *)(I2C_ADDR+0x4);	//printk("i2c rc : %08x\n", ret);	return ret;//	return *(volatile unsigned int *)(I2C_ADDR+0x4);}int i2c_WaitEndOfStatus_ken(unsigned long status_type, unsigned int time_out){        unsigned long status;	for (; time_out>0; --time_out)        {               //status = inw(CPE_I2C_VA_BASE + I2C_Status);		status=I2C_ReadStatus();               if (( status & status_type ) == 0)               {                    break;               }               set_current_state(TASK_INTERRUPTIBLE);               schedule_timeout (1);        }        return (time_out>0);}/*int WaitDT() {        if (i2c_WaitEndOfStatus_ken(I2C_BB, 1000) == 0){	        printk ("I2C bus busy, pls reset I2C device!\n");                return 0;        };	return 1;}*/int WaitDR(void){    volatile unsigned int status=0,count=0;;    while(1)    {            if(status&0x20) {		//printk("<0>DR is set!\n");		    return 1;	}	//mdelay(10);	status=I2C_ReadStatus();	count++;	if(count>0x10000) {		mdelay(4);	//note by Ken.Hsieh: eeprom must use this so that eeprom will write successfully; if mdelay(3) will fail on writing due to the less the value		//mdelay(10);	//note by Ken.Hsieh: eeprom must use this so that eeprom will write successfully; if mdelay(3) will fail on writing due to the less the value	}	if(count>0x10002)	//if(count>0x200000)	    return 0;     }	return 1;}	int WaitDT(void){    volatile unsigned int status=0,count=0;;	            while(1)    {     	//Add By Ken.Hsieh to check ACK in I2C Status Register	/*if (status&0x02) {		printk("ACK is set..and set I2C_STOP\n");		I2C_IOCtrl(I2C_STOP);		return 0;	}	  */  	if(status&0x10) {	        //printk("<0>DT is set!\n");			if (status&0x02) { 	//Non-ACK happens		        //printk("ACK is set and set I2C_STOP\n");			I2C_IOCtrl(I2C_STOP);			return 0;		}			return 1;	}        if(status&0x20) {		//rintk("<0>DR is set!\n");		    return 1;	}	//mdelay(10);	status=I2C_ReadStatus();	count++;	if(count>0x10000) {		mdelay(4);	//note by Ken.Hsieh: eeprom must use this so that eeprom will write successfully; if mdelay(3) will fail on writing due to the less the value		//mdelay(10);	//note by Ken.Hsieh: eeprom must use this so that eeprom will write successfully; if mdelay(3) will fail on writing due to the less the value	}	if(count>0x10002)	//if(count>0x200000)	    return 0;     }	return 1;}	static void iic_start(struct i2c_algo_iic_data *adap){	//iic_outw(adap,ITE_I2CHCR,ITE_CMD);}static void iic_stop(struct i2c_algo_iic_data *adap){//	iic_outw(adap,ITE_I2CHCR,0);//	iic_outw(adap,ITE_I2CHSR,ITE_I2CHSR_TDI);}static void iic_reset(struct i2c_algo_iic_data *adap){//	iic_outw(adap, PM_IBSR, iic_inw(adap, PM_IBSR) | 0x80);}static int wait_for_bb(struct i2c_algo_iic_data *adap){	//return(timeout<=0);}/* * Puts this process to sleep for a period equal to timeout  */static inline void iic_sleep(unsigned long timeout){	schedule_timeout( timeout * HZ);}/* After we issue a transaction on the IIC bus, this function * is called.  It puts this process to sleep until we get an interrupt from * from the controller telling us that the transaction we requested in complete. */static int wait_for_pin(struct i2c_algo_iic_data *adap, short *status) {}/* * Sanity check for the adapter hardware - check the reaction of * the bus lines only if it seems to be idle. */static int test_bus(struct i2c_algo_iic_data *adap, char *name) {	return (0);}/* ----- Utility functions *//* Verify the device we want to talk to on the IIC bus really exists. */#if 0static inline int try_address(struct i2c_algo_iic_data *adap,		       unsigned int addr, int retries){	//return ret;}#endif//static int iic_sendbytes(struct i2c_adapter *i2c_adap,const char *buf,int i2c_sendbytes(struct i2c_adapter *i2c_adap,unsigned char *buf, int count){    int i;    char *p_temp ;    struct GMi2c_info *fara_info;    fara_info=i2c_adap;        //struct i2c_algo_iic_data *adap = i2c_adap->algo_data;    //write slave address to device    if (count<1) {	printk("i2c-algo-GM.o:i2c_sendbytes count:%d can't less than 1!\n",count);	return 0;    }    p_temp = buf;     I2C_WriteData(fara_info->flags);	// specify the I2C device address    I2C_IOCtrl(I2C_ENABLE|I2C_TBEN|I2C_START); //0x3f96    if(WaitDT()==0)            return 0;    if (count == 1 ) {	    I2C_WriteData(fara_info->data);	// specify I2C offset    	    I2C_IOCtrl(I2C_ENABLE|I2C_TBEN);//0x3f86	    if(WaitDT()==0) {		printk("i2c-algo-GM.o:device 0x%x i2c_sendbytes offset(0x%x) error 11111!\n",fara_info->flags,fara_info->data);        	return 0;    	    }    }    //write data to device    for (i=0 ; i<count-1 ; i++) {    	I2C_WriteData(*p_temp);    	I2C_IOCtrl(I2C_ENABLE|I2C_TBEN);//0x3f86	if(WaitDT()==0) {		printk("i2c-algo-GM.o:device 0x%x i2c_sendbytes data error 22222!\n",fara_info->flags);        	return 0;    	}	p_temp++;	fara_info->data ++ ;    }        I2C_WriteData(*p_temp);    I2C_IOCtrl(I2C_ENABLE|I2C_TBEN|I2C_STOP); //0x3fa6    if(WaitDT()==0) {	printk("i2c-algo-GM.o:device 0x%x i2c_sendbytes data error 33333!\n",fara_info->flags);        return 0;    }    //for OV7640 reset,it must delay more than 1 ms    /*    if ((fara_info->flags == 0x42) && (fara_info->data==0x12) && (*buf ==0x80)) {    	//printk("<0>i2c-algo-GM.o:mdelay(2) for OV7640..\n");    	printk("<0>i2c-algo-GM.o:udelay(1000) for OV7640 reset all register\n");	//mdelay(2);	udelay(1000);    }    */    return 1;}EXPORT_SYMBOL_GPL(i2c_sendbytes);/* GM I2C bus interface for device drvier by Ken.Hsieh,instead of ii2_readbytes on 2006.6.1*///static int i2c_readbytes(struct i2c_adapter *i2c_adap, char *buf, int count,int i2c_readbytes(struct i2c_adapter *i2c_adap, char *buf, int count, int sread) {    	struct GMi2c_info *fara_info;	int i;	char *p_buf ;		    	fara_info=i2c_adap;	p_buf = buf;    		sread = 0 ;	//write address to device	if ( (count == 1) || (count>1 && fara_info->adap.retries ==0) ) {	    //write slave address to device	    //I2C_WriteData(wid);	    //printk("88888888888888888888888888888888888\n");	    for (i=0 ; i<count ; i++) {		//I2C_WriteData(fara_info->flags-1);		I2C_WriteData(fara_info->flags|1);		I2C_IOCtrl(I2C_ENABLE|I2C_TBEN|I2C_START);		if (WaitDT() ==0) {#ifdef DEBUG			    printk("i2c-algo-GM.o:device 0x%x i2c_readbytes data error 00000!\n",fara_info->flags);#endif				    I2C_IOCtrl(I2C_ENABLE|I2C_TBEN|I2C_START);		    if (WaitDT() ==0) {			printk("i2c-algo-GM.o:device 0x%x i2c_readbytes data error 111111!\n",fara_info->flags);			sread = -1 ; 		       	return -1;		    }		}				//write address to device		I2C_WriteData(fara_info->data);	// ?		if (fara_info->flags == 0x43) {		    I2C_IOCtrl(I2C_ENABLE|I2C_TBEN|I2C_STOP);	//Try for OV7660		}		else {		    I2C_IOCtrl(I2C_ENABLE|I2C_TBEN);		}		if (WaitDT() ==0) {		    printk("i2c-algo-GM.o:device 0x%x i2c_readbytes data error 22222!\n",fara_info->flags);		    		    sread = -1 ; 		    return -1;		}		//read data		//I2C_WriteData(rid);		I2C_WriteData(fara_info->flags);		I2C_IOCtrl(I2C_ENABLE|I2C_TBEN|I2C_START); //0x3f96		if(WaitDT()==0) {		    printk("i2c-algo-GM.o:device 0x%x i2c_readbytes data error 333333!\n",fara_info->flags);		    sread = -1 ; 		    return -1;		}		I2C_IOCtrl(I2C_ENABLE|I2C_TBEN|I2C_STOP|I2C_ACKNAK);		if(WaitDT()==0) {		    printk("i2c-algo-GM.o:device 0x%x i2c_readbytes data error 4444444!\n",fara_info->flags);		    sread = -1 ; 		    return -1;		}		*p_buf = *((char *)(I2C_ADDR+0xc));#ifdef DEBUG			printk("Read address 0x%02x with 0x%02x\n",fara_info->data,*p_buf);#endif        		if (count ==1 || i==count-1) break;		p_buf++;		fara_info->data++;	    }	}	else {	    if (fara_info->adap.retries ==1 ) {		//write slave address to device		//I2C_WriteData(wid);		I2C_WriteData(fara_info->flags | 0x1);		I2C_IOCtrl(I2C_ENABLE|I2C_TBEN|I2C_START);		//printk("777777777777777777777777777777777777\n");		//while(1);		if (WaitDT() ==0) {		    printk("i2c-algo-GM.o:device 0x%x i2c_readbytes data error 111111!\n",fara_info->flags);		    sread = -1 ;		    		    return -1;		}			//printk("222\n");		I2C_IOCtrl(I2C_ENABLE|I2C_TBEN);		if(WaitDR()==0) {		    printk("i2c-algo-GM.o:device 0x%x i2c_readbytes data error multi-read once 1111!\n",fara_info->flags);		    sread = -1 ; 		    return -1;		}					*p_buf = *((char *)(I2C_ADDR+0xc));		//printk("byte 1 = %x\n",*p_buf);		p_buf++;		I2C_IOCtrl(I2C_ENABLE|I2C_TBEN);		if(WaitDR()==0) {		    printk("i2c-algo-GM.o:device 0x%x i2c_readbytes data error multi-read once 1111!\n",fara_info->flags);		    sread = -1 ; 		    return -1;		}								for (i=2 ; i<count-1 ; i++) {		    *p_buf = *((char *)(I2C_ADDR+0xc));		    //printk("byte %d = %x\n",i,*p_buf);		    p_buf++;		    I2C_IOCtrl(I2C_ENABLE|I2C_TBEN);			    if(WaitDR()==0) {			printk("i2c-algo-GM.o:device 0x%x i2c_readbytes data error multi-read once 222!\n",fara_info->flags);			sread = -1 ; 			return -1;		    }		}		*p_buf = *((char *)(I2C_ADDR+0xc));		//printk("byte 4 = %x\n",*p_buf);		p_buf++;		I2C_IOCtrl(I2C_ENABLE|I2C_TBEN|I2C_STOP|I2C_ACKNAK);		if(WaitDR()==0) {		    printk("i2c-algo-GM.o:device 0x%x i2c_readbytes data error multi-read once 1111!\n",fara_info->flags);		    sread = -1 ; 		    return -1;		}					*p_buf = *((char *)(I2C_ADDR+0xc));		//printk("byte 5 = %x\n",*p_buf);						    }	}        //printk("Read address 0x%02x with 0x%02x\n",fara_info->data,*buf);	//count =1 ;	return count;}EXPORT_SYMBOL_GPL(i2c_readbytes);/* Description: Prepares the controller for a transaction (clearing status * registers, data buffers, etc), and then calls either iic_readbytes or * iic_sendbytes to do the actual transaction. * * still to be done: Before we issue a transaction, we should * verify that the bus is not busy or in some unknown state. *///static int iic_xfer(struct i2c_adapter *i2c_adap,#ifdef CONFIG_PLATFORM_GM8120int iic_xfer(struct i2c_adapter *i2c_adap,		    struct i2c_msg msgs[], 		    int num){	struct i2c_algo_iic_data *adap = i2c_adap->algo_data;	struct i2c_msg *pmsg;	int ret, timeout;	char *p;	int i=0;    	struct GMi2c_info *fara_info;    	fara_info=i2c_adap;    	#ifdef DEBUG    		printk("iic_xfer start\n"); #endif		pmsg = &msgs[i];	pmsg->len = num;	p=pmsg->buf;	if (fara_info->client_count >=0 ) {		ret = GM_fLib_I2C_SetClockdiv(fara_info->client_count);		if (ret !=0 ) {			printk("i2c-algo-GM.o:Error in GM_fLib_I2C_SetClockdiv\n");			return ret;		}	}		if(fara_info->flags & I2C_M_RD) {		/* Read */#ifdef DEBUG			printk("addr = 0x%x,waddr = 0x%x,client_count = 0x%x,buf = 0x%x\n",fara_info->flags,fara_info->data,fara_info->client_count,pmsg->buf);#endif				ret = i2c_readbytes(i2c_adap, pmsg->buf, pmsg->len, 0);	}	else {		/* Write */ 		ret = i2c_sendbytes(i2c_adap, pmsg->buf, pmsg->len);	}	if (ret != pmsg->len)		DEB3(printk("iic_xfer: error or fail on read/write %d bytes.\n",ret)); 	else		DEB3(printk("iic_xfer: read/write %d bytes.\n",ret));	return ret;}EXPORT_SYMBOL_GPL(iic_xfer);#elseint iic_xfer(struct i2c_adapter *i2c_adap,		    struct i2c_msg msgs[], 		    int num){	int ret;   	struct GMi2c_info *fara_info;    	fara_info=i2c_adap;    	#ifdef DEBUG    		printk("iic_xfer start\n"); #endif		msgs->addr=fara_info->flags;	msgs->flags=fara_info->data;

⌨️ 快捷键说明

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