summaryrefslogtreecommitdiffstats
path: root/drivers
diff options
context:
space:
mode:
authorSascha Hauer <s.hauer@pengutronix.de>2013-03-04 09:21:54 +0100
committerSascha Hauer <s.hauer@pengutronix.de>2013-03-04 09:21:54 +0100
commit678832e17a401819349bbea0425de44c7cdd288c (patch)
treea9711e29f0567aba0fe0e848649128452121e40a /drivers
parentea0f831cd0c749194a0103ec4814fe91c3955084 (diff)
parent0a643b3d426e606dd42678b87a1fe205aea2b9e7 (diff)
downloadbarebox-678832e17a401819349bbea0425de44c7cdd288c.tar.gz
barebox-678832e17a401819349bbea0425de44c7cdd288c.tar.xz
Merge branch 'for-next/usb'
Diffstat (limited to 'drivers')
-rw-r--r--drivers/usb/gadget/fsl_udc.c11
-rw-r--r--drivers/usb/host/ehci-hcd.c14
-rw-r--r--drivers/usb/imx/chipidea-imx.c56
-rw-r--r--drivers/usb/imx/imx-usb-misc.c123
4 files changed, 177 insertions, 27 deletions
diff --git a/drivers/usb/gadget/fsl_udc.c b/drivers/usb/gadget/fsl_udc.c
index 855dd931c2..81715f9e9a 100644
--- a/drivers/usb/gadget/fsl_udc.c
+++ b/drivers/usb/gadget/fsl_udc.c
@@ -2257,7 +2257,7 @@ static struct poller_struct poller = {
.func = fsl_udc_poller
};
-static int fsl_udc_probe(struct device_d *dev)
+int ci_udc_register(struct device_d *dev, void __iomem *regs)
{
int ret, i;
u32 dccparams;
@@ -2265,7 +2265,7 @@ static int fsl_udc_probe(struct device_d *dev)
udc_controller = xzalloc(sizeof(*udc_controller));
udc_controller->stopped = 1;
- dr_regs = dev_request_mem_region(dev, 0);
+ dr_regs = regs;
/* Read Device Controller Capability Parameters register */
dccparams = readl(&dr_regs->dccparams);
@@ -2326,6 +2326,13 @@ err_out:
return ret;
}
+static int fsl_udc_probe(struct device_d *dev)
+{
+ void __iomem *regs = dev_request_mem_region(dev, 0);
+
+ return ci_udc_register(dev, regs);
+}
+
static struct driver_d fsl_udc_driver = {
.name = "fsl-udc",
.probe = fsl_udc_probe,
diff --git a/drivers/usb/host/ehci-hcd.c b/drivers/usb/host/ehci-hcd.c
index d83e01cc83..0c789e479f 100644
--- a/drivers/usb/host/ehci-hcd.c
+++ b/drivers/usb/host/ehci-hcd.c
@@ -42,6 +42,10 @@ struct ehci_priv {
struct qTD *td;
int portreset;
unsigned long flags;
+
+ int (*init)(void *drvdata);
+ int (*post_init)(void *drvdata);
+ void *drvdata;
};
#define to_ehci(ptr) container_of(ptr, struct ehci_priv, host)
@@ -748,6 +752,9 @@ static int ehci_init(struct usb_host *host)
if (ehci_reset(ehci) != 0)
return -1;
+ if (ehci->init)
+ ehci->init(ehci->drvdata);
+
ehci->qh_list->qh_link = cpu_to_hc32((uint32_t)ehci->qh_list | QH_LINK_TYPE_QH);
ehci->qh_list->qh_endpt1 = cpu_to_hc32((1 << 15) | (USB_SPEED_HIGH << 12));
ehci->qh_list->qh_curtd = cpu_to_hc32(QT_NEXT_TERMINATE);
@@ -788,6 +795,9 @@ static int ehci_init(struct usb_host *host)
ehci->rootdev = 0;
+ if (ehci->post_init)
+ ehci->post_init(ehci->drvdata);
+
return 0;
}
@@ -856,6 +866,10 @@ int ehci_register(struct device_d *dev, struct ehci_data *data)
ehci->hcor = (void __iomem *)ehci->hccr +
HC_LENGTH(ehci_readl(&ehci->hccr->cr_capbase));
+ ehci->drvdata = data->drvdata;
+ ehci->init = data->init;
+ ehci->post_init = data->post_init;
+
ehci->qh_list = dma_alloc_coherent(sizeof(struct QH) * NUM_TD);
ehci->td = dma_alloc_coherent(sizeof(struct qTD) * NUM_TD);
diff --git a/drivers/usb/imx/chipidea-imx.c b/drivers/usb/imx/chipidea-imx.c
index 495ad6246e..483484e117 100644
--- a/drivers/usb/imx/chipidea-imx.c
+++ b/drivers/usb/imx/chipidea-imx.c
@@ -19,15 +19,45 @@
#include <usb/ehci.h>
#include <usb/chipidea-imx.h>
#include <usb/ulpi.h>
+#include <usb/fsl_usb2.h>
-#define MXC_EHCI_PORTSC_MASK (0xf << 28)
+#define MXC_EHCI_PORTSC_MASK ((0xf << 28) | (1 << 25))
+
+static int imx_chipidea_port_init(void *drvdata)
+{
+ struct device_d *dev = drvdata;
+ struct imxusb_platformdata *pdata = dev->platform_data;
+ int ret;
+
+ ret = imx_usbmisc_port_init(dev->id, pdata->flags);
+ if (ret)
+ dev_err(dev, "misc init failed: %s\n", strerror(-ret));
+
+ if (pdata->init)
+ pdata->init(dev->id);
+
+ return ret;
+}
+
+static int imx_chipidea_port_post_init(void *drvdata)
+{
+ struct device_d *dev = drvdata;
+ struct imxusb_platformdata *pdata = dev->platform_data;
+ int ret;
+
+ ret = imx_usbmisc_port_post_init(dev->id, pdata->flags);
+ if (ret)
+ dev_err(dev, "post misc init failed: %s\n", strerror(-ret));
+
+ return ret;
+}
static int imx_chipidea_probe(struct device_d *dev)
{
struct imxusb_platformdata *pdata = dev->platform_data;
int ret;
void __iomem *base;
- struct ehci_data data;
+ struct ehci_data data = {};
uint32_t portsc;
if (!pdata) {
@@ -39,17 +69,17 @@ static int imx_chipidea_probe(struct device_d *dev)
if (!base)
return -ENODEV;
+ data.init = imx_chipidea_port_init;
+ data.post_init = imx_chipidea_port_post_init;
+ data.drvdata = dev;
+
+ imx_chipidea_port_init(dev);
+
portsc = readl(base + 0x184);
portsc &= ~MXC_EHCI_PORTSC_MASK;
portsc |= pdata->flags & MXC_EHCI_PORTSC_MASK;
writel(portsc, base + 0x184);
- ret = imx_usbmisc_port_init(dev->id, pdata->flags);
- if (ret) {
- dev_err(dev, "failed to init misc regs: %s\n", strerror(-ret));
- return ret;
- }
-
if ((pdata->flags & MXC_EHCI_PORTSC_MASK) == MXC_EHCI_MODE_ULPI) {
dev_dbg(dev, "using ULPI phy\n");
if (IS_ENABLED(CONFIG_USB_ULPI)) {
@@ -67,13 +97,13 @@ static int imx_chipidea_probe(struct device_d *dev)
data.hcor = base + 0x140;
data.flags = EHCI_HAS_TT;
- if (pdata->mode == IMX_USB_MODE_HOST) {
+ if (pdata->mode == IMX_USB_MODE_HOST && IS_ENABLED(CONFIG_USB_EHCI)) {
ret = ehci_register(dev, &data);
+ } else if (pdata->mode == IMX_USB_MODE_DEVICE && IS_ENABLED(CONFIG_USB_GADGET_DRIVER_ARC)) {
+ ret = ci_udc_register(dev, base);
} else {
- /*
- * Not yet implemented. Register USB gadget driver here.
- */
- ret = -ENOSYS;
+ dev_err(dev, "No supported role\n");
+ ret = -ENODEV;
}
return ret;
diff --git a/drivers/usb/imx/imx-usb-misc.c b/drivers/usb/imx/imx-usb-misc.c
index 4cdf5ab3af..901ced485d 100644
--- a/drivers/usb/imx/imx-usb-misc.c
+++ b/drivers/usb/imx/imx-usb-misc.c
@@ -17,6 +17,8 @@
#include <init.h>
#include <io.h>
#include <usb/chipidea-imx.h>
+#include <mach/imx6-regs.h>
+#include <mach/iomux-mx6.h>
#define MX25_OTG_SIC_SHIFT 29
#define MX25_OTG_SIC_MASK (0x3 << MX25_OTG_SIC_SHIFT)
@@ -34,6 +36,11 @@
#define MX25_H1_USBTE_BIT (1 << 4)
#define MX25_H1_OCPOL_BIT (1 << 2)
+struct imx_usb_misc_data {
+ int (*init)(void __iomem *base, int port, unsigned int flags);
+ int (*post_init)(void __iomem *base, int port, unsigned int flags);
+};
+
static __maybe_unused int mx25_initialize_usb_hw(void __iomem *base, int port, unsigned int flags)
{
unsigned int v;
@@ -93,6 +100,10 @@ static __maybe_unused int mx25_initialize_usb_hw(void __iomem *base, int port, u
return 0;
}
+static __maybe_unused struct imx_usb_misc_data mx25_data = {
+ .init = mx25_initialize_usb_hw,
+};
+
#define MX27_OTG_SIC_SHIFT 29
#define MX27_OTG_SIC_MASK (0x3 << MX27_OTG_SIC_SHIFT)
#define MX27_OTG_PM_BIT (1 << 24)
@@ -152,6 +163,10 @@ static __maybe_unused int mx27_mx31_initialize_usb_hw(void __iomem *base, int po
return 0;
}
+static __maybe_unused struct imx_usb_misc_data mx27_mx31_data = {
+ .init = mx27_mx31_initialize_usb_hw,
+};
+
#define USBCTRL_OTGBASE_OFFSET 0x600
#define MX35_OTG_SIC_SHIFT 29
@@ -229,6 +244,10 @@ static __maybe_unused int mx35_initialize_usb_hw(void __iomem *base, int port, u
return 0;
}
+static __maybe_unused struct imx_usb_misc_data mx35_data = {
+ .init = mx35_initialize_usb_hw,
+};
+
/* USB_CTRL */
#define MX5_OTG_UCTRL_OWIE_BIT (1 << 27) /* OTG wakeup intr enable */
#define MX5_OTG_UCTRL_OPM_BIT (1 << 24) /* OTG power mask */
@@ -324,53 +343,119 @@ static __maybe_unused int mx5_initialize_usb_hw(void __iomem *base, int port,
return 0;
}
+static __maybe_unused struct imx_usb_misc_data mx5_data = {
+ .init = mx5_initialize_usb_hw,
+};
+
+static void mx6_hsic_pullup(unsigned long reg, int on)
+{
+ u32 val;
+
+ val = readl(MX6_IOMUXC_BASE_ADDR + reg);
+
+ if (on)
+ val |= MX6_PAD_CTL_PUS_47K_UP;
+ else
+ val &= ~MX6_PAD_CTL_PUS_47K_UP;
+
+ writel(val, MX6_IOMUXC_BASE_ADDR + reg);
+}
+
static __maybe_unused int mx6_initialize_usb_hw(void __iomem *base, int port,
unsigned int flags)
{
+ switch (port) {
+ case 0:
+ break;
+ case 1:
+ break;
+ case 2: /* HSIC port */
+ mx6_hsic_pullup(0x388, 0);
+
+ writel(0x00003000, base + 0x8);
+ writel(0x80001842, base + 0x10);
+
+ break;
+ case 3: /* HSIC port */
+ writel(0x00003000, base + 0xc);
+ writel(0x80001842, base + 0x14);
+
+ mx6_hsic_pullup(0x398, 0);
+ break;
+ default:
+ return -EINVAL;
+ }
+
return 0;
}
+static __maybe_unused int mx6_post_init(void __iomem *base, int port,
+ unsigned int flags)
+{
+ switch (port) {
+ case 0:
+ break;
+ case 1:
+ break;
+ case 2: /* HSIC port */
+ mx6_hsic_pullup(0x388, 1);
+ break;
+ case 3: /* HSIC port */
+ mx6_hsic_pullup(0x398, 1);
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
+static __maybe_unused struct imx_usb_misc_data mx6_data = {
+ .init = mx6_initialize_usb_hw,
+ .post_init = mx6_post_init,
+};
+
static struct platform_device_id imx_usbmisc_ids[] = {
#ifdef CONFIG_ARCH_IMX25
{
.name = "imx25-usb-misc",
- .driver_data = (unsigned long)&mx25_initialize_usb_hw,
+ .driver_data = (unsigned long)&mx25_data,
},
#endif
#ifdef CONFIG_ARCH_IMX27
{
.name = "imx27-usb-misc",
- .driver_data = (unsigned long)&mx27_mx31_initialize_usb_hw,
+ .driver_data = (unsigned long)&mx27_mx31_data,
},
#endif
#ifdef CONFIG_ARCH_IMX31
{
.name = "imx31-usb-misc",
- .driver_data = (unsigned long)&mx27_mx31_initialize_usb_hw,
+ .driver_data = (unsigned long)&mx27_mx31_data,
},
#endif
#ifdef CONFIG_ARCH_IMX35
{
.name = "imx35-usb-misc",
- .driver_data = (unsigned long)&mx35_initialize_usb_hw,
+ .driver_data = (unsigned long)&mx35_data,
},
#endif
#ifdef CONFIG_ARCH_IMX51
{
.name = "imx51-usb-misc",
- .driver_data = (unsigned long)&mx5_initialize_usb_hw,
+ .driver_data = (unsigned long)&mx5_data,
},
#endif
#ifdef CONFIG_ARCH_IMX53
{
.name = "imx53-usb-misc",
- .driver_data = (unsigned long)&mx5_initialize_usb_hw,
+ .driver_data = (unsigned long)&mx5_data,
},
#endif
#ifdef CONFIG_ARCH_IMX6
{
.name = "imx6-usb-misc",
- .driver_data = (unsigned long)&mx6_initialize_usb_hw,
+ .driver_data = (unsigned long)&mx6_data,
},
#endif
{
@@ -378,20 +463,34 @@ static struct platform_device_id imx_usbmisc_ids[] = {
},
};
-static int (*__imx_usbmisc_port_init)(void __iomem *base, int port, unsigned flags);
+static struct imx_usb_misc_data *imxusbmisc_data;
static void __iomem *usbmisc_base;
int imx_usbmisc_port_init(int port, unsigned flags)
{
- if (!__imx_usbmisc_port_init)
+ if (!imxusbmisc_data)
+ return -ENODEV;
+
+ if (!imxusbmisc_data->init)
+ return 0;
+
+ return imxusbmisc_data->init(usbmisc_base, port, flags);
+}
+
+int imx_usbmisc_port_post_init(int port, unsigned flags)
+{
+ if (!imxusbmisc_data)
return -ENODEV;
- return __imx_usbmisc_port_init(usbmisc_base, port, flags);
+ if (!imxusbmisc_data->post_init)
+ return 0;
+
+ return imxusbmisc_data->post_init(usbmisc_base, port, flags);
}
static int imx_usbmisc_probe(struct device_d *dev)
{
- struct imx_serial_devtype_data *devtype;
+ struct imx_usb_misc_data *devtype;
int ret;
ret = dev_get_drvdata(dev, (unsigned long *)&devtype);
@@ -402,7 +501,7 @@ static int imx_usbmisc_probe(struct device_d *dev)
if (!usbmisc_base)
return -ENOMEM;
- __imx_usbmisc_port_init = (void *)devtype;
+ imxusbmisc_data = devtype;
return 0;
}