xref: /OK3568_Linux_fs/kernel/drivers/mfd/omap-usb-tll.c (revision 4882a59341e53eb6f0b4789bf948001014eff981)
1*4882a593Smuzhiyun // SPDX-License-Identifier: GPL-2.0-only
2*4882a593Smuzhiyun /**
3*4882a593Smuzhiyun  * omap-usb-tll.c - The USB TLL driver for OMAP EHCI & OHCI
4*4882a593Smuzhiyun  *
5*4882a593Smuzhiyun  * Copyright (C) 2012-2013 Texas Instruments Incorporated - https://www.ti.com
6*4882a593Smuzhiyun  * Author: Keshava Munegowda <keshava_mgowda@ti.com>
7*4882a593Smuzhiyun  * Author: Roger Quadros <rogerq@ti.com>
8*4882a593Smuzhiyun  */
9*4882a593Smuzhiyun #include <linux/kernel.h>
10*4882a593Smuzhiyun #include <linux/module.h>
11*4882a593Smuzhiyun #include <linux/types.h>
12*4882a593Smuzhiyun #include <linux/slab.h>
13*4882a593Smuzhiyun #include <linux/spinlock.h>
14*4882a593Smuzhiyun #include <linux/platform_device.h>
15*4882a593Smuzhiyun #include <linux/clk.h>
16*4882a593Smuzhiyun #include <linux/io.h>
17*4882a593Smuzhiyun #include <linux/err.h>
18*4882a593Smuzhiyun #include <linux/pm_runtime.h>
19*4882a593Smuzhiyun #include <linux/platform_data/usb-omap.h>
20*4882a593Smuzhiyun #include <linux/of.h>
21*4882a593Smuzhiyun 
22*4882a593Smuzhiyun #include "omap-usb.h"
23*4882a593Smuzhiyun 
24*4882a593Smuzhiyun #define USBTLL_DRIVER_NAME	"usbhs_tll"
25*4882a593Smuzhiyun 
26*4882a593Smuzhiyun /* TLL Register Set */
27*4882a593Smuzhiyun #define	OMAP_USBTLL_REVISION				(0x00)
28*4882a593Smuzhiyun #define	OMAP_USBTLL_SYSCONFIG				(0x10)
29*4882a593Smuzhiyun #define	OMAP_USBTLL_SYSCONFIG_CACTIVITY			(1 << 8)
30*4882a593Smuzhiyun #define	OMAP_USBTLL_SYSCONFIG_SIDLEMODE			(1 << 3)
31*4882a593Smuzhiyun #define	OMAP_USBTLL_SYSCONFIG_ENAWAKEUP			(1 << 2)
32*4882a593Smuzhiyun #define	OMAP_USBTLL_SYSCONFIG_SOFTRESET			(1 << 1)
33*4882a593Smuzhiyun #define	OMAP_USBTLL_SYSCONFIG_AUTOIDLE			(1 << 0)
34*4882a593Smuzhiyun 
35*4882a593Smuzhiyun #define	OMAP_USBTLL_SYSSTATUS				(0x14)
36*4882a593Smuzhiyun #define	OMAP_USBTLL_SYSSTATUS_RESETDONE			(1 << 0)
37*4882a593Smuzhiyun 
38*4882a593Smuzhiyun #define	OMAP_USBTLL_IRQSTATUS				(0x18)
39*4882a593Smuzhiyun #define	OMAP_USBTLL_IRQENABLE				(0x1C)
40*4882a593Smuzhiyun 
41*4882a593Smuzhiyun #define	OMAP_TLL_SHARED_CONF				(0x30)
42*4882a593Smuzhiyun #define	OMAP_TLL_SHARED_CONF_USB_90D_DDR_EN		(1 << 6)
43*4882a593Smuzhiyun #define	OMAP_TLL_SHARED_CONF_USB_180D_SDR_EN		(1 << 5)
44*4882a593Smuzhiyun #define	OMAP_TLL_SHARED_CONF_USB_DIVRATION		(1 << 2)
45*4882a593Smuzhiyun #define	OMAP_TLL_SHARED_CONF_FCLK_REQ			(1 << 1)
46*4882a593Smuzhiyun #define	OMAP_TLL_SHARED_CONF_FCLK_IS_ON			(1 << 0)
47*4882a593Smuzhiyun 
48*4882a593Smuzhiyun #define	OMAP_TLL_CHANNEL_CONF(num)			(0x040 + 0x004 * num)
49*4882a593Smuzhiyun #define OMAP_TLL_CHANNEL_CONF_FSLSMODE_SHIFT		24
50*4882a593Smuzhiyun #define OMAP_TLL_CHANNEL_CONF_DRVVBUS			(1 << 16)
51*4882a593Smuzhiyun #define OMAP_TLL_CHANNEL_CONF_CHRGVBUS			(1 << 15)
52*4882a593Smuzhiyun #define	OMAP_TLL_CHANNEL_CONF_ULPINOBITSTUFF		(1 << 11)
53*4882a593Smuzhiyun #define	OMAP_TLL_CHANNEL_CONF_ULPI_ULPIAUTOIDLE		(1 << 10)
54*4882a593Smuzhiyun #define	OMAP_TLL_CHANNEL_CONF_UTMIAUTOIDLE		(1 << 9)
55*4882a593Smuzhiyun #define	OMAP_TLL_CHANNEL_CONF_ULPIDDRMODE		(1 << 8)
56*4882a593Smuzhiyun #define OMAP_TLL_CHANNEL_CONF_MODE_TRANSPARENT_UTMI	(2 << 1)
57*4882a593Smuzhiyun #define OMAP_TLL_CHANNEL_CONF_CHANMODE_FSLS		(1 << 1)
58*4882a593Smuzhiyun #define	OMAP_TLL_CHANNEL_CONF_CHANEN			(1 << 0)
59*4882a593Smuzhiyun 
60*4882a593Smuzhiyun #define OMAP_TLL_FSLSMODE_6PIN_PHY_DAT_SE0		0x0
61*4882a593Smuzhiyun #define OMAP_TLL_FSLSMODE_6PIN_PHY_DP_DM		0x1
62*4882a593Smuzhiyun #define OMAP_TLL_FSLSMODE_3PIN_PHY			0x2
63*4882a593Smuzhiyun #define OMAP_TLL_FSLSMODE_4PIN_PHY			0x3
64*4882a593Smuzhiyun #define OMAP_TLL_FSLSMODE_6PIN_TLL_DAT_SE0		0x4
65*4882a593Smuzhiyun #define OMAP_TLL_FSLSMODE_6PIN_TLL_DP_DM		0x5
66*4882a593Smuzhiyun #define OMAP_TLL_FSLSMODE_3PIN_TLL			0x6
67*4882a593Smuzhiyun #define OMAP_TLL_FSLSMODE_4PIN_TLL			0x7
68*4882a593Smuzhiyun #define OMAP_TLL_FSLSMODE_2PIN_TLL_DAT_SE0		0xA
69*4882a593Smuzhiyun #define OMAP_TLL_FSLSMODE_2PIN_DAT_DP_DM		0xB
70*4882a593Smuzhiyun 
71*4882a593Smuzhiyun #define	OMAP_TLL_ULPI_FUNCTION_CTRL(num)		(0x804 + 0x100 * num)
72*4882a593Smuzhiyun #define	OMAP_TLL_ULPI_INTERFACE_CTRL(num)		(0x807 + 0x100 * num)
73*4882a593Smuzhiyun #define	OMAP_TLL_ULPI_OTG_CTRL(num)			(0x80A + 0x100 * num)
74*4882a593Smuzhiyun #define	OMAP_TLL_ULPI_INT_EN_RISE(num)			(0x80D + 0x100 * num)
75*4882a593Smuzhiyun #define	OMAP_TLL_ULPI_INT_EN_FALL(num)			(0x810 + 0x100 * num)
76*4882a593Smuzhiyun #define	OMAP_TLL_ULPI_INT_STATUS(num)			(0x813 + 0x100 * num)
77*4882a593Smuzhiyun #define	OMAP_TLL_ULPI_INT_LATCH(num)			(0x814 + 0x100 * num)
78*4882a593Smuzhiyun #define	OMAP_TLL_ULPI_DEBUG(num)			(0x815 + 0x100 * num)
79*4882a593Smuzhiyun #define	OMAP_TLL_ULPI_SCRATCH_REGISTER(num)		(0x816 + 0x100 * num)
80*4882a593Smuzhiyun 
81*4882a593Smuzhiyun #define OMAP_REV2_TLL_CHANNEL_COUNT			2
82*4882a593Smuzhiyun #define OMAP_TLL_CHANNEL_COUNT				3
83*4882a593Smuzhiyun #define OMAP_TLL_CHANNEL_1_EN_MASK			(1 << 0)
84*4882a593Smuzhiyun #define OMAP_TLL_CHANNEL_2_EN_MASK			(1 << 1)
85*4882a593Smuzhiyun #define OMAP_TLL_CHANNEL_3_EN_MASK			(1 << 2)
86*4882a593Smuzhiyun 
87*4882a593Smuzhiyun /* Values of USBTLL_REVISION - Note: these are not given in the TRM */
88*4882a593Smuzhiyun #define OMAP_USBTLL_REV1		0x00000015	/* OMAP3 */
89*4882a593Smuzhiyun #define OMAP_USBTLL_REV2		0x00000018	/* OMAP 3630 */
90*4882a593Smuzhiyun #define OMAP_USBTLL_REV3		0x00000004	/* OMAP4 */
91*4882a593Smuzhiyun #define OMAP_USBTLL_REV4		0x00000006	/* OMAP5 */
92*4882a593Smuzhiyun 
93*4882a593Smuzhiyun #define is_ehci_tll_mode(x)	(x == OMAP_EHCI_PORT_MODE_TLL)
94*4882a593Smuzhiyun 
95*4882a593Smuzhiyun /* only PHY and UNUSED modes don't need TLL */
96*4882a593Smuzhiyun #define omap_usb_mode_needs_tll(x)	((x) != OMAP_USBHS_PORT_MODE_UNUSED &&\
97*4882a593Smuzhiyun 					 (x) != OMAP_EHCI_PORT_MODE_PHY)
98*4882a593Smuzhiyun 
99*4882a593Smuzhiyun struct usbtll_omap {
100*4882a593Smuzhiyun 	void __iomem	*base;
101*4882a593Smuzhiyun 	int		nch;		/* num. of channels */
102*4882a593Smuzhiyun 	struct clk	*ch_clk[];	/* must be the last member */
103*4882a593Smuzhiyun };
104*4882a593Smuzhiyun 
105*4882a593Smuzhiyun /*-------------------------------------------------------------------------*/
106*4882a593Smuzhiyun 
107*4882a593Smuzhiyun static const char usbtll_driver_name[] = USBTLL_DRIVER_NAME;
108*4882a593Smuzhiyun static struct device	*tll_dev;
109*4882a593Smuzhiyun static DEFINE_SPINLOCK(tll_lock);	/* serialize access to tll_dev */
110*4882a593Smuzhiyun 
111*4882a593Smuzhiyun /*-------------------------------------------------------------------------*/
112*4882a593Smuzhiyun 
usbtll_write(void __iomem * base,u32 reg,u32 val)113*4882a593Smuzhiyun static inline void usbtll_write(void __iomem *base, u32 reg, u32 val)
114*4882a593Smuzhiyun {
115*4882a593Smuzhiyun 	writel_relaxed(val, base + reg);
116*4882a593Smuzhiyun }
117*4882a593Smuzhiyun 
usbtll_read(void __iomem * base,u32 reg)118*4882a593Smuzhiyun static inline u32 usbtll_read(void __iomem *base, u32 reg)
119*4882a593Smuzhiyun {
120*4882a593Smuzhiyun 	return readl_relaxed(base + reg);
121*4882a593Smuzhiyun }
122*4882a593Smuzhiyun 
usbtll_writeb(void __iomem * base,u32 reg,u8 val)123*4882a593Smuzhiyun static inline void usbtll_writeb(void __iomem *base, u32 reg, u8 val)
124*4882a593Smuzhiyun {
125*4882a593Smuzhiyun 	writeb_relaxed(val, base + reg);
126*4882a593Smuzhiyun }
127*4882a593Smuzhiyun 
usbtll_readb(void __iomem * base,u32 reg)128*4882a593Smuzhiyun static inline u8 usbtll_readb(void __iomem *base, u32 reg)
129*4882a593Smuzhiyun {
130*4882a593Smuzhiyun 	return readb_relaxed(base + reg);
131*4882a593Smuzhiyun }
132*4882a593Smuzhiyun 
133*4882a593Smuzhiyun /*-------------------------------------------------------------------------*/
134*4882a593Smuzhiyun 
is_ohci_port(enum usbhs_omap_port_mode pmode)135*4882a593Smuzhiyun static bool is_ohci_port(enum usbhs_omap_port_mode pmode)
136*4882a593Smuzhiyun {
137*4882a593Smuzhiyun 	switch (pmode) {
138*4882a593Smuzhiyun 	case OMAP_OHCI_PORT_MODE_PHY_6PIN_DATSE0:
139*4882a593Smuzhiyun 	case OMAP_OHCI_PORT_MODE_PHY_6PIN_DPDM:
140*4882a593Smuzhiyun 	case OMAP_OHCI_PORT_MODE_PHY_3PIN_DATSE0:
141*4882a593Smuzhiyun 	case OMAP_OHCI_PORT_MODE_PHY_4PIN_DPDM:
142*4882a593Smuzhiyun 	case OMAP_OHCI_PORT_MODE_TLL_6PIN_DATSE0:
143*4882a593Smuzhiyun 	case OMAP_OHCI_PORT_MODE_TLL_6PIN_DPDM:
144*4882a593Smuzhiyun 	case OMAP_OHCI_PORT_MODE_TLL_3PIN_DATSE0:
145*4882a593Smuzhiyun 	case OMAP_OHCI_PORT_MODE_TLL_4PIN_DPDM:
146*4882a593Smuzhiyun 	case OMAP_OHCI_PORT_MODE_TLL_2PIN_DATSE0:
147*4882a593Smuzhiyun 	case OMAP_OHCI_PORT_MODE_TLL_2PIN_DPDM:
148*4882a593Smuzhiyun 		return true;
149*4882a593Smuzhiyun 
150*4882a593Smuzhiyun 	default:
151*4882a593Smuzhiyun 		return false;
152*4882a593Smuzhiyun 	}
153*4882a593Smuzhiyun }
154*4882a593Smuzhiyun 
155*4882a593Smuzhiyun /*
156*4882a593Smuzhiyun  * convert the port-mode enum to a value we can use in the FSLSMODE
157*4882a593Smuzhiyun  * field of USBTLL_CHANNEL_CONF
158*4882a593Smuzhiyun  */
ohci_omap3_fslsmode(enum usbhs_omap_port_mode mode)159*4882a593Smuzhiyun static unsigned ohci_omap3_fslsmode(enum usbhs_omap_port_mode mode)
160*4882a593Smuzhiyun {
161*4882a593Smuzhiyun 	switch (mode) {
162*4882a593Smuzhiyun 	case OMAP_USBHS_PORT_MODE_UNUSED:
163*4882a593Smuzhiyun 	case OMAP_OHCI_PORT_MODE_PHY_6PIN_DATSE0:
164*4882a593Smuzhiyun 		return OMAP_TLL_FSLSMODE_6PIN_PHY_DAT_SE0;
165*4882a593Smuzhiyun 
166*4882a593Smuzhiyun 	case OMAP_OHCI_PORT_MODE_PHY_6PIN_DPDM:
167*4882a593Smuzhiyun 		return OMAP_TLL_FSLSMODE_6PIN_PHY_DP_DM;
168*4882a593Smuzhiyun 
169*4882a593Smuzhiyun 	case OMAP_OHCI_PORT_MODE_PHY_3PIN_DATSE0:
170*4882a593Smuzhiyun 		return OMAP_TLL_FSLSMODE_3PIN_PHY;
171*4882a593Smuzhiyun 
172*4882a593Smuzhiyun 	case OMAP_OHCI_PORT_MODE_PHY_4PIN_DPDM:
173*4882a593Smuzhiyun 		return OMAP_TLL_FSLSMODE_4PIN_PHY;
174*4882a593Smuzhiyun 
175*4882a593Smuzhiyun 	case OMAP_OHCI_PORT_MODE_TLL_6PIN_DATSE0:
176*4882a593Smuzhiyun 		return OMAP_TLL_FSLSMODE_6PIN_TLL_DAT_SE0;
177*4882a593Smuzhiyun 
178*4882a593Smuzhiyun 	case OMAP_OHCI_PORT_MODE_TLL_6PIN_DPDM:
179*4882a593Smuzhiyun 		return OMAP_TLL_FSLSMODE_6PIN_TLL_DP_DM;
180*4882a593Smuzhiyun 
181*4882a593Smuzhiyun 	case OMAP_OHCI_PORT_MODE_TLL_3PIN_DATSE0:
182*4882a593Smuzhiyun 		return OMAP_TLL_FSLSMODE_3PIN_TLL;
183*4882a593Smuzhiyun 
184*4882a593Smuzhiyun 	case OMAP_OHCI_PORT_MODE_TLL_4PIN_DPDM:
185*4882a593Smuzhiyun 		return OMAP_TLL_FSLSMODE_4PIN_TLL;
186*4882a593Smuzhiyun 
187*4882a593Smuzhiyun 	case OMAP_OHCI_PORT_MODE_TLL_2PIN_DATSE0:
188*4882a593Smuzhiyun 		return OMAP_TLL_FSLSMODE_2PIN_TLL_DAT_SE0;
189*4882a593Smuzhiyun 
190*4882a593Smuzhiyun 	case OMAP_OHCI_PORT_MODE_TLL_2PIN_DPDM:
191*4882a593Smuzhiyun 		return OMAP_TLL_FSLSMODE_2PIN_DAT_DP_DM;
192*4882a593Smuzhiyun 	default:
193*4882a593Smuzhiyun 		pr_warn("Invalid port mode, using default\n");
194*4882a593Smuzhiyun 		return OMAP_TLL_FSLSMODE_6PIN_PHY_DAT_SE0;
195*4882a593Smuzhiyun 	}
196*4882a593Smuzhiyun }
197*4882a593Smuzhiyun 
198*4882a593Smuzhiyun /**
199*4882a593Smuzhiyun  * usbtll_omap_probe - initialize TI-based HCDs
200*4882a593Smuzhiyun  *
201*4882a593Smuzhiyun  * Allocates basic resources for this USB host controller.
202*4882a593Smuzhiyun  *
203*4882a593Smuzhiyun  * @pdev: Pointer to this device's platform device structure
204*4882a593Smuzhiyun  */
usbtll_omap_probe(struct platform_device * pdev)205*4882a593Smuzhiyun static int usbtll_omap_probe(struct platform_device *pdev)
206*4882a593Smuzhiyun {
207*4882a593Smuzhiyun 	struct device				*dev =  &pdev->dev;
208*4882a593Smuzhiyun 	struct resource				*res;
209*4882a593Smuzhiyun 	struct usbtll_omap			*tll;
210*4882a593Smuzhiyun 	void __iomem				*base;
211*4882a593Smuzhiyun 	int					i, nch, ver;
212*4882a593Smuzhiyun 
213*4882a593Smuzhiyun 	dev_dbg(dev, "starting TI HSUSB TLL Controller\n");
214*4882a593Smuzhiyun 
215*4882a593Smuzhiyun 	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
216*4882a593Smuzhiyun 	base = devm_ioremap_resource(dev, res);
217*4882a593Smuzhiyun 	if (IS_ERR(base))
218*4882a593Smuzhiyun 		return PTR_ERR(base);
219*4882a593Smuzhiyun 
220*4882a593Smuzhiyun 	pm_runtime_enable(dev);
221*4882a593Smuzhiyun 	pm_runtime_get_sync(dev);
222*4882a593Smuzhiyun 
223*4882a593Smuzhiyun 	ver = usbtll_read(base, OMAP_USBTLL_REVISION);
224*4882a593Smuzhiyun 	switch (ver) {
225*4882a593Smuzhiyun 	case OMAP_USBTLL_REV1:
226*4882a593Smuzhiyun 	case OMAP_USBTLL_REV4:
227*4882a593Smuzhiyun 		nch = OMAP_TLL_CHANNEL_COUNT;
228*4882a593Smuzhiyun 		break;
229*4882a593Smuzhiyun 	case OMAP_USBTLL_REV2:
230*4882a593Smuzhiyun 	case OMAP_USBTLL_REV3:
231*4882a593Smuzhiyun 		nch = OMAP_REV2_TLL_CHANNEL_COUNT;
232*4882a593Smuzhiyun 		break;
233*4882a593Smuzhiyun 	default:
234*4882a593Smuzhiyun 		nch = OMAP_TLL_CHANNEL_COUNT;
235*4882a593Smuzhiyun 		dev_dbg(dev, "rev 0x%x not recognized, assuming %d channels\n",
236*4882a593Smuzhiyun 			ver, nch);
237*4882a593Smuzhiyun 		break;
238*4882a593Smuzhiyun 	}
239*4882a593Smuzhiyun 
240*4882a593Smuzhiyun 	tll = devm_kzalloc(dev, sizeof(*tll) + sizeof(tll->ch_clk[nch]),
241*4882a593Smuzhiyun 			   GFP_KERNEL);
242*4882a593Smuzhiyun 	if (!tll) {
243*4882a593Smuzhiyun 		pm_runtime_put_sync(dev);
244*4882a593Smuzhiyun 		pm_runtime_disable(dev);
245*4882a593Smuzhiyun 		return -ENOMEM;
246*4882a593Smuzhiyun 	}
247*4882a593Smuzhiyun 
248*4882a593Smuzhiyun 	tll->base = base;
249*4882a593Smuzhiyun 	tll->nch = nch;
250*4882a593Smuzhiyun 	platform_set_drvdata(pdev, tll);
251*4882a593Smuzhiyun 
252*4882a593Smuzhiyun 	for (i = 0; i < nch; i++) {
253*4882a593Smuzhiyun 		char clkname[] = "usb_tll_hs_usb_chx_clk";
254*4882a593Smuzhiyun 
255*4882a593Smuzhiyun 		snprintf(clkname, sizeof(clkname),
256*4882a593Smuzhiyun 					"usb_tll_hs_usb_ch%d_clk", i);
257*4882a593Smuzhiyun 		tll->ch_clk[i] = clk_get(dev, clkname);
258*4882a593Smuzhiyun 
259*4882a593Smuzhiyun 		if (IS_ERR(tll->ch_clk[i]))
260*4882a593Smuzhiyun 			dev_dbg(dev, "can't get clock : %s\n", clkname);
261*4882a593Smuzhiyun 		else
262*4882a593Smuzhiyun 			clk_prepare(tll->ch_clk[i]);
263*4882a593Smuzhiyun 	}
264*4882a593Smuzhiyun 
265*4882a593Smuzhiyun 	pm_runtime_put_sync(dev);
266*4882a593Smuzhiyun 	/* only after this can omap_tll_enable/disable work */
267*4882a593Smuzhiyun 	spin_lock(&tll_lock);
268*4882a593Smuzhiyun 	tll_dev = dev;
269*4882a593Smuzhiyun 	spin_unlock(&tll_lock);
270*4882a593Smuzhiyun 
271*4882a593Smuzhiyun 	return 0;
272*4882a593Smuzhiyun }
273*4882a593Smuzhiyun 
274*4882a593Smuzhiyun /**
275*4882a593Smuzhiyun  * usbtll_omap_remove - shutdown processing for UHH & TLL HCDs
276*4882a593Smuzhiyun  * @pdev: USB Host Controller being removed
277*4882a593Smuzhiyun  *
278*4882a593Smuzhiyun  * Reverses the effect of usbtll_omap_probe().
279*4882a593Smuzhiyun  */
usbtll_omap_remove(struct platform_device * pdev)280*4882a593Smuzhiyun static int usbtll_omap_remove(struct platform_device *pdev)
281*4882a593Smuzhiyun {
282*4882a593Smuzhiyun 	struct usbtll_omap *tll = platform_get_drvdata(pdev);
283*4882a593Smuzhiyun 	int i;
284*4882a593Smuzhiyun 
285*4882a593Smuzhiyun 	spin_lock(&tll_lock);
286*4882a593Smuzhiyun 	tll_dev = NULL;
287*4882a593Smuzhiyun 	spin_unlock(&tll_lock);
288*4882a593Smuzhiyun 
289*4882a593Smuzhiyun 	for (i = 0; i < tll->nch; i++) {
290*4882a593Smuzhiyun 		if (!IS_ERR(tll->ch_clk[i])) {
291*4882a593Smuzhiyun 			clk_unprepare(tll->ch_clk[i]);
292*4882a593Smuzhiyun 			clk_put(tll->ch_clk[i]);
293*4882a593Smuzhiyun 		}
294*4882a593Smuzhiyun 	}
295*4882a593Smuzhiyun 
296*4882a593Smuzhiyun 	pm_runtime_disable(&pdev->dev);
297*4882a593Smuzhiyun 	return 0;
298*4882a593Smuzhiyun }
299*4882a593Smuzhiyun 
300*4882a593Smuzhiyun static const struct of_device_id usbtll_omap_dt_ids[] = {
301*4882a593Smuzhiyun 	{ .compatible = "ti,usbhs-tll" },
302*4882a593Smuzhiyun 	{ }
303*4882a593Smuzhiyun };
304*4882a593Smuzhiyun 
305*4882a593Smuzhiyun MODULE_DEVICE_TABLE(of, usbtll_omap_dt_ids);
306*4882a593Smuzhiyun 
307*4882a593Smuzhiyun static struct platform_driver usbtll_omap_driver = {
308*4882a593Smuzhiyun 	.driver = {
309*4882a593Smuzhiyun 		.name		= usbtll_driver_name,
310*4882a593Smuzhiyun 		.of_match_table = usbtll_omap_dt_ids,
311*4882a593Smuzhiyun 	},
312*4882a593Smuzhiyun 	.probe		= usbtll_omap_probe,
313*4882a593Smuzhiyun 	.remove		= usbtll_omap_remove,
314*4882a593Smuzhiyun };
315*4882a593Smuzhiyun 
omap_tll_init(struct usbhs_omap_platform_data * pdata)316*4882a593Smuzhiyun int omap_tll_init(struct usbhs_omap_platform_data *pdata)
317*4882a593Smuzhiyun {
318*4882a593Smuzhiyun 	int i;
319*4882a593Smuzhiyun 	bool needs_tll;
320*4882a593Smuzhiyun 	unsigned reg;
321*4882a593Smuzhiyun 	struct usbtll_omap *tll;
322*4882a593Smuzhiyun 
323*4882a593Smuzhiyun 	if (!tll_dev)
324*4882a593Smuzhiyun 		return -ENODEV;
325*4882a593Smuzhiyun 
326*4882a593Smuzhiyun 	pm_runtime_get_sync(tll_dev);
327*4882a593Smuzhiyun 
328*4882a593Smuzhiyun 	spin_lock(&tll_lock);
329*4882a593Smuzhiyun 	tll = dev_get_drvdata(tll_dev);
330*4882a593Smuzhiyun 	needs_tll = false;
331*4882a593Smuzhiyun 	for (i = 0; i < tll->nch; i++)
332*4882a593Smuzhiyun 		needs_tll |= omap_usb_mode_needs_tll(pdata->port_mode[i]);
333*4882a593Smuzhiyun 
334*4882a593Smuzhiyun 	if (needs_tll) {
335*4882a593Smuzhiyun 		void __iomem *base = tll->base;
336*4882a593Smuzhiyun 
337*4882a593Smuzhiyun 		/* Program Common TLL register */
338*4882a593Smuzhiyun 		reg = usbtll_read(base, OMAP_TLL_SHARED_CONF);
339*4882a593Smuzhiyun 		reg |= (OMAP_TLL_SHARED_CONF_FCLK_IS_ON
340*4882a593Smuzhiyun 			| OMAP_TLL_SHARED_CONF_USB_DIVRATION);
341*4882a593Smuzhiyun 		reg &= ~OMAP_TLL_SHARED_CONF_USB_90D_DDR_EN;
342*4882a593Smuzhiyun 		reg &= ~OMAP_TLL_SHARED_CONF_USB_180D_SDR_EN;
343*4882a593Smuzhiyun 
344*4882a593Smuzhiyun 		usbtll_write(base, OMAP_TLL_SHARED_CONF, reg);
345*4882a593Smuzhiyun 
346*4882a593Smuzhiyun 		/* Enable channels now */
347*4882a593Smuzhiyun 		for (i = 0; i < tll->nch; i++) {
348*4882a593Smuzhiyun 			reg = usbtll_read(base,	OMAP_TLL_CHANNEL_CONF(i));
349*4882a593Smuzhiyun 
350*4882a593Smuzhiyun 			if (is_ohci_port(pdata->port_mode[i])) {
351*4882a593Smuzhiyun 				reg |= ohci_omap3_fslsmode(pdata->port_mode[i])
352*4882a593Smuzhiyun 				<< OMAP_TLL_CHANNEL_CONF_FSLSMODE_SHIFT;
353*4882a593Smuzhiyun 				reg |= OMAP_TLL_CHANNEL_CONF_CHANMODE_FSLS;
354*4882a593Smuzhiyun 			} else if (pdata->port_mode[i] ==
355*4882a593Smuzhiyun 					OMAP_EHCI_PORT_MODE_TLL) {
356*4882a593Smuzhiyun 				/*
357*4882a593Smuzhiyun 				 * Disable UTMI AutoIdle, BitStuffing
358*4882a593Smuzhiyun 				 * and use SDR Mode. Enable ULPI AutoIdle.
359*4882a593Smuzhiyun 				 */
360*4882a593Smuzhiyun 				reg &= ~(OMAP_TLL_CHANNEL_CONF_UTMIAUTOIDLE
361*4882a593Smuzhiyun 					| OMAP_TLL_CHANNEL_CONF_ULPIDDRMODE);
362*4882a593Smuzhiyun 				reg |= OMAP_TLL_CHANNEL_CONF_ULPINOBITSTUFF;
363*4882a593Smuzhiyun 				reg |= OMAP_TLL_CHANNEL_CONF_ULPI_ULPIAUTOIDLE;
364*4882a593Smuzhiyun 			} else if (pdata->port_mode[i] ==
365*4882a593Smuzhiyun 					OMAP_EHCI_PORT_MODE_HSIC) {
366*4882a593Smuzhiyun 				/*
367*4882a593Smuzhiyun 				 * HSIC Mode requires UTMI port configurations
368*4882a593Smuzhiyun 				 */
369*4882a593Smuzhiyun 				reg |= OMAP_TLL_CHANNEL_CONF_DRVVBUS
370*4882a593Smuzhiyun 				 | OMAP_TLL_CHANNEL_CONF_CHRGVBUS
371*4882a593Smuzhiyun 				 | OMAP_TLL_CHANNEL_CONF_MODE_TRANSPARENT_UTMI
372*4882a593Smuzhiyun 				 | OMAP_TLL_CHANNEL_CONF_ULPINOBITSTUFF;
373*4882a593Smuzhiyun 			} else {
374*4882a593Smuzhiyun 				continue;
375*4882a593Smuzhiyun 			}
376*4882a593Smuzhiyun 			reg |= OMAP_TLL_CHANNEL_CONF_CHANEN;
377*4882a593Smuzhiyun 			usbtll_write(base, OMAP_TLL_CHANNEL_CONF(i), reg);
378*4882a593Smuzhiyun 
379*4882a593Smuzhiyun 			usbtll_writeb(base,
380*4882a593Smuzhiyun 				      OMAP_TLL_ULPI_SCRATCH_REGISTER(i),
381*4882a593Smuzhiyun 				      0xbe);
382*4882a593Smuzhiyun 		}
383*4882a593Smuzhiyun 	}
384*4882a593Smuzhiyun 
385*4882a593Smuzhiyun 	spin_unlock(&tll_lock);
386*4882a593Smuzhiyun 	pm_runtime_put_sync(tll_dev);
387*4882a593Smuzhiyun 
388*4882a593Smuzhiyun 	return 0;
389*4882a593Smuzhiyun }
390*4882a593Smuzhiyun EXPORT_SYMBOL_GPL(omap_tll_init);
391*4882a593Smuzhiyun 
omap_tll_enable(struct usbhs_omap_platform_data * pdata)392*4882a593Smuzhiyun int omap_tll_enable(struct usbhs_omap_platform_data *pdata)
393*4882a593Smuzhiyun {
394*4882a593Smuzhiyun 	int i;
395*4882a593Smuzhiyun 	struct usbtll_omap *tll;
396*4882a593Smuzhiyun 
397*4882a593Smuzhiyun 	if (!tll_dev)
398*4882a593Smuzhiyun 		return -ENODEV;
399*4882a593Smuzhiyun 
400*4882a593Smuzhiyun 	pm_runtime_get_sync(tll_dev);
401*4882a593Smuzhiyun 
402*4882a593Smuzhiyun 	spin_lock(&tll_lock);
403*4882a593Smuzhiyun 	tll = dev_get_drvdata(tll_dev);
404*4882a593Smuzhiyun 
405*4882a593Smuzhiyun 	for (i = 0; i < tll->nch; i++) {
406*4882a593Smuzhiyun 		if (omap_usb_mode_needs_tll(pdata->port_mode[i])) {
407*4882a593Smuzhiyun 			int r;
408*4882a593Smuzhiyun 
409*4882a593Smuzhiyun 			if (IS_ERR(tll->ch_clk[i]))
410*4882a593Smuzhiyun 				continue;
411*4882a593Smuzhiyun 
412*4882a593Smuzhiyun 			r = clk_enable(tll->ch_clk[i]);
413*4882a593Smuzhiyun 			if (r) {
414*4882a593Smuzhiyun 				dev_err(tll_dev,
415*4882a593Smuzhiyun 				 "Error enabling ch %d clock: %d\n", i, r);
416*4882a593Smuzhiyun 			}
417*4882a593Smuzhiyun 		}
418*4882a593Smuzhiyun 	}
419*4882a593Smuzhiyun 
420*4882a593Smuzhiyun 	spin_unlock(&tll_lock);
421*4882a593Smuzhiyun 
422*4882a593Smuzhiyun 	return 0;
423*4882a593Smuzhiyun }
424*4882a593Smuzhiyun EXPORT_SYMBOL_GPL(omap_tll_enable);
425*4882a593Smuzhiyun 
omap_tll_disable(struct usbhs_omap_platform_data * pdata)426*4882a593Smuzhiyun int omap_tll_disable(struct usbhs_omap_platform_data *pdata)
427*4882a593Smuzhiyun {
428*4882a593Smuzhiyun 	int i;
429*4882a593Smuzhiyun 	struct usbtll_omap *tll;
430*4882a593Smuzhiyun 
431*4882a593Smuzhiyun 	if (!tll_dev)
432*4882a593Smuzhiyun 		return -ENODEV;
433*4882a593Smuzhiyun 
434*4882a593Smuzhiyun 	spin_lock(&tll_lock);
435*4882a593Smuzhiyun 	tll = dev_get_drvdata(tll_dev);
436*4882a593Smuzhiyun 
437*4882a593Smuzhiyun 	for (i = 0; i < tll->nch; i++) {
438*4882a593Smuzhiyun 		if (omap_usb_mode_needs_tll(pdata->port_mode[i])) {
439*4882a593Smuzhiyun 			if (!IS_ERR(tll->ch_clk[i]))
440*4882a593Smuzhiyun 				clk_disable(tll->ch_clk[i]);
441*4882a593Smuzhiyun 		}
442*4882a593Smuzhiyun 	}
443*4882a593Smuzhiyun 
444*4882a593Smuzhiyun 	spin_unlock(&tll_lock);
445*4882a593Smuzhiyun 	pm_runtime_put_sync(tll_dev);
446*4882a593Smuzhiyun 
447*4882a593Smuzhiyun 	return 0;
448*4882a593Smuzhiyun }
449*4882a593Smuzhiyun EXPORT_SYMBOL_GPL(omap_tll_disable);
450*4882a593Smuzhiyun 
451*4882a593Smuzhiyun MODULE_AUTHOR("Keshava Munegowda <keshava_mgowda@ti.com>");
452*4882a593Smuzhiyun MODULE_AUTHOR("Roger Quadros <rogerq@ti.com>");
453*4882a593Smuzhiyun MODULE_LICENSE("GPL v2");
454*4882a593Smuzhiyun MODULE_DESCRIPTION("usb tll driver for TI OMAP EHCI and OHCI controllers");
455*4882a593Smuzhiyun 
omap_usbtll_drvinit(void)456*4882a593Smuzhiyun static int __init omap_usbtll_drvinit(void)
457*4882a593Smuzhiyun {
458*4882a593Smuzhiyun 	return platform_driver_register(&usbtll_omap_driver);
459*4882a593Smuzhiyun }
460*4882a593Smuzhiyun 
461*4882a593Smuzhiyun /*
462*4882a593Smuzhiyun  * init before usbhs core driver;
463*4882a593Smuzhiyun  * The usbtll driver should be initialized before
464*4882a593Smuzhiyun  * the usbhs core driver probe function is called.
465*4882a593Smuzhiyun  */
466*4882a593Smuzhiyun fs_initcall(omap_usbtll_drvinit);
467*4882a593Smuzhiyun 
omap_usbtll_drvexit(void)468*4882a593Smuzhiyun static void __exit omap_usbtll_drvexit(void)
469*4882a593Smuzhiyun {
470*4882a593Smuzhiyun 	platform_driver_unregister(&usbtll_omap_driver);
471*4882a593Smuzhiyun }
472*4882a593Smuzhiyun module_exit(omap_usbtll_drvexit);
473