* [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; 18+ 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] 18+ 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; 18+ 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] 18+ 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; 18+ 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] 18+ 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; 18+ 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] 18+ 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; 18+ 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] 18+ 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; 18+ 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] 18+ 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; 18+ 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] 18+ 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; 18+ 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] 18+ 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; 18+ 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] 18+ 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; 18+ 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] 18+ 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; 18+ 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] 18+ 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; 18+ 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] 18+ 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; 18+ 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] 18+ 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; 18+ 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] 18+ messages in thread