1 /******************************************************************************
3 * Copyright (C) 2010 - 2016 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 /*****************************************************************************/
35 * @file xiicps_master.c
36 * @addtogroup iicps_v3_0
39 * Handles master mode transfers.
41 * <pre> MODIFICATION HISTORY:
43 * Ver Who Date Changes
44 * ----- --- -------- ---------------------------------------------
45 * 1.00a jz 01/30/10 First release
46 * 1.00a sdm 09/21/11 Updated the XIicPs_SetupMaster to not check for
47 * Bus Busy condition when the Hold Bit is set.
48 * 1.01a sg 03/30/12 Fixed an issue in XIicPs_MasterSendPolled where a
49 * check for transfer completion is added, which indicates
50 * the completion of current transfer.
51 * 2.0 hk 03/07/14 Added check for error status in the while loop that
52 * checks for completion. CR# 762244, 764875.
53 * 2.1 hk 04/24/14 Fix for CR# 789821 to handle >14 byte transfers.
54 * Fix for CR# 761060 - provision for repeated start.
55 * 2.2 hk 08/23/14 Slave monitor mode changes - clear FIFO, enable
56 * read mode and clear transfer size register.
57 * Disable NACK to avoid interrupts on each retry.
58 * 2.3 sk 10/06/14 Fill transmit fifo before address register when sending.
59 * Replaced XIICPS_DATA_INTR_DEPTH with XIICPS_FIFO_DEPTH.
60 * Repeated start feature removed.
61 * 3.0 sk 12/06/14 Implemented Repeated start feature.
62 * 01/31/15 Modified the code according to MISRAC 2012 Compliant.
63 * 02/18/15 Implemented larger data transfer using repeated start
64 * in Zynq UltraScale MP.
65 * 3.3 kvn 05/05/16 Modified latest code for MISRA-C:2012 Compliance.
69 ******************************************************************************/
71 /***************************** Include Files *********************************/
75 /************************** Constant Definitions *****************************/
77 /**************************** Type Definitions *******************************/
79 /***************** Macros (Inline Functions) Definitions *********************/
81 /************************** Function Prototypes ******************************/
82 s32 TransmitFifoFill(XIicPs *InstancePtr);
84 static s32 XIicPs_SetupMaster(XIicPs *InstancePtr, s32 Role);
85 static void MasterSendData(XIicPs *InstancePtr);
87 /************************* Variable Definitions *****************************/
89 /*****************************************************************************/
91 * This function initiates an interrupt-driven send in master mode.
93 * It tries to send the first FIFO-full of data, then lets the interrupt
94 * handler to handle the rest of the data if there is any.
96 * @param InstancePtr is a pointer to the XIicPs instance.
97 * @param MsgPtr is the pointer to the send buffer.
98 * @param ByteCount is the number of bytes to be sent.
99 * @param SlaveAddr is the address of the slave we are sending to.
103 * @note This send routine is for interrupt-driven transfer only.
105 ****************************************************************************/
106 void XIicPs_MasterSend(XIicPs *InstancePtr, u8 *MsgPtr, s32 ByteCount,
110 u32 Platform = XGetPlatform_Info();
113 * Assert validates the input arguments.
115 Xil_AssertVoid(InstancePtr != NULL);
116 Xil_AssertVoid(MsgPtr != NULL);
117 Xil_AssertVoid(InstancePtr->IsReady == (u32)XIL_COMPONENT_IS_READY);
118 Xil_AssertVoid(XIICPS_ADDR_MASK >= SlaveAddr);
121 BaseAddr = InstancePtr->Config.BaseAddress;
122 InstancePtr->SendBufferPtr = MsgPtr;
123 InstancePtr->SendByteCount = ByteCount;
124 InstancePtr->RecvBufferPtr = NULL;
125 InstancePtr->IsSend = 1;
128 * Set repeated start if sending more than FIFO of data.
130 if (((InstancePtr->IsRepeatedStart) != 0)||
131 ((ByteCount > XIICPS_FIFO_DEPTH) != 0U)) {
132 XIicPs_WriteReg(BaseAddr, (u32)XIICPS_CR_OFFSET,
133 XIicPs_ReadReg(BaseAddr, (u32)XIICPS_CR_OFFSET) |
134 (u32)XIICPS_CR_HOLD_MASK);
138 * Setup as a master sending role.
140 (void)XIicPs_SetupMaster(InstancePtr, SENDING_ROLE);
142 (void)TransmitFifoFill(InstancePtr);
144 XIicPs_EnableInterrupts(BaseAddr,
145 (u32)XIICPS_IXR_NACK_MASK | (u32)XIICPS_IXR_COMP_MASK |
146 (u32)XIICPS_IXR_ARB_LOST_MASK);
148 * Do the address transfer to notify the slave.
150 XIicPs_WriteReg(BaseAddr, XIICPS_ADDR_OFFSET, (u32)SlaveAddr);
152 /* Clear the Hold bit in ZYNQ if receive byte count is less than
153 * the FIFO depth to get the completion interrupt properly.
155 if ((ByteCount < XIICPS_FIFO_DEPTH) && (Platform == (u32)XPLAT_ZYNQ))
157 XIicPs_WriteReg(BaseAddr, XIICPS_CR_OFFSET,
158 XIicPs_ReadReg(BaseAddr, (u32)XIICPS_CR_OFFSET) &
159 (u32)(~XIICPS_CR_HOLD_MASK));
164 /*****************************************************************************/
166 * This function initiates an interrupt-driven receive in master mode.
168 * It sets the transfer size register so the slave can send data to us.
169 * The rest of the work is managed by interrupt handler.
171 * @param InstancePtr is a pointer to the XIicPs instance.
172 * @param MsgPtr is the pointer to the receive buffer.
173 * @param ByteCount is the number of bytes to be received.
174 * @param SlaveAddr is the address of the slave we are receiving from.
178 * @note This receive routine is for interrupt-driven transfer only.
180 ****************************************************************************/
181 void XIicPs_MasterRecv(XIicPs *InstancePtr, u8 *MsgPtr, s32 ByteCount,
187 * Assert validates the input arguments.
189 Xil_AssertVoid(InstancePtr != NULL);
190 Xil_AssertVoid(MsgPtr != NULL);
191 Xil_AssertVoid(InstancePtr->IsReady == (u32)XIL_COMPONENT_IS_READY);
192 Xil_AssertVoid(XIICPS_ADDR_MASK >= SlaveAddr);
194 BaseAddr = InstancePtr->Config.BaseAddress;
195 InstancePtr->RecvBufferPtr = MsgPtr;
196 InstancePtr->RecvByteCount = ByteCount;
197 InstancePtr->SendBufferPtr = NULL;
198 InstancePtr->IsSend = 0;
200 if ((ByteCount > XIICPS_FIFO_DEPTH) ||
201 ((InstancePtr->IsRepeatedStart) !=0))
203 XIicPs_WriteReg(BaseAddr, XIICPS_CR_OFFSET,
204 XIicPs_ReadReg(BaseAddr, (u32)XIICPS_CR_OFFSET) |
205 (u32)XIICPS_CR_HOLD_MASK);
209 * Initialize for a master receiving role.
211 (void)XIicPs_SetupMaster(InstancePtr, RECVING_ROLE);
213 * Setup the transfer size register so the slave knows how much
216 if (ByteCount > (s32)XIICPS_MAX_TRANSFER_SIZE) {
217 XIicPs_WriteReg(BaseAddr, XIICPS_TRANS_SIZE_OFFSET,
218 XIICPS_MAX_TRANSFER_SIZE);
219 InstancePtr->CurrByteCount = (s32)XIICPS_MAX_TRANSFER_SIZE;
220 InstancePtr->UpdateTxSize = 1;
222 InstancePtr->CurrByteCount = ByteCount;
223 XIicPs_WriteReg(BaseAddr, (u32)(XIICPS_TRANS_SIZE_OFFSET),
225 InstancePtr->UpdateTxSize = 0;
228 XIicPs_EnableInterrupts(BaseAddr,
229 (u32)XIICPS_IXR_NACK_MASK | (u32)XIICPS_IXR_DATA_MASK |
230 (u32)XIICPS_IXR_RX_OVR_MASK | (u32)XIICPS_IXR_COMP_MASK |
231 (u32)XIICPS_IXR_ARB_LOST_MASK);
233 * Do the address transfer to signal the slave.
235 XIicPs_WriteReg(BaseAddr, XIICPS_ADDR_OFFSET, (u32)SlaveAddr);
239 /*****************************************************************************/
241 * This function initiates a polled mode send in master mode.
243 * It sends data to the FIFO and waits for the slave to pick them up.
244 * If slave fails to remove data from FIFO, the send fails with
247 * @param InstancePtr is a pointer to the XIicPs instance.
248 * @param MsgPtr is the pointer to the send buffer.
249 * @param ByteCount is the number of bytes to be sent.
250 * @param SlaveAddr is the address of the slave we are sending to.
253 * - XST_SUCCESS if everything went well.
254 * - XST_FAILURE if timed out.
256 * @note This send routine is for polled mode transfer only.
258 ****************************************************************************/
259 s32 XIicPs_MasterSendPolled(XIicPs *InstancePtr, u8 *MsgPtr,
260 s32 ByteCount, u16 SlaveAddr)
269 * Assert validates the input arguments.
271 Xil_AssertNonvoid(InstancePtr != NULL);
272 Xil_AssertNonvoid(MsgPtr != NULL);
273 Xil_AssertNonvoid(InstancePtr->IsReady == (u32)XIL_COMPONENT_IS_READY);
274 Xil_AssertNonvoid((u16)XIICPS_ADDR_MASK >= SlaveAddr);
276 BaseAddr = InstancePtr->Config.BaseAddress;
277 InstancePtr->SendBufferPtr = MsgPtr;
278 InstancePtr->SendByteCount = ByteCount;
280 if (((InstancePtr->IsRepeatedStart) != 0) ||
281 ((ByteCount > XIICPS_FIFO_DEPTH) != 0U)) {
282 XIicPs_WriteReg(BaseAddr, XIICPS_CR_OFFSET,
283 XIicPs_ReadReg(BaseAddr, (u32)XIICPS_CR_OFFSET) |
284 (u32)XIICPS_CR_HOLD_MASK);
287 (void)XIicPs_SetupMaster(InstancePtr, SENDING_ROLE);
290 * Intrs keeps all the error-related interrupts.
292 Intrs = (u32)XIICPS_IXR_ARB_LOST_MASK | (u32)XIICPS_IXR_TX_OVR_MASK |
293 (u32)XIICPS_IXR_NACK_MASK;
296 * Clear the interrupt status register before use it to monitor.
298 IntrStatusReg = XIicPs_ReadReg(BaseAddr, XIICPS_ISR_OFFSET);
299 XIicPs_WriteReg(BaseAddr, XIICPS_ISR_OFFSET, IntrStatusReg);
302 * Transmit first FIFO full of data.
304 (void)TransmitFifoFill(InstancePtr);
306 XIicPs_WriteReg(BaseAddr, XIICPS_ADDR_OFFSET, (u32)SlaveAddr);
308 IntrStatusReg = XIicPs_ReadReg(BaseAddr, XIICPS_ISR_OFFSET);
311 * Continue sending as long as there is more data and
312 * there are no errors.
314 Value = ((InstancePtr->SendByteCount > (s32)0) &&
315 ((IntrStatusReg & Intrs) == (u32)0U));
316 while (Value != FALSE) {
317 StatusReg = XIicPs_ReadReg(BaseAddr, XIICPS_SR_OFFSET);
320 * Wait until transmit FIFO is empty.
322 if ((StatusReg & XIICPS_SR_TXDV_MASK) != 0U) {
323 IntrStatusReg = XIicPs_ReadReg(BaseAddr,
325 Value = ((InstancePtr->SendByteCount > (s32)0) &&
326 ((IntrStatusReg & Intrs) == (u32)0U));
331 * Send more data out through transmit FIFO.
333 (void)TransmitFifoFill(InstancePtr);
334 Value = ((InstancePtr->SendByteCount > (s32)0) &&
335 ((IntrStatusReg & Intrs) == (u32)0U));
339 * Check for completion of transfer.
341 while ((IntrStatusReg & XIICPS_IXR_COMP_MASK) != XIICPS_IXR_COMP_MASK){
343 IntrStatusReg = XIicPs_ReadReg(BaseAddr, XIICPS_ISR_OFFSET);
345 * If there is an error, tell the caller.
347 if ((IntrStatusReg & Intrs) != 0U) {
348 return (s32)XST_FAILURE;
352 if ((!(InstancePtr->IsRepeatedStart)) != 0) {
353 XIicPs_WriteReg(BaseAddr, XIICPS_CR_OFFSET,
354 XIicPs_ReadReg(BaseAddr,XIICPS_CR_OFFSET) &
355 (~XIICPS_CR_HOLD_MASK));
358 return (s32)XST_SUCCESS;
361 /*****************************************************************************/
363 * This function initiates a polled mode receive in master mode.
365 * It repeatedly sets the transfer size register so the slave can
366 * send data to us. It polls the data register for data to come in.
367 * If slave fails to send us data, it fails with time out.
369 * @param InstancePtr is a pointer to the XIicPs instance.
370 * @param MsgPtr is the pointer to the receive buffer.
371 * @param ByteCount is the number of bytes to be received.
372 * @param SlaveAddr is the address of the slave we are receiving from.
375 * - XST_SUCCESS if everything went well.
376 * - XST_FAILURE if timed out.
378 * @note This receive routine is for polled mode transfer only.
380 ****************************************************************************/
381 s32 XIicPs_MasterRecvPolled(XIicPs *InstancePtr, u8 *MsgPtr,
382 s32 ByteCount, u16 SlaveAddr)
390 s32 UpdateTxSize = 0;
391 s32 ByteCountVar = ByteCount;
395 * Assert validates the input arguments.
397 Xil_AssertNonvoid(InstancePtr != NULL);
398 Xil_AssertNonvoid(MsgPtr != NULL);
399 Xil_AssertNonvoid(InstancePtr->IsReady == (u32)XIL_COMPONENT_IS_READY);
400 Xil_AssertNonvoid(XIICPS_ADDR_MASK >= SlaveAddr);
402 BaseAddr = InstancePtr->Config.BaseAddress;
403 InstancePtr->RecvBufferPtr = MsgPtr;
404 InstancePtr->RecvByteCount = ByteCountVar;
406 Platform = XGetPlatform_Info();
408 if((ByteCountVar > XIICPS_FIFO_DEPTH) ||
409 ((InstancePtr->IsRepeatedStart) !=0))
411 XIicPs_WriteReg(BaseAddr, XIICPS_CR_OFFSET,
412 XIicPs_ReadReg(BaseAddr, (u32)XIICPS_CR_OFFSET) |
413 (u32)XIICPS_CR_HOLD_MASK);
419 (void)XIicPs_SetupMaster(InstancePtr, RECVING_ROLE);
422 * Clear the interrupt status register before use it to monitor.
424 IntrStatusReg = XIicPs_ReadReg(BaseAddr, XIICPS_ISR_OFFSET);
425 XIicPs_WriteReg(BaseAddr, XIICPS_ISR_OFFSET, IntrStatusReg);
427 XIicPs_WriteReg(BaseAddr, XIICPS_ADDR_OFFSET, SlaveAddr);
430 * Set up the transfer size register so the slave knows how much
433 if (ByteCountVar > (s32)XIICPS_MAX_TRANSFER_SIZE) {
434 XIicPs_WriteReg(BaseAddr, XIICPS_TRANS_SIZE_OFFSET,
435 XIICPS_MAX_TRANSFER_SIZE);
436 ByteCountVar = (s32)XIICPS_MAX_TRANSFER_SIZE;
439 XIicPs_WriteReg(BaseAddr, XIICPS_TRANS_SIZE_OFFSET,
444 * Intrs keeps all the error-related interrupts.
446 Intrs = (u32)XIICPS_IXR_ARB_LOST_MASK | (u32)XIICPS_IXR_RX_OVR_MASK |
447 (u32)XIICPS_IXR_RX_UNF_MASK | (u32)XIICPS_IXR_NACK_MASK;
449 * Poll the interrupt status register to find the errors.
451 IntrStatusReg = XIicPs_ReadReg(BaseAddr, XIICPS_ISR_OFFSET);
452 while ((InstancePtr->RecvByteCount > 0) &&
453 ((IntrStatusReg & Intrs) == 0U)) {
454 StatusReg = XIicPs_ReadReg(BaseAddr, XIICPS_SR_OFFSET);
456 while ((StatusReg & XIICPS_SR_RXDV_MASK) != 0U) {
457 if (((InstancePtr->RecvByteCount <
458 XIICPS_DATA_INTR_DEPTH) != 0U) && (IsHold != 0) &&
459 ((!InstancePtr->IsRepeatedStart) != 0) &&
460 (UpdateTxSize == 0)) {
462 XIicPs_WriteReg(BaseAddr, XIICPS_CR_OFFSET,
463 XIicPs_ReadReg(BaseAddr,
465 (~XIICPS_CR_HOLD_MASK));
467 XIicPs_RecvByte(InstancePtr);
470 if (Platform == (u32)XPLAT_ZYNQ) {
471 if ((UpdateTxSize != 0) &&
472 (ByteCountVar == (XIICPS_FIFO_DEPTH + 1))) {
477 StatusReg = XIicPs_ReadReg(BaseAddr, XIICPS_SR_OFFSET);
479 if (Platform == (u32)XPLAT_ZYNQ) {
480 if ((UpdateTxSize != 0) &&
481 (ByteCountVar == (XIICPS_FIFO_DEPTH + 1))) {
482 /* wait while fifo is full */
483 while (XIicPs_ReadReg(BaseAddr,
484 XIICPS_TRANS_SIZE_OFFSET) !=
485 (u32)(ByteCountVar - XIICPS_FIFO_DEPTH)) { ;
488 if ((InstancePtr->RecvByteCount - XIICPS_FIFO_DEPTH) >
489 (s32)XIICPS_MAX_TRANSFER_SIZE) {
491 XIicPs_WriteReg(BaseAddr,
492 XIICPS_TRANS_SIZE_OFFSET,
493 XIICPS_MAX_TRANSFER_SIZE);
494 ByteCountVar = (s32)XIICPS_MAX_TRANSFER_SIZE +
497 XIicPs_WriteReg(BaseAddr,
498 XIICPS_TRANS_SIZE_OFFSET,
499 InstancePtr->RecvByteCount -
502 ByteCountVar = InstancePtr->RecvByteCount;
506 if ((InstancePtr->RecvByteCount > 0) && (ByteCountVar == 0)) {
508 * Clear the interrupt status register before use it to
511 IntrStatusReg = XIicPs_ReadReg(BaseAddr, XIICPS_ISR_OFFSET);
512 XIicPs_WriteReg(BaseAddr, XIICPS_ISR_OFFSET, IntrStatusReg);
514 XIicPs_WriteReg(BaseAddr, XIICPS_ADDR_OFFSET, SlaveAddr);
516 if ((InstancePtr->RecvByteCount) >
517 (s32)XIICPS_MAX_TRANSFER_SIZE) {
519 XIicPs_WriteReg(BaseAddr,
520 XIICPS_TRANS_SIZE_OFFSET,
521 XIICPS_MAX_TRANSFER_SIZE);
522 ByteCountVar = (s32)XIICPS_MAX_TRANSFER_SIZE;
524 XIicPs_WriteReg(BaseAddr,
525 XIICPS_TRANS_SIZE_OFFSET,
526 InstancePtr->RecvByteCount);
528 ByteCountVar = InstancePtr->RecvByteCount;
533 IntrStatusReg = XIicPs_ReadReg(BaseAddr, XIICPS_ISR_OFFSET);
536 if ((!(InstancePtr->IsRepeatedStart)) != 0) {
537 XIicPs_WriteReg(BaseAddr, XIICPS_CR_OFFSET,
538 XIicPs_ReadReg(BaseAddr,XIICPS_CR_OFFSET) &
539 (~XIICPS_CR_HOLD_MASK));
541 if ((IntrStatusReg & Intrs) != 0x0U) {
542 Result = (s32)XST_FAILURE;
545 Result = (s32)XST_SUCCESS;
551 /*****************************************************************************/
553 * This function enables the slave monitor mode.
555 * It enables slave monitor in the control register and enables
556 * slave ready interrupt. It then does an address transfer to slave.
557 * Interrupt handler will signal the caller if slave responds to
558 * the address transfer.
560 * @param InstancePtr is a pointer to the XIicPs instance.
561 * @param SlaveAddr is the address of the slave we want to contact.
567 ****************************************************************************/
568 void XIicPs_EnableSlaveMonitor(XIicPs *InstancePtr, u16 SlaveAddr)
573 Xil_AssertVoid(InstancePtr != NULL);
575 BaseAddr = InstancePtr->Config.BaseAddress;
577 /* Clear transfer size register */
578 XIicPs_WriteReg(BaseAddr, (u32)XIICPS_TRANS_SIZE_OFFSET, 0x0U);
581 * Enable slave monitor mode in control register.
583 ConfigReg = XIicPs_ReadReg(BaseAddr, (u32)XIICPS_CR_OFFSET);
584 ConfigReg |= (u32)XIICPS_CR_MS_MASK | (u32)XIICPS_CR_NEA_MASK |
585 (u32)XIICPS_CR_CLR_FIFO_MASK | (u32)XIICPS_CR_SLVMON_MASK;
586 ConfigReg &= (u32)(~XIICPS_CR_RD_WR_MASK);
588 XIicPs_WriteReg(BaseAddr, (u32)XIICPS_CR_OFFSET, ConfigReg);
591 * Set up interrupt flag for slave monitor interrupt.
594 XIicPs_EnableInterrupts(BaseAddr, (u32)XIICPS_IXR_SLV_RDY_MASK);
597 * Initialize the slave monitor register.
599 XIicPs_WriteReg(BaseAddr, (u32)XIICPS_SLV_PAUSE_OFFSET, 0xFU);
602 * Set the slave address to start the slave address transmission.
604 XIicPs_WriteReg(BaseAddr, (u32)XIICPS_ADDR_OFFSET, (u32)SlaveAddr);
609 /*****************************************************************************/
611 * This function disables slave monitor mode.
613 * @param InstancePtr is a pointer to the XIicPs instance.
619 ****************************************************************************/
620 void XIicPs_DisableSlaveMonitor(XIicPs *InstancePtr)
624 Xil_AssertVoid(InstancePtr != NULL);
626 BaseAddr = InstancePtr->Config.BaseAddress;
629 * Clear slave monitor control bit.
631 XIicPs_WriteReg(BaseAddr, XIICPS_CR_OFFSET,
632 XIicPs_ReadReg(BaseAddr, XIICPS_CR_OFFSET)
633 & (~XIICPS_CR_SLVMON_MASK));
636 * Clear interrupt flag for slave monitor interrupt.
638 XIicPs_DisableInterrupts(BaseAddr, XIICPS_IXR_SLV_RDY_MASK);
643 /*****************************************************************************/
645 * The interrupt handler for the master mode. It does the protocol handling for
646 * the interrupt-driven transfers.
648 * Completion events and errors are signaled to upper layer for proper handling.
651 * The interrupts that are handled are:
653 * This case is handled only for master receive data.
654 * The master has to request for more data (if there is more data to
655 * receive) and read the data from the FIFO .
658 * If the Master is transmitting data and there is more data to be
659 * sent then the data is written to the FIFO. If there is no more data to
660 * be transmitted then a completion event is signalled to the upper layer
661 * by calling the callback handler.
663 * If the Master is receiving data then the data is read from the FIFO and
664 * the Master has to request for more data (if there is more data to
665 * receive). If all the data has been received then a completion event
666 * is signalled to the upper layer by calling the callback handler.
667 * It is an error if the amount of received data is more than expected.
669 * - NAK and SLAVE_RDY
670 * This is signalled to the upper layer by calling the callback handler.
672 * - All Other interrupts
673 * These interrupts are marked as error. This is signalled to the upper
674 * layer by calling the callback handler.
678 * @param InstancePtr is a pointer to the XIicPs instance.
684 ****************************************************************************/
685 void XIicPs_MasterInterruptHandler(XIicPs *InstancePtr)
688 u32 StatusEvent = 0U;
696 * Assert validates the input arguments.
698 Xil_AssertVoid(InstancePtr != NULL);
699 Xil_AssertVoid(InstancePtr->IsReady == (u32)XIL_COMPONENT_IS_READY);
701 BaseAddr = InstancePtr->Config.BaseAddress;
703 Platform = XGetPlatform_Info();
706 * Read the Interrupt status register.
708 IntrStatusReg = XIicPs_ReadReg(BaseAddr,
709 (u32)XIICPS_ISR_OFFSET);
712 * Write the status back to clear the interrupts so no events are
713 * missed while processing this interrupt.
715 XIicPs_WriteReg(BaseAddr, (u32)XIICPS_ISR_OFFSET, IntrStatusReg);
718 * Use the Mask register AND with the Interrupt Status register so
719 * disabled interrupts are not processed.
721 IntrStatusReg &= ~(XIicPs_ReadReg(BaseAddr, (u32)XIICPS_IMR_OFFSET));
723 ByteCnt = InstancePtr->CurrByteCount;
726 if ((XIicPs_ReadReg(BaseAddr, (u32)XIICPS_CR_OFFSET) & (u32)XIICPS_CR_HOLD_MASK) != 0U) {
733 if (((InstancePtr->IsSend) != 0) &&
734 ((u32)0U != (IntrStatusReg & (u32)XIICPS_IXR_COMP_MASK))) {
735 if (InstancePtr->SendByteCount > 0) {
736 MasterSendData(InstancePtr);
738 StatusEvent |= XIICPS_EVENT_COMPLETE_SEND;
746 if (((!(InstancePtr->IsSend))!= 0) &&
747 ((0 != (IntrStatusReg & (u32)XIICPS_IXR_DATA_MASK)) ||
748 (0 != (IntrStatusReg & (u32)XIICPS_IXR_COMP_MASK)))){
750 while ((XIicPs_ReadReg(BaseAddr, (u32)XIICPS_SR_OFFSET) &
751 XIICPS_SR_RXDV_MASK) != 0U) {
752 if (((InstancePtr->RecvByteCount <
753 XIICPS_DATA_INTR_DEPTH)!= 0U) && (IsHold != 0) &&
754 ((!InstancePtr->IsRepeatedStart)!= 0) &&
755 (InstancePtr->UpdateTxSize == 0)) {
757 XIicPs_WriteReg(BaseAddr, XIICPS_CR_OFFSET,
758 XIicPs_ReadReg(BaseAddr,
760 (~XIICPS_CR_HOLD_MASK));
762 XIicPs_RecvByte(InstancePtr);
765 if (Platform == (u32)XPLAT_ZYNQ) {
766 if ((InstancePtr->UpdateTxSize != 0) &&
767 (ByteCnt == (XIICPS_FIFO_DEPTH + 1))) {
773 if (Platform == (u32)XPLAT_ZYNQ) {
774 if ((InstancePtr->UpdateTxSize != 0) &&
775 (ByteCnt == (XIICPS_FIFO_DEPTH + 1))) {
776 /* wait while fifo is full */
777 while (XIicPs_ReadReg(BaseAddr,
778 XIICPS_TRANS_SIZE_OFFSET) !=
779 (u32)(ByteCnt - XIICPS_FIFO_DEPTH)) {
782 if ((InstancePtr->RecvByteCount - XIICPS_FIFO_DEPTH) >
783 (s32)XIICPS_MAX_TRANSFER_SIZE) {
785 XIicPs_WriteReg(BaseAddr,
786 XIICPS_TRANS_SIZE_OFFSET,
787 XIICPS_MAX_TRANSFER_SIZE);
788 ByteCnt = (s32)XIICPS_MAX_TRANSFER_SIZE +
791 XIicPs_WriteReg(BaseAddr,
792 XIICPS_TRANS_SIZE_OFFSET,
793 InstancePtr->RecvByteCount -
795 InstancePtr->UpdateTxSize = 0;
796 ByteCnt = InstancePtr->RecvByteCount;
800 if ((InstancePtr->RecvByteCount > 0) && (ByteCnt == 0)) {
802 * Clear the interrupt status register before use it to
805 IntrStatusReg = XIicPs_ReadReg(BaseAddr, XIICPS_ISR_OFFSET);
806 XIicPs_WriteReg(BaseAddr, XIICPS_ISR_OFFSET, IntrStatusReg);
808 SlaveAddr = (u16)XIicPs_ReadReg(BaseAddr, (u32)XIICPS_ADDR_OFFSET);
809 XIicPs_WriteReg(BaseAddr, XIICPS_ADDR_OFFSET, SlaveAddr);
811 if ((InstancePtr->RecvByteCount) >
812 (s32)XIICPS_MAX_TRANSFER_SIZE) {
814 XIicPs_WriteReg(BaseAddr,
815 XIICPS_TRANS_SIZE_OFFSET,
816 XIICPS_MAX_TRANSFER_SIZE);
817 ByteCnt = (s32)XIICPS_MAX_TRANSFER_SIZE;
819 XIicPs_WriteReg(BaseAddr,
820 XIICPS_TRANS_SIZE_OFFSET,
821 InstancePtr->RecvByteCount);
822 InstancePtr->UpdateTxSize = 0;
823 ByteCnt = InstancePtr->RecvByteCount;
825 XIicPs_EnableInterrupts(BaseAddr,
826 (u32)XIICPS_IXR_NACK_MASK | (u32)XIICPS_IXR_DATA_MASK |
827 (u32)XIICPS_IXR_RX_OVR_MASK | (u32)XIICPS_IXR_COMP_MASK |
828 (u32)XIICPS_IXR_ARB_LOST_MASK);
831 InstancePtr->CurrByteCount = ByteCnt;
834 if (((!(InstancePtr->IsSend)) != 0) &&
835 (0U != (IntrStatusReg & XIICPS_IXR_COMP_MASK))) {
837 * If all done, tell the application.
839 if (InstancePtr->RecvByteCount == 0){
840 if ((!(InstancePtr->IsRepeatedStart)) != 0) {
841 XIicPs_WriteReg(BaseAddr, XIICPS_CR_OFFSET,
842 XIicPs_ReadReg(BaseAddr,
844 (~XIICPS_CR_HOLD_MASK));
846 StatusEvent |= XIICPS_EVENT_COMPLETE_RECV;
852 * Slave ready interrupt, it is only meaningful for master mode.
854 if (0U != (IntrStatusReg & XIICPS_IXR_SLV_RDY_MASK)) {
855 StatusEvent |= XIICPS_EVENT_SLAVE_RDY;
858 if (0U != (IntrStatusReg & XIICPS_IXR_NACK_MASK)) {
859 if ((!(InstancePtr->IsRepeatedStart)) != 0 ) {
860 XIicPs_WriteReg(BaseAddr, XIICPS_CR_OFFSET,
861 XIicPs_ReadReg(BaseAddr,
863 (~XIICPS_CR_HOLD_MASK));
865 StatusEvent |= XIICPS_EVENT_NACK;
869 * Arbitration lost interrupt
871 if (0U != (IntrStatusReg & XIICPS_IXR_ARB_LOST_MASK)) {
872 StatusEvent |= XIICPS_EVENT_ARB_LOST;
876 * All other interrupts are treated as error.
878 if (0U != (IntrStatusReg & (XIICPS_IXR_NACK_MASK |
879 XIICPS_IXR_RX_UNF_MASK | XIICPS_IXR_TX_OVR_MASK |
880 XIICPS_IXR_RX_OVR_MASK))) {
881 if ((!(InstancePtr->IsRepeatedStart)) != 0) {
882 XIicPs_WriteReg(BaseAddr, XIICPS_CR_OFFSET,
883 XIicPs_ReadReg(BaseAddr,
885 (~XIICPS_CR_HOLD_MASK));
887 StatusEvent |= XIICPS_EVENT_ERROR;
891 * Signal application if there are any events.
893 if (StatusEvent != 0U) {
894 InstancePtr->StatusHandler(InstancePtr->CallBackRef,
900 /*****************************************************************************/
902 * This function prepares a device to transfers as a master.
904 * @param InstancePtr is a pointer to the XIicPs instance.
906 * @param Role specifies whether the device is sending or receiving.
909 * - XST_SUCCESS if everything went well.
910 * - XST_FAILURE if bus is busy.
912 * @note Interrupts are always disabled, device which needs to use
913 * interrupts needs to setup interrupts after this call.
915 ****************************************************************************/
916 static s32 XIicPs_SetupMaster(XIicPs *InstancePtr, s32 Role)
921 Xil_AssertNonvoid(InstancePtr != NULL);
923 BaseAddr = InstancePtr->Config.BaseAddress;
924 ControlReg = XIicPs_ReadReg(BaseAddr, XIICPS_CR_OFFSET);
928 * Only check if bus is busy when repeated start option is not set.
930 if ((ControlReg & XIICPS_CR_HOLD_MASK) == 0U) {
931 if (XIicPs_BusIsBusy(InstancePtr) == (s32)1) {
932 return (s32)XST_FAILURE;
937 * Set up master, AckEn, nea and also clear fifo.
939 ControlReg |= (u32)XIICPS_CR_ACKEN_MASK | (u32)XIICPS_CR_CLR_FIFO_MASK |
940 (u32)XIICPS_CR_NEA_MASK | (u32)XIICPS_CR_MS_MASK;
942 if (Role == RECVING_ROLE) {
943 ControlReg |= (u32)XIICPS_CR_RD_WR_MASK;
945 ControlReg &= (u32)(~XIICPS_CR_RD_WR_MASK);
948 XIicPs_WriteReg(BaseAddr, XIICPS_CR_OFFSET, ControlReg);
950 XIicPs_DisableAllInterrupts(BaseAddr);
952 return (s32)XST_SUCCESS;
955 /*****************************************************************************/
957 * This function handles continuation of sending data. It is invoked
958 * from interrupt handler.
960 * @param InstancePtr is a pointer to the XIicPs instance.
966 ****************************************************************************/
967 static void MasterSendData(XIicPs *InstancePtr)
969 (void)TransmitFifoFill(InstancePtr);
972 * Clear hold bit if done, so stop can be sent out.
974 if (InstancePtr->SendByteCount == 0) {
977 * If user has enabled repeated start as an option,
980 if ((!(InstancePtr->IsRepeatedStart)) != 0) {
982 XIicPs_WriteReg(InstancePtr->Config.BaseAddress,
983 (u32)XIICPS_CR_OFFSET,
984 XIicPs_ReadReg(InstancePtr->Config.BaseAddress,
985 (u32)XIICPS_CR_OFFSET) & (u32)(~ XIICPS_CR_HOLD_MASK));