From 1943567163a6c0b34c5f3dc514b9e914d7ec3c49 Mon Sep 17 00:00:00 2001 From: Sascha Hauer Date: Wed, 23 Jan 2013 10:48:25 +0100 Subject: [PATCH 1/6] ARM i.MX6: Fix HSIC pad definitions Signed-off-by: Sascha Hauer --- arch/arm/mach-imx/include/mach/iomux-mx6.h | 19 +++++++++++-------- 1 file changed, 11 insertions(+), 8 deletions(-) diff --git a/arch/arm/mach-imx/include/mach/iomux-mx6.h b/arch/arm/mach-imx/include/mach/iomux-mx6.h index f50fd8af1..57d1a3bf9 100644 --- a/arch/arm/mach-imx/include/mach/iomux-mx6.h +++ b/arch/arm/mach-imx/include/mach/iomux-mx6.h @@ -83,6 +83,9 @@ MX6_PAD_CTL_DSE_40ohm | MX6_PAD_CTL_HYS | \ MX6_PAD_CTL_ODE | MX6_PAD_CTL_SRE_FAST) +#define MX6Q_USB_HSIC_PAD_CTRL (MX6_PAD_CTL_HYS | MX6_PAD_CTL_PKE | MX6_PAD_CTL_PUE | \ + MX6_PAD_CTL_DSE_40ohm) + #define MX6Q_HIGH_DRV (MX6_PAD_CTL_DSE_120ohm) #define _MX6Q_PAD_SD2_DAT1__USDHC2_DAT1 \ @@ -135,7 +138,7 @@ IOMUX_PAD(0x0368, 0x0054, 7, 0x0000, 0, 0) #define _MX6Q_PAD_RGMII_TXC__USBOH3_H2_DATA \ - IOMUX_PAD(0x036C, 0x0058, 0, 0x0000, 0, 0) + IOMUX_PAD(0x036C, 0x0058, IOMUX_CONFIG_SION, 0x0000, 0, 0) #define _MX6Q_PAD_RGMII_TXC__ENET_RGMII_TXC \ IOMUX_PAD(0x036C, 0x0058, 1, 0x0000, 0, 0) #define _MX6Q_PAD_RGMII_TXC__SPDIF_SPDIF_EXTCLK \ @@ -188,7 +191,7 @@ IOMUX_PAD(0x037C, 0x0068, 6, 0x0000, 0, 0) #define _MX6Q_PAD_RGMII_RX_CTL__USBOH3_H3_DATA \ - IOMUX_PAD(0x0380, 0x006C, 0, 0x0000, 0, 0) + IOMUX_PAD(0x0380, 0x006C, IOMUX_CONFIG_SION, 0x0000, 0, 0) #define _MX6Q_PAD_RGMII_RX_CTL__ENET_RGMII_RX_CTL \ IOMUX_PAD(0x0380, 0x006C, 1, 0x0858, 0, 0) #define _MX6Q_PAD_RGMII_RX_CTL__GPIO_6_24 \ @@ -206,7 +209,7 @@ IOMUX_PAD(0x0384, 0x0070, 6, 0x0000, 0, 0) #define _MX6Q_PAD_RGMII_TX_CTL__USBOH3_H2_STROBE \ - IOMUX_PAD(0x0388, 0x0074, 0, 0x0000, 0, 0) + IOMUX_PAD(0x0388, 0x0074, IOMUX_CONFIG_SION, 0x0000, 0, 0) #define _MX6Q_PAD_RGMII_TX_CTL__ENET_RGMII_TX_CTL \ IOMUX_PAD(0x0388, 0x0074, 1, 0x0000, 0, 0) #define _MX6Q_PAD_RGMII_TX_CTL__GPIO_6_26 \ @@ -246,7 +249,7 @@ IOMUX_PAD(0x0394, 0x0080, 6, 0x0000, 0, 0) #define _MX6Q_PAD_RGMII_RXC__USBOH3_H3_STROBE \ - IOMUX_PAD(0x0398, 0x0084, 0, 0x0000, 0, 0) + IOMUX_PAD(0x0398, 0x0084, IOMUX_CONFIG_SION, 0x0000, 0, 0) #define _MX6Q_PAD_RGMII_RXC__ENET_RGMII_RXC \ IOMUX_PAD(0x0398, 0x0084, 1, 0x0844, 0, 0) #define _MX6Q_PAD_RGMII_RXC__GPIO_6_30 \ @@ -3695,7 +3698,7 @@ #define MX6Q_PAD_SD2_DAT0__DCIC2_DCIC_OUT (_MX6Q_PAD_SD2_DAT0__DCIC2_DCIC_OUT | MUX_PAD_CTRL(NO_PAD_CTRL)) #define MX6Q_PAD_SD2_DAT0__ANATOP_ANATOP_TESTO_2 (_MX6Q_PAD_SD2_DAT0__ANATOP_ANATOP_TESTO_2 | MUX_PAD_CTRL(NO_PAD_CTRL)) -#define MX6Q_PAD_RGMII_TXC__USBOH3_H2_DATA (_MX6Q_PAD_RGMII_TXC__USBOH3_H2_DATA | MUX_PAD_CTRL(NO_PAD_CTRL)) +#define MX6Q_PAD_RGMII_TXC__USBOH3_H2_DATA (_MX6Q_PAD_RGMII_TXC__USBOH3_H2_DATA | MUX_PAD_CTRL(MX6Q_USB_HSIC_PAD_CTRL)) #define MX6Q_PAD_RGMII_TXC__ENET_RGMII_TXC (_MX6Q_PAD_RGMII_TXC__ENET_RGMII_TXC | MUX_PAD_CTRL(MX6Q_ENET_PAD_CTRL)) #define MX6Q_PAD_RGMII_TXC__SPDIF_SPDIF_EXTCLK (_MX6Q_PAD_RGMII_TXC__SPDIF_SPDIF_EXTCLK | MUX_PAD_CTRL(NO_PAD_CTRL)) #define MX6Q_PAD_RGMII_TXC__GPIO_6_19 (_MX6Q_PAD_RGMII_TXC__GPIO_6_19 | MUX_PAD_CTRL(NO_PAD_CTRL)) @@ -3724,7 +3727,7 @@ #define MX6Q_PAD_RGMII_TD3__GPIO_6_23 (_MX6Q_PAD_RGMII_TD3__GPIO_6_23 | MUX_PAD_CTRL(NO_PAD_CTRL)) #define MX6Q_PAD_RGMII_TD3__MIPI_CORE_DPHY_TEST_IN_4 (_MX6Q_PAD_RGMII_TD3__MIPI_CORE_DPHY_TEST_IN_4 | MUX_PAD_CTRL(NO_PAD_CTRL)) -#define MX6Q_PAD_RGMII_RX_CTL__USBOH3_H3_DATA (_MX6Q_PAD_RGMII_RX_CTL__USBOH3_H3_DATA | MUX_PAD_CTRL(NO_PAD_CTRL)) +#define MX6Q_PAD_RGMII_RX_CTL__USBOH3_H3_DATA (_MX6Q_PAD_RGMII_RX_CTL__USBOH3_H3_DATA | MUX_PAD_CTRL(MX6Q_USB_HSIC_PAD_CTRL)) #define MX6Q_PAD_RGMII_RX_CTL__ENET_RGMII_RX_CTL (_MX6Q_PAD_RGMII_RX_CTL__ENET_RGMII_RX_CTL | MUX_PAD_CTRL(MX6Q_ENET_PAD_CTRL)) #define MX6Q_PAD_RGMII_RX_CTL__GPIO_6_24 (_MX6Q_PAD_RGMII_RX_CTL__GPIO_6_24 | MUX_PAD_CTRL(NO_PAD_CTRL)) #define MX6Q_PAD_RGMII_RX_CTL__MIPI_CORE_DPHY_TEST_IN_5 (_MX6Q_PAD_RGMII_RX_CTL__MIPI_CORE_DPHY_TEST_IN_5 | MUX_PAD_CTRL(NO_PAD_CTRL)) @@ -3734,7 +3737,7 @@ #define MX6Q_PAD_RGMII_RD0__GPIO_6_25 (_MX6Q_PAD_RGMII_RD0__GPIO_6_25 | MUX_PAD_CTRL(NO_PAD_CTRL)) #define MX6Q_PAD_RGMII_RD0__MIPI_CORE_DPHY_TEST_IN_6 (_MX6Q_PAD_RGMII_RD0__MIPI_CORE_DPHY_TEST_IN_6 | MUX_PAD_CTRL(NO_PAD_CTRL)) -#define MX6Q_PAD_RGMII_TX_CTL__USBOH3_H2_STROBE (_MX6Q_PAD_RGMII_TX_CTL__USBOH3_H2_STROBE | MUX_PAD_CTRL(NO_PAD_CTRL)) +#define MX6Q_PAD_RGMII_TX_CTL__USBOH3_H2_STROBE (_MX6Q_PAD_RGMII_TX_CTL__USBOH3_H2_STROBE | MUX_PAD_CTRL(MX6Q_USB_HSIC_PAD_CTRL)) #define MX6Q_PAD_RGMII_TX_CTL__ENET_RGMII_TX_CTL (_MX6Q_PAD_RGMII_TX_CTL__ENET_RGMII_TX_CTL | MUX_PAD_CTRL(MX6Q_ENET_PAD_CTRL)) #define MX6Q_PAD_RGMII_TX_CTL__GPIO_6_26 (_MX6Q_PAD_RGMII_TX_CTL__GPIO_6_26 | MUX_PAD_CTRL(NO_PAD_CTRL)) #define MX6Q_PAD_RGMII_TX_CTL__MIPI_CORE_DPHY_TEST_IN_7 (_MX6Q_PAD_RGMII_TX_CTL__MIPI_CORE_DPHY_TEST_IN_7 | MUX_PAD_CTRL(NO_PAD_CTRL)) @@ -3756,7 +3759,7 @@ #define MX6Q_PAD_RGMII_RD3__GPIO_6_29 (_MX6Q_PAD_RGMII_RD3__GPIO_6_29 | MUX_PAD_CTRL(NO_PAD_CTRL)) #define MX6Q_PAD_RGMII_RD3__MIPI_CORE_DPHY_TEST_IN_10 (_MX6Q_PAD_RGMII_RD3__MIPI_CORE_DPHY_TEST_IN_10 | MUX_PAD_CTRL(NO_PAD_CTRL)) -#define MX6Q_PAD_RGMII_RXC__USBOH3_H3_STROBE (_MX6Q_PAD_RGMII_RXC__USBOH3_H3_STROBE | MUX_PAD_CTRL(NO_PAD_CTRL)) +#define MX6Q_PAD_RGMII_RXC__USBOH3_H3_STROBE (_MX6Q_PAD_RGMII_RXC__USBOH3_H3_STROBE | MUX_PAD_CTRL(MX6Q_USB_HSIC_PAD_CTRL)) #define MX6Q_PAD_RGMII_RXC__ENET_RGMII_RXC (_MX6Q_PAD_RGMII_RXC__ENET_RGMII_RXC | MUX_PAD_CTRL(MX6Q_ENET_PAD_CTRL)) #define MX6Q_PAD_RGMII_RXC__GPIO_6_30 (_MX6Q_PAD_RGMII_RXC__GPIO_6_30 | MUX_PAD_CTRL(NO_PAD_CTRL)) #define MX6Q_PAD_RGMII_RXC__MIPI_CORE_DPHY_TEST_IN_11 (_MX6Q_PAD_RGMII_RXC__MIPI_CORE_DPHY_TEST_IN_11 | MUX_PAD_CTRL(NO_PAD_CTRL)) From cefcb0c2817faf20e9709895d8ebb1a466e730af Mon Sep 17 00:00:00 2001 From: Sascha Hauer Date: Thu, 31 Jan 2013 15:33:38 +0100 Subject: [PATCH 2/6] USB chipidea i.MX: Fix PTS mask for HSIC bit25 is part of the PTS bits, so mask it out before rewriting it. Signed-off-by: Sascha Hauer --- drivers/usb/imx/chipidea-imx.c | 2 +- include/usb/chipidea-imx.h | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/usb/imx/chipidea-imx.c b/drivers/usb/imx/chipidea-imx.c index 5b4c0812c..64bb8669e 100644 --- a/drivers/usb/imx/chipidea-imx.c +++ b/drivers/usb/imx/chipidea-imx.c @@ -20,7 +20,7 @@ #include #include -#define MXC_EHCI_PORTSC_MASK (0xf << 28) +#define MXC_EHCI_PORTSC_MASK ((0xf << 28) | (1 << 25)) static int imx_chipidea_probe(struct device_d *dev) { diff --git a/include/usb/chipidea-imx.h b/include/usb/chipidea-imx.h index e98cc891b..252d488e5 100644 --- a/include/usb/chipidea-imx.h +++ b/include/usb/chipidea-imx.h @@ -9,6 +9,7 @@ #define MXC_EHCI_MODE_UTMI_16_BIT ((0 << 30) | (1 << 28)) #define MXC_EHCI_MODE_PHILIPS (1 << 30) #define MXC_EHCI_MODE_ULPI (2 << 30) +#define MXC_EHCI_MODE_HSIC (1 << 25) #define MXC_EHCI_MODE_SERIAL (3 << 30) /* From 80a4c202dd5f36ffcd127aa5178fdab7149e9139 Mon Sep 17 00:00:00 2001 From: Sascha Hauer Date: Thu, 31 Jan 2013 15:13:40 +0100 Subject: [PATCH 3/6] USB ehci: Add platform specific init calls Some USB cores need a platform specific init hook, add it to the ehci driver. Signed-off-by: Sascha Hauer --- drivers/usb/host/ehci-hcd.c | 14 ++++++++++++++ include/usb/ehci.h | 5 +++++ 2 files changed, 19 insertions(+) diff --git a/drivers/usb/host/ehci-hcd.c b/drivers/usb/host/ehci-hcd.c index d0d6ae4cc..d6dc1deec 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/include/usb/ehci.h b/include/usb/ehci.h index 437711697..93f980d34 100644 --- a/include/usb/ehci.h +++ b/include/usb/ehci.h @@ -11,6 +11,11 @@ struct ehci_data { void __iomem *hccr; void __iomem *hcor; unsigned long flags; + + /* platform specific init functions */ + int (*init)(void *drvdata); + int (*post_init)(void *drvdata); + void *drvdata; }; #ifdef CONFIG_USB_EHCI From 298f7fc3b6f8bcbbb0d4fafc60208e2ec997e9a7 Mon Sep 17 00:00:00 2001 From: Sascha Hauer Date: Thu, 31 Jan 2013 15:20:41 +0100 Subject: [PATCH 4/6] USB i.MX chipidea: implement post init support Some controllers need an init hook after the USB controller is started, so implement the post init hook for i.MX. Signed-off-by: Sascha Hauer --- drivers/usb/imx/chipidea-imx.c | 43 +++++++++++++++++++---- drivers/usb/imx/imx-usb-misc.c | 63 +++++++++++++++++++++++++++------- include/usb/chipidea-imx.h | 2 ++ 3 files changed, 89 insertions(+), 19 deletions(-) diff --git a/drivers/usb/imx/chipidea-imx.c b/drivers/usb/imx/chipidea-imx.c index 64bb8669e..de80c3616 100644 --- a/drivers/usb/imx/chipidea-imx.c +++ b/drivers/usb/imx/chipidea-imx.c @@ -22,12 +22,41 @@ #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 +68,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)) { diff --git a/drivers/usb/imx/imx-usb-misc.c b/drivers/usb/imx/imx-usb-misc.c index 4cdf5ab3a..d42f4c0dc 100644 --- a/drivers/usb/imx/imx-usb-misc.c +++ b/drivers/usb/imx/imx-usb-misc.c @@ -34,6 +34,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 +98,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 +161,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 +242,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 +341,61 @@ 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 __maybe_unused int mx6_initialize_usb_hw(void __iomem *base, int port, unsigned int flags) { return 0; } +static __maybe_unused struct imx_usb_misc_data mx6_data = { + .init = mx6_initialize_usb_hw, +}; + 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 +403,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; - return __imx_usbmisc_port_init(usbmisc_base, port, flags); + 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; + + 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 +441,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; } diff --git a/include/usb/chipidea-imx.h b/include/usb/chipidea-imx.h index 252d488e5..3f9f61ee1 100644 --- a/include/usb/chipidea-imx.h +++ b/include/usb/chipidea-imx.h @@ -40,8 +40,10 @@ enum imx_usb_mode { struct imxusb_platformdata { unsigned long flags; enum imx_usb_mode mode; + int (*init)(int port); }; int imx_usbmisc_port_init(int port, unsigned flags); +int imx_usbmisc_port_post_init(int port, unsigned flags); #endif /* __USB_CHIPIDEA_IMX_H */ From 8139fa78b9ab7c53e194679ec9855bfcd92b1f80 Mon Sep 17 00:00:00 2001 From: Sascha Hauer Date: Thu, 31 Jan 2013 15:21:59 +0100 Subject: [PATCH 5/6] USB i.MX6: Add HSIC support HSIC needs some special setup for i.MX6. Most ugly detail is that the HSIC needs help of the IOMUX to configure a pullup on the strobe line. This has to be done after the ehci controller has started. Fortunately there is only one muxing possibility for the HSIC ports on i.MX6, so we can simply control the iomux from the usbmisc driver. Signed-off-by: Sascha Hauer --- drivers/usb/imx/imx-usb-misc.c | 60 ++++++++++++++++++++++++++++++++++ 1 file changed, 60 insertions(+) diff --git a/drivers/usb/imx/imx-usb-misc.c b/drivers/usb/imx/imx-usb-misc.c index d42f4c0dc..901ced485 100644 --- a/drivers/usb/imx/imx-usb-misc.c +++ b/drivers/usb/imx/imx-usb-misc.c @@ -17,6 +17,8 @@ #include #include #include +#include +#include #define MX25_OTG_SIC_SHIFT 29 #define MX25_OTG_SIC_MASK (0x3 << MX25_OTG_SIC_SHIFT) @@ -345,14 +347,72 @@ 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[] = { From 0a643b3d426e606dd42678b87a1fe205aea2b9e7 Mon Sep 17 00:00:00 2001 From: Sascha Hauer Date: Tue, 5 Feb 2013 15:50:31 +0100 Subject: [PATCH 6/6] USB i.MX: Add chipidea gadget support This adds USB gadget support to the i.MX chipidea driver. Basically we have to add a register function to the fsl udc driver and call this from the chipidea driver if device mode is selected. Signed-off-by: Sascha Hauer --- drivers/usb/gadget/fsl_udc.c | 11 +++++++++-- drivers/usb/imx/chipidea-imx.c | 11 ++++++----- include/usb/fsl_usb2.h | 6 ++++++ 3 files changed, 21 insertions(+), 7 deletions(-) diff --git a/drivers/usb/gadget/fsl_udc.c b/drivers/usb/gadget/fsl_udc.c index 0a7c3ae26..968c58f57 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/imx/chipidea-imx.c b/drivers/usb/imx/chipidea-imx.c index de80c3616..ff6175f8c 100644 --- a/drivers/usb/imx/chipidea-imx.c +++ b/drivers/usb/imx/chipidea-imx.c @@ -19,6 +19,7 @@ #include #include #include +#include #define MXC_EHCI_PORTSC_MASK ((0xf << 28) | (1 << 25)) @@ -96,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/include/usb/fsl_usb2.h b/include/usb/fsl_usb2.h index fd37adebc..dec3933d8 100644 --- a/include/usb/fsl_usb2.h +++ b/include/usb/fsl_usb2.h @@ -1,3 +1,6 @@ +#ifndef __USB_FSL_USB2_H +#define __USB_FSL_USB2_H + enum fsl_usb2_operating_modes { FSL_USB2_MPH_HOST, FSL_USB2_DR_HOST, @@ -20,3 +23,6 @@ struct fsl_usb2_platform_data { unsigned int port_enables; }; +int ci_udc_register(struct device_d *dev, void __iomem *regs); + +#endif /* __USB_FSL_USB2_H */