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