]> git.sur5r.net Git - freertos/blob - FreeRTOS/Demo/CORTEX_A9_Zynq_ZC702/RTOSDemo_bsp/ps7_cortexa9_0/libsrc/iicps_v2_1/src/xiicps_master.c
a3e9f6df2dc01ad2920f8ba87905c8b947c4c704
[freertos] / FreeRTOS / Demo / CORTEX_A9_Zynq_ZC702 / RTOSDemo_bsp / ps7_cortexa9_0 / libsrc / iicps_v2_1 / src / xiicps_master.c
1 /******************************************************************************
2 *
3 * Copyright (C) 2010 - 2014 Xilinx, Inc.  All rights reserved.
4 *
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:
11 *
12 * The above copyright notice and this permission notice shall be included in
13 * all copies or substantial portions of the Software.
14 *
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.
18 *
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
25 * SOFTWARE.
26 *
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.
30 *
31 ******************************************************************************/
32 /*****************************************************************************/
33 /**
34 *
35 * @file xiicps_master.c
36 *
37 * Handles master mode transfers.
38 *
39 * <pre> MODIFICATION HISTORY:
40 *
41 * Ver   Who  Date     Changes
42 * ----- ---  -------- ---------------------------------------------
43 * 1.00a jz   01/30/10 First release
44 * 1.00a sdm  09/21/11 Updated the XIicPs_SetupMaster to not check for
45 *                     Bus Busy condition when the Hold Bit is set.
46 * 1.01a sg   03/30/12 Fixed an issue in XIicPs_MasterSendPolled where a
47 *                     check for transfer completion is added, which indicates
48 *                        the completion of current transfer.
49 * 2.0   hk   03/07/14 Added check for error status in the while loop that
50 *                     checks for completion. CR# 762244, 764875.
51 * 2.1   hk   04/24/14 Fix for CR# 789821 to handle >14 byte transfers.
52 *                     Fix for CR# 761060 - provision for repeated start.
53 *
54 * </pre>
55 *
56 ******************************************************************************/
57
58 /***************************** Include Files *********************************/
59
60 #include "xiicps.h"
61
62 /************************** Constant Definitions *****************************/
63
64 /**************************** Type Definitions *******************************/
65
66 /***************** Macros (Inline Functions) Definitions *********************/
67
68 /************************** Function Prototypes ******************************/
69 int TransmitFifoFill(XIicPs *InstancePtr);
70
71 static int XIicPs_SetupMaster(XIicPs *InstancePtr, int Role);
72 static void MasterSendData(XIicPs *InstancePtr);
73
74 /************************* Variable Definitions *****************************/
75
76 /*****************************************************************************/
77 /**
78 * This function initiates an interrupt-driven send in master mode.
79 *
80 * It tries to send the first FIFO-full of data, then lets the interrupt
81 * handler to handle the rest of the data if there is any.
82 *
83 * @param        InstancePtr is a pointer to the XIicPs instance.
84 * @param        MsgPtr is the pointer to the send buffer.
85 * @param        ByteCount is the number of bytes to be sent.
86 * @param        SlaveAddr is the address of the slave we are sending to.
87 *
88 * @return       None.
89 *
90 * @note         This send routine is for interrupt-driven transfer only.
91 *
92  ****************************************************************************/
93 void XIicPs_MasterSend(XIicPs *InstancePtr, u8 *MsgPtr, int ByteCount,
94                  u16 SlaveAddr)
95 {
96         u32 BaseAddr;
97
98         /*
99          * Assert validates the input arguments.
100          */
101         Xil_AssertVoid(InstancePtr != NULL);
102         Xil_AssertVoid(MsgPtr != NULL);
103         Xil_AssertVoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY);
104         Xil_AssertVoid(XIICPS_ADDR_MASK >= SlaveAddr);
105
106
107         BaseAddr = InstancePtr->Config.BaseAddress;
108         InstancePtr->SendBufferPtr = MsgPtr;
109         InstancePtr->SendByteCount = ByteCount;
110         InstancePtr->RecvBufferPtr = NULL;
111         InstancePtr->IsSend = 1;
112
113         /*
114          * Set repeated start if sending more than FIFO of data.
115          */
116         if ((InstancePtr->IsRepeatedStart) ||
117                 (ByteCount > XIICPS_FIFO_DEPTH)) {
118                 XIicPs_WriteReg(BaseAddr, XIICPS_CR_OFFSET,
119                         XIicPs_ReadReg(BaseAddr, XIICPS_CR_OFFSET) |
120                                 XIICPS_CR_HOLD_MASK);
121         }
122
123         /*
124          * Setup as a master sending role.
125          */
126         XIicPs_SetupMaster(InstancePtr, SENDING_ROLE);
127
128         /*
129          * Do the address transfer to notify the slave.
130          */
131         XIicPs_WriteReg(BaseAddr, XIICPS_ADDR_OFFSET, SlaveAddr);
132
133         TransmitFifoFill(InstancePtr);
134
135         XIicPs_EnableInterrupts(BaseAddr,
136                 XIICPS_IXR_NACK_MASK | XIICPS_IXR_COMP_MASK |
137                 XIICPS_IXR_ARB_LOST_MASK);
138 }
139
140 /*****************************************************************************/
141 /**
142 * This function initiates an interrupt-driven receive in master mode.
143 *
144 * It sets the transfer size register so the slave can send data to us.
145 * The rest of the work is managed by interrupt handler.
146 *
147 * @param        InstancePtr is a pointer to the XIicPs instance.
148 * @param        MsgPtr is the pointer to the receive buffer.
149 * @param        ByteCount is the number of bytes to be received.
150 * @param        SlaveAddr is the address of the slave we are receiving from.
151 *
152 * @return       None.
153 *
154 * @note         This receive routine is for interrupt-driven transfer only.
155 *
156 ****************************************************************************/
157 void XIicPs_MasterRecv(XIicPs *InstancePtr, u8 *MsgPtr, int ByteCount,
158                  u16 SlaveAddr)
159 {
160         u32 BaseAddr;
161
162         /*
163          * Assert validates the input arguments.
164          */
165         Xil_AssertVoid(InstancePtr != NULL);
166         Xil_AssertVoid(MsgPtr != NULL);
167         Xil_AssertVoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY);
168         Xil_AssertVoid(XIICPS_ADDR_MASK >= SlaveAddr);
169
170         BaseAddr = InstancePtr->Config.BaseAddress;
171         InstancePtr->RecvBufferPtr = MsgPtr;
172         InstancePtr->RecvByteCount = ByteCount;
173         InstancePtr->CurrByteCount = ByteCount;
174         InstancePtr->SendBufferPtr = NULL;
175         InstancePtr->IsSend = 0;
176         InstancePtr->UpdateTxSize = 0;
177
178         if ((ByteCount > XIICPS_DATA_INTR_DEPTH) ||
179                 (InstancePtr->IsRepeatedStart))
180         {
181                 XIicPs_WriteReg(BaseAddr, XIICPS_CR_OFFSET,
182                                 XIicPs_ReadReg(BaseAddr, XIICPS_CR_OFFSET) |
183                                                 XIICPS_CR_HOLD_MASK);
184         }
185
186         /*
187          * Initialize for a master receiving role.
188          */
189         XIicPs_SetupMaster(InstancePtr, RECVING_ROLE);
190
191         /*
192          * Do the address transfer to signal the slave.
193          */
194         XIicPs_WriteReg(BaseAddr, XIICPS_ADDR_OFFSET, SlaveAddr);
195
196         /*
197          * Setup the transfer size register so the slave knows how much
198          * to send to us.
199          */
200         if (ByteCount > XIICPS_MAX_TRANSFER_SIZE) {
201                 XIicPs_WriteReg(BaseAddr, XIICPS_TRANS_SIZE_OFFSET,
202                                 XIICPS_MAX_TRANSFER_SIZE);
203                 InstancePtr->CurrByteCount = XIICPS_MAX_TRANSFER_SIZE;
204                 InstancePtr->UpdateTxSize = 1;
205         }else {
206                 XIicPs_WriteReg(BaseAddr, XIICPS_TRANS_SIZE_OFFSET,
207                          ByteCount);
208         }
209
210         XIicPs_EnableInterrupts(BaseAddr,
211                 XIICPS_IXR_NACK_MASK | XIICPS_IXR_DATA_MASK |
212                 XIICPS_IXR_RX_OVR_MASK | XIICPS_IXR_COMP_MASK |
213                 XIICPS_IXR_ARB_LOST_MASK);
214 }
215
216 /*****************************************************************************/
217 /**
218 * This function initiates a polled mode send in master mode.
219 *
220 * It sends data to the FIFO and waits for the slave to pick them up.
221 * If slave fails to remove data from FIFO, the send fails with
222 * time out.
223 *
224 * @param        InstancePtr is a pointer to the XIicPs instance.
225 * @param        MsgPtr is the pointer to the send buffer.
226 * @param        ByteCount is the number of bytes to be sent.
227 * @param        SlaveAddr is the address of the slave we are sending to.
228 *
229 * @return
230 *               - XST_SUCCESS if everything went well.
231 *               - XST_FAILURE if timed out.
232 *
233 * @note         This send routine is for polled mode transfer only.
234 *
235 ****************************************************************************/
236 int XIicPs_MasterSendPolled(XIicPs *InstancePtr, u8 *MsgPtr,
237                  int ByteCount, u16 SlaveAddr)
238 {
239         u32 IntrStatusReg;
240         u32 StatusReg;
241         u32 BaseAddr;
242         u32 Intrs;
243
244         /*
245          * Assert validates the input arguments.
246          */
247         Xil_AssertNonvoid(InstancePtr != NULL);
248         Xil_AssertNonvoid(MsgPtr != NULL);
249         Xil_AssertNonvoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY);
250         Xil_AssertNonvoid(XIICPS_ADDR_MASK >= SlaveAddr);
251
252         BaseAddr = InstancePtr->Config.BaseAddress;
253         InstancePtr->SendBufferPtr = MsgPtr;
254         InstancePtr->SendByteCount = ByteCount;
255
256         if ((InstancePtr->IsRepeatedStart) ||
257                 (ByteCount > XIICPS_FIFO_DEPTH)) {
258                 XIicPs_WriteReg(BaseAddr, XIICPS_CR_OFFSET,
259                                 XIicPs_ReadReg(BaseAddr, XIICPS_CR_OFFSET) |
260                                                 XIICPS_CR_HOLD_MASK);
261         }
262
263         XIicPs_SetupMaster(InstancePtr, SENDING_ROLE);
264
265         XIicPs_WriteReg(BaseAddr, XIICPS_ADDR_OFFSET, SlaveAddr);
266
267         /*
268          * Intrs keeps all the error-related interrupts.
269          */
270         Intrs = XIICPS_IXR_ARB_LOST_MASK | XIICPS_IXR_TX_OVR_MASK |
271                 XIICPS_IXR_NACK_MASK;
272
273         /*
274          * Clear the interrupt status register before use it to monitor.
275          */
276         IntrStatusReg = XIicPs_ReadReg(BaseAddr, XIICPS_ISR_OFFSET);
277         XIicPs_WriteReg(BaseAddr, XIICPS_ISR_OFFSET, IntrStatusReg);
278
279         /*
280          * Transmit first FIFO full of data.
281          */
282         TransmitFifoFill(InstancePtr);
283
284         IntrStatusReg = XIicPs_ReadReg(BaseAddr, XIICPS_ISR_OFFSET);
285
286         /*
287          * Continue sending as long as there is more data and
288          * there are no errors.
289          */
290         while ((InstancePtr->SendByteCount > 0) &&
291                 ((IntrStatusReg & Intrs) == 0)) {
292                 StatusReg = XIicPs_ReadReg(BaseAddr, XIICPS_SR_OFFSET);
293
294                 /*
295                  * Wait until transmit FIFO is empty.
296                  */
297                 if ((StatusReg & XIICPS_SR_TXDV_MASK) != 0) {
298                         IntrStatusReg = XIicPs_ReadReg(BaseAddr,
299                                         XIICPS_ISR_OFFSET);
300                         continue;
301                 }
302
303                 /*
304                  * Send more data out through transmit FIFO.
305                  */
306                 TransmitFifoFill(InstancePtr);
307         }
308
309         /*
310          * Check for completion of transfer.
311          */
312         while ((IntrStatusReg & XIICPS_IXR_COMP_MASK) != XIICPS_IXR_COMP_MASK){
313
314                 IntrStatusReg = XIicPs_ReadReg(BaseAddr, XIICPS_ISR_OFFSET);
315                 /*
316                  * If there is an error, tell the caller.
317                  */
318                 if ((IntrStatusReg & Intrs) != 0) {
319                         return XST_FAILURE;
320                 }
321         }
322
323         if (!(InstancePtr->IsRepeatedStart)) {
324                 XIicPs_WriteReg(BaseAddr, XIICPS_CR_OFFSET,
325                                 XIicPs_ReadReg(BaseAddr,XIICPS_CR_OFFSET) &
326                                                 (~XIICPS_CR_HOLD_MASK));
327         }
328
329         return XST_SUCCESS;
330 }
331
332 /*****************************************************************************/
333 /**
334 * This function initiates a polled mode receive in master mode.
335 *
336 * It repeatedly sets the transfer size register so the slave can
337 * send data to us. It polls the data register for data to come in.
338 * If slave fails to send us data, it fails with time out.
339 *
340 * @param        InstancePtr is a pointer to the XIicPs instance.
341 * @param        MsgPtr is the pointer to the receive buffer.
342 * @param        ByteCount is the number of bytes to be received.
343 * @param        SlaveAddr is the address of the slave we are receiving from.
344 *
345 * @return
346 *               - XST_SUCCESS if everything went well.
347 *               - XST_FAILURE if timed out.
348 *
349 * @note         This receive routine is for polled mode transfer only.
350 *
351 ****************************************************************************/
352 int XIicPs_MasterRecvPolled(XIicPs *InstancePtr, u8 *MsgPtr,
353                                 int ByteCount, u16 SlaveAddr)
354 {
355         u32 IntrStatusReg;
356         u32 Intrs;
357         u32 StatusReg;
358         u32 BaseAddr;
359         int IsHold = 0;
360         int UpdateTxSize = 0;
361
362         /*
363          * Assert validates the input arguments.
364          */
365         Xil_AssertNonvoid(InstancePtr != NULL);
366         Xil_AssertNonvoid(MsgPtr != NULL);
367         Xil_AssertNonvoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY);
368         Xil_AssertNonvoid(XIICPS_ADDR_MASK >= SlaveAddr);
369
370         BaseAddr = InstancePtr->Config.BaseAddress;
371         InstancePtr->RecvBufferPtr = MsgPtr;
372         InstancePtr->RecvByteCount = ByteCount;
373
374         if((ByteCount > XIICPS_DATA_INTR_DEPTH) ||
375                 (InstancePtr->IsRepeatedStart))
376         {
377                 XIicPs_WriteReg(BaseAddr, XIICPS_CR_OFFSET,
378                                 XIicPs_ReadReg(BaseAddr, XIICPS_CR_OFFSET) |
379                                                 XIICPS_CR_HOLD_MASK);
380                 IsHold = 1;
381         }
382
383         XIicPs_SetupMaster(InstancePtr, RECVING_ROLE);
384
385         /*
386          * Clear the interrupt status register before use it to monitor.
387          */
388         IntrStatusReg = XIicPs_ReadReg(BaseAddr, XIICPS_ISR_OFFSET);
389         XIicPs_WriteReg(BaseAddr, XIICPS_ISR_OFFSET, IntrStatusReg);
390
391         XIicPs_WriteReg(BaseAddr, XIICPS_ADDR_OFFSET, SlaveAddr);
392
393         /*
394          * Set up the transfer size register so the slave knows how much
395          * to send to us.
396          */
397         if (ByteCount > XIICPS_MAX_TRANSFER_SIZE) {
398                 XIicPs_WriteReg(BaseAddr, XIICPS_TRANS_SIZE_OFFSET,
399                                 XIICPS_MAX_TRANSFER_SIZE);
400                 ByteCount = XIICPS_MAX_TRANSFER_SIZE;
401                 UpdateTxSize = 1;
402         }else {
403                 XIicPs_WriteReg(BaseAddr, XIICPS_TRANS_SIZE_OFFSET,
404                          ByteCount);
405         }
406
407         /*
408          * Intrs keeps all the error-related interrupts.
409          */
410         Intrs = XIICPS_IXR_ARB_LOST_MASK | XIICPS_IXR_RX_OVR_MASK |
411                         XIICPS_IXR_RX_UNF_MASK | XIICPS_IXR_NACK_MASK;
412
413         /*
414          * Poll the interrupt status register to find the errors.
415          */
416         IntrStatusReg = XIicPs_ReadReg(BaseAddr, XIICPS_ISR_OFFSET);
417         while ((InstancePtr->RecvByteCount > 0) &&
418                         ((IntrStatusReg & Intrs) == 0)) {
419                 StatusReg = XIicPs_ReadReg(BaseAddr, XIICPS_SR_OFFSET);
420
421                 while (StatusReg & XIICPS_SR_RXDV_MASK) {
422                         if ((InstancePtr->RecvByteCount <
423                                 XIICPS_DATA_INTR_DEPTH) && IsHold &&
424                                 (!(InstancePtr->IsRepeatedStart))) {
425                                 IsHold = 0;
426                                 XIicPs_WriteReg(BaseAddr, XIICPS_CR_OFFSET,
427                                                 XIicPs_ReadReg(BaseAddr,
428                                                 XIICPS_CR_OFFSET) &
429                                                 (~XIICPS_CR_HOLD_MASK));
430                         }
431                         XIicPs_RecvByte(InstancePtr);
432                         ByteCount --;
433
434                         if (UpdateTxSize &&
435                                 (ByteCount == XIICPS_FIFO_DEPTH + 1))
436                                 break;
437
438                         StatusReg = XIicPs_ReadReg(BaseAddr, XIICPS_SR_OFFSET);
439                 }
440
441                 if (UpdateTxSize && (ByteCount == XIICPS_FIFO_DEPTH + 1)) {
442                         /*
443                          * wait while fifo is full
444                          */
445                         while(XIicPs_ReadReg(BaseAddr,
446                                 XIICPS_TRANS_SIZE_OFFSET) !=
447                                 (ByteCount - XIICPS_FIFO_DEPTH));
448
449                         if ((InstancePtr->RecvByteCount - XIICPS_FIFO_DEPTH) >
450                                 XIICPS_MAX_TRANSFER_SIZE) {
451
452                                 XIicPs_WriteReg(BaseAddr,
453                                         XIICPS_TRANS_SIZE_OFFSET,
454                                         XIICPS_MAX_TRANSFER_SIZE);
455                                 ByteCount = XIICPS_MAX_TRANSFER_SIZE +
456                                                 XIICPS_FIFO_DEPTH;
457                         }else {
458                                 XIicPs_WriteReg(BaseAddr,
459                                         XIICPS_TRANS_SIZE_OFFSET,
460                                         InstancePtr->RecvByteCount -
461                                         XIICPS_FIFO_DEPTH);
462                                 UpdateTxSize = 0;
463                                 ByteCount = InstancePtr->RecvByteCount;
464                         }
465                 }
466
467                 IntrStatusReg = XIicPs_ReadReg(BaseAddr, XIICPS_ISR_OFFSET);
468         }
469
470         if (!(InstancePtr->IsRepeatedStart)) {
471                 XIicPs_WriteReg(BaseAddr, XIICPS_CR_OFFSET,
472                                 XIicPs_ReadReg(BaseAddr,XIICPS_CR_OFFSET) &
473                                                 (~XIICPS_CR_HOLD_MASK));
474         }
475
476         if (IntrStatusReg & Intrs) {
477                 return XST_FAILURE;
478         }
479
480         return XST_SUCCESS;
481 }
482
483 /*****************************************************************************/
484 /**
485 * This function enables the slave monitor mode.
486 *
487 * It enables slave monitor in the control register and enables
488 * slave ready interrupt. It then does an address transfer to slave.
489 * Interrupt handler will signal the caller if slave responds to
490 * the address transfer.
491 *
492 * @param        InstancePtr is a pointer to the XIicPs instance.
493 * @param        SlaveAddr is the address of the slave we want to contact.
494 *
495 * @return       None.
496 *
497 * @note         None.
498 *
499 ****************************************************************************/
500 void XIicPs_EnableSlaveMonitor(XIicPs *InstancePtr, u16 SlaveAddr)
501 {
502         u32 BaseAddr;
503
504         Xil_AssertVoid(InstancePtr != NULL);
505
506         BaseAddr = InstancePtr->Config.BaseAddress;
507
508         /*
509          * Enable slave monitor mode in control register.
510          */
511         XIicPs_WriteReg(BaseAddr, XIICPS_CR_OFFSET,
512         XIicPs_ReadReg(BaseAddr, XIICPS_CR_OFFSET) |
513                                 XIICPS_CR_MS_MASK |
514                                 XIICPS_CR_NEA_MASK |
515                                 XIICPS_CR_SLVMON_MASK );
516
517         /*
518          * Set up interrupt flag for slave monitor interrupt.
519          */
520         XIicPs_EnableInterrupts(BaseAddr, XIICPS_IXR_NACK_MASK |
521                                 XIICPS_IXR_SLV_RDY_MASK);
522
523         /*
524          * Initialize the slave monitor register.
525          */
526         XIicPs_WriteReg(BaseAddr, XIICPS_SLV_PAUSE_OFFSET, 0xF);
527
528         /*
529          * Set the slave address to start the slave address transmission.
530          */
531         XIicPs_WriteReg(BaseAddr, XIICPS_ADDR_OFFSET, SlaveAddr);
532
533         return;
534 }
535
536 /*****************************************************************************/
537 /**
538 * This function disables slave monitor mode.
539 *
540 * @param        InstancePtr is a pointer to the XIicPs instance.
541 *
542 * @return       None.
543 *
544 * @note         None.
545 *
546 ****************************************************************************/
547 void XIicPs_DisableSlaveMonitor(XIicPs *InstancePtr)
548 {
549         u32 BaseAddr;
550
551         Xil_AssertVoid(InstancePtr != NULL);
552
553         BaseAddr = InstancePtr->Config.BaseAddress;
554
555         /*
556          * Clear slave monitor control bit.
557          */
558         XIicPs_WriteReg(BaseAddr, XIICPS_CR_OFFSET,
559                 XIicPs_ReadReg(BaseAddr, XIICPS_CR_OFFSET)
560                         & (~XIICPS_CR_SLVMON_MASK));
561
562         /*
563          * Clear interrupt flag for slave monitor interrupt.
564          */
565         XIicPs_DisableInterrupts(BaseAddr, XIICPS_IXR_SLV_RDY_MASK);
566
567         return;
568 }
569
570 /*****************************************************************************/
571 /**
572 * The interrupt handler for the master mode. It does the protocol handling for
573 * the interrupt-driven transfers.
574 *
575 * Completion events and errors are signaled to upper layer for proper handling.
576 *
577 * <pre>
578 * The interrupts that are handled are:
579 * - DATA
580 *       This case is handled only for master receive data.
581 *       The master has to request for more data (if there is more data to
582 *       receive) and read the data from the FIFO .
583 *
584 * - COMP
585 *       If the Master is transmitting data and there is more data to be
586 *       sent then the data is written to the FIFO. If there is no more data to
587 *       be transmitted then a completion event is signalled to the upper layer
588 *       by calling the callback handler.
589 *
590 *       If the Master is receiving data then the data is read from the FIFO and
591 *       the Master has to request for more data (if there is more data to
592 *       receive). If all the data has been received then a completion event
593 *       is signalled to the upper layer by calling the callback handler.
594 *       It is an error if the amount of received data is more than expected.
595 *
596 * - NAK and SLAVE_RDY
597 *       This is signalled to the upper layer by calling the callback handler.
598 *
599 * - All Other interrupts
600 *       These interrupts are marked as error. This is signalled to the upper
601 *       layer by calling the callback handler.
602 *
603 * </pre>
604 *
605 * @param        InstancePtr is a pointer to the XIicPs instance.
606 *
607 * @return       None.
608 *
609 * @note         None.
610 *
611 ****************************************************************************/
612 void XIicPs_MasterInterruptHandler(XIicPs *InstancePtr)
613 {
614         u32 IntrStatusReg;
615         u32 StatusEvent = 0;
616         u32 BaseAddr;
617         int ByteCnt;
618         int IsHold;
619
620         /*
621          * Assert validates the input arguments.
622          */
623         Xil_AssertVoid(InstancePtr != NULL);
624         Xil_AssertVoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY);
625
626         BaseAddr = InstancePtr->Config.BaseAddress;
627
628         /*
629          * Read the Interrupt status register.
630          */
631         IntrStatusReg = XIicPs_ReadReg(BaseAddr,
632                                          XIICPS_ISR_OFFSET);
633
634         /*
635          * Write the status back to clear the interrupts so no events are
636          * missed while processing this interrupt.
637          */
638         XIicPs_WriteReg(BaseAddr, XIICPS_ISR_OFFSET, IntrStatusReg);
639
640         /*
641          * Use the Mask register AND with the Interrupt Status register so
642          * disabled interrupts are not processed.
643          */
644         IntrStatusReg &= ~(XIicPs_ReadReg(BaseAddr, XIICPS_IMR_OFFSET));
645
646         ByteCnt = InstancePtr->CurrByteCount;
647
648         IsHold = 0;
649         if (XIicPs_ReadReg(BaseAddr, XIICPS_CR_OFFSET) & XIICPS_CR_HOLD_MASK) {
650                 IsHold = 1;
651         }
652
653         /*
654          * Send
655          */
656         if ((InstancePtr->IsSend) &&
657                 (0 != (IntrStatusReg & XIICPS_IXR_COMP_MASK))) {
658                 if (InstancePtr->SendByteCount > 0) {
659                         MasterSendData(InstancePtr);
660                 } else {
661                         StatusEvent |= XIICPS_EVENT_COMPLETE_SEND;
662                 }
663         }
664
665
666         /*
667          * Receive
668          */
669         if ((!(InstancePtr->IsSend)) &&
670                 ((0 != (IntrStatusReg & XIICPS_IXR_DATA_MASK)) ||
671                 (0 != (IntrStatusReg & XIICPS_IXR_COMP_MASK)))){
672
673                 while (XIicPs_ReadReg(BaseAddr, XIICPS_SR_OFFSET) &
674                                 XIICPS_SR_RXDV_MASK) {
675                         if ((InstancePtr->RecvByteCount <
676                                 XIICPS_DATA_INTR_DEPTH) && IsHold &&
677                                 (!(InstancePtr->IsRepeatedStart))) {
678                                 IsHold = 0;
679                                 XIicPs_WriteReg(BaseAddr, XIICPS_CR_OFFSET,
680                                                 XIicPs_ReadReg(BaseAddr,
681                                                 XIICPS_CR_OFFSET) &
682                                                 (~XIICPS_CR_HOLD_MASK));
683                         }
684                         XIicPs_RecvByte(InstancePtr);
685                         ByteCnt--;
686
687                         if (InstancePtr->UpdateTxSize &&
688                                 (ByteCnt == XIICPS_FIFO_DEPTH + 1))
689                                 break;
690                 }
691
692                 if (InstancePtr->UpdateTxSize &&
693                         (ByteCnt == XIICPS_FIFO_DEPTH + 1)) {
694                         /*
695                          * wait while fifo is full
696                          */
697                         while(XIicPs_ReadReg(BaseAddr,
698                                 XIICPS_TRANS_SIZE_OFFSET) !=
699                                 (ByteCnt - XIICPS_FIFO_DEPTH));
700
701                         if ((InstancePtr->RecvByteCount - XIICPS_FIFO_DEPTH) >
702                                 XIICPS_MAX_TRANSFER_SIZE) {
703
704                                 XIicPs_WriteReg(BaseAddr,
705                                         XIICPS_TRANS_SIZE_OFFSET,
706                                         XIICPS_MAX_TRANSFER_SIZE);
707                                 ByteCnt = XIICPS_MAX_TRANSFER_SIZE +
708                                                 XIICPS_FIFO_DEPTH;
709                         }else {
710                                 XIicPs_WriteReg(BaseAddr,
711                                         XIICPS_TRANS_SIZE_OFFSET,
712                                         InstancePtr->RecvByteCount -
713                                         XIICPS_FIFO_DEPTH);
714                                 InstancePtr->UpdateTxSize = 0;
715                                 ByteCnt = InstancePtr->RecvByteCount;
716                         }
717                 }
718                 InstancePtr->CurrByteCount = ByteCnt;
719         }
720
721         if ((!(InstancePtr->IsSend)) &&
722                 (0 != (IntrStatusReg & XIICPS_IXR_COMP_MASK))) {
723                 /*
724                  * If all done, tell the application.
725                  */
726                 if (InstancePtr->RecvByteCount == 0){
727                         if (!(InstancePtr->IsRepeatedStart)) {
728                                 XIicPs_WriteReg(BaseAddr, XIICPS_CR_OFFSET,
729                                                 XIicPs_ReadReg(BaseAddr,
730                                                 XIICPS_CR_OFFSET) &
731                                                 (~XIICPS_CR_HOLD_MASK));
732                         }
733                         StatusEvent |= XIICPS_EVENT_COMPLETE_RECV;
734                 }
735         }
736
737
738         /*
739          * Slave ready interrupt, it is only meaningful for master mode.
740          */
741         if (0 != (IntrStatusReg & XIICPS_IXR_SLV_RDY_MASK)) {
742                 StatusEvent |= XIICPS_EVENT_SLAVE_RDY;
743         }
744
745         if (0 != (IntrStatusReg & XIICPS_IXR_NACK_MASK)) {
746                 if (!(InstancePtr->IsRepeatedStart)) {
747                         XIicPs_WriteReg(BaseAddr, XIICPS_CR_OFFSET,
748                                         XIicPs_ReadReg(BaseAddr,
749                                         XIICPS_CR_OFFSET) &
750                                         (~XIICPS_CR_HOLD_MASK));
751                 }
752                 StatusEvent |= XIICPS_EVENT_NACK;
753         }
754
755         /*
756          * All other interrupts are treated as error.
757          */
758         if (0 != (IntrStatusReg & (XIICPS_IXR_NACK_MASK |
759                         XIICPS_IXR_ARB_LOST_MASK | XIICPS_IXR_RX_UNF_MASK |
760                         XIICPS_IXR_TX_OVR_MASK | XIICPS_IXR_RX_OVR_MASK))) {
761                 if (!(InstancePtr->IsRepeatedStart)) {
762                         XIicPs_WriteReg(BaseAddr, XIICPS_CR_OFFSET,
763                                         XIicPs_ReadReg(BaseAddr,
764                                         XIICPS_CR_OFFSET) &
765                                         (~XIICPS_CR_HOLD_MASK));
766                 }
767                 StatusEvent |= XIICPS_EVENT_ERROR;
768         }
769
770         /*
771          * Signal application if there are any events.
772          */
773         if (0 != StatusEvent) {
774                 InstancePtr->StatusHandler(InstancePtr->CallBackRef,
775                                            StatusEvent);
776         }
777
778 }
779
780 /*****************************************************************************/
781 /*
782 * This function prepares a device to transfers as a master.
783 *
784 * @param        InstancePtr is a pointer to the XIicPs instance.
785 *
786 * @param        Role specifies whether the device is sending or receiving.
787 *
788 * @return
789 *               - XST_SUCCESS if everything went well.
790 *               - XST_FAILURE if bus is busy.
791 *
792 * @note         Interrupts are always disabled, device which needs to use
793 *               interrupts needs to setup interrupts after this call.
794 *
795 ****************************************************************************/
796 static int XIicPs_SetupMaster(XIicPs *InstancePtr, int Role)
797 {
798         u32 ControlReg;
799         u32 BaseAddr;
800         u32 EnabledIntr = 0x0;
801
802         Xil_AssertNonvoid(InstancePtr != NULL);
803
804         BaseAddr = InstancePtr->Config.BaseAddress;
805         ControlReg = XIicPs_ReadReg(BaseAddr, XIICPS_CR_OFFSET);
806
807
808         /*
809          * Only check if bus is busy when repeated start option is not set.
810          */
811         if ((ControlReg & XIICPS_CR_HOLD_MASK) == 0) {
812                 if (XIicPs_BusIsBusy(InstancePtr)) {
813                         return XST_FAILURE;
814                 }
815         }
816
817         /*
818          * Set up master, AckEn, nea and also clear fifo.
819          */
820         ControlReg |= XIICPS_CR_ACKEN_MASK | XIICPS_CR_CLR_FIFO_MASK |
821                         XIICPS_CR_NEA_MASK | XIICPS_CR_MS_MASK;
822
823         if (Role == RECVING_ROLE) {
824                 ControlReg |= XIICPS_CR_RD_WR_MASK;
825                 EnabledIntr = XIICPS_IXR_DATA_MASK |XIICPS_IXR_RX_OVR_MASK;
826         }else {
827                 ControlReg &= ~XIICPS_CR_RD_WR_MASK;
828         }
829         EnabledIntr |= XIICPS_IXR_COMP_MASK | XIICPS_IXR_ARB_LOST_MASK;
830
831         XIicPs_WriteReg(BaseAddr, XIICPS_CR_OFFSET, ControlReg);
832
833         XIicPs_DisableAllInterrupts(BaseAddr);
834
835         return XST_SUCCESS;
836 }
837
838 /*****************************************************************************/
839 /*
840 * This function handles continuation of sending data. It is invoked
841 * from interrupt handler.
842 *
843 * @param        InstancePtr is a pointer to the XIicPs instance.
844 *
845 * @return       None.
846 *
847 * @note         None.
848 *
849 ****************************************************************************/
850 static void MasterSendData(XIicPs *InstancePtr)
851 {
852         TransmitFifoFill(InstancePtr);
853
854         /*
855          * Clear hold bit if done, so stop can be sent out.
856          */
857         if (InstancePtr->SendByteCount == 0) {
858
859                 /*
860                  * If user has enabled repeated start as an option,
861                  * do not disable it.
862                  */
863                 if (!(InstancePtr->IsRepeatedStart)) {
864
865                         XIicPs_WriteReg(InstancePtr->Config.BaseAddress,
866                                 XIICPS_CR_OFFSET,
867                                 XIicPs_ReadReg(InstancePtr->Config.BaseAddress,
868                                 XIICPS_CR_OFFSET) & ~ XIICPS_CR_HOLD_MASK);
869                 }
870         }
871
872         return;
873 }
874
875
876