diff options
author | Sascha Hauer <s.hauer@pengutronix.de> | 2013-01-31 15:20:41 +0100 |
---|---|---|
committer | Sascha Hauer <s.hauer@pengutronix.de> | 2013-02-14 09:56:50 +0100 |
commit | 298f7fc3b6f8bcbbb0d4fafc60208e2ec997e9a7 (patch) | |
tree | 72e660866980a8282a3b1007e0a7112bf30942f0 | |
parent | 80a4c202dd5f36ffcd127aa5178fdab7149e9139 (diff) | |
download | barebox-298f7fc3b6f8bcbbb0d4fafc60208e2ec997e9a7.tar.gz barebox-298f7fc3b6f8bcbbb0d4fafc60208e2ec997e9a7.tar.xz |
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 <s.hauer@pengutronix.de>
-rw-r--r-- | drivers/usb/imx/chipidea-imx.c | 43 | ||||
-rw-r--r-- | drivers/usb/imx/imx-usb-misc.c | 63 | ||||
-rw-r--r-- | 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 */ |