]>
Commit | Line | Data |
---|---|---|
3f467529 WG |
1 | /* |
2 | * Copyright (c) 2009 Daniel Mack <daniel@caiaq.de> | |
3 | * Copyright (C) 2010 Freescale Semiconductor, Inc. | |
4 | * | |
1a459660 | 5 | * SPDX-License-Identifier: GPL-2.0+ |
3f467529 WG |
6 | */ |
7 | ||
8 | #include <common.h> | |
9 | #include <usb.h> | |
10 | #include <errno.h> | |
11 | #include <linux/compiler.h> | |
12 | #include <usb/ehci-fsl.h> | |
13 | #include <asm/io.h> | |
14 | #include <asm/arch/imx-regs.h> | |
15 | #include <asm/arch/clock.h> | |
af2a35fb | 16 | #include <asm/imx-common/iomux-v3.h> |
3f467529 WG |
17 | |
18 | #include "ehci.h" | |
3f467529 WG |
19 | |
20 | #define USB_OTGREGS_OFFSET 0x000 | |
21 | #define USB_H1REGS_OFFSET 0x200 | |
22 | #define USB_H2REGS_OFFSET 0x400 | |
23 | #define USB_H3REGS_OFFSET 0x600 | |
24 | #define USB_OTHERREGS_OFFSET 0x800 | |
25 | ||
26 | #define USB_H1_CTRL_OFFSET 0x04 | |
27 | ||
28 | #define USBPHY_CTRL 0x00000030 | |
29 | #define USBPHY_CTRL_SET 0x00000034 | |
30 | #define USBPHY_CTRL_CLR 0x00000038 | |
31 | #define USBPHY_CTRL_TOG 0x0000003c | |
32 | ||
33 | #define USBPHY_PWD 0x00000000 | |
34 | #define USBPHY_CTRL_SFTRST 0x80000000 | |
35 | #define USBPHY_CTRL_CLKGATE 0x40000000 | |
36 | #define USBPHY_CTRL_ENUTMILEVEL3 0x00008000 | |
37 | #define USBPHY_CTRL_ENUTMILEVEL2 0x00004000 | |
38 | ||
3f467529 WG |
39 | #define ANADIG_USB2_CHRG_DETECT_EN_B 0x00100000 |
40 | #define ANADIG_USB2_CHRG_DETECT_CHK_CHRG_B 0x00080000 | |
41 | ||
3f467529 WG |
42 | #define ANADIG_USB2_PLL_480_CTRL_BYPASS 0x00010000 |
43 | #define ANADIG_USB2_PLL_480_CTRL_ENABLE 0x00002000 | |
44 | #define ANADIG_USB2_PLL_480_CTRL_POWER 0x00001000 | |
45 | #define ANADIG_USB2_PLL_480_CTRL_EN_USB_CLKS 0x00000040 | |
46 | ||
47 | ||
48 | #define UCTRL_OVER_CUR_POL (1 << 8) /* OTG Polarity of Overcurrent */ | |
49 | #define UCTRL_OVER_CUR_DIS (1 << 7) /* Disable OTG Overcurrent Detection */ | |
50 | ||
51 | /* USBCMD */ | |
52 | #define UH1_USBCMD_OFFSET 0x140 | |
53 | #define UCMD_RUN_STOP (1 << 0) /* controller run/stop */ | |
54 | #define UCMD_RESET (1 << 1) /* controller reset */ | |
55 | ||
56 | static void usbh1_internal_phy_clock_gate(int on) | |
57 | { | |
58 | void __iomem *phy_reg = (void __iomem *)USB_PHY1_BASE_ADDR; | |
59 | ||
60 | phy_reg += on ? USBPHY_CTRL_CLR : USBPHY_CTRL_SET; | |
61 | __raw_writel(USBPHY_CTRL_CLKGATE, phy_reg); | |
62 | } | |
63 | ||
64 | static void usbh1_power_config(void) | |
65 | { | |
3f29d962 WG |
66 | struct anatop_regs __iomem *anatop = |
67 | (struct anatop_regs __iomem *)ANATOP_BASE_ADDR; | |
3f467529 WG |
68 | /* |
69 | * Some phy and power's special controls for host1 | |
70 | * 1. The external charger detector needs to be disabled | |
71 | * or the signal at DP will be poor | |
72 | * 2. The PLL's power and output to usb for host 1 | |
73 | * is totally controlled by IC, so the Software only needs | |
74 | * to enable them at initializtion. | |
75 | */ | |
76 | __raw_writel(ANADIG_USB2_CHRG_DETECT_EN_B | | |
77 | ANADIG_USB2_CHRG_DETECT_CHK_CHRG_B, | |
522b2a02 | 78 | &anatop->usb2_chrg_detect); |
3f467529 WG |
79 | |
80 | __raw_writel(ANADIG_USB2_PLL_480_CTRL_BYPASS, | |
3f29d962 | 81 | &anatop->usb2_pll_480_ctrl_clr); |
3f467529 WG |
82 | |
83 | __raw_writel(ANADIG_USB2_PLL_480_CTRL_ENABLE | | |
84 | ANADIG_USB2_PLL_480_CTRL_POWER | | |
85 | ANADIG_USB2_PLL_480_CTRL_EN_USB_CLKS, | |
522b2a02 | 86 | &anatop->usb2_pll_480_ctrl_set); |
3f467529 WG |
87 | } |
88 | ||
89 | static int usbh1_phy_enable(void) | |
90 | { | |
91 | void __iomem *phy_reg = (void __iomem *)USB_PHY1_BASE_ADDR; | |
92 | void __iomem *phy_ctrl = (void __iomem *)(phy_reg + USBPHY_CTRL); | |
93 | void __iomem *usb_cmd = (void __iomem *)(USBOH3_USB_BASE_ADDR + | |
94 | USB_H1REGS_OFFSET + | |
95 | UH1_USBCMD_OFFSET); | |
96 | u32 val; | |
97 | ||
98 | /* Stop then Reset */ | |
99 | val = __raw_readl(usb_cmd); | |
100 | val &= ~UCMD_RUN_STOP; | |
101 | __raw_writel(val, usb_cmd); | |
102 | while (__raw_readl(usb_cmd) & UCMD_RUN_STOP) | |
103 | ; | |
104 | ||
105 | val = __raw_readl(usb_cmd); | |
106 | val |= UCMD_RESET; | |
107 | __raw_writel(val, usb_cmd); | |
108 | while (__raw_readl(usb_cmd) & UCMD_RESET) | |
109 | ; | |
110 | ||
111 | /* Reset USBPHY module */ | |
112 | val = __raw_readl(phy_ctrl); | |
113 | val |= USBPHY_CTRL_SFTRST; | |
114 | __raw_writel(val, phy_ctrl); | |
115 | udelay(10); | |
116 | ||
117 | /* Remove CLKGATE and SFTRST */ | |
118 | val = __raw_readl(phy_ctrl); | |
119 | val &= ~(USBPHY_CTRL_CLKGATE | USBPHY_CTRL_SFTRST); | |
120 | __raw_writel(val, phy_ctrl); | |
121 | udelay(10); | |
122 | ||
123 | /* Power up the PHY */ | |
124 | __raw_writel(0, phy_reg + USBPHY_PWD); | |
125 | /* enable FS/LS device */ | |
126 | val = __raw_readl(phy_reg + USBPHY_CTRL); | |
127 | val |= (USBPHY_CTRL_ENUTMILEVEL2 | USBPHY_CTRL_ENUTMILEVEL3); | |
128 | __raw_writel(val, phy_reg + USBPHY_CTRL); | |
129 | ||
130 | return 0; | |
131 | } | |
132 | ||
133 | static void usbh1_oc_config(void) | |
134 | { | |
135 | void __iomem *usb_base = (void __iomem *)USBOH3_USB_BASE_ADDR; | |
136 | void __iomem *usbother_base = usb_base + USB_OTHERREGS_OFFSET; | |
137 | u32 val; | |
138 | ||
139 | val = __raw_readl(usbother_base + USB_H1_CTRL_OFFSET); | |
140 | #if CONFIG_MACH_TYPE == MACH_TYPE_MX6Q_ARM2 | |
141 | /* mx6qarm2 seems to required a different setting*/ | |
142 | val &= ~UCTRL_OVER_CUR_POL; | |
143 | #else | |
144 | val |= UCTRL_OVER_CUR_POL; | |
145 | #endif | |
146 | __raw_writel(val, usbother_base + USB_H1_CTRL_OFFSET); | |
147 | ||
148 | val = __raw_readl(usbother_base + USB_H1_CTRL_OFFSET); | |
149 | val |= UCTRL_OVER_CUR_DIS; | |
150 | __raw_writel(val, usbother_base + USB_H1_CTRL_OFFSET); | |
151 | } | |
152 | ||
f22e4fae BT |
153 | int __weak board_ehci_hcd_init(int port) |
154 | { | |
155 | return 0; | |
156 | } | |
157 | ||
676ae068 | 158 | int ehci_hcd_init(int index, struct ehci_hccr **hccr, struct ehci_hcor **hcor) |
3f467529 WG |
159 | { |
160 | struct usb_ehci *ehci; | |
161 | ||
162 | enable_usboh3_clk(1); | |
163 | mdelay(1); | |
164 | ||
165 | /* Do board specific initialization */ | |
166 | board_ehci_hcd_init(CONFIG_MXC_USB_PORT); | |
167 | ||
168 | #if CONFIG_MXC_USB_PORT == 1 | |
169 | /* USB Host 1 */ | |
170 | usbh1_power_config(); | |
171 | usbh1_oc_config(); | |
172 | usbh1_internal_phy_clock_gate(1); | |
173 | usbh1_phy_enable(); | |
174 | #else | |
175 | #error "MXC USB port not yet supported" | |
176 | #endif | |
177 | ||
178 | ehci = (struct usb_ehci *)(USBOH3_USB_BASE_ADDR + | |
179 | (0x200 * CONFIG_MXC_USB_PORT)); | |
676ae068 LS |
180 | *hccr = (struct ehci_hccr *)((uint32_t)&ehci->caplength); |
181 | *hcor = (struct ehci_hcor *)((uint32_t)*hccr + | |
182 | HC_LENGTH(ehci_readl(&(*hccr)->cr_capbase))); | |
3f467529 WG |
183 | setbits_le32(&ehci->usbmode, CM_HOST); |
184 | ||
185 | __raw_writel(CONFIG_MXC_USB_PORTSC, &ehci->portsc); | |
186 | setbits_le32(&ehci->portsc, USB_EN); | |
187 | ||
188 | mdelay(10); | |
189 | ||
190 | return 0; | |
191 | } | |
192 | ||
676ae068 | 193 | int ehci_hcd_stop(int index) |
3f467529 WG |
194 | { |
195 | return 0; | |
196 | } |