1 /* $Id: xiic.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 required functions for the XIic component. See xiic.h for more
45 * information on the driver.
48 * MODIFICATION HISTORY:
50 * Ver Who Date Changes
51 * ----- --- ------- -----------------------------------------------
52 * 1.01a rfp 10/19/01 release
55 ****************************************************************************/
57 /***************************** Include Files *******************************/
62 #include "xparameters.h"
64 /************************** Constant Definitions ***************************/
66 /**************************** Type Definitions *****************************/
68 /***************** Macros (Inline Functions) Definitions *******************/
70 /************************** Function Prototypes ****************************/
72 static void XIic_StubStatusHandler(void *CallBackRef, XStatus ErrorCode);
74 static void XIic_StubHandler(void *CallBackRef, int ByteCount);
76 /************************** Variable Definitions **************************/
78 /*****************************************************************************/
81 * Initializes a specific XIic instance. The initialization entails:
83 * - Check the device has an entry in the configuration table.
84 * - Initialize the driver to allow access to the device registers and
85 * initialize other subcomponents necessary for the operation of the device.
86 * - Default options to:
87 * - 7-bit slave addressing
88 * - Send messages as a slave device
89 * - Repeated start off
90 * - General call recognition disabled
91 * - Clear messageing and error statistics
93 * The XIic_Start() function must be called after this function before the device
94 * is ready to send and receive data on the IIC bus.
96 * Before XIic_Start() is called, the interrupt control must connect the ISR
97 * routine to the interrupt handler. This is done by the user, and not
98 * XIic_Start() to allow the user to use an interrupt controller of their choice.
100 * @param InstancePtr is a pointer to the XIic instance to be worked on.
101 * @param DeviceId is the unique id of the device controlled by this XIic
102 * instance. Passing in a device id associates the generic XIic
103 * instance to a specific device, as chosen by the caller or
104 * application developer.
108 * - XST_SUCCESS when successful
109 * - XST_DEVICE_IS_STARTED indicates the device is started (i.e. interrupts
110 * enabled and messaging is possible). Must stop before re-initialization
117 ****************************************************************************/
119 XIic_Initialize(XIic * InstancePtr, u16 DeviceId)
121 XIic_Config *IicConfigPtr; /* Pointer to configuration data */
124 * Asserts test the validity of selected input arguments.
126 XASSERT_NONVOID(InstancePtr != NULL);
128 InstancePtr->IsReady = 0;
131 * If the device is started, disallow the initialize and return a Status
132 * indicating it is started. This allows the user to stop the device
133 * and reinitialize, but prevents a user from inadvertently initializing
135 if (InstancePtr->IsStarted == XCOMPONENT_IS_STARTED) {
136 return XST_DEVICE_IS_STARTED;
140 * Lookup the device configuration in the temporary CROM table. Use this
141 * configuration info down below when initializing this component.
143 IicConfigPtr = XIic_LookupConfig(DeviceId);
144 if (IicConfigPtr == NULL) {
145 return XST_DEVICE_NOT_FOUND;
148 * Set default values, including setting the callback
149 * handlers to stubs so the system will not crash should the
150 * application not assign its own callbacks.
152 InstancePtr->IsStarted = 0;
153 InstancePtr->BaseAddress = IicConfigPtr->BaseAddress;
154 InstancePtr->RecvHandler = XIic_StubHandler;
155 InstancePtr->SendHandler = XIic_StubHandler;
156 InstancePtr->StatusHandler = XIic_StubStatusHandler;
157 InstancePtr->Has10BitAddr = IicConfigPtr->Has10BitAddr;
158 InstancePtr->IsReady = XCOMPONENT_IS_READY;
159 InstancePtr->Options = 0;
162 * Reset the device so it's in the reset state, this must be after the
163 * IPIF is initialized since it resets thru the IPIF and clear the stats
165 XIic_Reset(InstancePtr);
167 XIIC_CLEAR_STATS(InstancePtr);
172 /*****************************************************************************/
175 * This function starts the IIC device and driver by enabling the proper
176 * interrupts such that data may be sent and received on the IIC bus.
177 * This function must be called before the functions to send and receive data.
179 * Before XIic_Start() is called, the interrupt control must connect the ISR
180 * routine to the interrupt handler. This is done by the user, and not
181 * XIic_Start() to allow the user to use an interrupt controller of their choice.
186 * - Addressed as slave to allow messages from another master
187 * - Arbitration Lost to detect Tx arbitration errors
188 * - Global IIC interrupt within the IPIF interface
190 * @param InstancePtr is a pointer to the XIic instance to be worked on.
198 * The device interrupt is connected to the interrupt controller, but no
199 * "messaging" interrupts are enabled. Addressed as Slave is enabled to
200 * reception of messages when this devices address is written to the bus.
201 * The correct messaging interrupts are enabled when sending or receiving
202 * via the IicSend() and IicRecv() functions. No action is required
203 * by the user to control any IIC interrupts as the driver completely
204 * manages all 8 interrupts. Start and Stop control the ability
205 * to use the device. Stopping the device completely stops all device
206 * interrupts from the processor.
208 ****************************************************************************/
210 XIic_Start(XIic * InstancePtr)
212 XASSERT_NONVOID(InstancePtr != NULL);
213 XASSERT_NONVOID(InstancePtr->IsReady == XCOMPONENT_IS_READY);
216 * Mask off all interrupts, each is enabled when needed.
218 XIIF_V123B_WRITE_IIER(InstancePtr->BaseAddress, 0);
221 * Clear all interrupts by reading and rewriting exact value back.
222 * Only those bits set will get written as 1 (writing 1 clears intr)
224 XIic_mClearIntr(InstancePtr->BaseAddress, 0xFFFFFFFF);
229 XIo_Out8(InstancePtr->BaseAddress + XIIC_CR_REG_OFFSET,
230 XIIC_CR_ENABLE_DEVICE_MASK);
232 * Set Rx FIFO Occupancy depth to throttle at first byte(after reset = 0)
234 XIo_Out8(InstancePtr->BaseAddress + XIIC_RFD_REG_OFFSET, 0);
237 * Clear and enable the interrupts needed
239 XIic_mClearEnableIntr(InstancePtr->BaseAddress,
240 XIIC_INTR_AAS_MASK | XIIC_INTR_ARB_LOST_MASK);
242 InstancePtr->IsStarted = XCOMPONENT_IS_STARTED;
244 /* Enable all interrupts by the global enable in the IPIF */
246 XIIF_V123B_GINTR_ENABLE(InstancePtr->BaseAddress);
251 /*****************************************************************************/
254 * This function stops the IIC device and driver such that data is no longer
255 * sent or received on the IIC bus. This function stops the device by
256 * disabling interrupts. This function only disables interrupts within the
257 * device such that the caller is responsible for disconnecting the interrupt
258 * handler of the device from the interrupt source and disabling interrupts
261 * Due to bus throttling that could hold the bus between messages when using
262 * repeated start option, stop will not occur when the device is actively
263 * sending or receiving data from the IIC bus or the bus is being throttled
264 * by this device, but instead return XST_IIC_BUS_BUSY.
266 * @param InstancePtr is a pointer to the XIic instance to be worked on.
270 * - XST_SUCCESS indicates all IIC interrupts are disabled. No messages can
271 * be received or transmitted until XIic_Start() is called.
272 * - XST_IIC_BUS_BUSY indicates this device is currently engaged in message
273 * traffic and cannot be stopped.
279 ****************************************************************************/
281 XIic_Stop(XIic * InstancePtr)
286 XASSERT_NONVOID(InstancePtr != NULL);
289 * Disable all interrupts globally using the IPIF
291 XIIF_V123B_GINTR_DISABLE(InstancePtr->BaseAddress);
293 CntlReg = XIo_In8(InstancePtr->BaseAddress + XIIC_CR_REG_OFFSET);
294 Status = XIo_In8(InstancePtr->BaseAddress + XIIC_SR_REG_OFFSET);
296 if ((CntlReg & XIIC_CR_MSMS_MASK)
297 || (Status & XIIC_SR_ADDR_AS_SLAVE_MASK)) {
298 /* when this device is using the bus
299 * - re-enable interrupts to finish current messaging
302 XIIF_V123B_GINTR_ENABLE(InstancePtr->BaseAddress);
304 return XST_IIC_BUS_BUSY;
307 InstancePtr->IsStarted = 0;
312 /*****************************************************************************/
315 * Resets the IIC device. Reset must only be called after the driver has been
316 * initialized. The configuration after this reset is as follows:
317 * - Repeated start is disabled
318 * - General call is disabled
320 * The upper layer software is responsible for initializing and re-configuring
321 * (if necessary) and restarting the IIC device after the reset.
323 * @param InstancePtr is a pointer to the XIic instance to be worked on.
335 * The reset is accomplished by setting the IPIF reset register. This takes
336 * care of resetting all IPIF hardware blocks, including the IIC device.
338 ****************************************************************************/
340 XIic_Reset(XIic * InstancePtr)
342 XASSERT_VOID(InstancePtr != NULL);
343 XASSERT_VOID(InstancePtr->IsReady == XCOMPONENT_IS_READY);
345 XIIF_V123B_RESET(InstancePtr->BaseAddress);
348 /*****************************************************************************/
351 * This function sets the bus addresses. The addresses include the device
352 * address that the device responds to as a slave, or the slave address
353 * to communicate with on the bus. The IIC device hardware is built to
354 * allow either 7 or 10 bit slave addressing only at build time rather
355 * than at run time. When this device is a master, slave addressing can
356 * be selected at run time to match addressing modes for other bus devices.
358 * Addresses are represented as hex values with no adjustment for the data
359 * direction bit as the software manages address bit placement.
360 * Example: For a 7 address written to the device of 1010 011X where X is
361 * the transfer direction (send/recv), the address parameter for this function
362 * needs to be 01010011 or 0x53 where the correct bit alllignment will be
363 * handled for 7 as well as 10 bit devices. This is especially important as
364 * the bit placement is not handled the same depending on which options are
365 * used such as repeated start.
367 * @param InstancePtr is a pointer to the XIic instance to be worked on.
368 * @param AddressType indicates which address is being modified; the address
369 * which this device responds to on the IIC bus as a slave, or the
370 * slave address to communicate with when this device is a master. One
371 * of the following values must be contained in this argument.
373 * XII_ADDRESS_TO_SEND Slave being addressed by a this master
374 * XII_ADDRESS_TO_RESPOND Address to respond to as a slave device
376 * @param Address contains the address to be set; 7 bit or 10 bit address.
377 * A ten bit address must be within the range: 0 - 1023 and a 7 bit
378 * address must be within the range 0 - 127.
382 * XST_SUCCESS is returned if the address was successfully set, otherwise one
383 * of the following errors is returned.
384 * - XST_IIC_NO_10_BIT_ADDRESSING indicates only 7 bit addressing supported.
385 * - XST_INVALID_PARAM indicates an invalid parameter was specified.
389 * Upper bits of 10-bit address is written only when current device is built
390 * as a ten bit device.
392 ****************************************************************************/
394 XIic_SetAddress(XIic * InstancePtr, int AddressType, int Address)
398 XASSERT_NONVOID(InstancePtr != NULL);
399 XASSERT_NONVOID(Address < 1023);
401 /* Set address to respond to for this device into address registers */
403 if (AddressType == XII_ADDR_TO_RESPOND_TYPE) {
404 SendAddr = (u8) ((Address & 0x007F) << 1); /* Addr in upper 7 bits */
405 XIo_Out8(InstancePtr->BaseAddress + XIIC_ADR_REG_OFFSET,
408 if (InstancePtr->Has10BitAddr == TRUE) {
409 /* Write upper 3 bits of addr to DTR only when 10 bit option
410 * included in design i.e. register exists
412 SendAddr = (u8) ((Address & 0x0380) >> 7);
413 XIo_Out8(InstancePtr->BaseAddress + XIIC_TBA_REG_OFFSET,
420 /* Store address of slave device being read from */
422 if (AddressType == XII_ADDR_TO_SEND_TYPE) {
423 InstancePtr->AddrOfSlave = Address;
427 return XST_INVALID_PARAM;
430 /*****************************************************************************/
433 * This function gets the addresses for the IIC device driver. The addresses
434 * include the device address that the device responds to as a slave, or the
435 * slave address to communicate with on the bus. The address returned has the
436 * same format whether 7 or 10 bits.
438 * @param InstancePtr is a pointer to the XIic instance to be worked on.
439 * @param AddressType indicates which address, the address which this
440 * responds to on the IIC bus as a slave, or the slave address to
441 * communicate with when this device is a master. One of the following
442 * values must be contained in this argument.
444 * XII_ADDRESS_TO_SEND_TYPE slave being addressed as a master
445 * XII_ADDRESS_TO_RESPOND_TYPE slave address to respond to as a slave
447 * If neither of the two valid arguments are used, the function returns
448 * the address of the slave device
452 * The address retrieved.
458 ****************************************************************************/
460 XIic_GetAddress(XIic * InstancePtr, int AddressType)
465 XASSERT_NONVOID(InstancePtr != NULL);
467 /* return this devices address */
469 if (AddressType == XII_ADDR_TO_RESPOND_TYPE) {
472 XIo_In8(InstancePtr->BaseAddress + XIIC_ADR_REG_OFFSET);
474 if (InstancePtr->Has10BitAddr == TRUE) {
475 HighAddr = (u16) XIo_In8(InstancePtr->BaseAddress +
476 XIIC_TBA_REG_OFFSET);
478 return ((HighAddr << 8) & (u16) LowAddr);
481 /* Otherwise return address of slave device on the IIC bus */
483 return InstancePtr->AddrOfSlave;
486 /*****************************************************************************/
489 * A function to determine if the device is currently addressed as a slave
491 * @param InstancePtr is a pointer to the XIic instance to be worked on.
495 * TRUE if the device is addressed as slave, and FALSE otherwise.
501 ****************************************************************************/
503 XIic_IsSlave(XIic * InstancePtr)
505 XASSERT_NONVOID(InstancePtr != NULL);
507 if ((XIo_In8(InstancePtr->BaseAddress + XIIC_SR_REG_OFFSET) &
508 XIIC_SR_ADDR_AS_SLAVE_MASK) == 0) {
514 /*****************************************************************************/
517 * Sets the receive callback function, the receive handler, which the driver
518 * calls when it finishes receiving data. The number of bytes used to signal
519 * when the receive is complete is the number of bytes set in the XIic_Recv
522 * The handler executes in an interrupt context such that it must minimize
523 * the amount of processing performed such as transferring data to a thread
526 * The number of bytes received is passed to the handler as an argument.
528 * @param InstancePtr is a pointer to the XIic instance to be worked on.
529 * @param CallBackRef is the upper layer callback reference passed back when
530 * the callback function is invoked.
531 * @param FuncPtr is the pointer to the callback function.
539 * The handler is called within interrupt context ...
541 ****************************************************************************/
543 XIic_SetRecvHandler(XIic * InstancePtr, void *CallBackRef, XIic_Handler FuncPtr)
545 XASSERT_VOID(InstancePtr->IsReady == XCOMPONENT_IS_READY);
546 XASSERT_VOID(InstancePtr != NULL);
547 XASSERT_VOID(FuncPtr != NULL);
549 InstancePtr->RecvHandler = FuncPtr;
550 InstancePtr->RecvCallBackRef = CallBackRef;
553 /*****************************************************************************/
556 * Sets the send callback function, the send handler, which the driver calls when
557 * it receives confirmation of sent data. The handler executes in an interrupt
558 * context such that it must minimize the amount of processing performed such
559 * as transferring data to a thread context.
561 * @param InstancePtr the pointer to the XIic instance to be worked on.
562 * @param CallBackRef the upper layer callback reference passed back when
563 * the callback function is invoked.
564 * @param FuncPtr the pointer to the callback function.
572 * The handler is called within interrupt context ...
574 ****************************************************************************/
576 XIic_SetSendHandler(XIic * InstancePtr, void *CallBackRef, XIic_Handler FuncPtr)
578 XASSERT_VOID(InstancePtr != NULL);
579 XASSERT_VOID(InstancePtr->IsReady == XCOMPONENT_IS_READY);
580 XASSERT_VOID(FuncPtr != NULL);
582 InstancePtr->SendHandler = FuncPtr;
583 InstancePtr->SendCallBackRef = CallBackRef;
586 /*****************************************************************************/
589 * Sets the status callback function, the status handler, which the driver calls
590 * when it encounters conditions which are not data related. The handler
591 * executes in an interrupt context such that it must minimize the amount of
592 * processing performed such as transferring data to a thread context. The
593 * status events that can be returned are described in xiic.h.
595 * @param InstancePtr points to the XIic instance to be worked on.
596 * @param CallBackRef is the upper layer callback reference passed back when
597 * the callback function is invoked.
598 * @param FuncPtr is the pointer to the callback function.
606 * The handler is called within interrupt context ...
608 ****************************************************************************/
610 XIic_SetStatusHandler(XIic * InstancePtr, void *CallBackRef,
611 XIic_StatusHandler FuncPtr)
613 XASSERT_VOID(InstancePtr != NULL);
614 XASSERT_VOID(InstancePtr->IsReady == XCOMPONENT_IS_READY);
615 XASSERT_VOID(FuncPtr != NULL);
617 InstancePtr->StatusHandler = FuncPtr;
618 InstancePtr->StatusCallBackRef = CallBackRef;
621 /*****************************************************************************/
624 * Looks up the device configuration based on the unique device ID. The table
625 * IicConfigTable contains the configuration info for each device in the system.
627 * @param DeviceId is the unique device ID to look for
631 * A pointer to the configuration data of the device, or NULL if no match is
638 ******************************************************************************/
640 XIic_LookupConfig(u16 DeviceId)
642 XIic_Config *CfgPtr = NULL;
645 for (i = 0; i < XPAR_XIIC_NUM_INSTANCES; i++) {
646 if (XIic_ConfigTable[i].DeviceId == DeviceId) {
647 CfgPtr = &XIic_ConfigTable[i];
655 /*****************************************************************************
657 * This is a stub for the send and recv callbacks. The stub is here in case the
658 * upper layers forget to set the handlers.
660 * @param CallBackRef is a pointer to the upper layer callback reference
661 * @param ByteCount is the number of bytes sent or received
671 ******************************************************************************/
673 XIic_StubHandler(void *CallBackRef, int ByteCount)
678 /*****************************************************************************
680 * This is a stub for the asynchronous error callback. The stub is here in case
681 * the upper layers forget to set the handler.
683 * @param CallBackRef is a pointer to the upper layer callback reference
684 * @param ErrorCode is the Xilinx error code, indicating the cause of the error
694 ******************************************************************************/
696 XIic_StubStatusHandler(void *CallBackRef, XStatus ErrorCode)