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 <[email protected]>
-----------------------------------------------------------------------------------------------------------------------------
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 [email protected]
More majordomo info at http://vger.kernel.org/majordomo-info.html