1 /*
2 *
3 * phy-hi3516ev300-usb.c
4 *
5 * usb phy driver special for hi3516ev300
6 *
7 * Copyright (c) 2020 HiSilicon (Shanghai) Technologies CO., LIMITED.
8 *
9 * This program is free software; you can redistribute it and/or modify it
10 * under the terms of the GNU General Public License as published by the
11 * Free Software Foundation; either version 2 of the License, or (at your
12 * option) any later version.
13 *
14 * This program is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 * GNU General Public License for more details.
18 *
19 * You should have received a copy of the GNU General Public License
20 * along with this program. If not, see <http://www.gnu.org/licenses/>.
21 *
22 */
23 #include <asm/arch-hi3516ev300/platform.h>
24 #include <dm.h>
25 #include <usb.h>
26 #include <usb/xhci.h>
27 #include "phy-hisi-usb.h"
28
29 /* offset 0x140 */
30 #define USB2_CTRL 0x140
31 #define USB2_CRG_DEFAULT_VAL 0x3b2f
32 #define USB2_UTMI_CKEN (0x1 << 12)
33 #define USB2_PHY_APB_CKEN (0x1 << 11)
34 #define USB2_REF_CKEN (0x1 << 9)
35 #define USB2_BUS_CKEN (0x1 << 8)
36 #define USB2_PHY_PLL_CKEN (0x1 << 4)
37 #define USB2_PHY_XTAL_CKEN (0x1 << 2)
38 #define USB2_FREECLK_CKSEL (0x1 << 13)
39 #define USB2_PHY_APB_RST (0x1 << 10)
40 #define USB2_VCC_SRST_REQ (0x1 << 3)
41 #define USB2_PHY_REQ (0x1 << 0)
42 #define USB2_PHY_PORT_TREQ (0x1 << 1)
43
44
45 #define GTXTHRCFG 0xc108
46 #define GRXTHRCFG 0xc10c
47 #define REG_GCTL 0xc110
48 #define REG_GUSB3PIPECTL0 0xc2c0
49 #define PCS_SSP_SOFT_RESET (0x1 << 31)
50
51 #define PORT_CAP_DIR (0x3 << 12)
52 #define PORT_SET_HOST (0x1 << 12)
53 #define PORT_DISABLE_SUSPEND (0x1 << 17)
54
55
56 #define USB2_G_TXTHRCFG 0x23100000
57 #define USB2_G_RXTHRCFG 0x23100000
58
59 /* PHY base register */
60 #define USB2_PHY_BASE_REG 0x100D0000
61 #define RG_PLL_EN_MASK 0x0003
62 #define RG_PLL_EN_VAL 0x0003
63 #define PHY_PLL_OFFSET 0x0014
64
65 #define USB_VBUS_IO_CONFIG_REG 0x100c007C
66 #define USB_VBUS_IO_CONFIG_VAL 0x0431
67
68 #define USB_PWREN_CONFIG_REG 0x100c0080
69 #define USB_PWREN_CONFIG_VAL 0x1
70
71 /* PHY eye config */
72 #define HIXVP_PHY_ANA_CFG_0_OFFSET 0x00
73 #define HIXVP_PHY_PRE_DRIVE_MASK (0xf << 24)
74 #define HIXVP_PHY_PRE_DRIVE_VAL (0x4 << 24)
75 #define HIXVP_PHY_ANA_CFG_2_OFFSET 0x08
76 #define HIXVP_PHY_TX_TEST_BIT (0x1 << 20)
77 #define HIXVP_PHY_DISCONNECT_REFERENCE_MASK (0x7 << 16)
78 #define HIXVP_PHY_DISCONNECT_REFERENCE_VAL (0x2 << 16)
79 #define HIXVP_PHY_ANA_CFG_4_OFFSET 0x10
80 #define HIXVP_PHY_TX_REFERENCE_MASK (0x7 << 4)
81 #define HIXVP_PHY_TX_REFERENCE_VAL (0x5 << 4)
82 #define HIXVP_PHY_SQUELCH_REFERENCE_MASK (0x7 << 0)
83 #define HIXVP_PHY_SQUELCH_REFERENCE_VAL (0x5 << 0)
84
85 /* PHY trim config */
86 #define USB_TRIM_BASE_REG 0x12028004
87 #define USB_TRIM_VAL_MASK 0x001F
88 #define USB_TRIM_VAL_MIN 0x0009
89 #define USB_TRIM_VAL_MAX 0x001D
90 #define USB2_TRIM_OFFSET 0x0008
91 #define USB2_TRIM_MASK 0x1f00
92 #define usb2_trim_val(a) (((a) << 8) & USB2_TRIM_MASK)
93 #define USB2_TRIM_DEFAULT_VAL 0x000e
94
95 /* PHY svb config */
96 #define USB_SVB_BASE_REG 0x12020158
97 #define USB_SVB_OFFSET 0x00
98 #define USB_SVB_MASK (0x0f << 24)
99 #define USB_SVB_PREDEV_5_MIN 0x2bc
100 #define USB_SVB_PREDEV_5_MAX_4_MIN 0x32a
101 #define USB_SVB_PREDEV_4_MAX_3_MIN 0x398
102 #define USB_SVB_PREDEV_3_MAX_2_MIN 0x3ca
103 #define USB_SVB_PREDEV_2_MAX 0x44c
104 #define USB_SVB_PREDEV_5_PHY_VAL (0x05 << 24)
105 #define USB_SVB_PREDEV_4_PHY_VAL (0x04 << 24)
106 #define USB_SVB_PREDEV_3_PHY_VAL (0x03 << 24)
107 #define USB_SVB_PREDEV_2_PHY_VAL (0x02 << 24)
108 static uintptr_t xhci_base = 0;
109
xhci_hcd_init(int index,struct xhci_hccr ** hccr,struct xhci_hcor ** hcor)110 int xhci_hcd_init(int index, struct xhci_hccr **hccr, struct xhci_hcor **hcor)
111 {
112 if ((hccr == NULL) || (hcor == NULL))
113 return -EINVAL;
114
115 xhci_base = USB3_CTRL_REG_BASE;
116
117 *hccr = (struct xhci_hccr *)(xhci_base);
118 *hcor = (struct xhci_hcor *)((uintptr_t) *hccr +
119 HC_LENGTH(xhci_readl(&(*hccr)->cr_capbase)));
120
121 return 0;
122 }
123
usb2_eye_config(void)124 void usb2_eye_config(void)
125 {
126 unsigned int reg;
127 /* HSTX pre-drive strength */
128 reg = readl(USB2_PHY_BASE_REG + HIXVP_PHY_ANA_CFG_0_OFFSET);
129 reg &= ~HIXVP_PHY_PRE_DRIVE_MASK;
130 reg |= HIXVP_PHY_PRE_DRIVE_VAL;
131 writel(reg, USB2_PHY_BASE_REG + HIXVP_PHY_ANA_CFG_0_OFFSET);
132
133 /* TX test bit */
134 reg = readl(USB2_PHY_BASE_REG + HIXVP_PHY_ANA_CFG_2_OFFSET);
135 reg |= HIXVP_PHY_TX_TEST_BIT;
136 writel(reg, USB2_PHY_BASE_REG + HIXVP_PHY_ANA_CFG_2_OFFSET);
137
138 /* Disconnect reference voltage sel */
139 reg = readl(USB2_PHY_BASE_REG + HIXVP_PHY_ANA_CFG_2_OFFSET);
140 reg &= ~HIXVP_PHY_DISCONNECT_REFERENCE_MASK;
141 reg |= HIXVP_PHY_DISCONNECT_REFERENCE_VAL;
142 writel(reg, USB2_PHY_BASE_REG + HIXVP_PHY_ANA_CFG_2_OFFSET);
143
144 /* TX reference voltage sel */
145 reg = readl(USB2_PHY_BASE_REG + HIXVP_PHY_ANA_CFG_4_OFFSET);
146 reg &= ~HIXVP_PHY_TX_REFERENCE_MASK;
147 reg |= HIXVP_PHY_TX_REFERENCE_VAL;
148 writel(reg, USB2_PHY_BASE_REG + HIXVP_PHY_ANA_CFG_4_OFFSET);
149
150 /* Squlech reference voltage sel */
151 reg = readl(USB2_PHY_BASE_REG + HIXVP_PHY_ANA_CFG_4_OFFSET);
152 reg &= ~HIXVP_PHY_SQUELCH_REFERENCE_MASK;
153 reg |= HIXVP_PHY_SQUELCH_REFERENCE_VAL;
154 writel(reg, USB2_PHY_BASE_REG + HIXVP_PHY_ANA_CFG_4_OFFSET);
155 }
156
usb2_trim_config(void)157 void usb2_trim_config(void)
158 {
159 unsigned int ret;
160 unsigned int reg;
161 unsigned int trim_val;
162
163 ret = readl(USB_TRIM_BASE_REG);
164 trim_val = (ret & USB_TRIM_VAL_MASK); /* get usb trim value */
165 reg = readl(USB2_PHY_BASE_REG + USB2_TRIM_OFFSET);
166 reg &= ~USB2_TRIM_MASK;
167 /* set trim value to HiXVPV100 phy */
168 if ((trim_val >= USB_TRIM_VAL_MIN) && (trim_val <= USB_TRIM_VAL_MAX))
169 reg |= usb2_trim_val(trim_val);
170 else
171 reg |= usb2_trim_val(USB2_TRIM_DEFAULT_VAL);
172
173 writel(reg, USB2_PHY_BASE_REG + USB2_TRIM_OFFSET);
174 }
175
usb2_svb_config(void)176 void usb2_svb_config(void)
177 {
178 unsigned int ret;
179 unsigned int reg;
180
181 ret = readl(USB_SVB_BASE_REG);
182 reg = readl(USB2_PHY_BASE_REG + USB_SVB_OFFSET);
183 reg &= ~USB_SVB_MASK;
184 /* set svb value to HiXVPV100 phy */
185 if ((ret >= USB_SVB_PREDEV_5_MIN) && (ret < USB_SVB_PREDEV_5_MAX_4_MIN))
186 reg |= USB_SVB_PREDEV_5_PHY_VAL;
187 else if ((ret >= USB_SVB_PREDEV_5_MAX_4_MIN) && (ret < USB_SVB_PREDEV_4_MAX_3_MIN))
188 reg |= USB_SVB_PREDEV_4_PHY_VAL;
189 else if ((ret >= USB_SVB_PREDEV_4_MAX_3_MIN) && (ret <= USB_SVB_PREDEV_3_MAX_2_MIN))
190 reg |= USB_SVB_PREDEV_3_PHY_VAL;
191 else if ((ret > USB_SVB_PREDEV_3_MAX_2_MIN) && (ret <= USB_SVB_PREDEV_2_MAX))
192 reg |= USB_SVB_PREDEV_2_PHY_VAL;
193 else
194 reg |= USB_SVB_PREDEV_4_PHY_VAL;
195
196 writel(reg, USB2_PHY_BASE_REG + USB_SVB_OFFSET);
197 }
phy_hiusb_init_crg_clk(int index)198 void phy_hiusb_init_crg_clk(int index)
199 {
200 unsigned int reg;
201 /* set usb2 CRG default val */
202 reg = USB2_CRG_DEFAULT_VAL;
203 writel(reg, CRG_REG_BASE + USB2_CTRL);
204 udelay(U_LEVEL6);
205
206 /* open UTMI clk */
207 reg = readl(CRG_REG_BASE + USB2_CTRL);
208 reg |= USB2_UTMI_CKEN;
209 writel(reg, CRG_REG_BASE + USB2_CTRL);
210
211 /* open phy apb clk */
212 reg = readl(CRG_REG_BASE + USB2_CTRL);
213 reg |= USB2_PHY_APB_CKEN;
214 writel(reg, CRG_REG_BASE + USB2_CTRL);
215
216 /* open ctrl ref clk */
217 reg = readl(CRG_REG_BASE + USB2_CTRL);
218 reg |= USB2_REF_CKEN;
219 writel(reg, CRG_REG_BASE + USB2_CTRL);
220
221 /* open bus clk */
222 reg = readl(CRG_REG_BASE + USB2_CTRL);
223 reg |= USB2_BUS_CKEN;
224 writel(reg, CRG_REG_BASE + USB2_CTRL);
225
226 /* open phy pll clk */
227 reg = readl(CRG_REG_BASE + USB2_CTRL);
228 reg |= USB2_PHY_PLL_CKEN;
229 writel(reg, CRG_REG_BASE + USB2_CTRL);
230
231 /* open phy xtal clk */
232 reg = readl(CRG_REG_BASE + USB2_CTRL);
233 reg |= USB2_PHY_XTAL_CKEN;
234 writel(reg, CRG_REG_BASE + USB2_CTRL);
235
236 /* freeclk_cksel_free */
237 reg = readl(CRG_REG_BASE + USB2_CTRL);
238 reg |= USB2_FREECLK_CKSEL;
239 writel(reg, CRG_REG_BASE + USB2_CTRL);
240
241 udelay(U_LEVEL5);
242 }
243
phy_hiusb_init(int index)244 void phy_hiusb_init(int index)
245 {
246 unsigned int reg;
247
248 /* VBUS config */
249 reg = USB_VBUS_IO_CONFIG_VAL;
250 writel(reg, USB_VBUS_IO_CONFIG_REG);
251
252 reg = USB_PWREN_CONFIG_VAL;
253 writel(reg, USB_PWREN_CONFIG_REG);
254
255 /* init crg and clk */
256 phy_hiusb_init_crg_clk(index);
257
258 /* release phy apb */
259 reg = readl(CRG_REG_BASE + USB2_CTRL);
260 reg &= ~USB2_PHY_APB_RST;
261 writel(reg, CRG_REG_BASE + USB2_CTRL);
262
263 udelay(U_LEVEL5);
264
265 /* por noreset */
266 reg = readl(CRG_REG_BASE + USB2_CTRL);
267 reg &= ~USB2_PHY_REQ;
268 writel(reg, CRG_REG_BASE + USB2_CTRL);
269
270 reg = readl(USB2_PHY_BASE_REG + PHY_PLL_OFFSET);
271 reg &= ~RG_PLL_EN_MASK;
272 reg |= RG_PLL_EN_VAL;
273 writel(reg, USB2_PHY_BASE_REG + PHY_PLL_OFFSET);
274
275 udelay(U_LEVEL10);
276
277 /* cancel TPOR */
278 reg = readl(CRG_REG_BASE + USB2_CTRL);
279 reg &= ~USB2_PHY_PORT_TREQ;
280 writel(reg, CRG_REG_BASE + USB2_CTRL);
281 udelay(U_LEVEL6);
282
283 /* vcc reset */
284 reg = readl(CRG_REG_BASE + USB2_CTRL);
285 reg &= ~USB2_VCC_SRST_REQ;
286 writel(reg, CRG_REG_BASE + USB2_CTRL);
287
288 /* USB2 Controller configs */
289 reg = readl(USB3_CTRL_REG_BASE + REG_GUSB3PIPECTL0);
290 reg |= PCS_SSP_SOFT_RESET;
291 writel(reg, USB3_CTRL_REG_BASE + REG_GUSB3PIPECTL0);
292 udelay(U_LEVEL2);
293
294 reg = readl(USB3_CTRL_REG_BASE + REG_GCTL);
295 reg &= ~PORT_CAP_DIR;
296 reg |= PORT_SET_HOST; /* [13:12] 01: Host; 10: Device; 11: OTG */
297 writel(reg, USB3_CTRL_REG_BASE + REG_GCTL);
298 udelay(U_LEVEL2);
299
300 reg = readl(USB3_CTRL_REG_BASE + REG_GUSB3PIPECTL0);
301 reg &= ~PCS_SSP_SOFT_RESET;
302 reg &= ~PORT_DISABLE_SUSPEND; /* disable suspend */
303 writel(reg, USB3_CTRL_REG_BASE + REG_GUSB3PIPECTL0);
304 udelay(U_LEVEL2);
305
306 writel(USB2_G_TXTHRCFG, USB3_CTRL_REG_BASE + GTXTHRCFG);
307 writel(USB2_G_RXTHRCFG, USB3_CTRL_REG_BASE + GRXTHRCFG);
308 udelay(U_LEVEL2);
309
310 /* USB2 eye config */
311 usb2_eye_config();
312
313 /* USB2 trim config */
314 usb2_trim_config();
315
316 /* USB2 svb config */
317 usb2_svb_config();
318 }
319 EXPORT_SYMBOL(phy_hiusb_init);
320
xhci_hcd_stop(int index)321 void xhci_hcd_stop(int index)
322 {
323 unsigned int reg;
324
325 /* por noreset */
326 reg = readl(CRG_REG_BASE + USB2_CTRL);
327 reg |= USB2_PHY_REQ;
328 writel(reg, CRG_REG_BASE + USB2_CTRL);
329
330 udelay(U_LEVEL10);
331
332 /* cancel TPOR */
333 reg = readl(CRG_REG_BASE + USB2_CTRL);
334 reg |= USB2_PHY_PORT_TREQ;
335 writel(reg, CRG_REG_BASE + USB2_CTRL);
336 udelay(U_LEVEL6);
337
338 /* vcc reset */
339 reg = readl(CRG_REG_BASE + USB2_CTRL);
340 reg |= USB2_VCC_SRST_REQ;
341 writel(reg, CRG_REG_BASE + USB2_CTRL);
342 }
343 EXPORT_SYMBOL(xhci_hcd_stop);
344
345