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