/*** void TMP3_begin(PmodTMP3* InstancePtr, u32 IIC_Address) ** ** Parameters: ** InstancePtr: A PmodTMP3 object to start ** IIC_Address: The Base address of the PmodTMP3 IIC ** Chip_Address: 7 bit Pmod device address ** ** Return Value: ** none ** ** Errors: ** none ** ** Description: ** Initialize the PmodTMP3. */ void TMP3_begin(PmodTMP3* InstancePtr, u32 IIC_Address, u8 Chip_Address) { TMP3_Config.BaseAddress=IIC_Address; InstancePtr->chipAddr=Chip_Address; TMP3_IICInit(&InstancePtr->TMP3Iic); XIic_SetAddress(&InstancePtr->TMP3Iic, XII_ADDR_TO_SEND_TYPE, InstancePtr->chipAddr); }
static char *xilinx_iic_do_scan(struct xiic_data *dev) { int i; char *page = kmalloc(PAGE_SIZE, GFP_KERNEL); char *cptr = page; u8 data; u32 status; for (i = 0x08; i < 0x78 && cptr; i++) { snprintf(cptr, PAGE_SIZE - (cptr - page), "%02X: ", i); cptr += strlen(cptr); init_completion(&dev->complete); if (XIic_SetAddress(&dev->Iic, XII_ADDR_TO_SEND_TYPE, i) != XST_SUCCESS) { snprintf(cptr, PAGE_SIZE - (cptr - page), "can't set address\n"); cptr += strlen(cptr); continue; } dev->receive_intr_flag = ~0; status = XIic_MasterRecv(&dev->Iic, &data, sizeof(data)); if (status != XST_SUCCESS) { snprintf(cptr, PAGE_SIZE - (cptr - page), "unexpected error\n"); cptr += strlen(cptr); continue; } wait_for_completion(&dev->complete); snprintf(cptr, PAGE_SIZE - (cptr - page), dev->receive_intr_flag == XST_SUCCESS ? "OK\n" : "not respoding\n"); cptr += strlen(cptr); } return page; }
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; }
static int xiic_xfer(struct i2c_adapter *i2c_adap, struct i2c_msg msgs[], int num) { struct xiic_data *dev = container_of(i2c_adap, struct xiic_data, adap); struct i2c_msg *pmsg; u32 options; int i, retries; XStatus Status; for (i = 0; i < num; i++) { pmsg = &msgs[i]; if (!pmsg->len) /* If length is zero */ continue; /* on to the next request. */ options = 0; if (pmsg->flags & I2C_M_TEN) options |= XII_SEND_10_BIT_OPTION; if (i != num - 1) options |= XII_REPEATED_START_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->interrupt_status = ~(XStatus) 0; /* * The Xilinx layer does not handle bus busy conditions yet * so this code retries a request up to 16 times if it * receives a bus busy condition. If and when the underlying * code is enhanced, the retry code can be removed. */ retries = 16; init_completion(&dev->complete); if (pmsg->flags & I2C_M_RD) { while ((Status = XIic_MasterRecv(&dev->Iic, pmsg->buf, pmsg->len)) == XST_IIC_BUS_BUSY && retries--) { set_current_state(TASK_INTERRUPTIBLE); schedule_timeout(HZ / 10); } } else { while ((Status = XIic_MasterSend(&dev->Iic, pmsg->buf, pmsg->len)) == XST_IIC_BUS_BUSY && retries--) { printk("retry %d\n", retries); set_current_state(TASK_INTERRUPTIBLE); schedule_timeout(HZ / 10); } } if (Status != XST_SUCCESS) { printk(KERN_WARNING "%s #%d: Unexpected error %d.\n", dev->adap.name, dev->index, Status); return -EIO; } wait_for_completion(&dev->complete); if (dev->interrupt_status != XST_SUCCESS) { printk(KERN_WARNING "%s #%d: Could not talk to device 0x%2x (%d).\n", dev->adap.name, dev->index, pmsg->addr, dev->interrupt_status); return -EIO; } } return num; }
/** * The function reads the temperature of the IIC temperature sensor on the * IIC bus. It initializes the IIC device driver and sets it up to communicate * with the temperature sensor. This function does contain a loop that polls * for completion of the IIC processing such that it may not return if * interrupts or the hardware are not working. * * @param IicDeviceId is the XPAR_<IIC_instance>_DEVICE_ID value from * xparameters.h for the IIC Device * @param TempSensorAddress is the address of the Temperature Sensor device * on the IIC bus * @param TemperaturePtr is the data byte read from the temperature sensor * * @return XST_SUCCESS to indicate success, else XST_FAILURE to indicate * a Failure. * * @note None. * *******************************************************************************/ int TempSensorExample(u16 IicDeviceId, u8 TempSensorAddress, u8 *TemperaturePtr) { int Status; static int Initialized = FALSE; XIic_Config *ConfigPtr; /* Pointer to configuration data */ if (!Initialized) { Initialized = TRUE; /* * Initialize the IIC driver so that it is ready to use. */ ConfigPtr = XIic_LookupConfig(IicDeviceId); if (ConfigPtr == NULL) { return XST_FAILURE; } Status = XIic_CfgInitialize(&Iic, ConfigPtr, ConfigPtr->BaseAddress); if (Status != XST_SUCCESS) { return XST_FAILURE; } /* * Setup handler to process the asynchronous events which occur, * the driver is only interrupt driven such that this must be * done prior to starting the device. */ XIic_SetRecvHandler(&Iic, (void *)&HandlerInfo, RecvHandler); XIic_SetStatusHandler(&Iic, (void *)&HandlerInfo, StatusHandler); /* * Connect the ISR to the interrupt and enable interrupts. */ Status = SetupInterruptSystem(&Iic); if (Status != XST_SUCCESS) { return XST_FAILURE; } /* * Start the IIC driver such that it is ready to send and * receive messages on the IIC interface, set the address * to send to which is the temperature sensor address */ XIic_Start(&Iic); XIic_SetAddress(&Iic, XII_ADDR_TO_SEND_TYPE, TempSensorAddress); } /* * Clear updated flags such that they can be polled to indicate * when the handler information has changed asynchronously and * initialize the status which will be returned to a default value */ HandlerInfo.EventStatusUpdated = FALSE; HandlerInfo.RecvBytesUpdated = FALSE; Status = XST_FAILURE; /* * Attempt to receive a byte of data from the temperature sensor * on the IIC interface, ignore the return value since this example is * a single master system such that the IIC bus should not ever be busy */ (void)XIic_MasterRecv(&Iic, TemperaturePtr, 1); /* * The message is being received from the temperature sensor, * wait for it to complete by polling the information that is * updated asynchronously by interrupt processing */ while(1) { if(HandlerInfo.RecvBytesUpdated == TRUE) { /* * The device information has been updated for receive * processing,if all bytes received (1), indicate * success */ if (HandlerInfo.RemainingRecvBytes == 0) { Status = XST_SUCCESS; } break; } /* * Any event status which occurs indicates there was an error, * so return unsuccessful, for this example there should be no * status events since there is a single master on the bus */ if (HandlerInfo.EventStatusUpdated == TRUE) { break; } } return Status; }