mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git
synced 2024-08-24 17:59:32 +00:00
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:
parent
aaaaeb7a93
commit
935a665e15
2 changed files with 32 additions and 0 deletions
|
@ -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,
|
||||
|
|
|
@ -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 */
|
||||
|
|
Loading…
Reference in a new issue