[PATCH] da8xx musb: add device tree support

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

 



Trying this again as plain text... sorry about that.

Attached is a patch that adds device tree support to the da8xx musb driver.  The current driver expects a board file to setup the platform device and perform the initialization. With this patch all of the setup is done through the device tree.

diffstat for this patch is:
    Documentation/devicetree/bindings/usb/da8xx-usb.txt  |   18 ++
    drivers/usb/musb/Kconfig                                                |    1
    drivers/usb/musb/da8xx.c                                                 |  139 ++++++++++++++------
    3 files changed, 119 insertions(+), 39 deletions(-)

To apply this patch, in the root of a kernel tree use:
patch -p1 < da8xx-musb.patch

Please let me know any feedback you have on this patch.

Thanks

Andrew Holcomb
Software Engineer
RELM Wireless

Signed-off-by: Andrew T Holcomb <aholcomb@xxxxxxxxxx>

-----------------------------------------------------------------------------------------------------------------------------
diff -pruN linux-4.1/Documentation/devicetree/bindings/usb/da8xx-usb.txt linux-4.1.musb/Documentation/devicetree/bindings/usb/da8xx-usb.txt
--- linux-4.1/Documentation/devicetree/bindings/usb/da8xx-usb.txt	1969-12-31 18:00:00.000000000 -0600
+++ linux-4.1.musb/Documentation/devicetree/bindings/usb/da8xx-usb.txt	2015-07-23 10:49:35.926160500 -0500
@@ -0,0 +1,18 @@
+DA8XX MUSB
+
+Required properties:
+ - compatible : Should be "ti,da8xx-musb"
+ - reg        : Offset and length of registers
+ - interrupts : Interrupt number
+ - mode       : Dual-role; either host mode "host", peripheral mode "peripheral"
+                or both "otg"
+
+Example:
+
+musb@1e00000 {
+	compatible = "ti,da8xx-musb";
+	reg = <0x01e00000 0x10000>;
+	interrupts = <58>;
+	interrupt-names = "mc";
+	mode = "peripheral";
+};
diff -pruN linux-4.1/drivers/usb/musb/da8xx.c linux-4.1.musb/drivers/usb/musb/da8xx.c
--- linux-4.1/drivers/usb/musb/da8xx.c	2015-06-22 00:05:43.000000000 -0500
+++ linux-4.1.musb/drivers/usb/musb/da8xx.c	2015-07-23 10:49:35.926160500 -0500
@@ -89,6 +89,36 @@ struct da8xx_glue {
 	struct clk		*clk;
 };
 
+static struct musb_hdrc_eps_bits musb_eps[] = {
+        { "ep1_tx", 8, },
+        { "ep1_rx", 8, },
+        { "ep2_tx", 8, },
+        { "ep2_rx", 8, },
+        { "ep3_tx", 5, },
+        { "ep3_rx", 5, },
+        { "ep4_tx", 5, },
+        { "ep4_rx", 5, },
+};
+
+static struct musb_hdrc_config musb_config = {
+        .multipoint     = true,
+        .dyn_fifo       = true,
+        .soft_con       = true,
+        .dma            = true,
+
+        .num_eps        = 5,
+        .dma_channels   = 8,
+        .ram_bits       = 10,
+        .eps_bits       = musb_eps,
+};
+
+static struct musb_hdrc_platform_data usb_data = {
+        /* OTG requires a Mini-AB connector */
+        .mode           = MUSB_PERIPHERAL,
+        .clock          = "usb20",
+        .config         = &musb_config,
+};
+
 /*
  * REVISIT (PM): we should be able to keep the PHY in low power mode most
  * of the time (24 MHz oscillator and PLL off, etc.) by setting POWER.D0
@@ -105,6 +135,9 @@ static inline void phy_on(void)
 	 */
 	cfgchip2 &= ~(CFGCHIP2_RESET | CFGCHIP2_PHYPWRDN | CFGCHIP2_OTGPWRDN);
 	cfgchip2 |= CFGCHIP2_PHY_PLLON;
+	/* USB2.0 PHY reference clock is 24 MHz */
+	cfgchip2 &= ~CFGCHIP2_REFFREQ;
+	cfgchip2 |=  CFGCHIP2_REFFREQ_24MHZ;
 	__raw_writel(cfgchip2, CFGCHIP2);
 
 	pr_info("Waiting for USB PHY clock good...\n");
@@ -480,44 +513,68 @@ static const struct platform_device_info
 
 static int da8xx_probe(struct platform_device *pdev)
 {
-	struct resource musb_resources[2];
+	struct resource			musb_resources[2];
 	struct musb_hdrc_platform_data	*pdata = dev_get_platdata(&pdev->dev);
+	struct device_node		*np = pdev->dev.of_node;
 	struct platform_device		*musb;
 	struct da8xx_glue		*glue;
-	struct platform_device_info	pinfo;
 	struct clk			*clk;
-
 	int				ret = -ENOMEM;
+	const char 			*mode;
+	int 				strlen;
 
-	glue = kzalloc(sizeof(*glue), GFP_KERNEL);
-	if (!glue) {
-		dev_err(&pdev->dev, "failed to allocate glue context\n");
+	glue = devm_kzalloc(&pdev->dev, sizeof(*glue), GFP_KERNEL);
+	if (!glue)
+		goto err0;
+
+	musb = platform_device_alloc("musb-hdrc", PLATFORM_DEVID_AUTO);
+	if (!musb) {
+		dev_err(&pdev->dev, "failed to allocate musb device\n");
 		goto err0;
 	}
 
-	clk = clk_get(&pdev->dev, "usb20");
+	clk = devm_clk_get(&pdev->dev, "usb20");
 	if (IS_ERR(clk)) {
 		dev_err(&pdev->dev, "failed to get clock\n");
 		ret = PTR_ERR(clk);
-		goto err3;
+		goto err1;
 	}
 
-	ret = clk_enable(clk);
+	ret = clk_prepare_enable(clk);
 	if (ret) {
 		dev_err(&pdev->dev, "failed to enable clock\n");
-		goto err4;
+		goto err1;
 	}
 
+	musb->dev.parent		= &pdev->dev;
+	musb->dev.dma_mask		= &pdev->dev.coherent_dma_mask;
+	musb->dev.coherent_dma_mask	= pdev->dev.coherent_dma_mask;
+
 	glue->dev			= &pdev->dev;
+	glue->musb			= musb;
 	glue->clk			= clk;
 
-	pdata->platform_ops		= &da8xx_ops;
+	if (np) {
+		pdata = &usb_data;
+		/* Mode can be overridden */
+		mode = of_get_property(np, "mode", &strlen);
+		if (!mode) {
+			dev_info(&pdev->dev, "No 'mode' property found... defaulting to MUSB_PERIPHERAL.\n");
+			pdata->mode = MUSB_PERIPHERAL;
+		}
 
-	glue->phy = usb_phy_generic_register();
-	if (IS_ERR(glue->phy)) {
-		ret = PTR_ERR(glue->phy);
-		goto err5;
+		if (strlen > 0) {
+			if (!strcmp(mode, "host"))
+				pdata->mode = MUSB_HOST;
+			if (!strcmp(mode, "otg"))
+				pdata->mode = MUSB_OTG;
+			if (!strcmp(mode, "peripheral"))
+				pdata->mode = MUSB_PERIPHERAL;
+		}
 	}
+
+	pdata->platform_ops = &da8xx_ops;
+
 	platform_set_drvdata(pdev, glue);
 
 	memset(musb_resources, 0x00, sizeof(*musb_resources) *
@@ -533,34 +590,31 @@ static int da8xx_probe(struct platform_d
 	musb_resources[1].end = pdev->resource[1].end;
 	musb_resources[1].flags = pdev->resource[1].flags;
 
-	pinfo = da8xx_dev_info;
-	pinfo.parent = &pdev->dev;
-	pinfo.res = musb_resources;
-	pinfo.num_res = ARRAY_SIZE(musb_resources);
-	pinfo.data = pdata;
-	pinfo.size_data = sizeof(*pdata);
-
-	glue->musb = musb = platform_device_register_full(&pinfo);
-	if (IS_ERR(musb)) {
-		ret = PTR_ERR(musb);
-		dev_err(&pdev->dev, "failed to register musb device: %d\n", ret);
-		goto err6;
+	ret = platform_device_add_resources(musb, musb_resources,
+			ARRAY_SIZE(musb_resources));
+	if (ret) {
+		dev_err(&pdev->dev, "failed to add resources\n");
+		goto err2;
 	}
 
-	return 0;
-
-err6:
-	usb_phy_generic_unregister(glue->phy);
-
-err5:
-	clk_disable(clk);
+	ret = platform_device_add_data(musb, pdata, sizeof(*pdata));
+	if (ret) {
+		dev_err(&pdev->dev, "failed to add platform_data\n");
+		goto err2;
+	}
 
-err4:
-	clk_put(clk);
+	ret = platform_device_add(musb);
+	if (ret) {
+		dev_err(&pdev->dev, "failed to register musb device\n");
+		goto err2;
+	}
 
-err3:
-	kfree(glue);
+	return 0;
 
+err2:
+	clk_disable_unprepare(clk);
+err1:
+	platform_device_put(musb);
 err0:
 	return ret;
 }
@@ -578,11 +632,20 @@ static int da8xx_remove(struct platform_
 	return 0;
 }
 
+static const struct of_device_id da8xx_id_table[] = {
+	{
+		.compatible = "ti,da8xx-musb"
+	},
+	{},
+};
+MODULE_DEVICE_TABLE(of, da8xx_id_table);
+
 static struct platform_driver da8xx_driver = {
 	.probe		= da8xx_probe,
 	.remove		= da8xx_remove,
 	.driver		= {
 		.name	= "musb-da8xx",
+		.of_match_table = of_match_ptr(da8xx_id_table),
 	},
 };
 
diff -pruN linux-4.1/drivers/usb/musb/Kconfig linux-4.1.musb/drivers/usb/musb/Kconfig
--- linux-4.1/drivers/usb/musb/Kconfig	2015-06-22 00:05:43.000000000 -0500
+++ linux-4.1.musb/drivers/usb/musb/Kconfig	2015-07-23 10:49:35.926160500 -0500
@@ -70,7 +70,6 @@ config USB_MUSB_DA8XX
 	tristate "DA8xx/OMAP-L1x"
 	depends on ARCH_DAVINCI_DA8XX
 	depends on NOP_USB_XCEIV
-	depends on BROKEN
 
 config USB_MUSB_TUSB6010
 	tristate "TUSB6010"
--
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