aboutsummaryrefslogtreecommitdiff
path: root/drivers/usb/chipidea
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/usb/chipidea')
-rw-r--r--drivers/usb/chipidea/Kconfig1
-rw-r--r--drivers/usb/chipidea/Makefile9
-rw-r--r--drivers/usb/chipidea/ci.h32
-rw-r--r--drivers/usb/chipidea/ci13xxx_imx.c198
-rw-r--r--drivers/usb/chipidea/ci13xxx_msm.c63
-rw-r--r--drivers/usb/chipidea/ci13xxx_pci.c52
-rw-r--r--drivers/usb/chipidea/core.c70
-rw-r--r--drivers/usb/chipidea/debug.c146
-rw-r--r--drivers/usb/chipidea/host.c3
-rw-r--r--drivers/usb/chipidea/udc.c635
10 files changed, 721 insertions, 488 deletions
diff --git a/drivers/usb/chipidea/Kconfig b/drivers/usb/chipidea/Kconfig
index fd36dc8b889..8337fb5d988 100644
--- a/drivers/usb/chipidea/Kconfig
+++ b/drivers/usb/chipidea/Kconfig
@@ -20,6 +20,7 @@ config USB_CHIPIDEA_UDC
config USB_CHIPIDEA_HOST
bool "ChipIdea host controller"
+ select USB_EHCI_ROOT_HUB_TT
help
Say Y here to enable host controller functionality of the
ChipIdea driver.
diff --git a/drivers/usb/chipidea/Makefile b/drivers/usb/chipidea/Makefile
index cc349376972..5c66d9c330c 100644
--- a/drivers/usb/chipidea/Makefile
+++ b/drivers/usb/chipidea/Makefile
@@ -5,10 +5,15 @@ ci_hdrc-$(CONFIG_USB_CHIPIDEA_UDC) += udc.o
ci_hdrc-$(CONFIG_USB_CHIPIDEA_HOST) += host.o
ci_hdrc-$(CONFIG_USB_CHIPIDEA_DEBUG) += debug.o
+# Glue/Bridge layers go here
+
+obj-$(CONFIG_USB_CHIPIDEA) += ci13xxx_msm.o
+
+# PCI doesn't provide stubs, need to check
ifneq ($(CONFIG_PCI),)
obj-$(CONFIG_USB_CHIPIDEA) += ci13xxx_pci.o
endif
-ifneq ($(CONFIG_ARCH_MSM),)
- obj-$(CONFIG_USB_CHIPIDEA) += ci13xxx_msm.o
+ifneq ($(CONFIG_OF_DEVICE),)
+ obj-$(CONFIG_USB_CHIPIDEA) += ci13xxx_imx.o
endif
diff --git a/drivers/usb/chipidea/ci.h b/drivers/usb/chipidea/ci.h
index 50911f8490d..d738603a275 100644
--- a/drivers/usb/chipidea/ci.h
+++ b/drivers/usb/chipidea/ci.h
@@ -36,7 +36,7 @@
* @name: string description of the endpoint
* @qh: queue head for this endpoint
* @wedge: is the endpoint wedged
- * @udc: pointer to the controller
+ * @ci: pointer to the controller
* @lock: pointer to controller's spinlock
* @td_pool: pointer to controller's TD pool
*/
@@ -54,7 +54,7 @@ struct ci13xxx_ep {
int wedge;
/* global resources */
- struct ci13xxx *udc;
+ struct ci13xxx *ci;
spinlock_t *lock;
struct dma_pool *td_pool;
};
@@ -125,7 +125,7 @@ struct hw_bank {
* @remote_wakeup: host-enabled remote wakeup
* @suspended: suspended by host
* @test_mode: the selected test mode
- * @udc_driver: platform specific information supplied by parent device
+ * @platdata: platform specific information supplied by parent device
* @vbus_active: is VBUS active
* @transceiver: pointer to USB PHY, if any
* @hcd: pointer to usb_hcd for ehci host driver
@@ -158,8 +158,10 @@ struct ci13xxx {
u8 suspended;
u8 test_mode;
- struct ci13xxx_udc_driver *udc_driver;
+ struct ci13xxx_platform_data *platdata;
int vbus_active;
+ /* FIXME: some day, we'll not use global phy */
+ bool global_phy;
struct usb_phy *transceiver;
struct usb_hcd *hcd;
};
@@ -250,9 +252,9 @@ static inline int ffs_nr(u32 x)
*
* This function returns register contents
*/
-static inline u32 hw_read(struct ci13xxx *udc, enum ci13xxx_regs reg, u32 mask)
+static inline u32 hw_read(struct ci13xxx *ci, enum ci13xxx_regs reg, u32 mask)
{
- return ioread32(udc->hw_bank.regmap[reg]) & mask;
+ return ioread32(ci->hw_bank.regmap[reg]) & mask;
}
/**
@@ -261,14 +263,14 @@ static inline u32 hw_read(struct ci13xxx *udc, enum ci13xxx_regs reg, u32 mask)
* @mask: bitfield mask
* @data: new value
*/
-static inline void hw_write(struct ci13xxx *udc, enum ci13xxx_regs reg,
+static inline void hw_write(struct ci13xxx *ci, enum ci13xxx_regs reg,
u32 mask, u32 data)
{
if (~mask)
- data = (ioread32(udc->hw_bank.regmap[reg]) & ~mask)
+ data = (ioread32(ci->hw_bank.regmap[reg]) & ~mask)
| (data & mask);
- iowrite32(data, udc->hw_bank.regmap[reg]);
+ iowrite32(data, ci->hw_bank.regmap[reg]);
}
/**
@@ -278,12 +280,12 @@ static inline void hw_write(struct ci13xxx *udc, enum ci13xxx_regs reg,
*
* This function returns register contents
*/
-static inline u32 hw_test_and_clear(struct ci13xxx *udc, enum ci13xxx_regs reg,
+static inline u32 hw_test_and_clear(struct ci13xxx *ci, enum ci13xxx_regs reg,
u32 mask)
{
- u32 val = ioread32(udc->hw_bank.regmap[reg]) & mask;
+ u32 val = ioread32(ci->hw_bank.regmap[reg]) & mask;
- iowrite32(val, udc->hw_bank.regmap[reg]);
+ iowrite32(val, ci->hw_bank.regmap[reg]);
return val;
}
@@ -295,12 +297,12 @@ static inline u32 hw_test_and_clear(struct ci13xxx *udc, enum ci13xxx_regs reg,
*
* This function returns register contents
*/
-static inline u32 hw_test_and_write(struct ci13xxx *udc, enum ci13xxx_regs reg,
+static inline u32 hw_test_and_write(struct ci13xxx *ci, enum ci13xxx_regs reg,
u32 mask, u32 data)
{
- u32 val = hw_read(udc, reg, ~0);
+ u32 val = hw_read(ci, reg, ~0);
- hw_write(udc, reg, mask, data);
+ hw_write(ci, reg, mask, data);
return (val & mask) >> ffs_nr(mask);
}
diff --git a/drivers/usb/chipidea/ci13xxx_imx.c b/drivers/usb/chipidea/ci13xxx_imx.c
new file mode 100644
index 00000000000..ef60d06835d
--- /dev/null
+++ b/drivers/usb/chipidea/ci13xxx_imx.c
@@ -0,0 +1,198 @@
+/*
+ * Copyright 2012 Freescale Semiconductor, Inc.
+ * Copyright (C) 2012 Marek Vasut <marex@denx.de>
+ * on behalf of DENX Software Engineering GmbH
+ *
+ * The code contained herein is licensed under the GNU General Public
+ * License. You may obtain a copy of the GNU General Public License
+ * Version 2 or later at the following locations:
+ *
+ * http://www.opensource.org/licenses/gpl-license.html
+ * http://www.gnu.org/copyleft/gpl.html
+ */
+
+#include <linux/module.h>
+#include <linux/of_platform.h>
+#include <linux/of_gpio.h>
+#include <linux/platform_device.h>
+#include <linux/pm_runtime.h>
+#include <linux/dma-mapping.h>
+#include <linux/usb/chipidea.h>
+#include <linux/clk.h>
+#include <linux/regulator/consumer.h>
+
+#include "ci.h"
+
+#define pdev_to_phy(pdev) \
+ ((struct usb_phy *)platform_get_drvdata(pdev))
+
+struct ci13xxx_imx_data {
+ struct device_node *phy_np;
+ struct usb_phy *phy;
+ struct platform_device *ci_pdev;
+ struct clk *clk;
+ struct regulator *reg_vbus;
+};
+
+static struct ci13xxx_platform_data ci13xxx_imx_platdata __devinitdata = {
+ .name = "ci13xxx_imx",
+ .flags = CI13XXX_REQUIRE_TRANSCEIVER |
+ CI13XXX_PULLUP_ON_VBUS |
+ CI13XXX_DISABLE_STREAMING,
+ .capoffset = DEF_CAPOFFSET,
+};
+
+static int __devinit ci13xxx_imx_probe(struct platform_device *pdev)
+{
+ struct ci13xxx_imx_data *data;
+ struct platform_device *plat_ci, *phy_pdev;
+ struct device_node *phy_np;
+ struct resource *res;
+ struct regulator *reg_vbus;
+ int ret;
+
+ data = devm_kzalloc(&pdev->dev, sizeof(*data), GFP_KERNEL);
+ if (!data) {
+ dev_err(&pdev->dev, "Failed to allocate CI13xxx-IMX data!\n");
+ return -ENOMEM;
+ }
+
+ res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+ if (!res) {
+ dev_err(&pdev->dev, "Can't get device resources!\n");
+ return -ENOENT;
+ }
+
+ data->clk = devm_clk_get(&pdev->dev, NULL);
+ if (IS_ERR(data->clk)) {
+ dev_err(&pdev->dev,
+ "Failed to get clock, err=%ld\n", PTR_ERR(data->clk));
+ return PTR_ERR(data->clk);
+ }
+
+ ret = clk_prepare_enable(data->clk);
+ if (ret) {
+ dev_err(&pdev->dev,
+ "Failed to prepare or enable clock, err=%d\n", ret);
+ return ret;
+ }
+
+ phy_np = of_parse_phandle(pdev->dev.of_node, "fsl,usbphy", 0);
+ if (phy_np) {
+ data->phy_np = phy_np;
+ phy_pdev = of_find_device_by_node(phy_np);
+ if (phy_pdev) {
+ struct usb_phy *phy;
+ phy = pdev_to_phy(phy_pdev);
+ if (phy &&
+ try_module_get(phy_pdev->dev.driver->owner)) {
+ usb_phy_init(phy);
+ data->phy = phy;
+ }
+ }
+ }
+
+ /* we only support host now, so enable vbus here */
+ reg_vbus = devm_regulator_get(&pdev->dev, "vbus");
+ if (!IS_ERR(reg_vbus)) {
+ ret = regulator_enable(reg_vbus);
+ if (ret) {
+ dev_err(&pdev->dev,
+ "Failed to enable vbus regulator, err=%d\n",
+ ret);
+ goto put_np;
+ }
+ data->reg_vbus = reg_vbus;
+ } else {
+ reg_vbus = NULL;
+ }
+
+ ci13xxx_imx_platdata.phy = data->phy;
+
+ if (!pdev->dev.dma_mask) {
+ pdev->dev.dma_mask = devm_kzalloc(&pdev->dev,
+ sizeof(*pdev->dev.dma_mask), GFP_KERNEL);
+ if (!pdev->dev.dma_mask) {
+ ret = -ENOMEM;
+ dev_err(&pdev->dev, "Failed to alloc dma_mask!\n");
+ goto err;
+ }
+ *pdev->dev.dma_mask = DMA_BIT_MASK(32);
+ dma_set_coherent_mask(&pdev->dev, *pdev->dev.dma_mask);
+ }
+ plat_ci = ci13xxx_add_device(&pdev->dev,
+ pdev->resource, pdev->num_resources,
+ &ci13xxx_imx_platdata);
+ if (IS_ERR(plat_ci)) {
+ ret = PTR_ERR(plat_ci);
+ dev_err(&pdev->dev,
+ "Can't register ci_hdrc platform device, err=%d\n",
+ ret);
+ goto err;
+ }
+
+ data->ci_pdev = plat_ci;
+ platform_set_drvdata(pdev, data);
+
+ pm_runtime_no_callbacks(&pdev->dev);
+ pm_runtime_enable(&pdev->dev);
+
+ return 0;
+
+err:
+ if (reg_vbus)
+ regulator_disable(reg_vbus);
+put_np:
+ if (phy_np)
+ of_node_put(phy_np);
+ clk_disable_unprepare(data->clk);
+ return ret;
+}
+
+static int __devexit ci13xxx_imx_remove(struct platform_device *pdev)
+{
+ struct ci13xxx_imx_data *data = platform_get_drvdata(pdev);
+
+ pm_runtime_disable(&pdev->dev);
+ ci13xxx_remove_device(data->ci_pdev);
+
+ if (data->reg_vbus)
+ regulator_disable(data->reg_vbus);
+
+ if (data->phy) {
+ usb_phy_shutdown(data->phy);
+ module_put(data->phy->dev->driver->owner);
+ }
+
+ of_node_put(data->phy_np);
+
+ clk_disable_unprepare(data->clk);
+
+ platform_set_drvdata(pdev, NULL);
+
+ return 0;
+}
+
+static const struct of_device_id ci13xxx_imx_dt_ids[] = {
+ { .compatible = "fsl,imx27-usb", },
+ { /* sentinel */ }
+};
+MODULE_DEVICE_TABLE(of, ci13xxx_imx_dt_ids);
+
+static struct platform_driver ci13xxx_imx_driver = {
+ .probe = ci13xxx_imx_probe,
+ .remove = __devexit_p(ci13xxx_imx_remove),
+ .driver = {
+ .name = "imx_usb",
+ .owner = THIS_MODULE,
+ .of_match_table = ci13xxx_imx_dt_ids,
+ },
+};
+
+module_platform_driver(ci13xxx_imx_driver);
+
+MODULE_ALIAS("platform:imx-usb");
+MODULE_LICENSE("GPL v2");
+MODULE_DESCRIPTION("CI13xxx i.MX USB binding");
+MODULE_AUTHOR("Marek Vasut <marex@denx.de>");
+MODULE_AUTHOR("Richard Zhao <richard.zhao@freescale.com>");
diff --git a/drivers/usb/chipidea/ci13xxx_msm.c b/drivers/usb/chipidea/ci13xxx_msm.c
index 958069ef95e..b01feb3be92 100644
--- a/drivers/usb/chipidea/ci13xxx_msm.c
+++ b/drivers/usb/chipidea/ci13xxx_msm.c
@@ -15,11 +15,11 @@
#include "ci.h"
-#define MSM_USB_BASE (udc->hw_bank.abs)
+#define MSM_USB_BASE (ci->hw_bank.abs)
-static void ci13xxx_msm_notify_event(struct ci13xxx *udc, unsigned event)
+static void ci13xxx_msm_notify_event(struct ci13xxx *ci, unsigned event)
{
- struct device *dev = udc->gadget.dev.parent;
+ struct device *dev = ci->gadget.dev.parent;
int val;
switch (event) {
@@ -34,18 +34,18 @@ static void ci13xxx_msm_notify_event(struct ci13xxx *udc, unsigned event)
* Put the transceiver in non-driving mode. Otherwise host
* may not detect soft-disconnection.
*/
- val = usb_phy_io_read(udc->transceiver, ULPI_FUNC_CTRL);
+ val = usb_phy_io_read(ci->transceiver, ULPI_FUNC_CTRL);
val &= ~ULPI_FUNC_CTRL_OPMODE_MASK;
val |= ULPI_FUNC_CTRL_OPMODE_NONDRIVING;
- usb_phy_io_write(udc->transceiver, val, ULPI_FUNC_CTRL);
+ usb_phy_io_write(ci->transceiver, val, ULPI_FUNC_CTRL);
break;
default:
- dev_dbg(dev, "unknown ci13xxx_udc event\n");
+ dev_dbg(dev, "unknown ci13xxx event\n");
break;
}
}
-static struct ci13xxx_udc_driver ci13xxx_msm_udc_driver = {
+static struct ci13xxx_platform_data ci13xxx_msm_platdata = {
.name = "ci13xxx_msm",
.flags = CI13XXX_REGS_SHARED |
CI13XXX_REQUIRE_TRANSCEIVER |
@@ -55,56 +55,45 @@ static struct ci13xxx_udc_driver ci13xxx_msm_udc_driver = {
.notify_event = ci13xxx_msm_notify_event,
};
-static int ci13xxx_msm_probe(struct platform_device *pdev)
+static int __devinit ci13xxx_msm_probe(struct platform_device *pdev)
{
struct platform_device *plat_ci;
- int ret;
dev_dbg(&pdev->dev, "ci13xxx_msm_probe\n");
- plat_ci = platform_device_alloc("ci_hdrc", -1);
- if (!plat_ci) {
- dev_err(&pdev->dev, "can't allocate ci_hdrc platform device\n");
- return -ENOMEM;
+ plat_ci = ci13xxx_add_device(&pdev->dev,
+ pdev->resource, pdev->num_resources,
+ &ci13xxx_msm_platdata);
+ if (IS_ERR(plat_ci)) {
+ dev_err(&pdev->dev, "ci13xxx_add_device failed!\n");
+ return PTR_ERR(plat_ci);
}
- ret = platform_device_add_resources(plat_ci, pdev->resource,
- pdev->num_resources);
- if (ret) {
- dev_err(&pdev->dev, "can't add resources to platform device\n");
- goto put_platform;
- }
-
- ret = platform_device_add_data(plat_ci, &ci13xxx_msm_udc_driver,
- sizeof(ci13xxx_msm_udc_driver));
- if (ret)
- goto put_platform;
-
- ret = platform_device_add(plat_ci);
- if (ret)
- goto put_platform;
+ platform_set_drvdata(pdev, plat_ci);
pm_runtime_no_callbacks(&pdev->dev);
pm_runtime_enable(&pdev->dev);
return 0;
+}
+
+static int __devexit ci13xxx_msm_remove(struct platform_device *pdev)
+{
+ struct platform_device *plat_ci = platform_get_drvdata(pdev);
-put_platform:
- platform_device_put(plat_ci);
+ pm_runtime_disable(&pdev->dev);
+ ci13xxx_remove_device(plat_ci);
- return ret;
+ return 0;
}
static struct platform_driver ci13xxx_msm_driver = {
.probe = ci13xxx_msm_probe,
+ .remove = __devexit_p(ci13xxx_msm_remove),
.driver = { .name = "msm_hsusb", },
};
-MODULE_ALIAS("platform:msm_hsusb");
-static int __init ci13xxx_msm_init(void)
-{
- return platform_driver_register(&ci13xxx_msm_driver);
-}
-module_init(ci13xxx_msm_init);
+module_platform_driver(ci13xxx_msm_driver);
+MODULE_ALIAS("platform:msm_hsusb");
MODULE_LICENSE("GPL v2");
diff --git a/drivers/usb/chipidea/ci13xxx_pci.c b/drivers/usb/chipidea/ci13xxx_pci.c
index e3dab27f5c7..918e14971f2 100644
--- a/drivers/usb/chipidea/ci13xxx_pci.c
+++ b/drivers/usb/chipidea/ci13xxx_pci.c
@@ -23,17 +23,17 @@
/******************************************************************************
* PCI block
*****************************************************************************/
-struct ci13xxx_udc_driver pci_driver = {
+struct ci13xxx_platform_data pci_platdata = {
.name = UDC_DRIVER_NAME,
.capoffset = DEF_CAPOFFSET,
};
-struct ci13xxx_udc_driver langwell_pci_driver = {
+struct ci13xxx_platform_data langwell_pci_platdata = {
.name = UDC_DRIVER_NAME,
.capoffset = 0,
};
-struct ci13xxx_udc_driver penwell_pci_driver = {
+struct ci13xxx_platform_data penwell_pci_platdata = {
.name = UDC_DRIVER_NAME,
.capoffset = 0,
.power_budget = 200,
@@ -51,12 +51,12 @@ struct ci13xxx_udc_driver penwell_pci_driver = {
static int __devinit ci13xxx_pci_probe(struct pci_dev *pdev,
const struct pci_device_id *id)
{
- struct ci13xxx_udc_driver *driver = (void *)id->driver_data;
+ struct ci13xxx_platform_data *platdata = (void *)id->driver_data;
struct platform_device *plat_ci;
struct resource res[3];
int retval = 0, nres = 2;
- if (!driver) {
+ if (!platdata) {
dev_err(&pdev->dev, "device doesn't provide driver data\n");
return -ENODEV;
}
@@ -75,13 +75,6 @@ static int __devinit ci13xxx_pci_probe(struct pci_dev *pdev,
pci_set_master(pdev);
pci_try_set_mwi(pdev);
- plat_ci = platform_device_alloc("ci_hdrc", -1);
- if (!plat_ci) {
- dev_err(&pdev->dev, "can't allocate ci_hdrc platform device\n");
- retval = -ENOMEM;
- goto disable_device;
- }
-
memset(res, 0, sizeof(res));
res[0].start = pci_resource_start(pdev, 0);
res[0].end = pci_resource_end(pdev, 0);
@@ -89,32 +82,17 @@ static int __devinit ci13xxx_pci_probe(struct pci_dev *pdev,
res[1].start = pdev->irq;
res[1].flags = IORESOURCE_IRQ;
- retval = platform_device_add_resources(plat_ci, res, nres);
- if (retval) {
- dev_err(&pdev->dev, "can't add resources to platform device\n");
- goto put_platform;
+ plat_ci = ci13xxx_add_device(&pdev->dev, res, nres, platdata);
+ if (IS_ERR(plat_ci)) {
+ dev_err(&pdev->dev, "ci13xxx_add_device failed!\n");
+ retval = PTR_ERR(plat_ci);
+ goto disable_device;
}
- retval = platform_device_add_data(plat_ci, driver, sizeof(*driver));
- if (retval)
- goto put_platform;
-
- dma_set_coherent_mask(&plat_ci->dev, pdev->dev.coherent_dma_mask);
- plat_ci->dev.dma_mask = pdev->dev.dma_mask;
- plat_ci->dev.dma_parms = pdev->dev.dma_parms;
- plat_ci->dev.parent = &pdev->dev;
-
pci_set_drvdata(pdev, plat_ci);
- retval = platform_device_add(plat_ci);
- if (retval)
- goto put_platform;
-
return 0;
- put_platform:
- pci_set_drvdata(pdev, NULL);
- platform_device_put(plat_ci);
disable_device:
pci_disable_device(pdev);
done:
@@ -133,7 +111,7 @@ static void __devexit ci13xxx_pci_remove(struct pci_dev *pdev)
{
struct platform_device *plat_ci = pci_get_drvdata(pdev);
- platform_device_unregister(plat_ci);
+ ci13xxx_remove_device(plat_ci);
pci_set_drvdata(pdev, NULL);
pci_disable_device(pdev);
}
@@ -147,19 +125,19 @@ static void __devexit ci13xxx_pci_remove(struct pci_dev *pdev)
static DEFINE_PCI_DEVICE_TABLE(ci13xxx_pci_id_table) = {
{
PCI_DEVICE(0x153F, 0x1004),
- .driver_data = (kernel_ulong_t)&pci_driver,
+ .driver_data = (kernel_ulong_t)&pci_platdata,
},
{
PCI_DEVICE(0x153F, 0x1006),
- .driver_data = (kernel_ulong_t)&pci_driver,
+ .driver_data = (kernel_ulong_t)&pci_platdata,
},
{
PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x0811),
- .driver_data = (kernel_ulong_t)&langwell_pci_driver,
+ .driver_data = (kernel_ulong_t)&langwell_pci_platdata,
},
{
PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x0829),
- .driver_data = (kernel_ulong_t)&penwell_pci_driver,
+ .driver_data = (kernel_ulong_t)&penwell_pci_platdata,
},
{ 0, 0, 0, 0, 0, 0, 0 /* end: all zeroes */ }
};
diff --git a/drivers/usb/chipidea/core.c b/drivers/usb/chipidea/core.c
index 15e03b308f8..1083585fad0 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;
diff --git a/drivers/usb/chipidea/debug.c b/drivers/usb/chipidea/debug.c
index c4b3e15532d..c6f50a25756 100644
--- a/drivers/usb/chipidea/debug.c
+++ b/drivers/usb/chipidea/debug.c
@@ -68,15 +68,15 @@ void dbg_interrupt(u32 intmask)
*
* This function returns number of registers read
*/
-static size_t hw_register_read(struct ci13xxx *udc, u32 *buf, size_t size)
+static size_t hw_register_read(struct ci13xxx *ci, u32 *buf, size_t size)
{
unsigned i;
- if (size > udc->hw_bank.size)
- size = udc->hw_bank.size;
+ if (size > ci->hw_bank.size)
+ size = ci->hw_bank.size;
for (i = 0; i < size; i++)
- buf[i] = hw_read(udc, i * sizeof(u32), ~0);
+ buf[i] = hw_read(ci, i * sizeof(u32), ~0);
return size;
}
@@ -88,18 +88,18 @@ static size_t hw_register_read(struct ci13xxx *udc, u32 *buf, size_t size)
*
* This function returns an error code
*/
-static int hw_register_write(struct ci13xxx *udc, u16 addr, u32 data)
+static int hw_register_write(struct ci13xxx *ci, u16 addr, u32 data)
{
/* align */
addr /= sizeof(u32);
- if (addr >= udc->hw_bank.size)
+ if (addr >= ci->hw_bank.size)
return -EINVAL;
/* align */
addr *= sizeof(u32);
- hw_write(udc, addr, ~0, data);
+ hw_write(ci, addr, ~0, data);
return 0;
}
@@ -110,13 +110,13 @@ static int hw_register_write(struct ci13xxx *udc, u16 addr, u32 data)
*
* This function returns an error code
*/
-static int hw_intr_clear(struct ci13xxx *udc, int n)
+static int hw_intr_clear(struct ci13xxx *ci, int n)
{
if (n >= REG_BITS)
return -EINVAL;
- hw_write(udc, OP_USBINTR, BIT(n), 0);
- hw_write(udc, OP_USBSTS, BIT(n), BIT(n));
+ hw_write(ci, OP_USBINTR, BIT(n), 0);
+ hw_write(ci, OP_USBSTS, BIT(n), BIT(n));
return 0;
}
@@ -127,15 +127,15 @@ static int hw_intr_clear(struct ci13xxx *udc, int n)
*
* This function returns an error code
*/
-static int hw_intr_force(struct ci13xxx *udc, int n)
+static int hw_intr_force(struct ci13xxx *ci, int n)
{
if (n >= REG_BITS)
return -EINVAL;
- hw_write(udc, CAP_TESTMODE, TESTMODE_FORCE, TESTMODE_FORCE);
- hw_write(udc, OP_USBINTR, BIT(n), BIT(n));
- hw_write(udc, OP_USBSTS, BIT(n), BIT(n));
- hw_write(udc, CAP_TESTMODE, TESTMODE_FORCE, 0);
+ hw_write(ci, CAP_TESTMODE, TESTMODE_FORCE, TESTMODE_FORCE);
+ hw_write(ci, OP_USBINTR, BIT(n), BIT(n));
+ hw_write(ci, OP_USBSTS, BIT(n), BIT(n));
+ hw_write(ci, CAP_TESTMODE, TESTMODE_FORCE, 0);
return 0;
}
@@ -147,12 +147,12 @@ static int hw_intr_force(struct ci13xxx *udc, int n)
static ssize_t show_device(struct device *dev, struct device_attribute *attr,
char *buf)
{
- struct ci13xxx *udc = container_of(dev, struct ci13xxx, gadget.dev);
- struct usb_gadget *gadget = &udc->gadget;
+ struct ci13xxx *ci = container_of(dev, struct ci13xxx, gadget.dev);
+ struct usb_gadget *gadget = &ci->gadget;
int n = 0;
if (attr == NULL || buf == NULL) {
- dev_err(udc->dev, "[%s] EINVAL\n", __func__);
+ dev_err(ci->dev, "[%s] EINVAL\n", __func__);
return 0;
}
@@ -188,8 +188,8 @@ static DEVICE_ATTR(device, S_IRUSR, show_device, NULL);
static ssize_t show_driver(struct device *dev, struct device_attribute *attr,
char *buf)
{
- struct ci13xxx *udc = container_of(dev, struct ci13xxx, gadget.dev);
- struct usb_gadget_driver *driver = udc->driver;
+ struct ci13xxx *ci = container_of(dev, struct ci13xxx, gadget.dev);
+ struct usb_gadget_driver *driver = ci->driver;
int n = 0;
if (attr == NULL || buf == NULL) {
@@ -412,22 +412,22 @@ static DEVICE_ATTR(events, S_IRUSR | S_IWUSR, show_events, store_events);
static ssize_t show_inters(struct device *dev, struct device_attribute *attr,
char *buf)
{
- struct ci13xxx *udc = container_of(dev, struct ci13xxx, gadget.dev);
+ struct ci13xxx *ci = container_of(dev, struct ci13xxx, gadget.dev);
unsigned long flags;
u32 intr;
unsigned i, j, n = 0;
if (attr == NULL || buf == NULL) {
- dev_err(udc->dev, "[%s] EINVAL\n", __func__);
+ dev_err(ci->dev, "[%s] EINVAL\n", __func__);
return 0;
}
- spin_lock_irqsave(&udc->lock, flags);
+ spin_lock_irqsave(&ci->lock, flags);
/*n += scnprintf(buf + n, PAGE_SIZE - n,
- "status = %08x\n", hw_read_intr_status(udc));
+ "status = %08x\n", hw_read_intr_status(ci));
n += scnprintf(buf + n, PAGE_SIZE - n,
- "enable = %08x\n", hw_read_intr_enable(udc));*/
+ "enable = %08x\n", hw_read_intr_enable(ci));*/
n += scnprintf(buf + n, PAGE_SIZE - n, "*test = %d\n",
isr_statistics.test);
@@ -471,7 +471,7 @@ static ssize_t show_inters(struct device *dev, struct device_attribute *attr,
n += scnprintf(buf + n, PAGE_SIZE - n, "\n");
}
- spin_unlock_irqrestore(&udc->lock, flags);
+ spin_unlock_irqrestore(&ci->lock, flags);
return n;
}
@@ -485,31 +485,31 @@ static ssize_t show_inters(struct device *dev, struct device_attribute *attr,
static ssize_t store_inters(struct device *dev, struct device_attribute *attr,
const char *buf, size_t count)
{
- struct ci13xxx *udc = container_of(dev, struct ci13xxx, gadget.dev);
+ struct ci13xxx *ci = container_of(dev, struct ci13xxx, gadget.dev);
unsigned long flags;
unsigned en, bit;
if (attr == NULL || buf == NULL) {
- dev_err(udc->dev, "EINVAL\n");
+ dev_err(ci->dev, "EINVAL\n");
goto done;
}
if (sscanf(buf, "%u %u", &en, &bit) != 2 || en > 1) {
- dev_err(udc->dev, "<1|0> <bit>: enable|disable interrupt\n");
+ dev_err(ci->dev, "<1|0> <bit>: enable|disable interrupt\n");
goto done;
}
- spin_lock_irqsave(&udc->lock, flags);
+ spin_lock_irqsave(&ci->lock, flags);
if (en) {
- if (hw_intr_force(udc, bit))
+ if (hw_intr_force(ci, bit))
dev_err(dev, "invalid bit number\n");
else
isr_statistics.test++;
} else {
- if (hw_intr_clear(udc, bit))
+ if (hw_intr_clear(ci, bit))
dev_err(dev, "invalid bit number\n");
}
- spin_unlock_irqrestore(&udc->lock, flags);
+ spin_unlock_irqrestore(&ci->lock, flags);
done:
return count;
@@ -524,18 +524,18 @@ static DEVICE_ATTR(inters, S_IRUSR | S_IWUSR, show_inters, store_inters);
static ssize_t show_port_test(struct device *dev,
struct device_attribute *attr, char *buf)
{
- struct ci13xxx *udc = container_of(dev, struct ci13xxx, gadget.dev);
+ struct ci13xxx *ci = container_of(dev, struct ci13xxx, gadget.dev);
unsigned long flags;
unsigned mode;
if (attr == NULL || buf == NULL) {
- dev_err(udc->dev, "EINVAL\n");
+ dev_err(ci->dev, "EINVAL\n");
return 0;
}
- spin_lock_irqsave(&udc->lock, flags);
- mode = hw_port_test_get(udc);
- spin_unlock_irqrestore(&udc->lock, flags);
+ spin_lock_irqsave(&ci->lock, flags);
+ mode = hw_port_test_get(ci);
+ spin_unlock_irqrestore(&ci->lock, flags);
return scnprintf(buf, PAGE_SIZE, "mode = %u\n", mode);
}
@@ -549,24 +549,24 @@ static ssize_t store_port_test(struct device *dev,
struct device_attribute *attr,
const char *buf, size_t count)
{
- struct ci13xxx *udc = container_of(dev, struct ci13xxx, gadget.dev);
+ struct ci13xxx *ci = container_of(dev, struct ci13xxx, gadget.dev);
unsigned long flags;
unsigned mode;
if (attr == NULL || buf == NULL) {
- dev_err(udc->dev, "[%s] EINVAL\n", __func__);
+ dev_err(ci->dev, "[%s] EINVAL\n", __func__);
goto done;
}
if (sscanf(buf, "%u", &mode) != 1) {
- dev_err(udc->dev, "<mode>: set port test mode");
+ dev_err(ci->dev, "<mode>: set port test mode");
goto done;
}
- spin_lock_irqsave(&udc->lock, flags);
- if (hw_port_test_set(udc, mode))
- dev_err(udc->dev, "invalid mode\n");
- spin_unlock_irqrestore(&udc->lock, flags);
+ spin_lock_irqsave(&ci->lock, flags);
+ if (hw_port_test_set(ci, mode))
+ dev_err(ci->dev, "invalid mode\n");
+ spin_unlock_irqrestore(&ci->lock, flags);
done:
return count;
@@ -582,20 +582,20 @@ static DEVICE_ATTR(port_test, S_IRUSR | S_IWUSR,
static ssize_t show_qheads(struct device *dev, struct device_attribute *attr,
char *buf)
{
- struct ci13xxx *udc = container_of(dev, struct ci13xxx, gadget.dev);
+ struct ci13xxx *ci = container_of(dev, struct ci13xxx, gadget.dev);
unsigned long flags;
unsigned i, j, n = 0;
if (attr == NULL || buf == NULL) {
- dev_err(udc->dev, "[%s] EINVAL\n", __func__);
+ dev_err(ci->dev, "[%s] EINVAL\n", __func__);
return 0;
}
- spin_lock_irqsave(&udc->lock, flags);
- for (i = 0; i < udc->hw_ep_max/2; i++) {
- struct ci13xxx_ep *mEpRx = &udc->ci13xxx_ep[i];
+ spin_lock_irqsave(&ci->lock, flags);
+ for (i = 0; i < ci->hw_ep_max/2; i++) {
+ struct ci13xxx_ep *mEpRx = &ci->ci13xxx_ep[i];
struct ci13xxx_ep *mEpTx =
- &udc->ci13xxx_ep[i + udc->hw_ep_max/2];
+ &ci->ci13xxx_ep[i + ci->hw_ep_max/2];
n += scnprintf(buf + n, PAGE_SIZE - n,
"EP=%02i: RX=%08X TX=%08X\n",
i, (u32)mEpRx->qh.dma, (u32)mEpTx->qh.dma);
@@ -606,7 +606,7 @@ static ssize_t show_qheads(struct device *dev, struct device_attribute *attr,
*((u32 *)mEpTx->qh.ptr + j));
}
}
- spin_unlock_irqrestore(&udc->lock, flags);
+ spin_unlock_irqrestore(&ci->lock, flags);
return n;
}
@@ -621,25 +621,25 @@ static DEVICE_ATTR(qheads, S_IRUSR, show_qheads, NULL);
static ssize_t show_registers(struct device *dev,
struct device_attribute *attr, char *buf)
{
- struct ci13xxx *udc = container_of(dev, struct ci13xxx, gadget.dev);
+ struct ci13xxx *ci = container_of(dev, struct ci13xxx, gadget.dev);
unsigned long flags;
u32 *dump;
unsigned i, k, n = 0;
if (attr == NULL || buf == NULL) {
- dev_err(udc->dev, "[%s] EINVAL\n", __func__);
+ dev_err(ci->dev, "[%s] EINVAL\n", __func__);
return 0;
}
dump = kmalloc(sizeof(u32) * DUMP_ENTRIES, GFP_KERNEL);
if (!dump) {
- dev_err(udc->dev, "%s: out of memory\n", __func__);
+ dev_err(ci->dev, "%s: out of memory\n", __func__);
return 0;
}
- spin_lock_irqsave(&udc->lock, flags);
- k = hw_register_read(udc, dump, DUMP_ENTRIES);
- spin_unlock_irqrestore(&udc->lock, flags);
+ spin_lock_irqsave(&ci->lock, flags);
+ k = hw_register_read(ci, dump, DUMP_ENTRIES);
+ spin_unlock_irqrestore(&ci->lock, flags);
for (i = 0; i < k; i++) {
n += scnprintf(buf + n, PAGE_SIZE - n,
@@ -660,24 +660,24 @@ static ssize_t store_registers(struct device *dev,
struct device_attribute *attr,
const char *buf, size_t count)
{
- struct ci13xxx *udc = container_of(dev, struct ci13xxx, gadget.dev);
+ struct ci13xxx *ci = container_of(dev, struct ci13xxx, gadget.dev);
unsigned long addr, data, flags;
if (attr == NULL || buf == NULL) {
- dev_err(udc->dev, "[%s] EINVAL\n", __func__);
+ dev_err(ci->dev, "[%s] EINVAL\n", __func__);
goto done;
}
if (sscanf(