Commit 0ae86689 authored by Greg Kroah-Hartman's avatar Greg Kroah-Hartman

Merge branch 'omap4-ehci-for-greg' of...

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
parents e7cddda4 6aa85a5a
...@@ -44,6 +44,7 @@ config ARCH_OMAP4 ...@@ -44,6 +44,7 @@ config ARCH_OMAP4
select ARM_GIC select ARM_GIC
select PL310_ERRATA_588369 select PL310_ERRATA_588369
select ARM_ERRATA_720789 select ARM_ERRATA_720789
select USB_ARCH_HAS_EHCI
comment "OMAP Core Type" comment "OMAP Core Type"
depends on ARCH_OMAP2 depends on ARCH_OMAP2
......
...@@ -42,6 +42,7 @@ ...@@ -42,6 +42,7 @@
#define ETH_KS8851_IRQ 34 #define ETH_KS8851_IRQ 34
#define ETH_KS8851_POWER_ON 48 #define ETH_KS8851_POWER_ON 48
#define ETH_KS8851_QUART 138 #define ETH_KS8851_QUART 138
#define OMAP4SDP_MDM_PWR_EN_GPIO 157
#define OMAP4_SFH7741_SENSOR_OUTPUT_GPIO 184 #define OMAP4_SFH7741_SENSOR_OUTPUT_GPIO 184
#define OMAP4_SFH7741_ENABLE_GPIO 188 #define OMAP4_SFH7741_ENABLE_GPIO 188
...@@ -225,6 +226,16 @@ static void __init omap_4430sdp_init_irq(void) ...@@ -225,6 +226,16 @@ static void __init omap_4430sdp_init_irq(void)
omap_gpio_init(); omap_gpio_init();
} }
static const struct ehci_hcd_omap_platform_data ehci_pdata __initconst = {
.port_mode[0] = EHCI_HCD_OMAP_MODE_PHY,
.port_mode[1] = EHCI_HCD_OMAP_MODE_UNKNOWN,
.port_mode[2] = EHCI_HCD_OMAP_MODE_UNKNOWN,
.phy_reset = false,
.reset_gpio_port[0] = -EINVAL,
.reset_gpio_port[1] = -EINVAL,
.reset_gpio_port[2] = -EINVAL,
};
static struct omap_musb_board_data musb_board_data = { static struct omap_musb_board_data musb_board_data = {
.interface_type = MUSB_INTERFACE_UTMI, .interface_type = MUSB_INTERFACE_UTMI,
.mode = MUSB_PERIPHERAL, .mode = MUSB_PERIPHERAL,
...@@ -514,6 +525,15 @@ static void __init omap_4430sdp_init(void) ...@@ -514,6 +525,15 @@ static void __init omap_4430sdp_init(void)
platform_add_devices(sdp4430_devices, ARRAY_SIZE(sdp4430_devices)); platform_add_devices(sdp4430_devices, ARRAY_SIZE(sdp4430_devices));
omap_serial_init(); omap_serial_init();
omap4_twl6030_hsmmc_init(mmc); omap4_twl6030_hsmmc_init(mmc);
/* Power on the ULPI PHY */
if (gpio_is_valid(OMAP4SDP_MDM_PWR_EN_GPIO)) {
/* FIXME: Assumes pad is already muxed for GPIO mode */
gpio_request(OMAP4SDP_MDM_PWR_EN_GPIO, "USBB1 PHY VMDM_3V3");
gpio_direction_output(OMAP4SDP_MDM_PWR_EN_GPIO, 1);
}
usb_ehci_init(&ehci_pdata);
/* OMAP4 SDP uses internal transceiver so register nop transceiver */ /* OMAP4 SDP uses internal transceiver so register nop transceiver */
usb_nop_xceiv_register(); usb_nop_xceiv_register();
/* FIXME: allow multi-omap to boot until musb is updated for omap4 */ /* FIXME: allow multi-omap to boot until musb is updated for omap4 */
......
...@@ -3278,6 +3278,7 @@ static struct omap_clk omap3xxx_clks[] = { ...@@ -3278,6 +3278,7 @@ static struct omap_clk omap3xxx_clks[] = {
CLK(NULL, "cpefuse_fck", &cpefuse_fck, CK_3430ES2 | CK_AM35XX), CLK(NULL, "cpefuse_fck", &cpefuse_fck, CK_3430ES2 | CK_AM35XX),
CLK(NULL, "ts_fck", &ts_fck, CK_3430ES2 | CK_AM35XX), CLK(NULL, "ts_fck", &ts_fck, CK_3430ES2 | CK_AM35XX),
CLK(NULL, "usbtll_fck", &usbtll_fck, CK_3430ES2 | CK_AM35XX), CLK(NULL, "usbtll_fck", &usbtll_fck, CK_3430ES2 | CK_AM35XX),
CLK("ehci-omap.0", "usbtll_fck", &usbtll_fck, CK_3430ES2 | CK_AM35XX),
CLK("omap-mcbsp.1", "prcm_fck", &core_96m_fck, CK_3XXX), CLK("omap-mcbsp.1", "prcm_fck", &core_96m_fck, CK_3XXX),
CLK("omap-mcbsp.5", "prcm_fck", &core_96m_fck, CK_3XXX), CLK("omap-mcbsp.5", "prcm_fck", &core_96m_fck, CK_3XXX),
CLK(NULL, "core_96m_fck", &core_96m_fck, CK_3XXX), CLK(NULL, "core_96m_fck", &core_96m_fck, CK_3XXX),
...@@ -3313,6 +3314,7 @@ static struct omap_clk omap3xxx_clks[] = { ...@@ -3313,6 +3314,7 @@ static struct omap_clk omap3xxx_clks[] = {
CLK(NULL, "pka_ick", &pka_ick, CK_343X), CLK(NULL, "pka_ick", &pka_ick, CK_343X),
CLK(NULL, "core_l4_ick", &core_l4_ick, CK_3XXX), CLK(NULL, "core_l4_ick", &core_l4_ick, CK_3XXX),
CLK(NULL, "usbtll_ick", &usbtll_ick, CK_3430ES2 | CK_AM35XX), CLK(NULL, "usbtll_ick", &usbtll_ick, CK_3430ES2 | CK_AM35XX),
CLK("ehci-omap.0", "usbtll_ick", &usbtll_ick, CK_3430ES2 | CK_AM35XX),
CLK("mmci-omap-hs.2", "ick", &mmchs3_ick, CK_3430ES2 | CK_AM35XX), CLK("mmci-omap-hs.2", "ick", &mmchs3_ick, CK_3430ES2 | CK_AM35XX),
CLK(NULL, "icr_ick", &icr_ick, CK_343X), CLK(NULL, "icr_ick", &icr_ick, CK_343X),
CLK("omap-aes", "ick", &aes2_ick, CK_343X), CLK("omap-aes", "ick", &aes2_ick, CK_343X),
...@@ -3358,8 +3360,11 @@ static struct omap_clk omap3xxx_clks[] = { ...@@ -3358,8 +3360,11 @@ static struct omap_clk omap3xxx_clks[] = {
CLK(NULL, "cam_ick", &cam_ick, CK_343X), CLK(NULL, "cam_ick", &cam_ick, CK_343X),
CLK(NULL, "csi2_96m_fck", &csi2_96m_fck, CK_343X), CLK(NULL, "csi2_96m_fck", &csi2_96m_fck, CK_343X),
CLK(NULL, "usbhost_120m_fck", &usbhost_120m_fck, CK_3430ES2 | CK_AM35XX), CLK(NULL, "usbhost_120m_fck", &usbhost_120m_fck, CK_3430ES2 | CK_AM35XX),
CLK("ehci-omap.0", "hs_fck", &usbhost_120m_fck, CK_3430ES2 | CK_AM35XX),
CLK(NULL, "usbhost_48m_fck", &usbhost_48m_fck, CK_3430ES2 | CK_AM35XX), CLK(NULL, "usbhost_48m_fck", &usbhost_48m_fck, CK_3430ES2 | CK_AM35XX),
CLK("ehci-omap.0", "fs_fck", &usbhost_48m_fck, CK_3430ES2 | CK_AM35XX),
CLK(NULL, "usbhost_ick", &usbhost_ick, CK_3430ES2 | CK_AM35XX), CLK(NULL, "usbhost_ick", &usbhost_ick, CK_3430ES2 | CK_AM35XX),
CLK("ehci-omap.0", "usbhost_ick", &usbhost_ick, CK_3430ES2 | CK_AM35XX),
CLK(NULL, "usim_fck", &usim_fck, CK_3430ES2), CLK(NULL, "usim_fck", &usim_fck, CK_3430ES2),
CLK(NULL, "gpt1_fck", &gpt1_fck, CK_3XXX), CLK(NULL, "gpt1_fck", &gpt1_fck, CK_3XXX),
CLK(NULL, "wkup_32k_fck", &wkup_32k_fck, CK_3XXX), CLK(NULL, "wkup_32k_fck", &wkup_32k_fck, CK_3XXX),
......
...@@ -2937,6 +2937,7 @@ static struct omap_clk omap44xx_clks[] = { ...@@ -2937,6 +2937,7 @@ static struct omap_clk omap44xx_clks[] = {
CLK(NULL, "uart3_fck", &uart3_fck, CK_443X), CLK(NULL, "uart3_fck", &uart3_fck, CK_443X),
CLK(NULL, "uart4_fck", &uart4_fck, CK_443X), CLK(NULL, "uart4_fck", &uart4_fck, CK_443X),
CLK(NULL, "usb_host_fs_fck", &usb_host_fs_fck, CK_443X), CLK(NULL, "usb_host_fs_fck", &usb_host_fs_fck, CK_443X),
CLK("ehci-omap.0", "fs_fck", &usb_host_fs_fck, CK_443X),
CLK(NULL, "usb_host_hs_utmi_p3_clk", &usb_host_hs_utmi_p3_clk, CK_443X), CLK(NULL, "usb_host_hs_utmi_p3_clk", &usb_host_hs_utmi_p3_clk, CK_443X),
CLK(NULL, "usb_host_hs_hsic60m_p1_clk", &usb_host_hs_hsic60m_p1_clk, CK_443X), CLK(NULL, "usb_host_hs_hsic60m_p1_clk", &usb_host_hs_hsic60m_p1_clk, CK_443X),
CLK(NULL, "usb_host_hs_hsic60m_p2_clk", &usb_host_hs_hsic60m_p2_clk, CK_443X), CLK(NULL, "usb_host_hs_hsic60m_p2_clk", &usb_host_hs_hsic60m_p2_clk, CK_443X),
...@@ -2948,6 +2949,8 @@ static struct omap_clk omap44xx_clks[] = { ...@@ -2948,6 +2949,8 @@ static struct omap_clk omap44xx_clks[] = {
CLK(NULL, "usb_host_hs_hsic480m_p2_clk", &usb_host_hs_hsic480m_p2_clk, CK_443X), CLK(NULL, "usb_host_hs_hsic480m_p2_clk", &usb_host_hs_hsic480m_p2_clk, CK_443X),
CLK(NULL, "usb_host_hs_func48mclk", &usb_host_hs_func48mclk, CK_443X), CLK(NULL, "usb_host_hs_func48mclk", &usb_host_hs_func48mclk, CK_443X),
CLK(NULL, "usb_host_hs_fck", &usb_host_hs_fck, CK_443X), CLK(NULL, "usb_host_hs_fck", &usb_host_hs_fck, CK_443X),
CLK("ehci-omap.0", "hs_fck", &usb_host_hs_fck, CK_443X),
CLK("ehci-omap.0", "usbhost_ick", &dummy_ck, CK_443X),
CLK(NULL, "otg_60m_gfclk", &otg_60m_gfclk, CK_443X), CLK(NULL, "otg_60m_gfclk", &otg_60m_gfclk, CK_443X),
CLK(NULL, "usb_otg_hs_xclk", &usb_otg_hs_xclk, CK_443X), CLK(NULL, "usb_otg_hs_xclk", &usb_otg_hs_xclk, CK_443X),
CLK("musb_hdrc", "ick", &usb_otg_hs_ick, CK_443X), CLK("musb_hdrc", "ick", &usb_otg_hs_ick, CK_443X),
...@@ -2956,6 +2959,8 @@ static struct omap_clk omap44xx_clks[] = { ...@@ -2956,6 +2959,8 @@ static struct omap_clk omap44xx_clks[] = {
CLK(NULL, "usb_tll_hs_usb_ch0_clk", &usb_tll_hs_usb_ch0_clk, CK_443X), CLK(NULL, "usb_tll_hs_usb_ch0_clk", &usb_tll_hs_usb_ch0_clk, CK_443X),
CLK(NULL, "usb_tll_hs_usb_ch1_clk", &usb_tll_hs_usb_ch1_clk, CK_443X), CLK(NULL, "usb_tll_hs_usb_ch1_clk", &usb_tll_hs_usb_ch1_clk, CK_443X),
CLK(NULL, "usb_tll_hs_ick", &usb_tll_hs_ick, CK_443X), CLK(NULL, "usb_tll_hs_ick", &usb_tll_hs_ick, CK_443X),
CLK("ehci-omap.0", "usbtll_ick", &usb_tll_hs_ick, CK_443X),
CLK("ehci-omap.0", "usbtll_fck", &dummy_ck, CK_443X),
CLK(NULL, "usim_ck", &usim_ck, CK_443X), CLK(NULL, "usim_ck", &usim_ck, CK_443X),
CLK(NULL, "usim_fclk", &usim_fclk, CK_443X), CLK(NULL, "usim_fclk", &usim_fclk, CK_443X),
CLK(NULL, "usim_fck", &usim_fck, CK_443X), CLK(NULL, "usim_fck", &usim_fck, CK_443X),
......
...@@ -34,22 +34,15 @@ ...@@ -34,22 +34,15 @@
static struct resource ehci_resources[] = { static struct resource ehci_resources[] = {
{ {
.start = OMAP34XX_EHCI_BASE,
.end = OMAP34XX_EHCI_BASE + SZ_1K - 1,
.flags = IORESOURCE_MEM, .flags = IORESOURCE_MEM,
}, },
{ {
.start = OMAP34XX_UHH_CONFIG_BASE,
.end = OMAP34XX_UHH_CONFIG_BASE + SZ_1K - 1,
.flags = IORESOURCE_MEM, .flags = IORESOURCE_MEM,
}, },
{ {
.start = OMAP34XX_USBTLL_BASE,
.end = OMAP34XX_USBTLL_BASE + SZ_4K - 1,
.flags = IORESOURCE_MEM, .flags = IORESOURCE_MEM,
}, },
{ /* general IRQ */ { /* general IRQ */
.start = INT_34XX_EHCI_IRQ,
.flags = IORESOURCE_IRQ, .flags = IORESOURCE_IRQ,
} }
}; };
...@@ -214,13 +207,148 @@ static void setup_ehci_io_mux(const enum ehci_hcd_omap_mode *port_mode) ...@@ -214,13 +207,148 @@ static void setup_ehci_io_mux(const enum ehci_hcd_omap_mode *port_mode)
return; return;
} }
static void setup_4430ehci_io_mux(const enum ehci_hcd_omap_mode *port_mode)
{
switch (port_mode[0]) {
case EHCI_HCD_OMAP_MODE_PHY:
omap_mux_init_signal("usbb1_ulpiphy_stp",
OMAP_PIN_OUTPUT);
omap_mux_init_signal("usbb1_ulpiphy_clk",
OMAP_PIN_INPUT_PULLDOWN);
omap_mux_init_signal("usbb1_ulpiphy_dir",
OMAP_PIN_INPUT_PULLDOWN);
omap_mux_init_signal("usbb1_ulpiphy_nxt",
OMAP_PIN_INPUT_PULLDOWN);
omap_mux_init_signal("usbb1_ulpiphy_dat0",
OMAP_PIN_INPUT_PULLDOWN);
omap_mux_init_signal("usbb1_ulpiphy_dat1",
OMAP_PIN_INPUT_PULLDOWN);
omap_mux_init_signal("usbb1_ulpiphy_dat2",
OMAP_PIN_INPUT_PULLDOWN);
omap_mux_init_signal("usbb1_ulpiphy_dat3",
OMAP_PIN_INPUT_PULLDOWN);
omap_mux_init_signal("usbb1_ulpiphy_dat4",
OMAP_PIN_INPUT_PULLDOWN);
omap_mux_init_signal("usbb1_ulpiphy_dat5",
OMAP_PIN_INPUT_PULLDOWN);
omap_mux_init_signal("usbb1_ulpiphy_dat6",
OMAP_PIN_INPUT_PULLDOWN);
omap_mux_init_signal("usbb1_ulpiphy_dat7",
OMAP_PIN_INPUT_PULLDOWN);
break;
case EHCI_HCD_OMAP_MODE_TLL:
omap_mux_init_signal("usbb1_ulpitll_stp",
OMAP_PIN_INPUT_PULLUP);
omap_mux_init_signal("usbb1_ulpitll_clk",
OMAP_PIN_INPUT_PULLDOWN);
omap_mux_init_signal("usbb1_ulpitll_dir",
OMAP_PIN_INPUT_PULLDOWN);
omap_mux_init_signal("usbb1_ulpitll_nxt",
OMAP_PIN_INPUT_PULLDOWN);
omap_mux_init_signal("usbb1_ulpitll_dat0",
OMAP_PIN_INPUT_PULLDOWN);
omap_mux_init_signal("usbb1_ulpitll_dat1",
OMAP_PIN_INPUT_PULLDOWN);
omap_mux_init_signal("usbb1_ulpitll_dat2",
OMAP_PIN_INPUT_PULLDOWN);
omap_mux_init_signal("usbb1_ulpitll_dat3",
OMAP_PIN_INPUT_PULLDOWN);
omap_mux_init_signal("usbb1_ulpitll_dat4",
OMAP_PIN_INPUT_PULLDOWN);
omap_mux_init_signal("usbb1_ulpitll_dat5",
OMAP_PIN_INPUT_PULLDOWN);
omap_mux_init_signal("usbb1_ulpitll_dat6",
OMAP_PIN_INPUT_PULLDOWN);
omap_mux_init_signal("usbb1_ulpitll_dat7",
OMAP_PIN_INPUT_PULLDOWN);
break;
case EHCI_HCD_OMAP_MODE_UNKNOWN:
default:
break;
}
switch (port_mode[1]) {
case EHCI_HCD_OMAP_MODE_PHY:
omap_mux_init_signal("usbb2_ulpiphy_stp",
OMAP_PIN_OUTPUT);
omap_mux_init_signal("usbb2_ulpiphy_clk",
OMAP_PIN_INPUT_PULLDOWN);
omap_mux_init_signal("usbb2_ulpiphy_dir",
OMAP_PIN_INPUT_PULLDOWN);
omap_mux_init_signal("usbb2_ulpiphy_nxt",
OMAP_PIN_INPUT_PULLDOWN);
omap_mux_init_signal("usbb2_ulpiphy_dat0",
OMAP_PIN_INPUT_PULLDOWN);
omap_mux_init_signal("usbb2_ulpiphy_dat1",
OMAP_PIN_INPUT_PULLDOWN);
omap_mux_init_signal("usbb2_ulpiphy_dat2",
OMAP_PIN_INPUT_PULLDOWN);
omap_mux_init_signal("usbb2_ulpiphy_dat3",
OMAP_PIN_INPUT_PULLDOWN);
omap_mux_init_signal("usbb2_ulpiphy_dat4",
OMAP_PIN_INPUT_PULLDOWN);
omap_mux_init_signal("usbb2_ulpiphy_dat5",
OMAP_PIN_INPUT_PULLDOWN);
omap_mux_init_signal("usbb2_ulpiphy_dat6",
OMAP_PIN_INPUT_PULLDOWN);
omap_mux_init_signal("usbb2_ulpiphy_dat7",
OMAP_PIN_INPUT_PULLDOWN);
break;
case EHCI_HCD_OMAP_MODE_TLL:
omap_mux_init_signal("usbb2_ulpitll_stp",
OMAP_PIN_INPUT_PULLUP);
omap_mux_init_signal("usbb2_ulpitll_clk",
OMAP_PIN_INPUT_PULLDOWN);
omap_mux_init_signal("usbb2_ulpitll_dir",
OMAP_PIN_INPUT_PULLDOWN);
omap_mux_init_signal("usbb2_ulpitll_nxt",
OMAP_PIN_INPUT_PULLDOWN);
omap_mux_init_signal("usbb2_ulpitll_dat0",
OMAP_PIN_INPUT_PULLDOWN);
omap_mux_init_signal("usbb2_ulpitll_dat1",
OMAP_PIN_INPUT_PULLDOWN);
omap_mux_init_signal("usbb2_ulpitll_dat2",
OMAP_PIN_INPUT_PULLDOWN);
omap_mux_init_signal("usbb2_ulpitll_dat3",
OMAP_PIN_INPUT_PULLDOWN);
omap_mux_init_signal("usbb2_ulpitll_dat4",
OMAP_PIN_INPUT_PULLDOWN);
omap_mux_init_signal("usbb2_ulpitll_dat5",
OMAP_PIN_INPUT_PULLDOWN);
omap_mux_init_signal("usbb2_ulpitll_dat6",
OMAP_PIN_INPUT_PULLDOWN);
omap_mux_init_signal("usbb2_ulpitll_dat7",
OMAP_PIN_INPUT_PULLDOWN);
break;
case EHCI_HCD_OMAP_MODE_UNKNOWN:
default:
break;
}
}
void __init usb_ehci_init(const struct ehci_hcd_omap_platform_data *pdata) void __init usb_ehci_init(const struct ehci_hcd_omap_platform_data *pdata)
{ {
platform_device_add_data(&ehci_device, pdata, sizeof(*pdata)); platform_device_add_data(&ehci_device, pdata, sizeof(*pdata));
/* Setup Pin IO MUX for EHCI */ /* Setup Pin IO MUX for EHCI */
if (cpu_is_omap34xx()) if (cpu_is_omap34xx()) {
ehci_resources[0].start = OMAP34XX_EHCI_BASE;
ehci_resources[0].end = OMAP34XX_EHCI_BASE + SZ_1K - 1;
ehci_resources[1].start = OMAP34XX_UHH_CONFIG_BASE;
ehci_resources[1].end = OMAP34XX_UHH_CONFIG_BASE + SZ_1K - 1;
ehci_resources[2].start = OMAP34XX_USBTLL_BASE;
ehci_resources[2].end = OMAP34XX_USBTLL_BASE + SZ_4K - 1;
ehci_resources[3].start = INT_34XX_EHCI_IRQ;
setup_ehci_io_mux(pdata->port_mode); setup_ehci_io_mux(pdata->port_mode);
} else if (cpu_is_omap44xx()) {
ehci_resources[0].start = OMAP44XX_HSUSB_EHCI_BASE;
ehci_resources[0].end = OMAP44XX_HSUSB_EHCI_BASE + SZ_1K - 1;
ehci_resources[1].start = OMAP44XX_UHH_CONFIG_BASE;
ehci_resources[1].end = OMAP44XX_UHH_CONFIG_BASE + SZ_2K - 1;
ehci_resources[2].start = OMAP44XX_USBTLL_BASE;
ehci_resources[2].end = OMAP44XX_USBTLL_BASE + SZ_4K - 1;
ehci_resources[3].start = OMAP44XX_IRQ_EHCI;
setup_4430ehci_io_mux(pdata->port_mode);
}
if (platform_device_register(&ehci_device) < 0) { if (platform_device_register(&ehci_device) < 0) {
printk(KERN_ERR "Unable to register HS-USB (EHCI) device\n"); printk(KERN_ERR "Unable to register HS-USB (EHCI) device\n");
......
...@@ -52,5 +52,10 @@ ...@@ -52,5 +52,10 @@
#define OMAP4_MMU1_BASE 0x55082000 #define OMAP4_MMU1_BASE 0x55082000
#define OMAP4_MMU2_BASE 0x4A066000 #define OMAP4_MMU2_BASE 0x4A066000
#define OMAP44XX_USBTLL_BASE (L4_44XX_BASE + 0x62000)
#define OMAP44XX_UHH_CONFIG_BASE (L4_44XX_BASE + 0x64000)
#define OMAP44XX_HSUSB_OHCI_BASE (L4_44XX_BASE + 0x64800)
#define OMAP44XX_HSUSB_EHCI_BASE (L4_44XX_BASE + 0x64C00)
#endif /* __ASM_ARCH_OMAP44XX_H */ #endif /* __ASM_ARCH_OMAP44XX_H */
...@@ -11,6 +11,7 @@ enum ehci_hcd_omap_mode { ...@@ -11,6 +11,7 @@ enum ehci_hcd_omap_mode {
EHCI_HCD_OMAP_MODE_UNKNOWN, EHCI_HCD_OMAP_MODE_UNKNOWN,
EHCI_HCD_OMAP_MODE_PHY, EHCI_HCD_OMAP_MODE_PHY,
EHCI_HCD_OMAP_MODE_TLL, EHCI_HCD_OMAP_MODE_TLL,
EHCI_HCD_OMAP_MODE_HSIC,
}; };
enum ohci_omap3_port_mode { enum ohci_omap3_port_mode {
......
...@@ -133,6 +133,14 @@ config USB_EHCI_MXC ...@@ -133,6 +133,14 @@ config USB_EHCI_MXC
---help--- ---help---
Variation of ARC USB block used in some Freescale chips. 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 config USB_EHCI_HCD_PPC_OF
bool "EHCI support for PPC USB controller on OF platform bus" bool "EHCI support for PPC USB controller on OF platform bus"
depends on USB_EHCI_HCD && PPC_OF depends on USB_EHCI_HCD && PPC_OF
......
...@@ -1171,7 +1171,7 @@ MODULE_LICENSE ("GPL"); ...@@ -1171,7 +1171,7 @@ MODULE_LICENSE ("GPL");
#define PLATFORM_DRIVER ehci_hcd_au1xxx_driver #define PLATFORM_DRIVER ehci_hcd_au1xxx_driver
#endif #endif
#ifdef CONFIG_ARCH_OMAP3 #ifdef CONFIG_USB_EHCI_HCD_OMAP
#include "ehci-omap.c" #include "ehci-omap.c"
#define PLATFORM_DRIVER ehci_hcd_omap_driver #define PLATFORM_DRIVER ehci_hcd_omap_driver
#endif #endif
......
/* /*
* 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 * Bus Glue for the EHCI controllers in OMAP3/4
* Tested on OMAP3430 ES2.0 SDP * 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 <vikram.pandita@ti.com> * Author: Vikram Pandita <vikram.pandita@ti.com>
* Author: Anand Gadiyar <gadiyar@ti.com>
* *
* Copyright (C) 2009 Nokia Corporation * Copyright (C) 2009 Nokia Corporation
* Contact: Felipe Balbi <felipe.balbi@nokia.com> * Contact: Felipe Balbi <felipe.balbi@nokia.com>
...@@ -26,11 +27,14 @@ ...@@ -26,11 +27,14 @@
* along with this program; if not, write to the Free Software * along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * 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 * - add kernel-doc
* - enable AUTOIDLE * - enable AUTOIDLE
* - add suspend/resume * - add suspend/resume
* - move workarounds to board-files * - move workarounds to board-files
* - factor out code common to OHCI
* - add HSIC and TLL support
* - convert to use hwmod and runtime PM
*/ */
#include <linux/platform_device.h> #include <linux/platform_device.h>
...@@ -114,6 +118,23 @@ ...@@ -114,6 +118,23 @@
#define OMAP_UHH_HOSTCONFIG_P2_CONNECT_STATUS (1 << 9) #define OMAP_UHH_HOSTCONFIG_P2_CONNECT_STATUS (1 << 9)
#define OMAP_UHH_HOSTCONFIG_P3_CONNECT_STATUS (1 << 10) #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) #define OMAP_UHH_DEBUG_CSR (0x44)
/* EHCI Register Set */ /* EHCI Register Set */
...@@ -127,6 +148,17 @@ ...@@ -127,6 +148,17 @@
#define EHCI_INSNREG05_ULPI_EXTREGADD_SHIFT 8 #define EHCI_INSNREG05_ULPI_EXTREGADD_SHIFT 8
#define EHCI_INSNREG05_ULPI_WRDATA_SHIFT 0 #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)
/*-------------------------------------------------------------------------*/ /*-------------------------------------------------------------------------*/
static inline void ehci_omap_writel(void __iomem *base, u32 reg, u32 val) static inline void ehci_omap_writel(void __iomem *base, u32 reg, u32 val)
...@@ -156,10 +188,14 @@ struct ehci_hcd_omap { ...@@ -156,10 +188,14 @@ struct ehci_hcd_omap {
struct device *dev; struct device *dev;
struct clk *usbhost_ick; struct clk *usbhost_ick;
struct clk *usbhost2_120m_fck; struct clk *usbhost_hs_fck;
struct clk *usbhost1_48m_fck; struct clk *usbhost_fs_fck;
struct clk *usbtll_fck; struct clk *usbtll_fck;
struct clk *usbtll_ick; 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 /* FIXME the following two workarounds are
* board specific not silicon-specific so these * board specific not silicon-specific so these
...@@ -176,6 +212,9 @@ struct ehci_hcd_omap { ...@@ -176,6 +212,9 @@ struct ehci_hcd_omap {
/* phy reset workaround */ /* phy reset workaround */
int phy_reset; int phy_reset;
/* IP revision */
u32 omap_ehci_rev;
/* desired phy_mode: TLL, PHY */ /* desired phy_mode: TLL, PHY */
enum ehci_hcd_omap_mode port_mode[OMAP3_HS_USB_PORTS]; enum ehci_hcd_omap_mode port_mode[OMAP3_HS_USB_PORTS];
...@@ -191,13 +230,14 @@ struct ehci_hcd_omap { ...@@ -191,13 +230,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; unsigned reg;
int i; int i;
/* Program the 3 TLL channels upfront */ /* 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)); reg = ehci_omap_readl(omap->tll_base, OMAP_TLL_CHANNEL_CONF(i));
/* Disable AutoIdle, BitStuffing and use SDR Mode */ /* 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,7 +257,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); ehci_omap_writel(omap->tll_base, OMAP_TLL_SHARED_CONF, reg);
/* Enable channels now */ /* 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)); reg = ehci_omap_readl(omap->tll_base, OMAP_TLL_CHANNEL_CONF(i));
/* Enable only the reg that is needed */ /* 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,19 +326,19 @@ static int omap_start_ehc(struct ehci_hcd_omap *omap, struct usb_hcd *hcd)
} }
clk_enable(omap->usbhost_ick); clk_enable(omap->usbhost_ick);
omap->usbhost2_120m_fck = clk_get(omap->dev, "usbhost_120m_fck"); omap->usbhost_hs_fck = clk_get(omap->dev, "hs_fck");
if (IS_ERR(omap->usbhost2_120m_fck)) { if (IS_ERR(omap->usbhost_hs_fck)) {
ret = PTR_ERR(omap->usbhost2_120m_fck); ret = PTR_ERR(omap->usbhost_hs_fck);
goto err_host_120m_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"); omap->usbhost_fs_fck = clk_get(omap->dev, "fs_fck");
if (IS_ERR(omap->usbhost1_48m_fck)) { if (IS_ERR(omap->usbhost_fs_fck)) {
ret = PTR_ERR(omap->usbhost1_48m_fck); ret = PTR_ERR(omap->usbhost_fs_fck);
goto err_host_48m_fck; goto err_host_48m_fck;
} }
clk_enable(omap->usbhost1_48m_fck); clk_enable(omap->usbhost_fs_fck);
if (omap->phy_reset) { if (omap->phy_reset) {
/* Refer: ISSUE1 */ /* Refer: ISSUE1 */
...@@ -333,6 +373,80 @@ static int omap_start_ehc(struct ehci_hcd_omap *omap, struct usb_hcd *hcd) ...@@ -333,6 +373,80 @@ static int omap_start_ehc(struct ehci_hcd_omap *omap, struct usb_hcd *hcd)
} }
clk_enable(omap->usbtll_ick); 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 */ /* perform TLL soft reset, and wait until reset is complete */
ehci_omap_writel(omap->tll_base, OMAP_USBTLL_SYSCONFIG, ehci_omap_writel(omap->tll_base, OMAP_USBTLL_SYSCONFIG,
OMAP_USBTLL_SYSCONFIG_SOFTRESET); OMAP_USBTLL_SYSCONFIG_SOFTRESET);
...@@ -360,12 +474,20 @@ static int omap_start_ehc(struct ehci_hcd_omap *omap, struct usb_hcd *hcd) ...@@ -360,12 +474,20 @@ static int omap_start_ehc(struct ehci_hcd_omap *omap, struct usb_hcd *hcd)
/* Put UHH in NoIdle/NoStandby mode */ /* Put UHH in NoIdle/NoStandby mode */
reg = ehci_omap_readl(omap->uhh_base, OMAP_UHH_SYSCONFIG); reg = ehci_omap_readl(omap->uhh_base, OMAP_UHH_SYSCONFIG);
if (is_omap_ehci_rev1(omap)) {
reg |= (OMAP_UHH_SYSCONFIG_ENAWAKEUP reg |= (OMAP_UHH_SYSCONFIG_ENAWAKEUP
| OMAP_UHH_SYSCONFIG_SIDLEMODE | OMAP_UHH_SYSCONFIG_SIDLEMODE
| OMAP_UHH_SYSCONFIG_CACTIVITY | OMAP_UHH_SYSCONFIG_CACTIVITY
| OMAP_UHH_SYSCONFIG_MIDLEMODE); | OMAP_UHH_SYSCONFIG_MIDLEMODE);
reg &= ~OMAP_UHH_SYSCONFIG_AUTOIDLE; 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); ehci_omap_writel(omap->uhh_base, OMAP_UHH_SYSCONFIG, reg);
reg = ehci_omap_readl(omap->uhh_base, OMAP_UHH_HOSTCONFIG); reg = ehci_omap_readl(omap->uhh_base, OMAP_UHH_HOSTCONFIG);
...@@ -376,6 +498,7 @@ static int omap_start_ehc(struct ehci_hcd_omap *omap, struct usb_hcd *hcd) ...@@ -376,6 +498,7 @@ static int omap_start_ehc(struct ehci_hcd_omap *omap, struct usb_hcd *hcd)
| OMAP_UHH_HOSTCONFIG_INCR16_BURST_EN); | OMAP_UHH_HOSTCONFIG_INCR16_BURST_EN);
reg &= ~OMAP_UHH_HOSTCONFIG_INCRX_ALIGN_EN; reg &= ~OMAP_UHH_HOSTCONFIG_INCRX_ALIGN_EN;
if (is_omap_ehci_rev1(omap)) {
if (omap->port_mode[0] == EHCI_HCD_OMAP_MODE_UNKNOWN) if (omap->port_mode[0] == EHCI_HCD_OMAP_MODE_UNKNOWN)
reg &= ~OMAP_UHH_HOSTCONFIG_P1_CONNECT_STATUS; reg &= ~OMAP_UHH_HOSTCONFIG_P1_CONNECT_STATUS;
if (omap->port_mode[1] == EHCI_HCD_OMAP_MODE_UNKNOWN) if (omap->port_mode[1] == EHCI_HCD_OMAP_MODE_UNKNOWN)
...@@ -386,30 +509,45 @@ static int omap_start_ehc(struct ehci_hcd_omap *omap, struct usb_hcd *hcd) ...@@ -386,30 +509,45 @@ static int omap_start_ehc(struct ehci_hcd_omap *omap, struct usb_hcd *hcd)
/* Bypass the TLL module for PHY mode operation */ /* Bypass the TLL module for PHY mode operation */
if (cpu_is_omap3430() && (omap_rev() <= OMAP3430_REV_ES2_1)) { if (cpu_is_omap3430() && (omap_rev() <= OMAP3430_REV_ES2_1)) {
dev_dbg(omap->dev, "OMAP3 ES version <= ES2.1\n"); 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]) ||
(omap->port_mode[1] == EHCI_HCD_OMAP_MODE_PHY) || is_ehci_phy_mode(omap->port_mode[1]) ||
(omap->port_mode[2] == EHCI_HCD_OMAP_MODE_PHY)) is_ehci_phy_mode(omap->port_mode[2]))
reg &= ~OMAP_UHH_HOSTCONFIG_ULPI_BYPASS; reg &= ~OMAP_UHH_HOSTCONFIG_ULPI_BYPASS;
else else
reg |= OMAP_UHH_HOSTCONFIG_ULPI_BYPASS; reg |= OMAP_UHH_HOSTCONFIG_ULPI_BYPASS;
} else { } else {
dev_dbg(omap->dev, "OMAP3 ES version > ES2.1\n"); 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; 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; 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; 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; 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; 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; 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); ehci_omap_writel(omap->uhh_base, OMAP_UHH_HOSTCONFIG, reg);
dev_dbg(omap->dev, "UHH setup done, uhh_hostconfig=%x\n", reg); dev_dbg(omap->dev, "UHH setup done, uhh_hostconfig=%x\n", reg);
...@@ -438,7 +576,7 @@ static int omap_start_ehc(struct ehci_hcd_omap *omap, struct usb_hcd *hcd) ...@@ -438,7 +576,7 @@ static int omap_start_ehc(struct ehci_hcd_omap *omap, struct usb_hcd *hcd)
tll_ch_mask |= OMAP_TLL_CHANNEL_3_EN_MASK; tll_ch_mask |= OMAP_TLL_CHANNEL_3_EN_MASK;
/* Enable UTMI mode for required TLL channels */ /* 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) { if (omap->phy_reset) {
...@@ -464,6 +602,14 @@ static int omap_start_ehc(struct ehci_hcd_omap *omap, struct usb_hcd *hcd) ...@@ -464,6 +602,14 @@ static int omap_start_ehc(struct ehci_hcd_omap *omap, struct usb_hcd *hcd)
return 0; return 0;
err_sys_status: 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_disable(omap->usbtll_ick);
clk_put(omap->usbtll_ick); clk_put(omap->usbtll_ick);
...@@ -472,8 +618,8 @@ static int omap_start_ehc(struct ehci_hcd_omap *omap, struct usb_hcd *hcd) ...@@ -472,8 +618,8 @@ static int omap_start_ehc(struct ehci_hcd_omap *omap, struct usb_hcd *hcd)
clk_put(omap->usbtll_fck); clk_put(omap->usbtll_fck);
err_tll_fck: err_tll_fck:
clk_disable(omap->usbhost1_48m_fck); clk_disable(omap->usbhost_fs_fck);
clk_put(omap->usbhost1_48m_fck); clk_put(omap->usbhost_fs_fck);
if (omap->phy_reset) { if (omap->phy_reset) {
if (gpio_is_valid(omap->reset_gpio_port[0])) if (gpio_is_valid(omap->reset_gpio_port[0]))
...@@ -484,8 +630,8 @@ static int omap_start_ehc(struct ehci_hcd_omap *omap, struct usb_hcd *hcd) ...@@ -484,8 +630,8 @@ static int omap_start_ehc(struct ehci_hcd_omap *omap, struct usb_hcd *hcd)
} }
err_host_48m_fck: err_host_48m_fck:
clk_disable(omap->usbhost2_120m_fck); clk_disable(omap->usbhost_hs_fck);
clk_put(omap->usbhost2_120m_fck); clk_put(omap->usbhost_hs_fck);
err_host_120m_fck: err_host_120m_fck:
clk_disable(omap->usbhost_ick); clk_disable(omap->usbhost_ick);
...@@ -503,6 +649,8 @@ static void omap_stop_ehc(struct ehci_hcd_omap *omap, struct usb_hcd *hcd) ...@@ -503,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 */ /* Reset OMAP modules for insmod/rmmod to work */
ehci_omap_writel(omap->uhh_base, OMAP_UHH_SYSCONFIG, ehci_omap_writel(omap->uhh_base, OMAP_UHH_SYSCONFIG,
is_omap_ehci_rev2(omap) ?
OMAP4_UHH_SYSCONFIG_SOFTRESET :
OMAP_UHH_SYSCONFIG_SOFTRESET); OMAP_UHH_SYSCONFIG_SOFTRESET);
while (!(ehci_omap_readl(omap->uhh_base, OMAP_UHH_SYSSTATUS) while (!(ehci_omap_readl(omap->uhh_base, OMAP_UHH_SYSSTATUS)
& (1 << 0))) { & (1 << 0))) {
...@@ -550,16 +698,16 @@ static void omap_stop_ehc(struct ehci_hcd_omap *omap, struct usb_hcd *hcd) ...@@ -550,16 +698,16 @@ static void omap_stop_ehc(struct ehci_hcd_omap *omap, struct usb_hcd *hcd)
omap->usbhost_ick = NULL; omap->usbhost_ick = NULL;
} }
if (omap->usbhost1_48m_fck != NULL) { if (omap->usbhost_fs_fck != NULL) {
clk_disable(omap->usbhost1_48m_fck); clk_disable(omap->usbhost_fs_fck);
clk_put(omap->usbhost1_48m_fck); clk_put(omap->usbhost_fs_fck);
omap->usbhost1_48m_fck = NULL; omap->usbhost_fs_fck = NULL;
} }
if (omap->usbhost2_120m_fck != NULL) { if (omap->usbhost_hs_fck != NULL) {
clk_disable(omap->usbhost2_120m_fck); clk_disable(omap->usbhost_hs_fck);
clk_put(omap->usbhost2_120m_fck); clk_put(omap->usbhost_hs_fck);
omap->usbhost2_120m_fck = NULL; omap->usbhost_hs_fck = NULL;
} }
if (omap->usbtll_ick != NULL) { if (omap->usbtll_ick != NULL) {
...@@ -568,6 +716,32 @@ static void omap_stop_ehc(struct ehci_hcd_omap *omap, struct usb_hcd *hcd) ...@@ -568,6 +716,32 @@ static void omap_stop_ehc(struct ehci_hcd_omap *omap, struct usb_hcd *hcd)
omap->usbtll_ick = NULL; 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 (omap->phy_reset) {
if (gpio_is_valid(omap->reset_gpio_port[0])) if (gpio_is_valid(omap->reset_gpio_port[0]))
gpio_free(omap->reset_gpio_port[0]); gpio_free(omap->reset_gpio_port[0]);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment