From 8466fa3282c3c9788799e11e9110e3459697fdec Mon Sep 17 00:00:00 2001 From: Illyas Mansoor Date: Mon, 2 Jan 2012 20:49:51 +0530 Subject: [PATCH] [PORT FROM R2]mid_pmu: provide api to set lss01 to d0i0 in atomic context BZ: 9458 During panic we disable pre-emption but we require eMMC0 ie., LSS01 to be in D0i0 in order to store panic logs, but pmu_pci_set_power_state might_sleep hence we cannot use it for this purpose. Hence we provide a exclusive api for LSS01 to be put in D0i0. Change-Id: Ib55a9f8b61da735e76524e84d9ecd9b2a6a6493b Signed-off-by: Illyas Mansoor Reviewed-on: http://android.intel.com:8080/30285 Tested-by: Martin, LoicX Reviewed-by: buildbot Tested-by: buildbot --- arch/x86/platform/mfld/pmu.c | 72 ++++++++++++++++++++++++++++++++++++++++++++ include/linux/intel_mid_pm.h | 4 +++ 2 files changed, 76 insertions(+) diff --git a/arch/x86/platform/mfld/pmu.c b/arch/x86/platform/mfld/pmu.c index f0239a5..46d90a3 100755 --- a/arch/x86/platform/mfld/pmu.c +++ b/arch/x86/platform/mfld/pmu.c @@ -1626,6 +1626,78 @@ unlock: EXPORT_SYMBOL(pmu_nc_set_power_state); /** + * pmu_set_lss01_to_d0i0_atomic - + * This function is mainly meant for panic case to bring up storage + * device so panic reports can be logged, this is NOT meant for + * general purpose use!. + * + */ +int pmu_set_lss01_to_d0i0_atomic(void) +{ + u32 pm_cmd_val; + u32 new_value; + int sub_sys_pos, sub_sys_index; + struct pmu_ss_states cur_pmssc; + int status = 0; + + if (unlikely((!pmu_initialized))) + return 0; + + /* LSS 01 is index = 0, pos = 1 */ + sub_sys_index = PMU_EMMC0_LSS_01 / mid_pmu_cxt->ss_per_reg; + sub_sys_pos = PMU_EMMC0_LSS_01 % mid_pmu_cxt->ss_per_reg; + + memset(&cur_pmssc, 0, sizeof(cur_pmssc)); + + status = _pmu2_wait_not_busy(); + + if (status) + goto err; + + pmu_read_sss(&cur_pmssc); + + /* set D0i0 the LSS bits */ + pm_cmd_val = + (D0I3_MASK << (sub_sys_pos * BITS_PER_LSS)); + new_value = cur_pmssc.pmu2_states[sub_sys_index] & + (~pm_cmd_val); + + if (new_value == cur_pmssc.pmu2_states[sub_sys_index]) + goto err; + + cur_pmssc.pmu2_states[sub_sys_index] = new_value; + + /* set the lss positions that need + * to be ignored to D0i0 */ + cur_pmssc.pmu2_states[0] &= ~IGNORE_SSS0; + cur_pmssc.pmu2_states[1] &= ~IGNORE_SSS1; + cur_pmssc.pmu2_states[2] &= ~IGNORE_SSS2; + cur_pmssc.pmu2_states[3] &= ~IGNORE_SSS3; + + status = _pmu_issue_command(&cur_pmssc, SET_MODE, 0, PMU_NUM_2); + + if (unlikely(status != PMU_SUCCESS)) { + dev_dbg(&mid_pmu_cxt->pmu_dev->dev, + "Failed to Issue a PM command to PMU2\n"); + goto err; + } + + /* + * Wait for interactive command to complete. + * If we dont wait, there is a possibility that + * the driver may access the device before its + * powered on in SCU. + * + */ + if (_pmu2_wait_not_busy()) + BUG(); + +err: + return status; +} +EXPORT_SYMBOL(pmu_set_lss01_to_d0i0_atomic); + +/** * pmu_pci_set_power_state - Callback function is used by all the PCI devices * for a platform specific device power on/shutdown. * diff --git a/include/linux/intel_mid_pm.h b/include/linux/intel_mid_pm.h index ce5663d..3235dd2 100644 --- a/include/linux/intel_mid_pm.h +++ b/include/linux/intel_mid_pm.h @@ -115,6 +115,8 @@ extern void release_scu_ready_sem(void); extern int mfld_msg_read32(u32 cmd, u32 *data); extern int mfld_msg_write32(u32 cmd, u32 data); +extern int pmu_set_lss01_to_d0i0_atomic(void); + #else /* @@ -149,6 +151,8 @@ static inline int mfld_msg_write32(u32 cmd, u32 data) { return -ENOSYS; } static inline void acquire_scu_ready_sem(void) { return; }; static inline void release_scu_ready_sem(void) { return; }; +static inline int pmu_set_lss01_to_d0i0_atomic(void) { return -ENOSYS; } + #endif /* #ifdef CONFIG_INTEL_MID_POWER */ -- 2.7.4