ehci-omap.c revision 354ab8567ae3107a8cbe7228c3181990ba598aac
154ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi/*
24792a15bf0f388838c3e16636f961c99bc2f3572Anand Gadiyar * ehci-omap.c - driver for USBHOST on OMAP3/4 processors
354ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi *
44792a15bf0f388838c3e16636f961c99bc2f3572Anand Gadiyar * Bus Glue for the EHCI controllers in OMAP3/4
54792a15bf0f388838c3e16636f961c99bc2f3572Anand Gadiyar * Tested on several OMAP3 boards, and OMAP4 Pandaboard
654ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi *
719403165c272cc4ed00c97973e7271714b009708Keshava Munegowda * Copyright (C) 2007-2011 Texas Instruments, Inc.
854ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi *	Author: Vikram Pandita <vikram.pandita@ti.com>
94792a15bf0f388838c3e16636f961c99bc2f3572Anand Gadiyar *	Author: Anand Gadiyar <gadiyar@ti.com>
1019403165c272cc4ed00c97973e7271714b009708Keshava Munegowda *	Author: Keshava Munegowda <keshava_mgowda@ti.com>
1154ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi *
1254ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi * Copyright (C) 2009 Nokia Corporation
1354ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi *	Contact: Felipe Balbi <felipe.balbi@nokia.com>
1454ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi *
1554ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi * Based on "ehci-fsl.c" and "ehci-au1xxx.c" ehci glue layers
1654ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi *
1754ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi * This program is free software; you can redistribute it and/or modify
1854ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi * it under the terms of the GNU General Public License as published by
1954ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi * the Free Software Foundation; either version 2 of the License, or
2054ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi * (at your option) any later version.
2154ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi *
2254ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi * This program is distributed in the hope that it will be useful,
2354ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi * but WITHOUT ANY WARRANTY; without even the implied warranty of
2454ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
2554ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi * GNU General Public License for more details.
2654ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi *
2754ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi * You should have received a copy of the GNU General Public License
2854ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi * along with this program; if not, write to the Free Software
2954ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
3054ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi *
3119403165c272cc4ed00c97973e7271714b009708Keshava Munegowda * TODO (last updated Feb 27, 2010):
3254ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi *	- add kernel-doc
3354ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi *	- enable AUTOIDLE
3454ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi *	- add suspend/resume
354792a15bf0f388838c3e16636f961c99bc2f3572Anand Gadiyar *	- add HSIC and TLL support
364792a15bf0f388838c3e16636f961c99bc2f3572Anand Gadiyar *	- convert to use hwmod and runtime PM
3754ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi */
3854ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi
3954ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi#include <linux/platform_device.h>
405a0e3ad6af8660be21ca98a971cd00f331318c05Tejun Heo#include <linux/slab.h>
415aa4af2ce6a0643f32d47f21614817792b85298dAjay Kumar Gupta#include <linux/usb/ulpi.h>
42c76f782cb3cfffc1fd4233e11f3116655fa0fcd2Thomas Weber#include <plat/usb.h>
436e3d4bec6b1e0829ed8b23be750762255f225019Keshava Munegowda#include <linux/regulator/consumer.h>
446c984b066d84bb6e8f5a739ffb1dc4858df017a3Keshava Munegowda#include <linux/pm_runtime.h>
451fcb57d0f6e1150003d222051aaaf4bc4a9ccc94Keshava Munegowda#include <linux/gpio.h>
46354ab8567ae3107a8cbe7228c3181990ba598aacAnand Gadiyar#include <linux/clk.h>
4754ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi
4854ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi/* EHCI Register Set */
49572538dee7a4b25f3e77fdc11d20dbb753ecf367Anand Gadiyar#define EHCI_INSNREG04					(0xA0)
50572538dee7a4b25f3e77fdc11d20dbb753ecf367Anand Gadiyar#define EHCI_INSNREG04_DISABLE_UNSUSPEND		(1 << 5)
5154ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi#define	EHCI_INSNREG05_ULPI				(0xA4)
5254ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi#define	EHCI_INSNREG05_ULPI_CONTROL_SHIFT		31
5354ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi#define	EHCI_INSNREG05_ULPI_PORTSEL_SHIFT		24
5454ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi#define	EHCI_INSNREG05_ULPI_OPSEL_SHIFT			22
5554ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi#define	EHCI_INSNREG05_ULPI_REGADD_SHIFT		16
5654ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi#define	EHCI_INSNREG05_ULPI_EXTREGADD_SHIFT		8
5754ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi#define	EHCI_INSNREG05_ULPI_WRDATA_SHIFT		0
5854ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi
59354ab8567ae3107a8cbe7228c3181990ba598aacAnand Gadiyar/* Errata i693 */
60354ab8567ae3107a8cbe7228c3181990ba598aacAnand Gadiyarstatic struct clk	*utmi_p1_fck;
61354ab8567ae3107a8cbe7228c3181990ba598aacAnand Gadiyarstatic struct clk	*utmi_p2_fck;
62354ab8567ae3107a8cbe7228c3181990ba598aacAnand Gadiyarstatic struct clk	*xclk60mhsp1_ck;
63354ab8567ae3107a8cbe7228c3181990ba598aacAnand Gadiyarstatic struct clk	*xclk60mhsp2_ck;
64354ab8567ae3107a8cbe7228c3181990ba598aacAnand Gadiyarstatic struct clk	*usbhost_p1_fck;
65354ab8567ae3107a8cbe7228c3181990ba598aacAnand Gadiyarstatic struct clk	*usbhost_p2_fck;
66354ab8567ae3107a8cbe7228c3181990ba598aacAnand Gadiyarstatic struct clk	*init_60m_fclk;
67354ab8567ae3107a8cbe7228c3181990ba598aacAnand Gadiyar
6819403165c272cc4ed00c97973e7271714b009708Keshava Munegowda/*-------------------------------------------------------------------------*/
694792a15bf0f388838c3e16636f961c99bc2f3572Anand Gadiyar
7019403165c272cc4ed00c97973e7271714b009708Keshava Munegowdastatic const struct hc_driver ehci_omap_hc_driver;
714792a15bf0f388838c3e16636f961c99bc2f3572Anand Gadiyar
72a42ccdc14de388a35ad0e8057543369351395eb9Anand Gadiyar
7319403165c272cc4ed00c97973e7271714b009708Keshava Munegowdastatic inline void ehci_write(void __iomem *base, u32 reg, u32 val)
7454ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi{
7554ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi	__raw_writel(val, base + reg);
7654ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi}
7754ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi
7819403165c272cc4ed00c97973e7271714b009708Keshava Munegowdastatic inline u32 ehci_read(void __iomem *base, u32 reg)
7954ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi{
8054ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi	return __raw_readl(base + reg);
8154ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi}
8254ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi
83354ab8567ae3107a8cbe7228c3181990ba598aacAnand Gadiyar/* Erratum i693 workaround sequence */
84354ab8567ae3107a8cbe7228c3181990ba598aacAnand Gadiyarstatic void omap_ehci_erratum_i693(struct ehci_hcd *ehci)
85354ab8567ae3107a8cbe7228c3181990ba598aacAnand Gadiyar{
86354ab8567ae3107a8cbe7228c3181990ba598aacAnand Gadiyar	int ret = 0;
87354ab8567ae3107a8cbe7228c3181990ba598aacAnand Gadiyar
88354ab8567ae3107a8cbe7228c3181990ba598aacAnand Gadiyar	/* Switch to the internal 60 MHz clock */
89354ab8567ae3107a8cbe7228c3181990ba598aacAnand Gadiyar	ret = clk_set_parent(utmi_p1_fck, init_60m_fclk);
90354ab8567ae3107a8cbe7228c3181990ba598aacAnand Gadiyar	if (ret != 0)
91354ab8567ae3107a8cbe7228c3181990ba598aacAnand Gadiyar		ehci_err(ehci, "init_60m_fclk set parent"
92354ab8567ae3107a8cbe7228c3181990ba598aacAnand Gadiyar			"failed error:%d\n", ret);
93354ab8567ae3107a8cbe7228c3181990ba598aacAnand Gadiyar
94354ab8567ae3107a8cbe7228c3181990ba598aacAnand Gadiyar	ret = clk_set_parent(utmi_p2_fck, init_60m_fclk);
95354ab8567ae3107a8cbe7228c3181990ba598aacAnand Gadiyar	if (ret != 0)
96354ab8567ae3107a8cbe7228c3181990ba598aacAnand Gadiyar		ehci_err(ehci, "init_60m_fclk set parent"
97354ab8567ae3107a8cbe7228c3181990ba598aacAnand Gadiyar			"failed error:%d\n", ret);
98354ab8567ae3107a8cbe7228c3181990ba598aacAnand Gadiyar
99354ab8567ae3107a8cbe7228c3181990ba598aacAnand Gadiyar	clk_enable(usbhost_p1_fck);
100354ab8567ae3107a8cbe7228c3181990ba598aacAnand Gadiyar	clk_enable(usbhost_p2_fck);
101354ab8567ae3107a8cbe7228c3181990ba598aacAnand Gadiyar
102354ab8567ae3107a8cbe7228c3181990ba598aacAnand Gadiyar	/* Wait 1ms and switch back to the external clock */
103354ab8567ae3107a8cbe7228c3181990ba598aacAnand Gadiyar	mdelay(1);
104354ab8567ae3107a8cbe7228c3181990ba598aacAnand Gadiyar	ret = clk_set_parent(utmi_p1_fck, xclk60mhsp1_ck);
105354ab8567ae3107a8cbe7228c3181990ba598aacAnand Gadiyar	if (ret != 0)
106354ab8567ae3107a8cbe7228c3181990ba598aacAnand Gadiyar		ehci_err(ehci, "xclk60mhsp1_ck set parent"
107354ab8567ae3107a8cbe7228c3181990ba598aacAnand Gadiyar			"failed error:%d\n", ret);
108354ab8567ae3107a8cbe7228c3181990ba598aacAnand Gadiyar
109354ab8567ae3107a8cbe7228c3181990ba598aacAnand Gadiyar	ret = clk_set_parent(utmi_p2_fck, xclk60mhsp2_ck);
110354ab8567ae3107a8cbe7228c3181990ba598aacAnand Gadiyar	if (ret != 0)
111354ab8567ae3107a8cbe7228c3181990ba598aacAnand Gadiyar		ehci_err(ehci, "xclk60mhsp2_ck set parent"
112354ab8567ae3107a8cbe7228c3181990ba598aacAnand Gadiyar			"failed error:%d\n", ret);
113354ab8567ae3107a8cbe7228c3181990ba598aacAnand Gadiyar
114354ab8567ae3107a8cbe7228c3181990ba598aacAnand Gadiyar	clk_disable(usbhost_p1_fck);
115354ab8567ae3107a8cbe7228c3181990ba598aacAnand Gadiyar	clk_disable(usbhost_p2_fck);
116354ab8567ae3107a8cbe7228c3181990ba598aacAnand Gadiyar}
117354ab8567ae3107a8cbe7228c3181990ba598aacAnand Gadiyar
11819403165c272cc4ed00c97973e7271714b009708Keshava Munegowdastatic void omap_ehci_soft_phy_reset(struct platform_device *pdev, u8 port)
1195aa4af2ce6a0643f32d47f21614817792b85298dAjay Kumar Gupta{
12019403165c272cc4ed00c97973e7271714b009708Keshava Munegowda	struct usb_hcd	*hcd = dev_get_drvdata(&pdev->dev);
1215aa4af2ce6a0643f32d47f21614817792b85298dAjay Kumar Gupta	unsigned long timeout = jiffies + msecs_to_jiffies(1000);
1225aa4af2ce6a0643f32d47f21614817792b85298dAjay Kumar Gupta	unsigned reg = 0;
1235aa4af2ce6a0643f32d47f21614817792b85298dAjay Kumar Gupta
1245aa4af2ce6a0643f32d47f21614817792b85298dAjay Kumar Gupta	reg = ULPI_FUNC_CTRL_RESET
1255aa4af2ce6a0643f32d47f21614817792b85298dAjay Kumar Gupta		/* FUNCTION_CTRL_SET register */
1265aa4af2ce6a0643f32d47f21614817792b85298dAjay Kumar Gupta		| (ULPI_SET(ULPI_FUNC_CTRL) << EHCI_INSNREG05_ULPI_REGADD_SHIFT)
1275aa4af2ce6a0643f32d47f21614817792b85298dAjay Kumar Gupta		/* Write */
1285aa4af2ce6a0643f32d47f21614817792b85298dAjay Kumar Gupta		| (2 << EHCI_INSNREG05_ULPI_OPSEL_SHIFT)
1295aa4af2ce6a0643f32d47f21614817792b85298dAjay Kumar Gupta		/* PORTn */
1305aa4af2ce6a0643f32d47f21614817792b85298dAjay Kumar Gupta		| ((port + 1) << EHCI_INSNREG05_ULPI_PORTSEL_SHIFT)
1315aa4af2ce6a0643f32d47f21614817792b85298dAjay Kumar Gupta		/* start ULPI access*/
1325aa4af2ce6a0643f32d47f21614817792b85298dAjay Kumar Gupta		| (1 << EHCI_INSNREG05_ULPI_CONTROL_SHIFT);
1335aa4af2ce6a0643f32d47f21614817792b85298dAjay Kumar Gupta
13419403165c272cc4ed00c97973e7271714b009708Keshava Munegowda	ehci_write(hcd->regs, EHCI_INSNREG05_ULPI, reg);
1355aa4af2ce6a0643f32d47f21614817792b85298dAjay Kumar Gupta
1365aa4af2ce6a0643f32d47f21614817792b85298dAjay Kumar Gupta	/* Wait for ULPI access completion */
13719403165c272cc4ed00c97973e7271714b009708Keshava Munegowda	while ((ehci_read(hcd->regs, EHCI_INSNREG05_ULPI)
1385aa4af2ce6a0643f32d47f21614817792b85298dAjay Kumar Gupta			& (1 << EHCI_INSNREG05_ULPI_CONTROL_SHIFT))) {
1395aa4af2ce6a0643f32d47f21614817792b85298dAjay Kumar Gupta		cpu_relax();
1405aa4af2ce6a0643f32d47f21614817792b85298dAjay Kumar Gupta
1415aa4af2ce6a0643f32d47f21614817792b85298dAjay Kumar Gupta		if (time_after(jiffies, timeout)) {
14219403165c272cc4ed00c97973e7271714b009708Keshava Munegowda			dev_dbg(&pdev->dev, "phy reset operation timed out\n");
1435aa4af2ce6a0643f32d47f21614817792b85298dAjay Kumar Gupta			break;
1445aa4af2ce6a0643f32d47f21614817792b85298dAjay Kumar Gupta		}
1455aa4af2ce6a0643f32d47f21614817792b85298dAjay Kumar Gupta	}
1465aa4af2ce6a0643f32d47f21614817792b85298dAjay Kumar Gupta}
1475aa4af2ce6a0643f32d47f21614817792b85298dAjay Kumar Gupta
148354ab8567ae3107a8cbe7228c3181990ba598aacAnand Gadiyarstatic int omap_ehci_hub_control(
149354ab8567ae3107a8cbe7228c3181990ba598aacAnand Gadiyar	struct usb_hcd	*hcd,
150354ab8567ae3107a8cbe7228c3181990ba598aacAnand Gadiyar	u16		typeReq,
151354ab8567ae3107a8cbe7228c3181990ba598aacAnand Gadiyar	u16		wValue,
152354ab8567ae3107a8cbe7228c3181990ba598aacAnand Gadiyar	u16		wIndex,
153354ab8567ae3107a8cbe7228c3181990ba598aacAnand Gadiyar	char		*buf,
154354ab8567ae3107a8cbe7228c3181990ba598aacAnand Gadiyar	u16		wLength
155354ab8567ae3107a8cbe7228c3181990ba598aacAnand Gadiyar)
156354ab8567ae3107a8cbe7228c3181990ba598aacAnand Gadiyar{
157354ab8567ae3107a8cbe7228c3181990ba598aacAnand Gadiyar	struct ehci_hcd	*ehci = hcd_to_ehci(hcd);
158354ab8567ae3107a8cbe7228c3181990ba598aacAnand Gadiyar	u32 __iomem *status_reg = &ehci->regs->port_status[
159354ab8567ae3107a8cbe7228c3181990ba598aacAnand Gadiyar				(wIndex & 0xff) - 1];
160354ab8567ae3107a8cbe7228c3181990ba598aacAnand Gadiyar	u32		temp;
161354ab8567ae3107a8cbe7228c3181990ba598aacAnand Gadiyar	unsigned long	flags;
162354ab8567ae3107a8cbe7228c3181990ba598aacAnand Gadiyar	int		retval = 0;
163354ab8567ae3107a8cbe7228c3181990ba598aacAnand Gadiyar
164354ab8567ae3107a8cbe7228c3181990ba598aacAnand Gadiyar	spin_lock_irqsave(&ehci->lock, flags);
165354ab8567ae3107a8cbe7228c3181990ba598aacAnand Gadiyar
166354ab8567ae3107a8cbe7228c3181990ba598aacAnand Gadiyar	if (typeReq == SetPortFeature && wValue == USB_PORT_FEAT_SUSPEND) {
167354ab8567ae3107a8cbe7228c3181990ba598aacAnand Gadiyar		temp = ehci_readl(ehci, status_reg);
168354ab8567ae3107a8cbe7228c3181990ba598aacAnand Gadiyar		if ((temp & PORT_PE) == 0 || (temp & PORT_RESET) != 0) {
169354ab8567ae3107a8cbe7228c3181990ba598aacAnand Gadiyar			retval = -EPIPE;
170354ab8567ae3107a8cbe7228c3181990ba598aacAnand Gadiyar			goto done;
171354ab8567ae3107a8cbe7228c3181990ba598aacAnand Gadiyar		}
172354ab8567ae3107a8cbe7228c3181990ba598aacAnand Gadiyar
173354ab8567ae3107a8cbe7228c3181990ba598aacAnand Gadiyar		temp &= ~PORT_WKCONN_E;
174354ab8567ae3107a8cbe7228c3181990ba598aacAnand Gadiyar		temp |= PORT_WKDISC_E | PORT_WKOC_E;
175354ab8567ae3107a8cbe7228c3181990ba598aacAnand Gadiyar		ehci_writel(ehci, temp | PORT_SUSPEND, status_reg);
176354ab8567ae3107a8cbe7228c3181990ba598aacAnand Gadiyar
177354ab8567ae3107a8cbe7228c3181990ba598aacAnand Gadiyar		omap_ehci_erratum_i693(ehci);
178354ab8567ae3107a8cbe7228c3181990ba598aacAnand Gadiyar
179354ab8567ae3107a8cbe7228c3181990ba598aacAnand Gadiyar		set_bit((wIndex & 0xff) - 1, &ehci->suspended_ports);
180354ab8567ae3107a8cbe7228c3181990ba598aacAnand Gadiyar		goto done;
181354ab8567ae3107a8cbe7228c3181990ba598aacAnand Gadiyar	}
182354ab8567ae3107a8cbe7228c3181990ba598aacAnand Gadiyar
183354ab8567ae3107a8cbe7228c3181990ba598aacAnand Gadiyar	spin_unlock_irqrestore(&ehci->lock, flags);
184354ab8567ae3107a8cbe7228c3181990ba598aacAnand Gadiyar
185354ab8567ae3107a8cbe7228c3181990ba598aacAnand Gadiyar	/* Handle the hub control events here */
186354ab8567ae3107a8cbe7228c3181990ba598aacAnand Gadiyar	return ehci_hub_control(hcd, typeReq, wValue, wIndex, buf, wLength);
187354ab8567ae3107a8cbe7228c3181990ba598aacAnand Gadiyardone:
188354ab8567ae3107a8cbe7228c3181990ba598aacAnand Gadiyar	spin_unlock_irqrestore(&ehci->lock, flags);
189354ab8567ae3107a8cbe7228c3181990ba598aacAnand Gadiyar	return retval;
190354ab8567ae3107a8cbe7228c3181990ba598aacAnand Gadiyar}
191354ab8567ae3107a8cbe7228c3181990ba598aacAnand Gadiyar
192d4aefec5daf51ebda90ebf0989598c206cf8e640Ming Leistatic void disable_put_regulator(
193d4aefec5daf51ebda90ebf0989598c206cf8e640Ming Lei		struct ehci_hcd_omap_platform_data *pdata)
194d4aefec5daf51ebda90ebf0989598c206cf8e640Ming Lei{
195d4aefec5daf51ebda90ebf0989598c206cf8e640Ming Lei	int i;
196d4aefec5daf51ebda90ebf0989598c206cf8e640Ming Lei
197d4aefec5daf51ebda90ebf0989598c206cf8e640Ming Lei	for (i = 0 ; i < OMAP3_HS_USB_PORTS ; i++) {
198d4aefec5daf51ebda90ebf0989598c206cf8e640Ming Lei		if (pdata->regulator[i]) {
199d4aefec5daf51ebda90ebf0989598c206cf8e640Ming Lei			regulator_disable(pdata->regulator[i]);
200d4aefec5daf51ebda90ebf0989598c206cf8e640Ming Lei			regulator_put(pdata->regulator[i]);
201d4aefec5daf51ebda90ebf0989598c206cf8e640Ming Lei		}
202d4aefec5daf51ebda90ebf0989598c206cf8e640Ming Lei	}
203d4aefec5daf51ebda90ebf0989598c206cf8e640Ming Lei}
20454ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi
20554ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi/* configure so an HC device and id are always provided */
20654ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi/* always called with process context; sleeping is OK */
20754ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi
20854ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi/**
20954ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi * ehci_hcd_omap_probe - initialize TI-based HCDs
21054ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi *
21154ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi * Allocates basic resources for this USB host controller, and
21254ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi * then invokes the start() method for the HCD associated with it
21354ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi * through the hotplug entry's driver_data.
21454ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi */
21554ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbistatic int ehci_hcd_omap_probe(struct platform_device *pdev)
21654ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi{
21719403165c272cc4ed00c97973e7271714b009708Keshava Munegowda	struct device				*dev = &pdev->dev;
21819403165c272cc4ed00c97973e7271714b009708Keshava Munegowda	struct ehci_hcd_omap_platform_data	*pdata = dev->platform_data;
21919403165c272cc4ed00c97973e7271714b009708Keshava Munegowda	struct resource				*res;
22019403165c272cc4ed00c97973e7271714b009708Keshava Munegowda	struct usb_hcd				*hcd;
22119403165c272cc4ed00c97973e7271714b009708Keshava Munegowda	void __iomem				*regs;
22219403165c272cc4ed00c97973e7271714b009708Keshava Munegowda	struct ehci_hcd				*omap_ehci;
22319403165c272cc4ed00c97973e7271714b009708Keshava Munegowda	int					ret = -ENODEV;
22419403165c272cc4ed00c97973e7271714b009708Keshava Munegowda	int					irq;
2256e3d4bec6b1e0829ed8b23be750762255f225019Keshava Munegowda	int					i;
2266e3d4bec6b1e0829ed8b23be750762255f225019Keshava Munegowda	char					supply[7];
22754ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi
22819403165c272cc4ed00c97973e7271714b009708Keshava Munegowda	if (usb_disabled())
22919403165c272cc4ed00c97973e7271714b009708Keshava Munegowda		return -ENODEV;
23054ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi
23119403165c272cc4ed00c97973e7271714b009708Keshava Munegowda	if (!dev->parent) {
23219403165c272cc4ed00c97973e7271714b009708Keshava Munegowda		dev_err(dev, "Missing parent device\n");
23319403165c272cc4ed00c97973e7271714b009708Keshava Munegowda		return -ENODEV;
23454ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi	}
23554ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi
23619403165c272cc4ed00c97973e7271714b009708Keshava Munegowda	irq = platform_get_irq_byname(pdev, "ehci-irq");
23719403165c272cc4ed00c97973e7271714b009708Keshava Munegowda	if (irq < 0) {
23819403165c272cc4ed00c97973e7271714b009708Keshava Munegowda		dev_err(dev, "EHCI irq failed\n");
23919403165c272cc4ed00c97973e7271714b009708Keshava Munegowda		return -ENODEV;
24019403165c272cc4ed00c97973e7271714b009708Keshava Munegowda	}
24154ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi
24219403165c272cc4ed00c97973e7271714b009708Keshava Munegowda	res =  platform_get_resource_byname(pdev,
24319403165c272cc4ed00c97973e7271714b009708Keshava Munegowda				IORESOURCE_MEM, "ehci");
24419403165c272cc4ed00c97973e7271714b009708Keshava Munegowda	if (!res) {
24519403165c272cc4ed00c97973e7271714b009708Keshava Munegowda		dev_err(dev, "UHH EHCI get resource failed\n");
24619403165c272cc4ed00c97973e7271714b009708Keshava Munegowda		return -ENODEV;
24719403165c272cc4ed00c97973e7271714b009708Keshava Munegowda	}
24819403165c272cc4ed00c97973e7271714b009708Keshava Munegowda
24919403165c272cc4ed00c97973e7271714b009708Keshava Munegowda	regs = ioremap(res->start, resource_size(res));
25019403165c272cc4ed00c97973e7271714b009708Keshava Munegowda	if (!regs) {
25119403165c272cc4ed00c97973e7271714b009708Keshava Munegowda		dev_err(dev, "UHH EHCI ioremap failed\n");
25219403165c272cc4ed00c97973e7271714b009708Keshava Munegowda		return -ENOMEM;
25354ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi	}
25454ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi
25519403165c272cc4ed00c97973e7271714b009708Keshava Munegowda	hcd = usb_create_hcd(&ehci_omap_hc_driver, dev,
25619403165c272cc4ed00c97973e7271714b009708Keshava Munegowda			dev_name(dev));
25754ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi	if (!hcd) {
25819403165c272cc4ed00c97973e7271714b009708Keshava Munegowda		dev_err(dev, "failed to create hcd with err %d\n", ret);
25954ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi		ret = -ENOMEM;
26019403165c272cc4ed00c97973e7271714b009708Keshava Munegowda		goto err_io;
26154ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi	}
26254ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi
26354ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi	hcd->rsrc_start = res->start;
26454ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi	hcd->rsrc_len = resource_size(res);
26519403165c272cc4ed00c97973e7271714b009708Keshava Munegowda	hcd->regs = regs;
26654ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi
2676e3d4bec6b1e0829ed8b23be750762255f225019Keshava Munegowda	/* get ehci regulator and enable */
2686e3d4bec6b1e0829ed8b23be750762255f225019Keshava Munegowda	for (i = 0 ; i < OMAP3_HS_USB_PORTS ; i++) {
2696e3d4bec6b1e0829ed8b23be750762255f225019Keshava Munegowda		if (pdata->port_mode[i] != OMAP_EHCI_PORT_MODE_PHY) {
2706e3d4bec6b1e0829ed8b23be750762255f225019Keshava Munegowda			pdata->regulator[i] = NULL;
2716e3d4bec6b1e0829ed8b23be750762255f225019Keshava Munegowda			continue;
2726e3d4bec6b1e0829ed8b23be750762255f225019Keshava Munegowda		}
2736e3d4bec6b1e0829ed8b23be750762255f225019Keshava Munegowda		snprintf(supply, sizeof(supply), "hsusb%d", i);
2746e3d4bec6b1e0829ed8b23be750762255f225019Keshava Munegowda		pdata->regulator[i] = regulator_get(dev, supply);
2756e3d4bec6b1e0829ed8b23be750762255f225019Keshava Munegowda		if (IS_ERR(pdata->regulator[i])) {
2766e3d4bec6b1e0829ed8b23be750762255f225019Keshava Munegowda			pdata->regulator[i] = NULL;
2776e3d4bec6b1e0829ed8b23be750762255f225019Keshava Munegowda			dev_dbg(dev,
2786e3d4bec6b1e0829ed8b23be750762255f225019Keshava Munegowda			"failed to get ehci port%d regulator\n", i);
2796e3d4bec6b1e0829ed8b23be750762255f225019Keshava Munegowda		} else {
2806e3d4bec6b1e0829ed8b23be750762255f225019Keshava Munegowda			regulator_enable(pdata->regulator[i]);
2816e3d4bec6b1e0829ed8b23be750762255f225019Keshava Munegowda		}
2826e3d4bec6b1e0829ed8b23be750762255f225019Keshava Munegowda	}
2836e3d4bec6b1e0829ed8b23be750762255f225019Keshava Munegowda
2841fcb57d0f6e1150003d222051aaaf4bc4a9ccc94Keshava Munegowda	if (pdata->phy_reset) {
2851fcb57d0f6e1150003d222051aaaf4bc4a9ccc94Keshava Munegowda		if (gpio_is_valid(pdata->reset_gpio_port[0]))
2861fcb57d0f6e1150003d222051aaaf4bc4a9ccc94Keshava Munegowda			gpio_request_one(pdata->reset_gpio_port[0],
2871fcb57d0f6e1150003d222051aaaf4bc4a9ccc94Keshava Munegowda					 GPIOF_OUT_INIT_LOW, "USB1 PHY reset");
2881fcb57d0f6e1150003d222051aaaf4bc4a9ccc94Keshava Munegowda
2891fcb57d0f6e1150003d222051aaaf4bc4a9ccc94Keshava Munegowda		if (gpio_is_valid(pdata->reset_gpio_port[1]))
2901fcb57d0f6e1150003d222051aaaf4bc4a9ccc94Keshava Munegowda			gpio_request_one(pdata->reset_gpio_port[1],
2911fcb57d0f6e1150003d222051aaaf4bc4a9ccc94Keshava Munegowda					 GPIOF_OUT_INIT_LOW, "USB2 PHY reset");
2921fcb57d0f6e1150003d222051aaaf4bc4a9ccc94Keshava Munegowda
2931fcb57d0f6e1150003d222051aaaf4bc4a9ccc94Keshava Munegowda		/* Hold the PHY in RESET for enough time till DIR is high */
2941fcb57d0f6e1150003d222051aaaf4bc4a9ccc94Keshava Munegowda		udelay(10);
2951fcb57d0f6e1150003d222051aaaf4bc4a9ccc94Keshava Munegowda	}
2961fcb57d0f6e1150003d222051aaaf4bc4a9ccc94Keshava Munegowda
2976c984b066d84bb6e8f5a739ffb1dc4858df017a3Keshava Munegowda	pm_runtime_enable(dev);
2986c984b066d84bb6e8f5a739ffb1dc4858df017a3Keshava Munegowda	pm_runtime_get_sync(dev);
29954ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi
30019403165c272cc4ed00c97973e7271714b009708Keshava Munegowda	/*
30119403165c272cc4ed00c97973e7271714b009708Keshava Munegowda	 * An undocumented "feature" in the OMAP3 EHCI controller,
30219403165c272cc4ed00c97973e7271714b009708Keshava Munegowda	 * causes suspended ports to be taken out of suspend when
30319403165c272cc4ed00c97973e7271714b009708Keshava Munegowda	 * the USBCMD.Run/Stop bit is cleared (for example when
30419403165c272cc4ed00c97973e7271714b009708Keshava Munegowda	 * we do ehci_bus_suspend).
30519403165c272cc4ed00c97973e7271714b009708Keshava Munegowda	 * This breaks suspend-resume if the root-hub is allowed
30619403165c272cc4ed00c97973e7271714b009708Keshava Munegowda	 * to suspend. Writing 1 to this undocumented register bit
30719403165c272cc4ed00c97973e7271714b009708Keshava Munegowda	 * disables this feature and restores normal behavior.
30819403165c272cc4ed00c97973e7271714b009708Keshava Munegowda	 */
30919403165c272cc4ed00c97973e7271714b009708Keshava Munegowda	ehci_write(regs, EHCI_INSNREG04,
31019403165c272cc4ed00c97973e7271714b009708Keshava Munegowda				EHCI_INSNREG04_DISABLE_UNSUSPEND);
31154ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi
31219403165c272cc4ed00c97973e7271714b009708Keshava Munegowda	/* Soft reset the PHY using PHY reset command over ULPI */
31319403165c272cc4ed00c97973e7271714b009708Keshava Munegowda	if (pdata->port_mode[0] == OMAP_EHCI_PORT_MODE_PHY)
31419403165c272cc4ed00c97973e7271714b009708Keshava Munegowda		omap_ehci_soft_phy_reset(pdev, 0);
31519403165c272cc4ed00c97973e7271714b009708Keshava Munegowda	if (pdata->port_mode[1] == OMAP_EHCI_PORT_MODE_PHY)
31619403165c272cc4ed00c97973e7271714b009708Keshava Munegowda		omap_ehci_soft_phy_reset(pdev, 1);
317881142660697bba0f3ef44f070d80632082c978fAjay Kumar Gupta
31819403165c272cc4ed00c97973e7271714b009708Keshava Munegowda	omap_ehci = hcd_to_ehci(hcd);
31919403165c272cc4ed00c97973e7271714b009708Keshava Munegowda	omap_ehci->sbrn = 0x20;
32054ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi
32119403165c272cc4ed00c97973e7271714b009708Keshava Munegowda	/* we know this is the memory we want, no need to ioremap again */
32219403165c272cc4ed00c97973e7271714b009708Keshava Munegowda	omap_ehci->caps = hcd->regs;
32319403165c272cc4ed00c97973e7271714b009708Keshava Munegowda	omap_ehci->regs = hcd->regs
324c430131a02d677aa708f56342c1565edfdacb3c0Jan Andersson		+ HC_LENGTH(ehci, readl(&omap_ehci->caps->hc_capbase));
32554ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi
32619403165c272cc4ed00c97973e7271714b009708Keshava Munegowda	dbg_hcs_params(omap_ehci, "reset");
32719403165c272cc4ed00c97973e7271714b009708Keshava Munegowda	dbg_hcc_params(omap_ehci, "reset");
328bdb581bd6bd59a3303974977544d679d849214d1Anand Gadiyar
32954ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi	/* cache this readonly data; minimize chip reads */
33019403165c272cc4ed00c97973e7271714b009708Keshava Munegowda	omap_ehci->hcs_params = readl(&omap_ehci->caps->hcs_params);
33154ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi
332876e0df902c726408c84b75dab673a90fd492e1dGeoff Levand	ehci_reset(omap_ehci);
333876e0df902c726408c84b75dab673a90fd492e1dGeoff Levand
3341fcb57d0f6e1150003d222051aaaf4bc4a9ccc94Keshava Munegowda	if (pdata->phy_reset) {
3351fcb57d0f6e1150003d222051aaaf4bc4a9ccc94Keshava Munegowda		/* Hold the PHY in RESET for enough time till
3361fcb57d0f6e1150003d222051aaaf4bc4a9ccc94Keshava Munegowda		 * PHY is settled and ready
3371fcb57d0f6e1150003d222051aaaf4bc4a9ccc94Keshava Munegowda		 */
3381fcb57d0f6e1150003d222051aaaf4bc4a9ccc94Keshava Munegowda		udelay(10);
3391fcb57d0f6e1150003d222051aaaf4bc4a9ccc94Keshava Munegowda
3401fcb57d0f6e1150003d222051aaaf4bc4a9ccc94Keshava Munegowda		if (gpio_is_valid(pdata->reset_gpio_port[0]))
3417b18389dd4fe0b178117b09d054e214297f7e677Igor Grinberg			gpio_set_value_cansleep(pdata->reset_gpio_port[0], 1);
3421fcb57d0f6e1150003d222051aaaf4bc4a9ccc94Keshava Munegowda
3431fcb57d0f6e1150003d222051aaaf4bc4a9ccc94Keshava Munegowda		if (gpio_is_valid(pdata->reset_gpio_port[1]))
3447b18389dd4fe0b178117b09d054e214297f7e677Igor Grinberg			gpio_set_value_cansleep(pdata->reset_gpio_port[1], 1);
3451fcb57d0f6e1150003d222051aaaf4bc4a9ccc94Keshava Munegowda	}
3461fcb57d0f6e1150003d222051aaaf4bc4a9ccc94Keshava Munegowda
3473aa2ae74ba630ec9b98736d64aea8e4cb490861dRuss Dill	ret = usb_add_hcd(hcd, irq, IRQF_SHARED);
3483aa2ae74ba630ec9b98736d64aea8e4cb490861dRuss Dill	if (ret) {
3493aa2ae74ba630ec9b98736d64aea8e4cb490861dRuss Dill		dev_err(dev, "failed to add hcd with err %d\n", ret);
3503aa2ae74ba630ec9b98736d64aea8e4cb490861dRuss Dill		goto err_add_hcd;
3513aa2ae74ba630ec9b98736d64aea8e4cb490861dRuss Dill	}
3523aa2ae74ba630ec9b98736d64aea8e4cb490861dRuss Dill
3533aa2ae74ba630ec9b98736d64aea8e4cb490861dRuss Dill	/* root ports should always stay powered */
3543aa2ae74ba630ec9b98736d64aea8e4cb490861dRuss Dill	ehci_port_power(omap_ehci, 1);
3553aa2ae74ba630ec9b98736d64aea8e4cb490861dRuss Dill
356354ab8567ae3107a8cbe7228c3181990ba598aacAnand Gadiyar	/* get clocks */
357354ab8567ae3107a8cbe7228c3181990ba598aacAnand Gadiyar	utmi_p1_fck = clk_get(dev, "utmi_p1_gfclk");
358354ab8567ae3107a8cbe7228c3181990ba598aacAnand Gadiyar	if (IS_ERR(utmi_p1_fck)) {
359354ab8567ae3107a8cbe7228c3181990ba598aacAnand Gadiyar		ret = PTR_ERR(utmi_p1_fck);
360354ab8567ae3107a8cbe7228c3181990ba598aacAnand Gadiyar		dev_err(dev, "utmi_p1_gfclk failed error:%d\n",	ret);
361354ab8567ae3107a8cbe7228c3181990ba598aacAnand Gadiyar		goto err_add_hcd;
362354ab8567ae3107a8cbe7228c3181990ba598aacAnand Gadiyar	}
363354ab8567ae3107a8cbe7228c3181990ba598aacAnand Gadiyar
364354ab8567ae3107a8cbe7228c3181990ba598aacAnand Gadiyar	xclk60mhsp1_ck = clk_get(dev, "xclk60mhsp1_ck");
365354ab8567ae3107a8cbe7228c3181990ba598aacAnand Gadiyar	if (IS_ERR(xclk60mhsp1_ck)) {
366354ab8567ae3107a8cbe7228c3181990ba598aacAnand Gadiyar		ret = PTR_ERR(xclk60mhsp1_ck);
367354ab8567ae3107a8cbe7228c3181990ba598aacAnand Gadiyar		dev_err(dev, "xclk60mhsp1_ck failed error:%d\n", ret);
368354ab8567ae3107a8cbe7228c3181990ba598aacAnand Gadiyar		goto err_utmi_p1_fck;
369354ab8567ae3107a8cbe7228c3181990ba598aacAnand Gadiyar	}
370354ab8567ae3107a8cbe7228c3181990ba598aacAnand Gadiyar
371354ab8567ae3107a8cbe7228c3181990ba598aacAnand Gadiyar	utmi_p2_fck = clk_get(dev, "utmi_p2_gfclk");
372354ab8567ae3107a8cbe7228c3181990ba598aacAnand Gadiyar	if (IS_ERR(utmi_p2_fck)) {
373354ab8567ae3107a8cbe7228c3181990ba598aacAnand Gadiyar		ret = PTR_ERR(utmi_p2_fck);
374354ab8567ae3107a8cbe7228c3181990ba598aacAnand Gadiyar		dev_err(dev, "utmi_p2_gfclk failed error:%d\n", ret);
375354ab8567ae3107a8cbe7228c3181990ba598aacAnand Gadiyar		goto err_xclk60mhsp1_ck;
376354ab8567ae3107a8cbe7228c3181990ba598aacAnand Gadiyar	}
377354ab8567ae3107a8cbe7228c3181990ba598aacAnand Gadiyar
378354ab8567ae3107a8cbe7228c3181990ba598aacAnand Gadiyar	xclk60mhsp2_ck = clk_get(dev, "xclk60mhsp2_ck");
379354ab8567ae3107a8cbe7228c3181990ba598aacAnand Gadiyar	if (IS_ERR(xclk60mhsp2_ck)) {
380354ab8567ae3107a8cbe7228c3181990ba598aacAnand Gadiyar		ret = PTR_ERR(xclk60mhsp2_ck);
381354ab8567ae3107a8cbe7228c3181990ba598aacAnand Gadiyar		dev_err(dev, "xclk60mhsp2_ck failed error:%d\n", ret);
382354ab8567ae3107a8cbe7228c3181990ba598aacAnand Gadiyar		goto err_utmi_p2_fck;
383354ab8567ae3107a8cbe7228c3181990ba598aacAnand Gadiyar	}
384354ab8567ae3107a8cbe7228c3181990ba598aacAnand Gadiyar
385354ab8567ae3107a8cbe7228c3181990ba598aacAnand Gadiyar	usbhost_p1_fck = clk_get(dev, "usb_host_hs_utmi_p1_clk");
386354ab8567ae3107a8cbe7228c3181990ba598aacAnand Gadiyar	if (IS_ERR(usbhost_p1_fck)) {
387354ab8567ae3107a8cbe7228c3181990ba598aacAnand Gadiyar		ret = PTR_ERR(usbhost_p1_fck);
388354ab8567ae3107a8cbe7228c3181990ba598aacAnand Gadiyar		dev_err(dev, "usbhost_p1_fck failed error:%d\n", ret);
389354ab8567ae3107a8cbe7228c3181990ba598aacAnand Gadiyar		goto err_xclk60mhsp2_ck;
390354ab8567ae3107a8cbe7228c3181990ba598aacAnand Gadiyar	}
391354ab8567ae3107a8cbe7228c3181990ba598aacAnand Gadiyar
392354ab8567ae3107a8cbe7228c3181990ba598aacAnand Gadiyar	usbhost_p2_fck = clk_get(dev, "usb_host_hs_utmi_p2_clk");
393354ab8567ae3107a8cbe7228c3181990ba598aacAnand Gadiyar	if (IS_ERR(usbhost_p2_fck)) {
394354ab8567ae3107a8cbe7228c3181990ba598aacAnand Gadiyar		ret = PTR_ERR(usbhost_p2_fck);
395354ab8567ae3107a8cbe7228c3181990ba598aacAnand Gadiyar		dev_err(dev, "usbhost_p2_fck failed error:%d\n", ret);
396354ab8567ae3107a8cbe7228c3181990ba598aacAnand Gadiyar		goto err_usbhost_p1_fck;
397354ab8567ae3107a8cbe7228c3181990ba598aacAnand Gadiyar	}
398354ab8567ae3107a8cbe7228c3181990ba598aacAnand Gadiyar
399354ab8567ae3107a8cbe7228c3181990ba598aacAnand Gadiyar	init_60m_fclk = clk_get(dev, "init_60m_fclk");
400354ab8567ae3107a8cbe7228c3181990ba598aacAnand Gadiyar	if (IS_ERR(init_60m_fclk)) {
401354ab8567ae3107a8cbe7228c3181990ba598aacAnand Gadiyar		ret = PTR_ERR(init_60m_fclk);
402354ab8567ae3107a8cbe7228c3181990ba598aacAnand Gadiyar		dev_err(dev, "init_60m_fclk failed error:%d\n", ret);
403354ab8567ae3107a8cbe7228c3181990ba598aacAnand Gadiyar		goto err_usbhost_p2_fck;
404354ab8567ae3107a8cbe7228c3181990ba598aacAnand Gadiyar	}
405354ab8567ae3107a8cbe7228c3181990ba598aacAnand Gadiyar
40654ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi	return 0;
40754ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi
408354ab8567ae3107a8cbe7228c3181990ba598aacAnand Gadiyarerr_usbhost_p2_fck:
409354ab8567ae3107a8cbe7228c3181990ba598aacAnand Gadiyar	clk_put(usbhost_p2_fck);
410354ab8567ae3107a8cbe7228c3181990ba598aacAnand Gadiyar
411354ab8567ae3107a8cbe7228c3181990ba598aacAnand Gadiyarerr_usbhost_p1_fck:
412354ab8567ae3107a8cbe7228c3181990ba598aacAnand Gadiyar	clk_put(usbhost_p1_fck);
413354ab8567ae3107a8cbe7228c3181990ba598aacAnand Gadiyar
414354ab8567ae3107a8cbe7228c3181990ba598aacAnand Gadiyarerr_xclk60mhsp2_ck:
415354ab8567ae3107a8cbe7228c3181990ba598aacAnand Gadiyar	clk_put(xclk60mhsp2_ck);
416354ab8567ae3107a8cbe7228c3181990ba598aacAnand Gadiyar
417354ab8567ae3107a8cbe7228c3181990ba598aacAnand Gadiyarerr_utmi_p2_fck:
418354ab8567ae3107a8cbe7228c3181990ba598aacAnand Gadiyar	clk_put(utmi_p2_fck);
419354ab8567ae3107a8cbe7228c3181990ba598aacAnand Gadiyar
420354ab8567ae3107a8cbe7228c3181990ba598aacAnand Gadiyarerr_xclk60mhsp1_ck:
421354ab8567ae3107a8cbe7228c3181990ba598aacAnand Gadiyar	clk_put(xclk60mhsp1_ck);
422354ab8567ae3107a8cbe7228c3181990ba598aacAnand Gadiyar
423354ab8567ae3107a8cbe7228c3181990ba598aacAnand Gadiyarerr_utmi_p1_fck:
424354ab8567ae3107a8cbe7228c3181990ba598aacAnand Gadiyar	clk_put(utmi_p1_fck);
425354ab8567ae3107a8cbe7228c3181990ba598aacAnand Gadiyar
42654ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbierr_add_hcd:
427d4aefec5daf51ebda90ebf0989598c206cf8e640Ming Lei	disable_put_regulator(pdata);
4286c984b066d84bb6e8f5a739ffb1dc4858df017a3Keshava Munegowda	pm_runtime_put_sync(dev);
42954ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi
43019403165c272cc4ed00c97973e7271714b009708Keshava Munegowdaerr_io:
431d4aefec5daf51ebda90ebf0989598c206cf8e640Ming Lei	iounmap(regs);
43254ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi	return ret;
43354ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi}
43454ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi
43554ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi
43654ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi/**
43754ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi * ehci_hcd_omap_remove - shutdown processing for EHCI HCDs
43854ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi * @pdev: USB Host Controller being removed
43954ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi *
44054ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi * Reverses the effect of usb_ehci_hcd_omap_probe(), first invoking
44154ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi * the HCD's stop() method.  It is always called from a thread
44254ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi * context, normally "rmmod", "apmd", or something similar.
44354ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi */
44454ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbistatic int ehci_hcd_omap_remove(struct platform_device *pdev)
44554ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi{
4461fcb57d0f6e1150003d222051aaaf4bc4a9ccc94Keshava Munegowda	struct device *dev				= &pdev->dev;
4471fcb57d0f6e1150003d222051aaaf4bc4a9ccc94Keshava Munegowda	struct usb_hcd *hcd				= dev_get_drvdata(dev);
4481fcb57d0f6e1150003d222051aaaf4bc4a9ccc94Keshava Munegowda	struct ehci_hcd_omap_platform_data *pdata	= dev->platform_data;
44954ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi
45054ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi	usb_remove_hcd(hcd);
451d4aefec5daf51ebda90ebf0989598c206cf8e640Ming Lei	disable_put_regulator(dev->platform_data);
452d4aefec5daf51ebda90ebf0989598c206cf8e640Ming Lei	iounmap(hcd->regs);
45354ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi	usb_put_hcd(hcd);
454354ab8567ae3107a8cbe7228c3181990ba598aacAnand Gadiyar
455354ab8567ae3107a8cbe7228c3181990ba598aacAnand Gadiyar	clk_put(utmi_p1_fck);
456354ab8567ae3107a8cbe7228c3181990ba598aacAnand Gadiyar	clk_put(utmi_p2_fck);
457354ab8567ae3107a8cbe7228c3181990ba598aacAnand Gadiyar	clk_put(xclk60mhsp1_ck);
458354ab8567ae3107a8cbe7228c3181990ba598aacAnand Gadiyar	clk_put(xclk60mhsp2_ck);
459354ab8567ae3107a8cbe7228c3181990ba598aacAnand Gadiyar	clk_put(usbhost_p1_fck);
460354ab8567ae3107a8cbe7228c3181990ba598aacAnand Gadiyar	clk_put(usbhost_p2_fck);
461354ab8567ae3107a8cbe7228c3181990ba598aacAnand Gadiyar	clk_put(init_60m_fclk);
462354ab8567ae3107a8cbe7228c3181990ba598aacAnand Gadiyar
4636c984b066d84bb6e8f5a739ffb1dc4858df017a3Keshava Munegowda	pm_runtime_put_sync(dev);
4646c984b066d84bb6e8f5a739ffb1dc4858df017a3Keshava Munegowda	pm_runtime_disable(dev);
4656c984b066d84bb6e8f5a739ffb1dc4858df017a3Keshava Munegowda
4661fcb57d0f6e1150003d222051aaaf4bc4a9ccc94Keshava Munegowda	if (pdata->phy_reset) {
4671fcb57d0f6e1150003d222051aaaf4bc4a9ccc94Keshava Munegowda		if (gpio_is_valid(pdata->reset_gpio_port[0]))
4681fcb57d0f6e1150003d222051aaaf4bc4a9ccc94Keshava Munegowda			gpio_free(pdata->reset_gpio_port[0]);
4691fcb57d0f6e1150003d222051aaaf4bc4a9ccc94Keshava Munegowda
4701fcb57d0f6e1150003d222051aaaf4bc4a9ccc94Keshava Munegowda		if (gpio_is_valid(pdata->reset_gpio_port[1]))
4711fcb57d0f6e1150003d222051aaaf4bc4a9ccc94Keshava Munegowda			gpio_free(pdata->reset_gpio_port[1]);
4721fcb57d0f6e1150003d222051aaaf4bc4a9ccc94Keshava Munegowda	}
47354ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi	return 0;
47454ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi}
47554ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi
47654ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbistatic void ehci_hcd_omap_shutdown(struct platform_device *pdev)
47754ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi{
47819403165c272cc4ed00c97973e7271714b009708Keshava Munegowda	struct usb_hcd *hcd = dev_get_drvdata(&pdev->dev);
47954ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi
48054ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi	if (hcd->driver->shutdown)
48154ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi		hcd->driver->shutdown(hcd);
48254ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi}
48354ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi
48454ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbistatic struct platform_driver ehci_hcd_omap_driver = {
48554ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi	.probe			= ehci_hcd_omap_probe,
48654ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi	.remove			= ehci_hcd_omap_remove,
48754ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi	.shutdown		= ehci_hcd_omap_shutdown,
48854ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi	/*.suspend		= ehci_hcd_omap_suspend, */
48954ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi	/*.resume		= ehci_hcd_omap_resume, */
49054ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi	.driver = {
49154ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi		.name		= "ehci-omap",
49254ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi	}
49354ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi};
49454ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi
49554ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi/*-------------------------------------------------------------------------*/
49654ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi
49754ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbistatic const struct hc_driver ehci_omap_hc_driver = {
49854ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi	.description		= hcd_name,
49954ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi	.product_desc		= "OMAP-EHCI Host Controller",
50054ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi	.hcd_priv_size		= sizeof(struct ehci_hcd),
50154ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi
50254ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi	/*
50354ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi	 * generic hardware linkage
50454ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi	 */
50554ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi	.irq			= ehci_irq,
50654ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi	.flags			= HCD_MEMORY | HCD_USB2,
50754ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi
50854ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi	/*
50954ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi	 * basic lifecycle operations
51054ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi	 */
51154ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi	.reset			= ehci_init,
51254ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi	.start			= ehci_run,
51354ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi	.stop			= ehci_stop,
51454ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi	.shutdown		= ehci_shutdown,
51554ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi
51654ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi	/*
51754ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi	 * managing i/o requests and associated device resources
51854ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi	 */
51954ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi	.urb_enqueue		= ehci_urb_enqueue,
52054ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi	.urb_dequeue		= ehci_urb_dequeue,
52154ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi	.endpoint_disable	= ehci_endpoint_disable,
52254ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi	.endpoint_reset		= ehci_endpoint_reset,
52354ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi
52454ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi	/*
52554ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi	 * scheduling support
52654ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi	 */
52754ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi	.get_frame_number	= ehci_get_frame,
52854ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi
52954ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi	/*
53054ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi	 * root hub support
53154ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi	 */
53254ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi	.hub_status_data	= ehci_hub_status_data,
533354ab8567ae3107a8cbe7228c3181990ba598aacAnand Gadiyar	.hub_control		= omap_ehci_hub_control,
53454ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi	.bus_suspend		= ehci_bus_suspend,
53554ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi	.bus_resume		= ehci_bus_resume,
53654ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi
53754ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi	.clear_tt_buffer_complete = ehci_clear_tt_buffer_complete,
53854ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi};
53954ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi
54054ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe BalbiMODULE_ALIAS("platform:omap-ehci");
54154ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe BalbiMODULE_AUTHOR("Texas Instruments, Inc.");
54254ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe BalbiMODULE_AUTHOR("Felipe Balbi <felipe.balbi@nokia.com>");
54354ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi
544