From a89f841a2ad161f1a30227fc20f1507ddfde539a Mon Sep 17 00:00:00 2001 From: yangkai Date: Sun, 1 Apr 2012 12:42:18 +0800 Subject: [PATCH] add clockgate for rk30 usb 2.0 otg --- drivers/usb/dwc_otg/dwc_otg_cil_intr.c | 4 +- drivers/usb/dwc_otg/dwc_otg_driver.c | 92 ++++++++++++++++++---- drivers/usb/dwc_otg/dwc_otg_pcd.c | 101 ++++++++++++------------- 3 files changed, 126 insertions(+), 71 deletions(-) diff --git a/drivers/usb/dwc_otg/dwc_otg_cil_intr.c b/drivers/usb/dwc_otg/dwc_otg_cil_intr.c index bb3a89600371..a4a07b42b27a 100755 --- a/drivers/usb/dwc_otg/dwc_otg_cil_intr.c +++ b/drivers/usb/dwc_otg/dwc_otg_cil_intr.c @@ -340,7 +340,7 @@ int32_t dwc_otg_handle_otg_intr(dwc_otg_core_if_t *_core_if) #ifdef DWC_BOTH_HOST_SLAVE extern void dwc_otg_force_device(dwc_otg_core_if_t *core_if); extern void dwc_otg_force_host(dwc_otg_core_if_t *core_if); -extern int rk28_usb_suspend( int exitsuspend ); +extern int dwc_otg20phy_suspend( int exitsuspend ); #endif int32_t dwc_otg_handle_conn_id_status_change_intr(dwc_otg_core_if_t *_core_if) @@ -353,7 +353,7 @@ int32_t dwc_otg_handle_conn_id_status_change_intr(dwc_otg_core_if_t *_core_if) gotgctl_data_t gotgctl = { .d32 = 0 }; if(pcd &&(pcd->phy_suspend == 1)) { - rk28_usb_suspend( 1 ); + dwc_otg20phy_suspend( 1 ); } /* diff --git a/drivers/usb/dwc_otg/dwc_otg_driver.c b/drivers/usb/dwc_otg/dwc_otg_driver.c index 54b295f3a9af..403def8a463b 100755 --- a/drivers/usb/dwc_otg/dwc_otg_driver.c +++ b/drivers/usb/dwc_otg/dwc_otg_driver.c @@ -68,9 +68,7 @@ #include "dwc_otg_cil.h" #include "dwc_otg_pcd.h" #include "dwc_otg_hcd.h" -#ifdef CONFIG_ARCH_RK29 #include -#endif //#define DWC_DRIVER_VERSION "2.60a 22-NOV-2006" //#define DWC_DRIVER_VERSION "2.70 2009-12-31" #define DWC_DRIVER_VERSION "3.00 2010-12-12 rockchip" @@ -338,7 +336,7 @@ extern struct usb_hub *g_root_hub20; #ifdef DWC_BOTH_HOST_SLAVE extern void hcd_start( dwc_otg_core_if_t *_core_if ); -extern int rk28_usb_suspend( int exitsuspend ); +extern int dwc_otg20phy_suspend( int exitsuspend ); extern void hub_disconnect_device(struct usb_hub *hub); static ssize_t force_usb_mode_show(struct device_driver *_drv, char *_buf) @@ -376,7 +374,7 @@ void dwc_otg_force_host(dwc_otg_core_if_t *core_if) } if((otg_dev->pcd)&&(otg_dev->pcd->phy_suspend == 1)) { - rk28_usb_suspend( 1 ); + dwc_otg20phy_suspend( 1 ); } del_timer(&otg_dev->pcd->check_vbus_timer); // force disconnect @@ -503,7 +501,7 @@ static ssize_t force_usb_mode_store(struct device_driver *_drv, const char *_buf core_if->usb_mode = new_mode; if((otg_dev->pcd)&&(otg_dev->pcd->phy_suspend == 1)) { - rk28_usb_suspend( 1 ); + dwc_otg20phy_suspend( 1 ); } del_timer(&otg_dev->pcd->check_vbus_timer); dwc_otg_set_gusbcfg(core_if, new_mode); @@ -525,7 +523,7 @@ static ssize_t force_usb_mode_store(struct device_driver *_drv, const char *_buf { if((otg_dev->pcd)&&(otg_dev->pcd->phy_suspend == 1)) { - rk28_usb_suspend( 1 ); + dwc_otg20phy_suspend( 1 ); } core_if->usb_mode = new_mode; dwc_otg_set_gusbcfg(core_if, new_mode); @@ -1152,8 +1150,10 @@ static int dwc_otg_driver_remove(struct platform_device *pdev) clk_disable(otg_dev->phyclk); clk_put(otg_dev->ahbclk); clk_disable(otg_dev->ahbclk); +#ifdef CONFIG_ARCH_RK29 clk_put(otg_dev->busclk); clk_disable(otg_dev->busclk); +#endif kfree(otg_dev); /* @@ -1195,11 +1195,11 @@ static __devinit int dwc_otg_driver_probe(struct platform_device *pdev) unsigned int * otg_phy_con1 = (unsigned int*)(USB_GRF_CON); #endif #ifdef CONFIG_ARCH_RK30 - unsigned int * otg_phy_con1 = (unsigned int*)(USBGRF_UOC0_CON2); + unsigned int * otg_phy_con = (unsigned int*)(USBGRF_UOC0_CON2); #endif - regval = * otg_phy_con1; -#ifdef CONFIG_ARCH_RK29 +#ifdef CONFIG_ARCH_RK29 + regval = * otg_phy_con1; #ifndef CONFIG_USB11_HOST /* * disable usb host 1.1 controller if not support @@ -1258,6 +1258,34 @@ static __devinit int dwc_otg_driver_probe(struct platform_device *pdev) #endif #endif +#ifdef CONFIG_ARCH_RK30 +#ifndef CONFIG_USB20_HOST + otg_phy_con = (unsigned int*)(USBGRF_UOC1_CON2); + /* + * disable usb host 2.0 phy if not support + */ + phyclk = clk_get(NULL, "otgphy1"); + if (IS_ERR(phyclk)) { + retval = PTR_ERR(phyclk); + DWC_ERROR("can't get USBPHY1 clock\n"); + goto fail; + } + clk_enable(phyclk); + + ahbclk = clk_get(NULL, "hclk_otg1"); + if (IS_ERR(ahbclk)) { + retval = PTR_ERR(ahbclk); + DWC_ERROR("can't get USBOTG1 ahb bus clock\n"); + goto fail; + } + clk_enable(ahbclk); + + *otg_phy_con = ((0x01<<2)|(0x00<<3)|(0x05<<6))|(((0x01<<2)|(0x01<<3)|(0x07<<6))<<16); // enter suspend. + udelay(3); + clk_disable(phyclk); + clk_disable(ahbclk); +#endif +#endif dwc_otg_device = kmalloc(sizeof(dwc_otg_device_t), GFP_KERNEL); if (dwc_otg_device == 0) @@ -1315,7 +1343,42 @@ static __devinit int dwc_otg_driver_probe(struct platform_device *pdev) dwc_otg_device->phyclk = phyclk; dwc_otg_device->ahbclk = ahbclk; dwc_otg_device->busclk = busclk; -#endif +#endif +#ifdef CONFIG_ARCH_RK30 + otg_phy_con = (unsigned int*)(USBGRF_UOC0_CON2); + cru_set_soft_reset(SOFT_RST_USBPHY0, true); + cru_set_soft_reset(SOFT_RST_OTGC0, true); + cru_set_soft_reset(SOFT_RST_USBOTG0, true); + udelay(1); + + cru_set_soft_reset(SOFT_RST_USBOTG0, false); + cru_set_soft_reset(SOFT_RST_OTGC0, false); + cru_set_soft_reset(SOFT_RST_USBPHY0, false); + + phyclk = clk_get(NULL, "otgphy0"); + if (IS_ERR(phyclk)) { + retval = PTR_ERR(phyclk); + DWC_ERROR("can't get USBPHY0 clock\n"); + goto fail; + } + clk_enable(phyclk); + + ahbclk = clk_get(NULL, "hclk_otg0"); + if (IS_ERR(ahbclk)) { + retval = PTR_ERR(ahbclk); + DWC_ERROR("can't get USB otg0 ahb bus clock\n"); + goto fail; + } + clk_enable(ahbclk); + + /* + * Enable usb phy 0 + */ + *otg_phy_con = ((0x01<<2)<<16); + + dwc_otg_device->phyclk = phyclk; + dwc_otg_device->ahbclk = ahbclk; +#endif /* * Map the DWC_otg Core memory into virtual address space. */ @@ -1324,8 +1387,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,USBOTG_SIZE); + dwc_otg_device->base = ioremap(res_base->start,USBOTG_SIZE); if (dwc_otg_device->base == NULL) { dev_err(dev, "ioremap() failed\n"); @@ -1498,7 +1560,7 @@ static __devinit int dwc_otg_driver_probe(struct platform_device *pdev) } #ifndef CONFIG_DWC_OTG_HOST_ONLY -extern int rk28_usb_suspend( int exitsuspend ); +extern int dwc_otg20phy_suspend( int exitsuspend ); static int dwc_otg_driver_suspend(struct platform_device *_dev , pm_message_t state ) { struct device *dev = &_dev->dev; @@ -1512,7 +1574,7 @@ static int dwc_otg_driver_suspend(struct platform_device *_dev , pm_message_t st /* Clear any pending interrupts */ dwc_write_reg32( &core_if->core_global_regs->gintsts, 0xFFFFFFFF); dwc_otg_disable_global_interrupts(core_if); - rk28_usb_suspend(0); + dwc_otg20phy_suspend(0); del_timer(&otg_dev->pcd->check_vbus_timer); return 0; @@ -1540,7 +1602,7 @@ static int dwc_otg_driver_resume(struct platform_device *_dev ) } #ifndef CONFIG_DWC_OTG_HOST_ONLY - rk28_usb_suspend(1); + dwc_otg20phy_suspend(1); /* soft disconnect */ /* 20100226,HSL@RK,if not disconnect,when usb cable in,will auto reconnect diff --git a/drivers/usb/dwc_otg/dwc_otg_pcd.c b/drivers/usb/dwc_otg/dwc_otg_pcd.c index a1ad5d466ce9..8ea6354e68ed 100755 --- a/drivers/usb/dwc_otg/dwc_otg_pcd.c +++ b/drivers/usb/dwc_otg/dwc_otg_pcd.c @@ -1603,15 +1603,11 @@ int dwc_pcd_reset(dwc_otg_pcd_t *pcd) * 20090925,add vbus test code.500ms ¼ä¸ô. * 20100122,HSL@RK,hard reset usb controller and phy. */ -int rk28_usb_suspend( int exitsuspend ) +int dwc_otg20phy_suspend( int exitsuspend ) { dwc_otg_pcd_t *pcd = s_pcd; #ifdef CONFIG_ARCH_RK29 unsigned int * otg_phy_con1 = (unsigned int*)(USB_GRF_CON); -#endif -#ifdef CONFIG_ARCH_RK30 - unsigned int * otg_phy_con1 = (unsigned int*)(USBGRF_UOC0_CON2); -#endif if(exitsuspend && (pcd->phy_suspend == 1)) { clk_enable(pcd->otg_dev->ahbclk); clk_enable(pcd->otg_dev->phyclk); @@ -1635,24 +1631,36 @@ int rk28_usb_suspend( int exitsuspend ) //debug_print("disable usb phy\n"); DWC_DEBUGPL(DBG_PCDV, "disable usb phy\n"); } - - return pcd->phy_suspend; -} -void rk28_usb_force_resume( void ) -{ - dwc_otg_pcd_t *pcd = s_pcd; - if( pcd ) { - del_timer(&pcd->check_vbus_timer); +#endif +#ifdef CONFIG_ARCH_RK30 + unsigned int * otg_phy_con1 = (unsigned int*)(USBGRF_UOC0_CON2); + if(exitsuspend && (pcd->phy_suspend == 1)) { + clk_enable(pcd->otg_dev->ahbclk); + clk_enable(pcd->otg_dev->phyclk); + pcd->phy_suspend = 0; + *otg_phy_con1 = ((0x01<<2)<<16); // exit suspend. +// *otg_phy_con1 |= (0x01<<3); +// *otg_phy_con1 &= ~(0x01<<2); + + /* 20091011,reenable usb phy ,will raise reset intr */ +// DWC_PRINT("enable usb phy 0x%x\n", *otg_phy_con1); + DWC_DEBUGPL(DBG_PCDV, "enable usb phy\n"); } - mdelay( 10 ); - if( pcd ) { + if( !exitsuspend && (pcd->phy_suspend == 0)) { pcd->phy_suspend = 1; - pcd->vbus_status = 0; - dwc_otg_pcd_start_vbus_timer(pcd); + *otg_phy_con1 = ((0x01<<2)|(0x00<<3)|(0x05<<6))|(((0x01<<2)|(0x01<<3)|(0x07<<6))<<16); // enter suspend. + udelay(3); + clk_disable(pcd->otg_dev->phyclk); + clk_disable(pcd->otg_dev->ahbclk); + //*otg_phy_con1 &= ~(0x01<<2); +// DWC_PRINT("disable usb phy 0x%x\n", *otg_phy_con1); + DWC_DEBUGPL(DBG_PCDV, "disable usb phy\n"); } +#endif + + return pcd->phy_suspend; } - int dwc_otg_reset( void ) { dwc_otg_pcd_t * pcd = s_pcd; @@ -1779,10 +1787,10 @@ static void dwc_otg_pcd_check_vbus_timer( unsigned long pdata ) /* every 500 ms open usb phy power and start 1 jiffies timer to get vbus */ if( _pcd->phy_suspend == 0 ) { /* no vbus detect here , close usb phy for 500ms */ - rk28_usb_suspend( 0 ); + dwc_otg20phy_suspend( 0 ); _pcd->check_vbus_timer.expires = jiffies + (HZ/2); /* 500 ms */ } else if( _pcd->phy_suspend == 1 ) { - rk28_usb_suspend( 1 ); + dwc_otg20phy_suspend( 1 ); /*20100325 yk@rk,delay 2-->8,for host connect id detect*/ _pcd->check_vbus_timer.expires = jiffies + 8; /* 20091127,HSL@RK,1-->2 */ @@ -1802,6 +1810,7 @@ static void dwc_otg_pcd_check_vbus_timer( unsigned long pdata ) dctl_data_t dctl = {.d32=0}; //dsts_data_t gsts; unsigned long flags; + local_irq_save(flags); #ifdef CONFIG_ARCH_RK30 unsigned int usbgrf_status = *(unsigned int*)(USBGRF_SOC_STATUS0); #endif @@ -1809,44 +1818,17 @@ static void dwc_otg_pcd_check_vbus_timer( unsigned long pdata ) if(usbgrf_status &0x20000){ // bvalid /* if usb not connect before ,then start connect */ if( _pcd->vbus_status == 0 ) { - dwc_otg_msc_lock(_pcd); DWC_PRINT("********vbus detect*********************************************\n"); + dwc_otg_msc_lock(_pcd); _pcd->vbus_status = 1; if(_pcd->conn_en) - { - if( _pcd->phy_suspend == 1 ) { -// rk28_usb_suspend( 1 ); - } - schedule_delayed_work( &_pcd->reconnect , 8 ); /* delay 1 jiffies */ - _pcd->check_vbus_timer.expires = jiffies + (HZ<<1); /* 1 s */ - } - - } else if((_pcd->conn_status>0)&&(_pcd->conn_status <3)) { - //dwc_otg_msc_unlock(_pcd); + goto connect; + } + else if((_pcd->conn_en)&&(_pcd->conn_status>=0)&&(_pcd->conn_status <3)){ DWC_PRINT("********soft reconnect******************************************\n"); - //_pcd->vbus_status =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 ); - /* Clear any pending interrupts */ - dwc_write_reg32( &core_if->core_global_regs->gintsts, 0xFFFFFFFF); - if(_pcd->conn_en) - { - schedule_delayed_work( &_pcd->reconnect , 8 ); /* delay 1 jiffies */ - _pcd->check_vbus_timer.expires = jiffies + (HZ<<1); /* 1 s */ - } - } - else if((_pcd->conn_en)&&(_pcd->conn_status == 0)) - { - DWC_PRINT("********vbus detect ccccc*********************************************\n"); - - schedule_delayed_work( &_pcd->reconnect , 8 ); /* delay 1 jiffies */ - _pcd->check_vbus_timer.expires = jiffies + (HZ<<1); /* 1 s */ + goto connect; } - else if(_pcd->conn_status ==3) - { + else if(_pcd->conn_status ==3){ //*Á¬½Ó²»ÉÏʱÊÍ·ÅËø£¬ÔÊÐíϵͳ½øÈë¶þ¼¶Ë¯Ãߣ¬yk@rk,20100331*// dwc_otg_msc_unlock(_pcd); _pcd->conn_status++; @@ -1863,9 +1845,20 @@ static void dwc_otg_pcd_check_vbus_timer( unsigned long pdata ) /* every 500 ms open usb phy power and start 1 jiffies timer to get vbus */ if( _pcd->phy_suspend == 0 ) /* no vbus detect here , close usb phy */ - rk28_usb_suspend( 0 ); + dwc_otg20phy_suspend( 0 ); } add_timer(&_pcd->check_vbus_timer); + local_irq_restore(flags); + return; + +connect: + if( _pcd->phy_suspend == 1 ) + dwc_otg20phy_suspend( 1 ); + schedule_delayed_work( &_pcd->reconnect , 8 ); /* delay 1 jiffies */ + _pcd->check_vbus_timer.expires = jiffies + (HZ<<1); /* 1 s */ + add_timer(&_pcd->check_vbus_timer); + local_irq_restore(flags); + return; } #endif -- 2.34.1