mmc: msm_sdcc: vote against IDLE power collapse
During the SDCC DMA transfer, if DMA transfer time is
long enough to do IDLE power collapse then system may
go into IDLE power collapse and once SDCC DMA transfer
is completed, system wakes up from Idle Power Collapse
due to SDCC DMA interrupt. But delay for waking up
from Idle Power collapse could be as large as 5 ms which
really degrades the overall read & write throughputs
for SD/eMMC/SDIO cards.
For example, following are the performance numbers with
eMMC card on MSM8960 platform with and without Idle Power
Collapse.
Idle Power collapse enabled:
LMDD Read throughput = ~14 MB/s
LMDD Write throughput = ~6 MB/s
Idle Power Collapse disabled:
LMDD Read throughput = ~25 MB/s
LMDD Write throughput = ~8 MB/s
So this change votes against the Idle power collapse by registering
with PM QOS about it's acceptable DMA latency when SDCC transfer is
active. This latency value is one more than the latency of SWFI
which means system can go into SWFI but not in any of the other
low power modes (including Idle power collapse).
CRs-fixed: 327751
Change-Id: Iae5e12cade383544243f17c448346dd5d0faa60e
Signed-off-by: Subhash Jadavani <subhashj@codeaurora.org>
diff --git a/arch/arm/include/asm/mach/mmc.h b/arch/arm/include/asm/mach/mmc.h
index 75ec143..3dfb62f 100644
--- a/arch/arm/include/asm/mach/mmc.h
+++ b/arch/arm/include/asm/mach/mmc.h
@@ -152,6 +152,7 @@
bool disable_bam;
bool disable_runtime_pm;
bool disable_cmd23;
+ u32 swfi_latency;
};
#endif
diff --git a/arch/arm/mach-msm/board-8960-storage.c b/arch/arm/mach-msm/board-8960-storage.c
index 4e4d26ef..b03da38 100644
--- a/arch/arm/mach-msm/board-8960-storage.c
+++ b/arch/arm/mach-msm/board-8960-storage.c
@@ -227,7 +227,7 @@
.pclk_src_dfab = 1,
.nonremovable = 1,
.vreg_data = &mmc_slot_vreg_data[SDCC1],
- .pin_data = &mmc_slot_pin_data[SDCC1]
+ .pin_data = &mmc_slot_pin_data[SDCC1],
};
#endif
@@ -259,10 +259,12 @@
void __init msm8960_init_mmc(void)
{
#ifdef CONFIG_MMC_MSM_SDC1_SUPPORT
+ msm8960_sdc1_data.swfi_latency = msm_rpm_get_swfi_latency();
/* SDC1 : eMMC card connected */
msm_add_sdcc(1, &msm8960_sdc1_data);
#endif
#ifdef CONFIG_MMC_MSM_SDC3_SUPPORT
+ msm8960_sdc3_data.swfi_latency = msm_rpm_get_swfi_latency();
/* SDC3: External card slot */
msm_add_sdcc(3, &msm8960_sdc3_data);
#endif
diff --git a/arch/arm/mach-msm/board-8960.c b/arch/arm/mach-msm/board-8960.c
index a3380c6..d628eeb 100644
--- a/arch/arm/mach-msm/board-8960.c
+++ b/arch/arm/mach-msm/board-8960.c
@@ -2018,7 +2018,7 @@
},
};
-static struct msm_rpmrs_level msm_rpmrs_levels[] __initdata = {
+static struct msm_rpmrs_level msm_rpmrs_levels[] = {
{
MSM_PM_SLEEP_MODE_WAIT_FOR_INTERRUPT,
MSM_RPMRS_LIMITS(ON, ACTIVE, MAX, ACTIVE),
@@ -2113,6 +2113,19 @@
.mode = MSM_PM_BOOT_CONFIG_TZ,
};
+uint32_t msm_rpm_get_swfi_latency(void)
+{
+ int i;
+
+ for (i = 0; i < ARRAY_SIZE(msm_rpmrs_levels); i++) {
+ if (msm_rpmrs_levels[i].sleep_mode ==
+ MSM_PM_SLEEP_MODE_WAIT_FOR_INTERRUPT)
+ return msm_rpmrs_levels[i].latency_us;
+ }
+
+ return 0;
+}
+
#ifdef CONFIG_I2C
#define I2C_SURF 1
#define I2C_FFA (1 << 1)
diff --git a/arch/arm/mach-msm/board-8960.h b/arch/arm/mach-msm/board-8960.h
index 5f4f3a0..20af7b8 100644
--- a/arch/arm/mach-msm/board-8960.h
+++ b/arch/arm/mach-msm/board-8960.h
@@ -81,6 +81,7 @@
void msm8960_allocate_fb_region(void);
void msm8960_pm8921_gpio_mpp_init(void);
void msm8960_mdp_writeback(struct memtype_reserve *reserve_table);
+uint32_t msm_rpm_get_swfi_latency(void);
#define PLATFORM_IS_CHARM25() \
(machine_is_msm8960_cdp() && \
(socinfo_get_platform_subtype() == 1) \