* [RFC PATCH 00/11 V6] MXS: Add i.MX28 USB Host driver @ 2012-04-29 22:34 Marek Vasut 2012-04-29 22:34 ` [PATCH 01/11] MXS: Make clk_disable return integer Marek Vasut ` (11 more replies) 0 siblings, 12 replies; 28+ messages in thread From: Marek Vasut @ 2012-04-29 22:34 UTC (permalink / raw) To: linux-arm-kernel This patchset introduces the USB Host driver for i.MX28 CPU, utilising the generic USB PHY infrastructure. Also added is glue code for CI13xxx driver, to allow device mode. This patchset still does NOT support OTG mode, the device/host mode is selected via platform data. V2: Introduce stub imx-usb driver that then registers the PHY and EHCI drivers. V3: Add the HCD on demand based on the PHY's state (only add HCD if it's host). Currently, only the HOST mode is supported. V4: * Introduce ci13xxx gadget glue * Reorder patches in a more sensible order * Introduce platform data, containing VBUS GPIO and port mode (device/gadget) * Rename imx-usb to imx-otg * Drop mx28evk usb host patch * Use more devm_ function * Rework the mxs-phy to register the same interrupt as ehci-mxs (and effectivelly kill bogus otg_set_vbus() call from ehci-mxs ; use standard ehci irq handling in ehci-mxs) V5: * Finally move OTG IRQ handling into imx-otg * Move imx_otg_set_{host,peripheral}() into imx-otg * Move imx_otg_work() into imx-otg driver (now it all makes sense, yay!) V6: Do PHY-specific job inside the PHY driver Marek Vasut (11): MXS: Make clk_disable return integer MXS: Add USB EHCI and USB PHY clock handling MXS: Fixup i.MX233 USB base address name MXS: Add data shared between imx-otg and EHCI driver MXS: Modify the ci13xxx_udc to avoid adding UDC MXS: Add small registration glue for ci13xxx_udc MXS: Add separate MXS EHCI HCD driver MXS: Add imx-otg driver MXS: Add USB PHY driver MXS: Add platform registration hooks for USB EHCI MXS: Enable USB on M28EVK arch/arm/mach-mxs/Kconfig | 2 + arch/arm/mach-mxs/clock-mx28.c | 28 +- arch/arm/mach-mxs/devices-mx28.h | 5 + arch/arm/mach-mxs/devices/Kconfig | 3 + arch/arm/mach-mxs/devices/Makefile | 1 + arch/arm/mach-mxs/devices/platform-usb.c | 89 +++++ arch/arm/mach-mxs/include/mach/clock.h | 2 +- arch/arm/mach-mxs/include/mach/devices-common.h | 13 + arch/arm/mach-mxs/include/mach/mx23.h | 8 +- arch/arm/mach-mxs/mach-m28evk.c | 21 ++ drivers/usb/gadget/Kconfig | 17 + drivers/usb/gadget/Makefile | 1 + drivers/usb/gadget/ci13xxx_mxs.c | 67 ++++ drivers/usb/gadget/ci13xxx_udc.c | 12 +- drivers/usb/gadget/ci13xxx_udc.h | 1 + drivers/usb/host/Kconfig | 7 + drivers/usb/host/ehci-hcd.c | 5 + drivers/usb/host/ehci-mxs.c | 178 +++++++++ drivers/usb/otg/Kconfig | 16 + drivers/usb/otg/Makefile | 2 + drivers/usb/otg/imx-otg.c | 437 +++++++++++++++++++++++ drivers/usb/otg/mxs-phy.c | 293 +++++++++++++++ include/linux/usb/mxs-usb.h | 94 +++++ 23 files changed, 1289 insertions(+), 13 deletions(-) create mode 100644 arch/arm/mach-mxs/devices/platform-usb.c create mode 100644 drivers/usb/gadget/ci13xxx_mxs.c create mode 100644 drivers/usb/host/ehci-mxs.c create mode 100644 drivers/usb/otg/imx-otg.c create mode 100644 drivers/usb/otg/mxs-phy.c create mode 100644 include/linux/usb/mxs-usb.h Cc: Chen Peter-B29397 <B29397@freescale.com> Cc: Detlev Zundel <dzu@denx.de> Cc: Fabio Estevam <festevam@gmail.com> Cc: Li Frank-B20596 <B20596@freescale.com> Cc: Linux USB <linux-usb@vger.kernel.org> Cc: Liu JunJie-B08287 <B08287@freescale.com> Cc: Sascha Hauer <s.hauer@pengutronix.de> Cc: Shawn Guo <shawn.guo@linaro.org> Cc: Shi Make-B15407 <B15407@freescale.com> Cc: Stefano Babic <sbabic@denx.de> Cc: Subodh Nijsure <snijsure@grid-net.com> Cc: Wolfgang Denk <wd@denx.de> -- 1.7.10 ^ permalink raw reply [flat|nested] 28+ messages in thread
* [PATCH 01/11] MXS: Make clk_disable return integer 2012-04-29 22:34 [RFC PATCH 00/11 V6] MXS: Add i.MX28 USB Host driver Marek Vasut @ 2012-04-29 22:34 ` Marek Vasut 2012-04-29 22:34 ` [PATCH 02/11] MXS: Add USB EHCI and USB PHY clock handling Marek Vasut ` (10 subsequent siblings) 11 siblings, 0 replies; 28+ messages in thread From: Marek Vasut @ 2012-04-29 22:34 UTC (permalink / raw) To: linux-arm-kernel This allows subsequent USB clock patch to interchange enable() and disable() calls without adding unnecessary switching cruft. Signed-off-by: Marek Vasut <marex@denx.de> Cc: Chen Peter-B29397 <B29397@freescale.com> Cc: Detlev Zundel <dzu@denx.de> Cc: Fabio Estevam <festevam@gmail.com> Cc: Li Frank-B20596 <B20596@freescale.com> Cc: Linux USB <linux-usb@vger.kernel.org> Cc: Liu JunJie-B08287 <B08287@freescale.com> Cc: Sascha Hauer <s.hauer@pengutronix.de> Cc: Shawn Guo <shawn.guo@linaro.org> Cc: Shi Make-B15407 <B15407@freescale.com> Cc: Stefano Babic <sbabic@denx.de> Cc: Subodh Nijsure <snijsure@grid-net.com> Cc: Wolfgang Denk <wd@denx.de> --- arch/arm/mach-mxs/clock-mx28.c | 7 +++++-- arch/arm/mach-mxs/include/mach/clock.h | 2 +- 2 files changed, 6 insertions(+), 3 deletions(-) diff --git a/arch/arm/mach-mxs/clock-mx28.c b/arch/arm/mach-mxs/clock-mx28.c index cea29c9..43116ba 100644 --- a/arch/arm/mach-mxs/clock-mx28.c +++ b/arch/arm/mach-mxs/clock-mx28.c @@ -86,7 +86,7 @@ static int _raw_clk_enable(struct clk *clk) return 0; } -static void _raw_clk_disable(struct clk *clk) +static int _raw_clk_disable(struct clk *clk) { u32 reg; @@ -95,6 +95,8 @@ static void _raw_clk_disable(struct clk *clk) reg |= 1 << clk->enable_shift; __raw_writel(reg, clk->enable_reg); } + + return 0; } /* @@ -149,7 +151,7 @@ _CLK_ENABLE_PLL(pll1_clk, PLL1, EN_USB_CLKS) _CLK_ENABLE_PLL(pll2_clk, PLL2, CLKGATE) #define _CLK_DISABLE_PLL(name, r, g) \ -static void name##_disable(struct clk *clk) \ +static int name##_disable(struct clk *clk) \ { \ __raw_writel(BM_CLKCTRL_##r##CTRL0_POWER, \ CLKCTRL_BASE_ADDR + HW_CLKCTRL_##r##CTRL0_CLR); \ @@ -161,6 +163,7 @@ static void name##_disable(struct clk *clk) \ __raw_writel(BM_CLKCTRL_##r##CTRL0_##g, \ CLKCTRL_BASE_ADDR + HW_CLKCTRL_##r##CTRL0_CLR); \ \ + return 0; \ } _CLK_DISABLE_PLL(pll0_clk, PLL0, EN_USB_CLKS) diff --git a/arch/arm/mach-mxs/include/mach/clock.h b/arch/arm/mach-mxs/include/mach/clock.h index 592c9ab..21d1fad 100644 --- a/arch/arm/mach-mxs/include/mach/clock.h +++ b/arch/arm/mach-mxs/include/mach/clock.h @@ -50,7 +50,7 @@ struct clk { int (*enable) (struct clk *); /* Function ptr to disable the clock. Leave blank if clock can not be gated. */ - void (*disable) (struct clk *); + int (*disable) (struct clk *); /* Function ptr to set the parent clock of the clock. */ int (*set_parent) (struct clk *, struct clk *); }; -- 1.7.10 ^ permalink raw reply related [flat|nested] 28+ messages in thread
* [PATCH 02/11] MXS: Add USB EHCI and USB PHY clock handling 2012-04-29 22:34 [RFC PATCH 00/11 V6] MXS: Add i.MX28 USB Host driver Marek Vasut 2012-04-29 22:34 ` [PATCH 01/11] MXS: Make clk_disable return integer Marek Vasut @ 2012-04-29 22:34 ` Marek Vasut 2012-04-29 22:34 ` [PATCH 03/11] MXS: Fixup i.MX233 USB base address name Marek Vasut ` (9 subsequent siblings) 11 siblings, 0 replies; 28+ messages in thread From: Marek Vasut @ 2012-04-29 22:34 UTC (permalink / raw) To: linux-arm-kernel Based on code by: Tony Lin <tony.lin@freescale.com> Signed-off-by: Marek Vasut <marex@denx.de> Cc: Chen Peter-B29397 <B29397@freescale.com> Cc: Detlev Zundel <dzu@denx.de> Cc: Fabio Estevam <festevam@gmail.com> Cc: Li Frank-B20596 <B20596@freescale.com> Cc: Linux USB <linux-usb@vger.kernel.org> Cc: Liu JunJie-B08287 <B08287@freescale.com> Cc: Sascha Hauer <s.hauer@pengutronix.de> Cc: Shawn Guo <shawn.guo@linaro.org> Cc: Shi Make-B15407 <B15407@freescale.com> Cc: Stefano Babic <sbabic@denx.de> Cc: Subodh Nijsure <snijsure@grid-net.com> Cc: Wolfgang Denk <wd@denx.de> --- arch/arm/mach-mxs/clock-mx28.c | 21 +++++++++++++++++++-- 1 file changed, 19 insertions(+), 2 deletions(-) diff --git a/arch/arm/mach-mxs/clock-mx28.c b/arch/arm/mach-mxs/clock-mx28.c index 43116ba..8784a72 100644 --- a/arch/arm/mach-mxs/clock-mx28.c +++ b/arch/arm/mach-mxs/clock-mx28.c @@ -577,6 +577,21 @@ static struct clk usb1_clk = { .parent = &pll1_clk, }; +static struct clk usb_phy_clk0 = { + .parent = &pll0_clk, + .enable = _raw_clk_disable, + .disable = _raw_clk_enable, + .enable_reg = CLKCTRL_BASE_ADDR + HW_CLKCTRL_PLL0CTRL0, + .enable_shift = 18, +}; + +static struct clk usb_phy_clk1 = { + .parent = &pll1_clk, + .enable = _raw_clk_disable, + .disable = _raw_clk_enable, + .enable_reg = CLKCTRL_BASE_ADDR + HW_CLKCTRL_PLL1CTRL0, + .enable_shift = 18, +}; #define _DEFINE_CLOCK(name, er, es, p) \ static struct clk name = { \ .enable_reg = CLKCTRL_BASE_ADDR + HW_CLKCTRL_##er, \ @@ -636,8 +651,10 @@ static struct clk_lookup lookups[] = { _REGISTER_CLOCK("mxs-mmc.3", NULL, ssp3_clk) _REGISTER_CLOCK("flexcan.0", NULL, can0_clk) _REGISTER_CLOCK("flexcan.1", NULL, can1_clk) - _REGISTER_CLOCK(NULL, "usb0", usb0_clk) - _REGISTER_CLOCK(NULL, "usb1", usb1_clk) + _REGISTER_CLOCK("imx-otg.0", "usb", usb0_clk) + _REGISTER_CLOCK("imx-otg.1", "usb", usb1_clk) + _REGISTER_CLOCK("mxs-usb-phy.0", "phy", usb_phy_clk0) + _REGISTER_CLOCK("mxs-usb-phy.1", "phy", usb_phy_clk1) _REGISTER_CLOCK("mxs-pwm.0", NULL, pwm_clk) _REGISTER_CLOCK("mxs-pwm.1", NULL, pwm_clk) _REGISTER_CLOCK("mxs-pwm.2", NULL, pwm_clk) -- 1.7.10 ^ permalink raw reply related [flat|nested] 28+ messages in thread
* [PATCH 03/11] MXS: Fixup i.MX233 USB base address name 2012-04-29 22:34 [RFC PATCH 00/11 V6] MXS: Add i.MX28 USB Host driver Marek Vasut 2012-04-29 22:34 ` [PATCH 01/11] MXS: Make clk_disable return integer Marek Vasut 2012-04-29 22:34 ` [PATCH 02/11] MXS: Add USB EHCI and USB PHY clock handling Marek Vasut @ 2012-04-29 22:34 ` Marek Vasut 2012-04-29 22:34 ` [PATCH 04/11] MXS: Add data shared between imx-otg and EHCI driver Marek Vasut ` (8 subsequent siblings) 11 siblings, 0 replies; 28+ messages in thread From: Marek Vasut @ 2012-04-29 22:34 UTC (permalink / raw) To: linux-arm-kernel Modify USB EHCI and USB PHY base addresses on the i.MX233 to nicely fit into the whole USB registration scheme. Based on code by: Tony Lin <tony.lin@freescale.com> Signed-off-by: Marek Vasut <marex@denx.de> Cc: Chen Peter-B29397 <B29397@freescale.com> Cc: Detlev Zundel <dzu@denx.de> Cc: Fabio Estevam <festevam@gmail.com> Cc: Li Frank-B20596 <B20596@freescale.com> Cc: Linux USB <linux-usb@vger.kernel.org> Cc: Liu JunJie-B08287 <B08287@freescale.com> Cc: Sascha Hauer <s.hauer@pengutronix.de> Cc: Shawn Guo <shawn.guo@linaro.org> Cc: Shi Make-B15407 <B15407@freescale.com> Cc: Stefano Babic <sbabic@denx.de> Cc: Subodh Nijsure <snijsure@grid-net.com> Cc: Wolfgang Denk <wd@denx.de> --- arch/arm/mach-mxs/include/mach/mx23.h | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/arch/arm/mach-mxs/include/mach/mx23.h b/arch/arm/mach-mxs/include/mach/mx23.h index 599094b..7955b75 100644 --- a/arch/arm/mach-mxs/include/mach/mx23.h +++ b/arch/arm/mach-mxs/include/mach/mx23.h @@ -64,8 +64,8 @@ #define MX23_AUART1_BASE_ADDR (MX23_IO_BASE_ADDR + 0x06c000) #define MX23_AUART2_BASE_ADDR (MX23_IO_BASE_ADDR + 0x06e000) #define MX23_DUART_BASE_ADDR (MX23_IO_BASE_ADDR + 0x070000) -#define MX23_USBPHY_BASE_ADDR (MX23_IO_BASE_ADDR + 0x07c000) -#define MX23_USBCTRL_BASE_ADDR (MX23_IO_BASE_ADDR + 0x080000) +#define MX23_USBPHY0_BASE_ADDR (MX23_IO_BASE_ADDR + 0x07c000) +#define MX23_USBCTRL0_BASE_ADDR (MX23_IO_BASE_ADDR + 0x080000) #define MX23_DRAM_BASE_ADDR (MX23_IO_BASE_ADDR + 0x0e0000) #define MX23_IO_P2V(x) MXS_IO_P2V(x) @@ -89,8 +89,8 @@ #define MX23_INT_SPDIF_ERROR 10 #define MX23_INT_SAIF1_IRQ 10 #define MX23_INT_SAIF2_IRQ 10 -#define MX23_INT_USB_CTRL 11 -#define MX23_INT_USB_WAKEUP 12 +#define MX23_INT_USB0 11 +#define MX23_INT_USB0_WAKEUP 12 #define MX23_INT_GPMI_DMA 13 #define MX23_INT_SSP1_DMA 14 #define MX23_INT_SSP1_ERROR 15 -- 1.7.10 ^ permalink raw reply related [flat|nested] 28+ messages in thread
* [PATCH 04/11] MXS: Add data shared between imx-otg and EHCI driver 2012-04-29 22:34 [RFC PATCH 00/11 V6] MXS: Add i.MX28 USB Host driver Marek Vasut ` (2 preceding siblings ...) 2012-04-29 22:34 ` [PATCH 03/11] MXS: Fixup i.MX233 USB base address name Marek Vasut @ 2012-04-29 22:34 ` Marek Vasut 2012-04-29 22:34 ` [PATCH 05/11] MXS: Modify the ci13xxx_udc to avoid adding UDC Marek Vasut ` (7 subsequent siblings) 11 siblings, 0 replies; 28+ messages in thread From: Marek Vasut @ 2012-04-29 22:34 UTC (permalink / raw) To: linux-arm-kernel This patch adds common data shared between the MXS EHCI HCD driver, the MXS USB Gadget driver and the imx-otg driver. These data allow passing clock and memory stuff from imx-otg driver into the host/gadget driver. Signed-off-by: Marek Vasut <marex@denx.de> Cc: Chen Peter-B29397 <B29397@freescale.com> Cc: Detlev Zundel <dzu@denx.de> Cc: Fabio Estevam <festevam@gmail.com> Cc: Li Frank-B20596 <B20596@freescale.com> Cc: Linux USB <linux-usb@vger.kernel.org> Cc: Liu JunJie-B08287 <B08287@freescale.com> Cc: Sascha Hauer <s.hauer@pengutronix.de> Cc: Shawn Guo <shawn.guo@linaro.org> Cc: Shi Make-B15407 <B15407@freescale.com> Cc: Stefano Babic <sbabic@denx.de> Cc: Subodh Nijsure <snijsure@grid-net.com> Cc: Wolfgang Denk <wd@denx.de> --- include/linux/usb/mxs-usb.h | 94 +++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 94 insertions(+) create mode 100644 include/linux/usb/mxs-usb.h diff --git a/include/linux/usb/mxs-usb.h b/include/linux/usb/mxs-usb.h new file mode 100644 index 0000000..3f5b5fc --- /dev/null +++ b/include/linux/usb/mxs-usb.h @@ -0,0 +1,94 @@ +/* + * include/linux/usb/mxs-usb.h + * + * Freescale i.MX USB driver shared data. + * + * Copyright (C) 2012 Marek Vasut <marex@denx.de> + * on behalf of DENX Software Engineering GmbH + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#ifndef __INCLUDE_LINUX_USB_MXS_USB_H__ +#define __INCLUDE_LINUX_USB_MXS_USB_H__ + +#include <linux/types.h> +#include <linux/platform_device.h> + +#include <linux/usb/otg.h> + +/* MXS USB PHY register definitions. */ +#define HW_USBPHY_PWD 0x00 + +#define HW_USBPHY_CTRL 0x30 +#define HW_USBPHY_CTRL_SET 0x34 +#define HW_USBPHY_CTRL_CLR 0x38 +#define HW_USBPHY_CTRL_TOG 0x3c + +#define BM_USBPHY_CTRL_SFTRST (1 << 31) +#define BM_USBPHY_CTRL_CLKGATE (1 << 30) +#define BM_USBPHY_CTRL_ENVBUSCHG_WKUP (1 << 23) +#define BM_USBPHY_CTRL_ENIDCHG_WKUP (1 << 22) +#define BM_USBPHY_CTRL_ENDPDMCHG_WKUP (1 << 21) +#define BM_USBPHY_CTRL_WAKEUP_IRQ (1 << 17) +#define BM_USBPHY_CTRL_ENIRQWAKEUP (1 << 16) +#define BM_USBPHY_CTRL_ENUTMILEVEL3 (1 << 15) +#define BM_USBPHY_CTRL_ENUTMILEVEL2 (1 << 14) +#define BM_USBPHY_CTRL_ENIRQDEVPLUGIN (1 << 11) +#define BM_USBPHY_CTRL_RESUME_IRQ (1 << 10) +#define BM_USBPHY_CTRL_ENIRQRESUMEDETECT (1 << 9) +#define BM_USBPHY_CTRL_ENOTGIDDETECT (1 << 7) +#define BM_USBPHY_CTRL_ENDEVPLUGINDETECT (1 << 4) +#define BM_USBPHY_CTRL_HOSTDISCONDETECT_IRQ (1 << 3) +#define BM_USBPHY_CTRL_ENIRQHOSTDISCON (1 << 2) +#define BM_USBPHY_CTRL_ENHOSTDISCONDETECT (1 << 1) + +#define HW_USBPHY_STATUS 0x40 + +#define BM_USBPHY_STATUS_OTGID_STATUS (1 << 8) +#define BM_USBPHY_STATUS_DEVPLUGIN_STATUS (1 << 6) +#define BM_USBPHY_STATUS_HOSTDISCON_STATUS (1 << 3) + +struct imx_otg_priv { + uint32_t gpio_vbus; + uint32_t gpio_vbus_inverted; + enum usb_otg_state new_state; + enum usb_otg_state cur_state; + struct usb_otg otg; + struct work_struct work; + struct device *dev; +}; + +struct imx_otg { + struct platform_device *pdev_host; + struct platform_device *pdev_gadget; + + struct clk *clk; + struct resource *mem_res; + void __iomem *mem; + int irq; + int irq_wakeup; + + struct imx_otg_priv priv; +}; + +struct imx_usb_platform_data { + uint32_t gpio_vbus; + bool gpio_vbus_inverted; + bool host_mode; + bool gadget_mode; +}; + +#endif /* __INCLUDE_LINUX_USB_MXS_USB_H__ */ -- 1.7.10 ^ permalink raw reply related [flat|nested] 28+ messages in thread
* [PATCH 05/11] MXS: Modify the ci13xxx_udc to avoid adding UDC 2012-04-29 22:34 [RFC PATCH 00/11 V6] MXS: Add i.MX28 USB Host driver Marek Vasut ` (3 preceding siblings ...) 2012-04-29 22:34 ` [PATCH 04/11] MXS: Add data shared between imx-otg and EHCI driver Marek Vasut @ 2012-04-29 22:34 ` Marek Vasut 2012-04-29 22:34 ` [PATCH 06/11] MXS: Add small registration glue for ci13xxx_udc Marek Vasut ` (6 subsequent siblings) 11 siblings, 0 replies; 28+ messages in thread From: Marek Vasut @ 2012-04-29 22:34 UTC (permalink / raw) To: linux-arm-kernel On the i.MX platform, we are adding the UDC ourselves from the PHY driver. This patch adds a flag into the ci13xxx_udc that avoids adding the UDC if set. Signed-off-by: Marek Vasut <marex@denx.de> Cc: Chen Peter-B29397 <B29397@freescale.com> Cc: Detlev Zundel <dzu@denx.de> Cc: Fabio Estevam <festevam@gmail.com> Cc: Felipe Balbi <balbi@ti.com> Cc: Li Frank-B20596 <B20596@freescale.com> Cc: Linux USB <linux-usb@vger.kernel.org> Cc: Liu JunJie-B08287 <B08287@freescale.com> Cc: Sascha Hauer <s.hauer@pengutronix.de> Cc: Shawn Guo <shawn.guo@linaro.org> Cc: Shi Make-B15407 <B15407@freescale.com> Cc: Stefano Babic <sbabic@denx.de> Cc: Subodh Nijsure <snijsure@grid-net.com> Cc: Wolfgang Denk <wd@denx.de> --- drivers/usb/gadget/ci13xxx_udc.c | 12 ++++++++---- drivers/usb/gadget/ci13xxx_udc.h | 1 + 2 files changed, 9 insertions(+), 4 deletions(-) diff --git a/drivers/usb/gadget/ci13xxx_udc.c b/drivers/usb/gadget/ci13xxx_udc.c index 243ef1a..94f8b19 100644 --- a/drivers/usb/gadget/ci13xxx_udc.c +++ b/drivers/usb/gadget/ci13xxx_udc.c @@ -2935,9 +2935,11 @@ static int udc_probe(struct ci13xxx_udc_driver *driver, struct device *dev, goto remove_dbg; } - retval = usb_add_gadget_udc(dev, &udc->gadget); - if (retval) - goto remove_trans; + if (!(udc->udc_driver->flags & CI13XXX_DONT_REGISTER_GADGET)) { + retval = usb_add_gadget_udc(dev, &udc->gadget); + if (retval) + goto remove_trans; + } pm_runtime_no_callbacks(&udc->gadget.dev); pm_runtime_enable(&udc->gadget.dev); @@ -2980,7 +2982,9 @@ static void udc_remove(void) err("EINVAL"); return; } - usb_del_gadget_udc(&udc->gadget); + + if (!(udc->udc_driver->flags & CI13XXX_DONT_REGISTER_GADGET)) + usb_del_gadget_udc(&udc->gadget); if (udc->transceiver) { otg_set_peripheral(udc->transceiver->otg, &udc->gadget); diff --git a/drivers/usb/gadget/ci13xxx_udc.h b/drivers/usb/gadget/ci13xxx_udc.h index 0d31af5..9f2efa2 100644 --- a/drivers/usb/gadget/ci13xxx_udc.h +++ b/drivers/usb/gadget/ci13xxx_udc.h @@ -108,6 +108,7 @@ struct ci13xxx_udc_driver { #define CI13XXX_REQUIRE_TRANSCEIVER BIT(1) #define CI13XXX_PULLUP_ON_VBUS BIT(2) #define CI13XXX_DISABLE_STREAMING BIT(3) +#define CI13XXX_DONT_REGISTER_GADGET BIT(4) #define CI13XXX_CONTROLLER_RESET_EVENT 0 #define CI13XXX_CONTROLLER_STOPPED_EVENT 1 -- 1.7.10 ^ permalink raw reply related [flat|nested] 28+ messages in thread
* [PATCH 06/11] MXS: Add small registration glue for ci13xxx_udc 2012-04-29 22:34 [RFC PATCH 00/11 V6] MXS: Add i.MX28 USB Host driver Marek Vasut ` (4 preceding siblings ...) 2012-04-29 22:34 ` [PATCH 05/11] MXS: Modify the ci13xxx_udc to avoid adding UDC Marek Vasut @ 2012-04-29 22:34 ` Marek Vasut 2012-04-29 22:34 ` [PATCH 07/11] MXS: Add separate MXS EHCI HCD driver Marek Vasut ` (5 subsequent siblings) 11 siblings, 0 replies; 28+ messages in thread From: Marek Vasut @ 2012-04-29 22:34 UTC (permalink / raw) To: linux-arm-kernel This patch adds small registration glue for the ci13xxx_udc that is compatible with the imx-otg driver. Signed-off-by: Marek Vasut <marex@denx.de> Cc: Chen Peter-B29397 <B29397@freescale.com> Cc: Detlev Zundel <dzu@denx.de> Cc: Fabio Estevam <festevam@gmail.com> Cc: Li Frank-B20596 <B20596@freescale.com> Cc: Linux USB <linux-usb@vger.kernel.org> Cc: Liu JunJie-B08287 <B08287@freescale.com> Cc: Sascha Hauer <s.hauer@pengutronix.de> Cc: Shawn Guo <shawn.guo@linaro.org> Cc: Shi Make-B15407 <B15407@freescale.com> Cc: Stefano Babic <sbabic@denx.de> Cc: Subodh Nijsure <snijsure@grid-net.com> Cc: Wolfgang Denk <wd@denx.de> --- drivers/usb/gadget/Kconfig | 17 ++++++++++ drivers/usb/gadget/Makefile | 1 + drivers/usb/gadget/ci13xxx_mxs.c | 67 ++++++++++++++++++++++++++++++++++++++ 3 files changed, 85 insertions(+) create mode 100644 drivers/usb/gadget/ci13xxx_mxs.c diff --git a/drivers/usb/gadget/Kconfig b/drivers/usb/gadget/Kconfig index 2633f75..1fa6b0d 100644 --- a/drivers/usb/gadget/Kconfig +++ b/drivers/usb/gadget/Kconfig @@ -494,6 +494,23 @@ config USB_CI13XXX_MSM dynamically linked module called "ci13xxx_msm" and force all gadget drivers to also be dynamically linked. +config USB_CI13XXX_MXS + tristate "MIPS USB CI13xxx for i.MX23/28" + depends on ARCH_MXS + select USB_GADGET_DUALSPEED + select USB_IMX_COMPOSITE + help + i.MX SoC has chipidea USB controller. This driver uses + ci13xxx_udc core. + This driver depends on OTG driver for PHY initialization, + clock management, powering up VBUS, and power management. + This driver is not supported on boards like trout which + has an external PHY. + + Say "y" to link the driver statically, or "m" to build a + dynamically linked module called "ci13xxx_mxs" and force all + gadget drivers to also be dynamically linked. + # # LAST -- dummy/emulated controller # diff --git a/drivers/usb/gadget/Makefile b/drivers/usb/gadget/Makefile index b7f6eef..1f159a9 100644 --- a/drivers/usb/gadget/Makefile +++ b/drivers/usb/gadget/Makefile @@ -30,6 +30,7 @@ obj-$(CONFIG_USB_EG20T) += pch_udc.o obj-$(CONFIG_USB_MV_UDC) += mv_udc.o mv_udc-y := mv_udc_core.o obj-$(CONFIG_USB_CI13XXX_MSM) += ci13xxx_msm.o +obj-$(CONFIG_USB_CI13XXX_MXS) += ci13xxx_mxs.o obj-$(CONFIG_USB_FUSB300) += fusb300_udc.o # diff --git a/drivers/usb/gadget/ci13xxx_mxs.c b/drivers/usb/gadget/ci13xxx_mxs.c new file mode 100644 index 0000000..2d99336 --- /dev/null +++ b/drivers/usb/gadget/ci13xxx_mxs.c @@ -0,0 +1,67 @@ +/* Copyright (c) 2010, Code Aurora Forum. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 and + * only version 2 as published by the Free Software Foundation. + */ + +#include <linux/module.h> +#include <linux/platform_device.h> +#include <linux/pm_runtime.h> +#include <linux/usb/ulpi.h> +#include <linux/usb/mxs-usb.h> + +#include "ci13xxx_udc.c" + +#define MSM_USB_BASE (udc->regs) + +static irqreturn_t mxs_udc_irq(int irq, void *data) +{ + return udc_irq(); +} + +static struct ci13xxx_udc_driver ci13xxx_mxs_udc_driver = { + .name = "ci13xxx-mxs", + .flags = CI13XXX_REQUIRE_TRANSCEIVER | + CI13XXX_DISABLE_STREAMING | + CI13XXX_DONT_REGISTER_GADGET, +}; + +static int ci13xxx_mxs_probe(struct platform_device *pdev) +{ + struct imx_otg *data = pdev->dev.platform_data; + int ret; + + ret = devm_request_irq(&pdev->dev, data->irq, mxs_udc_irq, + IRQF_SHARED, pdev->name, pdev); + if (ret < 0) { + dev_err(&pdev->dev, "Failed to request IRQ!\n"); + return ret; + } + + ret = udc_probe(&ci13xxx_mxs_udc_driver, &pdev->dev, data->mem); + if (ret < 0) + dev_err(&pdev->dev, "Failed to probe CI13xxx-mxs!\n"); + + pm_runtime_no_callbacks(&pdev->dev); + pm_runtime_enable(&pdev->dev); + + return ret; +} + +static struct platform_driver ci13xxx_mxs_driver = { + .probe = ci13xxx_mxs_probe, + .driver = { + .name = "ci13xxx-mxs", + }, +}; + +static int __init ci13xxx_mxs_init(void) +{ + return platform_driver_register(&ci13xxx_mxs_driver); +} + +module_init(ci13xxx_mxs_init); + +MODULE_LICENSE("GPL v2"); +MODULE_ALIAS("platform:ci13xxx-mxs"); -- 1.7.10 ^ permalink raw reply related [flat|nested] 28+ messages in thread
* [PATCH 07/11] MXS: Add separate MXS EHCI HCD driver 2012-04-29 22:34 [RFC PATCH 00/11 V6] MXS: Add i.MX28 USB Host driver Marek Vasut ` (5 preceding siblings ...) 2012-04-29 22:34 ` [PATCH 06/11] MXS: Add small registration glue for ci13xxx_udc Marek Vasut @ 2012-04-29 22:34 ` Marek Vasut 2012-04-29 22:34 ` [PATCH 08/11] MXS: Add imx-otg driver Marek Vasut ` (4 subsequent siblings) 11 siblings, 0 replies; 28+ messages in thread From: Marek Vasut @ 2012-04-29 22:34 UTC (permalink / raw) To: linux-arm-kernel This driver will handle i.MX233/i.MX28 and I hope soon i.MX6Q. I tried to keep this separate from the MXC EHCI to avoid further polution of the MXC EHCI, though eventually these two might be merged. NOTE: I still haven't figured out how to enable/disable the disconnection detector, it can't be enabled all the time, so I toggle PHY stuff from this driver, which I doubt is correct. Signed-off-by: Marek Vasut <marex@denx.de> Cc: Chen Peter-B29397 <B29397@freescale.com> Cc: Detlev Zundel <dzu@denx.de> Cc: Fabio Estevam <festevam@gmail.com> Cc: Li Frank-B20596 <B20596@freescale.com> Cc: Linux USB <linux-usb@vger.kernel.org> Cc: Liu JunJie-B08287 <B08287@freescale.com> Cc: Sascha Hauer <s.hauer@pengutronix.de> Cc: Shawn Guo <shawn.guo@linaro.org> Cc: Shi Make-B15407 <B15407@freescale.com> Cc: Stefano Babic <sbabic@denx.de> Cc: Subodh Nijsure <snijsure@grid-net.com> Cc: Wolfgang Denk <wd@denx.de> --- drivers/usb/host/Kconfig | 7 ++ drivers/usb/host/ehci-hcd.c | 5 ++ drivers/usb/host/ehci-mxs.c | 178 +++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 190 insertions(+) create mode 100644 drivers/usb/host/ehci-mxs.c diff --git a/drivers/usb/host/Kconfig b/drivers/usb/host/Kconfig index f788eb8..85ed593 100644 --- a/drivers/usb/host/Kconfig +++ b/drivers/usb/host/Kconfig @@ -148,6 +148,13 @@ config USB_EHCI_MXC ---help--- Variation of ARC USB block used in some Freescale chips. +config USB_EHCI_MXS + bool "Support for Freescale i.MX28 on-chip EHCI USB controller" + depends on USB_EHCI_HCD && ARCH_MXS + select USB_EHCI_ROOT_HUB_TT + ---help--- + Enable USB support for i.MX28. + config USB_EHCI_HCD_OMAP bool "EHCI support for OMAP3 and later chips" depends on USB_EHCI_HCD && ARCH_OMAP diff --git a/drivers/usb/host/ehci-hcd.c b/drivers/usb/host/ehci-hcd.c index 4a3bc5b..16e161c 100644 --- a/drivers/usb/host/ehci-hcd.c +++ b/drivers/usb/host/ehci-hcd.c @@ -1268,6 +1268,11 @@ MODULE_LICENSE ("GPL"); #define PLATFORM_DRIVER ehci_mxc_driver #endif +#ifdef CONFIG_USB_EHCI_MXS +#include "ehci-mxs.c" +#define PLATFORM_DRIVER ehci_mxs_driver +#endif + #ifdef CONFIG_USB_EHCI_SH #include "ehci-sh.c" #define PLATFORM_DRIVER ehci_hcd_sh_driver diff --git a/drivers/usb/host/ehci-mxs.c b/drivers/usb/host/ehci-mxs.c new file mode 100644 index 0000000..4a696b4 --- /dev/null +++ b/drivers/usb/host/ehci-mxs.c @@ -0,0 +1,178 @@ +/* + * Freescale i.MX28 EHCI driver + * + * Copyright (c) 2012 Marek Vasut <marex@denx.de> + * on behalf of DENX Software Engineering GmbH + * + * Based on MXC EHCI driver: + * + * Copyright (c) 2009 Daniel Mack <daniel@caiaq.de> + * Copyright (c) 2008 Sascha Hauer <s.hauer@pengutronix.de>, Pengutronix + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#include <linux/platform_device.h> +#include <linux/delay.h> +#include <linux/usb/otg.h> +#include <linux/usb/ulpi.h> +#include <linux/slab.h> +#include <linux/usb/mxs-usb.h> + +#include <mach/hardware.h> +#include <mach/devices-common.h> +#include <mach/mx28.h> + +#include <asm/mach-types.h> + +/* Called during probe() after chip reset completes */ +static int ehci_mxs_setup(struct usb_hcd *hcd) +{ + struct ehci_hcd *ehci = hcd_to_ehci(hcd); + + hcd->has_tt = 1; + ehci_setup(hcd); + ehci_port_power(ehci, 0); + + return 0; +} + +static const struct hc_driver ehci_mxs_hc_driver = { + .description = hcd_name, + .product_desc = "Freescale i.MX On-Chip EHCI Host Controller", + .hcd_priv_size = sizeof(struct ehci_hcd), + + /* + * Generic hardware linkage + */ + .irq = ehci_irq, + .flags = HCD_USB2 | HCD_MEMORY, + + /* + * Basic lifecycle operations + */ + .reset = ehci_mxs_setup, + .start = ehci_run, + .stop = ehci_stop, + .shutdown = ehci_shutdown, + + /* + * managing i/o requests and associated device resources + */ + .urb_enqueue = ehci_urb_enqueue, + .urb_dequeue = ehci_urb_dequeue, + .endpoint_disable = ehci_endpoint_disable, + .endpoint_reset = ehci_endpoint_reset, + + /* + * scheduling support + */ + .get_frame_number = ehci_get_frame, + + /* + * root hub support + */ + .hub_status_data = ehci_hub_status_data, + .hub_control = ehci_hub_control, + .bus_suspend = ehci_bus_suspend, + .bus_resume = ehci_bus_resume, + .relinquish_port = ehci_relinquish_port, + .port_handed_over = ehci_port_handed_over, + + .clear_tt_buffer_complete = ehci_clear_tt_buffer_complete, +}; + +static int ehci_mxs_drv_probe(struct platform_device *pdev) +{ + struct device *dev = &pdev->dev; + struct imx_otg *data = pdev->dev.platform_data; + struct usb_hcd *hcd; + struct ehci_hcd *ehci; + struct usb_phy *phy; + int ret; + + dev_info(dev, "Initializing i.MX USB Controller\n"); + + if (!data) { + dev_err(dev, "USB Host platform data missing!\n"); + return -ENODEV; + } + + /* This should never fail. */ + phy = usb_get_transceiver(); + if (!phy) { + dev_err(&pdev->dev, "Unable to find transceiver.\n"); + return -ENODEV; + } + + /* Create HCD controller instance. */ + hcd = usb_create_hcd(&ehci_mxs_hc_driver, dev, dev_name(dev)); + if (!hcd) { + dev_err(dev, "Failed to create HCD instance!\n"); + return -ENOMEM; + } + + hcd->rsrc_start = data->mem_res->start; + hcd->rsrc_len = resource_size(data->mem_res); + hcd->regs = data->mem; + hcd->irq = data->irq; + + /* Wait for the controller to stabilize. */ + mdelay(10); + + ehci = hcd_to_ehci(hcd); + + /* EHCI registers start at offset 0x100 */ + ehci->caps = hcd->regs + 0x100; + ehci->regs = hcd->regs + 0x100 + + HC_LENGTH(ehci, ehci_readl(ehci, &ehci->caps->hc_capbase)); + + platform_set_drvdata(pdev, hcd); + + /* Connect this host to the PHY. */ + ret = otg_set_host(phy->otg, &hcd->self); + if (ret < 0) { + dev_err(&pdev->dev, "Unable to set transceiver host\n"); + usb_put_hcd(hcd); + return -ENODEV; + } + + return 0; +} + +static int __exit ehci_mxs_drv_remove(struct platform_device *pdev) +{ + struct usb_hcd *hcd = platform_get_drvdata(pdev); + struct usb_phy *phy = usb_get_transceiver(); + + if (phy) + usb_phy_shutdown(phy); + + usb_remove_hcd(hcd); + usb_put_hcd(hcd); + platform_set_drvdata(pdev, NULL); + + return 0; +} + +static struct platform_driver ehci_mxs_driver = { + .probe = ehci_mxs_drv_probe, + .remove = __exit_p(ehci_mxs_drv_remove), + .driver = { + .name = "mxs-ehci", + }, +}; + +MODULE_ALIAS("platform:mxs-ehci"); -- 1.7.10 ^ permalink raw reply related [flat|nested] 28+ messages in thread
* [PATCH 08/11] MXS: Add imx-otg driver 2012-04-29 22:34 [RFC PATCH 00/11 V6] MXS: Add i.MX28 USB Host driver Marek Vasut ` (6 preceding siblings ...) 2012-04-29 22:34 ` [PATCH 07/11] MXS: Add separate MXS EHCI HCD driver Marek Vasut @ 2012-04-29 22:34 ` Marek Vasut 2012-04-30 6:13 ` Lothar Waßmann 2012-04-29 22:34 ` [PATCH 09/11] MXS: Add USB PHY driver Marek Vasut ` (3 subsequent siblings) 11 siblings, 1 reply; 28+ messages in thread From: Marek Vasut @ 2012-04-29 22:34 UTC (permalink / raw) To: linux-arm-kernel This driver handles claiming of clocks and memory areas. These are later properly delegated to it's child devices, the USB Host (ehci-mxs) and USB Gadget (ci13xxx-mxs). Signed-off-by: Marek Vasut <marex@denx.de> Cc: Chen Peter-B29397 <B29397@freescale.com> Cc: Detlev Zundel <dzu@denx.de> Cc: Fabio Estevam <festevam@gmail.com> Cc: Li Frank-B20596 <B20596@freescale.com> Cc: Linux USB <linux-usb@vger.kernel.org> Cc: Liu JunJie-B08287 <B08287@freescale.com> Cc: Sascha Hauer <s.hauer@pengutronix.de> Cc: Shawn Guo <shawn.guo@linaro.org> Cc: Shi Make-B15407 <B15407@freescale.com> Cc: Stefano Babic <sbabic@denx.de> Cc: Subodh Nijsure <snijsure@grid-net.com> Cc: Wolfgang Denk <wd@denx.de> --- drivers/usb/otg/Kconfig | 6 + drivers/usb/otg/Makefile | 1 + drivers/usb/otg/imx-otg.c | 437 +++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 444 insertions(+) create mode 100644 drivers/usb/otg/imx-otg.c diff --git a/drivers/usb/otg/Kconfig b/drivers/usb/otg/Kconfig index 5c87db0..e7c6325 100644 --- a/drivers/usb/otg/Kconfig +++ b/drivers/usb/otg/Kconfig @@ -116,6 +116,12 @@ config FSL_USB2_OTG help Enable this to support Freescale USB OTG transceiver. +config USB_IMX_COMPOSITE + bool + help + Composite driver that handles clock and memory mapping for + i.MX USB host and USB PHY. + config USB_MV_OTG tristate "Marvell USB OTG support" depends on USB_EHCI_MV && USB_MV_UDC && USB_SUSPEND diff --git a/drivers/usb/otg/Makefile b/drivers/usb/otg/Makefile index 41aa509..7d2c631 100644 --- a/drivers/usb/otg/Makefile +++ b/drivers/usb/otg/Makefile @@ -20,4 +20,5 @@ obj-$(CONFIG_USB_MSM_OTG) += msm_otg.o obj-$(CONFIG_AB8500_USB) += ab8500-usb.o fsl_usb2_otg-objs := fsl_otg.o otg_fsm.o obj-$(CONFIG_FSL_USB2_OTG) += fsl_usb2_otg.o +obj-$(CONFIG_USB_IMX_COMPOSITE) += imx-otg.o obj-$(CONFIG_USB_MV_OTG) += mv_otg.o diff --git a/drivers/usb/otg/imx-otg.c b/drivers/usb/otg/imx-otg.c new file mode 100644 index 0000000..f8bf4c4 --- /dev/null +++ b/drivers/usb/otg/imx-otg.c @@ -0,0 +1,437 @@ +/* + * drivers/usb/otg/imx-otg.c + * + * Freescale i.MX USB composite driver. + * + * Copyright (C) 2012 Marek Vasut <marex@denx.de> + * on behalf of DENX Software Engineering GmbH + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#include <linux/module.h> +#include <linux/platform_device.h> +#include <linux/dma-mapping.h> +#include <linux/slab.h> +#include <linux/delay.h> +#include <linux/usb/mxs-usb.h> +#include <linux/io.h> +#include <linux/gpio.h> + +#include <linux/usb.h> +#include <linux/usb/ch9.h> +#include <linux/usb/otg.h> +#include <linux/usb/gadget.h> +#include <linux/usb/hcd.h> +#include <linux/usb/ehci_def.h> + +#include <mach/common.h> +#include <mach/hardware.h> +#include <mach/devices-common.h> + +/* + * Allocate platform device with the DMA mask, this is borrowed from + * arch/arm/mach-mxs/devices.c + */ +static struct platform_device *__devinit add_platform_device( + const char *name, int id, + const void *data, size_t size_data, u64 dmamask) +{ + int ret = -ENOMEM; + struct platform_device *pdev; + + pdev = platform_device_alloc(name, id); + if (!pdev) + goto err; + + if (dmamask) { + /* + * This memory isn't freed when the device is put, + * I don't have a nice idea for that though. Conceptually + * dma_mask in struct device should not be a pointer. + * See http://thread.gmane.org/gmane.linux.kernel.pci/9081 + */ + pdev->dev.dma_mask = + kmalloc(sizeof(*pdev->dev.dma_mask), GFP_KERNEL); + if (!pdev->dev.dma_mask) + /* ret is still -ENOMEM; */ + goto err; + + *pdev->dev.dma_mask = dmamask; + pdev->dev.coherent_dma_mask = dmamask; + } + + if (data) { + ret = platform_device_add_data(pdev, data, size_data); + if (ret) + goto err; + } + + ret = platform_device_add(pdev); + if (ret) { +err: + if (dmamask) + kfree(pdev->dev.dma_mask); + platform_device_put(pdev); + return ERR_PTR(ret); + } + + return pdev; +} + +static int imx_otg_set_host(struct usb_otg *otg, struct usb_bus *host) +{ + struct imx_otg_priv *priv = container_of(otg, struct imx_otg_priv, otg); + + if (host) { + BUG_ON(otg->host); + otg->host = host; + } else { + BUG_ON(!otg->host); + } + + schedule_work(&priv->work); + + return 0; +} + +static int imx_otg_set_peripheral(struct usb_otg *otg, struct usb_gadget *gg) +{ + struct imx_otg_priv *priv = container_of(otg, struct imx_otg_priv, otg); + + if (gg) { + BUG_ON(otg->gadget); + otg->gadget = gg; + } else { + BUG_ON(!otg->gadget); + } + + schedule_work(&priv->work); + + return 0; +} + +static void imx_otg_work(struct work_struct *w) +{ + struct imx_otg_priv *priv = container_of(w, struct imx_otg_priv, work); + struct usb_hcd *hcd; + +sm: + switch (priv->cur_state) { + case OTG_STATE_A_HOST: + if ((priv->new_state == OTG_STATE_B_PERIPHERAL) || + (priv->new_state == OTG_STATE_UNDEFINED)) { + hcd = bus_to_hcd(priv->otg.host); + usb_remove_hcd(hcd); + priv->cur_state = OTG_STATE_UNDEFINED; + /* Turn off VBUS */ + gpio_set_value(priv->gpio_vbus, + priv->gpio_vbus_inverted); + } + if (priv->new_state == OTG_STATE_B_PERIPHERAL) + goto sm; + break; + case OTG_STATE_B_PERIPHERAL: + if ((priv->new_state == OTG_STATE_A_HOST) || + (priv->new_state == OTG_STATE_UNDEFINED)) { + usb_del_gadget_udc(priv->otg.gadget); + priv->cur_state = OTG_STATE_UNDEFINED; + } + if (priv->new_state == OTG_STATE_A_HOST) + goto sm; + break; + case OTG_STATE_UNDEFINED: + /* Check desired state. */ + switch (priv->new_state) { + case OTG_STATE_A_HOST: + if (!priv->otg.host) + break; + priv->cur_state = priv->new_state; + + /* Turn on VBUS */ + gpio_set_value(priv->gpio_vbus, + !priv->gpio_vbus_inverted); + + hcd = bus_to_hcd(priv->otg.host); + usb_add_hcd(hcd, hcd->irq, IRQF_SHARED); + break; + case OTG_STATE_B_PERIPHERAL: + if (!priv->otg.gadget) + break; + priv->cur_state = priv->new_state; + usb_add_gadget_udc(priv->dev, priv->otg.gadget); + break; + default: + break; + } + break; + + default: + break; + } +} + +static irqreturn_t imx_otg_irq(int irq, void *irqdata) +{ + /* We do nothing during wakeup so far */ + return IRQ_NONE; +} + +static int __devinit imx_usb_probe(struct platform_device *pdev) +{ + struct imx_usb_platform_data *pdata = pdev->dev.platform_data; + struct imx_otg_priv *priv; + struct imx_otg *data; + struct usb_phy *phy; + struct usb_otg *otg; + int ret; + void *retp = NULL; + + if (!pdata) { + dev_err(&pdev->dev, "No platform data supplied!\n"); + return -ENODEV; + } + + phy = usb_get_transceiver(); + if (!phy) + return -EPROBE_DEFER; + + /* + * Until further notice, this claims all necessary resources. + */ + + /* Claim the VBUS GPIO */ + ret = gpio_request_one(pdata->gpio_vbus, GPIOF_DIR_OUT, "USB Power"); + if (ret) { + dev_err(&pdev->dev, "Failed to request USB Power GPIO!"); + ret = -EINVAL; + goto err_alloc_data; + } + + /* Disable the VBUS. */ + gpio_set_value(pdata->gpio_vbus, pdata->gpio_vbus_inverted); + + /* Allocate driver's private date. */ + data = devm_kzalloc(&pdev->dev, sizeof(*data), GFP_KERNEL); + if (!data) { + dev_err(&pdev->dev, "Failed to allocate OTG nodes data!\n"); + ret = -ENOMEM; + goto err_alloc_data; + } + + priv = &data->priv; + + /* Configure the OTG structure. */ + otg = &priv->otg; + otg->phy = phy; + otg->set_host = imx_otg_set_host; + otg->set_peripheral = imx_otg_set_peripheral; + phy->otg = otg; + + priv->dev = &pdev->dev; + priv->gpio_vbus = pdata->gpio_vbus; + priv->gpio_vbus_inverted = pdata->gpio_vbus_inverted; + priv->cur_state = OTG_STATE_UNDEFINED; + priv->new_state = OTG_STATE_UNDEFINED; + + /* We do NOT support OTG yet */ + if (pdata->host_mode && !pdata->gadget_mode) + priv->new_state = OTG_STATE_A_HOST; + else if (pdata->gadget_mode) + priv->new_state = OTG_STATE_B_PERIPHERAL; + + INIT_WORK(&priv->work, imx_otg_work); + + /* Claim the Host clock. */ + data->clk = clk_get(&pdev->dev, "usb"); + if (IS_ERR(data->clk)) { + dev_err(&pdev->dev, "Failed to claim clock for USB Host\n"); + ret = PTR_ERR(data->clk); + goto err_alloc_data; + } + + /* Prepare Host clock. */ + ret = clk_prepare_enable(data->clk); + if (ret) { + dev_err(&pdev->dev, "Failed to enable clock for USB Host.\n"); + goto err_prepare_host_clock; + } + + /* Get memory area for EHCI host from resources. */ + data->mem_res = platform_get_resource(pdev, IORESOURCE_MEM, 0); + if (!data->mem_res) { + dev_err(&pdev->dev, "Specify memory area for this USB Host!\n"); + ret = -ENODEV; + goto err_get_host_resource; + } + + /* Request the memory region for this USB Host. */ + retp = devm_request_mem_region(&pdev->dev, data->mem_res->start, + resource_size(data->mem_res), pdev->name); + if (!retp) { + dev_err(&pdev->dev, "USB Host memory area already in use!\n"); + ret = -EBUSY; + goto err_get_host_resource; + } + + /* Map the memory region for USB Host. */ + data->mem = devm_ioremap(&pdev->dev, data->mem_res->start, + resource_size(data->mem_res)); + if (!data->mem) { + dev_err(&pdev->dev, "Memory mapping of USB Host failed!\n"); + ret = -EFAULT; + goto err_get_host_resource; + } + + /* Get IRQ for EHCI host from resources. */ + data->irq = platform_get_irq(pdev, 0); + if (data->irq < 0) { + dev_err(&pdev->dev, "Specify IRQ for this USB Host!\n"); + ret = -ENODEV; + goto err_get_host_resource; + } + + /* Get IRQ for PHY wakeup from resources. */ + data->irq_wakeup = platform_get_irq(pdev, 1); + if (data->irq_wakeup < 0) { + dev_err(&pdev->dev, "Specify wakeup IRQ for this USB Host!\n"); + ret = -ENODEV; + goto err_get_host_resource; + } + + /* Request the Wakeup IRQ. */ + ret = devm_request_irq(&pdev->dev, data->irq_wakeup, imx_otg_irq, + IRQF_SHARED, "imx-otg-wakeup-irq", data); + if (ret < 0) { + dev_err(&pdev->dev, "Failed to request IRQ!\n"); + goto err_get_host_resource; + } + + /* + * Now finally probe the Host driver! + */ + if (pdata->gadget_mode) { + data->pdev_gadget = add_platform_device("ci13xxx-mxs", -1, + data, sizeof(*data), + DMA_BIT_MASK(32)); + if (!data->pdev_gadget) { + dev_err(&pdev->dev, "Failed registering Host!\n"); + ret = -ENODEV; + goto err_register_gadget; + } + } + + if (pdata->host_mode) { + data->pdev_host = add_platform_device("mxs-ehci", -1, + data, sizeof(*data), + DMA_BIT_MASK(32)); + if (!data->pdev_host) { + dev_err(&pdev->dev, "Failed registering Host!\n"); + ret = -ENODEV; + goto err_get_host_resource; + } + } + + /* + * Initialize the transceiver + */ + phy = usb_get_transceiver(); + if (!phy) { + dev_err(&pdev->dev, "Unable to find transceiver.\n"); + ret = -ENODEV; + goto err_phy; + } + + ret = usb_phy_init(phy); + if (ret < 0) { + dev_err(&pdev->dev, "Unable init transceiver\n"); + ret = -ENODEV; + goto err_phy_init; + } + + /* Kick in the state machine. */ + schedule_work(&priv->work); + + return 0; + +err_phy_init: + if (phy) + usb_put_transceiver(phy); +err_phy: + if (data->pdev_gadget) + platform_device_unregister(data->pdev_gadget); +err_register_gadget: + if (data->pdev_host) + platform_device_unregister(data->pdev_host); +err_get_host_resource: + clk_disable_unprepare(data->clk); +err_prepare_host_clock: + clk_put(data->clk); +err_alloc_data: + return ret; +} + +static int __devexit imx_usb_remove(struct platform_device *pdev) +{ + struct imx_otg *data = platform_get_drvdata(pdev); + struct imx_otg_priv *priv = &data->priv; + + /* Stop the PHY work. */ + cancel_work_sync(&priv->work); + + /* Shut off VBUS. */ + gpio_set_value(priv->gpio_vbus, priv->gpio_vbus_inverted); + gpio_free(priv->gpio_vbus); + + /* Deregister both Gadget and Host driver. */ + if (data->pdev_gadget) + platform_device_unregister(data->pdev_gadget); + + if (data->pdev_host) + platform_device_unregister(data->pdev_host); + + /* Stop the clock. */ + clk_disable_unprepare(data->clk); + clk_put(data->clk); + + return 0; +} + +static struct platform_driver imx_usb_driver = { + .probe = imx_usb_probe, + .remove = __devexit_p(imx_usb_remove), + .driver = { + .name = "imx-otg", + .owner = THIS_MODULE, + }, +}; + +static int __init imx_usb_init(void) +{ + return platform_driver_register(&imx_usb_driver); +} + +static void __exit imx_usb_exit(void) +{ + platform_driver_unregister(&imx_usb_driver); +} + +module_init(imx_usb_init); +module_exit(imx_usb_exit); + +MODULE_ALIAS("platform:imx-otg"); +MODULE_AUTHOR("Marek Vasut <marex@denx.de>"); +MODULE_DESCRIPTION("Freescale i.MX USB composite driver"); +MODULE_LICENSE("GPL"); -- 1.7.10 ^ permalink raw reply related [flat|nested] 28+ messages in thread
* [PATCH 08/11] MXS: Add imx-otg driver 2012-04-29 22:34 ` [PATCH 08/11] MXS: Add imx-otg driver Marek Vasut @ 2012-04-30 6:13 ` Lothar Waßmann 2012-04-30 12:24 ` Marek Vasut 0 siblings, 1 reply; 28+ messages in thread From: Lothar Waßmann @ 2012-04-30 6:13 UTC (permalink / raw) To: linux-arm-kernel Hi, Marek Vasut writes: > This driver handles claiming of clocks and memory areas. These are later > properly delegated to it's child devices, the USB Host (ehci-mxs) and > USB Gadget (ci13xxx-mxs). > [...] There is a conceptual bug in the following code. Did you ever run it? > + INIT_WORK(&priv->work, imx_otg_work); > + [...] > + if (pdata->gadget_mode) { > + data->pdev_gadget = add_platform_device("ci13xxx-mxs", -1, > + data, sizeof(*data), > + DMA_BIT_MASK(32)); This will blow up due to 'BUG_ON(!list_empty(&work->entry));' in kernel/workqueue.c when schedule_work() is called in imx_otg_set_host() or imx_otg_set_peripheral(). platform_add_data() (called from add_platform_device()) will make a copy of the data structure which contains the initialized work queue. INIT_WORK() will have initialized a list_head embedded in the work queue (making 'next' and 'prev' member pointing to the list_head itself). The copied list_head will thus have its members pointing to the original data structure rather than the respective copies and thus fail the 'list_empty()' check. Lothar Wa?mann -- ___________________________________________________________ Ka-Ro electronics GmbH | Pascalstra?e 22 | D - 52076 Aachen Phone: +49 2408 1402-0 | Fax: +49 2408 1402-10 Gesch?ftsf?hrer: Matthias Kaussen Handelsregistereintrag: Amtsgericht Aachen, HRB 4996 www.karo-electronics.de | info at karo-electronics.de ___________________________________________________________ ^ permalink raw reply [flat|nested] 28+ messages in thread
* [PATCH 08/11] MXS: Add imx-otg driver 2012-04-30 6:13 ` Lothar Waßmann @ 2012-04-30 12:24 ` Marek Vasut 0 siblings, 0 replies; 28+ messages in thread From: Marek Vasut @ 2012-04-30 12:24 UTC (permalink / raw) To: linux-arm-kernel Dear Lothar Wa?mann, > Hi, > > Marek Vasut writes: > > This driver handles claiming of clocks and memory areas. These are later > > properly delegated to it's child devices, the USB Host (ehci-mxs) and > > USB Gadget (ci13xxx-mxs). > > [...] > > There is a conceptual bug in the following code. Did you ever run it? Of course, but let's see the problem. > > + INIT_WORK(&priv->work, imx_otg_work); > > + > > [...] > > > + if (pdata->gadget_mode) { > > + data->pdev_gadget = add_platform_device("ci13xxx-mxs", -1, > > + data, sizeof(*data), > > + DMA_BIT_MASK(32)); > > This will blow up due to 'BUG_ON(!list_empty(&work->entry));' > in kernel/workqueue.c when schedule_work() is called in > imx_otg_set_host() or imx_otg_set_peripheral(). > > platform_add_data() (called from add_platform_device()) will make a > copy of the data structure which contains the initialized work queue. > INIT_WORK() will have initialized a list_head embedded in the work > queue (making 'next' and 'prev' member pointing to the list_head > itself). > The copied list_head will thus have its members pointing to the > original data structure rather than the respective copies and thus > fail the 'list_empty()' check. Very nice, good catch, thanks! It never manifested to me, but I'll look into it and fix it in V7. How did you notice this please? > > Lothar Wa?mann Best regards, Marek Vasut ^ permalink raw reply [flat|nested] 28+ messages in thread
* [PATCH 09/11] MXS: Add USB PHY driver 2012-04-29 22:34 [RFC PATCH 00/11 V6] MXS: Add i.MX28 USB Host driver Marek Vasut ` (7 preceding siblings ...) 2012-04-29 22:34 ` [PATCH 08/11] MXS: Add imx-otg driver Marek Vasut @ 2012-04-29 22:34 ` Marek Vasut 2012-04-29 22:34 ` [PATCH 10/11] MXS: Add platform registration hooks for USB EHCI Marek Vasut ` (2 subsequent siblings) 11 siblings, 0 replies; 28+ messages in thread From: Marek Vasut @ 2012-04-29 22:34 UTC (permalink / raw) To: linux-arm-kernel Add driver that controls the built-in USB PHY in the i.MX233/i.MX28. This enables the PHY upon powerup and shuts it down on shutdown. Signed-off-by: Marek Vasut <marex@denx.de> Cc: Chen Peter-B29397 <B29397@freescale.com> Cc: Detlev Zundel <dzu@denx.de> Cc: Fabio Estevam <festevam@gmail.com> Cc: Li Frank-B20596 <B20596@freescale.com> Cc: Linux USB <linux-usb@vger.kernel.org> Cc: Liu JunJie-B08287 <B08287@freescale.com> Cc: Sascha Hauer <s.hauer@pengutronix.de> Cc: Shawn Guo <shawn.guo@linaro.org> Cc: Shi Make-B15407 <B15407@freescale.com> Cc: Stefano Babic <sbabic@denx.de> Cc: Subodh Nijsure <snijsure@grid-net.com> Cc: Wolfgang Denk <wd@denx.de> --- drivers/usb/otg/Kconfig | 10 ++ drivers/usb/otg/Makefile | 1 + drivers/usb/otg/mxs-phy.c | 293 +++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 304 insertions(+) create mode 100644 drivers/usb/otg/mxs-phy.c diff --git a/drivers/usb/otg/Kconfig b/drivers/usb/otg/Kconfig index e7c6325..1de1495 100644 --- a/drivers/usb/otg/Kconfig +++ b/drivers/usb/otg/Kconfig @@ -122,6 +122,16 @@ config USB_IMX_COMPOSITE Composite driver that handles clock and memory mapping for i.MX USB host and USB PHY. +config USB_MXS_PHY + tristate "Freescale i.MX28 USB PHY support" + select USB_OTG_UTILS + select USB_IMX_COMPOSITE + help + Say Y here if you want to build Freescale i.MX28 USB PHY + driver in kernel. + + To compile this driver as a module, choose M here. + config USB_MV_OTG tristate "Marvell USB OTG support" depends on USB_EHCI_MV && USB_MV_UDC && USB_SUSPEND diff --git a/drivers/usb/otg/Makefile b/drivers/usb/otg/Makefile index 7d2c631..b8d7d5c 100644 --- a/drivers/usb/otg/Makefile +++ b/drivers/usb/otg/Makefile @@ -21,4 +21,5 @@ obj-$(CONFIG_AB8500_USB) += ab8500-usb.o fsl_usb2_otg-objs := fsl_otg.o otg_fsm.o obj-$(CONFIG_FSL_USB2_OTG) += fsl_usb2_otg.o obj-$(CONFIG_USB_IMX_COMPOSITE) += imx-otg.o +obj-$(CONFIG_USB_MXS_PHY) += mxs-phy.o obj-$(CONFIG_USB_MV_OTG) += mv_otg.o diff --git a/drivers/usb/otg/mxs-phy.c b/drivers/usb/otg/mxs-phy.c new file mode 100644 index 0000000..334b095 --- /dev/null +++ b/drivers/usb/otg/mxs-phy.c @@ -0,0 +1,293 @@ +/* + * drivers/usb/otg/mxs-phy.c + * + * Freescale i.MX28 USB PHY driver. + * + * Copyright (C) 2012 Marek Vasut <marex@denx.de> + * on behalf of DENX Software Engineering GmbH + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#include <linux/module.h> +#include <linux/platform_device.h> +#include <linux/dma-mapping.h> +#include <linux/slab.h> +#include <linux/delay.h> +#include <linux/usb/mxs-usb.h> + +#include <linux/usb.h> +#include <linux/usb/ch9.h> +#include <linux/usb/otg.h> +#include <linux/usb/gadget.h> +#include <linux/usb/hcd.h> +#include <linux/usb/ehci_def.h> + +#include <mach/common.h> +#include <mach/hardware.h> +#include <mach/devices-common.h> +#include <mach/mx28.h> + +struct mxs_usb_phy { + struct usb_phy phy; + struct clk *clk; + int irq; + uint32_t status; +}; + +static int mxs_usb_phy_init(struct usb_phy *x) +{ + struct mxs_usb_phy *phy = container_of(x, struct mxs_usb_phy, phy); + uint32_t val; + + /* Enable clock to the PHY. */ + clk_enable(phy->clk); + + /* Reset the PHY block. */ + mxs_reset_block(x->io_priv + HW_USBPHY_CTRL); + + /* Power up the PHY. */ + writel(0, x->io_priv + HW_USBPHY_PWD); + + /* Clear the wakeup IRQ before enabling them below. */ + writel(BM_USBPHY_CTRL_RESUME_IRQ | BM_USBPHY_CTRL_WAKEUP_IRQ, + x->io_priv + HW_USBPHY_CTRL_CLR); + + /* Enable FS/LS compatibility and wakeup IRQs. */ + val = BM_USBPHY_CTRL_ENUTMILEVEL2 | BM_USBPHY_CTRL_ENUTMILEVEL3 | + BM_USBPHY_CTRL_ENIRQWAKEUP; + + /* Enable IRQ sources. */ + val |= BM_USBPHY_CTRL_ENIDCHG_WKUP | BM_USBPHY_CTRL_ENDPDMCHG_WKUP | + BM_USBPHY_CTRL_ENVBUSCHG_WKUP; + + writel(val, x->io_priv + HW_USBPHY_CTRL_SET); + + return 0; +} + +static void mxs_usb_phy_shutdown(struct usb_phy *x) +{ + struct mxs_usb_phy *phy = container_of(x, struct mxs_usb_phy, phy); + uint32_t val; + + /* Clear the wakeup IRQ before disabling them below. */ + writel(BM_USBPHY_CTRL_RESUME_IRQ | BM_USBPHY_CTRL_WAKEUP_IRQ, + x->io_priv + HW_USBPHY_CTRL_CLR); + + /* Disable FS/LS compatibility and wakeup IRQs. */ + val = BM_USBPHY_CTRL_ENUTMILEVEL2 | BM_USBPHY_CTRL_ENUTMILEVEL3 | + BM_USBPHY_CTRL_ENIRQWAKEUP; + + /* Disable IRQ sources. */ + val |= BM_USBPHY_CTRL_ENIDCHG_WKUP | BM_USBPHY_CTRL_ENDPDMCHG_WKUP | + BM_USBPHY_CTRL_ENVBUSCHG_WKUP; + + writel(val, x->io_priv + HW_USBPHY_CTRL_CLR); + + /* + * The interrupt must be disabled for at least 3 cycles of the + * standby clock (32kHz), that is 0.094 ms. + */ + udelay(100); + + /* Gate off the PHY. */ + writel(BM_USBPHY_CTRL_CLKGATE, x->io_priv + HW_USBPHY_CTRL_SET); + + /* Disable clock to the PHY. */ + clk_disable(phy->clk); +} + +static irqreturn_t mxs_phy_irq(int irq, void *irqdata) +{ + struct mxs_usb_phy *phy = irqdata; + struct usb_phy *x = &phy->phy; + struct usb_otg *otg = x->otg; + struct imx_otg_priv *priv = container_of(otg, struct imx_otg_priv, otg); + struct imx_otg *data = container_of(priv, struct imx_otg, priv); + uint32_t status; + + if (otg->host) { + status = readl(data->mem + 0x144); + if (~(phy->status ^ status) & STS_PCD) + return IRQ_NONE; + + phy->status = status; + + if (phy->status & STS_PCD) { + writel(BM_USBPHY_CTRL_ENHOSTDISCONDETECT, + x->io_priv + HW_USBPHY_CTRL_CLR); + } else { + writel(BM_USBPHY_CTRL_ENHOSTDISCONDETECT, + x->io_priv + HW_USBPHY_CTRL_SET); + } + } + + return IRQ_NONE; +} + +static int __devinit mxs_phy_probe(struct platform_device *pdev) +{ + struct imx_usb_platform_data *pdata = pdev->dev.platform_data; + struct mxs_usb_phy *phy; + struct resource *mem_res; + void *retp; + int ret; + + if (!pdata) { + dev_err(&pdev->dev, "No platform data supplied!\n"); + ret = -ENODEV; + goto err_pdata; + } + + /* Allocate PHY driver's private data. */ + phy = devm_kzalloc(&pdev->dev, sizeof(*phy), GFP_KERNEL); + if (!phy) { + dev_err(&pdev->dev, "Failed to allocate USB PHY structure!\n"); + ret = -ENOMEM; + goto err_pdata; + } + + /* Get memory area for PHY from resources. */ + mem_res = platform_get_resource(pdev, IORESOURCE_MEM, 0); + if (!mem_res) { + dev_err(&pdev->dev, "Specify memory area for this USB PHY!\n"); + ret = -ENODEV; + goto err_pdata; + } + + /* Request the memory region for this USB PHY. */ + retp = devm_request_mem_region(&pdev->dev, mem_res->start, + resource_size(mem_res), pdev->name); + if (!retp) { + dev_err(&pdev->dev, "USB PHY memory area already in use!\n"); + ret = -EBUSY; + goto err_pdata; + } + + /* Map the memory region for USB PHY. */ + phy->phy.io_priv = devm_ioremap(&pdev->dev, mem_res->start, + resource_size(mem_res)); + if (!phy->phy.io_priv) { + dev_err(&pdev->dev, "Memory mapping of USB PHY failed!\n"); + ret = -EFAULT; + goto err_pdata; + } + + /* Get IRQ for PHY from resources. */ + phy->irq = platform_get_irq(pdev, 0); + if (phy->irq < 0) { + dev_err(&pdev->dev, "Specify IRQ for this USB Host!\n"); + ret = -ENODEV; + goto err_pdata; + } + + /* Request the PHY IRQ. */ + ret = devm_request_irq(&pdev->dev, phy->irq, mxs_phy_irq, + IRQF_SHARED, "mxs-phy-usb-irq", phy); + if (ret < 0) { + dev_err(&pdev->dev, "Failed to request IRQ!\n"); + goto err_pdata; + } + + /* Claim the PHY clock. */ + phy->clk = clk_get(&pdev->dev, "phy"); + if (!phy->clk) { + dev_err(&pdev->dev, "Failed to claim clock for USB PHY!\n"); + ret = PTR_ERR(phy->clk); + goto err_pdata; + } + + /* Prepare PHY clock. */ + ret = clk_prepare(phy->clk); + if (ret) { + dev_err(&pdev->dev, "Failed to prepare clock for USB PHY!\n"); + goto err_prepare_phy_clock; + } + + /* Setup the PHY structures. */ + phy->phy.dev = &pdev->dev; + phy->phy.label = "mxs-usb-phy"; + phy->phy.init = mxs_usb_phy_init; + phy->phy.shutdown = mxs_usb_phy_shutdown; + phy->phy.state = OTG_STATE_UNDEFINED; + + platform_set_drvdata(pdev, phy); + + ATOMIC_INIT_NOTIFIER_HEAD(&phy->phy.notifier); + + /* Register the transceiver with kernel. */ + ret = usb_set_transceiver(&phy->phy); + if (ret) { + dev_err(&pdev->dev, "Can't register transceiver, (%d)\n", ret); + goto err_set_transceiver; + } + + return 0; + +err_set_transceiver: + clk_unprepare(phy->clk); +err_prepare_phy_clock: + clk_put(phy->clk); +err_pdata: + return ret; +} + +static int __devexit mxs_phy_remove(struct platform_device *pdev) +{ + struct mxs_usb_phy *phy = platform_get_drvdata(pdev); + + /* Power down the PHY. */ + mxs_usb_phy_shutdown(&phy->phy); + + /* Remove the transceiver. */ + usb_set_transceiver(NULL); + + /* Stop the PHY clock. */ + clk_disable_unprepare(phy->clk); + clk_put(phy->clk); + + /* Free the rest. */ + platform_set_drvdata(pdev, NULL); + + return 0; +} + +static struct platform_driver mxs_phy_driver = { + .probe = mxs_phy_probe, + .remove = __devexit_p(mxs_phy_remove), + .driver = { + .name = "mxs-usb-phy", + .owner = THIS_MODULE, + }, +}; + +static int __init mxs_phy_init(void) +{ + return platform_driver_register(&mxs_phy_driver); +} + +static void __exit mxs_phy_exit(void) +{ + platform_driver_unregister(&mxs_phy_driver); +} + +arch_initcall(mxs_phy_init); +module_exit(mxs_phy_exit); + +MODULE_ALIAS("platform:mxs-usb-phy"); +MODULE_AUTHOR("Marek Vasut <marex@denx.de>"); +MODULE_DESCRIPTION("Freescale i.MX28 USB PHY driver"); +MODULE_LICENSE("GPL"); -- 1.7.10 ^ permalink raw reply related [flat|nested] 28+ messages in thread
* [PATCH 10/11] MXS: Add platform registration hooks for USB EHCI 2012-04-29 22:34 [RFC PATCH 00/11 V6] MXS: Add i.MX28 USB Host driver Marek Vasut ` (8 preceding siblings ...) 2012-04-29 22:34 ` [PATCH 09/11] MXS: Add USB PHY driver Marek Vasut @ 2012-04-29 22:34 ` Marek Vasut 2012-04-29 22:34 ` [PATCH 11/11] MXS: Enable USB on M28EVK Marek Vasut 2012-04-29 23:00 ` [RFC PATCH 00/11 V6] MXS: Add i.MX28 USB Host driver Marek Vasut 11 siblings, 0 replies; 28+ messages in thread From: Marek Vasut @ 2012-04-29 22:34 UTC (permalink / raw) To: linux-arm-kernel Based on code by: Tony Lin <tony.lin@freescale.com> Signed-off-by: Marek Vasut <marex@denx.de> Cc: Chen Peter-B29397 <B29397@freescale.com> Cc: Detlev Zundel <dzu@denx.de> Cc: Fabio Estevam <festevam@gmail.com> Cc: Li Frank-B20596 <B20596@freescale.com> Cc: Linux USB <linux-usb@vger.kernel.org> Cc: Liu JunJie-B08287 <B08287@freescale.com> Cc: Sascha Hauer <s.hauer@pengutronix.de> Cc: Shawn Guo <shawn.guo@linaro.org> Cc: Shi Make-B15407 <B15407@freescale.com> Cc: Stefano Babic <sbabic@denx.de> Cc: Subodh Nijsure <snijsure@grid-net.com> Cc: Wolfgang Denk <wd@denx.de> --- arch/arm/mach-mxs/devices-mx28.h | 5 ++ arch/arm/mach-mxs/devices/Kconfig | 3 + arch/arm/mach-mxs/devices/Makefile | 1 + arch/arm/mach-mxs/devices/platform-usb.c | 89 +++++++++++++++++++++++ arch/arm/mach-mxs/include/mach/devices-common.h | 13 ++++ 5 files changed, 111 insertions(+) create mode 100644 arch/arm/mach-mxs/devices/platform-usb.c diff --git a/arch/arm/mach-mxs/devices-mx28.h b/arch/arm/mach-mxs/devices-mx28.h index 9dbeae1..04a9120 100644 --- a/arch/arm/mach-mxs/devices-mx28.h +++ b/arch/arm/mach-mxs/devices-mx28.h @@ -11,6 +11,7 @@ #include <mach/mx28.h> #include <mach/devices-common.h> #include <mach/mxsfb.h> +#include <linux/usb/mxs-usb.h> extern const struct amba_device mx28_duart_device __initconst; #define mx28_add_duart() \ @@ -47,6 +48,10 @@ extern const struct mxs_mxs_mmc_data mx28_mxs_mmc_data[] __initconst; #define mx28_add_mxs_pwm(id) mxs_add_mxs_pwm(MX28_PWM_BASE_ADDR, id) +extern const struct mxs_usbh_data mx28_mxs_usbh_data[] __initconst; +#define mx28_add_mxs_usbh(id, pdata) \ + mxs_add_mxs_usbh(&mx28_mxs_usbh_data[id], pdata) + struct platform_device *__init mx28_add_mxsfb( const struct mxsfb_platform_data *pdata); diff --git a/arch/arm/mach-mxs/devices/Kconfig b/arch/arm/mach-mxs/devices/Kconfig index b8913df..f6709bc 100644 --- a/arch/arm/mach-mxs/devices/Kconfig +++ b/arch/arm/mach-mxs/devices/Kconfig @@ -32,3 +32,6 @@ config MXS_HAVE_PLATFORM_MXS_SAIF config MXS_HAVE_PLATFORM_RTC_STMP3XXX bool + +config MXS_HAVE_PLATFORM_USB + bool diff --git a/arch/arm/mach-mxs/devices/Makefile b/arch/arm/mach-mxs/devices/Makefile index c8f5c95..be4cc9e 100644 --- a/arch/arm/mach-mxs/devices/Makefile +++ b/arch/arm/mach-mxs/devices/Makefile @@ -11,3 +11,4 @@ obj-y += platform-gpio-mxs.o obj-$(CONFIG_MXS_HAVE_PLATFORM_MXSFB) += platform-mxsfb.o obj-$(CONFIG_MXS_HAVE_PLATFORM_MXS_SAIF) += platform-mxs-saif.o obj-$(CONFIG_MXS_HAVE_PLATFORM_RTC_STMP3XXX) += platform-rtc-stmp3xxx.o +obj-$(CONFIG_MXS_HAVE_PLATFORM_USB) += platform-usb.o diff --git a/arch/arm/mach-mxs/devices/platform-usb.c b/arch/arm/mach-mxs/devices/platform-usb.c new file mode 100644 index 0000000..47601972 --- /dev/null +++ b/arch/arm/mach-mxs/devices/platform-usb.c @@ -0,0 +1,89 @@ +/* + * Copyright 2011 Freescale Semiconductor, Inc. All Rights Reserved. + * + * This program is free software; you can redistribute it and/or modify it under + * the terms of the GNU General Public License version 2 as published by the + * Free Software Foundation. + */ + +#include <linux/compiler.h> +#include <linux/err.h> +#include <linux/init.h> +#include <linux/fsl_devices.h> +#include <linux/usb/mxs-usb.h> + +#include <mach/mx23.h> +#include <mach/mx28.h> +#include <mach/devices-common.h> + +#define mxs_usbh_data_entry_single(soc, _id, hwid) \ + { \ + .id = _id, \ + .usb_irq = soc ## _INT_USB ## hwid, \ + .phy_irq = soc ## _INT_USB ## hwid ## _WAKEUP, \ + .usb_iobase = soc ## _USBCTRL ## hwid ## _BASE_ADDR, \ + .phy_iobase = soc ## _USBPHY ## hwid ## _BASE_ADDR, \ + } + +#define mxs_usbh_data_entry(soc, _id, hwid) \ + [_id] = mxs_usbh_data_entry_single(soc, _id, hwid) + +#ifdef CONFIG_SOC_IMX23 +const struct mxs_usbh_data mx23_mxs_usbh_data[] __initconst = { + mxs_usbh_data_entry(MX23, 0, 0), +}; +#endif + +#ifdef CONFIG_SOC_IMX28 +const struct mxs_usbh_data mx28_mxs_usbh_data[] __initconst = { + mxs_usbh_data_entry(MX28, 0, 0), + mxs_usbh_data_entry(MX28, 1, 1), +}; +#endif + +void __init mxs_add_mxs_usbh(const struct mxs_usbh_data *data, + const struct imx_usb_platform_data *pdata) +{ + struct platform_device *pdev; + struct resource phy_res[] = { + { + .start = data->phy_iobase, + .end = data->phy_iobase + SZ_256 - 1, + .flags = IORESOURCE_MEM, + }, { + .start = data->usb_irq, + .end = data->usb_irq, + .flags = IORESOURCE_IRQ, + }, + }; + + struct resource usb_res[] = { + { + .start = data->usb_iobase, + .end = data->usb_iobase + SZ_64K - 1, + .flags = IORESOURCE_MEM, + }, { + .start = data->usb_irq, + .end = data->usb_irq, + .flags = IORESOURCE_IRQ, + }, { + .start = data->phy_irq, + .end = data->phy_irq, + .flags = IORESOURCE_IRQ, + }, + }; + + pdev = mxs_add_platform_device_dmamask("mxs-usb-phy", data->id, + phy_res, ARRAY_SIZE(phy_res), + pdata, sizeof(*pdata), + DMA_BIT_MASK(32)); + if (!pdev) + pr_err("Failed to register USB PHY driver!\n"); + + pdev = mxs_add_platform_device_dmamask("imx-otg", data->id, + usb_res, ARRAY_SIZE(usb_res), + pdata, sizeof(*pdata), + DMA_BIT_MASK(32)); + if (!pdev) + pr_err("Failed to register USB Host driver!\n"); +} diff --git a/arch/arm/mach-mxs/include/mach/devices-common.h b/arch/arm/mach-mxs/include/mach/devices-common.h index f2e3839..b4a65ab 100644 --- a/arch/arm/mach-mxs/include/mach/devices-common.h +++ b/arch/arm/mach-mxs/include/mach/devices-common.h @@ -10,6 +10,8 @@ #include <linux/platform_device.h> #include <linux/init.h> #include <linux/amba/bus.h> +#include <linux/fsl_devices.h> +#include <linux/usb/mxs-usb.h> extern struct device mxs_apbh_bus; @@ -42,6 +44,17 @@ struct mxs_auart_data { struct platform_device *__init mxs_add_auart( const struct mxs_auart_data *data); +/* usb host */ +struct mxs_usbh_data { + int id; + resource_size_t usb_irq; + resource_size_t phy_irq; + resource_size_t usb_iobase; + resource_size_t phy_iobase; +}; +void __init mxs_add_mxs_usbh(const struct mxs_usbh_data *data, + const struct imx_usb_platform_data *pdata); + /* fec */ #include <linux/fec.h> struct mxs_fec_data { -- 1.7.10 ^ permalink raw reply related [flat|nested] 28+ messages in thread
* [PATCH 11/11] MXS: Enable USB on M28EVK 2012-04-29 22:34 [RFC PATCH 00/11 V6] MXS: Add i.MX28 USB Host driver Marek Vasut ` (9 preceding siblings ...) 2012-04-29 22:34 ` [PATCH 10/11] MXS: Add platform registration hooks for USB EHCI Marek Vasut @ 2012-04-29 22:34 ` Marek Vasut 2012-04-29 23:00 ` [RFC PATCH 00/11 V6] MXS: Add i.MX28 USB Host driver Marek Vasut 11 siblings, 0 replies; 28+ messages in thread From: Marek Vasut @ 2012-04-29 22:34 UTC (permalink / raw) To: linux-arm-kernel Enable the second USB port on M28EVK board. Signed-off-by: Marek Vasut <marex@denx.de> Cc: Chen Peter-B29397 <B29397@freescale.com> Cc: Detlev Zundel <dzu@denx.de> Cc: Fabio Estevam <festevam@gmail.com> Cc: Li Frank-B20596 <B20596@freescale.com> Cc: Linux USB <linux-usb@vger.kernel.org> Cc: Liu JunJie-B08287 <B08287@freescale.com> Cc: Sascha Hauer <s.hauer@pengutronix.de> Cc: Shawn Guo <shawn.guo@linaro.org> Cc: Shi Make-B15407 <B15407@freescale.com> Cc: Stefano Babic <sbabic@denx.de> Cc: Subodh Nijsure <snijsure@grid-net.com> Cc: Wolfgang Denk <wd@denx.de> --- arch/arm/mach-mxs/Kconfig | 2 ++ arch/arm/mach-mxs/mach-m28evk.c | 21 +++++++++++++++++++++ 2 files changed, 23 insertions(+) diff --git a/arch/arm/mach-mxs/Kconfig b/arch/arm/mach-mxs/Kconfig index c57f996..05f6e84 100644 --- a/arch/arm/mach-mxs/Kconfig +++ b/arch/arm/mach-mxs/Kconfig @@ -81,6 +81,8 @@ config MODULE_M28 select MXS_HAVE_PLATFORM_MXS_I2C select MXS_HAVE_PLATFORM_MXS_MMC select MXS_HAVE_PLATFORM_MXSFB + select MXS_HAVE_PLATFORM_USB + select USB_ARCH_HAS_EHCI select MXS_OCOTP config MODULE_APX4 diff --git a/arch/arm/mach-mxs/mach-m28evk.c b/arch/arm/mach-mxs/mach-m28evk.c index 06d7996..fe00921 100644 --- a/arch/arm/mach-mxs/mach-m28evk.c +++ b/arch/arm/mach-mxs/mach-m28evk.c @@ -39,6 +39,8 @@ #define MX28EVK_BL_ENABLE MXS_GPIO_NR(3, 18) #define M28EVK_LCD_ENABLE MXS_GPIO_NR(3, 28) +#define M28EVK_USB_ENABLE MXS_GPIO_NR(3, 13) +#define M28EVK_USBOTG_ENABLE MXS_GPIO_NR(3, 12) #define MX28EVK_MMC0_WRITE_PROTECT MXS_GPIO_NR(2, 12) #define MX28EVK_MMC1_WRITE_PROTECT MXS_GPIO_NR(0, 28) @@ -210,6 +212,16 @@ static const iomux_cfg_t m28evk_pads[] __initconst = { /* Backlight */ MX28_PAD_PWM3__GPIO_3_28 | MXS_PAD_CTRL, + + /* USB */ + MX28_PAD_SSP2_SS2__USB0_OVERCURRENT, + MX28_PAD_SSP2_SS1__USB1_OVERCURRENT, + MX28_PAD_PWM2__USB0_ID | + MXS_PAD_12MA | MXS_PAD_3V3 | MXS_PAD_PULLUP, + MX28_PAD_AUART3_TX__GPIO_3_13 | + MXS_PAD_12MA | MXS_PAD_3V3 | MXS_PAD_PULLUP, + MX28_PAD_AUART3_RX__GPIO_3_12 | + MXS_PAD_12MA | MXS_PAD_3V3 | MXS_PAD_PULLUP, }; /* led */ @@ -317,6 +329,13 @@ static struct mxs_mmc_platform_data m28evk_mmc_pdata[] __initdata = { }, }; +static struct imx_usb_platform_data m28_usb_data = { + .gpio_vbus = M28EVK_USBOTG_ENABLE, + .gpio_vbus_inverted = 1, + .gadget_mode = 0, + .host_mode = 1, +}; + static void __init m28evk_init(void) { mxs_iomux_setup_multiple_pads(m28evk_pads, ARRAY_SIZE(m28evk_pads)); @@ -344,6 +363,8 @@ static void __init m28evk_init(void) mx28_add_mxs_i2c(0); i2c_register_board_info(0, m28_stk5v3_i2c_boardinfo, ARRAY_SIZE(m28_stk5v3_i2c_boardinfo)); + + mx28_add_mxs_usbh(0, &m28_usb_data); } static void __init m28evk_timer_init(void) -- 1.7.10 ^ permalink raw reply related [flat|nested] 28+ messages in thread
* [RFC PATCH 00/11 V6] MXS: Add i.MX28 USB Host driver 2012-04-29 22:34 [RFC PATCH 00/11 V6] MXS: Add i.MX28 USB Host driver Marek Vasut ` (10 preceding siblings ...) 2012-04-29 22:34 ` [PATCH 11/11] MXS: Enable USB on M28EVK Marek Vasut @ 2012-04-29 23:00 ` Marek Vasut 11 siblings, 0 replies; 28+ messages in thread From: Marek Vasut @ 2012-04-29 23:00 UTC (permalink / raw) To: linux-arm-kernel > This patchset introduces the USB Host driver for i.MX28 CPU, utilising the > generic USB PHY infrastructure. Also added is glue code for CI13xxx driver, > to allow device mode. This patchset still does NOT support OTG mode, the > device/host mode is selected via platform data. I also pushed the patchset here: http://git.kernel.org/?p=linux/kernel/git/marex/linux-2.6.git;a=shortlog;h=refs/heads/mxs- usb > > V2: Introduce stub imx-usb driver that then registers the PHY and EHCI > drivers. V3: Add the HCD on demand based on the PHY's state (only add HCD > if it's host). Currently, only the HOST mode is supported. > V4: * Introduce ci13xxx gadget glue > * Reorder patches in a more sensible order > * Introduce platform data, containing VBUS GPIO and port mode > (device/gadget) * Rename imx-usb to imx-otg > * Drop mx28evk usb host patch > * Use more devm_ function > * Rework the mxs-phy to register the same interrupt as ehci-mxs (and > effectivelly kill bogus otg_set_vbus() call from ehci-mxs ; use > standard ehci irq handling in ehci-mxs) > V5: * Finally move OTG IRQ handling into imx-otg > * Move imx_otg_set_{host,peripheral}() into imx-otg > * Move imx_otg_work() into imx-otg driver (now it all makes sense, > yay!) V6: Do PHY-specific job inside the PHY driver > > Marek Vasut (11): > MXS: Make clk_disable return integer > MXS: Add USB EHCI and USB PHY clock handling > MXS: Fixup i.MX233 USB base address name > MXS: Add data shared between imx-otg and EHCI driver > MXS: Modify the ci13xxx_udc to avoid adding UDC > MXS: Add small registration glue for ci13xxx_udc > MXS: Add separate MXS EHCI HCD driver > MXS: Add imx-otg driver > MXS: Add USB PHY driver > MXS: Add platform registration hooks for USB EHCI > MXS: Enable USB on M28EVK > > arch/arm/mach-mxs/Kconfig | 2 + > arch/arm/mach-mxs/clock-mx28.c | 28 +- > arch/arm/mach-mxs/devices-mx28.h | 5 + > arch/arm/mach-mxs/devices/Kconfig | 3 + > arch/arm/mach-mxs/devices/Makefile | 1 + > arch/arm/mach-mxs/devices/platform-usb.c | 89 +++++ > arch/arm/mach-mxs/include/mach/clock.h | 2 +- > arch/arm/mach-mxs/include/mach/devices-common.h | 13 + > arch/arm/mach-mxs/include/mach/mx23.h | 8 +- > arch/arm/mach-mxs/mach-m28evk.c | 21 ++ > drivers/usb/gadget/Kconfig | 17 + > drivers/usb/gadget/Makefile | 1 + > drivers/usb/gadget/ci13xxx_mxs.c | 67 ++++ > drivers/usb/gadget/ci13xxx_udc.c | 12 +- > drivers/usb/gadget/ci13xxx_udc.h | 1 + > drivers/usb/host/Kconfig | 7 + > drivers/usb/host/ehci-hcd.c | 5 + > drivers/usb/host/ehci-mxs.c | 178 +++++++++ > drivers/usb/otg/Kconfig | 16 + > drivers/usb/otg/Makefile | 2 + > drivers/usb/otg/imx-otg.c | 437 > +++++++++++++++++++++++ drivers/usb/otg/mxs-phy.c | > 293 +++++++++++++++ include/linux/usb/mxs-usb.h | 94 > +++++ > 23 files changed, 1289 insertions(+), 13 deletions(-) > create mode 100644 arch/arm/mach-mxs/devices/platform-usb.c > create mode 100644 drivers/usb/gadget/ci13xxx_mxs.c > create mode 100644 drivers/usb/host/ehci-mxs.c > create mode 100644 drivers/usb/otg/imx-otg.c > create mode 100644 drivers/usb/otg/mxs-phy.c > create mode 100644 include/linux/usb/mxs-usb.h > > Cc: Chen Peter-B29397 <B29397@freescale.com> > Cc: Detlev Zundel <dzu@denx.de> > Cc: Fabio Estevam <festevam@gmail.com> > Cc: Li Frank-B20596 <B20596@freescale.com> > Cc: Linux USB <linux-usb@vger.kernel.org> > Cc: Liu JunJie-B08287 <B08287@freescale.com> > Cc: Sascha Hauer <s.hauer@pengutronix.de> > Cc: Shawn Guo <shawn.guo@linaro.org> > Cc: Shi Make-B15407 <B15407@freescale.com> > Cc: Stefano Babic <sbabic@denx.de> > Cc: Subodh Nijsure <snijsure@grid-net.com> > Cc: Wolfgang Denk <wd@denx.de> Best regards, Marek Vasut ^ permalink raw reply [flat|nested] 28+ messages in thread
* [RFC PATCH 00/11 V7] MXS: Add i.MX28 USB Host driver @ 2012-05-01 1:55 Marek Vasut 2012-05-01 1:56 ` [PATCH 08/11] MXS: Add imx-otg driver Marek Vasut 0 siblings, 1 reply; 28+ messages in thread From: Marek Vasut @ 2012-05-01 1:55 UTC (permalink / raw) To: linux-arm-kernel This patchset introduces the USB Host driver for i.MX28 CPU, utilising the generic USB PHY infrastructure. Also added is glue code for CI13xxx driver, to allow device mode. This patchset still does NOT support OTG mode, the device/host mode is selected via platform data. NOTE: This patchset is also available at: http://git.kernel.org/?p=linux/kernel/git/marex/linux-2.6.git;a=shortlog;h=refs/heads/mxs-usb V2: Introduce stub imx-usb driver that then registers the PHY and EHCI drivers. V3: Add the HCD on demand based on the PHY's state (only add HCD if it's host). Currently, only the HOST mode is supported. V4: * Introduce ci13xxx gadget glue * Reorder patches in a more sensible order * Introduce platform data, containing VBUS GPIO and port mode (device/gadget) * Rename imx-usb to imx-otg * Drop mx28evk usb host patch * Use more devm_ function * Rework the mxs-phy to register the same interrupt as ehci-mxs (and effectivelly kill bogus otg_set_vbus() call from ehci-mxs ; use standard ehci irq handling in ehci-mxs) V5: * Finally move OTG IRQ handling into imx-otg * Move imx_otg_set_{host,peripheral}() into imx-otg * Move imx_otg_work() into imx-otg driver (now it all makes sense, yay!) V6: Do PHY-specific job inside the PHY driver V7: * Pass only necessary data to the drivers registered by imx-otg (memory, irq, pointer to imx-otg device). This should fix issue pointed out by Lothar Wassmann. * Have single IRQ handler in imx-otg, which then calls host/gadget IRQ handlers only if they're registered via imx_otg_set_irq_handler() call, depending on the current state of the OTG. Marek Vasut (11): MXS: Make clk_disable return integer MXS: Add USB EHCI and USB PHY clock handling MXS: Fixup i.MX233 USB base address name MXS: Add data shared between imx-otg and EHCI driver MXS: Modify the ci13xxx_udc to avoid adding UDC MXS: Add small registration glue for ci13xxx_udc MXS: Add separate MXS EHCI HCD driver MXS: Add imx-otg driver MXS: Add USB PHY driver MXS: Add platform registration hooks for USB EHCI MXS: Enable USB on M28EVK arch/arm/mach-mxs/Kconfig | 2 + arch/arm/mach-mxs/clock-mx28.c | 28 +- arch/arm/mach-mxs/devices-mx28.h | 5 + arch/arm/mach-mxs/devices/Kconfig | 3 + arch/arm/mach-mxs/devices/Makefile | 1 + arch/arm/mach-mxs/devices/platform-usb.c | 89 +++++ arch/arm/mach-mxs/include/mach/clock.h | 2 +- arch/arm/mach-mxs/include/mach/devices-common.h | 13 + arch/arm/mach-mxs/include/mach/mx23.h | 8 +- arch/arm/mach-mxs/mach-m28evk.c | 21 + drivers/usb/gadget/Kconfig | 17 + drivers/usb/gadget/Makefile | 1 + drivers/usb/gadget/ci13xxx_mxs.c | 73 ++++ drivers/usb/gadget/ci13xxx_udc.c | 12 +- drivers/usb/gadget/ci13xxx_udc.h | 1 + drivers/usb/host/Kconfig | 7 + drivers/usb/host/ehci-hcd.c | 5 + drivers/usb/host/ehci-mxs.c | 187 +++++++++ drivers/usb/otg/Kconfig | 16 + drivers/usb/otg/Makefile | 2 + drivers/usb/otg/imx-otg.c | 480 +++++++++++++++++++++++ drivers/usb/otg/mxs-phy.c | 328 ++++++++++++++++ include/linux/usb/mxs-usb.h | 72 ++++ 23 files changed, 1360 insertions(+), 13 deletions(-) create mode 100644 arch/arm/mach-mxs/devices/platform-usb.c create mode 100644 drivers/usb/gadget/ci13xxx_mxs.c create mode 100644 drivers/usb/host/ehci-mxs.c create mode 100644 drivers/usb/otg/imx-otg.c create mode 100644 drivers/usb/otg/mxs-phy.c create mode 100644 include/linux/usb/mxs-usb.h Cc: Chen Peter-B29397 <B29397@freescale.com> Cc: Detlev Zundel <dzu@denx.de> Cc: Fabio Estevam <festevam@gmail.com> Cc: Li Frank-B20596 <B20596@freescale.com> Cc: Linux USB <linux-usb@vger.kernel.org> Cc: Liu JunJie-B08287 <B08287@freescale.com> Cc: Sascha Hauer <s.hauer@pengutronix.de> Cc: Shawn Guo <shawn.guo@linaro.org> Cc: Shi Make-B15407 <B15407@freescale.com> Cc: Stefano Babic <sbabic@denx.de> Cc: Subodh Nijsure <snijsure@grid-net.com> Cc: Wolfgang Denk <wd@denx.de> -- 1.7.10 ^ permalink raw reply [flat|nested] 28+ messages in thread
* [PATCH 08/11] MXS: Add imx-otg driver 2012-05-01 1:55 [RFC PATCH 00/11 V7] " Marek Vasut @ 2012-05-01 1:56 ` Marek Vasut 0 siblings, 0 replies; 28+ messages in thread From: Marek Vasut @ 2012-05-01 1:56 UTC (permalink / raw) To: linux-arm-kernel This driver handles claiming of clocks and memory areas. These are later properly delegated to it's child devices, the USB Host (ehci-mxs) and USB Gadget (ci13xxx-mxs). Signed-off-by: Marek Vasut <marex@denx.de> Cc: Chen Peter-B29397 <B29397@freescale.com> Cc: Detlev Zundel <dzu@denx.de> Cc: Fabio Estevam <festevam@gmail.com> Cc: Li Frank-B20596 <B20596@freescale.com> Cc: Linux USB <linux-usb@vger.kernel.org> Cc: Liu JunJie-B08287 <B08287@freescale.com> Cc: Sascha Hauer <s.hauer@pengutronix.de> Cc: Shawn Guo <shawn.guo@linaro.org> Cc: Shi Make-B15407 <B15407@freescale.com> Cc: Stefano Babic <sbabic@denx.de> Cc: Subodh Nijsure <snijsure@grid-net.com> Cc: Wolfgang Denk <wd@denx.de> --- drivers/usb/otg/Kconfig | 6 + drivers/usb/otg/Makefile | 1 + drivers/usb/otg/imx-otg.c | 480 +++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 487 insertions(+) create mode 100644 drivers/usb/otg/imx-otg.c diff --git a/drivers/usb/otg/Kconfig b/drivers/usb/otg/Kconfig index 5c87db0..e7c6325 100644 --- a/drivers/usb/otg/Kconfig +++ b/drivers/usb/otg/Kconfig @@ -116,6 +116,12 @@ config FSL_USB2_OTG help Enable this to support Freescale USB OTG transceiver. +config USB_IMX_COMPOSITE + bool + help + Composite driver that handles clock and memory mapping for + i.MX USB host and USB PHY. + config USB_MV_OTG tristate "Marvell USB OTG support" depends on USB_EHCI_MV && USB_MV_UDC && USB_SUSPEND diff --git a/drivers/usb/otg/Makefile b/drivers/usb/otg/Makefile index 41aa509..7d2c631 100644 --- a/drivers/usb/otg/Makefile +++ b/drivers/usb/otg/Makefile @@ -20,4 +20,5 @@ obj-$(CONFIG_USB_MSM_OTG) += msm_otg.o obj-$(CONFIG_AB8500_USB) += ab8500-usb.o fsl_usb2_otg-objs := fsl_otg.o otg_fsm.o obj-$(CONFIG_FSL_USB2_OTG) += fsl_usb2_otg.o +obj-$(CONFIG_USB_IMX_COMPOSITE) += imx-otg.o obj-$(CONFIG_USB_MV_OTG) += mv_otg.o diff --git a/drivers/usb/otg/imx-otg.c b/drivers/usb/otg/imx-otg.c new file mode 100644 index 0000000..1fae1ba --- /dev/null +++ b/drivers/usb/otg/imx-otg.c @@ -0,0 +1,480 @@ +/* + * drivers/usb/otg/imx-otg.c + * + * Freescale i.MX USB composite driver. + * + * Copyright (C) 2012 Marek Vasut <marex@denx.de> + * on behalf of DENX Software Engineering GmbH + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#include <linux/module.h> +#include <linux/platform_device.h> +#include <linux/dma-mapping.h> +#include <linux/slab.h> +#include <linux/delay.h> +#include <linux/usb/mxs-usb.h> +#include <linux/io.h> +#include <linux/gpio.h> + +#include <linux/usb.h> +#include <linux/usb/ch9.h> +#include <linux/usb/otg.h> +#include <linux/usb/gadget.h> +#include <linux/usb/hcd.h> +#include <linux/usb/ehci_def.h> + +#include <mach/common.h> +#include <mach/hardware.h> +#include <mach/devices-common.h> + +/* + * Allocate platform device with the DMA mask, this is borrowed from + * arch/arm/mach-mxs/devices.c + */ +static struct platform_device *__devinit add_platform_device( + const char *name, int id, + const void *data, size_t size_data, u64 dmamask) +{ + int ret = -ENOMEM; + struct platform_device *pdev; + + pdev = platform_device_alloc(name, id); + if (!pdev) + goto err; + + if (dmamask) { + /* + * This memory isn't freed when the device is put, + * I don't have a nice idea for that though. Conceptually + * dma_mask in struct device should not be a pointer. + * See http://thread.gmane.org/gmane.linux.kernel.pci/9081 + */ + pdev->dev.dma_mask = + kmalloc(sizeof(*pdev->dev.dma_mask), GFP_KERNEL); + if (!pdev->dev.dma_mask) + /* ret is still -ENOMEM; */ + goto err; + + *pdev->dev.dma_mask = dmamask; + pdev->dev.coherent_dma_mask = dmamask; + } + + if (data) { + ret = platform_device_add_data(pdev, data, size_data); + if (ret) + goto err; + } + + ret = platform_device_add(pdev); + if (ret) { +err: + if (dmamask) + kfree(pdev->dev.dma_mask); + platform_device_put(pdev); + return ERR_PTR(ret); + } + + return pdev; +} + +static int imx_otg_set_host(struct usb_otg *otg, struct usb_bus *host) +{ + struct imx_otg *data = container_of(otg, struct imx_otg, otg); + + if (host) { + BUG_ON(otg->host); + otg->host = host; + } else { + BUG_ON(!otg->host); + } + + schedule_work(&data->work); + + return 0; +} + +static int imx_otg_set_peripheral(struct usb_otg *otg, struct usb_gadget *gg) +{ + struct imx_otg *data = container_of(otg, struct imx_otg, otg); + + if (gg) { + BUG_ON(otg->gadget); + otg->gadget = gg; + } else { + BUG_ON(!otg->gadget); + } + + schedule_work(&data->work); + + return 0; +} + +static void imx_otg_work(struct work_struct *w) +{ + struct imx_otg *data = container_of(w, struct imx_otg, work); + struct usb_hcd *hcd; + +sm: + switch (data->cur_state) { + case OTG_STATE_A_HOST: + if ((data->new_state == OTG_STATE_B_PERIPHERAL) || + (data->new_state == OTG_STATE_UNDEFINED)) { + hcd = bus_to_hcd(data->otg.host); + usb_remove_hcd(hcd); + data->cur_state = OTG_STATE_UNDEFINED; + /* Turn off VBUS */ + gpio_set_value(data->gpio_vbus, + data->gpio_vbus_inverted); + } + if (data->new_state == OTG_STATE_B_PERIPHERAL) + goto sm; + break; + case OTG_STATE_B_PERIPHERAL: + if ((data->new_state == OTG_STATE_A_HOST) || + (data->new_state == OTG_STATE_UNDEFINED)) { + usb_del_gadget_udc(data->otg.gadget); + data->cur_state = OTG_STATE_UNDEFINED; + } + if (data->new_state == OTG_STATE_A_HOST) + goto sm; + break; + case OTG_STATE_UNDEFINED: + /* Check desired state. */ + switch (data->new_state) { + case OTG_STATE_A_HOST: + if (!data->otg.host) + break; + data->cur_state = data->new_state; + + /* Turn on VBUS */ + gpio_set_value(data->gpio_vbus, + !data->gpio_vbus_inverted); + + hcd = bus_to_hcd(data->otg.host); + usb_add_hcd(hcd, 0, IRQF_DISABLED); + break; + case OTG_STATE_B_PERIPHERAL: + if (!data->otg.gadget) + break; + data->cur_state = data->new_state; + usb_add_gadget_udc(data->res.dev, data->otg.gadget); + break; + default: + break; + } + break; + + default: + break; + } +} + +void imx_otg_set_irq_handler(struct device *dev, + irqreturn_t (*handler)(int irq, void *data), + void *data, int host) +{ + struct imx_otg *otg = dev_get_drvdata(dev); + if (host) { + otg->host_handler = handler; + otg->host_data = data; + } else { + otg->gadget_handler = handler; + otg->gadget_data = data; + } +} + +static irqreturn_t imx_otg_wakeup_irq(int irq, void *irqdata) +{ + return IRQ_NONE; +} + +static irqreturn_t imx_otg_irq(int irq, void *irqdata) +{ + struct imx_otg *data = irqdata; + + switch (data->cur_state) { + case OTG_STATE_A_HOST: + if (data->host_handler) + return data->host_handler(irq, data->host_data); + break; + case OTG_STATE_B_PERIPHERAL: + if (data->gadget_handler) + return data->gadget_handler(irq, data->gadget_data); + break; + default: + return IRQ_NONE; + } + return IRQ_NONE; +} + +static int __devinit imx_usb_probe(struct platform_device *pdev) +{ + struct imx_usb_platform_data *pdata = pdev->dev.platform_data; + struct imx_otg_res *res; + struct imx_otg *data; + struct usb_phy *phy; + struct usb_otg *otg; + int ret; + void *retp = NULL; + + if (!pdata) { + dev_err(&pdev->dev, "No platform data supplied!\n"); + return -ENODEV; + } + + phy = usb_get_transceiver(); + if (!phy) + return -EPROBE_DEFER; + + /* + * Until further notice, this claims all necessary resources. + */ + + /* Claim the VBUS GPIO */ + ret = gpio_request_one(pdata->gpio_vbus, GPIOF_DIR_OUT, "USB Power"); + if (ret) { + dev_err(&pdev->dev, "Failed to request USB Power GPIO!"); + ret = -EINVAL; + goto err_alloc_data; + } + + /* Disable the VBUS. */ + gpio_set_value(pdata->gpio_vbus, pdata->gpio_vbus_inverted); + + /* Allocate driver's private data. */ + data = devm_kzalloc(&pdev->dev, sizeof(*data), GFP_KERNEL); + if (!data) { + dev_err(&pdev->dev, "Failed to allocate OTG nodes data!\n"); + ret = -ENOMEM; + goto err_alloc_data; + } + + res = &data->res; + res->dev = &pdev->dev; + + /* Configure the OTG structure. */ + otg = &data->otg; + otg->phy = phy; + otg->set_host = imx_otg_set_host; + otg->set_peripheral = imx_otg_set_peripheral; + phy->otg = otg; + + data->gpio_vbus = pdata->gpio_vbus; + data->gpio_vbus_inverted = pdata->gpio_vbus_inverted; + data->cur_state = OTG_STATE_UNDEFINED; + data->new_state = OTG_STATE_UNDEFINED; + + /* We do NOT support OTG yet */ + if (pdata->host_mode && !pdata->gadget_mode) + data->new_state = OTG_STATE_A_HOST; + else if (pdata->gadget_mode) + data->new_state = OTG_STATE_B_PERIPHERAL; + + INIT_WORK(&data->work, imx_otg_work); + + /* Claim the Host clock. */ + data->clk = clk_get(&pdev->dev, "usb"); + if (IS_ERR(data->clk)) { + dev_err(&pdev->dev, "Failed to claim clock for USB Host\n"); + ret = PTR_ERR(data->clk); + goto err_alloc_data; + } + + /* Prepare Host clock. */ + ret = clk_prepare_enable(data->clk); + if (ret) { + dev_err(&pdev->dev, "Failed to enable clock for USB Host.\n"); + goto err_prepare_host_clock; + } + + /* Get memory area for EHCI host from resources. */ + res->mem_res = platform_get_resource(pdev, IORESOURCE_MEM, 0); + if (!res->mem_res) { + dev_err(&pdev->dev, "Specify memory area for this USB Host!\n"); + ret = -ENODEV; + goto err_get_host_resource; + } + + /* Request the memory region for this USB Host. */ + retp = devm_request_mem_region(&pdev->dev, res->mem_res->start, + resource_size(res->mem_res), pdev->name); + if (!retp) { + dev_err(&pdev->dev, "USB Host memory area already in use!\n"); + ret = -EBUSY; + goto err_get_host_resource; + } + + /* Map the memory region for USB Host. */ + res->mem = devm_ioremap(&pdev->dev, res->mem_res->start, + resource_size(res->mem_res)); + if (!res->mem) { + dev_err(&pdev->dev, "Memory mapping of USB Host failed!\n"); + ret = -EFAULT; + goto err_get_host_resource; + } + + /* Get IRQ for EHCI host from resources. */ + data->irq = platform_get_irq(pdev, 0); + if (data->irq < 0) { + dev_err(&pdev->dev, "Specify IRQ for this USB Host!\n"); + ret = -ENODEV; + goto err_get_host_resource; + } + + /* Request the USB IRQ. */ + ret = devm_request_irq(&pdev->dev, data->irq, imx_otg_irq, + IRQF_SHARED, "imx-otg-usb-irq", data); + if (ret < 0) { + dev_err(&pdev->dev, "Failed to request IRQ!\n"); + goto err_get_host_resource; + } + + /* Get IRQ for PHY wakeup from resources. */ + data->irq_wakeup = platform_get_irq(pdev, 1); + if (data->irq_wakeup < 0) { + dev_err(&pdev->dev, "Specify wakeup IRQ for this USB Host!\n"); + ret = -ENODEV; + goto err_get_host_resource; + } + + /* Request the Wakeup IRQ. */ + ret = devm_request_irq(&pdev->dev, data->irq_wakeup, imx_otg_wakeup_irq, + IRQF_SHARED, "imx-otg-wakeup-irq", data); + if (ret < 0) { + dev_err(&pdev->dev, "Failed to request IRQ!\n"); + goto err_get_host_resource; + } + + dev_set_drvdata(&pdev->dev, data); + + /* + * Now finally probe the Host driver! + */ + if (pdata->gadget_mode) { + data->pdev_gadget = add_platform_device("ci13xxx-mxs", -1, + res, sizeof(*res), + DMA_BIT_MASK(32)); + if (!data->pdev_gadget) { + dev_err(&pdev->dev, "Failed registering Host!\n"); + ret = -ENODEV; + goto err_register_gadget; + } + } + + if (pdata->host_mode) { + data->pdev_host = add_platform_device("mxs-ehci", -1, + res, sizeof(*res), + DMA_BIT_MASK(32)); + if (!data->pdev_host) { + dev_err(&pdev->dev, "Failed registering Host!\n"); + ret = -ENODEV; + goto err_get_host_resource; + } + } + + /* + * Initialize the transceiver + */ + phy = usb_get_transceiver(); + if (!phy) { + dev_err(&pdev->dev, "Unable to find transceiver.\n"); + ret = -ENODEV; + goto err_phy; + } + + ret = usb_phy_init(phy); + if (ret < 0) { + dev_err(&pdev->dev, "Unable init transceiver\n"); + ret = -ENODEV; + goto err_phy_init; + } + + /* Kick in the state machine. */ + schedule_work(&data->work); + + return 0; + +err_phy_init: + if (phy) + usb_put_transceiver(phy); +err_phy: + if (data->pdev_gadget) + platform_device_unregister(data->pdev_gadget); +err_register_gadget: + if (data->pdev_host) + platform_device_unregister(data->pdev_host); +err_get_host_resource: + clk_disable_unprepare(data->clk); +err_prepare_host_clock: + clk_put(data->clk); +err_alloc_data: + return ret; +} + +static int __devexit imx_usb_remove(struct platform_device *pdev) +{ + struct imx_otg *data = platform_get_drvdata(pdev); + + /* Stop the PHY work. */ + cancel_work_sync(&data->work); + + /* Shut off VBUS. */ + gpio_set_value(data->gpio_vbus, data->gpio_vbus_inverted); + gpio_free(data->gpio_vbus); + + /* Deregister both Gadget and Host driver. */ + if (data->pdev_gadget) + platform_device_unregister(data->pdev_gadget); + + if (data->pdev_host) + platform_device_unregister(data->pdev_host); + + dev_set_drvdata(&pdev->dev, NULL); + + /* Stop the clock. */ + clk_disable_unprepare(data->clk); + clk_put(data->clk); + + return 0; +} + +static struct platform_driver imx_usb_driver = { + .probe = imx_usb_probe, + .remove = __devexit_p(imx_usb_remove), + .driver = { + .name = "imx-otg", + .owner = THIS_MODULE, + }, +}; + +static int __init imx_usb_init(void) +{ + return platform_driver_register(&imx_usb_driver); +} + +static void __exit imx_usb_exit(void) +{ + platform_driver_unregister(&imx_usb_driver); +} + +module_init(imx_usb_init); +module_exit(imx_usb_exit); + +MODULE_ALIAS("platform:imx-otg"); +MODULE_AUTHOR("Marek Vasut <marex@denx.de>"); +MODULE_DESCRIPTION("Freescale i.MX USB composite driver"); +MODULE_LICENSE("GPL"); -- 1.7.10 ^ permalink raw reply related [flat|nested] 28+ messages in thread
* [RFC PATCH 00/10 V3] MXS: Add i.MX28 USB Host driver @ 2012-04-18 17:46 Marek Vasut 2012-04-22 12:59 ` [RFC PATCH 00/11 V4] " Marek Vasut 0 siblings, 1 reply; 28+ messages in thread From: Marek Vasut @ 2012-04-18 17:46 UTC (permalink / raw) To: linux-arm-kernel This patchset introduces the USB Host driver for i.MX28 CPU, utilising the generic USB PHY infrastructure. V2: Introduce stub imx-usb driver that then registers the PHY and EHCI drivers. V3: Add the HCD on demand based on the PHY's state (only add HCD if it's host). Currently, only the HOST mode is supported. Marek Vasut (10): MXS: Make clk_disable return integer MXS: Add USB EHCI and USB PHY clock handling MXS: Fixup i.MX233 USB base address name MXS: Add data shared between imx-usb and EHCI driver MXS: Add platform registration hooks for USB EHCI MXS: Add imx-usb driver MXS: Add USB PHY driver MXS: Add separate MXS EHCI HCD driver MXS: Enable USB on M28EVK MXS: Enable USB on MX28EVK arch/arm/mach-mxs/Kconfig | 4 + arch/arm/mach-mxs/clock-mx28.c | 28 ++- arch/arm/mach-mxs/devices-mx28.h | 4 + arch/arm/mach-mxs/devices/Kconfig | 3 + arch/arm/mach-mxs/devices/Makefile | 1 + arch/arm/mach-mxs/devices/platform-usb.c | 78 ++++++ arch/arm/mach-mxs/include/mach/clock.h | 2 +- arch/arm/mach-mxs/include/mach/devices-common.h | 9 + arch/arm/mach-mxs/include/mach/mx23.h | 8 +- arch/arm/mach-mxs/mach-m28evk.c | 15 ++ arch/arm/mach-mxs/mach-mx28evk.c | 10 + drivers/usb/host/Kconfig | 7 + drivers/usb/host/ehci-hcd.c | 5 + drivers/usb/host/ehci-mxs.c | 228 +++++++++++++++++ drivers/usb/otg/Kconfig | 16 ++ drivers/usb/otg/Makefile | 2 + drivers/usb/otg/imx-usb.c | 226 +++++++++++++++++ drivers/usb/otg/mxs-phy.c | 305 +++++++++++++++++++++++ include/linux/fsl_devices.h | 10 + 19 files changed, 952 insertions(+), 9 deletions(-) create mode 100644 arch/arm/mach-mxs/devices/platform-usb.c create mode 100644 drivers/usb/host/ehci-mxs.c create mode 100644 drivers/usb/otg/imx-usb.c create mode 100644 drivers/usb/otg/mxs-phy.c Cc: Chen Peter-B29397 <B29397@freescale.com> Cc: Detlev Zundel <dzu@denx.de> Cc: Fabio Estevam <festevam@gmail.com> Cc: Li Frank-B20596 <B20596@freescale.com> Cc: Lin Tony-B19295 <B19295@freescale.com> Cc: Linux USB <linux-usb@vger.kernel.org> Cc: Sascha Hauer <s.hauer@pengutronix.de> Cc: Shawn Guo <shawn.guo@freescale.com> Cc: Shawn Guo <shawn.guo@linaro.org> Cc: Stefano Babic <sbabic@denx.de> Cc: Subodh Nijsure <snijsure@grid-net.com> Cc: Tony Lin <tony.lin@freescale.com> Cc: Wolfgang Denk <wd@denx.de> -- 1.7.9.5 ^ permalink raw reply [flat|nested] 28+ messages in thread
* [RFC PATCH 00/11 V4] MXS: Add i.MX28 USB Host driver 2012-04-18 17:46 [RFC PATCH 00/10 V3] MXS: Add i.MX28 USB Host driver Marek Vasut @ 2012-04-22 12:59 ` Marek Vasut 2012-04-22 12:59 ` [PATCH 08/11] MXS: Add imx-otg driver Marek Vasut 2012-04-24 3:18 ` [RFC PATCH 00/11 V5] MXS: Add i.MX28 USB Host driver Marek Vasut 0 siblings, 2 replies; 28+ messages in thread From: Marek Vasut @ 2012-04-22 12:59 UTC (permalink / raw) To: linux-arm-kernel This patchset introduces the USB Host driver for i.MX28 CPU, utilising the generic USB PHY infrastructure. Also added is glue code for CI13xxx driver, to allow device mode. This patchset still does NOT support OTG mode, the device/host mode is selected via platform data. V2: Introduce stub imx-usb driver that then registers the PHY and EHCI drivers. V3: Add the HCD on demand based on the PHY's state (only add HCD if it's host). Currently, only the HOST mode is supported. V4: * Introduce ci13xxx gadget glue * Reorder patches in a more sensible order * Introduce platform data, containing VBUS GPIO and port mode (device/gadget) * Rename imx-usb to imx-otg * Drop mx28evk usb host patch * Use more devm_ function * Rework the mxs-phy to register the same interrupt as ehci-mxs (and effectivelly kill bogus otg_set_vbus() call from ehci-mxs ; use standard ehci irq handling in ehci-mxs) Marek Vasut (11): MXS: Make clk_disable return integer MXS: Add USB EHCI and USB PHY clock handling MXS: Fixup i.MX233 USB base address name MXS: Add data shared between imx-otg and EHCI driver MXS: Modify the ci13xxx_udc to avoid adding UDC MXS: Add small registration glue for ci13xxx_udc MXS: Add separate MXS EHCI HCD driver MXS: Add imx-otg driver MXS: Add USB PHY driver MXS: Add platform registration hooks for USB EHCI MXS: Enable USB on M28EVK arch/arm/mach-mxs/Kconfig | 2 + arch/arm/mach-mxs/clock-mx28.c | 28 +- arch/arm/mach-mxs/devices-mx28.h | 5 + arch/arm/mach-mxs/devices/Kconfig | 3 + arch/arm/mach-mxs/devices/Makefile | 1 + arch/arm/mach-mxs/devices/platform-usb.c | 84 +++++ arch/arm/mach-mxs/include/mach/clock.h | 2 +- arch/arm/mach-mxs/include/mach/devices-common.h | 12 + arch/arm/mach-mxs/include/mach/mx23.h | 8 +- arch/arm/mach-mxs/mach-m28evk.c | 20 ++ drivers/usb/gadget/Kconfig | 17 + drivers/usb/gadget/Makefile | 1 + drivers/usb/gadget/ci13xxx_mxs.c | 67 ++++ drivers/usb/gadget/ci13xxx_udc.c | 12 +- drivers/usb/gadget/ci13xxx_udc.h | 1 + drivers/usb/host/Kconfig | 7 + drivers/usb/host/ehci-hcd.c | 5 + drivers/usb/host/ehci-mxs.c | 197 ++++++++++ drivers/usb/otg/Kconfig | 16 + drivers/usb/otg/Makefile | 2 + drivers/usb/otg/imx-otg.c | 282 +++++++++++++++ drivers/usb/otg/mxs-phy.c | 438 +++++++++++++++++++++++ include/linux/fsl/mxs-usb.h | 46 +++ 23 files changed, 1243 insertions(+), 13 deletions(-) create mode 100644 arch/arm/mach-mxs/devices/platform-usb.c create mode 100644 drivers/usb/gadget/ci13xxx_mxs.c create mode 100644 drivers/usb/host/ehci-mxs.c create mode 100644 drivers/usb/otg/imx-otg.c create mode 100644 drivers/usb/otg/mxs-phy.c create mode 100644 include/linux/fsl/mxs-usb.h Cc: Chen Peter-B29397 <B29397@freescale.com> Cc: Detlev Zundel <dzu@denx.de> Cc: Fabio Estevam <festevam@gmail.com> Cc: Li Frank-B20596 <B20596@freescale.com> Cc: Lin Tony-B19295 <B19295@freescale.com> Cc: Linux USB <linux-usb@vger.kernel.org> Cc: Sascha Hauer <s.hauer@pengutronix.de> Cc: Shawn Guo <shawn.guo@freescale.com> Cc: Shawn Guo <shawn.guo@linaro.org> Cc: Stefano Babic <sbabic@denx.de> Cc: Subodh Nijsure <snijsure@grid-net.com> Cc: Tony Lin <tony.lin@freescale.com> Cc: Wolfgang Denk <wd@denx.de> NOTE: Adding this ci13xxx-mxs driver was really helpful, it helped me to realise how this whole monster should look like in the end. Now the mxs-phy is also much more prepared for the OTG operation. -- 1.7.9.5 ^ permalink raw reply [flat|nested] 28+ messages in thread
* [PATCH 08/11] MXS: Add imx-otg driver 2012-04-22 12:59 ` [RFC PATCH 00/11 V4] " Marek Vasut @ 2012-04-22 12:59 ` Marek Vasut 2012-04-23 6:39 ` Sascha Hauer 2012-04-24 3:18 ` [RFC PATCH 00/11 V5] MXS: Add i.MX28 USB Host driver Marek Vasut 1 sibling, 1 reply; 28+ messages in thread From: Marek Vasut @ 2012-04-22 12:59 UTC (permalink / raw) To: linux-arm-kernel This driver handles claiming of clocks and memory areas. These are later properly delegated to it's child devices, the USB Host (ehci-mxs) and USB Gadget (ci13xxx-mxs). Signed-off-by: Marek Vasut <marex@denx.de> Cc: Chen Peter-B29397 <B29397@freescale.com> Cc: Detlev Zundel <dzu@denx.de> Cc: Fabio Estevam <festevam@gmail.com> Cc: Li Frank-B20596 <B20596@freescale.com> Cc: Lin Tony-B19295 <B19295@freescale.com> Cc: Linux USB <linux-usb@vger.kernel.org> Cc: Sascha Hauer <s.hauer@pengutronix.de> Cc: Shawn Guo <shawn.guo@freescale.com> Cc: Shawn Guo <shawn.guo@linaro.org> Cc: Stefano Babic <sbabic@denx.de> Cc: Subodh Nijsure <snijsure@grid-net.com> Cc: Tony Lin <tony.lin@freescale.com> Cc: Wolfgang Denk <wd@denx.de> --- drivers/usb/otg/Kconfig | 6 + drivers/usb/otg/Makefile | 1 + drivers/usb/otg/imx-otg.c | 282 +++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 289 insertions(+) create mode 100644 drivers/usb/otg/imx-otg.c diff --git a/drivers/usb/otg/Kconfig b/drivers/usb/otg/Kconfig index 5c87db0..e7c6325 100644 --- a/drivers/usb/otg/Kconfig +++ b/drivers/usb/otg/Kconfig @@ -116,6 +116,12 @@ config FSL_USB2_OTG help Enable this to support Freescale USB OTG transceiver. +config USB_IMX_COMPOSITE + bool + help + Composite driver that handles clock and memory mapping for + i.MX USB host and USB PHY. + config USB_MV_OTG tristate "Marvell USB OTG support" depends on USB_EHCI_MV && USB_MV_UDC && USB_SUSPEND diff --git a/drivers/usb/otg/Makefile b/drivers/usb/otg/Makefile index 41aa509..7d2c631 100644 --- a/drivers/usb/otg/Makefile +++ b/drivers/usb/otg/Makefile @@ -20,4 +20,5 @@ obj-$(CONFIG_USB_MSM_OTG) += msm_otg.o obj-$(CONFIG_AB8500_USB) += ab8500-usb.o fsl_usb2_otg-objs := fsl_otg.o otg_fsm.o obj-$(CONFIG_FSL_USB2_OTG) += fsl_usb2_otg.o +obj-$(CONFIG_USB_IMX_COMPOSITE) += imx-otg.o obj-$(CONFIG_USB_MV_OTG) += mv_otg.o diff --git a/drivers/usb/otg/imx-otg.c b/drivers/usb/otg/imx-otg.c new file mode 100644 index 0000000..249b6b5 --- /dev/null +++ b/drivers/usb/otg/imx-otg.c @@ -0,0 +1,282 @@ +/* + * drivers/usb/otg/imx-otg.c + * + * Freescale i.MX USB composite driver. + * + * Copyright (C) 2012 Marek Vasut <marex@denx.de> + * on behalf of DENX Software Engineering GmbH + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#include <linux/module.h> +#include <linux/platform_device.h> +#include <linux/dma-mapping.h> +#include <linux/usb.h> +#include <linux/usb/otg.h> +#include <linux/usb/hcd.h> +#include <linux/slab.h> +#include <linux/delay.h> +#include <linux/fsl/mxs-usb.h> +#include <linux/io.h> + +#include <mach/common.h> +#include <mach/hardware.h> +#include <mach/devices-common.h> + +/* + * Allocate platform device with the DMA mask, this is borrowed from + * arch/arm/mach-mxs/devices.c + */ +static struct platform_device *__devinit add_platform_device( + const char *name, int id, + const void *data, size_t size_data, u64 dmamask) +{ + int ret = -ENOMEM; + struct platform_device *pdev; + + pdev = platform_device_alloc(name, id); + if (!pdev) + goto err; + + if (dmamask) { + /* + * This memory isn't freed when the device is put, + * I don't have a nice idea for that though. Conceptually + * dma_mask in struct device should not be a pointer. + * See http://thread.gmane.org/gmane.linux.kernel.pci/9081 + */ + pdev->dev.dma_mask = + kmalloc(sizeof(*pdev->dev.dma_mask), GFP_KERNEL); + if (!pdev->dev.dma_mask) + /* ret is still -ENOMEM; */ + goto err; + + *pdev->dev.dma_mask = dmamask; + pdev->dev.coherent_dma_mask = dmamask; + } + + if (data) { + ret = platform_device_add_data(pdev, data, size_data); + if (ret) + goto err; + } + + ret = platform_device_add(pdev); + if (ret) { +err: + if (dmamask) + kfree(pdev->dev.dma_mask); + platform_device_put(pdev); + return ERR_PTR(ret); + } + + return pdev; +} + +static int __devinit imx_usb_probe(struct platform_device *pdev) +{ + struct imx_usb_platform_data *pdata = pdev->dev.platform_data; + struct imx_usb *data; + struct usb_phy *phy; + int ret; + void *retp = NULL; + + if (!pdata) { + dev_err(&pdev->dev, "No platform data supplied!\n"); + return -ENODEV; + } + + phy = usb_get_transceiver(); + if (!phy) + return -EPROBE_DEFER; + + /* + * Until further notice, this claims all necessary resources. + */ + + /* Allocate driver's private date. */ + data = devm_kzalloc(&pdev->dev, sizeof(*data), GFP_KERNEL); + if (!data) { + ret = -ENOMEM; + goto err_alloc_data; + } + + /* Claim the Host clock. */ + data->clk = clk_get(&pdev->dev, "usb"); + if (IS_ERR(data->clk)) { + dev_err(&pdev->dev, "Failed to claim clock for USB Host\n"); + ret = PTR_ERR(data->clk); + goto err_claim_host_clock; + } + + /* Prepare Host clock. */ + ret = clk_prepare_enable(data->clk); + if (ret) { + dev_err(&pdev->dev, "Failed to enable clock for USB Host.\n"); + goto err_prepare_host_clock; + } + + /* Get memory area for EHCI host from resources. */ + data->mem_res = platform_get_resource(pdev, IORESOURCE_MEM, 0); + if (!data->mem_res) { + dev_err(&pdev->dev, "Specify memory area for this USB Host!\n"); + ret = -ENODEV; + goto err_get_host_resource; + } + + /* Request the memory region for this USB Host. */ + retp = devm_request_mem_region(&pdev->dev, data->mem_res->start, + resource_size(data->mem_res), pdev->name); + if (!retp) { + dev_err(&pdev->dev, "USB Host memory area already in use!\n"); + ret = -EBUSY; + goto err_get_host_mem; + } + + /* Map the memory region for USB Host. */ + data->mem = devm_ioremap(&pdev->dev, data->mem_res->start, + resource_size(data->mem_res)); + if (!data->mem) { + dev_err(&pdev->dev, "Memory mapping of USB Host failed!\n"); + ret = -EFAULT; + goto err_map_host_mem; + } + + /* Get IRQ for EHCI host from resources. */ + data->irq = platform_get_irq(pdev, 0); + if (data->irq < 0) { + dev_err(&pdev->dev, "Specify IRQ for this USB Host!\n"); + ret = -ENODEV; + goto err_get_host_irq; + } + + /* + * Now finally probe the Host driver! + */ + if (pdata->host_mode) { + data->pdev_host = add_platform_device("mxs-ehci", -1, + data, sizeof(*data), + DMA_BIT_MASK(32)); + if (!data->pdev_host) { + dev_err(&pdev->dev, "Failed registering Host!\n"); + ret = -ENODEV; + goto err_register_host; + } + } else { + data->pdev_gadget = add_platform_device("ci13xxx-mxs", -1, + data, sizeof(*data), + DMA_BIT_MASK(32)); + if (!data->pdev_gadget) { + dev_err(&pdev->dev, "Failed registering Host!\n"); + ret = -ENODEV; + goto err_register_gadget; + } + } + + /* + * Initialize the transceiver + */ + phy = usb_get_transceiver(); + if (!phy) { + dev_err(&pdev->dev, "Unable to find transceiver.\n"); + ret = -ENODEV; + goto err_phy; + } + + ret = usb_phy_init(phy); + if (ret < 0) { + dev_err(&pdev->dev, "Unable init transceiver\n"); + ret = -ENODEV; + goto err_phy_init; + } + + /* Set up the PORTSCx register */ + writel(0, data->mem + 0x144); + + return 0; + +err_phy_init: + if (phy) + usb_put_transceiver(phy); +err_phy: + if (data->pdev_gadget) + platform_device_unregister(data->pdev_gadget); +err_register_gadget: + if (data->pdev_host) + platform_device_unregister(data->pdev_host); +err_register_host: +err_get_host_irq: + iounmap(data->mem); +err_map_host_mem: + release_mem_region(data->mem_res->start, + resource_size(data->mem_res)); +err_get_host_mem: + data->mem_res = NULL; +err_get_host_resource: + clk_disable_unprepare(data->clk); +err_prepare_host_clock: + clk_put(data->clk); +err_claim_host_clock: +err_alloc_data: + return ret; +} + +static int __devexit imx_usb_remove(struct platform_device *pdev) +{ + struct imx_usb *data = platform_get_drvdata(pdev); + + if (data->pdev_gadget) + platform_device_unregister(data->pdev_gadget); + + if (data->pdev_host) + platform_device_unregister(data->pdev_host); + + iounmap(data->mem); + release_mem_region(data->mem_res->start, + resource_size(data->mem_res)); + data->mem_res = NULL; + clk_disable_unprepare(data->clk); + clk_put(data->clk); + + return 0; +} + +static struct platform_driver imx_usb_driver = { + .probe = imx_usb_probe, + .remove = __devexit_p(imx_usb_remove), + .driver = { + .name = "imx-otg", + .owner = THIS_MODULE, + }, +}; + +static int __init imx_usb_init(void) +{ + return platform_driver_register(&imx_usb_driver); +} + +static void __exit imx_usb_exit(void) +{ + platform_driver_unregister(&imx_usb_driver); +} + +module_init(imx_usb_init); +module_exit(imx_usb_exit); + +MODULE_ALIAS("platform:imx-otg"); +MODULE_AUTHOR("Marek Vasut <marex@denx.de>"); +MODULE_DESCRIPTION("Freescale i.MX USB composite driver"); +MODULE_LICENSE("GPL"); -- 1.7.9.5 ^ permalink raw reply related [flat|nested] 28+ messages in thread
* [PATCH 08/11] MXS: Add imx-otg driver 2012-04-22 12:59 ` [PATCH 08/11] MXS: Add imx-otg driver Marek Vasut @ 2012-04-23 6:39 ` Sascha Hauer 2012-04-23 9:38 ` Marek Vasut 0 siblings, 1 reply; 28+ messages in thread From: Sascha Hauer @ 2012-04-23 6:39 UTC (permalink / raw) To: linux-arm-kernel On Sun, Apr 22, 2012 at 02:59:24PM +0200, Marek Vasut wrote: > This driver handles claiming of clocks and memory areas. These are later > properly delegated to it's child devices, the USB Host (ehci-mxs) and > USB Gadget (ci13xxx-mxs). > > Signed-off-by: Marek Vasut <marex@denx.de> > Cc: Chen Peter-B29397 <B29397@freescale.com> > Cc: Detlev Zundel <dzu@denx.de> > Cc: Fabio Estevam <festevam@gmail.com> > Cc: Li Frank-B20596 <B20596@freescale.com> > Cc: Lin Tony-B19295 <B19295@freescale.com> > Cc: Linux USB <linux-usb@vger.kernel.org> > Cc: Sascha Hauer <s.hauer@pengutronix.de> > Cc: Shawn Guo <shawn.guo@freescale.com> > Cc: Shawn Guo <shawn.guo@linaro.org> > Cc: Stefano Babic <sbabic@denx.de> > Cc: Subodh Nijsure <snijsure@grid-net.com> > Cc: Tony Lin <tony.lin@freescale.com> > Cc: Wolfgang Denk <wd@denx.de> > --- > drivers/usb/otg/Kconfig | 6 + > drivers/usb/otg/Makefile | 1 + > drivers/usb/otg/imx-otg.c | 282 +++++++++++++++++++++++++++++++++++++++++++++ > 3 files changed, 289 insertions(+) > create mode 100644 drivers/usb/otg/imx-otg.c > > diff --git a/drivers/usb/otg/Kconfig b/drivers/usb/otg/Kconfig > index 5c87db0..e7c6325 100644 > --- a/drivers/usb/otg/Kconfig > +++ b/drivers/usb/otg/Kconfig > @@ -116,6 +116,12 @@ config FSL_USB2_OTG > help > Enable this to support Freescale USB OTG transceiver. > > +config USB_IMX_COMPOSITE > + bool > + help > + Composite driver that handles clock and memory mapping for > + i.MX USB host and USB PHY. > + > config USB_MV_OTG > tristate "Marvell USB OTG support" > depends on USB_EHCI_MV && USB_MV_UDC && USB_SUSPEND > diff --git a/drivers/usb/otg/Makefile b/drivers/usb/otg/Makefile > index 41aa509..7d2c631 100644 > --- a/drivers/usb/otg/Makefile > +++ b/drivers/usb/otg/Makefile > @@ -20,4 +20,5 @@ obj-$(CONFIG_USB_MSM_OTG) += msm_otg.o > obj-$(CONFIG_AB8500_USB) += ab8500-usb.o > fsl_usb2_otg-objs := fsl_otg.o otg_fsm.o > obj-$(CONFIG_FSL_USB2_OTG) += fsl_usb2_otg.o > +obj-$(CONFIG_USB_IMX_COMPOSITE) += imx-otg.o > obj-$(CONFIG_USB_MV_OTG) += mv_otg.o > diff --git a/drivers/usb/otg/imx-otg.c b/drivers/usb/otg/imx-otg.c > new file mode 100644 > index 0000000..249b6b5 > --- /dev/null > +++ b/drivers/usb/otg/imx-otg.c > @@ -0,0 +1,282 @@ > +/* > + * drivers/usb/otg/imx-otg.c > + * > + * Freescale i.MX USB composite driver. > + * > + * Copyright (C) 2012 Marek Vasut <marex@denx.de> > + * on behalf of DENX Software Engineering GmbH > + * > + * This program is free software; you can redistribute it and/or modify > + * it under the terms of the GNU General Public License as published by > + * the Free Software Foundation; either version 2 of the License, or > + * (at your option) any later version. > + * > + * This program is distributed in the hope that it will be useful, > + * but WITHOUT ANY WARRANTY; without even the implied warranty of > + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the > + * GNU General Public License for more details. > + * > + * You should have received a copy of the GNU General Public License > + * along with this program; if not, write to the Free Software > + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. > + */ > + > +#include <linux/module.h> > +#include <linux/platform_device.h> > +#include <linux/dma-mapping.h> > +#include <linux/usb.h> > +#include <linux/usb/otg.h> > +#include <linux/usb/hcd.h> > +#include <linux/slab.h> > +#include <linux/delay.h> > +#include <linux/fsl/mxs-usb.h> > +#include <linux/io.h> > + > +#include <mach/common.h> > +#include <mach/hardware.h> > +#include <mach/devices-common.h> > + > +/* > + * Allocate platform device with the DMA mask, this is borrowed from > + * arch/arm/mach-mxs/devices.c > + */ > +static struct platform_device *__devinit add_platform_device( > + const char *name, int id, > + const void *data, size_t size_data, u64 dmamask) > +{ > + int ret = -ENOMEM; > + struct platform_device *pdev; > + > + pdev = platform_device_alloc(name, id); > + if (!pdev) > + goto err; > + > + if (dmamask) { > + /* > + * This memory isn't freed when the device is put, > + * I don't have a nice idea for that though. Conceptually > + * dma_mask in struct device should not be a pointer. > + * See http://thread.gmane.org/gmane.linux.kernel.pci/9081 > + */ > + pdev->dev.dma_mask = > + kmalloc(sizeof(*pdev->dev.dma_mask), GFP_KERNEL); > + if (!pdev->dev.dma_mask) > + /* ret is still -ENOMEM; */ > + goto err; > + > + *pdev->dev.dma_mask = dmamask; > + pdev->dev.coherent_dma_mask = dmamask; > + } > + > + if (data) { > + ret = platform_device_add_data(pdev, data, size_data); > + if (ret) > + goto err; > + } > + > + ret = platform_device_add(pdev); > + if (ret) { > +err: > + if (dmamask) > + kfree(pdev->dev.dma_mask); > + platform_device_put(pdev); > + return ERR_PTR(ret); > + } > + > + return pdev; > +} > + > +static int __devinit imx_usb_probe(struct platform_device *pdev) > +{ > + struct imx_usb_platform_data *pdata = pdev->dev.platform_data; > + struct imx_usb *data; > + struct usb_phy *phy; > + int ret; > + void *retp = NULL; > + > + if (!pdata) { > + dev_err(&pdev->dev, "No platform data supplied!\n"); > + return -ENODEV; > + } > + > + phy = usb_get_transceiver(); > + if (!phy) > + return -EPROBE_DEFER; > + > + /* > + * Until further notice, this claims all necessary resources. > + */ > + > + /* Allocate driver's private date. */ > + data = devm_kzalloc(&pdev->dev, sizeof(*data), GFP_KERNEL); > + if (!data) { > + ret = -ENOMEM; > + goto err_alloc_data; > + } > + > + /* Claim the Host clock. */ > + data->clk = clk_get(&pdev->dev, "usb"); > + if (IS_ERR(data->clk)) { > + dev_err(&pdev->dev, "Failed to claim clock for USB Host\n"); > + ret = PTR_ERR(data->clk); > + goto err_claim_host_clock; > + } > + > + /* Prepare Host clock. */ > + ret = clk_prepare_enable(data->clk); > + if (ret) { > + dev_err(&pdev->dev, "Failed to enable clock for USB Host.\n"); > + goto err_prepare_host_clock; > + } > + > + /* Get memory area for EHCI host from resources. */ > + data->mem_res = platform_get_resource(pdev, IORESOURCE_MEM, 0); > + if (!data->mem_res) { > + dev_err(&pdev->dev, "Specify memory area for this USB Host!\n"); > + ret = -ENODEV; > + goto err_get_host_resource; > + } > + > + /* Request the memory region for this USB Host. */ > + retp = devm_request_mem_region(&pdev->dev, data->mem_res->start, > + resource_size(data->mem_res), pdev->name); > + if (!retp) { > + dev_err(&pdev->dev, "USB Host memory area already in use!\n"); > + ret = -EBUSY; > + goto err_get_host_mem; > + } > + > + /* Map the memory region for USB Host. */ > + data->mem = devm_ioremap(&pdev->dev, data->mem_res->start, > + resource_size(data->mem_res)); > + if (!data->mem) { > + dev_err(&pdev->dev, "Memory mapping of USB Host failed!\n"); > + ret = -EFAULT; > + goto err_map_host_mem; > + } > + > + /* Get IRQ for EHCI host from resources. */ > + data->irq = platform_get_irq(pdev, 0); > + if (data->irq < 0) { > + dev_err(&pdev->dev, "Specify IRQ for this USB Host!\n"); > + ret = -ENODEV; > + goto err_get_host_irq; > + } > + > + /* > + * Now finally probe the Host driver! > + */ > + if (pdata->host_mode) { > + data->pdev_host = add_platform_device("mxs-ehci", -1, > + data, sizeof(*data), > + DMA_BIT_MASK(32)); > + if (!data->pdev_host) { > + dev_err(&pdev->dev, "Failed registering Host!\n"); > + ret = -ENODEV; > + goto err_register_host; > + } > + } else { > + data->pdev_gadget = add_platform_device("ci13xxx-mxs", -1, > + data, sizeof(*data), > + DMA_BIT_MASK(32)); > + if (!data->pdev_gadget) { > + dev_err(&pdev->dev, "Failed registering Host!\n"); > + ret = -ENODEV; > + goto err_register_gadget; > + } > + } > + > + /* > + * Initialize the transceiver > + */ > + phy = usb_get_transceiver(); > + if (!phy) { > + dev_err(&pdev->dev, "Unable to find transceiver.\n"); > + ret = -ENODEV; > + goto err_phy; > + } > + > + ret = usb_phy_init(phy); > + if (ret < 0) { > + dev_err(&pdev->dev, "Unable init transceiver\n"); > + ret = -ENODEV; > + goto err_phy_init; > + } > + > + /* Set up the PORTSCx register */ > + writel(0, data->mem + 0x144); > + > + return 0; > + > +err_phy_init: > + if (phy) > + usb_put_transceiver(phy); > +err_phy: > + if (data->pdev_gadget) > + platform_device_unregister(data->pdev_gadget); > +err_register_gadget: > + if (data->pdev_host) > + platform_device_unregister(data->pdev_host); > +err_register_host: > +err_get_host_irq: > + iounmap(data->mem); > +err_map_host_mem: > + release_mem_region(data->mem_res->start, > + resource_size(data->mem_res)); > +err_get_host_mem: > + data->mem_res = NULL; > +err_get_host_resource: > + clk_disable_unprepare(data->clk); > +err_prepare_host_clock: > + clk_put(data->clk); > +err_claim_host_clock: > +err_alloc_data: > + return ret; > +} > + > +static int __devexit imx_usb_remove(struct platform_device *pdev) > +{ > + struct imx_usb *data = platform_get_drvdata(pdev); > + > + if (data->pdev_gadget) > + platform_device_unregister(data->pdev_gadget); > + > + if (data->pdev_host) > + platform_device_unregister(data->pdev_host); > + > + iounmap(data->mem); > + release_mem_region(data->mem_res->start, > + resource_size(data->mem_res)); Again, you are using the managed versions of ioremap and request_mem_region. The whole point of these functions is that these resources are automatically released on driver exit (or failure at probe). Sascha -- Pengutronix e.K. | | Industrial Linux Solutions | http://www.pengutronix.de/ | Peiner Str. 6-8, 31137 Hildesheim, Germany | Phone: +49-5121-206917-0 | Amtsgericht Hildesheim, HRA 2686 | Fax: +49-5121-206917-5555 | ^ permalink raw reply [flat|nested] 28+ messages in thread
* [PATCH 08/11] MXS: Add imx-otg driver 2012-04-23 6:39 ` Sascha Hauer @ 2012-04-23 9:38 ` Marek Vasut 0 siblings, 0 replies; 28+ messages in thread From: Marek Vasut @ 2012-04-23 9:38 UTC (permalink / raw) To: linux-arm-kernel Dear Sascha Hauer, > On Sun, Apr 22, 2012 at 02:59:24PM +0200, Marek Vasut wrote: > > This driver handles claiming of clocks and memory areas. These are later > > properly delegated to it's child devices, the USB Host (ehci-mxs) and > > USB Gadget (ci13xxx-mxs). > > > > Signed-off-by: Marek Vasut <marex@denx.de> > > Cc: Chen Peter-B29397 <B29397@freescale.com> > > Cc: Detlev Zundel <dzu@denx.de> > > Cc: Fabio Estevam <festevam@gmail.com> > > Cc: Li Frank-B20596 <B20596@freescale.com> > > Cc: Lin Tony-B19295 <B19295@freescale.com> > > Cc: Linux USB <linux-usb@vger.kernel.org> > > Cc: Sascha Hauer <s.hauer@pengutronix.de> > > Cc: Shawn Guo <shawn.guo@freescale.com> > > Cc: Shawn Guo <shawn.guo@linaro.org> > > Cc: Stefano Babic <sbabic@denx.de> > > Cc: Subodh Nijsure <snijsure@grid-net.com> > > Cc: Tony Lin <tony.lin@freescale.com> > > Cc: Wolfgang Denk <wd@denx.de> > > --- > > > > drivers/usb/otg/Kconfig | 6 + > > drivers/usb/otg/Makefile | 1 + > > drivers/usb/otg/imx-otg.c | 282 > > +++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 289 > > insertions(+) > > create mode 100644 drivers/usb/otg/imx-otg.c > > > > diff --git a/drivers/usb/otg/Kconfig b/drivers/usb/otg/Kconfig > > index 5c87db0..e7c6325 100644 > > --- a/drivers/usb/otg/Kconfig > > +++ b/drivers/usb/otg/Kconfig > > @@ -116,6 +116,12 @@ config FSL_USB2_OTG > > > > help > > > > Enable this to support Freescale USB OTG transceiver. > > > > +config USB_IMX_COMPOSITE > > + bool > > + help > > + Composite driver that handles clock and memory mapping for > > + i.MX USB host and USB PHY. > > + > > > > config USB_MV_OTG > > > > tristate "Marvell USB OTG support" > > depends on USB_EHCI_MV && USB_MV_UDC && USB_SUSPEND > > > > diff --git a/drivers/usb/otg/Makefile b/drivers/usb/otg/Makefile > > index 41aa509..7d2c631 100644 > > --- a/drivers/usb/otg/Makefile > > +++ b/drivers/usb/otg/Makefile > > @@ -20,4 +20,5 @@ obj-$(CONFIG_USB_MSM_OTG) += msm_otg.o > > > > obj-$(CONFIG_AB8500_USB) += ab8500-usb.o > > fsl_usb2_otg-objs := fsl_otg.o otg_fsm.o > > obj-$(CONFIG_FSL_USB2_OTG) += fsl_usb2_otg.o > > > > +obj-$(CONFIG_USB_IMX_COMPOSITE) += imx-otg.o > > > > obj-$(CONFIG_USB_MV_OTG) += mv_otg.o > > > > diff --git a/drivers/usb/otg/imx-otg.c b/drivers/usb/otg/imx-otg.c > > new file mode 100644 > > index 0000000..249b6b5 > > --- /dev/null > > +++ b/drivers/usb/otg/imx-otg.c > > @@ -0,0 +1,282 @@ > > +/* > > + * drivers/usb/otg/imx-otg.c > > + * > > + * Freescale i.MX USB composite driver. > > + * > > + * Copyright (C) 2012 Marek Vasut <marex@denx.de> > > + * on behalf of DENX Software Engineering GmbH > > + * > > + * This program is free software; you can redistribute it and/or modify > > + * it under the terms of the GNU General Public License as published by > > + * the Free Software Foundation; either version 2 of the License, or > > + * (at your option) any later version. > > + * > > + * This program is distributed in the hope that it will be useful, > > + * but WITHOUT ANY WARRANTY; without even the implied warranty of > > + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the > > + * GNU General Public License for more details. > > + * > > + * You should have received a copy of the GNU General Public License > > + * along with this program; if not, write to the Free Software > > + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. > > + */ > > + > > +#include <linux/module.h> > > +#include <linux/platform_device.h> > > +#include <linux/dma-mapping.h> > > +#include <linux/usb.h> > > +#include <linux/usb/otg.h> > > +#include <linux/usb/hcd.h> > > +#include <linux/slab.h> > > +#include <linux/delay.h> > > +#include <linux/fsl/mxs-usb.h> > > +#include <linux/io.h> > > + > > +#include <mach/common.h> > > +#include <mach/hardware.h> > > +#include <mach/devices-common.h> > > + > > +/* > > + * Allocate platform device with the DMA mask, this is borrowed from > > + * arch/arm/mach-mxs/devices.c > > + */ > > +static struct platform_device *__devinit add_platform_device( > > + const char *name, int id, > > + const void *data, size_t size_data, u64 dmamask) > > +{ > > + int ret = -ENOMEM; > > + struct platform_device *pdev; > > + > > + pdev = platform_device_alloc(name, id); > > + if (!pdev) > > + goto err; > > + > > + if (dmamask) { > > + /* > > + * This memory isn't freed when the device is put, > > + * I don't have a nice idea for that though. Conceptually > > + * dma_mask in struct device should not be a pointer. > > + * See http://thread.gmane.org/gmane.linux.kernel.pci/9081 > > + */ > > + pdev->dev.dma_mask = > > + kmalloc(sizeof(*pdev->dev.dma_mask), GFP_KERNEL); > > + if (!pdev->dev.dma_mask) > > + /* ret is still -ENOMEM; */ > > + goto err; > > + > > + *pdev->dev.dma_mask = dmamask; > > + pdev->dev.coherent_dma_mask = dmamask; > > + } > > + > > + if (data) { > > + ret = platform_device_add_data(pdev, data, size_data); > > + if (ret) > > + goto err; > > + } > > + > > + ret = platform_device_add(pdev); > > + if (ret) { > > +err: > > + if (dmamask) > > + kfree(pdev->dev.dma_mask); > > + platform_device_put(pdev); > > + return ERR_PTR(ret); > > + } > > + > > + return pdev; > > +} > > + > > +static int __devinit imx_usb_probe(struct platform_device *pdev) > > +{ > > + struct imx_usb_platform_data *pdata = pdev->dev.platform_data; > > + struct imx_usb *data; > > + struct usb_phy *phy; > > + int ret; > > + void *retp = NULL; > > + > > + if (!pdata) { > > + dev_err(&pdev->dev, "No platform data supplied!\n"); > > + return -ENODEV; > > + } > > + > > + phy = usb_get_transceiver(); > > + if (!phy) > > + return -EPROBE_DEFER; > > + > > + /* > > + * Until further notice, this claims all necessary resources. > > + */ > > + > > + /* Allocate driver's private date. */ > > + data = devm_kzalloc(&pdev->dev, sizeof(*data), GFP_KERNEL); > > + if (!data) { > > + ret = -ENOMEM; > > + goto err_alloc_data; > > + } > > + > > + /* Claim the Host clock. */ > > + data->clk = clk_get(&pdev->dev, "usb"); > > + if (IS_ERR(data->clk)) { > > + dev_err(&pdev->dev, "Failed to claim clock for USB Host\n"); > > + ret = PTR_ERR(data->clk); > > + goto err_claim_host_clock; > > + } > > + > > + /* Prepare Host clock. */ > > + ret = clk_prepare_enable(data->clk); > > + if (ret) { > > + dev_err(&pdev->dev, "Failed to enable clock for USB Host.\n"); > > + goto err_prepare_host_clock; > > + } > > + > > + /* Get memory area for EHCI host from resources. */ > > + data->mem_res = platform_get_resource(pdev, IORESOURCE_MEM, 0); > > + if (!data->mem_res) { > > + dev_err(&pdev->dev, "Specify memory area for this USB Host!\n"); > > + ret = -ENODEV; > > + goto err_get_host_resource; > > + } > > + > > + /* Request the memory region for this USB Host. */ > > + retp = devm_request_mem_region(&pdev->dev, data->mem_res->start, > > + resource_size(data->mem_res), pdev->name); > > + if (!retp) { > > + dev_err(&pdev->dev, "USB Host memory area already in use!\n"); > > + ret = -EBUSY; > > + goto err_get_host_mem; > > + } > > + > > + /* Map the memory region for USB Host. */ > > + data->mem = devm_ioremap(&pdev->dev, data->mem_res->start, > > + resource_size(data->mem_res)); > > + if (!data->mem) { > > + dev_err(&pdev->dev, "Memory mapping of USB Host failed!\n"); > > + ret = -EFAULT; > > + goto err_map_host_mem; > > + } > > + > > + /* Get IRQ for EHCI host from resources. */ > > + data->irq = platform_get_irq(pdev, 0); > > + if (data->irq < 0) { > > + dev_err(&pdev->dev, "Specify IRQ for this USB Host!\n"); > > + ret = -ENODEV; > > + goto err_get_host_irq; > > + } > > + > > + /* > > + * Now finally probe the Host driver! > > + */ > > + if (pdata->host_mode) { > > + data->pdev_host = add_platform_device("mxs-ehci", -1, > > + data, sizeof(*data), > > + DMA_BIT_MASK(32)); > > + if (!data->pdev_host) { > > + dev_err(&pdev->dev, "Failed registering Host!\n"); > > + ret = -ENODEV; > > + goto err_register_host; > > + } > > + } else { > > + data->pdev_gadget = add_platform_device("ci13xxx-mxs", -1, > > + data, sizeof(*data), > > + DMA_BIT_MASK(32)); > > + if (!data->pdev_gadget) { > > + dev_err(&pdev->dev, "Failed registering Host!\n"); > > + ret = -ENODEV; > > + goto err_register_gadget; > > + } > > + } > > + > > + /* > > + * Initialize the transceiver > > + */ > > + phy = usb_get_transceiver(); > > + if (!phy) { > > + dev_err(&pdev->dev, "Unable to find transceiver.\n"); > > + ret = -ENODEV; > > + goto err_phy; > > + } > > + > > + ret = usb_phy_init(phy); > > + if (ret < 0) { > > + dev_err(&pdev->dev, "Unable init transceiver\n"); > > + ret = -ENODEV; > > + goto err_phy_init; > > + } > > + > > + /* Set up the PORTSCx register */ > > + writel(0, data->mem + 0x144); > > + > > + return 0; > > + > > +err_phy_init: > > + if (phy) > > + usb_put_transceiver(phy); > > +err_phy: > > + if (data->pdev_gadget) > > + platform_device_unregister(data->pdev_gadget); > > +err_register_gadget: > > + if (data->pdev_host) > > + platform_device_unregister(data->pdev_host); > > +err_register_host: > > +err_get_host_irq: > > + iounmap(data->mem); > > +err_map_host_mem: > > + release_mem_region(data->mem_res->start, > > + resource_size(data->mem_res)); > > +err_get_host_mem: > > + data->mem_res = NULL; > > +err_get_host_resource: > > + clk_disable_unprepare(data->clk); > > +err_prepare_host_clock: > > + clk_put(data->clk); > > +err_claim_host_clock: > > +err_alloc_data: > > + return ret; > > +} > > + > > +static int __devexit imx_usb_remove(struct platform_device *pdev) > > +{ > > + struct imx_usb *data = platform_get_drvdata(pdev); > > + > > + if (data->pdev_gadget) > > + platform_device_unregister(data->pdev_gadget); > > + > > + if (data->pdev_host) > > + platform_device_unregister(data->pdev_host); > > + > > + iounmap(data->mem); > > + release_mem_region(data->mem_res->start, > > + resource_size(data->mem_res)); > > Again, you are using the managed versions of ioremap and > request_mem_region. The whole point of these functions is that these > resources are automatically released on driver exit (or failure at > probe). Argh. Anyway, I'm more interested to hear your opinion on the general concept, esp. on Peter's comment on otg_set_host()/otg_set_peripheral() -- their implementation should be in the PHY driver and they should be called from EHCI host / ci13xxx gadget driver, correct? > Sascha ^ permalink raw reply [flat|nested] 28+ messages in thread
* [RFC PATCH 00/11 V5] MXS: Add i.MX28 USB Host driver 2012-04-22 12:59 ` [RFC PATCH 00/11 V4] " Marek Vasut 2012-04-22 12:59 ` [PATCH 08/11] MXS: Add imx-otg driver Marek Vasut @ 2012-04-24 3:18 ` Marek Vasut 2012-04-24 3:18 ` [PATCH 08/11] MXS: Add imx-otg driver Marek Vasut 1 sibling, 1 reply; 28+ messages in thread From: Marek Vasut @ 2012-04-24 3:18 UTC (permalink / raw) To: linux-arm-kernel From: Marek Vasut <marek.vasut@gmail.com> This patchset introduces the USB Host driver for i.MX28 CPU, utilising the generic USB PHY infrastructure. Also added is glue code for CI13xxx driver, to allow device mode. This patchset still does NOT support OTG mode, the device/host mode is selected via platform data. V2: Introduce stub imx-usb driver that then registers the PHY and EHCI drivers. V3: Add the HCD on demand based on the PHY's state (only add HCD if it's host). Currently, only the HOST mode is supported. V4: * Introduce ci13xxx gadget glue * Reorder patches in a more sensible order * Introduce platform data, containing VBUS GPIO and port mode (device/gadget) * Rename imx-usb to imx-otg * Drop mx28evk usb host patch * Use more devm_ function * Rework the mxs-phy to register the same interrupt as ehci-mxs (and effectivelly kill bogus otg_set_vbus() call from ehci-mxs ; use standard ehci irq handling in ehci-mxs) V5: * Finally move OTG IRQ handling into imx-otg * Move imx_otg_set_{host,peripheral}() into imx-otg * Move imx_otg_work() into imx-otg driver (now it all makes sense, yay!) Marek Vasut (11): MXS: Make clk_disable return integer MXS: Add USB EHCI and USB PHY clock handling MXS: Fixup i.MX233 USB base address name MXS: Add data shared between imx-otg and EHCI driver MXS: Modify the ci13xxx_udc to avoid adding UDC MXS: Add small registration glue for ci13xxx_udc MXS: Add separate MXS EHCI HCD driver MXS: Add imx-otg driver MXS: Add USB PHY driver MXS: Add platform registration hooks for USB EHCI MXS: Enable USB on M28EVK arch/arm/mach-mxs/Kconfig | 2 + arch/arm/mach-mxs/clock-mx28.c | 28 +- arch/arm/mach-mxs/devices-mx28.h | 5 + arch/arm/mach-mxs/devices/Kconfig | 3 + arch/arm/mach-mxs/devices/Makefile | 1 + arch/arm/mach-mxs/devices/platform-usb.c | 85 ++++ arch/arm/mach-mxs/include/mach/clock.h | 2 +- arch/arm/mach-mxs/include/mach/devices-common.h | 13 + arch/arm/mach-mxs/include/mach/mx23.h | 8 +- arch/arm/mach-mxs/mach-m28evk.c | 21 + drivers/usb/gadget/Kconfig | 17 + drivers/usb/gadget/Makefile | 1 + drivers/usb/gadget/ci13xxx_mxs.c | 67 ++++ drivers/usb/gadget/ci13xxx_udc.c | 12 +- drivers/usb/gadget/ci13xxx_udc.h | 1 + drivers/usb/host/Kconfig | 7 + drivers/usb/host/ehci-hcd.c | 5 + drivers/usb/host/ehci-mxs.c | 178 +++++++++ drivers/usb/otg/Kconfig | 16 + drivers/usb/otg/Makefile | 2 + drivers/usb/otg/imx-otg.c | 473 +++++++++++++++++++++++ drivers/usb/otg/mxs-phy.c | 237 ++++++++++++ include/linux/usb/mxs-usb.h | 95 +++++ 23 files changed, 1266 insertions(+), 13 deletions(-) create mode 100644 arch/arm/mach-mxs/devices/platform-usb.c create mode 100644 drivers/usb/gadget/ci13xxx_mxs.c create mode 100644 drivers/usb/host/ehci-mxs.c create mode 100644 drivers/usb/otg/imx-otg.c create mode 100644 drivers/usb/otg/mxs-phy.c create mode 100644 include/linux/usb/mxs-usb.h Cc: Chen Peter-B29397 <B29397@freescale.com> Cc: Detlev Zundel <dzu@denx.de> Cc: Fabio Estevam <festevam@gmail.com> Cc: Li Frank-B20596 <B20596@freescale.com> Cc: Lin Tony-B19295 <B19295@freescale.com> Cc: Linux USB <linux-usb@vger.kernel.org> Cc: Sascha Hauer <s.hauer@pengutronix.de> Cc: Shawn Guo <shawn.guo@freescale.com> Cc: Shawn Guo <shawn.guo@linaro.org> Cc: Stefano Babic <sbabic@denx.de> Cc: Subodh Nijsure <snijsure@grid-net.com> Cc: Tony Lin <tony.lin@freescale.com> Cc: Wolfgang Denk <wd@denx.de> -- 1.7.10 ^ permalink raw reply [flat|nested] 28+ messages in thread
* [PATCH 08/11] MXS: Add imx-otg driver 2012-04-24 3:18 ` [RFC PATCH 00/11 V5] MXS: Add i.MX28 USB Host driver Marek Vasut @ 2012-04-24 3:18 ` Marek Vasut 2012-04-24 14:48 ` Lothar Waßmann 0 siblings, 1 reply; 28+ messages in thread From: Marek Vasut @ 2012-04-24 3:18 UTC (permalink / raw) To: linux-arm-kernel This driver handles claiming of clocks and memory areas. These are later properly delegated to it's child devices, the USB Host (ehci-mxs) and USB Gadget (ci13xxx-mxs). Signed-off-by: Marek Vasut <marex@denx.de> Cc: Chen Peter-B29397 <B29397@freescale.com> Cc: Detlev Zundel <dzu@denx.de> Cc: Fabio Estevam <festevam@gmail.com> Cc: Li Frank-B20596 <B20596@freescale.com> Cc: Lin Tony-B19295 <B19295@freescale.com> Cc: Linux USB <linux-usb@vger.kernel.org> Cc: Sascha Hauer <s.hauer@pengutronix.de> Cc: Shawn Guo <shawn.guo@freescale.com> Cc: Shawn Guo <shawn.guo@linaro.org> Cc: Stefano Babic <sbabic@denx.de> Cc: Subodh Nijsure <snijsure@grid-net.com> Cc: Tony Lin <tony.lin@freescale.com> Cc: Wolfgang Denk <wd@denx.de> --- drivers/usb/otg/Kconfig | 6 + drivers/usb/otg/Makefile | 1 + drivers/usb/otg/imx-otg.c | 473 +++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 480 insertions(+) create mode 100644 drivers/usb/otg/imx-otg.c diff --git a/drivers/usb/otg/Kconfig b/drivers/usb/otg/Kconfig index 5c87db0..e7c6325 100644 --- a/drivers/usb/otg/Kconfig +++ b/drivers/usb/otg/Kconfig @@ -116,6 +116,12 @@ config FSL_USB2_OTG help Enable this to support Freescale USB OTG transceiver. +config USB_IMX_COMPOSITE + bool + help + Composite driver that handles clock and memory mapping for + i.MX USB host and USB PHY. + config USB_MV_OTG tristate "Marvell USB OTG support" depends on USB_EHCI_MV && USB_MV_UDC && USB_SUSPEND diff --git a/drivers/usb/otg/Makefile b/drivers/usb/otg/Makefile index 41aa509..7d2c631 100644 --- a/drivers/usb/otg/Makefile +++ b/drivers/usb/otg/Makefile @@ -20,4 +20,5 @@ obj-$(CONFIG_USB_MSM_OTG) += msm_otg.o obj-$(CONFIG_AB8500_USB) += ab8500-usb.o fsl_usb2_otg-objs := fsl_otg.o otg_fsm.o obj-$(CONFIG_FSL_USB2_OTG) += fsl_usb2_otg.o +obj-$(CONFIG_USB_IMX_COMPOSITE) += imx-otg.o obj-$(CONFIG_USB_MV_OTG) += mv_otg.o diff --git a/drivers/usb/otg/imx-otg.c b/drivers/usb/otg/imx-otg.c new file mode 100644 index 0000000..8440d909 --- /dev/null +++ b/drivers/usb/otg/imx-otg.c @@ -0,0 +1,473 @@ +/* + * drivers/usb/otg/imx-otg.c + * + * Freescale i.MX USB composite driver. + * + * Copyright (C) 2012 Marek Vasut <marex@denx.de> + * on behalf of DENX Software Engineering GmbH + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#include <linux/module.h> +#include <linux/platform_device.h> +#include <linux/dma-mapping.h> +#include <linux/slab.h> +#include <linux/delay.h> +#include <linux/usb/mxs-usb.h> +#include <linux/io.h> +#include <linux/gpio.h> + +#include <linux/usb.h> +#include <linux/usb/ch9.h> +#include <linux/usb/otg.h> +#include <linux/usb/gadget.h> +#include <linux/usb/hcd.h> +#include <linux/usb/ehci_def.h> + +#include <mach/common.h> +#include <mach/hardware.h> +#include <mach/devices-common.h> + +/* + * Allocate platform device with the DMA mask, this is borrowed from + * arch/arm/mach-mxs/devices.c + */ +static struct platform_device *__devinit add_platform_device( + const char *name, int id, + const void *data, size_t size_data, u64 dmamask) +{ + int ret = -ENOMEM; + struct platform_device *pdev; + + pdev = platform_device_alloc(name, id); + if (!pdev) + goto err; + + if (dmamask) { + /* + * This memory isn't freed when the device is put, + * I don't have a nice idea for that though. Conceptually + * dma_mask in struct device should not be a pointer. + * See http://thread.gmane.org/gmane.linux.kernel.pci/9081 + */ + pdev->dev.dma_mask = + kmalloc(sizeof(*pdev->dev.dma_mask), GFP_KERNEL); + if (!pdev->dev.dma_mask) + /* ret is still -ENOMEM; */ + goto err; + + *pdev->dev.dma_mask = dmamask; + pdev->dev.coherent_dma_mask = dmamask; + } + + if (data) { + ret = platform_device_add_data(pdev, data, size_data); + if (ret) + goto err; + } + + ret = platform_device_add(pdev); + if (ret) { +err: + if (dmamask) + kfree(pdev->dev.dma_mask); + platform_device_put(pdev); + return ERR_PTR(ret); + } + + return pdev; +} + +static int imx_otg_set_host(struct usb_otg *otg, struct usb_bus *host) +{ + struct imx_otg_priv *priv = container_of(otg, struct imx_otg_priv, otg); + struct usb_phy *x = otg->phy; + const uint32_t wakeup = + BM_USBPHY_CTRL_ENIDCHG_WKUP | BM_USBPHY_CTRL_ENDPDMCHG_WKUP; + + if (host) { + BUG_ON(otg->host); + otg->host = host; + + /* Enable the Host connection detect IRQ. */ + writel(wakeup, x->io_priv + HW_USBPHY_CTRL_SET); + } else { + BUG_ON(!otg->host); + + /* Disable the Host connection detect IRQ. */ + writel(wakeup, x->io_priv + HW_USBPHY_CTRL_CLR); + } + + schedule_work(&priv->work); + + return 0; +} + +static int imx_otg_set_peripheral(struct usb_otg *otg, struct usb_gadget *gg) +{ + struct imx_otg_priv *priv = container_of(otg, struct imx_otg_priv, otg); + struct usb_phy *x = otg->phy; + const uint32_t wakeup = + BM_USBPHY_CTRL_ENVBUSCHG_WKUP | BM_USBPHY_CTRL_ENDPDMCHG_WKUP; + + if (gg) { + BUG_ON(otg->gadget); + otg->gadget = gg; + + /* Enable the Host connection detect IRQ. */ + writel(wakeup, x->io_priv + HW_USBPHY_CTRL_SET); + } else { + BUG_ON(!otg->gadget); + + /* Disable the Host connection detect IRQ. */ + writel(wakeup, x->io_priv + HW_USBPHY_CTRL_CLR); + } + + schedule_work(&priv->work); + + return 0; +} + +static void imx_otg_work(struct work_struct *w) +{ + struct imx_otg_priv *priv = container_of(w, struct imx_otg_priv, work); + struct usb_hcd *hcd; + + switch (priv->cur_state) { + case OTG_STATE_A_HOST: + if (priv->new_state == OTG_STATE_UNDEFINED) { + hcd = bus_to_hcd(priv->otg.host); + usb_remove_hcd(hcd); + priv->cur_state = priv->new_state; + /* Turn off VBUS */ + gpio_set_value(priv->gpio_vbus, + priv->gpio_vbus_inverted); + } + break; + case OTG_STATE_B_PERIPHERAL: + if (priv->new_state == OTG_STATE_UNDEFINED) { + usb_del_gadget_udc(priv->otg.gadget); + priv->cur_state = priv->new_state; + } + break; + case OTG_STATE_UNDEFINED: + /* Check desired state. */ + switch (priv->new_state) { + case OTG_STATE_A_HOST: + if (!priv->otg.host) + break; + priv->cur_state = priv->new_state; + + /* Turn on VBUS */ + gpio_set_value(priv->gpio_vbus, + !priv->gpio_vbus_inverted); + + hcd = bus_to_hcd(priv->otg.host); + usb_add_hcd(hcd, hcd->irq, IRQF_SHARED); + break; + case OTG_STATE_B_PERIPHERAL: + if (!priv->otg.gadget) + break; + priv->cur_state = priv->new_state; + usb_add_gadget_udc(priv->dev, priv->otg.gadget); + break; + default: + break; + } + break; + + default: + break; + } +} + +static irqreturn_t imx_otg_irq(int irq, void *irqdata) +{ + struct imx_otg *data = irqdata; + struct imx_otg_priv *priv = &data->priv; + struct usb_otg *otg = &data->priv.otg; + struct usb_phy *x = otg->phy; + uint32_t status; + + if (otg->host) { + status = readl(data->mem + 0x144); + if (~(priv->status ^ status) & STS_PCD) + return IRQ_NONE; + + priv->status = status; + + if (priv->status & STS_PCD) { + writel(BM_USBPHY_CTRL_ENHOSTDISCONDETECT, + x->io_priv + HW_USBPHY_CTRL_CLR); + } else { + writel(BM_USBPHY_CTRL_ENHOSTDISCONDETECT, + x->io_priv + HW_USBPHY_CTRL_SET); + } + } + + return IRQ_NONE; +} + +static int __devinit imx_usb_probe(struct platform_device *pdev) +{ + struct imx_usb_platform_data *pdata = pdev->dev.platform_data; + struct imx_otg_priv *priv; + struct imx_otg *data; + struct usb_phy *phy; + struct usb_otg *otg; + int ret; + void *retp = NULL; + + if (!pdata) { + dev_err(&pdev->dev, "No platform data supplied!\n"); + return -ENODEV; + } + + phy = usb_get_transceiver(); + if (!phy) + return -EPROBE_DEFER; + + /* + * Until further notice, this claims all necessary resources. + */ + + /* Claim the VBUS GPIO */ + ret = gpio_request_one(pdata->gpio_vbus, GPIOF_DIR_OUT, "USB Power"); + if (ret) { + dev_err(&pdev->dev, "Failed to request USB Power GPIO!"); + ret = -EINVAL; + goto err_alloc_data; + } + + /* Disable the VBUS. */ + gpio_set_value(pdata->gpio_vbus, pdata->gpio_vbus_inverted); + + /* Allocate driver's private date. */ + data = devm_kzalloc(&pdev->dev, sizeof(*data), GFP_KERNEL); + if (!data) { + dev_err(&pdev->dev, "Failed to allocate OTG nodes data!\n"); + ret = -ENOMEM; + goto err_alloc_data; + } + + priv = &data->priv; + + /* Configure the OTG structure. */ + otg = &priv->otg; + otg->phy = phy; + otg->set_host = imx_otg_set_host; + otg->set_peripheral = imx_otg_set_peripheral; + phy->otg = otg; + + priv->dev = &pdev->dev; + priv->gpio_vbus = pdata->gpio_vbus; + priv->gpio_vbus_inverted = pdata->gpio_vbus_inverted; + priv->cur_state = OTG_STATE_UNDEFINED; + priv->new_state = OTG_STATE_UNDEFINED; + + if (pdata->host_mode && !pdata->gadget_mode) + priv->new_state = OTG_STATE_A_HOST; + else if (pdata->gadget_mode) + priv->new_state = OTG_STATE_B_PERIPHERAL; + + INIT_WORK(&priv->work, imx_otg_work); + + /* Claim the Host clock. */ + data->clk = clk_get(&pdev->dev, "usb"); + if (IS_ERR(data->clk)) { + dev_err(&pdev->dev, "Failed to claim clock for USB Host\n"); + ret = PTR_ERR(data->clk); + goto err_alloc_data; + } + + /* Prepare Host clock. */ + ret = clk_prepare_enable(data->clk); + if (ret) { + dev_err(&pdev->dev, "Failed to enable clock for USB Host.\n"); + goto err_prepare_host_clock; + } + + /* Get memory area for EHCI host from resources. */ + data->mem_res = platform_get_resource(pdev, IORESOURCE_MEM, 0); + if (!data->mem_res) { + dev_err(&pdev->dev, "Specify memory area for this USB Host!\n"); + ret = -ENODEV; + goto err_get_host_resource; + } + + /* Request the memory region for this USB Host. */ + retp = devm_request_mem_region(&pdev->dev, data->mem_res->start, + resource_size(data->mem_res), pdev->name); + if (!retp) { + dev_err(&pdev->dev, "USB Host memory area already in use!\n"); + ret = -EBUSY; + goto err_get_host_resource; + } + + /* Map the memory region for USB Host. */ + data->mem = devm_ioremap(&pdev->dev, data->mem_res->start, + resource_size(data->mem_res)); + if (!data->mem) { + dev_err(&pdev->dev, "Memory mapping of USB Host failed!\n"); + ret = -EFAULT; + goto err_get_host_resource; + } + + /* Get IRQ for EHCI host from resources. */ + data->irq = platform_get_irq(pdev, 0); + if (data->irq < 0) { + dev_err(&pdev->dev, "Specify IRQ for this USB Host!\n"); + ret = -ENODEV; + goto err_get_host_resource; + } + + /* Get IRQ for PHY wakeup from resources. */ + data->irq_wakeup = platform_get_irq(pdev, 1); + if (data->irq_wakeup < 0) { + dev_err(&pdev->dev, "Specify wakeup IRQ for this USB Host!\n"); + ret = -ENODEV; + goto err_get_host_resource; + } + + /* Request the EHCI IRQ. */ + ret = devm_request_irq(&pdev->dev, data->irq, imx_otg_irq, + IRQF_SHARED, "imx-otg-usb-irq", data); + if (ret < 0) { + dev_err(&pdev->dev, "Failed to request IRQ!\n"); + goto err_get_host_resource; + } + + /* Request the PHY IRQ. */ + ret = devm_request_irq(&pdev->dev, data->irq_wakeup, imx_otg_irq, + IRQF_SHARED, "imx-otg-wakeup-irq", data); + if (ret < 0) { + dev_err(&pdev->dev, "Failed to request IRQ!\n"); + goto err_get_host_resource; + } + + /* + * Now finally probe the Host driver! + */ + if (pdata->gadget_mode) { + data->pdev_gadget = add_platform_device("ci13xxx-mxs", -1, + data, sizeof(*data), + DMA_BIT_MASK(32)); + if (!data->pdev_gadget) { + dev_err(&pdev->dev, "Failed registering Host!\n"); + ret = -ENODEV; + goto err_register_gadget; + } + } + + if (pdata->host_mode) { + data->pdev_host = add_platform_device("mxs-ehci", -1, + data, sizeof(*data), + DMA_BIT_MASK(32)); + if (!data->pdev_host) { + dev_err(&pdev->dev, "Failed registering Host!\n"); + ret = -ENODEV; + goto err_get_host_resource; + } + } + + /* + * Initialize the transceiver + */ + phy = usb_get_transceiver(); + if (!phy) { + dev_err(&pdev->dev, "Unable to find transceiver.\n"); + ret = -ENODEV; + goto err_phy; + } + + ret = usb_phy_init(phy); + if (ret < 0) { + dev_err(&pdev->dev, "Unable init transceiver\n"); + ret = -ENODEV; + goto err_phy_init; + } + + return 0; + +err_phy_init: + if (phy) + usb_put_transceiver(phy); +err_phy: + if (data->pdev_gadget) + platform_device_unregister(data->pdev_gadget); +err_register_gadget: + if (data->pdev_host) + platform_device_unregister(data->pdev_host); +err_get_host_resource: + clk_disable_unprepare(data->clk); +err_prepare_host_clock: + clk_put(data->clk); +err_alloc_data: + return ret; +} + +static int __devexit imx_usb_remove(struct platform_device *pdev) +{ + struct imx_otg *data = platform_get_drvdata(pdev); + struct imx_otg_priv *priv = &data->priv; + + /* Stop the PHY work. */ + cancel_work_sync(&priv->work); + + /* Shut off VBUS. */ + gpio_set_value(priv->gpio_vbus, priv->gpio_vbus_inverted); + gpio_free(priv->gpio_vbus); + + /* Deregister both Gadget and Host driver. */ + if (data->pdev_gadget) + platform_device_unregister(data->pdev_gadget); + + if (data->pdev_host) + platform_device_unregister(data->pdev_host); + + /* Stop the clock. */ + clk_disable_unprepare(data->clk); + clk_put(data->clk); + + return 0; +} + +static struct platform_driver imx_usb_driver = { + .probe = imx_usb_probe, + .remove = __devexit_p(imx_usb_remove), + .driver = { + .name = "imx-otg", + .owner = THIS_MODULE, + }, +}; + +static int __init imx_usb_init(void) +{ + return platform_driver_register(&imx_usb_driver); +} + +static void __exit imx_usb_exit(void) +{ + platform_driver_unregister(&imx_usb_driver); +} + +module_init(imx_usb_init); +module_exit(imx_usb_exit); + +MODULE_ALIAS("platform:imx-otg"); +MODULE_AUTHOR("Marek Vasut <marex@denx.de>"); +MODULE_DESCRIPTION("Freescale i.MX USB composite driver"); +MODULE_LICENSE("GPL"); -- 1.7.10 ^ permalink raw reply related [flat|nested] 28+ messages in thread
* [PATCH 08/11] MXS: Add imx-otg driver 2012-04-24 3:18 ` [PATCH 08/11] MXS: Add imx-otg driver Marek Vasut @ 2012-04-24 14:48 ` Lothar Waßmann 2012-04-24 14:50 ` Sascha Hauer 0 siblings, 1 reply; 28+ messages in thread From: Lothar Waßmann @ 2012-04-24 14:48 UTC (permalink / raw) To: linux-arm-kernel Hi, Marek Vasut writes: > This driver handles claiming of clocks and memory areas. These are later > properly delegated to it's child devices, the USB Host (ehci-mxs) and > USB Gadget (ci13xxx-mxs). > > Signed-off-by: Marek Vasut <marex@denx.de> > Cc: Chen Peter-B29397 <B29397@freescale.com> > Cc: Detlev Zundel <dzu@denx.de> > Cc: Fabio Estevam <festevam@gmail.com> > Cc: Li Frank-B20596 <B20596@freescale.com> > Cc: Lin Tony-B19295 <B19295@freescale.com> > Cc: Linux USB <linux-usb@vger.kernel.org> > Cc: Sascha Hauer <s.hauer@pengutronix.de> > Cc: Shawn Guo <shawn.guo@freescale.com> > Cc: Shawn Guo <shawn.guo@linaro.org> > Cc: Stefano Babic <sbabic@denx.de> > Cc: Subodh Nijsure <snijsure@grid-net.com> > Cc: Tony Lin <tony.lin@freescale.com> > Cc: Wolfgang Denk <wd@denx.de> > --- > drivers/usb/otg/Kconfig | 6 + > drivers/usb/otg/Makefile | 1 + > drivers/usb/otg/imx-otg.c | 473 +++++++++++++++++++++++++++++++++++++++++++++ > 3 files changed, 480 insertions(+) > create mode 100644 drivers/usb/otg/imx-otg.c > > diff --git a/drivers/usb/otg/Kconfig b/drivers/usb/otg/Kconfig > index 5c87db0..e7c6325 100644 > --- a/drivers/usb/otg/Kconfig > +++ b/drivers/usb/otg/Kconfig > @@ -116,6 +116,12 @@ config FSL_USB2_OTG > help > Enable this to support Freescale USB OTG transceiver. > > +config USB_IMX_COMPOSITE > + bool > + help > + Composite driver that handles clock and memory mapping for > + i.MX USB host and USB PHY. > + > config USB_MV_OTG > tristate "Marvell USB OTG support" > depends on USB_EHCI_MV && USB_MV_UDC && USB_SUSPEND > diff --git a/drivers/usb/otg/Makefile b/drivers/usb/otg/Makefile > index 41aa509..7d2c631 100644 > --- a/drivers/usb/otg/Makefile > +++ b/drivers/usb/otg/Makefile > @@ -20,4 +20,5 @@ obj-$(CONFIG_USB_MSM_OTG) += msm_otg.o > obj-$(CONFIG_AB8500_USB) += ab8500-usb.o > fsl_usb2_otg-objs := fsl_otg.o otg_fsm.o > obj-$(CONFIG_FSL_USB2_OTG) += fsl_usb2_otg.o > +obj-$(CONFIG_USB_IMX_COMPOSITE) += imx-otg.o > obj-$(CONFIG_USB_MV_OTG) += mv_otg.o > diff --git a/drivers/usb/otg/imx-otg.c b/drivers/usb/otg/imx-otg.c > new file mode 100644 > index 0000000..8440d909 > --- /dev/null > +++ b/drivers/usb/otg/imx-otg.c > @@ -0,0 +1,473 @@ > +/* > + * drivers/usb/otg/imx-otg.c > + * > + * Freescale i.MX USB composite driver. > + * > + * Copyright (C) 2012 Marek Vasut <marex@denx.de> > + * on behalf of DENX Software Engineering GmbH > + * > + * This program is free software; you can redistribute it and/or modify > + * it under the terms of the GNU General Public License as published by > + * the Free Software Foundation; either version 2 of the License, or > + * (at your option) any later version. > + * > + * This program is distributed in the hope that it will be useful, > + * but WITHOUT ANY WARRANTY; without even the implied warranty of > + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the > + * GNU General Public License for more details. > + * > + * You should have received a copy of the GNU General Public License > + * along with this program; if not, write to the Free Software > + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. > + */ > + Why do you call this driver imx-otg when it is actually MXS specific? How would you call a corresponding driver for the remaining i.MX processors? Lothar Wa?mann -- ___________________________________________________________ Ka-Ro electronics GmbH | Pascalstra?e 22 | D - 52076 Aachen Phone: +49 2408 1402-0 | Fax: +49 2408 1402-10 Gesch?ftsf?hrer: Matthias Kaussen Handelsregistereintrag: Amtsgericht Aachen, HRB 4996 www.karo-electronics.de | info at karo-electronics.de ___________________________________________________________ ^ permalink raw reply [flat|nested] 28+ messages in thread
* [PATCH 08/11] MXS: Add imx-otg driver 2012-04-24 14:48 ` Lothar Waßmann @ 2012-04-24 14:50 ` Sascha Hauer 2012-04-24 16:13 ` Lothar Waßmann 0 siblings, 1 reply; 28+ messages in thread From: Sascha Hauer @ 2012-04-24 14:50 UTC (permalink / raw) To: linux-arm-kernel On Tue, Apr 24, 2012 at 04:48:14PM +0200, Lothar Wa?mann wrote: > Hi, > > Marek Vasut writes: > > This driver handles claiming of clocks and memory areas. These are later > > properly delegated to it's child devices, the USB Host (ehci-mxs) and > > USB Gadget (ci13xxx-mxs). > > > > Signed-off-by: Marek Vasut <marex@denx.de> > > Cc: Chen Peter-B29397 <B29397@freescale.com> > > Cc: Detlev Zundel <dzu@denx.de> > > Cc: Fabio Estevam <festevam@gmail.com> > > Cc: Li Frank-B20596 <B20596@freescale.com> > > Cc: Lin Tony-B19295 <B19295@freescale.com> > > Cc: Linux USB <linux-usb@vger.kernel.org> > > Cc: Sascha Hauer <s.hauer@pengutronix.de> > > Cc: Shawn Guo <shawn.guo@freescale.com> > > Cc: Shawn Guo <shawn.guo@linaro.org> > > Cc: Stefano Babic <sbabic@denx.de> > > Cc: Subodh Nijsure <snijsure@grid-net.com> > > Cc: Tony Lin <tony.lin@freescale.com> > > Cc: Wolfgang Denk <wd@denx.de> > > --- > > drivers/usb/otg/Kconfig | 6 + > > drivers/usb/otg/Makefile | 1 + > > drivers/usb/otg/imx-otg.c | 473 +++++++++++++++++++++++++++++++++++++++++++++ > > 3 files changed, 480 insertions(+) > > create mode 100644 drivers/usb/otg/imx-otg.c > > > > diff --git a/drivers/usb/otg/Kconfig b/drivers/usb/otg/Kconfig > > index 5c87db0..e7c6325 100644 > > --- a/drivers/usb/otg/Kconfig > > +++ b/drivers/usb/otg/Kconfig > > @@ -116,6 +116,12 @@ config FSL_USB2_OTG > > help > > Enable this to support Freescale USB OTG transceiver. > > > > +config USB_IMX_COMPOSITE > > + bool > > + help > > + Composite driver that handles clock and memory mapping for > > + i.MX USB host and USB PHY. > > + > > config USB_MV_OTG > > tristate "Marvell USB OTG support" > > depends on USB_EHCI_MV && USB_MV_UDC && USB_SUSPEND > > diff --git a/drivers/usb/otg/Makefile b/drivers/usb/otg/Makefile > > index 41aa509..7d2c631 100644 > > --- a/drivers/usb/otg/Makefile > > +++ b/drivers/usb/otg/Makefile > > @@ -20,4 +20,5 @@ obj-$(CONFIG_USB_MSM_OTG) += msm_otg.o > > obj-$(CONFIG_AB8500_USB) += ab8500-usb.o > > fsl_usb2_otg-objs := fsl_otg.o otg_fsm.o > > obj-$(CONFIG_FSL_USB2_OTG) += fsl_usb2_otg.o > > +obj-$(CONFIG_USB_IMX_COMPOSITE) += imx-otg.o > > obj-$(CONFIG_USB_MV_OTG) += mv_otg.o > > diff --git a/drivers/usb/otg/imx-otg.c b/drivers/usb/otg/imx-otg.c > > new file mode 100644 > > index 0000000..8440d909 > > --- /dev/null > > +++ b/drivers/usb/otg/imx-otg.c > > @@ -0,0 +1,473 @@ > > +/* > > + * drivers/usb/otg/imx-otg.c > > + * > > + * Freescale i.MX USB composite driver. > > + * > > + * Copyright (C) 2012 Marek Vasut <marex@denx.de> > > + * on behalf of DENX Software Engineering GmbH > > + * > > + * This program is free software; you can redistribute it and/or modify > > + * it under the terms of the GNU General Public License as published by > > + * the Free Software Foundation; either version 2 of the License, or > > + * (at your option) any later version. > > + * > > + * This program is distributed in the hope that it will be useful, > > + * but WITHOUT ANY WARRANTY; without even the implied warranty of > > + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the > > + * GNU General Public License for more details. > > + * > > + * You should have received a copy of the GNU General Public License > > + * along with this program; if not, write to the Free Software > > + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. > > + */ > > + > Why do you call this driver imx-otg when it is actually MXS specific? > How would you call a corresponding driver for the remaining i.MX > processors? This is the driver for the all i.MX processors. Sascha -- Pengutronix e.K. | | Industrial Linux Solutions | http://www.pengutronix.de/ | Peiner Str. 6-8, 31137 Hildesheim, Germany | Phone: +49-5121-206917-0 | Amtsgericht Hildesheim, HRA 2686 | Fax: +49-5121-206917-5555 | ^ permalink raw reply [flat|nested] 28+ messages in thread
* [PATCH 08/11] MXS: Add imx-otg driver 2012-04-24 14:50 ` Sascha Hauer @ 2012-04-24 16:13 ` Lothar Waßmann 2012-04-24 16:47 ` Sascha Hauer 0 siblings, 1 reply; 28+ messages in thread From: Lothar Waßmann @ 2012-04-24 16:13 UTC (permalink / raw) To: linux-arm-kernel Hi, Sascha Hauer writes: > On Tue, Apr 24, 2012 at 04:48:14PM +0200, Lothar Wa?mann wrote: > > Hi, > > > > Marek Vasut writes: > > > This driver handles claiming of clocks and memory areas. These are later > > > properly delegated to it's child devices, the USB Host (ehci-mxs) and > > > USB Gadget (ci13xxx-mxs). > > > > > > Signed-off-by: Marek Vasut <marex@denx.de> > > > Cc: Chen Peter-B29397 <B29397@freescale.com> > > > Cc: Detlev Zundel <dzu@denx.de> > > > Cc: Fabio Estevam <festevam@gmail.com> > > > Cc: Li Frank-B20596 <B20596@freescale.com> > > > Cc: Lin Tony-B19295 <B19295@freescale.com> > > > Cc: Linux USB <linux-usb@vger.kernel.org> > > > Cc: Sascha Hauer <s.hauer@pengutronix.de> > > > Cc: Shawn Guo <shawn.guo@freescale.com> > > > Cc: Shawn Guo <shawn.guo@linaro.org> > > > Cc: Stefano Babic <sbabic@denx.de> > > > Cc: Subodh Nijsure <snijsure@grid-net.com> > > > Cc: Tony Lin <tony.lin@freescale.com> > > > Cc: Wolfgang Denk <wd@denx.de> > > > --- > > > drivers/usb/otg/Kconfig | 6 + > > > drivers/usb/otg/Makefile | 1 + > > > drivers/usb/otg/imx-otg.c | 473 +++++++++++++++++++++++++++++++++++++++++++++ > > > 3 files changed, 480 insertions(+) > > > create mode 100644 drivers/usb/otg/imx-otg.c > > > > > > diff --git a/drivers/usb/otg/Kconfig b/drivers/usb/otg/Kconfig > > > index 5c87db0..e7c6325 100644 > > > --- a/drivers/usb/otg/Kconfig > > > +++ b/drivers/usb/otg/Kconfig > > > @@ -116,6 +116,12 @@ config FSL_USB2_OTG > > > help > > > Enable this to support Freescale USB OTG transceiver. > > > > > > +config USB_IMX_COMPOSITE > > > + bool > > > + help > > > + Composite driver that handles clock and memory mapping for > > > + i.MX USB host and USB PHY. > > > + > > > config USB_MV_OTG > > > tristate "Marvell USB OTG support" > > > depends on USB_EHCI_MV && USB_MV_UDC && USB_SUSPEND > > > diff --git a/drivers/usb/otg/Makefile b/drivers/usb/otg/Makefile > > > index 41aa509..7d2c631 100644 > > > --- a/drivers/usb/otg/Makefile > > > +++ b/drivers/usb/otg/Makefile > > > @@ -20,4 +20,5 @@ obj-$(CONFIG_USB_MSM_OTG) += msm_otg.o > > > obj-$(CONFIG_AB8500_USB) += ab8500-usb.o > > > fsl_usb2_otg-objs := fsl_otg.o otg_fsm.o > > > obj-$(CONFIG_FSL_USB2_OTG) += fsl_usb2_otg.o > > > +obj-$(CONFIG_USB_IMX_COMPOSITE) += imx-otg.o > > > obj-$(CONFIG_USB_MV_OTG) += mv_otg.o > > > diff --git a/drivers/usb/otg/imx-otg.c b/drivers/usb/otg/imx-otg.c > > > new file mode 100644 > > > index 0000000..8440d909 > > > --- /dev/null > > > +++ b/drivers/usb/otg/imx-otg.c > > > @@ -0,0 +1,473 @@ > > > +/* > > > + * drivers/usb/otg/imx-otg.c > > > + * > > > + * Freescale i.MX USB composite driver. > > > + * > > > + * Copyright (C) 2012 Marek Vasut <marex@denx.de> > > > + * on behalf of DENX Software Engineering GmbH > > > + * > > > + * This program is free software; you can redistribute it and/or modify > > > + * it under the terms of the GNU General Public License as published by > > > + * the Free Software Foundation; either version 2 of the License, or > > > + * (at your option) any later version. > > > + * > > > + * This program is distributed in the hope that it will be useful, > > > + * but WITHOUT ANY WARRANTY; without even the implied warranty of > > > + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the > > > + * GNU General Public License for more details. > > > + * > > > + * You should have received a copy of the GNU General Public License > > > + * along with this program; if not, write to the Free Software > > > + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. > > > + */ > > > + > > Why do you call this driver imx-otg when it is actually MXS specific? > > How would you call a corresponding driver for the remaining i.MX > > processors? > > This is the driver for the all i.MX processors. > If it is for all i.MX processors, it shouldn't access MXS specific registers, like: + writel(wakeup, x->io_priv + HW_USBPHY_CTRL_SET); Lothar Wa?mann -- ___________________________________________________________ Ka-Ro electronics GmbH | Pascalstra?e 22 | D - 52076 Aachen Phone: +49 2408 1402-0 | Fax: +49 2408 1402-10 Gesch?ftsf?hrer: Matthias Kaussen Handelsregistereintrag: Amtsgericht Aachen, HRB 4996 www.karo-electronics.de | info at karo-electronics.de ___________________________________________________________ ^ permalink raw reply [flat|nested] 28+ messages in thread
* [PATCH 08/11] MXS: Add imx-otg driver 2012-04-24 16:13 ` Lothar Waßmann @ 2012-04-24 16:47 ` Sascha Hauer 2012-04-24 17:49 ` Marek Vasut 0 siblings, 1 reply; 28+ messages in thread From: Sascha Hauer @ 2012-04-24 16:47 UTC (permalink / raw) To: linux-arm-kernel On Tue, Apr 24, 2012 at 06:13:04PM +0200, Lothar Wa?mann wrote: > Hi, > > Sascha Hauer writes: > > On Tue, Apr 24, 2012 at 04:48:14PM +0200, Lothar Wa?mann wrote: > > > Hi, > > > > > > Marek Vasut writes: > > > > This driver handles claiming of clocks and memory areas. These are later > > > > properly delegated to it's child devices, the USB Host (ehci-mxs) and > > > > USB Gadget (ci13xxx-mxs). > > > > > > > > Signed-off-by: Marek Vasut <marex@denx.de> > > > > Cc: Chen Peter-B29397 <B29397@freescale.com> > > > > Cc: Detlev Zundel <dzu@denx.de> > > > > Cc: Fabio Estevam <festevam@gmail.com> > > > > Cc: Li Frank-B20596 <B20596@freescale.com> > > > > Cc: Lin Tony-B19295 <B19295@freescale.com> > > > > Cc: Linux USB <linux-usb@vger.kernel.org> > > > > Cc: Sascha Hauer <s.hauer@pengutronix.de> > > > > Cc: Shawn Guo <shawn.guo@freescale.com> > > > > Cc: Shawn Guo <shawn.guo@linaro.org> > > > > Cc: Stefano Babic <sbabic@denx.de> > > > > Cc: Subodh Nijsure <snijsure@grid-net.com> > > > > Cc: Tony Lin <tony.lin@freescale.com> > > > > Cc: Wolfgang Denk <wd@denx.de> > > > > --- > > > > drivers/usb/otg/Kconfig | 6 + > > > > drivers/usb/otg/Makefile | 1 + > > > > drivers/usb/otg/imx-otg.c | 473 +++++++++++++++++++++++++++++++++++++++++++++ > > > > 3 files changed, 480 insertions(+) > > > > create mode 100644 drivers/usb/otg/imx-otg.c > > > > > > > > diff --git a/drivers/usb/otg/Kconfig b/drivers/usb/otg/Kconfig > > > > index 5c87db0..e7c6325 100644 > > > > --- a/drivers/usb/otg/Kconfig > > > > +++ b/drivers/usb/otg/Kconfig > > > > @@ -116,6 +116,12 @@ config FSL_USB2_OTG > > > > help > > > > Enable this to support Freescale USB OTG transceiver. > > > > > > > > +config USB_IMX_COMPOSITE > > > > + bool > > > > + help > > > > + Composite driver that handles clock and memory mapping for > > > > + i.MX USB host and USB PHY. > > > > + > > > > config USB_MV_OTG > > > > tristate "Marvell USB OTG support" > > > > depends on USB_EHCI_MV && USB_MV_UDC && USB_SUSPEND > > > > diff --git a/drivers/usb/otg/Makefile b/drivers/usb/otg/Makefile > > > > index 41aa509..7d2c631 100644 > > > > --- a/drivers/usb/otg/Makefile > > > > +++ b/drivers/usb/otg/Makefile > > > > @@ -20,4 +20,5 @@ obj-$(CONFIG_USB_MSM_OTG) += msm_otg.o > > > > obj-$(CONFIG_AB8500_USB) += ab8500-usb.o > > > > fsl_usb2_otg-objs := fsl_otg.o otg_fsm.o > > > > obj-$(CONFIG_FSL_USB2_OTG) += fsl_usb2_otg.o > > > > +obj-$(CONFIG_USB_IMX_COMPOSITE) += imx-otg.o > > > > obj-$(CONFIG_USB_MV_OTG) += mv_otg.o > > > > diff --git a/drivers/usb/otg/imx-otg.c b/drivers/usb/otg/imx-otg.c > > > > new file mode 100644 > > > > index 0000000..8440d909 > > > > --- /dev/null > > > > +++ b/drivers/usb/otg/imx-otg.c > > > > @@ -0,0 +1,473 @@ > > > > +/* > > > > + * drivers/usb/otg/imx-otg.c > > > > + * > > > > + * Freescale i.MX USB composite driver. > > > > + * > > > > + * Copyright (C) 2012 Marek Vasut <marex@denx.de> > > > > + * on behalf of DENX Software Engineering GmbH > > > > + * > > > > + * This program is free software; you can redistribute it and/or modify > > > > + * it under the terms of the GNU General Public License as published by > > > > + * the Free Software Foundation; either version 2 of the License, or > > > > + * (at your option) any later version. > > > > + * > > > > + * This program is distributed in the hope that it will be useful, > > > > + * but WITHOUT ANY WARRANTY; without even the implied warranty of > > > > + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the > > > > + * GNU General Public License for more details. > > > > + * > > > > + * You should have received a copy of the GNU General Public License > > > > + * along with this program; if not, write to the Free Software > > > > + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. > > > > + */ > > > > + > > > Why do you call this driver imx-otg when it is actually MXS specific? > > > How would you call a corresponding driver for the remaining i.MX > > > processors? > > > > This is the driver for the all i.MX processors. > > > If it is for all i.MX processors, it shouldn't access MXS specific > registers, like: > + writel(wakeup, x->io_priv + HW_USBPHY_CTRL_SET); Indeed not. This should be done in the phy driver. Sascha -- Pengutronix e.K. | | Industrial Linux Solutions | http://www.pengutronix.de/ | Peiner Str. 6-8, 31137 Hildesheim, Germany | Phone: +49-5121-206917-0 | Amtsgericht Hildesheim, HRA 2686 | Fax: +49-5121-206917-5555 | ^ permalink raw reply [flat|nested] 28+ messages in thread
* [PATCH 08/11] MXS: Add imx-otg driver 2012-04-24 16:47 ` Sascha Hauer @ 2012-04-24 17:49 ` Marek Vasut 2012-04-24 20:49 ` Sascha Hauer 0 siblings, 1 reply; 28+ messages in thread From: Marek Vasut @ 2012-04-24 17:49 UTC (permalink / raw) To: linux-arm-kernel Dear Sascha Hauer, > On Tue, Apr 24, 2012 at 06:13:04PM +0200, Lothar Wa?mann wrote: > > Hi, > > > > Sascha Hauer writes: > > > On Tue, Apr 24, 2012 at 04:48:14PM +0200, Lothar Wa?mann wrote: > > > > Hi, > > > > > > > > Marek Vasut writes: > > > > > This driver handles claiming of clocks and memory areas. These are > > > > > later properly delegated to it's child devices, the USB Host > > > > > (ehci-mxs) and USB Gadget (ci13xxx-mxs). > > > > > > > > > > Signed-off-by: Marek Vasut <marex@denx.de> > > > > > Cc: Chen Peter-B29397 <B29397@freescale.com> > > > > > Cc: Detlev Zundel <dzu@denx.de> > > > > > Cc: Fabio Estevam <festevam@gmail.com> > > > > > Cc: Li Frank-B20596 <B20596@freescale.com> > > > > > Cc: Lin Tony-B19295 <B19295@freescale.com> > > > > > Cc: Linux USB <linux-usb@vger.kernel.org> > > > > > Cc: Sascha Hauer <s.hauer@pengutronix.de> > > > > > Cc: Shawn Guo <shawn.guo@freescale.com> > > > > > Cc: Shawn Guo <shawn.guo@linaro.org> > > > > > Cc: Stefano Babic <sbabic@denx.de> > > > > > Cc: Subodh Nijsure <snijsure@grid-net.com> > > > > > Cc: Tony Lin <tony.lin@freescale.com> > > > > > Cc: Wolfgang Denk <wd@denx.de> > > > > > --- > > > > > > > > > > drivers/usb/otg/Kconfig | 6 + > > > > > drivers/usb/otg/Makefile | 1 + > > > > > drivers/usb/otg/imx-otg.c | 473 > > > > > +++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, > > > > > 480 insertions(+) > > > > > create mode 100644 drivers/usb/otg/imx-otg.c > > > > > > > > > > diff --git a/drivers/usb/otg/Kconfig b/drivers/usb/otg/Kconfig > > > > > index 5c87db0..e7c6325 100644 > > > > > --- a/drivers/usb/otg/Kconfig > > > > > +++ b/drivers/usb/otg/Kconfig > > > > > @@ -116,6 +116,12 @@ config FSL_USB2_OTG > > > > > > > > > > help > > > > > > > > > > Enable this to support Freescale USB OTG transceiver. > > > > > > > > > > +config USB_IMX_COMPOSITE > > > > > + bool > > > > > + help > > > > > + Composite driver that handles clock and memory mapping for > > > > > + i.MX USB host and USB PHY. > > > > > + > > > > > > > > > > config USB_MV_OTG > > > > > > > > > > tristate "Marvell USB OTG support" > > > > > depends on USB_EHCI_MV && USB_MV_UDC && USB_SUSPEND > > > > > > > > > > diff --git a/drivers/usb/otg/Makefile b/drivers/usb/otg/Makefile > > > > > index 41aa509..7d2c631 100644 > > > > > --- a/drivers/usb/otg/Makefile > > > > > +++ b/drivers/usb/otg/Makefile > > > > > @@ -20,4 +20,5 @@ obj-$(CONFIG_USB_MSM_OTG) += msm_otg.o > > > > > > > > > > obj-$(CONFIG_AB8500_USB) += ab8500-usb.o > > > > > fsl_usb2_otg-objs := fsl_otg.o otg_fsm.o > > > > > obj-$(CONFIG_FSL_USB2_OTG) += fsl_usb2_otg.o > > > > > > > > > > +obj-$(CONFIG_USB_IMX_COMPOSITE) += imx-otg.o > > > > > > > > > > obj-$(CONFIG_USB_MV_OTG) += mv_otg.o > > > > > > > > > > diff --git a/drivers/usb/otg/imx-otg.c b/drivers/usb/otg/imx-otg.c > > > > > new file mode 100644 > > > > > index 0000000..8440d909 > > > > > --- /dev/null > > > > > +++ b/drivers/usb/otg/imx-otg.c > > > > > @@ -0,0 +1,473 @@ > > > > > +/* > > > > > + * drivers/usb/otg/imx-otg.c > > > > > + * > > > > > + * Freescale i.MX USB composite driver. > > > > > + * > > > > > + * Copyright (C) 2012 Marek Vasut <marex@denx.de> > > > > > + * on behalf of DENX Software Engineering GmbH > > > > > + * > > > > > + * This program is free software; you can redistribute it and/or > > > > > modify + * it under the terms of the GNU General Public License as > > > > > published by + * the Free Software Foundation; either version 2 of > > > > > the License, or + * (at your option) any later version. > > > > > + * > > > > > + * This program is distributed in the hope that it will be useful, > > > > > + * but WITHOUT ANY WARRANTY; without even the implied warranty of > > > > > + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the > > > > > + * GNU General Public License for more details. > > > > > + * > > > > > + * You should have received a copy of the GNU General Public > > > > > License + * along with this program; if not, write to the Free > > > > > Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, > > > > > USA. + */ > > > > > + > > > > > > > > Why do you call this driver imx-otg when it is actually MXS specific? > > > > How would you call a corresponding driver for the remaining i.MX > > > > processors? > > > > > > This is the driver for the all i.MX processors. > > > > If it is for all i.MX processors, it shouldn't access MXS specific > > registers, like: > > + writel(wakeup, x->io_priv + HW_USBPHY_CTRL_SET); > > Indeed not. This should be done in the phy driver. Ok, so now you figured out that all these set_host() set_peripheral() work() calls should be back in the phy driver, not in the imx-otg? hm ... so back to the V4 of the patchset? > > Sascha Best regards, Marek Vasut ^ permalink raw reply [flat|nested] 28+ messages in thread
* [PATCH 08/11] MXS: Add imx-otg driver 2012-04-24 17:49 ` Marek Vasut @ 2012-04-24 20:49 ` Sascha Hauer 2012-04-24 20:58 ` Marek Vasut 0 siblings, 1 reply; 28+ messages in thread From: Sascha Hauer @ 2012-04-24 20:49 UTC (permalink / raw) To: linux-arm-kernel On Tue, Apr 24, 2012 at 07:49:37PM +0200, Marek Vasut wrote: > > > > > > > > > > Why do you call this driver imx-otg when it is actually MXS specific? > > > > > How would you call a corresponding driver for the remaining i.MX > > > > > processors? > > > > > > > > This is the driver for the all i.MX processors. > > > > > > If it is for all i.MX processors, it shouldn't access MXS specific > > > registers, like: > > > + writel(wakeup, x->io_priv + HW_USBPHY_CTRL_SET); > > > > Indeed not. This should be done in the phy driver. > > Ok, so now you figured out that all these set_host() set_peripheral() work() > calls should be back in the phy driver, not in the imx-otg? hm ... so back to > the V4 of the patchset? Not really, you are just not allowed to put phy code into imx-otg.c, because the phy may be another one on a different SoC. That said, I am a bit confused at the moment. There seems to be no method to activate the interrupt in the phy. Sascha -- Pengutronix e.K. | | Industrial Linux Solutions | http://www.pengutronix.de/ | Peiner Str. 6-8, 31137 Hildesheim, Germany | Phone: +49-5121-206917-0 | Amtsgericht Hildesheim, HRA 2686 | Fax: +49-5121-206917-5555 | ^ permalink raw reply [flat|nested] 28+ messages in thread
* [PATCH 08/11] MXS: Add imx-otg driver 2012-04-24 20:49 ` Sascha Hauer @ 2012-04-24 20:58 ` Marek Vasut 2012-04-25 0:17 ` Chen Peter-B29397 0 siblings, 1 reply; 28+ messages in thread From: Marek Vasut @ 2012-04-24 20:58 UTC (permalink / raw) To: linux-arm-kernel Dear Sascha Hauer, > On Tue, Apr 24, 2012 at 07:49:37PM +0200, Marek Vasut wrote: > > > > > > Why do you call this driver imx-otg when it is actually MXS > > > > > > specific? How would you call a corresponding driver for the > > > > > > remaining i.MX processors? > > > > > > > > > > This is the driver for the all i.MX processors. > > > > > > > > If it is for all i.MX processors, it shouldn't access MXS specific > > > > registers, like: > > > > + writel(wakeup, x->io_priv + HW_USBPHY_CTRL_SET); > > > > > > Indeed not. This should be done in the phy driver. > > > > Ok, so now you figured out that all these set_host() set_peripheral() > > work() calls should be back in the phy driver, not in the imx-otg? hm > > ... so back to the V4 of the patchset? > > Not really, you are just not allowed to put phy code into imx-otg.c, > because the phy may be another one on a different SoC. > > That said, I am a bit confused at the moment. There seems to be no > method to activate the interrupt in the phy. There is more to be confused about -- you don't get the host/device connection interrupt from the PHY, but you dig one of them from the EHCI host and the other from the EHCI host too -- which is pretty messed up already. We can certainly use IRQF_SHARED to trap some of the interrupts in the PHY code, but that's still quite weird. > Sascha Best regards, Marek Vasut ^ permalink raw reply [flat|nested] 28+ messages in thread
* [PATCH 08/11] MXS: Add imx-otg driver 2012-04-24 20:58 ` Marek Vasut @ 2012-04-25 0:17 ` Chen Peter-B29397 0 siblings, 0 replies; 28+ messages in thread From: Chen Peter-B29397 @ 2012-04-25 0:17 UTC (permalink / raw) To: linux-arm-kernel > > There is more to be confused about -- you don't get the host/device > connection > interrupt from the PHY, but you dig one of them from the EHCI host and > the other > from the EHCI host too -- which is pretty messed up already. > > We can certainly use IRQF_SHARED to trap some of the interrupts in the > PHY code, > but that's still quite weird. > Below need to be implemented at phy driver: - struct usb_phy; - phy's interrupt which is only used for handle wakeup issue, PHY's interrupt line is NOT the same with controller's, so you don't need to use IRQF_SHARED, and request the same irq with controller's. Below need to be implemented at otg driver: - struct usb_otg; - manage PHY through PHY interfaces which are implemented at phy driver. - OTG interrupt, it only handles ID/vbus interrupt. - OTG switch routine, it handles host and device's add/remove operation due to id/vbus change and some operation_mode defined at platform_data or DT in fture. > > Sascha > > Best regards, > Marek Vasut ^ permalink raw reply [flat|nested] 28+ messages in thread
end of thread, other threads:[~2012-05-01 1:56 UTC | newest] Thread overview: 28+ messages (download: mbox.gz / follow: Atom feed) -- links below jump to the message on this page -- 2012-04-29 22:34 [RFC PATCH 00/11 V6] MXS: Add i.MX28 USB Host driver Marek Vasut 2012-04-29 22:34 ` [PATCH 01/11] MXS: Make clk_disable return integer Marek Vasut 2012-04-29 22:34 ` [PATCH 02/11] MXS: Add USB EHCI and USB PHY clock handling Marek Vasut 2012-04-29 22:34 ` [PATCH 03/11] MXS: Fixup i.MX233 USB base address name Marek Vasut 2012-04-29 22:34 ` [PATCH 04/11] MXS: Add data shared between imx-otg and EHCI driver Marek Vasut 2012-04-29 22:34 ` [PATCH 05/11] MXS: Modify the ci13xxx_udc to avoid adding UDC Marek Vasut 2012-04-29 22:34 ` [PATCH 06/11] MXS: Add small registration glue for ci13xxx_udc Marek Vasut 2012-04-29 22:34 ` [PATCH 07/11] MXS: Add separate MXS EHCI HCD driver Marek Vasut 2012-04-29 22:34 ` [PATCH 08/11] MXS: Add imx-otg driver Marek Vasut 2012-04-30 6:13 ` Lothar Waßmann 2012-04-30 12:24 ` Marek Vasut 2012-04-29 22:34 ` [PATCH 09/11] MXS: Add USB PHY driver Marek Vasut 2012-04-29 22:34 ` [PATCH 10/11] MXS: Add platform registration hooks for USB EHCI Marek Vasut 2012-04-29 22:34 ` [PATCH 11/11] MXS: Enable USB on M28EVK Marek Vasut 2012-04-29 23:00 ` [RFC PATCH 00/11 V6] MXS: Add i.MX28 USB Host driver Marek Vasut -- strict thread matches above, loose matches on Subject: below -- 2012-05-01 1:55 [RFC PATCH 00/11 V7] " Marek Vasut 2012-05-01 1:56 ` [PATCH 08/11] MXS: Add imx-otg driver Marek Vasut 2012-04-18 17:46 [RFC PATCH 00/10 V3] MXS: Add i.MX28 USB Host driver Marek Vasut 2012-04-22 12:59 ` [RFC PATCH 00/11 V4] " Marek Vasut 2012-04-22 12:59 ` [PATCH 08/11] MXS: Add imx-otg driver Marek Vasut 2012-04-23 6:39 ` Sascha Hauer 2012-04-23 9:38 ` Marek Vasut 2012-04-24 3:18 ` [RFC PATCH 00/11 V5] MXS: Add i.MX28 USB Host driver Marek Vasut 2012-04-24 3:18 ` [PATCH 08/11] MXS: Add imx-otg driver Marek Vasut 2012-04-24 14:48 ` Lothar Waßmann 2012-04-24 14:50 ` Sascha Hauer 2012-04-24 16:13 ` Lothar Waßmann 2012-04-24 16:47 ` Sascha Hauer 2012-04-24 17:49 ` Marek Vasut 2012-04-24 20:49 ` Sascha Hauer 2012-04-24 20:58 ` Marek Vasut 2012-04-25 0:17 ` Chen Peter-B29397
This is an external index of several public inboxes, see mirroring instructions on how to clone and mirror all data and code used by this external index.