[PORT FROM R2] EM/BCU: Fix Sysburst behaviour in driver's suspend/resume path
authorDurgadoss R <durgadoss.r@intel.com>
Tue, 3 Jan 2012 16:31:00 +0000 (22:01 +0530)
committerbuildbot <buildbot@intel.com>
Tue, 3 Jan 2012 20:05:09 +0000 (12:05 -0800)
BZ: 18257

The intel_mid_ocd driver disables only the SYSACTEN bit during suspend.
But the SYSOUTEN signal can still be triggered by GSMPULSE (due to
hardware logic design). This patch corrects this behaviour by disabling
both the SYSACTEN and SYSOUTEN bits during suspend and programs these
bits according to battery_level during resume.

Change-Id: I6706fad725bddb299b36b61168c86cb82ce20deb
Signed-off-by: Durgadoss R <durgadoss.r@intel.com>
Reviewed-on: http://android.intel.com:8080/30339
Reviewed-by: Lebouc, Christophe <christophe.lebouc@intel.com>
Reviewed-by: Chotard, Celine <celine.chotard@intel.com>
Tested-by: Chotard, Celine <celine.chotard@intel.com>
Reviewed-by: buildbot <buildbot@intel.com>
Tested-by: buildbot <buildbot@intel.com>
drivers/hwmon/intel_mid_ocd.c

index 46d76ab..48759ca 100644 (file)
@@ -235,7 +235,7 @@ ipc_fail:
        return ret;
 }
 
-static int enable_sysburst(int on)
+static int disable_sysburst(void)
 {
        int ret;
        uint8_t out_data, act_data;
@@ -250,22 +250,60 @@ static int enable_sysburst(int on)
        if (ret)
                goto ipc_fail;
 
+       ret = intel_scu_ipc_iowrite8(BRSTCONFIGACTIONS, act_data & (~SYSACTEN));
+       if (ret)
+               goto ipc_fail;
+
+       ret = intel_scu_ipc_iowrite8(BRSTCONFIGOUTPUTS, out_data & (~SYSOUTEN));
+
+ipc_fail:
+       mutex_unlock(&ocd_update_lock);
+       return ret;
+}
+
+static int restore_sysburst(struct device *dev)
+{
+       int ret;
+       uint8_t out_data, act_data;
+       struct ocd_smip_data *smip_data;
+       struct ocd_info *cinfo = dev_get_drvdata(dev);
+
+       if (!cinfo) {
+               dev_err(dev, "cinfo is NULL in restore_sysburst\n");
+               return -ENODEV;
+       }
+
+       /* Alright, we can avoid this pointer. But keep it for readability. */
+       smip_data = &ocd_smip_data[cinfo->curr_batt_level];
+
        /*
-        * Zero disables the SYSBURST Action/Interrupt and one enables it.
-        * SYSOUTEN is automatically disabled by disabling SYSACTEN.
-        * So, there is no need to disable SYSOUTEN seperately.
+        * For the current battery level, if SYSACT and SYSOUT are not
+        * enabled in the SMIP settings, then just return. Not an Error.
         */
-       if (on) {
-               ret = intel_scu_ipc_iowrite8(BRSTCONFIGACTIONS,
-                                               act_data | SYSACTEN);
-               if (ret)
-                       goto ipc_fail;
-               ret = intel_scu_ipc_iowrite8(BRSTCONFIGOUTPUTS,
-                                               out_data | SYSOUTEN);
-       } else {
-               ret = intel_scu_ipc_iowrite8(BRSTCONFIGACTIONS,
-                                               act_data & (~SYSACTEN));
-       }
+       if (!((smip_data->bcu_actions & SYSACTEN) &&
+               (smip_data->bcu_outputs & SYSOUTEN)))
+               return 0;
+
+       /*
+        * SMIP settings for the current battery level enable _both_
+        * SYSACT and SYSOUT. But, we disabled these during suspend.
+        * Now, enable both of them.
+        */
+       mutex_lock(&ocd_update_lock);
+
+       ret = intel_scu_ipc_ioread8(BRSTCONFIGACTIONS, &act_data);
+       if (ret)
+               goto ipc_fail;
+
+       ret = intel_scu_ipc_ioread8(BRSTCONFIGOUTPUTS, &out_data);
+       if (ret)
+               goto ipc_fail;
+
+       ret = intel_scu_ipc_iowrite8(BRSTCONFIGACTIONS, act_data | SYSACTEN);
+       if (ret)
+               goto ipc_fail;
+
+       ret = intel_scu_ipc_iowrite8(BRSTCONFIGOUTPUTS, out_data | SYSOUTEN);
 
 ipc_fail:
        mutex_unlock(&ocd_update_lock);
@@ -802,12 +840,13 @@ ocd_error1:
 
 static int mid_ocd_resume(struct device *dev)
 {
-       return enable_sysburst(1);
+       return restore_sysburst(dev);
 }
 
 static int mid_ocd_suspend(struct device *dev)
 {
-       return enable_sysburst(0);
+    /* Disable the sysburst interrupt when we suspend */
+       return disable_sysburst();
 }
 
 static int mid_ocd_remove(struct platform_device *pdev)