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