[V2 PATCH 25/27] usb: gadget: mv_udc: add device tree support

Chao Xie chao.xie at marvell.com
Tue Nov 27 22:06:24 EST 2012


In original driver, we have callbacks in platform data, and some
dynamically allocations variables in platform data.
Now, these blocks are removed, the device tree support is easier
now.

Signed-off-by: Chao Xie <chao.xie at marvell.com>
---
 drivers/usb/gadget/mv_udc.h      |    5 +-
 drivers/usb/gadget/mv_udc_core.c |  105 ++++++++++++++++++++++++++++++--------
 2 files changed, 85 insertions(+), 25 deletions(-)

diff --git a/drivers/usb/gadget/mv_udc.h b/drivers/usb/gadget/mv_udc.h
index 50ae7c7..de84722 100644
--- a/drivers/usb/gadget/mv_udc.h
+++ b/drivers/usb/gadget/mv_udc.h
@@ -179,6 +179,7 @@ struct mv_udc {
 	int				irq;
 
 	unsigned int			extern_attr;
+	unsigned int			mode;
 	struct notifier_block		notifier;
 
 	struct mv_cap_regs __iomem	*cap_regs;
@@ -222,11 +223,9 @@ struct mv_udc {
 	struct mv_usb2_phy	*phy;
 	struct usb_phy		*transceiver;
 
-	struct mv_usb_platform_data     *pdata;
-
 	/* some SOC has mutiple clock sources for USB*/
 	unsigned int    clknum;
-	struct clk      *clk[0];
+	struct clk      **clk;
 };
 
 /* endpoint data structure */
diff --git a/drivers/usb/gadget/mv_udc_core.c b/drivers/usb/gadget/mv_udc_core.c
index 5571f42..2273a0c 100644
--- a/drivers/usb/gadget/mv_udc_core.c
+++ b/drivers/usb/gadget/mv_udc_core.c
@@ -34,6 +34,7 @@
 #include <linux/irq.h>
 #include <linux/platform_device.h>
 #include <linux/clk.h>
+#include <linux/of.h>
 #include <linux/platform_data/mv_usb.h>
 #include <linux/usb/mv_usb2.h>
 #include <asm/unaligned.h>
@@ -2153,21 +2154,57 @@ static int __devexit mv_udc_remove(struct platform_device *pdev)
 	return 0;
 }
 
+static int __devinit mv_udc_parse_dt(struct platform_device *pdev,
+				struct mv_udc *udc)
+{
+	struct device_node *np = pdev->dev.of_node;
+	unsigned int clks_num;
+	int i, ret;
+	const char *clk_name;
+
+	if (!np)
+		return 1;
+
+	clks_num = of_property_count_strings(np, "clocks");
+	if (clks_num < 0)
+		return clks_num;
+
+	udc->clk = devm_kzalloc(&pdev->dev,
+		sizeof(struct clk *) * clks_num, GFP_KERNEL);
+	if (udc->clk == NULL)
+		return -ENOMEM;
+
+	for (i = 0; i < clks_num; i++) {
+		ret = of_property_read_string_index(np, "clocks", i,
+			&clk_name);
+		if (ret)
+			return ret;
+		udc->clk[i] = devm_clk_get(&pdev->dev, clk_name);
+		if (IS_ERR(udc->clk[i]))
+			return PTR_ERR(udc->clk[i]);
+	}
+
+	udc->clknum = clks_num;
+
+	ret = of_property_read_u32(np, "extern_attr", &udc->extern_attr);
+	if (ret)
+		return ret;
+
+	ret = of_property_read_u32(np, "mode", &udc->mode);
+	if (ret)
+		return ret;
+
+	return 0;
+}
+
 static int __devinit mv_udc_probe(struct platform_device *pdev)
 {
-	struct mv_usb_platform_data *pdata = pdev->dev.platform_data;
 	struct mv_udc *udc;
 	int retval = 0;
-	int clk_i = 0;
 	struct resource *r;
 	size_t size;
 
-	if (pdata == NULL) {
-		dev_err(&pdev->dev, "missing platform_data\n");
-		return -ENODEV;
-	}
-
-	size = sizeof(*udc) + sizeof(struct clk *) * pdata->clknum;
+	size = sizeof(*udc);
 	udc = devm_kzalloc(&pdev->dev, size, GFP_KERNEL);
 	if (udc == NULL) {
 		dev_err(&pdev->dev, "failed to allocate memory for udc\n");
@@ -2175,14 +2212,43 @@ static int __devinit mv_udc_probe(struct platform_device *pdev)
 	}
 
 	udc->done = &release_done;
-	udc->extern_attr = pdata->extern_attr;
-	udc->pdata = pdev->dev.platform_data;
 	spin_lock_init(&udc->lock);
 
 	udc->dev = pdev;
 
+	retval = mv_udc_parse_dt(pdev, udc);
+	if (retval > 0) {
+		/* no CONFIG_OF */
+		struct mv_usb_platform_data *pdata = pdev->dev.platform_data;
+		int clk_i = 0;
+
+		if (pdata == NULL) {
+			dev_err(&pdev->dev, "missing platform_data\n");
+			return -ENODEV;
+		}
+		udc->extern_attr = pdata->extern_attr;
+		udc->mode = pdata->mode;
+		udc->clknum = pdata->clknum;
+
+		size = sizeof(struct clk *) * udc->clknum;
+		udc->clk = devm_kzalloc(&pdev->dev, size, GFP_KERNEL);
+		if (udc->clk == NULL)
+			return -ENOMEM;
+		for (clk_i = 0; clk_i < udc->clknum; clk_i++) {
+			udc->clk[clk_i] = devm_clk_get(&pdev->dev,
+						pdata->clkname[clk_i]);
+			if (IS_ERR(udc->clk[clk_i])) {
+				retval = PTR_ERR(udc->clk[clk_i]);
+				return retval;
+			}
+		}
+	} else if (retval < 0) {
+		dev_err(&pdev->dev, "error parse dt\n");
+		return retval;
+	}
+
 #ifdef CONFIG_USB_OTG_UTILS
-	if (pdata->mode == MV_USB_MODE_OTG) {
+	if (udc->mode == MV_USB_MODE_OTG) {
 		udc->transceiver = devm_usb_get_phy(&pdev->dev,
 					USB_PHY_TYPE_USB2);
 		if (IS_ERR_OR_NULL(udc->transceiver)) {
@@ -2191,17 +2257,6 @@ static int __devinit mv_udc_probe(struct platform_device *pdev)
 		}
 	}
 #endif
-
-	udc->clknum = pdata->clknum;
-	for (clk_i = 0; clk_i < udc->clknum; clk_i++) {
-		udc->clk[clk_i] = devm_clk_get(&pdev->dev,
-					pdata->clkname[clk_i]);
-		if (IS_ERR(udc->clk[clk_i])) {
-			retval = PTR_ERR(udc->clk[clk_i]);
-			return retval;
-		}
-	}
-
 	r = platform_get_resource(udc->dev, IORESOURCE_MEM, 0);
 	if (r == NULL) {
 		dev_err(&pdev->dev, "no I/O memory resource defined\n");
@@ -2466,6 +2521,11 @@ static void mv_udc_shutdown(struct platform_device *pdev)
 	mv_udc_disable(udc);
 }
 
+static struct of_device_id mv_udc_dt_ids[] = {
+	{ .compatible = "mrvl,mv-udc" },
+};
+MODULE_DEVICE_TABLE(of, mv_udc_dt_ids);
+
 static struct platform_driver udc_driver = {
 	.probe		= mv_udc_probe,
 	.remove		= __exit_p(mv_udc_remove),
@@ -2476,6 +2536,7 @@ static struct platform_driver udc_driver = {
 #ifdef CONFIG_PM
 		.pm	= &mv_udc_pm_ops,
 #endif
+		.of_match_table = mv_udc_dt_ids,
 	},
 };
 
-- 
1.7.4.1




More information about the linux-arm-kernel mailing list