From aaaaeb7a933471f6413ca44dd36efd57f2fa9429 Mon Sep 17 00:00:00 2001 From: Jaehoon Chung Date: Thu, 21 Jan 2016 11:01:06 +0900 Subject: mmc: dw_mmc: remove the prepare_command hook This patch removes the prepare_command hook from entire dw_mmc driver. Now, almost all SoCs are using by default, except Exynos. It seems that dwmmc controller is using unnecessary hook. To know whether needs to set this bit or not, add the DW_MMC_CARD_NO_USE_HOLD bit. If some SoCs need to disable this in future, just set the DW_MMC_CARD_NO_USE_HOLD bit. set_bit(DW_MMC_CARD_NO_USE_HOLD, &slot->flags), Signed-off-by: Jaehoon Chung Tested-by: Shawn Lin Reviewed-by: Shawn Lin Signed-off-by: Ulf Hansson --- drivers/mmc/host/dw_mmc.h | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'drivers/mmc/host/dw_mmc.h') diff --git a/drivers/mmc/host/dw_mmc.h b/drivers/mmc/host/dw_mmc.h index f695b58f0613..6fc84b61dc8c 100644 --- a/drivers/mmc/host/dw_mmc.h +++ b/drivers/mmc/host/dw_mmc.h @@ -265,6 +265,7 @@ struct dw_mci_slot { #define DW_MMC_CARD_PRESENT 0 #define DW_MMC_CARD_NEED_INIT 1 #define DW_MMC_CARD_NO_LOW_PWR 2 +#define DW_MMC_CARD_NO_USE_HOLD 3 int id; int sdio_id; }; @@ -274,7 +275,6 @@ struct dw_mci_slot { * @caps: mmc subsystem specified capabilities of the controller(s). * @init: early implementation specific initialization. * @setup_clock: implementation specific clock configuration. - * @prepare_command: handle CMD register extensions. * @set_ios: handle bus specific extensions. * @parse_dt: parse implementation specific device tree properties. * @execute_tuning: implementation specific tuning procedure. @@ -287,7 +287,6 @@ struct dw_mci_drv_data { unsigned long *caps; int (*init)(struct dw_mci *host); int (*setup_clock)(struct dw_mci *host); - void (*prepare_command)(struct dw_mci *host, u32 *cmdr); void (*set_ios)(struct dw_mci *host, struct mmc_ios *ios); int (*parse_dt)(struct dw_mci *host); int (*execute_tuning)(struct dw_mci_slot *slot, u32 opcode); -- cgit v1.2.3-59-g8ed1b From 935a665e15dcda3b0b986829f32e2724db1f20fc Mon Sep 17 00:00:00 2001 From: Shawn Lin Date: Thu, 14 Jan 2016 09:08:02 +0800 Subject: mmc: dw_mmc: add hw_reset support MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 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 Signed-off-by: Jaehoon Chung Signed-off-by: Ulf Hansson --- drivers/mmc/host/dw_mmc.c | 29 +++++++++++++++++++++++++++++ drivers/mmc/host/dw_mmc.h | 3 +++ 2 files changed, 32 insertions(+) (limited to 'drivers/mmc/host/dw_mmc.h') diff --git a/drivers/mmc/host/dw_mmc.c b/drivers/mmc/host/dw_mmc.c index 7d6bd9d32b48..6ad9ebf1faef 100644 --- a/drivers/mmc/host/dw_mmc.c +++ b/drivers/mmc/host/dw_mmc.c @@ -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, diff --git a/drivers/mmc/host/dw_mmc.h b/drivers/mmc/host/dw_mmc.h index 6fc84b61dc8c..68d5da2dfd19 100644 --- a/drivers/mmc/host/dw_mmc.h +++ b/drivers/mmc/host/dw_mmc.h @@ -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 */ -- cgit v1.2.3-59-g8ed1b