Merge tag 'drivers-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/arm...
[sfrench/cifs-2.6.git] / drivers / usb / musb / ux500.c
index 2c80004e0a83029b52b7ea13f2d4c97194f40412..fce71b605936ed228bc104efd2d5d60c0959af2f 100644 (file)
 #include <linux/clk.h>
 #include <linux/err.h>
 #include <linux/io.h>
+#include <linux/of.h>
 #include <linux/platform_device.h>
 #include <linux/usb/musb-ux500.h>
 
 #include "musb_core.h"
 
+static struct musb_hdrc_config ux500_musb_hdrc_config = {
+       .multipoint     = true,
+       .dyn_fifo       = true,
+       .num_eps        = 16,
+       .ram_bits       = 16,
+};
+
 struct ux500_glue {
        struct device           *dev;
        struct platform_device  *musb;
@@ -187,14 +195,58 @@ static const struct musb_platform_ops ux500_ops = {
        .set_vbus       = ux500_musb_set_vbus,
 };
 
+static struct musb_hdrc_platform_data *
+ux500_of_probe(struct platform_device *pdev, struct device_node *np)
+{
+       struct musb_hdrc_platform_data *pdata;
+       const char *mode;
+       int strlen;
+
+       pdata = devm_kzalloc(&pdev->dev, sizeof(*pdata), GFP_KERNEL);
+       if (!pdata)
+               return NULL;
+
+       mode = of_get_property(np, "dr_mode", &strlen);
+       if (!mode) {
+               dev_err(&pdev->dev, "No 'dr_mode' property found\n");
+               return NULL;
+       }
+
+       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;
+       }
+
+       return pdata;
+}
+
 static int ux500_probe(struct platform_device *pdev)
 {
+       struct resource musb_resources[2];
        struct musb_hdrc_platform_data  *pdata = pdev->dev.platform_data;
+       struct device_node              *np = pdev->dev.of_node;
        struct platform_device          *musb;
        struct ux500_glue               *glue;
        struct clk                      *clk;
        int                             ret = -ENOMEM;
 
+       if (!pdata) {
+               if (np) {
+                       pdata = ux500_of_probe(pdev, np);
+                       if (!pdata)
+                               goto err0;
+
+                       pdev->dev.platform_data = pdata;
+               } else {
+                       dev_err(&pdev->dev, "no pdata or device tree found\n");
+                       goto err0;
+               }
+       }
+
        glue = kzalloc(sizeof(*glue), GFP_KERNEL);
        if (!glue) {
                dev_err(&pdev->dev, "failed to allocate glue context\n");
@@ -221,19 +273,34 @@ static int ux500_probe(struct platform_device *pdev)
        }
 
        musb->dev.parent                = &pdev->dev;
-       musb->dev.dma_mask              = pdev->dev.dma_mask;
+       musb->dev.dma_mask              = &pdev->dev.coherent_dma_mask;
        musb->dev.coherent_dma_mask     = pdev->dev.coherent_dma_mask;
+       musb->dev.of_node               = pdev->dev.of_node;
 
        glue->dev                       = &pdev->dev;
        glue->musb                      = musb;
        glue->clk                       = clk;
 
        pdata->platform_ops             = &ux500_ops;
+       pdata->config                   = &ux500_musb_hdrc_config;
 
        platform_set_drvdata(pdev, glue);
 
-       ret = platform_device_add_resources(musb, pdev->resource,
-                       pdev->num_resources);
+       memset(musb_resources, 0x00, sizeof(*musb_resources) *
+                       ARRAY_SIZE(musb_resources));
+
+       musb_resources[0].name = pdev->resource[0].name;
+       musb_resources[0].start = pdev->resource[0].start;
+       musb_resources[0].end = pdev->resource[0].end;
+       musb_resources[0].flags = pdev->resource[0].flags;
+
+       musb_resources[1].name = pdev->resource[1].name;
+       musb_resources[1].start = pdev->resource[1].start;
+       musb_resources[1].end = pdev->resource[1].end;
+       musb_resources[1].flags = pdev->resource[1].flags;
+
+       ret = platform_device_add_resources(musb, musb_resources,
+                       ARRAY_SIZE(musb_resources));
        if (ret) {
                dev_err(&pdev->dev, "failed to add resources\n");
                goto err5;
@@ -320,12 +387,18 @@ static const struct dev_pm_ops ux500_pm_ops = {
 #define DEV_PM_OPS     NULL
 #endif
 
+static const struct of_device_id ux500_match[] = {
+        { .compatible = "stericsson,db8500-musb", },
+        {}
+};
+
 static struct platform_driver ux500_driver = {
        .probe          = ux500_probe,
        .remove         = ux500_remove,
        .driver         = {
                .name   = "musb-ux500",
                .pm     = DEV_PM_OPS,
+               .of_match_table = ux500_match,
        },
 };