1 #include <linux/kernel.h>
2 #include <linux/platform_device.h>
3 #include <linux/delay.h>
4 #include <linux/dma-mapping.h>
7 #include <linux/wakelock.h>
8 #include <linux/workqueue.h>
9 #include <linux/interrupt.h>
10 #include <linux/irq.h>
12 #include <mach/irqs.h>
13 #include <mach/gpio.h>
14 #include <mach/iomux.h>
16 #include <mach/board.h>
18 #include "usbdev_rk.h"
19 #include "dwc_otg_regs.h"
21 #ifdef CONFIG_ARCH_RK319X
22 #include "usbdev_rk3190_grf_regs.h"
24 pGRF_UOC0_REG USBGRF_UOC0 = (pGRF_UOC0_REG)(GRF_UOC0_BASE);
25 pGRF_UOC1_REG USBGRF_UOC1 = (pGRF_UOC1_REG)(GRF_UOC1_BASE);
26 pGRF_HSIC_REG USBGRF_HSIC = (pGRF_HSIC_REG)(GRF_UOC2_BASE);
27 pGRF_USBPHY_REG GRF_USBPHY1 = (pGRF_USBPHY_REG)(GRF_USBPHY1_CON_BASE);
28 pGRF_SOC_STATUS USBGRF_STATUS = (pGRF_SOC_STATUS)(USBGRF_SOC_STATUS0);
30 int dwc_otg_check_dpdm(void)
33 static uint8_t * reg_base = 0;
34 volatile unsigned int * otg_dctl;
35 volatile unsigned int * otg_gotgctl;
36 volatile unsigned int * otg_hprt0;
38 unsigned int * otg_phy_con0 = (unsigned int*)(USBGRF_UOC0_CON0) ;
40 *(unsigned int*)(RK319X_CRU_BASE+0x120) = ((7<<5)<<16)|(7<<5); // otg0 phy clkgate
42 *(unsigned int*)(RK319X_CRU_BASE+0x120) = ((7<<5)<<16)|(0<<5); // otg0 phy clkgate
44 *(unsigned int*)(RK319X_CRU_BASE+0xd4) = ((1<<5)<<16); // otg0 phy clkgate
45 *(unsigned int*)(RK319X_CRU_BASE+0xe4) = ((1<<13)<<16); // otg0 hclk clkgate
46 *(unsigned int*)(RK319X_CRU_BASE+0xf4) = ((3<<10)<<16); // hclk usb clkgat
49 *otg_phy_con0 = ((0x01<<0)<<16);
53 reg_base = ioremap(RK319X_USBOTG20_PHYS, RK319X_USBOTG20_SIZE);
60 //printk("regbase %p 0x%x, otg_phy_con%p, 0x%x\n",
61 // reg_base, *(reg_base), otg_phy_con1, *otg_phy_con1);
62 otg_dctl = (unsigned int * )(reg_base+0x804);
63 otg_gotgctl = (unsigned int * )(reg_base);
64 otg_hprt0 = (unsigned int * )(reg_base + DWC_OTG_HOST_PORT_REGS_OFFSET);
65 if(*otg_gotgctl &(1<<19)){
67 *otg_dctl &= ~(0x01<<1);//exit soft-disconnect mode
68 mdelay(1); // delay about 1ms
70 if((*otg_hprt0 & 0xc00)==0xc00)//check hprt[11:10]
72 //*(unsigned int*)(GRF_REG_BASE + GRF_UOC0_CON0) = 0x10001000;
80 EXPORT_SYMBOL(dwc_otg_check_dpdm);
82 /***********************************
87 3 : CDP - pc with big currect charge
88 ***********************************/
89 /* When do BC detect PCD pull-up register should be disabled */
91 #define T_DCD_TIMEOUT (200)
92 #define T_BC_WAIT_CHGDET (40)
93 #define T_BC_SRC_OFF (10)
95 int usb_battery_charger_detect(void)
101 if(USBGRF_STATUS->otg_vbusvalid){
103 mdelay(T_DCD_TIMEOUT);//no DCD just wait for timeout
106 USBGRF_UOC0->CON2 = 0x00e000e0;
107 timeout = T_BC_WAIT_CHGDET;
109 if((USBGRF_STATUS->snps_chgdet))
114 /* SDP and CDP/DCP distinguish */
115 if(!(USBGRF_STATUS->snps_chgdet))
118 /* Turn off VDPSRC */
119 USBGRF_UOC0->CON2 = 0x00e00000;
124 //Secondary Detection
125 USBGRF_UOC0->CON2 = 0x00e000c0;
126 timeout = T_BC_SRC_OFF;
128 if((USBGRF_UOC0->CON2 & 0x00e0) == 0x00c0)
133 timeout = T_BC_WAIT_CHGDET;
135 if((USBGRF_STATUS->snps_chgdet))
140 if((USBGRF_STATUS->snps_chgdet))
145 USBGRF_UOC0->CON2 = 0x00e00000;
146 timeout = T_BC_SRC_OFF;
148 if((USBGRF_UOC0->CON2 & 0x00e0) == 0x00c0)
154 printk("%s , battery_charger_detect %d\n", __func__, port_type);
157 EXPORT_SYMBOL(usb_battery_charger_detect);
160 #ifdef CONFIG_USB20_OTG
162 static struct resource usb20_otg_resource[] = {
164 .start = IRQ_USB_OTG,
166 .flags = IORESOURCE_IRQ,
169 .start = RK319X_USBOTG20_PHYS,
170 .end = RK319X_USBOTG20_PHYS + RK319X_USBOTG20_SIZE - 1,
171 .flags = IORESOURCE_MEM,
176 void usb20otg_hw_init(void)
178 #ifndef CONFIG_USB20_HOST
179 // close USB 2.0 HOST phy and clock
180 USBGRF_UOC1->CON1 = 0x007f0055;
183 // usb phy config init
185 // other hardware init
186 iomux_set(OTG_DRV_VBUS);
188 void usb20otg_phy_suspend(void* pdata, int suspend)
190 struct dwc_otg_platform_data *usbpdata=pdata;
192 USBGRF_UOC0->CON3 = 0x003f002a;
193 USBGRF_UOC0->CON2 = 0x00040004;
195 usbpdata->phy_status = 1;
198 USBGRF_UOC0->CON2 = 0x00040000;
199 usbpdata->phy_status = 0;
203 void usb20otg_soft_reset(void)
205 cru_set_soft_reset(SOFT_RST_USBOTG0, true);
206 cru_set_soft_reset(SOFT_RST_USBPHY0, true);
207 cru_set_soft_reset(SOFT_RST_OTGC0, true);
210 cru_set_soft_reset(SOFT_RST_USBOTG0, false);
211 cru_set_soft_reset(SOFT_RST_USBPHY0, false);
212 cru_set_soft_reset(SOFT_RST_OTGC0, false);
216 void usb20otg_clock_init(void* pdata)
218 struct dwc_otg_platform_data *usbpdata=pdata;
219 struct clk* ahbclk,*phyclk;
220 ahbclk = clk_get(NULL, "hclk_otg0");
221 phyclk = clk_get(NULL, "otgphy0_480m_vir");
222 usbpdata->phyclk = phyclk;
223 usbpdata->ahbclk = ahbclk;
225 void usb20otg_clock_enable(void* pdata, int enable)
227 struct dwc_otg_platform_data *usbpdata=pdata;
229 clk_enable(usbpdata->ahbclk);
230 clk_enable(usbpdata->phyclk);
233 clk_disable(usbpdata->phyclk);
234 clk_disable(usbpdata->ahbclk);
237 int usb20otg_get_status(int id)
242 case USB_STATUS_BVABLID:
244 ret = USBGRF_STATUS->otg_bvalid;
246 case USB_STATUS_DPDM:
248 ret = USBGRF_STATUS->otg_linestate;
252 ret = USBGRF_STATUS->otg_iddig;
260 void dwc_otg_uart_mode(void* pdata, int enter_usb_uart_mode)
262 #ifdef CONFIG_RK_USB_UART
263 //struct dwc_otg_platform_data *usbpdata=pdata;//1:uart 0:usb
264 if(1 == enter_usb_uart_mode) //uart mode
266 USBGRF_UOC0->CON0 = 0x03000300;
267 printk("otg-phy enter uart mode USBGRF_UOC1_CON0 = 0x%08x\n",USBGRF_UOC0->CON0);
270 if(0 == enter_usb_uart_mode) //usb mode
272 USBGRF_UOC0->CON0 = 0x03000000;
273 printk("otg-phy enter usb mode USBGRF_UOC1_CON0 = 0x%08x\n",USBGRF_UOC0->CON0);
278 void usb20otg_power_enable(int enable)
282 struct dwc_otg_platform_data usb20otg_pdata = {
287 .hw_init=usb20otg_hw_init,
288 .phy_suspend=usb20otg_phy_suspend,
289 .soft_reset=usb20otg_soft_reset,
290 .clock_init=usb20otg_clock_init,
291 .clock_enable=usb20otg_clock_enable,
292 .get_status=usb20otg_get_status,
293 .dwc_otg_uart_mode=dwc_otg_uart_mode,
296 struct platform_device device_usb20_otg = {
299 .num_resources = ARRAY_SIZE(usb20_otg_resource),
300 .resource = usb20_otg_resource,
302 .platform_data = &usb20otg_pdata,
306 #ifdef CONFIG_USB20_HOST
307 static struct resource usb20_host_resource[] = {
309 .start = IRQ_USB_HOST,
311 .flags = IORESOURCE_IRQ,
314 .start = RK319X_USBHOST20_PHYS,
315 .end = RK319X_USBHOST20_PHYS + RK319X_USBHOST20_SIZE - 1,
316 .flags = IORESOURCE_MEM,
321 void usb20host_hw_init(void)
323 // usb phy config init
325 //GRF_USBPHY1->CON7 = 0x78000000;//host_discon_con 575mv
326 GRF_USBPHY1->CON0 = 0xffff8518;
327 GRF_USBPHY1->CON1 = 0xffffe007;
328 GRF_USBPHY1->CON2 = 0xffff82c9;
329 GRF_USBPHY1->CON3 = 0xffff0202;
330 GRF_USBPHY1->CON4 = 0xffff5556;
331 GRF_USBPHY1->CON5 = 0xffff5555;
332 GRF_USBPHY1->CON6 = 0xffff0005;
333 GRF_USBPHY1->CON7 = 0xffff68d0;
334 GRF_USBPHY1->CON8 = 0xffff0001;
336 // other haredware init
337 iomux_set(HOST_DRV_VBUS);
339 void usb20host_phy_suspend(void* pdata, int suspend)
341 struct dwc_otg_platform_data *usbpdata=pdata;
344 USBGRF_UOC1->CON1 = 0x007f0051;
345 usbpdata->phy_status = 1;
348 USBGRF_UOC1->CON1 = 0x00010000;
349 usbpdata->phy_status = 0;
352 void usb20host_soft_reset(void)
355 USBGRF_UOC1->CON1 = 0x00030001;
357 cru_set_soft_reset(SOFT_RST_USBPHY1_UTMI, true);
361 USBGRF_UOC1->CON1 = 0x00030002;
364 cru_set_soft_reset(SOFT_RST_USBPHY1_UTMI, false);
366 cru_set_soft_reset(SOFT_RST_USBOTG1, true);
367 cru_set_soft_reset(SOFT_RST_USBPHY1, true);
368 cru_set_soft_reset(SOFT_RST_OTGC1, true);
371 cru_set_soft_reset(SOFT_RST_USBOTG1, false);
372 cru_set_soft_reset(SOFT_RST_USBPHY1, false);
373 cru_set_soft_reset(SOFT_RST_OTGC1, false);
378 void usb20host_clock_init(void* pdata)
380 struct dwc_otg_platform_data *usbpdata=pdata;
381 struct clk* ahbclk,*phyclk;
382 ahbclk = clk_get(NULL, "hclk_otg1");
383 phyclk = clk_get(NULL, "otgphy1_480m_vir");
384 usbpdata->phyclk = phyclk;
385 usbpdata->ahbclk = ahbclk;
388 void usb20host_clock_enable(void* pdata, int enable)
390 struct dwc_otg_platform_data *usbpdata=pdata;
393 clk_enable(usbpdata->ahbclk);
394 clk_enable(usbpdata->phyclk);
397 clk_disable(usbpdata->ahbclk);
398 //clk_disable(usbpdata->phyclk);
401 int usb20host_get_status(int id)
404 pGRF_SOC_STATUS USBGRF_STATUS = (pGRF_SOC_STATUS)(USBGRF_SOC_STATUS0);
407 case USB_STATUS_BVABLID:
409 ret = USBGRF_STATUS->uhost_bvalid;
411 case USB_STATUS_DPDM:
413 ret = USBGRF_STATUS->uhost_linestate;
424 void usb20host_power_enable(int enable)
428 struct dwc_otg_platform_data usb20host_pdata = {
433 .hw_init=usb20host_hw_init,
434 .phy_suspend=usb20host_phy_suspend,
435 .soft_reset=usb20host_soft_reset,
436 .clock_init=usb20host_clock_init,
437 .clock_enable=usb20host_clock_enable,
438 .get_status=usb20host_get_status,
441 struct platform_device device_usb20_host = {
442 .name = "usb20_host",
444 .num_resources = ARRAY_SIZE(usb20_host_resource),
445 .resource = usb20_host_resource,
447 .platform_data = &usb20host_pdata,
451 #ifdef CONFIG_USB_EHCI_RK
452 void rkehci_hw_init(void)
454 // usb phy config init
455 // hsic phy config init, set hsicphy_txsrtune
456 USBGRF_HSIC->PHY_CON0 = 0x03c003c0;
458 // other haredware init
459 // set common_on, in suspend mode, otg/host PLL blocks remain powered
460 USBGRF_UOC1->CON0 = 0x00400000;
462 /* change INCR to INCR16 or INCR8(beats less than 16)
463 * or INCR4(beats less than 8) or SINGLE(beats less than 4)
465 USBGRF_HSIC->CTRLER_CON0 = 0x00ff00bc;
468 void rkehci_clock_init(void* pdata)
470 struct rkehci_platform_data *usbpdata=pdata;
472 struct clk *clk_otg, *clk_hs;
474 /* By default, hsicphy_480m's parent is otg phy 480MHz clk
475 * rk3188 must use host phy 480MHz clk
477 clk_hs = clk_get(NULL, "hsicphy_480m");
478 clk_otg = clk_get(NULL, "otgphy1_480m");
479 clk_set_parent(clk_hs, clk_otg);
481 usbpdata->hclk_hsic = clk_get(NULL, "hclk_hsic");
482 usbpdata->hsic_phy_480m = clk_get(NULL, "hsicphy_480m");
483 usbpdata->hsic_phy_12m = clk_get(NULL, "hsicphy_12m");
486 void rkehci_clock_enable(void* pdata, int enable)
488 struct rkehci_platform_data *usbpdata=pdata;
490 if(enable == usbpdata->clk_status)
494 clk_enable(usbpdata->hclk_hsic);
495 clk_enable(usbpdata->hsic_phy_480m);
496 clk_enable(usbpdata->hsic_phy_12m);
497 usbpdata->clk_status = 1;
499 clk_disable(usbpdata->hsic_phy_12m);
500 clk_disable(usbpdata->hsic_phy_480m);
501 clk_disable(usbpdata->hclk_hsic);
502 usbpdata->clk_status = 0;
506 void rkehci_soft_reset(void)
508 pGRF_HSIC_REG USBGRF_HSIC = (pGRF_HSIC_REG)(GRF_UOC2_BASE);
510 cru_set_soft_reset(SOFT_RST_HSICPHY, true);
512 cru_set_soft_reset(SOFT_RST_HSICPHY, false);
515 USBGRF_HSIC->PHY_CON0 = 0x04000400;
517 USBGRF_HSIC->PHY_CON0 = 0x04000000;
520 cru_set_soft_reset(SOFT_RST_HSIC_AHB, true);
522 cru_set_soft_reset(SOFT_RST_HSIC_AHB, false);
526 struct rkehci_platform_data rkehci_pdata = {
528 .hsic_phy_12m = NULL,
529 .hsic_phy_480m = NULL,
531 .hw_init = rkehci_hw_init,
532 .clock_init = rkehci_clock_init,
533 .clock_enable = rkehci_clock_enable,
534 .soft_reset = rkehci_soft_reset,
537 static struct resource resources_hsusb_host[] = {
541 .flags = IORESOURCE_IRQ,
544 .start = RK30_HSIC_PHYS,
545 .end = RK30_HSIC_PHYS + RK30_HSIC_SIZE - 1,
546 .flags = IORESOURCE_MEM,
550 struct platform_device device_hsusb_host = {
551 .name = "rk_hsusb_host",
553 .num_resources = ARRAY_SIZE(resources_hsusb_host),
554 .resource = resources_hsusb_host,
556 .coherent_dma_mask = 0xffffffff,
557 .platform_data = &rkehci_pdata,
561 static int __init usbdev_init_devices(void)
564 #ifdef CONFIG_USB20_OTG
565 ret |= platform_device_register(&device_usb20_otg);
567 #ifdef CONFIG_USB20_HOST
568 ret |= platform_device_register(&device_usb20_host);
570 #ifdef CONFIG_USB_EHCI_RK
571 ret |= platform_device_register(&device_hsusb_host);
574 printk("%s: platform_device_register(usb20_otg) failed\n", __func__);
578 arch_initcall(usbdev_init_devices);
580 /*********************************************************************
582 *********************************************************************/
584 #define WAKE_LOCK_TIMEOUT (HZ * 10)
586 static struct wake_lock usb_wakelock;
587 static struct delayed_work usb_det_wakeup_work;
589 inline void do_wakeup(void)
591 wake_lock_timeout(&usb_wakelock, WAKE_LOCK_TIMEOUT);
592 rk28_send_wakeup_key();
596 /*********** handler for bvalid irq ***********/
598 static irqreturn_t bvalid_irq_handler(int irq, void *dev_id)
601 #ifdef CONFIG_RK_USB_UART
602 /* usb otg dp/dm switch to usb phy */
603 dwc_otg_uart_mode(NULL, PHY_USB_MODE);
606 schedule_delayed_work(&usb_det_wakeup_work, 0);
608 /* clear irq pending */
609 writel_relaxed(0x02000200, &USBGRF_UOC0->CON3);
614 /***** handler for otg id rise and fall edge *****/
616 static irqreturn_t id_irq_handler(int irq, void *dev_id)
618 unsigned int uoc_con;
621 uoc_con = USBGRF_UOC0->CON3;
623 if(uoc_con & (1<<11))//id rise
625 writel_relaxed(0x08000800, &USBGRF_UOC0->CON3);//clear id rise irq pandding
627 if(uoc_con & (1<<13))//id fall
630 #ifdef CONFIG_RK_USB_UART
631 /* usb otg dp/dm switch to usb phy */
632 dwc_otg_uart_mode(NULL, PHY_USB_MODE);
635 writel_relaxed(0x20002000, &USBGRF_UOC0->CON3);//clear id fall irq pandding
637 schedule_delayed_work(&usb_det_wakeup_work, 0);
642 /***** handler for otg line status change *****/
644 static int __init otg_irq_detect_init(void)
647 int irq = IRQ_OTG_BVALID;
649 wake_lock_init(&usb_wakelock, WAKE_LOCK_SUSPEND, "usb_detect");
650 INIT_DELAYED_WORK(&usb_det_wakeup_work, do_wakeup);
652 ret = request_irq(irq, bvalid_irq_handler, 0, "bvalid", NULL);
654 pr_err("%s: request_irq(%d) failed\n", __func__, irq);
658 /* clear & enable bvalid irq */
659 writel_relaxed((3 << 8) | (3 << 24), &USBGRF_UOC0->CON3);
663 ret = request_irq(irq, id_irq_handler, 0, "otg-id", NULL);
665 pr_err("%s: request_irq(%d) failed\n", __func__, irq);
669 /* clear & enable otg change irq */
670 /* for rk3026 enable and clear id_fall_irq & id_rise_irq*/
671 writel_relaxed((0xf << 26) | (0xf << 10), &USBGRF_UOC0->CON3);
675 late_initcall(otg_irq_detect_init);