mirror of
https://github.com/hardkernel/linux.git
synced 2026-06-06 19:08:57 +09:00
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:
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
@@ -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 */
|
||||
|
||||
Reference in New Issue
Block a user