[rft/rfc/patch-v2.6.29-rc5+,16/23] usb: host: ehci: add platform_data
diff mbox

Message ID 1235415335-17408-17-git-send-email-me@felipebalbi.com
State RFC
Delegated to: Felipe Balbi
Headers show

Commit Message

Felipe Balbi Feb. 23, 2009, 6:55 p.m. UTC
Adding a platform_data to the driver allow us
to remove some of the ifdeferry in the code.

Signed-off-by: Felipe Balbi <me@felipebalbi.com>
---
 arch/arm/mach-omap2/board-3430sdp.c      |    2 +-
 arch/arm/mach-omap2/board-omap3beagle.c  |    2 +-
 arch/arm/mach-omap2/board-omap3evm.c     |    2 +-
 arch/arm/mach-omap2/board-omap3pandora.c |    2 +-
 arch/arm/mach-omap2/board-overo.c        |    2 +-
 arch/arm/mach-omap2/usb-ehci.c           |   14 +-
 arch/arm/plat-omap/include/mach/usb.h    |   24 ++-
 drivers/usb/host/Kconfig                 |   19 --
 drivers/usb/host/ehci-omap.c             |  401 +++++++++++++++---------------
 9 files changed, 241 insertions(+), 227 deletions(-)

Comments

Grazvydas Ignotas Feb. 24, 2009, 10:35 p.m. UTC | #1
On Mon, Feb 23, 2009 at 8:55 PM, Felipe Balbi <me@felipebalbi.com> wrote:
> Adding a platform_data to the driver allow us
> to remove some of the ifdeferry in the code.
>

<snip>

> diff --git a/arch/arm/mach-omap2/board-omap3pandora.c b/arch/arm/mach-omap2/board-omap3pandora.c
> index b8a78c0..08215c0 100644
> --- a/arch/arm/mach-omap2/board-omap3pandora.c
> +++ b/arch/arm/mach-omap2/board-omap3pandora.c
> @@ -297,7 +297,7 @@ static void __init omap3pandora_init(void)
>        spi_register_board_info(omap3pandora_spi_board_info,
>                        ARRAY_SIZE(omap3pandora_spi_board_info));
>        usb_musb_init();
> -       usb_ehci_init();
> +       usb_ehci_init(EHCI_HCD_OMAP_MODE_PHY, true, true, 57, 61);

Perhaps it would be better to have .chargepump and .phy_reset set to
false by default, as pandora doesn't need that chargepump thing (I
guess some other boards too), and phy reset GPIO is wrong not only for
pandora I think. Board maintainers can then send patches as needed.
There also should be a way to specify only one reset GPIO, most boards
have only one EHCI port I think. Note that .phy_reset is required for
EHCI to work on pandora (in case you have thoughts of removing that
code later).

> diff --git a/arch/arm/mach-omap2/usb-ehci.c b/arch/arm/mach-omap2/usb-ehci.c
> index 23fe857..30e1ad6 100644
> --- a/arch/arm/mach-omap2/usb-ehci.c
> +++ b/arch/arm/mach-omap2/usb-ehci.c
> @@ -145,8 +145,20 @@ static void setup_ehci_io_mux(void)
>        return;
>  }
>
> -void __init usb_ehci_init(void)
> +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)
>  {
> +       struct ehci_hcd_omap_platform_data pdata = {
> +               .phy_mode               = phy_mode,
> +               .chargepump             = chargepump,
> +               .phy_reset              = phy_reset,
> +               .reset_gpio_port1       = reset_gpio_port1,
> +               .reset_gpio_port2       = reset_gpio_port2,
> +       };
> +
> +       ehci_device.dev.platform_data = &pdata;
> +

hmm, doesn't pdata end up on stack here? platform_device_register()
doesn't seem to make a copy of that structure.
--
To unsubscribe from this list: send the line "unsubscribe linux-omap" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Felipe Balbi Feb. 24, 2009, 10:39 p.m. UTC | #2
On Wed, Feb 25, 2009 at 12:35:05AM +0200, Grazvydas Ignotas wrote:
> On Mon, Feb 23, 2009 at 8:55 PM, Felipe Balbi <me@felipebalbi.com> wrote:
> > Adding a platform_data to the driver allow us
> > to remove some of the ifdeferry in the code.
> >
> 
> <snip>
> 
> > diff --git a/arch/arm/mach-omap2/board-omap3pandora.c b/arch/arm/mach-omap2/board-omap3pandora.c
> > index b8a78c0..08215c0 100644
> > --- a/arch/arm/mach-omap2/board-omap3pandora.c
> > +++ b/arch/arm/mach-omap2/board-omap3pandora.c
> > @@ -297,7 +297,7 @@ static void __init omap3pandora_init(void)
> >        spi_register_board_info(omap3pandora_spi_board_info,
> >                        ARRAY_SIZE(omap3pandora_spi_board_info));
> >        usb_musb_init();
> > -       usb_ehci_init();
> > +       usb_ehci_init(EHCI_HCD_OMAP_MODE_PHY, true, true, 57, 61);
> 
> Perhaps it would be better to have .chargepump and .phy_reset set to
> false by default, as pandora doesn't need that chargepump thing (I
> guess some other boards too), and phy reset GPIO is wrong not only for
> pandora I think. Board maintainers can then send patches as needed.
> There also should be a way to specify only one reset GPIO, most boards
> have only one EHCI port I think. Note that .phy_reset is required for
> EHCI to work on pandora (in case you have thoughts of removing that
> code later).

I made it true by default because those where always true in PHY mode as
of current driver. The correct way to do it, would be to move both to
board-file since those workarounds are board-specific.

We need a list of the boards that need the workarounds and a list of
those which don't need so we can move the workarounds to the
board-files.

> 
> > diff --git a/arch/arm/mach-omap2/usb-ehci.c b/arch/arm/mach-omap2/usb-ehci.c
> > index 23fe857..30e1ad6 100644
> > --- a/arch/arm/mach-omap2/usb-ehci.c
> > +++ b/arch/arm/mach-omap2/usb-ehci.c
> > @@ -145,8 +145,20 @@ static void setup_ehci_io_mux(void)
> >        return;
> >  }
> >
> > -void __init usb_ehci_init(void)
> > +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)
> >  {
> > +       struct ehci_hcd_omap_platform_data pdata = {
> > +               .phy_mode               = phy_mode,
> > +               .chargepump             = chargepump,
> > +               .phy_reset              = phy_reset,
> > +               .reset_gpio_port1       = reset_gpio_port1,
> > +               .reset_gpio_port2       = reset_gpio_port2,
> > +       };
> > +
> > +       ehci_device.dev.platform_data = &pdata;
> > +
> 
> hmm, doesn't pdata end up on stack here? platform_device_register()
> doesn't seem to make a copy of that structure.

hmm... should make that __initconst and use
platform_device_add_data();

Will fix, thanks a lot

Patch
diff mbox

diff --git a/arch/arm/mach-omap2/board-3430sdp.c b/arch/arm/mach-omap2/board-3430sdp.c
index 758183c..3f85c6e 100644
--- a/arch/arm/mach-omap2/board-3430sdp.c
+++ b/arch/arm/mach-omap2/board-3430sdp.c
@@ -643,7 +643,7 @@  static void __init omap_3430sdp_init(void)
 	msecure_init();
 	omap_serial_init();
 	usb_musb_init();
-	usb_ehci_init();
+	usb_ehci_init(EHCI_HCD_OMAP_MODE_PHY, true, true, 57, 61);
 }
 
 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 5f5cc39..18d9a86 100644
--- a/arch/arm/mach-omap2/board-omap3beagle.c
+++ b/arch/arm/mach-omap2/board-omap3beagle.c
@@ -380,7 +380,7 @@  static void __init omap3_beagle_init(void)
 	gpio_direction_output(170, true);
 
 	usb_musb_init();
-	usb_ehci_init();
+	usb_ehci_init(EHCI_HCD_OMAP_MODE_PHY, true, true, 57, 61);
 	omap3beagle_flash_init();
 }
 
diff --git a/arch/arm/mach-omap2/board-omap3evm.c b/arch/arm/mach-omap2/board-omap3evm.c
index 6577726..514058f 100644
--- a/arch/arm/mach-omap2/board-omap3evm.c
+++ b/arch/arm/mach-omap2/board-omap3evm.c
@@ -255,7 +255,7 @@  static void __init omap3_evm_init(void)
 	omap_serial_init();
 	twl4030_mmc_init(mmc);
 	usb_musb_init();
-	usb_ehci_init();
+	usb_ehci_init(EHCI_HCD_OMAP_MODE_PHY, true, true, 57, 61);
 	omap3evm_flash_init();
 	ads7846_dev_init();
 }
diff --git a/arch/arm/mach-omap2/board-omap3pandora.c b/arch/arm/mach-omap2/board-omap3pandora.c
index b8a78c0..08215c0 100644
--- a/arch/arm/mach-omap2/board-omap3pandora.c
+++ b/arch/arm/mach-omap2/board-omap3pandora.c
@@ -297,7 +297,7 @@  static void __init omap3pandora_init(void)
 	spi_register_board_info(omap3pandora_spi_board_info,
 			ARRAY_SIZE(omap3pandora_spi_board_info));
 	usb_musb_init();
-	usb_ehci_init();
+	usb_ehci_init(EHCI_HCD_OMAP_MODE_PHY, true, true, 57, 61);
 	omap3pandora_flash_init();
 	omap3pandora_ads7846_init();
 }
diff --git a/arch/arm/mach-omap2/board-overo.c b/arch/arm/mach-omap2/board-overo.c
index e5a3412..b51c835 100644
--- a/arch/arm/mach-omap2/board-overo.c
+++ b/arch/arm/mach-omap2/board-overo.c
@@ -246,7 +246,7 @@  static void __init overo_init(void)
 	omap_serial_init();
 	twl4030_mmc_init(mmc);
 	usb_musb_init();
-	usb_ehci_init();
+	usb_ehci_init(EHCI_HCD_OMAP_MODE_PHY, true, true, 57, 61);
 	overo_flash_init();
 
 	if ((gpio_request(OVERO_GPIO_W2W_NRESET,
diff --git a/arch/arm/mach-omap2/usb-ehci.c b/arch/arm/mach-omap2/usb-ehci.c
index 23fe857..30e1ad6 100644
--- a/arch/arm/mach-omap2/usb-ehci.c
+++ b/arch/arm/mach-omap2/usb-ehci.c
@@ -145,8 +145,20 @@  static void setup_ehci_io_mux(void)
 	return;
 }
 
-void __init usb_ehci_init(void)
+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)
 {
+	struct ehci_hcd_omap_platform_data pdata = {
+		.phy_mode		= phy_mode,
+		.chargepump		= chargepump,
+		.phy_reset		= phy_reset,
+		.reset_gpio_port1	= reset_gpio_port1,
+		.reset_gpio_port2	= reset_gpio_port2,
+	};
+
+	ehci_device.dev.platform_data = &pdata;
+
 	/* Setup Pin IO MUX for EHCI */
 	if (cpu_is_omap34xx())
 		setup_ehci_io_mux();
diff --git a/arch/arm/plat-omap/include/mach/usb.h b/arch/arm/plat-omap/include/mach/usb.h
index 47aba6b..8a341ca 100644
--- a/arch/arm/plat-omap/include/mach/usb.h
+++ b/arch/arm/plat-omap/include/mach/usb.h
@@ -5,6 +5,22 @@ 
 
 #include <mach/board.h>
 
+enum ehci_hcd_omap_mode {
+	EHCI_HCD_OMAP_MODE_UNKNOWN,
+	EHCI_HCD_OMAP_MODE_PHY,
+	EHCI_HCD_OMAP_MODE_TLL,
+};
+
+struct ehci_hcd_omap_platform_data {
+	enum ehci_hcd_omap_mode		phy_mode;
+	unsigned			chargepump:1;
+	unsigned			phy_reset:1;
+
+	/* have to be valid if phy_reset is true */
+	int				reset_gpio_port1;
+	int				reset_gpio_port2;
+};
+
 /*-------------------------------------------------------------------------*/
 
 #define OMAP1_OTG_BASE			0xfffb0400
@@ -36,9 +52,13 @@  static inline void usb_musb_init(void)
 #endif
 
 #if defined(CONFIG_USB_EHCI_HCD) || defined(CONFIG_USB_EHCI_HCD_MODULE)
-extern void usb_ehci_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);
 #else
-static inline void usb_ehci_init(void)
+static inline void usb_ehci_init(enum ehci_hcd_omap_mode phy_mode,
+		int chargepump, int phy_reset, int reset_gpio_port1,
+		int reset_gpio_port2)
 {
 }
 #endif
diff --git a/drivers/usb/host/Kconfig b/drivers/usb/host/Kconfig
index 02df795..2c63bfb 100644
--- a/drivers/usb/host/Kconfig
+++ b/drivers/usb/host/Kconfig
@@ -41,25 +41,6 @@  config USB_EHCI_HCD
 
 	  To compile this driver as a module, choose M here: the
 	  module will be called ehci-hcd.
-choice
-	prompt "PHY/TLL mode"
-	depends on USB_EHCI_HCD && EXPERIMENTAL && ARCH_OMAP34XX
-	---help---
-	Choose PHY or TLL mode of operation
-
-config OMAP_EHCI_PHY_MODE
-	bool "PHY mode: ISP1504 on Port1/2 (NEW 3430ES2.0)"
-	depends on USB_EHCI_HCD && EXPERIMENTAL && ARCH_OMAP34XX
-	---help---
-	  EHCI PHY mode. Port1 and Port2 are connected to ISP1504 transcievers
-
-config OMAP_EHCI_TLL_MODE
-	bool "TLL mode: (EXPERIMENTAL)"
-	depends on USB_EHCI_HCD && EXPERIMENTAL && ARCH_OMAP34XX
-	---help---
-	OMAP EHCI controller has TLL mode of operation for all 3 ports.
-	Use this mode when no transciever is present
-endchoice
 
 config USB_EHCI_ROOT_HUB_TT
 	bool "Root Hub Transaction Translators"
diff --git a/drivers/usb/host/ehci-omap.c b/drivers/usb/host/ehci-omap.c
index b058ada..cd891cc 100644
--- a/drivers/usb/host/ehci-omap.c
+++ b/drivers/usb/host/ehci-omap.c
@@ -29,6 +29,9 @@ 
 #include <linux/clk.h>
 #include <linux/gpio.h>
 
+/* platform_data lives here */
+#include <mach/usb.h>
+
 /* FIXME remove platform-specific code */
 #include <mach/hardware.h>
 #include "../../../arch/arm/mach-omap2/cm.h"
@@ -129,44 +132,30 @@ 
 /* OHCI Register Set */
 #define	OMAP_USBHOST_OHCI_BASE	(OMAP_USBHOST_BASE + 0x4400)
 
-#ifdef CONFIG_OMAP_EHCI_PHY_MODE
-/* EHCI connected to External PHY */
+/*-------------------------------------------------------------------------*/
 
-/* External USB connectivity board: 750-2083-001
- * Connected to OMAP3430 SDP
- * The board has Port1 and Port2 connected to ISP1504 in 12-pin ULPI mode
- */
+struct ehci_hcd_omap {
+	struct ehci_hcd		*ehci;
+	struct device		*dev;
 
-/* ISSUE1:
- *      ISP1504 for input clocking mode needs special reset handling
- *	Hold the PHY in reset by asserting RESET_N signal
- *	Then start the 60Mhz clock input to PHY
- *	Release the reset after a delay -
- *		to get the PHY state machine in working state
- */
-#define EXTERNAL_PHY_RESET
-#define	EXT_PHY_RESET_GPIO_PORT1	(57)
-#define	EXT_PHY_RESET_GPIO_PORT2	(61)
-#define	EXT_PHY_RESET_DELAY		(10)
-
-/* ISSUE2:
- * USBHOST supports External charge pump PHYs only
- * Use the VBUS from Port1 to power VBUS of Port2 externally
- * So use Port2 as the working ULPI port
- */
-#define VBUS_INTERNAL_CHARGEPUMP_HACK
+	struct clk		*usbhost_ick;
+	struct clk		*usbhost2_120m_fck;
+	struct clk		*usbhost1_48m_fck;
+	struct clk		*usbtll_fck;
+	struct clk		*usbtll_ick;
 
-#endif /* CONFIG_OMAP_EHCI_PHY_MODE */
+	/* gpio for resetting phy */
+	int			reset_gpio_port1;
+	int			reset_gpio_port2;
 
-/*-------------------------------------------------------------------------*/
+	/* phy reset workaround */
+	int			phy_reset;
 
-/* Define USBHOST clocks for clock management */
-struct ehci_omap_clock_defs {
-	struct clk	*usbhost_ick_clk;
-	struct clk	*usbhost2_120m_fck_clk;
-	struct clk	*usbhost1_48m_fck_clk;
-	struct clk	*usbtll_fck_clk;
-	struct clk	*usbtll_ick_clk;
+	/* vbus internal chargepump workaround */
+	int			chargepump;
+
+	/* desired phy_mode: TLL, PHY */
+	enum ehci_hcd_omap_mode	phy_mode;
 };
 
 /* Clock names as per clock framework: May change so keep as #defs */
@@ -178,8 +167,6 @@  struct ehci_omap_clock_defs {
 
 /*-------------------------------------------------------------------------*/
 
-#ifndef CONFIG_OMAP_EHCI_PHY_MODE
-
 static void omap_usb_utmi_init(struct usb_hcd *hcd, u8 tll_channel_mask)
 {
 	unsigned long timeout = jiffies + msecs_to_jiffies(100);
@@ -211,16 +198,16 @@  static void omap_usb_utmi_init(struct usb_hcd *hcd, u8 tll_channel_mask)
 
 		/* Disable AutoIdle */
 		omap_writel(omap_readl(OMAP_TLL_CHANNEL_CONF(i)) &
-			    ~(1 << OMAP_TLL_CHANNEL_CONF_UTMIAUTOIDLE_SHIFT),
-			    OMAP_TLL_CHANNEL_CONF(i));
+			~(1 << OMAP_TLL_CHANNEL_CONF_UTMIAUTOIDLE_SHIFT),
+			OMAP_TLL_CHANNEL_CONF(i));
 		/* Disable BitStuffing */
 		omap_writel(omap_readl(OMAP_TLL_CHANNEL_CONF(i)) &
-			    ~(1 << OMAP_TLL_CHANNEL_CONF_ULPINOBITSTUFF_SHIFT),
-			    OMAP_TLL_CHANNEL_CONF(i));
+			~(1 << OMAP_TLL_CHANNEL_CONF_ULPINOBITSTUFF_SHIFT),
+			OMAP_TLL_CHANNEL_CONF(i));
 		/* SDR Mode */
 		omap_writel(omap_readl(OMAP_TLL_CHANNEL_CONF(i)) &
-			    ~(1 << OMAP_TLL_CHANNEL_CONF_ULPIDDRMODE_SHIFT),
-			    OMAP_TLL_CHANNEL_CONF(i));
+				~(1 << OMAP_TLL_CHANNEL_CONF_ULPIDDRMODE_SHIFT),
+				OMAP_TLL_CHANNEL_CONF(i));
 
 	}
 
@@ -239,8 +226,8 @@  static void omap_usb_utmi_init(struct usb_hcd *hcd, u8 tll_channel_mask)
 			continue;
 
 		omap_writel(omap_readl(OMAP_TLL_CHANNEL_CONF(i)) |
-			    (1 << OMAP_TLL_CHANNEL_CONF_CHANEN_SHIFT),
-			    OMAP_TLL_CHANNEL_CONF(i));
+				(1 << OMAP_TLL_CHANNEL_CONF_CHANEN_SHIFT),
+				OMAP_TLL_CHANNEL_CONF(i));
 
 		omap_writeb(0xBE, OMAP_TLL_ULPI_SCRATCH_REGISTER(i));
 		dev_dbg(hcd->self.controller, "ULPI_SCRATCH_REG[ch=%d]"
@@ -249,27 +236,18 @@  static void omap_usb_utmi_init(struct usb_hcd *hcd, u8 tll_channel_mask)
 	}
 }
 
-#else
-# define omap_usb_utmi_init(x, y)	0
-#endif
-
 /*-------------------------------------------------------------------------*/
 
 /* omap_start_ehc
  *	- Start the TI USBHOST controller
  */
-static int omap_start_ehc(struct platform_device *dev, struct usb_hcd *hcd)
+static int omap_start_ehc(struct ehci_hcd_omap *omap, struct usb_hcd *hcd)
 {
-	struct ehci_omap_clock_defs *ehci_clocks;
 	unsigned long timeout = jiffies + msecs_to_jiffies(100);
 	int ret = 0;
 
 	dev_dbg(hcd->self.controller, "starting TI EHCI USB Controller\n");
 
-	ehci_clocks = (struct ehci_omap_clock_defs *)(
-				((char *)hcd_to_ehci(hcd)) +
-					sizeof(struct ehci_hcd));
-
 	/* Start DPLL5 Programming:
 	 * Clock Framework is not doing this now:
 	 * This will be done in clock framework later
@@ -317,55 +295,52 @@  static int omap_start_ehc(struct platform_device *dev, struct usb_hcd *hcd)
 				OMAP3430ES2_USBHOST_MOD, CM_CLKSTCTRL);
 
 	/* Enable Clocks for USBHOST */
-	ehci_clocks->usbhost_ick_clk = clk_get(&dev->dev,
-						USBHOST_ICKL);
-	if (IS_ERR(ehci_clocks->usbhost_ick_clk)) {
-		ret =  PTR_ERR(ehci_clocks->usbhost_ick_clk);
+	omap->usbhost_ick = clk_get(omap->dev, USBHOST_ICKL);
+	if (IS_ERR(omap->usbhost_ick)) {
+		ret =  PTR_ERR(omap->usbhost_ick);
 		goto err_host_ick;
 	}
-	clk_enable(ehci_clocks->usbhost_ick_clk);
+	clk_enable(omap->usbhost_ick);
 
-	ehci_clocks->usbhost2_120m_fck_clk = clk_get(&dev->dev,
-							USBHOST_120M_FCLK);
-	if (IS_ERR(ehci_clocks->usbhost2_120m_fck_clk)) {
-		ret = PTR_ERR(ehci_clocks->usbhost2_120m_fck_clk);
+	omap->usbhost2_120m_fck = clk_get(omap->dev, USBHOST_120M_FCLK);
+	if (IS_ERR(omap->usbhost2_120m_fck)) {
+		ret = PTR_ERR(omap->usbhost2_120m_fck);
 		goto err_host_120m_fck;
 	}
-	clk_enable(ehci_clocks->usbhost2_120m_fck_clk);
+	clk_enable(omap->usbhost2_120m_fck);
 
-	ehci_clocks->usbhost1_48m_fck_clk = clk_get(&dev->dev,
-						USBHOST_48M_FCLK);
-	if (IS_ERR(ehci_clocks->usbhost1_48m_fck_clk)) {
-		ret = PTR_ERR(ehci_clocks->usbhost1_48m_fck_clk);
+	omap->usbhost1_48m_fck = clk_get(omap->dev, USBHOST_48M_FCLK);
+	if (IS_ERR(omap->usbhost1_48m_fck)) {
+		ret = PTR_ERR(omap->usbhost1_48m_fck);
 		goto err_host_48m_fck;
 	}
-	clk_enable(ehci_clocks->usbhost1_48m_fck_clk);
+	clk_enable(omap->usbhost1_48m_fck);
 
 
-#ifdef EXTERNAL_PHY_RESET
-	/* Refer: ISSUE1 */
-	gpio_request(EXT_PHY_RESET_GPIO_PORT1, "USB1 PHY reset");
-	gpio_direction_output(EXT_PHY_RESET_GPIO_PORT1, 0);
-	gpio_request(EXT_PHY_RESET_GPIO_PORT2, "USB2 PHY reset");
-	gpio_direction_output(EXT_PHY_RESET_GPIO_PORT2, 0);
-	/* Hold the PHY in RESET for enough time till DIR is high */
-	udelay(EXT_PHY_RESET_DELAY);
-#endif
+	if (omap->phy_reset) {
+		/* Refer: ISSUE1 */
+		gpio_request(omap->reset_gpio_port1, "USB1 PHY reset");
+		gpio_direction_output(omap->reset_gpio_port1, 0);
+		gpio_request(omap->reset_gpio_port2, "USB2 PHY reset");
+		gpio_direction_output(omap->reset_gpio_port2, 0);
+		/* Hold the PHY in RESET for enough time till DIR is high */
+		udelay(10);
+	}
 
 	/* Configure TLL for 60Mhz clk for ULPI */
-	ehci_clocks->usbtll_fck_clk = clk_get(&dev->dev, USBHOST_TLL_FCLK);
-	if (IS_ERR(ehci_clocks->usbtll_fck_clk)) {
-		ret = PTR_ERR(ehci_clocks->usbtll_fck_clk);
+	omap->usbtll_fck = clk_get(omap->dev, USBHOST_TLL_FCLK);
+	if (IS_ERR(omap->usbtll_fck)) {
+		ret = PTR_ERR(omap->usbtll_fck);
 		goto err_tll_fck;
 	}
-	clk_enable(ehci_clocks->usbtll_fck_clk);
+	clk_enable(omap->usbtll_fck);
 
-	ehci_clocks->usbtll_ick_clk = clk_get(&dev->dev, USBHOST_TLL_ICKL);
-	if (IS_ERR(ehci_clocks->usbtll_ick_clk)) {
-		ret = PTR_ERR(ehci_clocks->usbtll_ick_clk);
+	omap->usbtll_ick = clk_get(omap->dev, USBHOST_TLL_ICKL);
+	if (IS_ERR(omap->usbtll_ick)) {
+		ret = PTR_ERR(omap->usbtll_ick);
 		goto err_tll_ick;
 	}
-	clk_enable(ehci_clocks->usbtll_ick_clk);
+	clk_enable(omap->usbtll_ick);
 
 	/* Disable Auto Idle of USBTLL */
 	cm_write_mod_reg((0 << OMAP3430ES2_AUTO_USBTLL_SHIFT),
@@ -416,120 +391,124 @@  static int omap_start_ehc(struct platform_device *dev, struct usb_hcd *hcd)
 			(1 << OMAP_UHH_SYSCONFIG_MIDLEMODE_SHIFT),
 			OMAP_UHH_SYSCONFIG);
 
-#ifdef CONFIG_OMAP_EHCI_PHY_MODE
-	/* Bypass the TLL module for PHY mode operation */
-	omap_writel((0 << OMAP_UHH_HOSTCONFIG_ULPI_BYPASS_SHIFT)|
+	if (omap->phy_mode == EHCI_HCD_OMAP_MODE_PHY) {
+
+		/* Bypass the TLL module for PHY mode operation */
+		omap_writel((0 << OMAP_UHH_HOSTCONFIG_ULPI_BYPASS_SHIFT)|
 			(1 << OMAP_UHH_HOSTCONFIG_INCR4_BURST_EN_SHIFT)|
 			(1 << OMAP_UHH_HOSTCONFIG_INCR8_BURST_EN_SHIFT)|
 			(1 << OMAP_UHH_HOSTCONFIG_INCR16_BURST_EN_SHIFT)|
 			(0 << OMAP_UHH_HOSTCONFIG_INCRX_ALIGN_EN_SHIFT),
-						OMAP_UHH_HOSTCONFIG);
+			OMAP_UHH_HOSTCONFIG);
 
-	/* Ensure that BYPASS is set */
-	while (omap_readl(OMAP_UHH_HOSTCONFIG)
+		/* Ensure that BYPASS is set */
+		while (omap_readl(OMAP_UHH_HOSTCONFIG)
 			& (1 << OMAP_UHH_HOSTCONFIG_ULPI_BYPASS_SHIFT)) {
-		cpu_relax();
-
-		if (time_after(timeout, jiffies)) {
-			dev_dbg(hcd->self.controller, "operation timed out\n");
-			ret = -EINVAL;
-			goto err_ulpi_bypass;
+			cpu_relax();
+
+			if (time_after(timeout, jiffies)) {
+				dev_dbg(hcd->self.controller,
+						"operation timed out\n");
+				ret = -EINVAL;
+				goto err_ulpi_bypass;
+			}
 		}
-	}
-
-	dev_dbg(hcd->self.controller, "Entered ULPI PHY MODE: success\n");
-
-#else
-	/* Enable UTMI mode for all 3 TLL channels */
-	omap_usb_utmi_init(hcd,
-		OMAP_TLL_CHANNEL_1_EN_MASK |
-		OMAP_TLL_CHANNEL_2_EN_MASK |
-		OMAP_TLL_CHANNEL_3_EN_MASK
-		);
-#endif
 
-#ifdef EXTERNAL_PHY_RESET
-	/* Refer ISSUE1:
-	 * Hold the PHY in RESET for enough time till PHY is settled and ready
-	 */
-	udelay(EXT_PHY_RESET_DELAY);
-	gpio_set_value(EXT_PHY_RESET_GPIO_PORT1, 1);
-	gpio_set_value(EXT_PHY_RESET_GPIO_PORT2, 1);
-#endif
-
-#ifdef VBUS_INTERNAL_CHARGEPUMP_HACK
-	/* Refer ISSUE2: LINK assumes external charge pump */
+		dev_dbg(hcd->self.controller,
+				"Entered ULPI PHY MODE: success\n");
+
+	} else if (omap->phy_mode == EHCI_HCD_OMAP_MODE_TLL) {
+
+		/* Enable UTMI mode for all 3 TLL channels */
+		omap_usb_utmi_init(hcd,
+			OMAP_TLL_CHANNEL_1_EN_MASK |
+			OMAP_TLL_CHANNEL_2_EN_MASK |
+			OMAP_TLL_CHANNEL_3_EN_MASK
+			);
+	} else {
+		dev_err(hcd->self.controller,
+				"UNKOWN mode requested\n");
+		ret = -EINVAL;
+		goto err_unknown_mode;
+	}
 
-	/* use Port1 VBUS to charge externally Port2:
-	 *	So for PHY mode operation use Port2 only
-	 */
-	omap_writel((0xA << EHCI_INSNREG05_ULPI_REGADD_SHIFT) |/* OTG ctrl reg*/
-			(2 << EHCI_INSNREG05_ULPI_OPSEL_SHIFT) |/*   Write */
-			(1 << EHCI_INSNREG05_ULPI_PORTSEL_SHIFT) |/* Port1 */
-			(1 << EHCI_INSNREG05_ULPI_CONTROL_SHIFT) |/* Start */
-			(0x26),
-			EHCI_INSNREG05_ULPI);
-
-	while (!(omap_readl(EHCI_INSNREG05_ULPI)
-			& (1 << EHCI_INSNREG05_ULPI_CONTROL_SHIFT))) {
-		cpu_relax();
+	if (omap->phy_reset) {
+		/* Refer ISSUE1:
+		 * Hold the PHY in RESET for enough time till
+		 * PHY is settled and ready
+		 */
+		udelay(10);
+		gpio_set_value(omap->reset_gpio_port1, 1);
+		gpio_set_value(omap->reset_gpio_port2, 1);
+	}
 
-		if (time_after(timeout, jiffies)) {
-			dev_dbg(hcd->self.controller, "operation timed out\n");
-			ret = -EINVAL;
-			goto err_ulpi_control;
+	if (omap->chargepump) {
+
+		/* Refer ISSUE2: LINK assumes external charge pump */
+
+		/* use Port1 VBUS to charge externally Port2:
+		 *	So for PHY mode operation use Port2 only
+		 */
+		omap_writel((0xA << EHCI_INSNREG05_ULPI_REGADD_SHIFT) |/* OTG ctrl reg*/
+				(2 << EHCI_INSNREG05_ULPI_OPSEL_SHIFT) |/*   Write */
+				(1 << EHCI_INSNREG05_ULPI_PORTSEL_SHIFT) |/* Port1 */
+				(1 << EHCI_INSNREG05_ULPI_CONTROL_SHIFT) |/* Start */
+				(0x26),
+				EHCI_INSNREG05_ULPI);
+
+		while (!(omap_readl(EHCI_INSNREG05_ULPI)
+				& (1 << EHCI_INSNREG05_ULPI_CONTROL_SHIFT))) {
+			cpu_relax();
+
+			if (time_after(timeout, jiffies)) {
+				dev_dbg(hcd->self.controller,
+						"operation timed out\n");
+				ret = -EINVAL;
+				goto err_ulpi_control;
+			}
 		}
 	}
 
-#endif
-
 	return 0;
 
-#ifdef VBUS_INTERNAL_CHARGEPUMP_HACK
 err_ulpi_control:
-#endif
-#ifdef CONFIG_OMAP_EHCI_PHY_MODE
+err_unknown_mode:
 err_ulpi_bypass:
-#endif
 err_sys_status:
 err_idlest3:
-	clk_disable(ehci_clocks->usbtll_ick_clk);
-	clk_put(ehci_clocks->usbtll_ick_clk);
+	clk_disable(omap->usbtll_ick);
+	clk_put(omap->usbtll_ick);
 
 err_tll_ick:
-	clk_disable(ehci_clocks->usbtll_fck_clk);
-	clk_put(ehci_clocks->usbtll_fck_clk);
+	clk_disable(omap->usbtll_fck);
+	clk_put(omap->usbtll_fck);
 
 err_tll_fck:
-	clk_disable(ehci_clocks->usbhost1_48m_fck_clk);
-	clk_put(ehci_clocks->usbhost1_48m_fck_clk);
+	clk_disable(omap->usbhost1_48m_fck);
+	clk_put(omap->usbhost1_48m_fck);
 
-#ifdef EXTERNAL_PHY_RESET
-	gpio_free(EXT_PHY_RESET_GPIO_PORT1);
-	gpio_free(EXT_PHY_RESET_GPIO_PORT2);
-#endif
+	if (omap->phy_reset) {
+		gpio_free(omap->reset_gpio_port1);
+		gpio_free(omap->reset_gpio_port2);
+	}
 
 err_host_48m_fck:
-	clk_disable(ehci_clocks->usbhost2_120m_fck_clk);
-	clk_put(ehci_clocks->usbhost2_120m_fck_clk);
+	clk_disable(omap->usbhost2_120m_fck);
+	clk_put(omap->usbhost2_120m_fck);
 
 err_host_120m_fck:
-	clk_disable(ehci_clocks->usbhost_ick_clk);
-	clk_put(ehci_clocks->usbhost_ick_clk);
+	clk_disable(omap->usbhost_ick);
+	clk_put(omap->usbhost_ick);
 
 err_host_ick:
 err_idlest2:
 	return ret;
 }
 
-static void omap_stop_ehc(struct platform_device *dev, struct usb_hcd *hcd)
+static void omap_stop_ehc(struct ehci_hcd_omap *omap, struct usb_hcd *hcd)
 {
-	struct ehci_omap_clock_defs *ehci_clocks;
 	unsigned long timeout = jiffies + msecs_to_jiffies(100);
 
-	ehci_clocks = (struct ehci_omap_clock_defs *)
-			(((char *)hcd_to_ehci(hcd)) + sizeof(struct ehci_hcd));
-
 	dev_dbg(hcd->self.controller, "stopping TI EHCI USB Controller\n");
 
 	/* Reset OMAP modules for insmod/rmmod to work */
@@ -575,40 +554,40 @@  static void omap_stop_ehc(struct platform_device *dev, struct usb_hcd *hcd)
 	}
 	dev_dbg(hcd->self.controller, "TLL RESET DONE\n");
 
-	if (ehci_clocks->usbtll_fck_clk != NULL) {
-		clk_disable(ehci_clocks->usbtll_fck_clk);
-		clk_put(ehci_clocks->usbtll_fck_clk);
-		ehci_clocks->usbtll_fck_clk = NULL;
+	if (omap->usbtll_fck != NULL) {
+		clk_disable(omap->usbtll_fck);
+		clk_put(omap->usbtll_fck);
+		omap->usbtll_fck = NULL;
 	}
 
-	if (ehci_clocks->usbhost_ick_clk != NULL) {
-		clk_disable(ehci_clocks->usbhost_ick_clk);
-		clk_put(ehci_clocks->usbhost_ick_clk);
-		ehci_clocks->usbhost_ick_clk = NULL;
+	if (omap->usbhost_ick != NULL) {
+		clk_disable(omap->usbhost_ick);
+		clk_put(omap->usbhost_ick);
+		omap->usbhost_ick = NULL;
 	}
 
-	if (ehci_clocks->usbhost1_48m_fck_clk != NULL) {
-		clk_disable(ehci_clocks->usbhost1_48m_fck_clk);
-		clk_put(ehci_clocks->usbhost1_48m_fck_clk);
-		ehci_clocks->usbhost1_48m_fck_clk = NULL;
+	if (omap->usbhost1_48m_fck != NULL) {
+		clk_disable(omap->usbhost1_48m_fck);
+		clk_put(omap->usbhost1_48m_fck);
+		omap->usbhost1_48m_fck = NULL;
 	}
 
-	if (ehci_clocks->usbhost2_120m_fck_clk != NULL) {
-		clk_disable(ehci_clocks->usbhost2_120m_fck_clk);
-		clk_put(ehci_clocks->usbhost2_120m_fck_clk);
-		ehci_clocks->usbhost2_120m_fck_clk = NULL;
+	if (omap->usbhost2_120m_fck != NULL) {
+		clk_disable(omap->usbhost2_120m_fck);
+		clk_put(omap->usbhost2_120m_fck);
+		omap->usbhost2_120m_fck = NULL;
 	}
 
-	if (ehci_clocks->usbtll_ick_clk != NULL) {
-		clk_disable(ehci_clocks->usbtll_ick_clk);
-		clk_put(ehci_clocks->usbtll_ick_clk);
-		ehci_clocks->usbtll_ick_clk = NULL;
+	if (omap->usbtll_ick != NULL) {
+		clk_disable(omap->usbtll_ick);
+		clk_put(omap->usbtll_ick);
+		omap->usbtll_ick = NULL;
 	}
 
-#ifdef EXTERNAL_PHY_RESET
-	gpio_free(EXT_PHY_RESET_GPIO_PORT1);
-	gpio_free(EXT_PHY_RESET_GPIO_PORT2);
-#endif
+	if (omap->phy_reset) {
+		gpio_free(omap->reset_gpio_port1);
+		gpio_free(omap->reset_gpio_port2);
+	}
 
 	dev_dbg(hcd->self.controller,
 		"Clock to USB host has been disabled\n");
@@ -630,16 +609,28 @@  static const struct hc_driver ehci_omap_hc_driver;
  */
 static int ehci_hcd_omap_probe(struct platform_device *pdev)
 {
-	struct ehci_hcd *ehci;
+	struct ehci_hcd_omap_platform_data *pdata = pdev->dev.platform_data;
+	struct ehci_hcd_omap *omap;
 	struct resource *res;
 	struct usb_hcd *hcd;
 
 	int irq = platform_get_irq(pdev, 0);
 	int ret = -ENODEV;
 
+	if (!pdata) {
+		dev_dbg(&pdev->dev, "missing platform_data\n");
+		goto err_pdata;
+	}
+
 	if (usb_disabled())
 		goto err_disabled;
 
+	omap = kzalloc(sizeof(*omap), GFP_KERNEL);
+	if (!omap) {
+		ret = -ENOMEM;
+		goto err_create_hcd;
+	}
+
 	hcd = usb_create_hcd(&ehci_omap_hc_driver, &pdev->dev,
 			dev_name(&pdev->dev));
 	if (!hcd) {
@@ -648,7 +639,17 @@  static int ehci_hcd_omap_probe(struct platform_device *pdev)
 		goto err_create_hcd;
 	}
 
-	ret = omap_start_ehc(pdev, hcd);
+	platform_set_drvdata(pdev, omap);
+	omap->dev		= &pdev->dev;
+	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->ehci		= hcd_to_ehci(hcd);
+	omap->ehci->caps	= hcd->regs;
+	omap->ehci->sbrn	= 0x20;
+
+	ret = omap_start_ehc(omap, hcd);
 	if (ret) {
 		dev_dbg(&pdev->dev, "failed to start ehci\n");
 		goto err_start;
@@ -668,16 +669,15 @@  static int ehci_hcd_omap_probe(struct platform_device *pdev)
 		goto err_ioremap;
 	}
 
-	ehci = hcd_to_ehci(hcd);
-	ehci->caps = hcd->regs;
-	ehci->sbrn = 0x20;
+	omap->ehci->regs = hcd->regs
+		+ HC_LENGTH(readl(&omap->ehci->caps->hc_capbase));
 
-	ehci->regs = hcd->regs + HC_LENGTH(readl(&ehci->caps->hc_capbase));
 	/* cache this readonly data; minimize chip reads */
-	ehci->hcs_params = readl(&ehci->caps->hcs_params);
+	omap->ehci->hcs_params = readl(&omap->ehci->caps->hcs_params);
 
 	/* SET 1 micro-frame Interrupt interval */
-	writel(readl(&ehci->regs->command) | (1 << 16), &ehci->regs->command);
+	writel(readl(&omap->ehci->regs->command) | (1 << 16),
+			&omap->ehci->regs->command);
 
 	ret = usb_add_hcd(hcd, irq, IRQF_DISABLED | IRQF_SHARED);
 	if (ret) {
@@ -691,13 +691,14 @@  err_add_hcd:
 	iounmap(hcd->regs);
 
 err_ioremap:
-	omap_stop_ehc(pdev, hcd);
+	omap_stop_ehc(omap, hcd);
 
 err_start:
 	usb_put_hcd(hcd);
 
 err_create_hcd:
 err_disabled:
+err_pdata:
 	return ret;
 }
 
@@ -714,11 +715,12 @@  err_disabled:
  */
 static int ehci_hcd_omap_remove(struct platform_device *pdev)
 {
-	struct usb_hcd *hcd = platform_get_drvdata(pdev);
+	struct ehci_hcd_omap *omap = platform_get_drvdata(pdev);
+	struct usb_hcd *hcd = ehci_to_hcd(omap->ehci);
 
 	usb_remove_hcd(hcd);
 	iounmap(hcd->regs);
-	omap_stop_ehc(pdev, hcd);
+	omap_stop_ehc(omap, hcd);
 	usb_put_hcd(hcd);
 
 	return 0;
@@ -738,10 +740,9 @@  static struct platform_driver ehci_hcd_omap_driver = {
 /*-------------------------------------------------------------------------*/
 
 static const struct hc_driver ehci_omap_hc_driver = {
-	.description = hcd_name,
+	.description		= hcd_name,
 	.product_desc		= "OMAP-EHCI Host Controller",
-	.hcd_priv_size		= sizeof(struct ehci_hcd)
-				+ sizeof(struct ehci_omap_clock_defs),
+	.hcd_priv_size		= sizeof(struct ehci_hcd_omap),
 
 	/*
 	 * generic hardware linkage