1 /******************************************************************************
3 * Copyright (C) 2010 - 2014 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_v2_1
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
49 ******************************************************************************/
51 /***************************** Include Files *********************************/
54 /************************** Constant Definitions *****************************/
56 /**************************** Type Definitions *******************************/
58 /***************** Macros (Inline Functions) Definitions *********************/
60 /************************** Function Prototypes ******************************/
61 extern int TransmitFifoFill(XIicPs *InstancePtr);
63 static int SlaveRecvData(XIicPs *InstancePtr);
65 /************************* Variable Definitions *****************************/
67 /*****************************************************************************/
69 * This function sets up the device to be a slave.
71 * @param InstancePtr is a pointer to the XIicPs instance.
72 * @param SlaveAddr is the address of the slave we are receiving from.
77 * Interrupt is always enabled no matter the tranfer is interrupt-
78 * driven or polled mode. Whether device will be interrupted or not
79 * depends on whether the device is connected to an interrupt
80 * controller and interrupt for the device is enabled.
82 ****************************************************************************/
83 void XIicPs_SetupSlave(XIicPs *InstancePtr, u16 SlaveAddr)
85 volatile u32 ControlReg;
88 Xil_AssertVoid(InstancePtr != NULL);
89 Xil_AssertVoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY);
90 Xil_AssertVoid(XIICPS_ADDR_MASK >= SlaveAddr);
92 BaseAddr = InstancePtr->Config.BaseAddress;
94 ControlReg = XIicPs_In32(BaseAddr + XIICPS_CR_OFFSET);
97 * Set up master, AckEn, nea and also clear fifo.
99 ControlReg |= XIICPS_CR_ACKEN_MASK | XIICPS_CR_CLR_FIFO_MASK;
100 ControlReg |= XIICPS_CR_NEA_MASK;
101 ControlReg &= ~XIICPS_CR_MS_MASK;
103 XIicPs_WriteReg(BaseAddr, XIICPS_CR_OFFSET,
106 XIicPs_DisableAllInterrupts(BaseAddr);
108 XIicPs_WriteReg(InstancePtr->Config.BaseAddress,
109 XIICPS_ADDR_OFFSET, SlaveAddr);
114 /*****************************************************************************/
116 * This function setup a slave interrupt-driven send. It set the repeated
117 * start for the device is the tranfer size is larger than FIFO depth.
118 * Data processing for the send is initiated by the interrupt handler.
120 * @param InstancePtr is a pointer to the XIicPs instance.
121 * @param MsgPtr is the pointer to the send buffer.
122 * @param ByteCount is the number of bytes to be sent.
126 * @note This send routine is for interrupt-driven transfer only.
128 ****************************************************************************/
129 void XIicPs_SlaveSend(XIicPs *InstancePtr, u8 *MsgPtr, int ByteCount)
134 * Assert validates the input arguments
136 Xil_AssertVoid(InstancePtr != NULL);
137 Xil_AssertVoid(MsgPtr != NULL);
138 Xil_AssertVoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY);
141 BaseAddr = InstancePtr->Config.BaseAddress;
142 InstancePtr->SendBufferPtr = MsgPtr;
143 InstancePtr->SendByteCount = ByteCount;
144 InstancePtr->RecvBufferPtr = NULL;
146 XIicPs_EnableInterrupts(BaseAddr,
147 XIICPS_IXR_DATA_MASK | XIICPS_IXR_COMP_MASK |
148 XIICPS_IXR_TO_MASK | XIICPS_IXR_NACK_MASK |
149 XIICPS_IXR_TX_OVR_MASK);
152 /*****************************************************************************/
154 * This function setup a slave interrupt-driven receive.
155 * Data processing for the receive is handled by the interrupt handler.
157 * @param InstancePtr is a pointer to the XIicPs instance.
158 * @param MsgPtr is the pointer to the receive buffer.
159 * @param ByteCount is the number of bytes to be received.
163 * @note This routine is for interrupt-driven transfer only.
165 ****************************************************************************/
166 void XIicPs_SlaveRecv(XIicPs *InstancePtr, u8 *MsgPtr, int ByteCount)
169 * Assert validates the input arguments.
171 Xil_AssertVoid(InstancePtr != NULL);
172 Xil_AssertVoid(MsgPtr != NULL);
173 Xil_AssertVoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY);
176 InstancePtr->RecvBufferPtr = MsgPtr;
177 InstancePtr->RecvByteCount = ByteCount;
178 InstancePtr->SendBufferPtr = NULL;
180 XIicPs_EnableInterrupts(InstancePtr->Config.BaseAddress,
181 XIICPS_IXR_DATA_MASK | XIICPS_IXR_COMP_MASK |
182 XIICPS_IXR_NACK_MASK | XIICPS_IXR_TO_MASK |
183 XIICPS_IXR_RX_OVR_MASK | XIICPS_IXR_RX_UNF_MASK);
187 /*****************************************************************************/
189 * This function sends a buffer in polled mode as a slave.
191 * @param InstancePtr is a pointer to the XIicPs instance.
192 * @param MsgPtr is the pointer to the send buffer.
193 * @param ByteCount is the number of bytes to be sent.
196 * - XST_SUCCESS if everything went well.
197 * - XST_FAILURE if master sends us data or master terminates the
198 * transfer before all data has sent out.
200 * @note This send routine is for polled mode transfer only.
202 ****************************************************************************/
203 int XIicPs_SlaveSendPolled(XIicPs *InstancePtr, u8 *MsgPtr, int ByteCount)
205 volatile u32 IntrStatusReg;
206 volatile u32 StatusReg;
213 * Assert validates the input arguments.
215 Xil_AssertNonvoid(InstancePtr != NULL);
216 Xil_AssertNonvoid(MsgPtr != NULL);
217 Xil_AssertNonvoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY);
219 BaseAddr = InstancePtr->Config.BaseAddress;
220 InstancePtr->SendBufferPtr = MsgPtr;
221 InstancePtr->SendByteCount = ByteCount;
224 * Use RXRW bit in status register to wait master to start a read.
226 StatusReg = XIicPs_ReadReg(BaseAddr, XIICPS_SR_OFFSET);
227 while (((StatusReg & XIICPS_SR_RXRW_MASK) == 0) && (!Error)) {
230 * If master tries to send us data, it is an error.
232 if (StatusReg & XIICPS_SR_RXDV_MASK) {
236 StatusReg = XIicPs_ReadReg(BaseAddr, XIICPS_SR_OFFSET);
244 * Clear the interrupt status register.
246 IntrStatusReg = XIicPs_ReadReg(BaseAddr, XIICPS_ISR_OFFSET);
247 XIicPs_WriteReg(BaseAddr, XIICPS_ISR_OFFSET, IntrStatusReg);
250 * Send data as long as there is more data to send and
251 * there are no errors.
253 while ((InstancePtr->SendByteCount > 0) && (!Error)){
256 * Find out how many can be sent.
258 BytesToSend = InstancePtr->SendByteCount;
259 if (BytesToSend > XIICPS_FIFO_DEPTH) {
260 BytesToSend = XIICPS_FIFO_DEPTH;
263 for(Tmp = 0; Tmp < BytesToSend; Tmp ++) {
264 XIicPs_SendByte(InstancePtr);
267 StatusReg = XIicPs_ReadReg(BaseAddr, XIICPS_SR_OFFSET);
270 * Wait for master to read the data out of fifo.
272 while (((StatusReg & XIICPS_SR_TXDV_MASK) != 0) && (!Error)) {
275 * If master terminates the transfer before all data is
276 * sent, it is an error.
278 IntrStatusReg = XIicPs_ReadReg(BaseAddr,
280 if (IntrStatusReg & XIICPS_IXR_NACK_MASK) {
286 XIicPs_WriteReg(BaseAddr, XIICPS_ISR_OFFSET,
289 StatusReg = XIicPs_ReadReg(BaseAddr,
300 /*****************************************************************************/
302 * This function receives a buffer in polled mode as a slave.
304 * @param InstancePtr is a pointer to the XIicPs instance.
305 * @param MsgPtr is the pointer to the receive buffer.
306 * @param ByteCount is the number of bytes to be received.
309 * - XST_SUCCESS if everything went well.
310 * - XST_FAILURE if timed out.
312 * @note This receive routine is for polled mode transfer only.
314 ****************************************************************************/
315 int XIicPs_SlaveRecvPolled(XIicPs *InstancePtr, u8 *MsgPtr, int ByteCount)
317 volatile u32 IntrStatusReg;
318 volatile u32 StatusReg;
322 * Assert validates the input arguments.
324 Xil_AssertNonvoid(InstancePtr != NULL);
325 Xil_AssertNonvoid(MsgPtr != NULL);
326 Xil_AssertNonvoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY);
328 BaseAddr = InstancePtr->Config.BaseAddress;
329 InstancePtr->RecvBufferPtr = MsgPtr;
330 InstancePtr->RecvByteCount = ByteCount;
332 StatusReg = XIicPs_ReadReg(BaseAddr, XIICPS_SR_OFFSET);
335 * Clear the interrupt status register.
337 IntrStatusReg = XIicPs_ReadReg(BaseAddr, XIICPS_ISR_OFFSET);
338 XIicPs_WriteReg(BaseAddr, XIICPS_ISR_OFFSET, IntrStatusReg);
341 * Clear the status register.
343 StatusReg = XIicPs_ReadReg(BaseAddr, XIICPS_SR_OFFSET);
344 XIicPs_WriteReg(BaseAddr, XIICPS_SR_OFFSET, StatusReg);
346 StatusReg = XIicPs_ReadReg(BaseAddr, XIICPS_SR_OFFSET);
347 while (InstancePtr->RecvByteCount > 0) {
349 /* Wait for master to put data */
350 while ((StatusReg & XIICPS_SR_RXDV_MASK) == 0) {
351 StatusReg = XIicPs_ReadReg(BaseAddr, XIICPS_SR_OFFSET);
354 * If master terminates the transfer before we get all
355 * the data or the master tries to read from us,
358 IntrStatusReg = XIicPs_ReadReg(BaseAddr,
360 if ((IntrStatusReg & (XIICPS_IXR_DATA_MASK |
361 XIICPS_IXR_COMP_MASK)) &&
362 ((StatusReg & XIICPS_SR_RXDV_MASK) == 0) &&
363 (InstancePtr->RecvByteCount > 0)) {
369 * Clear the interrupt status register.
371 XIicPs_WriteReg(BaseAddr, XIICPS_ISR_OFFSET,
376 * Read all data from FIFO.
378 while ((StatusReg & XIICPS_SR_RXDV_MASK) &&
379 (InstancePtr->RecvByteCount > 0)){
381 XIicPs_RecvByte(InstancePtr);
383 StatusReg = XIicPs_ReadReg(BaseAddr,
391 /*****************************************************************************/
393 * The interrupt handler for slave mode. It does the protocol handling for
394 * the interrupt-driven transfers.
396 * Completion events and errors are signaled to upper layer for proper
401 * The interrupts that are handled are:
403 * If the instance is sending, it means that the master wants to read more
404 * data from us. Send more data, and check whether we are done with this
407 * If the instance is receiving, it means that the master has writen
408 * more data to us. Receive more data, and check whether we are done with
412 * This marks that stop sequence has been sent from the master, transfer
413 * is about to terminate. However, for receiving, the master may have
414 * written us some data, so receive that first.
416 * It is an error if the amount of transfered data is less than expected.
419 * This marks that master does not want our data. It is for send only.
422 * These interrupts are marked as error.
426 * @param InstancePtr is a pointer to the XIicPs instance.
432 ****************************************************************************/
433 void XIicPs_SlaveInterruptHandler(XIicPs *InstancePtr)
435 volatile u32 IntrStatusReg;
442 * Assert validates the input arguments.
444 Xil_AssertVoid(InstancePtr != NULL);
445 Xil_AssertVoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY);
447 BaseAddr = InstancePtr->Config.BaseAddress;
450 * Read the Interrupt status register.
452 IntrStatusReg = XIicPs_ReadReg(BaseAddr, XIICPS_ISR_OFFSET);
455 * Write the status back to clear the interrupts so no events are missed
456 * while processing this interrupt.
458 XIicPs_WriteReg(BaseAddr, XIICPS_ISR_OFFSET, IntrStatusReg);
461 * Use the Mask register AND with the Interrupt Status register so
462 * disabled interrupts are not processed.
464 IntrStatusReg &= ~(XIicPs_ReadReg(BaseAddr, XIICPS_IMR_OFFSET));
467 * Determine whether the device is sending.
469 if (InstancePtr->RecvBufferPtr == NULL) {
475 * This means master wants to do more data transfers.
476 * Also check for completion of transfer, signal upper layer if done.
478 if (0 != (IntrStatusReg & XIICPS_IXR_DATA_MASK)) {
480 LeftOver = TransmitFifoFill(InstancePtr);
482 * We may finish send here
486 XIICPS_EVENT_COMPLETE_SEND;
489 LeftOver = SlaveRecvData(InstancePtr);
491 /* We may finish the receive here */
493 StatusEvent |= XIICPS_EVENT_COMPLETE_RECV;
499 * Complete interrupt.
501 * In slave mode, it means the master has done with this transfer, so
502 * we signal the application using completion event.
504 if (0 != (IntrStatusReg & XIICPS_IXR_COMP_MASK)) {
506 if (InstancePtr->SendByteCount > 0) {
507 StatusEvent |= XIICPS_EVENT_ERROR;
509 StatusEvent |= XIICPS_EVENT_COMPLETE_SEND;
512 LeftOver = SlaveRecvData(InstancePtr);
514 StatusEvent |= XIICPS_EVENT_ERROR;
516 StatusEvent |= XIICPS_EVENT_COMPLETE_RECV;
522 * Nack interrupt, pass this information to application.
524 if (0 != (IntrStatusReg & XIICPS_IXR_NACK_MASK)) {
525 StatusEvent |= XIICPS_EVENT_NACK;
529 * All other interrupts are treated as error.
531 if (0 != (IntrStatusReg & (XIICPS_IXR_TO_MASK |
532 XIICPS_IXR_RX_UNF_MASK |
533 XIICPS_IXR_TX_OVR_MASK |
534 XIICPS_IXR_RX_OVR_MASK))){
536 StatusEvent |= XIICPS_EVENT_ERROR;
540 * Signal application if there are any events.
542 if (0 != StatusEvent) {
543 InstancePtr->StatusHandler(InstancePtr->CallBackRef,
548 /*****************************************************************************/
551 * This function handles continuation of receiving data. It is invoked
552 * from interrupt handler.
554 * @param InstancePtr is a pointer to the XIicPs instance.
556 * @return Number of bytes still expected by the instance.
560 ****************************************************************************/
561 static int SlaveRecvData(XIicPs *InstancePtr)
563 volatile u32 StatusReg;
566 BaseAddr = InstancePtr->Config.BaseAddress;
568 StatusReg = XIicPs_ReadReg(BaseAddr, XIICPS_SR_OFFSET);
570 while ((StatusReg & XIICPS_SR_RXDV_MASK) &&
571 (InstancePtr->RecvByteCount > 0)) {
572 XIicPs_RecvByte(InstancePtr);
573 StatusReg = XIicPs_ReadReg(BaseAddr, XIICPS_SR_OFFSET);
576 return InstancePtr->RecvByteCount;