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