add clock gate in usb module
authoryangkai <yangkai@ubuntu-fs.(none)>
Tue, 21 Dec 2010 09:25:22 +0000 (17:25 +0800)
committeryangkai <yangkai@ubuntu-fs.(none)>
Tue, 21 Dec 2010 09:25:22 +0000 (17:25 +0800)
drivers/usb/dwc_otg/Kconfig
drivers/usb/dwc_otg/dwc_otg_cil.c
drivers/usb/dwc_otg/dwc_otg_driver.c
drivers/usb/dwc_otg/dwc_otg_driver.h
drivers/usb/dwc_otg/dwc_otg_pcd.c

index e5573885b786c4909fce9bccba4c1addd0dc986a..24267cd81b1ad6bba039d247fc65dcd96ca1c9cb 100755 (executable)
@@ -14,6 +14,7 @@ config USB20_HOST
 
 config USB20_OTG
        tristate "RockChip USB 2.0 OTG controller"
+       depends on USB||USB_GADGET
         ---help---
           This driver supports Rockchip USB2.0  DWC_OTG 
          controller.
index a5f2c07dda45f458f4455a7d020f729d84a0d3ab..853777fea7991b8f4d4982587c0da462af6069df 100755 (executable)
@@ -614,7 +614,7 @@ void dwc_otg_core_init(dwc_otg_core_if_t *_core_if)
        case DWC_INT_DMA_ARCH:
                /* rockchip dwc_otg */
                DWC_DEBUGPL(DBG_CIL, "Internal DMA Mode\n");
-               ahbcfg.b.hburstlen = DWC_GAHBCFG_INT_DMA_BURST_INCR;
+               ahbcfg.b.hburstlen = DWC_GAHBCFG_INT_DMA_BURST_INCR16; // yk@20101221
        _core_if->dma_enable = (_core_if->core_params->dma_enable != 0);
                break;
 
@@ -812,6 +812,7 @@ void dwc_otg_core_dev_init(dwc_otg_core_if_t *_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 );
 }
 
index 6b6361d596735e80c52621f1bb8f4606db448774..e5aa34a1648bb1d911709208c59df3155ba312c5 100755 (executable)
@@ -824,6 +824,8 @@ static int dwc_otg_driver_remove(struct platform_device *pdev)
        {
                iounmap(otg_dev->base);
        }
+       clk_put(otg_dev->clk);
+       clk_disable(otg_dev->clk);
        kfree(otg_dev);
 
        /*
@@ -853,8 +855,8 @@ static int dwc_otg_driver_remove(struct platform_device *pdev)
  */
 static __devinit int dwc_otg_driver_probe(struct platform_device *pdev)
 {
-       struct resource *res_base;
        int retval = 0;
+       struct resource *res_base;
        struct device *dev = &pdev->dev;
        dwc_otg_device_t *dwc_otg_device;
        int32_t snpsid;
@@ -864,7 +866,16 @@ static __devinit int dwc_otg_driver_probe(struct platform_device *pdev)
         *Enable usb phy
         */
     unsigned int * otg_phy_con1 = (unsigned int*)(USB_GRF_CON);
+    struct clk* clk;
     
+    clk = clk_get(NULL, "otgphy0");
+     if (IS_ERR(clk)) {
+             retval = PTR_ERR(clk);
+             DWC_ERROR("can't get USB clock of otgphy0\n");
+            goto fail;
+     }
+     clk_enable(clk);
+
     regval = * otg_phy_con1;
     regval |= (0x01<<2);
     regval |= (0x01<<3);    // exit suspend.
@@ -896,6 +907,7 @@ static __devinit int dwc_otg_driver_probe(struct platform_device *pdev)
        
        memset(dwc_otg_device, 0, sizeof(*dwc_otg_device));
        dwc_otg_device->reg_offset = 0xFFFFFFFF;
+       dwc_otg_device->clk = clk;
        /*
         * Map the DWC_otg Core memory into virtual address space.
         */
@@ -1046,7 +1058,6 @@ static __devinit int dwc_otg_driver_probe(struct platform_device *pdev)
        dwc_otg_enable_global_interrupts( dwc_otg_device->core_if );
        DWC_PRINT("dwc_otg_driver_probe end, everest\n");
        return 0;
-
  fail:
        devm_kfree(&pdev->dev, dwc_otg_device);
        DWC_PRINT("dwc_otg_driver_probe fail,everest\n");
@@ -1191,6 +1202,8 @@ static int host11_driver_remove(struct platform_device *pdev)
        {
                iounmap(otg_dev->base);
        }
+       clk_put(otg_dev->clk);
+       clk_disable(otg_dev->clk);
        kfree(otg_dev);
 
        /*
@@ -1224,6 +1237,25 @@ static __devinit int host11_driver_probe(struct platform_device *pdev)
         *Enable usb phy
         */
     unsigned int * otg_phy_con1 = (unsigned int*)(USB_GRF_CON);
+    struct clk* clk;
+    
+    clk = clk_get(NULL, "uhost");
+     if (IS_ERR(clk)) {
+             retval = PTR_ERR(clk);
+             DWC_ERROR("can't get USB clock of uhost\n");
+            goto fail;
+     }
+     clk_enable(clk);
+    if (clk_get_rate(clk) != 48000000) {
+        DWC_PRINT("Bad USB clock (%d Hz), changing to 48000000 Hz\n",
+                 (int)clk_get_rate(clk));
+        if (clk_set_rate(clk, 48000000)) {
+            DWC_ERROR("Unable to set correct USB clock (48MHz)\n");
+            retval = -EIO;
+            goto fail1;
+        }
+    }
+    
     *otg_phy_con1 &= ~(0x01<<28);    // exit suspend.
     #if 0
     *otg_phy_con1 |= (0x01<<2);
@@ -1246,6 +1278,7 @@ static __devinit int host11_driver_probe(struct platform_device *pdev)
        
        memset(dwc_otg_device, 0, sizeof(*dwc_otg_device));
        dwc_otg_device->reg_offset = 0xFFFFFFFF;
+       dwc_otg_device->clk = clk;
        /*
         * Map the DWC_otg Core memory into virtual address space.
         */
@@ -1358,6 +1391,10 @@ static __devinit int host11_driver_probe(struct platform_device *pdev)
        dwc_otg_enable_global_interrupts( dwc_otg_device->core_if );
        DWC_PRINT("host11_driver_probe end, everest\n");
        return 0;
+    
+fail1:
+    clk_put(clk);
+    clk_disable(clk);
 
  fail:
        devm_kfree(&pdev->dev, dwc_otg_device);
@@ -1439,12 +1476,15 @@ static int host20_driver_remove(struct platform_device *pdev)
        {
                iounmap(otg_dev->base);
        }
+       clk_put(otg_dev->clk);
+       clk_disable(otg_dev->clk);
        kfree(otg_dev);
 
        /*
         * Clear the drvdata pointer.
         */
        dev->platform_data = 0;
+       
 
        return 0;
 }
@@ -1473,6 +1513,16 @@ static __devinit int host20_driver_probe(struct platform_device *pdev)
         *Enable usb phy
         */
     unsigned int * otg_phy_con1 = (unsigned int*)(USB_GRF_CON);
+    struct clk* clk;
+    
+    clk = clk_get(NULL, "otgphy1");
+     if (IS_ERR(clk)) {
+             retval = PTR_ERR(clk);
+             DWC_ERROR(&"can't get USB clock of otgphy1\n");
+            goto fail;
+     }
+     clk_enable(clk);
+    
     otgreg = * otg_phy_con1;
     otgreg |= (0x01<<13);    // software control
     otgreg |= (0x01<<14);    // exit suspend.
@@ -1499,6 +1549,7 @@ static __devinit int host20_driver_probe(struct platform_device *pdev)
        
        memset(dwc_otg_device, 0, sizeof(*dwc_otg_device));
        dwc_otg_device->reg_offset = 0xFFFFFFFF;
+       dwc_otg_device->clk = clk;
        /*
         * Map the DWC_otg Core memory into virtual address space.
         */
index fa104e0fdcbf723b6a8fcd7123097223c91d85eb..702b9744b6ab6c375ca8bb02f4eb92f9b070b8e4 100755 (executable)
@@ -49,21 +49,23 @@ struct dwc_otg_hcd;
  */
 typedef struct dwc_otg_device
 {
-               /** Base address returned from ioremap() */
-               void *base;
+       /** Base address returned from ioremap() */
+       void *base;
 
-               /** Pointer to the core interface structure. */
-               dwc_otg_core_if_t *core_if;
+       /** Pointer to the core interface structure. */
+       dwc_otg_core_if_t *core_if;
 
-               /** Register offset for Diagnostic API.*/
-               uint32_t reg_offset;
-               
-               /** Pointer to the PCD structure. */
-               struct dwc_otg_pcd *pcd;
+       /** Register offset for Diagnostic API.*/
+       uint32_t reg_offset;
+       
+       /** Pointer to the PCD structure. */
+       struct dwc_otg_pcd *pcd;
 
-               /** Pointer to the HCD structure. */
-               struct dwc_otg_hcd *hcd;
+       /** Pointer to the HCD structure. */
+       struct dwc_otg_hcd *hcd;
 
+    struct clk* clk;
+    
        /** Flag to indicate whether the common IRQ handler is installed. */
        uint8_t common_irq_installed;
 
index c1fe4382d4284cb1fca076f3278a743f8f4b8d74..42efcdf41fbca87f286c658fae034efda87fcd49 100755 (executable)
@@ -1540,30 +1540,29 @@ int rk28_usb_suspend( int exitsuspend )
 {
        dwc_otg_pcd_t *pcd = s_pcd;
 
-        unsigned int * otg_phy_con1 = (unsigned int*)(USB_GRF_CON);
-//        unsigned int * usb_core_ctrl_reg = (unsigned int*)(USB_OTG_BASE_ADDR_VA);
-        if(exitsuspend && (pcd->phy_suspend == 1)) {
-                pcd->phy_suspend = 0;
-                *otg_phy_con1 |= (0x01<<2);
-                *otg_phy_con1 |= (0x01<<3);    // exit suspend.
-                *otg_phy_con1 &= ~(0x01<<2);
-                
-                /* 20091011,reenable usb phy ,will raise reset intr */
-                //debug_print("enable usb phy\n");
-                DWC_DEBUGPL(DBG_PCDV, "enable usb phy\n");
-        }
-        if( !exitsuspend && (pcd->phy_suspend == 0)) {
-                if(1) {//!__rkusb_debug_mod()
-                        pcd->phy_suspend = 1;
-                        *otg_phy_con1 |= (0x01<<2);
-                        *otg_phy_con1 &= ~(0x01<<3);    // enter suspend.
-                        //*otg_phy_con1 &= ~(0x01<<2);
-                        //debug_print("disable usb phy\n");
-                }
-                DWC_DEBUGPL(DBG_PCDV, "disable usb phy\n");
-        }
+    unsigned int * otg_phy_con1 = (unsigned int*)(USB_GRF_CON);
+    if(exitsuspend && (pcd->phy_suspend == 1)) {
+        clk_enable(pcd->otg_dev->clk);
+        pcd->phy_suspend = 0;
+        *otg_phy_con1 |= (0x01<<2);
+        *otg_phy_con1 |= (0x01<<3);    // exit suspend.
+        *otg_phy_con1 &= ~(0x01<<2);
         
-        return pcd->phy_suspend;
+        /* 20091011,reenable usb phy ,will raise reset intr */
+        //debug_print("enable usb phy\n");
+        DWC_DEBUGPL(DBG_PCDV, "enable usb phy\n");
+    }
+    if( !exitsuspend && (pcd->phy_suspend == 0)) {
+        pcd->phy_suspend = 1;
+        *otg_phy_con1 |= (0x01<<2);
+        *otg_phy_con1 &= ~(0x01<<3);    // enter suspend.
+        clk_disable(pcd->otg_dev->clk);
+        //*otg_phy_con1 &= ~(0x01<<2);
+        //debug_print("disable usb phy\n");
+        DWC_DEBUGPL(DBG_PCDV, "disable usb phy\n");
+    }
+    
+    return pcd->phy_suspend;
 }
 void rk28_usb_force_resume( void )
 {
@@ -1607,28 +1606,27 @@ void dwc_otg_msc_unlock(void)
 }
 static void dwc_phy_reconnect(struct work_struct *work)
 {
-        dwc_otg_pcd_t *pcd;
-        dwc_otg_core_if_t *core_if;
-        gotgctl_data_t    gctrl;
-        dctl_data_t dctl = {.d32=0};
-
-        pcd = container_of(work, dwc_otg_pcd_t, reconnect.work);
-        core_if = GET_CORE_IF(pcd); 
-        gctrl.d32 = dwc_read_reg32( &core_if->core_global_regs->gotgctl );
-        if( gctrl.b.bsesvld  ) {
-            dwc_otg_msc_lock();
-//            pcd->vbus_status = 1;    /* set after softconnect */
-            pcd->conn_status++;
-                  dwc_pcd_reset(pcd);
-               /*
-                * Enable the global interrupt after all the interrupt
-                * handlers are installed.
-                */
+    dwc_otg_pcd_t *pcd;
+    dwc_otg_core_if_t *core_if;
+    gotgctl_data_t    gctrl;
+    dctl_data_t dctl = {.d32=0};
+
+    pcd = container_of(work, dwc_otg_pcd_t, reconnect.work);
+    core_if = GET_CORE_IF(pcd); 
+    gctrl.d32 = dwc_read_reg32( &core_if->core_global_regs->gotgctl );
+    if( gctrl.b.bsesvld  ) {
+        dwc_otg_msc_lock();
+        pcd->conn_status++;
+           dwc_pcd_reset(pcd);
+       /*
+        * Enable the global interrupt after all the interrupt
+        * handlers are installed.
+        */
         dctl.d32 = dwc_read_reg32( &core_if->dev_if->dev_global_regs->dctl );
         dctl.b.sftdiscon = 0;
         dwc_write_reg32( &core_if->dev_if->dev_global_regs->dctl, dctl.d32 );     
         DWC_PRINT("********soft connect!!!*****************************************\n");
-        
+    } 
 }
 
 static void dwc_otg_pcd_check_vbus_timer( unsigned long pdata )
@@ -1645,66 +1643,65 @@ static void dwc_otg_pcd_check_vbus_timer( unsigned long pdata )
 
     _pcd->check_vbus_timer.expires = jiffies + (HZ); /* 1 s */
     if( gctrl.b.bsesvld ) {
-            /* if usb not connect before ,then start connect */
-             if( _pcd->vbus_status == 0 ) {
-                    DWC_PRINT("********vbus detect*********************************************\n");
-//                 _pcd->conn_status =
-                   _pcd->vbus_status = 1;
-                    /* 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_status>0)&&(_pcd->conn_status <3)) {
-                    dwc_otg_msc_unlock();
-                    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); 
-            }
-           else if((_pcd->conn_en)&&(_pcd->conn_status == 0))
+        /* if usb not connect before ,then start connect */
+         if( _pcd->vbus_status == 0 ) {
+            DWC_PRINT("********vbus detect*********************************************\n");
+           _pcd->vbus_status = 1;
+        /* 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 */
+           schedule_delayed_work( &_pcd->reconnect , 8 ); /* delay 1 jiffies */
+                    _pcd->check_vbus_timer.expires = jiffies + (HZ<<1); /* 1 s */
            }
-            else if(_pcd->conn_status ==3)
-            {
-                                       //*Á¬½Ó²»ÉÏʱÊÍ·ÅËø£¬ÔÊÐíϵͳ½øÈë¶þ¼¶Ë¯Ãߣ¬yk@rk,20100331*//
-                    dwc_otg_msc_unlock();
-                    _pcd->conn_status++;
-            }
+
+        } else if((_pcd->conn_status>0)&&(_pcd->conn_status <3)) {
+            dwc_otg_msc_unlock();
+            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); 
+        }
+        else if((_pcd->conn_en)&&(_pcd->conn_status == 0))
+        {
+       
+           schedule_delayed_work( &_pcd->reconnect , 8 ); /* delay 1 jiffies */
+                    _pcd->check_vbus_timer.expires = jiffies + (HZ<<1); /* 1 s */
+        }
+        else if(_pcd->conn_status ==3)
+        {
+                       //*Á¬½Ó²»ÉÏʱÊÍ·ÅËø£¬ÔÊÐíϵͳ½øÈë¶þ¼¶Ë¯Ãߣ¬yk@rk,20100331*//
+            dwc_otg_msc_unlock();
+            _pcd->conn_status++;
+        }
     } else {
-            //DWC_PRINT("new vbus=%d,old vbus=%d\n" , gctrl.b.bsesvld , _pcd->vbus_status );
-            _pcd->vbus_status = 0;
-            if(_pcd->conn_status)
-            {
-                 _pcd->conn_status = 0;
-                 dwc_otg_msc_unlock();
-            }
-            /* 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 );
-                  _pcd->check_vbus_timer.expires = jiffies + (HZ/2); /* 500 ms */
-            } else if( _pcd->phy_suspend  == 1 ) { 
-                 rk28_usb_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  */
-                 
-            }
+        //DWC_PRINT("new vbus=%d,old vbus=%d\n" , gctrl.b.bsesvld , _pcd->vbus_status );
+        _pcd->vbus_status = 0;
+        if(_pcd->conn_status)
+        {
+             _pcd->conn_status = 0;
+             dwc_otg_msc_unlock();
+        }
+        /* 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 );
+              _pcd->check_vbus_timer.expires = jiffies + (HZ/2); /* 500 ms */
+        } else if( _pcd->phy_suspend  == 1 ) { 
+             rk28_usb_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  */
+             
+        }
     }
     //DWC_PRINT("%s:restart check vbus timer\n" , __func__ );
     add_timer(&_pcd->check_vbus_timer); 
@@ -1851,6 +1848,7 @@ int dwc_otg_pcd_init(struct device *dev)
     
     INIT_DELAYED_WORK(&pcd->reconnect , dwc_phy_reconnect);
     pcd->vbus_status  = 0;
+    pcd->phy_suspend  = 0;
     if(dwc_otg_is_device_mode(core_if))
        dwc_otg_pcd_start_vbus_timer( pcd );
        return 0;