summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorsupriya karanth <supriya.karanth@stericsson.com>2012-01-12 16:56:40 +0530
committerPhilippe Langlais <philippe.langlais@stericsson.com>2012-05-22 11:03:16 +0200
commit7182586f3896bef6679c90e1bcf8a0903c09b06a (patch)
tree05a71c18622c88bdd236ef691a78bd61966bf832
parentd392ee8d592fa53fc12e34ececcf566e9dfd8d85 (diff)
u5500:USB: prevent sleep while usb host audio
While playing audio in usb host mode noise is observed, The system wake up latency from sleep adds an extra overhead when transferring ISO packets in host mode. Prevent CPU from going to idle state when when there is high usb activity in host mode. ST-Ericsson ID: 373230 ST-Ericsson Linux next: NA ST-Ericsson FOSS-OUT ID: Trivial Change-Id: Ie60e21e58cdffce0e83b10ac50b4fbb5890c19cd Signed-off-by: supriya karanth <supriya.karanth@stericsson.com> Reviewed-on: http://gerrit.lud.stericsson.com/gerrit/44999 Reviewed-by: QATOOLS Reviewed-by: Praveena NADAHALLY <praveen.nadahally@stericsson.com> Reviewed-by: QABUILD Reviewed-by: Rabin VINCENT <rabin.vincent@stericsson.com>
-rw-r--r--drivers/usb/otg/ab5500-usb.c58
1 files changed, 58 insertions, 0 deletions
diff --git a/drivers/usb/otg/ab5500-usb.c b/drivers/usb/otg/ab5500-usb.c
index c57234d92be..1d38576a8f4 100644
--- a/drivers/usb/otg/ab5500-usb.c
+++ b/drivers/usb/otg/ab5500-usb.c
@@ -21,6 +21,7 @@
#include <linux/kernel_stat.h>
#include <mach/gpio.h>
#include <mach/reboot_reasons.h>
+#include <linux/pm_qos_params.h>
/* AB5500 USB macros
*/
@@ -46,6 +47,10 @@
#define AB5500_USB_LINK_STATUS_MASK_V2 0xF8
#define USB_PROBE_DELAY 1000 /* 1 seconds */
+#define USB_LIMIT (200) /* If we have more than 200 irqs per second */
+
+static struct pm_qos_request_list usb_pm_qos_latency;
+static bool usb_pm_qos_is_latency_0;
#define PUBLIC_ID_BACKUPRAM1 (U5500_BACKUPRAM1_BASE + 0x0FC0)
#define MAX_USB_SERIAL_NUMBER_LEN 31
@@ -145,6 +150,42 @@ static void ab5500_usb_wd_workaround(struct ab5500_usb *ab)
udelay(AB5500_WATCHDOG_DELAY_US);
}
+static void ab5500_usb_load(struct work_struct *work)
+{
+ int cpu;
+ unsigned int num_irqs = 0;
+ static unsigned int old_num_irqs = UINT_MAX;
+ struct delayed_work *work_usb_workaround = to_delayed_work(work);
+ struct ab5500_usb *ab = container_of(work_usb_workaround,
+ struct ab5500_usb, work_usb_workaround);
+
+ for_each_online_cpu(cpu)
+ num_irqs += kstat_irqs_cpu(IRQ_DB5500_USBOTG, cpu);
+
+ if ((num_irqs > old_num_irqs) &&
+ (num_irqs - old_num_irqs) > USB_LIMIT) {
+
+ if (!usb_pm_qos_is_latency_0) {
+
+ pm_qos_add_request(&usb_pm_qos_latency,
+ PM_QOS_CPU_DMA_LATENCY, 0);
+ usb_pm_qos_is_latency_0 = true;
+ }
+ } else {
+
+ if (usb_pm_qos_is_latency_0) {
+
+ pm_qos_remove_request(&usb_pm_qos_latency);
+ usb_pm_qos_is_latency_0 = false;
+ }
+ }
+ old_num_irqs = num_irqs;
+
+ schedule_delayed_work_on(0,
+ &ab->work_usb_workaround,
+ msecs_to_jiffies(USB_PROBE_DELAY));
+}
+
static void ab5500_usb_phy_enable(struct ab5500_usb *ab, bool sel_host)
{
u8 bit;
@@ -166,6 +207,11 @@ static void ab5500_usb_phy_enable(struct ab5500_usb *ab, bool sel_host)
}
ux500_restore_context();
+ if (sel_host) {
+ schedule_delayed_work_on(0,
+ &ab->work_usb_workaround,
+ msecs_to_jiffies(USB_PROBE_DELAY));
+ }
abx500_mask_and_set_register_interruptible(ab->dev,
AB5500_BANK_USB,
AB5500_USB_PHY_CTRL_REG,
@@ -191,6 +237,15 @@ static void ab5500_usb_phy_disable(struct ab5500_usb *ab, bool sel_host)
clk_disable(ab->sysclk);
regulator_disable(ab->v_ape);
ab->usb_gpio->disable();
+
+ if (sel_host) {
+ if (usb_pm_qos_is_latency_0) {
+
+ pm_qos_remove_request(&usb_pm_qos_latency);
+ usb_pm_qos_is_latency_0 = false;
+ }
+ cancel_delayed_work_sync(&ab->work_usb_workaround);
+ }
}
#define ab5500_usb_peri_phy_en(ab) ab5500_usb_phy_enable(ab, false)
@@ -724,6 +779,9 @@ static int __devinit ab5500_usb_probe(struct platform_device *pdev)
*/
INIT_DELAYED_WORK(&ab->dwork, ab5500_usb_delayed_work);
+ INIT_DELAYED_WORK_DEFERRABLE(&ab->work_usb_workaround,
+ ab5500_usb_load);
+
err = otg_set_transceiver(&ab->otg);
if (err)
dev_err(&pdev->dev, "Can't register transceiver\n");