ehci-omap.c revision a42ccdc14de388a35ad0e8057543369351395eb9
154ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi/*
254ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi * ehci-omap.c - driver for USBHOST on OMAP 34xx processor
354ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi *
454ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi * Bus Glue for OMAP34xx USBHOST 3 port EHCI controller
554ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi * Tested on OMAP3430 ES2.0 SDP
654ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi *
754ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi * Copyright (C) 2007-2008 Texas Instruments, Inc.
854ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi *	Author: Vikram Pandita <vikram.pandita@ti.com>
954ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi *
1054ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi * Copyright (C) 2009 Nokia Corporation
1154ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi *	Contact: Felipe Balbi <felipe.balbi@nokia.com>
1254ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi *
1354ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi * Based on "ehci-fsl.c" and "ehci-au1xxx.c" ehci glue layers
1454ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi *
1554ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi * This program is free software; you can redistribute it and/or modify
1654ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi * it under the terms of the GNU General Public License as published by
1754ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi * the Free Software Foundation; either version 2 of the License, or
1854ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi * (at your option) any later version.
1954ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi *
2054ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi * This program is distributed in the hope that it will be useful,
2154ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi * but WITHOUT ANY WARRANTY; without even the implied warranty of
2254ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
2354ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi * GNU General Public License for more details.
2454ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi *
2554ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi * You should have received a copy of the GNU General Public License
2654ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi * along with this program; if not, write to the Free Software
2754ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
2854ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi *
29bdee2d8432f5af5af953896182a59ec1c5d6fa3aAnand Gadiyar * TODO (last updated Feb 12, 2010):
3054ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi *	- add kernel-doc
3154ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi *	- enable AUTOIDLE
3254ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi *	- add suspend/resume
3354ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi *	- move workarounds to board-files
3454ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi */
3554ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi
3654ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi#include <linux/platform_device.h>
3754ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi#include <linux/clk.h>
3854ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi#include <linux/gpio.h>
39881142660697bba0f3ef44f070d80632082c978fAjay Kumar Gupta#include <linux/regulator/consumer.h>
405a0e3ad6af8660be21ca98a971cd00f331318c05Tejun Heo#include <linux/slab.h>
415aa4af2ce6a0643f32d47f21614817792b85298dAjay Kumar Gupta#include <linux/usb/ulpi.h>
42c76f782cb3cfffc1fd4233e11f3116655fa0fcd2Thomas Weber#include <plat/usb.h>
4354ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi
4454ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi/*
4554ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi * OMAP USBHOST Register addresses: VIRTUAL ADDRESSES
4654ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi *	Use ehci_omap_readl()/ehci_omap_writel() functions
4754ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi */
4854ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi
4954ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi/* TLL Register Set */
5054ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi#define	OMAP_USBTLL_REVISION				(0x00)
5154ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi#define	OMAP_USBTLL_SYSCONFIG				(0x10)
5254ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi#define	OMAP_USBTLL_SYSCONFIG_CACTIVITY			(1 << 8)
5354ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi#define	OMAP_USBTLL_SYSCONFIG_SIDLEMODE			(1 << 3)
5454ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi#define	OMAP_USBTLL_SYSCONFIG_ENAWAKEUP			(1 << 2)
5554ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi#define	OMAP_USBTLL_SYSCONFIG_SOFTRESET			(1 << 1)
5654ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi#define	OMAP_USBTLL_SYSCONFIG_AUTOIDLE			(1 << 0)
5754ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi
5854ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi#define	OMAP_USBTLL_SYSSTATUS				(0x14)
5954ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi#define	OMAP_USBTLL_SYSSTATUS_RESETDONE			(1 << 0)
6054ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi
6154ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi#define	OMAP_USBTLL_IRQSTATUS				(0x18)
6254ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi#define	OMAP_USBTLL_IRQENABLE				(0x1C)
6354ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi
6454ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi#define	OMAP_TLL_SHARED_CONF				(0x30)
6554ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi#define	OMAP_TLL_SHARED_CONF_USB_90D_DDR_EN		(1 << 6)
6654ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi#define	OMAP_TLL_SHARED_CONF_USB_180D_SDR_EN		(1 << 5)
6754ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi#define	OMAP_TLL_SHARED_CONF_USB_DIVRATION		(1 << 2)
6854ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi#define	OMAP_TLL_SHARED_CONF_FCLK_REQ			(1 << 1)
6954ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi#define	OMAP_TLL_SHARED_CONF_FCLK_IS_ON			(1 << 0)
7054ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi
7154ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi#define	OMAP_TLL_CHANNEL_CONF(num)			(0x040 + 0x004 * num)
7254ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi#define	OMAP_TLL_CHANNEL_CONF_ULPINOBITSTUFF		(1 << 11)
7354ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi#define	OMAP_TLL_CHANNEL_CONF_ULPI_ULPIAUTOIDLE		(1 << 10)
7454ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi#define	OMAP_TLL_CHANNEL_CONF_UTMIAUTOIDLE		(1 << 9)
7554ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi#define	OMAP_TLL_CHANNEL_CONF_ULPIDDRMODE		(1 << 8)
7654ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi#define	OMAP_TLL_CHANNEL_CONF_CHANEN			(1 << 0)
7754ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi
7854ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi#define	OMAP_TLL_ULPI_FUNCTION_CTRL(num)		(0x804 + 0x100 * num)
7954ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi#define	OMAP_TLL_ULPI_INTERFACE_CTRL(num)		(0x807 + 0x100 * num)
8054ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi#define	OMAP_TLL_ULPI_OTG_CTRL(num)			(0x80A + 0x100 * num)
8154ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi#define	OMAP_TLL_ULPI_INT_EN_RISE(num)			(0x80D + 0x100 * num)
8254ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi#define	OMAP_TLL_ULPI_INT_EN_FALL(num)			(0x810 + 0x100 * num)
8354ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi#define	OMAP_TLL_ULPI_INT_STATUS(num)			(0x813 + 0x100 * num)
8454ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi#define	OMAP_TLL_ULPI_INT_LATCH(num)			(0x814 + 0x100 * num)
8554ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi#define	OMAP_TLL_ULPI_DEBUG(num)			(0x815 + 0x100 * num)
8654ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi#define	OMAP_TLL_ULPI_SCRATCH_REGISTER(num)		(0x816 + 0x100 * num)
8754ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi
8854ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi#define OMAP_TLL_CHANNEL_COUNT				3
8954ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi#define OMAP_TLL_CHANNEL_1_EN_MASK			(1 << 1)
9054ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi#define OMAP_TLL_CHANNEL_2_EN_MASK			(1 << 2)
9154ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi#define OMAP_TLL_CHANNEL_3_EN_MASK			(1 << 4)
9254ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi
9354ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi/* UHH Register Set */
9454ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi#define	OMAP_UHH_REVISION				(0x00)
9554ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi#define	OMAP_UHH_SYSCONFIG				(0x10)
9654ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi#define	OMAP_UHH_SYSCONFIG_MIDLEMODE			(1 << 12)
9754ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi#define	OMAP_UHH_SYSCONFIG_CACTIVITY			(1 << 8)
9854ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi#define	OMAP_UHH_SYSCONFIG_SIDLEMODE			(1 << 3)
9954ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi#define	OMAP_UHH_SYSCONFIG_ENAWAKEUP			(1 << 2)
10054ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi#define	OMAP_UHH_SYSCONFIG_SOFTRESET			(1 << 1)
10154ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi#define	OMAP_UHH_SYSCONFIG_AUTOIDLE			(1 << 0)
10254ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi
10354ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi#define	OMAP_UHH_SYSSTATUS				(0x14)
10454ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi#define	OMAP_UHH_HOSTCONFIG				(0x40)
10554ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi#define	OMAP_UHH_HOSTCONFIG_ULPI_BYPASS			(1 << 0)
10654ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi#define	OMAP_UHH_HOSTCONFIG_ULPI_P1_BYPASS		(1 << 0)
10754ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi#define	OMAP_UHH_HOSTCONFIG_ULPI_P2_BYPASS		(1 << 11)
10854ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi#define	OMAP_UHH_HOSTCONFIG_ULPI_P3_BYPASS		(1 << 12)
10954ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi#define OMAP_UHH_HOSTCONFIG_INCR4_BURST_EN		(1 << 2)
11054ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi#define OMAP_UHH_HOSTCONFIG_INCR8_BURST_EN		(1 << 3)
11154ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi#define OMAP_UHH_HOSTCONFIG_INCR16_BURST_EN		(1 << 4)
11254ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi#define OMAP_UHH_HOSTCONFIG_INCRX_ALIGN_EN		(1 << 5)
11354ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi#define OMAP_UHH_HOSTCONFIG_P1_CONNECT_STATUS		(1 << 8)
11454ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi#define OMAP_UHH_HOSTCONFIG_P2_CONNECT_STATUS		(1 << 9)
11554ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi#define OMAP_UHH_HOSTCONFIG_P3_CONNECT_STATUS		(1 << 10)
11654ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi
11754ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi#define	OMAP_UHH_DEBUG_CSR				(0x44)
11854ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi
11954ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi/* EHCI Register Set */
120572538dee7a4b25f3e77fdc11d20dbb753ecf367Anand Gadiyar#define EHCI_INSNREG04					(0xA0)
121572538dee7a4b25f3e77fdc11d20dbb753ecf367Anand Gadiyar#define EHCI_INSNREG04_DISABLE_UNSUSPEND		(1 << 5)
12254ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi#define	EHCI_INSNREG05_ULPI				(0xA4)
12354ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi#define	EHCI_INSNREG05_ULPI_CONTROL_SHIFT		31
12454ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi#define	EHCI_INSNREG05_ULPI_PORTSEL_SHIFT		24
12554ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi#define	EHCI_INSNREG05_ULPI_OPSEL_SHIFT			22
12654ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi#define	EHCI_INSNREG05_ULPI_REGADD_SHIFT		16
12754ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi#define	EHCI_INSNREG05_ULPI_EXTREGADD_SHIFT		8
12854ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi#define	EHCI_INSNREG05_ULPI_WRDATA_SHIFT		0
12954ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi
130a42ccdc14de388a35ad0e8057543369351395eb9Anand Gadiyar#define is_ehci_phy_mode(x)	(x == EHCI_HCD_OMAP_MODE_PHY)
131a42ccdc14de388a35ad0e8057543369351395eb9Anand Gadiyar#define is_ehci_tll_mode(x)	(x == EHCI_HCD_OMAP_MODE_TLL)
132a42ccdc14de388a35ad0e8057543369351395eb9Anand Gadiyar
13354ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi/*-------------------------------------------------------------------------*/
13454ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi
13554ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbistatic inline void ehci_omap_writel(void __iomem *base, u32 reg, u32 val)
13654ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi{
13754ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi	__raw_writel(val, base + reg);
13854ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi}
13954ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi
14054ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbistatic inline u32 ehci_omap_readl(void __iomem *base, u32 reg)
14154ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi{
14254ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi	return __raw_readl(base + reg);
14354ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi}
14454ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi
14554ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbistatic inline void ehci_omap_writeb(void __iomem *base, u8 reg, u8 val)
14654ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi{
14754ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi	__raw_writeb(val, base + reg);
14854ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi}
14954ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi
15054ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbistatic inline u8 ehci_omap_readb(void __iomem *base, u8 reg)
15154ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi{
15254ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi	return __raw_readb(base + reg);
15354ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi}
15454ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi
15554ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi/*-------------------------------------------------------------------------*/
15654ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi
15754ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbistruct ehci_hcd_omap {
15854ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi	struct ehci_hcd		*ehci;
15954ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi	struct device		*dev;
16054ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi
16154ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi	struct clk		*usbhost_ick;
1626dba39e278b81665a838f37a75fe37b89f3ce610Keshava Munegowda	struct clk		*usbhost_hs_fck;
1636dba39e278b81665a838f37a75fe37b89f3ce610Keshava Munegowda	struct clk		*usbhost_fs_fck;
16454ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi	struct clk		*usbtll_fck;
16554ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi	struct clk		*usbtll_ick;
16654ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi
16754ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi	/* FIXME the following two workarounds are
16854ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi	 * board specific not silicon-specific so these
16954ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi	 * should be moved to board-file instead.
17054ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi	 *
17154ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi	 * Maybe someone from TI will know better which
17254ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi	 * board is affected and needs the workarounds
17354ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi	 * to be applied
17454ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi	 */
17554ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi
17654ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi	/* gpio for resetting phy */
17754ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi	int			reset_gpio_port[OMAP3_HS_USB_PORTS];
17854ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi
17954ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi	/* phy reset workaround */
18054ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi	int			phy_reset;
18154ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi
18254ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi	/* desired phy_mode: TLL, PHY */
18354ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi	enum ehci_hcd_omap_mode	port_mode[OMAP3_HS_USB_PORTS];
18454ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi
18554ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi	void __iomem		*uhh_base;
18654ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi	void __iomem		*tll_base;
18754ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi	void __iomem		*ehci_base;
188881142660697bba0f3ef44f070d80632082c978fAjay Kumar Gupta
189881142660697bba0f3ef44f070d80632082c978fAjay Kumar Gupta	/* Regulators for USB PHYs.
190a8cd4561ea176f51e9f4707873ca4eff8fd5ee70Anand Gadiyar	 * Each PHY can have a separate regulator.
191881142660697bba0f3ef44f070d80632082c978fAjay Kumar Gupta	 */
192881142660697bba0f3ef44f070d80632082c978fAjay Kumar Gupta	struct regulator        *regulator[OMAP3_HS_USB_PORTS];
19354ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi};
19454ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi
19554ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi/*-------------------------------------------------------------------------*/
19654ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi
197c072604115ab50d023eb5c33d4f3229400e441f4Keshava Munegowdastatic void omap_usb_utmi_init(struct ehci_hcd_omap *omap, u8 tll_channel_mask,
198c072604115ab50d023eb5c33d4f3229400e441f4Keshava Munegowda				u8 tll_channel_count)
19954ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi{
20054ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi	unsigned reg;
20154ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi	int i;
20254ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi
20354ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi	/* Program the 3 TLL channels upfront */
204c072604115ab50d023eb5c33d4f3229400e441f4Keshava Munegowda	for (i = 0; i < tll_channel_count; i++) {
20554ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi		reg = ehci_omap_readl(omap->tll_base, OMAP_TLL_CHANNEL_CONF(i));
20654ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi
20754ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi		/* Disable AutoIdle, BitStuffing and use SDR Mode */
20854ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi		reg &= ~(OMAP_TLL_CHANNEL_CONF_UTMIAUTOIDLE
20954ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi				| OMAP_TLL_CHANNEL_CONF_ULPINOBITSTUFF
21054ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi				| OMAP_TLL_CHANNEL_CONF_ULPIDDRMODE);
21154ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi		ehci_omap_writel(omap->tll_base, OMAP_TLL_CHANNEL_CONF(i), reg);
21254ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi	}
21354ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi
21454ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi	/* Program Common TLL register */
21554ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi	reg = ehci_omap_readl(omap->tll_base, OMAP_TLL_SHARED_CONF);
21654ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi	reg |= (OMAP_TLL_SHARED_CONF_FCLK_IS_ON
21754ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi			| OMAP_TLL_SHARED_CONF_USB_DIVRATION
21854ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi			| OMAP_TLL_SHARED_CONF_USB_180D_SDR_EN);
21954ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi	reg &= ~OMAP_TLL_SHARED_CONF_USB_90D_DDR_EN;
22054ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi
22154ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi	ehci_omap_writel(omap->tll_base, OMAP_TLL_SHARED_CONF, reg);
22254ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi
22354ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi	/* Enable channels now */
224c072604115ab50d023eb5c33d4f3229400e441f4Keshava Munegowda	for (i = 0; i < tll_channel_count; i++) {
22554ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi		reg = ehci_omap_readl(omap->tll_base, OMAP_TLL_CHANNEL_CONF(i));
22654ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi
22754ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi		/* Enable only the reg that is needed */
22854ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi		if (!(tll_channel_mask & 1<<i))
22954ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi			continue;
23054ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi
23154ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi		reg |= OMAP_TLL_CHANNEL_CONF_CHANEN;
23254ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi		ehci_omap_writel(omap->tll_base, OMAP_TLL_CHANNEL_CONF(i), reg);
23354ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi
23454ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi		ehci_omap_writeb(omap->tll_base,
23554ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi				OMAP_TLL_ULPI_SCRATCH_REGISTER(i), 0xbe);
23654ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi		dev_dbg(omap->dev, "ULPI_SCRATCH_REG[ch=%d]= 0x%02x\n",
23754ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi				i+1, ehci_omap_readb(omap->tll_base,
23854ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi				OMAP_TLL_ULPI_SCRATCH_REGISTER(i)));
23954ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi	}
24054ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi}
24154ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi
24254ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi/*-------------------------------------------------------------------------*/
24354ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi
2445aa4af2ce6a0643f32d47f21614817792b85298dAjay Kumar Guptastatic void omap_ehci_soft_phy_reset(struct ehci_hcd_omap *omap, u8 port)
2455aa4af2ce6a0643f32d47f21614817792b85298dAjay Kumar Gupta{
2465aa4af2ce6a0643f32d47f21614817792b85298dAjay Kumar Gupta	unsigned long timeout = jiffies + msecs_to_jiffies(1000);
2475aa4af2ce6a0643f32d47f21614817792b85298dAjay Kumar Gupta	unsigned reg = 0;
2485aa4af2ce6a0643f32d47f21614817792b85298dAjay Kumar Gupta
2495aa4af2ce6a0643f32d47f21614817792b85298dAjay Kumar Gupta	reg = ULPI_FUNC_CTRL_RESET
2505aa4af2ce6a0643f32d47f21614817792b85298dAjay Kumar Gupta		/* FUNCTION_CTRL_SET register */
2515aa4af2ce6a0643f32d47f21614817792b85298dAjay Kumar Gupta		| (ULPI_SET(ULPI_FUNC_CTRL) << EHCI_INSNREG05_ULPI_REGADD_SHIFT)
2525aa4af2ce6a0643f32d47f21614817792b85298dAjay Kumar Gupta		/* Write */
2535aa4af2ce6a0643f32d47f21614817792b85298dAjay Kumar Gupta		| (2 << EHCI_INSNREG05_ULPI_OPSEL_SHIFT)
2545aa4af2ce6a0643f32d47f21614817792b85298dAjay Kumar Gupta		/* PORTn */
2555aa4af2ce6a0643f32d47f21614817792b85298dAjay Kumar Gupta		| ((port + 1) << EHCI_INSNREG05_ULPI_PORTSEL_SHIFT)
2565aa4af2ce6a0643f32d47f21614817792b85298dAjay Kumar Gupta		/* start ULPI access*/
2575aa4af2ce6a0643f32d47f21614817792b85298dAjay Kumar Gupta		| (1 << EHCI_INSNREG05_ULPI_CONTROL_SHIFT);
2585aa4af2ce6a0643f32d47f21614817792b85298dAjay Kumar Gupta
2595aa4af2ce6a0643f32d47f21614817792b85298dAjay Kumar Gupta	ehci_omap_writel(omap->ehci_base, EHCI_INSNREG05_ULPI, reg);
2605aa4af2ce6a0643f32d47f21614817792b85298dAjay Kumar Gupta
2615aa4af2ce6a0643f32d47f21614817792b85298dAjay Kumar Gupta	/* Wait for ULPI access completion */
2625aa4af2ce6a0643f32d47f21614817792b85298dAjay Kumar Gupta	while ((ehci_omap_readl(omap->ehci_base, EHCI_INSNREG05_ULPI)
2635aa4af2ce6a0643f32d47f21614817792b85298dAjay Kumar Gupta			& (1 << EHCI_INSNREG05_ULPI_CONTROL_SHIFT))) {
2645aa4af2ce6a0643f32d47f21614817792b85298dAjay Kumar Gupta		cpu_relax();
2655aa4af2ce6a0643f32d47f21614817792b85298dAjay Kumar Gupta
2665aa4af2ce6a0643f32d47f21614817792b85298dAjay Kumar Gupta		if (time_after(jiffies, timeout)) {
2675aa4af2ce6a0643f32d47f21614817792b85298dAjay Kumar Gupta			dev_dbg(omap->dev, "phy reset operation timed out\n");
2685aa4af2ce6a0643f32d47f21614817792b85298dAjay Kumar Gupta			break;
2695aa4af2ce6a0643f32d47f21614817792b85298dAjay Kumar Gupta		}
2705aa4af2ce6a0643f32d47f21614817792b85298dAjay Kumar Gupta	}
2715aa4af2ce6a0643f32d47f21614817792b85298dAjay Kumar Gupta}
2725aa4af2ce6a0643f32d47f21614817792b85298dAjay Kumar Gupta
27354ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi/* omap_start_ehc
27454ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi *	- Start the TI USBHOST controller
27554ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi */
27654ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbistatic int omap_start_ehc(struct ehci_hcd_omap *omap, struct usb_hcd *hcd)
27754ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi{
27854ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi	unsigned long timeout = jiffies + msecs_to_jiffies(1000);
27954ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi	u8 tll_ch_mask = 0;
28054ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi	unsigned reg = 0;
28154ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi	int ret = 0;
28254ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi
28354ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi	dev_dbg(omap->dev, "starting TI EHCI USB Controller\n");
28454ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi
28554ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi	/* Enable Clocks for USBHOST */
28654ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi	omap->usbhost_ick = clk_get(omap->dev, "usbhost_ick");
28754ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi	if (IS_ERR(omap->usbhost_ick)) {
28854ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi		ret =  PTR_ERR(omap->usbhost_ick);
28954ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi		goto err_host_ick;
29054ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi	}
29154ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi	clk_enable(omap->usbhost_ick);
29254ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi
293c5dff5545c97ab33bdb2a529a2375966ceb0700cAnand Gadiyar	omap->usbhost_hs_fck = clk_get(omap->dev, "hs_fck");
2946dba39e278b81665a838f37a75fe37b89f3ce610Keshava Munegowda	if (IS_ERR(omap->usbhost_hs_fck)) {
2956dba39e278b81665a838f37a75fe37b89f3ce610Keshava Munegowda		ret = PTR_ERR(omap->usbhost_hs_fck);
29654ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi		goto err_host_120m_fck;
29754ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi	}
2986dba39e278b81665a838f37a75fe37b89f3ce610Keshava Munegowda	clk_enable(omap->usbhost_hs_fck);
29954ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi
300c5dff5545c97ab33bdb2a529a2375966ceb0700cAnand Gadiyar	omap->usbhost_fs_fck = clk_get(omap->dev, "fs_fck");
3016dba39e278b81665a838f37a75fe37b89f3ce610Keshava Munegowda	if (IS_ERR(omap->usbhost_fs_fck)) {
3026dba39e278b81665a838f37a75fe37b89f3ce610Keshava Munegowda		ret = PTR_ERR(omap->usbhost_fs_fck);
30354ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi		goto err_host_48m_fck;
30454ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi	}
3056dba39e278b81665a838f37a75fe37b89f3ce610Keshava Munegowda	clk_enable(omap->usbhost_fs_fck);
30654ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi
30754ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi	if (omap->phy_reset) {
30854ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi		/* Refer: ISSUE1 */
30954ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi		if (gpio_is_valid(omap->reset_gpio_port[0])) {
31054ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi			gpio_request(omap->reset_gpio_port[0],
31154ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi						"USB1 PHY reset");
31254ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi			gpio_direction_output(omap->reset_gpio_port[0], 0);
31354ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi		}
31454ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi
31554ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi		if (gpio_is_valid(omap->reset_gpio_port[1])) {
31654ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi			gpio_request(omap->reset_gpio_port[1],
31754ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi						"USB2 PHY reset");
31854ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi			gpio_direction_output(omap->reset_gpio_port[1], 0);
31954ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi		}
32054ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi
32154ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi		/* Hold the PHY in RESET for enough time till DIR is high */
32254ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi		udelay(10);
32354ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi	}
32454ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi
32554ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi	/* Configure TLL for 60Mhz clk for ULPI */
32654ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi	omap->usbtll_fck = clk_get(omap->dev, "usbtll_fck");
32754ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi	if (IS_ERR(omap->usbtll_fck)) {
32854ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi		ret = PTR_ERR(omap->usbtll_fck);
32954ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi		goto err_tll_fck;
33054ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi	}
33154ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi	clk_enable(omap->usbtll_fck);
33254ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi
33354ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi	omap->usbtll_ick = clk_get(omap->dev, "usbtll_ick");
33454ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi	if (IS_ERR(omap->usbtll_ick)) {
33554ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi		ret = PTR_ERR(omap->usbtll_ick);
33654ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi		goto err_tll_ick;
33754ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi	}
33854ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi	clk_enable(omap->usbtll_ick);
33954ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi
34054ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi	/* perform TLL soft reset, and wait until reset is complete */
34154ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi	ehci_omap_writel(omap->tll_base, OMAP_USBTLL_SYSCONFIG,
34254ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi			OMAP_USBTLL_SYSCONFIG_SOFTRESET);
34354ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi
34454ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi	/* Wait for TLL reset to complete */
34554ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi	while (!(ehci_omap_readl(omap->tll_base, OMAP_USBTLL_SYSSTATUS)
34654ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi			& OMAP_USBTLL_SYSSTATUS_RESETDONE)) {
34754ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi		cpu_relax();
34854ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi
34954ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi		if (time_after(jiffies, timeout)) {
35054ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi			dev_dbg(omap->dev, "operation timed out\n");
35154ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi			ret = -EINVAL;
35254ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi			goto err_sys_status;
35354ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi		}
35454ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi	}
35554ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi
35654ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi	dev_dbg(omap->dev, "TLL RESET DONE\n");
35754ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi
35854ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi	/* (1<<3) = no idle mode only for initial debugging */
35954ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi	ehci_omap_writel(omap->tll_base, OMAP_USBTLL_SYSCONFIG,
36054ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi			OMAP_USBTLL_SYSCONFIG_ENAWAKEUP |
36154ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi			OMAP_USBTLL_SYSCONFIG_SIDLEMODE |
36254ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi			OMAP_USBTLL_SYSCONFIG_CACTIVITY);
36354ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi
36454ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi
36554ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi	/* Put UHH in NoIdle/NoStandby mode */
36654ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi	reg = ehci_omap_readl(omap->uhh_base, OMAP_UHH_SYSCONFIG);
36754ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi	reg |= (OMAP_UHH_SYSCONFIG_ENAWAKEUP
36854ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi			| OMAP_UHH_SYSCONFIG_SIDLEMODE
36954ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi			| OMAP_UHH_SYSCONFIG_CACTIVITY
37054ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi			| OMAP_UHH_SYSCONFIG_MIDLEMODE);
37154ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi	reg &= ~OMAP_UHH_SYSCONFIG_AUTOIDLE;
37254ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi
37354ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi	ehci_omap_writel(omap->uhh_base, OMAP_UHH_SYSCONFIG, reg);
37454ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi
37554ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi	reg = ehci_omap_readl(omap->uhh_base, OMAP_UHH_HOSTCONFIG);
37654ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi
37754ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi	/* setup ULPI bypass and burst configurations */
37854ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi	reg |= (OMAP_UHH_HOSTCONFIG_INCR4_BURST_EN
37954ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi			| OMAP_UHH_HOSTCONFIG_INCR8_BURST_EN
38054ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi			| OMAP_UHH_HOSTCONFIG_INCR16_BURST_EN);
38154ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi	reg &= ~OMAP_UHH_HOSTCONFIG_INCRX_ALIGN_EN;
38254ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi
38354ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi	if (omap->port_mode[0] == EHCI_HCD_OMAP_MODE_UNKNOWN)
38454ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi		reg &= ~OMAP_UHH_HOSTCONFIG_P1_CONNECT_STATUS;
38554ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi	if (omap->port_mode[1] == EHCI_HCD_OMAP_MODE_UNKNOWN)
38654ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi		reg &= ~OMAP_UHH_HOSTCONFIG_P2_CONNECT_STATUS;
38754ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi	if (omap->port_mode[2] == EHCI_HCD_OMAP_MODE_UNKNOWN)
38854ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi		reg &= ~OMAP_UHH_HOSTCONFIG_P3_CONNECT_STATUS;
38954ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi
39054ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi	/* Bypass the TLL module for PHY mode operation */
39197dc7c61f1a25e906c0eb65fac2573e1ce063d63Ajay Kumar Gupta	if (cpu_is_omap3430() && (omap_rev() <= OMAP3430_REV_ES2_1)) {
39297dc7c61f1a25e906c0eb65fac2573e1ce063d63Ajay Kumar Gupta		dev_dbg(omap->dev, "OMAP3 ES version <= ES2.1\n");
393a42ccdc14de388a35ad0e8057543369351395eb9Anand Gadiyar		if (is_ehci_phy_mode(omap->port_mode[0]) ||
394a42ccdc14de388a35ad0e8057543369351395eb9Anand Gadiyar			is_ehci_phy_mode(omap->port_mode[1]) ||
395a42ccdc14de388a35ad0e8057543369351395eb9Anand Gadiyar				is_ehci_phy_mode(omap->port_mode[2]))
39654ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi			reg &= ~OMAP_UHH_HOSTCONFIG_ULPI_BYPASS;
39754ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi		else
39854ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi			reg |= OMAP_UHH_HOSTCONFIG_ULPI_BYPASS;
39954ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi	} else {
40054ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi		dev_dbg(omap->dev, "OMAP3 ES version > ES2.1\n");
401a42ccdc14de388a35ad0e8057543369351395eb9Anand Gadiyar		if (is_ehci_phy_mode(omap->port_mode[0]))
40254ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi			reg &= ~OMAP_UHH_HOSTCONFIG_ULPI_P1_BYPASS;
403a42ccdc14de388a35ad0e8057543369351395eb9Anand Gadiyar		else if (is_ehci_tll_mode(omap->port_mode[0]))
40454ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi			reg |= OMAP_UHH_HOSTCONFIG_ULPI_P1_BYPASS;
40554ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi
406a42ccdc14de388a35ad0e8057543369351395eb9Anand Gadiyar		if (is_ehci_phy_mode(omap->port_mode[1]))
40754ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi			reg &= ~OMAP_UHH_HOSTCONFIG_ULPI_P2_BYPASS;
408a42ccdc14de388a35ad0e8057543369351395eb9Anand Gadiyar		else if (is_ehci_tll_mode(omap->port_mode[1]))
40954ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi			reg |= OMAP_UHH_HOSTCONFIG_ULPI_P2_BYPASS;
41054ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi
411a42ccdc14de388a35ad0e8057543369351395eb9Anand Gadiyar		if (is_ehci_phy_mode(omap->port_mode[2]))
41254ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi			reg &= ~OMAP_UHH_HOSTCONFIG_ULPI_P3_BYPASS;
413a42ccdc14de388a35ad0e8057543369351395eb9Anand Gadiyar		else if (is_ehci_tll_mode(omap->port_mode[2]))
41454ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi			reg |= OMAP_UHH_HOSTCONFIG_ULPI_P3_BYPASS;
41554ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi
41654ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi	}
41754ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi	ehci_omap_writel(omap->uhh_base, OMAP_UHH_HOSTCONFIG, reg);
41854ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi	dev_dbg(omap->dev, "UHH setup done, uhh_hostconfig=%x\n", reg);
41954ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi
42054ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi
421572538dee7a4b25f3e77fdc11d20dbb753ecf367Anand Gadiyar	/*
422572538dee7a4b25f3e77fdc11d20dbb753ecf367Anand Gadiyar	 * An undocumented "feature" in the OMAP3 EHCI controller,
423572538dee7a4b25f3e77fdc11d20dbb753ecf367Anand Gadiyar	 * causes suspended ports to be taken out of suspend when
424572538dee7a4b25f3e77fdc11d20dbb753ecf367Anand Gadiyar	 * the USBCMD.Run/Stop bit is cleared (for example when
425572538dee7a4b25f3e77fdc11d20dbb753ecf367Anand Gadiyar	 * we do ehci_bus_suspend).
426572538dee7a4b25f3e77fdc11d20dbb753ecf367Anand Gadiyar	 * This breaks suspend-resume if the root-hub is allowed
427572538dee7a4b25f3e77fdc11d20dbb753ecf367Anand Gadiyar	 * to suspend. Writing 1 to this undocumented register bit
428572538dee7a4b25f3e77fdc11d20dbb753ecf367Anand Gadiyar	 * disables this feature and restores normal behavior.
429572538dee7a4b25f3e77fdc11d20dbb753ecf367Anand Gadiyar	 */
430572538dee7a4b25f3e77fdc11d20dbb753ecf367Anand Gadiyar	ehci_omap_writel(omap->ehci_base, EHCI_INSNREG04,
431572538dee7a4b25f3e77fdc11d20dbb753ecf367Anand Gadiyar				EHCI_INSNREG04_DISABLE_UNSUSPEND);
432572538dee7a4b25f3e77fdc11d20dbb753ecf367Anand Gadiyar
43354ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi	if ((omap->port_mode[0] == EHCI_HCD_OMAP_MODE_TLL) ||
43454ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi		(omap->port_mode[1] == EHCI_HCD_OMAP_MODE_TLL) ||
43554ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi			(omap->port_mode[2] == EHCI_HCD_OMAP_MODE_TLL)) {
43654ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi
43754ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi		if (omap->port_mode[0] == EHCI_HCD_OMAP_MODE_TLL)
43854ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi			tll_ch_mask |= OMAP_TLL_CHANNEL_1_EN_MASK;
43954ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi		if (omap->port_mode[1] == EHCI_HCD_OMAP_MODE_TLL)
44054ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi			tll_ch_mask |= OMAP_TLL_CHANNEL_2_EN_MASK;
44154ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi		if (omap->port_mode[2] == EHCI_HCD_OMAP_MODE_TLL)
44254ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi			tll_ch_mask |= OMAP_TLL_CHANNEL_3_EN_MASK;
44354ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi
44454ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi		/* Enable UTMI mode for required TLL channels */
445c072604115ab50d023eb5c33d4f3229400e441f4Keshava Munegowda		omap_usb_utmi_init(omap, tll_ch_mask, OMAP_TLL_CHANNEL_COUNT);
44654ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi	}
44754ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi
44854ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi	if (omap->phy_reset) {
44954ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi		/* Refer ISSUE1:
45054ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi		 * Hold the PHY in RESET for enough time till
45154ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi		 * PHY is settled and ready
45254ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi		 */
45354ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi		udelay(10);
45454ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi
45554ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi		if (gpio_is_valid(omap->reset_gpio_port[0]))
45654ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi			gpio_set_value(omap->reset_gpio_port[0], 1);
45754ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi
45854ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi		if (gpio_is_valid(omap->reset_gpio_port[1]))
45954ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi			gpio_set_value(omap->reset_gpio_port[1], 1);
46054ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi	}
46154ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi
4625aa4af2ce6a0643f32d47f21614817792b85298dAjay Kumar Gupta	/* Soft reset the PHY using PHY reset command over ULPI */
4635aa4af2ce6a0643f32d47f21614817792b85298dAjay Kumar Gupta	if (omap->port_mode[0] == EHCI_HCD_OMAP_MODE_PHY)
4645aa4af2ce6a0643f32d47f21614817792b85298dAjay Kumar Gupta		omap_ehci_soft_phy_reset(omap, 0);
4655aa4af2ce6a0643f32d47f21614817792b85298dAjay Kumar Gupta	if (omap->port_mode[1] == EHCI_HCD_OMAP_MODE_PHY)
4665aa4af2ce6a0643f32d47f21614817792b85298dAjay Kumar Gupta		omap_ehci_soft_phy_reset(omap, 1);
4675aa4af2ce6a0643f32d47f21614817792b85298dAjay Kumar Gupta
46854ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi	return 0;
46954ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi
47054ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbierr_sys_status:
47154ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi	clk_disable(omap->usbtll_ick);
47254ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi	clk_put(omap->usbtll_ick);
47354ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi
47454ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbierr_tll_ick:
47554ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi	clk_disable(omap->usbtll_fck);
47654ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi	clk_put(omap->usbtll_fck);
47754ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi
47854ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbierr_tll_fck:
4796dba39e278b81665a838f37a75fe37b89f3ce610Keshava Munegowda	clk_disable(omap->usbhost_fs_fck);
4806dba39e278b81665a838f37a75fe37b89f3ce610Keshava Munegowda	clk_put(omap->usbhost_fs_fck);
48154ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi
48254ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi	if (omap->phy_reset) {
48354ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi		if (gpio_is_valid(omap->reset_gpio_port[0]))
48454ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi			gpio_free(omap->reset_gpio_port[0]);
48554ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi
48654ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi		if (gpio_is_valid(omap->reset_gpio_port[1]))
48754ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi			gpio_free(omap->reset_gpio_port[1]);
48854ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi	}
48954ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi
49054ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbierr_host_48m_fck:
4916dba39e278b81665a838f37a75fe37b89f3ce610Keshava Munegowda	clk_disable(omap->usbhost_hs_fck);
4926dba39e278b81665a838f37a75fe37b89f3ce610Keshava Munegowda	clk_put(omap->usbhost_hs_fck);
49354ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi
49454ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbierr_host_120m_fck:
49554ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi	clk_disable(omap->usbhost_ick);
49654ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi	clk_put(omap->usbhost_ick);
49754ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi
49854ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbierr_host_ick:
49954ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi	return ret;
50054ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi}
50154ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi
50254ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbistatic void omap_stop_ehc(struct ehci_hcd_omap *omap, struct usb_hcd *hcd)
50354ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi{
50454ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi	unsigned long timeout = jiffies + msecs_to_jiffies(100);
50554ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi
50654ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi	dev_dbg(omap->dev, "stopping TI EHCI USB Controller\n");
50754ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi
50854ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi	/* Reset OMAP modules for insmod/rmmod to work */
50954ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi	ehci_omap_writel(omap->uhh_base, OMAP_UHH_SYSCONFIG,
51054ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi			OMAP_UHH_SYSCONFIG_SOFTRESET);
51154ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi	while (!(ehci_omap_readl(omap->uhh_base, OMAP_UHH_SYSSTATUS)
51254ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi				& (1 << 0))) {
51354ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi		cpu_relax();
51454ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi
51554ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi		if (time_after(jiffies, timeout))
51654ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi			dev_dbg(omap->dev, "operation timed out\n");
51754ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi	}
51854ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi
51954ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi	while (!(ehci_omap_readl(omap->uhh_base, OMAP_UHH_SYSSTATUS)
52054ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi				& (1 << 1))) {
52154ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi		cpu_relax();
52254ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi
52354ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi		if (time_after(jiffies, timeout))
52454ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi			dev_dbg(omap->dev, "operation timed out\n");
52554ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi	}
52654ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi
52754ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi	while (!(ehci_omap_readl(omap->uhh_base, OMAP_UHH_SYSSTATUS)
52854ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi				& (1 << 2))) {
52954ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi		cpu_relax();
53054ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi
53154ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi		if (time_after(jiffies, timeout))
53254ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi			dev_dbg(omap->dev, "operation timed out\n");
53354ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi	}
53454ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi
53554ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi	ehci_omap_writel(omap->tll_base, OMAP_USBTLL_SYSCONFIG, (1 << 1));
53654ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi
53754ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi	while (!(ehci_omap_readl(omap->tll_base, OMAP_USBTLL_SYSSTATUS)
53854ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi				& (1 << 0))) {
53954ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi		cpu_relax();
54054ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi
54154ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi		if (time_after(jiffies, timeout))
54254ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi			dev_dbg(omap->dev, "operation timed out\n");
54354ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi	}
54454ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi
54554ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi	if (omap->usbtll_fck != NULL) {
54654ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi		clk_disable(omap->usbtll_fck);
54754ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi		clk_put(omap->usbtll_fck);
54854ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi		omap->usbtll_fck = NULL;
54954ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi	}
55054ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi
55154ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi	if (omap->usbhost_ick != NULL) {
55254ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi		clk_disable(omap->usbhost_ick);
55354ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi		clk_put(omap->usbhost_ick);
55454ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi		omap->usbhost_ick = NULL;
55554ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi	}
55654ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi
5576dba39e278b81665a838f37a75fe37b89f3ce610Keshava Munegowda	if (omap->usbhost_fs_fck != NULL) {
5586dba39e278b81665a838f37a75fe37b89f3ce610Keshava Munegowda		clk_disable(omap->usbhost_fs_fck);
5596dba39e278b81665a838f37a75fe37b89f3ce610Keshava Munegowda		clk_put(omap->usbhost_fs_fck);
5606dba39e278b81665a838f37a75fe37b89f3ce610Keshava Munegowda		omap->usbhost_fs_fck = NULL;
56154ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi	}
56254ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi
5636dba39e278b81665a838f37a75fe37b89f3ce610Keshava Munegowda	if (omap->usbhost_hs_fck != NULL) {
5646dba39e278b81665a838f37a75fe37b89f3ce610Keshava Munegowda		clk_disable(omap->usbhost_hs_fck);
5656dba39e278b81665a838f37a75fe37b89f3ce610Keshava Munegowda		clk_put(omap->usbhost_hs_fck);
5666dba39e278b81665a838f37a75fe37b89f3ce610Keshava Munegowda		omap->usbhost_hs_fck = NULL;
56754ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi	}
56854ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi
56954ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi	if (omap->usbtll_ick != NULL) {
57054ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi		clk_disable(omap->usbtll_ick);
57154ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi		clk_put(omap->usbtll_ick);
57254ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi		omap->usbtll_ick = NULL;
57354ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi	}
57454ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi
57554ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi	if (omap->phy_reset) {
57654ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi		if (gpio_is_valid(omap->reset_gpio_port[0]))
57754ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi			gpio_free(omap->reset_gpio_port[0]);
57854ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi
57954ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi		if (gpio_is_valid(omap->reset_gpio_port[1]))
58054ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi			gpio_free(omap->reset_gpio_port[1]);
58154ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi	}
58254ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi
58354ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi	dev_dbg(omap->dev, "Clock to USB host has been disabled\n");
58454ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi}
58554ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi
58654ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi/*-------------------------------------------------------------------------*/
58754ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi
58854ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbistatic const struct hc_driver ehci_omap_hc_driver;
58954ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi
59054ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi/* configure so an HC device and id are always provided */
59154ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi/* always called with process context; sleeping is OK */
59254ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi
59354ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi/**
59454ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi * ehci_hcd_omap_probe - initialize TI-based HCDs
59554ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi *
59654ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi * Allocates basic resources for this USB host controller, and
59754ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi * then invokes the start() method for the HCD associated with it
59854ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi * through the hotplug entry's driver_data.
59954ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi */
60054ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbistatic int ehci_hcd_omap_probe(struct platform_device *pdev)
60154ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi{
60254ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi	struct ehci_hcd_omap_platform_data *pdata = pdev->dev.platform_data;
60354ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi	struct ehci_hcd_omap *omap;
60454ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi	struct resource *res;
60554ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi	struct usb_hcd *hcd;
60654ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi
60754ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi	int irq = platform_get_irq(pdev, 0);
60854ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi	int ret = -ENODEV;
609881142660697bba0f3ef44f070d80632082c978fAjay Kumar Gupta	int i;
610881142660697bba0f3ef44f070d80632082c978fAjay Kumar Gupta	char supply[7];
61154ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi
61254ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi	if (!pdata) {
61354ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi		dev_dbg(&pdev->dev, "missing platform_data\n");
61454ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi		goto err_pdata;
61554ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi	}
61654ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi
61754ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi	if (usb_disabled())
61854ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi		goto err_disabled;
61954ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi
62054ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi	omap = kzalloc(sizeof(*omap), GFP_KERNEL);
62154ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi	if (!omap) {
62254ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi		ret = -ENOMEM;
623b2b608090544ecd30a826c32958bca74fb717963Julia Lawall		goto err_disabled;
62454ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi	}
62554ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi
62654ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi	hcd = usb_create_hcd(&ehci_omap_hc_driver, &pdev->dev,
62754ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi			dev_name(&pdev->dev));
62854ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi	if (!hcd) {
62954ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi		dev_dbg(&pdev->dev, "failed to create hcd with err %d\n", ret);
63054ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi		ret = -ENOMEM;
63154ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi		goto err_create_hcd;
63254ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi	}
63354ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi
63454ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi	platform_set_drvdata(pdev, omap);
63554ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi	omap->dev		= &pdev->dev;
63654ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi	omap->phy_reset		= pdata->phy_reset;
63754ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi	omap->reset_gpio_port[0]	= pdata->reset_gpio_port[0];
63854ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi	omap->reset_gpio_port[1]	= pdata->reset_gpio_port[1];
63954ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi	omap->reset_gpio_port[2]	= pdata->reset_gpio_port[2];
64054ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi	omap->port_mode[0]		= pdata->port_mode[0];
64154ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi	omap->port_mode[1]		= pdata->port_mode[1];
64254ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi	omap->port_mode[2]		= pdata->port_mode[2];
64354ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi	omap->ehci		= hcd_to_ehci(hcd);
64454ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi	omap->ehci->sbrn	= 0x20;
64554ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi
64654ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
64754ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi
64854ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi	hcd->rsrc_start = res->start;
64954ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi	hcd->rsrc_len = resource_size(res);
65054ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi
65154ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi	hcd->regs = ioremap(hcd->rsrc_start, hcd->rsrc_len);
65254ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi	if (!hcd->regs) {
65354ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi		dev_err(&pdev->dev, "EHCI ioremap failed\n");
65454ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi		ret = -ENOMEM;
65554ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi		goto err_ioremap;
65654ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi	}
65754ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi
65854ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi	/* we know this is the memory we want, no need to ioremap again */
65954ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi	omap->ehci->caps = hcd->regs;
66054ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi	omap->ehci_base = hcd->regs;
66154ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi
66254ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi	res = platform_get_resource(pdev, IORESOURCE_MEM, 1);
66354ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi	omap->uhh_base = ioremap(res->start, resource_size(res));
66454ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi	if (!omap->uhh_base) {
66554ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi		dev_err(&pdev->dev, "UHH ioremap failed\n");
66654ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi		ret = -ENOMEM;
66754ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi		goto err_uhh_ioremap;
66854ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi	}
66954ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi
67054ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi	res = platform_get_resource(pdev, IORESOURCE_MEM, 2);
67154ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi	omap->tll_base = ioremap(res->start, resource_size(res));
67254ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi	if (!omap->tll_base) {
67354ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi		dev_err(&pdev->dev, "TLL ioremap failed\n");
67454ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi		ret = -ENOMEM;
67554ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi		goto err_tll_ioremap;
67654ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi	}
67754ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi
678881142660697bba0f3ef44f070d80632082c978fAjay Kumar Gupta	/* get ehci regulator and enable */
679881142660697bba0f3ef44f070d80632082c978fAjay Kumar Gupta	for (i = 0 ; i < OMAP3_HS_USB_PORTS ; i++) {
680881142660697bba0f3ef44f070d80632082c978fAjay Kumar Gupta		if (omap->port_mode[i] != EHCI_HCD_OMAP_MODE_PHY) {
681881142660697bba0f3ef44f070d80632082c978fAjay Kumar Gupta			omap->regulator[i] = NULL;
682881142660697bba0f3ef44f070d80632082c978fAjay Kumar Gupta			continue;
683881142660697bba0f3ef44f070d80632082c978fAjay Kumar Gupta		}
684881142660697bba0f3ef44f070d80632082c978fAjay Kumar Gupta		snprintf(supply, sizeof(supply), "hsusb%d", i);
685881142660697bba0f3ef44f070d80632082c978fAjay Kumar Gupta		omap->regulator[i] = regulator_get(omap->dev, supply);
68618f91196b6e7994bd694a96a6c3b0ac1f3e81d82Ajay Kumar Gupta		if (IS_ERR(omap->regulator[i])) {
68718f91196b6e7994bd694a96a6c3b0ac1f3e81d82Ajay Kumar Gupta			omap->regulator[i] = NULL;
688881142660697bba0f3ef44f070d80632082c978fAjay Kumar Gupta			dev_dbg(&pdev->dev,
689881142660697bba0f3ef44f070d80632082c978fAjay Kumar Gupta			"failed to get ehci port%d regulator\n", i);
69018f91196b6e7994bd694a96a6c3b0ac1f3e81d82Ajay Kumar Gupta		} else {
691881142660697bba0f3ef44f070d80632082c978fAjay Kumar Gupta			regulator_enable(omap->regulator[i]);
69218f91196b6e7994bd694a96a6c3b0ac1f3e81d82Ajay Kumar Gupta		}
693881142660697bba0f3ef44f070d80632082c978fAjay Kumar Gupta	}
694881142660697bba0f3ef44f070d80632082c978fAjay Kumar Gupta
69554ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi	ret = omap_start_ehc(omap, hcd);
69654ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi	if (ret) {
69754ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi		dev_dbg(&pdev->dev, "failed to start ehci\n");
69854ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi		goto err_start;
69954ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi	}
70054ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi
70154ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi	omap->ehci->regs = hcd->regs
70254ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi		+ HC_LENGTH(readl(&omap->ehci->caps->hc_capbase));
70354ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi
704bdb581bd6bd59a3303974977544d679d849214d1Anand Gadiyar	dbg_hcs_params(omap->ehci, "reset");
705bdb581bd6bd59a3303974977544d679d849214d1Anand Gadiyar	dbg_hcc_params(omap->ehci, "reset");
706bdb581bd6bd59a3303974977544d679d849214d1Anand Gadiyar
70754ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi	/* cache this readonly data; minimize chip reads */
70854ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi	omap->ehci->hcs_params = readl(&omap->ehci->caps->hcs_params);
70954ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi
71054ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi	ret = usb_add_hcd(hcd, irq, IRQF_DISABLED | IRQF_SHARED);
71154ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi	if (ret) {
71254ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi		dev_dbg(&pdev->dev, "failed to add hcd with err %d\n", ret);
71354ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi		goto err_add_hcd;
71454ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi	}
71554ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi
716289621c31bffb743e4007f6332b9004cdd080644Ajay Kumar Gupta	/* root ports should always stay powered */
717289621c31bffb743e4007f6332b9004cdd080644Ajay Kumar Gupta	ehci_port_power(omap->ehci, 1);
718289621c31bffb743e4007f6332b9004cdd080644Ajay Kumar Gupta
71954ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi	return 0;
72054ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi
72154ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbierr_add_hcd:
72254ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi	omap_stop_ehc(omap, hcd);
72354ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi
72454ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbierr_start:
725881142660697bba0f3ef44f070d80632082c978fAjay Kumar Gupta	for (i = 0 ; i < OMAP3_HS_USB_PORTS ; i++) {
726881142660697bba0f3ef44f070d80632082c978fAjay Kumar Gupta		if (omap->regulator[i]) {
727881142660697bba0f3ef44f070d80632082c978fAjay Kumar Gupta			regulator_disable(omap->regulator[i]);
728881142660697bba0f3ef44f070d80632082c978fAjay Kumar Gupta			regulator_put(omap->regulator[i]);
729881142660697bba0f3ef44f070d80632082c978fAjay Kumar Gupta		}
730881142660697bba0f3ef44f070d80632082c978fAjay Kumar Gupta	}
73154ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi	iounmap(omap->tll_base);
73254ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi
73354ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbierr_tll_ioremap:
73454ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi	iounmap(omap->uhh_base);
73554ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi
73654ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbierr_uhh_ioremap:
73754ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi	iounmap(hcd->regs);
73854ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi
73954ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbierr_ioremap:
74054ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi	usb_put_hcd(hcd);
74154ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi
74254ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbierr_create_hcd:
743b2b608090544ecd30a826c32958bca74fb717963Julia Lawall	kfree(omap);
74454ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbierr_disabled:
74554ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbierr_pdata:
74654ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi	return ret;
74754ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi}
74854ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi
74954ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi/* may be called without controller electrically present */
75054ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi/* may be called with controller, bus, and devices active */
75154ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi
75254ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi/**
75354ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi * ehci_hcd_omap_remove - shutdown processing for EHCI HCDs
75454ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi * @pdev: USB Host Controller being removed
75554ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi *
75654ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi * Reverses the effect of usb_ehci_hcd_omap_probe(), first invoking
75754ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi * the HCD's stop() method.  It is always called from a thread
75854ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi * context, normally "rmmod", "apmd", or something similar.
75954ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi */
76054ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbistatic int ehci_hcd_omap_remove(struct platform_device *pdev)
76154ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi{
76254ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi	struct ehci_hcd_omap *omap = platform_get_drvdata(pdev);
76354ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi	struct usb_hcd *hcd = ehci_to_hcd(omap->ehci);
764881142660697bba0f3ef44f070d80632082c978fAjay Kumar Gupta	int i;
76554ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi
76654ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi	usb_remove_hcd(hcd);
76754ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi	omap_stop_ehc(omap, hcd);
76854ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi	iounmap(hcd->regs);
769881142660697bba0f3ef44f070d80632082c978fAjay Kumar Gupta	for (i = 0 ; i < OMAP3_HS_USB_PORTS ; i++) {
770881142660697bba0f3ef44f070d80632082c978fAjay Kumar Gupta		if (omap->regulator[i]) {
771881142660697bba0f3ef44f070d80632082c978fAjay Kumar Gupta			regulator_disable(omap->regulator[i]);
772881142660697bba0f3ef44f070d80632082c978fAjay Kumar Gupta			regulator_put(omap->regulator[i]);
773881142660697bba0f3ef44f070d80632082c978fAjay Kumar Gupta		}
774881142660697bba0f3ef44f070d80632082c978fAjay Kumar Gupta	}
77554ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi	iounmap(omap->tll_base);
77654ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi	iounmap(omap->uhh_base);
77754ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi	usb_put_hcd(hcd);
778d3ae8562d43fe2b97d605dd67dc67bf8fa9b956aAjay Kumar Gupta	kfree(omap);
77954ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi
78054ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi	return 0;
78154ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi}
78254ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi
78354ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbistatic void ehci_hcd_omap_shutdown(struct platform_device *pdev)
78454ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi{
78554ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi	struct ehci_hcd_omap *omap = platform_get_drvdata(pdev);
78654ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi	struct usb_hcd *hcd = ehci_to_hcd(omap->ehci);
78754ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi
78854ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi	if (hcd->driver->shutdown)
78954ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi		hcd->driver->shutdown(hcd);
79054ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi}
79154ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi
79254ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbistatic struct platform_driver ehci_hcd_omap_driver = {
79354ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi	.probe			= ehci_hcd_omap_probe,
79454ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi	.remove			= ehci_hcd_omap_remove,
79554ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi	.shutdown		= ehci_hcd_omap_shutdown,
79654ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi	/*.suspend		= ehci_hcd_omap_suspend, */
79754ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi	/*.resume		= ehci_hcd_omap_resume, */
79854ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi	.driver = {
79954ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi		.name		= "ehci-omap",
80054ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi	}
80154ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi};
80254ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi
80354ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi/*-------------------------------------------------------------------------*/
80454ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi
80554ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbistatic const struct hc_driver ehci_omap_hc_driver = {
80654ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi	.description		= hcd_name,
80754ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi	.product_desc		= "OMAP-EHCI Host Controller",
80854ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi	.hcd_priv_size		= sizeof(struct ehci_hcd),
80954ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi
81054ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi	/*
81154ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi	 * generic hardware linkage
81254ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi	 */
81354ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi	.irq			= ehci_irq,
81454ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi	.flags			= HCD_MEMORY | HCD_USB2,
81554ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi
81654ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi	/*
81754ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi	 * basic lifecycle operations
81854ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi	 */
81954ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi	.reset			= ehci_init,
82054ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi	.start			= ehci_run,
82154ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi	.stop			= ehci_stop,
82254ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi	.shutdown		= ehci_shutdown,
82354ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi
82454ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi	/*
82554ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi	 * managing i/o requests and associated device resources
82654ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi	 */
82754ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi	.urb_enqueue		= ehci_urb_enqueue,
82854ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi	.urb_dequeue		= ehci_urb_dequeue,
82954ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi	.endpoint_disable	= ehci_endpoint_disable,
83054ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi	.endpoint_reset		= ehci_endpoint_reset,
83154ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi
83254ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi	/*
83354ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi	 * scheduling support
83454ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi	 */
83554ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi	.get_frame_number	= ehci_get_frame,
83654ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi
83754ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi	/*
83854ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi	 * root hub support
83954ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi	 */
84054ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi	.hub_status_data	= ehci_hub_status_data,
84154ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi	.hub_control		= ehci_hub_control,
84254ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi	.bus_suspend		= ehci_bus_suspend,
84354ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi	.bus_resume		= ehci_bus_resume,
84454ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi
84554ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi	.clear_tt_buffer_complete = ehci_clear_tt_buffer_complete,
84654ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi};
84754ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi
84854ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe BalbiMODULE_ALIAS("platform:omap-ehci");
84954ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe BalbiMODULE_AUTHOR("Texas Instruments, Inc.");
85054ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe BalbiMODULE_AUTHOR("Felipe Balbi <felipe.balbi@nokia.com>");
85154ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi
852