1 /******************************************************************************
3 * Copyright (C) 2010 - 2015 Xilinx, Inc. All rights reserved.
5 * Permission is hereby granted, free of charge, to any person obtaining a copy
6 * of this software and associated documentation files (the "Software"), to deal
7 * in the Software without restriction, including without limitation the rights
8 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 * copies of the Software, and to permit persons to whom the Software is
10 * furnished to do so, subject to the following conditions:
12 * The above copyright notice and this permission notice shall be included in
13 * all copies or substantial portions of the Software.
15 * Use of the Software is limited solely to applications:
16 * (a) running on a Xilinx device, or
17 * (b) that interact with a Xilinx device through a bus or interconnect.
19 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
20 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
21 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
22 * XILINX BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
23 * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF
24 * OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
27 * Except as contained in this notice, the name of the Xilinx shall not be used
28 * in advertising or otherwise to promote the sale, use or other dealings in
29 * this Software without prior written authorization from Xilinx.
31 ******************************************************************************/
32 /*****************************************************************************/
34 * @file xiicps_slave.c
35 * @addtogroup iicps_v3_0
38 * Handles slave transfers
40 * <pre> MODIFICATION HISTORY:
42 * Ver Who Date Changes
43 * ----- -- -------- ---------------------------------------------
44 * 1.00a jz 01/30/10 First release
45 * 1.04a kpc 08/30/13 Avoid buffer overwrite in SlaveRecvData function
46 * 3.00 sk 01/31/15 Modified the code according to MISRAC 2012 Compliant.
50 ******************************************************************************/
52 /***************************** Include Files *********************************/
55 /************************** Constant Definitions *****************************/
57 /**************************** Type Definitions *******************************/
59 /***************** Macros (Inline Functions) Definitions *********************/
61 /************************** Function Prototypes ******************************/
62 extern s32 TransmitFifoFill(XIicPs *InstancePtr);
64 static s32 SlaveRecvData(XIicPs *InstancePtr);
66 /************************* Variable Definitions *****************************/
68 /*****************************************************************************/
70 * This function sets up the device to be a slave.
72 * @param InstancePtr is a pointer to the XIicPs instance.
73 * @param SlaveAddr is the address of the slave we are receiving from.
78 * Interrupt is always enabled no matter the tranfer is interrupt-
79 * driven or polled mode. Whether device will be interrupted or not
80 * depends on whether the device is connected to an interrupt
81 * controller and interrupt for the device is enabled.
83 ****************************************************************************/
84 void XIicPs_SetupSlave(XIicPs *InstancePtr, u16 SlaveAddr)
89 Xil_AssertVoid(InstancePtr != NULL);
90 Xil_AssertVoid(InstancePtr->IsReady == (u32)XIL_COMPONENT_IS_READY);
91 Xil_AssertVoid(XIICPS_ADDR_MASK >= SlaveAddr);
93 BaseAddr = InstancePtr->Config.BaseAddress;
95 ControlReg = XIicPs_In32(BaseAddr + XIICPS_CR_OFFSET);
98 * Set up master, AckEn, nea and also clear fifo.
100 ControlReg |= (u32)XIICPS_CR_ACKEN_MASK | (u32)XIICPS_CR_CLR_FIFO_MASK;
101 ControlReg |= (u32)XIICPS_CR_NEA_MASK;
102 ControlReg &= (u32)(~XIICPS_CR_MS_MASK);
104 XIicPs_WriteReg(BaseAddr, XIICPS_CR_OFFSET,
107 XIicPs_DisableAllInterrupts(BaseAddr);
109 XIicPs_WriteReg(InstancePtr->Config.BaseAddress,
110 XIICPS_ADDR_OFFSET, (u32)SlaveAddr);
115 /*****************************************************************************/
117 * This function setup a slave interrupt-driven send. It set the repeated
118 * start for the device is the tranfer size is larger than FIFO depth.
119 * Data processing for the send is initiated by the interrupt handler.
121 * @param InstancePtr is a pointer to the XIicPs instance.
122 * @param MsgPtr is the pointer to the send buffer.
123 * @param ByteCount is the number of bytes to be sent.
127 * @note This send routine is for interrupt-driven transfer only.
129 ****************************************************************************/
130 void XIicPs_SlaveSend(XIicPs *InstancePtr, u8 *MsgPtr, s32 ByteCount)
135 * Assert validates the input arguments
137 Xil_AssertVoid(InstancePtr != NULL);
138 Xil_AssertVoid(MsgPtr != NULL);
139 Xil_AssertVoid(InstancePtr->IsReady == (u32)XIL_COMPONENT_IS_READY);
142 BaseAddr = InstancePtr->Config.BaseAddress;
143 InstancePtr->SendBufferPtr = MsgPtr;
144 InstancePtr->SendByteCount = ByteCount;
145 InstancePtr->RecvBufferPtr = NULL;
147 XIicPs_EnableInterrupts(BaseAddr,
148 (u32)XIICPS_IXR_DATA_MASK | (u32)XIICPS_IXR_COMP_MASK |
149 (u32)XIICPS_IXR_TO_MASK | (u32)XIICPS_IXR_NACK_MASK |
150 (u32)XIICPS_IXR_TX_OVR_MASK);
153 /*****************************************************************************/
155 * This function setup a slave interrupt-driven receive.
156 * Data processing for the receive is handled by the interrupt handler.
158 * @param InstancePtr is a pointer to the XIicPs instance.
159 * @param MsgPtr is the pointer to the receive buffer.
160 * @param ByteCount is the number of bytes to be received.
164 * @note This routine is for interrupt-driven transfer only.
166 ****************************************************************************/
167 void XIicPs_SlaveRecv(XIicPs *InstancePtr, u8 *MsgPtr, s32 ByteCount)
170 * Assert validates the input arguments.
172 Xil_AssertVoid(InstancePtr != NULL);
173 Xil_AssertVoid(MsgPtr != NULL);
174 Xil_AssertVoid(InstancePtr->IsReady == (u32)XIL_COMPONENT_IS_READY);
177 InstancePtr->RecvBufferPtr = MsgPtr;
178 InstancePtr->RecvByteCount = ByteCount;
179 InstancePtr->SendBufferPtr = NULL;
181 XIicPs_EnableInterrupts(InstancePtr->Config.BaseAddress,
182 (u32)XIICPS_IXR_DATA_MASK | (u32)XIICPS_IXR_COMP_MASK |
183 (u32)XIICPS_IXR_NACK_MASK | (u32)XIICPS_IXR_TO_MASK |
184 (u32)XIICPS_IXR_RX_OVR_MASK | (u32)XIICPS_IXR_RX_UNF_MASK);
188 /*****************************************************************************/
190 * This function sends a buffer in polled mode as a slave.
192 * @param InstancePtr is a pointer to the XIicPs instance.
193 * @param MsgPtr is the pointer to the send buffer.
194 * @param ByteCount is the number of bytes to be sent.
197 * - XST_SUCCESS if everything went well.
198 * - XST_FAILURE if master sends us data or master terminates the
199 * transfer before all data has sent out.
201 * @note This send routine is for polled mode transfer only.
203 ****************************************************************************/
204 s32 XIicPs_SlaveSendPolled(XIicPs *InstancePtr, u8 *MsgPtr, s32 ByteCount)
212 s32 Status = (s32)XST_SUCCESS;
216 * Assert validates the input arguments.
218 Xil_AssertNonvoid(InstancePtr != NULL);
219 Xil_AssertNonvoid(MsgPtr != NULL);
220 Xil_AssertNonvoid(InstancePtr->IsReady == (u32)XIL_COMPONENT_IS_READY);
222 BaseAddr = InstancePtr->Config.BaseAddress;
223 InstancePtr->SendBufferPtr = MsgPtr;
224 InstancePtr->SendByteCount = ByteCount;
227 * Use RXRW bit in status register to wait master to start a read.
229 StatusReg = XIicPs_ReadReg(BaseAddr, XIICPS_SR_OFFSET);
230 while (((StatusReg & XIICPS_SR_RXRW_MASK) == 0U) &&
234 * If master tries to send us data, it is an error.
236 if ((StatusReg & XIICPS_SR_RXDV_MASK) != 0x0U) {
240 StatusReg = XIicPs_ReadReg(BaseAddr, XIICPS_SR_OFFSET);
244 Status = (s32)XST_FAILURE;
248 * Clear the interrupt status register.
250 IntrStatusReg = XIicPs_ReadReg(BaseAddr, XIICPS_ISR_OFFSET);
251 XIicPs_WriteReg(BaseAddr, XIICPS_ISR_OFFSET, IntrStatusReg);
254 * Send data as long as there is more data to send and
255 * there are no errors.
257 Value = (InstancePtr->SendByteCount > (s32)0) &&
259 while (Value != (u32)0x00U) {
262 * Find out how many can be sent.
264 BytesToSend = InstancePtr->SendByteCount;
265 if (BytesToSend > (s32)(XIICPS_FIFO_DEPTH)) {
266 BytesToSend = (s32)(XIICPS_FIFO_DEPTH);
269 for(Tmp = 0; Tmp < BytesToSend; Tmp ++) {
270 XIicPs_SendByte(InstancePtr);
273 StatusReg = XIicPs_ReadReg(BaseAddr, XIICPS_SR_OFFSET);
276 * Wait for master to read the data out of fifo.
278 while (((StatusReg & XIICPS_SR_TXDV_MASK) != (u32)0x00U) &&
282 * If master terminates the transfer before all data is
283 * sent, it is an error.
285 IntrStatusReg = XIicPs_ReadReg(BaseAddr,
287 if ((IntrStatusReg & XIICPS_IXR_NACK_MASK) != 0x0U) {
293 XIicPs_WriteReg(BaseAddr, XIICPS_ISR_OFFSET,
296 StatusReg = XIicPs_ReadReg(BaseAddr,
299 Value = (InstancePtr->SendByteCount > (s32)0U) &&
304 Status = (s32)XST_FAILURE;
309 /*****************************************************************************/
311 * This function receives a buffer in polled mode as a slave.
313 * @param InstancePtr is a pointer to the XIicPs instance.
314 * @param MsgPtr is the pointer to the receive buffer.
315 * @param ByteCount is the number of bytes to be received.
318 * - XST_SUCCESS if everything went well.
319 * - XST_FAILURE if timed out.
321 * @note This receive routine is for polled mode transfer only.
323 ****************************************************************************/
324 s32 XIicPs_SlaveRecvPolled(XIicPs *InstancePtr, u8 *MsgPtr, s32 ByteCount)
332 * Assert validates the input arguments.
334 Xil_AssertNonvoid(InstancePtr != NULL);
335 Xil_AssertNonvoid(MsgPtr != NULL);
336 Xil_AssertNonvoid(InstancePtr->IsReady == (u32)XIL_COMPONENT_IS_READY);
338 BaseAddr = InstancePtr->Config.BaseAddress;
339 InstancePtr->RecvBufferPtr = MsgPtr;
340 InstancePtr->RecvByteCount = ByteCount;
342 StatusReg = XIicPs_ReadReg(BaseAddr, XIICPS_SR_OFFSET);
345 * Clear the interrupt status register.
347 IntrStatusReg = XIicPs_ReadReg(BaseAddr, XIICPS_ISR_OFFSET);
348 XIicPs_WriteReg(BaseAddr, XIICPS_ISR_OFFSET, IntrStatusReg);
351 * Clear the status register.
353 StatusReg = XIicPs_ReadReg(BaseAddr, XIICPS_SR_OFFSET);
354 XIicPs_WriteReg(BaseAddr, XIICPS_SR_OFFSET, StatusReg);
356 StatusReg = XIicPs_ReadReg(BaseAddr, XIICPS_SR_OFFSET);
357 Count = InstancePtr->RecvByteCount;
358 while (Count > (s32)0) {
360 /* Wait for master to put data */
361 while ((StatusReg & XIICPS_SR_RXDV_MASK) == 0U) {
362 StatusReg = XIicPs_ReadReg(BaseAddr, XIICPS_SR_OFFSET);
365 * If master terminates the transfer before we get all
366 * the data or the master tries to read from us,
369 IntrStatusReg = XIicPs_ReadReg(BaseAddr,
371 if (((IntrStatusReg & (XIICPS_IXR_DATA_MASK |
372 XIICPS_IXR_COMP_MASK))!=0x0U) &&
373 ((StatusReg & XIICPS_SR_RXDV_MASK) == 0U) &&
374 ((InstancePtr->RecvByteCount > 0) != 0x0U)) {
376 return (s32)XST_FAILURE;
380 * Clear the interrupt status register.
382 XIicPs_WriteReg(BaseAddr, XIICPS_ISR_OFFSET,
387 * Read all data from FIFO.
389 while (((StatusReg & XIICPS_SR_RXDV_MASK)!=0x0U) &&
390 ((InstancePtr->RecvByteCount > 0) != 0x0U)){
392 XIicPs_RecvByte(InstancePtr);
394 StatusReg = XIicPs_ReadReg(BaseAddr,
397 Count = InstancePtr->RecvByteCount;
400 return (s32)XST_SUCCESS;
403 /*****************************************************************************/
405 * The interrupt handler for slave mode. It does the protocol handling for
406 * the interrupt-driven transfers.
408 * Completion events and errors are signaled to upper layer for proper
413 * The interrupts that are handled are:
415 * If the instance is sending, it means that the master wants to read more
416 * data from us. Send more data, and check whether we are done with this
419 * If the instance is receiving, it means that the master has writen
420 * more data to us. Receive more data, and check whether we are done with
424 * This marks that stop sequence has been sent from the master, transfer
425 * is about to terminate. However, for receiving, the master may have
426 * written us some data, so receive that first.
428 * It is an error if the amount of transfered data is less than expected.
431 * This marks that master does not want our data. It is for send only.
434 * These interrupts are marked as error.
438 * @param InstancePtr is a pointer to the XIicPs instance.
444 ****************************************************************************/
445 void XIicPs_SlaveInterruptHandler(XIicPs *InstancePtr)
449 u32 StatusEvent = 0U;
454 * Assert validates the input arguments.
456 Xil_AssertVoid(InstancePtr != NULL);
457 Xil_AssertVoid(InstancePtr->IsReady == (u32)XIL_COMPONENT_IS_READY);
459 BaseAddr = InstancePtr->Config.BaseAddress;
462 * Read the Interrupt status register.
464 IntrStatusReg = XIicPs_ReadReg(BaseAddr, XIICPS_ISR_OFFSET);
467 * Write the status back to clear the interrupts so no events are missed
468 * while processing this interrupt.
470 XIicPs_WriteReg(BaseAddr, XIICPS_ISR_OFFSET, IntrStatusReg);
473 * Use the Mask register AND with the Interrupt Status register so
474 * disabled interrupts are not processed.
476 IntrStatusReg &= ~(XIicPs_ReadReg(BaseAddr, XIICPS_IMR_OFFSET));
479 * Determine whether the device is sending.
481 if (InstancePtr->RecvBufferPtr == NULL) {
487 * This means master wants to do more data transfers.
488 * Also check for completion of transfer, signal upper layer if done.
490 if ((u32)0U != (IntrStatusReg & XIICPS_IXR_DATA_MASK)) {
491 if (IsSend != 0x0U) {
492 LeftOver = TransmitFifoFill(InstancePtr);
494 * We may finish send here
498 XIICPS_EVENT_COMPLETE_SEND;
501 LeftOver = SlaveRecvData(InstancePtr);
503 /* We may finish the receive here */
505 StatusEvent |= XIICPS_EVENT_COMPLETE_RECV;
511 * Complete interrupt.
513 * In slave mode, it means the master has done with this transfer, so
514 * we signal the application using completion event.
516 if (0U != (IntrStatusReg & XIICPS_IXR_COMP_MASK)) {
517 if (IsSend != 0x0U) {
518 if (InstancePtr->SendByteCount > 0) {
519 StatusEvent |= XIICPS_EVENT_ERROR;
521 StatusEvent |= XIICPS_EVENT_COMPLETE_SEND;
524 LeftOver = SlaveRecvData(InstancePtr);
526 StatusEvent |= XIICPS_EVENT_ERROR;
528 StatusEvent |= XIICPS_EVENT_COMPLETE_RECV;
534 * Nack interrupt, pass this information to application.
536 if (0U != (IntrStatusReg & XIICPS_IXR_NACK_MASK)) {
537 StatusEvent |= XIICPS_EVENT_NACK;
541 * All other interrupts are treated as error.
543 if (0U != (IntrStatusReg & (XIICPS_IXR_TO_MASK |
544 XIICPS_IXR_RX_UNF_MASK |
545 XIICPS_IXR_TX_OVR_MASK |
546 XIICPS_IXR_RX_OVR_MASK))){
548 StatusEvent |= XIICPS_EVENT_ERROR;
552 * Signal application if there are any events.
554 if (0U != StatusEvent) {
555 InstancePtr->StatusHandler(InstancePtr->CallBackRef,
560 /*****************************************************************************/
563 * This function handles continuation of receiving data. It is invoked
564 * from interrupt handler.
566 * @param InstancePtr is a pointer to the XIicPs instance.
568 * @return Number of bytes still expected by the instance.
572 ****************************************************************************/
573 static s32 SlaveRecvData(XIicPs *InstancePtr)
578 BaseAddr = InstancePtr->Config.BaseAddress;
580 StatusReg = XIicPs_ReadReg(BaseAddr, XIICPS_SR_OFFSET);
582 while (((StatusReg & XIICPS_SR_RXDV_MASK)!=0x0U) &&
583 ((InstancePtr->RecvByteCount > 0) != 0x0U)) {
584 XIicPs_RecvByte(InstancePtr);
585 StatusReg = XIicPs_ReadReg(BaseAddr, XIICPS_SR_OFFSET);
588 return InstancePtr->RecvByteCount;