diff options
author | Doug Anderson <dianders@chromium.org> | 2013-06-07 13:28:29 -0400 |
---|---|---|
committer | Chris Ball <cjb@laptop.org> | 2013-06-27 12:39:06 -0400 |
commit | 870556a3dfb16d004f8e09dd59a1eddc727fcf0c (patch) | |
tree | 54c95bbaea975ad8cc85137fb6d72ec8b8f1f12b /drivers/mmc/host/dw_mmc.c | |
parent | 0ddf03c95bbb4f4ed57281fa7b781472950df749 (diff) |
mmc: dw_mmc: Handle late vmmc regulators with EPROBE_DEFER
It is possible to specify a regulator that should be turned on when
dw_mmc is probed. At the moment dw_mmc will fail to use the regulator
properly if the regulator probes after dw_mmc. Fix this problem by
honoring EPROBE_DEFER.
At the same time move the regulator code out of the slot init code.
We only specify one regulator for the whole device and other parts of
the code (like suspend/resume) assume that the regulator has only been
enabled once.
Signed-off-by: Doug Anderson <dianders@chromium.org>
Signed-off-by: Chris Ball <cjb@laptop.org>
Diffstat (limited to 'drivers/mmc/host/dw_mmc.c')
-rw-r--r-- | drivers/mmc/host/dw_mmc.c | 34 |
1 files changed, 20 insertions, 14 deletions
diff --git a/drivers/mmc/host/dw_mmc.c b/drivers/mmc/host/dw_mmc.c index 7dca5e92dcb4..957f5d7ea426 100644 --- a/drivers/mmc/host/dw_mmc.c +++ b/drivers/mmc/host/dw_mmc.c | |||
@@ -1991,19 +1991,6 @@ static int dw_mci_init_slot(struct dw_mci *host, unsigned int id) | |||
1991 | #endif /* CONFIG_MMC_DW_IDMAC */ | 1991 | #endif /* CONFIG_MMC_DW_IDMAC */ |
1992 | } | 1992 | } |
1993 | 1993 | ||
1994 | host->vmmc = devm_regulator_get(mmc_dev(mmc), "vmmc"); | ||
1995 | if (IS_ERR(host->vmmc)) { | ||
1996 | pr_info("%s: no vmmc regulator found\n", mmc_hostname(mmc)); | ||
1997 | host->vmmc = NULL; | ||
1998 | } else { | ||
1999 | ret = regulator_enable(host->vmmc); | ||
2000 | if (ret) { | ||
2001 | dev_err(host->dev, | ||
2002 | "failed to enable regulator: %d\n", ret); | ||
2003 | goto err_setup_bus; | ||
2004 | } | ||
2005 | } | ||
2006 | |||
2007 | if (dw_mci_get_cd(mmc)) | 1994 | if (dw_mci_get_cd(mmc)) |
2008 | set_bit(DW_MMC_CARD_PRESENT, &slot->flags); | 1995 | set_bit(DW_MMC_CARD_PRESENT, &slot->flags); |
2009 | else | 1996 | else |
@@ -2235,11 +2222,29 @@ int dw_mci_probe(struct dw_mci *host) | |||
2235 | } | 2222 | } |
2236 | } | 2223 | } |
2237 | 2224 | ||
2225 | host->vmmc = devm_regulator_get(host->dev, "vmmc"); | ||
2226 | if (IS_ERR(host->vmmc)) { | ||
2227 | ret = PTR_ERR(host->vmmc); | ||
2228 | if (ret == -EPROBE_DEFER) | ||
2229 | goto err_clk_ciu; | ||
2230 | |||
2231 | dev_info(host->dev, "no vmmc regulator found: %d\n", ret); | ||
2232 | host->vmmc = NULL; | ||
2233 | } else { | ||
2234 | ret = regulator_enable(host->vmmc); | ||
2235 | if (ret) { | ||
2236 | if (ret != -EPROBE_DEFER) | ||
2237 | dev_err(host->dev, | ||
2238 | "regulator_enable fail: %d\n", ret); | ||
2239 | goto err_clk_ciu; | ||
2240 | } | ||
2241 | } | ||
2242 | |||
2238 | if (!host->bus_hz) { | 2243 | if (!host->bus_hz) { |
2239 | dev_err(host->dev, | 2244 | dev_err(host->dev, |
2240 | "Platform data must supply bus speed\n"); | 2245 | "Platform data must supply bus speed\n"); |
2241 | ret = -ENODEV; | 2246 | ret = -ENODEV; |
2242 | goto err_clk_ciu; | 2247 | goto err_regulator; |
2243 | } | 2248 | } |
2244 | 2249 | ||
2245 | host->quirks = host->pdata->quirks; | 2250 | host->quirks = host->pdata->quirks; |
@@ -2386,6 +2391,7 @@ err_dmaunmap: | |||
2386 | if (host->use_dma && host->dma_ops->exit) | 2391 | if (host->use_dma && host->dma_ops->exit) |
2387 | host->dma_ops->exit(host); | 2392 | host->dma_ops->exit(host); |
2388 | 2393 | ||
2394 | err_regulator: | ||
2389 | if (host->vmmc) | 2395 | if (host->vmmc) |
2390 | regulator_disable(host->vmmc); | 2396 | regulator_disable(host->vmmc); |
2391 | 2397 | ||