📄 ixi2cdrv.c
字号:
/** * @file IxI2cDrv.c * * @version File Version: $Revision: 0.1 $ * * @par * IXP400 SW Release version 2.1 * * -- Copyright Notice -- * * @par * Copyright (c) 2001-2005, Intel Corporation. * All rights reserved. * * @par * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. Neither the name of the Intel Corporation nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * * @par * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``AS IS'' * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * * * @par * -- End of Copyright Notice -- */#ifdef __ixp46X#include "IxI2cDrv.h"#include "IxOsal.h"#include "IxFeatureCtrl.h" /** * Local #defines */#define IX_I2C_CR_OFFSET 0x0 /* I2C Control Register (ICR) offset from IXP400_I2C_BASE */#define IX_I2C_SR_OFFSET 0x4 /* I2C Status Register (ISR) offset from IXP400_I2C_BASE */#define IX_I2C_SAR_OFFSET 0x8 /* I2C Slave Address Register (ISAR) offset from IXP400_I2C_BASE */#define IX_I2C_DBR_OFFSET 0xC /* I2C Data Buffer Register (IDBR) offset from IXP400_I2C_BASE */#define IX_I2C_MASK_7_BITS 0x7F/* Mask for the least significant 7-bits */#define IX_I2C_SLAVE_READ 0x1 /* 1 indicates a read in the LSB after the 7-bit slave address */#define IX_I2C_SLAVE_WRITE 0x0 /* 0 indicates a write in the LSB after the 7-bit slave address */#define IX_I2C_ENABLE 0x1 /* 1 enables the feature in the ICR */#define IX_I2C_DISABLE 0x0 /* 0 disables the feature in the ICR */#define IX_I2C_GEN_CALL_DISABLE 0x1 /* 1 disables response to gen call */#define IX_I2C_NACK 0x1 /* 1 sends a Nack in the ICR */#define IX_I2C_ACK 0x0 /* 0 sends an Ack in the ICR */#define IX_I2C_TRIGGERED 0x1 /* 1 indicates the bit is triggered in the ISR */#define IX_I2C_INTERRUPTED 0x1 /* 1 indicates an interrupt has occured in the ISR */#define IX_I2C_INTERRUPT_ENABLE 0x1 /* 1 enables the interrupt in the ICR */#define IX_I2C_SLAVE_READ_MODE 0x0 /* 0 indicates a slave-receive for the read/write mode bit in the ISR */#define IX_I2C_MIN_SLAVE_ADDR 0x1 /* The lowest slave addr for I2C */#define IX_I2C_MAX_7_BIT_SLAVE_ADDR 0x7F/* The max slave addr for 7-bit I2C */#define IX_I2C_SET_TO_BE_CLEARED 0x1 /* Use for write 1 to clear in the registers */#define IX_I2C_US_DELAY_FOR_REG_READ 0x10 /* min delay implemented to avoid a tight loop in polling */#define IX_I2C_INVALID_SLAVE_ADDRESS 0x0 /* 0 value slave address is invalid as it is reserved for general calls */#define IX_I2C_NOT_TO_BE_USED_I2C_ADDR 0x1 /* I2C address of 0x1 is reserved for the (now obsolete) C-Bus format *//* #defines for mask and location of I2C Control Register contents */#define IX_I2C_SPEEDMODE_LOC (0xF)#define IX_I2C_SPEEDMODE_MASK (0x1 << IX_I2C_SPEEDMODE_LOC)#define IX_I2C_UNIT_RESET_LOC (0xE)#define IX_I2C_UNIT_RESET_MASK (0x1 << IX_I2C_UNIT_RESET_LOC)#define IX_I2C_SLAVE_ADDR_DETECT_ENABLE_LOC (0xD)#define IX_I2C_SLAVE_ADDR_DETECT_ENABLE_MASK (0x1 << IX_I2C_SLAVE_ADDR_DETECT_ENABLE_LOC)#define IX_I2C_ARB_LOSS_INT_ENABLE_LOC (0xC)#define IX_I2C_ARB_LOSS_INT_ENABLE_MASK (0x1 << IX_I2C_ARB_LOSS_INT_ENABLE_LOC)#define IX_I2C_SLAVE_STOP_DETECT_ENABLE_LOC (0xB)#define IX_I2C_SLAVE_STOP_DETECT_ENABLE_MASK (0x1 << IX_I2C_SLAVE_STOP_DETECT_ENABLE_LOC)#define IX_I2C_BUS_ERROR_INT_ENABLE_LOC (0xA)#define IX_I2C_BUS_ERROR_INT_ENABLE_MASK (0x1 << IX_I2C_BUS_ERROR_INT_ENABLE_LOC)#define IX_I2C_IDBR_RX_FULL_INT_ENABLE_LOC (0x9)#define IX_I2C_IDBR_RX_FULL_INT_ENABLE_MASK (0x1 << IX_I2C_IDBR_RX_FULL_INT_ENABLE_LOC)#define IX_I2C_IDBR_TX_EMPTY_INT_ENABLE_LOC (0x8)#define IX_I2C_IDBR_TX_EMPTY_INT_ENABLE_MASK (0x1 << IX_I2C_IDBR_TX_EMPTY_INT_ENABLE_LOC)#define IX_I2C_GEN_CALL_RESPOND_LOC (0x7)#define IX_I2C_GEN_CALL_RESPOND_MASK (0x1 << IX_I2C_GEN_CALL_RESPOND_LOC)#define IX_I2C_UNIT_ENABLE_LOC (0x6)#define IX_I2C_UNIT_ENABLE_MASK (0x1 << IX_I2C_UNIT_ENABLE_LOC)#define IX_I2C_SCL_ENABLE_LOC (0x5)#define IX_I2C_SCL_ENABLE_MASK (0x1 << IX_I2C_SCL_ENABLE_LOC)#define IX_I2C_MASTER_ABORT_LOC (0x4)#define IX_I2C_MASTER_ABORT_MASK (0x1 << IX_I2C_MASTER_ABORT_LOC)#define IX_I2C_TRANSFER_BYTE_LOC (0x3)#define IX_I2C_TRANSFER_BYTE_MASK (0x1 << IX_I2C_TRANSFER_BYTE_LOC)#define IX_I2C_ACK_NACK_CTL_LOC (0x2)#define IX_I2C_ACK_NACK_CTL_MASK (0x1 << IX_I2C_ACK_NACK_CTL_LOC)#define IX_I2C_SEND_STOP_LOC (0x1)#define IX_I2C_SEND_STOP_MASK (0x1 << IX_I2C_SEND_STOP_LOC)#define IX_I2C_SEND_START_LOC (0x0)#define IX_I2C_SEND_START_MASK (0x1 << IX_I2C_SEND_START_LOC)/* #defines for mask and location of I2C Status Register contents */#define IX_I2C_BUS_ERROR_DETECTED_LOC (0xA)#define IX_I2C_BUS_ERROR_DETECTED_MASK (0x1 << IX_I2C_BUS_ERROR_DETECTED_LOC)#define IX_I2C_SLAVE_ADDR_DETECTED_LOC (0x9)#define IX_I2C_SLAVE_ADDR_DETECTED_MASK (0x1 << IX_I2C_SLAVE_ADDR_DETECTED_LOC)#define IX_I2C_GEN_CALL_ADDR_DETECTED_LOC (0x8)#define IX_I2C_GEN_CALL_ADDR_DETECTED_MASK (0x1 << IX_I2C_GEN_CALL_ADDR_DETECTED_LOC)#define IX_I2C_IDBR_RX_FULL_LOC (0x7)#define IX_I2C_IDBR_RX_FULL_MASK (0x1 << IX_I2C_IDBR_RX_FULL_LOC)#define IX_I2C_IDBR_TX_EMPTY_LOC (0x6)#define IX_I2C_IDBR_TX_EMPTY_MASK (0x1 << IX_I2C_IDBR_TX_EMPTY_LOC)#define IX_I2C_ARB_LOSS_DETECTED_LOC (0x5)#define IX_I2C_ARB_LOSS_DETECTED_MASK (0x1 << IX_I2C_ARB_LOSS_DETECTED_LOC)#define IX_I2C_SLAVE_STOP_DETECTED_LOC (0x4)#define IX_I2C_SLAVE_STOP_DETECTED_MASK (0x1 << IX_I2C_SLAVE_STOP_DETECTED_LOC)#define IX_I2C_BUS_BUSY_LOC (0x3)#define IX_I2C_BUS_BUSY_MASK (0x1 << IX_I2C_BUS_BUSY_LOC)#define IX_I2C_UNIT_BUSY_LOC (0x2)#define IX_I2C_UNIT_BUSY_MASK (0x1 << IX_I2C_UNIT_BUSY_LOC)#define IX_I2C_ACK_NACK_STATUS_LOC (0x1)#define IX_I2C_ACK_NACK_STATUS_MASK (0x1 << IX_I2C_ACK_NACK_STATUS_LOC)#define IX_I2C_READ_WRITE_MODE_LOC (0x0)#define IX_I2C_READ_WRITE_MODE_MASK (0x1 << IX_I2C_READ_WRITE_MODE_LOC)/** * section for macros *//* Used by most APIs to check if the I2C is already init by checking the ixI2cInitComplete flag. Display and return error if I2C is not init */#define IX_I2C_INIT_SUCCESS_CHECK(funcName) \if(FALSE == ixI2cInitComplete) \{ \ ixOsalLog (IX_OSAL_LOG_LVL_ERROR, IX_OSAL_LOG_DEV_STDERR, \ funcName": I2C Driver not initialized\n", \ 0,0,0,0,0,0); \ return IX_I2C_NOT_INIT; \} /* end of FALSE == ixI2cInitComplete *//* Used in ixI2cDrvSlaveAddrDetectedHdlr, ixI2cDrvIDBRTxEmptyHdlr, and ixI2cDrvIDBRRxFullHdlr to check if the client buffer is NULL, then call the respective client callback to indicate no buffer. If callback does not provide a buffer after a few tries, then disable the I2C unit and log an error. *NOTE*: numOfTries has to be declared to use this macro. */#define IX_I2C_CHECK_SLAVE_OR_GEN_BUFFER_NULL(CBFuncName, CBFuncStr, CallingAPIName, returnVal)\/* Clear number of tries to check buffer after calling callback */ \numOfTries = 0; \ \while(NULL == ixI2cSlaveOrGenBufTracker.bufP) \{ \ CBFuncName(IX_I2C_SLAVE_NO_BUFFER, \ ixI2cSlaveOrGenBufTracker.bufP, \ ixI2cSlaveOrGenBufTracker.bufSize, \ ixI2cSlaveOrGenBufTracker.offset); \ \ /* Preventive mechanism when client does not provide buffer */ \ if(numOfTries++ >= IX_I2C_NUM_OF_TRIES_TO_CALL_CALLBACK_FUNC) \ { \ /* Disable the I2C unit and log an error */ \ ixI2cCfgStored = (ixI2cCfgStored & (~IX_I2C_UNIT_ENABLE_MASK)) | \ (IX_I2C_DISABLE << IX_I2C_UNIT_ENABLE_LOC); \ IX_OSAL_WRITE_LONG(ixI2cCRAddr, ixI2cCfgStored); \ ixOsalLog (IX_OSAL_LOG_LVL_ERROR, IX_OSAL_LOG_DEV_STDERR, \ CallingAPIName ": " CBFuncStr \ "not providing buffer! I2C disabled!!\n", 0,0,0,0,0,0); \ return returnVal; \ } /* end of preventive mechanism for client not providing buffer */ \} /* end of buffer is NULL *//* Used in ixI2cDrvIDBRRxFullHdlr to check if the client buffer is filled then call the callback to indicate buffer full. If callback does not clear the buffer after a few tries, then disable the I2C unit and log an error. *NOTE*: numOfTries has to be declared to use this macro. */#define IX_I2C_CHECK_SLAVE_OR_GEN_BUFFER_FULL(CBFuncName, CBFuncStr, CallingAPIName, returnVal)\/* Clear number of tries to check buffer after calling callback */ \numOfTries = 0; \ \/* Check if the buffer is full */ \while(ixI2cSlaveOrGenBufTracker.bufSize <= ixI2cSlaveOrGenBufTracker.offset)\{ \ CBFuncName(IX_I2C_SLAVE_OR_GEN_READ_BUFFER_FULL, \ ixI2cSlaveOrGenBufTracker.bufP, \ ixI2cSlaveOrGenBufTracker.bufSize, \ ixI2cSlaveOrGenBufTracker.offset); \ /* Preventive mechanism if the client does not have code to \ empty the buffer */ \ if(numOfTries++ >= IX_I2C_NUM_OF_TRIES_TO_CALL_CALLBACK_FUNC) \ { \ /* Disable the I2C unit and log an error */ \ ixI2cCfgStored = (ixI2cCfgStored & (~IX_I2C_UNIT_ENABLE_MASK)) | \ (IX_I2C_DISABLE << IX_I2C_UNIT_ENABLE_LOC); \ IX_OSAL_WRITE_LONG(ixI2cCRAddr, ixI2cCfgStored); \ ixOsalLog (IX_OSAL_LOG_LVL_ERROR, IX_OSAL_LOG_DEV_STDERR, \ CallingAPIName ": " CBFuncStr \ "not emptying buffer! I2C disabled!!\n", 0,0,0,0,0,0); \ return returnVal; \ } /* end of preventive mechanism for client not emptying the buffer */ \} /* end of buffer is full *//* Used in ixI2cDrvSlaveAddrDetectedHdlr and ixI2cDrvIDBRTxEmptyHdlr to check if the client buffer is empty then call the callback to indicate buffer empty. If callback does not provide a filled buffer after a few tries, then disable the I2C unit and log an error. *NOTE*: numOfTries has to be declared to use this macro. */#define IX_I2C_CHECK_SLAVE_BUFFER_EMPTY(CallingAPIName, returnVal) \/* Clear number of tries to check buffer after calling callback */ \numOfTries = 0; \ \/* Check if the buffer is empty */ \while(ixI2cSlaveOrGenBufTracker.bufSize <= ixI2cSlaveOrGenBufTracker.offset)\{ \ /* Call slave write callback to indicate buffer empty */ \ ixI2cSlaveWrCallbackP(IX_I2C_SLAVE_WRITE_BUFFER_EMPTY, \ ixI2cSlaveOrGenBufTracker.bufP, ixI2cSlaveOrGenBufTracker.bufSize, \ ixI2cSlaveOrGenBufTracker.offset); \ \ /* Preventive mechanism when client does not fill the buffer */ \ if(numOfTries++ >= IX_I2C_NUM_OF_TRIES_TO_CALL_CALLBACK_FUNC) \ { \ /* Disable the I2C unit and log an error */ \ ixI2cCfgStored = (ixI2cCfgStored & (~IX_I2C_UNIT_ENABLE_MASK)) | \ (IX_I2C_DISABLE << IX_I2C_UNIT_ENABLE_LOC); \ IX_OSAL_WRITE_LONG(ixI2cCRAddr, ixI2cCfgStored); \ ixOsalLog (IX_OSAL_LOG_LVL_ERROR, IX_OSAL_LOG_DEV_STDERR, \ CallingAPIName "ixI2cSlaveWrCallbackP not emptying buffer! I2C disabled!!\n", \ 0,0,0,0,0,0); \ return returnVal; \ } /* end of preventive mechanism for client not emptying the buffer */ \} /* end of buffer is empty *//* Used in ixI2cDrvWriteTransfer to poll for the IDBR Tx bit in the I2C SR and if it never received it then check if the error is due to an arb loss or a transfer error. Return respective error if error else continue. *NOTE*: numOfTries has to be declared to use this macro. */#define IX_I2C_POLL_IDBR_TX_EMPTY_AND_CHECK_FOR_ARB_LOSS(dataXferred) \/* Reset numOfTries to zero for polling */ \numOfTries = 0; \ \/* Poll for IDBR Transmit Empty to determine the data in the IDBR \ has bean transmitted */ \do /* IX_I2C_TRIGGERED != ixI2cStsStored.IDBRTxEmpty */ \{ \
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -