diff options
author | Alok Chauhan <alokc@nvidia.com> | 2012-03-07 13:48:41 +0530 |
---|---|---|
committer | Rohan Somvanshi <rsomvanshi@nvidia.com> | 2012-04-05 09:01:52 -0700 |
commit | e11a9f34dcdfb33c578ecffc6e21d857b5b773b6 (patch) | |
tree | a3fb670e050dde304b7a7b2fec3f08125926cf22 /drivers/usb/gadget | |
parent | d4e9b6e5ef68b51610dbe2d7ccfde25f296373b5 (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/usb/gadget')
-rw-r--r-- | drivers/usb/gadget/fsl_udc_core.c | 48 | ||||
-rw-r--r-- | drivers/usb/gadget/fsl_usb2_udc.h | 1 |
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 */ }; /*-------------------------------------------------------------------------*/ |