From 91bfa2dca037019b61f7c2d51d0e19958cd37ca1 Mon Sep 17 00:00:00 2001 From: Andrey Smirnov Date: Tue, 10 Jan 2017 07:09:10 -0800 Subject: i.MX: imx-usb-phy: Add VF610 OF compatiblity string From looking at analogous Linux driver code it seems that all of the differences between code "imx23-usbphy" and "vf610-usbphy" pertain to suspend/resume functionality, which shouldn't affetct Barebox. As a result this commit just adds a compatiblity string and no other code. Signed-off-by: Andrey Smirnov Signed-off-by: Sascha Hauer --- drivers/usb/imx/imx-usb-phy.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'drivers/usb') diff --git a/drivers/usb/imx/imx-usb-phy.c b/drivers/usb/imx/imx-usb-phy.c index 9f46f8de6d..274153bd58 100644 --- a/drivers/usb/imx/imx-usb-phy.c +++ b/drivers/usb/imx/imx-usb-phy.c @@ -167,6 +167,8 @@ err_free: static __maybe_unused struct of_device_id imx_usbphy_dt_ids[] = { { .compatible = "fsl,imx23-usbphy", + }, { + .compatible = "fsl,vf610-usbphy", }, { /* sentinel */ }, -- cgit v1.2.3 From 024f720adc34df6a4cb6a981ffc0fa6d1677eda7 Mon Sep 17 00:00:00 2001 From: Andrey Smirnov Date: Tue, 10 Jan 2017 07:09:11 -0800 Subject: i.MX: Default CONFIG_USB_IMX_PHY to 'y' on Vybrid Signed-off-by: Andrey Smirnov Signed-off-by: Sascha Hauer --- drivers/usb/imx/Kconfig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/usb') diff --git a/drivers/usb/imx/Kconfig b/drivers/usb/imx/Kconfig index b0c6a4167e..8e6f3156a1 100644 --- a/drivers/usb/imx/Kconfig +++ b/drivers/usb/imx/Kconfig @@ -16,4 +16,4 @@ config USB_IMX_CHIPIDEA config USB_IMX_PHY bool - default y if ARCH_IMX6 && GENERIC_PHY + default y if (ARCH_IMX6 || ARCH_VF610) && GENERIC_PHY -- cgit v1.2.3 From 8108b5a81b1dacd9eb8d82cd2f7530b916015e14 Mon Sep 17 00:00:00 2001 From: Andrey Smirnov Date: Tue, 10 Jan 2017 07:09:12 -0800 Subject: i.MX: imx-usb-misc: Add Vybrid support Add code to do usbmisc initialization on VF610 family of SoCs. Based on analogous code from Linux kernel. Signed-off-by: Andrey Smirnov Signed-off-by: Sascha Hauer --- drivers/usb/imx/imx-usb-misc.c | 28 ++++++++++++++++++++++++++++ 1 file changed, 28 insertions(+) (limited to 'drivers/usb') diff --git a/drivers/usb/imx/imx-usb-misc.c b/drivers/usb/imx/imx-usb-misc.c index 7c18ca2a18..9cae44056c 100644 --- a/drivers/usb/imx/imx-usb-misc.c +++ b/drivers/usb/imx/imx-usb-misc.c @@ -422,6 +422,28 @@ static __maybe_unused struct imx_usb_misc_data mx6_data = { .post_init = mx6_post_init, }; +#define VF610_OVER_CUR_DIS BIT(7) + +static __maybe_unused int vf610_initialize_usb_hw(void __iomem *base, int port, + unsigned int flags) +{ + u32 reg; + + if (port >= 1) + return -EINVAL; + + if (flags & MXC_EHCI_DISABLE_OVERCURRENT) { + reg = readl(base); + writel(reg | VF610_OVER_CUR_DIS, base); + } + + return 0; +} + +static __maybe_unused struct imx_usb_misc_data vf610_data = { + .init = vf610_initialize_usb_hw, +}; + static struct platform_device_id imx_usbmisc_ids[] = { #ifdef CONFIG_ARCH_IMX25 { @@ -518,6 +540,12 @@ static __maybe_unused struct of_device_id imx_usbmisc_dt_ids[] = { .compatible = "fsl,imx6q-usbmisc", .data = &mx6_data, }, +#endif +#ifdef CONFIG_ARCH_VF610 + { + .compatible = "fsl,vf610-usbmisc", + .data = &vf610_data, + }, #endif { /* sentinel */ -- cgit v1.2.3 From fc10539f7dc088f2466cfcf21899a461f93feedf Mon Sep 17 00:00:00 2001 From: Sascha Hauer Date: Fri, 13 Jan 2017 12:10:04 +0100 Subject: usb: imx: Make usb-misc multi instance safe i.MX7 has two usbmisc devices, so we cannot use global instance variables anymore. Create a driver private data struct for it. Signed-off-by: Sascha Hauer --- drivers/usb/imx/chipidea-imx.c | 9 +++++++-- drivers/usb/imx/imx-usb-misc.c | 34 +++++++++++++++++++++------------- include/usb/chipidea-imx.h | 4 ++-- 3 files changed, 30 insertions(+), 17 deletions(-) (limited to 'drivers/usb') diff --git a/drivers/usb/imx/chipidea-imx.c b/drivers/usb/imx/chipidea-imx.c index ed00ff4a1d..f4354876cf 100644 --- a/drivers/usb/imx/chipidea-imx.c +++ b/drivers/usb/imx/chipidea-imx.c @@ -37,6 +37,7 @@ struct imx_chipidea { unsigned long flags; uint32_t mode; int portno; + struct device_d *usbmisc; enum usb_phy_interface phymode; struct param_d *param_mode; int role_registered; @@ -67,7 +68,7 @@ static int imx_chipidea_port_init(void *drvdata) return ret; } - ret = imx_usbmisc_port_init(ci->portno, ci->flags); + ret = imx_usbmisc_port_init(ci->usbmisc, ci->portno, ci->flags); if (ret) dev_err(ci->dev, "misc init failed: %s\n", strerror(-ret)); @@ -79,7 +80,7 @@ static int imx_chipidea_port_post_init(void *drvdata) struct imx_chipidea *ci = drvdata; int ret; - ret = imx_usbmisc_port_post_init(ci->portno, ci->flags); + ret = imx_usbmisc_port_post_init(ci->usbmisc, ci->portno, ci->flags); if (ret) dev_err(ci->dev, "post misc init failed: %s\n", strerror(-ret)); @@ -95,6 +96,10 @@ static int imx_chipidea_probe_dt(struct imx_chipidea *ci) "#index-cells", 0, &out_args)) return -ENODEV; + ci->usbmisc = of_find_device_by_node(out_args.np); + if (!ci->usbmisc) + return -ENODEV; + ci->portno = out_args.args[0]; ci->flags = MXC_EHCI_MODE_UTMI_8BIT; diff --git a/drivers/usb/imx/imx-usb-misc.c b/drivers/usb/imx/imx-usb-misc.c index 9cae44056c..b7606e2634 100644 --- a/drivers/usb/imx/imx-usb-misc.c +++ b/drivers/usb/imx/imx-usb-misc.c @@ -43,6 +43,11 @@ struct imx_usb_misc_data { int (*post_init)(void __iomem *base, int port, unsigned int flags); }; +struct imx_usb_misc_priv { + struct imx_usb_misc_data *data; + void __iomem *base; +}; + static __maybe_unused int mx25_initialize_usb_hw(void __iomem *base, int port, unsigned int flags) { unsigned int v; @@ -552,35 +557,37 @@ static __maybe_unused struct of_device_id imx_usbmisc_dt_ids[] = { }, }; -static struct imx_usb_misc_data *imxusbmisc_data; -static void __iomem *usbmisc_base; - -int imx_usbmisc_port_init(int port, unsigned flags) +int imx_usbmisc_port_init(struct device_d *dev, int port, unsigned flags) { - if (!imxusbmisc_data) + struct imx_usb_misc_priv *usbmisc = dev->priv; + + if (!usbmisc) return -ENODEV; - if (!imxusbmisc_data->init) + if (!usbmisc->data->init) return 0; - return imxusbmisc_data->init(usbmisc_base, port, flags); + return usbmisc->data->init(usbmisc->base, port, flags); } -int imx_usbmisc_port_post_init(int port, unsigned flags) +int imx_usbmisc_port_post_init(struct device_d *dev, int port, unsigned flags) { - if (!imxusbmisc_data) + struct imx_usb_misc_priv *usbmisc = dev->priv; + + if (!usbmisc) return -ENODEV; - if (!imxusbmisc_data->post_init) + if (!usbmisc->data->post_init) return 0; - return imxusbmisc_data->post_init(usbmisc_base, port, flags); + return usbmisc->data->post_init(usbmisc->base, port, flags); } static int imx_usbmisc_probe(struct device_d *dev) { struct resource *iores; struct imx_usb_misc_data *devtype; + struct imx_usb_misc_priv *usbmisc = dev->priv; int ret; ret = dev_get_drvdata(dev, (const void **)&devtype); @@ -590,9 +597,10 @@ static int imx_usbmisc_probe(struct device_d *dev) iores = dev_request_mem_resource(dev, 0); if (IS_ERR(iores)) return PTR_ERR(iores); - usbmisc_base = IOMEM(iores->start); - imxusbmisc_data = devtype; + usbmisc = xzalloc(sizeof(*usbmisc)); + usbmisc->base = IOMEM(iores->start); + usbmisc->data = devtype; return 0; } diff --git a/include/usb/chipidea-imx.h b/include/usb/chipidea-imx.h index 64f086af6c..640ae06944 100644 --- a/include/usb/chipidea-imx.h +++ b/include/usb/chipidea-imx.h @@ -48,7 +48,7 @@ struct imxusb_platformdata { enum imx_usb_mode mode; }; -int imx_usbmisc_port_init(int port, unsigned flags); -int imx_usbmisc_port_post_init(int port, unsigned flags); +int imx_usbmisc_port_init(struct device_d *dev, int port, unsigned flags); +int imx_usbmisc_port_post_init(struct device_d *dev, int port, unsigned flags); #endif /* __USB_CHIPIDEA_IMX_H */ -- cgit v1.2.3 From 2eb99b610bf321eb56aba5d72d1b4ff346823374 Mon Sep 17 00:00:00 2001 From: Sascha Hauer Date: Fri, 13 Jan 2017 12:12:09 +0100 Subject: usb: imx: Add usbmisc support for i.MX7 Taken directly from Linux-4.10-rc3 Signed-off-by: Sascha Hauer --- drivers/usb/imx/imx-usb-misc.c | 53 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 53 insertions(+) (limited to 'drivers/usb') diff --git a/drivers/usb/imx/imx-usb-misc.c b/drivers/usb/imx/imx-usb-misc.c index b7606e2634..dc0de9e9e1 100644 --- a/drivers/usb/imx/imx-usb-misc.c +++ b/drivers/usb/imx/imx-usb-misc.c @@ -353,6 +353,7 @@ static __maybe_unused struct imx_usb_misc_data mx5_data = { #define MX6_USB_CTRL(n) ((n) * 4) #define MX6_USB_CTRL_OVER_CUR_DIS (1 << 7) +#define MX6_USB_CTRL_OVER_CUR_ACT_HIGH (1 << 8) static void mx6_hsic_pullup(unsigned long reg, int on) { @@ -427,6 +428,46 @@ static __maybe_unused struct imx_usb_misc_data mx6_data = { .post_init = mx6_post_init, }; +#define MX7D_USBNC_USB_CTRL2 0x4 +#define MX7D_USB_VBUS_WAKEUP_SOURCE_MASK 0x3 +#define MX7D_USB_VBUS_WAKEUP_SOURCE(v) (v << 0) +#define MX7D_USB_VBUS_WAKEUP_SOURCE_VBUS MX7D_USB_VBUS_WAKEUP_SOURCE(0) +#define MX7D_USB_VBUS_WAKEUP_SOURCE_AVALID MX7D_USB_VBUS_WAKEUP_SOURCE(1) +#define MX7D_USB_VBUS_WAKEUP_SOURCE_BVALID MX7D_USB_VBUS_WAKEUP_SOURCE(2) +#define MX7D_USB_VBUS_WAKEUP_SOURCE_SESS_END MX7D_USB_VBUS_WAKEUP_SOURCE(3) + +static int usbmisc_imx7d_init(void __iomem *base, int port, + unsigned int flags) +{ + u32 reg; + + if (port >= 1) + return -EINVAL; + + reg = readl(base); + if (flags & MXC_EHCI_DISABLE_OVERCURRENT) { + reg |= MX6_USB_CTRL_OVER_CUR_DIS; + } else { + reg &= ~MX6_USB_CTRL_OVER_CUR_DIS; + if (flags & MXC_EHCI_OC_PIN_ACTIVE_LOW) + reg &= ~MX6_USB_CTRL_OVER_CUR_ACT_HIGH; + else + reg |= MX6_USB_CTRL_OVER_CUR_ACT_HIGH; + } + writel(reg, base); + + reg = readl(base + MX7D_USBNC_USB_CTRL2); + reg &= ~MX7D_USB_VBUS_WAKEUP_SOURCE_MASK; + writel(reg | MX7D_USB_VBUS_WAKEUP_SOURCE_BVALID, + base + MX7D_USBNC_USB_CTRL2); + + return 0; +} + +static __maybe_unused struct imx_usb_misc_data mx7_data = { + .init = usbmisc_imx7d_init, +}; + #define VF610_OVER_CUR_DIS BIT(7) static __maybe_unused int vf610_initialize_usb_hw(void __iomem *base, int port, @@ -497,6 +538,12 @@ static struct platform_device_id imx_usbmisc_ids[] = { .name = "imx6-usb-misc", .driver_data = (unsigned long)&mx6_data, }, +#endif +#ifdef CONFIG_ARCH_IMX7 + { + .name = "imx7d-usb-misc", + .driver_data = (unsigned long)&mx7_data, + }, #endif { /* sentinel */ @@ -546,6 +593,12 @@ static __maybe_unused struct of_device_id imx_usbmisc_dt_ids[] = { .data = &mx6_data, }, #endif +#ifdef CONFIG_ARCH_IMX7 + { + .compatible = "fsl,imx7d-usbmisc", + .data = &mx7_data, + }, +#endif #ifdef CONFIG_ARCH_VF610 { .compatible = "fsl,vf610-usbmisc", -- cgit v1.2.3 From bbe0df90b8e2463dd8db651e9f1dd57702985d2d Mon Sep 17 00:00:00 2001 From: Sascha Hauer Date: Fri, 13 Jan 2017 12:17:34 +0100 Subject: usb: imx: Add clock support Signed-off-by: Sascha Hauer --- drivers/usb/imx/chipidea-imx.c | 13 +++++++++++++ 1 file changed, 13 insertions(+) (limited to 'drivers/usb') diff --git a/drivers/usb/imx/chipidea-imx.c b/drivers/usb/imx/chipidea-imx.c index f4354876cf..ccd5346133 100644 --- a/drivers/usb/imx/chipidea-imx.c +++ b/drivers/usb/imx/chipidea-imx.c @@ -27,6 +27,7 @@ #include #include #include +#include #define MXC_EHCI_PORTSC_MASK ((0xf << 28) | (1 << 25)) @@ -44,6 +45,7 @@ struct imx_chipidea { struct regulator *vbus; struct phy *phy; struct usb_phy *usbphy; + struct clk *clk; }; static int imx_chipidea_port_init(void *drvdata) @@ -268,6 +270,17 @@ static int imx_chipidea_probe(struct device_d *dev) if (IS_ERR(ci->vbus)) ci->vbus = NULL; + /* + * Some devices have more than one clock, in this case they are enabled + * by default in the clock driver. At least enable the main clock for + * devices which have only one. + */ + ci->clk = clk_get(dev, NULL); + if (IS_ERR(ci->clk)) + return PTR_ERR(ci->clk); + + clk_enable(ci->clk); + if (of_property_read_bool(dev->device_node, "fsl,usbphy")) { ci->phy = of_phy_get_by_phandle(dev, "fsl,usbphy", 0); if (IS_ERR(ci->phy)) { -- cgit v1.2.3