• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * drivers/usb/sunxi_usb/usbc/usbc_phy.c
3  * (C) Copyright 2010-2015
4  * Allwinner Technology Co., Ltd. <www.allwinnertech.com>
5  * daniel, 2009.10.21
6  *
7  * usb common ops.
8  *
9  * This program is free software; you can redistribute it and/or
10  * modify it under the terms of the GNU General Public License as
11  * published by the Free Software Foundation; either version 2 of
12  * the License, or (at your option) any later version.
13  *
14  */
15 #include  "usbc_i.h"
16 #include "sunxi-sid.h"
17 
18 /**
19  * define USB PHY controller reg bit
20  */
21 
22 /* Common Control Bits for Both PHYs */
23 #define  USBC_PHY_PLL_BW			0x03
24 #define  USBC_PHY_RES45_CAL_EN			0x0c
25 
26 /* Private Control Bits for Each PHY */
27 #define  USBC_PHY_TX_AMPLITUDE_TUNE		0x20
28 #define  USBC_PHY_TX_SLEWRATE_TUNE		0x22
29 #define  USBC_PHY_VBUSVALID_TH_SEL		0x25
30 #define  USBC_PHY_PULLUP_RES_SEL		0x27
31 #define  USBC_PHY_OTG_FUNC_EN			0x28
32 #define  USBC_PHY_VBUS_DET_EN			0x29
33 #define  USBC_PHY_DISCON_TH_SEL			0x2a
34 
35 /* usb PHY common set, initialize */
USBC_PHY_SetCommonConfig(void)36 void USBC_PHY_SetCommonConfig(void)
37 {
38 }
39 
40 /**
41  * usb PHY specific set
42  * @hUSB: handle returned by USBC_open_otg,
43  *        include some key data that the USBC need.
44  *
45  */
USBC_PHY_SetPrivateConfig(__hdle hUSB)46 void USBC_PHY_SetPrivateConfig(__hdle hUSB)
47 {
48 }
49 
50 /**
51  * get PHY's common setting. for debug, to see if PHY is set correctly.
52  *
53  * return the 32bit usb PHY common setting value.
54  */
USBC_PHY_GetCommonConfig(void)55 __u32 USBC_PHY_GetCommonConfig(void)
56 {
57 	__u32 reg_val = 0;
58 
59 	return reg_val;
60 }
61 
62 /**
63  * write usb PHY0's phy reg setting. mainly for phy0 standby.
64  *
65  * return the data wrote
66  */
usb_phy0_write(__u32 addr,__u32 data,__u32 dmask,void __iomem * usbc_base_addr)67 static __u32 usb_phy0_write(__u32 addr,
68 		__u32 data, __u32 dmask, void __iomem *usbc_base_addr)
69 {
70 	__u32 i = 0;
71 
72 	data = data & 0x0f;
73 	addr = addr & 0x0f;
74 	dmask = dmask & 0x0f;
75 
76 	USBC_Writeb((dmask<<4)|data, usbc_base_addr + 0x404 + 2);
77 	USBC_Writeb(addr|0x10, usbc_base_addr + 0x404);
78 	for (i = 0; i < 5 ; i++)
79 		;
80 	USBC_Writeb(addr|0x30, usbc_base_addr + 0x404);
81 	for (i = 0 ; i < 5 ; i++)
82 		;
83 	USBC_Writeb(addr|0x10, usbc_base_addr + 0x404);
84 	for (i = 0 ; i < 5 ; i++)
85 		;
86 
87 	return (USBC_Readb(usbc_base_addr + 0x404 + 3) & 0x0f);
88 }
89 
90 /**
91  * Standby the usb phy with the input usb phy index number
92  * @phy_index: usb phy index number, which used to select the phy to standby
93  *
94  */
USBC_phy_Standby(__hdle hUSB,__u32 phy_index)95 void USBC_phy_Standby(__hdle hUSB, __u32 phy_index)
96 {
97 	__usbc_otg_t *usbc_otg = (__usbc_otg_t *)hUSB;
98 
99 	if (phy_index == 0) {
100 		usb_phy0_write(0xB, 0x8, 0xf, usbc_otg->base_addr);
101 		usb_phy0_write(0x7, 0xf, 0xf, usbc_otg->base_addr);
102 		usb_phy0_write(0x1, 0xf, 0xf, usbc_otg->base_addr);
103 		usb_phy0_write(0x2, 0xf, 0xf, usbc_otg->base_addr);
104 	}
105 }
106 
107 /**
108  * Recover the standby phy with the input index number
109  * @phy_index: usb phy index number
110  *
111  */
USBC_Phy_Standby_Recover(__hdle hUSB,__u32 phy_index)112 void USBC_Phy_Standby_Recover(__hdle hUSB, __u32 phy_index)
113 {
114 	__u32 i;
115 
116 	if (phy_index == 0) {
117 		for (i = 0; i < 0x10; i++)
118 			;
119 	}
120 }
121 
USBC_Phy_TpWrite(__u32 usbc_no,__u32 addr,__u32 data,__u32 len)122 static __u32 USBC_Phy_TpWrite(__u32 usbc_no, __u32 addr, __u32 data, __u32 len)
123 {
124 	void __iomem *otgc_base = NULL;
125 	void __iomem *phyctl_val = NULL;
126 	__u32 temp = 0, dtmp = 0;
127 	__u32 j = 0;
128 
129 	otgc_base = get_otgc_vbase();
130 	if (otgc_base == NULL)
131 		return 0;
132 
133 	phyctl_val = otgc_base + USBPHYC_REG_o_PHYCTL;
134 
135 	dtmp = data;
136 	for (j = 0; j < len; j++) {
137 		/* set the bit address to be write */
138 		temp = USBC_Readl(phyctl_val);
139 		temp &= ~(0xff << 8);
140 		temp |= ((addr + j) << 8);
141 		USBC_Writel(temp, phyctl_val);
142 
143 		temp = USBC_Readb(phyctl_val);
144 		temp &= ~(0x1 << 7);
145 		temp |= (dtmp & 0x1) << 7;
146 		temp &= ~(0x1 << (usbc_no << 1));
147 		USBC_Writeb(temp, phyctl_val);
148 
149 		temp = USBC_Readb(phyctl_val);
150 		temp |= (0x1 << (usbc_no << 1));
151 		USBC_Writeb(temp, phyctl_val);
152 
153 		temp = USBC_Readb(phyctl_val);
154 		temp &= ~(0x1 << (usbc_no << 1));
155 		USBC_Writeb(temp, phyctl_val);
156 		dtmp >>= 1;
157 	}
158 
159 	return data;
160 }
161 
USBC_Phy_Write(__u32 usbc_no,__u32 addr,__u32 data,__u32 len)162 static __u32 USBC_Phy_Write(__u32 usbc_no, __u32 addr, __u32 data, __u32 len)
163 {
164 	return USBC_Phy_TpWrite(usbc_no, addr, data, len);
165 }
166 
UsbPhyCtl(void __iomem * regs)167 void UsbPhyCtl(void __iomem *regs)
168 {
169 	__u32 reg_val = 0;
170 
171 	reg_val = USBC_Readl(regs + USBPHYC_REG_o_PHYCTL);
172 	reg_val |= (0x01 << USBC_PHY_CTL_VBUSVLDEXT);
173 	USBC_Writel(reg_val, (regs + USBPHYC_REG_o_PHYCTL));
174 }
175 
USBC_PHY_Set_Ctl(void __iomem * regs,__u32 mask)176 void USBC_PHY_Set_Ctl(void __iomem *regs, __u32 mask)
177 {
178 	__u32 reg_val = 0;
179 
180 	reg_val = USBC_Readl(regs + USBPHYC_REG_o_PHYCTL);
181 	reg_val |= (0x01 << mask);
182 	USBC_Writel(reg_val, (regs + USBPHYC_REG_o_PHYCTL));
183 }
184 
USBC_PHY_Clear_Ctl(void __iomem * regs,__u32 mask)185 void USBC_PHY_Clear_Ctl(void __iomem *regs, __u32 mask)
186 {
187 	__u32 reg_val = 0;
188 
189 	reg_val = USBC_Readl(regs + USBPHYC_REG_o_PHYCTL);
190 	reg_val &= ~(0x01 << mask);
191 	USBC_Writel(reg_val, (regs + USBPHYC_REG_o_PHYCTL));
192 }
193 
UsbPhyInit(__u32 usbc_no)194 void UsbPhyInit(__u32 usbc_no)
195 {
196 
197 	/* adjust the 45 ohm resistor */
198 	if (usbc_no == 0)
199 		USBC_Phy_Write(usbc_no, 0x0c, 0x01, 1);
200 
201 	/* adjust USB0 PHY range and rate */
202 	USBC_Phy_Write(usbc_no, 0x20, 0x14, 5);
203 
204 	/* adjust disconnect threshold */
205 	USBC_Phy_Write(usbc_no, 0x2a, 3, 2);
206 	/* by wangjx */
207 }
208 
UsbPhyEndReset(__u32 usbc_no)209 void UsbPhyEndReset(__u32 usbc_no)
210 {
211 	int i;
212 
213 	if (usbc_no == 0) {
214 		/**
215 		 * Disable Sequelch Detect for a while
216 		 * before Release USB Reset.
217 		 */
218 		USBC_Phy_Write(usbc_no, 0x3c, 0x2, 2);
219 		for (i = 0; i < 0x100; i++)
220 			;
221 		USBC_Phy_Write(usbc_no, 0x3c, 0x0, 2);
222 	}
223 }
224 
usb_otg_phy_txtune(void __iomem * regs)225 void usb_otg_phy_txtune(void __iomem *regs)
226 {
227 	__u32 reg_val = 0;
228 
229 	reg_val = USBC_Readl(regs + USBC_REG_o_PHYTUNE);
230 #if defined(CONFIG_ARCH_SUN8IW18)
231 	reg_val |= (0x01 << 1);
232 #else
233 	reg_val |= 0x03 << 2;	/* TXRESTUNE */
234 #endif
235 	reg_val &= ~(0xf << 8);
236 	reg_val |= 0xc << 8;	/* TXVREFTUNE */
237 	USBC_Writel(reg_val, (regs + USBC_REG_o_PHYTUNE));
238 }
239 
240 /*for new phy*/
usbc_new_phyx_tp_write(void __iomem * regs,int addr,int data,int len)241 static int usbc_new_phyx_tp_write(void __iomem *regs,
242 		int addr, int data, int len)
243 {
244 	int temp = 0;
245 	int j = 0;
246 	int dtmp = 0;
247 
248 	/*device: 0x410(phy_ctl)*/
249 	dtmp = data;
250 
251 	for (j = 0; j < len; j++) {
252 
253 		temp = USBC_Readb(regs + USBPHYC_REG_o_PHYCTL);
254 		temp |= (0x1 << 1);
255 		USBC_Writeb(temp, regs + USBPHYC_REG_o_PHYCTL);
256 
257 		USBC_Writeb(addr + j, regs + USBPHYC_REG_o_PHYCTL + 1);
258 
259 		temp = USBC_Readb(regs + USBPHYC_REG_o_PHYCTL);
260 		temp &= ~(0x1 << 0);
261 		USBC_Writeb(temp, regs + USBPHYC_REG_o_PHYCTL);
262 
263 		temp = USBC_Readb(regs + USBPHYC_REG_o_PHYCTL);
264 		temp &= ~(0x1 << 7);
265 		temp |= (dtmp & 0x1) << 7;
266 		USBC_Writeb(temp, regs + USBPHYC_REG_o_PHYCTL);
267 
268 		temp |= (0x1 << 0);
269 		USBC_Writeb(temp, regs + USBPHYC_REG_o_PHYCTL);
270 
271 		temp &= ~(0x1 << 0);
272 		USBC_Writeb(temp, regs + USBPHYC_REG_o_PHYCTL);
273 
274 		temp = USBC_Readb(regs + USBPHYC_REG_o_PHYCTL);
275 		temp &= ~(0x1 << 1);
276 		USBC_Writeb(temp, regs + USBPHYC_REG_o_PHYCTL);
277 
278 		dtmp >>= 1;
279 	}
280 
281 	return 0;
282 }
283 
usbc_new_phyx_tp_read(void __iomem * regs,int addr,int len)284 static int usbc_new_phyx_tp_read(void __iomem *regs, int addr, int len)
285 {
286 	int temp = 0;
287 	int i = 0;
288 	int j = 0;
289 	int ret = 0;
290 
291 	temp = USBC_Readb(regs + USBPHYC_REG_o_PHYCTL);
292 	temp |= (0x1 << 1);
293 	USBC_Writeb(temp, regs + USBPHYC_REG_o_PHYCTL);
294 
295 	for (j = len; j > 0; j--) {
296 		USBC_Writeb((addr + j - 1), regs + USBPHYC_REG_o_PHYCTL + 1);
297 
298 		for (i = 0; i < 0x4; i++)
299 			;
300 
301 		temp = USBC_Readb(regs + USBC_REG_o_PHYSTATUS);
302 		ret <<= 1;
303 		ret |= (temp & 0x1);
304 	}
305 
306 	temp = USBC_Readb(regs + USBPHYC_REG_o_PHYCTL);
307 	temp &= ~(0x1 << 1);
308 	USBC_Writeb(temp, regs + USBPHYC_REG_o_PHYCTL);
309 
310 	return ret;
311 }
312 
313 
usbc_new_phy_init(void __iomem * regs)314 void usbc_new_phy_init(void __iomem *regs)
315 {
316 	int value = 0;
317 	u32 efuse_val  = 0;
318 
319 	pr_debug("addr:%x,len:%x,value:%x\n", 0x03, 0x06,
320 			usbc_new_phyx_tp_read(regs, 0x03, 0x06));
321 	pr_debug("addr:%x,len:%x,value:%x\n", 0x16, 0x03,
322 			usbc_new_phyx_tp_read(regs, 0x16, 0x03));
323 	pr_debug("addr:%x,len:%x,value:%x\n", 0x0b, 0x08,
324 			usbc_new_phyx_tp_read(regs, 0x0b, 0x08));
325 	pr_debug("addr:%x,len:%x,value:%x\n", 0x09, 0x03,
326 			usbc_new_phyx_tp_read(regs, 0x09, 0x03));
327 
328 	sunxi_get_module_param_from_sid(&efuse_val, EFUSE_OFFSET, 4);
329 	pr_debug("efuse_val:0x%x\n", efuse_val);
330 
331 	usbc_new_phyx_tp_write(regs, 0x1c, 0x0, 0x03);
332 	pr_debug("addr:%x,len:%x,value:%x\n", 0x1c, 0x03,
333 			usbc_new_phyx_tp_read(regs, 0x1c, 0x03));
334 
335 	if (efuse_val & SUNXI_USB_PHY_EFUSE_ADJUST) {
336 		if (efuse_val & SUNXI_USB_PHY_EFUSE_MODE) {
337 			/* iref mode */
338 			usbc_new_phyx_tp_write(regs, 0x60, 0x1, 0x01);
339 
340 			/* usbc-0 */
341 			value = (efuse_val & SUNXI_USB_PHY_EFUSE_USB0TX) >> 22;
342 			usbc_new_phyx_tp_write(regs, 0x61, value, 0x03);
343 
344 			value = (efuse_val & SUNXI_USB_PHY_EFUSE_RES) >> 18;
345 			usbc_new_phyx_tp_write(regs, 0x44, value, 0x04);
346 
347 			pr_debug("addr:%x,len:%x,value:%x\n", 0x60, 0x01,
348 				usbc_new_phyx_tp_read(regs, 0x60, 0x01));
349 			pr_debug("addr:%x,len:%x,value:%x\n", 0x61, 0x03,
350 				usbc_new_phyx_tp_read(regs, 0x61, 0x03));
351 			pr_debug("addr:%x,len:%x,value:%x\n", 0x44, 0x04,
352 				usbc_new_phyx_tp_read(regs, 0x44, 0x04));
353 		} else {
354 			/* verf mode */
355 			usbc_new_phyx_tp_write(regs, 0x60, 0x0, 0x01);
356 
357 			value = (efuse_val & SUNXI_USB_PHY_EFUSE_RES) >> 18;
358 			usbc_new_phyx_tp_write(regs, 0x44, value, 0x04);
359 
360 			value = (efuse_val & SUNXI_USB_PHY_EFUSE_COM) >> 22;
361 			usbc_new_phyx_tp_write(regs, 0x36, value, 0x03);
362 
363 			pr_debug("addr:%x,len:%x,value:%x\n", 0x60, 0x01,
364 				usbc_new_phyx_tp_read(regs, 0x60, 0x01));
365 			pr_debug("addr:%x,len:%x,value:%x\n", 0x44, 0x04,
366 				usbc_new_phyx_tp_read(regs, 0x44, 0x04));
367 			pr_debug("addr:%x,len:%x,value:%x\n", 0x36, 0x03,
368 				usbc_new_phyx_tp_read(regs, 0x36, 0x03));
369 		}
370 	}
371 
372 	pr_debug("addr:%x,len:%x,value:%x\n", 0x03, 0x06,
373 			usbc_new_phyx_tp_read(regs, 0x03, 0x06));
374 	pr_debug("addr:%x,len:%x,value:%x\n", 0x16, 0x03,
375 			usbc_new_phyx_tp_read(regs, 0x16, 0x03));
376 	pr_debug("addr:%x,len:%x,value:%x\n", 0x0b, 0x08,
377 			usbc_new_phyx_tp_read(regs, 0x0b, 0x08));
378 	pr_debug("addr:%x,len:%x,value:%x\n", 0x09, 0x03,
379 			usbc_new_phyx_tp_read(regs, 0x09, 0x03));
380 }
381 
usbc_new_phy_res_cal(void __iomem * regs)382 void usbc_new_phy_res_cal(void __iomem *regs)
383 {
384 	int value;
385 
386 	/*clear software res cail*/
387 	usbc_new_phyx_tp_write(regs, 0x43, 0x0, 0x01);
388 	usbc_new_phyx_tp_write(regs, 0x41, 0x0, 0x01);
389 	usbc_new_phyx_tp_write(regs, 0x40, 0x0, 0x01);
390 	/*res cail*/
391 	usbc_new_phyx_tp_write(regs, 0x40, 0x01, 0x01);
392 	mdelay(1);
393 	usbc_new_phyx_tp_write(regs, 0x41, 0x01, 0x01);
394 
395 	while (1) {
396 		if (usbc_new_phyx_tp_read(regs, 0x42, 0x01))
397 			break;
398 	}
399 
400 	/*set res*/
401 	value = usbc_new_phyx_tp_read(regs, 0x49, 0x04);
402 	pr_debug("addr:%x,,value:%x\n", 0x49, value);
403 	usbc_new_phyx_tp_write(regs, 0x44, value, 0x04);
404 	usbc_new_phyx_tp_write(regs, 0x41, 0x0, 0x01);
405 	usbc_new_phyx_tp_write(regs, 0x40, 0x0, 0x01);
406 	usbc_new_phyx_tp_write(regs, 0x43, 0x01, 0x01);
407 }
408 
409