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