iicps_v2_4: Implemented repeated start feature.
This patch adds the repeated start feature in the iicps driver. Signed-off-by: P L Sai Krishna <lakshmis@xilinx.com>
This commit is contained in:
parent
aeae1a8d96
commit
5ae0b34872
4 changed files with 103 additions and 39 deletions
|
@ -50,6 +50,7 @@
|
|||
* 2.3 sk 10/07/14 Repeated start feature removed.
|
||||
* 2.4 sk 11/03/14 Modified TimeOut Register value to 0xFF
|
||||
* in XIicPs_Reset.
|
||||
* 12/06/14 Implemented Repeated start feature.
|
||||
*
|
||||
* </pre>
|
||||
*
|
||||
|
@ -132,6 +133,9 @@ int XIicPs_CfgInitialize(XIicPs *InstancePtr, XIicPs_Config *ConfigPtr,
|
|||
*/
|
||||
InstancePtr->Options = XIicPs_GetOptions(InstancePtr);
|
||||
|
||||
/* Initialize repeated start flag to 0 */
|
||||
InstancePtr->IsRepeatedStart = 0;
|
||||
|
||||
return XST_SUCCESS;
|
||||
}
|
||||
|
||||
|
|
|
@ -134,6 +134,12 @@
|
|||
* thread mutual exclusion, virtual memory, or cache control must be satisfied by
|
||||
* the layer above this driver.
|
||||
*
|
||||
*<b>Repeated Start</b>
|
||||
*
|
||||
* The I2C controller does not indicate completion of a receive transfer if HOLD
|
||||
* bit is set. Due to this errata, repeated start cannot be used if a receive
|
||||
* transfer is followed by any other transfer.
|
||||
*
|
||||
* <pre> MODIFICATION HISTORY:
|
||||
*
|
||||
* Ver Who Date Changes
|
||||
|
@ -170,6 +176,7 @@
|
|||
* 2.3 sk 10/07/14 Repeated start feature deleted.
|
||||
* 2.4 sk 11/03/14 Modified TimeOut Register value to 0xFF
|
||||
* in XIicPs_Reset.
|
||||
* 12/06/14 Implemented Repeated start feature.
|
||||
*
|
||||
* </pre>
|
||||
*
|
||||
|
@ -202,6 +209,7 @@ extern "C" {
|
|||
#define XIICPS_7_BIT_ADDR_OPTION 0x01 /**< 7-bit address mode */
|
||||
#define XIICPS_10_BIT_ADDR_OPTION 0x02 /**< 10-bit address mode */
|
||||
#define XIICPS_SLAVE_MON_OPTION 0x04 /**< Slave monitor mode */
|
||||
#define XIICPS_REP_START_OPTION 0x08 /**< Repeated Start */
|
||||
/*@}*/
|
||||
|
||||
/** @name Callback events
|
||||
|
@ -277,6 +285,7 @@ typedef struct {
|
|||
|
||||
int UpdateTxSize; /* If tx size register has to be updated */
|
||||
int IsSend; /* Whether master is sending or receiving */
|
||||
int IsRepeatedStart; /* Indicates if user set repeated start */
|
||||
|
||||
XIicPs_IntrHandler StatusHandler; /* Event handler function */
|
||||
void *CallBackRef; /* Callback reference for event handler */
|
||||
|
|
|
@ -56,6 +56,7 @@
|
|||
* 2.3 sk 10/06/14 Fill transmit fifo before address register when sending.
|
||||
* Replaced XIICPS_DATA_INTR_DEPTH with XIICPS_FIFO_DEPTH.
|
||||
* Repeated start feature removed.
|
||||
* 12/06/14 Implemented Repeated start feature.
|
||||
*
|
||||
* </pre>
|
||||
*
|
||||
|
@ -116,21 +117,21 @@ void XIicPs_MasterSend(XIicPs *InstancePtr, u8 *MsgPtr, int ByteCount,
|
|||
InstancePtr->RecvBufferPtr = NULL;
|
||||
InstancePtr->IsSend = 1;
|
||||
|
||||
/*
|
||||
* Set repeated start if sending more than FIFO of data.
|
||||
*/
|
||||
if ((InstancePtr->IsRepeatedStart) ||
|
||||
(ByteCount > XIICPS_FIFO_DEPTH)) {
|
||||
XIicPs_WriteReg(BaseAddr, XIICPS_CR_OFFSET,
|
||||
XIicPs_ReadReg(BaseAddr, XIICPS_CR_OFFSET) |
|
||||
XIICPS_CR_HOLD_MASK);
|
||||
}
|
||||
|
||||
/*
|
||||
* Setup as a master sending role.
|
||||
*/
|
||||
XIicPs_SetupMaster(InstancePtr, SENDING_ROLE);
|
||||
|
||||
/*
|
||||
* Set HOLD bit if sending more than FIFO of data.
|
||||
*/
|
||||
if (ByteCount > XIICPS_FIFO_DEPTH) {
|
||||
XIicPs_WriteReg(BaseAddr, XIICPS_CR_OFFSET,
|
||||
XIicPs_ReadReg(BaseAddr, XIICPS_CR_OFFSET) |
|
||||
XIICPS_CR_HOLD_MASK);
|
||||
}
|
||||
|
||||
TransmitFifoFill(InstancePtr);
|
||||
|
||||
/*
|
||||
|
@ -181,7 +182,9 @@ void XIicPs_MasterRecv(XIicPs *InstancePtr, u8 *MsgPtr, int ByteCount,
|
|||
InstancePtr->IsSend = 0;
|
||||
InstancePtr->UpdateTxSize = 0;
|
||||
|
||||
if (ByteCount > XIICPS_FIFO_DEPTH) {
|
||||
if ((ByteCount > XIICPS_FIFO_DEPTH) ||
|
||||
(InstancePtr->IsRepeatedStart))
|
||||
{
|
||||
XIicPs_WriteReg(BaseAddr, XIICPS_CR_OFFSET,
|
||||
XIicPs_ReadReg(BaseAddr, XIICPS_CR_OFFSET) |
|
||||
XIICPS_CR_HOLD_MASK);
|
||||
|
@ -257,7 +260,8 @@ int XIicPs_MasterSendPolled(XIicPs *InstancePtr, u8 *MsgPtr,
|
|||
InstancePtr->SendBufferPtr = MsgPtr;
|
||||
InstancePtr->SendByteCount = ByteCount;
|
||||
|
||||
if (ByteCount > XIICPS_FIFO_DEPTH) {
|
||||
if ((InstancePtr->IsRepeatedStart) ||
|
||||
(ByteCount > XIICPS_FIFO_DEPTH)) {
|
||||
XIicPs_WriteReg(BaseAddr, XIICPS_CR_OFFSET,
|
||||
XIicPs_ReadReg(BaseAddr, XIICPS_CR_OFFSET) |
|
||||
XIICPS_CR_HOLD_MASK);
|
||||
|
@ -323,9 +327,11 @@ int XIicPs_MasterSendPolled(XIicPs *InstancePtr, u8 *MsgPtr,
|
|||
}
|
||||
}
|
||||
|
||||
XIicPs_WriteReg(BaseAddr, XIICPS_CR_OFFSET,
|
||||
XIicPs_ReadReg(BaseAddr,XIICPS_CR_OFFSET) &
|
||||
(~XIICPS_CR_HOLD_MASK));
|
||||
if (!(InstancePtr->IsRepeatedStart)) {
|
||||
XIicPs_WriteReg(BaseAddr, XIICPS_CR_OFFSET,
|
||||
XIicPs_ReadReg(BaseAddr,XIICPS_CR_OFFSET) &
|
||||
(~XIICPS_CR_HOLD_MASK));
|
||||
}
|
||||
|
||||
return XST_SUCCESS;
|
||||
}
|
||||
|
@ -372,15 +378,17 @@ int XIicPs_MasterRecvPolled(XIicPs *InstancePtr, u8 *MsgPtr,
|
|||
InstancePtr->RecvBufferPtr = MsgPtr;
|
||||
InstancePtr->RecvByteCount = ByteCount;
|
||||
|
||||
XIicPs_SetupMaster(InstancePtr, RECVING_ROLE);
|
||||
|
||||
if(ByteCount > XIICPS_FIFO_DEPTH) {
|
||||
if((ByteCount > XIICPS_FIFO_DEPTH) ||
|
||||
(InstancePtr->IsRepeatedStart))
|
||||
{
|
||||
XIicPs_WriteReg(BaseAddr, XIICPS_CR_OFFSET,
|
||||
XIicPs_ReadReg(BaseAddr, XIICPS_CR_OFFSET) |
|
||||
XIICPS_CR_HOLD_MASK);
|
||||
IsHold = 1;
|
||||
}
|
||||
|
||||
XIicPs_SetupMaster(InstancePtr, RECVING_ROLE);
|
||||
|
||||
/*
|
||||
* Clear the interrupt status register before use it to monitor.
|
||||
*/
|
||||
|
@ -419,7 +427,8 @@ int XIicPs_MasterRecvPolled(XIicPs *InstancePtr, u8 *MsgPtr,
|
|||
|
||||
while (StatusReg & XIICPS_SR_RXDV_MASK) {
|
||||
if ((InstancePtr->RecvByteCount <
|
||||
XIICPS_DATA_INTR_DEPTH) && IsHold) {
|
||||
XIICPS_DATA_INTR_DEPTH) && IsHold &&
|
||||
(!(InstancePtr->IsRepeatedStart))) {
|
||||
IsHold = 0;
|
||||
XIicPs_WriteReg(BaseAddr, XIICPS_CR_OFFSET,
|
||||
XIicPs_ReadReg(BaseAddr,
|
||||
|
@ -465,9 +474,11 @@ int XIicPs_MasterRecvPolled(XIicPs *InstancePtr, u8 *MsgPtr,
|
|||
IntrStatusReg = XIicPs_ReadReg(BaseAddr, XIICPS_ISR_OFFSET);
|
||||
}
|
||||
|
||||
XIicPs_WriteReg(BaseAddr, XIICPS_CR_OFFSET,
|
||||
XIicPs_ReadReg(BaseAddr,XIICPS_CR_OFFSET) &
|
||||
(~XIICPS_CR_HOLD_MASK));
|
||||
if (!(InstancePtr->IsRepeatedStart)) {
|
||||
XIicPs_WriteReg(BaseAddr, XIICPS_CR_OFFSET,
|
||||
XIicPs_ReadReg(BaseAddr,XIICPS_CR_OFFSET) &
|
||||
(~XIICPS_CR_HOLD_MASK));
|
||||
}
|
||||
|
||||
if (IntrStatusReg & Intrs) {
|
||||
return XST_FAILURE;
|
||||
|
@ -674,7 +685,8 @@ void XIicPs_MasterInterruptHandler(XIicPs *InstancePtr)
|
|||
while (XIicPs_ReadReg(BaseAddr, XIICPS_SR_OFFSET) &
|
||||
XIICPS_SR_RXDV_MASK) {
|
||||
if ((InstancePtr->RecvByteCount <
|
||||
XIICPS_DATA_INTR_DEPTH) && IsHold) {
|
||||
XIICPS_DATA_INTR_DEPTH) && IsHold &&
|
||||
(!(InstancePtr->IsRepeatedStart))) {
|
||||
IsHold = 0;
|
||||
XIicPs_WriteReg(BaseAddr, XIICPS_CR_OFFSET,
|
||||
XIicPs_ReadReg(BaseAddr,
|
||||
|
@ -724,10 +736,12 @@ void XIicPs_MasterInterruptHandler(XIicPs *InstancePtr)
|
|||
* If all done, tell the application.
|
||||
*/
|
||||
if (InstancePtr->RecvByteCount == 0){
|
||||
XIicPs_WriteReg(BaseAddr, XIICPS_CR_OFFSET,
|
||||
XIicPs_ReadReg(BaseAddr,
|
||||
XIICPS_CR_OFFSET) &
|
||||
(~XIICPS_CR_HOLD_MASK));
|
||||
if (!(InstancePtr->IsRepeatedStart)) {
|
||||
XIicPs_WriteReg(BaseAddr, XIICPS_CR_OFFSET,
|
||||
XIicPs_ReadReg(BaseAddr,
|
||||
XIICPS_CR_OFFSET) &
|
||||
(~XIICPS_CR_HOLD_MASK));
|
||||
}
|
||||
StatusEvent |= XIICPS_EVENT_COMPLETE_RECV;
|
||||
}
|
||||
}
|
||||
|
@ -741,10 +755,12 @@ void XIicPs_MasterInterruptHandler(XIicPs *InstancePtr)
|
|||
}
|
||||
|
||||
if (0 != (IntrStatusReg & XIICPS_IXR_NACK_MASK)) {
|
||||
XIicPs_WriteReg(BaseAddr, XIICPS_CR_OFFSET,
|
||||
XIicPs_ReadReg(BaseAddr,
|
||||
XIICPS_CR_OFFSET) &
|
||||
(~XIICPS_CR_HOLD_MASK));
|
||||
if (!(InstancePtr->IsRepeatedStart)) {
|
||||
XIicPs_WriteReg(BaseAddr, XIICPS_CR_OFFSET,
|
||||
XIicPs_ReadReg(BaseAddr,
|
||||
XIICPS_CR_OFFSET) &
|
||||
(~XIICPS_CR_HOLD_MASK));
|
||||
}
|
||||
StatusEvent |= XIICPS_EVENT_NACK;
|
||||
}
|
||||
|
||||
|
@ -754,10 +770,12 @@ void XIicPs_MasterInterruptHandler(XIicPs *InstancePtr)
|
|||
if (0 != (IntrStatusReg & (XIICPS_IXR_NACK_MASK |
|
||||
XIICPS_IXR_ARB_LOST_MASK | XIICPS_IXR_RX_UNF_MASK |
|
||||
XIICPS_IXR_TX_OVR_MASK | XIICPS_IXR_RX_OVR_MASK))) {
|
||||
XIicPs_WriteReg(BaseAddr, XIICPS_CR_OFFSET,
|
||||
XIicPs_ReadReg(BaseAddr,
|
||||
XIICPS_CR_OFFSET) &
|
||||
(~XIICPS_CR_HOLD_MASK));
|
||||
if (!(InstancePtr->IsRepeatedStart)) {
|
||||
XIicPs_WriteReg(BaseAddr, XIICPS_CR_OFFSET,
|
||||
XIicPs_ReadReg(BaseAddr,
|
||||
XIICPS_CR_OFFSET) &
|
||||
(~XIICPS_CR_HOLD_MASK));
|
||||
}
|
||||
StatusEvent |= XIICPS_EVENT_ERROR;
|
||||
}
|
||||
|
||||
|
@ -800,7 +818,7 @@ static int XIicPs_SetupMaster(XIicPs *InstancePtr, int Role)
|
|||
|
||||
|
||||
/*
|
||||
* Only check if bus is busy when HOLD bit is not set.
|
||||
* Only check if bus is busy when repeated start option is not set.
|
||||
*/
|
||||
if ((ControlReg & XIICPS_CR_HOLD_MASK) == 0) {
|
||||
if (XIicPs_BusIsBusy(InstancePtr)) {
|
||||
|
@ -849,10 +867,18 @@ static void MasterSendData(XIicPs *InstancePtr)
|
|||
* Clear hold bit if done, so stop can be sent out.
|
||||
*/
|
||||
if (InstancePtr->SendByteCount == 0) {
|
||||
XIicPs_WriteReg(InstancePtr->Config.BaseAddress,
|
||||
XIICPS_CR_OFFSET,
|
||||
XIicPs_ReadReg(InstancePtr->Config.BaseAddress,
|
||||
XIICPS_CR_OFFSET) & ~ XIICPS_CR_HOLD_MASK);
|
||||
|
||||
/*
|
||||
* If user has enabled repeated start as an option,
|
||||
* do not disable it.
|
||||
*/
|
||||
if (!(InstancePtr->IsRepeatedStart)) {
|
||||
|
||||
XIicPs_WriteReg(InstancePtr->Config.BaseAddress,
|
||||
XIICPS_CR_OFFSET,
|
||||
XIicPs_ReadReg(InstancePtr->Config.BaseAddress,
|
||||
XIICPS_CR_OFFSET) & ~ XIICPS_CR_HOLD_MASK);
|
||||
}
|
||||
}
|
||||
|
||||
return;
|
||||
|
|
|
@ -51,6 +51,7 @@
|
|||
* selected. This is a hardware limitation. CR#779290.
|
||||
* 2.1 hk 04/24/14 Fix for CR# 761060 - provision for repeated start.
|
||||
* 2.3 sk 10/07/14 Repeated start feature removed.
|
||||
* 2.4 sk 12/06/14 Implemented Repeated start feature.
|
||||
*
|
||||
* </pre>
|
||||
*
|
||||
|
@ -87,6 +88,7 @@ static OptionsMap OptionsTable[] = {
|
|||
{XIICPS_7_BIT_ADDR_OPTION, XIICPS_CR_NEA_MASK},
|
||||
{XIICPS_10_BIT_ADDR_OPTION, XIICPS_CR_NEA_MASK},
|
||||
{XIICPS_SLAVE_MON_OPTION, XIICPS_CR_SLVMON_MASK},
|
||||
{XIICPS_REP_START_OPTION, XIICPS_CR_HOLD_MASK},
|
||||
};
|
||||
|
||||
#define XIICPS_NUM_OPTIONS (sizeof(OptionsTable) / sizeof(OptionsMap))
|
||||
|
@ -124,6 +126,16 @@ int XIicPs_SetOptions(XIicPs *InstancePtr, u32 Options)
|
|||
ControlReg = XIicPs_ReadReg(InstancePtr->Config.BaseAddress,
|
||||
XIICPS_CR_OFFSET);
|
||||
|
||||
/*
|
||||
* If repeated start option is requested, set the flag.
|
||||
* The hold bit in CR will be written by driver when the next transfer
|
||||
* is initiated.
|
||||
*/
|
||||
if (Options & XIICPS_REP_START_OPTION) {
|
||||
InstancePtr->IsRepeatedStart = 1;
|
||||
Options = Options & (~XIICPS_REP_START_OPTION);
|
||||
}
|
||||
|
||||
/*
|
||||
* Loop through the options table, turning the option on.
|
||||
*/
|
||||
|
@ -193,6 +205,16 @@ int XIicPs_ClearOptions(XIicPs *InstancePtr, u32 Options)
|
|||
ControlReg = XIicPs_ReadReg(InstancePtr->Config.BaseAddress,
|
||||
XIICPS_CR_OFFSET);
|
||||
|
||||
/*
|
||||
* If repeated start option is cleared, set the flag.
|
||||
* The hold bit in CR will be cleared by driver when the
|
||||
* following transfer ends.
|
||||
*/
|
||||
if (Options & XIICPS_REP_START_OPTION) {
|
||||
InstancePtr->IsRepeatedStart = 0;
|
||||
Options = Options & (~XIICPS_REP_START_OPTION);
|
||||
}
|
||||
|
||||
/*
|
||||
* Loop through the options table and clear the specified options.
|
||||
*/
|
||||
|
@ -276,6 +298,9 @@ u32 XIicPs_GetOptions(XIicPs *InstancePtr)
|
|||
}
|
||||
}
|
||||
|
||||
if (InstancePtr->IsRepeatedStart) {
|
||||
OptionsFlag |= XIICPS_REP_START_OPTION;
|
||||
}
|
||||
return OptionsFlag;
|
||||
}
|
||||
|
||||
|
|
Loading…
Add table
Reference in a new issue