usb: gadget: fsl_udc: boost cpu rate for transaction
Alok Chauhan [Wed, 7 Mar 2012 08:18:41 +0000 (13:18 +0530)]
Boost CPU rate floor ( based upon
TEGRA_GADGET_BOOST_CPU_FREQ ) before any transaction
starts and remove the boost once the transaction completes.

Bug 923594

Signed-off-by: Alok Chauhan <alokc@nvidia.com>
Reviewed-on: http://git-master/r/88247
(cherry picked from commit cfb0c2d7bc7c00962c97c895958e2e0a13a14cfd)

Change-Id: I6c7524dbf90d6c3c8840ee8cd88e896dde6aa041
Reviewed-on: http://git-master/r/94173
Reviewed-by: Rohan Somvanshi <rsomvanshi@nvidia.com>
Tested-by: Rohan Somvanshi <rsomvanshi@nvidia.com>

drivers/usb/gadget/fsl_udc_core.c
drivers/usb/gadget/fsl_usb2_udc.h

index 7dfbc5e..c90e2d0 100644 (file)
@@ -82,10 +82,17 @@ static struct usb_sys_interface *usb_sys_regs;
 #define USB_CHARGING_CURRENT_LIMIT_MA 1800
 /* 1 sec wait time for charger detection after vbus is detected */
 #define USB_CHARGER_DETECTION_WAIT_TIME_MS 1000
+#define BOOST_TRIGGER_SIZE 4096
 
 /* it is initialized in probe()  */
 static struct fsl_udc *udc_controller = NULL;
 
+#ifdef CONFIG_TEGRA_GADGET_BOOST_CPU_FREQ
+static struct pm_qos_request_list boost_cpu_freq_req;
+static u32 ep_queue_request_count;
+static u8 boost_cpufreq_work_flag;
+#endif
+
 static const struct usb_endpoint_descriptor
 fsl_ep0_desc = {
        .bLength =              USB_DT_ENDPOINT_SIZE,
@@ -262,7 +269,13 @@ static void done(struct fsl_ep *ep, struct fsl_req *req, int status)
                        req->req.actual, req->req.length);
 
        ep->stopped = 1;
-
+#ifdef CONFIG_TEGRA_GADGET_BOOST_CPU_FREQ
+       if (req->req.complete && req->req.length >= BOOST_TRIGGER_SIZE) {
+               ep_queue_request_count--;
+               if (!ep_queue_request_count)
+                       schedule_work(&udc->boost_cpufreq_work);
+       }
+#endif
        spin_unlock(&ep->udc->lock);
        /* complete() is from gadget layer,
         * eg fsg->bulk_in_complete() */
@@ -1019,7 +1032,13 @@ fsl_ep_queue(struct usb_ep *_ep, struct usb_request *_req, gfp_t gfp_flags)
                        return -EMSGSIZE;
                }
        }
-
+#ifdef CONFIG_TEGRA_GADGET_BOOST_CPU_FREQ
+       if (req->req.length >= BOOST_TRIGGER_SIZE) {
+               ep_queue_request_count++;
+               if (ep_queue_request_count && boost_cpufreq_work_flag)
+                       schedule_work(&udc->boost_cpufreq_work);
+       }
+#endif
        dir = ep_is_in(ep) ? DMA_TO_DEVICE : DMA_FROM_DEVICE;
 
        spin_unlock_irqrestore(&udc->lock, flags);
@@ -2255,6 +2274,19 @@ static void fsl_udc_set_current_limit_work(struct work_struct* work)
        }
 }
 
+#ifdef CONFIG_TEGRA_GADGET_BOOST_CPU_FREQ
+static void fsl_udc_boost_cpu_frequency_work(struct work_struct* work)
+{
+       if (ep_queue_request_count && boost_cpufreq_work_flag) {
+               pm_qos_update_request(&boost_cpu_freq_req, (s32)CONFIG_TEGRA_GADGET_BOOST_CPU_FREQ * 1000);
+               boost_cpufreq_work_flag = 0;
+       } else if (!ep_queue_request_count && !boost_cpufreq_work_flag) {
+               pm_qos_update_request(&boost_cpu_freq_req, PM_QOS_DEFAULT_VALUE);
+               boost_cpufreq_work_flag = 1;
+       }
+}
+#endif
+
 /*
  * If VBUS is detected and setup packet is not received in 100ms then
  * work thread starts and checks for the USB charger detection.
@@ -3065,10 +3097,17 @@ static int __init fsl_udc_probe(struct platform_device *pdev)
                goto err_del_udc;
 
        create_proc_file();
-
+#ifdef CONFIG_TEGRA_GADGET_BOOST_CPU_FREQ
+       boost_cpufreq_work_flag = 1;
+       ep_queue_request_count = 0;
+#endif
        /* create a delayed work for detecting the USB charger */
        INIT_DELAYED_WORK(&udc_controller->work, fsl_udc_charger_detect_work);
        INIT_WORK(&udc_controller->charger_work, fsl_udc_set_current_limit_work);
+#ifdef CONFIG_TEGRA_GADGET_BOOST_CPU_FREQ
+       INIT_WORK(&udc_controller->boost_cpufreq_work, fsl_udc_boost_cpu_frequency_work);
+       pm_qos_add_request(&boost_cpu_freq_req, PM_QOS_CPU_FREQ_MIN, PM_QOS_DEFAULT_VALUE);
+#endif
 
        /* Get the regulator for drawing the vbus current in udc driver */
        udc_controller->vbus_regulator = regulator_get(NULL, "usb_bat_chg");
@@ -3136,6 +3175,9 @@ static int __exit fsl_udc_remove(struct platform_device *pdev)
        udc_controller->done = &done;
 
        cancel_delayed_work(&udc_controller->work);
+#ifdef CONFIG_TEGRA_GADGET_BOOST_CPU_FREQ
+       cancel_work_sync(&udc_controller->boost_cpufreq_work);
+#endif
        if (udc_controller->vbus_regulator)
                regulator_put(udc_controller->vbus_regulator);
 
index 922092f..60055e7 100644 (file)
@@ -641,6 +641,7 @@ struct fsl_udc {
        struct regulator *vbus_regulator;       /* regulator for drawing VBUS */
        u32 current_limit;
        struct work_struct charger_work; /* work for settting regulator current limit */
+       struct work_struct boost_cpufreq_work; /* work for boosting cpu frequency */
 };
 
 /*-------------------------------------------------------------------------*/