diff options
Diffstat (limited to 'drivers/mmc/host/mtk-sd.c')
| -rw-r--r-- | drivers/mmc/host/mtk-sd.c | 312 |
1 files changed, 207 insertions, 105 deletions
diff --git a/drivers/mmc/host/mtk-sd.c b/drivers/mmc/host/mtk-sd.c index efb0d2d5716b..daed659f63f6 100644 --- a/drivers/mmc/host/mtk-sd.c +++ b/drivers/mmc/host/mtk-sd.c @@ -5,6 +5,7 @@ */ #include <linux/module.h> +#include <linux/bitfield.h> #include <linux/bitops.h> #include <linux/clk.h> #include <linux/delay.h> @@ -83,6 +84,7 @@ #define EMMC51_CFG0 0x204 #define EMMC50_CFG0 0x208 #define EMMC50_CFG1 0x20c +#define EMMC50_CFG2 0x21c #define EMMC50_CFG3 0x220 #define SDC_FIFO_CFG 0x228 #define CQHCI_SETTING 0x7fc @@ -233,7 +235,9 @@ /* MSDC_PATCH_BIT mask */ #define MSDC_PATCH_BIT_ODDSUPP BIT(1) /* RW */ +#define MSDC_PATCH_BIT_DIS_WRMON BIT(2) /* RW */ #define MSDC_PATCH_BIT_RD_DAT_SEL BIT(3) /* RW */ +#define MSDC_PATCH_BIT_DESCUP_SEL BIT(6) /* RW */ #define MSDC_INT_DAT_LATCH_CK_SEL GENMASK(9, 7) #define MSDC_CKGEN_MSDC_DLY_SEL GENMASK(14, 10) #define MSDC_PATCH_BIT_IODSSEL BIT(16) /* RW */ @@ -246,10 +250,22 @@ #define MSDC_PATCH_BIT_SPCPUSH BIT(29) /* RW */ #define MSDC_PATCH_BIT_DECRCTMO BIT(30) /* RW */ -#define MSDC_PATCH_BIT1_CMDTA GENMASK(5, 3) /* RW */ +/* MSDC_PATCH_BIT1 mask */ +#define MSDC_PB1_WRDAT_CRC_TACNTR GENMASK(2, 0) /* RW */ +#define MSDC_PATCH_BIT1_CMDTA GENMASK(5, 3) /* RW */ #define MSDC_PB1_BUSY_CHECK_SEL BIT(7) /* RW */ #define MSDC_PATCH_BIT1_STOP_DLY GENMASK(11, 8) /* RW */ - +#define MSDC_PB1_DDR_CMD_FIX_SEL BIT(14) /* RW */ +#define MSDC_PB1_SINGLE_BURST BIT(16) /* RW */ +#define MSDC_PB1_RSVD20 GENMASK(18, 17) /* RW */ +#define MSDC_PB1_AUTO_SYNCST_CLR BIT(19) /* RW */ +#define MSDC_PB1_MARK_POP_WATER BIT(20) /* RW */ +#define MSDC_PB1_LP_DCM_EN BIT(21) /* RW */ +#define MSDC_PB1_RSVD3 BIT(22) /* RW */ +#define MSDC_PB1_AHB_GDMA_HCLK BIT(23) /* RW */ +#define MSDC_PB1_MSDC_CLK_ENFEAT GENMASK(31, 24) /* RW */ + +/* MSDC_PATCH_BIT2 mask */ #define MSDC_PATCH_BIT2_CFGRESP BIT(15) /* RW */ #define MSDC_PATCH_BIT2_CFGCRCSTS BIT(28) /* RW */ #define MSDC_PB2_SUPPORT_64G BIT(1) /* RW */ @@ -273,6 +289,7 @@ #define MSDC_PAD_TUNE_CMD2_SEL BIT(21) /* RW */ #define PAD_DS_TUNE_DLY_SEL BIT(0) /* RW */ +#define PAD_DS_TUNE_DLY2_SEL BIT(1) /* RW */ #define PAD_DS_TUNE_DLY1 GENMASK(6, 2) /* RW */ #define PAD_DS_TUNE_DLY2 GENMASK(11, 7) /* RW */ #define PAD_DS_TUNE_DLY3 GENMASK(16, 12) /* RW */ @@ -290,7 +307,10 @@ /* EMMC50_CFG1 mask */ #define EMMC50_CFG1_DS_CFG BIT(28) /* RW */ -#define EMMC50_CFG3_OUTS_WR GENMASK(4, 0) /* RW */ +/* EMMC50_CFG2 mask */ +#define EMMC50_CFG2_AXI_SET_LEN GENMASK(27, 24) /* RW */ + +#define EMMC50_CFG3_OUTS_WR GENMASK(4, 0) /* RW */ #define SDC_FIFO_CFG_WRVALIDSEL BIT(24) /* RW */ #define SDC_FIFO_CFG_RDVALIDSEL BIT(25) /* RW */ @@ -318,6 +338,7 @@ /* EMMC50_PAD_DS_TUNE mask */ #define PAD_DS_DLY_SEL BIT(16) /* RW */ +#define PAD_DS_DLY2_SEL BIT(15) /* RW */ #define PAD_DS_DLY1 GENMASK(14, 10) /* RW */ #define PAD_DS_DLY3 GENMASK(4, 0) /* RW */ @@ -414,6 +435,7 @@ struct mtk_mmc_compatible { u8 clk_div_bits; bool recheck_sdio_irq; bool hs400_tune; /* only used for MT8173 */ + bool needs_top_base; u32 pad_tune_reg; bool async_fifo; bool data_tune; @@ -587,6 +609,7 @@ static const struct mtk_mmc_compatible mt7986_compat = { .clk_div_bits = 12, .recheck_sdio_irq = true, .hs400_tune = false, + .needs_top_base = true, .pad_tune_reg = MSDC_PAD_TUNE0, .async_fifo = true, .data_tune = true, @@ -627,6 +650,7 @@ static const struct mtk_mmc_compatible mt8183_compat = { .clk_div_bits = 12, .recheck_sdio_irq = false, .hs400_tune = false, + .needs_top_base = true, .pad_tune_reg = MSDC_PAD_TUNE0, .async_fifo = true, .data_tune = true, @@ -653,6 +677,7 @@ static const struct mtk_mmc_compatible mt8196_compat = { .clk_div_bits = 12, .recheck_sdio_irq = false, .hs400_tune = false, + .needs_top_base = true, .pad_tune_reg = MSDC_PAD_TUNE0, .async_fifo = true, .data_tune = true, @@ -821,12 +846,18 @@ static inline void msdc_dma_setup(struct msdc_host *host, struct msdc_dma *dma, static void msdc_prepare_data(struct msdc_host *host, struct mmc_data *data) { if (!(data->host_cookie & MSDC_PREPARE_FLAG)) { - data->host_cookie |= MSDC_PREPARE_FLAG; data->sg_count = dma_map_sg(host->dev, data->sg, data->sg_len, mmc_get_dma_dir(data)); + if (data->sg_count) + data->host_cookie |= MSDC_PREPARE_FLAG; } } +static bool msdc_data_prepared(struct mmc_data *data) +{ + return data->host_cookie & MSDC_PREPARE_FLAG; +} + static void msdc_unprepare_data(struct msdc_host *host, struct mmc_data *data) { if (data->host_cookie & MSDC_ASYNC_FLAG) @@ -921,15 +952,15 @@ static int msdc_ungate_clock(struct msdc_host *host) static void msdc_new_tx_setting(struct msdc_host *host) { + u32 val; + if (!host->top_base) return; - sdr_set_bits(host->top_base + LOOP_TEST_CONTROL, - TEST_LOOP_DSCLK_MUX_SEL); - sdr_set_bits(host->top_base + LOOP_TEST_CONTROL, - TEST_LOOP_LATCH_MUX_SEL); - sdr_clr_bits(host->top_base + LOOP_TEST_CONTROL, - TEST_HS400_CMD_LOOP_MUX_SEL); + val = readl(host->top_base + LOOP_TEST_CONTROL); + val |= TEST_LOOP_DSCLK_MUX_SEL; + val |= TEST_LOOP_LATCH_MUX_SEL; + val &= ~TEST_HS400_CMD_LOOP_MUX_SEL; switch (host->timing) { case MMC_TIMING_LEGACY: @@ -939,19 +970,18 @@ static void msdc_new_tx_setting(struct msdc_host *host) case MMC_TIMING_UHS_SDR25: case MMC_TIMING_UHS_DDR50: case MMC_TIMING_MMC_DDR52: - sdr_clr_bits(host->top_base + LOOP_TEST_CONTROL, - LOOP_EN_SEL_CLK); + val &= ~LOOP_EN_SEL_CLK; break; case MMC_TIMING_UHS_SDR50: case MMC_TIMING_UHS_SDR104: case MMC_TIMING_MMC_HS200: case MMC_TIMING_MMC_HS400: - sdr_set_bits(host->top_base + LOOP_TEST_CONTROL, - LOOP_EN_SEL_CLK); + val |= LOOP_EN_SEL_CLK; break; default: break; } + writel(val, host->top_base + LOOP_TEST_CONTROL); } static void msdc_set_mclk(struct msdc_host *host, unsigned char timing, u32 hz) @@ -1097,11 +1127,12 @@ static inline u32 msdc_cmd_find_resp(struct msdc_host *host, u32 resp; switch (mmc_resp_type(cmd)) { - /* Actually, R1, R5, R6, R7 are the same */ + /* Actually, R1, R5, R6, R7 are the same */ case MMC_RSP_R1: resp = 0x1; break; case MMC_RSP_R1B: + case MMC_RSP_R1B_NO_CRC: resp = 0x7; break; case MMC_RSP_R2: @@ -1183,7 +1214,7 @@ static void msdc_start_data(struct msdc_host *host, struct mmc_command *cmd, host->data = data; read = data->flags & MMC_DATA_READ; - mod_delayed_work(system_wq, &host->req_timeout, DAT_TIMEOUT); + mod_delayed_work(system_percpu_wq, &host->req_timeout, DAT_TIMEOUT); msdc_dma_setup(host, &host->dma, data); sdr_set_bits(host->base + MSDC_INTEN, data_ints_mask); sdr_set_field(host->base + MSDC_DMA_CTRL, MSDC_DMA_CTRL_START, 1); @@ -1351,7 +1382,8 @@ static bool msdc_cmd_done(struct msdc_host *host, int events, * CRC error. */ msdc_reset_hw(host); - if (events & MSDC_INT_RSPCRCERR) { + if (events & MSDC_INT_RSPCRCERR && + mmc_resp_type(cmd) != MMC_RSP_R1B_NO_CRC) { cmd->error = -EILSEQ; host->error |= REQ_CMD_EIO; } else if (events & MSDC_INT_CMDTMO) { @@ -1412,7 +1444,7 @@ static void msdc_start_command(struct msdc_host *host, WARN_ON(host->cmd); host->cmd = cmd; - mod_delayed_work(system_wq, &host->req_timeout, DAT_TIMEOUT); + mod_delayed_work(system_percpu_wq, &host->req_timeout, DAT_TIMEOUT); if (!msdc_cmd_is_ready(host, mrq, cmd)) return; @@ -1457,8 +1489,19 @@ static void msdc_ops_request(struct mmc_host *mmc, struct mmc_request *mrq) WARN_ON(!host->hsq_en && host->mrq); host->mrq = mrq; - if (mrq->data) + if (mrq->data) { msdc_prepare_data(host, mrq->data); + if (!msdc_data_prepared(mrq->data)) { + host->mrq = NULL; + /* + * Failed to prepare DMA area, fail fast before + * starting any commands. + */ + mrq->cmd->error = -ENOSPC; + mmc_request_done(mmc_from_priv(host), mrq); + return; + } + } /* if SBC is required, we have HW option and SW option. * if HW option is enabled, and SBC does not have "special" flags, @@ -1808,7 +1851,7 @@ static irqreturn_t msdc_irq(int irq, void *dev_id) static void msdc_init_hw(struct msdc_host *host) { - u32 val; + u32 val, pb1_val, pb2_val; u32 tune_reg = host->dev_comp->pad_tune_reg; struct mmc_host *mmc = mmc_from_priv(host); @@ -1861,71 +1904,115 @@ static void msdc_init_hw(struct msdc_host *host) } writel(0, host->base + MSDC_IOCON); sdr_set_field(host->base + MSDC_IOCON, MSDC_IOCON_DDLSEL, 0); - writel(0x403c0046, host->base + MSDC_PATCH_BIT); - sdr_set_field(host->base + MSDC_PATCH_BIT, MSDC_CKGEN_MSDC_DLY_SEL, 1); - writel(0xffff4089, host->base + MSDC_PATCH_BIT1); - sdr_set_bits(host->base + EMMC50_CFG0, EMMC50_CFG_CFCSTS_SEL); + + /* + * Patch bit 0 and 1 are completely rewritten, but for patch bit 2 + * defaults are retained and, if necessary, only some bits are fixed + * up: read the PB2 register here for later usage in this function. + */ + pb2_val = readl(host->base + MSDC_PATCH_BIT2); + + /* Enable odd number support for 8-bit data bus */ + val = MSDC_PATCH_BIT_ODDSUPP; + + /* Disable SD command register write monitor */ + val |= MSDC_PATCH_BIT_DIS_WRMON; + + /* Issue transfer done interrupt after GPD update */ + val |= MSDC_PATCH_BIT_DESCUP_SEL; + + /* Extend R1B busy detection delay (in clock cycles) */ + val |= FIELD_PREP(MSDC_PATCH_BIT_BUSYDLY, 15); + + /* Enable CRC phase timeout during data write operation */ + val |= MSDC_PATCH_BIT_DECRCTMO; + + /* Set CKGEN delay to one stage */ + val |= FIELD_PREP(MSDC_CKGEN_MSDC_DLY_SEL, 1); + + /* First MSDC_PATCH_BIT setup is done: pull the trigger! */ + writel(val, host->base + MSDC_PATCH_BIT); + + /* Set wr data, crc status, cmd response turnaround period for UHS104 */ + pb1_val = FIELD_PREP(MSDC_PB1_WRDAT_CRC_TACNTR, 1); + pb1_val |= FIELD_PREP(MSDC_PATCH_BIT1_CMDTA, 1); + pb1_val |= MSDC_PB1_DDR_CMD_FIX_SEL; + + /* Support 'single' burst type only when AXI_LEN is 0 */ + sdr_get_field(host->base + EMMC50_CFG2, EMMC50_CFG2_AXI_SET_LEN, &val); + if (!val) + pb1_val |= MSDC_PB1_SINGLE_BURST; + + /* Set auto sync state clear, block gap stop clk */ + pb1_val |= MSDC_PB1_RSVD20 | MSDC_PB1_AUTO_SYNCST_CLR | MSDC_PB1_MARK_POP_WATER; + + /* Set low power DCM, use HCLK for GDMA, use MSDC CLK for everything else */ + pb1_val |= MSDC_PB1_LP_DCM_EN | MSDC_PB1_RSVD3 | + MSDC_PB1_AHB_GDMA_HCLK | MSDC_PB1_MSDC_CLK_ENFEAT; + + /* If needed, enable R1b command busy check at controller init time */ + if (!host->dev_comp->busy_check) + pb1_val |= MSDC_PB1_BUSY_CHECK_SEL; if (host->dev_comp->stop_clk_fix) { if (host->dev_comp->stop_dly_sel) - sdr_set_field(host->base + MSDC_PATCH_BIT1, - MSDC_PATCH_BIT1_STOP_DLY, - host->dev_comp->stop_dly_sel); + pb1_val |= FIELD_PREP(MSDC_PATCH_BIT1_STOP_DLY, + host->dev_comp->stop_dly_sel); - if (host->dev_comp->pop_en_cnt) - sdr_set_field(host->base + MSDC_PATCH_BIT2, - MSDC_PB2_POP_EN_CNT, - host->dev_comp->pop_en_cnt); + if (host->dev_comp->pop_en_cnt) { + pb2_val &= ~MSDC_PB2_POP_EN_CNT; + pb2_val |= FIELD_PREP(MSDC_PB2_POP_EN_CNT, + host->dev_comp->pop_en_cnt); + } - sdr_clr_bits(host->base + SDC_FIFO_CFG, - SDC_FIFO_CFG_WRVALIDSEL); - sdr_clr_bits(host->base + SDC_FIFO_CFG, - SDC_FIFO_CFG_RDVALIDSEL); + sdr_clr_bits(host->base + SDC_FIFO_CFG, SDC_FIFO_CFG_WRVALIDSEL); + sdr_clr_bits(host->base + SDC_FIFO_CFG, SDC_FIFO_CFG_RDVALIDSEL); } - if (host->dev_comp->busy_check) - sdr_clr_bits(host->base + MSDC_PATCH_BIT1, BIT(7)); - if (host->dev_comp->async_fifo) { - sdr_set_field(host->base + MSDC_PATCH_BIT2, - MSDC_PB2_RESPWAIT, 3); - if (host->dev_comp->enhance_rx) { - if (host->top_base) - sdr_set_bits(host->top_base + EMMC_TOP_CONTROL, - SDC_RX_ENH_EN); - else - sdr_set_bits(host->base + SDC_ADV_CFG0, - SDC_RX_ENHANCE_EN); + /* Set CMD response timeout multiplier to 65 + (16 * 3) cycles */ + pb2_val &= ~MSDC_PB2_RESPWAIT; + pb2_val |= FIELD_PREP(MSDC_PB2_RESPWAIT, 3); + + /* eMMC4.5: Select async FIFO path for CMD resp and CRC status */ + pb2_val &= ~MSDC_PATCH_BIT2_CFGRESP; + pb2_val |= MSDC_PATCH_BIT2_CFGCRCSTS; + + if (!host->dev_comp->enhance_rx) { + /* eMMC4.5: Delay 2T for CMD resp and CRC status EN signals */ + pb2_val &= ~(MSDC_PB2_RESPSTSENSEL | MSDC_PB2_CRCSTSENSEL); + pb2_val |= FIELD_PREP(MSDC_PB2_RESPSTSENSEL, 2); + pb2_val |= FIELD_PREP(MSDC_PB2_CRCSTSENSEL, 2); + } else if (host->top_base) { + sdr_set_bits(host->top_base + EMMC_TOP_CONTROL, SDC_RX_ENH_EN); } else { - sdr_set_field(host->base + MSDC_PATCH_BIT2, - MSDC_PB2_RESPSTSENSEL, 2); - sdr_set_field(host->base + MSDC_PATCH_BIT2, - MSDC_PB2_CRCSTSENSEL, 2); + sdr_set_bits(host->base + SDC_ADV_CFG0, SDC_RX_ENHANCE_EN); } - /* use async fifo, then no need tune internal delay */ - sdr_clr_bits(host->base + MSDC_PATCH_BIT2, - MSDC_PATCH_BIT2_CFGRESP); - sdr_set_bits(host->base + MSDC_PATCH_BIT2, - MSDC_PATCH_BIT2_CFGCRCSTS); } if (host->dev_comp->support_64g) - sdr_set_bits(host->base + MSDC_PATCH_BIT2, - MSDC_PB2_SUPPORT_64G); + pb2_val |= MSDC_PB2_SUPPORT_64G; + + /* Patch Bit 1/2 setup is done: pull the trigger! */ + writel(pb1_val, host->base + MSDC_PATCH_BIT1); + writel(pb2_val, host->base + MSDC_PATCH_BIT2); + sdr_set_bits(host->base + EMMC50_CFG0, EMMC50_CFG_CFCSTS_SEL); + if (host->dev_comp->data_tune) { if (host->top_base) { - sdr_set_bits(host->top_base + EMMC_TOP_CONTROL, - PAD_DAT_RD_RXDLY_SEL); - sdr_clr_bits(host->top_base + EMMC_TOP_CONTROL, - DATA_K_VALUE_SEL); - sdr_set_bits(host->top_base + EMMC_TOP_CMD, - PAD_CMD_RD_RXDLY_SEL); + u32 top_ctl_val = readl(host->top_base + EMMC_TOP_CONTROL); + u32 top_cmd_val = readl(host->top_base + EMMC_TOP_CMD); + + top_cmd_val |= PAD_CMD_RD_RXDLY_SEL; + top_ctl_val |= PAD_DAT_RD_RXDLY_SEL; + top_ctl_val &= ~DATA_K_VALUE_SEL; if (host->tuning_step > PAD_DELAY_HALF) { - sdr_set_bits(host->top_base + EMMC_TOP_CONTROL, - PAD_DAT_RD_RXDLY2_SEL); - sdr_set_bits(host->top_base + EMMC_TOP_CMD, - PAD_CMD_RD_RXDLY2_SEL); + top_cmd_val |= PAD_CMD_RD_RXDLY2_SEL; + top_ctl_val |= PAD_DAT_RD_RXDLY2_SEL; } + + writel(top_ctl_val, host->top_base + EMMC_TOP_CONTROL); + writel(top_cmd_val, host->top_base + EMMC_TOP_CMD); } else { sdr_set_bits(host->base + tune_reg, MSDC_PAD_TUNE_RD_SEL | @@ -2135,15 +2222,17 @@ static inline void msdc_set_cmd_delay(struct msdc_host *host, u32 value) u32 tune_reg = host->dev_comp->pad_tune_reg; if (host->top_base) { + u32 regval = readl(host->top_base + EMMC_TOP_CMD); + + regval &= ~(PAD_CMD_RXDLY | PAD_CMD_RXDLY2); + if (value < PAD_DELAY_HALF) { - sdr_set_field(host->top_base + EMMC_TOP_CMD, PAD_CMD_RXDLY, value); - sdr_set_field(host->top_base + EMMC_TOP_CMD, PAD_CMD_RXDLY2, 0); + regval |= FIELD_PREP(PAD_CMD_RXDLY, value); } else { - sdr_set_field(host->top_base + EMMC_TOP_CMD, PAD_CMD_RXDLY, - PAD_DELAY_HALF - 1); - sdr_set_field(host->top_base + EMMC_TOP_CMD, PAD_CMD_RXDLY2, - value - PAD_DELAY_HALF); + regval |= FIELD_PREP(PAD_CMD_RXDLY, PAD_DELAY_HALF - 1); + regval |= FIELD_PREP(PAD_CMD_RXDLY2, value - PAD_DELAY_HALF); } + writel(regval, host->top_base + EMMC_TOP_CMD); } else { if (value < PAD_DELAY_HALF) { sdr_set_field(host->base + tune_reg, MSDC_PAD_TUNE_CMDRDLY, value); @@ -2163,17 +2252,18 @@ static inline void msdc_set_data_delay(struct msdc_host *host, u32 value) u32 tune_reg = host->dev_comp->pad_tune_reg; if (host->top_base) { + u32 regval = readl(host->top_base + EMMC_TOP_CONTROL); + + regval &= ~(PAD_DAT_RD_RXDLY | PAD_DAT_RD_RXDLY2); + if (value < PAD_DELAY_HALF) { - sdr_set_field(host->top_base + EMMC_TOP_CONTROL, - PAD_DAT_RD_RXDLY, value); - sdr_set_field(host->top_base + EMMC_TOP_CONTROL, - PAD_DAT_RD_RXDLY2, 0); + regval |= FIELD_PREP(PAD_DAT_RD_RXDLY, value); + regval |= FIELD_PREP(PAD_DAT_RD_RXDLY2, value); } else { - sdr_set_field(host->top_base + EMMC_TOP_CONTROL, - PAD_DAT_RD_RXDLY, PAD_DELAY_HALF - 1); - sdr_set_field(host->top_base + EMMC_TOP_CONTROL, - PAD_DAT_RD_RXDLY2, value - PAD_DELAY_HALF); + regval |= FIELD_PREP(PAD_DAT_RD_RXDLY, PAD_DELAY_HALF - 1); + regval |= FIELD_PREP(PAD_DAT_RD_RXDLY2, value - PAD_DELAY_HALF); } + writel(regval, host->top_base + EMMC_TOP_CONTROL); } else { if (value < PAD_DELAY_HALF) { sdr_set_field(host->base + tune_reg, MSDC_PAD_TUNE_DATRRDLY, value); @@ -2498,13 +2588,23 @@ tune_done: static int msdc_prepare_hs400_tuning(struct mmc_host *mmc, struct mmc_ios *ios) { struct msdc_host *host = mmc_priv(mmc); + host->hs400_mode = true; - if (host->top_base) - writel(host->hs400_ds_delay, - host->top_base + EMMC50_PAD_DS_TUNE); - else - writel(host->hs400_ds_delay, host->base + PAD_DS_TUNE); + if (host->top_base) { + if (host->hs400_ds_dly3) + sdr_set_field(host->top_base + EMMC50_PAD_DS_TUNE, + PAD_DS_DLY3, host->hs400_ds_dly3); + if (host->hs400_ds_delay) + writel(host->hs400_ds_delay, + host->top_base + EMMC50_PAD_DS_TUNE); + } else { + if (host->hs400_ds_dly3) + sdr_set_field(host->base + PAD_DS_TUNE, + PAD_DS_TUNE_DLY3, host->hs400_ds_dly3); + if (host->hs400_ds_delay) + writel(host->hs400_ds_delay, host->base + PAD_DS_TUNE); + } /* hs400 mode must set it to 0 */ sdr_clr_bits(host->base + MSDC_PATCH_BIT2, MSDC_PATCH_BIT2_CFGCRCSTS); /* to improve read performance, set outstanding to 2 */ @@ -2524,14 +2624,11 @@ static int msdc_execute_hs400_tuning(struct mmc_host *mmc, struct mmc_card *card if (host->top_base) { sdr_set_bits(host->top_base + EMMC50_PAD_DS_TUNE, PAD_DS_DLY_SEL); - if (host->hs400_ds_dly3) - sdr_set_field(host->top_base + EMMC50_PAD_DS_TUNE, - PAD_DS_DLY3, host->hs400_ds_dly3); + sdr_clr_bits(host->top_base + EMMC50_PAD_DS_TUNE, + PAD_DS_DLY2_SEL); } else { sdr_set_bits(host->base + PAD_DS_TUNE, PAD_DS_TUNE_DLY_SEL); - if (host->hs400_ds_dly3) - sdr_set_field(host->base + PAD_DS_TUNE, - PAD_DS_TUNE_DLY3, host->hs400_ds_dly3); + sdr_clr_bits(host->base + PAD_DS_TUNE, PAD_DS_TUNE_DLY2_SEL); } host->hs400_tuning = true; @@ -2885,9 +2982,13 @@ static int msdc_drv_probe(struct platform_device *pdev) if (IS_ERR(host->base)) return PTR_ERR(host->base); - host->top_base = devm_platform_ioremap_resource(pdev, 1); - if (IS_ERR(host->top_base)) - host->top_base = NULL; + host->dev_comp = of_device_get_match_data(&pdev->dev); + + if (host->dev_comp->needs_top_base) { + host->top_base = devm_platform_ioremap_resource(pdev, 1); + if (IS_ERR(host->top_base)) + return PTR_ERR(host->top_base); + } ret = mmc_regulator_get_supply(mmc); if (ret) @@ -2949,7 +3050,6 @@ static int msdc_drv_probe(struct platform_device *pdev) msdc_of_property_parse(pdev, host); host->dev = &pdev->dev; - host->dev_comp = of_device_get_match_data(&pdev->dev); host->src_clk_freq = clk_get_rate(host->src_clk); /* Set host parameters to mmc */ mmc->ops = &mt_msdc_ops; @@ -2959,7 +3059,7 @@ static int msdc_drv_probe(struct platform_device *pdev) mmc->f_min = DIV_ROUND_UP(host->src_clk_freq, 4 * 4095); if (!(mmc->caps & MMC_CAP_NONREMOVABLE) && - !mmc_can_gpio_cd(mmc) && + !mmc_host_can_gpio_cd(mmc) && host->dev_comp->use_internal_cd) { /* * Is removable but no GPIO declared, so @@ -3070,6 +3170,7 @@ release_clk: msdc_gate_clock(host); platform_set_drvdata(pdev, NULL); release_mem: + device_init_wakeup(&pdev->dev, false); if (host->dma.gpd) dma_free_coherent(&pdev->dev, 2 * sizeof(struct mt_gpdma_desc), @@ -3103,6 +3204,7 @@ static void msdc_drv_remove(struct platform_device *pdev) host->dma.gpd, host->dma.gpd_addr); dma_free_coherent(&pdev->dev, MAX_BD_NUM * sizeof(struct mt_bdma_desc), host->dma.bd, host->dma.bd_addr); + device_init_wakeup(&pdev->dev, false); } static void msdc_save_reg(struct msdc_host *host) @@ -3176,7 +3278,7 @@ static void msdc_restore_reg(struct msdc_host *host) __msdc_enable_sdio_irq(host, 1); } -static int __maybe_unused msdc_runtime_suspend(struct device *dev) +static int msdc_runtime_suspend(struct device *dev) { struct mmc_host *mmc = dev_get_drvdata(dev); struct msdc_host *host = mmc_priv(mmc); @@ -3198,7 +3300,7 @@ static int __maybe_unused msdc_runtime_suspend(struct device *dev) return 0; } -static int __maybe_unused msdc_runtime_resume(struct device *dev) +static int msdc_runtime_resume(struct device *dev) { struct mmc_host *mmc = dev_get_drvdata(dev); struct msdc_host *host = mmc_priv(mmc); @@ -3221,7 +3323,7 @@ static int __maybe_unused msdc_runtime_resume(struct device *dev) return 0; } -static int __maybe_unused msdc_suspend(struct device *dev) +static int msdc_suspend(struct device *dev) { struct mmc_host *mmc = dev_get_drvdata(dev); struct msdc_host *host = mmc_priv(mmc); @@ -3246,7 +3348,7 @@ static int __maybe_unused msdc_suspend(struct device *dev) return pm_runtime_force_suspend(dev); } -static int __maybe_unused msdc_resume(struct device *dev) +static int msdc_resume(struct device *dev) { struct mmc_host *mmc = dev_get_drvdata(dev); struct msdc_host *host = mmc_priv(mmc); @@ -3258,8 +3360,8 @@ static int __maybe_unused msdc_resume(struct device *dev) } static const struct dev_pm_ops msdc_dev_pm_ops = { - SET_SYSTEM_SLEEP_PM_OPS(msdc_suspend, msdc_resume) - SET_RUNTIME_PM_OPS(msdc_runtime_suspend, msdc_runtime_resume, NULL) + SYSTEM_SLEEP_PM_OPS(msdc_suspend, msdc_resume) + RUNTIME_PM_OPS(msdc_runtime_suspend, msdc_runtime_resume, NULL) }; static struct platform_driver mt_msdc_driver = { @@ -3269,7 +3371,7 @@ static struct platform_driver mt_msdc_driver = { .name = "mtk-msdc", .probe_type = PROBE_PREFER_ASYNCHRONOUS, .of_match_table = msdc_of_ids, - .pm = &msdc_dev_pm_ops, + .pm = pm_ptr(&msdc_dev_pm_ops), }, }; |
