summaryrefslogtreecommitdiff
path: root/drivers
diff options
context:
space:
mode:
authorAlok Chauhan <alokc@nvidia.com>2012-03-07 13:48:41 +0530
committerRohan Somvanshi <rsomvanshi@nvidia.com>2012-04-05 09:01:52 -0700
commite11a9f34dcdfb33c578ecffc6e21d857b5b773b6 (patch)
treea3fb670e050dde304b7a7b2fec3f08125926cf22 /drivers
parentd4e9b6e5ef68b51610dbe2d7ccfde25f296373b5 (diff)
usb: gadget: fsl_udc: boost cpu rate for transaction
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>
Diffstat (limited to 'drivers')
-rw-r--r--drivers/usb/gadget/fsl_udc_core.c48
-rw-r--r--drivers/usb/gadget/fsl_usb2_udc.h1
2 files changed, 46 insertions, 3 deletions
diff --git a/drivers/usb/gadget/fsl_udc_core.c b/drivers/usb/gadget/fsl_udc_core.c
index 7dfbc5e95c96..c90e2d01f02c 100644
--- a/drivers/usb/gadget/fsl_udc_core.c
+++ b/drivers/usb/gadget/fsl_udc_core.c
@@ -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);
diff --git a/drivers/usb/gadget/fsl_usb2_udc.h b/drivers/usb/gadget/fsl_usb2_udc.h
index 922092f1afdd..60055e77bf9a 100644
--- a/drivers/usb/gadget/fsl_usb2_udc.h
+++ b/drivers/usb/gadget/fsl_usb2_udc.h
@@ -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 */
};
/*-------------------------------------------------------------------------*/