Commit 3b292bb0 authored by Ulf Hansson's avatar Ulf Hansson

mmc: tmio: Restructure ->set_ios() and adapt ->probe() to it

An internal power state machine were beeing used to keep ->probe() and
->set_ios() in sync. Especially for handling specific scenarios while
using CONFIG_MMC_CLKGATE. Moreover dependency to CONFIG_MMC_CLKGATE
existed to handle runtime PM properly, which we moves away from here.

By removing the state machine and instead make ->set_ios() rely on the
information provided through the function's in-parameters, the code
becomes significantly simplier.

Additonally as a part of this rework we prepares for making the runtime
PM callbacks responsible of clock gating.
Signed-off-by: default avatarUlf Hansson <ulf.hansson@linaro.org>
Acked-by: default avatarGeert Uytterhoeven <geert+renesas@glider.be>
parent 9ae4ed7d
......@@ -40,22 +40,6 @@
struct tmio_mmc_data;
/*
* We differentiate between the following 3 power states:
* 1. card slot powered off, controller stopped. This is used, when either there
* is no card in the slot, or the card really has to be powered down.
* 2. card slot powered on, controller stopped. This is used, when a card is in
* the slot, but no activity is currently taking place. This is a power-
* saving mode with card-state preserved. This state can be entered, e.g.
* when MMC clock-gating is used.
* 3. card slot powered on, controller running. This is the actual active state.
*/
enum tmio_mmc_power {
TMIO_MMC_OFF_STOP, /* card power off, controller stopped */
TMIO_MMC_ON_STOP, /* card power on, controller stopped */
TMIO_MMC_ON_RUN, /* card power on, controller running */
};
struct tmio_mmc_host {
void __iomem *ctl;
struct mmc_command *cmd;
......@@ -63,9 +47,6 @@ struct tmio_mmc_host {
struct mmc_data *data;
struct mmc_host *mmc;
/* Controller and card power state */
enum tmio_mmc_power power;
/* Callbacks for clock / power control */
void (*set_pwr)(struct platform_device *host, int state);
void (*set_clk_div)(struct platform_device *host, int state);
......@@ -100,7 +81,6 @@ struct tmio_mmc_host {
unsigned long last_req_ts;
struct mutex ios_lock; /* protect set_ios() context */
bool native_hotplug;
bool resuming;
bool sdio_irq_enabled;
};
......
......@@ -884,51 +884,23 @@ static void tmio_mmc_set_ios(struct mmc_host *mmc, struct mmc_ios *ios)
spin_unlock_irqrestore(&host->lock, flags);
/*
* host->power toggles between false and true in both cases - either
* or not the controller can be runtime-suspended during inactivity.
* But if the controller has to be kept on, the runtime-pm usage_count
* is kept positive, so no suspending actually takes place.
*/
if (ios->power_mode == MMC_POWER_ON && ios->clock) {
if (host->power != TMIO_MMC_ON_RUN) {
tmio_mmc_clk_update(mmc);
if (host->resuming) {
tmio_mmc_reset(host);
host->resuming = false;
}
}
if (host->power == TMIO_MMC_OFF_STOP)
tmio_mmc_reset(host);
switch (ios->power_mode) {
case MMC_POWER_OFF:
tmio_mmc_power_off(host);
tmio_mmc_clk_stop(host);
break;
case MMC_POWER_UP:
tmio_mmc_set_clock(host, ios->clock);
if (host->power == TMIO_MMC_OFF_STOP)
/* power up SD card and the bus */
tmio_mmc_power_on(host, ios->vdd);
host->power = TMIO_MMC_ON_RUN;
/* start bus clock */
tmio_mmc_power_on(host, ios->vdd);
tmio_mmc_clk_start(host);
} else if (ios->power_mode != MMC_POWER_UP) {
struct tmio_mmc_data *pdata = host->pdata;
unsigned int old_power = host->power;
if (old_power != TMIO_MMC_OFF_STOP) {
if (ios->power_mode == MMC_POWER_OFF) {
tmio_mmc_power_off(host);
host->power = TMIO_MMC_OFF_STOP;
} else {
host->power = TMIO_MMC_ON_STOP;
}
}
if (old_power == TMIO_MMC_ON_RUN) {
tmio_mmc_clk_stop(host);
if (pdata->clk_disable)
pdata->clk_disable(host->pdev);
}
}
if (host->power != TMIO_MMC_OFF_STOP)
tmio_mmc_set_bus_width(host, ios->bus_width);
break;
case MMC_POWER_ON:
tmio_mmc_set_clock(host, ios->clock);
tmio_mmc_clk_start(host);
tmio_mmc_set_bus_width(host, ios->bus_width);
break;
}
/* Let things settle. delay taken from winCE driver */
udelay(140);
......@@ -1064,7 +1036,6 @@ int tmio_mmc_host_probe(struct tmio_mmc_host **host,
mmc->caps & MMC_CAP_NONREMOVABLE ||
mmc->slot.cd_irq >= 0);
_host->power = TMIO_MMC_OFF_STOP;
if (tmio_mmc_clk_update(mmc) < 0) {
mmc->f_max = pdata->hclk;
mmc->f_min = mmc->f_max / 512;
......@@ -1116,8 +1087,6 @@ int tmio_mmc_host_probe(struct tmio_mmc_host **host,
pm_runtime_enable(&pdev->dev);
ret = mmc_add_host(mmc);
if (pdata->clk_disable)
pdata->clk_disable(pdev);
if (ret < 0) {
tmio_mmc_host_remove(_host);
return ret;
......@@ -1185,8 +1154,6 @@ int tmio_mmc_host_resume(struct device *dev)
tmio_mmc_enable_dma(host, true);
/* The MMC core will perform the complete set up */
host->resuming = true;
return 0;
}
EXPORT_SYMBOL(tmio_mmc_host_resume);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment