1*4882a593Smuzhiyun /*
2*4882a593Smuzhiyun * Copyright (c) 2009 Daniel Mack <daniel@caiaq.de>
3*4882a593Smuzhiyun * Copyright (C) 2010 Freescale Semiconductor, Inc.
4*4882a593Smuzhiyun *
5*4882a593Smuzhiyun * SPDX-License-Identifier: GPL-2.0+
6*4882a593Smuzhiyun */
7*4882a593Smuzhiyun
8*4882a593Smuzhiyun #include <common.h>
9*4882a593Smuzhiyun #include <usb.h>
10*4882a593Smuzhiyun #include <errno.h>
11*4882a593Smuzhiyun #include <wait_bit.h>
12*4882a593Smuzhiyun #include <linux/compiler.h>
13*4882a593Smuzhiyun #include <usb/ehci-ci.h>
14*4882a593Smuzhiyun #include <asm/io.h>
15*4882a593Smuzhiyun #include <asm/arch/imx-regs.h>
16*4882a593Smuzhiyun #include <asm/arch/clock.h>
17*4882a593Smuzhiyun #include <asm/mach-imx/iomux-v3.h>
18*4882a593Smuzhiyun #include <asm/mach-imx/sys_proto.h>
19*4882a593Smuzhiyun #include <dm.h>
20*4882a593Smuzhiyun #include <asm/mach-types.h>
21*4882a593Smuzhiyun #include <power/regulator.h>
22*4882a593Smuzhiyun #include <linux/usb/otg.h>
23*4882a593Smuzhiyun
24*4882a593Smuzhiyun #include "ehci.h"
25*4882a593Smuzhiyun
26*4882a593Smuzhiyun DECLARE_GLOBAL_DATA_PTR;
27*4882a593Smuzhiyun
28*4882a593Smuzhiyun #define USB_OTGREGS_OFFSET 0x000
29*4882a593Smuzhiyun #define USB_H1REGS_OFFSET 0x200
30*4882a593Smuzhiyun #define USB_H2REGS_OFFSET 0x400
31*4882a593Smuzhiyun #define USB_H3REGS_OFFSET 0x600
32*4882a593Smuzhiyun #define USB_OTHERREGS_OFFSET 0x800
33*4882a593Smuzhiyun
34*4882a593Smuzhiyun #define USB_H1_CTRL_OFFSET 0x04
35*4882a593Smuzhiyun
36*4882a593Smuzhiyun #define USBPHY_CTRL 0x00000030
37*4882a593Smuzhiyun #define USBPHY_CTRL_SET 0x00000034
38*4882a593Smuzhiyun #define USBPHY_CTRL_CLR 0x00000038
39*4882a593Smuzhiyun #define USBPHY_CTRL_TOG 0x0000003c
40*4882a593Smuzhiyun
41*4882a593Smuzhiyun #define USBPHY_PWD 0x00000000
42*4882a593Smuzhiyun #define USBPHY_CTRL_SFTRST 0x80000000
43*4882a593Smuzhiyun #define USBPHY_CTRL_CLKGATE 0x40000000
44*4882a593Smuzhiyun #define USBPHY_CTRL_ENUTMILEVEL3 0x00008000
45*4882a593Smuzhiyun #define USBPHY_CTRL_ENUTMILEVEL2 0x00004000
46*4882a593Smuzhiyun #define USBPHY_CTRL_OTG_ID 0x08000000
47*4882a593Smuzhiyun
48*4882a593Smuzhiyun #define ANADIG_USB2_CHRG_DETECT_EN_B 0x00100000
49*4882a593Smuzhiyun #define ANADIG_USB2_CHRG_DETECT_CHK_CHRG_B 0x00080000
50*4882a593Smuzhiyun
51*4882a593Smuzhiyun #define ANADIG_USB2_PLL_480_CTRL_BYPASS 0x00010000
52*4882a593Smuzhiyun #define ANADIG_USB2_PLL_480_CTRL_ENABLE 0x00002000
53*4882a593Smuzhiyun #define ANADIG_USB2_PLL_480_CTRL_POWER 0x00001000
54*4882a593Smuzhiyun #define ANADIG_USB2_PLL_480_CTRL_EN_USB_CLKS 0x00000040
55*4882a593Smuzhiyun
56*4882a593Smuzhiyun #define USBNC_OFFSET 0x200
57*4882a593Smuzhiyun #define USBNC_PHY_STATUS_OFFSET 0x23C
58*4882a593Smuzhiyun #define USBNC_PHYSTATUS_ID_DIG (1 << 4) /* otg_id status */
59*4882a593Smuzhiyun #define USBNC_PHYCFG2_ACAENB (1 << 4) /* otg_id detection enable */
60*4882a593Smuzhiyun #define UCTRL_PWR_POL (1 << 9) /* OTG Polarity of Power Pin */
61*4882a593Smuzhiyun #define UCTRL_OVER_CUR_POL (1 << 8) /* OTG Polarity of Overcurrent */
62*4882a593Smuzhiyun #define UCTRL_OVER_CUR_DIS (1 << 7) /* Disable OTG Overcurrent Detection */
63*4882a593Smuzhiyun
64*4882a593Smuzhiyun /* USBCMD */
65*4882a593Smuzhiyun #define UCMD_RUN_STOP (1 << 0) /* controller run/stop */
66*4882a593Smuzhiyun #define UCMD_RESET (1 << 1) /* controller reset */
67*4882a593Smuzhiyun
68*4882a593Smuzhiyun #if defined(CONFIG_MX6) || defined(CONFIG_MX7ULP)
69*4882a593Smuzhiyun static const unsigned phy_bases[] = {
70*4882a593Smuzhiyun USB_PHY0_BASE_ADDR,
71*4882a593Smuzhiyun #if defined(USB_PHY1_BASE_ADDR)
72*4882a593Smuzhiyun USB_PHY1_BASE_ADDR,
73*4882a593Smuzhiyun #endif
74*4882a593Smuzhiyun };
75*4882a593Smuzhiyun
usb_internal_phy_clock_gate(int index,int on)76*4882a593Smuzhiyun static void usb_internal_phy_clock_gate(int index, int on)
77*4882a593Smuzhiyun {
78*4882a593Smuzhiyun void __iomem *phy_reg;
79*4882a593Smuzhiyun
80*4882a593Smuzhiyun if (index >= ARRAY_SIZE(phy_bases))
81*4882a593Smuzhiyun return;
82*4882a593Smuzhiyun
83*4882a593Smuzhiyun phy_reg = (void __iomem *)phy_bases[index];
84*4882a593Smuzhiyun phy_reg += on ? USBPHY_CTRL_CLR : USBPHY_CTRL_SET;
85*4882a593Smuzhiyun writel(USBPHY_CTRL_CLKGATE, phy_reg);
86*4882a593Smuzhiyun }
87*4882a593Smuzhiyun
usb_power_config(int index)88*4882a593Smuzhiyun static void usb_power_config(int index)
89*4882a593Smuzhiyun {
90*4882a593Smuzhiyun #if defined(CONFIG_MX7ULP)
91*4882a593Smuzhiyun struct usbphy_regs __iomem *usbphy =
92*4882a593Smuzhiyun (struct usbphy_regs __iomem *)USB_PHY0_BASE_ADDR;
93*4882a593Smuzhiyun
94*4882a593Smuzhiyun if (index > 0)
95*4882a593Smuzhiyun return;
96*4882a593Smuzhiyun
97*4882a593Smuzhiyun writel(ANADIG_USB2_CHRG_DETECT_EN_B |
98*4882a593Smuzhiyun ANADIG_USB2_CHRG_DETECT_CHK_CHRG_B,
99*4882a593Smuzhiyun &usbphy->usb1_chrg_detect);
100*4882a593Smuzhiyun
101*4882a593Smuzhiyun scg_enable_usb_pll(true);
102*4882a593Smuzhiyun
103*4882a593Smuzhiyun #else
104*4882a593Smuzhiyun struct anatop_regs __iomem *anatop =
105*4882a593Smuzhiyun (struct anatop_regs __iomem *)ANATOP_BASE_ADDR;
106*4882a593Smuzhiyun void __iomem *chrg_detect;
107*4882a593Smuzhiyun void __iomem *pll_480_ctrl_clr;
108*4882a593Smuzhiyun void __iomem *pll_480_ctrl_set;
109*4882a593Smuzhiyun
110*4882a593Smuzhiyun switch (index) {
111*4882a593Smuzhiyun case 0:
112*4882a593Smuzhiyun chrg_detect = &anatop->usb1_chrg_detect;
113*4882a593Smuzhiyun pll_480_ctrl_clr = &anatop->usb1_pll_480_ctrl_clr;
114*4882a593Smuzhiyun pll_480_ctrl_set = &anatop->usb1_pll_480_ctrl_set;
115*4882a593Smuzhiyun break;
116*4882a593Smuzhiyun case 1:
117*4882a593Smuzhiyun chrg_detect = &anatop->usb2_chrg_detect;
118*4882a593Smuzhiyun pll_480_ctrl_clr = &anatop->usb2_pll_480_ctrl_clr;
119*4882a593Smuzhiyun pll_480_ctrl_set = &anatop->usb2_pll_480_ctrl_set;
120*4882a593Smuzhiyun break;
121*4882a593Smuzhiyun default:
122*4882a593Smuzhiyun return;
123*4882a593Smuzhiyun }
124*4882a593Smuzhiyun /*
125*4882a593Smuzhiyun * Some phy and power's special controls
126*4882a593Smuzhiyun * 1. The external charger detector needs to be disabled
127*4882a593Smuzhiyun * or the signal at DP will be poor
128*4882a593Smuzhiyun * 2. The PLL's power and output to usb
129*4882a593Smuzhiyun * is totally controlled by IC, so the Software only needs
130*4882a593Smuzhiyun * to enable them at initializtion.
131*4882a593Smuzhiyun */
132*4882a593Smuzhiyun writel(ANADIG_USB2_CHRG_DETECT_EN_B |
133*4882a593Smuzhiyun ANADIG_USB2_CHRG_DETECT_CHK_CHRG_B,
134*4882a593Smuzhiyun chrg_detect);
135*4882a593Smuzhiyun
136*4882a593Smuzhiyun writel(ANADIG_USB2_PLL_480_CTRL_BYPASS,
137*4882a593Smuzhiyun pll_480_ctrl_clr);
138*4882a593Smuzhiyun
139*4882a593Smuzhiyun writel(ANADIG_USB2_PLL_480_CTRL_ENABLE |
140*4882a593Smuzhiyun ANADIG_USB2_PLL_480_CTRL_POWER |
141*4882a593Smuzhiyun ANADIG_USB2_PLL_480_CTRL_EN_USB_CLKS,
142*4882a593Smuzhiyun pll_480_ctrl_set);
143*4882a593Smuzhiyun
144*4882a593Smuzhiyun #endif
145*4882a593Smuzhiyun }
146*4882a593Smuzhiyun
147*4882a593Smuzhiyun /* Return 0 : host node, <>0 : device mode */
usb_phy_enable(int index,struct usb_ehci * ehci)148*4882a593Smuzhiyun static int usb_phy_enable(int index, struct usb_ehci *ehci)
149*4882a593Smuzhiyun {
150*4882a593Smuzhiyun void __iomem *phy_reg;
151*4882a593Smuzhiyun void __iomem *phy_ctrl;
152*4882a593Smuzhiyun void __iomem *usb_cmd;
153*4882a593Smuzhiyun int ret;
154*4882a593Smuzhiyun
155*4882a593Smuzhiyun if (index >= ARRAY_SIZE(phy_bases))
156*4882a593Smuzhiyun return 0;
157*4882a593Smuzhiyun
158*4882a593Smuzhiyun phy_reg = (void __iomem *)phy_bases[index];
159*4882a593Smuzhiyun phy_ctrl = (void __iomem *)(phy_reg + USBPHY_CTRL);
160*4882a593Smuzhiyun usb_cmd = (void __iomem *)&ehci->usbcmd;
161*4882a593Smuzhiyun
162*4882a593Smuzhiyun /* Stop then Reset */
163*4882a593Smuzhiyun clrbits_le32(usb_cmd, UCMD_RUN_STOP);
164*4882a593Smuzhiyun ret = wait_for_bit_le32(usb_cmd, UCMD_RUN_STOP, false, 10000, false);
165*4882a593Smuzhiyun if (ret)
166*4882a593Smuzhiyun return ret;
167*4882a593Smuzhiyun
168*4882a593Smuzhiyun setbits_le32(usb_cmd, UCMD_RESET);
169*4882a593Smuzhiyun ret = wait_for_bit_le32(usb_cmd, UCMD_RESET, false, 10000, false);
170*4882a593Smuzhiyun if (ret)
171*4882a593Smuzhiyun return ret;
172*4882a593Smuzhiyun
173*4882a593Smuzhiyun /* Reset USBPHY module */
174*4882a593Smuzhiyun setbits_le32(phy_ctrl, USBPHY_CTRL_SFTRST);
175*4882a593Smuzhiyun udelay(10);
176*4882a593Smuzhiyun
177*4882a593Smuzhiyun /* Remove CLKGATE and SFTRST */
178*4882a593Smuzhiyun clrbits_le32(phy_ctrl, USBPHY_CTRL_CLKGATE | USBPHY_CTRL_SFTRST);
179*4882a593Smuzhiyun udelay(10);
180*4882a593Smuzhiyun
181*4882a593Smuzhiyun /* Power up the PHY */
182*4882a593Smuzhiyun writel(0, phy_reg + USBPHY_PWD);
183*4882a593Smuzhiyun /* enable FS/LS device */
184*4882a593Smuzhiyun setbits_le32(phy_ctrl, USBPHY_CTRL_ENUTMILEVEL2 |
185*4882a593Smuzhiyun USBPHY_CTRL_ENUTMILEVEL3);
186*4882a593Smuzhiyun
187*4882a593Smuzhiyun return 0;
188*4882a593Smuzhiyun }
189*4882a593Smuzhiyun
usb_phy_mode(int port)190*4882a593Smuzhiyun int usb_phy_mode(int port)
191*4882a593Smuzhiyun {
192*4882a593Smuzhiyun void __iomem *phy_reg;
193*4882a593Smuzhiyun void __iomem *phy_ctrl;
194*4882a593Smuzhiyun u32 val;
195*4882a593Smuzhiyun
196*4882a593Smuzhiyun phy_reg = (void __iomem *)phy_bases[port];
197*4882a593Smuzhiyun phy_ctrl = (void __iomem *)(phy_reg + USBPHY_CTRL);
198*4882a593Smuzhiyun
199*4882a593Smuzhiyun val = readl(phy_ctrl);
200*4882a593Smuzhiyun
201*4882a593Smuzhiyun if (val & USBPHY_CTRL_OTG_ID)
202*4882a593Smuzhiyun return USB_INIT_DEVICE;
203*4882a593Smuzhiyun else
204*4882a593Smuzhiyun return USB_INIT_HOST;
205*4882a593Smuzhiyun }
206*4882a593Smuzhiyun
207*4882a593Smuzhiyun #if defined(CONFIG_MX7ULP)
208*4882a593Smuzhiyun struct usbnc_regs {
209*4882a593Smuzhiyun u32 ctrl1;
210*4882a593Smuzhiyun u32 ctrl2;
211*4882a593Smuzhiyun u32 reserve0[2];
212*4882a593Smuzhiyun u32 hsic_ctrl;
213*4882a593Smuzhiyun };
214*4882a593Smuzhiyun #else
215*4882a593Smuzhiyun /* Base address for this IP block is 0x02184800 */
216*4882a593Smuzhiyun struct usbnc_regs {
217*4882a593Smuzhiyun u32 ctrl[4]; /* otg/host1-3 */
218*4882a593Smuzhiyun u32 uh2_hsic_ctrl;
219*4882a593Smuzhiyun u32 uh3_hsic_ctrl;
220*4882a593Smuzhiyun u32 otg_phy_ctrl_0;
221*4882a593Smuzhiyun u32 uh1_phy_ctrl_0;
222*4882a593Smuzhiyun };
223*4882a593Smuzhiyun #endif
224*4882a593Smuzhiyun
225*4882a593Smuzhiyun #elif defined(CONFIG_MX7)
226*4882a593Smuzhiyun struct usbnc_regs {
227*4882a593Smuzhiyun u32 ctrl1;
228*4882a593Smuzhiyun u32 ctrl2;
229*4882a593Smuzhiyun u32 reserve1[10];
230*4882a593Smuzhiyun u32 phy_cfg1;
231*4882a593Smuzhiyun u32 phy_cfg2;
232*4882a593Smuzhiyun u32 reserve2;
233*4882a593Smuzhiyun u32 phy_status;
234*4882a593Smuzhiyun u32 reserve3[4];
235*4882a593Smuzhiyun u32 adp_cfg1;
236*4882a593Smuzhiyun u32 adp_cfg2;
237*4882a593Smuzhiyun u32 adp_status;
238*4882a593Smuzhiyun };
239*4882a593Smuzhiyun
usb_power_config(int index)240*4882a593Smuzhiyun static void usb_power_config(int index)
241*4882a593Smuzhiyun {
242*4882a593Smuzhiyun struct usbnc_regs *usbnc = (struct usbnc_regs *)(USB_BASE_ADDR +
243*4882a593Smuzhiyun (0x10000 * index) + USBNC_OFFSET);
244*4882a593Smuzhiyun void __iomem *phy_cfg2 = (void __iomem *)(&usbnc->phy_cfg2);
245*4882a593Smuzhiyun
246*4882a593Smuzhiyun /*
247*4882a593Smuzhiyun * Clear the ACAENB to enable usb_otg_id detection,
248*4882a593Smuzhiyun * otherwise it is the ACA detection enabled.
249*4882a593Smuzhiyun */
250*4882a593Smuzhiyun clrbits_le32(phy_cfg2, USBNC_PHYCFG2_ACAENB);
251*4882a593Smuzhiyun }
252*4882a593Smuzhiyun
usb_phy_mode(int port)253*4882a593Smuzhiyun int usb_phy_mode(int port)
254*4882a593Smuzhiyun {
255*4882a593Smuzhiyun struct usbnc_regs *usbnc = (struct usbnc_regs *)(USB_BASE_ADDR +
256*4882a593Smuzhiyun (0x10000 * port) + USBNC_OFFSET);
257*4882a593Smuzhiyun void __iomem *status = (void __iomem *)(&usbnc->phy_status);
258*4882a593Smuzhiyun u32 val;
259*4882a593Smuzhiyun
260*4882a593Smuzhiyun val = readl(status);
261*4882a593Smuzhiyun
262*4882a593Smuzhiyun if (val & USBNC_PHYSTATUS_ID_DIG)
263*4882a593Smuzhiyun return USB_INIT_DEVICE;
264*4882a593Smuzhiyun else
265*4882a593Smuzhiyun return USB_INIT_HOST;
266*4882a593Smuzhiyun }
267*4882a593Smuzhiyun #endif
268*4882a593Smuzhiyun
usb_oc_config(int index)269*4882a593Smuzhiyun static void usb_oc_config(int index)
270*4882a593Smuzhiyun {
271*4882a593Smuzhiyun #if defined(CONFIG_MX6)
272*4882a593Smuzhiyun struct usbnc_regs *usbnc = (struct usbnc_regs *)(USB_BASE_ADDR +
273*4882a593Smuzhiyun USB_OTHERREGS_OFFSET);
274*4882a593Smuzhiyun void __iomem *ctrl = (void __iomem *)(&usbnc->ctrl[index]);
275*4882a593Smuzhiyun #elif defined(CONFIG_MX7) || defined(CONFIG_MX7ULP)
276*4882a593Smuzhiyun struct usbnc_regs *usbnc = (struct usbnc_regs *)(USB_BASE_ADDR +
277*4882a593Smuzhiyun (0x10000 * index) + USBNC_OFFSET);
278*4882a593Smuzhiyun void __iomem *ctrl = (void __iomem *)(&usbnc->ctrl1);
279*4882a593Smuzhiyun #endif
280*4882a593Smuzhiyun
281*4882a593Smuzhiyun #if CONFIG_MACH_TYPE == MACH_TYPE_MX6Q_ARM2
282*4882a593Smuzhiyun /* mx6qarm2 seems to required a different setting*/
283*4882a593Smuzhiyun clrbits_le32(ctrl, UCTRL_OVER_CUR_POL);
284*4882a593Smuzhiyun #else
285*4882a593Smuzhiyun setbits_le32(ctrl, UCTRL_OVER_CUR_POL);
286*4882a593Smuzhiyun #endif
287*4882a593Smuzhiyun
288*4882a593Smuzhiyun setbits_le32(ctrl, UCTRL_OVER_CUR_DIS);
289*4882a593Smuzhiyun
290*4882a593Smuzhiyun /* Set power polarity to high active */
291*4882a593Smuzhiyun #ifdef CONFIG_MXC_USB_OTG_HACTIVE
292*4882a593Smuzhiyun setbits_le32(ctrl, UCTRL_PWR_POL);
293*4882a593Smuzhiyun #else
294*4882a593Smuzhiyun clrbits_le32(ctrl, UCTRL_PWR_POL);
295*4882a593Smuzhiyun #endif
296*4882a593Smuzhiyun }
297*4882a593Smuzhiyun
298*4882a593Smuzhiyun /**
299*4882a593Smuzhiyun * board_usb_phy_mode - override usb phy mode
300*4882a593Smuzhiyun * @port: usb host/otg port
301*4882a593Smuzhiyun *
302*4882a593Smuzhiyun * Target board specific, override usb_phy_mode.
303*4882a593Smuzhiyun * When usb-otg is used as usb host port, iomux pad usb_otg_id can be
304*4882a593Smuzhiyun * left disconnected in this case usb_phy_mode will not be able to identify
305*4882a593Smuzhiyun * the phy mode that usb port is used.
306*4882a593Smuzhiyun * Machine file overrides board_usb_phy_mode.
307*4882a593Smuzhiyun *
308*4882a593Smuzhiyun * Return: USB_INIT_DEVICE or USB_INIT_HOST
309*4882a593Smuzhiyun */
board_usb_phy_mode(int port)310*4882a593Smuzhiyun int __weak board_usb_phy_mode(int port)
311*4882a593Smuzhiyun {
312*4882a593Smuzhiyun return usb_phy_mode(port);
313*4882a593Smuzhiyun }
314*4882a593Smuzhiyun
315*4882a593Smuzhiyun /**
316*4882a593Smuzhiyun * board_ehci_hcd_init - set usb vbus voltage
317*4882a593Smuzhiyun * @port: usb otg port
318*4882a593Smuzhiyun *
319*4882a593Smuzhiyun * Target board specific, setup iomux pad to setup supply vbus voltage
320*4882a593Smuzhiyun * for usb otg port. Machine board file overrides board_ehci_hcd_init
321*4882a593Smuzhiyun *
322*4882a593Smuzhiyun * Return: 0 Success
323*4882a593Smuzhiyun */
board_ehci_hcd_init(int port)324*4882a593Smuzhiyun int __weak board_ehci_hcd_init(int port)
325*4882a593Smuzhiyun {
326*4882a593Smuzhiyun return 0;
327*4882a593Smuzhiyun }
328*4882a593Smuzhiyun
329*4882a593Smuzhiyun /**
330*4882a593Smuzhiyun * board_ehci_power - enables/disables usb vbus voltage
331*4882a593Smuzhiyun * @port: usb otg port
332*4882a593Smuzhiyun * @on: on/off vbus voltage
333*4882a593Smuzhiyun *
334*4882a593Smuzhiyun * Enables/disables supply vbus voltage for usb otg port.
335*4882a593Smuzhiyun * Machine board file overrides board_ehci_power
336*4882a593Smuzhiyun *
337*4882a593Smuzhiyun * Return: 0 Success
338*4882a593Smuzhiyun */
board_ehci_power(int port,int on)339*4882a593Smuzhiyun int __weak board_ehci_power(int port, int on)
340*4882a593Smuzhiyun {
341*4882a593Smuzhiyun return 0;
342*4882a593Smuzhiyun }
343*4882a593Smuzhiyun
ehci_mx6_common_init(struct usb_ehci * ehci,int index)344*4882a593Smuzhiyun int ehci_mx6_common_init(struct usb_ehci *ehci, int index)
345*4882a593Smuzhiyun {
346*4882a593Smuzhiyun int ret;
347*4882a593Smuzhiyun
348*4882a593Smuzhiyun enable_usboh3_clk(1);
349*4882a593Smuzhiyun mdelay(1);
350*4882a593Smuzhiyun
351*4882a593Smuzhiyun /* Do board specific initialization */
352*4882a593Smuzhiyun ret = board_ehci_hcd_init(index);
353*4882a593Smuzhiyun if (ret)
354*4882a593Smuzhiyun return ret;
355*4882a593Smuzhiyun
356*4882a593Smuzhiyun usb_power_config(index);
357*4882a593Smuzhiyun usb_oc_config(index);
358*4882a593Smuzhiyun
359*4882a593Smuzhiyun #if defined(CONFIG_MX6) || defined(CONFIG_MX7ULP)
360*4882a593Smuzhiyun usb_internal_phy_clock_gate(index, 1);
361*4882a593Smuzhiyun usb_phy_enable(index, ehci);
362*4882a593Smuzhiyun #endif
363*4882a593Smuzhiyun
364*4882a593Smuzhiyun return 0;
365*4882a593Smuzhiyun }
366*4882a593Smuzhiyun
367*4882a593Smuzhiyun #if !CONFIG_IS_ENABLED(DM_USB)
ehci_hcd_init(int index,enum usb_init_type init,struct ehci_hccr ** hccr,struct ehci_hcor ** hcor)368*4882a593Smuzhiyun int ehci_hcd_init(int index, enum usb_init_type init,
369*4882a593Smuzhiyun struct ehci_hccr **hccr, struct ehci_hcor **hcor)
370*4882a593Smuzhiyun {
371*4882a593Smuzhiyun enum usb_init_type type;
372*4882a593Smuzhiyun #if defined(CONFIG_MX6)
373*4882a593Smuzhiyun u32 controller_spacing = 0x200;
374*4882a593Smuzhiyun #elif defined(CONFIG_MX7) || defined(CONFIG_MX7ULP)
375*4882a593Smuzhiyun u32 controller_spacing = 0x10000;
376*4882a593Smuzhiyun #endif
377*4882a593Smuzhiyun struct usb_ehci *ehci = (struct usb_ehci *)(USB_BASE_ADDR +
378*4882a593Smuzhiyun (controller_spacing * index));
379*4882a593Smuzhiyun int ret;
380*4882a593Smuzhiyun
381*4882a593Smuzhiyun if (index > 3)
382*4882a593Smuzhiyun return -EINVAL;
383*4882a593Smuzhiyun
384*4882a593Smuzhiyun ret = ehci_mx6_common_init(ehci, index);
385*4882a593Smuzhiyun if (ret)
386*4882a593Smuzhiyun return ret;
387*4882a593Smuzhiyun
388*4882a593Smuzhiyun type = board_usb_phy_mode(index);
389*4882a593Smuzhiyun
390*4882a593Smuzhiyun if (hccr && hcor) {
391*4882a593Smuzhiyun *hccr = (struct ehci_hccr *)((uint32_t)&ehci->caplength);
392*4882a593Smuzhiyun *hcor = (struct ehci_hcor *)((uint32_t)*hccr +
393*4882a593Smuzhiyun HC_LENGTH(ehci_readl(&(*hccr)->cr_capbase)));
394*4882a593Smuzhiyun }
395*4882a593Smuzhiyun
396*4882a593Smuzhiyun if ((type == init) || (type == USB_INIT_DEVICE))
397*4882a593Smuzhiyun board_ehci_power(index, (type == USB_INIT_DEVICE) ? 0 : 1);
398*4882a593Smuzhiyun if (type != init)
399*4882a593Smuzhiyun return -ENODEV;
400*4882a593Smuzhiyun if (type == USB_INIT_DEVICE)
401*4882a593Smuzhiyun return 0;
402*4882a593Smuzhiyun
403*4882a593Smuzhiyun setbits_le32(&ehci->usbmode, CM_HOST);
404*4882a593Smuzhiyun writel(CONFIG_MXC_USB_PORTSC, &ehci->portsc);
405*4882a593Smuzhiyun setbits_le32(&ehci->portsc, USB_EN);
406*4882a593Smuzhiyun
407*4882a593Smuzhiyun mdelay(10);
408*4882a593Smuzhiyun
409*4882a593Smuzhiyun return 0;
410*4882a593Smuzhiyun }
411*4882a593Smuzhiyun
ehci_hcd_stop(int index)412*4882a593Smuzhiyun int ehci_hcd_stop(int index)
413*4882a593Smuzhiyun {
414*4882a593Smuzhiyun return 0;
415*4882a593Smuzhiyun }
416*4882a593Smuzhiyun #else
417*4882a593Smuzhiyun struct ehci_mx6_priv_data {
418*4882a593Smuzhiyun struct ehci_ctrl ctrl;
419*4882a593Smuzhiyun struct usb_ehci *ehci;
420*4882a593Smuzhiyun struct udevice *vbus_supply;
421*4882a593Smuzhiyun enum usb_init_type init_type;
422*4882a593Smuzhiyun int portnr;
423*4882a593Smuzhiyun };
424*4882a593Smuzhiyun
mx6_init_after_reset(struct ehci_ctrl * dev)425*4882a593Smuzhiyun static int mx6_init_after_reset(struct ehci_ctrl *dev)
426*4882a593Smuzhiyun {
427*4882a593Smuzhiyun struct ehci_mx6_priv_data *priv = dev->priv;
428*4882a593Smuzhiyun enum usb_init_type type = priv->init_type;
429*4882a593Smuzhiyun struct usb_ehci *ehci = priv->ehci;
430*4882a593Smuzhiyun int ret;
431*4882a593Smuzhiyun
432*4882a593Smuzhiyun ret = ehci_mx6_common_init(priv->ehci, priv->portnr);
433*4882a593Smuzhiyun if (ret)
434*4882a593Smuzhiyun return ret;
435*4882a593Smuzhiyun
436*4882a593Smuzhiyun #if CONFIG_IS_ENABLED(DM_REGULATOR)
437*4882a593Smuzhiyun if (priv->vbus_supply) {
438*4882a593Smuzhiyun ret = regulator_set_enable(priv->vbus_supply,
439*4882a593Smuzhiyun (type == USB_INIT_DEVICE) ?
440*4882a593Smuzhiyun false : true);
441*4882a593Smuzhiyun if (ret) {
442*4882a593Smuzhiyun puts("Error enabling VBUS supply\n");
443*4882a593Smuzhiyun return ret;
444*4882a593Smuzhiyun }
445*4882a593Smuzhiyun }
446*4882a593Smuzhiyun #endif
447*4882a593Smuzhiyun
448*4882a593Smuzhiyun if (type == USB_INIT_DEVICE)
449*4882a593Smuzhiyun return 0;
450*4882a593Smuzhiyun
451*4882a593Smuzhiyun setbits_le32(&ehci->usbmode, CM_HOST);
452*4882a593Smuzhiyun writel(CONFIG_MXC_USB_PORTSC, &ehci->portsc);
453*4882a593Smuzhiyun setbits_le32(&ehci->portsc, USB_EN);
454*4882a593Smuzhiyun
455*4882a593Smuzhiyun mdelay(10);
456*4882a593Smuzhiyun
457*4882a593Smuzhiyun return 0;
458*4882a593Smuzhiyun }
459*4882a593Smuzhiyun
460*4882a593Smuzhiyun static const struct ehci_ops mx6_ehci_ops = {
461*4882a593Smuzhiyun .init_after_reset = mx6_init_after_reset
462*4882a593Smuzhiyun };
463*4882a593Smuzhiyun
ehci_usb_phy_mode(struct udevice * dev)464*4882a593Smuzhiyun static int ehci_usb_phy_mode(struct udevice *dev)
465*4882a593Smuzhiyun {
466*4882a593Smuzhiyun struct usb_platdata *plat = dev_get_platdata(dev);
467*4882a593Smuzhiyun void *__iomem addr = (void *__iomem)devfdt_get_addr(dev);
468*4882a593Smuzhiyun void *__iomem phy_ctrl, *__iomem phy_status;
469*4882a593Smuzhiyun const void *blob = gd->fdt_blob;
470*4882a593Smuzhiyun int offset = dev_of_offset(dev), phy_off;
471*4882a593Smuzhiyun u32 val;
472*4882a593Smuzhiyun
473*4882a593Smuzhiyun /*
474*4882a593Smuzhiyun * About fsl,usbphy, Refer to
475*4882a593Smuzhiyun * Documentation/devicetree/bindings/usb/ci-hdrc-usb2.txt.
476*4882a593Smuzhiyun */
477*4882a593Smuzhiyun if (is_mx6() || is_mx7ulp()) {
478*4882a593Smuzhiyun phy_off = fdtdec_lookup_phandle(blob,
479*4882a593Smuzhiyun offset,
480*4882a593Smuzhiyun "fsl,usbphy");
481*4882a593Smuzhiyun if (phy_off < 0)
482*4882a593Smuzhiyun return -EINVAL;
483*4882a593Smuzhiyun
484*4882a593Smuzhiyun addr = (void __iomem *)fdtdec_get_addr(blob, phy_off,
485*4882a593Smuzhiyun "reg");
486*4882a593Smuzhiyun if ((fdt_addr_t)addr == FDT_ADDR_T_NONE)
487*4882a593Smuzhiyun return -EINVAL;
488*4882a593Smuzhiyun
489*4882a593Smuzhiyun phy_ctrl = (void __iomem *)(addr + USBPHY_CTRL);
490*4882a593Smuzhiyun val = readl(phy_ctrl);
491*4882a593Smuzhiyun
492*4882a593Smuzhiyun if (val & USBPHY_CTRL_OTG_ID)
493*4882a593Smuzhiyun plat->init_type = USB_INIT_DEVICE;
494*4882a593Smuzhiyun else
495*4882a593Smuzhiyun plat->init_type = USB_INIT_HOST;
496*4882a593Smuzhiyun } else if (is_mx7()) {
497*4882a593Smuzhiyun phy_status = (void __iomem *)(addr +
498*4882a593Smuzhiyun USBNC_PHY_STATUS_OFFSET);
499*4882a593Smuzhiyun val = readl(phy_status);
500*4882a593Smuzhiyun
501*4882a593Smuzhiyun if (val & USBNC_PHYSTATUS_ID_DIG)
502*4882a593Smuzhiyun plat->init_type = USB_INIT_DEVICE;
503*4882a593Smuzhiyun else
504*4882a593Smuzhiyun plat->init_type = USB_INIT_HOST;
505*4882a593Smuzhiyun } else {
506*4882a593Smuzhiyun return -EINVAL;
507*4882a593Smuzhiyun }
508*4882a593Smuzhiyun
509*4882a593Smuzhiyun return 0;
510*4882a593Smuzhiyun }
511*4882a593Smuzhiyun
ehci_usb_ofdata_to_platdata(struct udevice * dev)512*4882a593Smuzhiyun static int ehci_usb_ofdata_to_platdata(struct udevice *dev)
513*4882a593Smuzhiyun {
514*4882a593Smuzhiyun struct usb_platdata *plat = dev_get_platdata(dev);
515*4882a593Smuzhiyun enum usb_dr_mode dr_mode;
516*4882a593Smuzhiyun
517*4882a593Smuzhiyun dr_mode = usb_get_dr_mode(dev->node);
518*4882a593Smuzhiyun
519*4882a593Smuzhiyun switch (dr_mode) {
520*4882a593Smuzhiyun case USB_DR_MODE_HOST:
521*4882a593Smuzhiyun plat->init_type = USB_INIT_HOST;
522*4882a593Smuzhiyun break;
523*4882a593Smuzhiyun case USB_DR_MODE_PERIPHERAL:
524*4882a593Smuzhiyun plat->init_type = USB_INIT_DEVICE;
525*4882a593Smuzhiyun break;
526*4882a593Smuzhiyun case USB_DR_MODE_OTG:
527*4882a593Smuzhiyun case USB_DR_MODE_UNKNOWN:
528*4882a593Smuzhiyun return ehci_usb_phy_mode(dev);
529*4882a593Smuzhiyun };
530*4882a593Smuzhiyun
531*4882a593Smuzhiyun return 0;
532*4882a593Smuzhiyun }
533*4882a593Smuzhiyun
ehci_usb_bind(struct udevice * dev)534*4882a593Smuzhiyun static int ehci_usb_bind(struct udevice *dev)
535*4882a593Smuzhiyun {
536*4882a593Smuzhiyun /*
537*4882a593Smuzhiyun * TODO:
538*4882a593Smuzhiyun * This driver is only partly converted to DT probing and still uses
539*4882a593Smuzhiyun * a tremendous amount of hard-coded addresses. To make things worse,
540*4882a593Smuzhiyun * the driver depends on specific sequential indexing of controllers,
541*4882a593Smuzhiyun * from which it derives offsets in the PHY and ANATOP register sets.
542*4882a593Smuzhiyun *
543*4882a593Smuzhiyun * Here we attempt to calculate these indexes from DT information as
544*4882a593Smuzhiyun * well as we can. The USB controllers on all existing iMX6 SoCs
545*4882a593Smuzhiyun * are placed next to each other, at addresses incremented by 0x200,
546*4882a593Smuzhiyun * and iMX7 their addresses are shifted by 0x10000.
547*4882a593Smuzhiyun * Thus, the index is derived from the multiple of 0x200 (0x10000 for
548*4882a593Smuzhiyun * iMX7) offset from the first controller address.
549*4882a593Smuzhiyun *
550*4882a593Smuzhiyun * However, to complete conversion of this driver to DT probing, the
551*4882a593Smuzhiyun * following has to be done:
552*4882a593Smuzhiyun * - DM clock framework support for iMX must be implemented
553*4882a593Smuzhiyun * - usb_power_config() has to be converted to clock framework
554*4882a593Smuzhiyun * -> Thus, the ad-hoc "index" variable goes away.
555*4882a593Smuzhiyun * - USB PHY handling has to be factored out into separate driver
556*4882a593Smuzhiyun * -> Thus, the ad-hoc "index" variable goes away from the PHY
557*4882a593Smuzhiyun * code, the PHY driver must parse it's address from DT. This
558*4882a593Smuzhiyun * USB driver must find the PHY driver via DT phandle.
559*4882a593Smuzhiyun * -> usb_power_config() shall be moved to PHY driver
560*4882a593Smuzhiyun * With these changes in place, the ad-hoc indexing goes away and
561*4882a593Smuzhiyun * the driver is fully converted to DT probing.
562*4882a593Smuzhiyun */
563*4882a593Smuzhiyun u32 controller_spacing = is_mx7() ? 0x10000 : 0x200;
564*4882a593Smuzhiyun fdt_addr_t addr = devfdt_get_addr_index(dev, 0);
565*4882a593Smuzhiyun
566*4882a593Smuzhiyun dev->req_seq = (addr - USB_BASE_ADDR) / controller_spacing;
567*4882a593Smuzhiyun
568*4882a593Smuzhiyun return 0;
569*4882a593Smuzhiyun }
570*4882a593Smuzhiyun
ehci_usb_probe(struct udevice * dev)571*4882a593Smuzhiyun static int ehci_usb_probe(struct udevice *dev)
572*4882a593Smuzhiyun {
573*4882a593Smuzhiyun struct usb_platdata *plat = dev_get_platdata(dev);
574*4882a593Smuzhiyun struct usb_ehci *ehci = (struct usb_ehci *)devfdt_get_addr(dev);
575*4882a593Smuzhiyun struct ehci_mx6_priv_data *priv = dev_get_priv(dev);
576*4882a593Smuzhiyun enum usb_init_type type = plat->init_type;
577*4882a593Smuzhiyun struct ehci_hccr *hccr;
578*4882a593Smuzhiyun struct ehci_hcor *hcor;
579*4882a593Smuzhiyun int ret;
580*4882a593Smuzhiyun
581*4882a593Smuzhiyun priv->ehci = ehci;
582*4882a593Smuzhiyun priv->portnr = dev->seq;
583*4882a593Smuzhiyun priv->init_type = type;
584*4882a593Smuzhiyun
585*4882a593Smuzhiyun #if CONFIG_IS_ENABLED(DM_REGULATOR)
586*4882a593Smuzhiyun ret = device_get_supply_regulator(dev, "vbus-supply",
587*4882a593Smuzhiyun &priv->vbus_supply);
588*4882a593Smuzhiyun if (ret)
589*4882a593Smuzhiyun debug("%s: No vbus supply\n", dev->name);
590*4882a593Smuzhiyun #endif
591*4882a593Smuzhiyun ret = ehci_mx6_common_init(ehci, priv->portnr);
592*4882a593Smuzhiyun if (ret)
593*4882a593Smuzhiyun return ret;
594*4882a593Smuzhiyun
595*4882a593Smuzhiyun #if CONFIG_IS_ENABLED(DM_REGULATOR)
596*4882a593Smuzhiyun if (priv->vbus_supply) {
597*4882a593Smuzhiyun ret = regulator_set_enable(priv->vbus_supply,
598*4882a593Smuzhiyun (type == USB_INIT_DEVICE) ?
599*4882a593Smuzhiyun false : true);
600*4882a593Smuzhiyun if (ret) {
601*4882a593Smuzhiyun puts("Error enabling VBUS supply\n");
602*4882a593Smuzhiyun return ret;
603*4882a593Smuzhiyun }
604*4882a593Smuzhiyun }
605*4882a593Smuzhiyun #endif
606*4882a593Smuzhiyun
607*4882a593Smuzhiyun if (priv->init_type == USB_INIT_HOST) {
608*4882a593Smuzhiyun setbits_le32(&ehci->usbmode, CM_HOST);
609*4882a593Smuzhiyun writel(CONFIG_MXC_USB_PORTSC, &ehci->portsc);
610*4882a593Smuzhiyun setbits_le32(&ehci->portsc, USB_EN);
611*4882a593Smuzhiyun }
612*4882a593Smuzhiyun
613*4882a593Smuzhiyun mdelay(10);
614*4882a593Smuzhiyun
615*4882a593Smuzhiyun hccr = (struct ehci_hccr *)((uint32_t)&ehci->caplength);
616*4882a593Smuzhiyun hcor = (struct ehci_hcor *)((uint32_t)hccr +
617*4882a593Smuzhiyun HC_LENGTH(ehci_readl(&(hccr)->cr_capbase)));
618*4882a593Smuzhiyun
619*4882a593Smuzhiyun return ehci_register(dev, hccr, hcor, &mx6_ehci_ops, 0, priv->init_type);
620*4882a593Smuzhiyun }
621*4882a593Smuzhiyun
622*4882a593Smuzhiyun static const struct udevice_id mx6_usb_ids[] = {
623*4882a593Smuzhiyun { .compatible = "fsl,imx27-usb" },
624*4882a593Smuzhiyun { }
625*4882a593Smuzhiyun };
626*4882a593Smuzhiyun
627*4882a593Smuzhiyun U_BOOT_DRIVER(usb_mx6) = {
628*4882a593Smuzhiyun .name = "ehci_mx6",
629*4882a593Smuzhiyun .id = UCLASS_USB,
630*4882a593Smuzhiyun .of_match = mx6_usb_ids,
631*4882a593Smuzhiyun .ofdata_to_platdata = ehci_usb_ofdata_to_platdata,
632*4882a593Smuzhiyun .bind = ehci_usb_bind,
633*4882a593Smuzhiyun .probe = ehci_usb_probe,
634*4882a593Smuzhiyun .remove = ehci_deregister,
635*4882a593Smuzhiyun .ops = &ehci_usb_ops,
636*4882a593Smuzhiyun .platdata_auto_alloc_size = sizeof(struct usb_platdata),
637*4882a593Smuzhiyun .priv_auto_alloc_size = sizeof(struct ehci_mx6_priv_data),
638*4882a593Smuzhiyun .flags = DM_FLAG_ALLOC_PRIV_DMA,
639*4882a593Smuzhiyun };
640*4882a593Smuzhiyun #endif
641