aboutsummaryrefslogtreecommitdiffstats
path: root/drivers
diff options
context:
space:
mode:
authorAnand Gadiyar <gadiyar@ti.com>2010-11-21 12:53:42 -0500
committerAnand Gadiyar <gadiyar@ti.com>2010-11-30 16:05:49 -0500
commit4792a15bf0f388838c3e16636f961c99bc2f3572 (patch)
tree6007fd08b6008a98798027781b6a7bbec4ae5838 /drivers
parent1ed85659a29287bda958a9429461f4a1b0a033be (diff)
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 <keshava_mgowda@ti.com> Signed-off-by: Anand Gadiyar <gadiyar@ti.com>
Diffstat (limited to 'drivers')
-rw-r--r--drivers/usb/host/ehci-omap.c254
1 files changed, 212 insertions, 42 deletions
diff --git a/drivers/usb/host/ehci-omap.c b/drivers/usb/host/ehci-omap.c
index dd9d5c1d9a8f..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,8 +148,16 @@
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
130#define is_ehci_phy_mode(x) (x == EHCI_HCD_OMAP_MODE_PHY) 158#define is_ehci_phy_mode(x) (x == EHCI_HCD_OMAP_MODE_PHY)
131#define is_ehci_tll_mode(x) (x == EHCI_HCD_OMAP_MODE_TLL) 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)
132 161
133/*-------------------------------------------------------------------------*/ 162/*-------------------------------------------------------------------------*/
134 163
@@ -163,6 +192,10 @@ struct ehci_hcd_omap {
163 struct clk *usbhost_fs_fck; 192 struct clk *usbhost_fs_fck;
164 struct clk *usbtll_fck; 193 struct clk *usbtll_fck;
165 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;
166 199
167 /* FIXME the following two workarounds are 200 /* FIXME the following two workarounds are
168 * board specific not silicon-specific so these 201 * board specific not silicon-specific so these
@@ -179,6 +212,9 @@ struct ehci_hcd_omap {
179 /* phy reset workaround */ 212 /* phy reset workaround */
180 int phy_reset; 213 int phy_reset;
181 214
215 /* IP revision */
216 u32 omap_ehci_rev;
217
182 /* desired phy_mode: TLL, PHY */ 218 /* desired phy_mode: TLL, PHY */
183 enum ehci_hcd_omap_mode port_mode[OMAP3_HS_USB_PORTS]; 219 enum ehci_hcd_omap_mode port_mode[OMAP3_HS_USB_PORTS];
184 220
@@ -337,6 +373,80 @@ static int omap_start_ehc(struct ehci_hcd_omap *omap, struct usb_hcd *hcd)
337 } 373 }
338 clk_enable(omap->usbtll_ick); 374 clk_enable(omap->usbtll_ick);
339 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
340 /* perform TLL soft reset, and wait until reset is complete */ 450 /* perform TLL soft reset, and wait until reset is complete */
341 ehci_omap_writel(omap->tll_base, OMAP_USBTLL_SYSCONFIG, 451 ehci_omap_writel(omap->tll_base, OMAP_USBTLL_SYSCONFIG,
342 OMAP_USBTLL_SYSCONFIG_SOFTRESET); 452 OMAP_USBTLL_SYSCONFIG_SOFTRESET);
@@ -364,12 +474,20 @@ static int omap_start_ehc(struct ehci_hcd_omap *omap, struct usb_hcd *hcd)
364 474
365 /* Put UHH in NoIdle/NoStandby mode */ 475 /* Put UHH in NoIdle/NoStandby mode */
366 reg = ehci_omap_readl(omap->uhh_base, OMAP_UHH_SYSCONFIG); 476 reg = ehci_omap_readl(omap->uhh_base, OMAP_UHH_SYSCONFIG);
367 reg |= (OMAP_UHH_SYSCONFIG_ENAWAKEUP 477 if (is_omap_ehci_rev1(omap)) {
368 | OMAP_UHH_SYSCONFIG_SIDLEMODE 478 reg |= (OMAP_UHH_SYSCONFIG_ENAWAKEUP
369 | OMAP_UHH_SYSCONFIG_CACTIVITY 479 | OMAP_UHH_SYSCONFIG_SIDLEMODE
370 | OMAP_UHH_SYSCONFIG_MIDLEMODE); 480 | OMAP_UHH_SYSCONFIG_CACTIVITY
371 reg &= ~OMAP_UHH_SYSCONFIG_AUTOIDLE; 481 | OMAP_UHH_SYSCONFIG_MIDLEMODE);
482 reg &= ~OMAP_UHH_SYSCONFIG_AUTOIDLE;
483
372 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 }
373 ehci_omap_writel(omap->uhh_base, OMAP_UHH_SYSCONFIG, reg); 491 ehci_omap_writel(omap->uhh_base, OMAP_UHH_SYSCONFIG, reg);
374 492
375 reg = ehci_omap_readl(omap->uhh_base, OMAP_UHH_HOSTCONFIG); 493 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)
380 | OMAP_UHH_HOSTCONFIG_INCR16_BURST_EN); 498 | OMAP_UHH_HOSTCONFIG_INCR16_BURST_EN);
381 reg &= ~OMAP_UHH_HOSTCONFIG_INCRX_ALIGN_EN; 499 reg &= ~OMAP_UHH_HOSTCONFIG_INCRX_ALIGN_EN;
382 500
383 if (omap->port_mode[0] == EHCI_HCD_OMAP_MODE_UNKNOWN) 501 if (is_omap_ehci_rev1(omap)) {
384 reg &= ~OMAP_UHH_HOSTCONFIG_P1_CONNECT_STATUS; 502 if (omap->port_mode[0] == EHCI_HCD_OMAP_MODE_UNKNOWN)
385 if (omap->port_mode[1] == EHCI_HCD_OMAP_MODE_UNKNOWN) 503 reg &= ~OMAP_UHH_HOSTCONFIG_P1_CONNECT_STATUS;
386 reg &= ~OMAP_UHH_HOSTCONFIG_P2_CONNECT_STATUS; 504 if (omap->port_mode[1] == EHCI_HCD_OMAP_MODE_UNKNOWN)
387 if (omap->port_mode[2] == EHCI_HCD_OMAP_MODE_UNKNOWN) 505 reg &= ~OMAP_UHH_HOSTCONFIG_P2_CONNECT_STATUS;
388 reg &= ~OMAP_UHH_HOSTCONFIG_P3_CONNECT_STATUS; 506 if (omap->port_mode[2] == EHCI_HCD_OMAP_MODE_UNKNOWN)
389 507 reg &= ~OMAP_UHH_HOSTCONFIG_P3_CONNECT_STATUS;
390 /* Bypass the TLL module for PHY mode operation */ 508
391 if (cpu_is_omap3430() && (omap_rev() <= OMAP3430_REV_ES2_1)) { 509 /* Bypass the TLL module for PHY mode operation */
392 dev_dbg(omap->dev, "OMAP3 ES version <= ES2.1\n"); 510 if (cpu_is_omap3430() && (omap_rev() <= OMAP3430_REV_ES2_1)) {
393 if (is_ehci_phy_mode(omap->port_mode[0]) || 511 dev_dbg(omap->dev, "OMAP3 ES version <= ES2.1\n");
394 is_ehci_phy_mode(omap->port_mode[1]) || 512 if (is_ehci_phy_mode(omap->port_mode[0]) ||
395 is_ehci_phy_mode(omap->port_mode[2])) 513 is_ehci_phy_mode(omap->port_mode[1]) ||
396 reg &= ~OMAP_UHH_HOSTCONFIG_ULPI_BYPASS; 514 is_ehci_phy_mode(omap->port_mode[2]))
397 else 515 reg &= ~OMAP_UHH_HOSTCONFIG_ULPI_BYPASS;
398 reg |= OMAP_UHH_HOSTCONFIG_ULPI_BYPASS; 516 else
399 } else { 517 reg |= OMAP_UHH_HOSTCONFIG_ULPI_BYPASS;
400 dev_dbg(omap->dev, "OMAP3 ES version > ES2.1\n"); 518 } else {
401 if (is_ehci_phy_mode(omap->port_mode[0])) 519 dev_dbg(omap->dev, "OMAP3 ES version > ES2.1\n");
402 reg &= ~OMAP_UHH_HOSTCONFIG_ULPI_P1_BYPASS; 520 if (is_ehci_phy_mode(omap->port_mode[0]))
403 else if (is_ehci_tll_mode(omap->port_mode[0])) 521 reg &= ~OMAP_UHH_HOSTCONFIG_ULPI_P1_BYPASS;
404 reg |= OMAP_UHH_HOSTCONFIG_ULPI_P1_BYPASS; 522 else if (is_ehci_tll_mode(omap->port_mode[0]))
405 523 reg |= OMAP_UHH_HOSTCONFIG_ULPI_P1_BYPASS;
406 if (is_ehci_phy_mode(omap->port_mode[1])) 524
407 reg &= ~OMAP_UHH_HOSTCONFIG_ULPI_P2_BYPASS; 525 if (is_ehci_phy_mode(omap->port_mode[1]))
408 else if (is_ehci_tll_mode(omap->port_mode[1])) 526 reg &= ~OMAP_UHH_HOSTCONFIG_ULPI_P2_BYPASS;
409 reg |= OMAP_UHH_HOSTCONFIG_ULPI_P2_BYPASS; 527 else if (is_ehci_tll_mode(omap->port_mode[1]))
410 528 reg |= OMAP_UHH_HOSTCONFIG_ULPI_P2_BYPASS;
411 if (is_ehci_phy_mode(omap->port_mode[2])) 529
412 reg &= ~OMAP_UHH_HOSTCONFIG_ULPI_P3_BYPASS; 530 if (is_ehci_phy_mode(omap->port_mode[2]))
413 else if (is_ehci_tll_mode(omap->port_mode[2])) 531 reg &= ~OMAP_UHH_HOSTCONFIG_ULPI_P3_BYPASS;
414 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;
415 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;
416 } 549 }
550
417 ehci_omap_writel(omap->uhh_base, OMAP_UHH_HOSTCONFIG, reg); 551 ehci_omap_writel(omap->uhh_base, OMAP_UHH_HOSTCONFIG, reg);
418 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);
419 553
@@ -468,6 +602,14 @@ static int omap_start_ehc(struct ehci_hcd_omap *omap, struct usb_hcd *hcd)
468 return 0; 602 return 0;
469 603
470err_sys_status: 604err_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);
471 clk_disable(omap->usbtll_ick); 613 clk_disable(omap->usbtll_ick);
472 clk_put(omap->usbtll_ick); 614 clk_put(omap->usbtll_ick);
473 615
@@ -507,6 +649,8 @@ static void omap_stop_ehc(struct ehci_hcd_omap *omap, struct usb_hcd *hcd)
507 649
508 /* Reset OMAP modules for insmod/rmmod to work */ 650 /* Reset OMAP modules for insmod/rmmod to work */
509 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 :
510 OMAP_UHH_SYSCONFIG_SOFTRESET); 654 OMAP_UHH_SYSCONFIG_SOFTRESET);
511 while (!(ehci_omap_readl(omap->uhh_base, OMAP_UHH_SYSSTATUS) 655 while (!(ehci_omap_readl(omap->uhh_base, OMAP_UHH_SYSSTATUS)
512 & (1 << 0))) { 656 & (1 << 0))) {
@@ -572,6 +716,32 @@ static void omap_stop_ehc(struct ehci_hcd_omap *omap, struct usb_hcd *hcd)
572 omap->usbtll_ick = NULL; 716 omap->usbtll_ick = NULL;
573 } 717 }
574 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
575 if (omap->phy_reset) { 745 if (omap->phy_reset) {
576 if (gpio_is_valid(omap->reset_gpio_port[0])) 746 if (gpio_is_valid(omap->reset_gpio_port[0]))
577 gpio_free(omap->reset_gpio_port[0]); 747 gpio_free(omap->reset_gpio_port[0]);