Skip to content

Commit 9623b5b

Browse files
dianderscjb
authored andcommitted
mmc: dw_mmc: Disable low power mode if SDIO interrupts are used
The documentation for the dw_mmc part says that the low power mode should normally only be set for MMC and SD memory and should be turned off for SDIO cards that need interrupts detected. The best place I could find to do this is when the SDIO interrupt was first enabled. I rely on the fact that dw_mci_setup_bus() will be called when it's time to reenable. Signed-off-by: Doug Anderson <dianders@chromium.org> Acked-by: Seungwon Jeon <tgih.jun@samsung.com> Signed-off-by: Chris Ball <cjb@laptop.org>
1 parent e74f3a9 commit 9623b5b

File tree

1 file changed

+38
-3
lines changed

1 file changed

+38
-3
lines changed

drivers/mmc/host/dw_mmc.c

Lines changed: 38 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -627,6 +627,7 @@ static void dw_mci_setup_bus(struct dw_mci_slot *slot)
627627
{
628628
struct dw_mci *host = slot->host;
629629
u32 div;
630+
u32 clk_en_a;
630631

631632
if (slot->clock != host->current_speed) {
632633
div = host->bus_hz / slot->clock;
@@ -659,9 +660,11 @@ static void dw_mci_setup_bus(struct dw_mci_slot *slot)
659660
mci_send_cmd(slot,
660661
SDMMC_CMD_UPD_CLK | SDMMC_CMD_PRV_DAT_WAIT, 0);
661662

662-
/* enable clock */
663-
mci_writel(host, CLKENA, ((SDMMC_CLKEN_ENABLE |
664-
SDMMC_CLKEN_LOW_PWR) << slot->id));
663+
/* enable clock; only low power if no SDIO */
664+
clk_en_a = SDMMC_CLKEN_ENABLE << slot->id;
665+
if (!(mci_readl(host, INTMASK) & SDMMC_INT_SDIO(slot->id)))
666+
clk_en_a |= SDMMC_CLKEN_LOW_PWR << slot->id;
667+
mci_writel(host, CLKENA, clk_en_a);
665668

666669
/* inform CIU */
667670
mci_send_cmd(slot,
@@ -862,6 +865,30 @@ static int dw_mci_get_cd(struct mmc_host *mmc)
862865
return present;
863866
}
864867

868+
/*
869+
* Disable lower power mode.
870+
*
871+
* Low power mode will stop the card clock when idle. According to the
872+
* description of the CLKENA register we should disable low power mode
873+
* for SDIO cards if we need SDIO interrupts to work.
874+
*
875+
* This function is fast if low power mode is already disabled.
876+
*/
877+
static void dw_mci_disable_low_power(struct dw_mci_slot *slot)
878+
{
879+
struct dw_mci *host = slot->host;
880+
u32 clk_en_a;
881+
const u32 clken_low_pwr = SDMMC_CLKEN_LOW_PWR << slot->id;
882+
883+
clk_en_a = mci_readl(host, CLKENA);
884+
885+
if (clk_en_a & clken_low_pwr) {
886+
mci_writel(host, CLKENA, clk_en_a & ~clken_low_pwr);
887+
mci_send_cmd(slot, SDMMC_CMD_UPD_CLK |
888+
SDMMC_CMD_PRV_DAT_WAIT, 0);
889+
}
890+
}
891+
865892
static void dw_mci_enable_sdio_irq(struct mmc_host *mmc, int enb)
866893
{
867894
struct dw_mci_slot *slot = mmc_priv(mmc);
@@ -871,6 +898,14 @@ static void dw_mci_enable_sdio_irq(struct mmc_host *mmc, int enb)
871898
/* Enable/disable Slot Specific SDIO interrupt */
872899
int_mask = mci_readl(host, INTMASK);
873900
if (enb) {
901+
/*
902+
* Turn off low power mode if it was enabled. This is a bit of
903+
* a heavy operation and we disable / enable IRQs a lot, so
904+
* we'll leave low power mode disabled and it will get
905+
* re-enabled again in dw_mci_setup_bus().
906+
*/
907+
dw_mci_disable_low_power(slot);
908+
874909
mci_writel(host, INTMASK,
875910
(int_mask | SDMMC_INT_SDIO(slot->id)));
876911
} else {

0 commit comments

Comments
 (0)