OMAP3 EHCI has three ports and we can configure port modes (PHY/TLL) on per port basis in silicon version ES3.0 onwards. This patch modifies the existing EHCI driver to accomodate portwise mode configuration. Changes being done: - Pass platform_data pointer as parameter to usb_ehci_init() to avoid multiple parameters. - Use platform_data pointer in usb-ehci.c as platform_data directly without copying it to another *pdata*. - Initializing platform_data in all platform files with platform specific ehci parameters. - Added port_mode[OMAP_HS_USB_PORTS]in platform_data structures.This allows to setup mux pins on per port basis. - Added phy_reset_gpio[OMAP_HS_USB_PORTS]. Signed-off-by: Ajay Kumar Gupta <ajay.gupta@xxxxxx> --- arch/arm/mach-omap2/board-3430sdp.c | 15 +++++- arch/arm/mach-omap2/board-omap3beagle.c | 15 +++++- arch/arm/mach-omap2/board-omap3evm.c | 15 +++++- arch/arm/mach-omap2/board-omap3pandora.c | 15 +++++- arch/arm/mach-omap2/usb-ehci.c | 95 +++++++++++++++--------------- arch/arm/plat-omap/include/mach/usb.h | 12 ++-- drivers/usb/host/ehci-omap.c | 63 +++++++++++--------- 7 files changed, 145 insertions(+), 85 deletions(-) diff --git a/arch/arm/mach-omap2/board-3430sdp.c b/arch/arm/mach-omap2/board-3430sdp.c index 21b4a52..4d7a176 100644 --- a/arch/arm/mach-omap2/board-3430sdp.c +++ b/arch/arm/mach-omap2/board-3430sdp.c @@ -478,6 +478,19 @@ static inline void board_smc91x_init(void) #endif +static struct ehci_hcd_omap_platform_data ehci_pdata __initconst = { + + .port_mode[0] = EHCI_HCD_OMAP_MODE_PHY, + .port_mode[1] = EHCI_HCD_OMAP_MODE_PHY, + .port_mode[2] = EHCI_HCD_OMAP_MODE_UNKNOWN, + + .chargepump = true, + .phy_reset = true, + .reset_gpio_port[0] = 57, + .reset_gpio_port[1] = 61, + .reset_gpio_port[2] = -EINVAL +}; + static void __init omap_3430sdp_init(void) { omap3430_i2c_init(); @@ -495,7 +508,7 @@ static void __init omap_3430sdp_init(void) omap_serial_init(); usb_musb_init(); board_smc91x_init(); - usb_ehci_init(EHCI_HCD_OMAP_MODE_PHY, true, true, 57, 61); + usb_ehci_init(&ehci_pdata); } static void __init omap_3430sdp_map_io(void) diff --git a/arch/arm/mach-omap2/board-omap3beagle.c b/arch/arm/mach-omap2/board-omap3beagle.c index b6a68d5..1868e56 100644 --- a/arch/arm/mach-omap2/board-omap3beagle.c +++ b/arch/arm/mach-omap2/board-omap3beagle.c @@ -392,6 +392,19 @@ static void __init omap3beagle_flash_init(void) } } +static struct ehci_hcd_omap_platform_data ehci_pdata __initconst = { + + .port_mode[0] = EHCI_HCD_OMAP_MODE_PHY, + .port_mode[1] = EHCI_HCD_OMAP_MODE_PHY, + .port_mode[2] = EHCI_HCD_OMAP_MODE_UNKNOWN, + + .chargepump = true, + .phy_reset = true, + .reset_gpio_port[0] = 57, + .reset_gpio_port[1] = 61, + .reset_gpio_port[2] = -EINVAL +}; + static void __init omap3_beagle_init(void) { omap3_beagle_i2c_init(); @@ -407,7 +420,7 @@ static void __init omap3_beagle_init(void) gpio_direction_output(170, true); usb_musb_init(); - usb_ehci_init(EHCI_HCD_OMAP_MODE_PHY, true, true, 57, 61); + usb_ehci_init(&ehci_pdata); omap3beagle_flash_init(); } diff --git a/arch/arm/mach-omap2/board-omap3evm.c b/arch/arm/mach-omap2/board-omap3evm.c index b497979..d2477e7 100644 --- a/arch/arm/mach-omap2/board-omap3evm.c +++ b/arch/arm/mach-omap2/board-omap3evm.c @@ -295,6 +295,19 @@ static struct platform_device *omap3_evm_devices[] __initdata = { &omap3evm_smc911x_device, }; +static struct ehci_hcd_omap_platform_data ehci_pdata __initconst = { + + .port_mode[0] = EHCI_HCD_OMAP_MODE_UNKNOWN, + .port_mode[1] = EHCI_HCD_OMAP_MODE_PHY, + .port_mode[2] = EHCI_HCD_OMAP_MODE_UNKNOWN, + + .chargepump = false, + .phy_reset = true, + .reset_gpio_port[0] = -EINVAL, + .reset_gpio_port[1] = 135, + .reset_gpio_port[2] = -EINVAL +}; + static void __init omap3_evm_init(void) { omap3_evm_i2c_init(); @@ -310,7 +323,7 @@ static void __init omap3_evm_init(void) usb_musb_init(); /* Setup EHCI phy reset padconfig */ omap_cfg_reg(AF4_34XX_GPIO135_OUT); - usb_ehci_init(EHCI_HCD_OMAP_MODE_PHY, false, true, -EINVAL, 135); + usb_ehci_init(&ehci_pdata); ads7846_dev_init(); } diff --git a/arch/arm/mach-omap2/board-omap3pandora.c b/arch/arm/mach-omap2/board-omap3pandora.c index 85cc2a7..5b20b3d 100644 --- a/arch/arm/mach-omap2/board-omap3pandora.c +++ b/arch/arm/mach-omap2/board-omap3pandora.c @@ -384,6 +384,19 @@ static struct platform_device *omap3pandora_devices[] __initdata = { &pandora_keys_gpio, }; +static 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, + + .chargepump = false, + .phy_reset = true, + .reset_gpio_port[0] = 16, + .reset_gpio_port[1] = -EINVAL, + .reset_gpio_port[2] = -EINVAL +}; + static void __init omap3pandora_init(void) { omap3pandora_i2c_init(); @@ -395,7 +408,7 @@ static void __init omap3pandora_init(void) spi_register_board_info(omap3pandora_spi_board_info, ARRAY_SIZE(omap3pandora_spi_board_info)); omap3pandora_ads7846_init(); - usb_ehci_init(EHCI_HCD_OMAP_MODE_PHY, false, true, 16, -EINVAL); + usb_ehci_init(&ehci_pdata); pandora_keys_gpio_init(); usb_musb_init(); } diff --git a/arch/arm/mach-omap2/usb-ehci.c b/arch/arm/mach-omap2/usb-ehci.c index 53e6e85..3af3236 100644 --- a/arch/arm/mach-omap2/usb-ehci.c +++ b/arch/arm/mach-omap2/usb-ehci.c @@ -68,14 +68,10 @@ static struct platform_device ehci_device = { /* * setup_ehci_io_mux - initialize IO pad mux for USBHOST */ -static void setup_ehci_io_mux(enum ehci_hcd_omap_mode phy_mode) +static void setup_ehci_io_mux(enum ehci_hcd_omap_mode *port_mode) { - if (phy_mode == EHCI_HCD_OMAP_MODE_PHY) { - /* PHY mode of operation for board: 750-2083-001 - * ISP1504 connected to Port1 and Port2 - * Do Func Mux setting for 12-pin ULPI PHY mode - */ - /* Port1 */ + switch (port_mode[0]) { + case EHCI_HCD_OMAP_MODE_PHY: omap_cfg_reg(Y9_3430_USB1HS_PHY_STP); omap_cfg_reg(Y8_3430_USB1HS_PHY_CLK); omap_cfg_reg(AA14_3430_USB1HS_PHY_DIR); @@ -88,28 +84,8 @@ static void setup_ehci_io_mux(enum ehci_hcd_omap_mode phy_mode) omap_cfg_reg(Y12_3430_USB1HS_PHY_DATA5); omap_cfg_reg(W8_3430_USB1HS_PHY_DATA6); omap_cfg_reg(Y13_3430_USB1HS_PHY_DATA7); - - /* Port2 */ - omap_cfg_reg(AA10_3430_USB2HS_PHY_STP); - omap_cfg_reg(AA8_3430_USB2HS_PHY_CLK); - omap_cfg_reg(AA9_3430_USB2HS_PHY_DIR); - omap_cfg_reg(AB11_3430_USB2HS_PHY_NXT); - omap_cfg_reg(AB10_3430_USB2HS_PHY_DATA0); - omap_cfg_reg(AB9_3430_USB2HS_PHY_DATA1); - omap_cfg_reg(W3_3430_USB2HS_PHY_DATA2); - omap_cfg_reg(T4_3430_USB2HS_PHY_DATA3); - omap_cfg_reg(T3_3430_USB2HS_PHY_DATA4); - omap_cfg_reg(R3_3430_USB2HS_PHY_DATA5); - omap_cfg_reg(R4_3430_USB2HS_PHY_DATA6); - omap_cfg_reg(T2_3430_USB2HS_PHY_DATA7); - - } else { - /* Set Func mux for : - * TLL mode of operation - * 12-pin ULPI SDR TLL mode for Port1/2/3 - */ - - /* Port1 */ + break; + case EHCI_HCD_OMAP_MODE_TLL: omap_cfg_reg(Y9_3430_USB1HS_TLL_STP); omap_cfg_reg(Y8_3430_USB1HS_TLL_CLK); omap_cfg_reg(AA14_3430_USB1HS_TLL_DIR); @@ -122,8 +98,29 @@ static void setup_ehci_io_mux(enum ehci_hcd_omap_mode phy_mode) omap_cfg_reg(Y12_3430_USB1HS_TLL_DATA5); omap_cfg_reg(W8_3430_USB1HS_TLL_DATA6); omap_cfg_reg(Y13_3430_USB1HS_TLL_DATA7); + break; + case EHCI_HCD_OMAP_MODE_UNKNOWN: + /* FALLTHROUGH */ + default: + break; + } - /* Port2 */ + switch (port_mode[1]) { + case EHCI_HCD_OMAP_MODE_PHY: + omap_cfg_reg(AA10_3430_USB2HS_PHY_STP); + omap_cfg_reg(AA8_3430_USB2HS_PHY_CLK); + omap_cfg_reg(AA9_3430_USB2HS_PHY_DIR); + omap_cfg_reg(AB11_3430_USB2HS_PHY_NXT); + omap_cfg_reg(AB10_3430_USB2HS_PHY_DATA0); + omap_cfg_reg(AB9_3430_USB2HS_PHY_DATA1); + omap_cfg_reg(W3_3430_USB2HS_PHY_DATA2); + omap_cfg_reg(T4_3430_USB2HS_PHY_DATA3); + omap_cfg_reg(T3_3430_USB2HS_PHY_DATA4); + omap_cfg_reg(R3_3430_USB2HS_PHY_DATA5); + omap_cfg_reg(R4_3430_USB2HS_PHY_DATA6); + omap_cfg_reg(T2_3430_USB2HS_PHY_DATA7); + break; + case EHCI_HCD_OMAP_MODE_TLL: omap_cfg_reg(AA10_3430_USB2HS_TLL_STP); omap_cfg_reg(AA8_3430_USB2HS_TLL_CLK); omap_cfg_reg(AA9_3430_USB2HS_TLL_DIR); @@ -136,8 +133,18 @@ static void setup_ehci_io_mux(enum ehci_hcd_omap_mode phy_mode) omap_cfg_reg(R3_3430_USB2HS_TLL_DATA5); omap_cfg_reg(R4_3430_USB2HS_TLL_DATA6); omap_cfg_reg(T2_3430_USB2HS_TLL_DATA7); + break; + case EHCI_HCD_OMAP_MODE_UNKNOWN: + /* FALLTHROUGH */ + default: + break; + } - /* Port3 */ + switch (port_mode[2]) { + case EHCI_HCD_OMAP_MODE_PHY: + printk(KERN_WARNING "Port3 can't be used in PHY mode\n"); + break; + case EHCI_HCD_OMAP_MODE_TLL: omap_cfg_reg(AB3_3430_USB3HS_TLL_STP); omap_cfg_reg(AA6_3430_USB3HS_TLL_CLK); omap_cfg_reg(AA3_3430_USB3HS_TLL_DIR); @@ -150,28 +157,23 @@ static void setup_ehci_io_mux(enum ehci_hcd_omap_mode phy_mode) omap_cfg_reg(AB13_3430_USB3HS_TLL_DATA5); omap_cfg_reg(AA13_3430_USB3HS_TLL_DATA6); omap_cfg_reg(AA12_3430_USB3HS_TLL_DATA7); + break; + case EHCI_HCD_OMAP_MODE_UNKNOWN: + /* FALLTHROUGH */ + default: + break; } return; } -static struct ehci_hcd_omap_platform_data pdata __initconst; - -void __init usb_ehci_init(enum ehci_hcd_omap_mode phy_mode, - int chargepump, int phy_reset, int reset_gpio_port1, - int reset_gpio_port2) +void __init usb_ehci_init(struct ehci_hcd_omap_platform_data *pdata) { - pdata.phy_mode = phy_mode; - pdata.chargepump = chargepump; - pdata.phy_reset = phy_reset; - pdata.reset_gpio_port1 = reset_gpio_port1; - pdata.reset_gpio_port2 = reset_gpio_port2; - - platform_device_add_data(&ehci_device, &pdata, sizeof(pdata)); + platform_device_add_data(&ehci_device, pdata, sizeof(*pdata)); /* Setup Pin IO MUX for EHCI */ if (cpu_is_omap34xx()) - setup_ehci_io_mux(phy_mode); + setup_ehci_io_mux(pdata->port_mode); if (platform_device_register(&ehci_device) < 0) { printk(KERN_ERR "Unable to register HS-USB (EHCI) device\n"); @@ -181,9 +183,8 @@ void __init usb_ehci_init(enum ehci_hcd_omap_mode phy_mode, #else -void __init usb_ehci_init(enum ehci_hcd_omap_mode phy_mode, - int chargepump, int phy_reset, int reset_gpio_port1, - int reset_gpio_port2) +void __init usb_ehci_init(struct ehci_hcd_omap_platform_data *pdata) + { } diff --git a/arch/arm/plat-omap/include/mach/usb.h b/arch/arm/plat-omap/include/mach/usb.h index 1b1366c..d1b14cc 100644 --- a/arch/arm/plat-omap/include/mach/usb.h +++ b/arch/arm/plat-omap/include/mach/usb.h @@ -5,6 +5,7 @@ #include <mach/board.h> +#define OMAP3_HS_USB_PORTS 3 enum ehci_hcd_omap_mode { EHCI_HCD_OMAP_MODE_UNKNOWN, EHCI_HCD_OMAP_MODE_PHY, @@ -12,13 +13,12 @@ enum ehci_hcd_omap_mode { }; struct ehci_hcd_omap_platform_data { - enum ehci_hcd_omap_mode phy_mode; + enum ehci_hcd_omap_mode port_mode[OMAP3_HS_USB_PORTS]; unsigned chargepump:1; unsigned phy_reset:1; - /* have to be valid if phy_reset is true */ - int reset_gpio_port1; - int reset_gpio_port2; + /* have to be valid if phy_reset is true and portx is in phy mode */ + int reset_gpio_port[OMAP3_HS_USB_PORTS]; }; /*-------------------------------------------------------------------------*/ @@ -45,9 +45,7 @@ struct ehci_hcd_omap_platform_data { extern void usb_musb_init(void); -extern void usb_ehci_init(enum ehci_hcd_omap_mode phy_mode, - int chargepump, int phy_reset, int reset_gpio_port1, - int reset_gpio_port2); +extern void usb_ehci_init(struct ehci_hcd_omap_platform_data *pdata); #endif diff --git a/drivers/usb/host/ehci-omap.c b/drivers/usb/host/ehci-omap.c index c7631f5..3175122 100644 --- a/drivers/usb/host/ehci-omap.c +++ b/drivers/usb/host/ehci-omap.c @@ -162,8 +162,7 @@ struct ehci_hcd_omap { */ /* gpio for resetting phy */ - int reset_gpio_port1; - int reset_gpio_port2; + int reset_gpio_port[OMAP3_HS_USB_PORTS]; /* phy reset workaround */ int phy_reset; @@ -172,7 +171,7 @@ struct ehci_hcd_omap { int chargepump; /* desired phy_mode: TLL, PHY */ - enum ehci_hcd_omap_mode phy_mode; + enum ehci_hcd_omap_mode port_mode[OMAP3_HS_USB_PORTS]; void __iomem *uhh_base; void __iomem *tll_base; @@ -297,14 +296,16 @@ static int omap_start_ehc(struct ehci_hcd_omap *omap, struct usb_hcd *hcd) if (omap->phy_reset) { /* Refer: ISSUE1 */ - if (gpio_is_valid(omap->reset_gpio_port1)) { - gpio_request(omap->reset_gpio_port1, "USB1 PHY reset"); - gpio_direction_output(omap->reset_gpio_port1, 0); + if (gpio_is_valid(omap->reset_gpio_port[0])) { + gpio_request(omap->reset_gpio_port[0], + "USB1 PHY reset"); + gpio_direction_output(omap->reset_gpio_port[0], 0); } - if (gpio_is_valid(omap->reset_gpio_port2)) { - gpio_request(omap->reset_gpio_port2, "USB2 PHY reset"); - gpio_direction_output(omap->reset_gpio_port2, 0); + if (gpio_is_valid(omap->reset_gpio_port[1])) { + gpio_request(omap->reset_gpio_port[1], + "USB2 PHY reset"); + gpio_direction_output(omap->reset_gpio_port[1], 0); } /* Hold the PHY in RESET for enough time till DIR is high */ @@ -361,7 +362,10 @@ static int omap_start_ehc(struct ehci_hcd_omap *omap, struct usb_hcd *hcd) ehci_omap_writel(omap->uhh_base, OMAP_UHH_SYSCONFIG, reg); - if (omap->phy_mode == EHCI_HCD_OMAP_MODE_PHY) { + 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)) { + reg = ehci_omap_readl(omap->uhh_base, OMAP_UHH_HOSTCONFIG); reg |= (OMAP_UHH_HOSTCONFIG_INCR4_BURST_EN @@ -374,7 +378,9 @@ static int omap_start_ehc(struct ehci_hcd_omap *omap, struct usb_hcd *hcd) ehci_omap_writel(omap->uhh_base, OMAP_UHH_HOSTCONFIG, reg); dev_dbg(omap->dev, "Entered ULPI PHY MODE: success\n"); - } else if (omap->phy_mode == EHCI_HCD_OMAP_MODE_TLL) { + } else if ((omap->port_mode[0] == EHCI_HCD_OMAP_MODE_TLL) || + (omap->port_mode[1] == EHCI_HCD_OMAP_MODE_TLL) || + (omap->port_mode[2] == EHCI_HCD_OMAP_MODE_TLL)) { /* Enable UTMI mode for all 3 TLL channels */ omap_usb_utmi_init(omap, @@ -396,11 +402,11 @@ static int omap_start_ehc(struct ehci_hcd_omap *omap, struct usb_hcd *hcd) */ udelay(10); - if (gpio_is_valid(omap->reset_gpio_port1)) - gpio_set_value(omap->reset_gpio_port1, 1); + if (gpio_is_valid(omap->reset_gpio_port[0])) + gpio_set_value(omap->reset_gpio_port[0], 1); - if (gpio_is_valid(omap->reset_gpio_port2)) - gpio_set_value(omap->reset_gpio_port2, 1); + if (gpio_is_valid(omap->reset_gpio_port[1])) + gpio_set_value(omap->reset_gpio_port[1], 1); } if (omap->chargepump) { @@ -438,11 +444,11 @@ err_tll_fck: clk_put(omap->usbhost1_48m_fck); if (omap->phy_reset) { - if (gpio_is_valid(omap->reset_gpio_port1)) - gpio_free(omap->reset_gpio_port1); + if (gpio_is_valid(omap->reset_gpio_port[0])) + gpio_free(omap->reset_gpio_port[0]); - if (gpio_is_valid(omap->reset_gpio_port2)) - gpio_free(omap->reset_gpio_port2); + if (gpio_is_valid(omap->reset_gpio_port[1])) + gpio_free(omap->reset_gpio_port[1]); } err_host_48m_fck: @@ -531,11 +537,11 @@ static void omap_stop_ehc(struct ehci_hcd_omap *omap, struct usb_hcd *hcd) } if (omap->phy_reset) { - if (gpio_is_valid(omap->reset_gpio_port1)) - gpio_free(omap->reset_gpio_port1); + if (gpio_is_valid(omap->reset_gpio_port[0])) + gpio_free(omap->reset_gpio_port[0]); - if (gpio_is_valid(omap->reset_gpio_port2)) - gpio_free(omap->reset_gpio_port2); + if (gpio_is_valid(omap->reset_gpio_port[1])) + gpio_free(omap->reset_gpio_port[1]); } dev_dbg(omap->dev, "Clock to USB host has been disabled\n"); @@ -590,10 +596,13 @@ static int ehci_hcd_omap_probe(struct platform_device *pdev) platform_set_drvdata(pdev, omap); omap->dev = &pdev->dev; omap->phy_reset = pdata->phy_reset; - omap->reset_gpio_port1 = pdata->reset_gpio_port1; - omap->reset_gpio_port2 = pdata->reset_gpio_port2; - omap->phy_mode = pdata->phy_mode; - omap->chargepump = pdata->chargepump; + omap->reset_gpio_port[0] = pdata->reset_gpio_port[0]; + omap->reset_gpio_port[1] = pdata->reset_gpio_port[1]; + omap->reset_gpio_port[2] = pdata->reset_gpio_port[2]; + omap->port_mode[0] = pdata->port_mode[0]; + omap->port_mode[1] = pdata->port_mode[1]; + omap->port_mode[2] = pdata->port_mode[2]; + omap->chargepump = pdata->chargepump; omap->ehci = hcd_to_ehci(hcd); omap->ehci->sbrn = 0x20; -- 1.6.2.4 -- To unsubscribe from this list: send the line "unsubscribe linux-omap" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html