From 6dba39e278b81665a838f37a75fe37b89f3ce610 Mon Sep 17 00:00:00 2001 From: Keshava Munegowda Date: Sun, 21 Nov 2010 23:23:40 +0530 Subject: usb: ehci-omap: update clock names to be more generic Rename usbhost2_120m_fck to usbhost_hs_fck and usbhost1_48m_fck to usbhost_fs_fck, to better reflect the clocks' functionalities. In OMAP4, the frequencies for the corresponding clocks are not necessarily the same as with OMAP3, however the functionalities are. Signed-off-by: Keshava Munegowda Signed-off-by: Anand Gadiyar --- drivers/usb/host/ehci-omap.c | 44 ++++++++++++++++++++++---------------------- 1 file changed, 22 insertions(+), 22 deletions(-) (limited to 'drivers/usb/host') diff --git a/drivers/usb/host/ehci-omap.c b/drivers/usb/host/ehci-omap.c index 116ae280053..d042bdefa2b 100644 --- a/drivers/usb/host/ehci-omap.c +++ b/drivers/usb/host/ehci-omap.c @@ -156,8 +156,8 @@ struct ehci_hcd_omap { struct device *dev; struct clk *usbhost_ick; - struct clk *usbhost2_120m_fck; - struct clk *usbhost1_48m_fck; + struct clk *usbhost_hs_fck; + struct clk *usbhost_fs_fck; struct clk *usbtll_fck; struct clk *usbtll_ick; @@ -286,19 +286,19 @@ static int omap_start_ehc(struct ehci_hcd_omap *omap, struct usb_hcd *hcd) } clk_enable(omap->usbhost_ick); - omap->usbhost2_120m_fck = clk_get(omap->dev, "usbhost_120m_fck"); - if (IS_ERR(omap->usbhost2_120m_fck)) { - ret = PTR_ERR(omap->usbhost2_120m_fck); + omap->usbhost_hs_fck = clk_get(omap->dev, "usbhost_120m_fck"); + if (IS_ERR(omap->usbhost_hs_fck)) { + ret = PTR_ERR(omap->usbhost_hs_fck); goto err_host_120m_fck; } - clk_enable(omap->usbhost2_120m_fck); + clk_enable(omap->usbhost_hs_fck); - omap->usbhost1_48m_fck = clk_get(omap->dev, "usbhost_48m_fck"); - if (IS_ERR(omap->usbhost1_48m_fck)) { - ret = PTR_ERR(omap->usbhost1_48m_fck); + omap->usbhost_fs_fck = clk_get(omap->dev, "usbhost_48m_fck"); + if (IS_ERR(omap->usbhost_fs_fck)) { + ret = PTR_ERR(omap->usbhost_fs_fck); goto err_host_48m_fck; } - clk_enable(omap->usbhost1_48m_fck); + clk_enable(omap->usbhost_fs_fck); if (omap->phy_reset) { /* Refer: ISSUE1 */ @@ -472,8 +472,8 @@ err_tll_ick: clk_put(omap->usbtll_fck); err_tll_fck: - clk_disable(omap->usbhost1_48m_fck); - clk_put(omap->usbhost1_48m_fck); + clk_disable(omap->usbhost_fs_fck); + clk_put(omap->usbhost_fs_fck); if (omap->phy_reset) { if (gpio_is_valid(omap->reset_gpio_port[0])) @@ -484,8 +484,8 @@ err_tll_fck: } err_host_48m_fck: - clk_disable(omap->usbhost2_120m_fck); - clk_put(omap->usbhost2_120m_fck); + clk_disable(omap->usbhost_hs_fck); + clk_put(omap->usbhost_hs_fck); err_host_120m_fck: clk_disable(omap->usbhost_ick); @@ -550,16 +550,16 @@ static void omap_stop_ehc(struct ehci_hcd_omap *omap, struct usb_hcd *hcd) omap->usbhost_ick = NULL; } - if (omap->usbhost1_48m_fck != NULL) { - clk_disable(omap->usbhost1_48m_fck); - clk_put(omap->usbhost1_48m_fck); - omap->usbhost1_48m_fck = NULL; + if (omap->usbhost_fs_fck != NULL) { + clk_disable(omap->usbhost_fs_fck); + clk_put(omap->usbhost_fs_fck); + omap->usbhost_fs_fck = NULL; } - if (omap->usbhost2_120m_fck != NULL) { - clk_disable(omap->usbhost2_120m_fck); - clk_put(omap->usbhost2_120m_fck); - omap->usbhost2_120m_fck = NULL; + if (omap->usbhost_hs_fck != NULL) { + clk_disable(omap->usbhost_hs_fck); + clk_put(omap->usbhost_hs_fck); + omap->usbhost_hs_fck = NULL; } if (omap->usbtll_ick != NULL) { -- cgit v1.2.3-70-g09d2 From c072604115ab50d023eb5c33d4f3229400e441f4 Mon Sep 17 00:00:00 2001 From: Keshava Munegowda Date: Sun, 21 Nov 2010 23:23:40 +0530 Subject: usb: ehci-omap: don't hard-code TLL channel count Make the TLL channel count a parameter instead of a hardcoded value. This allows us to be flexible with future OMAP revisions which could have a different number of channels. Signed-off-by: Keshava Munegowda Signed-off-by: Anand Gadiyar --- drivers/usb/host/ehci-omap.c | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) (limited to 'drivers/usb/host') diff --git a/drivers/usb/host/ehci-omap.c b/drivers/usb/host/ehci-omap.c index d042bdefa2b..d60efdc9b14 100644 --- a/drivers/usb/host/ehci-omap.c +++ b/drivers/usb/host/ehci-omap.c @@ -191,13 +191,14 @@ struct ehci_hcd_omap { /*-------------------------------------------------------------------------*/ -static void omap_usb_utmi_init(struct ehci_hcd_omap *omap, u8 tll_channel_mask) +static void omap_usb_utmi_init(struct ehci_hcd_omap *omap, u8 tll_channel_mask, + u8 tll_channel_count) { unsigned reg; int i; /* Program the 3 TLL channels upfront */ - for (i = 0; i < OMAP_TLL_CHANNEL_COUNT; i++) { + for (i = 0; i < tll_channel_count; i++) { reg = ehci_omap_readl(omap->tll_base, OMAP_TLL_CHANNEL_CONF(i)); /* Disable AutoIdle, BitStuffing and use SDR Mode */ @@ -217,7 +218,7 @@ static void omap_usb_utmi_init(struct ehci_hcd_omap *omap, u8 tll_channel_mask) ehci_omap_writel(omap->tll_base, OMAP_TLL_SHARED_CONF, reg); /* Enable channels now */ - for (i = 0; i < OMAP_TLL_CHANNEL_COUNT; i++) { + for (i = 0; i < tll_channel_count; i++) { reg = ehci_omap_readl(omap->tll_base, OMAP_TLL_CHANNEL_CONF(i)); /* Enable only the reg that is needed */ @@ -438,7 +439,7 @@ static int omap_start_ehc(struct ehci_hcd_omap *omap, struct usb_hcd *hcd) tll_ch_mask |= OMAP_TLL_CHANNEL_3_EN_MASK; /* Enable UTMI mode for required TLL channels */ - omap_usb_utmi_init(omap, tll_ch_mask); + omap_usb_utmi_init(omap, tll_ch_mask, OMAP_TLL_CHANNEL_COUNT); } if (omap->phy_reset) { -- cgit v1.2.3-70-g09d2 From 7f124f4b353672bc150af959910cfc2a9778260a Mon Sep 17 00:00:00 2001 From: Keshava Munegowda Date: Sun, 21 Nov 2010 23:23:41 +0530 Subject: usb: ehci: introduce CONFIG_USB_EHCI_HCD_OMAP Introduce the CONFIG_USB_EHCI_HCD_OMAP option to select EHCI support on OMAP3 and later chips. This scales better than having a long line of dependencies for each new OMAP with EHCI support. Signed-off-by: Keshava Munegowda Signed-off-by: Anand Gadiyar --- drivers/usb/host/Kconfig | 8 ++++++++ drivers/usb/host/ehci-hcd.c | 2 +- 2 files changed, 9 insertions(+), 1 deletion(-) (limited to 'drivers/usb/host') diff --git a/drivers/usb/host/Kconfig b/drivers/usb/host/Kconfig index 2391c396ca3..6a7c688b478 100644 --- a/drivers/usb/host/Kconfig +++ b/drivers/usb/host/Kconfig @@ -133,6 +133,14 @@ config USB_EHCI_MXC ---help--- Variation of ARC USB block used in some Freescale chips. +config USB_EHCI_HCD_OMAP + bool "EHCI support for OMAP3 and later chips" + depends on USB_EHCI_HCD && ARCH_OMAP + default y + --- help --- + Enables support for the on-chip EHCI controller on + OMAP3 and later chips. + config USB_EHCI_HCD_PPC_OF bool "EHCI support for PPC USB controller on OF platform bus" depends on USB_EHCI_HCD && PPC_OF diff --git a/drivers/usb/host/ehci-hcd.c b/drivers/usb/host/ehci-hcd.c index 87157db155f..2f06ba47195 100644 --- a/drivers/usb/host/ehci-hcd.c +++ b/drivers/usb/host/ehci-hcd.c @@ -1171,7 +1171,7 @@ MODULE_LICENSE ("GPL"); #define PLATFORM_DRIVER ehci_hcd_au1xxx_driver #endif -#ifdef CONFIG_ARCH_OMAP3 +#ifdef CONFIG_USB_EHCI_HCD_OMAP #include "ehci-omap.c" #define PLATFORM_DRIVER ehci_hcd_omap_driver #endif -- cgit v1.2.3-70-g09d2 From c5dff5545c97ab33bdb2a529a2375966ceb0700c Mon Sep 17 00:00:00 2001 From: Anand Gadiyar Date: Sun, 21 Nov 2010 23:23:41 +0530 Subject: usb: ehci-omap: use clkdev aliases for functional clocks Use the recently updated aliases to get functional clocks needed by the driver. This allows the driver to acquire OMAP4-specific clocks without having to use different clock names for OMAP3 and OMAP4. Signed-off-by: Anand Gadiyar --- drivers/usb/host/ehci-omap.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers/usb/host') diff --git a/drivers/usb/host/ehci-omap.c b/drivers/usb/host/ehci-omap.c index d60efdc9b14..7a4682c4ff6 100644 --- a/drivers/usb/host/ehci-omap.c +++ b/drivers/usb/host/ehci-omap.c @@ -287,14 +287,14 @@ static int omap_start_ehc(struct ehci_hcd_omap *omap, struct usb_hcd *hcd) } clk_enable(omap->usbhost_ick); - omap->usbhost_hs_fck = clk_get(omap->dev, "usbhost_120m_fck"); + omap->usbhost_hs_fck = clk_get(omap->dev, "hs_fck"); if (IS_ERR(omap->usbhost_hs_fck)) { ret = PTR_ERR(omap->usbhost_hs_fck); goto err_host_120m_fck; } clk_enable(omap->usbhost_hs_fck); - omap->usbhost_fs_fck = clk_get(omap->dev, "usbhost_48m_fck"); + omap->usbhost_fs_fck = clk_get(omap->dev, "fs_fck"); if (IS_ERR(omap->usbhost_fs_fck)) { ret = PTR_ERR(omap->usbhost_fs_fck); goto err_host_48m_fck; -- cgit v1.2.3-70-g09d2 From a42ccdc14de388a35ad0e8057543369351395eb9 Mon Sep 17 00:00:00 2001 From: Anand Gadiyar Date: Sun, 21 Nov 2010 23:23:41 +0530 Subject: usb: ehci-omap: add helpers for checking port mode Introduce helper functions to test port mode. These checks are performed in several places in the driver, and these helpers improve readability. Signed-off-by: Anand Gadiyar --- drivers/usb/host/ehci-omap.c | 21 ++++++++++++--------- 1 file changed, 12 insertions(+), 9 deletions(-) (limited to 'drivers/usb/host') diff --git a/drivers/usb/host/ehci-omap.c b/drivers/usb/host/ehci-omap.c index 7a4682c4ff6..dd9d5c1d9a8 100644 --- a/drivers/usb/host/ehci-omap.c +++ b/drivers/usb/host/ehci-omap.c @@ -127,6 +127,9 @@ #define EHCI_INSNREG05_ULPI_EXTREGADD_SHIFT 8 #define EHCI_INSNREG05_ULPI_WRDATA_SHIFT 0 +#define is_ehci_phy_mode(x) (x == EHCI_HCD_OMAP_MODE_PHY) +#define is_ehci_tll_mode(x) (x == EHCI_HCD_OMAP_MODE_TLL) + /*-------------------------------------------------------------------------*/ static inline void ehci_omap_writel(void __iomem *base, u32 reg, u32 val) @@ -387,27 +390,27 @@ static int omap_start_ehc(struct ehci_hcd_omap *omap, struct usb_hcd *hcd) /* Bypass the TLL module for PHY mode operation */ if (cpu_is_omap3430() && (omap_rev() <= OMAP3430_REV_ES2_1)) { dev_dbg(omap->dev, "OMAP3 ES version <= ES2.1\n"); - if ((omap->port_mode[0] == EHCI_HCD_OMAP_MODE_PHY) || - (omap->port_mode[1] == EHCI_HCD_OMAP_MODE_PHY) || - (omap->port_mode[2] == EHCI_HCD_OMAP_MODE_PHY)) + if (is_ehci_phy_mode(omap->port_mode[0]) || + is_ehci_phy_mode(omap->port_mode[1]) || + is_ehci_phy_mode(omap->port_mode[2])) reg &= ~OMAP_UHH_HOSTCONFIG_ULPI_BYPASS; else reg |= OMAP_UHH_HOSTCONFIG_ULPI_BYPASS; } else { dev_dbg(omap->dev, "OMAP3 ES version > ES2.1\n"); - if (omap->port_mode[0] == EHCI_HCD_OMAP_MODE_PHY) + if (is_ehci_phy_mode(omap->port_mode[0])) reg &= ~OMAP_UHH_HOSTCONFIG_ULPI_P1_BYPASS; - else if (omap->port_mode[0] == EHCI_HCD_OMAP_MODE_TLL) + else if (is_ehci_tll_mode(omap->port_mode[0])) reg |= OMAP_UHH_HOSTCONFIG_ULPI_P1_BYPASS; - if (omap->port_mode[1] == EHCI_HCD_OMAP_MODE_PHY) + if (is_ehci_phy_mode(omap->port_mode[1])) reg &= ~OMAP_UHH_HOSTCONFIG_ULPI_P2_BYPASS; - else if (omap->port_mode[1] == EHCI_HCD_OMAP_MODE_TLL) + else if (is_ehci_tll_mode(omap->port_mode[1])) reg |= OMAP_UHH_HOSTCONFIG_ULPI_P2_BYPASS; - if (omap->port_mode[2] == EHCI_HCD_OMAP_MODE_PHY) + if (is_ehci_phy_mode(omap->port_mode[2])) reg &= ~OMAP_UHH_HOSTCONFIG_ULPI_P3_BYPASS; - else if (omap->port_mode[2] == EHCI_HCD_OMAP_MODE_TLL) + else if (is_ehci_tll_mode(omap->port_mode[2])) reg |= OMAP_UHH_HOSTCONFIG_ULPI_P3_BYPASS; } -- cgit v1.2.3-70-g09d2 From 4792a15bf0f388838c3e16636f961c99bc2f3572 Mon Sep 17 00:00:00 2001 From: Anand Gadiyar Date: Sun, 21 Nov 2010 23:23:42 +0530 Subject: usb: ehci-omap: Add OMAP4 support Update the ehci-omap glue layer to support the controller in the OMAP4. Major differences from OMAP3 is that the OMAP4 has per-port clocking, and supports ULPI output clocking mode. The old input clocking mode is not supported. Also, there are only 2 externally available ports as against 3 in the OMAP3. The third port is internally tied off and should not be used. Signed-off-by: Keshava Munegowda Signed-off-by: Anand Gadiyar --- drivers/usb/host/ehci-omap.c | 254 ++++++++++++++++++++++++++++++++++++------- 1 file changed, 212 insertions(+), 42 deletions(-) (limited to 'drivers/usb/host') diff --git a/drivers/usb/host/ehci-omap.c b/drivers/usb/host/ehci-omap.c index dd9d5c1d9a8..0374eb47f09 100644 --- a/drivers/usb/host/ehci-omap.c +++ b/drivers/usb/host/ehci-omap.c @@ -1,11 +1,12 @@ /* - * ehci-omap.c - driver for USBHOST on OMAP 34xx processor + * ehci-omap.c - driver for USBHOST on OMAP3/4 processors * - * Bus Glue for OMAP34xx USBHOST 3 port EHCI controller - * Tested on OMAP3430 ES2.0 SDP + * Bus Glue for the EHCI controllers in OMAP3/4 + * Tested on several OMAP3 boards, and OMAP4 Pandaboard * - * Copyright (C) 2007-2008 Texas Instruments, Inc. + * Copyright (C) 2007-2010 Texas Instruments, Inc. * Author: Vikram Pandita + * Author: Anand Gadiyar * * Copyright (C) 2009 Nokia Corporation * Contact: Felipe Balbi @@ -26,11 +27,14 @@ * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * - * TODO (last updated Feb 12, 2010): + * TODO (last updated Nov 21, 2010): * - add kernel-doc * - enable AUTOIDLE * - add suspend/resume * - move workarounds to board-files + * - factor out code common to OHCI + * - add HSIC and TLL support + * - convert to use hwmod and runtime PM */ #include @@ -114,6 +118,23 @@ #define OMAP_UHH_HOSTCONFIG_P2_CONNECT_STATUS (1 << 9) #define OMAP_UHH_HOSTCONFIG_P3_CONNECT_STATUS (1 << 10) +/* OMAP4-specific defines */ +#define OMAP4_UHH_SYSCONFIG_IDLEMODE_CLEAR (3 << 2) +#define OMAP4_UHH_SYSCONFIG_NOIDLE (1 << 2) + +#define OMAP4_UHH_SYSCONFIG_STDBYMODE_CLEAR (3 << 4) +#define OMAP4_UHH_SYSCONFIG_NOSTDBY (1 << 4) +#define OMAP4_UHH_SYSCONFIG_SOFTRESET (1 << 0) + +#define OMAP4_P1_MODE_CLEAR (3 << 16) +#define OMAP4_P1_MODE_TLL (1 << 16) +#define OMAP4_P1_MODE_HSIC (3 << 16) +#define OMAP4_P2_MODE_CLEAR (3 << 18) +#define OMAP4_P2_MODE_TLL (1 << 18) +#define OMAP4_P2_MODE_HSIC (3 << 18) + +#define OMAP_REV2_TLL_CHANNEL_COUNT 2 + #define OMAP_UHH_DEBUG_CSR (0x44) /* EHCI Register Set */ @@ -127,8 +148,16 @@ #define EHCI_INSNREG05_ULPI_EXTREGADD_SHIFT 8 #define EHCI_INSNREG05_ULPI_WRDATA_SHIFT 0 +/* Values of UHH_REVISION - Note: these are not given in the TRM */ +#define OMAP_EHCI_REV1 0x00000010 /* OMAP3 */ +#define OMAP_EHCI_REV2 0x50700100 /* OMAP4 */ + +#define is_omap_ehci_rev1(x) (x->omap_ehci_rev == OMAP_EHCI_REV1) +#define is_omap_ehci_rev2(x) (x->omap_ehci_rev == OMAP_EHCI_REV2) + #define is_ehci_phy_mode(x) (x == EHCI_HCD_OMAP_MODE_PHY) #define is_ehci_tll_mode(x) (x == EHCI_HCD_OMAP_MODE_TLL) +#define is_ehci_hsic_mode(x) (x == EHCI_HCD_OMAP_MODE_HSIC) /*-------------------------------------------------------------------------*/ @@ -163,6 +192,10 @@ struct ehci_hcd_omap { struct clk *usbhost_fs_fck; struct clk *usbtll_fck; struct clk *usbtll_ick; + struct clk *xclk60mhsp1_ck; + struct clk *xclk60mhsp2_ck; + struct clk *utmi_p1_fck; + struct clk *utmi_p2_fck; /* FIXME the following two workarounds are * board specific not silicon-specific so these @@ -179,6 +212,9 @@ struct ehci_hcd_omap { /* phy reset workaround */ int phy_reset; + /* IP revision */ + u32 omap_ehci_rev; + /* desired phy_mode: TLL, PHY */ enum ehci_hcd_omap_mode port_mode[OMAP3_HS_USB_PORTS]; @@ -337,6 +373,80 @@ static int omap_start_ehc(struct ehci_hcd_omap *omap, struct usb_hcd *hcd) } clk_enable(omap->usbtll_ick); + omap->omap_ehci_rev = ehci_omap_readl(omap->uhh_base, + OMAP_UHH_REVISION); + dev_dbg(omap->dev, "OMAP UHH_REVISION 0x%x\n", + omap->omap_ehci_rev); + + /* + * Enable per-port clocks as needed (newer controllers only). + * - External ULPI clock for PHY mode + * - Internal clocks for TLL and HSIC modes (TODO) + */ + if (is_omap_ehci_rev2(omap)) { + switch (omap->port_mode[0]) { + case EHCI_HCD_OMAP_MODE_PHY: + omap->xclk60mhsp1_ck = clk_get(omap->dev, + "xclk60mhsp1_ck"); + if (IS_ERR(omap->xclk60mhsp1_ck)) { + ret = PTR_ERR(omap->xclk60mhsp1_ck); + dev_err(omap->dev, + "Unable to get Port1 ULPI clock\n"); + } + + omap->utmi_p1_fck = clk_get(omap->dev, + "utmi_p1_gfclk"); + if (IS_ERR(omap->utmi_p1_fck)) { + ret = PTR_ERR(omap->utmi_p1_fck); + dev_err(omap->dev, + "Unable to get utmi_p1_fck\n"); + } + + ret = clk_set_parent(omap->utmi_p1_fck, + omap->xclk60mhsp1_ck); + if (ret != 0) { + dev_err(omap->dev, + "Unable to set P1 f-clock\n"); + } + break; + case EHCI_HCD_OMAP_MODE_TLL: + /* TODO */ + default: + break; + } + switch (omap->port_mode[1]) { + case EHCI_HCD_OMAP_MODE_PHY: + omap->xclk60mhsp2_ck = clk_get(omap->dev, + "xclk60mhsp2_ck"); + if (IS_ERR(omap->xclk60mhsp2_ck)) { + ret = PTR_ERR(omap->xclk60mhsp2_ck); + dev_err(omap->dev, + "Unable to get Port2 ULPI clock\n"); + } + + omap->utmi_p2_fck = clk_get(omap->dev, + "utmi_p2_gfclk"); + if (IS_ERR(omap->utmi_p2_fck)) { + ret = PTR_ERR(omap->utmi_p2_fck); + dev_err(omap->dev, + "Unable to get utmi_p2_fck\n"); + } + + ret = clk_set_parent(omap->utmi_p2_fck, + omap->xclk60mhsp2_ck); + if (ret != 0) { + dev_err(omap->dev, + "Unable to set P2 f-clock\n"); + } + break; + case EHCI_HCD_OMAP_MODE_TLL: + /* TODO */ + default: + break; + } + } + + /* perform TLL soft reset, and wait until reset is complete */ ehci_omap_writel(omap->tll_base, OMAP_USBTLL_SYSCONFIG, OMAP_USBTLL_SYSCONFIG_SOFTRESET); @@ -364,12 +474,20 @@ static int omap_start_ehc(struct ehci_hcd_omap *omap, struct usb_hcd *hcd) /* Put UHH in NoIdle/NoStandby mode */ reg = ehci_omap_readl(omap->uhh_base, OMAP_UHH_SYSCONFIG); - reg |= (OMAP_UHH_SYSCONFIG_ENAWAKEUP - | OMAP_UHH_SYSCONFIG_SIDLEMODE - | OMAP_UHH_SYSCONFIG_CACTIVITY - | OMAP_UHH_SYSCONFIG_MIDLEMODE); - reg &= ~OMAP_UHH_SYSCONFIG_AUTOIDLE; + if (is_omap_ehci_rev1(omap)) { + reg |= (OMAP_UHH_SYSCONFIG_ENAWAKEUP + | OMAP_UHH_SYSCONFIG_SIDLEMODE + | OMAP_UHH_SYSCONFIG_CACTIVITY + | OMAP_UHH_SYSCONFIG_MIDLEMODE); + reg &= ~OMAP_UHH_SYSCONFIG_AUTOIDLE; + + } else if (is_omap_ehci_rev2(omap)) { + reg &= ~OMAP4_UHH_SYSCONFIG_IDLEMODE_CLEAR; + reg |= OMAP4_UHH_SYSCONFIG_NOIDLE; + reg &= ~OMAP4_UHH_SYSCONFIG_STDBYMODE_CLEAR; + reg |= OMAP4_UHH_SYSCONFIG_NOSTDBY; + } ehci_omap_writel(omap->uhh_base, OMAP_UHH_SYSCONFIG, reg); reg = ehci_omap_readl(omap->uhh_base, OMAP_UHH_HOSTCONFIG); @@ -380,40 +498,56 @@ static int omap_start_ehc(struct ehci_hcd_omap *omap, struct usb_hcd *hcd) | OMAP_UHH_HOSTCONFIG_INCR16_BURST_EN); reg &= ~OMAP_UHH_HOSTCONFIG_INCRX_ALIGN_EN; - if (omap->port_mode[0] == EHCI_HCD_OMAP_MODE_UNKNOWN) - reg &= ~OMAP_UHH_HOSTCONFIG_P1_CONNECT_STATUS; - if (omap->port_mode[1] == EHCI_HCD_OMAP_MODE_UNKNOWN) - reg &= ~OMAP_UHH_HOSTCONFIG_P2_CONNECT_STATUS; - if (omap->port_mode[2] == EHCI_HCD_OMAP_MODE_UNKNOWN) - reg &= ~OMAP_UHH_HOSTCONFIG_P3_CONNECT_STATUS; - - /* Bypass the TLL module for PHY mode operation */ - if (cpu_is_omap3430() && (omap_rev() <= OMAP3430_REV_ES2_1)) { - dev_dbg(omap->dev, "OMAP3 ES version <= ES2.1\n"); - if (is_ehci_phy_mode(omap->port_mode[0]) || - is_ehci_phy_mode(omap->port_mode[1]) || - is_ehci_phy_mode(omap->port_mode[2])) - reg &= ~OMAP_UHH_HOSTCONFIG_ULPI_BYPASS; - else - reg |= OMAP_UHH_HOSTCONFIG_ULPI_BYPASS; - } else { - dev_dbg(omap->dev, "OMAP3 ES version > ES2.1\n"); - if (is_ehci_phy_mode(omap->port_mode[0])) - reg &= ~OMAP_UHH_HOSTCONFIG_ULPI_P1_BYPASS; - else if (is_ehci_tll_mode(omap->port_mode[0])) - reg |= OMAP_UHH_HOSTCONFIG_ULPI_P1_BYPASS; - - if (is_ehci_phy_mode(omap->port_mode[1])) - reg &= ~OMAP_UHH_HOSTCONFIG_ULPI_P2_BYPASS; - else if (is_ehci_tll_mode(omap->port_mode[1])) - reg |= OMAP_UHH_HOSTCONFIG_ULPI_P2_BYPASS; - - if (is_ehci_phy_mode(omap->port_mode[2])) - reg &= ~OMAP_UHH_HOSTCONFIG_ULPI_P3_BYPASS; - else if (is_ehci_tll_mode(omap->port_mode[2])) - reg |= OMAP_UHH_HOSTCONFIG_ULPI_P3_BYPASS; + if (is_omap_ehci_rev1(omap)) { + if (omap->port_mode[0] == EHCI_HCD_OMAP_MODE_UNKNOWN) + reg &= ~OMAP_UHH_HOSTCONFIG_P1_CONNECT_STATUS; + if (omap->port_mode[1] == EHCI_HCD_OMAP_MODE_UNKNOWN) + reg &= ~OMAP_UHH_HOSTCONFIG_P2_CONNECT_STATUS; + if (omap->port_mode[2] == EHCI_HCD_OMAP_MODE_UNKNOWN) + reg &= ~OMAP_UHH_HOSTCONFIG_P3_CONNECT_STATUS; + + /* Bypass the TLL module for PHY mode operation */ + if (cpu_is_omap3430() && (omap_rev() <= OMAP3430_REV_ES2_1)) { + dev_dbg(omap->dev, "OMAP3 ES version <= ES2.1\n"); + if (is_ehci_phy_mode(omap->port_mode[0]) || + is_ehci_phy_mode(omap->port_mode[1]) || + is_ehci_phy_mode(omap->port_mode[2])) + reg &= ~OMAP_UHH_HOSTCONFIG_ULPI_BYPASS; + else + reg |= OMAP_UHH_HOSTCONFIG_ULPI_BYPASS; + } else { + dev_dbg(omap->dev, "OMAP3 ES version > ES2.1\n"); + if (is_ehci_phy_mode(omap->port_mode[0])) + reg &= ~OMAP_UHH_HOSTCONFIG_ULPI_P1_BYPASS; + else if (is_ehci_tll_mode(omap->port_mode[0])) + reg |= OMAP_UHH_HOSTCONFIG_ULPI_P1_BYPASS; + + if (is_ehci_phy_mode(omap->port_mode[1])) + reg &= ~OMAP_UHH_HOSTCONFIG_ULPI_P2_BYPASS; + else if (is_ehci_tll_mode(omap->port_mode[1])) + reg |= OMAP_UHH_HOSTCONFIG_ULPI_P2_BYPASS; + + if (is_ehci_phy_mode(omap->port_mode[2])) + reg &= ~OMAP_UHH_HOSTCONFIG_ULPI_P3_BYPASS; + else if (is_ehci_tll_mode(omap->port_mode[2])) + reg |= OMAP_UHH_HOSTCONFIG_ULPI_P3_BYPASS; + } + } else if (is_omap_ehci_rev2(omap)) { + /* Clear port mode fields for PHY mode*/ + reg &= ~OMAP4_P1_MODE_CLEAR; + reg &= ~OMAP4_P2_MODE_CLEAR; + + if (is_ehci_tll_mode(omap->port_mode[0])) + reg |= OMAP4_P1_MODE_TLL; + else if (is_ehci_hsic_mode(omap->port_mode[0])) + reg |= OMAP4_P1_MODE_HSIC; + if (is_ehci_tll_mode(omap->port_mode[1])) + reg |= OMAP4_P2_MODE_TLL; + else if (is_ehci_hsic_mode(omap->port_mode[1])) + reg |= OMAP4_P2_MODE_HSIC; } + ehci_omap_writel(omap->uhh_base, OMAP_UHH_HOSTCONFIG, reg); dev_dbg(omap->dev, "UHH setup done, uhh_hostconfig=%x\n", reg); @@ -468,6 +602,14 @@ static int omap_start_ehc(struct ehci_hcd_omap *omap, struct usb_hcd *hcd) return 0; err_sys_status: + clk_disable(omap->utmi_p2_fck); + clk_put(omap->utmi_p2_fck); + clk_disable(omap->xclk60mhsp2_ck); + clk_put(omap->xclk60mhsp2_ck); + clk_disable(omap->utmi_p1_fck); + clk_put(omap->utmi_p1_fck); + clk_disable(omap->xclk60mhsp1_ck); + clk_put(omap->xclk60mhsp1_ck); clk_disable(omap->usbtll_ick); clk_put(omap->usbtll_ick); @@ -507,6 +649,8 @@ static void omap_stop_ehc(struct ehci_hcd_omap *omap, struct usb_hcd *hcd) /* Reset OMAP modules for insmod/rmmod to work */ ehci_omap_writel(omap->uhh_base, OMAP_UHH_SYSCONFIG, + is_omap_ehci_rev2(omap) ? + OMAP4_UHH_SYSCONFIG_SOFTRESET : OMAP_UHH_SYSCONFIG_SOFTRESET); while (!(ehci_omap_readl(omap->uhh_base, OMAP_UHH_SYSSTATUS) & (1 << 0))) { @@ -572,6 +716,32 @@ static void omap_stop_ehc(struct ehci_hcd_omap *omap, struct usb_hcd *hcd) omap->usbtll_ick = NULL; } + if (is_omap_ehci_rev2(omap)) { + if (omap->xclk60mhsp1_ck != NULL) { + clk_disable(omap->xclk60mhsp1_ck); + clk_put(omap->xclk60mhsp1_ck); + omap->xclk60mhsp1_ck = NULL; + } + + if (omap->utmi_p1_fck != NULL) { + clk_disable(omap->utmi_p1_fck); + clk_put(omap->utmi_p1_fck); + omap->utmi_p1_fck = NULL; + } + + if (omap->xclk60mhsp2_ck != NULL) { + clk_disable(omap->xclk60mhsp2_ck); + clk_put(omap->xclk60mhsp2_ck); + omap->xclk60mhsp2_ck = NULL; + } + + if (omap->utmi_p2_fck != NULL) { + clk_disable(omap->utmi_p2_fck); + clk_put(omap->utmi_p2_fck); + omap->utmi_p2_fck = NULL; + } + } + if (omap->phy_reset) { if (gpio_is_valid(omap->reset_gpio_port[0])) gpio_free(omap->reset_gpio_port[0]); -- cgit v1.2.3-70-g09d2