From 28d106f5703c470a9fdaaa24176e5d595431f29d Mon Sep 17 00:00:00 2001 From: wlf Date: Thu, 13 Feb 2014 15:45:30 +0800 Subject: [PATCH] USB: support usb otg and host20 functions --- arch/arm/boot/dts/rk3188.dtsi | 28 + arch/arm/configs/rockchip_defconfig | 3 + drivers/usb/Kconfig | 2 + drivers/usb/Makefile | 1 + drivers/usb/core/hcd.c | 6 +- drivers/usb/core/hub.c | 19 + drivers/usb/dwc_otg/Kconfig | 12 - drivers/usb/dwc_otg/Makefile | 2 +- drivers/usb/dwc_otg/dwc_otg_attr.c | 12 +- drivers/usb/dwc_otg/dwc_otg_cil.c | 105 +-- drivers/usb/dwc_otg/dwc_otg_driver.c | 166 ++-- drivers/usb/dwc_otg/dwc_otg_hcd.c | 14 +- drivers/usb/dwc_otg/dwc_otg_hcd.h | 2 +- drivers/usb/dwc_otg/dwc_otg_hcd_queue.c | 2 +- drivers/usb/dwc_otg/dwc_otg_pcd.c | 45 +- drivers/usb/dwc_otg/usbdev_rk.h | 13 + drivers/usb/dwc_otg/usbdev_rk30.c | 1015 +++++++++-------------- drivers/usb/gadget/android.c | 4 +- drivers/usb/gadget/composite.c | 5 + 19 files changed, 680 insertions(+), 776 deletions(-) mode change 100644 => 100755 arch/arm/boot/dts/rk3188.dtsi mode change 100644 => 100755 drivers/usb/core/hcd.c mode change 100644 => 100755 drivers/usb/core/hub.c mode change 100755 => 100644 drivers/usb/dwc_otg/usbdev_rk30.c diff --git a/arch/arm/boot/dts/rk3188.dtsi b/arch/arm/boot/dts/rk3188.dtsi old mode 100644 new mode 100755 index eaf10c731cc7..4f4154ad3628 --- a/arch/arm/boot/dts/rk3188.dtsi +++ b/arch/arm/boot/dts/rk3188.dtsi @@ -532,4 +532,32 @@ reg = <1>; }; }; + + dwc_control_usb: dwc-control-usb@0x200080ac { + compatible = "rockchip,dwc-control-usb"; + reg = <0x200080ac 0x4>, + <0x2000810c 0x10>, + <0x2000811c 0x10>; + reg-names = "GRF_SOC_STATUS0", + "GRF_UOC0_BASE", + "GRF_UOC1_BASE"; + gpios = <&gpio0 GPIO_C0 GPIO_ACTIVE_LOW>, <&gpio3 GPIO_D5 GPIO_ACTIVE_LOW>; + }; + + usb@10180000 { + compatible = "rockchip,usb20_otg"; + reg = <0x10180000 0x40000>; + interrupts = ; + /*clocks = <&clk_gates1 5>, <&clk_gates5 13>;*/ + /*clock-names = "otgphy0", "hclk_otg0"*/ + }; + + usb@101c0000 { + compatible = "rockchip,usb20_host"; + reg = <0x101c0000 0x40000>; + interrupts = ; + /*clocks = <&clk_gates1 6>, <&clk_gates7 3>;*/ + /*clock-names = "otgphy1", "hclk_otg1"*/ + }; + }; diff --git a/arch/arm/configs/rockchip_defconfig b/arch/arm/configs/rockchip_defconfig index c90fabf3b60a..b8645530990d 100755 --- a/arch/arm/configs/rockchip_defconfig +++ b/arch/arm/configs/rockchip_defconfig @@ -422,6 +422,9 @@ CONFIG_USB_STORAGE_ONETOUCH=y CONFIG_USB_STORAGE_KARMA=y CONFIG_USB_STORAGE_CYPRESS_ATACB=y CONFIG_USB_STORAGE_ENE_UB6250=y +CONFIG_USB20_HOST=y +CONFIG_USB20_OTG=y +CONFIG_DWC_OTG_BOTH_HOST_SLAVE=y CONFIG_USB_TRANCEVIBRATOR=y CONFIG_USB_OTG_WAKELOCK=y CONFIG_USB_GADGET=y diff --git a/drivers/usb/Kconfig b/drivers/usb/Kconfig index 92e1dc94ecc8..749bd14a9837 100644 --- a/drivers/usb/Kconfig +++ b/drivers/usb/Kconfig @@ -148,6 +148,8 @@ source "drivers/usb/dwc3/Kconfig" source "drivers/usb/chipidea/Kconfig" +source "drivers/usb/dwc_otg/Kconfig" + comment "USB port drivers" if USB diff --git a/drivers/usb/Makefile b/drivers/usb/Makefile index c41feba8d5c0..cfc8ceafa240 100644 --- a/drivers/usb/Makefile +++ b/drivers/usb/Makefile @@ -50,6 +50,7 @@ obj-$(CONFIG_EARLY_PRINTK_DBGP) += early/ obj-$(CONFIG_USB_ATM) += atm/ obj-$(CONFIG_USB_SPEEDTOUCH) += atm/ +obj-$(CONFIG_DWC_OTG) += dwc_otg/ obj-$(CONFIG_USB_MUSB_HDRC) += musb/ obj-$(CONFIG_USB_CHIPIDEA) += chipidea/ obj-$(CONFIG_USB_RENESAS_USBHS) += renesas_usbhs/ diff --git a/drivers/usb/core/hcd.c b/drivers/usb/core/hcd.c old mode 100644 new mode 100755 index d3aa353908aa..176f8af0d576 --- a/drivers/usb/core/hcd.c +++ b/drivers/usb/core/hcd.c @@ -1657,8 +1657,12 @@ void usb_hcd_giveback_urb(struct usb_hcd *hcd, struct urb *urb, int status) /* pass ownership to the completion handler */ urb->status = status; - urb->complete (urb); + if(!atomic_read(&urb->use_count)){ + printk("%s %d\n", __func__, atomic_read(&urb->use_count)); + return; + } atomic_dec (&urb->use_count); + urb->complete (urb); if (unlikely(atomic_read(&urb->reject))) wake_up (&usb_kill_urb_queue); usb_put_urb (urb); diff --git a/drivers/usb/core/hub.c b/drivers/usb/core/hub.c old mode 100644 new mode 100755 index 4d25bff2dac1..7783a7044e26 --- a/drivers/usb/core/hub.c +++ b/drivers/usb/core/hub.c @@ -1639,6 +1639,7 @@ static void hub_disconnect(struct usb_interface *intf) kref_put(&hub->kref, hub_release); } +struct usb_hub *g_dwc_otg_root_hub20 = NULL; static int hub_probe(struct usb_interface *intf, const struct usb_device_id *id) { struct usb_host_interface *desc; @@ -1728,6 +1729,9 @@ descriptor_error: return -ENOMEM; } + if(!g_dwc_otg_root_hub20){ + g_dwc_otg_root_hub20 = hub; + } kref_init(&hub->kref); INIT_LIST_HEAD(&hub->event_list); hub->intfdev = &intf->dev; @@ -4053,11 +4057,16 @@ hub_port_init (struct usb_hub *hub, struct usb_device *udev, int port1, udev->ttport = hdev->ttport; } else if (udev->speed != USB_SPEED_HIGH && hdev->speed == USB_SPEED_HIGH) { + /* yk@rk 20110617 + * parent hub has no TT would not be error in rk29 + */ + #if 0 if (!hub->tt.hub) { dev_err(&udev->dev, "parent hub has no TT\n"); retval = -EINVAL; goto fail; } + #endif udev->tt = &hub->tt; udev->ttport = port1; } @@ -4874,6 +4883,16 @@ static void hub_events(void) } /* end while (1) */ } +/* yk@rk 20100730 + * * disconnect all devices on dwc otg controller root hub + */ +void dwc_otg_hub_disconnect_device(struct usb_hub *hub) +{ + hub_port_connect_change(hub, 1, 0, 0x2); +} + +EXPORT_SYMBOL_GPL(dwc_otg_hub_disconnect_device); + static int hub_thread(void *__unused) { /* khubd needs to be freezable to avoid intefering with USB-PERSIST diff --git a/drivers/usb/dwc_otg/Kconfig b/drivers/usb/dwc_otg/Kconfig index 87d2a37e4018..967f87f1c4d5 100755 --- a/drivers/usb/dwc_otg/Kconfig +++ b/drivers/usb/dwc_otg/Kconfig @@ -1,15 +1,3 @@ -config USB11_HOST - tristate "RockChip USB 1.1 host controller" - depends on USB - ---help--- - This driver supports Rockchip USB 1.1 HOST - controller. - -config USB11_HOST_EN - bool "---usb1.1 host controller enable" - depends on USB11_HOST - default y - config USB20_HOST tristate "Rockchip USB 2.0 host controller" depends on USB diff --git a/drivers/usb/dwc_otg/Makefile b/drivers/usb/dwc_otg/Makefile index 2a27dfe6ab8c..c23bce656c54 100755 --- a/drivers/usb/dwc_otg/Makefile +++ b/drivers/usb/dwc_otg/Makefile @@ -29,6 +29,6 @@ dwc_otg-objs := dwc_otg_driver.o dwc_otg_attr.o dwc_otg-objs += dwc_otg_cil.o dwc_otg_cil_intr.o dwc_otg-objs += dwc_otg_pcd.o dwc_otg_pcd_intr.o dwc_otg-objs += dwc_otg_hcd.o dwc_otg_hcd_intr.o dwc_otg_hcd_queue.o -dwc_otg-objs += usbdev_rk30.o usbdev_rk2928.o usbdev_rk3026.o +dwc_otg-objs += usbdev_rk30.o obj-$(CONFIG_DWC_OTG) := dwc_otg.o diff --git a/drivers/usb/dwc_otg/dwc_otg_attr.c b/drivers/usb/dwc_otg/dwc_otg_attr.c index 9b7a5d3355aa..8420ba9b0685 100755 --- a/drivers/usb/dwc_otg/dwc_otg_attr.c +++ b/drivers/usb/dwc_otg/dwc_otg_attr.c @@ -424,7 +424,7 @@ DEVICE_ATTR(regvalue, S_IRUGO|S_IWUSR, regvalue_show, regvalue_store); /* * Attributes */ -DWC_OTG_DEVICE_ATTR_BITFIELD_RO(mode,&(otg_dev->core_if->core_global_regs->gotgctl),(1<<20),20,"Mode"); +DWC_OTG_DEVICE_ATTR_BITFIELD_RO(mode,&(otg_dev->core_if->core_global_regs->gintsts),(1<<0),0,"Mode"); DWC_OTG_DEVICE_ATTR_BITFIELD_RW(hnpcapable,&(otg_dev->core_if->core_global_regs->gusbcfg),(1<<9),9,"Mode"); DWC_OTG_DEVICE_ATTR_BITFIELD_RW(srpcapable,&(otg_dev->core_if->core_global_regs->gusbcfg),(1<<8),8,"Mode"); @@ -648,7 +648,7 @@ static ssize_t regdump_show( struct device *_dev, return sprintf( buf, "Register Dump\n" ); } -DEVICE_ATTR(regdump, S_IRUGO|S_IWUSR, regdump_show, 0); +DEVICE_ATTR(regdump, S_IRUGO, regdump_show, 0); /** * Dump the current hcd state. @@ -663,7 +663,7 @@ static ssize_t hcddump_show( struct device *_dev, return sprintf( buf, "HCD Dump\n" ); } -DEVICE_ATTR(hcddump, S_IRUGO|S_IWUSR, hcddump_show, 0); +DEVICE_ATTR(hcddump, S_IRUGO, hcddump_show, 0); /** * Dump the average frame remaining at SOF. This can be used to @@ -680,7 +680,7 @@ static ssize_t hcd_frrem_show( struct device *_dev, return sprintf( buf, "HCD Dump Frame Remaining\n" ); } -DEVICE_ATTR(hcd_frrem, S_IRUGO|S_IWUSR, hcd_frrem_show, 0); +DEVICE_ATTR(hcd_frrem, S_IRUGO, hcd_frrem_show, 0); /** * Displays the time required to read the GNPTXFSIZ register many times (the @@ -707,7 +707,7 @@ static ssize_t rd_reg_test_show( struct device *_dev, RW_REG_COUNT, time * MSEC_PER_JIFFIE, time ); } -DEVICE_ATTR(rd_reg_test, S_IRUGO|S_IWUSR, rd_reg_test_show, 0); +DEVICE_ATTR(rd_reg_test, S_IRUGO, rd_reg_test_show, 0); /** * Displays the time required to write the GNPTXFSIZ register many times (the @@ -734,7 +734,7 @@ static ssize_t wr_reg_test_show( struct device *_dev, RW_REG_COUNT, time * MSEC_PER_JIFFIE, time); } -DEVICE_ATTR(wr_reg_test, S_IRUGO|S_IWUSR, wr_reg_test_show, 0); +DEVICE_ATTR(wr_reg_test, S_IRUGO, wr_reg_test_show, 0); extern int dwc_debug(dwc_otg_core_if_t *core_if, int flag); static ssize_t debug_show( struct device *_dev, diff --git a/drivers/usb/dwc_otg/dwc_otg_cil.c b/drivers/usb/dwc_otg/dwc_otg_cil.c index 649b76b16a34..8bf8a734c1db 100755 --- a/drivers/usb/dwc_otg/dwc_otg_cil.c +++ b/drivers/usb/dwc_otg/dwc_otg_cil.c @@ -702,40 +702,41 @@ void dwc_otg_core_dev_init(dwc_otg_core_if_t *_core_if) _core_if->core_global_regs; dwc_otg_dev_if_t *dev_if = _core_if->dev_if; volatile dcfg_data_t dcfg = {.d32 = 0}; - volatile dctl_data_t dctl = {.d32 = 0}; - volatile grstctl_t grstctl = {.d32 = 0}; - volatile depctl_data_t depctl = {.d32 = 0}; - volatile daint_data_t daintmsk = {.d32 = 0}; - volatile gahbcfg_data_t gahbcfg = {.d32 = 0}; + volatile dctl_data_t dctl = {.d32 = 0}; + volatile grstctl_t grstctl = {.d32 = 0}; + volatile depctl_data_t depctl = {.d32 = 0}; + volatile daint_data_t daintmsk = {.d32 = 0}; + volatile gahbcfg_data_t gahbcfg = {.d32 = 0}; volatile dthrctl_data_t dthrctl; dwc_otg_core_reset(_core_if); /* Restart the Phy Clock */ dwc_write_reg32(_core_if->pcgcctl, 0); /* soft disconnect */ - dctl.d32 = dwc_read_reg32( &_core_if->dev_if->dev_global_regs->dctl ); - dctl.b.sftdiscon = 1; - dwc_write_reg32( &_core_if->dev_if->dev_global_regs->dctl, dctl.d32 ); + dctl.d32 = dwc_read_reg32( &_core_if->dev_if->dev_global_regs->dctl ); + dctl.b.sftdiscon = 1; + dwc_write_reg32( &_core_if->dev_if->dev_global_regs->dctl, dctl.d32 ); #ifdef CONFIG_ARCH_RK29 /* Configure data FIFO sizes, RK29 otg has 0x3c0 dwords total */ - dwc_write_reg32( &global_regs->grxfsiz, 0x00000210 ); - dwc_write_reg32( &global_regs->gnptxfsiz, 0x00100210 ); //ep0 tx fifo - dwc_write_reg32( &global_regs->dptxfsiz_dieptxf[0], 0x01000220 ); //ep1 tx fifo - dwc_write_reg32( &global_regs->dptxfsiz_dieptxf[1], 0x00100320 ); //ep3 tx fifo - dwc_write_reg32( &global_regs->dptxfsiz_dieptxf[2], 0x00800330 ); //ep5 tx fifo + dwc_write_reg32( &global_regs->grxfsiz, 0x00000210 ); + dwc_write_reg32( &global_regs->gnptxfsiz, 0x00100210 ); //ep0 tx fifo + dwc_write_reg32( &global_regs->dptxfsiz_dieptxf[0], 0x01000220 ); //ep1 tx fifo + dwc_write_reg32( &global_regs->dptxfsiz_dieptxf[1], 0x00100320 ); //ep3 tx fifo + dwc_write_reg32( &global_regs->dptxfsiz_dieptxf[2], 0x00800330 ); //ep5 tx fifo #else #if !(defined(CONFIG_ARCH_RK30) || defined(CONFIG_ARCH_RK3188) || \ - defined(CONFIG_ARCH_RK2928)|| defined(CONFIG_ARCH_RK3026) ) - DWC_ERROR("Warning!!! Please Check USB Controller FIFO Configuration\n"); + defined(CONFIG_ARCH_RK2928)|| defined(CONFIG_ARCH_RK3026) ||\ + defined(CONFIG_ARCH_ROCKCHIP)) + DWC_ERROR("Warning!!! Please Check USB Controller FIFO Configuration\n"); #endif /* Configure data FIFO sizes, RK30 otg has 0x3cc dwords total */ - dwc_write_reg32( &global_regs->grxfsiz, 0x00000120 ); - dwc_write_reg32( &global_regs->gnptxfsiz, 0x00100120 ); //ep0 tx fifo - dwc_write_reg32( &global_regs->dptxfsiz_dieptxf[0], 0x01000130 ); //ep1 tx fifo - dwc_write_reg32( &global_regs->dptxfsiz_dieptxf[1], 0x00800230 ); //ep3 tx fifo - dwc_write_reg32( &global_regs->dptxfsiz_dieptxf[2], 0x008002b0 ); //ep5 tx fifo - dwc_write_reg32( &global_regs->dptxfsiz_dieptxf[3], 0x00800330 ); //ep7 tx fifo - dwc_write_reg32( &global_regs->dptxfsiz_dieptxf[4], 0x001003b0 ); //ep9 tx fifo + dwc_write_reg32( &global_regs->grxfsiz, 0x00000120 ); + dwc_write_reg32( &global_regs->gnptxfsiz, 0x00100120 ); //ep0 tx fifo + dwc_write_reg32( &global_regs->dptxfsiz_dieptxf[0], 0x01000130 ); //ep1 tx fifo + dwc_write_reg32( &global_regs->dptxfsiz_dieptxf[1], 0x00800230 ); //ep3 tx fifo + dwc_write_reg32( &global_regs->dptxfsiz_dieptxf[2], 0x008002b0 ); //ep5 tx fifo + dwc_write_reg32( &global_regs->dptxfsiz_dieptxf[3], 0x00800330 ); //ep7 tx fifo + dwc_write_reg32( &global_regs->dptxfsiz_dieptxf[4], 0x001003b0 ); //ep9 tx fifo #endif if(_core_if->en_multiple_tx_fifo && _core_if->dma_enable) @@ -790,45 +791,45 @@ void dwc_otg_core_dev_init(dwc_otg_core_if_t *_core_if) depctl.d32 = 0; depctl.b.epdis = 1; depctl.b.snak = 1; - dwc_write_reg32( &dev_if->in_ep_regs[0]->diepctl, depctl.d32 ); - dwc_write_reg32( &dev_if->in_ep_regs[0]->dieptsiz, 0 ); - dwc_write_reg32( &dev_if->in_ep_regs[0]->diepdma, 0 ); - dwc_write_reg32( &dev_if->in_ep_regs[0]->diepint, 0xff ); + dwc_write_reg32( &dev_if->in_ep_regs[0]->diepctl, depctl.d32 ); + dwc_write_reg32( &dev_if->in_ep_regs[0]->dieptsiz, 0 ); + dwc_write_reg32( &dev_if->in_ep_regs[0]->diepdma, 0 ); + dwc_write_reg32( &dev_if->in_ep_regs[0]->diepint, 0xff ); - dwc_write_reg32( &dev_if->out_ep_regs[0]->doepctl, depctl.d32 ); - dwc_write_reg32( &dev_if->out_ep_regs[0]->doeptsiz, 0 ); - dwc_write_reg32( &dev_if->out_ep_regs[0]->doepdma, 0 ); - dwc_write_reg32( &dev_if->out_ep_regs[0]->doepint, 0xff ); + dwc_write_reg32( &dev_if->out_ep_regs[0]->doepctl, depctl.d32 ); + dwc_write_reg32( &dev_if->out_ep_regs[0]->doeptsiz, 0 ); + dwc_write_reg32( &dev_if->out_ep_regs[0]->doepdma, 0 ); + dwc_write_reg32( &dev_if->out_ep_regs[0]->doepint, 0xff ); depctl.d32 = 0; depctl.b.setd0pid = 1; - dwc_write_reg32( &dev_if->in_ep_regs[1]->diepctl, depctl.d32); + dwc_write_reg32( &dev_if->in_ep_regs[1]->diepctl, depctl.d32); depctl.b.snak = 1; depctl.b.txfnum = 2; depctl.b.eptype = 2; - depctl.b.usbactep = 1; - depctl.b.mps = 0x200; - dwc_write_reg32( &dev_if->out_ep_regs[2]->doepctl, depctl.d32 ); - dwc_write_reg32( &dev_if->out_ep_regs[2]->doepint, 0xff ); - - /* global register initial */ - dwc_write_reg32( &dev_if->dev_global_regs->diepmsk, 0x2f );//device IN interrutp mask - dwc_write_reg32( &dev_if->dev_global_regs->doepmsk, 0x0f );//device OUT interrutp mask - dwc_write_reg32( &dev_if->dev_global_regs->daint, 0xffffffff ); //clear all pending intrrupt - daintmsk.b.inep0 = 1; - daintmsk.b.inep1 = 1; - daintmsk.b.outep0 = 1; - daintmsk.b.outep2 = 1; - dwc_write_reg32( &dev_if->dev_global_regs->daintmsk, daintmsk.d32 ); + depctl.b.usbactep = 1; + depctl.b.mps = 0x200; + dwc_write_reg32( &dev_if->out_ep_regs[2]->doepctl, depctl.d32 ); + dwc_write_reg32( &dev_if->out_ep_regs[2]->doepint, 0xff ); + + /* global register initial */ + dwc_write_reg32( &dev_if->dev_global_regs->diepmsk, 0x2f );//device IN interrutp mask + dwc_write_reg32( &dev_if->dev_global_regs->doepmsk, 0x0f );//device OUT interrutp mask + dwc_write_reg32( &dev_if->dev_global_regs->daint, 0xffffffff ); //clear all pending intrrupt + daintmsk.b.inep0 = 1; + daintmsk.b.inep1 = 1; + daintmsk.b.outep0 = 1; + daintmsk.b.outep2 = 1; + dwc_write_reg32( &dev_if->dev_global_regs->daintmsk, daintmsk.d32 ); - dwc_write_reg32( &global_regs->gintsts, 0xffffffff ); - dwc_write_reg32( &global_regs->gotgint, 0xffffffff ); - dwc_otg_enable_device_interrupts(_core_if); - gahbcfg.d32 = 0; - gahbcfg.b.glblintrmsk = 1; - gahbcfg.b.dmaenable = 1; + dwc_write_reg32( &global_regs->gintsts, 0xffffffff ); + dwc_write_reg32( &global_regs->gotgint, 0xffffffff ); + dwc_otg_enable_device_interrupts(_core_if); + gahbcfg.d32 = 0; + gahbcfg.b.glblintrmsk = 1; + gahbcfg.b.dmaenable = 1; gahbcfg.b.hburstlen = DWC_GAHBCFG_INT_DMA_BURST_INCR16; // yk@20101221 - dwc_write_reg32( &global_regs->gahbcfg, gahbcfg.d32 ); + dwc_write_reg32( &global_regs->gahbcfg, gahbcfg.d32 ); } /** diff --git a/drivers/usb/dwc_otg/dwc_otg_driver.c b/drivers/usb/dwc_otg/dwc_otg_driver.c index ddee92afa239..49cbbb8b7170 100755 --- a/drivers/usb/dwc_otg/dwc_otg_driver.c +++ b/drivers/usb/dwc_otg/dwc_otg_driver.c @@ -62,6 +62,8 @@ #include "linux/dwc_otg_plat.h" #include +#include +#include #include "dwc_otg_attr.h" #include "dwc_otg_driver.h" #include "dwc_otg_cil.h" @@ -79,6 +81,8 @@ static const char dwc_driver_name[] = "usb20_otg"; dwc_otg_device_t* g_otgdev = NULL; +extern struct dwc_otg_platform_data usb20otg_pdata; +extern struct dwc_otg_platform_data usb20host_pdata; /*-------------------------------------------------------------------------*/ /* Encapsulate the module parameter settings */ @@ -332,11 +336,11 @@ static ssize_t dbg_level_store(struct device_driver *_drv, const char *_buf, static DRIVER_ATTR(debuglevel, S_IRUGO|S_IWUSR, dbg_level_show, dbg_level_store); #ifdef CONFIG_USB -extern struct usb_hub *g_root_hub20; +extern struct usb_hub *g_dwc_otg_root_hub20; #ifdef DWC_BOTH_HOST_SLAVE extern void hcd_start( dwc_otg_core_if_t *_core_if ); -extern void hub_disconnect_device(struct usb_hub *hub); +extern void dwc_otg_hub_disconnect_device(struct usb_hub *hub); static ssize_t force_usb_mode_show(struct device_driver *_drv, char *_buf) { @@ -388,7 +392,7 @@ void dwc_otg_force_device(dwc_otg_core_if_t *core_if) printk("dwc_otg_force_device,already in B_PERIPHERAL,everest\n"); return; } - hub_disconnect_device(g_root_hub20); + dwc_otg_hub_disconnect_device(g_dwc_otg_root_hub20); otg_dev->core_if->op_state = B_PERIPHERAL; /* Reset the Controller */ dwc_otg_core_reset( core_if ); @@ -510,7 +514,7 @@ static ssize_t force_usb_mode_store(struct device_driver *_drv, const char *_buf dwc_otg_force_device(core_if); } //if(dwc_otg_connid(core_if)) - // hub_disconnect_device(); + // dwc_otg_hub_disconnect_device(g_dwc_otg_root_hub20); //core_if->usb_mode = new_mode; // dwc_otg_force_device(core_if); } @@ -1112,6 +1116,7 @@ static irqreturn_t dwc_otg_common_irq(int _irq, void *_dev) return IRQ_RETVAL(retval); } +#ifdef CONFIG_USB20_OTG /** * This function is called when a lm_device is unregistered with the * dwc_otg_driver. This happens, for example, when the rmmod command is @@ -1198,31 +1203,41 @@ static int dwc_otg_driver_remove(struct platform_device *pdev) * * @param[in] pdev platform_device definition */ -static __devinit int dwc_otg_driver_probe(struct platform_device *pdev) +static int dwc_otg_driver_probe(struct platform_device *pdev) { - int retval = 0; - struct resource *res_base; - struct device *dev = &pdev->dev; - dwc_otg_device_t *dwc_otg_device; - int32_t snpsid; - int irq; - struct dwc_otg_platform_data *pldata = dev->platform_data; + struct device_node *node = pdev->dev.of_node; + int retval = 0; + struct resource *res_base; + struct device *dev = &pdev->dev; + dwc_otg_device_t *dwc_otg_device; + int32_t snpsid; + int irq; + struct dwc_otg_platform_data *pldata; + + dev->platform_data = &usb20otg_pdata; + pldata = dev->platform_data; + pldata->dev = dev; + + if (!node) { + dev_err(dev, "device node not found\n"); + return -EINVAL; + } - // clock and hw init - if(pldata->hw_init) - pldata->hw_init(); + // clock and hw init + if(pldata->hw_init) + pldata->hw_init(); - if(pldata->clock_init){ - pldata->clock_init(pldata); - pldata->clock_enable(pldata, 1); - } + if(pldata->clock_init){ + pldata->clock_init(pldata); + pldata->clock_enable(pldata, 1); + } - if(pldata->phy_suspend) - pldata->phy_suspend(pldata, USB_PHY_ENABLED); + if(pldata->phy_suspend) + pldata->phy_suspend(pldata, USB_PHY_ENABLED); - if(pldata->soft_reset) - pldata->soft_reset(); + if(pldata->soft_reset) + pldata->soft_reset(); dwc_otg_device = kmalloc(sizeof(dwc_otg_device_t), GFP_KERNEL); @@ -1244,7 +1259,7 @@ static __devinit int dwc_otg_driver_probe(struct platform_device *pdev) if (!res_base) goto fail; - dwc_otg_device->base = ioremap(res_base->start,res_base->end-res_base->start+1); + dwc_otg_device->base = devm_ioremap_resource(dev, res_base); if (dwc_otg_device->base == NULL) { dev_err(dev, "ioremap() failed\n"); @@ -1307,7 +1322,7 @@ static __devinit int dwc_otg_driver_probe(struct platform_device *pdev) /* * Create Device Attributes in sysfs - */ + */ dwc_otg_attr_create(dev); #ifndef CONFIG_DWC_OTG_DEVICE_ONLY retval |= device_create_file(dev, &dev_attr_enable); @@ -1492,6 +1507,11 @@ static void dwc_otg_driver_shutdown(struct platform_device *_dev ) * to this driver. The remove function is called when a device is * unregistered with the bus driver. */ +static const struct of_device_id usb20_otg_of_match[] = { + { .compatible = "rockchip,usb20_otg", }, + {}, +}; +MODULE_DEVICE_TABLE(of, usb20_otg_of_match); static struct platform_driver dwc_otg_driver = { .probe = dwc_otg_driver_probe, .remove = dwc_otg_driver_remove, @@ -1500,13 +1520,15 @@ static struct platform_driver dwc_otg_driver = { .shutdown = dwc_otg_driver_shutdown, .driver = { .name = dwc_driver_name, - .owner = THIS_MODULE}, + .owner = THIS_MODULE, + .of_match_table = of_match_ptr(usb20_otg_of_match), + }, }; - +#endif #ifdef CONFIG_USB20_HOST extern void dwc_otg_hcd_remove(struct device *dev); -extern int __devinit host20_hcd_init(struct device *_dev); +extern int host20_hcd_init(struct device *_dev); static int host20_driver_remove(struct platform_device *pdev) @@ -1573,30 +1595,40 @@ static int host20_driver_remove(struct platform_device *pdev) * * @param[in] pdev platform_device definition */ -static __devinit int host20_driver_probe(struct platform_device *pdev) +static int host20_driver_probe(struct platform_device *pdev) { - struct resource *res_base; - int retval = 0; - struct device *dev = &pdev->dev; - dwc_otg_device_t *dwc_otg_device; - int32_t snpsid; - int irq; - struct dwc_otg_platform_data *pldata = dev->platform_data; - - // clock and hw init - if(pldata->hw_init) - pldata->hw_init(); + struct device_node *node = pdev->dev.of_node; + struct resource *res_base; + int retval = 0; + struct device *dev = &pdev->dev; + dwc_otg_device_t *dwc_otg_device; + int32_t snpsid; + int irq; + struct dwc_otg_platform_data *pldata; + + dev->platform_data = &usb20host_pdata; + pldata = dev->platform_data; + pldata->dev = dev; + + if (!node) { + dev_err(dev, "device node not found\n"); + return -EINVAL; + } + + // clock and hw init + if(pldata->hw_init) + pldata->hw_init(); - if(pldata->clock_init){ - pldata->clock_init(pldata); - pldata->clock_enable(pldata, 1); - } + if(pldata->clock_init){ + pldata->clock_init(pldata); + pldata->clock_enable(pldata, 1); + } - if(pldata->phy_suspend) - pldata->phy_suspend(pldata, USB_PHY_ENABLED); + if(pldata->phy_suspend) + pldata->phy_suspend(pldata, USB_PHY_ENABLED); - if(pldata->soft_reset) - pldata->soft_reset(); + if(pldata->soft_reset) + pldata->soft_reset(); /* *Enable usb phy @@ -1622,9 +1654,8 @@ static __devinit int host20_driver_probe(struct platform_device *pdev) if (!res_base) goto fail; - dwc_otg_device->base = - ioremap(res_base->start,res_base->end-res_base->start+1); - DWC_PRINT("%s host2.0 reg addr: 0x%x remap:0x%x\n",__func__, + dwc_otg_device->base = devm_ioremap_resource(dev, res_base); + DWC_PRINT("%s host2.0 reg addr: 0x%x remap:0x%x\n",__func__, (unsigned)res_base->start, (unsigned)dwc_otg_device->base); if (dwc_otg_device->base == NULL) { @@ -1736,12 +1767,19 @@ static __devinit int host20_driver_probe(struct platform_device *pdev) return retval; } +static const struct of_device_id usb20_host_of_match[] = { + { .compatible = "rockchip,usb20_host", }, + {}, +}; +MODULE_DEVICE_TABLE(of, usb20_host_of_match); static struct platform_driver host20_driver = { .probe = host20_driver_probe, .remove = host20_driver_remove, .driver = { .name = "usb20_host", - .owner = THIS_MODULE}, + .owner = THIS_MODULE, + .of_match_table = of_match_ptr(usb20_host_of_match), + }, }; #endif @@ -1761,6 +1799,7 @@ static int __init dwc_otg_driver_init(void) /* * USB2.0 OTG controller */ +#ifdef CONFIG_USB20_OTG retval = platform_driver_register(&dwc_otg_driver); if (retval < 0) { @@ -1777,18 +1816,22 @@ static int __init dwc_otg_driver_init(void) #endif #ifdef CONFIG_RK_USB_UART -if(driver_create_file(&dwc_otg_driver.driver, &driver_attr_dwc_otg_force_uart)) - pr_warning("DWC_OTG: Failed to create driver dwc_otg_force_uart file"); -#endif + if(driver_create_file(&dwc_otg_driver.driver, &driver_attr_dwc_otg_force_uart)) + pr_warning("DWC_OTG: Failed to create driver dwc_otg_force_uart file"); +#endif + #ifndef CONFIG_DWC_OTG_HOST_ONLY if(driver_create_file(&dwc_otg_driver.driver, &driver_attr_vbus_status)) pr_warning("DWC_OTG: Failed to create driver vbus status file"); #endif + #ifdef DWC_BOTH_HOST_SLAVE if(driver_create_file(&dwc_otg_driver.driver, &driver_attr_force_usb_mode)) pr_warning("DWC_OTG: Failed to create driver force usb mode file\n"); #endif - + +#endif + /* * USB2.0 host controller */ @@ -1829,25 +1872,28 @@ static void __exit dwc_otg_driver_cleanup(void) { DWC_PRINT("dwc_otg_driver_cleanup()\n"); +#ifdef CONFIG_USB20_OTG driver_remove_file(&dwc_otg_driver.driver, &driver_attr_version); driver_remove_file(&dwc_otg_driver.driver, &driver_attr_debuglevel); #ifdef DWC_BOTH_HOST_SLAVE - driver_remove_file(&dwc_otg_driver.driver, &driver_attr_force_usb_mode); + driver_remove_file(&dwc_otg_driver.driver, &driver_attr_force_usb_mode); #endif + #ifndef CONFIG_DWC_OTG_HOST_ONLY - driver_remove_file(&dwc_otg_driver.driver, &driver_attr_dwc_otg_conn_en); + driver_remove_file(&dwc_otg_driver.driver, &driver_attr_dwc_otg_conn_en); #endif #ifdef CONFIG_RK_USB_UART - driver_remove_file(&dwc_otg_driver.driver, &driver_attr_dwc_otg_force_uart); + driver_remove_file(&dwc_otg_driver.driver, &driver_attr_dwc_otg_force_uart); #endif #ifndef CONFIG_DWC_OTG_HOST_ONLY - driver_remove_file(&dwc_otg_driver.driver, &driver_attr_vbus_status); + driver_remove_file(&dwc_otg_driver.driver, &driver_attr_vbus_status); #endif platform_driver_unregister(&dwc_otg_driver); +#endif #ifdef CONFIG_USB11_HOST platform_driver_unregister(&host11_driver); diff --git a/drivers/usb/dwc_otg/dwc_otg_hcd.c b/drivers/usb/dwc_otg/dwc_otg_hcd.c index bfaa2d02db3e..976b56726e63 100755 --- a/drivers/usb/dwc_otg/dwc_otg_hcd.c +++ b/drivers/usb/dwc_otg/dwc_otg_hcd.c @@ -73,7 +73,7 @@ static int dwc_otg_hcd_suspend(struct usb_hcd *hcd) if(!(dwc_otg_hcd->host_enabled&1)) return 0; hprt0.d32 = dwc_read_reg32(core_if->host_if->hprt0); -#ifdef CONFIG_USB_SUSPEND +#ifdef CONFIG_PM_RUNTIME if((!hprt0.b.prtena)) return 0; #endif @@ -135,7 +135,7 @@ static int dwc_otg_hcd_resume(struct usb_hcd *hcd) DWC_PRINT("%s, usb device mode\n", __func__); return 0; } -//#ifdef CONFIG_USB_SUSPEND +//#ifdef CONFIG_PM_RUNTIME if(!(dwc_otg_hcd->host_enabled&1)) return 0; //#endif @@ -158,7 +158,7 @@ static int dwc_otg_hcd_resume(struct usb_hcd *hcd) dwc_write_reg32(&core_if->core_global_regs->gintmsk, gintmsk.d32); hprt0.d32 = dwc_read_reg32(core_if->host_if->hprt0); -#ifdef CONFIG_USB_SUSPEND +#ifdef CONFIG_PM_RUNTIME if(!hprt0.b.prtena) return 0; #endif @@ -717,7 +717,7 @@ static void dwc_otg_hcd_connect_detect(unsigned long pdata) * a negative error on failure. */ extern uint32_t g_dbg_lvl; -int __devinit dwc_otg_hcd_init(struct device *dev) +int dwc_otg_hcd_init(struct device *dev) { struct usb_hcd *hcd = NULL; dwc_otg_hcd_t *dwc_otg_hcd = NULL; @@ -1044,7 +1044,7 @@ static struct tasklet_struct host20_reset_tasklet = { .data = 0, }; -int __devinit host20_hcd_init(struct device *dev) +int host20_hcd_init(struct device *dev) { struct usb_hcd *hcd = NULL; dwc_otg_hcd_t *dwc_otg_hcd = NULL; @@ -2328,7 +2328,7 @@ int dwc_otg_hcd_hub_control(struct usb_hcd *_hcd, dwc_write_reg32(core_if->host_if->hprt0, hprt0.d32); break; case USB_PORT_FEAT_SUSPEND: - #ifdef CONFIG_USB_SUSPEND + #ifdef CONFIG_PM_RUNTIME break; #endif DWC_DEBUGPL (DBG_HCD, "DWC OTG HCD HUB CONTROL - " @@ -2514,7 +2514,7 @@ int dwc_otg_hcd_hub_control(struct usb_hcd *_hcd, switch (_wValue) { case USB_PORT_FEAT_SUSPEND: - #ifdef CONFIG_USB_SUSPEND + #ifdef CONFIG_PM_RUNTIME break; #endif DWC_DEBUGPL (DBG_HCD, "DWC OTG HCD HUB CONTROL - " diff --git a/drivers/usb/dwc_otg/dwc_otg_hcd.h b/drivers/usb/dwc_otg/dwc_otg_hcd.h index cdf9a184a574..1afd8b56ec51 100755 --- a/drivers/usb/dwc_otg/dwc_otg_hcd.h +++ b/drivers/usb/dwc_otg/dwc_otg_hcd.h @@ -427,7 +427,7 @@ static inline struct usb_hcd *dwc_otg_hcd_to_hcd(dwc_otg_hcd_t *dwc_otg_hcd) /** @name HCD Create/Destroy Functions */ /** @{ */ -extern int __init dwc_otg_hcd_init(struct device *_dev); +extern int dwc_otg_hcd_init(struct device *_dev); extern void dwc_otg_hcd_remove(struct device *_dev); /** @} */ diff --git a/drivers/usb/dwc_otg/dwc_otg_hcd_queue.c b/drivers/usb/dwc_otg/dwc_otg_hcd_queue.c index a0b935762658..3a0c8957c558 100755 --- a/drivers/usb/dwc_otg/dwc_otg_hcd_queue.c +++ b/drivers/usb/dwc_otg/dwc_otg_hcd_queue.c @@ -247,7 +247,7 @@ static int periodic_channel_available(dwc_otg_hcd_t *_hcd) * non-periodic transactions. */ int status; -#if defined(CONFIG_ARCH_RK30) || defined(CONFIG_ARCH_RK3188) +#if CONFIG_ARCH_ROCKCHIP int num_channels; num_channels = _hcd->core_if->core_params->host_channels; diff --git a/drivers/usb/dwc_otg/dwc_otg_pcd.c b/drivers/usb/dwc_otg/dwc_otg_pcd.c index 50ec2d878605..de81406162b9 100755 --- a/drivers/usb/dwc_otg/dwc_otg_pcd.c +++ b/drivers/usb/dwc_otg/dwc_otg_pcd.c @@ -86,6 +86,7 @@ #include "dwc_otg_regs.h" #include "usbdev_rk.h" + /** * Static PCD pointer for use in usb_gadget_register_driver and * usb_gadget_unregister_driver. Initialized in dwc_otg_pcd_init. @@ -1058,12 +1059,43 @@ static int dwc_otg_pcd_pullup(struct usb_gadget *_gadget, int is_on) return 0; } +static int dwc_otg_gadget_start(struct usb_gadget *g, + struct usb_gadget_driver *driver) +{ + DWC_DEBUGPL(DBG_PCD, "registering gadget driver '%s'\n", driver->driver.name); + if (s_pcd == 0) + { + DWC_ERROR("ENODEV\n"); + return -ENODEV; + } + if (s_pcd->driver != 0) + { + DWC_ERROR("EBUSY (%p)\n", s_pcd->driver); + return -EBUSY; + } + /* hook up the driver */ + s_pcd->driver = driver; + s_pcd->gadget.dev.driver = &driver->driver; + + DWC_DEBUGPL(DBG_PCD, "bind to driver %s\n", driver->driver.name); + + return 0; +} + +static int dwc_otg_gadget_stop(struct usb_gadget *g, + struct usb_gadget_driver *driver) +{ + return 0; +} + static const struct usb_gadget_ops dwc_otg_pcd_ops = { .get_frame = dwc_otg_pcd_get_frame, .wakeup = dwc_otg_pcd_wakeup, .pullup = dwc_otg_pcd_pullup, // current versions must always be self-powered + .udc_start = dwc_otg_gadget_start, + .udc_stop = dwc_otg_gadget_stop, }; /** @@ -1899,7 +1931,7 @@ int dwc_otg_pcd_init(struct device *dev) static char pcd_name[] = "dwc_otg_pcd"; dwc_otg_pcd_t *pcd; dwc_otg_device_t *otg_dev = (dwc_otg_device_t *)(*((uint32_t *)dev->platform_data)); - dwc_otg_core_if_t *core_if = otg_dev->core_if; + dwc_otg_core_if_t *core_if = otg_dev->core_if; struct dwc_otg_platform_data *pldata = dev->platform_data; int retval = 0; int irq; @@ -1927,12 +1959,13 @@ int dwc_otg_pcd_init(struct device *dev) pcd->gadget.dev.init_name= "gadget"; pcd->gadget.ops = &dwc_otg_pcd_ops; - pcd->gadget.is_dualspeed = 0; +// pcd->gadget.is_dualspeed = 0; pcd->gadget.is_otg = 0; + pcd->gadget.max_speed = USB_SPEED_HIGH; pcd->driver = 0; - pcd->conn_en = 0; + pcd->conn_en = 0; /* Register the gadget device */ - retval = device_register( &pcd->gadget.dev ); + retval = usb_add_gadget_udc(dev, &pcd->gadget); if(retval != 0) { DWC_ERROR("device_register failed\n"); @@ -2072,7 +2105,7 @@ void dwc_otg_pcd_remove( struct device *dev ) * * @param _driver The driver being registered */ - +#if 0 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 37)) int usb_gadget_probe_driver(struct usb_gadget_driver *_driver, int (*bind)(struct usb_gadget *)) @@ -2135,7 +2168,6 @@ EXPORT_SYMBOL(usb_gadget_probe_driver); #else EXPORT_SYMBOL(usb_gadget_register_driver); #endif - /** * This function unregisters a gadget driver * @@ -2166,4 +2198,5 @@ int usb_gadget_unregister_driver(struct usb_gadget_driver *_driver) return 0; } EXPORT_SYMBOL(usb_gadget_unregister_driver); +#endif #endif /* DWC_HOST_ONLY */ diff --git a/drivers/usb/dwc_otg/usbdev_rk.h b/drivers/usb/dwc_otg/usbdev_rk.h index 672fdd737a09..19cd5e835022 100755 --- a/drivers/usb/dwc_otg/usbdev_rk.h +++ b/drivers/usb/dwc_otg/usbdev_rk.h @@ -1,3 +1,5 @@ +#ifndef __USBDEV_RK_H +#define __USBDEV_RK_H #define USB_PHY_ENABLED 0 #define USB_PHY_SUSPEND 1 @@ -12,6 +14,7 @@ struct dwc_otg_platform_data { void *privdata; + struct device *dev; struct clk* phyclk; struct clk* ahbclk; struct clk* busclk; @@ -36,3 +39,13 @@ struct rkehci_platform_data{ void (*soft_reset)(void); int clk_status; }; + +struct dwc_otg_control_usb { + void *grf_soc_status0; + void *grf_uoc0_base; + void *grf_uoc1_base; + struct gpio *host_gpios; + struct gpio *otg_gpios; +}; + +#endif diff --git a/drivers/usb/dwc_otg/usbdev_rk30.c b/drivers/usb/dwc_otg/usbdev_rk30.c old mode 100755 new mode 100644 index d7c21d0a7ae9..cb4da87d6d8e --- a/drivers/usb/dwc_otg/usbdev_rk30.c +++ b/drivers/usb/dwc_otg/usbdev_rk30.c @@ -1,627 +1,388 @@ -#include -#include -#include -#include -#include - -#include -#include -#include -#include - -#include "usbdev_rk.h" -#include "dwc_otg_regs.h" - -#if defined(CONFIG_ARCH_RK30) || defined(CONFIG_ARCH_RK3188) - -#define GRF_REG_BASE RK30_GRF_BASE -#define USBOTG_SIZE RK30_USBOTG20_SIZE -#if defined(CONFIG_ARCH_RK3066B) || defined(CONFIG_ARCH_RK3188) -#define USBGRF_SOC_STATUS0 (GRF_REG_BASE+0xac) -#define USBGRF_UOC0_CON0 (GRF_REG_BASE+0x10c) -#define USBGRF_UOC0_CON2 (GRF_REG_BASE+0x114) -#define USBGRF_UOC0_CON3 (GRF_REG_BASE+0x118) -#define USBGRF_UOC1_CON0 (GRF_REG_BASE+0x11C) -#define USBGRF_UOC1_CON2 (GRF_REG_BASE+0x124) -#define USBGRF_UOC1_CON3 (GRF_REG_BASE+0x128) -#define USBGRF_UOC3_CON0 (GRF_REG_BASE+0x138) - -#define USBGRF_UOC2_CON0 (GRF_REG_BASE+0x12C) -#if defined(CONFIG_SOC_RK3066B) || defined(CONFIG_SOC_RK3108) -#define RK3066B_HOST_DRV_VBUS RK30_PIN0_PD7 -#define RK3066B_OTG_DRV_VBUS RK30_PIN0_PD6 -#elif defined(CONFIG_SOC_RK3168) || defined(CONFIG_SOC_RK3188) || defined(CONFIG_SOC_RK3168M) || defined(CONFIG_SOC_RK3188M) -#define RK3066B_HOST_DRV_VBUS RK30_PIN0_PC0 -#define RK3066B_OTG_DRV_VBUS RK30_PIN3_PD5 -#elif defined(CONFIG_SOC_RK3028) -#define RK3066B_HOST_DRV_VBUS RK30_PIN1_PA4 -#define RK3066B_OTG_DRV_VBUS RK30_PIN3_PD7 -#endif - -#else -#define USBGRF_SOC_STATUS0 (GRF_REG_BASE+0x15c) -#define USBGRF_UOC0_CON2 (GRF_REG_BASE+0x184) -#define USBGRF_UOC1_CON2 (GRF_REG_BASE+0x190) -#endif - -int dwc_otg_check_dpdm(void) -{ - static uint8_t * reg_base = 0; - volatile unsigned int * otg_dctl; - volatile unsigned int * otg_gotgctl; - volatile unsigned int * otg_hprt0; - int bus_status = 0; - unsigned int * otg_phy_con1 = (unsigned int*)(USBGRF_UOC0_CON2); - - // softreset & clockgate - *(unsigned int*)(RK30_CRU_BASE+0x120) = ((7<<5)<<16)|(7<<5); // otg0 phy clkgate - udelay(3); - *(unsigned int*)(RK30_CRU_BASE+0x120) = ((7<<5)<<16)|(0<<5); // otg0 phy clkgate - dsb(); - *(unsigned int*)(RK30_CRU_BASE+0xd4) = ((1<<5)<<16); // otg0 phy clkgate - *(unsigned int*)(RK30_CRU_BASE+0xe4) = ((1<<13)<<16); // otg0 hclk clkgate - *(unsigned int*)(RK30_CRU_BASE+0xe0) = ((3<<5)<<16); // hclk usb clkgate - - // exit phy suspend - *otg_phy_con1 = ((0x01<<2)<<16); // exit suspend. - - // soft connect - if(reg_base == 0){ - reg_base = ioremap(RK30_USBOTG20_PHYS,USBOTG_SIZE); - if(!reg_base){ - bus_status = -1; - goto out; - } - } - mdelay(105); - printk("regbase %p 0x%x, otg_phy_con%p, 0x%x\n", - reg_base, *(reg_base), otg_phy_con1, *otg_phy_con1); - otg_dctl = (unsigned int * )(reg_base+0x804); - otg_gotgctl = (unsigned int * )(reg_base); - otg_hprt0 = (unsigned int * )(reg_base + DWC_OTG_HOST_PORT_REGS_OFFSET); - if(*otg_gotgctl &(1<<19)){ - bus_status = 1; - *otg_dctl &= ~2; - mdelay(50); // delay about 10ms - // check dp,dm - if((*otg_hprt0 & 0xc00)==0xc00) - bus_status = 2; - } -out: - return bus_status; -} - -EXPORT_SYMBOL(dwc_otg_check_dpdm); - -#ifdef CONFIG_USB20_OTG -/*DWC_OTG*/ -static struct resource usb20_otg_resource[] = { - { - .start = IRQ_USB_OTG, - .end = IRQ_USB_OTG, - .flags = IORESOURCE_IRQ, - }, - { - .start = RK30_USBOTG20_PHYS, - .end = RK30_USBOTG20_PHYS + RK30_USBOTG20_SIZE - 1, - .flags = IORESOURCE_MEM, - }, - -}; - -void usb20otg_hw_init(void) -{ -#ifndef CONFIG_USB20_HOST - // close USB 2.0 HOST phy and clock -#if defined(CONFIG_ARCH_RK3066B) || defined(CONFIG_ARCH_RK3188) - unsigned int * otg_phy_con1 = (unsigned int*)(USBGRF_UOC1_CON2); - unsigned int * otg_phy_con2 = (unsigned int*)(USBGRF_UOC1_CON3); - *otg_phy_con1 = (0x01<<2)|((0x01<<2)<<16); //enable soft control - *otg_phy_con2 = 0x2A|(0x3F<<16); // enter suspend -#else - unsigned int * otg_phy_con1 = (unsigned int*)(USBGRF_UOC1_CON2); - *otg_phy_con1 = 0x554|(0xfff<<16); // enter suspend. -#endif -#endif - // usb phy config init -#ifdef CONFIG_ARCH_RK3188 - //usb phy enter usb mode - unsigned int * otg_phy_con3 = (unsigned int*)(USBGRF_UOC0_CON0); - *otg_phy_con3 = (0x0300 << 16); - //Disconnect Threshold Adjustment - *otg_phy_con3 = (0x07<<1)|((0x07<<1)<<16); -#endif - // other haredware init -#if defined(CONFIG_ARCH_RK3066B) || defined(CONFIG_ARCH_RK3188) - //GPIO init - gpio_request(RK3066B_OTG_DRV_VBUS, NULL); - gpio_direction_output(RK3066B_OTG_DRV_VBUS, GPIO_LOW); -#else - rk30_mux_api_set(GPIO0A5_OTGDRVVBUS_NAME, GPIO0A_OTG_DRV_VBUS); -#endif -} - -void usb20otg_phy_suspend(void* pdata, int suspend) -{ -#if defined(CONFIG_ARCH_RK3066B) || defined(CONFIG_ARCH_RK3188) - struct dwc_otg_platform_data *usbpdata=pdata; - unsigned int * otg_phy_con1 = (unsigned int*)(USBGRF_UOC0_CON2); - unsigned int * otg_phy_con2 = (unsigned int*)(USBGRF_UOC0_CON3); - if(suspend){ - *otg_phy_con1 = (0x01<<2)|((0x01<<2)<<16); ; //enable soft control - *otg_phy_con2 = 0x2A|(0x3F<<16);; // enter suspend - usbpdata->phy_status = 1; - } - else{ - *otg_phy_con1 = ((0x01<<2)<<16); // exit suspend. - usbpdata->phy_status = 0; - } -#else - struct dwc_otg_platform_data *usbpdata=pdata; - unsigned int * otg_phy_con1 = (unsigned int*)(USBGRF_UOC0_CON2); - if(suspend){ - *otg_phy_con1 = 0x554|(0xfff<<16); // enter suspend. - usbpdata->phy_status = 1; - } - else{ - *otg_phy_con1 = ((0x01<<2)<<16); // exit suspend. - usbpdata->phy_status = 0; - } -#endif -} -void usb20otg_soft_reset(void) -{ - cru_set_soft_reset(SOFT_RST_USBOTG0, true); - cru_set_soft_reset(SOFT_RST_USBPHY0, true); - cru_set_soft_reset(SOFT_RST_OTGC0, true); - udelay(1); - - cru_set_soft_reset(SOFT_RST_USBOTG0, false); - cru_set_soft_reset(SOFT_RST_USBPHY0, false); - cru_set_soft_reset(SOFT_RST_OTGC0, false); - mdelay(1); -} -void usb20otg_clock_init(void* pdata) -{ - struct dwc_otg_platform_data *usbpdata=pdata; - struct clk* ahbclk,*phyclk; - ahbclk = clk_get(NULL, "hclk_otg0"); - phyclk = clk_get(NULL, "otgphy0"); - usbpdata->phyclk = phyclk; - usbpdata->ahbclk = ahbclk; -} -void usb20otg_clock_enable(void* pdata, int enable) -{ - struct dwc_otg_platform_data *usbpdata=pdata; - - if(enable){ - clk_enable(usbpdata->ahbclk); - clk_enable(usbpdata->phyclk); - } - else{ - clk_disable(usbpdata->phyclk); - clk_disable(usbpdata->ahbclk); - } -} -int usb20otg_get_status(int id) -{ - int ret = -1; - unsigned int usbgrf_status = *(unsigned int*)(USBGRF_SOC_STATUS0); - switch(id) - { -#if defined(CONFIG_ARCH_RK3066B) || defined(CONFIG_ARCH_RK3188) - case USB_STATUS_BVABLID: - // bvalid in grf - ret = (usbgrf_status &(1<<10)); - break; - case USB_STATUS_DPDM: - // dpdm in grf - ret = (usbgrf_status &(3<<11)); - break; - case USB_STATUS_ID: - // id in grf - ret = (usbgrf_status &(1<<13)); - break; -#else - case USB_STATUS_BVABLID: - // bvalid in grf - ret = (usbgrf_status &0x20000); - break; - case USB_STATUS_DPDM: - // dpdm in grf - ret = (usbgrf_status &(3<<18)); - break; - case USB_STATUS_ID: - // id in grf - ret = (usbgrf_status &(1<<20)); - break; -#endif - default: - break; - } - return ret; -} - -#ifdef CONFIG_RK_USB_UART -void dwc_otg_uart_mode(void* pdata, int enter_usb_uart_mode) -{ - unsigned int * otg_phy_con1 = (unsigned int*)(USBGRF_UOC0_CON0); - - if(1 == enter_usb_uart_mode){ //enter uart mode - /*note: can't disable otg here! If otg disable, the ID change - *interrupt can't be triggered when otg cable connect without - *device.At the same time, uart can't be used normally - */ - //*otg_phy_con1 = (0x10 | (0x10 << 16));//otg disable - *otg_phy_con1 = (0x0300 | (0x0300 << 16));//bypass dm - } - if(0 == enter_usb_uart_mode){ //enter usb mode - *otg_phy_con1 = (0x0300 << 16); //bypass dm disable - //*otg_phy_con1 = (0x10 << 16);//otg enable - } -} -#endif - -#if defined(CONFIG_ARCH_RK3066B) || defined(CONFIG_ARCH_RK3188) -void usb20otg_power_enable(int enable) -{ - unsigned int usbgrf_status = *(unsigned int*)(USBGRF_SOC_STATUS0); - if(0 == enable)//disable - { - gpio_set_value(RK3066B_OTG_DRV_VBUS, GPIO_LOW); - - } - if(1 == enable)//enable - { - gpio_set_value(RK3066B_OTG_DRV_VBUS, GPIO_HIGH); - } -} -#endif -struct dwc_otg_platform_data usb20otg_pdata = { - .phyclk = NULL, - .ahbclk = NULL, - .busclk = NULL, - .phy_status = 0, - .hw_init=usb20otg_hw_init, - .phy_suspend=usb20otg_phy_suspend, - .soft_reset=usb20otg_soft_reset, - .clock_init=usb20otg_clock_init, - .clock_enable=usb20otg_clock_enable, - .get_status=usb20otg_get_status, -#if defined(CONFIG_ARCH_RK3066B) || defined(CONFIG_ARCH_RK3188) - .power_enable=usb20otg_power_enable, -#endif -#ifdef CONFIG_RK_USB_UART - .dwc_otg_uart_mode=dwc_otg_uart_mode, -#endif -}; - -struct platform_device device_usb20_otg = { - .name = "usb20_otg", - .id = -1, - .num_resources = ARRAY_SIZE(usb20_otg_resource), - .resource = usb20_otg_resource, - .dev = { - .platform_data = &usb20otg_pdata, - }, -}; -#endif -#ifdef CONFIG_USB20_HOST -static struct resource usb20_host_resource[] = { - { - .start = IRQ_USB_HOST, - .end = IRQ_USB_HOST, - .flags = IORESOURCE_IRQ, - }, - { - .start = RK30_USBHOST20_PHYS, - .end = RK30_USBHOST20_PHYS + RK30_USBHOST20_SIZE - 1, - .flags = IORESOURCE_MEM, - }, - -}; -void usb20host_hw_init(void) -{ - // usb phy config init -#ifdef CONFIG_ARCH_RK3188 - //Disconnect Threshold Adjustment - unsigned int * otg_phy_con1 = (unsigned int*)(USBGRF_UOC1_CON0); - *otg_phy_con1 = (0x07<<1)|((0x07<<1)<<16); -#endif - - // other haredware init -#if defined(CONFIG_ARCH_RK3066B) || defined(CONFIG_ARCH_RK3188) - gpio_request(RK3066B_HOST_DRV_VBUS, NULL); - gpio_direction_output(RK3066B_HOST_DRV_VBUS, GPIO_HIGH); -#else - rk30_mux_api_set(GPIO0A6_HOSTDRVVBUS_NAME, GPIO0A_HOST_DRV_VBUS); -#endif -} -void usb20host_phy_suspend(void* pdata, int suspend) -{ -#if defined(CONFIG_ARCH_RK3066B) || defined(CONFIG_ARCH_RK3188) - struct dwc_otg_platform_data *usbpdata=pdata; - unsigned int * otg_phy_con1 = (unsigned int*)(USBGRF_UOC1_CON2); - unsigned int * otg_phy_con2 = (unsigned int*)(USBGRF_UOC1_CON3); - if(suspend) - { - *otg_phy_con1 = (0x01<<2)|((0x01<<2)<<16); ; //enable soft control - *otg_phy_con2 = 0x2A|(0x3F<<16);; // enter suspend - usbpdata->phy_status = 1; - } - else - { - *otg_phy_con1 = ((0x01<<2)<<16); // exit suspend. - usbpdata->phy_status = 0; - } -#else - struct dwc_otg_platform_data *usbpdata=pdata; - unsigned int * otg_phy_con1 = (unsigned int*)(USBGRF_UOC1_CON2); - if(suspend) - { - *otg_phy_con1 = 0x554|(0xfff<<16); // enter suspend. - usbpdata->phy_status = 1; - } - else - { - *otg_phy_con1 = ((0x01<<2)<<16); // exit suspend. - usbpdata->phy_status = 0; - } -#endif -} -void usb20host_soft_reset(void) -{ - cru_set_soft_reset(SOFT_RST_USBOTG1, true); - cru_set_soft_reset(SOFT_RST_USBPHY1, true); - cru_set_soft_reset(SOFT_RST_OTGC1, true); - udelay(5); - - cru_set_soft_reset(SOFT_RST_USBOTG1, false); - cru_set_soft_reset(SOFT_RST_USBPHY1, false); - cru_set_soft_reset(SOFT_RST_OTGC1, false); - mdelay(2); -} -void usb20host_clock_init(void* pdata) -{ - struct dwc_otg_platform_data *usbpdata=pdata; - struct clk* ahbclk,*phyclk; - ahbclk = clk_get(NULL, "hclk_otg1"); - phyclk = clk_get(NULL, "otgphy1"); - usbpdata->phyclk = phyclk; - usbpdata->ahbclk = ahbclk; -} -void usb20host_clock_enable(void* pdata, int enable) -{ - struct dwc_otg_platform_data *usbpdata=pdata; - - if(enable){ - clk_enable(usbpdata->ahbclk); - clk_enable(usbpdata->phyclk); - } - else{ - clk_disable(usbpdata->phyclk); - clk_disable(usbpdata->ahbclk); - } -} -int usb20host_get_status(int id) -{ - int ret = -1; - unsigned int usbgrf_status = *(unsigned int*)(USBGRF_SOC_STATUS0); - switch(id) - { -#if defined(CONFIG_ARCH_RK3066B) || defined(CONFIG_ARCH_RK3188) - case USB_STATUS_BVABLID: - // bvalid in grf - ret = (usbgrf_status &(1<<17)); - break; - case USB_STATUS_DPDM: - // dpdm in grf - ret = (usbgrf_status &(3<<18)); - break; - case USB_STATUS_ID: - // id in grf - ret = (usbgrf_status &(1<<20)); - break; -#else - case USB_STATUS_BVABLID: - // bvalid in grf - ret = (usbgrf_status &(1<<22)); - break; - case USB_STATUS_DPDM: - // dpdm in grf - ret = (usbgrf_status &(3<<23)); - break; - case USB_STATUS_ID: - // id in grf - ret = 0; - break; -#endif - default: - break; - } - return ret; -} - -#if defined(CONFIG_ARCH_RK3066B) || defined(CONFIG_ARCH_RK3188) -void usb20host_power_enable(int enable) -{ - - if(0 == enable)//disable - { - //ret = gpio_request(RK3066B_HOST_DRV_VBUS, NULL); - //if (ret != 0) { - // gpio_free(RK3066B_HOST_DRV_VBUS); - //} - //gpio_direction_output(RK3066B_HOST_DRV_VBUS, 1); - //gpio_set_value(RK3066B_HOST_DRV_VBUS, 0); - //printk("!!!!!!!!!!!!!!!!!!!disable host power!!!!!!!!!!!!!!!!!!\n"); - } - - if(1 == enable)//enable - { - gpio_set_value(RK3066B_HOST_DRV_VBUS, GPIO_HIGH); - //printk("!!!!!!!!!!!!!!!!!!!!!enable host power!!!!!!!!!!!!!!!!!!\n"); - } -} -#endif -struct dwc_otg_platform_data usb20host_pdata = { - .phyclk = NULL, - .ahbclk = NULL, - .busclk = NULL, - .phy_status = 0, - .hw_init=usb20host_hw_init, - .phy_suspend=usb20host_phy_suspend, - .soft_reset=usb20host_soft_reset, - .clock_init=usb20host_clock_init, - .clock_enable=usb20host_clock_enable, - .get_status=usb20host_get_status, -#if defined(CONFIG_ARCH_RK3066B) || defined(CONFIG_ARCH_RK3188) - .power_enable=usb20host_power_enable, -#endif -}; - -struct platform_device device_usb20_host = { - .name = "usb20_host", - .id = -1, - .num_resources = ARRAY_SIZE(usb20_host_resource), - .resource = usb20_host_resource, - .dev = { - .platform_data = &usb20host_pdata, - }, -}; -#endif -#ifdef CONFIG_USB_EHCI_RK -void rkehci_hw_init(void) -{ - unsigned int * phy_con0 = (unsigned int*)(USBGRF_UOC2_CON0); - unsigned int * phy_con1 = (unsigned int*)(USBGRF_UOC1_CON0); - unsigned int * phy_con2 = (unsigned int*)(USBGRF_UOC0_CON0); - unsigned int * phy_con3 = (unsigned int*)(USBGRF_UOC3_CON0); - // usb phy config init - // hsic phy config init, set hsicphy_txsrtune - *phy_con0 = ((0xf<<6)<<16)|(0xf<<6); - - // other haredware init - // set common_on, in suspend mode, otg/host PLL blocks remain powered -#ifdef CONFIG_ARCH_RK3188 - *phy_con1 = (1<<16)|0; -#else - *phy_con2 = (1<<16)|0; -#endif - /* change INCR to INCR16 or INCR8(beats less than 16) - * or INCR4(beats less than 8) or SINGLE(beats less than 4) - */ - *phy_con3 = 0x00ff00bc; -} - -void rkehci_clock_init(void* pdata) -{ - struct rkehci_platform_data *usbpdata=pdata; - -#ifdef CONFIG_ARCH_RK3188 - struct clk *clk_otg, *clk_hs; - - /* By default, hsicphy_480m's parent is otg phy 480MHz clk - * rk3188 must use host phy 480MHz clk - */ - clk_hs = clk_get(NULL, "hsicphy_480m"); - clk_otg = clk_get(NULL, "otgphy1_480m"); - clk_set_parent(clk_hs, clk_otg); -#endif - - usbpdata->hclk_hsic = clk_get(NULL, "hclk_hsic"); - usbpdata->hsic_phy_480m = clk_get(NULL, "hsicphy_480m"); - usbpdata->hsic_phy_12m = clk_get(NULL, "hsicphy_12m"); -} - -void rkehci_clock_enable(void* pdata, int enable) -{ - struct rkehci_platform_data *usbpdata=pdata; - - if(enable == usbpdata->clk_status) - return; - - if(enable){ - clk_enable(usbpdata->hclk_hsic); - clk_enable(usbpdata->hsic_phy_480m); - clk_enable(usbpdata->hsic_phy_12m); - usbpdata->clk_status = 1; - }else{ - clk_disable(usbpdata->hsic_phy_12m); - clk_disable(usbpdata->hsic_phy_480m); - clk_disable(usbpdata->hclk_hsic); - usbpdata->clk_status = 0; - } -} - -void rkehci_soft_reset(void) -{ - unsigned int * phy_con0 = (unsigned int*)(USBGRF_UOC2_CON0); - - cru_set_soft_reset(SOFT_RST_HSICPHY, true); - udelay(12); - cru_set_soft_reset(SOFT_RST_HSICPHY, false); - mdelay(2); - - *phy_con0 = ((1<<10)<<16)|(1<<10); - udelay(2); - *phy_con0 = ((1<<10)<<16)|(0<<10); - udelay(2); - - cru_set_soft_reset(SOFT_RST_HSIC_AHB, true); - udelay(2); - cru_set_soft_reset(SOFT_RST_HSIC_AHB, false); - udelay(2); -} - -struct rkehci_platform_data rkehci_pdata = { - .hclk_hsic = NULL, - .hsic_phy_12m = NULL, - .hsic_phy_480m = NULL, - .clk_status = -1, - .hw_init = rkehci_hw_init, - .clock_init = rkehci_clock_init, - .clock_enable = rkehci_clock_enable, - .soft_reset = rkehci_soft_reset, -}; - -static struct resource resources_hsusb_host[] = { - { - .start = IRQ_HSIC, - .end = IRQ_HSIC, - .flags = IORESOURCE_IRQ, - }, - { - .start = RK30_HSIC_PHYS, - .end = RK30_HSIC_PHYS + RK30_HSIC_SIZE - 1, - .flags = IORESOURCE_MEM, - }, -}; - -struct platform_device device_hsusb_host = { - .name = "rk_hsusb_host", - .id = -1, - .num_resources = ARRAY_SIZE(resources_hsusb_host), - .resource = resources_hsusb_host, - .dev = { - .coherent_dma_mask = 0xffffffff, - .platform_data = &rkehci_pdata, - }, -}; -#endif - -static int __init usbdev_init_devices(void) -{ -#ifdef CONFIG_USB_EHCI_RK - platform_device_register(&device_hsusb_host); -#endif -#ifdef CONFIG_USB20_OTG - platform_device_register(&device_usb20_otg); -#endif -#ifdef CONFIG_USB20_HOST - platform_device_register(&device_usb20_host); -#endif - return 0; -} -arch_initcall(usbdev_init_devices); -#endif +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "usbdev_rk.h" +#include "dwc_otg_regs.h" + +static struct dwc_otg_control_usb *control_usb; + +int dwc_otg_check_dpdm(void) +{ + int bus_status = 0; + return bus_status; +} + +EXPORT_SYMBOL(dwc_otg_check_dpdm); + +#ifdef CONFIG_USB20_OTG + +void usb20otg_hw_init(void) +{ +#ifndef CONFIG_USB20_HOST + unsigned int * otg_phy_con1 = (control_usb->grf_uoc1_base + 0x8); + unsigned int * otg_phy_con2 = (control_usb->grf_uoc1_base + 0xc); + *otg_phy_con1 = (0x01<<2)|((0x01<<2)<<16); //enable soft control + *otg_phy_con2 = 0x2A|(0x3F<<16); // enter suspend +#endif + /* usb phy config init + * usb phy enter usb mode */ + unsigned int * otg_phy_con3 = (control_usb->grf_uoc0_base); + *otg_phy_con3 = (0x0300 << 16); + + /* other haredware init,include: + * DRV_VBUS GPIO init */ + gpio_direction_output(control_usb->otg_gpios->gpio, 0); +} + +void usb20otg_phy_suspend(void* pdata, int suspend) +{ + struct dwc_otg_platform_data *usbpdata=pdata; + unsigned int * otg_phy_con1 = (control_usb->grf_uoc0_base + 0x8); + unsigned int * otg_phy_con2 = (control_usb->grf_uoc0_base + 0xc); + + if(suspend){ + *otg_phy_con1 = (0x01<<2)|((0x01<<2)<<16); //enable soft control + *otg_phy_con2 = 0x2A|(0x3F<<16); // enter suspend + usbpdata->phy_status = 1; + }else{ + *otg_phy_con1 = ((0x01<<2)<<16); // exit suspend. + usbpdata->phy_status = 0; + } +} + +void usb20otg_soft_reset(void) +{ +} + +void usb20otg_clock_init(void* pdata) +{ + /* + struct dwc_otg_platform_data *usbpdata=pdata; + struct clk* ahbclk,*phyclk; + + ahbclk = devm_clk_get(usbpdata->dev, "hclk_otg0"); + if (IS_ERR(ahbclk)) { + dev_err(usbpdata->dev, "Failed to get hclk_otg0\n"); + return; + } + + phyclk = devm_clk_get(usbpdata->dev, "otgphy0"); + if (IS_ERR(phyclk)) { + dev_err(usbpdata->dev, "Failed to get otgphy0\n"); + return; + } + + usbpdata->phyclk = phyclk; + usbpdata->ahbclk = ahbclk;*/ +} + +void usb20otg_clock_enable(void* pdata, int enable) +{ + /* + struct dwc_otg_platform_data *usbpdata=pdata; + + if(enable){ + clk_prepare_enable(usbpdata->ahbclk); + clk_prepare_enable(usbpdata->phyclk); + }else{ + clk_disable_unprepare(usbpdata->ahbclk); + clk_disable_unprepare(usbpdata->phyclk); + } + */ +} + +int usb20otg_get_status(int id) +{ + int ret = -1; + unsigned int usbgrf_status = *(unsigned int*)(control_usb->grf_soc_status0); + + switch(id){ + case USB_STATUS_BVABLID: + // bvalid in grf + ret = (usbgrf_status &(1<<10)); + break; + case USB_STATUS_DPDM: + // dpdm in grf + ret = (usbgrf_status &(3<<11)); + break; + case USB_STATUS_ID: + // id in grf + ret = (usbgrf_status &(1<<13)); + break; + default: + break; + } + + return ret; +} + +#ifdef CONFIG_RK_USB_UART +void dwc_otg_uart_mode(void* pdata, int enter_usb_uart_mode) +{ + unsigned int * otg_phy_con1 = (unsigned int*)(control_usb->grf_uoc0_base); + + if(1 == enter_usb_uart_mode){ + /* enter uart mode + * note: can't disable otg here! If otg disable, the ID change + * interrupt can't be triggered when otg cable connect without + * device.At the same time, uart can't be used normally + */ + *otg_phy_con1 = (0x0300 | (0x0300 << 16)); //bypass dm + }else if(0 == enter_usb_uart_mode){ + /* enter usb mode */ + *otg_phy_con1 = (0x0300 << 16); //bypass dm disable + } +} +#endif + +void usb20otg_power_enable(int enable) +{ + if(0 == enable){//disable otg_drv power + gpio_set_value(control_usb->otg_gpios->gpio, 0); + }else if(1 == enable){//enable otg_drv power + gpio_set_value(control_usb->otg_gpios->gpio, 1); + } +} + +struct dwc_otg_platform_data usb20otg_pdata = { + .phyclk = NULL, + .ahbclk = NULL, + .busclk = NULL, + .phy_status = 0, + .hw_init=usb20otg_hw_init, + .phy_suspend=usb20otg_phy_suspend, + .soft_reset=usb20otg_soft_reset, + .clock_init=usb20otg_clock_init, + .clock_enable=usb20otg_clock_enable, + .get_status=usb20otg_get_status, + .power_enable=usb20otg_power_enable, +#ifdef CONFIG_RK_USB_UART + .dwc_otg_uart_mode=dwc_otg_uart_mode, +#endif +}; + +#endif + +#ifdef CONFIG_USB20_HOST +void usb20host_hw_init(void) +{ + /* usb phy config init */ + + /* other haredware init,include: + * DRV_VBUS GPIO init */ + gpio_direction_output(control_usb->host_gpios->gpio, 1); + +} + +void usb20host_phy_suspend(void* pdata, int suspend) +{ + struct dwc_otg_platform_data *usbpdata=pdata; + unsigned int * otg_phy_con1 = (unsigned int*)(control_usb->grf_uoc1_base + 0x8); + unsigned int * otg_phy_con2 = (unsigned int*)(control_usb->grf_uoc1_base + 0xc); + + if(suspend){ + *otg_phy_con1 = (0x01<<2)|((0x01<<2)<<16); // enable soft control + *otg_phy_con2 = 0x2A|(0x3F<<16); // enter suspend + usbpdata->phy_status = 1; + }else{ + *otg_phy_con1 = ((0x01<<2)<<16); // exit suspend. + usbpdata->phy_status = 0; + } +} + +void usb20host_soft_reset(void) +{ +} + +void usb20host_clock_init(void* pdata) +{ + /* + struct dwc_otg_platform_data *usbpdata=pdata; + struct clk* ahbclk,*phyclk; + + ahbclk = devm_clk_get(usbpdata->dev, "hclk_otg1"); + if (IS_ERR(ahbclk)) { + dev_err(usbpdata->dev, "Failed to get hclk_otg1\n"); + return; + } + + phyclk = devm_clk_get(usbpdata->dev, "otgphy1"); + if (IS_ERR(phyclk)) { + dev_err(usbpdata->dev, "Failed to get otgphy1\n"); + return; + } + + usbpdata->phyclk = phyclk; + usbpdata->ahbclk = ahbclk;*/ +} + +void usb20host_clock_enable(void* pdata, int enable) +{ + /* + struct dwc_otg_platform_data *usbpdata=pdata; + + if(enable){ + clk_prepare_enable(usbpdata->ahbclk); + clk_prepare_enable(usbpdata->phyclk); + }else{ + clk_disable_unprepare(usbpdata->ahbclk); + clk_disable_unprepare(usbpdata->phyclk); + }*/ +} + +int usb20host_get_status(int id) +{ + int ret = -1; + unsigned int usbgrf_status = *(unsigned int*)(control_usb->grf_soc_status0); + + switch(id){ + case USB_STATUS_BVABLID: + // bvalid in grf + ret = (usbgrf_status &(1<<17)); + break; + case USB_STATUS_DPDM: + // dpdm in grf + ret = (usbgrf_status &(3<<18)); + break; + case USB_STATUS_ID: + // id in grf + ret = (usbgrf_status &(1<<20)); + break; + default: + break; + } + + return ret; +} + +void usb20host_power_enable(int enable) +{ + if(0 == enable){//disable host_drv power + //do not disable power in default + }else if(1 == enable){//enable host_drv power + gpio_set_value(control_usb->host_gpios->gpio, 1); + } +} + +struct dwc_otg_platform_data usb20host_pdata = { + .phyclk = NULL, + .ahbclk = NULL, + .busclk = NULL, + .phy_status = 0, + .hw_init=usb20host_hw_init, + .phy_suspend=usb20host_phy_suspend, + .soft_reset=usb20host_soft_reset, + .clock_init=usb20host_clock_init, + .clock_enable=usb20host_clock_enable, + .get_status=usb20host_get_status, + .power_enable=usb20host_power_enable, +}; +#endif + +static int dwc_otg_control_usb_probe(struct platform_device *pdev) +{ + struct resource *res; + int gpio, err; + struct device_node *np = pdev->dev.of_node; + + control_usb = devm_kzalloc(&pdev->dev, sizeof(*control_usb),GFP_KERNEL); + if (!control_usb) { + dev_err(&pdev->dev, "unable to alloc memory for control usb\n"); + return -ENOMEM; + } + + res = platform_get_resource_byname(pdev, IORESOURCE_MEM, + "GRF_SOC_STATUS0"); + control_usb->grf_soc_status0 = devm_ioremap_resource(&pdev->dev, res); + if (IS_ERR(control_usb->grf_soc_status0)) + return PTR_ERR(control_usb->grf_soc_status0); + + res = platform_get_resource_byname(pdev, IORESOURCE_MEM, + "GRF_UOC0_BASE"); + control_usb->grf_uoc0_base = devm_ioremap_resource(&pdev->dev, res); + if (IS_ERR(control_usb->grf_uoc0_base)) + return PTR_ERR(control_usb->grf_uoc0_base); + + res = platform_get_resource_byname(pdev, IORESOURCE_MEM, + "GRF_UOC1_BASE"); + control_usb->grf_uoc1_base = devm_ioremap_resource(&pdev->dev, res); + if (IS_ERR(control_usb->grf_uoc1_base)) + return PTR_ERR(control_usb->grf_uoc1_base); + + control_usb->host_gpios = devm_kzalloc(&pdev->dev, sizeof(struct gpio), GFP_KERNEL); + + gpio = of_get_named_gpio(np, "gpios", 0); + if(!gpio_is_valid(gpio)){ + dev_err(&pdev->dev, "invalid host gpio%d\n", gpio); + return -EINVAL; + } + control_usb->host_gpios->gpio = gpio; + err = devm_gpio_request(&pdev->dev, gpio, "host_drv_gpio"); + if (err) { + dev_err(&pdev->dev, + "failed to request GPIO%d for host_drv\n", + gpio); + return err; + } + + control_usb->otg_gpios = devm_kzalloc(&pdev->dev, sizeof(struct gpio), GFP_KERNEL); + + gpio = of_get_named_gpio(np, "gpios", 1); + if(!gpio_is_valid(gpio)){ + dev_err(&pdev->dev, "invalid otg gpio%d\n", gpio); + return -EINVAL; + } + control_usb->otg_gpios->gpio = gpio; + err = devm_gpio_request(&pdev->dev, gpio, "otg_drv_gpio"); + if (err) { + dev_err(&pdev->dev, + "failed to request GPIO%d for otg_drv\n", + gpio); + return err; + } + + return 0; +} + +#ifdef CONFIG_OF +static const struct of_device_id dwc_otg_control_usb_id_table[] = { + { .compatible = "rockchip,dwc-control-usb" }, + {} +}; +MODULE_DEVICE_TABLE(of, dwc_otg_control_usb_id_table); +#endif + +static struct platform_driver dwc_otg_control_usb_driver = { + .probe = dwc_otg_control_usb_probe, + .driver = { + .name = "dwc-control-usb", + .owner = THIS_MODULE, + .of_match_table = of_match_ptr(dwc_otg_control_usb_id_table), + }, +}; + +static int __init dwc_otg_control_usb_init(void) +{ + return platform_driver_register(&dwc_otg_control_usb_driver); +} +subsys_initcall(dwc_otg_control_usb_init); + +static void __exit dwc_otg_control_usb_exit(void) +{ + platform_driver_unregister(&dwc_otg_control_usb_driver); +} + +module_exit(dwc_otg_control_usb_exit); +MODULE_ALIAS("platform: dwc_control_usb"); +MODULE_AUTHOR("RockChip Inc."); +MODULE_DESCRIPTION("RockChip Control Module USB Driver"); +MODULE_LICENSE("GPL v2"); diff --git a/drivers/usb/gadget/android.c b/drivers/usb/gadget/android.c index 04cbeb134814..6de842d6af97 100644 --- a/drivers/usb/gadget/android.c +++ b/drivers/usb/gadget/android.c @@ -48,8 +48,8 @@ MODULE_VERSION("1.0"); static const char longname[] = "Gadget Android"; /* Default vendor and product IDs, overridden by userspace */ -#define VENDOR_ID 0x18D1 -#define PRODUCT_ID 0x0001 +#define VENDOR_ID 0x2207 +#define PRODUCT_ID 0x2910 struct android_usb_function { char *name; diff --git a/drivers/usb/gadget/composite.c b/drivers/usb/gadget/composite.c index 2dd57853de67..b331472cd307 100644 --- a/drivers/usb/gadget/composite.c +++ b/drivers/usb/gadget/composite.c @@ -636,6 +636,9 @@ static int set_config(struct usb_composite_dev *cdev, cdev->config = c; + /* reset delay status to zero every time usb reconnect */ + cdev->delayed_status = 0; + /* Initialize all interfaces by setting them to altsetting zero. */ for (tmp = 0; tmp < MAX_CONFIG_INTERFACES; tmp++) { struct usb_function *f = c->interface[tmp]; @@ -1839,6 +1842,8 @@ void usb_composite_setup_continue(struct usb_composite_dev *cdev) req->status = 0; composite_setup_complete(cdev->gadget->ep0, req); } + }else{ + WARN(cdev, "%s: Unexpected delayed status 0x%x\n", __func__, cdev->delayed_status); } spin_unlock_irqrestore(&cdev->lock, flags); -- 2.34.1