make oldconfig will rebuild these...
[linux-2.4.21-pre4.git] / drivers / i2c / xilinx_iic / xiic_intr.c
1 /* $Id: xiic_intr.c,v 1.1.1.1 2005/04/11 02:50:21 jack Exp $ */
2 /******************************************************************************
3 *
4 *     Author: Xilinx, Inc.
5 *     
6 *     
7 *     This program is free software; you can redistribute it and/or modify it
8 *     under the terms of the GNU General Public License as published by the
9 *     Free Software Foundation; either version 2 of the License, or (at your
10 *     option) any later version.
11 *     
12 *     
13 *     XILINX IS PROVIDING THIS DESIGN, CODE, OR INFORMATION "AS IS" AS A
14 *     COURTESY TO YOU. BY PROVIDING THIS DESIGN, CODE, OR INFORMATION AS
15 *     ONE POSSIBLE IMPLEMENTATION OF THIS FEATURE, APPLICATION OR STANDARD,
16 *     XILINX IS MAKING NO REPRESENTATION THAT THIS IMPLEMENTATION IS FREE
17 *     FROM ANY CLAIMS OF INFRINGEMENT, AND YOU ARE RESPONSIBLE FOR
18 *     OBTAINING ANY RIGHTS YOU MAY REQUIRE FOR YOUR IMPLEMENTATION.
19 *     XILINX EXPRESSLY DISCLAIMS ANY WARRANTY WHATSOEVER WITH RESPECT TO
20 *     THE ADEQUACY OF THE IMPLEMENTATION, INCLUDING BUT NOT LIMITED TO ANY
21 *     WARRANTIES OR REPRESENTATIONS THAT THIS IMPLEMENTATION IS FREE FROM
22 *     CLAIMS OF INFRINGEMENT, IMPLIED WARRANTIES OF MERCHANTABILITY AND
23 *     FITNESS FOR A PARTICULAR PURPOSE.
24 *     
25 *     
26 *     Xilinx products are not intended for use in life support appliances,
27 *     devices, or systems. Use in such applications is expressly prohibited.
28 *     
29 *     
30 *     (c) Copyright 2002 Xilinx Inc.
31 *     All rights reserved.
32 *     
33 *     
34 *     You should have received a copy of the GNU General Public License along
35 *     with this program; if not, write to the Free Software Foundation, Inc.,
36 *     675 Mass Ave, Cambridge, MA 02139, USA.
37 *
38 ******************************************************************************/
39 /*****************************************************************************/
40 /**
41 *
42 * @file xiic_intr.c
43 *
44 * Contains interrupt functions of the XIic driver.  This file is required
45 * for the driver.
46 *
47 * <pre>
48 * MODIFICATION HISTORY:
49 *
50 * Ver   Who  Date     Changes
51 * ----- ---- -------- -----------------------------------------------
52 * 1.01a rfp  10/19/01 release
53 * </pre>
54 *
55 ******************************************************************************/
56
57 /***************************** Include Files *********************************/
58
59 #include "xiic.h"
60 #include "xiic_i.h"
61 #include "xio.h"
62
63 /************************** Constant Definitions *****************************/
64
65 /**************************** Type Definitions *******************************/
66
67 /***************** Macros (Inline Functions) Definitions ******************/
68
69 /*************** Macros (Inline Functions) Definitions ********************/
70
71 /************************** Function Prototypes ****************************/
72
73 static void StubFunction(XIic * InstancePtr);
74 static void TxErrorHandler(XIic * InstancePtr);
75
76 /************************** Variable Definitions *****************************/
77
78 /* The following function pointers are used to help allow finer partitioning
79  * of the driver such that some parts of it are optional. These pointers are
80  * setup by functions in the optional parts of the driver.
81  */
82 void (*XIic_AddrAsSlaveFuncPtr) (XIic * InstancePtr) = StubFunction;
83 void (*XIic_NotAddrAsSlaveFuncPtr) (XIic * InstancePtr) = StubFunction;
84 void (*XIic_RecvSlaveFuncPtr) (XIic * InstancePtr) = StubFunction;
85 void (*XIic_SendSlaveFuncPtr) (XIic * InstancePtr) = StubFunction;
86 void (*XIic_RecvMasterFuncPtr) (XIic * InstancePtr) = StubFunction;
87 void (*XIic_SendMasterFuncPtr) (XIic * InstancePtr) = StubFunction;
88 void (*XIic_ArbLostFuncPtr) (XIic * InstancePtr) = StubFunction;
89 void (*XIic_BusNotBusyFuncPtr) (XIic * InstancePtr) = StubFunction;
90
91 /*****************************************************************************/
92 /**
93 *
94 * This function is the interrupt handler for the XIic driver. This function
95 * should be connected to the interrupt system.
96 *
97 * Only one interrupt source is handled for each interrupt allowing
98 * higher priority system interrupts quicker response time.
99 *
100 * @param    InstancePtr is a pointer to the XIic instance to be worked on.
101 *
102 * @return
103 *
104 * None.
105 *
106 * @internal
107 *
108 * The XIIC_INTR_ARB_LOST_MASK and XIIC_INTR_TX_ERROR_MASK interrupts must have
109 * higher priority than the other device interrupts so that the IIC device does
110 * not get into a potentially confused state. The remaining interrupts may be
111 * rearranged with no harm.
112 *
113 * All XIic device interrupts are ORed into one device interrupt. This routine
114 * reads the pending interrupts via the IpIf interface and masks that with the
115 * interrupt mask to evaluate only the interrupts enabled.
116 *
117 ******************************************************************************/
118 void
119 XIic_InterruptHandler(void *InstancePtr)
120 {
121         u8 Status;
122         u32 IntrStatus;
123         u32 IntrPending;
124         u32 IntrEnable;
125         XIic *IicPtr = NULL;
126         u32 Clear = 0;
127
128         /*
129          * Verify that each of the inputs are valid.
130          */
131         XASSERT_VOID(InstancePtr != NULL);
132
133         /*
134          * Convert the non-typed pointer to an IIC instance pointer
135          */
136         IicPtr = (XIic *) InstancePtr;
137
138         /* Get the interrupt Status from the IPIF. There is no clearing of
139          * interrupts in the IPIF. Interrupts must be cleared at the source.
140          * To find which interrupts are pending; AND interrupts pending with
141          * interrupts masked.
142          */
143         IntrPending = XIIF_V123B_READ_IISR(IicPtr->BaseAddress);
144         IntrEnable = XIIF_V123B_READ_IIER(IicPtr->BaseAddress);
145         IntrStatus = IntrPending & IntrEnable;
146
147         /* Do not processes a devices interrupts if the device has no
148          * interrupts pending or the global interrupts have been disabled
149          */
150
151         if ((IntrStatus == 0) |
152             (XIIF_V123B_IS_GINTR_ENABLED(IicPtr->BaseAddress) == FALSE)) {
153                 return;
154         }
155
156         /* Update interrupt stats and get the contents of the status register
157          */
158         IicPtr->Stats.IicInterrupts++;
159         Status = XIo_In8(IicPtr->BaseAddress + XIIC_SR_REG_OFFSET);
160
161         /* Service requesting interrupt
162          */
163         if (IntrStatus & XIIC_INTR_ARB_LOST_MASK) {
164                 /* Bus Arbritration Lost */
165
166                 IicPtr->Stats.ArbitrationLost++;
167                 XIic_ArbLostFuncPtr(IicPtr);
168
169                 Clear = XIIC_INTR_ARB_LOST_MASK;
170         }
171
172         else if (IntrStatus & XIIC_INTR_TX_ERROR_MASK) {
173                 /* Transmit errors (no acknowledge) received */
174
175                 IicPtr->Stats.TxErrors++;
176                 TxErrorHandler(IicPtr);
177
178                 Clear = XIIC_INTR_TX_ERROR_MASK;
179         }
180
181         else if (IntrStatus & XIIC_INTR_NAAS_MASK) {
182                 /* Not Addressed As Slave */
183
184                 XIic_NotAddrAsSlaveFuncPtr(IicPtr);
185                 Clear = XIIC_INTR_NAAS_MASK;
186         }
187
188         else if (IntrStatus & XIIC_INTR_RX_FULL_MASK) {
189                 /* Receive register/FIFO is full */
190
191                 IicPtr->Stats.RecvInterrupts++;
192
193                 if (Status & XIIC_SR_ADDR_AS_SLAVE_MASK) {
194                         XIic_RecvSlaveFuncPtr(InstancePtr);
195                 } else {
196                         XIic_RecvMasterFuncPtr(InstancePtr);
197                 }
198
199                 Clear = XIIC_INTR_RX_FULL_MASK;
200         }
201
202         else if (IntrStatus & XIIC_INTR_AAS_MASK) {
203                 /* Addressed As Slave */
204
205                 XIic_AddrAsSlaveFuncPtr(IicPtr);
206                 Clear = XIIC_INTR_AAS_MASK;
207         }
208
209         else if (IntrStatus & XIIC_INTR_BNB_MASK) {
210                 /* IIC bus has transitioned to not busy */
211
212                 XIic_BusNotBusyFuncPtr(IicPtr);
213                 Clear = XIIC_INTR_BNB_MASK;
214         }
215
216         else if ((IntrStatus & XIIC_INTR_TX_EMPTY_MASK) ||
217                  (IntrStatus & XIIC_INTR_TX_HALF_MASK)) {
218                 /* Transmit register/FIFO is empty or ½ empty *
219                  */
220                 IicPtr->Stats.SendInterrupts++;
221
222                 if (Status & XIIC_SR_ADDR_AS_SLAVE_MASK) {
223                         XIic_SendSlaveFuncPtr(InstancePtr);
224                 } else {
225                         XIic_SendMasterFuncPtr(InstancePtr);
226                 }
227
228                 /* Clear Interrupts
229                  */
230                 IntrStatus = XIIF_V123B_READ_IISR(IicPtr->BaseAddress);
231                 Clear = IntrStatus & (XIIC_INTR_TX_EMPTY_MASK |
232                                       XIIC_INTR_TX_HALF_MASK);
233         }
234
235         XIIF_V123B_WRITE_IISR(IicPtr->BaseAddress, Clear);
236 }
237
238 /******************************************************************************
239 *
240 * This function fills the FIFO using the occupancy register to determine the
241 * available space to be filled. When the repeated start option is on, the last
242 * byte is withheld to allow the control register to be properly set on the last
243 * byte.
244 *
245 * @param    InstancePtr is a pointer to the XIic instance to be worked on.
246 *
247 * @param    Role indicates the role of this IIC device, a slave or a master, on
248 *           the IIC bus (XIIC_SLAVE_ROLE or XIIC_MASTER_ROLE)
249 *
250 * @return
251 *
252 * None.
253 *
254 * @note
255 *
256 * None.
257 *
258 ******************************************************************************/
259 void
260 XIic_TransmitFifoFill(XIic * InstancePtr, int Role)
261 {
262         u8 AvailBytes;
263         s32 LoopCnt;
264         s32 NumBytesToSend;
265
266         /* Determine number of bytes to write to FIFO. Number of bytes that can be
267          * put into the FIFO is (FIFO depth) - (current occupancy + 1)
268          * When more room in FIFO than msg bytes put all of message in the FIFO.
269          */
270         AvailBytes = IIC_TX_FIFO_DEPTH -
271             (XIo_In8(InstancePtr->BaseAddress + XIIC_TFO_REG_OFFSET) + 1);
272
273         if (InstancePtr->SendByteCount > AvailBytes) {
274                 NumBytesToSend = AvailBytes;
275         } else {
276                 /* More space in FIFO than bytes in message
277                  */
278                 if ((InstancePtr->Options & XII_REPEATED_START_OPTION) ||
279                     (Role == XIIC_SLAVE_ROLE)) {
280                         NumBytesToSend = InstancePtr->SendByteCount;
281                 } else {
282                         NumBytesToSend = InstancePtr->SendByteCount - 1;
283                 }
284         }
285
286         /* fill FIFO with amount determined above */
287
288         for (LoopCnt = 0; LoopCnt < NumBytesToSend; LoopCnt++) {
289                 XIic_mWriteSendByte(InstancePtr);
290         }
291 }
292
293 /*****************************************************************************/
294 /**
295 *
296 * This interrupt occurs four different ways: Two as master and two as slave.
297 * Master:
298 * <pre>
299 *  (1) Transmitter (IMPLIES AN ERROR)
300 *      The slave receiver did not acknowledge properly.
301 *  (2) Receiver (Implies tx complete)
302 *      Interrupt caused by setting TxAck high in the IIC to indicate to the
303 *      the last byte has been transmitted.
304 * </pre>
305 *
306 * Slave:
307 * <pre>
308 *  (3) Transmitter (Implies tx complete)
309 *      Interrupt caused by master device indicating last byte of the message
310 *      has been transmitted.
311 *  (4) Receiver (IMPLIES AN ERROR)
312 *      Interrupt caused by setting TxAck high in the IIC to indicate Rx
313 *      IIC had a problem - set by this device and condition already known
314 *      and interrupt is not enabled.
315 * </pre>
316 *
317 * This interrupt is enabled during Master send and receive and disabled
318 * when this device knows it is going to send a negative acknowledge (Ack = No).
319 *
320 * Signals user of Tx error via status callback sending: XII_TX_ERROR_EVENT
321 *
322 * When MasterRecv has no message to send and only receives one byte of data
323 * from the salve device, the TxError must be enabled to catch addressing
324 * errors, yet there is not opportunity to disable TxError when there is no
325 * data to send allowing disabling on last byte. When the slave sends the
326 * only byte the NOAck causes a Tx Error. To disregard this as no real error,
327 * when there is data in the Receive FIFO/register then the error was not
328 * a device address write error, but a NOACK read error - to be ignored.
329 * To work with or without FIFO's, the Rx Data interrupt is used to indicate
330 * data is in the rx register.
331 *
332 * @param    InstancePtr is a pointer to the XIic instance to be worked on.
333 *
334 * @return
335 *
336 * None.
337 *
338 * @note
339 *
340 * No action is required to clear this interrupt in the device as it is a
341 * pulse. The interrupt need only be cleared in the IpIf interface.
342 *
343 ******************************************************************************/
344 static void
345 TxErrorHandler(XIic * InstancePtr)
346 {
347         u32 IntrStatus;
348         u8 CntlReg;
349
350         /* When Sending as a slave, Tx error signals end of msg. Not Addressed As
351          * Slave will handle the callbacks. this is used to only flush the Tx fifo.
352          * The addressed as slave bit is gone as soon as the bus has been released
353          * such that the buffer pointers are used to determine the direction of
354          * transfer (send or receive).
355          */
356         if (InstancePtr->RecvBufferPtr == NULL) {
357                 /* Master Receiver finished reading message. Flush Tx fifo to remove an
358                  * 0xFF that was written to prevent bus throttling, and disable all
359                  * transmit and receive interrupts
360                  */
361                 XIic_mFlushTxFifo(InstancePtr);
362                 XIic_mDisableIntr(InstancePtr->BaseAddress,
363                                   XIIC_TX_RX_INTERRUPTS);
364
365                 return;
366         }
367
368         /* Data in the receive register from either master or slave receive
369          * When:slave, indicates master sent last byte, message completed.
370          * When:master, indicates a master Receive with one byte received. When a
371          * byte is in Rx reg then the Tx error indicates the Rx data was recovered
372          * normally Tx errors are not enabled such that this should not occur.
373          */
374         IntrStatus = XIIF_V123B_READ_IISR(InstancePtr->BaseAddress);
375         if (IntrStatus & XIIC_INTR_RX_FULL_MASK) {
376                 /* Rx Reg/FIFO has data,  Disable tx error interrupts */
377
378                 XIic_mDisableIntr(InstancePtr->BaseAddress,
379                                   XIIC_INTR_TX_ERROR_MASK);
380                 return;
381         }
382
383         XIic_mFlushTxFifo(InstancePtr);
384
385         /* Disable and clear tx empty, ½ empty, Rx Full or tx error interrupts
386          */
387         XIic_mDisableIntr(InstancePtr->BaseAddress, XIIC_TX_RX_INTERRUPTS);
388         XIic_mClearIntr(InstancePtr->BaseAddress, XIIC_TX_RX_INTERRUPTS);
389
390         /* Clear MSMS as on TX error when Rxing, the bus will be
391          * stopped but MSMS bit is still set. Reset to proper state
392          */
393         CntlReg = XIo_In8(InstancePtr->BaseAddress + XIIC_CR_REG_OFFSET);
394         CntlReg &= ~XIIC_CR_MSMS_MASK;
395         XIo_Out8(InstancePtr->BaseAddress + XIIC_CR_REG_OFFSET, CntlReg);
396
397         /* set FIFO occupancy depth = 1 so that the first byte will throttle
398          * next recieve msg
399          */
400         XIo_Out8(InstancePtr->BaseAddress + XIIC_RFD_REG_OFFSET, 0);
401
402         /* make event callback */
403
404         InstancePtr->StatusHandler(InstancePtr->StatusCallBackRef,
405                                    XII_SLAVE_NO_ACK_EVENT);
406 }
407
408 /*****************************************************************************/
409 /**
410 *
411 * This function is a stub function that is used for the default function for
412 * events that are handled optionally only when the appropriate modules are
413 * linked in.  Function pointers are used to handle some events to allow
414 * some events to be optionally handled.
415 *
416 * @param    InstancePtr is a pointer to the XIic instance to be worked on.
417 *
418 ******************************************************************************/
419 static void
420 StubFunction(XIic * InstancePtr)
421 {
422         XASSERT_VOID(FALSE);
423 }