• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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