/** * * Runs a limited self-test on the driver/device. This test does a read/write * test of the Interrupt Registers There is no loopback capabilities for the * device such that this test does not send or receive data. * * @param InstancePtr is a pointer to the XIic instance to be worked on. * * @return * - XST_SUCCESS if no errors are found * - XST_FAILURE if errors are found * * @note None. * ****************************************************************************/ int XIic_SelfTest(XIic *InstancePtr) { int Status = XST_SUCCESS; int GlobalIntrStatus; u32 IntrEnableStatus; Xil_AssertNonvoid(InstancePtr != NULL); Xil_AssertNonvoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY); /* * Store the Global Interrupt Register and the Interrupt Enable Register * contents. */ GlobalIntrStatus = XIic_IsIntrGlobalEnabled(InstancePtr->BaseAddress); IntrEnableStatus = XIic_ReadIier(InstancePtr->BaseAddress); /* * Reset the device so it's in a known state and the default state of * the interrupt registers can be tested. */ XIic_Reset(InstancePtr); if (XIic_IsIntrGlobalEnabled(InstancePtr->BaseAddress)!= 0) { Status = XST_FAILURE; } if (XIic_ReadIier(InstancePtr->BaseAddress)!= 0) { Status = XST_FAILURE; } /* * Test Read/Write to the Interrupt Enable register. */ XIic_WriteIier(InstancePtr->BaseAddress, XIIC_TX_RX_INTERRUPTS); if (XIic_ReadIier(InstancePtr->BaseAddress)!= XIIC_TX_RX_INTERRUPTS) { Status = XST_FAILURE; } /* * Reset device to remove the affects of the previous test. */ XIic_Reset(InstancePtr); /* * Restore the Global Interrupt Register and the Interrupt Enable * Register contents. */ if (GlobalIntrStatus == TRUE) { XIic_IntrGlobalEnable(InstancePtr->BaseAddress); } XIic_WriteIier(InstancePtr->BaseAddress, IntrEnableStatus); return Status; }
/** * * Initializes a specific XIic instance. The initialization entails: * * - Initialize the driver to allow access to the device registers and * initialize other subcomponents necessary for the operation of the device. * - Default options to: * - 7-bit slave addressing * - Send messages as a slave device * - Repeated start off * - General call recognition disabled * - Clear messageing and error statistics * * The XIic_Start() function must be called after this function before the device * is ready to send and receive data on the IIC bus. * * Before XIic_Start() is called, the interrupt control must connect the ISR * routine to the interrupt handler. This is done by the user, and not * XIic_Start() to allow the user to use an interrupt controller of their choice. * * @param InstancePtr is a pointer to the XIic instance to be worked on. * @param Config is a reference to a structure containing information * about a specific IIC device. This function can initialize * multiple instance objects with the use of multiple calls giving * different Config information on each call. * @param EffectiveAddr is the device base address in the virtual memory * address space. The caller is responsible for keeping the * address mapping from EffectiveAddr to the device physical base * address unchanged once this function is invoked. Unexpected * errors may occur if the address mapping changes after this * function is called. If address translation is not used, use * Config->BaseAddress for this parameters, passing the physical * address instead. * * @return * - XST_SUCCESS when successful * - XST_DEVICE_IS_STARTED indicates the device is started * (i.e. interrupts enabled and messaging is possible). Must stop * before re-initialization is allowed. * * @note None. * ****************************************************************************/ int XIic_CfgInitialize(XIic *InstancePtr, XIic_Config * Config, u32 EffectiveAddr) { /* * Asserts test the validity of selected input arguments. */ Xil_AssertNonvoid(InstancePtr != NULL); InstancePtr->IsReady = 0; /* * If the device is started, disallow the initialize and return a Status * indicating it is started. This allows the user to stop the device * and reinitialize, but prevents a user from inadvertently * initializing. */ if (InstancePtr->IsStarted == XIL_COMPONENT_IS_STARTED) { return XST_DEVICE_IS_STARTED; } /* * Set default values and configuration data, including setting the * callback handlers to stubs so the system will not crash should the * application not assign its own callbacks. */ InstancePtr->IsStarted = 0; InstancePtr->BaseAddress = EffectiveAddr; InstancePtr->RecvHandler = XIic_StubHandler; InstancePtr->RecvBufferPtr = NULL; InstancePtr->SendHandler = XIic_StubHandler; InstancePtr->SendBufferPtr = NULL; InstancePtr->StatusHandler = XIic_StubStatusHandler; InstancePtr->Has10BitAddr = Config->Has10BitAddr; InstancePtr->IsReady = XIL_COMPONENT_IS_READY; InstancePtr->Options = 0; InstancePtr->BNBOnly = FALSE; InstancePtr->GpOutWidth = Config->GpOutWidth; InstancePtr->IsDynamic = FALSE; InstancePtr->IsSlaveSetAckOff = FALSE; /* * Reset the device. */ XIic_Reset(InstancePtr); XIic_ClearStats(InstancePtr); return XST_SUCCESS; }
static int xiic_xfer(struct i2c_adapter *i2c_adap, struct i2c_msg msgs[], int num) { struct xiic_data *dev = (struct xiic_data *) i2c_adap; struct i2c_msg *pmsg; u32 options; int i, retries; u32 Status; u32 writeop; for (i = 0; i < num; i++) { pmsg = &msgs[i]; if (!pmsg->len) /* If length is zero */ continue; /* on to the next request. */ /* * This code checks up to 16 times for the * bus busy condition. */ retries = 4; while((XIic_IsIicBusy(&dev->Iic) == TRUE) && (retries-- != 0)) { set_current_state(TASK_INTERRUPTIBLE); schedule_timeout(HZ/250); } /* If bus is still busy, bail */ if (XIic_IsIicBusy(&dev->Iic) == TRUE) { printk(KERN_WARNING "%s #%d: Could not talk to device 0x%2x (%d), bus always busy, trying to reset\n", dev->adap.name, dev->index, pmsg->addr, dev->status_intr_flag); /* Try stopping, reseting and starting device to clear condition */ if (XIic_Stop(&dev->Iic) != XST_SUCCESS) { /* The bus was in use.. */ printk(KERN_WARNING "%s #%d: Could not stop device. Restart from higher layer.\n", dev->adap.name, dev->index); return -ENXIO; } else { XIic_Reset(&dev->Iic); if (XIic_Start(&dev->Iic) != XST_SUCCESS) { printk(KERN_ERR "%s #%d: Could not start device.\n", dev->adap.name, dev->index); return -ENODEV; } return -ENXIO; } } options = 0; if (pmsg->flags & I2C_M_TEN) options |= XII_SEND_10_BIT_OPTION; XIic_SetOptions(&dev->Iic, options); if (XIic_SetAddress(&dev->Iic, XII_ADDR_TO_SEND_TYPE, pmsg->addr) != XST_SUCCESS) { printk(KERN_WARNING "%s #%d: Could not set address to 0x%2x.\n", dev->adap.name, dev->index, pmsg->addr); return -EIO; } dev->transmit_intr_flag = 0xFFFFFFFF; dev->receive_intr_flag = 0xFFFFFFFF; dev->status_intr_flag = 0xFFFFFFFF; /* set the writeop flag to 0 so the adapter does not wait * at bottom of loop */ writeop = 0; dev->Iic.Stats.TxErrors = 0; if (pmsg->flags & I2C_M_RD) { Status = XIic_MasterRecv(&dev->Iic, pmsg->buf, pmsg->len); } else { Status = XIic_MasterSend(&dev->Iic, pmsg->buf, pmsg->len); } if (Status != XST_SUCCESS) { printk(KERN_WARNING "%s #%d: Unexpected error %d.\n", dev->adap.name, dev->index, (int)Status); return -EIO; } /* * Wait till the data is transmitted or received. If there is an error * retry for 10 times. */ retries = 10; if(pmsg->flags & I2C_M_RD) { while((((volatile int)(dev->receive_intr_flag)) != 0) && (retries != 0)) { if ( dev->Iic.Stats.TxErrors != 0) { udelay(25); Status = XIic_MasterRecv(&dev->Iic, pmsg->buf, pmsg->len); dev->Iic.Stats.TxErrors = 0; retries--; } /* the udelay was not working for Microblaze and this seems like a better solution */ schedule_timeout_interruptible(1); } } else { while((((volatile int)(dev->transmit_intr_flag)) != 0) && (retries != 0)) { if ( dev->Iic.Stats.TxErrors != 0) { udelay(25); Status = XIic_MasterSend(&dev->Iic, pmsg->buf, pmsg->len); dev->Iic.Stats.TxErrors = 0; retries--; } /* the udelay was not working for Microblaze and this seems like a better solution */ schedule_timeout_interruptible(1); } } if(retries == 0) { printk("Unable to talk to Device\n"); printk("Wrong Slave address or Slave device Busy\n"); } } return num; }
/* * ********************************************************* * IicWriteData with address added as an input parameter * ********************************************************* */ int IicWriteData(u8 IicAddr, u8 *BufferPtr, u16 ByteCount) { int Status; u32 IicTimeoutCounter = 0; // Mark the Transmit Flag TransmitComplete = 1; IicInstance.Stats.TxErrors = 0; /* * Start Iic Device */ Status = XIic_Start(&IicInstance); if (Status != XST_SUCCESS) { #ifdef IIC_DEBUG xil_printf("IicWriteData: IIC Start Device Failed with status %x\r\n", Status); #endif return XST_FAILURE; } /* * Set Iic Address */ Status = XIic_SetAddress(&IicInstance, XII_ADDR_TO_SEND_TYPE, IicAddr); if (Status != XST_SUCCESS) { #ifdef IIC_DEBUG xil_printf("IicWriteData: IIC Set Address Failed with status %x\r\n", Status); #endif return XST_FAILURE; } /* * Send the Data */ Status = XIic_MasterSend(&IicInstance, BufferPtr, ByteCount); if (Status != XST_SUCCESS) { #ifdef IIC_DEBUG xil_printf("IicWriteData: IIC Master Send failed with status %x\r\n", Status); #endif return XST_FAILURE; } /* * Wait till the transmission is completed */ while(((TransmitComplete) || (XIic_IsIicBusy(&IicInstance)==TRUE)) && IicTimeoutCounter <= IIC_TIMEOUT) { IicTimeoutCounter++; } if (IicTimeoutCounter > IIC_TIMEOUT) { TransmitComplete = 0; XIic_Reset(&IicInstance); Status = XIic_Stop(&IicInstance); #ifdef IIC_DEBUG xil_printf("IicWriteData: IIC Write Timeout!\r\n"); if (Status != XST_SUCCESS) { xil_printf("IicWriteData: IIC stop failed with status %x\r\n", Status); } #endif return XST_FAILURE; } /* * Stop Iic Device */ Status = XIic_Stop(&IicInstance); if (Status != XST_SUCCESS) { #ifdef IIC_DEBUG xil_printf("IicWriteData: IIC Stop failed with status %x\r\n", Status); #endif return XST_FAILURE; } return XST_SUCCESS; }
/* * ********************************************************* * IicReadData3 with address added as an input parameter - two bytes address * ********************************************************* */ int IicReadData3(u8 IicAddr, u16 addr, u8 *BufferPtr, u16 ByteCount) { int Status; u8 IicOptions; u32 IicTimeoutCounter = 0; /* * Set Receive Flag */ ReceiveComplete = 1; /* * Start Iic Device */ Status = XIic_Start(&IicInstance); if (Status != XST_SUCCESS) { #ifdef IIC_DEBUG xil_printf("IicReadData3: IIC Start failed with status %x\r\n", Status); #endif return XST_FAILURE; } /* * Set Iic Address */ Status = XIic_SetAddress(&IicInstance, XII_ADDR_TO_SEND_TYPE, IicAddr); if (Status != XST_SUCCESS) { #ifdef IIC_DEBUG xil_printf("IicReadData3: IIC Set Address failed with status %x\r\n", Status); #endif return XST_FAILURE; } /* * Write addr to the device */ // Mark the Transmit Flag TransmitComplete = 1; IicInstance.Stats.TxErrors = 0; /* * Send the Data */ u8 addrReorder[2]; u8 *addrPtr; addrPtr = &addr; addrReorder[0] = addrPtr[1]; addrReorder[1] = addrPtr[0]; Status = XIic_MasterSend(&IicInstance, addrReorder, 2); if (Status != XST_SUCCESS) { #ifdef IIC_DEBUG xil_printf("IicReadData3: IIC Master Send failed with status %x\r\n", Status); #endif return XST_FAILURE; } /* * Wait till the transmission is completed */ while(((TransmitComplete) || (XIic_IsIicBusy(&IicInstance)==TRUE)) && IicTimeoutCounter <= IIC_TIMEOUT) { IicTimeoutCounter ++; } /* * Handle Tx Timeout */ if (IicTimeoutCounter > IIC_TIMEOUT) { XIic_Reset(&IicInstance); Status = XIic_Stop(&IicInstance); #ifdef IIC_DEBUG xil_printf("IicReadData3: IIC Write Timeout!\r\n"); if (Status != XST_SUCCESS) { xil_printf("IicReadData3: IIC Stop Failed with status %x\r\n", Status); } #endif return XST_FAILURE; } /* * Receive Data */ Status = XIic_MasterRecv(&IicInstance, BufferPtr, ByteCount); if(Status != XST_SUCCESS) { if (Status != XST_SUCCESS) { #ifdef IIC_DEBUG xil_printf("IicReadData3: IIC Master Recv Failed with status %x\r\n", Status); #endif return XST_FAILURE; } } /* * Wait until all the data is received */ IicTimeoutCounter = 0; while(((ReceiveComplete) || (XIic_IsIicBusy(&IicInstance)==TRUE)) && IicTimeoutCounter <= IIC_TIMEOUT) { IicTimeoutCounter ++; } /* * Handle Rx Timeout */ if (IicTimeoutCounter > IIC_TIMEOUT) { XIic_Reset(&IicInstance); Status = XIic_Stop(&IicInstance); #ifdef IIC_DEBUG xil_printf("IicReadData3: IIC Recv Timeout!\r\n"); if (Status != XST_SUCCESS) { xil_printf("IicReadData3: IIC Stop Failed with status %x\r\n", Status); } #endif return XST_FAILURE; } /* * Stop Iic */ Status = XIic_Stop(&IicInstance); if (Status != XST_SUCCESS) { #ifdef IIC_DEBUG xil_printf("IicReadData3: IIC Stop Failed with status %x\r\n", Status); #endif return XST_FAILURE; } return XST_SUCCESS; }
/** * * Runs a limited self-test on the driver/device. The self-test is destructive * in that a reset of the device is performed in order to check the reset * values of the registers and to get the device into a known state. There is no * loopback capabilities for the device such that this test does not send or * receive data. * * @param InstancePtr is a pointer to the XIic instance to be worked on. * * @return * * <pre> * XST_SUCCESS No errors found * XST_IIC_STAND_REG_ERROR One or more IIC regular registers did * not zero on reset or read back * correctly based on what was written * to it * XST_IIC_TX_FIFO_REG_ERROR One or more IIC parametrizable TX * FIFO registers did not zero on reset * or read back correctly based on what * was written to it * XST_IIC_RX_FIFO_REG_ERROR One or more IIC parametrizable RX * FIFO registers did not zero on reset * or read back correctly based on what * was written to it * XST_IIC_STAND_REG_RESET_ERROR A non parameterizable reg value after * reset not valid * XST_IIC_TX_FIFO_REG_RESET_ERROR Tx fifo, included in design, value * after reset not valid * XST_IIC_RX_FIFO_REG_RESET_ERROR Rx fifo, included in design, value * after reset not valid * XST_IIC_TBA_REG_RESET_ERROR 10 bit addr, incl in design, value * after reset not valid * XST_IIC_CR_READBACK_ERROR Read of the control register didn't * return value written * XST_IIC_DTR_READBACK_ERROR Read of the data Tx reg didn't return * value written * XST_IIC_DRR_READBACK_ERROR Read of the data Receive reg didn't * return value written * XST_IIC_ADR_READBACK_ERROR Read of the data Tx reg didn't return * value written * XST_IIC_TBA_READBACK_ERROR Read of the 10 bit addr reg didn't * return written value * </pre> * * @note * * Only the registers that have be included into the hardware design are * tested, such as, 10-bit vs 7-bit addressing. * ****************************************************************************/ int XIic_SelfTest(XIic * InstancePtr) { int Status = XST_SUCCESS; XASSERT_NONVOID(InstancePtr != NULL); XASSERT_NONVOID(InstancePtr->IsReady == XCOMPONENT_IS_READY); /* * Reset the device so it's in a known state and the default state of * the registers can be tested */ XIic_Reset(InstancePtr); /* * Test the standard - non parameterizable registers to ensure they are * in the default state */ if ((XIo_In8(InstancePtr->BaseAddress + XIIC_CR_REG_OFFSET) & XIo_In8(InstancePtr->BaseAddress + XIIC_SR_REG_OFFSET) & XIo_In8(InstancePtr->BaseAddress + XIIC_DTR_REG_OFFSET) & XIo_In8(InstancePtr->BaseAddress + XIIC_DRR_REG_OFFSET) & XIo_In8(InstancePtr->BaseAddress + XIIC_ADR_REG_OFFSET)) != 0) { Status = XST_IIC_STAND_REG_RESET_ERROR; } if (XIo_In8(InstancePtr->BaseAddress + XIIC_TFO_REG_OFFSET) != 0) { Status = XST_IIC_TX_FIFO_REG_RESET_ERROR; } if ((XIo_In8(InstancePtr->BaseAddress + XIIC_RFO_REG_OFFSET) & XIo_In8(InstancePtr->BaseAddress + XIIC_RFD_REG_OFFSET)) != 0) { Status = XST_IIC_RX_FIFO_REG_RESET_ERROR; } /* * Test the 10-bit address parameterizable register only if it's supposed * to be in the hardware */ if (InstancePtr->Has10BitAddr == TRUE) { if (XIo_In8(InstancePtr->BaseAddress + XIIC_TBA_REG_OFFSET) != 0) { Status = XST_IIC_TBA_REG_RESET_ERROR; } } /* * Perform register write/readback tests to verify the registers are * working, test the control register by writing all 1's except the * MSMS bit. */ XIo_Out8(InstancePtr->BaseAddress + XIIC_CR_REG_OFFSET, 0x7B); if (XIo_In8(InstancePtr->BaseAddress + XIIC_CR_REG_OFFSET) != 0x7B) { Status = XST_IIC_CR_READBACK_ERROR; } /* Reset device to remove the affects of the previous test */ XIic_Reset(InstancePtr); /* Test the data transmit register */ XIo_Out8(InstancePtr->BaseAddress + XIIC_DTR_REG_OFFSET, 0xFF); if (XIo_In8(InstancePtr->BaseAddress + XIIC_DTR_REG_OFFSET) != 0xFF) { Status = XST_IIC_DTR_READBACK_ERROR; } /* Test the address register */ XIo_Out8(InstancePtr->BaseAddress + XIIC_ADR_REG_OFFSET, 0xFE); if (XIo_In8(InstancePtr->BaseAddress + XIIC_ADR_REG_OFFSET) != 0xFE) { Status = XST_IIC_ADR_READBACK_ERROR; } /* Test 10-bit address register only if it's in the hardware */ if (InstancePtr->Has10BitAddr == TRUE) { XIo_Out8(InstancePtr->BaseAddress + XIIC_TBA_REG_OFFSET, 0x07); if (XIo_In8(InstancePtr->BaseAddress + XIIC_TBA_REG_OFFSET) != 0x07) { Status = XST_IIC_TBA_READBACK_ERROR; } } /* Reset the device so that it's in a known state before returning */ XIic_Reset(InstancePtr); return Status; }