From bf3772b12539b3595e60b8b334051160269f9071 Mon Sep 17 00:00:00 2001 From: Christophe Priouzeau Date: Mon, 26 Nov 2018 14:45:33 +0100 Subject: [PATCH 28/52] ARM-stm32mp1-r0-rc2-MMC --- drivers/mmc/host/mmci.c | 36 +++++++++++++++++++++++++----------- drivers/mmc/host/mmci.h | 13 +++++++++++-- 2 files changed, 36 insertions(+), 13 deletions(-) diff --git a/drivers/mmc/host/mmci.c b/drivers/mmc/host/mmci.c index db50d1e..02b631f 100644 --- a/drivers/mmc/host/mmci.c +++ b/drivers/mmc/host/mmci.c @@ -135,7 +135,6 @@ static struct variant_data variant_u300 = { .datactrl_blocksz = 11, .datactrl_dpsm_enable = MCI_DPSM_ENABLE, .datactrl_mask_sdio = MCI_DPSM_ST_SDIOEN, - .st_sdio = true, .pwrreg_powerup = MCI_PWR_ON, .f_max = 100000000, .signal_direction = true, @@ -146,6 +145,7 @@ static struct variant_data variant_u300 = { .start_err = MCI_STARTBITERR, .opendrain = MCI_OD, .init = mmci_variant_init, + .quirks = MMCI_QUIRK_ST_SDIO, }; static struct variant_data variant_nomadik = { @@ -161,7 +161,6 @@ static struct variant_data variant_nomadik = { .datactrl_blocksz = 11, .datactrl_dpsm_enable = MCI_DPSM_ENABLE, .datactrl_mask_sdio = MCI_DPSM_ST_SDIOEN, - .st_sdio = true, .st_clkdiv = true, .pwrreg_powerup = MCI_PWR_ON, .f_max = 100000000, @@ -173,6 +172,7 @@ static struct variant_data variant_nomadik = { .start_err = MCI_STARTBITERR, .opendrain = MCI_OD, .init = mmci_variant_init, + .quirks = MMCI_QUIRK_ST_SDIO, }; static struct variant_data variant_ux500 = { @@ -190,7 +190,6 @@ static struct variant_data variant_ux500 = { .datactrl_blocksz = 11, .datactrl_dpsm_enable = MCI_DPSM_ENABLE, .datactrl_mask_sdio = MCI_DPSM_ST_SDIOEN, - .st_sdio = true, .st_clkdiv = true, .pwrreg_powerup = MCI_PWR_ON, .f_max = 100000000, @@ -206,6 +205,7 @@ static struct variant_data variant_ux500 = { .start_err = MCI_STARTBITERR, .opendrain = MCI_OD, .init = mmci_variant_init, + .quirks = MMCI_QUIRK_ST_SDIO, }; static struct variant_data variant_ux500v2 = { @@ -224,7 +224,6 @@ static struct variant_data variant_ux500v2 = { .datactrl_blocksz = 11, .datactrl_dpsm_enable = MCI_DPSM_ENABLE, .datactrl_mask_sdio = MCI_DPSM_ST_SDIOEN, - .st_sdio = true, .st_clkdiv = true, .blksz_datactrl16 = true, .pwrreg_powerup = MCI_PWR_ON, @@ -241,6 +240,7 @@ static struct variant_data variant_ux500v2 = { .start_err = MCI_STARTBITERR, .opendrain = MCI_OD, .init = mmci_variant_init, + .quirks = MMCI_QUIRK_ST_SDIO, }; static struct variant_data variant_stm32 = { @@ -259,13 +259,13 @@ static struct variant_data variant_stm32 = { .datactrl_blocksz = 11, .datactrl_dpsm_enable = MCI_DPSM_ENABLE, .datactrl_mask_sdio = MCI_DPSM_ST_SDIOEN, - .st_sdio = true, .st_clkdiv = true, .pwrreg_powerup = MCI_PWR_ON, .f_max = 48000000, .pwrreg_clkgate = true, .pwrreg_nopower = true, .init = mmci_variant_init, + .quirks = MMCI_QUIRK_ST_SDIO, }; static struct variant_data variant_stm32_sdmmc = { @@ -284,12 +284,14 @@ static struct variant_data variant_stm32_sdmmc = { .datacnt_useless = true, .datalength_bits = 25, .datactrl_blocksz = 14, + .datactrl_mask_sdio = MCI_DPSM_STM32_SDIOEN, .stm32_idmabsize_mask = GENMASK(12, 5), .busy_detect = true, .busy_timeout = true, .busy_detect_flag = MCI_STM32_BUSYD0, .busy_detect_mask = MCI_STM32_BUSYD0ENDMASK, .init = sdmmc_variant_init, + .quirks = MMCI_QUIRK_STM32_DTMODE, }; static struct variant_data variant_stm32_sdmmcv2 = { @@ -308,6 +310,7 @@ static struct variant_data variant_stm32_sdmmcv2 = { .datacnt_useless = true, .datalength_bits = 25, .datactrl_blocksz = 14, + .datactrl_mask_sdio = MCI_DPSM_STM32_SDIOEN, .stm32_idmabsize_mask = GENMASK(16, 5), .dma_lli = true, .busy_detect = true, @@ -315,6 +318,7 @@ static struct variant_data variant_stm32_sdmmcv2 = { .busy_detect_flag = MCI_STM32_BUSYD0, .busy_detect_mask = MCI_STM32_BUSYD0ENDMASK, .init = sdmmc_variant_init, + .quirks = MMCI_QUIRK_STM32_DTMODE, }; static struct variant_data variant_qcom = { @@ -505,7 +509,8 @@ static int mmci_validate_data(struct mmci_host *host, if (!data) return 0; - if (!is_power_of_2(data->blksz)) { + if ((host->mmc->card && !mmc_card_sdio(host->mmc->card)) && + !is_power_of_2(data->blksz)) { dev_err(mmc_dev(host->mmc), "unsupported block size (%d bytes)\n", data->blksz); return -EINVAL; @@ -1068,7 +1073,6 @@ static void mmci_start_data(struct mmci_host *host, struct mmc_data *data) writel(host->size, base + MMCIDATALENGTH); blksz_bits = ffs(data->blksz) - 1; - BUG_ON(1 << blksz_bits != data->blksz); if (variant->blksz_datactrl16) datactrl = variant->datactrl_dpsm_enable | (data->blksz << 16); @@ -1077,6 +1081,16 @@ static void mmci_start_data(struct mmci_host *host, struct mmc_data *data) else datactrl = variant->datactrl_dpsm_enable | blksz_bits << 4; + if (variant->quirks & MMCI_QUIRK_STM32_DTMODE) { + if (host->mmc->card && mmc_card_sdio(host->mmc->card) && + data->blocks == 1) + datactrl |= MCI_DPSM_STM32_MODE_SDIO; + else if (data->stop && !host->mrq->sbc) + datactrl |= MCI_DPSM_STM32_MODE_BLOCK_STOP; + else + datactrl |= MCI_DPSM_STM32_MODE_BLOCK; + } + if (data->flags & MMC_DATA_READ) datactrl |= MCI_DPSM_DIRECTION; @@ -1091,7 +1105,8 @@ static void mmci_start_data(struct mmci_host *host, struct mmc_data *data) * otherwise the transfer will not start. The threshold * depends on the rate of MCLK. */ - if (variant->st_sdio && data->flags & MMC_DATA_WRITE && + if (variant->quirks & MMCI_QUIRK_ST_SDIO && + data->flags & MMC_DATA_WRITE && (host->size < 8 || (host->size <= 8 && host->mclk > 50000000))) clk = host->clk_reg & ~variant->clkreg_enable; @@ -1257,11 +1272,10 @@ mmci_data_irq(struct mmci_host *host, struct mmc_data *data, /* The error clause is handled above, success! */ data->bytes_xfered = data->blksz * data->blocks; - if (!data->stop || host->mrq->sbc) { + if (!data->stop || (host->mrq->sbc && !data->error)) mmci_request_end(host, data->mrq); - } else { + else mmci_start_command(host, data->stop, 0); - } } } diff --git a/drivers/mmc/host/mmci.h b/drivers/mmc/host/mmci.h index 36a744a..55867fc 100644 --- a/drivers/mmc/host/mmci.h +++ b/drivers/mmc/host/mmci.h @@ -131,6 +131,12 @@ /* Control register extensions in the Qualcomm versions */ #define MCI_DPSM_QCOM_DATA_PEND BIT(17) #define MCI_DPSM_QCOM_RX_DATA_PEND BIT(20) +/* Control register extensions in STM32 versions */ +#define MCI_DPSM_STM32_MODE_BLOCK (0 << 2) +#define MCI_DPSM_STM32_MODE_SDIO (1 << 2) +#define MCI_DPSM_STM32_MODE_STREAM (2 << 2) +#define MCI_DPSM_STM32_MODE_BLOCK_STOP (3 << 2) +#define MCI_DPSM_STM32_SDIOEN BIT(11) #define MMCIDATACNT 0x030 #define MMCISTATUS 0x034 @@ -273,7 +279,6 @@ struct mmci_host; * @fifohalfsize: number of bytes that can be written when MCI_TXFIFOHALFEMPTY * is asserted (likewise for RX) * @data_cmd_enable: enable value for data commands. - * @st_sdio: enable ST specific SDIO logic * @st_clkdiv: true if using a ST-specific clock divider algorithm * @stm32_clkdiv: true if using a STM32-specific clock divider algorithm * @datactrl_mask_ddrmode: ddr mode mask in datactrl register. @@ -309,6 +314,7 @@ struct mmci_host; * @opendrain: bitmask identifying the OPENDRAIN bit inside MMCIPOWER register * @dma_lli: true if variant has dma link list feature. * @stm32_idmabsize_mask: stm32 sdmmc idma buffer size. + * @quirks: A bitmap of hardware quirks that require some special action. */ struct variant_data { unsigned int clkreg; @@ -330,7 +336,6 @@ struct variant_data { unsigned int datactrl_dpsm_enable; u8 datactrl_first:1; u8 datacnt_useless:1; - u8 st_sdio:1; u8 st_clkdiv:1; u8 stm32_clkdiv:1; u8 blksz_datactrl16:1; @@ -355,9 +360,13 @@ struct variant_data { u32 opendrain; u8 dma_lli:1; u32 stm32_idmabsize_mask; + u32 quirks; void (*init)(struct mmci_host *host); }; +#define MMCI_QUIRK_STM32_DTMODE BIT(0) +#define MMCI_QUIRK_ST_SDIO BIT(2) /* enable ST specific SDIO logic */ + /* mmci variant callbacks */ struct mmci_host_ops { int (*validate_data)(struct mmci_host *host, struct mmc_data *data); -- 2.7.4