diff options
author | Greg Kroah-Hartman <gregkh@suse.de> | 2010-11-30 20:04:33 -0500 |
---|---|---|
committer | Greg Kroah-Hartman <gregkh@suse.de> | 2010-11-30 20:04:51 -0500 |
commit | 0ae86689d88bebba16c2db899f845446578d53b3 (patch) | |
tree | 221f807566461620c240a190d551c73118529da0 /drivers/usb/host | |
parent | e7cddda48c7f892a3fb5c10a6f41a4395f46c0c2 (diff) | |
parent | 6aa85a5ae610106d89e50c7e1f760c56d12f9bc4 (diff) |
Merge branch 'omap4-ehci-for-greg' of git://dev.omapzoom.org/pub/scm/anand/linux-omap-usb into usb-next
* 'omap4-ehci-for-greg' of git://dev.omapzoom.org/pub/scm/anand/linux-omap-usb:
omap4: 4430sdp: enable the ehci port on 4430SDP
arm: omap4: select USB_ARCH_HAS_EHCI
arm: omap4: usb: add platform init code for EHCI
arm: omap4: add USBHOST and related base addresses
usb: ehci-omap: Add OMAP4 support
omap: usb: ehci: introduce HSIC mode
usb: ehci-omap: add helpers for checking port mode
usb: ehci-omap: use clkdev aliases for functional clocks
omap: clock: add clkdev aliases for EHCI clocks
usb: ehci: introduce CONFIG_USB_EHCI_HCD_OMAP
usb: ehci-omap: don't hard-code TLL channel count
usb: ehci-omap: update clock names to be more generic
Diffstat (limited to 'drivers/usb/host')
-rw-r--r-- | drivers/usb/host/Kconfig | 8 | ||||
-rw-r--r-- | drivers/usb/host/ehci-hcd.c | 2 | ||||
-rw-r--r-- | drivers/usb/host/ehci-omap.c | 310 |
3 files changed, 251 insertions, 69 deletions
diff --git a/drivers/usb/host/Kconfig b/drivers/usb/host/Kconfig index 2391c396ca32..6a7c688b4781 100644 --- a/drivers/usb/host/Kconfig +++ b/drivers/usb/host/Kconfig | |||
@@ -133,6 +133,14 @@ config USB_EHCI_MXC | |||
133 | ---help--- | 133 | ---help--- |
134 | Variation of ARC USB block used in some Freescale chips. | 134 | Variation of ARC USB block used in some Freescale chips. |
135 | 135 | ||
136 | config USB_EHCI_HCD_OMAP | ||
137 | bool "EHCI support for OMAP3 and later chips" | ||
138 | depends on USB_EHCI_HCD && ARCH_OMAP | ||
139 | default y | ||
140 | --- help --- | ||
141 | Enables support for the on-chip EHCI controller on | ||
142 | OMAP3 and later chips. | ||
143 | |||
136 | config USB_EHCI_HCD_PPC_OF | 144 | config USB_EHCI_HCD_PPC_OF |
137 | bool "EHCI support for PPC USB controller on OF platform bus" | 145 | bool "EHCI support for PPC USB controller on OF platform bus" |
138 | depends on USB_EHCI_HCD && PPC_OF | 146 | depends on USB_EHCI_HCD && PPC_OF |
diff --git a/drivers/usb/host/ehci-hcd.c b/drivers/usb/host/ehci-hcd.c index 87157db155f6..2f06ba471953 100644 --- a/drivers/usb/host/ehci-hcd.c +++ b/drivers/usb/host/ehci-hcd.c | |||
@@ -1171,7 +1171,7 @@ MODULE_LICENSE ("GPL"); | |||
1171 | #define PLATFORM_DRIVER ehci_hcd_au1xxx_driver | 1171 | #define PLATFORM_DRIVER ehci_hcd_au1xxx_driver |
1172 | #endif | 1172 | #endif |
1173 | 1173 | ||
1174 | #ifdef CONFIG_ARCH_OMAP3 | 1174 | #ifdef CONFIG_USB_EHCI_HCD_OMAP |
1175 | #include "ehci-omap.c" | 1175 | #include "ehci-omap.c" |
1176 | #define PLATFORM_DRIVER ehci_hcd_omap_driver | 1176 | #define PLATFORM_DRIVER ehci_hcd_omap_driver |
1177 | #endif | 1177 | #endif |
diff --git a/drivers/usb/host/ehci-omap.c b/drivers/usb/host/ehci-omap.c index 116ae280053a..0374eb47f09b 100644 --- a/drivers/usb/host/ehci-omap.c +++ b/drivers/usb/host/ehci-omap.c | |||
@@ -1,11 +1,12 @@ | |||
1 | /* | 1 | /* |
2 | * ehci-omap.c - driver for USBHOST on OMAP 34xx processor | 2 | * ehci-omap.c - driver for USBHOST on OMAP3/4 processors |
3 | * | 3 | * |
4 | * Bus Glue for OMAP34xx USBHOST 3 port EHCI controller | 4 | * Bus Glue for the EHCI controllers in OMAP3/4 |
5 | * Tested on OMAP3430 ES2.0 SDP | 5 | * Tested on several OMAP3 boards, and OMAP4 Pandaboard |
6 | * | 6 | * |
7 | * Copyright (C) 2007-2008 Texas Instruments, Inc. | 7 | * Copyright (C) 2007-2010 Texas Instruments, Inc. |
8 | * Author: Vikram Pandita <vikram.pandita@ti.com> | 8 | * Author: Vikram Pandita <vikram.pandita@ti.com> |
9 | * Author: Anand Gadiyar <gadiyar@ti.com> | ||
9 | * | 10 | * |
10 | * Copyright (C) 2009 Nokia Corporation | 11 | * Copyright (C) 2009 Nokia Corporation |
11 | * Contact: Felipe Balbi <felipe.balbi@nokia.com> | 12 | * Contact: Felipe Balbi <felipe.balbi@nokia.com> |
@@ -26,11 +27,14 @@ | |||
26 | * along with this program; if not, write to the Free Software | 27 | * along with this program; if not, write to the Free Software |
27 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | 28 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA |
28 | * | 29 | * |
29 | * TODO (last updated Feb 12, 2010): | 30 | * TODO (last updated Nov 21, 2010): |
30 | * - add kernel-doc | 31 | * - add kernel-doc |
31 | * - enable AUTOIDLE | 32 | * - enable AUTOIDLE |
32 | * - add suspend/resume | 33 | * - add suspend/resume |
33 | * - move workarounds to board-files | 34 | * - move workarounds to board-files |
35 | * - factor out code common to OHCI | ||
36 | * - add HSIC and TLL support | ||
37 | * - convert to use hwmod and runtime PM | ||
34 | */ | 38 | */ |
35 | 39 | ||
36 | #include <linux/platform_device.h> | 40 | #include <linux/platform_device.h> |
@@ -114,6 +118,23 @@ | |||
114 | #define OMAP_UHH_HOSTCONFIG_P2_CONNECT_STATUS (1 << 9) | 118 | #define OMAP_UHH_HOSTCONFIG_P2_CONNECT_STATUS (1 << 9) |
115 | #define OMAP_UHH_HOSTCONFIG_P3_CONNECT_STATUS (1 << 10) | 119 | #define OMAP_UHH_HOSTCONFIG_P3_CONNECT_STATUS (1 << 10) |
116 | 120 | ||
121 | /* OMAP4-specific defines */ | ||
122 | #define OMAP4_UHH_SYSCONFIG_IDLEMODE_CLEAR (3 << 2) | ||
123 | #define OMAP4_UHH_SYSCONFIG_NOIDLE (1 << 2) | ||
124 | |||
125 | #define OMAP4_UHH_SYSCONFIG_STDBYMODE_CLEAR (3 << 4) | ||
126 | #define OMAP4_UHH_SYSCONFIG_NOSTDBY (1 << 4) | ||
127 | #define OMAP4_UHH_SYSCONFIG_SOFTRESET (1 << 0) | ||
128 | |||
129 | #define OMAP4_P1_MODE_CLEAR (3 << 16) | ||
130 | #define OMAP4_P1_MODE_TLL (1 << 16) | ||
131 | #define OMAP4_P1_MODE_HSIC (3 << 16) | ||
132 | #define OMAP4_P2_MODE_CLEAR (3 << 18) | ||
133 | #define OMAP4_P2_MODE_TLL (1 << 18) | ||
134 | #define OMAP4_P2_MODE_HSIC (3 << 18) | ||
135 | |||
136 | #define OMAP_REV2_TLL_CHANNEL_COUNT 2 | ||
137 | |||
117 | #define OMAP_UHH_DEBUG_CSR (0x44) | 138 | #define OMAP_UHH_DEBUG_CSR (0x44) |
118 | 139 | ||
119 | /* EHCI Register Set */ | 140 | /* EHCI Register Set */ |
@@ -127,6 +148,17 @@ | |||
127 | #define EHCI_INSNREG05_ULPI_EXTREGADD_SHIFT 8 | 148 | #define EHCI_INSNREG05_ULPI_EXTREGADD_SHIFT 8 |
128 | #define EHCI_INSNREG05_ULPI_WRDATA_SHIFT 0 | 149 | #define EHCI_INSNREG05_ULPI_WRDATA_SHIFT 0 |
129 | 150 | ||
151 | /* Values of UHH_REVISION - Note: these are not given in the TRM */ | ||
152 | #define OMAP_EHCI_REV1 0x00000010 /* OMAP3 */ | ||
153 | #define OMAP_EHCI_REV2 0x50700100 /* OMAP4 */ | ||
154 | |||
155 | #define is_omap_ehci_rev1(x) (x->omap_ehci_rev == OMAP_EHCI_REV1) | ||
156 | #define is_omap_ehci_rev2(x) (x->omap_ehci_rev == OMAP_EHCI_REV2) | ||
157 | |||
158 | #define is_ehci_phy_mode(x) (x == EHCI_HCD_OMAP_MODE_PHY) | ||
159 | #define is_ehci_tll_mode(x) (x == EHCI_HCD_OMAP_MODE_TLL) | ||
160 | #define is_ehci_hsic_mode(x) (x == EHCI_HCD_OMAP_MODE_HSIC) | ||
161 | |||
130 | /*-------------------------------------------------------------------------*/ | 162 | /*-------------------------------------------------------------------------*/ |
131 | 163 | ||
132 | static inline void ehci_omap_writel(void __iomem *base, u32 reg, u32 val) | 164 | static inline void ehci_omap_writel(void __iomem *base, u32 reg, u32 val) |
@@ -156,10 +188,14 @@ struct ehci_hcd_omap { | |||
156 | struct device *dev; | 188 | struct device *dev; |
157 | 189 | ||
158 | struct clk *usbhost_ick; | 190 | struct clk *usbhost_ick; |
159 | struct clk *usbhost2_120m_fck; | 191 | struct clk *usbhost_hs_fck; |
160 | struct clk *usbhost1_48m_fck; | 192 | struct clk *usbhost_fs_fck; |
161 | struct clk *usbtll_fck; | 193 | struct clk *usbtll_fck; |
162 | struct clk *usbtll_ick; | 194 | struct clk *usbtll_ick; |
195 | struct clk *xclk60mhsp1_ck; | ||
196 | struct clk *xclk60mhsp2_ck; | ||
197 | struct clk *utmi_p1_fck; | ||
198 | struct clk *utmi_p2_fck; | ||
163 | 199 | ||
164 | /* FIXME the following two workarounds are | 200 | /* FIXME the following two workarounds are |
165 | * board specific not silicon-specific so these | 201 | * board specific not silicon-specific so these |
@@ -176,6 +212,9 @@ struct ehci_hcd_omap { | |||
176 | /* phy reset workaround */ | 212 | /* phy reset workaround */ |
177 | int phy_reset; | 213 | int phy_reset; |
178 | 214 | ||
215 | /* IP revision */ | ||
216 | u32 omap_ehci_rev; | ||
217 | |||
179 | /* desired phy_mode: TLL, PHY */ | 218 | /* desired phy_mode: TLL, PHY */ |
180 | enum ehci_hcd_omap_mode port_mode[OMAP3_HS_USB_PORTS]; | 219 | enum ehci_hcd_omap_mode port_mode[OMAP3_HS_USB_PORTS]; |
181 | 220 | ||
@@ -191,13 +230,14 @@ struct ehci_hcd_omap { | |||
191 | 230 | ||
192 | /*-------------------------------------------------------------------------*/ | 231 | /*-------------------------------------------------------------------------*/ |
193 | 232 | ||
194 | static void omap_usb_utmi_init(struct ehci_hcd_omap *omap, u8 tll_channel_mask) | 233 | static void omap_usb_utmi_init(struct ehci_hcd_omap *omap, u8 tll_channel_mask, |
234 | u8 tll_channel_count) | ||
195 | { | 235 | { |
196 | unsigned reg; | 236 | unsigned reg; |
197 | int i; | 237 | int i; |
198 | 238 | ||
199 | /* Program the 3 TLL channels upfront */ | 239 | /* Program the 3 TLL channels upfront */ |
200 | for (i = 0; i < OMAP_TLL_CHANNEL_COUNT; i++) { | 240 | for (i = 0; i < tll_channel_count; i++) { |
201 | reg = ehci_omap_readl(omap->tll_base, OMAP_TLL_CHANNEL_CONF(i)); | 241 | reg = ehci_omap_readl(omap->tll_base, OMAP_TLL_CHANNEL_CONF(i)); |
202 | 242 | ||
203 | /* Disable AutoIdle, BitStuffing and use SDR Mode */ | 243 | /* Disable AutoIdle, BitStuffing and use SDR Mode */ |
@@ -217,7 +257,7 @@ static void omap_usb_utmi_init(struct ehci_hcd_omap *omap, u8 tll_channel_mask) | |||
217 | ehci_omap_writel(omap->tll_base, OMAP_TLL_SHARED_CONF, reg); | 257 | ehci_omap_writel(omap->tll_base, OMAP_TLL_SHARED_CONF, reg); |
218 | 258 | ||
219 | /* Enable channels now */ | 259 | /* Enable channels now */ |
220 | for (i = 0; i < OMAP_TLL_CHANNEL_COUNT; i++) { | 260 | for (i = 0; i < tll_channel_count; i++) { |
221 | reg = ehci_omap_readl(omap->tll_base, OMAP_TLL_CHANNEL_CONF(i)); | 261 | reg = ehci_omap_readl(omap->tll_base, OMAP_TLL_CHANNEL_CONF(i)); |
222 | 262 | ||
223 | /* Enable only the reg that is needed */ | 263 | /* Enable only the reg that is needed */ |
@@ -286,19 +326,19 @@ static int omap_start_ehc(struct ehci_hcd_omap *omap, struct usb_hcd *hcd) | |||
286 | } | 326 | } |
287 | clk_enable(omap->usbhost_ick); | 327 | clk_enable(omap->usbhost_ick); |
288 | 328 | ||
289 | omap->usbhost2_120m_fck = clk_get(omap->dev, "usbhost_120m_fck"); | 329 | omap->usbhost_hs_fck = clk_get(omap->dev, "hs_fck"); |
290 | if (IS_ERR(omap->usbhost2_120m_fck)) { | 330 | if (IS_ERR(omap->usbhost_hs_fck)) { |
291 | ret = PTR_ERR(omap->usbhost2_120m_fck); | 331 | ret = PTR_ERR(omap->usbhost_hs_fck); |
292 | goto err_host_120m_fck; | 332 | goto err_host_120m_fck; |
293 | } | 333 | } |
294 | clk_enable(omap->usbhost2_120m_fck); | 334 | clk_enable(omap->usbhost_hs_fck); |
295 | 335 | ||
296 | omap->usbhost1_48m_fck = clk_get(omap->dev, "usbhost_48m_fck"); | 336 | omap->usbhost_fs_fck = clk_get(omap->dev, "fs_fck"); |
297 | if (IS_ERR(omap->usbhost1_48m_fck)) { | 337 | if (IS_ERR(omap->usbhost_fs_fck)) { |
298 | ret = PTR_ERR(omap->usbhost1_48m_fck); | 338 | ret = PTR_ERR(omap->usbhost_fs_fck); |
299 | goto err_host_48m_fck; | 339 | goto err_host_48m_fck; |
300 | } | 340 | } |
301 | clk_enable(omap->usbhost1_48m_fck); | 341 | clk_enable(omap->usbhost_fs_fck); |
302 | 342 | ||
303 | if (omap->phy_reset) { | 343 | if (omap->phy_reset) { |
304 | /* Refer: ISSUE1 */ | 344 | /* Refer: ISSUE1 */ |
@@ -333,6 +373,80 @@ static int omap_start_ehc(struct ehci_hcd_omap *omap, struct usb_hcd *hcd) | |||
333 | } | 373 | } |
334 | clk_enable(omap->usbtll_ick); | 374 | clk_enable(omap->usbtll_ick); |
335 | 375 | ||
376 | omap->omap_ehci_rev = ehci_omap_readl(omap->uhh_base, | ||
377 | OMAP_UHH_REVISION); | ||
378 | dev_dbg(omap->dev, "OMAP UHH_REVISION 0x%x\n", | ||
379 | omap->omap_ehci_rev); | ||
380 | |||
381 | /* | ||
382 | * Enable per-port clocks as needed (newer controllers only). | ||
383 | * - External ULPI clock for PHY mode | ||
384 | * - Internal clocks for TLL and HSIC modes (TODO) | ||
385 | */ | ||
386 | if (is_omap_ehci_rev2(omap)) { | ||
387 | switch (omap->port_mode[0]) { | ||
388 | case EHCI_HCD_OMAP_MODE_PHY: | ||
389 | omap->xclk60mhsp1_ck = clk_get(omap->dev, | ||
390 | "xclk60mhsp1_ck"); | ||
391 | if (IS_ERR(omap->xclk60mhsp1_ck)) { | ||
392 | ret = PTR_ERR(omap->xclk60mhsp1_ck); | ||
393 | dev_err(omap->dev, | ||
394 | "Unable to get Port1 ULPI clock\n"); | ||
395 | } | ||
396 | |||
397 | omap->utmi_p1_fck = clk_get(omap->dev, | ||
398 | "utmi_p1_gfclk"); | ||
399 | if (IS_ERR(omap->utmi_p1_fck)) { | ||
400 | ret = PTR_ERR(omap->utmi_p1_fck); | ||
401 | dev_err(omap->dev, | ||
402 | "Unable to get utmi_p1_fck\n"); | ||
403 | } | ||
404 | |||
405 | ret = clk_set_parent(omap->utmi_p1_fck, | ||
406 | omap->xclk60mhsp1_ck); | ||
407 | if (ret != 0) { | ||
408 | dev_err(omap->dev, | ||
409 | "Unable to set P1 f-clock\n"); | ||
410 | } | ||
411 | break; | ||
412 | case EHCI_HCD_OMAP_MODE_TLL: | ||
413 | /* TODO */ | ||
414 | default: | ||
415 | break; | ||
416 | } | ||
417 | switch (omap->port_mode[1]) { | ||
418 | case EHCI_HCD_OMAP_MODE_PHY: | ||
419 | omap->xclk60mhsp2_ck = clk_get(omap->dev, | ||
420 | "xclk60mhsp2_ck"); | ||
421 | if (IS_ERR(omap->xclk60mhsp2_ck)) { | ||
422 | ret = PTR_ERR(omap->xclk60mhsp2_ck); | ||
423 | dev_err(omap->dev, | ||
424 | "Unable to get Port2 ULPI clock\n"); | ||
425 | } | ||
426 | |||
427 | omap->utmi_p2_fck = clk_get(omap->dev, | ||
428 | "utmi_p2_gfclk"); | ||
429 | if (IS_ERR(omap->utmi_p2_fck)) { | ||
430 | ret = PTR_ERR(omap->utmi_p2_fck); | ||
431 | dev_err(omap->dev, | ||
432 | "Unable to get utmi_p2_fck\n"); | ||
433 | } | ||
434 | |||
435 | ret = clk_set_parent(omap->utmi_p2_fck, | ||
436 | omap->xclk60mhsp2_ck); | ||
437 | if (ret != 0) { | ||
438 | dev_err(omap->dev, | ||
439 | "Unable to set P2 f-clock\n"); | ||
440 | } | ||
441 | break; | ||
442 | case EHCI_HCD_OMAP_MODE_TLL: | ||
443 | /* TODO */ | ||
444 | default: | ||
445 | break; | ||
446 | } | ||
447 | } | ||
448 | |||
449 | |||
336 | /* perform TLL soft reset, and wait until reset is complete */ | 450 | /* perform TLL soft reset, and wait until reset is complete */ |
337 | ehci_omap_writel(omap->tll_base, OMAP_USBTLL_SYSCONFIG, | 451 | ehci_omap_writel(omap->tll_base, OMAP_USBTLL_SYSCONFIG, |
338 | OMAP_USBTLL_SYSCONFIG_SOFTRESET); | 452 | OMAP_USBTLL_SYSCONFIG_SOFTRESET); |
@@ -360,12 +474,20 @@ static int omap_start_ehc(struct ehci_hcd_omap *omap, struct usb_hcd *hcd) | |||
360 | 474 | ||
361 | /* Put UHH in NoIdle/NoStandby mode */ | 475 | /* Put UHH in NoIdle/NoStandby mode */ |
362 | reg = ehci_omap_readl(omap->uhh_base, OMAP_UHH_SYSCONFIG); | 476 | reg = ehci_omap_readl(omap->uhh_base, OMAP_UHH_SYSCONFIG); |
363 | reg |= (OMAP_UHH_SYSCONFIG_ENAWAKEUP | 477 | if (is_omap_ehci_rev1(omap)) { |
364 | | OMAP_UHH_SYSCONFIG_SIDLEMODE | 478 | reg |= (OMAP_UHH_SYSCONFIG_ENAWAKEUP |
365 | | OMAP_UHH_SYSCONFIG_CACTIVITY | 479 | | OMAP_UHH_SYSCONFIG_SIDLEMODE |
366 | | OMAP_UHH_SYSCONFIG_MIDLEMODE); | 480 | | OMAP_UHH_SYSCONFIG_CACTIVITY |
367 | reg &= ~OMAP_UHH_SYSCONFIG_AUTOIDLE; | 481 | | OMAP_UHH_SYSCONFIG_MIDLEMODE); |
482 | reg &= ~OMAP_UHH_SYSCONFIG_AUTOIDLE; | ||
483 | |||
368 | 484 | ||
485 | } else if (is_omap_ehci_rev2(omap)) { | ||
486 | reg &= ~OMAP4_UHH_SYSCONFIG_IDLEMODE_CLEAR; | ||
487 | reg |= OMAP4_UHH_SYSCONFIG_NOIDLE; | ||
488 | reg &= ~OMAP4_UHH_SYSCONFIG_STDBYMODE_CLEAR; | ||
489 | reg |= OMAP4_UHH_SYSCONFIG_NOSTDBY; | ||
490 | } | ||
369 | ehci_omap_writel(omap->uhh_base, OMAP_UHH_SYSCONFIG, reg); | 491 | ehci_omap_writel(omap->uhh_base, OMAP_UHH_SYSCONFIG, reg); |
370 | 492 | ||
371 | reg = ehci_omap_readl(omap->uhh_base, OMAP_UHH_HOSTCONFIG); | 493 | reg = ehci_omap_readl(omap->uhh_base, OMAP_UHH_HOSTCONFIG); |
@@ -376,40 +498,56 @@ static int omap_start_ehc(struct ehci_hcd_omap *omap, struct usb_hcd *hcd) | |||
376 | | OMAP_UHH_HOSTCONFIG_INCR16_BURST_EN); | 498 | | OMAP_UHH_HOSTCONFIG_INCR16_BURST_EN); |
377 | reg &= ~OMAP_UHH_HOSTCONFIG_INCRX_ALIGN_EN; | 499 | reg &= ~OMAP_UHH_HOSTCONFIG_INCRX_ALIGN_EN; |
378 | 500 | ||
379 | if (omap->port_mode[0] == EHCI_HCD_OMAP_MODE_UNKNOWN) | 501 | if (is_omap_ehci_rev1(omap)) { |
380 | reg &= ~OMAP_UHH_HOSTCONFIG_P1_CONNECT_STATUS; | 502 | if (omap->port_mode[0] == EHCI_HCD_OMAP_MODE_UNKNOWN) |
381 | if (omap->port_mode[1] == EHCI_HCD_OMAP_MODE_UNKNOWN) | 503 | reg &= ~OMAP_UHH_HOSTCONFIG_P1_CONNECT_STATUS; |
382 | reg &= ~OMAP_UHH_HOSTCONFIG_P2_CONNECT_STATUS; | 504 | if (omap->port_mode[1] == EHCI_HCD_OMAP_MODE_UNKNOWN) |
383 | if (omap->port_mode[2] == EHCI_HCD_OMAP_MODE_UNKNOWN) | 505 | reg &= ~OMAP_UHH_HOSTCONFIG_P2_CONNECT_STATUS; |
384 | reg &= ~OMAP_UHH_HOSTCONFIG_P3_CONNECT_STATUS; | 506 | if (omap->port_mode[2] == EHCI_HCD_OMAP_MODE_UNKNOWN) |
385 | 507 | reg &= ~OMAP_UHH_HOSTCONFIG_P3_CONNECT_STATUS; | |
386 | /* Bypass the TLL module for PHY mode operation */ | 508 | |
387 | if (cpu_is_omap3430() && (omap_rev() <= OMAP3430_REV_ES2_1)) { | 509 | /* Bypass the TLL module for PHY mode operation */ |
388 | dev_dbg(omap->dev, "OMAP3 ES version <= ES2.1\n"); | 510 | if (cpu_is_omap3430() && (omap_rev() <= OMAP3430_REV_ES2_1)) { |
389 | if ((omap->port_mode[0] == EHCI_HCD_OMAP_MODE_PHY) || | 511 | dev_dbg(omap->dev, "OMAP3 ES version <= ES2.1\n"); |
390 | (omap->port_mode[1] == EHCI_HCD_OMAP_MODE_PHY) || | 512 | if (is_ehci_phy_mode(omap->port_mode[0]) || |
391 | (omap->port_mode[2] == EHCI_HCD_OMAP_MODE_PHY)) | 513 | is_ehci_phy_mode(omap->port_mode[1]) || |
392 | reg &= ~OMAP_UHH_HOSTCONFIG_ULPI_BYPASS; | 514 | is_ehci_phy_mode(omap->port_mode[2])) |
393 | else | 515 | reg &= ~OMAP_UHH_HOSTCONFIG_ULPI_BYPASS; |
394 | reg |= OMAP_UHH_HOSTCONFIG_ULPI_BYPASS; | 516 | else |
395 | } else { | 517 | reg |= OMAP_UHH_HOSTCONFIG_ULPI_BYPASS; |
396 | dev_dbg(omap->dev, "OMAP3 ES version > ES2.1\n"); | 518 | } else { |
397 | if (omap->port_mode[0] == EHCI_HCD_OMAP_MODE_PHY) | 519 | dev_dbg(omap->dev, "OMAP3 ES version > ES2.1\n"); |
398 | reg &= ~OMAP_UHH_HOSTCONFIG_ULPI_P1_BYPASS; | 520 | if (is_ehci_phy_mode(omap->port_mode[0])) |
399 | else if (omap->port_mode[0] == EHCI_HCD_OMAP_MODE_TLL) | 521 | reg &= ~OMAP_UHH_HOSTCONFIG_ULPI_P1_BYPASS; |
400 | reg |= OMAP_UHH_HOSTCONFIG_ULPI_P1_BYPASS; | 522 | else if (is_ehci_tll_mode(omap->port_mode[0])) |
401 | 523 | reg |= OMAP_UHH_HOSTCONFIG_ULPI_P1_BYPASS; | |
402 | if (omap->port_mode[1] == EHCI_HCD_OMAP_MODE_PHY) | 524 | |
403 | reg &= ~OMAP_UHH_HOSTCONFIG_ULPI_P2_BYPASS; | 525 | if (is_ehci_phy_mode(omap->port_mode[1])) |
404 | else if (omap->port_mode[1] == EHCI_HCD_OMAP_MODE_TLL) | 526 | reg &= ~OMAP_UHH_HOSTCONFIG_ULPI_P2_BYPASS; |
405 | reg |= OMAP_UHH_HOSTCONFIG_ULPI_P2_BYPASS; | 527 | else if (is_ehci_tll_mode(omap->port_mode[1])) |
406 | 528 | reg |= OMAP_UHH_HOSTCONFIG_ULPI_P2_BYPASS; | |
407 | if (omap->port_mode[2] == EHCI_HCD_OMAP_MODE_PHY) | 529 | |
408 | reg &= ~OMAP_UHH_HOSTCONFIG_ULPI_P3_BYPASS; | 530 | if (is_ehci_phy_mode(omap->port_mode[2])) |
409 | else if (omap->port_mode[2] == EHCI_HCD_OMAP_MODE_TLL) | 531 | reg &= ~OMAP_UHH_HOSTCONFIG_ULPI_P3_BYPASS; |
410 | reg |= OMAP_UHH_HOSTCONFIG_ULPI_P3_BYPASS; | 532 | else if (is_ehci_tll_mode(omap->port_mode[2])) |
533 | reg |= OMAP_UHH_HOSTCONFIG_ULPI_P3_BYPASS; | ||
534 | } | ||
535 | } else if (is_omap_ehci_rev2(omap)) { | ||
536 | /* Clear port mode fields for PHY mode*/ | ||
537 | reg &= ~OMAP4_P1_MODE_CLEAR; | ||
538 | reg &= ~OMAP4_P2_MODE_CLEAR; | ||
539 | |||
540 | if (is_ehci_tll_mode(omap->port_mode[0])) | ||
541 | reg |= OMAP4_P1_MODE_TLL; | ||
542 | else if (is_ehci_hsic_mode(omap->port_mode[0])) | ||
543 | reg |= OMAP4_P1_MODE_HSIC; | ||
411 | 544 | ||
545 | if (is_ehci_tll_mode(omap->port_mode[1])) | ||
546 | reg |= OMAP4_P2_MODE_TLL; | ||
547 | else if (is_ehci_hsic_mode(omap->port_mode[1])) | ||
548 | reg |= OMAP4_P2_MODE_HSIC; | ||
412 | } | 549 | } |
550 | |||
413 | ehci_omap_writel(omap->uhh_base, OMAP_UHH_HOSTCONFIG, reg); | 551 | ehci_omap_writel(omap->uhh_base, OMAP_UHH_HOSTCONFIG, reg); |
414 | dev_dbg(omap->dev, "UHH setup done, uhh_hostconfig=%x\n", reg); | 552 | dev_dbg(omap->dev, "UHH setup done, uhh_hostconfig=%x\n", reg); |
415 | 553 | ||
@@ -438,7 +576,7 @@ static int omap_start_ehc(struct ehci_hcd_omap *omap, struct usb_hcd *hcd) | |||
438 | tll_ch_mask |= OMAP_TLL_CHANNEL_3_EN_MASK; | 576 | tll_ch_mask |= OMAP_TLL_CHANNEL_3_EN_MASK; |
439 | 577 | ||
440 | /* Enable UTMI mode for required TLL channels */ | 578 | /* Enable UTMI mode for required TLL channels */ |
441 | omap_usb_utmi_init(omap, tll_ch_mask); | 579 | omap_usb_utmi_init(omap, tll_ch_mask, OMAP_TLL_CHANNEL_COUNT); |
442 | } | 580 | } |
443 | 581 | ||
444 | if (omap->phy_reset) { | 582 | if (omap->phy_reset) { |
@@ -464,6 +602,14 @@ static int omap_start_ehc(struct ehci_hcd_omap *omap, struct usb_hcd *hcd) | |||
464 | return 0; | 602 | return 0; |
465 | 603 | ||
466 | err_sys_status: | 604 | err_sys_status: |
605 | clk_disable(omap->utmi_p2_fck); | ||
606 | clk_put(omap->utmi_p2_fck); | ||
607 | clk_disable(omap->xclk60mhsp2_ck); | ||
608 | clk_put(omap->xclk60mhsp2_ck); | ||
609 | clk_disable(omap->utmi_p1_fck); | ||
610 | clk_put(omap->utmi_p1_fck); | ||
611 | clk_disable(omap->xclk60mhsp1_ck); | ||
612 | clk_put(omap->xclk60mhsp1_ck); | ||
467 | clk_disable(omap->usbtll_ick); | 613 | clk_disable(omap->usbtll_ick); |
468 | clk_put(omap->usbtll_ick); | 614 | clk_put(omap->usbtll_ick); |
469 | 615 | ||
@@ -472,8 +618,8 @@ err_tll_ick: | |||
472 | clk_put(omap->usbtll_fck); | 618 | clk_put(omap->usbtll_fck); |
473 | 619 | ||
474 | err_tll_fck: | 620 | err_tll_fck: |
475 | clk_disable(omap->usbhost1_48m_fck); | 621 | clk_disable(omap->usbhost_fs_fck); |
476 | clk_put(omap->usbhost1_48m_fck); | 622 | clk_put(omap->usbhost_fs_fck); |
477 | 623 | ||
478 | if (omap->phy_reset) { | 624 | if (omap->phy_reset) { |
479 | if (gpio_is_valid(omap->reset_gpio_port[0])) | 625 | if (gpio_is_valid(omap->reset_gpio_port[0])) |
@@ -484,8 +630,8 @@ err_tll_fck: | |||
484 | } | 630 | } |
485 | 631 | ||
486 | err_host_48m_fck: | 632 | err_host_48m_fck: |
487 | clk_disable(omap->usbhost2_120m_fck); | 633 | clk_disable(omap->usbhost_hs_fck); |
488 | clk_put(omap->usbhost2_120m_fck); | 634 | clk_put(omap->usbhost_hs_fck); |
489 | 635 | ||
490 | err_host_120m_fck: | 636 | err_host_120m_fck: |
491 | clk_disable(omap->usbhost_ick); | 637 | clk_disable(omap->usbhost_ick); |
@@ -503,6 +649,8 @@ static void omap_stop_ehc(struct ehci_hcd_omap *omap, struct usb_hcd *hcd) | |||
503 | 649 | ||
504 | /* Reset OMAP modules for insmod/rmmod to work */ | 650 | /* Reset OMAP modules for insmod/rmmod to work */ |
505 | ehci_omap_writel(omap->uhh_base, OMAP_UHH_SYSCONFIG, | 651 | ehci_omap_writel(omap->uhh_base, OMAP_UHH_SYSCONFIG, |
652 | is_omap_ehci_rev2(omap) ? | ||
653 | OMAP4_UHH_SYSCONFIG_SOFTRESET : | ||
506 | OMAP_UHH_SYSCONFIG_SOFTRESET); | 654 | OMAP_UHH_SYSCONFIG_SOFTRESET); |
507 | while (!(ehci_omap_readl(omap->uhh_base, OMAP_UHH_SYSSTATUS) | 655 | while (!(ehci_omap_readl(omap->uhh_base, OMAP_UHH_SYSSTATUS) |
508 | & (1 << 0))) { | 656 | & (1 << 0))) { |
@@ -550,16 +698,16 @@ static void omap_stop_ehc(struct ehci_hcd_omap *omap, struct usb_hcd *hcd) | |||
550 | omap->usbhost_ick = NULL; | 698 | omap->usbhost_ick = NULL; |
551 | } | 699 | } |
552 | 700 | ||
553 | if (omap->usbhost1_48m_fck != NULL) { | 701 | if (omap->usbhost_fs_fck != NULL) { |
554 | clk_disable(omap->usbhost1_48m_fck); | 702 | clk_disable(omap->usbhost_fs_fck); |
555 | clk_put(omap->usbhost1_48m_fck); | 703 | clk_put(omap->usbhost_fs_fck); |
556 | omap->usbhost1_48m_fck = NULL; | 704 | omap->usbhost_fs_fck = NULL; |
557 | } | 705 | } |
558 | 706 | ||
559 | if (omap->usbhost2_120m_fck != NULL) { | 707 | if (omap->usbhost_hs_fck != NULL) { |
560 | clk_disable(omap->usbhost2_120m_fck); | 708 | clk_disable(omap->usbhost_hs_fck); |
561 | clk_put(omap->usbhost2_120m_fck); | 709 | clk_put(omap->usbhost_hs_fck); |
562 | omap->usbhost2_120m_fck = NULL; | 710 | omap->usbhost_hs_fck = NULL; |
563 | } | 711 | } |
564 | 712 | ||
565 | if (omap->usbtll_ick != NULL) { | 713 | if (omap->usbtll_ick != NULL) { |
@@ -568,6 +716,32 @@ static void omap_stop_ehc(struct ehci_hcd_omap *omap, struct usb_hcd *hcd) | |||
568 | omap->usbtll_ick = NULL; | 716 | omap->usbtll_ick = NULL; |
569 | } | 717 | } |
570 | 718 | ||
719 | if (is_omap_ehci_rev2(omap)) { | ||
720 | if (omap->xclk60mhsp1_ck != NULL) { | ||
721 | clk_disable(omap->xclk60mhsp1_ck); | ||
722 | clk_put(omap->xclk60mhsp1_ck); | ||
723 | omap->xclk60mhsp1_ck = NULL; | ||
724 | } | ||
725 | |||
726 | if (omap->utmi_p1_fck != NULL) { | ||
727 | clk_disable(omap->utmi_p1_fck); | ||
728 | clk_put(omap->utmi_p1_fck); | ||
729 | omap->utmi_p1_fck = NULL; | ||
730 | } | ||
731 | |||
732 | if (omap->xclk60mhsp2_ck != NULL) { | ||
733 | clk_disable(omap->xclk60mhsp2_ck); | ||
734 | clk_put(omap->xclk60mhsp2_ck); | ||
735 | omap->xclk60mhsp2_ck = NULL; | ||
736 | } | ||
737 | |||
738 | if (omap->utmi_p2_fck != NULL) { | ||
739 | clk_disable(omap->utmi_p2_fck); | ||
740 | clk_put(omap->utmi_p2_fck); | ||
741 | omap->utmi_p2_fck = NULL; | ||
742 | } | ||
743 | } | ||
744 | |||
571 | if (omap->phy_reset) { | 745 | if (omap->phy_reset) { |
572 | if (gpio_is_valid(omap->reset_gpio_port[0])) | 746 | if (gpio_is_valid(omap->reset_gpio_port[0])) |
573 | gpio_free(omap->reset_gpio_port[0]); | 747 | gpio_free(omap->reset_gpio_port[0]); |