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
36 * Handles slave transfers
38 * <pre> MODIFICATION HISTORY:
40 * Ver Who Date Changes
41 * ----- -- -------- ---------------------------------------------
42 * 1.00a jz 01/30/10 First release
43 * 1.04a kpc 08/30/13 Avoid buffer overwrite in SlaveRecvData function
44 * 3.00 sk 01/31/15 Modified the code according to MISRAC 2012 Compliant.
48 ******************************************************************************/
50 /***************************** Include Files *********************************/
53 /************************** Constant Definitions *****************************/
55 /**************************** Type Definitions *******************************/
57 /***************** Macros (Inline Functions) Definitions *********************/
59 /************************** Function Prototypes ******************************/
60 extern s32 TransmitFifoFill(XIicPs *InstancePtr);
62 static s32 SlaveRecvData(XIicPs *InstancePtr);
64 /************************* Variable Definitions *****************************/
66 /*****************************************************************************/
68 * This function sets up the device to be a slave.
70 * @param InstancePtr is a pointer to the XIicPs instance.
71 * @param SlaveAddr is the address of the slave we are receiving from.
76 * Interrupt is always enabled no matter the tranfer is interrupt-
77 * driven or polled mode. Whether device will be interrupted or not
78 * depends on whether the device is connected to an interrupt
79 * controller and interrupt for the device is enabled.
81 ****************************************************************************/
82 void XIicPs_SetupSlave(XIicPs *InstancePtr, u16 SlaveAddr)
87 Xil_AssertVoid(InstancePtr != NULL);
88 Xil_AssertVoid(InstancePtr->IsReady == (u32)XIL_COMPONENT_IS_READY);
89 Xil_AssertVoid(XIICPS_ADDR_MASK >= SlaveAddr);
91 BaseAddr = InstancePtr->Config.BaseAddress;
93 ControlReg = XIicPs_In32(BaseAddr + XIICPS_CR_OFFSET);
96 * Set up master, AckEn, nea and also clear fifo.
98 ControlReg |= (u32)XIICPS_CR_ACKEN_MASK | (u32)XIICPS_CR_CLR_FIFO_MASK;
99 ControlReg |= (u32)XIICPS_CR_NEA_MASK;
100 ControlReg &= (u32)(~XIICPS_CR_MS_MASK);
102 XIicPs_WriteReg(BaseAddr, XIICPS_CR_OFFSET,
105 XIicPs_DisableAllInterrupts(BaseAddr);
107 XIicPs_WriteReg(InstancePtr->Config.BaseAddress,
108 XIICPS_ADDR_OFFSET, (u32)SlaveAddr);
113 /*****************************************************************************/
115 * This function setup a slave interrupt-driven send. It set the repeated
116 * start for the device is the tranfer size is larger than FIFO depth.
117 * Data processing for the send is initiated by the interrupt handler.
119 * @param InstancePtr is a pointer to the XIicPs instance.
120 * @param MsgPtr is the pointer to the send buffer.
121 * @param ByteCount is the number of bytes to be sent.
125 * @note This send routine is for interrupt-driven transfer only.
127 ****************************************************************************/
128 void XIicPs_SlaveSend(XIicPs *InstancePtr, u8 *MsgPtr, s32 ByteCount)
133 * Assert validates the input arguments
135 Xil_AssertVoid(InstancePtr != NULL);
136 Xil_AssertVoid(MsgPtr != NULL);
137 Xil_AssertVoid(InstancePtr->IsReady == (u32)XIL_COMPONENT_IS_READY);
140 BaseAddr = InstancePtr->Config.BaseAddress;
141 InstancePtr->SendBufferPtr = MsgPtr;
142 InstancePtr->SendByteCount = ByteCount;
143 InstancePtr->RecvBufferPtr = NULL;
145 XIicPs_EnableInterrupts(BaseAddr,
146 (u32)XIICPS_IXR_DATA_MASK | (u32)XIICPS_IXR_COMP_MASK |
147 (u32)XIICPS_IXR_TO_MASK | (u32)XIICPS_IXR_NACK_MASK |
148 (u32)XIICPS_IXR_TX_OVR_MASK);
151 /*****************************************************************************/
153 * This function setup a slave interrupt-driven receive.
154 * Data processing for the receive is handled by the interrupt handler.
156 * @param InstancePtr is a pointer to the XIicPs instance.
157 * @param MsgPtr is the pointer to the receive buffer.
158 * @param ByteCount is the number of bytes to be received.
162 * @note This routine is for interrupt-driven transfer only.
164 ****************************************************************************/
165 void XIicPs_SlaveRecv(XIicPs *InstancePtr, u8 *MsgPtr, s32 ByteCount)
168 * Assert validates the input arguments.
170 Xil_AssertVoid(InstancePtr != NULL);
171 Xil_AssertVoid(MsgPtr != NULL);
172 Xil_AssertVoid(InstancePtr->IsReady == (u32)XIL_COMPONENT_IS_READY);
175 InstancePtr->RecvBufferPtr = MsgPtr;
176 InstancePtr->RecvByteCount = ByteCount;
177 InstancePtr->SendBufferPtr = NULL;
179 XIicPs_EnableInterrupts(InstancePtr->Config.BaseAddress,
180 (u32)XIICPS_IXR_DATA_MASK | (u32)XIICPS_IXR_COMP_MASK |
181 (u32)XIICPS_IXR_NACK_MASK | (u32)XIICPS_IXR_TO_MASK |
182 (u32)XIICPS_IXR_RX_OVR_MASK | (u32)XIICPS_IXR_RX_UNF_MASK);
186 /*****************************************************************************/
188 * This function sends a buffer in polled mode as a slave.
190 * @param InstancePtr is a pointer to the XIicPs instance.
191 * @param MsgPtr is the pointer to the send buffer.
192 * @param ByteCount is the number of bytes to be sent.
195 * - XST_SUCCESS if everything went well.
196 * - XST_FAILURE if master sends us data or master terminates the
197 * transfer before all data has sent out.
199 * @note This send routine is for polled mode transfer only.
201 ****************************************************************************/
202 s32 XIicPs_SlaveSendPolled(XIicPs *InstancePtr, u8 *MsgPtr, s32 ByteCount)
210 s32 Status = (s32)XST_SUCCESS;
214 * Assert validates the input arguments.
216 Xil_AssertNonvoid(InstancePtr != NULL);
217 Xil_AssertNonvoid(MsgPtr != NULL);
218 Xil_AssertNonvoid(InstancePtr->IsReady == (u32)XIL_COMPONENT_IS_READY);
220 BaseAddr = InstancePtr->Config.BaseAddress;
221 InstancePtr->SendBufferPtr = MsgPtr;
222 InstancePtr->SendByteCount = ByteCount;
225 * Use RXRW bit in status register to wait master to start a read.
227 StatusReg = XIicPs_ReadReg(BaseAddr, XIICPS_SR_OFFSET);
228 while (((StatusReg & XIICPS_SR_RXRW_MASK) == 0U) &&
232 * If master tries to send us data, it is an error.
234 if ((StatusReg & XIICPS_SR_RXDV_MASK) != 0x0U) {
238 StatusReg = XIicPs_ReadReg(BaseAddr, XIICPS_SR_OFFSET);
242 Status = (s32)XST_FAILURE;
246 * Clear the interrupt status register.
248 IntrStatusReg = XIicPs_ReadReg(BaseAddr, XIICPS_ISR_OFFSET);
249 XIicPs_WriteReg(BaseAddr, XIICPS_ISR_OFFSET, IntrStatusReg);
252 * Send data as long as there is more data to send and
253 * there are no errors.
255 Value = (InstancePtr->SendByteCount > (s32)0) &&
257 while (Value != (u32)0x00U) {
260 * Find out how many can be sent.
262 BytesToSend = InstancePtr->SendByteCount;
263 if (BytesToSend > (s32)(XIICPS_FIFO_DEPTH)) {
264 BytesToSend = (s32)(XIICPS_FIFO_DEPTH);
267 for(Tmp = 0; Tmp < BytesToSend; Tmp ++) {
268 XIicPs_SendByte(InstancePtr);
271 StatusReg = XIicPs_ReadReg(BaseAddr, XIICPS_SR_OFFSET);
274 * Wait for master to read the data out of fifo.
276 while (((StatusReg & XIICPS_SR_TXDV_MASK) != (u32)0x00U) &&
280 * If master terminates the transfer before all data is
281 * sent, it is an error.
283 IntrStatusReg = XIicPs_ReadReg(BaseAddr,
285 if ((IntrStatusReg & XIICPS_IXR_NACK_MASK) != 0x0U) {
291 XIicPs_WriteReg(BaseAddr, XIICPS_ISR_OFFSET,
294 StatusReg = XIicPs_ReadReg(BaseAddr,
297 Value = (InstancePtr->SendByteCount > (s32)0U) &&
302 Status = (s32)XST_FAILURE;
307 /*****************************************************************************/
309 * This function receives a buffer in polled mode as a slave.
311 * @param InstancePtr is a pointer to the XIicPs instance.
312 * @param MsgPtr is the pointer to the receive buffer.
313 * @param ByteCount is the number of bytes to be received.
316 * - XST_SUCCESS if everything went well.
317 * - XST_FAILURE if timed out.
319 * @note This receive routine is for polled mode transfer only.
321 ****************************************************************************/
322 s32 XIicPs_SlaveRecvPolled(XIicPs *InstancePtr, u8 *MsgPtr, s32 ByteCount)
330 * Assert validates the input arguments.
332 Xil_AssertNonvoid(InstancePtr != NULL);
333 Xil_AssertNonvoid(MsgPtr != NULL);
334 Xil_AssertNonvoid(InstancePtr->IsReady == (u32)XIL_COMPONENT_IS_READY);
336 BaseAddr = InstancePtr->Config.BaseAddress;
337 InstancePtr->RecvBufferPtr = MsgPtr;
338 InstancePtr->RecvByteCount = ByteCount;
340 StatusReg = XIicPs_ReadReg(BaseAddr, XIICPS_SR_OFFSET);
343 * Clear the interrupt status register.
345 IntrStatusReg = XIicPs_ReadReg(BaseAddr, XIICPS_ISR_OFFSET);
346 XIicPs_WriteReg(BaseAddr, XIICPS_ISR_OFFSET, IntrStatusReg);
349 * Clear the status register.
351 StatusReg = XIicPs_ReadReg(BaseAddr, XIICPS_SR_OFFSET);
352 XIicPs_WriteReg(BaseAddr, XIICPS_SR_OFFSET, StatusReg);
354 StatusReg = XIicPs_ReadReg(BaseAddr, XIICPS_SR_OFFSET);
355 Count = InstancePtr->RecvByteCount;
356 while (Count > (s32)0) {
358 /* Wait for master to put data */
359 while ((StatusReg & XIICPS_SR_RXDV_MASK) == 0U) {
360 StatusReg = XIicPs_ReadReg(BaseAddr, XIICPS_SR_OFFSET);
363 * If master terminates the transfer before we get all
364 * the data or the master tries to read from us,
367 IntrStatusReg = XIicPs_ReadReg(BaseAddr,
369 if (((IntrStatusReg & (XIICPS_IXR_DATA_MASK |
370 XIICPS_IXR_COMP_MASK))!=0x0U) &&
371 ((StatusReg & XIICPS_SR_RXDV_MASK) == 0U) &&
372 ((InstancePtr->RecvByteCount > 0) != 0x0U)) {
374 return (s32)XST_FAILURE;
378 * Clear the interrupt status register.
380 XIicPs_WriteReg(BaseAddr, XIICPS_ISR_OFFSET,
385 * Read all data from FIFO.
387 while (((StatusReg & XIICPS_SR_RXDV_MASK)!=0x0U) &&
388 ((InstancePtr->RecvByteCount > 0) != 0x0U)){
390 XIicPs_RecvByte(InstancePtr);
392 StatusReg = XIicPs_ReadReg(BaseAddr,
395 Count = InstancePtr->RecvByteCount;
398 return (s32)XST_SUCCESS;
401 /*****************************************************************************/
403 * The interrupt handler for slave mode. It does the protocol handling for
404 * the interrupt-driven transfers.
406 * Completion events and errors are signaled to upper layer for proper
411 * The interrupts that are handled are:
413 * If the instance is sending, it means that the master wants to read more
414 * data from us. Send more data, and check whether we are done with this
417 * If the instance is receiving, it means that the master has writen
418 * more data to us. Receive more data, and check whether we are done with
422 * This marks that stop sequence has been sent from the master, transfer
423 * is about to terminate. However, for receiving, the master may have
424 * written us some data, so receive that first.
426 * It is an error if the amount of transfered data is less than expected.
429 * This marks that master does not want our data. It is for send only.
432 * These interrupts are marked as error.
436 * @param InstancePtr is a pointer to the XIicPs instance.
442 ****************************************************************************/
443 void XIicPs_SlaveInterruptHandler(XIicPs *InstancePtr)
447 u32 StatusEvent = 0U;
452 * Assert validates the input arguments.
454 Xil_AssertVoid(InstancePtr != NULL);
455 Xil_AssertVoid(InstancePtr->IsReady == (u32)XIL_COMPONENT_IS_READY);
457 BaseAddr = InstancePtr->Config.BaseAddress;
460 * Read the Interrupt status register.
462 IntrStatusReg = XIicPs_ReadReg(BaseAddr, XIICPS_ISR_OFFSET);
465 * Write the status back to clear the interrupts so no events are missed
466 * while processing this interrupt.
468 XIicPs_WriteReg(BaseAddr, XIICPS_ISR_OFFSET, IntrStatusReg);
471 * Use the Mask register AND with the Interrupt Status register so
472 * disabled interrupts are not processed.
474 IntrStatusReg &= ~(XIicPs_ReadReg(BaseAddr, XIICPS_IMR_OFFSET));
477 * Determine whether the device is sending.
479 if (InstancePtr->RecvBufferPtr == NULL) {
485 * This means master wants to do more data transfers.
486 * Also check for completion of transfer, signal upper layer if done.
488 if ((u32)0U != (IntrStatusReg & XIICPS_IXR_DATA_MASK)) {
489 if (IsSend != 0x0U) {
490 LeftOver = TransmitFifoFill(InstancePtr);
492 * We may finish send here
496 XIICPS_EVENT_COMPLETE_SEND;
499 LeftOver = SlaveRecvData(InstancePtr);
501 /* We may finish the receive here */
503 StatusEvent |= XIICPS_EVENT_COMPLETE_RECV;
509 * Complete interrupt.
511 * In slave mode, it means the master has done with this transfer, so
512 * we signal the application using completion event.
514 if (0U != (IntrStatusReg & XIICPS_IXR_COMP_MASK)) {
515 if (IsSend != 0x0U) {
516 if (InstancePtr->SendByteCount > 0) {
517 StatusEvent |= XIICPS_EVENT_ERROR;
519 StatusEvent |= XIICPS_EVENT_COMPLETE_SEND;
522 LeftOver = SlaveRecvData(InstancePtr);
524 StatusEvent |= XIICPS_EVENT_ERROR;
526 StatusEvent |= XIICPS_EVENT_COMPLETE_RECV;
532 * Nack interrupt, pass this information to application.
534 if (0U != (IntrStatusReg & XIICPS_IXR_NACK_MASK)) {
535 StatusEvent |= XIICPS_EVENT_NACK;
539 * All other interrupts are treated as error.
541 if (0U != (IntrStatusReg & (XIICPS_IXR_TO_MASK |
542 XIICPS_IXR_RX_UNF_MASK |
543 XIICPS_IXR_TX_OVR_MASK |
544 XIICPS_IXR_RX_OVR_MASK))){
546 StatusEvent |= XIICPS_EVENT_ERROR;
550 * Signal application if there are any events.
552 if (0U != StatusEvent) {
553 InstancePtr->StatusHandler(InstancePtr->CallBackRef,
558 /*****************************************************************************/
561 * This function handles continuation of receiving data. It is invoked
562 * from interrupt handler.
564 * @param InstancePtr is a pointer to the XIicPs instance.
566 * @return Number of bytes still expected by the instance.
570 ****************************************************************************/
571 static s32 SlaveRecvData(XIicPs *InstancePtr)
576 BaseAddr = InstancePtr->Config.BaseAddress;
578 StatusReg = XIicPs_ReadReg(BaseAddr, XIICPS_SR_OFFSET);
580 while (((StatusReg & XIICPS_SR_RXDV_MASK)!=0x0U) &&
581 ((InstancePtr->RecvByteCount > 0) != 0x0U)) {
582 XIicPs_RecvByte(InstancePtr);
583 StatusReg = XIicPs_ReadReg(BaseAddr, XIICPS_SR_OFFSET);
586 return InstancePtr->RecvByteCount;