12874c5fdSThomas Gleixner // SPDX-License-Identifier: GPL-2.0-or-later 2f2c6203fSMark Brown // 3f2c6203fSMark Brown // core.c -- Voltage/Current Regulator framework. 4f2c6203fSMark Brown // 5f2c6203fSMark Brown // Copyright 2007, 2008 Wolfson Microelectronics PLC. 6f2c6203fSMark Brown // Copyright 2008 SlimLogic Ltd. 7f2c6203fSMark Brown // 8f2c6203fSMark Brown // Author: Liam Girdwood <lrg@slimlogic.co.uk> 9414c70cbSLiam Girdwood 10414c70cbSLiam Girdwood #include <linux/kernel.h> 11414c70cbSLiam Girdwood #include <linux/init.h> 121130e5b3SMark Brown #include <linux/debugfs.h> 13414c70cbSLiam Girdwood #include <linux/device.h> 145a0e3ad6STejun Heo #include <linux/slab.h> 15f21e0e81SMark Brown #include <linux/async.h> 16414c70cbSLiam Girdwood #include <linux/err.h> 17414c70cbSLiam Girdwood #include <linux/mutex.h> 18414c70cbSLiam Girdwood #include <linux/suspend.h> 1931aae2beSMark Brown #include <linux/delay.h> 20778b28b4SRussell King #include <linux/gpio/consumer.h> 2169511a45SRajendra Nayak #include <linux/of.h> 2265b19ce6SMark Brown #include <linux/regmap.h> 2369511a45SRajendra Nayak #include <linux/regulator/of_regulator.h> 24414c70cbSLiam Girdwood #include <linux/regulator/consumer.h> 25d8ca7d18SDmitry Osipenko #include <linux/regulator/coupler.h> 26414c70cbSLiam Girdwood #include <linux/regulator/driver.h> 27414c70cbSLiam Girdwood #include <linux/regulator/machine.h> 2865602c32SPaul Gortmaker #include <linux/module.h> 29414c70cbSLiam Girdwood 3002fa3ec0SMark Brown #define CREATE_TRACE_POINTS 3102fa3ec0SMark Brown #include <trace/events/regulator.h> 3202fa3ec0SMark Brown 3334abbd68SMark Brown #include "dummy.h" 340cdfcc0fSMark Brown #include "internal.h" 3534abbd68SMark Brown 367d51a0dbSMark Brown #define rdev_crit(rdev, fmt, ...) \ 377d51a0dbSMark Brown pr_crit("%s: " fmt, rdev_get_name(rdev), ##__VA_ARGS__) 385da84fd9SJoe Perches #define rdev_err(rdev, fmt, ...) \ 395da84fd9SJoe Perches pr_err("%s: " fmt, rdev_get_name(rdev), ##__VA_ARGS__) 405da84fd9SJoe Perches #define rdev_warn(rdev, fmt, ...) \ 415da84fd9SJoe Perches pr_warn("%s: " fmt, rdev_get_name(rdev), ##__VA_ARGS__) 425da84fd9SJoe Perches #define rdev_info(rdev, fmt, ...) \ 435da84fd9SJoe Perches pr_info("%s: " fmt, rdev_get_name(rdev), ##__VA_ARGS__) 445da84fd9SJoe Perches #define rdev_dbg(rdev, fmt, ...) \ 455da84fd9SJoe Perches pr_debug("%s: " fmt, rdev_get_name(rdev), ##__VA_ARGS__) 465da84fd9SJoe Perches 47f8702f9eSDmitry Osipenko static DEFINE_WW_CLASS(regulator_ww_class); 48f8702f9eSDmitry Osipenko static DEFINE_MUTEX(regulator_nesting_mutex); 49414c70cbSLiam Girdwood static DEFINE_MUTEX(regulator_list_mutex); 50414c70cbSLiam Girdwood static LIST_HEAD(regulator_map_list); 51f19b00daSKim, Milo static LIST_HEAD(regulator_ena_gpio_list); 52a06ccd9cSCharles Keepax static LIST_HEAD(regulator_supply_alias_list); 53d8ca7d18SDmitry Osipenko static LIST_HEAD(regulator_coupler_list); 5421cf891aSMark Brown static bool has_full_constraints; 55414c70cbSLiam Girdwood 561130e5b3SMark Brown static struct dentry *debugfs_root; 571130e5b3SMark Brown 588dc5390dSMark Brown /* 59414c70cbSLiam Girdwood * struct regulator_map 60414c70cbSLiam Girdwood * 61414c70cbSLiam Girdwood * Used to provide symbolic supply names to devices. 62414c70cbSLiam Girdwood */ 63414c70cbSLiam Girdwood struct regulator_map { 64414c70cbSLiam Girdwood struct list_head list; 6540f9244fSMark Brown const char *dev_name; /* The dev_name() for the consumer */ 66414c70cbSLiam Girdwood const char *supply; 67a5766f11SLiam Girdwood struct regulator_dev *regulator; 68414c70cbSLiam Girdwood }; 69414c70cbSLiam Girdwood 70414c70cbSLiam Girdwood /* 71f19b00daSKim, Milo * struct regulator_enable_gpio 72f19b00daSKim, Milo * 73f19b00daSKim, Milo * Management for shared enable GPIO pin 74f19b00daSKim, Milo */ 75f19b00daSKim, Milo struct regulator_enable_gpio { 76f19b00daSKim, Milo struct list_head list; 77778b28b4SRussell King struct gpio_desc *gpiod; 78f19b00daSKim, Milo u32 enable_count; /* a number of enabled shared GPIO */ 79f19b00daSKim, Milo u32 request_count; /* a number of requested shared GPIO */ 80f19b00daSKim, Milo }; 81f19b00daSKim, Milo 82a06ccd9cSCharles Keepax /* 83a06ccd9cSCharles Keepax * struct regulator_supply_alias 84a06ccd9cSCharles Keepax * 85a06ccd9cSCharles Keepax * Used to map lookups for a supply onto an alternative device. 86a06ccd9cSCharles Keepax */ 87a06ccd9cSCharles Keepax struct regulator_supply_alias { 88a06ccd9cSCharles Keepax struct list_head list; 89a06ccd9cSCharles Keepax struct device *src_dev; 90a06ccd9cSCharles Keepax const char *src_supply; 91a06ccd9cSCharles Keepax struct device *alias_dev; 92a06ccd9cSCharles Keepax const char *alias_supply; 93a06ccd9cSCharles Keepax }; 94a06ccd9cSCharles Keepax 95414c70cbSLiam Girdwood static int _regulator_is_enabled(struct regulator_dev *rdev); 965451781dSDouglas Anderson static int _regulator_disable(struct regulator *regulator); 97414c70cbSLiam Girdwood static int _regulator_get_current_limit(struct regulator_dev *rdev); 98414c70cbSLiam Girdwood static unsigned int _regulator_get_mode(struct regulator_dev *rdev); 997179569aSHeiko Stübner static int _notifier_call_chain(struct regulator_dev *rdev, 100414c70cbSLiam Girdwood unsigned long event, void *data); 10175790251SMark Brown static int _regulator_do_set_voltage(struct regulator_dev *rdev, 10275790251SMark Brown int min_uV, int max_uV); 103c054c6c7SMaciej Purski static int regulator_balance_voltage(struct regulator_dev *rdev, 104c054c6c7SMaciej Purski suspend_state_t state); 1053801b86aSMark Brown static struct regulator *create_regulator(struct regulator_dev *rdev, 1063801b86aSMark Brown struct device *dev, 1073801b86aSMark Brown const char *supply_name); 108e1794aa4SSaravana Kannan static void destroy_regulator(struct regulator *regulator); 10936a1f1b6SJavier Martinez Canillas static void _regulator_put(struct regulator *regulator); 110414c70cbSLiam Girdwood 111d22b85a1SDmitry Osipenko const char *rdev_get_name(struct regulator_dev *rdev) 1121083c393SMark Brown { 1131083c393SMark Brown if (rdev->constraints && rdev->constraints->name) 1141083c393SMark Brown return rdev->constraints->name; 1151083c393SMark Brown else if (rdev->desc->name) 1161083c393SMark Brown return rdev->desc->name; 1171083c393SMark Brown else 1181083c393SMark Brown return ""; 1191083c393SMark Brown } 1201083c393SMark Brown 12187b28417SMark Brown static bool have_full_constraints(void) 12287b28417SMark Brown { 12375bc9641SMark Brown return has_full_constraints || of_have_populated_dt(); 12487b28417SMark Brown } 12587b28417SMark Brown 1268a34e979SWEN Pingbo static bool regulator_ops_is_valid(struct regulator_dev *rdev, int ops) 1278a34e979SWEN Pingbo { 1288a34e979SWEN Pingbo if (!rdev->constraints) { 1298a34e979SWEN Pingbo rdev_err(rdev, "no constraints\n"); 1308a34e979SWEN Pingbo return false; 1318a34e979SWEN Pingbo } 1328a34e979SWEN Pingbo 1338a34e979SWEN Pingbo if (rdev->constraints->valid_ops_mask & ops) 1348a34e979SWEN Pingbo return true; 1358a34e979SWEN Pingbo 1368a34e979SWEN Pingbo return false; 1378a34e979SWEN Pingbo } 1388a34e979SWEN Pingbo 13969511a45SRajendra Nayak /** 14066cf9a7eSMaciej Purski * regulator_lock_nested - lock a single regulator 14166cf9a7eSMaciej Purski * @rdev: regulator source 142f8702f9eSDmitry Osipenko * @ww_ctx: w/w mutex acquire context 14366cf9a7eSMaciej Purski * 14466cf9a7eSMaciej Purski * This function can be called many times by one task on 14566cf9a7eSMaciej Purski * a single regulator and its mutex will be locked only 14666cf9a7eSMaciej Purski * once. If a task, which is calling this function is other 14766cf9a7eSMaciej Purski * than the one, which initially locked the mutex, it will 14866cf9a7eSMaciej Purski * wait on mutex. 14966cf9a7eSMaciej Purski */ 150f8702f9eSDmitry Osipenko static inline int regulator_lock_nested(struct regulator_dev *rdev, 151f8702f9eSDmitry Osipenko struct ww_acquire_ctx *ww_ctx) 15266cf9a7eSMaciej Purski { 153f8702f9eSDmitry Osipenko bool lock = false; 154f8702f9eSDmitry Osipenko int ret = 0; 155f8702f9eSDmitry Osipenko 156f8702f9eSDmitry Osipenko mutex_lock(®ulator_nesting_mutex); 157f8702f9eSDmitry Osipenko 158f8702f9eSDmitry Osipenko if (ww_ctx || !ww_mutex_trylock(&rdev->mutex)) { 159f8702f9eSDmitry Osipenko if (rdev->mutex_owner == current) 16066cf9a7eSMaciej Purski rdev->ref_cnt++; 161f8702f9eSDmitry Osipenko else 162f8702f9eSDmitry Osipenko lock = true; 163f8702f9eSDmitry Osipenko 164f8702f9eSDmitry Osipenko if (lock) { 165f8702f9eSDmitry Osipenko mutex_unlock(®ulator_nesting_mutex); 166f8702f9eSDmitry Osipenko ret = ww_mutex_lock(&rdev->mutex, ww_ctx); 167f8702f9eSDmitry Osipenko mutex_lock(®ulator_nesting_mutex); 16866cf9a7eSMaciej Purski } 169f8702f9eSDmitry Osipenko } else { 170f8702f9eSDmitry Osipenko lock = true; 17166cf9a7eSMaciej Purski } 17266cf9a7eSMaciej Purski 173f8702f9eSDmitry Osipenko if (lock && ret != -EDEADLK) { 174f8702f9eSDmitry Osipenko rdev->ref_cnt++; 17566cf9a7eSMaciej Purski rdev->mutex_owner = current; 17666cf9a7eSMaciej Purski } 17766cf9a7eSMaciej Purski 178f8702f9eSDmitry Osipenko mutex_unlock(®ulator_nesting_mutex); 179f8702f9eSDmitry Osipenko 180f8702f9eSDmitry Osipenko return ret; 181f8702f9eSDmitry Osipenko } 182f8702f9eSDmitry Osipenko 183f8702f9eSDmitry Osipenko /** 184f8702f9eSDmitry Osipenko * regulator_lock - lock a single regulator 185f8702f9eSDmitry Osipenko * @rdev: regulator source 186f8702f9eSDmitry Osipenko * 187f8702f9eSDmitry Osipenko * This function can be called many times by one task on 188f8702f9eSDmitry Osipenko * a single regulator and its mutex will be locked only 189f8702f9eSDmitry Osipenko * once. If a task, which is calling this function is other 190f8702f9eSDmitry Osipenko * than the one, which initially locked the mutex, it will 191f8702f9eSDmitry Osipenko * wait on mutex. 192f8702f9eSDmitry Osipenko */ 1934c9db393SMichał Mirosław static void regulator_lock(struct regulator_dev *rdev) 19466cf9a7eSMaciej Purski { 195f8702f9eSDmitry Osipenko regulator_lock_nested(rdev, NULL); 19666cf9a7eSMaciej Purski } 19766cf9a7eSMaciej Purski 19866cf9a7eSMaciej Purski /** 19966cf9a7eSMaciej Purski * regulator_unlock - unlock a single regulator 20066cf9a7eSMaciej Purski * @rdev: regulator_source 20166cf9a7eSMaciej Purski * 20266cf9a7eSMaciej Purski * This function unlocks the mutex when the 20366cf9a7eSMaciej Purski * reference counter reaches 0. 20466cf9a7eSMaciej Purski */ 2054c9db393SMichał Mirosław static void regulator_unlock(struct regulator_dev *rdev) 20666cf9a7eSMaciej Purski { 207f8702f9eSDmitry Osipenko mutex_lock(®ulator_nesting_mutex); 20866cf9a7eSMaciej Purski 209f8702f9eSDmitry Osipenko if (--rdev->ref_cnt == 0) { 21066cf9a7eSMaciej Purski rdev->mutex_owner = NULL; 211f8702f9eSDmitry Osipenko ww_mutex_unlock(&rdev->mutex); 21266cf9a7eSMaciej Purski } 21366cf9a7eSMaciej Purski 214f8702f9eSDmitry Osipenko WARN_ON_ONCE(rdev->ref_cnt < 0); 215f8702f9eSDmitry Osipenko 216f8702f9eSDmitry Osipenko mutex_unlock(®ulator_nesting_mutex); 217f8702f9eSDmitry Osipenko } 218f8702f9eSDmitry Osipenko 219089e2cc2SDmitry Osipenko static bool regulator_supply_is_couple(struct regulator_dev *rdev) 2209f01cd4aSSascha Hauer { 221089e2cc2SDmitry Osipenko struct regulator_dev *c_rdev; 222fa731ac7SArnd Bergmann int i; 2239f01cd4aSSascha Hauer 224089e2cc2SDmitry Osipenko for (i = 1; i < rdev->coupling_desc.n_coupled; i++) { 225089e2cc2SDmitry Osipenko c_rdev = rdev->coupling_desc.coupled_rdevs[i]; 226089e2cc2SDmitry Osipenko 227089e2cc2SDmitry Osipenko if (rdev->supply->rdev == c_rdev) 228089e2cc2SDmitry Osipenko return true; 229089e2cc2SDmitry Osipenko } 230089e2cc2SDmitry Osipenko 231089e2cc2SDmitry Osipenko return false; 232089e2cc2SDmitry Osipenko } 233089e2cc2SDmitry Osipenko 234f8702f9eSDmitry Osipenko static void regulator_unlock_recursive(struct regulator_dev *rdev, 235f8702f9eSDmitry Osipenko unsigned int n_coupled) 236f8702f9eSDmitry Osipenko { 2370a7416f9SDmitry Osipenko struct regulator_dev *c_rdev, *supply_rdev; 2380a7416f9SDmitry Osipenko int i, supply_n_coupled; 239f8702f9eSDmitry Osipenko 240f8702f9eSDmitry Osipenko for (i = n_coupled; i > 0; i--) { 241f8702f9eSDmitry Osipenko c_rdev = rdev->coupling_desc.coupled_rdevs[i - 1]; 242f8702f9eSDmitry Osipenko 243f8702f9eSDmitry Osipenko if (!c_rdev) 244f8702f9eSDmitry Osipenko continue; 245f8702f9eSDmitry Osipenko 2460a7416f9SDmitry Osipenko if (c_rdev->supply && !regulator_supply_is_couple(c_rdev)) { 2470a7416f9SDmitry Osipenko supply_rdev = c_rdev->supply->rdev; 2480a7416f9SDmitry Osipenko supply_n_coupled = supply_rdev->coupling_desc.n_coupled; 2490a7416f9SDmitry Osipenko 2500a7416f9SDmitry Osipenko regulator_unlock_recursive(supply_rdev, 2510a7416f9SDmitry Osipenko supply_n_coupled); 2520a7416f9SDmitry Osipenko } 253f8702f9eSDmitry Osipenko 254f8702f9eSDmitry Osipenko regulator_unlock(c_rdev); 255414c70cbSLiam Girdwood } 256414c70cbSLiam Girdwood } 257414c70cbSLiam Girdwood 2589243a195SMaciej Purski static int regulator_lock_recursive(struct regulator_dev *rdev, 259f8702f9eSDmitry Osipenko struct regulator_dev **new_contended_rdev, 260f8702f9eSDmitry Osipenko struct regulator_dev **old_contended_rdev, 261f8702f9eSDmitry Osipenko struct ww_acquire_ctx *ww_ctx) 2629f01cd4aSSascha Hauer { 2639243a195SMaciej Purski struct regulator_dev *c_rdev; 264f8702f9eSDmitry Osipenko int i, err; 2659f01cd4aSSascha Hauer 2669243a195SMaciej Purski for (i = 0; i < rdev->coupling_desc.n_coupled; i++) { 2679243a195SMaciej Purski c_rdev = rdev->coupling_desc.coupled_rdevs[i]; 2689243a195SMaciej Purski 2699243a195SMaciej Purski if (!c_rdev) 2709243a195SMaciej Purski continue; 2719243a195SMaciej Purski 272f8702f9eSDmitry Osipenko if (c_rdev != *old_contended_rdev) { 273f8702f9eSDmitry Osipenko err = regulator_lock_nested(c_rdev, ww_ctx); 274f8702f9eSDmitry Osipenko if (err) { 275f8702f9eSDmitry Osipenko if (err == -EDEADLK) { 276f8702f9eSDmitry Osipenko *new_contended_rdev = c_rdev; 277f8702f9eSDmitry Osipenko goto err_unlock; 2789243a195SMaciej Purski } 2799243a195SMaciej Purski 280f8702f9eSDmitry Osipenko /* shouldn't happen */ 281f8702f9eSDmitry Osipenko WARN_ON_ONCE(err != -EALREADY); 282f8702f9eSDmitry Osipenko } 283f8702f9eSDmitry Osipenko } else { 284f8702f9eSDmitry Osipenko *old_contended_rdev = NULL; 285f8702f9eSDmitry Osipenko } 286f8702f9eSDmitry Osipenko 287089e2cc2SDmitry Osipenko if (c_rdev->supply && !regulator_supply_is_couple(c_rdev)) { 288f8702f9eSDmitry Osipenko err = regulator_lock_recursive(c_rdev->supply->rdev, 289f8702f9eSDmitry Osipenko new_contended_rdev, 290f8702f9eSDmitry Osipenko old_contended_rdev, 291f8702f9eSDmitry Osipenko ww_ctx); 292f8702f9eSDmitry Osipenko if (err) { 293f8702f9eSDmitry Osipenko regulator_unlock(c_rdev); 294f8702f9eSDmitry Osipenko goto err_unlock; 295f8702f9eSDmitry Osipenko } 296f8702f9eSDmitry Osipenko } 297f8702f9eSDmitry Osipenko } 298f8702f9eSDmitry Osipenko 299f8702f9eSDmitry Osipenko return 0; 300f8702f9eSDmitry Osipenko 301f8702f9eSDmitry Osipenko err_unlock: 302f8702f9eSDmitry Osipenko regulator_unlock_recursive(rdev, i); 303f8702f9eSDmitry Osipenko 304f8702f9eSDmitry Osipenko return err; 3059f01cd4aSSascha Hauer } 3069f01cd4aSSascha Hauer 3079f01cd4aSSascha Hauer /** 3089243a195SMaciej Purski * regulator_unlock_dependent - unlock regulator's suppliers and coupled 3099243a195SMaciej Purski * regulators 3109f01cd4aSSascha Hauer * @rdev: regulator source 311f8702f9eSDmitry Osipenko * @ww_ctx: w/w mutex acquire context 3129243a195SMaciej Purski * 31348f1b4efSKrzysztof Kozlowski * Unlock all regulators related with rdev by coupling or supplying. 3149f01cd4aSSascha Hauer */ 315f8702f9eSDmitry Osipenko static void regulator_unlock_dependent(struct regulator_dev *rdev, 316f8702f9eSDmitry Osipenko struct ww_acquire_ctx *ww_ctx) 3179f01cd4aSSascha Hauer { 318f8702f9eSDmitry Osipenko regulator_unlock_recursive(rdev, rdev->coupling_desc.n_coupled); 319f8702f9eSDmitry Osipenko ww_acquire_fini(ww_ctx); 3209f01cd4aSSascha Hauer } 3219f01cd4aSSascha Hauer 3229f01cd4aSSascha Hauer /** 3239243a195SMaciej Purski * regulator_lock_dependent - lock regulator's suppliers and coupled regulators 3249243a195SMaciej Purski * @rdev: regulator source 325f8702f9eSDmitry Osipenko * @ww_ctx: w/w mutex acquire context 3269243a195SMaciej Purski * 3279243a195SMaciej Purski * This function as a wrapper on regulator_lock_recursive(), which locks 32848f1b4efSKrzysztof Kozlowski * all regulators related with rdev by coupling or supplying. 3299243a195SMaciej Purski */ 330f8702f9eSDmitry Osipenko static void regulator_lock_dependent(struct regulator_dev *rdev, 331f8702f9eSDmitry Osipenko struct ww_acquire_ctx *ww_ctx) 3329243a195SMaciej Purski { 333f8702f9eSDmitry Osipenko struct regulator_dev *new_contended_rdev = NULL; 334f8702f9eSDmitry Osipenko struct regulator_dev *old_contended_rdev = NULL; 335f8702f9eSDmitry Osipenko int err; 336f8702f9eSDmitry Osipenko 337f8702f9eSDmitry Osipenko mutex_lock(®ulator_list_mutex); 338f8702f9eSDmitry Osipenko 339f8702f9eSDmitry Osipenko ww_acquire_init(ww_ctx, ®ulator_ww_class); 340f8702f9eSDmitry Osipenko 341f8702f9eSDmitry Osipenko do { 342f8702f9eSDmitry Osipenko if (new_contended_rdev) { 343f8702f9eSDmitry Osipenko ww_mutex_lock_slow(&new_contended_rdev->mutex, ww_ctx); 344f8702f9eSDmitry Osipenko old_contended_rdev = new_contended_rdev; 345f8702f9eSDmitry Osipenko old_contended_rdev->ref_cnt++; 346f8702f9eSDmitry Osipenko } 347f8702f9eSDmitry Osipenko 348f8702f9eSDmitry Osipenko err = regulator_lock_recursive(rdev, 349f8702f9eSDmitry Osipenko &new_contended_rdev, 350f8702f9eSDmitry Osipenko &old_contended_rdev, 351f8702f9eSDmitry Osipenko ww_ctx); 352f8702f9eSDmitry Osipenko 353f8702f9eSDmitry Osipenko if (old_contended_rdev) 354f8702f9eSDmitry Osipenko regulator_unlock(old_contended_rdev); 355f8702f9eSDmitry Osipenko 356f8702f9eSDmitry Osipenko } while (err == -EDEADLK); 357f8702f9eSDmitry Osipenko 358f8702f9eSDmitry Osipenko ww_acquire_done(ww_ctx); 359f8702f9eSDmitry Osipenko 360f8702f9eSDmitry Osipenko mutex_unlock(®ulator_list_mutex); 361414c70cbSLiam Girdwood } 362414c70cbSLiam Girdwood 363414c70cbSLiam Girdwood /** 364fe06051dSzoro * of_get_child_regulator - get a child regulator device node 365fe06051dSzoro * based on supply name 366fe06051dSzoro * @parent: Parent device node 367fe06051dSzoro * @prop_name: Combination regulator supply name and "-supply" 368fe06051dSzoro * 369fe06051dSzoro * Traverse all child nodes. 370fe06051dSzoro * Extract the child regulator device node corresponding to the supply name. 371fe06051dSzoro * returns the device node corresponding to the regulator if found, else 372fe06051dSzoro * returns NULL. 373fe06051dSzoro */ 374fe06051dSzoro static struct device_node *of_get_child_regulator(struct device_node *parent, 375fe06051dSzoro const char *prop_name) 376fe06051dSzoro { 377fe06051dSzoro struct device_node *regnode = NULL; 378fe06051dSzoro struct device_node *child = NULL; 379fe06051dSzoro 380fe06051dSzoro for_each_child_of_node(parent, child) { 381fe06051dSzoro regnode = of_parse_phandle(child, prop_name, 0); 382fe06051dSzoro 383fe06051dSzoro if (!regnode) { 384fe06051dSzoro regnode = of_get_child_regulator(child, prop_name); 38581eeb0a3SNishka Dasgupta if (regnode) 38681eeb0a3SNishka Dasgupta goto err_node_put; 387fe06051dSzoro } else { 38881eeb0a3SNishka Dasgupta goto err_node_put; 389fe06051dSzoro } 390fe06051dSzoro } 391fe06051dSzoro return NULL; 39281eeb0a3SNishka Dasgupta 39381eeb0a3SNishka Dasgupta err_node_put: 39481eeb0a3SNishka Dasgupta of_node_put(child); 39581eeb0a3SNishka Dasgupta return regnode; 396fe06051dSzoro } 397fe06051dSzoro 398fe06051dSzoro /** 39969511a45SRajendra Nayak * of_get_regulator - get a regulator device node based on supply name 40069511a45SRajendra Nayak * @dev: Device pointer for the consumer (of regulator) device 40169511a45SRajendra Nayak * @supply: regulator supply name 40269511a45SRajendra Nayak * 40369511a45SRajendra Nayak * Extract the regulator device node corresponding to the supply name. 404167d41dcSMaxime Ripard * returns the device node corresponding to the regulator if found, else 40569511a45SRajendra Nayak * returns NULL. 40669511a45SRajendra Nayak */ 40769511a45SRajendra Nayak static struct device_node *of_get_regulator(struct device *dev, const char *supply) 40869511a45SRajendra Nayak { 40969511a45SRajendra Nayak struct device_node *regnode = NULL; 410e9bb4a06SAngeloGioacchino Del Regno char prop_name[64]; /* 64 is max size of property name */ 41169511a45SRajendra Nayak 41269511a45SRajendra Nayak dev_dbg(dev, "Looking up %s-supply from device tree\n", supply); 41369511a45SRajendra Nayak 414e9bb4a06SAngeloGioacchino Del Regno snprintf(prop_name, 64, "%s-supply", supply); 41569511a45SRajendra Nayak regnode = of_parse_phandle(dev->of_node, prop_name, 0); 41669511a45SRajendra Nayak 41769511a45SRajendra Nayak if (!regnode) { 418fe06051dSzoro regnode = of_get_child_regulator(dev->of_node, prop_name); 419fe06051dSzoro if (regnode) 420fe06051dSzoro return regnode; 421fe06051dSzoro 4227799167bSRob Herring dev_dbg(dev, "Looking up %s property in node %pOF failed\n", 4237799167bSRob Herring prop_name, dev->of_node); 42469511a45SRajendra Nayak return NULL; 42569511a45SRajendra Nayak } 42669511a45SRajendra Nayak return regnode; 42769511a45SRajendra Nayak } 42869511a45SRajendra Nayak 429414c70cbSLiam Girdwood /* Platform voltage constraint check */ 430d22b85a1SDmitry Osipenko int regulator_check_voltage(struct regulator_dev *rdev, 431414c70cbSLiam Girdwood int *min_uV, int *max_uV) 432414c70cbSLiam Girdwood { 433414c70cbSLiam Girdwood BUG_ON(*min_uV > *max_uV); 434414c70cbSLiam Girdwood 4358a34e979SWEN Pingbo if (!regulator_ops_is_valid(rdev, REGULATOR_CHANGE_VOLTAGE)) { 4367ebcf26cSStephen Boyd rdev_err(rdev, "voltage operation not allowed\n"); 437414c70cbSLiam Girdwood return -EPERM; 438414c70cbSLiam Girdwood } 439414c70cbSLiam Girdwood 440414c70cbSLiam Girdwood if (*max_uV > rdev->constraints->max_uV) 441414c70cbSLiam Girdwood *max_uV = rdev->constraints->max_uV; 442414c70cbSLiam Girdwood if (*min_uV < rdev->constraints->min_uV) 443414c70cbSLiam Girdwood *min_uV = rdev->constraints->min_uV; 444414c70cbSLiam Girdwood 44589f425edSMark Brown if (*min_uV > *max_uV) { 44689f425edSMark Brown rdev_err(rdev, "unsupportable voltage range: %d-%duV\n", 44754abd335SMark Brown *min_uV, *max_uV); 448414c70cbSLiam Girdwood return -EINVAL; 44989f425edSMark Brown } 450414c70cbSLiam Girdwood 451414c70cbSLiam Girdwood return 0; 452414c70cbSLiam Girdwood } 453414c70cbSLiam Girdwood 454f7efad10SChunyan Zhang /* return 0 if the state is valid */ 455f7efad10SChunyan Zhang static int regulator_check_states(suspend_state_t state) 456f7efad10SChunyan Zhang { 457f7efad10SChunyan Zhang return (state > PM_SUSPEND_MAX || state == PM_SUSPEND_TO_IDLE); 458f7efad10SChunyan Zhang } 459f7efad10SChunyan Zhang 46005fda3b1SThomas Petazzoni /* Make sure we select a voltage that suits the needs of all 46105fda3b1SThomas Petazzoni * regulator consumers 46205fda3b1SThomas Petazzoni */ 463d22b85a1SDmitry Osipenko int regulator_check_consumers(struct regulator_dev *rdev, 464c360a6dfSChunyan Zhang int *min_uV, int *max_uV, 465c360a6dfSChunyan Zhang suspend_state_t state) 46605fda3b1SThomas Petazzoni { 46705fda3b1SThomas Petazzoni struct regulator *regulator; 468c360a6dfSChunyan Zhang struct regulator_voltage *voltage; 46905fda3b1SThomas Petazzoni 47005fda3b1SThomas Petazzoni list_for_each_entry(regulator, &rdev->consumer_list, list) { 471c360a6dfSChunyan Zhang voltage = ®ulator->voltage[state]; 4724aa922c0SMark Brown /* 4734aa922c0SMark Brown * Assume consumers that didn't say anything are OK 4744aa922c0SMark Brown * with anything in the constraint range. 4754aa922c0SMark Brown */ 476c360a6dfSChunyan Zhang if (!voltage->min_uV && !voltage->max_uV) 4774aa922c0SMark Brown continue; 4784aa922c0SMark Brown 479c360a6dfSChunyan Zhang if (*max_uV > voltage->max_uV) 480c360a6dfSChunyan Zhang *max_uV = voltage->max_uV; 481c360a6dfSChunyan Zhang if (*min_uV < voltage->min_uV) 482c360a6dfSChunyan Zhang *min_uV = voltage->min_uV; 48305fda3b1SThomas Petazzoni } 48405fda3b1SThomas Petazzoni 485dd8004afSMark Brown if (*min_uV > *max_uV) { 4869c7b4e8aSRuss Dill rdev_err(rdev, "Restricting voltage, %u-%uuV\n", 4879c7b4e8aSRuss Dill *min_uV, *max_uV); 48805fda3b1SThomas Petazzoni return -EINVAL; 489dd8004afSMark Brown } 49005fda3b1SThomas Petazzoni 49105fda3b1SThomas Petazzoni return 0; 49205fda3b1SThomas Petazzoni } 49305fda3b1SThomas Petazzoni 494414c70cbSLiam Girdwood /* current constraint check */ 495414c70cbSLiam Girdwood static int regulator_check_current_limit(struct regulator_dev *rdev, 496414c70cbSLiam Girdwood int *min_uA, int *max_uA) 497414c70cbSLiam Girdwood { 498414c70cbSLiam Girdwood BUG_ON(*min_uA > *max_uA); 499414c70cbSLiam Girdwood 5008a34e979SWEN Pingbo if (!regulator_ops_is_valid(rdev, REGULATOR_CHANGE_CURRENT)) { 5017ebcf26cSStephen Boyd rdev_err(rdev, "current operation not allowed\n"); 502414c70cbSLiam Girdwood return -EPERM; 503414c70cbSLiam Girdwood } 504414c70cbSLiam Girdwood 505414c70cbSLiam Girdwood if (*max_uA > rdev->constraints->max_uA) 506414c70cbSLiam Girdwood *max_uA = rdev->constraints->max_uA; 507414c70cbSLiam Girdwood if (*min_uA < rdev->constraints->min_uA) 508414c70cbSLiam Girdwood *min_uA = rdev->constraints->min_uA; 509414c70cbSLiam Girdwood 51089f425edSMark Brown if (*min_uA > *max_uA) { 51189f425edSMark Brown rdev_err(rdev, "unsupportable current range: %d-%duA\n", 51254abd335SMark Brown *min_uA, *max_uA); 513414c70cbSLiam Girdwood return -EINVAL; 51489f425edSMark Brown } 515414c70cbSLiam Girdwood 516414c70cbSLiam Girdwood return 0; 517414c70cbSLiam Girdwood } 518414c70cbSLiam Girdwood 519414c70cbSLiam Girdwood /* operating mode constraint check */ 520109c75afSCharles Keepax static int regulator_mode_constrain(struct regulator_dev *rdev, 521109c75afSCharles Keepax unsigned int *mode) 522414c70cbSLiam Girdwood { 5232c608234SMark Brown switch (*mode) { 524e573520bSDavid Brownell case REGULATOR_MODE_FAST: 525e573520bSDavid Brownell case REGULATOR_MODE_NORMAL: 526e573520bSDavid Brownell case REGULATOR_MODE_IDLE: 527e573520bSDavid Brownell case REGULATOR_MODE_STANDBY: 528e573520bSDavid Brownell break; 529e573520bSDavid Brownell default: 53089f425edSMark Brown rdev_err(rdev, "invalid mode %x specified\n", *mode); 531e573520bSDavid Brownell return -EINVAL; 532e573520bSDavid Brownell } 533e573520bSDavid Brownell 5348a34e979SWEN Pingbo if (!regulator_ops_is_valid(rdev, REGULATOR_CHANGE_MODE)) { 5357ebcf26cSStephen Boyd rdev_err(rdev, "mode operation not allowed\n"); 536414c70cbSLiam Girdwood return -EPERM; 537414c70cbSLiam Girdwood } 5382c608234SMark Brown 5392c608234SMark Brown /* The modes are bitmasks, the most power hungry modes having 5402c608234SMark Brown * the lowest values. If the requested mode isn't supported 5412c608234SMark Brown * try higher modes. */ 5422c608234SMark Brown while (*mode) { 5432c608234SMark Brown if (rdev->constraints->valid_modes_mask & *mode) 544414c70cbSLiam Girdwood return 0; 5452c608234SMark Brown *mode /= 2; 5462c608234SMark Brown } 5472c608234SMark Brown 5482c608234SMark Brown return -EINVAL; 549414c70cbSLiam Girdwood } 550414c70cbSLiam Girdwood 551f7efad10SChunyan Zhang static inline struct regulator_state * 552f7efad10SChunyan Zhang regulator_get_suspend_state(struct regulator_dev *rdev, suspend_state_t state) 553f7efad10SChunyan Zhang { 554f7efad10SChunyan Zhang if (rdev->constraints == NULL) 555f7efad10SChunyan Zhang return NULL; 556f7efad10SChunyan Zhang 557f7efad10SChunyan Zhang switch (state) { 558f7efad10SChunyan Zhang case PM_SUSPEND_STANDBY: 559f7efad10SChunyan Zhang return &rdev->constraints->state_standby; 560f7efad10SChunyan Zhang case PM_SUSPEND_MEM: 561f7efad10SChunyan Zhang return &rdev->constraints->state_mem; 562f7efad10SChunyan Zhang case PM_SUSPEND_MAX: 563f7efad10SChunyan Zhang return &rdev->constraints->state_disk; 564f7efad10SChunyan Zhang default: 565f7efad10SChunyan Zhang return NULL; 566f7efad10SChunyan Zhang } 567f7efad10SChunyan Zhang } 568f7efad10SChunyan Zhang 5690955f5beSStephen Boyd static const struct regulator_state * 5700955f5beSStephen Boyd regulator_get_suspend_state_check(struct regulator_dev *rdev, suspend_state_t state) 5710955f5beSStephen Boyd { 5720955f5beSStephen Boyd const struct regulator_state *rstate; 5730955f5beSStephen Boyd 5740955f5beSStephen Boyd rstate = regulator_get_suspend_state(rdev, state); 5750955f5beSStephen Boyd if (rstate == NULL) 5760955f5beSStephen Boyd return NULL; 5770955f5beSStephen Boyd 5780955f5beSStephen Boyd /* If we have no suspend mode configuration don't set anything; 5790955f5beSStephen Boyd * only warn if the driver implements set_suspend_voltage or 5800955f5beSStephen Boyd * set_suspend_mode callback. 5810955f5beSStephen Boyd */ 5820955f5beSStephen Boyd if (rstate->enabled != ENABLE_IN_SUSPEND && 5830955f5beSStephen Boyd rstate->enabled != DISABLE_IN_SUSPEND) { 5840955f5beSStephen Boyd if (rdev->desc->ops->set_suspend_voltage || 5850955f5beSStephen Boyd rdev->desc->ops->set_suspend_mode) 5860955f5beSStephen Boyd rdev_warn(rdev, "No configuration\n"); 5870955f5beSStephen Boyd return NULL; 5880955f5beSStephen Boyd } 5890955f5beSStephen Boyd 5900955f5beSStephen Boyd return rstate; 5910955f5beSStephen Boyd } 5920955f5beSStephen Boyd 593414c70cbSLiam Girdwood static ssize_t regulator_uV_show(struct device *dev, 594414c70cbSLiam Girdwood struct device_attribute *attr, char *buf) 595414c70cbSLiam Girdwood { 596a5766f11SLiam Girdwood struct regulator_dev *rdev = dev_get_drvdata(dev); 597c82f27dfSH. Nikolaus Schaller int uV; 598414c70cbSLiam Girdwood 59966cf9a7eSMaciej Purski regulator_lock(rdev); 600c82f27dfSH. Nikolaus Schaller uV = regulator_get_voltage_rdev(rdev); 60166cf9a7eSMaciej Purski regulator_unlock(rdev); 602414c70cbSLiam Girdwood 603c82f27dfSH. Nikolaus Schaller if (uV < 0) 604c82f27dfSH. Nikolaus Schaller return uV; 605c82f27dfSH. Nikolaus Schaller return sprintf(buf, "%d\n", uV); 606414c70cbSLiam Girdwood } 6077ad68e2fSDavid Brownell static DEVICE_ATTR(microvolts, 0444, regulator_uV_show, NULL); 608414c70cbSLiam Girdwood 609414c70cbSLiam Girdwood static ssize_t regulator_uA_show(struct device *dev, 610414c70cbSLiam Girdwood struct device_attribute *attr, char *buf) 611414c70cbSLiam Girdwood { 612a5766f11SLiam Girdwood struct regulator_dev *rdev = dev_get_drvdata(dev); 613414c70cbSLiam Girdwood 614414c70cbSLiam Girdwood return sprintf(buf, "%d\n", _regulator_get_current_limit(rdev)); 615414c70cbSLiam Girdwood } 6167ad68e2fSDavid Brownell static DEVICE_ATTR(microamps, 0444, regulator_uA_show, NULL); 617414c70cbSLiam Girdwood 618587cea27SGreg Kroah-Hartman static ssize_t name_show(struct device *dev, struct device_attribute *attr, 619587cea27SGreg Kroah-Hartman char *buf) 620bc558a60SMark Brown { 621bc558a60SMark Brown struct regulator_dev *rdev = dev_get_drvdata(dev); 622bc558a60SMark Brown 6231083c393SMark Brown return sprintf(buf, "%s\n", rdev_get_name(rdev)); 624bc558a60SMark Brown } 625587cea27SGreg Kroah-Hartman static DEVICE_ATTR_RO(name); 626bc558a60SMark Brown 62701de19d0SDouglas Anderson static const char *regulator_opmode_to_str(int mode) 628414c70cbSLiam Girdwood { 629414c70cbSLiam Girdwood switch (mode) { 630414c70cbSLiam Girdwood case REGULATOR_MODE_FAST: 63101de19d0SDouglas Anderson return "fast"; 632414c70cbSLiam Girdwood case REGULATOR_MODE_NORMAL: 63301de19d0SDouglas Anderson return "normal"; 634414c70cbSLiam Girdwood case REGULATOR_MODE_IDLE: 63501de19d0SDouglas Anderson return "idle"; 636414c70cbSLiam Girdwood case REGULATOR_MODE_STANDBY: 63701de19d0SDouglas Anderson return "standby"; 638414c70cbSLiam Girdwood } 63901de19d0SDouglas Anderson return "unknown"; 64001de19d0SDouglas Anderson } 64101de19d0SDouglas Anderson 64201de19d0SDouglas Anderson static ssize_t regulator_print_opmode(char *buf, int mode) 64301de19d0SDouglas Anderson { 64401de19d0SDouglas Anderson return sprintf(buf, "%s\n", regulator_opmode_to_str(mode)); 645414c70cbSLiam Girdwood } 646414c70cbSLiam Girdwood 6474fca9545SDavid Brownell static ssize_t regulator_opmode_show(struct device *dev, 648414c70cbSLiam Girdwood struct device_attribute *attr, char *buf) 649414c70cbSLiam Girdwood { 650a5766f11SLiam Girdwood struct regulator_dev *rdev = dev_get_drvdata(dev); 651414c70cbSLiam Girdwood 6524fca9545SDavid Brownell return regulator_print_opmode(buf, _regulator_get_mode(rdev)); 6534fca9545SDavid Brownell } 6547ad68e2fSDavid Brownell static DEVICE_ATTR(opmode, 0444, regulator_opmode_show, NULL); 6554fca9545SDavid Brownell 6564fca9545SDavid Brownell static ssize_t regulator_print_state(char *buf, int state) 6574fca9545SDavid Brownell { 658414c70cbSLiam Girdwood if (state > 0) 659414c70cbSLiam Girdwood return sprintf(buf, "enabled\n"); 660414c70cbSLiam Girdwood else if (state == 0) 661414c70cbSLiam Girdwood return sprintf(buf, "disabled\n"); 662414c70cbSLiam Girdwood else 663414c70cbSLiam Girdwood return sprintf(buf, "unknown\n"); 664414c70cbSLiam Girdwood } 665414c70cbSLiam Girdwood 6664fca9545SDavid Brownell static ssize_t regulator_state_show(struct device *dev, 6674fca9545SDavid Brownell struct device_attribute *attr, char *buf) 6684fca9545SDavid Brownell { 6694fca9545SDavid Brownell struct regulator_dev *rdev = dev_get_drvdata(dev); 6709332546fSMark Brown ssize_t ret; 6714fca9545SDavid Brownell 67266cf9a7eSMaciej Purski regulator_lock(rdev); 6739332546fSMark Brown ret = regulator_print_state(buf, _regulator_is_enabled(rdev)); 67466cf9a7eSMaciej Purski regulator_unlock(rdev); 6759332546fSMark Brown 6769332546fSMark Brown return ret; 6774fca9545SDavid Brownell } 6787ad68e2fSDavid Brownell static DEVICE_ATTR(state, 0444, regulator_state_show, NULL); 6794fca9545SDavid Brownell 680853116a1SDavid Brownell static ssize_t regulator_status_show(struct device *dev, 681853116a1SDavid Brownell struct device_attribute *attr, char *buf) 682853116a1SDavid Brownell { 683853116a1SDavid Brownell struct regulator_dev *rdev = dev_get_drvdata(dev); 684853116a1SDavid Brownell int status; 685853116a1SDavid Brownell char *label; 686853116a1SDavid Brownell 687853116a1SDavid Brownell status = rdev->desc->ops->get_status(rdev); 688853116a1SDavid Brownell if (status < 0) 689853116a1SDavid Brownell return status; 690853116a1SDavid Brownell 691853116a1SDavid Brownell switch (status) { 692853116a1SDavid Brownell case REGULATOR_STATUS_OFF: 693853116a1SDavid Brownell label = "off"; 694853116a1SDavid Brownell break; 695853116a1SDavid Brownell case REGULATOR_STATUS_ON: 696853116a1SDavid Brownell label = "on"; 697853116a1SDavid Brownell break; 698853116a1SDavid Brownell case REGULATOR_STATUS_ERROR: 699853116a1SDavid Brownell label = "error"; 700853116a1SDavid Brownell break; 701853116a1SDavid Brownell case REGULATOR_STATUS_FAST: 702853116a1SDavid Brownell label = "fast"; 703853116a1SDavid Brownell break; 704853116a1SDavid Brownell case REGULATOR_STATUS_NORMAL: 705853116a1SDavid Brownell label = "normal"; 706853116a1SDavid Brownell break; 707853116a1SDavid Brownell case REGULATOR_STATUS_IDLE: 708853116a1SDavid Brownell label = "idle"; 709853116a1SDavid Brownell break; 710853116a1SDavid Brownell case REGULATOR_STATUS_STANDBY: 711853116a1SDavid Brownell label = "standby"; 712853116a1SDavid Brownell break; 713f59c8f9fSMark Brown case REGULATOR_STATUS_BYPASS: 714f59c8f9fSMark Brown label = "bypass"; 715f59c8f9fSMark Brown break; 7161beaf762SKrystian Garbaciak case REGULATOR_STATUS_UNDEFINED: 7171beaf762SKrystian Garbaciak label = "undefined"; 7181beaf762SKrystian Garbaciak break; 719853116a1SDavid Brownell default: 720853116a1SDavid Brownell return -ERANGE; 721853116a1SDavid Brownell } 722853116a1SDavid Brownell 723853116a1SDavid Brownell return sprintf(buf, "%s\n", label); 724853116a1SDavid Brownell } 725853116a1SDavid Brownell static DEVICE_ATTR(status, 0444, regulator_status_show, NULL); 726853116a1SDavid Brownell 727414c70cbSLiam Girdwood static ssize_t regulator_min_uA_show(struct device *dev, 728414c70cbSLiam Girdwood struct device_attribute *attr, char *buf) 729414c70cbSLiam Girdwood { 730a5766f11SLiam Girdwood struct regulator_dev *rdev = dev_get_drvdata(dev); 731414c70cbSLiam Girdwood 732414c70cbSLiam Girdwood if (!rdev->constraints) 733414c70cbSLiam Girdwood return sprintf(buf, "constraint not defined\n"); 734414c70cbSLiam Girdwood 735414c70cbSLiam Girdwood return sprintf(buf, "%d\n", rdev->constraints->min_uA); 736414c70cbSLiam Girdwood } 7377ad68e2fSDavid Brownell static DEVICE_ATTR(min_microamps, 0444, regulator_min_uA_show, NULL); 738414c70cbSLiam Girdwood 739414c70cbSLiam Girdwood static ssize_t regulator_max_uA_show(struct device *dev, 740414c70cbSLiam Girdwood struct device_attribute *attr, char *buf) 741414c70cbSLiam Girdwood { 742a5766f11SLiam Girdwood struct regulator_dev *rdev = dev_get_drvdata(dev); 743414c70cbSLiam Girdwood 744414c70cbSLiam Girdwood if (!rdev->constraints) 745414c70cbSLiam Girdwood return sprintf(buf, "constraint not defined\n"); 746414c70cbSLiam Girdwood 747414c70cbSLiam Girdwood return sprintf(buf, "%d\n", rdev->constraints->max_uA); 748414c70cbSLiam Girdwood } 7497ad68e2fSDavid Brownell static DEVICE_ATTR(max_microamps, 0444, regulator_max_uA_show, NULL); 750414c70cbSLiam Girdwood 751414c70cbSLiam Girdwood static ssize_t regulator_min_uV_show(struct device *dev, 752414c70cbSLiam Girdwood struct device_attribute *attr, char *buf) 753414c70cbSLiam Girdwood { 754a5766f11SLiam Girdwood struct regulator_dev *rdev = dev_get_drvdata(dev); 755414c70cbSLiam Girdwood 756414c70cbSLiam Girdwood if (!rdev->constraints) 757414c70cbSLiam Girdwood return sprintf(buf, "constraint not defined\n"); 758414c70cbSLiam Girdwood 759414c70cbSLiam Girdwood return sprintf(buf, "%d\n", rdev->constraints->min_uV); 760414c70cbSLiam Girdwood } 7617ad68e2fSDavid Brownell static DEVICE_ATTR(min_microvolts, 0444, regulator_min_uV_show, NULL); 762414c70cbSLiam Girdwood 763414c70cbSLiam Girdwood static ssize_t regulator_max_uV_show(struct device *dev, 764414c70cbSLiam Girdwood struct device_attribute *attr, char *buf) 765414c70cbSLiam Girdwood { 766a5766f11SLiam Girdwood struct regulator_dev *rdev = dev_get_drvdata(dev); 767414c70cbSLiam Girdwood 768414c70cbSLiam Girdwood if (!rdev->constraints) 769414c70cbSLiam Girdwood return sprintf(buf, "constraint not defined\n"); 770414c70cbSLiam Girdwood 771414c70cbSLiam Girdwood return sprintf(buf, "%d\n", rdev->constraints->max_uV); 772414c70cbSLiam Girdwood } 7737ad68e2fSDavid Brownell static DEVICE_ATTR(max_microvolts, 0444, regulator_max_uV_show, NULL); 774414c70cbSLiam Girdwood 775414c70cbSLiam Girdwood static ssize_t regulator_total_uA_show(struct device *dev, 776414c70cbSLiam Girdwood struct device_attribute *attr, char *buf) 777414c70cbSLiam Girdwood { 778a5766f11SLiam Girdwood struct regulator_dev *rdev = dev_get_drvdata(dev); 779414c70cbSLiam Girdwood struct regulator *regulator; 780414c70cbSLiam Girdwood int uA = 0; 781414c70cbSLiam Girdwood 78266cf9a7eSMaciej Purski regulator_lock(rdev); 7835451781dSDouglas Anderson list_for_each_entry(regulator, &rdev->consumer_list, list) { 7845451781dSDouglas Anderson if (regulator->enable_count) 785414c70cbSLiam Girdwood uA += regulator->uA_load; 7865451781dSDouglas Anderson } 78766cf9a7eSMaciej Purski regulator_unlock(rdev); 788414c70cbSLiam Girdwood return sprintf(buf, "%d\n", uA); 789414c70cbSLiam Girdwood } 7907ad68e2fSDavid Brownell static DEVICE_ATTR(requested_microamps, 0444, regulator_total_uA_show, NULL); 791414c70cbSLiam Girdwood 792587cea27SGreg Kroah-Hartman static ssize_t num_users_show(struct device *dev, struct device_attribute *attr, 793587cea27SGreg Kroah-Hartman char *buf) 794414c70cbSLiam Girdwood { 795a5766f11SLiam Girdwood struct regulator_dev *rdev = dev_get_drvdata(dev); 796414c70cbSLiam Girdwood return sprintf(buf, "%d\n", rdev->use_count); 797414c70cbSLiam Girdwood } 798587cea27SGreg Kroah-Hartman static DEVICE_ATTR_RO(num_users); 799414c70cbSLiam Girdwood 800587cea27SGreg Kroah-Hartman static ssize_t type_show(struct device *dev, struct device_attribute *attr, 801587cea27SGreg Kroah-Hartman char *buf) 802414c70cbSLiam Girdwood { 803a5766f11SLiam Girdwood struct regulator_dev *rdev = dev_get_drvdata(dev); 804414c70cbSLiam Girdwood 805414c70cbSLiam Girdwood switch (rdev->desc->type) { 806414c70cbSLiam Girdwood case REGULATOR_VOLTAGE: 807414c70cbSLiam Girdwood return sprintf(buf, "voltage\n"); 808414c70cbSLiam Girdwood case REGULATOR_CURRENT: 809414c70cbSLiam Girdwood return sprintf(buf, "current\n"); 810414c70cbSLiam Girdwood } 811414c70cbSLiam Girdwood return sprintf(buf, "unknown\n"); 812414c70cbSLiam Girdwood } 813587cea27SGreg Kroah-Hartman static DEVICE_ATTR_RO(type); 814414c70cbSLiam Girdwood 815414c70cbSLiam Girdwood static ssize_t regulator_suspend_mem_uV_show(struct device *dev, 816414c70cbSLiam Girdwood struct device_attribute *attr, char *buf) 817414c70cbSLiam Girdwood { 818a5766f11SLiam Girdwood struct regulator_dev *rdev = dev_get_drvdata(dev); 819414c70cbSLiam Girdwood 820414c70cbSLiam Girdwood return sprintf(buf, "%d\n", rdev->constraints->state_mem.uV); 821414c70cbSLiam Girdwood } 8227ad68e2fSDavid Brownell static DEVICE_ATTR(suspend_mem_microvolts, 0444, 8237ad68e2fSDavid Brownell regulator_suspend_mem_uV_show, NULL); 824414c70cbSLiam Girdwood 825414c70cbSLiam Girdwood static ssize_t regulator_suspend_disk_uV_show(struct device *dev, 826414c70cbSLiam Girdwood struct device_attribute *attr, char *buf) 827414c70cbSLiam Girdwood { 828a5766f11SLiam Girdwood struct regulator_dev *rdev = dev_get_drvdata(dev); 829414c70cbSLiam Girdwood 830414c70cbSLiam Girdwood return sprintf(buf, "%d\n", rdev->constraints->state_disk.uV); 831414c70cbSLiam Girdwood } 8327ad68e2fSDavid Brownell static DEVICE_ATTR(suspend_disk_microvolts, 0444, 8337ad68e2fSDavid Brownell regulator_suspend_disk_uV_show, NULL); 834414c70cbSLiam Girdwood 835414c70cbSLiam Girdwood static ssize_t regulator_suspend_standby_uV_show(struct device *dev, 836414c70cbSLiam Girdwood struct device_attribute *attr, char *buf) 837414c70cbSLiam Girdwood { 838a5766f11SLiam Girdwood struct regulator_dev *rdev = dev_get_drvdata(dev); 839414c70cbSLiam Girdwood 840414c70cbSLiam Girdwood return sprintf(buf, "%d\n", rdev->constraints->state_standby.uV); 841414c70cbSLiam Girdwood } 8427ad68e2fSDavid Brownell static DEVICE_ATTR(suspend_standby_microvolts, 0444, 8437ad68e2fSDavid Brownell regulator_suspend_standby_uV_show, NULL); 844414c70cbSLiam Girdwood 845414c70cbSLiam Girdwood static ssize_t regulator_suspend_mem_mode_show(struct device *dev, 846414c70cbSLiam Girdwood struct device_attribute *attr, char *buf) 847414c70cbSLiam Girdwood { 848a5766f11SLiam Girdwood struct regulator_dev *rdev = dev_get_drvdata(dev); 849414c70cbSLiam Girdwood 8504fca9545SDavid Brownell return regulator_print_opmode(buf, 8514fca9545SDavid Brownell rdev->constraints->state_mem.mode); 852414c70cbSLiam Girdwood } 8537ad68e2fSDavid Brownell static DEVICE_ATTR(suspend_mem_mode, 0444, 8547ad68e2fSDavid Brownell regulator_suspend_mem_mode_show, NULL); 855414c70cbSLiam Girdwood 856414c70cbSLiam Girdwood static ssize_t regulator_suspend_disk_mode_show(struct device *dev, 857414c70cbSLiam Girdwood struct device_attribute *attr, char *buf) 858414c70cbSLiam Girdwood { 859a5766f11SLiam Girdwood struct regulator_dev *rdev = dev_get_drvdata(dev); 860414c70cbSLiam Girdwood 8614fca9545SDavid Brownell return regulator_print_opmode(buf, 8624fca9545SDavid Brownell rdev->constraints->state_disk.mode); 863414c70cbSLiam Girdwood } 8647ad68e2fSDavid Brownell static DEVICE_ATTR(suspend_disk_mode, 0444, 8657ad68e2fSDavid Brownell regulator_suspend_disk_mode_show, NULL); 866414c70cbSLiam Girdwood 867414c70cbSLiam Girdwood static ssize_t regulator_suspend_standby_mode_show(struct device *dev, 868414c70cbSLiam Girdwood struct device_attribute *attr, char *buf) 869414c70cbSLiam Girdwood { 870a5766f11SLiam Girdwood struct regulator_dev *rdev = dev_get_drvdata(dev); 871414c70cbSLiam Girdwood 8724fca9545SDavid Brownell return regulator_print_opmode(buf, 8734fca9545SDavid Brownell rdev->constraints->state_standby.mode); 874414c70cbSLiam Girdwood } 8757ad68e2fSDavid Brownell static DEVICE_ATTR(suspend_standby_mode, 0444, 8767ad68e2fSDavid Brownell regulator_suspend_standby_mode_show, NULL); 877414c70cbSLiam Girdwood 878414c70cbSLiam Girdwood static ssize_t regulator_suspend_mem_state_show(struct device *dev, 879414c70cbSLiam Girdwood struct device_attribute *attr, char *buf) 880414c70cbSLiam Girdwood { 881a5766f11SLiam Girdwood struct regulator_dev *rdev = dev_get_drvdata(dev); 882414c70cbSLiam Girdwood 8834fca9545SDavid Brownell return regulator_print_state(buf, 8844fca9545SDavid Brownell rdev->constraints->state_mem.enabled); 885414c70cbSLiam Girdwood } 8867ad68e2fSDavid Brownell static DEVICE_ATTR(suspend_mem_state, 0444, 8877ad68e2fSDavid Brownell regulator_suspend_mem_state_show, NULL); 888414c70cbSLiam Girdwood 889414c70cbSLiam Girdwood static ssize_t regulator_suspend_disk_state_show(struct device *dev, 890414c70cbSLiam Girdwood struct device_attribute *attr, char *buf) 891414c70cbSLiam Girdwood { 892a5766f11SLiam Girdwood struct regulator_dev *rdev = dev_get_drvdata(dev); 893414c70cbSLiam Girdwood 8944fca9545SDavid Brownell return regulator_print_state(buf, 8954fca9545SDavid Brownell rdev->constraints->state_disk.enabled); 896414c70cbSLiam Girdwood } 8977ad68e2fSDavid Brownell static DEVICE_ATTR(suspend_disk_state, 0444, 8987ad68e2fSDavid Brownell regulator_suspend_disk_state_show, NULL); 899414c70cbSLiam Girdwood 900414c70cbSLiam Girdwood static ssize_t regulator_suspend_standby_state_show(struct device *dev, 901414c70cbSLiam Girdwood struct device_attribute *attr, char *buf) 902414c70cbSLiam Girdwood { 903a5766f11SLiam Girdwood struct regulator_dev *rdev = dev_get_drvdata(dev); 904414c70cbSLiam Girdwood 9054fca9545SDavid Brownell return regulator_print_state(buf, 9064fca9545SDavid Brownell rdev->constraints->state_standby.enabled); 907414c70cbSLiam Girdwood } 9087ad68e2fSDavid Brownell static DEVICE_ATTR(suspend_standby_state, 0444, 9097ad68e2fSDavid Brownell regulator_suspend_standby_state_show, NULL); 910bc558a60SMark Brown 911f59c8f9fSMark Brown static ssize_t regulator_bypass_show(struct device *dev, 912f59c8f9fSMark Brown struct device_attribute *attr, char *buf) 913f59c8f9fSMark Brown { 914f59c8f9fSMark Brown struct regulator_dev *rdev = dev_get_drvdata(dev); 915f59c8f9fSMark Brown const char *report; 916f59c8f9fSMark Brown bool bypass; 917f59c8f9fSMark Brown int ret; 918f59c8f9fSMark Brown 919f59c8f9fSMark Brown ret = rdev->desc->ops->get_bypass(rdev, &bypass); 920f59c8f9fSMark Brown 921f59c8f9fSMark Brown if (ret != 0) 922f59c8f9fSMark Brown report = "unknown"; 923f59c8f9fSMark Brown else if (bypass) 924f59c8f9fSMark Brown report = "enabled"; 925f59c8f9fSMark Brown else 926f59c8f9fSMark Brown report = "disabled"; 927f59c8f9fSMark Brown 928f59c8f9fSMark Brown return sprintf(buf, "%s\n", report); 929f59c8f9fSMark Brown } 930f59c8f9fSMark Brown static DEVICE_ATTR(bypass, 0444, 931f59c8f9fSMark Brown regulator_bypass_show, NULL); 9327ad68e2fSDavid Brownell 933414c70cbSLiam Girdwood /* Calculate the new optimum regulator operating mode based on the new total 934414c70cbSLiam Girdwood * consumer load. All locks held by caller */ 9358460ef38SBjorn Andersson static int drms_uA_update(struct regulator_dev *rdev) 936414c70cbSLiam Girdwood { 937414c70cbSLiam Girdwood struct regulator *sibling; 938414c70cbSLiam Girdwood int current_uA = 0, output_uV, input_uV, err; 939414c70cbSLiam Girdwood unsigned int mode; 940414c70cbSLiam Girdwood 9418460ef38SBjorn Andersson /* 9428460ef38SBjorn Andersson * first check to see if we can set modes at all, otherwise just 9438460ef38SBjorn Andersson * tell the consumer everything is OK. 9448460ef38SBjorn Andersson */ 94574a569eeSMarc Gonzalez if (!regulator_ops_is_valid(rdev, REGULATOR_CHANGE_DRMS)) { 94674a569eeSMarc Gonzalez rdev_dbg(rdev, "DRMS operation not allowed\n"); 9478460ef38SBjorn Andersson return 0; 94874a569eeSMarc Gonzalez } 9498460ef38SBjorn Andersson 9508f4490e0SBjorn Andersson if (!rdev->desc->ops->get_optimum_mode && 9518f4490e0SBjorn Andersson !rdev->desc->ops->set_load) 9528460ef38SBjorn Andersson return 0; 9538460ef38SBjorn Andersson 9548f4490e0SBjorn Andersson if (!rdev->desc->ops->set_mode && 9558f4490e0SBjorn Andersson !rdev->desc->ops->set_load) 9568460ef38SBjorn Andersson return -EINVAL; 957414c70cbSLiam Girdwood 95857776617SJoonwoo Park /* calc total requested load */ 9595451781dSDouglas Anderson list_for_each_entry(sibling, &rdev->consumer_list, list) { 9605451781dSDouglas Anderson if (sibling->enable_count) 96157776617SJoonwoo Park current_uA += sibling->uA_load; 9625451781dSDouglas Anderson } 96357776617SJoonwoo Park 96457776617SJoonwoo Park current_uA += rdev->constraints->system_load; 96557776617SJoonwoo Park 96657776617SJoonwoo Park if (rdev->desc->ops->set_load) { 96757776617SJoonwoo Park /* set the optimum mode for our new total regulator load */ 96857776617SJoonwoo Park err = rdev->desc->ops->set_load(rdev, current_uA); 96957776617SJoonwoo Park if (err < 0) 97061aab5adSMichał Mirosław rdev_err(rdev, "failed to set load %d: %pe\n", 97161aab5adSMichał Mirosław current_uA, ERR_PTR(err)); 97257776617SJoonwoo Park } else { 973414c70cbSLiam Girdwood /* get output voltage */ 974d22b85a1SDmitry Osipenko output_uV = regulator_get_voltage_rdev(rdev); 9758460ef38SBjorn Andersson if (output_uV <= 0) { 9768460ef38SBjorn Andersson rdev_err(rdev, "invalid output voltage found\n"); 9778460ef38SBjorn Andersson return -EINVAL; 9788460ef38SBjorn Andersson } 979414c70cbSLiam Girdwood 980414c70cbSLiam Girdwood /* get input voltage */ 9811bf5a1f8SMark Brown input_uV = 0; 9821bf5a1f8SMark Brown if (rdev->supply) 9833f24f5adSAxel Lin input_uV = regulator_get_voltage(rdev->supply); 9841bf5a1f8SMark Brown if (input_uV <= 0) 985414c70cbSLiam Girdwood input_uV = rdev->constraints->input_uV; 9868460ef38SBjorn Andersson if (input_uV <= 0) { 9878460ef38SBjorn Andersson rdev_err(rdev, "invalid input voltage found\n"); 9888460ef38SBjorn Andersson return -EINVAL; 9898460ef38SBjorn Andersson } 990414c70cbSLiam Girdwood 991414c70cbSLiam Girdwood /* now get the optimum mode for our new total regulator load */ 992414c70cbSLiam Girdwood mode = rdev->desc->ops->get_optimum_mode(rdev, input_uV, 993414c70cbSLiam Girdwood output_uV, current_uA); 994414c70cbSLiam Girdwood 995414c70cbSLiam Girdwood /* check the new mode is allowed */ 9962c608234SMark Brown err = regulator_mode_constrain(rdev, &mode); 9978460ef38SBjorn Andersson if (err < 0) { 99861aab5adSMichał Mirosław rdev_err(rdev, "failed to get optimum mode @ %d uA %d -> %d uV: %pe\n", 99961aab5adSMichał Mirosław current_uA, input_uV, output_uV, ERR_PTR(err)); 10008460ef38SBjorn Andersson return err; 10018460ef38SBjorn Andersson } 10028460ef38SBjorn Andersson 10038460ef38SBjorn Andersson err = rdev->desc->ops->set_mode(rdev, mode); 10048460ef38SBjorn Andersson if (err < 0) 100561aab5adSMichał Mirosław rdev_err(rdev, "failed to set optimum mode %x: %pe\n", 100661aab5adSMichał Mirosław mode, ERR_PTR(err)); 10078f4490e0SBjorn Andersson } 10088460ef38SBjorn Andersson 10098460ef38SBjorn Andersson return err; 1010414c70cbSLiam Girdwood } 1011414c70cbSLiam Girdwood 10120955f5beSStephen Boyd static int __suspend_set_state(struct regulator_dev *rdev, 10130955f5beSStephen Boyd const struct regulator_state *rstate) 1014414c70cbSLiam Girdwood { 1015414c70cbSLiam Girdwood int ret = 0; 1016638f85c5SMark Brown 101772069f99SChunyan Zhang if (rstate->enabled == ENABLE_IN_SUSPEND && 101872069f99SChunyan Zhang rdev->desc->ops->set_suspend_enable) 1019414c70cbSLiam Girdwood ret = rdev->desc->ops->set_suspend_enable(rdev); 102072069f99SChunyan Zhang else if (rstate->enabled == DISABLE_IN_SUSPEND && 102172069f99SChunyan Zhang rdev->desc->ops->set_suspend_disable) 1022414c70cbSLiam Girdwood ret = rdev->desc->ops->set_suspend_disable(rdev); 10238ac0e95dSAxel Lin else /* OK if set_suspend_enable or set_suspend_disable is NULL */ 10248ac0e95dSAxel Lin ret = 0; 10258ac0e95dSAxel Lin 1026414c70cbSLiam Girdwood if (ret < 0) { 102761aab5adSMichał Mirosław rdev_err(rdev, "failed to enabled/disable: %pe\n", ERR_PTR(ret)); 1028414c70cbSLiam Girdwood return ret; 1029414c70cbSLiam Girdwood } 1030414c70cbSLiam Girdwood 1031414c70cbSLiam Girdwood if (rdev->desc->ops->set_suspend_voltage && rstate->uV > 0) { 1032414c70cbSLiam Girdwood ret = rdev->desc->ops->set_suspend_voltage(rdev, rstate->uV); 1033414c70cbSLiam Girdwood if (ret < 0) { 103461aab5adSMichał Mirosław rdev_err(rdev, "failed to set voltage: %pe\n", ERR_PTR(ret)); 1035414c70cbSLiam Girdwood return ret; 1036414c70cbSLiam Girdwood } 1037414c70cbSLiam Girdwood } 1038414c70cbSLiam Girdwood 1039414c70cbSLiam Girdwood if (rdev->desc->ops->set_suspend_mode && rstate->mode > 0) { 1040414c70cbSLiam Girdwood ret = rdev->desc->ops->set_suspend_mode(rdev, rstate->mode); 1041414c70cbSLiam Girdwood if (ret < 0) { 104261aab5adSMichał Mirosław rdev_err(rdev, "failed to set mode: %pe\n", ERR_PTR(ret)); 1043414c70cbSLiam Girdwood return ret; 1044414c70cbSLiam Girdwood } 1045414c70cbSLiam Girdwood } 1046f7efad10SChunyan Zhang 1047414c70cbSLiam Girdwood return ret; 1048414c70cbSLiam Girdwood } 1049414c70cbSLiam Girdwood 10500955f5beSStephen Boyd static int suspend_set_initial_state(struct regulator_dev *rdev) 10510955f5beSStephen Boyd { 10520955f5beSStephen Boyd const struct regulator_state *rstate; 10530955f5beSStephen Boyd 10540955f5beSStephen Boyd rstate = regulator_get_suspend_state_check(rdev, 10550955f5beSStephen Boyd rdev->constraints->initial_state); 10560955f5beSStephen Boyd if (!rstate) 10570955f5beSStephen Boyd return 0; 10580955f5beSStephen Boyd 10590955f5beSStephen Boyd return __suspend_set_state(rdev, rstate); 10600955f5beSStephen Boyd } 10610955f5beSStephen Boyd 1062c845f21aSGeert Uytterhoeven #if defined(DEBUG) || defined(CONFIG_DYNAMIC_DEBUG) 1063c845f21aSGeert Uytterhoeven static void print_constraints_debug(struct regulator_dev *rdev) 1064414c70cbSLiam Girdwood { 1065414c70cbSLiam Girdwood struct regulation_constraints *constraints = rdev->constraints; 1066a7068e39SStefan Wahren char buf[160] = ""; 10675751a99fSStefan Wahren size_t len = sizeof(buf) - 1; 10688f031b48SMark Brown int count = 0; 10698f031b48SMark Brown int ret; 1070414c70cbSLiam Girdwood 10718f031b48SMark Brown if (constraints->min_uV && constraints->max_uV) { 1072414c70cbSLiam Girdwood if (constraints->min_uV == constraints->max_uV) 10735751a99fSStefan Wahren count += scnprintf(buf + count, len - count, "%d mV ", 1074414c70cbSLiam Girdwood constraints->min_uV / 1000); 1075414c70cbSLiam Girdwood else 10765751a99fSStefan Wahren count += scnprintf(buf + count, len - count, 10775751a99fSStefan Wahren "%d <--> %d mV ", 1078414c70cbSLiam Girdwood constraints->min_uV / 1000, 1079414c70cbSLiam Girdwood constraints->max_uV / 1000); 10808f031b48SMark Brown } 10818f031b48SMark Brown 10828f031b48SMark Brown if (!constraints->min_uV || 10838f031b48SMark Brown constraints->min_uV != constraints->max_uV) { 1084d22b85a1SDmitry Osipenko ret = regulator_get_voltage_rdev(rdev); 10858f031b48SMark Brown if (ret > 0) 10865751a99fSStefan Wahren count += scnprintf(buf + count, len - count, 10875751a99fSStefan Wahren "at %d mV ", ret / 1000); 10888f031b48SMark Brown } 10898f031b48SMark Brown 1090bf5892a8SMark Brown if (constraints->uV_offset) 10915751a99fSStefan Wahren count += scnprintf(buf + count, len - count, "%dmV offset ", 1092bf5892a8SMark Brown constraints->uV_offset / 1000); 1093bf5892a8SMark Brown 10948f031b48SMark Brown if (constraints->min_uA && constraints->max_uA) { 1095414c70cbSLiam Girdwood if (constraints->min_uA == constraints->max_uA) 10965751a99fSStefan Wahren count += scnprintf(buf + count, len - count, "%d mA ", 1097414c70cbSLiam Girdwood constraints->min_uA / 1000); 1098414c70cbSLiam Girdwood else 10995751a99fSStefan Wahren count += scnprintf(buf + count, len - count, 11005751a99fSStefan Wahren "%d <--> %d mA ", 1101414c70cbSLiam Girdwood constraints->min_uA / 1000, 1102414c70cbSLiam Girdwood constraints->max_uA / 1000); 1103414c70cbSLiam Girdwood } 11048f031b48SMark Brown 11058f031b48SMark Brown if (!constraints->min_uA || 11068f031b48SMark Brown constraints->min_uA != constraints->max_uA) { 11078f031b48SMark Brown ret = _regulator_get_current_limit(rdev); 11088f031b48SMark Brown if (ret > 0) 11095751a99fSStefan Wahren count += scnprintf(buf + count, len - count, 11105751a99fSStefan Wahren "at %d mA ", ret / 1000); 11118f031b48SMark Brown } 11128f031b48SMark Brown 1113414c70cbSLiam Girdwood if (constraints->valid_modes_mask & REGULATOR_MODE_FAST) 11145751a99fSStefan Wahren count += scnprintf(buf + count, len - count, "fast "); 1115414c70cbSLiam Girdwood if (constraints->valid_modes_mask & REGULATOR_MODE_NORMAL) 11165751a99fSStefan Wahren count += scnprintf(buf + count, len - count, "normal "); 1117414c70cbSLiam Girdwood if (constraints->valid_modes_mask & REGULATOR_MODE_IDLE) 11185751a99fSStefan Wahren count += scnprintf(buf + count, len - count, "idle "); 1119414c70cbSLiam Girdwood if (constraints->valid_modes_mask & REGULATOR_MODE_STANDBY) 11205751a99fSStefan Wahren count += scnprintf(buf + count, len - count, "standby "); 1121414c70cbSLiam Girdwood 1122215b8b05SUwe Kleine-König if (!count) 112399ad5f6eSMichał Mirosław count = scnprintf(buf, len, "no parameters"); 112499ad5f6eSMichał Mirosław else 112599ad5f6eSMichał Mirosław --count; 112699ad5f6eSMichał Mirosław 112799ad5f6eSMichał Mirosław count += scnprintf(buf + count, len - count, ", %s", 112899ad5f6eSMichał Mirosław _regulator_is_enabled(rdev) ? "enabled" : "disabled"); 1129215b8b05SUwe Kleine-König 1130194dbaefSMark Brown rdev_dbg(rdev, "%s\n", buf); 1131c845f21aSGeert Uytterhoeven } 1132c845f21aSGeert Uytterhoeven #else /* !DEBUG && !CONFIG_DYNAMIC_DEBUG */ 1133c845f21aSGeert Uytterhoeven static inline void print_constraints_debug(struct regulator_dev *rdev) {} 1134c845f21aSGeert Uytterhoeven #endif /* !DEBUG && !CONFIG_DYNAMIC_DEBUG */ 1135c845f21aSGeert Uytterhoeven 1136c845f21aSGeert Uytterhoeven static void print_constraints(struct regulator_dev *rdev) 1137c845f21aSGeert Uytterhoeven { 1138c845f21aSGeert Uytterhoeven struct regulation_constraints *constraints = rdev->constraints; 1139c845f21aSGeert Uytterhoeven 1140c845f21aSGeert Uytterhoeven print_constraints_debug(rdev); 11414a682922SMark Brown 11424a682922SMark Brown if ((constraints->min_uV != constraints->max_uV) && 11438a34e979SWEN Pingbo !regulator_ops_is_valid(rdev, REGULATOR_CHANGE_VOLTAGE)) 11444a682922SMark Brown rdev_warn(rdev, 11454a682922SMark Brown "Voltage range but no REGULATOR_CHANGE_VOLTAGE\n"); 1146414c70cbSLiam Girdwood } 1147414c70cbSLiam Girdwood 1148e79055d6SMark Brown static int machine_constraints_voltage(struct regulator_dev *rdev, 11491083c393SMark Brown struct regulation_constraints *constraints) 1150e79055d6SMark Brown { 1151272e2315SGuodong Xu const struct regulator_ops *ops = rdev->desc->ops; 1152af5866c9SMark Brown int ret; 1153af5866c9SMark Brown 1154af5866c9SMark Brown /* do we need to apply the constraint voltage */ 1155af5866c9SMark Brown if (rdev->constraints->apply_uV && 1156fa93fd4eSMark Brown rdev->constraints->min_uV && rdev->constraints->max_uV) { 1157fa93fd4eSMark Brown int target_min, target_max; 1158d22b85a1SDmitry Osipenko int current_uV = regulator_get_voltage_rdev(rdev); 115984b3a7c9SDouglas Anderson 116084b3a7c9SDouglas Anderson if (current_uV == -ENOTRECOVERABLE) { 116148f1b4efSKrzysztof Kozlowski /* This regulator can't be read and must be initialized */ 116284b3a7c9SDouglas Anderson rdev_info(rdev, "Setting %d-%duV\n", 116384b3a7c9SDouglas Anderson rdev->constraints->min_uV, 116484b3a7c9SDouglas Anderson rdev->constraints->max_uV); 116584b3a7c9SDouglas Anderson _regulator_do_set_voltage(rdev, 116684b3a7c9SDouglas Anderson rdev->constraints->min_uV, 116784b3a7c9SDouglas Anderson rdev->constraints->max_uV); 1168d22b85a1SDmitry Osipenko current_uV = regulator_get_voltage_rdev(rdev); 116984b3a7c9SDouglas Anderson } 117084b3a7c9SDouglas Anderson 1171064d5cd1SAlban Bedel if (current_uV < 0) { 117269d58839SNishanth Menon rdev_err(rdev, 117361aab5adSMichał Mirosław "failed to get the current voltage: %pe\n", 117461aab5adSMichał Mirosław ERR_PTR(current_uV)); 1175064d5cd1SAlban Bedel return current_uV; 1176064d5cd1SAlban Bedel } 1177fa93fd4eSMark Brown 1178fa93fd4eSMark Brown /* 1179fa93fd4eSMark Brown * If we're below the minimum voltage move up to the 1180fa93fd4eSMark Brown * minimum voltage, if we're above the maximum voltage 1181fa93fd4eSMark Brown * then move down to the maximum. 1182fa93fd4eSMark Brown */ 1183fa93fd4eSMark Brown target_min = current_uV; 1184fa93fd4eSMark Brown target_max = current_uV; 1185fa93fd4eSMark Brown 1186fa93fd4eSMark Brown if (current_uV < rdev->constraints->min_uV) { 1187fa93fd4eSMark Brown target_min = rdev->constraints->min_uV; 1188fa93fd4eSMark Brown target_max = rdev->constraints->min_uV; 1189fa93fd4eSMark Brown } 1190fa93fd4eSMark Brown 1191fa93fd4eSMark Brown if (current_uV > rdev->constraints->max_uV) { 1192fa93fd4eSMark Brown target_min = rdev->constraints->max_uV; 1193fa93fd4eSMark Brown target_max = rdev->constraints->max_uV; 1194fa93fd4eSMark Brown } 1195fa93fd4eSMark Brown 1196fa93fd4eSMark Brown if (target_min != current_uV || target_max != current_uV) { 119745a91e8fSMark Brown rdev_info(rdev, "Bringing %duV into %d-%duV\n", 119845a91e8fSMark Brown current_uV, target_min, target_max); 1199064d5cd1SAlban Bedel ret = _regulator_do_set_voltage( 1200fa93fd4eSMark Brown rdev, target_min, target_max); 1201af5866c9SMark Brown if (ret < 0) { 1202064d5cd1SAlban Bedel rdev_err(rdev, 120361aab5adSMichał Mirosław "failed to apply %d-%duV constraint: %pe\n", 120461aab5adSMichał Mirosław target_min, target_max, ERR_PTR(ret)); 1205af5866c9SMark Brown return ret; 1206af5866c9SMark Brown } 1207af5866c9SMark Brown } 1208064d5cd1SAlban Bedel } 1209e79055d6SMark Brown 1210e79055d6SMark Brown /* constrain machine-level voltage specs to fit 1211e79055d6SMark Brown * the actual range supported by this regulator. 1212e79055d6SMark Brown */ 1213e79055d6SMark Brown if (ops->list_voltage && rdev->desc->n_voltages) { 1214e79055d6SMark Brown int count = rdev->desc->n_voltages; 1215e79055d6SMark Brown int i; 1216e79055d6SMark Brown int min_uV = INT_MAX; 1217e79055d6SMark Brown int max_uV = INT_MIN; 1218e79055d6SMark Brown int cmin = constraints->min_uV; 1219e79055d6SMark Brown int cmax = constraints->max_uV; 1220e79055d6SMark Brown 1221e79055d6SMark Brown /* it's safe to autoconfigure fixed-voltage supplies 1222e79055d6SMark Brown and the constraints are used by list_voltage. */ 1223e79055d6SMark Brown if (count == 1 && !cmin) { 1224e79055d6SMark Brown cmin = 1; 1225e79055d6SMark Brown cmax = INT_MAX; 1226e79055d6SMark Brown constraints->min_uV = cmin; 1227e79055d6SMark Brown constraints->max_uV = cmax; 1228e79055d6SMark Brown } 1229e79055d6SMark Brown 1230e79055d6SMark Brown /* voltage constraints are optional */ 1231e79055d6SMark Brown if ((cmin == 0) && (cmax == 0)) 1232e79055d6SMark Brown return 0; 1233e79055d6SMark Brown 1234e79055d6SMark Brown /* else require explicit machine-level constraints */ 1235e79055d6SMark Brown if (cmin <= 0 || cmax <= 0 || cmax < cmin) { 12365da84fd9SJoe Perches rdev_err(rdev, "invalid voltage constraints\n"); 1237e79055d6SMark Brown return -EINVAL; 1238e79055d6SMark Brown } 1239e79055d6SMark Brown 12406d30fc51SCristian Marussi /* no need to loop voltages if range is continuous */ 12416d30fc51SCristian Marussi if (rdev->desc->continuous_voltage_range) 12426d30fc51SCristian Marussi return 0; 12436d30fc51SCristian Marussi 1244e79055d6SMark Brown /* initial: [cmin..cmax] valid, [min_uV..max_uV] not */ 1245e79055d6SMark Brown for (i = 0; i < count; i++) { 1246e79055d6SMark Brown int value; 1247e79055d6SMark Brown 1248e79055d6SMark Brown value = ops->list_voltage(rdev, i); 1249e79055d6SMark Brown if (value <= 0) 1250e79055d6SMark Brown continue; 1251e79055d6SMark Brown 1252e79055d6SMark Brown /* maybe adjust [min_uV..max_uV] */ 1253e79055d6SMark Brown if (value >= cmin && value < min_uV) 1254e79055d6SMark Brown min_uV = value; 1255e79055d6SMark Brown if (value <= cmax && value > max_uV) 1256e79055d6SMark Brown max_uV = value; 1257e79055d6SMark Brown } 1258e79055d6SMark Brown 1259e79055d6SMark Brown /* final: [min_uV..max_uV] valid iff constraints valid */ 1260e79055d6SMark Brown if (max_uV < min_uV) { 1261fff15befSMark Brown rdev_err(rdev, 1262fff15befSMark Brown "unsupportable voltage constraints %u-%uuV\n", 1263fff15befSMark Brown min_uV, max_uV); 1264e79055d6SMark Brown return -EINVAL; 1265e79055d6SMark Brown } 1266e79055d6SMark Brown 1267e79055d6SMark Brown /* use regulator's subset of machine constraints */ 1268e79055d6SMark Brown if (constraints->min_uV < min_uV) { 12695da84fd9SJoe Perches rdev_dbg(rdev, "override min_uV, %d -> %d\n", 12705da84fd9SJoe Perches constraints->min_uV, min_uV); 1271e79055d6SMark Brown constraints->min_uV = min_uV; 1272e79055d6SMark Brown } 1273e79055d6SMark Brown if (constraints->max_uV > max_uV) { 12745da84fd9SJoe Perches rdev_dbg(rdev, "override max_uV, %d -> %d\n", 12755da84fd9SJoe Perches constraints->max_uV, max_uV); 1276e79055d6SMark Brown constraints->max_uV = max_uV; 1277e79055d6SMark Brown } 1278e79055d6SMark Brown } 1279e79055d6SMark Brown 1280e79055d6SMark Brown return 0; 1281e79055d6SMark Brown } 1282e79055d6SMark Brown 1283f8c1700dSLaxman Dewangan static int machine_constraints_current(struct regulator_dev *rdev, 1284f8c1700dSLaxman Dewangan struct regulation_constraints *constraints) 1285f8c1700dSLaxman Dewangan { 1286272e2315SGuodong Xu const struct regulator_ops *ops = rdev->desc->ops; 1287f8c1700dSLaxman Dewangan int ret; 1288f8c1700dSLaxman Dewangan 1289f8c1700dSLaxman Dewangan if (!constraints->min_uA && !constraints->max_uA) 1290f8c1700dSLaxman Dewangan return 0; 1291f8c1700dSLaxman Dewangan 1292f8c1700dSLaxman Dewangan if (constraints->min_uA > constraints->max_uA) { 1293f8c1700dSLaxman Dewangan rdev_err(rdev, "Invalid current constraints\n"); 1294f8c1700dSLaxman Dewangan return -EINVAL; 1295f8c1700dSLaxman Dewangan } 1296f8c1700dSLaxman Dewangan 1297f8c1700dSLaxman Dewangan if (!ops->set_current_limit || !ops->get_current_limit) { 1298f8c1700dSLaxman Dewangan rdev_warn(rdev, "Operation of current configuration missing\n"); 1299f8c1700dSLaxman Dewangan return 0; 1300f8c1700dSLaxman Dewangan } 1301f8c1700dSLaxman Dewangan 1302f8c1700dSLaxman Dewangan /* Set regulator current in constraints range */ 1303f8c1700dSLaxman Dewangan ret = ops->set_current_limit(rdev, constraints->min_uA, 1304f8c1700dSLaxman Dewangan constraints->max_uA); 1305f8c1700dSLaxman Dewangan if (ret < 0) { 1306f8c1700dSLaxman Dewangan rdev_err(rdev, "Failed to set current constraint, %d\n", ret); 1307f8c1700dSLaxman Dewangan return ret; 1308f8c1700dSLaxman Dewangan } 1309f8c1700dSLaxman Dewangan 1310f8c1700dSLaxman Dewangan return 0; 1311f8c1700dSLaxman Dewangan } 1312f8c1700dSLaxman Dewangan 131330c21971SMarkus Pargmann static int _regulator_do_enable(struct regulator_dev *rdev); 131430c21971SMarkus Pargmann 1315a5766f11SLiam Girdwood /** 1316a5766f11SLiam Girdwood * set_machine_constraints - sets regulator constraints 131769279fb9SMark Brown * @rdev: regulator source 1318c8e7e464SMark Brown * @constraints: constraints to apply 1319a5766f11SLiam Girdwood * 1320a5766f11SLiam Girdwood * Allows platform initialisation code to define and constrain 1321a5766f11SLiam Girdwood * regulator circuits e.g. valid voltage/current ranges, etc. NOTE: 1322a5766f11SLiam Girdwood * Constraints *must* be set by platform code in order for some 1323a5766f11SLiam Girdwood * regulator operations to proceed i.e. set_voltage, set_current_limit, 1324a5766f11SLiam Girdwood * set_mode. 1325a5766f11SLiam Girdwood */ 1326a5766f11SLiam Girdwood static int set_machine_constraints(struct regulator_dev *rdev, 1327f8c12fe3SMark Brown const struct regulation_constraints *constraints) 1328a5766f11SLiam Girdwood { 1329a5766f11SLiam Girdwood int ret = 0; 1330272e2315SGuodong Xu const struct regulator_ops *ops = rdev->desc->ops; 1331e06f5b4fSMark Brown 13329a8f5e07SMark Brown if (constraints) 1333f8c12fe3SMark Brown rdev->constraints = kmemdup(constraints, sizeof(*constraints), 1334f8c12fe3SMark Brown GFP_KERNEL); 13359a8f5e07SMark Brown else 13369a8f5e07SMark Brown rdev->constraints = kzalloc(sizeof(*constraints), 13379a8f5e07SMark Brown GFP_KERNEL); 1338f8c12fe3SMark Brown if (!rdev->constraints) 1339f8c12fe3SMark Brown return -ENOMEM; 1340af5866c9SMark Brown 1341f8c12fe3SMark Brown ret = machine_constraints_voltage(rdev, rdev->constraints); 1342e79055d6SMark Brown if (ret != 0) 13436333ef46SCharles Keepax return ret; 13443e2b9abdSMark Brown 1345f8c1700dSLaxman Dewangan ret = machine_constraints_current(rdev, rdev->constraints); 1346f8c1700dSLaxman Dewangan if (ret != 0) 13476333ef46SCharles Keepax return ret; 1348f8c1700dSLaxman Dewangan 134936e4f839SStephen Boyd if (rdev->constraints->ilim_uA && ops->set_input_current_limit) { 135036e4f839SStephen Boyd ret = ops->set_input_current_limit(rdev, 135136e4f839SStephen Boyd rdev->constraints->ilim_uA); 135236e4f839SStephen Boyd if (ret < 0) { 135361aab5adSMichał Mirosław rdev_err(rdev, "failed to set input limit: %pe\n", ERR_PTR(ret)); 13546333ef46SCharles Keepax return ret; 135536e4f839SStephen Boyd } 135636e4f839SStephen Boyd } 135736e4f839SStephen Boyd 1358a5766f11SLiam Girdwood /* do we need to setup our suspend state */ 13599a8f5e07SMark Brown if (rdev->constraints->initial_state) { 13600955f5beSStephen Boyd ret = suspend_set_initial_state(rdev); 1361e06f5b4fSMark Brown if (ret < 0) { 136261aab5adSMichał Mirosław rdev_err(rdev, "failed to set suspend state: %pe\n", ERR_PTR(ret)); 13636333ef46SCharles Keepax return ret; 1364e06f5b4fSMark Brown } 1365e06f5b4fSMark Brown } 1366a5766f11SLiam Girdwood 13679a8f5e07SMark Brown if (rdev->constraints->initial_mode) { 1368a308466cSMark Brown if (!ops->set_mode) { 13695da84fd9SJoe Perches rdev_err(rdev, "no set_mode operation\n"); 13706333ef46SCharles Keepax return -EINVAL; 1371a308466cSMark Brown } 1372a308466cSMark Brown 1373f8c12fe3SMark Brown ret = ops->set_mode(rdev, rdev->constraints->initial_mode); 1374a308466cSMark Brown if (ret < 0) { 137561aab5adSMichał Mirosław rdev_err(rdev, "failed to set initial mode: %pe\n", ERR_PTR(ret)); 13766333ef46SCharles Keepax return ret; 1377a308466cSMark Brown } 1378fa94e48eSDouglas Anderson } else if (rdev->constraints->system_load) { 1379fa94e48eSDouglas Anderson /* 1380fa94e48eSDouglas Anderson * We'll only apply the initial system load if an 1381fa94e48eSDouglas Anderson * initial mode wasn't specified. 1382fa94e48eSDouglas Anderson */ 1383fa94e48eSDouglas Anderson drms_uA_update(rdev); 1384a308466cSMark Brown } 1385a308466cSMark Brown 13861653ccf4SYadwinder Singh Brar if ((rdev->constraints->ramp_delay || rdev->constraints->ramp_disable) 13871653ccf4SYadwinder Singh Brar && ops->set_ramp_delay) { 13886f0b2c69SYadwinder Singh Brar ret = ops->set_ramp_delay(rdev, rdev->constraints->ramp_delay); 13896f0b2c69SYadwinder Singh Brar if (ret < 0) { 139061aab5adSMichał Mirosław rdev_err(rdev, "failed to set ramp_delay: %pe\n", ERR_PTR(ret)); 13916333ef46SCharles Keepax return ret; 13926f0b2c69SYadwinder Singh Brar } 13936f0b2c69SYadwinder Singh Brar } 13946f0b2c69SYadwinder Singh Brar 139523c779b9SStephen Boyd if (rdev->constraints->pull_down && ops->set_pull_down) { 139623c779b9SStephen Boyd ret = ops->set_pull_down(rdev); 139723c779b9SStephen Boyd if (ret < 0) { 139861aab5adSMichał Mirosław rdev_err(rdev, "failed to set pull down: %pe\n", ERR_PTR(ret)); 13996333ef46SCharles Keepax return ret; 140023c779b9SStephen Boyd } 140123c779b9SStephen Boyd } 140223c779b9SStephen Boyd 140357f66b78SStephen Boyd if (rdev->constraints->soft_start && ops->set_soft_start) { 140457f66b78SStephen Boyd ret = ops->set_soft_start(rdev); 140557f66b78SStephen Boyd if (ret < 0) { 140661aab5adSMichał Mirosław rdev_err(rdev, "failed to set soft start: %pe\n", ERR_PTR(ret)); 14076333ef46SCharles Keepax return ret; 140857f66b78SStephen Boyd } 140957f66b78SStephen Boyd } 141057f66b78SStephen Boyd 14113a003baeSStephen Boyd if (rdev->constraints->over_current_protection 14123a003baeSStephen Boyd && ops->set_over_current_protection) { 14133a003baeSStephen Boyd ret = ops->set_over_current_protection(rdev); 14143a003baeSStephen Boyd if (ret < 0) { 141561aab5adSMichał Mirosław rdev_err(rdev, "failed to set over current protection: %pe\n", 141661aab5adSMichał Mirosław ERR_PTR(ret)); 14176333ef46SCharles Keepax return ret; 14183a003baeSStephen Boyd } 14193a003baeSStephen Boyd } 14203a003baeSStephen Boyd 1421670666b9SLaxman Dewangan if (rdev->constraints->active_discharge && ops->set_active_discharge) { 1422670666b9SLaxman Dewangan bool ad_state = (rdev->constraints->active_discharge == 1423670666b9SLaxman Dewangan REGULATOR_ACTIVE_DISCHARGE_ENABLE) ? true : false; 1424670666b9SLaxman Dewangan 1425670666b9SLaxman Dewangan ret = ops->set_active_discharge(rdev, ad_state); 1426670666b9SLaxman Dewangan if (ret < 0) { 142761aab5adSMichał Mirosław rdev_err(rdev, "failed to set active discharge: %pe\n", ERR_PTR(ret)); 1428670666b9SLaxman Dewangan return ret; 1429670666b9SLaxman Dewangan } 1430670666b9SLaxman Dewangan } 1431670666b9SLaxman Dewangan 14322bb16663SOlliver Schinagl /* If the constraints say the regulator should be on at this point 14332bb16663SOlliver Schinagl * and we have control then make sure it is enabled. 14342bb16663SOlliver Schinagl */ 14352bb16663SOlliver Schinagl if (rdev->constraints->always_on || rdev->constraints->boot_on) { 143605f224caSDouglas Anderson if (rdev->supply) { 143705f224caSDouglas Anderson ret = regulator_enable(rdev->supply); 143805f224caSDouglas Anderson if (ret < 0) { 143905f224caSDouglas Anderson _regulator_put(rdev->supply); 144005f224caSDouglas Anderson rdev->supply = NULL; 144105f224caSDouglas Anderson return ret; 144205f224caSDouglas Anderson } 144305f224caSDouglas Anderson } 144405f224caSDouglas Anderson 14452bb16663SOlliver Schinagl ret = _regulator_do_enable(rdev); 14462bb16663SOlliver Schinagl if (ret < 0 && ret != -EINVAL) { 144761aab5adSMichał Mirosław rdev_err(rdev, "failed to enable: %pe\n", ERR_PTR(ret)); 14482bb16663SOlliver Schinagl return ret; 14492bb16663SOlliver Schinagl } 1450089b3f61SPascal Paillet 1451089b3f61SPascal Paillet if (rdev->constraints->always_on) 145205f224caSDouglas Anderson rdev->use_count++; 14532bb16663SOlliver Schinagl } 14542bb16663SOlliver Schinagl 1455a5766f11SLiam Girdwood print_constraints(rdev); 14561a6958e7SAxel Lin return 0; 1457a5766f11SLiam Girdwood } 1458a5766f11SLiam Girdwood 1459a5766f11SLiam Girdwood /** 1460a5766f11SLiam Girdwood * set_supply - set regulator supply regulator 146169279fb9SMark Brown * @rdev: regulator name 146269279fb9SMark Brown * @supply_rdev: supply regulator name 1463a5766f11SLiam Girdwood * 1464a5766f11SLiam Girdwood * Called by platform initialisation code to set the supply regulator for this 1465a5766f11SLiam Girdwood * regulator. This ensures that a regulators supply will also be enabled by the 1466a5766f11SLiam Girdwood * core if it's child is enabled. 1467a5766f11SLiam Girdwood */ 1468a5766f11SLiam Girdwood static int set_supply(struct regulator_dev *rdev, 1469a5766f11SLiam Girdwood struct regulator_dev *supply_rdev) 1470a5766f11SLiam Girdwood { 1471a5766f11SLiam Girdwood int err; 1472a5766f11SLiam Girdwood 14733801b86aSMark Brown rdev_info(rdev, "supplied by %s\n", rdev_get_name(supply_rdev)); 14743801b86aSMark Brown 1475e2c09ae7SJavier Martinez Canillas if (!try_module_get(supply_rdev->owner)) 1476e2c09ae7SJavier Martinez Canillas return -ENODEV; 1477e2c09ae7SJavier Martinez Canillas 14783801b86aSMark Brown rdev->supply = create_regulator(supply_rdev, &rdev->dev, "SUPPLY"); 147932c78de8SAxel Lin if (rdev->supply == NULL) { 148032c78de8SAxel Lin err = -ENOMEM; 1481a5766f11SLiam Girdwood return err; 1482a5766f11SLiam Girdwood } 148357ad526aSLaxman Dewangan supply_rdev->open_count++; 1484a5766f11SLiam Girdwood 14853801b86aSMark Brown return 0; 14863801b86aSMark Brown } 14873801b86aSMark Brown 1488a5766f11SLiam Girdwood /** 148906c63f93SRandy Dunlap * set_consumer_device_supply - Bind a regulator to a symbolic supply 149069279fb9SMark Brown * @rdev: regulator source 149140f9244fSMark Brown * @consumer_dev_name: dev_name() string for device supply applies to 1492a5766f11SLiam Girdwood * @supply: symbolic name for supply 1493a5766f11SLiam Girdwood * 1494a5766f11SLiam Girdwood * Allows platform initialisation code to map physical regulator 1495a5766f11SLiam Girdwood * sources to symbolic names for supplies for use by devices. Devices 1496a5766f11SLiam Girdwood * should use these symbolic names to request regulators, avoiding the 1497a5766f11SLiam Girdwood * need to provide board-specific regulator names as platform data. 1498a5766f11SLiam Girdwood */ 1499a5766f11SLiam Girdwood static int set_consumer_device_supply(struct regulator_dev *rdev, 1500737f360dSMark Brown const char *consumer_dev_name, 150140f9244fSMark Brown const char *supply) 1502a5766f11SLiam Girdwood { 15035c065401SMichał Mirosław struct regulator_map *node, *new_node; 15049ed2099eSMark Brown int has_dev; 1505a5766f11SLiam Girdwood 1506a5766f11SLiam Girdwood if (supply == NULL) 1507a5766f11SLiam Girdwood return -EINVAL; 1508a5766f11SLiam Girdwood 15099ed2099eSMark Brown if (consumer_dev_name != NULL) 15109ed2099eSMark Brown has_dev = 1; 15119ed2099eSMark Brown else 15129ed2099eSMark Brown has_dev = 0; 15139ed2099eSMark Brown 15145c065401SMichał Mirosław new_node = kzalloc(sizeof(struct regulator_map), GFP_KERNEL); 15155c065401SMichał Mirosław if (new_node == NULL) 15165c065401SMichał Mirosław return -ENOMEM; 15175c065401SMichał Mirosław 15185c065401SMichał Mirosław new_node->regulator = rdev; 15195c065401SMichał Mirosław new_node->supply = supply; 15205c065401SMichał Mirosław 15215c065401SMichał Mirosław if (has_dev) { 15225c065401SMichał Mirosław new_node->dev_name = kstrdup(consumer_dev_name, GFP_KERNEL); 15235c065401SMichał Mirosław if (new_node->dev_name == NULL) { 15245c065401SMichał Mirosław kfree(new_node); 15255c065401SMichał Mirosław return -ENOMEM; 15265c065401SMichał Mirosław } 15275c065401SMichał Mirosław } 15285c065401SMichał Mirosław 15295c065401SMichał Mirosław mutex_lock(®ulator_list_mutex); 15306001e13cSDavid Brownell list_for_each_entry(node, ®ulator_map_list, list) { 153123b5cc2aSJani Nikula if (node->dev_name && consumer_dev_name) { 153223b5cc2aSJani Nikula if (strcmp(node->dev_name, consumer_dev_name) != 0) 15336001e13cSDavid Brownell continue; 153423b5cc2aSJani Nikula } else if (node->dev_name || consumer_dev_name) { 153523b5cc2aSJani Nikula continue; 153623b5cc2aSJani Nikula } 153723b5cc2aSJani Nikula 15386001e13cSDavid Brownell if (strcmp(node->supply, supply) != 0) 15396001e13cSDavid Brownell continue; 15406001e13cSDavid Brownell 1541737f360dSMark Brown pr_debug("%s: %s/%s is '%s' supply; fail %s/%s\n", 1542737f360dSMark Brown consumer_dev_name, 15436001e13cSDavid Brownell dev_name(&node->regulator->dev), 15446001e13cSDavid Brownell node->regulator->desc->name, 15456001e13cSDavid Brownell supply, 15461083c393SMark Brown dev_name(&rdev->dev), rdev_get_name(rdev)); 15475c065401SMichał Mirosław goto fail; 15486001e13cSDavid Brownell } 15496001e13cSDavid Brownell 15505c065401SMichał Mirosław list_add(&new_node->list, ®ulator_map_list); 15515c065401SMichał Mirosław mutex_unlock(®ulator_list_mutex); 1552a5766f11SLiam Girdwood 1553a5766f11SLiam Girdwood return 0; 15545c065401SMichał Mirosław 15555c065401SMichał Mirosław fail: 15565c065401SMichał Mirosław mutex_unlock(®ulator_list_mutex); 15575c065401SMichał Mirosław kfree(new_node->dev_name); 15585c065401SMichał Mirosław kfree(new_node); 15595c065401SMichał Mirosław return -EBUSY; 1560a5766f11SLiam Girdwood } 1561a5766f11SLiam Girdwood 15620f1d747bSMike Rapoport static void unset_regulator_supplies(struct regulator_dev *rdev) 15630f1d747bSMike Rapoport { 15640f1d747bSMike Rapoport struct regulator_map *node, *n; 15650f1d747bSMike Rapoport 15660f1d747bSMike Rapoport list_for_each_entry_safe(node, n, ®ulator_map_list, list) { 15670f1d747bSMike Rapoport if (rdev == node->regulator) { 15680f1d747bSMike Rapoport list_del(&node->list); 156940f9244fSMark Brown kfree(node->dev_name); 15700f1d747bSMike Rapoport kfree(node); 15710f1d747bSMike Rapoport } 15720f1d747bSMike Rapoport } 15730f1d747bSMike Rapoport } 15740f1d747bSMike Rapoport 15752d80a91bSRichard Fitzgerald #ifdef CONFIG_DEBUG_FS 15762d80a91bSRichard Fitzgerald static ssize_t constraint_flags_read_file(struct file *file, 15772d80a91bSRichard Fitzgerald char __user *user_buf, 15782d80a91bSRichard Fitzgerald size_t count, loff_t *ppos) 15792d80a91bSRichard Fitzgerald { 15802d80a91bSRichard Fitzgerald const struct regulator *regulator = file->private_data; 15812d80a91bSRichard Fitzgerald const struct regulation_constraints *c = regulator->rdev->constraints; 15822d80a91bSRichard Fitzgerald char *buf; 15832d80a91bSRichard Fitzgerald ssize_t ret; 15842d80a91bSRichard Fitzgerald 15852d80a91bSRichard Fitzgerald if (!c) 15862d80a91bSRichard Fitzgerald return 0; 15872d80a91bSRichard Fitzgerald 15882d80a91bSRichard Fitzgerald buf = kmalloc(PAGE_SIZE, GFP_KERNEL); 15892d80a91bSRichard Fitzgerald if (!buf) 15902d80a91bSRichard Fitzgerald return -ENOMEM; 15912d80a91bSRichard Fitzgerald 15922d80a91bSRichard Fitzgerald ret = snprintf(buf, PAGE_SIZE, 15932d80a91bSRichard Fitzgerald "always_on: %u\n" 15942d80a91bSRichard Fitzgerald "boot_on: %u\n" 15952d80a91bSRichard Fitzgerald "apply_uV: %u\n" 15962d80a91bSRichard Fitzgerald "ramp_disable: %u\n" 15972d80a91bSRichard Fitzgerald "soft_start: %u\n" 15982d80a91bSRichard Fitzgerald "pull_down: %u\n" 15992d80a91bSRichard Fitzgerald "over_current_protection: %u\n", 16002d80a91bSRichard Fitzgerald c->always_on, 16012d80a91bSRichard Fitzgerald c->boot_on, 16022d80a91bSRichard Fitzgerald c->apply_uV, 16032d80a91bSRichard Fitzgerald c->ramp_disable, 16042d80a91bSRichard Fitzgerald c->soft_start, 16052d80a91bSRichard Fitzgerald c->pull_down, 16062d80a91bSRichard Fitzgerald c->over_current_protection); 16072d80a91bSRichard Fitzgerald 16082d80a91bSRichard Fitzgerald ret = simple_read_from_buffer(user_buf, count, ppos, buf, ret); 16092d80a91bSRichard Fitzgerald kfree(buf); 16102d80a91bSRichard Fitzgerald 16112d80a91bSRichard Fitzgerald return ret; 16122d80a91bSRichard Fitzgerald } 16132d80a91bSRichard Fitzgerald 16142d80a91bSRichard Fitzgerald #endif 16152d80a91bSRichard Fitzgerald 16162d80a91bSRichard Fitzgerald static const struct file_operations constraint_flags_fops = { 16172d80a91bSRichard Fitzgerald #ifdef CONFIG_DEBUG_FS 16182d80a91bSRichard Fitzgerald .open = simple_open, 16192d80a91bSRichard Fitzgerald .read = constraint_flags_read_file, 16202d80a91bSRichard Fitzgerald .llseek = default_llseek, 16212d80a91bSRichard Fitzgerald #endif 16222d80a91bSRichard Fitzgerald }; 16232d80a91bSRichard Fitzgerald 1624f5726ae3SMark Brown #define REG_STR_SIZE 64 1625414c70cbSLiam Girdwood 1626414c70cbSLiam Girdwood static struct regulator *create_regulator(struct regulator_dev *rdev, 1627414c70cbSLiam Girdwood struct device *dev, 1628414c70cbSLiam Girdwood const char *supply_name) 1629414c70cbSLiam Girdwood { 1630414c70cbSLiam Girdwood struct regulator *regulator; 163187fe29b6SMichał Mirosław int err; 1632414c70cbSLiam Girdwood 163387fe29b6SMichał Mirosław if (dev) { 163487fe29b6SMichał Mirosław char buf[REG_STR_SIZE]; 163587fe29b6SMichał Mirosław int size; 163687fe29b6SMichał Mirosław 163787fe29b6SMichał Mirosław size = snprintf(buf, REG_STR_SIZE, "%s-%s", 163887fe29b6SMichał Mirosław dev->kobj.name, supply_name); 163987fe29b6SMichał Mirosław if (size >= REG_STR_SIZE) 1640414c70cbSLiam Girdwood return NULL; 1641414c70cbSLiam Girdwood 164287fe29b6SMichał Mirosław supply_name = kstrdup(buf, GFP_KERNEL); 164387fe29b6SMichał Mirosław if (supply_name == NULL) 164487fe29b6SMichał Mirosław return NULL; 164587fe29b6SMichał Mirosław } else { 164687fe29b6SMichał Mirosław supply_name = kstrdup_const(supply_name, GFP_KERNEL); 164787fe29b6SMichał Mirosław if (supply_name == NULL) 164887fe29b6SMichał Mirosław return NULL; 164987fe29b6SMichał Mirosław } 165087fe29b6SMichał Mirosław 165187fe29b6SMichał Mirosław regulator = kzalloc(sizeof(*regulator), GFP_KERNEL); 165287fe29b6SMichał Mirosław if (regulator == NULL) { 165387fe29b6SMichał Mirosław kfree(supply_name); 165487fe29b6SMichał Mirosław return NULL; 165587fe29b6SMichał Mirosław } 165687fe29b6SMichał Mirosław 1657414c70cbSLiam Girdwood regulator->rdev = rdev; 165887fe29b6SMichał Mirosław regulator->supply_name = supply_name; 165987fe29b6SMichał Mirosław 166087fe29b6SMichał Mirosław regulator_lock(rdev); 1661414c70cbSLiam Girdwood list_add(®ulator->list, &rdev->consumer_list); 166287fe29b6SMichał Mirosław regulator_unlock(rdev); 1663414c70cbSLiam Girdwood 1664414c70cbSLiam Girdwood if (dev) { 1665e2c98eafSShawn Guo regulator->dev = dev; 1666e2c98eafSShawn Guo 1667222cc7b1SMark Brown /* Add a link to the device sysfs entry */ 1668ff268b56SStephen Boyd err = sysfs_create_link_nowarn(&rdev->dev.kobj, &dev->kobj, 166987fe29b6SMichał Mirosław supply_name); 1670414c70cbSLiam Girdwood if (err) { 167161aab5adSMichał Mirosław rdev_dbg(rdev, "could not add device link %s: %pe\n", 167261aab5adSMichał Mirosław dev->kobj.name, ERR_PTR(err)); 1673222cc7b1SMark Brown /* non-fatal */ 1674414c70cbSLiam Girdwood } 1675414c70cbSLiam Girdwood } 16765de70519SMark Brown 167787fe29b6SMichał Mirosław regulator->debugfs = debugfs_create_dir(supply_name, 16785de70519SMark Brown rdev->debugfs); 167924751434SStephen Boyd if (!regulator->debugfs) { 1680ad3a942bSStephen Boyd rdev_dbg(rdev, "Failed to create debugfs directory\n"); 16815de70519SMark Brown } else { 16825de70519SMark Brown debugfs_create_u32("uA_load", 0444, regulator->debugfs, 16835de70519SMark Brown ®ulator->uA_load); 16845de70519SMark Brown debugfs_create_u32("min_uV", 0444, regulator->debugfs, 1685c360a6dfSChunyan Zhang ®ulator->voltage[PM_SUSPEND_ON].min_uV); 16865de70519SMark Brown debugfs_create_u32("max_uV", 0444, regulator->debugfs, 1687c360a6dfSChunyan Zhang ®ulator->voltage[PM_SUSPEND_ON].max_uV); 16882d80a91bSRichard Fitzgerald debugfs_create_file("constraint_flags", 0444, 16892d80a91bSRichard Fitzgerald regulator->debugfs, regulator, 16902d80a91bSRichard Fitzgerald &constraint_flags_fops); 16915de70519SMark Brown } 16925de70519SMark Brown 16936492bc1bSMark Brown /* 16946492bc1bSMark Brown * Check now if the regulator is an always on regulator - if 16956492bc1bSMark Brown * it is then we don't need to do nearly so much work for 16966492bc1bSMark Brown * enable/disable calls. 16976492bc1bSMark Brown */ 16988a34e979SWEN Pingbo if (!regulator_ops_is_valid(rdev, REGULATOR_CHANGE_STATUS) && 16996492bc1bSMark Brown _regulator_is_enabled(rdev)) 17006492bc1bSMark Brown regulator->always_on = true; 17016492bc1bSMark Brown 1702414c70cbSLiam Girdwood return regulator; 1703414c70cbSLiam Girdwood } 1704414c70cbSLiam Girdwood 170531aae2beSMark Brown static int _regulator_get_enable_time(struct regulator_dev *rdev) 170631aae2beSMark Brown { 170700c877c6SLaxman Dewangan if (rdev->constraints && rdev->constraints->enable_time) 170800c877c6SLaxman Dewangan return rdev->constraints->enable_time; 170968ce3a44SAxel Lin if (rdev->desc->ops->enable_time) 171031aae2beSMark Brown return rdev->desc->ops->enable_time(rdev); 171168ce3a44SAxel Lin return rdev->desc->enable_time; 171231aae2beSMark Brown } 171331aae2beSMark Brown 1714a06ccd9cSCharles Keepax static struct regulator_supply_alias *regulator_find_supply_alias( 1715a06ccd9cSCharles Keepax struct device *dev, const char *supply) 1716a06ccd9cSCharles Keepax { 1717a06ccd9cSCharles Keepax struct regulator_supply_alias *map; 1718a06ccd9cSCharles Keepax 1719a06ccd9cSCharles Keepax list_for_each_entry(map, ®ulator_supply_alias_list, list) 1720a06ccd9cSCharles Keepax if (map->src_dev == dev && strcmp(map->src_supply, supply) == 0) 1721a06ccd9cSCharles Keepax return map; 1722a06ccd9cSCharles Keepax 1723a06ccd9cSCharles Keepax return NULL; 1724a06ccd9cSCharles Keepax } 1725a06ccd9cSCharles Keepax 1726a06ccd9cSCharles Keepax static void regulator_supply_alias(struct device **dev, const char **supply) 1727a06ccd9cSCharles Keepax { 1728a06ccd9cSCharles Keepax struct regulator_supply_alias *map; 1729a06ccd9cSCharles Keepax 1730a06ccd9cSCharles Keepax map = regulator_find_supply_alias(*dev, *supply); 1731a06ccd9cSCharles Keepax if (map) { 1732a06ccd9cSCharles Keepax dev_dbg(*dev, "Mapping supply %s to %s,%s\n", 1733a06ccd9cSCharles Keepax *supply, map->alias_supply, 1734a06ccd9cSCharles Keepax dev_name(map->alias_dev)); 1735a06ccd9cSCharles Keepax *dev = map->alias_dev; 1736a06ccd9cSCharles Keepax *supply = map->alias_supply; 1737a06ccd9cSCharles Keepax } 1738a06ccd9cSCharles Keepax } 1739a06ccd9cSCharles Keepax 174085f3b431STomeu Vizoso static int regulator_match(struct device *dev, const void *data) 174185f3b431STomeu Vizoso { 174285f3b431STomeu Vizoso struct regulator_dev *r = dev_to_rdev(dev); 174385f3b431STomeu Vizoso 174485f3b431STomeu Vizoso return strcmp(rdev_get_name(r), data) == 0; 174585f3b431STomeu Vizoso } 174685f3b431STomeu Vizoso 174785f3b431STomeu Vizoso static struct regulator_dev *regulator_lookup_by_name(const char *name) 174885f3b431STomeu Vizoso { 174985f3b431STomeu Vizoso struct device *dev; 175085f3b431STomeu Vizoso 175185f3b431STomeu Vizoso dev = class_find_device(®ulator_class, NULL, name, regulator_match); 175285f3b431STomeu Vizoso 175385f3b431STomeu Vizoso return dev ? dev_to_rdev(dev) : NULL; 175485f3b431STomeu Vizoso } 175585f3b431STomeu Vizoso 175685f3b431STomeu Vizoso /** 175785f3b431STomeu Vizoso * regulator_dev_lookup - lookup a regulator device. 175885f3b431STomeu Vizoso * @dev: device for regulator "consumer". 175985f3b431STomeu Vizoso * @supply: Supply name or regulator ID. 176085f3b431STomeu Vizoso * 176185f3b431STomeu Vizoso * If successful, returns a struct regulator_dev that corresponds to the name 1762163478daSDmitry Torokhov * @supply and with the embedded struct device refcount incremented by one. 1763163478daSDmitry Torokhov * The refcount must be dropped by calling put_device(). 1764163478daSDmitry Torokhov * On failure one of the following ERR-PTR-encoded values is returned: 1765163478daSDmitry Torokhov * -ENODEV if lookup fails permanently, -EPROBE_DEFER if lookup could succeed 1766163478daSDmitry Torokhov * in the future. 176785f3b431STomeu Vizoso */ 176869511a45SRajendra Nayak static struct regulator_dev *regulator_dev_lookup(struct device *dev, 1769163478daSDmitry Torokhov const char *supply) 177069511a45SRajendra Nayak { 177106217197SCharles Keepax struct regulator_dev *r = NULL; 177269511a45SRajendra Nayak struct device_node *node; 1773576ca436SMark Brown struct regulator_map *map; 1774576ca436SMark Brown const char *devname = NULL; 177569511a45SRajendra Nayak 1776a06ccd9cSCharles Keepax regulator_supply_alias(&dev, &supply); 1777a06ccd9cSCharles Keepax 177869511a45SRajendra Nayak /* first do a dt based lookup */ 177969511a45SRajendra Nayak if (dev && dev->of_node) { 178069511a45SRajendra Nayak node = of_get_regulator(dev, supply); 17816d191a5fSMark Brown if (node) { 178285f3b431STomeu Vizoso r = of_find_regulator_by_node(node); 178385f3b431STomeu Vizoso if (r) 178469511a45SRajendra Nayak return r; 1785163478daSDmitry Torokhov 17866d191a5fSMark Brown /* 1787163478daSDmitry Torokhov * We have a node, but there is no device. 1788163478daSDmitry Torokhov * assume it has not registered yet. 17896d191a5fSMark Brown */ 1790163478daSDmitry Torokhov return ERR_PTR(-EPROBE_DEFER); 17916d191a5fSMark Brown } 179269511a45SRajendra Nayak } 179369511a45SRajendra Nayak 179469511a45SRajendra Nayak /* if not found, try doing it non-dt way */ 1795576ca436SMark Brown if (dev) 1796576ca436SMark Brown devname = dev_name(dev); 1797576ca436SMark Brown 179885f3b431STomeu Vizoso mutex_lock(®ulator_list_mutex); 1799576ca436SMark Brown list_for_each_entry(map, ®ulator_map_list, list) { 1800576ca436SMark Brown /* If the mapping has a device set up it must match */ 1801576ca436SMark Brown if (map->dev_name && 1802576ca436SMark Brown (!devname || strcmp(map->dev_name, devname))) 1803576ca436SMark Brown continue; 1804576ca436SMark Brown 180585f3b431STomeu Vizoso if (strcmp(map->supply, supply) == 0 && 180685f3b431STomeu Vizoso get_device(&map->regulator->dev)) { 1807163478daSDmitry Torokhov r = map->regulator; 1808163478daSDmitry Torokhov break; 1809576ca436SMark Brown } 181085f3b431STomeu Vizoso } 181185f3b431STomeu Vizoso mutex_unlock(®ulator_list_mutex); 1812576ca436SMark Brown 1813163478daSDmitry Torokhov if (r) 1814163478daSDmitry Torokhov return r; 1815163478daSDmitry Torokhov 181606217197SCharles Keepax r = regulator_lookup_by_name(supply); 181706217197SCharles Keepax if (r) 181806217197SCharles Keepax return r; 181906217197SCharles Keepax 1820163478daSDmitry Torokhov return ERR_PTR(-ENODEV); 182169511a45SRajendra Nayak } 182269511a45SRajendra Nayak 18236261b06dSBjorn Andersson static int regulator_resolve_supply(struct regulator_dev *rdev) 18246261b06dSBjorn Andersson { 18256261b06dSBjorn Andersson struct regulator_dev *r; 18266261b06dSBjorn Andersson struct device *dev = rdev->dev.parent; 18276261b06dSBjorn Andersson int ret; 18286261b06dSBjorn Andersson 182948f1b4efSKrzysztof Kozlowski /* No supply to resolve? */ 18306261b06dSBjorn Andersson if (!rdev->supply_name) 18316261b06dSBjorn Andersson return 0; 18326261b06dSBjorn Andersson 18336261b06dSBjorn Andersson /* Supply already resolved? */ 18346261b06dSBjorn Andersson if (rdev->supply) 18356261b06dSBjorn Andersson return 0; 18366261b06dSBjorn Andersson 1837163478daSDmitry Torokhov r = regulator_dev_lookup(dev, rdev->supply_name); 1838163478daSDmitry Torokhov if (IS_ERR(r)) { 1839163478daSDmitry Torokhov ret = PTR_ERR(r); 1840163478daSDmitry Torokhov 184106423121SMark Brown /* Did the lookup explicitly defer for us? */ 184206423121SMark Brown if (ret == -EPROBE_DEFER) 184306423121SMark Brown return ret; 184406423121SMark Brown 18459f7e25edSMark Brown if (have_full_constraints()) { 18469f7e25edSMark Brown r = dummy_regulator_rdev; 184785f3b431STomeu Vizoso get_device(&r->dev); 18489f7e25edSMark Brown } else { 18496261b06dSBjorn Andersson dev_err(dev, "Failed to resolve %s-supply for %s\n", 18506261b06dSBjorn Andersson rdev->supply_name, rdev->desc->name); 18516261b06dSBjorn Andersson return -EPROBE_DEFER; 18526261b06dSBjorn Andersson } 18539f7e25edSMark Brown } 18546261b06dSBjorn Andersson 185566d228a2SJon Hunter /* 185666d228a2SJon Hunter * If the supply's parent device is not the same as the 185766d228a2SJon Hunter * regulator's parent device, then ensure the parent device 185866d228a2SJon Hunter * is bound before we resolve the supply, in case the parent 185966d228a2SJon Hunter * device get probe deferred and unregisters the supply. 186066d228a2SJon Hunter */ 186166d228a2SJon Hunter if (r->dev.parent && r->dev.parent != rdev->dev.parent) { 186266d228a2SJon Hunter if (!device_is_bound(r->dev.parent)) { 186366d228a2SJon Hunter put_device(&r->dev); 186466d228a2SJon Hunter return -EPROBE_DEFER; 186566d228a2SJon Hunter } 186666d228a2SJon Hunter } 186766d228a2SJon Hunter 18686261b06dSBjorn Andersson /* Recursively resolve the supply of the supply */ 18696261b06dSBjorn Andersson ret = regulator_resolve_supply(r); 187085f3b431STomeu Vizoso if (ret < 0) { 187185f3b431STomeu Vizoso put_device(&r->dev); 18726261b06dSBjorn Andersson return ret; 187385f3b431STomeu Vizoso } 18746261b06dSBjorn Andersson 18756261b06dSBjorn Andersson ret = set_supply(rdev, r); 187685f3b431STomeu Vizoso if (ret < 0) { 187785f3b431STomeu Vizoso put_device(&r->dev); 18786261b06dSBjorn Andersson return ret; 187985f3b431STomeu Vizoso } 18806261b06dSBjorn Andersson 188105f224caSDouglas Anderson /* 188205f224caSDouglas Anderson * In set_machine_constraints() we may have turned this regulator on 188305f224caSDouglas Anderson * but we couldn't propagate to the supply if it hadn't been resolved 188405f224caSDouglas Anderson * yet. Do it now. 188505f224caSDouglas Anderson */ 188605f224caSDouglas Anderson if (rdev->use_count) { 18876261b06dSBjorn Andersson ret = regulator_enable(rdev->supply); 188836a1f1b6SJavier Martinez Canillas if (ret < 0) { 188936a1f1b6SJavier Martinez Canillas _regulator_put(rdev->supply); 18908e5356a7SJon Hunter rdev->supply = NULL; 18916261b06dSBjorn Andersson return ret; 18926261b06dSBjorn Andersson } 189336a1f1b6SJavier Martinez Canillas } 18946261b06dSBjorn Andersson 18956261b06dSBjorn Andersson return 0; 18966261b06dSBjorn Andersson } 18976261b06dSBjorn Andersson 18985ffbd136SMark Brown /* Internal regulator request function */ 1899a8bd42a9SDmitry Torokhov struct regulator *_regulator_get(struct device *dev, const char *id, 1900a8bd42a9SDmitry Torokhov enum regulator_get_type get_type) 1901414c70cbSLiam Girdwood { 1902414c70cbSLiam Girdwood struct regulator_dev *rdev; 19037d245afaSDmitry Torokhov struct regulator *regulator; 1904b59b6544SSaravana Kannan struct device_link *link; 1905317b5684SMark Brown int ret; 1906414c70cbSLiam Girdwood 1907a8bd42a9SDmitry Torokhov if (get_type >= MAX_GET_TYPE) { 1908a8bd42a9SDmitry Torokhov dev_err(dev, "invalid type %d in %s\n", get_type, __func__); 1909a8bd42a9SDmitry Torokhov return ERR_PTR(-EINVAL); 1910a8bd42a9SDmitry Torokhov } 1911a8bd42a9SDmitry Torokhov 1912414c70cbSLiam Girdwood if (id == NULL) { 19135da84fd9SJoe Perches pr_err("get() with no identifier\n"); 1914043c998fSMark Brown return ERR_PTR(-EINVAL); 1915414c70cbSLiam Girdwood } 1916414c70cbSLiam Girdwood 1917163478daSDmitry Torokhov rdev = regulator_dev_lookup(dev, id); 1918a4d7641fSDmitry Torokhov if (IS_ERR(rdev)) { 1919163478daSDmitry Torokhov ret = PTR_ERR(rdev); 1920ef60abbbSMark Brown 19211e4b545cSNishanth Menon /* 1922a4d7641fSDmitry Torokhov * If regulator_dev_lookup() fails with error other 1923a4d7641fSDmitry Torokhov * than -ENODEV our job here is done, we simply return it. 19241e4b545cSNishanth Menon */ 1925a4d7641fSDmitry Torokhov if (ret != -ENODEV) 1926a4d7641fSDmitry Torokhov return ERR_PTR(ret); 19271e4b545cSNishanth Menon 1928a4d7641fSDmitry Torokhov if (!have_full_constraints()) { 1929a4d7641fSDmitry Torokhov dev_warn(dev, 1930a4d7641fSDmitry Torokhov "incomplete constraints, dummy supplies not allowed\n"); 1931a4d7641fSDmitry Torokhov return ERR_PTR(-ENODEV); 193234abbd68SMark Brown } 193334abbd68SMark Brown 1934a4d7641fSDmitry Torokhov switch (get_type) { 1935a4d7641fSDmitry Torokhov case NORMAL_GET: 1936a4d7641fSDmitry Torokhov /* 1937a4d7641fSDmitry Torokhov * Assume that a regulator is physically present and 1938a4d7641fSDmitry Torokhov * enabled, even if it isn't hooked up, and just 1939a4d7641fSDmitry Torokhov * provide a dummy. 1940a4d7641fSDmitry Torokhov */ 19416e5505cfSAndy Shevchenko dev_warn(dev, "supply %s not found, using dummy regulator\n", id); 1942a4d7641fSDmitry Torokhov rdev = dummy_regulator_rdev; 1943a4d7641fSDmitry Torokhov get_device(&rdev->dev); 1944a4d7641fSDmitry Torokhov break; 1945414c70cbSLiam Girdwood 1946a4d7641fSDmitry Torokhov case EXCLUSIVE_GET: 1947a4d7641fSDmitry Torokhov dev_warn(dev, 1948a4d7641fSDmitry Torokhov "dummy supplies not allowed for exclusive requests\n"); 1949df561f66SGustavo A. R. Silva fallthrough; 1950a4d7641fSDmitry Torokhov 1951a4d7641fSDmitry Torokhov default: 1952a4d7641fSDmitry Torokhov return ERR_PTR(-ENODEV); 1953a4d7641fSDmitry Torokhov } 1954a4d7641fSDmitry Torokhov } 1955a4d7641fSDmitry Torokhov 19565ffbd136SMark Brown if (rdev->exclusive) { 19575ffbd136SMark Brown regulator = ERR_PTR(-EPERM); 195885f3b431STomeu Vizoso put_device(&rdev->dev); 195985f3b431STomeu Vizoso return regulator; 19605ffbd136SMark Brown } 19615ffbd136SMark Brown 1962a8bd42a9SDmitry Torokhov if (get_type == EXCLUSIVE_GET && rdev->open_count) { 19635ffbd136SMark Brown regulator = ERR_PTR(-EBUSY); 196485f3b431STomeu Vizoso put_device(&rdev->dev); 196585f3b431STomeu Vizoso return regulator; 19665ffbd136SMark Brown } 19675ffbd136SMark Brown 196879d6f049SDmitry Osipenko mutex_lock(®ulator_list_mutex); 196979d6f049SDmitry Osipenko ret = (rdev->coupling_desc.n_resolved != rdev->coupling_desc.n_coupled); 197079d6f049SDmitry Osipenko mutex_unlock(®ulator_list_mutex); 197179d6f049SDmitry Osipenko 197279d6f049SDmitry Osipenko if (ret != 0) { 197379d6f049SDmitry Osipenko regulator = ERR_PTR(-EPROBE_DEFER); 197479d6f049SDmitry Osipenko put_device(&rdev->dev); 197579d6f049SDmitry Osipenko return regulator; 197679d6f049SDmitry Osipenko } 197779d6f049SDmitry Osipenko 19786261b06dSBjorn Andersson ret = regulator_resolve_supply(rdev); 19796261b06dSBjorn Andersson if (ret < 0) { 19806261b06dSBjorn Andersson regulator = ERR_PTR(ret); 198185f3b431STomeu Vizoso put_device(&rdev->dev); 198285f3b431STomeu Vizoso return regulator; 19836261b06dSBjorn Andersson } 19846261b06dSBjorn Andersson 198585f3b431STomeu Vizoso if (!try_module_get(rdev->owner)) { 19867d245afaSDmitry Torokhov regulator = ERR_PTR(-EPROBE_DEFER); 198785f3b431STomeu Vizoso put_device(&rdev->dev); 198885f3b431STomeu Vizoso return regulator; 198985f3b431STomeu Vizoso } 1990a5766f11SLiam Girdwood 1991414c70cbSLiam Girdwood regulator = create_regulator(rdev, dev, id); 1992414c70cbSLiam Girdwood if (regulator == NULL) { 1993414c70cbSLiam Girdwood regulator = ERR_PTR(-ENOMEM); 1994414c70cbSLiam Girdwood module_put(rdev->owner); 19954affd79aSWen Yang put_device(&rdev->dev); 199685f3b431STomeu Vizoso return regulator; 1997414c70cbSLiam Girdwood } 1998414c70cbSLiam Girdwood 19995ffbd136SMark Brown rdev->open_count++; 2000a8bd42a9SDmitry Torokhov if (get_type == EXCLUSIVE_GET) { 20015ffbd136SMark Brown rdev->exclusive = 1; 20025ffbd136SMark Brown 20035ffbd136SMark Brown ret = _regulator_is_enabled(rdev); 20045ffbd136SMark Brown if (ret > 0) 20055ffbd136SMark Brown rdev->use_count = 1; 20065ffbd136SMark Brown else 20075ffbd136SMark Brown rdev->use_count = 0; 20085ffbd136SMark Brown } 20095ffbd136SMark Brown 2010b59b6544SSaravana Kannan link = device_link_add(dev, &rdev->dev, DL_FLAG_STATELESS); 2011b59b6544SSaravana Kannan if (!IS_ERR_OR_NULL(link)) 2012b59b6544SSaravana Kannan regulator->device_link = true; 2013ed1ae2ddSpascal paillet 2014414c70cbSLiam Girdwood return regulator; 2015414c70cbSLiam Girdwood } 20165ffbd136SMark Brown 20175ffbd136SMark Brown /** 20185ffbd136SMark Brown * regulator_get - lookup and obtain a reference to a regulator. 20195ffbd136SMark Brown * @dev: device for regulator "consumer" 20205ffbd136SMark Brown * @id: Supply name or regulator ID. 20215ffbd136SMark Brown * 20225ffbd136SMark Brown * Returns a struct regulator corresponding to the regulator producer, 20235ffbd136SMark Brown * or IS_ERR() condition containing errno. 20245ffbd136SMark Brown * 20255ffbd136SMark Brown * Use of supply names configured via regulator_set_device_supply() is 20265ffbd136SMark Brown * strongly encouraged. It is recommended that the supply name used 20275ffbd136SMark Brown * should match the name used for the supply and/or the relevant 20285ffbd136SMark Brown * device pins in the datasheet. 20295ffbd136SMark Brown */ 20305ffbd136SMark Brown struct regulator *regulator_get(struct device *dev, const char *id) 20315ffbd136SMark Brown { 2032a8bd42a9SDmitry Torokhov return _regulator_get(dev, id, NORMAL_GET); 20335ffbd136SMark Brown } 2034414c70cbSLiam Girdwood EXPORT_SYMBOL_GPL(regulator_get); 2035414c70cbSLiam Girdwood 2036070b9079SStephen Boyd /** 20375ffbd136SMark Brown * regulator_get_exclusive - obtain exclusive access to a regulator. 20385ffbd136SMark Brown * @dev: device for regulator "consumer" 20395ffbd136SMark Brown * @id: Supply name or regulator ID. 20405ffbd136SMark Brown * 20415ffbd136SMark Brown * Returns a struct regulator corresponding to the regulator producer, 20425ffbd136SMark Brown * or IS_ERR() condition containing errno. Other consumers will be 204369c3f723SStephen Boyd * unable to obtain this regulator while this reference is held and the 204469c3f723SStephen Boyd * use count for the regulator will be initialised to reflect the current 204569c3f723SStephen Boyd * state of the regulator. 20465ffbd136SMark Brown * 20475ffbd136SMark Brown * This is intended for use by consumers which cannot tolerate shared 20485ffbd136SMark Brown * use of the regulator such as those which need to force the 20495ffbd136SMark Brown * regulator off for correct operation of the hardware they are 20505ffbd136SMark Brown * controlling. 20515ffbd136SMark Brown * 20525ffbd136SMark Brown * Use of supply names configured via regulator_set_device_supply() is 20535ffbd136SMark Brown * strongly encouraged. It is recommended that the supply name used 20545ffbd136SMark Brown * should match the name used for the supply and/or the relevant 20555ffbd136SMark Brown * device pins in the datasheet. 20565ffbd136SMark Brown */ 20575ffbd136SMark Brown struct regulator *regulator_get_exclusive(struct device *dev, const char *id) 20585ffbd136SMark Brown { 2059a8bd42a9SDmitry Torokhov return _regulator_get(dev, id, EXCLUSIVE_GET); 20605ffbd136SMark Brown } 20615ffbd136SMark Brown EXPORT_SYMBOL_GPL(regulator_get_exclusive); 20625ffbd136SMark Brown 2063de1dd9fdSMark Brown /** 2064de1dd9fdSMark Brown * regulator_get_optional - obtain optional access to a regulator. 2065de1dd9fdSMark Brown * @dev: device for regulator "consumer" 2066de1dd9fdSMark Brown * @id: Supply name or regulator ID. 2067de1dd9fdSMark Brown * 2068de1dd9fdSMark Brown * Returns a struct regulator corresponding to the regulator producer, 206969c3f723SStephen Boyd * or IS_ERR() condition containing errno. 2070de1dd9fdSMark Brown * 2071de1dd9fdSMark Brown * This is intended for use by consumers for devices which can have 2072de1dd9fdSMark Brown * some supplies unconnected in normal use, such as some MMC devices. 2073de1dd9fdSMark Brown * It can allow the regulator core to provide stub supplies for other 2074de1dd9fdSMark Brown * supplies requested using normal regulator_get() calls without 2075de1dd9fdSMark Brown * disrupting the operation of drivers that can handle absent 2076de1dd9fdSMark Brown * supplies. 2077de1dd9fdSMark Brown * 2078de1dd9fdSMark Brown * Use of supply names configured via regulator_set_device_supply() is 2079de1dd9fdSMark Brown * strongly encouraged. It is recommended that the supply name used 2080de1dd9fdSMark Brown * should match the name used for the supply and/or the relevant 2081de1dd9fdSMark Brown * device pins in the datasheet. 2082de1dd9fdSMark Brown */ 2083de1dd9fdSMark Brown struct regulator *regulator_get_optional(struct device *dev, const char *id) 2084de1dd9fdSMark Brown { 2085a8bd42a9SDmitry Torokhov return _regulator_get(dev, id, OPTIONAL_GET); 2086de1dd9fdSMark Brown } 2087de1dd9fdSMark Brown EXPORT_SYMBOL_GPL(regulator_get_optional); 2088de1dd9fdSMark Brown 2089e1794aa4SSaravana Kannan static void destroy_regulator(struct regulator *regulator) 2090414c70cbSLiam Girdwood { 2091e1794aa4SSaravana Kannan struct regulator_dev *rdev = regulator->rdev; 2092414c70cbSLiam Girdwood 20935de70519SMark Brown debugfs_remove_recursive(regulator->debugfs); 20945de70519SMark Brown 2095ed1ae2ddSpascal paillet if (regulator->dev) { 2096b59b6544SSaravana Kannan if (regulator->device_link) 2097ed1ae2ddSpascal paillet device_link_remove(regulator->dev, &rdev->dev); 2098ed1ae2ddSpascal paillet 2099414c70cbSLiam Girdwood /* remove any sysfs entries */ 2100414c70cbSLiam Girdwood sysfs_remove_link(&rdev->dev.kobj, regulator->supply_name); 2101ed1ae2ddSpascal paillet } 2102ed1ae2ddSpascal paillet 210366cf9a7eSMaciej Purski regulator_lock(rdev); 2104414c70cbSLiam Girdwood list_del(®ulator->list); 2105414c70cbSLiam Girdwood 21065ffbd136SMark Brown rdev->open_count--; 21075ffbd136SMark Brown rdev->exclusive = 0; 210866cf9a7eSMaciej Purski regulator_unlock(rdev); 21095ffbd136SMark Brown 21100630b614SStephen Boyd kfree_const(regulator->supply_name); 21111768514eSMark Brown kfree(regulator); 2112e1794aa4SSaravana Kannan } 2113e1794aa4SSaravana Kannan 2114e1794aa4SSaravana Kannan /* regulator_list_mutex lock held by regulator_put() */ 2115e1794aa4SSaravana Kannan static void _regulator_put(struct regulator *regulator) 2116e1794aa4SSaravana Kannan { 2117e1794aa4SSaravana Kannan struct regulator_dev *rdev; 2118e1794aa4SSaravana Kannan 2119e1794aa4SSaravana Kannan if (IS_ERR_OR_NULL(regulator)) 2120e1794aa4SSaravana Kannan return; 2121e1794aa4SSaravana Kannan 2122e1794aa4SSaravana Kannan lockdep_assert_held_once(®ulator_list_mutex); 2123e1794aa4SSaravana Kannan 2124e1794aa4SSaravana Kannan /* Docs say you must disable before calling regulator_put() */ 2125e1794aa4SSaravana Kannan WARN_ON(regulator->enable_count); 2126e1794aa4SSaravana Kannan 2127e1794aa4SSaravana Kannan rdev = regulator->rdev; 2128e1794aa4SSaravana Kannan 2129e1794aa4SSaravana Kannan destroy_regulator(regulator); 21301768514eSMark Brown 2131414c70cbSLiam Girdwood module_put(rdev->owner); 21324affd79aSWen Yang put_device(&rdev->dev); 213323ff2f0fSCharles Keepax } 213423ff2f0fSCharles Keepax 213523ff2f0fSCharles Keepax /** 213623ff2f0fSCharles Keepax * regulator_put - "free" the regulator source 213723ff2f0fSCharles Keepax * @regulator: regulator source 213823ff2f0fSCharles Keepax * 213923ff2f0fSCharles Keepax * Note: drivers must ensure that all regulator_enable calls made on this 214023ff2f0fSCharles Keepax * regulator source are balanced by regulator_disable calls prior to calling 214123ff2f0fSCharles Keepax * this function. 214223ff2f0fSCharles Keepax */ 214323ff2f0fSCharles Keepax void regulator_put(struct regulator *regulator) 214423ff2f0fSCharles Keepax { 214523ff2f0fSCharles Keepax mutex_lock(®ulator_list_mutex); 214623ff2f0fSCharles Keepax _regulator_put(regulator); 2147414c70cbSLiam Girdwood mutex_unlock(®ulator_list_mutex); 2148414c70cbSLiam Girdwood } 2149414c70cbSLiam Girdwood EXPORT_SYMBOL_GPL(regulator_put); 2150414c70cbSLiam Girdwood 2151a06ccd9cSCharles Keepax /** 2152a06ccd9cSCharles Keepax * regulator_register_supply_alias - Provide device alias for supply lookup 2153a06ccd9cSCharles Keepax * 2154a06ccd9cSCharles Keepax * @dev: device that will be given as the regulator "consumer" 2155a06ccd9cSCharles Keepax * @id: Supply name or regulator ID 2156a06ccd9cSCharles Keepax * @alias_dev: device that should be used to lookup the supply 2157a06ccd9cSCharles Keepax * @alias_id: Supply name or regulator ID that should be used to lookup the 2158a06ccd9cSCharles Keepax * supply 2159a06ccd9cSCharles Keepax * 2160a06ccd9cSCharles Keepax * All lookups for id on dev will instead be conducted for alias_id on 2161a06ccd9cSCharles Keepax * alias_dev. 2162a06ccd9cSCharles Keepax */ 2163a06ccd9cSCharles Keepax int regulator_register_supply_alias(struct device *dev, const char *id, 2164a06ccd9cSCharles Keepax struct device *alias_dev, 2165a06ccd9cSCharles Keepax const char *alias_id) 2166a06ccd9cSCharles Keepax { 2167a06ccd9cSCharles Keepax struct regulator_supply_alias *map; 2168a06ccd9cSCharles Keepax 2169a06ccd9cSCharles Keepax map = regulator_find_supply_alias(dev, id); 2170a06ccd9cSCharles Keepax if (map) 2171a06ccd9cSCharles Keepax return -EEXIST; 2172a06ccd9cSCharles Keepax 2173a06ccd9cSCharles Keepax map = kzalloc(sizeof(struct regulator_supply_alias), GFP_KERNEL); 2174a06ccd9cSCharles Keepax if (!map) 2175a06ccd9cSCharles Keepax return -ENOMEM; 2176a06ccd9cSCharles Keepax 2177a06ccd9cSCharles Keepax map->src_dev = dev; 2178a06ccd9cSCharles Keepax map->src_supply = id; 2179a06ccd9cSCharles Keepax map->alias_dev = alias_dev; 2180a06ccd9cSCharles Keepax map->alias_supply = alias_id; 2181a06ccd9cSCharles Keepax 2182a06ccd9cSCharles Keepax list_add(&map->list, ®ulator_supply_alias_list); 2183a06ccd9cSCharles Keepax 2184a06ccd9cSCharles Keepax pr_info("Adding alias for supply %s,%s -> %s,%s\n", 2185a06ccd9cSCharles Keepax id, dev_name(dev), alias_id, dev_name(alias_dev)); 2186a06ccd9cSCharles Keepax 2187a06ccd9cSCharles Keepax return 0; 2188a06ccd9cSCharles Keepax } 2189a06ccd9cSCharles Keepax EXPORT_SYMBOL_GPL(regulator_register_supply_alias); 2190a06ccd9cSCharles Keepax 2191a06ccd9cSCharles Keepax /** 2192a06ccd9cSCharles Keepax * regulator_unregister_supply_alias - Remove device alias 2193a06ccd9cSCharles Keepax * 2194a06ccd9cSCharles Keepax * @dev: device that will be given as the regulator "consumer" 2195a06ccd9cSCharles Keepax * @id: Supply name or regulator ID 2196a06ccd9cSCharles Keepax * 2197a06ccd9cSCharles Keepax * Remove a lookup alias if one exists for id on dev. 2198a06ccd9cSCharles Keepax */ 2199a06ccd9cSCharles Keepax void regulator_unregister_supply_alias(struct device *dev, const char *id) 2200a06ccd9cSCharles Keepax { 2201a06ccd9cSCharles Keepax struct regulator_supply_alias *map; 2202a06ccd9cSCharles Keepax 2203a06ccd9cSCharles Keepax map = regulator_find_supply_alias(dev, id); 2204a06ccd9cSCharles Keepax if (map) { 2205a06ccd9cSCharles Keepax list_del(&map->list); 2206a06ccd9cSCharles Keepax kfree(map); 2207a06ccd9cSCharles Keepax } 2208a06ccd9cSCharles Keepax } 2209a06ccd9cSCharles Keepax EXPORT_SYMBOL_GPL(regulator_unregister_supply_alias); 2210a06ccd9cSCharles Keepax 2211a06ccd9cSCharles Keepax /** 2212a06ccd9cSCharles Keepax * regulator_bulk_register_supply_alias - register multiple aliases 2213a06ccd9cSCharles Keepax * 2214a06ccd9cSCharles Keepax * @dev: device that will be given as the regulator "consumer" 2215a06ccd9cSCharles Keepax * @id: List of supply names or regulator IDs 2216a06ccd9cSCharles Keepax * @alias_dev: device that should be used to lookup the supply 2217a06ccd9cSCharles Keepax * @alias_id: List of supply names or regulator IDs that should be used to 2218a06ccd9cSCharles Keepax * lookup the supply 2219a06ccd9cSCharles Keepax * @num_id: Number of aliases to register 2220a06ccd9cSCharles Keepax * 2221a06ccd9cSCharles Keepax * @return 0 on success, an errno on failure. 2222a06ccd9cSCharles Keepax * 2223a06ccd9cSCharles Keepax * This helper function allows drivers to register several supply 2224a06ccd9cSCharles Keepax * aliases in one operation. If any of the aliases cannot be 2225a06ccd9cSCharles Keepax * registered any aliases that were registered will be removed 2226a06ccd9cSCharles Keepax * before returning to the caller. 2227a06ccd9cSCharles Keepax */ 22289f8c0fe9SLee Jones int regulator_bulk_register_supply_alias(struct device *dev, 22299f8c0fe9SLee Jones const char *const *id, 2230a06ccd9cSCharles Keepax struct device *alias_dev, 22319f8c0fe9SLee Jones const char *const *alias_id, 2232a06ccd9cSCharles Keepax int num_id) 2233a06ccd9cSCharles Keepax { 2234a06ccd9cSCharles Keepax int i; 2235a06ccd9cSCharles Keepax int ret; 2236a06ccd9cSCharles Keepax 2237a06ccd9cSCharles Keepax for (i = 0; i < num_id; ++i) { 2238a06ccd9cSCharles Keepax ret = regulator_register_supply_alias(dev, id[i], alias_dev, 2239a06ccd9cSCharles Keepax alias_id[i]); 2240a06ccd9cSCharles Keepax if (ret < 0) 2241a06ccd9cSCharles Keepax goto err; 2242a06ccd9cSCharles Keepax } 2243a06ccd9cSCharles Keepax 2244a06ccd9cSCharles Keepax return 0; 2245a06ccd9cSCharles Keepax 2246a06ccd9cSCharles Keepax err: 2247a06ccd9cSCharles Keepax dev_err(dev, 2248a06ccd9cSCharles Keepax "Failed to create supply alias %s,%s -> %s,%s\n", 2249a06ccd9cSCharles Keepax id[i], dev_name(dev), alias_id[i], dev_name(alias_dev)); 2250a06ccd9cSCharles Keepax 2251a06ccd9cSCharles Keepax while (--i >= 0) 2252a06ccd9cSCharles Keepax regulator_unregister_supply_alias(dev, id[i]); 2253a06ccd9cSCharles Keepax 2254a06ccd9cSCharles Keepax return ret; 2255a06ccd9cSCharles Keepax } 2256a06ccd9cSCharles Keepax EXPORT_SYMBOL_GPL(regulator_bulk_register_supply_alias); 2257a06ccd9cSCharles Keepax 2258a06ccd9cSCharles Keepax /** 2259a06ccd9cSCharles Keepax * regulator_bulk_unregister_supply_alias - unregister multiple aliases 2260a06ccd9cSCharles Keepax * 2261a06ccd9cSCharles Keepax * @dev: device that will be given as the regulator "consumer" 2262a06ccd9cSCharles Keepax * @id: List of supply names or regulator IDs 2263a06ccd9cSCharles Keepax * @num_id: Number of aliases to unregister 2264a06ccd9cSCharles Keepax * 2265a06ccd9cSCharles Keepax * This helper function allows drivers to unregister several supply 2266a06ccd9cSCharles Keepax * aliases in one operation. 2267a06ccd9cSCharles Keepax */ 2268a06ccd9cSCharles Keepax void regulator_bulk_unregister_supply_alias(struct device *dev, 22699f8c0fe9SLee Jones const char *const *id, 2270a06ccd9cSCharles Keepax int num_id) 2271a06ccd9cSCharles Keepax { 2272a06ccd9cSCharles Keepax int i; 2273a06ccd9cSCharles Keepax 2274a06ccd9cSCharles Keepax for (i = 0; i < num_id; ++i) 2275a06ccd9cSCharles Keepax regulator_unregister_supply_alias(dev, id[i]); 2276a06ccd9cSCharles Keepax } 2277a06ccd9cSCharles Keepax EXPORT_SYMBOL_GPL(regulator_bulk_unregister_supply_alias); 2278a06ccd9cSCharles Keepax 2279a06ccd9cSCharles Keepax 2280f19b00daSKim, Milo /* Manage enable GPIO list. Same GPIO pin can be shared among regulators */ 2281f19b00daSKim, Milo static int regulator_ena_gpio_request(struct regulator_dev *rdev, 2282f19b00daSKim, Milo const struct regulator_config *config) 2283f19b00daSKim, Milo { 2284467bf301SMichał Mirosław struct regulator_enable_gpio *pin, *new_pin; 2285778b28b4SRussell King struct gpio_desc *gpiod; 2286f19b00daSKim, Milo 2287e45e290aSLinus Walleij gpiod = config->ena_gpiod; 2288467bf301SMichał Mirosław new_pin = kzalloc(sizeof(*new_pin), GFP_KERNEL); 2289467bf301SMichał Mirosław 2290467bf301SMichał Mirosław mutex_lock(®ulator_list_mutex); 2291778b28b4SRussell King 2292f19b00daSKim, Milo list_for_each_entry(pin, ®ulator_ena_gpio_list, list) { 2293778b28b4SRussell King if (pin->gpiod == gpiod) { 2294541d052dSLinus Walleij rdev_dbg(rdev, "GPIO is already used\n"); 2295f19b00daSKim, Milo goto update_ena_gpio_to_rdev; 2296f19b00daSKim, Milo } 2297f19b00daSKim, Milo } 2298f19b00daSKim, Milo 2299467bf301SMichał Mirosław if (new_pin == NULL) { 2300467bf301SMichał Mirosław mutex_unlock(®ulator_list_mutex); 2301f19b00daSKim, Milo return -ENOMEM; 2302467bf301SMichał Mirosław } 2303467bf301SMichał Mirosław 2304467bf301SMichał Mirosław pin = new_pin; 2305467bf301SMichał Mirosław new_pin = NULL; 2306f19b00daSKim, Milo 2307778b28b4SRussell King pin->gpiod = gpiod; 2308f19b00daSKim, Milo list_add(&pin->list, ®ulator_ena_gpio_list); 2309f19b00daSKim, Milo 2310f19b00daSKim, Milo update_ena_gpio_to_rdev: 2311f19b00daSKim, Milo pin->request_count++; 2312f19b00daSKim, Milo rdev->ena_pin = pin; 2313467bf301SMichał Mirosław 2314467bf301SMichał Mirosław mutex_unlock(®ulator_list_mutex); 2315467bf301SMichał Mirosław kfree(new_pin); 2316467bf301SMichał Mirosław 2317f19b00daSKim, Milo return 0; 2318f19b00daSKim, Milo } 2319f19b00daSKim, Milo 2320f19b00daSKim, Milo static void regulator_ena_gpio_free(struct regulator_dev *rdev) 2321f19b00daSKim, Milo { 2322f19b00daSKim, Milo struct regulator_enable_gpio *pin, *n; 2323f19b00daSKim, Milo 2324f19b00daSKim, Milo if (!rdev->ena_pin) 2325f19b00daSKim, Milo return; 2326f19b00daSKim, Milo 2327f19b00daSKim, Milo /* Free the GPIO only in case of no use */ 2328f19b00daSKim, Milo list_for_each_entry_safe(pin, n, ®ulator_ena_gpio_list, list) { 23292dbf0855SMichał Mirosław if (pin != rdev->ena_pin) 23302dbf0855SMichał Mirosław continue; 23312dbf0855SMichał Mirosław 23322dbf0855SMichał Mirosław if (--pin->request_count) 23332dbf0855SMichał Mirosław break; 23342dbf0855SMichał Mirosław 233578927aa4SLinus Walleij gpiod_put(pin->gpiod); 2336f19b00daSKim, Milo list_del(&pin->list); 2337f19b00daSKim, Milo kfree(pin); 23382dbf0855SMichał Mirosław break; 23392dbf0855SMichał Mirosław } 23402dbf0855SMichał Mirosław 234160a2362fSSeung-Woo Kim rdev->ena_pin = NULL; 2342f19b00daSKim, Milo } 2343f19b00daSKim, Milo 2344967cfb18SKim, Milo /** 234531d6eebfSRobert P. J. Day * regulator_ena_gpio_ctrl - balance enable_count of each GPIO and actual GPIO pin control 234631d6eebfSRobert P. J. Day * @rdev: regulator_dev structure 234731d6eebfSRobert P. J. Day * @enable: enable GPIO at initial use? 234831d6eebfSRobert P. J. Day * 2349967cfb18SKim, Milo * GPIO is enabled in case of initial use. (enable_count is 0) 2350967cfb18SKim, Milo * GPIO is disabled when it is not shared any more. (enable_count <= 1) 2351967cfb18SKim, Milo */ 2352967cfb18SKim, Milo static int regulator_ena_gpio_ctrl(struct regulator_dev *rdev, bool enable) 2353967cfb18SKim, Milo { 2354967cfb18SKim, Milo struct regulator_enable_gpio *pin = rdev->ena_pin; 2355967cfb18SKim, Milo 2356967cfb18SKim, Milo if (!pin) 2357967cfb18SKim, Milo return -EINVAL; 2358967cfb18SKim, Milo 2359967cfb18SKim, Milo if (enable) { 2360967cfb18SKim, Milo /* Enable GPIO at initial use */ 2361967cfb18SKim, Milo if (pin->enable_count == 0) 236201dc79cdSLinus Walleij gpiod_set_value_cansleep(pin->gpiod, 1); 2363967cfb18SKim, Milo 2364967cfb18SKim, Milo pin->enable_count++; 2365967cfb18SKim, Milo } else { 2366967cfb18SKim, Milo if (pin->enable_count > 1) { 2367967cfb18SKim, Milo pin->enable_count--; 2368967cfb18SKim, Milo return 0; 2369967cfb18SKim, Milo } 2370967cfb18SKim, Milo 2371967cfb18SKim, Milo /* Disable GPIO if not used */ 2372967cfb18SKim, Milo if (pin->enable_count <= 1) { 237301dc79cdSLinus Walleij gpiod_set_value_cansleep(pin->gpiod, 0); 2374967cfb18SKim, Milo pin->enable_count = 0; 2375967cfb18SKim, Milo } 2376967cfb18SKim, Milo } 2377967cfb18SKim, Milo 2378967cfb18SKim, Milo return 0; 2379967cfb18SKim, Milo } 2380967cfb18SKim, Milo 238179fd1141SGuodong Xu /** 238279fd1141SGuodong Xu * _regulator_enable_delay - a delay helper function 238379fd1141SGuodong Xu * @delay: time to delay in microseconds 238479fd1141SGuodong Xu * 23855df529d4SThierry Reding * Delay for the requested amount of time as per the guidelines in: 23865df529d4SThierry Reding * 2387458f69efSMauro Carvalho Chehab * Documentation/timers/timers-howto.rst 23885df529d4SThierry Reding * 23895df529d4SThierry Reding * The assumption here is that regulators will never be enabled in 23905df529d4SThierry Reding * atomic context and therefore sleeping functions can be used. 23915df529d4SThierry Reding */ 239279fd1141SGuodong Xu static void _regulator_enable_delay(unsigned int delay) 239379fd1141SGuodong Xu { 23945df529d4SThierry Reding unsigned int ms = delay / 1000; 23955df529d4SThierry Reding unsigned int us = delay % 1000; 23965df529d4SThierry Reding 23975df529d4SThierry Reding if (ms > 0) { 23985df529d4SThierry Reding /* 23995df529d4SThierry Reding * For small enough values, handle super-millisecond 24005df529d4SThierry Reding * delays in the usleep_range() call below. 24015df529d4SThierry Reding */ 24025df529d4SThierry Reding if (ms < 20) 24035df529d4SThierry Reding us += ms * 1000; 24045df529d4SThierry Reding else 24055df529d4SThierry Reding msleep(ms); 24065df529d4SThierry Reding } 24075df529d4SThierry Reding 24085df529d4SThierry Reding /* 24095df529d4SThierry Reding * Give the scheduler some room to coalesce with any other 24105df529d4SThierry Reding * wakeup sources. For delays shorter than 10 us, don't even 24115df529d4SThierry Reding * bother setting up high-resolution timers and just busy- 24125df529d4SThierry Reding * loop. 24135df529d4SThierry Reding */ 24145df529d4SThierry Reding if (us >= 10) 24155df529d4SThierry Reding usleep_range(us, us + 100); 24165df529d4SThierry Reding else 24175df529d4SThierry Reding udelay(us); 24185c5659d0SMark Brown } 24195c5659d0SMark Brown 2420f7d7ad42SSumit Semwal /** 2421f7d7ad42SSumit Semwal * _regulator_check_status_enabled 2422f7d7ad42SSumit Semwal * 2423f7d7ad42SSumit Semwal * A helper function to check if the regulator status can be interpreted 2424f7d7ad42SSumit Semwal * as 'regulator is enabled'. 2425f7d7ad42SSumit Semwal * @rdev: the regulator device to check 2426f7d7ad42SSumit Semwal * 2427f7d7ad42SSumit Semwal * Return: 2428f7d7ad42SSumit Semwal * * 1 - if status shows regulator is in enabled state 2429f7d7ad42SSumit Semwal * * 0 - if not enabled state 2430f7d7ad42SSumit Semwal * * Error Value - as received from ops->get_status() 2431f7d7ad42SSumit Semwal */ 2432f7d7ad42SSumit Semwal static inline int _regulator_check_status_enabled(struct regulator_dev *rdev) 2433f7d7ad42SSumit Semwal { 2434f7d7ad42SSumit Semwal int ret = rdev->desc->ops->get_status(rdev); 2435f7d7ad42SSumit Semwal 2436f7d7ad42SSumit Semwal if (ret < 0) { 2437f7d7ad42SSumit Semwal rdev_info(rdev, "get_status returned error: %d\n", ret); 2438f7d7ad42SSumit Semwal return ret; 2439f7d7ad42SSumit Semwal } 2440f7d7ad42SSumit Semwal 2441f7d7ad42SSumit Semwal switch (ret) { 2442f7d7ad42SSumit Semwal case REGULATOR_STATUS_OFF: 2443f7d7ad42SSumit Semwal case REGULATOR_STATUS_ERROR: 2444f7d7ad42SSumit Semwal case REGULATOR_STATUS_UNDEFINED: 2445f7d7ad42SSumit Semwal return 0; 2446f7d7ad42SSumit Semwal default: 2447f7d7ad42SSumit Semwal return 1; 2448f7d7ad42SSumit Semwal } 2449f7d7ad42SSumit Semwal } 2450f7d7ad42SSumit Semwal 24515c5659d0SMark Brown static int _regulator_do_enable(struct regulator_dev *rdev) 24525c5659d0SMark Brown { 24535c5659d0SMark Brown int ret, delay; 24545c5659d0SMark Brown 24555c5659d0SMark Brown /* Query before enabling in case configuration dependent. */ 24565c5659d0SMark Brown ret = _regulator_get_enable_time(rdev); 24575c5659d0SMark Brown if (ret >= 0) { 24585c5659d0SMark Brown delay = ret; 24595c5659d0SMark Brown } else { 246061aab5adSMichał Mirosław rdev_warn(rdev, "enable_time() failed: %pe\n", ERR_PTR(ret)); 2461414c70cbSLiam Girdwood delay = 0; 2462414c70cbSLiam Girdwood } 24635c5659d0SMark Brown 2464414c70cbSLiam Girdwood trace_regulator_enable(rdev_get_name(rdev)); 2465414c70cbSLiam Girdwood 2466871f5650SGuodong Xu if (rdev->desc->off_on_delay) { 2467871f5650SGuodong Xu /* if needed, keep a distance of off_on_delay from last time 2468871f5650SGuodong Xu * this regulator was disabled. 2469871f5650SGuodong Xu */ 2470871f5650SGuodong Xu unsigned long start_jiffy = jiffies; 2471871f5650SGuodong Xu unsigned long intended, max_delay, remaining; 2472871f5650SGuodong Xu 2473871f5650SGuodong Xu max_delay = usecs_to_jiffies(rdev->desc->off_on_delay); 2474871f5650SGuodong Xu intended = rdev->last_off_jiffy + max_delay; 2475871f5650SGuodong Xu 2476871f5650SGuodong Xu if (time_before(start_jiffy, intended)) { 2477871f5650SGuodong Xu /* calc remaining jiffies to deal with one-time 2478871f5650SGuodong Xu * timer wrapping. 2479871f5650SGuodong Xu * in case of multiple timer wrapping, either it can be 2480871f5650SGuodong Xu * detected by out-of-range remaining, or it cannot be 248148f1b4efSKrzysztof Kozlowski * detected and we get a penalty of 2482871f5650SGuodong Xu * _regulator_enable_delay(). 2483871f5650SGuodong Xu */ 2484871f5650SGuodong Xu remaining = intended - start_jiffy; 2485871f5650SGuodong Xu if (remaining <= max_delay) 2486871f5650SGuodong Xu _regulator_enable_delay( 2487871f5650SGuodong Xu jiffies_to_usecs(remaining)); 2488871f5650SGuodong Xu } 2489871f5650SGuodong Xu } 2490871f5650SGuodong Xu 2491414c70cbSLiam Girdwood if (rdev->ena_pin) { 249229d62ec5SDoug Anderson if (!rdev->ena_gpio_state) { 24939a2372faSMark Brown ret = regulator_ena_gpio_ctrl(rdev, true); 2494414c70cbSLiam Girdwood if (ret < 0) 2495414c70cbSLiam Girdwood return ret; 24969a2372faSMark Brown rdev->ena_gpio_state = 1; 249729d62ec5SDoug Anderson } 24989a2372faSMark Brown } else if (rdev->desc->ops->enable) { 24999a2372faSMark Brown ret = rdev->desc->ops->enable(rdev); 25009a2372faSMark Brown if (ret < 0) 25019a2372faSMark Brown return ret; 25029a2372faSMark Brown } else { 25039a2372faSMark Brown return -EINVAL; 25045c5659d0SMark Brown } 25059a2372faSMark Brown 25069a2372faSMark Brown /* Allow the regulator to ramp; it would be useful to extend 250731aae2beSMark Brown * this for bulk operations so that the regulators can ramp 2508a7433cffSLinus Walleij * together. */ 25095da84fd9SJoe Perches trace_regulator_enable_delay(rdev_get_name(rdev)); 2510414c70cbSLiam Girdwood 2511f7d7ad42SSumit Semwal /* If poll_enabled_time is set, poll upto the delay calculated 2512f7d7ad42SSumit Semwal * above, delaying poll_enabled_time uS to check if the regulator 2513f7d7ad42SSumit Semwal * actually got enabled. 2514f7d7ad42SSumit Semwal * If the regulator isn't enabled after enable_delay has 2515f7d7ad42SSumit Semwal * expired, return -ETIMEDOUT. 2516f7d7ad42SSumit Semwal */ 2517f7d7ad42SSumit Semwal if (rdev->desc->poll_enabled_time) { 2518f7d7ad42SSumit Semwal unsigned int time_remaining = delay; 2519f7d7ad42SSumit Semwal 2520f7d7ad42SSumit Semwal while (time_remaining > 0) { 2521f7d7ad42SSumit Semwal _regulator_enable_delay(rdev->desc->poll_enabled_time); 2522f7d7ad42SSumit Semwal 2523f7d7ad42SSumit Semwal if (rdev->desc->ops->get_status) { 2524f7d7ad42SSumit Semwal ret = _regulator_check_status_enabled(rdev); 2525f7d7ad42SSumit Semwal if (ret < 0) 2526f7d7ad42SSumit Semwal return ret; 2527f7d7ad42SSumit Semwal else if (ret) 2528f7d7ad42SSumit Semwal break; 2529f7d7ad42SSumit Semwal } else if (rdev->desc->ops->is_enabled(rdev)) 2530f7d7ad42SSumit Semwal break; 2531f7d7ad42SSumit Semwal 2532f7d7ad42SSumit Semwal time_remaining -= rdev->desc->poll_enabled_time; 2533f7d7ad42SSumit Semwal } 2534f7d7ad42SSumit Semwal 2535f7d7ad42SSumit Semwal if (time_remaining <= 0) { 2536f7d7ad42SSumit Semwal rdev_err(rdev, "Enabled check timed out\n"); 2537f7d7ad42SSumit Semwal return -ETIMEDOUT; 2538f7d7ad42SSumit Semwal } 2539f7d7ad42SSumit Semwal } else { 254079fd1141SGuodong Xu _regulator_enable_delay(delay); 2541f7d7ad42SSumit Semwal } 2542a7433cffSLinus Walleij 2543414c70cbSLiam Girdwood trace_regulator_enable_complete(rdev_get_name(rdev)); 2544414c70cbSLiam Girdwood 25459a2372faSMark Brown return 0; 25469a2372faSMark Brown } 25479a2372faSMark Brown 25485451781dSDouglas Anderson /** 25495451781dSDouglas Anderson * _regulator_handle_consumer_enable - handle that a consumer enabled 25505451781dSDouglas Anderson * @regulator: regulator source 25515451781dSDouglas Anderson * 25525451781dSDouglas Anderson * Some things on a regulator consumer (like the contribution towards total 25535451781dSDouglas Anderson * load on the regulator) only have an effect when the consumer wants the 25545451781dSDouglas Anderson * regulator enabled. Explained in example with two consumers of the same 25555451781dSDouglas Anderson * regulator: 25565451781dSDouglas Anderson * consumer A: set_load(100); => total load = 0 25575451781dSDouglas Anderson * consumer A: regulator_enable(); => total load = 100 25585451781dSDouglas Anderson * consumer B: set_load(1000); => total load = 100 25595451781dSDouglas Anderson * consumer B: regulator_enable(); => total load = 1100 25605451781dSDouglas Anderson * consumer A: regulator_disable(); => total_load = 1000 25615451781dSDouglas Anderson * 25625451781dSDouglas Anderson * This function (together with _regulator_handle_consumer_disable) is 25635451781dSDouglas Anderson * responsible for keeping track of the refcount for a given regulator consumer 25645451781dSDouglas Anderson * and applying / unapplying these things. 25655451781dSDouglas Anderson * 25665451781dSDouglas Anderson * Returns 0 upon no error; -error upon error. 25675451781dSDouglas Anderson */ 25685451781dSDouglas Anderson static int _regulator_handle_consumer_enable(struct regulator *regulator) 2569414c70cbSLiam Girdwood { 25705451781dSDouglas Anderson struct regulator_dev *rdev = regulator->rdev; 25715451781dSDouglas Anderson 25725451781dSDouglas Anderson lockdep_assert_held_once(&rdev->mutex.base); 25735451781dSDouglas Anderson 25745451781dSDouglas Anderson regulator->enable_count++; 25755451781dSDouglas Anderson if (regulator->uA_load && regulator->enable_count == 1) 25765451781dSDouglas Anderson return drms_uA_update(rdev); 25775451781dSDouglas Anderson 25785451781dSDouglas Anderson return 0; 25795451781dSDouglas Anderson } 25805451781dSDouglas Anderson 25815451781dSDouglas Anderson /** 25825451781dSDouglas Anderson * _regulator_handle_consumer_disable - handle that a consumer disabled 25835451781dSDouglas Anderson * @regulator: regulator source 25845451781dSDouglas Anderson * 25855451781dSDouglas Anderson * The opposite of _regulator_handle_consumer_enable(). 25865451781dSDouglas Anderson * 25875451781dSDouglas Anderson * Returns 0 upon no error; -error upon error. 25885451781dSDouglas Anderson */ 25895451781dSDouglas Anderson static int _regulator_handle_consumer_disable(struct regulator *regulator) 25905451781dSDouglas Anderson { 25915451781dSDouglas Anderson struct regulator_dev *rdev = regulator->rdev; 25925451781dSDouglas Anderson 25935451781dSDouglas Anderson lockdep_assert_held_once(&rdev->mutex.base); 25945451781dSDouglas Anderson 25955451781dSDouglas Anderson if (!regulator->enable_count) { 25965451781dSDouglas Anderson rdev_err(rdev, "Underflow of regulator enable count\n"); 25975451781dSDouglas Anderson return -EINVAL; 25985451781dSDouglas Anderson } 25995451781dSDouglas Anderson 26005451781dSDouglas Anderson regulator->enable_count--; 26015451781dSDouglas Anderson if (regulator->uA_load && regulator->enable_count == 0) 26025451781dSDouglas Anderson return drms_uA_update(rdev); 26035451781dSDouglas Anderson 26045451781dSDouglas Anderson return 0; 26055451781dSDouglas Anderson } 26065451781dSDouglas Anderson 26075451781dSDouglas Anderson /* locks held by regulator_enable() */ 26085451781dSDouglas Anderson static int _regulator_enable(struct regulator *regulator) 26095451781dSDouglas Anderson { 26105451781dSDouglas Anderson struct regulator_dev *rdev = regulator->rdev; 2611414c70cbSLiam Girdwood int ret; 2612414c70cbSLiam Girdwood 2613f8702f9eSDmitry Osipenko lockdep_assert_held_once(&rdev->mutex.base); 2614f8702f9eSDmitry Osipenko 26151fc12b05SDouglas Anderson if (rdev->use_count == 0 && rdev->supply) { 26165451781dSDouglas Anderson ret = _regulator_enable(rdev->supply); 2617f8702f9eSDmitry Osipenko if (ret < 0) 2618f8702f9eSDmitry Osipenko return ret; 2619f8702f9eSDmitry Osipenko } 2620f8702f9eSDmitry Osipenko 2621f8702f9eSDmitry Osipenko /* balance only if there are regulators coupled */ 2622f8702f9eSDmitry Osipenko if (rdev->coupling_desc.n_coupled > 1) { 2623f8702f9eSDmitry Osipenko ret = regulator_balance_voltage(rdev, PM_SUSPEND_ON); 2624f8702f9eSDmitry Osipenko if (ret < 0) 2625f8702f9eSDmitry Osipenko goto err_disable_supply; 2626f8702f9eSDmitry Osipenko } 262770cfef26SKrzysztof Kozlowski 26285451781dSDouglas Anderson ret = _regulator_handle_consumer_enable(regulator); 26295451781dSDouglas Anderson if (ret < 0) 26305451781dSDouglas Anderson goto err_disable_supply; 2631cf7bbcdfSMark Brown 2632414c70cbSLiam Girdwood if (rdev->use_count == 0) { 2633cf7bbcdfSMark Brown /* The regulator may on if it's not switchable or left on */ 2634414c70cbSLiam Girdwood ret = _regulator_is_enabled(rdev); 2635414c70cbSLiam Girdwood if (ret == -EINVAL || ret == 0) { 26368a34e979SWEN Pingbo if (!regulator_ops_is_valid(rdev, 2637f8702f9eSDmitry Osipenko REGULATOR_CHANGE_STATUS)) { 2638f8702f9eSDmitry Osipenko ret = -EPERM; 26395451781dSDouglas Anderson goto err_consumer_disable; 2640f8702f9eSDmitry Osipenko } 2641412aec61SDavid Brownell 2642414c70cbSLiam Girdwood ret = _regulator_do_enable(rdev); 2643412aec61SDavid Brownell if (ret < 0) 26445451781dSDouglas Anderson goto err_consumer_disable; 2645414c70cbSLiam Girdwood 2646264b88c9SHarald Geyer _notifier_call_chain(rdev, REGULATOR_EVENT_ENABLE, 2647264b88c9SHarald Geyer NULL); 2648414c70cbSLiam Girdwood } else if (ret < 0) { 264961aab5adSMichał Mirosław rdev_err(rdev, "is_enabled() failed: %pe\n", ERR_PTR(ret)); 26505451781dSDouglas Anderson goto err_consumer_disable; 2651414c70cbSLiam Girdwood } 2652414c70cbSLiam Girdwood /* Fallthrough on positive return values - already enabled */ 2653414c70cbSLiam Girdwood } 2654414c70cbSLiam Girdwood 2655414c70cbSLiam Girdwood rdev->use_count++; 2656414c70cbSLiam Girdwood 2657414c70cbSLiam Girdwood return 0; 2658f8702f9eSDmitry Osipenko 26595451781dSDouglas Anderson err_consumer_disable: 26605451781dSDouglas Anderson _regulator_handle_consumer_disable(regulator); 26615451781dSDouglas Anderson 2662f8702f9eSDmitry Osipenko err_disable_supply: 26631fc12b05SDouglas Anderson if (rdev->use_count == 0 && rdev->supply) 26645451781dSDouglas Anderson _regulator_disable(rdev->supply); 2665f8702f9eSDmitry Osipenko 2666f8702f9eSDmitry Osipenko return ret; 2667414c70cbSLiam Girdwood } 2668414c70cbSLiam Girdwood 2669414c70cbSLiam Girdwood /** 2670414c70cbSLiam Girdwood * regulator_enable - enable regulator output 2671414c70cbSLiam Girdwood * @regulator: regulator source 2672414c70cbSLiam Girdwood * 2673414c70cbSLiam Girdwood * Request that the regulator be enabled with the regulator output at 2674414c70cbSLiam Girdwood * the predefined voltage or current value. Calls to regulator_enable() 2675414c70cbSLiam Girdwood * must be balanced with calls to regulator_disable(). 2676414c70cbSLiam Girdwood * 2677414c70cbSLiam Girdwood * NOTE: the output value can be set by other drivers, boot loader or may be 2678414c70cbSLiam Girdwood * hardwired in the regulator. 2679414c70cbSLiam Girdwood */ 2680414c70cbSLiam Girdwood int regulator_enable(struct regulator *regulator) 2681414c70cbSLiam Girdwood { 2682414c70cbSLiam Girdwood struct regulator_dev *rdev = regulator->rdev; 2683f8702f9eSDmitry Osipenko struct ww_acquire_ctx ww_ctx; 26845451781dSDouglas Anderson int ret; 26856492bc1bSMark Brown 2686f8702f9eSDmitry Osipenko regulator_lock_dependent(rdev, &ww_ctx); 26875451781dSDouglas Anderson ret = _regulator_enable(regulator); 2688f8702f9eSDmitry Osipenko regulator_unlock_dependent(rdev, &ww_ctx); 26893801b86aSMark Brown 2690414c70cbSLiam Girdwood return ret; 2691414c70cbSLiam Girdwood } 2692414c70cbSLiam Girdwood EXPORT_SYMBOL_GPL(regulator_enable); 2693414c70cbSLiam Girdwood 26945c5659d0SMark Brown static int _regulator_do_disable(struct regulator_dev *rdev) 26955c5659d0SMark Brown { 26965c5659d0SMark Brown int ret; 26975c5659d0SMark Brown 26985c5659d0SMark Brown trace_regulator_disable(rdev_get_name(rdev)); 26995c5659d0SMark Brown 2700967cfb18SKim, Milo if (rdev->ena_pin) { 270129d62ec5SDoug Anderson if (rdev->ena_gpio_state) { 2702967cfb18SKim, Milo ret = regulator_ena_gpio_ctrl(rdev, false); 2703967cfb18SKim, Milo if (ret < 0) 2704967cfb18SKim, Milo return ret; 27055c5659d0SMark Brown rdev->ena_gpio_state = 0; 270629d62ec5SDoug Anderson } 27075c5659d0SMark Brown 27085c5659d0SMark Brown } else if (rdev->desc->ops->disable) { 27095c5659d0SMark Brown ret = rdev->desc->ops->disable(rdev); 27105c5659d0SMark Brown if (ret != 0) 27115c5659d0SMark Brown return ret; 27125c5659d0SMark Brown } 27135c5659d0SMark Brown 2714871f5650SGuodong Xu /* cares about last_off_jiffy only if off_on_delay is required by 2715871f5650SGuodong Xu * device. 2716871f5650SGuodong Xu */ 2717871f5650SGuodong Xu if (rdev->desc->off_on_delay) 2718871f5650SGuodong Xu rdev->last_off_jiffy = jiffies; 2719871f5650SGuodong Xu 27205c5659d0SMark Brown trace_regulator_disable_complete(rdev_get_name(rdev)); 27215c5659d0SMark Brown 27225c5659d0SMark Brown return 0; 27235c5659d0SMark Brown } 27245c5659d0SMark Brown 2725414c70cbSLiam Girdwood /* locks held by regulator_disable() */ 27265451781dSDouglas Anderson static int _regulator_disable(struct regulator *regulator) 2727414c70cbSLiam Girdwood { 27285451781dSDouglas Anderson struct regulator_dev *rdev = regulator->rdev; 2729414c70cbSLiam Girdwood int ret = 0; 2730414c70cbSLiam Girdwood 2731f8702f9eSDmitry Osipenko lockdep_assert_held_once(&rdev->mutex.base); 273270cfef26SKrzysztof Kozlowski 2733cd94b505SDavid Brownell if (WARN(rdev->use_count <= 0, 273443e7ee33SJoe Perches "unbalanced disables for %s\n", rdev_get_name(rdev))) 2735cd94b505SDavid Brownell return -EIO; 2736cd94b505SDavid Brownell 2737414c70cbSLiam Girdwood /* are we the last user and permitted to disable ? */ 273860ef66fcSMark Brown if (rdev->use_count == 1 && 273960ef66fcSMark Brown (rdev->constraints && !rdev->constraints->always_on)) { 2740414c70cbSLiam Girdwood 2741414c70cbSLiam Girdwood /* we are last user */ 27428a34e979SWEN Pingbo if (regulator_ops_is_valid(rdev, REGULATOR_CHANGE_STATUS)) { 2743a1c8a551SRichard Fitzgerald ret = _notifier_call_chain(rdev, 2744a1c8a551SRichard Fitzgerald REGULATOR_EVENT_PRE_DISABLE, 2745a1c8a551SRichard Fitzgerald NULL); 2746a1c8a551SRichard Fitzgerald if (ret & NOTIFY_STOP_MASK) 2747a1c8a551SRichard Fitzgerald return -EINVAL; 2748a1c8a551SRichard Fitzgerald 27495c5659d0SMark Brown ret = _regulator_do_disable(rdev); 2750414c70cbSLiam Girdwood if (ret < 0) { 275161aab5adSMichał Mirosław rdev_err(rdev, "failed to disable: %pe\n", ERR_PTR(ret)); 2752a1c8a551SRichard Fitzgerald _notifier_call_chain(rdev, 2753a1c8a551SRichard Fitzgerald REGULATOR_EVENT_ABORT_DISABLE, 2754a1c8a551SRichard Fitzgerald NULL); 2755414c70cbSLiam Girdwood return ret; 2756414c70cbSLiam Girdwood } 275766fda75fSMarkus Pargmann _notifier_call_chain(rdev, REGULATOR_EVENT_DISABLE, 275866fda75fSMarkus Pargmann NULL); 2759414c70cbSLiam Girdwood } 2760414c70cbSLiam Girdwood 2761414c70cbSLiam Girdwood rdev->use_count = 0; 2762414c70cbSLiam Girdwood } else if (rdev->use_count > 1) { 2763414c70cbSLiam Girdwood rdev->use_count--; 2764414c70cbSLiam Girdwood } 27653801b86aSMark Brown 27665451781dSDouglas Anderson if (ret == 0) 27675451781dSDouglas Anderson ret = _regulator_handle_consumer_disable(regulator); 27685451781dSDouglas Anderson 2769f8702f9eSDmitry Osipenko if (ret == 0 && rdev->coupling_desc.n_coupled > 1) 2770f8702f9eSDmitry Osipenko ret = regulator_balance_voltage(rdev, PM_SUSPEND_ON); 2771f8702f9eSDmitry Osipenko 27721fc12b05SDouglas Anderson if (ret == 0 && rdev->use_count == 0 && rdev->supply) 27735451781dSDouglas Anderson ret = _regulator_disable(rdev->supply); 2774f8702f9eSDmitry Osipenko 2775414c70cbSLiam Girdwood return ret; 2776414c70cbSLiam Girdwood } 2777414c70cbSLiam Girdwood 2778414c70cbSLiam Girdwood /** 2779414c70cbSLiam Girdwood * regulator_disable - disable regulator output 2780414c70cbSLiam Girdwood * @regulator: regulator source 2781414c70cbSLiam Girdwood * 2782cf7bbcdfSMark Brown * Disable the regulator output voltage or current. Calls to 2783cf7bbcdfSMark Brown * regulator_enable() must be balanced with calls to 2784cf7bbcdfSMark Brown * regulator_disable(). 278569279fb9SMark Brown * 2786414c70cbSLiam Girdwood * NOTE: this will only disable the regulator output if no other consumer 2787cf7bbcdfSMark Brown * devices have it enabled, the regulator device supports disabling and 2788cf7bbcdfSMark Brown * machine constraints permit this operation. 2789414c70cbSLiam Girdwood */ 2790414c70cbSLiam Girdwood int regulator_disable(struct regulator *regulator) 2791414c70cbSLiam Girdwood { 2792412aec61SDavid Brownell struct regulator_dev *rdev = regulator->rdev; 2793f8702f9eSDmitry Osipenko struct ww_acquire_ctx ww_ctx; 27945451781dSDouglas Anderson int ret; 27956492bc1bSMark Brown 2796f8702f9eSDmitry Osipenko regulator_lock_dependent(rdev, &ww_ctx); 27975451781dSDouglas Anderson ret = _regulator_disable(regulator); 2798f8702f9eSDmitry Osipenko regulator_unlock_dependent(rdev, &ww_ctx); 27998cbf811dSJeffrey Carlyle 2800414c70cbSLiam Girdwood return ret; 2801414c70cbSLiam Girdwood } 2802414c70cbSLiam Girdwood EXPORT_SYMBOL_GPL(regulator_disable); 2803414c70cbSLiam Girdwood 2804414c70cbSLiam Girdwood /* locks held by regulator_force_disable() */ 28053801b86aSMark Brown static int _regulator_force_disable(struct regulator_dev *rdev) 2806414c70cbSLiam Girdwood { 2807414c70cbSLiam Girdwood int ret = 0; 2808414c70cbSLiam Girdwood 2809f8702f9eSDmitry Osipenko lockdep_assert_held_once(&rdev->mutex.base); 281070cfef26SKrzysztof Kozlowski 2811a1c8a551SRichard Fitzgerald ret = _notifier_call_chain(rdev, REGULATOR_EVENT_FORCE_DISABLE | 2812a1c8a551SRichard Fitzgerald REGULATOR_EVENT_PRE_DISABLE, NULL); 2813a1c8a551SRichard Fitzgerald if (ret & NOTIFY_STOP_MASK) 2814a1c8a551SRichard Fitzgerald return -EINVAL; 2815a1c8a551SRichard Fitzgerald 281666fda75fSMarkus Pargmann ret = _regulator_do_disable(rdev); 2817414c70cbSLiam Girdwood if (ret < 0) { 281861aab5adSMichał Mirosław rdev_err(rdev, "failed to force disable: %pe\n", ERR_PTR(ret)); 2819a1c8a551SRichard Fitzgerald _notifier_call_chain(rdev, REGULATOR_EVENT_FORCE_DISABLE | 2820a1c8a551SRichard Fitzgerald REGULATOR_EVENT_ABORT_DISABLE, NULL); 2821414c70cbSLiam Girdwood return ret; 2822414c70cbSLiam Girdwood } 282366fda75fSMarkus Pargmann 282484b68263SMark Brown _notifier_call_chain(rdev, REGULATOR_EVENT_FORCE_DISABLE | 282584b68263SMark Brown REGULATOR_EVENT_DISABLE, NULL); 2826414c70cbSLiam Girdwood 282766fda75fSMarkus Pargmann return 0; 2828414c70cbSLiam Girdwood } 2829414c70cbSLiam Girdwood 2830414c70cbSLiam Girdwood /** 2831414c70cbSLiam Girdwood * regulator_force_disable - force disable regulator output 2832414c70cbSLiam Girdwood * @regulator: regulator source 2833414c70cbSLiam Girdwood * 2834414c70cbSLiam Girdwood * Forcibly disable the regulator output voltage or current. 2835414c70cbSLiam Girdwood * NOTE: this *will* disable the regulator output even if other consumer 2836414c70cbSLiam Girdwood * devices have it enabled. This should be used for situations when device 2837414c70cbSLiam Girdwood * damage will likely occur if the regulator is not disabled (e.g. over temp). 2838414c70cbSLiam Girdwood */ 2839414c70cbSLiam Girdwood int regulator_force_disable(struct regulator *regulator) 2840414c70cbSLiam Girdwood { 284182d15839SMark Brown struct regulator_dev *rdev = regulator->rdev; 2842f8702f9eSDmitry Osipenko struct ww_acquire_ctx ww_ctx; 2843414c70cbSLiam Girdwood int ret; 2844414c70cbSLiam Girdwood 2845f8702f9eSDmitry Osipenko regulator_lock_dependent(rdev, &ww_ctx); 28465451781dSDouglas Anderson 28473801b86aSMark Brown ret = _regulator_force_disable(regulator->rdev); 28485451781dSDouglas Anderson 28499243a195SMaciej Purski if (rdev->coupling_desc.n_coupled > 1) 28509243a195SMaciej Purski regulator_balance_voltage(rdev, PM_SUSPEND_ON); 28515451781dSDouglas Anderson 28525451781dSDouglas Anderson if (regulator->uA_load) { 28535451781dSDouglas Anderson regulator->uA_load = 0; 28545451781dSDouglas Anderson ret = drms_uA_update(rdev); 28555451781dSDouglas Anderson } 28565451781dSDouglas Anderson 28571fc12b05SDouglas Anderson if (rdev->use_count != 0 && rdev->supply) 28581fc12b05SDouglas Anderson _regulator_disable(rdev->supply); 28598cbf811dSJeffrey Carlyle 28601fc12b05SDouglas Anderson regulator_unlock_dependent(rdev, &ww_ctx); 28618cbf811dSJeffrey Carlyle 2862414c70cbSLiam Girdwood return ret; 2863414c70cbSLiam Girdwood } 2864414c70cbSLiam Girdwood EXPORT_SYMBOL_GPL(regulator_force_disable); 2865414c70cbSLiam Girdwood 2866da07ecd9SMark Brown static void regulator_disable_work(struct work_struct *work) 2867da07ecd9SMark Brown { 2868da07ecd9SMark Brown struct regulator_dev *rdev = container_of(work, struct regulator_dev, 2869da07ecd9SMark Brown disable_work.work); 2870f8702f9eSDmitry Osipenko struct ww_acquire_ctx ww_ctx; 2871da07ecd9SMark Brown int count, i, ret; 28725451781dSDouglas Anderson struct regulator *regulator; 28735451781dSDouglas Anderson int total_count = 0; 2874da07ecd9SMark Brown 2875f8702f9eSDmitry Osipenko regulator_lock_dependent(rdev, &ww_ctx); 2876da07ecd9SMark Brown 2877c9ccaa0cSTirupathi Reddy /* 2878c9ccaa0cSTirupathi Reddy * Workqueue functions queue the new work instance while the previous 2879c9ccaa0cSTirupathi Reddy * work instance is being processed. Cancel the queued work instance 2880c9ccaa0cSTirupathi Reddy * as the work instance under processing does the job of the queued 2881c9ccaa0cSTirupathi Reddy * work instance. 2882c9ccaa0cSTirupathi Reddy */ 2883c9ccaa0cSTirupathi Reddy cancel_delayed_work(&rdev->disable_work); 2884c9ccaa0cSTirupathi Reddy 28855451781dSDouglas Anderson list_for_each_entry(regulator, &rdev->consumer_list, list) { 28865451781dSDouglas Anderson count = regulator->deferred_disables; 28875451781dSDouglas Anderson 28885451781dSDouglas Anderson if (!count) 28895451781dSDouglas Anderson continue; 28905451781dSDouglas Anderson 28915451781dSDouglas Anderson total_count += count; 28925451781dSDouglas Anderson regulator->deferred_disables = 0; 28935451781dSDouglas Anderson 2894da07ecd9SMark Brown for (i = 0; i < count; i++) { 28955451781dSDouglas Anderson ret = _regulator_disable(regulator); 2896da07ecd9SMark Brown if (ret != 0) 289761aab5adSMichał Mirosław rdev_err(rdev, "Deferred disable failed: %pe\n", 289861aab5adSMichał Mirosław ERR_PTR(ret)); 2899da07ecd9SMark Brown } 29005451781dSDouglas Anderson } 29015451781dSDouglas Anderson WARN_ON(!total_count); 2902da07ecd9SMark Brown 2903f8702f9eSDmitry Osipenko if (rdev->coupling_desc.n_coupled > 1) 2904f8702f9eSDmitry Osipenko regulator_balance_voltage(rdev, PM_SUSPEND_ON); 2905f8702f9eSDmitry Osipenko 2906f8702f9eSDmitry Osipenko regulator_unlock_dependent(rdev, &ww_ctx); 2907da07ecd9SMark Brown } 2908da07ecd9SMark Brown 2909da07ecd9SMark Brown /** 2910da07ecd9SMark Brown * regulator_disable_deferred - disable regulator output with delay 2911da07ecd9SMark Brown * @regulator: regulator source 291248f1b4efSKrzysztof Kozlowski * @ms: milliseconds until the regulator is disabled 2913da07ecd9SMark Brown * 2914da07ecd9SMark Brown * Execute regulator_disable() on the regulator after a delay. This 2915da07ecd9SMark Brown * is intended for use with devices that require some time to quiesce. 2916da07ecd9SMark Brown * 2917da07ecd9SMark Brown * NOTE: this will only disable the regulator output if no other consumer 2918da07ecd9SMark Brown * devices have it enabled, the regulator device supports disabling and 2919da07ecd9SMark Brown * machine constraints permit this operation. 2920da07ecd9SMark Brown */ 2921da07ecd9SMark Brown int regulator_disable_deferred(struct regulator *regulator, int ms) 2922da07ecd9SMark Brown { 2923da07ecd9SMark Brown struct regulator_dev *rdev = regulator->rdev; 2924da07ecd9SMark Brown 29252b5a24a0SMark Brown if (!ms) 29262b5a24a0SMark Brown return regulator_disable(regulator); 29272b5a24a0SMark Brown 292866cf9a7eSMaciej Purski regulator_lock(rdev); 29295451781dSDouglas Anderson regulator->deferred_disables++; 2930c9ccaa0cSTirupathi Reddy mod_delayed_work(system_power_efficient_wq, &rdev->disable_work, 2931c9ccaa0cSTirupathi Reddy msecs_to_jiffies(ms)); 293266cf9a7eSMaciej Purski regulator_unlock(rdev); 2933da07ecd9SMark Brown 2934aa59802dSMark Brown return 0; 2935da07ecd9SMark Brown } 2936da07ecd9SMark Brown EXPORT_SYMBOL_GPL(regulator_disable_deferred); 2937da07ecd9SMark Brown 2938414c70cbSLiam Girdwood static int _regulator_is_enabled(struct regulator_dev *rdev) 2939414c70cbSLiam Girdwood { 294065f73508SMark Brown /* A GPIO control always takes precedence */ 29417b74d149SKim, Milo if (rdev->ena_pin) 294265f73508SMark Brown return rdev->ena_gpio_state; 294365f73508SMark Brown 29449a7f6a4cSMark Brown /* If we don't know then assume that the regulator is always on */ 29459332546fSMark Brown if (!rdev->desc->ops->is_enabled) 29469a7f6a4cSMark Brown return 1; 2947414c70cbSLiam Girdwood 29489332546fSMark Brown return rdev->desc->ops->is_enabled(rdev); 2949414c70cbSLiam Girdwood } 2950414c70cbSLiam Girdwood 29513d67fe95SMaciej Purski static int _regulator_list_voltage(struct regulator_dev *rdev, 29523a40cfc3SSascha Hauer unsigned selector, int lock) 29533a40cfc3SSascha Hauer { 29543a40cfc3SSascha Hauer const struct regulator_ops *ops = rdev->desc->ops; 29553a40cfc3SSascha Hauer int ret; 29563a40cfc3SSascha Hauer 29573a40cfc3SSascha Hauer if (rdev->desc->fixed_uV && rdev->desc->n_voltages == 1 && !selector) 29583a40cfc3SSascha Hauer return rdev->desc->fixed_uV; 29593a40cfc3SSascha Hauer 29603a40cfc3SSascha Hauer if (ops->list_voltage) { 29613a40cfc3SSascha Hauer if (selector >= rdev->desc->n_voltages) 29623a40cfc3SSascha Hauer return -EINVAL; 29633a40cfc3SSascha Hauer if (lock) 296466cf9a7eSMaciej Purski regulator_lock(rdev); 29653a40cfc3SSascha Hauer ret = ops->list_voltage(rdev, selector); 29663a40cfc3SSascha Hauer if (lock) 296766cf9a7eSMaciej Purski regulator_unlock(rdev); 2968fd086045SMatthias Kaehlcke } else if (rdev->is_switch && rdev->supply) { 29693d67fe95SMaciej Purski ret = _regulator_list_voltage(rdev->supply->rdev, 29703d67fe95SMaciej Purski selector, lock); 29713a40cfc3SSascha Hauer } else { 29723a40cfc3SSascha Hauer return -EINVAL; 29733a40cfc3SSascha Hauer } 29743a40cfc3SSascha Hauer 29753a40cfc3SSascha Hauer if (ret > 0) { 29763a40cfc3SSascha Hauer if (ret < rdev->constraints->min_uV) 29773a40cfc3SSascha Hauer ret = 0; 29783a40cfc3SSascha Hauer else if (ret > rdev->constraints->max_uV) 29793a40cfc3SSascha Hauer ret = 0; 29803a40cfc3SSascha Hauer } 29813a40cfc3SSascha Hauer 29823a40cfc3SSascha Hauer return ret; 29833a40cfc3SSascha Hauer } 29843a40cfc3SSascha Hauer 2985414c70cbSLiam Girdwood /** 2986414c70cbSLiam Girdwood * regulator_is_enabled - is the regulator output enabled 2987414c70cbSLiam Girdwood * @regulator: regulator source 2988414c70cbSLiam Girdwood * 2989412aec61SDavid Brownell * Returns positive if the regulator driver backing the source/client 2990412aec61SDavid Brownell * has requested that the device be enabled, zero if it hasn't, else a 2991412aec61SDavid Brownell * negative errno code. 2992412aec61SDavid Brownell * 2993412aec61SDavid Brownell * Note that the device backing this regulator handle can have multiple 2994412aec61SDavid Brownell * users, so it might be enabled even if regulator_enable() was never 2995412aec61SDavid Brownell * called for this particular source. 2996414c70cbSLiam Girdwood */ 2997414c70cbSLiam Girdwood int regulator_is_enabled(struct regulator *regulator) 2998414c70cbSLiam Girdwood { 29999332546fSMark Brown int ret; 30009332546fSMark Brown 30016492bc1bSMark Brown if (regulator->always_on) 30026492bc1bSMark Brown return 1; 30036492bc1bSMark Brown 3004f8702f9eSDmitry Osipenko regulator_lock(regulator->rdev); 30059332546fSMark Brown ret = _regulator_is_enabled(regulator->rdev); 3006f8702f9eSDmitry Osipenko regulator_unlock(regulator->rdev); 30079332546fSMark Brown 30089332546fSMark Brown return ret; 3009414c70cbSLiam Girdwood } 3010414c70cbSLiam Girdwood EXPORT_SYMBOL_GPL(regulator_is_enabled); 3011414c70cbSLiam Girdwood 3012414c70cbSLiam Girdwood /** 30134367cfdcSDavid Brownell * regulator_count_voltages - count regulator_list_voltage() selectors 30144367cfdcSDavid Brownell * @regulator: regulator source 30154367cfdcSDavid Brownell * 30164367cfdcSDavid Brownell * Returns number of selectors, or negative errno. Selectors are 30174367cfdcSDavid Brownell * numbered starting at zero, and typically correspond to bitfields 30184367cfdcSDavid Brownell * in hardware registers. 30194367cfdcSDavid Brownell */ 30204367cfdcSDavid Brownell int regulator_count_voltages(struct regulator *regulator) 30214367cfdcSDavid Brownell { 30224367cfdcSDavid Brownell struct regulator_dev *rdev = regulator->rdev; 30234367cfdcSDavid Brownell 302426988efeSJavier Martinez Canillas if (rdev->desc->n_voltages) 302526988efeSJavier Martinez Canillas return rdev->desc->n_voltages; 302626988efeSJavier Martinez Canillas 3027fd086045SMatthias Kaehlcke if (!rdev->is_switch || !rdev->supply) 302826988efeSJavier Martinez Canillas return -EINVAL; 302926988efeSJavier Martinez Canillas 303026988efeSJavier Martinez Canillas return regulator_count_voltages(rdev->supply); 30314367cfdcSDavid Brownell } 30324367cfdcSDavid Brownell EXPORT_SYMBOL_GPL(regulator_count_voltages); 30334367cfdcSDavid Brownell 30344367cfdcSDavid Brownell /** 30354367cfdcSDavid Brownell * regulator_list_voltage - enumerate supported voltages 30364367cfdcSDavid Brownell * @regulator: regulator source 30374367cfdcSDavid Brownell * @selector: identify voltage to list 30384367cfdcSDavid Brownell * Context: can sleep 30394367cfdcSDavid Brownell * 30404367cfdcSDavid Brownell * Returns a voltage that can be passed to @regulator_set_voltage(), 304188393161SThomas Weber * zero if this selector code can't be used on this system, or a 30424367cfdcSDavid Brownell * negative errno. 30434367cfdcSDavid Brownell */ 30444367cfdcSDavid Brownell int regulator_list_voltage(struct regulator *regulator, unsigned selector) 30454367cfdcSDavid Brownell { 30463d67fe95SMaciej Purski return _regulator_list_voltage(regulator->rdev, selector, 1); 30474367cfdcSDavid Brownell } 30484367cfdcSDavid Brownell EXPORT_SYMBOL_GPL(regulator_list_voltage); 30494367cfdcSDavid Brownell 30504367cfdcSDavid Brownell /** 305104eca28cSTuomas Tynkkynen * regulator_get_regmap - get the regulator's register map 305204eca28cSTuomas Tynkkynen * @regulator: regulator source 305304eca28cSTuomas Tynkkynen * 305404eca28cSTuomas Tynkkynen * Returns the register map for the given regulator, or an ERR_PTR value 305504eca28cSTuomas Tynkkynen * if the regulator doesn't use regmap. 305604eca28cSTuomas Tynkkynen */ 305704eca28cSTuomas Tynkkynen struct regmap *regulator_get_regmap(struct regulator *regulator) 305804eca28cSTuomas Tynkkynen { 305904eca28cSTuomas Tynkkynen struct regmap *map = regulator->rdev->regmap; 306004eca28cSTuomas Tynkkynen 306104eca28cSTuomas Tynkkynen return map ? map : ERR_PTR(-EOPNOTSUPP); 306204eca28cSTuomas Tynkkynen } 306304eca28cSTuomas Tynkkynen 306404eca28cSTuomas Tynkkynen /** 306504eca28cSTuomas Tynkkynen * regulator_get_hardware_vsel_register - get the HW voltage selector register 306604eca28cSTuomas Tynkkynen * @regulator: regulator source 306704eca28cSTuomas Tynkkynen * @vsel_reg: voltage selector register, output parameter 306804eca28cSTuomas Tynkkynen * @vsel_mask: mask for voltage selector bitfield, output parameter 306904eca28cSTuomas Tynkkynen * 307004eca28cSTuomas Tynkkynen * Returns the hardware register offset and bitmask used for setting the 307104eca28cSTuomas Tynkkynen * regulator voltage. This might be useful when configuring voltage-scaling 307204eca28cSTuomas Tynkkynen * hardware or firmware that can make I2C requests behind the kernel's back, 307304eca28cSTuomas Tynkkynen * for example. 307404eca28cSTuomas Tynkkynen * 307504eca28cSTuomas Tynkkynen * On success, the output parameters @vsel_reg and @vsel_mask are filled in 307604eca28cSTuomas Tynkkynen * and 0 is returned, otherwise a negative errno is returned. 307704eca28cSTuomas Tynkkynen */ 307804eca28cSTuomas Tynkkynen int regulator_get_hardware_vsel_register(struct regulator *regulator, 307904eca28cSTuomas Tynkkynen unsigned *vsel_reg, 308004eca28cSTuomas Tynkkynen unsigned *vsel_mask) 308104eca28cSTuomas Tynkkynen { 308204eca28cSTuomas Tynkkynen struct regulator_dev *rdev = regulator->rdev; 308339f5460dSGuodong Xu const struct regulator_ops *ops = rdev->desc->ops; 308404eca28cSTuomas Tynkkynen 308504eca28cSTuomas Tynkkynen if (ops->set_voltage_sel != regulator_set_voltage_sel_regmap) 308604eca28cSTuomas Tynkkynen return -EOPNOTSUPP; 308704eca28cSTuomas Tynkkynen 308804eca28cSTuomas Tynkkynen *vsel_reg = rdev->desc->vsel_reg; 308904eca28cSTuomas Tynkkynen *vsel_mask = rdev->desc->vsel_mask; 309004eca28cSTuomas Tynkkynen 309104eca28cSTuomas Tynkkynen return 0; 309204eca28cSTuomas Tynkkynen } 309304eca28cSTuomas Tynkkynen EXPORT_SYMBOL_GPL(regulator_get_hardware_vsel_register); 309404eca28cSTuomas Tynkkynen 309504eca28cSTuomas Tynkkynen /** 309604eca28cSTuomas Tynkkynen * regulator_list_hardware_vsel - get the HW-specific register value for a selector 309704eca28cSTuomas Tynkkynen * @regulator: regulator source 309804eca28cSTuomas Tynkkynen * @selector: identify voltage to list 309904eca28cSTuomas Tynkkynen * 310004eca28cSTuomas Tynkkynen * Converts the selector to a hardware-specific voltage selector that can be 310104eca28cSTuomas Tynkkynen * directly written to the regulator registers. The address of the voltage 310204eca28cSTuomas Tynkkynen * register can be determined by calling @regulator_get_hardware_vsel_register. 310304eca28cSTuomas Tynkkynen * 310404eca28cSTuomas Tynkkynen * On error a negative errno is returned. 310504eca28cSTuomas Tynkkynen */ 310604eca28cSTuomas Tynkkynen int regulator_list_hardware_vsel(struct regulator *regulator, 310704eca28cSTuomas Tynkkynen unsigned selector) 310804eca28cSTuomas Tynkkynen { 310904eca28cSTuomas Tynkkynen struct regulator_dev *rdev = regulator->rdev; 311039f5460dSGuodong Xu const struct regulator_ops *ops = rdev->desc->ops; 311104eca28cSTuomas Tynkkynen 311204eca28cSTuomas Tynkkynen if (selector >= rdev->desc->n_voltages) 311304eca28cSTuomas Tynkkynen return -EINVAL; 311404eca28cSTuomas Tynkkynen if (ops->set_voltage_sel != regulator_set_voltage_sel_regmap) 311504eca28cSTuomas Tynkkynen return -EOPNOTSUPP; 311604eca28cSTuomas Tynkkynen 311704eca28cSTuomas Tynkkynen return selector; 311804eca28cSTuomas Tynkkynen } 311904eca28cSTuomas Tynkkynen EXPORT_SYMBOL_GPL(regulator_list_hardware_vsel); 312004eca28cSTuomas Tynkkynen 312104eca28cSTuomas Tynkkynen /** 31222a668a8bSPaul Walmsley * regulator_get_linear_step - return the voltage step size between VSEL values 31232a668a8bSPaul Walmsley * @regulator: regulator source 31242a668a8bSPaul Walmsley * 31252a668a8bSPaul Walmsley * Returns the voltage step size between VSEL values for linear 31262a668a8bSPaul Walmsley * regulators, or return 0 if the regulator isn't a linear regulator. 31272a668a8bSPaul Walmsley */ 31282a668a8bSPaul Walmsley unsigned int regulator_get_linear_step(struct regulator *regulator) 31292a668a8bSPaul Walmsley { 31302a668a8bSPaul Walmsley struct regulator_dev *rdev = regulator->rdev; 31312a668a8bSPaul Walmsley 31322a668a8bSPaul Walmsley return rdev->desc->uV_step; 31332a668a8bSPaul Walmsley } 31342a668a8bSPaul Walmsley EXPORT_SYMBOL_GPL(regulator_get_linear_step); 31352a668a8bSPaul Walmsley 31362a668a8bSPaul Walmsley /** 3137a7a1ad90SMark Brown * regulator_is_supported_voltage - check if a voltage range can be supported 3138a7a1ad90SMark Brown * 3139a7a1ad90SMark Brown * @regulator: Regulator to check. 3140a7a1ad90SMark Brown * @min_uV: Minimum required voltage in uV. 3141a7a1ad90SMark Brown * @max_uV: Maximum required voltage in uV. 3142a7a1ad90SMark Brown * 314349820944SJorge Ramirez-Ortiz * Returns a boolean. 3144a7a1ad90SMark Brown */ 3145a7a1ad90SMark Brown int regulator_is_supported_voltage(struct regulator *regulator, 3146a7a1ad90SMark Brown int min_uV, int max_uV) 3147a7a1ad90SMark Brown { 3148c5f3939bSMark Brown struct regulator_dev *rdev = regulator->rdev; 3149a7a1ad90SMark Brown int i, voltages, ret; 3150a7a1ad90SMark Brown 3151c5f3939bSMark Brown /* If we can't change voltage check the current voltage */ 31528a34e979SWEN Pingbo if (!regulator_ops_is_valid(rdev, REGULATOR_CHANGE_VOLTAGE)) { 3153c5f3939bSMark Brown ret = regulator_get_voltage(regulator); 3154c5f3939bSMark Brown if (ret >= 0) 31550d25d09dSJingoo Han return min_uV <= ret && ret <= max_uV; 3156c5f3939bSMark Brown else 3157c5f3939bSMark Brown return ret; 3158c5f3939bSMark Brown } 3159c5f3939bSMark Brown 3160bd7a2b60SPawel Moll /* Any voltage within constrains range is fine? */ 3161bd7a2b60SPawel Moll if (rdev->desc->continuous_voltage_range) 3162bd7a2b60SPawel Moll return min_uV >= rdev->constraints->min_uV && 3163bd7a2b60SPawel Moll max_uV <= rdev->constraints->max_uV; 3164bd7a2b60SPawel Moll 3165a7a1ad90SMark Brown ret = regulator_count_voltages(regulator); 3166a7a1ad90SMark Brown if (ret < 0) 316749820944SJorge Ramirez-Ortiz return 0; 3168a7a1ad90SMark Brown voltages = ret; 3169a7a1ad90SMark Brown 3170a7a1ad90SMark Brown for (i = 0; i < voltages; i++) { 3171a7a1ad90SMark Brown ret = regulator_list_voltage(regulator, i); 3172a7a1ad90SMark Brown 3173a7a1ad90SMark Brown if (ret >= min_uV && ret <= max_uV) 3174a7a1ad90SMark Brown return 1; 3175a7a1ad90SMark Brown } 3176a7a1ad90SMark Brown 3177a7a1ad90SMark Brown return 0; 3178a7a1ad90SMark Brown } 3179a398eaa2SMark Brown EXPORT_SYMBOL_GPL(regulator_is_supported_voltage); 3180a7a1ad90SMark Brown 3181a204f41eSSascha Hauer static int regulator_map_voltage(struct regulator_dev *rdev, int min_uV, 3182a204f41eSSascha Hauer int max_uV) 3183a204f41eSSascha Hauer { 3184a204f41eSSascha Hauer const struct regulator_desc *desc = rdev->desc; 3185a204f41eSSascha Hauer 3186a204f41eSSascha Hauer if (desc->ops->map_voltage) 3187a204f41eSSascha Hauer return desc->ops->map_voltage(rdev, min_uV, max_uV); 3188a204f41eSSascha Hauer 3189a204f41eSSascha Hauer if (desc->ops->list_voltage == regulator_list_voltage_linear) 3190a204f41eSSascha Hauer return regulator_map_voltage_linear(rdev, min_uV, max_uV); 3191a204f41eSSascha Hauer 3192a204f41eSSascha Hauer if (desc->ops->list_voltage == regulator_list_voltage_linear_range) 3193a204f41eSSascha Hauer return regulator_map_voltage_linear_range(rdev, min_uV, max_uV); 3194a204f41eSSascha Hauer 319518e4b55fSMatti Vaittinen if (desc->ops->list_voltage == 319618e4b55fSMatti Vaittinen regulator_list_voltage_pickable_linear_range) 319718e4b55fSMatti Vaittinen return regulator_map_voltage_pickable_linear_range(rdev, 319818e4b55fSMatti Vaittinen min_uV, max_uV); 319918e4b55fSMatti Vaittinen 3200a204f41eSSascha Hauer return regulator_map_voltage_iterate(rdev, min_uV, max_uV); 3201a204f41eSSascha Hauer } 3202a204f41eSSascha Hauer 32037179569aSHeiko Stübner static int _regulator_call_set_voltage(struct regulator_dev *rdev, 32047179569aSHeiko Stübner int min_uV, int max_uV, 32057179569aSHeiko Stübner unsigned *selector) 32067179569aSHeiko Stübner { 32077179569aSHeiko Stübner struct pre_voltage_change_data data; 32087179569aSHeiko Stübner int ret; 32097179569aSHeiko Stübner 3210d22b85a1SDmitry Osipenko data.old_uV = regulator_get_voltage_rdev(rdev); 32117179569aSHeiko Stübner data.min_uV = min_uV; 32127179569aSHeiko Stübner data.max_uV = max_uV; 32137179569aSHeiko Stübner ret = _notifier_call_chain(rdev, REGULATOR_EVENT_PRE_VOLTAGE_CHANGE, 32147179569aSHeiko Stübner &data); 32157179569aSHeiko Stübner if (ret & NOTIFY_STOP_MASK) 32167179569aSHeiko Stübner return -EINVAL; 32177179569aSHeiko Stübner 32187179569aSHeiko Stübner ret = rdev->desc->ops->set_voltage(rdev, min_uV, max_uV, selector); 32197179569aSHeiko Stübner if (ret >= 0) 32207179569aSHeiko Stübner return ret; 32217179569aSHeiko Stübner 32227179569aSHeiko Stübner _notifier_call_chain(rdev, REGULATOR_EVENT_ABORT_VOLTAGE_CHANGE, 32237179569aSHeiko Stübner (void *)data.old_uV); 32247179569aSHeiko Stübner 32257179569aSHeiko Stübner return ret; 32267179569aSHeiko Stübner } 32277179569aSHeiko Stübner 32287179569aSHeiko Stübner static int _regulator_call_set_voltage_sel(struct regulator_dev *rdev, 32297179569aSHeiko Stübner int uV, unsigned selector) 32307179569aSHeiko Stübner { 32317179569aSHeiko Stübner struct pre_voltage_change_data data; 32327179569aSHeiko Stübner int ret; 32337179569aSHeiko Stübner 3234d22b85a1SDmitry Osipenko data.old_uV = regulator_get_voltage_rdev(rdev); 32357179569aSHeiko Stübner data.min_uV = uV; 32367179569aSHeiko Stübner data.max_uV = uV; 32377179569aSHeiko Stübner ret = _notifier_call_chain(rdev, REGULATOR_EVENT_PRE_VOLTAGE_CHANGE, 32387179569aSHeiko Stübner &data); 32397179569aSHeiko Stübner if (ret & NOTIFY_STOP_MASK) 32407179569aSHeiko Stübner return -EINVAL; 32417179569aSHeiko Stübner 32427179569aSHeiko Stübner ret = rdev->desc->ops->set_voltage_sel(rdev, selector); 32437179569aSHeiko Stübner if (ret >= 0) 32447179569aSHeiko Stübner return ret; 32457179569aSHeiko Stübner 32467179569aSHeiko Stübner _notifier_call_chain(rdev, REGULATOR_EVENT_ABORT_VOLTAGE_CHANGE, 32477179569aSHeiko Stübner (void *)data.old_uV); 32487179569aSHeiko Stübner 32497179569aSHeiko Stübner return ret; 32507179569aSHeiko Stübner } 32517179569aSHeiko Stübner 32522da8d947SBartosz Golaszewski static int _regulator_set_voltage_sel_step(struct regulator_dev *rdev, 32532da8d947SBartosz Golaszewski int uV, int new_selector) 32542da8d947SBartosz Golaszewski { 32552da8d947SBartosz Golaszewski const struct regulator_ops *ops = rdev->desc->ops; 32562da8d947SBartosz Golaszewski int diff, old_sel, curr_sel, ret; 32572da8d947SBartosz Golaszewski 32582da8d947SBartosz Golaszewski /* Stepping is only needed if the regulator is enabled. */ 32592da8d947SBartosz Golaszewski if (!_regulator_is_enabled(rdev)) 32602da8d947SBartosz Golaszewski goto final_set; 32612da8d947SBartosz Golaszewski 32622da8d947SBartosz Golaszewski if (!ops->get_voltage_sel) 32632da8d947SBartosz Golaszewski return -EINVAL; 32642da8d947SBartosz Golaszewski 32652da8d947SBartosz Golaszewski old_sel = ops->get_voltage_sel(rdev); 32662da8d947SBartosz Golaszewski if (old_sel < 0) 32672da8d947SBartosz Golaszewski return old_sel; 32682da8d947SBartosz Golaszewski 32692da8d947SBartosz Golaszewski diff = new_selector - old_sel; 32702da8d947SBartosz Golaszewski if (diff == 0) 32712da8d947SBartosz Golaszewski return 0; /* No change needed. */ 32722da8d947SBartosz Golaszewski 32732da8d947SBartosz Golaszewski if (diff > 0) { 32742da8d947SBartosz Golaszewski /* Stepping up. */ 32752da8d947SBartosz Golaszewski for (curr_sel = old_sel + rdev->desc->vsel_step; 32762da8d947SBartosz Golaszewski curr_sel < new_selector; 32772da8d947SBartosz Golaszewski curr_sel += rdev->desc->vsel_step) { 32782da8d947SBartosz Golaszewski /* 32792da8d947SBartosz Golaszewski * Call the callback directly instead of using 32802da8d947SBartosz Golaszewski * _regulator_call_set_voltage_sel() as we don't 32812da8d947SBartosz Golaszewski * want to notify anyone yet. Same in the branch 32822da8d947SBartosz Golaszewski * below. 32832da8d947SBartosz Golaszewski */ 32842da8d947SBartosz Golaszewski ret = ops->set_voltage_sel(rdev, curr_sel); 32852da8d947SBartosz Golaszewski if (ret) 32862da8d947SBartosz Golaszewski goto try_revert; 32872da8d947SBartosz Golaszewski } 32882da8d947SBartosz Golaszewski } else { 32892da8d947SBartosz Golaszewski /* Stepping down. */ 32902da8d947SBartosz Golaszewski for (curr_sel = old_sel - rdev->desc->vsel_step; 32912da8d947SBartosz Golaszewski curr_sel > new_selector; 32922da8d947SBartosz Golaszewski curr_sel -= rdev->desc->vsel_step) { 32932da8d947SBartosz Golaszewski ret = ops->set_voltage_sel(rdev, curr_sel); 32942da8d947SBartosz Golaszewski if (ret) 32952da8d947SBartosz Golaszewski goto try_revert; 32962da8d947SBartosz Golaszewski } 32972da8d947SBartosz Golaszewski } 32982da8d947SBartosz Golaszewski 32992da8d947SBartosz Golaszewski final_set: 33002da8d947SBartosz Golaszewski /* The final selector will trigger the notifiers. */ 33012da8d947SBartosz Golaszewski return _regulator_call_set_voltage_sel(rdev, uV, new_selector); 33022da8d947SBartosz Golaszewski 33032da8d947SBartosz Golaszewski try_revert: 33042da8d947SBartosz Golaszewski /* 33052da8d947SBartosz Golaszewski * At least try to return to the previous voltage if setting a new 33062da8d947SBartosz Golaszewski * one failed. 33072da8d947SBartosz Golaszewski */ 33082da8d947SBartosz Golaszewski (void)ops->set_voltage_sel(rdev, old_sel); 33092da8d947SBartosz Golaszewski return ret; 33102da8d947SBartosz Golaszewski } 33112da8d947SBartosz Golaszewski 331273e705bfSMatthias Kaehlcke static int _regulator_set_voltage_time(struct regulator_dev *rdev, 331373e705bfSMatthias Kaehlcke int old_uV, int new_uV) 331473e705bfSMatthias Kaehlcke { 331573e705bfSMatthias Kaehlcke unsigned int ramp_delay = 0; 331673e705bfSMatthias Kaehlcke 331773e705bfSMatthias Kaehlcke if (rdev->constraints->ramp_delay) 331873e705bfSMatthias Kaehlcke ramp_delay = rdev->constraints->ramp_delay; 331973e705bfSMatthias Kaehlcke else if (rdev->desc->ramp_delay) 332073e705bfSMatthias Kaehlcke ramp_delay = rdev->desc->ramp_delay; 3321d6c1dc3fSLaxman Dewangan else if (rdev->constraints->settling_time) 3322d6c1dc3fSLaxman Dewangan return rdev->constraints->settling_time; 33233ffad468SMatthias Kaehlcke else if (rdev->constraints->settling_time_up && 33243ffad468SMatthias Kaehlcke (new_uV > old_uV)) 33253ffad468SMatthias Kaehlcke return rdev->constraints->settling_time_up; 33263ffad468SMatthias Kaehlcke else if (rdev->constraints->settling_time_down && 33273ffad468SMatthias Kaehlcke (new_uV < old_uV)) 33283ffad468SMatthias Kaehlcke return rdev->constraints->settling_time_down; 332973e705bfSMatthias Kaehlcke 333073e705bfSMatthias Kaehlcke if (ramp_delay == 0) { 3331ba14fa1aSH. Nikolaus Schaller rdev_dbg(rdev, "ramp_delay not set\n"); 333273e705bfSMatthias Kaehlcke return 0; 333373e705bfSMatthias Kaehlcke } 333473e705bfSMatthias Kaehlcke 333573e705bfSMatthias Kaehlcke return DIV_ROUND_UP(abs(new_uV - old_uV), ramp_delay); 333673e705bfSMatthias Kaehlcke } 333773e705bfSMatthias Kaehlcke 333875790251SMark Brown static int _regulator_do_set_voltage(struct regulator_dev *rdev, 333975790251SMark Brown int min_uV, int max_uV) 334075790251SMark Brown { 334175790251SMark Brown int ret; 334277af1b26SLinus Walleij int delay = 0; 3343e113d792SMark Brown int best_val = 0; 334475790251SMark Brown unsigned int selector; 3345eba41a5eSAxel Lin int old_selector = -1; 334657995a48SMatthias Kaehlcke const struct regulator_ops *ops = rdev->desc->ops; 3347d22b85a1SDmitry Osipenko int old_uV = regulator_get_voltage_rdev(rdev); 334875790251SMark Brown 334975790251SMark Brown trace_regulator_set_voltage(rdev_get_name(rdev), min_uV, max_uV); 335075790251SMark Brown 3351bf5892a8SMark Brown min_uV += rdev->constraints->uV_offset; 3352bf5892a8SMark Brown max_uV += rdev->constraints->uV_offset; 3353bf5892a8SMark Brown 335477af1b26SLinus Walleij /* 335577af1b26SLinus Walleij * If we can't obtain the old selector there is not enough 335677af1b26SLinus Walleij * info to call set_voltage_time_sel(). 335777af1b26SLinus Walleij */ 33588b7485efSAxel Lin if (_regulator_is_enabled(rdev) && 335957995a48SMatthias Kaehlcke ops->set_voltage_time_sel && ops->get_voltage_sel) { 336057995a48SMatthias Kaehlcke old_selector = ops->get_voltage_sel(rdev); 3361eba41a5eSAxel Lin if (old_selector < 0) 3362eba41a5eSAxel Lin return old_selector; 3363eba41a5eSAxel Lin } 336477af1b26SLinus Walleij 336557995a48SMatthias Kaehlcke if (ops->set_voltage) { 33667179569aSHeiko Stübner ret = _regulator_call_set_voltage(rdev, min_uV, max_uV, 336775790251SMark Brown &selector); 3368e113d792SMark Brown 3369e113d792SMark Brown if (ret >= 0) { 337057995a48SMatthias Kaehlcke if (ops->list_voltage) 337157995a48SMatthias Kaehlcke best_val = ops->list_voltage(rdev, 3372e113d792SMark Brown selector); 3373e113d792SMark Brown else 3374d22b85a1SDmitry Osipenko best_val = regulator_get_voltage_rdev(rdev); 3375e113d792SMark Brown } 3376e113d792SMark Brown 337757995a48SMatthias Kaehlcke } else if (ops->set_voltage_sel) { 3378a204f41eSSascha Hauer ret = regulator_map_voltage(rdev, min_uV, max_uV); 3379e843fc46SMark Brown if (ret >= 0) { 338057995a48SMatthias Kaehlcke best_val = ops->list_voltage(rdev, ret); 3381e113d792SMark Brown if (min_uV <= best_val && max_uV >= best_val) { 3382e843fc46SMark Brown selector = ret; 3383c66a566aSAxel Lin if (old_selector == selector) 3384c66a566aSAxel Lin ret = 0; 33852da8d947SBartosz Golaszewski else if (rdev->desc->vsel_step) 33862da8d947SBartosz Golaszewski ret = _regulator_set_voltage_sel_step( 33872da8d947SBartosz Golaszewski rdev, best_val, selector); 3388c66a566aSAxel Lin else 33897179569aSHeiko Stübner ret = _regulator_call_set_voltage_sel( 33907179569aSHeiko Stübner rdev, best_val, selector); 3391e113d792SMark Brown } else { 3392e113d792SMark Brown ret = -EINVAL; 3393e113d792SMark Brown } 3394e843fc46SMark Brown } 3395e8eef82bSMark Brown } else { 3396e8eef82bSMark Brown ret = -EINVAL; 3397e8eef82bSMark Brown } 3398e8eef82bSMark Brown 339931dfe686SMatthias Kaehlcke if (ret) 340031dfe686SMatthias Kaehlcke goto out; 3401eba41a5eSAxel Lin 340273e705bfSMatthias Kaehlcke if (ops->set_voltage_time_sel) { 340373e705bfSMatthias Kaehlcke /* 340473e705bfSMatthias Kaehlcke * Call set_voltage_time_sel if successfully obtained 340573e705bfSMatthias Kaehlcke * old_selector 340673e705bfSMatthias Kaehlcke */ 340773e705bfSMatthias Kaehlcke if (old_selector >= 0 && old_selector != selector) 340873e705bfSMatthias Kaehlcke delay = ops->set_voltage_time_sel(rdev, old_selector, 340973e705bfSMatthias Kaehlcke selector); 341073e705bfSMatthias Kaehlcke } else { 341173e705bfSMatthias Kaehlcke if (old_uV != best_val) { 341273e705bfSMatthias Kaehlcke if (ops->set_voltage_time) 341373e705bfSMatthias Kaehlcke delay = ops->set_voltage_time(rdev, old_uV, 341473e705bfSMatthias Kaehlcke best_val); 341573e705bfSMatthias Kaehlcke else 341673e705bfSMatthias Kaehlcke delay = _regulator_set_voltage_time(rdev, 341773e705bfSMatthias Kaehlcke old_uV, 341873e705bfSMatthias Kaehlcke best_val); 341973e705bfSMatthias Kaehlcke } 342073e705bfSMatthias Kaehlcke } 342173e705bfSMatthias Kaehlcke 3422eba41a5eSAxel Lin if (delay < 0) { 342361aab5adSMichał Mirosław rdev_warn(rdev, "failed to get delay: %pe\n", ERR_PTR(delay)); 3424eba41a5eSAxel Lin delay = 0; 3425e8eef82bSMark Brown } 342675790251SMark Brown 342777af1b26SLinus Walleij /* Insert any necessary delays */ 342877af1b26SLinus Walleij if (delay >= 1000) { 342977af1b26SLinus Walleij mdelay(delay / 1000); 343077af1b26SLinus Walleij udelay(delay % 1000); 343177af1b26SLinus Walleij } else if (delay) { 343277af1b26SLinus Walleij udelay(delay); 343377af1b26SLinus Walleij } 343477af1b26SLinus Walleij 343531dfe686SMatthias Kaehlcke if (best_val >= 0) { 34362f6c797fSAxel Lin unsigned long data = best_val; 34372f6c797fSAxel Lin 3438ded06a52SMark Brown _notifier_call_chain(rdev, REGULATOR_EVENT_VOLTAGE_CHANGE, 34392f6c797fSAxel Lin (void *)data); 34402f6c797fSAxel Lin } 3441ded06a52SMark Brown 344231dfe686SMatthias Kaehlcke out: 3443eba41a5eSAxel Lin trace_regulator_set_voltage_complete(rdev_get_name(rdev), best_val); 344475790251SMark Brown 344575790251SMark Brown return ret; 344675790251SMark Brown } 344775790251SMark Brown 3448f7efad10SChunyan Zhang static int _regulator_do_set_suspend_voltage(struct regulator_dev *rdev, 3449f7efad10SChunyan Zhang int min_uV, int max_uV, suspend_state_t state) 3450f7efad10SChunyan Zhang { 3451f7efad10SChunyan Zhang struct regulator_state *rstate; 3452f7efad10SChunyan Zhang int uV, sel; 3453f7efad10SChunyan Zhang 3454f7efad10SChunyan Zhang rstate = regulator_get_suspend_state(rdev, state); 3455f7efad10SChunyan Zhang if (rstate == NULL) 3456f7efad10SChunyan Zhang return -EINVAL; 3457f7efad10SChunyan Zhang 3458f7efad10SChunyan Zhang if (min_uV < rstate->min_uV) 3459f7efad10SChunyan Zhang min_uV = rstate->min_uV; 3460f7efad10SChunyan Zhang if (max_uV > rstate->max_uV) 3461f7efad10SChunyan Zhang max_uV = rstate->max_uV; 3462f7efad10SChunyan Zhang 3463f7efad10SChunyan Zhang sel = regulator_map_voltage(rdev, min_uV, max_uV); 3464f7efad10SChunyan Zhang if (sel < 0) 3465f7efad10SChunyan Zhang return sel; 3466f7efad10SChunyan Zhang 3467f7efad10SChunyan Zhang uV = rdev->desc->ops->list_voltage(rdev, sel); 3468f7efad10SChunyan Zhang if (uV >= min_uV && uV <= max_uV) 3469f7efad10SChunyan Zhang rstate->uV = uV; 3470f7efad10SChunyan Zhang 3471f7efad10SChunyan Zhang return 0; 3472f7efad10SChunyan Zhang } 3473f7efad10SChunyan Zhang 3474a9f226bcSSascha Hauer static int regulator_set_voltage_unlocked(struct regulator *regulator, 3475c360a6dfSChunyan Zhang int min_uV, int max_uV, 3476c360a6dfSChunyan Zhang suspend_state_t state) 3477414c70cbSLiam Girdwood { 3478414c70cbSLiam Girdwood struct regulator_dev *rdev = regulator->rdev; 3479c360a6dfSChunyan Zhang struct regulator_voltage *voltage = ®ulator->voltage[state]; 348095a3c23aSMark Brown int ret = 0; 348192d7a558SPaolo Pisati int old_min_uV, old_max_uV; 3482c00dc359SBjorn Andersson int current_uV; 3483414c70cbSLiam Girdwood 348495a3c23aSMark Brown /* If we're setting the same range as last time the change 348595a3c23aSMark Brown * should be a noop (some cpufreq implementations use the same 348695a3c23aSMark Brown * voltage for multiple frequencies, for example). 348795a3c23aSMark Brown */ 3488c360a6dfSChunyan Zhang if (voltage->min_uV == min_uV && voltage->max_uV == max_uV) 348995a3c23aSMark Brown goto out; 349095a3c23aSMark Brown 3491c00dc359SBjorn Andersson /* If we're trying to set a range that overlaps the current voltage, 3492d3fb9800SViresh Kumar * return successfully even though the regulator does not support 3493c00dc359SBjorn Andersson * changing the voltage. 3494c00dc359SBjorn Andersson */ 34958a34e979SWEN Pingbo if (!regulator_ops_is_valid(rdev, REGULATOR_CHANGE_VOLTAGE)) { 3496d22b85a1SDmitry Osipenko current_uV = regulator_get_voltage_rdev(rdev); 3497c00dc359SBjorn Andersson if (min_uV <= current_uV && current_uV <= max_uV) { 3498c360a6dfSChunyan Zhang voltage->min_uV = min_uV; 3499c360a6dfSChunyan Zhang voltage->max_uV = max_uV; 3500c00dc359SBjorn Andersson goto out; 3501c00dc359SBjorn Andersson } 3502c00dc359SBjorn Andersson } 3503c00dc359SBjorn Andersson 3504414c70cbSLiam Girdwood /* sanity check */ 3505e8eef82bSMark Brown if (!rdev->desc->ops->set_voltage && 3506e8eef82bSMark Brown !rdev->desc->ops->set_voltage_sel) { 3507414c70cbSLiam Girdwood ret = -EINVAL; 3508414c70cbSLiam Girdwood goto out; 3509414c70cbSLiam Girdwood } 3510414c70cbSLiam Girdwood 3511414c70cbSLiam Girdwood /* constraints check */ 3512414c70cbSLiam Girdwood ret = regulator_check_voltage(rdev, &min_uV, &max_uV); 3513414c70cbSLiam Girdwood if (ret < 0) 3514414c70cbSLiam Girdwood goto out; 351592d7a558SPaolo Pisati 351692d7a558SPaolo Pisati /* restore original values in case of error */ 3517c360a6dfSChunyan Zhang old_min_uV = voltage->min_uV; 3518c360a6dfSChunyan Zhang old_max_uV = voltage->max_uV; 3519c360a6dfSChunyan Zhang voltage->min_uV = min_uV; 3520c360a6dfSChunyan Zhang voltage->max_uV = max_uV; 35213a93f2a9SMark Brown 35229243a195SMaciej Purski /* for not coupled regulators this will just set the voltage */ 35239243a195SMaciej Purski ret = regulator_balance_voltage(rdev, state); 352470b46491SSteve Twiss if (ret < 0) { 35259243a195SMaciej Purski voltage->min_uV = old_min_uV; 35269243a195SMaciej Purski voltage->max_uV = old_max_uV; 352770b46491SSteve Twiss } 35289243a195SMaciej Purski 352970b46491SSteve Twiss out: 35309243a195SMaciej Purski return ret; 35319243a195SMaciej Purski } 35329243a195SMaciej Purski 3533d22b85a1SDmitry Osipenko int regulator_set_voltage_rdev(struct regulator_dev *rdev, int min_uV, 35349243a195SMaciej Purski int max_uV, suspend_state_t state) 35359243a195SMaciej Purski { 35369243a195SMaciej Purski int best_supply_uV = 0; 35379243a195SMaciej Purski int supply_change_uV = 0; 35389243a195SMaciej Purski int ret; 35399243a195SMaciej Purski 354043fc99f2SMark Brown if (rdev->supply && 354143fc99f2SMark Brown regulator_ops_is_valid(rdev->supply->rdev, 354243fc99f2SMark Brown REGULATOR_CHANGE_VOLTAGE) && 35432c2874b1STirupathi Reddy (rdev->desc->min_dropout_uV || !(rdev->desc->ops->get_voltage || 35442c2874b1STirupathi Reddy rdev->desc->ops->get_voltage_sel))) { 3545fc42112cSSascha Hauer int current_supply_uV; 3546fc42112cSSascha Hauer int selector; 3547fc42112cSSascha Hauer 3548fc42112cSSascha Hauer selector = regulator_map_voltage(rdev, min_uV, max_uV); 3549fc42112cSSascha Hauer if (selector < 0) { 3550fc42112cSSascha Hauer ret = selector; 35519243a195SMaciej Purski goto out; 3552fc42112cSSascha Hauer } 3553fc42112cSSascha Hauer 355400cb9f4fSMark Brown best_supply_uV = _regulator_list_voltage(rdev, selector, 0); 3555fc42112cSSascha Hauer if (best_supply_uV < 0) { 3556fc42112cSSascha Hauer ret = best_supply_uV; 35579243a195SMaciej Purski goto out; 3558fc42112cSSascha Hauer } 3559fc42112cSSascha Hauer 3560fc42112cSSascha Hauer best_supply_uV += rdev->desc->min_dropout_uV; 3561fc42112cSSascha Hauer 3562d22b85a1SDmitry Osipenko current_supply_uV = regulator_get_voltage_rdev(rdev->supply->rdev); 3563fc42112cSSascha Hauer if (current_supply_uV < 0) { 3564fc42112cSSascha Hauer ret = current_supply_uV; 35659243a195SMaciej Purski goto out; 3566fc42112cSSascha Hauer } 3567fc42112cSSascha Hauer 3568fc42112cSSascha Hauer supply_change_uV = best_supply_uV - current_supply_uV; 3569fc42112cSSascha Hauer } 3570fc42112cSSascha Hauer 3571fc42112cSSascha Hauer if (supply_change_uV > 0) { 3572fc42112cSSascha Hauer ret = regulator_set_voltage_unlocked(rdev->supply, 3573c360a6dfSChunyan Zhang best_supply_uV, INT_MAX, state); 3574fc42112cSSascha Hauer if (ret) { 357561aab5adSMichał Mirosław dev_err(&rdev->dev, "Failed to increase supply voltage: %pe\n", 357661aab5adSMichał Mirosław ERR_PTR(ret)); 35779243a195SMaciej Purski goto out; 3578fc42112cSSascha Hauer } 3579fc42112cSSascha Hauer } 3580fc42112cSSascha Hauer 3581f7efad10SChunyan Zhang if (state == PM_SUSPEND_ON) 358275790251SMark Brown ret = _regulator_do_set_voltage(rdev, min_uV, max_uV); 3583f7efad10SChunyan Zhang else 3584f7efad10SChunyan Zhang ret = _regulator_do_set_suspend_voltage(rdev, min_uV, 3585f7efad10SChunyan Zhang max_uV, state); 358692d7a558SPaolo Pisati if (ret < 0) 35879243a195SMaciej Purski goto out; 358802fa3ec0SMark Brown 3589fc42112cSSascha Hauer if (supply_change_uV < 0) { 3590fc42112cSSascha Hauer ret = regulator_set_voltage_unlocked(rdev->supply, 3591c360a6dfSChunyan Zhang best_supply_uV, INT_MAX, state); 3592fc42112cSSascha Hauer if (ret) 359361aab5adSMichał Mirosław dev_warn(&rdev->dev, "Failed to decrease supply voltage: %pe\n", 359461aab5adSMichał Mirosław ERR_PTR(ret)); 3595fc42112cSSascha Hauer /* No need to fail here */ 3596fc42112cSSascha Hauer ret = 0; 3597fc42112cSSascha Hauer } 3598fc42112cSSascha Hauer 3599414c70cbSLiam Girdwood out: 3600414c70cbSLiam Girdwood return ret; 360169686176SMaciej Purski } 36023d7610e8SEnric Balletbo i Serra EXPORT_SYMBOL_GPL(regulator_set_voltage_rdev); 360369686176SMaciej Purski 360485254bcfSDmitry Osipenko static int regulator_limit_voltage_step(struct regulator_dev *rdev, 360585254bcfSDmitry Osipenko int *current_uV, int *min_uV) 360685254bcfSDmitry Osipenko { 360785254bcfSDmitry Osipenko struct regulation_constraints *constraints = rdev->constraints; 360885254bcfSDmitry Osipenko 360985254bcfSDmitry Osipenko /* Limit voltage change only if necessary */ 361085254bcfSDmitry Osipenko if (!constraints->max_uV_step || !_regulator_is_enabled(rdev)) 361185254bcfSDmitry Osipenko return 1; 361285254bcfSDmitry Osipenko 361385254bcfSDmitry Osipenko if (*current_uV < 0) { 3614d22b85a1SDmitry Osipenko *current_uV = regulator_get_voltage_rdev(rdev); 361585254bcfSDmitry Osipenko 361685254bcfSDmitry Osipenko if (*current_uV < 0) 361785254bcfSDmitry Osipenko return *current_uV; 361885254bcfSDmitry Osipenko } 361985254bcfSDmitry Osipenko 362085254bcfSDmitry Osipenko if (abs(*current_uV - *min_uV) <= constraints->max_uV_step) 362185254bcfSDmitry Osipenko return 1; 362285254bcfSDmitry Osipenko 362385254bcfSDmitry Osipenko /* Clamp target voltage within the given step */ 362485254bcfSDmitry Osipenko if (*current_uV < *min_uV) 362585254bcfSDmitry Osipenko *min_uV = min(*current_uV + constraints->max_uV_step, 362685254bcfSDmitry Osipenko *min_uV); 362785254bcfSDmitry Osipenko else 362885254bcfSDmitry Osipenko *min_uV = max(*current_uV - constraints->max_uV_step, 362985254bcfSDmitry Osipenko *min_uV); 363085254bcfSDmitry Osipenko 363185254bcfSDmitry Osipenko return 0; 363285254bcfSDmitry Osipenko } 363385254bcfSDmitry Osipenko 3634c054c6c7SMaciej Purski static int regulator_get_optimal_voltage(struct regulator_dev *rdev, 3635c054c6c7SMaciej Purski int *current_uV, 3636c054c6c7SMaciej Purski int *min_uV, int *max_uV, 3637c054c6c7SMaciej Purski suspend_state_t state, 3638c054c6c7SMaciej Purski int n_coupled) 3639c054c6c7SMaciej Purski { 3640c054c6c7SMaciej Purski struct coupling_desc *c_desc = &rdev->coupling_desc; 3641c054c6c7SMaciej Purski struct regulator_dev **c_rdevs = c_desc->coupled_rdevs; 3642c054c6c7SMaciej Purski struct regulation_constraints *constraints = rdev->constraints; 3643c054c6c7SMaciej Purski int desired_min_uV = 0, desired_max_uV = INT_MAX; 3644c054c6c7SMaciej Purski int max_current_uV = 0, min_current_uV = INT_MAX; 3645c054c6c7SMaciej Purski int highest_min_uV = 0, target_uV, possible_uV; 3646d8ca7d18SDmitry Osipenko int i, ret, max_spread; 3647c054c6c7SMaciej Purski bool done; 3648c054c6c7SMaciej Purski 3649c054c6c7SMaciej Purski *current_uV = -1; 3650c054c6c7SMaciej Purski 3651c054c6c7SMaciej Purski /* 3652c054c6c7SMaciej Purski * If there are no coupled regulators, simply set the voltage 3653c054c6c7SMaciej Purski * demanded by consumers. 3654c054c6c7SMaciej Purski */ 3655c054c6c7SMaciej Purski if (n_coupled == 1) { 3656c054c6c7SMaciej Purski /* 3657c054c6c7SMaciej Purski * If consumers don't provide any demands, set voltage 3658c054c6c7SMaciej Purski * to min_uV 3659c054c6c7SMaciej Purski */ 3660c054c6c7SMaciej Purski desired_min_uV = constraints->min_uV; 3661c054c6c7SMaciej Purski desired_max_uV = constraints->max_uV; 3662c054c6c7SMaciej Purski 3663c054c6c7SMaciej Purski ret = regulator_check_consumers(rdev, 3664c054c6c7SMaciej Purski &desired_min_uV, 3665c054c6c7SMaciej Purski &desired_max_uV, state); 3666c054c6c7SMaciej Purski if (ret < 0) 3667c054c6c7SMaciej Purski return ret; 3668c054c6c7SMaciej Purski 3669c054c6c7SMaciej Purski possible_uV = desired_min_uV; 3670c054c6c7SMaciej Purski done = true; 3671c054c6c7SMaciej Purski 3672c054c6c7SMaciej Purski goto finish; 3673c054c6c7SMaciej Purski } 3674c054c6c7SMaciej Purski 3675c054c6c7SMaciej Purski /* Find highest min desired voltage */ 3676c054c6c7SMaciej Purski for (i = 0; i < n_coupled; i++) { 3677c054c6c7SMaciej Purski int tmp_min = 0; 3678c054c6c7SMaciej Purski int tmp_max = INT_MAX; 3679c054c6c7SMaciej Purski 3680f8702f9eSDmitry Osipenko lockdep_assert_held_once(&c_rdevs[i]->mutex.base); 3681c054c6c7SMaciej Purski 3682c054c6c7SMaciej Purski ret = regulator_check_consumers(c_rdevs[i], 3683c054c6c7SMaciej Purski &tmp_min, 3684c054c6c7SMaciej Purski &tmp_max, state); 3685c054c6c7SMaciej Purski if (ret < 0) 3686c054c6c7SMaciej Purski return ret; 3687c054c6c7SMaciej Purski 3688c054c6c7SMaciej Purski ret = regulator_check_voltage(c_rdevs[i], &tmp_min, &tmp_max); 3689c054c6c7SMaciej Purski if (ret < 0) 3690c054c6c7SMaciej Purski return ret; 3691c054c6c7SMaciej Purski 3692c054c6c7SMaciej Purski highest_min_uV = max(highest_min_uV, tmp_min); 3693c054c6c7SMaciej Purski 3694c054c6c7SMaciej Purski if (i == 0) { 3695c054c6c7SMaciej Purski desired_min_uV = tmp_min; 3696c054c6c7SMaciej Purski desired_max_uV = tmp_max; 3697c054c6c7SMaciej Purski } 3698c054c6c7SMaciej Purski } 3699c054c6c7SMaciej Purski 3700d8ca7d18SDmitry Osipenko max_spread = constraints->max_spread[0]; 3701d8ca7d18SDmitry Osipenko 3702c054c6c7SMaciej Purski /* 3703c054c6c7SMaciej Purski * Let target_uV be equal to the desired one if possible. 3704c054c6c7SMaciej Purski * If not, set it to minimum voltage, allowed by other coupled 3705c054c6c7SMaciej Purski * regulators. 3706c054c6c7SMaciej Purski */ 3707c054c6c7SMaciej Purski target_uV = max(desired_min_uV, highest_min_uV - max_spread); 3708c054c6c7SMaciej Purski 3709c054c6c7SMaciej Purski /* 3710c054c6c7SMaciej Purski * Find min and max voltages, which currently aren't violating 3711c054c6c7SMaciej Purski * max_spread. 3712c054c6c7SMaciej Purski */ 3713c054c6c7SMaciej Purski for (i = 1; i < n_coupled; i++) { 3714c054c6c7SMaciej Purski int tmp_act; 3715c054c6c7SMaciej Purski 3716c054c6c7SMaciej Purski if (!_regulator_is_enabled(c_rdevs[i])) 3717c054c6c7SMaciej Purski continue; 3718c054c6c7SMaciej Purski 3719d22b85a1SDmitry Osipenko tmp_act = regulator_get_voltage_rdev(c_rdevs[i]); 3720c054c6c7SMaciej Purski if (tmp_act < 0) 3721c054c6c7SMaciej Purski return tmp_act; 3722c054c6c7SMaciej Purski 3723c054c6c7SMaciej Purski min_current_uV = min(tmp_act, min_current_uV); 3724c054c6c7SMaciej Purski max_current_uV = max(tmp_act, max_current_uV); 3725c054c6c7SMaciej Purski } 3726c054c6c7SMaciej Purski 3727c054c6c7SMaciej Purski /* There aren't any other regulators enabled */ 3728c054c6c7SMaciej Purski if (max_current_uV == 0) { 3729c054c6c7SMaciej Purski possible_uV = target_uV; 3730c054c6c7SMaciej Purski } else { 3731c054c6c7SMaciej Purski /* 3732c054c6c7SMaciej Purski * Correct target voltage, so as it currently isn't 3733c054c6c7SMaciej Purski * violating max_spread 3734c054c6c7SMaciej Purski */ 3735c054c6c7SMaciej Purski possible_uV = max(target_uV, max_current_uV - max_spread); 3736c054c6c7SMaciej Purski possible_uV = min(possible_uV, min_current_uV + max_spread); 3737c054c6c7SMaciej Purski } 3738c054c6c7SMaciej Purski 3739c054c6c7SMaciej Purski if (possible_uV > desired_max_uV) 3740c054c6c7SMaciej Purski return -EINVAL; 3741c054c6c7SMaciej Purski 3742c054c6c7SMaciej Purski done = (possible_uV == target_uV); 3743c054c6c7SMaciej Purski desired_min_uV = possible_uV; 3744c054c6c7SMaciej Purski 3745c054c6c7SMaciej Purski finish: 374685254bcfSDmitry Osipenko /* Apply max_uV_step constraint if necessary */ 374785254bcfSDmitry Osipenko if (state == PM_SUSPEND_ON) { 374885254bcfSDmitry Osipenko ret = regulator_limit_voltage_step(rdev, current_uV, 374985254bcfSDmitry Osipenko &desired_min_uV); 375085254bcfSDmitry Osipenko if (ret < 0) 375185254bcfSDmitry Osipenko return ret; 375285254bcfSDmitry Osipenko 375385254bcfSDmitry Osipenko if (ret == 0) 375485254bcfSDmitry Osipenko done = false; 375585254bcfSDmitry Osipenko } 375685254bcfSDmitry Osipenko 3757c054c6c7SMaciej Purski /* Set current_uV if wasn't done earlier in the code and if necessary */ 3758c054c6c7SMaciej Purski if (n_coupled > 1 && *current_uV == -1) { 3759c054c6c7SMaciej Purski 3760c054c6c7SMaciej Purski if (_regulator_is_enabled(rdev)) { 3761d22b85a1SDmitry Osipenko ret = regulator_get_voltage_rdev(rdev); 3762c054c6c7SMaciej Purski if (ret < 0) 3763c054c6c7SMaciej Purski return ret; 3764c054c6c7SMaciej Purski 3765c054c6c7SMaciej Purski *current_uV = ret; 3766c054c6c7SMaciej Purski } else { 3767c054c6c7SMaciej Purski *current_uV = desired_min_uV; 3768c054c6c7SMaciej Purski } 3769c054c6c7SMaciej Purski } 3770c054c6c7SMaciej Purski 3771c054c6c7SMaciej Purski *min_uV = desired_min_uV; 3772c054c6c7SMaciej Purski *max_uV = desired_max_uV; 3773c054c6c7SMaciej Purski 3774c054c6c7SMaciej Purski return done; 3775c054c6c7SMaciej Purski } 3776c054c6c7SMaciej Purski 3777752db83aSMarek Szyprowski int regulator_do_balance_voltage(struct regulator_dev *rdev, 3778752db83aSMarek Szyprowski suspend_state_t state, bool skip_coupled) 3779c054c6c7SMaciej Purski { 3780c054c6c7SMaciej Purski struct regulator_dev **c_rdevs; 3781c054c6c7SMaciej Purski struct regulator_dev *best_rdev; 3782c054c6c7SMaciej Purski struct coupling_desc *c_desc = &rdev->coupling_desc; 3783c054c6c7SMaciej Purski int i, ret, n_coupled, best_min_uV, best_max_uV, best_c_rdev; 3784c054c6c7SMaciej Purski unsigned int delta, best_delta; 3785d8ca7d18SDmitry Osipenko unsigned long c_rdev_done = 0; 3786d8ca7d18SDmitry Osipenko bool best_c_rdev_done; 3787c054c6c7SMaciej Purski 3788c054c6c7SMaciej Purski c_rdevs = c_desc->coupled_rdevs; 3789752db83aSMarek Szyprowski n_coupled = skip_coupled ? 1 : c_desc->n_coupled; 3790c054c6c7SMaciej Purski 3791c054c6c7SMaciej Purski /* 3792c054c6c7SMaciej Purski * Find the best possible voltage change on each loop. Leave the loop 3793c054c6c7SMaciej Purski * if there isn't any possible change. 3794c054c6c7SMaciej Purski */ 3795c054c6c7SMaciej Purski do { 3796c054c6c7SMaciej Purski best_c_rdev_done = false; 3797c054c6c7SMaciej Purski best_delta = 0; 3798c054c6c7SMaciej Purski best_min_uV = 0; 3799c054c6c7SMaciej Purski best_max_uV = 0; 3800c054c6c7SMaciej Purski best_c_rdev = 0; 3801c054c6c7SMaciej Purski best_rdev = NULL; 3802c054c6c7SMaciej Purski 3803c054c6c7SMaciej Purski /* 3804c054c6c7SMaciej Purski * Find highest difference between optimal voltage 3805c054c6c7SMaciej Purski * and current voltage. 3806c054c6c7SMaciej Purski */ 3807c054c6c7SMaciej Purski for (i = 0; i < n_coupled; i++) { 3808c054c6c7SMaciej Purski /* 3809c054c6c7SMaciej Purski * optimal_uV is the best voltage that can be set for 3810c054c6c7SMaciej Purski * i-th regulator at the moment without violating 3811c054c6c7SMaciej Purski * max_spread constraint in order to balance 3812c054c6c7SMaciej Purski * the coupled voltages. 3813c054c6c7SMaciej Purski */ 3814c054c6c7SMaciej Purski int optimal_uV = 0, optimal_max_uV = 0, current_uV = 0; 3815c054c6c7SMaciej Purski 3816d8ca7d18SDmitry Osipenko if (test_bit(i, &c_rdev_done)) 3817c054c6c7SMaciej Purski continue; 3818c054c6c7SMaciej Purski 3819c054c6c7SMaciej Purski ret = regulator_get_optimal_voltage(c_rdevs[i], 3820c054c6c7SMaciej Purski ¤t_uV, 3821c054c6c7SMaciej Purski &optimal_uV, 3822c054c6c7SMaciej Purski &optimal_max_uV, 3823c054c6c7SMaciej Purski state, n_coupled); 3824c054c6c7SMaciej Purski if (ret < 0) 3825c054c6c7SMaciej Purski goto out; 3826c054c6c7SMaciej Purski 3827c054c6c7SMaciej Purski delta = abs(optimal_uV - current_uV); 3828c054c6c7SMaciej Purski 3829c054c6c7SMaciej Purski if (delta && best_delta <= delta) { 3830c054c6c7SMaciej Purski best_c_rdev_done = ret; 3831c054c6c7SMaciej Purski best_delta = delta; 3832c054c6c7SMaciej Purski best_rdev = c_rdevs[i]; 3833c054c6c7SMaciej Purski best_min_uV = optimal_uV; 3834c054c6c7SMaciej Purski best_max_uV = optimal_max_uV; 3835c054c6c7SMaciej Purski best_c_rdev = i; 3836c054c6c7SMaciej Purski } 3837c054c6c7SMaciej Purski } 3838c054c6c7SMaciej Purski 3839c054c6c7SMaciej Purski /* Nothing to change, return successfully */ 3840c054c6c7SMaciej Purski if (!best_rdev) { 3841c054c6c7SMaciej Purski ret = 0; 3842c054c6c7SMaciej Purski goto out; 3843c054c6c7SMaciej Purski } 38449243a195SMaciej Purski 3845c054c6c7SMaciej Purski ret = regulator_set_voltage_rdev(best_rdev, best_min_uV, 3846c054c6c7SMaciej Purski best_max_uV, state); 38479243a195SMaciej Purski 3848c054c6c7SMaciej Purski if (ret < 0) 3849c054c6c7SMaciej Purski goto out; 3850c054c6c7SMaciej Purski 3851d8ca7d18SDmitry Osipenko if (best_c_rdev_done) 3852d8ca7d18SDmitry Osipenko set_bit(best_c_rdev, &c_rdev_done); 3853c054c6c7SMaciej Purski 3854c054c6c7SMaciej Purski } while (n_coupled > 1); 3855c054c6c7SMaciej Purski 3856c054c6c7SMaciej Purski out: 385769686176SMaciej Purski return ret; 385869686176SMaciej Purski } 385969686176SMaciej Purski 3860752db83aSMarek Szyprowski static int regulator_balance_voltage(struct regulator_dev *rdev, 3861752db83aSMarek Szyprowski suspend_state_t state) 3862752db83aSMarek Szyprowski { 3863752db83aSMarek Szyprowski struct coupling_desc *c_desc = &rdev->coupling_desc; 3864752db83aSMarek Szyprowski struct regulator_coupler *coupler = c_desc->coupler; 3865752db83aSMarek Szyprowski bool skip_coupled = false; 3866752db83aSMarek Szyprowski 3867752db83aSMarek Szyprowski /* 3868752db83aSMarek Szyprowski * If system is in a state other than PM_SUSPEND_ON, don't check 3869752db83aSMarek Szyprowski * other coupled regulators. 3870752db83aSMarek Szyprowski */ 3871752db83aSMarek Szyprowski if (state != PM_SUSPEND_ON) 3872752db83aSMarek Szyprowski skip_coupled = true; 3873752db83aSMarek Szyprowski 3874752db83aSMarek Szyprowski if (c_desc->n_resolved < c_desc->n_coupled) { 3875752db83aSMarek Szyprowski rdev_err(rdev, "Not all coupled regulators registered\n"); 3876752db83aSMarek Szyprowski return -EPERM; 3877752db83aSMarek Szyprowski } 3878752db83aSMarek Szyprowski 3879752db83aSMarek Szyprowski /* Invoke custom balancer for customized couplers */ 3880752db83aSMarek Szyprowski if (coupler && coupler->balance_voltage) 3881752db83aSMarek Szyprowski return coupler->balance_voltage(coupler, rdev, state); 3882752db83aSMarek Szyprowski 3883752db83aSMarek Szyprowski return regulator_do_balance_voltage(rdev, state, skip_coupled); 3884752db83aSMarek Szyprowski } 3885752db83aSMarek Szyprowski 3886a9f226bcSSascha Hauer /** 3887a9f226bcSSascha Hauer * regulator_set_voltage - set regulator output voltage 3888a9f226bcSSascha Hauer * @regulator: regulator source 3889a9f226bcSSascha Hauer * @min_uV: Minimum required voltage in uV 3890a9f226bcSSascha Hauer * @max_uV: Maximum acceptable voltage in uV 3891a9f226bcSSascha Hauer * 3892a9f226bcSSascha Hauer * Sets a voltage regulator to the desired output voltage. This can be set 3893a9f226bcSSascha Hauer * during any regulator state. IOW, regulator can be disabled or enabled. 3894a9f226bcSSascha Hauer * 3895a9f226bcSSascha Hauer * If the regulator is enabled then the voltage will change to the new value 3896a9f226bcSSascha Hauer * immediately otherwise if the regulator is disabled the regulator will 3897a9f226bcSSascha Hauer * output at the new voltage when enabled. 3898a9f226bcSSascha Hauer * 3899a9f226bcSSascha Hauer * NOTE: If the regulator is shared between several devices then the lowest 3900a9f226bcSSascha Hauer * request voltage that meets the system constraints will be used. 3901a9f226bcSSascha Hauer * Regulator system constraints must be set for this regulator before 3902a9f226bcSSascha Hauer * calling this function otherwise this call will fail. 3903a9f226bcSSascha Hauer */ 3904a9f226bcSSascha Hauer int regulator_set_voltage(struct regulator *regulator, int min_uV, int max_uV) 3905a9f226bcSSascha Hauer { 3906f8702f9eSDmitry Osipenko struct ww_acquire_ctx ww_ctx; 3907f8702f9eSDmitry Osipenko int ret; 3908a9f226bcSSascha Hauer 3909f8702f9eSDmitry Osipenko regulator_lock_dependent(regulator->rdev, &ww_ctx); 3910a9f226bcSSascha Hauer 3911c360a6dfSChunyan Zhang ret = regulator_set_voltage_unlocked(regulator, min_uV, max_uV, 3912c360a6dfSChunyan Zhang PM_SUSPEND_ON); 3913a9f226bcSSascha Hauer 3914f8702f9eSDmitry Osipenko regulator_unlock_dependent(regulator->rdev, &ww_ctx); 3915a9f226bcSSascha Hauer 391692d7a558SPaolo Pisati return ret; 3917414c70cbSLiam Girdwood } 3918414c70cbSLiam Girdwood EXPORT_SYMBOL_GPL(regulator_set_voltage); 3919414c70cbSLiam Girdwood 3920f7efad10SChunyan Zhang static inline int regulator_suspend_toggle(struct regulator_dev *rdev, 3921f7efad10SChunyan Zhang suspend_state_t state, bool en) 3922f7efad10SChunyan Zhang { 3923f7efad10SChunyan Zhang struct regulator_state *rstate; 3924f7efad10SChunyan Zhang 3925f7efad10SChunyan Zhang rstate = regulator_get_suspend_state(rdev, state); 3926f7efad10SChunyan Zhang if (rstate == NULL) 3927f7efad10SChunyan Zhang return -EINVAL; 3928f7efad10SChunyan Zhang 3929f7efad10SChunyan Zhang if (!rstate->changeable) 3930f7efad10SChunyan Zhang return -EPERM; 3931f7efad10SChunyan Zhang 39323edd79cfSMarek Szyprowski rstate->enabled = (en) ? ENABLE_IN_SUSPEND : DISABLE_IN_SUSPEND; 3933f7efad10SChunyan Zhang 3934f7efad10SChunyan Zhang return 0; 3935f7efad10SChunyan Zhang } 3936f7efad10SChunyan Zhang 3937f7efad10SChunyan Zhang int regulator_suspend_enable(struct regulator_dev *rdev, 3938f7efad10SChunyan Zhang suspend_state_t state) 3939f7efad10SChunyan Zhang { 3940f7efad10SChunyan Zhang return regulator_suspend_toggle(rdev, state, true); 3941f7efad10SChunyan Zhang } 3942f7efad10SChunyan Zhang EXPORT_SYMBOL_GPL(regulator_suspend_enable); 3943f7efad10SChunyan Zhang 3944f7efad10SChunyan Zhang int regulator_suspend_disable(struct regulator_dev *rdev, 3945f7efad10SChunyan Zhang suspend_state_t state) 3946f7efad10SChunyan Zhang { 3947f7efad10SChunyan Zhang struct regulator *regulator; 3948f7efad10SChunyan Zhang struct regulator_voltage *voltage; 3949f7efad10SChunyan Zhang 3950f7efad10SChunyan Zhang /* 3951f7efad10SChunyan Zhang * if any consumer wants this regulator device keeping on in 3952f7efad10SChunyan Zhang * suspend states, don't set it as disabled. 3953f7efad10SChunyan Zhang */ 3954f7efad10SChunyan Zhang list_for_each_entry(regulator, &rdev->consumer_list, list) { 3955f7efad10SChunyan Zhang voltage = ®ulator->voltage[state]; 3956f7efad10SChunyan Zhang if (voltage->min_uV || voltage->max_uV) 3957f7efad10SChunyan Zhang return 0; 3958f7efad10SChunyan Zhang } 3959f7efad10SChunyan Zhang 3960f7efad10SChunyan Zhang return regulator_suspend_toggle(rdev, state, false); 3961f7efad10SChunyan Zhang } 3962f7efad10SChunyan Zhang EXPORT_SYMBOL_GPL(regulator_suspend_disable); 3963f7efad10SChunyan Zhang 3964f7efad10SChunyan Zhang static int _regulator_set_suspend_voltage(struct regulator *regulator, 3965f7efad10SChunyan Zhang int min_uV, int max_uV, 3966f7efad10SChunyan Zhang suspend_state_t state) 3967f7efad10SChunyan Zhang { 3968f7efad10SChunyan Zhang struct regulator_dev *rdev = regulator->rdev; 3969f7efad10SChunyan Zhang struct regulator_state *rstate; 3970f7efad10SChunyan Zhang 3971f7efad10SChunyan Zhang rstate = regulator_get_suspend_state(rdev, state); 3972f7efad10SChunyan Zhang if (rstate == NULL) 3973f7efad10SChunyan Zhang return -EINVAL; 3974f7efad10SChunyan Zhang 3975f7efad10SChunyan Zhang if (rstate->min_uV == rstate->max_uV) { 3976f7efad10SChunyan Zhang rdev_err(rdev, "The suspend voltage can't be changed!\n"); 3977f7efad10SChunyan Zhang return -EPERM; 3978f7efad10SChunyan Zhang } 3979f7efad10SChunyan Zhang 3980f7efad10SChunyan Zhang return regulator_set_voltage_unlocked(regulator, min_uV, max_uV, state); 3981f7efad10SChunyan Zhang } 3982f7efad10SChunyan Zhang 3983f7efad10SChunyan Zhang int regulator_set_suspend_voltage(struct regulator *regulator, int min_uV, 3984f7efad10SChunyan Zhang int max_uV, suspend_state_t state) 3985f7efad10SChunyan Zhang { 3986f8702f9eSDmitry Osipenko struct ww_acquire_ctx ww_ctx; 3987f8702f9eSDmitry Osipenko int ret; 3988f7efad10SChunyan Zhang 3989f7efad10SChunyan Zhang /* PM_SUSPEND_ON is handled by regulator_set_voltage() */ 3990f7efad10SChunyan Zhang if (regulator_check_states(state) || state == PM_SUSPEND_ON) 3991f7efad10SChunyan Zhang return -EINVAL; 3992f7efad10SChunyan Zhang 3993f8702f9eSDmitry Osipenko regulator_lock_dependent(regulator->rdev, &ww_ctx); 3994f7efad10SChunyan Zhang 3995f7efad10SChunyan Zhang ret = _regulator_set_suspend_voltage(regulator, min_uV, 3996f7efad10SChunyan Zhang max_uV, state); 3997f7efad10SChunyan Zhang 3998f8702f9eSDmitry Osipenko regulator_unlock_dependent(regulator->rdev, &ww_ctx); 3999f7efad10SChunyan Zhang 4000f7efad10SChunyan Zhang return ret; 4001f7efad10SChunyan Zhang } 4002f7efad10SChunyan Zhang EXPORT_SYMBOL_GPL(regulator_set_suspend_voltage); 4003f7efad10SChunyan Zhang 4004606a2562SMark Brown /** 400588cd222bSLinus Walleij * regulator_set_voltage_time - get raise/fall time 400688cd222bSLinus Walleij * @regulator: regulator source 400788cd222bSLinus Walleij * @old_uV: starting voltage in microvolts 400888cd222bSLinus Walleij * @new_uV: target voltage in microvolts 400988cd222bSLinus Walleij * 401088cd222bSLinus Walleij * Provided with the starting and ending voltage, this function attempts to 401188cd222bSLinus Walleij * calculate the time in microseconds required to rise or fall to this new 401288cd222bSLinus Walleij * voltage. 401388cd222bSLinus Walleij */ 401488cd222bSLinus Walleij int regulator_set_voltage_time(struct regulator *regulator, 401588cd222bSLinus Walleij int old_uV, int new_uV) 401688cd222bSLinus Walleij { 401788cd222bSLinus Walleij struct regulator_dev *rdev = regulator->rdev; 4018272e2315SGuodong Xu const struct regulator_ops *ops = rdev->desc->ops; 401988cd222bSLinus Walleij int old_sel = -1; 402088cd222bSLinus Walleij int new_sel = -1; 402188cd222bSLinus Walleij int voltage; 402288cd222bSLinus Walleij int i; 402388cd222bSLinus Walleij 402473e705bfSMatthias Kaehlcke if (ops->set_voltage_time) 402573e705bfSMatthias Kaehlcke return ops->set_voltage_time(rdev, old_uV, new_uV); 402673e705bfSMatthias Kaehlcke else if (!ops->set_voltage_time_sel) 402773e705bfSMatthias Kaehlcke return _regulator_set_voltage_time(rdev, old_uV, new_uV); 402873e705bfSMatthias Kaehlcke 402988cd222bSLinus Walleij /* Currently requires operations to do this */ 403073e705bfSMatthias Kaehlcke if (!ops->list_voltage || !rdev->desc->n_voltages) 403188cd222bSLinus Walleij return -EINVAL; 403288cd222bSLinus Walleij 403388cd222bSLinus Walleij for (i = 0; i < rdev->desc->n_voltages; i++) { 403488cd222bSLinus Walleij /* We only look for exact voltage matches here */ 403588cd222bSLinus Walleij voltage = regulator_list_voltage(regulator, i); 403688cd222bSLinus Walleij if (voltage < 0) 403788cd222bSLinus Walleij return -EINVAL; 403888cd222bSLinus Walleij if (voltage == 0) 403988cd222bSLinus Walleij continue; 404088cd222bSLinus Walleij if (voltage == old_uV) 404188cd222bSLinus Walleij old_sel = i; 404288cd222bSLinus Walleij if (voltage == new_uV) 404388cd222bSLinus Walleij new_sel = i; 404488cd222bSLinus Walleij } 404588cd222bSLinus Walleij 404688cd222bSLinus Walleij if (old_sel < 0 || new_sel < 0) 404788cd222bSLinus Walleij return -EINVAL; 404888cd222bSLinus Walleij 404988cd222bSLinus Walleij return ops->set_voltage_time_sel(rdev, old_sel, new_sel); 405088cd222bSLinus Walleij } 405188cd222bSLinus Walleij EXPORT_SYMBOL_GPL(regulator_set_voltage_time); 405288cd222bSLinus Walleij 405388cd222bSLinus Walleij /** 405498a175b6SYadwinder Singh Brar * regulator_set_voltage_time_sel - get raise/fall time 4055296c6566SRandy Dunlap * @rdev: regulator source device 405698a175b6SYadwinder Singh Brar * @old_selector: selector for starting voltage 405798a175b6SYadwinder Singh Brar * @new_selector: selector for target voltage 405898a175b6SYadwinder Singh Brar * 405998a175b6SYadwinder Singh Brar * Provided with the starting and target voltage selectors, this function 406098a175b6SYadwinder Singh Brar * returns time in microseconds required to rise or fall to this new voltage 406198a175b6SYadwinder Singh Brar * 4062f11d08c3SAxel Lin * Drivers providing ramp_delay in regulation_constraints can use this as their 4063398715abSAxel Lin * set_voltage_time_sel() operation. 406498a175b6SYadwinder Singh Brar */ 406598a175b6SYadwinder Singh Brar int regulator_set_voltage_time_sel(struct regulator_dev *rdev, 406698a175b6SYadwinder Singh Brar unsigned int old_selector, 406798a175b6SYadwinder Singh Brar unsigned int new_selector) 406898a175b6SYadwinder Singh Brar { 4069f11d08c3SAxel Lin int old_volt, new_volt; 4070398715abSAxel Lin 4071f11d08c3SAxel Lin /* sanity check */ 4072f11d08c3SAxel Lin if (!rdev->desc->ops->list_voltage) 4073f11d08c3SAxel Lin return -EINVAL; 4074398715abSAxel Lin 4075f11d08c3SAxel Lin old_volt = rdev->desc->ops->list_voltage(rdev, old_selector); 4076f11d08c3SAxel Lin new_volt = rdev->desc->ops->list_voltage(rdev, new_selector); 4077f11d08c3SAxel Lin 407873e705bfSMatthias Kaehlcke if (rdev->desc->ops->set_voltage_time) 407973e705bfSMatthias Kaehlcke return rdev->desc->ops->set_voltage_time(rdev, old_volt, 408073e705bfSMatthias Kaehlcke new_volt); 408173e705bfSMatthias Kaehlcke else 408273e705bfSMatthias Kaehlcke return _regulator_set_voltage_time(rdev, old_volt, new_volt); 408398a175b6SYadwinder Singh Brar } 4084b19dbf71SMark Brown EXPORT_SYMBOL_GPL(regulator_set_voltage_time_sel); 408598a175b6SYadwinder Singh Brar 408698a175b6SYadwinder Singh Brar /** 4087606a2562SMark Brown * regulator_sync_voltage - re-apply last regulator output voltage 4088606a2562SMark Brown * @regulator: regulator source 4089606a2562SMark Brown * 4090606a2562SMark Brown * Re-apply the last configured voltage. This is intended to be used 4091606a2562SMark Brown * where some external control source the consumer is cooperating with 4092606a2562SMark Brown * has caused the configured voltage to change. 4093606a2562SMark Brown */ 4094606a2562SMark Brown int regulator_sync_voltage(struct regulator *regulator) 4095606a2562SMark Brown { 4096606a2562SMark Brown struct regulator_dev *rdev = regulator->rdev; 4097c360a6dfSChunyan Zhang struct regulator_voltage *voltage = ®ulator->voltage[PM_SUSPEND_ON]; 4098606a2562SMark Brown int ret, min_uV, max_uV; 4099606a2562SMark Brown 410066cf9a7eSMaciej Purski regulator_lock(rdev); 4101606a2562SMark Brown 4102606a2562SMark Brown if (!rdev->desc->ops->set_voltage && 4103606a2562SMark Brown !rdev->desc->ops->set_voltage_sel) { 4104606a2562SMark Brown ret = -EINVAL; 4105606a2562SMark Brown goto out; 4106606a2562SMark Brown } 4107606a2562SMark Brown 4108606a2562SMark Brown /* This is only going to work if we've had a voltage configured. */ 4109c360a6dfSChunyan Zhang if (!voltage->min_uV && !voltage->max_uV) { 4110606a2562SMark Brown ret = -EINVAL; 4111606a2562SMark Brown goto out; 4112606a2562SMark Brown } 4113606a2562SMark Brown 4114c360a6dfSChunyan Zhang min_uV = voltage->min_uV; 4115c360a6dfSChunyan Zhang max_uV = voltage->max_uV; 4116606a2562SMark Brown 4117606a2562SMark Brown /* This should be a paranoia check... */ 4118606a2562SMark Brown ret = regulator_check_voltage(rdev, &min_uV, &max_uV); 4119606a2562SMark Brown if (ret < 0) 4120606a2562SMark Brown goto out; 4121606a2562SMark Brown 4122c360a6dfSChunyan Zhang ret = regulator_check_consumers(rdev, &min_uV, &max_uV, 0); 4123606a2562SMark Brown if (ret < 0) 4124606a2562SMark Brown goto out; 4125606a2562SMark Brown 4126606a2562SMark Brown ret = _regulator_do_set_voltage(rdev, min_uV, max_uV); 4127606a2562SMark Brown 4128606a2562SMark Brown out: 412966cf9a7eSMaciej Purski regulator_unlock(rdev); 4130606a2562SMark Brown return ret; 4131606a2562SMark Brown } 4132606a2562SMark Brown EXPORT_SYMBOL_GPL(regulator_sync_voltage); 4133606a2562SMark Brown 4134d22b85a1SDmitry Osipenko int regulator_get_voltage_rdev(struct regulator_dev *rdev) 4135414c70cbSLiam Girdwood { 4136bf5892a8SMark Brown int sel, ret; 4137fef95019SMark Brown bool bypassed; 4138fef95019SMark Brown 4139fef95019SMark Brown if (rdev->desc->ops->get_bypass) { 4140fef95019SMark Brown ret = rdev->desc->ops->get_bypass(rdev, &bypassed); 4141fef95019SMark Brown if (ret < 0) 4142fef95019SMark Brown return ret; 4143fef95019SMark Brown if (bypassed) { 4144fef95019SMark Brown /* if bypassed the regulator must have a supply */ 414545389c47SJon Hunter if (!rdev->supply) { 414645389c47SJon Hunter rdev_err(rdev, 414745389c47SJon Hunter "bypassed regulator has no supply!\n"); 414845389c47SJon Hunter return -EPROBE_DEFER; 414945389c47SJon Hunter } 4150fef95019SMark Brown 4151d22b85a1SDmitry Osipenko return regulator_get_voltage_rdev(rdev->supply->rdev); 4152fef95019SMark Brown } 4153fef95019SMark Brown } 4154476c2d83SMark Brown 4155476c2d83SMark Brown if (rdev->desc->ops->get_voltage_sel) { 4156476c2d83SMark Brown sel = rdev->desc->ops->get_voltage_sel(rdev); 4157476c2d83SMark Brown if (sel < 0) 4158476c2d83SMark Brown return sel; 4159bf5892a8SMark Brown ret = rdev->desc->ops->list_voltage(rdev, sel); 4160cb220d16SAxel Lin } else if (rdev->desc->ops->get_voltage) { 4161bf5892a8SMark Brown ret = rdev->desc->ops->get_voltage(rdev); 4162f7df20ecSMark Brown } else if (rdev->desc->ops->list_voltage) { 4163f7df20ecSMark Brown ret = rdev->desc->ops->list_voltage(rdev, 0); 41645a523605SLaxman Dewangan } else if (rdev->desc->fixed_uV && (rdev->desc->n_voltages == 1)) { 41655a523605SLaxman Dewangan ret = rdev->desc->fixed_uV; 4166e303996eSJavier Martinez Canillas } else if (rdev->supply) { 4167d22b85a1SDmitry Osipenko ret = regulator_get_voltage_rdev(rdev->supply->rdev); 4168cf1ad559SMichał Mirosław } else if (rdev->supply_name) { 4169cf1ad559SMichał Mirosław return -EPROBE_DEFER; 4170cb220d16SAxel Lin } else { 4171414c70cbSLiam Girdwood return -EINVAL; 4172cb220d16SAxel Lin } 4173bf5892a8SMark Brown 4174cb220d16SAxel Lin if (ret < 0) 4175cb220d16SAxel Lin return ret; 4176bf5892a8SMark Brown return ret - rdev->constraints->uV_offset; 4177414c70cbSLiam Girdwood } 41783d7610e8SEnric Balletbo i Serra EXPORT_SYMBOL_GPL(regulator_get_voltage_rdev); 4179414c70cbSLiam Girdwood 4180414c70cbSLiam Girdwood /** 4181414c70cbSLiam Girdwood * regulator_get_voltage - get regulator output voltage 4182414c70cbSLiam Girdwood * @regulator: regulator source 4183414c70cbSLiam Girdwood * 4184414c70cbSLiam Girdwood * This returns the current regulator voltage in uV. 4185414c70cbSLiam Girdwood * 4186414c70cbSLiam Girdwood * NOTE: If the regulator is disabled it will return the voltage value. This 4187414c70cbSLiam Girdwood * function should not be used to determine regulator state. 4188414c70cbSLiam Girdwood */ 4189414c70cbSLiam Girdwood int regulator_get_voltage(struct regulator *regulator) 4190414c70cbSLiam Girdwood { 4191f8702f9eSDmitry Osipenko struct ww_acquire_ctx ww_ctx; 4192414c70cbSLiam Girdwood int ret; 4193414c70cbSLiam Girdwood 4194f8702f9eSDmitry Osipenko regulator_lock_dependent(regulator->rdev, &ww_ctx); 4195d22b85a1SDmitry Osipenko ret = regulator_get_voltage_rdev(regulator->rdev); 4196f8702f9eSDmitry Osipenko regulator_unlock_dependent(regulator->rdev, &ww_ctx); 4197414c70cbSLiam Girdwood 4198414c70cbSLiam Girdwood return ret; 4199414c70cbSLiam Girdwood } 4200414c70cbSLiam Girdwood EXPORT_SYMBOL_GPL(regulator_get_voltage); 4201414c70cbSLiam Girdwood 4202414c70cbSLiam Girdwood /** 4203414c70cbSLiam Girdwood * regulator_set_current_limit - set regulator output current limit 4204414c70cbSLiam Girdwood * @regulator: regulator source 4205ce0d10f8SCharles Keepax * @min_uA: Minimum supported current in uA 4206414c70cbSLiam Girdwood * @max_uA: Maximum supported current in uA 4207414c70cbSLiam Girdwood * 4208414c70cbSLiam Girdwood * Sets current sink to the desired output current. This can be set during 4209414c70cbSLiam Girdwood * any regulator state. IOW, regulator can be disabled or enabled. 4210414c70cbSLiam Girdwood * 4211414c70cbSLiam Girdwood * If the regulator is enabled then the current will change to the new value 4212414c70cbSLiam Girdwood * immediately otherwise if the regulator is disabled the regulator will 4213414c70cbSLiam Girdwood * output at the new current when enabled. 4214414c70cbSLiam Girdwood * 4215414c70cbSLiam Girdwood * NOTE: Regulator system constraints must be set for this regulator before 4216414c70cbSLiam Girdwood * calling this function otherwise this call will fail. 4217414c70cbSLiam Girdwood */ 4218414c70cbSLiam Girdwood int regulator_set_current_limit(struct regulator *regulator, 4219414c70cbSLiam Girdwood int min_uA, int max_uA) 4220414c70cbSLiam Girdwood { 4221414c70cbSLiam Girdwood struct regulator_dev *rdev = regulator->rdev; 4222414c70cbSLiam Girdwood int ret; 4223414c70cbSLiam Girdwood 422466cf9a7eSMaciej Purski regulator_lock(rdev); 4225414c70cbSLiam Girdwood 4226414c70cbSLiam Girdwood /* sanity check */ 4227414c70cbSLiam Girdwood if (!rdev->desc->ops->set_current_limit) { 4228414c70cbSLiam Girdwood ret = -EINVAL; 4229414c70cbSLiam Girdwood goto out; 4230414c70cbSLiam Girdwood } 4231414c70cbSLiam Girdwood 4232414c70cbSLiam Girdwood /* constraints check */ 4233414c70cbSLiam Girdwood ret = regulator_check_current_limit(rdev, &min_uA, &max_uA); 4234414c70cbSLiam Girdwood if (ret < 0) 4235414c70cbSLiam Girdwood goto out; 4236414c70cbSLiam Girdwood 4237414c70cbSLiam Girdwood ret = rdev->desc->ops->set_current_limit(rdev, min_uA, max_uA); 4238414c70cbSLiam Girdwood out: 423966cf9a7eSMaciej Purski regulator_unlock(rdev); 4240414c70cbSLiam Girdwood return ret; 4241414c70cbSLiam Girdwood } 4242414c70cbSLiam Girdwood EXPORT_SYMBOL_GPL(regulator_set_current_limit); 4243414c70cbSLiam Girdwood 42447e4d9683SDouglas Anderson static int _regulator_get_current_limit_unlocked(struct regulator_dev *rdev) 42457e4d9683SDouglas Anderson { 42467e4d9683SDouglas Anderson /* sanity check */ 42477e4d9683SDouglas Anderson if (!rdev->desc->ops->get_current_limit) 42487e4d9683SDouglas Anderson return -EINVAL; 42497e4d9683SDouglas Anderson 42507e4d9683SDouglas Anderson return rdev->desc->ops->get_current_limit(rdev); 42517e4d9683SDouglas Anderson } 42527e4d9683SDouglas Anderson 4253414c70cbSLiam Girdwood static int _regulator_get_current_limit(struct regulator_dev *rdev) 4254414c70cbSLiam Girdwood { 4255414c70cbSLiam Girdwood int ret; 4256414c70cbSLiam Girdwood 425766cf9a7eSMaciej Purski regulator_lock(rdev); 42587e4d9683SDouglas Anderson ret = _regulator_get_current_limit_unlocked(rdev); 425966cf9a7eSMaciej Purski regulator_unlock(rdev); 42607e4d9683SDouglas Anderson 4261414c70cbSLiam Girdwood return ret; 4262414c70cbSLiam Girdwood } 4263414c70cbSLiam Girdwood 4264414c70cbSLiam Girdwood /** 4265414c70cbSLiam Girdwood * regulator_get_current_limit - get regulator output current 4266414c70cbSLiam Girdwood * @regulator: regulator source 4267414c70cbSLiam Girdwood * 4268414c70cbSLiam Girdwood * This returns the current supplied by the specified current sink in uA. 4269414c70cbSLiam Girdwood * 4270414c70cbSLiam Girdwood * NOTE: If the regulator is disabled it will return the current value. This 4271414c70cbSLiam Girdwood * function should not be used to determine regulator state. 4272414c70cbSLiam Girdwood */ 4273414c70cbSLiam Girdwood int regulator_get_current_limit(struct regulator *regulator) 4274414c70cbSLiam Girdwood { 4275414c70cbSLiam Girdwood return _regulator_get_current_limit(regulator->rdev); 4276414c70cbSLiam Girdwood } 4277414c70cbSLiam Girdwood EXPORT_SYMBOL_GPL(regulator_get_current_limit); 4278414c70cbSLiam Girdwood 4279414c70cbSLiam Girdwood /** 4280414c70cbSLiam Girdwood * regulator_set_mode - set regulator operating mode 4281414c70cbSLiam Girdwood * @regulator: regulator source 4282414c70cbSLiam Girdwood * @mode: operating mode - one of the REGULATOR_MODE constants 4283414c70cbSLiam Girdwood * 4284414c70cbSLiam Girdwood * Set regulator operating mode to increase regulator efficiency or improve 4285414c70cbSLiam Girdwood * regulation performance. 4286414c70cbSLiam Girdwood * 4287414c70cbSLiam Girdwood * NOTE: Regulator system constraints must be set for this regulator before 4288414c70cbSLiam Girdwood * calling this function otherwise this call will fail. 4289414c70cbSLiam Girdwood */ 4290414c70cbSLiam Girdwood int regulator_set_mode(struct regulator *regulator, unsigned int mode) 4291414c70cbSLiam Girdwood { 4292414c70cbSLiam Girdwood struct regulator_dev *rdev = regulator->rdev; 4293414c70cbSLiam Girdwood int ret; 4294500b4ac9SSundar R Iyer int regulator_curr_mode; 4295414c70cbSLiam Girdwood 429666cf9a7eSMaciej Purski regulator_lock(rdev); 4297414c70cbSLiam Girdwood 4298414c70cbSLiam Girdwood /* sanity check */ 4299414c70cbSLiam Girdwood if (!rdev->desc->ops->set_mode) { 4300414c70cbSLiam Girdwood ret = -EINVAL; 4301414c70cbSLiam Girdwood goto out; 4302414c70cbSLiam Girdwood } 4303414c70cbSLiam Girdwood 4304500b4ac9SSundar R Iyer /* return if the same mode is requested */ 4305500b4ac9SSundar R Iyer if (rdev->desc->ops->get_mode) { 4306500b4ac9SSundar R Iyer regulator_curr_mode = rdev->desc->ops->get_mode(rdev); 4307500b4ac9SSundar R Iyer if (regulator_curr_mode == mode) { 4308500b4ac9SSundar R Iyer ret = 0; 4309500b4ac9SSundar R Iyer goto out; 4310500b4ac9SSundar R Iyer } 4311500b4ac9SSundar R Iyer } 4312500b4ac9SSundar R Iyer 4313414c70cbSLiam Girdwood /* constraints check */ 431422c51b47SAxel Lin ret = regulator_mode_constrain(rdev, &mode); 4315414c70cbSLiam Girdwood if (ret < 0) 4316414c70cbSLiam Girdwood goto out; 4317414c70cbSLiam Girdwood 4318414c70cbSLiam Girdwood ret = rdev->desc->ops->set_mode(rdev, mode); 4319414c70cbSLiam Girdwood out: 432066cf9a7eSMaciej Purski regulator_unlock(rdev); 4321414c70cbSLiam Girdwood return ret; 4322414c70cbSLiam Girdwood } 4323414c70cbSLiam Girdwood EXPORT_SYMBOL_GPL(regulator_set_mode); 4324414c70cbSLiam Girdwood 43257e4d9683SDouglas Anderson static unsigned int _regulator_get_mode_unlocked(struct regulator_dev *rdev) 43267e4d9683SDouglas Anderson { 43277e4d9683SDouglas Anderson /* sanity check */ 43287e4d9683SDouglas Anderson if (!rdev->desc->ops->get_mode) 43297e4d9683SDouglas Anderson return -EINVAL; 43307e4d9683SDouglas Anderson 43317e4d9683SDouglas Anderson return rdev->desc->ops->get_mode(rdev); 43327e4d9683SDouglas Anderson } 43337e4d9683SDouglas Anderson 4334414c70cbSLiam Girdwood static unsigned int _regulator_get_mode(struct regulator_dev *rdev) 4335414c70cbSLiam Girdwood { 4336414c70cbSLiam Girdwood int ret; 4337414c70cbSLiam Girdwood 433866cf9a7eSMaciej Purski regulator_lock(rdev); 43397e4d9683SDouglas Anderson ret = _regulator_get_mode_unlocked(rdev); 434066cf9a7eSMaciej Purski regulator_unlock(rdev); 43417e4d9683SDouglas Anderson 4342414c70cbSLiam Girdwood return ret; 4343414c70cbSLiam Girdwood } 4344414c70cbSLiam Girdwood 4345414c70cbSLiam Girdwood /** 4346414c70cbSLiam Girdwood * regulator_get_mode - get regulator operating mode 4347414c70cbSLiam Girdwood * @regulator: regulator source 4348414c70cbSLiam Girdwood * 4349414c70cbSLiam Girdwood * Get the current regulator operating mode. 4350414c70cbSLiam Girdwood */ 4351414c70cbSLiam Girdwood unsigned int regulator_get_mode(struct regulator *regulator) 4352414c70cbSLiam Girdwood { 4353414c70cbSLiam Girdwood return _regulator_get_mode(regulator->rdev); 4354414c70cbSLiam Girdwood } 4355414c70cbSLiam Girdwood EXPORT_SYMBOL_GPL(regulator_get_mode); 4356414c70cbSLiam Girdwood 43571b5b4221SAxel Haslam static int _regulator_get_error_flags(struct regulator_dev *rdev, 43581b5b4221SAxel Haslam unsigned int *flags) 43591b5b4221SAxel Haslam { 43601b5b4221SAxel Haslam int ret; 43611b5b4221SAxel Haslam 436266cf9a7eSMaciej Purski regulator_lock(rdev); 43631b5b4221SAxel Haslam 43641b5b4221SAxel Haslam /* sanity check */ 43651b5b4221SAxel Haslam if (!rdev->desc->ops->get_error_flags) { 43661b5b4221SAxel Haslam ret = -EINVAL; 43671b5b4221SAxel Haslam goto out; 43681b5b4221SAxel Haslam } 43691b5b4221SAxel Haslam 43701b5b4221SAxel Haslam ret = rdev->desc->ops->get_error_flags(rdev, flags); 43711b5b4221SAxel Haslam out: 437266cf9a7eSMaciej Purski regulator_unlock(rdev); 43731b5b4221SAxel Haslam return ret; 43741b5b4221SAxel Haslam } 43751b5b4221SAxel Haslam 43761b5b4221SAxel Haslam /** 43771b5b4221SAxel Haslam * regulator_get_error_flags - get regulator error information 43781b5b4221SAxel Haslam * @regulator: regulator source 43791b5b4221SAxel Haslam * @flags: pointer to store error flags 43801b5b4221SAxel Haslam * 43811b5b4221SAxel Haslam * Get the current regulator error information. 43821b5b4221SAxel Haslam */ 43831b5b4221SAxel Haslam int regulator_get_error_flags(struct regulator *regulator, 43841b5b4221SAxel Haslam unsigned int *flags) 43851b5b4221SAxel Haslam { 43861b5b4221SAxel Haslam return _regulator_get_error_flags(regulator->rdev, flags); 43871b5b4221SAxel Haslam } 43881b5b4221SAxel Haslam EXPORT_SYMBOL_GPL(regulator_get_error_flags); 43891b5b4221SAxel Haslam 4390414c70cbSLiam Girdwood /** 4391e39ce48fSBjorn Andersson * regulator_set_load - set regulator load 4392414c70cbSLiam Girdwood * @regulator: regulator source 4393414c70cbSLiam Girdwood * @uA_load: load current 4394414c70cbSLiam Girdwood * 4395414c70cbSLiam Girdwood * Notifies the regulator core of a new device load. This is then used by 4396414c70cbSLiam Girdwood * DRMS (if enabled by constraints) to set the most efficient regulator 4397414c70cbSLiam Girdwood * operating mode for the new regulator loading. 4398414c70cbSLiam Girdwood * 4399414c70cbSLiam Girdwood * Consumer devices notify their supply regulator of the maximum power 4400414c70cbSLiam Girdwood * they will require (can be taken from device datasheet in the power 4401414c70cbSLiam Girdwood * consumption tables) when they change operational status and hence power 4402414c70cbSLiam Girdwood * state. Examples of operational state changes that can affect power 4403414c70cbSLiam Girdwood * consumption are :- 4404414c70cbSLiam Girdwood * 4405414c70cbSLiam Girdwood * o Device is opened / closed. 4406414c70cbSLiam Girdwood * o Device I/O is about to begin or has just finished. 4407414c70cbSLiam Girdwood * o Device is idling in between work. 4408414c70cbSLiam Girdwood * 4409414c70cbSLiam Girdwood * This information is also exported via sysfs to userspace. 4410414c70cbSLiam Girdwood * 4411414c70cbSLiam Girdwood * DRMS will sum the total requested load on the regulator and change 4412414c70cbSLiam Girdwood * to the most efficient operating mode if platform constraints allow. 4413414c70cbSLiam Girdwood * 44145451781dSDouglas Anderson * NOTE: when a regulator consumer requests to have a regulator 44155451781dSDouglas Anderson * disabled then any load that consumer requested no longer counts 44165451781dSDouglas Anderson * toward the total requested load. If the regulator is re-enabled 44175451781dSDouglas Anderson * then the previously requested load will start counting again. 44185451781dSDouglas Anderson * 44195451781dSDouglas Anderson * If a regulator is an always-on regulator then an individual consumer's 44205451781dSDouglas Anderson * load will still be removed if that consumer is fully disabled. 44215451781dSDouglas Anderson * 4422e39ce48fSBjorn Andersson * On error a negative errno is returned. 4423414c70cbSLiam Girdwood */ 4424e39ce48fSBjorn Andersson int regulator_set_load(struct regulator *regulator, int uA_load) 4425414c70cbSLiam Girdwood { 4426414c70cbSLiam Girdwood struct regulator_dev *rdev = regulator->rdev; 44275451781dSDouglas Anderson int old_uA_load; 44285451781dSDouglas Anderson int ret = 0; 4429d92d95b6SStephen Boyd 443066cf9a7eSMaciej Purski regulator_lock(rdev); 44315451781dSDouglas Anderson old_uA_load = regulator->uA_load; 4432414c70cbSLiam Girdwood regulator->uA_load = uA_load; 44335451781dSDouglas Anderson if (regulator->enable_count && old_uA_load != uA_load) { 44348460ef38SBjorn Andersson ret = drms_uA_update(rdev); 44355451781dSDouglas Anderson if (ret < 0) 44365451781dSDouglas Anderson regulator->uA_load = old_uA_load; 44375451781dSDouglas Anderson } 443866cf9a7eSMaciej Purski regulator_unlock(rdev); 44398460ef38SBjorn Andersson 4440414c70cbSLiam Girdwood return ret; 4441414c70cbSLiam Girdwood } 4442e39ce48fSBjorn Andersson EXPORT_SYMBOL_GPL(regulator_set_load); 4443414c70cbSLiam Girdwood 4444414c70cbSLiam Girdwood /** 4445f59c8f9fSMark Brown * regulator_allow_bypass - allow the regulator to go into bypass mode 4446f59c8f9fSMark Brown * 4447f59c8f9fSMark Brown * @regulator: Regulator to configure 44489345dfb8SNishanth Menon * @enable: enable or disable bypass mode 4449f59c8f9fSMark Brown * 4450f59c8f9fSMark Brown * Allow the regulator to go into bypass mode if all other consumers 4451f59c8f9fSMark Brown * for the regulator also enable bypass mode and the machine 4452f59c8f9fSMark Brown * constraints allow this. Bypass mode means that the regulator is 4453f59c8f9fSMark Brown * simply passing the input directly to the output with no regulation. 4454f59c8f9fSMark Brown */ 4455f59c8f9fSMark Brown int regulator_allow_bypass(struct regulator *regulator, bool enable) 4456f59c8f9fSMark Brown { 4457f59c8f9fSMark Brown struct regulator_dev *rdev = regulator->rdev; 445848325655SCharles Keepax const char *name = rdev_get_name(rdev); 4459f59c8f9fSMark Brown int ret = 0; 4460f59c8f9fSMark Brown 4461f59c8f9fSMark Brown if (!rdev->desc->ops->set_bypass) 4462f59c8f9fSMark Brown return 0; 4463f59c8f9fSMark Brown 44648a34e979SWEN Pingbo if (!regulator_ops_is_valid(rdev, REGULATOR_CHANGE_BYPASS)) 4465f59c8f9fSMark Brown return 0; 4466f59c8f9fSMark Brown 446766cf9a7eSMaciej Purski regulator_lock(rdev); 4468f59c8f9fSMark Brown 4469f59c8f9fSMark Brown if (enable && !regulator->bypass) { 4470f59c8f9fSMark Brown rdev->bypass_count++; 4471f59c8f9fSMark Brown 4472f59c8f9fSMark Brown if (rdev->bypass_count == rdev->open_count) { 447348325655SCharles Keepax trace_regulator_bypass_enable(name); 447448325655SCharles Keepax 4475f59c8f9fSMark Brown ret = rdev->desc->ops->set_bypass(rdev, enable); 4476f59c8f9fSMark Brown if (ret != 0) 4477f59c8f9fSMark Brown rdev->bypass_count--; 447848325655SCharles Keepax else 447948325655SCharles Keepax trace_regulator_bypass_enable_complete(name); 4480f59c8f9fSMark Brown } 4481f59c8f9fSMark Brown 4482f59c8f9fSMark Brown } else if (!enable && regulator->bypass) { 4483f59c8f9fSMark Brown rdev->bypass_count--; 4484f59c8f9fSMark Brown 4485f59c8f9fSMark Brown if (rdev->bypass_count != rdev->open_count) { 448648325655SCharles Keepax trace_regulator_bypass_disable(name); 448748325655SCharles Keepax 4488f59c8f9fSMark Brown ret = rdev->desc->ops->set_bypass(rdev, enable); 4489f59c8f9fSMark Brown if (ret != 0) 4490f59c8f9fSMark Brown rdev->bypass_count++; 449148325655SCharles Keepax else 449248325655SCharles Keepax trace_regulator_bypass_disable_complete(name); 4493f59c8f9fSMark Brown } 4494f59c8f9fSMark Brown } 4495f59c8f9fSMark Brown 4496f59c8f9fSMark Brown if (ret == 0) 4497f59c8f9fSMark Brown regulator->bypass = enable; 4498f59c8f9fSMark Brown 449966cf9a7eSMaciej Purski regulator_unlock(rdev); 4500f59c8f9fSMark Brown 4501f59c8f9fSMark Brown return ret; 4502f59c8f9fSMark Brown } 4503f59c8f9fSMark Brown EXPORT_SYMBOL_GPL(regulator_allow_bypass); 4504f59c8f9fSMark Brown 4505f59c8f9fSMark Brown /** 4506414c70cbSLiam Girdwood * regulator_register_notifier - register regulator event notifier 4507414c70cbSLiam Girdwood * @regulator: regulator source 450869279fb9SMark Brown * @nb: notifier block 4509414c70cbSLiam Girdwood * 4510414c70cbSLiam Girdwood * Register notifier block to receive regulator events. 4511414c70cbSLiam Girdwood */ 4512414c70cbSLiam Girdwood int regulator_register_notifier(struct regulator *regulator, 4513414c70cbSLiam Girdwood struct notifier_block *nb) 4514414c70cbSLiam Girdwood { 4515414c70cbSLiam Girdwood return blocking_notifier_chain_register(®ulator->rdev->notifier, 4516414c70cbSLiam Girdwood nb); 4517414c70cbSLiam Girdwood } 4518414c70cbSLiam Girdwood EXPORT_SYMBOL_GPL(regulator_register_notifier); 4519414c70cbSLiam Girdwood 4520414c70cbSLiam Girdwood /** 4521414c70cbSLiam Girdwood * regulator_unregister_notifier - unregister regulator event notifier 4522414c70cbSLiam Girdwood * @regulator: regulator source 452369279fb9SMark Brown * @nb: notifier block 4524414c70cbSLiam Girdwood * 4525414c70cbSLiam Girdwood * Unregister regulator event notifier block. 4526414c70cbSLiam Girdwood */ 4527414c70cbSLiam Girdwood int regulator_unregister_notifier(struct regulator *regulator, 4528414c70cbSLiam Girdwood struct notifier_block *nb) 4529414c70cbSLiam Girdwood { 4530414c70cbSLiam Girdwood return blocking_notifier_chain_unregister(®ulator->rdev->notifier, 4531414c70cbSLiam Girdwood nb); 4532414c70cbSLiam Girdwood } 4533414c70cbSLiam Girdwood EXPORT_SYMBOL_GPL(regulator_unregister_notifier); 4534414c70cbSLiam Girdwood 4535b136fb44SJonathan Cameron /* notify regulator consumers and downstream regulator consumers. 4536b136fb44SJonathan Cameron * Note mutex must be held by caller. 4537b136fb44SJonathan Cameron */ 45387179569aSHeiko Stübner static int _notifier_call_chain(struct regulator_dev *rdev, 4539414c70cbSLiam Girdwood unsigned long event, void *data) 4540414c70cbSLiam Girdwood { 4541414c70cbSLiam Girdwood /* call rdev chain first */ 45427179569aSHeiko Stübner return blocking_notifier_call_chain(&rdev->notifier, event, data); 4543414c70cbSLiam Girdwood } 4544414c70cbSLiam Girdwood 4545414c70cbSLiam Girdwood /** 4546414c70cbSLiam Girdwood * regulator_bulk_get - get multiple regulator consumers 4547414c70cbSLiam Girdwood * 4548414c70cbSLiam Girdwood * @dev: Device to supply 4549414c70cbSLiam Girdwood * @num_consumers: Number of consumers to register 4550414c70cbSLiam Girdwood * @consumers: Configuration of consumers; clients are stored here. 4551414c70cbSLiam Girdwood * 4552414c70cbSLiam Girdwood * @return 0 on success, an errno on failure. 4553414c70cbSLiam Girdwood * 4554414c70cbSLiam Girdwood * This helper function allows drivers to get several regulator 4555414c70cbSLiam Girdwood * consumers in one operation. If any of the regulators cannot be 4556414c70cbSLiam Girdwood * acquired then any regulators that were allocated will be freed 4557414c70cbSLiam Girdwood * before returning to the caller. 4558414c70cbSLiam Girdwood */ 4559414c70cbSLiam Girdwood int regulator_bulk_get(struct device *dev, int num_consumers, 4560414c70cbSLiam Girdwood struct regulator_bulk_data *consumers) 4561414c70cbSLiam Girdwood { 4562414c70cbSLiam Girdwood int i; 4563414c70cbSLiam Girdwood int ret; 4564414c70cbSLiam Girdwood 4565414c70cbSLiam Girdwood for (i = 0; i < num_consumers; i++) 4566414c70cbSLiam Girdwood consumers[i].consumer = NULL; 4567414c70cbSLiam Girdwood 4568414c70cbSLiam Girdwood for (i = 0; i < num_consumers; i++) { 4569565f9b07SBjorn Andersson consumers[i].consumer = regulator_get(dev, 4570565f9b07SBjorn Andersson consumers[i].supply); 4571414c70cbSLiam Girdwood if (IS_ERR(consumers[i].consumer)) { 4572414c70cbSLiam Girdwood ret = PTR_ERR(consumers[i].consumer); 4573414c70cbSLiam Girdwood consumers[i].consumer = NULL; 4574414c70cbSLiam Girdwood goto err; 4575414c70cbSLiam Girdwood } 4576414c70cbSLiam Girdwood } 4577414c70cbSLiam Girdwood 4578414c70cbSLiam Girdwood return 0; 4579414c70cbSLiam Girdwood 4580414c70cbSLiam Girdwood err: 4581b9816363SJorge Ramirez-Ortiz if (ret != -EPROBE_DEFER) 458261aab5adSMichał Mirosław dev_err(dev, "Failed to get supply '%s': %pe\n", 458361aab5adSMichał Mirosław consumers[i].supply, ERR_PTR(ret)); 4584b9816363SJorge Ramirez-Ortiz else 4585b9816363SJorge Ramirez-Ortiz dev_dbg(dev, "Failed to get supply '%s', deferring\n", 4586b9816363SJorge Ramirez-Ortiz consumers[i].supply); 4587b9816363SJorge Ramirez-Ortiz 4588b29c7690SAxel Lin while (--i >= 0) 4589414c70cbSLiam Girdwood regulator_put(consumers[i].consumer); 4590414c70cbSLiam Girdwood 4591414c70cbSLiam Girdwood return ret; 4592414c70cbSLiam Girdwood } 4593414c70cbSLiam Girdwood EXPORT_SYMBOL_GPL(regulator_bulk_get); 4594414c70cbSLiam Girdwood 4595f21e0e81SMark Brown static void regulator_bulk_enable_async(void *data, async_cookie_t cookie) 4596f21e0e81SMark Brown { 4597f21e0e81SMark Brown struct regulator_bulk_data *bulk = data; 4598f21e0e81SMark Brown 4599f21e0e81SMark Brown bulk->ret = regulator_enable(bulk->consumer); 4600f21e0e81SMark Brown } 4601f21e0e81SMark Brown 4602414c70cbSLiam Girdwood /** 4603414c70cbSLiam Girdwood * regulator_bulk_enable - enable multiple regulator consumers 4604414c70cbSLiam Girdwood * 4605414c70cbSLiam Girdwood * @num_consumers: Number of consumers 4606414c70cbSLiam Girdwood * @consumers: Consumer data; clients are stored here. 4607414c70cbSLiam Girdwood * @return 0 on success, an errno on failure 4608414c70cbSLiam Girdwood * 4609414c70cbSLiam Girdwood * This convenience API allows consumers to enable multiple regulator 4610414c70cbSLiam Girdwood * clients in a single API call. If any consumers cannot be enabled 4611414c70cbSLiam Girdwood * then any others that were enabled will be disabled again prior to 4612414c70cbSLiam Girdwood * return. 4613414c70cbSLiam Girdwood */ 4614414c70cbSLiam Girdwood int regulator_bulk_enable(int num_consumers, 4615414c70cbSLiam Girdwood struct regulator_bulk_data *consumers) 4616414c70cbSLiam Girdwood { 46172955b47dSDan Williams ASYNC_DOMAIN_EXCLUSIVE(async_domain); 4618414c70cbSLiam Girdwood int i; 4619f21e0e81SMark Brown int ret = 0; 4620414c70cbSLiam Girdwood 46216492bc1bSMark Brown for (i = 0; i < num_consumers; i++) { 4622f21e0e81SMark Brown async_schedule_domain(regulator_bulk_enable_async, 4623f21e0e81SMark Brown &consumers[i], &async_domain); 46246492bc1bSMark Brown } 4625f21e0e81SMark Brown 4626f21e0e81SMark Brown async_synchronize_full_domain(&async_domain); 4627f21e0e81SMark Brown 4628f21e0e81SMark Brown /* If any consumer failed we need to unwind any that succeeded */ 4629414c70cbSLiam Girdwood for (i = 0; i < num_consumers; i++) { 4630f21e0e81SMark Brown if (consumers[i].ret != 0) { 4631f21e0e81SMark Brown ret = consumers[i].ret; 4632414c70cbSLiam Girdwood goto err; 4633414c70cbSLiam Girdwood } 4634f21e0e81SMark Brown } 4635414c70cbSLiam Girdwood 4636414c70cbSLiam Girdwood return 0; 4637414c70cbSLiam Girdwood 4638414c70cbSLiam Girdwood err: 4639fbe31057SAndrzej Hajda for (i = 0; i < num_consumers; i++) { 4640fbe31057SAndrzej Hajda if (consumers[i].ret < 0) 464161aab5adSMichał Mirosław pr_err("Failed to enable %s: %pe\n", consumers[i].supply, 464261aab5adSMichał Mirosław ERR_PTR(consumers[i].ret)); 4643fbe31057SAndrzej Hajda else 4644414c70cbSLiam Girdwood regulator_disable(consumers[i].consumer); 4645fbe31057SAndrzej Hajda } 4646414c70cbSLiam Girdwood 4647414c70cbSLiam Girdwood return ret; 4648414c70cbSLiam Girdwood } 4649414c70cbSLiam Girdwood EXPORT_SYMBOL_GPL(regulator_bulk_enable); 4650414c70cbSLiam Girdwood 4651414c70cbSLiam Girdwood /** 4652414c70cbSLiam Girdwood * regulator_bulk_disable - disable 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 disable multiple regulator 465949e22632SSylwester Nawrocki * clients in a single API call. If any consumers cannot be disabled 466049e22632SSylwester Nawrocki * then any others that were disabled will be enabled again prior to 4661414c70cbSLiam Girdwood * return. 4662414c70cbSLiam Girdwood */ 4663414c70cbSLiam Girdwood int regulator_bulk_disable(int num_consumers, 4664414c70cbSLiam Girdwood struct regulator_bulk_data *consumers) 4665414c70cbSLiam Girdwood { 4666414c70cbSLiam Girdwood int i; 466701e86f49SMark Brown int ret, r; 4668414c70cbSLiam Girdwood 466949e22632SSylwester Nawrocki for (i = num_consumers - 1; i >= 0; --i) { 4670414c70cbSLiam Girdwood ret = regulator_disable(consumers[i].consumer); 4671414c70cbSLiam Girdwood if (ret != 0) 4672414c70cbSLiam Girdwood goto err; 4673414c70cbSLiam Girdwood } 4674414c70cbSLiam Girdwood 4675414c70cbSLiam Girdwood return 0; 4676414c70cbSLiam Girdwood 4677414c70cbSLiam Girdwood err: 467861aab5adSMichał Mirosław pr_err("Failed to disable %s: %pe\n", consumers[i].supply, ERR_PTR(ret)); 467901e86f49SMark Brown for (++i; i < num_consumers; ++i) { 468001e86f49SMark Brown r = regulator_enable(consumers[i].consumer); 468101e86f49SMark Brown if (r != 0) 468261aab5adSMichał Mirosław pr_err("Failed to re-enable %s: %pe\n", 468361aab5adSMichał Mirosław consumers[i].supply, ERR_PTR(r)); 468401e86f49SMark Brown } 4685414c70cbSLiam Girdwood 4686414c70cbSLiam Girdwood return ret; 4687414c70cbSLiam Girdwood } 4688414c70cbSLiam Girdwood EXPORT_SYMBOL_GPL(regulator_bulk_disable); 4689414c70cbSLiam Girdwood 4690414c70cbSLiam Girdwood /** 4691e1de2f42SDonggeun Kim * regulator_bulk_force_disable - force disable multiple regulator consumers 4692e1de2f42SDonggeun Kim * 4693e1de2f42SDonggeun Kim * @num_consumers: Number of consumers 4694e1de2f42SDonggeun Kim * @consumers: Consumer data; clients are stored here. 4695e1de2f42SDonggeun Kim * @return 0 on success, an errno on failure 4696e1de2f42SDonggeun Kim * 4697e1de2f42SDonggeun Kim * This convenience API allows consumers to forcibly disable multiple regulator 4698e1de2f42SDonggeun Kim * clients in a single API call. 4699e1de2f42SDonggeun Kim * NOTE: This should be used for situations when device damage will 4700e1de2f42SDonggeun Kim * likely occur if the regulators are not disabled (e.g. over temp). 4701e1de2f42SDonggeun Kim * Although regulator_force_disable function call for some consumers can 4702e1de2f42SDonggeun Kim * return error numbers, the function is called for all consumers. 4703e1de2f42SDonggeun Kim */ 4704e1de2f42SDonggeun Kim int regulator_bulk_force_disable(int num_consumers, 4705e1de2f42SDonggeun Kim struct regulator_bulk_data *consumers) 4706e1de2f42SDonggeun Kim { 4707e1de2f42SDonggeun Kim int i; 4708b8c77ff6SDmitry Torokhov int ret = 0; 4709e1de2f42SDonggeun Kim 4710b8c77ff6SDmitry Torokhov for (i = 0; i < num_consumers; i++) { 4711e1de2f42SDonggeun Kim consumers[i].ret = 4712e1de2f42SDonggeun Kim regulator_force_disable(consumers[i].consumer); 4713e1de2f42SDonggeun Kim 4714b8c77ff6SDmitry Torokhov /* Store first error for reporting */ 4715b8c77ff6SDmitry Torokhov if (consumers[i].ret && !ret) 4716e1de2f42SDonggeun Kim ret = consumers[i].ret; 4717e1de2f42SDonggeun Kim } 4718e1de2f42SDonggeun Kim 4719e1de2f42SDonggeun Kim return ret; 4720e1de2f42SDonggeun Kim } 4721e1de2f42SDonggeun Kim EXPORT_SYMBOL_GPL(regulator_bulk_force_disable); 4722e1de2f42SDonggeun Kim 4723e1de2f42SDonggeun Kim /** 4724414c70cbSLiam Girdwood * regulator_bulk_free - free multiple regulator consumers 4725414c70cbSLiam Girdwood * 4726414c70cbSLiam Girdwood * @num_consumers: Number of consumers 4727414c70cbSLiam Girdwood * @consumers: Consumer data; clients are stored here. 4728414c70cbSLiam Girdwood * 4729414c70cbSLiam Girdwood * This convenience API allows consumers to free multiple regulator 4730414c70cbSLiam Girdwood * clients in a single API call. 4731414c70cbSLiam Girdwood */ 4732414c70cbSLiam Girdwood void regulator_bulk_free(int num_consumers, 4733414c70cbSLiam Girdwood struct regulator_bulk_data *consumers) 4734414c70cbSLiam Girdwood { 4735414c70cbSLiam Girdwood int i; 4736414c70cbSLiam Girdwood 4737414c70cbSLiam Girdwood for (i = 0; i < num_consumers; i++) { 4738414c70cbSLiam Girdwood regulator_put(consumers[i].consumer); 4739414c70cbSLiam Girdwood consumers[i].consumer = NULL; 4740414c70cbSLiam Girdwood } 4741414c70cbSLiam Girdwood } 4742414c70cbSLiam Girdwood EXPORT_SYMBOL_GPL(regulator_bulk_free); 4743414c70cbSLiam Girdwood 4744414c70cbSLiam Girdwood /** 4745414c70cbSLiam Girdwood * regulator_notifier_call_chain - call regulator event notifier 474669279fb9SMark Brown * @rdev: regulator source 4747414c70cbSLiam Girdwood * @event: notifier block 474869279fb9SMark Brown * @data: callback-specific data. 4749414c70cbSLiam Girdwood * 4750414c70cbSLiam Girdwood * Called by regulator drivers to notify clients a regulator event has 47513bca239dSMichał Mirosław * occurred. 4752414c70cbSLiam Girdwood */ 4753414c70cbSLiam Girdwood int regulator_notifier_call_chain(struct regulator_dev *rdev, 4754414c70cbSLiam Girdwood unsigned long event, void *data) 4755414c70cbSLiam Girdwood { 4756414c70cbSLiam Girdwood _notifier_call_chain(rdev, event, data); 4757414c70cbSLiam Girdwood return NOTIFY_DONE; 4758414c70cbSLiam Girdwood 4759414c70cbSLiam Girdwood } 4760414c70cbSLiam Girdwood EXPORT_SYMBOL_GPL(regulator_notifier_call_chain); 4761414c70cbSLiam Girdwood 4762be721979SMark Brown /** 4763be721979SMark Brown * regulator_mode_to_status - convert a regulator mode into a status 4764be721979SMark Brown * 4765be721979SMark Brown * @mode: Mode to convert 4766be721979SMark Brown * 4767be721979SMark Brown * Convert a regulator mode into a status. 4768be721979SMark Brown */ 4769be721979SMark Brown int regulator_mode_to_status(unsigned int mode) 4770be721979SMark Brown { 4771be721979SMark Brown switch (mode) { 4772be721979SMark Brown case REGULATOR_MODE_FAST: 4773be721979SMark Brown return REGULATOR_STATUS_FAST; 4774be721979SMark Brown case REGULATOR_MODE_NORMAL: 4775be721979SMark Brown return REGULATOR_STATUS_NORMAL; 4776be721979SMark Brown case REGULATOR_MODE_IDLE: 4777be721979SMark Brown return REGULATOR_STATUS_IDLE; 477803ffcf3dSKrystian Garbaciak case REGULATOR_MODE_STANDBY: 4779be721979SMark Brown return REGULATOR_STATUS_STANDBY; 4780be721979SMark Brown default: 47811beaf762SKrystian Garbaciak return REGULATOR_STATUS_UNDEFINED; 4782be721979SMark Brown } 4783be721979SMark Brown } 4784be721979SMark Brown EXPORT_SYMBOL_GPL(regulator_mode_to_status); 4785be721979SMark Brown 478639f802d6STakashi Iwai static struct attribute *regulator_dev_attrs[] = { 478739f802d6STakashi Iwai &dev_attr_name.attr, 478839f802d6STakashi Iwai &dev_attr_num_users.attr, 478939f802d6STakashi Iwai &dev_attr_type.attr, 479039f802d6STakashi Iwai &dev_attr_microvolts.attr, 479139f802d6STakashi Iwai &dev_attr_microamps.attr, 479239f802d6STakashi Iwai &dev_attr_opmode.attr, 479339f802d6STakashi Iwai &dev_attr_state.attr, 479439f802d6STakashi Iwai &dev_attr_status.attr, 479539f802d6STakashi Iwai &dev_attr_bypass.attr, 479639f802d6STakashi Iwai &dev_attr_requested_microamps.attr, 479739f802d6STakashi Iwai &dev_attr_min_microvolts.attr, 479839f802d6STakashi Iwai &dev_attr_max_microvolts.attr, 479939f802d6STakashi Iwai &dev_attr_min_microamps.attr, 480039f802d6STakashi Iwai &dev_attr_max_microamps.attr, 480139f802d6STakashi Iwai &dev_attr_suspend_standby_state.attr, 480239f802d6STakashi Iwai &dev_attr_suspend_mem_state.attr, 480339f802d6STakashi Iwai &dev_attr_suspend_disk_state.attr, 480439f802d6STakashi Iwai &dev_attr_suspend_standby_microvolts.attr, 480539f802d6STakashi Iwai &dev_attr_suspend_mem_microvolts.attr, 480639f802d6STakashi Iwai &dev_attr_suspend_disk_microvolts.attr, 480739f802d6STakashi Iwai &dev_attr_suspend_standby_mode.attr, 480839f802d6STakashi Iwai &dev_attr_suspend_mem_mode.attr, 480939f802d6STakashi Iwai &dev_attr_suspend_disk_mode.attr, 481039f802d6STakashi Iwai NULL 481139f802d6STakashi Iwai }; 481239f802d6STakashi Iwai 48137ad68e2fSDavid Brownell /* 48147ad68e2fSDavid Brownell * To avoid cluttering sysfs (and memory) with useless state, only 48157ad68e2fSDavid Brownell * create attributes that can be meaningfully displayed. 48167ad68e2fSDavid Brownell */ 481739f802d6STakashi Iwai static umode_t regulator_attr_is_visible(struct kobject *kobj, 481839f802d6STakashi Iwai struct attribute *attr, int idx) 48197ad68e2fSDavid Brownell { 482039f802d6STakashi Iwai struct device *dev = kobj_to_dev(kobj); 482183080a14SGeliang Tang struct regulator_dev *rdev = dev_to_rdev(dev); 4822272e2315SGuodong Xu const struct regulator_ops *ops = rdev->desc->ops; 482339f802d6STakashi Iwai umode_t mode = attr->mode; 482439f802d6STakashi Iwai 482539f802d6STakashi Iwai /* these three are always present */ 482639f802d6STakashi Iwai if (attr == &dev_attr_name.attr || 482739f802d6STakashi Iwai attr == &dev_attr_num_users.attr || 482839f802d6STakashi Iwai attr == &dev_attr_type.attr) 482939f802d6STakashi Iwai return mode; 48307ad68e2fSDavid Brownell 48317ad68e2fSDavid Brownell /* some attributes need specific methods to be displayed */ 483239f802d6STakashi Iwai if (attr == &dev_attr_microvolts.attr) { 48334c78899bSMark Brown if ((ops->get_voltage && ops->get_voltage(rdev) >= 0) || 4834f2889e65SMark Brown (ops->get_voltage_sel && ops->get_voltage_sel(rdev) >= 0) || 48355a523605SLaxman Dewangan (ops->list_voltage && ops->list_voltage(rdev, 0) >= 0) || 483639f802d6STakashi Iwai (rdev->desc->fixed_uV && rdev->desc->n_voltages == 1)) 483739f802d6STakashi Iwai return mode; 483839f802d6STakashi Iwai return 0; 4839f59c8f9fSMark Brown } 48407ad68e2fSDavid Brownell 484139f802d6STakashi Iwai if (attr == &dev_attr_microamps.attr) 484239f802d6STakashi Iwai return ops->get_current_limit ? mode : 0; 484339f802d6STakashi Iwai 484439f802d6STakashi Iwai if (attr == &dev_attr_opmode.attr) 484539f802d6STakashi Iwai return ops->get_mode ? mode : 0; 484639f802d6STakashi Iwai 484739f802d6STakashi Iwai if (attr == &dev_attr_state.attr) 484839f802d6STakashi Iwai return (rdev->ena_pin || ops->is_enabled) ? mode : 0; 484939f802d6STakashi Iwai 485039f802d6STakashi Iwai if (attr == &dev_attr_status.attr) 485139f802d6STakashi Iwai return ops->get_status ? mode : 0; 485239f802d6STakashi Iwai 485339f802d6STakashi Iwai if (attr == &dev_attr_bypass.attr) 485439f802d6STakashi Iwai return ops->get_bypass ? mode : 0; 485539f802d6STakashi Iwai 48567ad68e2fSDavid Brownell /* constraints need specific supporting methods */ 485739f802d6STakashi Iwai if (attr == &dev_attr_min_microvolts.attr || 485839f802d6STakashi Iwai attr == &dev_attr_max_microvolts.attr) 485939f802d6STakashi Iwai return (ops->set_voltage || ops->set_voltage_sel) ? mode : 0; 486039f802d6STakashi Iwai 486139f802d6STakashi Iwai if (attr == &dev_attr_min_microamps.attr || 486239f802d6STakashi Iwai attr == &dev_attr_max_microamps.attr) 486339f802d6STakashi Iwai return ops->set_current_limit ? mode : 0; 486439f802d6STakashi Iwai 486539f802d6STakashi Iwai if (attr == &dev_attr_suspend_standby_state.attr || 486639f802d6STakashi Iwai attr == &dev_attr_suspend_mem_state.attr || 486739f802d6STakashi Iwai attr == &dev_attr_suspend_disk_state.attr) 486839f802d6STakashi Iwai return mode; 486939f802d6STakashi Iwai 487039f802d6STakashi Iwai if (attr == &dev_attr_suspend_standby_microvolts.attr || 487139f802d6STakashi Iwai attr == &dev_attr_suspend_mem_microvolts.attr || 487239f802d6STakashi Iwai attr == &dev_attr_suspend_disk_microvolts.attr) 487339f802d6STakashi Iwai return ops->set_suspend_voltage ? mode : 0; 487439f802d6STakashi Iwai 487539f802d6STakashi Iwai if (attr == &dev_attr_suspend_standby_mode.attr || 487639f802d6STakashi Iwai attr == &dev_attr_suspend_mem_mode.attr || 487739f802d6STakashi Iwai attr == &dev_attr_suspend_disk_mode.attr) 487839f802d6STakashi Iwai return ops->set_suspend_mode ? mode : 0; 487939f802d6STakashi Iwai 488039f802d6STakashi Iwai return mode; 48817ad68e2fSDavid Brownell } 48827ad68e2fSDavid Brownell 488339f802d6STakashi Iwai static const struct attribute_group regulator_dev_group = { 488439f802d6STakashi Iwai .attrs = regulator_dev_attrs, 488539f802d6STakashi Iwai .is_visible = regulator_attr_is_visible, 488639f802d6STakashi Iwai }; 48877ad68e2fSDavid Brownell 488839f802d6STakashi Iwai static const struct attribute_group *regulator_dev_groups[] = { 488939f802d6STakashi Iwai ®ulator_dev_group, 489039f802d6STakashi Iwai NULL 489139f802d6STakashi Iwai }; 489239f802d6STakashi Iwai 489339f802d6STakashi Iwai static void regulator_dev_release(struct device *dev) 489439f802d6STakashi Iwai { 489539f802d6STakashi Iwai struct regulator_dev *rdev = dev_get_drvdata(dev); 489629f5f486SMark Brown 489729f5f486SMark Brown kfree(rdev->constraints); 489829f5f486SMark Brown of_node_put(rdev->dev.of_node); 489939f802d6STakashi Iwai kfree(rdev); 49007ad68e2fSDavid Brownell } 49017ad68e2fSDavid Brownell 49021130e5b3SMark Brown static void rdev_init_debugfs(struct regulator_dev *rdev) 49031130e5b3SMark Brown { 4904a9eaa813SGuenter Roeck struct device *parent = rdev->dev.parent; 4905a9eaa813SGuenter Roeck const char *rname = rdev_get_name(rdev); 4906a9eaa813SGuenter Roeck char name[NAME_MAX]; 4907a9eaa813SGuenter Roeck 4908a9eaa813SGuenter Roeck /* Avoid duplicate debugfs directory names */ 4909a9eaa813SGuenter Roeck if (parent && rname == rdev->desc->name) { 4910a9eaa813SGuenter Roeck snprintf(name, sizeof(name), "%s-%s", dev_name(parent), 4911a9eaa813SGuenter Roeck rname); 4912a9eaa813SGuenter Roeck rname = name; 4913a9eaa813SGuenter Roeck } 4914a9eaa813SGuenter Roeck 4915a9eaa813SGuenter Roeck rdev->debugfs = debugfs_create_dir(rname, debugfs_root); 491624751434SStephen Boyd if (!rdev->debugfs) { 49171130e5b3SMark Brown rdev_warn(rdev, "Failed to create debugfs directory\n"); 49181130e5b3SMark Brown return; 49191130e5b3SMark Brown } 49201130e5b3SMark Brown 49211130e5b3SMark Brown debugfs_create_u32("use_count", 0444, rdev->debugfs, 49221130e5b3SMark Brown &rdev->use_count); 49231130e5b3SMark Brown debugfs_create_u32("open_count", 0444, rdev->debugfs, 49241130e5b3SMark Brown &rdev->open_count); 4925f59c8f9fSMark Brown debugfs_create_u32("bypass_count", 0444, rdev->debugfs, 4926f59c8f9fSMark Brown &rdev->bypass_count); 49271130e5b3SMark Brown } 49281130e5b3SMark Brown 49295e3ca2b3SJavier Martinez Canillas static int regulator_register_resolve_supply(struct device *dev, void *data) 49305e3ca2b3SJavier Martinez Canillas { 49317ddede6aSJon Hunter struct regulator_dev *rdev = dev_to_rdev(dev); 49327ddede6aSJon Hunter 49337ddede6aSJon Hunter if (regulator_resolve_supply(rdev)) 49347ddede6aSJon Hunter rdev_dbg(rdev, "unable to resolve supply\n"); 49357ddede6aSJon Hunter 49367ddede6aSJon Hunter return 0; 49375e3ca2b3SJavier Martinez Canillas } 49385e3ca2b3SJavier Martinez Canillas 4939d8ca7d18SDmitry Osipenko int regulator_coupler_register(struct regulator_coupler *coupler) 4940d8ca7d18SDmitry Osipenko { 4941d8ca7d18SDmitry Osipenko mutex_lock(®ulator_list_mutex); 4942d8ca7d18SDmitry Osipenko list_add_tail(&coupler->list, ®ulator_coupler_list); 4943d8ca7d18SDmitry Osipenko mutex_unlock(®ulator_list_mutex); 4944d8ca7d18SDmitry Osipenko 4945d8ca7d18SDmitry Osipenko return 0; 4946d8ca7d18SDmitry Osipenko } 4947d8ca7d18SDmitry Osipenko 4948d8ca7d18SDmitry Osipenko static struct regulator_coupler * 4949d8ca7d18SDmitry Osipenko regulator_find_coupler(struct regulator_dev *rdev) 4950d8ca7d18SDmitry Osipenko { 4951d8ca7d18SDmitry Osipenko struct regulator_coupler *coupler; 4952d8ca7d18SDmitry Osipenko int err; 4953d8ca7d18SDmitry Osipenko 4954d8ca7d18SDmitry Osipenko /* 4955d8ca7d18SDmitry Osipenko * Note that regulators are appended to the list and the generic 4956d8ca7d18SDmitry Osipenko * coupler is registered first, hence it will be attached at last 4957d8ca7d18SDmitry Osipenko * if nobody cared. 4958d8ca7d18SDmitry Osipenko */ 4959d8ca7d18SDmitry Osipenko list_for_each_entry_reverse(coupler, ®ulator_coupler_list, list) { 4960d8ca7d18SDmitry Osipenko err = coupler->attach_regulator(coupler, rdev); 4961d8ca7d18SDmitry Osipenko if (!err) { 4962d8ca7d18SDmitry Osipenko if (!coupler->balance_voltage && 4963d8ca7d18SDmitry Osipenko rdev->coupling_desc.n_coupled > 2) 4964d8ca7d18SDmitry Osipenko goto err_unsupported; 4965d8ca7d18SDmitry Osipenko 4966d8ca7d18SDmitry Osipenko return coupler; 4967d8ca7d18SDmitry Osipenko } 4968d8ca7d18SDmitry Osipenko 4969d8ca7d18SDmitry Osipenko if (err < 0) 4970d8ca7d18SDmitry Osipenko return ERR_PTR(err); 4971d8ca7d18SDmitry Osipenko 4972d8ca7d18SDmitry Osipenko if (err == 1) 4973d8ca7d18SDmitry Osipenko continue; 4974d8ca7d18SDmitry Osipenko 4975d8ca7d18SDmitry Osipenko break; 4976d8ca7d18SDmitry Osipenko } 4977d8ca7d18SDmitry Osipenko 4978d8ca7d18SDmitry Osipenko return ERR_PTR(-EINVAL); 4979d8ca7d18SDmitry Osipenko 4980d8ca7d18SDmitry Osipenko err_unsupported: 4981d8ca7d18SDmitry Osipenko if (coupler->detach_regulator) 4982d8ca7d18SDmitry Osipenko coupler->detach_regulator(coupler, rdev); 4983d8ca7d18SDmitry Osipenko 4984d8ca7d18SDmitry Osipenko rdev_err(rdev, 4985d8ca7d18SDmitry Osipenko "Voltage balancing for multiple regulator couples is unimplemented\n"); 4986d8ca7d18SDmitry Osipenko 4987d8ca7d18SDmitry Osipenko return ERR_PTR(-EPERM); 4988d8ca7d18SDmitry Osipenko } 4989d8ca7d18SDmitry Osipenko 4990f9503385SDmitry Osipenko static void regulator_resolve_coupling(struct regulator_dev *rdev) 4991d3d64537SMaciej Purski { 4992d8ca7d18SDmitry Osipenko struct regulator_coupler *coupler = rdev->coupling_desc.coupler; 4993d3d64537SMaciej Purski struct coupling_desc *c_desc = &rdev->coupling_desc; 4994d3d64537SMaciej Purski int n_coupled = c_desc->n_coupled; 4995d3d64537SMaciej Purski struct regulator_dev *c_rdev; 4996d3d64537SMaciej Purski int i; 4997d3d64537SMaciej Purski 4998d3d64537SMaciej Purski for (i = 1; i < n_coupled; i++) { 4999d3d64537SMaciej Purski /* already resolved */ 5000d3d64537SMaciej Purski if (c_desc->coupled_rdevs[i]) 5001d3d64537SMaciej Purski continue; 5002d3d64537SMaciej Purski 5003d3d64537SMaciej Purski c_rdev = of_parse_coupled_regulator(rdev, i - 1); 5004d3d64537SMaciej Purski 5005f9503385SDmitry Osipenko if (!c_rdev) 5006f9503385SDmitry Osipenko continue; 5007f9503385SDmitry Osipenko 5008d8ca7d18SDmitry Osipenko if (c_rdev->coupling_desc.coupler != coupler) { 5009d8ca7d18SDmitry Osipenko rdev_err(rdev, "coupler mismatch with %s\n", 5010d8ca7d18SDmitry Osipenko rdev_get_name(c_rdev)); 5011d8ca7d18SDmitry Osipenko return; 5012d8ca7d18SDmitry Osipenko } 5013d8ca7d18SDmitry Osipenko 5014d3d64537SMaciej Purski c_desc->coupled_rdevs[i] = c_rdev; 5015d3d64537SMaciej Purski c_desc->n_resolved++; 5016f9503385SDmitry Osipenko 5017f9503385SDmitry Osipenko regulator_resolve_coupling(c_rdev); 5018d3d64537SMaciej Purski } 5019d3d64537SMaciej Purski } 5020d3d64537SMaciej Purski 50216303f3e7SDmitry Osipenko static void regulator_remove_coupling(struct regulator_dev *rdev) 5022d3d64537SMaciej Purski { 5023d8ca7d18SDmitry Osipenko struct regulator_coupler *coupler = rdev->coupling_desc.coupler; 50246303f3e7SDmitry Osipenko struct coupling_desc *__c_desc, *c_desc = &rdev->coupling_desc; 50256303f3e7SDmitry Osipenko struct regulator_dev *__c_rdev, *c_rdev; 50266303f3e7SDmitry Osipenko unsigned int __n_coupled, n_coupled; 50276303f3e7SDmitry Osipenko int i, k; 5028d8ca7d18SDmitry Osipenko int err; 5029d3d64537SMaciej Purski 50306303f3e7SDmitry Osipenko n_coupled = c_desc->n_coupled; 5031d3d64537SMaciej Purski 50326303f3e7SDmitry Osipenko for (i = 1; i < n_coupled; i++) { 50336303f3e7SDmitry Osipenko c_rdev = c_desc->coupled_rdevs[i]; 5034d3d64537SMaciej Purski 50356303f3e7SDmitry Osipenko if (!c_rdev) 50366303f3e7SDmitry Osipenko continue; 50376303f3e7SDmitry Osipenko 50386303f3e7SDmitry Osipenko regulator_lock(c_rdev); 50396303f3e7SDmitry Osipenko 50406303f3e7SDmitry Osipenko __c_desc = &c_rdev->coupling_desc; 50416303f3e7SDmitry Osipenko __n_coupled = __c_desc->n_coupled; 50426303f3e7SDmitry Osipenko 50436303f3e7SDmitry Osipenko for (k = 1; k < __n_coupled; k++) { 50446303f3e7SDmitry Osipenko __c_rdev = __c_desc->coupled_rdevs[k]; 50456303f3e7SDmitry Osipenko 50466303f3e7SDmitry Osipenko if (__c_rdev == rdev) { 50476303f3e7SDmitry Osipenko __c_desc->coupled_rdevs[k] = NULL; 50486303f3e7SDmitry Osipenko __c_desc->n_resolved--; 50496303f3e7SDmitry Osipenko break; 50506303f3e7SDmitry Osipenko } 5051d3d64537SMaciej Purski } 5052d3d64537SMaciej Purski 50536303f3e7SDmitry Osipenko regulator_unlock(c_rdev); 50546303f3e7SDmitry Osipenko 50556303f3e7SDmitry Osipenko c_desc->coupled_rdevs[i] = NULL; 50566303f3e7SDmitry Osipenko c_desc->n_resolved--; 50576303f3e7SDmitry Osipenko } 5058d8ca7d18SDmitry Osipenko 5059d8ca7d18SDmitry Osipenko if (coupler && coupler->detach_regulator) { 5060d8ca7d18SDmitry Osipenko err = coupler->detach_regulator(coupler, rdev); 5061d8ca7d18SDmitry Osipenko if (err) 506261aab5adSMichał Mirosław rdev_err(rdev, "failed to detach from coupler: %pe\n", 506361aab5adSMichał Mirosław ERR_PTR(err)); 5064d8ca7d18SDmitry Osipenko } 5065d8ca7d18SDmitry Osipenko 5066d8ca7d18SDmitry Osipenko kfree(rdev->coupling_desc.coupled_rdevs); 5067d8ca7d18SDmitry Osipenko rdev->coupling_desc.coupled_rdevs = NULL; 50686303f3e7SDmitry Osipenko } 50696303f3e7SDmitry Osipenko 5070f9503385SDmitry Osipenko static int regulator_init_coupling(struct regulator_dev *rdev) 5071d3d64537SMaciej Purski { 50727d819664SMichał Mirosław struct regulator_dev **coupled; 5073d8ca7d18SDmitry Osipenko int err, n_phandles; 5074d3d64537SMaciej Purski 5075d3d64537SMaciej Purski if (!IS_ENABLED(CONFIG_OF)) 5076d3d64537SMaciej Purski n_phandles = 0; 5077d3d64537SMaciej Purski else 5078d3d64537SMaciej Purski n_phandles = of_get_n_coupled(rdev); 5079d3d64537SMaciej Purski 50807d819664SMichał Mirosław coupled = kcalloc(n_phandles + 1, sizeof(*coupled), GFP_KERNEL); 50817d819664SMichał Mirosław if (!coupled) 5082d8ca7d18SDmitry Osipenko return -ENOMEM; 5083d3d64537SMaciej Purski 50847d819664SMichał Mirosław rdev->coupling_desc.coupled_rdevs = coupled; 50857d819664SMichał Mirosław 5086d3d64537SMaciej Purski /* 5087d3d64537SMaciej Purski * Every regulator should always have coupling descriptor filled with 5088d3d64537SMaciej Purski * at least pointer to itself. 5089d3d64537SMaciej Purski */ 5090d3d64537SMaciej Purski rdev->coupling_desc.coupled_rdevs[0] = rdev; 5091d3d64537SMaciej Purski rdev->coupling_desc.n_coupled = n_phandles + 1; 5092d3d64537SMaciej Purski rdev->coupling_desc.n_resolved++; 5093d3d64537SMaciej Purski 5094d3d64537SMaciej Purski /* regulator isn't coupled */ 5095d3d64537SMaciej Purski if (n_phandles == 0) 5096d3d64537SMaciej Purski return 0; 5097d3d64537SMaciej Purski 5098d3d64537SMaciej Purski if (!of_check_coupling_data(rdev)) 5099d3d64537SMaciej Purski return -EPERM; 5100d3d64537SMaciej Purski 510173a32129SMichał Mirosław mutex_lock(®ulator_list_mutex); 5102d8ca7d18SDmitry Osipenko rdev->coupling_desc.coupler = regulator_find_coupler(rdev); 510373a32129SMichał Mirosław mutex_unlock(®ulator_list_mutex); 510473a32129SMichał Mirosław 5105d8ca7d18SDmitry Osipenko if (IS_ERR(rdev->coupling_desc.coupler)) { 5106d8ca7d18SDmitry Osipenko err = PTR_ERR(rdev->coupling_desc.coupler); 510761aab5adSMichał Mirosław rdev_err(rdev, "failed to get coupler: %pe\n", ERR_PTR(err)); 5108d8ca7d18SDmitry Osipenko return err; 5109d8ca7d18SDmitry Osipenko } 5110d8ca7d18SDmitry Osipenko 5111d3d64537SMaciej Purski return 0; 5112d3d64537SMaciej Purski } 5113d3d64537SMaciej Purski 5114d8ca7d18SDmitry Osipenko static int generic_coupler_attach(struct regulator_coupler *coupler, 5115d8ca7d18SDmitry Osipenko struct regulator_dev *rdev) 5116d8ca7d18SDmitry Osipenko { 5117d8ca7d18SDmitry Osipenko if (rdev->coupling_desc.n_coupled > 2) { 5118d8ca7d18SDmitry Osipenko rdev_err(rdev, 5119d8ca7d18SDmitry Osipenko "Voltage balancing for multiple regulator couples is unimplemented\n"); 5120d8ca7d18SDmitry Osipenko return -EPERM; 5121d8ca7d18SDmitry Osipenko } 5122d8ca7d18SDmitry Osipenko 5123e381bfe4SDmitry Osipenko if (!rdev->constraints->always_on) { 5124e381bfe4SDmitry Osipenko rdev_err(rdev, 5125e381bfe4SDmitry Osipenko "Coupling of a non always-on regulator is unimplemented\n"); 5126e381bfe4SDmitry Osipenko return -ENOTSUPP; 5127e381bfe4SDmitry Osipenko } 5128e381bfe4SDmitry Osipenko 5129d8ca7d18SDmitry Osipenko return 0; 5130d8ca7d18SDmitry Osipenko } 5131d8ca7d18SDmitry Osipenko 5132d8ca7d18SDmitry Osipenko static struct regulator_coupler generic_regulator_coupler = { 5133d8ca7d18SDmitry Osipenko .attach_regulator = generic_coupler_attach, 5134d8ca7d18SDmitry Osipenko }; 5135d8ca7d18SDmitry Osipenko 5136414c70cbSLiam Girdwood /** 5137414c70cbSLiam Girdwood * regulator_register - register regulator 513869279fb9SMark Brown * @regulator_desc: regulator to register 5139f47531b1SKrzysztof Kozlowski * @cfg: runtime configuration for regulator 5140414c70cbSLiam Girdwood * 5141414c70cbSLiam Girdwood * Called by regulator drivers to register a regulator. 51420384618aSAxel Lin * Returns a valid pointer to struct regulator_dev on success 51430384618aSAxel Lin * or an ERR_PTR() on error. 5144414c70cbSLiam Girdwood */ 514565f26846SMark Brown struct regulator_dev * 514665f26846SMark Brown regulator_register(const struct regulator_desc *regulator_desc, 51471b3de223SKrzysztof Kozlowski const struct regulator_config *cfg) 5148414c70cbSLiam Girdwood { 51499a8f5e07SMark Brown const struct regulation_constraints *constraints = NULL; 5150c172708dSMark Brown const struct regulator_init_data *init_data; 51511b3de223SKrzysztof Kozlowski struct regulator_config *config = NULL; 515272dca06fSAniroop Mathur static atomic_t regulator_no = ATOMIC_INIT(-1); 5153414c70cbSLiam Girdwood struct regulator_dev *rdev; 51540edb040dSLinus Walleij bool dangling_cfg_gpiod = false; 51550edb040dSLinus Walleij bool dangling_of_gpiod = false; 515632c8fad4SMark Brown struct device *dev; 5157a5766f11SLiam Girdwood int ret, i; 5158414c70cbSLiam Girdwood 51590edb040dSLinus Walleij if (cfg == NULL) 5160414c70cbSLiam Girdwood return ERR_PTR(-EINVAL); 51610edb040dSLinus Walleij if (cfg->ena_gpiod) 51620edb040dSLinus Walleij dangling_cfg_gpiod = true; 51630edb040dSLinus Walleij if (regulator_desc == NULL) { 51640edb040dSLinus Walleij ret = -EINVAL; 51650edb040dSLinus Walleij goto rinse; 51660edb040dSLinus Walleij } 5167414c70cbSLiam Girdwood 51681b3de223SKrzysztof Kozlowski dev = cfg->dev; 5169dcf70112SMark Brown WARN_ON(!dev); 517032c8fad4SMark Brown 51710edb040dSLinus Walleij if (regulator_desc->name == NULL || regulator_desc->ops == NULL) { 51720edb040dSLinus Walleij ret = -EINVAL; 51730edb040dSLinus Walleij goto rinse; 51740edb040dSLinus Walleij } 5175414c70cbSLiam Girdwood 5176cd78dfc6SDiego Liziero if (regulator_desc->type != REGULATOR_VOLTAGE && 51770edb040dSLinus Walleij regulator_desc->type != REGULATOR_CURRENT) { 51780edb040dSLinus Walleij ret = -EINVAL; 51790edb040dSLinus Walleij goto rinse; 51800edb040dSLinus Walleij } 5181414c70cbSLiam Girdwood 5182476c2d83SMark Brown /* Only one of each should be implemented */ 5183476c2d83SMark Brown WARN_ON(regulator_desc->ops->get_voltage && 5184476c2d83SMark Brown regulator_desc->ops->get_voltage_sel); 5185e8eef82bSMark Brown WARN_ON(regulator_desc->ops->set_voltage && 5186e8eef82bSMark Brown regulator_desc->ops->set_voltage_sel); 5187476c2d83SMark Brown 5188476c2d83SMark Brown /* If we're using selectors we must implement list_voltage. */ 5189476c2d83SMark Brown if (regulator_desc->ops->get_voltage_sel && 5190476c2d83SMark Brown !regulator_desc->ops->list_voltage) { 51910edb040dSLinus Walleij ret = -EINVAL; 51920edb040dSLinus Walleij goto rinse; 5193476c2d83SMark Brown } 5194e8eef82bSMark Brown if (regulator_desc->ops->set_voltage_sel && 5195e8eef82bSMark Brown !regulator_desc->ops->list_voltage) { 51960edb040dSLinus Walleij ret = -EINVAL; 51970edb040dSLinus Walleij goto rinse; 5198e8eef82bSMark Brown } 5199476c2d83SMark Brown 5200414c70cbSLiam Girdwood rdev = kzalloc(sizeof(struct regulator_dev), GFP_KERNEL); 52010edb040dSLinus Walleij if (rdev == NULL) { 52020edb040dSLinus Walleij ret = -ENOMEM; 52030edb040dSLinus Walleij goto rinse; 52040edb040dSLinus Walleij } 5205d3c73156SMichał Mirosław device_initialize(&rdev->dev); 5206414c70cbSLiam Girdwood 52071b3de223SKrzysztof Kozlowski /* 52081b3de223SKrzysztof Kozlowski * Duplicate the config so the driver could override it after 52091b3de223SKrzysztof Kozlowski * parsing init data. 52101b3de223SKrzysztof Kozlowski */ 52111b3de223SKrzysztof Kozlowski config = kmemdup(cfg, sizeof(*cfg), GFP_KERNEL); 52121b3de223SKrzysztof Kozlowski if (config == NULL) { 52130edb040dSLinus Walleij ret = -ENOMEM; 5214d3c73156SMichał Mirosław goto clean; 52151b3de223SKrzysztof Kozlowski } 52161b3de223SKrzysztof Kozlowski 5217bfa21a0dSKrzysztof Kozlowski init_data = regulator_of_get_init_data(dev, regulator_desc, config, 5218a0c7b164SMark Brown &rdev->dev.of_node); 5219f8970d34SMarco Felsch 5220f8970d34SMarco Felsch /* 5221f8970d34SMarco Felsch * Sometimes not all resources are probed already so we need to take 5222f8970d34SMarco Felsch * that into account. This happens most the time if the ena_gpiod comes 5223f8970d34SMarco Felsch * from a gpio extender or something else. 5224f8970d34SMarco Felsch */ 5225f8970d34SMarco Felsch if (PTR_ERR(init_data) == -EPROBE_DEFER) { 5226f8970d34SMarco Felsch ret = -EPROBE_DEFER; 5227d3c73156SMichał Mirosław goto clean; 5228f8970d34SMarco Felsch } 5229f8970d34SMarco Felsch 52300edb040dSLinus Walleij /* 52310edb040dSLinus Walleij * We need to keep track of any GPIO descriptor coming from the 52320edb040dSLinus Walleij * device tree until we have handled it over to the core. If the 52330edb040dSLinus Walleij * config that was passed in to this function DOES NOT contain 52340edb040dSLinus Walleij * a descriptor, and the config after this call DOES contain 523548f1b4efSKrzysztof Kozlowski * a descriptor, we definitely got one from parsing the device 52360edb040dSLinus Walleij * tree. 52370edb040dSLinus Walleij */ 52380edb040dSLinus Walleij if (!cfg->ena_gpiod && config->ena_gpiod) 52390edb040dSLinus Walleij dangling_of_gpiod = true; 5240a0c7b164SMark Brown if (!init_data) { 5241a0c7b164SMark Brown init_data = config->init_data; 5242a0c7b164SMark Brown rdev->dev.of_node = of_node_get(config->of_node); 5243a0c7b164SMark Brown } 5244a0c7b164SMark Brown 5245f8702f9eSDmitry Osipenko ww_mutex_init(&rdev->mutex, ®ulator_ww_class); 5246c172708dSMark Brown rdev->reg_data = config->driver_data; 5247414c70cbSLiam Girdwood rdev->owner = regulator_desc->owner; 5248414c70cbSLiam Girdwood rdev->desc = regulator_desc; 52493a4b0a07SMark Brown if (config->regmap) 525065b19ce6SMark Brown rdev->regmap = config->regmap; 525152b84dacSAnilKumar Ch else if (dev_get_regmap(dev, NULL)) 52523a4b0a07SMark Brown rdev->regmap = dev_get_regmap(dev, NULL); 525352b84dacSAnilKumar Ch else if (dev->parent) 525452b84dacSAnilKumar Ch rdev->regmap = dev_get_regmap(dev->parent, NULL); 5255414c70cbSLiam Girdwood INIT_LIST_HEAD(&rdev->consumer_list); 5256414c70cbSLiam Girdwood INIT_LIST_HEAD(&rdev->list); 5257414c70cbSLiam Girdwood BLOCKING_INIT_NOTIFIER_HEAD(&rdev->notifier); 5258da07ecd9SMark Brown INIT_DELAYED_WORK(&rdev->disable_work, regulator_disable_work); 5259414c70cbSLiam Girdwood 5260a5766f11SLiam Girdwood /* preform any regulator specific init */ 52619a8f5e07SMark Brown if (init_data && init_data->regulator_init) { 5262a5766f11SLiam Girdwood ret = init_data->regulator_init(rdev->reg_data); 52634fca9545SDavid Brownell if (ret < 0) 52644fca9545SDavid Brownell goto clean; 5265a5766f11SLiam Girdwood } 5266a5766f11SLiam Girdwood 5267541d052dSLinus Walleij if (config->ena_gpiod) { 5268daad134dSKrzysztof Adamski ret = regulator_ena_gpio_request(rdev, config); 5269daad134dSKrzysztof Adamski if (ret != 0) { 527061aab5adSMichał Mirosław rdev_err(rdev, "Failed to request enable GPIO: %pe\n", 527161aab5adSMichał Mirosław ERR_PTR(ret)); 527232165230SKrzysztof Adamski goto clean; 5273daad134dSKrzysztof Adamski } 52740edb040dSLinus Walleij /* The regulator core took over the GPIO descriptor */ 52750edb040dSLinus Walleij dangling_cfg_gpiod = false; 52760edb040dSLinus Walleij dangling_of_gpiod = false; 5277daad134dSKrzysztof Adamski } 5278daad134dSKrzysztof Adamski 5279a5766f11SLiam Girdwood /* register with sysfs */ 5280a5766f11SLiam Girdwood rdev->dev.class = ®ulator_class; 5281a5766f11SLiam Girdwood rdev->dev.parent = dev; 528272dca06fSAniroop Mathur dev_set_name(&rdev->dev, "regulator.%lu", 528339138818SAniroop Mathur (unsigned long) atomic_inc_return(®ulator_no)); 52849177514cSVladimir Zapolskiy dev_set_drvdata(&rdev->dev, rdev); 5285a5766f11SLiam Girdwood 528674f544c1SMike Rapoport /* set regulator constraints */ 52879a8f5e07SMark Brown if (init_data) 52889a8f5e07SMark Brown constraints = &init_data->constraints; 52899a8f5e07SMark Brown 52909a8f5e07SMark Brown if (init_data && init_data->supply_regulator) 52916261b06dSBjorn Andersson rdev->supply_name = init_data->supply_regulator; 529269511a45SRajendra Nayak else if (regulator_desc->supply_name) 52936261b06dSBjorn Andersson rdev->supply_name = regulator_desc->supply_name; 529469511a45SRajendra Nayak 529545389c47SJon Hunter ret = set_machine_constraints(rdev, constraints); 5296aea6cb99SMichał Mirosław if (ret == -EPROBE_DEFER) { 5297aea6cb99SMichał Mirosław /* Regulator might be in bypass mode and so needs its supply 5298aea6cb99SMichał Mirosław * to set the constraints */ 5299aea6cb99SMichał Mirosław /* FIXME: this currently triggers a chicken-and-egg problem 5300aea6cb99SMichał Mirosław * when creating -SUPPLY symlink in sysfs to a regulator 5301aea6cb99SMichał Mirosław * that is just being created */ 5302aea6cb99SMichał Mirosław ret = regulator_resolve_supply(rdev); 5303aea6cb99SMichał Mirosław if (!ret) 5304aea6cb99SMichał Mirosław ret = set_machine_constraints(rdev, constraints); 5305aea6cb99SMichał Mirosław else 5306aea6cb99SMichał Mirosław rdev_dbg(rdev, "unable to resolve supply early: %pe\n", 5307aea6cb99SMichał Mirosław ERR_PTR(ret)); 5308aea6cb99SMichał Mirosław } 530945389c47SJon Hunter if (ret < 0) 531045389c47SJon Hunter goto wash; 531145389c47SJon Hunter 5312f9503385SDmitry Osipenko ret = regulator_init_coupling(rdev); 5313f9503385SDmitry Osipenko if (ret < 0) 5314d3d64537SMaciej Purski goto wash; 5315d3d64537SMaciej Purski 5316a5766f11SLiam Girdwood /* add consumers devices */ 53179a8f5e07SMark Brown if (init_data) { 5318a5766f11SLiam Girdwood for (i = 0; i < init_data->num_consumer_supplies; i++) { 5319a5766f11SLiam Girdwood ret = set_consumer_device_supply(rdev, 532040f9244fSMark Brown init_data->consumer_supplies[i].dev_name, 5321a5766f11SLiam Girdwood init_data->consumer_supplies[i].supply); 532223c2f041SMark Brown if (ret < 0) { 532323c2f041SMark Brown dev_err(dev, "Failed to set supply %s\n", 532423c2f041SMark Brown init_data->consumer_supplies[i].supply); 5325d4033b54SJani Nikula goto unset_supplies; 5326a5766f11SLiam Girdwood } 532723c2f041SMark Brown } 53289a8f5e07SMark Brown } 5329a5766f11SLiam Girdwood 5330fd086045SMatthias Kaehlcke if (!rdev->desc->ops->get_voltage && 5331fd086045SMatthias Kaehlcke !rdev->desc->ops->list_voltage && 5332fd086045SMatthias Kaehlcke !rdev->desc->fixed_uV) 5333fd086045SMatthias Kaehlcke rdev->is_switch = true; 5334fd086045SMatthias Kaehlcke 53359177514cSVladimir Zapolskiy ret = device_add(&rdev->dev); 53369177514cSVladimir Zapolskiy if (ret != 0) 5337c438b9d0SJon Hunter goto unset_supplies; 5338c438b9d0SJon Hunter 53391130e5b3SMark Brown rdev_init_debugfs(rdev); 53405e3ca2b3SJavier Martinez Canillas 5341f9503385SDmitry Osipenko /* try to resolve regulators coupling since a new one was registered */ 5342f9503385SDmitry Osipenko mutex_lock(®ulator_list_mutex); 5343f9503385SDmitry Osipenko regulator_resolve_coupling(rdev); 5344f9503385SDmitry Osipenko mutex_unlock(®ulator_list_mutex); 5345f9503385SDmitry Osipenko 53465e3ca2b3SJavier Martinez Canillas /* try to resolve regulators supply since a new one was registered */ 53475e3ca2b3SJavier Martinez Canillas class_for_each_device(®ulator_class, NULL, NULL, 53485e3ca2b3SJavier Martinez Canillas regulator_register_resolve_supply); 53491b3de223SKrzysztof Kozlowski kfree(config); 5350414c70cbSLiam Girdwood return rdev; 53514fca9545SDavid Brownell 5352d4033b54SJani Nikula unset_supplies: 535345389c47SJon Hunter mutex_lock(®ulator_list_mutex); 5354d4033b54SJani Nikula unset_regulator_supplies(rdev); 5355d8ca7d18SDmitry Osipenko regulator_remove_coupling(rdev); 535645389c47SJon Hunter mutex_unlock(®ulator_list_mutex); 535732165230SKrzysztof Adamski wash: 535826c2c997SDmitry Osipenko kfree(rdev->coupling_desc.coupled_rdevs); 535945389c47SJon Hunter mutex_lock(®ulator_list_mutex); 536032165230SKrzysztof Adamski regulator_ena_gpio_free(rdev); 536145389c47SJon Hunter mutex_unlock(®ulator_list_mutex); 53624fca9545SDavid Brownell clean: 53630edb040dSLinus Walleij if (dangling_of_gpiod) 53640edb040dSLinus Walleij gpiod_put(config->ena_gpiod); 5365a2151374SJon Hunter kfree(config); 5366d3c73156SMichał Mirosław put_device(&rdev->dev); 53670edb040dSLinus Walleij rinse: 53680edb040dSLinus Walleij if (dangling_cfg_gpiod) 53690edb040dSLinus Walleij gpiod_put(cfg->ena_gpiod); 5370a2151374SJon Hunter return ERR_PTR(ret); 5371414c70cbSLiam Girdwood } 5372414c70cbSLiam Girdwood EXPORT_SYMBOL_GPL(regulator_register); 5373414c70cbSLiam Girdwood 5374414c70cbSLiam Girdwood /** 5375414c70cbSLiam Girdwood * regulator_unregister - unregister regulator 537669279fb9SMark Brown * @rdev: regulator to unregister 5377414c70cbSLiam Girdwood * 5378414c70cbSLiam Girdwood * Called by regulator drivers to unregister a regulator. 5379414c70cbSLiam Girdwood */ 5380414c70cbSLiam Girdwood void regulator_unregister(struct regulator_dev *rdev) 5381414c70cbSLiam Girdwood { 5382414c70cbSLiam Girdwood if (rdev == NULL) 5383414c70cbSLiam Girdwood return; 5384414c70cbSLiam Girdwood 5385891636eaSMark Brown if (rdev->supply) { 5386891636eaSMark Brown while (rdev->use_count--) 5387891636eaSMark Brown regulator_disable(rdev->supply); 5388e032b376SMark Brown regulator_put(rdev->supply); 5389891636eaSMark Brown } 5390ff9b34b6SDmitry Osipenko 539106377301SCharles Keepax flush_work(&rdev->disable_work.work); 539206377301SCharles Keepax 5393414c70cbSLiam Girdwood mutex_lock(®ulator_list_mutex); 5394ff9b34b6SDmitry Osipenko 53951130e5b3SMark Brown debugfs_remove_recursive(rdev->debugfs); 53966bf87d17SMark Brown WARN_ON(rdev->open_count); 53976303f3e7SDmitry Osipenko regulator_remove_coupling(rdev); 53980f1d747bSMike Rapoport unset_regulator_supplies(rdev); 5399414c70cbSLiam Girdwood list_del(&rdev->list); 5400f19b00daSKim, Milo regulator_ena_gpio_free(rdev); 540158fb5cf5SLothar Waßmann device_unregister(&rdev->dev); 5402ff9b34b6SDmitry Osipenko 5403ff9b34b6SDmitry Osipenko mutex_unlock(®ulator_list_mutex); 5404414c70cbSLiam Girdwood } 5405414c70cbSLiam Girdwood EXPORT_SYMBOL_GPL(regulator_unregister); 5406414c70cbSLiam Girdwood 5407f7efad10SChunyan Zhang #ifdef CONFIG_SUSPEND 5408414c70cbSLiam Girdwood /** 54090380cf7dSpascal paillet * regulator_suspend - prepare regulators for system wide suspend 54101efef7ccSRandy Dunlap * @dev: ``&struct device`` pointer that is passed to _regulator_suspend() 5411414c70cbSLiam Girdwood * 5412414c70cbSLiam Girdwood * Configure each regulator with it's suspend operating parameters for state. 5413414c70cbSLiam Girdwood */ 54140380cf7dSpascal paillet static int regulator_suspend(struct device *dev) 5415414c70cbSLiam Girdwood { 5416cd7e36abSMarek Szyprowski struct regulator_dev *rdev = dev_to_rdev(dev); 5417f7efad10SChunyan Zhang suspend_state_t state = pm_suspend_target_state; 5418cd7e36abSMarek Szyprowski int ret; 54190955f5beSStephen Boyd const struct regulator_state *rstate; 54200955f5beSStephen Boyd 54210955f5beSStephen Boyd rstate = regulator_get_suspend_state_check(rdev, state); 54220955f5beSStephen Boyd if (!rstate) 54230955f5beSStephen Boyd return 0; 5424414c70cbSLiam Girdwood 5425cd7e36abSMarek Szyprowski regulator_lock(rdev); 54260955f5beSStephen Boyd ret = __suspend_set_state(rdev, rstate); 5427cd7e36abSMarek Szyprowski regulator_unlock(rdev); 5428cd7e36abSMarek Szyprowski 5429cd7e36abSMarek Szyprowski return ret; 5430414c70cbSLiam Girdwood } 5431d3e4eccbSMark Brown 5432cd7e36abSMarek Szyprowski static int regulator_resume(struct device *dev) 543385f3b431STomeu Vizoso { 5434cd7e36abSMarek Szyprowski suspend_state_t state = pm_suspend_target_state; 543585f3b431STomeu Vizoso struct regulator_dev *rdev = dev_to_rdev(dev); 5436f7efad10SChunyan Zhang struct regulator_state *rstate; 5437cd7e36abSMarek Szyprowski int ret = 0; 5438f7efad10SChunyan Zhang 5439cd7e36abSMarek Szyprowski rstate = regulator_get_suspend_state(rdev, state); 5440f7efad10SChunyan Zhang if (rstate == NULL) 544135b5f14eSGeert Uytterhoeven return 0; 544285f3b431STomeu Vizoso 54430955f5beSStephen Boyd /* Avoid grabbing the lock if we don't need to */ 54440955f5beSStephen Boyd if (!rdev->desc->ops->resume) 54450955f5beSStephen Boyd return 0; 54460955f5beSStephen Boyd 544766cf9a7eSMaciej Purski regulator_lock(rdev); 544885f3b431STomeu Vizoso 54490955f5beSStephen Boyd if (rstate->enabled == ENABLE_IN_SUSPEND || 54500955f5beSStephen Boyd rstate->enabled == DISABLE_IN_SUSPEND) 54510380cf7dSpascal paillet ret = rdev->desc->ops->resume(rdev); 5452f7efad10SChunyan Zhang 545366cf9a7eSMaciej Purski regulator_unlock(rdev); 545485f3b431STomeu Vizoso 5455f7efad10SChunyan Zhang return ret; 545685f3b431STomeu Vizoso } 5457f7efad10SChunyan Zhang #else /* !CONFIG_SUSPEND */ 5458f7efad10SChunyan Zhang 54590380cf7dSpascal paillet #define regulator_suspend NULL 54600380cf7dSpascal paillet #define regulator_resume NULL 5461f7efad10SChunyan Zhang 5462f7efad10SChunyan Zhang #endif /* !CONFIG_SUSPEND */ 5463f7efad10SChunyan Zhang 5464f7efad10SChunyan Zhang #ifdef CONFIG_PM 5465f7efad10SChunyan Zhang static const struct dev_pm_ops __maybe_unused regulator_pm_ops = { 54660380cf7dSpascal paillet .suspend = regulator_suspend, 54670380cf7dSpascal paillet .resume = regulator_resume, 5468f7efad10SChunyan Zhang }; 5469f7efad10SChunyan Zhang #endif 5470f7efad10SChunyan Zhang 5471285c22deSMark Brown struct class regulator_class = { 5472f7efad10SChunyan Zhang .name = "regulator", 5473f7efad10SChunyan Zhang .dev_release = regulator_dev_release, 5474f7efad10SChunyan Zhang .dev_groups = regulator_dev_groups, 5475f7efad10SChunyan Zhang #ifdef CONFIG_PM 5476f7efad10SChunyan Zhang .pm = ®ulator_pm_ops, 5477f7efad10SChunyan Zhang #endif 5478f7efad10SChunyan Zhang }; 54797a32b589SMyungJoo Ham /** 5480ca725561SMark Brown * regulator_has_full_constraints - the system has fully specified constraints 5481ca725561SMark Brown * 5482ca725561SMark Brown * Calling this function will cause the regulator API to disable all 5483ca725561SMark Brown * regulators which have a zero use count and don't have an always_on 5484ca725561SMark Brown * constraint in a late_initcall. 5485ca725561SMark Brown * 5486ca725561SMark Brown * The intention is that this will become the default behaviour in a 5487ca725561SMark Brown * future kernel release so users are encouraged to use this facility 5488ca725561SMark Brown * now. 5489ca725561SMark Brown */ 5490ca725561SMark Brown void regulator_has_full_constraints(void) 5491ca725561SMark Brown { 5492ca725561SMark Brown has_full_constraints = 1; 5493ca725561SMark Brown } 5494ca725561SMark Brown EXPORT_SYMBOL_GPL(regulator_has_full_constraints); 5495ca725561SMark Brown 5496ca725561SMark Brown /** 5497414c70cbSLiam Girdwood * rdev_get_drvdata - get rdev regulator driver data 549869279fb9SMark Brown * @rdev: regulator 5499414c70cbSLiam Girdwood * 5500414c70cbSLiam Girdwood * Get rdev regulator driver private data. This call can be used in the 5501414c70cbSLiam Girdwood * regulator driver context. 5502414c70cbSLiam Girdwood */ 5503414c70cbSLiam Girdwood void *rdev_get_drvdata(struct regulator_dev *rdev) 5504414c70cbSLiam Girdwood { 5505414c70cbSLiam Girdwood return rdev->reg_data; 5506414c70cbSLiam Girdwood } 5507414c70cbSLiam Girdwood EXPORT_SYMBOL_GPL(rdev_get_drvdata); 5508414c70cbSLiam Girdwood 5509414c70cbSLiam Girdwood /** 5510414c70cbSLiam Girdwood * regulator_get_drvdata - get regulator driver data 5511414c70cbSLiam Girdwood * @regulator: regulator 5512414c70cbSLiam Girdwood * 5513414c70cbSLiam Girdwood * Get regulator driver private data. This call can be used in the consumer 5514414c70cbSLiam Girdwood * driver context when non API regulator specific functions need to be called. 5515414c70cbSLiam Girdwood */ 5516414c70cbSLiam Girdwood void *regulator_get_drvdata(struct regulator *regulator) 5517414c70cbSLiam Girdwood { 5518414c70cbSLiam Girdwood return regulator->rdev->reg_data; 5519414c70cbSLiam Girdwood } 5520414c70cbSLiam Girdwood EXPORT_SYMBOL_GPL(regulator_get_drvdata); 5521414c70cbSLiam Girdwood 5522414c70cbSLiam Girdwood /** 5523414c70cbSLiam Girdwood * regulator_set_drvdata - set regulator driver data 5524414c70cbSLiam Girdwood * @regulator: regulator 5525414c70cbSLiam Girdwood * @data: data 5526414c70cbSLiam Girdwood */ 5527414c70cbSLiam Girdwood void regulator_set_drvdata(struct regulator *regulator, void *data) 5528414c70cbSLiam Girdwood { 5529414c70cbSLiam Girdwood regulator->rdev->reg_data = data; 5530414c70cbSLiam Girdwood } 5531414c70cbSLiam Girdwood EXPORT_SYMBOL_GPL(regulator_set_drvdata); 5532414c70cbSLiam Girdwood 5533414c70cbSLiam Girdwood /** 5534414c70cbSLiam Girdwood * regulator_get_id - get regulator ID 553569279fb9SMark Brown * @rdev: regulator 5536414c70cbSLiam Girdwood */ 5537414c70cbSLiam Girdwood int rdev_get_id(struct regulator_dev *rdev) 5538414c70cbSLiam Girdwood { 5539414c70cbSLiam Girdwood return rdev->desc->id; 5540414c70cbSLiam Girdwood } 5541414c70cbSLiam Girdwood EXPORT_SYMBOL_GPL(rdev_get_id); 5542414c70cbSLiam Girdwood 5543a5766f11SLiam Girdwood struct device *rdev_get_dev(struct regulator_dev *rdev) 5544a5766f11SLiam Girdwood { 5545a5766f11SLiam Girdwood return &rdev->dev; 5546a5766f11SLiam Girdwood } 5547a5766f11SLiam Girdwood EXPORT_SYMBOL_GPL(rdev_get_dev); 5548a5766f11SLiam Girdwood 554903c87b95SBartosz Golaszewski struct regmap *rdev_get_regmap(struct regulator_dev *rdev) 555003c87b95SBartosz Golaszewski { 555103c87b95SBartosz Golaszewski return rdev->regmap; 555203c87b95SBartosz Golaszewski } 555303c87b95SBartosz Golaszewski EXPORT_SYMBOL_GPL(rdev_get_regmap); 555403c87b95SBartosz Golaszewski 5555a5766f11SLiam Girdwood void *regulator_get_init_drvdata(struct regulator_init_data *reg_init_data) 5556a5766f11SLiam Girdwood { 5557a5766f11SLiam Girdwood return reg_init_data->driver_data; 5558a5766f11SLiam Girdwood } 5559a5766f11SLiam Girdwood EXPORT_SYMBOL_GPL(regulator_get_init_drvdata); 5560a5766f11SLiam Girdwood 5561ba55a974SMark Brown #ifdef CONFIG_DEBUG_FS 5562dbc55955SHaishan Zhou static int supply_map_show(struct seq_file *sf, void *data) 5563ba55a974SMark Brown { 5564ba55a974SMark Brown struct regulator_map *map; 5565ba55a974SMark Brown 5566ba55a974SMark Brown list_for_each_entry(map, ®ulator_map_list, list) { 5567dbc55955SHaishan Zhou seq_printf(sf, "%s -> %s.%s\n", 5568ba55a974SMark Brown rdev_get_name(map->regulator), map->dev_name, 5569ba55a974SMark Brown map->supply); 5570ba55a974SMark Brown } 5571ba55a974SMark Brown 5572dbc55955SHaishan Zhou return 0; 5573dbc55955SHaishan Zhou } 55743e60b4fcSYangtao Li DEFINE_SHOW_ATTRIBUTE(supply_map); 5575ba55a974SMark Brown 557685f3b431STomeu Vizoso struct summary_data { 557785f3b431STomeu Vizoso struct seq_file *s; 557885f3b431STomeu Vizoso struct regulator_dev *parent; 557985f3b431STomeu Vizoso int level; 558085f3b431STomeu Vizoso }; 558185f3b431STomeu Vizoso 558285f3b431STomeu Vizoso static void regulator_summary_show_subtree(struct seq_file *s, 558385f3b431STomeu Vizoso struct regulator_dev *rdev, 558485f3b431STomeu Vizoso int level); 558585f3b431STomeu Vizoso 558685f3b431STomeu Vizoso static int regulator_summary_show_children(struct device *dev, void *data) 558785f3b431STomeu Vizoso { 558885f3b431STomeu Vizoso struct regulator_dev *rdev = dev_to_rdev(dev); 558985f3b431STomeu Vizoso struct summary_data *summary_data = data; 559085f3b431STomeu Vizoso 559185f3b431STomeu Vizoso if (rdev->supply && rdev->supply->rdev == summary_data->parent) 559285f3b431STomeu Vizoso regulator_summary_show_subtree(summary_data->s, rdev, 559385f3b431STomeu Vizoso summary_data->level + 1); 559485f3b431STomeu Vizoso 559585f3b431STomeu Vizoso return 0; 559685f3b431STomeu Vizoso } 559785f3b431STomeu Vizoso 55987c225ec9SHeiko Stübner static void regulator_summary_show_subtree(struct seq_file *s, 55997c225ec9SHeiko Stübner struct regulator_dev *rdev, 56007c225ec9SHeiko Stübner int level) 56017c225ec9SHeiko Stübner { 56027c225ec9SHeiko Stübner struct regulation_constraints *c; 56037c225ec9SHeiko Stübner struct regulator *consumer; 560485f3b431STomeu Vizoso struct summary_data summary_data; 56057e4d9683SDouglas Anderson unsigned int opmode; 56067c225ec9SHeiko Stübner 56077c225ec9SHeiko Stübner if (!rdev) 56087c225ec9SHeiko Stübner return; 56097c225ec9SHeiko Stübner 56107e4d9683SDouglas Anderson opmode = _regulator_get_mode_unlocked(rdev); 561101de19d0SDouglas Anderson seq_printf(s, "%*s%-*s %3d %4d %6d %7s ", 56127c225ec9SHeiko Stübner level * 3 + 1, "", 56137c225ec9SHeiko Stübner 30 - level * 3, rdev_get_name(rdev), 561401de19d0SDouglas Anderson rdev->use_count, rdev->open_count, rdev->bypass_count, 56157e4d9683SDouglas Anderson regulator_opmode_to_str(opmode)); 56167c225ec9SHeiko Stübner 5617d22b85a1SDmitry Osipenko seq_printf(s, "%5dmV ", regulator_get_voltage_rdev(rdev) / 1000); 56187e4d9683SDouglas Anderson seq_printf(s, "%5dmA ", 56197e4d9683SDouglas Anderson _regulator_get_current_limit_unlocked(rdev) / 1000); 56207c225ec9SHeiko Stübner 56217c225ec9SHeiko Stübner c = rdev->constraints; 56227c225ec9SHeiko Stübner if (c) { 56237c225ec9SHeiko Stübner switch (rdev->desc->type) { 56247c225ec9SHeiko Stübner case REGULATOR_VOLTAGE: 56257c225ec9SHeiko Stübner seq_printf(s, "%5dmV %5dmV ", 56267c225ec9SHeiko Stübner c->min_uV / 1000, c->max_uV / 1000); 56277c225ec9SHeiko Stübner break; 56287c225ec9SHeiko Stübner case REGULATOR_CURRENT: 56297c225ec9SHeiko Stübner seq_printf(s, "%5dmA %5dmA ", 56307c225ec9SHeiko Stübner c->min_uA / 1000, c->max_uA / 1000); 56317c225ec9SHeiko Stübner break; 56327c225ec9SHeiko Stübner } 56337c225ec9SHeiko Stübner } 56347c225ec9SHeiko Stübner 56357c225ec9SHeiko Stübner seq_puts(s, "\n"); 56367c225ec9SHeiko Stübner 56377c225ec9SHeiko Stübner list_for_each_entry(consumer, &rdev->consumer_list, list) { 5638e42a46b6SLeonard Crestez if (consumer->dev && consumer->dev->class == ®ulator_class) 56397c225ec9SHeiko Stübner continue; 56407c225ec9SHeiko Stübner 56417c225ec9SHeiko Stübner seq_printf(s, "%*s%-*s ", 56427c225ec9SHeiko Stübner (level + 1) * 3 + 1, "", 5643e42a46b6SLeonard Crestez 30 - (level + 1) * 3, 56446b576eb0SMichał Mirosław consumer->supply_name ? consumer->supply_name : 5645e42a46b6SLeonard Crestez consumer->dev ? dev_name(consumer->dev) : "deviceless"); 56467c225ec9SHeiko Stübner 56477c225ec9SHeiko Stübner switch (rdev->desc->type) { 56487c225ec9SHeiko Stübner case REGULATOR_VOLTAGE: 56495451781dSDouglas Anderson seq_printf(s, "%3d %33dmA%c%5dmV %5dmV", 56505451781dSDouglas Anderson consumer->enable_count, 56517d3827b5SDouglas Anderson consumer->uA_load / 1000, 56525451781dSDouglas Anderson consumer->uA_load && !consumer->enable_count ? 56535451781dSDouglas Anderson '*' : ' ', 5654c360a6dfSChunyan Zhang consumer->voltage[PM_SUSPEND_ON].min_uV / 1000, 5655c360a6dfSChunyan Zhang consumer->voltage[PM_SUSPEND_ON].max_uV / 1000); 56567c225ec9SHeiko Stübner break; 56577c225ec9SHeiko Stübner case REGULATOR_CURRENT: 56587c225ec9SHeiko Stübner break; 56597c225ec9SHeiko Stübner } 56607c225ec9SHeiko Stübner 56617c225ec9SHeiko Stübner seq_puts(s, "\n"); 56627c225ec9SHeiko Stübner } 56637c225ec9SHeiko Stübner 566485f3b431STomeu Vizoso summary_data.s = s; 566585f3b431STomeu Vizoso summary_data.level = level; 566685f3b431STomeu Vizoso summary_data.parent = rdev; 56677c225ec9SHeiko Stübner 566885f3b431STomeu Vizoso class_for_each_device(®ulator_class, NULL, &summary_data, 566985f3b431STomeu Vizoso regulator_summary_show_children); 5670f8702f9eSDmitry Osipenko } 5671f8702f9eSDmitry Osipenko 5672f8702f9eSDmitry Osipenko struct summary_lock_data { 5673f8702f9eSDmitry Osipenko struct ww_acquire_ctx *ww_ctx; 5674f8702f9eSDmitry Osipenko struct regulator_dev **new_contended_rdev; 5675f8702f9eSDmitry Osipenko struct regulator_dev **old_contended_rdev; 5676f8702f9eSDmitry Osipenko }; 5677f8702f9eSDmitry Osipenko 5678f8702f9eSDmitry Osipenko static int regulator_summary_lock_one(struct device *dev, void *data) 5679f8702f9eSDmitry Osipenko { 5680f8702f9eSDmitry Osipenko struct regulator_dev *rdev = dev_to_rdev(dev); 5681f8702f9eSDmitry Osipenko struct summary_lock_data *lock_data = data; 5682f8702f9eSDmitry Osipenko int ret = 0; 5683f8702f9eSDmitry Osipenko 5684f8702f9eSDmitry Osipenko if (rdev != *lock_data->old_contended_rdev) { 5685f8702f9eSDmitry Osipenko ret = regulator_lock_nested(rdev, lock_data->ww_ctx); 5686f8702f9eSDmitry Osipenko 5687f8702f9eSDmitry Osipenko if (ret == -EDEADLK) 5688f8702f9eSDmitry Osipenko *lock_data->new_contended_rdev = rdev; 5689f8702f9eSDmitry Osipenko else 5690f8702f9eSDmitry Osipenko WARN_ON_ONCE(ret); 5691f8702f9eSDmitry Osipenko } else { 5692f8702f9eSDmitry Osipenko *lock_data->old_contended_rdev = NULL; 5693f8702f9eSDmitry Osipenko } 5694f8702f9eSDmitry Osipenko 5695f8702f9eSDmitry Osipenko return ret; 5696f8702f9eSDmitry Osipenko } 5697f8702f9eSDmitry Osipenko 5698f8702f9eSDmitry Osipenko static int regulator_summary_unlock_one(struct device *dev, void *data) 5699f8702f9eSDmitry Osipenko { 5700f8702f9eSDmitry Osipenko struct regulator_dev *rdev = dev_to_rdev(dev); 5701f8702f9eSDmitry Osipenko struct summary_lock_data *lock_data = data; 5702f8702f9eSDmitry Osipenko 5703f8702f9eSDmitry Osipenko if (lock_data) { 5704f8702f9eSDmitry Osipenko if (rdev == *lock_data->new_contended_rdev) 5705f8702f9eSDmitry Osipenko return -EDEADLK; 5706f8702f9eSDmitry Osipenko } 57077e4d9683SDouglas Anderson 57087e4d9683SDouglas Anderson regulator_unlock(rdev); 5709f8702f9eSDmitry Osipenko 5710f8702f9eSDmitry Osipenko return 0; 5711f8702f9eSDmitry Osipenko } 5712f8702f9eSDmitry Osipenko 5713f8702f9eSDmitry Osipenko static int regulator_summary_lock_all(struct ww_acquire_ctx *ww_ctx, 5714f8702f9eSDmitry Osipenko struct regulator_dev **new_contended_rdev, 5715f8702f9eSDmitry Osipenko struct regulator_dev **old_contended_rdev) 5716f8702f9eSDmitry Osipenko { 5717f8702f9eSDmitry Osipenko struct summary_lock_data lock_data; 5718f8702f9eSDmitry Osipenko int ret; 5719f8702f9eSDmitry Osipenko 5720f8702f9eSDmitry Osipenko lock_data.ww_ctx = ww_ctx; 5721f8702f9eSDmitry Osipenko lock_data.new_contended_rdev = new_contended_rdev; 5722f8702f9eSDmitry Osipenko lock_data.old_contended_rdev = old_contended_rdev; 5723f8702f9eSDmitry Osipenko 5724f8702f9eSDmitry Osipenko ret = class_for_each_device(®ulator_class, NULL, &lock_data, 5725f8702f9eSDmitry Osipenko regulator_summary_lock_one); 5726f8702f9eSDmitry Osipenko if (ret) 5727f8702f9eSDmitry Osipenko class_for_each_device(®ulator_class, NULL, &lock_data, 5728f8702f9eSDmitry Osipenko regulator_summary_unlock_one); 5729f8702f9eSDmitry Osipenko 5730f8702f9eSDmitry Osipenko return ret; 5731f8702f9eSDmitry Osipenko } 5732f8702f9eSDmitry Osipenko 5733f8702f9eSDmitry Osipenko static void regulator_summary_lock(struct ww_acquire_ctx *ww_ctx) 5734f8702f9eSDmitry Osipenko { 5735f8702f9eSDmitry Osipenko struct regulator_dev *new_contended_rdev = NULL; 5736f8702f9eSDmitry Osipenko struct regulator_dev *old_contended_rdev = NULL; 5737f8702f9eSDmitry Osipenko int err; 5738f8702f9eSDmitry Osipenko 5739ff9b34b6SDmitry Osipenko mutex_lock(®ulator_list_mutex); 5740ff9b34b6SDmitry Osipenko 5741f8702f9eSDmitry Osipenko ww_acquire_init(ww_ctx, ®ulator_ww_class); 5742f8702f9eSDmitry Osipenko 5743f8702f9eSDmitry Osipenko do { 5744f8702f9eSDmitry Osipenko if (new_contended_rdev) { 5745f8702f9eSDmitry Osipenko ww_mutex_lock_slow(&new_contended_rdev->mutex, ww_ctx); 5746f8702f9eSDmitry Osipenko old_contended_rdev = new_contended_rdev; 5747f8702f9eSDmitry Osipenko old_contended_rdev->ref_cnt++; 5748f8702f9eSDmitry Osipenko } 5749f8702f9eSDmitry Osipenko 5750f8702f9eSDmitry Osipenko err = regulator_summary_lock_all(ww_ctx, 5751f8702f9eSDmitry Osipenko &new_contended_rdev, 5752f8702f9eSDmitry Osipenko &old_contended_rdev); 5753f8702f9eSDmitry Osipenko 5754f8702f9eSDmitry Osipenko if (old_contended_rdev) 5755f8702f9eSDmitry Osipenko regulator_unlock(old_contended_rdev); 5756f8702f9eSDmitry Osipenko 5757f8702f9eSDmitry Osipenko } while (err == -EDEADLK); 5758f8702f9eSDmitry Osipenko 5759f8702f9eSDmitry Osipenko ww_acquire_done(ww_ctx); 5760f8702f9eSDmitry Osipenko } 5761f8702f9eSDmitry Osipenko 5762f8702f9eSDmitry Osipenko static void regulator_summary_unlock(struct ww_acquire_ctx *ww_ctx) 5763f8702f9eSDmitry Osipenko { 5764f8702f9eSDmitry Osipenko class_for_each_device(®ulator_class, NULL, NULL, 5765f8702f9eSDmitry Osipenko regulator_summary_unlock_one); 5766f8702f9eSDmitry Osipenko ww_acquire_fini(ww_ctx); 5767ff9b34b6SDmitry Osipenko 5768ff9b34b6SDmitry Osipenko mutex_unlock(®ulator_list_mutex); 57697c225ec9SHeiko Stübner } 577085f3b431STomeu Vizoso 577185f3b431STomeu Vizoso static int regulator_summary_show_roots(struct device *dev, void *data) 577285f3b431STomeu Vizoso { 577385f3b431STomeu Vizoso struct regulator_dev *rdev = dev_to_rdev(dev); 577485f3b431STomeu Vizoso struct seq_file *s = data; 577585f3b431STomeu Vizoso 577685f3b431STomeu Vizoso if (!rdev->supply) 577785f3b431STomeu Vizoso regulator_summary_show_subtree(s, rdev, 0); 577885f3b431STomeu Vizoso 577985f3b431STomeu Vizoso return 0; 57807c225ec9SHeiko Stübner } 57817c225ec9SHeiko Stübner 57827c225ec9SHeiko Stübner static int regulator_summary_show(struct seq_file *s, void *data) 57837c225ec9SHeiko Stübner { 5784f8702f9eSDmitry Osipenko struct ww_acquire_ctx ww_ctx; 5785f8702f9eSDmitry Osipenko 578601de19d0SDouglas Anderson seq_puts(s, " regulator use open bypass opmode voltage current min max\n"); 578701de19d0SDouglas Anderson seq_puts(s, "---------------------------------------------------------------------------------------\n"); 57887c225ec9SHeiko Stübner 5789f8702f9eSDmitry Osipenko regulator_summary_lock(&ww_ctx); 5790f8702f9eSDmitry Osipenko 579185f3b431STomeu Vizoso class_for_each_device(®ulator_class, NULL, s, 579285f3b431STomeu Vizoso regulator_summary_show_roots); 57937c225ec9SHeiko Stübner 5794f8702f9eSDmitry Osipenko regulator_summary_unlock(&ww_ctx); 5795f8702f9eSDmitry Osipenko 57967c225ec9SHeiko Stübner return 0; 57977c225ec9SHeiko Stübner } 57983e60b4fcSYangtao Li DEFINE_SHOW_ATTRIBUTE(regulator_summary); 57993e60b4fcSYangtao Li #endif /* CONFIG_DEBUG_FS */ 58007c225ec9SHeiko Stübner 5801414c70cbSLiam Girdwood static int __init regulator_init(void) 5802414c70cbSLiam Girdwood { 580334abbd68SMark Brown int ret; 580434abbd68SMark Brown 580534abbd68SMark Brown ret = class_register(®ulator_class); 580634abbd68SMark Brown 58071130e5b3SMark Brown debugfs_root = debugfs_create_dir("regulator", NULL); 580824751434SStephen Boyd if (!debugfs_root) 58091130e5b3SMark Brown pr_warn("regulator: Failed to create debugfs directory\n"); 5810ba55a974SMark Brown 58113e60b4fcSYangtao Li #ifdef CONFIG_DEBUG_FS 5812f4d562c6SMark Brown debugfs_create_file("supply_map", 0444, debugfs_root, NULL, 5813f4d562c6SMark Brown &supply_map_fops); 58141130e5b3SMark Brown 58157c225ec9SHeiko Stübner debugfs_create_file("regulator_summary", 0444, debugfs_root, 581685f3b431STomeu Vizoso NULL, ®ulator_summary_fops); 58173e60b4fcSYangtao Li #endif 581834abbd68SMark Brown regulator_dummy_init(); 581934abbd68SMark Brown 5820d8ca7d18SDmitry Osipenko regulator_coupler_register(&generic_regulator_coupler); 5821d8ca7d18SDmitry Osipenko 582234abbd68SMark Brown return ret; 5823414c70cbSLiam Girdwood } 5824414c70cbSLiam Girdwood 5825414c70cbSLiam Girdwood /* init early to allow our consumers to complete system booting */ 5826414c70cbSLiam Girdwood core_initcall(regulator_init); 5827ca725561SMark Brown 582855576cf1SMark Brown static int regulator_late_cleanup(struct device *dev, void *data) 5829ca725561SMark Brown { 5830609ca5f3SMark Brown struct regulator_dev *rdev = dev_to_rdev(dev); 5831609ca5f3SMark Brown const struct regulator_ops *ops = rdev->desc->ops; 5832609ca5f3SMark Brown struct regulation_constraints *c = rdev->constraints; 5833ca725561SMark Brown int enabled, ret; 5834ca725561SMark Brown 583566fda75fSMarkus Pargmann if (c && c->always_on) 5836609ca5f3SMark Brown return 0; 5837ca725561SMark Brown 58388a34e979SWEN Pingbo if (!regulator_ops_is_valid(rdev, REGULATOR_CHANGE_STATUS)) 5839609ca5f3SMark Brown return 0; 5840e9535834SMark Brown 584166cf9a7eSMaciej Purski regulator_lock(rdev); 5842ca725561SMark Brown 5843ca725561SMark Brown if (rdev->use_count) 5844ca725561SMark Brown goto unlock; 5845ca725561SMark Brown 5846c088a498SPi-Hsun Shih /* If we can't read the status assume it's always on. */ 5847ca725561SMark Brown if (ops->is_enabled) 5848ca725561SMark Brown enabled = ops->is_enabled(rdev); 5849ca725561SMark Brown else 5850ca725561SMark Brown enabled = 1; 5851ca725561SMark Brown 5852c088a498SPi-Hsun Shih /* But if reading the status failed, assume that it's off. */ 5853c088a498SPi-Hsun Shih if (enabled <= 0) 5854ca725561SMark Brown goto unlock; 5855ca725561SMark Brown 585687b28417SMark Brown if (have_full_constraints()) { 5857609ca5f3SMark Brown /* We log since this may kill the system if it goes 5858609ca5f3SMark Brown * wrong. */ 58595da84fd9SJoe Perches rdev_info(rdev, "disabling\n"); 586066fda75fSMarkus Pargmann ret = _regulator_do_disable(rdev); 58610d25d09dSJingoo Han if (ret != 0) 586261aab5adSMichał Mirosław rdev_err(rdev, "couldn't disable: %pe\n", ERR_PTR(ret)); 5863ca725561SMark Brown } else { 5864ca725561SMark Brown /* The intention is that in future we will 5865ca725561SMark Brown * assume that full constraints are provided 5866ca725561SMark Brown * so warn even if we aren't going to do 5867ca725561SMark Brown * anything here. 5868ca725561SMark Brown */ 58695da84fd9SJoe Perches rdev_warn(rdev, "incomplete constraints, leaving on\n"); 5870ca725561SMark Brown } 5871ca725561SMark Brown 5872ca725561SMark Brown unlock: 587366cf9a7eSMaciej Purski regulator_unlock(rdev); 5874609ca5f3SMark Brown 5875609ca5f3SMark Brown return 0; 5876ca725561SMark Brown } 5877ca725561SMark Brown 587855576cf1SMark Brown static void regulator_init_complete_work_function(struct work_struct *work) 5879609ca5f3SMark Brown { 5880609ca5f3SMark Brown /* 58813827b64dSJavier Martinez Canillas * Regulators may had failed to resolve their input supplies 58823827b64dSJavier Martinez Canillas * when were registered, either because the input supply was 58833827b64dSJavier Martinez Canillas * not registered yet or because its parent device was not 58843827b64dSJavier Martinez Canillas * bound yet. So attempt to resolve the input supplies for 58853827b64dSJavier Martinez Canillas * pending regulators before trying to disable unused ones. 58863827b64dSJavier Martinez Canillas */ 58873827b64dSJavier Martinez Canillas class_for_each_device(®ulator_class, NULL, NULL, 58883827b64dSJavier Martinez Canillas regulator_register_resolve_supply); 58893827b64dSJavier Martinez Canillas 5890609ca5f3SMark Brown /* If we have a full configuration then disable any regulators 5891609ca5f3SMark Brown * we have permission to change the status for and which are 5892609ca5f3SMark Brown * not in use or always_on. This is effectively the default 5893609ca5f3SMark Brown * for DT and ACPI as they have full constraints. 5894609ca5f3SMark Brown */ 5895609ca5f3SMark Brown class_for_each_device(®ulator_class, NULL, NULL, 5896609ca5f3SMark Brown regulator_late_cleanup); 589755576cf1SMark Brown } 589855576cf1SMark Brown 589955576cf1SMark Brown static DECLARE_DELAYED_WORK(regulator_init_complete_work, 590055576cf1SMark Brown regulator_init_complete_work_function); 590155576cf1SMark Brown 590255576cf1SMark Brown static int __init regulator_init_complete(void) 590355576cf1SMark Brown { 590455576cf1SMark Brown /* 590555576cf1SMark Brown * Since DT doesn't provide an idiomatic mechanism for 590655576cf1SMark Brown * enabling full constraints and since it's much more natural 590755576cf1SMark Brown * with DT to provide them just assume that a DT enabled 590855576cf1SMark Brown * system has full constraints. 590955576cf1SMark Brown */ 591055576cf1SMark Brown if (of_have_populated_dt()) 591155576cf1SMark Brown has_full_constraints = true; 591255576cf1SMark Brown 591355576cf1SMark Brown /* 59142a15483bSJohn Stultz * We punt completion for an arbitrary amount of time since 59152a15483bSJohn Stultz * systems like distros will load many drivers from userspace 59162a15483bSJohn Stultz * so consumers might not always be ready yet, this is 59172a15483bSJohn Stultz * particularly an issue with laptops where this might bounce 59182a15483bSJohn Stultz * the display off then on. Ideally we'd get a notification 59192a15483bSJohn Stultz * from userspace when this happens but we don't so just wait 59202a15483bSJohn Stultz * a bit and hope we waited long enough. It'd be better if 59212a15483bSJohn Stultz * we'd only do this on systems that need it, and a kernel 59222a15483bSJohn Stultz * command line option might be useful. 592355576cf1SMark Brown */ 59242a15483bSJohn Stultz schedule_delayed_work(®ulator_init_complete_work, 59252a15483bSJohn Stultz msecs_to_jiffies(30000)); 5926ca725561SMark Brown 5927ca725561SMark Brown return 0; 5928ca725561SMark Brown } 5929fd482a3eSSaravana Kannan late_initcall_sync(regulator_init_complete); 5930