I have added device tree support into the ISP116X driver by: 1) Adding ".of_match_table = isp116x_match". 2) Use devm_kzalloc() during device tree probe function. 3) pdata config setting now gets its bool values from the device tree. 4) Delay check will default to ndelay() if no platform delay is used in device tree, otherwise will not compile. I can confirm this driver compiles and function well in my embedded Nios2-Linux system running on our FPGAs. This USB chip is quite outdated and not mantained by anyone anymore, prompting me to try and rectify the issue. I have been trying to push this patch for quite a while now. I tried to break up the patch into multiple parts but unfortunately the code would not work unless every part of it were included. Signed-off-by: Vishnu P. Nambiar <vishnu@xxxxxxxxxxxxxxxxxx> --- diff --git a/drivers/usb/host/isp116x-hcd.c b/drivers/usb/host/isp116x-hcd.c index baae4cc..f6bfc17 100644 --- a/drivers/usb/host/isp116x-hcd.c +++ b/drivers/usb/host/isp116x-hcd.c @@ -68,6 +68,7 @@ #include <linux/usb/hcd.h> #include <linux/platform_device.h> +#include <linux/of.h> #include <asm/io.h> #include <asm/irq.h> #include <asm/system.h> @@ -1535,6 +1536,14 @@ static struct hc_driver isp116x_hc_driver = { /*----------------------------------------------------------------*/ +/* + * Backup ndelay function if delay funtion not defined in device tree + */ +static void isp116x_ndelay(struct device *dev, int delay) +{ + ndelay(delay); +} + static int isp116x_remove(struct platform_device *pdev) { struct usb_hcd *hcd = platform_get_drvdata(pdev); @@ -1558,11 +1567,48 @@ static int isp116x_remove(struct platform_device *pdev) return 0; } +#ifdef CONFIG_OF +/* + * Translate device tree nodes to platform data. + */ + +static int isp116x_get_devtree_pdata(struct platform_device *pdev, + struct isp116x_platform_data *pdata) +{ + struct device_node *node = pdev->dev.of_node; + + if (!node) + return -ENODEV; + + pdata->sel15Kres = !!of_get_property(node, + "nxp,sel15Kres", NULL); + pdata->oc_enable = !!of_get_property(node, + "nxp,oc-enable", NULL); + pdata->int_act_high = !!of_get_property(node, + "nxp,int-act-high", NULL); + pdata->int_edge_triggered = !!of_get_property(node, + "nxp,int-edge-triggered", NULL); + pdata->remote_wakeup_enable = !!of_get_property(node, + "nxp,remote-wakeup-enable", NULL); + pdata->delay = !!of_get_property(node, + "delay", NULL); + + return 0; +} +#else +static int isp116x_get_devtree_pdata(struct platform_device *pdev, + struct isp116x_platform_data *pdata) +{ + return -ENODEV; +} +#endif /* CONFIG_OF */ + static int __devinit isp116x_probe(struct platform_device *pdev) { struct usb_hcd *hcd; struct isp116x *isp116x; struct resource *addr, *data, *ires; + struct isp116x_platform_data *pdata; void __iomem *addr_reg; void __iomem *data_reg; int irq; @@ -1624,19 +1670,30 @@ static int __devinit isp116x_probe(struct platform_device *pdev) isp116x->addr_reg = addr_reg; spin_lock_init(&isp116x->lock); INIT_LIST_HEAD(&isp116x->async); - isp116x->board = pdev->dev.platform_data; - if (!isp116x->board) { - ERR("Platform data structure not initialized\n"); - ret = -ENODEV; - goto err6; + pdata = pdev->dev.platform_data; + + /* If no platform data is available, try to get it from device tree */ + if (!pdata) { + pdata = devm_kzalloc(&pdev->dev, sizeof(struct + isp116x_platform_data), GFP_KERNEL); + if (!pdata) { + ret = -ENOMEM; + goto err6; + } + + ret = isp116x_get_devtree_pdata(pdev, pdata); + if (ret) + goto err6; } + + isp116x->board = pdata; + if (isp116x_check_platform_delay(isp116x)) { - ERR("USE_PLATFORM_DELAY defined, but delay function not " + DBG("USE_PLATFORM_DELAY defined, but delay function not " "implemented.\n"); - ERR("See comments in drivers/usb/host/isp116x-hcd.c\n"); - ret = -ENODEV; - goto err6; + DBG("Defaulting to ndelay().\n"); + isp116x->board->delay = isp116x_ndelay; } ret = usb_add_hcd(hcd, irq, irqflags | IRQF_DISABLED); @@ -1697,6 +1754,17 @@ static int isp116x_resume(struct platform_device *dev) /* work with hotplug and coldplug */ MODULE_ALIAS("platform:isp116x-hcd"); +#ifdef CONFIG_OF +static struct of_device_id isp116x_match[] = { + { .compatible = "nxp,isp1161a-1.0" }, + { .compatible = "nxp,isp116x" }, + {} +}; +MODULE_DEVICE_TABLE(of, isp116x_match); +#else +#define isp116x_match NULL +#endif /* CONFIG_OF */ + static struct platform_driver isp116x_driver = { .probe = isp116x_probe, .remove = isp116x_remove, @@ -1705,6 +1773,7 @@ static struct platform_driver isp116x_driver = { .driver = { .name = (char *)hcd_name, .owner = THIS_MODULE, + .of_match_table = isp116x_match, }, }; -- To unsubscribe from this list: send the line "unsubscribe linux-usb" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html