|
@@ -25,6 +25,7 @@
|
|
#include <linux/clk.h>
|
|
#include <linux/clk.h>
|
|
#include <linux/err.h>
|
|
#include <linux/err.h>
|
|
#include <linux/io.h>
|
|
#include <linux/io.h>
|
|
|
|
+#include <linux/of.h>
|
|
#include <linux/platform_device.h>
|
|
#include <linux/platform_device.h>
|
|
#include <linux/usb/musb-ux500.h>
|
|
#include <linux/usb/musb-ux500.h>
|
|
|
|
|
|
@@ -194,14 +195,57 @@ static const struct musb_platform_ops ux500_ops = {
|
|
.set_vbus = ux500_musb_set_vbus,
|
|
.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)
|
|
static int ux500_probe(struct platform_device *pdev)
|
|
{
|
|
{
|
|
struct musb_hdrc_platform_data *pdata = pdev->dev.platform_data;
|
|
struct musb_hdrc_platform_data *pdata = pdev->dev.platform_data;
|
|
|
|
+ struct device_node *np = pdev->dev.of_node;
|
|
struct platform_device *musb;
|
|
struct platform_device *musb;
|
|
struct ux500_glue *glue;
|
|
struct ux500_glue *glue;
|
|
struct clk *clk;
|
|
struct clk *clk;
|
|
int ret = -ENOMEM;
|
|
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);
|
|
glue = kzalloc(sizeof(*glue), GFP_KERNEL);
|
|
if (!glue) {
|
|
if (!glue) {
|
|
dev_err(&pdev->dev, "failed to allocate glue context\n");
|
|
dev_err(&pdev->dev, "failed to allocate glue context\n");
|
|
@@ -230,6 +274,7 @@ static int ux500_probe(struct platform_device *pdev)
|
|
musb->dev.parent = &pdev->dev;
|
|
musb->dev.parent = &pdev->dev;
|
|
musb->dev.dma_mask = &pdev->dev.coherent_dma_mask;
|
|
musb->dev.dma_mask = &pdev->dev.coherent_dma_mask;
|
|
musb->dev.coherent_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->dev = &pdev->dev;
|
|
glue->musb = musb;
|
|
glue->musb = musb;
|
|
@@ -328,12 +373,18 @@ static const struct dev_pm_ops ux500_pm_ops = {
|
|
#define DEV_PM_OPS NULL
|
|
#define DEV_PM_OPS NULL
|
|
#endif
|
|
#endif
|
|
|
|
|
|
|
|
+static const struct of_device_id ux500_match[] = {
|
|
|
|
+ { .compatible = "stericsson,db8500-musb", },
|
|
|
|
+ {}
|
|
|
|
+};
|
|
|
|
+
|
|
static struct platform_driver ux500_driver = {
|
|
static struct platform_driver ux500_driver = {
|
|
.probe = ux500_probe,
|
|
.probe = ux500_probe,
|
|
.remove = ux500_remove,
|
|
.remove = ux500_remove,
|
|
.driver = {
|
|
.driver = {
|
|
.name = "musb-ux500",
|
|
.name = "musb-ux500",
|
|
.pm = DEV_PM_OPS,
|
|
.pm = DEV_PM_OPS,
|
|
|
|
+ .of_match_table = ux500_match,
|
|
},
|
|
},
|
|
};
|
|
};
|
|
|
|
|