add sysfs switch for usbhost
authoryangkai <yangkai@ubuntu-fs.(none)>
Mon, 27 Dec 2010 08:46:37 +0000 (16:46 +0800)
committeryangkai <yangkai@ubuntu-fs.(none)>
Mon, 27 Dec 2010 08:46:37 +0000 (16:46 +0800)
drivers/usb/dwc_otg/Kconfig
drivers/usb/dwc_otg/dwc_otg_attr.c
drivers/usb/dwc_otg/dwc_otg_cil.c
drivers/usb/dwc_otg/dwc_otg_cil.h
drivers/usb/dwc_otg/dwc_otg_driver.c
drivers/usb/dwc_otg/dwc_otg_hcd.c
drivers/usb/dwc_otg/dwc_otg_hcd.h
drivers/usb/dwc_otg/dwc_otg_hcd_intr.c

index 24267cd81b1ad6bba039d247fc65dcd96ca1c9cb..004b92d016aa940aa0ad585a967e704566eeafa9 100755 (executable)
@@ -5,6 +5,11 @@ config USB11_HOST
          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
@@ -12,6 +17,11 @@ config USB20_HOST
          This driver supports Rockchip USB2.0 host
          controller.
 
+config USB20_HOST_EN
+       bool "---usb2.0 host controller enable"
+       depends on USB20_HOST
+       default y
+
 config USB20_OTG
        tristate "RockChip USB 2.0 OTG controller"
        depends on USB||USB_GADGET
@@ -43,14 +53,19 @@ config DWC_OTG_DEVICE_ONLY
 endchoice
 
 config DWC_CONN_EN
-       bool "connect to PC when vbus detect"
-       default y
+       bool "---connect to PC when vbus detect"
        depends on DWC_OTG_DEVICE_ONLY
+       default y
        help
          USB2.0 OTG controller always polling the USB vbus
          
          if selected, device will connect to PC automatic
 
+config USB20_OTG_EN
+       bool "---usb2.0 otg host controller enable"
+       depends on DWC_OTG_HOST_ONLY
+       default y
+
 config DWC_OTG_DEBUG
        bool "DWC_OTG debug messages"
        depends on USB11_HOST || USB20_HOST || USB20_OTG
index 9fb2024a5888b316ec22121fc79cd3d194e7f114..710c9ca9e27b1441be0e02c2cdd096a23d068f65 100755 (executable)
@@ -735,7 +735,7 @@ static ssize_t wr_reg_test_show( struct device *_dev,
 }
 
 DEVICE_ATTR(wr_reg_test, S_IRUGO|S_IWUSR, wr_reg_test_show, 0);
-extern int dwc_debug(int flag);
+extern int dwc_debug(dwc_otg_core_if_t *core_if, int flag);
 static ssize_t debug_show( struct device *_dev, 
                                                                struct device_attribute *attr, char *buf) 
 {
@@ -753,11 +753,15 @@ static ssize_t debug_store( struct device *_dev,
                                                                const char *buf, size_t count ) 
 {
        uint32_t val = simple_strtoul(buf, NULL, 16);
-    dwc_debug(val);
+    dwc_otg_device_t *otg_dev = _dev->platform_data;
+    dwc_otg_dump_global_registers( otg_dev->core_if);
+    dwc_debug(otg_dev->core_if,val);
        return count;
 }
 
 DEVICE_ATTR(debug, S_IRUGO|S_IWUSR, debug_show, debug_store);
+
+
 /**@}*/
 
 /**
index 853777fea7991b8f4d4982587c0da462af6069df..387d1e4c712602a29c948d7a3433dc7dac614195 100755 (executable)
@@ -65,6 +65,7 @@
 #include "dwc_otg_regs.h"
 #include "dwc_otg_driver.h"
 #include "dwc_otg_cil.h"
+#include "dwc_otg_pcd.h"
 static dwc_otg_core_if_t * dwc_core_if = NULL;
 /** 
  * This function is called to initialize the DWC_otg CSR data
@@ -3335,9 +3336,11 @@ void dwc_otg_dump_flags(dwc_otg_core_if_t *_core_if)
        DWC_PRINT("core_if->usb_mode = %x\n",_core_if->usb_mode);
        DWC_PRINT("core_if->usb_wakeup = %x\n",_core_if->usb_wakeup);
 }
-int dwc_debug(int flag)
+int dwc_debug(dwc_otg_core_if_t *core_if, int flag)
 {
-       dwc_otg_core_if_t *core_if = dwc_core_if;
+       //dwc_otg_core_if_t *core_if = dwc_core_if;
+       struct dwc_otg_device *otg_dev;
+       dwc_otg_pcd_t * pcd;
        switch(flag)
        {
                case 1:
@@ -3345,8 +3348,9 @@ int dwc_debug(int flag)
                        dwc_otg_dump_host_registers(core_if);
                        break;
                case 2:
-                       dwc_otg_dump_global_registers(core_if);
-                       dwc_otg_dump_dev_registers(core_if);
+                   otg_dev = core_if->otg_dev;
+                   pcd = otg_dev->pcd;
+                   pcd->vbus_status = 0;
                        break;
                case 3:
                        dump_scu_regs();
index 9027ff2b6658e21acd55fa9ed054de843b35f28f..003c689cfbc45c2ce1a9774ae1e8724e3975d43a 100755 (executable)
@@ -922,5 +922,5 @@ extern void dwc_otg_cil_register_pcd_callbacks( dwc_otg_core_if_t *_core_if,
 extern void dwc_otg_cil_register_hcd_callbacks( dwc_otg_core_if_t *_core_if,
                                                                                                dwc_otg_cil_callbacks_t *_cb,
                                                                                                void *_p);
-extern int dwc_debug(int flag);                                                                                                
+extern int dwc_debug(dwc_otg_core_if_t *core_if, int flag);                                                                                            
 #endif
index ebbb9da51bd561d15a40bc82a3371cb6d01c4f43..0f53243432e0f8bdf0379c35ee90121fb0623dd3 100755 (executable)
@@ -331,17 +331,66 @@ 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_DWC_OTG_DEVICE_ONLY
+static ssize_t dwc_otg_enable_show( struct device *_dev, 
+                                                               struct device_attribute *attr, char *buf)
+{
+    dwc_otg_device_t *otg_dev = _dev->platform_data;
+    return sprintf (buf, "%d\n", otg_dev->hcd->host_enabled);
+}
+
+static ssize_t dwc_otg_enable_store( struct device *_dev,
+                                                               struct device_attribute *attr, 
+                                                               const char *buf, size_t count )
+{
+    dwc_otg_device_t *otg_dev = _dev->platform_data;
+    dwc_otg_core_if_t *_core_if = otg_dev->core_if;
+    struct platform_device *pdev = to_platform_device(_dev);
+       uint32_t val = simple_strtoul(buf, NULL, 16);
+       if(otg_dev->hcd->host_enabled == val)
+           return count;
+           
+       otg_dev->hcd->host_enabled = val;
+       if(val == 0)    // enable -> disable
+       {
+           DWC_PRINT("disable host controller:%s\n",pdev->name);
+           #if 1
+        if (_core_if->hcd_cb && _core_if->hcd_cb->disconnect) {
+                _core_if->hcd_cb->disconnect( _core_if->hcd_cb->p );
+        }
+        #endif
+        if (_core_if->hcd_cb && _core_if->hcd_cb->stop) {
+                _core_if->hcd_cb->stop( _core_if->hcd_cb->p );
+        }
+        clk_disable(otg_dev->phyclk);
+        clk_disable(otg_dev->ahbclk);
+       }
+       else if(val == 1)
+       {
+           DWC_PRINT("enable host controller:%s\n",pdev->name);
+        clk_enable(otg_dev->phyclk);
+        clk_enable(otg_dev->ahbclk);
+        if (_core_if->hcd_cb && _core_if->hcd_cb->start) {
+                _core_if->hcd_cb->start( _core_if->hcd_cb->p );
+        }
+       }
+
+    return count;
+}
+static DEVICE_ATTR(enable, S_IRUGO|S_IWUSR, dwc_otg_enable_show, dwc_otg_enable_store);
+
 static ssize_t dwc_otg_conn_en_show(struct device_driver *_drv, char *_buf)
 {
+#ifdef CONFIG_DWC_OTG_DEVICE_ONLY
     dwc_otg_device_t *otg_dev = g_otgdev;
     dwc_otg_pcd_t *_pcd = otg_dev->pcd;
     return sprintf (_buf, "%d\n", _pcd->conn_en);
+#endif
 }
 
 static ssize_t dwc_otg_conn_en_store(struct device_driver *_drv, const char *_buf,
                                     size_t _count)
 {
+#ifdef CONFIG_DWC_OTG_DEVICE_ONLY
     int enable = simple_strtoul(_buf, NULL, 10);
     dwc_otg_device_t *otg_dev = g_otgdev;
     dwc_otg_pcd_t *_pcd = otg_dev->pcd;
@@ -349,8 +398,10 @@ static ssize_t dwc_otg_conn_en_store(struct device_driver *_drv, const char *_bu
     
     _pcd->conn_en = enable;
     return _count;
+#endif
 }
 static DRIVER_ATTR(dwc_otg_conn_en, S_IRUGO|S_IWUSR, dwc_otg_conn_en_show, dwc_otg_conn_en_store);
+#ifdef CONFIG_DWC_OTG_DEVICE_ONLY
 static ssize_t vbus_status_show(struct device_driver *_drv, char *_buf)
 {
     dwc_otg_device_t *otg_dev = g_otgdev;
@@ -1004,6 +1055,9 @@ static __devinit int dwc_otg_driver_probe(struct platform_device *pdev)
         * Create Device Attributes in sysfs
         */      
        dwc_otg_attr_create(dev);
+#ifdef CONFIG_DWC_OTG_HOST_ONLY
+       retval |= device_create_file(dev, &dev_attr_enable);
+#endif
 
        /*
         * Disable the global interrupt until all the interrupt
@@ -1079,6 +1133,12 @@ static __devinit int dwc_otg_driver_probe(struct platform_device *pdev)
         * handlers are installed.
         */
        dwc_otg_enable_global_interrupts( dwc_otg_device->core_if );
+#ifdef CONFIG_DWC_OTG_HOST_ONLY
+#ifndef CONFIG_USB20_OTG_EN
+            clk_disable(otg_dev->phyclk);
+            clk_disable(otg_dev->ahbclk);
+#endif
+#endif
        DWC_PRINT("dwc_otg_driver_probe end, everest\n");
        return 0;
  fail:
@@ -1379,6 +1439,7 @@ static __devinit int host11_driver_probe(struct platform_device *pdev)
         * Create Device Attributes in sysfs
         */      
        dwc_otg_attr_create(dev);
+       retval |= device_create_file(dev, &dev_attr_enable);
 
        /*
         * Disable the global interrupt until all the interrupt
@@ -1425,6 +1486,10 @@ static __devinit int host11_driver_probe(struct platform_device *pdev)
         * handlers are installed.
         */
        dwc_otg_enable_global_interrupts( dwc_otg_device->core_if );
+#ifndef CONFIG_USB11_HOST_EN
+    clk_disable(phyclk);
+    clk_disable(ahbclk);
+#endif
        DWC_PRINT("host11_driver_probe end, everest\n");
        return 0;
     
@@ -1665,6 +1730,7 @@ static __devinit int host20_driver_probe(struct platform_device *pdev)
         * Create Device Attributes in sysfs
         */      
        dwc_otg_attr_create(dev);
+       retval |= device_create_file(dev, &dev_attr_enable);
 
        /*
         * Disable the global interrupt until all the interrupt
@@ -1712,6 +1778,10 @@ static __devinit int host20_driver_probe(struct platform_device *pdev)
         * handlers are installed.
         */
        dwc_otg_enable_global_interrupts( dwc_otg_device->core_if );
+#ifndef CONFIG_USB20_HOST_EN
+    clk_disable(phyclk);
+    clk_disable(ahbclk);
+#endif
        DWC_PRINT("host20_driver_probe end, everest\n");
        return 0;
 
index 021b62b297d683b225fb7a70050fdb6dc5aaeb08..ff0453726a5820ddb3d478bdb445a87e17d0be88 100755 (executable)
@@ -62,7 +62,6 @@ static int dwc_otg_hcd_suspend(struct usb_hcd *hcd)
     dwc_otg_core_if_t *core_if = dwc_otg_hcd->core_if;
     hprt0_data_t hprt0;
     pcgcctl_data_t pcgcctl;
-    //dwc_debug(1);
     
     if(core_if->op_state == B_PERIPHERAL)
     {
@@ -129,8 +128,6 @@ static int dwc_otg_hcd_resume(struct usb_hcd *hcd)
     dwc_write_reg32(core_if->pcgcctl, pcgcctl.d32);
     udelay(2);
 #endif
-    //dwc_debug(3);
-    //dwc_debug(1);
     gintmsk.d32 = dwc_read_reg32(&core_if->core_global_regs->gintmsk);
     gintmsk.b.portintr = 0;
     dwc_write_reg32(&core_if->core_global_regs->gintmsk, gintmsk.d32);
@@ -386,7 +383,7 @@ static void kill_urbs_in_qh_list(dwc_otg_hcd_t *_hcd, struct list_head *_qh_list
                }
        }
 }
-
+#if 0
 /**
  * Responds with an error status of ETIMEDOUT to all URBs in the non-periodic
  * and periodic schedules. The QTD associated with each URB is removed from
@@ -402,7 +399,7 @@ static void kill_all_urbs(dwc_otg_hcd_t *_hcd)
        kill_urbs_in_qh_list(_hcd, &_hcd->periodic_sched_assigned);
        kill_urbs_in_qh_list(_hcd, &_hcd->periodic_sched_queued);
 }
-
+#endif 
 /**
  * HCD Callback function for disconnect of the HCD.
  *
@@ -453,7 +450,8 @@ static int32_t dwc_otg_hcd_disconnect_cb( void *_p )
         }
                 
        /* Respond with an error status to all URBs in the schedule. */
-       kill_all_urbs(dwc_otg_hcd);
+       // yk@20101227 handle kernel panic bug when disconnect
+       //kill_all_urbs(dwc_otg_hcd);
 
        if (dwc_otg_is_host_mode(dwc_otg_hcd->core_if)) {
                /* Clean up any host channels that were in use. */
@@ -638,6 +636,12 @@ int __devinit dwc_otg_hcd_init(struct device *dev)
 
        dwc_otg_hcd->core_if = otg_dev->core_if;
        otg_dev->hcd = dwc_otg_hcd;
+    
+#ifdef CONFIG_USB20_OTG_EN
+    dwc_otg_hcd->host_enabled = 1;
+#else
+    dwc_otg_hcd->host_enabled = 0;
+#endif
 
         /* Register the HCD CIL Callbacks */
         dwc_otg_cil_register_hcd_callbacks(otg_dev->core_if, 
@@ -714,7 +718,7 @@ int __devinit dwc_otg_hcd_init(struct device *dev)
                DWC_ERROR("%s: status_buf allocation failed\n", __func__);
                goto error3;
        }
-
+    
        DWC_PRINT("%s end,everest\n",__func__);
 //     DWC_DEBUGPL(DBG_HCD, "DWC OTG HCD Initialized HCD, bus=%s, usbbus=%d\n", 
 //                 dev->bus_id, hcd->self.busnum);
@@ -795,6 +799,12 @@ int __devinit host11_hcd_init(struct device *dev)
        dwc_otg_hcd = hcd_to_dwc_otg_hcd(hcd);
        dwc_otg_hcd->core_if = otg_dev->core_if;
        otg_dev->hcd = dwc_otg_hcd;
+    
+#ifdef CONFIG_USB11_HOST_EN
+        dwc_otg_hcd->host_enabled = 1;
+#else
+        dwc_otg_hcd->host_enabled = 0;
+#endif
 
        spin_lock_init(&dwc_otg_hcd->global_lock);
 
@@ -955,6 +965,12 @@ int __devinit host20_hcd_init(struct device *dev)
        dwc_otg_hcd = hcd_to_dwc_otg_hcd(hcd);
        dwc_otg_hcd->core_if = otg_dev->core_if;
        otg_dev->hcd = dwc_otg_hcd;
+    
+#ifdef CONFIG_USB20_HOST_EN
+        dwc_otg_hcd->host_enabled = 1;
+#else
+        dwc_otg_hcd->host_enabled = 0;
+#endif
 
        spin_lock_init(&dwc_otg_hcd->global_lock);
 
@@ -1034,10 +1050,8 @@ int __devinit host20_hcd_init(struct device *dev)
                DWC_ERROR("%s: status_buf allocation failed\n", __func__);
                goto error3;
        }
-
+    
        DWC_PRINT("%s end,everest\n",__func__);
-//     DWC_DEBUGPL(DBG_HCD, "DWC OTG HCD Initialized HCD, bus=%s, usbbus=%d\n", 
-//                 dev->bus_id, hcd->self.busnum);
         
        return 0;
 
@@ -1164,7 +1178,7 @@ int dwc_otg_hcd_start(struct usb_hcd *_hcd)
        }
        /* Initialize the bus state.  If the core is in Device Mode
         * HALT the USB bus and return. */
-       if (dwc_otg_is_device_mode (core_if)) {
+       if (!dwc_otg_hcd->host_enabled || dwc_otg_is_device_mode (core_if)) {
                DWC_PRINT("dwc_otg_hcd_start controller in device mode,everest\n");
                //_hcd->state = HC_STATE_HALT;
                goto out;
@@ -1467,6 +1481,7 @@ int dwc_otg_hcd_urb_dequeue(struct usb_hcd *_hcd, struct urb *_urb, int _status)
        if(urb_qtd == NULL)
        {
                DWC_PRINT("%s,urb_qtd is null\n",__func__);
+               goto urb_qtd_null;
                //return -1;
        }
        dwc_otg_hcd = hcd_to_dwc_otg_hcd(_hcd);
@@ -1510,6 +1525,8 @@ int dwc_otg_hcd_urb_dequeue(struct usb_hcd *_hcd, struct urb *_urb, int _status)
                dwc_otg_hcd_qh_remove(dwc_otg_hcd, qh);
        }
 #endif
+       
+urb_qtd_null:
        spin_unlock_irqrestore(&dwc_otg_hcd->global_lock, flags);
        _urb->hcpriv = NULL;
        usb_hcd_unlink_urb_from_ep(_hcd, _urb);
index 18ddb3ea19238c62ac74d4709b487278a1f810aa..262f2289dd0599d0a30ef856140e4e13bff31f18 100755 (executable)
@@ -382,6 +382,9 @@ typedef struct dwc_otg_hcd {
        uint64_t                hfnum_other_frrem_accum_b;
 #endif 
 
+    /** Flag to indicate whether host controller is enabled. */
+    uint8_t host_enabled;
+
 } dwc_otg_hcd_t;
 
 /** Gets the dwc_otg_hcd from a struct usb_hcd */
index 150ec592d9755caa821f3d7ff171f22fbb9f97cb..74a41c9566b4f211a34ee8fb480c0ef60d3d552a 100755 (executable)
@@ -1764,7 +1764,6 @@ static void handle_hc_chhltd_intr_dma(dwc_otg_hcd_t *_hcd,
                handle_hc_ack_intr(_hcd, _hc, _hc_regs, _qtd);
        } else if(hcint.b.datatglerr){
             DWC_PRINT("%s, DATA toggle error, Channel %d\n",__func__, _hc->hc_num);
-            dwc_debug(1);
                                clear_hc_int(_hc_regs,chhltd);
        } else {
                if (_hc->ep_type == DWC_OTG_EP_TYPE_INTR ||