579 lines
22 KiB
C
579 lines
22 KiB
C
/*--------------------------------------------------------------------------------------------------------------------
|
||
(C) Copyright 2006, 2007 Marvell DSPC Ltd. All Rights Reserved.
|
||
-------------------------------------------------------------------------------------------------------------------*/
|
||
|
||
/*--------------------------------------------------------------------------------------------------------------------
|
||
INTEL CONFIDENTIAL
|
||
Copyright 2006 Intel Corporation All Rights Reserved.
|
||
The source code contained or described herein and all documents related to the source code (“Material? are owned
|
||
by Intel Corporation or its suppliers or licensors. Title to the Material remains with Intel Corporation or
|
||
its suppliers and licensors. The Material contains trade secrets and proprietary and confidential information of
|
||
Intel or its suppliers and licensors. The Material is protected by worldwide copyright and trade secret laws and
|
||
treaty provisions. No part of the Material may be used, copied, reproduced, modified, published, uploaded, posted,
|
||
transmitted, distributed, or disclosed in any way without Intel’s prior express written permission.
|
||
|
||
No license under any patent, copyright, trade secret or other intellectual property right is granted to or
|
||
conferred upon you by disclosure or delivery of the Materials, either expressly, by implication, inducement,
|
||
estoppel or otherwise. Any license under such intellectual property rights must be express and approved by
|
||
Intel in writing.
|
||
-------------------------------------------------------------------------------------------------------------------*/
|
||
#include "dm_i2c.h"
|
||
|
||
#define SET 1
|
||
#define CLEAR 0
|
||
|
||
#define I2C_RECORD_FLAG 0x494E4954
|
||
#define I2C_DEVICE_ERROR 0xDEADBEEF
|
||
|
||
// I2C registers offset
|
||
#define I2C_ISAR_REG 0x0020 // Slave Address Register
|
||
#define I2C_ISR_REG 0x0018 // Status Register
|
||
#define I2C_ICR_REG 0x0010 // Control Register
|
||
#define I2C_IDBR_REG 0x0008 // Data Byte Register
|
||
//#define I2C_IBMR_REG 0x0000 // Bus Monitor Register
|
||
|
||
#define I2C_OWN_SLAVE_ADDRESS 0xFF /* response */
|
||
|
||
/** bit map of the ICR register **/
|
||
#define I2C_ICR_UNIT_RESET_BIT 14
|
||
#define I2C_ICR_IDBR_RECEIVE_FULL_INT_ENABLE_BIT 9
|
||
#define I2C_ICR_MASTER_ABORT_BIT 4
|
||
#define I2C_ICR_TRANSFER_BYTE_BIT 3
|
||
#define I2C_ICR_ACK_NACK_CONTROL_BIT 2
|
||
#define I2C_ICR_STOP_BIT 1
|
||
#define I2C_ICR_START_BIT 0
|
||
|
||
|
||
#define I2C_ICR_MASTER_ABORT (1 << I2C_ICR_MASTER_ABORT_BIT)
|
||
#define I2C_ICR_TRANSFER_BYTE (1 << I2C_ICR_TRANSFER_BYTE_BIT)
|
||
#define I2C_ICR_ACK_NACK_CONTROL (1 << I2C_ICR_ACK_NACK_CONTROL_BIT)
|
||
#define I2C_ICR_STOP (1 << I2C_ICR_STOP_BIT)
|
||
#define I2C_ICR_START (1 << I2C_ICR_START_BIT)
|
||
|
||
/** bit map of the ISR register **/
|
||
#define I2C_ISR_UNEXPECTED_INTERRUPTS 0x00000310
|
||
#define I2C_ISR_CLEAR_ALL_INTERRUPTS 0x000007f0
|
||
|
||
#define I2C_ISR_BUS_ERROR_DETECTED_BIT 10
|
||
#define I2C_ISR_IDBR_RECEIVE_FULL_BIT 7
|
||
#define I2C_ISR_IDBR_TRANSMIT_EMPTY_BIT 6
|
||
#define I2C_ISR_ARBITRATION_LOSS_DETECTED_BIT 5
|
||
#define I2C_ISR_UNIT_BUSY_BIT 2
|
||
#define I2C_ISR_READ_WRITE_MODE_BIT 0
|
||
|
||
#define I2C_ICR_REG_INIT_VALUE 0x014E0 //all interrupts are disabled, except of the Bus Error and arbitration lost
|
||
#define LOOP_COUNTER_LIMIT 4000L
|
||
|
||
#define SLOW_MODE_ENABLE 0x7fff
|
||
#define FAST_MODE_ENABLE 0x8000
|
||
#define HIGH_MODE_ENABLE 0x18000
|
||
|
||
volatile unsigned long i2cRegisterBaseAddr = 0xD4037000;
|
||
|
||
#define I2C_REG_WRITE(reg, wval) \
|
||
((*((volatile UINT32*)(i2cRegisterBaseAddr + (reg)))) = wval);
|
||
|
||
#define I2C_REG_READ(reg, rval) \
|
||
rval = (*((volatile UINT32*)(i2cRegisterBaseAddr + (reg))));
|
||
|
||
#define I2C_REG_BIT_WRITE(reg, btNm, sc) \
|
||
{ UINT32 regVl; \
|
||
I2C_REG_READ(reg, regVl); \
|
||
sc ? (regVl = (1 << btNm) | regVl) : (regVl = ((regVl) & (~(1 << btNm)))); \
|
||
I2C_REG_WRITE(reg, regVl); \
|
||
}
|
||
|
||
|
||
#define I2C_STATUS_REG_CLEAR_BIT(bitNum) \
|
||
{ UINT32 regVal; \
|
||
regVal = (1 << bitNum); \
|
||
I2C_REG_WRITE(I2C_ISR_REG, regVal); \
|
||
}
|
||
|
||
#define CHECK_IF_CHIP_BUSY(st) \
|
||
{ UINT32 rv; \
|
||
I2C_REG_READ(I2C_ISR_REG, rv); \
|
||
st = I2C_REG_BIT_READ(rv, I2C_ISR_UNIT_BUSY_BIT) ? TRUE : FALSE; \
|
||
}
|
||
|
||
#define I2C_REG_BIT_READ(regVl, btNm) ((regVl >> btNm) & 0x00000001)
|
||
#define I2C_REG_BIT(btNm) (((UINT32)1) << (btNm))
|
||
#define I2C_SLAVE_WRITE(slv) ((slv) | 0x00000000) /* Master is writing to the slave */
|
||
#define I2C_SLAVE_READ(slv) ((slv) | 0x00000001) /* Master is reading from the slave */
|
||
|
||
/* I2C device status*/
|
||
typedef struct I2CDeviceStatusT {
|
||
UINT32 recordFlag;
|
||
UINT32 baseAddress;
|
||
UINT32 slaveAddress;
|
||
UINT32 deviceStatus;
|
||
} I2CDeviceStatusTT;
|
||
|
||
typedef struct I2CReceiveRequestParamsT {
|
||
UINT8 activeSlaveAddress;
|
||
UINT8 *RxBufferPtr;
|
||
UINT16 dataSize;
|
||
} I2CReceiveRequestParamsTT;
|
||
|
||
static BOOL repeatStart = TRUE;
|
||
static struct I2CDeviceStatusT i2cStatusArray[4];
|
||
static struct I2CReceiveRequestParamsT receiveReqParams;
|
||
|
||
static void i2cClockAndPinEnable(void)
|
||
{
|
||
*(volatile unsigned long*)0xD4090104 |= 0x2; // enable PLL1_614 for PWIC I2C
|
||
}
|
||
|
||
static void i2cUnitDiReset(void)
|
||
{
|
||
UINT32 ICRRegValue;
|
||
|
||
// Read the control register
|
||
I2C_REG_READ(I2C_ICR_REG, ICRRegValue);
|
||
|
||
ICRRegValue &= ~I2C_ICR_MASTER_ABORT; // Clear the abort bit
|
||
ICRRegValue &= ~I2C_ICR_START; // Clear the start bit
|
||
ICRRegValue &= ~I2C_ICR_STOP; // Clear the stop bit
|
||
ICRRegValue &= ~I2C_ICR_ACK_NACK_CONTROL; // Clear the ACK bit
|
||
ICRRegValue &= ~I2C_ICR_TRANSFER_BYTE; // Clear the transfer_byte bit
|
||
|
||
// clear the ICR register
|
||
I2C_REG_WRITE(I2C_ICR_REG, 0x0000);
|
||
|
||
// Set the RESET bit in the ICR rewgister
|
||
I2C_REG_BIT_WRITE(I2C_ICR_REG, I2C_ICR_UNIT_RESET_BIT, SET);
|
||
|
||
// clear the ISR register after reset
|
||
I2C_REG_WRITE(I2C_ISR_REG, I2C_ISR_CLEAR_ALL_INTERRUPTS);
|
||
|
||
// Clear the RESET bit in the ICR rewgister
|
||
I2C_REG_BIT_WRITE(I2C_ICR_REG, I2C_ICR_UNIT_RESET_BIT, CLEAR);
|
||
|
||
// Restore the ICR register
|
||
I2C_REG_WRITE(I2C_ICR_REG, ICRRegValue);
|
||
}
|
||
|
||
static void i2cConfigureDi(void)
|
||
{
|
||
UINT32 controlRegValue = I2C_ICR_REG_INIT_VALUE;
|
||
|
||
// reset the I2C unit
|
||
i2cUnitDiReset();
|
||
|
||
controlRegValue |= FAST_MODE_ENABLE;
|
||
|
||
I2C_REG_WRITE(I2C_ICR_REG, controlRegValue);
|
||
|
||
I2C_REG_WRITE(I2C_ISAR_REG, I2C_OWN_SLAVE_ADDRESS);
|
||
}
|
||
|
||
void i2cInit(void)
|
||
{
|
||
i2cClockAndPinEnable();
|
||
i2cConfigureDi();
|
||
}
|
||
|
||
static I2C_ReturnCode i2cWaitStatusDirect (UINT32 bitsSet, UINT32 bitsCleared)
|
||
{
|
||
UINT32 statusRegValue;
|
||
UINT32 countLimit = LOOP_COUNTER_LIMIT;
|
||
UINT32 mask = bitsSet | bitsCleared; // all bits we care of
|
||
UINT32 value = bitsSet;
|
||
|
||
do {
|
||
I2C_REG_READ(I2C_ISR_REG, statusRegValue);
|
||
countLimit--;
|
||
} while (((statusRegValue & mask) != value)
|
||
&& (!(I2C_REG_BIT_READ(statusRegValue, I2C_ISR_BUS_ERROR_DETECTED_BIT))
|
||
&& (countLimit > 0)
|
||
&& (!(I2C_REG_BIT_READ(statusRegValue, I2C_ISR_ARBITRATION_LOSS_DETECTED_BIT)))));
|
||
|
||
if (I2C_REG_BIT_READ(statusRegValue, I2C_ISR_ARBITRATION_LOSS_DETECTED_BIT)) {
|
||
return I2C_ISR_ARBITRATION_LOSS;
|
||
}
|
||
|
||
// check for timeout, reset the I2C device for next operations and return error if needed
|
||
if (countLimit == 0) {
|
||
UINT32 ICRRegValue = 0;
|
||
I2C_REG_READ(I2C_ICR_REG, ICRRegValue);
|
||
ICRRegValue |= I2C_ICR_MASTER_ABORT;
|
||
ICRRegValue &= ~I2C_ICR_TRANSFER_BYTE;
|
||
I2C_REG_WRITE(I2C_ICR_REG, ICRRegValue );
|
||
return I2C_RC_TIMEOUT_ERROR;
|
||
} else if ((I2C_REG_BIT_READ(statusRegValue, I2C_ISR_BUS_ERROR_DETECTED_BIT))) {
|
||
return I2C_ISR_BUS_ERROR;
|
||
}
|
||
|
||
return I2C_RC_OK;
|
||
}
|
||
|
||
static I2C_ReturnCode i2cMasterSendDirect(UINT8 *data, UINT16 dataSize, UINT8 slaveAddress, BOOL repeatedStart , BOOL masterReceiveCalled)
|
||
{
|
||
int i;
|
||
UINT32 ICRRegValue = 0;
|
||
I2C_ReturnCode I2CReturnCode = I2C_RC_OK;
|
||
|
||
/* Check the bus for free - If there is an arbitration loss, stay until it become free */
|
||
do {
|
||
// check if 'Arbitration Loss' was detected
|
||
if (I2CReturnCode == I2C_ISR_ARBITRATION_LOSS) {
|
||
I2C_STATUS_REG_CLEAR_BIT(I2C_ISR_ARBITRATION_LOSS_DETECTED_BIT);
|
||
|
||
// Read the control register
|
||
I2C_REG_READ(I2C_ICR_REG, ICRRegValue);
|
||
|
||
ICRRegValue &= ~I2C_ICR_START; // Clear the start bit
|
||
ICRRegValue &= ~I2C_ICR_TRANSFER_BYTE; // Clear the transfer_byte bit
|
||
|
||
// Write to the ICR register
|
||
I2C_REG_WRITE(I2C_ICR_REG, ICRRegValue);
|
||
|
||
for ( i = 0; i < 50000; i++ ); /* A little delay to enable others master to finish without interruption */
|
||
/* the bus arbiter, and reduce the arbitration sequences */
|
||
}
|
||
|
||
// write IDBR register: target slave address and R/W# bit=0 for write transaction.
|
||
I2C_REG_WRITE(I2C_IDBR_REG, I2C_SLAVE_WRITE(slaveAddress));
|
||
|
||
// write ICR register: set START bit, clear STOP bit, set Transfer Byte bit to initiate the access
|
||
I2C_REG_READ(I2C_ICR_REG, ICRRegValue);
|
||
ICRRegValue &= ~I2C_ICR_STOP;
|
||
ICRRegValue |= (I2C_ICR_START | I2C_ICR_TRANSFER_BYTE);
|
||
I2C_REG_WRITE(I2C_ICR_REG, ICRRegValue);
|
||
|
||
I2CReturnCode = i2cWaitStatusDirect((I2C_REG_BIT(I2C_ISR_IDBR_TRANSMIT_EMPTY_BIT) | I2C_REG_BIT(I2C_ISR_UNIT_BUSY_BIT)),
|
||
I2C_REG_BIT(I2C_ISR_READ_WRITE_MODE_BIT));
|
||
|
||
// clear 'IDBR Transmit Empty' bit (write '1')
|
||
I2C_STATUS_REG_CLEAR_BIT(I2C_ISR_IDBR_TRANSMIT_EMPTY_BIT);
|
||
if ((I2CReturnCode != I2C_ISR_ARBITRATION_LOSS) && (I2CReturnCode != I2C_RC_OK)) {
|
||
I2C_REG_READ(I2C_ICR_REG, ICRRegValue);
|
||
ICRRegValue &= 0xfff0;
|
||
I2C_REG_WRITE(I2C_ICR_REG, ICRRegValue);
|
||
return I2CReturnCode;
|
||
}
|
||
// check if 'Arbitration Loss' was detected
|
||
}while (I2CReturnCode == I2C_ISR_ARBITRATION_LOSS);
|
||
|
||
// write ICR register: clear START bit, clear STOP bit
|
||
I2C_REG_READ(I2C_ICR_REG, ICRRegValue);
|
||
ICRRegValue &= ~I2C_ICR_STOP;
|
||
ICRRegValue &= ~I2C_ICR_START;
|
||
I2C_REG_WRITE(I2C_ICR_REG, ICRRegValue );
|
||
|
||
/*** Send data bytes - all, except the last byte ***/
|
||
for (i = 0; i < (dataSize - 1); i++) {
|
||
// write data byte to the IDBR register
|
||
I2C_REG_WRITE(I2C_IDBR_REG, *data);
|
||
data++;
|
||
|
||
// Set 'Tranfer Byte' bit to intiate the access
|
||
I2C_REG_BIT_WRITE(I2C_ICR_REG, I2C_ICR_TRANSFER_BYTE_BIT, SET);
|
||
if((I2CReturnCode = i2cWaitStatusDirect(I2C_REG_BIT(I2C_ISR_IDBR_TRANSMIT_EMPTY_BIT) | I2C_REG_BIT(I2C_ISR_UNIT_BUSY_BIT),
|
||
I2C_REG_BIT(I2C_ISR_READ_WRITE_MODE_BIT))) != I2C_RC_OK) {
|
||
return I2CReturnCode;
|
||
}
|
||
|
||
// clear 'IDBR Transmit Empty' bit (write '1')
|
||
I2C_STATUS_REG_CLEAR_BIT(I2C_ISR_IDBR_TRANSMIT_EMPTY_BIT);
|
||
}
|
||
|
||
/*** Send the last byte with STOP bit ***/
|
||
// write the last data byte to the IDBR register
|
||
I2C_REG_WRITE(I2C_IDBR_REG, *data);
|
||
|
||
// write ICR: clear START bit
|
||
I2C_REG_BIT_WRITE(I2C_ICR_REG, I2C_ICR_START_BIT, CLEAR);
|
||
|
||
if ((repeatedStart == FALSE) || (masterReceiveCalled == FALSE)) {
|
||
I2C_REG_BIT_WRITE(I2C_ICR_REG, I2C_ICR_STOP_BIT, SET);
|
||
}
|
||
|
||
I2C_REG_BIT_WRITE(I2C_ICR_REG, I2C_ICR_TRANSFER_BYTE_BIT, SET);
|
||
|
||
// if (repeatedStart)
|
||
// {
|
||
// if ((I2CReturnCode = i2cWaitStatusDirect (I2C_REG_BIT(I2C_ISR_IDBR_TRANSMIT_EMPTY_BIT)|I2C_REG_BIT(I2C_ISR_UNIT_BUSY_BIT),
|
||
// I2C_REG_BIT(I2C_ISR_READ_WRITE_MODE_BIT)))!=I2C_RC_OK)
|
||
// return I2CReturnCode;
|
||
// }
|
||
// else
|
||
if ((I2CReturnCode = i2cWaitStatusDirect(I2C_REG_BIT(I2C_ISR_IDBR_TRANSMIT_EMPTY_BIT),
|
||
I2C_REG_BIT(I2C_ISR_READ_WRITE_MODE_BIT))) != I2C_RC_OK) {
|
||
return I2CReturnCode;
|
||
}
|
||
// clear 'IDBR Transmit Empty' bit (write '1')
|
||
I2C_STATUS_REG_CLEAR_BIT(I2C_ISR_IDBR_TRANSMIT_EMPTY_BIT);
|
||
I2C_REG_BIT_WRITE(I2C_ICR_REG, I2C_ICR_STOP_BIT, CLEAR);
|
||
|
||
return I2C_RC_OK;
|
||
}
|
||
|
||
static I2C_ReturnCode i2cMasterDataSendDirect(UINT8 *data , UINT16 dataSize , UINT8 slaveAddress , BOOL protected , UINT16 userId)
|
||
{
|
||
BOOL chipBusy;
|
||
I2C_ReturnCode I2CReturnCode;
|
||
|
||
CHECK_IF_CHIP_BUSY(chipBusy);
|
||
if (chipBusy == TRUE) {
|
||
return I2C_RC_CHIP_BUSY;
|
||
}
|
||
|
||
I2CReturnCode = i2cMasterSendDirect(data, dataSize, slaveAddress, repeatStart, FALSE);
|
||
return I2CReturnCode;
|
||
}
|
||
|
||
static UINT16 i2cIntLISRDirect(void)
|
||
{
|
||
UINT32 statusRegValue = 0, ICRRegValue = 0;
|
||
|
||
//check interrupt source
|
||
I2C_REG_READ(I2C_ISR_REG, statusRegValue);
|
||
if (I2C_REG_BIT_READ(statusRegValue, I2C_ISR_IDBR_RECEIVE_FULL_BIT)) {
|
||
// clear 'IDBR Receive Full' bit (write '1')
|
||
I2C_STATUS_REG_CLEAR_BIT(I2C_ISR_IDBR_RECEIVE_FULL_BIT);
|
||
{
|
||
// read the received byte
|
||
I2C_REG_READ(I2C_IDBR_REG, *receiveReqParams.RxBufferPtr);
|
||
receiveReqParams.RxBufferPtr++;
|
||
receiveReqParams.dataSize--;
|
||
|
||
// write ICR: clear STOP bit(1), clear ACK/NACK bit(2)
|
||
I2C_REG_READ(I2C_ICR_REG, ICRRegValue);
|
||
ICRRegValue &= ~I2C_ICR_STOP;
|
||
ICRRegValue &= ~I2C_ICR_ACK_NACK_CONTROL;
|
||
I2C_REG_WRITE(I2C_ICR_REG, ICRRegValue);
|
||
|
||
|
||
if (receiveReqParams.dataSize > 1) {
|
||
// write ICR: clear START bit, clear STOP bit, send ACK bit (0 for ACK),
|
||
// set Transfer Byte bit to initiate the access
|
||
I2C_REG_READ(I2C_ICR_REG, ICRRegValue);
|
||
ICRRegValue &= ~I2C_ICR_START;
|
||
ICRRegValue &= ~I2C_ICR_STOP;
|
||
ICRRegValue &= ~I2C_ICR_ACK_NACK_CONTROL;
|
||
ICRRegValue |= I2C_ICR_TRANSFER_BYTE;
|
||
I2C_REG_WRITE(I2C_ICR_REG, ICRRegValue);
|
||
} else if (receiveReqParams.dataSize == 1) {
|
||
// last byte remaing to read (with STOP signal)
|
||
// write ICR: clear START bit, set STOP bit, send NACK bit (1 for NACK),
|
||
// set Transfer Byte bit to initiate the access
|
||
I2C_REG_READ(I2C_ICR_REG, ICRRegValue);
|
||
ICRRegValue &= ~I2C_ICR_START;
|
||
ICRRegValue |= (I2C_ICR_STOP | I2C_ICR_ACK_NACK_CONTROL | I2C_ICR_TRANSFER_BYTE);
|
||
I2C_REG_WRITE(I2C_ICR_REG, ICRRegValue);
|
||
} else {
|
||
// disable 'IDBR Buffer Full' interrupt
|
||
I2C_REG_BIT_WRITE(I2C_ICR_REG, I2C_ICR_IDBR_RECEIVE_FULL_INT_ENABLE_BIT, CLEAR);
|
||
}
|
||
}
|
||
}
|
||
|
||
if (I2C_REG_BIT_READ(statusRegValue, I2C_ISR_BUS_ERROR_DETECTED_BIT)) {
|
||
// clear 'Bus Error Detected' bit (write '1')
|
||
I2C_STATUS_REG_CLEAR_BIT(I2C_ISR_BUS_ERROR_DETECTED_BIT);
|
||
}
|
||
|
||
if (statusRegValue & I2C_ISR_UNEXPECTED_INTERRUPTS) {
|
||
// clear 'I2C_ISR_UNEXPECTED_INTERRUPTS ' bits (write '1')
|
||
I2C_REG_WRITE(I2C_ISR_REG,I2C_ISR_UNEXPECTED_INTERRUPTS);
|
||
}
|
||
|
||
return receiveReqParams.dataSize;
|
||
}
|
||
|
||
static I2C_ReturnCode i2cMasterDataReceiveDirect (UINT8 *cmd, UINT16 cmdLength,
|
||
UINT8 writeSlaveAddress, BOOL protected, UINT8 *designatedRxBufferPtr,
|
||
UINT16 dataSize, UINT8 readSlaveAddress)
|
||
{
|
||
I2C_ReturnCode I2CReturnCode;
|
||
UINT32 ICRRegValue = 0;
|
||
BOOL chipBusy;
|
||
|
||
// store the request parameters (to be used from the ISR and by the I2C task when error)
|
||
receiveReqParams.RxBufferPtr = designatedRxBufferPtr;
|
||
receiveReqParams.dataSize = dataSize;
|
||
|
||
CHECK_IF_CHIP_BUSY(chipBusy);
|
||
if(chipBusy) {
|
||
return I2C_RC_CHIP_BUSY;
|
||
}
|
||
|
||
if ((cmdLength != 0) && (cmd != NULL)) {
|
||
/* if command is associated with the received request */
|
||
I2CReturnCode = i2cMasterSendDirect(cmd, cmdLength, writeSlaveAddress, repeatStart, TRUE);
|
||
if(I2CReturnCode != I2C_RC_OK) {
|
||
return I2CReturnCode;
|
||
}
|
||
}
|
||
|
||
/*** send Read Request ***/
|
||
// write IDBR: target slave address and R/W# bit (1 for read)
|
||
I2C_REG_WRITE(I2C_IDBR_REG, I2C_SLAVE_READ(readSlaveAddress));
|
||
|
||
// write ICR: set START bit, clear STOP bit, set Transfer Byte bit to initiate the access
|
||
I2C_REG_READ(I2C_ICR_REG, ICRRegValue);
|
||
ICRRegValue &= ~I2C_ICR_STOP;
|
||
ICRRegValue |= (I2C_ICR_START | I2C_ICR_TRANSFER_BYTE);
|
||
I2C_REG_WRITE(I2C_ICR_REG, ICRRegValue);
|
||
|
||
I2CReturnCode = i2cWaitStatusDirect(I2C_REG_BIT(I2C_ISR_IDBR_TRANSMIT_EMPTY_BIT)|I2C_REG_BIT(I2C_ISR_UNIT_BUSY_BIT)|I2C_REG_BIT(I2C_ISR_READ_WRITE_MODE_BIT), 0 );
|
||
|
||
// clear 'IDBR Transmit Empty' bit (write '1')
|
||
I2C_STATUS_REG_CLEAR_BIT(I2C_ISR_IDBR_TRANSMIT_EMPTY_BIT);
|
||
|
||
if (I2CReturnCode != I2C_RC_OK) {
|
||
return I2CReturnCode;
|
||
}
|
||
|
||
// Initiate the read process:
|
||
if (dataSize == 1) {
|
||
// only one byte to read
|
||
// write ICR: set STOP bit, set ACK/NACK bit (1 for NACK)
|
||
I2C_REG_READ(I2C_ICR_REG,ICRRegValue);
|
||
ICRRegValue &= ~I2C_ICR_START;
|
||
ICRRegValue |= (I2C_ICR_STOP | I2C_ICR_ACK_NACK_CONTROL);
|
||
I2C_REG_WRITE(I2C_ICR_REG, ICRRegValue);
|
||
} else {
|
||
// more than one byte to read
|
||
// write ICR: clear STOP bit, clear ACK/NACK bit (0 for ACK)
|
||
I2C_REG_READ(I2C_ICR_REG,ICRRegValue);
|
||
ICRRegValue &= ~I2C_ICR_STOP;
|
||
ICRRegValue &= ~I2C_ICR_ACK_NACK_CONTROL;
|
||
I2C_REG_WRITE(I2C_ICR_REG, ICRRegValue);
|
||
}
|
||
|
||
I2C_REG_READ(I2C_ICR_REG,ICRRegValue);
|
||
ICRRegValue &= ~I2C_ICR_START;
|
||
ICRRegValue |= I2C_ICR_TRANSFER_BYTE;
|
||
I2C_REG_WRITE(I2C_ICR_REG, ICRRegValue);
|
||
|
||
while(i2cIntLISRDirect());
|
||
|
||
return I2C_RC_OK;
|
||
}
|
||
|
||
static BOOL i2cDeviceStatusRecord(UINT32 slaveAddress, BOOL error)
|
||
{
|
||
UINT8 i = 0;
|
||
BOOL status = FALSE;
|
||
|
||
for (i = 0; i < sizeof(i2cStatusArray)/sizeof(struct I2CDeviceStatusT); i++) {
|
||
if (I2C_RECORD_FLAG != i2cStatusArray[i].recordFlag) {
|
||
i2cStatusArray[i].recordFlag = I2C_RECORD_FLAG;
|
||
i2cStatusArray[i].baseAddress = i2cRegisterBaseAddr;
|
||
i2cStatusArray[i].slaveAddress = slaveAddress;
|
||
|
||
if (error) {
|
||
i2cStatusArray[i].deviceStatus = I2C_DEVICE_ERROR;
|
||
} else {
|
||
i2cStatusArray[i].deviceStatus = 0;
|
||
}
|
||
status = TRUE;
|
||
}
|
||
}
|
||
|
||
return status;
|
||
}
|
||
|
||
static BOOL i2cDeviceStatusCheck(UINT32 slaveAddress)
|
||
{
|
||
UINT8 i = 0;
|
||
BOOL status = TRUE;
|
||
|
||
for (i = 0; i < sizeof(i2cStatusArray)/sizeof(struct I2CDeviceStatusT); i++) {
|
||
if ((i2cStatusArray[i].baseAddress == i2cRegisterBaseAddr )
|
||
&& (i2cStatusArray[i].slaveAddress == slaveAddress)
|
||
&& (i2cStatusArray[i].recordFlag == I2C_RECORD_FLAG)
|
||
&& (i2cStatusArray[i].deviceStatus == I2C_DEVICE_ERROR)) {
|
||
status = FALSE;
|
||
}
|
||
}
|
||
|
||
return status;
|
||
}
|
||
|
||
static I2C_ReturnCode i2cMastSend(UINT8 slaveAddr, UINT8 regAddr, UINT8 regData)
|
||
{
|
||
UINT16 readTimes = 0;
|
||
UINT32 i = 0;
|
||
UINT8 paramData[3] = {0};
|
||
I2C_ReturnCode status = I2C_RC_NOT_OK;
|
||
|
||
if (!i2cDeviceStatusCheck(slaveAddr)) {
|
||
return I2C_RC_NOT_OK;
|
||
}
|
||
|
||
paramData[0] = regAddr;
|
||
paramData[1] = regData;
|
||
paramData[2] = 0;
|
||
|
||
status = i2cMasterDataSendDirect(paramData, 2, slaveAddr, FALSE, 0);
|
||
|
||
readTimes = 0;
|
||
while (status != I2C_RC_OK) {
|
||
readTimes++;
|
||
|
||
for(i = 0; i < 0x10000; i++); /* Short delay. */
|
||
|
||
status = i2cMasterDataSendDirect(paramData, 2, slaveAddr, FALSE, 0);
|
||
|
||
if (readTimes >= 3) {
|
||
i2cDeviceStatusRecord(slaveAddr, TRUE);
|
||
break;
|
||
}
|
||
}
|
||
return status;
|
||
}
|
||
|
||
static UINT8 i2cMastReceive(UINT8 slaveAddr, UINT8 regAddr)
|
||
{
|
||
UINT32 i = 0;
|
||
UINT16 readTimes = 0;
|
||
UINT8 regData = 0;
|
||
I2C_ReturnCode status = I2C_RC_NOT_OK;
|
||
slaveAddr &=0xFE;
|
||
|
||
if (!i2cDeviceStatusCheck(slaveAddr)) {
|
||
return I2C_RC_NOT_OK;
|
||
}
|
||
|
||
status = i2cMasterDataReceiveDirect(®Addr,
|
||
1 /*cmd lenght*/,
|
||
slaveAddr,
|
||
FALSE /*not protected*/,
|
||
®Data,
|
||
0x1,
|
||
slaveAddr | 0x1);
|
||
|
||
while (status != I2C_RC_OK) {
|
||
readTimes ++;
|
||
for(i=0;i<0x10000;i++);
|
||
status = i2cMasterDataReceiveDirect(®Addr,
|
||
1 /*cmd lenght*/,
|
||
slaveAddr,
|
||
FALSE /*not protected*/,
|
||
®Data,
|
||
0x1,
|
||
(slaveAddr|0x1));
|
||
if (readTimes >= 3) {
|
||
i2cDeviceStatusRecord(slaveAddr, TRUE);
|
||
break;
|
||
}
|
||
}
|
||
|
||
return regData;
|
||
}
|
||
|
||
I2C_ReturnCode i2cSend( UINT8 slaveAddr, UINT8 regAddr, UINT8 regData)
|
||
{
|
||
return (i2cMastSend(slaveAddr, regAddr, regData));
|
||
}
|
||
|
||
UINT8 i2cReceive( UINT8 slaveAddr, UINT8 regAddr)
|
||
{
|
||
UINT8 res = 0;
|
||
res = i2cMastReceive(slaveAddr, regAddr);
|
||
return res;
|
||
}
|