ehci-omap.c revision 04753523266629b1cd0518091da1658755787198
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>
426e3d4bec6b1e0829ed8b23be750762255f225019Keshava Munegowda#include <linux/regulator/consumer.h>
436c984b066d84bb6e8f5a739ffb1dc4858df017a3Keshava Munegowda#include <linux/pm_runtime.h>
441fcb57d0f6e1150003d222051aaaf4bc4a9ccc94Keshava Munegowda#include <linux/gpio.h>
45354ab8567ae3107a8cbe7228c3181990ba598aacAnand Gadiyar#include <linux/clk.h>
4654ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi
47e8c4a7acc9ec0ee82feedcdc3c6d0ee44d67918aFelipe Balbi#include <linux/platform_data/usb-omap.h>
48e8c4a7acc9ec0ee82feedcdc3c6d0ee44d67918aFelipe Balbi
4954ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi/* EHCI Register Set */
50572538dee7a4b25f3e77fdc11d20dbb753ecf367Anand Gadiyar#define EHCI_INSNREG04					(0xA0)
51572538dee7a4b25f3e77fdc11d20dbb753ecf367Anand Gadiyar#define EHCI_INSNREG04_DISABLE_UNSUSPEND		(1 << 5)
5254ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi#define	EHCI_INSNREG05_ULPI				(0xA4)
5354ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi#define	EHCI_INSNREG05_ULPI_CONTROL_SHIFT		31
5454ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi#define	EHCI_INSNREG05_ULPI_PORTSEL_SHIFT		24
5554ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi#define	EHCI_INSNREG05_ULPI_OPSEL_SHIFT			22
5654ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi#define	EHCI_INSNREG05_ULPI_REGADD_SHIFT		16
5754ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi#define	EHCI_INSNREG05_ULPI_EXTREGADD_SHIFT		8
5854ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi#define	EHCI_INSNREG05_ULPI_WRDATA_SHIFT		0
5954ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi
6019403165c272cc4ed00c97973e7271714b009708Keshava Munegowda/*-------------------------------------------------------------------------*/
614792a15bf0f388838c3e16636f961c99bc2f3572Anand Gadiyar
6219403165c272cc4ed00c97973e7271714b009708Keshava Munegowdastatic const struct hc_driver ehci_omap_hc_driver;
634792a15bf0f388838c3e16636f961c99bc2f3572Anand Gadiyar
64a42ccdc14de388a35ad0e8057543369351395eb9Anand Gadiyar
6519403165c272cc4ed00c97973e7271714b009708Keshava Munegowdastatic inline void ehci_write(void __iomem *base, u32 reg, u32 val)
6654ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi{
6754ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi	__raw_writel(val, base + reg);
6854ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi}
6954ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi
7019403165c272cc4ed00c97973e7271714b009708Keshava Munegowdastatic inline u32 ehci_read(void __iomem *base, u32 reg)
7154ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi{
7254ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi	return __raw_readl(base + reg);
7354ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi}
7454ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi
75354ab8567ae3107a8cbe7228c3181990ba598aacAnand Gadiyar
76ba5952e0711b14d8d4fe172671f8aa6091ace3eeMing Leistatic void omap_ehci_soft_phy_reset(struct usb_hcd *hcd, u8 port)
775aa4af2ce6a0643f32d47f21614817792b85298dAjay Kumar Gupta{
785aa4af2ce6a0643f32d47f21614817792b85298dAjay Kumar Gupta	unsigned long timeout = jiffies + msecs_to_jiffies(1000);
795aa4af2ce6a0643f32d47f21614817792b85298dAjay Kumar Gupta	unsigned reg = 0;
805aa4af2ce6a0643f32d47f21614817792b85298dAjay Kumar Gupta
815aa4af2ce6a0643f32d47f21614817792b85298dAjay Kumar Gupta	reg = ULPI_FUNC_CTRL_RESET
825aa4af2ce6a0643f32d47f21614817792b85298dAjay Kumar Gupta		/* FUNCTION_CTRL_SET register */
835aa4af2ce6a0643f32d47f21614817792b85298dAjay Kumar Gupta		| (ULPI_SET(ULPI_FUNC_CTRL) << EHCI_INSNREG05_ULPI_REGADD_SHIFT)
845aa4af2ce6a0643f32d47f21614817792b85298dAjay Kumar Gupta		/* Write */
855aa4af2ce6a0643f32d47f21614817792b85298dAjay Kumar Gupta		| (2 << EHCI_INSNREG05_ULPI_OPSEL_SHIFT)
865aa4af2ce6a0643f32d47f21614817792b85298dAjay Kumar Gupta		/* PORTn */
875aa4af2ce6a0643f32d47f21614817792b85298dAjay Kumar Gupta		| ((port + 1) << EHCI_INSNREG05_ULPI_PORTSEL_SHIFT)
885aa4af2ce6a0643f32d47f21614817792b85298dAjay Kumar Gupta		/* start ULPI access*/
895aa4af2ce6a0643f32d47f21614817792b85298dAjay Kumar Gupta		| (1 << EHCI_INSNREG05_ULPI_CONTROL_SHIFT);
905aa4af2ce6a0643f32d47f21614817792b85298dAjay Kumar Gupta
9119403165c272cc4ed00c97973e7271714b009708Keshava Munegowda	ehci_write(hcd->regs, EHCI_INSNREG05_ULPI, reg);
925aa4af2ce6a0643f32d47f21614817792b85298dAjay Kumar Gupta
935aa4af2ce6a0643f32d47f21614817792b85298dAjay Kumar Gupta	/* Wait for ULPI access completion */
9419403165c272cc4ed00c97973e7271714b009708Keshava Munegowda	while ((ehci_read(hcd->regs, EHCI_INSNREG05_ULPI)
955aa4af2ce6a0643f32d47f21614817792b85298dAjay Kumar Gupta			& (1 << EHCI_INSNREG05_ULPI_CONTROL_SHIFT))) {
965aa4af2ce6a0643f32d47f21614817792b85298dAjay Kumar Gupta		cpu_relax();
975aa4af2ce6a0643f32d47f21614817792b85298dAjay Kumar Gupta
985aa4af2ce6a0643f32d47f21614817792b85298dAjay Kumar Gupta		if (time_after(jiffies, timeout)) {
99ba5952e0711b14d8d4fe172671f8aa6091ace3eeMing Lei			dev_dbg(hcd->self.controller,
100ba5952e0711b14d8d4fe172671f8aa6091ace3eeMing Lei					"phy reset operation timed out\n");
1015aa4af2ce6a0643f32d47f21614817792b85298dAjay Kumar Gupta			break;
1025aa4af2ce6a0643f32d47f21614817792b85298dAjay Kumar Gupta		}
1035aa4af2ce6a0643f32d47f21614817792b85298dAjay Kumar Gupta	}
1045aa4af2ce6a0643f32d47f21614817792b85298dAjay Kumar Gupta}
1055aa4af2ce6a0643f32d47f21614817792b85298dAjay Kumar Gupta
1061a49e2ac9651df7349867a5cf44e2c83de1046afAlan Sternstatic int omap_ehci_init(struct usb_hcd *hcd)
1071a49e2ac9651df7349867a5cf44e2c83de1046afAlan Stern{
1081a49e2ac9651df7349867a5cf44e2c83de1046afAlan Stern	struct ehci_hcd		*ehci = hcd_to_ehci(hcd);
1091a49e2ac9651df7349867a5cf44e2c83de1046afAlan Stern	int			rc;
1101a49e2ac9651df7349867a5cf44e2c83de1046afAlan Stern	struct ehci_hcd_omap_platform_data	*pdata;
1111a49e2ac9651df7349867a5cf44e2c83de1046afAlan Stern
1121a49e2ac9651df7349867a5cf44e2c83de1046afAlan Stern	pdata = hcd->self.controller->platform_data;
1133e701cdfe601306817604ca7f79f1d1c1088007cLinus Torvalds
1143e701cdfe601306817604ca7f79f1d1c1088007cLinus Torvalds	/* Hold PHYs in reset while initializing EHCI controller */
1151a49e2ac9651df7349867a5cf44e2c83de1046afAlan Stern	if (pdata->phy_reset) {
1161a49e2ac9651df7349867a5cf44e2c83de1046afAlan Stern		if (gpio_is_valid(pdata->reset_gpio_port[0]))
1173e701cdfe601306817604ca7f79f1d1c1088007cLinus Torvalds			gpio_set_value_cansleep(pdata->reset_gpio_port[0], 0);
1181a49e2ac9651df7349867a5cf44e2c83de1046afAlan Stern
1191a49e2ac9651df7349867a5cf44e2c83de1046afAlan Stern		if (gpio_is_valid(pdata->reset_gpio_port[1]))
1203e701cdfe601306817604ca7f79f1d1c1088007cLinus Torvalds			gpio_set_value_cansleep(pdata->reset_gpio_port[1], 0);
1211a49e2ac9651df7349867a5cf44e2c83de1046afAlan Stern
1221a49e2ac9651df7349867a5cf44e2c83de1046afAlan Stern		/* Hold the PHY in RESET for enough time till DIR is high */
1231a49e2ac9651df7349867a5cf44e2c83de1046afAlan Stern		udelay(10);
1241a49e2ac9651df7349867a5cf44e2c83de1046afAlan Stern	}
1251a49e2ac9651df7349867a5cf44e2c83de1046afAlan Stern
1261a49e2ac9651df7349867a5cf44e2c83de1046afAlan Stern	/* Soft reset the PHY using PHY reset command over ULPI */
1271a49e2ac9651df7349867a5cf44e2c83de1046afAlan Stern	if (pdata->port_mode[0] == OMAP_EHCI_PORT_MODE_PHY)
128ba5952e0711b14d8d4fe172671f8aa6091ace3eeMing Lei		omap_ehci_soft_phy_reset(hcd, 0);
1291a49e2ac9651df7349867a5cf44e2c83de1046afAlan Stern	if (pdata->port_mode[1] == OMAP_EHCI_PORT_MODE_PHY)
130ba5952e0711b14d8d4fe172671f8aa6091ace3eeMing Lei		omap_ehci_soft_phy_reset(hcd, 1);
1311a49e2ac9651df7349867a5cf44e2c83de1046afAlan Stern
1321a49e2ac9651df7349867a5cf44e2c83de1046afAlan Stern	/* we know this is the memory we want, no need to ioremap again */
1331a49e2ac9651df7349867a5cf44e2c83de1046afAlan Stern	ehci->caps = hcd->regs;
1341a49e2ac9651df7349867a5cf44e2c83de1046afAlan Stern
1351a49e2ac9651df7349867a5cf44e2c83de1046afAlan Stern	rc = ehci_setup(hcd);
1361a49e2ac9651df7349867a5cf44e2c83de1046afAlan Stern
1371a49e2ac9651df7349867a5cf44e2c83de1046afAlan Stern	if (pdata->phy_reset) {
1381a49e2ac9651df7349867a5cf44e2c83de1046afAlan Stern		/* Hold the PHY in RESET for enough time till
1391a49e2ac9651df7349867a5cf44e2c83de1046afAlan Stern		 * PHY is settled and ready
1401a49e2ac9651df7349867a5cf44e2c83de1046afAlan Stern		 */
1411a49e2ac9651df7349867a5cf44e2c83de1046afAlan Stern		udelay(10);
1421a49e2ac9651df7349867a5cf44e2c83de1046afAlan Stern
1431a49e2ac9651df7349867a5cf44e2c83de1046afAlan Stern		if (gpio_is_valid(pdata->reset_gpio_port[0]))
1441a49e2ac9651df7349867a5cf44e2c83de1046afAlan Stern			gpio_set_value_cansleep(pdata->reset_gpio_port[0], 1);
1451a49e2ac9651df7349867a5cf44e2c83de1046afAlan Stern
1461a49e2ac9651df7349867a5cf44e2c83de1046afAlan Stern		if (gpio_is_valid(pdata->reset_gpio_port[1]))
1471a49e2ac9651df7349867a5cf44e2c83de1046afAlan Stern			gpio_set_value_cansleep(pdata->reset_gpio_port[1], 1);
1481a49e2ac9651df7349867a5cf44e2c83de1046afAlan Stern	}
1491a49e2ac9651df7349867a5cf44e2c83de1046afAlan Stern
1501a49e2ac9651df7349867a5cf44e2c83de1046afAlan Stern	return rc;
1511a49e2ac9651df7349867a5cf44e2c83de1046afAlan Stern}
1521a49e2ac9651df7349867a5cf44e2c83de1046afAlan Stern
153d4aefec5daf51ebda90ebf0989598c206cf8e640Ming Leistatic void disable_put_regulator(
154d4aefec5daf51ebda90ebf0989598c206cf8e640Ming Lei		struct ehci_hcd_omap_platform_data *pdata)
155d4aefec5daf51ebda90ebf0989598c206cf8e640Ming Lei{
156d4aefec5daf51ebda90ebf0989598c206cf8e640Ming Lei	int i;
157d4aefec5daf51ebda90ebf0989598c206cf8e640Ming Lei
158d4aefec5daf51ebda90ebf0989598c206cf8e640Ming Lei	for (i = 0 ; i < OMAP3_HS_USB_PORTS ; i++) {
159d4aefec5daf51ebda90ebf0989598c206cf8e640Ming Lei		if (pdata->regulator[i]) {
160d4aefec5daf51ebda90ebf0989598c206cf8e640Ming Lei			regulator_disable(pdata->regulator[i]);
161d4aefec5daf51ebda90ebf0989598c206cf8e640Ming Lei			regulator_put(pdata->regulator[i]);
162d4aefec5daf51ebda90ebf0989598c206cf8e640Ming Lei		}
163d4aefec5daf51ebda90ebf0989598c206cf8e640Ming Lei	}
164d4aefec5daf51ebda90ebf0989598c206cf8e640Ming Lei}
16554ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi
16654ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi/* configure so an HC device and id are always provided */
16754ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi/* always called with process context; sleeping is OK */
16854ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi
16954ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi/**
17054ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi * ehci_hcd_omap_probe - initialize TI-based HCDs
17154ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi *
17254ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi * Allocates basic resources for this USB host controller, and
17354ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi * then invokes the start() method for the HCD associated with it
17454ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi * through the hotplug entry's driver_data.
17554ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi */
17654ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbistatic int ehci_hcd_omap_probe(struct platform_device *pdev)
17754ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi{
17819403165c272cc4ed00c97973e7271714b009708Keshava Munegowda	struct device				*dev = &pdev->dev;
17919403165c272cc4ed00c97973e7271714b009708Keshava Munegowda	struct ehci_hcd_omap_platform_data	*pdata = dev->platform_data;
18019403165c272cc4ed00c97973e7271714b009708Keshava Munegowda	struct resource				*res;
18119403165c272cc4ed00c97973e7271714b009708Keshava Munegowda	struct usb_hcd				*hcd;
18219403165c272cc4ed00c97973e7271714b009708Keshava Munegowda	void __iomem				*regs;
18319403165c272cc4ed00c97973e7271714b009708Keshava Munegowda	int					ret = -ENODEV;
18419403165c272cc4ed00c97973e7271714b009708Keshava Munegowda	int					irq;
1856e3d4bec6b1e0829ed8b23be750762255f225019Keshava Munegowda	int					i;
1866e3d4bec6b1e0829ed8b23be750762255f225019Keshava Munegowda	char					supply[7];
18754ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi
18819403165c272cc4ed00c97973e7271714b009708Keshava Munegowda	if (usb_disabled())
18919403165c272cc4ed00c97973e7271714b009708Keshava Munegowda		return -ENODEV;
19054ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi
19119403165c272cc4ed00c97973e7271714b009708Keshava Munegowda	if (!dev->parent) {
19219403165c272cc4ed00c97973e7271714b009708Keshava Munegowda		dev_err(dev, "Missing parent device\n");
19319403165c272cc4ed00c97973e7271714b009708Keshava Munegowda		return -ENODEV;
19454ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi	}
19554ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi
19619403165c272cc4ed00c97973e7271714b009708Keshava Munegowda	irq = platform_get_irq_byname(pdev, "ehci-irq");
19719403165c272cc4ed00c97973e7271714b009708Keshava Munegowda	if (irq < 0) {
19819403165c272cc4ed00c97973e7271714b009708Keshava Munegowda		dev_err(dev, "EHCI irq failed\n");
19919403165c272cc4ed00c97973e7271714b009708Keshava Munegowda		return -ENODEV;
20019403165c272cc4ed00c97973e7271714b009708Keshava Munegowda	}
20154ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi
20219403165c272cc4ed00c97973e7271714b009708Keshava Munegowda	res =  platform_get_resource_byname(pdev,
20319403165c272cc4ed00c97973e7271714b009708Keshava Munegowda				IORESOURCE_MEM, "ehci");
20419403165c272cc4ed00c97973e7271714b009708Keshava Munegowda	if (!res) {
20519403165c272cc4ed00c97973e7271714b009708Keshava Munegowda		dev_err(dev, "UHH EHCI get resource failed\n");
20619403165c272cc4ed00c97973e7271714b009708Keshava Munegowda		return -ENODEV;
20719403165c272cc4ed00c97973e7271714b009708Keshava Munegowda	}
20819403165c272cc4ed00c97973e7271714b009708Keshava Munegowda
20919403165c272cc4ed00c97973e7271714b009708Keshava Munegowda	regs = ioremap(res->start, resource_size(res));
21019403165c272cc4ed00c97973e7271714b009708Keshava Munegowda	if (!regs) {
21119403165c272cc4ed00c97973e7271714b009708Keshava Munegowda		dev_err(dev, "UHH EHCI ioremap failed\n");
21219403165c272cc4ed00c97973e7271714b009708Keshava Munegowda		return -ENOMEM;
21354ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi	}
21454ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi
21519403165c272cc4ed00c97973e7271714b009708Keshava Munegowda	hcd = usb_create_hcd(&ehci_omap_hc_driver, dev,
21619403165c272cc4ed00c97973e7271714b009708Keshava Munegowda			dev_name(dev));
21754ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi	if (!hcd) {
21819403165c272cc4ed00c97973e7271714b009708Keshava Munegowda		dev_err(dev, "failed to create hcd with err %d\n", ret);
21954ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi		ret = -ENOMEM;
22019403165c272cc4ed00c97973e7271714b009708Keshava Munegowda		goto err_io;
22154ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi	}
22254ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi
22354ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi	hcd->rsrc_start = res->start;
22454ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi	hcd->rsrc_len = resource_size(res);
22519403165c272cc4ed00c97973e7271714b009708Keshava Munegowda	hcd->regs = regs;
22654ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi
2276e3d4bec6b1e0829ed8b23be750762255f225019Keshava Munegowda	/* get ehci regulator and enable */
2286e3d4bec6b1e0829ed8b23be750762255f225019Keshava Munegowda	for (i = 0 ; i < OMAP3_HS_USB_PORTS ; i++) {
2296e3d4bec6b1e0829ed8b23be750762255f225019Keshava Munegowda		if (pdata->port_mode[i] != OMAP_EHCI_PORT_MODE_PHY) {
2306e3d4bec6b1e0829ed8b23be750762255f225019Keshava Munegowda			pdata->regulator[i] = NULL;
2316e3d4bec6b1e0829ed8b23be750762255f225019Keshava Munegowda			continue;
2326e3d4bec6b1e0829ed8b23be750762255f225019Keshava Munegowda		}
2336e3d4bec6b1e0829ed8b23be750762255f225019Keshava Munegowda		snprintf(supply, sizeof(supply), "hsusb%d", i);
2346e3d4bec6b1e0829ed8b23be750762255f225019Keshava Munegowda		pdata->regulator[i] = regulator_get(dev, supply);
2356e3d4bec6b1e0829ed8b23be750762255f225019Keshava Munegowda		if (IS_ERR(pdata->regulator[i])) {
2366e3d4bec6b1e0829ed8b23be750762255f225019Keshava Munegowda			pdata->regulator[i] = NULL;
2376e3d4bec6b1e0829ed8b23be750762255f225019Keshava Munegowda			dev_dbg(dev,
2386e3d4bec6b1e0829ed8b23be750762255f225019Keshava Munegowda			"failed to get ehci port%d regulator\n", i);
2396e3d4bec6b1e0829ed8b23be750762255f225019Keshava Munegowda		} else {
2406e3d4bec6b1e0829ed8b23be750762255f225019Keshava Munegowda			regulator_enable(pdata->regulator[i]);
2416e3d4bec6b1e0829ed8b23be750762255f225019Keshava Munegowda		}
2426e3d4bec6b1e0829ed8b23be750762255f225019Keshava Munegowda	}
2436e3d4bec6b1e0829ed8b23be750762255f225019Keshava Munegowda
2446c984b066d84bb6e8f5a739ffb1dc4858df017a3Keshava Munegowda	pm_runtime_enable(dev);
2456c984b066d84bb6e8f5a739ffb1dc4858df017a3Keshava Munegowda	pm_runtime_get_sync(dev);
24654ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi
24719403165c272cc4ed00c97973e7271714b009708Keshava Munegowda	/*
24819403165c272cc4ed00c97973e7271714b009708Keshava Munegowda	 * An undocumented "feature" in the OMAP3 EHCI controller,
24919403165c272cc4ed00c97973e7271714b009708Keshava Munegowda	 * causes suspended ports to be taken out of suspend when
25019403165c272cc4ed00c97973e7271714b009708Keshava Munegowda	 * the USBCMD.Run/Stop bit is cleared (for example when
25119403165c272cc4ed00c97973e7271714b009708Keshava Munegowda	 * we do ehci_bus_suspend).
25219403165c272cc4ed00c97973e7271714b009708Keshava Munegowda	 * This breaks suspend-resume if the root-hub is allowed
25319403165c272cc4ed00c97973e7271714b009708Keshava Munegowda	 * to suspend. Writing 1 to this undocumented register bit
25419403165c272cc4ed00c97973e7271714b009708Keshava Munegowda	 * disables this feature and restores normal behavior.
25519403165c272cc4ed00c97973e7271714b009708Keshava Munegowda	 */
25619403165c272cc4ed00c97973e7271714b009708Keshava Munegowda	ehci_write(regs, EHCI_INSNREG04,
25719403165c272cc4ed00c97973e7271714b009708Keshava Munegowda				EHCI_INSNREG04_DISABLE_UNSUSPEND);
25854ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi
2593aa2ae74ba630ec9b98736d64aea8e4cb490861dRuss Dill	ret = usb_add_hcd(hcd, irq, IRQF_SHARED);
2603aa2ae74ba630ec9b98736d64aea8e4cb490861dRuss Dill	if (ret) {
2613aa2ae74ba630ec9b98736d64aea8e4cb490861dRuss Dill		dev_err(dev, "failed to add hcd with err %d\n", ret);
262984e97483a143f95d861b7218161ae033df293abRuss Dill		goto err_pm_runtime;
2633aa2ae74ba630ec9b98736d64aea8e4cb490861dRuss Dill	}
2643aa2ae74ba630ec9b98736d64aea8e4cb490861dRuss Dill
265354ab8567ae3107a8cbe7228c3181990ba598aacAnand Gadiyar
26654ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi	return 0;
26754ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi
268984e97483a143f95d861b7218161ae033df293abRuss Dillerr_pm_runtime:
269d4aefec5daf51ebda90ebf0989598c206cf8e640Ming Lei	disable_put_regulator(pdata);
2706c984b066d84bb6e8f5a739ffb1dc4858df017a3Keshava Munegowda	pm_runtime_put_sync(dev);
271984e97483a143f95d861b7218161ae033df293abRuss Dill	usb_put_hcd(hcd);
27254ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi
27319403165c272cc4ed00c97973e7271714b009708Keshava Munegowdaerr_io:
274d4aefec5daf51ebda90ebf0989598c206cf8e640Ming Lei	iounmap(regs);
27554ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi	return ret;
27654ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi}
27754ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi
27854ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi
27954ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi/**
28054ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi * ehci_hcd_omap_remove - shutdown processing for EHCI HCDs
28154ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi * @pdev: USB Host Controller being removed
28254ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi *
28354ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi * Reverses the effect of usb_ehci_hcd_omap_probe(), first invoking
28454ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi * the HCD's stop() method.  It is always called from a thread
28554ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi * context, normally "rmmod", "apmd", or something similar.
28654ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi */
28754ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbistatic int ehci_hcd_omap_remove(struct platform_device *pdev)
28854ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi{
2891fcb57d0f6e1150003d222051aaaf4bc4a9ccc94Keshava Munegowda	struct device *dev				= &pdev->dev;
2901fcb57d0f6e1150003d222051aaaf4bc4a9ccc94Keshava Munegowda	struct usb_hcd *hcd				= dev_get_drvdata(dev);
29154ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi
29254ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi	usb_remove_hcd(hcd);
293d4aefec5daf51ebda90ebf0989598c206cf8e640Ming Lei	disable_put_regulator(dev->platform_data);
294d4aefec5daf51ebda90ebf0989598c206cf8e640Ming Lei	iounmap(hcd->regs);
29554ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi	usb_put_hcd(hcd);
296354ab8567ae3107a8cbe7228c3181990ba598aacAnand Gadiyar
2976c984b066d84bb6e8f5a739ffb1dc4858df017a3Keshava Munegowda	pm_runtime_put_sync(dev);
2986c984b066d84bb6e8f5a739ffb1dc4858df017a3Keshava Munegowda	pm_runtime_disable(dev);
2996c984b066d84bb6e8f5a739ffb1dc4858df017a3Keshava Munegowda
30054ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi	return 0;
30154ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi}
30254ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi
30354ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbistatic void ehci_hcd_omap_shutdown(struct platform_device *pdev)
30454ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi{
30519403165c272cc4ed00c97973e7271714b009708Keshava Munegowda	struct usb_hcd *hcd = dev_get_drvdata(&pdev->dev);
30654ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi
30754ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi	if (hcd->driver->shutdown)
30854ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi		hcd->driver->shutdown(hcd);
30954ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi}
31054ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi
31154ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbistatic struct platform_driver ehci_hcd_omap_driver = {
31254ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi	.probe			= ehci_hcd_omap_probe,
31354ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi	.remove			= ehci_hcd_omap_remove,
31454ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi	.shutdown		= ehci_hcd_omap_shutdown,
31554ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi	/*.suspend		= ehci_hcd_omap_suspend, */
31654ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi	/*.resume		= ehci_hcd_omap_resume, */
31754ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi	.driver = {
31854ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi		.name		= "ehci-omap",
31954ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi	}
32054ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi};
32154ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi
32254ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi/*-------------------------------------------------------------------------*/
32354ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi
32454ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbistatic const struct hc_driver ehci_omap_hc_driver = {
32554ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi	.description		= hcd_name,
32654ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi	.product_desc		= "OMAP-EHCI Host Controller",
32754ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi	.hcd_priv_size		= sizeof(struct ehci_hcd),
32854ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi
32954ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi	/*
33054ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi	 * generic hardware linkage
33154ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi	 */
33254ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi	.irq			= ehci_irq,
33354ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi	.flags			= HCD_MEMORY | HCD_USB2,
33454ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi
33554ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi	/*
33654ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi	 * basic lifecycle operations
33754ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi	 */
3381a49e2ac9651df7349867a5cf44e2c83de1046afAlan Stern	.reset			= omap_ehci_init,
33954ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi	.start			= ehci_run,
34054ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi	.stop			= ehci_stop,
34154ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi	.shutdown		= ehci_shutdown,
34254ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi
34354ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi	/*
34454ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi	 * managing i/o requests and associated device resources
34554ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi	 */
34654ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi	.urb_enqueue		= ehci_urb_enqueue,
34754ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi	.urb_dequeue		= ehci_urb_dequeue,
34854ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi	.endpoint_disable	= ehci_endpoint_disable,
34954ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi	.endpoint_reset		= ehci_endpoint_reset,
35054ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi
35154ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi	/*
35254ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi	 * scheduling support
35354ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi	 */
35454ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi	.get_frame_number	= ehci_get_frame,
35554ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi
35654ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi	/*
35754ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi	 * root hub support
35854ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi	 */
35954ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi	.hub_status_data	= ehci_hub_status_data,
360872c495dd0f9d1f48814a8ee80c2c7b3b7c3b4d9Keshava Munegowda	.hub_control		= ehci_hub_control,
36154ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi	.bus_suspend		= ehci_bus_suspend,
36254ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi	.bus_resume		= ehci_bus_resume,
36354ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi
36454ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi	.clear_tt_buffer_complete = ehci_clear_tt_buffer_complete,
36554ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi};
36654ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi
36704753523266629b1cd0518091da1658755787198Roger QuadrosMODULE_ALIAS("platform:ehci-omap");
36854ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe BalbiMODULE_AUTHOR("Texas Instruments, Inc.");
36954ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe BalbiMODULE_AUTHOR("Felipe Balbi <felipe.balbi@nokia.com>");
37054ab2b02ef6a454b4cca969f546d0dd43fec7308Felipe Balbi
371