diff options
Diffstat (limited to 'drivers')
-rw-r--r-- | drivers/mmc/host/dw_mmc-k3.c | 13 | ||||
-rw-r--r-- | drivers/mmc/host/dw_mmc.c | 41 |
2 files changed, 46 insertions, 8 deletions
diff --git a/drivers/mmc/host/dw_mmc-k3.c b/drivers/mmc/host/dw_mmc-k3.c index 63c2e2ed1288..6aa6d0d63f7f 100644 --- a/drivers/mmc/host/dw_mmc-k3.c +++ b/drivers/mmc/host/dw_mmc-k3.c @@ -32,6 +32,12 @@ struct k3_priv { struct regmap *reg; }; +static unsigned long dw_mci_hi6220_caps[] = { + MMC_CAP_CMD23, + MMC_CAP_CMD23, + 0 +}; + static void dw_mci_k3_set_ios(struct dw_mci *host, struct mmc_ios *ios) { int ret; @@ -125,10 +131,17 @@ static void dw_mci_hi6220_set_ios(struct dw_mci *host, struct mmc_ios *ios) host->bus_hz = clk_get_rate(host->biu_clk); } +static void dw_mci_hi6220_prepare_command(struct dw_mci *host, u32 *cmdr) +{ + *cmdr |= SDMMC_CMD_USE_HOLD_REG; +} + static const struct dw_mci_drv_data hi6220_data = { + .caps = dw_mci_hi6220_caps, .switch_voltage = dw_mci_hi6220_switch_voltage, .set_ios = dw_mci_hi6220_set_ios, .parse_dt = dw_mci_hi6220_parse_dt, + .prepare_command = dw_mci_hi6220_prepare_command, }; static const struct of_device_id dw_mci_k3_match[] = { diff --git a/drivers/mmc/host/dw_mmc.c b/drivers/mmc/host/dw_mmc.c index fb204ee6ff89..900a4941eab5 100644 --- a/drivers/mmc/host/dw_mmc.c +++ b/drivers/mmc/host/dw_mmc.c @@ -250,7 +250,7 @@ static u32 dw_mci_prepare_command(struct mmc_host *mmc, struct mmc_command *cmd) cmdr |= SDMMC_CMD_PRV_DAT_WAIT; if (cmd->opcode == SD_SWITCH_VOLTAGE) { - u32 clk_en_a; + /*u32 clk_en_a;*/ /* Special bit makes CMD11 not die */ cmdr |= SDMMC_CMD_VOLT_SWITCH; @@ -270,11 +270,11 @@ static u32 dw_mci_prepare_command(struct mmc_host *mmc, struct mmc_command *cmd) * ever called with a non-zero clock. That shouldn't happen * until the voltage change is all done. */ - clk_en_a = mci_readl(host, CLKENA); - clk_en_a &= ~(SDMMC_CLKEN_LOW_PWR << slot->id); - mci_writel(host, CLKENA, clk_en_a); - mci_send_cmd(slot, SDMMC_CMD_UPD_CLK | - SDMMC_CMD_PRV_DAT_WAIT, 0); + /*clk_en_a = mci_readl(host, CLKENA);*/ + /*clk_en_a &= ~(SDMMC_CLKEN_LOW_PWR << slot->id);*/ + /*mci_writel(host, CLKENA, clk_en_a);*/ + /*mci_send_cmd(slot, SDMMC_CMD_UPD_CLK |*/ + /*SDMMC_CMD_PRV_DAT_WAIT, 0);*/ } if (cmd->flags & MMC_RSP_PRESENT) { @@ -1124,7 +1124,7 @@ static void dw_mci_setup_bus(struct dw_mci_slot *slot, bool force_clkinit) /* enable clock; only low power if no SDIO */ clk_en_a = SDMMC_CLKEN_ENABLE << slot->id; - if (!test_bit(DW_MMC_CARD_NO_LOW_PWR, &slot->flags)) + if (!test_bit(DW_MMC_CARD_NO_LOW_PWR, &slot->flags) && (slot->mmc->index != 1)) clk_en_a |= SDMMC_CLKEN_LOW_PWR << slot->id; mci_writel(host, CLKENA, clk_en_a); @@ -1298,6 +1298,8 @@ static void dw_mci_set_ios(struct mmc_host *mmc, struct mmc_ios *ios) regs |= ((0x1 << slot->id) << 16); else regs &= ~((0x1 << slot->id) << 16); + if (mmc->index == 1) + regs |= (0x1 << slot->id); mci_writel(slot->host, UHS_REG, regs); slot->host->timing = ios->timing; @@ -1540,6 +1542,8 @@ static int dw_mci_execute_tuning(struct mmc_host *mmc, u32 opcode) if (drv_data && drv_data->execute_tuning) err = drv_data->execute_tuning(slot, opcode); + else + err = 0; return err; } @@ -2879,6 +2883,15 @@ static struct dw_mci_board *dw_mci_parse_dt(struct dw_mci *host) if (!pdata) return ERR_PTR(-ENOMEM); + /* find reset controller when exist */ + pdata->rstc = devm_reset_control_get_optional(dev, NULL); + if (IS_ERR(pdata->rstc)) { + if (PTR_ERR(pdata->rstc) == -EPROBE_DEFER) + return ERR_PTR(-EPROBE_DEFER); + else + pdata->rstc = NULL; + } + /* find out number of slots supported */ if (of_property_read_u32(dev->of_node, "num-slots", &pdata->num_slots)) { @@ -2959,7 +2972,9 @@ int dw_mci_probe(struct dw_mci *host) if (!host->pdata) { host->pdata = dw_mci_parse_dt(host); - if (IS_ERR(host->pdata)) { + if (PTR_ERR(host->pdata) == -EPROBE_DEFER) + return -EPROBE_DEFER; + else if (IS_ERR(host->pdata)) { dev_err(host->dev, "platform data not available\n"); return -EINVAL; } @@ -3028,6 +3043,9 @@ int dw_mci_probe(struct dw_mci *host) } } + if (host->pdata->rstc != NULL) + reset_control_deassert(host->pdata->rstc); + setup_timer(&host->cmd11_timer, dw_mci_cmd11_timer, (unsigned long)host); @@ -3174,6 +3192,9 @@ err_dmaunmap: if (host->use_dma && host->dma_ops->exit) host->dma_ops->exit(host); + if (host->pdata->rstc != NULL) + reset_control_assert(host->pdata->rstc); + err_clk_ciu: if (!IS_ERR(host->ciu_clk)) clk_disable_unprepare(host->ciu_clk); @@ -3206,11 +3227,15 @@ void dw_mci_remove(struct dw_mci *host) if (host->use_dma && host->dma_ops->exit) host->dma_ops->exit(host); + if (host->pdata->rstc != NULL) + reset_control_assert(host->pdata->rstc); + if (!IS_ERR(host->ciu_clk)) clk_disable_unprepare(host->ciu_clk); if (!IS_ERR(host->biu_clk)) clk_disable_unprepare(host->biu_clk); + } EXPORT_SYMBOL(dw_mci_remove); |