[PATCH] NXP ISP116x Host Controller Driver Device Tree Support

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

 



Here are the list of changes:
1) Added devtree support into the code by adding
".of_match_table = isp116x_match" (see end of code).
2) Added a reference to the ndelay() function called isp116x_ndelay(). Therefore, if
platform delay function is not defined in devicetree, the delay function will default
to ndelay() by calling this reference function.
3) Use devm_kzalloc() during probe function.
4) pdata config setting now gets its bool values from the device tree.
5) Changed delay check to default to ndelay() if no plateform delay is used.

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