1 /* $Id: xiic_intr.c,v 1.1.1.1 2005/04/11 02:50:21 jack Exp $ */
2 /******************************************************************************
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.
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.
26 * Xilinx products are not intended for use in life support appliances,
27 * devices, or systems. Use in such applications is expressly prohibited.
30 * (c) Copyright 2002 Xilinx Inc.
31 * All rights reserved.
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.
38 ******************************************************************************/
39 /*****************************************************************************/
44 * Contains interrupt functions of the XIic driver. This file is required
48 * MODIFICATION HISTORY:
50 * Ver Who Date Changes
51 * ----- ---- -------- -----------------------------------------------
52 * 1.01a rfp 10/19/01 release
55 ******************************************************************************/
57 /***************************** Include Files *********************************/
63 /************************** Constant Definitions *****************************/
65 /**************************** Type Definitions *******************************/
67 /***************** Macros (Inline Functions) Definitions ******************/
69 /*************** Macros (Inline Functions) Definitions ********************/
71 /************************** Function Prototypes ****************************/
73 static void StubFunction(XIic * InstancePtr);
74 static void TxErrorHandler(XIic * InstancePtr);
76 /************************** Variable Definitions *****************************/
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.
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;
91 /*****************************************************************************/
94 * This function is the interrupt handler for the XIic driver. This function
95 * should be connected to the interrupt system.
97 * Only one interrupt source is handled for each interrupt allowing
98 * higher priority system interrupts quicker response time.
100 * @param InstancePtr is a pointer to the XIic instance to be worked on.
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.
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.
117 ******************************************************************************/
119 XIic_InterruptHandler(void *InstancePtr)
129 * Verify that each of the inputs are valid.
131 XASSERT_VOID(InstancePtr != NULL);
134 * Convert the non-typed pointer to an IIC instance pointer
136 IicPtr = (XIic *) InstancePtr;
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
143 IntrPending = XIIF_V123B_READ_IISR(IicPtr->BaseAddress);
144 IntrEnable = XIIF_V123B_READ_IIER(IicPtr->BaseAddress);
145 IntrStatus = IntrPending & IntrEnable;
147 /* Do not processes a devices interrupts if the device has no
148 * interrupts pending or the global interrupts have been disabled
151 if ((IntrStatus == 0) |
152 (XIIF_V123B_IS_GINTR_ENABLED(IicPtr->BaseAddress) == FALSE)) {
156 /* Update interrupt stats and get the contents of the status register
158 IicPtr->Stats.IicInterrupts++;
159 Status = XIo_In8(IicPtr->BaseAddress + XIIC_SR_REG_OFFSET);
161 /* Service requesting interrupt
163 if (IntrStatus & XIIC_INTR_ARB_LOST_MASK) {
164 /* Bus Arbritration Lost */
166 IicPtr->Stats.ArbitrationLost++;
167 XIic_ArbLostFuncPtr(IicPtr);
169 Clear = XIIC_INTR_ARB_LOST_MASK;
172 else if (IntrStatus & XIIC_INTR_TX_ERROR_MASK) {
173 /* Transmit errors (no acknowledge) received */
175 IicPtr->Stats.TxErrors++;
176 TxErrorHandler(IicPtr);
178 Clear = XIIC_INTR_TX_ERROR_MASK;
181 else if (IntrStatus & XIIC_INTR_NAAS_MASK) {
182 /* Not Addressed As Slave */
184 XIic_NotAddrAsSlaveFuncPtr(IicPtr);
185 Clear = XIIC_INTR_NAAS_MASK;
188 else if (IntrStatus & XIIC_INTR_RX_FULL_MASK) {
189 /* Receive register/FIFO is full */
191 IicPtr->Stats.RecvInterrupts++;
193 if (Status & XIIC_SR_ADDR_AS_SLAVE_MASK) {
194 XIic_RecvSlaveFuncPtr(InstancePtr);
196 XIic_RecvMasterFuncPtr(InstancePtr);
199 Clear = XIIC_INTR_RX_FULL_MASK;
202 else if (IntrStatus & XIIC_INTR_AAS_MASK) {
203 /* Addressed As Slave */
205 XIic_AddrAsSlaveFuncPtr(IicPtr);
206 Clear = XIIC_INTR_AAS_MASK;
209 else if (IntrStatus & XIIC_INTR_BNB_MASK) {
210 /* IIC bus has transitioned to not busy */
212 XIic_BusNotBusyFuncPtr(IicPtr);
213 Clear = XIIC_INTR_BNB_MASK;
216 else if ((IntrStatus & XIIC_INTR_TX_EMPTY_MASK) ||
217 (IntrStatus & XIIC_INTR_TX_HALF_MASK)) {
218 /* Transmit register/FIFO is empty or ½ empty *
220 IicPtr->Stats.SendInterrupts++;
222 if (Status & XIIC_SR_ADDR_AS_SLAVE_MASK) {
223 XIic_SendSlaveFuncPtr(InstancePtr);
225 XIic_SendMasterFuncPtr(InstancePtr);
230 IntrStatus = XIIF_V123B_READ_IISR(IicPtr->BaseAddress);
231 Clear = IntrStatus & (XIIC_INTR_TX_EMPTY_MASK |
232 XIIC_INTR_TX_HALF_MASK);
235 XIIF_V123B_WRITE_IISR(IicPtr->BaseAddress, Clear);
238 /******************************************************************************
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
245 * @param InstancePtr is a pointer to the XIic instance to be worked on.
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)
258 ******************************************************************************/
260 XIic_TransmitFifoFill(XIic * InstancePtr, int Role)
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.
270 AvailBytes = IIC_TX_FIFO_DEPTH -
271 (XIo_In8(InstancePtr->BaseAddress + XIIC_TFO_REG_OFFSET) + 1);
273 if (InstancePtr->SendByteCount > AvailBytes) {
274 NumBytesToSend = AvailBytes;
276 /* More space in FIFO than bytes in message
278 if ((InstancePtr->Options & XII_REPEATED_START_OPTION) ||
279 (Role == XIIC_SLAVE_ROLE)) {
280 NumBytesToSend = InstancePtr->SendByteCount;
282 NumBytesToSend = InstancePtr->SendByteCount - 1;
286 /* fill FIFO with amount determined above */
288 for (LoopCnt = 0; LoopCnt < NumBytesToSend; LoopCnt++) {
289 XIic_mWriteSendByte(InstancePtr);
293 /*****************************************************************************/
296 * This interrupt occurs four different ways: Two as master and two as slave.
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.
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.
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).
320 * Signals user of Tx error via status callback sending: XII_TX_ERROR_EVENT
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.
332 * @param InstancePtr is a pointer to the XIic instance to be worked on.
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.
343 ******************************************************************************/
345 TxErrorHandler(XIic * InstancePtr)
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).
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
361 XIic_mFlushTxFifo(InstancePtr);
362 XIic_mDisableIntr(InstancePtr->BaseAddress,
363 XIIC_TX_RX_INTERRUPTS);
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.
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 */
378 XIic_mDisableIntr(InstancePtr->BaseAddress,
379 XIIC_INTR_TX_ERROR_MASK);
383 XIic_mFlushTxFifo(InstancePtr);
385 /* Disable and clear tx empty, ½ empty, Rx Full or tx error interrupts
387 XIic_mDisableIntr(InstancePtr->BaseAddress, XIIC_TX_RX_INTERRUPTS);
388 XIic_mClearIntr(InstancePtr->BaseAddress, XIIC_TX_RX_INTERRUPTS);
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
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);
397 /* set FIFO occupancy depth = 1 so that the first byte will throttle
400 XIo_Out8(InstancePtr->BaseAddress + XIIC_RFD_REG_OFFSET, 0);
402 /* make event callback */
404 InstancePtr->StatusHandler(InstancePtr->StatusCallBackRef,
405 XII_SLAVE_NO_ACK_EVENT);
408 /*****************************************************************************/
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.
416 * @param InstancePtr is a pointer to the XIic instance to be worked on.
418 ******************************************************************************/
420 StubFunction(XIic * InstancePtr)