提交 9623b5b9 编写于 作者: D Doug Anderson 提交者: Chris Ball

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: NDoug Anderson <dianders@chromium.org>
Acked-by: NSeungwon Jeon <tgih.jun@samsung.com>
Signed-off-by: NChris Ball <cjb@laptop.org>
上级 e74f3a9c
...@@ -627,6 +627,7 @@ static void dw_mci_setup_bus(struct dw_mci_slot *slot) ...@@ -627,6 +627,7 @@ static void dw_mci_setup_bus(struct dw_mci_slot *slot)
{ {
struct dw_mci *host = slot->host; struct dw_mci *host = slot->host;
u32 div; u32 div;
u32 clk_en_a;
if (slot->clock != host->current_speed) { if (slot->clock != host->current_speed) {
div = host->bus_hz / slot->clock; div = host->bus_hz / slot->clock;
...@@ -659,9 +660,11 @@ static void dw_mci_setup_bus(struct dw_mci_slot *slot) ...@@ -659,9 +660,11 @@ static void dw_mci_setup_bus(struct dw_mci_slot *slot)
mci_send_cmd(slot, mci_send_cmd(slot,
SDMMC_CMD_UPD_CLK | SDMMC_CMD_PRV_DAT_WAIT, 0); SDMMC_CMD_UPD_CLK | SDMMC_CMD_PRV_DAT_WAIT, 0);
/* enable clock */ /* enable clock; only low power if no SDIO */
mci_writel(host, CLKENA, ((SDMMC_CLKEN_ENABLE | clk_en_a = SDMMC_CLKEN_ENABLE << slot->id;
SDMMC_CLKEN_LOW_PWR) << slot->id)); if (!(mci_readl(host, INTMASK) & SDMMC_INT_SDIO(slot->id)))
clk_en_a |= SDMMC_CLKEN_LOW_PWR << slot->id;
mci_writel(host, CLKENA, clk_en_a);
/* inform CIU */ /* inform CIU */
mci_send_cmd(slot, mci_send_cmd(slot,
...@@ -862,6 +865,30 @@ static int dw_mci_get_cd(struct mmc_host *mmc) ...@@ -862,6 +865,30 @@ static int dw_mci_get_cd(struct mmc_host *mmc)
return present; return present;
} }
/*
* Disable lower power mode.
*
* Low power mode will stop the card clock when idle. According to the
* description of the CLKENA register we should disable low power mode
* for SDIO cards if we need SDIO interrupts to work.
*
* This function is fast if low power mode is already disabled.
*/
static void dw_mci_disable_low_power(struct dw_mci_slot *slot)
{
struct dw_mci *host = slot->host;
u32 clk_en_a;
const u32 clken_low_pwr = SDMMC_CLKEN_LOW_PWR << slot->id;
clk_en_a = mci_readl(host, CLKENA);
if (clk_en_a & clken_low_pwr) {
mci_writel(host, CLKENA, clk_en_a & ~clken_low_pwr);
mci_send_cmd(slot, SDMMC_CMD_UPD_CLK |
SDMMC_CMD_PRV_DAT_WAIT, 0);
}
}
static void dw_mci_enable_sdio_irq(struct mmc_host *mmc, int enb) static void dw_mci_enable_sdio_irq(struct mmc_host *mmc, int enb)
{ {
struct dw_mci_slot *slot = mmc_priv(mmc); 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) ...@@ -871,6 +898,14 @@ static void dw_mci_enable_sdio_irq(struct mmc_host *mmc, int enb)
/* Enable/disable Slot Specific SDIO interrupt */ /* Enable/disable Slot Specific SDIO interrupt */
int_mask = mci_readl(host, INTMASK); int_mask = mci_readl(host, INTMASK);
if (enb) { if (enb) {
/*
* Turn off low power mode if it was enabled. This is a bit of
* a heavy operation and we disable / enable IRQs a lot, so
* we'll leave low power mode disabled and it will get
* re-enabled again in dw_mci_setup_bus().
*/
dw_mci_disable_low_power(slot);
mci_writel(host, INTMASK, mci_writel(host, INTMASK,
(int_mask | SDMMC_INT_SDIO(slot->id))); (int_mask | SDMMC_INT_SDIO(slot->id)));
} else { } else {
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册