From 4bdfb2729c3a396fe7400c9332c49aee2b971bd8 Mon Sep 17 00:00:00 2001 From: Mark Brown Date: Mon, 29 Jul 2013 21:00:53 +0100 Subject: regulator: core: Add missing stub for regulator_get_exclusive() Signed-off-by: Mark Brown diff --git a/include/linux/regulator/consumer.h b/include/linux/regulator/consumer.h index 3a76389..60da4a6 100644 --- a/include/linux/regulator/consumer.h +++ b/include/linux/regulator/consumer.h @@ -212,6 +212,13 @@ static inline struct regulator *__must_check regulator_get(struct device *dev, } static inline struct regulator *__must_check +regulator_get_exclusive(struct device *dev, const char *id) +{ + return NULL; +} + + +static inline struct regulator *__must_check devm_regulator_get(struct device *dev, const char *id) { return NULL; -- cgit v0.10.2 From de1dd9fd2156874b45803299b3b27e65d5defdd9 Mon Sep 17 00:00:00 2001 From: Mark Brown Date: Mon, 29 Jul 2013 21:42:42 +0100 Subject: regulator: core: Provide hints to the core about optional supplies While the majority of supplies on devices are mandatory and can't be physically omitted for electrical reasons some devices do have optional supplies and need to know if they are missing, MMC being the most common of these. Currently the core accurately reports all errors when regulators are requested since it does not know if the supply is one that must be provided even if by a regulator software does not know about or if it is one that may genuinely be disconnected. In order to allow this behaviour to be changed and stub regulators to be provided in the former case add a new regulator request function regulator_get_optional() which provides a hint to the core that the regulator may genuinely not be connected. Currently the implementation is identical to the current behaviour, future patches will add support in the core for returning stub regulators in the case where normal regulator_get() fails and the board has requested it. Signed-off-by: Mark Brown Acked-by: Chris Ball diff --git a/drivers/regulator/core.c b/drivers/regulator/core.c index 288c75a..a27a5b6 100644 --- a/drivers/regulator/core.c +++ b/drivers/regulator/core.c @@ -1409,6 +1409,65 @@ struct regulator *regulator_get_exclusive(struct device *dev, const char *id) } EXPORT_SYMBOL_GPL(regulator_get_exclusive); +/** + * regulator_get_optional - obtain optional access to a regulator. + * @dev: device for regulator "consumer" + * @id: Supply name or regulator ID. + * + * Returns a struct regulator corresponding to the regulator producer, + * or IS_ERR() condition containing errno. Other consumers will be + * unable to obtain this reference is held and the use count for the + * regulator will be initialised to reflect the current state of the + * regulator. + * + * This is intended for use by consumers for devices which can have + * some supplies unconnected in normal use, such as some MMC devices. + * It can allow the regulator core to provide stub supplies for other + * supplies requested using normal regulator_get() calls without + * disrupting the operation of drivers that can handle absent + * supplies. + * + * Use of supply names configured via regulator_set_device_supply() is + * strongly encouraged. It is recommended that the supply name used + * should match the name used for the supply and/or the relevant + * device pins in the datasheet. + */ +struct regulator *regulator_get_optional(struct device *dev, const char *id) +{ + return _regulator_get(dev, id, 0); +} +EXPORT_SYMBOL_GPL(regulator_get_optional); + +/** + * devm_regulator_get_optional - Resource managed regulator_get_optional() + * @dev: device for regulator "consumer" + * @id: Supply name or regulator ID. + * + * Managed regulator_get_optional(). Regulators returned from this + * function are automatically regulator_put() on driver detach. See + * regulator_get_optional() for more information. + */ +struct regulator *devm_regulator_get_optional(struct device *dev, + const char *id) +{ + struct regulator **ptr, *regulator; + + ptr = devres_alloc(devm_regulator_release, sizeof(*ptr), GFP_KERNEL); + if (!ptr) + return ERR_PTR(-ENOMEM); + + regulator = regulator_get_optional(dev, id); + if (!IS_ERR(regulator)) { + *ptr = regulator; + devres_add(dev, ptr); + } else { + devres_free(ptr); + } + + return regulator; +} +EXPORT_SYMBOL_GPL(devm_regulator_get_optional); + /* Locks held by regulator_put() */ static void _regulator_put(struct regulator *regulator) { diff --git a/include/linux/regulator/consumer.h b/include/linux/regulator/consumer.h index 60da4a6..e2bac6d 100644 --- a/include/linux/regulator/consumer.h +++ b/include/linux/regulator/consumer.h @@ -137,6 +137,10 @@ struct regulator *__must_check devm_regulator_get(struct device *dev, const char *id); struct regulator *__must_check regulator_get_exclusive(struct device *dev, const char *id); +struct regulator *__must_check regulator_get_optional(struct device *dev, + const char *id); +struct regulator *__must_check devm_regulator_get_optional(struct device *dev, + const char *id); void regulator_put(struct regulator *regulator); void devm_regulator_put(struct regulator *regulator); @@ -212,14 +216,26 @@ static inline struct regulator *__must_check regulator_get(struct device *dev, } static inline struct regulator *__must_check +devm_regulator_get(struct device *dev, const char *id) +{ + return NULL; +} + +static inline struct regulator *__must_check regulator_get_exclusive(struct device *dev, const char *id) { return NULL; } +static inline struct regulator *__must_check +regulator_get_optional(struct device *dev, const char *id) +{ + return NULL; +} + static inline struct regulator *__must_check -devm_regulator_get(struct device *dev, const char *id) +devm_regulator_get_optional(struct device *dev, const char *id) { return NULL; } -- cgit v0.10.2 From bc35d5ed5d14e63a4d6018098a129196ba4c44ae Mon Sep 17 00:00:00 2001 From: Mark Brown Date: Mon, 29 Jul 2013 21:58:01 +0100 Subject: mmc: core: Indicate that vmmcq may be absent Use regulator_get_optional() to tell the core that requests for the vmmcq regulator can fail in a real system. Signed-off-by: Mark Brown Acked-by: Chris Ball diff --git a/drivers/mmc/core/core.c b/drivers/mmc/core/core.c index 49a5bca..5d08855 100644 --- a/drivers/mmc/core/core.c +++ b/drivers/mmc/core/core.c @@ -1313,7 +1313,7 @@ int mmc_regulator_get_supply(struct mmc_host *mmc) supply = devm_regulator_get(dev, "vmmc"); mmc->supply.vmmc = supply; - mmc->supply.vqmmc = devm_regulator_get(dev, "vqmmc"); + mmc->supply.vqmmc = devm_regulator_get_optional(dev, "vqmmc"); if (IS_ERR(supply)) return PTR_ERR(supply); -- cgit v0.10.2 From 462849aad50fced728d82a2ddba1b9d348e32f67 Mon Sep 17 00:00:00 2001 From: Mark Brown Date: Mon, 29 Jul 2013 21:52:55 +0100 Subject: mmc: sdhci: Indicate that regulators may be absent Use regulator_get_optional() to tell the core that requests for regulators can fail in a real system. Signed-off-by: Mark Brown Acked-by: Chris Ball diff --git a/drivers/mmc/host/sdhci.c b/drivers/mmc/host/sdhci.c index a78bd4f..dd2c083 100644 --- a/drivers/mmc/host/sdhci.c +++ b/drivers/mmc/host/sdhci.c @@ -2966,7 +2966,7 @@ int sdhci_add_host(struct sdhci_host *host) mmc->caps |= MMC_CAP_NEEDS_POLL; /* If vqmmc regulator and no 1.8V signalling, then there's no UHS */ - host->vqmmc = regulator_get(mmc_dev(mmc), "vqmmc"); + host->vqmmc = regulator_get_optional(mmc_dev(mmc), "vqmmc"); if (IS_ERR_OR_NULL(host->vqmmc)) { if (PTR_ERR(host->vqmmc) < 0) { pr_info("%s: no vqmmc regulator found\n", @@ -3042,7 +3042,7 @@ int sdhci_add_host(struct sdhci_host *host) ocr_avail = 0; - host->vmmc = regulator_get(mmc_dev(mmc), "vmmc"); + host->vmmc = regulator_get_optional(mmc_dev(mmc), "vmmc"); if (IS_ERR_OR_NULL(host->vmmc)) { if (PTR_ERR(host->vmmc) < 0) { pr_info("%s: no vmmc regulator found\n", -- cgit v0.10.2 From a55d6ff0ed169fe2cf4bcdd81049c3c2041a7465 Mon Sep 17 00:00:00 2001 From: Mark Brown Date: Mon, 29 Jul 2013 21:55:27 +0100 Subject: mmc: dw_mmc: Indicate that regulators may be absent Use regulator_get_optional() to tell the core that requests for regulators can fail in a real system. Signed-off-by: Mark Brown Acked-by: Chris Ball Acked-by: Seungwon Jeon Acked-by: Jaehoon Chung diff --git a/drivers/mmc/host/dw_mmc.c b/drivers/mmc/host/dw_mmc.c index ee5f167..5424073 100644 --- a/drivers/mmc/host/dw_mmc.c +++ b/drivers/mmc/host/dw_mmc.c @@ -2231,7 +2231,7 @@ int dw_mci_probe(struct dw_mci *host) } } - host->vmmc = devm_regulator_get(host->dev, "vmmc"); + host->vmmc = devm_regulator_get_optional(host->dev, "vmmc"); if (IS_ERR(host->vmmc)) { ret = PTR_ERR(host->vmmc); if (ret == -EPROBE_DEFER) -- cgit v0.10.2 From 6ae8717a4897d776097c5c2578a907d3c59b1e9f Mon Sep 17 00:00:00 2001 From: Mark Brown Date: Mon, 29 Jul 2013 21:55:40 +0100 Subject: mmc: pxamci: Indicate that regulators may be absent Use regulator_get_optional() to tell the core that requests for regulators can fail in a real system. Signed-off-by: Mark Brown Acked-by: Chris Ball diff --git a/drivers/mmc/host/pxamci.c b/drivers/mmc/host/pxamci.c index 2c5a91b..1956a3d 100644 --- a/drivers/mmc/host/pxamci.c +++ b/drivers/mmc/host/pxamci.c @@ -83,7 +83,7 @@ struct pxamci_host { static inline void pxamci_init_ocr(struct pxamci_host *host) { #ifdef CONFIG_REGULATOR - host->vcc = regulator_get(mmc_dev(host->mmc), "vmmc"); + host->vcc = regulator_get_optional(mmc_dev(host->mmc), "vmmc"); if (IS_ERR(host->vcc)) host->vcc = NULL; -- cgit v0.10.2 From 7d748971c0c04122cc7a06bc0573e27e106efe6a Mon Sep 17 00:00:00 2001 From: Mark Brown Date: Fri, 9 Aug 2013 19:07:12 +0100 Subject: cpufreq: cpufreq-cpu0: Use devm_regulator_get_optional() Since the cpufreq-cpu0 driver is capable of coping without a software controllable regulator and would be confused by a dummy one it should use devm_regulator_get_optional() to ensure no dummy is provided. Signed-off-by: Mark Brown diff --git a/drivers/cpufreq/cpufreq-cpu0.c b/drivers/cpufreq/cpufreq-cpu0.c index ad1fde2..e9dedb2 100644 --- a/drivers/cpufreq/cpufreq-cpu0.c +++ b/drivers/cpufreq/cpufreq-cpu0.c @@ -197,7 +197,7 @@ static int cpu0_cpufreq_probe(struct platform_device *pdev) cpu_dev = &pdev->dev; cpu_dev->of_node = np; - cpu_reg = devm_regulator_get(cpu_dev, "cpu0"); + cpu_reg = devm_regulator_get_optional(cpu_dev, "cpu0"); if (IS_ERR(cpu_reg)) { /* * If cpu0 regulator supply node is present, but regulator is -- cgit v0.10.2 From 9e059bacecf1c46c1784cb6f6826f85629b4a1be Mon Sep 17 00:00:00 2001 From: Mark Brown Date: Sun, 18 Aug 2013 17:35:52 +0100 Subject: hwmon: (sht15) Use devm_regulator_get_optional() Since the sht15 driver supports operation without an external vref regulator the driver should use the new devm_regulator_get_optional() to indicate that a stub regulator should not be provided. Signed-off-by: Mark Brown Acked-by: Guenter Roeck diff --git a/drivers/hwmon/sht15.c b/drivers/hwmon/sht15.c index 2507f90..ab5dc3a 100644 --- a/drivers/hwmon/sht15.c +++ b/drivers/hwmon/sht15.c @@ -957,7 +957,7 @@ static int sht15_probe(struct platform_device *pdev) * If a regulator is available, * query what the supply voltage actually is! */ - data->reg = devm_regulator_get(data->dev, "vcc"); + data->reg = devm_regulator_get_optional(data->dev, "vcc"); if (!IS_ERR(data->reg)) { int voltage; -- cgit v0.10.2 From 9efdd27678ef5e22c27c230a08a211b702768f3a Mon Sep 17 00:00:00 2001 From: Matthias Kaehlcke Date: Sun, 25 Aug 2013 17:54:13 +0200 Subject: regulator: Add devm_regulator_get_exclusive() Add a resource managed regulator_get_exclusive() Signed-off-by: Matthias Kaehlcke Signed-off-by: Mark Brown diff --git a/drivers/regulator/core.c b/drivers/regulator/core.c index a27a5b6..4b9039b 100644 --- a/drivers/regulator/core.c +++ b/drivers/regulator/core.c @@ -1494,6 +1494,36 @@ static void _regulator_put(struct regulator *regulator) } /** + * devm_regulator_get_exclusive - Resource managed regulator_get_exclusive() + * @dev: device for regulator "consumer" + * @id: Supply name or regulator ID. + * + * Managed regulator_get_exclusive(). Regulators returned from this function + * are automatically regulator_put() on driver detach. See regulator_get() for + * more information. + */ +struct regulator *devm_regulator_get_exclusive(struct device *dev, + const char *id) +{ + struct regulator **ptr, *regulator; + + ptr = devres_alloc(devm_regulator_release, sizeof(*ptr), GFP_KERNEL); + if (!ptr) + return ERR_PTR(-ENOMEM); + + regulator = _regulator_get(dev, id, 1); + if (!IS_ERR(regulator)) { + *ptr = regulator; + devres_add(dev, ptr); + } else { + devres_free(ptr); + } + + return regulator; +} +EXPORT_SYMBOL_GPL(devm_regulator_get_exclusive); + +/** * regulator_put - "free" the regulator source * @regulator: regulator source * diff --git a/include/linux/regulator/consumer.h b/include/linux/regulator/consumer.h index e2bac6d..91aca11 100644 --- a/include/linux/regulator/consumer.h +++ b/include/linux/regulator/consumer.h @@ -137,6 +137,8 @@ struct regulator *__must_check devm_regulator_get(struct device *dev, const char *id); struct regulator *__must_check regulator_get_exclusive(struct device *dev, const char *id); +struct regulator *__must_check devm_regulator_get_exclusive(struct device *dev, + const char *id); struct regulator *__must_check regulator_get_optional(struct device *dev, const char *id); struct regulator *__must_check devm_regulator_get_optional(struct device *dev, -- cgit v0.10.2