gpadc: prevent CPU from S0i3 when ADC is active
authorBin Yang <bin.yang@intel.com>
Thu, 6 Oct 2011 15:18:26 +0000 (16:18 +0100)
committermgross <mark.gross@intel.com>
Wed, 9 Nov 2011 21:17:18 +0000 (13:17 -0800)
Under the following scenario:
1. IPC1 request sent to SCU
2. PM_CMD s0ix entry request sent to SCU
3. MWAIT C6 abort (or no attempt at MWAIT C6)
If steps #1 an #2 are sufficiently close (maybe within 200us) there is
a possibility that SCU will handle the PM_CMD first and begin waiting on an
ack_c6 response from the MWAIT that is expected. Since the MWAIT never comes
(or is aborted) SCU will have to eventually time out before being able to move
on and handle the IPC1 request.

Change-Id: I00674d66806d127cef0810fa023eed5dd0fda7c2
Signed-off-by: Bin Yang <bin.yang@intel.com>
[ port to new pm_qos_add_request() interface -Guanqun ]
Signed-off-by: Lu Guanqun <guanqun.lu@intel.com>
drivers/hwmon/intel_mid_gpadc.c

index b1b8f84..888833b 100644 (file)
@@ -32,6 +32,7 @@
 #include <linux/delay.h>
 #include <linux/sched.h>
 #include <linux/platform_device.h>
+#include <linux/pm_qos_params.h>
 #include <asm/intel_scu_ipc.h>
 #include <asm/intel_mid_gpadc.h>
 
@@ -78,6 +79,8 @@
 
 #define GPADC_CH_MAX           15
 
+#define PM_QOS_ADC_DRV_VALUE   4999
+
 struct gpadc_info {
        int initialized;
        /* This mutex protects gpadc sample/config from concurrent conflict.
@@ -103,6 +106,8 @@ struct gpadc_info {
        int rnd_done;
        int conv_done;
        int gsmpulse_done;
+
+       struct pm_qos_request_list pm_qos_request;
 };
 
 struct gpadc_request {
@@ -282,6 +287,8 @@ int intel_mid_gpadc_gsmpulse_sample(int *vol, int *cur)
                return -ENODEV;
 
        mutex_lock(&mgi->lock);
+       pm_qos_add_request(&mgi->pm_qos_request,
+                          PM_QOS_CPU_DMA_LATENCY, PM_QOS_ADC_DRV_VALUE);
        gpadc_write(ADC1CNTL2, ADC1CNTL2_DEF);
        gpadc_set_bits(ADC1CNTL2, ADC1CNTL2_ADCGSMEN);
 
@@ -317,6 +324,7 @@ int intel_mid_gpadc_gsmpulse_sample(int *vol, int *cur)
        gpadc_clear_bits(ADC1CNTL3, ADC1CNTL3_GSMDATARD);
 fail:
        gpadc_clear_bits(ADC1CNTL2, ADC1CNTL2_ADCGSMEN);
+       pm_qos_remove_request(&mgi->pm_qos_request);
        mutex_unlock(&mgi->lock);
 
        return ret;
@@ -357,6 +365,8 @@ int intel_mid_gpadc_sample(void *handle, int sample_count, ...)
        va_end(args);
 
        mutex_lock(&mgi->lock);
+       pm_qos_add_request(&mgi->pm_qos_request,
+                          PM_QOS_CPU_DMA_LATENCY, PM_QOS_ADC_DRV_VALUE);
        gpadc_poweron(mgi, rq->vref);
        gpadc_clear_bits(ADC1CNTL1, ADC1CNTL1_AD1OFFSETEN);
        gpadc_read(ADC1CNTL1, &data);
@@ -394,6 +404,7 @@ int intel_mid_gpadc_sample(void *handle, int sample_count, ...)
 fail:
        gpadc_clear_bits(ADC1CNTL1, ADC1CNTL1_ADSTRT);
        gpadc_poweroff(mgi);
+       pm_qos_remove_request(&mgi->pm_qos_request);
        mutex_unlock(&mgi->lock);
        return ret;
 }