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 54169b8821eSShubhankar Kuranagatti * try higher modes. 54269b8821eSShubhankar Kuranagatti */ 5432c608234SMark Brown while (*mode) { 5442c608234SMark Brown if (rdev->constraints->valid_modes_mask & *mode) 545414c70cbSLiam Girdwood return 0; 5462c608234SMark Brown *mode /= 2; 5472c608234SMark Brown } 5482c608234SMark Brown 5492c608234SMark Brown return -EINVAL; 550414c70cbSLiam Girdwood } 551414c70cbSLiam Girdwood 552f7efad10SChunyan Zhang static inline struct regulator_state * 553f7efad10SChunyan Zhang regulator_get_suspend_state(struct regulator_dev *rdev, suspend_state_t state) 554f7efad10SChunyan Zhang { 555f7efad10SChunyan Zhang if (rdev->constraints == NULL) 556f7efad10SChunyan Zhang return NULL; 557f7efad10SChunyan Zhang 558f7efad10SChunyan Zhang switch (state) { 559f7efad10SChunyan Zhang case PM_SUSPEND_STANDBY: 560f7efad10SChunyan Zhang return &rdev->constraints->state_standby; 561f7efad10SChunyan Zhang case PM_SUSPEND_MEM: 562f7efad10SChunyan Zhang return &rdev->constraints->state_mem; 563f7efad10SChunyan Zhang case PM_SUSPEND_MAX: 564f7efad10SChunyan Zhang return &rdev->constraints->state_disk; 565f7efad10SChunyan Zhang default: 566f7efad10SChunyan Zhang return NULL; 567f7efad10SChunyan Zhang } 568f7efad10SChunyan Zhang } 569f7efad10SChunyan Zhang 5700955f5beSStephen Boyd static const struct regulator_state * 5710955f5beSStephen Boyd regulator_get_suspend_state_check(struct regulator_dev *rdev, suspend_state_t state) 5720955f5beSStephen Boyd { 5730955f5beSStephen Boyd const struct regulator_state *rstate; 5740955f5beSStephen Boyd 5750955f5beSStephen Boyd rstate = regulator_get_suspend_state(rdev, state); 5760955f5beSStephen Boyd if (rstate == NULL) 5770955f5beSStephen Boyd return NULL; 5780955f5beSStephen Boyd 5790955f5beSStephen Boyd /* If we have no suspend mode configuration don't set anything; 5800955f5beSStephen Boyd * only warn if the driver implements set_suspend_voltage or 5810955f5beSStephen Boyd * set_suspend_mode callback. 5820955f5beSStephen Boyd */ 5830955f5beSStephen Boyd if (rstate->enabled != ENABLE_IN_SUSPEND && 5840955f5beSStephen Boyd rstate->enabled != DISABLE_IN_SUSPEND) { 5850955f5beSStephen Boyd if (rdev->desc->ops->set_suspend_voltage || 5860955f5beSStephen Boyd rdev->desc->ops->set_suspend_mode) 5870955f5beSStephen Boyd rdev_warn(rdev, "No configuration\n"); 5880955f5beSStephen Boyd return NULL; 5890955f5beSStephen Boyd } 5900955f5beSStephen Boyd 5910955f5beSStephen Boyd return rstate; 5920955f5beSStephen Boyd } 5930955f5beSStephen Boyd 594414c70cbSLiam Girdwood static ssize_t regulator_uV_show(struct device *dev, 595414c70cbSLiam Girdwood struct device_attribute *attr, char *buf) 596414c70cbSLiam Girdwood { 597a5766f11SLiam Girdwood struct regulator_dev *rdev = dev_get_drvdata(dev); 598c82f27dfSH. Nikolaus Schaller int uV; 599414c70cbSLiam Girdwood 60066cf9a7eSMaciej Purski regulator_lock(rdev); 601c82f27dfSH. Nikolaus Schaller uV = regulator_get_voltage_rdev(rdev); 60266cf9a7eSMaciej Purski regulator_unlock(rdev); 603414c70cbSLiam Girdwood 604c82f27dfSH. Nikolaus Schaller if (uV < 0) 605c82f27dfSH. Nikolaus Schaller return uV; 606c82f27dfSH. Nikolaus Schaller return sprintf(buf, "%d\n", uV); 607414c70cbSLiam Girdwood } 6087ad68e2fSDavid Brownell static DEVICE_ATTR(microvolts, 0444, regulator_uV_show, NULL); 609414c70cbSLiam Girdwood 610414c70cbSLiam Girdwood static ssize_t regulator_uA_show(struct device *dev, 611414c70cbSLiam Girdwood struct device_attribute *attr, char *buf) 612414c70cbSLiam Girdwood { 613a5766f11SLiam Girdwood struct regulator_dev *rdev = dev_get_drvdata(dev); 614414c70cbSLiam Girdwood 615414c70cbSLiam Girdwood return sprintf(buf, "%d\n", _regulator_get_current_limit(rdev)); 616414c70cbSLiam Girdwood } 6177ad68e2fSDavid Brownell static DEVICE_ATTR(microamps, 0444, regulator_uA_show, NULL); 618414c70cbSLiam Girdwood 619587cea27SGreg Kroah-Hartman static ssize_t name_show(struct device *dev, struct device_attribute *attr, 620587cea27SGreg Kroah-Hartman char *buf) 621bc558a60SMark Brown { 622bc558a60SMark Brown struct regulator_dev *rdev = dev_get_drvdata(dev); 623bc558a60SMark Brown 6241083c393SMark Brown return sprintf(buf, "%s\n", rdev_get_name(rdev)); 625bc558a60SMark Brown } 626587cea27SGreg Kroah-Hartman static DEVICE_ATTR_RO(name); 627bc558a60SMark Brown 62801de19d0SDouglas Anderson static const char *regulator_opmode_to_str(int mode) 629414c70cbSLiam Girdwood { 630414c70cbSLiam Girdwood switch (mode) { 631414c70cbSLiam Girdwood case REGULATOR_MODE_FAST: 63201de19d0SDouglas Anderson return "fast"; 633414c70cbSLiam Girdwood case REGULATOR_MODE_NORMAL: 63401de19d0SDouglas Anderson return "normal"; 635414c70cbSLiam Girdwood case REGULATOR_MODE_IDLE: 63601de19d0SDouglas Anderson return "idle"; 637414c70cbSLiam Girdwood case REGULATOR_MODE_STANDBY: 63801de19d0SDouglas Anderson return "standby"; 639414c70cbSLiam Girdwood } 64001de19d0SDouglas Anderson return "unknown"; 64101de19d0SDouglas Anderson } 64201de19d0SDouglas Anderson 64301de19d0SDouglas Anderson static ssize_t regulator_print_opmode(char *buf, int mode) 64401de19d0SDouglas Anderson { 64501de19d0SDouglas Anderson return sprintf(buf, "%s\n", regulator_opmode_to_str(mode)); 646414c70cbSLiam Girdwood } 647414c70cbSLiam Girdwood 6484fca9545SDavid Brownell static ssize_t regulator_opmode_show(struct device *dev, 649414c70cbSLiam Girdwood struct device_attribute *attr, char *buf) 650414c70cbSLiam Girdwood { 651a5766f11SLiam Girdwood struct regulator_dev *rdev = dev_get_drvdata(dev); 652414c70cbSLiam Girdwood 6534fca9545SDavid Brownell return regulator_print_opmode(buf, _regulator_get_mode(rdev)); 6544fca9545SDavid Brownell } 6557ad68e2fSDavid Brownell static DEVICE_ATTR(opmode, 0444, regulator_opmode_show, NULL); 6564fca9545SDavid Brownell 6574fca9545SDavid Brownell static ssize_t regulator_print_state(char *buf, int state) 6584fca9545SDavid Brownell { 659414c70cbSLiam Girdwood if (state > 0) 660414c70cbSLiam Girdwood return sprintf(buf, "enabled\n"); 661414c70cbSLiam Girdwood else if (state == 0) 662414c70cbSLiam Girdwood return sprintf(buf, "disabled\n"); 663414c70cbSLiam Girdwood else 664414c70cbSLiam Girdwood return sprintf(buf, "unknown\n"); 665414c70cbSLiam Girdwood } 666414c70cbSLiam Girdwood 6674fca9545SDavid Brownell static ssize_t regulator_state_show(struct device *dev, 6684fca9545SDavid Brownell struct device_attribute *attr, char *buf) 6694fca9545SDavid Brownell { 6704fca9545SDavid Brownell struct regulator_dev *rdev = dev_get_drvdata(dev); 6719332546fSMark Brown ssize_t ret; 6724fca9545SDavid Brownell 67366cf9a7eSMaciej Purski regulator_lock(rdev); 6749332546fSMark Brown ret = regulator_print_state(buf, _regulator_is_enabled(rdev)); 67566cf9a7eSMaciej Purski regulator_unlock(rdev); 6769332546fSMark Brown 6779332546fSMark Brown return ret; 6784fca9545SDavid Brownell } 6797ad68e2fSDavid Brownell static DEVICE_ATTR(state, 0444, regulator_state_show, NULL); 6804fca9545SDavid Brownell 681853116a1SDavid Brownell static ssize_t regulator_status_show(struct device *dev, 682853116a1SDavid Brownell struct device_attribute *attr, char *buf) 683853116a1SDavid Brownell { 684853116a1SDavid Brownell struct regulator_dev *rdev = dev_get_drvdata(dev); 685853116a1SDavid Brownell int status; 686853116a1SDavid Brownell char *label; 687853116a1SDavid Brownell 688853116a1SDavid Brownell status = rdev->desc->ops->get_status(rdev); 689853116a1SDavid Brownell if (status < 0) 690853116a1SDavid Brownell return status; 691853116a1SDavid Brownell 692853116a1SDavid Brownell switch (status) { 693853116a1SDavid Brownell case REGULATOR_STATUS_OFF: 694853116a1SDavid Brownell label = "off"; 695853116a1SDavid Brownell break; 696853116a1SDavid Brownell case REGULATOR_STATUS_ON: 697853116a1SDavid Brownell label = "on"; 698853116a1SDavid Brownell break; 699853116a1SDavid Brownell case REGULATOR_STATUS_ERROR: 700853116a1SDavid Brownell label = "error"; 701853116a1SDavid Brownell break; 702853116a1SDavid Brownell case REGULATOR_STATUS_FAST: 703853116a1SDavid Brownell label = "fast"; 704853116a1SDavid Brownell break; 705853116a1SDavid Brownell case REGULATOR_STATUS_NORMAL: 706853116a1SDavid Brownell label = "normal"; 707853116a1SDavid Brownell break; 708853116a1SDavid Brownell case REGULATOR_STATUS_IDLE: 709853116a1SDavid Brownell label = "idle"; 710853116a1SDavid Brownell break; 711853116a1SDavid Brownell case REGULATOR_STATUS_STANDBY: 712853116a1SDavid Brownell label = "standby"; 713853116a1SDavid Brownell break; 714f59c8f9fSMark Brown case REGULATOR_STATUS_BYPASS: 715f59c8f9fSMark Brown label = "bypass"; 716f59c8f9fSMark Brown break; 7171beaf762SKrystian Garbaciak case REGULATOR_STATUS_UNDEFINED: 7181beaf762SKrystian Garbaciak label = "undefined"; 7191beaf762SKrystian Garbaciak break; 720853116a1SDavid Brownell default: 721853116a1SDavid Brownell return -ERANGE; 722853116a1SDavid Brownell } 723853116a1SDavid Brownell 724853116a1SDavid Brownell return sprintf(buf, "%s\n", label); 725853116a1SDavid Brownell } 726853116a1SDavid Brownell static DEVICE_ATTR(status, 0444, regulator_status_show, NULL); 727853116a1SDavid Brownell 728414c70cbSLiam Girdwood static ssize_t regulator_min_uA_show(struct device *dev, 729414c70cbSLiam Girdwood struct device_attribute *attr, char *buf) 730414c70cbSLiam Girdwood { 731a5766f11SLiam Girdwood struct regulator_dev *rdev = dev_get_drvdata(dev); 732414c70cbSLiam Girdwood 733414c70cbSLiam Girdwood if (!rdev->constraints) 734414c70cbSLiam Girdwood return sprintf(buf, "constraint not defined\n"); 735414c70cbSLiam Girdwood 736414c70cbSLiam Girdwood return sprintf(buf, "%d\n", rdev->constraints->min_uA); 737414c70cbSLiam Girdwood } 7387ad68e2fSDavid Brownell static DEVICE_ATTR(min_microamps, 0444, regulator_min_uA_show, NULL); 739414c70cbSLiam Girdwood 740414c70cbSLiam Girdwood static ssize_t regulator_max_uA_show(struct device *dev, 741414c70cbSLiam Girdwood struct device_attribute *attr, char *buf) 742414c70cbSLiam Girdwood { 743a5766f11SLiam Girdwood struct regulator_dev *rdev = dev_get_drvdata(dev); 744414c70cbSLiam Girdwood 745414c70cbSLiam Girdwood if (!rdev->constraints) 746414c70cbSLiam Girdwood return sprintf(buf, "constraint not defined\n"); 747414c70cbSLiam Girdwood 748414c70cbSLiam Girdwood return sprintf(buf, "%d\n", rdev->constraints->max_uA); 749414c70cbSLiam Girdwood } 7507ad68e2fSDavid Brownell static DEVICE_ATTR(max_microamps, 0444, regulator_max_uA_show, NULL); 751414c70cbSLiam Girdwood 752414c70cbSLiam Girdwood static ssize_t regulator_min_uV_show(struct device *dev, 753414c70cbSLiam Girdwood struct device_attribute *attr, char *buf) 754414c70cbSLiam Girdwood { 755a5766f11SLiam Girdwood struct regulator_dev *rdev = dev_get_drvdata(dev); 756414c70cbSLiam Girdwood 757414c70cbSLiam Girdwood if (!rdev->constraints) 758414c70cbSLiam Girdwood return sprintf(buf, "constraint not defined\n"); 759414c70cbSLiam Girdwood 760414c70cbSLiam Girdwood return sprintf(buf, "%d\n", rdev->constraints->min_uV); 761414c70cbSLiam Girdwood } 7627ad68e2fSDavid Brownell static DEVICE_ATTR(min_microvolts, 0444, regulator_min_uV_show, NULL); 763414c70cbSLiam Girdwood 764414c70cbSLiam Girdwood static ssize_t regulator_max_uV_show(struct device *dev, 765414c70cbSLiam Girdwood struct device_attribute *attr, char *buf) 766414c70cbSLiam Girdwood { 767a5766f11SLiam Girdwood struct regulator_dev *rdev = dev_get_drvdata(dev); 768414c70cbSLiam Girdwood 769414c70cbSLiam Girdwood if (!rdev->constraints) 770414c70cbSLiam Girdwood return sprintf(buf, "constraint not defined\n"); 771414c70cbSLiam Girdwood 772414c70cbSLiam Girdwood return sprintf(buf, "%d\n", rdev->constraints->max_uV); 773414c70cbSLiam Girdwood } 7747ad68e2fSDavid Brownell static DEVICE_ATTR(max_microvolts, 0444, regulator_max_uV_show, NULL); 775414c70cbSLiam Girdwood 776414c70cbSLiam Girdwood static ssize_t regulator_total_uA_show(struct device *dev, 777414c70cbSLiam Girdwood struct device_attribute *attr, char *buf) 778414c70cbSLiam Girdwood { 779a5766f11SLiam Girdwood struct regulator_dev *rdev = dev_get_drvdata(dev); 780414c70cbSLiam Girdwood struct regulator *regulator; 781414c70cbSLiam Girdwood int uA = 0; 782414c70cbSLiam Girdwood 78366cf9a7eSMaciej Purski regulator_lock(rdev); 7845451781dSDouglas Anderson list_for_each_entry(regulator, &rdev->consumer_list, list) { 7855451781dSDouglas Anderson if (regulator->enable_count) 786414c70cbSLiam Girdwood uA += regulator->uA_load; 7875451781dSDouglas Anderson } 78866cf9a7eSMaciej Purski regulator_unlock(rdev); 789414c70cbSLiam Girdwood return sprintf(buf, "%d\n", uA); 790414c70cbSLiam Girdwood } 7917ad68e2fSDavid Brownell static DEVICE_ATTR(requested_microamps, 0444, regulator_total_uA_show, NULL); 792414c70cbSLiam Girdwood 793587cea27SGreg Kroah-Hartman static ssize_t num_users_show(struct device *dev, struct device_attribute *attr, 794587cea27SGreg Kroah-Hartman char *buf) 795414c70cbSLiam Girdwood { 796a5766f11SLiam Girdwood struct regulator_dev *rdev = dev_get_drvdata(dev); 797414c70cbSLiam Girdwood return sprintf(buf, "%d\n", rdev->use_count); 798414c70cbSLiam Girdwood } 799587cea27SGreg Kroah-Hartman static DEVICE_ATTR_RO(num_users); 800414c70cbSLiam Girdwood 801587cea27SGreg Kroah-Hartman static ssize_t type_show(struct device *dev, struct device_attribute *attr, 802587cea27SGreg Kroah-Hartman char *buf) 803414c70cbSLiam Girdwood { 804a5766f11SLiam Girdwood struct regulator_dev *rdev = dev_get_drvdata(dev); 805414c70cbSLiam Girdwood 806414c70cbSLiam Girdwood switch (rdev->desc->type) { 807414c70cbSLiam Girdwood case REGULATOR_VOLTAGE: 808414c70cbSLiam Girdwood return sprintf(buf, "voltage\n"); 809414c70cbSLiam Girdwood case REGULATOR_CURRENT: 810414c70cbSLiam Girdwood return sprintf(buf, "current\n"); 811414c70cbSLiam Girdwood } 812414c70cbSLiam Girdwood return sprintf(buf, "unknown\n"); 813414c70cbSLiam Girdwood } 814587cea27SGreg Kroah-Hartman static DEVICE_ATTR_RO(type); 815414c70cbSLiam Girdwood 816414c70cbSLiam Girdwood static ssize_t regulator_suspend_mem_uV_show(struct device *dev, 817414c70cbSLiam Girdwood struct device_attribute *attr, char *buf) 818414c70cbSLiam Girdwood { 819a5766f11SLiam Girdwood struct regulator_dev *rdev = dev_get_drvdata(dev); 820414c70cbSLiam Girdwood 821414c70cbSLiam Girdwood return sprintf(buf, "%d\n", rdev->constraints->state_mem.uV); 822414c70cbSLiam Girdwood } 8237ad68e2fSDavid Brownell static DEVICE_ATTR(suspend_mem_microvolts, 0444, 8247ad68e2fSDavid Brownell regulator_suspend_mem_uV_show, NULL); 825414c70cbSLiam Girdwood 826414c70cbSLiam Girdwood static ssize_t regulator_suspend_disk_uV_show(struct device *dev, 827414c70cbSLiam Girdwood struct device_attribute *attr, char *buf) 828414c70cbSLiam Girdwood { 829a5766f11SLiam Girdwood struct regulator_dev *rdev = dev_get_drvdata(dev); 830414c70cbSLiam Girdwood 831414c70cbSLiam Girdwood return sprintf(buf, "%d\n", rdev->constraints->state_disk.uV); 832414c70cbSLiam Girdwood } 8337ad68e2fSDavid Brownell static DEVICE_ATTR(suspend_disk_microvolts, 0444, 8347ad68e2fSDavid Brownell regulator_suspend_disk_uV_show, NULL); 835414c70cbSLiam Girdwood 836414c70cbSLiam Girdwood static ssize_t regulator_suspend_standby_uV_show(struct device *dev, 837414c70cbSLiam Girdwood struct device_attribute *attr, char *buf) 838414c70cbSLiam Girdwood { 839a5766f11SLiam Girdwood struct regulator_dev *rdev = dev_get_drvdata(dev); 840414c70cbSLiam Girdwood 841414c70cbSLiam Girdwood return sprintf(buf, "%d\n", rdev->constraints->state_standby.uV); 842414c70cbSLiam Girdwood } 8437ad68e2fSDavid Brownell static DEVICE_ATTR(suspend_standby_microvolts, 0444, 8447ad68e2fSDavid Brownell regulator_suspend_standby_uV_show, NULL); 845414c70cbSLiam Girdwood 846414c70cbSLiam Girdwood static ssize_t regulator_suspend_mem_mode_show(struct device *dev, 847414c70cbSLiam Girdwood struct device_attribute *attr, char *buf) 848414c70cbSLiam Girdwood { 849a5766f11SLiam Girdwood struct regulator_dev *rdev = dev_get_drvdata(dev); 850414c70cbSLiam Girdwood 8514fca9545SDavid Brownell return regulator_print_opmode(buf, 8524fca9545SDavid Brownell rdev->constraints->state_mem.mode); 853414c70cbSLiam Girdwood } 8547ad68e2fSDavid Brownell static DEVICE_ATTR(suspend_mem_mode, 0444, 8557ad68e2fSDavid Brownell regulator_suspend_mem_mode_show, NULL); 856414c70cbSLiam Girdwood 857414c70cbSLiam Girdwood static ssize_t regulator_suspend_disk_mode_show(struct device *dev, 858414c70cbSLiam Girdwood struct device_attribute *attr, char *buf) 859414c70cbSLiam Girdwood { 860a5766f11SLiam Girdwood struct regulator_dev *rdev = dev_get_drvdata(dev); 861414c70cbSLiam Girdwood 8624fca9545SDavid Brownell return regulator_print_opmode(buf, 8634fca9545SDavid Brownell rdev->constraints->state_disk.mode); 864414c70cbSLiam Girdwood } 8657ad68e2fSDavid Brownell static DEVICE_ATTR(suspend_disk_mode, 0444, 8667ad68e2fSDavid Brownell regulator_suspend_disk_mode_show, NULL); 867414c70cbSLiam Girdwood 868414c70cbSLiam Girdwood static ssize_t regulator_suspend_standby_mode_show(struct device *dev, 869414c70cbSLiam Girdwood struct device_attribute *attr, char *buf) 870414c70cbSLiam Girdwood { 871a5766f11SLiam Girdwood struct regulator_dev *rdev = dev_get_drvdata(dev); 872414c70cbSLiam Girdwood 8734fca9545SDavid Brownell return regulator_print_opmode(buf, 8744fca9545SDavid Brownell rdev->constraints->state_standby.mode); 875414c70cbSLiam Girdwood } 8767ad68e2fSDavid Brownell static DEVICE_ATTR(suspend_standby_mode, 0444, 8777ad68e2fSDavid Brownell regulator_suspend_standby_mode_show, NULL); 878414c70cbSLiam Girdwood 879414c70cbSLiam Girdwood static ssize_t regulator_suspend_mem_state_show(struct device *dev, 880414c70cbSLiam Girdwood struct device_attribute *attr, char *buf) 881414c70cbSLiam Girdwood { 882a5766f11SLiam Girdwood struct regulator_dev *rdev = dev_get_drvdata(dev); 883414c70cbSLiam Girdwood 8844fca9545SDavid Brownell return regulator_print_state(buf, 8854fca9545SDavid Brownell rdev->constraints->state_mem.enabled); 886414c70cbSLiam Girdwood } 8877ad68e2fSDavid Brownell static DEVICE_ATTR(suspend_mem_state, 0444, 8887ad68e2fSDavid Brownell regulator_suspend_mem_state_show, NULL); 889414c70cbSLiam Girdwood 890414c70cbSLiam Girdwood static ssize_t regulator_suspend_disk_state_show(struct device *dev, 891414c70cbSLiam Girdwood struct device_attribute *attr, char *buf) 892414c70cbSLiam Girdwood { 893a5766f11SLiam Girdwood struct regulator_dev *rdev = dev_get_drvdata(dev); 894414c70cbSLiam Girdwood 8954fca9545SDavid Brownell return regulator_print_state(buf, 8964fca9545SDavid Brownell rdev->constraints->state_disk.enabled); 897414c70cbSLiam Girdwood } 8987ad68e2fSDavid Brownell static DEVICE_ATTR(suspend_disk_state, 0444, 8997ad68e2fSDavid Brownell regulator_suspend_disk_state_show, NULL); 900414c70cbSLiam Girdwood 901414c70cbSLiam Girdwood static ssize_t regulator_suspend_standby_state_show(struct device *dev, 902414c70cbSLiam Girdwood struct device_attribute *attr, char *buf) 903414c70cbSLiam Girdwood { 904a5766f11SLiam Girdwood struct regulator_dev *rdev = dev_get_drvdata(dev); 905414c70cbSLiam Girdwood 9064fca9545SDavid Brownell return regulator_print_state(buf, 9074fca9545SDavid Brownell rdev->constraints->state_standby.enabled); 908414c70cbSLiam Girdwood } 9097ad68e2fSDavid Brownell static DEVICE_ATTR(suspend_standby_state, 0444, 9107ad68e2fSDavid Brownell regulator_suspend_standby_state_show, NULL); 911bc558a60SMark Brown 912f59c8f9fSMark Brown static ssize_t regulator_bypass_show(struct device *dev, 913f59c8f9fSMark Brown struct device_attribute *attr, char *buf) 914f59c8f9fSMark Brown { 915f59c8f9fSMark Brown struct regulator_dev *rdev = dev_get_drvdata(dev); 916f59c8f9fSMark Brown const char *report; 917f59c8f9fSMark Brown bool bypass; 918f59c8f9fSMark Brown int ret; 919f59c8f9fSMark Brown 920f59c8f9fSMark Brown ret = rdev->desc->ops->get_bypass(rdev, &bypass); 921f59c8f9fSMark Brown 922f59c8f9fSMark Brown if (ret != 0) 923f59c8f9fSMark Brown report = "unknown"; 924f59c8f9fSMark Brown else if (bypass) 925f59c8f9fSMark Brown report = "enabled"; 926f59c8f9fSMark Brown else 927f59c8f9fSMark Brown report = "disabled"; 928f59c8f9fSMark Brown 929f59c8f9fSMark Brown return sprintf(buf, "%s\n", report); 930f59c8f9fSMark Brown } 931f59c8f9fSMark Brown static DEVICE_ATTR(bypass, 0444, 932f59c8f9fSMark Brown regulator_bypass_show, NULL); 9337ad68e2fSDavid Brownell 934414c70cbSLiam Girdwood /* Calculate the new optimum regulator operating mode based on the new total 93569b8821eSShubhankar Kuranagatti * consumer load. All locks held by caller 93669b8821eSShubhankar Kuranagatti */ 9378460ef38SBjorn Andersson static int drms_uA_update(struct regulator_dev *rdev) 938414c70cbSLiam Girdwood { 939414c70cbSLiam Girdwood struct regulator *sibling; 940414c70cbSLiam Girdwood int current_uA = 0, output_uV, input_uV, err; 941414c70cbSLiam Girdwood unsigned int mode; 942414c70cbSLiam Girdwood 9438460ef38SBjorn Andersson /* 9448460ef38SBjorn Andersson * first check to see if we can set modes at all, otherwise just 9458460ef38SBjorn Andersson * tell the consumer everything is OK. 9468460ef38SBjorn Andersson */ 94774a569eeSMarc Gonzalez if (!regulator_ops_is_valid(rdev, REGULATOR_CHANGE_DRMS)) { 94874a569eeSMarc Gonzalez rdev_dbg(rdev, "DRMS operation not allowed\n"); 9498460ef38SBjorn Andersson return 0; 95074a569eeSMarc Gonzalez } 9518460ef38SBjorn Andersson 9528f4490e0SBjorn Andersson if (!rdev->desc->ops->get_optimum_mode && 9538f4490e0SBjorn Andersson !rdev->desc->ops->set_load) 9548460ef38SBjorn Andersson return 0; 9558460ef38SBjorn Andersson 9568f4490e0SBjorn Andersson if (!rdev->desc->ops->set_mode && 9578f4490e0SBjorn Andersson !rdev->desc->ops->set_load) 9588460ef38SBjorn Andersson return -EINVAL; 959414c70cbSLiam Girdwood 96057776617SJoonwoo Park /* calc total requested load */ 9615451781dSDouglas Anderson list_for_each_entry(sibling, &rdev->consumer_list, list) { 9625451781dSDouglas Anderson if (sibling->enable_count) 96357776617SJoonwoo Park current_uA += sibling->uA_load; 9645451781dSDouglas Anderson } 96557776617SJoonwoo Park 96657776617SJoonwoo Park current_uA += rdev->constraints->system_load; 96757776617SJoonwoo Park 96857776617SJoonwoo Park if (rdev->desc->ops->set_load) { 96957776617SJoonwoo Park /* set the optimum mode for our new total regulator load */ 97057776617SJoonwoo Park err = rdev->desc->ops->set_load(rdev, current_uA); 97157776617SJoonwoo Park if (err < 0) 97261aab5adSMichał Mirosław rdev_err(rdev, "failed to set load %d: %pe\n", 97361aab5adSMichał Mirosław current_uA, ERR_PTR(err)); 97457776617SJoonwoo Park } else { 975414c70cbSLiam Girdwood /* get output voltage */ 976d22b85a1SDmitry Osipenko output_uV = regulator_get_voltage_rdev(rdev); 9778460ef38SBjorn Andersson if (output_uV <= 0) { 9788460ef38SBjorn Andersson rdev_err(rdev, "invalid output voltage found\n"); 9798460ef38SBjorn Andersson return -EINVAL; 9808460ef38SBjorn Andersson } 981414c70cbSLiam Girdwood 982414c70cbSLiam Girdwood /* get input voltage */ 9831bf5a1f8SMark Brown input_uV = 0; 9841bf5a1f8SMark Brown if (rdev->supply) 9853f24f5adSAxel Lin input_uV = regulator_get_voltage(rdev->supply); 9861bf5a1f8SMark Brown if (input_uV <= 0) 987414c70cbSLiam Girdwood input_uV = rdev->constraints->input_uV; 9888460ef38SBjorn Andersson if (input_uV <= 0) { 9898460ef38SBjorn Andersson rdev_err(rdev, "invalid input voltage found\n"); 9908460ef38SBjorn Andersson return -EINVAL; 9918460ef38SBjorn Andersson } 992414c70cbSLiam Girdwood 993414c70cbSLiam Girdwood /* now get the optimum mode for our new total regulator load */ 994414c70cbSLiam Girdwood mode = rdev->desc->ops->get_optimum_mode(rdev, input_uV, 995414c70cbSLiam Girdwood output_uV, current_uA); 996414c70cbSLiam Girdwood 997414c70cbSLiam Girdwood /* check the new mode is allowed */ 9982c608234SMark Brown err = regulator_mode_constrain(rdev, &mode); 9998460ef38SBjorn Andersson if (err < 0) { 100061aab5adSMichał Mirosław rdev_err(rdev, "failed to get optimum mode @ %d uA %d -> %d uV: %pe\n", 100161aab5adSMichał Mirosław current_uA, input_uV, output_uV, ERR_PTR(err)); 10028460ef38SBjorn Andersson return err; 10038460ef38SBjorn Andersson } 10048460ef38SBjorn Andersson 10058460ef38SBjorn Andersson err = rdev->desc->ops->set_mode(rdev, mode); 10068460ef38SBjorn Andersson if (err < 0) 100761aab5adSMichał Mirosław rdev_err(rdev, "failed to set optimum mode %x: %pe\n", 100861aab5adSMichał Mirosław mode, ERR_PTR(err)); 10098f4490e0SBjorn Andersson } 10108460ef38SBjorn Andersson 10118460ef38SBjorn Andersson return err; 1012414c70cbSLiam Girdwood } 1013414c70cbSLiam Girdwood 10140955f5beSStephen Boyd static int __suspend_set_state(struct regulator_dev *rdev, 10150955f5beSStephen Boyd const struct regulator_state *rstate) 1016414c70cbSLiam Girdwood { 1017414c70cbSLiam Girdwood int ret = 0; 1018638f85c5SMark Brown 101972069f99SChunyan Zhang if (rstate->enabled == ENABLE_IN_SUSPEND && 102072069f99SChunyan Zhang rdev->desc->ops->set_suspend_enable) 1021414c70cbSLiam Girdwood ret = rdev->desc->ops->set_suspend_enable(rdev); 102272069f99SChunyan Zhang else if (rstate->enabled == DISABLE_IN_SUSPEND && 102372069f99SChunyan Zhang rdev->desc->ops->set_suspend_disable) 1024414c70cbSLiam Girdwood ret = rdev->desc->ops->set_suspend_disable(rdev); 10258ac0e95dSAxel Lin else /* OK if set_suspend_enable or set_suspend_disable is NULL */ 10268ac0e95dSAxel Lin ret = 0; 10278ac0e95dSAxel Lin 1028414c70cbSLiam Girdwood if (ret < 0) { 102961aab5adSMichał Mirosław rdev_err(rdev, "failed to enabled/disable: %pe\n", ERR_PTR(ret)); 1030414c70cbSLiam Girdwood return ret; 1031414c70cbSLiam Girdwood } 1032414c70cbSLiam Girdwood 1033414c70cbSLiam Girdwood if (rdev->desc->ops->set_suspend_voltage && rstate->uV > 0) { 1034414c70cbSLiam Girdwood ret = rdev->desc->ops->set_suspend_voltage(rdev, rstate->uV); 1035414c70cbSLiam Girdwood if (ret < 0) { 103661aab5adSMichał Mirosław rdev_err(rdev, "failed to set voltage: %pe\n", ERR_PTR(ret)); 1037414c70cbSLiam Girdwood return ret; 1038414c70cbSLiam Girdwood } 1039414c70cbSLiam Girdwood } 1040414c70cbSLiam Girdwood 1041414c70cbSLiam Girdwood if (rdev->desc->ops->set_suspend_mode && rstate->mode > 0) { 1042414c70cbSLiam Girdwood ret = rdev->desc->ops->set_suspend_mode(rdev, rstate->mode); 1043414c70cbSLiam Girdwood if (ret < 0) { 104461aab5adSMichał Mirosław rdev_err(rdev, "failed to set mode: %pe\n", ERR_PTR(ret)); 1045414c70cbSLiam Girdwood return ret; 1046414c70cbSLiam Girdwood } 1047414c70cbSLiam Girdwood } 1048f7efad10SChunyan Zhang 1049414c70cbSLiam Girdwood return ret; 1050414c70cbSLiam Girdwood } 1051414c70cbSLiam Girdwood 10520955f5beSStephen Boyd static int suspend_set_initial_state(struct regulator_dev *rdev) 10530955f5beSStephen Boyd { 10540955f5beSStephen Boyd const struct regulator_state *rstate; 10550955f5beSStephen Boyd 10560955f5beSStephen Boyd rstate = regulator_get_suspend_state_check(rdev, 10570955f5beSStephen Boyd rdev->constraints->initial_state); 10580955f5beSStephen Boyd if (!rstate) 10590955f5beSStephen Boyd return 0; 10600955f5beSStephen Boyd 10610955f5beSStephen Boyd return __suspend_set_state(rdev, rstate); 10620955f5beSStephen Boyd } 10630955f5beSStephen Boyd 1064c845f21aSGeert Uytterhoeven #if defined(DEBUG) || defined(CONFIG_DYNAMIC_DEBUG) 1065c845f21aSGeert Uytterhoeven static void print_constraints_debug(struct regulator_dev *rdev) 1066414c70cbSLiam Girdwood { 1067414c70cbSLiam Girdwood struct regulation_constraints *constraints = rdev->constraints; 1068a7068e39SStefan Wahren char buf[160] = ""; 10695751a99fSStefan Wahren size_t len = sizeof(buf) - 1; 10708f031b48SMark Brown int count = 0; 10718f031b48SMark Brown int ret; 1072414c70cbSLiam Girdwood 10738f031b48SMark Brown if (constraints->min_uV && constraints->max_uV) { 1074414c70cbSLiam Girdwood if (constraints->min_uV == constraints->max_uV) 10755751a99fSStefan Wahren count += scnprintf(buf + count, len - count, "%d mV ", 1076414c70cbSLiam Girdwood constraints->min_uV / 1000); 1077414c70cbSLiam Girdwood else 10785751a99fSStefan Wahren count += scnprintf(buf + count, len - count, 10795751a99fSStefan Wahren "%d <--> %d mV ", 1080414c70cbSLiam Girdwood constraints->min_uV / 1000, 1081414c70cbSLiam Girdwood constraints->max_uV / 1000); 10828f031b48SMark Brown } 10838f031b48SMark Brown 10848f031b48SMark Brown if (!constraints->min_uV || 10858f031b48SMark Brown constraints->min_uV != constraints->max_uV) { 1086d22b85a1SDmitry Osipenko ret = regulator_get_voltage_rdev(rdev); 10878f031b48SMark Brown if (ret > 0) 10885751a99fSStefan Wahren count += scnprintf(buf + count, len - count, 10895751a99fSStefan Wahren "at %d mV ", ret / 1000); 10908f031b48SMark Brown } 10918f031b48SMark Brown 1092bf5892a8SMark Brown if (constraints->uV_offset) 10935751a99fSStefan Wahren count += scnprintf(buf + count, len - count, "%dmV offset ", 1094bf5892a8SMark Brown constraints->uV_offset / 1000); 1095bf5892a8SMark Brown 10968f031b48SMark Brown if (constraints->min_uA && constraints->max_uA) { 1097414c70cbSLiam Girdwood if (constraints->min_uA == constraints->max_uA) 10985751a99fSStefan Wahren count += scnprintf(buf + count, len - count, "%d mA ", 1099414c70cbSLiam Girdwood constraints->min_uA / 1000); 1100414c70cbSLiam Girdwood else 11015751a99fSStefan Wahren count += scnprintf(buf + count, len - count, 11025751a99fSStefan Wahren "%d <--> %d mA ", 1103414c70cbSLiam Girdwood constraints->min_uA / 1000, 1104414c70cbSLiam Girdwood constraints->max_uA / 1000); 1105414c70cbSLiam Girdwood } 11068f031b48SMark Brown 11078f031b48SMark Brown if (!constraints->min_uA || 11088f031b48SMark Brown constraints->min_uA != constraints->max_uA) { 11098f031b48SMark Brown ret = _regulator_get_current_limit(rdev); 11108f031b48SMark Brown if (ret > 0) 11115751a99fSStefan Wahren count += scnprintf(buf + count, len - count, 11125751a99fSStefan Wahren "at %d mA ", ret / 1000); 11138f031b48SMark Brown } 11148f031b48SMark Brown 1115414c70cbSLiam Girdwood if (constraints->valid_modes_mask & REGULATOR_MODE_FAST) 11165751a99fSStefan Wahren count += scnprintf(buf + count, len - count, "fast "); 1117414c70cbSLiam Girdwood if (constraints->valid_modes_mask & REGULATOR_MODE_NORMAL) 11185751a99fSStefan Wahren count += scnprintf(buf + count, len - count, "normal "); 1119414c70cbSLiam Girdwood if (constraints->valid_modes_mask & REGULATOR_MODE_IDLE) 11205751a99fSStefan Wahren count += scnprintf(buf + count, len - count, "idle "); 1121414c70cbSLiam Girdwood if (constraints->valid_modes_mask & REGULATOR_MODE_STANDBY) 11225751a99fSStefan Wahren count += scnprintf(buf + count, len - count, "standby "); 1123414c70cbSLiam Girdwood 1124215b8b05SUwe Kleine-König if (!count) 112599ad5f6eSMichał Mirosław count = scnprintf(buf, len, "no parameters"); 112699ad5f6eSMichał Mirosław else 112799ad5f6eSMichał Mirosław --count; 112899ad5f6eSMichał Mirosław 112999ad5f6eSMichał Mirosław count += scnprintf(buf + count, len - count, ", %s", 113099ad5f6eSMichał Mirosław _regulator_is_enabled(rdev) ? "enabled" : "disabled"); 1131215b8b05SUwe Kleine-König 1132194dbaefSMark Brown rdev_dbg(rdev, "%s\n", buf); 1133c845f21aSGeert Uytterhoeven } 1134c845f21aSGeert Uytterhoeven #else /* !DEBUG && !CONFIG_DYNAMIC_DEBUG */ 1135c845f21aSGeert Uytterhoeven static inline void print_constraints_debug(struct regulator_dev *rdev) {} 1136c845f21aSGeert Uytterhoeven #endif /* !DEBUG && !CONFIG_DYNAMIC_DEBUG */ 1137c845f21aSGeert Uytterhoeven 1138c845f21aSGeert Uytterhoeven static void print_constraints(struct regulator_dev *rdev) 1139c845f21aSGeert Uytterhoeven { 1140c845f21aSGeert Uytterhoeven struct regulation_constraints *constraints = rdev->constraints; 1141c845f21aSGeert Uytterhoeven 1142c845f21aSGeert Uytterhoeven print_constraints_debug(rdev); 11434a682922SMark Brown 11444a682922SMark Brown if ((constraints->min_uV != constraints->max_uV) && 11458a34e979SWEN Pingbo !regulator_ops_is_valid(rdev, REGULATOR_CHANGE_VOLTAGE)) 11464a682922SMark Brown rdev_warn(rdev, 11474a682922SMark Brown "Voltage range but no REGULATOR_CHANGE_VOLTAGE\n"); 1148414c70cbSLiam Girdwood } 1149414c70cbSLiam Girdwood 1150e79055d6SMark Brown static int machine_constraints_voltage(struct regulator_dev *rdev, 11511083c393SMark Brown struct regulation_constraints *constraints) 1152e79055d6SMark Brown { 1153272e2315SGuodong Xu const struct regulator_ops *ops = rdev->desc->ops; 1154af5866c9SMark Brown int ret; 1155af5866c9SMark Brown 1156af5866c9SMark Brown /* do we need to apply the constraint voltage */ 1157af5866c9SMark Brown if (rdev->constraints->apply_uV && 1158fa93fd4eSMark Brown rdev->constraints->min_uV && rdev->constraints->max_uV) { 1159fa93fd4eSMark Brown int target_min, target_max; 1160d22b85a1SDmitry Osipenko int current_uV = regulator_get_voltage_rdev(rdev); 116184b3a7c9SDouglas Anderson 116284b3a7c9SDouglas Anderson if (current_uV == -ENOTRECOVERABLE) { 116348f1b4efSKrzysztof Kozlowski /* This regulator can't be read and must be initialized */ 116484b3a7c9SDouglas Anderson rdev_info(rdev, "Setting %d-%duV\n", 116584b3a7c9SDouglas Anderson rdev->constraints->min_uV, 116684b3a7c9SDouglas Anderson rdev->constraints->max_uV); 116784b3a7c9SDouglas Anderson _regulator_do_set_voltage(rdev, 116884b3a7c9SDouglas Anderson rdev->constraints->min_uV, 116984b3a7c9SDouglas Anderson rdev->constraints->max_uV); 1170d22b85a1SDmitry Osipenko current_uV = regulator_get_voltage_rdev(rdev); 117184b3a7c9SDouglas Anderson } 117284b3a7c9SDouglas Anderson 1173064d5cd1SAlban Bedel if (current_uV < 0) { 117469d58839SNishanth Menon rdev_err(rdev, 117561aab5adSMichał Mirosław "failed to get the current voltage: %pe\n", 117661aab5adSMichał Mirosław ERR_PTR(current_uV)); 1177064d5cd1SAlban Bedel return current_uV; 1178064d5cd1SAlban Bedel } 1179fa93fd4eSMark Brown 1180fa93fd4eSMark Brown /* 1181fa93fd4eSMark Brown * If we're below the minimum voltage move up to the 1182fa93fd4eSMark Brown * minimum voltage, if we're above the maximum voltage 1183fa93fd4eSMark Brown * then move down to the maximum. 1184fa93fd4eSMark Brown */ 1185fa93fd4eSMark Brown target_min = current_uV; 1186fa93fd4eSMark Brown target_max = current_uV; 1187fa93fd4eSMark Brown 1188fa93fd4eSMark Brown if (current_uV < rdev->constraints->min_uV) { 1189fa93fd4eSMark Brown target_min = rdev->constraints->min_uV; 1190fa93fd4eSMark Brown target_max = rdev->constraints->min_uV; 1191fa93fd4eSMark Brown } 1192fa93fd4eSMark Brown 1193fa93fd4eSMark Brown if (current_uV > rdev->constraints->max_uV) { 1194fa93fd4eSMark Brown target_min = rdev->constraints->max_uV; 1195fa93fd4eSMark Brown target_max = rdev->constraints->max_uV; 1196fa93fd4eSMark Brown } 1197fa93fd4eSMark Brown 1198fa93fd4eSMark Brown if (target_min != current_uV || target_max != current_uV) { 119945a91e8fSMark Brown rdev_info(rdev, "Bringing %duV into %d-%duV\n", 120045a91e8fSMark Brown current_uV, target_min, target_max); 1201064d5cd1SAlban Bedel ret = _regulator_do_set_voltage( 1202fa93fd4eSMark Brown rdev, target_min, target_max); 1203af5866c9SMark Brown if (ret < 0) { 1204064d5cd1SAlban Bedel rdev_err(rdev, 120561aab5adSMichał Mirosław "failed to apply %d-%duV constraint: %pe\n", 120661aab5adSMichał Mirosław target_min, target_max, ERR_PTR(ret)); 1207af5866c9SMark Brown return ret; 1208af5866c9SMark Brown } 1209af5866c9SMark Brown } 1210064d5cd1SAlban Bedel } 1211e79055d6SMark Brown 1212e79055d6SMark Brown /* constrain machine-level voltage specs to fit 1213e79055d6SMark Brown * the actual range supported by this regulator. 1214e79055d6SMark Brown */ 1215e79055d6SMark Brown if (ops->list_voltage && rdev->desc->n_voltages) { 1216e79055d6SMark Brown int count = rdev->desc->n_voltages; 1217e79055d6SMark Brown int i; 1218e79055d6SMark Brown int min_uV = INT_MAX; 1219e79055d6SMark Brown int max_uV = INT_MIN; 1220e79055d6SMark Brown int cmin = constraints->min_uV; 1221e79055d6SMark Brown int cmax = constraints->max_uV; 1222e79055d6SMark Brown 1223e79055d6SMark Brown /* it's safe to autoconfigure fixed-voltage supplies 122469b8821eSShubhankar Kuranagatti * and the constraints are used by list_voltage. 122569b8821eSShubhankar Kuranagatti */ 1226e79055d6SMark Brown if (count == 1 && !cmin) { 1227e79055d6SMark Brown cmin = 1; 1228e79055d6SMark Brown cmax = INT_MAX; 1229e79055d6SMark Brown constraints->min_uV = cmin; 1230e79055d6SMark Brown constraints->max_uV = cmax; 1231e79055d6SMark Brown } 1232e79055d6SMark Brown 1233e79055d6SMark Brown /* voltage constraints are optional */ 1234e79055d6SMark Brown if ((cmin == 0) && (cmax == 0)) 1235e79055d6SMark Brown return 0; 1236e79055d6SMark Brown 1237e79055d6SMark Brown /* else require explicit machine-level constraints */ 1238e79055d6SMark Brown if (cmin <= 0 || cmax <= 0 || cmax < cmin) { 12395da84fd9SJoe Perches rdev_err(rdev, "invalid voltage constraints\n"); 1240e79055d6SMark Brown return -EINVAL; 1241e79055d6SMark Brown } 1242e79055d6SMark Brown 12436d30fc51SCristian Marussi /* no need to loop voltages if range is continuous */ 12446d30fc51SCristian Marussi if (rdev->desc->continuous_voltage_range) 12456d30fc51SCristian Marussi return 0; 12466d30fc51SCristian Marussi 1247e79055d6SMark Brown /* initial: [cmin..cmax] valid, [min_uV..max_uV] not */ 1248e79055d6SMark Brown for (i = 0; i < count; i++) { 1249e79055d6SMark Brown int value; 1250e79055d6SMark Brown 1251e79055d6SMark Brown value = ops->list_voltage(rdev, i); 1252e79055d6SMark Brown if (value <= 0) 1253e79055d6SMark Brown continue; 1254e79055d6SMark Brown 1255e79055d6SMark Brown /* maybe adjust [min_uV..max_uV] */ 1256e79055d6SMark Brown if (value >= cmin && value < min_uV) 1257e79055d6SMark Brown min_uV = value; 1258e79055d6SMark Brown if (value <= cmax && value > max_uV) 1259e79055d6SMark Brown max_uV = value; 1260e79055d6SMark Brown } 1261e79055d6SMark Brown 1262e79055d6SMark Brown /* final: [min_uV..max_uV] valid iff constraints valid */ 1263e79055d6SMark Brown if (max_uV < min_uV) { 1264fff15befSMark Brown rdev_err(rdev, 1265fff15befSMark Brown "unsupportable voltage constraints %u-%uuV\n", 1266fff15befSMark Brown min_uV, max_uV); 1267e79055d6SMark Brown return -EINVAL; 1268e79055d6SMark Brown } 1269e79055d6SMark Brown 1270e79055d6SMark Brown /* use regulator's subset of machine constraints */ 1271e79055d6SMark Brown if (constraints->min_uV < min_uV) { 12725da84fd9SJoe Perches rdev_dbg(rdev, "override min_uV, %d -> %d\n", 12735da84fd9SJoe Perches constraints->min_uV, min_uV); 1274e79055d6SMark Brown constraints->min_uV = min_uV; 1275e79055d6SMark Brown } 1276e79055d6SMark Brown if (constraints->max_uV > max_uV) { 12775da84fd9SJoe Perches rdev_dbg(rdev, "override max_uV, %d -> %d\n", 12785da84fd9SJoe Perches constraints->max_uV, max_uV); 1279e79055d6SMark Brown constraints->max_uV = max_uV; 1280e79055d6SMark Brown } 1281e79055d6SMark Brown } 1282e79055d6SMark Brown 1283e79055d6SMark Brown return 0; 1284e79055d6SMark Brown } 1285e79055d6SMark Brown 1286f8c1700dSLaxman Dewangan static int machine_constraints_current(struct regulator_dev *rdev, 1287f8c1700dSLaxman Dewangan struct regulation_constraints *constraints) 1288f8c1700dSLaxman Dewangan { 1289272e2315SGuodong Xu const struct regulator_ops *ops = rdev->desc->ops; 1290f8c1700dSLaxman Dewangan int ret; 1291f8c1700dSLaxman Dewangan 1292f8c1700dSLaxman Dewangan if (!constraints->min_uA && !constraints->max_uA) 1293f8c1700dSLaxman Dewangan return 0; 1294f8c1700dSLaxman Dewangan 1295f8c1700dSLaxman Dewangan if (constraints->min_uA > constraints->max_uA) { 1296f8c1700dSLaxman Dewangan rdev_err(rdev, "Invalid current constraints\n"); 1297f8c1700dSLaxman Dewangan return -EINVAL; 1298f8c1700dSLaxman Dewangan } 1299f8c1700dSLaxman Dewangan 1300f8c1700dSLaxman Dewangan if (!ops->set_current_limit || !ops->get_current_limit) { 1301f8c1700dSLaxman Dewangan rdev_warn(rdev, "Operation of current configuration missing\n"); 1302f8c1700dSLaxman Dewangan return 0; 1303f8c1700dSLaxman Dewangan } 1304f8c1700dSLaxman Dewangan 1305f8c1700dSLaxman Dewangan /* Set regulator current in constraints range */ 1306f8c1700dSLaxman Dewangan ret = ops->set_current_limit(rdev, constraints->min_uA, 1307f8c1700dSLaxman Dewangan constraints->max_uA); 1308f8c1700dSLaxman Dewangan if (ret < 0) { 1309f8c1700dSLaxman Dewangan rdev_err(rdev, "Failed to set current constraint, %d\n", ret); 1310f8c1700dSLaxman Dewangan return ret; 1311f8c1700dSLaxman Dewangan } 1312f8c1700dSLaxman Dewangan 1313f8c1700dSLaxman Dewangan return 0; 1314f8c1700dSLaxman Dewangan } 1315f8c1700dSLaxman Dewangan 131630c21971SMarkus Pargmann static int _regulator_do_enable(struct regulator_dev *rdev); 131730c21971SMarkus Pargmann 1318a5766f11SLiam Girdwood /** 1319a5766f11SLiam Girdwood * set_machine_constraints - sets regulator constraints 132069279fb9SMark Brown * @rdev: regulator source 1321a5766f11SLiam Girdwood * 1322a5766f11SLiam Girdwood * Allows platform initialisation code to define and constrain 1323a5766f11SLiam Girdwood * regulator circuits e.g. valid voltage/current ranges, etc. NOTE: 1324a5766f11SLiam Girdwood * Constraints *must* be set by platform code in order for some 1325a5766f11SLiam Girdwood * regulator operations to proceed i.e. set_voltage, set_current_limit, 1326a5766f11SLiam Girdwood * set_mode. 1327a5766f11SLiam Girdwood */ 132857a6ad48SMichał Mirosław static int set_machine_constraints(struct regulator_dev *rdev) 1329a5766f11SLiam Girdwood { 1330a5766f11SLiam Girdwood int ret = 0; 1331272e2315SGuodong Xu const struct regulator_ops *ops = rdev->desc->ops; 1332e06f5b4fSMark Brown 1333f8c12fe3SMark Brown ret = machine_constraints_voltage(rdev, rdev->constraints); 1334e79055d6SMark Brown if (ret != 0) 13356333ef46SCharles Keepax return ret; 13363e2b9abdSMark Brown 1337f8c1700dSLaxman Dewangan ret = machine_constraints_current(rdev, rdev->constraints); 1338f8c1700dSLaxman Dewangan if (ret != 0) 13396333ef46SCharles Keepax return ret; 1340f8c1700dSLaxman Dewangan 134136e4f839SStephen Boyd if (rdev->constraints->ilim_uA && ops->set_input_current_limit) { 134236e4f839SStephen Boyd ret = ops->set_input_current_limit(rdev, 134336e4f839SStephen Boyd rdev->constraints->ilim_uA); 134436e4f839SStephen Boyd if (ret < 0) { 134561aab5adSMichał Mirosław rdev_err(rdev, "failed to set input limit: %pe\n", ERR_PTR(ret)); 13466333ef46SCharles Keepax return ret; 134736e4f839SStephen Boyd } 134836e4f839SStephen Boyd } 134936e4f839SStephen Boyd 1350a5766f11SLiam Girdwood /* do we need to setup our suspend state */ 13519a8f5e07SMark Brown if (rdev->constraints->initial_state) { 13520955f5beSStephen Boyd ret = suspend_set_initial_state(rdev); 1353e06f5b4fSMark Brown if (ret < 0) { 135461aab5adSMichał Mirosław rdev_err(rdev, "failed to set suspend state: %pe\n", ERR_PTR(ret)); 13556333ef46SCharles Keepax return ret; 1356e06f5b4fSMark Brown } 1357e06f5b4fSMark Brown } 1358a5766f11SLiam Girdwood 13599a8f5e07SMark Brown if (rdev->constraints->initial_mode) { 1360a308466cSMark Brown if (!ops->set_mode) { 13615da84fd9SJoe Perches rdev_err(rdev, "no set_mode operation\n"); 13626333ef46SCharles Keepax return -EINVAL; 1363a308466cSMark Brown } 1364a308466cSMark Brown 1365f8c12fe3SMark Brown ret = ops->set_mode(rdev, rdev->constraints->initial_mode); 1366a308466cSMark Brown if (ret < 0) { 136761aab5adSMichał Mirosław rdev_err(rdev, "failed to set initial mode: %pe\n", ERR_PTR(ret)); 13686333ef46SCharles Keepax return ret; 1369a308466cSMark Brown } 1370fa94e48eSDouglas Anderson } else if (rdev->constraints->system_load) { 1371fa94e48eSDouglas Anderson /* 1372fa94e48eSDouglas Anderson * We'll only apply the initial system load if an 1373fa94e48eSDouglas Anderson * initial mode wasn't specified. 1374fa94e48eSDouglas Anderson */ 1375fa94e48eSDouglas Anderson drms_uA_update(rdev); 1376a308466cSMark Brown } 1377a308466cSMark Brown 13781653ccf4SYadwinder Singh Brar if ((rdev->constraints->ramp_delay || rdev->constraints->ramp_disable) 13791653ccf4SYadwinder Singh Brar && ops->set_ramp_delay) { 13806f0b2c69SYadwinder Singh Brar ret = ops->set_ramp_delay(rdev, rdev->constraints->ramp_delay); 13816f0b2c69SYadwinder Singh Brar if (ret < 0) { 138261aab5adSMichał Mirosław rdev_err(rdev, "failed to set ramp_delay: %pe\n", ERR_PTR(ret)); 13836333ef46SCharles Keepax return ret; 13846f0b2c69SYadwinder Singh Brar } 13856f0b2c69SYadwinder Singh Brar } 13866f0b2c69SYadwinder Singh Brar 138723c779b9SStephen Boyd if (rdev->constraints->pull_down && ops->set_pull_down) { 138823c779b9SStephen Boyd ret = ops->set_pull_down(rdev); 138923c779b9SStephen Boyd if (ret < 0) { 139061aab5adSMichał Mirosław rdev_err(rdev, "failed to set pull down: %pe\n", ERR_PTR(ret)); 13916333ef46SCharles Keepax return ret; 139223c779b9SStephen Boyd } 139323c779b9SStephen Boyd } 139423c779b9SStephen Boyd 139557f66b78SStephen Boyd if (rdev->constraints->soft_start && ops->set_soft_start) { 139657f66b78SStephen Boyd ret = ops->set_soft_start(rdev); 139757f66b78SStephen Boyd if (ret < 0) { 139861aab5adSMichał Mirosław rdev_err(rdev, "failed to set soft start: %pe\n", ERR_PTR(ret)); 13996333ef46SCharles Keepax return ret; 140057f66b78SStephen Boyd } 140157f66b78SStephen Boyd } 140257f66b78SStephen Boyd 14033a003baeSStephen Boyd if (rdev->constraints->over_current_protection 14043a003baeSStephen Boyd && ops->set_over_current_protection) { 14053a003baeSStephen Boyd ret = ops->set_over_current_protection(rdev); 14063a003baeSStephen Boyd if (ret < 0) { 140761aab5adSMichał Mirosław rdev_err(rdev, "failed to set over current protection: %pe\n", 140861aab5adSMichał Mirosław ERR_PTR(ret)); 14096333ef46SCharles Keepax return ret; 14103a003baeSStephen Boyd } 14113a003baeSStephen Boyd } 14123a003baeSStephen Boyd 1413670666b9SLaxman Dewangan if (rdev->constraints->active_discharge && ops->set_active_discharge) { 1414670666b9SLaxman Dewangan bool ad_state = (rdev->constraints->active_discharge == 1415670666b9SLaxman Dewangan REGULATOR_ACTIVE_DISCHARGE_ENABLE) ? true : false; 1416670666b9SLaxman Dewangan 1417670666b9SLaxman Dewangan ret = ops->set_active_discharge(rdev, ad_state); 1418670666b9SLaxman Dewangan if (ret < 0) { 141961aab5adSMichał Mirosław rdev_err(rdev, "failed to set active discharge: %pe\n", ERR_PTR(ret)); 1420670666b9SLaxman Dewangan return ret; 1421670666b9SLaxman Dewangan } 1422670666b9SLaxman Dewangan } 1423670666b9SLaxman Dewangan 14242bb16663SOlliver Schinagl /* If the constraints say the regulator should be on at this point 14252bb16663SOlliver Schinagl * and we have control then make sure it is enabled. 14262bb16663SOlliver Schinagl */ 14272bb16663SOlliver Schinagl if (rdev->constraints->always_on || rdev->constraints->boot_on) { 142805f224caSDouglas Anderson if (rdev->supply) { 142905f224caSDouglas Anderson ret = regulator_enable(rdev->supply); 143005f224caSDouglas Anderson if (ret < 0) { 143105f224caSDouglas Anderson _regulator_put(rdev->supply); 143205f224caSDouglas Anderson rdev->supply = NULL; 143305f224caSDouglas Anderson return ret; 143405f224caSDouglas Anderson } 143505f224caSDouglas Anderson } 143605f224caSDouglas Anderson 14372bb16663SOlliver Schinagl ret = _regulator_do_enable(rdev); 14382bb16663SOlliver Schinagl if (ret < 0 && ret != -EINVAL) { 143961aab5adSMichał Mirosław rdev_err(rdev, "failed to enable: %pe\n", ERR_PTR(ret)); 14402bb16663SOlliver Schinagl return ret; 14412bb16663SOlliver Schinagl } 1442089b3f61SPascal Paillet 1443089b3f61SPascal Paillet if (rdev->constraints->always_on) 144405f224caSDouglas Anderson rdev->use_count++; 1445a5ccccb3SVincent Whitchurch } else if (rdev->desc->off_on_delay) { 1446a8ce7bd8SVincent Whitchurch rdev->last_off = ktime_get(); 14472bb16663SOlliver Schinagl } 14482bb16663SOlliver Schinagl 1449a5766f11SLiam Girdwood print_constraints(rdev); 14501a6958e7SAxel Lin return 0; 1451a5766f11SLiam Girdwood } 1452a5766f11SLiam Girdwood 1453a5766f11SLiam Girdwood /** 1454a5766f11SLiam Girdwood * set_supply - set regulator supply regulator 145569279fb9SMark Brown * @rdev: regulator name 145669279fb9SMark Brown * @supply_rdev: supply regulator name 1457a5766f11SLiam Girdwood * 1458a5766f11SLiam Girdwood * Called by platform initialisation code to set the supply regulator for this 1459a5766f11SLiam Girdwood * regulator. This ensures that a regulators supply will also be enabled by the 1460a5766f11SLiam Girdwood * core if it's child is enabled. 1461a5766f11SLiam Girdwood */ 1462a5766f11SLiam Girdwood static int set_supply(struct regulator_dev *rdev, 1463a5766f11SLiam Girdwood struct regulator_dev *supply_rdev) 1464a5766f11SLiam Girdwood { 1465a5766f11SLiam Girdwood int err; 1466a5766f11SLiam Girdwood 14673801b86aSMark Brown rdev_info(rdev, "supplied by %s\n", rdev_get_name(supply_rdev)); 14683801b86aSMark Brown 1469e2c09ae7SJavier Martinez Canillas if (!try_module_get(supply_rdev->owner)) 1470e2c09ae7SJavier Martinez Canillas return -ENODEV; 1471e2c09ae7SJavier Martinez Canillas 14723801b86aSMark Brown rdev->supply = create_regulator(supply_rdev, &rdev->dev, "SUPPLY"); 147332c78de8SAxel Lin if (rdev->supply == NULL) { 147432c78de8SAxel Lin err = -ENOMEM; 1475a5766f11SLiam Girdwood return err; 1476a5766f11SLiam Girdwood } 147757ad526aSLaxman Dewangan supply_rdev->open_count++; 1478a5766f11SLiam Girdwood 14793801b86aSMark Brown return 0; 14803801b86aSMark Brown } 14813801b86aSMark Brown 1482a5766f11SLiam Girdwood /** 148306c63f93SRandy Dunlap * set_consumer_device_supply - Bind a regulator to a symbolic supply 148469279fb9SMark Brown * @rdev: regulator source 148540f9244fSMark Brown * @consumer_dev_name: dev_name() string for device supply applies to 1486a5766f11SLiam Girdwood * @supply: symbolic name for supply 1487a5766f11SLiam Girdwood * 1488a5766f11SLiam Girdwood * Allows platform initialisation code to map physical regulator 1489a5766f11SLiam Girdwood * sources to symbolic names for supplies for use by devices. Devices 1490a5766f11SLiam Girdwood * should use these symbolic names to request regulators, avoiding the 1491a5766f11SLiam Girdwood * need to provide board-specific regulator names as platform data. 1492a5766f11SLiam Girdwood */ 1493a5766f11SLiam Girdwood static int set_consumer_device_supply(struct regulator_dev *rdev, 1494737f360dSMark Brown const char *consumer_dev_name, 149540f9244fSMark Brown const char *supply) 1496a5766f11SLiam Girdwood { 14975c065401SMichał Mirosław struct regulator_map *node, *new_node; 14989ed2099eSMark Brown int has_dev; 1499a5766f11SLiam Girdwood 1500a5766f11SLiam Girdwood if (supply == NULL) 1501a5766f11SLiam Girdwood return -EINVAL; 1502a5766f11SLiam Girdwood 15039ed2099eSMark Brown if (consumer_dev_name != NULL) 15049ed2099eSMark Brown has_dev = 1; 15059ed2099eSMark Brown else 15069ed2099eSMark Brown has_dev = 0; 15079ed2099eSMark Brown 15085c065401SMichał Mirosław new_node = kzalloc(sizeof(struct regulator_map), GFP_KERNEL); 15095c065401SMichał Mirosław if (new_node == NULL) 15105c065401SMichał Mirosław return -ENOMEM; 15115c065401SMichał Mirosław 15125c065401SMichał Mirosław new_node->regulator = rdev; 15135c065401SMichał Mirosław new_node->supply = supply; 15145c065401SMichał Mirosław 15155c065401SMichał Mirosław if (has_dev) { 15165c065401SMichał Mirosław new_node->dev_name = kstrdup(consumer_dev_name, GFP_KERNEL); 15175c065401SMichał Mirosław if (new_node->dev_name == NULL) { 15185c065401SMichał Mirosław kfree(new_node); 15195c065401SMichał Mirosław return -ENOMEM; 15205c065401SMichał Mirosław } 15215c065401SMichał Mirosław } 15225c065401SMichał Mirosław 15235c065401SMichał Mirosław mutex_lock(®ulator_list_mutex); 15246001e13cSDavid Brownell list_for_each_entry(node, ®ulator_map_list, list) { 152523b5cc2aSJani Nikula if (node->dev_name && consumer_dev_name) { 152623b5cc2aSJani Nikula if (strcmp(node->dev_name, consumer_dev_name) != 0) 15276001e13cSDavid Brownell continue; 152823b5cc2aSJani Nikula } else if (node->dev_name || consumer_dev_name) { 152923b5cc2aSJani Nikula continue; 153023b5cc2aSJani Nikula } 153123b5cc2aSJani Nikula 15326001e13cSDavid Brownell if (strcmp(node->supply, supply) != 0) 15336001e13cSDavid Brownell continue; 15346001e13cSDavid Brownell 1535737f360dSMark Brown pr_debug("%s: %s/%s is '%s' supply; fail %s/%s\n", 1536737f360dSMark Brown consumer_dev_name, 15376001e13cSDavid Brownell dev_name(&node->regulator->dev), 15386001e13cSDavid Brownell node->regulator->desc->name, 15396001e13cSDavid Brownell supply, 15401083c393SMark Brown dev_name(&rdev->dev), rdev_get_name(rdev)); 15415c065401SMichał Mirosław goto fail; 15426001e13cSDavid Brownell } 15436001e13cSDavid Brownell 15445c065401SMichał Mirosław list_add(&new_node->list, ®ulator_map_list); 15455c065401SMichał Mirosław mutex_unlock(®ulator_list_mutex); 1546a5766f11SLiam Girdwood 1547a5766f11SLiam Girdwood return 0; 15485c065401SMichał Mirosław 15495c065401SMichał Mirosław fail: 15505c065401SMichał Mirosław mutex_unlock(®ulator_list_mutex); 15515c065401SMichał Mirosław kfree(new_node->dev_name); 15525c065401SMichał Mirosław kfree(new_node); 15535c065401SMichał Mirosław return -EBUSY; 1554a5766f11SLiam Girdwood } 1555a5766f11SLiam Girdwood 15560f1d747bSMike Rapoport static void unset_regulator_supplies(struct regulator_dev *rdev) 15570f1d747bSMike Rapoport { 15580f1d747bSMike Rapoport struct regulator_map *node, *n; 15590f1d747bSMike Rapoport 15600f1d747bSMike Rapoport list_for_each_entry_safe(node, n, ®ulator_map_list, list) { 15610f1d747bSMike Rapoport if (rdev == node->regulator) { 15620f1d747bSMike Rapoport list_del(&node->list); 156340f9244fSMark Brown kfree(node->dev_name); 15640f1d747bSMike Rapoport kfree(node); 15650f1d747bSMike Rapoport } 15660f1d747bSMike Rapoport } 15670f1d747bSMike Rapoport } 15680f1d747bSMike Rapoport 15692d80a91bSRichard Fitzgerald #ifdef CONFIG_DEBUG_FS 15702d80a91bSRichard Fitzgerald static ssize_t constraint_flags_read_file(struct file *file, 15712d80a91bSRichard Fitzgerald char __user *user_buf, 15722d80a91bSRichard Fitzgerald size_t count, loff_t *ppos) 15732d80a91bSRichard Fitzgerald { 15742d80a91bSRichard Fitzgerald const struct regulator *regulator = file->private_data; 15752d80a91bSRichard Fitzgerald const struct regulation_constraints *c = regulator->rdev->constraints; 15762d80a91bSRichard Fitzgerald char *buf; 15772d80a91bSRichard Fitzgerald ssize_t ret; 15782d80a91bSRichard Fitzgerald 15792d80a91bSRichard Fitzgerald if (!c) 15802d80a91bSRichard Fitzgerald return 0; 15812d80a91bSRichard Fitzgerald 15822d80a91bSRichard Fitzgerald buf = kmalloc(PAGE_SIZE, GFP_KERNEL); 15832d80a91bSRichard Fitzgerald if (!buf) 15842d80a91bSRichard Fitzgerald return -ENOMEM; 15852d80a91bSRichard Fitzgerald 15862d80a91bSRichard Fitzgerald ret = snprintf(buf, PAGE_SIZE, 15872d80a91bSRichard Fitzgerald "always_on: %u\n" 15882d80a91bSRichard Fitzgerald "boot_on: %u\n" 15892d80a91bSRichard Fitzgerald "apply_uV: %u\n" 15902d80a91bSRichard Fitzgerald "ramp_disable: %u\n" 15912d80a91bSRichard Fitzgerald "soft_start: %u\n" 15922d80a91bSRichard Fitzgerald "pull_down: %u\n" 15932d80a91bSRichard Fitzgerald "over_current_protection: %u\n", 15942d80a91bSRichard Fitzgerald c->always_on, 15952d80a91bSRichard Fitzgerald c->boot_on, 15962d80a91bSRichard Fitzgerald c->apply_uV, 15972d80a91bSRichard Fitzgerald c->ramp_disable, 15982d80a91bSRichard Fitzgerald c->soft_start, 15992d80a91bSRichard Fitzgerald c->pull_down, 16002d80a91bSRichard Fitzgerald c->over_current_protection); 16012d80a91bSRichard Fitzgerald 16022d80a91bSRichard Fitzgerald ret = simple_read_from_buffer(user_buf, count, ppos, buf, ret); 16032d80a91bSRichard Fitzgerald kfree(buf); 16042d80a91bSRichard Fitzgerald 16052d80a91bSRichard Fitzgerald return ret; 16062d80a91bSRichard Fitzgerald } 16072d80a91bSRichard Fitzgerald 16082d80a91bSRichard Fitzgerald #endif 16092d80a91bSRichard Fitzgerald 16102d80a91bSRichard Fitzgerald static const struct file_operations constraint_flags_fops = { 16112d80a91bSRichard Fitzgerald #ifdef CONFIG_DEBUG_FS 16122d80a91bSRichard Fitzgerald .open = simple_open, 16132d80a91bSRichard Fitzgerald .read = constraint_flags_read_file, 16142d80a91bSRichard Fitzgerald .llseek = default_llseek, 16152d80a91bSRichard Fitzgerald #endif 16162d80a91bSRichard Fitzgerald }; 16172d80a91bSRichard Fitzgerald 1618f5726ae3SMark Brown #define REG_STR_SIZE 64 1619414c70cbSLiam Girdwood 1620414c70cbSLiam Girdwood static struct regulator *create_regulator(struct regulator_dev *rdev, 1621414c70cbSLiam Girdwood struct device *dev, 1622414c70cbSLiam Girdwood const char *supply_name) 1623414c70cbSLiam Girdwood { 1624414c70cbSLiam Girdwood struct regulator *regulator; 1625dbe954d8SHans de Goede int err = 0; 1626414c70cbSLiam Girdwood 162787fe29b6SMichał Mirosław if (dev) { 162887fe29b6SMichał Mirosław char buf[REG_STR_SIZE]; 162987fe29b6SMichał Mirosław int size; 163087fe29b6SMichał Mirosław 163187fe29b6SMichał Mirosław size = snprintf(buf, REG_STR_SIZE, "%s-%s", 163287fe29b6SMichał Mirosław dev->kobj.name, supply_name); 163387fe29b6SMichał Mirosław if (size >= REG_STR_SIZE) 1634414c70cbSLiam Girdwood return NULL; 1635414c70cbSLiam Girdwood 163687fe29b6SMichał Mirosław supply_name = kstrdup(buf, GFP_KERNEL); 163787fe29b6SMichał Mirosław if (supply_name == NULL) 163887fe29b6SMichał Mirosław return NULL; 163987fe29b6SMichał Mirosław } else { 164087fe29b6SMichał Mirosław supply_name = kstrdup_const(supply_name, GFP_KERNEL); 164187fe29b6SMichał Mirosław if (supply_name == NULL) 164287fe29b6SMichał Mirosław return NULL; 164387fe29b6SMichał Mirosław } 164487fe29b6SMichał Mirosław 164587fe29b6SMichał Mirosław regulator = kzalloc(sizeof(*regulator), GFP_KERNEL); 164687fe29b6SMichał Mirosław if (regulator == NULL) { 164787fe29b6SMichał Mirosław kfree(supply_name); 164887fe29b6SMichał Mirosław return NULL; 164987fe29b6SMichał Mirosław } 165087fe29b6SMichał Mirosław 1651414c70cbSLiam Girdwood regulator->rdev = rdev; 165287fe29b6SMichał Mirosław regulator->supply_name = supply_name; 165387fe29b6SMichał Mirosław 165487fe29b6SMichał Mirosław regulator_lock(rdev); 1655414c70cbSLiam Girdwood list_add(®ulator->list, &rdev->consumer_list); 165687fe29b6SMichał Mirosław regulator_unlock(rdev); 1657414c70cbSLiam Girdwood 1658414c70cbSLiam Girdwood if (dev) { 1659e2c98eafSShawn Guo regulator->dev = dev; 1660e2c98eafSShawn Guo 1661222cc7b1SMark Brown /* Add a link to the device sysfs entry */ 1662ff268b56SStephen Boyd err = sysfs_create_link_nowarn(&rdev->dev.kobj, &dev->kobj, 166387fe29b6SMichał Mirosław supply_name); 1664414c70cbSLiam Girdwood if (err) { 166561aab5adSMichał Mirosław rdev_dbg(rdev, "could not add device link %s: %pe\n", 166661aab5adSMichał Mirosław dev->kobj.name, ERR_PTR(err)); 1667222cc7b1SMark Brown /* non-fatal */ 1668414c70cbSLiam Girdwood } 1669414c70cbSLiam Girdwood } 16705de70519SMark Brown 1671dbe954d8SHans de Goede if (err != -EEXIST) 1672dbe954d8SHans de Goede regulator->debugfs = debugfs_create_dir(supply_name, rdev->debugfs); 167324751434SStephen Boyd if (!regulator->debugfs) { 1674ad3a942bSStephen Boyd rdev_dbg(rdev, "Failed to create debugfs directory\n"); 16755de70519SMark Brown } else { 16765de70519SMark Brown debugfs_create_u32("uA_load", 0444, regulator->debugfs, 16775de70519SMark Brown ®ulator->uA_load); 16785de70519SMark Brown debugfs_create_u32("min_uV", 0444, regulator->debugfs, 1679c360a6dfSChunyan Zhang ®ulator->voltage[PM_SUSPEND_ON].min_uV); 16805de70519SMark Brown debugfs_create_u32("max_uV", 0444, regulator->debugfs, 1681c360a6dfSChunyan Zhang ®ulator->voltage[PM_SUSPEND_ON].max_uV); 16822d80a91bSRichard Fitzgerald debugfs_create_file("constraint_flags", 0444, 16832d80a91bSRichard Fitzgerald regulator->debugfs, regulator, 16842d80a91bSRichard Fitzgerald &constraint_flags_fops); 16855de70519SMark Brown } 16865de70519SMark Brown 16876492bc1bSMark Brown /* 16886492bc1bSMark Brown * Check now if the regulator is an always on regulator - if 16896492bc1bSMark Brown * it is then we don't need to do nearly so much work for 16906492bc1bSMark Brown * enable/disable calls. 16916492bc1bSMark Brown */ 16928a34e979SWEN Pingbo if (!regulator_ops_is_valid(rdev, REGULATOR_CHANGE_STATUS) && 16936492bc1bSMark Brown _regulator_is_enabled(rdev)) 16946492bc1bSMark Brown regulator->always_on = true; 16956492bc1bSMark Brown 1696414c70cbSLiam Girdwood return regulator; 1697414c70cbSLiam Girdwood } 1698414c70cbSLiam Girdwood 169931aae2beSMark Brown static int _regulator_get_enable_time(struct regulator_dev *rdev) 170031aae2beSMark Brown { 170100c877c6SLaxman Dewangan if (rdev->constraints && rdev->constraints->enable_time) 170200c877c6SLaxman Dewangan return rdev->constraints->enable_time; 170368ce3a44SAxel Lin if (rdev->desc->ops->enable_time) 170431aae2beSMark Brown return rdev->desc->ops->enable_time(rdev); 170568ce3a44SAxel Lin return rdev->desc->enable_time; 170631aae2beSMark Brown } 170731aae2beSMark Brown 1708a06ccd9cSCharles Keepax static struct regulator_supply_alias *regulator_find_supply_alias( 1709a06ccd9cSCharles Keepax struct device *dev, const char *supply) 1710a06ccd9cSCharles Keepax { 1711a06ccd9cSCharles Keepax struct regulator_supply_alias *map; 1712a06ccd9cSCharles Keepax 1713a06ccd9cSCharles Keepax list_for_each_entry(map, ®ulator_supply_alias_list, list) 1714a06ccd9cSCharles Keepax if (map->src_dev == dev && strcmp(map->src_supply, supply) == 0) 1715a06ccd9cSCharles Keepax return map; 1716a06ccd9cSCharles Keepax 1717a06ccd9cSCharles Keepax return NULL; 1718a06ccd9cSCharles Keepax } 1719a06ccd9cSCharles Keepax 1720a06ccd9cSCharles Keepax static void regulator_supply_alias(struct device **dev, const char **supply) 1721a06ccd9cSCharles Keepax { 1722a06ccd9cSCharles Keepax struct regulator_supply_alias *map; 1723a06ccd9cSCharles Keepax 1724a06ccd9cSCharles Keepax map = regulator_find_supply_alias(*dev, *supply); 1725a06ccd9cSCharles Keepax if (map) { 1726a06ccd9cSCharles Keepax dev_dbg(*dev, "Mapping supply %s to %s,%s\n", 1727a06ccd9cSCharles Keepax *supply, map->alias_supply, 1728a06ccd9cSCharles Keepax dev_name(map->alias_dev)); 1729a06ccd9cSCharles Keepax *dev = map->alias_dev; 1730a06ccd9cSCharles Keepax *supply = map->alias_supply; 1731a06ccd9cSCharles Keepax } 1732a06ccd9cSCharles Keepax } 1733a06ccd9cSCharles Keepax 173485f3b431STomeu Vizoso static int regulator_match(struct device *dev, const void *data) 173585f3b431STomeu Vizoso { 173685f3b431STomeu Vizoso struct regulator_dev *r = dev_to_rdev(dev); 173785f3b431STomeu Vizoso 173885f3b431STomeu Vizoso return strcmp(rdev_get_name(r), data) == 0; 173985f3b431STomeu Vizoso } 174085f3b431STomeu Vizoso 174185f3b431STomeu Vizoso static struct regulator_dev *regulator_lookup_by_name(const char *name) 174285f3b431STomeu Vizoso { 174385f3b431STomeu Vizoso struct device *dev; 174485f3b431STomeu Vizoso 174585f3b431STomeu Vizoso dev = class_find_device(®ulator_class, NULL, name, regulator_match); 174685f3b431STomeu Vizoso 174785f3b431STomeu Vizoso return dev ? dev_to_rdev(dev) : NULL; 174885f3b431STomeu Vizoso } 174985f3b431STomeu Vizoso 175085f3b431STomeu Vizoso /** 175185f3b431STomeu Vizoso * regulator_dev_lookup - lookup a regulator device. 175285f3b431STomeu Vizoso * @dev: device for regulator "consumer". 175385f3b431STomeu Vizoso * @supply: Supply name or regulator ID. 175485f3b431STomeu Vizoso * 175585f3b431STomeu Vizoso * If successful, returns a struct regulator_dev that corresponds to the name 1756163478daSDmitry Torokhov * @supply and with the embedded struct device refcount incremented by one. 1757163478daSDmitry Torokhov * The refcount must be dropped by calling put_device(). 1758163478daSDmitry Torokhov * On failure one of the following ERR-PTR-encoded values is returned: 1759163478daSDmitry Torokhov * -ENODEV if lookup fails permanently, -EPROBE_DEFER if lookup could succeed 1760163478daSDmitry Torokhov * in the future. 176185f3b431STomeu Vizoso */ 176269511a45SRajendra Nayak static struct regulator_dev *regulator_dev_lookup(struct device *dev, 1763163478daSDmitry Torokhov const char *supply) 176469511a45SRajendra Nayak { 176506217197SCharles Keepax struct regulator_dev *r = NULL; 176669511a45SRajendra Nayak struct device_node *node; 1767576ca436SMark Brown struct regulator_map *map; 1768576ca436SMark Brown const char *devname = NULL; 176969511a45SRajendra Nayak 1770a06ccd9cSCharles Keepax regulator_supply_alias(&dev, &supply); 1771a06ccd9cSCharles Keepax 177269511a45SRajendra Nayak /* first do a dt based lookup */ 177369511a45SRajendra Nayak if (dev && dev->of_node) { 177469511a45SRajendra Nayak node = of_get_regulator(dev, supply); 17756d191a5fSMark Brown if (node) { 177685f3b431STomeu Vizoso r = of_find_regulator_by_node(node); 177785f3b431STomeu Vizoso if (r) 177869511a45SRajendra Nayak return r; 1779163478daSDmitry Torokhov 17806d191a5fSMark Brown /* 1781163478daSDmitry Torokhov * We have a node, but there is no device. 1782163478daSDmitry Torokhov * assume it has not registered yet. 17836d191a5fSMark Brown */ 1784163478daSDmitry Torokhov return ERR_PTR(-EPROBE_DEFER); 17856d191a5fSMark Brown } 178669511a45SRajendra Nayak } 178769511a45SRajendra Nayak 178869511a45SRajendra Nayak /* if not found, try doing it non-dt way */ 1789576ca436SMark Brown if (dev) 1790576ca436SMark Brown devname = dev_name(dev); 1791576ca436SMark Brown 179285f3b431STomeu Vizoso mutex_lock(®ulator_list_mutex); 1793576ca436SMark Brown list_for_each_entry(map, ®ulator_map_list, list) { 1794576ca436SMark Brown /* If the mapping has a device set up it must match */ 1795576ca436SMark Brown if (map->dev_name && 1796576ca436SMark Brown (!devname || strcmp(map->dev_name, devname))) 1797576ca436SMark Brown continue; 1798576ca436SMark Brown 179985f3b431STomeu Vizoso if (strcmp(map->supply, supply) == 0 && 180085f3b431STomeu Vizoso get_device(&map->regulator->dev)) { 1801163478daSDmitry Torokhov r = map->regulator; 1802163478daSDmitry Torokhov break; 1803576ca436SMark Brown } 180485f3b431STomeu Vizoso } 180585f3b431STomeu Vizoso mutex_unlock(®ulator_list_mutex); 1806576ca436SMark Brown 1807163478daSDmitry Torokhov if (r) 1808163478daSDmitry Torokhov return r; 1809163478daSDmitry Torokhov 181006217197SCharles Keepax r = regulator_lookup_by_name(supply); 181106217197SCharles Keepax if (r) 181206217197SCharles Keepax return r; 181306217197SCharles Keepax 1814163478daSDmitry Torokhov return ERR_PTR(-ENODEV); 181569511a45SRajendra Nayak } 181669511a45SRajendra Nayak 18176261b06dSBjorn Andersson static int regulator_resolve_supply(struct regulator_dev *rdev) 18186261b06dSBjorn Andersson { 18196261b06dSBjorn Andersson struct regulator_dev *r; 18206261b06dSBjorn Andersson struct device *dev = rdev->dev.parent; 1821eaa7995cSDavid Collins int ret = 0; 18226261b06dSBjorn Andersson 182348f1b4efSKrzysztof Kozlowski /* No supply to resolve? */ 18246261b06dSBjorn Andersson if (!rdev->supply_name) 18256261b06dSBjorn Andersson return 0; 18266261b06dSBjorn Andersson 1827eaa7995cSDavid Collins /* Supply already resolved? (fast-path without locking contention) */ 18286261b06dSBjorn Andersson if (rdev->supply) 18296261b06dSBjorn Andersson return 0; 18306261b06dSBjorn Andersson 1831163478daSDmitry Torokhov r = regulator_dev_lookup(dev, rdev->supply_name); 1832163478daSDmitry Torokhov if (IS_ERR(r)) { 1833163478daSDmitry Torokhov ret = PTR_ERR(r); 1834163478daSDmitry Torokhov 183506423121SMark Brown /* Did the lookup explicitly defer for us? */ 183606423121SMark Brown if (ret == -EPROBE_DEFER) 1837eaa7995cSDavid Collins goto out; 183806423121SMark Brown 18399f7e25edSMark Brown if (have_full_constraints()) { 18409f7e25edSMark Brown r = dummy_regulator_rdev; 184185f3b431STomeu Vizoso get_device(&r->dev); 18429f7e25edSMark Brown } else { 18436261b06dSBjorn Andersson dev_err(dev, "Failed to resolve %s-supply for %s\n", 18446261b06dSBjorn Andersson rdev->supply_name, rdev->desc->name); 1845eaa7995cSDavid Collins ret = -EPROBE_DEFER; 1846eaa7995cSDavid Collins goto out; 18476261b06dSBjorn Andersson } 18489f7e25edSMark Brown } 18496261b06dSBjorn Andersson 18504b639e25SMichał Mirosław if (r == rdev) { 18514b639e25SMichał Mirosław dev_err(dev, "Supply for %s (%s) resolved to itself\n", 18524b639e25SMichał Mirosław rdev->desc->name, rdev->supply_name); 1853eaa7995cSDavid Collins if (!have_full_constraints()) { 1854eaa7995cSDavid Collins ret = -EINVAL; 1855eaa7995cSDavid Collins goto out; 1856eaa7995cSDavid Collins } 1857f5c042b2SMichał Mirosław r = dummy_regulator_rdev; 1858f5c042b2SMichał Mirosław get_device(&r->dev); 18594b639e25SMichał Mirosław } 18604b639e25SMichał Mirosław 186166d228a2SJon Hunter /* 186266d228a2SJon Hunter * If the supply's parent device is not the same as the 186366d228a2SJon Hunter * regulator's parent device, then ensure the parent device 186466d228a2SJon Hunter * is bound before we resolve the supply, in case the parent 186566d228a2SJon Hunter * device get probe deferred and unregisters the supply. 186666d228a2SJon Hunter */ 186766d228a2SJon Hunter if (r->dev.parent && r->dev.parent != rdev->dev.parent) { 186866d228a2SJon Hunter if (!device_is_bound(r->dev.parent)) { 186966d228a2SJon Hunter put_device(&r->dev); 1870eaa7995cSDavid Collins ret = -EPROBE_DEFER; 1871eaa7995cSDavid Collins goto out; 187266d228a2SJon Hunter } 187366d228a2SJon Hunter } 187466d228a2SJon Hunter 18756261b06dSBjorn Andersson /* Recursively resolve the supply of the supply */ 18766261b06dSBjorn Andersson ret = regulator_resolve_supply(r); 187785f3b431STomeu Vizoso if (ret < 0) { 187885f3b431STomeu Vizoso put_device(&r->dev); 1879eaa7995cSDavid Collins goto out; 188085f3b431STomeu Vizoso } 18816261b06dSBjorn Andersson 188214a71d50SMark Brown /* 188314a71d50SMark Brown * Recheck rdev->supply with rdev->mutex lock held to avoid a race 188414a71d50SMark Brown * between rdev->supply null check and setting rdev->supply in 188514a71d50SMark Brown * set_supply() from concurrent tasks. 188614a71d50SMark Brown */ 188714a71d50SMark Brown regulator_lock(rdev); 188814a71d50SMark Brown 188914a71d50SMark Brown /* Supply just resolved by a concurrent task? */ 189014a71d50SMark Brown if (rdev->supply) { 189114a71d50SMark Brown regulator_unlock(rdev); 189285f3b431STomeu Vizoso put_device(&r->dev); 1893eaa7995cSDavid Collins goto out; 189485f3b431STomeu Vizoso } 18956261b06dSBjorn Andersson 189614a71d50SMark Brown ret = set_supply(rdev, r); 189714a71d50SMark Brown if (ret < 0) { 189814a71d50SMark Brown regulator_unlock(rdev); 189914a71d50SMark Brown put_device(&r->dev); 190014a71d50SMark Brown goto out; 190114a71d50SMark Brown } 190214a71d50SMark Brown 190314a71d50SMark Brown regulator_unlock(rdev); 190414a71d50SMark Brown 190505f224caSDouglas Anderson /* 190605f224caSDouglas Anderson * In set_machine_constraints() we may have turned this regulator on 190705f224caSDouglas Anderson * but we couldn't propagate to the supply if it hadn't been resolved 190805f224caSDouglas Anderson * yet. Do it now. 190905f224caSDouglas Anderson */ 191005f224caSDouglas Anderson if (rdev->use_count) { 19116261b06dSBjorn Andersson ret = regulator_enable(rdev->supply); 191236a1f1b6SJavier Martinez Canillas if (ret < 0) { 191336a1f1b6SJavier Martinez Canillas _regulator_put(rdev->supply); 19148e5356a7SJon Hunter rdev->supply = NULL; 1915eaa7995cSDavid Collins goto out; 19166261b06dSBjorn Andersson } 191736a1f1b6SJavier Martinez Canillas } 19186261b06dSBjorn Andersson 1919eaa7995cSDavid Collins out: 1920eaa7995cSDavid Collins return ret; 19216261b06dSBjorn Andersson } 19226261b06dSBjorn Andersson 19235ffbd136SMark Brown /* Internal regulator request function */ 1924a8bd42a9SDmitry Torokhov struct regulator *_regulator_get(struct device *dev, const char *id, 1925a8bd42a9SDmitry Torokhov enum regulator_get_type get_type) 1926414c70cbSLiam Girdwood { 1927414c70cbSLiam Girdwood struct regulator_dev *rdev; 19287d245afaSDmitry Torokhov struct regulator *regulator; 1929b59b6544SSaravana Kannan struct device_link *link; 1930317b5684SMark Brown int ret; 1931414c70cbSLiam Girdwood 1932a8bd42a9SDmitry Torokhov if (get_type >= MAX_GET_TYPE) { 1933a8bd42a9SDmitry Torokhov dev_err(dev, "invalid type %d in %s\n", get_type, __func__); 1934a8bd42a9SDmitry Torokhov return ERR_PTR(-EINVAL); 1935a8bd42a9SDmitry Torokhov } 1936a8bd42a9SDmitry Torokhov 1937414c70cbSLiam Girdwood if (id == NULL) { 19385da84fd9SJoe Perches pr_err("get() with no identifier\n"); 1939043c998fSMark Brown return ERR_PTR(-EINVAL); 1940414c70cbSLiam Girdwood } 1941414c70cbSLiam Girdwood 1942163478daSDmitry Torokhov rdev = regulator_dev_lookup(dev, id); 1943a4d7641fSDmitry Torokhov if (IS_ERR(rdev)) { 1944163478daSDmitry Torokhov ret = PTR_ERR(rdev); 1945ef60abbbSMark Brown 19461e4b545cSNishanth Menon /* 1947a4d7641fSDmitry Torokhov * If regulator_dev_lookup() fails with error other 1948a4d7641fSDmitry Torokhov * than -ENODEV our job here is done, we simply return it. 19491e4b545cSNishanth Menon */ 1950a4d7641fSDmitry Torokhov if (ret != -ENODEV) 1951a4d7641fSDmitry Torokhov return ERR_PTR(ret); 19521e4b545cSNishanth Menon 1953a4d7641fSDmitry Torokhov if (!have_full_constraints()) { 1954a4d7641fSDmitry Torokhov dev_warn(dev, 1955a4d7641fSDmitry Torokhov "incomplete constraints, dummy supplies not allowed\n"); 1956a4d7641fSDmitry Torokhov return ERR_PTR(-ENODEV); 195734abbd68SMark Brown } 195834abbd68SMark Brown 1959a4d7641fSDmitry Torokhov switch (get_type) { 1960a4d7641fSDmitry Torokhov case NORMAL_GET: 1961a4d7641fSDmitry Torokhov /* 1962a4d7641fSDmitry Torokhov * Assume that a regulator is physically present and 1963a4d7641fSDmitry Torokhov * enabled, even if it isn't hooked up, and just 1964a4d7641fSDmitry Torokhov * provide a dummy. 1965a4d7641fSDmitry Torokhov */ 19666e5505cfSAndy Shevchenko dev_warn(dev, "supply %s not found, using dummy regulator\n", id); 1967a4d7641fSDmitry Torokhov rdev = dummy_regulator_rdev; 1968a4d7641fSDmitry Torokhov get_device(&rdev->dev); 1969a4d7641fSDmitry Torokhov break; 1970414c70cbSLiam Girdwood 1971a4d7641fSDmitry Torokhov case EXCLUSIVE_GET: 1972a4d7641fSDmitry Torokhov dev_warn(dev, 1973a4d7641fSDmitry Torokhov "dummy supplies not allowed for exclusive requests\n"); 1974df561f66SGustavo A. R. Silva fallthrough; 1975a4d7641fSDmitry Torokhov 1976a4d7641fSDmitry Torokhov default: 1977a4d7641fSDmitry Torokhov return ERR_PTR(-ENODEV); 1978a4d7641fSDmitry Torokhov } 1979a4d7641fSDmitry Torokhov } 1980a4d7641fSDmitry Torokhov 19815ffbd136SMark Brown if (rdev->exclusive) { 19825ffbd136SMark Brown regulator = ERR_PTR(-EPERM); 198385f3b431STomeu Vizoso put_device(&rdev->dev); 198485f3b431STomeu Vizoso return regulator; 19855ffbd136SMark Brown } 19865ffbd136SMark Brown 1987a8bd42a9SDmitry Torokhov if (get_type == EXCLUSIVE_GET && rdev->open_count) { 19885ffbd136SMark Brown regulator = ERR_PTR(-EBUSY); 198985f3b431STomeu Vizoso put_device(&rdev->dev); 199085f3b431STomeu Vizoso return regulator; 19915ffbd136SMark Brown } 19925ffbd136SMark Brown 199379d6f049SDmitry Osipenko mutex_lock(®ulator_list_mutex); 199479d6f049SDmitry Osipenko ret = (rdev->coupling_desc.n_resolved != rdev->coupling_desc.n_coupled); 199579d6f049SDmitry Osipenko mutex_unlock(®ulator_list_mutex); 199679d6f049SDmitry Osipenko 199779d6f049SDmitry Osipenko if (ret != 0) { 199879d6f049SDmitry Osipenko regulator = ERR_PTR(-EPROBE_DEFER); 199979d6f049SDmitry Osipenko put_device(&rdev->dev); 200079d6f049SDmitry Osipenko return regulator; 200179d6f049SDmitry Osipenko } 200279d6f049SDmitry Osipenko 20036261b06dSBjorn Andersson ret = regulator_resolve_supply(rdev); 20046261b06dSBjorn Andersson if (ret < 0) { 20056261b06dSBjorn Andersson regulator = ERR_PTR(ret); 200685f3b431STomeu Vizoso put_device(&rdev->dev); 200785f3b431STomeu Vizoso return regulator; 20086261b06dSBjorn Andersson } 20096261b06dSBjorn Andersson 201085f3b431STomeu Vizoso if (!try_module_get(rdev->owner)) { 20117d245afaSDmitry Torokhov regulator = ERR_PTR(-EPROBE_DEFER); 201285f3b431STomeu Vizoso put_device(&rdev->dev); 201385f3b431STomeu Vizoso return regulator; 201485f3b431STomeu Vizoso } 2015a5766f11SLiam Girdwood 2016414c70cbSLiam Girdwood regulator = create_regulator(rdev, dev, id); 2017414c70cbSLiam Girdwood if (regulator == NULL) { 2018414c70cbSLiam Girdwood regulator = ERR_PTR(-ENOMEM); 2019414c70cbSLiam Girdwood module_put(rdev->owner); 20204affd79aSWen Yang put_device(&rdev->dev); 202185f3b431STomeu Vizoso return regulator; 2022414c70cbSLiam Girdwood } 2023414c70cbSLiam Girdwood 20245ffbd136SMark Brown rdev->open_count++; 2025a8bd42a9SDmitry Torokhov if (get_type == EXCLUSIVE_GET) { 20265ffbd136SMark Brown rdev->exclusive = 1; 20275ffbd136SMark Brown 20285ffbd136SMark Brown ret = _regulator_is_enabled(rdev); 20295ffbd136SMark Brown if (ret > 0) 20305ffbd136SMark Brown rdev->use_count = 1; 20315ffbd136SMark Brown else 20325ffbd136SMark Brown rdev->use_count = 0; 20335ffbd136SMark Brown } 20345ffbd136SMark Brown 2035b59b6544SSaravana Kannan link = device_link_add(dev, &rdev->dev, DL_FLAG_STATELESS); 2036b59b6544SSaravana Kannan if (!IS_ERR_OR_NULL(link)) 2037b59b6544SSaravana Kannan regulator->device_link = true; 2038ed1ae2ddSpascal paillet 2039414c70cbSLiam Girdwood return regulator; 2040414c70cbSLiam Girdwood } 20415ffbd136SMark Brown 20425ffbd136SMark Brown /** 20435ffbd136SMark Brown * regulator_get - lookup and obtain a reference to a regulator. 20445ffbd136SMark Brown * @dev: device for regulator "consumer" 20455ffbd136SMark Brown * @id: Supply name or regulator ID. 20465ffbd136SMark Brown * 20475ffbd136SMark Brown * Returns a struct regulator corresponding to the regulator producer, 20485ffbd136SMark Brown * or IS_ERR() condition containing errno. 20495ffbd136SMark Brown * 205090cf443dSDaniel Scally * Use of supply names configured via set_consumer_device_supply() is 20515ffbd136SMark Brown * strongly encouraged. It is recommended that the supply name used 20525ffbd136SMark Brown * should match the name used for the supply and/or the relevant 20535ffbd136SMark Brown * device pins in the datasheet. 20545ffbd136SMark Brown */ 20555ffbd136SMark Brown struct regulator *regulator_get(struct device *dev, const char *id) 20565ffbd136SMark Brown { 2057a8bd42a9SDmitry Torokhov return _regulator_get(dev, id, NORMAL_GET); 20585ffbd136SMark Brown } 2059414c70cbSLiam Girdwood EXPORT_SYMBOL_GPL(regulator_get); 2060414c70cbSLiam Girdwood 2061070b9079SStephen Boyd /** 20625ffbd136SMark Brown * regulator_get_exclusive - obtain exclusive access to a regulator. 20635ffbd136SMark Brown * @dev: device for regulator "consumer" 20645ffbd136SMark Brown * @id: Supply name or regulator ID. 20655ffbd136SMark Brown * 20665ffbd136SMark Brown * Returns a struct regulator corresponding to the regulator producer, 20675ffbd136SMark Brown * or IS_ERR() condition containing errno. Other consumers will be 206869c3f723SStephen Boyd * unable to obtain this regulator while this reference is held and the 206969c3f723SStephen Boyd * use count for the regulator will be initialised to reflect the current 207069c3f723SStephen Boyd * state of the regulator. 20715ffbd136SMark Brown * 20725ffbd136SMark Brown * This is intended for use by consumers which cannot tolerate shared 20735ffbd136SMark Brown * use of the regulator such as those which need to force the 20745ffbd136SMark Brown * regulator off for correct operation of the hardware they are 20755ffbd136SMark Brown * controlling. 20765ffbd136SMark Brown * 207790cf443dSDaniel Scally * Use of supply names configured via set_consumer_device_supply() is 20785ffbd136SMark Brown * strongly encouraged. It is recommended that the supply name used 20795ffbd136SMark Brown * should match the name used for the supply and/or the relevant 20805ffbd136SMark Brown * device pins in the datasheet. 20815ffbd136SMark Brown */ 20825ffbd136SMark Brown struct regulator *regulator_get_exclusive(struct device *dev, const char *id) 20835ffbd136SMark Brown { 2084a8bd42a9SDmitry Torokhov return _regulator_get(dev, id, EXCLUSIVE_GET); 20855ffbd136SMark Brown } 20865ffbd136SMark Brown EXPORT_SYMBOL_GPL(regulator_get_exclusive); 20875ffbd136SMark Brown 2088de1dd9fdSMark Brown /** 2089de1dd9fdSMark Brown * regulator_get_optional - obtain optional access to a regulator. 2090de1dd9fdSMark Brown * @dev: device for regulator "consumer" 2091de1dd9fdSMark Brown * @id: Supply name or regulator ID. 2092de1dd9fdSMark Brown * 2093de1dd9fdSMark Brown * Returns a struct regulator corresponding to the regulator producer, 209469c3f723SStephen Boyd * or IS_ERR() condition containing errno. 2095de1dd9fdSMark Brown * 2096de1dd9fdSMark Brown * This is intended for use by consumers for devices which can have 2097de1dd9fdSMark Brown * some supplies unconnected in normal use, such as some MMC devices. 2098de1dd9fdSMark Brown * It can allow the regulator core to provide stub supplies for other 2099de1dd9fdSMark Brown * supplies requested using normal regulator_get() calls without 2100de1dd9fdSMark Brown * disrupting the operation of drivers that can handle absent 2101de1dd9fdSMark Brown * supplies. 2102de1dd9fdSMark Brown * 210390cf443dSDaniel Scally * Use of supply names configured via set_consumer_device_supply() is 2104de1dd9fdSMark Brown * strongly encouraged. It is recommended that the supply name used 2105de1dd9fdSMark Brown * should match the name used for the supply and/or the relevant 2106de1dd9fdSMark Brown * device pins in the datasheet. 2107de1dd9fdSMark Brown */ 2108de1dd9fdSMark Brown struct regulator *regulator_get_optional(struct device *dev, const char *id) 2109de1dd9fdSMark Brown { 2110a8bd42a9SDmitry Torokhov return _regulator_get(dev, id, OPTIONAL_GET); 2111de1dd9fdSMark Brown } 2112de1dd9fdSMark Brown EXPORT_SYMBOL_GPL(regulator_get_optional); 2113de1dd9fdSMark Brown 2114e1794aa4SSaravana Kannan static void destroy_regulator(struct regulator *regulator) 2115414c70cbSLiam Girdwood { 2116e1794aa4SSaravana Kannan struct regulator_dev *rdev = regulator->rdev; 2117414c70cbSLiam Girdwood 21185de70519SMark Brown debugfs_remove_recursive(regulator->debugfs); 21195de70519SMark Brown 2120ed1ae2ddSpascal paillet if (regulator->dev) { 2121b59b6544SSaravana Kannan if (regulator->device_link) 2122ed1ae2ddSpascal paillet device_link_remove(regulator->dev, &rdev->dev); 2123ed1ae2ddSpascal paillet 2124414c70cbSLiam Girdwood /* remove any sysfs entries */ 2125414c70cbSLiam Girdwood sysfs_remove_link(&rdev->dev.kobj, regulator->supply_name); 2126ed1ae2ddSpascal paillet } 2127ed1ae2ddSpascal paillet 212866cf9a7eSMaciej Purski regulator_lock(rdev); 2129414c70cbSLiam Girdwood list_del(®ulator->list); 2130414c70cbSLiam Girdwood 21315ffbd136SMark Brown rdev->open_count--; 21325ffbd136SMark Brown rdev->exclusive = 0; 213366cf9a7eSMaciej Purski regulator_unlock(rdev); 21345ffbd136SMark Brown 21350630b614SStephen Boyd kfree_const(regulator->supply_name); 21361768514eSMark Brown kfree(regulator); 2137e1794aa4SSaravana Kannan } 2138e1794aa4SSaravana Kannan 2139e1794aa4SSaravana Kannan /* regulator_list_mutex lock held by regulator_put() */ 2140e1794aa4SSaravana Kannan static void _regulator_put(struct regulator *regulator) 2141e1794aa4SSaravana Kannan { 2142e1794aa4SSaravana Kannan struct regulator_dev *rdev; 2143e1794aa4SSaravana Kannan 2144e1794aa4SSaravana Kannan if (IS_ERR_OR_NULL(regulator)) 2145e1794aa4SSaravana Kannan return; 2146e1794aa4SSaravana Kannan 2147e1794aa4SSaravana Kannan lockdep_assert_held_once(®ulator_list_mutex); 2148e1794aa4SSaravana Kannan 2149e1794aa4SSaravana Kannan /* Docs say you must disable before calling regulator_put() */ 2150e1794aa4SSaravana Kannan WARN_ON(regulator->enable_count); 2151e1794aa4SSaravana Kannan 2152e1794aa4SSaravana Kannan rdev = regulator->rdev; 2153e1794aa4SSaravana Kannan 2154e1794aa4SSaravana Kannan destroy_regulator(regulator); 21551768514eSMark Brown 2156414c70cbSLiam Girdwood module_put(rdev->owner); 21574affd79aSWen Yang put_device(&rdev->dev); 215823ff2f0fSCharles Keepax } 215923ff2f0fSCharles Keepax 216023ff2f0fSCharles Keepax /** 216123ff2f0fSCharles Keepax * regulator_put - "free" the regulator source 216223ff2f0fSCharles Keepax * @regulator: regulator source 216323ff2f0fSCharles Keepax * 216423ff2f0fSCharles Keepax * Note: drivers must ensure that all regulator_enable calls made on this 216523ff2f0fSCharles Keepax * regulator source are balanced by regulator_disable calls prior to calling 216623ff2f0fSCharles Keepax * this function. 216723ff2f0fSCharles Keepax */ 216823ff2f0fSCharles Keepax void regulator_put(struct regulator *regulator) 216923ff2f0fSCharles Keepax { 217023ff2f0fSCharles Keepax mutex_lock(®ulator_list_mutex); 217123ff2f0fSCharles Keepax _regulator_put(regulator); 2172414c70cbSLiam Girdwood mutex_unlock(®ulator_list_mutex); 2173414c70cbSLiam Girdwood } 2174414c70cbSLiam Girdwood EXPORT_SYMBOL_GPL(regulator_put); 2175414c70cbSLiam Girdwood 2176a06ccd9cSCharles Keepax /** 2177a06ccd9cSCharles Keepax * regulator_register_supply_alias - Provide device alias for supply lookup 2178a06ccd9cSCharles Keepax * 2179a06ccd9cSCharles Keepax * @dev: device that will be given as the regulator "consumer" 2180a06ccd9cSCharles Keepax * @id: Supply name or regulator ID 2181a06ccd9cSCharles Keepax * @alias_dev: device that should be used to lookup the supply 2182a06ccd9cSCharles Keepax * @alias_id: Supply name or regulator ID that should be used to lookup the 2183a06ccd9cSCharles Keepax * supply 2184a06ccd9cSCharles Keepax * 2185a06ccd9cSCharles Keepax * All lookups for id on dev will instead be conducted for alias_id on 2186a06ccd9cSCharles Keepax * alias_dev. 2187a06ccd9cSCharles Keepax */ 2188a06ccd9cSCharles Keepax int regulator_register_supply_alias(struct device *dev, const char *id, 2189a06ccd9cSCharles Keepax struct device *alias_dev, 2190a06ccd9cSCharles Keepax const char *alias_id) 2191a06ccd9cSCharles Keepax { 2192a06ccd9cSCharles Keepax struct regulator_supply_alias *map; 2193a06ccd9cSCharles Keepax 2194a06ccd9cSCharles Keepax map = regulator_find_supply_alias(dev, id); 2195a06ccd9cSCharles Keepax if (map) 2196a06ccd9cSCharles Keepax return -EEXIST; 2197a06ccd9cSCharles Keepax 2198a06ccd9cSCharles Keepax map = kzalloc(sizeof(struct regulator_supply_alias), GFP_KERNEL); 2199a06ccd9cSCharles Keepax if (!map) 2200a06ccd9cSCharles Keepax return -ENOMEM; 2201a06ccd9cSCharles Keepax 2202a06ccd9cSCharles Keepax map->src_dev = dev; 2203a06ccd9cSCharles Keepax map->src_supply = id; 2204a06ccd9cSCharles Keepax map->alias_dev = alias_dev; 2205a06ccd9cSCharles Keepax map->alias_supply = alias_id; 2206a06ccd9cSCharles Keepax 2207a06ccd9cSCharles Keepax list_add(&map->list, ®ulator_supply_alias_list); 2208a06ccd9cSCharles Keepax 2209a06ccd9cSCharles Keepax pr_info("Adding alias for supply %s,%s -> %s,%s\n", 2210a06ccd9cSCharles Keepax id, dev_name(dev), alias_id, dev_name(alias_dev)); 2211a06ccd9cSCharles Keepax 2212a06ccd9cSCharles Keepax return 0; 2213a06ccd9cSCharles Keepax } 2214a06ccd9cSCharles Keepax EXPORT_SYMBOL_GPL(regulator_register_supply_alias); 2215a06ccd9cSCharles Keepax 2216a06ccd9cSCharles Keepax /** 2217a06ccd9cSCharles Keepax * regulator_unregister_supply_alias - Remove device alias 2218a06ccd9cSCharles Keepax * 2219a06ccd9cSCharles Keepax * @dev: device that will be given as the regulator "consumer" 2220a06ccd9cSCharles Keepax * @id: Supply name or regulator ID 2221a06ccd9cSCharles Keepax * 2222a06ccd9cSCharles Keepax * Remove a lookup alias if one exists for id on dev. 2223a06ccd9cSCharles Keepax */ 2224a06ccd9cSCharles Keepax void regulator_unregister_supply_alias(struct device *dev, const char *id) 2225a06ccd9cSCharles Keepax { 2226a06ccd9cSCharles Keepax struct regulator_supply_alias *map; 2227a06ccd9cSCharles Keepax 2228a06ccd9cSCharles Keepax map = regulator_find_supply_alias(dev, id); 2229a06ccd9cSCharles Keepax if (map) { 2230a06ccd9cSCharles Keepax list_del(&map->list); 2231a06ccd9cSCharles Keepax kfree(map); 2232a06ccd9cSCharles Keepax } 2233a06ccd9cSCharles Keepax } 2234a06ccd9cSCharles Keepax EXPORT_SYMBOL_GPL(regulator_unregister_supply_alias); 2235a06ccd9cSCharles Keepax 2236a06ccd9cSCharles Keepax /** 2237a06ccd9cSCharles Keepax * regulator_bulk_register_supply_alias - register multiple aliases 2238a06ccd9cSCharles Keepax * 2239a06ccd9cSCharles Keepax * @dev: device that will be given as the regulator "consumer" 2240a06ccd9cSCharles Keepax * @id: List of supply names or regulator IDs 2241a06ccd9cSCharles Keepax * @alias_dev: device that should be used to lookup the supply 2242a06ccd9cSCharles Keepax * @alias_id: List of supply names or regulator IDs that should be used to 2243a06ccd9cSCharles Keepax * lookup the supply 2244a06ccd9cSCharles Keepax * @num_id: Number of aliases to register 2245a06ccd9cSCharles Keepax * 2246a06ccd9cSCharles Keepax * @return 0 on success, an errno on failure. 2247a06ccd9cSCharles Keepax * 2248a06ccd9cSCharles Keepax * This helper function allows drivers to register several supply 2249a06ccd9cSCharles Keepax * aliases in one operation. If any of the aliases cannot be 2250a06ccd9cSCharles Keepax * registered any aliases that were registered will be removed 2251a06ccd9cSCharles Keepax * before returning to the caller. 2252a06ccd9cSCharles Keepax */ 22539f8c0fe9SLee Jones int regulator_bulk_register_supply_alias(struct device *dev, 22549f8c0fe9SLee Jones const char *const *id, 2255a06ccd9cSCharles Keepax struct device *alias_dev, 22569f8c0fe9SLee Jones const char *const *alias_id, 2257a06ccd9cSCharles Keepax int num_id) 2258a06ccd9cSCharles Keepax { 2259a06ccd9cSCharles Keepax int i; 2260a06ccd9cSCharles Keepax int ret; 2261a06ccd9cSCharles Keepax 2262a06ccd9cSCharles Keepax for (i = 0; i < num_id; ++i) { 2263a06ccd9cSCharles Keepax ret = regulator_register_supply_alias(dev, id[i], alias_dev, 2264a06ccd9cSCharles Keepax alias_id[i]); 2265a06ccd9cSCharles Keepax if (ret < 0) 2266a06ccd9cSCharles Keepax goto err; 2267a06ccd9cSCharles Keepax } 2268a06ccd9cSCharles Keepax 2269a06ccd9cSCharles Keepax return 0; 2270a06ccd9cSCharles Keepax 2271a06ccd9cSCharles Keepax err: 2272a06ccd9cSCharles Keepax dev_err(dev, 2273a06ccd9cSCharles Keepax "Failed to create supply alias %s,%s -> %s,%s\n", 2274a06ccd9cSCharles Keepax id[i], dev_name(dev), alias_id[i], dev_name(alias_dev)); 2275a06ccd9cSCharles Keepax 2276a06ccd9cSCharles Keepax while (--i >= 0) 2277a06ccd9cSCharles Keepax regulator_unregister_supply_alias(dev, id[i]); 2278a06ccd9cSCharles Keepax 2279a06ccd9cSCharles Keepax return ret; 2280a06ccd9cSCharles Keepax } 2281a06ccd9cSCharles Keepax EXPORT_SYMBOL_GPL(regulator_bulk_register_supply_alias); 2282a06ccd9cSCharles Keepax 2283a06ccd9cSCharles Keepax /** 2284a06ccd9cSCharles Keepax * regulator_bulk_unregister_supply_alias - unregister multiple aliases 2285a06ccd9cSCharles Keepax * 2286a06ccd9cSCharles Keepax * @dev: device that will be given as the regulator "consumer" 2287a06ccd9cSCharles Keepax * @id: List of supply names or regulator IDs 2288a06ccd9cSCharles Keepax * @num_id: Number of aliases to unregister 2289a06ccd9cSCharles Keepax * 2290a06ccd9cSCharles Keepax * This helper function allows drivers to unregister several supply 2291a06ccd9cSCharles Keepax * aliases in one operation. 2292a06ccd9cSCharles Keepax */ 2293a06ccd9cSCharles Keepax void regulator_bulk_unregister_supply_alias(struct device *dev, 22949f8c0fe9SLee Jones const char *const *id, 2295a06ccd9cSCharles Keepax int num_id) 2296a06ccd9cSCharles Keepax { 2297a06ccd9cSCharles Keepax int i; 2298a06ccd9cSCharles Keepax 2299a06ccd9cSCharles Keepax for (i = 0; i < num_id; ++i) 2300a06ccd9cSCharles Keepax regulator_unregister_supply_alias(dev, id[i]); 2301a06ccd9cSCharles Keepax } 2302a06ccd9cSCharles Keepax EXPORT_SYMBOL_GPL(regulator_bulk_unregister_supply_alias); 2303a06ccd9cSCharles Keepax 2304a06ccd9cSCharles Keepax 2305f19b00daSKim, Milo /* Manage enable GPIO list. Same GPIO pin can be shared among regulators */ 2306f19b00daSKim, Milo static int regulator_ena_gpio_request(struct regulator_dev *rdev, 2307f19b00daSKim, Milo const struct regulator_config *config) 2308f19b00daSKim, Milo { 2309467bf301SMichał Mirosław struct regulator_enable_gpio *pin, *new_pin; 2310778b28b4SRussell King struct gpio_desc *gpiod; 2311f19b00daSKim, Milo 2312e45e290aSLinus Walleij gpiod = config->ena_gpiod; 2313467bf301SMichał Mirosław new_pin = kzalloc(sizeof(*new_pin), GFP_KERNEL); 2314467bf301SMichał Mirosław 2315467bf301SMichał Mirosław mutex_lock(®ulator_list_mutex); 2316778b28b4SRussell King 2317f19b00daSKim, Milo list_for_each_entry(pin, ®ulator_ena_gpio_list, list) { 2318778b28b4SRussell King if (pin->gpiod == gpiod) { 2319541d052dSLinus Walleij rdev_dbg(rdev, "GPIO is already used\n"); 2320f19b00daSKim, Milo goto update_ena_gpio_to_rdev; 2321f19b00daSKim, Milo } 2322f19b00daSKim, Milo } 2323f19b00daSKim, Milo 2324467bf301SMichał Mirosław if (new_pin == NULL) { 2325467bf301SMichał Mirosław mutex_unlock(®ulator_list_mutex); 2326f19b00daSKim, Milo return -ENOMEM; 2327467bf301SMichał Mirosław } 2328467bf301SMichał Mirosław 2329467bf301SMichał Mirosław pin = new_pin; 2330467bf301SMichał Mirosław new_pin = NULL; 2331f19b00daSKim, Milo 2332778b28b4SRussell King pin->gpiod = gpiod; 2333f19b00daSKim, Milo list_add(&pin->list, ®ulator_ena_gpio_list); 2334f19b00daSKim, Milo 2335f19b00daSKim, Milo update_ena_gpio_to_rdev: 2336f19b00daSKim, Milo pin->request_count++; 2337f19b00daSKim, Milo rdev->ena_pin = pin; 2338467bf301SMichał Mirosław 2339467bf301SMichał Mirosław mutex_unlock(®ulator_list_mutex); 2340467bf301SMichał Mirosław kfree(new_pin); 2341467bf301SMichał Mirosław 2342f19b00daSKim, Milo return 0; 2343f19b00daSKim, Milo } 2344f19b00daSKim, Milo 2345f19b00daSKim, Milo static void regulator_ena_gpio_free(struct regulator_dev *rdev) 2346f19b00daSKim, Milo { 2347f19b00daSKim, Milo struct regulator_enable_gpio *pin, *n; 2348f19b00daSKim, Milo 2349f19b00daSKim, Milo if (!rdev->ena_pin) 2350f19b00daSKim, Milo return; 2351f19b00daSKim, Milo 2352f19b00daSKim, Milo /* Free the GPIO only in case of no use */ 2353f19b00daSKim, Milo list_for_each_entry_safe(pin, n, ®ulator_ena_gpio_list, list) { 23542dbf0855SMichał Mirosław if (pin != rdev->ena_pin) 23552dbf0855SMichał Mirosław continue; 23562dbf0855SMichał Mirosław 23572dbf0855SMichał Mirosław if (--pin->request_count) 23582dbf0855SMichał Mirosław break; 23592dbf0855SMichał Mirosław 236078927aa4SLinus Walleij gpiod_put(pin->gpiod); 2361f19b00daSKim, Milo list_del(&pin->list); 2362f19b00daSKim, Milo kfree(pin); 23632dbf0855SMichał Mirosław break; 23642dbf0855SMichał Mirosław } 23652dbf0855SMichał Mirosław 236660a2362fSSeung-Woo Kim rdev->ena_pin = NULL; 2367f19b00daSKim, Milo } 2368f19b00daSKim, Milo 2369967cfb18SKim, Milo /** 237031d6eebfSRobert P. J. Day * regulator_ena_gpio_ctrl - balance enable_count of each GPIO and actual GPIO pin control 237131d6eebfSRobert P. J. Day * @rdev: regulator_dev structure 237231d6eebfSRobert P. J. Day * @enable: enable GPIO at initial use? 237331d6eebfSRobert P. J. Day * 2374967cfb18SKim, Milo * GPIO is enabled in case of initial use. (enable_count is 0) 2375967cfb18SKim, Milo * GPIO is disabled when it is not shared any more. (enable_count <= 1) 2376967cfb18SKim, Milo */ 2377967cfb18SKim, Milo static int regulator_ena_gpio_ctrl(struct regulator_dev *rdev, bool enable) 2378967cfb18SKim, Milo { 2379967cfb18SKim, Milo struct regulator_enable_gpio *pin = rdev->ena_pin; 2380967cfb18SKim, Milo 2381967cfb18SKim, Milo if (!pin) 2382967cfb18SKim, Milo return -EINVAL; 2383967cfb18SKim, Milo 2384967cfb18SKim, Milo if (enable) { 2385967cfb18SKim, Milo /* Enable GPIO at initial use */ 2386967cfb18SKim, Milo if (pin->enable_count == 0) 238701dc79cdSLinus Walleij gpiod_set_value_cansleep(pin->gpiod, 1); 2388967cfb18SKim, Milo 2389967cfb18SKim, Milo pin->enable_count++; 2390967cfb18SKim, Milo } else { 2391967cfb18SKim, Milo if (pin->enable_count > 1) { 2392967cfb18SKim, Milo pin->enable_count--; 2393967cfb18SKim, Milo return 0; 2394967cfb18SKim, Milo } 2395967cfb18SKim, Milo 2396967cfb18SKim, Milo /* Disable GPIO if not used */ 2397967cfb18SKim, Milo if (pin->enable_count <= 1) { 239801dc79cdSLinus Walleij gpiod_set_value_cansleep(pin->gpiod, 0); 2399967cfb18SKim, Milo pin->enable_count = 0; 2400967cfb18SKim, Milo } 2401967cfb18SKim, Milo } 2402967cfb18SKim, Milo 2403967cfb18SKim, Milo return 0; 2404967cfb18SKim, Milo } 2405967cfb18SKim, Milo 240679fd1141SGuodong Xu /** 240779fd1141SGuodong Xu * _regulator_enable_delay - a delay helper function 240879fd1141SGuodong Xu * @delay: time to delay in microseconds 240979fd1141SGuodong Xu * 24105df529d4SThierry Reding * Delay for the requested amount of time as per the guidelines in: 24115df529d4SThierry Reding * 2412458f69efSMauro Carvalho Chehab * Documentation/timers/timers-howto.rst 24135df529d4SThierry Reding * 24145df529d4SThierry Reding * The assumption here is that regulators will never be enabled in 24155df529d4SThierry Reding * atomic context and therefore sleeping functions can be used. 24165df529d4SThierry Reding */ 241779fd1141SGuodong Xu static void _regulator_enable_delay(unsigned int delay) 241879fd1141SGuodong Xu { 24195df529d4SThierry Reding unsigned int ms = delay / 1000; 24205df529d4SThierry Reding unsigned int us = delay % 1000; 24215df529d4SThierry Reding 24225df529d4SThierry Reding if (ms > 0) { 24235df529d4SThierry Reding /* 24245df529d4SThierry Reding * For small enough values, handle super-millisecond 24255df529d4SThierry Reding * delays in the usleep_range() call below. 24265df529d4SThierry Reding */ 24275df529d4SThierry Reding if (ms < 20) 24285df529d4SThierry Reding us += ms * 1000; 24295df529d4SThierry Reding else 24305df529d4SThierry Reding msleep(ms); 24315df529d4SThierry Reding } 24325df529d4SThierry Reding 24335df529d4SThierry Reding /* 24345df529d4SThierry Reding * Give the scheduler some room to coalesce with any other 24355df529d4SThierry Reding * wakeup sources. For delays shorter than 10 us, don't even 24365df529d4SThierry Reding * bother setting up high-resolution timers and just busy- 24375df529d4SThierry Reding * loop. 24385df529d4SThierry Reding */ 24395df529d4SThierry Reding if (us >= 10) 24405df529d4SThierry Reding usleep_range(us, us + 100); 24415df529d4SThierry Reding else 24425df529d4SThierry Reding udelay(us); 24435c5659d0SMark Brown } 24445c5659d0SMark Brown 2445f7d7ad42SSumit Semwal /** 2446f7d7ad42SSumit Semwal * _regulator_check_status_enabled 2447f7d7ad42SSumit Semwal * 2448f7d7ad42SSumit Semwal * A helper function to check if the regulator status can be interpreted 2449f7d7ad42SSumit Semwal * as 'regulator is enabled'. 2450f7d7ad42SSumit Semwal * @rdev: the regulator device to check 2451f7d7ad42SSumit Semwal * 2452f7d7ad42SSumit Semwal * Return: 2453f7d7ad42SSumit Semwal * * 1 - if status shows regulator is in enabled state 2454f7d7ad42SSumit Semwal * * 0 - if not enabled state 2455f7d7ad42SSumit Semwal * * Error Value - as received from ops->get_status() 2456f7d7ad42SSumit Semwal */ 2457f7d7ad42SSumit Semwal static inline int _regulator_check_status_enabled(struct regulator_dev *rdev) 2458f7d7ad42SSumit Semwal { 2459f7d7ad42SSumit Semwal int ret = rdev->desc->ops->get_status(rdev); 2460f7d7ad42SSumit Semwal 2461f7d7ad42SSumit Semwal if (ret < 0) { 2462f7d7ad42SSumit Semwal rdev_info(rdev, "get_status returned error: %d\n", ret); 2463f7d7ad42SSumit Semwal return ret; 2464f7d7ad42SSumit Semwal } 2465f7d7ad42SSumit Semwal 2466f7d7ad42SSumit Semwal switch (ret) { 2467f7d7ad42SSumit Semwal case REGULATOR_STATUS_OFF: 2468f7d7ad42SSumit Semwal case REGULATOR_STATUS_ERROR: 2469f7d7ad42SSumit Semwal case REGULATOR_STATUS_UNDEFINED: 2470f7d7ad42SSumit Semwal return 0; 2471f7d7ad42SSumit Semwal default: 2472f7d7ad42SSumit Semwal return 1; 2473f7d7ad42SSumit Semwal } 2474f7d7ad42SSumit Semwal } 2475f7d7ad42SSumit Semwal 24765c5659d0SMark Brown static int _regulator_do_enable(struct regulator_dev *rdev) 24775c5659d0SMark Brown { 24785c5659d0SMark Brown int ret, delay; 24795c5659d0SMark Brown 24805c5659d0SMark Brown /* Query before enabling in case configuration dependent. */ 24815c5659d0SMark Brown ret = _regulator_get_enable_time(rdev); 24825c5659d0SMark Brown if (ret >= 0) { 24835c5659d0SMark Brown delay = ret; 24845c5659d0SMark Brown } else { 248561aab5adSMichał Mirosław rdev_warn(rdev, "enable_time() failed: %pe\n", ERR_PTR(ret)); 2486414c70cbSLiam Girdwood delay = 0; 2487414c70cbSLiam Girdwood } 24885c5659d0SMark Brown 2489414c70cbSLiam Girdwood trace_regulator_enable(rdev_get_name(rdev)); 2490414c70cbSLiam Girdwood 2491a8ce7bd8SVincent Whitchurch if (rdev->desc->off_on_delay && rdev->last_off) { 2492871f5650SGuodong Xu /* if needed, keep a distance of off_on_delay from last time 2493871f5650SGuodong Xu * this regulator was disabled. 2494871f5650SGuodong Xu */ 2495a8ce7bd8SVincent Whitchurch ktime_t end = ktime_add_us(rdev->last_off, rdev->desc->off_on_delay); 2496a8ce7bd8SVincent Whitchurch s64 remaining = ktime_us_delta(end, ktime_get()); 2497871f5650SGuodong Xu 2498a8ce7bd8SVincent Whitchurch if (remaining > 0) 2499a8ce7bd8SVincent Whitchurch _regulator_enable_delay(remaining); 2500871f5650SGuodong Xu } 2501871f5650SGuodong Xu 2502414c70cbSLiam Girdwood if (rdev->ena_pin) { 250329d62ec5SDoug Anderson if (!rdev->ena_gpio_state) { 25049a2372faSMark Brown ret = regulator_ena_gpio_ctrl(rdev, true); 2505414c70cbSLiam Girdwood if (ret < 0) 2506414c70cbSLiam Girdwood return ret; 25079a2372faSMark Brown rdev->ena_gpio_state = 1; 250829d62ec5SDoug Anderson } 25099a2372faSMark Brown } else if (rdev->desc->ops->enable) { 25109a2372faSMark Brown ret = rdev->desc->ops->enable(rdev); 25119a2372faSMark Brown if (ret < 0) 25129a2372faSMark Brown return ret; 25139a2372faSMark Brown } else { 25149a2372faSMark Brown return -EINVAL; 25155c5659d0SMark Brown } 25169a2372faSMark Brown 25179a2372faSMark Brown /* Allow the regulator to ramp; it would be useful to extend 251831aae2beSMark Brown * this for bulk operations so that the regulators can ramp 251969b8821eSShubhankar Kuranagatti * together. 252069b8821eSShubhankar Kuranagatti */ 25215da84fd9SJoe Perches trace_regulator_enable_delay(rdev_get_name(rdev)); 2522414c70cbSLiam Girdwood 2523f7d7ad42SSumit Semwal /* If poll_enabled_time is set, poll upto the delay calculated 2524f7d7ad42SSumit Semwal * above, delaying poll_enabled_time uS to check if the regulator 2525f7d7ad42SSumit Semwal * actually got enabled. 2526f7d7ad42SSumit Semwal * If the regulator isn't enabled after enable_delay has 2527f7d7ad42SSumit Semwal * expired, return -ETIMEDOUT. 2528f7d7ad42SSumit Semwal */ 2529f7d7ad42SSumit Semwal if (rdev->desc->poll_enabled_time) { 2530f7d7ad42SSumit Semwal unsigned int time_remaining = delay; 2531f7d7ad42SSumit Semwal 2532f7d7ad42SSumit Semwal while (time_remaining > 0) { 2533f7d7ad42SSumit Semwal _regulator_enable_delay(rdev->desc->poll_enabled_time); 2534f7d7ad42SSumit Semwal 2535f7d7ad42SSumit Semwal if (rdev->desc->ops->get_status) { 2536f7d7ad42SSumit Semwal ret = _regulator_check_status_enabled(rdev); 2537f7d7ad42SSumit Semwal if (ret < 0) 2538f7d7ad42SSumit Semwal return ret; 2539f7d7ad42SSumit Semwal else if (ret) 2540f7d7ad42SSumit Semwal break; 2541f7d7ad42SSumit Semwal } else if (rdev->desc->ops->is_enabled(rdev)) 2542f7d7ad42SSumit Semwal break; 2543f7d7ad42SSumit Semwal 2544f7d7ad42SSumit Semwal time_remaining -= rdev->desc->poll_enabled_time; 2545f7d7ad42SSumit Semwal } 2546f7d7ad42SSumit Semwal 2547f7d7ad42SSumit Semwal if (time_remaining <= 0) { 2548f7d7ad42SSumit Semwal rdev_err(rdev, "Enabled check timed out\n"); 2549f7d7ad42SSumit Semwal return -ETIMEDOUT; 2550f7d7ad42SSumit Semwal } 2551f7d7ad42SSumit Semwal } else { 255279fd1141SGuodong Xu _regulator_enable_delay(delay); 2553f7d7ad42SSumit Semwal } 2554a7433cffSLinus Walleij 2555414c70cbSLiam Girdwood trace_regulator_enable_complete(rdev_get_name(rdev)); 2556414c70cbSLiam Girdwood 25579a2372faSMark Brown return 0; 25589a2372faSMark Brown } 25599a2372faSMark Brown 25605451781dSDouglas Anderson /** 25615451781dSDouglas Anderson * _regulator_handle_consumer_enable - handle that a consumer enabled 25625451781dSDouglas Anderson * @regulator: regulator source 25635451781dSDouglas Anderson * 25645451781dSDouglas Anderson * Some things on a regulator consumer (like the contribution towards total 25655451781dSDouglas Anderson * load on the regulator) only have an effect when the consumer wants the 25665451781dSDouglas Anderson * regulator enabled. Explained in example with two consumers of the same 25675451781dSDouglas Anderson * regulator: 25685451781dSDouglas Anderson * consumer A: set_load(100); => total load = 0 25695451781dSDouglas Anderson * consumer A: regulator_enable(); => total load = 100 25705451781dSDouglas Anderson * consumer B: set_load(1000); => total load = 100 25715451781dSDouglas Anderson * consumer B: regulator_enable(); => total load = 1100 25725451781dSDouglas Anderson * consumer A: regulator_disable(); => total_load = 1000 25735451781dSDouglas Anderson * 25745451781dSDouglas Anderson * This function (together with _regulator_handle_consumer_disable) is 25755451781dSDouglas Anderson * responsible for keeping track of the refcount for a given regulator consumer 25765451781dSDouglas Anderson * and applying / unapplying these things. 25775451781dSDouglas Anderson * 25785451781dSDouglas Anderson * Returns 0 upon no error; -error upon error. 25795451781dSDouglas Anderson */ 25805451781dSDouglas Anderson static int _regulator_handle_consumer_enable(struct regulator *regulator) 2581414c70cbSLiam Girdwood { 25825451781dSDouglas Anderson struct regulator_dev *rdev = regulator->rdev; 25835451781dSDouglas Anderson 25845451781dSDouglas Anderson lockdep_assert_held_once(&rdev->mutex.base); 25855451781dSDouglas Anderson 25865451781dSDouglas Anderson regulator->enable_count++; 25875451781dSDouglas Anderson if (regulator->uA_load && regulator->enable_count == 1) 25885451781dSDouglas Anderson return drms_uA_update(rdev); 25895451781dSDouglas Anderson 25905451781dSDouglas Anderson return 0; 25915451781dSDouglas Anderson } 25925451781dSDouglas Anderson 25935451781dSDouglas Anderson /** 25945451781dSDouglas Anderson * _regulator_handle_consumer_disable - handle that a consumer disabled 25955451781dSDouglas Anderson * @regulator: regulator source 25965451781dSDouglas Anderson * 25975451781dSDouglas Anderson * The opposite of _regulator_handle_consumer_enable(). 25985451781dSDouglas Anderson * 25995451781dSDouglas Anderson * Returns 0 upon no error; -error upon error. 26005451781dSDouglas Anderson */ 26015451781dSDouglas Anderson static int _regulator_handle_consumer_disable(struct regulator *regulator) 26025451781dSDouglas Anderson { 26035451781dSDouglas Anderson struct regulator_dev *rdev = regulator->rdev; 26045451781dSDouglas Anderson 26055451781dSDouglas Anderson lockdep_assert_held_once(&rdev->mutex.base); 26065451781dSDouglas Anderson 26075451781dSDouglas Anderson if (!regulator->enable_count) { 26085451781dSDouglas Anderson rdev_err(rdev, "Underflow of regulator enable count\n"); 26095451781dSDouglas Anderson return -EINVAL; 26105451781dSDouglas Anderson } 26115451781dSDouglas Anderson 26125451781dSDouglas Anderson regulator->enable_count--; 26135451781dSDouglas Anderson if (regulator->uA_load && regulator->enable_count == 0) 26145451781dSDouglas Anderson return drms_uA_update(rdev); 26155451781dSDouglas Anderson 26165451781dSDouglas Anderson return 0; 26175451781dSDouglas Anderson } 26185451781dSDouglas Anderson 26195451781dSDouglas Anderson /* locks held by regulator_enable() */ 26205451781dSDouglas Anderson static int _regulator_enable(struct regulator *regulator) 26215451781dSDouglas Anderson { 26225451781dSDouglas Anderson struct regulator_dev *rdev = regulator->rdev; 2623414c70cbSLiam Girdwood int ret; 2624414c70cbSLiam Girdwood 2625f8702f9eSDmitry Osipenko lockdep_assert_held_once(&rdev->mutex.base); 2626f8702f9eSDmitry Osipenko 26271fc12b05SDouglas Anderson if (rdev->use_count == 0 && rdev->supply) { 26285451781dSDouglas Anderson ret = _regulator_enable(rdev->supply); 2629f8702f9eSDmitry Osipenko if (ret < 0) 2630f8702f9eSDmitry Osipenko return ret; 2631f8702f9eSDmitry Osipenko } 2632f8702f9eSDmitry Osipenko 2633f8702f9eSDmitry Osipenko /* balance only if there are regulators coupled */ 2634f8702f9eSDmitry Osipenko if (rdev->coupling_desc.n_coupled > 1) { 2635f8702f9eSDmitry Osipenko ret = regulator_balance_voltage(rdev, PM_SUSPEND_ON); 2636f8702f9eSDmitry Osipenko if (ret < 0) 2637f8702f9eSDmitry Osipenko goto err_disable_supply; 2638f8702f9eSDmitry Osipenko } 263970cfef26SKrzysztof Kozlowski 26405451781dSDouglas Anderson ret = _regulator_handle_consumer_enable(regulator); 26415451781dSDouglas Anderson if (ret < 0) 26425451781dSDouglas Anderson goto err_disable_supply; 2643cf7bbcdfSMark Brown 2644414c70cbSLiam Girdwood if (rdev->use_count == 0) { 264572241e31SSebastian Fricke /* 264672241e31SSebastian Fricke * The regulator may already be enabled if it's not switchable 264772241e31SSebastian Fricke * or was left on 264872241e31SSebastian Fricke */ 2649414c70cbSLiam Girdwood ret = _regulator_is_enabled(rdev); 2650414c70cbSLiam Girdwood if (ret == -EINVAL || ret == 0) { 26518a34e979SWEN Pingbo if (!regulator_ops_is_valid(rdev, 2652f8702f9eSDmitry Osipenko REGULATOR_CHANGE_STATUS)) { 2653f8702f9eSDmitry Osipenko ret = -EPERM; 26545451781dSDouglas Anderson goto err_consumer_disable; 2655f8702f9eSDmitry Osipenko } 2656412aec61SDavid Brownell 2657414c70cbSLiam Girdwood ret = _regulator_do_enable(rdev); 2658412aec61SDavid Brownell if (ret < 0) 26595451781dSDouglas Anderson goto err_consumer_disable; 2660414c70cbSLiam Girdwood 2661264b88c9SHarald Geyer _notifier_call_chain(rdev, REGULATOR_EVENT_ENABLE, 2662264b88c9SHarald Geyer NULL); 2663414c70cbSLiam Girdwood } else if (ret < 0) { 266461aab5adSMichał Mirosław rdev_err(rdev, "is_enabled() failed: %pe\n", ERR_PTR(ret)); 26655451781dSDouglas Anderson goto err_consumer_disable; 2666414c70cbSLiam Girdwood } 2667414c70cbSLiam Girdwood /* Fallthrough on positive return values - already enabled */ 2668414c70cbSLiam Girdwood } 2669414c70cbSLiam Girdwood 2670414c70cbSLiam Girdwood rdev->use_count++; 2671414c70cbSLiam Girdwood 2672414c70cbSLiam Girdwood return 0; 2673f8702f9eSDmitry Osipenko 26745451781dSDouglas Anderson err_consumer_disable: 26755451781dSDouglas Anderson _regulator_handle_consumer_disable(regulator); 26765451781dSDouglas Anderson 2677f8702f9eSDmitry Osipenko err_disable_supply: 26781fc12b05SDouglas Anderson if (rdev->use_count == 0 && rdev->supply) 26795451781dSDouglas Anderson _regulator_disable(rdev->supply); 2680f8702f9eSDmitry Osipenko 2681f8702f9eSDmitry Osipenko return ret; 2682414c70cbSLiam Girdwood } 2683414c70cbSLiam Girdwood 2684414c70cbSLiam Girdwood /** 2685414c70cbSLiam Girdwood * regulator_enable - enable regulator output 2686414c70cbSLiam Girdwood * @regulator: regulator source 2687414c70cbSLiam Girdwood * 2688414c70cbSLiam Girdwood * Request that the regulator be enabled with the regulator output at 2689414c70cbSLiam Girdwood * the predefined voltage or current value. Calls to regulator_enable() 2690414c70cbSLiam Girdwood * must be balanced with calls to regulator_disable(). 2691414c70cbSLiam Girdwood * 2692414c70cbSLiam Girdwood * NOTE: the output value can be set by other drivers, boot loader or may be 2693414c70cbSLiam Girdwood * hardwired in the regulator. 2694414c70cbSLiam Girdwood */ 2695414c70cbSLiam Girdwood int regulator_enable(struct regulator *regulator) 2696414c70cbSLiam Girdwood { 2697414c70cbSLiam Girdwood struct regulator_dev *rdev = regulator->rdev; 2698f8702f9eSDmitry Osipenko struct ww_acquire_ctx ww_ctx; 26995451781dSDouglas Anderson int ret; 27006492bc1bSMark Brown 2701f8702f9eSDmitry Osipenko regulator_lock_dependent(rdev, &ww_ctx); 27025451781dSDouglas Anderson ret = _regulator_enable(regulator); 2703f8702f9eSDmitry Osipenko regulator_unlock_dependent(rdev, &ww_ctx); 27043801b86aSMark Brown 2705414c70cbSLiam Girdwood return ret; 2706414c70cbSLiam Girdwood } 2707414c70cbSLiam Girdwood EXPORT_SYMBOL_GPL(regulator_enable); 2708414c70cbSLiam Girdwood 27095c5659d0SMark Brown static int _regulator_do_disable(struct regulator_dev *rdev) 27105c5659d0SMark Brown { 27115c5659d0SMark Brown int ret; 27125c5659d0SMark Brown 27135c5659d0SMark Brown trace_regulator_disable(rdev_get_name(rdev)); 27145c5659d0SMark Brown 2715967cfb18SKim, Milo if (rdev->ena_pin) { 271629d62ec5SDoug Anderson if (rdev->ena_gpio_state) { 2717967cfb18SKim, Milo ret = regulator_ena_gpio_ctrl(rdev, false); 2718967cfb18SKim, Milo if (ret < 0) 2719967cfb18SKim, Milo return ret; 27205c5659d0SMark Brown rdev->ena_gpio_state = 0; 272129d62ec5SDoug Anderson } 27225c5659d0SMark Brown 27235c5659d0SMark Brown } else if (rdev->desc->ops->disable) { 27245c5659d0SMark Brown ret = rdev->desc->ops->disable(rdev); 27255c5659d0SMark Brown if (ret != 0) 27265c5659d0SMark Brown return ret; 27275c5659d0SMark Brown } 27285c5659d0SMark Brown 2729871f5650SGuodong Xu if (rdev->desc->off_on_delay) 2730a8ce7bd8SVincent Whitchurch rdev->last_off = ktime_get(); 2731871f5650SGuodong Xu 27325c5659d0SMark Brown trace_regulator_disable_complete(rdev_get_name(rdev)); 27335c5659d0SMark Brown 27345c5659d0SMark Brown return 0; 27355c5659d0SMark Brown } 27365c5659d0SMark Brown 2737414c70cbSLiam Girdwood /* locks held by regulator_disable() */ 27385451781dSDouglas Anderson static int _regulator_disable(struct regulator *regulator) 2739414c70cbSLiam Girdwood { 27405451781dSDouglas Anderson struct regulator_dev *rdev = regulator->rdev; 2741414c70cbSLiam Girdwood int ret = 0; 2742414c70cbSLiam Girdwood 2743f8702f9eSDmitry Osipenko lockdep_assert_held_once(&rdev->mutex.base); 274470cfef26SKrzysztof Kozlowski 2745cd94b505SDavid Brownell if (WARN(rdev->use_count <= 0, 274643e7ee33SJoe Perches "unbalanced disables for %s\n", rdev_get_name(rdev))) 2747cd94b505SDavid Brownell return -EIO; 2748cd94b505SDavid Brownell 2749414c70cbSLiam Girdwood /* are we the last user and permitted to disable ? */ 275060ef66fcSMark Brown if (rdev->use_count == 1 && 275160ef66fcSMark Brown (rdev->constraints && !rdev->constraints->always_on)) { 2752414c70cbSLiam Girdwood 2753414c70cbSLiam Girdwood /* we are last user */ 27548a34e979SWEN Pingbo if (regulator_ops_is_valid(rdev, REGULATOR_CHANGE_STATUS)) { 2755a1c8a551SRichard Fitzgerald ret = _notifier_call_chain(rdev, 2756a1c8a551SRichard Fitzgerald REGULATOR_EVENT_PRE_DISABLE, 2757a1c8a551SRichard Fitzgerald NULL); 2758a1c8a551SRichard Fitzgerald if (ret & NOTIFY_STOP_MASK) 2759a1c8a551SRichard Fitzgerald return -EINVAL; 2760a1c8a551SRichard Fitzgerald 27615c5659d0SMark Brown ret = _regulator_do_disable(rdev); 2762414c70cbSLiam Girdwood if (ret < 0) { 276361aab5adSMichał Mirosław rdev_err(rdev, "failed to disable: %pe\n", ERR_PTR(ret)); 2764a1c8a551SRichard Fitzgerald _notifier_call_chain(rdev, 2765a1c8a551SRichard Fitzgerald REGULATOR_EVENT_ABORT_DISABLE, 2766a1c8a551SRichard Fitzgerald NULL); 2767414c70cbSLiam Girdwood return ret; 2768414c70cbSLiam Girdwood } 276966fda75fSMarkus Pargmann _notifier_call_chain(rdev, REGULATOR_EVENT_DISABLE, 277066fda75fSMarkus Pargmann NULL); 2771414c70cbSLiam Girdwood } 2772414c70cbSLiam Girdwood 2773414c70cbSLiam Girdwood rdev->use_count = 0; 2774414c70cbSLiam Girdwood } else if (rdev->use_count > 1) { 2775414c70cbSLiam Girdwood rdev->use_count--; 2776414c70cbSLiam Girdwood } 27773801b86aSMark Brown 27785451781dSDouglas Anderson if (ret == 0) 27795451781dSDouglas Anderson ret = _regulator_handle_consumer_disable(regulator); 27805451781dSDouglas Anderson 2781f8702f9eSDmitry Osipenko if (ret == 0 && rdev->coupling_desc.n_coupled > 1) 2782f8702f9eSDmitry Osipenko ret = regulator_balance_voltage(rdev, PM_SUSPEND_ON); 2783f8702f9eSDmitry Osipenko 27841fc12b05SDouglas Anderson if (ret == 0 && rdev->use_count == 0 && rdev->supply) 27855451781dSDouglas Anderson ret = _regulator_disable(rdev->supply); 2786f8702f9eSDmitry Osipenko 2787414c70cbSLiam Girdwood return ret; 2788414c70cbSLiam Girdwood } 2789414c70cbSLiam Girdwood 2790414c70cbSLiam Girdwood /** 2791414c70cbSLiam Girdwood * regulator_disable - disable regulator output 2792414c70cbSLiam Girdwood * @regulator: regulator source 2793414c70cbSLiam Girdwood * 2794cf7bbcdfSMark Brown * Disable the regulator output voltage or current. Calls to 2795cf7bbcdfSMark Brown * regulator_enable() must be balanced with calls to 2796cf7bbcdfSMark Brown * regulator_disable(). 279769279fb9SMark Brown * 2798414c70cbSLiam Girdwood * NOTE: this will only disable the regulator output if no other consumer 2799cf7bbcdfSMark Brown * devices have it enabled, the regulator device supports disabling and 2800cf7bbcdfSMark Brown * machine constraints permit this operation. 2801414c70cbSLiam Girdwood */ 2802414c70cbSLiam Girdwood int regulator_disable(struct regulator *regulator) 2803414c70cbSLiam Girdwood { 2804412aec61SDavid Brownell struct regulator_dev *rdev = regulator->rdev; 2805f8702f9eSDmitry Osipenko struct ww_acquire_ctx ww_ctx; 28065451781dSDouglas Anderson int ret; 28076492bc1bSMark Brown 2808f8702f9eSDmitry Osipenko regulator_lock_dependent(rdev, &ww_ctx); 28095451781dSDouglas Anderson ret = _regulator_disable(regulator); 2810f8702f9eSDmitry Osipenko regulator_unlock_dependent(rdev, &ww_ctx); 28118cbf811dSJeffrey Carlyle 2812414c70cbSLiam Girdwood return ret; 2813414c70cbSLiam Girdwood } 2814414c70cbSLiam Girdwood EXPORT_SYMBOL_GPL(regulator_disable); 2815414c70cbSLiam Girdwood 2816414c70cbSLiam Girdwood /* locks held by regulator_force_disable() */ 28173801b86aSMark Brown static int _regulator_force_disable(struct regulator_dev *rdev) 2818414c70cbSLiam Girdwood { 2819414c70cbSLiam Girdwood int ret = 0; 2820414c70cbSLiam Girdwood 2821f8702f9eSDmitry Osipenko lockdep_assert_held_once(&rdev->mutex.base); 282270cfef26SKrzysztof Kozlowski 2823a1c8a551SRichard Fitzgerald ret = _notifier_call_chain(rdev, REGULATOR_EVENT_FORCE_DISABLE | 2824a1c8a551SRichard Fitzgerald REGULATOR_EVENT_PRE_DISABLE, NULL); 2825a1c8a551SRichard Fitzgerald if (ret & NOTIFY_STOP_MASK) 2826a1c8a551SRichard Fitzgerald return -EINVAL; 2827a1c8a551SRichard Fitzgerald 282866fda75fSMarkus Pargmann ret = _regulator_do_disable(rdev); 2829414c70cbSLiam Girdwood if (ret < 0) { 283061aab5adSMichał Mirosław rdev_err(rdev, "failed to force disable: %pe\n", ERR_PTR(ret)); 2831a1c8a551SRichard Fitzgerald _notifier_call_chain(rdev, REGULATOR_EVENT_FORCE_DISABLE | 2832a1c8a551SRichard Fitzgerald REGULATOR_EVENT_ABORT_DISABLE, NULL); 2833414c70cbSLiam Girdwood return ret; 2834414c70cbSLiam Girdwood } 283566fda75fSMarkus Pargmann 283684b68263SMark Brown _notifier_call_chain(rdev, REGULATOR_EVENT_FORCE_DISABLE | 283784b68263SMark Brown REGULATOR_EVENT_DISABLE, NULL); 2838414c70cbSLiam Girdwood 283966fda75fSMarkus Pargmann return 0; 2840414c70cbSLiam Girdwood } 2841414c70cbSLiam Girdwood 2842414c70cbSLiam Girdwood /** 2843414c70cbSLiam Girdwood * regulator_force_disable - force disable regulator output 2844414c70cbSLiam Girdwood * @regulator: regulator source 2845414c70cbSLiam Girdwood * 2846414c70cbSLiam Girdwood * Forcibly disable the regulator output voltage or current. 2847414c70cbSLiam Girdwood * NOTE: this *will* disable the regulator output even if other consumer 2848414c70cbSLiam Girdwood * devices have it enabled. This should be used for situations when device 2849414c70cbSLiam Girdwood * damage will likely occur if the regulator is not disabled (e.g. over temp). 2850414c70cbSLiam Girdwood */ 2851414c70cbSLiam Girdwood int regulator_force_disable(struct regulator *regulator) 2852414c70cbSLiam Girdwood { 285382d15839SMark Brown struct regulator_dev *rdev = regulator->rdev; 2854f8702f9eSDmitry Osipenko struct ww_acquire_ctx ww_ctx; 2855414c70cbSLiam Girdwood int ret; 2856414c70cbSLiam Girdwood 2857f8702f9eSDmitry Osipenko regulator_lock_dependent(rdev, &ww_ctx); 28585451781dSDouglas Anderson 28593801b86aSMark Brown ret = _regulator_force_disable(regulator->rdev); 28605451781dSDouglas Anderson 28619243a195SMaciej Purski if (rdev->coupling_desc.n_coupled > 1) 28629243a195SMaciej Purski regulator_balance_voltage(rdev, PM_SUSPEND_ON); 28635451781dSDouglas Anderson 28645451781dSDouglas Anderson if (regulator->uA_load) { 28655451781dSDouglas Anderson regulator->uA_load = 0; 28665451781dSDouglas Anderson ret = drms_uA_update(rdev); 28675451781dSDouglas Anderson } 28685451781dSDouglas Anderson 28691fc12b05SDouglas Anderson if (rdev->use_count != 0 && rdev->supply) 28701fc12b05SDouglas Anderson _regulator_disable(rdev->supply); 28718cbf811dSJeffrey Carlyle 28721fc12b05SDouglas Anderson regulator_unlock_dependent(rdev, &ww_ctx); 28738cbf811dSJeffrey Carlyle 2874414c70cbSLiam Girdwood return ret; 2875414c70cbSLiam Girdwood } 2876414c70cbSLiam Girdwood EXPORT_SYMBOL_GPL(regulator_force_disable); 2877414c70cbSLiam Girdwood 2878da07ecd9SMark Brown static void regulator_disable_work(struct work_struct *work) 2879da07ecd9SMark Brown { 2880da07ecd9SMark Brown struct regulator_dev *rdev = container_of(work, struct regulator_dev, 2881da07ecd9SMark Brown disable_work.work); 2882f8702f9eSDmitry Osipenko struct ww_acquire_ctx ww_ctx; 2883da07ecd9SMark Brown int count, i, ret; 28845451781dSDouglas Anderson struct regulator *regulator; 28855451781dSDouglas Anderson int total_count = 0; 2886da07ecd9SMark Brown 2887f8702f9eSDmitry Osipenko regulator_lock_dependent(rdev, &ww_ctx); 2888da07ecd9SMark Brown 2889c9ccaa0cSTirupathi Reddy /* 2890c9ccaa0cSTirupathi Reddy * Workqueue functions queue the new work instance while the previous 2891c9ccaa0cSTirupathi Reddy * work instance is being processed. Cancel the queued work instance 2892c9ccaa0cSTirupathi Reddy * as the work instance under processing does the job of the queued 2893c9ccaa0cSTirupathi Reddy * work instance. 2894c9ccaa0cSTirupathi Reddy */ 2895c9ccaa0cSTirupathi Reddy cancel_delayed_work(&rdev->disable_work); 2896c9ccaa0cSTirupathi Reddy 28975451781dSDouglas Anderson list_for_each_entry(regulator, &rdev->consumer_list, list) { 28985451781dSDouglas Anderson count = regulator->deferred_disables; 28995451781dSDouglas Anderson 29005451781dSDouglas Anderson if (!count) 29015451781dSDouglas Anderson continue; 29025451781dSDouglas Anderson 29035451781dSDouglas Anderson total_count += count; 29045451781dSDouglas Anderson regulator->deferred_disables = 0; 29055451781dSDouglas Anderson 2906da07ecd9SMark Brown for (i = 0; i < count; i++) { 29075451781dSDouglas Anderson ret = _regulator_disable(regulator); 2908da07ecd9SMark Brown if (ret != 0) 290961aab5adSMichał Mirosław rdev_err(rdev, "Deferred disable failed: %pe\n", 291061aab5adSMichał Mirosław ERR_PTR(ret)); 2911da07ecd9SMark Brown } 29125451781dSDouglas Anderson } 29135451781dSDouglas Anderson WARN_ON(!total_count); 2914da07ecd9SMark Brown 2915f8702f9eSDmitry Osipenko if (rdev->coupling_desc.n_coupled > 1) 2916f8702f9eSDmitry Osipenko regulator_balance_voltage(rdev, PM_SUSPEND_ON); 2917f8702f9eSDmitry Osipenko 2918f8702f9eSDmitry Osipenko regulator_unlock_dependent(rdev, &ww_ctx); 2919da07ecd9SMark Brown } 2920da07ecd9SMark Brown 2921da07ecd9SMark Brown /** 2922da07ecd9SMark Brown * regulator_disable_deferred - disable regulator output with delay 2923da07ecd9SMark Brown * @regulator: regulator source 292448f1b4efSKrzysztof Kozlowski * @ms: milliseconds until the regulator is disabled 2925da07ecd9SMark Brown * 2926da07ecd9SMark Brown * Execute regulator_disable() on the regulator after a delay. This 2927da07ecd9SMark Brown * is intended for use with devices that require some time to quiesce. 2928da07ecd9SMark Brown * 2929da07ecd9SMark Brown * NOTE: this will only disable the regulator output if no other consumer 2930da07ecd9SMark Brown * devices have it enabled, the regulator device supports disabling and 2931da07ecd9SMark Brown * machine constraints permit this operation. 2932da07ecd9SMark Brown */ 2933da07ecd9SMark Brown int regulator_disable_deferred(struct regulator *regulator, int ms) 2934da07ecd9SMark Brown { 2935da07ecd9SMark Brown struct regulator_dev *rdev = regulator->rdev; 2936da07ecd9SMark Brown 29372b5a24a0SMark Brown if (!ms) 29382b5a24a0SMark Brown return regulator_disable(regulator); 29392b5a24a0SMark Brown 294066cf9a7eSMaciej Purski regulator_lock(rdev); 29415451781dSDouglas Anderson regulator->deferred_disables++; 2942c9ccaa0cSTirupathi Reddy mod_delayed_work(system_power_efficient_wq, &rdev->disable_work, 2943c9ccaa0cSTirupathi Reddy msecs_to_jiffies(ms)); 294466cf9a7eSMaciej Purski regulator_unlock(rdev); 2945da07ecd9SMark Brown 2946aa59802dSMark Brown return 0; 2947da07ecd9SMark Brown } 2948da07ecd9SMark Brown EXPORT_SYMBOL_GPL(regulator_disable_deferred); 2949da07ecd9SMark Brown 2950414c70cbSLiam Girdwood static int _regulator_is_enabled(struct regulator_dev *rdev) 2951414c70cbSLiam Girdwood { 295265f73508SMark Brown /* A GPIO control always takes precedence */ 29537b74d149SKim, Milo if (rdev->ena_pin) 295465f73508SMark Brown return rdev->ena_gpio_state; 295565f73508SMark Brown 29569a7f6a4cSMark Brown /* If we don't know then assume that the regulator is always on */ 29579332546fSMark Brown if (!rdev->desc->ops->is_enabled) 29589a7f6a4cSMark Brown return 1; 2959414c70cbSLiam Girdwood 29609332546fSMark Brown return rdev->desc->ops->is_enabled(rdev); 2961414c70cbSLiam Girdwood } 2962414c70cbSLiam Girdwood 29633d67fe95SMaciej Purski static int _regulator_list_voltage(struct regulator_dev *rdev, 29643a40cfc3SSascha Hauer unsigned selector, int lock) 29653a40cfc3SSascha Hauer { 29663a40cfc3SSascha Hauer const struct regulator_ops *ops = rdev->desc->ops; 29673a40cfc3SSascha Hauer int ret; 29683a40cfc3SSascha Hauer 29693a40cfc3SSascha Hauer if (rdev->desc->fixed_uV && rdev->desc->n_voltages == 1 && !selector) 29703a40cfc3SSascha Hauer return rdev->desc->fixed_uV; 29713a40cfc3SSascha Hauer 29723a40cfc3SSascha Hauer if (ops->list_voltage) { 29733a40cfc3SSascha Hauer if (selector >= rdev->desc->n_voltages) 29743a40cfc3SSascha Hauer return -EINVAL; 297555cca739SClaudiu Beznea if (selector < rdev->desc->linear_min_sel) 297655cca739SClaudiu Beznea return 0; 29773a40cfc3SSascha Hauer if (lock) 297866cf9a7eSMaciej Purski regulator_lock(rdev); 29793a40cfc3SSascha Hauer ret = ops->list_voltage(rdev, selector); 29803a40cfc3SSascha Hauer if (lock) 298166cf9a7eSMaciej Purski regulator_unlock(rdev); 2982fd086045SMatthias Kaehlcke } else if (rdev->is_switch && rdev->supply) { 29833d67fe95SMaciej Purski ret = _regulator_list_voltage(rdev->supply->rdev, 29843d67fe95SMaciej Purski selector, lock); 29853a40cfc3SSascha Hauer } else { 29863a40cfc3SSascha Hauer return -EINVAL; 29873a40cfc3SSascha Hauer } 29883a40cfc3SSascha Hauer 29893a40cfc3SSascha Hauer if (ret > 0) { 29903a40cfc3SSascha Hauer if (ret < rdev->constraints->min_uV) 29913a40cfc3SSascha Hauer ret = 0; 29923a40cfc3SSascha Hauer else if (ret > rdev->constraints->max_uV) 29933a40cfc3SSascha Hauer ret = 0; 29943a40cfc3SSascha Hauer } 29953a40cfc3SSascha Hauer 29963a40cfc3SSascha Hauer return ret; 29973a40cfc3SSascha Hauer } 29983a40cfc3SSascha Hauer 2999414c70cbSLiam Girdwood /** 3000414c70cbSLiam Girdwood * regulator_is_enabled - is the regulator output enabled 3001414c70cbSLiam Girdwood * @regulator: regulator source 3002414c70cbSLiam Girdwood * 3003412aec61SDavid Brownell * Returns positive if the regulator driver backing the source/client 3004412aec61SDavid Brownell * has requested that the device be enabled, zero if it hasn't, else a 3005412aec61SDavid Brownell * negative errno code. 3006412aec61SDavid Brownell * 3007412aec61SDavid Brownell * Note that the device backing this regulator handle can have multiple 3008412aec61SDavid Brownell * users, so it might be enabled even if regulator_enable() was never 3009412aec61SDavid Brownell * called for this particular source. 3010414c70cbSLiam Girdwood */ 3011414c70cbSLiam Girdwood int regulator_is_enabled(struct regulator *regulator) 3012414c70cbSLiam Girdwood { 30139332546fSMark Brown int ret; 30149332546fSMark Brown 30156492bc1bSMark Brown if (regulator->always_on) 30166492bc1bSMark Brown return 1; 30176492bc1bSMark Brown 3018f8702f9eSDmitry Osipenko regulator_lock(regulator->rdev); 30199332546fSMark Brown ret = _regulator_is_enabled(regulator->rdev); 3020f8702f9eSDmitry Osipenko regulator_unlock(regulator->rdev); 30219332546fSMark Brown 30229332546fSMark Brown return ret; 3023414c70cbSLiam Girdwood } 3024414c70cbSLiam Girdwood EXPORT_SYMBOL_GPL(regulator_is_enabled); 3025414c70cbSLiam Girdwood 3026414c70cbSLiam Girdwood /** 30274367cfdcSDavid Brownell * regulator_count_voltages - count regulator_list_voltage() selectors 30284367cfdcSDavid Brownell * @regulator: regulator source 30294367cfdcSDavid Brownell * 30304367cfdcSDavid Brownell * Returns number of selectors, or negative errno. Selectors are 30314367cfdcSDavid Brownell * numbered starting at zero, and typically correspond to bitfields 30324367cfdcSDavid Brownell * in hardware registers. 30334367cfdcSDavid Brownell */ 30344367cfdcSDavid Brownell int regulator_count_voltages(struct regulator *regulator) 30354367cfdcSDavid Brownell { 30364367cfdcSDavid Brownell struct regulator_dev *rdev = regulator->rdev; 30374367cfdcSDavid Brownell 303826988efeSJavier Martinez Canillas if (rdev->desc->n_voltages) 303926988efeSJavier Martinez Canillas return rdev->desc->n_voltages; 304026988efeSJavier Martinez Canillas 3041fd086045SMatthias Kaehlcke if (!rdev->is_switch || !rdev->supply) 304226988efeSJavier Martinez Canillas return -EINVAL; 304326988efeSJavier Martinez Canillas 304426988efeSJavier Martinez Canillas return regulator_count_voltages(rdev->supply); 30454367cfdcSDavid Brownell } 30464367cfdcSDavid Brownell EXPORT_SYMBOL_GPL(regulator_count_voltages); 30474367cfdcSDavid Brownell 30484367cfdcSDavid Brownell /** 30494367cfdcSDavid Brownell * regulator_list_voltage - enumerate supported voltages 30504367cfdcSDavid Brownell * @regulator: regulator source 30514367cfdcSDavid Brownell * @selector: identify voltage to list 30524367cfdcSDavid Brownell * Context: can sleep 30534367cfdcSDavid Brownell * 30544367cfdcSDavid Brownell * Returns a voltage that can be passed to @regulator_set_voltage(), 305588393161SThomas Weber * zero if this selector code can't be used on this system, or a 30564367cfdcSDavid Brownell * negative errno. 30574367cfdcSDavid Brownell */ 30584367cfdcSDavid Brownell int regulator_list_voltage(struct regulator *regulator, unsigned selector) 30594367cfdcSDavid Brownell { 30603d67fe95SMaciej Purski return _regulator_list_voltage(regulator->rdev, selector, 1); 30614367cfdcSDavid Brownell } 30624367cfdcSDavid Brownell EXPORT_SYMBOL_GPL(regulator_list_voltage); 30634367cfdcSDavid Brownell 30644367cfdcSDavid Brownell /** 306504eca28cSTuomas Tynkkynen * regulator_get_regmap - get the regulator's register map 306604eca28cSTuomas Tynkkynen * @regulator: regulator source 306704eca28cSTuomas Tynkkynen * 306804eca28cSTuomas Tynkkynen * Returns the register map for the given regulator, or an ERR_PTR value 306904eca28cSTuomas Tynkkynen * if the regulator doesn't use regmap. 307004eca28cSTuomas Tynkkynen */ 307104eca28cSTuomas Tynkkynen struct regmap *regulator_get_regmap(struct regulator *regulator) 307204eca28cSTuomas Tynkkynen { 307304eca28cSTuomas Tynkkynen struct regmap *map = regulator->rdev->regmap; 307404eca28cSTuomas Tynkkynen 307504eca28cSTuomas Tynkkynen return map ? map : ERR_PTR(-EOPNOTSUPP); 307604eca28cSTuomas Tynkkynen } 307704eca28cSTuomas Tynkkynen 307804eca28cSTuomas Tynkkynen /** 307904eca28cSTuomas Tynkkynen * regulator_get_hardware_vsel_register - get the HW voltage selector register 308004eca28cSTuomas Tynkkynen * @regulator: regulator source 308104eca28cSTuomas Tynkkynen * @vsel_reg: voltage selector register, output parameter 308204eca28cSTuomas Tynkkynen * @vsel_mask: mask for voltage selector bitfield, output parameter 308304eca28cSTuomas Tynkkynen * 308404eca28cSTuomas Tynkkynen * Returns the hardware register offset and bitmask used for setting the 308504eca28cSTuomas Tynkkynen * regulator voltage. This might be useful when configuring voltage-scaling 308604eca28cSTuomas Tynkkynen * hardware or firmware that can make I2C requests behind the kernel's back, 308704eca28cSTuomas Tynkkynen * for example. 308804eca28cSTuomas Tynkkynen * 308904eca28cSTuomas Tynkkynen * On success, the output parameters @vsel_reg and @vsel_mask are filled in 309004eca28cSTuomas Tynkkynen * and 0 is returned, otherwise a negative errno is returned. 309104eca28cSTuomas Tynkkynen */ 309204eca28cSTuomas Tynkkynen int regulator_get_hardware_vsel_register(struct regulator *regulator, 309304eca28cSTuomas Tynkkynen unsigned *vsel_reg, 309404eca28cSTuomas Tynkkynen unsigned *vsel_mask) 309504eca28cSTuomas Tynkkynen { 309604eca28cSTuomas Tynkkynen struct regulator_dev *rdev = regulator->rdev; 309739f5460dSGuodong Xu const struct regulator_ops *ops = rdev->desc->ops; 309804eca28cSTuomas Tynkkynen 309904eca28cSTuomas Tynkkynen if (ops->set_voltage_sel != regulator_set_voltage_sel_regmap) 310004eca28cSTuomas Tynkkynen return -EOPNOTSUPP; 310104eca28cSTuomas Tynkkynen 310204eca28cSTuomas Tynkkynen *vsel_reg = rdev->desc->vsel_reg; 310304eca28cSTuomas Tynkkynen *vsel_mask = rdev->desc->vsel_mask; 310404eca28cSTuomas Tynkkynen 310504eca28cSTuomas Tynkkynen return 0; 310604eca28cSTuomas Tynkkynen } 310704eca28cSTuomas Tynkkynen EXPORT_SYMBOL_GPL(regulator_get_hardware_vsel_register); 310804eca28cSTuomas Tynkkynen 310904eca28cSTuomas Tynkkynen /** 311004eca28cSTuomas Tynkkynen * regulator_list_hardware_vsel - get the HW-specific register value for a selector 311104eca28cSTuomas Tynkkynen * @regulator: regulator source 311204eca28cSTuomas Tynkkynen * @selector: identify voltage to list 311304eca28cSTuomas Tynkkynen * 311404eca28cSTuomas Tynkkynen * Converts the selector to a hardware-specific voltage selector that can be 311504eca28cSTuomas Tynkkynen * directly written to the regulator registers. The address of the voltage 311604eca28cSTuomas Tynkkynen * register can be determined by calling @regulator_get_hardware_vsel_register. 311704eca28cSTuomas Tynkkynen * 311804eca28cSTuomas Tynkkynen * On error a negative errno is returned. 311904eca28cSTuomas Tynkkynen */ 312004eca28cSTuomas Tynkkynen int regulator_list_hardware_vsel(struct regulator *regulator, 312104eca28cSTuomas Tynkkynen unsigned selector) 312204eca28cSTuomas Tynkkynen { 312304eca28cSTuomas Tynkkynen struct regulator_dev *rdev = regulator->rdev; 312439f5460dSGuodong Xu const struct regulator_ops *ops = rdev->desc->ops; 312504eca28cSTuomas Tynkkynen 312604eca28cSTuomas Tynkkynen if (selector >= rdev->desc->n_voltages) 312704eca28cSTuomas Tynkkynen return -EINVAL; 312855cca739SClaudiu Beznea if (selector < rdev->desc->linear_min_sel) 312955cca739SClaudiu Beznea return 0; 313004eca28cSTuomas Tynkkynen if (ops->set_voltage_sel != regulator_set_voltage_sel_regmap) 313104eca28cSTuomas Tynkkynen return -EOPNOTSUPP; 313204eca28cSTuomas Tynkkynen 313304eca28cSTuomas Tynkkynen return selector; 313404eca28cSTuomas Tynkkynen } 313504eca28cSTuomas Tynkkynen EXPORT_SYMBOL_GPL(regulator_list_hardware_vsel); 313604eca28cSTuomas Tynkkynen 313704eca28cSTuomas Tynkkynen /** 31382a668a8bSPaul Walmsley * regulator_get_linear_step - return the voltage step size between VSEL values 31392a668a8bSPaul Walmsley * @regulator: regulator source 31402a668a8bSPaul Walmsley * 31412a668a8bSPaul Walmsley * Returns the voltage step size between VSEL values for linear 31422a668a8bSPaul Walmsley * regulators, or return 0 if the regulator isn't a linear regulator. 31432a668a8bSPaul Walmsley */ 31442a668a8bSPaul Walmsley unsigned int regulator_get_linear_step(struct regulator *regulator) 31452a668a8bSPaul Walmsley { 31462a668a8bSPaul Walmsley struct regulator_dev *rdev = regulator->rdev; 31472a668a8bSPaul Walmsley 31482a668a8bSPaul Walmsley return rdev->desc->uV_step; 31492a668a8bSPaul Walmsley } 31502a668a8bSPaul Walmsley EXPORT_SYMBOL_GPL(regulator_get_linear_step); 31512a668a8bSPaul Walmsley 31522a668a8bSPaul Walmsley /** 3153a7a1ad90SMark Brown * regulator_is_supported_voltage - check if a voltage range can be supported 3154a7a1ad90SMark Brown * 3155a7a1ad90SMark Brown * @regulator: Regulator to check. 3156a7a1ad90SMark Brown * @min_uV: Minimum required voltage in uV. 3157a7a1ad90SMark Brown * @max_uV: Maximum required voltage in uV. 3158a7a1ad90SMark Brown * 315949820944SJorge Ramirez-Ortiz * Returns a boolean. 3160a7a1ad90SMark Brown */ 3161a7a1ad90SMark Brown int regulator_is_supported_voltage(struct regulator *regulator, 3162a7a1ad90SMark Brown int min_uV, int max_uV) 3163a7a1ad90SMark Brown { 3164c5f3939bSMark Brown struct regulator_dev *rdev = regulator->rdev; 3165a7a1ad90SMark Brown int i, voltages, ret; 3166a7a1ad90SMark Brown 3167c5f3939bSMark Brown /* If we can't change voltage check the current voltage */ 31688a34e979SWEN Pingbo if (!regulator_ops_is_valid(rdev, REGULATOR_CHANGE_VOLTAGE)) { 3169c5f3939bSMark Brown ret = regulator_get_voltage(regulator); 3170c5f3939bSMark Brown if (ret >= 0) 31710d25d09dSJingoo Han return min_uV <= ret && ret <= max_uV; 3172c5f3939bSMark Brown else 3173c5f3939bSMark Brown return ret; 3174c5f3939bSMark Brown } 3175c5f3939bSMark Brown 3176bd7a2b60SPawel Moll /* Any voltage within constrains range is fine? */ 3177bd7a2b60SPawel Moll if (rdev->desc->continuous_voltage_range) 3178bd7a2b60SPawel Moll return min_uV >= rdev->constraints->min_uV && 3179bd7a2b60SPawel Moll max_uV <= rdev->constraints->max_uV; 3180bd7a2b60SPawel Moll 3181a7a1ad90SMark Brown ret = regulator_count_voltages(regulator); 3182a7a1ad90SMark Brown if (ret < 0) 318349820944SJorge Ramirez-Ortiz return 0; 3184a7a1ad90SMark Brown voltages = ret; 3185a7a1ad90SMark Brown 3186a7a1ad90SMark Brown for (i = 0; i < voltages; i++) { 3187a7a1ad90SMark Brown ret = regulator_list_voltage(regulator, i); 3188a7a1ad90SMark Brown 3189a7a1ad90SMark Brown if (ret >= min_uV && ret <= max_uV) 3190a7a1ad90SMark Brown return 1; 3191a7a1ad90SMark Brown } 3192a7a1ad90SMark Brown 3193a7a1ad90SMark Brown return 0; 3194a7a1ad90SMark Brown } 3195a398eaa2SMark Brown EXPORT_SYMBOL_GPL(regulator_is_supported_voltage); 3196a7a1ad90SMark Brown 3197a204f41eSSascha Hauer static int regulator_map_voltage(struct regulator_dev *rdev, int min_uV, 3198a204f41eSSascha Hauer int max_uV) 3199a204f41eSSascha Hauer { 3200a204f41eSSascha Hauer const struct regulator_desc *desc = rdev->desc; 3201a204f41eSSascha Hauer 3202a204f41eSSascha Hauer if (desc->ops->map_voltage) 3203a204f41eSSascha Hauer return desc->ops->map_voltage(rdev, min_uV, max_uV); 3204a204f41eSSascha Hauer 3205a204f41eSSascha Hauer if (desc->ops->list_voltage == regulator_list_voltage_linear) 3206a204f41eSSascha Hauer return regulator_map_voltage_linear(rdev, min_uV, max_uV); 3207a204f41eSSascha Hauer 3208a204f41eSSascha Hauer if (desc->ops->list_voltage == regulator_list_voltage_linear_range) 3209a204f41eSSascha Hauer return regulator_map_voltage_linear_range(rdev, min_uV, max_uV); 3210a204f41eSSascha Hauer 321118e4b55fSMatti Vaittinen if (desc->ops->list_voltage == 321218e4b55fSMatti Vaittinen regulator_list_voltage_pickable_linear_range) 321318e4b55fSMatti Vaittinen return regulator_map_voltage_pickable_linear_range(rdev, 321418e4b55fSMatti Vaittinen min_uV, max_uV); 321518e4b55fSMatti Vaittinen 3216a204f41eSSascha Hauer return regulator_map_voltage_iterate(rdev, min_uV, max_uV); 3217a204f41eSSascha Hauer } 3218a204f41eSSascha Hauer 32197179569aSHeiko Stübner static int _regulator_call_set_voltage(struct regulator_dev *rdev, 32207179569aSHeiko Stübner int min_uV, int max_uV, 32217179569aSHeiko Stübner unsigned *selector) 32227179569aSHeiko Stübner { 32237179569aSHeiko Stübner struct pre_voltage_change_data data; 32247179569aSHeiko Stübner int ret; 32257179569aSHeiko Stübner 3226d22b85a1SDmitry Osipenko data.old_uV = regulator_get_voltage_rdev(rdev); 32277179569aSHeiko Stübner data.min_uV = min_uV; 32287179569aSHeiko Stübner data.max_uV = max_uV; 32297179569aSHeiko Stübner ret = _notifier_call_chain(rdev, REGULATOR_EVENT_PRE_VOLTAGE_CHANGE, 32307179569aSHeiko Stübner &data); 32317179569aSHeiko Stübner if (ret & NOTIFY_STOP_MASK) 32327179569aSHeiko Stübner return -EINVAL; 32337179569aSHeiko Stübner 32347179569aSHeiko Stübner ret = rdev->desc->ops->set_voltage(rdev, min_uV, max_uV, selector); 32357179569aSHeiko Stübner if (ret >= 0) 32367179569aSHeiko Stübner return ret; 32377179569aSHeiko Stübner 32387179569aSHeiko Stübner _notifier_call_chain(rdev, REGULATOR_EVENT_ABORT_VOLTAGE_CHANGE, 32397179569aSHeiko Stübner (void *)data.old_uV); 32407179569aSHeiko Stübner 32417179569aSHeiko Stübner return ret; 32427179569aSHeiko Stübner } 32437179569aSHeiko Stübner 32447179569aSHeiko Stübner static int _regulator_call_set_voltage_sel(struct regulator_dev *rdev, 32457179569aSHeiko Stübner int uV, unsigned selector) 32467179569aSHeiko Stübner { 32477179569aSHeiko Stübner struct pre_voltage_change_data data; 32487179569aSHeiko Stübner int ret; 32497179569aSHeiko Stübner 3250d22b85a1SDmitry Osipenko data.old_uV = regulator_get_voltage_rdev(rdev); 32517179569aSHeiko Stübner data.min_uV = uV; 32527179569aSHeiko Stübner data.max_uV = uV; 32537179569aSHeiko Stübner ret = _notifier_call_chain(rdev, REGULATOR_EVENT_PRE_VOLTAGE_CHANGE, 32547179569aSHeiko Stübner &data); 32557179569aSHeiko Stübner if (ret & NOTIFY_STOP_MASK) 32567179569aSHeiko Stübner return -EINVAL; 32577179569aSHeiko Stübner 32587179569aSHeiko Stübner ret = rdev->desc->ops->set_voltage_sel(rdev, selector); 32597179569aSHeiko Stübner if (ret >= 0) 32607179569aSHeiko Stübner return ret; 32617179569aSHeiko Stübner 32627179569aSHeiko Stübner _notifier_call_chain(rdev, REGULATOR_EVENT_ABORT_VOLTAGE_CHANGE, 32637179569aSHeiko Stübner (void *)data.old_uV); 32647179569aSHeiko Stübner 32657179569aSHeiko Stübner return ret; 32667179569aSHeiko Stübner } 32677179569aSHeiko Stübner 32682da8d947SBartosz Golaszewski static int _regulator_set_voltage_sel_step(struct regulator_dev *rdev, 32692da8d947SBartosz Golaszewski int uV, int new_selector) 32702da8d947SBartosz Golaszewski { 32712da8d947SBartosz Golaszewski const struct regulator_ops *ops = rdev->desc->ops; 32722da8d947SBartosz Golaszewski int diff, old_sel, curr_sel, ret; 32732da8d947SBartosz Golaszewski 32742da8d947SBartosz Golaszewski /* Stepping is only needed if the regulator is enabled. */ 32752da8d947SBartosz Golaszewski if (!_regulator_is_enabled(rdev)) 32762da8d947SBartosz Golaszewski goto final_set; 32772da8d947SBartosz Golaszewski 32782da8d947SBartosz Golaszewski if (!ops->get_voltage_sel) 32792da8d947SBartosz Golaszewski return -EINVAL; 32802da8d947SBartosz Golaszewski 32812da8d947SBartosz Golaszewski old_sel = ops->get_voltage_sel(rdev); 32822da8d947SBartosz Golaszewski if (old_sel < 0) 32832da8d947SBartosz Golaszewski return old_sel; 32842da8d947SBartosz Golaszewski 32852da8d947SBartosz Golaszewski diff = new_selector - old_sel; 32862da8d947SBartosz Golaszewski if (diff == 0) 32872da8d947SBartosz Golaszewski return 0; /* No change needed. */ 32882da8d947SBartosz Golaszewski 32892da8d947SBartosz Golaszewski if (diff > 0) { 32902da8d947SBartosz Golaszewski /* Stepping up. */ 32912da8d947SBartosz Golaszewski for (curr_sel = old_sel + rdev->desc->vsel_step; 32922da8d947SBartosz Golaszewski curr_sel < new_selector; 32932da8d947SBartosz Golaszewski curr_sel += rdev->desc->vsel_step) { 32942da8d947SBartosz Golaszewski /* 32952da8d947SBartosz Golaszewski * Call the callback directly instead of using 32962da8d947SBartosz Golaszewski * _regulator_call_set_voltage_sel() as we don't 32972da8d947SBartosz Golaszewski * want to notify anyone yet. Same in the branch 32982da8d947SBartosz Golaszewski * below. 32992da8d947SBartosz Golaszewski */ 33002da8d947SBartosz Golaszewski ret = ops->set_voltage_sel(rdev, curr_sel); 33012da8d947SBartosz Golaszewski if (ret) 33022da8d947SBartosz Golaszewski goto try_revert; 33032da8d947SBartosz Golaszewski } 33042da8d947SBartosz Golaszewski } else { 33052da8d947SBartosz Golaszewski /* Stepping down. */ 33062da8d947SBartosz Golaszewski for (curr_sel = old_sel - rdev->desc->vsel_step; 33072da8d947SBartosz Golaszewski curr_sel > new_selector; 33082da8d947SBartosz Golaszewski curr_sel -= rdev->desc->vsel_step) { 33092da8d947SBartosz Golaszewski ret = ops->set_voltage_sel(rdev, curr_sel); 33102da8d947SBartosz Golaszewski if (ret) 33112da8d947SBartosz Golaszewski goto try_revert; 33122da8d947SBartosz Golaszewski } 33132da8d947SBartosz Golaszewski } 33142da8d947SBartosz Golaszewski 33152da8d947SBartosz Golaszewski final_set: 33162da8d947SBartosz Golaszewski /* The final selector will trigger the notifiers. */ 33172da8d947SBartosz Golaszewski return _regulator_call_set_voltage_sel(rdev, uV, new_selector); 33182da8d947SBartosz Golaszewski 33192da8d947SBartosz Golaszewski try_revert: 33202da8d947SBartosz Golaszewski /* 33212da8d947SBartosz Golaszewski * At least try to return to the previous voltage if setting a new 33222da8d947SBartosz Golaszewski * one failed. 33232da8d947SBartosz Golaszewski */ 33242da8d947SBartosz Golaszewski (void)ops->set_voltage_sel(rdev, old_sel); 33252da8d947SBartosz Golaszewski return ret; 33262da8d947SBartosz Golaszewski } 33272da8d947SBartosz Golaszewski 332873e705bfSMatthias Kaehlcke static int _regulator_set_voltage_time(struct regulator_dev *rdev, 332973e705bfSMatthias Kaehlcke int old_uV, int new_uV) 333073e705bfSMatthias Kaehlcke { 333173e705bfSMatthias Kaehlcke unsigned int ramp_delay = 0; 333273e705bfSMatthias Kaehlcke 333373e705bfSMatthias Kaehlcke if (rdev->constraints->ramp_delay) 333473e705bfSMatthias Kaehlcke ramp_delay = rdev->constraints->ramp_delay; 333573e705bfSMatthias Kaehlcke else if (rdev->desc->ramp_delay) 333673e705bfSMatthias Kaehlcke ramp_delay = rdev->desc->ramp_delay; 3337d6c1dc3fSLaxman Dewangan else if (rdev->constraints->settling_time) 3338d6c1dc3fSLaxman Dewangan return rdev->constraints->settling_time; 33393ffad468SMatthias Kaehlcke else if (rdev->constraints->settling_time_up && 33403ffad468SMatthias Kaehlcke (new_uV > old_uV)) 33413ffad468SMatthias Kaehlcke return rdev->constraints->settling_time_up; 33423ffad468SMatthias Kaehlcke else if (rdev->constraints->settling_time_down && 33433ffad468SMatthias Kaehlcke (new_uV < old_uV)) 33443ffad468SMatthias Kaehlcke return rdev->constraints->settling_time_down; 334573e705bfSMatthias Kaehlcke 334673e705bfSMatthias Kaehlcke if (ramp_delay == 0) { 3347ba14fa1aSH. Nikolaus Schaller rdev_dbg(rdev, "ramp_delay not set\n"); 334873e705bfSMatthias Kaehlcke return 0; 334973e705bfSMatthias Kaehlcke } 335073e705bfSMatthias Kaehlcke 335173e705bfSMatthias Kaehlcke return DIV_ROUND_UP(abs(new_uV - old_uV), ramp_delay); 335273e705bfSMatthias Kaehlcke } 335373e705bfSMatthias Kaehlcke 335475790251SMark Brown static int _regulator_do_set_voltage(struct regulator_dev *rdev, 335575790251SMark Brown int min_uV, int max_uV) 335675790251SMark Brown { 335775790251SMark Brown int ret; 335877af1b26SLinus Walleij int delay = 0; 3359e113d792SMark Brown int best_val = 0; 336075790251SMark Brown unsigned int selector; 3361eba41a5eSAxel Lin int old_selector = -1; 336257995a48SMatthias Kaehlcke const struct regulator_ops *ops = rdev->desc->ops; 3363d22b85a1SDmitry Osipenko int old_uV = regulator_get_voltage_rdev(rdev); 336475790251SMark Brown 336575790251SMark Brown trace_regulator_set_voltage(rdev_get_name(rdev), min_uV, max_uV); 336675790251SMark Brown 3367bf5892a8SMark Brown min_uV += rdev->constraints->uV_offset; 3368bf5892a8SMark Brown max_uV += rdev->constraints->uV_offset; 3369bf5892a8SMark Brown 337077af1b26SLinus Walleij /* 337177af1b26SLinus Walleij * If we can't obtain the old selector there is not enough 337277af1b26SLinus Walleij * info to call set_voltage_time_sel(). 337377af1b26SLinus Walleij */ 33748b7485efSAxel Lin if (_regulator_is_enabled(rdev) && 337557995a48SMatthias Kaehlcke ops->set_voltage_time_sel && ops->get_voltage_sel) { 337657995a48SMatthias Kaehlcke old_selector = ops->get_voltage_sel(rdev); 3377eba41a5eSAxel Lin if (old_selector < 0) 3378eba41a5eSAxel Lin return old_selector; 3379eba41a5eSAxel Lin } 338077af1b26SLinus Walleij 338157995a48SMatthias Kaehlcke if (ops->set_voltage) { 33827179569aSHeiko Stübner ret = _regulator_call_set_voltage(rdev, min_uV, max_uV, 338375790251SMark Brown &selector); 3384e113d792SMark Brown 3385e113d792SMark Brown if (ret >= 0) { 338657995a48SMatthias Kaehlcke if (ops->list_voltage) 338757995a48SMatthias Kaehlcke best_val = ops->list_voltage(rdev, 3388e113d792SMark Brown selector); 3389e113d792SMark Brown else 3390d22b85a1SDmitry Osipenko best_val = regulator_get_voltage_rdev(rdev); 3391e113d792SMark Brown } 3392e113d792SMark Brown 339357995a48SMatthias Kaehlcke } else if (ops->set_voltage_sel) { 3394a204f41eSSascha Hauer ret = regulator_map_voltage(rdev, min_uV, max_uV); 3395e843fc46SMark Brown if (ret >= 0) { 339657995a48SMatthias Kaehlcke best_val = ops->list_voltage(rdev, ret); 3397e113d792SMark Brown if (min_uV <= best_val && max_uV >= best_val) { 3398e843fc46SMark Brown selector = ret; 3399c66a566aSAxel Lin if (old_selector == selector) 3400c66a566aSAxel Lin ret = 0; 34012da8d947SBartosz Golaszewski else if (rdev->desc->vsel_step) 34022da8d947SBartosz Golaszewski ret = _regulator_set_voltage_sel_step( 34032da8d947SBartosz Golaszewski rdev, best_val, selector); 3404c66a566aSAxel Lin else 34057179569aSHeiko Stübner ret = _regulator_call_set_voltage_sel( 34067179569aSHeiko Stübner rdev, best_val, selector); 3407e113d792SMark Brown } else { 3408e113d792SMark Brown ret = -EINVAL; 3409e113d792SMark Brown } 3410e843fc46SMark Brown } 3411e8eef82bSMark Brown } else { 3412e8eef82bSMark Brown ret = -EINVAL; 3413e8eef82bSMark Brown } 3414e8eef82bSMark Brown 341531dfe686SMatthias Kaehlcke if (ret) 341631dfe686SMatthias Kaehlcke goto out; 3417eba41a5eSAxel Lin 341873e705bfSMatthias Kaehlcke if (ops->set_voltage_time_sel) { 341973e705bfSMatthias Kaehlcke /* 342073e705bfSMatthias Kaehlcke * Call set_voltage_time_sel if successfully obtained 342173e705bfSMatthias Kaehlcke * old_selector 342273e705bfSMatthias Kaehlcke */ 342373e705bfSMatthias Kaehlcke if (old_selector >= 0 && old_selector != selector) 342473e705bfSMatthias Kaehlcke delay = ops->set_voltage_time_sel(rdev, old_selector, 342573e705bfSMatthias Kaehlcke selector); 342673e705bfSMatthias Kaehlcke } else { 342773e705bfSMatthias Kaehlcke if (old_uV != best_val) { 342873e705bfSMatthias Kaehlcke if (ops->set_voltage_time) 342973e705bfSMatthias Kaehlcke delay = ops->set_voltage_time(rdev, old_uV, 343073e705bfSMatthias Kaehlcke best_val); 343173e705bfSMatthias Kaehlcke else 343273e705bfSMatthias Kaehlcke delay = _regulator_set_voltage_time(rdev, 343373e705bfSMatthias Kaehlcke old_uV, 343473e705bfSMatthias Kaehlcke best_val); 343573e705bfSMatthias Kaehlcke } 343673e705bfSMatthias Kaehlcke } 343773e705bfSMatthias Kaehlcke 3438eba41a5eSAxel Lin if (delay < 0) { 343961aab5adSMichał Mirosław rdev_warn(rdev, "failed to get delay: %pe\n", ERR_PTR(delay)); 3440eba41a5eSAxel Lin delay = 0; 3441e8eef82bSMark Brown } 344275790251SMark Brown 344377af1b26SLinus Walleij /* Insert any necessary delays */ 344477af1b26SLinus Walleij if (delay >= 1000) { 344577af1b26SLinus Walleij mdelay(delay / 1000); 344677af1b26SLinus Walleij udelay(delay % 1000); 344777af1b26SLinus Walleij } else if (delay) { 344877af1b26SLinus Walleij udelay(delay); 344977af1b26SLinus Walleij } 345077af1b26SLinus Walleij 345131dfe686SMatthias Kaehlcke if (best_val >= 0) { 34522f6c797fSAxel Lin unsigned long data = best_val; 34532f6c797fSAxel Lin 3454ded06a52SMark Brown _notifier_call_chain(rdev, REGULATOR_EVENT_VOLTAGE_CHANGE, 34552f6c797fSAxel Lin (void *)data); 34562f6c797fSAxel Lin } 3457ded06a52SMark Brown 345831dfe686SMatthias Kaehlcke out: 3459eba41a5eSAxel Lin trace_regulator_set_voltage_complete(rdev_get_name(rdev), best_val); 346075790251SMark Brown 346175790251SMark Brown return ret; 346275790251SMark Brown } 346375790251SMark Brown 3464f7efad10SChunyan Zhang static int _regulator_do_set_suspend_voltage(struct regulator_dev *rdev, 3465f7efad10SChunyan Zhang int min_uV, int max_uV, suspend_state_t state) 3466f7efad10SChunyan Zhang { 3467f7efad10SChunyan Zhang struct regulator_state *rstate; 3468f7efad10SChunyan Zhang int uV, sel; 3469f7efad10SChunyan Zhang 3470f7efad10SChunyan Zhang rstate = regulator_get_suspend_state(rdev, state); 3471f7efad10SChunyan Zhang if (rstate == NULL) 3472f7efad10SChunyan Zhang return -EINVAL; 3473f7efad10SChunyan Zhang 3474f7efad10SChunyan Zhang if (min_uV < rstate->min_uV) 3475f7efad10SChunyan Zhang min_uV = rstate->min_uV; 3476f7efad10SChunyan Zhang if (max_uV > rstate->max_uV) 3477f7efad10SChunyan Zhang max_uV = rstate->max_uV; 3478f7efad10SChunyan Zhang 3479f7efad10SChunyan Zhang sel = regulator_map_voltage(rdev, min_uV, max_uV); 3480f7efad10SChunyan Zhang if (sel < 0) 3481f7efad10SChunyan Zhang return sel; 3482f7efad10SChunyan Zhang 3483f7efad10SChunyan Zhang uV = rdev->desc->ops->list_voltage(rdev, sel); 3484f7efad10SChunyan Zhang if (uV >= min_uV && uV <= max_uV) 3485f7efad10SChunyan Zhang rstate->uV = uV; 3486f7efad10SChunyan Zhang 3487f7efad10SChunyan Zhang return 0; 3488f7efad10SChunyan Zhang } 3489f7efad10SChunyan Zhang 3490a9f226bcSSascha Hauer static int regulator_set_voltage_unlocked(struct regulator *regulator, 3491c360a6dfSChunyan Zhang int min_uV, int max_uV, 3492c360a6dfSChunyan Zhang suspend_state_t state) 3493414c70cbSLiam Girdwood { 3494414c70cbSLiam Girdwood struct regulator_dev *rdev = regulator->rdev; 3495c360a6dfSChunyan Zhang struct regulator_voltage *voltage = ®ulator->voltage[state]; 349695a3c23aSMark Brown int ret = 0; 349792d7a558SPaolo Pisati int old_min_uV, old_max_uV; 3498c00dc359SBjorn Andersson int current_uV; 3499414c70cbSLiam Girdwood 350095a3c23aSMark Brown /* If we're setting the same range as last time the change 350195a3c23aSMark Brown * should be a noop (some cpufreq implementations use the same 350295a3c23aSMark Brown * voltage for multiple frequencies, for example). 350395a3c23aSMark Brown */ 3504c360a6dfSChunyan Zhang if (voltage->min_uV == min_uV && voltage->max_uV == max_uV) 350595a3c23aSMark Brown goto out; 350695a3c23aSMark Brown 3507c00dc359SBjorn Andersson /* If we're trying to set a range that overlaps the current voltage, 3508d3fb9800SViresh Kumar * return successfully even though the regulator does not support 3509c00dc359SBjorn Andersson * changing the voltage. 3510c00dc359SBjorn Andersson */ 35118a34e979SWEN Pingbo if (!regulator_ops_is_valid(rdev, REGULATOR_CHANGE_VOLTAGE)) { 3512d22b85a1SDmitry Osipenko current_uV = regulator_get_voltage_rdev(rdev); 3513c00dc359SBjorn Andersson if (min_uV <= current_uV && current_uV <= max_uV) { 3514c360a6dfSChunyan Zhang voltage->min_uV = min_uV; 3515c360a6dfSChunyan Zhang voltage->max_uV = max_uV; 3516c00dc359SBjorn Andersson goto out; 3517c00dc359SBjorn Andersson } 3518c00dc359SBjorn Andersson } 3519c00dc359SBjorn Andersson 3520414c70cbSLiam Girdwood /* sanity check */ 3521e8eef82bSMark Brown if (!rdev->desc->ops->set_voltage && 3522e8eef82bSMark Brown !rdev->desc->ops->set_voltage_sel) { 3523414c70cbSLiam Girdwood ret = -EINVAL; 3524414c70cbSLiam Girdwood goto out; 3525414c70cbSLiam Girdwood } 3526414c70cbSLiam Girdwood 3527414c70cbSLiam Girdwood /* constraints check */ 3528414c70cbSLiam Girdwood ret = regulator_check_voltage(rdev, &min_uV, &max_uV); 3529414c70cbSLiam Girdwood if (ret < 0) 3530414c70cbSLiam Girdwood goto out; 353192d7a558SPaolo Pisati 353292d7a558SPaolo Pisati /* restore original values in case of error */ 3533c360a6dfSChunyan Zhang old_min_uV = voltage->min_uV; 3534c360a6dfSChunyan Zhang old_max_uV = voltage->max_uV; 3535c360a6dfSChunyan Zhang voltage->min_uV = min_uV; 3536c360a6dfSChunyan Zhang voltage->max_uV = max_uV; 35373a93f2a9SMark Brown 35389243a195SMaciej Purski /* for not coupled regulators this will just set the voltage */ 35399243a195SMaciej Purski ret = regulator_balance_voltage(rdev, state); 354070b46491SSteve Twiss if (ret < 0) { 35419243a195SMaciej Purski voltage->min_uV = old_min_uV; 35429243a195SMaciej Purski voltage->max_uV = old_max_uV; 354370b46491SSteve Twiss } 35449243a195SMaciej Purski 354570b46491SSteve Twiss out: 35469243a195SMaciej Purski return ret; 35479243a195SMaciej Purski } 35489243a195SMaciej Purski 3549d22b85a1SDmitry Osipenko int regulator_set_voltage_rdev(struct regulator_dev *rdev, int min_uV, 35509243a195SMaciej Purski int max_uV, suspend_state_t state) 35519243a195SMaciej Purski { 35529243a195SMaciej Purski int best_supply_uV = 0; 35539243a195SMaciej Purski int supply_change_uV = 0; 35549243a195SMaciej Purski int ret; 35559243a195SMaciej Purski 355643fc99f2SMark Brown if (rdev->supply && 355743fc99f2SMark Brown regulator_ops_is_valid(rdev->supply->rdev, 355843fc99f2SMark Brown REGULATOR_CHANGE_VOLTAGE) && 35592c2874b1STirupathi Reddy (rdev->desc->min_dropout_uV || !(rdev->desc->ops->get_voltage || 35602c2874b1STirupathi Reddy rdev->desc->ops->get_voltage_sel))) { 3561fc42112cSSascha Hauer int current_supply_uV; 3562fc42112cSSascha Hauer int selector; 3563fc42112cSSascha Hauer 3564fc42112cSSascha Hauer selector = regulator_map_voltage(rdev, min_uV, max_uV); 3565fc42112cSSascha Hauer if (selector < 0) { 3566fc42112cSSascha Hauer ret = selector; 35679243a195SMaciej Purski goto out; 3568fc42112cSSascha Hauer } 3569fc42112cSSascha Hauer 357000cb9f4fSMark Brown best_supply_uV = _regulator_list_voltage(rdev, selector, 0); 3571fc42112cSSascha Hauer if (best_supply_uV < 0) { 3572fc42112cSSascha Hauer ret = best_supply_uV; 35739243a195SMaciej Purski goto out; 3574fc42112cSSascha Hauer } 3575fc42112cSSascha Hauer 3576fc42112cSSascha Hauer best_supply_uV += rdev->desc->min_dropout_uV; 3577fc42112cSSascha Hauer 3578d22b85a1SDmitry Osipenko current_supply_uV = regulator_get_voltage_rdev(rdev->supply->rdev); 3579fc42112cSSascha Hauer if (current_supply_uV < 0) { 3580fc42112cSSascha Hauer ret = current_supply_uV; 35819243a195SMaciej Purski goto out; 3582fc42112cSSascha Hauer } 3583fc42112cSSascha Hauer 3584fc42112cSSascha Hauer supply_change_uV = best_supply_uV - current_supply_uV; 3585fc42112cSSascha Hauer } 3586fc42112cSSascha Hauer 3587fc42112cSSascha Hauer if (supply_change_uV > 0) { 3588fc42112cSSascha Hauer ret = regulator_set_voltage_unlocked(rdev->supply, 3589c360a6dfSChunyan Zhang best_supply_uV, INT_MAX, state); 3590fc42112cSSascha Hauer if (ret) { 359161aab5adSMichał Mirosław dev_err(&rdev->dev, "Failed to increase supply voltage: %pe\n", 359261aab5adSMichał Mirosław ERR_PTR(ret)); 35939243a195SMaciej Purski goto out; 3594fc42112cSSascha Hauer } 3595fc42112cSSascha Hauer } 3596fc42112cSSascha Hauer 3597f7efad10SChunyan Zhang if (state == PM_SUSPEND_ON) 359875790251SMark Brown ret = _regulator_do_set_voltage(rdev, min_uV, max_uV); 3599f7efad10SChunyan Zhang else 3600f7efad10SChunyan Zhang ret = _regulator_do_set_suspend_voltage(rdev, min_uV, 3601f7efad10SChunyan Zhang max_uV, state); 360292d7a558SPaolo Pisati if (ret < 0) 36039243a195SMaciej Purski goto out; 360402fa3ec0SMark Brown 3605fc42112cSSascha Hauer if (supply_change_uV < 0) { 3606fc42112cSSascha Hauer ret = regulator_set_voltage_unlocked(rdev->supply, 3607c360a6dfSChunyan Zhang best_supply_uV, INT_MAX, state); 3608fc42112cSSascha Hauer if (ret) 360961aab5adSMichał Mirosław dev_warn(&rdev->dev, "Failed to decrease supply voltage: %pe\n", 361061aab5adSMichał Mirosław ERR_PTR(ret)); 3611fc42112cSSascha Hauer /* No need to fail here */ 3612fc42112cSSascha Hauer ret = 0; 3613fc42112cSSascha Hauer } 3614fc42112cSSascha Hauer 3615414c70cbSLiam Girdwood out: 3616414c70cbSLiam Girdwood return ret; 361769686176SMaciej Purski } 36183d7610e8SEnric Balletbo i Serra EXPORT_SYMBOL_GPL(regulator_set_voltage_rdev); 361969686176SMaciej Purski 362085254bcfSDmitry Osipenko static int regulator_limit_voltage_step(struct regulator_dev *rdev, 362185254bcfSDmitry Osipenko int *current_uV, int *min_uV) 362285254bcfSDmitry Osipenko { 362385254bcfSDmitry Osipenko struct regulation_constraints *constraints = rdev->constraints; 362485254bcfSDmitry Osipenko 362585254bcfSDmitry Osipenko /* Limit voltage change only if necessary */ 362685254bcfSDmitry Osipenko if (!constraints->max_uV_step || !_regulator_is_enabled(rdev)) 362785254bcfSDmitry Osipenko return 1; 362885254bcfSDmitry Osipenko 362985254bcfSDmitry Osipenko if (*current_uV < 0) { 3630d22b85a1SDmitry Osipenko *current_uV = regulator_get_voltage_rdev(rdev); 363185254bcfSDmitry Osipenko 363285254bcfSDmitry Osipenko if (*current_uV < 0) 363385254bcfSDmitry Osipenko return *current_uV; 363485254bcfSDmitry Osipenko } 363585254bcfSDmitry Osipenko 363685254bcfSDmitry Osipenko if (abs(*current_uV - *min_uV) <= constraints->max_uV_step) 363785254bcfSDmitry Osipenko return 1; 363885254bcfSDmitry Osipenko 363985254bcfSDmitry Osipenko /* Clamp target voltage within the given step */ 364085254bcfSDmitry Osipenko if (*current_uV < *min_uV) 364185254bcfSDmitry Osipenko *min_uV = min(*current_uV + constraints->max_uV_step, 364285254bcfSDmitry Osipenko *min_uV); 364385254bcfSDmitry Osipenko else 364485254bcfSDmitry Osipenko *min_uV = max(*current_uV - constraints->max_uV_step, 364585254bcfSDmitry Osipenko *min_uV); 364685254bcfSDmitry Osipenko 364785254bcfSDmitry Osipenko return 0; 364885254bcfSDmitry Osipenko } 364985254bcfSDmitry Osipenko 3650c054c6c7SMaciej Purski static int regulator_get_optimal_voltage(struct regulator_dev *rdev, 3651c054c6c7SMaciej Purski int *current_uV, 3652c054c6c7SMaciej Purski int *min_uV, int *max_uV, 3653c054c6c7SMaciej Purski suspend_state_t state, 3654c054c6c7SMaciej Purski int n_coupled) 3655c054c6c7SMaciej Purski { 3656c054c6c7SMaciej Purski struct coupling_desc *c_desc = &rdev->coupling_desc; 3657c054c6c7SMaciej Purski struct regulator_dev **c_rdevs = c_desc->coupled_rdevs; 3658c054c6c7SMaciej Purski struct regulation_constraints *constraints = rdev->constraints; 3659c054c6c7SMaciej Purski int desired_min_uV = 0, desired_max_uV = INT_MAX; 3660c054c6c7SMaciej Purski int max_current_uV = 0, min_current_uV = INT_MAX; 3661c054c6c7SMaciej Purski int highest_min_uV = 0, target_uV, possible_uV; 3662d8ca7d18SDmitry Osipenko int i, ret, max_spread; 3663c054c6c7SMaciej Purski bool done; 3664c054c6c7SMaciej Purski 3665c054c6c7SMaciej Purski *current_uV = -1; 3666c054c6c7SMaciej Purski 3667c054c6c7SMaciej Purski /* 3668c054c6c7SMaciej Purski * If there are no coupled regulators, simply set the voltage 3669c054c6c7SMaciej Purski * demanded by consumers. 3670c054c6c7SMaciej Purski */ 3671c054c6c7SMaciej Purski if (n_coupled == 1) { 3672c054c6c7SMaciej Purski /* 3673c054c6c7SMaciej Purski * If consumers don't provide any demands, set voltage 3674c054c6c7SMaciej Purski * to min_uV 3675c054c6c7SMaciej Purski */ 3676c054c6c7SMaciej Purski desired_min_uV = constraints->min_uV; 3677c054c6c7SMaciej Purski desired_max_uV = constraints->max_uV; 3678c054c6c7SMaciej Purski 3679c054c6c7SMaciej Purski ret = regulator_check_consumers(rdev, 3680c054c6c7SMaciej Purski &desired_min_uV, 3681c054c6c7SMaciej Purski &desired_max_uV, state); 3682c054c6c7SMaciej Purski if (ret < 0) 3683c054c6c7SMaciej Purski return ret; 3684c054c6c7SMaciej Purski 3685c054c6c7SMaciej Purski possible_uV = desired_min_uV; 3686c054c6c7SMaciej Purski done = true; 3687c054c6c7SMaciej Purski 3688c054c6c7SMaciej Purski goto finish; 3689c054c6c7SMaciej Purski } 3690c054c6c7SMaciej Purski 3691c054c6c7SMaciej Purski /* Find highest min desired voltage */ 3692c054c6c7SMaciej Purski for (i = 0; i < n_coupled; i++) { 3693c054c6c7SMaciej Purski int tmp_min = 0; 3694c054c6c7SMaciej Purski int tmp_max = INT_MAX; 3695c054c6c7SMaciej Purski 3696f8702f9eSDmitry Osipenko lockdep_assert_held_once(&c_rdevs[i]->mutex.base); 3697c054c6c7SMaciej Purski 3698c054c6c7SMaciej Purski ret = regulator_check_consumers(c_rdevs[i], 3699c054c6c7SMaciej Purski &tmp_min, 3700c054c6c7SMaciej Purski &tmp_max, state); 3701c054c6c7SMaciej Purski if (ret < 0) 3702c054c6c7SMaciej Purski return ret; 3703c054c6c7SMaciej Purski 3704c054c6c7SMaciej Purski ret = regulator_check_voltage(c_rdevs[i], &tmp_min, &tmp_max); 3705c054c6c7SMaciej Purski if (ret < 0) 3706c054c6c7SMaciej Purski return ret; 3707c054c6c7SMaciej Purski 3708c054c6c7SMaciej Purski highest_min_uV = max(highest_min_uV, tmp_min); 3709c054c6c7SMaciej Purski 3710c054c6c7SMaciej Purski if (i == 0) { 3711c054c6c7SMaciej Purski desired_min_uV = tmp_min; 3712c054c6c7SMaciej Purski desired_max_uV = tmp_max; 3713c054c6c7SMaciej Purski } 3714c054c6c7SMaciej Purski } 3715c054c6c7SMaciej Purski 3716d8ca7d18SDmitry Osipenko max_spread = constraints->max_spread[0]; 3717d8ca7d18SDmitry Osipenko 3718c054c6c7SMaciej Purski /* 3719c054c6c7SMaciej Purski * Let target_uV be equal to the desired one if possible. 3720c054c6c7SMaciej Purski * If not, set it to minimum voltage, allowed by other coupled 3721c054c6c7SMaciej Purski * regulators. 3722c054c6c7SMaciej Purski */ 3723c054c6c7SMaciej Purski target_uV = max(desired_min_uV, highest_min_uV - max_spread); 3724c054c6c7SMaciej Purski 3725c054c6c7SMaciej Purski /* 3726c054c6c7SMaciej Purski * Find min and max voltages, which currently aren't violating 3727c054c6c7SMaciej Purski * max_spread. 3728c054c6c7SMaciej Purski */ 3729c054c6c7SMaciej Purski for (i = 1; i < n_coupled; i++) { 3730c054c6c7SMaciej Purski int tmp_act; 3731c054c6c7SMaciej Purski 3732c054c6c7SMaciej Purski if (!_regulator_is_enabled(c_rdevs[i])) 3733c054c6c7SMaciej Purski continue; 3734c054c6c7SMaciej Purski 3735d22b85a1SDmitry Osipenko tmp_act = regulator_get_voltage_rdev(c_rdevs[i]); 3736c054c6c7SMaciej Purski if (tmp_act < 0) 3737c054c6c7SMaciej Purski return tmp_act; 3738c054c6c7SMaciej Purski 3739c054c6c7SMaciej Purski min_current_uV = min(tmp_act, min_current_uV); 3740c054c6c7SMaciej Purski max_current_uV = max(tmp_act, max_current_uV); 3741c054c6c7SMaciej Purski } 3742c054c6c7SMaciej Purski 3743c054c6c7SMaciej Purski /* There aren't any other regulators enabled */ 3744c054c6c7SMaciej Purski if (max_current_uV == 0) { 3745c054c6c7SMaciej Purski possible_uV = target_uV; 3746c054c6c7SMaciej Purski } else { 3747c054c6c7SMaciej Purski /* 3748c054c6c7SMaciej Purski * Correct target voltage, so as it currently isn't 3749c054c6c7SMaciej Purski * violating max_spread 3750c054c6c7SMaciej Purski */ 3751c054c6c7SMaciej Purski possible_uV = max(target_uV, max_current_uV - max_spread); 3752c054c6c7SMaciej Purski possible_uV = min(possible_uV, min_current_uV + max_spread); 3753c054c6c7SMaciej Purski } 3754c054c6c7SMaciej Purski 3755c054c6c7SMaciej Purski if (possible_uV > desired_max_uV) 3756c054c6c7SMaciej Purski return -EINVAL; 3757c054c6c7SMaciej Purski 3758c054c6c7SMaciej Purski done = (possible_uV == target_uV); 3759c054c6c7SMaciej Purski desired_min_uV = possible_uV; 3760c054c6c7SMaciej Purski 3761c054c6c7SMaciej Purski finish: 376285254bcfSDmitry Osipenko /* Apply max_uV_step constraint if necessary */ 376385254bcfSDmitry Osipenko if (state == PM_SUSPEND_ON) { 376485254bcfSDmitry Osipenko ret = regulator_limit_voltage_step(rdev, current_uV, 376585254bcfSDmitry Osipenko &desired_min_uV); 376685254bcfSDmitry Osipenko if (ret < 0) 376785254bcfSDmitry Osipenko return ret; 376885254bcfSDmitry Osipenko 376985254bcfSDmitry Osipenko if (ret == 0) 377085254bcfSDmitry Osipenko done = false; 377185254bcfSDmitry Osipenko } 377285254bcfSDmitry Osipenko 3773c054c6c7SMaciej Purski /* Set current_uV if wasn't done earlier in the code and if necessary */ 3774c054c6c7SMaciej Purski if (n_coupled > 1 && *current_uV == -1) { 3775c054c6c7SMaciej Purski 3776c054c6c7SMaciej Purski if (_regulator_is_enabled(rdev)) { 3777d22b85a1SDmitry Osipenko ret = regulator_get_voltage_rdev(rdev); 3778c054c6c7SMaciej Purski if (ret < 0) 3779c054c6c7SMaciej Purski return ret; 3780c054c6c7SMaciej Purski 3781c054c6c7SMaciej Purski *current_uV = ret; 3782c054c6c7SMaciej Purski } else { 3783c054c6c7SMaciej Purski *current_uV = desired_min_uV; 3784c054c6c7SMaciej Purski } 3785c054c6c7SMaciej Purski } 3786c054c6c7SMaciej Purski 3787c054c6c7SMaciej Purski *min_uV = desired_min_uV; 3788c054c6c7SMaciej Purski *max_uV = desired_max_uV; 3789c054c6c7SMaciej Purski 3790c054c6c7SMaciej Purski return done; 3791c054c6c7SMaciej Purski } 3792c054c6c7SMaciej Purski 3793752db83aSMarek Szyprowski int regulator_do_balance_voltage(struct regulator_dev *rdev, 3794752db83aSMarek Szyprowski suspend_state_t state, bool skip_coupled) 3795c054c6c7SMaciej Purski { 3796c054c6c7SMaciej Purski struct regulator_dev **c_rdevs; 3797c054c6c7SMaciej Purski struct regulator_dev *best_rdev; 3798c054c6c7SMaciej Purski struct coupling_desc *c_desc = &rdev->coupling_desc; 3799c054c6c7SMaciej Purski int i, ret, n_coupled, best_min_uV, best_max_uV, best_c_rdev; 3800c054c6c7SMaciej Purski unsigned int delta, best_delta; 3801d8ca7d18SDmitry Osipenko unsigned long c_rdev_done = 0; 3802d8ca7d18SDmitry Osipenko bool best_c_rdev_done; 3803c054c6c7SMaciej Purski 3804c054c6c7SMaciej Purski c_rdevs = c_desc->coupled_rdevs; 3805752db83aSMarek Szyprowski n_coupled = skip_coupled ? 1 : c_desc->n_coupled; 3806c054c6c7SMaciej Purski 3807c054c6c7SMaciej Purski /* 3808c054c6c7SMaciej Purski * Find the best possible voltage change on each loop. Leave the loop 3809c054c6c7SMaciej Purski * if there isn't any possible change. 3810c054c6c7SMaciej Purski */ 3811c054c6c7SMaciej Purski do { 3812c054c6c7SMaciej Purski best_c_rdev_done = false; 3813c054c6c7SMaciej Purski best_delta = 0; 3814c054c6c7SMaciej Purski best_min_uV = 0; 3815c054c6c7SMaciej Purski best_max_uV = 0; 3816c054c6c7SMaciej Purski best_c_rdev = 0; 3817c054c6c7SMaciej Purski best_rdev = NULL; 3818c054c6c7SMaciej Purski 3819c054c6c7SMaciej Purski /* 3820c054c6c7SMaciej Purski * Find highest difference between optimal voltage 3821c054c6c7SMaciej Purski * and current voltage. 3822c054c6c7SMaciej Purski */ 3823c054c6c7SMaciej Purski for (i = 0; i < n_coupled; i++) { 3824c054c6c7SMaciej Purski /* 3825c054c6c7SMaciej Purski * optimal_uV is the best voltage that can be set for 3826c054c6c7SMaciej Purski * i-th regulator at the moment without violating 3827c054c6c7SMaciej Purski * max_spread constraint in order to balance 3828c054c6c7SMaciej Purski * the coupled voltages. 3829c054c6c7SMaciej Purski */ 3830c054c6c7SMaciej Purski int optimal_uV = 0, optimal_max_uV = 0, current_uV = 0; 3831c054c6c7SMaciej Purski 3832d8ca7d18SDmitry Osipenko if (test_bit(i, &c_rdev_done)) 3833c054c6c7SMaciej Purski continue; 3834c054c6c7SMaciej Purski 3835c054c6c7SMaciej Purski ret = regulator_get_optimal_voltage(c_rdevs[i], 3836c054c6c7SMaciej Purski ¤t_uV, 3837c054c6c7SMaciej Purski &optimal_uV, 3838c054c6c7SMaciej Purski &optimal_max_uV, 3839c054c6c7SMaciej Purski state, n_coupled); 3840c054c6c7SMaciej Purski if (ret < 0) 3841c054c6c7SMaciej Purski goto out; 3842c054c6c7SMaciej Purski 3843c054c6c7SMaciej Purski delta = abs(optimal_uV - current_uV); 3844c054c6c7SMaciej Purski 3845c054c6c7SMaciej Purski if (delta && best_delta <= delta) { 3846c054c6c7SMaciej Purski best_c_rdev_done = ret; 3847c054c6c7SMaciej Purski best_delta = delta; 3848c054c6c7SMaciej Purski best_rdev = c_rdevs[i]; 3849c054c6c7SMaciej Purski best_min_uV = optimal_uV; 3850c054c6c7SMaciej Purski best_max_uV = optimal_max_uV; 3851c054c6c7SMaciej Purski best_c_rdev = i; 3852c054c6c7SMaciej Purski } 3853c054c6c7SMaciej Purski } 3854c054c6c7SMaciej Purski 3855c054c6c7SMaciej Purski /* Nothing to change, return successfully */ 3856c054c6c7SMaciej Purski if (!best_rdev) { 3857c054c6c7SMaciej Purski ret = 0; 3858c054c6c7SMaciej Purski goto out; 3859c054c6c7SMaciej Purski } 38609243a195SMaciej Purski 3861c054c6c7SMaciej Purski ret = regulator_set_voltage_rdev(best_rdev, best_min_uV, 3862c054c6c7SMaciej Purski best_max_uV, state); 38639243a195SMaciej Purski 3864c054c6c7SMaciej Purski if (ret < 0) 3865c054c6c7SMaciej Purski goto out; 3866c054c6c7SMaciej Purski 3867d8ca7d18SDmitry Osipenko if (best_c_rdev_done) 3868d8ca7d18SDmitry Osipenko set_bit(best_c_rdev, &c_rdev_done); 3869c054c6c7SMaciej Purski 3870c054c6c7SMaciej Purski } while (n_coupled > 1); 3871c054c6c7SMaciej Purski 3872c054c6c7SMaciej Purski out: 387369686176SMaciej Purski return ret; 387469686176SMaciej Purski } 387569686176SMaciej Purski 3876752db83aSMarek Szyprowski static int regulator_balance_voltage(struct regulator_dev *rdev, 3877752db83aSMarek Szyprowski suspend_state_t state) 3878752db83aSMarek Szyprowski { 3879752db83aSMarek Szyprowski struct coupling_desc *c_desc = &rdev->coupling_desc; 3880752db83aSMarek Szyprowski struct regulator_coupler *coupler = c_desc->coupler; 3881752db83aSMarek Szyprowski bool skip_coupled = false; 3882752db83aSMarek Szyprowski 3883752db83aSMarek Szyprowski /* 3884752db83aSMarek Szyprowski * If system is in a state other than PM_SUSPEND_ON, don't check 3885752db83aSMarek Szyprowski * other coupled regulators. 3886752db83aSMarek Szyprowski */ 3887752db83aSMarek Szyprowski if (state != PM_SUSPEND_ON) 3888752db83aSMarek Szyprowski skip_coupled = true; 3889752db83aSMarek Szyprowski 3890752db83aSMarek Szyprowski if (c_desc->n_resolved < c_desc->n_coupled) { 3891752db83aSMarek Szyprowski rdev_err(rdev, "Not all coupled regulators registered\n"); 3892752db83aSMarek Szyprowski return -EPERM; 3893752db83aSMarek Szyprowski } 3894752db83aSMarek Szyprowski 3895752db83aSMarek Szyprowski /* Invoke custom balancer for customized couplers */ 3896752db83aSMarek Szyprowski if (coupler && coupler->balance_voltage) 3897752db83aSMarek Szyprowski return coupler->balance_voltage(coupler, rdev, state); 3898752db83aSMarek Szyprowski 3899752db83aSMarek Szyprowski return regulator_do_balance_voltage(rdev, state, skip_coupled); 3900752db83aSMarek Szyprowski } 3901752db83aSMarek Szyprowski 3902a9f226bcSSascha Hauer /** 3903a9f226bcSSascha Hauer * regulator_set_voltage - set regulator output voltage 3904a9f226bcSSascha Hauer * @regulator: regulator source 3905a9f226bcSSascha Hauer * @min_uV: Minimum required voltage in uV 3906a9f226bcSSascha Hauer * @max_uV: Maximum acceptable voltage in uV 3907a9f226bcSSascha Hauer * 3908a9f226bcSSascha Hauer * Sets a voltage regulator to the desired output voltage. This can be set 3909a9f226bcSSascha Hauer * during any regulator state. IOW, regulator can be disabled or enabled. 3910a9f226bcSSascha Hauer * 3911a9f226bcSSascha Hauer * If the regulator is enabled then the voltage will change to the new value 3912a9f226bcSSascha Hauer * immediately otherwise if the regulator is disabled the regulator will 3913a9f226bcSSascha Hauer * output at the new voltage when enabled. 3914a9f226bcSSascha Hauer * 3915a9f226bcSSascha Hauer * NOTE: If the regulator is shared between several devices then the lowest 3916a9f226bcSSascha Hauer * request voltage that meets the system constraints will be used. 3917a9f226bcSSascha Hauer * Regulator system constraints must be set for this regulator before 3918a9f226bcSSascha Hauer * calling this function otherwise this call will fail. 3919a9f226bcSSascha Hauer */ 3920a9f226bcSSascha Hauer int regulator_set_voltage(struct regulator *regulator, int min_uV, int max_uV) 3921a9f226bcSSascha Hauer { 3922f8702f9eSDmitry Osipenko struct ww_acquire_ctx ww_ctx; 3923f8702f9eSDmitry Osipenko int ret; 3924a9f226bcSSascha Hauer 3925f8702f9eSDmitry Osipenko regulator_lock_dependent(regulator->rdev, &ww_ctx); 3926a9f226bcSSascha Hauer 3927c360a6dfSChunyan Zhang ret = regulator_set_voltage_unlocked(regulator, min_uV, max_uV, 3928c360a6dfSChunyan Zhang PM_SUSPEND_ON); 3929a9f226bcSSascha Hauer 3930f8702f9eSDmitry Osipenko regulator_unlock_dependent(regulator->rdev, &ww_ctx); 3931a9f226bcSSascha Hauer 393292d7a558SPaolo Pisati return ret; 3933414c70cbSLiam Girdwood } 3934414c70cbSLiam Girdwood EXPORT_SYMBOL_GPL(regulator_set_voltage); 3935414c70cbSLiam Girdwood 3936f7efad10SChunyan Zhang static inline int regulator_suspend_toggle(struct regulator_dev *rdev, 3937f7efad10SChunyan Zhang suspend_state_t state, bool en) 3938f7efad10SChunyan Zhang { 3939f7efad10SChunyan Zhang struct regulator_state *rstate; 3940f7efad10SChunyan Zhang 3941f7efad10SChunyan Zhang rstate = regulator_get_suspend_state(rdev, state); 3942f7efad10SChunyan Zhang if (rstate == NULL) 3943f7efad10SChunyan Zhang return -EINVAL; 3944f7efad10SChunyan Zhang 3945f7efad10SChunyan Zhang if (!rstate->changeable) 3946f7efad10SChunyan Zhang return -EPERM; 3947f7efad10SChunyan Zhang 39483edd79cfSMarek Szyprowski rstate->enabled = (en) ? ENABLE_IN_SUSPEND : DISABLE_IN_SUSPEND; 3949f7efad10SChunyan Zhang 3950f7efad10SChunyan Zhang return 0; 3951f7efad10SChunyan Zhang } 3952f7efad10SChunyan Zhang 3953f7efad10SChunyan Zhang int regulator_suspend_enable(struct regulator_dev *rdev, 3954f7efad10SChunyan Zhang suspend_state_t state) 3955f7efad10SChunyan Zhang { 3956f7efad10SChunyan Zhang return regulator_suspend_toggle(rdev, state, true); 3957f7efad10SChunyan Zhang } 3958f7efad10SChunyan Zhang EXPORT_SYMBOL_GPL(regulator_suspend_enable); 3959f7efad10SChunyan Zhang 3960f7efad10SChunyan Zhang int regulator_suspend_disable(struct regulator_dev *rdev, 3961f7efad10SChunyan Zhang suspend_state_t state) 3962f7efad10SChunyan Zhang { 3963f7efad10SChunyan Zhang struct regulator *regulator; 3964f7efad10SChunyan Zhang struct regulator_voltage *voltage; 3965f7efad10SChunyan Zhang 3966f7efad10SChunyan Zhang /* 3967f7efad10SChunyan Zhang * if any consumer wants this regulator device keeping on in 3968f7efad10SChunyan Zhang * suspend states, don't set it as disabled. 3969f7efad10SChunyan Zhang */ 3970f7efad10SChunyan Zhang list_for_each_entry(regulator, &rdev->consumer_list, list) { 3971f7efad10SChunyan Zhang voltage = ®ulator->voltage[state]; 3972f7efad10SChunyan Zhang if (voltage->min_uV || voltage->max_uV) 3973f7efad10SChunyan Zhang return 0; 3974f7efad10SChunyan Zhang } 3975f7efad10SChunyan Zhang 3976f7efad10SChunyan Zhang return regulator_suspend_toggle(rdev, state, false); 3977f7efad10SChunyan Zhang } 3978f7efad10SChunyan Zhang EXPORT_SYMBOL_GPL(regulator_suspend_disable); 3979f7efad10SChunyan Zhang 3980f7efad10SChunyan Zhang static int _regulator_set_suspend_voltage(struct regulator *regulator, 3981f7efad10SChunyan Zhang int min_uV, int max_uV, 3982f7efad10SChunyan Zhang suspend_state_t state) 3983f7efad10SChunyan Zhang { 3984f7efad10SChunyan Zhang struct regulator_dev *rdev = regulator->rdev; 3985f7efad10SChunyan Zhang struct regulator_state *rstate; 3986f7efad10SChunyan Zhang 3987f7efad10SChunyan Zhang rstate = regulator_get_suspend_state(rdev, state); 3988f7efad10SChunyan Zhang if (rstate == NULL) 3989f7efad10SChunyan Zhang return -EINVAL; 3990f7efad10SChunyan Zhang 3991f7efad10SChunyan Zhang if (rstate->min_uV == rstate->max_uV) { 3992f7efad10SChunyan Zhang rdev_err(rdev, "The suspend voltage can't be changed!\n"); 3993f7efad10SChunyan Zhang return -EPERM; 3994f7efad10SChunyan Zhang } 3995f7efad10SChunyan Zhang 3996f7efad10SChunyan Zhang return regulator_set_voltage_unlocked(regulator, min_uV, max_uV, state); 3997f7efad10SChunyan Zhang } 3998f7efad10SChunyan Zhang 3999f7efad10SChunyan Zhang int regulator_set_suspend_voltage(struct regulator *regulator, int min_uV, 4000f7efad10SChunyan Zhang int max_uV, suspend_state_t state) 4001f7efad10SChunyan Zhang { 4002f8702f9eSDmitry Osipenko struct ww_acquire_ctx ww_ctx; 4003f8702f9eSDmitry Osipenko int ret; 4004f7efad10SChunyan Zhang 4005f7efad10SChunyan Zhang /* PM_SUSPEND_ON is handled by regulator_set_voltage() */ 4006f7efad10SChunyan Zhang if (regulator_check_states(state) || state == PM_SUSPEND_ON) 4007f7efad10SChunyan Zhang return -EINVAL; 4008f7efad10SChunyan Zhang 4009f8702f9eSDmitry Osipenko regulator_lock_dependent(regulator->rdev, &ww_ctx); 4010f7efad10SChunyan Zhang 4011f7efad10SChunyan Zhang ret = _regulator_set_suspend_voltage(regulator, min_uV, 4012f7efad10SChunyan Zhang max_uV, state); 4013f7efad10SChunyan Zhang 4014f8702f9eSDmitry Osipenko regulator_unlock_dependent(regulator->rdev, &ww_ctx); 4015f7efad10SChunyan Zhang 4016f7efad10SChunyan Zhang return ret; 4017f7efad10SChunyan Zhang } 4018f7efad10SChunyan Zhang EXPORT_SYMBOL_GPL(regulator_set_suspend_voltage); 4019f7efad10SChunyan Zhang 4020606a2562SMark Brown /** 402188cd222bSLinus Walleij * regulator_set_voltage_time - get raise/fall time 402288cd222bSLinus Walleij * @regulator: regulator source 402388cd222bSLinus Walleij * @old_uV: starting voltage in microvolts 402488cd222bSLinus Walleij * @new_uV: target voltage in microvolts 402588cd222bSLinus Walleij * 402688cd222bSLinus Walleij * Provided with the starting and ending voltage, this function attempts to 402788cd222bSLinus Walleij * calculate the time in microseconds required to rise or fall to this new 402888cd222bSLinus Walleij * voltage. 402988cd222bSLinus Walleij */ 403088cd222bSLinus Walleij int regulator_set_voltage_time(struct regulator *regulator, 403188cd222bSLinus Walleij int old_uV, int new_uV) 403288cd222bSLinus Walleij { 403388cd222bSLinus Walleij struct regulator_dev *rdev = regulator->rdev; 4034272e2315SGuodong Xu const struct regulator_ops *ops = rdev->desc->ops; 403588cd222bSLinus Walleij int old_sel = -1; 403688cd222bSLinus Walleij int new_sel = -1; 403788cd222bSLinus Walleij int voltage; 403888cd222bSLinus Walleij int i; 403988cd222bSLinus Walleij 404073e705bfSMatthias Kaehlcke if (ops->set_voltage_time) 404173e705bfSMatthias Kaehlcke return ops->set_voltage_time(rdev, old_uV, new_uV); 404273e705bfSMatthias Kaehlcke else if (!ops->set_voltage_time_sel) 404373e705bfSMatthias Kaehlcke return _regulator_set_voltage_time(rdev, old_uV, new_uV); 404473e705bfSMatthias Kaehlcke 404588cd222bSLinus Walleij /* Currently requires operations to do this */ 404673e705bfSMatthias Kaehlcke if (!ops->list_voltage || !rdev->desc->n_voltages) 404788cd222bSLinus Walleij return -EINVAL; 404888cd222bSLinus Walleij 404988cd222bSLinus Walleij for (i = 0; i < rdev->desc->n_voltages; i++) { 405088cd222bSLinus Walleij /* We only look for exact voltage matches here */ 4051bdcd1177SClaudiu Beznea if (i < rdev->desc->linear_min_sel) 4052bdcd1177SClaudiu Beznea continue; 4053bdcd1177SClaudiu Beznea 4054ab97800eSClaudiu Beznea if (old_sel >= 0 && new_sel >= 0) 4055ab97800eSClaudiu Beznea break; 4056ab97800eSClaudiu Beznea 405788cd222bSLinus Walleij voltage = regulator_list_voltage(regulator, i); 405888cd222bSLinus Walleij if (voltage < 0) 405988cd222bSLinus Walleij return -EINVAL; 406088cd222bSLinus Walleij if (voltage == 0) 406188cd222bSLinus Walleij continue; 406288cd222bSLinus Walleij if (voltage == old_uV) 406388cd222bSLinus Walleij old_sel = i; 406488cd222bSLinus Walleij if (voltage == new_uV) 406588cd222bSLinus Walleij new_sel = i; 406688cd222bSLinus Walleij } 406788cd222bSLinus Walleij 406888cd222bSLinus Walleij if (old_sel < 0 || new_sel < 0) 406988cd222bSLinus Walleij return -EINVAL; 407088cd222bSLinus Walleij 407188cd222bSLinus Walleij return ops->set_voltage_time_sel(rdev, old_sel, new_sel); 407288cd222bSLinus Walleij } 407388cd222bSLinus Walleij EXPORT_SYMBOL_GPL(regulator_set_voltage_time); 407488cd222bSLinus Walleij 407588cd222bSLinus Walleij /** 407698a175b6SYadwinder Singh Brar * regulator_set_voltage_time_sel - get raise/fall time 4077296c6566SRandy Dunlap * @rdev: regulator source device 407898a175b6SYadwinder Singh Brar * @old_selector: selector for starting voltage 407998a175b6SYadwinder Singh Brar * @new_selector: selector for target voltage 408098a175b6SYadwinder Singh Brar * 408198a175b6SYadwinder Singh Brar * Provided with the starting and target voltage selectors, this function 408298a175b6SYadwinder Singh Brar * returns time in microseconds required to rise or fall to this new voltage 408398a175b6SYadwinder Singh Brar * 4084f11d08c3SAxel Lin * Drivers providing ramp_delay in regulation_constraints can use this as their 4085398715abSAxel Lin * set_voltage_time_sel() operation. 408698a175b6SYadwinder Singh Brar */ 408798a175b6SYadwinder Singh Brar int regulator_set_voltage_time_sel(struct regulator_dev *rdev, 408898a175b6SYadwinder Singh Brar unsigned int old_selector, 408998a175b6SYadwinder Singh Brar unsigned int new_selector) 409098a175b6SYadwinder Singh Brar { 4091f11d08c3SAxel Lin int old_volt, new_volt; 4092398715abSAxel Lin 4093f11d08c3SAxel Lin /* sanity check */ 4094f11d08c3SAxel Lin if (!rdev->desc->ops->list_voltage) 4095f11d08c3SAxel Lin return -EINVAL; 4096398715abSAxel Lin 4097f11d08c3SAxel Lin old_volt = rdev->desc->ops->list_voltage(rdev, old_selector); 4098f11d08c3SAxel Lin new_volt = rdev->desc->ops->list_voltage(rdev, new_selector); 4099f11d08c3SAxel Lin 410073e705bfSMatthias Kaehlcke if (rdev->desc->ops->set_voltage_time) 410173e705bfSMatthias Kaehlcke return rdev->desc->ops->set_voltage_time(rdev, old_volt, 410273e705bfSMatthias Kaehlcke new_volt); 410373e705bfSMatthias Kaehlcke else 410473e705bfSMatthias Kaehlcke return _regulator_set_voltage_time(rdev, old_volt, new_volt); 410598a175b6SYadwinder Singh Brar } 4106b19dbf71SMark Brown EXPORT_SYMBOL_GPL(regulator_set_voltage_time_sel); 410798a175b6SYadwinder Singh Brar 4108*380d2b2dSDmitry Osipenko int regulator_sync_voltage_rdev(struct regulator_dev *rdev) 4109*380d2b2dSDmitry Osipenko { 4110*380d2b2dSDmitry Osipenko int ret; 4111*380d2b2dSDmitry Osipenko 4112*380d2b2dSDmitry Osipenko regulator_lock(rdev); 4113*380d2b2dSDmitry Osipenko 4114*380d2b2dSDmitry Osipenko if (!rdev->desc->ops->set_voltage && 4115*380d2b2dSDmitry Osipenko !rdev->desc->ops->set_voltage_sel) { 4116*380d2b2dSDmitry Osipenko ret = -EINVAL; 4117*380d2b2dSDmitry Osipenko goto out; 4118*380d2b2dSDmitry Osipenko } 4119*380d2b2dSDmitry Osipenko 4120*380d2b2dSDmitry Osipenko /* balance only, if regulator is coupled */ 4121*380d2b2dSDmitry Osipenko if (rdev->coupling_desc.n_coupled > 1) 4122*380d2b2dSDmitry Osipenko ret = regulator_balance_voltage(rdev, PM_SUSPEND_ON); 4123*380d2b2dSDmitry Osipenko else 4124*380d2b2dSDmitry Osipenko ret = -EOPNOTSUPP; 4125*380d2b2dSDmitry Osipenko 4126*380d2b2dSDmitry Osipenko out: 4127*380d2b2dSDmitry Osipenko regulator_unlock(rdev); 4128*380d2b2dSDmitry Osipenko return ret; 4129*380d2b2dSDmitry Osipenko } 4130*380d2b2dSDmitry Osipenko 413198a175b6SYadwinder Singh Brar /** 4132606a2562SMark Brown * regulator_sync_voltage - re-apply last regulator output voltage 4133606a2562SMark Brown * @regulator: regulator source 4134606a2562SMark Brown * 4135606a2562SMark Brown * Re-apply the last configured voltage. This is intended to be used 4136606a2562SMark Brown * where some external control source the consumer is cooperating with 4137606a2562SMark Brown * has caused the configured voltage to change. 4138606a2562SMark Brown */ 4139606a2562SMark Brown int regulator_sync_voltage(struct regulator *regulator) 4140606a2562SMark Brown { 4141606a2562SMark Brown struct regulator_dev *rdev = regulator->rdev; 4142c360a6dfSChunyan Zhang struct regulator_voltage *voltage = ®ulator->voltage[PM_SUSPEND_ON]; 4143606a2562SMark Brown int ret, min_uV, max_uV; 4144606a2562SMark Brown 414566cf9a7eSMaciej Purski regulator_lock(rdev); 4146606a2562SMark Brown 4147606a2562SMark Brown if (!rdev->desc->ops->set_voltage && 4148606a2562SMark Brown !rdev->desc->ops->set_voltage_sel) { 4149606a2562SMark Brown ret = -EINVAL; 4150606a2562SMark Brown goto out; 4151606a2562SMark Brown } 4152606a2562SMark Brown 4153606a2562SMark Brown /* This is only going to work if we've had a voltage configured. */ 4154c360a6dfSChunyan Zhang if (!voltage->min_uV && !voltage->max_uV) { 4155606a2562SMark Brown ret = -EINVAL; 4156606a2562SMark Brown goto out; 4157606a2562SMark Brown } 4158606a2562SMark Brown 4159c360a6dfSChunyan Zhang min_uV = voltage->min_uV; 4160c360a6dfSChunyan Zhang max_uV = voltage->max_uV; 4161606a2562SMark Brown 4162606a2562SMark Brown /* This should be a paranoia check... */ 4163606a2562SMark Brown ret = regulator_check_voltage(rdev, &min_uV, &max_uV); 4164606a2562SMark Brown if (ret < 0) 4165606a2562SMark Brown goto out; 4166606a2562SMark Brown 4167c360a6dfSChunyan Zhang ret = regulator_check_consumers(rdev, &min_uV, &max_uV, 0); 4168606a2562SMark Brown if (ret < 0) 4169606a2562SMark Brown goto out; 4170606a2562SMark Brown 417124be0c71SDmitry Osipenko /* balance only, if regulator is coupled */ 417224be0c71SDmitry Osipenko if (rdev->coupling_desc.n_coupled > 1) 417324be0c71SDmitry Osipenko ret = regulator_balance_voltage(rdev, PM_SUSPEND_ON); 417424be0c71SDmitry Osipenko else 4175606a2562SMark Brown ret = _regulator_do_set_voltage(rdev, min_uV, max_uV); 4176606a2562SMark Brown 4177606a2562SMark Brown out: 417866cf9a7eSMaciej Purski regulator_unlock(rdev); 4179606a2562SMark Brown return ret; 4180606a2562SMark Brown } 4181606a2562SMark Brown EXPORT_SYMBOL_GPL(regulator_sync_voltage); 4182606a2562SMark Brown 4183d22b85a1SDmitry Osipenko int regulator_get_voltage_rdev(struct regulator_dev *rdev) 4184414c70cbSLiam Girdwood { 4185bf5892a8SMark Brown int sel, ret; 4186fef95019SMark Brown bool bypassed; 4187fef95019SMark Brown 4188fef95019SMark Brown if (rdev->desc->ops->get_bypass) { 4189fef95019SMark Brown ret = rdev->desc->ops->get_bypass(rdev, &bypassed); 4190fef95019SMark Brown if (ret < 0) 4191fef95019SMark Brown return ret; 4192fef95019SMark Brown if (bypassed) { 4193fef95019SMark Brown /* if bypassed the regulator must have a supply */ 419445389c47SJon Hunter if (!rdev->supply) { 419545389c47SJon Hunter rdev_err(rdev, 419645389c47SJon Hunter "bypassed regulator has no supply!\n"); 419745389c47SJon Hunter return -EPROBE_DEFER; 419845389c47SJon Hunter } 4199fef95019SMark Brown 4200d22b85a1SDmitry Osipenko return regulator_get_voltage_rdev(rdev->supply->rdev); 4201fef95019SMark Brown } 4202fef95019SMark Brown } 4203476c2d83SMark Brown 4204476c2d83SMark Brown if (rdev->desc->ops->get_voltage_sel) { 4205476c2d83SMark Brown sel = rdev->desc->ops->get_voltage_sel(rdev); 4206476c2d83SMark Brown if (sel < 0) 4207476c2d83SMark Brown return sel; 4208bf5892a8SMark Brown ret = rdev->desc->ops->list_voltage(rdev, sel); 4209cb220d16SAxel Lin } else if (rdev->desc->ops->get_voltage) { 4210bf5892a8SMark Brown ret = rdev->desc->ops->get_voltage(rdev); 4211f7df20ecSMark Brown } else if (rdev->desc->ops->list_voltage) { 4212f7df20ecSMark Brown ret = rdev->desc->ops->list_voltage(rdev, 0); 42135a523605SLaxman Dewangan } else if (rdev->desc->fixed_uV && (rdev->desc->n_voltages == 1)) { 42145a523605SLaxman Dewangan ret = rdev->desc->fixed_uV; 4215e303996eSJavier Martinez Canillas } else if (rdev->supply) { 4216d22b85a1SDmitry Osipenko ret = regulator_get_voltage_rdev(rdev->supply->rdev); 4217cf1ad559SMichał Mirosław } else if (rdev->supply_name) { 4218cf1ad559SMichał Mirosław return -EPROBE_DEFER; 4219cb220d16SAxel Lin } else { 4220414c70cbSLiam Girdwood return -EINVAL; 4221cb220d16SAxel Lin } 4222bf5892a8SMark Brown 4223cb220d16SAxel Lin if (ret < 0) 4224cb220d16SAxel Lin return ret; 4225bf5892a8SMark Brown return ret - rdev->constraints->uV_offset; 4226414c70cbSLiam Girdwood } 42273d7610e8SEnric Balletbo i Serra EXPORT_SYMBOL_GPL(regulator_get_voltage_rdev); 4228414c70cbSLiam Girdwood 4229414c70cbSLiam Girdwood /** 4230414c70cbSLiam Girdwood * regulator_get_voltage - get regulator output voltage 4231414c70cbSLiam Girdwood * @regulator: regulator source 4232414c70cbSLiam Girdwood * 4233414c70cbSLiam Girdwood * This returns the current regulator voltage in uV. 4234414c70cbSLiam Girdwood * 4235414c70cbSLiam Girdwood * NOTE: If the regulator is disabled it will return the voltage value. This 4236414c70cbSLiam Girdwood * function should not be used to determine regulator state. 4237414c70cbSLiam Girdwood */ 4238414c70cbSLiam Girdwood int regulator_get_voltage(struct regulator *regulator) 4239414c70cbSLiam Girdwood { 4240f8702f9eSDmitry Osipenko struct ww_acquire_ctx ww_ctx; 4241414c70cbSLiam Girdwood int ret; 4242414c70cbSLiam Girdwood 4243f8702f9eSDmitry Osipenko regulator_lock_dependent(regulator->rdev, &ww_ctx); 4244d22b85a1SDmitry Osipenko ret = regulator_get_voltage_rdev(regulator->rdev); 4245f8702f9eSDmitry Osipenko regulator_unlock_dependent(regulator->rdev, &ww_ctx); 4246414c70cbSLiam Girdwood 4247414c70cbSLiam Girdwood return ret; 4248414c70cbSLiam Girdwood } 4249414c70cbSLiam Girdwood EXPORT_SYMBOL_GPL(regulator_get_voltage); 4250414c70cbSLiam Girdwood 4251414c70cbSLiam Girdwood /** 4252414c70cbSLiam Girdwood * regulator_set_current_limit - set regulator output current limit 4253414c70cbSLiam Girdwood * @regulator: regulator source 4254ce0d10f8SCharles Keepax * @min_uA: Minimum supported current in uA 4255414c70cbSLiam Girdwood * @max_uA: Maximum supported current in uA 4256414c70cbSLiam Girdwood * 4257414c70cbSLiam Girdwood * Sets current sink to the desired output current. This can be set during 4258414c70cbSLiam Girdwood * any regulator state. IOW, regulator can be disabled or enabled. 4259414c70cbSLiam Girdwood * 4260414c70cbSLiam Girdwood * If the regulator is enabled then the current will change to the new value 4261414c70cbSLiam Girdwood * immediately otherwise if the regulator is disabled the regulator will 4262414c70cbSLiam Girdwood * output at the new current when enabled. 4263414c70cbSLiam Girdwood * 4264414c70cbSLiam Girdwood * NOTE: Regulator system constraints must be set for this regulator before 4265414c70cbSLiam Girdwood * calling this function otherwise this call will fail. 4266414c70cbSLiam Girdwood */ 4267414c70cbSLiam Girdwood int regulator_set_current_limit(struct regulator *regulator, 4268414c70cbSLiam Girdwood int min_uA, int max_uA) 4269414c70cbSLiam Girdwood { 4270414c70cbSLiam Girdwood struct regulator_dev *rdev = regulator->rdev; 4271414c70cbSLiam Girdwood int ret; 4272414c70cbSLiam Girdwood 427366cf9a7eSMaciej Purski regulator_lock(rdev); 4274414c70cbSLiam Girdwood 4275414c70cbSLiam Girdwood /* sanity check */ 4276414c70cbSLiam Girdwood if (!rdev->desc->ops->set_current_limit) { 4277414c70cbSLiam Girdwood ret = -EINVAL; 4278414c70cbSLiam Girdwood goto out; 4279414c70cbSLiam Girdwood } 4280414c70cbSLiam Girdwood 4281414c70cbSLiam Girdwood /* constraints check */ 4282414c70cbSLiam Girdwood ret = regulator_check_current_limit(rdev, &min_uA, &max_uA); 4283414c70cbSLiam Girdwood if (ret < 0) 4284414c70cbSLiam Girdwood goto out; 4285414c70cbSLiam Girdwood 4286414c70cbSLiam Girdwood ret = rdev->desc->ops->set_current_limit(rdev, min_uA, max_uA); 4287414c70cbSLiam Girdwood out: 428866cf9a7eSMaciej Purski regulator_unlock(rdev); 4289414c70cbSLiam Girdwood return ret; 4290414c70cbSLiam Girdwood } 4291414c70cbSLiam Girdwood EXPORT_SYMBOL_GPL(regulator_set_current_limit); 4292414c70cbSLiam Girdwood 42937e4d9683SDouglas Anderson static int _regulator_get_current_limit_unlocked(struct regulator_dev *rdev) 42947e4d9683SDouglas Anderson { 42957e4d9683SDouglas Anderson /* sanity check */ 42967e4d9683SDouglas Anderson if (!rdev->desc->ops->get_current_limit) 42977e4d9683SDouglas Anderson return -EINVAL; 42987e4d9683SDouglas Anderson 42997e4d9683SDouglas Anderson return rdev->desc->ops->get_current_limit(rdev); 43007e4d9683SDouglas Anderson } 43017e4d9683SDouglas Anderson 4302414c70cbSLiam Girdwood static int _regulator_get_current_limit(struct regulator_dev *rdev) 4303414c70cbSLiam Girdwood { 4304414c70cbSLiam Girdwood int ret; 4305414c70cbSLiam Girdwood 430666cf9a7eSMaciej Purski regulator_lock(rdev); 43077e4d9683SDouglas Anderson ret = _regulator_get_current_limit_unlocked(rdev); 430866cf9a7eSMaciej Purski regulator_unlock(rdev); 43097e4d9683SDouglas Anderson 4310414c70cbSLiam Girdwood return ret; 4311414c70cbSLiam Girdwood } 4312414c70cbSLiam Girdwood 4313414c70cbSLiam Girdwood /** 4314414c70cbSLiam Girdwood * regulator_get_current_limit - get regulator output current 4315414c70cbSLiam Girdwood * @regulator: regulator source 4316414c70cbSLiam Girdwood * 4317414c70cbSLiam Girdwood * This returns the current supplied by the specified current sink in uA. 4318414c70cbSLiam Girdwood * 4319414c70cbSLiam Girdwood * NOTE: If the regulator is disabled it will return the current value. This 4320414c70cbSLiam Girdwood * function should not be used to determine regulator state. 4321414c70cbSLiam Girdwood */ 4322414c70cbSLiam Girdwood int regulator_get_current_limit(struct regulator *regulator) 4323414c70cbSLiam Girdwood { 4324414c70cbSLiam Girdwood return _regulator_get_current_limit(regulator->rdev); 4325414c70cbSLiam Girdwood } 4326414c70cbSLiam Girdwood EXPORT_SYMBOL_GPL(regulator_get_current_limit); 4327414c70cbSLiam Girdwood 4328414c70cbSLiam Girdwood /** 4329414c70cbSLiam Girdwood * regulator_set_mode - set regulator operating mode 4330414c70cbSLiam Girdwood * @regulator: regulator source 4331414c70cbSLiam Girdwood * @mode: operating mode - one of the REGULATOR_MODE constants 4332414c70cbSLiam Girdwood * 4333414c70cbSLiam Girdwood * Set regulator operating mode to increase regulator efficiency or improve 4334414c70cbSLiam Girdwood * regulation performance. 4335414c70cbSLiam Girdwood * 4336414c70cbSLiam Girdwood * NOTE: Regulator system constraints must be set for this regulator before 4337414c70cbSLiam Girdwood * calling this function otherwise this call will fail. 4338414c70cbSLiam Girdwood */ 4339414c70cbSLiam Girdwood int regulator_set_mode(struct regulator *regulator, unsigned int mode) 4340414c70cbSLiam Girdwood { 4341414c70cbSLiam Girdwood struct regulator_dev *rdev = regulator->rdev; 4342414c70cbSLiam Girdwood int ret; 4343500b4ac9SSundar R Iyer int regulator_curr_mode; 4344414c70cbSLiam Girdwood 434566cf9a7eSMaciej Purski regulator_lock(rdev); 4346414c70cbSLiam Girdwood 4347414c70cbSLiam Girdwood /* sanity check */ 4348414c70cbSLiam Girdwood if (!rdev->desc->ops->set_mode) { 4349414c70cbSLiam Girdwood ret = -EINVAL; 4350414c70cbSLiam Girdwood goto out; 4351414c70cbSLiam Girdwood } 4352414c70cbSLiam Girdwood 4353500b4ac9SSundar R Iyer /* return if the same mode is requested */ 4354500b4ac9SSundar R Iyer if (rdev->desc->ops->get_mode) { 4355500b4ac9SSundar R Iyer regulator_curr_mode = rdev->desc->ops->get_mode(rdev); 4356500b4ac9SSundar R Iyer if (regulator_curr_mode == mode) { 4357500b4ac9SSundar R Iyer ret = 0; 4358500b4ac9SSundar R Iyer goto out; 4359500b4ac9SSundar R Iyer } 4360500b4ac9SSundar R Iyer } 4361500b4ac9SSundar R Iyer 4362414c70cbSLiam Girdwood /* constraints check */ 436322c51b47SAxel Lin ret = regulator_mode_constrain(rdev, &mode); 4364414c70cbSLiam Girdwood if (ret < 0) 4365414c70cbSLiam Girdwood goto out; 4366414c70cbSLiam Girdwood 4367414c70cbSLiam Girdwood ret = rdev->desc->ops->set_mode(rdev, mode); 4368414c70cbSLiam Girdwood out: 436966cf9a7eSMaciej Purski regulator_unlock(rdev); 4370414c70cbSLiam Girdwood return ret; 4371414c70cbSLiam Girdwood } 4372414c70cbSLiam Girdwood EXPORT_SYMBOL_GPL(regulator_set_mode); 4373414c70cbSLiam Girdwood 43747e4d9683SDouglas Anderson static unsigned int _regulator_get_mode_unlocked(struct regulator_dev *rdev) 43757e4d9683SDouglas Anderson { 43767e4d9683SDouglas Anderson /* sanity check */ 43777e4d9683SDouglas Anderson if (!rdev->desc->ops->get_mode) 43787e4d9683SDouglas Anderson return -EINVAL; 43797e4d9683SDouglas Anderson 43807e4d9683SDouglas Anderson return rdev->desc->ops->get_mode(rdev); 43817e4d9683SDouglas Anderson } 43827e4d9683SDouglas Anderson 4383414c70cbSLiam Girdwood static unsigned int _regulator_get_mode(struct regulator_dev *rdev) 4384414c70cbSLiam Girdwood { 4385414c70cbSLiam Girdwood int ret; 4386414c70cbSLiam Girdwood 438766cf9a7eSMaciej Purski regulator_lock(rdev); 43887e4d9683SDouglas Anderson ret = _regulator_get_mode_unlocked(rdev); 438966cf9a7eSMaciej Purski regulator_unlock(rdev); 43907e4d9683SDouglas Anderson 4391414c70cbSLiam Girdwood return ret; 4392414c70cbSLiam Girdwood } 4393414c70cbSLiam Girdwood 4394414c70cbSLiam Girdwood /** 4395414c70cbSLiam Girdwood * regulator_get_mode - get regulator operating mode 4396414c70cbSLiam Girdwood * @regulator: regulator source 4397414c70cbSLiam Girdwood * 4398414c70cbSLiam Girdwood * Get the current regulator operating mode. 4399414c70cbSLiam Girdwood */ 4400414c70cbSLiam Girdwood unsigned int regulator_get_mode(struct regulator *regulator) 4401414c70cbSLiam Girdwood { 4402414c70cbSLiam Girdwood return _regulator_get_mode(regulator->rdev); 4403414c70cbSLiam Girdwood } 4404414c70cbSLiam Girdwood EXPORT_SYMBOL_GPL(regulator_get_mode); 4405414c70cbSLiam Girdwood 44061b5b4221SAxel Haslam static int _regulator_get_error_flags(struct regulator_dev *rdev, 44071b5b4221SAxel Haslam unsigned int *flags) 44081b5b4221SAxel Haslam { 44091b5b4221SAxel Haslam int ret; 44101b5b4221SAxel Haslam 441166cf9a7eSMaciej Purski regulator_lock(rdev); 44121b5b4221SAxel Haslam 44131b5b4221SAxel Haslam /* sanity check */ 44141b5b4221SAxel Haslam if (!rdev->desc->ops->get_error_flags) { 44151b5b4221SAxel Haslam ret = -EINVAL; 44161b5b4221SAxel Haslam goto out; 44171b5b4221SAxel Haslam } 44181b5b4221SAxel Haslam 44191b5b4221SAxel Haslam ret = rdev->desc->ops->get_error_flags(rdev, flags); 44201b5b4221SAxel Haslam out: 442166cf9a7eSMaciej Purski regulator_unlock(rdev); 44221b5b4221SAxel Haslam return ret; 44231b5b4221SAxel Haslam } 44241b5b4221SAxel Haslam 44251b5b4221SAxel Haslam /** 44261b5b4221SAxel Haslam * regulator_get_error_flags - get regulator error information 44271b5b4221SAxel Haslam * @regulator: regulator source 44281b5b4221SAxel Haslam * @flags: pointer to store error flags 44291b5b4221SAxel Haslam * 44301b5b4221SAxel Haslam * Get the current regulator error information. 44311b5b4221SAxel Haslam */ 44321b5b4221SAxel Haslam int regulator_get_error_flags(struct regulator *regulator, 44331b5b4221SAxel Haslam unsigned int *flags) 44341b5b4221SAxel Haslam { 44351b5b4221SAxel Haslam return _regulator_get_error_flags(regulator->rdev, flags); 44361b5b4221SAxel Haslam } 44371b5b4221SAxel Haslam EXPORT_SYMBOL_GPL(regulator_get_error_flags); 44381b5b4221SAxel Haslam 4439414c70cbSLiam Girdwood /** 4440e39ce48fSBjorn Andersson * regulator_set_load - set regulator load 4441414c70cbSLiam Girdwood * @regulator: regulator source 4442414c70cbSLiam Girdwood * @uA_load: load current 4443414c70cbSLiam Girdwood * 4444414c70cbSLiam Girdwood * Notifies the regulator core of a new device load. This is then used by 4445414c70cbSLiam Girdwood * DRMS (if enabled by constraints) to set the most efficient regulator 4446414c70cbSLiam Girdwood * operating mode for the new regulator loading. 4447414c70cbSLiam Girdwood * 4448414c70cbSLiam Girdwood * Consumer devices notify their supply regulator of the maximum power 4449414c70cbSLiam Girdwood * they will require (can be taken from device datasheet in the power 4450414c70cbSLiam Girdwood * consumption tables) when they change operational status and hence power 4451414c70cbSLiam Girdwood * state. Examples of operational state changes that can affect power 4452414c70cbSLiam Girdwood * consumption are :- 4453414c70cbSLiam Girdwood * 4454414c70cbSLiam Girdwood * o Device is opened / closed. 4455414c70cbSLiam Girdwood * o Device I/O is about to begin or has just finished. 4456414c70cbSLiam Girdwood * o Device is idling in between work. 4457414c70cbSLiam Girdwood * 4458414c70cbSLiam Girdwood * This information is also exported via sysfs to userspace. 4459414c70cbSLiam Girdwood * 4460414c70cbSLiam Girdwood * DRMS will sum the total requested load on the regulator and change 4461414c70cbSLiam Girdwood * to the most efficient operating mode if platform constraints allow. 4462414c70cbSLiam Girdwood * 44635451781dSDouglas Anderson * NOTE: when a regulator consumer requests to have a regulator 44645451781dSDouglas Anderson * disabled then any load that consumer requested no longer counts 44655451781dSDouglas Anderson * toward the total requested load. If the regulator is re-enabled 44665451781dSDouglas Anderson * then the previously requested load will start counting again. 44675451781dSDouglas Anderson * 44685451781dSDouglas Anderson * If a regulator is an always-on regulator then an individual consumer's 44695451781dSDouglas Anderson * load will still be removed if that consumer is fully disabled. 44705451781dSDouglas Anderson * 4471e39ce48fSBjorn Andersson * On error a negative errno is returned. 4472414c70cbSLiam Girdwood */ 4473e39ce48fSBjorn Andersson int regulator_set_load(struct regulator *regulator, int uA_load) 4474414c70cbSLiam Girdwood { 4475414c70cbSLiam Girdwood struct regulator_dev *rdev = regulator->rdev; 44765451781dSDouglas Anderson int old_uA_load; 44775451781dSDouglas Anderson int ret = 0; 4478d92d95b6SStephen Boyd 447966cf9a7eSMaciej Purski regulator_lock(rdev); 44805451781dSDouglas Anderson old_uA_load = regulator->uA_load; 4481414c70cbSLiam Girdwood regulator->uA_load = uA_load; 44825451781dSDouglas Anderson if (regulator->enable_count && old_uA_load != uA_load) { 44838460ef38SBjorn Andersson ret = drms_uA_update(rdev); 44845451781dSDouglas Anderson if (ret < 0) 44855451781dSDouglas Anderson regulator->uA_load = old_uA_load; 44865451781dSDouglas Anderson } 448766cf9a7eSMaciej Purski regulator_unlock(rdev); 44888460ef38SBjorn Andersson 4489414c70cbSLiam Girdwood return ret; 4490414c70cbSLiam Girdwood } 4491e39ce48fSBjorn Andersson EXPORT_SYMBOL_GPL(regulator_set_load); 4492414c70cbSLiam Girdwood 4493414c70cbSLiam Girdwood /** 4494f59c8f9fSMark Brown * regulator_allow_bypass - allow the regulator to go into bypass mode 4495f59c8f9fSMark Brown * 4496f59c8f9fSMark Brown * @regulator: Regulator to configure 44979345dfb8SNishanth Menon * @enable: enable or disable bypass mode 4498f59c8f9fSMark Brown * 4499f59c8f9fSMark Brown * Allow the regulator to go into bypass mode if all other consumers 4500f59c8f9fSMark Brown * for the regulator also enable bypass mode and the machine 4501f59c8f9fSMark Brown * constraints allow this. Bypass mode means that the regulator is 4502f59c8f9fSMark Brown * simply passing the input directly to the output with no regulation. 4503f59c8f9fSMark Brown */ 4504f59c8f9fSMark Brown int regulator_allow_bypass(struct regulator *regulator, bool enable) 4505f59c8f9fSMark Brown { 4506f59c8f9fSMark Brown struct regulator_dev *rdev = regulator->rdev; 450748325655SCharles Keepax const char *name = rdev_get_name(rdev); 4508f59c8f9fSMark Brown int ret = 0; 4509f59c8f9fSMark Brown 4510f59c8f9fSMark Brown if (!rdev->desc->ops->set_bypass) 4511f59c8f9fSMark Brown return 0; 4512f59c8f9fSMark Brown 45138a34e979SWEN Pingbo if (!regulator_ops_is_valid(rdev, REGULATOR_CHANGE_BYPASS)) 4514f59c8f9fSMark Brown return 0; 4515f59c8f9fSMark Brown 451666cf9a7eSMaciej Purski regulator_lock(rdev); 4517f59c8f9fSMark Brown 4518f59c8f9fSMark Brown 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_enable(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_enable_complete(name); 4529f59c8f9fSMark Brown } 4530f59c8f9fSMark Brown 4531f59c8f9fSMark Brown } else if (!enable && regulator->bypass) { 4532f59c8f9fSMark Brown rdev->bypass_count--; 4533f59c8f9fSMark Brown 4534f59c8f9fSMark Brown if (rdev->bypass_count != rdev->open_count) { 453548325655SCharles Keepax trace_regulator_bypass_disable(name); 453648325655SCharles Keepax 4537f59c8f9fSMark Brown ret = rdev->desc->ops->set_bypass(rdev, enable); 4538f59c8f9fSMark Brown if (ret != 0) 4539f59c8f9fSMark Brown rdev->bypass_count++; 454048325655SCharles Keepax else 454148325655SCharles Keepax trace_regulator_bypass_disable_complete(name); 4542f59c8f9fSMark Brown } 4543f59c8f9fSMark Brown } 4544f59c8f9fSMark Brown 4545f59c8f9fSMark Brown if (ret == 0) 4546f59c8f9fSMark Brown regulator->bypass = enable; 4547f59c8f9fSMark Brown 454866cf9a7eSMaciej Purski regulator_unlock(rdev); 4549f59c8f9fSMark Brown 4550f59c8f9fSMark Brown return ret; 4551f59c8f9fSMark Brown } 4552f59c8f9fSMark Brown EXPORT_SYMBOL_GPL(regulator_allow_bypass); 4553f59c8f9fSMark Brown 4554f59c8f9fSMark Brown /** 4555414c70cbSLiam Girdwood * regulator_register_notifier - register regulator event notifier 4556414c70cbSLiam Girdwood * @regulator: regulator source 455769279fb9SMark Brown * @nb: notifier block 4558414c70cbSLiam Girdwood * 4559414c70cbSLiam Girdwood * Register notifier block to receive regulator events. 4560414c70cbSLiam Girdwood */ 4561414c70cbSLiam Girdwood int regulator_register_notifier(struct regulator *regulator, 4562414c70cbSLiam Girdwood struct notifier_block *nb) 4563414c70cbSLiam Girdwood { 4564414c70cbSLiam Girdwood return blocking_notifier_chain_register(®ulator->rdev->notifier, 4565414c70cbSLiam Girdwood nb); 4566414c70cbSLiam Girdwood } 4567414c70cbSLiam Girdwood EXPORT_SYMBOL_GPL(regulator_register_notifier); 4568414c70cbSLiam Girdwood 4569414c70cbSLiam Girdwood /** 4570414c70cbSLiam Girdwood * regulator_unregister_notifier - unregister regulator event notifier 4571414c70cbSLiam Girdwood * @regulator: regulator source 457269279fb9SMark Brown * @nb: notifier block 4573414c70cbSLiam Girdwood * 4574414c70cbSLiam Girdwood * Unregister regulator event notifier block. 4575414c70cbSLiam Girdwood */ 4576414c70cbSLiam Girdwood int regulator_unregister_notifier(struct regulator *regulator, 4577414c70cbSLiam Girdwood struct notifier_block *nb) 4578414c70cbSLiam Girdwood { 4579414c70cbSLiam Girdwood return blocking_notifier_chain_unregister(®ulator->rdev->notifier, 4580414c70cbSLiam Girdwood nb); 4581414c70cbSLiam Girdwood } 4582414c70cbSLiam Girdwood EXPORT_SYMBOL_GPL(regulator_unregister_notifier); 4583414c70cbSLiam Girdwood 4584b136fb44SJonathan Cameron /* notify regulator consumers and downstream regulator consumers. 4585b136fb44SJonathan Cameron * Note mutex must be held by caller. 4586b136fb44SJonathan Cameron */ 45877179569aSHeiko Stübner static int _notifier_call_chain(struct regulator_dev *rdev, 4588414c70cbSLiam Girdwood unsigned long event, void *data) 4589414c70cbSLiam Girdwood { 4590414c70cbSLiam Girdwood /* call rdev chain first */ 45917179569aSHeiko Stübner return blocking_notifier_call_chain(&rdev->notifier, event, data); 4592414c70cbSLiam Girdwood } 4593414c70cbSLiam Girdwood 4594414c70cbSLiam Girdwood /** 4595414c70cbSLiam Girdwood * regulator_bulk_get - get multiple regulator consumers 4596414c70cbSLiam Girdwood * 4597414c70cbSLiam Girdwood * @dev: Device to supply 4598414c70cbSLiam Girdwood * @num_consumers: Number of consumers to register 4599414c70cbSLiam Girdwood * @consumers: Configuration of consumers; clients are stored here. 4600414c70cbSLiam Girdwood * 4601414c70cbSLiam Girdwood * @return 0 on success, an errno on failure. 4602414c70cbSLiam Girdwood * 4603414c70cbSLiam Girdwood * This helper function allows drivers to get several regulator 4604414c70cbSLiam Girdwood * consumers in one operation. If any of the regulators cannot be 4605414c70cbSLiam Girdwood * acquired then any regulators that were allocated will be freed 4606414c70cbSLiam Girdwood * before returning to the caller. 4607414c70cbSLiam Girdwood */ 4608414c70cbSLiam Girdwood int regulator_bulk_get(struct device *dev, int num_consumers, 4609414c70cbSLiam Girdwood struct regulator_bulk_data *consumers) 4610414c70cbSLiam Girdwood { 4611414c70cbSLiam Girdwood int i; 4612414c70cbSLiam Girdwood int ret; 4613414c70cbSLiam Girdwood 4614414c70cbSLiam Girdwood for (i = 0; i < num_consumers; i++) 4615414c70cbSLiam Girdwood consumers[i].consumer = NULL; 4616414c70cbSLiam Girdwood 4617414c70cbSLiam Girdwood for (i = 0; i < num_consumers; i++) { 4618565f9b07SBjorn Andersson consumers[i].consumer = regulator_get(dev, 4619565f9b07SBjorn Andersson consumers[i].supply); 4620414c70cbSLiam Girdwood if (IS_ERR(consumers[i].consumer)) { 4621414c70cbSLiam Girdwood ret = PTR_ERR(consumers[i].consumer); 4622414c70cbSLiam Girdwood consumers[i].consumer = NULL; 4623414c70cbSLiam Girdwood goto err; 4624414c70cbSLiam Girdwood } 4625414c70cbSLiam Girdwood } 4626414c70cbSLiam Girdwood 4627414c70cbSLiam Girdwood return 0; 4628414c70cbSLiam Girdwood 4629414c70cbSLiam Girdwood err: 4630b9816363SJorge Ramirez-Ortiz if (ret != -EPROBE_DEFER) 463161aab5adSMichał Mirosław dev_err(dev, "Failed to get supply '%s': %pe\n", 463261aab5adSMichał Mirosław consumers[i].supply, ERR_PTR(ret)); 4633b9816363SJorge Ramirez-Ortiz else 4634b9816363SJorge Ramirez-Ortiz dev_dbg(dev, "Failed to get supply '%s', deferring\n", 4635b9816363SJorge Ramirez-Ortiz consumers[i].supply); 4636b9816363SJorge Ramirez-Ortiz 4637b29c7690SAxel Lin while (--i >= 0) 4638414c70cbSLiam Girdwood regulator_put(consumers[i].consumer); 4639414c70cbSLiam Girdwood 4640414c70cbSLiam Girdwood return ret; 4641414c70cbSLiam Girdwood } 4642414c70cbSLiam Girdwood EXPORT_SYMBOL_GPL(regulator_bulk_get); 4643414c70cbSLiam Girdwood 4644f21e0e81SMark Brown static void regulator_bulk_enable_async(void *data, async_cookie_t cookie) 4645f21e0e81SMark Brown { 4646f21e0e81SMark Brown struct regulator_bulk_data *bulk = data; 4647f21e0e81SMark Brown 4648f21e0e81SMark Brown bulk->ret = regulator_enable(bulk->consumer); 4649f21e0e81SMark Brown } 4650f21e0e81SMark Brown 4651414c70cbSLiam Girdwood /** 4652414c70cbSLiam Girdwood * regulator_bulk_enable - enable multiple regulator consumers 4653414c70cbSLiam Girdwood * 4654414c70cbSLiam Girdwood * @num_consumers: Number of consumers 4655414c70cbSLiam Girdwood * @consumers: Consumer data; clients are stored here. 4656414c70cbSLiam Girdwood * @return 0 on success, an errno on failure 4657414c70cbSLiam Girdwood * 4658414c70cbSLiam Girdwood * This convenience API allows consumers to enable multiple regulator 4659414c70cbSLiam Girdwood * clients in a single API call. If any consumers cannot be enabled 4660414c70cbSLiam Girdwood * then any others that were enabled will be disabled again prior to 4661414c70cbSLiam Girdwood * return. 4662414c70cbSLiam Girdwood */ 4663414c70cbSLiam Girdwood int regulator_bulk_enable(int num_consumers, 4664414c70cbSLiam Girdwood struct regulator_bulk_data *consumers) 4665414c70cbSLiam Girdwood { 46662955b47dSDan Williams ASYNC_DOMAIN_EXCLUSIVE(async_domain); 4667414c70cbSLiam Girdwood int i; 4668f21e0e81SMark Brown int ret = 0; 4669414c70cbSLiam Girdwood 46706492bc1bSMark Brown for (i = 0; i < num_consumers; i++) { 4671f21e0e81SMark Brown async_schedule_domain(regulator_bulk_enable_async, 4672f21e0e81SMark Brown &consumers[i], &async_domain); 46736492bc1bSMark Brown } 4674f21e0e81SMark Brown 4675f21e0e81SMark Brown async_synchronize_full_domain(&async_domain); 4676f21e0e81SMark Brown 4677f21e0e81SMark Brown /* If any consumer failed we need to unwind any that succeeded */ 4678414c70cbSLiam Girdwood for (i = 0; i < num_consumers; i++) { 4679f21e0e81SMark Brown if (consumers[i].ret != 0) { 4680f21e0e81SMark Brown ret = consumers[i].ret; 4681414c70cbSLiam Girdwood goto err; 4682414c70cbSLiam Girdwood } 4683f21e0e81SMark Brown } 4684414c70cbSLiam Girdwood 4685414c70cbSLiam Girdwood return 0; 4686414c70cbSLiam Girdwood 4687414c70cbSLiam Girdwood err: 4688fbe31057SAndrzej Hajda for (i = 0; i < num_consumers; i++) { 4689fbe31057SAndrzej Hajda if (consumers[i].ret < 0) 469061aab5adSMichał Mirosław pr_err("Failed to enable %s: %pe\n", consumers[i].supply, 469161aab5adSMichał Mirosław ERR_PTR(consumers[i].ret)); 4692fbe31057SAndrzej Hajda else 4693414c70cbSLiam Girdwood regulator_disable(consumers[i].consumer); 4694fbe31057SAndrzej Hajda } 4695414c70cbSLiam Girdwood 4696414c70cbSLiam Girdwood return ret; 4697414c70cbSLiam Girdwood } 4698414c70cbSLiam Girdwood EXPORT_SYMBOL_GPL(regulator_bulk_enable); 4699414c70cbSLiam Girdwood 4700414c70cbSLiam Girdwood /** 4701414c70cbSLiam Girdwood * regulator_bulk_disable - disable multiple regulator consumers 4702414c70cbSLiam Girdwood * 4703414c70cbSLiam Girdwood * @num_consumers: Number of consumers 4704414c70cbSLiam Girdwood * @consumers: Consumer data; clients are stored here. 4705414c70cbSLiam Girdwood * @return 0 on success, an errno on failure 4706414c70cbSLiam Girdwood * 4707414c70cbSLiam Girdwood * This convenience API allows consumers to disable multiple regulator 470849e22632SSylwester Nawrocki * clients in a single API call. If any consumers cannot be disabled 470949e22632SSylwester Nawrocki * then any others that were disabled will be enabled again prior to 4710414c70cbSLiam Girdwood * return. 4711414c70cbSLiam Girdwood */ 4712414c70cbSLiam Girdwood int regulator_bulk_disable(int num_consumers, 4713414c70cbSLiam Girdwood struct regulator_bulk_data *consumers) 4714414c70cbSLiam Girdwood { 4715414c70cbSLiam Girdwood int i; 471601e86f49SMark Brown int ret, r; 4717414c70cbSLiam Girdwood 471849e22632SSylwester Nawrocki for (i = num_consumers - 1; i >= 0; --i) { 4719414c70cbSLiam Girdwood ret = regulator_disable(consumers[i].consumer); 4720414c70cbSLiam Girdwood if (ret != 0) 4721414c70cbSLiam Girdwood goto err; 4722414c70cbSLiam Girdwood } 4723414c70cbSLiam Girdwood 4724414c70cbSLiam Girdwood return 0; 4725414c70cbSLiam Girdwood 4726414c70cbSLiam Girdwood err: 472761aab5adSMichał Mirosław pr_err("Failed to disable %s: %pe\n", consumers[i].supply, ERR_PTR(ret)); 472801e86f49SMark Brown for (++i; i < num_consumers; ++i) { 472901e86f49SMark Brown r = regulator_enable(consumers[i].consumer); 473001e86f49SMark Brown if (r != 0) 473161aab5adSMichał Mirosław pr_err("Failed to re-enable %s: %pe\n", 473261aab5adSMichał Mirosław consumers[i].supply, ERR_PTR(r)); 473301e86f49SMark Brown } 4734414c70cbSLiam Girdwood 4735414c70cbSLiam Girdwood return ret; 4736414c70cbSLiam Girdwood } 4737414c70cbSLiam Girdwood EXPORT_SYMBOL_GPL(regulator_bulk_disable); 4738414c70cbSLiam Girdwood 4739414c70cbSLiam Girdwood /** 4740e1de2f42SDonggeun Kim * regulator_bulk_force_disable - force disable multiple regulator consumers 4741e1de2f42SDonggeun Kim * 4742e1de2f42SDonggeun Kim * @num_consumers: Number of consumers 4743e1de2f42SDonggeun Kim * @consumers: Consumer data; clients are stored here. 4744e1de2f42SDonggeun Kim * @return 0 on success, an errno on failure 4745e1de2f42SDonggeun Kim * 4746e1de2f42SDonggeun Kim * This convenience API allows consumers to forcibly disable multiple regulator 4747e1de2f42SDonggeun Kim * clients in a single API call. 4748e1de2f42SDonggeun Kim * NOTE: This should be used for situations when device damage will 4749e1de2f42SDonggeun Kim * likely occur if the regulators are not disabled (e.g. over temp). 4750e1de2f42SDonggeun Kim * Although regulator_force_disable function call for some consumers can 4751e1de2f42SDonggeun Kim * return error numbers, the function is called for all consumers. 4752e1de2f42SDonggeun Kim */ 4753e1de2f42SDonggeun Kim int regulator_bulk_force_disable(int num_consumers, 4754e1de2f42SDonggeun Kim struct regulator_bulk_data *consumers) 4755e1de2f42SDonggeun Kim { 4756e1de2f42SDonggeun Kim int i; 4757b8c77ff6SDmitry Torokhov int ret = 0; 4758e1de2f42SDonggeun Kim 4759b8c77ff6SDmitry Torokhov for (i = 0; i < num_consumers; i++) { 4760e1de2f42SDonggeun Kim consumers[i].ret = 4761e1de2f42SDonggeun Kim regulator_force_disable(consumers[i].consumer); 4762e1de2f42SDonggeun Kim 4763b8c77ff6SDmitry Torokhov /* Store first error for reporting */ 4764b8c77ff6SDmitry Torokhov if (consumers[i].ret && !ret) 4765e1de2f42SDonggeun Kim ret = consumers[i].ret; 4766e1de2f42SDonggeun Kim } 4767e1de2f42SDonggeun Kim 4768e1de2f42SDonggeun Kim return ret; 4769e1de2f42SDonggeun Kim } 4770e1de2f42SDonggeun Kim EXPORT_SYMBOL_GPL(regulator_bulk_force_disable); 4771e1de2f42SDonggeun Kim 4772e1de2f42SDonggeun Kim /** 4773414c70cbSLiam Girdwood * regulator_bulk_free - free multiple regulator consumers 4774414c70cbSLiam Girdwood * 4775414c70cbSLiam Girdwood * @num_consumers: Number of consumers 4776414c70cbSLiam Girdwood * @consumers: Consumer data; clients are stored here. 4777414c70cbSLiam Girdwood * 4778414c70cbSLiam Girdwood * This convenience API allows consumers to free multiple regulator 4779414c70cbSLiam Girdwood * clients in a single API call. 4780414c70cbSLiam Girdwood */ 4781414c70cbSLiam Girdwood void regulator_bulk_free(int num_consumers, 4782414c70cbSLiam Girdwood struct regulator_bulk_data *consumers) 4783414c70cbSLiam Girdwood { 4784414c70cbSLiam Girdwood int i; 4785414c70cbSLiam Girdwood 4786414c70cbSLiam Girdwood for (i = 0; i < num_consumers; i++) { 4787414c70cbSLiam Girdwood regulator_put(consumers[i].consumer); 4788414c70cbSLiam Girdwood consumers[i].consumer = NULL; 4789414c70cbSLiam Girdwood } 4790414c70cbSLiam Girdwood } 4791414c70cbSLiam Girdwood EXPORT_SYMBOL_GPL(regulator_bulk_free); 4792414c70cbSLiam Girdwood 4793414c70cbSLiam Girdwood /** 4794414c70cbSLiam Girdwood * regulator_notifier_call_chain - call regulator event notifier 479569279fb9SMark Brown * @rdev: regulator source 4796414c70cbSLiam Girdwood * @event: notifier block 479769279fb9SMark Brown * @data: callback-specific data. 4798414c70cbSLiam Girdwood * 4799414c70cbSLiam Girdwood * Called by regulator drivers to notify clients a regulator event has 48003bca239dSMichał Mirosław * occurred. 4801414c70cbSLiam Girdwood */ 4802414c70cbSLiam Girdwood int regulator_notifier_call_chain(struct regulator_dev *rdev, 4803414c70cbSLiam Girdwood unsigned long event, void *data) 4804414c70cbSLiam Girdwood { 4805414c70cbSLiam Girdwood _notifier_call_chain(rdev, event, data); 4806414c70cbSLiam Girdwood return NOTIFY_DONE; 4807414c70cbSLiam Girdwood 4808414c70cbSLiam Girdwood } 4809414c70cbSLiam Girdwood EXPORT_SYMBOL_GPL(regulator_notifier_call_chain); 4810414c70cbSLiam Girdwood 4811be721979SMark Brown /** 4812be721979SMark Brown * regulator_mode_to_status - convert a regulator mode into a status 4813be721979SMark Brown * 4814be721979SMark Brown * @mode: Mode to convert 4815be721979SMark Brown * 4816be721979SMark Brown * Convert a regulator mode into a status. 4817be721979SMark Brown */ 4818be721979SMark Brown int regulator_mode_to_status(unsigned int mode) 4819be721979SMark Brown { 4820be721979SMark Brown switch (mode) { 4821be721979SMark Brown case REGULATOR_MODE_FAST: 4822be721979SMark Brown return REGULATOR_STATUS_FAST; 4823be721979SMark Brown case REGULATOR_MODE_NORMAL: 4824be721979SMark Brown return REGULATOR_STATUS_NORMAL; 4825be721979SMark Brown case REGULATOR_MODE_IDLE: 4826be721979SMark Brown return REGULATOR_STATUS_IDLE; 482703ffcf3dSKrystian Garbaciak case REGULATOR_MODE_STANDBY: 4828be721979SMark Brown return REGULATOR_STATUS_STANDBY; 4829be721979SMark Brown default: 48301beaf762SKrystian Garbaciak return REGULATOR_STATUS_UNDEFINED; 4831be721979SMark Brown } 4832be721979SMark Brown } 4833be721979SMark Brown EXPORT_SYMBOL_GPL(regulator_mode_to_status); 4834be721979SMark Brown 483539f802d6STakashi Iwai static struct attribute *regulator_dev_attrs[] = { 483639f802d6STakashi Iwai &dev_attr_name.attr, 483739f802d6STakashi Iwai &dev_attr_num_users.attr, 483839f802d6STakashi Iwai &dev_attr_type.attr, 483939f802d6STakashi Iwai &dev_attr_microvolts.attr, 484039f802d6STakashi Iwai &dev_attr_microamps.attr, 484139f802d6STakashi Iwai &dev_attr_opmode.attr, 484239f802d6STakashi Iwai &dev_attr_state.attr, 484339f802d6STakashi Iwai &dev_attr_status.attr, 484439f802d6STakashi Iwai &dev_attr_bypass.attr, 484539f802d6STakashi Iwai &dev_attr_requested_microamps.attr, 484639f802d6STakashi Iwai &dev_attr_min_microvolts.attr, 484739f802d6STakashi Iwai &dev_attr_max_microvolts.attr, 484839f802d6STakashi Iwai &dev_attr_min_microamps.attr, 484939f802d6STakashi Iwai &dev_attr_max_microamps.attr, 485039f802d6STakashi Iwai &dev_attr_suspend_standby_state.attr, 485139f802d6STakashi Iwai &dev_attr_suspend_mem_state.attr, 485239f802d6STakashi Iwai &dev_attr_suspend_disk_state.attr, 485339f802d6STakashi Iwai &dev_attr_suspend_standby_microvolts.attr, 485439f802d6STakashi Iwai &dev_attr_suspend_mem_microvolts.attr, 485539f802d6STakashi Iwai &dev_attr_suspend_disk_microvolts.attr, 485639f802d6STakashi Iwai &dev_attr_suspend_standby_mode.attr, 485739f802d6STakashi Iwai &dev_attr_suspend_mem_mode.attr, 485839f802d6STakashi Iwai &dev_attr_suspend_disk_mode.attr, 485939f802d6STakashi Iwai NULL 486039f802d6STakashi Iwai }; 486139f802d6STakashi Iwai 48627ad68e2fSDavid Brownell /* 48637ad68e2fSDavid Brownell * To avoid cluttering sysfs (and memory) with useless state, only 48647ad68e2fSDavid Brownell * create attributes that can be meaningfully displayed. 48657ad68e2fSDavid Brownell */ 486639f802d6STakashi Iwai static umode_t regulator_attr_is_visible(struct kobject *kobj, 486739f802d6STakashi Iwai struct attribute *attr, int idx) 48687ad68e2fSDavid Brownell { 486939f802d6STakashi Iwai struct device *dev = kobj_to_dev(kobj); 487083080a14SGeliang Tang struct regulator_dev *rdev = dev_to_rdev(dev); 4871272e2315SGuodong Xu const struct regulator_ops *ops = rdev->desc->ops; 487239f802d6STakashi Iwai umode_t mode = attr->mode; 487339f802d6STakashi Iwai 487439f802d6STakashi Iwai /* these three are always present */ 487539f802d6STakashi Iwai if (attr == &dev_attr_name.attr || 487639f802d6STakashi Iwai attr == &dev_attr_num_users.attr || 487739f802d6STakashi Iwai attr == &dev_attr_type.attr) 487839f802d6STakashi Iwai return mode; 48797ad68e2fSDavid Brownell 48807ad68e2fSDavid Brownell /* some attributes need specific methods to be displayed */ 488139f802d6STakashi Iwai if (attr == &dev_attr_microvolts.attr) { 48824c78899bSMark Brown if ((ops->get_voltage && ops->get_voltage(rdev) >= 0) || 4883f2889e65SMark Brown (ops->get_voltage_sel && ops->get_voltage_sel(rdev) >= 0) || 48845a523605SLaxman Dewangan (ops->list_voltage && ops->list_voltage(rdev, 0) >= 0) || 488539f802d6STakashi Iwai (rdev->desc->fixed_uV && rdev->desc->n_voltages == 1)) 488639f802d6STakashi Iwai return mode; 488739f802d6STakashi Iwai return 0; 4888f59c8f9fSMark Brown } 48897ad68e2fSDavid Brownell 489039f802d6STakashi Iwai if (attr == &dev_attr_microamps.attr) 489139f802d6STakashi Iwai return ops->get_current_limit ? mode : 0; 489239f802d6STakashi Iwai 489339f802d6STakashi Iwai if (attr == &dev_attr_opmode.attr) 489439f802d6STakashi Iwai return ops->get_mode ? mode : 0; 489539f802d6STakashi Iwai 489639f802d6STakashi Iwai if (attr == &dev_attr_state.attr) 489739f802d6STakashi Iwai return (rdev->ena_pin || ops->is_enabled) ? mode : 0; 489839f802d6STakashi Iwai 489939f802d6STakashi Iwai if (attr == &dev_attr_status.attr) 490039f802d6STakashi Iwai return ops->get_status ? mode : 0; 490139f802d6STakashi Iwai 490239f802d6STakashi Iwai if (attr == &dev_attr_bypass.attr) 490339f802d6STakashi Iwai return ops->get_bypass ? mode : 0; 490439f802d6STakashi Iwai 49057ad68e2fSDavid Brownell /* constraints need specific supporting methods */ 490639f802d6STakashi Iwai if (attr == &dev_attr_min_microvolts.attr || 490739f802d6STakashi Iwai attr == &dev_attr_max_microvolts.attr) 490839f802d6STakashi Iwai return (ops->set_voltage || ops->set_voltage_sel) ? mode : 0; 490939f802d6STakashi Iwai 491039f802d6STakashi Iwai if (attr == &dev_attr_min_microamps.attr || 491139f802d6STakashi Iwai attr == &dev_attr_max_microamps.attr) 491239f802d6STakashi Iwai return ops->set_current_limit ? mode : 0; 491339f802d6STakashi Iwai 491439f802d6STakashi Iwai if (attr == &dev_attr_suspend_standby_state.attr || 491539f802d6STakashi Iwai attr == &dev_attr_suspend_mem_state.attr || 491639f802d6STakashi Iwai attr == &dev_attr_suspend_disk_state.attr) 491739f802d6STakashi Iwai return mode; 491839f802d6STakashi Iwai 491939f802d6STakashi Iwai if (attr == &dev_attr_suspend_standby_microvolts.attr || 492039f802d6STakashi Iwai attr == &dev_attr_suspend_mem_microvolts.attr || 492139f802d6STakashi Iwai attr == &dev_attr_suspend_disk_microvolts.attr) 492239f802d6STakashi Iwai return ops->set_suspend_voltage ? mode : 0; 492339f802d6STakashi Iwai 492439f802d6STakashi Iwai if (attr == &dev_attr_suspend_standby_mode.attr || 492539f802d6STakashi Iwai attr == &dev_attr_suspend_mem_mode.attr || 492639f802d6STakashi Iwai attr == &dev_attr_suspend_disk_mode.attr) 492739f802d6STakashi Iwai return ops->set_suspend_mode ? mode : 0; 492839f802d6STakashi Iwai 492939f802d6STakashi Iwai return mode; 49307ad68e2fSDavid Brownell } 49317ad68e2fSDavid Brownell 493239f802d6STakashi Iwai static const struct attribute_group regulator_dev_group = { 493339f802d6STakashi Iwai .attrs = regulator_dev_attrs, 493439f802d6STakashi Iwai .is_visible = regulator_attr_is_visible, 493539f802d6STakashi Iwai }; 49367ad68e2fSDavid Brownell 493739f802d6STakashi Iwai static const struct attribute_group *regulator_dev_groups[] = { 493839f802d6STakashi Iwai ®ulator_dev_group, 493939f802d6STakashi Iwai NULL 494039f802d6STakashi Iwai }; 494139f802d6STakashi Iwai 494239f802d6STakashi Iwai static void regulator_dev_release(struct device *dev) 494339f802d6STakashi Iwai { 494439f802d6STakashi Iwai struct regulator_dev *rdev = dev_get_drvdata(dev); 494529f5f486SMark Brown 494629f5f486SMark Brown kfree(rdev->constraints); 494729f5f486SMark Brown of_node_put(rdev->dev.of_node); 494839f802d6STakashi Iwai kfree(rdev); 49497ad68e2fSDavid Brownell } 49507ad68e2fSDavid Brownell 49511130e5b3SMark Brown static void rdev_init_debugfs(struct regulator_dev *rdev) 49521130e5b3SMark Brown { 4953a9eaa813SGuenter Roeck struct device *parent = rdev->dev.parent; 4954a9eaa813SGuenter Roeck const char *rname = rdev_get_name(rdev); 4955a9eaa813SGuenter Roeck char name[NAME_MAX]; 4956a9eaa813SGuenter Roeck 4957a9eaa813SGuenter Roeck /* Avoid duplicate debugfs directory names */ 4958a9eaa813SGuenter Roeck if (parent && rname == rdev->desc->name) { 4959a9eaa813SGuenter Roeck snprintf(name, sizeof(name), "%s-%s", dev_name(parent), 4960a9eaa813SGuenter Roeck rname); 4961a9eaa813SGuenter Roeck rname = name; 4962a9eaa813SGuenter Roeck } 4963a9eaa813SGuenter Roeck 4964a9eaa813SGuenter Roeck rdev->debugfs = debugfs_create_dir(rname, debugfs_root); 496524751434SStephen Boyd if (!rdev->debugfs) { 49661130e5b3SMark Brown rdev_warn(rdev, "Failed to create debugfs directory\n"); 49671130e5b3SMark Brown return; 49681130e5b3SMark Brown } 49691130e5b3SMark Brown 49701130e5b3SMark Brown debugfs_create_u32("use_count", 0444, rdev->debugfs, 49711130e5b3SMark Brown &rdev->use_count); 49721130e5b3SMark Brown debugfs_create_u32("open_count", 0444, rdev->debugfs, 49731130e5b3SMark Brown &rdev->open_count); 4974f59c8f9fSMark Brown debugfs_create_u32("bypass_count", 0444, rdev->debugfs, 4975f59c8f9fSMark Brown &rdev->bypass_count); 49761130e5b3SMark Brown } 49771130e5b3SMark Brown 49785e3ca2b3SJavier Martinez Canillas static int regulator_register_resolve_supply(struct device *dev, void *data) 49795e3ca2b3SJavier Martinez Canillas { 49807ddede6aSJon Hunter struct regulator_dev *rdev = dev_to_rdev(dev); 49817ddede6aSJon Hunter 49827ddede6aSJon Hunter if (regulator_resolve_supply(rdev)) 49837ddede6aSJon Hunter rdev_dbg(rdev, "unable to resolve supply\n"); 49847ddede6aSJon Hunter 49857ddede6aSJon Hunter return 0; 49865e3ca2b3SJavier Martinez Canillas } 49875e3ca2b3SJavier Martinez Canillas 4988d8ca7d18SDmitry Osipenko int regulator_coupler_register(struct regulator_coupler *coupler) 4989d8ca7d18SDmitry Osipenko { 4990d8ca7d18SDmitry Osipenko mutex_lock(®ulator_list_mutex); 4991d8ca7d18SDmitry Osipenko list_add_tail(&coupler->list, ®ulator_coupler_list); 4992d8ca7d18SDmitry Osipenko mutex_unlock(®ulator_list_mutex); 4993d8ca7d18SDmitry Osipenko 4994d8ca7d18SDmitry Osipenko return 0; 4995d8ca7d18SDmitry Osipenko } 4996d8ca7d18SDmitry Osipenko 4997d8ca7d18SDmitry Osipenko static struct regulator_coupler * 4998d8ca7d18SDmitry Osipenko regulator_find_coupler(struct regulator_dev *rdev) 4999d8ca7d18SDmitry Osipenko { 5000d8ca7d18SDmitry Osipenko struct regulator_coupler *coupler; 5001d8ca7d18SDmitry Osipenko int err; 5002d8ca7d18SDmitry Osipenko 5003d8ca7d18SDmitry Osipenko /* 5004d8ca7d18SDmitry Osipenko * Note that regulators are appended to the list and the generic 5005d8ca7d18SDmitry Osipenko * coupler is registered first, hence it will be attached at last 5006d8ca7d18SDmitry Osipenko * if nobody cared. 5007d8ca7d18SDmitry Osipenko */ 5008d8ca7d18SDmitry Osipenko list_for_each_entry_reverse(coupler, ®ulator_coupler_list, list) { 5009d8ca7d18SDmitry Osipenko err = coupler->attach_regulator(coupler, rdev); 5010d8ca7d18SDmitry Osipenko if (!err) { 5011d8ca7d18SDmitry Osipenko if (!coupler->balance_voltage && 5012d8ca7d18SDmitry Osipenko rdev->coupling_desc.n_coupled > 2) 5013d8ca7d18SDmitry Osipenko goto err_unsupported; 5014d8ca7d18SDmitry Osipenko 5015d8ca7d18SDmitry Osipenko return coupler; 5016d8ca7d18SDmitry Osipenko } 5017d8ca7d18SDmitry Osipenko 5018d8ca7d18SDmitry Osipenko if (err < 0) 5019d8ca7d18SDmitry Osipenko return ERR_PTR(err); 5020d8ca7d18SDmitry Osipenko 5021d8ca7d18SDmitry Osipenko if (err == 1) 5022d8ca7d18SDmitry Osipenko continue; 5023d8ca7d18SDmitry Osipenko 5024d8ca7d18SDmitry Osipenko break; 5025d8ca7d18SDmitry Osipenko } 5026d8ca7d18SDmitry Osipenko 5027d8ca7d18SDmitry Osipenko return ERR_PTR(-EINVAL); 5028d8ca7d18SDmitry Osipenko 5029d8ca7d18SDmitry Osipenko err_unsupported: 5030d8ca7d18SDmitry Osipenko if (coupler->detach_regulator) 5031d8ca7d18SDmitry Osipenko coupler->detach_regulator(coupler, rdev); 5032d8ca7d18SDmitry Osipenko 5033d8ca7d18SDmitry Osipenko rdev_err(rdev, 5034d8ca7d18SDmitry Osipenko "Voltage balancing for multiple regulator couples is unimplemented\n"); 5035d8ca7d18SDmitry Osipenko 5036d8ca7d18SDmitry Osipenko return ERR_PTR(-EPERM); 5037d8ca7d18SDmitry Osipenko } 5038d8ca7d18SDmitry Osipenko 5039f9503385SDmitry Osipenko static void regulator_resolve_coupling(struct regulator_dev *rdev) 5040d3d64537SMaciej Purski { 5041d8ca7d18SDmitry Osipenko struct regulator_coupler *coupler = rdev->coupling_desc.coupler; 5042d3d64537SMaciej Purski struct coupling_desc *c_desc = &rdev->coupling_desc; 5043d3d64537SMaciej Purski int n_coupled = c_desc->n_coupled; 5044d3d64537SMaciej Purski struct regulator_dev *c_rdev; 5045d3d64537SMaciej Purski int i; 5046d3d64537SMaciej Purski 5047d3d64537SMaciej Purski for (i = 1; i < n_coupled; i++) { 5048d3d64537SMaciej Purski /* already resolved */ 5049d3d64537SMaciej Purski if (c_desc->coupled_rdevs[i]) 5050d3d64537SMaciej Purski continue; 5051d3d64537SMaciej Purski 5052d3d64537SMaciej Purski c_rdev = of_parse_coupled_regulator(rdev, i - 1); 5053d3d64537SMaciej Purski 5054f9503385SDmitry Osipenko if (!c_rdev) 5055f9503385SDmitry Osipenko continue; 5056f9503385SDmitry Osipenko 5057d8ca7d18SDmitry Osipenko if (c_rdev->coupling_desc.coupler != coupler) { 5058d8ca7d18SDmitry Osipenko rdev_err(rdev, "coupler mismatch with %s\n", 5059d8ca7d18SDmitry Osipenko rdev_get_name(c_rdev)); 5060d8ca7d18SDmitry Osipenko return; 5061d8ca7d18SDmitry Osipenko } 5062d8ca7d18SDmitry Osipenko 5063d3d64537SMaciej Purski c_desc->coupled_rdevs[i] = c_rdev; 5064d3d64537SMaciej Purski c_desc->n_resolved++; 5065f9503385SDmitry Osipenko 5066f9503385SDmitry Osipenko regulator_resolve_coupling(c_rdev); 5067d3d64537SMaciej Purski } 5068d3d64537SMaciej Purski } 5069d3d64537SMaciej Purski 50706303f3e7SDmitry Osipenko static void regulator_remove_coupling(struct regulator_dev *rdev) 5071d3d64537SMaciej Purski { 5072d8ca7d18SDmitry Osipenko struct regulator_coupler *coupler = rdev->coupling_desc.coupler; 50736303f3e7SDmitry Osipenko struct coupling_desc *__c_desc, *c_desc = &rdev->coupling_desc; 50746303f3e7SDmitry Osipenko struct regulator_dev *__c_rdev, *c_rdev; 50756303f3e7SDmitry Osipenko unsigned int __n_coupled, n_coupled; 50766303f3e7SDmitry Osipenko int i, k; 5077d8ca7d18SDmitry Osipenko int err; 5078d3d64537SMaciej Purski 50796303f3e7SDmitry Osipenko n_coupled = c_desc->n_coupled; 5080d3d64537SMaciej Purski 50816303f3e7SDmitry Osipenko for (i = 1; i < n_coupled; i++) { 50826303f3e7SDmitry Osipenko c_rdev = c_desc->coupled_rdevs[i]; 5083d3d64537SMaciej Purski 50846303f3e7SDmitry Osipenko if (!c_rdev) 50856303f3e7SDmitry Osipenko continue; 50866303f3e7SDmitry Osipenko 50876303f3e7SDmitry Osipenko regulator_lock(c_rdev); 50886303f3e7SDmitry Osipenko 50896303f3e7SDmitry Osipenko __c_desc = &c_rdev->coupling_desc; 50906303f3e7SDmitry Osipenko __n_coupled = __c_desc->n_coupled; 50916303f3e7SDmitry Osipenko 50926303f3e7SDmitry Osipenko for (k = 1; k < __n_coupled; k++) { 50936303f3e7SDmitry Osipenko __c_rdev = __c_desc->coupled_rdevs[k]; 50946303f3e7SDmitry Osipenko 50956303f3e7SDmitry Osipenko if (__c_rdev == rdev) { 50966303f3e7SDmitry Osipenko __c_desc->coupled_rdevs[k] = NULL; 50976303f3e7SDmitry Osipenko __c_desc->n_resolved--; 50986303f3e7SDmitry Osipenko break; 50996303f3e7SDmitry Osipenko } 5100d3d64537SMaciej Purski } 5101d3d64537SMaciej Purski 51026303f3e7SDmitry Osipenko regulator_unlock(c_rdev); 51036303f3e7SDmitry Osipenko 51046303f3e7SDmitry Osipenko c_desc->coupled_rdevs[i] = NULL; 51056303f3e7SDmitry Osipenko c_desc->n_resolved--; 51066303f3e7SDmitry Osipenko } 5107d8ca7d18SDmitry Osipenko 5108d8ca7d18SDmitry Osipenko if (coupler && coupler->detach_regulator) { 5109d8ca7d18SDmitry Osipenko err = coupler->detach_regulator(coupler, rdev); 5110d8ca7d18SDmitry Osipenko if (err) 511161aab5adSMichał Mirosław rdev_err(rdev, "failed to detach from coupler: %pe\n", 511261aab5adSMichał Mirosław ERR_PTR(err)); 5113d8ca7d18SDmitry Osipenko } 5114d8ca7d18SDmitry Osipenko 5115d8ca7d18SDmitry Osipenko kfree(rdev->coupling_desc.coupled_rdevs); 5116d8ca7d18SDmitry Osipenko rdev->coupling_desc.coupled_rdevs = NULL; 51176303f3e7SDmitry Osipenko } 51186303f3e7SDmitry Osipenko 5119f9503385SDmitry Osipenko static int regulator_init_coupling(struct regulator_dev *rdev) 5120d3d64537SMaciej Purski { 51217d819664SMichał Mirosław struct regulator_dev **coupled; 5122d8ca7d18SDmitry Osipenko int err, n_phandles; 5123d3d64537SMaciej Purski 5124d3d64537SMaciej Purski if (!IS_ENABLED(CONFIG_OF)) 5125d3d64537SMaciej Purski n_phandles = 0; 5126d3d64537SMaciej Purski else 5127d3d64537SMaciej Purski n_phandles = of_get_n_coupled(rdev); 5128d3d64537SMaciej Purski 51297d819664SMichał Mirosław coupled = kcalloc(n_phandles + 1, sizeof(*coupled), GFP_KERNEL); 51307d819664SMichał Mirosław if (!coupled) 5131d8ca7d18SDmitry Osipenko return -ENOMEM; 5132d3d64537SMaciej Purski 51337d819664SMichał Mirosław rdev->coupling_desc.coupled_rdevs = coupled; 51347d819664SMichał Mirosław 5135d3d64537SMaciej Purski /* 5136d3d64537SMaciej Purski * Every regulator should always have coupling descriptor filled with 5137d3d64537SMaciej Purski * at least pointer to itself. 5138d3d64537SMaciej Purski */ 5139d3d64537SMaciej Purski rdev->coupling_desc.coupled_rdevs[0] = rdev; 5140d3d64537SMaciej Purski rdev->coupling_desc.n_coupled = n_phandles + 1; 5141d3d64537SMaciej Purski rdev->coupling_desc.n_resolved++; 5142d3d64537SMaciej Purski 5143d3d64537SMaciej Purski /* regulator isn't coupled */ 5144d3d64537SMaciej Purski if (n_phandles == 0) 5145d3d64537SMaciej Purski return 0; 5146d3d64537SMaciej Purski 5147d3d64537SMaciej Purski if (!of_check_coupling_data(rdev)) 5148d3d64537SMaciej Purski return -EPERM; 5149d3d64537SMaciej Purski 515073a32129SMichał Mirosław mutex_lock(®ulator_list_mutex); 5151d8ca7d18SDmitry Osipenko rdev->coupling_desc.coupler = regulator_find_coupler(rdev); 515273a32129SMichał Mirosław mutex_unlock(®ulator_list_mutex); 515373a32129SMichał Mirosław 5154d8ca7d18SDmitry Osipenko if (IS_ERR(rdev->coupling_desc.coupler)) { 5155d8ca7d18SDmitry Osipenko err = PTR_ERR(rdev->coupling_desc.coupler); 515661aab5adSMichał Mirosław rdev_err(rdev, "failed to get coupler: %pe\n", ERR_PTR(err)); 5157d8ca7d18SDmitry Osipenko return err; 5158d8ca7d18SDmitry Osipenko } 5159d8ca7d18SDmitry Osipenko 5160d3d64537SMaciej Purski return 0; 5161d3d64537SMaciej Purski } 5162d3d64537SMaciej Purski 5163d8ca7d18SDmitry Osipenko static int generic_coupler_attach(struct regulator_coupler *coupler, 5164d8ca7d18SDmitry Osipenko struct regulator_dev *rdev) 5165d8ca7d18SDmitry Osipenko { 5166d8ca7d18SDmitry Osipenko if (rdev->coupling_desc.n_coupled > 2) { 5167d8ca7d18SDmitry Osipenko rdev_err(rdev, 5168d8ca7d18SDmitry Osipenko "Voltage balancing for multiple regulator couples is unimplemented\n"); 5169d8ca7d18SDmitry Osipenko return -EPERM; 5170d8ca7d18SDmitry Osipenko } 5171d8ca7d18SDmitry Osipenko 5172e381bfe4SDmitry Osipenko if (!rdev->constraints->always_on) { 5173e381bfe4SDmitry Osipenko rdev_err(rdev, 5174e381bfe4SDmitry Osipenko "Coupling of a non always-on regulator is unimplemented\n"); 5175e381bfe4SDmitry Osipenko return -ENOTSUPP; 5176e381bfe4SDmitry Osipenko } 5177e381bfe4SDmitry Osipenko 5178d8ca7d18SDmitry Osipenko return 0; 5179d8ca7d18SDmitry Osipenko } 5180d8ca7d18SDmitry Osipenko 5181d8ca7d18SDmitry Osipenko static struct regulator_coupler generic_regulator_coupler = { 5182d8ca7d18SDmitry Osipenko .attach_regulator = generic_coupler_attach, 5183d8ca7d18SDmitry Osipenko }; 5184d8ca7d18SDmitry Osipenko 5185414c70cbSLiam Girdwood /** 5186414c70cbSLiam Girdwood * regulator_register - register regulator 518769279fb9SMark Brown * @regulator_desc: regulator to register 5188f47531b1SKrzysztof Kozlowski * @cfg: runtime configuration for regulator 5189414c70cbSLiam Girdwood * 5190414c70cbSLiam Girdwood * Called by regulator drivers to register a regulator. 51910384618aSAxel Lin * Returns a valid pointer to struct regulator_dev on success 51920384618aSAxel Lin * or an ERR_PTR() on error. 5193414c70cbSLiam Girdwood */ 519465f26846SMark Brown struct regulator_dev * 519565f26846SMark Brown regulator_register(const struct regulator_desc *regulator_desc, 51961b3de223SKrzysztof Kozlowski const struct regulator_config *cfg) 5197414c70cbSLiam Girdwood { 5198c172708dSMark Brown const struct regulator_init_data *init_data; 51991b3de223SKrzysztof Kozlowski struct regulator_config *config = NULL; 520072dca06fSAniroop Mathur static atomic_t regulator_no = ATOMIC_INIT(-1); 5201414c70cbSLiam Girdwood struct regulator_dev *rdev; 52020edb040dSLinus Walleij bool dangling_cfg_gpiod = false; 52030edb040dSLinus Walleij bool dangling_of_gpiod = false; 520432c8fad4SMark Brown struct device *dev; 5205a5766f11SLiam Girdwood int ret, i; 5206414c70cbSLiam Girdwood 52070edb040dSLinus Walleij if (cfg == NULL) 5208414c70cbSLiam Girdwood return ERR_PTR(-EINVAL); 52090edb040dSLinus Walleij if (cfg->ena_gpiod) 52100edb040dSLinus Walleij dangling_cfg_gpiod = true; 52110edb040dSLinus Walleij if (regulator_desc == NULL) { 52120edb040dSLinus Walleij ret = -EINVAL; 52130edb040dSLinus Walleij goto rinse; 52140edb040dSLinus Walleij } 5215414c70cbSLiam Girdwood 52161b3de223SKrzysztof Kozlowski dev = cfg->dev; 5217dcf70112SMark Brown WARN_ON(!dev); 521832c8fad4SMark Brown 52190edb040dSLinus Walleij if (regulator_desc->name == NULL || regulator_desc->ops == NULL) { 52200edb040dSLinus Walleij ret = -EINVAL; 52210edb040dSLinus Walleij goto rinse; 52220edb040dSLinus Walleij } 5223414c70cbSLiam Girdwood 5224cd78dfc6SDiego Liziero if (regulator_desc->type != REGULATOR_VOLTAGE && 52250edb040dSLinus Walleij regulator_desc->type != REGULATOR_CURRENT) { 52260edb040dSLinus Walleij ret = -EINVAL; 52270edb040dSLinus Walleij goto rinse; 52280edb040dSLinus Walleij } 5229414c70cbSLiam Girdwood 5230476c2d83SMark Brown /* Only one of each should be implemented */ 5231476c2d83SMark Brown WARN_ON(regulator_desc->ops->get_voltage && 5232476c2d83SMark Brown regulator_desc->ops->get_voltage_sel); 5233e8eef82bSMark Brown WARN_ON(regulator_desc->ops->set_voltage && 5234e8eef82bSMark Brown regulator_desc->ops->set_voltage_sel); 5235476c2d83SMark Brown 5236476c2d83SMark Brown /* If we're using selectors we must implement list_voltage. */ 5237476c2d83SMark Brown if (regulator_desc->ops->get_voltage_sel && 5238476c2d83SMark Brown !regulator_desc->ops->list_voltage) { 52390edb040dSLinus Walleij ret = -EINVAL; 52400edb040dSLinus Walleij goto rinse; 5241476c2d83SMark Brown } 5242e8eef82bSMark Brown if (regulator_desc->ops->set_voltage_sel && 5243e8eef82bSMark Brown !regulator_desc->ops->list_voltage) { 52440edb040dSLinus Walleij ret = -EINVAL; 52450edb040dSLinus Walleij goto rinse; 5246e8eef82bSMark Brown } 5247476c2d83SMark Brown 5248414c70cbSLiam Girdwood rdev = kzalloc(sizeof(struct regulator_dev), GFP_KERNEL); 52490edb040dSLinus Walleij if (rdev == NULL) { 52500edb040dSLinus Walleij ret = -ENOMEM; 52510edb040dSLinus Walleij goto rinse; 52520edb040dSLinus Walleij } 5253d3c73156SMichał Mirosław device_initialize(&rdev->dev); 5254414c70cbSLiam Girdwood 52551b3de223SKrzysztof Kozlowski /* 52561b3de223SKrzysztof Kozlowski * Duplicate the config so the driver could override it after 52571b3de223SKrzysztof Kozlowski * parsing init data. 52581b3de223SKrzysztof Kozlowski */ 52591b3de223SKrzysztof Kozlowski config = kmemdup(cfg, sizeof(*cfg), GFP_KERNEL); 52601b3de223SKrzysztof Kozlowski if (config == NULL) { 52610edb040dSLinus Walleij ret = -ENOMEM; 5262d3c73156SMichał Mirosław goto clean; 52631b3de223SKrzysztof Kozlowski } 52641b3de223SKrzysztof Kozlowski 5265bfa21a0dSKrzysztof Kozlowski init_data = regulator_of_get_init_data(dev, regulator_desc, config, 5266a0c7b164SMark Brown &rdev->dev.of_node); 5267f8970d34SMarco Felsch 5268f8970d34SMarco Felsch /* 5269f8970d34SMarco Felsch * Sometimes not all resources are probed already so we need to take 5270f8970d34SMarco Felsch * that into account. This happens most the time if the ena_gpiod comes 5271f8970d34SMarco Felsch * from a gpio extender or something else. 5272f8970d34SMarco Felsch */ 5273f8970d34SMarco Felsch if (PTR_ERR(init_data) == -EPROBE_DEFER) { 5274f8970d34SMarco Felsch ret = -EPROBE_DEFER; 5275d3c73156SMichał Mirosław goto clean; 5276f8970d34SMarco Felsch } 5277f8970d34SMarco Felsch 52780edb040dSLinus Walleij /* 52790edb040dSLinus Walleij * We need to keep track of any GPIO descriptor coming from the 52800edb040dSLinus Walleij * device tree until we have handled it over to the core. If the 52810edb040dSLinus Walleij * config that was passed in to this function DOES NOT contain 52820edb040dSLinus Walleij * a descriptor, and the config after this call DOES contain 528348f1b4efSKrzysztof Kozlowski * a descriptor, we definitely got one from parsing the device 52840edb040dSLinus Walleij * tree. 52850edb040dSLinus Walleij */ 52860edb040dSLinus Walleij if (!cfg->ena_gpiod && config->ena_gpiod) 52870edb040dSLinus Walleij dangling_of_gpiod = true; 5288a0c7b164SMark Brown if (!init_data) { 5289a0c7b164SMark Brown init_data = config->init_data; 5290a0c7b164SMark Brown rdev->dev.of_node = of_node_get(config->of_node); 5291a0c7b164SMark Brown } 5292a0c7b164SMark Brown 5293f8702f9eSDmitry Osipenko ww_mutex_init(&rdev->mutex, ®ulator_ww_class); 5294c172708dSMark Brown rdev->reg_data = config->driver_data; 5295414c70cbSLiam Girdwood rdev->owner = regulator_desc->owner; 5296414c70cbSLiam Girdwood rdev->desc = regulator_desc; 52973a4b0a07SMark Brown if (config->regmap) 529865b19ce6SMark Brown rdev->regmap = config->regmap; 529952b84dacSAnilKumar Ch else if (dev_get_regmap(dev, NULL)) 53003a4b0a07SMark Brown rdev->regmap = dev_get_regmap(dev, NULL); 530152b84dacSAnilKumar Ch else if (dev->parent) 530252b84dacSAnilKumar Ch rdev->regmap = dev_get_regmap(dev->parent, NULL); 5303414c70cbSLiam Girdwood INIT_LIST_HEAD(&rdev->consumer_list); 5304414c70cbSLiam Girdwood INIT_LIST_HEAD(&rdev->list); 5305414c70cbSLiam Girdwood BLOCKING_INIT_NOTIFIER_HEAD(&rdev->notifier); 5306da07ecd9SMark Brown INIT_DELAYED_WORK(&rdev->disable_work, regulator_disable_work); 5307414c70cbSLiam Girdwood 5308a5766f11SLiam Girdwood /* preform any regulator specific init */ 53099a8f5e07SMark Brown if (init_data && init_data->regulator_init) { 5310a5766f11SLiam Girdwood ret = init_data->regulator_init(rdev->reg_data); 53114fca9545SDavid Brownell if (ret < 0) 53124fca9545SDavid Brownell goto clean; 5313a5766f11SLiam Girdwood } 5314a5766f11SLiam Girdwood 5315541d052dSLinus Walleij if (config->ena_gpiod) { 5316daad134dSKrzysztof Adamski ret = regulator_ena_gpio_request(rdev, config); 5317daad134dSKrzysztof Adamski if (ret != 0) { 531861aab5adSMichał Mirosław rdev_err(rdev, "Failed to request enable GPIO: %pe\n", 531961aab5adSMichał Mirosław ERR_PTR(ret)); 532032165230SKrzysztof Adamski goto clean; 5321daad134dSKrzysztof Adamski } 53220edb040dSLinus Walleij /* The regulator core took over the GPIO descriptor */ 53230edb040dSLinus Walleij dangling_cfg_gpiod = false; 53240edb040dSLinus Walleij dangling_of_gpiod = false; 5325daad134dSKrzysztof Adamski } 5326daad134dSKrzysztof Adamski 5327a5766f11SLiam Girdwood /* register with sysfs */ 5328a5766f11SLiam Girdwood rdev->dev.class = ®ulator_class; 5329a5766f11SLiam Girdwood rdev->dev.parent = dev; 533072dca06fSAniroop Mathur dev_set_name(&rdev->dev, "regulator.%lu", 533139138818SAniroop Mathur (unsigned long) atomic_inc_return(®ulator_no)); 53329177514cSVladimir Zapolskiy dev_set_drvdata(&rdev->dev, rdev); 5333a5766f11SLiam Girdwood 533474f544c1SMike Rapoport /* set regulator constraints */ 53359a8f5e07SMark Brown if (init_data) 533657a6ad48SMichał Mirosław rdev->constraints = kmemdup(&init_data->constraints, 533757a6ad48SMichał Mirosław sizeof(*rdev->constraints), 533857a6ad48SMichał Mirosław GFP_KERNEL); 533957a6ad48SMichał Mirosław else 534057a6ad48SMichał Mirosław rdev->constraints = kzalloc(sizeof(*rdev->constraints), 534157a6ad48SMichał Mirosław GFP_KERNEL); 534257a6ad48SMichał Mirosław if (!rdev->constraints) { 534357a6ad48SMichał Mirosław ret = -ENOMEM; 534457a6ad48SMichał Mirosław goto wash; 534557a6ad48SMichał Mirosław } 53469a8f5e07SMark Brown 53479a8f5e07SMark Brown if (init_data && init_data->supply_regulator) 53486261b06dSBjorn Andersson rdev->supply_name = init_data->supply_regulator; 534969511a45SRajendra Nayak else if (regulator_desc->supply_name) 53506261b06dSBjorn Andersson rdev->supply_name = regulator_desc->supply_name; 535169511a45SRajendra Nayak 535257a6ad48SMichał Mirosław ret = set_machine_constraints(rdev); 5353aea6cb99SMichał Mirosław if (ret == -EPROBE_DEFER) { 5354aea6cb99SMichał Mirosław /* Regulator might be in bypass mode and so needs its supply 535569b8821eSShubhankar Kuranagatti * to set the constraints 535669b8821eSShubhankar Kuranagatti */ 5357aea6cb99SMichał Mirosław /* FIXME: this currently triggers a chicken-and-egg problem 5358aea6cb99SMichał Mirosław * when creating -SUPPLY symlink in sysfs to a regulator 535969b8821eSShubhankar Kuranagatti * that is just being created 536069b8821eSShubhankar Kuranagatti */ 53610917c9dbSMichał Mirosław rdev_dbg(rdev, "will resolve supply early: %s\n", 53620917c9dbSMichał Mirosław rdev->supply_name); 5363aea6cb99SMichał Mirosław ret = regulator_resolve_supply(rdev); 5364aea6cb99SMichał Mirosław if (!ret) 536557a6ad48SMichał Mirosław ret = set_machine_constraints(rdev); 5366aea6cb99SMichał Mirosław else 5367aea6cb99SMichał Mirosław rdev_dbg(rdev, "unable to resolve supply early: %pe\n", 5368aea6cb99SMichał Mirosław ERR_PTR(ret)); 5369aea6cb99SMichał Mirosław } 537045389c47SJon Hunter if (ret < 0) 537145389c47SJon Hunter goto wash; 537245389c47SJon Hunter 5373f9503385SDmitry Osipenko ret = regulator_init_coupling(rdev); 5374f9503385SDmitry Osipenko if (ret < 0) 5375d3d64537SMaciej Purski goto wash; 5376d3d64537SMaciej Purski 5377a5766f11SLiam Girdwood /* add consumers devices */ 53789a8f5e07SMark Brown if (init_data) { 5379a5766f11SLiam Girdwood for (i = 0; i < init_data->num_consumer_supplies; i++) { 5380a5766f11SLiam Girdwood ret = set_consumer_device_supply(rdev, 538140f9244fSMark Brown init_data->consumer_supplies[i].dev_name, 5382a5766f11SLiam Girdwood init_data->consumer_supplies[i].supply); 538323c2f041SMark Brown if (ret < 0) { 538423c2f041SMark Brown dev_err(dev, "Failed to set supply %s\n", 538523c2f041SMark Brown init_data->consumer_supplies[i].supply); 5386d4033b54SJani Nikula goto unset_supplies; 5387a5766f11SLiam Girdwood } 538823c2f041SMark Brown } 53899a8f5e07SMark Brown } 5390a5766f11SLiam Girdwood 5391fd086045SMatthias Kaehlcke if (!rdev->desc->ops->get_voltage && 5392fd086045SMatthias Kaehlcke !rdev->desc->ops->list_voltage && 5393fd086045SMatthias Kaehlcke !rdev->desc->fixed_uV) 5394fd086045SMatthias Kaehlcke rdev->is_switch = true; 5395fd086045SMatthias Kaehlcke 53969177514cSVladimir Zapolskiy ret = device_add(&rdev->dev); 53979177514cSVladimir Zapolskiy if (ret != 0) 5398c438b9d0SJon Hunter goto unset_supplies; 5399c438b9d0SJon Hunter 54001130e5b3SMark Brown rdev_init_debugfs(rdev); 54015e3ca2b3SJavier Martinez Canillas 5402f9503385SDmitry Osipenko /* try to resolve regulators coupling since a new one was registered */ 5403f9503385SDmitry Osipenko mutex_lock(®ulator_list_mutex); 5404f9503385SDmitry Osipenko regulator_resolve_coupling(rdev); 5405f9503385SDmitry Osipenko mutex_unlock(®ulator_list_mutex); 5406f9503385SDmitry Osipenko 54075e3ca2b3SJavier Martinez Canillas /* try to resolve regulators supply since a new one was registered */ 54085e3ca2b3SJavier Martinez Canillas class_for_each_device(®ulator_class, NULL, NULL, 54095e3ca2b3SJavier Martinez Canillas regulator_register_resolve_supply); 54101b3de223SKrzysztof Kozlowski kfree(config); 5411414c70cbSLiam Girdwood return rdev; 54124fca9545SDavid Brownell 5413d4033b54SJani Nikula unset_supplies: 541445389c47SJon Hunter mutex_lock(®ulator_list_mutex); 5415d4033b54SJani Nikula unset_regulator_supplies(rdev); 5416d8ca7d18SDmitry Osipenko regulator_remove_coupling(rdev); 541745389c47SJon Hunter mutex_unlock(®ulator_list_mutex); 541832165230SKrzysztof Adamski wash: 541926c2c997SDmitry Osipenko kfree(rdev->coupling_desc.coupled_rdevs); 542045389c47SJon Hunter mutex_lock(®ulator_list_mutex); 542132165230SKrzysztof Adamski regulator_ena_gpio_free(rdev); 542245389c47SJon Hunter mutex_unlock(®ulator_list_mutex); 54234fca9545SDavid Brownell clean: 54240edb040dSLinus Walleij if (dangling_of_gpiod) 54250edb040dSLinus Walleij gpiod_put(config->ena_gpiod); 5426a2151374SJon Hunter kfree(config); 5427d3c73156SMichał Mirosław put_device(&rdev->dev); 54280edb040dSLinus Walleij rinse: 54290edb040dSLinus Walleij if (dangling_cfg_gpiod) 54300edb040dSLinus Walleij gpiod_put(cfg->ena_gpiod); 5431a2151374SJon Hunter return ERR_PTR(ret); 5432414c70cbSLiam Girdwood } 5433414c70cbSLiam Girdwood EXPORT_SYMBOL_GPL(regulator_register); 5434414c70cbSLiam Girdwood 5435414c70cbSLiam Girdwood /** 5436414c70cbSLiam Girdwood * regulator_unregister - unregister regulator 543769279fb9SMark Brown * @rdev: regulator to unregister 5438414c70cbSLiam Girdwood * 5439414c70cbSLiam Girdwood * Called by regulator drivers to unregister a regulator. 5440414c70cbSLiam Girdwood */ 5441414c70cbSLiam Girdwood void regulator_unregister(struct regulator_dev *rdev) 5442414c70cbSLiam Girdwood { 5443414c70cbSLiam Girdwood if (rdev == NULL) 5444414c70cbSLiam Girdwood return; 5445414c70cbSLiam Girdwood 5446891636eaSMark Brown if (rdev->supply) { 5447891636eaSMark Brown while (rdev->use_count--) 5448891636eaSMark Brown regulator_disable(rdev->supply); 5449e032b376SMark Brown regulator_put(rdev->supply); 5450891636eaSMark Brown } 5451ff9b34b6SDmitry Osipenko 545206377301SCharles Keepax flush_work(&rdev->disable_work.work); 545306377301SCharles Keepax 5454414c70cbSLiam Girdwood mutex_lock(®ulator_list_mutex); 5455ff9b34b6SDmitry Osipenko 54561130e5b3SMark Brown debugfs_remove_recursive(rdev->debugfs); 54576bf87d17SMark Brown WARN_ON(rdev->open_count); 54586303f3e7SDmitry Osipenko regulator_remove_coupling(rdev); 54590f1d747bSMike Rapoport unset_regulator_supplies(rdev); 5460414c70cbSLiam Girdwood list_del(&rdev->list); 5461f19b00daSKim, Milo regulator_ena_gpio_free(rdev); 546258fb5cf5SLothar Waßmann device_unregister(&rdev->dev); 5463ff9b34b6SDmitry Osipenko 5464ff9b34b6SDmitry Osipenko mutex_unlock(®ulator_list_mutex); 5465414c70cbSLiam Girdwood } 5466414c70cbSLiam Girdwood EXPORT_SYMBOL_GPL(regulator_unregister); 5467414c70cbSLiam Girdwood 5468f7efad10SChunyan Zhang #ifdef CONFIG_SUSPEND 5469414c70cbSLiam Girdwood /** 54700380cf7dSpascal paillet * regulator_suspend - prepare regulators for system wide suspend 54711efef7ccSRandy Dunlap * @dev: ``&struct device`` pointer that is passed to _regulator_suspend() 5472414c70cbSLiam Girdwood * 5473414c70cbSLiam Girdwood * Configure each regulator with it's suspend operating parameters for state. 5474414c70cbSLiam Girdwood */ 54750380cf7dSpascal paillet static int regulator_suspend(struct device *dev) 5476414c70cbSLiam Girdwood { 5477cd7e36abSMarek Szyprowski struct regulator_dev *rdev = dev_to_rdev(dev); 5478f7efad10SChunyan Zhang suspend_state_t state = pm_suspend_target_state; 5479cd7e36abSMarek Szyprowski int ret; 54800955f5beSStephen Boyd const struct regulator_state *rstate; 54810955f5beSStephen Boyd 54820955f5beSStephen Boyd rstate = regulator_get_suspend_state_check(rdev, state); 54830955f5beSStephen Boyd if (!rstate) 54840955f5beSStephen Boyd return 0; 5485414c70cbSLiam Girdwood 5486cd7e36abSMarek Szyprowski regulator_lock(rdev); 54870955f5beSStephen Boyd ret = __suspend_set_state(rdev, rstate); 5488cd7e36abSMarek Szyprowski regulator_unlock(rdev); 5489cd7e36abSMarek Szyprowski 5490cd7e36abSMarek Szyprowski return ret; 5491414c70cbSLiam Girdwood } 5492d3e4eccbSMark Brown 5493cd7e36abSMarek Szyprowski static int regulator_resume(struct device *dev) 549485f3b431STomeu Vizoso { 5495cd7e36abSMarek Szyprowski suspend_state_t state = pm_suspend_target_state; 549685f3b431STomeu Vizoso struct regulator_dev *rdev = dev_to_rdev(dev); 5497f7efad10SChunyan Zhang struct regulator_state *rstate; 5498cd7e36abSMarek Szyprowski int ret = 0; 5499f7efad10SChunyan Zhang 5500cd7e36abSMarek Szyprowski rstate = regulator_get_suspend_state(rdev, state); 5501f7efad10SChunyan Zhang if (rstate == NULL) 550235b5f14eSGeert Uytterhoeven return 0; 550385f3b431STomeu Vizoso 55040955f5beSStephen Boyd /* Avoid grabbing the lock if we don't need to */ 55050955f5beSStephen Boyd if (!rdev->desc->ops->resume) 55060955f5beSStephen Boyd return 0; 55070955f5beSStephen Boyd 550866cf9a7eSMaciej Purski regulator_lock(rdev); 550985f3b431STomeu Vizoso 55100955f5beSStephen Boyd if (rstate->enabled == ENABLE_IN_SUSPEND || 55110955f5beSStephen Boyd rstate->enabled == DISABLE_IN_SUSPEND) 55120380cf7dSpascal paillet ret = rdev->desc->ops->resume(rdev); 5513f7efad10SChunyan Zhang 551466cf9a7eSMaciej Purski regulator_unlock(rdev); 551585f3b431STomeu Vizoso 5516f7efad10SChunyan Zhang return ret; 551785f3b431STomeu Vizoso } 5518f7efad10SChunyan Zhang #else /* !CONFIG_SUSPEND */ 5519f7efad10SChunyan Zhang 55200380cf7dSpascal paillet #define regulator_suspend NULL 55210380cf7dSpascal paillet #define regulator_resume NULL 5522f7efad10SChunyan Zhang 5523f7efad10SChunyan Zhang #endif /* !CONFIG_SUSPEND */ 5524f7efad10SChunyan Zhang 5525f7efad10SChunyan Zhang #ifdef CONFIG_PM 5526f7efad10SChunyan Zhang static const struct dev_pm_ops __maybe_unused regulator_pm_ops = { 55270380cf7dSpascal paillet .suspend = regulator_suspend, 55280380cf7dSpascal paillet .resume = regulator_resume, 5529f7efad10SChunyan Zhang }; 5530f7efad10SChunyan Zhang #endif 5531f7efad10SChunyan Zhang 5532285c22deSMark Brown struct class regulator_class = { 5533f7efad10SChunyan Zhang .name = "regulator", 5534f7efad10SChunyan Zhang .dev_release = regulator_dev_release, 5535f7efad10SChunyan Zhang .dev_groups = regulator_dev_groups, 5536f7efad10SChunyan Zhang #ifdef CONFIG_PM 5537f7efad10SChunyan Zhang .pm = ®ulator_pm_ops, 5538f7efad10SChunyan Zhang #endif 5539f7efad10SChunyan Zhang }; 55407a32b589SMyungJoo Ham /** 5541ca725561SMark Brown * regulator_has_full_constraints - the system has fully specified constraints 5542ca725561SMark Brown * 5543ca725561SMark Brown * Calling this function will cause the regulator API to disable all 5544ca725561SMark Brown * regulators which have a zero use count and don't have an always_on 5545ca725561SMark Brown * constraint in a late_initcall. 5546ca725561SMark Brown * 5547ca725561SMark Brown * The intention is that this will become the default behaviour in a 5548ca725561SMark Brown * future kernel release so users are encouraged to use this facility 5549ca725561SMark Brown * now. 5550ca725561SMark Brown */ 5551ca725561SMark Brown void regulator_has_full_constraints(void) 5552ca725561SMark Brown { 5553ca725561SMark Brown has_full_constraints = 1; 5554ca725561SMark Brown } 5555ca725561SMark Brown EXPORT_SYMBOL_GPL(regulator_has_full_constraints); 5556ca725561SMark Brown 5557ca725561SMark Brown /** 5558414c70cbSLiam Girdwood * rdev_get_drvdata - get rdev regulator driver data 555969279fb9SMark Brown * @rdev: regulator 5560414c70cbSLiam Girdwood * 5561414c70cbSLiam Girdwood * Get rdev regulator driver private data. This call can be used in the 5562414c70cbSLiam Girdwood * regulator driver context. 5563414c70cbSLiam Girdwood */ 5564414c70cbSLiam Girdwood void *rdev_get_drvdata(struct regulator_dev *rdev) 5565414c70cbSLiam Girdwood { 5566414c70cbSLiam Girdwood return rdev->reg_data; 5567414c70cbSLiam Girdwood } 5568414c70cbSLiam Girdwood EXPORT_SYMBOL_GPL(rdev_get_drvdata); 5569414c70cbSLiam Girdwood 5570414c70cbSLiam Girdwood /** 5571414c70cbSLiam Girdwood * regulator_get_drvdata - get regulator driver data 5572414c70cbSLiam Girdwood * @regulator: regulator 5573414c70cbSLiam Girdwood * 5574414c70cbSLiam Girdwood * Get regulator driver private data. This call can be used in the consumer 5575414c70cbSLiam Girdwood * driver context when non API regulator specific functions need to be called. 5576414c70cbSLiam Girdwood */ 5577414c70cbSLiam Girdwood void *regulator_get_drvdata(struct regulator *regulator) 5578414c70cbSLiam Girdwood { 5579414c70cbSLiam Girdwood return regulator->rdev->reg_data; 5580414c70cbSLiam Girdwood } 5581414c70cbSLiam Girdwood EXPORT_SYMBOL_GPL(regulator_get_drvdata); 5582414c70cbSLiam Girdwood 5583414c70cbSLiam Girdwood /** 5584414c70cbSLiam Girdwood * regulator_set_drvdata - set regulator driver data 5585414c70cbSLiam Girdwood * @regulator: regulator 5586414c70cbSLiam Girdwood * @data: data 5587414c70cbSLiam Girdwood */ 5588414c70cbSLiam Girdwood void regulator_set_drvdata(struct regulator *regulator, void *data) 5589414c70cbSLiam Girdwood { 5590414c70cbSLiam Girdwood regulator->rdev->reg_data = data; 5591414c70cbSLiam Girdwood } 5592414c70cbSLiam Girdwood EXPORT_SYMBOL_GPL(regulator_set_drvdata); 5593414c70cbSLiam Girdwood 5594414c70cbSLiam Girdwood /** 5595d73e873bSMauro Carvalho Chehab * rdev_get_id - get regulator ID 559669279fb9SMark Brown * @rdev: regulator 5597414c70cbSLiam Girdwood */ 5598414c70cbSLiam Girdwood int rdev_get_id(struct regulator_dev *rdev) 5599414c70cbSLiam Girdwood { 5600414c70cbSLiam Girdwood return rdev->desc->id; 5601414c70cbSLiam Girdwood } 5602414c70cbSLiam Girdwood EXPORT_SYMBOL_GPL(rdev_get_id); 5603414c70cbSLiam Girdwood 5604a5766f11SLiam Girdwood struct device *rdev_get_dev(struct regulator_dev *rdev) 5605a5766f11SLiam Girdwood { 5606a5766f11SLiam Girdwood return &rdev->dev; 5607a5766f11SLiam Girdwood } 5608a5766f11SLiam Girdwood EXPORT_SYMBOL_GPL(rdev_get_dev); 5609a5766f11SLiam Girdwood 561003c87b95SBartosz Golaszewski struct regmap *rdev_get_regmap(struct regulator_dev *rdev) 561103c87b95SBartosz Golaszewski { 561203c87b95SBartosz Golaszewski return rdev->regmap; 561303c87b95SBartosz Golaszewski } 561403c87b95SBartosz Golaszewski EXPORT_SYMBOL_GPL(rdev_get_regmap); 561503c87b95SBartosz Golaszewski 5616a5766f11SLiam Girdwood void *regulator_get_init_drvdata(struct regulator_init_data *reg_init_data) 5617a5766f11SLiam Girdwood { 5618a5766f11SLiam Girdwood return reg_init_data->driver_data; 5619a5766f11SLiam Girdwood } 5620a5766f11SLiam Girdwood EXPORT_SYMBOL_GPL(regulator_get_init_drvdata); 5621a5766f11SLiam Girdwood 5622ba55a974SMark Brown #ifdef CONFIG_DEBUG_FS 5623dbc55955SHaishan Zhou static int supply_map_show(struct seq_file *sf, void *data) 5624ba55a974SMark Brown { 5625ba55a974SMark Brown struct regulator_map *map; 5626ba55a974SMark Brown 5627ba55a974SMark Brown list_for_each_entry(map, ®ulator_map_list, list) { 5628dbc55955SHaishan Zhou seq_printf(sf, "%s -> %s.%s\n", 5629ba55a974SMark Brown rdev_get_name(map->regulator), map->dev_name, 5630ba55a974SMark Brown map->supply); 5631ba55a974SMark Brown } 5632ba55a974SMark Brown 5633dbc55955SHaishan Zhou return 0; 5634dbc55955SHaishan Zhou } 56353e60b4fcSYangtao Li DEFINE_SHOW_ATTRIBUTE(supply_map); 5636ba55a974SMark Brown 563785f3b431STomeu Vizoso struct summary_data { 563885f3b431STomeu Vizoso struct seq_file *s; 563985f3b431STomeu Vizoso struct regulator_dev *parent; 564085f3b431STomeu Vizoso int level; 564185f3b431STomeu Vizoso }; 564285f3b431STomeu Vizoso 564385f3b431STomeu Vizoso static void regulator_summary_show_subtree(struct seq_file *s, 564485f3b431STomeu Vizoso struct regulator_dev *rdev, 564585f3b431STomeu Vizoso int level); 564685f3b431STomeu Vizoso 564785f3b431STomeu Vizoso static int regulator_summary_show_children(struct device *dev, void *data) 564885f3b431STomeu Vizoso { 564985f3b431STomeu Vizoso struct regulator_dev *rdev = dev_to_rdev(dev); 565085f3b431STomeu Vizoso struct summary_data *summary_data = data; 565185f3b431STomeu Vizoso 565285f3b431STomeu Vizoso if (rdev->supply && rdev->supply->rdev == summary_data->parent) 565385f3b431STomeu Vizoso regulator_summary_show_subtree(summary_data->s, rdev, 565485f3b431STomeu Vizoso summary_data->level + 1); 565585f3b431STomeu Vizoso 565685f3b431STomeu Vizoso return 0; 565785f3b431STomeu Vizoso } 565885f3b431STomeu Vizoso 56597c225ec9SHeiko Stübner static void regulator_summary_show_subtree(struct seq_file *s, 56607c225ec9SHeiko Stübner struct regulator_dev *rdev, 56617c225ec9SHeiko Stübner int level) 56627c225ec9SHeiko Stübner { 56637c225ec9SHeiko Stübner struct regulation_constraints *c; 56647c225ec9SHeiko Stübner struct regulator *consumer; 566585f3b431STomeu Vizoso struct summary_data summary_data; 56667e4d9683SDouglas Anderson unsigned int opmode; 56677c225ec9SHeiko Stübner 56687c225ec9SHeiko Stübner if (!rdev) 56697c225ec9SHeiko Stübner return; 56707c225ec9SHeiko Stübner 56717e4d9683SDouglas Anderson opmode = _regulator_get_mode_unlocked(rdev); 567201de19d0SDouglas Anderson seq_printf(s, "%*s%-*s %3d %4d %6d %7s ", 56737c225ec9SHeiko Stübner level * 3 + 1, "", 56747c225ec9SHeiko Stübner 30 - level * 3, rdev_get_name(rdev), 567501de19d0SDouglas Anderson rdev->use_count, rdev->open_count, rdev->bypass_count, 56767e4d9683SDouglas Anderson regulator_opmode_to_str(opmode)); 56777c225ec9SHeiko Stübner 5678d22b85a1SDmitry Osipenko seq_printf(s, "%5dmV ", regulator_get_voltage_rdev(rdev) / 1000); 56797e4d9683SDouglas Anderson seq_printf(s, "%5dmA ", 56807e4d9683SDouglas Anderson _regulator_get_current_limit_unlocked(rdev) / 1000); 56817c225ec9SHeiko Stübner 56827c225ec9SHeiko Stübner c = rdev->constraints; 56837c225ec9SHeiko Stübner if (c) { 56847c225ec9SHeiko Stübner switch (rdev->desc->type) { 56857c225ec9SHeiko Stübner case REGULATOR_VOLTAGE: 56867c225ec9SHeiko Stübner seq_printf(s, "%5dmV %5dmV ", 56877c225ec9SHeiko Stübner c->min_uV / 1000, c->max_uV / 1000); 56887c225ec9SHeiko Stübner break; 56897c225ec9SHeiko Stübner case REGULATOR_CURRENT: 56907c225ec9SHeiko Stübner seq_printf(s, "%5dmA %5dmA ", 56917c225ec9SHeiko Stübner c->min_uA / 1000, c->max_uA / 1000); 56927c225ec9SHeiko Stübner break; 56937c225ec9SHeiko Stübner } 56947c225ec9SHeiko Stübner } 56957c225ec9SHeiko Stübner 56967c225ec9SHeiko Stübner seq_puts(s, "\n"); 56977c225ec9SHeiko Stübner 56987c225ec9SHeiko Stübner list_for_each_entry(consumer, &rdev->consumer_list, list) { 5699e42a46b6SLeonard Crestez if (consumer->dev && consumer->dev->class == ®ulator_class) 57007c225ec9SHeiko Stübner continue; 57017c225ec9SHeiko Stübner 57027c225ec9SHeiko Stübner seq_printf(s, "%*s%-*s ", 57037c225ec9SHeiko Stübner (level + 1) * 3 + 1, "", 5704e42a46b6SLeonard Crestez 30 - (level + 1) * 3, 57056b576eb0SMichał Mirosław consumer->supply_name ? consumer->supply_name : 5706e42a46b6SLeonard Crestez consumer->dev ? dev_name(consumer->dev) : "deviceless"); 57077c225ec9SHeiko Stübner 57087c225ec9SHeiko Stübner switch (rdev->desc->type) { 57097c225ec9SHeiko Stübner case REGULATOR_VOLTAGE: 57105451781dSDouglas Anderson seq_printf(s, "%3d %33dmA%c%5dmV %5dmV", 57115451781dSDouglas Anderson consumer->enable_count, 57127d3827b5SDouglas Anderson consumer->uA_load / 1000, 57135451781dSDouglas Anderson consumer->uA_load && !consumer->enable_count ? 57145451781dSDouglas Anderson '*' : ' ', 5715c360a6dfSChunyan Zhang consumer->voltage[PM_SUSPEND_ON].min_uV / 1000, 5716c360a6dfSChunyan Zhang consumer->voltage[PM_SUSPEND_ON].max_uV / 1000); 57177c225ec9SHeiko Stübner break; 57187c225ec9SHeiko Stübner case REGULATOR_CURRENT: 57197c225ec9SHeiko Stübner break; 57207c225ec9SHeiko Stübner } 57217c225ec9SHeiko Stübner 57227c225ec9SHeiko Stübner seq_puts(s, "\n"); 57237c225ec9SHeiko Stübner } 57247c225ec9SHeiko Stübner 572585f3b431STomeu Vizoso summary_data.s = s; 572685f3b431STomeu Vizoso summary_data.level = level; 572785f3b431STomeu Vizoso summary_data.parent = rdev; 57287c225ec9SHeiko Stübner 572985f3b431STomeu Vizoso class_for_each_device(®ulator_class, NULL, &summary_data, 573085f3b431STomeu Vizoso regulator_summary_show_children); 5731f8702f9eSDmitry Osipenko } 5732f8702f9eSDmitry Osipenko 5733f8702f9eSDmitry Osipenko struct summary_lock_data { 5734f8702f9eSDmitry Osipenko struct ww_acquire_ctx *ww_ctx; 5735f8702f9eSDmitry Osipenko struct regulator_dev **new_contended_rdev; 5736f8702f9eSDmitry Osipenko struct regulator_dev **old_contended_rdev; 5737f8702f9eSDmitry Osipenko }; 5738f8702f9eSDmitry Osipenko 5739f8702f9eSDmitry Osipenko static int regulator_summary_lock_one(struct device *dev, void *data) 5740f8702f9eSDmitry Osipenko { 5741f8702f9eSDmitry Osipenko struct regulator_dev *rdev = dev_to_rdev(dev); 5742f8702f9eSDmitry Osipenko struct summary_lock_data *lock_data = data; 5743f8702f9eSDmitry Osipenko int ret = 0; 5744f8702f9eSDmitry Osipenko 5745f8702f9eSDmitry Osipenko if (rdev != *lock_data->old_contended_rdev) { 5746f8702f9eSDmitry Osipenko ret = regulator_lock_nested(rdev, lock_data->ww_ctx); 5747f8702f9eSDmitry Osipenko 5748f8702f9eSDmitry Osipenko if (ret == -EDEADLK) 5749f8702f9eSDmitry Osipenko *lock_data->new_contended_rdev = rdev; 5750f8702f9eSDmitry Osipenko else 5751f8702f9eSDmitry Osipenko WARN_ON_ONCE(ret); 5752f8702f9eSDmitry Osipenko } else { 5753f8702f9eSDmitry Osipenko *lock_data->old_contended_rdev = NULL; 5754f8702f9eSDmitry Osipenko } 5755f8702f9eSDmitry Osipenko 5756f8702f9eSDmitry Osipenko return ret; 5757f8702f9eSDmitry Osipenko } 5758f8702f9eSDmitry Osipenko 5759f8702f9eSDmitry Osipenko static int regulator_summary_unlock_one(struct device *dev, void *data) 5760f8702f9eSDmitry Osipenko { 5761f8702f9eSDmitry Osipenko struct regulator_dev *rdev = dev_to_rdev(dev); 5762f8702f9eSDmitry Osipenko struct summary_lock_data *lock_data = data; 5763f8702f9eSDmitry Osipenko 5764f8702f9eSDmitry Osipenko if (lock_data) { 5765f8702f9eSDmitry Osipenko if (rdev == *lock_data->new_contended_rdev) 5766f8702f9eSDmitry Osipenko return -EDEADLK; 5767f8702f9eSDmitry Osipenko } 57687e4d9683SDouglas Anderson 57697e4d9683SDouglas Anderson regulator_unlock(rdev); 5770f8702f9eSDmitry Osipenko 5771f8702f9eSDmitry Osipenko return 0; 5772f8702f9eSDmitry Osipenko } 5773f8702f9eSDmitry Osipenko 5774f8702f9eSDmitry Osipenko static int regulator_summary_lock_all(struct ww_acquire_ctx *ww_ctx, 5775f8702f9eSDmitry Osipenko struct regulator_dev **new_contended_rdev, 5776f8702f9eSDmitry Osipenko struct regulator_dev **old_contended_rdev) 5777f8702f9eSDmitry Osipenko { 5778f8702f9eSDmitry Osipenko struct summary_lock_data lock_data; 5779f8702f9eSDmitry Osipenko int ret; 5780f8702f9eSDmitry Osipenko 5781f8702f9eSDmitry Osipenko lock_data.ww_ctx = ww_ctx; 5782f8702f9eSDmitry Osipenko lock_data.new_contended_rdev = new_contended_rdev; 5783f8702f9eSDmitry Osipenko lock_data.old_contended_rdev = old_contended_rdev; 5784f8702f9eSDmitry Osipenko 5785f8702f9eSDmitry Osipenko ret = class_for_each_device(®ulator_class, NULL, &lock_data, 5786f8702f9eSDmitry Osipenko regulator_summary_lock_one); 5787f8702f9eSDmitry Osipenko if (ret) 5788f8702f9eSDmitry Osipenko class_for_each_device(®ulator_class, NULL, &lock_data, 5789f8702f9eSDmitry Osipenko regulator_summary_unlock_one); 5790f8702f9eSDmitry Osipenko 5791f8702f9eSDmitry Osipenko return ret; 5792f8702f9eSDmitry Osipenko } 5793f8702f9eSDmitry Osipenko 5794f8702f9eSDmitry Osipenko static void regulator_summary_lock(struct ww_acquire_ctx *ww_ctx) 5795f8702f9eSDmitry Osipenko { 5796f8702f9eSDmitry Osipenko struct regulator_dev *new_contended_rdev = NULL; 5797f8702f9eSDmitry Osipenko struct regulator_dev *old_contended_rdev = NULL; 5798f8702f9eSDmitry Osipenko int err; 5799f8702f9eSDmitry Osipenko 5800ff9b34b6SDmitry Osipenko mutex_lock(®ulator_list_mutex); 5801ff9b34b6SDmitry Osipenko 5802f8702f9eSDmitry Osipenko ww_acquire_init(ww_ctx, ®ulator_ww_class); 5803f8702f9eSDmitry Osipenko 5804f8702f9eSDmitry Osipenko do { 5805f8702f9eSDmitry Osipenko if (new_contended_rdev) { 5806f8702f9eSDmitry Osipenko ww_mutex_lock_slow(&new_contended_rdev->mutex, ww_ctx); 5807f8702f9eSDmitry Osipenko old_contended_rdev = new_contended_rdev; 5808f8702f9eSDmitry Osipenko old_contended_rdev->ref_cnt++; 5809f8702f9eSDmitry Osipenko } 5810f8702f9eSDmitry Osipenko 5811f8702f9eSDmitry Osipenko err = regulator_summary_lock_all(ww_ctx, 5812f8702f9eSDmitry Osipenko &new_contended_rdev, 5813f8702f9eSDmitry Osipenko &old_contended_rdev); 5814f8702f9eSDmitry Osipenko 5815f8702f9eSDmitry Osipenko if (old_contended_rdev) 5816f8702f9eSDmitry Osipenko regulator_unlock(old_contended_rdev); 5817f8702f9eSDmitry Osipenko 5818f8702f9eSDmitry Osipenko } while (err == -EDEADLK); 5819f8702f9eSDmitry Osipenko 5820f8702f9eSDmitry Osipenko ww_acquire_done(ww_ctx); 5821f8702f9eSDmitry Osipenko } 5822f8702f9eSDmitry Osipenko 5823f8702f9eSDmitry Osipenko static void regulator_summary_unlock(struct ww_acquire_ctx *ww_ctx) 5824f8702f9eSDmitry Osipenko { 5825f8702f9eSDmitry Osipenko class_for_each_device(®ulator_class, NULL, NULL, 5826f8702f9eSDmitry Osipenko regulator_summary_unlock_one); 5827f8702f9eSDmitry Osipenko ww_acquire_fini(ww_ctx); 5828ff9b34b6SDmitry Osipenko 5829ff9b34b6SDmitry Osipenko mutex_unlock(®ulator_list_mutex); 58307c225ec9SHeiko Stübner } 583185f3b431STomeu Vizoso 583285f3b431STomeu Vizoso static int regulator_summary_show_roots(struct device *dev, void *data) 583385f3b431STomeu Vizoso { 583485f3b431STomeu Vizoso struct regulator_dev *rdev = dev_to_rdev(dev); 583585f3b431STomeu Vizoso struct seq_file *s = data; 583685f3b431STomeu Vizoso 583785f3b431STomeu Vizoso if (!rdev->supply) 583885f3b431STomeu Vizoso regulator_summary_show_subtree(s, rdev, 0); 583985f3b431STomeu Vizoso 584085f3b431STomeu Vizoso return 0; 58417c225ec9SHeiko Stübner } 58427c225ec9SHeiko Stübner 58437c225ec9SHeiko Stübner static int regulator_summary_show(struct seq_file *s, void *data) 58447c225ec9SHeiko Stübner { 5845f8702f9eSDmitry Osipenko struct ww_acquire_ctx ww_ctx; 5846f8702f9eSDmitry Osipenko 584701de19d0SDouglas Anderson seq_puts(s, " regulator use open bypass opmode voltage current min max\n"); 584801de19d0SDouglas Anderson seq_puts(s, "---------------------------------------------------------------------------------------\n"); 58497c225ec9SHeiko Stübner 5850f8702f9eSDmitry Osipenko regulator_summary_lock(&ww_ctx); 5851f8702f9eSDmitry Osipenko 585285f3b431STomeu Vizoso class_for_each_device(®ulator_class, NULL, s, 585385f3b431STomeu Vizoso regulator_summary_show_roots); 58547c225ec9SHeiko Stübner 5855f8702f9eSDmitry Osipenko regulator_summary_unlock(&ww_ctx); 5856f8702f9eSDmitry Osipenko 58577c225ec9SHeiko Stübner return 0; 58587c225ec9SHeiko Stübner } 58593e60b4fcSYangtao Li DEFINE_SHOW_ATTRIBUTE(regulator_summary); 58603e60b4fcSYangtao Li #endif /* CONFIG_DEBUG_FS */ 58617c225ec9SHeiko Stübner 5862414c70cbSLiam Girdwood static int __init regulator_init(void) 5863414c70cbSLiam Girdwood { 586434abbd68SMark Brown int ret; 586534abbd68SMark Brown 586634abbd68SMark Brown ret = class_register(®ulator_class); 586734abbd68SMark Brown 58681130e5b3SMark Brown debugfs_root = debugfs_create_dir("regulator", NULL); 586924751434SStephen Boyd if (!debugfs_root) 58701130e5b3SMark Brown pr_warn("regulator: Failed to create debugfs directory\n"); 5871ba55a974SMark Brown 58723e60b4fcSYangtao Li #ifdef CONFIG_DEBUG_FS 5873f4d562c6SMark Brown debugfs_create_file("supply_map", 0444, debugfs_root, NULL, 5874f4d562c6SMark Brown &supply_map_fops); 58751130e5b3SMark Brown 58767c225ec9SHeiko Stübner debugfs_create_file("regulator_summary", 0444, debugfs_root, 587785f3b431STomeu Vizoso NULL, ®ulator_summary_fops); 58783e60b4fcSYangtao Li #endif 587934abbd68SMark Brown regulator_dummy_init(); 588034abbd68SMark Brown 5881d8ca7d18SDmitry Osipenko regulator_coupler_register(&generic_regulator_coupler); 5882d8ca7d18SDmitry Osipenko 588334abbd68SMark Brown return ret; 5884414c70cbSLiam Girdwood } 5885414c70cbSLiam Girdwood 5886414c70cbSLiam Girdwood /* init early to allow our consumers to complete system booting */ 5887414c70cbSLiam Girdwood core_initcall(regulator_init); 5888ca725561SMark Brown 588955576cf1SMark Brown static int regulator_late_cleanup(struct device *dev, void *data) 5890ca725561SMark Brown { 5891609ca5f3SMark Brown struct regulator_dev *rdev = dev_to_rdev(dev); 5892609ca5f3SMark Brown const struct regulator_ops *ops = rdev->desc->ops; 5893609ca5f3SMark Brown struct regulation_constraints *c = rdev->constraints; 5894ca725561SMark Brown int enabled, ret; 5895ca725561SMark Brown 589666fda75fSMarkus Pargmann if (c && c->always_on) 5897609ca5f3SMark Brown return 0; 5898ca725561SMark Brown 58998a34e979SWEN Pingbo if (!regulator_ops_is_valid(rdev, REGULATOR_CHANGE_STATUS)) 5900609ca5f3SMark Brown return 0; 5901e9535834SMark Brown 590266cf9a7eSMaciej Purski regulator_lock(rdev); 5903ca725561SMark Brown 5904ca725561SMark Brown if (rdev->use_count) 5905ca725561SMark Brown goto unlock; 5906ca725561SMark Brown 5907c088a498SPi-Hsun Shih /* If we can't read the status assume it's always on. */ 5908ca725561SMark Brown if (ops->is_enabled) 5909ca725561SMark Brown enabled = ops->is_enabled(rdev); 5910ca725561SMark Brown else 5911ca725561SMark Brown enabled = 1; 5912ca725561SMark Brown 5913c088a498SPi-Hsun Shih /* But if reading the status failed, assume that it's off. */ 5914c088a498SPi-Hsun Shih if (enabled <= 0) 5915ca725561SMark Brown goto unlock; 5916ca725561SMark Brown 591787b28417SMark Brown if (have_full_constraints()) { 5918609ca5f3SMark Brown /* We log since this may kill the system if it goes 591969b8821eSShubhankar Kuranagatti * wrong. 592069b8821eSShubhankar Kuranagatti */ 59215da84fd9SJoe Perches rdev_info(rdev, "disabling\n"); 592266fda75fSMarkus Pargmann ret = _regulator_do_disable(rdev); 59230d25d09dSJingoo Han if (ret != 0) 592461aab5adSMichał Mirosław rdev_err(rdev, "couldn't disable: %pe\n", ERR_PTR(ret)); 5925ca725561SMark Brown } else { 5926ca725561SMark Brown /* The intention is that in future we will 5927ca725561SMark Brown * assume that full constraints are provided 5928ca725561SMark Brown * so warn even if we aren't going to do 5929ca725561SMark Brown * anything here. 5930ca725561SMark Brown */ 59315da84fd9SJoe Perches rdev_warn(rdev, "incomplete constraints, leaving on\n"); 5932ca725561SMark Brown } 5933ca725561SMark Brown 5934ca725561SMark Brown unlock: 593566cf9a7eSMaciej Purski regulator_unlock(rdev); 5936609ca5f3SMark Brown 5937609ca5f3SMark Brown return 0; 5938ca725561SMark Brown } 5939ca725561SMark Brown 594055576cf1SMark Brown static void regulator_init_complete_work_function(struct work_struct *work) 5941609ca5f3SMark Brown { 5942609ca5f3SMark Brown /* 59433827b64dSJavier Martinez Canillas * Regulators may had failed to resolve their input supplies 59443827b64dSJavier Martinez Canillas * when were registered, either because the input supply was 59453827b64dSJavier Martinez Canillas * not registered yet or because its parent device was not 59463827b64dSJavier Martinez Canillas * bound yet. So attempt to resolve the input supplies for 59473827b64dSJavier Martinez Canillas * pending regulators before trying to disable unused ones. 59483827b64dSJavier Martinez Canillas */ 59493827b64dSJavier Martinez Canillas class_for_each_device(®ulator_class, NULL, NULL, 59503827b64dSJavier Martinez Canillas regulator_register_resolve_supply); 59513827b64dSJavier Martinez Canillas 5952609ca5f3SMark Brown /* If we have a full configuration then disable any regulators 5953609ca5f3SMark Brown * we have permission to change the status for and which are 5954609ca5f3SMark Brown * not in use or always_on. This is effectively the default 5955609ca5f3SMark Brown * for DT and ACPI as they have full constraints. 5956609ca5f3SMark Brown */ 5957609ca5f3SMark Brown class_for_each_device(®ulator_class, NULL, NULL, 5958609ca5f3SMark Brown regulator_late_cleanup); 595955576cf1SMark Brown } 596055576cf1SMark Brown 596155576cf1SMark Brown static DECLARE_DELAYED_WORK(regulator_init_complete_work, 596255576cf1SMark Brown regulator_init_complete_work_function); 596355576cf1SMark Brown 596455576cf1SMark Brown static int __init regulator_init_complete(void) 596555576cf1SMark Brown { 596655576cf1SMark Brown /* 596755576cf1SMark Brown * Since DT doesn't provide an idiomatic mechanism for 596855576cf1SMark Brown * enabling full constraints and since it's much more natural 596955576cf1SMark Brown * with DT to provide them just assume that a DT enabled 597055576cf1SMark Brown * system has full constraints. 597155576cf1SMark Brown */ 597255576cf1SMark Brown if (of_have_populated_dt()) 597355576cf1SMark Brown has_full_constraints = true; 597455576cf1SMark Brown 597555576cf1SMark Brown /* 59762a15483bSJohn Stultz * We punt completion for an arbitrary amount of time since 59772a15483bSJohn Stultz * systems like distros will load many drivers from userspace 59782a15483bSJohn Stultz * so consumers might not always be ready yet, this is 59792a15483bSJohn Stultz * particularly an issue with laptops where this might bounce 59802a15483bSJohn Stultz * the display off then on. Ideally we'd get a notification 59812a15483bSJohn Stultz * from userspace when this happens but we don't so just wait 59822a15483bSJohn Stultz * a bit and hope we waited long enough. It'd be better if 59832a15483bSJohn Stultz * we'd only do this on systems that need it, and a kernel 59842a15483bSJohn Stultz * command line option might be useful. 598555576cf1SMark Brown */ 59862a15483bSJohn Stultz schedule_delayed_work(®ulator_init_complete_work, 59872a15483bSJohn Stultz msecs_to_jiffies(30000)); 5988ca725561SMark Brown 5989ca725561SMark Brown return 0; 5990ca725561SMark Brown } 5991fd482a3eSSaravana Kannan late_initcall_sync(regulator_init_complete); 5992