mmc: dw_mmc: add hw_reset support

This patch implement hw_reset function for DesignWare
MMC controller. By adding this feature, mmc blk can
do some basic recovery.

Set the following resets:
software reset – BMOD[0] for IDMAC only
DMA reset - CTRL[2]
FIFO reset - CTRL[1] bits

Program the CARD_RESET register with a value of 0 for the bit
corresponding to the card number; This programming asserts the
RST_n signal and resets the card. After a minimum of 1 ?s, de-asserts the
RST_n signal and takes the card out of reset. The application can program
a new CMD only after a minimum of 200 us

This implementation can be easily tested by cutting off->On vmmc
while doing data accessing in background to simulate that case.

Signed-off-by: Shawn Lin <shawn.lin@rock-chips.com>
Signed-off-by: Jaehoon Chung <jh80.chung@samsung.com>
Signed-off-by: Ulf Hansson <ulf.hansson@linaro.org>
This commit is contained in:
Shawn Lin 2016-01-14 09:08:02 +08:00 committed by Ulf Hansson
parent aaaaeb7a93
commit 935a665e15
2 changed files with 32 additions and 0 deletions

View file

@ -1474,6 +1474,34 @@ static int dw_mci_get_cd(struct mmc_host *mmc)
return present;
}
static void dw_mci_hw_reset(struct mmc_host *mmc)
{
struct dw_mci_slot *slot = mmc_priv(mmc);
struct dw_mci *host = slot->host;
int reset;
if (host->use_dma == TRANS_MODE_IDMAC)
dw_mci_idmac_reset(host);
if (!dw_mci_ctrl_reset(host, SDMMC_CTRL_DMA_RESET |
SDMMC_CTRL_FIFO_RESET))
return;
/*
* According to eMMC spec, card reset procedure:
* tRstW >= 1us: RST_n pulse width
* tRSCA >= 200us: RST_n to Command time
* tRSTH >= 1us: RST_n high period
*/
reset = mci_readl(host, RST_N);
reset &= ~(SDMMC_RST_HWACTIVE << slot->id);
mci_writel(host, RST_N, reset);
usleep_range(1, 2);
reset |= SDMMC_RST_HWACTIVE << slot->id;
mci_writel(host, RST_N, reset);
usleep_range(200, 300);
}
static void dw_mci_init_card(struct mmc_host *mmc, struct mmc_card *card)
{
struct dw_mci_slot *slot = mmc_priv(mmc);
@ -1560,6 +1588,7 @@ static const struct mmc_host_ops dw_mci_ops = {
.set_ios = dw_mci_set_ios,
.get_ro = dw_mci_get_ro,
.get_cd = dw_mci_get_cd,
.hw_reset = dw_mci_hw_reset,
.enable_sdio_irq = dw_mci_enable_sdio_irq,
.execute_tuning = dw_mci_execute_tuning,
.card_busy = dw_mci_card_busy,

View file

@ -46,6 +46,7 @@
#define SDMMC_VERID 0x06c
#define SDMMC_HCON 0x070
#define SDMMC_UHS_REG 0x074
#define SDMMC_RST_N 0x078
#define SDMMC_BMOD 0x080
#define SDMMC_PLDMND 0x084
#define SDMMC_DBADDR 0x088
@ -169,6 +170,8 @@
#define SDMMC_IDMAC_ENABLE BIT(7)
#define SDMMC_IDMAC_FB BIT(1)
#define SDMMC_IDMAC_SWRESET BIT(0)
/* H/W reset */
#define SDMMC_RST_HWACTIVE 0x1
/* Version ID register define */
#define SDMMC_GET_VERID(x) ((x) & 0xFFFF)
/* Card read threshold */