[PATCH] ISP116x Host Controller Driver Device Tree Support

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



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


[Index of Archives]     [Linux Media]     [Linux Input]     [Linux Audio Users]     [Yosemite News]     [Linux Kernel]     [Linux SCSI]     [Old Linux USB Devel Archive]

  Powered by Linux