msm: 8960: usb: Add msm_bus vote when cable is connected
Drivers need to specify their bandwidth requirements to
bus-scaling driver to get guaranteed bandwidth on fabrics.
USB hardware uses a single buffer to transfer data across the
bus. As a result USB performance is highly dependent on system
fabric frequency as USB controller continuously sends NAKs on
the USB BUS unless complete buffer is filled/drained to the memory.
Hence, request for high bus bandwidth as long as USB cable is
connected to improve USB throughput.
While testing with Class-10 Extreme III SD cards, this patch
seems to improve the IN performance from 15MBps to 24MBps and
OUT performance from 11MBps to 16MBps.
CRs-Fixed: 327557
Change-Id: I21c284c611a09b1b12df9ae7a6f39e0b1bff45ef
Signed-off-by: Manu Gautam <mgautam@codeaurora.org>
diff --git a/drivers/usb/otg/msm_otg.c b/drivers/usb/otg/msm_otg.c
index 00e4fda..6dd65e8 100644
--- a/drivers/usb/otg/msm_otg.c
+++ b/drivers/usb/otg/msm_otg.c
@@ -42,6 +42,7 @@
#include <mach/clk.h>
#include <mach/msm_xo.h>
+#include <mach/msm_bus.h>
#define MSM_USB_BASE (motg->regs)
#define DRIVER_NAME "msm_otg"
@@ -1122,6 +1123,7 @@
static void msm_otg_start_peripheral(struct otg_transceiver *otg, int on)
{
+ int ret;
struct msm_otg *motg = container_of(otg, struct msm_otg, otg);
struct msm_otg_platform_data *pdata = motg->pdata;
@@ -1142,11 +1144,27 @@
* power collapse(pc) while running in peripheral mode.
*/
otg_pm_qos_update_latency(motg, 1);
+ /* Configure BUS performance parameters for MAX bandwidth */
+ if (motg->bus_perf_client) {
+ ret = msm_bus_scale_client_update_request(
+ motg->bus_perf_client, 1);
+ if (ret)
+ dev_err(motg->otg.dev, "%s: Failed to vote for "
+ "bus bandwidth %d\n", __func__, ret);
+ }
usb_gadget_vbus_connect(otg->gadget);
} else {
dev_dbg(otg->dev, "gadget off\n");
usb_gadget_vbus_disconnect(otg->gadget);
otg_pm_qos_update_latency(motg, 0);
+ /* Configure BUS performance parameters to default */
+ if (motg->bus_perf_client) {
+ ret = msm_bus_scale_client_update_request(
+ motg->bus_perf_client, 0);
+ if (ret)
+ dev_err(motg->otg.dev, "%s: Failed to devote "
+ "for bus bw %d\n", __func__, ret);
+ }
if (pdata->setup_gpio)
pdata->setup_gpio(OTG_STATE_UNDEFINED);
}
@@ -2601,6 +2619,14 @@
pm_runtime_set_active(&pdev->dev);
pm_runtime_enable(&pdev->dev);
+ if (motg->pdata->bus_scale_table) {
+ motg->bus_perf_client =
+ msm_bus_scale_register_client(motg->pdata->bus_scale_table);
+ if (!motg->bus_perf_client)
+ dev_err(motg->otg.dev, "%s: Failed to register BUS "
+ "scaling client!!\n", __func__);
+ }
+
return 0;
remove_otg:
@@ -2702,6 +2728,9 @@
if (motg->pdata->swfi_latency)
pm_qos_remove_request(&motg->pm_qos_req_dma);
+ if (motg->bus_perf_client)
+ msm_bus_scale_unregister_client(motg->bus_perf_client);
+
kfree(motg);
return 0;
}