mmc: dw_mmc: Add normal and idle pinctrl control

normal pinctrl is used for sd working mode. idle pinctrl is
used when the card is added or removed, so pull down the
IO to avoid power leak which makes the card unable to work.

Signed-off-by: Shawn Lin <shawn.lin@rock-chips.com>
Change-Id: I8780b9de735b86918b4d5ba857711e56de740ecf
This commit is contained in:
Shawn Lin
2023-06-01 10:30:48 +08:00
committed by Tao Huang
parent 4fa6921109
commit 60c9e5240f
2 changed files with 28 additions and 0 deletions

View File

@@ -1507,6 +1507,9 @@ static void dw_mci_set_ios(struct mmc_host *mmc, struct mmc_ios *ios)
switch (ios->power_mode) {
case MMC_POWER_UP:
if (!IS_ERR_OR_NULL(slot->host->pinctrl))
pinctrl_select_state(slot->host->pinctrl, slot->host->idle_state);
if (!IS_ERR(mmc->supply.vmmc)) {
ret = mmc_regulator_set_ocr(mmc, mmc->supply.vmmc,
ios->vdd);
@@ -1523,6 +1526,9 @@ static void dw_mci_set_ios(struct mmc_host *mmc, struct mmc_ios *ios)
mci_writel(slot->host, PWREN, regs);
break;
case MMC_POWER_ON:
if (!IS_ERR_OR_NULL(slot->host->pinctrl))
pinctrl_select_state(slot->host->pinctrl, slot->host->normal_state);
if (!slot->host->vqmmc_enabled) {
if (!IS_ERR(mmc->supply.vqmmc)) {
ret = regulator_enable(mmc->supply.vqmmc);
@@ -1547,6 +1553,9 @@ static void dw_mci_set_ios(struct mmc_host *mmc, struct mmc_ios *ios)
break;
case MMC_POWER_OFF:
if (!IS_ERR_OR_NULL(slot->host->pinctrl))
pinctrl_select_state(slot->host->pinctrl, slot->host->idle_state);
/* Turn clock off before power goes down */
dw_mci_setup_bus(slot, false);
@@ -3262,6 +3271,22 @@ static struct dw_mci_board *dw_mci_parse_dt(struct dw_mci *host)
return ERR_PTR(ret);
}
host->pinctrl = devm_pinctrl_get(host->dev);
if (!IS_ERR(host->pinctrl)) {
host->normal_state = pinctrl_lookup_state(host->pinctrl, "normal");
if (IS_ERR(host->normal_state))
dev_warn(dev, "No normal pinctrl state\n");
host->idle_state = pinctrl_lookup_state(host->pinctrl, "idle");
if (IS_ERR(host->idle_state))
dev_warn(dev, "No idle pinctrl state\n");
if (!IS_ERR(host->normal_state) && !IS_ERR(host->idle_state))
pinctrl_select_state(host->pinctrl, host->idle_state);
else
host->pinctrl = NULL;
}
return pdata;
}

View File

@@ -233,6 +233,9 @@ struct dw_mci {
bool need_xfer_timer;
struct timer_list xfer_timer;
bool is_rv1106_sd;
struct pinctrl *pinctrl;
struct pinctrl_state *normal_state;
struct pinctrl_state *idle_state;
};
/* DMA ops for Internal/External DMAC interface */