📄 apb_i2c_module.c
字号:
/********************************************//* I2CFunc.c: implementation of the I2C API.*//* Author : DQ *//* Time : 2005-12-15 *//********************************************/#include <linux/major.h>#include <linux/vmalloc.h>#include <linux/init.h>#include <linux/interrupt.h>#include <linux/module.h>#include <linux/blkdev.h>#include <linux/bitops.h>#include <linux/delay.h>#include <asm/uaccess.h>#include <asm/io.h>#include <asm/arch-x900/apb_i2c_module.h>#include <asm/arch-x900/apb_i2c_tvin.h>#ifdef CONFIG_ARCH_X900 #define PHY_SYS_BASE 0x20031000 #define PHY_I2C_BASE 0x20026000#else #define PHY_SYS_BASE 0x20020000 #define PHY_I2C_BASE 0x20036000#endif#define SZ_4K 0x1000unsigned int *g_i2c_base = 0;unsigned int *g_sysctrl_base = 0;/* This struct aims at translate parameters.** Para : addr , the slave's address** Para : control, the control register's value** Para : mask, the mask for interrupt** Para : rx , the recive FIFO's depth** Para : tx , the transmit FIFO's depth **/typedef struct { unsigned short addr; unsigned short control; unsigned short mask; unsigned short rx; unsigned short tx;}i2cConfig;/* This struct describe the SCL Paramter ** mode : this is the I2C translate mode , such as SS = SlowSpeed, FS = Full Speed , HS = High Speed** hcnt : this is the High period for the SCL** lcnt : this is the Low period for the SCL**/typedef struct { I2CMODE mode; unsigned short hcnt; unsigned short lcnt;}i2cSpeedMode;void i2cSetConfig(i2cConfig* Init_data, i2cSpeedMode* m ){ I2C_DISABLE; if(Init_data) { I2C_SAR(Init_data->addr);//Set the address of the i2c device I2C_CON(Init_data->control);//Set the control register for the transfer I2C_INTR_MASK(Init_data->mask);//Enable interrupts I2C_RX_TL(Init_data->rx);//Set Rx FIFO Threshold I2C_TX_TL(Init_data->tx);//Set Tx FIFO Threshold } if(m) { switch(m->mode) { case I2C_SS: I2C_SS_HCNT(m->hcnt); I2C_SS_LCNT(m->lcnt); break; case I2C_FS: I2C_FS_HCNT(m->hcnt); I2C_FS_LCNT(m->lcnt); break; case I2C_HS: I2C_HS_HCNT(m->hcnt); I2C_HS_LCNT(m->lcnt); break; default: { I2C_ERROR("There is no such I2C mode."); break; } } } I2C_ENABLE;//Enable the I2C MASTER}void i2cSetTarget( char target_addr){ //Disable the I2C MASTER, all the config should be set when the i2c master is disabled if (target_addr) { I2C_DISABLE; I2C_TAR(target_addr/2);//Set the address for the target slave I2C_ENABLE;//Enable the I2C MASTER }}/* brief : Initialize the I2C module */i2cInst* init_i2c(){ int error = 0; i2cInst* t = 0; i2cConfig* g_initData = 0; i2cSpeedMode* spemode = 0; // Define the Initialize parameters t = (i2cInst*)vmalloc( sizeof(i2cInst)); if( t ) { t->config = (void*)vmalloc( sizeof(i2cConfig) ); t->speed = (void*)vmalloc( sizeof(i2cSpeedMode) ); } else error = 1; g_initData = (i2cConfig*)t->config; spemode = (i2cSpeedMode*)t->speed; g_initData->addr = 0x0045;//slave address g_initData->control = 0x0023;//change from 0x0003 /* Ruskee: Why change from 0x03?*/ g_initData->mask = 0x0000; g_initData->rx = 0x0008; /*Ruskee: Why change from 0x0*/ g_initData->tx = 0x0000; spemode->mode = I2C_SS; spemode->hcnt = 0x0028;//0x88; spemode->lcnt = 0x002f;//0x8f; g_i2c_base = (u32 *)(ioremap(PHY_I2C_BASE, SZ_4K)); i2cSetConfig(g_initData,spemode); return t;}/* brief : Delete the I2C module from the system */void dele_i2c(i2cInst* t){ if(t) { if(t->config) vfree(t->config); if(t->speed) vfree(t->speed); vfree(t); } iounmap(g_i2c_base);}// wait for Receive FIFO Not Emptyint waitRFNE(unsigned int timeout){ timeout = timeout*10000; while(!(I2C_STATUS & RFNE)&&timeout) { timeout --; } if( timeout > 0 ) return 0; else return -1;}// Transmit FIFO Not Fullbool isTFNF(void){ if (I2C_STATUS & TFNF) return true; else return false;}// wait for Transmit FIFO Completely Emptyint waitTFE(unsigned int timeout){ timeout = timeout*10000; while(!(I2C_STATUS & TFE)&&timeout) { timeout --; } if( timeout > 0 ) return 0; else return -1;}/* brief: This API is used to transmit data ** para : threhold -- the threhold of the FIFO** para : buffer -- the pointer of data** para : target -- the address of the target*/ int transmitData(const int threhold, const unsigned char buffer[], const unsigned short target){ int error = 0 ,i; if(!g_i2c_base) return -1; if(threhold < 0 || threhold >255){ error = 1; return error; } I2C_DISABLE; I2C_TX_TL((threhold-1)); I2C_TAR(target); I2C_ENABLE; error = waitTFE(100); i=0; while(i < threhold) { while (!isTFNF()); I2C_WRITE (buffer[i++]); { int k = 4; while( k -- ); } } error = waitTFE(100); udelay(100); //hw_delay(1); return error;}int ReadData(const int threhold, const unsigned char buffer[], const unsigned short target , unsigned char buffer2[]){ int i, error = 0,tx_num = threhold; if(!g_i2c_base) { return -1; } I2C_DISABLE; I2C_TX_TL((1)); I2C_TAR(target); I2C_CON(I2CR_CON | 0x20); I2C_ENABLE; error = waitTFE(100); i=0; while(i < threhold) { I2C_WRITE (buffer[i++]); { int k = 4; while( k -- ); } } i = 0; while( i < threhold && !error) { while(((I2C_STATUS)&(TFNF))&&tx_num) { I2C_WRITE(0x100); tx_num--; } error = waitRFNE(100); buffer2[ i ] = I2C_READ; i++; } return error;}int i2cWrite( i2cInst* inst , const unsigned short target , const unsigned char* address , int acount , unsigned char* value , int vcount ){ int error = 0 ,i = 0; if(target != inst->target) { inst->target = target; i2cSetTarget(target); } error = waitTFE(100); while( i < acount && !error) { I2C_WRITE (address[i++]); { int k = 4; while( k -- ); } } i = 0; while( i < vcount && !error) { I2C_WRITE (value[i++]); { int k = 4;//33000/4; while( k -- ); } } error = waitTFE(100); return error;}int i2cRead( i2cInst* inst , const unsigned short target , const unsigned char* address , int acount , unsigned char* value , int vcount ){ int error = 0 ,i = 0, tx_num = vcount; if (!g_i2c_base) return -1; if(target != inst->target) { inst->target = target; i2cSetTarget(target); } I2C_CON(I2CR_CON | 0x20); /* Ruskee: Is it necessary to have this?*/ error = waitTFE(100); while( i < acount && !error) { I2C_WRITE (address[i++]); { int k = 4; while( k -- ); } } i = 0; error = waitTFE(1000); while( i < vcount && !error) { while(((I2C_STATUS)&(TFNF))&&tx_num) { I2C_WRITE(0x100); tx_num--; } error = waitRFNE(100); value[ i ] = I2C_READ; i++; } return error;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -