12874c5fdSThomas Gleixner // SPDX-License-Identifier: GPL-2.0-or-later 2f2c6203fSMark Brown // 3f2c6203fSMark Brown // core.c -- Voltage/Current Regulator framework. 4f2c6203fSMark Brown // 5f2c6203fSMark Brown // Copyright 2007, 2008 Wolfson Microelectronics PLC. 6f2c6203fSMark Brown // Copyright 2008 SlimLogic Ltd. 7f2c6203fSMark Brown // 8f2c6203fSMark Brown // Author: Liam Girdwood <lrg@slimlogic.co.uk> 9414c70cbSLiam Girdwood 10414c70cbSLiam Girdwood #include <linux/kernel.h> 11414c70cbSLiam Girdwood #include <linux/init.h> 121130e5b3SMark Brown #include <linux/debugfs.h> 13414c70cbSLiam Girdwood #include <linux/device.h> 145a0e3ad6STejun Heo #include <linux/slab.h> 15f21e0e81SMark Brown #include <linux/async.h> 16414c70cbSLiam Girdwood #include <linux/err.h> 17414c70cbSLiam Girdwood #include <linux/mutex.h> 18414c70cbSLiam Girdwood #include <linux/suspend.h> 1931aae2beSMark Brown #include <linux/delay.h> 20778b28b4SRussell King #include <linux/gpio/consumer.h> 2169511a45SRajendra Nayak #include <linux/of.h> 2265b19ce6SMark Brown #include <linux/regmap.h> 2369511a45SRajendra Nayak #include <linux/regulator/of_regulator.h> 24414c70cbSLiam Girdwood #include <linux/regulator/consumer.h> 25d8ca7d18SDmitry Osipenko #include <linux/regulator/coupler.h> 26414c70cbSLiam Girdwood #include <linux/regulator/driver.h> 27414c70cbSLiam Girdwood #include <linux/regulator/machine.h> 2865602c32SPaul Gortmaker #include <linux/module.h> 29414c70cbSLiam Girdwood 3002fa3ec0SMark Brown #define CREATE_TRACE_POINTS 3102fa3ec0SMark Brown #include <trace/events/regulator.h> 3202fa3ec0SMark Brown 3334abbd68SMark Brown #include "dummy.h" 340cdfcc0fSMark Brown #include "internal.h" 3534abbd68SMark Brown 367d51a0dbSMark Brown #define rdev_crit(rdev, fmt, ...) \ 377d51a0dbSMark Brown pr_crit("%s: " fmt, rdev_get_name(rdev), ##__VA_ARGS__) 385da84fd9SJoe Perches #define rdev_err(rdev, fmt, ...) \ 395da84fd9SJoe Perches pr_err("%s: " fmt, rdev_get_name(rdev), ##__VA_ARGS__) 405da84fd9SJoe Perches #define rdev_warn(rdev, fmt, ...) \ 415da84fd9SJoe Perches pr_warn("%s: " fmt, rdev_get_name(rdev), ##__VA_ARGS__) 425da84fd9SJoe Perches #define rdev_info(rdev, fmt, ...) \ 435da84fd9SJoe Perches pr_info("%s: " fmt, rdev_get_name(rdev), ##__VA_ARGS__) 445da84fd9SJoe Perches #define rdev_dbg(rdev, fmt, ...) \ 455da84fd9SJoe Perches pr_debug("%s: " fmt, rdev_get_name(rdev), ##__VA_ARGS__) 465da84fd9SJoe Perches 47f8702f9eSDmitry Osipenko static DEFINE_WW_CLASS(regulator_ww_class); 48f8702f9eSDmitry Osipenko static DEFINE_MUTEX(regulator_nesting_mutex); 49414c70cbSLiam Girdwood static DEFINE_MUTEX(regulator_list_mutex); 50414c70cbSLiam Girdwood static LIST_HEAD(regulator_map_list); 51f19b00daSKim, Milo static LIST_HEAD(regulator_ena_gpio_list); 52a06ccd9cSCharles Keepax static LIST_HEAD(regulator_supply_alias_list); 53d8ca7d18SDmitry Osipenko static LIST_HEAD(regulator_coupler_list); 5421cf891aSMark Brown static bool has_full_constraints; 55414c70cbSLiam Girdwood 561130e5b3SMark Brown static struct dentry *debugfs_root; 571130e5b3SMark Brown 588dc5390dSMark Brown /* 59414c70cbSLiam Girdwood * struct regulator_map 60414c70cbSLiam Girdwood * 61414c70cbSLiam Girdwood * Used to provide symbolic supply names to devices. 62414c70cbSLiam Girdwood */ 63414c70cbSLiam Girdwood struct regulator_map { 64414c70cbSLiam Girdwood struct list_head list; 6540f9244fSMark Brown const char *dev_name; /* The dev_name() for the consumer */ 66414c70cbSLiam Girdwood const char *supply; 67a5766f11SLiam Girdwood struct regulator_dev *regulator; 68414c70cbSLiam Girdwood }; 69414c70cbSLiam Girdwood 70414c70cbSLiam Girdwood /* 71f19b00daSKim, Milo * struct regulator_enable_gpio 72f19b00daSKim, Milo * 73f19b00daSKim, Milo * Management for shared enable GPIO pin 74f19b00daSKim, Milo */ 75f19b00daSKim, Milo struct regulator_enable_gpio { 76f19b00daSKim, Milo struct list_head list; 77778b28b4SRussell King struct gpio_desc *gpiod; 78f19b00daSKim, Milo u32 enable_count; /* a number of enabled shared GPIO */ 79f19b00daSKim, Milo u32 request_count; /* a number of requested shared GPIO */ 80f19b00daSKim, Milo }; 81f19b00daSKim, Milo 82a06ccd9cSCharles Keepax /* 83a06ccd9cSCharles Keepax * struct regulator_supply_alias 84a06ccd9cSCharles Keepax * 85a06ccd9cSCharles Keepax * Used to map lookups for a supply onto an alternative device. 86a06ccd9cSCharles Keepax */ 87a06ccd9cSCharles Keepax struct regulator_supply_alias { 88a06ccd9cSCharles Keepax struct list_head list; 89a06ccd9cSCharles Keepax struct device *src_dev; 90a06ccd9cSCharles Keepax const char *src_supply; 91a06ccd9cSCharles Keepax struct device *alias_dev; 92a06ccd9cSCharles Keepax const char *alias_supply; 93a06ccd9cSCharles Keepax }; 94a06ccd9cSCharles Keepax 95414c70cbSLiam Girdwood static int _regulator_is_enabled(struct regulator_dev *rdev); 965451781dSDouglas Anderson static int _regulator_disable(struct regulator *regulator); 97414c70cbSLiam Girdwood static int _regulator_get_current_limit(struct regulator_dev *rdev); 98414c70cbSLiam Girdwood static unsigned int _regulator_get_mode(struct regulator_dev *rdev); 997179569aSHeiko Stübner static int _notifier_call_chain(struct regulator_dev *rdev, 100414c70cbSLiam Girdwood unsigned long event, void *data); 10175790251SMark Brown static int _regulator_do_set_voltage(struct regulator_dev *rdev, 10275790251SMark Brown int min_uV, int max_uV); 103c054c6c7SMaciej Purski static int regulator_balance_voltage(struct regulator_dev *rdev, 104c054c6c7SMaciej Purski suspend_state_t state); 1053801b86aSMark Brown static struct regulator *create_regulator(struct regulator_dev *rdev, 1063801b86aSMark Brown struct device *dev, 1073801b86aSMark Brown const char *supply_name); 108e1794aa4SSaravana Kannan static void destroy_regulator(struct regulator *regulator); 10936a1f1b6SJavier Martinez Canillas static void _regulator_put(struct regulator *regulator); 110414c70cbSLiam Girdwood 111d22b85a1SDmitry Osipenko const char *rdev_get_name(struct regulator_dev *rdev) 1121083c393SMark Brown { 1131083c393SMark Brown if (rdev->constraints && rdev->constraints->name) 1141083c393SMark Brown return rdev->constraints->name; 1151083c393SMark Brown else if (rdev->desc->name) 1161083c393SMark Brown return rdev->desc->name; 1171083c393SMark Brown else 1181083c393SMark Brown return ""; 1191083c393SMark Brown } 1201083c393SMark Brown 12187b28417SMark Brown static bool have_full_constraints(void) 12287b28417SMark Brown { 12375bc9641SMark Brown return has_full_constraints || of_have_populated_dt(); 12487b28417SMark Brown } 12587b28417SMark Brown 1268a34e979SWEN Pingbo static bool regulator_ops_is_valid(struct regulator_dev *rdev, int ops) 1278a34e979SWEN Pingbo { 1288a34e979SWEN Pingbo if (!rdev->constraints) { 1298a34e979SWEN Pingbo rdev_err(rdev, "no constraints\n"); 1308a34e979SWEN Pingbo return false; 1318a34e979SWEN Pingbo } 1328a34e979SWEN Pingbo 1338a34e979SWEN Pingbo if (rdev->constraints->valid_ops_mask & ops) 1348a34e979SWEN Pingbo return true; 1358a34e979SWEN Pingbo 1368a34e979SWEN Pingbo return false; 1378a34e979SWEN Pingbo } 1388a34e979SWEN Pingbo 13969511a45SRajendra Nayak /** 14066cf9a7eSMaciej Purski * regulator_lock_nested - lock a single regulator 14166cf9a7eSMaciej Purski * @rdev: regulator source 142f8702f9eSDmitry Osipenko * @ww_ctx: w/w mutex acquire context 14366cf9a7eSMaciej Purski * 14466cf9a7eSMaciej Purski * This function can be called many times by one task on 14566cf9a7eSMaciej Purski * a single regulator and its mutex will be locked only 14666cf9a7eSMaciej Purski * once. If a task, which is calling this function is other 14766cf9a7eSMaciej Purski * than the one, which initially locked the mutex, it will 14866cf9a7eSMaciej Purski * wait on mutex. 14966cf9a7eSMaciej Purski */ 150f8702f9eSDmitry Osipenko static inline int regulator_lock_nested(struct regulator_dev *rdev, 151f8702f9eSDmitry Osipenko struct ww_acquire_ctx *ww_ctx) 15266cf9a7eSMaciej Purski { 153f8702f9eSDmitry Osipenko bool lock = false; 154f8702f9eSDmitry Osipenko int ret = 0; 155f8702f9eSDmitry Osipenko 156f8702f9eSDmitry Osipenko mutex_lock(®ulator_nesting_mutex); 157f8702f9eSDmitry Osipenko 158f8702f9eSDmitry Osipenko if (ww_ctx || !ww_mutex_trylock(&rdev->mutex)) { 159f8702f9eSDmitry Osipenko if (rdev->mutex_owner == current) 16066cf9a7eSMaciej Purski rdev->ref_cnt++; 161f8702f9eSDmitry Osipenko else 162f8702f9eSDmitry Osipenko lock = true; 163f8702f9eSDmitry Osipenko 164f8702f9eSDmitry Osipenko if (lock) { 165f8702f9eSDmitry Osipenko mutex_unlock(®ulator_nesting_mutex); 166f8702f9eSDmitry Osipenko ret = ww_mutex_lock(&rdev->mutex, ww_ctx); 167f8702f9eSDmitry Osipenko mutex_lock(®ulator_nesting_mutex); 16866cf9a7eSMaciej Purski } 169f8702f9eSDmitry Osipenko } else { 170f8702f9eSDmitry Osipenko lock = true; 17166cf9a7eSMaciej Purski } 17266cf9a7eSMaciej Purski 173f8702f9eSDmitry Osipenko if (lock && ret != -EDEADLK) { 174f8702f9eSDmitry Osipenko rdev->ref_cnt++; 17566cf9a7eSMaciej Purski rdev->mutex_owner = current; 17666cf9a7eSMaciej Purski } 17766cf9a7eSMaciej Purski 178f8702f9eSDmitry Osipenko mutex_unlock(®ulator_nesting_mutex); 179f8702f9eSDmitry Osipenko 180f8702f9eSDmitry Osipenko return ret; 181f8702f9eSDmitry Osipenko } 182f8702f9eSDmitry Osipenko 183f8702f9eSDmitry Osipenko /** 184f8702f9eSDmitry Osipenko * regulator_lock - lock a single regulator 185f8702f9eSDmitry Osipenko * @rdev: regulator source 186f8702f9eSDmitry Osipenko * 187f8702f9eSDmitry Osipenko * This function can be called many times by one task on 188f8702f9eSDmitry Osipenko * a single regulator and its mutex will be locked only 189f8702f9eSDmitry Osipenko * once. If a task, which is calling this function is other 190f8702f9eSDmitry Osipenko * than the one, which initially locked the mutex, it will 191f8702f9eSDmitry Osipenko * wait on mutex. 192f8702f9eSDmitry Osipenko */ 1934c9db393SMichał Mirosław static void regulator_lock(struct regulator_dev *rdev) 19466cf9a7eSMaciej Purski { 195f8702f9eSDmitry Osipenko regulator_lock_nested(rdev, NULL); 19666cf9a7eSMaciej Purski } 19766cf9a7eSMaciej Purski 19866cf9a7eSMaciej Purski /** 19966cf9a7eSMaciej Purski * regulator_unlock - unlock a single regulator 20066cf9a7eSMaciej Purski * @rdev: regulator_source 20166cf9a7eSMaciej Purski * 20266cf9a7eSMaciej Purski * This function unlocks the mutex when the 20366cf9a7eSMaciej Purski * reference counter reaches 0. 20466cf9a7eSMaciej Purski */ 2054c9db393SMichał Mirosław static void regulator_unlock(struct regulator_dev *rdev) 20666cf9a7eSMaciej Purski { 207f8702f9eSDmitry Osipenko mutex_lock(®ulator_nesting_mutex); 20866cf9a7eSMaciej Purski 209f8702f9eSDmitry Osipenko if (--rdev->ref_cnt == 0) { 21066cf9a7eSMaciej Purski rdev->mutex_owner = NULL; 211f8702f9eSDmitry Osipenko ww_mutex_unlock(&rdev->mutex); 21266cf9a7eSMaciej Purski } 21366cf9a7eSMaciej Purski 214f8702f9eSDmitry Osipenko WARN_ON_ONCE(rdev->ref_cnt < 0); 215f8702f9eSDmitry Osipenko 216f8702f9eSDmitry Osipenko mutex_unlock(®ulator_nesting_mutex); 217f8702f9eSDmitry Osipenko } 218f8702f9eSDmitry Osipenko 219089e2cc2SDmitry Osipenko static bool regulator_supply_is_couple(struct regulator_dev *rdev) 2209f01cd4aSSascha Hauer { 221089e2cc2SDmitry Osipenko struct regulator_dev *c_rdev; 222fa731ac7SArnd Bergmann int i; 2239f01cd4aSSascha Hauer 224089e2cc2SDmitry Osipenko for (i = 1; i < rdev->coupling_desc.n_coupled; i++) { 225089e2cc2SDmitry Osipenko c_rdev = rdev->coupling_desc.coupled_rdevs[i]; 226089e2cc2SDmitry Osipenko 227089e2cc2SDmitry Osipenko if (rdev->supply->rdev == c_rdev) 228089e2cc2SDmitry Osipenko return true; 229089e2cc2SDmitry Osipenko } 230089e2cc2SDmitry Osipenko 231089e2cc2SDmitry Osipenko return false; 232089e2cc2SDmitry Osipenko } 233089e2cc2SDmitry Osipenko 234f8702f9eSDmitry Osipenko static void regulator_unlock_recursive(struct regulator_dev *rdev, 235f8702f9eSDmitry Osipenko unsigned int n_coupled) 236f8702f9eSDmitry Osipenko { 2370a7416f9SDmitry Osipenko struct regulator_dev *c_rdev, *supply_rdev; 2380a7416f9SDmitry Osipenko int i, supply_n_coupled; 239f8702f9eSDmitry Osipenko 240f8702f9eSDmitry Osipenko for (i = n_coupled; i > 0; i--) { 241f8702f9eSDmitry Osipenko c_rdev = rdev->coupling_desc.coupled_rdevs[i - 1]; 242f8702f9eSDmitry Osipenko 243f8702f9eSDmitry Osipenko if (!c_rdev) 244f8702f9eSDmitry Osipenko continue; 245f8702f9eSDmitry Osipenko 2460a7416f9SDmitry Osipenko if (c_rdev->supply && !regulator_supply_is_couple(c_rdev)) { 2470a7416f9SDmitry Osipenko supply_rdev = c_rdev->supply->rdev; 2480a7416f9SDmitry Osipenko supply_n_coupled = supply_rdev->coupling_desc.n_coupled; 2490a7416f9SDmitry Osipenko 2500a7416f9SDmitry Osipenko regulator_unlock_recursive(supply_rdev, 2510a7416f9SDmitry Osipenko supply_n_coupled); 2520a7416f9SDmitry Osipenko } 253f8702f9eSDmitry Osipenko 254f8702f9eSDmitry Osipenko regulator_unlock(c_rdev); 255414c70cbSLiam Girdwood } 256414c70cbSLiam Girdwood } 257414c70cbSLiam Girdwood 2589243a195SMaciej Purski static int regulator_lock_recursive(struct regulator_dev *rdev, 259f8702f9eSDmitry Osipenko struct regulator_dev **new_contended_rdev, 260f8702f9eSDmitry Osipenko struct regulator_dev **old_contended_rdev, 261f8702f9eSDmitry Osipenko struct ww_acquire_ctx *ww_ctx) 2629f01cd4aSSascha Hauer { 2639243a195SMaciej Purski struct regulator_dev *c_rdev; 264f8702f9eSDmitry Osipenko int i, err; 2659f01cd4aSSascha Hauer 2669243a195SMaciej Purski for (i = 0; i < rdev->coupling_desc.n_coupled; i++) { 2679243a195SMaciej Purski c_rdev = rdev->coupling_desc.coupled_rdevs[i]; 2689243a195SMaciej Purski 2699243a195SMaciej Purski if (!c_rdev) 2709243a195SMaciej Purski continue; 2719243a195SMaciej Purski 272f8702f9eSDmitry Osipenko if (c_rdev != *old_contended_rdev) { 273f8702f9eSDmitry Osipenko err = regulator_lock_nested(c_rdev, ww_ctx); 274f8702f9eSDmitry Osipenko if (err) { 275f8702f9eSDmitry Osipenko if (err == -EDEADLK) { 276f8702f9eSDmitry Osipenko *new_contended_rdev = c_rdev; 277f8702f9eSDmitry Osipenko goto err_unlock; 2789243a195SMaciej Purski } 2799243a195SMaciej Purski 280f8702f9eSDmitry Osipenko /* shouldn't happen */ 281f8702f9eSDmitry Osipenko WARN_ON_ONCE(err != -EALREADY); 282f8702f9eSDmitry Osipenko } 283f8702f9eSDmitry Osipenko } else { 284f8702f9eSDmitry Osipenko *old_contended_rdev = NULL; 285f8702f9eSDmitry Osipenko } 286f8702f9eSDmitry Osipenko 287089e2cc2SDmitry Osipenko if (c_rdev->supply && !regulator_supply_is_couple(c_rdev)) { 288f8702f9eSDmitry Osipenko err = regulator_lock_recursive(c_rdev->supply->rdev, 289f8702f9eSDmitry Osipenko new_contended_rdev, 290f8702f9eSDmitry Osipenko old_contended_rdev, 291f8702f9eSDmitry Osipenko ww_ctx); 292f8702f9eSDmitry Osipenko if (err) { 293f8702f9eSDmitry Osipenko regulator_unlock(c_rdev); 294f8702f9eSDmitry Osipenko goto err_unlock; 295f8702f9eSDmitry Osipenko } 296f8702f9eSDmitry Osipenko } 297f8702f9eSDmitry Osipenko } 298f8702f9eSDmitry Osipenko 299f8702f9eSDmitry Osipenko return 0; 300f8702f9eSDmitry Osipenko 301f8702f9eSDmitry Osipenko err_unlock: 302f8702f9eSDmitry Osipenko regulator_unlock_recursive(rdev, i); 303f8702f9eSDmitry Osipenko 304f8702f9eSDmitry Osipenko return err; 3059f01cd4aSSascha Hauer } 3069f01cd4aSSascha Hauer 3079f01cd4aSSascha Hauer /** 3089243a195SMaciej Purski * regulator_unlock_dependent - unlock regulator's suppliers and coupled 3099243a195SMaciej Purski * regulators 3109f01cd4aSSascha Hauer * @rdev: regulator source 311f8702f9eSDmitry Osipenko * @ww_ctx: w/w mutex acquire context 3129243a195SMaciej Purski * 31348f1b4efSKrzysztof Kozlowski * Unlock all regulators related with rdev by coupling or supplying. 3149f01cd4aSSascha Hauer */ 315f8702f9eSDmitry Osipenko static void regulator_unlock_dependent(struct regulator_dev *rdev, 316f8702f9eSDmitry Osipenko struct ww_acquire_ctx *ww_ctx) 3179f01cd4aSSascha Hauer { 318f8702f9eSDmitry Osipenko regulator_unlock_recursive(rdev, rdev->coupling_desc.n_coupled); 319f8702f9eSDmitry Osipenko ww_acquire_fini(ww_ctx); 3209f01cd4aSSascha Hauer } 3219f01cd4aSSascha Hauer 3229f01cd4aSSascha Hauer /** 3239243a195SMaciej Purski * regulator_lock_dependent - lock regulator's suppliers and coupled regulators 3249243a195SMaciej Purski * @rdev: regulator source 325f8702f9eSDmitry Osipenko * @ww_ctx: w/w mutex acquire context 3269243a195SMaciej Purski * 3279243a195SMaciej Purski * This function as a wrapper on regulator_lock_recursive(), which locks 32848f1b4efSKrzysztof Kozlowski * all regulators related with rdev by coupling or supplying. 3299243a195SMaciej Purski */ 330f8702f9eSDmitry Osipenko static void regulator_lock_dependent(struct regulator_dev *rdev, 331f8702f9eSDmitry Osipenko struct ww_acquire_ctx *ww_ctx) 3329243a195SMaciej Purski { 333f8702f9eSDmitry Osipenko struct regulator_dev *new_contended_rdev = NULL; 334f8702f9eSDmitry Osipenko struct regulator_dev *old_contended_rdev = NULL; 335f8702f9eSDmitry Osipenko int err; 336f8702f9eSDmitry Osipenko 337f8702f9eSDmitry Osipenko mutex_lock(®ulator_list_mutex); 338f8702f9eSDmitry Osipenko 339f8702f9eSDmitry Osipenko ww_acquire_init(ww_ctx, ®ulator_ww_class); 340f8702f9eSDmitry Osipenko 341f8702f9eSDmitry Osipenko do { 342f8702f9eSDmitry Osipenko if (new_contended_rdev) { 343f8702f9eSDmitry Osipenko ww_mutex_lock_slow(&new_contended_rdev->mutex, ww_ctx); 344f8702f9eSDmitry Osipenko old_contended_rdev = new_contended_rdev; 345f8702f9eSDmitry Osipenko old_contended_rdev->ref_cnt++; 346f8702f9eSDmitry Osipenko } 347f8702f9eSDmitry Osipenko 348f8702f9eSDmitry Osipenko err = regulator_lock_recursive(rdev, 349f8702f9eSDmitry Osipenko &new_contended_rdev, 350f8702f9eSDmitry Osipenko &old_contended_rdev, 351f8702f9eSDmitry Osipenko ww_ctx); 352f8702f9eSDmitry Osipenko 353f8702f9eSDmitry Osipenko if (old_contended_rdev) 354f8702f9eSDmitry Osipenko regulator_unlock(old_contended_rdev); 355f8702f9eSDmitry Osipenko 356f8702f9eSDmitry Osipenko } while (err == -EDEADLK); 357f8702f9eSDmitry Osipenko 358f8702f9eSDmitry Osipenko ww_acquire_done(ww_ctx); 359f8702f9eSDmitry Osipenko 360f8702f9eSDmitry Osipenko mutex_unlock(®ulator_list_mutex); 361414c70cbSLiam Girdwood } 362414c70cbSLiam Girdwood 363414c70cbSLiam Girdwood /** 364fe06051dSzoro * of_get_child_regulator - get a child regulator device node 365fe06051dSzoro * based on supply name 366fe06051dSzoro * @parent: Parent device node 367fe06051dSzoro * @prop_name: Combination regulator supply name and "-supply" 368fe06051dSzoro * 369fe06051dSzoro * Traverse all child nodes. 370fe06051dSzoro * Extract the child regulator device node corresponding to the supply name. 371fe06051dSzoro * returns the device node corresponding to the regulator if found, else 372fe06051dSzoro * returns NULL. 373fe06051dSzoro */ 374fe06051dSzoro static struct device_node *of_get_child_regulator(struct device_node *parent, 375fe06051dSzoro const char *prop_name) 376fe06051dSzoro { 377fe06051dSzoro struct device_node *regnode = NULL; 378fe06051dSzoro struct device_node *child = NULL; 379fe06051dSzoro 380fe06051dSzoro for_each_child_of_node(parent, child) { 381fe06051dSzoro regnode = of_parse_phandle(child, prop_name, 0); 382fe06051dSzoro 383fe06051dSzoro if (!regnode) { 384fe06051dSzoro regnode = of_get_child_regulator(child, prop_name); 38581eeb0a3SNishka Dasgupta if (regnode) 38681eeb0a3SNishka Dasgupta goto err_node_put; 387fe06051dSzoro } else { 38881eeb0a3SNishka Dasgupta goto err_node_put; 389fe06051dSzoro } 390fe06051dSzoro } 391fe06051dSzoro return NULL; 39281eeb0a3SNishka Dasgupta 39381eeb0a3SNishka Dasgupta err_node_put: 39481eeb0a3SNishka Dasgupta of_node_put(child); 39581eeb0a3SNishka Dasgupta return regnode; 396fe06051dSzoro } 397fe06051dSzoro 398fe06051dSzoro /** 39969511a45SRajendra Nayak * of_get_regulator - get a regulator device node based on supply name 40069511a45SRajendra Nayak * @dev: Device pointer for the consumer (of regulator) device 40169511a45SRajendra Nayak * @supply: regulator supply name 40269511a45SRajendra Nayak * 40369511a45SRajendra Nayak * Extract the regulator device node corresponding to the supply name. 404167d41dcSMaxime Ripard * returns the device node corresponding to the regulator if found, else 40569511a45SRajendra Nayak * returns NULL. 40669511a45SRajendra Nayak */ 40769511a45SRajendra Nayak static struct device_node *of_get_regulator(struct device *dev, const char *supply) 40869511a45SRajendra Nayak { 40969511a45SRajendra Nayak struct device_node *regnode = NULL; 410e9bb4a06SAngeloGioacchino Del Regno char prop_name[64]; /* 64 is max size of property name */ 41169511a45SRajendra Nayak 41269511a45SRajendra Nayak dev_dbg(dev, "Looking up %s-supply from device tree\n", supply); 41369511a45SRajendra Nayak 414e9bb4a06SAngeloGioacchino Del Regno snprintf(prop_name, 64, "%s-supply", supply); 41569511a45SRajendra Nayak regnode = of_parse_phandle(dev->of_node, prop_name, 0); 41669511a45SRajendra Nayak 41769511a45SRajendra Nayak if (!regnode) { 418fe06051dSzoro regnode = of_get_child_regulator(dev->of_node, prop_name); 419fe06051dSzoro if (regnode) 420fe06051dSzoro return regnode; 421fe06051dSzoro 4227799167bSRob Herring dev_dbg(dev, "Looking up %s property in node %pOF failed\n", 4237799167bSRob Herring prop_name, dev->of_node); 42469511a45SRajendra Nayak return NULL; 42569511a45SRajendra Nayak } 42669511a45SRajendra Nayak return regnode; 42769511a45SRajendra Nayak } 42869511a45SRajendra Nayak 429414c70cbSLiam Girdwood /* Platform voltage constraint check */ 430d22b85a1SDmitry Osipenko int regulator_check_voltage(struct regulator_dev *rdev, 431414c70cbSLiam Girdwood int *min_uV, int *max_uV) 432414c70cbSLiam Girdwood { 433414c70cbSLiam Girdwood BUG_ON(*min_uV > *max_uV); 434414c70cbSLiam Girdwood 4358a34e979SWEN Pingbo if (!regulator_ops_is_valid(rdev, REGULATOR_CHANGE_VOLTAGE)) { 4367ebcf26cSStephen Boyd rdev_err(rdev, "voltage operation not allowed\n"); 437414c70cbSLiam Girdwood return -EPERM; 438414c70cbSLiam Girdwood } 439414c70cbSLiam Girdwood 440414c70cbSLiam Girdwood if (*max_uV > rdev->constraints->max_uV) 441414c70cbSLiam Girdwood *max_uV = rdev->constraints->max_uV; 442414c70cbSLiam Girdwood if (*min_uV < rdev->constraints->min_uV) 443414c70cbSLiam Girdwood *min_uV = rdev->constraints->min_uV; 444414c70cbSLiam Girdwood 44589f425edSMark Brown if (*min_uV > *max_uV) { 44689f425edSMark Brown rdev_err(rdev, "unsupportable voltage range: %d-%duV\n", 44754abd335SMark Brown *min_uV, *max_uV); 448414c70cbSLiam Girdwood return -EINVAL; 44989f425edSMark Brown } 450414c70cbSLiam Girdwood 451414c70cbSLiam Girdwood return 0; 452414c70cbSLiam Girdwood } 453414c70cbSLiam Girdwood 454f7efad10SChunyan Zhang /* return 0 if the state is valid */ 455f7efad10SChunyan Zhang static int regulator_check_states(suspend_state_t state) 456f7efad10SChunyan Zhang { 457f7efad10SChunyan Zhang return (state > PM_SUSPEND_MAX || state == PM_SUSPEND_TO_IDLE); 458f7efad10SChunyan Zhang } 459f7efad10SChunyan Zhang 46005fda3b1SThomas Petazzoni /* Make sure we select a voltage that suits the needs of all 46105fda3b1SThomas Petazzoni * regulator consumers 46205fda3b1SThomas Petazzoni */ 463d22b85a1SDmitry Osipenko int regulator_check_consumers(struct regulator_dev *rdev, 464c360a6dfSChunyan Zhang int *min_uV, int *max_uV, 465c360a6dfSChunyan Zhang suspend_state_t state) 46605fda3b1SThomas Petazzoni { 46705fda3b1SThomas Petazzoni struct regulator *regulator; 468c360a6dfSChunyan Zhang struct regulator_voltage *voltage; 46905fda3b1SThomas Petazzoni 47005fda3b1SThomas Petazzoni list_for_each_entry(regulator, &rdev->consumer_list, list) { 471c360a6dfSChunyan Zhang voltage = ®ulator->voltage[state]; 4724aa922c0SMark Brown /* 4734aa922c0SMark Brown * Assume consumers that didn't say anything are OK 4744aa922c0SMark Brown * with anything in the constraint range. 4754aa922c0SMark Brown */ 476c360a6dfSChunyan Zhang if (!voltage->min_uV && !voltage->max_uV) 4774aa922c0SMark Brown continue; 4784aa922c0SMark Brown 479c360a6dfSChunyan Zhang if (*max_uV > voltage->max_uV) 480c360a6dfSChunyan Zhang *max_uV = voltage->max_uV; 481c360a6dfSChunyan Zhang if (*min_uV < voltage->min_uV) 482c360a6dfSChunyan Zhang *min_uV = voltage->min_uV; 48305fda3b1SThomas Petazzoni } 48405fda3b1SThomas Petazzoni 485dd8004afSMark Brown if (*min_uV > *max_uV) { 4869c7b4e8aSRuss Dill rdev_err(rdev, "Restricting voltage, %u-%uuV\n", 4879c7b4e8aSRuss Dill *min_uV, *max_uV); 48805fda3b1SThomas Petazzoni return -EINVAL; 489dd8004afSMark Brown } 49005fda3b1SThomas Petazzoni 49105fda3b1SThomas Petazzoni return 0; 49205fda3b1SThomas Petazzoni } 49305fda3b1SThomas Petazzoni 494414c70cbSLiam Girdwood /* current constraint check */ 495414c70cbSLiam Girdwood static int regulator_check_current_limit(struct regulator_dev *rdev, 496414c70cbSLiam Girdwood int *min_uA, int *max_uA) 497414c70cbSLiam Girdwood { 498414c70cbSLiam Girdwood BUG_ON(*min_uA > *max_uA); 499414c70cbSLiam Girdwood 5008a34e979SWEN Pingbo if (!regulator_ops_is_valid(rdev, REGULATOR_CHANGE_CURRENT)) { 5017ebcf26cSStephen Boyd rdev_err(rdev, "current operation not allowed\n"); 502414c70cbSLiam Girdwood return -EPERM; 503414c70cbSLiam Girdwood } 504414c70cbSLiam Girdwood 505414c70cbSLiam Girdwood if (*max_uA > rdev->constraints->max_uA) 506414c70cbSLiam Girdwood *max_uA = rdev->constraints->max_uA; 507414c70cbSLiam Girdwood if (*min_uA < rdev->constraints->min_uA) 508414c70cbSLiam Girdwood *min_uA = rdev->constraints->min_uA; 509414c70cbSLiam Girdwood 51089f425edSMark Brown if (*min_uA > *max_uA) { 51189f425edSMark Brown rdev_err(rdev, "unsupportable current range: %d-%duA\n", 51254abd335SMark Brown *min_uA, *max_uA); 513414c70cbSLiam Girdwood return -EINVAL; 51489f425edSMark Brown } 515414c70cbSLiam Girdwood 516414c70cbSLiam Girdwood return 0; 517414c70cbSLiam Girdwood } 518414c70cbSLiam Girdwood 519414c70cbSLiam Girdwood /* operating mode constraint check */ 520109c75afSCharles Keepax static int regulator_mode_constrain(struct regulator_dev *rdev, 521109c75afSCharles Keepax unsigned int *mode) 522414c70cbSLiam Girdwood { 5232c608234SMark Brown switch (*mode) { 524e573520bSDavid Brownell case REGULATOR_MODE_FAST: 525e573520bSDavid Brownell case REGULATOR_MODE_NORMAL: 526e573520bSDavid Brownell case REGULATOR_MODE_IDLE: 527e573520bSDavid Brownell case REGULATOR_MODE_STANDBY: 528e573520bSDavid Brownell break; 529e573520bSDavid Brownell default: 53089f425edSMark Brown rdev_err(rdev, "invalid mode %x specified\n", *mode); 531e573520bSDavid Brownell return -EINVAL; 532e573520bSDavid Brownell } 533e573520bSDavid Brownell 5348a34e979SWEN Pingbo if (!regulator_ops_is_valid(rdev, REGULATOR_CHANGE_MODE)) { 5357ebcf26cSStephen Boyd rdev_err(rdev, "mode operation not allowed\n"); 536414c70cbSLiam Girdwood return -EPERM; 537414c70cbSLiam Girdwood } 5382c608234SMark Brown 5392c608234SMark Brown /* The modes are bitmasks, the most power hungry modes having 5402c608234SMark Brown * the lowest values. If the requested mode isn't supported 5412c608234SMark Brown * try higher modes. */ 5422c608234SMark Brown while (*mode) { 5432c608234SMark Brown if (rdev->constraints->valid_modes_mask & *mode) 544414c70cbSLiam Girdwood return 0; 5452c608234SMark Brown *mode /= 2; 5462c608234SMark Brown } 5472c608234SMark Brown 5482c608234SMark Brown return -EINVAL; 549414c70cbSLiam Girdwood } 550414c70cbSLiam Girdwood 551f7efad10SChunyan Zhang static inline struct regulator_state * 552f7efad10SChunyan Zhang regulator_get_suspend_state(struct regulator_dev *rdev, suspend_state_t state) 553f7efad10SChunyan Zhang { 554f7efad10SChunyan Zhang if (rdev->constraints == NULL) 555f7efad10SChunyan Zhang return NULL; 556f7efad10SChunyan Zhang 557f7efad10SChunyan Zhang switch (state) { 558f7efad10SChunyan Zhang case PM_SUSPEND_STANDBY: 559f7efad10SChunyan Zhang return &rdev->constraints->state_standby; 560f7efad10SChunyan Zhang case PM_SUSPEND_MEM: 561f7efad10SChunyan Zhang return &rdev->constraints->state_mem; 562f7efad10SChunyan Zhang case PM_SUSPEND_MAX: 563f7efad10SChunyan Zhang return &rdev->constraints->state_disk; 564f7efad10SChunyan Zhang default: 565f7efad10SChunyan Zhang return NULL; 566f7efad10SChunyan Zhang } 567f7efad10SChunyan Zhang } 568f7efad10SChunyan Zhang 5690955f5beSStephen Boyd static const struct regulator_state * 5700955f5beSStephen Boyd regulator_get_suspend_state_check(struct regulator_dev *rdev, suspend_state_t state) 5710955f5beSStephen Boyd { 5720955f5beSStephen Boyd const struct regulator_state *rstate; 5730955f5beSStephen Boyd 5740955f5beSStephen Boyd rstate = regulator_get_suspend_state(rdev, state); 5750955f5beSStephen Boyd if (rstate == NULL) 5760955f5beSStephen Boyd return NULL; 5770955f5beSStephen Boyd 5780955f5beSStephen Boyd /* If we have no suspend mode configuration don't set anything; 5790955f5beSStephen Boyd * only warn if the driver implements set_suspend_voltage or 5800955f5beSStephen Boyd * set_suspend_mode callback. 5810955f5beSStephen Boyd */ 5820955f5beSStephen Boyd if (rstate->enabled != ENABLE_IN_SUSPEND && 5830955f5beSStephen Boyd rstate->enabled != DISABLE_IN_SUSPEND) { 5840955f5beSStephen Boyd if (rdev->desc->ops->set_suspend_voltage || 5850955f5beSStephen Boyd rdev->desc->ops->set_suspend_mode) 5860955f5beSStephen Boyd rdev_warn(rdev, "No configuration\n"); 5870955f5beSStephen Boyd return NULL; 5880955f5beSStephen Boyd } 5890955f5beSStephen Boyd 5900955f5beSStephen Boyd return rstate; 5910955f5beSStephen Boyd } 5920955f5beSStephen Boyd 593414c70cbSLiam Girdwood static ssize_t regulator_uV_show(struct device *dev, 594414c70cbSLiam Girdwood struct device_attribute *attr, char *buf) 595414c70cbSLiam Girdwood { 596a5766f11SLiam Girdwood struct regulator_dev *rdev = dev_get_drvdata(dev); 597c82f27dfSH. Nikolaus Schaller int uV; 598414c70cbSLiam Girdwood 59966cf9a7eSMaciej Purski regulator_lock(rdev); 600c82f27dfSH. Nikolaus Schaller uV = regulator_get_voltage_rdev(rdev); 60166cf9a7eSMaciej Purski regulator_unlock(rdev); 602414c70cbSLiam Girdwood 603c82f27dfSH. Nikolaus Schaller if (uV < 0) 604c82f27dfSH. Nikolaus Schaller return uV; 605c82f27dfSH. Nikolaus Schaller return sprintf(buf, "%d\n", uV); 606414c70cbSLiam Girdwood } 6077ad68e2fSDavid Brownell static DEVICE_ATTR(microvolts, 0444, regulator_uV_show, NULL); 608414c70cbSLiam Girdwood 609414c70cbSLiam Girdwood static ssize_t regulator_uA_show(struct device *dev, 610414c70cbSLiam Girdwood struct device_attribute *attr, char *buf) 611414c70cbSLiam Girdwood { 612a5766f11SLiam Girdwood struct regulator_dev *rdev = dev_get_drvdata(dev); 613414c70cbSLiam Girdwood 614414c70cbSLiam Girdwood return sprintf(buf, "%d\n", _regulator_get_current_limit(rdev)); 615414c70cbSLiam Girdwood } 6167ad68e2fSDavid Brownell static DEVICE_ATTR(microamps, 0444, regulator_uA_show, NULL); 617414c70cbSLiam Girdwood 618587cea27SGreg Kroah-Hartman static ssize_t name_show(struct device *dev, struct device_attribute *attr, 619587cea27SGreg Kroah-Hartman char *buf) 620bc558a60SMark Brown { 621bc558a60SMark Brown struct regulator_dev *rdev = dev_get_drvdata(dev); 622bc558a60SMark Brown 6231083c393SMark Brown return sprintf(buf, "%s\n", rdev_get_name(rdev)); 624bc558a60SMark Brown } 625587cea27SGreg Kroah-Hartman static DEVICE_ATTR_RO(name); 626bc558a60SMark Brown 62701de19d0SDouglas Anderson static const char *regulator_opmode_to_str(int mode) 628414c70cbSLiam Girdwood { 629414c70cbSLiam Girdwood switch (mode) { 630414c70cbSLiam Girdwood case REGULATOR_MODE_FAST: 63101de19d0SDouglas Anderson return "fast"; 632414c70cbSLiam Girdwood case REGULATOR_MODE_NORMAL: 63301de19d0SDouglas Anderson return "normal"; 634414c70cbSLiam Girdwood case REGULATOR_MODE_IDLE: 63501de19d0SDouglas Anderson return "idle"; 636414c70cbSLiam Girdwood case REGULATOR_MODE_STANDBY: 63701de19d0SDouglas Anderson return "standby"; 638414c70cbSLiam Girdwood } 63901de19d0SDouglas Anderson return "unknown"; 64001de19d0SDouglas Anderson } 64101de19d0SDouglas Anderson 64201de19d0SDouglas Anderson static ssize_t regulator_print_opmode(char *buf, int mode) 64301de19d0SDouglas Anderson { 64401de19d0SDouglas Anderson return sprintf(buf, "%s\n", regulator_opmode_to_str(mode)); 645414c70cbSLiam Girdwood } 646414c70cbSLiam Girdwood 6474fca9545SDavid Brownell static ssize_t regulator_opmode_show(struct device *dev, 648414c70cbSLiam Girdwood struct device_attribute *attr, char *buf) 649414c70cbSLiam Girdwood { 650a5766f11SLiam Girdwood struct regulator_dev *rdev = dev_get_drvdata(dev); 651414c70cbSLiam Girdwood 6524fca9545SDavid Brownell return regulator_print_opmode(buf, _regulator_get_mode(rdev)); 6534fca9545SDavid Brownell } 6547ad68e2fSDavid Brownell static DEVICE_ATTR(opmode, 0444, regulator_opmode_show, NULL); 6554fca9545SDavid Brownell 6564fca9545SDavid Brownell static ssize_t regulator_print_state(char *buf, int state) 6574fca9545SDavid Brownell { 658414c70cbSLiam Girdwood if (state > 0) 659414c70cbSLiam Girdwood return sprintf(buf, "enabled\n"); 660414c70cbSLiam Girdwood else if (state == 0) 661414c70cbSLiam Girdwood return sprintf(buf, "disabled\n"); 662414c70cbSLiam Girdwood else 663414c70cbSLiam Girdwood return sprintf(buf, "unknown\n"); 664414c70cbSLiam Girdwood } 665414c70cbSLiam Girdwood 6664fca9545SDavid Brownell static ssize_t regulator_state_show(struct device *dev, 6674fca9545SDavid Brownell struct device_attribute *attr, char *buf) 6684fca9545SDavid Brownell { 6694fca9545SDavid Brownell struct regulator_dev *rdev = dev_get_drvdata(dev); 6709332546fSMark Brown ssize_t ret; 6714fca9545SDavid Brownell 67266cf9a7eSMaciej Purski regulator_lock(rdev); 6739332546fSMark Brown ret = regulator_print_state(buf, _regulator_is_enabled(rdev)); 67466cf9a7eSMaciej Purski regulator_unlock(rdev); 6759332546fSMark Brown 6769332546fSMark Brown return ret; 6774fca9545SDavid Brownell } 6787ad68e2fSDavid Brownell static DEVICE_ATTR(state, 0444, regulator_state_show, NULL); 6794fca9545SDavid Brownell 680853116a1SDavid Brownell static ssize_t regulator_status_show(struct device *dev, 681853116a1SDavid Brownell struct device_attribute *attr, char *buf) 682853116a1SDavid Brownell { 683853116a1SDavid Brownell struct regulator_dev *rdev = dev_get_drvdata(dev); 684853116a1SDavid Brownell int status; 685853116a1SDavid Brownell char *label; 686853116a1SDavid Brownell 687853116a1SDavid Brownell status = rdev->desc->ops->get_status(rdev); 688853116a1SDavid Brownell if (status < 0) 689853116a1SDavid Brownell return status; 690853116a1SDavid Brownell 691853116a1SDavid Brownell switch (status) { 692853116a1SDavid Brownell case REGULATOR_STATUS_OFF: 693853116a1SDavid Brownell label = "off"; 694853116a1SDavid Brownell break; 695853116a1SDavid Brownell case REGULATOR_STATUS_ON: 696853116a1SDavid Brownell label = "on"; 697853116a1SDavid Brownell break; 698853116a1SDavid Brownell case REGULATOR_STATUS_ERROR: 699853116a1SDavid Brownell label = "error"; 700853116a1SDavid Brownell break; 701853116a1SDavid Brownell case REGULATOR_STATUS_FAST: 702853116a1SDavid Brownell label = "fast"; 703853116a1SDavid Brownell break; 704853116a1SDavid Brownell case REGULATOR_STATUS_NORMAL: 705853116a1SDavid Brownell label = "normal"; 706853116a1SDavid Brownell break; 707853116a1SDavid Brownell case REGULATOR_STATUS_IDLE: 708853116a1SDavid Brownell label = "idle"; 709853116a1SDavid Brownell break; 710853116a1SDavid Brownell case REGULATOR_STATUS_STANDBY: 711853116a1SDavid Brownell label = "standby"; 712853116a1SDavid Brownell break; 713f59c8f9fSMark Brown case REGULATOR_STATUS_BYPASS: 714f59c8f9fSMark Brown label = "bypass"; 715f59c8f9fSMark Brown break; 7161beaf762SKrystian Garbaciak case REGULATOR_STATUS_UNDEFINED: 7171beaf762SKrystian Garbaciak label = "undefined"; 7181beaf762SKrystian Garbaciak break; 719853116a1SDavid Brownell default: 720853116a1SDavid Brownell return -ERANGE; 721853116a1SDavid Brownell } 722853116a1SDavid Brownell 723853116a1SDavid Brownell return sprintf(buf, "%s\n", label); 724853116a1SDavid Brownell } 725853116a1SDavid Brownell static DEVICE_ATTR(status, 0444, regulator_status_show, NULL); 726853116a1SDavid Brownell 727414c70cbSLiam Girdwood static ssize_t regulator_min_uA_show(struct device *dev, 728414c70cbSLiam Girdwood struct device_attribute *attr, char *buf) 729414c70cbSLiam Girdwood { 730a5766f11SLiam Girdwood struct regulator_dev *rdev = dev_get_drvdata(dev); 731414c70cbSLiam Girdwood 732414c70cbSLiam Girdwood if (!rdev->constraints) 733414c70cbSLiam Girdwood return sprintf(buf, "constraint not defined\n"); 734414c70cbSLiam Girdwood 735414c70cbSLiam Girdwood return sprintf(buf, "%d\n", rdev->constraints->min_uA); 736414c70cbSLiam Girdwood } 7377ad68e2fSDavid Brownell static DEVICE_ATTR(min_microamps, 0444, regulator_min_uA_show, NULL); 738414c70cbSLiam Girdwood 739414c70cbSLiam Girdwood static ssize_t regulator_max_uA_show(struct device *dev, 740414c70cbSLiam Girdwood struct device_attribute *attr, char *buf) 741414c70cbSLiam Girdwood { 742a5766f11SLiam Girdwood struct regulator_dev *rdev = dev_get_drvdata(dev); 743414c70cbSLiam Girdwood 744414c70cbSLiam Girdwood if (!rdev->constraints) 745414c70cbSLiam Girdwood return sprintf(buf, "constraint not defined\n"); 746414c70cbSLiam Girdwood 747414c70cbSLiam Girdwood return sprintf(buf, "%d\n", rdev->constraints->max_uA); 748414c70cbSLiam Girdwood } 7497ad68e2fSDavid Brownell static DEVICE_ATTR(max_microamps, 0444, regulator_max_uA_show, NULL); 750414c70cbSLiam Girdwood 751414c70cbSLiam Girdwood static ssize_t regulator_min_uV_show(struct device *dev, 752414c70cbSLiam Girdwood struct device_attribute *attr, char *buf) 753414c70cbSLiam Girdwood { 754a5766f11SLiam Girdwood struct regulator_dev *rdev = dev_get_drvdata(dev); 755414c70cbSLiam Girdwood 756414c70cbSLiam Girdwood if (!rdev->constraints) 757414c70cbSLiam Girdwood return sprintf(buf, "constraint not defined\n"); 758414c70cbSLiam Girdwood 759414c70cbSLiam Girdwood return sprintf(buf, "%d\n", rdev->constraints->min_uV); 760414c70cbSLiam Girdwood } 7617ad68e2fSDavid Brownell static DEVICE_ATTR(min_microvolts, 0444, regulator_min_uV_show, NULL); 762414c70cbSLiam Girdwood 763414c70cbSLiam Girdwood static ssize_t regulator_max_uV_show(struct device *dev, 764414c70cbSLiam Girdwood struct device_attribute *attr, char *buf) 765414c70cbSLiam Girdwood { 766a5766f11SLiam Girdwood struct regulator_dev *rdev = dev_get_drvdata(dev); 767414c70cbSLiam Girdwood 768414c70cbSLiam Girdwood if (!rdev->constraints) 769414c70cbSLiam Girdwood return sprintf(buf, "constraint not defined\n"); 770414c70cbSLiam Girdwood 771414c70cbSLiam Girdwood return sprintf(buf, "%d\n", rdev->constraints->max_uV); 772414c70cbSLiam Girdwood } 7737ad68e2fSDavid Brownell static DEVICE_ATTR(max_microvolts, 0444, regulator_max_uV_show, NULL); 774414c70cbSLiam Girdwood 775414c70cbSLiam Girdwood static ssize_t regulator_total_uA_show(struct device *dev, 776414c70cbSLiam Girdwood struct device_attribute *attr, char *buf) 777414c70cbSLiam Girdwood { 778a5766f11SLiam Girdwood struct regulator_dev *rdev = dev_get_drvdata(dev); 779414c70cbSLiam Girdwood struct regulator *regulator; 780414c70cbSLiam Girdwood int uA = 0; 781414c70cbSLiam Girdwood 78266cf9a7eSMaciej Purski regulator_lock(rdev); 7835451781dSDouglas Anderson list_for_each_entry(regulator, &rdev->consumer_list, list) { 7845451781dSDouglas Anderson if (regulator->enable_count) 785414c70cbSLiam Girdwood uA += regulator->uA_load; 7865451781dSDouglas Anderson } 78766cf9a7eSMaciej Purski regulator_unlock(rdev); 788414c70cbSLiam Girdwood return sprintf(buf, "%d\n", uA); 789414c70cbSLiam Girdwood } 7907ad68e2fSDavid Brownell static DEVICE_ATTR(requested_microamps, 0444, regulator_total_uA_show, NULL); 791414c70cbSLiam Girdwood 792587cea27SGreg Kroah-Hartman static ssize_t num_users_show(struct device *dev, struct device_attribute *attr, 793587cea27SGreg Kroah-Hartman char *buf) 794414c70cbSLiam Girdwood { 795a5766f11SLiam Girdwood struct regulator_dev *rdev = dev_get_drvdata(dev); 796414c70cbSLiam Girdwood return sprintf(buf, "%d\n", rdev->use_count); 797414c70cbSLiam Girdwood } 798587cea27SGreg Kroah-Hartman static DEVICE_ATTR_RO(num_users); 799414c70cbSLiam Girdwood 800587cea27SGreg Kroah-Hartman static ssize_t type_show(struct device *dev, struct device_attribute *attr, 801587cea27SGreg Kroah-Hartman char *buf) 802414c70cbSLiam Girdwood { 803a5766f11SLiam Girdwood struct regulator_dev *rdev = dev_get_drvdata(dev); 804414c70cbSLiam Girdwood 805414c70cbSLiam Girdwood switch (rdev->desc->type) { 806414c70cbSLiam Girdwood case REGULATOR_VOLTAGE: 807414c70cbSLiam Girdwood return sprintf(buf, "voltage\n"); 808414c70cbSLiam Girdwood case REGULATOR_CURRENT: 809414c70cbSLiam Girdwood return sprintf(buf, "current\n"); 810414c70cbSLiam Girdwood } 811414c70cbSLiam Girdwood return sprintf(buf, "unknown\n"); 812414c70cbSLiam Girdwood } 813587cea27SGreg Kroah-Hartman static DEVICE_ATTR_RO(type); 814414c70cbSLiam Girdwood 815414c70cbSLiam Girdwood static ssize_t regulator_suspend_mem_uV_show(struct device *dev, 816414c70cbSLiam Girdwood struct device_attribute *attr, char *buf) 817414c70cbSLiam Girdwood { 818a5766f11SLiam Girdwood struct regulator_dev *rdev = dev_get_drvdata(dev); 819414c70cbSLiam Girdwood 820414c70cbSLiam Girdwood return sprintf(buf, "%d\n", rdev->constraints->state_mem.uV); 821414c70cbSLiam Girdwood } 8227ad68e2fSDavid Brownell static DEVICE_ATTR(suspend_mem_microvolts, 0444, 8237ad68e2fSDavid Brownell regulator_suspend_mem_uV_show, NULL); 824414c70cbSLiam Girdwood 825414c70cbSLiam Girdwood static ssize_t regulator_suspend_disk_uV_show(struct device *dev, 826414c70cbSLiam Girdwood struct device_attribute *attr, char *buf) 827414c70cbSLiam Girdwood { 828a5766f11SLiam Girdwood struct regulator_dev *rdev = dev_get_drvdata(dev); 829414c70cbSLiam Girdwood 830414c70cbSLiam Girdwood return sprintf(buf, "%d\n", rdev->constraints->state_disk.uV); 831414c70cbSLiam Girdwood } 8327ad68e2fSDavid Brownell static DEVICE_ATTR(suspend_disk_microvolts, 0444, 8337ad68e2fSDavid Brownell regulator_suspend_disk_uV_show, NULL); 834414c70cbSLiam Girdwood 835414c70cbSLiam Girdwood static ssize_t regulator_suspend_standby_uV_show(struct device *dev, 836414c70cbSLiam Girdwood struct device_attribute *attr, char *buf) 837414c70cbSLiam Girdwood { 838a5766f11SLiam Girdwood struct regulator_dev *rdev = dev_get_drvdata(dev); 839414c70cbSLiam Girdwood 840414c70cbSLiam Girdwood return sprintf(buf, "%d\n", rdev->constraints->state_standby.uV); 841414c70cbSLiam Girdwood } 8427ad68e2fSDavid Brownell static DEVICE_ATTR(suspend_standby_microvolts, 0444, 8437ad68e2fSDavid Brownell regulator_suspend_standby_uV_show, NULL); 844414c70cbSLiam Girdwood 845414c70cbSLiam Girdwood static ssize_t regulator_suspend_mem_mode_show(struct device *dev, 846414c70cbSLiam Girdwood struct device_attribute *attr, char *buf) 847414c70cbSLiam Girdwood { 848a5766f11SLiam Girdwood struct regulator_dev *rdev = dev_get_drvdata(dev); 849414c70cbSLiam Girdwood 8504fca9545SDavid Brownell return regulator_print_opmode(buf, 8514fca9545SDavid Brownell rdev->constraints->state_mem.mode); 852414c70cbSLiam Girdwood } 8537ad68e2fSDavid Brownell static DEVICE_ATTR(suspend_mem_mode, 0444, 8547ad68e2fSDavid Brownell regulator_suspend_mem_mode_show, NULL); 855414c70cbSLiam Girdwood 856414c70cbSLiam Girdwood static ssize_t regulator_suspend_disk_mode_show(struct device *dev, 857414c70cbSLiam Girdwood struct device_attribute *attr, char *buf) 858414c70cbSLiam Girdwood { 859a5766f11SLiam Girdwood struct regulator_dev *rdev = dev_get_drvdata(dev); 860414c70cbSLiam Girdwood 8614fca9545SDavid Brownell return regulator_print_opmode(buf, 8624fca9545SDavid Brownell rdev->constraints->state_disk.mode); 863414c70cbSLiam Girdwood } 8647ad68e2fSDavid Brownell static DEVICE_ATTR(suspend_disk_mode, 0444, 8657ad68e2fSDavid Brownell regulator_suspend_disk_mode_show, NULL); 866414c70cbSLiam Girdwood 867414c70cbSLiam Girdwood static ssize_t regulator_suspend_standby_mode_show(struct device *dev, 868414c70cbSLiam Girdwood struct device_attribute *attr, char *buf) 869414c70cbSLiam Girdwood { 870a5766f11SLiam Girdwood struct regulator_dev *rdev = dev_get_drvdata(dev); 871414c70cbSLiam Girdwood 8724fca9545SDavid Brownell return regulator_print_opmode(buf, 8734fca9545SDavid Brownell rdev->constraints->state_standby.mode); 874414c70cbSLiam Girdwood } 8757ad68e2fSDavid Brownell static DEVICE_ATTR(suspend_standby_mode, 0444, 8767ad68e2fSDavid Brownell regulator_suspend_standby_mode_show, NULL); 877414c70cbSLiam Girdwood 878414c70cbSLiam Girdwood static ssize_t regulator_suspend_mem_state_show(struct device *dev, 879414c70cbSLiam Girdwood struct device_attribute *attr, char *buf) 880414c70cbSLiam Girdwood { 881a5766f11SLiam Girdwood struct regulator_dev *rdev = dev_get_drvdata(dev); 882414c70cbSLiam Girdwood 8834fca9545SDavid Brownell return regulator_print_state(buf, 8844fca9545SDavid Brownell rdev->constraints->state_mem.enabled); 885414c70cbSLiam Girdwood } 8867ad68e2fSDavid Brownell static DEVICE_ATTR(suspend_mem_state, 0444, 8877ad68e2fSDavid Brownell regulator_suspend_mem_state_show, NULL); 888414c70cbSLiam Girdwood 889414c70cbSLiam Girdwood static ssize_t regulator_suspend_disk_state_show(struct device *dev, 890414c70cbSLiam Girdwood struct device_attribute *attr, char *buf) 891414c70cbSLiam Girdwood { 892a5766f11SLiam Girdwood struct regulator_dev *rdev = dev_get_drvdata(dev); 893414c70cbSLiam Girdwood 8944fca9545SDavid Brownell return regulator_print_state(buf, 8954fca9545SDavid Brownell rdev->constraints->state_disk.enabled); 896414c70cbSLiam Girdwood } 8977ad68e2fSDavid Brownell static DEVICE_ATTR(suspend_disk_state, 0444, 8987ad68e2fSDavid Brownell regulator_suspend_disk_state_show, NULL); 899414c70cbSLiam Girdwood 900414c70cbSLiam Girdwood static ssize_t regulator_suspend_standby_state_show(struct device *dev, 901414c70cbSLiam Girdwood struct device_attribute *attr, char *buf) 902414c70cbSLiam Girdwood { 903a5766f11SLiam Girdwood struct regulator_dev *rdev = dev_get_drvdata(dev); 904414c70cbSLiam Girdwood 9054fca9545SDavid Brownell return regulator_print_state(buf, 9064fca9545SDavid Brownell rdev->constraints->state_standby.enabled); 907414c70cbSLiam Girdwood } 9087ad68e2fSDavid Brownell static DEVICE_ATTR(suspend_standby_state, 0444, 9097ad68e2fSDavid Brownell regulator_suspend_standby_state_show, NULL); 910bc558a60SMark Brown 911f59c8f9fSMark Brown static ssize_t regulator_bypass_show(struct device *dev, 912f59c8f9fSMark Brown struct device_attribute *attr, char *buf) 913f59c8f9fSMark Brown { 914f59c8f9fSMark Brown struct regulator_dev *rdev = dev_get_drvdata(dev); 915f59c8f9fSMark Brown const char *report; 916f59c8f9fSMark Brown bool bypass; 917f59c8f9fSMark Brown int ret; 918f59c8f9fSMark Brown 919f59c8f9fSMark Brown ret = rdev->desc->ops->get_bypass(rdev, &bypass); 920f59c8f9fSMark Brown 921f59c8f9fSMark Brown if (ret != 0) 922f59c8f9fSMark Brown report = "unknown"; 923f59c8f9fSMark Brown else if (bypass) 924f59c8f9fSMark Brown report = "enabled"; 925f59c8f9fSMark Brown else 926f59c8f9fSMark Brown report = "disabled"; 927f59c8f9fSMark Brown 928f59c8f9fSMark Brown return sprintf(buf, "%s\n", report); 929f59c8f9fSMark Brown } 930f59c8f9fSMark Brown static DEVICE_ATTR(bypass, 0444, 931f59c8f9fSMark Brown regulator_bypass_show, NULL); 9327ad68e2fSDavid Brownell 933414c70cbSLiam Girdwood /* Calculate the new optimum regulator operating mode based on the new total 934414c70cbSLiam Girdwood * consumer load. All locks held by caller */ 9358460ef38SBjorn Andersson static int drms_uA_update(struct regulator_dev *rdev) 936414c70cbSLiam Girdwood { 937414c70cbSLiam Girdwood struct regulator *sibling; 938414c70cbSLiam Girdwood int current_uA = 0, output_uV, input_uV, err; 939414c70cbSLiam Girdwood unsigned int mode; 940414c70cbSLiam Girdwood 9418460ef38SBjorn Andersson /* 9428460ef38SBjorn Andersson * first check to see if we can set modes at all, otherwise just 9438460ef38SBjorn Andersson * tell the consumer everything is OK. 9448460ef38SBjorn Andersson */ 94574a569eeSMarc Gonzalez if (!regulator_ops_is_valid(rdev, REGULATOR_CHANGE_DRMS)) { 94674a569eeSMarc Gonzalez rdev_dbg(rdev, "DRMS operation not allowed\n"); 9478460ef38SBjorn Andersson return 0; 94874a569eeSMarc Gonzalez } 9498460ef38SBjorn Andersson 9508f4490e0SBjorn Andersson if (!rdev->desc->ops->get_optimum_mode && 9518f4490e0SBjorn Andersson !rdev->desc->ops->set_load) 9528460ef38SBjorn Andersson return 0; 9538460ef38SBjorn Andersson 9548f4490e0SBjorn Andersson if (!rdev->desc->ops->set_mode && 9558f4490e0SBjorn Andersson !rdev->desc->ops->set_load) 9568460ef38SBjorn Andersson return -EINVAL; 957414c70cbSLiam Girdwood 95857776617SJoonwoo Park /* calc total requested load */ 9595451781dSDouglas Anderson list_for_each_entry(sibling, &rdev->consumer_list, list) { 9605451781dSDouglas Anderson if (sibling->enable_count) 96157776617SJoonwoo Park current_uA += sibling->uA_load; 9625451781dSDouglas Anderson } 96357776617SJoonwoo Park 96457776617SJoonwoo Park current_uA += rdev->constraints->system_load; 96557776617SJoonwoo Park 96657776617SJoonwoo Park if (rdev->desc->ops->set_load) { 96757776617SJoonwoo Park /* set the optimum mode for our new total regulator load */ 96857776617SJoonwoo Park err = rdev->desc->ops->set_load(rdev, current_uA); 96957776617SJoonwoo Park if (err < 0) 97061aab5adSMichał Mirosław rdev_err(rdev, "failed to set load %d: %pe\n", 97161aab5adSMichał Mirosław current_uA, ERR_PTR(err)); 97257776617SJoonwoo Park } else { 973414c70cbSLiam Girdwood /* get output voltage */ 974d22b85a1SDmitry Osipenko output_uV = regulator_get_voltage_rdev(rdev); 9758460ef38SBjorn Andersson if (output_uV <= 0) { 9768460ef38SBjorn Andersson rdev_err(rdev, "invalid output voltage found\n"); 9778460ef38SBjorn Andersson return -EINVAL; 9788460ef38SBjorn Andersson } 979414c70cbSLiam Girdwood 980414c70cbSLiam Girdwood /* get input voltage */ 9811bf5a1f8SMark Brown input_uV = 0; 9821bf5a1f8SMark Brown if (rdev->supply) 9833f24f5adSAxel Lin input_uV = regulator_get_voltage(rdev->supply); 9841bf5a1f8SMark Brown if (input_uV <= 0) 985414c70cbSLiam Girdwood input_uV = rdev->constraints->input_uV; 9868460ef38SBjorn Andersson if (input_uV <= 0) { 9878460ef38SBjorn Andersson rdev_err(rdev, "invalid input voltage found\n"); 9888460ef38SBjorn Andersson return -EINVAL; 9898460ef38SBjorn Andersson } 990414c70cbSLiam Girdwood 991414c70cbSLiam Girdwood /* now get the optimum mode for our new total regulator load */ 992414c70cbSLiam Girdwood mode = rdev->desc->ops->get_optimum_mode(rdev, input_uV, 993414c70cbSLiam Girdwood output_uV, current_uA); 994414c70cbSLiam Girdwood 995414c70cbSLiam Girdwood /* check the new mode is allowed */ 9962c608234SMark Brown err = regulator_mode_constrain(rdev, &mode); 9978460ef38SBjorn Andersson if (err < 0) { 99861aab5adSMichał Mirosław rdev_err(rdev, "failed to get optimum mode @ %d uA %d -> %d uV: %pe\n", 99961aab5adSMichał Mirosław current_uA, input_uV, output_uV, ERR_PTR(err)); 10008460ef38SBjorn Andersson return err; 10018460ef38SBjorn Andersson } 10028460ef38SBjorn Andersson 10038460ef38SBjorn Andersson err = rdev->desc->ops->set_mode(rdev, mode); 10048460ef38SBjorn Andersson if (err < 0) 100561aab5adSMichał Mirosław rdev_err(rdev, "failed to set optimum mode %x: %pe\n", 100661aab5adSMichał Mirosław mode, ERR_PTR(err)); 10078f4490e0SBjorn Andersson } 10088460ef38SBjorn Andersson 10098460ef38SBjorn Andersson return err; 1010414c70cbSLiam Girdwood } 1011414c70cbSLiam Girdwood 10120955f5beSStephen Boyd static int __suspend_set_state(struct regulator_dev *rdev, 10130955f5beSStephen Boyd const struct regulator_state *rstate) 1014414c70cbSLiam Girdwood { 1015414c70cbSLiam Girdwood int ret = 0; 1016638f85c5SMark Brown 101772069f99SChunyan Zhang if (rstate->enabled == ENABLE_IN_SUSPEND && 101872069f99SChunyan Zhang rdev->desc->ops->set_suspend_enable) 1019414c70cbSLiam Girdwood ret = rdev->desc->ops->set_suspend_enable(rdev); 102072069f99SChunyan Zhang else if (rstate->enabled == DISABLE_IN_SUSPEND && 102172069f99SChunyan Zhang rdev->desc->ops->set_suspend_disable) 1022414c70cbSLiam Girdwood ret = rdev->desc->ops->set_suspend_disable(rdev); 10238ac0e95dSAxel Lin else /* OK if set_suspend_enable or set_suspend_disable is NULL */ 10248ac0e95dSAxel Lin ret = 0; 10258ac0e95dSAxel Lin 1026414c70cbSLiam Girdwood if (ret < 0) { 102761aab5adSMichał Mirosław rdev_err(rdev, "failed to enabled/disable: %pe\n", ERR_PTR(ret)); 1028414c70cbSLiam Girdwood return ret; 1029414c70cbSLiam Girdwood } 1030414c70cbSLiam Girdwood 1031414c70cbSLiam Girdwood if (rdev->desc->ops->set_suspend_voltage && rstate->uV > 0) { 1032414c70cbSLiam Girdwood ret = rdev->desc->ops->set_suspend_voltage(rdev, rstate->uV); 1033414c70cbSLiam Girdwood if (ret < 0) { 103461aab5adSMichał Mirosław rdev_err(rdev, "failed to set voltage: %pe\n", ERR_PTR(ret)); 1035414c70cbSLiam Girdwood return ret; 1036414c70cbSLiam Girdwood } 1037414c70cbSLiam Girdwood } 1038414c70cbSLiam Girdwood 1039414c70cbSLiam Girdwood if (rdev->desc->ops->set_suspend_mode && rstate->mode > 0) { 1040414c70cbSLiam Girdwood ret = rdev->desc->ops->set_suspend_mode(rdev, rstate->mode); 1041414c70cbSLiam Girdwood if (ret < 0) { 104261aab5adSMichał Mirosław rdev_err(rdev, "failed to set mode: %pe\n", ERR_PTR(ret)); 1043414c70cbSLiam Girdwood return ret; 1044414c70cbSLiam Girdwood } 1045414c70cbSLiam Girdwood } 1046f7efad10SChunyan Zhang 1047414c70cbSLiam Girdwood return ret; 1048414c70cbSLiam Girdwood } 1049414c70cbSLiam Girdwood 10500955f5beSStephen Boyd static int suspend_set_initial_state(struct regulator_dev *rdev) 10510955f5beSStephen Boyd { 10520955f5beSStephen Boyd const struct regulator_state *rstate; 10530955f5beSStephen Boyd 10540955f5beSStephen Boyd rstate = regulator_get_suspend_state_check(rdev, 10550955f5beSStephen Boyd rdev->constraints->initial_state); 10560955f5beSStephen Boyd if (!rstate) 10570955f5beSStephen Boyd return 0; 10580955f5beSStephen Boyd 10590955f5beSStephen Boyd return __suspend_set_state(rdev, rstate); 10600955f5beSStephen Boyd } 10610955f5beSStephen Boyd 1062c845f21aSGeert Uytterhoeven #if defined(DEBUG) || defined(CONFIG_DYNAMIC_DEBUG) 1063c845f21aSGeert Uytterhoeven static void print_constraints_debug(struct regulator_dev *rdev) 1064414c70cbSLiam Girdwood { 1065414c70cbSLiam Girdwood struct regulation_constraints *constraints = rdev->constraints; 1066a7068e39SStefan Wahren char buf[160] = ""; 10675751a99fSStefan Wahren size_t len = sizeof(buf) - 1; 10688f031b48SMark Brown int count = 0; 10698f031b48SMark Brown int ret; 1070414c70cbSLiam Girdwood 10718f031b48SMark Brown if (constraints->min_uV && constraints->max_uV) { 1072414c70cbSLiam Girdwood if (constraints->min_uV == constraints->max_uV) 10735751a99fSStefan Wahren count += scnprintf(buf + count, len - count, "%d mV ", 1074414c70cbSLiam Girdwood constraints->min_uV / 1000); 1075414c70cbSLiam Girdwood else 10765751a99fSStefan Wahren count += scnprintf(buf + count, len - count, 10775751a99fSStefan Wahren "%d <--> %d mV ", 1078414c70cbSLiam Girdwood constraints->min_uV / 1000, 1079414c70cbSLiam Girdwood constraints->max_uV / 1000); 10808f031b48SMark Brown } 10818f031b48SMark Brown 10828f031b48SMark Brown if (!constraints->min_uV || 10838f031b48SMark Brown constraints->min_uV != constraints->max_uV) { 1084d22b85a1SDmitry Osipenko ret = regulator_get_voltage_rdev(rdev); 10858f031b48SMark Brown if (ret > 0) 10865751a99fSStefan Wahren count += scnprintf(buf + count, len - count, 10875751a99fSStefan Wahren "at %d mV ", ret / 1000); 10888f031b48SMark Brown } 10898f031b48SMark Brown 1090bf5892a8SMark Brown if (constraints->uV_offset) 10915751a99fSStefan Wahren count += scnprintf(buf + count, len - count, "%dmV offset ", 1092bf5892a8SMark Brown constraints->uV_offset / 1000); 1093bf5892a8SMark Brown 10948f031b48SMark Brown if (constraints->min_uA && constraints->max_uA) { 1095414c70cbSLiam Girdwood if (constraints->min_uA == constraints->max_uA) 10965751a99fSStefan Wahren count += scnprintf(buf + count, len - count, "%d mA ", 1097414c70cbSLiam Girdwood constraints->min_uA / 1000); 1098414c70cbSLiam Girdwood else 10995751a99fSStefan Wahren count += scnprintf(buf + count, len - count, 11005751a99fSStefan Wahren "%d <--> %d mA ", 1101414c70cbSLiam Girdwood constraints->min_uA / 1000, 1102414c70cbSLiam Girdwood constraints->max_uA / 1000); 1103414c70cbSLiam Girdwood } 11048f031b48SMark Brown 11058f031b48SMark Brown if (!constraints->min_uA || 11068f031b48SMark Brown constraints->min_uA != constraints->max_uA) { 11078f031b48SMark Brown ret = _regulator_get_current_limit(rdev); 11088f031b48SMark Brown if (ret > 0) 11095751a99fSStefan Wahren count += scnprintf(buf + count, len - count, 11105751a99fSStefan Wahren "at %d mA ", ret / 1000); 11118f031b48SMark Brown } 11128f031b48SMark Brown 1113414c70cbSLiam Girdwood if (constraints->valid_modes_mask & REGULATOR_MODE_FAST) 11145751a99fSStefan Wahren count += scnprintf(buf + count, len - count, "fast "); 1115414c70cbSLiam Girdwood if (constraints->valid_modes_mask & REGULATOR_MODE_NORMAL) 11165751a99fSStefan Wahren count += scnprintf(buf + count, len - count, "normal "); 1117414c70cbSLiam Girdwood if (constraints->valid_modes_mask & REGULATOR_MODE_IDLE) 11185751a99fSStefan Wahren count += scnprintf(buf + count, len - count, "idle "); 1119414c70cbSLiam Girdwood if (constraints->valid_modes_mask & REGULATOR_MODE_STANDBY) 11205751a99fSStefan Wahren count += scnprintf(buf + count, len - count, "standby "); 1121414c70cbSLiam Girdwood 1122215b8b05SUwe Kleine-König if (!count) 112399ad5f6eSMichał Mirosław count = scnprintf(buf, len, "no parameters"); 112499ad5f6eSMichał Mirosław else 112599ad5f6eSMichał Mirosław --count; 112699ad5f6eSMichał Mirosław 112799ad5f6eSMichał Mirosław count += scnprintf(buf + count, len - count, ", %s", 112899ad5f6eSMichał Mirosław _regulator_is_enabled(rdev) ? "enabled" : "disabled"); 1129215b8b05SUwe Kleine-König 1130194dbaefSMark Brown rdev_dbg(rdev, "%s\n", buf); 1131c845f21aSGeert Uytterhoeven } 1132c845f21aSGeert Uytterhoeven #else /* !DEBUG && !CONFIG_DYNAMIC_DEBUG */ 1133c845f21aSGeert Uytterhoeven static inline void print_constraints_debug(struct regulator_dev *rdev) {} 1134c845f21aSGeert Uytterhoeven #endif /* !DEBUG && !CONFIG_DYNAMIC_DEBUG */ 1135c845f21aSGeert Uytterhoeven 1136c845f21aSGeert Uytterhoeven static void print_constraints(struct regulator_dev *rdev) 1137c845f21aSGeert Uytterhoeven { 1138c845f21aSGeert Uytterhoeven struct regulation_constraints *constraints = rdev->constraints; 1139c845f21aSGeert Uytterhoeven 1140c845f21aSGeert Uytterhoeven print_constraints_debug(rdev); 11414a682922SMark Brown 11424a682922SMark Brown if ((constraints->min_uV != constraints->max_uV) && 11438a34e979SWEN Pingbo !regulator_ops_is_valid(rdev, REGULATOR_CHANGE_VOLTAGE)) 11444a682922SMark Brown rdev_warn(rdev, 11454a682922SMark Brown "Voltage range but no REGULATOR_CHANGE_VOLTAGE\n"); 1146414c70cbSLiam Girdwood } 1147414c70cbSLiam Girdwood 1148e79055d6SMark Brown static int machine_constraints_voltage(struct regulator_dev *rdev, 11491083c393SMark Brown struct regulation_constraints *constraints) 1150e79055d6SMark Brown { 1151272e2315SGuodong Xu const struct regulator_ops *ops = rdev->desc->ops; 1152af5866c9SMark Brown int ret; 1153af5866c9SMark Brown 1154af5866c9SMark Brown /* do we need to apply the constraint voltage */ 1155af5866c9SMark Brown if (rdev->constraints->apply_uV && 1156fa93fd4eSMark Brown rdev->constraints->min_uV && rdev->constraints->max_uV) { 1157fa93fd4eSMark Brown int target_min, target_max; 1158d22b85a1SDmitry Osipenko int current_uV = regulator_get_voltage_rdev(rdev); 115984b3a7c9SDouglas Anderson 116084b3a7c9SDouglas Anderson if (current_uV == -ENOTRECOVERABLE) { 116148f1b4efSKrzysztof Kozlowski /* This regulator can't be read and must be initialized */ 116284b3a7c9SDouglas Anderson rdev_info(rdev, "Setting %d-%duV\n", 116384b3a7c9SDouglas Anderson rdev->constraints->min_uV, 116484b3a7c9SDouglas Anderson rdev->constraints->max_uV); 116584b3a7c9SDouglas Anderson _regulator_do_set_voltage(rdev, 116684b3a7c9SDouglas Anderson rdev->constraints->min_uV, 116784b3a7c9SDouglas Anderson rdev->constraints->max_uV); 1168d22b85a1SDmitry Osipenko current_uV = regulator_get_voltage_rdev(rdev); 116984b3a7c9SDouglas Anderson } 117084b3a7c9SDouglas Anderson 1171064d5cd1SAlban Bedel if (current_uV < 0) { 117269d58839SNishanth Menon rdev_err(rdev, 117361aab5adSMichał Mirosław "failed to get the current voltage: %pe\n", 117461aab5adSMichał Mirosław ERR_PTR(current_uV)); 1175064d5cd1SAlban Bedel return current_uV; 1176064d5cd1SAlban Bedel } 1177fa93fd4eSMark Brown 1178fa93fd4eSMark Brown /* 1179fa93fd4eSMark Brown * If we're below the minimum voltage move up to the 1180fa93fd4eSMark Brown * minimum voltage, if we're above the maximum voltage 1181fa93fd4eSMark Brown * then move down to the maximum. 1182fa93fd4eSMark Brown */ 1183fa93fd4eSMark Brown target_min = current_uV; 1184fa93fd4eSMark Brown target_max = current_uV; 1185fa93fd4eSMark Brown 1186fa93fd4eSMark Brown if (current_uV < rdev->constraints->min_uV) { 1187fa93fd4eSMark Brown target_min = rdev->constraints->min_uV; 1188fa93fd4eSMark Brown target_max = rdev->constraints->min_uV; 1189fa93fd4eSMark Brown } 1190fa93fd4eSMark Brown 1191fa93fd4eSMark Brown if (current_uV > rdev->constraints->max_uV) { 1192fa93fd4eSMark Brown target_min = rdev->constraints->max_uV; 1193fa93fd4eSMark Brown target_max = rdev->constraints->max_uV; 1194fa93fd4eSMark Brown } 1195fa93fd4eSMark Brown 1196fa93fd4eSMark Brown if (target_min != current_uV || target_max != current_uV) { 119745a91e8fSMark Brown rdev_info(rdev, "Bringing %duV into %d-%duV\n", 119845a91e8fSMark Brown current_uV, target_min, target_max); 1199064d5cd1SAlban Bedel ret = _regulator_do_set_voltage( 1200fa93fd4eSMark Brown rdev, target_min, target_max); 1201af5866c9SMark Brown if (ret < 0) { 1202064d5cd1SAlban Bedel rdev_err(rdev, 120361aab5adSMichał Mirosław "failed to apply %d-%duV constraint: %pe\n", 120461aab5adSMichał Mirosław target_min, target_max, ERR_PTR(ret)); 1205af5866c9SMark Brown return ret; 1206af5866c9SMark Brown } 1207af5866c9SMark Brown } 1208064d5cd1SAlban Bedel } 1209e79055d6SMark Brown 1210e79055d6SMark Brown /* constrain machine-level voltage specs to fit 1211e79055d6SMark Brown * the actual range supported by this regulator. 1212e79055d6SMark Brown */ 1213e79055d6SMark Brown if (ops->list_voltage && rdev->desc->n_voltages) { 1214e79055d6SMark Brown int count = rdev->desc->n_voltages; 1215e79055d6SMark Brown int i; 1216e79055d6SMark Brown int min_uV = INT_MAX; 1217e79055d6SMark Brown int max_uV = INT_MIN; 1218e79055d6SMark Brown int cmin = constraints->min_uV; 1219e79055d6SMark Brown int cmax = constraints->max_uV; 1220e79055d6SMark Brown 1221e79055d6SMark Brown /* it's safe to autoconfigure fixed-voltage supplies 1222e79055d6SMark Brown and the constraints are used by list_voltage. */ 1223e79055d6SMark Brown if (count == 1 && !cmin) { 1224e79055d6SMark Brown cmin = 1; 1225e79055d6SMark Brown cmax = INT_MAX; 1226e79055d6SMark Brown constraints->min_uV = cmin; 1227e79055d6SMark Brown constraints->max_uV = cmax; 1228e79055d6SMark Brown } 1229e79055d6SMark Brown 1230e79055d6SMark Brown /* voltage constraints are optional */ 1231e79055d6SMark Brown if ((cmin == 0) && (cmax == 0)) 1232e79055d6SMark Brown return 0; 1233e79055d6SMark Brown 1234e79055d6SMark Brown /* else require explicit machine-level constraints */ 1235e79055d6SMark Brown if (cmin <= 0 || cmax <= 0 || cmax < cmin) { 12365da84fd9SJoe Perches rdev_err(rdev, "invalid voltage constraints\n"); 1237e79055d6SMark Brown return -EINVAL; 1238e79055d6SMark Brown } 1239e79055d6SMark Brown 12406d30fc51SCristian Marussi /* no need to loop voltages if range is continuous */ 12416d30fc51SCristian Marussi if (rdev->desc->continuous_voltage_range) 12426d30fc51SCristian Marussi return 0; 12436d30fc51SCristian Marussi 1244e79055d6SMark Brown /* initial: [cmin..cmax] valid, [min_uV..max_uV] not */ 1245e79055d6SMark Brown for (i = 0; i < count; i++) { 1246e79055d6SMark Brown int value; 1247e79055d6SMark Brown 1248e79055d6SMark Brown value = ops->list_voltage(rdev, i); 1249e79055d6SMark Brown if (value <= 0) 1250e79055d6SMark Brown continue; 1251e79055d6SMark Brown 1252e79055d6SMark Brown /* maybe adjust [min_uV..max_uV] */ 1253e79055d6SMark Brown if (value >= cmin && value < min_uV) 1254e79055d6SMark Brown min_uV = value; 1255e79055d6SMark Brown if (value <= cmax && value > max_uV) 1256e79055d6SMark Brown max_uV = value; 1257e79055d6SMark Brown } 1258e79055d6SMark Brown 1259e79055d6SMark Brown /* final: [min_uV..max_uV] valid iff constraints valid */ 1260e79055d6SMark Brown if (max_uV < min_uV) { 1261fff15befSMark Brown rdev_err(rdev, 1262fff15befSMark Brown "unsupportable voltage constraints %u-%uuV\n", 1263fff15befSMark Brown min_uV, max_uV); 1264e79055d6SMark Brown return -EINVAL; 1265e79055d6SMark Brown } 1266e79055d6SMark Brown 1267e79055d6SMark Brown /* use regulator's subset of machine constraints */ 1268e79055d6SMark Brown if (constraints->min_uV < min_uV) { 12695da84fd9SJoe Perches rdev_dbg(rdev, "override min_uV, %d -> %d\n", 12705da84fd9SJoe Perches constraints->min_uV, min_uV); 1271e79055d6SMark Brown constraints->min_uV = min_uV; 1272e79055d6SMark Brown } 1273e79055d6SMark Brown if (constraints->max_uV > max_uV) { 12745da84fd9SJoe Perches rdev_dbg(rdev, "override max_uV, %d -> %d\n", 12755da84fd9SJoe Perches constraints->max_uV, max_uV); 1276e79055d6SMark Brown constraints->max_uV = max_uV; 1277e79055d6SMark Brown } 1278e79055d6SMark Brown } 1279e79055d6SMark Brown 1280e79055d6SMark Brown return 0; 1281e79055d6SMark Brown } 1282e79055d6SMark Brown 1283f8c1700dSLaxman Dewangan static int machine_constraints_current(struct regulator_dev *rdev, 1284f8c1700dSLaxman Dewangan struct regulation_constraints *constraints) 1285f8c1700dSLaxman Dewangan { 1286272e2315SGuodong Xu const struct regulator_ops *ops = rdev->desc->ops; 1287f8c1700dSLaxman Dewangan int ret; 1288f8c1700dSLaxman Dewangan 1289f8c1700dSLaxman Dewangan if (!constraints->min_uA && !constraints->max_uA) 1290f8c1700dSLaxman Dewangan return 0; 1291f8c1700dSLaxman Dewangan 1292f8c1700dSLaxman Dewangan if (constraints->min_uA > constraints->max_uA) { 1293f8c1700dSLaxman Dewangan rdev_err(rdev, "Invalid current constraints\n"); 1294f8c1700dSLaxman Dewangan return -EINVAL; 1295f8c1700dSLaxman Dewangan } 1296f8c1700dSLaxman Dewangan 1297f8c1700dSLaxman Dewangan if (!ops->set_current_limit || !ops->get_current_limit) { 1298f8c1700dSLaxman Dewangan rdev_warn(rdev, "Operation of current configuration missing\n"); 1299f8c1700dSLaxman Dewangan return 0; 1300f8c1700dSLaxman Dewangan } 1301f8c1700dSLaxman Dewangan 1302f8c1700dSLaxman Dewangan /* Set regulator current in constraints range */ 1303f8c1700dSLaxman Dewangan ret = ops->set_current_limit(rdev, constraints->min_uA, 1304f8c1700dSLaxman Dewangan constraints->max_uA); 1305f8c1700dSLaxman Dewangan if (ret < 0) { 1306f8c1700dSLaxman Dewangan rdev_err(rdev, "Failed to set current constraint, %d\n", ret); 1307f8c1700dSLaxman Dewangan return ret; 1308f8c1700dSLaxman Dewangan } 1309f8c1700dSLaxman Dewangan 1310f8c1700dSLaxman Dewangan return 0; 1311f8c1700dSLaxman Dewangan } 1312f8c1700dSLaxman Dewangan 131330c21971SMarkus Pargmann static int _regulator_do_enable(struct regulator_dev *rdev); 131430c21971SMarkus Pargmann 1315a5766f11SLiam Girdwood /** 1316a5766f11SLiam Girdwood * set_machine_constraints - sets regulator constraints 131769279fb9SMark Brown * @rdev: regulator source 1318a5766f11SLiam Girdwood * 1319a5766f11SLiam Girdwood * Allows platform initialisation code to define and constrain 1320a5766f11SLiam Girdwood * regulator circuits e.g. valid voltage/current ranges, etc. NOTE: 1321a5766f11SLiam Girdwood * Constraints *must* be set by platform code in order for some 1322a5766f11SLiam Girdwood * regulator operations to proceed i.e. set_voltage, set_current_limit, 1323a5766f11SLiam Girdwood * set_mode. 1324a5766f11SLiam Girdwood */ 132557a6ad48SMichał Mirosław static int set_machine_constraints(struct regulator_dev *rdev) 1326a5766f11SLiam Girdwood { 1327a5766f11SLiam Girdwood int ret = 0; 1328272e2315SGuodong Xu const struct regulator_ops *ops = rdev->desc->ops; 1329e06f5b4fSMark Brown 1330f8c12fe3SMark Brown ret = machine_constraints_voltage(rdev, rdev->constraints); 1331e79055d6SMark Brown if (ret != 0) 13326333ef46SCharles Keepax return ret; 13333e2b9abdSMark Brown 1334f8c1700dSLaxman Dewangan ret = machine_constraints_current(rdev, rdev->constraints); 1335f8c1700dSLaxman Dewangan if (ret != 0) 13366333ef46SCharles Keepax return ret; 1337f8c1700dSLaxman Dewangan 133836e4f839SStephen Boyd if (rdev->constraints->ilim_uA && ops->set_input_current_limit) { 133936e4f839SStephen Boyd ret = ops->set_input_current_limit(rdev, 134036e4f839SStephen Boyd rdev->constraints->ilim_uA); 134136e4f839SStephen Boyd if (ret < 0) { 134261aab5adSMichał Mirosław rdev_err(rdev, "failed to set input limit: %pe\n", ERR_PTR(ret)); 13436333ef46SCharles Keepax return ret; 134436e4f839SStephen Boyd } 134536e4f839SStephen Boyd } 134636e4f839SStephen Boyd 1347a5766f11SLiam Girdwood /* do we need to setup our suspend state */ 13489a8f5e07SMark Brown if (rdev->constraints->initial_state) { 13490955f5beSStephen Boyd ret = suspend_set_initial_state(rdev); 1350e06f5b4fSMark Brown if (ret < 0) { 135161aab5adSMichał Mirosław rdev_err(rdev, "failed to set suspend state: %pe\n", ERR_PTR(ret)); 13526333ef46SCharles Keepax return ret; 1353e06f5b4fSMark Brown } 1354e06f5b4fSMark Brown } 1355a5766f11SLiam Girdwood 13569a8f5e07SMark Brown if (rdev->constraints->initial_mode) { 1357a308466cSMark Brown if (!ops->set_mode) { 13585da84fd9SJoe Perches rdev_err(rdev, "no set_mode operation\n"); 13596333ef46SCharles Keepax return -EINVAL; 1360a308466cSMark Brown } 1361a308466cSMark Brown 1362f8c12fe3SMark Brown ret = ops->set_mode(rdev, rdev->constraints->initial_mode); 1363a308466cSMark Brown if (ret < 0) { 136461aab5adSMichał Mirosław rdev_err(rdev, "failed to set initial mode: %pe\n", ERR_PTR(ret)); 13656333ef46SCharles Keepax return ret; 1366a308466cSMark Brown } 1367fa94e48eSDouglas Anderson } else if (rdev->constraints->system_load) { 1368fa94e48eSDouglas Anderson /* 1369fa94e48eSDouglas Anderson * We'll only apply the initial system load if an 1370fa94e48eSDouglas Anderson * initial mode wasn't specified. 1371fa94e48eSDouglas Anderson */ 1372fa94e48eSDouglas Anderson drms_uA_update(rdev); 1373a308466cSMark Brown } 1374a308466cSMark Brown 13751653ccf4SYadwinder Singh Brar if ((rdev->constraints->ramp_delay || rdev->constraints->ramp_disable) 13761653ccf4SYadwinder Singh Brar && ops->set_ramp_delay) { 13776f0b2c69SYadwinder Singh Brar ret = ops->set_ramp_delay(rdev, rdev->constraints->ramp_delay); 13786f0b2c69SYadwinder Singh Brar if (ret < 0) { 137961aab5adSMichał Mirosław rdev_err(rdev, "failed to set ramp_delay: %pe\n", ERR_PTR(ret)); 13806333ef46SCharles Keepax return ret; 13816f0b2c69SYadwinder Singh Brar } 13826f0b2c69SYadwinder Singh Brar } 13836f0b2c69SYadwinder Singh Brar 138423c779b9SStephen Boyd if (rdev->constraints->pull_down && ops->set_pull_down) { 138523c779b9SStephen Boyd ret = ops->set_pull_down(rdev); 138623c779b9SStephen Boyd if (ret < 0) { 138761aab5adSMichał Mirosław rdev_err(rdev, "failed to set pull down: %pe\n", ERR_PTR(ret)); 13886333ef46SCharles Keepax return ret; 138923c779b9SStephen Boyd } 139023c779b9SStephen Boyd } 139123c779b9SStephen Boyd 139257f66b78SStephen Boyd if (rdev->constraints->soft_start && ops->set_soft_start) { 139357f66b78SStephen Boyd ret = ops->set_soft_start(rdev); 139457f66b78SStephen Boyd if (ret < 0) { 139561aab5adSMichał Mirosław rdev_err(rdev, "failed to set soft start: %pe\n", ERR_PTR(ret)); 13966333ef46SCharles Keepax return ret; 139757f66b78SStephen Boyd } 139857f66b78SStephen Boyd } 139957f66b78SStephen Boyd 14003a003baeSStephen Boyd if (rdev->constraints->over_current_protection 14013a003baeSStephen Boyd && ops->set_over_current_protection) { 14023a003baeSStephen Boyd ret = ops->set_over_current_protection(rdev); 14033a003baeSStephen Boyd if (ret < 0) { 140461aab5adSMichał Mirosław rdev_err(rdev, "failed to set over current protection: %pe\n", 140561aab5adSMichał Mirosław ERR_PTR(ret)); 14066333ef46SCharles Keepax return ret; 14073a003baeSStephen Boyd } 14083a003baeSStephen Boyd } 14093a003baeSStephen Boyd 1410670666b9SLaxman Dewangan if (rdev->constraints->active_discharge && ops->set_active_discharge) { 1411670666b9SLaxman Dewangan bool ad_state = (rdev->constraints->active_discharge == 1412670666b9SLaxman Dewangan REGULATOR_ACTIVE_DISCHARGE_ENABLE) ? true : false; 1413670666b9SLaxman Dewangan 1414670666b9SLaxman Dewangan ret = ops->set_active_discharge(rdev, ad_state); 1415670666b9SLaxman Dewangan if (ret < 0) { 141661aab5adSMichał Mirosław rdev_err(rdev, "failed to set active discharge: %pe\n", ERR_PTR(ret)); 1417670666b9SLaxman Dewangan return ret; 1418670666b9SLaxman Dewangan } 1419670666b9SLaxman Dewangan } 1420670666b9SLaxman Dewangan 14212bb16663SOlliver Schinagl /* If the constraints say the regulator should be on at this point 14222bb16663SOlliver Schinagl * and we have control then make sure it is enabled. 14232bb16663SOlliver Schinagl */ 14242bb16663SOlliver Schinagl if (rdev->constraints->always_on || rdev->constraints->boot_on) { 142505f224caSDouglas Anderson if (rdev->supply) { 142605f224caSDouglas Anderson ret = regulator_enable(rdev->supply); 142705f224caSDouglas Anderson if (ret < 0) { 142805f224caSDouglas Anderson _regulator_put(rdev->supply); 142905f224caSDouglas Anderson rdev->supply = NULL; 143005f224caSDouglas Anderson return ret; 143105f224caSDouglas Anderson } 143205f224caSDouglas Anderson } 143305f224caSDouglas Anderson 14342bb16663SOlliver Schinagl ret = _regulator_do_enable(rdev); 14352bb16663SOlliver Schinagl if (ret < 0 && ret != -EINVAL) { 143661aab5adSMichał Mirosław rdev_err(rdev, "failed to enable: %pe\n", ERR_PTR(ret)); 14372bb16663SOlliver Schinagl return ret; 14382bb16663SOlliver Schinagl } 1439089b3f61SPascal Paillet 1440089b3f61SPascal Paillet if (rdev->constraints->always_on) 144105f224caSDouglas Anderson rdev->use_count++; 1442*a5ccccb3SVincent Whitchurch } else if (rdev->desc->off_on_delay) { 1443*a5ccccb3SVincent Whitchurch rdev->last_off_jiffy = jiffies; 14442bb16663SOlliver Schinagl } 14452bb16663SOlliver Schinagl 1446a5766f11SLiam Girdwood print_constraints(rdev); 14471a6958e7SAxel Lin return 0; 1448a5766f11SLiam Girdwood } 1449a5766f11SLiam Girdwood 1450a5766f11SLiam Girdwood /** 1451a5766f11SLiam Girdwood * set_supply - set regulator supply regulator 145269279fb9SMark Brown * @rdev: regulator name 145369279fb9SMark Brown * @supply_rdev: supply regulator name 1454a5766f11SLiam Girdwood * 1455a5766f11SLiam Girdwood * Called by platform initialisation code to set the supply regulator for this 1456a5766f11SLiam Girdwood * regulator. This ensures that a regulators supply will also be enabled by the 1457a5766f11SLiam Girdwood * core if it's child is enabled. 1458a5766f11SLiam Girdwood */ 1459a5766f11SLiam Girdwood static int set_supply(struct regulator_dev *rdev, 1460a5766f11SLiam Girdwood struct regulator_dev *supply_rdev) 1461a5766f11SLiam Girdwood { 1462a5766f11SLiam Girdwood int err; 1463a5766f11SLiam Girdwood 14643801b86aSMark Brown rdev_info(rdev, "supplied by %s\n", rdev_get_name(supply_rdev)); 14653801b86aSMark Brown 1466e2c09ae7SJavier Martinez Canillas if (!try_module_get(supply_rdev->owner)) 1467e2c09ae7SJavier Martinez Canillas return -ENODEV; 1468e2c09ae7SJavier Martinez Canillas 14693801b86aSMark Brown rdev->supply = create_regulator(supply_rdev, &rdev->dev, "SUPPLY"); 147032c78de8SAxel Lin if (rdev->supply == NULL) { 147132c78de8SAxel Lin err = -ENOMEM; 1472a5766f11SLiam Girdwood return err; 1473a5766f11SLiam Girdwood } 147457ad526aSLaxman Dewangan supply_rdev->open_count++; 1475a5766f11SLiam Girdwood 14763801b86aSMark Brown return 0; 14773801b86aSMark Brown } 14783801b86aSMark Brown 1479a5766f11SLiam Girdwood /** 148006c63f93SRandy Dunlap * set_consumer_device_supply - Bind a regulator to a symbolic supply 148169279fb9SMark Brown * @rdev: regulator source 148240f9244fSMark Brown * @consumer_dev_name: dev_name() string for device supply applies to 1483a5766f11SLiam Girdwood * @supply: symbolic name for supply 1484a5766f11SLiam Girdwood * 1485a5766f11SLiam Girdwood * Allows platform initialisation code to map physical regulator 1486a5766f11SLiam Girdwood * sources to symbolic names for supplies for use by devices. Devices 1487a5766f11SLiam Girdwood * should use these symbolic names to request regulators, avoiding the 1488a5766f11SLiam Girdwood * need to provide board-specific regulator names as platform data. 1489a5766f11SLiam Girdwood */ 1490a5766f11SLiam Girdwood static int set_consumer_device_supply(struct regulator_dev *rdev, 1491737f360dSMark Brown const char *consumer_dev_name, 149240f9244fSMark Brown const char *supply) 1493a5766f11SLiam Girdwood { 14945c065401SMichał Mirosław struct regulator_map *node, *new_node; 14959ed2099eSMark Brown int has_dev; 1496a5766f11SLiam Girdwood 1497a5766f11SLiam Girdwood if (supply == NULL) 1498a5766f11SLiam Girdwood return -EINVAL; 1499a5766f11SLiam Girdwood 15009ed2099eSMark Brown if (consumer_dev_name != NULL) 15019ed2099eSMark Brown has_dev = 1; 15029ed2099eSMark Brown else 15039ed2099eSMark Brown has_dev = 0; 15049ed2099eSMark Brown 15055c065401SMichał Mirosław new_node = kzalloc(sizeof(struct regulator_map), GFP_KERNEL); 15065c065401SMichał Mirosław if (new_node == NULL) 15075c065401SMichał Mirosław return -ENOMEM; 15085c065401SMichał Mirosław 15095c065401SMichał Mirosław new_node->regulator = rdev; 15105c065401SMichał Mirosław new_node->supply = supply; 15115c065401SMichał Mirosław 15125c065401SMichał Mirosław if (has_dev) { 15135c065401SMichał Mirosław new_node->dev_name = kstrdup(consumer_dev_name, GFP_KERNEL); 15145c065401SMichał Mirosław if (new_node->dev_name == NULL) { 15155c065401SMichał Mirosław kfree(new_node); 15165c065401SMichał Mirosław return -ENOMEM; 15175c065401SMichał Mirosław } 15185c065401SMichał Mirosław } 15195c065401SMichał Mirosław 15205c065401SMichał Mirosław mutex_lock(®ulator_list_mutex); 15216001e13cSDavid Brownell list_for_each_entry(node, ®ulator_map_list, list) { 152223b5cc2aSJani Nikula if (node->dev_name && consumer_dev_name) { 152323b5cc2aSJani Nikula if (strcmp(node->dev_name, consumer_dev_name) != 0) 15246001e13cSDavid Brownell continue; 152523b5cc2aSJani Nikula } else if (node->dev_name || consumer_dev_name) { 152623b5cc2aSJani Nikula continue; 152723b5cc2aSJani Nikula } 152823b5cc2aSJani Nikula 15296001e13cSDavid Brownell if (strcmp(node->supply, supply) != 0) 15306001e13cSDavid Brownell continue; 15316001e13cSDavid Brownell 1532737f360dSMark Brown pr_debug("%s: %s/%s is '%s' supply; fail %s/%s\n", 1533737f360dSMark Brown consumer_dev_name, 15346001e13cSDavid Brownell dev_name(&node->regulator->dev), 15356001e13cSDavid Brownell node->regulator->desc->name, 15366001e13cSDavid Brownell supply, 15371083c393SMark Brown dev_name(&rdev->dev), rdev_get_name(rdev)); 15385c065401SMichał Mirosław goto fail; 15396001e13cSDavid Brownell } 15406001e13cSDavid Brownell 15415c065401SMichał Mirosław list_add(&new_node->list, ®ulator_map_list); 15425c065401SMichał Mirosław mutex_unlock(®ulator_list_mutex); 1543a5766f11SLiam Girdwood 1544a5766f11SLiam Girdwood return 0; 15455c065401SMichał Mirosław 15465c065401SMichał Mirosław fail: 15475c065401SMichał Mirosław mutex_unlock(®ulator_list_mutex); 15485c065401SMichał Mirosław kfree(new_node->dev_name); 15495c065401SMichał Mirosław kfree(new_node); 15505c065401SMichał Mirosław return -EBUSY; 1551a5766f11SLiam Girdwood } 1552a5766f11SLiam Girdwood 15530f1d747bSMike Rapoport static void unset_regulator_supplies(struct regulator_dev *rdev) 15540f1d747bSMike Rapoport { 15550f1d747bSMike Rapoport struct regulator_map *node, *n; 15560f1d747bSMike Rapoport 15570f1d747bSMike Rapoport list_for_each_entry_safe(node, n, ®ulator_map_list, list) { 15580f1d747bSMike Rapoport if (rdev == node->regulator) { 15590f1d747bSMike Rapoport list_del(&node->list); 156040f9244fSMark Brown kfree(node->dev_name); 15610f1d747bSMike Rapoport kfree(node); 15620f1d747bSMike Rapoport } 15630f1d747bSMike Rapoport } 15640f1d747bSMike Rapoport } 15650f1d747bSMike Rapoport 15662d80a91bSRichard Fitzgerald #ifdef CONFIG_DEBUG_FS 15672d80a91bSRichard Fitzgerald static ssize_t constraint_flags_read_file(struct file *file, 15682d80a91bSRichard Fitzgerald char __user *user_buf, 15692d80a91bSRichard Fitzgerald size_t count, loff_t *ppos) 15702d80a91bSRichard Fitzgerald { 15712d80a91bSRichard Fitzgerald const struct regulator *regulator = file->private_data; 15722d80a91bSRichard Fitzgerald const struct regulation_constraints *c = regulator->rdev->constraints; 15732d80a91bSRichard Fitzgerald char *buf; 15742d80a91bSRichard Fitzgerald ssize_t ret; 15752d80a91bSRichard Fitzgerald 15762d80a91bSRichard Fitzgerald if (!c) 15772d80a91bSRichard Fitzgerald return 0; 15782d80a91bSRichard Fitzgerald 15792d80a91bSRichard Fitzgerald buf = kmalloc(PAGE_SIZE, GFP_KERNEL); 15802d80a91bSRichard Fitzgerald if (!buf) 15812d80a91bSRichard Fitzgerald return -ENOMEM; 15822d80a91bSRichard Fitzgerald 15832d80a91bSRichard Fitzgerald ret = snprintf(buf, PAGE_SIZE, 15842d80a91bSRichard Fitzgerald "always_on: %u\n" 15852d80a91bSRichard Fitzgerald "boot_on: %u\n" 15862d80a91bSRichard Fitzgerald "apply_uV: %u\n" 15872d80a91bSRichard Fitzgerald "ramp_disable: %u\n" 15882d80a91bSRichard Fitzgerald "soft_start: %u\n" 15892d80a91bSRichard Fitzgerald "pull_down: %u\n" 15902d80a91bSRichard Fitzgerald "over_current_protection: %u\n", 15912d80a91bSRichard Fitzgerald c->always_on, 15922d80a91bSRichard Fitzgerald c->boot_on, 15932d80a91bSRichard Fitzgerald c->apply_uV, 15942d80a91bSRichard Fitzgerald c->ramp_disable, 15952d80a91bSRichard Fitzgerald c->soft_start, 15962d80a91bSRichard Fitzgerald c->pull_down, 15972d80a91bSRichard Fitzgerald c->over_current_protection); 15982d80a91bSRichard Fitzgerald 15992d80a91bSRichard Fitzgerald ret = simple_read_from_buffer(user_buf, count, ppos, buf, ret); 16002d80a91bSRichard Fitzgerald kfree(buf); 16012d80a91bSRichard Fitzgerald 16022d80a91bSRichard Fitzgerald return ret; 16032d80a91bSRichard Fitzgerald } 16042d80a91bSRichard Fitzgerald 16052d80a91bSRichard Fitzgerald #endif 16062d80a91bSRichard Fitzgerald 16072d80a91bSRichard Fitzgerald static const struct file_operations constraint_flags_fops = { 16082d80a91bSRichard Fitzgerald #ifdef CONFIG_DEBUG_FS 16092d80a91bSRichard Fitzgerald .open = simple_open, 16102d80a91bSRichard Fitzgerald .read = constraint_flags_read_file, 16112d80a91bSRichard Fitzgerald .llseek = default_llseek, 16122d80a91bSRichard Fitzgerald #endif 16132d80a91bSRichard Fitzgerald }; 16142d80a91bSRichard Fitzgerald 1615f5726ae3SMark Brown #define REG_STR_SIZE 64 1616414c70cbSLiam Girdwood 1617414c70cbSLiam Girdwood static struct regulator *create_regulator(struct regulator_dev *rdev, 1618414c70cbSLiam Girdwood struct device *dev, 1619414c70cbSLiam Girdwood const char *supply_name) 1620414c70cbSLiam Girdwood { 1621414c70cbSLiam Girdwood struct regulator *regulator; 1622dbe954d8SHans de Goede int err = 0; 1623414c70cbSLiam Girdwood 162487fe29b6SMichał Mirosław if (dev) { 162587fe29b6SMichał Mirosław char buf[REG_STR_SIZE]; 162687fe29b6SMichał Mirosław int size; 162787fe29b6SMichał Mirosław 162887fe29b6SMichał Mirosław size = snprintf(buf, REG_STR_SIZE, "%s-%s", 162987fe29b6SMichał Mirosław dev->kobj.name, supply_name); 163087fe29b6SMichał Mirosław if (size >= REG_STR_SIZE) 1631414c70cbSLiam Girdwood return NULL; 1632414c70cbSLiam Girdwood 163387fe29b6SMichał Mirosław supply_name = kstrdup(buf, GFP_KERNEL); 163487fe29b6SMichał Mirosław if (supply_name == NULL) 163587fe29b6SMichał Mirosław return NULL; 163687fe29b6SMichał Mirosław } else { 163787fe29b6SMichał Mirosław supply_name = kstrdup_const(supply_name, GFP_KERNEL); 163887fe29b6SMichał Mirosław if (supply_name == NULL) 163987fe29b6SMichał Mirosław return NULL; 164087fe29b6SMichał Mirosław } 164187fe29b6SMichał Mirosław 164287fe29b6SMichał Mirosław regulator = kzalloc(sizeof(*regulator), GFP_KERNEL); 164387fe29b6SMichał Mirosław if (regulator == NULL) { 164487fe29b6SMichał Mirosław kfree(supply_name); 164587fe29b6SMichał Mirosław return NULL; 164687fe29b6SMichał Mirosław } 164787fe29b6SMichał Mirosław 1648414c70cbSLiam Girdwood regulator->rdev = rdev; 164987fe29b6SMichał Mirosław regulator->supply_name = supply_name; 165087fe29b6SMichał Mirosław 165187fe29b6SMichał Mirosław regulator_lock(rdev); 1652414c70cbSLiam Girdwood list_add(®ulator->list, &rdev->consumer_list); 165387fe29b6SMichał Mirosław regulator_unlock(rdev); 1654414c70cbSLiam Girdwood 1655414c70cbSLiam Girdwood if (dev) { 1656e2c98eafSShawn Guo regulator->dev = dev; 1657e2c98eafSShawn Guo 1658222cc7b1SMark Brown /* Add a link to the device sysfs entry */ 1659ff268b56SStephen Boyd err = sysfs_create_link_nowarn(&rdev->dev.kobj, &dev->kobj, 166087fe29b6SMichał Mirosław supply_name); 1661414c70cbSLiam Girdwood if (err) { 166261aab5adSMichał Mirosław rdev_dbg(rdev, "could not add device link %s: %pe\n", 166361aab5adSMichał Mirosław dev->kobj.name, ERR_PTR(err)); 1664222cc7b1SMark Brown /* non-fatal */ 1665414c70cbSLiam Girdwood } 1666414c70cbSLiam Girdwood } 16675de70519SMark Brown 1668dbe954d8SHans de Goede if (err != -EEXIST) 1669dbe954d8SHans de Goede regulator->debugfs = debugfs_create_dir(supply_name, rdev->debugfs); 167024751434SStephen Boyd if (!regulator->debugfs) { 1671ad3a942bSStephen Boyd rdev_dbg(rdev, "Failed to create debugfs directory\n"); 16725de70519SMark Brown } else { 16735de70519SMark Brown debugfs_create_u32("uA_load", 0444, regulator->debugfs, 16745de70519SMark Brown ®ulator->uA_load); 16755de70519SMark Brown debugfs_create_u32("min_uV", 0444, regulator->debugfs, 1676c360a6dfSChunyan Zhang ®ulator->voltage[PM_SUSPEND_ON].min_uV); 16775de70519SMark Brown debugfs_create_u32("max_uV", 0444, regulator->debugfs, 1678c360a6dfSChunyan Zhang ®ulator->voltage[PM_SUSPEND_ON].max_uV); 16792d80a91bSRichard Fitzgerald debugfs_create_file("constraint_flags", 0444, 16802d80a91bSRichard Fitzgerald regulator->debugfs, regulator, 16812d80a91bSRichard Fitzgerald &constraint_flags_fops); 16825de70519SMark Brown } 16835de70519SMark Brown 16846492bc1bSMark Brown /* 16856492bc1bSMark Brown * Check now if the regulator is an always on regulator - if 16866492bc1bSMark Brown * it is then we don't need to do nearly so much work for 16876492bc1bSMark Brown * enable/disable calls. 16886492bc1bSMark Brown */ 16898a34e979SWEN Pingbo if (!regulator_ops_is_valid(rdev, REGULATOR_CHANGE_STATUS) && 16906492bc1bSMark Brown _regulator_is_enabled(rdev)) 16916492bc1bSMark Brown regulator->always_on = true; 16926492bc1bSMark Brown 1693414c70cbSLiam Girdwood return regulator; 1694414c70cbSLiam Girdwood } 1695414c70cbSLiam Girdwood 169631aae2beSMark Brown static int _regulator_get_enable_time(struct regulator_dev *rdev) 169731aae2beSMark Brown { 169800c877c6SLaxman Dewangan if (rdev->constraints && rdev->constraints->enable_time) 169900c877c6SLaxman Dewangan return rdev->constraints->enable_time; 170068ce3a44SAxel Lin if (rdev->desc->ops->enable_time) 170131aae2beSMark Brown return rdev->desc->ops->enable_time(rdev); 170268ce3a44SAxel Lin return rdev->desc->enable_time; 170331aae2beSMark Brown } 170431aae2beSMark Brown 1705a06ccd9cSCharles Keepax static struct regulator_supply_alias *regulator_find_supply_alias( 1706a06ccd9cSCharles Keepax struct device *dev, const char *supply) 1707a06ccd9cSCharles Keepax { 1708a06ccd9cSCharles Keepax struct regulator_supply_alias *map; 1709a06ccd9cSCharles Keepax 1710a06ccd9cSCharles Keepax list_for_each_entry(map, ®ulator_supply_alias_list, list) 1711a06ccd9cSCharles Keepax if (map->src_dev == dev && strcmp(map->src_supply, supply) == 0) 1712a06ccd9cSCharles Keepax return map; 1713a06ccd9cSCharles Keepax 1714a06ccd9cSCharles Keepax return NULL; 1715a06ccd9cSCharles Keepax } 1716a06ccd9cSCharles Keepax 1717a06ccd9cSCharles Keepax static void regulator_supply_alias(struct device **dev, const char **supply) 1718a06ccd9cSCharles Keepax { 1719a06ccd9cSCharles Keepax struct regulator_supply_alias *map; 1720a06ccd9cSCharles Keepax 1721a06ccd9cSCharles Keepax map = regulator_find_supply_alias(*dev, *supply); 1722a06ccd9cSCharles Keepax if (map) { 1723a06ccd9cSCharles Keepax dev_dbg(*dev, "Mapping supply %s to %s,%s\n", 1724a06ccd9cSCharles Keepax *supply, map->alias_supply, 1725a06ccd9cSCharles Keepax dev_name(map->alias_dev)); 1726a06ccd9cSCharles Keepax *dev = map->alias_dev; 1727a06ccd9cSCharles Keepax *supply = map->alias_supply; 1728a06ccd9cSCharles Keepax } 1729a06ccd9cSCharles Keepax } 1730a06ccd9cSCharles Keepax 173185f3b431STomeu Vizoso static int regulator_match(struct device *dev, const void *data) 173285f3b431STomeu Vizoso { 173385f3b431STomeu Vizoso struct regulator_dev *r = dev_to_rdev(dev); 173485f3b431STomeu Vizoso 173585f3b431STomeu Vizoso return strcmp(rdev_get_name(r), data) == 0; 173685f3b431STomeu Vizoso } 173785f3b431STomeu Vizoso 173885f3b431STomeu Vizoso static struct regulator_dev *regulator_lookup_by_name(const char *name) 173985f3b431STomeu Vizoso { 174085f3b431STomeu Vizoso struct device *dev; 174185f3b431STomeu Vizoso 174285f3b431STomeu Vizoso dev = class_find_device(®ulator_class, NULL, name, regulator_match); 174385f3b431STomeu Vizoso 174485f3b431STomeu Vizoso return dev ? dev_to_rdev(dev) : NULL; 174585f3b431STomeu Vizoso } 174685f3b431STomeu Vizoso 174785f3b431STomeu Vizoso /** 174885f3b431STomeu Vizoso * regulator_dev_lookup - lookup a regulator device. 174985f3b431STomeu Vizoso * @dev: device for regulator "consumer". 175085f3b431STomeu Vizoso * @supply: Supply name or regulator ID. 175185f3b431STomeu Vizoso * 175285f3b431STomeu Vizoso * If successful, returns a struct regulator_dev that corresponds to the name 1753163478daSDmitry Torokhov * @supply and with the embedded struct device refcount incremented by one. 1754163478daSDmitry Torokhov * The refcount must be dropped by calling put_device(). 1755163478daSDmitry Torokhov * On failure one of the following ERR-PTR-encoded values is returned: 1756163478daSDmitry Torokhov * -ENODEV if lookup fails permanently, -EPROBE_DEFER if lookup could succeed 1757163478daSDmitry Torokhov * in the future. 175885f3b431STomeu Vizoso */ 175969511a45SRajendra Nayak static struct regulator_dev *regulator_dev_lookup(struct device *dev, 1760163478daSDmitry Torokhov const char *supply) 176169511a45SRajendra Nayak { 176206217197SCharles Keepax struct regulator_dev *r = NULL; 176369511a45SRajendra Nayak struct device_node *node; 1764576ca436SMark Brown struct regulator_map *map; 1765576ca436SMark Brown const char *devname = NULL; 176669511a45SRajendra Nayak 1767a06ccd9cSCharles Keepax regulator_supply_alias(&dev, &supply); 1768a06ccd9cSCharles Keepax 176969511a45SRajendra Nayak /* first do a dt based lookup */ 177069511a45SRajendra Nayak if (dev && dev->of_node) { 177169511a45SRajendra Nayak node = of_get_regulator(dev, supply); 17726d191a5fSMark Brown if (node) { 177385f3b431STomeu Vizoso r = of_find_regulator_by_node(node); 177485f3b431STomeu Vizoso if (r) 177569511a45SRajendra Nayak return r; 1776163478daSDmitry Torokhov 17776d191a5fSMark Brown /* 1778163478daSDmitry Torokhov * We have a node, but there is no device. 1779163478daSDmitry Torokhov * assume it has not registered yet. 17806d191a5fSMark Brown */ 1781163478daSDmitry Torokhov return ERR_PTR(-EPROBE_DEFER); 17826d191a5fSMark Brown } 178369511a45SRajendra Nayak } 178469511a45SRajendra Nayak 178569511a45SRajendra Nayak /* if not found, try doing it non-dt way */ 1786576ca436SMark Brown if (dev) 1787576ca436SMark Brown devname = dev_name(dev); 1788576ca436SMark Brown 178985f3b431STomeu Vizoso mutex_lock(®ulator_list_mutex); 1790576ca436SMark Brown list_for_each_entry(map, ®ulator_map_list, list) { 1791576ca436SMark Brown /* If the mapping has a device set up it must match */ 1792576ca436SMark Brown if (map->dev_name && 1793576ca436SMark Brown (!devname || strcmp(map->dev_name, devname))) 1794576ca436SMark Brown continue; 1795576ca436SMark Brown 179685f3b431STomeu Vizoso if (strcmp(map->supply, supply) == 0 && 179785f3b431STomeu Vizoso get_device(&map->regulator->dev)) { 1798163478daSDmitry Torokhov r = map->regulator; 1799163478daSDmitry Torokhov break; 1800576ca436SMark Brown } 180185f3b431STomeu Vizoso } 180285f3b431STomeu Vizoso mutex_unlock(®ulator_list_mutex); 1803576ca436SMark Brown 1804163478daSDmitry Torokhov if (r) 1805163478daSDmitry Torokhov return r; 1806163478daSDmitry Torokhov 180706217197SCharles Keepax r = regulator_lookup_by_name(supply); 180806217197SCharles Keepax if (r) 180906217197SCharles Keepax return r; 181006217197SCharles Keepax 1811163478daSDmitry Torokhov return ERR_PTR(-ENODEV); 181269511a45SRajendra Nayak } 181369511a45SRajendra Nayak 18146261b06dSBjorn Andersson static int regulator_resolve_supply(struct regulator_dev *rdev) 18156261b06dSBjorn Andersson { 18166261b06dSBjorn Andersson struct regulator_dev *r; 18176261b06dSBjorn Andersson struct device *dev = rdev->dev.parent; 1818eaa7995cSDavid Collins int ret = 0; 18196261b06dSBjorn Andersson 182048f1b4efSKrzysztof Kozlowski /* No supply to resolve? */ 18216261b06dSBjorn Andersson if (!rdev->supply_name) 18226261b06dSBjorn Andersson return 0; 18236261b06dSBjorn Andersson 1824eaa7995cSDavid Collins /* Supply already resolved? (fast-path without locking contention) */ 18256261b06dSBjorn Andersson if (rdev->supply) 18266261b06dSBjorn Andersson return 0; 18276261b06dSBjorn Andersson 1828163478daSDmitry Torokhov r = regulator_dev_lookup(dev, rdev->supply_name); 1829163478daSDmitry Torokhov if (IS_ERR(r)) { 1830163478daSDmitry Torokhov ret = PTR_ERR(r); 1831163478daSDmitry Torokhov 183206423121SMark Brown /* Did the lookup explicitly defer for us? */ 183306423121SMark Brown if (ret == -EPROBE_DEFER) 1834eaa7995cSDavid Collins goto out; 183506423121SMark Brown 18369f7e25edSMark Brown if (have_full_constraints()) { 18379f7e25edSMark Brown r = dummy_regulator_rdev; 183885f3b431STomeu Vizoso get_device(&r->dev); 18399f7e25edSMark Brown } else { 18406261b06dSBjorn Andersson dev_err(dev, "Failed to resolve %s-supply for %s\n", 18416261b06dSBjorn Andersson rdev->supply_name, rdev->desc->name); 1842eaa7995cSDavid Collins ret = -EPROBE_DEFER; 1843eaa7995cSDavid Collins goto out; 18446261b06dSBjorn Andersson } 18459f7e25edSMark Brown } 18466261b06dSBjorn Andersson 18474b639e25SMichał Mirosław if (r == rdev) { 18484b639e25SMichał Mirosław dev_err(dev, "Supply for %s (%s) resolved to itself\n", 18494b639e25SMichał Mirosław rdev->desc->name, rdev->supply_name); 1850eaa7995cSDavid Collins if (!have_full_constraints()) { 1851eaa7995cSDavid Collins ret = -EINVAL; 1852eaa7995cSDavid Collins goto out; 1853eaa7995cSDavid Collins } 1854f5c042b2SMichał Mirosław r = dummy_regulator_rdev; 1855f5c042b2SMichał Mirosław get_device(&r->dev); 18564b639e25SMichał Mirosław } 18574b639e25SMichał Mirosław 185866d228a2SJon Hunter /* 185966d228a2SJon Hunter * If the supply's parent device is not the same as the 186066d228a2SJon Hunter * regulator's parent device, then ensure the parent device 186166d228a2SJon Hunter * is bound before we resolve the supply, in case the parent 186266d228a2SJon Hunter * device get probe deferred and unregisters the supply. 186366d228a2SJon Hunter */ 186466d228a2SJon Hunter if (r->dev.parent && r->dev.parent != rdev->dev.parent) { 186566d228a2SJon Hunter if (!device_is_bound(r->dev.parent)) { 186666d228a2SJon Hunter put_device(&r->dev); 1867eaa7995cSDavid Collins ret = -EPROBE_DEFER; 1868eaa7995cSDavid Collins goto out; 186966d228a2SJon Hunter } 187066d228a2SJon Hunter } 187166d228a2SJon Hunter 18726261b06dSBjorn Andersson /* Recursively resolve the supply of the supply */ 18736261b06dSBjorn Andersson ret = regulator_resolve_supply(r); 187485f3b431STomeu Vizoso if (ret < 0) { 187585f3b431STomeu Vizoso put_device(&r->dev); 1876eaa7995cSDavid Collins goto out; 187785f3b431STomeu Vizoso } 18786261b06dSBjorn Andersson 187914a71d50SMark Brown /* 188014a71d50SMark Brown * Recheck rdev->supply with rdev->mutex lock held to avoid a race 188114a71d50SMark Brown * between rdev->supply null check and setting rdev->supply in 188214a71d50SMark Brown * set_supply() from concurrent tasks. 188314a71d50SMark Brown */ 188414a71d50SMark Brown regulator_lock(rdev); 188514a71d50SMark Brown 188614a71d50SMark Brown /* Supply just resolved by a concurrent task? */ 188714a71d50SMark Brown if (rdev->supply) { 188814a71d50SMark Brown regulator_unlock(rdev); 188985f3b431STomeu Vizoso put_device(&r->dev); 1890eaa7995cSDavid Collins goto out; 189185f3b431STomeu Vizoso } 18926261b06dSBjorn Andersson 189314a71d50SMark Brown ret = set_supply(rdev, r); 189414a71d50SMark Brown if (ret < 0) { 189514a71d50SMark Brown regulator_unlock(rdev); 189614a71d50SMark Brown put_device(&r->dev); 189714a71d50SMark Brown goto out; 189814a71d50SMark Brown } 189914a71d50SMark Brown 190014a71d50SMark Brown regulator_unlock(rdev); 190114a71d50SMark Brown 190205f224caSDouglas Anderson /* 190305f224caSDouglas Anderson * In set_machine_constraints() we may have turned this regulator on 190405f224caSDouglas Anderson * but we couldn't propagate to the supply if it hadn't been resolved 190505f224caSDouglas Anderson * yet. Do it now. 190605f224caSDouglas Anderson */ 190705f224caSDouglas Anderson if (rdev->use_count) { 19086261b06dSBjorn Andersson ret = regulator_enable(rdev->supply); 190936a1f1b6SJavier Martinez Canillas if (ret < 0) { 191036a1f1b6SJavier Martinez Canillas _regulator_put(rdev->supply); 19118e5356a7SJon Hunter rdev->supply = NULL; 1912eaa7995cSDavid Collins goto out; 19136261b06dSBjorn Andersson } 191436a1f1b6SJavier Martinez Canillas } 19156261b06dSBjorn Andersson 1916eaa7995cSDavid Collins out: 1917eaa7995cSDavid Collins return ret; 19186261b06dSBjorn Andersson } 19196261b06dSBjorn Andersson 19205ffbd136SMark Brown /* Internal regulator request function */ 1921a8bd42a9SDmitry Torokhov struct regulator *_regulator_get(struct device *dev, const char *id, 1922a8bd42a9SDmitry Torokhov enum regulator_get_type get_type) 1923414c70cbSLiam Girdwood { 1924414c70cbSLiam Girdwood struct regulator_dev *rdev; 19257d245afaSDmitry Torokhov struct regulator *regulator; 1926b59b6544SSaravana Kannan struct device_link *link; 1927317b5684SMark Brown int ret; 1928414c70cbSLiam Girdwood 1929a8bd42a9SDmitry Torokhov if (get_type >= MAX_GET_TYPE) { 1930a8bd42a9SDmitry Torokhov dev_err(dev, "invalid type %d in %s\n", get_type, __func__); 1931a8bd42a9SDmitry Torokhov return ERR_PTR(-EINVAL); 1932a8bd42a9SDmitry Torokhov } 1933a8bd42a9SDmitry Torokhov 1934414c70cbSLiam Girdwood if (id == NULL) { 19355da84fd9SJoe Perches pr_err("get() with no identifier\n"); 1936043c998fSMark Brown return ERR_PTR(-EINVAL); 1937414c70cbSLiam Girdwood } 1938414c70cbSLiam Girdwood 1939163478daSDmitry Torokhov rdev = regulator_dev_lookup(dev, id); 1940a4d7641fSDmitry Torokhov if (IS_ERR(rdev)) { 1941163478daSDmitry Torokhov ret = PTR_ERR(rdev); 1942ef60abbbSMark Brown 19431e4b545cSNishanth Menon /* 1944a4d7641fSDmitry Torokhov * If regulator_dev_lookup() fails with error other 1945a4d7641fSDmitry Torokhov * than -ENODEV our job here is done, we simply return it. 19461e4b545cSNishanth Menon */ 1947a4d7641fSDmitry Torokhov if (ret != -ENODEV) 1948a4d7641fSDmitry Torokhov return ERR_PTR(ret); 19491e4b545cSNishanth Menon 1950a4d7641fSDmitry Torokhov if (!have_full_constraints()) { 1951a4d7641fSDmitry Torokhov dev_warn(dev, 1952a4d7641fSDmitry Torokhov "incomplete constraints, dummy supplies not allowed\n"); 1953a4d7641fSDmitry Torokhov return ERR_PTR(-ENODEV); 195434abbd68SMark Brown } 195534abbd68SMark Brown 1956a4d7641fSDmitry Torokhov switch (get_type) { 1957a4d7641fSDmitry Torokhov case NORMAL_GET: 1958a4d7641fSDmitry Torokhov /* 1959a4d7641fSDmitry Torokhov * Assume that a regulator is physically present and 1960a4d7641fSDmitry Torokhov * enabled, even if it isn't hooked up, and just 1961a4d7641fSDmitry Torokhov * provide a dummy. 1962a4d7641fSDmitry Torokhov */ 19636e5505cfSAndy Shevchenko dev_warn(dev, "supply %s not found, using dummy regulator\n", id); 1964a4d7641fSDmitry Torokhov rdev = dummy_regulator_rdev; 1965a4d7641fSDmitry Torokhov get_device(&rdev->dev); 1966a4d7641fSDmitry Torokhov break; 1967414c70cbSLiam Girdwood 1968a4d7641fSDmitry Torokhov case EXCLUSIVE_GET: 1969a4d7641fSDmitry Torokhov dev_warn(dev, 1970a4d7641fSDmitry Torokhov "dummy supplies not allowed for exclusive requests\n"); 1971df561f66SGustavo A. R. Silva fallthrough; 1972a4d7641fSDmitry Torokhov 1973a4d7641fSDmitry Torokhov default: 1974a4d7641fSDmitry Torokhov return ERR_PTR(-ENODEV); 1975a4d7641fSDmitry Torokhov } 1976a4d7641fSDmitry Torokhov } 1977a4d7641fSDmitry Torokhov 19785ffbd136SMark Brown if (rdev->exclusive) { 19795ffbd136SMark Brown regulator = ERR_PTR(-EPERM); 198085f3b431STomeu Vizoso put_device(&rdev->dev); 198185f3b431STomeu Vizoso return regulator; 19825ffbd136SMark Brown } 19835ffbd136SMark Brown 1984a8bd42a9SDmitry Torokhov if (get_type == EXCLUSIVE_GET && rdev->open_count) { 19855ffbd136SMark Brown regulator = ERR_PTR(-EBUSY); 198685f3b431STomeu Vizoso put_device(&rdev->dev); 198785f3b431STomeu Vizoso return regulator; 19885ffbd136SMark Brown } 19895ffbd136SMark Brown 199079d6f049SDmitry Osipenko mutex_lock(®ulator_list_mutex); 199179d6f049SDmitry Osipenko ret = (rdev->coupling_desc.n_resolved != rdev->coupling_desc.n_coupled); 199279d6f049SDmitry Osipenko mutex_unlock(®ulator_list_mutex); 199379d6f049SDmitry Osipenko 199479d6f049SDmitry Osipenko if (ret != 0) { 199579d6f049SDmitry Osipenko regulator = ERR_PTR(-EPROBE_DEFER); 199679d6f049SDmitry Osipenko put_device(&rdev->dev); 199779d6f049SDmitry Osipenko return regulator; 199879d6f049SDmitry Osipenko } 199979d6f049SDmitry Osipenko 20006261b06dSBjorn Andersson ret = regulator_resolve_supply(rdev); 20016261b06dSBjorn Andersson if (ret < 0) { 20026261b06dSBjorn Andersson regulator = ERR_PTR(ret); 200385f3b431STomeu Vizoso put_device(&rdev->dev); 200485f3b431STomeu Vizoso return regulator; 20056261b06dSBjorn Andersson } 20066261b06dSBjorn Andersson 200785f3b431STomeu Vizoso if (!try_module_get(rdev->owner)) { 20087d245afaSDmitry Torokhov regulator = ERR_PTR(-EPROBE_DEFER); 200985f3b431STomeu Vizoso put_device(&rdev->dev); 201085f3b431STomeu Vizoso return regulator; 201185f3b431STomeu Vizoso } 2012a5766f11SLiam Girdwood 2013414c70cbSLiam Girdwood regulator = create_regulator(rdev, dev, id); 2014414c70cbSLiam Girdwood if (regulator == NULL) { 2015414c70cbSLiam Girdwood regulator = ERR_PTR(-ENOMEM); 2016414c70cbSLiam Girdwood module_put(rdev->owner); 20174affd79aSWen Yang put_device(&rdev->dev); 201885f3b431STomeu Vizoso return regulator; 2019414c70cbSLiam Girdwood } 2020414c70cbSLiam Girdwood 20215ffbd136SMark Brown rdev->open_count++; 2022a8bd42a9SDmitry Torokhov if (get_type == EXCLUSIVE_GET) { 20235ffbd136SMark Brown rdev->exclusive = 1; 20245ffbd136SMark Brown 20255ffbd136SMark Brown ret = _regulator_is_enabled(rdev); 20265ffbd136SMark Brown if (ret > 0) 20275ffbd136SMark Brown rdev->use_count = 1; 20285ffbd136SMark Brown else 20295ffbd136SMark Brown rdev->use_count = 0; 20305ffbd136SMark Brown } 20315ffbd136SMark Brown 2032b59b6544SSaravana Kannan link = device_link_add(dev, &rdev->dev, DL_FLAG_STATELESS); 2033b59b6544SSaravana Kannan if (!IS_ERR_OR_NULL(link)) 2034b59b6544SSaravana Kannan regulator->device_link = true; 2035ed1ae2ddSpascal paillet 2036414c70cbSLiam Girdwood return regulator; 2037414c70cbSLiam Girdwood } 20385ffbd136SMark Brown 20395ffbd136SMark Brown /** 20405ffbd136SMark Brown * regulator_get - lookup and obtain a reference to a regulator. 20415ffbd136SMark Brown * @dev: device for regulator "consumer" 20425ffbd136SMark Brown * @id: Supply name or regulator ID. 20435ffbd136SMark Brown * 20445ffbd136SMark Brown * Returns a struct regulator corresponding to the regulator producer, 20455ffbd136SMark Brown * or IS_ERR() condition containing errno. 20465ffbd136SMark Brown * 204790cf443dSDaniel Scally * Use of supply names configured via set_consumer_device_supply() is 20485ffbd136SMark Brown * strongly encouraged. It is recommended that the supply name used 20495ffbd136SMark Brown * should match the name used for the supply and/or the relevant 20505ffbd136SMark Brown * device pins in the datasheet. 20515ffbd136SMark Brown */ 20525ffbd136SMark Brown struct regulator *regulator_get(struct device *dev, const char *id) 20535ffbd136SMark Brown { 2054a8bd42a9SDmitry Torokhov return _regulator_get(dev, id, NORMAL_GET); 20555ffbd136SMark Brown } 2056414c70cbSLiam Girdwood EXPORT_SYMBOL_GPL(regulator_get); 2057414c70cbSLiam Girdwood 2058070b9079SStephen Boyd /** 20595ffbd136SMark Brown * regulator_get_exclusive - obtain exclusive access to a regulator. 20605ffbd136SMark Brown * @dev: device for regulator "consumer" 20615ffbd136SMark Brown * @id: Supply name or regulator ID. 20625ffbd136SMark Brown * 20635ffbd136SMark Brown * Returns a struct regulator corresponding to the regulator producer, 20645ffbd136SMark Brown * or IS_ERR() condition containing errno. Other consumers will be 206569c3f723SStephen Boyd * unable to obtain this regulator while this reference is held and the 206669c3f723SStephen Boyd * use count for the regulator will be initialised to reflect the current 206769c3f723SStephen Boyd * state of the regulator. 20685ffbd136SMark Brown * 20695ffbd136SMark Brown * This is intended for use by consumers which cannot tolerate shared 20705ffbd136SMark Brown * use of the regulator such as those which need to force the 20715ffbd136SMark Brown * regulator off for correct operation of the hardware they are 20725ffbd136SMark Brown * controlling. 20735ffbd136SMark Brown * 207490cf443dSDaniel Scally * Use of supply names configured via set_consumer_device_supply() is 20755ffbd136SMark Brown * strongly encouraged. It is recommended that the supply name used 20765ffbd136SMark Brown * should match the name used for the supply and/or the relevant 20775ffbd136SMark Brown * device pins in the datasheet. 20785ffbd136SMark Brown */ 20795ffbd136SMark Brown struct regulator *regulator_get_exclusive(struct device *dev, const char *id) 20805ffbd136SMark Brown { 2081a8bd42a9SDmitry Torokhov return _regulator_get(dev, id, EXCLUSIVE_GET); 20825ffbd136SMark Brown } 20835ffbd136SMark Brown EXPORT_SYMBOL_GPL(regulator_get_exclusive); 20845ffbd136SMark Brown 2085de1dd9fdSMark Brown /** 2086de1dd9fdSMark Brown * regulator_get_optional - obtain optional access to a regulator. 2087de1dd9fdSMark Brown * @dev: device for regulator "consumer" 2088de1dd9fdSMark Brown * @id: Supply name or regulator ID. 2089de1dd9fdSMark Brown * 2090de1dd9fdSMark Brown * Returns a struct regulator corresponding to the regulator producer, 209169c3f723SStephen Boyd * or IS_ERR() condition containing errno. 2092de1dd9fdSMark Brown * 2093de1dd9fdSMark Brown * This is intended for use by consumers for devices which can have 2094de1dd9fdSMark Brown * some supplies unconnected in normal use, such as some MMC devices. 2095de1dd9fdSMark Brown * It can allow the regulator core to provide stub supplies for other 2096de1dd9fdSMark Brown * supplies requested using normal regulator_get() calls without 2097de1dd9fdSMark Brown * disrupting the operation of drivers that can handle absent 2098de1dd9fdSMark Brown * supplies. 2099de1dd9fdSMark Brown * 210090cf443dSDaniel Scally * Use of supply names configured via set_consumer_device_supply() is 2101de1dd9fdSMark Brown * strongly encouraged. It is recommended that the supply name used 2102de1dd9fdSMark Brown * should match the name used for the supply and/or the relevant 2103de1dd9fdSMark Brown * device pins in the datasheet. 2104de1dd9fdSMark Brown */ 2105de1dd9fdSMark Brown struct regulator *regulator_get_optional(struct device *dev, const char *id) 2106de1dd9fdSMark Brown { 2107a8bd42a9SDmitry Torokhov return _regulator_get(dev, id, OPTIONAL_GET); 2108de1dd9fdSMark Brown } 2109de1dd9fdSMark Brown EXPORT_SYMBOL_GPL(regulator_get_optional); 2110de1dd9fdSMark Brown 2111e1794aa4SSaravana Kannan static void destroy_regulator(struct regulator *regulator) 2112414c70cbSLiam Girdwood { 2113e1794aa4SSaravana Kannan struct regulator_dev *rdev = regulator->rdev; 2114414c70cbSLiam Girdwood 21155de70519SMark Brown debugfs_remove_recursive(regulator->debugfs); 21165de70519SMark Brown 2117ed1ae2ddSpascal paillet if (regulator->dev) { 2118b59b6544SSaravana Kannan if (regulator->device_link) 2119ed1ae2ddSpascal paillet device_link_remove(regulator->dev, &rdev->dev); 2120ed1ae2ddSpascal paillet 2121414c70cbSLiam Girdwood /* remove any sysfs entries */ 2122414c70cbSLiam Girdwood sysfs_remove_link(&rdev->dev.kobj, regulator->supply_name); 2123ed1ae2ddSpascal paillet } 2124ed1ae2ddSpascal paillet 212566cf9a7eSMaciej Purski regulator_lock(rdev); 2126414c70cbSLiam Girdwood list_del(®ulator->list); 2127414c70cbSLiam Girdwood 21285ffbd136SMark Brown rdev->open_count--; 21295ffbd136SMark Brown rdev->exclusive = 0; 213066cf9a7eSMaciej Purski regulator_unlock(rdev); 21315ffbd136SMark Brown 21320630b614SStephen Boyd kfree_const(regulator->supply_name); 21331768514eSMark Brown kfree(regulator); 2134e1794aa4SSaravana Kannan } 2135e1794aa4SSaravana Kannan 2136e1794aa4SSaravana Kannan /* regulator_list_mutex lock held by regulator_put() */ 2137e1794aa4SSaravana Kannan static void _regulator_put(struct regulator *regulator) 2138e1794aa4SSaravana Kannan { 2139e1794aa4SSaravana Kannan struct regulator_dev *rdev; 2140e1794aa4SSaravana Kannan 2141e1794aa4SSaravana Kannan if (IS_ERR_OR_NULL(regulator)) 2142e1794aa4SSaravana Kannan return; 2143e1794aa4SSaravana Kannan 2144e1794aa4SSaravana Kannan lockdep_assert_held_once(®ulator_list_mutex); 2145e1794aa4SSaravana Kannan 2146e1794aa4SSaravana Kannan /* Docs say you must disable before calling regulator_put() */ 2147e1794aa4SSaravana Kannan WARN_ON(regulator->enable_count); 2148e1794aa4SSaravana Kannan 2149e1794aa4SSaravana Kannan rdev = regulator->rdev; 2150e1794aa4SSaravana Kannan 2151e1794aa4SSaravana Kannan destroy_regulator(regulator); 21521768514eSMark Brown 2153414c70cbSLiam Girdwood module_put(rdev->owner); 21544affd79aSWen Yang put_device(&rdev->dev); 215523ff2f0fSCharles Keepax } 215623ff2f0fSCharles Keepax 215723ff2f0fSCharles Keepax /** 215823ff2f0fSCharles Keepax * regulator_put - "free" the regulator source 215923ff2f0fSCharles Keepax * @regulator: regulator source 216023ff2f0fSCharles Keepax * 216123ff2f0fSCharles Keepax * Note: drivers must ensure that all regulator_enable calls made on this 216223ff2f0fSCharles Keepax * regulator source are balanced by regulator_disable calls prior to calling 216323ff2f0fSCharles Keepax * this function. 216423ff2f0fSCharles Keepax */ 216523ff2f0fSCharles Keepax void regulator_put(struct regulator *regulator) 216623ff2f0fSCharles Keepax { 216723ff2f0fSCharles Keepax mutex_lock(®ulator_list_mutex); 216823ff2f0fSCharles Keepax _regulator_put(regulator); 2169414c70cbSLiam Girdwood mutex_unlock(®ulator_list_mutex); 2170414c70cbSLiam Girdwood } 2171414c70cbSLiam Girdwood EXPORT_SYMBOL_GPL(regulator_put); 2172414c70cbSLiam Girdwood 2173a06ccd9cSCharles Keepax /** 2174a06ccd9cSCharles Keepax * regulator_register_supply_alias - Provide device alias for supply lookup 2175a06ccd9cSCharles Keepax * 2176a06ccd9cSCharles Keepax * @dev: device that will be given as the regulator "consumer" 2177a06ccd9cSCharles Keepax * @id: Supply name or regulator ID 2178a06ccd9cSCharles Keepax * @alias_dev: device that should be used to lookup the supply 2179a06ccd9cSCharles Keepax * @alias_id: Supply name or regulator ID that should be used to lookup the 2180a06ccd9cSCharles Keepax * supply 2181a06ccd9cSCharles Keepax * 2182a06ccd9cSCharles Keepax * All lookups for id on dev will instead be conducted for alias_id on 2183a06ccd9cSCharles Keepax * alias_dev. 2184a06ccd9cSCharles Keepax */ 2185a06ccd9cSCharles Keepax int regulator_register_supply_alias(struct device *dev, const char *id, 2186a06ccd9cSCharles Keepax struct device *alias_dev, 2187a06ccd9cSCharles Keepax const char *alias_id) 2188a06ccd9cSCharles Keepax { 2189a06ccd9cSCharles Keepax struct regulator_supply_alias *map; 2190a06ccd9cSCharles Keepax 2191a06ccd9cSCharles Keepax map = regulator_find_supply_alias(dev, id); 2192a06ccd9cSCharles Keepax if (map) 2193a06ccd9cSCharles Keepax return -EEXIST; 2194a06ccd9cSCharles Keepax 2195a06ccd9cSCharles Keepax map = kzalloc(sizeof(struct regulator_supply_alias), GFP_KERNEL); 2196a06ccd9cSCharles Keepax if (!map) 2197a06ccd9cSCharles Keepax return -ENOMEM; 2198a06ccd9cSCharles Keepax 2199a06ccd9cSCharles Keepax map->src_dev = dev; 2200a06ccd9cSCharles Keepax map->src_supply = id; 2201a06ccd9cSCharles Keepax map->alias_dev = alias_dev; 2202a06ccd9cSCharles Keepax map->alias_supply = alias_id; 2203a06ccd9cSCharles Keepax 2204a06ccd9cSCharles Keepax list_add(&map->list, ®ulator_supply_alias_list); 2205a06ccd9cSCharles Keepax 2206a06ccd9cSCharles Keepax pr_info("Adding alias for supply %s,%s -> %s,%s\n", 2207a06ccd9cSCharles Keepax id, dev_name(dev), alias_id, dev_name(alias_dev)); 2208a06ccd9cSCharles Keepax 2209a06ccd9cSCharles Keepax return 0; 2210a06ccd9cSCharles Keepax } 2211a06ccd9cSCharles Keepax EXPORT_SYMBOL_GPL(regulator_register_supply_alias); 2212a06ccd9cSCharles Keepax 2213a06ccd9cSCharles Keepax /** 2214a06ccd9cSCharles Keepax * regulator_unregister_supply_alias - Remove device alias 2215a06ccd9cSCharles Keepax * 2216a06ccd9cSCharles Keepax * @dev: device that will be given as the regulator "consumer" 2217a06ccd9cSCharles Keepax * @id: Supply name or regulator ID 2218a06ccd9cSCharles Keepax * 2219a06ccd9cSCharles Keepax * Remove a lookup alias if one exists for id on dev. 2220a06ccd9cSCharles Keepax */ 2221a06ccd9cSCharles Keepax void regulator_unregister_supply_alias(struct device *dev, const char *id) 2222a06ccd9cSCharles Keepax { 2223a06ccd9cSCharles Keepax struct regulator_supply_alias *map; 2224a06ccd9cSCharles Keepax 2225a06ccd9cSCharles Keepax map = regulator_find_supply_alias(dev, id); 2226a06ccd9cSCharles Keepax if (map) { 2227a06ccd9cSCharles Keepax list_del(&map->list); 2228a06ccd9cSCharles Keepax kfree(map); 2229a06ccd9cSCharles Keepax } 2230a06ccd9cSCharles Keepax } 2231a06ccd9cSCharles Keepax EXPORT_SYMBOL_GPL(regulator_unregister_supply_alias); 2232a06ccd9cSCharles Keepax 2233a06ccd9cSCharles Keepax /** 2234a06ccd9cSCharles Keepax * regulator_bulk_register_supply_alias - register multiple aliases 2235a06ccd9cSCharles Keepax * 2236a06ccd9cSCharles Keepax * @dev: device that will be given as the regulator "consumer" 2237a06ccd9cSCharles Keepax * @id: List of supply names or regulator IDs 2238a06ccd9cSCharles Keepax * @alias_dev: device that should be used to lookup the supply 2239a06ccd9cSCharles Keepax * @alias_id: List of supply names or regulator IDs that should be used to 2240a06ccd9cSCharles Keepax * lookup the supply 2241a06ccd9cSCharles Keepax * @num_id: Number of aliases to register 2242a06ccd9cSCharles Keepax * 2243a06ccd9cSCharles Keepax * @return 0 on success, an errno on failure. 2244a06ccd9cSCharles Keepax * 2245a06ccd9cSCharles Keepax * This helper function allows drivers to register several supply 2246a06ccd9cSCharles Keepax * aliases in one operation. If any of the aliases cannot be 2247a06ccd9cSCharles Keepax * registered any aliases that were registered will be removed 2248a06ccd9cSCharles Keepax * before returning to the caller. 2249a06ccd9cSCharles Keepax */ 22509f8c0fe9SLee Jones int regulator_bulk_register_supply_alias(struct device *dev, 22519f8c0fe9SLee Jones const char *const *id, 2252a06ccd9cSCharles Keepax struct device *alias_dev, 22539f8c0fe9SLee Jones const char *const *alias_id, 2254a06ccd9cSCharles Keepax int num_id) 2255a06ccd9cSCharles Keepax { 2256a06ccd9cSCharles Keepax int i; 2257a06ccd9cSCharles Keepax int ret; 2258a06ccd9cSCharles Keepax 2259a06ccd9cSCharles Keepax for (i = 0; i < num_id; ++i) { 2260a06ccd9cSCharles Keepax ret = regulator_register_supply_alias(dev, id[i], alias_dev, 2261a06ccd9cSCharles Keepax alias_id[i]); 2262a06ccd9cSCharles Keepax if (ret < 0) 2263a06ccd9cSCharles Keepax goto err; 2264a06ccd9cSCharles Keepax } 2265a06ccd9cSCharles Keepax 2266a06ccd9cSCharles Keepax return 0; 2267a06ccd9cSCharles Keepax 2268a06ccd9cSCharles Keepax err: 2269a06ccd9cSCharles Keepax dev_err(dev, 2270a06ccd9cSCharles Keepax "Failed to create supply alias %s,%s -> %s,%s\n", 2271a06ccd9cSCharles Keepax id[i], dev_name(dev), alias_id[i], dev_name(alias_dev)); 2272a06ccd9cSCharles Keepax 2273a06ccd9cSCharles Keepax while (--i >= 0) 2274a06ccd9cSCharles Keepax regulator_unregister_supply_alias(dev, id[i]); 2275a06ccd9cSCharles Keepax 2276a06ccd9cSCharles Keepax return ret; 2277a06ccd9cSCharles Keepax } 2278a06ccd9cSCharles Keepax EXPORT_SYMBOL_GPL(regulator_bulk_register_supply_alias); 2279a06ccd9cSCharles Keepax 2280a06ccd9cSCharles Keepax /** 2281a06ccd9cSCharles Keepax * regulator_bulk_unregister_supply_alias - unregister multiple aliases 2282a06ccd9cSCharles Keepax * 2283a06ccd9cSCharles Keepax * @dev: device that will be given as the regulator "consumer" 2284a06ccd9cSCharles Keepax * @id: List of supply names or regulator IDs 2285a06ccd9cSCharles Keepax * @num_id: Number of aliases to unregister 2286a06ccd9cSCharles Keepax * 2287a06ccd9cSCharles Keepax * This helper function allows drivers to unregister several supply 2288a06ccd9cSCharles Keepax * aliases in one operation. 2289a06ccd9cSCharles Keepax */ 2290a06ccd9cSCharles Keepax void regulator_bulk_unregister_supply_alias(struct device *dev, 22919f8c0fe9SLee Jones const char *const *id, 2292a06ccd9cSCharles Keepax int num_id) 2293a06ccd9cSCharles Keepax { 2294a06ccd9cSCharles Keepax int i; 2295a06ccd9cSCharles Keepax 2296a06ccd9cSCharles Keepax for (i = 0; i < num_id; ++i) 2297a06ccd9cSCharles Keepax regulator_unregister_supply_alias(dev, id[i]); 2298a06ccd9cSCharles Keepax } 2299a06ccd9cSCharles Keepax EXPORT_SYMBOL_GPL(regulator_bulk_unregister_supply_alias); 2300a06ccd9cSCharles Keepax 2301a06ccd9cSCharles Keepax 2302f19b00daSKim, Milo /* Manage enable GPIO list. Same GPIO pin can be shared among regulators */ 2303f19b00daSKim, Milo static int regulator_ena_gpio_request(struct regulator_dev *rdev, 2304f19b00daSKim, Milo const struct regulator_config *config) 2305f19b00daSKim, Milo { 2306467bf301SMichał Mirosław struct regulator_enable_gpio *pin, *new_pin; 2307778b28b4SRussell King struct gpio_desc *gpiod; 2308f19b00daSKim, Milo 2309e45e290aSLinus Walleij gpiod = config->ena_gpiod; 2310467bf301SMichał Mirosław new_pin = kzalloc(sizeof(*new_pin), GFP_KERNEL); 2311467bf301SMichał Mirosław 2312467bf301SMichał Mirosław mutex_lock(®ulator_list_mutex); 2313778b28b4SRussell King 2314f19b00daSKim, Milo list_for_each_entry(pin, ®ulator_ena_gpio_list, list) { 2315778b28b4SRussell King if (pin->gpiod == gpiod) { 2316541d052dSLinus Walleij rdev_dbg(rdev, "GPIO is already used\n"); 2317f19b00daSKim, Milo goto update_ena_gpio_to_rdev; 2318f19b00daSKim, Milo } 2319f19b00daSKim, Milo } 2320f19b00daSKim, Milo 2321467bf301SMichał Mirosław if (new_pin == NULL) { 2322467bf301SMichał Mirosław mutex_unlock(®ulator_list_mutex); 2323f19b00daSKim, Milo return -ENOMEM; 2324467bf301SMichał Mirosław } 2325467bf301SMichał Mirosław 2326467bf301SMichał Mirosław pin = new_pin; 2327467bf301SMichał Mirosław new_pin = NULL; 2328f19b00daSKim, Milo 2329778b28b4SRussell King pin->gpiod = gpiod; 2330f19b00daSKim, Milo list_add(&pin->list, ®ulator_ena_gpio_list); 2331f19b00daSKim, Milo 2332f19b00daSKim, Milo update_ena_gpio_to_rdev: 2333f19b00daSKim, Milo pin->request_count++; 2334f19b00daSKim, Milo rdev->ena_pin = pin; 2335467bf301SMichał Mirosław 2336467bf301SMichał Mirosław mutex_unlock(®ulator_list_mutex); 2337467bf301SMichał Mirosław kfree(new_pin); 2338467bf301SMichał Mirosław 2339f19b00daSKim, Milo return 0; 2340f19b00daSKim, Milo } 2341f19b00daSKim, Milo 2342f19b00daSKim, Milo static void regulator_ena_gpio_free(struct regulator_dev *rdev) 2343f19b00daSKim, Milo { 2344f19b00daSKim, Milo struct regulator_enable_gpio *pin, *n; 2345f19b00daSKim, Milo 2346f19b00daSKim, Milo if (!rdev->ena_pin) 2347f19b00daSKim, Milo return; 2348f19b00daSKim, Milo 2349f19b00daSKim, Milo /* Free the GPIO only in case of no use */ 2350f19b00daSKim, Milo list_for_each_entry_safe(pin, n, ®ulator_ena_gpio_list, list) { 23512dbf0855SMichał Mirosław if (pin != rdev->ena_pin) 23522dbf0855SMichał Mirosław continue; 23532dbf0855SMichał Mirosław 23542dbf0855SMichał Mirosław if (--pin->request_count) 23552dbf0855SMichał Mirosław break; 23562dbf0855SMichał Mirosław 235778927aa4SLinus Walleij gpiod_put(pin->gpiod); 2358f19b00daSKim, Milo list_del(&pin->list); 2359f19b00daSKim, Milo kfree(pin); 23602dbf0855SMichał Mirosław break; 23612dbf0855SMichał Mirosław } 23622dbf0855SMichał Mirosław 236360a2362fSSeung-Woo Kim rdev->ena_pin = NULL; 2364f19b00daSKim, Milo } 2365f19b00daSKim, Milo 2366967cfb18SKim, Milo /** 236731d6eebfSRobert P. J. Day * regulator_ena_gpio_ctrl - balance enable_count of each GPIO and actual GPIO pin control 236831d6eebfSRobert P. J. Day * @rdev: regulator_dev structure 236931d6eebfSRobert P. J. Day * @enable: enable GPIO at initial use? 237031d6eebfSRobert P. J. Day * 2371967cfb18SKim, Milo * GPIO is enabled in case of initial use. (enable_count is 0) 2372967cfb18SKim, Milo * GPIO is disabled when it is not shared any more. (enable_count <= 1) 2373967cfb18SKim, Milo */ 2374967cfb18SKim, Milo static int regulator_ena_gpio_ctrl(struct regulator_dev *rdev, bool enable) 2375967cfb18SKim, Milo { 2376967cfb18SKim, Milo struct regulator_enable_gpio *pin = rdev->ena_pin; 2377967cfb18SKim, Milo 2378967cfb18SKim, Milo if (!pin) 2379967cfb18SKim, Milo return -EINVAL; 2380967cfb18SKim, Milo 2381967cfb18SKim, Milo if (enable) { 2382967cfb18SKim, Milo /* Enable GPIO at initial use */ 2383967cfb18SKim, Milo if (pin->enable_count == 0) 238401dc79cdSLinus Walleij gpiod_set_value_cansleep(pin->gpiod, 1); 2385967cfb18SKim, Milo 2386967cfb18SKim, Milo pin->enable_count++; 2387967cfb18SKim, Milo } else { 2388967cfb18SKim, Milo if (pin->enable_count > 1) { 2389967cfb18SKim, Milo pin->enable_count--; 2390967cfb18SKim, Milo return 0; 2391967cfb18SKim, Milo } 2392967cfb18SKim, Milo 2393967cfb18SKim, Milo /* Disable GPIO if not used */ 2394967cfb18SKim, Milo if (pin->enable_count <= 1) { 239501dc79cdSLinus Walleij gpiod_set_value_cansleep(pin->gpiod, 0); 2396967cfb18SKim, Milo pin->enable_count = 0; 2397967cfb18SKim, Milo } 2398967cfb18SKim, Milo } 2399967cfb18SKim, Milo 2400967cfb18SKim, Milo return 0; 2401967cfb18SKim, Milo } 2402967cfb18SKim, Milo 240379fd1141SGuodong Xu /** 240479fd1141SGuodong Xu * _regulator_enable_delay - a delay helper function 240579fd1141SGuodong Xu * @delay: time to delay in microseconds 240679fd1141SGuodong Xu * 24075df529d4SThierry Reding * Delay for the requested amount of time as per the guidelines in: 24085df529d4SThierry Reding * 2409458f69efSMauro Carvalho Chehab * Documentation/timers/timers-howto.rst 24105df529d4SThierry Reding * 24115df529d4SThierry Reding * The assumption here is that regulators will never be enabled in 24125df529d4SThierry Reding * atomic context and therefore sleeping functions can be used. 24135df529d4SThierry Reding */ 241479fd1141SGuodong Xu static void _regulator_enable_delay(unsigned int delay) 241579fd1141SGuodong Xu { 24165df529d4SThierry Reding unsigned int ms = delay / 1000; 24175df529d4SThierry Reding unsigned int us = delay % 1000; 24185df529d4SThierry Reding 24195df529d4SThierry Reding if (ms > 0) { 24205df529d4SThierry Reding /* 24215df529d4SThierry Reding * For small enough values, handle super-millisecond 24225df529d4SThierry Reding * delays in the usleep_range() call below. 24235df529d4SThierry Reding */ 24245df529d4SThierry Reding if (ms < 20) 24255df529d4SThierry Reding us += ms * 1000; 24265df529d4SThierry Reding else 24275df529d4SThierry Reding msleep(ms); 24285df529d4SThierry Reding } 24295df529d4SThierry Reding 24305df529d4SThierry Reding /* 24315df529d4SThierry Reding * Give the scheduler some room to coalesce with any other 24325df529d4SThierry Reding * wakeup sources. For delays shorter than 10 us, don't even 24335df529d4SThierry Reding * bother setting up high-resolution timers and just busy- 24345df529d4SThierry Reding * loop. 24355df529d4SThierry Reding */ 24365df529d4SThierry Reding if (us >= 10) 24375df529d4SThierry Reding usleep_range(us, us + 100); 24385df529d4SThierry Reding else 24395df529d4SThierry Reding udelay(us); 24405c5659d0SMark Brown } 24415c5659d0SMark Brown 2442f7d7ad42SSumit Semwal /** 2443f7d7ad42SSumit Semwal * _regulator_check_status_enabled 2444f7d7ad42SSumit Semwal * 2445f7d7ad42SSumit Semwal * A helper function to check if the regulator status can be interpreted 2446f7d7ad42SSumit Semwal * as 'regulator is enabled'. 2447f7d7ad42SSumit Semwal * @rdev: the regulator device to check 2448f7d7ad42SSumit Semwal * 2449f7d7ad42SSumit Semwal * Return: 2450f7d7ad42SSumit Semwal * * 1 - if status shows regulator is in enabled state 2451f7d7ad42SSumit Semwal * * 0 - if not enabled state 2452f7d7ad42SSumit Semwal * * Error Value - as received from ops->get_status() 2453f7d7ad42SSumit Semwal */ 2454f7d7ad42SSumit Semwal static inline int _regulator_check_status_enabled(struct regulator_dev *rdev) 2455f7d7ad42SSumit Semwal { 2456f7d7ad42SSumit Semwal int ret = rdev->desc->ops->get_status(rdev); 2457f7d7ad42SSumit Semwal 2458f7d7ad42SSumit Semwal if (ret < 0) { 2459f7d7ad42SSumit Semwal rdev_info(rdev, "get_status returned error: %d\n", ret); 2460f7d7ad42SSumit Semwal return ret; 2461f7d7ad42SSumit Semwal } 2462f7d7ad42SSumit Semwal 2463f7d7ad42SSumit Semwal switch (ret) { 2464f7d7ad42SSumit Semwal case REGULATOR_STATUS_OFF: 2465f7d7ad42SSumit Semwal case REGULATOR_STATUS_ERROR: 2466f7d7ad42SSumit Semwal case REGULATOR_STATUS_UNDEFINED: 2467f7d7ad42SSumit Semwal return 0; 2468f7d7ad42SSumit Semwal default: 2469f7d7ad42SSumit Semwal return 1; 2470f7d7ad42SSumit Semwal } 2471f7d7ad42SSumit Semwal } 2472f7d7ad42SSumit Semwal 24735c5659d0SMark Brown static int _regulator_do_enable(struct regulator_dev *rdev) 24745c5659d0SMark Brown { 24755c5659d0SMark Brown int ret, delay; 24765c5659d0SMark Brown 24775c5659d0SMark Brown /* Query before enabling in case configuration dependent. */ 24785c5659d0SMark Brown ret = _regulator_get_enable_time(rdev); 24795c5659d0SMark Brown if (ret >= 0) { 24805c5659d0SMark Brown delay = ret; 24815c5659d0SMark Brown } else { 248261aab5adSMichał Mirosław rdev_warn(rdev, "enable_time() failed: %pe\n", ERR_PTR(ret)); 2483414c70cbSLiam Girdwood delay = 0; 2484414c70cbSLiam Girdwood } 24855c5659d0SMark Brown 2486414c70cbSLiam Girdwood trace_regulator_enable(rdev_get_name(rdev)); 2487414c70cbSLiam Girdwood 2488871f5650SGuodong Xu if (rdev->desc->off_on_delay) { 2489871f5650SGuodong Xu /* if needed, keep a distance of off_on_delay from last time 2490871f5650SGuodong Xu * this regulator was disabled. 2491871f5650SGuodong Xu */ 2492871f5650SGuodong Xu unsigned long start_jiffy = jiffies; 2493871f5650SGuodong Xu unsigned long intended, max_delay, remaining; 2494871f5650SGuodong Xu 2495871f5650SGuodong Xu max_delay = usecs_to_jiffies(rdev->desc->off_on_delay); 2496871f5650SGuodong Xu intended = rdev->last_off_jiffy + max_delay; 2497871f5650SGuodong Xu 2498871f5650SGuodong Xu if (time_before(start_jiffy, intended)) { 2499871f5650SGuodong Xu /* calc remaining jiffies to deal with one-time 2500871f5650SGuodong Xu * timer wrapping. 2501871f5650SGuodong Xu * in case of multiple timer wrapping, either it can be 2502871f5650SGuodong Xu * detected by out-of-range remaining, or it cannot be 250348f1b4efSKrzysztof Kozlowski * detected and we get a penalty of 2504871f5650SGuodong Xu * _regulator_enable_delay(). 2505871f5650SGuodong Xu */ 2506871f5650SGuodong Xu remaining = intended - start_jiffy; 2507871f5650SGuodong Xu if (remaining <= max_delay) 2508871f5650SGuodong Xu _regulator_enable_delay( 2509871f5650SGuodong Xu jiffies_to_usecs(remaining)); 2510871f5650SGuodong Xu } 2511871f5650SGuodong Xu } 2512871f5650SGuodong Xu 2513414c70cbSLiam Girdwood if (rdev->ena_pin) { 251429d62ec5SDoug Anderson if (!rdev->ena_gpio_state) { 25159a2372faSMark Brown ret = regulator_ena_gpio_ctrl(rdev, true); 2516414c70cbSLiam Girdwood if (ret < 0) 2517414c70cbSLiam Girdwood return ret; 25189a2372faSMark Brown rdev->ena_gpio_state = 1; 251929d62ec5SDoug Anderson } 25209a2372faSMark Brown } else if (rdev->desc->ops->enable) { 25219a2372faSMark Brown ret = rdev->desc->ops->enable(rdev); 25229a2372faSMark Brown if (ret < 0) 25239a2372faSMark Brown return ret; 25249a2372faSMark Brown } else { 25259a2372faSMark Brown return -EINVAL; 25265c5659d0SMark Brown } 25279a2372faSMark Brown 25289a2372faSMark Brown /* Allow the regulator to ramp; it would be useful to extend 252931aae2beSMark Brown * this for bulk operations so that the regulators can ramp 2530a7433cffSLinus Walleij * together. */ 25315da84fd9SJoe Perches trace_regulator_enable_delay(rdev_get_name(rdev)); 2532414c70cbSLiam Girdwood 2533f7d7ad42SSumit Semwal /* If poll_enabled_time is set, poll upto the delay calculated 2534f7d7ad42SSumit Semwal * above, delaying poll_enabled_time uS to check if the regulator 2535f7d7ad42SSumit Semwal * actually got enabled. 2536f7d7ad42SSumit Semwal * If the regulator isn't enabled after enable_delay has 2537f7d7ad42SSumit Semwal * expired, return -ETIMEDOUT. 2538f7d7ad42SSumit Semwal */ 2539f7d7ad42SSumit Semwal if (rdev->desc->poll_enabled_time) { 2540f7d7ad42SSumit Semwal unsigned int time_remaining = delay; 2541f7d7ad42SSumit Semwal 2542f7d7ad42SSumit Semwal while (time_remaining > 0) { 2543f7d7ad42SSumit Semwal _regulator_enable_delay(rdev->desc->poll_enabled_time); 2544f7d7ad42SSumit Semwal 2545f7d7ad42SSumit Semwal if (rdev->desc->ops->get_status) { 2546f7d7ad42SSumit Semwal ret = _regulator_check_status_enabled(rdev); 2547f7d7ad42SSumit Semwal if (ret < 0) 2548f7d7ad42SSumit Semwal return ret; 2549f7d7ad42SSumit Semwal else if (ret) 2550f7d7ad42SSumit Semwal break; 2551f7d7ad42SSumit Semwal } else if (rdev->desc->ops->is_enabled(rdev)) 2552f7d7ad42SSumit Semwal break; 2553f7d7ad42SSumit Semwal 2554f7d7ad42SSumit Semwal time_remaining -= rdev->desc->poll_enabled_time; 2555f7d7ad42SSumit Semwal } 2556f7d7ad42SSumit Semwal 2557f7d7ad42SSumit Semwal if (time_remaining <= 0) { 2558f7d7ad42SSumit Semwal rdev_err(rdev, "Enabled check timed out\n"); 2559f7d7ad42SSumit Semwal return -ETIMEDOUT; 2560f7d7ad42SSumit Semwal } 2561f7d7ad42SSumit Semwal } else { 256279fd1141SGuodong Xu _regulator_enable_delay(delay); 2563f7d7ad42SSumit Semwal } 2564a7433cffSLinus Walleij 2565414c70cbSLiam Girdwood trace_regulator_enable_complete(rdev_get_name(rdev)); 2566414c70cbSLiam Girdwood 25679a2372faSMark Brown return 0; 25689a2372faSMark Brown } 25699a2372faSMark Brown 25705451781dSDouglas Anderson /** 25715451781dSDouglas Anderson * _regulator_handle_consumer_enable - handle that a consumer enabled 25725451781dSDouglas Anderson * @regulator: regulator source 25735451781dSDouglas Anderson * 25745451781dSDouglas Anderson * Some things on a regulator consumer (like the contribution towards total 25755451781dSDouglas Anderson * load on the regulator) only have an effect when the consumer wants the 25765451781dSDouglas Anderson * regulator enabled. Explained in example with two consumers of the same 25775451781dSDouglas Anderson * regulator: 25785451781dSDouglas Anderson * consumer A: set_load(100); => total load = 0 25795451781dSDouglas Anderson * consumer A: regulator_enable(); => total load = 100 25805451781dSDouglas Anderson * consumer B: set_load(1000); => total load = 100 25815451781dSDouglas Anderson * consumer B: regulator_enable(); => total load = 1100 25825451781dSDouglas Anderson * consumer A: regulator_disable(); => total_load = 1000 25835451781dSDouglas Anderson * 25845451781dSDouglas Anderson * This function (together with _regulator_handle_consumer_disable) is 25855451781dSDouglas Anderson * responsible for keeping track of the refcount for a given regulator consumer 25865451781dSDouglas Anderson * and applying / unapplying these things. 25875451781dSDouglas Anderson * 25885451781dSDouglas Anderson * Returns 0 upon no error; -error upon error. 25895451781dSDouglas Anderson */ 25905451781dSDouglas Anderson static int _regulator_handle_consumer_enable(struct regulator *regulator) 2591414c70cbSLiam Girdwood { 25925451781dSDouglas Anderson struct regulator_dev *rdev = regulator->rdev; 25935451781dSDouglas Anderson 25945451781dSDouglas Anderson lockdep_assert_held_once(&rdev->mutex.base); 25955451781dSDouglas Anderson 25965451781dSDouglas Anderson regulator->enable_count++; 25975451781dSDouglas Anderson if (regulator->uA_load && regulator->enable_count == 1) 25985451781dSDouglas Anderson return drms_uA_update(rdev); 25995451781dSDouglas Anderson 26005451781dSDouglas Anderson return 0; 26015451781dSDouglas Anderson } 26025451781dSDouglas Anderson 26035451781dSDouglas Anderson /** 26045451781dSDouglas Anderson * _regulator_handle_consumer_disable - handle that a consumer disabled 26055451781dSDouglas Anderson * @regulator: regulator source 26065451781dSDouglas Anderson * 26075451781dSDouglas Anderson * The opposite of _regulator_handle_consumer_enable(). 26085451781dSDouglas Anderson * 26095451781dSDouglas Anderson * Returns 0 upon no error; -error upon error. 26105451781dSDouglas Anderson */ 26115451781dSDouglas Anderson static int _regulator_handle_consumer_disable(struct regulator *regulator) 26125451781dSDouglas Anderson { 26135451781dSDouglas Anderson struct regulator_dev *rdev = regulator->rdev; 26145451781dSDouglas Anderson 26155451781dSDouglas Anderson lockdep_assert_held_once(&rdev->mutex.base); 26165451781dSDouglas Anderson 26175451781dSDouglas Anderson if (!regulator->enable_count) { 26185451781dSDouglas Anderson rdev_err(rdev, "Underflow of regulator enable count\n"); 26195451781dSDouglas Anderson return -EINVAL; 26205451781dSDouglas Anderson } 26215451781dSDouglas Anderson 26225451781dSDouglas Anderson regulator->enable_count--; 26235451781dSDouglas Anderson if (regulator->uA_load && regulator->enable_count == 0) 26245451781dSDouglas Anderson return drms_uA_update(rdev); 26255451781dSDouglas Anderson 26265451781dSDouglas Anderson return 0; 26275451781dSDouglas Anderson } 26285451781dSDouglas Anderson 26295451781dSDouglas Anderson /* locks held by regulator_enable() */ 26305451781dSDouglas Anderson static int _regulator_enable(struct regulator *regulator) 26315451781dSDouglas Anderson { 26325451781dSDouglas Anderson struct regulator_dev *rdev = regulator->rdev; 2633414c70cbSLiam Girdwood int ret; 2634414c70cbSLiam Girdwood 2635f8702f9eSDmitry Osipenko lockdep_assert_held_once(&rdev->mutex.base); 2636f8702f9eSDmitry Osipenko 26371fc12b05SDouglas Anderson if (rdev->use_count == 0 && rdev->supply) { 26385451781dSDouglas Anderson ret = _regulator_enable(rdev->supply); 2639f8702f9eSDmitry Osipenko if (ret < 0) 2640f8702f9eSDmitry Osipenko return ret; 2641f8702f9eSDmitry Osipenko } 2642f8702f9eSDmitry Osipenko 2643f8702f9eSDmitry Osipenko /* balance only if there are regulators coupled */ 2644f8702f9eSDmitry Osipenko if (rdev->coupling_desc.n_coupled > 1) { 2645f8702f9eSDmitry Osipenko ret = regulator_balance_voltage(rdev, PM_SUSPEND_ON); 2646f8702f9eSDmitry Osipenko if (ret < 0) 2647f8702f9eSDmitry Osipenko goto err_disable_supply; 2648f8702f9eSDmitry Osipenko } 264970cfef26SKrzysztof Kozlowski 26505451781dSDouglas Anderson ret = _regulator_handle_consumer_enable(regulator); 26515451781dSDouglas Anderson if (ret < 0) 26525451781dSDouglas Anderson goto err_disable_supply; 2653cf7bbcdfSMark Brown 2654414c70cbSLiam Girdwood if (rdev->use_count == 0) { 2655cf7bbcdfSMark Brown /* The regulator may on if it's not switchable or left on */ 2656414c70cbSLiam Girdwood ret = _regulator_is_enabled(rdev); 2657414c70cbSLiam Girdwood if (ret == -EINVAL || ret == 0) { 26588a34e979SWEN Pingbo if (!regulator_ops_is_valid(rdev, 2659f8702f9eSDmitry Osipenko REGULATOR_CHANGE_STATUS)) { 2660f8702f9eSDmitry Osipenko ret = -EPERM; 26615451781dSDouglas Anderson goto err_consumer_disable; 2662f8702f9eSDmitry Osipenko } 2663412aec61SDavid Brownell 2664414c70cbSLiam Girdwood ret = _regulator_do_enable(rdev); 2665412aec61SDavid Brownell if (ret < 0) 26665451781dSDouglas Anderson goto err_consumer_disable; 2667414c70cbSLiam Girdwood 2668264b88c9SHarald Geyer _notifier_call_chain(rdev, REGULATOR_EVENT_ENABLE, 2669264b88c9SHarald Geyer NULL); 2670414c70cbSLiam Girdwood } else if (ret < 0) { 267161aab5adSMichał Mirosław rdev_err(rdev, "is_enabled() failed: %pe\n", ERR_PTR(ret)); 26725451781dSDouglas Anderson goto err_consumer_disable; 2673414c70cbSLiam Girdwood } 2674414c70cbSLiam Girdwood /* Fallthrough on positive return values - already enabled */ 2675414c70cbSLiam Girdwood } 2676414c70cbSLiam Girdwood 2677414c70cbSLiam Girdwood rdev->use_count++; 2678414c70cbSLiam Girdwood 2679414c70cbSLiam Girdwood return 0; 2680f8702f9eSDmitry Osipenko 26815451781dSDouglas Anderson err_consumer_disable: 26825451781dSDouglas Anderson _regulator_handle_consumer_disable(regulator); 26835451781dSDouglas Anderson 2684f8702f9eSDmitry Osipenko err_disable_supply: 26851fc12b05SDouglas Anderson if (rdev->use_count == 0 && rdev->supply) 26865451781dSDouglas Anderson _regulator_disable(rdev->supply); 2687f8702f9eSDmitry Osipenko 2688f8702f9eSDmitry Osipenko return ret; 2689414c70cbSLiam Girdwood } 2690414c70cbSLiam Girdwood 2691414c70cbSLiam Girdwood /** 2692414c70cbSLiam Girdwood * regulator_enable - enable regulator output 2693414c70cbSLiam Girdwood * @regulator: regulator source 2694414c70cbSLiam Girdwood * 2695414c70cbSLiam Girdwood * Request that the regulator be enabled with the regulator output at 2696414c70cbSLiam Girdwood * the predefined voltage or current value. Calls to regulator_enable() 2697414c70cbSLiam Girdwood * must be balanced with calls to regulator_disable(). 2698414c70cbSLiam Girdwood * 2699414c70cbSLiam Girdwood * NOTE: the output value can be set by other drivers, boot loader or may be 2700414c70cbSLiam Girdwood * hardwired in the regulator. 2701414c70cbSLiam Girdwood */ 2702414c70cbSLiam Girdwood int regulator_enable(struct regulator *regulator) 2703414c70cbSLiam Girdwood { 2704414c70cbSLiam Girdwood struct regulator_dev *rdev = regulator->rdev; 2705f8702f9eSDmitry Osipenko struct ww_acquire_ctx ww_ctx; 27065451781dSDouglas Anderson int ret; 27076492bc1bSMark Brown 2708f8702f9eSDmitry Osipenko regulator_lock_dependent(rdev, &ww_ctx); 27095451781dSDouglas Anderson ret = _regulator_enable(regulator); 2710f8702f9eSDmitry Osipenko regulator_unlock_dependent(rdev, &ww_ctx); 27113801b86aSMark Brown 2712414c70cbSLiam Girdwood return ret; 2713414c70cbSLiam Girdwood } 2714414c70cbSLiam Girdwood EXPORT_SYMBOL_GPL(regulator_enable); 2715414c70cbSLiam Girdwood 27165c5659d0SMark Brown static int _regulator_do_disable(struct regulator_dev *rdev) 27175c5659d0SMark Brown { 27185c5659d0SMark Brown int ret; 27195c5659d0SMark Brown 27205c5659d0SMark Brown trace_regulator_disable(rdev_get_name(rdev)); 27215c5659d0SMark Brown 2722967cfb18SKim, Milo if (rdev->ena_pin) { 272329d62ec5SDoug Anderson if (rdev->ena_gpio_state) { 2724967cfb18SKim, Milo ret = regulator_ena_gpio_ctrl(rdev, false); 2725967cfb18SKim, Milo if (ret < 0) 2726967cfb18SKim, Milo return ret; 27275c5659d0SMark Brown rdev->ena_gpio_state = 0; 272829d62ec5SDoug Anderson } 27295c5659d0SMark Brown 27305c5659d0SMark Brown } else if (rdev->desc->ops->disable) { 27315c5659d0SMark Brown ret = rdev->desc->ops->disable(rdev); 27325c5659d0SMark Brown if (ret != 0) 27335c5659d0SMark Brown return ret; 27345c5659d0SMark Brown } 27355c5659d0SMark Brown 2736871f5650SGuodong Xu /* cares about last_off_jiffy only if off_on_delay is required by 2737871f5650SGuodong Xu * device. 2738871f5650SGuodong Xu */ 2739871f5650SGuodong Xu if (rdev->desc->off_on_delay) 2740871f5650SGuodong Xu rdev->last_off_jiffy = jiffies; 2741871f5650SGuodong Xu 27425c5659d0SMark Brown trace_regulator_disable_complete(rdev_get_name(rdev)); 27435c5659d0SMark Brown 27445c5659d0SMark Brown return 0; 27455c5659d0SMark Brown } 27465c5659d0SMark Brown 2747414c70cbSLiam Girdwood /* locks held by regulator_disable() */ 27485451781dSDouglas Anderson static int _regulator_disable(struct regulator *regulator) 2749414c70cbSLiam Girdwood { 27505451781dSDouglas Anderson struct regulator_dev *rdev = regulator->rdev; 2751414c70cbSLiam Girdwood int ret = 0; 2752414c70cbSLiam Girdwood 2753f8702f9eSDmitry Osipenko lockdep_assert_held_once(&rdev->mutex.base); 275470cfef26SKrzysztof Kozlowski 2755cd94b505SDavid Brownell if (WARN(rdev->use_count <= 0, 275643e7ee33SJoe Perches "unbalanced disables for %s\n", rdev_get_name(rdev))) 2757cd94b505SDavid Brownell return -EIO; 2758cd94b505SDavid Brownell 2759414c70cbSLiam Girdwood /* are we the last user and permitted to disable ? */ 276060ef66fcSMark Brown if (rdev->use_count == 1 && 276160ef66fcSMark Brown (rdev->constraints && !rdev->constraints->always_on)) { 2762414c70cbSLiam Girdwood 2763414c70cbSLiam Girdwood /* we are last user */ 27648a34e979SWEN Pingbo if (regulator_ops_is_valid(rdev, REGULATOR_CHANGE_STATUS)) { 2765a1c8a551SRichard Fitzgerald ret = _notifier_call_chain(rdev, 2766a1c8a551SRichard Fitzgerald REGULATOR_EVENT_PRE_DISABLE, 2767a1c8a551SRichard Fitzgerald NULL); 2768a1c8a551SRichard Fitzgerald if (ret & NOTIFY_STOP_MASK) 2769a1c8a551SRichard Fitzgerald return -EINVAL; 2770a1c8a551SRichard Fitzgerald 27715c5659d0SMark Brown ret = _regulator_do_disable(rdev); 2772414c70cbSLiam Girdwood if (ret < 0) { 277361aab5adSMichał Mirosław rdev_err(rdev, "failed to disable: %pe\n", ERR_PTR(ret)); 2774a1c8a551SRichard Fitzgerald _notifier_call_chain(rdev, 2775a1c8a551SRichard Fitzgerald REGULATOR_EVENT_ABORT_DISABLE, 2776a1c8a551SRichard Fitzgerald NULL); 2777414c70cbSLiam Girdwood return ret; 2778414c70cbSLiam Girdwood } 277966fda75fSMarkus Pargmann _notifier_call_chain(rdev, REGULATOR_EVENT_DISABLE, 278066fda75fSMarkus Pargmann NULL); 2781414c70cbSLiam Girdwood } 2782414c70cbSLiam Girdwood 2783414c70cbSLiam Girdwood rdev->use_count = 0; 2784414c70cbSLiam Girdwood } else if (rdev->use_count > 1) { 2785414c70cbSLiam Girdwood rdev->use_count--; 2786414c70cbSLiam Girdwood } 27873801b86aSMark Brown 27885451781dSDouglas Anderson if (ret == 0) 27895451781dSDouglas Anderson ret = _regulator_handle_consumer_disable(regulator); 27905451781dSDouglas Anderson 2791f8702f9eSDmitry Osipenko if (ret == 0 && rdev->coupling_desc.n_coupled > 1) 2792f8702f9eSDmitry Osipenko ret = regulator_balance_voltage(rdev, PM_SUSPEND_ON); 2793f8702f9eSDmitry Osipenko 27941fc12b05SDouglas Anderson if (ret == 0 && rdev->use_count == 0 && rdev->supply) 27955451781dSDouglas Anderson ret = _regulator_disable(rdev->supply); 2796f8702f9eSDmitry Osipenko 2797414c70cbSLiam Girdwood return ret; 2798414c70cbSLiam Girdwood } 2799414c70cbSLiam Girdwood 2800414c70cbSLiam Girdwood /** 2801414c70cbSLiam Girdwood * regulator_disable - disable regulator output 2802414c70cbSLiam Girdwood * @regulator: regulator source 2803414c70cbSLiam Girdwood * 2804cf7bbcdfSMark Brown * Disable the regulator output voltage or current. Calls to 2805cf7bbcdfSMark Brown * regulator_enable() must be balanced with calls to 2806cf7bbcdfSMark Brown * regulator_disable(). 280769279fb9SMark Brown * 2808414c70cbSLiam Girdwood * NOTE: this will only disable the regulator output if no other consumer 2809cf7bbcdfSMark Brown * devices have it enabled, the regulator device supports disabling and 2810cf7bbcdfSMark Brown * machine constraints permit this operation. 2811414c70cbSLiam Girdwood */ 2812414c70cbSLiam Girdwood int regulator_disable(struct regulator *regulator) 2813414c70cbSLiam Girdwood { 2814412aec61SDavid Brownell struct regulator_dev *rdev = regulator->rdev; 2815f8702f9eSDmitry Osipenko struct ww_acquire_ctx ww_ctx; 28165451781dSDouglas Anderson int ret; 28176492bc1bSMark Brown 2818f8702f9eSDmitry Osipenko regulator_lock_dependent(rdev, &ww_ctx); 28195451781dSDouglas Anderson ret = _regulator_disable(regulator); 2820f8702f9eSDmitry Osipenko regulator_unlock_dependent(rdev, &ww_ctx); 28218cbf811dSJeffrey Carlyle 2822414c70cbSLiam Girdwood return ret; 2823414c70cbSLiam Girdwood } 2824414c70cbSLiam Girdwood EXPORT_SYMBOL_GPL(regulator_disable); 2825414c70cbSLiam Girdwood 2826414c70cbSLiam Girdwood /* locks held by regulator_force_disable() */ 28273801b86aSMark Brown static int _regulator_force_disable(struct regulator_dev *rdev) 2828414c70cbSLiam Girdwood { 2829414c70cbSLiam Girdwood int ret = 0; 2830414c70cbSLiam Girdwood 2831f8702f9eSDmitry Osipenko lockdep_assert_held_once(&rdev->mutex.base); 283270cfef26SKrzysztof Kozlowski 2833a1c8a551SRichard Fitzgerald ret = _notifier_call_chain(rdev, REGULATOR_EVENT_FORCE_DISABLE | 2834a1c8a551SRichard Fitzgerald REGULATOR_EVENT_PRE_DISABLE, NULL); 2835a1c8a551SRichard Fitzgerald if (ret & NOTIFY_STOP_MASK) 2836a1c8a551SRichard Fitzgerald return -EINVAL; 2837a1c8a551SRichard Fitzgerald 283866fda75fSMarkus Pargmann ret = _regulator_do_disable(rdev); 2839414c70cbSLiam Girdwood if (ret < 0) { 284061aab5adSMichał Mirosław rdev_err(rdev, "failed to force disable: %pe\n", ERR_PTR(ret)); 2841a1c8a551SRichard Fitzgerald _notifier_call_chain(rdev, REGULATOR_EVENT_FORCE_DISABLE | 2842a1c8a551SRichard Fitzgerald REGULATOR_EVENT_ABORT_DISABLE, NULL); 2843414c70cbSLiam Girdwood return ret; 2844414c70cbSLiam Girdwood } 284566fda75fSMarkus Pargmann 284684b68263SMark Brown _notifier_call_chain(rdev, REGULATOR_EVENT_FORCE_DISABLE | 284784b68263SMark Brown REGULATOR_EVENT_DISABLE, NULL); 2848414c70cbSLiam Girdwood 284966fda75fSMarkus Pargmann return 0; 2850414c70cbSLiam Girdwood } 2851414c70cbSLiam Girdwood 2852414c70cbSLiam Girdwood /** 2853414c70cbSLiam Girdwood * regulator_force_disable - force disable regulator output 2854414c70cbSLiam Girdwood * @regulator: regulator source 2855414c70cbSLiam Girdwood * 2856414c70cbSLiam Girdwood * Forcibly disable the regulator output voltage or current. 2857414c70cbSLiam Girdwood * NOTE: this *will* disable the regulator output even if other consumer 2858414c70cbSLiam Girdwood * devices have it enabled. This should be used for situations when device 2859414c70cbSLiam Girdwood * damage will likely occur if the regulator is not disabled (e.g. over temp). 2860414c70cbSLiam Girdwood */ 2861414c70cbSLiam Girdwood int regulator_force_disable(struct regulator *regulator) 2862414c70cbSLiam Girdwood { 286382d15839SMark Brown struct regulator_dev *rdev = regulator->rdev; 2864f8702f9eSDmitry Osipenko struct ww_acquire_ctx ww_ctx; 2865414c70cbSLiam Girdwood int ret; 2866414c70cbSLiam Girdwood 2867f8702f9eSDmitry Osipenko regulator_lock_dependent(rdev, &ww_ctx); 28685451781dSDouglas Anderson 28693801b86aSMark Brown ret = _regulator_force_disable(regulator->rdev); 28705451781dSDouglas Anderson 28719243a195SMaciej Purski if (rdev->coupling_desc.n_coupled > 1) 28729243a195SMaciej Purski regulator_balance_voltage(rdev, PM_SUSPEND_ON); 28735451781dSDouglas Anderson 28745451781dSDouglas Anderson if (regulator->uA_load) { 28755451781dSDouglas Anderson regulator->uA_load = 0; 28765451781dSDouglas Anderson ret = drms_uA_update(rdev); 28775451781dSDouglas Anderson } 28785451781dSDouglas Anderson 28791fc12b05SDouglas Anderson if (rdev->use_count != 0 && rdev->supply) 28801fc12b05SDouglas Anderson _regulator_disable(rdev->supply); 28818cbf811dSJeffrey Carlyle 28821fc12b05SDouglas Anderson regulator_unlock_dependent(rdev, &ww_ctx); 28838cbf811dSJeffrey Carlyle 2884414c70cbSLiam Girdwood return ret; 2885414c70cbSLiam Girdwood } 2886414c70cbSLiam Girdwood EXPORT_SYMBOL_GPL(regulator_force_disable); 2887414c70cbSLiam Girdwood 2888da07ecd9SMark Brown static void regulator_disable_work(struct work_struct *work) 2889da07ecd9SMark Brown { 2890da07ecd9SMark Brown struct regulator_dev *rdev = container_of(work, struct regulator_dev, 2891da07ecd9SMark Brown disable_work.work); 2892f8702f9eSDmitry Osipenko struct ww_acquire_ctx ww_ctx; 2893da07ecd9SMark Brown int count, i, ret; 28945451781dSDouglas Anderson struct regulator *regulator; 28955451781dSDouglas Anderson int total_count = 0; 2896da07ecd9SMark Brown 2897f8702f9eSDmitry Osipenko regulator_lock_dependent(rdev, &ww_ctx); 2898da07ecd9SMark Brown 2899c9ccaa0cSTirupathi Reddy /* 2900c9ccaa0cSTirupathi Reddy * Workqueue functions queue the new work instance while the previous 2901c9ccaa0cSTirupathi Reddy * work instance is being processed. Cancel the queued work instance 2902c9ccaa0cSTirupathi Reddy * as the work instance under processing does the job of the queued 2903c9ccaa0cSTirupathi Reddy * work instance. 2904c9ccaa0cSTirupathi Reddy */ 2905c9ccaa0cSTirupathi Reddy cancel_delayed_work(&rdev->disable_work); 2906c9ccaa0cSTirupathi Reddy 29075451781dSDouglas Anderson list_for_each_entry(regulator, &rdev->consumer_list, list) { 29085451781dSDouglas Anderson count = regulator->deferred_disables; 29095451781dSDouglas Anderson 29105451781dSDouglas Anderson if (!count) 29115451781dSDouglas Anderson continue; 29125451781dSDouglas Anderson 29135451781dSDouglas Anderson total_count += count; 29145451781dSDouglas Anderson regulator->deferred_disables = 0; 29155451781dSDouglas Anderson 2916da07ecd9SMark Brown for (i = 0; i < count; i++) { 29175451781dSDouglas Anderson ret = _regulator_disable(regulator); 2918da07ecd9SMark Brown if (ret != 0) 291961aab5adSMichał Mirosław rdev_err(rdev, "Deferred disable failed: %pe\n", 292061aab5adSMichał Mirosław ERR_PTR(ret)); 2921da07ecd9SMark Brown } 29225451781dSDouglas Anderson } 29235451781dSDouglas Anderson WARN_ON(!total_count); 2924da07ecd9SMark Brown 2925f8702f9eSDmitry Osipenko if (rdev->coupling_desc.n_coupled > 1) 2926f8702f9eSDmitry Osipenko regulator_balance_voltage(rdev, PM_SUSPEND_ON); 2927f8702f9eSDmitry Osipenko 2928f8702f9eSDmitry Osipenko regulator_unlock_dependent(rdev, &ww_ctx); 2929da07ecd9SMark Brown } 2930da07ecd9SMark Brown 2931da07ecd9SMark Brown /** 2932da07ecd9SMark Brown * regulator_disable_deferred - disable regulator output with delay 2933da07ecd9SMark Brown * @regulator: regulator source 293448f1b4efSKrzysztof Kozlowski * @ms: milliseconds until the regulator is disabled 2935da07ecd9SMark Brown * 2936da07ecd9SMark Brown * Execute regulator_disable() on the regulator after a delay. This 2937da07ecd9SMark Brown * is intended for use with devices that require some time to quiesce. 2938da07ecd9SMark Brown * 2939da07ecd9SMark Brown * NOTE: this will only disable the regulator output if no other consumer 2940da07ecd9SMark Brown * devices have it enabled, the regulator device supports disabling and 2941da07ecd9SMark Brown * machine constraints permit this operation. 2942da07ecd9SMark Brown */ 2943da07ecd9SMark Brown int regulator_disable_deferred(struct regulator *regulator, int ms) 2944da07ecd9SMark Brown { 2945da07ecd9SMark Brown struct regulator_dev *rdev = regulator->rdev; 2946da07ecd9SMark Brown 29472b5a24a0SMark Brown if (!ms) 29482b5a24a0SMark Brown return regulator_disable(regulator); 29492b5a24a0SMark Brown 295066cf9a7eSMaciej Purski regulator_lock(rdev); 29515451781dSDouglas Anderson regulator->deferred_disables++; 2952c9ccaa0cSTirupathi Reddy mod_delayed_work(system_power_efficient_wq, &rdev->disable_work, 2953c9ccaa0cSTirupathi Reddy msecs_to_jiffies(ms)); 295466cf9a7eSMaciej Purski regulator_unlock(rdev); 2955da07ecd9SMark Brown 2956aa59802dSMark Brown return 0; 2957da07ecd9SMark Brown } 2958da07ecd9SMark Brown EXPORT_SYMBOL_GPL(regulator_disable_deferred); 2959da07ecd9SMark Brown 2960414c70cbSLiam Girdwood static int _regulator_is_enabled(struct regulator_dev *rdev) 2961414c70cbSLiam Girdwood { 296265f73508SMark Brown /* A GPIO control always takes precedence */ 29637b74d149SKim, Milo if (rdev->ena_pin) 296465f73508SMark Brown return rdev->ena_gpio_state; 296565f73508SMark Brown 29669a7f6a4cSMark Brown /* If we don't know then assume that the regulator is always on */ 29679332546fSMark Brown if (!rdev->desc->ops->is_enabled) 29689a7f6a4cSMark Brown return 1; 2969414c70cbSLiam Girdwood 29709332546fSMark Brown return rdev->desc->ops->is_enabled(rdev); 2971414c70cbSLiam Girdwood } 2972414c70cbSLiam Girdwood 29733d67fe95SMaciej Purski static int _regulator_list_voltage(struct regulator_dev *rdev, 29743a40cfc3SSascha Hauer unsigned selector, int lock) 29753a40cfc3SSascha Hauer { 29763a40cfc3SSascha Hauer const struct regulator_ops *ops = rdev->desc->ops; 29773a40cfc3SSascha Hauer int ret; 29783a40cfc3SSascha Hauer 29793a40cfc3SSascha Hauer if (rdev->desc->fixed_uV && rdev->desc->n_voltages == 1 && !selector) 29803a40cfc3SSascha Hauer return rdev->desc->fixed_uV; 29813a40cfc3SSascha Hauer 29823a40cfc3SSascha Hauer if (ops->list_voltage) { 29833a40cfc3SSascha Hauer if (selector >= rdev->desc->n_voltages) 29843a40cfc3SSascha Hauer return -EINVAL; 298555cca739SClaudiu Beznea if (selector < rdev->desc->linear_min_sel) 298655cca739SClaudiu Beznea return 0; 29873a40cfc3SSascha Hauer if (lock) 298866cf9a7eSMaciej Purski regulator_lock(rdev); 29893a40cfc3SSascha Hauer ret = ops->list_voltage(rdev, selector); 29903a40cfc3SSascha Hauer if (lock) 299166cf9a7eSMaciej Purski regulator_unlock(rdev); 2992fd086045SMatthias Kaehlcke } else if (rdev->is_switch && rdev->supply) { 29933d67fe95SMaciej Purski ret = _regulator_list_voltage(rdev->supply->rdev, 29943d67fe95SMaciej Purski selector, lock); 29953a40cfc3SSascha Hauer } else { 29963a40cfc3SSascha Hauer return -EINVAL; 29973a40cfc3SSascha Hauer } 29983a40cfc3SSascha Hauer 29993a40cfc3SSascha Hauer if (ret > 0) { 30003a40cfc3SSascha Hauer if (ret < rdev->constraints->min_uV) 30013a40cfc3SSascha Hauer ret = 0; 30023a40cfc3SSascha Hauer else if (ret > rdev->constraints->max_uV) 30033a40cfc3SSascha Hauer ret = 0; 30043a40cfc3SSascha Hauer } 30053a40cfc3SSascha Hauer 30063a40cfc3SSascha Hauer return ret; 30073a40cfc3SSascha Hauer } 30083a40cfc3SSascha Hauer 3009414c70cbSLiam Girdwood /** 3010414c70cbSLiam Girdwood * regulator_is_enabled - is the regulator output enabled 3011414c70cbSLiam Girdwood * @regulator: regulator source 3012414c70cbSLiam Girdwood * 3013412aec61SDavid Brownell * Returns positive if the regulator driver backing the source/client 3014412aec61SDavid Brownell * has requested that the device be enabled, zero if it hasn't, else a 3015412aec61SDavid Brownell * negative errno code. 3016412aec61SDavid Brownell * 3017412aec61SDavid Brownell * Note that the device backing this regulator handle can have multiple 3018412aec61SDavid Brownell * users, so it might be enabled even if regulator_enable() was never 3019412aec61SDavid Brownell * called for this particular source. 3020414c70cbSLiam Girdwood */ 3021414c70cbSLiam Girdwood int regulator_is_enabled(struct regulator *regulator) 3022414c70cbSLiam Girdwood { 30239332546fSMark Brown int ret; 30249332546fSMark Brown 30256492bc1bSMark Brown if (regulator->always_on) 30266492bc1bSMark Brown return 1; 30276492bc1bSMark Brown 3028f8702f9eSDmitry Osipenko regulator_lock(regulator->rdev); 30299332546fSMark Brown ret = _regulator_is_enabled(regulator->rdev); 3030f8702f9eSDmitry Osipenko regulator_unlock(regulator->rdev); 30319332546fSMark Brown 30329332546fSMark Brown return ret; 3033414c70cbSLiam Girdwood } 3034414c70cbSLiam Girdwood EXPORT_SYMBOL_GPL(regulator_is_enabled); 3035414c70cbSLiam Girdwood 3036414c70cbSLiam Girdwood /** 30374367cfdcSDavid Brownell * regulator_count_voltages - count regulator_list_voltage() selectors 30384367cfdcSDavid Brownell * @regulator: regulator source 30394367cfdcSDavid Brownell * 30404367cfdcSDavid Brownell * Returns number of selectors, or negative errno. Selectors are 30414367cfdcSDavid Brownell * numbered starting at zero, and typically correspond to bitfields 30424367cfdcSDavid Brownell * in hardware registers. 30434367cfdcSDavid Brownell */ 30444367cfdcSDavid Brownell int regulator_count_voltages(struct regulator *regulator) 30454367cfdcSDavid Brownell { 30464367cfdcSDavid Brownell struct regulator_dev *rdev = regulator->rdev; 30474367cfdcSDavid Brownell 304826988efeSJavier Martinez Canillas if (rdev->desc->n_voltages) 304926988efeSJavier Martinez Canillas return rdev->desc->n_voltages; 305026988efeSJavier Martinez Canillas 3051fd086045SMatthias Kaehlcke if (!rdev->is_switch || !rdev->supply) 305226988efeSJavier Martinez Canillas return -EINVAL; 305326988efeSJavier Martinez Canillas 305426988efeSJavier Martinez Canillas return regulator_count_voltages(rdev->supply); 30554367cfdcSDavid Brownell } 30564367cfdcSDavid Brownell EXPORT_SYMBOL_GPL(regulator_count_voltages); 30574367cfdcSDavid Brownell 30584367cfdcSDavid Brownell /** 30594367cfdcSDavid Brownell * regulator_list_voltage - enumerate supported voltages 30604367cfdcSDavid Brownell * @regulator: regulator source 30614367cfdcSDavid Brownell * @selector: identify voltage to list 30624367cfdcSDavid Brownell * Context: can sleep 30634367cfdcSDavid Brownell * 30644367cfdcSDavid Brownell * Returns a voltage that can be passed to @regulator_set_voltage(), 306588393161SThomas Weber * zero if this selector code can't be used on this system, or a 30664367cfdcSDavid Brownell * negative errno. 30674367cfdcSDavid Brownell */ 30684367cfdcSDavid Brownell int regulator_list_voltage(struct regulator *regulator, unsigned selector) 30694367cfdcSDavid Brownell { 30703d67fe95SMaciej Purski return _regulator_list_voltage(regulator->rdev, selector, 1); 30714367cfdcSDavid Brownell } 30724367cfdcSDavid Brownell EXPORT_SYMBOL_GPL(regulator_list_voltage); 30734367cfdcSDavid Brownell 30744367cfdcSDavid Brownell /** 307504eca28cSTuomas Tynkkynen * regulator_get_regmap - get the regulator's register map 307604eca28cSTuomas Tynkkynen * @regulator: regulator source 307704eca28cSTuomas Tynkkynen * 307804eca28cSTuomas Tynkkynen * Returns the register map for the given regulator, or an ERR_PTR value 307904eca28cSTuomas Tynkkynen * if the regulator doesn't use regmap. 308004eca28cSTuomas Tynkkynen */ 308104eca28cSTuomas Tynkkynen struct regmap *regulator_get_regmap(struct regulator *regulator) 308204eca28cSTuomas Tynkkynen { 308304eca28cSTuomas Tynkkynen struct regmap *map = regulator->rdev->regmap; 308404eca28cSTuomas Tynkkynen 308504eca28cSTuomas Tynkkynen return map ? map : ERR_PTR(-EOPNOTSUPP); 308604eca28cSTuomas Tynkkynen } 308704eca28cSTuomas Tynkkynen 308804eca28cSTuomas Tynkkynen /** 308904eca28cSTuomas Tynkkynen * regulator_get_hardware_vsel_register - get the HW voltage selector register 309004eca28cSTuomas Tynkkynen * @regulator: regulator source 309104eca28cSTuomas Tynkkynen * @vsel_reg: voltage selector register, output parameter 309204eca28cSTuomas Tynkkynen * @vsel_mask: mask for voltage selector bitfield, output parameter 309304eca28cSTuomas Tynkkynen * 309404eca28cSTuomas Tynkkynen * Returns the hardware register offset and bitmask used for setting the 309504eca28cSTuomas Tynkkynen * regulator voltage. This might be useful when configuring voltage-scaling 309604eca28cSTuomas Tynkkynen * hardware or firmware that can make I2C requests behind the kernel's back, 309704eca28cSTuomas Tynkkynen * for example. 309804eca28cSTuomas Tynkkynen * 309904eca28cSTuomas Tynkkynen * On success, the output parameters @vsel_reg and @vsel_mask are filled in 310004eca28cSTuomas Tynkkynen * and 0 is returned, otherwise a negative errno is returned. 310104eca28cSTuomas Tynkkynen */ 310204eca28cSTuomas Tynkkynen int regulator_get_hardware_vsel_register(struct regulator *regulator, 310304eca28cSTuomas Tynkkynen unsigned *vsel_reg, 310404eca28cSTuomas Tynkkynen unsigned *vsel_mask) 310504eca28cSTuomas Tynkkynen { 310604eca28cSTuomas Tynkkynen struct regulator_dev *rdev = regulator->rdev; 310739f5460dSGuodong Xu const struct regulator_ops *ops = rdev->desc->ops; 310804eca28cSTuomas Tynkkynen 310904eca28cSTuomas Tynkkynen if (ops->set_voltage_sel != regulator_set_voltage_sel_regmap) 311004eca28cSTuomas Tynkkynen return -EOPNOTSUPP; 311104eca28cSTuomas Tynkkynen 311204eca28cSTuomas Tynkkynen *vsel_reg = rdev->desc->vsel_reg; 311304eca28cSTuomas Tynkkynen *vsel_mask = rdev->desc->vsel_mask; 311404eca28cSTuomas Tynkkynen 311504eca28cSTuomas Tynkkynen return 0; 311604eca28cSTuomas Tynkkynen } 311704eca28cSTuomas Tynkkynen EXPORT_SYMBOL_GPL(regulator_get_hardware_vsel_register); 311804eca28cSTuomas Tynkkynen 311904eca28cSTuomas Tynkkynen /** 312004eca28cSTuomas Tynkkynen * regulator_list_hardware_vsel - get the HW-specific register value for a selector 312104eca28cSTuomas Tynkkynen * @regulator: regulator source 312204eca28cSTuomas Tynkkynen * @selector: identify voltage to list 312304eca28cSTuomas Tynkkynen * 312404eca28cSTuomas Tynkkynen * Converts the selector to a hardware-specific voltage selector that can be 312504eca28cSTuomas Tynkkynen * directly written to the regulator registers. The address of the voltage 312604eca28cSTuomas Tynkkynen * register can be determined by calling @regulator_get_hardware_vsel_register. 312704eca28cSTuomas Tynkkynen * 312804eca28cSTuomas Tynkkynen * On error a negative errno is returned. 312904eca28cSTuomas Tynkkynen */ 313004eca28cSTuomas Tynkkynen int regulator_list_hardware_vsel(struct regulator *regulator, 313104eca28cSTuomas Tynkkynen unsigned selector) 313204eca28cSTuomas Tynkkynen { 313304eca28cSTuomas Tynkkynen struct regulator_dev *rdev = regulator->rdev; 313439f5460dSGuodong Xu const struct regulator_ops *ops = rdev->desc->ops; 313504eca28cSTuomas Tynkkynen 313604eca28cSTuomas Tynkkynen if (selector >= rdev->desc->n_voltages) 313704eca28cSTuomas Tynkkynen return -EINVAL; 313855cca739SClaudiu Beznea if (selector < rdev->desc->linear_min_sel) 313955cca739SClaudiu Beznea return 0; 314004eca28cSTuomas Tynkkynen if (ops->set_voltage_sel != regulator_set_voltage_sel_regmap) 314104eca28cSTuomas Tynkkynen return -EOPNOTSUPP; 314204eca28cSTuomas Tynkkynen 314304eca28cSTuomas Tynkkynen return selector; 314404eca28cSTuomas Tynkkynen } 314504eca28cSTuomas Tynkkynen EXPORT_SYMBOL_GPL(regulator_list_hardware_vsel); 314604eca28cSTuomas Tynkkynen 314704eca28cSTuomas Tynkkynen /** 31482a668a8bSPaul Walmsley * regulator_get_linear_step - return the voltage step size between VSEL values 31492a668a8bSPaul Walmsley * @regulator: regulator source 31502a668a8bSPaul Walmsley * 31512a668a8bSPaul Walmsley * Returns the voltage step size between VSEL values for linear 31522a668a8bSPaul Walmsley * regulators, or return 0 if the regulator isn't a linear regulator. 31532a668a8bSPaul Walmsley */ 31542a668a8bSPaul Walmsley unsigned int regulator_get_linear_step(struct regulator *regulator) 31552a668a8bSPaul Walmsley { 31562a668a8bSPaul Walmsley struct regulator_dev *rdev = regulator->rdev; 31572a668a8bSPaul Walmsley 31582a668a8bSPaul Walmsley return rdev->desc->uV_step; 31592a668a8bSPaul Walmsley } 31602a668a8bSPaul Walmsley EXPORT_SYMBOL_GPL(regulator_get_linear_step); 31612a668a8bSPaul Walmsley 31622a668a8bSPaul Walmsley /** 3163a7a1ad90SMark Brown * regulator_is_supported_voltage - check if a voltage range can be supported 3164a7a1ad90SMark Brown * 3165a7a1ad90SMark Brown * @regulator: Regulator to check. 3166a7a1ad90SMark Brown * @min_uV: Minimum required voltage in uV. 3167a7a1ad90SMark Brown * @max_uV: Maximum required voltage in uV. 3168a7a1ad90SMark Brown * 316949820944SJorge Ramirez-Ortiz * Returns a boolean. 3170a7a1ad90SMark Brown */ 3171a7a1ad90SMark Brown int regulator_is_supported_voltage(struct regulator *regulator, 3172a7a1ad90SMark Brown int min_uV, int max_uV) 3173a7a1ad90SMark Brown { 3174c5f3939bSMark Brown struct regulator_dev *rdev = regulator->rdev; 3175a7a1ad90SMark Brown int i, voltages, ret; 3176a7a1ad90SMark Brown 3177c5f3939bSMark Brown /* If we can't change voltage check the current voltage */ 31788a34e979SWEN Pingbo if (!regulator_ops_is_valid(rdev, REGULATOR_CHANGE_VOLTAGE)) { 3179c5f3939bSMark Brown ret = regulator_get_voltage(regulator); 3180c5f3939bSMark Brown if (ret >= 0) 31810d25d09dSJingoo Han return min_uV <= ret && ret <= max_uV; 3182c5f3939bSMark Brown else 3183c5f3939bSMark Brown return ret; 3184c5f3939bSMark Brown } 3185c5f3939bSMark Brown 3186bd7a2b60SPawel Moll /* Any voltage within constrains range is fine? */ 3187bd7a2b60SPawel Moll if (rdev->desc->continuous_voltage_range) 3188bd7a2b60SPawel Moll return min_uV >= rdev->constraints->min_uV && 3189bd7a2b60SPawel Moll max_uV <= rdev->constraints->max_uV; 3190bd7a2b60SPawel Moll 3191a7a1ad90SMark Brown ret = regulator_count_voltages(regulator); 3192a7a1ad90SMark Brown if (ret < 0) 319349820944SJorge Ramirez-Ortiz return 0; 3194a7a1ad90SMark Brown voltages = ret; 3195a7a1ad90SMark Brown 3196a7a1ad90SMark Brown for (i = 0; i < voltages; i++) { 3197a7a1ad90SMark Brown ret = regulator_list_voltage(regulator, i); 3198a7a1ad90SMark Brown 3199a7a1ad90SMark Brown if (ret >= min_uV && ret <= max_uV) 3200a7a1ad90SMark Brown return 1; 3201a7a1ad90SMark Brown } 3202a7a1ad90SMark Brown 3203a7a1ad90SMark Brown return 0; 3204a7a1ad90SMark Brown } 3205a398eaa2SMark Brown EXPORT_SYMBOL_GPL(regulator_is_supported_voltage); 3206a7a1ad90SMark Brown 3207a204f41eSSascha Hauer static int regulator_map_voltage(struct regulator_dev *rdev, int min_uV, 3208a204f41eSSascha Hauer int max_uV) 3209a204f41eSSascha Hauer { 3210a204f41eSSascha Hauer const struct regulator_desc *desc = rdev->desc; 3211a204f41eSSascha Hauer 3212a204f41eSSascha Hauer if (desc->ops->map_voltage) 3213a204f41eSSascha Hauer return desc->ops->map_voltage(rdev, min_uV, max_uV); 3214a204f41eSSascha Hauer 3215a204f41eSSascha Hauer if (desc->ops->list_voltage == regulator_list_voltage_linear) 3216a204f41eSSascha Hauer return regulator_map_voltage_linear(rdev, min_uV, max_uV); 3217a204f41eSSascha Hauer 3218a204f41eSSascha Hauer if (desc->ops->list_voltage == regulator_list_voltage_linear_range) 3219a204f41eSSascha Hauer return regulator_map_voltage_linear_range(rdev, min_uV, max_uV); 3220a204f41eSSascha Hauer 322118e4b55fSMatti Vaittinen if (desc->ops->list_voltage == 322218e4b55fSMatti Vaittinen regulator_list_voltage_pickable_linear_range) 322318e4b55fSMatti Vaittinen return regulator_map_voltage_pickable_linear_range(rdev, 322418e4b55fSMatti Vaittinen min_uV, max_uV); 322518e4b55fSMatti Vaittinen 3226a204f41eSSascha Hauer return regulator_map_voltage_iterate(rdev, min_uV, max_uV); 3227a204f41eSSascha Hauer } 3228a204f41eSSascha Hauer 32297179569aSHeiko Stübner static int _regulator_call_set_voltage(struct regulator_dev *rdev, 32307179569aSHeiko Stübner int min_uV, int max_uV, 32317179569aSHeiko Stübner unsigned *selector) 32327179569aSHeiko Stübner { 32337179569aSHeiko Stübner struct pre_voltage_change_data data; 32347179569aSHeiko Stübner int ret; 32357179569aSHeiko Stübner 3236d22b85a1SDmitry Osipenko data.old_uV = regulator_get_voltage_rdev(rdev); 32377179569aSHeiko Stübner data.min_uV = min_uV; 32387179569aSHeiko Stübner data.max_uV = max_uV; 32397179569aSHeiko Stübner ret = _notifier_call_chain(rdev, REGULATOR_EVENT_PRE_VOLTAGE_CHANGE, 32407179569aSHeiko Stübner &data); 32417179569aSHeiko Stübner if (ret & NOTIFY_STOP_MASK) 32427179569aSHeiko Stübner return -EINVAL; 32437179569aSHeiko Stübner 32447179569aSHeiko Stübner ret = rdev->desc->ops->set_voltage(rdev, min_uV, max_uV, selector); 32457179569aSHeiko Stübner if (ret >= 0) 32467179569aSHeiko Stübner return ret; 32477179569aSHeiko Stübner 32487179569aSHeiko Stübner _notifier_call_chain(rdev, REGULATOR_EVENT_ABORT_VOLTAGE_CHANGE, 32497179569aSHeiko Stübner (void *)data.old_uV); 32507179569aSHeiko Stübner 32517179569aSHeiko Stübner return ret; 32527179569aSHeiko Stübner } 32537179569aSHeiko Stübner 32547179569aSHeiko Stübner static int _regulator_call_set_voltage_sel(struct regulator_dev *rdev, 32557179569aSHeiko Stübner int uV, unsigned selector) 32567179569aSHeiko Stübner { 32577179569aSHeiko Stübner struct pre_voltage_change_data data; 32587179569aSHeiko Stübner int ret; 32597179569aSHeiko Stübner 3260d22b85a1SDmitry Osipenko data.old_uV = regulator_get_voltage_rdev(rdev); 32617179569aSHeiko Stübner data.min_uV = uV; 32627179569aSHeiko Stübner data.max_uV = uV; 32637179569aSHeiko Stübner ret = _notifier_call_chain(rdev, REGULATOR_EVENT_PRE_VOLTAGE_CHANGE, 32647179569aSHeiko Stübner &data); 32657179569aSHeiko Stübner if (ret & NOTIFY_STOP_MASK) 32667179569aSHeiko Stübner return -EINVAL; 32677179569aSHeiko Stübner 32687179569aSHeiko Stübner ret = rdev->desc->ops->set_voltage_sel(rdev, selector); 32697179569aSHeiko Stübner if (ret >= 0) 32707179569aSHeiko Stübner return ret; 32717179569aSHeiko Stübner 32727179569aSHeiko Stübner _notifier_call_chain(rdev, REGULATOR_EVENT_ABORT_VOLTAGE_CHANGE, 32737179569aSHeiko Stübner (void *)data.old_uV); 32747179569aSHeiko Stübner 32757179569aSHeiko Stübner return ret; 32767179569aSHeiko Stübner } 32777179569aSHeiko Stübner 32782da8d947SBartosz Golaszewski static int _regulator_set_voltage_sel_step(struct regulator_dev *rdev, 32792da8d947SBartosz Golaszewski int uV, int new_selector) 32802da8d947SBartosz Golaszewski { 32812da8d947SBartosz Golaszewski const struct regulator_ops *ops = rdev->desc->ops; 32822da8d947SBartosz Golaszewski int diff, old_sel, curr_sel, ret; 32832da8d947SBartosz Golaszewski 32842da8d947SBartosz Golaszewski /* Stepping is only needed if the regulator is enabled. */ 32852da8d947SBartosz Golaszewski if (!_regulator_is_enabled(rdev)) 32862da8d947SBartosz Golaszewski goto final_set; 32872da8d947SBartosz Golaszewski 32882da8d947SBartosz Golaszewski if (!ops->get_voltage_sel) 32892da8d947SBartosz Golaszewski return -EINVAL; 32902da8d947SBartosz Golaszewski 32912da8d947SBartosz Golaszewski old_sel = ops->get_voltage_sel(rdev); 32922da8d947SBartosz Golaszewski if (old_sel < 0) 32932da8d947SBartosz Golaszewski return old_sel; 32942da8d947SBartosz Golaszewski 32952da8d947SBartosz Golaszewski diff = new_selector - old_sel; 32962da8d947SBartosz Golaszewski if (diff == 0) 32972da8d947SBartosz Golaszewski return 0; /* No change needed. */ 32982da8d947SBartosz Golaszewski 32992da8d947SBartosz Golaszewski if (diff > 0) { 33002da8d947SBartosz Golaszewski /* Stepping up. */ 33012da8d947SBartosz Golaszewski for (curr_sel = old_sel + rdev->desc->vsel_step; 33022da8d947SBartosz Golaszewski curr_sel < new_selector; 33032da8d947SBartosz Golaszewski curr_sel += rdev->desc->vsel_step) { 33042da8d947SBartosz Golaszewski /* 33052da8d947SBartosz Golaszewski * Call the callback directly instead of using 33062da8d947SBartosz Golaszewski * _regulator_call_set_voltage_sel() as we don't 33072da8d947SBartosz Golaszewski * want to notify anyone yet. Same in the branch 33082da8d947SBartosz Golaszewski * below. 33092da8d947SBartosz Golaszewski */ 33102da8d947SBartosz Golaszewski ret = ops->set_voltage_sel(rdev, curr_sel); 33112da8d947SBartosz Golaszewski if (ret) 33122da8d947SBartosz Golaszewski goto try_revert; 33132da8d947SBartosz Golaszewski } 33142da8d947SBartosz Golaszewski } else { 33152da8d947SBartosz Golaszewski /* Stepping down. */ 33162da8d947SBartosz Golaszewski for (curr_sel = old_sel - rdev->desc->vsel_step; 33172da8d947SBartosz Golaszewski curr_sel > new_selector; 33182da8d947SBartosz Golaszewski curr_sel -= rdev->desc->vsel_step) { 33192da8d947SBartosz Golaszewski ret = ops->set_voltage_sel(rdev, curr_sel); 33202da8d947SBartosz Golaszewski if (ret) 33212da8d947SBartosz Golaszewski goto try_revert; 33222da8d947SBartosz Golaszewski } 33232da8d947SBartosz Golaszewski } 33242da8d947SBartosz Golaszewski 33252da8d947SBartosz Golaszewski final_set: 33262da8d947SBartosz Golaszewski /* The final selector will trigger the notifiers. */ 33272da8d947SBartosz Golaszewski return _regulator_call_set_voltage_sel(rdev, uV, new_selector); 33282da8d947SBartosz Golaszewski 33292da8d947SBartosz Golaszewski try_revert: 33302da8d947SBartosz Golaszewski /* 33312da8d947SBartosz Golaszewski * At least try to return to the previous voltage if setting a new 33322da8d947SBartosz Golaszewski * one failed. 33332da8d947SBartosz Golaszewski */ 33342da8d947SBartosz Golaszewski (void)ops->set_voltage_sel(rdev, old_sel); 33352da8d947SBartosz Golaszewski return ret; 33362da8d947SBartosz Golaszewski } 33372da8d947SBartosz Golaszewski 333873e705bfSMatthias Kaehlcke static int _regulator_set_voltage_time(struct regulator_dev *rdev, 333973e705bfSMatthias Kaehlcke int old_uV, int new_uV) 334073e705bfSMatthias Kaehlcke { 334173e705bfSMatthias Kaehlcke unsigned int ramp_delay = 0; 334273e705bfSMatthias Kaehlcke 334373e705bfSMatthias Kaehlcke if (rdev->constraints->ramp_delay) 334473e705bfSMatthias Kaehlcke ramp_delay = rdev->constraints->ramp_delay; 334573e705bfSMatthias Kaehlcke else if (rdev->desc->ramp_delay) 334673e705bfSMatthias Kaehlcke ramp_delay = rdev->desc->ramp_delay; 3347d6c1dc3fSLaxman Dewangan else if (rdev->constraints->settling_time) 3348d6c1dc3fSLaxman Dewangan return rdev->constraints->settling_time; 33493ffad468SMatthias Kaehlcke else if (rdev->constraints->settling_time_up && 33503ffad468SMatthias Kaehlcke (new_uV > old_uV)) 33513ffad468SMatthias Kaehlcke return rdev->constraints->settling_time_up; 33523ffad468SMatthias Kaehlcke else if (rdev->constraints->settling_time_down && 33533ffad468SMatthias Kaehlcke (new_uV < old_uV)) 33543ffad468SMatthias Kaehlcke return rdev->constraints->settling_time_down; 335573e705bfSMatthias Kaehlcke 335673e705bfSMatthias Kaehlcke if (ramp_delay == 0) { 3357ba14fa1aSH. Nikolaus Schaller rdev_dbg(rdev, "ramp_delay not set\n"); 335873e705bfSMatthias Kaehlcke return 0; 335973e705bfSMatthias Kaehlcke } 336073e705bfSMatthias Kaehlcke 336173e705bfSMatthias Kaehlcke return DIV_ROUND_UP(abs(new_uV - old_uV), ramp_delay); 336273e705bfSMatthias Kaehlcke } 336373e705bfSMatthias Kaehlcke 336475790251SMark Brown static int _regulator_do_set_voltage(struct regulator_dev *rdev, 336575790251SMark Brown int min_uV, int max_uV) 336675790251SMark Brown { 336775790251SMark Brown int ret; 336877af1b26SLinus Walleij int delay = 0; 3369e113d792SMark Brown int best_val = 0; 337075790251SMark Brown unsigned int selector; 3371eba41a5eSAxel Lin int old_selector = -1; 337257995a48SMatthias Kaehlcke const struct regulator_ops *ops = rdev->desc->ops; 3373d22b85a1SDmitry Osipenko int old_uV = regulator_get_voltage_rdev(rdev); 337475790251SMark Brown 337575790251SMark Brown trace_regulator_set_voltage(rdev_get_name(rdev), min_uV, max_uV); 337675790251SMark Brown 3377bf5892a8SMark Brown min_uV += rdev->constraints->uV_offset; 3378bf5892a8SMark Brown max_uV += rdev->constraints->uV_offset; 3379bf5892a8SMark Brown 338077af1b26SLinus Walleij /* 338177af1b26SLinus Walleij * If we can't obtain the old selector there is not enough 338277af1b26SLinus Walleij * info to call set_voltage_time_sel(). 338377af1b26SLinus Walleij */ 33848b7485efSAxel Lin if (_regulator_is_enabled(rdev) && 338557995a48SMatthias Kaehlcke ops->set_voltage_time_sel && ops->get_voltage_sel) { 338657995a48SMatthias Kaehlcke old_selector = ops->get_voltage_sel(rdev); 3387eba41a5eSAxel Lin if (old_selector < 0) 3388eba41a5eSAxel Lin return old_selector; 3389eba41a5eSAxel Lin } 339077af1b26SLinus Walleij 339157995a48SMatthias Kaehlcke if (ops->set_voltage) { 33927179569aSHeiko Stübner ret = _regulator_call_set_voltage(rdev, min_uV, max_uV, 339375790251SMark Brown &selector); 3394e113d792SMark Brown 3395e113d792SMark Brown if (ret >= 0) { 339657995a48SMatthias Kaehlcke if (ops->list_voltage) 339757995a48SMatthias Kaehlcke best_val = ops->list_voltage(rdev, 3398e113d792SMark Brown selector); 3399e113d792SMark Brown else 3400d22b85a1SDmitry Osipenko best_val = regulator_get_voltage_rdev(rdev); 3401e113d792SMark Brown } 3402e113d792SMark Brown 340357995a48SMatthias Kaehlcke } else if (ops->set_voltage_sel) { 3404a204f41eSSascha Hauer ret = regulator_map_voltage(rdev, min_uV, max_uV); 3405e843fc46SMark Brown if (ret >= 0) { 340657995a48SMatthias Kaehlcke best_val = ops->list_voltage(rdev, ret); 3407e113d792SMark Brown if (min_uV <= best_val && max_uV >= best_val) { 3408e843fc46SMark Brown selector = ret; 3409c66a566aSAxel Lin if (old_selector == selector) 3410c66a566aSAxel Lin ret = 0; 34112da8d947SBartosz Golaszewski else if (rdev->desc->vsel_step) 34122da8d947SBartosz Golaszewski ret = _regulator_set_voltage_sel_step( 34132da8d947SBartosz Golaszewski rdev, best_val, selector); 3414c66a566aSAxel Lin else 34157179569aSHeiko Stübner ret = _regulator_call_set_voltage_sel( 34167179569aSHeiko Stübner rdev, best_val, selector); 3417e113d792SMark Brown } else { 3418e113d792SMark Brown ret = -EINVAL; 3419e113d792SMark Brown } 3420e843fc46SMark Brown } 3421e8eef82bSMark Brown } else { 3422e8eef82bSMark Brown ret = -EINVAL; 3423e8eef82bSMark Brown } 3424e8eef82bSMark Brown 342531dfe686SMatthias Kaehlcke if (ret) 342631dfe686SMatthias Kaehlcke goto out; 3427eba41a5eSAxel Lin 342873e705bfSMatthias Kaehlcke if (ops->set_voltage_time_sel) { 342973e705bfSMatthias Kaehlcke /* 343073e705bfSMatthias Kaehlcke * Call set_voltage_time_sel if successfully obtained 343173e705bfSMatthias Kaehlcke * old_selector 343273e705bfSMatthias Kaehlcke */ 343373e705bfSMatthias Kaehlcke if (old_selector >= 0 && old_selector != selector) 343473e705bfSMatthias Kaehlcke delay = ops->set_voltage_time_sel(rdev, old_selector, 343573e705bfSMatthias Kaehlcke selector); 343673e705bfSMatthias Kaehlcke } else { 343773e705bfSMatthias Kaehlcke if (old_uV != best_val) { 343873e705bfSMatthias Kaehlcke if (ops->set_voltage_time) 343973e705bfSMatthias Kaehlcke delay = ops->set_voltage_time(rdev, old_uV, 344073e705bfSMatthias Kaehlcke best_val); 344173e705bfSMatthias Kaehlcke else 344273e705bfSMatthias Kaehlcke delay = _regulator_set_voltage_time(rdev, 344373e705bfSMatthias Kaehlcke old_uV, 344473e705bfSMatthias Kaehlcke best_val); 344573e705bfSMatthias Kaehlcke } 344673e705bfSMatthias Kaehlcke } 344773e705bfSMatthias Kaehlcke 3448eba41a5eSAxel Lin if (delay < 0) { 344961aab5adSMichał Mirosław rdev_warn(rdev, "failed to get delay: %pe\n", ERR_PTR(delay)); 3450eba41a5eSAxel Lin delay = 0; 3451e8eef82bSMark Brown } 345275790251SMark Brown 345377af1b26SLinus Walleij /* Insert any necessary delays */ 345477af1b26SLinus Walleij if (delay >= 1000) { 345577af1b26SLinus Walleij mdelay(delay / 1000); 345677af1b26SLinus Walleij udelay(delay % 1000); 345777af1b26SLinus Walleij } else if (delay) { 345877af1b26SLinus Walleij udelay(delay); 345977af1b26SLinus Walleij } 346077af1b26SLinus Walleij 346131dfe686SMatthias Kaehlcke if (best_val >= 0) { 34622f6c797fSAxel Lin unsigned long data = best_val; 34632f6c797fSAxel Lin 3464ded06a52SMark Brown _notifier_call_chain(rdev, REGULATOR_EVENT_VOLTAGE_CHANGE, 34652f6c797fSAxel Lin (void *)data); 34662f6c797fSAxel Lin } 3467ded06a52SMark Brown 346831dfe686SMatthias Kaehlcke out: 3469eba41a5eSAxel Lin trace_regulator_set_voltage_complete(rdev_get_name(rdev), best_val); 347075790251SMark Brown 347175790251SMark Brown return ret; 347275790251SMark Brown } 347375790251SMark Brown 3474f7efad10SChunyan Zhang static int _regulator_do_set_suspend_voltage(struct regulator_dev *rdev, 3475f7efad10SChunyan Zhang int min_uV, int max_uV, suspend_state_t state) 3476f7efad10SChunyan Zhang { 3477f7efad10SChunyan Zhang struct regulator_state *rstate; 3478f7efad10SChunyan Zhang int uV, sel; 3479f7efad10SChunyan Zhang 3480f7efad10SChunyan Zhang rstate = regulator_get_suspend_state(rdev, state); 3481f7efad10SChunyan Zhang if (rstate == NULL) 3482f7efad10SChunyan Zhang return -EINVAL; 3483f7efad10SChunyan Zhang 3484f7efad10SChunyan Zhang if (min_uV < rstate->min_uV) 3485f7efad10SChunyan Zhang min_uV = rstate->min_uV; 3486f7efad10SChunyan Zhang if (max_uV > rstate->max_uV) 3487f7efad10SChunyan Zhang max_uV = rstate->max_uV; 3488f7efad10SChunyan Zhang 3489f7efad10SChunyan Zhang sel = regulator_map_voltage(rdev, min_uV, max_uV); 3490f7efad10SChunyan Zhang if (sel < 0) 3491f7efad10SChunyan Zhang return sel; 3492f7efad10SChunyan Zhang 3493f7efad10SChunyan Zhang uV = rdev->desc->ops->list_voltage(rdev, sel); 3494f7efad10SChunyan Zhang if (uV >= min_uV && uV <= max_uV) 3495f7efad10SChunyan Zhang rstate->uV = uV; 3496f7efad10SChunyan Zhang 3497f7efad10SChunyan Zhang return 0; 3498f7efad10SChunyan Zhang } 3499f7efad10SChunyan Zhang 3500a9f226bcSSascha Hauer static int regulator_set_voltage_unlocked(struct regulator *regulator, 3501c360a6dfSChunyan Zhang int min_uV, int max_uV, 3502c360a6dfSChunyan Zhang suspend_state_t state) 3503414c70cbSLiam Girdwood { 3504414c70cbSLiam Girdwood struct regulator_dev *rdev = regulator->rdev; 3505c360a6dfSChunyan Zhang struct regulator_voltage *voltage = ®ulator->voltage[state]; 350695a3c23aSMark Brown int ret = 0; 350792d7a558SPaolo Pisati int old_min_uV, old_max_uV; 3508c00dc359SBjorn Andersson int current_uV; 3509414c70cbSLiam Girdwood 351095a3c23aSMark Brown /* If we're setting the same range as last time the change 351195a3c23aSMark Brown * should be a noop (some cpufreq implementations use the same 351295a3c23aSMark Brown * voltage for multiple frequencies, for example). 351395a3c23aSMark Brown */ 3514c360a6dfSChunyan Zhang if (voltage->min_uV == min_uV && voltage->max_uV == max_uV) 351595a3c23aSMark Brown goto out; 351695a3c23aSMark Brown 3517c00dc359SBjorn Andersson /* If we're trying to set a range that overlaps the current voltage, 3518d3fb9800SViresh Kumar * return successfully even though the regulator does not support 3519c00dc359SBjorn Andersson * changing the voltage. 3520c00dc359SBjorn Andersson */ 35218a34e979SWEN Pingbo if (!regulator_ops_is_valid(rdev, REGULATOR_CHANGE_VOLTAGE)) { 3522d22b85a1SDmitry Osipenko current_uV = regulator_get_voltage_rdev(rdev); 3523c00dc359SBjorn Andersson if (min_uV <= current_uV && current_uV <= max_uV) { 3524c360a6dfSChunyan Zhang voltage->min_uV = min_uV; 3525c360a6dfSChunyan Zhang voltage->max_uV = max_uV; 3526c00dc359SBjorn Andersson goto out; 3527c00dc359SBjorn Andersson } 3528c00dc359SBjorn Andersson } 3529c00dc359SBjorn Andersson 3530414c70cbSLiam Girdwood /* sanity check */ 3531e8eef82bSMark Brown if (!rdev->desc->ops->set_voltage && 3532e8eef82bSMark Brown !rdev->desc->ops->set_voltage_sel) { 3533414c70cbSLiam Girdwood ret = -EINVAL; 3534414c70cbSLiam Girdwood goto out; 3535414c70cbSLiam Girdwood } 3536414c70cbSLiam Girdwood 3537414c70cbSLiam Girdwood /* constraints check */ 3538414c70cbSLiam Girdwood ret = regulator_check_voltage(rdev, &min_uV, &max_uV); 3539414c70cbSLiam Girdwood if (ret < 0) 3540414c70cbSLiam Girdwood goto out; 354192d7a558SPaolo Pisati 354292d7a558SPaolo Pisati /* restore original values in case of error */ 3543c360a6dfSChunyan Zhang old_min_uV = voltage->min_uV; 3544c360a6dfSChunyan Zhang old_max_uV = voltage->max_uV; 3545c360a6dfSChunyan Zhang voltage->min_uV = min_uV; 3546c360a6dfSChunyan Zhang voltage->max_uV = max_uV; 35473a93f2a9SMark Brown 35489243a195SMaciej Purski /* for not coupled regulators this will just set the voltage */ 35499243a195SMaciej Purski ret = regulator_balance_voltage(rdev, state); 355070b46491SSteve Twiss if (ret < 0) { 35519243a195SMaciej Purski voltage->min_uV = old_min_uV; 35529243a195SMaciej Purski voltage->max_uV = old_max_uV; 355370b46491SSteve Twiss } 35549243a195SMaciej Purski 355570b46491SSteve Twiss out: 35569243a195SMaciej Purski return ret; 35579243a195SMaciej Purski } 35589243a195SMaciej Purski 3559d22b85a1SDmitry Osipenko int regulator_set_voltage_rdev(struct regulator_dev *rdev, int min_uV, 35609243a195SMaciej Purski int max_uV, suspend_state_t state) 35619243a195SMaciej Purski { 35629243a195SMaciej Purski int best_supply_uV = 0; 35639243a195SMaciej Purski int supply_change_uV = 0; 35649243a195SMaciej Purski int ret; 35659243a195SMaciej Purski 356643fc99f2SMark Brown if (rdev->supply && 356743fc99f2SMark Brown regulator_ops_is_valid(rdev->supply->rdev, 356843fc99f2SMark Brown REGULATOR_CHANGE_VOLTAGE) && 35692c2874b1STirupathi Reddy (rdev->desc->min_dropout_uV || !(rdev->desc->ops->get_voltage || 35702c2874b1STirupathi Reddy rdev->desc->ops->get_voltage_sel))) { 3571fc42112cSSascha Hauer int current_supply_uV; 3572fc42112cSSascha Hauer int selector; 3573fc42112cSSascha Hauer 3574fc42112cSSascha Hauer selector = regulator_map_voltage(rdev, min_uV, max_uV); 3575fc42112cSSascha Hauer if (selector < 0) { 3576fc42112cSSascha Hauer ret = selector; 35779243a195SMaciej Purski goto out; 3578fc42112cSSascha Hauer } 3579fc42112cSSascha Hauer 358000cb9f4fSMark Brown best_supply_uV = _regulator_list_voltage(rdev, selector, 0); 3581fc42112cSSascha Hauer if (best_supply_uV < 0) { 3582fc42112cSSascha Hauer ret = best_supply_uV; 35839243a195SMaciej Purski goto out; 3584fc42112cSSascha Hauer } 3585fc42112cSSascha Hauer 3586fc42112cSSascha Hauer best_supply_uV += rdev->desc->min_dropout_uV; 3587fc42112cSSascha Hauer 3588d22b85a1SDmitry Osipenko current_supply_uV = regulator_get_voltage_rdev(rdev->supply->rdev); 3589fc42112cSSascha Hauer if (current_supply_uV < 0) { 3590fc42112cSSascha Hauer ret = current_supply_uV; 35919243a195SMaciej Purski goto out; 3592fc42112cSSascha Hauer } 3593fc42112cSSascha Hauer 3594fc42112cSSascha Hauer supply_change_uV = best_supply_uV - current_supply_uV; 3595fc42112cSSascha Hauer } 3596fc42112cSSascha Hauer 3597fc42112cSSascha Hauer if (supply_change_uV > 0) { 3598fc42112cSSascha Hauer ret = regulator_set_voltage_unlocked(rdev->supply, 3599c360a6dfSChunyan Zhang best_supply_uV, INT_MAX, state); 3600fc42112cSSascha Hauer if (ret) { 360161aab5adSMichał Mirosław dev_err(&rdev->dev, "Failed to increase supply voltage: %pe\n", 360261aab5adSMichał Mirosław ERR_PTR(ret)); 36039243a195SMaciej Purski goto out; 3604fc42112cSSascha Hauer } 3605fc42112cSSascha Hauer } 3606fc42112cSSascha Hauer 3607f7efad10SChunyan Zhang if (state == PM_SUSPEND_ON) 360875790251SMark Brown ret = _regulator_do_set_voltage(rdev, min_uV, max_uV); 3609f7efad10SChunyan Zhang else 3610f7efad10SChunyan Zhang ret = _regulator_do_set_suspend_voltage(rdev, min_uV, 3611f7efad10SChunyan Zhang max_uV, state); 361292d7a558SPaolo Pisati if (ret < 0) 36139243a195SMaciej Purski goto out; 361402fa3ec0SMark Brown 3615fc42112cSSascha Hauer if (supply_change_uV < 0) { 3616fc42112cSSascha Hauer ret = regulator_set_voltage_unlocked(rdev->supply, 3617c360a6dfSChunyan Zhang best_supply_uV, INT_MAX, state); 3618fc42112cSSascha Hauer if (ret) 361961aab5adSMichał Mirosław dev_warn(&rdev->dev, "Failed to decrease supply voltage: %pe\n", 362061aab5adSMichał Mirosław ERR_PTR(ret)); 3621fc42112cSSascha Hauer /* No need to fail here */ 3622fc42112cSSascha Hauer ret = 0; 3623fc42112cSSascha Hauer } 3624fc42112cSSascha Hauer 3625414c70cbSLiam Girdwood out: 3626414c70cbSLiam Girdwood return ret; 362769686176SMaciej Purski } 36283d7610e8SEnric Balletbo i Serra EXPORT_SYMBOL_GPL(regulator_set_voltage_rdev); 362969686176SMaciej Purski 363085254bcfSDmitry Osipenko static int regulator_limit_voltage_step(struct regulator_dev *rdev, 363185254bcfSDmitry Osipenko int *current_uV, int *min_uV) 363285254bcfSDmitry Osipenko { 363385254bcfSDmitry Osipenko struct regulation_constraints *constraints = rdev->constraints; 363485254bcfSDmitry Osipenko 363585254bcfSDmitry Osipenko /* Limit voltage change only if necessary */ 363685254bcfSDmitry Osipenko if (!constraints->max_uV_step || !_regulator_is_enabled(rdev)) 363785254bcfSDmitry Osipenko return 1; 363885254bcfSDmitry Osipenko 363985254bcfSDmitry Osipenko if (*current_uV < 0) { 3640d22b85a1SDmitry Osipenko *current_uV = regulator_get_voltage_rdev(rdev); 364185254bcfSDmitry Osipenko 364285254bcfSDmitry Osipenko if (*current_uV < 0) 364385254bcfSDmitry Osipenko return *current_uV; 364485254bcfSDmitry Osipenko } 364585254bcfSDmitry Osipenko 364685254bcfSDmitry Osipenko if (abs(*current_uV - *min_uV) <= constraints->max_uV_step) 364785254bcfSDmitry Osipenko return 1; 364885254bcfSDmitry Osipenko 364985254bcfSDmitry Osipenko /* Clamp target voltage within the given step */ 365085254bcfSDmitry Osipenko if (*current_uV < *min_uV) 365185254bcfSDmitry Osipenko *min_uV = min(*current_uV + constraints->max_uV_step, 365285254bcfSDmitry Osipenko *min_uV); 365385254bcfSDmitry Osipenko else 365485254bcfSDmitry Osipenko *min_uV = max(*current_uV - constraints->max_uV_step, 365585254bcfSDmitry Osipenko *min_uV); 365685254bcfSDmitry Osipenko 365785254bcfSDmitry Osipenko return 0; 365885254bcfSDmitry Osipenko } 365985254bcfSDmitry Osipenko 3660c054c6c7SMaciej Purski static int regulator_get_optimal_voltage(struct regulator_dev *rdev, 3661c054c6c7SMaciej Purski int *current_uV, 3662c054c6c7SMaciej Purski int *min_uV, int *max_uV, 3663c054c6c7SMaciej Purski suspend_state_t state, 3664c054c6c7SMaciej Purski int n_coupled) 3665c054c6c7SMaciej Purski { 3666c054c6c7SMaciej Purski struct coupling_desc *c_desc = &rdev->coupling_desc; 3667c054c6c7SMaciej Purski struct regulator_dev **c_rdevs = c_desc->coupled_rdevs; 3668c054c6c7SMaciej Purski struct regulation_constraints *constraints = rdev->constraints; 3669c054c6c7SMaciej Purski int desired_min_uV = 0, desired_max_uV = INT_MAX; 3670c054c6c7SMaciej Purski int max_current_uV = 0, min_current_uV = INT_MAX; 3671c054c6c7SMaciej Purski int highest_min_uV = 0, target_uV, possible_uV; 3672d8ca7d18SDmitry Osipenko int i, ret, max_spread; 3673c054c6c7SMaciej Purski bool done; 3674c054c6c7SMaciej Purski 3675c054c6c7SMaciej Purski *current_uV = -1; 3676c054c6c7SMaciej Purski 3677c054c6c7SMaciej Purski /* 3678c054c6c7SMaciej Purski * If there are no coupled regulators, simply set the voltage 3679c054c6c7SMaciej Purski * demanded by consumers. 3680c054c6c7SMaciej Purski */ 3681c054c6c7SMaciej Purski if (n_coupled == 1) { 3682c054c6c7SMaciej Purski /* 3683c054c6c7SMaciej Purski * If consumers don't provide any demands, set voltage 3684c054c6c7SMaciej Purski * to min_uV 3685c054c6c7SMaciej Purski */ 3686c054c6c7SMaciej Purski desired_min_uV = constraints->min_uV; 3687c054c6c7SMaciej Purski desired_max_uV = constraints->max_uV; 3688c054c6c7SMaciej Purski 3689c054c6c7SMaciej Purski ret = regulator_check_consumers(rdev, 3690c054c6c7SMaciej Purski &desired_min_uV, 3691c054c6c7SMaciej Purski &desired_max_uV, state); 3692c054c6c7SMaciej Purski if (ret < 0) 3693c054c6c7SMaciej Purski return ret; 3694c054c6c7SMaciej Purski 3695c054c6c7SMaciej Purski possible_uV = desired_min_uV; 3696c054c6c7SMaciej Purski done = true; 3697c054c6c7SMaciej Purski 3698c054c6c7SMaciej Purski goto finish; 3699c054c6c7SMaciej Purski } 3700c054c6c7SMaciej Purski 3701c054c6c7SMaciej Purski /* Find highest min desired voltage */ 3702c054c6c7SMaciej Purski for (i = 0; i < n_coupled; i++) { 3703c054c6c7SMaciej Purski int tmp_min = 0; 3704c054c6c7SMaciej Purski int tmp_max = INT_MAX; 3705c054c6c7SMaciej Purski 3706f8702f9eSDmitry Osipenko lockdep_assert_held_once(&c_rdevs[i]->mutex.base); 3707c054c6c7SMaciej Purski 3708c054c6c7SMaciej Purski ret = regulator_check_consumers(c_rdevs[i], 3709c054c6c7SMaciej Purski &tmp_min, 3710c054c6c7SMaciej Purski &tmp_max, state); 3711c054c6c7SMaciej Purski if (ret < 0) 3712c054c6c7SMaciej Purski return ret; 3713c054c6c7SMaciej Purski 3714c054c6c7SMaciej Purski ret = regulator_check_voltage(c_rdevs[i], &tmp_min, &tmp_max); 3715c054c6c7SMaciej Purski if (ret < 0) 3716c054c6c7SMaciej Purski return ret; 3717c054c6c7SMaciej Purski 3718c054c6c7SMaciej Purski highest_min_uV = max(highest_min_uV, tmp_min); 3719c054c6c7SMaciej Purski 3720c054c6c7SMaciej Purski if (i == 0) { 3721c054c6c7SMaciej Purski desired_min_uV = tmp_min; 3722c054c6c7SMaciej Purski desired_max_uV = tmp_max; 3723c054c6c7SMaciej Purski } 3724c054c6c7SMaciej Purski } 3725c054c6c7SMaciej Purski 3726d8ca7d18SDmitry Osipenko max_spread = constraints->max_spread[0]; 3727d8ca7d18SDmitry Osipenko 3728c054c6c7SMaciej Purski /* 3729c054c6c7SMaciej Purski * Let target_uV be equal to the desired one if possible. 3730c054c6c7SMaciej Purski * If not, set it to minimum voltage, allowed by other coupled 3731c054c6c7SMaciej Purski * regulators. 3732c054c6c7SMaciej Purski */ 3733c054c6c7SMaciej Purski target_uV = max(desired_min_uV, highest_min_uV - max_spread); 3734c054c6c7SMaciej Purski 3735c054c6c7SMaciej Purski /* 3736c054c6c7SMaciej Purski * Find min and max voltages, which currently aren't violating 3737c054c6c7SMaciej Purski * max_spread. 3738c054c6c7SMaciej Purski */ 3739c054c6c7SMaciej Purski for (i = 1; i < n_coupled; i++) { 3740c054c6c7SMaciej Purski int tmp_act; 3741c054c6c7SMaciej Purski 3742c054c6c7SMaciej Purski if (!_regulator_is_enabled(c_rdevs[i])) 3743c054c6c7SMaciej Purski continue; 3744c054c6c7SMaciej Purski 3745d22b85a1SDmitry Osipenko tmp_act = regulator_get_voltage_rdev(c_rdevs[i]); 3746c054c6c7SMaciej Purski if (tmp_act < 0) 3747c054c6c7SMaciej Purski return tmp_act; 3748c054c6c7SMaciej Purski 3749c054c6c7SMaciej Purski min_current_uV = min(tmp_act, min_current_uV); 3750c054c6c7SMaciej Purski max_current_uV = max(tmp_act, max_current_uV); 3751c054c6c7SMaciej Purski } 3752c054c6c7SMaciej Purski 3753c054c6c7SMaciej Purski /* There aren't any other regulators enabled */ 3754c054c6c7SMaciej Purski if (max_current_uV == 0) { 3755c054c6c7SMaciej Purski possible_uV = target_uV; 3756c054c6c7SMaciej Purski } else { 3757c054c6c7SMaciej Purski /* 3758c054c6c7SMaciej Purski * Correct target voltage, so as it currently isn't 3759c054c6c7SMaciej Purski * violating max_spread 3760c054c6c7SMaciej Purski */ 3761c054c6c7SMaciej Purski possible_uV = max(target_uV, max_current_uV - max_spread); 3762c054c6c7SMaciej Purski possible_uV = min(possible_uV, min_current_uV + max_spread); 3763c054c6c7SMaciej Purski } 3764c054c6c7SMaciej Purski 3765c054c6c7SMaciej Purski if (possible_uV > desired_max_uV) 3766c054c6c7SMaciej Purski return -EINVAL; 3767c054c6c7SMaciej Purski 3768c054c6c7SMaciej Purski done = (possible_uV == target_uV); 3769c054c6c7SMaciej Purski desired_min_uV = possible_uV; 3770c054c6c7SMaciej Purski 3771c054c6c7SMaciej Purski finish: 377285254bcfSDmitry Osipenko /* Apply max_uV_step constraint if necessary */ 377385254bcfSDmitry Osipenko if (state == PM_SUSPEND_ON) { 377485254bcfSDmitry Osipenko ret = regulator_limit_voltage_step(rdev, current_uV, 377585254bcfSDmitry Osipenko &desired_min_uV); 377685254bcfSDmitry Osipenko if (ret < 0) 377785254bcfSDmitry Osipenko return ret; 377885254bcfSDmitry Osipenko 377985254bcfSDmitry Osipenko if (ret == 0) 378085254bcfSDmitry Osipenko done = false; 378185254bcfSDmitry Osipenko } 378285254bcfSDmitry Osipenko 3783c054c6c7SMaciej Purski /* Set current_uV if wasn't done earlier in the code and if necessary */ 3784c054c6c7SMaciej Purski if (n_coupled > 1 && *current_uV == -1) { 3785c054c6c7SMaciej Purski 3786c054c6c7SMaciej Purski if (_regulator_is_enabled(rdev)) { 3787d22b85a1SDmitry Osipenko ret = regulator_get_voltage_rdev(rdev); 3788c054c6c7SMaciej Purski if (ret < 0) 3789c054c6c7SMaciej Purski return ret; 3790c054c6c7SMaciej Purski 3791c054c6c7SMaciej Purski *current_uV = ret; 3792c054c6c7SMaciej Purski } else { 3793c054c6c7SMaciej Purski *current_uV = desired_min_uV; 3794c054c6c7SMaciej Purski } 3795c054c6c7SMaciej Purski } 3796c054c6c7SMaciej Purski 3797c054c6c7SMaciej Purski *min_uV = desired_min_uV; 3798c054c6c7SMaciej Purski *max_uV = desired_max_uV; 3799c054c6c7SMaciej Purski 3800c054c6c7SMaciej Purski return done; 3801c054c6c7SMaciej Purski } 3802c054c6c7SMaciej Purski 3803752db83aSMarek Szyprowski int regulator_do_balance_voltage(struct regulator_dev *rdev, 3804752db83aSMarek Szyprowski suspend_state_t state, bool skip_coupled) 3805c054c6c7SMaciej Purski { 3806c054c6c7SMaciej Purski struct regulator_dev **c_rdevs; 3807c054c6c7SMaciej Purski struct regulator_dev *best_rdev; 3808c054c6c7SMaciej Purski struct coupling_desc *c_desc = &rdev->coupling_desc; 3809c054c6c7SMaciej Purski int i, ret, n_coupled, best_min_uV, best_max_uV, best_c_rdev; 3810c054c6c7SMaciej Purski unsigned int delta, best_delta; 3811d8ca7d18SDmitry Osipenko unsigned long c_rdev_done = 0; 3812d8ca7d18SDmitry Osipenko bool best_c_rdev_done; 3813c054c6c7SMaciej Purski 3814c054c6c7SMaciej Purski c_rdevs = c_desc->coupled_rdevs; 3815752db83aSMarek Szyprowski n_coupled = skip_coupled ? 1 : c_desc->n_coupled; 3816c054c6c7SMaciej Purski 3817c054c6c7SMaciej Purski /* 3818c054c6c7SMaciej Purski * Find the best possible voltage change on each loop. Leave the loop 3819c054c6c7SMaciej Purski * if there isn't any possible change. 3820c054c6c7SMaciej Purski */ 3821c054c6c7SMaciej Purski do { 3822c054c6c7SMaciej Purski best_c_rdev_done = false; 3823c054c6c7SMaciej Purski best_delta = 0; 3824c054c6c7SMaciej Purski best_min_uV = 0; 3825c054c6c7SMaciej Purski best_max_uV = 0; 3826c054c6c7SMaciej Purski best_c_rdev = 0; 3827c054c6c7SMaciej Purski best_rdev = NULL; 3828c054c6c7SMaciej Purski 3829c054c6c7SMaciej Purski /* 3830c054c6c7SMaciej Purski * Find highest difference between optimal voltage 3831c054c6c7SMaciej Purski * and current voltage. 3832c054c6c7SMaciej Purski */ 3833c054c6c7SMaciej Purski for (i = 0; i < n_coupled; i++) { 3834c054c6c7SMaciej Purski /* 3835c054c6c7SMaciej Purski * optimal_uV is the best voltage that can be set for 3836c054c6c7SMaciej Purski * i-th regulator at the moment without violating 3837c054c6c7SMaciej Purski * max_spread constraint in order to balance 3838c054c6c7SMaciej Purski * the coupled voltages. 3839c054c6c7SMaciej Purski */ 3840c054c6c7SMaciej Purski int optimal_uV = 0, optimal_max_uV = 0, current_uV = 0; 3841c054c6c7SMaciej Purski 3842d8ca7d18SDmitry Osipenko if (test_bit(i, &c_rdev_done)) 3843c054c6c7SMaciej Purski continue; 3844c054c6c7SMaciej Purski 3845c054c6c7SMaciej Purski ret = regulator_get_optimal_voltage(c_rdevs[i], 3846c054c6c7SMaciej Purski ¤t_uV, 3847c054c6c7SMaciej Purski &optimal_uV, 3848c054c6c7SMaciej Purski &optimal_max_uV, 3849c054c6c7SMaciej Purski state, n_coupled); 3850c054c6c7SMaciej Purski if (ret < 0) 3851c054c6c7SMaciej Purski goto out; 3852c054c6c7SMaciej Purski 3853c054c6c7SMaciej Purski delta = abs(optimal_uV - current_uV); 3854c054c6c7SMaciej Purski 3855c054c6c7SMaciej Purski if (delta && best_delta <= delta) { 3856c054c6c7SMaciej Purski best_c_rdev_done = ret; 3857c054c6c7SMaciej Purski best_delta = delta; 3858c054c6c7SMaciej Purski best_rdev = c_rdevs[i]; 3859c054c6c7SMaciej Purski best_min_uV = optimal_uV; 3860c054c6c7SMaciej Purski best_max_uV = optimal_max_uV; 3861c054c6c7SMaciej Purski best_c_rdev = i; 3862c054c6c7SMaciej Purski } 3863c054c6c7SMaciej Purski } 3864c054c6c7SMaciej Purski 3865c054c6c7SMaciej Purski /* Nothing to change, return successfully */ 3866c054c6c7SMaciej Purski if (!best_rdev) { 3867c054c6c7SMaciej Purski ret = 0; 3868c054c6c7SMaciej Purski goto out; 3869c054c6c7SMaciej Purski } 38709243a195SMaciej Purski 3871c054c6c7SMaciej Purski ret = regulator_set_voltage_rdev(best_rdev, best_min_uV, 3872c054c6c7SMaciej Purski best_max_uV, state); 38739243a195SMaciej Purski 3874c054c6c7SMaciej Purski if (ret < 0) 3875c054c6c7SMaciej Purski goto out; 3876c054c6c7SMaciej Purski 3877d8ca7d18SDmitry Osipenko if (best_c_rdev_done) 3878d8ca7d18SDmitry Osipenko set_bit(best_c_rdev, &c_rdev_done); 3879c054c6c7SMaciej Purski 3880c054c6c7SMaciej Purski } while (n_coupled > 1); 3881c054c6c7SMaciej Purski 3882c054c6c7SMaciej Purski out: 388369686176SMaciej Purski return ret; 388469686176SMaciej Purski } 388569686176SMaciej Purski 3886752db83aSMarek Szyprowski static int regulator_balance_voltage(struct regulator_dev *rdev, 3887752db83aSMarek Szyprowski suspend_state_t state) 3888752db83aSMarek Szyprowski { 3889752db83aSMarek Szyprowski struct coupling_desc *c_desc = &rdev->coupling_desc; 3890752db83aSMarek Szyprowski struct regulator_coupler *coupler = c_desc->coupler; 3891752db83aSMarek Szyprowski bool skip_coupled = false; 3892752db83aSMarek Szyprowski 3893752db83aSMarek Szyprowski /* 3894752db83aSMarek Szyprowski * If system is in a state other than PM_SUSPEND_ON, don't check 3895752db83aSMarek Szyprowski * other coupled regulators. 3896752db83aSMarek Szyprowski */ 3897752db83aSMarek Szyprowski if (state != PM_SUSPEND_ON) 3898752db83aSMarek Szyprowski skip_coupled = true; 3899752db83aSMarek Szyprowski 3900752db83aSMarek Szyprowski if (c_desc->n_resolved < c_desc->n_coupled) { 3901752db83aSMarek Szyprowski rdev_err(rdev, "Not all coupled regulators registered\n"); 3902752db83aSMarek Szyprowski return -EPERM; 3903752db83aSMarek Szyprowski } 3904752db83aSMarek Szyprowski 3905752db83aSMarek Szyprowski /* Invoke custom balancer for customized couplers */ 3906752db83aSMarek Szyprowski if (coupler && coupler->balance_voltage) 3907752db83aSMarek Szyprowski return coupler->balance_voltage(coupler, rdev, state); 3908752db83aSMarek Szyprowski 3909752db83aSMarek Szyprowski return regulator_do_balance_voltage(rdev, state, skip_coupled); 3910752db83aSMarek Szyprowski } 3911752db83aSMarek Szyprowski 3912a9f226bcSSascha Hauer /** 3913a9f226bcSSascha Hauer * regulator_set_voltage - set regulator output voltage 3914a9f226bcSSascha Hauer * @regulator: regulator source 3915a9f226bcSSascha Hauer * @min_uV: Minimum required voltage in uV 3916a9f226bcSSascha Hauer * @max_uV: Maximum acceptable voltage in uV 3917a9f226bcSSascha Hauer * 3918a9f226bcSSascha Hauer * Sets a voltage regulator to the desired output voltage. This can be set 3919a9f226bcSSascha Hauer * during any regulator state. IOW, regulator can be disabled or enabled. 3920a9f226bcSSascha Hauer * 3921a9f226bcSSascha Hauer * If the regulator is enabled then the voltage will change to the new value 3922a9f226bcSSascha Hauer * immediately otherwise if the regulator is disabled the regulator will 3923a9f226bcSSascha Hauer * output at the new voltage when enabled. 3924a9f226bcSSascha Hauer * 3925a9f226bcSSascha Hauer * NOTE: If the regulator is shared between several devices then the lowest 3926a9f226bcSSascha Hauer * request voltage that meets the system constraints will be used. 3927a9f226bcSSascha Hauer * Regulator system constraints must be set for this regulator before 3928a9f226bcSSascha Hauer * calling this function otherwise this call will fail. 3929a9f226bcSSascha Hauer */ 3930a9f226bcSSascha Hauer int regulator_set_voltage(struct regulator *regulator, int min_uV, int max_uV) 3931a9f226bcSSascha Hauer { 3932f8702f9eSDmitry Osipenko struct ww_acquire_ctx ww_ctx; 3933f8702f9eSDmitry Osipenko int ret; 3934a9f226bcSSascha Hauer 3935f8702f9eSDmitry Osipenko regulator_lock_dependent(regulator->rdev, &ww_ctx); 3936a9f226bcSSascha Hauer 3937c360a6dfSChunyan Zhang ret = regulator_set_voltage_unlocked(regulator, min_uV, max_uV, 3938c360a6dfSChunyan Zhang PM_SUSPEND_ON); 3939a9f226bcSSascha Hauer 3940f8702f9eSDmitry Osipenko regulator_unlock_dependent(regulator->rdev, &ww_ctx); 3941a9f226bcSSascha Hauer 394292d7a558SPaolo Pisati return ret; 3943414c70cbSLiam Girdwood } 3944414c70cbSLiam Girdwood EXPORT_SYMBOL_GPL(regulator_set_voltage); 3945414c70cbSLiam Girdwood 3946f7efad10SChunyan Zhang static inline int regulator_suspend_toggle(struct regulator_dev *rdev, 3947f7efad10SChunyan Zhang suspend_state_t state, bool en) 3948f7efad10SChunyan Zhang { 3949f7efad10SChunyan Zhang struct regulator_state *rstate; 3950f7efad10SChunyan Zhang 3951f7efad10SChunyan Zhang rstate = regulator_get_suspend_state(rdev, state); 3952f7efad10SChunyan Zhang if (rstate == NULL) 3953f7efad10SChunyan Zhang return -EINVAL; 3954f7efad10SChunyan Zhang 3955f7efad10SChunyan Zhang if (!rstate->changeable) 3956f7efad10SChunyan Zhang return -EPERM; 3957f7efad10SChunyan Zhang 39583edd79cfSMarek Szyprowski rstate->enabled = (en) ? ENABLE_IN_SUSPEND : DISABLE_IN_SUSPEND; 3959f7efad10SChunyan Zhang 3960f7efad10SChunyan Zhang return 0; 3961f7efad10SChunyan Zhang } 3962f7efad10SChunyan Zhang 3963f7efad10SChunyan Zhang int regulator_suspend_enable(struct regulator_dev *rdev, 3964f7efad10SChunyan Zhang suspend_state_t state) 3965f7efad10SChunyan Zhang { 3966f7efad10SChunyan Zhang return regulator_suspend_toggle(rdev, state, true); 3967f7efad10SChunyan Zhang } 3968f7efad10SChunyan Zhang EXPORT_SYMBOL_GPL(regulator_suspend_enable); 3969f7efad10SChunyan Zhang 3970f7efad10SChunyan Zhang int regulator_suspend_disable(struct regulator_dev *rdev, 3971f7efad10SChunyan Zhang suspend_state_t state) 3972f7efad10SChunyan Zhang { 3973f7efad10SChunyan Zhang struct regulator *regulator; 3974f7efad10SChunyan Zhang struct regulator_voltage *voltage; 3975f7efad10SChunyan Zhang 3976f7efad10SChunyan Zhang /* 3977f7efad10SChunyan Zhang * if any consumer wants this regulator device keeping on in 3978f7efad10SChunyan Zhang * suspend states, don't set it as disabled. 3979f7efad10SChunyan Zhang */ 3980f7efad10SChunyan Zhang list_for_each_entry(regulator, &rdev->consumer_list, list) { 3981f7efad10SChunyan Zhang voltage = ®ulator->voltage[state]; 3982f7efad10SChunyan Zhang if (voltage->min_uV || voltage->max_uV) 3983f7efad10SChunyan Zhang return 0; 3984f7efad10SChunyan Zhang } 3985f7efad10SChunyan Zhang 3986f7efad10SChunyan Zhang return regulator_suspend_toggle(rdev, state, false); 3987f7efad10SChunyan Zhang } 3988f7efad10SChunyan Zhang EXPORT_SYMBOL_GPL(regulator_suspend_disable); 3989f7efad10SChunyan Zhang 3990f7efad10SChunyan Zhang static int _regulator_set_suspend_voltage(struct regulator *regulator, 3991f7efad10SChunyan Zhang int min_uV, int max_uV, 3992f7efad10SChunyan Zhang suspend_state_t state) 3993f7efad10SChunyan Zhang { 3994f7efad10SChunyan Zhang struct regulator_dev *rdev = regulator->rdev; 3995f7efad10SChunyan Zhang struct regulator_state *rstate; 3996f7efad10SChunyan Zhang 3997f7efad10SChunyan Zhang rstate = regulator_get_suspend_state(rdev, state); 3998f7efad10SChunyan Zhang if (rstate == NULL) 3999f7efad10SChunyan Zhang return -EINVAL; 4000f7efad10SChunyan Zhang 4001f7efad10SChunyan Zhang if (rstate->min_uV == rstate->max_uV) { 4002f7efad10SChunyan Zhang rdev_err(rdev, "The suspend voltage can't be changed!\n"); 4003f7efad10SChunyan Zhang return -EPERM; 4004f7efad10SChunyan Zhang } 4005f7efad10SChunyan Zhang 4006f7efad10SChunyan Zhang return regulator_set_voltage_unlocked(regulator, min_uV, max_uV, state); 4007f7efad10SChunyan Zhang } 4008f7efad10SChunyan Zhang 4009f7efad10SChunyan Zhang int regulator_set_suspend_voltage(struct regulator *regulator, int min_uV, 4010f7efad10SChunyan Zhang int max_uV, suspend_state_t state) 4011f7efad10SChunyan Zhang { 4012f8702f9eSDmitry Osipenko struct ww_acquire_ctx ww_ctx; 4013f8702f9eSDmitry Osipenko int ret; 4014f7efad10SChunyan Zhang 4015f7efad10SChunyan Zhang /* PM_SUSPEND_ON is handled by regulator_set_voltage() */ 4016f7efad10SChunyan Zhang if (regulator_check_states(state) || state == PM_SUSPEND_ON) 4017f7efad10SChunyan Zhang return -EINVAL; 4018f7efad10SChunyan Zhang 4019f8702f9eSDmitry Osipenko regulator_lock_dependent(regulator->rdev, &ww_ctx); 4020f7efad10SChunyan Zhang 4021f7efad10SChunyan Zhang ret = _regulator_set_suspend_voltage(regulator, min_uV, 4022f7efad10SChunyan Zhang max_uV, state); 4023f7efad10SChunyan Zhang 4024f8702f9eSDmitry Osipenko regulator_unlock_dependent(regulator->rdev, &ww_ctx); 4025f7efad10SChunyan Zhang 4026f7efad10SChunyan Zhang return ret; 4027f7efad10SChunyan Zhang } 4028f7efad10SChunyan Zhang EXPORT_SYMBOL_GPL(regulator_set_suspend_voltage); 4029f7efad10SChunyan Zhang 4030606a2562SMark Brown /** 403188cd222bSLinus Walleij * regulator_set_voltage_time - get raise/fall time 403288cd222bSLinus Walleij * @regulator: regulator source 403388cd222bSLinus Walleij * @old_uV: starting voltage in microvolts 403488cd222bSLinus Walleij * @new_uV: target voltage in microvolts 403588cd222bSLinus Walleij * 403688cd222bSLinus Walleij * Provided with the starting and ending voltage, this function attempts to 403788cd222bSLinus Walleij * calculate the time in microseconds required to rise or fall to this new 403888cd222bSLinus Walleij * voltage. 403988cd222bSLinus Walleij */ 404088cd222bSLinus Walleij int regulator_set_voltage_time(struct regulator *regulator, 404188cd222bSLinus Walleij int old_uV, int new_uV) 404288cd222bSLinus Walleij { 404388cd222bSLinus Walleij struct regulator_dev *rdev = regulator->rdev; 4044272e2315SGuodong Xu const struct regulator_ops *ops = rdev->desc->ops; 404588cd222bSLinus Walleij int old_sel = -1; 404688cd222bSLinus Walleij int new_sel = -1; 404788cd222bSLinus Walleij int voltage; 404888cd222bSLinus Walleij int i; 404988cd222bSLinus Walleij 405073e705bfSMatthias Kaehlcke if (ops->set_voltage_time) 405173e705bfSMatthias Kaehlcke return ops->set_voltage_time(rdev, old_uV, new_uV); 405273e705bfSMatthias Kaehlcke else if (!ops->set_voltage_time_sel) 405373e705bfSMatthias Kaehlcke return _regulator_set_voltage_time(rdev, old_uV, new_uV); 405473e705bfSMatthias Kaehlcke 405588cd222bSLinus Walleij /* Currently requires operations to do this */ 405673e705bfSMatthias Kaehlcke if (!ops->list_voltage || !rdev->desc->n_voltages) 405788cd222bSLinus Walleij return -EINVAL; 405888cd222bSLinus Walleij 405988cd222bSLinus Walleij for (i = 0; i < rdev->desc->n_voltages; i++) { 406088cd222bSLinus Walleij /* We only look for exact voltage matches here */ 4061bdcd1177SClaudiu Beznea if (i < rdev->desc->linear_min_sel) 4062bdcd1177SClaudiu Beznea continue; 4063bdcd1177SClaudiu Beznea 4064ab97800eSClaudiu Beznea if (old_sel >= 0 && new_sel >= 0) 4065ab97800eSClaudiu Beznea break; 4066ab97800eSClaudiu Beznea 406788cd222bSLinus Walleij voltage = regulator_list_voltage(regulator, i); 406888cd222bSLinus Walleij if (voltage < 0) 406988cd222bSLinus Walleij return -EINVAL; 407088cd222bSLinus Walleij if (voltage == 0) 407188cd222bSLinus Walleij continue; 407288cd222bSLinus Walleij if (voltage == old_uV) 407388cd222bSLinus Walleij old_sel = i; 407488cd222bSLinus Walleij if (voltage == new_uV) 407588cd222bSLinus Walleij new_sel = i; 407688cd222bSLinus Walleij } 407788cd222bSLinus Walleij 407888cd222bSLinus Walleij if (old_sel < 0 || new_sel < 0) 407988cd222bSLinus Walleij return -EINVAL; 408088cd222bSLinus Walleij 408188cd222bSLinus Walleij return ops->set_voltage_time_sel(rdev, old_sel, new_sel); 408288cd222bSLinus Walleij } 408388cd222bSLinus Walleij EXPORT_SYMBOL_GPL(regulator_set_voltage_time); 408488cd222bSLinus Walleij 408588cd222bSLinus Walleij /** 408698a175b6SYadwinder Singh Brar * regulator_set_voltage_time_sel - get raise/fall time 4087296c6566SRandy Dunlap * @rdev: regulator source device 408898a175b6SYadwinder Singh Brar * @old_selector: selector for starting voltage 408998a175b6SYadwinder Singh Brar * @new_selector: selector for target voltage 409098a175b6SYadwinder Singh Brar * 409198a175b6SYadwinder Singh Brar * Provided with the starting and target voltage selectors, this function 409298a175b6SYadwinder Singh Brar * returns time in microseconds required to rise or fall to this new voltage 409398a175b6SYadwinder Singh Brar * 4094f11d08c3SAxel Lin * Drivers providing ramp_delay in regulation_constraints can use this as their 4095398715abSAxel Lin * set_voltage_time_sel() operation. 409698a175b6SYadwinder Singh Brar */ 409798a175b6SYadwinder Singh Brar int regulator_set_voltage_time_sel(struct regulator_dev *rdev, 409898a175b6SYadwinder Singh Brar unsigned int old_selector, 409998a175b6SYadwinder Singh Brar unsigned int new_selector) 410098a175b6SYadwinder Singh Brar { 4101f11d08c3SAxel Lin int old_volt, new_volt; 4102398715abSAxel Lin 4103f11d08c3SAxel Lin /* sanity check */ 4104f11d08c3SAxel Lin if (!rdev->desc->ops->list_voltage) 4105f11d08c3SAxel Lin return -EINVAL; 4106398715abSAxel Lin 4107f11d08c3SAxel Lin old_volt = rdev->desc->ops->list_voltage(rdev, old_selector); 4108f11d08c3SAxel Lin new_volt = rdev->desc->ops->list_voltage(rdev, new_selector); 4109f11d08c3SAxel Lin 411073e705bfSMatthias Kaehlcke if (rdev->desc->ops->set_voltage_time) 411173e705bfSMatthias Kaehlcke return rdev->desc->ops->set_voltage_time(rdev, old_volt, 411273e705bfSMatthias Kaehlcke new_volt); 411373e705bfSMatthias Kaehlcke else 411473e705bfSMatthias Kaehlcke return _regulator_set_voltage_time(rdev, old_volt, new_volt); 411598a175b6SYadwinder Singh Brar } 4116b19dbf71SMark Brown EXPORT_SYMBOL_GPL(regulator_set_voltage_time_sel); 411798a175b6SYadwinder Singh Brar 411898a175b6SYadwinder Singh Brar /** 4119606a2562SMark Brown * regulator_sync_voltage - re-apply last regulator output voltage 4120606a2562SMark Brown * @regulator: regulator source 4121606a2562SMark Brown * 4122606a2562SMark Brown * Re-apply the last configured voltage. This is intended to be used 4123606a2562SMark Brown * where some external control source the consumer is cooperating with 4124606a2562SMark Brown * has caused the configured voltage to change. 4125606a2562SMark Brown */ 4126606a2562SMark Brown int regulator_sync_voltage(struct regulator *regulator) 4127606a2562SMark Brown { 4128606a2562SMark Brown struct regulator_dev *rdev = regulator->rdev; 4129c360a6dfSChunyan Zhang struct regulator_voltage *voltage = ®ulator->voltage[PM_SUSPEND_ON]; 4130606a2562SMark Brown int ret, min_uV, max_uV; 4131606a2562SMark Brown 413266cf9a7eSMaciej Purski regulator_lock(rdev); 4133606a2562SMark Brown 4134606a2562SMark Brown if (!rdev->desc->ops->set_voltage && 4135606a2562SMark Brown !rdev->desc->ops->set_voltage_sel) { 4136606a2562SMark Brown ret = -EINVAL; 4137606a2562SMark Brown goto out; 4138606a2562SMark Brown } 4139606a2562SMark Brown 4140606a2562SMark Brown /* This is only going to work if we've had a voltage configured. */ 4141c360a6dfSChunyan Zhang if (!voltage->min_uV && !voltage->max_uV) { 4142606a2562SMark Brown ret = -EINVAL; 4143606a2562SMark Brown goto out; 4144606a2562SMark Brown } 4145606a2562SMark Brown 4146c360a6dfSChunyan Zhang min_uV = voltage->min_uV; 4147c360a6dfSChunyan Zhang max_uV = voltage->max_uV; 4148606a2562SMark Brown 4149606a2562SMark Brown /* This should be a paranoia check... */ 4150606a2562SMark Brown ret = regulator_check_voltage(rdev, &min_uV, &max_uV); 4151606a2562SMark Brown if (ret < 0) 4152606a2562SMark Brown goto out; 4153606a2562SMark Brown 4154c360a6dfSChunyan Zhang ret = regulator_check_consumers(rdev, &min_uV, &max_uV, 0); 4155606a2562SMark Brown if (ret < 0) 4156606a2562SMark Brown goto out; 4157606a2562SMark Brown 415824be0c71SDmitry Osipenko /* balance only, if regulator is coupled */ 415924be0c71SDmitry Osipenko if (rdev->coupling_desc.n_coupled > 1) 416024be0c71SDmitry Osipenko ret = regulator_balance_voltage(rdev, PM_SUSPEND_ON); 416124be0c71SDmitry Osipenko else 4162606a2562SMark Brown ret = _regulator_do_set_voltage(rdev, min_uV, max_uV); 4163606a2562SMark Brown 4164606a2562SMark Brown out: 416566cf9a7eSMaciej Purski regulator_unlock(rdev); 4166606a2562SMark Brown return ret; 4167606a2562SMark Brown } 4168606a2562SMark Brown EXPORT_SYMBOL_GPL(regulator_sync_voltage); 4169606a2562SMark Brown 4170d22b85a1SDmitry Osipenko int regulator_get_voltage_rdev(struct regulator_dev *rdev) 4171414c70cbSLiam Girdwood { 4172bf5892a8SMark Brown int sel, ret; 4173fef95019SMark Brown bool bypassed; 4174fef95019SMark Brown 4175fef95019SMark Brown if (rdev->desc->ops->get_bypass) { 4176fef95019SMark Brown ret = rdev->desc->ops->get_bypass(rdev, &bypassed); 4177fef95019SMark Brown if (ret < 0) 4178fef95019SMark Brown return ret; 4179fef95019SMark Brown if (bypassed) { 4180fef95019SMark Brown /* if bypassed the regulator must have a supply */ 418145389c47SJon Hunter if (!rdev->supply) { 418245389c47SJon Hunter rdev_err(rdev, 418345389c47SJon Hunter "bypassed regulator has no supply!\n"); 418445389c47SJon Hunter return -EPROBE_DEFER; 418545389c47SJon Hunter } 4186fef95019SMark Brown 4187d22b85a1SDmitry Osipenko return regulator_get_voltage_rdev(rdev->supply->rdev); 4188fef95019SMark Brown } 4189fef95019SMark Brown } 4190476c2d83SMark Brown 4191476c2d83SMark Brown if (rdev->desc->ops->get_voltage_sel) { 4192476c2d83SMark Brown sel = rdev->desc->ops->get_voltage_sel(rdev); 4193476c2d83SMark Brown if (sel < 0) 4194476c2d83SMark Brown return sel; 4195bf5892a8SMark Brown ret = rdev->desc->ops->list_voltage(rdev, sel); 4196cb220d16SAxel Lin } else if (rdev->desc->ops->get_voltage) { 4197bf5892a8SMark Brown ret = rdev->desc->ops->get_voltage(rdev); 4198f7df20ecSMark Brown } else if (rdev->desc->ops->list_voltage) { 4199f7df20ecSMark Brown ret = rdev->desc->ops->list_voltage(rdev, 0); 42005a523605SLaxman Dewangan } else if (rdev->desc->fixed_uV && (rdev->desc->n_voltages == 1)) { 42015a523605SLaxman Dewangan ret = rdev->desc->fixed_uV; 4202e303996eSJavier Martinez Canillas } else if (rdev->supply) { 4203d22b85a1SDmitry Osipenko ret = regulator_get_voltage_rdev(rdev->supply->rdev); 4204cf1ad559SMichał Mirosław } else if (rdev->supply_name) { 4205cf1ad559SMichał Mirosław return -EPROBE_DEFER; 4206cb220d16SAxel Lin } else { 4207414c70cbSLiam Girdwood return -EINVAL; 4208cb220d16SAxel Lin } 4209bf5892a8SMark Brown 4210cb220d16SAxel Lin if (ret < 0) 4211cb220d16SAxel Lin return ret; 4212bf5892a8SMark Brown return ret - rdev->constraints->uV_offset; 4213414c70cbSLiam Girdwood } 42143d7610e8SEnric Balletbo i Serra EXPORT_SYMBOL_GPL(regulator_get_voltage_rdev); 4215414c70cbSLiam Girdwood 4216414c70cbSLiam Girdwood /** 4217414c70cbSLiam Girdwood * regulator_get_voltage - get regulator output voltage 4218414c70cbSLiam Girdwood * @regulator: regulator source 4219414c70cbSLiam Girdwood * 4220414c70cbSLiam Girdwood * This returns the current regulator voltage in uV. 4221414c70cbSLiam Girdwood * 4222414c70cbSLiam Girdwood * NOTE: If the regulator is disabled it will return the voltage value. This 4223414c70cbSLiam Girdwood * function should not be used to determine regulator state. 4224414c70cbSLiam Girdwood */ 4225414c70cbSLiam Girdwood int regulator_get_voltage(struct regulator *regulator) 4226414c70cbSLiam Girdwood { 4227f8702f9eSDmitry Osipenko struct ww_acquire_ctx ww_ctx; 4228414c70cbSLiam Girdwood int ret; 4229414c70cbSLiam Girdwood 4230f8702f9eSDmitry Osipenko regulator_lock_dependent(regulator->rdev, &ww_ctx); 4231d22b85a1SDmitry Osipenko ret = regulator_get_voltage_rdev(regulator->rdev); 4232f8702f9eSDmitry Osipenko regulator_unlock_dependent(regulator->rdev, &ww_ctx); 4233414c70cbSLiam Girdwood 4234414c70cbSLiam Girdwood return ret; 4235414c70cbSLiam Girdwood } 4236414c70cbSLiam Girdwood EXPORT_SYMBOL_GPL(regulator_get_voltage); 4237414c70cbSLiam Girdwood 4238414c70cbSLiam Girdwood /** 4239414c70cbSLiam Girdwood * regulator_set_current_limit - set regulator output current limit 4240414c70cbSLiam Girdwood * @regulator: regulator source 4241ce0d10f8SCharles Keepax * @min_uA: Minimum supported current in uA 4242414c70cbSLiam Girdwood * @max_uA: Maximum supported current in uA 4243414c70cbSLiam Girdwood * 4244414c70cbSLiam Girdwood * Sets current sink to the desired output current. This can be set during 4245414c70cbSLiam Girdwood * any regulator state. IOW, regulator can be disabled or enabled. 4246414c70cbSLiam Girdwood * 4247414c70cbSLiam Girdwood * If the regulator is enabled then the current will change to the new value 4248414c70cbSLiam Girdwood * immediately otherwise if the regulator is disabled the regulator will 4249414c70cbSLiam Girdwood * output at the new current when enabled. 4250414c70cbSLiam Girdwood * 4251414c70cbSLiam Girdwood * NOTE: Regulator system constraints must be set for this regulator before 4252414c70cbSLiam Girdwood * calling this function otherwise this call will fail. 4253414c70cbSLiam Girdwood */ 4254414c70cbSLiam Girdwood int regulator_set_current_limit(struct regulator *regulator, 4255414c70cbSLiam Girdwood int min_uA, int max_uA) 4256414c70cbSLiam Girdwood { 4257414c70cbSLiam Girdwood struct regulator_dev *rdev = regulator->rdev; 4258414c70cbSLiam Girdwood int ret; 4259414c70cbSLiam Girdwood 426066cf9a7eSMaciej Purski regulator_lock(rdev); 4261414c70cbSLiam Girdwood 4262414c70cbSLiam Girdwood /* sanity check */ 4263414c70cbSLiam Girdwood if (!rdev->desc->ops->set_current_limit) { 4264414c70cbSLiam Girdwood ret = -EINVAL; 4265414c70cbSLiam Girdwood goto out; 4266414c70cbSLiam Girdwood } 4267414c70cbSLiam Girdwood 4268414c70cbSLiam Girdwood /* constraints check */ 4269414c70cbSLiam Girdwood ret = regulator_check_current_limit(rdev, &min_uA, &max_uA); 4270414c70cbSLiam Girdwood if (ret < 0) 4271414c70cbSLiam Girdwood goto out; 4272414c70cbSLiam Girdwood 4273414c70cbSLiam Girdwood ret = rdev->desc->ops->set_current_limit(rdev, min_uA, max_uA); 4274414c70cbSLiam Girdwood out: 427566cf9a7eSMaciej Purski regulator_unlock(rdev); 4276414c70cbSLiam Girdwood return ret; 4277414c70cbSLiam Girdwood } 4278414c70cbSLiam Girdwood EXPORT_SYMBOL_GPL(regulator_set_current_limit); 4279414c70cbSLiam Girdwood 42807e4d9683SDouglas Anderson static int _regulator_get_current_limit_unlocked(struct regulator_dev *rdev) 42817e4d9683SDouglas Anderson { 42827e4d9683SDouglas Anderson /* sanity check */ 42837e4d9683SDouglas Anderson if (!rdev->desc->ops->get_current_limit) 42847e4d9683SDouglas Anderson return -EINVAL; 42857e4d9683SDouglas Anderson 42867e4d9683SDouglas Anderson return rdev->desc->ops->get_current_limit(rdev); 42877e4d9683SDouglas Anderson } 42887e4d9683SDouglas Anderson 4289414c70cbSLiam Girdwood static int _regulator_get_current_limit(struct regulator_dev *rdev) 4290414c70cbSLiam Girdwood { 4291414c70cbSLiam Girdwood int ret; 4292414c70cbSLiam Girdwood 429366cf9a7eSMaciej Purski regulator_lock(rdev); 42947e4d9683SDouglas Anderson ret = _regulator_get_current_limit_unlocked(rdev); 429566cf9a7eSMaciej Purski regulator_unlock(rdev); 42967e4d9683SDouglas Anderson 4297414c70cbSLiam Girdwood return ret; 4298414c70cbSLiam Girdwood } 4299414c70cbSLiam Girdwood 4300414c70cbSLiam Girdwood /** 4301414c70cbSLiam Girdwood * regulator_get_current_limit - get regulator output current 4302414c70cbSLiam Girdwood * @regulator: regulator source 4303414c70cbSLiam Girdwood * 4304414c70cbSLiam Girdwood * This returns the current supplied by the specified current sink in uA. 4305414c70cbSLiam Girdwood * 4306414c70cbSLiam Girdwood * NOTE: If the regulator is disabled it will return the current value. This 4307414c70cbSLiam Girdwood * function should not be used to determine regulator state. 4308414c70cbSLiam Girdwood */ 4309414c70cbSLiam Girdwood int regulator_get_current_limit(struct regulator *regulator) 4310414c70cbSLiam Girdwood { 4311414c70cbSLiam Girdwood return _regulator_get_current_limit(regulator->rdev); 4312414c70cbSLiam Girdwood } 4313414c70cbSLiam Girdwood EXPORT_SYMBOL_GPL(regulator_get_current_limit); 4314414c70cbSLiam Girdwood 4315414c70cbSLiam Girdwood /** 4316414c70cbSLiam Girdwood * regulator_set_mode - set regulator operating mode 4317414c70cbSLiam Girdwood * @regulator: regulator source 4318414c70cbSLiam Girdwood * @mode: operating mode - one of the REGULATOR_MODE constants 4319414c70cbSLiam Girdwood * 4320414c70cbSLiam Girdwood * Set regulator operating mode to increase regulator efficiency or improve 4321414c70cbSLiam Girdwood * regulation performance. 4322414c70cbSLiam Girdwood * 4323414c70cbSLiam Girdwood * NOTE: Regulator system constraints must be set for this regulator before 4324414c70cbSLiam Girdwood * calling this function otherwise this call will fail. 4325414c70cbSLiam Girdwood */ 4326414c70cbSLiam Girdwood int regulator_set_mode(struct regulator *regulator, unsigned int mode) 4327414c70cbSLiam Girdwood { 4328414c70cbSLiam Girdwood struct regulator_dev *rdev = regulator->rdev; 4329414c70cbSLiam Girdwood int ret; 4330500b4ac9SSundar R Iyer int regulator_curr_mode; 4331414c70cbSLiam Girdwood 433266cf9a7eSMaciej Purski regulator_lock(rdev); 4333414c70cbSLiam Girdwood 4334414c70cbSLiam Girdwood /* sanity check */ 4335414c70cbSLiam Girdwood if (!rdev->desc->ops->set_mode) { 4336414c70cbSLiam Girdwood ret = -EINVAL; 4337414c70cbSLiam Girdwood goto out; 4338414c70cbSLiam Girdwood } 4339414c70cbSLiam Girdwood 4340500b4ac9SSundar R Iyer /* return if the same mode is requested */ 4341500b4ac9SSundar R Iyer if (rdev->desc->ops->get_mode) { 4342500b4ac9SSundar R Iyer regulator_curr_mode = rdev->desc->ops->get_mode(rdev); 4343500b4ac9SSundar R Iyer if (regulator_curr_mode == mode) { 4344500b4ac9SSundar R Iyer ret = 0; 4345500b4ac9SSundar R Iyer goto out; 4346500b4ac9SSundar R Iyer } 4347500b4ac9SSundar R Iyer } 4348500b4ac9SSundar R Iyer 4349414c70cbSLiam Girdwood /* constraints check */ 435022c51b47SAxel Lin ret = regulator_mode_constrain(rdev, &mode); 4351414c70cbSLiam Girdwood if (ret < 0) 4352414c70cbSLiam Girdwood goto out; 4353414c70cbSLiam Girdwood 4354414c70cbSLiam Girdwood ret = rdev->desc->ops->set_mode(rdev, mode); 4355414c70cbSLiam Girdwood out: 435666cf9a7eSMaciej Purski regulator_unlock(rdev); 4357414c70cbSLiam Girdwood return ret; 4358414c70cbSLiam Girdwood } 4359414c70cbSLiam Girdwood EXPORT_SYMBOL_GPL(regulator_set_mode); 4360414c70cbSLiam Girdwood 43617e4d9683SDouglas Anderson static unsigned int _regulator_get_mode_unlocked(struct regulator_dev *rdev) 43627e4d9683SDouglas Anderson { 43637e4d9683SDouglas Anderson /* sanity check */ 43647e4d9683SDouglas Anderson if (!rdev->desc->ops->get_mode) 43657e4d9683SDouglas Anderson return -EINVAL; 43667e4d9683SDouglas Anderson 43677e4d9683SDouglas Anderson return rdev->desc->ops->get_mode(rdev); 43687e4d9683SDouglas Anderson } 43697e4d9683SDouglas Anderson 4370414c70cbSLiam Girdwood static unsigned int _regulator_get_mode(struct regulator_dev *rdev) 4371414c70cbSLiam Girdwood { 4372414c70cbSLiam Girdwood int ret; 4373414c70cbSLiam Girdwood 437466cf9a7eSMaciej Purski regulator_lock(rdev); 43757e4d9683SDouglas Anderson ret = _regulator_get_mode_unlocked(rdev); 437666cf9a7eSMaciej Purski regulator_unlock(rdev); 43777e4d9683SDouglas Anderson 4378414c70cbSLiam Girdwood return ret; 4379414c70cbSLiam Girdwood } 4380414c70cbSLiam Girdwood 4381414c70cbSLiam Girdwood /** 4382414c70cbSLiam Girdwood * regulator_get_mode - get regulator operating mode 4383414c70cbSLiam Girdwood * @regulator: regulator source 4384414c70cbSLiam Girdwood * 4385414c70cbSLiam Girdwood * Get the current regulator operating mode. 4386414c70cbSLiam Girdwood */ 4387414c70cbSLiam Girdwood unsigned int regulator_get_mode(struct regulator *regulator) 4388414c70cbSLiam Girdwood { 4389414c70cbSLiam Girdwood return _regulator_get_mode(regulator->rdev); 4390414c70cbSLiam Girdwood } 4391414c70cbSLiam Girdwood EXPORT_SYMBOL_GPL(regulator_get_mode); 4392414c70cbSLiam Girdwood 43931b5b4221SAxel Haslam static int _regulator_get_error_flags(struct regulator_dev *rdev, 43941b5b4221SAxel Haslam unsigned int *flags) 43951b5b4221SAxel Haslam { 43961b5b4221SAxel Haslam int ret; 43971b5b4221SAxel Haslam 439866cf9a7eSMaciej Purski regulator_lock(rdev); 43991b5b4221SAxel Haslam 44001b5b4221SAxel Haslam /* sanity check */ 44011b5b4221SAxel Haslam if (!rdev->desc->ops->get_error_flags) { 44021b5b4221SAxel Haslam ret = -EINVAL; 44031b5b4221SAxel Haslam goto out; 44041b5b4221SAxel Haslam } 44051b5b4221SAxel Haslam 44061b5b4221SAxel Haslam ret = rdev->desc->ops->get_error_flags(rdev, flags); 44071b5b4221SAxel Haslam out: 440866cf9a7eSMaciej Purski regulator_unlock(rdev); 44091b5b4221SAxel Haslam return ret; 44101b5b4221SAxel Haslam } 44111b5b4221SAxel Haslam 44121b5b4221SAxel Haslam /** 44131b5b4221SAxel Haslam * regulator_get_error_flags - get regulator error information 44141b5b4221SAxel Haslam * @regulator: regulator source 44151b5b4221SAxel Haslam * @flags: pointer to store error flags 44161b5b4221SAxel Haslam * 44171b5b4221SAxel Haslam * Get the current regulator error information. 44181b5b4221SAxel Haslam */ 44191b5b4221SAxel Haslam int regulator_get_error_flags(struct regulator *regulator, 44201b5b4221SAxel Haslam unsigned int *flags) 44211b5b4221SAxel Haslam { 44221b5b4221SAxel Haslam return _regulator_get_error_flags(regulator->rdev, flags); 44231b5b4221SAxel Haslam } 44241b5b4221SAxel Haslam EXPORT_SYMBOL_GPL(regulator_get_error_flags); 44251b5b4221SAxel Haslam 4426414c70cbSLiam Girdwood /** 4427e39ce48fSBjorn Andersson * regulator_set_load - set regulator load 4428414c70cbSLiam Girdwood * @regulator: regulator source 4429414c70cbSLiam Girdwood * @uA_load: load current 4430414c70cbSLiam Girdwood * 4431414c70cbSLiam Girdwood * Notifies the regulator core of a new device load. This is then used by 4432414c70cbSLiam Girdwood * DRMS (if enabled by constraints) to set the most efficient regulator 4433414c70cbSLiam Girdwood * operating mode for the new regulator loading. 4434414c70cbSLiam Girdwood * 4435414c70cbSLiam Girdwood * Consumer devices notify their supply regulator of the maximum power 4436414c70cbSLiam Girdwood * they will require (can be taken from device datasheet in the power 4437414c70cbSLiam Girdwood * consumption tables) when they change operational status and hence power 4438414c70cbSLiam Girdwood * state. Examples of operational state changes that can affect power 4439414c70cbSLiam Girdwood * consumption are :- 4440414c70cbSLiam Girdwood * 4441414c70cbSLiam Girdwood * o Device is opened / closed. 4442414c70cbSLiam Girdwood * o Device I/O is about to begin or has just finished. 4443414c70cbSLiam Girdwood * o Device is idling in between work. 4444414c70cbSLiam Girdwood * 4445414c70cbSLiam Girdwood * This information is also exported via sysfs to userspace. 4446414c70cbSLiam Girdwood * 4447414c70cbSLiam Girdwood * DRMS will sum the total requested load on the regulator and change 4448414c70cbSLiam Girdwood * to the most efficient operating mode if platform constraints allow. 4449414c70cbSLiam Girdwood * 44505451781dSDouglas Anderson * NOTE: when a regulator consumer requests to have a regulator 44515451781dSDouglas Anderson * disabled then any load that consumer requested no longer counts 44525451781dSDouglas Anderson * toward the total requested load. If the regulator is re-enabled 44535451781dSDouglas Anderson * then the previously requested load will start counting again. 44545451781dSDouglas Anderson * 44555451781dSDouglas Anderson * If a regulator is an always-on regulator then an individual consumer's 44565451781dSDouglas Anderson * load will still be removed if that consumer is fully disabled. 44575451781dSDouglas Anderson * 4458e39ce48fSBjorn Andersson * On error a negative errno is returned. 4459414c70cbSLiam Girdwood */ 4460e39ce48fSBjorn Andersson int regulator_set_load(struct regulator *regulator, int uA_load) 4461414c70cbSLiam Girdwood { 4462414c70cbSLiam Girdwood struct regulator_dev *rdev = regulator->rdev; 44635451781dSDouglas Anderson int old_uA_load; 44645451781dSDouglas Anderson int ret = 0; 4465d92d95b6SStephen Boyd 446666cf9a7eSMaciej Purski regulator_lock(rdev); 44675451781dSDouglas Anderson old_uA_load = regulator->uA_load; 4468414c70cbSLiam Girdwood regulator->uA_load = uA_load; 44695451781dSDouglas Anderson if (regulator->enable_count && old_uA_load != uA_load) { 44708460ef38SBjorn Andersson ret = drms_uA_update(rdev); 44715451781dSDouglas Anderson if (ret < 0) 44725451781dSDouglas Anderson regulator->uA_load = old_uA_load; 44735451781dSDouglas Anderson } 447466cf9a7eSMaciej Purski regulator_unlock(rdev); 44758460ef38SBjorn Andersson 4476414c70cbSLiam Girdwood return ret; 4477414c70cbSLiam Girdwood } 4478e39ce48fSBjorn Andersson EXPORT_SYMBOL_GPL(regulator_set_load); 4479414c70cbSLiam Girdwood 4480414c70cbSLiam Girdwood /** 4481f59c8f9fSMark Brown * regulator_allow_bypass - allow the regulator to go into bypass mode 4482f59c8f9fSMark Brown * 4483f59c8f9fSMark Brown * @regulator: Regulator to configure 44849345dfb8SNishanth Menon * @enable: enable or disable bypass mode 4485f59c8f9fSMark Brown * 4486f59c8f9fSMark Brown * Allow the regulator to go into bypass mode if all other consumers 4487f59c8f9fSMark Brown * for the regulator also enable bypass mode and the machine 4488f59c8f9fSMark Brown * constraints allow this. Bypass mode means that the regulator is 4489f59c8f9fSMark Brown * simply passing the input directly to the output with no regulation. 4490f59c8f9fSMark Brown */ 4491f59c8f9fSMark Brown int regulator_allow_bypass(struct regulator *regulator, bool enable) 4492f59c8f9fSMark Brown { 4493f59c8f9fSMark Brown struct regulator_dev *rdev = regulator->rdev; 449448325655SCharles Keepax const char *name = rdev_get_name(rdev); 4495f59c8f9fSMark Brown int ret = 0; 4496f59c8f9fSMark Brown 4497f59c8f9fSMark Brown if (!rdev->desc->ops->set_bypass) 4498f59c8f9fSMark Brown return 0; 4499f59c8f9fSMark Brown 45008a34e979SWEN Pingbo if (!regulator_ops_is_valid(rdev, REGULATOR_CHANGE_BYPASS)) 4501f59c8f9fSMark Brown return 0; 4502f59c8f9fSMark Brown 450366cf9a7eSMaciej Purski regulator_lock(rdev); 4504f59c8f9fSMark Brown 4505f59c8f9fSMark Brown if (enable && !regulator->bypass) { 4506f59c8f9fSMark Brown rdev->bypass_count++; 4507f59c8f9fSMark Brown 4508f59c8f9fSMark Brown if (rdev->bypass_count == rdev->open_count) { 450948325655SCharles Keepax trace_regulator_bypass_enable(name); 451048325655SCharles Keepax 4511f59c8f9fSMark Brown ret = rdev->desc->ops->set_bypass(rdev, enable); 4512f59c8f9fSMark Brown if (ret != 0) 4513f59c8f9fSMark Brown rdev->bypass_count--; 451448325655SCharles Keepax else 451548325655SCharles Keepax trace_regulator_bypass_enable_complete(name); 4516f59c8f9fSMark Brown } 4517f59c8f9fSMark Brown 4518f59c8f9fSMark Brown } else if (!enable && regulator->bypass) { 4519f59c8f9fSMark Brown rdev->bypass_count--; 4520f59c8f9fSMark Brown 4521f59c8f9fSMark Brown if (rdev->bypass_count != rdev->open_count) { 452248325655SCharles Keepax trace_regulator_bypass_disable(name); 452348325655SCharles Keepax 4524f59c8f9fSMark Brown ret = rdev->desc->ops->set_bypass(rdev, enable); 4525f59c8f9fSMark Brown if (ret != 0) 4526f59c8f9fSMark Brown rdev->bypass_count++; 452748325655SCharles Keepax else 452848325655SCharles Keepax trace_regulator_bypass_disable_complete(name); 4529f59c8f9fSMark Brown } 4530f59c8f9fSMark Brown } 4531f59c8f9fSMark Brown 4532f59c8f9fSMark Brown if (ret == 0) 4533f59c8f9fSMark Brown regulator->bypass = enable; 4534f59c8f9fSMark Brown 453566cf9a7eSMaciej Purski regulator_unlock(rdev); 4536f59c8f9fSMark Brown 4537f59c8f9fSMark Brown return ret; 4538f59c8f9fSMark Brown } 4539f59c8f9fSMark Brown EXPORT_SYMBOL_GPL(regulator_allow_bypass); 4540f59c8f9fSMark Brown 4541f59c8f9fSMark Brown /** 4542414c70cbSLiam Girdwood * regulator_register_notifier - register regulator event notifier 4543414c70cbSLiam Girdwood * @regulator: regulator source 454469279fb9SMark Brown * @nb: notifier block 4545414c70cbSLiam Girdwood * 4546414c70cbSLiam Girdwood * Register notifier block to receive regulator events. 4547414c70cbSLiam Girdwood */ 4548414c70cbSLiam Girdwood int regulator_register_notifier(struct regulator *regulator, 4549414c70cbSLiam Girdwood struct notifier_block *nb) 4550414c70cbSLiam Girdwood { 4551414c70cbSLiam Girdwood return blocking_notifier_chain_register(®ulator->rdev->notifier, 4552414c70cbSLiam Girdwood nb); 4553414c70cbSLiam Girdwood } 4554414c70cbSLiam Girdwood EXPORT_SYMBOL_GPL(regulator_register_notifier); 4555414c70cbSLiam Girdwood 4556414c70cbSLiam Girdwood /** 4557414c70cbSLiam Girdwood * regulator_unregister_notifier - unregister regulator event notifier 4558414c70cbSLiam Girdwood * @regulator: regulator source 455969279fb9SMark Brown * @nb: notifier block 4560414c70cbSLiam Girdwood * 4561414c70cbSLiam Girdwood * Unregister regulator event notifier block. 4562414c70cbSLiam Girdwood */ 4563414c70cbSLiam Girdwood int regulator_unregister_notifier(struct regulator *regulator, 4564414c70cbSLiam Girdwood struct notifier_block *nb) 4565414c70cbSLiam Girdwood { 4566414c70cbSLiam Girdwood return blocking_notifier_chain_unregister(®ulator->rdev->notifier, 4567414c70cbSLiam Girdwood nb); 4568414c70cbSLiam Girdwood } 4569414c70cbSLiam Girdwood EXPORT_SYMBOL_GPL(regulator_unregister_notifier); 4570414c70cbSLiam Girdwood 4571b136fb44SJonathan Cameron /* notify regulator consumers and downstream regulator consumers. 4572b136fb44SJonathan Cameron * Note mutex must be held by caller. 4573b136fb44SJonathan Cameron */ 45747179569aSHeiko Stübner static int _notifier_call_chain(struct regulator_dev *rdev, 4575414c70cbSLiam Girdwood unsigned long event, void *data) 4576414c70cbSLiam Girdwood { 4577414c70cbSLiam Girdwood /* call rdev chain first */ 45787179569aSHeiko Stübner return blocking_notifier_call_chain(&rdev->notifier, event, data); 4579414c70cbSLiam Girdwood } 4580414c70cbSLiam Girdwood 4581414c70cbSLiam Girdwood /** 4582414c70cbSLiam Girdwood * regulator_bulk_get - get multiple regulator consumers 4583414c70cbSLiam Girdwood * 4584414c70cbSLiam Girdwood * @dev: Device to supply 4585414c70cbSLiam Girdwood * @num_consumers: Number of consumers to register 4586414c70cbSLiam Girdwood * @consumers: Configuration of consumers; clients are stored here. 4587414c70cbSLiam Girdwood * 4588414c70cbSLiam Girdwood * @return 0 on success, an errno on failure. 4589414c70cbSLiam Girdwood * 4590414c70cbSLiam Girdwood * This helper function allows drivers to get several regulator 4591414c70cbSLiam Girdwood * consumers in one operation. If any of the regulators cannot be 4592414c70cbSLiam Girdwood * acquired then any regulators that were allocated will be freed 4593414c70cbSLiam Girdwood * before returning to the caller. 4594414c70cbSLiam Girdwood */ 4595414c70cbSLiam Girdwood int regulator_bulk_get(struct device *dev, int num_consumers, 4596414c70cbSLiam Girdwood struct regulator_bulk_data *consumers) 4597414c70cbSLiam Girdwood { 4598414c70cbSLiam Girdwood int i; 4599414c70cbSLiam Girdwood int ret; 4600414c70cbSLiam Girdwood 4601414c70cbSLiam Girdwood for (i = 0; i < num_consumers; i++) 4602414c70cbSLiam Girdwood consumers[i].consumer = NULL; 4603414c70cbSLiam Girdwood 4604414c70cbSLiam Girdwood for (i = 0; i < num_consumers; i++) { 4605565f9b07SBjorn Andersson consumers[i].consumer = regulator_get(dev, 4606565f9b07SBjorn Andersson consumers[i].supply); 4607414c70cbSLiam Girdwood if (IS_ERR(consumers[i].consumer)) { 4608414c70cbSLiam Girdwood ret = PTR_ERR(consumers[i].consumer); 4609414c70cbSLiam Girdwood consumers[i].consumer = NULL; 4610414c70cbSLiam Girdwood goto err; 4611414c70cbSLiam Girdwood } 4612414c70cbSLiam Girdwood } 4613414c70cbSLiam Girdwood 4614414c70cbSLiam Girdwood return 0; 4615414c70cbSLiam Girdwood 4616414c70cbSLiam Girdwood err: 4617b9816363SJorge Ramirez-Ortiz if (ret != -EPROBE_DEFER) 461861aab5adSMichał Mirosław dev_err(dev, "Failed to get supply '%s': %pe\n", 461961aab5adSMichał Mirosław consumers[i].supply, ERR_PTR(ret)); 4620b9816363SJorge Ramirez-Ortiz else 4621b9816363SJorge Ramirez-Ortiz dev_dbg(dev, "Failed to get supply '%s', deferring\n", 4622b9816363SJorge Ramirez-Ortiz consumers[i].supply); 4623b9816363SJorge Ramirez-Ortiz 4624b29c7690SAxel Lin while (--i >= 0) 4625414c70cbSLiam Girdwood regulator_put(consumers[i].consumer); 4626414c70cbSLiam Girdwood 4627414c70cbSLiam Girdwood return ret; 4628414c70cbSLiam Girdwood } 4629414c70cbSLiam Girdwood EXPORT_SYMBOL_GPL(regulator_bulk_get); 4630414c70cbSLiam Girdwood 4631f21e0e81SMark Brown static void regulator_bulk_enable_async(void *data, async_cookie_t cookie) 4632f21e0e81SMark Brown { 4633f21e0e81SMark Brown struct regulator_bulk_data *bulk = data; 4634f21e0e81SMark Brown 4635f21e0e81SMark Brown bulk->ret = regulator_enable(bulk->consumer); 4636f21e0e81SMark Brown } 4637f21e0e81SMark Brown 4638414c70cbSLiam Girdwood /** 4639414c70cbSLiam Girdwood * regulator_bulk_enable - enable multiple regulator consumers 4640414c70cbSLiam Girdwood * 4641414c70cbSLiam Girdwood * @num_consumers: Number of consumers 4642414c70cbSLiam Girdwood * @consumers: Consumer data; clients are stored here. 4643414c70cbSLiam Girdwood * @return 0 on success, an errno on failure 4644414c70cbSLiam Girdwood * 4645414c70cbSLiam Girdwood * This convenience API allows consumers to enable multiple regulator 4646414c70cbSLiam Girdwood * clients in a single API call. If any consumers cannot be enabled 4647414c70cbSLiam Girdwood * then any others that were enabled will be disabled again prior to 4648414c70cbSLiam Girdwood * return. 4649414c70cbSLiam Girdwood */ 4650414c70cbSLiam Girdwood int regulator_bulk_enable(int num_consumers, 4651414c70cbSLiam Girdwood struct regulator_bulk_data *consumers) 4652414c70cbSLiam Girdwood { 46532955b47dSDan Williams ASYNC_DOMAIN_EXCLUSIVE(async_domain); 4654414c70cbSLiam Girdwood int i; 4655f21e0e81SMark Brown int ret = 0; 4656414c70cbSLiam Girdwood 46576492bc1bSMark Brown for (i = 0; i < num_consumers; i++) { 4658f21e0e81SMark Brown async_schedule_domain(regulator_bulk_enable_async, 4659f21e0e81SMark Brown &consumers[i], &async_domain); 46606492bc1bSMark Brown } 4661f21e0e81SMark Brown 4662f21e0e81SMark Brown async_synchronize_full_domain(&async_domain); 4663f21e0e81SMark Brown 4664f21e0e81SMark Brown /* If any consumer failed we need to unwind any that succeeded */ 4665414c70cbSLiam Girdwood for (i = 0; i < num_consumers; i++) { 4666f21e0e81SMark Brown if (consumers[i].ret != 0) { 4667f21e0e81SMark Brown ret = consumers[i].ret; 4668414c70cbSLiam Girdwood goto err; 4669414c70cbSLiam Girdwood } 4670f21e0e81SMark Brown } 4671414c70cbSLiam Girdwood 4672414c70cbSLiam Girdwood return 0; 4673414c70cbSLiam Girdwood 4674414c70cbSLiam Girdwood err: 4675fbe31057SAndrzej Hajda for (i = 0; i < num_consumers; i++) { 4676fbe31057SAndrzej Hajda if (consumers[i].ret < 0) 467761aab5adSMichał Mirosław pr_err("Failed to enable %s: %pe\n", consumers[i].supply, 467861aab5adSMichał Mirosław ERR_PTR(consumers[i].ret)); 4679fbe31057SAndrzej Hajda else 4680414c70cbSLiam Girdwood regulator_disable(consumers[i].consumer); 4681fbe31057SAndrzej Hajda } 4682414c70cbSLiam Girdwood 4683414c70cbSLiam Girdwood return ret; 4684414c70cbSLiam Girdwood } 4685414c70cbSLiam Girdwood EXPORT_SYMBOL_GPL(regulator_bulk_enable); 4686414c70cbSLiam Girdwood 4687414c70cbSLiam Girdwood /** 4688414c70cbSLiam Girdwood * regulator_bulk_disable - disable multiple regulator consumers 4689414c70cbSLiam Girdwood * 4690414c70cbSLiam Girdwood * @num_consumers: Number of consumers 4691414c70cbSLiam Girdwood * @consumers: Consumer data; clients are stored here. 4692414c70cbSLiam Girdwood * @return 0 on success, an errno on failure 4693414c70cbSLiam Girdwood * 4694414c70cbSLiam Girdwood * This convenience API allows consumers to disable multiple regulator 469549e22632SSylwester Nawrocki * clients in a single API call. If any consumers cannot be disabled 469649e22632SSylwester Nawrocki * then any others that were disabled will be enabled again prior to 4697414c70cbSLiam Girdwood * return. 4698414c70cbSLiam Girdwood */ 4699414c70cbSLiam Girdwood int regulator_bulk_disable(int num_consumers, 4700414c70cbSLiam Girdwood struct regulator_bulk_data *consumers) 4701414c70cbSLiam Girdwood { 4702414c70cbSLiam Girdwood int i; 470301e86f49SMark Brown int ret, r; 4704414c70cbSLiam Girdwood 470549e22632SSylwester Nawrocki for (i = num_consumers - 1; i >= 0; --i) { 4706414c70cbSLiam Girdwood ret = regulator_disable(consumers[i].consumer); 4707414c70cbSLiam Girdwood if (ret != 0) 4708414c70cbSLiam Girdwood goto err; 4709414c70cbSLiam Girdwood } 4710414c70cbSLiam Girdwood 4711414c70cbSLiam Girdwood return 0; 4712414c70cbSLiam Girdwood 4713414c70cbSLiam Girdwood err: 471461aab5adSMichał Mirosław pr_err("Failed to disable %s: %pe\n", consumers[i].supply, ERR_PTR(ret)); 471501e86f49SMark Brown for (++i; i < num_consumers; ++i) { 471601e86f49SMark Brown r = regulator_enable(consumers[i].consumer); 471701e86f49SMark Brown if (r != 0) 471861aab5adSMichał Mirosław pr_err("Failed to re-enable %s: %pe\n", 471961aab5adSMichał Mirosław consumers[i].supply, ERR_PTR(r)); 472001e86f49SMark Brown } 4721414c70cbSLiam Girdwood 4722414c70cbSLiam Girdwood return ret; 4723414c70cbSLiam Girdwood } 4724414c70cbSLiam Girdwood EXPORT_SYMBOL_GPL(regulator_bulk_disable); 4725414c70cbSLiam Girdwood 4726414c70cbSLiam Girdwood /** 4727e1de2f42SDonggeun Kim * regulator_bulk_force_disable - force disable multiple regulator consumers 4728e1de2f42SDonggeun Kim * 4729e1de2f42SDonggeun Kim * @num_consumers: Number of consumers 4730e1de2f42SDonggeun Kim * @consumers: Consumer data; clients are stored here. 4731e1de2f42SDonggeun Kim * @return 0 on success, an errno on failure 4732e1de2f42SDonggeun Kim * 4733e1de2f42SDonggeun Kim * This convenience API allows consumers to forcibly disable multiple regulator 4734e1de2f42SDonggeun Kim * clients in a single API call. 4735e1de2f42SDonggeun Kim * NOTE: This should be used for situations when device damage will 4736e1de2f42SDonggeun Kim * likely occur if the regulators are not disabled (e.g. over temp). 4737e1de2f42SDonggeun Kim * Although regulator_force_disable function call for some consumers can 4738e1de2f42SDonggeun Kim * return error numbers, the function is called for all consumers. 4739e1de2f42SDonggeun Kim */ 4740e1de2f42SDonggeun Kim int regulator_bulk_force_disable(int num_consumers, 4741e1de2f42SDonggeun Kim struct regulator_bulk_data *consumers) 4742e1de2f42SDonggeun Kim { 4743e1de2f42SDonggeun Kim int i; 4744b8c77ff6SDmitry Torokhov int ret = 0; 4745e1de2f42SDonggeun Kim 4746b8c77ff6SDmitry Torokhov for (i = 0; i < num_consumers; i++) { 4747e1de2f42SDonggeun Kim consumers[i].ret = 4748e1de2f42SDonggeun Kim regulator_force_disable(consumers[i].consumer); 4749e1de2f42SDonggeun Kim 4750b8c77ff6SDmitry Torokhov /* Store first error for reporting */ 4751b8c77ff6SDmitry Torokhov if (consumers[i].ret && !ret) 4752e1de2f42SDonggeun Kim ret = consumers[i].ret; 4753e1de2f42SDonggeun Kim } 4754e1de2f42SDonggeun Kim 4755e1de2f42SDonggeun Kim return ret; 4756e1de2f42SDonggeun Kim } 4757e1de2f42SDonggeun Kim EXPORT_SYMBOL_GPL(regulator_bulk_force_disable); 4758e1de2f42SDonggeun Kim 4759e1de2f42SDonggeun Kim /** 4760414c70cbSLiam Girdwood * regulator_bulk_free - free multiple regulator consumers 4761414c70cbSLiam Girdwood * 4762414c70cbSLiam Girdwood * @num_consumers: Number of consumers 4763414c70cbSLiam Girdwood * @consumers: Consumer data; clients are stored here. 4764414c70cbSLiam Girdwood * 4765414c70cbSLiam Girdwood * This convenience API allows consumers to free multiple regulator 4766414c70cbSLiam Girdwood * clients in a single API call. 4767414c70cbSLiam Girdwood */ 4768414c70cbSLiam Girdwood void regulator_bulk_free(int num_consumers, 4769414c70cbSLiam Girdwood struct regulator_bulk_data *consumers) 4770414c70cbSLiam Girdwood { 4771414c70cbSLiam Girdwood int i; 4772414c70cbSLiam Girdwood 4773414c70cbSLiam Girdwood for (i = 0; i < num_consumers; i++) { 4774414c70cbSLiam Girdwood regulator_put(consumers[i].consumer); 4775414c70cbSLiam Girdwood consumers[i].consumer = NULL; 4776414c70cbSLiam Girdwood } 4777414c70cbSLiam Girdwood } 4778414c70cbSLiam Girdwood EXPORT_SYMBOL_GPL(regulator_bulk_free); 4779414c70cbSLiam Girdwood 4780414c70cbSLiam Girdwood /** 4781414c70cbSLiam Girdwood * regulator_notifier_call_chain - call regulator event notifier 478269279fb9SMark Brown * @rdev: regulator source 4783414c70cbSLiam Girdwood * @event: notifier block 478469279fb9SMark Brown * @data: callback-specific data. 4785414c70cbSLiam Girdwood * 4786414c70cbSLiam Girdwood * Called by regulator drivers to notify clients a regulator event has 47873bca239dSMichał Mirosław * occurred. 4788414c70cbSLiam Girdwood */ 4789414c70cbSLiam Girdwood int regulator_notifier_call_chain(struct regulator_dev *rdev, 4790414c70cbSLiam Girdwood unsigned long event, void *data) 4791414c70cbSLiam Girdwood { 4792414c70cbSLiam Girdwood _notifier_call_chain(rdev, event, data); 4793414c70cbSLiam Girdwood return NOTIFY_DONE; 4794414c70cbSLiam Girdwood 4795414c70cbSLiam Girdwood } 4796414c70cbSLiam Girdwood EXPORT_SYMBOL_GPL(regulator_notifier_call_chain); 4797414c70cbSLiam Girdwood 4798be721979SMark Brown /** 4799be721979SMark Brown * regulator_mode_to_status - convert a regulator mode into a status 4800be721979SMark Brown * 4801be721979SMark Brown * @mode: Mode to convert 4802be721979SMark Brown * 4803be721979SMark Brown * Convert a regulator mode into a status. 4804be721979SMark Brown */ 4805be721979SMark Brown int regulator_mode_to_status(unsigned int mode) 4806be721979SMark Brown { 4807be721979SMark Brown switch (mode) { 4808be721979SMark Brown case REGULATOR_MODE_FAST: 4809be721979SMark Brown return REGULATOR_STATUS_FAST; 4810be721979SMark Brown case REGULATOR_MODE_NORMAL: 4811be721979SMark Brown return REGULATOR_STATUS_NORMAL; 4812be721979SMark Brown case REGULATOR_MODE_IDLE: 4813be721979SMark Brown return REGULATOR_STATUS_IDLE; 481403ffcf3dSKrystian Garbaciak case REGULATOR_MODE_STANDBY: 4815be721979SMark Brown return REGULATOR_STATUS_STANDBY; 4816be721979SMark Brown default: 48171beaf762SKrystian Garbaciak return REGULATOR_STATUS_UNDEFINED; 4818be721979SMark Brown } 4819be721979SMark Brown } 4820be721979SMark Brown EXPORT_SYMBOL_GPL(regulator_mode_to_status); 4821be721979SMark Brown 482239f802d6STakashi Iwai static struct attribute *regulator_dev_attrs[] = { 482339f802d6STakashi Iwai &dev_attr_name.attr, 482439f802d6STakashi Iwai &dev_attr_num_users.attr, 482539f802d6STakashi Iwai &dev_attr_type.attr, 482639f802d6STakashi Iwai &dev_attr_microvolts.attr, 482739f802d6STakashi Iwai &dev_attr_microamps.attr, 482839f802d6STakashi Iwai &dev_attr_opmode.attr, 482939f802d6STakashi Iwai &dev_attr_state.attr, 483039f802d6STakashi Iwai &dev_attr_status.attr, 483139f802d6STakashi Iwai &dev_attr_bypass.attr, 483239f802d6STakashi Iwai &dev_attr_requested_microamps.attr, 483339f802d6STakashi Iwai &dev_attr_min_microvolts.attr, 483439f802d6STakashi Iwai &dev_attr_max_microvolts.attr, 483539f802d6STakashi Iwai &dev_attr_min_microamps.attr, 483639f802d6STakashi Iwai &dev_attr_max_microamps.attr, 483739f802d6STakashi Iwai &dev_attr_suspend_standby_state.attr, 483839f802d6STakashi Iwai &dev_attr_suspend_mem_state.attr, 483939f802d6STakashi Iwai &dev_attr_suspend_disk_state.attr, 484039f802d6STakashi Iwai &dev_attr_suspend_standby_microvolts.attr, 484139f802d6STakashi Iwai &dev_attr_suspend_mem_microvolts.attr, 484239f802d6STakashi Iwai &dev_attr_suspend_disk_microvolts.attr, 484339f802d6STakashi Iwai &dev_attr_suspend_standby_mode.attr, 484439f802d6STakashi Iwai &dev_attr_suspend_mem_mode.attr, 484539f802d6STakashi Iwai &dev_attr_suspend_disk_mode.attr, 484639f802d6STakashi Iwai NULL 484739f802d6STakashi Iwai }; 484839f802d6STakashi Iwai 48497ad68e2fSDavid Brownell /* 48507ad68e2fSDavid Brownell * To avoid cluttering sysfs (and memory) with useless state, only 48517ad68e2fSDavid Brownell * create attributes that can be meaningfully displayed. 48527ad68e2fSDavid Brownell */ 485339f802d6STakashi Iwai static umode_t regulator_attr_is_visible(struct kobject *kobj, 485439f802d6STakashi Iwai struct attribute *attr, int idx) 48557ad68e2fSDavid Brownell { 485639f802d6STakashi Iwai struct device *dev = kobj_to_dev(kobj); 485783080a14SGeliang Tang struct regulator_dev *rdev = dev_to_rdev(dev); 4858272e2315SGuodong Xu const struct regulator_ops *ops = rdev->desc->ops; 485939f802d6STakashi Iwai umode_t mode = attr->mode; 486039f802d6STakashi Iwai 486139f802d6STakashi Iwai /* these three are always present */ 486239f802d6STakashi Iwai if (attr == &dev_attr_name.attr || 486339f802d6STakashi Iwai attr == &dev_attr_num_users.attr || 486439f802d6STakashi Iwai attr == &dev_attr_type.attr) 486539f802d6STakashi Iwai return mode; 48667ad68e2fSDavid Brownell 48677ad68e2fSDavid Brownell /* some attributes need specific methods to be displayed */ 486839f802d6STakashi Iwai if (attr == &dev_attr_microvolts.attr) { 48694c78899bSMark Brown if ((ops->get_voltage && ops->get_voltage(rdev) >= 0) || 4870f2889e65SMark Brown (ops->get_voltage_sel && ops->get_voltage_sel(rdev) >= 0) || 48715a523605SLaxman Dewangan (ops->list_voltage && ops->list_voltage(rdev, 0) >= 0) || 487239f802d6STakashi Iwai (rdev->desc->fixed_uV && rdev->desc->n_voltages == 1)) 487339f802d6STakashi Iwai return mode; 487439f802d6STakashi Iwai return 0; 4875f59c8f9fSMark Brown } 48767ad68e2fSDavid Brownell 487739f802d6STakashi Iwai if (attr == &dev_attr_microamps.attr) 487839f802d6STakashi Iwai return ops->get_current_limit ? mode : 0; 487939f802d6STakashi Iwai 488039f802d6STakashi Iwai if (attr == &dev_attr_opmode.attr) 488139f802d6STakashi Iwai return ops->get_mode ? mode : 0; 488239f802d6STakashi Iwai 488339f802d6STakashi Iwai if (attr == &dev_attr_state.attr) 488439f802d6STakashi Iwai return (rdev->ena_pin || ops->is_enabled) ? mode : 0; 488539f802d6STakashi Iwai 488639f802d6STakashi Iwai if (attr == &dev_attr_status.attr) 488739f802d6STakashi Iwai return ops->get_status ? mode : 0; 488839f802d6STakashi Iwai 488939f802d6STakashi Iwai if (attr == &dev_attr_bypass.attr) 489039f802d6STakashi Iwai return ops->get_bypass ? mode : 0; 489139f802d6STakashi Iwai 48927ad68e2fSDavid Brownell /* constraints need specific supporting methods */ 489339f802d6STakashi Iwai if (attr == &dev_attr_min_microvolts.attr || 489439f802d6STakashi Iwai attr == &dev_attr_max_microvolts.attr) 489539f802d6STakashi Iwai return (ops->set_voltage || ops->set_voltage_sel) ? mode : 0; 489639f802d6STakashi Iwai 489739f802d6STakashi Iwai if (attr == &dev_attr_min_microamps.attr || 489839f802d6STakashi Iwai attr == &dev_attr_max_microamps.attr) 489939f802d6STakashi Iwai return ops->set_current_limit ? mode : 0; 490039f802d6STakashi Iwai 490139f802d6STakashi Iwai if (attr == &dev_attr_suspend_standby_state.attr || 490239f802d6STakashi Iwai attr == &dev_attr_suspend_mem_state.attr || 490339f802d6STakashi Iwai attr == &dev_attr_suspend_disk_state.attr) 490439f802d6STakashi Iwai return mode; 490539f802d6STakashi Iwai 490639f802d6STakashi Iwai if (attr == &dev_attr_suspend_standby_microvolts.attr || 490739f802d6STakashi Iwai attr == &dev_attr_suspend_mem_microvolts.attr || 490839f802d6STakashi Iwai attr == &dev_attr_suspend_disk_microvolts.attr) 490939f802d6STakashi Iwai return ops->set_suspend_voltage ? mode : 0; 491039f802d6STakashi Iwai 491139f802d6STakashi Iwai if (attr == &dev_attr_suspend_standby_mode.attr || 491239f802d6STakashi Iwai attr == &dev_attr_suspend_mem_mode.attr || 491339f802d6STakashi Iwai attr == &dev_attr_suspend_disk_mode.attr) 491439f802d6STakashi Iwai return ops->set_suspend_mode ? mode : 0; 491539f802d6STakashi Iwai 491639f802d6STakashi Iwai return mode; 49177ad68e2fSDavid Brownell } 49187ad68e2fSDavid Brownell 491939f802d6STakashi Iwai static const struct attribute_group regulator_dev_group = { 492039f802d6STakashi Iwai .attrs = regulator_dev_attrs, 492139f802d6STakashi Iwai .is_visible = regulator_attr_is_visible, 492239f802d6STakashi Iwai }; 49237ad68e2fSDavid Brownell 492439f802d6STakashi Iwai static const struct attribute_group *regulator_dev_groups[] = { 492539f802d6STakashi Iwai ®ulator_dev_group, 492639f802d6STakashi Iwai NULL 492739f802d6STakashi Iwai }; 492839f802d6STakashi Iwai 492939f802d6STakashi Iwai static void regulator_dev_release(struct device *dev) 493039f802d6STakashi Iwai { 493139f802d6STakashi Iwai struct regulator_dev *rdev = dev_get_drvdata(dev); 493229f5f486SMark Brown 493329f5f486SMark Brown kfree(rdev->constraints); 493429f5f486SMark Brown of_node_put(rdev->dev.of_node); 493539f802d6STakashi Iwai kfree(rdev); 49367ad68e2fSDavid Brownell } 49377ad68e2fSDavid Brownell 49381130e5b3SMark Brown static void rdev_init_debugfs(struct regulator_dev *rdev) 49391130e5b3SMark Brown { 4940a9eaa813SGuenter Roeck struct device *parent = rdev->dev.parent; 4941a9eaa813SGuenter Roeck const char *rname = rdev_get_name(rdev); 4942a9eaa813SGuenter Roeck char name[NAME_MAX]; 4943a9eaa813SGuenter Roeck 4944a9eaa813SGuenter Roeck /* Avoid duplicate debugfs directory names */ 4945a9eaa813SGuenter Roeck if (parent && rname == rdev->desc->name) { 4946a9eaa813SGuenter Roeck snprintf(name, sizeof(name), "%s-%s", dev_name(parent), 4947a9eaa813SGuenter Roeck rname); 4948a9eaa813SGuenter Roeck rname = name; 4949a9eaa813SGuenter Roeck } 4950a9eaa813SGuenter Roeck 4951a9eaa813SGuenter Roeck rdev->debugfs = debugfs_create_dir(rname, debugfs_root); 495224751434SStephen Boyd if (!rdev->debugfs) { 49531130e5b3SMark Brown rdev_warn(rdev, "Failed to create debugfs directory\n"); 49541130e5b3SMark Brown return; 49551130e5b3SMark Brown } 49561130e5b3SMark Brown 49571130e5b3SMark Brown debugfs_create_u32("use_count", 0444, rdev->debugfs, 49581130e5b3SMark Brown &rdev->use_count); 49591130e5b3SMark Brown debugfs_create_u32("open_count", 0444, rdev->debugfs, 49601130e5b3SMark Brown &rdev->open_count); 4961f59c8f9fSMark Brown debugfs_create_u32("bypass_count", 0444, rdev->debugfs, 4962f59c8f9fSMark Brown &rdev->bypass_count); 49631130e5b3SMark Brown } 49641130e5b3SMark Brown 49655e3ca2b3SJavier Martinez Canillas static int regulator_register_resolve_supply(struct device *dev, void *data) 49665e3ca2b3SJavier Martinez Canillas { 49677ddede6aSJon Hunter struct regulator_dev *rdev = dev_to_rdev(dev); 49687ddede6aSJon Hunter 49697ddede6aSJon Hunter if (regulator_resolve_supply(rdev)) 49707ddede6aSJon Hunter rdev_dbg(rdev, "unable to resolve supply\n"); 49717ddede6aSJon Hunter 49727ddede6aSJon Hunter return 0; 49735e3ca2b3SJavier Martinez Canillas } 49745e3ca2b3SJavier Martinez Canillas 4975d8ca7d18SDmitry Osipenko int regulator_coupler_register(struct regulator_coupler *coupler) 4976d8ca7d18SDmitry Osipenko { 4977d8ca7d18SDmitry Osipenko mutex_lock(®ulator_list_mutex); 4978d8ca7d18SDmitry Osipenko list_add_tail(&coupler->list, ®ulator_coupler_list); 4979d8ca7d18SDmitry Osipenko mutex_unlock(®ulator_list_mutex); 4980d8ca7d18SDmitry Osipenko 4981d8ca7d18SDmitry Osipenko return 0; 4982d8ca7d18SDmitry Osipenko } 4983d8ca7d18SDmitry Osipenko 4984d8ca7d18SDmitry Osipenko static struct regulator_coupler * 4985d8ca7d18SDmitry Osipenko regulator_find_coupler(struct regulator_dev *rdev) 4986d8ca7d18SDmitry Osipenko { 4987d8ca7d18SDmitry Osipenko struct regulator_coupler *coupler; 4988d8ca7d18SDmitry Osipenko int err; 4989d8ca7d18SDmitry Osipenko 4990d8ca7d18SDmitry Osipenko /* 4991d8ca7d18SDmitry Osipenko * Note that regulators are appended to the list and the generic 4992d8ca7d18SDmitry Osipenko * coupler is registered first, hence it will be attached at last 4993d8ca7d18SDmitry Osipenko * if nobody cared. 4994d8ca7d18SDmitry Osipenko */ 4995d8ca7d18SDmitry Osipenko list_for_each_entry_reverse(coupler, ®ulator_coupler_list, list) { 4996d8ca7d18SDmitry Osipenko err = coupler->attach_regulator(coupler, rdev); 4997d8ca7d18SDmitry Osipenko if (!err) { 4998d8ca7d18SDmitry Osipenko if (!coupler->balance_voltage && 4999d8ca7d18SDmitry Osipenko rdev->coupling_desc.n_coupled > 2) 5000d8ca7d18SDmitry Osipenko goto err_unsupported; 5001d8ca7d18SDmitry Osipenko 5002d8ca7d18SDmitry Osipenko return coupler; 5003d8ca7d18SDmitry Osipenko } 5004d8ca7d18SDmitry Osipenko 5005d8ca7d18SDmitry Osipenko if (err < 0) 5006d8ca7d18SDmitry Osipenko return ERR_PTR(err); 5007d8ca7d18SDmitry Osipenko 5008d8ca7d18SDmitry Osipenko if (err == 1) 5009d8ca7d18SDmitry Osipenko continue; 5010d8ca7d18SDmitry Osipenko 5011d8ca7d18SDmitry Osipenko break; 5012d8ca7d18SDmitry Osipenko } 5013d8ca7d18SDmitry Osipenko 5014d8ca7d18SDmitry Osipenko return ERR_PTR(-EINVAL); 5015d8ca7d18SDmitry Osipenko 5016d8ca7d18SDmitry Osipenko err_unsupported: 5017d8ca7d18SDmitry Osipenko if (coupler->detach_regulator) 5018d8ca7d18SDmitry Osipenko coupler->detach_regulator(coupler, rdev); 5019d8ca7d18SDmitry Osipenko 5020d8ca7d18SDmitry Osipenko rdev_err(rdev, 5021d8ca7d18SDmitry Osipenko "Voltage balancing for multiple regulator couples is unimplemented\n"); 5022d8ca7d18SDmitry Osipenko 5023d8ca7d18SDmitry Osipenko return ERR_PTR(-EPERM); 5024d8ca7d18SDmitry Osipenko } 5025d8ca7d18SDmitry Osipenko 5026f9503385SDmitry Osipenko static void regulator_resolve_coupling(struct regulator_dev *rdev) 5027d3d64537SMaciej Purski { 5028d8ca7d18SDmitry Osipenko struct regulator_coupler *coupler = rdev->coupling_desc.coupler; 5029d3d64537SMaciej Purski struct coupling_desc *c_desc = &rdev->coupling_desc; 5030d3d64537SMaciej Purski int n_coupled = c_desc->n_coupled; 5031d3d64537SMaciej Purski struct regulator_dev *c_rdev; 5032d3d64537SMaciej Purski int i; 5033d3d64537SMaciej Purski 5034d3d64537SMaciej Purski for (i = 1; i < n_coupled; i++) { 5035d3d64537SMaciej Purski /* already resolved */ 5036d3d64537SMaciej Purski if (c_desc->coupled_rdevs[i]) 5037d3d64537SMaciej Purski continue; 5038d3d64537SMaciej Purski 5039d3d64537SMaciej Purski c_rdev = of_parse_coupled_regulator(rdev, i - 1); 5040d3d64537SMaciej Purski 5041f9503385SDmitry Osipenko if (!c_rdev) 5042f9503385SDmitry Osipenko continue; 5043f9503385SDmitry Osipenko 5044d8ca7d18SDmitry Osipenko if (c_rdev->coupling_desc.coupler != coupler) { 5045d8ca7d18SDmitry Osipenko rdev_err(rdev, "coupler mismatch with %s\n", 5046d8ca7d18SDmitry Osipenko rdev_get_name(c_rdev)); 5047d8ca7d18SDmitry Osipenko return; 5048d8ca7d18SDmitry Osipenko } 5049d8ca7d18SDmitry Osipenko 5050d3d64537SMaciej Purski c_desc->coupled_rdevs[i] = c_rdev; 5051d3d64537SMaciej Purski c_desc->n_resolved++; 5052f9503385SDmitry Osipenko 5053f9503385SDmitry Osipenko regulator_resolve_coupling(c_rdev); 5054d3d64537SMaciej Purski } 5055d3d64537SMaciej Purski } 5056d3d64537SMaciej Purski 50576303f3e7SDmitry Osipenko static void regulator_remove_coupling(struct regulator_dev *rdev) 5058d3d64537SMaciej Purski { 5059d8ca7d18SDmitry Osipenko struct regulator_coupler *coupler = rdev->coupling_desc.coupler; 50606303f3e7SDmitry Osipenko struct coupling_desc *__c_desc, *c_desc = &rdev->coupling_desc; 50616303f3e7SDmitry Osipenko struct regulator_dev *__c_rdev, *c_rdev; 50626303f3e7SDmitry Osipenko unsigned int __n_coupled, n_coupled; 50636303f3e7SDmitry Osipenko int i, k; 5064d8ca7d18SDmitry Osipenko int err; 5065d3d64537SMaciej Purski 50666303f3e7SDmitry Osipenko n_coupled = c_desc->n_coupled; 5067d3d64537SMaciej Purski 50686303f3e7SDmitry Osipenko for (i = 1; i < n_coupled; i++) { 50696303f3e7SDmitry Osipenko c_rdev = c_desc->coupled_rdevs[i]; 5070d3d64537SMaciej Purski 50716303f3e7SDmitry Osipenko if (!c_rdev) 50726303f3e7SDmitry Osipenko continue; 50736303f3e7SDmitry Osipenko 50746303f3e7SDmitry Osipenko regulator_lock(c_rdev); 50756303f3e7SDmitry Osipenko 50766303f3e7SDmitry Osipenko __c_desc = &c_rdev->coupling_desc; 50776303f3e7SDmitry Osipenko __n_coupled = __c_desc->n_coupled; 50786303f3e7SDmitry Osipenko 50796303f3e7SDmitry Osipenko for (k = 1; k < __n_coupled; k++) { 50806303f3e7SDmitry Osipenko __c_rdev = __c_desc->coupled_rdevs[k]; 50816303f3e7SDmitry Osipenko 50826303f3e7SDmitry Osipenko if (__c_rdev == rdev) { 50836303f3e7SDmitry Osipenko __c_desc->coupled_rdevs[k] = NULL; 50846303f3e7SDmitry Osipenko __c_desc->n_resolved--; 50856303f3e7SDmitry Osipenko break; 50866303f3e7SDmitry Osipenko } 5087d3d64537SMaciej Purski } 5088d3d64537SMaciej Purski 50896303f3e7SDmitry Osipenko regulator_unlock(c_rdev); 50906303f3e7SDmitry Osipenko 50916303f3e7SDmitry Osipenko c_desc->coupled_rdevs[i] = NULL; 50926303f3e7SDmitry Osipenko c_desc->n_resolved--; 50936303f3e7SDmitry Osipenko } 5094d8ca7d18SDmitry Osipenko 5095d8ca7d18SDmitry Osipenko if (coupler && coupler->detach_regulator) { 5096d8ca7d18SDmitry Osipenko err = coupler->detach_regulator(coupler, rdev); 5097d8ca7d18SDmitry Osipenko if (err) 509861aab5adSMichał Mirosław rdev_err(rdev, "failed to detach from coupler: %pe\n", 509961aab5adSMichał Mirosław ERR_PTR(err)); 5100d8ca7d18SDmitry Osipenko } 5101d8ca7d18SDmitry Osipenko 5102d8ca7d18SDmitry Osipenko kfree(rdev->coupling_desc.coupled_rdevs); 5103d8ca7d18SDmitry Osipenko rdev->coupling_desc.coupled_rdevs = NULL; 51046303f3e7SDmitry Osipenko } 51056303f3e7SDmitry Osipenko 5106f9503385SDmitry Osipenko static int regulator_init_coupling(struct regulator_dev *rdev) 5107d3d64537SMaciej Purski { 51087d819664SMichał Mirosław struct regulator_dev **coupled; 5109d8ca7d18SDmitry Osipenko int err, n_phandles; 5110d3d64537SMaciej Purski 5111d3d64537SMaciej Purski if (!IS_ENABLED(CONFIG_OF)) 5112d3d64537SMaciej Purski n_phandles = 0; 5113d3d64537SMaciej Purski else 5114d3d64537SMaciej Purski n_phandles = of_get_n_coupled(rdev); 5115d3d64537SMaciej Purski 51167d819664SMichał Mirosław coupled = kcalloc(n_phandles + 1, sizeof(*coupled), GFP_KERNEL); 51177d819664SMichał Mirosław if (!coupled) 5118d8ca7d18SDmitry Osipenko return -ENOMEM; 5119d3d64537SMaciej Purski 51207d819664SMichał Mirosław rdev->coupling_desc.coupled_rdevs = coupled; 51217d819664SMichał Mirosław 5122d3d64537SMaciej Purski /* 5123d3d64537SMaciej Purski * Every regulator should always have coupling descriptor filled with 5124d3d64537SMaciej Purski * at least pointer to itself. 5125d3d64537SMaciej Purski */ 5126d3d64537SMaciej Purski rdev->coupling_desc.coupled_rdevs[0] = rdev; 5127d3d64537SMaciej Purski rdev->coupling_desc.n_coupled = n_phandles + 1; 5128d3d64537SMaciej Purski rdev->coupling_desc.n_resolved++; 5129d3d64537SMaciej Purski 5130d3d64537SMaciej Purski /* regulator isn't coupled */ 5131d3d64537SMaciej Purski if (n_phandles == 0) 5132d3d64537SMaciej Purski return 0; 5133d3d64537SMaciej Purski 5134d3d64537SMaciej Purski if (!of_check_coupling_data(rdev)) 5135d3d64537SMaciej Purski return -EPERM; 5136d3d64537SMaciej Purski 513773a32129SMichał Mirosław mutex_lock(®ulator_list_mutex); 5138d8ca7d18SDmitry Osipenko rdev->coupling_desc.coupler = regulator_find_coupler(rdev); 513973a32129SMichał Mirosław mutex_unlock(®ulator_list_mutex); 514073a32129SMichał Mirosław 5141d8ca7d18SDmitry Osipenko if (IS_ERR(rdev->coupling_desc.coupler)) { 5142d8ca7d18SDmitry Osipenko err = PTR_ERR(rdev->coupling_desc.coupler); 514361aab5adSMichał Mirosław rdev_err(rdev, "failed to get coupler: %pe\n", ERR_PTR(err)); 5144d8ca7d18SDmitry Osipenko return err; 5145d8ca7d18SDmitry Osipenko } 5146d8ca7d18SDmitry Osipenko 5147d3d64537SMaciej Purski return 0; 5148d3d64537SMaciej Purski } 5149d3d64537SMaciej Purski 5150d8ca7d18SDmitry Osipenko static int generic_coupler_attach(struct regulator_coupler *coupler, 5151d8ca7d18SDmitry Osipenko struct regulator_dev *rdev) 5152d8ca7d18SDmitry Osipenko { 5153d8ca7d18SDmitry Osipenko if (rdev->coupling_desc.n_coupled > 2) { 5154d8ca7d18SDmitry Osipenko rdev_err(rdev, 5155d8ca7d18SDmitry Osipenko "Voltage balancing for multiple regulator couples is unimplemented\n"); 5156d8ca7d18SDmitry Osipenko return -EPERM; 5157d8ca7d18SDmitry Osipenko } 5158d8ca7d18SDmitry Osipenko 5159e381bfe4SDmitry Osipenko if (!rdev->constraints->always_on) { 5160e381bfe4SDmitry Osipenko rdev_err(rdev, 5161e381bfe4SDmitry Osipenko "Coupling of a non always-on regulator is unimplemented\n"); 5162e381bfe4SDmitry Osipenko return -ENOTSUPP; 5163e381bfe4SDmitry Osipenko } 5164e381bfe4SDmitry Osipenko 5165d8ca7d18SDmitry Osipenko return 0; 5166d8ca7d18SDmitry Osipenko } 5167d8ca7d18SDmitry Osipenko 5168d8ca7d18SDmitry Osipenko static struct regulator_coupler generic_regulator_coupler = { 5169d8ca7d18SDmitry Osipenko .attach_regulator = generic_coupler_attach, 5170d8ca7d18SDmitry Osipenko }; 5171d8ca7d18SDmitry Osipenko 5172414c70cbSLiam Girdwood /** 5173414c70cbSLiam Girdwood * regulator_register - register regulator 517469279fb9SMark Brown * @regulator_desc: regulator to register 5175f47531b1SKrzysztof Kozlowski * @cfg: runtime configuration for regulator 5176414c70cbSLiam Girdwood * 5177414c70cbSLiam Girdwood * Called by regulator drivers to register a regulator. 51780384618aSAxel Lin * Returns a valid pointer to struct regulator_dev on success 51790384618aSAxel Lin * or an ERR_PTR() on error. 5180414c70cbSLiam Girdwood */ 518165f26846SMark Brown struct regulator_dev * 518265f26846SMark Brown regulator_register(const struct regulator_desc *regulator_desc, 51831b3de223SKrzysztof Kozlowski const struct regulator_config *cfg) 5184414c70cbSLiam Girdwood { 5185c172708dSMark Brown const struct regulator_init_data *init_data; 51861b3de223SKrzysztof Kozlowski struct regulator_config *config = NULL; 518772dca06fSAniroop Mathur static atomic_t regulator_no = ATOMIC_INIT(-1); 5188414c70cbSLiam Girdwood struct regulator_dev *rdev; 51890edb040dSLinus Walleij bool dangling_cfg_gpiod = false; 51900edb040dSLinus Walleij bool dangling_of_gpiod = false; 519132c8fad4SMark Brown struct device *dev; 5192a5766f11SLiam Girdwood int ret, i; 5193414c70cbSLiam Girdwood 51940edb040dSLinus Walleij if (cfg == NULL) 5195414c70cbSLiam Girdwood return ERR_PTR(-EINVAL); 51960edb040dSLinus Walleij if (cfg->ena_gpiod) 51970edb040dSLinus Walleij dangling_cfg_gpiod = true; 51980edb040dSLinus Walleij if (regulator_desc == NULL) { 51990edb040dSLinus Walleij ret = -EINVAL; 52000edb040dSLinus Walleij goto rinse; 52010edb040dSLinus Walleij } 5202414c70cbSLiam Girdwood 52031b3de223SKrzysztof Kozlowski dev = cfg->dev; 5204dcf70112SMark Brown WARN_ON(!dev); 520532c8fad4SMark Brown 52060edb040dSLinus Walleij if (regulator_desc->name == NULL || regulator_desc->ops == NULL) { 52070edb040dSLinus Walleij ret = -EINVAL; 52080edb040dSLinus Walleij goto rinse; 52090edb040dSLinus Walleij } 5210414c70cbSLiam Girdwood 5211cd78dfc6SDiego Liziero if (regulator_desc->type != REGULATOR_VOLTAGE && 52120edb040dSLinus Walleij regulator_desc->type != REGULATOR_CURRENT) { 52130edb040dSLinus Walleij ret = -EINVAL; 52140edb040dSLinus Walleij goto rinse; 52150edb040dSLinus Walleij } 5216414c70cbSLiam Girdwood 5217476c2d83SMark Brown /* Only one of each should be implemented */ 5218476c2d83SMark Brown WARN_ON(regulator_desc->ops->get_voltage && 5219476c2d83SMark Brown regulator_desc->ops->get_voltage_sel); 5220e8eef82bSMark Brown WARN_ON(regulator_desc->ops->set_voltage && 5221e8eef82bSMark Brown regulator_desc->ops->set_voltage_sel); 5222476c2d83SMark Brown 5223476c2d83SMark Brown /* If we're using selectors we must implement list_voltage. */ 5224476c2d83SMark Brown if (regulator_desc->ops->get_voltage_sel && 5225476c2d83SMark Brown !regulator_desc->ops->list_voltage) { 52260edb040dSLinus Walleij ret = -EINVAL; 52270edb040dSLinus Walleij goto rinse; 5228476c2d83SMark Brown } 5229e8eef82bSMark Brown if (regulator_desc->ops->set_voltage_sel && 5230e8eef82bSMark Brown !regulator_desc->ops->list_voltage) { 52310edb040dSLinus Walleij ret = -EINVAL; 52320edb040dSLinus Walleij goto rinse; 5233e8eef82bSMark Brown } 5234476c2d83SMark Brown 5235414c70cbSLiam Girdwood rdev = kzalloc(sizeof(struct regulator_dev), GFP_KERNEL); 52360edb040dSLinus Walleij if (rdev == NULL) { 52370edb040dSLinus Walleij ret = -ENOMEM; 52380edb040dSLinus Walleij goto rinse; 52390edb040dSLinus Walleij } 5240d3c73156SMichał Mirosław device_initialize(&rdev->dev); 5241414c70cbSLiam Girdwood 52421b3de223SKrzysztof Kozlowski /* 52431b3de223SKrzysztof Kozlowski * Duplicate the config so the driver could override it after 52441b3de223SKrzysztof Kozlowski * parsing init data. 52451b3de223SKrzysztof Kozlowski */ 52461b3de223SKrzysztof Kozlowski config = kmemdup(cfg, sizeof(*cfg), GFP_KERNEL); 52471b3de223SKrzysztof Kozlowski if (config == NULL) { 52480edb040dSLinus Walleij ret = -ENOMEM; 5249d3c73156SMichał Mirosław goto clean; 52501b3de223SKrzysztof Kozlowski } 52511b3de223SKrzysztof Kozlowski 5252bfa21a0dSKrzysztof Kozlowski init_data = regulator_of_get_init_data(dev, regulator_desc, config, 5253a0c7b164SMark Brown &rdev->dev.of_node); 5254f8970d34SMarco Felsch 5255f8970d34SMarco Felsch /* 5256f8970d34SMarco Felsch * Sometimes not all resources are probed already so we need to take 5257f8970d34SMarco Felsch * that into account. This happens most the time if the ena_gpiod comes 5258f8970d34SMarco Felsch * from a gpio extender or something else. 5259f8970d34SMarco Felsch */ 5260f8970d34SMarco Felsch if (PTR_ERR(init_data) == -EPROBE_DEFER) { 5261f8970d34SMarco Felsch ret = -EPROBE_DEFER; 5262d3c73156SMichał Mirosław goto clean; 5263f8970d34SMarco Felsch } 5264f8970d34SMarco Felsch 52650edb040dSLinus Walleij /* 52660edb040dSLinus Walleij * We need to keep track of any GPIO descriptor coming from the 52670edb040dSLinus Walleij * device tree until we have handled it over to the core. If the 52680edb040dSLinus Walleij * config that was passed in to this function DOES NOT contain 52690edb040dSLinus Walleij * a descriptor, and the config after this call DOES contain 527048f1b4efSKrzysztof Kozlowski * a descriptor, we definitely got one from parsing the device 52710edb040dSLinus Walleij * tree. 52720edb040dSLinus Walleij */ 52730edb040dSLinus Walleij if (!cfg->ena_gpiod && config->ena_gpiod) 52740edb040dSLinus Walleij dangling_of_gpiod = true; 5275a0c7b164SMark Brown if (!init_data) { 5276a0c7b164SMark Brown init_data = config->init_data; 5277a0c7b164SMark Brown rdev->dev.of_node = of_node_get(config->of_node); 5278a0c7b164SMark Brown } 5279a0c7b164SMark Brown 5280f8702f9eSDmitry Osipenko ww_mutex_init(&rdev->mutex, ®ulator_ww_class); 5281c172708dSMark Brown rdev->reg_data = config->driver_data; 5282414c70cbSLiam Girdwood rdev->owner = regulator_desc->owner; 5283414c70cbSLiam Girdwood rdev->desc = regulator_desc; 52843a4b0a07SMark Brown if (config->regmap) 528565b19ce6SMark Brown rdev->regmap = config->regmap; 528652b84dacSAnilKumar Ch else if (dev_get_regmap(dev, NULL)) 52873a4b0a07SMark Brown rdev->regmap = dev_get_regmap(dev, NULL); 528852b84dacSAnilKumar Ch else if (dev->parent) 528952b84dacSAnilKumar Ch rdev->regmap = dev_get_regmap(dev->parent, NULL); 5290414c70cbSLiam Girdwood INIT_LIST_HEAD(&rdev->consumer_list); 5291414c70cbSLiam Girdwood INIT_LIST_HEAD(&rdev->list); 5292414c70cbSLiam Girdwood BLOCKING_INIT_NOTIFIER_HEAD(&rdev->notifier); 5293da07ecd9SMark Brown INIT_DELAYED_WORK(&rdev->disable_work, regulator_disable_work); 5294414c70cbSLiam Girdwood 5295a5766f11SLiam Girdwood /* preform any regulator specific init */ 52969a8f5e07SMark Brown if (init_data && init_data->regulator_init) { 5297a5766f11SLiam Girdwood ret = init_data->regulator_init(rdev->reg_data); 52984fca9545SDavid Brownell if (ret < 0) 52994fca9545SDavid Brownell goto clean; 5300a5766f11SLiam Girdwood } 5301a5766f11SLiam Girdwood 5302541d052dSLinus Walleij if (config->ena_gpiod) { 5303daad134dSKrzysztof Adamski ret = regulator_ena_gpio_request(rdev, config); 5304daad134dSKrzysztof Adamski if (ret != 0) { 530561aab5adSMichał Mirosław rdev_err(rdev, "Failed to request enable GPIO: %pe\n", 530661aab5adSMichał Mirosław ERR_PTR(ret)); 530732165230SKrzysztof Adamski goto clean; 5308daad134dSKrzysztof Adamski } 53090edb040dSLinus Walleij /* The regulator core took over the GPIO descriptor */ 53100edb040dSLinus Walleij dangling_cfg_gpiod = false; 53110edb040dSLinus Walleij dangling_of_gpiod = false; 5312daad134dSKrzysztof Adamski } 5313daad134dSKrzysztof Adamski 5314a5766f11SLiam Girdwood /* register with sysfs */ 5315a5766f11SLiam Girdwood rdev->dev.class = ®ulator_class; 5316a5766f11SLiam Girdwood rdev->dev.parent = dev; 531772dca06fSAniroop Mathur dev_set_name(&rdev->dev, "regulator.%lu", 531839138818SAniroop Mathur (unsigned long) atomic_inc_return(®ulator_no)); 53199177514cSVladimir Zapolskiy dev_set_drvdata(&rdev->dev, rdev); 5320a5766f11SLiam Girdwood 532174f544c1SMike Rapoport /* set regulator constraints */ 53229a8f5e07SMark Brown if (init_data) 532357a6ad48SMichał Mirosław rdev->constraints = kmemdup(&init_data->constraints, 532457a6ad48SMichał Mirosław sizeof(*rdev->constraints), 532557a6ad48SMichał Mirosław GFP_KERNEL); 532657a6ad48SMichał Mirosław else 532757a6ad48SMichał Mirosław rdev->constraints = kzalloc(sizeof(*rdev->constraints), 532857a6ad48SMichał Mirosław GFP_KERNEL); 532957a6ad48SMichał Mirosław if (!rdev->constraints) { 533057a6ad48SMichał Mirosław ret = -ENOMEM; 533157a6ad48SMichał Mirosław goto wash; 533257a6ad48SMichał Mirosław } 53339a8f5e07SMark Brown 53349a8f5e07SMark Brown if (init_data && init_data->supply_regulator) 53356261b06dSBjorn Andersson rdev->supply_name = init_data->supply_regulator; 533669511a45SRajendra Nayak else if (regulator_desc->supply_name) 53376261b06dSBjorn Andersson rdev->supply_name = regulator_desc->supply_name; 533869511a45SRajendra Nayak 533957a6ad48SMichał Mirosław ret = set_machine_constraints(rdev); 5340aea6cb99SMichał Mirosław if (ret == -EPROBE_DEFER) { 5341aea6cb99SMichał Mirosław /* Regulator might be in bypass mode and so needs its supply 5342aea6cb99SMichał Mirosław * to set the constraints */ 5343aea6cb99SMichał Mirosław /* FIXME: this currently triggers a chicken-and-egg problem 5344aea6cb99SMichał Mirosław * when creating -SUPPLY symlink in sysfs to a regulator 5345aea6cb99SMichał Mirosław * that is just being created */ 53460917c9dbSMichał Mirosław rdev_dbg(rdev, "will resolve supply early: %s\n", 53470917c9dbSMichał Mirosław rdev->supply_name); 5348aea6cb99SMichał Mirosław ret = regulator_resolve_supply(rdev); 5349aea6cb99SMichał Mirosław if (!ret) 535057a6ad48SMichał Mirosław ret = set_machine_constraints(rdev); 5351aea6cb99SMichał Mirosław else 5352aea6cb99SMichał Mirosław rdev_dbg(rdev, "unable to resolve supply early: %pe\n", 5353aea6cb99SMichał Mirosław ERR_PTR(ret)); 5354aea6cb99SMichał Mirosław } 535545389c47SJon Hunter if (ret < 0) 535645389c47SJon Hunter goto wash; 535745389c47SJon Hunter 5358f9503385SDmitry Osipenko ret = regulator_init_coupling(rdev); 5359f9503385SDmitry Osipenko if (ret < 0) 5360d3d64537SMaciej Purski goto wash; 5361d3d64537SMaciej Purski 5362a5766f11SLiam Girdwood /* add consumers devices */ 53639a8f5e07SMark Brown if (init_data) { 5364a5766f11SLiam Girdwood for (i = 0; i < init_data->num_consumer_supplies; i++) { 5365a5766f11SLiam Girdwood ret = set_consumer_device_supply(rdev, 536640f9244fSMark Brown init_data->consumer_supplies[i].dev_name, 5367a5766f11SLiam Girdwood init_data->consumer_supplies[i].supply); 536823c2f041SMark Brown if (ret < 0) { 536923c2f041SMark Brown dev_err(dev, "Failed to set supply %s\n", 537023c2f041SMark Brown init_data->consumer_supplies[i].supply); 5371d4033b54SJani Nikula goto unset_supplies; 5372a5766f11SLiam Girdwood } 537323c2f041SMark Brown } 53749a8f5e07SMark Brown } 5375a5766f11SLiam Girdwood 5376fd086045SMatthias Kaehlcke if (!rdev->desc->ops->get_voltage && 5377fd086045SMatthias Kaehlcke !rdev->desc->ops->list_voltage && 5378fd086045SMatthias Kaehlcke !rdev->desc->fixed_uV) 5379fd086045SMatthias Kaehlcke rdev->is_switch = true; 5380fd086045SMatthias Kaehlcke 53819177514cSVladimir Zapolskiy ret = device_add(&rdev->dev); 53829177514cSVladimir Zapolskiy if (ret != 0) 5383c438b9d0SJon Hunter goto unset_supplies; 5384c438b9d0SJon Hunter 53851130e5b3SMark Brown rdev_init_debugfs(rdev); 53865e3ca2b3SJavier Martinez Canillas 5387f9503385SDmitry Osipenko /* try to resolve regulators coupling since a new one was registered */ 5388f9503385SDmitry Osipenko mutex_lock(®ulator_list_mutex); 5389f9503385SDmitry Osipenko regulator_resolve_coupling(rdev); 5390f9503385SDmitry Osipenko mutex_unlock(®ulator_list_mutex); 5391f9503385SDmitry Osipenko 53925e3ca2b3SJavier Martinez Canillas /* try to resolve regulators supply since a new one was registered */ 53935e3ca2b3SJavier Martinez Canillas class_for_each_device(®ulator_class, NULL, NULL, 53945e3ca2b3SJavier Martinez Canillas regulator_register_resolve_supply); 53951b3de223SKrzysztof Kozlowski kfree(config); 5396414c70cbSLiam Girdwood return rdev; 53974fca9545SDavid Brownell 5398d4033b54SJani Nikula unset_supplies: 539945389c47SJon Hunter mutex_lock(®ulator_list_mutex); 5400d4033b54SJani Nikula unset_regulator_supplies(rdev); 5401d8ca7d18SDmitry Osipenko regulator_remove_coupling(rdev); 540245389c47SJon Hunter mutex_unlock(®ulator_list_mutex); 540332165230SKrzysztof Adamski wash: 540426c2c997SDmitry Osipenko kfree(rdev->coupling_desc.coupled_rdevs); 540545389c47SJon Hunter mutex_lock(®ulator_list_mutex); 540632165230SKrzysztof Adamski regulator_ena_gpio_free(rdev); 540745389c47SJon Hunter mutex_unlock(®ulator_list_mutex); 54084fca9545SDavid Brownell clean: 54090edb040dSLinus Walleij if (dangling_of_gpiod) 54100edb040dSLinus Walleij gpiod_put(config->ena_gpiod); 5411a2151374SJon Hunter kfree(config); 5412d3c73156SMichał Mirosław put_device(&rdev->dev); 54130edb040dSLinus Walleij rinse: 54140edb040dSLinus Walleij if (dangling_cfg_gpiod) 54150edb040dSLinus Walleij gpiod_put(cfg->ena_gpiod); 5416a2151374SJon Hunter return ERR_PTR(ret); 5417414c70cbSLiam Girdwood } 5418414c70cbSLiam Girdwood EXPORT_SYMBOL_GPL(regulator_register); 5419414c70cbSLiam Girdwood 5420414c70cbSLiam Girdwood /** 5421414c70cbSLiam Girdwood * regulator_unregister - unregister regulator 542269279fb9SMark Brown * @rdev: regulator to unregister 5423414c70cbSLiam Girdwood * 5424414c70cbSLiam Girdwood * Called by regulator drivers to unregister a regulator. 5425414c70cbSLiam Girdwood */ 5426414c70cbSLiam Girdwood void regulator_unregister(struct regulator_dev *rdev) 5427414c70cbSLiam Girdwood { 5428414c70cbSLiam Girdwood if (rdev == NULL) 5429414c70cbSLiam Girdwood return; 5430414c70cbSLiam Girdwood 5431891636eaSMark Brown if (rdev->supply) { 5432891636eaSMark Brown while (rdev->use_count--) 5433891636eaSMark Brown regulator_disable(rdev->supply); 5434e032b376SMark Brown regulator_put(rdev->supply); 5435891636eaSMark Brown } 5436ff9b34b6SDmitry Osipenko 543706377301SCharles Keepax flush_work(&rdev->disable_work.work); 543806377301SCharles Keepax 5439414c70cbSLiam Girdwood mutex_lock(®ulator_list_mutex); 5440ff9b34b6SDmitry Osipenko 54411130e5b3SMark Brown debugfs_remove_recursive(rdev->debugfs); 54426bf87d17SMark Brown WARN_ON(rdev->open_count); 54436303f3e7SDmitry Osipenko regulator_remove_coupling(rdev); 54440f1d747bSMike Rapoport unset_regulator_supplies(rdev); 5445414c70cbSLiam Girdwood list_del(&rdev->list); 5446f19b00daSKim, Milo regulator_ena_gpio_free(rdev); 544758fb5cf5SLothar Waßmann device_unregister(&rdev->dev); 5448ff9b34b6SDmitry Osipenko 5449ff9b34b6SDmitry Osipenko mutex_unlock(®ulator_list_mutex); 5450414c70cbSLiam Girdwood } 5451414c70cbSLiam Girdwood EXPORT_SYMBOL_GPL(regulator_unregister); 5452414c70cbSLiam Girdwood 5453f7efad10SChunyan Zhang #ifdef CONFIG_SUSPEND 5454414c70cbSLiam Girdwood /** 54550380cf7dSpascal paillet * regulator_suspend - prepare regulators for system wide suspend 54561efef7ccSRandy Dunlap * @dev: ``&struct device`` pointer that is passed to _regulator_suspend() 5457414c70cbSLiam Girdwood * 5458414c70cbSLiam Girdwood * Configure each regulator with it's suspend operating parameters for state. 5459414c70cbSLiam Girdwood */ 54600380cf7dSpascal paillet static int regulator_suspend(struct device *dev) 5461414c70cbSLiam Girdwood { 5462cd7e36abSMarek Szyprowski struct regulator_dev *rdev = dev_to_rdev(dev); 5463f7efad10SChunyan Zhang suspend_state_t state = pm_suspend_target_state; 5464cd7e36abSMarek Szyprowski int ret; 54650955f5beSStephen Boyd const struct regulator_state *rstate; 54660955f5beSStephen Boyd 54670955f5beSStephen Boyd rstate = regulator_get_suspend_state_check(rdev, state); 54680955f5beSStephen Boyd if (!rstate) 54690955f5beSStephen Boyd return 0; 5470414c70cbSLiam Girdwood 5471cd7e36abSMarek Szyprowski regulator_lock(rdev); 54720955f5beSStephen Boyd ret = __suspend_set_state(rdev, rstate); 5473cd7e36abSMarek Szyprowski regulator_unlock(rdev); 5474cd7e36abSMarek Szyprowski 5475cd7e36abSMarek Szyprowski return ret; 5476414c70cbSLiam Girdwood } 5477d3e4eccbSMark Brown 5478cd7e36abSMarek Szyprowski static int regulator_resume(struct device *dev) 547985f3b431STomeu Vizoso { 5480cd7e36abSMarek Szyprowski suspend_state_t state = pm_suspend_target_state; 548185f3b431STomeu Vizoso struct regulator_dev *rdev = dev_to_rdev(dev); 5482f7efad10SChunyan Zhang struct regulator_state *rstate; 5483cd7e36abSMarek Szyprowski int ret = 0; 5484f7efad10SChunyan Zhang 5485cd7e36abSMarek Szyprowski rstate = regulator_get_suspend_state(rdev, state); 5486f7efad10SChunyan Zhang if (rstate == NULL) 548735b5f14eSGeert Uytterhoeven return 0; 548885f3b431STomeu Vizoso 54890955f5beSStephen Boyd /* Avoid grabbing the lock if we don't need to */ 54900955f5beSStephen Boyd if (!rdev->desc->ops->resume) 54910955f5beSStephen Boyd return 0; 54920955f5beSStephen Boyd 549366cf9a7eSMaciej Purski regulator_lock(rdev); 549485f3b431STomeu Vizoso 54950955f5beSStephen Boyd if (rstate->enabled == ENABLE_IN_SUSPEND || 54960955f5beSStephen Boyd rstate->enabled == DISABLE_IN_SUSPEND) 54970380cf7dSpascal paillet ret = rdev->desc->ops->resume(rdev); 5498f7efad10SChunyan Zhang 549966cf9a7eSMaciej Purski regulator_unlock(rdev); 550085f3b431STomeu Vizoso 5501f7efad10SChunyan Zhang return ret; 550285f3b431STomeu Vizoso } 5503f7efad10SChunyan Zhang #else /* !CONFIG_SUSPEND */ 5504f7efad10SChunyan Zhang 55050380cf7dSpascal paillet #define regulator_suspend NULL 55060380cf7dSpascal paillet #define regulator_resume NULL 5507f7efad10SChunyan Zhang 5508f7efad10SChunyan Zhang #endif /* !CONFIG_SUSPEND */ 5509f7efad10SChunyan Zhang 5510f7efad10SChunyan Zhang #ifdef CONFIG_PM 5511f7efad10SChunyan Zhang static const struct dev_pm_ops __maybe_unused regulator_pm_ops = { 55120380cf7dSpascal paillet .suspend = regulator_suspend, 55130380cf7dSpascal paillet .resume = regulator_resume, 5514f7efad10SChunyan Zhang }; 5515f7efad10SChunyan Zhang #endif 5516f7efad10SChunyan Zhang 5517285c22deSMark Brown struct class regulator_class = { 5518f7efad10SChunyan Zhang .name = "regulator", 5519f7efad10SChunyan Zhang .dev_release = regulator_dev_release, 5520f7efad10SChunyan Zhang .dev_groups = regulator_dev_groups, 5521f7efad10SChunyan Zhang #ifdef CONFIG_PM 5522f7efad10SChunyan Zhang .pm = ®ulator_pm_ops, 5523f7efad10SChunyan Zhang #endif 5524f7efad10SChunyan Zhang }; 55257a32b589SMyungJoo Ham /** 5526ca725561SMark Brown * regulator_has_full_constraints - the system has fully specified constraints 5527ca725561SMark Brown * 5528ca725561SMark Brown * Calling this function will cause the regulator API to disable all 5529ca725561SMark Brown * regulators which have a zero use count and don't have an always_on 5530ca725561SMark Brown * constraint in a late_initcall. 5531ca725561SMark Brown * 5532ca725561SMark Brown * The intention is that this will become the default behaviour in a 5533ca725561SMark Brown * future kernel release so users are encouraged to use this facility 5534ca725561SMark Brown * now. 5535ca725561SMark Brown */ 5536ca725561SMark Brown void regulator_has_full_constraints(void) 5537ca725561SMark Brown { 5538ca725561SMark Brown has_full_constraints = 1; 5539ca725561SMark Brown } 5540ca725561SMark Brown EXPORT_SYMBOL_GPL(regulator_has_full_constraints); 5541ca725561SMark Brown 5542ca725561SMark Brown /** 5543414c70cbSLiam Girdwood * rdev_get_drvdata - get rdev regulator driver data 554469279fb9SMark Brown * @rdev: regulator 5545414c70cbSLiam Girdwood * 5546414c70cbSLiam Girdwood * Get rdev regulator driver private data. This call can be used in the 5547414c70cbSLiam Girdwood * regulator driver context. 5548414c70cbSLiam Girdwood */ 5549414c70cbSLiam Girdwood void *rdev_get_drvdata(struct regulator_dev *rdev) 5550414c70cbSLiam Girdwood { 5551414c70cbSLiam Girdwood return rdev->reg_data; 5552414c70cbSLiam Girdwood } 5553414c70cbSLiam Girdwood EXPORT_SYMBOL_GPL(rdev_get_drvdata); 5554414c70cbSLiam Girdwood 5555414c70cbSLiam Girdwood /** 5556414c70cbSLiam Girdwood * regulator_get_drvdata - get regulator driver data 5557414c70cbSLiam Girdwood * @regulator: regulator 5558414c70cbSLiam Girdwood * 5559414c70cbSLiam Girdwood * Get regulator driver private data. This call can be used in the consumer 5560414c70cbSLiam Girdwood * driver context when non API regulator specific functions need to be called. 5561414c70cbSLiam Girdwood */ 5562414c70cbSLiam Girdwood void *regulator_get_drvdata(struct regulator *regulator) 5563414c70cbSLiam Girdwood { 5564414c70cbSLiam Girdwood return regulator->rdev->reg_data; 5565414c70cbSLiam Girdwood } 5566414c70cbSLiam Girdwood EXPORT_SYMBOL_GPL(regulator_get_drvdata); 5567414c70cbSLiam Girdwood 5568414c70cbSLiam Girdwood /** 5569414c70cbSLiam Girdwood * regulator_set_drvdata - set regulator driver data 5570414c70cbSLiam Girdwood * @regulator: regulator 5571414c70cbSLiam Girdwood * @data: data 5572414c70cbSLiam Girdwood */ 5573414c70cbSLiam Girdwood void regulator_set_drvdata(struct regulator *regulator, void *data) 5574414c70cbSLiam Girdwood { 5575414c70cbSLiam Girdwood regulator->rdev->reg_data = data; 5576414c70cbSLiam Girdwood } 5577414c70cbSLiam Girdwood EXPORT_SYMBOL_GPL(regulator_set_drvdata); 5578414c70cbSLiam Girdwood 5579414c70cbSLiam Girdwood /** 5580d73e873bSMauro Carvalho Chehab * rdev_get_id - get regulator ID 558169279fb9SMark Brown * @rdev: regulator 5582414c70cbSLiam Girdwood */ 5583414c70cbSLiam Girdwood int rdev_get_id(struct regulator_dev *rdev) 5584414c70cbSLiam Girdwood { 5585414c70cbSLiam Girdwood return rdev->desc->id; 5586414c70cbSLiam Girdwood } 5587414c70cbSLiam Girdwood EXPORT_SYMBOL_GPL(rdev_get_id); 5588414c70cbSLiam Girdwood 5589a5766f11SLiam Girdwood struct device *rdev_get_dev(struct regulator_dev *rdev) 5590a5766f11SLiam Girdwood { 5591a5766f11SLiam Girdwood return &rdev->dev; 5592a5766f11SLiam Girdwood } 5593a5766f11SLiam Girdwood EXPORT_SYMBOL_GPL(rdev_get_dev); 5594a5766f11SLiam Girdwood 559503c87b95SBartosz Golaszewski struct regmap *rdev_get_regmap(struct regulator_dev *rdev) 559603c87b95SBartosz Golaszewski { 559703c87b95SBartosz Golaszewski return rdev->regmap; 559803c87b95SBartosz Golaszewski } 559903c87b95SBartosz Golaszewski EXPORT_SYMBOL_GPL(rdev_get_regmap); 560003c87b95SBartosz Golaszewski 5601a5766f11SLiam Girdwood void *regulator_get_init_drvdata(struct regulator_init_data *reg_init_data) 5602a5766f11SLiam Girdwood { 5603a5766f11SLiam Girdwood return reg_init_data->driver_data; 5604a5766f11SLiam Girdwood } 5605a5766f11SLiam Girdwood EXPORT_SYMBOL_GPL(regulator_get_init_drvdata); 5606a5766f11SLiam Girdwood 5607ba55a974SMark Brown #ifdef CONFIG_DEBUG_FS 5608dbc55955SHaishan Zhou static int supply_map_show(struct seq_file *sf, void *data) 5609ba55a974SMark Brown { 5610ba55a974SMark Brown struct regulator_map *map; 5611ba55a974SMark Brown 5612ba55a974SMark Brown list_for_each_entry(map, ®ulator_map_list, list) { 5613dbc55955SHaishan Zhou seq_printf(sf, "%s -> %s.%s\n", 5614ba55a974SMark Brown rdev_get_name(map->regulator), map->dev_name, 5615ba55a974SMark Brown map->supply); 5616ba55a974SMark Brown } 5617ba55a974SMark Brown 5618dbc55955SHaishan Zhou return 0; 5619dbc55955SHaishan Zhou } 56203e60b4fcSYangtao Li DEFINE_SHOW_ATTRIBUTE(supply_map); 5621ba55a974SMark Brown 562285f3b431STomeu Vizoso struct summary_data { 562385f3b431STomeu Vizoso struct seq_file *s; 562485f3b431STomeu Vizoso struct regulator_dev *parent; 562585f3b431STomeu Vizoso int level; 562685f3b431STomeu Vizoso }; 562785f3b431STomeu Vizoso 562885f3b431STomeu Vizoso static void regulator_summary_show_subtree(struct seq_file *s, 562985f3b431STomeu Vizoso struct regulator_dev *rdev, 563085f3b431STomeu Vizoso int level); 563185f3b431STomeu Vizoso 563285f3b431STomeu Vizoso static int regulator_summary_show_children(struct device *dev, void *data) 563385f3b431STomeu Vizoso { 563485f3b431STomeu Vizoso struct regulator_dev *rdev = dev_to_rdev(dev); 563585f3b431STomeu Vizoso struct summary_data *summary_data = data; 563685f3b431STomeu Vizoso 563785f3b431STomeu Vizoso if (rdev->supply && rdev->supply->rdev == summary_data->parent) 563885f3b431STomeu Vizoso regulator_summary_show_subtree(summary_data->s, rdev, 563985f3b431STomeu Vizoso summary_data->level + 1); 564085f3b431STomeu Vizoso 564185f3b431STomeu Vizoso return 0; 564285f3b431STomeu Vizoso } 564385f3b431STomeu Vizoso 56447c225ec9SHeiko Stübner static void regulator_summary_show_subtree(struct seq_file *s, 56457c225ec9SHeiko Stübner struct regulator_dev *rdev, 56467c225ec9SHeiko Stübner int level) 56477c225ec9SHeiko Stübner { 56487c225ec9SHeiko Stübner struct regulation_constraints *c; 56497c225ec9SHeiko Stübner struct regulator *consumer; 565085f3b431STomeu Vizoso struct summary_data summary_data; 56517e4d9683SDouglas Anderson unsigned int opmode; 56527c225ec9SHeiko Stübner 56537c225ec9SHeiko Stübner if (!rdev) 56547c225ec9SHeiko Stübner return; 56557c225ec9SHeiko Stübner 56567e4d9683SDouglas Anderson opmode = _regulator_get_mode_unlocked(rdev); 565701de19d0SDouglas Anderson seq_printf(s, "%*s%-*s %3d %4d %6d %7s ", 56587c225ec9SHeiko Stübner level * 3 + 1, "", 56597c225ec9SHeiko Stübner 30 - level * 3, rdev_get_name(rdev), 566001de19d0SDouglas Anderson rdev->use_count, rdev->open_count, rdev->bypass_count, 56617e4d9683SDouglas Anderson regulator_opmode_to_str(opmode)); 56627c225ec9SHeiko Stübner 5663d22b85a1SDmitry Osipenko seq_printf(s, "%5dmV ", regulator_get_voltage_rdev(rdev) / 1000); 56647e4d9683SDouglas Anderson seq_printf(s, "%5dmA ", 56657e4d9683SDouglas Anderson _regulator_get_current_limit_unlocked(rdev) / 1000); 56667c225ec9SHeiko Stübner 56677c225ec9SHeiko Stübner c = rdev->constraints; 56687c225ec9SHeiko Stübner if (c) { 56697c225ec9SHeiko Stübner switch (rdev->desc->type) { 56707c225ec9SHeiko Stübner case REGULATOR_VOLTAGE: 56717c225ec9SHeiko Stübner seq_printf(s, "%5dmV %5dmV ", 56727c225ec9SHeiko Stübner c->min_uV / 1000, c->max_uV / 1000); 56737c225ec9SHeiko Stübner break; 56747c225ec9SHeiko Stübner case REGULATOR_CURRENT: 56757c225ec9SHeiko Stübner seq_printf(s, "%5dmA %5dmA ", 56767c225ec9SHeiko Stübner c->min_uA / 1000, c->max_uA / 1000); 56777c225ec9SHeiko Stübner break; 56787c225ec9SHeiko Stübner } 56797c225ec9SHeiko Stübner } 56807c225ec9SHeiko Stübner 56817c225ec9SHeiko Stübner seq_puts(s, "\n"); 56827c225ec9SHeiko Stübner 56837c225ec9SHeiko Stübner list_for_each_entry(consumer, &rdev->consumer_list, list) { 5684e42a46b6SLeonard Crestez if (consumer->dev && consumer->dev->class == ®ulator_class) 56857c225ec9SHeiko Stübner continue; 56867c225ec9SHeiko Stübner 56877c225ec9SHeiko Stübner seq_printf(s, "%*s%-*s ", 56887c225ec9SHeiko Stübner (level + 1) * 3 + 1, "", 5689e42a46b6SLeonard Crestez 30 - (level + 1) * 3, 56906b576eb0SMichał Mirosław consumer->supply_name ? consumer->supply_name : 5691e42a46b6SLeonard Crestez consumer->dev ? dev_name(consumer->dev) : "deviceless"); 56927c225ec9SHeiko Stübner 56937c225ec9SHeiko Stübner switch (rdev->desc->type) { 56947c225ec9SHeiko Stübner case REGULATOR_VOLTAGE: 56955451781dSDouglas Anderson seq_printf(s, "%3d %33dmA%c%5dmV %5dmV", 56965451781dSDouglas Anderson consumer->enable_count, 56977d3827b5SDouglas Anderson consumer->uA_load / 1000, 56985451781dSDouglas Anderson consumer->uA_load && !consumer->enable_count ? 56995451781dSDouglas Anderson '*' : ' ', 5700c360a6dfSChunyan Zhang consumer->voltage[PM_SUSPEND_ON].min_uV / 1000, 5701c360a6dfSChunyan Zhang consumer->voltage[PM_SUSPEND_ON].max_uV / 1000); 57027c225ec9SHeiko Stübner break; 57037c225ec9SHeiko Stübner case REGULATOR_CURRENT: 57047c225ec9SHeiko Stübner break; 57057c225ec9SHeiko Stübner } 57067c225ec9SHeiko Stübner 57077c225ec9SHeiko Stübner seq_puts(s, "\n"); 57087c225ec9SHeiko Stübner } 57097c225ec9SHeiko Stübner 571085f3b431STomeu Vizoso summary_data.s = s; 571185f3b431STomeu Vizoso summary_data.level = level; 571285f3b431STomeu Vizoso summary_data.parent = rdev; 57137c225ec9SHeiko Stübner 571485f3b431STomeu Vizoso class_for_each_device(®ulator_class, NULL, &summary_data, 571585f3b431STomeu Vizoso regulator_summary_show_children); 5716f8702f9eSDmitry Osipenko } 5717f8702f9eSDmitry Osipenko 5718f8702f9eSDmitry Osipenko struct summary_lock_data { 5719f8702f9eSDmitry Osipenko struct ww_acquire_ctx *ww_ctx; 5720f8702f9eSDmitry Osipenko struct regulator_dev **new_contended_rdev; 5721f8702f9eSDmitry Osipenko struct regulator_dev **old_contended_rdev; 5722f8702f9eSDmitry Osipenko }; 5723f8702f9eSDmitry Osipenko 5724f8702f9eSDmitry Osipenko static int regulator_summary_lock_one(struct device *dev, void *data) 5725f8702f9eSDmitry Osipenko { 5726f8702f9eSDmitry Osipenko struct regulator_dev *rdev = dev_to_rdev(dev); 5727f8702f9eSDmitry Osipenko struct summary_lock_data *lock_data = data; 5728f8702f9eSDmitry Osipenko int ret = 0; 5729f8702f9eSDmitry Osipenko 5730f8702f9eSDmitry Osipenko if (rdev != *lock_data->old_contended_rdev) { 5731f8702f9eSDmitry Osipenko ret = regulator_lock_nested(rdev, lock_data->ww_ctx); 5732f8702f9eSDmitry Osipenko 5733f8702f9eSDmitry Osipenko if (ret == -EDEADLK) 5734f8702f9eSDmitry Osipenko *lock_data->new_contended_rdev = rdev; 5735f8702f9eSDmitry Osipenko else 5736f8702f9eSDmitry Osipenko WARN_ON_ONCE(ret); 5737f8702f9eSDmitry Osipenko } else { 5738f8702f9eSDmitry Osipenko *lock_data->old_contended_rdev = NULL; 5739f8702f9eSDmitry Osipenko } 5740f8702f9eSDmitry Osipenko 5741f8702f9eSDmitry Osipenko return ret; 5742f8702f9eSDmitry Osipenko } 5743f8702f9eSDmitry Osipenko 5744f8702f9eSDmitry Osipenko static int regulator_summary_unlock_one(struct device *dev, void *data) 5745f8702f9eSDmitry Osipenko { 5746f8702f9eSDmitry Osipenko struct regulator_dev *rdev = dev_to_rdev(dev); 5747f8702f9eSDmitry Osipenko struct summary_lock_data *lock_data = data; 5748f8702f9eSDmitry Osipenko 5749f8702f9eSDmitry Osipenko if (lock_data) { 5750f8702f9eSDmitry Osipenko if (rdev == *lock_data->new_contended_rdev) 5751f8702f9eSDmitry Osipenko return -EDEADLK; 5752f8702f9eSDmitry Osipenko } 57537e4d9683SDouglas Anderson 57547e4d9683SDouglas Anderson regulator_unlock(rdev); 5755f8702f9eSDmitry Osipenko 5756f8702f9eSDmitry Osipenko return 0; 5757f8702f9eSDmitry Osipenko } 5758f8702f9eSDmitry Osipenko 5759f8702f9eSDmitry Osipenko static int regulator_summary_lock_all(struct ww_acquire_ctx *ww_ctx, 5760f8702f9eSDmitry Osipenko struct regulator_dev **new_contended_rdev, 5761f8702f9eSDmitry Osipenko struct regulator_dev **old_contended_rdev) 5762f8702f9eSDmitry Osipenko { 5763f8702f9eSDmitry Osipenko struct summary_lock_data lock_data; 5764f8702f9eSDmitry Osipenko int ret; 5765f8702f9eSDmitry Osipenko 5766f8702f9eSDmitry Osipenko lock_data.ww_ctx = ww_ctx; 5767f8702f9eSDmitry Osipenko lock_data.new_contended_rdev = new_contended_rdev; 5768f8702f9eSDmitry Osipenko lock_data.old_contended_rdev = old_contended_rdev; 5769f8702f9eSDmitry Osipenko 5770f8702f9eSDmitry Osipenko ret = class_for_each_device(®ulator_class, NULL, &lock_data, 5771f8702f9eSDmitry Osipenko regulator_summary_lock_one); 5772f8702f9eSDmitry Osipenko if (ret) 5773f8702f9eSDmitry Osipenko class_for_each_device(®ulator_class, NULL, &lock_data, 5774f8702f9eSDmitry Osipenko regulator_summary_unlock_one); 5775f8702f9eSDmitry Osipenko 5776f8702f9eSDmitry Osipenko return ret; 5777f8702f9eSDmitry Osipenko } 5778f8702f9eSDmitry Osipenko 5779f8702f9eSDmitry Osipenko static void regulator_summary_lock(struct ww_acquire_ctx *ww_ctx) 5780f8702f9eSDmitry Osipenko { 5781f8702f9eSDmitry Osipenko struct regulator_dev *new_contended_rdev = NULL; 5782f8702f9eSDmitry Osipenko struct regulator_dev *old_contended_rdev = NULL; 5783f8702f9eSDmitry Osipenko int err; 5784f8702f9eSDmitry Osipenko 5785ff9b34b6SDmitry Osipenko mutex_lock(®ulator_list_mutex); 5786ff9b34b6SDmitry Osipenko 5787f8702f9eSDmitry Osipenko ww_acquire_init(ww_ctx, ®ulator_ww_class); 5788f8702f9eSDmitry Osipenko 5789f8702f9eSDmitry Osipenko do { 5790f8702f9eSDmitry Osipenko if (new_contended_rdev) { 5791f8702f9eSDmitry Osipenko ww_mutex_lock_slow(&new_contended_rdev->mutex, ww_ctx); 5792f8702f9eSDmitry Osipenko old_contended_rdev = new_contended_rdev; 5793f8702f9eSDmitry Osipenko old_contended_rdev->ref_cnt++; 5794f8702f9eSDmitry Osipenko } 5795f8702f9eSDmitry Osipenko 5796f8702f9eSDmitry Osipenko err = regulator_summary_lock_all(ww_ctx, 5797f8702f9eSDmitry Osipenko &new_contended_rdev, 5798f8702f9eSDmitry Osipenko &old_contended_rdev); 5799f8702f9eSDmitry Osipenko 5800f8702f9eSDmitry Osipenko if (old_contended_rdev) 5801f8702f9eSDmitry Osipenko regulator_unlock(old_contended_rdev); 5802f8702f9eSDmitry Osipenko 5803f8702f9eSDmitry Osipenko } while (err == -EDEADLK); 5804f8702f9eSDmitry Osipenko 5805f8702f9eSDmitry Osipenko ww_acquire_done(ww_ctx); 5806f8702f9eSDmitry Osipenko } 5807f8702f9eSDmitry Osipenko 5808f8702f9eSDmitry Osipenko static void regulator_summary_unlock(struct ww_acquire_ctx *ww_ctx) 5809f8702f9eSDmitry Osipenko { 5810f8702f9eSDmitry Osipenko class_for_each_device(®ulator_class, NULL, NULL, 5811f8702f9eSDmitry Osipenko regulator_summary_unlock_one); 5812f8702f9eSDmitry Osipenko ww_acquire_fini(ww_ctx); 5813ff9b34b6SDmitry Osipenko 5814ff9b34b6SDmitry Osipenko mutex_unlock(®ulator_list_mutex); 58157c225ec9SHeiko Stübner } 581685f3b431STomeu Vizoso 581785f3b431STomeu Vizoso static int regulator_summary_show_roots(struct device *dev, void *data) 581885f3b431STomeu Vizoso { 581985f3b431STomeu Vizoso struct regulator_dev *rdev = dev_to_rdev(dev); 582085f3b431STomeu Vizoso struct seq_file *s = data; 582185f3b431STomeu Vizoso 582285f3b431STomeu Vizoso if (!rdev->supply) 582385f3b431STomeu Vizoso regulator_summary_show_subtree(s, rdev, 0); 582485f3b431STomeu Vizoso 582585f3b431STomeu Vizoso return 0; 58267c225ec9SHeiko Stübner } 58277c225ec9SHeiko Stübner 58287c225ec9SHeiko Stübner static int regulator_summary_show(struct seq_file *s, void *data) 58297c225ec9SHeiko Stübner { 5830f8702f9eSDmitry Osipenko struct ww_acquire_ctx ww_ctx; 5831f8702f9eSDmitry Osipenko 583201de19d0SDouglas Anderson seq_puts(s, " regulator use open bypass opmode voltage current min max\n"); 583301de19d0SDouglas Anderson seq_puts(s, "---------------------------------------------------------------------------------------\n"); 58347c225ec9SHeiko Stübner 5835f8702f9eSDmitry Osipenko regulator_summary_lock(&ww_ctx); 5836f8702f9eSDmitry Osipenko 583785f3b431STomeu Vizoso class_for_each_device(®ulator_class, NULL, s, 583885f3b431STomeu Vizoso regulator_summary_show_roots); 58397c225ec9SHeiko Stübner 5840f8702f9eSDmitry Osipenko regulator_summary_unlock(&ww_ctx); 5841f8702f9eSDmitry Osipenko 58427c225ec9SHeiko Stübner return 0; 58437c225ec9SHeiko Stübner } 58443e60b4fcSYangtao Li DEFINE_SHOW_ATTRIBUTE(regulator_summary); 58453e60b4fcSYangtao Li #endif /* CONFIG_DEBUG_FS */ 58467c225ec9SHeiko Stübner 5847414c70cbSLiam Girdwood static int __init regulator_init(void) 5848414c70cbSLiam Girdwood { 584934abbd68SMark Brown int ret; 585034abbd68SMark Brown 585134abbd68SMark Brown ret = class_register(®ulator_class); 585234abbd68SMark Brown 58531130e5b3SMark Brown debugfs_root = debugfs_create_dir("regulator", NULL); 585424751434SStephen Boyd if (!debugfs_root) 58551130e5b3SMark Brown pr_warn("regulator: Failed to create debugfs directory\n"); 5856ba55a974SMark Brown 58573e60b4fcSYangtao Li #ifdef CONFIG_DEBUG_FS 5858f4d562c6SMark Brown debugfs_create_file("supply_map", 0444, debugfs_root, NULL, 5859f4d562c6SMark Brown &supply_map_fops); 58601130e5b3SMark Brown 58617c225ec9SHeiko Stübner debugfs_create_file("regulator_summary", 0444, debugfs_root, 586285f3b431STomeu Vizoso NULL, ®ulator_summary_fops); 58633e60b4fcSYangtao Li #endif 586434abbd68SMark Brown regulator_dummy_init(); 586534abbd68SMark Brown 5866d8ca7d18SDmitry Osipenko regulator_coupler_register(&generic_regulator_coupler); 5867d8ca7d18SDmitry Osipenko 586834abbd68SMark Brown return ret; 5869414c70cbSLiam Girdwood } 5870414c70cbSLiam Girdwood 5871414c70cbSLiam Girdwood /* init early to allow our consumers to complete system booting */ 5872414c70cbSLiam Girdwood core_initcall(regulator_init); 5873ca725561SMark Brown 587455576cf1SMark Brown static int regulator_late_cleanup(struct device *dev, void *data) 5875ca725561SMark Brown { 5876609ca5f3SMark Brown struct regulator_dev *rdev = dev_to_rdev(dev); 5877609ca5f3SMark Brown const struct regulator_ops *ops = rdev->desc->ops; 5878609ca5f3SMark Brown struct regulation_constraints *c = rdev->constraints; 5879ca725561SMark Brown int enabled, ret; 5880ca725561SMark Brown 588166fda75fSMarkus Pargmann if (c && c->always_on) 5882609ca5f3SMark Brown return 0; 5883ca725561SMark Brown 58848a34e979SWEN Pingbo if (!regulator_ops_is_valid(rdev, REGULATOR_CHANGE_STATUS)) 5885609ca5f3SMark Brown return 0; 5886e9535834SMark Brown 588766cf9a7eSMaciej Purski regulator_lock(rdev); 5888ca725561SMark Brown 5889ca725561SMark Brown if (rdev->use_count) 5890ca725561SMark Brown goto unlock; 5891ca725561SMark Brown 5892c088a498SPi-Hsun Shih /* If we can't read the status assume it's always on. */ 5893ca725561SMark Brown if (ops->is_enabled) 5894ca725561SMark Brown enabled = ops->is_enabled(rdev); 5895ca725561SMark Brown else 5896ca725561SMark Brown enabled = 1; 5897ca725561SMark Brown 5898c088a498SPi-Hsun Shih /* But if reading the status failed, assume that it's off. */ 5899c088a498SPi-Hsun Shih if (enabled <= 0) 5900ca725561SMark Brown goto unlock; 5901ca725561SMark Brown 590287b28417SMark Brown if (have_full_constraints()) { 5903609ca5f3SMark Brown /* We log since this may kill the system if it goes 5904609ca5f3SMark Brown * wrong. */ 59055da84fd9SJoe Perches rdev_info(rdev, "disabling\n"); 590666fda75fSMarkus Pargmann ret = _regulator_do_disable(rdev); 59070d25d09dSJingoo Han if (ret != 0) 590861aab5adSMichał Mirosław rdev_err(rdev, "couldn't disable: %pe\n", ERR_PTR(ret)); 5909ca725561SMark Brown } else { 5910ca725561SMark Brown /* The intention is that in future we will 5911ca725561SMark Brown * assume that full constraints are provided 5912ca725561SMark Brown * so warn even if we aren't going to do 5913ca725561SMark Brown * anything here. 5914ca725561SMark Brown */ 59155da84fd9SJoe Perches rdev_warn(rdev, "incomplete constraints, leaving on\n"); 5916ca725561SMark Brown } 5917ca725561SMark Brown 5918ca725561SMark Brown unlock: 591966cf9a7eSMaciej Purski regulator_unlock(rdev); 5920609ca5f3SMark Brown 5921609ca5f3SMark Brown return 0; 5922ca725561SMark Brown } 5923ca725561SMark Brown 592455576cf1SMark Brown static void regulator_init_complete_work_function(struct work_struct *work) 5925609ca5f3SMark Brown { 5926609ca5f3SMark Brown /* 59273827b64dSJavier Martinez Canillas * Regulators may had failed to resolve their input supplies 59283827b64dSJavier Martinez Canillas * when were registered, either because the input supply was 59293827b64dSJavier Martinez Canillas * not registered yet or because its parent device was not 59303827b64dSJavier Martinez Canillas * bound yet. So attempt to resolve the input supplies for 59313827b64dSJavier Martinez Canillas * pending regulators before trying to disable unused ones. 59323827b64dSJavier Martinez Canillas */ 59333827b64dSJavier Martinez Canillas class_for_each_device(®ulator_class, NULL, NULL, 59343827b64dSJavier Martinez Canillas regulator_register_resolve_supply); 59353827b64dSJavier Martinez Canillas 5936609ca5f3SMark Brown /* If we have a full configuration then disable any regulators 5937609ca5f3SMark Brown * we have permission to change the status for and which are 5938609ca5f3SMark Brown * not in use or always_on. This is effectively the default 5939609ca5f3SMark Brown * for DT and ACPI as they have full constraints. 5940609ca5f3SMark Brown */ 5941609ca5f3SMark Brown class_for_each_device(®ulator_class, NULL, NULL, 5942609ca5f3SMark Brown regulator_late_cleanup); 594355576cf1SMark Brown } 594455576cf1SMark Brown 594555576cf1SMark Brown static DECLARE_DELAYED_WORK(regulator_init_complete_work, 594655576cf1SMark Brown regulator_init_complete_work_function); 594755576cf1SMark Brown 594855576cf1SMark Brown static int __init regulator_init_complete(void) 594955576cf1SMark Brown { 595055576cf1SMark Brown /* 595155576cf1SMark Brown * Since DT doesn't provide an idiomatic mechanism for 595255576cf1SMark Brown * enabling full constraints and since it's much more natural 595355576cf1SMark Brown * with DT to provide them just assume that a DT enabled 595455576cf1SMark Brown * system has full constraints. 595555576cf1SMark Brown */ 595655576cf1SMark Brown if (of_have_populated_dt()) 595755576cf1SMark Brown has_full_constraints = true; 595855576cf1SMark Brown 595955576cf1SMark Brown /* 59602a15483bSJohn Stultz * We punt completion for an arbitrary amount of time since 59612a15483bSJohn Stultz * systems like distros will load many drivers from userspace 59622a15483bSJohn Stultz * so consumers might not always be ready yet, this is 59632a15483bSJohn Stultz * particularly an issue with laptops where this might bounce 59642a15483bSJohn Stultz * the display off then on. Ideally we'd get a notification 59652a15483bSJohn Stultz * from userspace when this happens but we don't so just wait 59662a15483bSJohn Stultz * a bit and hope we waited long enough. It'd be better if 59672a15483bSJohn Stultz * we'd only do this on systems that need it, and a kernel 59682a15483bSJohn Stultz * command line option might be useful. 596955576cf1SMark Brown */ 59702a15483bSJohn Stultz schedule_delayed_work(®ulator_init_complete_work, 59712a15483bSJohn Stultz msecs_to_jiffies(30000)); 5972ca725561SMark Brown 5973ca725561SMark Brown return 0; 5974ca725561SMark Brown } 5975fd482a3eSSaravana Kannan late_initcall_sync(regulator_init_complete); 5976