📄 omap730iic.c
字号:
//------------------------------------------------------------------------------
//
// Function: I2C_Open
//
// Called by device manager to open a device for reading and/or writing.
//
DWORD I2C_Open()
{
DWORD rc = (DWORD)NULL;
I2C_INSTANCE *pInstance = &g_Instance;
// Set cookie
g_Instance.pDevice = &g_device;
// Done...
rc = (DWORD)pInstance;
return rc;
}
//------------------------------------------------------------------------------
//
// Function: I2C_Init
//
// Called by device manager to initialize device.
//
DWORD I2C_Init()
{
DWORD rc = (DWORD)NULL;
I2C_DEVICE *pDevice = &g_device;
g_pTimerRegs = OALPAtoUA(OMAP730_TIMER32K_REGS_PA);
OUTREG32(&g_pTimerRegs->TVR, 0xFFFFFF);
SETREG32(&g_pTimerRegs->CR, CR_TRB);
while ((INREG32(&g_pTimerRegs->CR) & CR_TRB) != 0);
SETREG32(&g_pTimerRegs->CR, CR_TSS|CR_INT_EN|CR_ARL);
// Map I2C controller
pDevice->pI2CRegs = OALPAtoUA(OMAP730_I2C_REGS_PA);
// Check if we get correct context
if (pDevice->pI2CRegs == NULL) {
OALMSG(OAL_ERROR, (L"ERROR: I2C_Init: pDevice->pI2CRegs == NULL\r\n"));
goto clean;
}
I2C_Reset(pDevice);
I2C_Open();
// Return non-null value
rc = (DWORD)pDevice;
OALMSG(0, (L"-I2C_Init(rc = 0x%08x)\r\n", rc));
clean:
return rc;
}
//------------------------------------------------------------------------------
//
// Function: I2C_Close
//
// This function closes the device context.
//
BOOL I2C_Close(DWORD context)
{
BOOL rc = FALSE;
I2C_INSTANCE *pInstance = (I2C_INSTANCE*)context;
// Check if we get correct context
if (pInstance == NULL) {
DEBUGMSG (ZONE_ERROR, (L"ERROR: I2C_Read: "
L"Incorrect context paramer\r\n"
));
goto cleanUp;
}
// Done...
rc = TRUE;
cleanUp:
OALMSG(OAL_INFO, (L"-I2C_Close(rc = %d)\r\n", rc));
return rc;
}
//------------------------------------------------------------------------------
//
// Function: I2C_Deinit
//
// Called by device manager to uninitialize device.
//
BOOL I2C_Deinit(DWORD context)
{
BOOL rc = FALSE;
I2C_DEVICE *pDevice = (I2C_DEVICE*)context;
// Check if we get correct context
if (pDevice == NULL ) {
DEBUGMSG (ZONE_ERROR, (L"ERROR: I2C_Deinit: "
L"Incorrect context paramer\r\n"
));
goto cleanUp;
}
I2C_Close(context);
// Done
rc = TRUE;
cleanUp:
OALMSG(OAL_ERROR, (L"-I2C_Deinit(rc = %d)\r\n", rc));
return rc;
}
//------------------------------------------------------------------------------
//
// Function: I2C_Read
//
// This function reads data from the device identified by the open context.
//
DWORD I2C_Read(DWORD context, PVOID pBuffer, DWORD size)
{
DWORD rc = 0;
I2C_INSTANCE *pInstance = &g_Instance;
I2C_DEVICE *pDevice;
OMAP730_I2C_REGS *pI2CRegs;
DWORD base;
UCHAR *pData;
USHORT count;
USHORT con, stat;
DEBUGMSG(ZONE_I2C&&ZONE_FUNCTION, (
L"+I2C_Read(0x%08x, 0x%08x, %d\r\n", context, pBuffer, size
));
// Check if we get correct context
if (pInstance == NULL)
{
DEBUGMSG (ZONE_ERROR, (L"ERROR: I2C_Read: "
L"Incorrect context paramer\r\n"
));
goto clean;
}
pDevice = &g_device;
pI2CRegs = pDevice->pI2CRegs;
// Make sure I2C device is enabled...
if ((INREG16(&pI2CRegs->CON) & I2C_CON_EN) == 0)
{
// after a NACK the only way to recover
OUTREG16(&pI2CRegs->CON, I2C_CON_EN|I2C_CON_MST);
// Wait until resetting is done
while ((INREG16(&pI2CRegs->SYSS) & I2C_SYSS_RDONE) == 0);
// Clear all interrupts
SETREG16(&pI2CRegs->STAT, 0x3F);
}
// I2C slave address
OUTREG16(&pI2CRegs->SA, pInstance->address);
// Set up CON register
con = I2C_CON_EN | I2C_CON_MST | I2C_CON_STP | I2C_CON_STT;
if (pInstance->addrSize == 10) con |= I2C_CON_XA;
retry:
// Start transaction
pData = (UCHAR*)pBuffer;
count = (USHORT)size;
// Wait until bus isn't free - don't set CNT register before this.
// When CNT register is set when bus is busy it holds busy bit high.
base = OALGetTickCount();
while ((INREG16(&pI2CRegs->STAT) & I2C_STAT_BB) != 0)
{
if ((OALGetTickCount() - base) > I2C_TimeOut)
{
I2C_Reset(pDevice);
OALMSG(OAL_ERROR, (L"ERROR: I2C_Read: "
L"Bus remains locked -- resetting I2C controller 0x%02x\r\n",
pInstance->address
));
goto clean;
}
OALStall(1000);
}
// Number of buffer to be transmitted
OUTREG16(&pI2CRegs->CNT, count);
// Clear bits
OUTREG16(&pI2CRegs->STAT, I2C_STAT_AL|I2C_STAT_NACK|I2C_STAT_RRDY);
// Start transaction
OUTREG16(&pI2CRegs->CON, con);
// Receive all expected data
while (count > 0)
{
do
{
// Get status
stat = INREG16(&pI2CRegs->STAT);
// Clear bits
OUTREG16(&pI2CRegs->STAT, I2C_STAT_AL|I2C_STAT_NACK|I2C_STAT_RRDY);
// Lost arbitration? Wait for empty bus...
if ((stat & I2C_STAT_AL) != 0) goto retry;
// No ACK? Exit... device may not be on the bus
if ((stat & I2C_STAT_NACK) != 0)
{
I2C_Reset(pDevice);
OALMSG(OAL_ERROR, (L"ERROR: I2C_Read: "
L"No ACK from slave device with address 0x%02x\r\n",
pInstance->address
));
goto clean;
}
// This should not happen
if ((stat & I2C_STAT_RRDY) == 0)
{
OALMSG(OAL_ERROR, (L"I2C_Read: --325-----This should not happen---------\r\n" ));
}
else
{
break;
}
}while(1);
// Clear the bit
OUTREG16(&pI2CRegs->STAT, I2C_STAT_RRDY);
// Depending on amount of data remaining
if (count > 1)
{
*(USHORT*)pData = INREG16(&pI2CRegs->DATA);
count -= 2;
pData += 2;
}
else
{
*pData = (UCHAR)INREG16(&pI2CRegs->DATA);
count -= 1;
pData += 1;
}
if( count > dcount)
OALStall(8000);
}
// We read all buffer
rc = size;
clean:
return rc;
}
//------------------------------------------------------------------------------
//
// Function: I2C_Write
//
// This function writes data to the device.
//
DWORD I2C_Write(DWORD context, PVOID pBuffer, DWORD size)
{
DWORD rc = -1;
I2C_DEVICE *pDevice;
I2C_INSTANCE *pInstance = &g_Instance;
OMAP730_I2C_REGS *pI2CRegs;
DWORD base;
UCHAR *pData;
USHORT count;
USHORT con, stat;
// Check if we get correct context
if (pInstance == NULL)
{
DEBUGMSG (ZONE_ERROR, (L"ERROR: I2C_Read: "
L"Incorrect context paramer\r\n"
));
goto clean;
}
pDevice = &g_device;
pI2CRegs = pDevice->pI2CRegs;
OALMSG(0, (L"I2C_Write: correct context paramer, pDevice = 0x%x\r\n", pDevice));
// Make sure I2C device is enabled...
if ((INREG16(&pI2CRegs->CON) & I2C_CON_EN) == 0)
{
// after a NACK the only way to recover
OUTREG16(&pI2CRegs->CON, I2C_CON_EN|I2C_CON_MST);
// Wait until resetting is done
while ((INREG16(&pI2CRegs->SYSS) & I2C_SYSS_RDONE) == 0);
// Clear all interrupts
SETREG16(&pI2CRegs->STAT, 0x3F);
}
// I2C slave address
OUTREG16(&pI2CRegs->SA, pInstance->address);
// Set up CON register
con = I2C_CON_EN | I2C_CON_MST | I2C_CON_TRX | I2C_CON_STP | I2C_CON_STT;
if (pInstance->addrSize == 10) con |= I2C_CON_XA;
retry:
OALMSG(0, (L"I2C_Write: ----------retry-----------\r\n" ));
pData = (UCHAR*)pBuffer;
count = (USHORT)size;
// Wait until bus isn't free - don't set CNT register before this.
// When CNT register is set when bus is busy it holds busy bit high.
base = OALGetTickCount();
while ((INREG16(&pI2CRegs->STAT) & I2C_STAT_BB) != 0)
{
if ((OALGetTickCount() - base) > I2C_TimeOut)
{
I2C_Reset(pDevice);
OALMSG(OAL_ERROR, (L"ERROR: I2C_Write: "
L"Bus remains locked -- resetting I2C controller 0x%02x\r\n",
pInstance->address
));
goto clean;
}
OALStall(1000);
}
// Number of buffer to be transmitted
OUTREG16(&pI2CRegs->CNT, count);
// Clear bit
OUTREG16(&pI2CRegs->STAT, I2C_STAT_AL|I2C_STAT_NACK|I2C_STAT_XRDY);
// Start transaction
OUTREG16(&pI2CRegs->CON, con);
// Send all data
while (count > 0)
{
do
{
// Get status
stat = INREG16(&pI2CRegs->STAT);
// Clear bits
OUTREG16(&pI2CRegs->STAT, I2C_STAT_AL|I2C_STAT_NACK|I2C_STAT_XRDY);
// Lost arbitration? Retry...
if ((stat & I2C_STAT_AL) != 0)
{
OALMSG(OAL_ERROR,(L"I2C:AL failed\r\n"));
goto retry;
}
// No ACK? Exit... device may not be on the bus
if ((stat & I2C_STAT_NACK) != 0)
{
I2C_Reset(pDevice);
OALMSG(OAL_ERROR, (L"ERROR: I2C_Write: "
L"No ACK from slave device with address 0x%02x\r\n",
pInstance->address
));
goto clean;
}
// This should not happen...
if ((stat & I2C_STAT_XRDY) == 0)
{
OALMSG(OAL_ERROR, (L"ERROR:I2C_Write: -------This should not happen...-------\r\n" ));
}
else
{
break;
}
}while(1);
// Clear the bit
OUTREG16(&pI2CRegs->STAT, I2C_STAT_XRDY);
// Depending on data amount
if (count > 1) {
OUTREG16(&pI2CRegs->DATA, *(USHORT*)pData);
count -= 2;
pData += 2;
} else {
OUTREG16(&pI2CRegs->DATA, *pData);
count -= 1;
pData += 1;
}
if( count> dcount)
OALStall(500);
}
// We wrote all buffer
rc = size;
clean:
return rc;
}
//------------------------------------------------------------------------------
BOOL I2C_SetSlaveAddress(DWORD context, DWORD size, DWORD address)
{
BOOL rc = FALSE;
I2C_INSTANCE *pInstance = (I2C_INSTANCE *)context;
g_Instance = *pInstance;
// Check if we get correct context
if (pInstance == NULL) {
OALMSG(OAL_ERROR, (L"ERROR: I2C_SetSlaveAddress: "
L"Incorrect context paramer 0x%x\r\n", pInstance
));
goto cleanUp;
}
if (size != 7 && size != 10) {
OALMSG(OAL_ERROR, (L"ERROR: I2C_SetSlaveAddress: "
L"Incorrect address size %d (valid values are 7 & 10 bits\r\n", size
));
goto cleanUp;
}
g_Instance.addrSize = size;
g_Instance.address = address;
rc = TRUE;
cleanUp:
return rc;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -