add clockgate for rk30 usb 2.0 otg
authoryangkai <yk@rock-chips.com>
Sun, 1 Apr 2012 04:42:18 +0000 (12:42 +0800)
committeryangkai <yk@rock-chips.com>
Sun, 1 Apr 2012 04:42:18 +0000 (12:42 +0800)
drivers/usb/dwc_otg/dwc_otg_cil_intr.c
drivers/usb/dwc_otg/dwc_otg_driver.c
drivers/usb/dwc_otg/dwc_otg_pcd.c

index bb3a896003713284a4a9a152f01067da59357a29..a4a07b42b27ab296b33a4128c6dbc8c97f2da374 100755 (executable)
@@ -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 );
        }
        
     /*
index 54b295f3a9affa6c5283fd0ee663ee5c305281d9..403def8a463bb45868bf6c7594f47d91fe9d2ebb 100755 (executable)
@@ -68,9 +68,7 @@
 #include "dwc_otg_cil.h"
 #include "dwc_otg_pcd.h"
 #include "dwc_otg_hcd.h"
-#ifdef CONFIG_ARCH_RK29
 #include <mach/cru.h>
-#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 
index a1ad5d466ce91f1d9166d2dec45ba46eeb3b4e88..8ea6354e68ed885797d71ddde9d057b5320d7784 100755 (executable)
@@ -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