Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 935a665e authored by Shawn Lin's avatar Shawn Lin Committed by Ulf Hansson
Browse files

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: default avatarShawn Lin <shawn.lin@rock-chips.com>
Signed-off-by: default avatarJaehoon Chung <jh80.chung@samsung.com>
Signed-off-by: default avatarUlf Hansson <ulf.hansson@linaro.org>
parent aaaaeb7a
Loading
Loading
Loading
Loading
+29 −0
Original line number Original line Diff line number Diff line
@@ -1474,6 +1474,34 @@ static int dw_mci_get_cd(struct mmc_host *mmc)
	return present;
	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)
static void dw_mci_init_card(struct mmc_host *mmc, struct mmc_card *card)
{
{
	struct dw_mci_slot *slot = mmc_priv(mmc);
	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,
	.set_ios		= dw_mci_set_ios,
	.get_ro			= dw_mci_get_ro,
	.get_ro			= dw_mci_get_ro,
	.get_cd			= dw_mci_get_cd,
	.get_cd			= dw_mci_get_cd,
	.hw_reset               = dw_mci_hw_reset,
	.enable_sdio_irq	= dw_mci_enable_sdio_irq,
	.enable_sdio_irq	= dw_mci_enable_sdio_irq,
	.execute_tuning		= dw_mci_execute_tuning,
	.execute_tuning		= dw_mci_execute_tuning,
	.card_busy		= dw_mci_card_busy,
	.card_busy		= dw_mci_card_busy,
+3 −0
Original line number Original line Diff line number Diff line
@@ -46,6 +46,7 @@
#define SDMMC_VERID		0x06c
#define SDMMC_VERID		0x06c
#define SDMMC_HCON		0x070
#define SDMMC_HCON		0x070
#define SDMMC_UHS_REG		0x074
#define SDMMC_UHS_REG		0x074
#define SDMMC_RST_N		0x078
#define SDMMC_BMOD		0x080
#define SDMMC_BMOD		0x080
#define SDMMC_PLDMND		0x084
#define SDMMC_PLDMND		0x084
#define SDMMC_DBADDR		0x088
#define SDMMC_DBADDR		0x088
@@ -169,6 +170,8 @@
#define SDMMC_IDMAC_ENABLE		BIT(7)
#define SDMMC_IDMAC_ENABLE		BIT(7)
#define SDMMC_IDMAC_FB			BIT(1)
#define SDMMC_IDMAC_FB			BIT(1)
#define SDMMC_IDMAC_SWRESET		BIT(0)
#define SDMMC_IDMAC_SWRESET		BIT(0)
/* H/W reset */
#define SDMMC_RST_HWACTIVE		0x1
/* Version ID register define */
/* Version ID register define */
#define SDMMC_GET_VERID(x)		((x) & 0xFFFF)
#define SDMMC_GET_VERID(x)		((x) & 0xFFFF)
/* Card read threshold */
/* Card read threshold */