?? sysi2ckahlua.c
字號(hào):
/* sysI2cKahlua.c - I2C Driver Source Module *//* Copyright 1998-2002 Motorola, Inc. All Rights Reserved *//*modification history--------------------01g,16apr02,dat Update for T2.2 release01f,16sep01,dat Use of WRS_ASM macro01e,14apr00,krp 'bclr' short circuits stack cleanup with optimization turned off.01d,08feb00,rhk Added patch for I2C BUS BUSY lockup condition.01c,28may99,dmw Updated to Wind River coding standards.01b,18may99,rhk changes to support compressed builds.01a,18feb99,dmw created - based on MCG DVT group's Kahlua I2C driver. *//*DESCRIPTIONI2C Driver Source (Low Level Routines) ModuleKahlua Memory Controller (PowerPlus Architecture)Notes: 1. GREAT care must be made when sending commands to the MPC8240(Kahlua). Several "i2cCycleKahluaDelay" calls are made in order to not overwhelm the I2C interface. If commands are sent too fast, the I2C interface will lockup and the I2C bus may become unusable without a powercycle. Generally, if if you cause a I2C bus cycle, you should wait for "a while". A possible cause is that the caches were turned on when this driver was written.*//* includes */#include "vxWorks.h" /* vxWorks generics */#include "sysI2cKahlua.h" /* low level definitions, specific */#include "config.h" /* BSP specifics */#include "kahlua.h" /* processor specifics - MPC8240 */#include "arch/ppc/vxPpcLib.h" /* for vxDecGet() */#ifdef DEBUG_I2C# include "sdramSpd.h"# include "stdio.h"#endif/* externals */IMPORT int i2cRead(); /* device read operation */IMPORT int i2cWrite(); /* device write operation */#ifdef DEBUG_I2CIMPORT logMsg ();#endifIMPORT UINT32 i2cPciIoctl (UINT32 ioctlflg, UINT32 address, UINT32, UINT32);IMPORT UINT32 abs(UINT32 old);IMPORT STATUS i2cDrvInit (int i2cControllerType);/* forward declarations */void sysKahluaMsDelay (UINT mSeconds);LOCAL UINT32 sysKahluaGetDec(void);void i2cCycleKahluaDelay (int mSeconds);/* debug declarations */#ifdef DEBUG_I2C#define REAL_SPD_SIZE 256char defaultSPD[SPD_SIZE];#endif /* DEBUG_I2C *//* Global flag */int I2CDoRepeatStart = 0; /* indicates if a "Repeat Start" is requested *//******************************************************************************* * i2cCycleKahluaStart - perform I2C "start" cycle* * This function's purpose is to perform an I2C start cycle.* * RETURNS:* zero = operation successful* non-zero = operation failed*/int i2cCycleKahluaStart (void) { unsigned int timeOutCount; unsigned int statusReg = 0; /* * if this is a repeat start, then set the required bits and return. * * NOTE: * this driver ONLY supports one repeat start between the start * stop and cycles. */ if(I2CDoRepeatStart == 1) { i2cCycleKahluaDelay(1); i2cPciIoctl(2, (UINT32)KAHLUA_I2C_CONTROL_REG, (KAHLUA_I2C_CONTROL_REG_RSTA | KAHLUA_I2C_CONTROL_REG_MSTA | KAHLUA_I2C_CONTROL_REG_MTX),0); SYNC; i2cCycleKahluaDelay(1); I2CDoRepeatStart = 0; /* one repeat start only, so clear this bit */ return(0); } /* * wait until the I2C bus is free. if it doesn't become free * within a *reasonable* amount of time, exit with an error. */ for (timeOutCount = 10; timeOutCount; timeOutCount--) { i2cCycleKahluaDelay(1); statusReg = i2cPciIoctl(1, (UINT32)KAHLUA_I2C_STATUS_REG, 0, 0); SYNC; if (!(statusReg & KAHLUA_I2C_STATUS_REG_MBB)) { break; } } if (!timeOutCount) { return (-1); } /* * since this is the first time through, generate a START(MSTA) and * place the I2C interface into a master transmitter mode(MTX). */ i2cPciIoctl(2, (UINT32)KAHLUA_I2C_CONTROL_REG, (KAHLUA_I2C_CONTROL_REG_MTX | KAHLUA_I2C_CONTROL_REG_MSTA),0); SYNC; i2cCycleKahluaDelay(1); /* * The first time through, set "I2CDoRepeatStart". If this function * is called again BEFORE a STOP is sent, then we are doing a * "dummy write", which sets the devices internal byte pointer * to the byte we intend to read. */ I2CDoRepeatStart = 1; return (0); }/******************************************************************************* * i2cCycleKahluaStop - perform I2C "stop" cycle* * This function's purpose is to perform an I2C stop cycle.* * RETURNS:* zero = operation successful* non-zero = operation failed*/int i2cCycleKahluaStop (void) { i2cCycleKahluaDelay(1); /* * turn off MSTA bit(which will generate a STOP bus cycle) * turn off MTX bit(which places the MPC8240 interface into receive mode * turn off TXAK bit(which allows 9th clock cycle acknowledges) */ i2cPciIoctl(3, (UINT32)KAHLUA_I2C_CONTROL_REG, (~(KAHLUA_I2C_CONTROL_REG_MTX | KAHLUA_I2C_CONTROL_REG_MSTA | KAHLUA_I2C_CONTROL_REG_TXAK)),0); SYNC; i2cCycleKahluaDelay(1); /* * Clear the global I2C "Repeat Start" flag. */ I2CDoRepeatStart = 0; return (0); }* * i2cCycleKahluaRead - perform I2C "read" cycle* * This function's purpose is to perform an I2C read cycle.* * RETURNS:* zero = operation successful* non-zero = operation failed*/int i2cCycleKahluaRead ( unsigned char *pReadDataBuf /* pointer to read data buffer */ ) { unsigned int readData = 0; i2cCycleKahluaDelay(1); /* * place the I2C interface into receive mode(MTX=0) and set the interface * to NOT acknowledge(TXAK=1) the incoming data on the 9th clock cycle. * this is required when doing random reads of a I2C device. */ i2cPciIoctl(4, (UINT32)KAHLUA_I2C_CONTROL_REG, (~KAHLUA_I2C_CONTROL_REG_MTX), KAHLUA_I2C_CONTROL_REG_TXAK); SYNC; i2cCycleKahluaDelay(1); /* do a "dummy read". this latches the data off the bus. */ i2cPciIoctl(1, (UINT32)KAHLUA_I2C_DATA_REG, 0, 0); SYNC; i2cCycleKahluaDelay(1); /* now do the actual read, make this one count */ readData = i2cPciIoctl(1, (UINT32)KAHLUA_I2C_DATA_REG, 0, 0); SYNC; *pReadDataBuf = (unsigned char)readData; return (0); }/******************************************************************************* * i2cCycleKahluaWrite - perform I2C "write" cycle* * This function's purpose is to perform an I2C write cycle.* * RETURNS:* zero = operation successful* non-zero = operation failed*/int i2cCycleKahluaWrite ( unsigned char writeData /* character to write */ ) { i2cCycleKahluaDelay(1); /* * write the requested data to the data register, which will cause * it to be transmitted on the I2C bus. */ i2cPciIoctl(0, (UINT32)KAHLUA_I2C_DATA_REG, writeData, 0); SYNC; i2cCycleKahluaDelay(1); return (0); }/******************************************************************************* * i2cCycleKahluaAckIn - perform I2C "acknowledge-in" cycle* * This function's purpose is to perform an I2C acknowledge-in* cycle.* * RETURNS:* zero = operation successful* non-zero = operation failed*/int i2cCycleKahluaAckIn (void) { unsigned int statusReg = 0; unsigned int timeOutCount; /* * wait until an *internal* device interrupt has been generated, then * clear it. if it is not received, return with an error. * we are polling, so NO processor interrupt is generated. */ for (timeOutCount = 100; timeOutCount; timeOutCount--) { i2cCycleKahluaDelay(1); statusReg = i2cPciIoctl(1, (UINT32)KAHLUA_I2C_STATUS_REG, 0, 0); SYNC; if (statusReg & KAHLUA_I2C_STATUS_REG_MIF) { i2cPciIoctl(3, (UINT32)KAHLUA_I2C_STATUS_REG, (~KAHLUA_I2C_STATUS_REG_MIF), 0); SYNC; break; } } if (!timeOutCount) { return (-1); } return (0); }/******************************************************************************* * i2cCycleKahluaAckOut - perform I2C "acknowledge-out" cycle* * This function's purpose is to perform an I2C acknowledge-out* cycle.* * RETURN:* zero = operation successful* non-zero = operation failed*/int i2cCycleKahluaAckOut (void) { return (0); }/******************************************************************************* * i2cCycleKahluaKnownState - initialize the I2C bus to a known state* * This function's purpose is to initialize the I2C bus to a* known state.* * RETURNS:* zero = operation successful* non-zero = operation failed*/int i2cCycleKahluaKnownState (void) { STATUS status; UINT timeOutCount; UINT statusReg;
?? 快捷鍵說(shuō)明
復(fù)制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號(hào)
Ctrl + =
減小字號(hào)
Ctrl + -