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