From fe62fd3b8b7cf0fb9915ec33eb4794624c38303a Mon Sep 17 00:00:00 2001 From: David Lechner Date: Wed, 21 Jan 2026 16:36:24 -0600 Subject: mmc: mtk-sd: use GENMASK and FIELD macros Replace separate mask and shift definitions with GENMASK and FIELD_* macros for better readability and maintainability. All macros ending in _M have the suffix dropped. The value remains the same but is now generated with GENMASK. All macros ending in _S are removed and their uses replaced with FIELD_PREP and FIELD_GET macros. Signed-off-by: David Lechner Reviewed-by: Macpaul Lin Signed-off-by: Peng Fan --- drivers/mmc/mtk-sd.c | 357 ++++++++++++++++++++++----------------------------- 1 file changed, 151 insertions(+), 206 deletions(-) diff --git a/drivers/mmc/mtk-sd.c b/drivers/mmc/mtk-sd.c index 2bc700b0d05..69f54a342c6 100644 --- a/drivers/mmc/mtk-sd.c +++ b/drivers/mmc/mtk-sd.c @@ -16,6 +16,7 @@ #include #include #include +#include #include #include #include @@ -23,15 +24,11 @@ /* MSDC_CFG */ #define MSDC_CFG_HS400_CK_MODE_EXT BIT(22) -#define MSDC_CFG_CKMOD_EXT_M 0x300000 -#define MSDC_CFG_CKMOD_EXT_S 20 -#define MSDC_CFG_CKDIV_EXT_M 0xfff00 -#define MSDC_CFG_CKDIV_EXT_S 8 +#define MSDC_CFG_CKMOD_EXT GENMASK(21, 20) +#define MSDC_CFG_CKDIV_EXT GENMASK(19, 8) #define MSDC_CFG_HS400_CK_MODE BIT(18) -#define MSDC_CFG_CKMOD_M 0x30000 -#define MSDC_CFG_CKMOD_S 16 -#define MSDC_CFG_CKDIV_M 0xff00 -#define MSDC_CFG_CKDIV_S 8 +#define MSDC_CFG_CKMOD GENMASK(17, 16) +#define MSDC_CFG_CKDIV GENMASK(15, 8) #define MSDC_CFG_CKSTB BIT(7) #define MSDC_CFG_PIO BIT(3) #define MSDC_CFG_RST BIT(2) @@ -45,8 +42,7 @@ /* MSDC_PS */ #define MSDC_PS_DAT0 BIT(16) -#define MSDC_PS_CDDBCE_M 0xf000 -#define MSDC_PS_CDDBCE_S 12 +#define MSDC_PS_CDDBCE GENMASK(15, 12) #define MSDC_PS_CDSTS BIT(1) #define MSDC_PS_CDEN BIT(0) @@ -63,30 +59,22 @@ /* MSDC_FIFOCS */ #define MSDC_FIFOCS_CLR BIT(31) -#define MSDC_FIFOCS_TXCNT_M 0xff0000 -#define MSDC_FIFOCS_TXCNT_S 16 -#define MSDC_FIFOCS_RXCNT_M 0xff -#define MSDC_FIFOCS_RXCNT_S 0 +#define MSDC_FIFOCS_TXCNT GENMASK(23, 16) +#define MSDC_FIFOCS_RXCNT GENMASK(7, 0) /* #define SDC_CFG */ -#define SDC_CFG_DTOC_M 0xff000000 -#define SDC_CFG_DTOC_S 24 +#define SDC_CFG_DTOC GENMASK(31, 24) #define SDC_CFG_SDIOIDE BIT(20) #define SDC_CFG_SDIO BIT(19) -#define SDC_CFG_BUSWIDTH_M 0x30000 -#define SDC_CFG_BUSWIDTH_S 16 +#define SDC_CFG_BUSWIDTH GENMASK(17, 16) /* SDC_CMD */ -#define SDC_CMD_BLK_LEN_M 0xfff0000 -#define SDC_CMD_BLK_LEN_S 16 +#define SDC_CMD_BLK_LEN GENMASK(27, 16) #define SDC_CMD_STOP BIT(14) #define SDC_CMD_WR BIT(13) -#define SDC_CMD_DTYPE_M 0x1800 -#define SDC_CMD_DTYPE_S 11 -#define SDC_CMD_RSPTYP_M 0x380 -#define SDC_CMD_RSPTYP_S 7 -#define SDC_CMD_CMD_M 0x3f -#define SDC_CMD_CMD_S 0 +#define SDC_CMD_DTYPE GENMASK(12, 11) +#define SDC_CMD_RSPTYP GENMASK(9, 7) +#define SDC_CMD_CMD GENMASK(5, 0) /* SDC_STS */ #define SDC_STS_CMDBUSY BIT(1) @@ -96,102 +84,73 @@ #define SDC_RX_ENHANCE_EN BIT(20) /* PATCH_BIT0 */ -#define MSDC_INT_DAT_LATCH_CK_SEL_M 0x380 -#define MSDC_INT_DAT_LATCH_CK_SEL_S 7 +#define MSDC_INT_DAT_LATCH_CK_SEL GENMASK(9, 7) /* PATCH_BIT1 */ -#define MSDC_PB1_STOP_DLY_M 0xf00 -#define MSDC_PB1_STOP_DLY_S 8 +#define MSDC_PB1_STOP_DLY GENMASK(11, 8) /* PATCH_BIT2 */ -#define MSDC_PB2_CRCSTSENSEL_M 0xe0000000 -#define MSDC_PB2_CRCSTSENSEL_S 29 +#define MSDC_PB2_CRCSTSENSEL GENMASK(31, 29) #define MSDC_PB2_CFGCRCSTS BIT(28) -#define MSDC_PB2_RESPSTSENSEL_M 0x70000 -#define MSDC_PB2_RESPSTSENSEL_S 16 +#define MSDC_PB2_RESPSTSENSEL GENMASK(18, 16) #define MSDC_PB2_CFGRESP BIT(15) -#define MSDC_PB2_RESPWAIT_M 0x0c -#define MSDC_PB2_RESPWAIT_S 2 +#define MSDC_PB2_RESPWAIT GENMASK(3, 2) /* MSDC_PAD_CTRL0 */ -#define MSDC_PAD_CTRL0_CLKRDSEL_M 0xff000000 -#define MSDC_PAD_CTRL0_CLKRDSEL_S 24 +#define MSDC_PAD_CTRL0_CLKRDSEL GENMASK(31, 24) #define MSDC_PAD_CTRL0_CLKTDSEL BIT(20) #define MSDC_PAD_CTRL0_CLKIES BIT(19) #define MSDC_PAD_CTRL0_CLKSMT BIT(18) #define MSDC_PAD_CTRL0_CLKPU BIT(17) #define MSDC_PAD_CTRL0_CLKPD BIT(16) #define MSDC_PAD_CTRL0_CLKSR BIT(8) -#define MSDC_PAD_CTRL0_CLKDRVP_M 0x70 -#define MSDC_PAD_CTRL0_CLKDRVP_S 4 -#define MSDC_PAD_CTRL0_CLKDRVN_M 0x7 -#define MSDC_PAD_CTRL0_CLKDRVN_S 0 +#define MSDC_PAD_CTRL0_CLKDRVP GENMASK(6, 4) +#define MSDC_PAD_CTRL0_CLKDRVN GENMASK(2, 0) /* MSDC_PAD_CTRL1 */ -#define MSDC_PAD_CTRL1_CMDRDSEL_M 0xff000000 -#define MSDC_PAD_CTRL1_CMDRDSEL_S 24 +#define MSDC_PAD_CTRL1_CMDRDSEL GENMASK(31, 24) #define MSDC_PAD_CTRL1_CMDTDSEL BIT(20) #define MSDC_PAD_CTRL1_CMDIES BIT(19) #define MSDC_PAD_CTRL1_CMDSMT BIT(18) #define MSDC_PAD_CTRL1_CMDPU BIT(17) #define MSDC_PAD_CTRL1_CMDPD BIT(16) #define MSDC_PAD_CTRL1_CMDSR BIT(8) -#define MSDC_PAD_CTRL1_CMDDRVP_M 0x70 -#define MSDC_PAD_CTRL1_CMDDRVP_S 4 -#define MSDC_PAD_CTRL1_CMDDRVN_M 0x7 -#define MSDC_PAD_CTRL1_CMDDRVN_S 0 - +#define MSDC_PAD_CTRL1_CMDDRVP GENMASK(6, 4) +#define MSDC_PAD_CTRL1_CMDDRVN GENMASK(2, 0) /* MSDC_PAD_CTRL2 */ -#define MSDC_PAD_CTRL2_DATRDSEL_M 0xff000000 -#define MSDC_PAD_CTRL2_DATRDSEL_S 24 +#define MSDC_PAD_CTRL2_DATRDSEL GENMASK(31, 24) #define MSDC_PAD_CTRL2_DATTDSEL BIT(20) #define MSDC_PAD_CTRL2_DATIES BIT(19) #define MSDC_PAD_CTRL2_DATSMT BIT(18) #define MSDC_PAD_CTRL2_DATPU BIT(17) #define MSDC_PAD_CTRL2_DATPD BIT(16) #define MSDC_PAD_CTRL2_DATSR BIT(8) -#define MSDC_PAD_CTRL2_DATDRVP_M 0x70 -#define MSDC_PAD_CTRL2_DATDRVP_S 4 -#define MSDC_PAD_CTRL2_DATDRVN_M 0x7 -#define MSDC_PAD_CTRL2_DATDRVN_S 0 +#define MSDC_PAD_CTRL2_DATDRVP GENMASK(6, 4) +#define MSDC_PAD_CTRL2_DATDRVN GENMASK(2, 0) /* PAD_TUNE */ -#define MSDC_PAD_TUNE_CLKTDLY_M 0xf8000000 -#define MSDC_PAD_TUNE_CLKTDLY_S 27 -#define MSDC_PAD_TUNE_CMDRRDLY_M 0x7c00000 -#define MSDC_PAD_TUNE_CMDRRDLY_S 22 +#define MSDC_PAD_TUNE_CLKTDLY GENMASK(31, 27) +#define MSDC_PAD_TUNE_CMDRRDLY GENMASK(26, 22) #define MSDC_PAD_TUNE_CMD_SEL BIT(21) -#define MSDC_PAD_TUNE_CMDRDLY_M 0x1f0000 -#define MSDC_PAD_TUNE_CMDRDLY_S 16 +#define MSDC_PAD_TUNE_CMDRDLY GENMASK(20, 16) #define MSDC_PAD_TUNE_RXDLYSEL BIT(15) #define MSDC_PAD_TUNE_RD_SEL BIT(13) -#define MSDC_PAD_TUNE_DATRRDLY_M 0x1f00 -#define MSDC_PAD_TUNE_DATRRDLY_S 8 -#define MSDC_PAD_TUNE_DATWRDLY_M 0x1f -#define MSDC_PAD_TUNE_DATWRDLY_S 0 +#define MSDC_PAD_TUNE_DATRRDLY GENMASK(12, 8) +#define MSDC_PAD_TUNE_DATWRDLY GENMASK(4, 0) -#define PAD_CMD_TUNE_RX_DLY3 0x3E -#define PAD_CMD_TUNE_RX_DLY3_S 1 +#define PAD_CMD_TUNE_RX_DLY3 GENMASK(5, 1) /* PAD_TUNE0 */ -#define MSDC_PAD_TUNE0_DAT0RDDLY_M 0x1f000000 -#define MSDC_PAD_TUNE0_DAT0RDDLY_S 24 -#define MSDC_PAD_TUNE0_DAT1RDDLY_M 0x1f0000 -#define MSDC_PAD_TUNE0_DAT1RDDLY_S 16 -#define MSDC_PAD_TUNE0_DAT2RDDLY_M 0x1f00 -#define MSDC_PAD_TUNE0_DAT2RDDLY_S 8 -#define MSDC_PAD_TUNE0_DAT3RDDLY_M 0x1f -#define MSDC_PAD_TUNE0_DAT3RDDLY_S 0 +#define MSDC_PAD_TUNE0_DAT0RDDLY GENMASK(28, 24) +#define MSDC_PAD_TUNE0_DAT1RDDLY GENMASK(20, 16) +#define MSDC_PAD_TUNE0_DAT2RDDLY GENMASK(12, 8) +#define MSDC_PAD_TUNE0_DAT3RDDLY GENMASK(4, 0) /* PAD_TUNE1 */ -#define MSDC_PAD_TUNE1_DAT4RDDLY_M 0x1f000000 -#define MSDC_PAD_TUNE1_DAT4RDDLY_S 24 -#define MSDC_PAD_TUNE1_DAT5RDDLY_M 0x1f0000 -#define MSDC_PAD_TUNE1_DAT5RDDLY_S 16 -#define MSDC_PAD_TUNE1_DAT6RDDLY_M 0x1f00 -#define MSDC_PAD_TUNE1_DAT6RDDLY_S 8 -#define MSDC_PAD_TUNE1_DAT7RDDLY_M 0x1f -#define MSDC_PAD_TUNE1_DAT7RDDLY_S 0 +#define MSDC_PAD_TUNE1_DAT4RDDLY GENMASK(28, 24) +#define MSDC_PAD_TUNE1_DAT5RDDLY GENMASK(20, 16) +#define MSDC_PAD_TUNE1_DAT6RDDLY GENMASK(12, 8) +#define MSDC_PAD_TUNE1_DAT7RDDLY GENMASK(4, 0) /* EMMC50_CFG0 */ #define EMMC50_CFG_CFCSTS_SEL BIT(4) @@ -203,21 +162,19 @@ /* EMMC_TOP_CONTROL mask */ #define PAD_RXDLY_SEL BIT(0) #define DELAY_EN BIT(1) -#define PAD_DAT_RD_RXDLY2 (0x1f << 2) -#define PAD_DAT_RD_RXDLY (0x1f << 7) -#define PAD_DAT_RD_RXDLY_S 7 +#define PAD_DAT_RD_RXDLY2 GENMASK(6, 2) +#define PAD_DAT_RD_RXDLY GENMASK(11, 7) #define PAD_DAT_RD_RXDLY2_SEL BIT(12) #define PAD_DAT_RD_RXDLY_SEL BIT(13) #define DATA_K_VALUE_SEL BIT(14) #define SDC_RX_ENH_EN BIT(15) /* EMMC_TOP_CMD mask */ -#define PAD_CMD_RXDLY2 (0x1f << 0) -#define PAD_CMD_RXDLY (0x1f << 5) -#define PAD_CMD_RXDLY_S 5 +#define PAD_CMD_RXDLY2 GENMASK(4, 0) +#define PAD_CMD_RXDLY GENMASK(9, 5) #define PAD_CMD_RD_RXDLY2_SEL BIT(10) #define PAD_CMD_RD_RXDLY_SEL BIT(11) -#define PAD_CMD_TX_DLY (0x1f << 12) +#define PAD_CMD_TX_DLY GENMASK(16, 12) /* SDC_CFG_BUSWIDTH */ #define MSDC_BUS_1BITS 0x0 @@ -428,14 +385,12 @@ static void msdc_fifo_clr(struct msdc_host *host) static u32 msdc_fifo_rx_bytes(struct msdc_host *host) { - return (readl(&host->base->msdc_fifocs) & - MSDC_FIFOCS_RXCNT_M) >> MSDC_FIFOCS_RXCNT_S; + return FIELD_GET(MSDC_FIFOCS_RXCNT, readl(&host->base->msdc_fifocs)); } static u32 msdc_fifo_tx_bytes(struct msdc_host *host) { - return (readl(&host->base->msdc_fifocs) & - MSDC_FIFOCS_TXCNT_M) >> MSDC_FIFOCS_TXCNT_S; + return FIELD_GET(MSDC_FIFOCS_TXCNT, readl(&host->base->msdc_fifocs)); } static u32 msdc_cmd_find_resp(struct msdc_host *host, struct mmc_cmd *cmd) @@ -504,10 +459,10 @@ static u32 msdc_cmd_prepare_raw_cmd(struct msdc_host *host, blocksize = data->blocksize; } - rawcmd |= ((opcode << SDC_CMD_CMD_S) & SDC_CMD_CMD_M) | - ((resp_type << SDC_CMD_RSPTYP_S) & SDC_CMD_RSPTYP_M) | - ((blocksize << SDC_CMD_BLK_LEN_S) & SDC_CMD_BLK_LEN_M) | - ((dtype << SDC_CMD_DTYPE_S) & SDC_CMD_DTYPE_M); + rawcmd |= FIELD_PREP(SDC_CMD_CMD, opcode) | + FIELD_PREP(SDC_CMD_RSPTYP, resp_type) | + FIELD_PREP(SDC_CMD_BLK_LEN, blocksize) | + FIELD_PREP(SDC_CMD_DTYPE, dtype); if (opcode == MMC_CMD_STOP_TRANSMISSION) rawcmd |= SDC_CMD_STOP; @@ -590,10 +545,8 @@ static int msdc_start_command(struct msdc_host *host, struct mmc_cmd *cmd, if (!msdc_cmd_is_ready(host)) return -EIO; - if ((readl(&host->base->msdc_fifocs) & - MSDC_FIFOCS_TXCNT_M) >> MSDC_FIFOCS_TXCNT_S || - (readl(&host->base->msdc_fifocs) & - MSDC_FIFOCS_RXCNT_M) >> MSDC_FIFOCS_RXCNT_S) { + if (FIELD_GET(MSDC_FIFOCS_TXCNT, readl(&host->base->msdc_fifocs)) || + FIELD_GET(MSDC_FIFOCS_RXCNT, readl(&host->base->msdc_fifocs))) { pr_err("TX/RX FIFO non-empty before start of IO. Reset\n"); msdc_reset_hw(host); } @@ -814,37 +767,35 @@ static void msdc_set_timeout(struct msdc_host *host, u32 ns, u32 clks) /* unit is 1048576 sclk cycles */ timeout = (timeout + (0x1 << shift) - 1) >> shift; if (host->dev_comp->clk_div_bits == 8) - mode = (readl(&host->base->msdc_cfg) & - MSDC_CFG_CKMOD_M) >> MSDC_CFG_CKMOD_S; + mode = FIELD_GET(MSDC_CFG_CKMOD, readl(&host->base->msdc_cfg)); else - mode = (readl(&host->base->msdc_cfg) & - MSDC_CFG_CKMOD_EXT_M) >> MSDC_CFG_CKMOD_EXT_S; + mode = FIELD_GET(MSDC_CFG_CKMOD_EXT, readl(&host->base->msdc_cfg)); /* DDR mode will double the clk cycles for data timeout */ timeout = mode >= 2 ? timeout * 2 : timeout; timeout = timeout > 1 ? timeout - 1 : 0; timeout = timeout > 255 ? 255 : timeout; } - clrsetbits_le32(&host->base->sdc_cfg, SDC_CFG_DTOC_M, - timeout << SDC_CFG_DTOC_S); + clrsetbits_le32(&host->base->sdc_cfg, SDC_CFG_DTOC, + FIELD_PREP(SDC_CFG_DTOC, timeout)); } static void msdc_set_buswidth(struct msdc_host *host, u32 width) { u32 val = readl(&host->base->sdc_cfg); - val &= ~SDC_CFG_BUSWIDTH_M; + val &= ~SDC_CFG_BUSWIDTH; switch (width) { default: case 1: - val |= (MSDC_BUS_1BITS << SDC_CFG_BUSWIDTH_S); + val |= FIELD_PREP(SDC_CFG_BUSWIDTH, MSDC_BUS_1BITS); break; case 4: - val |= (MSDC_BUS_4BITS << SDC_CFG_BUSWIDTH_S); + val |= FIELD_PREP(SDC_CFG_BUSWIDTH, MSDC_BUS_4BITS); break; case 8: - val |= (MSDC_BUS_8BITS << SDC_CFG_BUSWIDTH_S); + val |= FIELD_PREP(SDC_CFG_BUSWIDTH, MSDC_BUS_8BITS); break; } @@ -918,18 +869,17 @@ static void msdc_set_mclk(struct udevice *dev, clrbits_le32(&host->base->msdc_cfg, MSDC_CFG_CKPDN); if (host->dev_comp->clk_div_bits == 8) { - div = min(div, (u32)(MSDC_CFG_CKDIV_M >> MSDC_CFG_CKDIV_S)); + div = min(div, (u32)FIELD_MAX(MSDC_CFG_CKDIV)); clrsetbits_le32(&host->base->msdc_cfg, - MSDC_CFG_CKMOD_M | MSDC_CFG_CKDIV_M, - (mode << MSDC_CFG_CKMOD_S) | - (div << MSDC_CFG_CKDIV_S)); + MSDC_CFG_CKMOD | MSDC_CFG_CKDIV, + FIELD_PREP(MSDC_CFG_CKMOD, mode) | + FIELD_PREP(MSDC_CFG_CKDIV, div)); } else { - div = min(div, (u32)(MSDC_CFG_CKDIV_EXT_M >> - MSDC_CFG_CKDIV_EXT_S)); + div = min(div, (u32)FIELD_MAX(MSDC_CFG_CKDIV_EXT)); clrsetbits_le32(&host->base->msdc_cfg, - MSDC_CFG_CKMOD_EXT_M | MSDC_CFG_CKDIV_EXT_M, - (mode << MSDC_CFG_CKMOD_EXT_S) | - (div << MSDC_CFG_CKDIV_EXT_S)); + MSDC_CFG_CKMOD_EXT | MSDC_CFG_CKDIV_EXT, + FIELD_PREP(MSDC_CFG_CKMOD_EXT, mode) | + FIELD_PREP(MSDC_CFG_CKDIV_EXT, div)); } readl_poll_timeout(&host->base->msdc_cfg, reg, @@ -1085,10 +1035,10 @@ static inline void msdc_set_cmd_delay(struct msdc_host *host, u32 value) if (host->top_base) clrsetbits_le32(&host->top_base->emmc_top_cmd, PAD_CMD_RXDLY, - value << PAD_CMD_RXDLY_S); + FIELD_PREP(PAD_CMD_RXDLY, value)); else - clrsetbits_le32(tune_reg, MSDC_PAD_TUNE_CMDRDLY_M, - value << MSDC_PAD_TUNE_CMDRDLY_S); + clrsetbits_le32(tune_reg, MSDC_PAD_TUNE_CMDRDLY, + FIELD_PREP(MSDC_PAD_TUNE_CMDRDLY, value)); } static inline void msdc_set_data_delay(struct msdc_host *host, u32 value) @@ -1100,10 +1050,10 @@ static inline void msdc_set_data_delay(struct msdc_host *host, u32 value) if (host->top_base) clrsetbits_le32(&host->top_base->emmc_top_control, - PAD_DAT_RD_RXDLY, value << PAD_DAT_RD_RXDLY_S); + PAD_DAT_RD_RXDLY, FIELD_PREP(PAD_DAT_RD_RXDLY, value)); else - clrsetbits_le32(tune_reg, MSDC_PAD_TUNE_DATRRDLY_M, - value << MSDC_PAD_TUNE_DATRRDLY_S); + clrsetbits_le32(tune_reg, MSDC_PAD_TUNE_DATRRDLY, + FIELD_PREP(MSDC_PAD_TUNE_DATRRDLY, value)); } static int hs400_tune_response(struct udevice *dev, u32 opcode) @@ -1122,9 +1072,9 @@ static int hs400_tune_response(struct udevice *dev, u32 opcode) if (mmc->selected_mode == MMC_HS_200 || mmc->selected_mode == UHS_SDR104) - clrsetbits_le32(tune_reg, MSDC_PAD_TUNE_CMDRRDLY_M, - host->hs200_cmd_int_delay << - MSDC_PAD_TUNE_CMDRRDLY_S); + clrsetbits_le32(tune_reg, MSDC_PAD_TUNE_CMDRRDLY, + FIELD_PREP(MSDC_PAD_TUNE_CMDRRDLY, + host->hs200_cmd_int_delay)); if (host->r_smpl) clrbits_le32(&host->base->msdc_iocon, MSDC_IOCON_RSPL); @@ -1133,7 +1083,7 @@ static int hs400_tune_response(struct udevice *dev, u32 opcode) for (i = 0; i < PAD_DELAY_MAX; i++) { clrsetbits_le32(tune_reg, PAD_CMD_TUNE_RX_DLY3, - i << PAD_CMD_TUNE_RX_DLY3_S); + FIELD_PREP(PAD_CMD_TUNE_RX_DLY3, i)); for (j = 0; j < 3; j++) { cmd_err = mmc_send_tuning(mmc, opcode); @@ -1148,8 +1098,7 @@ static int hs400_tune_response(struct udevice *dev, u32 opcode) final_cmd_delay = get_best_delay(dev, host, cmd_delay); clrsetbits_le32(tune_reg, PAD_CMD_TUNE_RX_DLY3, - final_cmd_delay.final_phase << - PAD_CMD_TUNE_RX_DLY3_S); + FIELD_PREP(PAD_CMD_TUNE_RX_DLY3, final_cmd_delay.final_phase)); final_delay = final_cmd_delay.final_phase; dev_info(dev, "Final cmd pad delay: %x\n", final_delay); @@ -1175,15 +1124,15 @@ static int msdc_tune_response(struct udevice *dev, u32 opcode) if (mmc->selected_mode == MMC_HS_200 || mmc->selected_mode == UHS_SDR104) - clrsetbits_le32(tune_reg, MSDC_PAD_TUNE_CMDRRDLY_M, - host->hs200_cmd_int_delay << - MSDC_PAD_TUNE_CMDRRDLY_S); + clrsetbits_le32(tune_reg, MSDC_PAD_TUNE_CMDRRDLY, + FIELD_PREP(MSDC_PAD_TUNE_CMDRRDLY, + host->hs200_cmd_int_delay)); clrbits_le32(&host->base->msdc_iocon, MSDC_IOCON_RSPL); for (i = 0; i < PAD_DELAY_MAX; i++) { - clrsetbits_le32(tune_reg, MSDC_PAD_TUNE_CMDRDLY_M, - i << MSDC_PAD_TUNE_CMDRDLY_S); + clrsetbits_le32(tune_reg, MSDC_PAD_TUNE_CMDRDLY, + FIELD_PREP(MSDC_PAD_TUNE_CMDRDLY, i)); for (j = 0; j < 3; j++) { cmd_err = mmc_send_tuning(mmc, opcode); @@ -1204,8 +1153,8 @@ static int msdc_tune_response(struct udevice *dev, u32 opcode) setbits_le32(&host->base->msdc_iocon, MSDC_IOCON_RSPL); for (i = 0; i < PAD_DELAY_MAX; i++) { - clrsetbits_le32(tune_reg, MSDC_PAD_TUNE_CMDRDLY_M, - i << MSDC_PAD_TUNE_CMDRDLY_S); + clrsetbits_le32(tune_reg, MSDC_PAD_TUNE_CMDRDLY, + FIELD_PREP(MSDC_PAD_TUNE_CMDRDLY, i)); for (j = 0; j < 3; j++) { cmd_err = mmc_send_tuning(mmc, opcode); @@ -1224,15 +1173,13 @@ skip_fall: final_maxlen = max(final_rise_delay.maxlen, final_fall_delay.maxlen); if (final_maxlen == final_rise_delay.maxlen) { clrbits_le32(&host->base->msdc_iocon, MSDC_IOCON_RSPL); - clrsetbits_le32(tune_reg, MSDC_PAD_TUNE_CMDRDLY_M, - final_rise_delay.final_phase << - MSDC_PAD_TUNE_CMDRDLY_S); + clrsetbits_le32(tune_reg, MSDC_PAD_TUNE_CMDRDLY, + FIELD_PREP(MSDC_PAD_TUNE_CMDRDLY, final_rise_delay.final_phase)); final_delay = final_rise_delay.final_phase; } else { setbits_le32(&host->base->msdc_iocon, MSDC_IOCON_RSPL); - clrsetbits_le32(tune_reg, MSDC_PAD_TUNE_CMDRDLY_M, - final_fall_delay.final_phase << - MSDC_PAD_TUNE_CMDRDLY_S); + clrsetbits_le32(tune_reg, MSDC_PAD_TUNE_CMDRDLY, + FIELD_PREP(MSDC_PAD_TUNE_CMDRDLY, final_fall_delay.final_phase)); final_delay = final_fall_delay.final_phase; } @@ -1240,9 +1187,8 @@ skip_fall: goto skip_internal; for (i = 0; i < PAD_DELAY_MAX; i++) { - clrsetbits_le32(tune_reg, MSDC_PAD_TUNE_CMDRRDLY_M, - i << MSDC_PAD_TUNE_CMDRRDLY_S); - + clrsetbits_le32(tune_reg, MSDC_PAD_TUNE_CMDRRDLY, + FIELD_PREP(MSDC_PAD_TUNE_CMDRRDLY, i)); cmd_err = mmc_send_tuning(mmc, opcode); if (!cmd_err) internal_delay |= (1 << i); @@ -1251,9 +1197,9 @@ skip_fall: dev_dbg(dev, "Final internal delay: 0x%x\n", internal_delay); internal_delay_phase = get_best_delay(dev, host, internal_delay); - clrsetbits_le32(tune_reg, MSDC_PAD_TUNE_CMDRRDLY_M, - internal_delay_phase.final_phase << - MSDC_PAD_TUNE_CMDRRDLY_S); + clrsetbits_le32(tune_reg, MSDC_PAD_TUNE_CMDRRDLY, + FIELD_PREP(MSDC_PAD_TUNE_CMDRRDLY, + internal_delay_phase.final_phase)); skip_internal: dev_dbg(dev, "Final cmd pad delay: %x\n", final_delay); @@ -1278,8 +1224,8 @@ static int msdc_tune_data(struct udevice *dev, u32 opcode) clrbits_le32(&host->base->msdc_iocon, MSDC_IOCON_W_DSPL); for (i = 0; i < PAD_DELAY_MAX; i++) { - clrsetbits_le32(tune_reg, MSDC_PAD_TUNE_DATRRDLY_M, - i << MSDC_PAD_TUNE_DATRRDLY_S); + clrsetbits_le32(tune_reg, MSDC_PAD_TUNE_DATRRDLY, + FIELD_PREP(MSDC_PAD_TUNE_DATRRDLY, i)); ret = mmc_send_tuning(mmc, opcode); if (!ret) { @@ -1301,8 +1247,8 @@ static int msdc_tune_data(struct udevice *dev, u32 opcode) setbits_le32(&host->base->msdc_iocon, MSDC_IOCON_W_DSPL); for (i = 0; i < PAD_DELAY_MAX; i++) { - clrsetbits_le32(tune_reg, MSDC_PAD_TUNE_DATRRDLY_M, - i << MSDC_PAD_TUNE_DATRRDLY_S); + clrsetbits_le32(tune_reg, MSDC_PAD_TUNE_DATRRDLY, + FIELD_PREP(MSDC_PAD_TUNE_DATRRDLY, i)); ret = mmc_send_tuning(mmc, opcode); if (!ret) { @@ -1322,24 +1268,24 @@ skip_fall: if (final_maxlen == final_rise_delay.maxlen) { clrbits_le32(&host->base->msdc_iocon, MSDC_IOCON_DSPL); clrbits_le32(&host->base->msdc_iocon, MSDC_IOCON_W_DSPL); - clrsetbits_le32(tune_reg, MSDC_PAD_TUNE_DATRRDLY_M, - final_rise_delay.final_phase << - MSDC_PAD_TUNE_DATRRDLY_S); + clrsetbits_le32(tune_reg, MSDC_PAD_TUNE_DATRRDLY, + FIELD_PREP(MSDC_PAD_TUNE_DATRRDLY, + final_rise_delay.final_phase)); final_delay = final_rise_delay.final_phase; } else { setbits_le32(&host->base->msdc_iocon, MSDC_IOCON_DSPL); setbits_le32(&host->base->msdc_iocon, MSDC_IOCON_W_DSPL); - clrsetbits_le32(tune_reg, MSDC_PAD_TUNE_DATRRDLY_M, - final_fall_delay.final_phase << - MSDC_PAD_TUNE_DATRRDLY_S); + clrsetbits_le32(tune_reg, MSDC_PAD_TUNE_DATRRDLY, + FIELD_PREP(MSDC_PAD_TUNE_DATRRDLY, + final_fall_delay.final_phase)); final_delay = final_fall_delay.final_phase; } if (mmc->selected_mode == MMC_HS_200 || mmc->selected_mode == UHS_SDR104) - clrsetbits_le32(tune_reg, MSDC_PAD_TUNE_DATWRDLY_M, - host->hs200_write_int_delay << - MSDC_PAD_TUNE_DATWRDLY_S); + clrsetbits_le32(tune_reg, MSDC_PAD_TUNE_DATWRDLY, + FIELD_PREP(MSDC_PAD_TUNE_DATWRDLY, + host->hs200_write_int_delay)); dev_dbg(dev, "Final data pad delay: %x\n", final_delay); @@ -1426,7 +1372,7 @@ static int msdc_execute_tuning(struct udevice *dev, uint opcode) clrbits_le32(&host->base->msdc_iocon, MSDC_IOCON_DSPL | MSDC_IOCON_W_DSPL); clrsetbits_le32(&host->base->pad_tune, - MSDC_PAD_TUNE_DATRRDLY_M, 0); + MSDC_PAD_TUNE_DATRRDLY, 0); writel(host->hs400_ds_delay, &host->base->pad_ds_tune); /* for hs400 mode it must be set to 0 */ @@ -1488,8 +1434,8 @@ static void msdc_init_hw(struct msdc_host *host) /* Enable/disable hw card detection according to fdt option */ if (host->builtin_cd) clrsetbits_le32(&host->base->msdc_ps, - MSDC_PS_CDDBCE_M, - (DEFAULT_CD_DEBOUNCE << MSDC_PS_CDDBCE_S) | + MSDC_PS_CDDBCE, + FIELD_PREP(MSDC_PS_CDDBCE, DEFAULT_CD_DEBOUNCE) | MSDC_PS_CDEN); else clrbits_le32(&host->base->msdc_ps, MSDC_PS_CDEN); @@ -1518,8 +1464,8 @@ static void msdc_init_hw(struct msdc_host *host) writel(0xffff4089, &host->base->patch_bit1); if (host->dev_comp->stop_clk_fix) { - clrsetbits_le32(&host->base->patch_bit1, MSDC_PB1_STOP_DLY_M, - 3 << MSDC_PB1_STOP_DLY_S); + clrsetbits_le32(&host->base->patch_bit1, MSDC_PB1_STOP_DLY, + FIELD_PREP(MSDC_PB1_STOP_DLY, 3)); clrbits_le32(&host->base->sdc_fifo_cfg, SDC_FIFO_CFG_WRVALIDSEL); clrbits_le32(&host->base->sdc_fifo_cfg, @@ -1532,8 +1478,8 @@ static void msdc_init_hw(struct msdc_host *host) setbits_le32(&host->base->emmc50_cfg0, EMMC50_CFG_CFCSTS_SEL); if (host->dev_comp->async_fifo) { - clrsetbits_le32(&host->base->patch_bit2, MSDC_PB2_RESPWAIT_M, - 3 << MSDC_PB2_RESPWAIT_S); + clrsetbits_le32(&host->base->patch_bit2, MSDC_PB2_RESPWAIT, + FIELD_PREP(MSDC_PB2_RESPWAIT, 3)); if (host->dev_comp->enhance_rx) { if (host->top_base) @@ -1544,11 +1490,11 @@ static void msdc_init_hw(struct msdc_host *host) SDC_RX_ENHANCE_EN); } else { clrsetbits_le32(&host->base->patch_bit2, - MSDC_PB2_RESPSTSENSEL_M, - 2 << MSDC_PB2_RESPSTSENSEL_S); + MSDC_PB2_RESPSTSENSEL, + FIELD_PREP(MSDC_PB2_RESPSTSENSEL, 2)); clrsetbits_le32(&host->base->patch_bit2, - MSDC_PB2_CRCSTSENSEL_M, - 2 << MSDC_PB2_CRCSTSENSEL_S); + MSDC_PB2_CRCSTSENSEL, + FIELD_PREP(MSDC_PB2_CRCSTSENSEL, 2)); } /* use async fifo to avoid tune internal delay */ @@ -1574,9 +1520,9 @@ static void msdc_init_hw(struct msdc_host *host) setbits_le32(tune_reg, MSDC_PAD_TUNE_RD_SEL | MSDC_PAD_TUNE_CMD_SEL); clrsetbits_le32(&host->base->patch_bit0, - MSDC_INT_DAT_LATCH_CK_SEL_M, - host->latch_ck << - MSDC_INT_DAT_LATCH_CK_SEL_S); + MSDC_INT_DAT_LATCH_CK_SEL, + FIELD_PREP(MSDC_INT_DAT_LATCH_CK_SEL, + host->latch_ck)); } } else { /* choose clock tune */ @@ -1590,39 +1536,38 @@ static void msdc_init_hw(struct msdc_host *host) if (host->dev_comp->builtin_pad_ctrl) { /* Set pins driving strength */ writel(MSDC_PAD_CTRL0_CLKPD | MSDC_PAD_CTRL0_CLKSMT | - MSDC_PAD_CTRL0_CLKIES | (4 << MSDC_PAD_CTRL0_CLKDRVN_S) | - (4 << MSDC_PAD_CTRL0_CLKDRVP_S), &host->base->pad_ctrl0); + MSDC_PAD_CTRL0_CLKIES | FIELD_PREP(MSDC_PAD_CTRL0_CLKDRVN, 4) | + FIELD_PREP(MSDC_PAD_CTRL0_CLKDRVP, 4), &host->base->pad_ctrl0); writel(MSDC_PAD_CTRL1_CMDPU | MSDC_PAD_CTRL1_CMDSMT | - MSDC_PAD_CTRL1_CMDIES | (4 << MSDC_PAD_CTRL1_CMDDRVN_S) | - (4 << MSDC_PAD_CTRL1_CMDDRVP_S), &host->base->pad_ctrl1); + MSDC_PAD_CTRL1_CMDIES | FIELD_PREP(MSDC_PAD_CTRL1_CMDDRVN, 4) | + FIELD_PREP(MSDC_PAD_CTRL1_CMDDRVP, 4), &host->base->pad_ctrl1); writel(MSDC_PAD_CTRL2_DATPU | MSDC_PAD_CTRL2_DATSMT | - MSDC_PAD_CTRL2_DATIES | (4 << MSDC_PAD_CTRL2_DATDRVN_S) | - (4 << MSDC_PAD_CTRL2_DATDRVP_S), &host->base->pad_ctrl2); + MSDC_PAD_CTRL2_DATIES | FIELD_PREP(MSDC_PAD_CTRL2_DATDRVN, 4) | + FIELD_PREP(MSDC_PAD_CTRL2_DATDRVP, 4), &host->base->pad_ctrl2); } if (host->dev_comp->default_pad_dly) { /* Default pad delay may be needed if tuning not enabled */ - clrsetbits_le32(tune_reg, MSDC_PAD_TUNE_CLKTDLY_M | - MSDC_PAD_TUNE_CMDRRDLY_M | - MSDC_PAD_TUNE_CMDRDLY_M | - MSDC_PAD_TUNE_DATRRDLY_M | - MSDC_PAD_TUNE_DATWRDLY_M, - (0x10 << MSDC_PAD_TUNE_CLKTDLY_S) | - (0x10 << MSDC_PAD_TUNE_CMDRRDLY_S) | - (0x10 << MSDC_PAD_TUNE_CMDRDLY_S) | - (0x10 << MSDC_PAD_TUNE_DATRRDLY_S) | - (0x10 << MSDC_PAD_TUNE_DATWRDLY_S)); - - writel((0x10 << MSDC_PAD_TUNE0_DAT0RDDLY_S) | - (0x10 << MSDC_PAD_TUNE0_DAT1RDDLY_S) | - (0x10 << MSDC_PAD_TUNE0_DAT2RDDLY_S) | - (0x10 << MSDC_PAD_TUNE0_DAT3RDDLY_S), + clrsetbits_le32(tune_reg, MSDC_PAD_TUNE_CLKTDLY | + MSDC_PAD_TUNE_CMDRRDLY | + MSDC_PAD_TUNE_CMDRDLY | + MSDC_PAD_TUNE_DATRRDLY | + MSDC_PAD_TUNE_DATWRDLY, + FIELD_PREP(MSDC_PAD_TUNE_CLKTDLY, 0x10) | + FIELD_PREP(MSDC_PAD_TUNE_CMDRRDLY, 0x10) | + FIELD_PREP(MSDC_PAD_TUNE_CMDRDLY, 0x10) | + FIELD_PREP(MSDC_PAD_TUNE_DATRRDLY, 0x10) | + FIELD_PREP(MSDC_PAD_TUNE_DATWRDLY, 0x10)); + writel(FIELD_PREP(MSDC_PAD_TUNE0_DAT0RDDLY, 0x10) | + FIELD_PREP(MSDC_PAD_TUNE0_DAT1RDDLY, 0x10) | + FIELD_PREP(MSDC_PAD_TUNE0_DAT2RDDLY, 0x10) | + FIELD_PREP(MSDC_PAD_TUNE0_DAT3RDDLY, 0x10), rd_dly0_reg); - writel((0x10 << MSDC_PAD_TUNE1_DAT4RDDLY_S) | - (0x10 << MSDC_PAD_TUNE1_DAT5RDDLY_S) | - (0x10 << MSDC_PAD_TUNE1_DAT6RDDLY_S) | - (0x10 << MSDC_PAD_TUNE1_DAT7RDDLY_S), + writel(FIELD_PREP(MSDC_PAD_TUNE1_DAT4RDDLY, 0x10) | + FIELD_PREP(MSDC_PAD_TUNE1_DAT5RDDLY, 0x10) | + FIELD_PREP(MSDC_PAD_TUNE1_DAT6RDDLY, 0x10) | + FIELD_PREP(MSDC_PAD_TUNE1_DAT7RDDLY, 0x10), rd_dly1_reg); } @@ -1633,8 +1578,8 @@ static void msdc_init_hw(struct msdc_host *host) clrbits_le32(&host->base->sdc_cfg, SDC_CFG_SDIOIDE); /* Configure to default data timeout */ - clrsetbits_le32(&host->base->sdc_cfg, SDC_CFG_DTOC_M, - 3 << SDC_CFG_DTOC_S); + clrsetbits_le32(&host->base->sdc_cfg, SDC_CFG_DTOC, + FIELD_PREP(SDC_CFG_DTOC, 3)); host->def_tune_para.iocon = readl(&host->base->msdc_iocon); host->def_tune_para.pad_tune = readl(&host->base->pad_tune); -- cgit v1.3.1 From aa38b1781078e312ee0eacfe20fc1914d7b1f0e7 Mon Sep 17 00:00:00 2001 From: David Lechner Date: Wed, 21 Jan 2026 16:36:25 -0600 Subject: mmc: mtk-sd: fix misaligned brace Indent a brace for proper code style. Signed-off-by: David Lechner Reviewed-by: Macpaul Lin Signed-off-by: Peng Fan --- drivers/mmc/mtk-sd.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/mmc/mtk-sd.c b/drivers/mmc/mtk-sd.c index 69f54a342c6..d434363508c 100644 --- a/drivers/mmc/mtk-sd.c +++ b/drivers/mmc/mtk-sd.c @@ -657,7 +657,7 @@ static int msdc_pio_read(struct msdc_host *host, u8 *ptr, u32 size) break; } -} + } return ret; } -- cgit v1.3.1 From 9652f2591d52804ffd9e88faecfe0ba246d6c317 Mon Sep 17 00:00:00 2001 From: "ht.lin" Date: Wed, 21 Jan 2026 16:36:26 -0600 Subject: mmc: mediatek: add DMA mode support Implement DMA support in the MediaTek MMC driver to enhance data transfer speed. - Define DMA control and configuration registers - Implement functions for starting, stopping, and completing DMA transfers - Modify data transfer logic to utilize DMA when enabled - Ensure proper cache management during DMA operations Signed-off-by: Wenbin Mei Signed-off-by: ht.lin Signed-off-by: Julien Masson Signed-off-by: Macpaul Lin Signed-off-by: David Lechner Signed-off-by: Peng Fan --- drivers/mmc/mtk-sd.c | 164 +++++++++++++++++++++++++++++++++++++++++++++++---- 1 file changed, 151 insertions(+), 13 deletions(-) diff --git a/drivers/mmc/mtk-sd.c b/drivers/mmc/mtk-sd.c index d434363508c..4928a880038 100644 --- a/drivers/mmc/mtk-sd.c +++ b/drivers/mmc/mtk-sd.c @@ -7,6 +7,7 @@ */ #include +#include #include #include #include @@ -14,6 +15,7 @@ #include #include #include +#include #include #include #include @@ -56,6 +58,8 @@ #define MSDC_INT_XFER_COMPL BIT(12) #define MSDC_INT_DATTMO BIT(14) #define MSDC_INT_DATCRCERR BIT(15) +#define MSDC_INT_BDCSERR BIT(17) +#define MSDC_INT_GPDCSERR BIT(18) /* MSDC_FIFOCS */ #define MSDC_FIFOCS_CLR BIT(31) @@ -83,6 +87,16 @@ /* SDC_ADV_CFG0 */ #define SDC_RX_ENHANCE_EN BIT(20) +/* MSDC_DMA_CTRL */ +#define MSDC_DMA_CTRL_BURSTSZ GENMASK(14, 12) +#define MSDC_DMA_CTRL_LASTBUF BIT(10) +#define MSDC_DMA_CTRL_MODE BIT(8) +#define MSDC_DMA_CTRL_STOP BIT(1) +#define MSDC_DMA_CTRL_START BIT(0) + +/* DMA_CFG */ +#define MSDC_DMA_CFG_STS BIT(0) + /* PATCH_BIT0 */ #define MSDC_INT_DAT_LATCH_CK_SEL GENMASK(9, 7) @@ -195,7 +209,8 @@ (MSDC_INT_CMDRDY | MSDC_INT_RSPCRCERR | MSDC_INT_CMDTMO) #define DATA_INTS_MASK \ - (MSDC_INT_XFER_COMPL | MSDC_INT_DATTMO | MSDC_INT_DATCRCERR) + (MSDC_INT_XFER_COMPL | MSDC_INT_DATTMO | MSDC_INT_DATCRCERR | \ + MSDC_INT_BDCSERR | MSDC_INT_GPDCSERR) /* Register offset */ struct mtk_sd_regs { @@ -294,6 +309,7 @@ struct msdc_compatible { bool builtin_pad_ctrl; bool default_pad_dly; bool use_internal_cd; + bool use_dma_mode; }; struct msdc_delay_phase { @@ -502,6 +518,9 @@ static int msdc_cmd_done(struct msdc_host *host, int events, ret = -EIO; } + /* Clear CMD interrupt */ + writel(events & CMD_INTS_MASK, &host->base->msdc_int); + return ret; } @@ -549,10 +568,9 @@ static int msdc_start_command(struct msdc_host *host, struct mmc_cmd *cmd, FIELD_GET(MSDC_FIFOCS_RXCNT, readl(&host->base->msdc_fifocs))) { pr_err("TX/RX FIFO non-empty before start of IO. Reset\n"); msdc_reset_hw(host); + msdc_fifo_clr(host); } - msdc_fifo_clr(host); - host->last_resp_type = cmd->resp_type; host->last_data_write = 0; @@ -561,8 +579,6 @@ static int msdc_start_command(struct msdc_host *host, struct mmc_cmd *cmd, if (data) blocks = data->blocks; - writel(CMD_INTS_MASK, &host->base->msdc_int); - writel(DATA_INTS_MASK, &host->base->msdc_int); writel(blocks, &host->base->sdc_blk_num); writel(cmd->cmdarg, &host->base->sdc_arg); writel(rawcmd, &host->base->sdc_cmd); @@ -704,14 +720,11 @@ static int msdc_pio_write(struct msdc_host *host, const u8 *ptr, u32 size) return ret; } -static int msdc_start_data(struct msdc_host *host, struct mmc_data *data) +static int msdc_pio_transfer(struct msdc_host *host, struct mmc_data *data) { u32 size; int ret; - if (data->flags == MMC_DATA_WRITE) - host->last_data_write = 1; - size = data->blocks * data->blocksize; if (data->flags == MMC_DATA_WRITE) @@ -719,6 +732,124 @@ static int msdc_start_data(struct msdc_host *host, struct mmc_data *data) else ret = msdc_pio_read(host, (u8 *)data->dest, size); + return ret; +} + +static dma_addr_t msdc_flush_membuf(const void *ptr, size_t size, enum dma_data_direction dir) +{ + dma_addr_t addr = (dma_addr_t)ptr; + + if (dir == DMA_FROM_DEVICE) + invalidate_dcache_range(addr, addr + size); + else + flush_dcache_range(addr, addr + size); + + return addr; +} + +static void msdc_dma_start(struct msdc_host *host, dma_addr_t addr, u32 size) +{ + writel((u32)addr, &host->base->dma_sa); + clrsetbits_le32(&host->base->dma_ctrl, MSDC_DMA_CTRL_BURSTSZ, + FIELD_PREP(MSDC_DMA_CTRL_BURSTSZ, 6)); + + /* BASIC_DMA mode */ + clrbits_le32(&host->base->dma_ctrl, MSDC_DMA_CTRL_MODE); + + /* This is the last buffer */ + setbits_le32(&host->base->dma_ctrl, MSDC_DMA_CTRL_LASTBUF); + + /* Total transfer size */ + writel(size, &host->base->dma_length); + + /* Trigger DMA start */ + setbits_le32(&host->base->dma_ctrl, MSDC_DMA_CTRL_START); +} + +static void msdc_dma_stop(struct msdc_host *host) +{ + u32 reg; + + setbits_le32(&host->base->dma_ctrl, MSDC_DMA_CTRL_STOP); + readl_poll_timeout(&host->base->dma_cfg, reg, + !(reg & MSDC_DMA_CFG_STS), 1000000); +} + +static int msdc_dma_done(struct msdc_host *host, int events) +{ + int ret = 0; + u32 rawcmd, arg; + + if (!(events & MSDC_INT_XFER_COMPL)) { + rawcmd = readl(&host->base->sdc_cmd); + arg = readl(&host->base->sdc_arg); + + if (events & MSDC_INT_DATTMO) + ret = -ETIMEDOUT; + else if (events & (MSDC_INT_DATCRCERR | MSDC_INT_GPDCSERR | MSDC_INT_BDCSERR)) + ret = -EIO; + else + ret = -EBADRQC; + + pr_err("MSDC: start data failure with %d, INT(0x%x), rawcmd=0x%x, arg=0x%x\n", + ret, events, rawcmd, arg); + } + + /* Clear DAT interrupt */ + writel(events & DATA_INTS_MASK, &host->base->msdc_int); + + return ret; +} + +static int msdc_dma_transfer(struct msdc_host *host, struct mmc_data *data) +{ + u32 size, status; + int ret; + const void *buf; + enum dma_data_direction dir; + dma_addr_t dma_addr; + + size = data->blocks * data->blocksize; + if (data->flags == MMC_DATA_WRITE) { + buf = data->src; + dir = DMA_TO_DEVICE; + } else { + buf = data->dest; + dir = DMA_FROM_DEVICE; + } + + dma_addr = msdc_flush_membuf(buf, size, dir); + msdc_dma_start(host, dma_addr, size); + + ret = readl_poll_timeout(&host->base->msdc_int, status, + status & DATA_INTS_MASK, 5000000); + if (ret) + status = MSDC_INT_DATTMO; + + msdc_dma_stop(host); + + /* + * Need invalidate the dcache again to avoid any + * cache-refill during the DMA operations (pre-fetching) + */ + if (data->flags & MMC_DATA_READ) + invalidate_dcache_range(dma_addr, dma_addr + size); + + return msdc_dma_done(host, status); +} + +static int msdc_start_data(struct msdc_host *host, struct mmc_data *data) +{ + int ret; + + if (data->flags == MMC_DATA_WRITE) + host->last_data_write = 1; + + if (host->dev_comp->use_dma_mode) + ret = msdc_dma_transfer(host, data); + else + ret = msdc_pio_transfer(host, data); + if (ret) { msdc_reset_hw(host); msdc_fifo_clr(host); @@ -1174,12 +1305,14 @@ skip_fall: if (final_maxlen == final_rise_delay.maxlen) { clrbits_le32(&host->base->msdc_iocon, MSDC_IOCON_RSPL); clrsetbits_le32(tune_reg, MSDC_PAD_TUNE_CMDRDLY, - FIELD_PREP(MSDC_PAD_TUNE_CMDRDLY, final_rise_delay.final_phase)); + FIELD_PREP(MSDC_PAD_TUNE_CMDRDLY, + final_rise_delay.final_phase)); final_delay = final_rise_delay.final_phase; } else { setbits_le32(&host->base->msdc_iocon, MSDC_IOCON_RSPL); clrsetbits_le32(tune_reg, MSDC_PAD_TUNE_CMDRDLY, - FIELD_PREP(MSDC_PAD_TUNE_CMDRDLY, final_fall_delay.final_phase)); + FIELD_PREP(MSDC_PAD_TUNE_CMDRDLY, + final_fall_delay.final_phase)); final_delay = final_fall_delay.final_phase; } @@ -1425,8 +1558,11 @@ static void msdc_init_hw(struct msdc_host *host) /* Configure to MMC/SD mode, clock free running */ setbits_le32(&host->base->msdc_cfg, MSDC_CFG_MODE); - /* Use PIO mode */ - setbits_le32(&host->base->msdc_cfg, MSDC_CFG_PIO); + /* Data transfer mode */ + if (host->dev_comp->use_dma_mode) + clrbits_le32(&host->base->msdc_cfg, MSDC_CFG_PIO); + else + setbits_le32(&host->base->msdc_cfg, MSDC_CFG_PIO); /* Reset */ msdc_reset_hw(host); @@ -1839,6 +1975,8 @@ static const struct msdc_compatible mt8183_compat = { .data_tune = true, .busy_check = true, .stop_clk_fix = true, + .enhance_rx = true, + .use_dma_mode = true, }; static const struct udevice_id msdc_ids[] = { -- cgit v1.3.1 From 7f9e9b50336777ce07ca7d7bc40bd82856d12468 Mon Sep 17 00:00:00 2001 From: Tanmay Kathpalia Date: Sun, 25 Jan 2026 04:39:57 -0800 Subject: mmc: Fix typos in comments and debug messages Fix the following typos in drivers/mmc/mmc.c: - "neiter" -> "neither" in __mmc_switch() comment - "witdh" -> "width" in bus_width() warning message - "enver" -> "never" in mmc_select_mode_and_width() comment Signed-off-by: Tanmay Kathpalia Reviewed-by: Peng Fan Signed-off-by: Peng Fan --- drivers/mmc/mmc.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/mmc/mmc.c b/drivers/mmc/mmc.c index 7dadff27abe..c5705f4f215 100644 --- a/drivers/mmc/mmc.c +++ b/drivers/mmc/mmc.c @@ -889,7 +889,7 @@ static int __mmc_switch(struct mmc *mmc, u8 set, u8 index, u8 value, return ret; /* - * In cases when neiter allowed to poll by using CMD13 nor we are + * In cases when neither allowed to poll by using CMD13 nor we are * capable of polling by using mmc_wait_dat0, then rely on waiting the * stated timeout to be sufficient. */ @@ -1663,7 +1663,7 @@ static inline int bus_width(uint cap) return 4; if (cap == MMC_MODE_1BIT) return 1; - pr_warn("invalid bus witdh capability 0x%x\n", cap); + pr_warn("invalid bus width capability 0x%x\n", cap); return 0; } @@ -2200,7 +2200,7 @@ static int mmc_select_mode_and_width(struct mmc *mmc, uint card_caps) return 0; if (!mmc->ext_csd) { - pr_debug("No ext_csd found!\n"); /* this should enver happen */ + pr_debug("No ext_csd found!\n"); /* this should never happen */ return -ENOTSUPP; } -- cgit v1.3.1 From 97cc26f6b6a85312305e5b953ef44861891936bf Mon Sep 17 00:00:00 2001 From: Yao Zi Date: Fri, 30 Jan 2026 18:03:51 +0000 Subject: cmd: mmc: Simplify dev subcommand handling Replace the big if-else block in do_mmc_dev() with switch-case and use fallthrough to remove the duplicated code for parsing dev and part. Signed-off-by: Yao Zi Tested-by: Anshul Dalal Reviewed-by: Peng Fan Signed-off-by: Peng Fan --- cmd/mmc.c | 34 ++++++++++++++-------------------- 1 file changed, 14 insertions(+), 20 deletions(-) diff --git a/cmd/mmc.c b/cmd/mmc.c index 5340a58be8e..f2a59af087c 100644 --- a/cmd/mmc.c +++ b/cmd/mmc.c @@ -16,6 +16,7 @@ #include #include #include +#include #include static int curr_device = -1; @@ -556,37 +557,30 @@ static int do_mmc_part(struct cmd_tbl *cmdtp, int flag, static int do_mmc_dev(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[]) { - int dev, part = 0, ret; + enum bus_mode speed_mode = MMC_MODES_END; + int dev = curr_device, part = 0, ret; struct mmc *mmc; - if (argc == 1) { - dev = curr_device; - mmc = init_mmc_device(dev, true); - } else if (argc == 2) { - dev = (int)dectoul(argv[1], NULL); - mmc = init_mmc_device(dev, true); - } else if (argc == 3) { - dev = (int)dectoul(argv[1], NULL); + switch (argc) { + case 4: + speed_mode = (int)dectoul(argv[3], NULL); + fallthrough; + case 3: part = (int)dectoul(argv[2], NULL); if (part > PART_ACCESS_MASK) { printf("#part_num shouldn't be larger than %d\n", PART_ACCESS_MASK); return CMD_RET_FAILURE; } - mmc = init_mmc_device(dev, true); - } else if (argc == 4) { - enum bus_mode speed_mode; + fallthrough; + case 2: dev = (int)dectoul(argv[1], NULL); - part = (int)dectoul(argv[2], NULL); - if (part > PART_ACCESS_MASK) { - printf("#part_num shouldn't be larger than %d\n", - PART_ACCESS_MASK); - return CMD_RET_FAILURE; - } - speed_mode = (int)dectoul(argv[3], NULL); + fallthrough; + case 1: mmc = __init_mmc_device(dev, true, speed_mode); - } else { + break; + default: return CMD_RET_USAGE; } -- cgit v1.3.1 From f955e00e42e9b7ef5a3adf1ba1947f46c05a3d36 Mon Sep 17 00:00:00 2001 From: Yao Zi Date: Fri, 30 Jan 2026 18:03:52 +0000 Subject: cmd: mmc: Check whether arguments are valid numbers in dev subcommand Currently when any of speed_mode, part, or dev fails to be parse as a number, no error is reported. In this case __init_mmc_device() is called with weird arguments, probably zeroes if there's no digit prefixing the argument, which is especially confusing when the invocation occasionally succeeds. Let's check whether arguments are valid numbers without trailing characters. This is quite helpful for speed_mode: it requires an index instead of a mode name, one may easily pass in a string, which will be parsed as zero (MMC_LEGACY), without carefully reading the documentation, then finds the MMC device is under an unexpected mode. Signed-off-by: Yao Zi Tested-by: Anshul Dalal Reviewed-by: Peng Fan Signed-off-by: Peng Fan --- cmd/mmc.c | 23 +++++++++++++++++++---- 1 file changed, 19 insertions(+), 4 deletions(-) diff --git a/cmd/mmc.c b/cmd/mmc.c index f2a59af087c..512bd482ae8 100644 --- a/cmd/mmc.c +++ b/cmd/mmc.c @@ -559,15 +559,25 @@ static int do_mmc_dev(struct cmd_tbl *cmdtp, int flag, { enum bus_mode speed_mode = MMC_MODES_END; int dev = curr_device, part = 0, ret; + char *endp; struct mmc *mmc; switch (argc) { case 4: - speed_mode = (int)dectoul(argv[3], NULL); + speed_mode = (int)dectoul(argv[3], &endp); + if (*endp) { + printf("Invalid speed mode index '%s', " + "did you specify a mode name?\n", argv[3]); + return CMD_RET_USAGE; + } + fallthrough; case 3: - part = (int)dectoul(argv[2], NULL); - if (part > PART_ACCESS_MASK) { + part = (int)dectoul(argv[2], &endp); + if (*endp) { + printf("Invalid part number '%s'\n", argv[2]); + return CMD_RET_USAGE; + } else if (part > PART_ACCESS_MASK) { printf("#part_num shouldn't be larger than %d\n", PART_ACCESS_MASK); return CMD_RET_FAILURE; @@ -575,7 +585,12 @@ static int do_mmc_dev(struct cmd_tbl *cmdtp, int flag, fallthrough; case 2: - dev = (int)dectoul(argv[1], NULL); + dev = (int)dectoul(argv[1], &endp); + if (*endp) { + printf("Invalid device number '%s'\n", argv[1]); + return CMD_RET_USAGE; + } + fallthrough; case 1: mmc = __init_mmc_device(dev, true, speed_mode); -- cgit v1.3.1 From b4f0479e076014f403319fdce53c5c1ac278f8ae Mon Sep 17 00:00:00 2001 From: Yao Zi Date: Fri, 30 Jan 2026 18:03:53 +0000 Subject: cmd: mmc: Return symbolic value when part switching fails in mmc dev Return symbolic value CMD_RET_FAILURE instead of literal "1" when failing to switch the partition to improve readability. Signed-off-by: Yao Zi Tested-by: Anshul Dalal Reviewed-by: Peng Fan Signed-off-by: Peng Fan --- cmd/mmc.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cmd/mmc.c b/cmd/mmc.c index 512bd482ae8..bcbe963f8ac 100644 --- a/cmd/mmc.c +++ b/cmd/mmc.c @@ -606,7 +606,7 @@ static int do_mmc_dev(struct cmd_tbl *cmdtp, int flag, printf("switch to partitions #%d, %s\n", part, (!ret) ? "OK" : "ERROR"); if (ret) - return 1; + return CMD_RET_FAILURE; curr_device = dev; if (mmc->part_config == MMCPART_NOAVAILABLE) -- cgit v1.3.1