1 /**
2  * drivers/usb/host/ehci_sunxi.c
3  * (C) Copyright 2010-2015
4  * Allwinner Technology Co., Ltd. <www.allwinnertech.com>
5  * yangnaitian, 2011-5-24, create this file
6  * javen, 2011-6-26, add suspend and resume
7  * javen, 2011-7-18, move clock and power operations out from driver
8  *
9  * SoftWinner EHCI Driver
10  *
11  * This program is free software; you can redistribute it and/or
12  * modify it under the terms of the GNU General Public License as
13  * published by the Free Software Foundation; either version 2 of
14  * the License, or (at your option) any later version.
15  *
16  */
17 
18 #include <stdlib.h>
19 #include <string.h>
20 #include <usb_gen_hcd.h>
21 #include "sunxi-hci.h"
22 #include "platform_usb.h"
23 #include "ehci.h"
24 #include "hal_gpio.h"
25 #include "hal_cfg.h"
26 
27 #if USB_MAX_CONTROLLER_COUNT
28 static struct sunxi_hci_hcd g_sunxi_ehci[USB_MAX_CONTROLLER_COUNT];
29 #else
30 static struct sunxi_hci_hcd *g_sunxi_ehci = 0;
31 #endif
32 
33 static unsigned char g_sunxi_insmod_cnt = 0;
34 
sunxi_ehci_insmod_count(void)35 static void sunxi_ehci_insmod_count(void)
36 {
37     g_sunxi_insmod_cnt++;
38 }
39 
sunxi_ehci_rmmod_count(void)40 static void sunxi_ehci_rmmod_count(void)
41 {
42     if (g_sunxi_insmod_cnt > 0)
43     {
44         g_sunxi_insmod_cnt--;
45     }
46     else
47     {
48         hal_log_err("ERR: g_sunxi_insmod_cnt = %d", g_sunxi_insmod_cnt);
49     }
50 }
51 
sunxi_ehci_count(void)52 static unsigned char sunxi_ehci_count(void)
53 {
54     return g_sunxi_insmod_cnt;
55 }
56 
sunxi_hcd_board_set_vbus(struct sunxi_hci_hcd * sunxi_ehci,int is_on)57 static void sunxi_hcd_board_set_vbus(
58         struct sunxi_hci_hcd *sunxi_ehci, int is_on)
59 {
60     sunxi_ehci->set_power(sunxi_ehci, is_on);
61 }
62 
sunxi_hcd_board_set_passby(struct sunxi_hci_hcd * sunxi_ehci,int is_on)63 static void sunxi_hcd_board_set_passby(struct sunxi_hci_hcd *sunxi_ehci,
64                         int is_on)
65 {
66     sunxi_ehci->usb_passby(sunxi_ehci, is_on);
67 }
68 
open_ehci_clock(struct sunxi_hci_hcd * sunxi_ehci)69 static int open_ehci_clock(struct sunxi_hci_hcd *sunxi_ehci)
70 {
71     return sunxi_ehci->open_clock(sunxi_ehci, 0);
72 }
73 
close_ehci_clock(struct sunxi_hci_hcd * sunxi_ehci)74 static int close_ehci_clock(struct sunxi_hci_hcd *sunxi_ehci)
75 {
76     return sunxi_ehci->close_clock(sunxi_ehci, 0);
77 }
78 
sunxi_start_ehci(struct sunxi_hci_hcd * sunxi_ehci)79 static void sunxi_start_ehci(struct sunxi_hci_hcd *sunxi_ehci)
80 {
81     open_ehci_clock(sunxi_ehci);
82     sunxi_hcd_board_set_passby(sunxi_ehci, 1);
83     sunxi_hcd_board_set_vbus(sunxi_ehci, 1);
84 #if defined(CONFIG_ARCH_SUN8IW20) || defined(CONFIG_SOC_SUN20IW1)
85     sunxi_ehci_insmod_count();
86 #endif
87 }
88 
sunxi_stop_ehci(struct sunxi_hci_hcd * sunxi_ehci)89 static void sunxi_stop_ehci(struct sunxi_hci_hcd *sunxi_ehci)
90 {
91 #if defined(CONFIG_ARCH_SUN8IW20) || defined(CONFIG_SOC_SUN20IW1)
92     sunxi_ehci_rmmod_count();
93     if (sunxi_ehci_count() == 0)
94 #endif
95     {
96         sunxi_hcd_board_set_vbus(sunxi_ehci, 0);
97     }
98 
99     sunxi_hcd_board_set_passby(sunxi_ehci, 0);
100     close_ehci_clock(sunxi_ehci);
101 }
102 
sunxi_ehci_setup(struct hc_gen_dev * hcd)103 static int sunxi_ehci_setup(struct hc_gen_dev *hcd)
104 {
105     struct ehci_hcd *ehci = hcd_to_ehci(hcd);
106     int ret = ehci_init(hcd);
107 
108     //ehci->need_io_watchdog = 0;
109 
110     return ret;
111 }
112 
113 static const struct hc_driver sunxi_ehci_hc_driver = {
114     .description            = "ehci_hcd",
115     .product_desc           = "SW USB2.0 'Enhanced' Host Controller (EHCI) Driver",
116     .hcd_priv_size          = sizeof(struct ehci_hcd),
117 
118     /**
119      * generic hardware linkage
120      */
121     .irq                =  NULL,
122     //.flags                =  HCD_MEMORY | HCD_USB2 | HCD_BH,
123     .flags              =  HC_DRIVER_FLAG_HCD_USB2,
124 
125     /**
126      * basic lifecycle operations
127      *
128      * FIXME -- ehci_init() doesn't do enough here.
129      * See ehci-ppc-soc for a complete implementation.
130      */
131     .reset              = sunxi_ehci_setup,
132     .start              = ehci_run,
133     .stop               = ehci_stop,
134 //  .shutdown           = ehci_shutdown,
135 
136     /**
137      * managing i/o requests and associated device resources
138      */
139     .urb_enqueue            = ehci_urb_enqueue,
140     .urb_dequeue            = ehci_urb_dequeue,
141     .endpoint_disable       = ehci_endpoint_disable,
142 
143 //  .endpoint_reset         = ehci_endpoint_reset,
144 
145     /**
146      * scheduling support
147      */
148     .get_frame_number       = ehci_get_frame,
149 
150     /**
151      * root hub support
152      */
153     .hub_status_data        = ehci_hub_status_data,
154     .hub_control            = ehci_hub_control,
155     .hub_suspend            = ehci_bus_suspend,
156     .hub_resume             = ehci_bus_resume,
157 //  .relinquish_port        = ehci_relinquish_port,
158 //  .port_handed_over       = ehci_port_handed_over,
159 
160 //  .clear_tt_buffer_complete   = ehci_clear_tt_buffer_complete,
161 };
162 
sunxi_insmod_ehci(struct sunxi_hci_hcd * sunxi_ehci)163 int sunxi_insmod_ehci(struct sunxi_hci_hcd * sunxi_ehci)
164 {
165     /*
166      * hc_gen_dev----------usb_hcd
167      * hc_private----------ehci_hcd
168      * usb_host_virt_dev--------usb_device
169      * */
170     //struct usb_hcd *hcd   = NULL;
171     struct hc_gen_dev *hcd  = NULL;
172     struct ehci_hcd *ehci   = NULL;
173 
174     int     mask;
175     int port;
176     int ret = 0;
177 
178     hal_log_info("[%s%d]: probe, sunxi_ehci: 0x%p, 0x:%p, irq_no:%d\n",
179         sunxi_ehci->hci_name, sunxi_ehci->usbc_no, sunxi_ehci,
180         sunxi_ehci->usb_vbase, sunxi_ehci->irq_no);
181 
182     sunxi_ehci->ehci_base       = sunxi_ehci->usb_vbase;
183     sunxi_ehci->ehci_reg_length = SUNXI_USB_EHCI_LEN;
184 
185     /* creat a usb_hcd for the ehci controller*/
186     hcd = usb_create_hc_gen_dev(&sunxi_ehci_hc_driver, sunxi_ehci->hci_name);
187     //hcd = usb_create_hcd(&sunxi_ehci_hc_driver, sunxi_ehci->hci_name);
188     sunxi_ehci->hcd = hcd;
189 
190     /* request irq */
191     if (request_irq(sunxi_ehci->irq_no, ehci_irq_handler, sunxi_ehci->usb_irq_flag, "ehci", hcd) < 0) {
192         hal_log_err("request irq error\n");
193         return -1;
194     }
195 
196     enable_irq(sunxi_ehci->irq_no);
197 
198     /* echi start to work */
199     sunxi_start_ehci(sunxi_ehci);
200 
201     ehci = hcd_to_ehci(hcd);
202     ehci->caps = (struct ehci_caps *)(long)sunxi_ehci->ehci_base;
203     ehci->regs = (struct ehci_regs *)((long)ehci->caps +
204             HC_LENGTH(ehci, hal_readl(&ehci->caps->hc_capbase)));
205 
206     /* cache this readonly data, minimize chip reads */
207     ehci->hcs_params = hal_readl(&ehci->caps->hcs_params);
208 
209     hcd->state = HC_GEN_DEV_STATE_RUNNING;
210     /*melis original func: usb_add_hc_gen_dev()*/
211     ret = usb_add_hc_gen_dev(hcd, sunxi_ehci->irq_no, IRQF_SHARED);
212     if (ret != 0) {
213         hal_log_err("ERR: usb_add_hcd failed\n");
214         ret = -ENOMEM;
215         goto ERR3;
216     }
217 
218     /* ehci_bus_suspend */
219     //port = HCS_N_PORTS(ehci->hcs_params);
220     //while (port--) {
221     //  uint32_t *reg = &ehci->regs->port_status [port];
222     //  uint32_t t1 = ehci_readl(ehci, reg) & ~PORT_RWC_BITS;
223     //  uint32_t t2 = t1 & ~PORT_WAKE_BITS;
224 
225     //  t2 |= PORT_WKOC_E | PORT_WKCONN_E;
226 
227     //  ehci_writel(ehci, t2, reg);
228     //}
229 
230     /* Do not halt the controller since the PM ops not supported yet. */
231     //ehci_halt (ehci);
232 
233     /* allow remote wakeup */
234     mask = INTR_MASK;
235     //if (!hcd->self.root_hub->do_remote_wakeup)
236     //  mask &= ~STS_PCD;
237     ehci_writel(ehci, mask, &ehci->regs->intr_enable);
238     ehci_readl(ehci, &ehci->regs->intr_enable);
239 
240     return 0;
241 
242 ERR3:
243     sunxi_stop_ehci(sunxi_ehci);
244     //usb_put_hcd(hcd);
245 
246 ERR2:
247     sunxi_ehci->hcd = NULL;
248     //g_sunxi_ehci[sunxi_ehci->usbc_no] = NULL;
249 
250 ERR1:
251 
252     return ret;
253 }
254 
sunxi_rmmod_ehci(struct sunxi_hci_hcd * sunxi_ehci)255 int sunxi_rmmod_ehci(struct sunxi_hci_hcd * sunxi_ehci)
256 {
257 
258 
259     hal_log_info("[%s%d]: remove, sunxi_ehci: 0x%p, 0x:%p, irq_no:%d\n",
260         sunxi_ehci->hci_name, sunxi_ehci->usbc_no, sunxi_ehci,
261         sunxi_ehci->usb_vbase, sunxi_ehci->irq_no);
262     //usb_remove_hcd(hcd);
263 
264     if (sunxi_ehci->irq_no > 0)
265     {
266         free_irq(sunxi_ehci->irq_no, sunxi_ehci->hcd);
267     }
268     //usb_put_hcd(hcd);
269 
270 //#if defined(CONFIG_SUNXI_REGULATOR_DT)
271 //  if (sunxi_ehci->supply)
272 //      regulator_put(sunxi_ehci->supply);
273 //#endif
274 //
275     sunxi_stop_ehci(sunxi_ehci);
276 
277     sunxi_ehci->hcd = NULL;
278 
279     return 0;
280 }
281 
sunxi_ehci_hcd_init(int hci_num)282 int sunxi_ehci_hcd_init(int hci_num)
283 {
284     int value = 0;
285     char ehci_name[10] = {0};
286     sprintf(ehci_name, "usbc%1d", hci_num);
287 
288     if (Hal_Cfg_GetKeyValue(ehci_name, KEY_USB_ENABLE, (int32_t *)&value, 1) == 0) {
289         if (value == SUNXI_USB_DISABLE) {
290             hal_log_err("ERR: ehci%d disable", hci_num);
291             return -1;
292         }
293     }
294 
295     if(g_sunxi_ehci == 0) {
296         hal_log_err("ERR: ehci%d NULL!", hci_num);
297         return -1;
298     }
299 
300     if (hci_num >= USB_MAX_CONTROLLER_COUNT) {
301         hal_log_err("ERR: ehci%d oversize!", hci_num);
302         return -1;
303     }
304 
305     int ret = 0;
306     struct sunxi_hci_hcd *sunxi_ehci = &g_sunxi_ehci[hci_num];
307 
308     if(!sunxi_ehci->hcd)
309     {
310         struct platform_usb_config *hci_table = platform_get_hci_table();
311         struct platform_usb_config *otg_table = platform_get_otg_table();
312 
313         sunxi_ehci->usbc_no     = hci_num;
314         sunxi_ehci->usb_vbase   = hci_table[hci_num].pbase;
315         sunxi_ehci->irq_no      = hci_table[hci_num].irq;
316         sunxi_ehci->otg_vbase   = otg_table->pbase;
317 
318         sprintf(sunxi_ehci->hci_name, "%s", hci_table[hci_num].name);
319 
320         hci_clock_init(sunxi_ehci);
321         sunxi_hci_get_config_param(sunxi_ehci);
322 
323         sunxi_ehci->open_clock          = open_clock;
324         sunxi_ehci->close_clock         = close_clock;
325         sunxi_ehci->set_power           = sunxi_set_vbus;
326         sunxi_ehci->usb_passby          = usb_passby;
327 
328         sunxi_insmod_ehci(sunxi_ehci);
329         return 0;
330     }
331     else
332     {
333         hal_log_err("ERR: ehci%d already exist!", hci_num);
334     }
335 
336     return -1;
337 }
338 
sunxi_ehci_hcd_deinit(int hci_num)339 int sunxi_ehci_hcd_deinit(int hci_num)
340 {
341 
342     struct sunxi_hci_hcd *sunxi_ehci = &g_sunxi_ehci[hci_num];
343 #if 0
344     /* TODO */
345     struct sunxi_hci_hcd *sunxi_ehci = NULL;
346 
347     int ret = 0;
348 
349     if (sunxi_ehci->probe == 1) {
350         ret = sunxi_rmmod_ehci(pdev);
351         if (ret == 0)
352             exit_sunxi_hci(sunxi_ehci);
353 
354         return ret;
355     } else
356         return 0;
357 #endif
358     if(sunxi_ehci->hcd)
359         return sunxi_rmmod_ehci(sunxi_ehci);
360     else
361         hal_log_err("ERR: ehci%d is NULL!", hci_num);
362 
363     return 0;
364 }
ehci_set_interrupt_enable(const struct ehci_hcd * ehci,uint32_t regs,u32 enable)365 static void  ehci_set_interrupt_enable(const struct ehci_hcd *ehci,
366         uint32_t regs, u32 enable)
367 {
368     USBC_Writel(enable & 0x3f, (regs + EHCI_OPR_USBINTR));
369 }
ehci_disable_periodic_schedule(const struct ehci_hcd * ehci,uint32_t regs)370 static void ehci_disable_periodic_schedule(const struct ehci_hcd *ehci,
371         uint32_t regs)
372 {
373     u32 reg_val = 0;
374 
375     reg_val =  USBC_Readl(regs + EHCI_OPR_USBCMD);
376     reg_val &= ~(0x1<<4);
377     USBC_Writel(reg_val, (regs + EHCI_OPR_USBCMD));
378 }
379 
ehci_disable_async_schedule(const struct ehci_hcd * ehci,uint32_t regs)380 static void ehci_disable_async_schedule(const struct ehci_hcd *ehci,
381         uint32_t regs)
382 {
383     unsigned int reg_val = 0;
384 
385     reg_val =  USBC_Readl(regs + EHCI_OPR_USBCMD);
386     reg_val &= ~(0x1<<5);
387     USBC_Writel(reg_val, (regs + EHCI_OPR_USBCMD));
388 }
389 
ehci_set_config_flag(const struct ehci_hcd * ehci,uint32_t regs)390 static void ehci_set_config_flag(const struct ehci_hcd *ehci,
391         uint32_t regs)
392 {
393     USBC_Writel(0x1, (regs + EHCI_OPR_CFGFLAG));
394 }
395 
ehci_test_stop(const struct ehci_hcd * ehci,uint32_t regs)396 static void ehci_test_stop(const struct ehci_hcd *ehci,
397         uint32_t regs)
398 {
399     unsigned int reg_val = 0;
400 
401     reg_val =  USBC_Readl(regs + EHCI_OPR_USBCMD);
402     reg_val &= (~0x1);
403     USBC_Writel(reg_val, (regs + EHCI_OPR_USBCMD));
404 }
405 
ehci_test_reset(const struct ehci_hcd * ehci,uint32_t regs)406 static void ehci_test_reset(const struct ehci_hcd *ehci,
407         uint32_t regs)
408 {
409     u32 reg_val = 0;
410 
411     reg_val =  USBC_Readl(regs + EHCI_OPR_USBCMD);
412     reg_val |= (0x1<<1);
413     USBC_Writel(reg_val, (regs + EHCI_OPR_USBCMD));
414 }
415 
ehci_test_reset_complete(const struct ehci_hcd * ehci,uint32_t regs)416 static unsigned int ehci_test_reset_complete(const struct ehci_hcd *ehci,
417         uint32_t regs)
418 {
419 
420     unsigned int reg_val = 0;
421 
422     reg_val = USBC_Readl(regs + EHCI_OPR_USBCMD);
423     reg_val &= (0x1<<1);
424 
425     return !reg_val;
426 }
427 
ehci_start(const struct ehci_hcd * ehci,uint32_t regs)428 static void ehci_start(const struct ehci_hcd *ehci, uint32_t regs)
429 {
430     unsigned int reg_val = 0;
431 
432     reg_val =  USBC_Readl(regs + EHCI_OPR_USBCMD);
433     reg_val |= 0x1;
434     USBC_Writel(reg_val, (regs + EHCI_OPR_USBCMD));
435 }
436 
ehci_is_halt(const struct ehci_hcd * ehci,uint32_t regs)437 static unsigned int ehci_is_halt(const struct ehci_hcd *ehci,
438         uint32_t regs)
439 {
440     unsigned int reg_val = 0;
441 
442     reg_val = USBC_Readl(regs + EHCI_OPR_USBSTS) >> 12;
443     reg_val &= 0x1;
444     return reg_val;
445 }
446 
ehci_port_control(const struct ehci_hcd * ehci,uint32_t regs,u32 port_no,u32 control)447 static void ehci_port_control(const struct ehci_hcd *ehci,
448         uint32_t regs, u32 port_no, u32 control)
449 {
450     USBC_Writel(control, (regs + EHCI_OPR_USBCMD + (port_no<<2)));
451 }
452 
ehci_put_port_suspend(const struct ehci_hcd * ehci,uint32_t regs)453 static void  ehci_put_port_suspend(const struct ehci_hcd *ehci,
454         uint32_t regs)
455 {
456     unsigned int reg_val = 0;
457 
458     reg_val =  USBC_Readl(regs + EHCI_OPR_PORTSC);
459     reg_val |= (0x01<<7);
460     USBC_Writel(reg_val, (regs + EHCI_OPR_PORTSC));
461 }
462 
ehci_test_mode(const struct ehci_hcd * ehci,uint32_t regs,u32 test_mode)463 static void ehci_test_mode(const struct ehci_hcd *ehci,
464         uint32_t regs, u32 test_mode)
465 {
466     unsigned int reg_val = 0;
467 
468     reg_val =  USBC_Readl(regs + EHCI_OPR_PORTSC);
469     reg_val &= ~(0x0f<<16);
470     reg_val |= test_mode;
471     USBC_Writel(reg_val, (regs + EHCI_OPR_PORTSC));
472 }
473 
__ehci_ed_test(const struct ehci_hcd * ehci,uint32_t regs,__u32 test_mode)474 static void __ehci_ed_test(const struct ehci_hcd *ehci,
475         uint32_t regs, __u32 test_mode)
476 {
477     printf("regs: 0x%x\n", regs);
478     ehci_set_interrupt_enable(ehci, regs, 0x00);
479     ehci_disable_periodic_schedule(ehci, regs);
480     ehci_disable_async_schedule(ehci, regs);
481 
482     ehci_set_config_flag(ehci, regs);
483 
484     ehci_test_stop(ehci, regs);
485     ehci_test_reset(ehci, regs);
486 
487     /* Wait until EHCI reset complete. */
488     while (!ehci_test_reset_complete(ehci, regs))
489         ;
490 
491     if (!ehci_is_halt(ehci, regs)) {
492         DMSG_ERR("%s_%d\n", __func__, __LINE__);
493     }
494 
495     ehci_start(ehci, regs);
496     /* Wait until EHCI to be not halt. */
497     while (ehci_is_halt(ehci, regs))
498         DMSG_ERR("%s_%d\n", __func__, __LINE__);
499         ;
500 
501     /* Ehci start, config to test. */
502     ehci_set_config_flag(ehci, regs);
503     ehci_port_control(ehci, regs, 0, EHCI_PORTSC_POWER);
504 
505     ehci_disable_periodic_schedule(ehci, regs);
506     ehci_disable_async_schedule(ehci, regs);
507 
508     /* Put port suspend. */
509     ehci_put_port_suspend(ehci, regs);
510 
511     ehci_test_stop(ehci, regs);
512 
513     while ((!ehci_is_halt(ehci, regs)))
514         DMSG_ERR("%s_%d\n", __func__, __LINE__);
515         ;
516 
517     /* Test pack. */
518     DMSG_INFO("Start Host Test,mode:0x%x!\n", test_mode);
519     ehci_test_mode(ehci, regs, test_mode);
520     DMSG_INFO("End Host Test,mode:0x%x!\n", test_mode);
521 }
522 
ehci_ed_test(int hci_num,const char * buf,unsigned int count)523 unsigned int ehci_ed_test(int hci_num, const char *buf, unsigned int count)
524 {
525     __u32 test_mode = 0;
526     struct sunxi_hci_hcd *sunxi_ehci = &g_sunxi_ehci[hci_num];
527     struct hc_gen_dev *hcd  = sunxi_ehci->hcd;
528     struct ehci_hcd *ehci   = NULL;
529 
530     ehci = hcd_to_ehci(hcd);
531     if (ehci == NULL) {
532         DMSG_PANIC("ERR: ehci is null\n");
533         return 0;
534     }
535     DMSG_INFO("ehci_ed_test:%s\n", buf);
536     if (!strncmp(buf, "test_not_operating", 18)) {
537         test_mode = EHCI_PORTSC_PTC_DIS;
538         DMSG_INFO("test_mode:0x%x\n", test_mode);
539     } else if (!strncmp(buf, "test_j_state", 12)) {
540         test_mode = EHCI_PORTSC_PTC_J;
541         DMSG_INFO("test_mode:0x%x\n", test_mode);
542     } else if (!strncmp(buf, "test_k_state", 12)) {
543         test_mode = EHCI_PORTSC_PTC_K;
544         DMSG_INFO("test_mode:0x%x\n", test_mode);
545     } else if (!strncmp(buf, "test_se0_nak", 12)) {
546         test_mode = EHCI_PORTSC_PTC_SE0NAK;
547         DMSG_INFO("test_mode:0x%x\n", test_mode);
548     } else if (!strncmp(buf, "test_pack", 9)) {
549         test_mode = EHCI_PORTSC_PTC_PACKET;
550         DMSG_INFO("test_mode:0x%x\n", test_mode);
551     } else if (!strncmp(buf, "test_force_enable", 17)) {
552         test_mode = EHCI_PORTSC_PTC_FORCE;
553         DMSG_INFO("test_mode:0x%x\n", test_mode);
554     } else if (!strncmp(buf, "test_mask", 9)) {
555         test_mode = EHCI_PORTSC_PTC_MASK;
556         DMSG_INFO("test_mode:0x%x\n", test_mode);
557     } else {
558         DMSG_PANIC("ERR: test_mode Argment is invalid\n");
559         return count;
560     }
561 
562     printf("regs: 0x%x\n", sunxi_ehci->usb_vbase);
563     __ehci_ed_test(ehci, sunxi_ehci->usb_vbase, test_mode);
564 
565     return count;
566 }
ehci_usb_driverlevel_adjust(int hci_num,int driverlevel)567 unsigned int ehci_usb_driverlevel_adjust(int hci_num, int driverlevel)
568 {
569     struct sunxi_hci_hcd *sunxi_ehci = &g_sunxi_ehci[hci_num];
570     usb_new_phy_adjust(sunxi_ehci, driverlevel);
571     return 0;
572 }
573 
574