summaryrefslogtreecommitdiffstats
path: root/drivers/usb/chipidea/core.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/usb/chipidea/core.c')
-rw-r--r--drivers/usb/chipidea/core.c70
1 files changed, 64 insertions, 6 deletions
diff --git a/drivers/usb/chipidea/core.c b/drivers/usb/chipidea/core.c
index 15e03b308f8a..1083585fad00 100644
--- a/drivers/usb/chipidea/core.c
+++ b/drivers/usb/chipidea/core.c
@@ -56,6 +56,7 @@
#include <linux/init.h>
#include <linux/platform_device.h>
#include <linux/module.h>
+#include <linux/idr.h>
#include <linux/interrupt.h>
#include <linux/io.h>
#include <linux/irq.h>
@@ -179,7 +180,7 @@ static int hw_device_init(struct ci13xxx *ci, void __iomem *base)
ci->hw_bank.abs = base;
ci->hw_bank.cap = ci->hw_bank.abs;
- ci->hw_bank.cap += ci->udc_driver->capoffset;
+ ci->hw_bank.cap += ci->platdata->capoffset;
ci->hw_bank.op = ci->hw_bank.cap + ioread8(ci->hw_bank.cap);
hw_alloc_regmap(ci, false);
@@ -227,11 +228,11 @@ int hw_device_reset(struct ci13xxx *ci, u32 mode)
udelay(10); /* not RTOS friendly */
- if (ci->udc_driver->notify_event)
- ci->udc_driver->notify_event(ci,
+ if (ci->platdata->notify_event)
+ ci->platdata->notify_event(ci,
CI13XXX_CONTROLLER_RESET_EVENT);
- if (ci->udc_driver->flags & CI13XXX_DISABLE_STREAMING)
+ if (ci->platdata->flags & CI13XXX_DISABLE_STREAMING)
hw_write(ci, OP_USBMODE, USBMODE_CI_SDIS, USBMODE_CI_SDIS);
/* USBMODE should be configured step by step */
@@ -332,6 +333,59 @@ static irqreturn_t ci_irq(int irq, void *data)
return ci->role == CI_ROLE_END ? ret : ci_role(ci)->irq(ci);
}
+static DEFINE_IDA(ci_ida);
+
+struct platform_device *ci13xxx_add_device(struct device *dev,
+ struct resource *res, int nres,
+ struct ci13xxx_platform_data *platdata)
+{
+ struct platform_device *pdev;
+ int id, ret;
+
+ id = ida_simple_get(&ci_ida, 0, 0, GFP_KERNEL);
+ if (id < 0)
+ return ERR_PTR(id);
+
+ pdev = platform_device_alloc("ci_hdrc", id);
+ if (!pdev) {
+ ret = -ENOMEM;
+ goto put_id;
+ }
+
+ pdev->dev.parent = dev;
+ pdev->dev.dma_mask = dev->dma_mask;
+ pdev->dev.dma_parms = dev->dma_parms;
+ dma_set_coherent_mask(&pdev->dev, dev->coherent_dma_mask);
+
+ ret = platform_device_add_resources(pdev, res, nres);
+ if (ret)
+ goto err;
+
+ ret = platform_device_add_data(pdev, platdata, sizeof(*platdata));
+ if (ret)
+ goto err;
+
+ ret = platform_device_add(pdev);
+ if (ret)
+ goto err;
+
+ return pdev;
+
+err:
+ platform_device_put(pdev);
+put_id:
+ ida_simple_remove(&ci_ida, id);
+ return ERR_PTR(ret);
+}
+EXPORT_SYMBOL_GPL(ci13xxx_add_device);
+
+void ci13xxx_remove_device(struct platform_device *pdev)
+{
+ platform_device_unregister(pdev);
+ ida_simple_remove(&ci_ida, pdev->id);
+}
+EXPORT_SYMBOL_GPL(ci13xxx_remove_device);
+
static int __devinit ci_hdrc_probe(struct platform_device *pdev)
{
struct device *dev = &pdev->dev;
@@ -364,7 +418,11 @@ static int __devinit ci_hdrc_probe(struct platform_device *pdev)
}
ci->dev = dev;
- ci->udc_driver = dev->platform_data;
+ ci->platdata = dev->platform_data;
+ if (ci->platdata->phy)
+ ci->transceiver = ci->platdata->phy;
+ else
+ ci->global_phy = true;
ret = hw_device_init(ci, base);
if (ret < 0) {
@@ -419,7 +477,7 @@ static int __devinit ci_hdrc_probe(struct platform_device *pdev)
}
platform_set_drvdata(pdev, ci);
- ret = request_irq(ci->irq, ci_irq, IRQF_SHARED, ci->udc_driver->name,
+ ret = request_irq(ci->irq, ci_irq, IRQF_SHARED, ci->platdata->name,
ci);
if (ret)
goto stop;