Skip to content

Commit 61840ed

Browse files
committed
mmc: dw_mmc: Drop use of ->init_card() callback
For dw_mmc, the ->init_card() callback is being used to turn on/off automatic internal clock gating for powersave, which is needed to properly support SDIO irqs on DAT1. However, using the ->init_card() comes with a drawback in this case, as it means that the powersave feature becomes disabled, no matter whether the SDIO irqs becomes turned on or not. To improve the behaviour, let's change into using the ->enable_sdio_irq() callback instead. This works fine, because dw_mmc uses sdio_signal_irq() to signal the irqs, thus the ->enable_sdio_irq() is never executed from within atomic context. Signed-off-by: Ulf Hansson <[email protected]> Reviewed-by: Douglas Anderson <[email protected]> Link: https://lore.kernel.org/r/[email protected] Signed-off-by: Ulf Hansson <[email protected]>
1 parent f85a15c commit 61840ed

File tree

1 file changed

+17
-22
lines changed

1 file changed

+17
-22
lines changed

drivers/mmc/host/dw_mmc.c

Lines changed: 17 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -1611,37 +1611,32 @@ static void dw_mci_hw_reset(struct mmc_host *mmc)
16111611
usleep_range(200, 300);
16121612
}
16131613

1614-
static void dw_mci_init_card(struct mmc_host *mmc, struct mmc_card *card)
1614+
static void dw_mci_prepare_sdio_irq(struct dw_mci_slot *slot, bool prepare)
16151615
{
1616-
struct dw_mci_slot *slot = mmc_priv(mmc);
16171616
struct dw_mci *host = slot->host;
1617+
const u32 clken_low_pwr = SDMMC_CLKEN_LOW_PWR << slot->id;
1618+
u32 clk_en_a_old;
1619+
u32 clk_en_a;
16181620

16191621
/*
16201622
* Low power mode will stop the card clock when idle. According to the
16211623
* description of the CLKENA register we should disable low power mode
16221624
* for SDIO cards if we need SDIO interrupts to work.
16231625
*/
1624-
if (mmc->caps & MMC_CAP_SDIO_IRQ) {
1625-
const u32 clken_low_pwr = SDMMC_CLKEN_LOW_PWR << slot->id;
1626-
u32 clk_en_a_old;
1627-
u32 clk_en_a;
16281626

1629-
clk_en_a_old = mci_readl(host, CLKENA);
1630-
1631-
if (card->type == MMC_TYPE_SDIO ||
1632-
card->type == MMC_TYPE_SD_COMBO) {
1633-
set_bit(DW_MMC_CARD_NO_LOW_PWR, &slot->flags);
1634-
clk_en_a = clk_en_a_old & ~clken_low_pwr;
1635-
} else {
1636-
clear_bit(DW_MMC_CARD_NO_LOW_PWR, &slot->flags);
1637-
clk_en_a = clk_en_a_old | clken_low_pwr;
1638-
}
1627+
clk_en_a_old = mci_readl(host, CLKENA);
1628+
if (prepare) {
1629+
set_bit(DW_MMC_CARD_NO_LOW_PWR, &slot->flags);
1630+
clk_en_a = clk_en_a_old & ~clken_low_pwr;
1631+
} else {
1632+
clear_bit(DW_MMC_CARD_NO_LOW_PWR, &slot->flags);
1633+
clk_en_a = clk_en_a_old | clken_low_pwr;
1634+
}
16391635

1640-
if (clk_en_a != clk_en_a_old) {
1641-
mci_writel(host, CLKENA, clk_en_a);
1642-
mci_send_cmd(slot, SDMMC_CMD_UPD_CLK |
1643-
SDMMC_CMD_PRV_DAT_WAIT, 0);
1644-
}
1636+
if (clk_en_a != clk_en_a_old) {
1637+
mci_writel(host, CLKENA, clk_en_a);
1638+
mci_send_cmd(slot, SDMMC_CMD_UPD_CLK | SDMMC_CMD_PRV_DAT_WAIT,
1639+
0);
16451640
}
16461641
}
16471642

@@ -1669,6 +1664,7 @@ static void dw_mci_enable_sdio_irq(struct mmc_host *mmc, int enb)
16691664
struct dw_mci_slot *slot = mmc_priv(mmc);
16701665
struct dw_mci *host = slot->host;
16711666

1667+
dw_mci_prepare_sdio_irq(slot, enb);
16721668
__dw_mci_enable_sdio_irq(slot, enb);
16731669

16741670
/* Avoid runtime suspending the device when SDIO IRQ is enabled */
@@ -1790,7 +1786,6 @@ static const struct mmc_host_ops dw_mci_ops = {
17901786
.execute_tuning = dw_mci_execute_tuning,
17911787
.card_busy = dw_mci_card_busy,
17921788
.start_signal_voltage_switch = dw_mci_switch_voltage,
1793-
.init_card = dw_mci_init_card,
17941789
.prepare_hs400_tuning = dw_mci_prepare_hs400_tuning,
17951790
};
17961791

0 commit comments

Comments
 (0)