Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 870556a3 authored by Doug Anderson's avatar Doug Anderson Committed by Chris Ball
Browse files

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: default avatarDoug Anderson <dianders@chromium.org>
Signed-off-by: default avatarChris Ball <cjb@laptop.org>
parent 0ddf03c9
Loading
Loading
Loading
Loading
+4 −0
Original line number Diff line number Diff line
@@ -55,6 +55,9 @@ Optional properties:

* broken-cd: as documented in mmc core bindings.

* vmmc-supply: The phandle to the regulator to use for vmmc.  If this is
  specified we'll defer probe until we can find this regulator.

Aliases:

- All the MSHC controller nodes should be represented in the aliases node using
@@ -79,6 +82,7 @@ board specific portions as listed below.
		broken-cd;
		fifo-depth = <0x80>;
		card-detect-delay = <200>;
		vmmc-supply = <&buck8>;

		slot@0 {
			reg = <0>;
+20 −14
Original line number Diff line number Diff line
@@ -1991,19 +1991,6 @@ static int dw_mci_init_slot(struct dw_mci *host, unsigned int id)
#endif /* CONFIG_MMC_DW_IDMAC */
	}

	host->vmmc = devm_regulator_get(mmc_dev(mmc), "vmmc");
	if (IS_ERR(host->vmmc)) {
		pr_info("%s: no vmmc regulator found\n", mmc_hostname(mmc));
		host->vmmc = NULL;
	} else {
		ret = regulator_enable(host->vmmc);
		if (ret) {
			dev_err(host->dev,
				"failed to enable regulator: %d\n", ret);
			goto err_setup_bus;
		}
	}

	if (dw_mci_get_cd(mmc))
		set_bit(DW_MMC_CARD_PRESENT, &slot->flags);
	else
@@ -2235,11 +2222,29 @@ int dw_mci_probe(struct dw_mci *host)
		}
	}

	host->vmmc = devm_regulator_get(host->dev, "vmmc");
	if (IS_ERR(host->vmmc)) {
		ret = PTR_ERR(host->vmmc);
		if (ret == -EPROBE_DEFER)
			goto err_clk_ciu;

		dev_info(host->dev, "no vmmc regulator found: %d\n", ret);
		host->vmmc = NULL;
	} else {
		ret = regulator_enable(host->vmmc);
		if (ret) {
			if (ret != -EPROBE_DEFER)
				dev_err(host->dev,
					"regulator_enable fail: %d\n", ret);
			goto err_clk_ciu;
		}
	}

	if (!host->bus_hz) {
		dev_err(host->dev,
			"Platform data must supply bus speed\n");
		ret = -ENODEV;
		goto err_clk_ciu;
		goto err_regulator;
	}

	host->quirks = host->pdata->quirks;
@@ -2386,6 +2391,7 @@ int dw_mci_probe(struct dw_mci *host)
	if (host->use_dma && host->dma_ops->exit)
		host->dma_ops->exit(host);

err_regulator:
	if (host->vmmc)
		regulator_disable(host->vmmc);