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