/* * Iic Post Initialization Procedure * Need to be called after Interrupt system is configured. */ int IicInitPost(XIic *IicInstPtr) { // Setup Handlers for transmit and reception XIic_SetSendHandler(IicInstPtr, IicInstPtr, (XIic_Handler) IicSendHandler); XIic_SetRecvHandler(IicInstPtr, IicInstPtr, (XIic_Handler) IicRecvHandler); XIic_SetStatusHandler(IicInstPtr, IicInstPtr, (XIic_StatusHandler) IicStatusHandler); // Release reset on the PCA9548 IIC Switch XIic_SetGpOutput(IicInstPtr, 0xFF); XIic_SetGpOutput(IicInstPtr, 0x00); return XST_SUCCESS; }
/** Shared device initialization code */ static int __devinit xilinx_iic_setup( struct device *device, struct device_node *node, struct resource *r_mem, struct resource *r_irq, u32 ten_bit_addr, u32 gpo_width) { XIic_Config xiic_cfg; struct xiic_data *dev; char *scan_results; int error; /* Allocate the dev and zero it out. */ dev = kmalloc(sizeof(struct xiic_data), GFP_KERNEL); if (!dev) { dev_err(device, "Cannot allocate struct xiic_data\n"); error = -ENOMEM; goto out2; } memset(dev, 0, sizeof(struct xiic_data)); dev_set_drvdata(device, dev); dev->irq = r_irq->start; /* initialize fields to satisfy i2c */ dev->index = 0; init_completion(&dev->complete); memset(&xiic_cfg, 0, sizeof(XIic_Config)); xiic_cfg.DeviceId = 0; /* Change the addresses to be virtual; save the old ones to restore. */ dev->base = r_mem->start; xiic_cfg.BaseAddress = (u32) ioremap(r_mem->start, r_mem->end - r_mem->start + 1); dev->remapped = 1; down(&cfg_sem); xiic_cfg.Has10BitAddr = (int)ten_bit_addr; xiic_cfg.GpOutWidth = (u8)gpo_width; /* Tell the Xilinx code to bring this IIC interface up. */ if (XIic_CfgInitialize(&dev->Iic, &xiic_cfg, xiic_cfg.BaseAddress) != XST_SUCCESS) { up(&cfg_sem); dev_err(device, "could not initialize device.\n"); error = -ENODEV; goto out; } up(&cfg_sem); XIic_SetRecvHandler(&dev->Iic, (void *)dev, RecvHandler); XIic_SetSendHandler(&dev->Iic, (void *)dev, SendHandler); XIic_SetStatusHandler(&dev->Iic, (void *)dev, StatusHandler); /* Grab the IRQ */ error = request_irq(dev->irq, xiic_interrupt, 0, dev->adap.name, dev); if (error) { dev_err(device, "could not allocate interrupt %d.\n", dev->irq); goto out; } dev->reqirq = 1; if (XIic_Start(&dev->Iic) != XST_SUCCESS) { dev_err(device, "could not start device\n"); error = -ENODEV; goto out; } dev->started = 1; /* Now tell the core I2C code about our new device. */ strcpy(dev->adap.name, "xilinx-iic"); dev->adap.dev.of_node = node; dev->adap.algo = &xiic_algo; dev->adap.algo_data = NULL; dev->adap.timeout = XIIC_TIMEOUT; dev->adap.retries = XIIC_RETRY; error = i2c_add_adapter(&dev->adap); if (error) { dev_err(device, "could not add i2c adapter\n"); goto out; } dev->added = 1; printk("%s #%d at 0x%08X mapped to 0x%08X, irq=%d\n", dev->adap.name, dev->index, dev->base, (unsigned int)dev->Iic.BaseAddress, dev->irq); if (scan) { scan_results = xilinx_iic_do_scan(dev); if (scan_results) { printk(scan_results); kfree(scan_results); } } of_i2c_register_devices(&dev->adap); error = device_create_file(device, &dev_attr_scan); out: if (error) xilinx_iic_remove(device); out2: return error; }
static int __init xilinx_iic_probe(struct of_device *of_dev, const struct of_device_id *match) { XIic_Config xiic_cfg; struct xiic_data *dev; char *scan_results; struct resource mem; struct device_node *dev_node = of_dev->node; int error; const u32 *did; /* Allocate the dev and zero it out. */ dev = kzalloc(sizeof(struct xiic_data), SLAB_KERNEL); if (!dev) { dev_err(&of_dev->dev, "Cannot allocate struct xiic_data\n"); error = -ENOMEM; goto out2; } dev_set_drvdata(&of_dev->dev, dev); /* get resources from device tree */ dev->irq = irq_of_parse_and_map(dev_node, 0); if (dev->irq == 0 /* NOIRQ */ ) { error = -ENODEV; goto out; } if (of_address_to_resource(dev_node, 0, &mem)) { error = -ENODEV; goto out; } /* initialize fields to satisfy i2c */ strcpy(dev->adap.name, of_dev->dev.bus_id); did = of_get_property(dev_node, "index", NULL); if (did == NULL) { printk ("%s: Can not get device index from device tree, assume 0\n", __FUNCTION__); dev->index = 0; } else dev->index = *did; init_completion(&dev->complete); memset(&xiic_cfg, 0, sizeof(XIic_Config)); xiic_cfg.DeviceId = dev->index; /* Change the addresses to be virtual; save the old ones to restore. */ dev->base = mem.start; xiic_cfg.BaseAddress = (u32) ioremap(mem.start, mem.end - mem.start + 1); dev->remapped = 1; down(&cfg_sem); /* Tell the Xilinx code to bring this IIC interface up. */ if (XIic_CfgInitialize(&dev->Iic, &xiic_cfg, xiic_cfg.BaseAddress) != XST_SUCCESS) { up(&cfg_sem); dev_err(&of_dev->dev, "could not initialize device.\n"); error = -ENODEV; goto out; } up(&cfg_sem); XIic_SetRecvHandler(&dev->Iic, (void *)dev, RecvHandler); XIic_SetSendHandler(&dev->Iic, (void *)dev, SendHandler); XIic_SetStatusHandler(&dev->Iic, (void *)dev, StatusHandler); /* Grab the IRQ */ error = request_irq(dev->irq, xiic_interrupt, 0, dev->adap.name, dev); if (error) { dev_err(&of_dev->dev, "could not allocate interrupt %d.\n", dev->irq); goto out; } dev->reqirq = 1; if (XIic_Start(&dev->Iic) != XST_SUCCESS) { dev_err(&of_dev->dev, "could not start device\n"); error = -ENODEV; goto out; } dev->started = 1; /* Now tell the core I2C code about our new device. */ /* * SAATODO: Get a real ID (perhaps I2C_HW_XILINX) after * initial release. Will need to email [email protected] * per http://www2.lm-sensors.nu/~lm78/support.html */ dev->adap.id = I2C_DRIVERID_I2CDEV; dev->adap.algo = &xiic_algo; dev->adap.algo_data = NULL; dev->adap.timeout = XIIC_TIMEOUT; dev->adap.retries = XIIC_RETRY; error = i2c_add_adapter(&dev->adap); if (error) { dev_err(&of_dev->dev, "could not add i2c adapter\n"); goto out; } dev->added = 1; printk("%s #%d at 0x%08X mapped to 0x%08X, irq=%d\n", dev->adap.name, dev->index, dev->base, dev->Iic.BaseAddress, dev->irq); if (scan) { scan_results = xilinx_iic_do_scan(dev); if (scan_results) { printk(scan_results); kfree(scan_results); } } device_create_file(&of_dev->dev, &dev_attr_scan); out: if (error) xilinx_iic_remove(of_dev); out2: return error; }
static int __init xilinx_iic_probe(struct device *device) { XIic_Config xiic_cfg; struct platform_device *pdev = to_platform_device(device); struct xiic_data *dev; char *scan_results; struct resource *mem; int error; /* Allocate the dev and zero it out. */ dev = kzalloc(sizeof(struct xiic_data), SLAB_KERNEL); if (!dev) { dev_err(device, "Cannot allocate struct xiic_data\n"); error = -ENOMEM; goto out2; } dev_set_drvdata(device, dev); /* get resources from resource list of passed platform_device */ dev->irq = platform_get_irq(pdev, 0); if (dev->irq == 0 /* NOIRQ */ ) { error = -ENODEV; goto out; } mem = platform_get_resource(pdev, IORESOURCE_MEM, 0); if (!mem) { error = -ENODEV; goto out; } /* initialize fields to satisfy i2c */ strcpy(dev->adap.name, device->bus_id); dev->index = pdev->id; init_completion(&dev->complete); memset(&xiic_cfg, 0, sizeof(XIic_Config)); xiic_cfg.DeviceId = pdev->id; /* Change the addresses to be virtual; save the old ones to restore. */ dev->base = mem->start; xiic_cfg.BaseAddress = (u32) ioremap(mem->start, mem->end - mem->start + 1); dev->remapped = 1; down(&cfg_sem); /* Tell the Xilinx code to bring this IIC interface up. */ if (XIic_CfgInitialize(&dev->Iic, &xiic_cfg, xiic_cfg.BaseAddress) != XST_SUCCESS) { up(&cfg_sem); dev_err(device, "could not initialize device.\n"); error = -ENODEV; goto out; } up(&cfg_sem); XIic_SetRecvHandler(&dev->Iic, (void *)dev, RecvHandler); XIic_SetSendHandler(&dev->Iic, (void *)dev, SendHandler); XIic_SetStatusHandler(&dev->Iic, (void *)dev, StatusHandler); /* Grab the IRQ */ error = request_irq(dev->irq, xiic_interrupt, 0, dev->adap.name, dev); if (error) { dev_err(device, "could not allocate interrupt %d.\n", dev->irq); goto out; } dev->reqirq = 1; if (XIic_Start(&dev->Iic) != XST_SUCCESS) { dev_err(device, "could not start device\n"); error = -ENODEV; goto out; } dev->started = 1; /* Now tell the core I2C code about our new device. */ /* * SAATODO: Get a real ID (perhaps I2C_HW_XILINX) after * initial release. Will need to email [email protected] * per http://www2.lm-sensors.nu/~lm78/support.html */ dev->adap.id = xiic_algo.id | I2C_DRIVERID_EXP0; dev->adap.algo = &xiic_algo; dev->adap.algo_data = NULL; dev->adap.timeout = XIIC_TIMEOUT; dev->adap.retries = XIIC_RETRY; error = i2c_add_adapter(&dev->adap); if (error) { dev_err(device, "could not add i2c adapter\n"); goto out; } dev->added = 1; printk("%s #%d at 0x%08X mapped to 0x%08X, irq=%d\n", dev->adap.name, dev->index, dev->base, dev->Iic.BaseAddress, dev->irq); if (scan) { scan_results = xilinx_iic_do_scan(dev); if (scan_results) { printk(scan_results); kfree(scan_results); } } device_create_file(device, &dev_attr_scan); out: if (error) xilinx_iic_remove(device); out2: return error; }
/** * 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; }
/* TMP3_SetupInterruptSystem() ** ** Parameters: ** InstancePtr: PmodTMP3 object to get data from ** interruptDeviceID: Device ID of the interrupt controller ** interruptID: The vector ID of the TMP3 I2C interrupt ** ** Return Value: ** A status indicating XST_SUCCESS or a value that is contained in ** xstatus.h. ** ** Errors: ** none ** ** Description: ** This function sets up the interrupt system for the example. The processing ** contained in this function assumes the hardware system was built with ** and interrupt controller. ** *****************************************************************************/ int TMP3_SetupInterruptSystem(PmodTMP3* InstancePtr, u32 interruptDeviceID, u32 interruptID, void* SendHandler, void* ReceiveHandler) { int Result; #ifdef XPAR_XINTC_NUM_INSTANCES INTC *IntcInstancePtr = &InstancePtr->intc; /* * Initialize the interrupt controller driver so that it's ready to use. * specify the device ID that was generated in xparameters.h */ Result = XIntc_Initialize(IntcInstancePtr, interruptDeviceID); if (Result != XST_SUCCESS) { return Result; } /* Hook up interrupt service routine */ XIntc_Connect(IntcInstancePtr, interruptID, (Xil_ExceptionHandler)XIic_InterruptHandler, &InstancePtr->TMP3Iic); /* Enable the interrupt vector at the interrupt controller */ XIntc_Enable(IntcInstancePtr, interruptID); /* * Start the interrupt controller such that interrupts are recognized * and handled by the processor */ Result = XIntc_Start(IntcInstancePtr, XIN_REAL_MODE); if (Result != XST_SUCCESS) { return Result; } XIic_SetSendHandler(&InstancePtr->TMP3Iic, InstancePtr, (XIic_Handler)SendHandler); XIic_SetRecvHandler(&InstancePtr->TMP3Iic, InstancePtr, (XIic_Handler)ReceiveHandler); /* * Initialize the exception table and register the interrupt * controller handler with the exception table */ Xil_ExceptionInit(); Xil_ExceptionRegisterHandler(XIL_EXCEPTION_ID_INT, (Xil_ExceptionHandler)INTC_HANDLER, IntcInstancePtr); /* Enable non-critical exceptions */ Xil_ExceptionEnable(); #endif #ifdef XPAR_SCUGIC_0_DEVICE_ID INTC *IntcInstancePtr = &InstancePtr->intc; XScuGic_Config *IntcConfig; /* * Initialize the interrupt controller driver so that it is ready to * use. */ IntcConfig = XScuGic_LookupConfig(interruptDeviceID); if (NULL == IntcConfig) { return XST_FAILURE; } Result = XScuGic_CfgInitialize(IntcInstancePtr, IntcConfig, IntcConfig->CpuBaseAddress); if (Result != XST_SUCCESS) { return XST_FAILURE; } XScuGic_SetPriorityTriggerType(IntcInstancePtr, interruptID, 0xA0, 0x3); /* * Connect the interrupt handler that will be called when an * interrupt occurs for the device. */ Result = XScuGic_Connect(IntcInstancePtr, interruptID, (Xil_ExceptionHandler)XIic_InterruptHandler, &InstancePtr->TMP3Iic); if (Result != XST_SUCCESS) { return Result; } /* * Enable the interrupt for the device. */ XScuGic_Enable(IntcInstancePtr, interruptID); XIic_SetSendHandler(&InstancePtr->TMP3Iic, InstancePtr, (XIic_Handler)SendHandler); XIic_SetRecvHandler(&InstancePtr->TMP3Iic, InstancePtr, (XIic_Handler)ReceiveHandler); XIic_SetStatusHandler(&InstancePtr->TMP3Iic, InstancePtr, (XIic_Handler)StatusHandler); /* * Initialize the exception table and register the interrupt * controller handler with the exception table */ Xil_ExceptionInit(); Xil_ExceptionRegisterHandler(XIL_EXCEPTION_ID_INT, (Xil_ExceptionHandler)INTC_HANDLER, IntcInstancePtr); /* Enable non-critical exceptions */ Xil_ExceptionEnable(); #endif return XST_SUCCESS; }