📄 emi2c.c
字号:
/* * emi2c.c * * $Log: emi2c.c,v $ * Revision 1.2 2006/01/22 00:32:25 bertrand * Ported contents of set_tron from dcc_2_branch to HEAD * * Revision 1.1.1.1.2.4 2006/01/04 19:50:05 tvh * Enable Tunerapps compilation for SMP8634 * * Revision 1.1.1.1.2.3 2005/06/23 11:23:14 michon * fixbuild * * Revision 1.1.1.1.2.1 2005/03/15 06:23:54 bertrand * Added missing standard header * * Revision 1.1.1.1 2005/03/10 00:06:00 bertrand * Initial import of the DTV specific code into the ndc repository * * Revision 1.2 2004/11/30 05:49:17 jpong * tunerapi addition : added property for low and high frequency of the tuner * tunerapp : shows exapmple of this addition * all: debug logging types fixed in DPRINT, _DEBUG = DEBUG * tuv1236d message fix * * Revision 1.1.1.1 2004/11/10 03:02:41 jpong * i2c devices * * Revision 1.8 2004/07/24 00:09:04 jpong * emi2c_read_subaddress and I2CRead now nacks last byte by default. i2c spec. * new flag EMI2C_RD_SUB_NONACKLASTBYTE added. * * Revision 1.7 2004/06/07 23:05:59 jpong * emi2c - bytecount on emi2c_read_subaddress was being updated incorrectly * README has new commandline parameters * * Revision 1.6 2004/05/13 00:36:21 jpong * added RM i2c_hal like API, can be used to replace i2c_hal.o * * Revision 1.5 2004/04/22 01:10:45 jpong * SR flag fix, more rmtypes.. * * Revision 1.4 2004/04/12 19:04:48 jpong * uses RMtypes.. * * Revision 1.3 2004/03/18 23:26:24 jpong * EMI2C_FLAG_NOSR removed, all calls are now NOSR * * Revision 1.2 2004/03/11 06:07:20 jpong * high level functions emi2c_read/write_subaddress, emi2c_send_table added * no stop on start added with EMI2C_FLAG_NOSR * * Revision 1.1.1.1 2004/03/03 03:28:26 jpong * board test * * *//* standard includes *///#include <sys/io.h>#include <stdio.h>#include <string.h>//#include "../include/em_types.h"//#include "../include/dmesg.h"/* mum includes */#define ALLOW_OS_CODE 1#include "rmdef/rmdef.h"#include "llad/include/gbus.h"#include "emhwlib_hal/include/emhwlib_registers.h"//#define GPIO_DIR_ADDR (REG_BASE_system_block + SYS_gpio_dir)//#define GPIO_DATA_ADDR (REG_BASE_system_block + SYS_gpio_data)#include "emhwlib_hal/i2c/include/i2c_hal.h"#include "../helper/helper.h"#include "emi2c.h"/* local defines */#define SCLHI_TIMEOUT 25/* em860x GPIO definition */#define OUT 1#define IN 0/*--------------Utility Functions -----------------*/static RMvoid em_udelay(EMI2C_CONFIG *pC, RMuint32 us){ RMuint32 t0, t1, d; RMuint32 TotalDelay = us + pC->AdditionalDelay; assert(pC); assert(pC->RegBase == REG_BASE_system_block); // implementation safe for delays smaller than 0xFFFFFFFF/27us = 159 sec // if SYS_xtal_in_cnt doesn't work - hang here !! t0 = gbus_read_uint32( pC->pGBus, pC->RegBase + SYS_xtal_in_cnt); do { t1 = gbus_read_uint32( pC->pGBus, pC->RegBase + SYS_xtal_in_cnt); if (t1 >= t0) d = t1 - t0; else d = 0xFFFFFFFF - t0 + t1 + 1; } while ( d < (27 * TotalDelay) );}/*---------------Hardware Control------------------*//* Clock Control */static RMvoid em_sclio(EMI2C_CONFIG *pC, RMuint8 out){ assert(pC); if(out) gbus_write_uint32(pC->pGBus, pC->RegBase + SYS_gpio_dir, 0x00010001 << pC->PIO_Clock); else gbus_write_uint32(pC->pGBus, pC->RegBase + SYS_gpio_dir, 0x00010000 << pC->PIO_Clock);}static RMvoid em_sclset(EMI2C_CONFIG *pC, RMuint8 high){ assert(pC); if(high) gbus_write_uint32(pC->pGBus, pC->RegBase + SYS_gpio_data, 0x00010001 << pC->PIO_Clock); else gbus_write_uint32(pC->pGBus, pC->RegBase + SYS_gpio_data, 0x00010000 << pC->PIO_Clock); }static RMvoid em_sclget(EMI2C_CONFIG *pC, RMuint8 *pData){ assert(pC); assert(pData); *pData = (gbus_read_uint32(pC->pGBus, pC->RegBase + SYS_gpio_data) & (1 << pC->PIO_Clock))?1:0;}/* a device can hold the scl time for a wait state *//* an i2c bus is supposed to have external pullups */static RMstatus em_scltryhi(EMI2C_CONFIG *pC){ RMuint32 count = 0; RMuint8 data = 0; RMuint32 timeout = DEFAULT_SCL_HI_TIMEOUT; assert(pC); if( pC->SclHiTimeout != 0 ) timeout = pC->SclHiTimeout; em_sclset(pC, 1); /* if it is in, we are floating hi/we have control * and if it is out, set it to 1 */ em_sclio(pC, OUT); em_sclio(pC, IN); /* float hi using external pullups */ em_sclget(pC, &data); while (data == 0) { if(count++ > timeout) return -1; /*sclset(1);*//* OUT is already 1*/ em_sclio(pC, OUT); em_udelay(pC, 1); em_sclio(pC, IN); em_sclget(pC, &data); } /* sclset(1);*//* OUT is already 1*/ em_sclio(pC, OUT); return RM_OK;}/* Data Control */static RMvoid em_sdaio(EMI2C_CONFIG *pC, RMuint8 out){ assert(pC); if(out) gbus_write_uint32(pC->pGBus, pC->RegBase + SYS_gpio_dir, 0x00010001 << pC->PIO_Data); else gbus_write_uint32(pC->pGBus, pC->RegBase + SYS_gpio_dir, 0x00010000 << pC->PIO_Data);}static RMvoid em_sdaset(EMI2C_CONFIG *pC, RMuint8 high){ assert(pC); if(high) gbus_write_uint32(pC->pGBus, pC->RegBase + SYS_gpio_data, 0x00010001 << pC->PIO_Data); else gbus_write_uint32(pC->pGBus, pC->RegBase + SYS_gpio_data, 0x00010000 << pC->PIO_Data);}static RMvoid em_sdaget(EMI2C_CONFIG *pC, RMuint8 *pData){ assert(pC); assert(pData); *pData = (gbus_read_uint32(pC->pGBus, pC->RegBase + SYS_gpio_data) & (1 << pC->PIO_Data))?1:0;}/*-----------------I2C Calls----------------------*//* in between start and stop, we tristate * in between read/write/ack, we OUT D =0, C =0 */ RMstatus emi2c_start(EMI2C_CONFIG *pC){ RMuint8 sda; //RMuint8 scl; assert(pC); em_sdaset(pC, 1); em_sdaio(pC, OUT); em_sdaget(pC, &sda); if( sda == 0 ) return -1; /* sda is being held low */ if( em_scltryhi(pC) != RM_OK ) /* sets scl OUT */ return -1; /*{ // Stop on Start em_sdaget(pC, &sda); em_sclget(pC, &scl); if( (sda == 0) || (scl == 0) ) { if( emi2c_stop(pC) != RM_OK ) return -1; } else { em_sdaset(pC, 1); em_sclset(pC, 1); } em_sdaio(pC, OUT); em_sclio(pC, OUT); }*/ /* now we are at 1,1 for OUT either from stop or manually */ /* Then Start */ em_sdaset(pC, 0); em_udelay(pC, 4); /*tHD;STA*/ em_sclset(pC, 0); em_udelay(pC, 5); /*tLOW*/ return RM_OK;}RMstatus emi2c_stop(EMI2C_CONFIG *pC){ assert(pC); em_sdaset(pC, 0); em_sdaio(pC, OUT); if( em_scltryhi(pC) != RM_OK ) return -1; em_udelay(pC, 4); /*tSU;STO*/ em_sdaset(pC, 1); em_udelay(pC, 5); /*tBUF*/ /* at this point, both outputs are 1, tristate for easy * read or for other devices to grab bus */ em_sdaio(pC, IN); em_sclio(pC, IN); return RM_OK;}RMstatus emi2c_sendbyte(EMI2C_CONFIG *pC, RMuint8 uData, RMuint8 *pNack){ RMuint8 uMask=0x80; RMuint8 i; RMuint8 b; assert(pC); assert(pNack); em_sclget(pC, &b); if( b != 0 ) return -1; /*sclio(OUT);*//*should already be in output mode */ em_sdaio(pC, OUT); for( i = 0; i < 8; i++ ) { if (uData & uMask) em_sdaset(pC, 1); else em_sdaset(pC, 0); uMask = uMask >> 1; /* get ready for next bit */ em_udelay(pC, 1); /* tSU;DAT */ /* clock */ if( em_scltryhi(pC) != RM_OK ) { em_sdaset(pC, 0); return -1; } em_udelay(pC, 4); /* tHIGH */ em_sclset(pC, 0); em_udelay(pC, 5); /* tHD;DAT */ } /* Ack/Nack */ em_sdaio(pC, IN); em_udelay(pC, 1); /* let sda float for slave to drive */ if( em_scltryhi(pC) != RM_OK ) { em_sdaset(pC, 0); em_sdaio(pC, OUT); return -1; } em_udelay(pC, 4); /* tHIGH */ em_sdaget(pC, pNack); /* get the ack/Nack */ em_sclset(pC, 0); em_sdaio(pC, OUT); em_sdaset(pC, 0); /* hold the bus */ em_udelay(pC, 5); /* tLOW */ return RM_OK;}RMstatus emi2c_readbyte(EMI2C_CONFIG *pC, RMuint8* pData, RMuint32 nackConfiguration){ RMuint8 b = 0; RMuint8 uData = 0; RMuint8 i = 0; assert(pC); assert(pData); // make sure we aren't using stray flags assert( (nackConfiguration & (~(EMI2C_SEND_NACK | EMI2C_SEND_NACK_IF_MISMATCH | EMI2C_SEND_NACK_COMPARE_DATA))) == 0 ); em_sclget(pC, &b); /* see if the slave is holding SCL */ if( b != 0 ) return -1; b = 0; em_sdaio(pC, IN); em_udelay(pC, 1); /* slave now drives */ for ( i = 0; i < 8; i++) { if( em_scltryhi(pC) != RM_OK ) { em_sdaset(pC, 0); /* hold the bus */ em_sdaio(pC, OUT); return -1; } em_udelay(pC, 4); /* tHIGH and tSU;DAT */ uData = uData << 1; em_sdaget(pC, &b); /* get data while HIGH, spec says data must be stable */ uData |= b; em_sclset(pC, 0); em_udelay(pC, 5); /* tHD;DAT not necessary? doesn't matter*/ } if( nackConfiguration & EMI2C_SEND_NACK ) em_sdaset(pC, 1); /* sda = 1 for nack */ else { if( nackConfiguration & EMI2C_SEND_NACK_IF_MISMATCH ) { if( uData != (nackConfiguration & EMI2C_SEND_NACK_COMPARE_DATA)) em_sdaset(pC, 1); /* sda = 1 for nack */ else em_sdaset(pC, 0); /* 0 for ack */ } else em_sdaset(pC, 0); /* 0 for ack */ } em_sdaio(pC, OUT); em_udelay(pC, 1); /* tSU;DAT */ if( em_scltryhi(pC) != RM_OK ) { em_sdaset(pC, 0); return -1; } em_udelay(pC, 4); /* tHIGH */ em_sclset(pC, 0); em_udelay(pC, 5); /* tLOW ,diff from tHD;DAT but same */ *pData = uData; return RM_OK;}/*-----------------High Level I2C Calls----------------------*/RMstatus emi2c_write_subaddress(EMI2C_CONFIG* pC, RMuint8 uSlaveAddress, RMuint8 uSubAddress,
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -