1 /*
2 *
3 * phy-hi3516ev200-usb.c
4 *
5 * usb phy driver special for hi3516ev200
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-hi3516ev200/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 #define GTXTHRCFG 0xc108
45 #define GRXTHRCFG 0xc10c
46 #define REG_GCTL 0xc110
47 #define REG_GUSB3PIPECTL0 0xc2c0
48 #define PCS_SSP_SOFT_RESET (0x1 << 31)
49
50 #define PORT_CAP_DIR (0x3 << 12)
51 #define PORT_SET_HOST (0x1 << 12)
52 #define PORT_DISABLE_SUSPEND (0x1 << 17)
53
54 #define USB2_G_TXTHRCFG 0x23100000
55 #define USB2_G_RXTHRCFG 0x23100000
56
57 /* PHY base register */
58 #define USB2_PHY_BASE_REG 0x100D0000
59 #define RG_PLL_EN_MASK 0x0003
60 #define RG_PLL_EN_VAL 0x0003
61 #define PHY_PLL_OFFSET 0x0014
62
63 #define USB_VBUS_IO_CONFIG_REG 0x100c007C
64 #define USB_VBUS_IO_CONFIG_VAL 0x0531
65
66 #define USB_PWREN_CONFIG_REG 0x100c0080
67 #define USB_PWREN_CONFIG_VAL 0x1
68
69 /* PHY eye config */
70 #define HIXVP_PHY_ANA_CFG_0_OFFSET 0x00
71 #define HIXVP_PHY_PRE_DRIVE_MASK (0xf << 24)
72 #define HIXVP_PHY_PRE_DRIVE_VAL (0x4 << 24)
73 #define HIXVP_PHY_ANA_CFG_2_OFFSET 0x08
74 #define HIXVP_PHY_TX_TEST_BIT (0x1 << 20)
75 #define HIXVP_PHY_DISCONNECT_REFERENCE_MASK (0x7 << 16)
76 #define HIXVP_PHY_DISCONNECT_REFERENCE_VAL (0x2 << 16)
77 #define HIXVP_PHY_ANA_CFG_4_OFFSET 0x10
78 #define HIXVP_PHY_TX_REFERENCE_MASK (0x7 << 4)
79 #define HIXVP_PHY_TX_REFERENCE_VAL (0x5 << 4)
80 #define HIXVP_PHY_SQUELCH_REFERENCE_MASK (0x7 << 0)
81 #define HIXVP_PHY_SQUELCH_REFERENCE_VAL (0x5 << 0)
82
83 /* PHY trim config */
84 #define USB_TRIM_BASE_REG 0x12028004
85 #define USB_TRIM_VAL_MASK 0x001F
86 #define USB_TRIM_VAL_MIN 0x0009
87 #define USB_TRIM_VAL_MAX 0x001D
88 #define USB2_TRIM_OFFSET 0x0008
89 #define USB2_TRIM_MASK 0x1f00
90 #define usb2_trim_val(a) (((a) << 8) & USB2_TRIM_MASK)
91 #define USB2_TRIM_DEFAULT_VAL 0x000e
92
93 /* PHY svb config */
94 #define USB_SVB_BASE_REG 0x12020158
95 #define USB_SVB_OFFSET 0x00
96 #define USB_SVB_MASK (0x0f << 24)
97 #define USB_SVB_PREDEV_5_MIN 0x2bc
98 #define USB_SVB_PREDEV_5_MAX_4_MIN 0x32a
99 #define USB_SVB_PREDEV_4_MAX_3_MIN 0x398
100 #define USB_SVB_PREDEV_3_MAX_2_MIN 0x3ca
101 #define USB_SVB_PREDEV_2_MAX 0x44c
102 #define USB_SVB_PREDEV_5_PHY_VAL (0x05 << 24)
103 #define USB_SVB_PREDEV_4_PHY_VAL (0x04 << 24)
104 #define USB_SVB_PREDEV_3_PHY_VAL (0x03 << 24)
105 #define USB_SVB_PREDEV_2_PHY_VAL (0x02 << 24)
106 static uintptr_t xhci_base = 0;
107
xhci_hcd_init(int index,struct xhci_hccr ** hccr,struct xhci_hcor ** hcor)108 int xhci_hcd_init(int index, struct xhci_hccr **hccr, struct xhci_hcor **hcor)
109 {
110 if ((hccr == NULL) || (hcor == NULL))
111 return -EINVAL;
112
113 xhci_base = USB3_CTRL_REG_BASE;
114
115 *hccr = (struct xhci_hccr *)(xhci_base);
116 *hcor = (struct xhci_hcor *)((uintptr_t) *hccr +
117 HC_LENGTH(xhci_readl(&(*hccr)->cr_capbase)));
118
119 return 0;
120 }
121
usb2_eye_config(void)122 void usb2_eye_config(void)
123 {
124 unsigned int reg;
125 /* HSTX pre-drive strength */
126 reg = readl(USB2_PHY_BASE_REG + HIXVP_PHY_ANA_CFG_0_OFFSET);
127 reg &= ~HIXVP_PHY_PRE_DRIVE_MASK;
128 reg |= HIXVP_PHY_PRE_DRIVE_VAL;
129 writel(reg, USB2_PHY_BASE_REG + HIXVP_PHY_ANA_CFG_0_OFFSET);
130
131 /* TX test bit */
132 reg = readl(USB2_PHY_BASE_REG + HIXVP_PHY_ANA_CFG_2_OFFSET);
133 reg |= HIXVP_PHY_TX_TEST_BIT;
134 writel(reg, USB2_PHY_BASE_REG + HIXVP_PHY_ANA_CFG_2_OFFSET);
135
136 /* Disconnect reference voltage sel */
137 reg = readl(USB2_PHY_BASE_REG + HIXVP_PHY_ANA_CFG_2_OFFSET);
138 reg &= ~HIXVP_PHY_DISCONNECT_REFERENCE_MASK;
139 reg |= HIXVP_PHY_DISCONNECT_REFERENCE_VAL;
140 writel(reg, USB2_PHY_BASE_REG + HIXVP_PHY_ANA_CFG_2_OFFSET);
141
142 /* TX reference voltage sel */
143 reg = readl(USB2_PHY_BASE_REG + HIXVP_PHY_ANA_CFG_4_OFFSET);
144 reg &= ~HIXVP_PHY_TX_REFERENCE_MASK;
145 reg |= HIXVP_PHY_TX_REFERENCE_VAL;
146 writel(reg, USB2_PHY_BASE_REG + HIXVP_PHY_ANA_CFG_4_OFFSET);
147
148 /* Squlech reference voltage sel */
149 reg = readl(USB2_PHY_BASE_REG + HIXVP_PHY_ANA_CFG_4_OFFSET);
150 reg &= ~HIXVP_PHY_SQUELCH_REFERENCE_MASK;
151 reg |= HIXVP_PHY_SQUELCH_REFERENCE_VAL;
152 writel(reg, USB2_PHY_BASE_REG + HIXVP_PHY_ANA_CFG_4_OFFSET);
153 }
154
usb2_trim_config(void)155 void usb2_trim_config(void)
156 {
157 unsigned int ret;
158 unsigned int reg;
159 unsigned int trim_val;
160
161 ret = readl(USB_TRIM_BASE_REG);
162 trim_val = (ret & USB_TRIM_VAL_MASK); /* get usb trim value */
163 reg = readl(USB2_PHY_BASE_REG + USB2_TRIM_OFFSET);
164 reg &= ~USB2_TRIM_MASK;
165 /* set trim value to HiXVPV100 phy */
166 if ((trim_val >= USB_TRIM_VAL_MIN) && (trim_val <= USB_TRIM_VAL_MAX))
167 reg |= usb2_trim_val(trim_val);
168 else
169 reg |= usb2_trim_val(USB2_TRIM_DEFAULT_VAL);
170
171 writel(reg, USB2_PHY_BASE_REG + USB2_TRIM_OFFSET);
172 }
173
usb2_svb_config(void)174 void usb2_svb_config(void)
175 {
176 unsigned int ret;
177 unsigned int reg;
178
179 ret = readl(USB_SVB_BASE_REG);
180 reg = readl(USB2_PHY_BASE_REG + USB_SVB_OFFSET);
181 reg &= ~USB_SVB_MASK;
182 /* set svb value to HiXVPV100 phy */
183 if ((ret >= USB_SVB_PREDEV_5_MIN) && (ret < USB_SVB_PREDEV_5_MAX_4_MIN))
184 reg |= USB_SVB_PREDEV_5_PHY_VAL;
185 else if ((ret >= USB_SVB_PREDEV_5_MAX_4_MIN) && (ret < USB_SVB_PREDEV_4_MAX_3_MIN))
186 reg |= USB_SVB_PREDEV_4_PHY_VAL;
187 else if ((ret >= USB_SVB_PREDEV_4_MAX_3_MIN) && (ret <= USB_SVB_PREDEV_3_MAX_2_MIN))
188 reg |= USB_SVB_PREDEV_3_PHY_VAL;
189 else if ((ret > USB_SVB_PREDEV_3_MAX_2_MIN) && (ret <= USB_SVB_PREDEV_2_MAX))
190 reg |= USB_SVB_PREDEV_2_PHY_VAL;
191 else
192 reg |= USB_SVB_PREDEV_4_PHY_VAL;
193
194 writel(reg, USB2_PHY_BASE_REG + USB_SVB_OFFSET);
195 }
196
phy_hiusb_init_crg_clk(int index)197 void phy_hiusb_init_crg_clk(int index)
198 {
199 unsigned int reg;
200
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 /* inti 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