12874c5fdSThomas Gleixner // SPDX-License-Identifier: GPL-2.0-or-later 2414c70cbSLiam Girdwood /* 3414c70cbSLiam Girdwood * core.c -- Voltage/Current Regulator framework. 4414c70cbSLiam Girdwood * 5414c70cbSLiam Girdwood * Copyright 2007, 2008 Wolfson Microelectronics PLC. 6a5766f11SLiam Girdwood * Copyright 2008 SlimLogic Ltd. 7414c70cbSLiam Girdwood * 8a5766f11SLiam Girdwood * Author: Liam Girdwood <lrg@slimlogic.co.uk> 9414c70cbSLiam Girdwood */ 10414c70cbSLiam Girdwood 11414c70cbSLiam Girdwood #include <linux/kernel.h> 12414c70cbSLiam Girdwood #include <linux/init.h> 131130e5b3SMark Brown #include <linux/debugfs.h> 14414c70cbSLiam Girdwood #include <linux/device.h> 155a0e3ad6STejun Heo #include <linux/slab.h> 16f21e0e81SMark Brown #include <linux/async.h> 17414c70cbSLiam Girdwood #include <linux/err.h> 18414c70cbSLiam Girdwood #include <linux/mutex.h> 19414c70cbSLiam Girdwood #include <linux/suspend.h> 2031aae2beSMark Brown #include <linux/delay.h> 21778b28b4SRussell King #include <linux/gpio/consumer.h> 2269511a45SRajendra Nayak #include <linux/of.h> 2365b19ce6SMark Brown #include <linux/regmap.h> 2469511a45SRajendra Nayak #include <linux/regulator/of_regulator.h> 25414c70cbSLiam Girdwood #include <linux/regulator/consumer.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); 5321cf891aSMark Brown static bool has_full_constraints; 54414c70cbSLiam Girdwood 551130e5b3SMark Brown static struct dentry *debugfs_root; 561130e5b3SMark Brown 578dc5390dSMark Brown /* 58414c70cbSLiam Girdwood * struct regulator_map 59414c70cbSLiam Girdwood * 60414c70cbSLiam Girdwood * Used to provide symbolic supply names to devices. 61414c70cbSLiam Girdwood */ 62414c70cbSLiam Girdwood struct regulator_map { 63414c70cbSLiam Girdwood struct list_head list; 6440f9244fSMark Brown const char *dev_name; /* The dev_name() for the consumer */ 65414c70cbSLiam Girdwood const char *supply; 66a5766f11SLiam Girdwood struct regulator_dev *regulator; 67414c70cbSLiam Girdwood }; 68414c70cbSLiam Girdwood 69414c70cbSLiam Girdwood /* 70f19b00daSKim, Milo * struct regulator_enable_gpio 71f19b00daSKim, Milo * 72f19b00daSKim, Milo * Management for shared enable GPIO pin 73f19b00daSKim, Milo */ 74f19b00daSKim, Milo struct regulator_enable_gpio { 75f19b00daSKim, Milo struct list_head list; 76778b28b4SRussell King struct gpio_desc *gpiod; 77f19b00daSKim, Milo u32 enable_count; /* a number of enabled shared GPIO */ 78f19b00daSKim, Milo u32 request_count; /* a number of requested shared GPIO */ 79f19b00daSKim, Milo }; 80f19b00daSKim, Milo 81a06ccd9cSCharles Keepax /* 82a06ccd9cSCharles Keepax * struct regulator_supply_alias 83a06ccd9cSCharles Keepax * 84a06ccd9cSCharles Keepax * Used to map lookups for a supply onto an alternative device. 85a06ccd9cSCharles Keepax */ 86a06ccd9cSCharles Keepax struct regulator_supply_alias { 87a06ccd9cSCharles Keepax struct list_head list; 88a06ccd9cSCharles Keepax struct device *src_dev; 89a06ccd9cSCharles Keepax const char *src_supply; 90a06ccd9cSCharles Keepax struct device *alias_dev; 91a06ccd9cSCharles Keepax const char *alias_supply; 92a06ccd9cSCharles Keepax }; 93a06ccd9cSCharles Keepax 94414c70cbSLiam Girdwood static int _regulator_is_enabled(struct regulator_dev *rdev); 955451781dSDouglas Anderson static int _regulator_disable(struct regulator *regulator); 96414c70cbSLiam Girdwood static int _regulator_get_voltage(struct regulator_dev *rdev); 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); 1059243a195SMaciej Purski static int regulator_set_voltage_rdev(struct regulator_dev *rdev, 1069243a195SMaciej Purski int min_uV, int max_uV, 1079243a195SMaciej Purski suspend_state_t state); 1083801b86aSMark Brown static struct regulator *create_regulator(struct regulator_dev *rdev, 1093801b86aSMark Brown struct device *dev, 1103801b86aSMark Brown const char *supply_name); 11136a1f1b6SJavier Martinez Canillas static void _regulator_put(struct regulator *regulator); 112414c70cbSLiam Girdwood 1131083c393SMark Brown static const char *rdev_get_name(struct regulator_dev *rdev) 1141083c393SMark Brown { 1151083c393SMark Brown if (rdev->constraints && rdev->constraints->name) 1161083c393SMark Brown return rdev->constraints->name; 1171083c393SMark Brown else if (rdev->desc->name) 1181083c393SMark Brown return rdev->desc->name; 1191083c393SMark Brown else 1201083c393SMark Brown return ""; 1211083c393SMark Brown } 1221083c393SMark Brown 12387b28417SMark Brown static bool have_full_constraints(void) 12487b28417SMark Brown { 12575bc9641SMark Brown return has_full_constraints || of_have_populated_dt(); 12687b28417SMark Brown } 12787b28417SMark Brown 1288a34e979SWEN Pingbo static bool regulator_ops_is_valid(struct regulator_dev *rdev, int ops) 1298a34e979SWEN Pingbo { 1308a34e979SWEN Pingbo if (!rdev->constraints) { 1318a34e979SWEN Pingbo rdev_err(rdev, "no constraints\n"); 1328a34e979SWEN Pingbo return false; 1338a34e979SWEN Pingbo } 1348a34e979SWEN Pingbo 1358a34e979SWEN Pingbo if (rdev->constraints->valid_ops_mask & ops) 1368a34e979SWEN Pingbo return true; 1378a34e979SWEN Pingbo 1388a34e979SWEN Pingbo return false; 1398a34e979SWEN Pingbo } 1408a34e979SWEN Pingbo 14169511a45SRajendra Nayak /** 14266cf9a7eSMaciej Purski * regulator_lock_nested - lock a single regulator 14366cf9a7eSMaciej Purski * @rdev: regulator source 144f8702f9eSDmitry Osipenko * @ww_ctx: w/w mutex acquire context 14566cf9a7eSMaciej Purski * 14666cf9a7eSMaciej Purski * This function can be called many times by one task on 14766cf9a7eSMaciej Purski * a single regulator and its mutex will be locked only 14866cf9a7eSMaciej Purski * once. If a task, which is calling this function is other 14966cf9a7eSMaciej Purski * than the one, which initially locked the mutex, it will 15066cf9a7eSMaciej Purski * wait on mutex. 15166cf9a7eSMaciej Purski */ 152f8702f9eSDmitry Osipenko static inline int regulator_lock_nested(struct regulator_dev *rdev, 153f8702f9eSDmitry Osipenko struct ww_acquire_ctx *ww_ctx) 15466cf9a7eSMaciej Purski { 155f8702f9eSDmitry Osipenko bool lock = false; 156f8702f9eSDmitry Osipenko int ret = 0; 157f8702f9eSDmitry Osipenko 158f8702f9eSDmitry Osipenko mutex_lock(®ulator_nesting_mutex); 159f8702f9eSDmitry Osipenko 160f8702f9eSDmitry Osipenko if (ww_ctx || !ww_mutex_trylock(&rdev->mutex)) { 161f8702f9eSDmitry Osipenko if (rdev->mutex_owner == current) 16266cf9a7eSMaciej Purski rdev->ref_cnt++; 163f8702f9eSDmitry Osipenko else 164f8702f9eSDmitry Osipenko lock = true; 165f8702f9eSDmitry Osipenko 166f8702f9eSDmitry Osipenko if (lock) { 167f8702f9eSDmitry Osipenko mutex_unlock(®ulator_nesting_mutex); 168f8702f9eSDmitry Osipenko ret = ww_mutex_lock(&rdev->mutex, ww_ctx); 169f8702f9eSDmitry Osipenko mutex_lock(®ulator_nesting_mutex); 17066cf9a7eSMaciej Purski } 171f8702f9eSDmitry Osipenko } else { 172f8702f9eSDmitry Osipenko lock = true; 17366cf9a7eSMaciej Purski } 17466cf9a7eSMaciej Purski 175f8702f9eSDmitry Osipenko if (lock && ret != -EDEADLK) { 176f8702f9eSDmitry Osipenko rdev->ref_cnt++; 17766cf9a7eSMaciej Purski rdev->mutex_owner = current; 17866cf9a7eSMaciej Purski } 17966cf9a7eSMaciej Purski 180f8702f9eSDmitry Osipenko mutex_unlock(®ulator_nesting_mutex); 181f8702f9eSDmitry Osipenko 182f8702f9eSDmitry Osipenko return ret; 183f8702f9eSDmitry Osipenko } 184f8702f9eSDmitry Osipenko 185f8702f9eSDmitry Osipenko /** 186f8702f9eSDmitry Osipenko * regulator_lock - lock a single regulator 187f8702f9eSDmitry Osipenko * @rdev: regulator source 188f8702f9eSDmitry Osipenko * 189f8702f9eSDmitry Osipenko * This function can be called many times by one task on 190f8702f9eSDmitry Osipenko * a single regulator and its mutex will be locked only 191f8702f9eSDmitry Osipenko * once. If a task, which is calling this function is other 192f8702f9eSDmitry Osipenko * than the one, which initially locked the mutex, it will 193f8702f9eSDmitry Osipenko * wait on mutex. 194f8702f9eSDmitry Osipenko */ 195f8702f9eSDmitry Osipenko void regulator_lock(struct regulator_dev *rdev) 19666cf9a7eSMaciej Purski { 197f8702f9eSDmitry Osipenko regulator_lock_nested(rdev, NULL); 19866cf9a7eSMaciej Purski } 19914a74272SDmitry Osipenko EXPORT_SYMBOL_GPL(regulator_lock); 20066cf9a7eSMaciej Purski 20166cf9a7eSMaciej Purski /** 20266cf9a7eSMaciej Purski * regulator_unlock - unlock a single regulator 20366cf9a7eSMaciej Purski * @rdev: regulator_source 20466cf9a7eSMaciej Purski * 20566cf9a7eSMaciej Purski * This function unlocks the mutex when the 20666cf9a7eSMaciej Purski * reference counter reaches 0. 20766cf9a7eSMaciej Purski */ 208f8702f9eSDmitry Osipenko void regulator_unlock(struct regulator_dev *rdev) 20966cf9a7eSMaciej Purski { 210f8702f9eSDmitry Osipenko mutex_lock(®ulator_nesting_mutex); 21166cf9a7eSMaciej Purski 212f8702f9eSDmitry Osipenko if (--rdev->ref_cnt == 0) { 21366cf9a7eSMaciej Purski rdev->mutex_owner = NULL; 214f8702f9eSDmitry Osipenko ww_mutex_unlock(&rdev->mutex); 21566cf9a7eSMaciej Purski } 21666cf9a7eSMaciej Purski 217f8702f9eSDmitry Osipenko WARN_ON_ONCE(rdev->ref_cnt < 0); 218f8702f9eSDmitry Osipenko 219f8702f9eSDmitry Osipenko mutex_unlock(®ulator_nesting_mutex); 220f8702f9eSDmitry Osipenko } 22114a74272SDmitry Osipenko EXPORT_SYMBOL_GPL(regulator_unlock); 222f8702f9eSDmitry Osipenko 223089e2cc2SDmitry Osipenko static bool regulator_supply_is_couple(struct regulator_dev *rdev) 2249f01cd4aSSascha Hauer { 225089e2cc2SDmitry Osipenko struct regulator_dev *c_rdev; 226fa731ac7SArnd Bergmann int i; 2279f01cd4aSSascha Hauer 228089e2cc2SDmitry Osipenko for (i = 1; i < rdev->coupling_desc.n_coupled; i++) { 229089e2cc2SDmitry Osipenko c_rdev = rdev->coupling_desc.coupled_rdevs[i]; 230089e2cc2SDmitry Osipenko 231089e2cc2SDmitry Osipenko if (rdev->supply->rdev == c_rdev) 232089e2cc2SDmitry Osipenko return true; 233089e2cc2SDmitry Osipenko } 234089e2cc2SDmitry Osipenko 235089e2cc2SDmitry Osipenko return false; 236089e2cc2SDmitry Osipenko } 237089e2cc2SDmitry Osipenko 238f8702f9eSDmitry Osipenko static void regulator_unlock_recursive(struct regulator_dev *rdev, 239f8702f9eSDmitry Osipenko unsigned int n_coupled) 240f8702f9eSDmitry Osipenko { 241f8702f9eSDmitry Osipenko struct regulator_dev *c_rdev; 242f8702f9eSDmitry Osipenko int i; 243f8702f9eSDmitry Osipenko 244f8702f9eSDmitry Osipenko for (i = n_coupled; i > 0; i--) { 245f8702f9eSDmitry Osipenko c_rdev = rdev->coupling_desc.coupled_rdevs[i - 1]; 246f8702f9eSDmitry Osipenko 247f8702f9eSDmitry Osipenko if (!c_rdev) 248f8702f9eSDmitry Osipenko continue; 249f8702f9eSDmitry Osipenko 250089e2cc2SDmitry Osipenko if (c_rdev->supply && !regulator_supply_is_couple(c_rdev)) 251f8702f9eSDmitry Osipenko regulator_unlock_recursive( 252f8702f9eSDmitry Osipenko c_rdev->supply->rdev, 253f8702f9eSDmitry Osipenko c_rdev->coupling_desc.n_coupled); 254f8702f9eSDmitry Osipenko 255f8702f9eSDmitry Osipenko regulator_unlock(c_rdev); 256414c70cbSLiam Girdwood } 257414c70cbSLiam Girdwood } 258414c70cbSLiam Girdwood 2599243a195SMaciej Purski static int regulator_lock_recursive(struct regulator_dev *rdev, 260f8702f9eSDmitry Osipenko struct regulator_dev **new_contended_rdev, 261f8702f9eSDmitry Osipenko struct regulator_dev **old_contended_rdev, 262f8702f9eSDmitry Osipenko struct ww_acquire_ctx *ww_ctx) 2639f01cd4aSSascha Hauer { 2649243a195SMaciej Purski struct regulator_dev *c_rdev; 265f8702f9eSDmitry Osipenko int i, err; 2669f01cd4aSSascha Hauer 2679243a195SMaciej Purski for (i = 0; i < rdev->coupling_desc.n_coupled; i++) { 2689243a195SMaciej Purski c_rdev = rdev->coupling_desc.coupled_rdevs[i]; 2699243a195SMaciej Purski 2709243a195SMaciej Purski if (!c_rdev) 2719243a195SMaciej Purski continue; 2729243a195SMaciej Purski 273f8702f9eSDmitry Osipenko if (c_rdev != *old_contended_rdev) { 274f8702f9eSDmitry Osipenko err = regulator_lock_nested(c_rdev, ww_ctx); 275f8702f9eSDmitry Osipenko if (err) { 276f8702f9eSDmitry Osipenko if (err == -EDEADLK) { 277f8702f9eSDmitry Osipenko *new_contended_rdev = c_rdev; 278f8702f9eSDmitry Osipenko goto err_unlock; 2799243a195SMaciej Purski } 2809243a195SMaciej Purski 281f8702f9eSDmitry Osipenko /* shouldn't happen */ 282f8702f9eSDmitry Osipenko WARN_ON_ONCE(err != -EALREADY); 283f8702f9eSDmitry Osipenko } 284f8702f9eSDmitry Osipenko } else { 285f8702f9eSDmitry Osipenko *old_contended_rdev = NULL; 286f8702f9eSDmitry Osipenko } 287f8702f9eSDmitry Osipenko 288089e2cc2SDmitry Osipenko if (c_rdev->supply && !regulator_supply_is_couple(c_rdev)) { 289f8702f9eSDmitry Osipenko err = regulator_lock_recursive(c_rdev->supply->rdev, 290f8702f9eSDmitry Osipenko new_contended_rdev, 291f8702f9eSDmitry Osipenko old_contended_rdev, 292f8702f9eSDmitry Osipenko ww_ctx); 293f8702f9eSDmitry Osipenko if (err) { 294f8702f9eSDmitry Osipenko regulator_unlock(c_rdev); 295f8702f9eSDmitry Osipenko goto err_unlock; 296f8702f9eSDmitry Osipenko } 297f8702f9eSDmitry Osipenko } 298f8702f9eSDmitry Osipenko } 299f8702f9eSDmitry Osipenko 300f8702f9eSDmitry Osipenko return 0; 301f8702f9eSDmitry Osipenko 302f8702f9eSDmitry Osipenko err_unlock: 303f8702f9eSDmitry Osipenko regulator_unlock_recursive(rdev, i); 304f8702f9eSDmitry Osipenko 305f8702f9eSDmitry Osipenko return err; 3069f01cd4aSSascha Hauer } 3079f01cd4aSSascha Hauer 3089f01cd4aSSascha Hauer /** 3099243a195SMaciej Purski * regulator_unlock_dependent - unlock regulator's suppliers and coupled 3109243a195SMaciej Purski * regulators 3119f01cd4aSSascha Hauer * @rdev: regulator source 312f8702f9eSDmitry Osipenko * @ww_ctx: w/w mutex acquire context 3139243a195SMaciej Purski * 31448f1b4efSKrzysztof Kozlowski * Unlock all regulators related with rdev by coupling or supplying. 3159f01cd4aSSascha Hauer */ 316f8702f9eSDmitry Osipenko static void regulator_unlock_dependent(struct regulator_dev *rdev, 317f8702f9eSDmitry Osipenko struct ww_acquire_ctx *ww_ctx) 3189f01cd4aSSascha Hauer { 319f8702f9eSDmitry Osipenko regulator_unlock_recursive(rdev, rdev->coupling_desc.n_coupled); 320f8702f9eSDmitry Osipenko ww_acquire_fini(ww_ctx); 3219f01cd4aSSascha Hauer } 3229f01cd4aSSascha Hauer 3239f01cd4aSSascha Hauer /** 3249243a195SMaciej Purski * regulator_lock_dependent - lock regulator's suppliers and coupled regulators 3259243a195SMaciej Purski * @rdev: regulator source 326f8702f9eSDmitry Osipenko * @ww_ctx: w/w mutex acquire context 3279243a195SMaciej Purski * 3289243a195SMaciej Purski * This function as a wrapper on regulator_lock_recursive(), which locks 32948f1b4efSKrzysztof Kozlowski * all regulators related with rdev by coupling or supplying. 3309243a195SMaciej Purski */ 331f8702f9eSDmitry Osipenko static void regulator_lock_dependent(struct regulator_dev *rdev, 332f8702f9eSDmitry Osipenko struct ww_acquire_ctx *ww_ctx) 3339243a195SMaciej Purski { 334f8702f9eSDmitry Osipenko struct regulator_dev *new_contended_rdev = NULL; 335f8702f9eSDmitry Osipenko struct regulator_dev *old_contended_rdev = NULL; 336f8702f9eSDmitry Osipenko int err; 337f8702f9eSDmitry Osipenko 338f8702f9eSDmitry Osipenko mutex_lock(®ulator_list_mutex); 339f8702f9eSDmitry Osipenko 340f8702f9eSDmitry Osipenko ww_acquire_init(ww_ctx, ®ulator_ww_class); 341f8702f9eSDmitry Osipenko 342f8702f9eSDmitry Osipenko do { 343f8702f9eSDmitry Osipenko if (new_contended_rdev) { 344f8702f9eSDmitry Osipenko ww_mutex_lock_slow(&new_contended_rdev->mutex, ww_ctx); 345f8702f9eSDmitry Osipenko old_contended_rdev = new_contended_rdev; 346f8702f9eSDmitry Osipenko old_contended_rdev->ref_cnt++; 347f8702f9eSDmitry Osipenko } 348f8702f9eSDmitry Osipenko 349f8702f9eSDmitry Osipenko err = regulator_lock_recursive(rdev, 350f8702f9eSDmitry Osipenko &new_contended_rdev, 351f8702f9eSDmitry Osipenko &old_contended_rdev, 352f8702f9eSDmitry Osipenko ww_ctx); 353f8702f9eSDmitry Osipenko 354f8702f9eSDmitry Osipenko if (old_contended_rdev) 355f8702f9eSDmitry Osipenko regulator_unlock(old_contended_rdev); 356f8702f9eSDmitry Osipenko 357f8702f9eSDmitry Osipenko } while (err == -EDEADLK); 358f8702f9eSDmitry Osipenko 359f8702f9eSDmitry Osipenko ww_acquire_done(ww_ctx); 360f8702f9eSDmitry Osipenko 361f8702f9eSDmitry Osipenko mutex_unlock(®ulator_list_mutex); 362414c70cbSLiam Girdwood } 363414c70cbSLiam Girdwood 364414c70cbSLiam Girdwood /** 365fe06051dSzoro * of_get_child_regulator - get a child regulator device node 366fe06051dSzoro * based on supply name 367fe06051dSzoro * @parent: Parent device node 368fe06051dSzoro * @prop_name: Combination regulator supply name and "-supply" 369fe06051dSzoro * 370fe06051dSzoro * Traverse all child nodes. 371fe06051dSzoro * Extract the child regulator device node corresponding to the supply name. 372fe06051dSzoro * returns the device node corresponding to the regulator if found, else 373fe06051dSzoro * returns NULL. 374fe06051dSzoro */ 375fe06051dSzoro static struct device_node *of_get_child_regulator(struct device_node *parent, 376fe06051dSzoro const char *prop_name) 377fe06051dSzoro { 378fe06051dSzoro struct device_node *regnode = NULL; 379fe06051dSzoro struct device_node *child = NULL; 380fe06051dSzoro 381fe06051dSzoro for_each_child_of_node(parent, child) { 382fe06051dSzoro regnode = of_parse_phandle(child, prop_name, 0); 383fe06051dSzoro 384fe06051dSzoro if (!regnode) { 385fe06051dSzoro regnode = of_get_child_regulator(child, prop_name); 386fe06051dSzoro if (regnode) 387fe06051dSzoro return regnode; 388fe06051dSzoro } else { 389fe06051dSzoro return regnode; 390fe06051dSzoro } 391fe06051dSzoro } 392fe06051dSzoro return NULL; 393fe06051dSzoro } 394fe06051dSzoro 395fe06051dSzoro /** 39669511a45SRajendra Nayak * of_get_regulator - get a regulator device node based on supply name 39769511a45SRajendra Nayak * @dev: Device pointer for the consumer (of regulator) device 39869511a45SRajendra Nayak * @supply: regulator supply name 39969511a45SRajendra Nayak * 40069511a45SRajendra Nayak * Extract the regulator device node corresponding to the supply name. 401167d41dcSMaxime Ripard * returns the device node corresponding to the regulator if found, else 40269511a45SRajendra Nayak * returns NULL. 40369511a45SRajendra Nayak */ 40469511a45SRajendra Nayak static struct device_node *of_get_regulator(struct device *dev, const char *supply) 40569511a45SRajendra Nayak { 40669511a45SRajendra Nayak struct device_node *regnode = NULL; 40769511a45SRajendra Nayak char prop_name[32]; /* 32 is max size of property name */ 40869511a45SRajendra Nayak 40969511a45SRajendra Nayak dev_dbg(dev, "Looking up %s-supply from device tree\n", supply); 41069511a45SRajendra Nayak 41169511a45SRajendra Nayak snprintf(prop_name, 32, "%s-supply", supply); 41269511a45SRajendra Nayak regnode = of_parse_phandle(dev->of_node, prop_name, 0); 41369511a45SRajendra Nayak 41469511a45SRajendra Nayak if (!regnode) { 415fe06051dSzoro regnode = of_get_child_regulator(dev->of_node, prop_name); 416fe06051dSzoro if (regnode) 417fe06051dSzoro return regnode; 418fe06051dSzoro 4197799167bSRob Herring dev_dbg(dev, "Looking up %s property in node %pOF failed\n", 4207799167bSRob Herring prop_name, dev->of_node); 42169511a45SRajendra Nayak return NULL; 42269511a45SRajendra Nayak } 42369511a45SRajendra Nayak return regnode; 42469511a45SRajendra Nayak } 42569511a45SRajendra Nayak 426414c70cbSLiam Girdwood /* Platform voltage constraint check */ 427414c70cbSLiam Girdwood static int regulator_check_voltage(struct regulator_dev *rdev, 428414c70cbSLiam Girdwood int *min_uV, int *max_uV) 429414c70cbSLiam Girdwood { 430414c70cbSLiam Girdwood BUG_ON(*min_uV > *max_uV); 431414c70cbSLiam Girdwood 4328a34e979SWEN Pingbo if (!regulator_ops_is_valid(rdev, REGULATOR_CHANGE_VOLTAGE)) { 4337ebcf26cSStephen Boyd rdev_err(rdev, "voltage operation not allowed\n"); 434414c70cbSLiam Girdwood return -EPERM; 435414c70cbSLiam Girdwood } 436414c70cbSLiam Girdwood 437414c70cbSLiam Girdwood if (*max_uV > rdev->constraints->max_uV) 438414c70cbSLiam Girdwood *max_uV = rdev->constraints->max_uV; 439414c70cbSLiam Girdwood if (*min_uV < rdev->constraints->min_uV) 440414c70cbSLiam Girdwood *min_uV = rdev->constraints->min_uV; 441414c70cbSLiam Girdwood 44289f425edSMark Brown if (*min_uV > *max_uV) { 44389f425edSMark Brown rdev_err(rdev, "unsupportable voltage range: %d-%duV\n", 44454abd335SMark Brown *min_uV, *max_uV); 445414c70cbSLiam Girdwood return -EINVAL; 44689f425edSMark Brown } 447414c70cbSLiam Girdwood 448414c70cbSLiam Girdwood return 0; 449414c70cbSLiam Girdwood } 450414c70cbSLiam Girdwood 451f7efad10SChunyan Zhang /* return 0 if the state is valid */ 452f7efad10SChunyan Zhang static int regulator_check_states(suspend_state_t state) 453f7efad10SChunyan Zhang { 454f7efad10SChunyan Zhang return (state > PM_SUSPEND_MAX || state == PM_SUSPEND_TO_IDLE); 455f7efad10SChunyan Zhang } 456f7efad10SChunyan Zhang 45705fda3b1SThomas Petazzoni /* Make sure we select a voltage that suits the needs of all 45805fda3b1SThomas Petazzoni * regulator consumers 45905fda3b1SThomas Petazzoni */ 46005fda3b1SThomas Petazzoni static int regulator_check_consumers(struct regulator_dev *rdev, 461c360a6dfSChunyan Zhang int *min_uV, int *max_uV, 462c360a6dfSChunyan Zhang suspend_state_t state) 46305fda3b1SThomas Petazzoni { 46405fda3b1SThomas Petazzoni struct regulator *regulator; 465c360a6dfSChunyan Zhang struct regulator_voltage *voltage; 46605fda3b1SThomas Petazzoni 46705fda3b1SThomas Petazzoni list_for_each_entry(regulator, &rdev->consumer_list, list) { 468c360a6dfSChunyan Zhang voltage = ®ulator->voltage[state]; 4694aa922c0SMark Brown /* 4704aa922c0SMark Brown * Assume consumers that didn't say anything are OK 4714aa922c0SMark Brown * with anything in the constraint range. 4724aa922c0SMark Brown */ 473c360a6dfSChunyan Zhang if (!voltage->min_uV && !voltage->max_uV) 4744aa922c0SMark Brown continue; 4754aa922c0SMark Brown 476c360a6dfSChunyan Zhang if (*max_uV > voltage->max_uV) 477c360a6dfSChunyan Zhang *max_uV = voltage->max_uV; 478c360a6dfSChunyan Zhang if (*min_uV < voltage->min_uV) 479c360a6dfSChunyan Zhang *min_uV = voltage->min_uV; 48005fda3b1SThomas Petazzoni } 48105fda3b1SThomas Petazzoni 482dd8004afSMark Brown if (*min_uV > *max_uV) { 4839c7b4e8aSRuss Dill rdev_err(rdev, "Restricting voltage, %u-%uuV\n", 4849c7b4e8aSRuss Dill *min_uV, *max_uV); 48505fda3b1SThomas Petazzoni return -EINVAL; 486dd8004afSMark Brown } 48705fda3b1SThomas Petazzoni 48805fda3b1SThomas Petazzoni return 0; 48905fda3b1SThomas Petazzoni } 49005fda3b1SThomas Petazzoni 491414c70cbSLiam Girdwood /* current constraint check */ 492414c70cbSLiam Girdwood static int regulator_check_current_limit(struct regulator_dev *rdev, 493414c70cbSLiam Girdwood int *min_uA, int *max_uA) 494414c70cbSLiam Girdwood { 495414c70cbSLiam Girdwood BUG_ON(*min_uA > *max_uA); 496414c70cbSLiam Girdwood 4978a34e979SWEN Pingbo if (!regulator_ops_is_valid(rdev, REGULATOR_CHANGE_CURRENT)) { 4987ebcf26cSStephen Boyd rdev_err(rdev, "current operation not allowed\n"); 499414c70cbSLiam Girdwood return -EPERM; 500414c70cbSLiam Girdwood } 501414c70cbSLiam Girdwood 502414c70cbSLiam Girdwood if (*max_uA > rdev->constraints->max_uA) 503414c70cbSLiam Girdwood *max_uA = rdev->constraints->max_uA; 504414c70cbSLiam Girdwood if (*min_uA < rdev->constraints->min_uA) 505414c70cbSLiam Girdwood *min_uA = rdev->constraints->min_uA; 506414c70cbSLiam Girdwood 50789f425edSMark Brown if (*min_uA > *max_uA) { 50889f425edSMark Brown rdev_err(rdev, "unsupportable current range: %d-%duA\n", 50954abd335SMark Brown *min_uA, *max_uA); 510414c70cbSLiam Girdwood return -EINVAL; 51189f425edSMark Brown } 512414c70cbSLiam Girdwood 513414c70cbSLiam Girdwood return 0; 514414c70cbSLiam Girdwood } 515414c70cbSLiam Girdwood 516414c70cbSLiam Girdwood /* operating mode constraint check */ 517109c75afSCharles Keepax static int regulator_mode_constrain(struct regulator_dev *rdev, 518109c75afSCharles Keepax unsigned int *mode) 519414c70cbSLiam Girdwood { 5202c608234SMark Brown switch (*mode) { 521e573520bSDavid Brownell case REGULATOR_MODE_FAST: 522e573520bSDavid Brownell case REGULATOR_MODE_NORMAL: 523e573520bSDavid Brownell case REGULATOR_MODE_IDLE: 524e573520bSDavid Brownell case REGULATOR_MODE_STANDBY: 525e573520bSDavid Brownell break; 526e573520bSDavid Brownell default: 52789f425edSMark Brown rdev_err(rdev, "invalid mode %x specified\n", *mode); 528e573520bSDavid Brownell return -EINVAL; 529e573520bSDavid Brownell } 530e573520bSDavid Brownell 5318a34e979SWEN Pingbo if (!regulator_ops_is_valid(rdev, REGULATOR_CHANGE_MODE)) { 5327ebcf26cSStephen Boyd rdev_err(rdev, "mode operation not allowed\n"); 533414c70cbSLiam Girdwood return -EPERM; 534414c70cbSLiam Girdwood } 5352c608234SMark Brown 5362c608234SMark Brown /* The modes are bitmasks, the most power hungry modes having 5372c608234SMark Brown * the lowest values. If the requested mode isn't supported 5382c608234SMark Brown * try higher modes. */ 5392c608234SMark Brown while (*mode) { 5402c608234SMark Brown if (rdev->constraints->valid_modes_mask & *mode) 541414c70cbSLiam Girdwood return 0; 5422c608234SMark Brown *mode /= 2; 5432c608234SMark Brown } 5442c608234SMark Brown 5452c608234SMark Brown return -EINVAL; 546414c70cbSLiam Girdwood } 547414c70cbSLiam Girdwood 548f7efad10SChunyan Zhang static inline struct regulator_state * 549f7efad10SChunyan Zhang regulator_get_suspend_state(struct regulator_dev *rdev, suspend_state_t state) 550f7efad10SChunyan Zhang { 551f7efad10SChunyan Zhang if (rdev->constraints == NULL) 552f7efad10SChunyan Zhang return NULL; 553f7efad10SChunyan Zhang 554f7efad10SChunyan Zhang switch (state) { 555f7efad10SChunyan Zhang case PM_SUSPEND_STANDBY: 556f7efad10SChunyan Zhang return &rdev->constraints->state_standby; 557f7efad10SChunyan Zhang case PM_SUSPEND_MEM: 558f7efad10SChunyan Zhang return &rdev->constraints->state_mem; 559f7efad10SChunyan Zhang case PM_SUSPEND_MAX: 560f7efad10SChunyan Zhang return &rdev->constraints->state_disk; 561f7efad10SChunyan Zhang default: 562f7efad10SChunyan Zhang return NULL; 563f7efad10SChunyan Zhang } 564f7efad10SChunyan Zhang } 565f7efad10SChunyan Zhang 566414c70cbSLiam Girdwood static ssize_t regulator_uV_show(struct device *dev, 567414c70cbSLiam Girdwood struct device_attribute *attr, char *buf) 568414c70cbSLiam Girdwood { 569a5766f11SLiam Girdwood struct regulator_dev *rdev = dev_get_drvdata(dev); 570414c70cbSLiam Girdwood ssize_t ret; 571414c70cbSLiam Girdwood 57266cf9a7eSMaciej Purski regulator_lock(rdev); 573414c70cbSLiam Girdwood ret = sprintf(buf, "%d\n", _regulator_get_voltage(rdev)); 57466cf9a7eSMaciej Purski regulator_unlock(rdev); 575414c70cbSLiam Girdwood 576414c70cbSLiam Girdwood return ret; 577414c70cbSLiam Girdwood } 5787ad68e2fSDavid Brownell static DEVICE_ATTR(microvolts, 0444, regulator_uV_show, NULL); 579414c70cbSLiam Girdwood 580414c70cbSLiam Girdwood static ssize_t regulator_uA_show(struct device *dev, 581414c70cbSLiam Girdwood struct device_attribute *attr, char *buf) 582414c70cbSLiam Girdwood { 583a5766f11SLiam Girdwood struct regulator_dev *rdev = dev_get_drvdata(dev); 584414c70cbSLiam Girdwood 585414c70cbSLiam Girdwood return sprintf(buf, "%d\n", _regulator_get_current_limit(rdev)); 586414c70cbSLiam Girdwood } 5877ad68e2fSDavid Brownell static DEVICE_ATTR(microamps, 0444, regulator_uA_show, NULL); 588414c70cbSLiam Girdwood 589587cea27SGreg Kroah-Hartman static ssize_t name_show(struct device *dev, struct device_attribute *attr, 590587cea27SGreg Kroah-Hartman char *buf) 591bc558a60SMark Brown { 592bc558a60SMark Brown struct regulator_dev *rdev = dev_get_drvdata(dev); 593bc558a60SMark Brown 5941083c393SMark Brown return sprintf(buf, "%s\n", rdev_get_name(rdev)); 595bc558a60SMark Brown } 596587cea27SGreg Kroah-Hartman static DEVICE_ATTR_RO(name); 597bc558a60SMark Brown 59801de19d0SDouglas Anderson static const char *regulator_opmode_to_str(int mode) 599414c70cbSLiam Girdwood { 600414c70cbSLiam Girdwood switch (mode) { 601414c70cbSLiam Girdwood case REGULATOR_MODE_FAST: 60201de19d0SDouglas Anderson return "fast"; 603414c70cbSLiam Girdwood case REGULATOR_MODE_NORMAL: 60401de19d0SDouglas Anderson return "normal"; 605414c70cbSLiam Girdwood case REGULATOR_MODE_IDLE: 60601de19d0SDouglas Anderson return "idle"; 607414c70cbSLiam Girdwood case REGULATOR_MODE_STANDBY: 60801de19d0SDouglas Anderson return "standby"; 609414c70cbSLiam Girdwood } 61001de19d0SDouglas Anderson return "unknown"; 61101de19d0SDouglas Anderson } 61201de19d0SDouglas Anderson 61301de19d0SDouglas Anderson static ssize_t regulator_print_opmode(char *buf, int mode) 61401de19d0SDouglas Anderson { 61501de19d0SDouglas Anderson return sprintf(buf, "%s\n", regulator_opmode_to_str(mode)); 616414c70cbSLiam Girdwood } 617414c70cbSLiam Girdwood 6184fca9545SDavid Brownell static ssize_t regulator_opmode_show(struct device *dev, 619414c70cbSLiam Girdwood struct device_attribute *attr, char *buf) 620414c70cbSLiam Girdwood { 621a5766f11SLiam Girdwood struct regulator_dev *rdev = dev_get_drvdata(dev); 622414c70cbSLiam Girdwood 6234fca9545SDavid Brownell return regulator_print_opmode(buf, _regulator_get_mode(rdev)); 6244fca9545SDavid Brownell } 6257ad68e2fSDavid Brownell static DEVICE_ATTR(opmode, 0444, regulator_opmode_show, NULL); 6264fca9545SDavid Brownell 6274fca9545SDavid Brownell static ssize_t regulator_print_state(char *buf, int state) 6284fca9545SDavid Brownell { 629414c70cbSLiam Girdwood if (state > 0) 630414c70cbSLiam Girdwood return sprintf(buf, "enabled\n"); 631414c70cbSLiam Girdwood else if (state == 0) 632414c70cbSLiam Girdwood return sprintf(buf, "disabled\n"); 633414c70cbSLiam Girdwood else 634414c70cbSLiam Girdwood return sprintf(buf, "unknown\n"); 635414c70cbSLiam Girdwood } 636414c70cbSLiam Girdwood 6374fca9545SDavid Brownell static ssize_t regulator_state_show(struct device *dev, 6384fca9545SDavid Brownell struct device_attribute *attr, char *buf) 6394fca9545SDavid Brownell { 6404fca9545SDavid Brownell struct regulator_dev *rdev = dev_get_drvdata(dev); 6419332546fSMark Brown ssize_t ret; 6424fca9545SDavid Brownell 64366cf9a7eSMaciej Purski regulator_lock(rdev); 6449332546fSMark Brown ret = regulator_print_state(buf, _regulator_is_enabled(rdev)); 64566cf9a7eSMaciej Purski regulator_unlock(rdev); 6469332546fSMark Brown 6479332546fSMark Brown return ret; 6484fca9545SDavid Brownell } 6497ad68e2fSDavid Brownell static DEVICE_ATTR(state, 0444, regulator_state_show, NULL); 6504fca9545SDavid Brownell 651853116a1SDavid Brownell static ssize_t regulator_status_show(struct device *dev, 652853116a1SDavid Brownell struct device_attribute *attr, char *buf) 653853116a1SDavid Brownell { 654853116a1SDavid Brownell struct regulator_dev *rdev = dev_get_drvdata(dev); 655853116a1SDavid Brownell int status; 656853116a1SDavid Brownell char *label; 657853116a1SDavid Brownell 658853116a1SDavid Brownell status = rdev->desc->ops->get_status(rdev); 659853116a1SDavid Brownell if (status < 0) 660853116a1SDavid Brownell return status; 661853116a1SDavid Brownell 662853116a1SDavid Brownell switch (status) { 663853116a1SDavid Brownell case REGULATOR_STATUS_OFF: 664853116a1SDavid Brownell label = "off"; 665853116a1SDavid Brownell break; 666853116a1SDavid Brownell case REGULATOR_STATUS_ON: 667853116a1SDavid Brownell label = "on"; 668853116a1SDavid Brownell break; 669853116a1SDavid Brownell case REGULATOR_STATUS_ERROR: 670853116a1SDavid Brownell label = "error"; 671853116a1SDavid Brownell break; 672853116a1SDavid Brownell case REGULATOR_STATUS_FAST: 673853116a1SDavid Brownell label = "fast"; 674853116a1SDavid Brownell break; 675853116a1SDavid Brownell case REGULATOR_STATUS_NORMAL: 676853116a1SDavid Brownell label = "normal"; 677853116a1SDavid Brownell break; 678853116a1SDavid Brownell case REGULATOR_STATUS_IDLE: 679853116a1SDavid Brownell label = "idle"; 680853116a1SDavid Brownell break; 681853116a1SDavid Brownell case REGULATOR_STATUS_STANDBY: 682853116a1SDavid Brownell label = "standby"; 683853116a1SDavid Brownell break; 684f59c8f9fSMark Brown case REGULATOR_STATUS_BYPASS: 685f59c8f9fSMark Brown label = "bypass"; 686f59c8f9fSMark Brown break; 6871beaf762SKrystian Garbaciak case REGULATOR_STATUS_UNDEFINED: 6881beaf762SKrystian Garbaciak label = "undefined"; 6891beaf762SKrystian Garbaciak break; 690853116a1SDavid Brownell default: 691853116a1SDavid Brownell return -ERANGE; 692853116a1SDavid Brownell } 693853116a1SDavid Brownell 694853116a1SDavid Brownell return sprintf(buf, "%s\n", label); 695853116a1SDavid Brownell } 696853116a1SDavid Brownell static DEVICE_ATTR(status, 0444, regulator_status_show, NULL); 697853116a1SDavid Brownell 698414c70cbSLiam Girdwood static ssize_t regulator_min_uA_show(struct device *dev, 699414c70cbSLiam Girdwood struct device_attribute *attr, char *buf) 700414c70cbSLiam Girdwood { 701a5766f11SLiam Girdwood struct regulator_dev *rdev = dev_get_drvdata(dev); 702414c70cbSLiam Girdwood 703414c70cbSLiam Girdwood if (!rdev->constraints) 704414c70cbSLiam Girdwood return sprintf(buf, "constraint not defined\n"); 705414c70cbSLiam Girdwood 706414c70cbSLiam Girdwood return sprintf(buf, "%d\n", rdev->constraints->min_uA); 707414c70cbSLiam Girdwood } 7087ad68e2fSDavid Brownell static DEVICE_ATTR(min_microamps, 0444, regulator_min_uA_show, NULL); 709414c70cbSLiam Girdwood 710414c70cbSLiam Girdwood static ssize_t regulator_max_uA_show(struct device *dev, 711414c70cbSLiam Girdwood struct device_attribute *attr, char *buf) 712414c70cbSLiam Girdwood { 713a5766f11SLiam Girdwood struct regulator_dev *rdev = dev_get_drvdata(dev); 714414c70cbSLiam Girdwood 715414c70cbSLiam Girdwood if (!rdev->constraints) 716414c70cbSLiam Girdwood return sprintf(buf, "constraint not defined\n"); 717414c70cbSLiam Girdwood 718414c70cbSLiam Girdwood return sprintf(buf, "%d\n", rdev->constraints->max_uA); 719414c70cbSLiam Girdwood } 7207ad68e2fSDavid Brownell static DEVICE_ATTR(max_microamps, 0444, regulator_max_uA_show, NULL); 721414c70cbSLiam Girdwood 722414c70cbSLiam Girdwood static ssize_t regulator_min_uV_show(struct device *dev, 723414c70cbSLiam Girdwood struct device_attribute *attr, char *buf) 724414c70cbSLiam Girdwood { 725a5766f11SLiam Girdwood struct regulator_dev *rdev = dev_get_drvdata(dev); 726414c70cbSLiam Girdwood 727414c70cbSLiam Girdwood if (!rdev->constraints) 728414c70cbSLiam Girdwood return sprintf(buf, "constraint not defined\n"); 729414c70cbSLiam Girdwood 730414c70cbSLiam Girdwood return sprintf(buf, "%d\n", rdev->constraints->min_uV); 731414c70cbSLiam Girdwood } 7327ad68e2fSDavid Brownell static DEVICE_ATTR(min_microvolts, 0444, regulator_min_uV_show, NULL); 733414c70cbSLiam Girdwood 734414c70cbSLiam Girdwood static ssize_t regulator_max_uV_show(struct device *dev, 735414c70cbSLiam Girdwood struct device_attribute *attr, char *buf) 736414c70cbSLiam Girdwood { 737a5766f11SLiam Girdwood struct regulator_dev *rdev = dev_get_drvdata(dev); 738414c70cbSLiam Girdwood 739414c70cbSLiam Girdwood if (!rdev->constraints) 740414c70cbSLiam Girdwood return sprintf(buf, "constraint not defined\n"); 741414c70cbSLiam Girdwood 742414c70cbSLiam Girdwood return sprintf(buf, "%d\n", rdev->constraints->max_uV); 743414c70cbSLiam Girdwood } 7447ad68e2fSDavid Brownell static DEVICE_ATTR(max_microvolts, 0444, regulator_max_uV_show, NULL); 745414c70cbSLiam Girdwood 746414c70cbSLiam Girdwood static ssize_t regulator_total_uA_show(struct device *dev, 747414c70cbSLiam Girdwood struct device_attribute *attr, char *buf) 748414c70cbSLiam Girdwood { 749a5766f11SLiam Girdwood struct regulator_dev *rdev = dev_get_drvdata(dev); 750414c70cbSLiam Girdwood struct regulator *regulator; 751414c70cbSLiam Girdwood int uA = 0; 752414c70cbSLiam Girdwood 75366cf9a7eSMaciej Purski regulator_lock(rdev); 7545451781dSDouglas Anderson list_for_each_entry(regulator, &rdev->consumer_list, list) { 7555451781dSDouglas Anderson if (regulator->enable_count) 756414c70cbSLiam Girdwood uA += regulator->uA_load; 7575451781dSDouglas Anderson } 75866cf9a7eSMaciej Purski regulator_unlock(rdev); 759414c70cbSLiam Girdwood return sprintf(buf, "%d\n", uA); 760414c70cbSLiam Girdwood } 7617ad68e2fSDavid Brownell static DEVICE_ATTR(requested_microamps, 0444, regulator_total_uA_show, NULL); 762414c70cbSLiam Girdwood 763587cea27SGreg Kroah-Hartman static ssize_t num_users_show(struct device *dev, struct device_attribute *attr, 764587cea27SGreg Kroah-Hartman char *buf) 765414c70cbSLiam Girdwood { 766a5766f11SLiam Girdwood struct regulator_dev *rdev = dev_get_drvdata(dev); 767414c70cbSLiam Girdwood return sprintf(buf, "%d\n", rdev->use_count); 768414c70cbSLiam Girdwood } 769587cea27SGreg Kroah-Hartman static DEVICE_ATTR_RO(num_users); 770414c70cbSLiam Girdwood 771587cea27SGreg Kroah-Hartman static ssize_t type_show(struct device *dev, struct device_attribute *attr, 772587cea27SGreg Kroah-Hartman char *buf) 773414c70cbSLiam Girdwood { 774a5766f11SLiam Girdwood struct regulator_dev *rdev = dev_get_drvdata(dev); 775414c70cbSLiam Girdwood 776414c70cbSLiam Girdwood switch (rdev->desc->type) { 777414c70cbSLiam Girdwood case REGULATOR_VOLTAGE: 778414c70cbSLiam Girdwood return sprintf(buf, "voltage\n"); 779414c70cbSLiam Girdwood case REGULATOR_CURRENT: 780414c70cbSLiam Girdwood return sprintf(buf, "current\n"); 781414c70cbSLiam Girdwood } 782414c70cbSLiam Girdwood return sprintf(buf, "unknown\n"); 783414c70cbSLiam Girdwood } 784587cea27SGreg Kroah-Hartman static DEVICE_ATTR_RO(type); 785414c70cbSLiam Girdwood 786414c70cbSLiam Girdwood static ssize_t regulator_suspend_mem_uV_show(struct device *dev, 787414c70cbSLiam Girdwood struct device_attribute *attr, char *buf) 788414c70cbSLiam Girdwood { 789a5766f11SLiam Girdwood struct regulator_dev *rdev = dev_get_drvdata(dev); 790414c70cbSLiam Girdwood 791414c70cbSLiam Girdwood return sprintf(buf, "%d\n", rdev->constraints->state_mem.uV); 792414c70cbSLiam Girdwood } 7937ad68e2fSDavid Brownell static DEVICE_ATTR(suspend_mem_microvolts, 0444, 7947ad68e2fSDavid Brownell regulator_suspend_mem_uV_show, NULL); 795414c70cbSLiam Girdwood 796414c70cbSLiam Girdwood static ssize_t regulator_suspend_disk_uV_show(struct device *dev, 797414c70cbSLiam Girdwood struct device_attribute *attr, char *buf) 798414c70cbSLiam Girdwood { 799a5766f11SLiam Girdwood struct regulator_dev *rdev = dev_get_drvdata(dev); 800414c70cbSLiam Girdwood 801414c70cbSLiam Girdwood return sprintf(buf, "%d\n", rdev->constraints->state_disk.uV); 802414c70cbSLiam Girdwood } 8037ad68e2fSDavid Brownell static DEVICE_ATTR(suspend_disk_microvolts, 0444, 8047ad68e2fSDavid Brownell regulator_suspend_disk_uV_show, NULL); 805414c70cbSLiam Girdwood 806414c70cbSLiam Girdwood static ssize_t regulator_suspend_standby_uV_show(struct device *dev, 807414c70cbSLiam Girdwood struct device_attribute *attr, char *buf) 808414c70cbSLiam Girdwood { 809a5766f11SLiam Girdwood struct regulator_dev *rdev = dev_get_drvdata(dev); 810414c70cbSLiam Girdwood 811414c70cbSLiam Girdwood return sprintf(buf, "%d\n", rdev->constraints->state_standby.uV); 812414c70cbSLiam Girdwood } 8137ad68e2fSDavid Brownell static DEVICE_ATTR(suspend_standby_microvolts, 0444, 8147ad68e2fSDavid Brownell regulator_suspend_standby_uV_show, NULL); 815414c70cbSLiam Girdwood 816414c70cbSLiam Girdwood static ssize_t regulator_suspend_mem_mode_show(struct device *dev, 817414c70cbSLiam Girdwood struct device_attribute *attr, char *buf) 818414c70cbSLiam Girdwood { 819a5766f11SLiam Girdwood struct regulator_dev *rdev = dev_get_drvdata(dev); 820414c70cbSLiam Girdwood 8214fca9545SDavid Brownell return regulator_print_opmode(buf, 8224fca9545SDavid Brownell rdev->constraints->state_mem.mode); 823414c70cbSLiam Girdwood } 8247ad68e2fSDavid Brownell static DEVICE_ATTR(suspend_mem_mode, 0444, 8257ad68e2fSDavid Brownell regulator_suspend_mem_mode_show, NULL); 826414c70cbSLiam Girdwood 827414c70cbSLiam Girdwood static ssize_t regulator_suspend_disk_mode_show(struct device *dev, 828414c70cbSLiam Girdwood struct device_attribute *attr, char *buf) 829414c70cbSLiam Girdwood { 830a5766f11SLiam Girdwood struct regulator_dev *rdev = dev_get_drvdata(dev); 831414c70cbSLiam Girdwood 8324fca9545SDavid Brownell return regulator_print_opmode(buf, 8334fca9545SDavid Brownell rdev->constraints->state_disk.mode); 834414c70cbSLiam Girdwood } 8357ad68e2fSDavid Brownell static DEVICE_ATTR(suspend_disk_mode, 0444, 8367ad68e2fSDavid Brownell regulator_suspend_disk_mode_show, NULL); 837414c70cbSLiam Girdwood 838414c70cbSLiam Girdwood static ssize_t regulator_suspend_standby_mode_show(struct device *dev, 839414c70cbSLiam Girdwood struct device_attribute *attr, char *buf) 840414c70cbSLiam Girdwood { 841a5766f11SLiam Girdwood struct regulator_dev *rdev = dev_get_drvdata(dev); 842414c70cbSLiam Girdwood 8434fca9545SDavid Brownell return regulator_print_opmode(buf, 8444fca9545SDavid Brownell rdev->constraints->state_standby.mode); 845414c70cbSLiam Girdwood } 8467ad68e2fSDavid Brownell static DEVICE_ATTR(suspend_standby_mode, 0444, 8477ad68e2fSDavid Brownell regulator_suspend_standby_mode_show, NULL); 848414c70cbSLiam Girdwood 849414c70cbSLiam Girdwood static ssize_t regulator_suspend_mem_state_show(struct device *dev, 850414c70cbSLiam Girdwood struct device_attribute *attr, char *buf) 851414c70cbSLiam Girdwood { 852a5766f11SLiam Girdwood struct regulator_dev *rdev = dev_get_drvdata(dev); 853414c70cbSLiam Girdwood 8544fca9545SDavid Brownell return regulator_print_state(buf, 8554fca9545SDavid Brownell rdev->constraints->state_mem.enabled); 856414c70cbSLiam Girdwood } 8577ad68e2fSDavid Brownell static DEVICE_ATTR(suspend_mem_state, 0444, 8587ad68e2fSDavid Brownell regulator_suspend_mem_state_show, NULL); 859414c70cbSLiam Girdwood 860414c70cbSLiam Girdwood static ssize_t regulator_suspend_disk_state_show(struct device *dev, 861414c70cbSLiam Girdwood struct device_attribute *attr, char *buf) 862414c70cbSLiam Girdwood { 863a5766f11SLiam Girdwood struct regulator_dev *rdev = dev_get_drvdata(dev); 864414c70cbSLiam Girdwood 8654fca9545SDavid Brownell return regulator_print_state(buf, 8664fca9545SDavid Brownell rdev->constraints->state_disk.enabled); 867414c70cbSLiam Girdwood } 8687ad68e2fSDavid Brownell static DEVICE_ATTR(suspend_disk_state, 0444, 8697ad68e2fSDavid Brownell regulator_suspend_disk_state_show, NULL); 870414c70cbSLiam Girdwood 871414c70cbSLiam Girdwood static ssize_t regulator_suspend_standby_state_show(struct device *dev, 872414c70cbSLiam Girdwood struct device_attribute *attr, char *buf) 873414c70cbSLiam Girdwood { 874a5766f11SLiam Girdwood struct regulator_dev *rdev = dev_get_drvdata(dev); 875414c70cbSLiam Girdwood 8764fca9545SDavid Brownell return regulator_print_state(buf, 8774fca9545SDavid Brownell rdev->constraints->state_standby.enabled); 878414c70cbSLiam Girdwood } 8797ad68e2fSDavid Brownell static DEVICE_ATTR(suspend_standby_state, 0444, 8807ad68e2fSDavid Brownell regulator_suspend_standby_state_show, NULL); 881bc558a60SMark Brown 882f59c8f9fSMark Brown static ssize_t regulator_bypass_show(struct device *dev, 883f59c8f9fSMark Brown struct device_attribute *attr, char *buf) 884f59c8f9fSMark Brown { 885f59c8f9fSMark Brown struct regulator_dev *rdev = dev_get_drvdata(dev); 886f59c8f9fSMark Brown const char *report; 887f59c8f9fSMark Brown bool bypass; 888f59c8f9fSMark Brown int ret; 889f59c8f9fSMark Brown 890f59c8f9fSMark Brown ret = rdev->desc->ops->get_bypass(rdev, &bypass); 891f59c8f9fSMark Brown 892f59c8f9fSMark Brown if (ret != 0) 893f59c8f9fSMark Brown report = "unknown"; 894f59c8f9fSMark Brown else if (bypass) 895f59c8f9fSMark Brown report = "enabled"; 896f59c8f9fSMark Brown else 897f59c8f9fSMark Brown report = "disabled"; 898f59c8f9fSMark Brown 899f59c8f9fSMark Brown return sprintf(buf, "%s\n", report); 900f59c8f9fSMark Brown } 901f59c8f9fSMark Brown static DEVICE_ATTR(bypass, 0444, 902f59c8f9fSMark Brown regulator_bypass_show, NULL); 9037ad68e2fSDavid Brownell 904414c70cbSLiam Girdwood /* Calculate the new optimum regulator operating mode based on the new total 905414c70cbSLiam Girdwood * consumer load. All locks held by caller */ 9068460ef38SBjorn Andersson static int drms_uA_update(struct regulator_dev *rdev) 907414c70cbSLiam Girdwood { 908414c70cbSLiam Girdwood struct regulator *sibling; 909414c70cbSLiam Girdwood int current_uA = 0, output_uV, input_uV, err; 910414c70cbSLiam Girdwood unsigned int mode; 911414c70cbSLiam Girdwood 9128460ef38SBjorn Andersson /* 9138460ef38SBjorn Andersson * first check to see if we can set modes at all, otherwise just 9148460ef38SBjorn Andersson * tell the consumer everything is OK. 9158460ef38SBjorn Andersson */ 91674a569eeSMarc Gonzalez if (!regulator_ops_is_valid(rdev, REGULATOR_CHANGE_DRMS)) { 91774a569eeSMarc Gonzalez rdev_dbg(rdev, "DRMS operation not allowed\n"); 9188460ef38SBjorn Andersson return 0; 91974a569eeSMarc Gonzalez } 9208460ef38SBjorn Andersson 9218f4490e0SBjorn Andersson if (!rdev->desc->ops->get_optimum_mode && 9228f4490e0SBjorn Andersson !rdev->desc->ops->set_load) 9238460ef38SBjorn Andersson return 0; 9248460ef38SBjorn Andersson 9258f4490e0SBjorn Andersson if (!rdev->desc->ops->set_mode && 9268f4490e0SBjorn Andersson !rdev->desc->ops->set_load) 9278460ef38SBjorn Andersson return -EINVAL; 928414c70cbSLiam Girdwood 92957776617SJoonwoo Park /* calc total requested load */ 9305451781dSDouglas Anderson list_for_each_entry(sibling, &rdev->consumer_list, list) { 9315451781dSDouglas Anderson if (sibling->enable_count) 93257776617SJoonwoo Park current_uA += sibling->uA_load; 9335451781dSDouglas Anderson } 93457776617SJoonwoo Park 93557776617SJoonwoo Park current_uA += rdev->constraints->system_load; 93657776617SJoonwoo Park 93757776617SJoonwoo Park if (rdev->desc->ops->set_load) { 93857776617SJoonwoo Park /* set the optimum mode for our new total regulator load */ 93957776617SJoonwoo Park err = rdev->desc->ops->set_load(rdev, current_uA); 94057776617SJoonwoo Park if (err < 0) 94157776617SJoonwoo Park rdev_err(rdev, "failed to set load %d\n", current_uA); 94257776617SJoonwoo Park } else { 943414c70cbSLiam Girdwood /* get output voltage */ 9441bf5a1f8SMark Brown output_uV = _regulator_get_voltage(rdev); 9458460ef38SBjorn Andersson if (output_uV <= 0) { 9468460ef38SBjorn Andersson rdev_err(rdev, "invalid output voltage found\n"); 9478460ef38SBjorn Andersson return -EINVAL; 9488460ef38SBjorn Andersson } 949414c70cbSLiam Girdwood 950414c70cbSLiam Girdwood /* get input voltage */ 9511bf5a1f8SMark Brown input_uV = 0; 9521bf5a1f8SMark Brown if (rdev->supply) 9533f24f5adSAxel Lin input_uV = regulator_get_voltage(rdev->supply); 9541bf5a1f8SMark Brown if (input_uV <= 0) 955414c70cbSLiam Girdwood input_uV = rdev->constraints->input_uV; 9568460ef38SBjorn Andersson if (input_uV <= 0) { 9578460ef38SBjorn Andersson rdev_err(rdev, "invalid input voltage found\n"); 9588460ef38SBjorn Andersson return -EINVAL; 9598460ef38SBjorn Andersson } 960414c70cbSLiam Girdwood 961414c70cbSLiam Girdwood /* now get the optimum mode for our new total regulator load */ 962414c70cbSLiam Girdwood mode = rdev->desc->ops->get_optimum_mode(rdev, input_uV, 963414c70cbSLiam Girdwood output_uV, current_uA); 964414c70cbSLiam Girdwood 965414c70cbSLiam Girdwood /* check the new mode is allowed */ 9662c608234SMark Brown err = regulator_mode_constrain(rdev, &mode); 9678460ef38SBjorn Andersson if (err < 0) { 9688460ef38SBjorn Andersson rdev_err(rdev, "failed to get optimum mode @ %d uA %d -> %d uV\n", 9698460ef38SBjorn Andersson current_uA, input_uV, output_uV); 9708460ef38SBjorn Andersson return err; 9718460ef38SBjorn Andersson } 9728460ef38SBjorn Andersson 9738460ef38SBjorn Andersson err = rdev->desc->ops->set_mode(rdev, mode); 9748460ef38SBjorn Andersson if (err < 0) 9758460ef38SBjorn Andersson rdev_err(rdev, "failed to set optimum mode %x\n", mode); 9768f4490e0SBjorn Andersson } 9778460ef38SBjorn Andersson 9788460ef38SBjorn Andersson return err; 979414c70cbSLiam Girdwood } 980414c70cbSLiam Girdwood 981414c70cbSLiam Girdwood static int suspend_set_state(struct regulator_dev *rdev, 982f7efad10SChunyan Zhang suspend_state_t state) 983414c70cbSLiam Girdwood { 984414c70cbSLiam Girdwood int ret = 0; 985f7efad10SChunyan Zhang struct regulator_state *rstate; 986f7efad10SChunyan Zhang 987f7efad10SChunyan Zhang rstate = regulator_get_suspend_state(rdev, state); 988f7efad10SChunyan Zhang if (rstate == NULL) 98957a0dd18SMark Brown return 0; 990638f85c5SMark Brown 99148f1b4efSKrzysztof Kozlowski /* If we have no suspend mode configuration don't set anything; 9928ac0e95dSAxel Lin * only warn if the driver implements set_suspend_voltage or 9938ac0e95dSAxel Lin * set_suspend_mode callback. 994638f85c5SMark Brown */ 99572069f99SChunyan Zhang if (rstate->enabled != ENABLE_IN_SUSPEND && 99672069f99SChunyan Zhang rstate->enabled != DISABLE_IN_SUSPEND) { 9978ac0e95dSAxel Lin if (rdev->desc->ops->set_suspend_voltage || 9988ac0e95dSAxel Lin rdev->desc->ops->set_suspend_mode) 9995da84fd9SJoe Perches rdev_warn(rdev, "No configuration\n"); 1000638f85c5SMark Brown return 0; 1001638f85c5SMark Brown } 1002638f85c5SMark Brown 100372069f99SChunyan Zhang if (rstate->enabled == ENABLE_IN_SUSPEND && 100472069f99SChunyan Zhang rdev->desc->ops->set_suspend_enable) 1005414c70cbSLiam Girdwood ret = rdev->desc->ops->set_suspend_enable(rdev); 100672069f99SChunyan Zhang else if (rstate->enabled == DISABLE_IN_SUSPEND && 100772069f99SChunyan Zhang rdev->desc->ops->set_suspend_disable) 1008414c70cbSLiam Girdwood ret = rdev->desc->ops->set_suspend_disable(rdev); 10098ac0e95dSAxel Lin else /* OK if set_suspend_enable or set_suspend_disable is NULL */ 10108ac0e95dSAxel Lin ret = 0; 10118ac0e95dSAxel Lin 1012414c70cbSLiam Girdwood if (ret < 0) { 10135da84fd9SJoe Perches rdev_err(rdev, "failed to enabled/disable\n"); 1014414c70cbSLiam Girdwood return ret; 1015414c70cbSLiam Girdwood } 1016414c70cbSLiam Girdwood 1017414c70cbSLiam Girdwood if (rdev->desc->ops->set_suspend_voltage && rstate->uV > 0) { 1018414c70cbSLiam Girdwood ret = rdev->desc->ops->set_suspend_voltage(rdev, rstate->uV); 1019414c70cbSLiam Girdwood if (ret < 0) { 10205da84fd9SJoe Perches rdev_err(rdev, "failed to set voltage\n"); 1021414c70cbSLiam Girdwood return ret; 1022414c70cbSLiam Girdwood } 1023414c70cbSLiam Girdwood } 1024414c70cbSLiam Girdwood 1025414c70cbSLiam Girdwood if (rdev->desc->ops->set_suspend_mode && rstate->mode > 0) { 1026414c70cbSLiam Girdwood ret = rdev->desc->ops->set_suspend_mode(rdev, rstate->mode); 1027414c70cbSLiam Girdwood if (ret < 0) { 10285da84fd9SJoe Perches rdev_err(rdev, "failed to set mode\n"); 1029414c70cbSLiam Girdwood return ret; 1030414c70cbSLiam Girdwood } 1031414c70cbSLiam Girdwood } 1032f7efad10SChunyan Zhang 1033414c70cbSLiam Girdwood return ret; 1034414c70cbSLiam Girdwood } 1035414c70cbSLiam Girdwood 1036414c70cbSLiam Girdwood static void print_constraints(struct regulator_dev *rdev) 1037414c70cbSLiam Girdwood { 1038414c70cbSLiam Girdwood struct regulation_constraints *constraints = rdev->constraints; 1039a7068e39SStefan Wahren char buf[160] = ""; 10405751a99fSStefan Wahren size_t len = sizeof(buf) - 1; 10418f031b48SMark Brown int count = 0; 10428f031b48SMark Brown int ret; 1043414c70cbSLiam Girdwood 10448f031b48SMark Brown if (constraints->min_uV && constraints->max_uV) { 1045414c70cbSLiam Girdwood if (constraints->min_uV == constraints->max_uV) 10465751a99fSStefan Wahren count += scnprintf(buf + count, len - count, "%d mV ", 1047414c70cbSLiam Girdwood constraints->min_uV / 1000); 1048414c70cbSLiam Girdwood else 10495751a99fSStefan Wahren count += scnprintf(buf + count, len - count, 10505751a99fSStefan Wahren "%d <--> %d mV ", 1051414c70cbSLiam Girdwood constraints->min_uV / 1000, 1052414c70cbSLiam Girdwood constraints->max_uV / 1000); 10538f031b48SMark Brown } 10548f031b48SMark Brown 10558f031b48SMark Brown if (!constraints->min_uV || 10568f031b48SMark Brown constraints->min_uV != constraints->max_uV) { 10578f031b48SMark Brown ret = _regulator_get_voltage(rdev); 10588f031b48SMark Brown if (ret > 0) 10595751a99fSStefan Wahren count += scnprintf(buf + count, len - count, 10605751a99fSStefan Wahren "at %d mV ", ret / 1000); 10618f031b48SMark Brown } 10628f031b48SMark Brown 1063bf5892a8SMark Brown if (constraints->uV_offset) 10645751a99fSStefan Wahren count += scnprintf(buf + count, len - count, "%dmV offset ", 1065bf5892a8SMark Brown constraints->uV_offset / 1000); 1066bf5892a8SMark Brown 10678f031b48SMark Brown if (constraints->min_uA && constraints->max_uA) { 1068414c70cbSLiam Girdwood if (constraints->min_uA == constraints->max_uA) 10695751a99fSStefan Wahren count += scnprintf(buf + count, len - count, "%d mA ", 1070414c70cbSLiam Girdwood constraints->min_uA / 1000); 1071414c70cbSLiam Girdwood else 10725751a99fSStefan Wahren count += scnprintf(buf + count, len - count, 10735751a99fSStefan Wahren "%d <--> %d mA ", 1074414c70cbSLiam Girdwood constraints->min_uA / 1000, 1075414c70cbSLiam Girdwood constraints->max_uA / 1000); 1076414c70cbSLiam Girdwood } 10778f031b48SMark Brown 10788f031b48SMark Brown if (!constraints->min_uA || 10798f031b48SMark Brown constraints->min_uA != constraints->max_uA) { 10808f031b48SMark Brown ret = _regulator_get_current_limit(rdev); 10818f031b48SMark Brown if (ret > 0) 10825751a99fSStefan Wahren count += scnprintf(buf + count, len - count, 10835751a99fSStefan Wahren "at %d mA ", ret / 1000); 10848f031b48SMark Brown } 10858f031b48SMark Brown 1086414c70cbSLiam Girdwood if (constraints->valid_modes_mask & REGULATOR_MODE_FAST) 10875751a99fSStefan Wahren count += scnprintf(buf + count, len - count, "fast "); 1088414c70cbSLiam Girdwood if (constraints->valid_modes_mask & REGULATOR_MODE_NORMAL) 10895751a99fSStefan Wahren count += scnprintf(buf + count, len - count, "normal "); 1090414c70cbSLiam Girdwood if (constraints->valid_modes_mask & REGULATOR_MODE_IDLE) 10915751a99fSStefan Wahren count += scnprintf(buf + count, len - count, "idle "); 1092414c70cbSLiam Girdwood if (constraints->valid_modes_mask & REGULATOR_MODE_STANDBY) 10935751a99fSStefan Wahren count += scnprintf(buf + count, len - count, "standby"); 1094414c70cbSLiam Girdwood 1095215b8b05SUwe Kleine-König if (!count) 10965751a99fSStefan Wahren scnprintf(buf, len, "no parameters"); 1097215b8b05SUwe Kleine-König 1098194dbaefSMark Brown rdev_dbg(rdev, "%s\n", buf); 10994a682922SMark Brown 11004a682922SMark Brown if ((constraints->min_uV != constraints->max_uV) && 11018a34e979SWEN Pingbo !regulator_ops_is_valid(rdev, REGULATOR_CHANGE_VOLTAGE)) 11024a682922SMark Brown rdev_warn(rdev, 11034a682922SMark Brown "Voltage range but no REGULATOR_CHANGE_VOLTAGE\n"); 1104414c70cbSLiam Girdwood } 1105414c70cbSLiam Girdwood 1106e79055d6SMark Brown static int machine_constraints_voltage(struct regulator_dev *rdev, 11071083c393SMark Brown struct regulation_constraints *constraints) 1108e79055d6SMark Brown { 1109272e2315SGuodong Xu const struct regulator_ops *ops = rdev->desc->ops; 1110af5866c9SMark Brown int ret; 1111af5866c9SMark Brown 1112af5866c9SMark Brown /* do we need to apply the constraint voltage */ 1113af5866c9SMark Brown if (rdev->constraints->apply_uV && 1114fa93fd4eSMark Brown rdev->constraints->min_uV && rdev->constraints->max_uV) { 1115fa93fd4eSMark Brown int target_min, target_max; 1116064d5cd1SAlban Bedel int current_uV = _regulator_get_voltage(rdev); 111784b3a7c9SDouglas Anderson 111884b3a7c9SDouglas Anderson if (current_uV == -ENOTRECOVERABLE) { 111948f1b4efSKrzysztof Kozlowski /* This regulator can't be read and must be initialized */ 112084b3a7c9SDouglas Anderson rdev_info(rdev, "Setting %d-%duV\n", 112184b3a7c9SDouglas Anderson rdev->constraints->min_uV, 112284b3a7c9SDouglas Anderson rdev->constraints->max_uV); 112384b3a7c9SDouglas Anderson _regulator_do_set_voltage(rdev, 112484b3a7c9SDouglas Anderson rdev->constraints->min_uV, 112584b3a7c9SDouglas Anderson rdev->constraints->max_uV); 112684b3a7c9SDouglas Anderson current_uV = _regulator_get_voltage(rdev); 112784b3a7c9SDouglas Anderson } 112884b3a7c9SDouglas Anderson 1129064d5cd1SAlban Bedel if (current_uV < 0) { 113069d58839SNishanth Menon rdev_err(rdev, 113169d58839SNishanth Menon "failed to get the current voltage(%d)\n", 113269d58839SNishanth Menon current_uV); 1133064d5cd1SAlban Bedel return current_uV; 1134064d5cd1SAlban Bedel } 1135fa93fd4eSMark Brown 1136fa93fd4eSMark Brown /* 1137fa93fd4eSMark Brown * If we're below the minimum voltage move up to the 1138fa93fd4eSMark Brown * minimum voltage, if we're above the maximum voltage 1139fa93fd4eSMark Brown * then move down to the maximum. 1140fa93fd4eSMark Brown */ 1141fa93fd4eSMark Brown target_min = current_uV; 1142fa93fd4eSMark Brown target_max = current_uV; 1143fa93fd4eSMark Brown 1144fa93fd4eSMark Brown if (current_uV < rdev->constraints->min_uV) { 1145fa93fd4eSMark Brown target_min = rdev->constraints->min_uV; 1146fa93fd4eSMark Brown target_max = rdev->constraints->min_uV; 1147fa93fd4eSMark Brown } 1148fa93fd4eSMark Brown 1149fa93fd4eSMark Brown if (current_uV > rdev->constraints->max_uV) { 1150fa93fd4eSMark Brown target_min = rdev->constraints->max_uV; 1151fa93fd4eSMark Brown target_max = rdev->constraints->max_uV; 1152fa93fd4eSMark Brown } 1153fa93fd4eSMark Brown 1154fa93fd4eSMark Brown if (target_min != current_uV || target_max != current_uV) { 115545a91e8fSMark Brown rdev_info(rdev, "Bringing %duV into %d-%duV\n", 115645a91e8fSMark Brown current_uV, target_min, target_max); 1157064d5cd1SAlban Bedel ret = _regulator_do_set_voltage( 1158fa93fd4eSMark Brown rdev, target_min, target_max); 1159af5866c9SMark Brown if (ret < 0) { 1160064d5cd1SAlban Bedel rdev_err(rdev, 1161fa93fd4eSMark Brown "failed to apply %d-%duV constraint(%d)\n", 1162fa93fd4eSMark Brown target_min, target_max, ret); 1163af5866c9SMark Brown return ret; 1164af5866c9SMark Brown } 1165af5866c9SMark Brown } 1166064d5cd1SAlban Bedel } 1167e79055d6SMark Brown 1168e79055d6SMark Brown /* constrain machine-level voltage specs to fit 1169e79055d6SMark Brown * the actual range supported by this regulator. 1170e79055d6SMark Brown */ 1171e79055d6SMark Brown if (ops->list_voltage && rdev->desc->n_voltages) { 1172e79055d6SMark Brown int count = rdev->desc->n_voltages; 1173e79055d6SMark Brown int i; 1174e79055d6SMark Brown int min_uV = INT_MAX; 1175e79055d6SMark Brown int max_uV = INT_MIN; 1176e79055d6SMark Brown int cmin = constraints->min_uV; 1177e79055d6SMark Brown int cmax = constraints->max_uV; 1178e79055d6SMark Brown 1179e79055d6SMark Brown /* it's safe to autoconfigure fixed-voltage supplies 1180e79055d6SMark Brown and the constraints are used by list_voltage. */ 1181e79055d6SMark Brown if (count == 1 && !cmin) { 1182e79055d6SMark Brown cmin = 1; 1183e79055d6SMark Brown cmax = INT_MAX; 1184e79055d6SMark Brown constraints->min_uV = cmin; 1185e79055d6SMark Brown constraints->max_uV = cmax; 1186e79055d6SMark Brown } 1187e79055d6SMark Brown 1188e79055d6SMark Brown /* voltage constraints are optional */ 1189e79055d6SMark Brown if ((cmin == 0) && (cmax == 0)) 1190e79055d6SMark Brown return 0; 1191e79055d6SMark Brown 1192e79055d6SMark Brown /* else require explicit machine-level constraints */ 1193e79055d6SMark Brown if (cmin <= 0 || cmax <= 0 || cmax < cmin) { 11945da84fd9SJoe Perches rdev_err(rdev, "invalid voltage constraints\n"); 1195e79055d6SMark Brown return -EINVAL; 1196e79055d6SMark Brown } 1197e79055d6SMark Brown 1198e79055d6SMark Brown /* initial: [cmin..cmax] valid, [min_uV..max_uV] not */ 1199e79055d6SMark Brown for (i = 0; i < count; i++) { 1200e79055d6SMark Brown int value; 1201e79055d6SMark Brown 1202e79055d6SMark Brown value = ops->list_voltage(rdev, i); 1203e79055d6SMark Brown if (value <= 0) 1204e79055d6SMark Brown continue; 1205e79055d6SMark Brown 1206e79055d6SMark Brown /* maybe adjust [min_uV..max_uV] */ 1207e79055d6SMark Brown if (value >= cmin && value < min_uV) 1208e79055d6SMark Brown min_uV = value; 1209e79055d6SMark Brown if (value <= cmax && value > max_uV) 1210e79055d6SMark Brown max_uV = value; 1211e79055d6SMark Brown } 1212e79055d6SMark Brown 1213e79055d6SMark Brown /* final: [min_uV..max_uV] valid iff constraints valid */ 1214e79055d6SMark Brown if (max_uV < min_uV) { 1215fff15befSMark Brown rdev_err(rdev, 1216fff15befSMark Brown "unsupportable voltage constraints %u-%uuV\n", 1217fff15befSMark Brown min_uV, max_uV); 1218e79055d6SMark Brown return -EINVAL; 1219e79055d6SMark Brown } 1220e79055d6SMark Brown 1221e79055d6SMark Brown /* use regulator's subset of machine constraints */ 1222e79055d6SMark Brown if (constraints->min_uV < min_uV) { 12235da84fd9SJoe Perches rdev_dbg(rdev, "override min_uV, %d -> %d\n", 12245da84fd9SJoe Perches constraints->min_uV, min_uV); 1225e79055d6SMark Brown constraints->min_uV = min_uV; 1226e79055d6SMark Brown } 1227e79055d6SMark Brown if (constraints->max_uV > max_uV) { 12285da84fd9SJoe Perches rdev_dbg(rdev, "override max_uV, %d -> %d\n", 12295da84fd9SJoe Perches constraints->max_uV, max_uV); 1230e79055d6SMark Brown constraints->max_uV = max_uV; 1231e79055d6SMark Brown } 1232e79055d6SMark Brown } 1233e79055d6SMark Brown 1234e79055d6SMark Brown return 0; 1235e79055d6SMark Brown } 1236e79055d6SMark Brown 1237f8c1700dSLaxman Dewangan static int machine_constraints_current(struct regulator_dev *rdev, 1238f8c1700dSLaxman Dewangan struct regulation_constraints *constraints) 1239f8c1700dSLaxman Dewangan { 1240272e2315SGuodong Xu const struct regulator_ops *ops = rdev->desc->ops; 1241f8c1700dSLaxman Dewangan int ret; 1242f8c1700dSLaxman Dewangan 1243f8c1700dSLaxman Dewangan if (!constraints->min_uA && !constraints->max_uA) 1244f8c1700dSLaxman Dewangan return 0; 1245f8c1700dSLaxman Dewangan 1246f8c1700dSLaxman Dewangan if (constraints->min_uA > constraints->max_uA) { 1247f8c1700dSLaxman Dewangan rdev_err(rdev, "Invalid current constraints\n"); 1248f8c1700dSLaxman Dewangan return -EINVAL; 1249f8c1700dSLaxman Dewangan } 1250f8c1700dSLaxman Dewangan 1251f8c1700dSLaxman Dewangan if (!ops->set_current_limit || !ops->get_current_limit) { 1252f8c1700dSLaxman Dewangan rdev_warn(rdev, "Operation of current configuration missing\n"); 1253f8c1700dSLaxman Dewangan return 0; 1254f8c1700dSLaxman Dewangan } 1255f8c1700dSLaxman Dewangan 1256f8c1700dSLaxman Dewangan /* Set regulator current in constraints range */ 1257f8c1700dSLaxman Dewangan ret = ops->set_current_limit(rdev, constraints->min_uA, 1258f8c1700dSLaxman Dewangan constraints->max_uA); 1259f8c1700dSLaxman Dewangan if (ret < 0) { 1260f8c1700dSLaxman Dewangan rdev_err(rdev, "Failed to set current constraint, %d\n", ret); 1261f8c1700dSLaxman Dewangan return ret; 1262f8c1700dSLaxman Dewangan } 1263f8c1700dSLaxman Dewangan 1264f8c1700dSLaxman Dewangan return 0; 1265f8c1700dSLaxman Dewangan } 1266f8c1700dSLaxman Dewangan 126730c21971SMarkus Pargmann static int _regulator_do_enable(struct regulator_dev *rdev); 126830c21971SMarkus Pargmann 1269a5766f11SLiam Girdwood /** 1270a5766f11SLiam Girdwood * set_machine_constraints - sets regulator constraints 127169279fb9SMark Brown * @rdev: regulator source 1272c8e7e464SMark Brown * @constraints: constraints to apply 1273a5766f11SLiam Girdwood * 1274a5766f11SLiam Girdwood * Allows platform initialisation code to define and constrain 1275a5766f11SLiam Girdwood * regulator circuits e.g. valid voltage/current ranges, etc. NOTE: 1276a5766f11SLiam Girdwood * Constraints *must* be set by platform code in order for some 1277a5766f11SLiam Girdwood * regulator operations to proceed i.e. set_voltage, set_current_limit, 1278a5766f11SLiam Girdwood * set_mode. 1279a5766f11SLiam Girdwood */ 1280a5766f11SLiam Girdwood static int set_machine_constraints(struct regulator_dev *rdev, 1281f8c12fe3SMark Brown const struct regulation_constraints *constraints) 1282a5766f11SLiam Girdwood { 1283a5766f11SLiam Girdwood int ret = 0; 1284272e2315SGuodong Xu const struct regulator_ops *ops = rdev->desc->ops; 1285e06f5b4fSMark Brown 12869a8f5e07SMark Brown if (constraints) 1287f8c12fe3SMark Brown rdev->constraints = kmemdup(constraints, sizeof(*constraints), 1288f8c12fe3SMark Brown GFP_KERNEL); 12899a8f5e07SMark Brown else 12909a8f5e07SMark Brown rdev->constraints = kzalloc(sizeof(*constraints), 12919a8f5e07SMark Brown GFP_KERNEL); 1292f8c12fe3SMark Brown if (!rdev->constraints) 1293f8c12fe3SMark Brown return -ENOMEM; 1294af5866c9SMark Brown 1295f8c12fe3SMark Brown ret = machine_constraints_voltage(rdev, rdev->constraints); 1296e79055d6SMark Brown if (ret != 0) 12976333ef46SCharles Keepax return ret; 12983e2b9abdSMark Brown 1299f8c1700dSLaxman Dewangan ret = machine_constraints_current(rdev, rdev->constraints); 1300f8c1700dSLaxman Dewangan if (ret != 0) 13016333ef46SCharles Keepax return ret; 1302f8c1700dSLaxman Dewangan 130336e4f839SStephen Boyd if (rdev->constraints->ilim_uA && ops->set_input_current_limit) { 130436e4f839SStephen Boyd ret = ops->set_input_current_limit(rdev, 130536e4f839SStephen Boyd rdev->constraints->ilim_uA); 130636e4f839SStephen Boyd if (ret < 0) { 130736e4f839SStephen Boyd rdev_err(rdev, "failed to set input limit\n"); 13086333ef46SCharles Keepax return ret; 130936e4f839SStephen Boyd } 131036e4f839SStephen Boyd } 131136e4f839SStephen Boyd 1312a5766f11SLiam Girdwood /* do we need to setup our suspend state */ 13139a8f5e07SMark Brown if (rdev->constraints->initial_state) { 1314f7efad10SChunyan Zhang ret = suspend_set_state(rdev, rdev->constraints->initial_state); 1315e06f5b4fSMark Brown if (ret < 0) { 13165da84fd9SJoe Perches rdev_err(rdev, "failed to set suspend state\n"); 13176333ef46SCharles Keepax return ret; 1318e06f5b4fSMark Brown } 1319e06f5b4fSMark Brown } 1320a5766f11SLiam Girdwood 13219a8f5e07SMark Brown if (rdev->constraints->initial_mode) { 1322a308466cSMark Brown if (!ops->set_mode) { 13235da84fd9SJoe Perches rdev_err(rdev, "no set_mode operation\n"); 13246333ef46SCharles Keepax return -EINVAL; 1325a308466cSMark Brown } 1326a308466cSMark Brown 1327f8c12fe3SMark Brown ret = ops->set_mode(rdev, rdev->constraints->initial_mode); 1328a308466cSMark Brown if (ret < 0) { 13295da84fd9SJoe Perches rdev_err(rdev, "failed to set initial mode: %d\n", ret); 13306333ef46SCharles Keepax return ret; 1331a308466cSMark Brown } 1332fa94e48eSDouglas Anderson } else if (rdev->constraints->system_load) { 1333fa94e48eSDouglas Anderson /* 1334fa94e48eSDouglas Anderson * We'll only apply the initial system load if an 1335fa94e48eSDouglas Anderson * initial mode wasn't specified. 1336fa94e48eSDouglas Anderson */ 1337fa94e48eSDouglas Anderson drms_uA_update(rdev); 1338a308466cSMark Brown } 1339a308466cSMark Brown 13401653ccf4SYadwinder Singh Brar if ((rdev->constraints->ramp_delay || rdev->constraints->ramp_disable) 13411653ccf4SYadwinder Singh Brar && ops->set_ramp_delay) { 13426f0b2c69SYadwinder Singh Brar ret = ops->set_ramp_delay(rdev, rdev->constraints->ramp_delay); 13436f0b2c69SYadwinder Singh Brar if (ret < 0) { 13446f0b2c69SYadwinder Singh Brar rdev_err(rdev, "failed to set ramp_delay\n"); 13456333ef46SCharles Keepax return ret; 13466f0b2c69SYadwinder Singh Brar } 13476f0b2c69SYadwinder Singh Brar } 13486f0b2c69SYadwinder Singh Brar 134923c779b9SStephen Boyd if (rdev->constraints->pull_down && ops->set_pull_down) { 135023c779b9SStephen Boyd ret = ops->set_pull_down(rdev); 135123c779b9SStephen Boyd if (ret < 0) { 135223c779b9SStephen Boyd rdev_err(rdev, "failed to set pull down\n"); 13536333ef46SCharles Keepax return ret; 135423c779b9SStephen Boyd } 135523c779b9SStephen Boyd } 135623c779b9SStephen Boyd 135757f66b78SStephen Boyd if (rdev->constraints->soft_start && ops->set_soft_start) { 135857f66b78SStephen Boyd ret = ops->set_soft_start(rdev); 135957f66b78SStephen Boyd if (ret < 0) { 136057f66b78SStephen Boyd rdev_err(rdev, "failed to set soft start\n"); 13616333ef46SCharles Keepax return ret; 136257f66b78SStephen Boyd } 136357f66b78SStephen Boyd } 136457f66b78SStephen Boyd 13653a003baeSStephen Boyd if (rdev->constraints->over_current_protection 13663a003baeSStephen Boyd && ops->set_over_current_protection) { 13673a003baeSStephen Boyd ret = ops->set_over_current_protection(rdev); 13683a003baeSStephen Boyd if (ret < 0) { 13693a003baeSStephen Boyd rdev_err(rdev, "failed to set over current protection\n"); 13706333ef46SCharles Keepax return ret; 13713a003baeSStephen Boyd } 13723a003baeSStephen Boyd } 13733a003baeSStephen Boyd 1374670666b9SLaxman Dewangan if (rdev->constraints->active_discharge && ops->set_active_discharge) { 1375670666b9SLaxman Dewangan bool ad_state = (rdev->constraints->active_discharge == 1376670666b9SLaxman Dewangan REGULATOR_ACTIVE_DISCHARGE_ENABLE) ? true : false; 1377670666b9SLaxman Dewangan 1378670666b9SLaxman Dewangan ret = ops->set_active_discharge(rdev, ad_state); 1379670666b9SLaxman Dewangan if (ret < 0) { 1380670666b9SLaxman Dewangan rdev_err(rdev, "failed to set active discharge\n"); 1381670666b9SLaxman Dewangan return ret; 1382670666b9SLaxman Dewangan } 1383670666b9SLaxman Dewangan } 1384670666b9SLaxman Dewangan 13852bb16663SOlliver Schinagl /* If the constraints say the regulator should be on at this point 13862bb16663SOlliver Schinagl * and we have control then make sure it is enabled. 13872bb16663SOlliver Schinagl */ 13882bb16663SOlliver Schinagl if (rdev->constraints->always_on || rdev->constraints->boot_on) { 138905f224caSDouglas Anderson if (rdev->supply) { 139005f224caSDouglas Anderson ret = regulator_enable(rdev->supply); 139105f224caSDouglas Anderson if (ret < 0) { 139205f224caSDouglas Anderson _regulator_put(rdev->supply); 139305f224caSDouglas Anderson rdev->supply = NULL; 139405f224caSDouglas Anderson return ret; 139505f224caSDouglas Anderson } 139605f224caSDouglas Anderson } 139705f224caSDouglas Anderson 13982bb16663SOlliver Schinagl ret = _regulator_do_enable(rdev); 13992bb16663SOlliver Schinagl if (ret < 0 && ret != -EINVAL) { 14002bb16663SOlliver Schinagl rdev_err(rdev, "failed to enable\n"); 14012bb16663SOlliver Schinagl return ret; 14022bb16663SOlliver Schinagl } 140305f224caSDouglas Anderson rdev->use_count++; 14042bb16663SOlliver Schinagl } 14052bb16663SOlliver Schinagl 1406a5766f11SLiam Girdwood print_constraints(rdev); 14071a6958e7SAxel Lin return 0; 1408a5766f11SLiam Girdwood } 1409a5766f11SLiam Girdwood 1410a5766f11SLiam Girdwood /** 1411a5766f11SLiam Girdwood * set_supply - set regulator supply regulator 141269279fb9SMark Brown * @rdev: regulator name 141369279fb9SMark Brown * @supply_rdev: supply regulator name 1414a5766f11SLiam Girdwood * 1415a5766f11SLiam Girdwood * Called by platform initialisation code to set the supply regulator for this 1416a5766f11SLiam Girdwood * regulator. This ensures that a regulators supply will also be enabled by the 1417a5766f11SLiam Girdwood * core if it's child is enabled. 1418a5766f11SLiam Girdwood */ 1419a5766f11SLiam Girdwood static int set_supply(struct regulator_dev *rdev, 1420a5766f11SLiam Girdwood struct regulator_dev *supply_rdev) 1421a5766f11SLiam Girdwood { 1422a5766f11SLiam Girdwood int err; 1423a5766f11SLiam Girdwood 14243801b86aSMark Brown rdev_info(rdev, "supplied by %s\n", rdev_get_name(supply_rdev)); 14253801b86aSMark Brown 1426e2c09ae7SJavier Martinez Canillas if (!try_module_get(supply_rdev->owner)) 1427e2c09ae7SJavier Martinez Canillas return -ENODEV; 1428e2c09ae7SJavier Martinez Canillas 14293801b86aSMark Brown rdev->supply = create_regulator(supply_rdev, &rdev->dev, "SUPPLY"); 143032c78de8SAxel Lin if (rdev->supply == NULL) { 143132c78de8SAxel Lin err = -ENOMEM; 1432a5766f11SLiam Girdwood return err; 1433a5766f11SLiam Girdwood } 143457ad526aSLaxman Dewangan supply_rdev->open_count++; 1435a5766f11SLiam Girdwood 14363801b86aSMark Brown return 0; 14373801b86aSMark Brown } 14383801b86aSMark Brown 1439a5766f11SLiam Girdwood /** 144006c63f93SRandy Dunlap * set_consumer_device_supply - Bind a regulator to a symbolic supply 144169279fb9SMark Brown * @rdev: regulator source 144240f9244fSMark Brown * @consumer_dev_name: dev_name() string for device supply applies to 1443a5766f11SLiam Girdwood * @supply: symbolic name for supply 1444a5766f11SLiam Girdwood * 1445a5766f11SLiam Girdwood * Allows platform initialisation code to map physical regulator 1446a5766f11SLiam Girdwood * sources to symbolic names for supplies for use by devices. Devices 1447a5766f11SLiam Girdwood * should use these symbolic names to request regulators, avoiding the 1448a5766f11SLiam Girdwood * need to provide board-specific regulator names as platform data. 1449a5766f11SLiam Girdwood */ 1450a5766f11SLiam Girdwood static int set_consumer_device_supply(struct regulator_dev *rdev, 1451737f360dSMark Brown const char *consumer_dev_name, 145240f9244fSMark Brown const char *supply) 1453a5766f11SLiam Girdwood { 1454a5766f11SLiam Girdwood struct regulator_map *node; 14559ed2099eSMark Brown int has_dev; 1456a5766f11SLiam Girdwood 1457a5766f11SLiam Girdwood if (supply == NULL) 1458a5766f11SLiam Girdwood return -EINVAL; 1459a5766f11SLiam Girdwood 14609ed2099eSMark Brown if (consumer_dev_name != NULL) 14619ed2099eSMark Brown has_dev = 1; 14629ed2099eSMark Brown else 14639ed2099eSMark Brown has_dev = 0; 14649ed2099eSMark Brown 14656001e13cSDavid Brownell list_for_each_entry(node, ®ulator_map_list, list) { 146623b5cc2aSJani Nikula if (node->dev_name && consumer_dev_name) { 146723b5cc2aSJani Nikula if (strcmp(node->dev_name, consumer_dev_name) != 0) 14686001e13cSDavid Brownell continue; 146923b5cc2aSJani Nikula } else if (node->dev_name || consumer_dev_name) { 147023b5cc2aSJani Nikula continue; 147123b5cc2aSJani Nikula } 147223b5cc2aSJani Nikula 14736001e13cSDavid Brownell if (strcmp(node->supply, supply) != 0) 14746001e13cSDavid Brownell continue; 14756001e13cSDavid Brownell 1476737f360dSMark Brown pr_debug("%s: %s/%s is '%s' supply; fail %s/%s\n", 1477737f360dSMark Brown consumer_dev_name, 14786001e13cSDavid Brownell dev_name(&node->regulator->dev), 14796001e13cSDavid Brownell node->regulator->desc->name, 14806001e13cSDavid Brownell supply, 14811083c393SMark Brown dev_name(&rdev->dev), rdev_get_name(rdev)); 14826001e13cSDavid Brownell return -EBUSY; 14836001e13cSDavid Brownell } 14846001e13cSDavid Brownell 14859ed2099eSMark Brown node = kzalloc(sizeof(struct regulator_map), GFP_KERNEL); 1486a5766f11SLiam Girdwood if (node == NULL) 1487a5766f11SLiam Girdwood return -ENOMEM; 1488a5766f11SLiam Girdwood 1489a5766f11SLiam Girdwood node->regulator = rdev; 1490a5766f11SLiam Girdwood node->supply = supply; 1491a5766f11SLiam Girdwood 14929ed2099eSMark Brown if (has_dev) { 14939ed2099eSMark Brown node->dev_name = kstrdup(consumer_dev_name, GFP_KERNEL); 149440f9244fSMark Brown if (node->dev_name == NULL) { 149540f9244fSMark Brown kfree(node); 149640f9244fSMark Brown return -ENOMEM; 149740f9244fSMark Brown } 14989ed2099eSMark Brown } 149940f9244fSMark Brown 1500a5766f11SLiam Girdwood list_add(&node->list, ®ulator_map_list); 1501a5766f11SLiam Girdwood return 0; 1502a5766f11SLiam Girdwood } 1503a5766f11SLiam Girdwood 15040f1d747bSMike Rapoport static void unset_regulator_supplies(struct regulator_dev *rdev) 15050f1d747bSMike Rapoport { 15060f1d747bSMike Rapoport struct regulator_map *node, *n; 15070f1d747bSMike Rapoport 15080f1d747bSMike Rapoport list_for_each_entry_safe(node, n, ®ulator_map_list, list) { 15090f1d747bSMike Rapoport if (rdev == node->regulator) { 15100f1d747bSMike Rapoport list_del(&node->list); 151140f9244fSMark Brown kfree(node->dev_name); 15120f1d747bSMike Rapoport kfree(node); 15130f1d747bSMike Rapoport } 15140f1d747bSMike Rapoport } 15150f1d747bSMike Rapoport } 15160f1d747bSMike Rapoport 15172d80a91bSRichard Fitzgerald #ifdef CONFIG_DEBUG_FS 15182d80a91bSRichard Fitzgerald static ssize_t constraint_flags_read_file(struct file *file, 15192d80a91bSRichard Fitzgerald char __user *user_buf, 15202d80a91bSRichard Fitzgerald size_t count, loff_t *ppos) 15212d80a91bSRichard Fitzgerald { 15222d80a91bSRichard Fitzgerald const struct regulator *regulator = file->private_data; 15232d80a91bSRichard Fitzgerald const struct regulation_constraints *c = regulator->rdev->constraints; 15242d80a91bSRichard Fitzgerald char *buf; 15252d80a91bSRichard Fitzgerald ssize_t ret; 15262d80a91bSRichard Fitzgerald 15272d80a91bSRichard Fitzgerald if (!c) 15282d80a91bSRichard Fitzgerald return 0; 15292d80a91bSRichard Fitzgerald 15302d80a91bSRichard Fitzgerald buf = kmalloc(PAGE_SIZE, GFP_KERNEL); 15312d80a91bSRichard Fitzgerald if (!buf) 15322d80a91bSRichard Fitzgerald return -ENOMEM; 15332d80a91bSRichard Fitzgerald 15342d80a91bSRichard Fitzgerald ret = snprintf(buf, PAGE_SIZE, 15352d80a91bSRichard Fitzgerald "always_on: %u\n" 15362d80a91bSRichard Fitzgerald "boot_on: %u\n" 15372d80a91bSRichard Fitzgerald "apply_uV: %u\n" 15382d80a91bSRichard Fitzgerald "ramp_disable: %u\n" 15392d80a91bSRichard Fitzgerald "soft_start: %u\n" 15402d80a91bSRichard Fitzgerald "pull_down: %u\n" 15412d80a91bSRichard Fitzgerald "over_current_protection: %u\n", 15422d80a91bSRichard Fitzgerald c->always_on, 15432d80a91bSRichard Fitzgerald c->boot_on, 15442d80a91bSRichard Fitzgerald c->apply_uV, 15452d80a91bSRichard Fitzgerald c->ramp_disable, 15462d80a91bSRichard Fitzgerald c->soft_start, 15472d80a91bSRichard Fitzgerald c->pull_down, 15482d80a91bSRichard Fitzgerald c->over_current_protection); 15492d80a91bSRichard Fitzgerald 15502d80a91bSRichard Fitzgerald ret = simple_read_from_buffer(user_buf, count, ppos, buf, ret); 15512d80a91bSRichard Fitzgerald kfree(buf); 15522d80a91bSRichard Fitzgerald 15532d80a91bSRichard Fitzgerald return ret; 15542d80a91bSRichard Fitzgerald } 15552d80a91bSRichard Fitzgerald 15562d80a91bSRichard Fitzgerald #endif 15572d80a91bSRichard Fitzgerald 15582d80a91bSRichard Fitzgerald static const struct file_operations constraint_flags_fops = { 15592d80a91bSRichard Fitzgerald #ifdef CONFIG_DEBUG_FS 15602d80a91bSRichard Fitzgerald .open = simple_open, 15612d80a91bSRichard Fitzgerald .read = constraint_flags_read_file, 15622d80a91bSRichard Fitzgerald .llseek = default_llseek, 15632d80a91bSRichard Fitzgerald #endif 15642d80a91bSRichard Fitzgerald }; 15652d80a91bSRichard Fitzgerald 1566f5726ae3SMark Brown #define REG_STR_SIZE 64 1567414c70cbSLiam Girdwood 1568414c70cbSLiam Girdwood static struct regulator *create_regulator(struct regulator_dev *rdev, 1569414c70cbSLiam Girdwood struct device *dev, 1570414c70cbSLiam Girdwood const char *supply_name) 1571414c70cbSLiam Girdwood { 1572414c70cbSLiam Girdwood struct regulator *regulator; 1573414c70cbSLiam Girdwood char buf[REG_STR_SIZE]; 1574414c70cbSLiam Girdwood int err, size; 1575414c70cbSLiam Girdwood 1576414c70cbSLiam Girdwood regulator = kzalloc(sizeof(*regulator), GFP_KERNEL); 1577414c70cbSLiam Girdwood if (regulator == NULL) 1578414c70cbSLiam Girdwood return NULL; 1579414c70cbSLiam Girdwood 158066cf9a7eSMaciej Purski regulator_lock(rdev); 1581414c70cbSLiam Girdwood regulator->rdev = rdev; 1582414c70cbSLiam Girdwood list_add(®ulator->list, &rdev->consumer_list); 1583414c70cbSLiam Girdwood 1584414c70cbSLiam Girdwood if (dev) { 1585e2c98eafSShawn Guo regulator->dev = dev; 1586e2c98eafSShawn Guo 1587222cc7b1SMark Brown /* Add a link to the device sysfs entry */ 1588b7cd1b13SBartosz Golaszewski size = snprintf(buf, REG_STR_SIZE, "%s-%s", 1589414c70cbSLiam Girdwood dev->kobj.name, supply_name); 1590414c70cbSLiam Girdwood if (size >= REG_STR_SIZE) 1591222cc7b1SMark Brown goto overflow_err; 1592414c70cbSLiam Girdwood 1593414c70cbSLiam Girdwood regulator->supply_name = kstrdup(buf, GFP_KERNEL); 1594414c70cbSLiam Girdwood if (regulator->supply_name == NULL) 1595222cc7b1SMark Brown goto overflow_err; 1596414c70cbSLiam Girdwood 1597ff268b56SStephen Boyd err = sysfs_create_link_nowarn(&rdev->dev.kobj, &dev->kobj, 1598414c70cbSLiam Girdwood buf); 1599414c70cbSLiam Girdwood if (err) { 1600ff268b56SStephen Boyd rdev_dbg(rdev, "could not add device link %s err %d\n", 16011d7372e1SDaniel Walker dev->kobj.name, err); 1602222cc7b1SMark Brown /* non-fatal */ 1603414c70cbSLiam Girdwood } 16045de70519SMark Brown } else { 16050630b614SStephen Boyd regulator->supply_name = kstrdup_const(supply_name, GFP_KERNEL); 16065de70519SMark Brown if (regulator->supply_name == NULL) 1607222cc7b1SMark Brown goto overflow_err; 1608414c70cbSLiam Girdwood } 16095de70519SMark Brown 16105de70519SMark Brown regulator->debugfs = debugfs_create_dir(regulator->supply_name, 16115de70519SMark Brown rdev->debugfs); 161224751434SStephen Boyd if (!regulator->debugfs) { 1613ad3a942bSStephen Boyd rdev_dbg(rdev, "Failed to create debugfs directory\n"); 16145de70519SMark Brown } else { 16155de70519SMark Brown debugfs_create_u32("uA_load", 0444, regulator->debugfs, 16165de70519SMark Brown ®ulator->uA_load); 16175de70519SMark Brown debugfs_create_u32("min_uV", 0444, regulator->debugfs, 1618c360a6dfSChunyan Zhang ®ulator->voltage[PM_SUSPEND_ON].min_uV); 16195de70519SMark Brown debugfs_create_u32("max_uV", 0444, regulator->debugfs, 1620c360a6dfSChunyan Zhang ®ulator->voltage[PM_SUSPEND_ON].max_uV); 16212d80a91bSRichard Fitzgerald debugfs_create_file("constraint_flags", 0444, 16222d80a91bSRichard Fitzgerald regulator->debugfs, regulator, 16232d80a91bSRichard Fitzgerald &constraint_flags_fops); 16245de70519SMark Brown } 16255de70519SMark Brown 16266492bc1bSMark Brown /* 16276492bc1bSMark Brown * Check now if the regulator is an always on regulator - if 16286492bc1bSMark Brown * it is then we don't need to do nearly so much work for 16296492bc1bSMark Brown * enable/disable calls. 16306492bc1bSMark Brown */ 16318a34e979SWEN Pingbo if (!regulator_ops_is_valid(rdev, REGULATOR_CHANGE_STATUS) && 16326492bc1bSMark Brown _regulator_is_enabled(rdev)) 16336492bc1bSMark Brown regulator->always_on = true; 16346492bc1bSMark Brown 163566cf9a7eSMaciej Purski regulator_unlock(rdev); 1636414c70cbSLiam Girdwood return regulator; 1637414c70cbSLiam Girdwood overflow_err: 1638414c70cbSLiam Girdwood list_del(®ulator->list); 1639414c70cbSLiam Girdwood kfree(regulator); 164066cf9a7eSMaciej Purski regulator_unlock(rdev); 1641414c70cbSLiam Girdwood return NULL; 1642414c70cbSLiam Girdwood } 1643414c70cbSLiam Girdwood 164431aae2beSMark Brown static int _regulator_get_enable_time(struct regulator_dev *rdev) 164531aae2beSMark Brown { 164600c877c6SLaxman Dewangan if (rdev->constraints && rdev->constraints->enable_time) 164700c877c6SLaxman Dewangan return rdev->constraints->enable_time; 164831aae2beSMark Brown if (!rdev->desc->ops->enable_time) 164979511ed3SMark Brown return rdev->desc->enable_time; 165031aae2beSMark Brown return rdev->desc->ops->enable_time(rdev); 165131aae2beSMark Brown } 165231aae2beSMark Brown 1653a06ccd9cSCharles Keepax static struct regulator_supply_alias *regulator_find_supply_alias( 1654a06ccd9cSCharles Keepax struct device *dev, const char *supply) 1655a06ccd9cSCharles Keepax { 1656a06ccd9cSCharles Keepax struct regulator_supply_alias *map; 1657a06ccd9cSCharles Keepax 1658a06ccd9cSCharles Keepax list_for_each_entry(map, ®ulator_supply_alias_list, list) 1659a06ccd9cSCharles Keepax if (map->src_dev == dev && strcmp(map->src_supply, supply) == 0) 1660a06ccd9cSCharles Keepax return map; 1661a06ccd9cSCharles Keepax 1662a06ccd9cSCharles Keepax return NULL; 1663a06ccd9cSCharles Keepax } 1664a06ccd9cSCharles Keepax 1665a06ccd9cSCharles Keepax static void regulator_supply_alias(struct device **dev, const char **supply) 1666a06ccd9cSCharles Keepax { 1667a06ccd9cSCharles Keepax struct regulator_supply_alias *map; 1668a06ccd9cSCharles Keepax 1669a06ccd9cSCharles Keepax map = regulator_find_supply_alias(*dev, *supply); 1670a06ccd9cSCharles Keepax if (map) { 1671a06ccd9cSCharles Keepax dev_dbg(*dev, "Mapping supply %s to %s,%s\n", 1672a06ccd9cSCharles Keepax *supply, map->alias_supply, 1673a06ccd9cSCharles Keepax dev_name(map->alias_dev)); 1674a06ccd9cSCharles Keepax *dev = map->alias_dev; 1675a06ccd9cSCharles Keepax *supply = map->alias_supply; 1676a06ccd9cSCharles Keepax } 1677a06ccd9cSCharles Keepax } 1678a06ccd9cSCharles Keepax 167985f3b431STomeu Vizoso static int regulator_match(struct device *dev, const void *data) 168085f3b431STomeu Vizoso { 168185f3b431STomeu Vizoso struct regulator_dev *r = dev_to_rdev(dev); 168285f3b431STomeu Vizoso 168385f3b431STomeu Vizoso return strcmp(rdev_get_name(r), data) == 0; 168485f3b431STomeu Vizoso } 168585f3b431STomeu Vizoso 168685f3b431STomeu Vizoso static struct regulator_dev *regulator_lookup_by_name(const char *name) 168785f3b431STomeu Vizoso { 168885f3b431STomeu Vizoso struct device *dev; 168985f3b431STomeu Vizoso 169085f3b431STomeu Vizoso dev = class_find_device(®ulator_class, NULL, name, regulator_match); 169185f3b431STomeu Vizoso 169285f3b431STomeu Vizoso return dev ? dev_to_rdev(dev) : NULL; 169385f3b431STomeu Vizoso } 169485f3b431STomeu Vizoso 169585f3b431STomeu Vizoso /** 169685f3b431STomeu Vizoso * regulator_dev_lookup - lookup a regulator device. 169785f3b431STomeu Vizoso * @dev: device for regulator "consumer". 169885f3b431STomeu Vizoso * @supply: Supply name or regulator ID. 169985f3b431STomeu Vizoso * 170085f3b431STomeu Vizoso * If successful, returns a struct regulator_dev that corresponds to the name 1701163478daSDmitry Torokhov * @supply and with the embedded struct device refcount incremented by one. 1702163478daSDmitry Torokhov * The refcount must be dropped by calling put_device(). 1703163478daSDmitry Torokhov * On failure one of the following ERR-PTR-encoded values is returned: 1704163478daSDmitry Torokhov * -ENODEV if lookup fails permanently, -EPROBE_DEFER if lookup could succeed 1705163478daSDmitry Torokhov * in the future. 170685f3b431STomeu Vizoso */ 170769511a45SRajendra Nayak static struct regulator_dev *regulator_dev_lookup(struct device *dev, 1708163478daSDmitry Torokhov const char *supply) 170969511a45SRajendra Nayak { 171006217197SCharles Keepax struct regulator_dev *r = NULL; 171169511a45SRajendra Nayak struct device_node *node; 1712576ca436SMark Brown struct regulator_map *map; 1713576ca436SMark Brown const char *devname = NULL; 171469511a45SRajendra Nayak 1715a06ccd9cSCharles Keepax regulator_supply_alias(&dev, &supply); 1716a06ccd9cSCharles Keepax 171769511a45SRajendra Nayak /* first do a dt based lookup */ 171869511a45SRajendra Nayak if (dev && dev->of_node) { 171969511a45SRajendra Nayak node = of_get_regulator(dev, supply); 17206d191a5fSMark Brown if (node) { 172185f3b431STomeu Vizoso r = of_find_regulator_by_node(node); 172285f3b431STomeu Vizoso if (r) 172369511a45SRajendra Nayak return r; 1724163478daSDmitry Torokhov 17256d191a5fSMark Brown /* 1726163478daSDmitry Torokhov * We have a node, but there is no device. 1727163478daSDmitry Torokhov * assume it has not registered yet. 17286d191a5fSMark Brown */ 1729163478daSDmitry Torokhov return ERR_PTR(-EPROBE_DEFER); 17306d191a5fSMark Brown } 173169511a45SRajendra Nayak } 173269511a45SRajendra Nayak 173369511a45SRajendra Nayak /* if not found, try doing it non-dt way */ 1734576ca436SMark Brown if (dev) 1735576ca436SMark Brown devname = dev_name(dev); 1736576ca436SMark Brown 173785f3b431STomeu Vizoso mutex_lock(®ulator_list_mutex); 1738576ca436SMark Brown list_for_each_entry(map, ®ulator_map_list, list) { 1739576ca436SMark Brown /* If the mapping has a device set up it must match */ 1740576ca436SMark Brown if (map->dev_name && 1741576ca436SMark Brown (!devname || strcmp(map->dev_name, devname))) 1742576ca436SMark Brown continue; 1743576ca436SMark Brown 174485f3b431STomeu Vizoso if (strcmp(map->supply, supply) == 0 && 174585f3b431STomeu Vizoso get_device(&map->regulator->dev)) { 1746163478daSDmitry Torokhov r = map->regulator; 1747163478daSDmitry Torokhov break; 1748576ca436SMark Brown } 174985f3b431STomeu Vizoso } 175085f3b431STomeu Vizoso mutex_unlock(®ulator_list_mutex); 1751576ca436SMark Brown 1752163478daSDmitry Torokhov if (r) 1753163478daSDmitry Torokhov return r; 1754163478daSDmitry Torokhov 175506217197SCharles Keepax r = regulator_lookup_by_name(supply); 175606217197SCharles Keepax if (r) 175706217197SCharles Keepax return r; 175806217197SCharles Keepax 1759163478daSDmitry Torokhov return ERR_PTR(-ENODEV); 176069511a45SRajendra Nayak } 176169511a45SRajendra Nayak 17626261b06dSBjorn Andersson static int regulator_resolve_supply(struct regulator_dev *rdev) 17636261b06dSBjorn Andersson { 17646261b06dSBjorn Andersson struct regulator_dev *r; 17656261b06dSBjorn Andersson struct device *dev = rdev->dev.parent; 17666261b06dSBjorn Andersson int ret; 17676261b06dSBjorn Andersson 176848f1b4efSKrzysztof Kozlowski /* No supply to resolve? */ 17696261b06dSBjorn Andersson if (!rdev->supply_name) 17706261b06dSBjorn Andersson return 0; 17716261b06dSBjorn Andersson 17726261b06dSBjorn Andersson /* Supply already resolved? */ 17736261b06dSBjorn Andersson if (rdev->supply) 17746261b06dSBjorn Andersson return 0; 17756261b06dSBjorn Andersson 1776163478daSDmitry Torokhov r = regulator_dev_lookup(dev, rdev->supply_name); 1777163478daSDmitry Torokhov if (IS_ERR(r)) { 1778163478daSDmitry Torokhov ret = PTR_ERR(r); 1779163478daSDmitry Torokhov 178006423121SMark Brown /* Did the lookup explicitly defer for us? */ 178106423121SMark Brown if (ret == -EPROBE_DEFER) 178206423121SMark Brown return ret; 178306423121SMark Brown 17849f7e25edSMark Brown if (have_full_constraints()) { 17859f7e25edSMark Brown r = dummy_regulator_rdev; 178685f3b431STomeu Vizoso get_device(&r->dev); 17879f7e25edSMark Brown } else { 17886261b06dSBjorn Andersson dev_err(dev, "Failed to resolve %s-supply for %s\n", 17896261b06dSBjorn Andersson rdev->supply_name, rdev->desc->name); 17906261b06dSBjorn Andersson return -EPROBE_DEFER; 17916261b06dSBjorn Andersson } 17929f7e25edSMark Brown } 17936261b06dSBjorn Andersson 179466d228a2SJon Hunter /* 179566d228a2SJon Hunter * If the supply's parent device is not the same as the 179666d228a2SJon Hunter * regulator's parent device, then ensure the parent device 179766d228a2SJon Hunter * is bound before we resolve the supply, in case the parent 179866d228a2SJon Hunter * device get probe deferred and unregisters the supply. 179966d228a2SJon Hunter */ 180066d228a2SJon Hunter if (r->dev.parent && r->dev.parent != rdev->dev.parent) { 180166d228a2SJon Hunter if (!device_is_bound(r->dev.parent)) { 180266d228a2SJon Hunter put_device(&r->dev); 180366d228a2SJon Hunter return -EPROBE_DEFER; 180466d228a2SJon Hunter } 180566d228a2SJon Hunter } 180666d228a2SJon Hunter 18076261b06dSBjorn Andersson /* Recursively resolve the supply of the supply */ 18086261b06dSBjorn Andersson ret = regulator_resolve_supply(r); 180985f3b431STomeu Vizoso if (ret < 0) { 181085f3b431STomeu Vizoso put_device(&r->dev); 18116261b06dSBjorn Andersson return ret; 181285f3b431STomeu Vizoso } 18136261b06dSBjorn Andersson 18146261b06dSBjorn Andersson ret = set_supply(rdev, r); 181585f3b431STomeu Vizoso if (ret < 0) { 181685f3b431STomeu Vizoso put_device(&r->dev); 18176261b06dSBjorn Andersson return ret; 181885f3b431STomeu Vizoso } 18196261b06dSBjorn Andersson 182005f224caSDouglas Anderson /* 182105f224caSDouglas Anderson * In set_machine_constraints() we may have turned this regulator on 182205f224caSDouglas Anderson * but we couldn't propagate to the supply if it hadn't been resolved 182305f224caSDouglas Anderson * yet. Do it now. 182405f224caSDouglas Anderson */ 182505f224caSDouglas Anderson if (rdev->use_count) { 18266261b06dSBjorn Andersson ret = regulator_enable(rdev->supply); 182736a1f1b6SJavier Martinez Canillas if (ret < 0) { 182836a1f1b6SJavier Martinez Canillas _regulator_put(rdev->supply); 18298e5356a7SJon Hunter rdev->supply = NULL; 18306261b06dSBjorn Andersson return ret; 18316261b06dSBjorn Andersson } 183236a1f1b6SJavier Martinez Canillas } 18336261b06dSBjorn Andersson 18346261b06dSBjorn Andersson return 0; 18356261b06dSBjorn Andersson } 18366261b06dSBjorn Andersson 18375ffbd136SMark Brown /* Internal regulator request function */ 1838a8bd42a9SDmitry Torokhov struct regulator *_regulator_get(struct device *dev, const char *id, 1839a8bd42a9SDmitry Torokhov enum regulator_get_type get_type) 1840414c70cbSLiam Girdwood { 1841414c70cbSLiam Girdwood struct regulator_dev *rdev; 18427d245afaSDmitry Torokhov struct regulator *regulator; 1843a4d7641fSDmitry Torokhov const char *devname = dev ? dev_name(dev) : "deviceless"; 1844317b5684SMark Brown int ret; 1845414c70cbSLiam Girdwood 1846a8bd42a9SDmitry Torokhov if (get_type >= MAX_GET_TYPE) { 1847a8bd42a9SDmitry Torokhov dev_err(dev, "invalid type %d in %s\n", get_type, __func__); 1848a8bd42a9SDmitry Torokhov return ERR_PTR(-EINVAL); 1849a8bd42a9SDmitry Torokhov } 1850a8bd42a9SDmitry Torokhov 1851414c70cbSLiam Girdwood if (id == NULL) { 18525da84fd9SJoe Perches pr_err("get() with no identifier\n"); 1853043c998fSMark Brown return ERR_PTR(-EINVAL); 1854414c70cbSLiam Girdwood } 1855414c70cbSLiam Girdwood 1856163478daSDmitry Torokhov rdev = regulator_dev_lookup(dev, id); 1857a4d7641fSDmitry Torokhov if (IS_ERR(rdev)) { 1858163478daSDmitry Torokhov ret = PTR_ERR(rdev); 1859ef60abbbSMark Brown 18601e4b545cSNishanth Menon /* 1861a4d7641fSDmitry Torokhov * If regulator_dev_lookup() fails with error other 1862a4d7641fSDmitry Torokhov * than -ENODEV our job here is done, we simply return it. 18631e4b545cSNishanth Menon */ 1864a4d7641fSDmitry Torokhov if (ret != -ENODEV) 1865a4d7641fSDmitry Torokhov return ERR_PTR(ret); 18661e4b545cSNishanth Menon 1867a4d7641fSDmitry Torokhov if (!have_full_constraints()) { 1868a4d7641fSDmitry Torokhov dev_warn(dev, 1869a4d7641fSDmitry Torokhov "incomplete constraints, dummy supplies not allowed\n"); 1870a4d7641fSDmitry Torokhov return ERR_PTR(-ENODEV); 187134abbd68SMark Brown } 187234abbd68SMark Brown 1873a4d7641fSDmitry Torokhov switch (get_type) { 1874a4d7641fSDmitry Torokhov case NORMAL_GET: 1875a4d7641fSDmitry Torokhov /* 1876a4d7641fSDmitry Torokhov * Assume that a regulator is physically present and 1877a4d7641fSDmitry Torokhov * enabled, even if it isn't hooked up, and just 1878a4d7641fSDmitry Torokhov * provide a dummy. 1879a4d7641fSDmitry Torokhov */ 1880a4d7641fSDmitry Torokhov dev_warn(dev, 1881a4d7641fSDmitry Torokhov "%s supply %s not found, using dummy regulator\n", 1882a4d7641fSDmitry Torokhov devname, id); 1883a4d7641fSDmitry Torokhov rdev = dummy_regulator_rdev; 1884a4d7641fSDmitry Torokhov get_device(&rdev->dev); 1885a4d7641fSDmitry Torokhov break; 1886414c70cbSLiam Girdwood 1887a4d7641fSDmitry Torokhov case EXCLUSIVE_GET: 1888a4d7641fSDmitry Torokhov dev_warn(dev, 1889a4d7641fSDmitry Torokhov "dummy supplies not allowed for exclusive requests\n"); 1890a4d7641fSDmitry Torokhov /* fall through */ 1891a4d7641fSDmitry Torokhov 1892a4d7641fSDmitry Torokhov default: 1893a4d7641fSDmitry Torokhov return ERR_PTR(-ENODEV); 1894a4d7641fSDmitry Torokhov } 1895a4d7641fSDmitry Torokhov } 1896a4d7641fSDmitry Torokhov 18975ffbd136SMark Brown if (rdev->exclusive) { 18985ffbd136SMark Brown regulator = ERR_PTR(-EPERM); 189985f3b431STomeu Vizoso put_device(&rdev->dev); 190085f3b431STomeu Vizoso return regulator; 19015ffbd136SMark Brown } 19025ffbd136SMark Brown 1903a8bd42a9SDmitry Torokhov if (get_type == EXCLUSIVE_GET && rdev->open_count) { 19045ffbd136SMark Brown regulator = ERR_PTR(-EBUSY); 190585f3b431STomeu Vizoso put_device(&rdev->dev); 190685f3b431STomeu Vizoso return regulator; 19075ffbd136SMark Brown } 19085ffbd136SMark Brown 190979d6f049SDmitry Osipenko mutex_lock(®ulator_list_mutex); 191079d6f049SDmitry Osipenko ret = (rdev->coupling_desc.n_resolved != rdev->coupling_desc.n_coupled); 191179d6f049SDmitry Osipenko mutex_unlock(®ulator_list_mutex); 191279d6f049SDmitry Osipenko 191379d6f049SDmitry Osipenko if (ret != 0) { 191479d6f049SDmitry Osipenko regulator = ERR_PTR(-EPROBE_DEFER); 191579d6f049SDmitry Osipenko put_device(&rdev->dev); 191679d6f049SDmitry Osipenko return regulator; 191779d6f049SDmitry Osipenko } 191879d6f049SDmitry Osipenko 19196261b06dSBjorn Andersson ret = regulator_resolve_supply(rdev); 19206261b06dSBjorn Andersson if (ret < 0) { 19216261b06dSBjorn Andersson regulator = ERR_PTR(ret); 192285f3b431STomeu Vizoso put_device(&rdev->dev); 192385f3b431STomeu Vizoso return regulator; 19246261b06dSBjorn Andersson } 19256261b06dSBjorn Andersson 192685f3b431STomeu Vizoso if (!try_module_get(rdev->owner)) { 19277d245afaSDmitry Torokhov regulator = ERR_PTR(-EPROBE_DEFER); 192885f3b431STomeu Vizoso put_device(&rdev->dev); 192985f3b431STomeu Vizoso return regulator; 193085f3b431STomeu Vizoso } 1931a5766f11SLiam Girdwood 1932414c70cbSLiam Girdwood regulator = create_regulator(rdev, dev, id); 1933414c70cbSLiam Girdwood if (regulator == NULL) { 1934414c70cbSLiam Girdwood regulator = ERR_PTR(-ENOMEM); 193585f3b431STomeu Vizoso put_device(&rdev->dev); 1936414c70cbSLiam Girdwood module_put(rdev->owner); 193785f3b431STomeu Vizoso return regulator; 1938414c70cbSLiam Girdwood } 1939414c70cbSLiam Girdwood 19405ffbd136SMark Brown rdev->open_count++; 1941a8bd42a9SDmitry Torokhov if (get_type == EXCLUSIVE_GET) { 19425ffbd136SMark Brown rdev->exclusive = 1; 19435ffbd136SMark Brown 19445ffbd136SMark Brown ret = _regulator_is_enabled(rdev); 19455ffbd136SMark Brown if (ret > 0) 19465ffbd136SMark Brown rdev->use_count = 1; 19475ffbd136SMark Brown else 19485ffbd136SMark Brown rdev->use_count = 0; 19495ffbd136SMark Brown } 19505ffbd136SMark Brown 1951ed1ae2ddSpascal paillet device_link_add(dev, &rdev->dev, DL_FLAG_STATELESS); 1952ed1ae2ddSpascal paillet 1953414c70cbSLiam Girdwood return regulator; 1954414c70cbSLiam Girdwood } 19555ffbd136SMark Brown 19565ffbd136SMark Brown /** 19575ffbd136SMark Brown * regulator_get - lookup and obtain a reference to a regulator. 19585ffbd136SMark Brown * @dev: device for regulator "consumer" 19595ffbd136SMark Brown * @id: Supply name or regulator ID. 19605ffbd136SMark Brown * 19615ffbd136SMark Brown * Returns a struct regulator corresponding to the regulator producer, 19625ffbd136SMark Brown * or IS_ERR() condition containing errno. 19635ffbd136SMark Brown * 19645ffbd136SMark Brown * Use of supply names configured via regulator_set_device_supply() is 19655ffbd136SMark Brown * strongly encouraged. It is recommended that the supply name used 19665ffbd136SMark Brown * should match the name used for the supply and/or the relevant 19675ffbd136SMark Brown * device pins in the datasheet. 19685ffbd136SMark Brown */ 19695ffbd136SMark Brown struct regulator *regulator_get(struct device *dev, const char *id) 19705ffbd136SMark Brown { 1971a8bd42a9SDmitry Torokhov return _regulator_get(dev, id, NORMAL_GET); 19725ffbd136SMark Brown } 1973414c70cbSLiam Girdwood EXPORT_SYMBOL_GPL(regulator_get); 1974414c70cbSLiam Girdwood 1975070b9079SStephen Boyd /** 19765ffbd136SMark Brown * regulator_get_exclusive - obtain exclusive access to a regulator. 19775ffbd136SMark Brown * @dev: device for regulator "consumer" 19785ffbd136SMark Brown * @id: Supply name or regulator ID. 19795ffbd136SMark Brown * 19805ffbd136SMark Brown * Returns a struct regulator corresponding to the regulator producer, 19815ffbd136SMark Brown * or IS_ERR() condition containing errno. Other consumers will be 198269c3f723SStephen Boyd * unable to obtain this regulator while this reference is held and the 198369c3f723SStephen Boyd * use count for the regulator will be initialised to reflect the current 198469c3f723SStephen Boyd * state of the regulator. 19855ffbd136SMark Brown * 19865ffbd136SMark Brown * This is intended for use by consumers which cannot tolerate shared 19875ffbd136SMark Brown * use of the regulator such as those which need to force the 19885ffbd136SMark Brown * regulator off for correct operation of the hardware they are 19895ffbd136SMark Brown * controlling. 19905ffbd136SMark Brown * 19915ffbd136SMark Brown * Use of supply names configured via regulator_set_device_supply() is 19925ffbd136SMark Brown * strongly encouraged. It is recommended that the supply name used 19935ffbd136SMark Brown * should match the name used for the supply and/or the relevant 19945ffbd136SMark Brown * device pins in the datasheet. 19955ffbd136SMark Brown */ 19965ffbd136SMark Brown struct regulator *regulator_get_exclusive(struct device *dev, const char *id) 19975ffbd136SMark Brown { 1998a8bd42a9SDmitry Torokhov return _regulator_get(dev, id, EXCLUSIVE_GET); 19995ffbd136SMark Brown } 20005ffbd136SMark Brown EXPORT_SYMBOL_GPL(regulator_get_exclusive); 20015ffbd136SMark Brown 2002de1dd9fdSMark Brown /** 2003de1dd9fdSMark Brown * regulator_get_optional - obtain optional access to a regulator. 2004de1dd9fdSMark Brown * @dev: device for regulator "consumer" 2005de1dd9fdSMark Brown * @id: Supply name or regulator ID. 2006de1dd9fdSMark Brown * 2007de1dd9fdSMark Brown * Returns a struct regulator corresponding to the regulator producer, 200869c3f723SStephen Boyd * or IS_ERR() condition containing errno. 2009de1dd9fdSMark Brown * 2010de1dd9fdSMark Brown * This is intended for use by consumers for devices which can have 2011de1dd9fdSMark Brown * some supplies unconnected in normal use, such as some MMC devices. 2012de1dd9fdSMark Brown * It can allow the regulator core to provide stub supplies for other 2013de1dd9fdSMark Brown * supplies requested using normal regulator_get() calls without 2014de1dd9fdSMark Brown * disrupting the operation of drivers that can handle absent 2015de1dd9fdSMark Brown * supplies. 2016de1dd9fdSMark Brown * 2017de1dd9fdSMark Brown * Use of supply names configured via regulator_set_device_supply() is 2018de1dd9fdSMark Brown * strongly encouraged. It is recommended that the supply name used 2019de1dd9fdSMark Brown * should match the name used for the supply and/or the relevant 2020de1dd9fdSMark Brown * device pins in the datasheet. 2021de1dd9fdSMark Brown */ 2022de1dd9fdSMark Brown struct regulator *regulator_get_optional(struct device *dev, const char *id) 2023de1dd9fdSMark Brown { 2024a8bd42a9SDmitry Torokhov return _regulator_get(dev, id, OPTIONAL_GET); 2025de1dd9fdSMark Brown } 2026de1dd9fdSMark Brown EXPORT_SYMBOL_GPL(regulator_get_optional); 2027de1dd9fdSMark Brown 202883b0302dSAshay Jaiswal /* regulator_list_mutex lock held by regulator_put() */ 202923ff2f0fSCharles Keepax static void _regulator_put(struct regulator *regulator) 2030414c70cbSLiam Girdwood { 2031414c70cbSLiam Girdwood struct regulator_dev *rdev; 2032414c70cbSLiam Girdwood 203393576842SViresh Kumar if (IS_ERR_OR_NULL(regulator)) 2034414c70cbSLiam Girdwood return; 2035414c70cbSLiam Girdwood 203670cfef26SKrzysztof Kozlowski lockdep_assert_held_once(®ulator_list_mutex); 203770cfef26SKrzysztof Kozlowski 20385451781dSDouglas Anderson /* Docs say you must disable before calling regulator_put() */ 20395451781dSDouglas Anderson WARN_ON(regulator->enable_count); 20405451781dSDouglas Anderson 2041414c70cbSLiam Girdwood rdev = regulator->rdev; 2042414c70cbSLiam Girdwood 20435de70519SMark Brown debugfs_remove_recursive(regulator->debugfs); 20445de70519SMark Brown 2045ed1ae2ddSpascal paillet if (regulator->dev) { 2046ed1ae2ddSpascal paillet device_link_remove(regulator->dev, &rdev->dev); 2047ed1ae2ddSpascal paillet 2048414c70cbSLiam Girdwood /* remove any sysfs entries */ 2049414c70cbSLiam Girdwood sysfs_remove_link(&rdev->dev.kobj, regulator->supply_name); 2050ed1ae2ddSpascal paillet } 2051ed1ae2ddSpascal paillet 205266cf9a7eSMaciej Purski regulator_lock(rdev); 2053414c70cbSLiam Girdwood list_del(®ulator->list); 2054414c70cbSLiam Girdwood 20555ffbd136SMark Brown rdev->open_count--; 20565ffbd136SMark Brown rdev->exclusive = 0; 205785f3b431STomeu Vizoso put_device(&rdev->dev); 205866cf9a7eSMaciej Purski regulator_unlock(rdev); 20595ffbd136SMark Brown 20600630b614SStephen Boyd kfree_const(regulator->supply_name); 20611768514eSMark Brown kfree(regulator); 20621768514eSMark Brown 2063414c70cbSLiam Girdwood module_put(rdev->owner); 206423ff2f0fSCharles Keepax } 206523ff2f0fSCharles Keepax 206623ff2f0fSCharles Keepax /** 206723ff2f0fSCharles Keepax * regulator_put - "free" the regulator source 206823ff2f0fSCharles Keepax * @regulator: regulator source 206923ff2f0fSCharles Keepax * 207023ff2f0fSCharles Keepax * Note: drivers must ensure that all regulator_enable calls made on this 207123ff2f0fSCharles Keepax * regulator source are balanced by regulator_disable calls prior to calling 207223ff2f0fSCharles Keepax * this function. 207323ff2f0fSCharles Keepax */ 207423ff2f0fSCharles Keepax void regulator_put(struct regulator *regulator) 207523ff2f0fSCharles Keepax { 207623ff2f0fSCharles Keepax mutex_lock(®ulator_list_mutex); 207723ff2f0fSCharles Keepax _regulator_put(regulator); 2078414c70cbSLiam Girdwood mutex_unlock(®ulator_list_mutex); 2079414c70cbSLiam Girdwood } 2080414c70cbSLiam Girdwood EXPORT_SYMBOL_GPL(regulator_put); 2081414c70cbSLiam Girdwood 2082a06ccd9cSCharles Keepax /** 2083a06ccd9cSCharles Keepax * regulator_register_supply_alias - Provide device alias for supply lookup 2084a06ccd9cSCharles Keepax * 2085a06ccd9cSCharles Keepax * @dev: device that will be given as the regulator "consumer" 2086a06ccd9cSCharles Keepax * @id: Supply name or regulator ID 2087a06ccd9cSCharles Keepax * @alias_dev: device that should be used to lookup the supply 2088a06ccd9cSCharles Keepax * @alias_id: Supply name or regulator ID that should be used to lookup the 2089a06ccd9cSCharles Keepax * supply 2090a06ccd9cSCharles Keepax * 2091a06ccd9cSCharles Keepax * All lookups for id on dev will instead be conducted for alias_id on 2092a06ccd9cSCharles Keepax * alias_dev. 2093a06ccd9cSCharles Keepax */ 2094a06ccd9cSCharles Keepax int regulator_register_supply_alias(struct device *dev, const char *id, 2095a06ccd9cSCharles Keepax struct device *alias_dev, 2096a06ccd9cSCharles Keepax const char *alias_id) 2097a06ccd9cSCharles Keepax { 2098a06ccd9cSCharles Keepax struct regulator_supply_alias *map; 2099a06ccd9cSCharles Keepax 2100a06ccd9cSCharles Keepax map = regulator_find_supply_alias(dev, id); 2101a06ccd9cSCharles Keepax if (map) 2102a06ccd9cSCharles Keepax return -EEXIST; 2103a06ccd9cSCharles Keepax 2104a06ccd9cSCharles Keepax map = kzalloc(sizeof(struct regulator_supply_alias), GFP_KERNEL); 2105a06ccd9cSCharles Keepax if (!map) 2106a06ccd9cSCharles Keepax return -ENOMEM; 2107a06ccd9cSCharles Keepax 2108a06ccd9cSCharles Keepax map->src_dev = dev; 2109a06ccd9cSCharles Keepax map->src_supply = id; 2110a06ccd9cSCharles Keepax map->alias_dev = alias_dev; 2111a06ccd9cSCharles Keepax map->alias_supply = alias_id; 2112a06ccd9cSCharles Keepax 2113a06ccd9cSCharles Keepax list_add(&map->list, ®ulator_supply_alias_list); 2114a06ccd9cSCharles Keepax 2115a06ccd9cSCharles Keepax pr_info("Adding alias for supply %s,%s -> %s,%s\n", 2116a06ccd9cSCharles Keepax id, dev_name(dev), alias_id, dev_name(alias_dev)); 2117a06ccd9cSCharles Keepax 2118a06ccd9cSCharles Keepax return 0; 2119a06ccd9cSCharles Keepax } 2120a06ccd9cSCharles Keepax EXPORT_SYMBOL_GPL(regulator_register_supply_alias); 2121a06ccd9cSCharles Keepax 2122a06ccd9cSCharles Keepax /** 2123a06ccd9cSCharles Keepax * regulator_unregister_supply_alias - Remove device alias 2124a06ccd9cSCharles Keepax * 2125a06ccd9cSCharles Keepax * @dev: device that will be given as the regulator "consumer" 2126a06ccd9cSCharles Keepax * @id: Supply name or regulator ID 2127a06ccd9cSCharles Keepax * 2128a06ccd9cSCharles Keepax * Remove a lookup alias if one exists for id on dev. 2129a06ccd9cSCharles Keepax */ 2130a06ccd9cSCharles Keepax void regulator_unregister_supply_alias(struct device *dev, const char *id) 2131a06ccd9cSCharles Keepax { 2132a06ccd9cSCharles Keepax struct regulator_supply_alias *map; 2133a06ccd9cSCharles Keepax 2134a06ccd9cSCharles Keepax map = regulator_find_supply_alias(dev, id); 2135a06ccd9cSCharles Keepax if (map) { 2136a06ccd9cSCharles Keepax list_del(&map->list); 2137a06ccd9cSCharles Keepax kfree(map); 2138a06ccd9cSCharles Keepax } 2139a06ccd9cSCharles Keepax } 2140a06ccd9cSCharles Keepax EXPORT_SYMBOL_GPL(regulator_unregister_supply_alias); 2141a06ccd9cSCharles Keepax 2142a06ccd9cSCharles Keepax /** 2143a06ccd9cSCharles Keepax * regulator_bulk_register_supply_alias - register multiple aliases 2144a06ccd9cSCharles Keepax * 2145a06ccd9cSCharles Keepax * @dev: device that will be given as the regulator "consumer" 2146a06ccd9cSCharles Keepax * @id: List of supply names or regulator IDs 2147a06ccd9cSCharles Keepax * @alias_dev: device that should be used to lookup the supply 2148a06ccd9cSCharles Keepax * @alias_id: List of supply names or regulator IDs that should be used to 2149a06ccd9cSCharles Keepax * lookup the supply 2150a06ccd9cSCharles Keepax * @num_id: Number of aliases to register 2151a06ccd9cSCharles Keepax * 2152a06ccd9cSCharles Keepax * @return 0 on success, an errno on failure. 2153a06ccd9cSCharles Keepax * 2154a06ccd9cSCharles Keepax * This helper function allows drivers to register several supply 2155a06ccd9cSCharles Keepax * aliases in one operation. If any of the aliases cannot be 2156a06ccd9cSCharles Keepax * registered any aliases that were registered will be removed 2157a06ccd9cSCharles Keepax * before returning to the caller. 2158a06ccd9cSCharles Keepax */ 21599f8c0fe9SLee Jones int regulator_bulk_register_supply_alias(struct device *dev, 21609f8c0fe9SLee Jones const char *const *id, 2161a06ccd9cSCharles Keepax struct device *alias_dev, 21629f8c0fe9SLee Jones const char *const *alias_id, 2163a06ccd9cSCharles Keepax int num_id) 2164a06ccd9cSCharles Keepax { 2165a06ccd9cSCharles Keepax int i; 2166a06ccd9cSCharles Keepax int ret; 2167a06ccd9cSCharles Keepax 2168a06ccd9cSCharles Keepax for (i = 0; i < num_id; ++i) { 2169a06ccd9cSCharles Keepax ret = regulator_register_supply_alias(dev, id[i], alias_dev, 2170a06ccd9cSCharles Keepax alias_id[i]); 2171a06ccd9cSCharles Keepax if (ret < 0) 2172a06ccd9cSCharles Keepax goto err; 2173a06ccd9cSCharles Keepax } 2174a06ccd9cSCharles Keepax 2175a06ccd9cSCharles Keepax return 0; 2176a06ccd9cSCharles Keepax 2177a06ccd9cSCharles Keepax err: 2178a06ccd9cSCharles Keepax dev_err(dev, 2179a06ccd9cSCharles Keepax "Failed to create supply alias %s,%s -> %s,%s\n", 2180a06ccd9cSCharles Keepax id[i], dev_name(dev), alias_id[i], dev_name(alias_dev)); 2181a06ccd9cSCharles Keepax 2182a06ccd9cSCharles Keepax while (--i >= 0) 2183a06ccd9cSCharles Keepax regulator_unregister_supply_alias(dev, id[i]); 2184a06ccd9cSCharles Keepax 2185a06ccd9cSCharles Keepax return ret; 2186a06ccd9cSCharles Keepax } 2187a06ccd9cSCharles Keepax EXPORT_SYMBOL_GPL(regulator_bulk_register_supply_alias); 2188a06ccd9cSCharles Keepax 2189a06ccd9cSCharles Keepax /** 2190a06ccd9cSCharles Keepax * regulator_bulk_unregister_supply_alias - unregister multiple aliases 2191a06ccd9cSCharles Keepax * 2192a06ccd9cSCharles Keepax * @dev: device that will be given as the regulator "consumer" 2193a06ccd9cSCharles Keepax * @id: List of supply names or regulator IDs 2194a06ccd9cSCharles Keepax * @num_id: Number of aliases to unregister 2195a06ccd9cSCharles Keepax * 2196a06ccd9cSCharles Keepax * This helper function allows drivers to unregister several supply 2197a06ccd9cSCharles Keepax * aliases in one operation. 2198a06ccd9cSCharles Keepax */ 2199a06ccd9cSCharles Keepax void regulator_bulk_unregister_supply_alias(struct device *dev, 22009f8c0fe9SLee Jones const char *const *id, 2201a06ccd9cSCharles Keepax int num_id) 2202a06ccd9cSCharles Keepax { 2203a06ccd9cSCharles Keepax int i; 2204a06ccd9cSCharles Keepax 2205a06ccd9cSCharles Keepax for (i = 0; i < num_id; ++i) 2206a06ccd9cSCharles Keepax regulator_unregister_supply_alias(dev, id[i]); 2207a06ccd9cSCharles Keepax } 2208a06ccd9cSCharles Keepax EXPORT_SYMBOL_GPL(regulator_bulk_unregister_supply_alias); 2209a06ccd9cSCharles Keepax 2210a06ccd9cSCharles Keepax 2211f19b00daSKim, Milo /* Manage enable GPIO list. Same GPIO pin can be shared among regulators */ 2212f19b00daSKim, Milo static int regulator_ena_gpio_request(struct regulator_dev *rdev, 2213f19b00daSKim, Milo const struct regulator_config *config) 2214f19b00daSKim, Milo { 2215f19b00daSKim, Milo struct regulator_enable_gpio *pin; 2216778b28b4SRussell King struct gpio_desc *gpiod; 2217f19b00daSKim, Milo 2218e45e290aSLinus Walleij gpiod = config->ena_gpiod; 2219778b28b4SRussell King 2220f19b00daSKim, Milo list_for_each_entry(pin, ®ulator_ena_gpio_list, list) { 2221778b28b4SRussell King if (pin->gpiod == gpiod) { 2222541d052dSLinus Walleij rdev_dbg(rdev, "GPIO is already used\n"); 2223f19b00daSKim, Milo goto update_ena_gpio_to_rdev; 2224f19b00daSKim, Milo } 2225f19b00daSKim, Milo } 2226f19b00daSKim, Milo 2227f19b00daSKim, Milo pin = kzalloc(sizeof(struct regulator_enable_gpio), GFP_KERNEL); 2228541d052dSLinus Walleij if (pin == NULL) 2229f19b00daSKim, Milo return -ENOMEM; 2230f19b00daSKim, Milo 2231778b28b4SRussell King pin->gpiod = gpiod; 2232f19b00daSKim, Milo list_add(&pin->list, ®ulator_ena_gpio_list); 2233f19b00daSKim, Milo 2234f19b00daSKim, Milo update_ena_gpio_to_rdev: 2235f19b00daSKim, Milo pin->request_count++; 2236f19b00daSKim, Milo rdev->ena_pin = pin; 2237f19b00daSKim, Milo return 0; 2238f19b00daSKim, Milo } 2239f19b00daSKim, Milo 2240f19b00daSKim, Milo static void regulator_ena_gpio_free(struct regulator_dev *rdev) 2241f19b00daSKim, Milo { 2242f19b00daSKim, Milo struct regulator_enable_gpio *pin, *n; 2243f19b00daSKim, Milo 2244f19b00daSKim, Milo if (!rdev->ena_pin) 2245f19b00daSKim, Milo return; 2246f19b00daSKim, Milo 2247f19b00daSKim, Milo /* Free the GPIO only in case of no use */ 2248f19b00daSKim, Milo list_for_each_entry_safe(pin, n, ®ulator_ena_gpio_list, list) { 2249778b28b4SRussell King if (pin->gpiod == rdev->ena_pin->gpiod) { 2250f19b00daSKim, Milo if (pin->request_count <= 1) { 2251f19b00daSKim, Milo pin->request_count = 0; 225278927aa4SLinus Walleij gpiod_put(pin->gpiod); 2253f19b00daSKim, Milo list_del(&pin->list); 2254f19b00daSKim, Milo kfree(pin); 225560a2362fSSeung-Woo Kim rdev->ena_pin = NULL; 225660a2362fSSeung-Woo Kim return; 2257f19b00daSKim, Milo } else { 2258f19b00daSKim, Milo pin->request_count--; 2259f19b00daSKim, Milo } 2260f19b00daSKim, Milo } 2261f19b00daSKim, Milo } 2262f19b00daSKim, Milo } 2263f19b00daSKim, Milo 2264967cfb18SKim, Milo /** 226531d6eebfSRobert P. J. Day * regulator_ena_gpio_ctrl - balance enable_count of each GPIO and actual GPIO pin control 226631d6eebfSRobert P. J. Day * @rdev: regulator_dev structure 226731d6eebfSRobert P. J. Day * @enable: enable GPIO at initial use? 226831d6eebfSRobert P. J. Day * 2269967cfb18SKim, Milo * GPIO is enabled in case of initial use. (enable_count is 0) 2270967cfb18SKim, Milo * GPIO is disabled when it is not shared any more. (enable_count <= 1) 2271967cfb18SKim, Milo */ 2272967cfb18SKim, Milo static int regulator_ena_gpio_ctrl(struct regulator_dev *rdev, bool enable) 2273967cfb18SKim, Milo { 2274967cfb18SKim, Milo struct regulator_enable_gpio *pin = rdev->ena_pin; 2275967cfb18SKim, Milo 2276967cfb18SKim, Milo if (!pin) 2277967cfb18SKim, Milo return -EINVAL; 2278967cfb18SKim, Milo 2279967cfb18SKim, Milo if (enable) { 2280967cfb18SKim, Milo /* Enable GPIO at initial use */ 2281967cfb18SKim, Milo if (pin->enable_count == 0) 228201dc79cdSLinus Walleij gpiod_set_value_cansleep(pin->gpiod, 1); 2283967cfb18SKim, Milo 2284967cfb18SKim, Milo pin->enable_count++; 2285967cfb18SKim, Milo } else { 2286967cfb18SKim, Milo if (pin->enable_count > 1) { 2287967cfb18SKim, Milo pin->enable_count--; 2288967cfb18SKim, Milo return 0; 2289967cfb18SKim, Milo } 2290967cfb18SKim, Milo 2291967cfb18SKim, Milo /* Disable GPIO if not used */ 2292967cfb18SKim, Milo if (pin->enable_count <= 1) { 229301dc79cdSLinus Walleij gpiod_set_value_cansleep(pin->gpiod, 0); 2294967cfb18SKim, Milo pin->enable_count = 0; 2295967cfb18SKim, Milo } 2296967cfb18SKim, Milo } 2297967cfb18SKim, Milo 2298967cfb18SKim, Milo return 0; 2299967cfb18SKim, Milo } 2300967cfb18SKim, Milo 230179fd1141SGuodong Xu /** 230279fd1141SGuodong Xu * _regulator_enable_delay - a delay helper function 230379fd1141SGuodong Xu * @delay: time to delay in microseconds 230479fd1141SGuodong Xu * 23055df529d4SThierry Reding * Delay for the requested amount of time as per the guidelines in: 23065df529d4SThierry Reding * 23075df529d4SThierry Reding * Documentation/timers/timers-howto.txt 23085df529d4SThierry Reding * 23095df529d4SThierry Reding * The assumption here is that regulators will never be enabled in 23105df529d4SThierry Reding * atomic context and therefore sleeping functions can be used. 23115df529d4SThierry Reding */ 231279fd1141SGuodong Xu static void _regulator_enable_delay(unsigned int delay) 231379fd1141SGuodong Xu { 23145df529d4SThierry Reding unsigned int ms = delay / 1000; 23155df529d4SThierry Reding unsigned int us = delay % 1000; 23165df529d4SThierry Reding 23175df529d4SThierry Reding if (ms > 0) { 23185df529d4SThierry Reding /* 23195df529d4SThierry Reding * For small enough values, handle super-millisecond 23205df529d4SThierry Reding * delays in the usleep_range() call below. 23215df529d4SThierry Reding */ 23225df529d4SThierry Reding if (ms < 20) 23235df529d4SThierry Reding us += ms * 1000; 23245df529d4SThierry Reding else 23255df529d4SThierry Reding msleep(ms); 23265df529d4SThierry Reding } 23275df529d4SThierry Reding 23285df529d4SThierry Reding /* 23295df529d4SThierry Reding * Give the scheduler some room to coalesce with any other 23305df529d4SThierry Reding * wakeup sources. For delays shorter than 10 us, don't even 23315df529d4SThierry Reding * bother setting up high-resolution timers and just busy- 23325df529d4SThierry Reding * loop. 23335df529d4SThierry Reding */ 23345df529d4SThierry Reding if (us >= 10) 23355df529d4SThierry Reding usleep_range(us, us + 100); 23365df529d4SThierry Reding else 23375df529d4SThierry Reding udelay(us); 23385c5659d0SMark Brown } 23395c5659d0SMark Brown 23405c5659d0SMark Brown static int _regulator_do_enable(struct regulator_dev *rdev) 23415c5659d0SMark Brown { 23425c5659d0SMark Brown int ret, delay; 23435c5659d0SMark Brown 23445c5659d0SMark Brown /* Query before enabling in case configuration dependent. */ 23455c5659d0SMark Brown ret = _regulator_get_enable_time(rdev); 23465c5659d0SMark Brown if (ret >= 0) { 23475c5659d0SMark Brown delay = ret; 23485c5659d0SMark Brown } else { 2349414c70cbSLiam Girdwood rdev_warn(rdev, "enable_time() failed: %d\n", ret); 2350414c70cbSLiam Girdwood delay = 0; 2351414c70cbSLiam Girdwood } 23525c5659d0SMark Brown 2353414c70cbSLiam Girdwood trace_regulator_enable(rdev_get_name(rdev)); 2354414c70cbSLiam Girdwood 2355871f5650SGuodong Xu if (rdev->desc->off_on_delay) { 2356871f5650SGuodong Xu /* if needed, keep a distance of off_on_delay from last time 2357871f5650SGuodong Xu * this regulator was disabled. 2358871f5650SGuodong Xu */ 2359871f5650SGuodong Xu unsigned long start_jiffy = jiffies; 2360871f5650SGuodong Xu unsigned long intended, max_delay, remaining; 2361871f5650SGuodong Xu 2362871f5650SGuodong Xu max_delay = usecs_to_jiffies(rdev->desc->off_on_delay); 2363871f5650SGuodong Xu intended = rdev->last_off_jiffy + max_delay; 2364871f5650SGuodong Xu 2365871f5650SGuodong Xu if (time_before(start_jiffy, intended)) { 2366871f5650SGuodong Xu /* calc remaining jiffies to deal with one-time 2367871f5650SGuodong Xu * timer wrapping. 2368871f5650SGuodong Xu * in case of multiple timer wrapping, either it can be 2369871f5650SGuodong Xu * detected by out-of-range remaining, or it cannot be 237048f1b4efSKrzysztof Kozlowski * detected and we get a penalty of 2371871f5650SGuodong Xu * _regulator_enable_delay(). 2372871f5650SGuodong Xu */ 2373871f5650SGuodong Xu remaining = intended - start_jiffy; 2374871f5650SGuodong Xu if (remaining <= max_delay) 2375871f5650SGuodong Xu _regulator_enable_delay( 2376871f5650SGuodong Xu jiffies_to_usecs(remaining)); 2377871f5650SGuodong Xu } 2378871f5650SGuodong Xu } 2379871f5650SGuodong Xu 2380414c70cbSLiam Girdwood if (rdev->ena_pin) { 238129d62ec5SDoug Anderson if (!rdev->ena_gpio_state) { 23829a2372faSMark Brown ret = regulator_ena_gpio_ctrl(rdev, true); 2383414c70cbSLiam Girdwood if (ret < 0) 2384414c70cbSLiam Girdwood return ret; 23859a2372faSMark Brown rdev->ena_gpio_state = 1; 238629d62ec5SDoug Anderson } 23879a2372faSMark Brown } else if (rdev->desc->ops->enable) { 23889a2372faSMark Brown ret = rdev->desc->ops->enable(rdev); 23899a2372faSMark Brown if (ret < 0) 23909a2372faSMark Brown return ret; 23919a2372faSMark Brown } else { 23929a2372faSMark Brown return -EINVAL; 23935c5659d0SMark Brown } 23949a2372faSMark Brown 23959a2372faSMark Brown /* Allow the regulator to ramp; it would be useful to extend 239631aae2beSMark Brown * this for bulk operations so that the regulators can ramp 2397a7433cffSLinus Walleij * together. */ 23985da84fd9SJoe Perches trace_regulator_enable_delay(rdev_get_name(rdev)); 2399414c70cbSLiam Girdwood 240079fd1141SGuodong Xu _regulator_enable_delay(delay); 2401a7433cffSLinus Walleij 2402414c70cbSLiam Girdwood trace_regulator_enable_complete(rdev_get_name(rdev)); 2403414c70cbSLiam Girdwood 24049a2372faSMark Brown return 0; 24059a2372faSMark Brown } 24069a2372faSMark Brown 24075451781dSDouglas Anderson /** 24085451781dSDouglas Anderson * _regulator_handle_consumer_enable - handle that a consumer enabled 24095451781dSDouglas Anderson * @regulator: regulator source 24105451781dSDouglas Anderson * 24115451781dSDouglas Anderson * Some things on a regulator consumer (like the contribution towards total 24125451781dSDouglas Anderson * load on the regulator) only have an effect when the consumer wants the 24135451781dSDouglas Anderson * regulator enabled. Explained in example with two consumers of the same 24145451781dSDouglas Anderson * regulator: 24155451781dSDouglas Anderson * consumer A: set_load(100); => total load = 0 24165451781dSDouglas Anderson * consumer A: regulator_enable(); => total load = 100 24175451781dSDouglas Anderson * consumer B: set_load(1000); => total load = 100 24185451781dSDouglas Anderson * consumer B: regulator_enable(); => total load = 1100 24195451781dSDouglas Anderson * consumer A: regulator_disable(); => total_load = 1000 24205451781dSDouglas Anderson * 24215451781dSDouglas Anderson * This function (together with _regulator_handle_consumer_disable) is 24225451781dSDouglas Anderson * responsible for keeping track of the refcount for a given regulator consumer 24235451781dSDouglas Anderson * and applying / unapplying these things. 24245451781dSDouglas Anderson * 24255451781dSDouglas Anderson * Returns 0 upon no error; -error upon error. 24265451781dSDouglas Anderson */ 24275451781dSDouglas Anderson static int _regulator_handle_consumer_enable(struct regulator *regulator) 2428414c70cbSLiam Girdwood { 24295451781dSDouglas Anderson struct regulator_dev *rdev = regulator->rdev; 24305451781dSDouglas Anderson 24315451781dSDouglas Anderson lockdep_assert_held_once(&rdev->mutex.base); 24325451781dSDouglas Anderson 24335451781dSDouglas Anderson regulator->enable_count++; 24345451781dSDouglas Anderson if (regulator->uA_load && regulator->enable_count == 1) 24355451781dSDouglas Anderson return drms_uA_update(rdev); 24365451781dSDouglas Anderson 24375451781dSDouglas Anderson return 0; 24385451781dSDouglas Anderson } 24395451781dSDouglas Anderson 24405451781dSDouglas Anderson /** 24415451781dSDouglas Anderson * _regulator_handle_consumer_disable - handle that a consumer disabled 24425451781dSDouglas Anderson * @regulator: regulator source 24435451781dSDouglas Anderson * 24445451781dSDouglas Anderson * The opposite of _regulator_handle_consumer_enable(). 24455451781dSDouglas Anderson * 24465451781dSDouglas Anderson * Returns 0 upon no error; -error upon error. 24475451781dSDouglas Anderson */ 24485451781dSDouglas Anderson static int _regulator_handle_consumer_disable(struct regulator *regulator) 24495451781dSDouglas Anderson { 24505451781dSDouglas Anderson struct regulator_dev *rdev = regulator->rdev; 24515451781dSDouglas Anderson 24525451781dSDouglas Anderson lockdep_assert_held_once(&rdev->mutex.base); 24535451781dSDouglas Anderson 24545451781dSDouglas Anderson if (!regulator->enable_count) { 24555451781dSDouglas Anderson rdev_err(rdev, "Underflow of regulator enable count\n"); 24565451781dSDouglas Anderson return -EINVAL; 24575451781dSDouglas Anderson } 24585451781dSDouglas Anderson 24595451781dSDouglas Anderson regulator->enable_count--; 24605451781dSDouglas Anderson if (regulator->uA_load && regulator->enable_count == 0) 24615451781dSDouglas Anderson return drms_uA_update(rdev); 24625451781dSDouglas Anderson 24635451781dSDouglas Anderson return 0; 24645451781dSDouglas Anderson } 24655451781dSDouglas Anderson 24665451781dSDouglas Anderson /* locks held by regulator_enable() */ 24675451781dSDouglas Anderson static int _regulator_enable(struct regulator *regulator) 24685451781dSDouglas Anderson { 24695451781dSDouglas Anderson struct regulator_dev *rdev = regulator->rdev; 2470414c70cbSLiam Girdwood int ret; 2471414c70cbSLiam Girdwood 2472f8702f9eSDmitry Osipenko lockdep_assert_held_once(&rdev->mutex.base); 2473f8702f9eSDmitry Osipenko 24741fc12b05SDouglas Anderson if (rdev->use_count == 0 && rdev->supply) { 24755451781dSDouglas Anderson ret = _regulator_enable(rdev->supply); 2476f8702f9eSDmitry Osipenko if (ret < 0) 2477f8702f9eSDmitry Osipenko return ret; 2478f8702f9eSDmitry Osipenko } 2479f8702f9eSDmitry Osipenko 2480f8702f9eSDmitry Osipenko /* balance only if there are regulators coupled */ 2481f8702f9eSDmitry Osipenko if (rdev->coupling_desc.n_coupled > 1) { 2482f8702f9eSDmitry Osipenko ret = regulator_balance_voltage(rdev, PM_SUSPEND_ON); 2483f8702f9eSDmitry Osipenko if (ret < 0) 2484f8702f9eSDmitry Osipenko goto err_disable_supply; 2485f8702f9eSDmitry Osipenko } 248670cfef26SKrzysztof Kozlowski 24875451781dSDouglas Anderson ret = _regulator_handle_consumer_enable(regulator); 24885451781dSDouglas Anderson if (ret < 0) 24895451781dSDouglas Anderson goto err_disable_supply; 2490cf7bbcdfSMark Brown 2491414c70cbSLiam Girdwood if (rdev->use_count == 0) { 2492cf7bbcdfSMark Brown /* The regulator may on if it's not switchable or left on */ 2493414c70cbSLiam Girdwood ret = _regulator_is_enabled(rdev); 2494414c70cbSLiam Girdwood if (ret == -EINVAL || ret == 0) { 24958a34e979SWEN Pingbo if (!regulator_ops_is_valid(rdev, 2496f8702f9eSDmitry Osipenko REGULATOR_CHANGE_STATUS)) { 2497f8702f9eSDmitry Osipenko ret = -EPERM; 24985451781dSDouglas Anderson goto err_consumer_disable; 2499f8702f9eSDmitry Osipenko } 2500412aec61SDavid Brownell 2501414c70cbSLiam Girdwood ret = _regulator_do_enable(rdev); 2502412aec61SDavid Brownell if (ret < 0) 25035451781dSDouglas Anderson goto err_consumer_disable; 2504414c70cbSLiam Girdwood 2505264b88c9SHarald Geyer _notifier_call_chain(rdev, REGULATOR_EVENT_ENABLE, 2506264b88c9SHarald Geyer NULL); 2507414c70cbSLiam Girdwood } else if (ret < 0) { 2508414c70cbSLiam Girdwood rdev_err(rdev, "is_enabled() failed: %d\n", ret); 25095451781dSDouglas Anderson goto err_consumer_disable; 2510414c70cbSLiam Girdwood } 2511414c70cbSLiam Girdwood /* Fallthrough on positive return values - already enabled */ 2512414c70cbSLiam Girdwood } 2513414c70cbSLiam Girdwood 2514414c70cbSLiam Girdwood rdev->use_count++; 2515414c70cbSLiam Girdwood 2516414c70cbSLiam Girdwood return 0; 2517f8702f9eSDmitry Osipenko 25185451781dSDouglas Anderson err_consumer_disable: 25195451781dSDouglas Anderson _regulator_handle_consumer_disable(regulator); 25205451781dSDouglas Anderson 2521f8702f9eSDmitry Osipenko err_disable_supply: 25221fc12b05SDouglas Anderson if (rdev->use_count == 0 && rdev->supply) 25235451781dSDouglas Anderson _regulator_disable(rdev->supply); 2524f8702f9eSDmitry Osipenko 2525f8702f9eSDmitry Osipenko return ret; 2526414c70cbSLiam Girdwood } 2527414c70cbSLiam Girdwood 2528414c70cbSLiam Girdwood /** 2529414c70cbSLiam Girdwood * regulator_enable - enable regulator output 2530414c70cbSLiam Girdwood * @regulator: regulator source 2531414c70cbSLiam Girdwood * 2532414c70cbSLiam Girdwood * Request that the regulator be enabled with the regulator output at 2533414c70cbSLiam Girdwood * the predefined voltage or current value. Calls to regulator_enable() 2534414c70cbSLiam Girdwood * must be balanced with calls to regulator_disable(). 2535414c70cbSLiam Girdwood * 2536414c70cbSLiam Girdwood * NOTE: the output value can be set by other drivers, boot loader or may be 2537414c70cbSLiam Girdwood * hardwired in the regulator. 2538414c70cbSLiam Girdwood */ 2539414c70cbSLiam Girdwood int regulator_enable(struct regulator *regulator) 2540414c70cbSLiam Girdwood { 2541414c70cbSLiam Girdwood struct regulator_dev *rdev = regulator->rdev; 2542f8702f9eSDmitry Osipenko struct ww_acquire_ctx ww_ctx; 25435451781dSDouglas Anderson int ret; 25446492bc1bSMark Brown 2545f8702f9eSDmitry Osipenko regulator_lock_dependent(rdev, &ww_ctx); 25465451781dSDouglas Anderson ret = _regulator_enable(regulator); 2547f8702f9eSDmitry Osipenko regulator_unlock_dependent(rdev, &ww_ctx); 25483801b86aSMark Brown 2549414c70cbSLiam Girdwood return ret; 2550414c70cbSLiam Girdwood } 2551414c70cbSLiam Girdwood EXPORT_SYMBOL_GPL(regulator_enable); 2552414c70cbSLiam Girdwood 25535c5659d0SMark Brown static int _regulator_do_disable(struct regulator_dev *rdev) 25545c5659d0SMark Brown { 25555c5659d0SMark Brown int ret; 25565c5659d0SMark Brown 25575c5659d0SMark Brown trace_regulator_disable(rdev_get_name(rdev)); 25585c5659d0SMark Brown 2559967cfb18SKim, Milo if (rdev->ena_pin) { 256029d62ec5SDoug Anderson if (rdev->ena_gpio_state) { 2561967cfb18SKim, Milo ret = regulator_ena_gpio_ctrl(rdev, false); 2562967cfb18SKim, Milo if (ret < 0) 2563967cfb18SKim, Milo return ret; 25645c5659d0SMark Brown rdev->ena_gpio_state = 0; 256529d62ec5SDoug Anderson } 25665c5659d0SMark Brown 25675c5659d0SMark Brown } else if (rdev->desc->ops->disable) { 25685c5659d0SMark Brown ret = rdev->desc->ops->disable(rdev); 25695c5659d0SMark Brown if (ret != 0) 25705c5659d0SMark Brown return ret; 25715c5659d0SMark Brown } 25725c5659d0SMark Brown 2573871f5650SGuodong Xu /* cares about last_off_jiffy only if off_on_delay is required by 2574871f5650SGuodong Xu * device. 2575871f5650SGuodong Xu */ 2576871f5650SGuodong Xu if (rdev->desc->off_on_delay) 2577871f5650SGuodong Xu rdev->last_off_jiffy = jiffies; 2578871f5650SGuodong Xu 25795c5659d0SMark Brown trace_regulator_disable_complete(rdev_get_name(rdev)); 25805c5659d0SMark Brown 25815c5659d0SMark Brown return 0; 25825c5659d0SMark Brown } 25835c5659d0SMark Brown 2584414c70cbSLiam Girdwood /* locks held by regulator_disable() */ 25855451781dSDouglas Anderson static int _regulator_disable(struct regulator *regulator) 2586414c70cbSLiam Girdwood { 25875451781dSDouglas Anderson struct regulator_dev *rdev = regulator->rdev; 2588414c70cbSLiam Girdwood int ret = 0; 2589414c70cbSLiam Girdwood 2590f8702f9eSDmitry Osipenko lockdep_assert_held_once(&rdev->mutex.base); 259170cfef26SKrzysztof Kozlowski 2592cd94b505SDavid Brownell if (WARN(rdev->use_count <= 0, 259343e7ee33SJoe Perches "unbalanced disables for %s\n", rdev_get_name(rdev))) 2594cd94b505SDavid Brownell return -EIO; 2595cd94b505SDavid Brownell 2596414c70cbSLiam Girdwood /* are we the last user and permitted to disable ? */ 259760ef66fcSMark Brown if (rdev->use_count == 1 && 259860ef66fcSMark Brown (rdev->constraints && !rdev->constraints->always_on)) { 2599414c70cbSLiam Girdwood 2600414c70cbSLiam Girdwood /* we are last user */ 26018a34e979SWEN Pingbo if (regulator_ops_is_valid(rdev, REGULATOR_CHANGE_STATUS)) { 2602a1c8a551SRichard Fitzgerald ret = _notifier_call_chain(rdev, 2603a1c8a551SRichard Fitzgerald REGULATOR_EVENT_PRE_DISABLE, 2604a1c8a551SRichard Fitzgerald NULL); 2605a1c8a551SRichard Fitzgerald if (ret & NOTIFY_STOP_MASK) 2606a1c8a551SRichard Fitzgerald return -EINVAL; 2607a1c8a551SRichard Fitzgerald 26085c5659d0SMark Brown ret = _regulator_do_disable(rdev); 2609414c70cbSLiam Girdwood if (ret < 0) { 26105da84fd9SJoe Perches rdev_err(rdev, "failed to disable\n"); 2611a1c8a551SRichard Fitzgerald _notifier_call_chain(rdev, 2612a1c8a551SRichard Fitzgerald REGULATOR_EVENT_ABORT_DISABLE, 2613a1c8a551SRichard Fitzgerald NULL); 2614414c70cbSLiam Girdwood return ret; 2615414c70cbSLiam Girdwood } 261666fda75fSMarkus Pargmann _notifier_call_chain(rdev, REGULATOR_EVENT_DISABLE, 261766fda75fSMarkus Pargmann NULL); 2618414c70cbSLiam Girdwood } 2619414c70cbSLiam Girdwood 2620414c70cbSLiam Girdwood rdev->use_count = 0; 2621414c70cbSLiam Girdwood } else if (rdev->use_count > 1) { 2622414c70cbSLiam Girdwood rdev->use_count--; 2623414c70cbSLiam Girdwood } 26243801b86aSMark Brown 26255451781dSDouglas Anderson if (ret == 0) 26265451781dSDouglas Anderson ret = _regulator_handle_consumer_disable(regulator); 26275451781dSDouglas Anderson 2628f8702f9eSDmitry Osipenko if (ret == 0 && rdev->coupling_desc.n_coupled > 1) 2629f8702f9eSDmitry Osipenko ret = regulator_balance_voltage(rdev, PM_SUSPEND_ON); 2630f8702f9eSDmitry Osipenko 26311fc12b05SDouglas Anderson if (ret == 0 && rdev->use_count == 0 && rdev->supply) 26325451781dSDouglas Anderson ret = _regulator_disable(rdev->supply); 2633f8702f9eSDmitry Osipenko 2634414c70cbSLiam Girdwood return ret; 2635414c70cbSLiam Girdwood } 2636414c70cbSLiam Girdwood 2637414c70cbSLiam Girdwood /** 2638414c70cbSLiam Girdwood * regulator_disable - disable regulator output 2639414c70cbSLiam Girdwood * @regulator: regulator source 2640414c70cbSLiam Girdwood * 2641cf7bbcdfSMark Brown * Disable the regulator output voltage or current. Calls to 2642cf7bbcdfSMark Brown * regulator_enable() must be balanced with calls to 2643cf7bbcdfSMark Brown * regulator_disable(). 264469279fb9SMark Brown * 2645414c70cbSLiam Girdwood * NOTE: this will only disable the regulator output if no other consumer 2646cf7bbcdfSMark Brown * devices have it enabled, the regulator device supports disabling and 2647cf7bbcdfSMark Brown * machine constraints permit this operation. 2648414c70cbSLiam Girdwood */ 2649414c70cbSLiam Girdwood int regulator_disable(struct regulator *regulator) 2650414c70cbSLiam Girdwood { 2651412aec61SDavid Brownell struct regulator_dev *rdev = regulator->rdev; 2652f8702f9eSDmitry Osipenko struct ww_acquire_ctx ww_ctx; 26535451781dSDouglas Anderson int ret; 26546492bc1bSMark Brown 2655f8702f9eSDmitry Osipenko regulator_lock_dependent(rdev, &ww_ctx); 26565451781dSDouglas Anderson ret = _regulator_disable(regulator); 2657f8702f9eSDmitry Osipenko regulator_unlock_dependent(rdev, &ww_ctx); 26588cbf811dSJeffrey Carlyle 2659414c70cbSLiam Girdwood return ret; 2660414c70cbSLiam Girdwood } 2661414c70cbSLiam Girdwood EXPORT_SYMBOL_GPL(regulator_disable); 2662414c70cbSLiam Girdwood 2663414c70cbSLiam Girdwood /* locks held by regulator_force_disable() */ 26643801b86aSMark Brown static int _regulator_force_disable(struct regulator_dev *rdev) 2665414c70cbSLiam Girdwood { 2666414c70cbSLiam Girdwood int ret = 0; 2667414c70cbSLiam Girdwood 2668f8702f9eSDmitry Osipenko lockdep_assert_held_once(&rdev->mutex.base); 266970cfef26SKrzysztof Kozlowski 2670a1c8a551SRichard Fitzgerald ret = _notifier_call_chain(rdev, REGULATOR_EVENT_FORCE_DISABLE | 2671a1c8a551SRichard Fitzgerald REGULATOR_EVENT_PRE_DISABLE, NULL); 2672a1c8a551SRichard Fitzgerald if (ret & NOTIFY_STOP_MASK) 2673a1c8a551SRichard Fitzgerald return -EINVAL; 2674a1c8a551SRichard Fitzgerald 267566fda75fSMarkus Pargmann ret = _regulator_do_disable(rdev); 2676414c70cbSLiam Girdwood if (ret < 0) { 26775da84fd9SJoe Perches rdev_err(rdev, "failed to force disable\n"); 2678a1c8a551SRichard Fitzgerald _notifier_call_chain(rdev, REGULATOR_EVENT_FORCE_DISABLE | 2679a1c8a551SRichard Fitzgerald REGULATOR_EVENT_ABORT_DISABLE, NULL); 2680414c70cbSLiam Girdwood return ret; 2681414c70cbSLiam Girdwood } 268266fda75fSMarkus Pargmann 268384b68263SMark Brown _notifier_call_chain(rdev, REGULATOR_EVENT_FORCE_DISABLE | 268484b68263SMark Brown REGULATOR_EVENT_DISABLE, NULL); 2685414c70cbSLiam Girdwood 268666fda75fSMarkus Pargmann return 0; 2687414c70cbSLiam Girdwood } 2688414c70cbSLiam Girdwood 2689414c70cbSLiam Girdwood /** 2690414c70cbSLiam Girdwood * regulator_force_disable - force disable regulator output 2691414c70cbSLiam Girdwood * @regulator: regulator source 2692414c70cbSLiam Girdwood * 2693414c70cbSLiam Girdwood * Forcibly disable the regulator output voltage or current. 2694414c70cbSLiam Girdwood * NOTE: this *will* disable the regulator output even if other consumer 2695414c70cbSLiam Girdwood * devices have it enabled. This should be used for situations when device 2696414c70cbSLiam Girdwood * damage will likely occur if the regulator is not disabled (e.g. over temp). 2697414c70cbSLiam Girdwood */ 2698414c70cbSLiam Girdwood int regulator_force_disable(struct regulator *regulator) 2699414c70cbSLiam Girdwood { 270082d15839SMark Brown struct regulator_dev *rdev = regulator->rdev; 2701f8702f9eSDmitry Osipenko struct ww_acquire_ctx ww_ctx; 2702414c70cbSLiam Girdwood int ret; 2703414c70cbSLiam Girdwood 2704f8702f9eSDmitry Osipenko regulator_lock_dependent(rdev, &ww_ctx); 27055451781dSDouglas Anderson 27063801b86aSMark Brown ret = _regulator_force_disable(regulator->rdev); 27075451781dSDouglas Anderson 27089243a195SMaciej Purski if (rdev->coupling_desc.n_coupled > 1) 27099243a195SMaciej Purski regulator_balance_voltage(rdev, PM_SUSPEND_ON); 27105451781dSDouglas Anderson 27115451781dSDouglas Anderson if (regulator->uA_load) { 27125451781dSDouglas Anderson regulator->uA_load = 0; 27135451781dSDouglas Anderson ret = drms_uA_update(rdev); 27145451781dSDouglas Anderson } 27155451781dSDouglas Anderson 27161fc12b05SDouglas Anderson if (rdev->use_count != 0 && rdev->supply) 27171fc12b05SDouglas Anderson _regulator_disable(rdev->supply); 27188cbf811dSJeffrey Carlyle 27191fc12b05SDouglas Anderson regulator_unlock_dependent(rdev, &ww_ctx); 27208cbf811dSJeffrey Carlyle 2721414c70cbSLiam Girdwood return ret; 2722414c70cbSLiam Girdwood } 2723414c70cbSLiam Girdwood EXPORT_SYMBOL_GPL(regulator_force_disable); 2724414c70cbSLiam Girdwood 2725da07ecd9SMark Brown static void regulator_disable_work(struct work_struct *work) 2726da07ecd9SMark Brown { 2727da07ecd9SMark Brown struct regulator_dev *rdev = container_of(work, struct regulator_dev, 2728da07ecd9SMark Brown disable_work.work); 2729f8702f9eSDmitry Osipenko struct ww_acquire_ctx ww_ctx; 2730da07ecd9SMark Brown int count, i, ret; 27315451781dSDouglas Anderson struct regulator *regulator; 27325451781dSDouglas Anderson int total_count = 0; 2733da07ecd9SMark Brown 2734f8702f9eSDmitry Osipenko regulator_lock_dependent(rdev, &ww_ctx); 2735da07ecd9SMark Brown 2736c9ccaa0cSTirupathi Reddy /* 2737c9ccaa0cSTirupathi Reddy * Workqueue functions queue the new work instance while the previous 2738c9ccaa0cSTirupathi Reddy * work instance is being processed. Cancel the queued work instance 2739c9ccaa0cSTirupathi Reddy * as the work instance under processing does the job of the queued 2740c9ccaa0cSTirupathi Reddy * work instance. 2741c9ccaa0cSTirupathi Reddy */ 2742c9ccaa0cSTirupathi Reddy cancel_delayed_work(&rdev->disable_work); 2743c9ccaa0cSTirupathi Reddy 27445451781dSDouglas Anderson list_for_each_entry(regulator, &rdev->consumer_list, list) { 27455451781dSDouglas Anderson count = regulator->deferred_disables; 27465451781dSDouglas Anderson 27475451781dSDouglas Anderson if (!count) 27485451781dSDouglas Anderson continue; 27495451781dSDouglas Anderson 27505451781dSDouglas Anderson total_count += count; 27515451781dSDouglas Anderson regulator->deferred_disables = 0; 27525451781dSDouglas Anderson 2753da07ecd9SMark Brown for (i = 0; i < count; i++) { 27545451781dSDouglas Anderson ret = _regulator_disable(regulator); 2755da07ecd9SMark Brown if (ret != 0) 2756da07ecd9SMark Brown rdev_err(rdev, "Deferred disable failed: %d\n", ret); 2757da07ecd9SMark Brown } 27585451781dSDouglas Anderson } 27595451781dSDouglas Anderson WARN_ON(!total_count); 2760da07ecd9SMark Brown 2761f8702f9eSDmitry Osipenko if (rdev->coupling_desc.n_coupled > 1) 2762f8702f9eSDmitry Osipenko regulator_balance_voltage(rdev, PM_SUSPEND_ON); 2763f8702f9eSDmitry Osipenko 2764f8702f9eSDmitry Osipenko regulator_unlock_dependent(rdev, &ww_ctx); 2765da07ecd9SMark Brown } 2766da07ecd9SMark Brown 2767da07ecd9SMark Brown /** 2768da07ecd9SMark Brown * regulator_disable_deferred - disable regulator output with delay 2769da07ecd9SMark Brown * @regulator: regulator source 277048f1b4efSKrzysztof Kozlowski * @ms: milliseconds until the regulator is disabled 2771da07ecd9SMark Brown * 2772da07ecd9SMark Brown * Execute regulator_disable() on the regulator after a delay. This 2773da07ecd9SMark Brown * is intended for use with devices that require some time to quiesce. 2774da07ecd9SMark Brown * 2775da07ecd9SMark Brown * NOTE: this will only disable the regulator output if no other consumer 2776da07ecd9SMark Brown * devices have it enabled, the regulator device supports disabling and 2777da07ecd9SMark Brown * machine constraints permit this operation. 2778da07ecd9SMark Brown */ 2779da07ecd9SMark Brown int regulator_disable_deferred(struct regulator *regulator, int ms) 2780da07ecd9SMark Brown { 2781da07ecd9SMark Brown struct regulator_dev *rdev = regulator->rdev; 2782da07ecd9SMark Brown 27832b5a24a0SMark Brown if (!ms) 27842b5a24a0SMark Brown return regulator_disable(regulator); 27852b5a24a0SMark Brown 278666cf9a7eSMaciej Purski regulator_lock(rdev); 27875451781dSDouglas Anderson regulator->deferred_disables++; 2788c9ccaa0cSTirupathi Reddy mod_delayed_work(system_power_efficient_wq, &rdev->disable_work, 2789c9ccaa0cSTirupathi Reddy msecs_to_jiffies(ms)); 279066cf9a7eSMaciej Purski regulator_unlock(rdev); 2791da07ecd9SMark Brown 2792aa59802dSMark Brown return 0; 2793da07ecd9SMark Brown } 2794da07ecd9SMark Brown EXPORT_SYMBOL_GPL(regulator_disable_deferred); 2795da07ecd9SMark Brown 2796414c70cbSLiam Girdwood static int _regulator_is_enabled(struct regulator_dev *rdev) 2797414c70cbSLiam Girdwood { 279865f73508SMark Brown /* A GPIO control always takes precedence */ 27997b74d149SKim, Milo if (rdev->ena_pin) 280065f73508SMark Brown return rdev->ena_gpio_state; 280165f73508SMark Brown 28029a7f6a4cSMark Brown /* If we don't know then assume that the regulator is always on */ 28039332546fSMark Brown if (!rdev->desc->ops->is_enabled) 28049a7f6a4cSMark Brown return 1; 2805414c70cbSLiam Girdwood 28069332546fSMark Brown return rdev->desc->ops->is_enabled(rdev); 2807414c70cbSLiam Girdwood } 2808414c70cbSLiam Girdwood 28093d67fe95SMaciej Purski static int _regulator_list_voltage(struct regulator_dev *rdev, 28103a40cfc3SSascha Hauer unsigned selector, int lock) 28113a40cfc3SSascha Hauer { 28123a40cfc3SSascha Hauer const struct regulator_ops *ops = rdev->desc->ops; 28133a40cfc3SSascha Hauer int ret; 28143a40cfc3SSascha Hauer 28153a40cfc3SSascha Hauer if (rdev->desc->fixed_uV && rdev->desc->n_voltages == 1 && !selector) 28163a40cfc3SSascha Hauer return rdev->desc->fixed_uV; 28173a40cfc3SSascha Hauer 28183a40cfc3SSascha Hauer if (ops->list_voltage) { 28193a40cfc3SSascha Hauer if (selector >= rdev->desc->n_voltages) 28203a40cfc3SSascha Hauer return -EINVAL; 28213a40cfc3SSascha Hauer if (lock) 282266cf9a7eSMaciej Purski regulator_lock(rdev); 28233a40cfc3SSascha Hauer ret = ops->list_voltage(rdev, selector); 28243a40cfc3SSascha Hauer if (lock) 282566cf9a7eSMaciej Purski regulator_unlock(rdev); 2826fd086045SMatthias Kaehlcke } else if (rdev->is_switch && rdev->supply) { 28273d67fe95SMaciej Purski ret = _regulator_list_voltage(rdev->supply->rdev, 28283d67fe95SMaciej Purski selector, lock); 28293a40cfc3SSascha Hauer } else { 28303a40cfc3SSascha Hauer return -EINVAL; 28313a40cfc3SSascha Hauer } 28323a40cfc3SSascha Hauer 28333a40cfc3SSascha Hauer if (ret > 0) { 28343a40cfc3SSascha Hauer if (ret < rdev->constraints->min_uV) 28353a40cfc3SSascha Hauer ret = 0; 28363a40cfc3SSascha Hauer else if (ret > rdev->constraints->max_uV) 28373a40cfc3SSascha Hauer ret = 0; 28383a40cfc3SSascha Hauer } 28393a40cfc3SSascha Hauer 28403a40cfc3SSascha Hauer return ret; 28413a40cfc3SSascha Hauer } 28423a40cfc3SSascha Hauer 2843414c70cbSLiam Girdwood /** 2844414c70cbSLiam Girdwood * regulator_is_enabled - is the regulator output enabled 2845414c70cbSLiam Girdwood * @regulator: regulator source 2846414c70cbSLiam Girdwood * 2847412aec61SDavid Brownell * Returns positive if the regulator driver backing the source/client 2848412aec61SDavid Brownell * has requested that the device be enabled, zero if it hasn't, else a 2849412aec61SDavid Brownell * negative errno code. 2850412aec61SDavid Brownell * 2851412aec61SDavid Brownell * Note that the device backing this regulator handle can have multiple 2852412aec61SDavid Brownell * users, so it might be enabled even if regulator_enable() was never 2853412aec61SDavid Brownell * called for this particular source. 2854414c70cbSLiam Girdwood */ 2855414c70cbSLiam Girdwood int regulator_is_enabled(struct regulator *regulator) 2856414c70cbSLiam Girdwood { 28579332546fSMark Brown int ret; 28589332546fSMark Brown 28596492bc1bSMark Brown if (regulator->always_on) 28606492bc1bSMark Brown return 1; 28616492bc1bSMark Brown 2862f8702f9eSDmitry Osipenko regulator_lock(regulator->rdev); 28639332546fSMark Brown ret = _regulator_is_enabled(regulator->rdev); 2864f8702f9eSDmitry Osipenko regulator_unlock(regulator->rdev); 28659332546fSMark Brown 28669332546fSMark Brown return ret; 2867414c70cbSLiam Girdwood } 2868414c70cbSLiam Girdwood EXPORT_SYMBOL_GPL(regulator_is_enabled); 2869414c70cbSLiam Girdwood 2870414c70cbSLiam Girdwood /** 28714367cfdcSDavid Brownell * regulator_count_voltages - count regulator_list_voltage() selectors 28724367cfdcSDavid Brownell * @regulator: regulator source 28734367cfdcSDavid Brownell * 28744367cfdcSDavid Brownell * Returns number of selectors, or negative errno. Selectors are 28754367cfdcSDavid Brownell * numbered starting at zero, and typically correspond to bitfields 28764367cfdcSDavid Brownell * in hardware registers. 28774367cfdcSDavid Brownell */ 28784367cfdcSDavid Brownell int regulator_count_voltages(struct regulator *regulator) 28794367cfdcSDavid Brownell { 28804367cfdcSDavid Brownell struct regulator_dev *rdev = regulator->rdev; 28814367cfdcSDavid Brownell 288226988efeSJavier Martinez Canillas if (rdev->desc->n_voltages) 288326988efeSJavier Martinez Canillas return rdev->desc->n_voltages; 288426988efeSJavier Martinez Canillas 2885fd086045SMatthias Kaehlcke if (!rdev->is_switch || !rdev->supply) 288626988efeSJavier Martinez Canillas return -EINVAL; 288726988efeSJavier Martinez Canillas 288826988efeSJavier Martinez Canillas return regulator_count_voltages(rdev->supply); 28894367cfdcSDavid Brownell } 28904367cfdcSDavid Brownell EXPORT_SYMBOL_GPL(regulator_count_voltages); 28914367cfdcSDavid Brownell 28924367cfdcSDavid Brownell /** 28934367cfdcSDavid Brownell * regulator_list_voltage - enumerate supported voltages 28944367cfdcSDavid Brownell * @regulator: regulator source 28954367cfdcSDavid Brownell * @selector: identify voltage to list 28964367cfdcSDavid Brownell * Context: can sleep 28974367cfdcSDavid Brownell * 28984367cfdcSDavid Brownell * Returns a voltage that can be passed to @regulator_set_voltage(), 289988393161SThomas Weber * zero if this selector code can't be used on this system, or a 29004367cfdcSDavid Brownell * negative errno. 29014367cfdcSDavid Brownell */ 29024367cfdcSDavid Brownell int regulator_list_voltage(struct regulator *regulator, unsigned selector) 29034367cfdcSDavid Brownell { 29043d67fe95SMaciej Purski return _regulator_list_voltage(regulator->rdev, selector, 1); 29054367cfdcSDavid Brownell } 29064367cfdcSDavid Brownell EXPORT_SYMBOL_GPL(regulator_list_voltage); 29074367cfdcSDavid Brownell 29084367cfdcSDavid Brownell /** 290904eca28cSTuomas Tynkkynen * regulator_get_regmap - get the regulator's register map 291004eca28cSTuomas Tynkkynen * @regulator: regulator source 291104eca28cSTuomas Tynkkynen * 291204eca28cSTuomas Tynkkynen * Returns the register map for the given regulator, or an ERR_PTR value 291304eca28cSTuomas Tynkkynen * if the regulator doesn't use regmap. 291404eca28cSTuomas Tynkkynen */ 291504eca28cSTuomas Tynkkynen struct regmap *regulator_get_regmap(struct regulator *regulator) 291604eca28cSTuomas Tynkkynen { 291704eca28cSTuomas Tynkkynen struct regmap *map = regulator->rdev->regmap; 291804eca28cSTuomas Tynkkynen 291904eca28cSTuomas Tynkkynen return map ? map : ERR_PTR(-EOPNOTSUPP); 292004eca28cSTuomas Tynkkynen } 292104eca28cSTuomas Tynkkynen 292204eca28cSTuomas Tynkkynen /** 292304eca28cSTuomas Tynkkynen * regulator_get_hardware_vsel_register - get the HW voltage selector register 292404eca28cSTuomas Tynkkynen * @regulator: regulator source 292504eca28cSTuomas Tynkkynen * @vsel_reg: voltage selector register, output parameter 292604eca28cSTuomas Tynkkynen * @vsel_mask: mask for voltage selector bitfield, output parameter 292704eca28cSTuomas Tynkkynen * 292804eca28cSTuomas Tynkkynen * Returns the hardware register offset and bitmask used for setting the 292904eca28cSTuomas Tynkkynen * regulator voltage. This might be useful when configuring voltage-scaling 293004eca28cSTuomas Tynkkynen * hardware or firmware that can make I2C requests behind the kernel's back, 293104eca28cSTuomas Tynkkynen * for example. 293204eca28cSTuomas Tynkkynen * 293304eca28cSTuomas Tynkkynen * On success, the output parameters @vsel_reg and @vsel_mask are filled in 293404eca28cSTuomas Tynkkynen * and 0 is returned, otherwise a negative errno is returned. 293504eca28cSTuomas Tynkkynen */ 293604eca28cSTuomas Tynkkynen int regulator_get_hardware_vsel_register(struct regulator *regulator, 293704eca28cSTuomas Tynkkynen unsigned *vsel_reg, 293804eca28cSTuomas Tynkkynen unsigned *vsel_mask) 293904eca28cSTuomas Tynkkynen { 294004eca28cSTuomas Tynkkynen struct regulator_dev *rdev = regulator->rdev; 294139f5460dSGuodong Xu const struct regulator_ops *ops = rdev->desc->ops; 294204eca28cSTuomas Tynkkynen 294304eca28cSTuomas Tynkkynen if (ops->set_voltage_sel != regulator_set_voltage_sel_regmap) 294404eca28cSTuomas Tynkkynen return -EOPNOTSUPP; 294504eca28cSTuomas Tynkkynen 294604eca28cSTuomas Tynkkynen *vsel_reg = rdev->desc->vsel_reg; 294704eca28cSTuomas Tynkkynen *vsel_mask = rdev->desc->vsel_mask; 294804eca28cSTuomas Tynkkynen 294904eca28cSTuomas Tynkkynen return 0; 295004eca28cSTuomas Tynkkynen } 295104eca28cSTuomas Tynkkynen EXPORT_SYMBOL_GPL(regulator_get_hardware_vsel_register); 295204eca28cSTuomas Tynkkynen 295304eca28cSTuomas Tynkkynen /** 295404eca28cSTuomas Tynkkynen * regulator_list_hardware_vsel - get the HW-specific register value for a selector 295504eca28cSTuomas Tynkkynen * @regulator: regulator source 295604eca28cSTuomas Tynkkynen * @selector: identify voltage to list 295704eca28cSTuomas Tynkkynen * 295804eca28cSTuomas Tynkkynen * Converts the selector to a hardware-specific voltage selector that can be 295904eca28cSTuomas Tynkkynen * directly written to the regulator registers. The address of the voltage 296004eca28cSTuomas Tynkkynen * register can be determined by calling @regulator_get_hardware_vsel_register. 296104eca28cSTuomas Tynkkynen * 296204eca28cSTuomas Tynkkynen * On error a negative errno is returned. 296304eca28cSTuomas Tynkkynen */ 296404eca28cSTuomas Tynkkynen int regulator_list_hardware_vsel(struct regulator *regulator, 296504eca28cSTuomas Tynkkynen unsigned selector) 296604eca28cSTuomas Tynkkynen { 296704eca28cSTuomas Tynkkynen struct regulator_dev *rdev = regulator->rdev; 296839f5460dSGuodong Xu const struct regulator_ops *ops = rdev->desc->ops; 296904eca28cSTuomas Tynkkynen 297004eca28cSTuomas Tynkkynen if (selector >= rdev->desc->n_voltages) 297104eca28cSTuomas Tynkkynen return -EINVAL; 297204eca28cSTuomas Tynkkynen if (ops->set_voltage_sel != regulator_set_voltage_sel_regmap) 297304eca28cSTuomas Tynkkynen return -EOPNOTSUPP; 297404eca28cSTuomas Tynkkynen 297504eca28cSTuomas Tynkkynen return selector; 297604eca28cSTuomas Tynkkynen } 297704eca28cSTuomas Tynkkynen EXPORT_SYMBOL_GPL(regulator_list_hardware_vsel); 297804eca28cSTuomas Tynkkynen 297904eca28cSTuomas Tynkkynen /** 29802a668a8bSPaul Walmsley * regulator_get_linear_step - return the voltage step size between VSEL values 29812a668a8bSPaul Walmsley * @regulator: regulator source 29822a668a8bSPaul Walmsley * 29832a668a8bSPaul Walmsley * Returns the voltage step size between VSEL values for linear 29842a668a8bSPaul Walmsley * regulators, or return 0 if the regulator isn't a linear regulator. 29852a668a8bSPaul Walmsley */ 29862a668a8bSPaul Walmsley unsigned int regulator_get_linear_step(struct regulator *regulator) 29872a668a8bSPaul Walmsley { 29882a668a8bSPaul Walmsley struct regulator_dev *rdev = regulator->rdev; 29892a668a8bSPaul Walmsley 29902a668a8bSPaul Walmsley return rdev->desc->uV_step; 29912a668a8bSPaul Walmsley } 29922a668a8bSPaul Walmsley EXPORT_SYMBOL_GPL(regulator_get_linear_step); 29932a668a8bSPaul Walmsley 29942a668a8bSPaul Walmsley /** 2995a7a1ad90SMark Brown * regulator_is_supported_voltage - check if a voltage range can be supported 2996a7a1ad90SMark Brown * 2997a7a1ad90SMark Brown * @regulator: Regulator to check. 2998a7a1ad90SMark Brown * @min_uV: Minimum required voltage in uV. 2999a7a1ad90SMark Brown * @max_uV: Maximum required voltage in uV. 3000a7a1ad90SMark Brown * 300149820944SJorge Ramirez-Ortiz * Returns a boolean. 3002a7a1ad90SMark Brown */ 3003a7a1ad90SMark Brown int regulator_is_supported_voltage(struct regulator *regulator, 3004a7a1ad90SMark Brown int min_uV, int max_uV) 3005a7a1ad90SMark Brown { 3006c5f3939bSMark Brown struct regulator_dev *rdev = regulator->rdev; 3007a7a1ad90SMark Brown int i, voltages, ret; 3008a7a1ad90SMark Brown 3009c5f3939bSMark Brown /* If we can't change voltage check the current voltage */ 30108a34e979SWEN Pingbo if (!regulator_ops_is_valid(rdev, REGULATOR_CHANGE_VOLTAGE)) { 3011c5f3939bSMark Brown ret = regulator_get_voltage(regulator); 3012c5f3939bSMark Brown if (ret >= 0) 30130d25d09dSJingoo Han return min_uV <= ret && ret <= max_uV; 3014c5f3939bSMark Brown else 3015c5f3939bSMark Brown return ret; 3016c5f3939bSMark Brown } 3017c5f3939bSMark Brown 3018bd7a2b60SPawel Moll /* Any voltage within constrains range is fine? */ 3019bd7a2b60SPawel Moll if (rdev->desc->continuous_voltage_range) 3020bd7a2b60SPawel Moll return min_uV >= rdev->constraints->min_uV && 3021bd7a2b60SPawel Moll max_uV <= rdev->constraints->max_uV; 3022bd7a2b60SPawel Moll 3023a7a1ad90SMark Brown ret = regulator_count_voltages(regulator); 3024a7a1ad90SMark Brown if (ret < 0) 302549820944SJorge Ramirez-Ortiz return 0; 3026a7a1ad90SMark Brown voltages = ret; 3027a7a1ad90SMark Brown 3028a7a1ad90SMark Brown for (i = 0; i < voltages; i++) { 3029a7a1ad90SMark Brown ret = regulator_list_voltage(regulator, i); 3030a7a1ad90SMark Brown 3031a7a1ad90SMark Brown if (ret >= min_uV && ret <= max_uV) 3032a7a1ad90SMark Brown return 1; 3033a7a1ad90SMark Brown } 3034a7a1ad90SMark Brown 3035a7a1ad90SMark Brown return 0; 3036a7a1ad90SMark Brown } 3037a398eaa2SMark Brown EXPORT_SYMBOL_GPL(regulator_is_supported_voltage); 3038a7a1ad90SMark Brown 3039a204f41eSSascha Hauer static int regulator_map_voltage(struct regulator_dev *rdev, int min_uV, 3040a204f41eSSascha Hauer int max_uV) 3041a204f41eSSascha Hauer { 3042a204f41eSSascha Hauer const struct regulator_desc *desc = rdev->desc; 3043a204f41eSSascha Hauer 3044a204f41eSSascha Hauer if (desc->ops->map_voltage) 3045a204f41eSSascha Hauer return desc->ops->map_voltage(rdev, min_uV, max_uV); 3046a204f41eSSascha Hauer 3047a204f41eSSascha Hauer if (desc->ops->list_voltage == regulator_list_voltage_linear) 3048a204f41eSSascha Hauer return regulator_map_voltage_linear(rdev, min_uV, max_uV); 3049a204f41eSSascha Hauer 3050a204f41eSSascha Hauer if (desc->ops->list_voltage == regulator_list_voltage_linear_range) 3051a204f41eSSascha Hauer return regulator_map_voltage_linear_range(rdev, min_uV, max_uV); 3052a204f41eSSascha Hauer 305318e4b55fSMatti Vaittinen if (desc->ops->list_voltage == 305418e4b55fSMatti Vaittinen regulator_list_voltage_pickable_linear_range) 305518e4b55fSMatti Vaittinen return regulator_map_voltage_pickable_linear_range(rdev, 305618e4b55fSMatti Vaittinen min_uV, max_uV); 305718e4b55fSMatti Vaittinen 3058a204f41eSSascha Hauer return regulator_map_voltage_iterate(rdev, min_uV, max_uV); 3059a204f41eSSascha Hauer } 3060a204f41eSSascha Hauer 30617179569aSHeiko Stübner static int _regulator_call_set_voltage(struct regulator_dev *rdev, 30627179569aSHeiko Stübner int min_uV, int max_uV, 30637179569aSHeiko Stübner unsigned *selector) 30647179569aSHeiko Stübner { 30657179569aSHeiko Stübner struct pre_voltage_change_data data; 30667179569aSHeiko Stübner int ret; 30677179569aSHeiko Stübner 30687179569aSHeiko Stübner data.old_uV = _regulator_get_voltage(rdev); 30697179569aSHeiko Stübner data.min_uV = min_uV; 30707179569aSHeiko Stübner data.max_uV = max_uV; 30717179569aSHeiko Stübner ret = _notifier_call_chain(rdev, REGULATOR_EVENT_PRE_VOLTAGE_CHANGE, 30727179569aSHeiko Stübner &data); 30737179569aSHeiko Stübner if (ret & NOTIFY_STOP_MASK) 30747179569aSHeiko Stübner return -EINVAL; 30757179569aSHeiko Stübner 30767179569aSHeiko Stübner ret = rdev->desc->ops->set_voltage(rdev, min_uV, max_uV, selector); 30777179569aSHeiko Stübner if (ret >= 0) 30787179569aSHeiko Stübner return ret; 30797179569aSHeiko Stübner 30807179569aSHeiko Stübner _notifier_call_chain(rdev, REGULATOR_EVENT_ABORT_VOLTAGE_CHANGE, 30817179569aSHeiko Stübner (void *)data.old_uV); 30827179569aSHeiko Stübner 30837179569aSHeiko Stübner return ret; 30847179569aSHeiko Stübner } 30857179569aSHeiko Stübner 30867179569aSHeiko Stübner static int _regulator_call_set_voltage_sel(struct regulator_dev *rdev, 30877179569aSHeiko Stübner int uV, unsigned selector) 30887179569aSHeiko Stübner { 30897179569aSHeiko Stübner struct pre_voltage_change_data data; 30907179569aSHeiko Stübner int ret; 30917179569aSHeiko Stübner 30927179569aSHeiko Stübner data.old_uV = _regulator_get_voltage(rdev); 30937179569aSHeiko Stübner data.min_uV = uV; 30947179569aSHeiko Stübner data.max_uV = uV; 30957179569aSHeiko Stübner ret = _notifier_call_chain(rdev, REGULATOR_EVENT_PRE_VOLTAGE_CHANGE, 30967179569aSHeiko Stübner &data); 30977179569aSHeiko Stübner if (ret & NOTIFY_STOP_MASK) 30987179569aSHeiko Stübner return -EINVAL; 30997179569aSHeiko Stübner 31007179569aSHeiko Stübner ret = rdev->desc->ops->set_voltage_sel(rdev, selector); 31017179569aSHeiko Stübner if (ret >= 0) 31027179569aSHeiko Stübner return ret; 31037179569aSHeiko Stübner 31047179569aSHeiko Stübner _notifier_call_chain(rdev, REGULATOR_EVENT_ABORT_VOLTAGE_CHANGE, 31057179569aSHeiko Stübner (void *)data.old_uV); 31067179569aSHeiko Stübner 31077179569aSHeiko Stübner return ret; 31087179569aSHeiko Stübner } 31097179569aSHeiko Stübner 311073e705bfSMatthias Kaehlcke static int _regulator_set_voltage_time(struct regulator_dev *rdev, 311173e705bfSMatthias Kaehlcke int old_uV, int new_uV) 311273e705bfSMatthias Kaehlcke { 311373e705bfSMatthias Kaehlcke unsigned int ramp_delay = 0; 311473e705bfSMatthias Kaehlcke 311573e705bfSMatthias Kaehlcke if (rdev->constraints->ramp_delay) 311673e705bfSMatthias Kaehlcke ramp_delay = rdev->constraints->ramp_delay; 311773e705bfSMatthias Kaehlcke else if (rdev->desc->ramp_delay) 311873e705bfSMatthias Kaehlcke ramp_delay = rdev->desc->ramp_delay; 3119d6c1dc3fSLaxman Dewangan else if (rdev->constraints->settling_time) 3120d6c1dc3fSLaxman Dewangan return rdev->constraints->settling_time; 31213ffad468SMatthias Kaehlcke else if (rdev->constraints->settling_time_up && 31223ffad468SMatthias Kaehlcke (new_uV > old_uV)) 31233ffad468SMatthias Kaehlcke return rdev->constraints->settling_time_up; 31243ffad468SMatthias Kaehlcke else if (rdev->constraints->settling_time_down && 31253ffad468SMatthias Kaehlcke (new_uV < old_uV)) 31263ffad468SMatthias Kaehlcke return rdev->constraints->settling_time_down; 312773e705bfSMatthias Kaehlcke 312873e705bfSMatthias Kaehlcke if (ramp_delay == 0) { 3129ba14fa1aSH. Nikolaus Schaller rdev_dbg(rdev, "ramp_delay not set\n"); 313073e705bfSMatthias Kaehlcke return 0; 313173e705bfSMatthias Kaehlcke } 313273e705bfSMatthias Kaehlcke 313373e705bfSMatthias Kaehlcke return DIV_ROUND_UP(abs(new_uV - old_uV), ramp_delay); 313473e705bfSMatthias Kaehlcke } 313573e705bfSMatthias Kaehlcke 313675790251SMark Brown static int _regulator_do_set_voltage(struct regulator_dev *rdev, 313775790251SMark Brown int min_uV, int max_uV) 313875790251SMark Brown { 313975790251SMark Brown int ret; 314077af1b26SLinus Walleij int delay = 0; 3141e113d792SMark Brown int best_val = 0; 314275790251SMark Brown unsigned int selector; 3143eba41a5eSAxel Lin int old_selector = -1; 314457995a48SMatthias Kaehlcke const struct regulator_ops *ops = rdev->desc->ops; 314573e705bfSMatthias Kaehlcke int old_uV = _regulator_get_voltage(rdev); 314675790251SMark Brown 314775790251SMark Brown trace_regulator_set_voltage(rdev_get_name(rdev), min_uV, max_uV); 314875790251SMark Brown 3149bf5892a8SMark Brown min_uV += rdev->constraints->uV_offset; 3150bf5892a8SMark Brown max_uV += rdev->constraints->uV_offset; 3151bf5892a8SMark Brown 315277af1b26SLinus Walleij /* 315377af1b26SLinus Walleij * If we can't obtain the old selector there is not enough 315477af1b26SLinus Walleij * info to call set_voltage_time_sel(). 315577af1b26SLinus Walleij */ 31568b7485efSAxel Lin if (_regulator_is_enabled(rdev) && 315757995a48SMatthias Kaehlcke ops->set_voltage_time_sel && ops->get_voltage_sel) { 315857995a48SMatthias Kaehlcke old_selector = ops->get_voltage_sel(rdev); 3159eba41a5eSAxel Lin if (old_selector < 0) 3160eba41a5eSAxel Lin return old_selector; 3161eba41a5eSAxel Lin } 316277af1b26SLinus Walleij 316357995a48SMatthias Kaehlcke if (ops->set_voltage) { 31647179569aSHeiko Stübner ret = _regulator_call_set_voltage(rdev, min_uV, max_uV, 316575790251SMark Brown &selector); 3166e113d792SMark Brown 3167e113d792SMark Brown if (ret >= 0) { 316857995a48SMatthias Kaehlcke if (ops->list_voltage) 316957995a48SMatthias Kaehlcke best_val = ops->list_voltage(rdev, 3170e113d792SMark Brown selector); 3171e113d792SMark Brown else 3172e113d792SMark Brown best_val = _regulator_get_voltage(rdev); 3173e113d792SMark Brown } 3174e113d792SMark Brown 317557995a48SMatthias Kaehlcke } else if (ops->set_voltage_sel) { 3176a204f41eSSascha Hauer ret = regulator_map_voltage(rdev, min_uV, max_uV); 3177e843fc46SMark Brown if (ret >= 0) { 317857995a48SMatthias Kaehlcke best_val = ops->list_voltage(rdev, ret); 3179e113d792SMark Brown if (min_uV <= best_val && max_uV >= best_val) { 3180e843fc46SMark Brown selector = ret; 3181c66a566aSAxel Lin if (old_selector == selector) 3182c66a566aSAxel Lin ret = 0; 3183c66a566aSAxel Lin else 31847179569aSHeiko Stübner ret = _regulator_call_set_voltage_sel( 31857179569aSHeiko Stübner rdev, best_val, selector); 3186e113d792SMark Brown } else { 3187e113d792SMark Brown ret = -EINVAL; 3188e113d792SMark Brown } 3189e843fc46SMark Brown } 3190e8eef82bSMark Brown } else { 3191e8eef82bSMark Brown ret = -EINVAL; 3192e8eef82bSMark Brown } 3193e8eef82bSMark Brown 319431dfe686SMatthias Kaehlcke if (ret) 319531dfe686SMatthias Kaehlcke goto out; 3196eba41a5eSAxel Lin 319773e705bfSMatthias Kaehlcke if (ops->set_voltage_time_sel) { 319873e705bfSMatthias Kaehlcke /* 319973e705bfSMatthias Kaehlcke * Call set_voltage_time_sel if successfully obtained 320073e705bfSMatthias Kaehlcke * old_selector 320173e705bfSMatthias Kaehlcke */ 320273e705bfSMatthias Kaehlcke if (old_selector >= 0 && old_selector != selector) 320373e705bfSMatthias Kaehlcke delay = ops->set_voltage_time_sel(rdev, old_selector, 320473e705bfSMatthias Kaehlcke selector); 320573e705bfSMatthias Kaehlcke } else { 320673e705bfSMatthias Kaehlcke if (old_uV != best_val) { 320773e705bfSMatthias Kaehlcke if (ops->set_voltage_time) 320873e705bfSMatthias Kaehlcke delay = ops->set_voltage_time(rdev, old_uV, 320973e705bfSMatthias Kaehlcke best_val); 321073e705bfSMatthias Kaehlcke else 321173e705bfSMatthias Kaehlcke delay = _regulator_set_voltage_time(rdev, 321273e705bfSMatthias Kaehlcke old_uV, 321373e705bfSMatthias Kaehlcke best_val); 321473e705bfSMatthias Kaehlcke } 321573e705bfSMatthias Kaehlcke } 321673e705bfSMatthias Kaehlcke 3217eba41a5eSAxel Lin if (delay < 0) { 321873e705bfSMatthias Kaehlcke rdev_warn(rdev, "failed to get delay: %d\n", delay); 3219eba41a5eSAxel Lin delay = 0; 3220e8eef82bSMark Brown } 322175790251SMark Brown 322277af1b26SLinus Walleij /* Insert any necessary delays */ 322377af1b26SLinus Walleij if (delay >= 1000) { 322477af1b26SLinus Walleij mdelay(delay / 1000); 322577af1b26SLinus Walleij udelay(delay % 1000); 322677af1b26SLinus Walleij } else if (delay) { 322777af1b26SLinus Walleij udelay(delay); 322877af1b26SLinus Walleij } 322977af1b26SLinus Walleij 323031dfe686SMatthias Kaehlcke if (best_val >= 0) { 32312f6c797fSAxel Lin unsigned long data = best_val; 32322f6c797fSAxel Lin 3233ded06a52SMark Brown _notifier_call_chain(rdev, REGULATOR_EVENT_VOLTAGE_CHANGE, 32342f6c797fSAxel Lin (void *)data); 32352f6c797fSAxel Lin } 3236ded06a52SMark Brown 323731dfe686SMatthias Kaehlcke out: 3238eba41a5eSAxel Lin trace_regulator_set_voltage_complete(rdev_get_name(rdev), best_val); 323975790251SMark Brown 324075790251SMark Brown return ret; 324175790251SMark Brown } 324275790251SMark Brown 3243f7efad10SChunyan Zhang static int _regulator_do_set_suspend_voltage(struct regulator_dev *rdev, 3244f7efad10SChunyan Zhang int min_uV, int max_uV, suspend_state_t state) 3245f7efad10SChunyan Zhang { 3246f7efad10SChunyan Zhang struct regulator_state *rstate; 3247f7efad10SChunyan Zhang int uV, sel; 3248f7efad10SChunyan Zhang 3249f7efad10SChunyan Zhang rstate = regulator_get_suspend_state(rdev, state); 3250f7efad10SChunyan Zhang if (rstate == NULL) 3251f7efad10SChunyan Zhang return -EINVAL; 3252f7efad10SChunyan Zhang 3253f7efad10SChunyan Zhang if (min_uV < rstate->min_uV) 3254f7efad10SChunyan Zhang min_uV = rstate->min_uV; 3255f7efad10SChunyan Zhang if (max_uV > rstate->max_uV) 3256f7efad10SChunyan Zhang max_uV = rstate->max_uV; 3257f7efad10SChunyan Zhang 3258f7efad10SChunyan Zhang sel = regulator_map_voltage(rdev, min_uV, max_uV); 3259f7efad10SChunyan Zhang if (sel < 0) 3260f7efad10SChunyan Zhang return sel; 3261f7efad10SChunyan Zhang 3262f7efad10SChunyan Zhang uV = rdev->desc->ops->list_voltage(rdev, sel); 3263f7efad10SChunyan Zhang if (uV >= min_uV && uV <= max_uV) 3264f7efad10SChunyan Zhang rstate->uV = uV; 3265f7efad10SChunyan Zhang 3266f7efad10SChunyan Zhang return 0; 3267f7efad10SChunyan Zhang } 3268f7efad10SChunyan Zhang 3269a9f226bcSSascha Hauer static int regulator_set_voltage_unlocked(struct regulator *regulator, 3270c360a6dfSChunyan Zhang int min_uV, int max_uV, 3271c360a6dfSChunyan Zhang suspend_state_t state) 3272414c70cbSLiam Girdwood { 3273414c70cbSLiam Girdwood struct regulator_dev *rdev = regulator->rdev; 3274c360a6dfSChunyan Zhang struct regulator_voltage *voltage = ®ulator->voltage[state]; 327595a3c23aSMark Brown int ret = 0; 327692d7a558SPaolo Pisati int old_min_uV, old_max_uV; 3277c00dc359SBjorn Andersson int current_uV; 3278414c70cbSLiam Girdwood 327995a3c23aSMark Brown /* If we're setting the same range as last time the change 328095a3c23aSMark Brown * should be a noop (some cpufreq implementations use the same 328195a3c23aSMark Brown * voltage for multiple frequencies, for example). 328295a3c23aSMark Brown */ 3283c360a6dfSChunyan Zhang if (voltage->min_uV == min_uV && voltage->max_uV == max_uV) 328495a3c23aSMark Brown goto out; 328595a3c23aSMark Brown 3286c00dc359SBjorn Andersson /* If we're trying to set a range that overlaps the current voltage, 3287d3fb9800SViresh Kumar * return successfully even though the regulator does not support 3288c00dc359SBjorn Andersson * changing the voltage. 3289c00dc359SBjorn Andersson */ 32908a34e979SWEN Pingbo if (!regulator_ops_is_valid(rdev, REGULATOR_CHANGE_VOLTAGE)) { 3291c00dc359SBjorn Andersson current_uV = _regulator_get_voltage(rdev); 3292c00dc359SBjorn Andersson if (min_uV <= current_uV && current_uV <= max_uV) { 3293c360a6dfSChunyan Zhang voltage->min_uV = min_uV; 3294c360a6dfSChunyan Zhang voltage->max_uV = max_uV; 3295c00dc359SBjorn Andersson goto out; 3296c00dc359SBjorn Andersson } 3297c00dc359SBjorn Andersson } 3298c00dc359SBjorn Andersson 3299414c70cbSLiam Girdwood /* sanity check */ 3300e8eef82bSMark Brown if (!rdev->desc->ops->set_voltage && 3301e8eef82bSMark Brown !rdev->desc->ops->set_voltage_sel) { 3302414c70cbSLiam Girdwood ret = -EINVAL; 3303414c70cbSLiam Girdwood goto out; 3304414c70cbSLiam Girdwood } 3305414c70cbSLiam Girdwood 3306414c70cbSLiam Girdwood /* constraints check */ 3307414c70cbSLiam Girdwood ret = regulator_check_voltage(rdev, &min_uV, &max_uV); 3308414c70cbSLiam Girdwood if (ret < 0) 3309414c70cbSLiam Girdwood goto out; 331092d7a558SPaolo Pisati 331192d7a558SPaolo Pisati /* restore original values in case of error */ 3312c360a6dfSChunyan Zhang old_min_uV = voltage->min_uV; 3313c360a6dfSChunyan Zhang old_max_uV = voltage->max_uV; 3314c360a6dfSChunyan Zhang voltage->min_uV = min_uV; 3315c360a6dfSChunyan Zhang voltage->max_uV = max_uV; 33163a93f2a9SMark Brown 33179243a195SMaciej Purski /* for not coupled regulators this will just set the voltage */ 33189243a195SMaciej Purski ret = regulator_balance_voltage(rdev, state); 331970b46491SSteve Twiss if (ret < 0) { 33209243a195SMaciej Purski voltage->min_uV = old_min_uV; 33219243a195SMaciej Purski voltage->max_uV = old_max_uV; 332270b46491SSteve Twiss } 33239243a195SMaciej Purski 332470b46491SSteve Twiss out: 33259243a195SMaciej Purski return ret; 33269243a195SMaciej Purski } 33279243a195SMaciej Purski 33289243a195SMaciej Purski static int regulator_set_voltage_rdev(struct regulator_dev *rdev, int min_uV, 33299243a195SMaciej Purski int max_uV, suspend_state_t state) 33309243a195SMaciej Purski { 33319243a195SMaciej Purski int best_supply_uV = 0; 33329243a195SMaciej Purski int supply_change_uV = 0; 33339243a195SMaciej Purski int ret; 33349243a195SMaciej Purski 333543fc99f2SMark Brown if (rdev->supply && 333643fc99f2SMark Brown regulator_ops_is_valid(rdev->supply->rdev, 333743fc99f2SMark Brown REGULATOR_CHANGE_VOLTAGE) && 33382c2874b1STirupathi Reddy (rdev->desc->min_dropout_uV || !(rdev->desc->ops->get_voltage || 33392c2874b1STirupathi Reddy rdev->desc->ops->get_voltage_sel))) { 3340fc42112cSSascha Hauer int current_supply_uV; 3341fc42112cSSascha Hauer int selector; 3342fc42112cSSascha Hauer 3343fc42112cSSascha Hauer selector = regulator_map_voltage(rdev, min_uV, max_uV); 3344fc42112cSSascha Hauer if (selector < 0) { 3345fc42112cSSascha Hauer ret = selector; 33469243a195SMaciej Purski goto out; 3347fc42112cSSascha Hauer } 3348fc42112cSSascha Hauer 334900cb9f4fSMark Brown best_supply_uV = _regulator_list_voltage(rdev, selector, 0); 3350fc42112cSSascha Hauer if (best_supply_uV < 0) { 3351fc42112cSSascha Hauer ret = best_supply_uV; 33529243a195SMaciej Purski goto out; 3353fc42112cSSascha Hauer } 3354fc42112cSSascha Hauer 3355fc42112cSSascha Hauer best_supply_uV += rdev->desc->min_dropout_uV; 3356fc42112cSSascha Hauer 3357fc42112cSSascha Hauer current_supply_uV = _regulator_get_voltage(rdev->supply->rdev); 3358fc42112cSSascha Hauer if (current_supply_uV < 0) { 3359fc42112cSSascha Hauer ret = current_supply_uV; 33609243a195SMaciej Purski goto out; 3361fc42112cSSascha Hauer } 3362fc42112cSSascha Hauer 3363fc42112cSSascha Hauer supply_change_uV = best_supply_uV - current_supply_uV; 3364fc42112cSSascha Hauer } 3365fc42112cSSascha Hauer 3366fc42112cSSascha Hauer if (supply_change_uV > 0) { 3367fc42112cSSascha Hauer ret = regulator_set_voltage_unlocked(rdev->supply, 3368c360a6dfSChunyan Zhang best_supply_uV, INT_MAX, state); 3369fc42112cSSascha Hauer if (ret) { 3370fc42112cSSascha Hauer dev_err(&rdev->dev, "Failed to increase supply voltage: %d\n", 3371fc42112cSSascha Hauer ret); 33729243a195SMaciej Purski goto out; 3373fc42112cSSascha Hauer } 3374fc42112cSSascha Hauer } 3375fc42112cSSascha Hauer 3376f7efad10SChunyan Zhang if (state == PM_SUSPEND_ON) 337775790251SMark Brown ret = _regulator_do_set_voltage(rdev, min_uV, max_uV); 3378f7efad10SChunyan Zhang else 3379f7efad10SChunyan Zhang ret = _regulator_do_set_suspend_voltage(rdev, min_uV, 3380f7efad10SChunyan Zhang max_uV, state); 338192d7a558SPaolo Pisati if (ret < 0) 33829243a195SMaciej Purski goto out; 338302fa3ec0SMark Brown 3384fc42112cSSascha Hauer if (supply_change_uV < 0) { 3385fc42112cSSascha Hauer ret = regulator_set_voltage_unlocked(rdev->supply, 3386c360a6dfSChunyan Zhang best_supply_uV, INT_MAX, state); 3387fc42112cSSascha Hauer if (ret) 3388fc42112cSSascha Hauer dev_warn(&rdev->dev, "Failed to decrease supply voltage: %d\n", 3389fc42112cSSascha Hauer ret); 3390fc42112cSSascha Hauer /* No need to fail here */ 3391fc42112cSSascha Hauer ret = 0; 3392fc42112cSSascha Hauer } 3393fc42112cSSascha Hauer 3394414c70cbSLiam Girdwood out: 3395414c70cbSLiam Girdwood return ret; 339669686176SMaciej Purski } 339769686176SMaciej Purski 339885254bcfSDmitry Osipenko static int regulator_limit_voltage_step(struct regulator_dev *rdev, 339985254bcfSDmitry Osipenko int *current_uV, int *min_uV) 340085254bcfSDmitry Osipenko { 340185254bcfSDmitry Osipenko struct regulation_constraints *constraints = rdev->constraints; 340285254bcfSDmitry Osipenko 340385254bcfSDmitry Osipenko /* Limit voltage change only if necessary */ 340485254bcfSDmitry Osipenko if (!constraints->max_uV_step || !_regulator_is_enabled(rdev)) 340585254bcfSDmitry Osipenko return 1; 340685254bcfSDmitry Osipenko 340785254bcfSDmitry Osipenko if (*current_uV < 0) { 340885254bcfSDmitry Osipenko *current_uV = _regulator_get_voltage(rdev); 340985254bcfSDmitry Osipenko 341085254bcfSDmitry Osipenko if (*current_uV < 0) 341185254bcfSDmitry Osipenko return *current_uV; 341285254bcfSDmitry Osipenko } 341385254bcfSDmitry Osipenko 341485254bcfSDmitry Osipenko if (abs(*current_uV - *min_uV) <= constraints->max_uV_step) 341585254bcfSDmitry Osipenko return 1; 341685254bcfSDmitry Osipenko 341785254bcfSDmitry Osipenko /* Clamp target voltage within the given step */ 341885254bcfSDmitry Osipenko if (*current_uV < *min_uV) 341985254bcfSDmitry Osipenko *min_uV = min(*current_uV + constraints->max_uV_step, 342085254bcfSDmitry Osipenko *min_uV); 342185254bcfSDmitry Osipenko else 342285254bcfSDmitry Osipenko *min_uV = max(*current_uV - constraints->max_uV_step, 342385254bcfSDmitry Osipenko *min_uV); 342485254bcfSDmitry Osipenko 342585254bcfSDmitry Osipenko return 0; 342685254bcfSDmitry Osipenko } 342785254bcfSDmitry Osipenko 3428c054c6c7SMaciej Purski static int regulator_get_optimal_voltage(struct regulator_dev *rdev, 3429c054c6c7SMaciej Purski int *current_uV, 3430c054c6c7SMaciej Purski int *min_uV, int *max_uV, 3431c054c6c7SMaciej Purski suspend_state_t state, 3432c054c6c7SMaciej Purski int n_coupled) 3433c054c6c7SMaciej Purski { 3434c054c6c7SMaciej Purski struct coupling_desc *c_desc = &rdev->coupling_desc; 3435c054c6c7SMaciej Purski struct regulator_dev **c_rdevs = c_desc->coupled_rdevs; 3436c054c6c7SMaciej Purski struct regulation_constraints *constraints = rdev->constraints; 3437c054c6c7SMaciej Purski int max_spread = constraints->max_spread; 3438c054c6c7SMaciej Purski int desired_min_uV = 0, desired_max_uV = INT_MAX; 3439c054c6c7SMaciej Purski int max_current_uV = 0, min_current_uV = INT_MAX; 3440c054c6c7SMaciej Purski int highest_min_uV = 0, target_uV, possible_uV; 3441c054c6c7SMaciej Purski int i, ret; 3442c054c6c7SMaciej Purski bool done; 3443c054c6c7SMaciej Purski 3444c054c6c7SMaciej Purski *current_uV = -1; 3445c054c6c7SMaciej Purski 3446c054c6c7SMaciej Purski /* 3447c054c6c7SMaciej Purski * If there are no coupled regulators, simply set the voltage 3448c054c6c7SMaciej Purski * demanded by consumers. 3449c054c6c7SMaciej Purski */ 3450c054c6c7SMaciej Purski if (n_coupled == 1) { 3451c054c6c7SMaciej Purski /* 3452c054c6c7SMaciej Purski * If consumers don't provide any demands, set voltage 3453c054c6c7SMaciej Purski * to min_uV 3454c054c6c7SMaciej Purski */ 3455c054c6c7SMaciej Purski desired_min_uV = constraints->min_uV; 3456c054c6c7SMaciej Purski desired_max_uV = constraints->max_uV; 3457c054c6c7SMaciej Purski 3458c054c6c7SMaciej Purski ret = regulator_check_consumers(rdev, 3459c054c6c7SMaciej Purski &desired_min_uV, 3460c054c6c7SMaciej Purski &desired_max_uV, state); 3461c054c6c7SMaciej Purski if (ret < 0) 3462c054c6c7SMaciej Purski return ret; 3463c054c6c7SMaciej Purski 3464c054c6c7SMaciej Purski possible_uV = desired_min_uV; 3465c054c6c7SMaciej Purski done = true; 3466c054c6c7SMaciej Purski 3467c054c6c7SMaciej Purski goto finish; 3468c054c6c7SMaciej Purski } 3469c054c6c7SMaciej Purski 3470c054c6c7SMaciej Purski /* Find highest min desired voltage */ 3471c054c6c7SMaciej Purski for (i = 0; i < n_coupled; i++) { 3472c054c6c7SMaciej Purski int tmp_min = 0; 3473c054c6c7SMaciej Purski int tmp_max = INT_MAX; 3474c054c6c7SMaciej Purski 3475f8702f9eSDmitry Osipenko lockdep_assert_held_once(&c_rdevs[i]->mutex.base); 3476c054c6c7SMaciej Purski 3477c054c6c7SMaciej Purski ret = regulator_check_consumers(c_rdevs[i], 3478c054c6c7SMaciej Purski &tmp_min, 3479c054c6c7SMaciej Purski &tmp_max, state); 3480c054c6c7SMaciej Purski if (ret < 0) 3481c054c6c7SMaciej Purski return ret; 3482c054c6c7SMaciej Purski 3483c054c6c7SMaciej Purski ret = regulator_check_voltage(c_rdevs[i], &tmp_min, &tmp_max); 3484c054c6c7SMaciej Purski if (ret < 0) 3485c054c6c7SMaciej Purski return ret; 3486c054c6c7SMaciej Purski 3487c054c6c7SMaciej Purski highest_min_uV = max(highest_min_uV, tmp_min); 3488c054c6c7SMaciej Purski 3489c054c6c7SMaciej Purski if (i == 0) { 3490c054c6c7SMaciej Purski desired_min_uV = tmp_min; 3491c054c6c7SMaciej Purski desired_max_uV = tmp_max; 3492c054c6c7SMaciej Purski } 3493c054c6c7SMaciej Purski } 3494c054c6c7SMaciej Purski 3495c054c6c7SMaciej Purski /* 3496c054c6c7SMaciej Purski * Let target_uV be equal to the desired one if possible. 3497c054c6c7SMaciej Purski * If not, set it to minimum voltage, allowed by other coupled 3498c054c6c7SMaciej Purski * regulators. 3499c054c6c7SMaciej Purski */ 3500c054c6c7SMaciej Purski target_uV = max(desired_min_uV, highest_min_uV - max_spread); 3501c054c6c7SMaciej Purski 3502c054c6c7SMaciej Purski /* 3503c054c6c7SMaciej Purski * Find min and max voltages, which currently aren't violating 3504c054c6c7SMaciej Purski * max_spread. 3505c054c6c7SMaciej Purski */ 3506c054c6c7SMaciej Purski for (i = 1; i < n_coupled; i++) { 3507c054c6c7SMaciej Purski int tmp_act; 3508c054c6c7SMaciej Purski 3509c054c6c7SMaciej Purski if (!_regulator_is_enabled(c_rdevs[i])) 3510c054c6c7SMaciej Purski continue; 3511c054c6c7SMaciej Purski 3512c054c6c7SMaciej Purski tmp_act = _regulator_get_voltage(c_rdevs[i]); 3513c054c6c7SMaciej Purski if (tmp_act < 0) 3514c054c6c7SMaciej Purski return tmp_act; 3515c054c6c7SMaciej Purski 3516c054c6c7SMaciej Purski min_current_uV = min(tmp_act, min_current_uV); 3517c054c6c7SMaciej Purski max_current_uV = max(tmp_act, max_current_uV); 3518c054c6c7SMaciej Purski } 3519c054c6c7SMaciej Purski 3520c054c6c7SMaciej Purski /* There aren't any other regulators enabled */ 3521c054c6c7SMaciej Purski if (max_current_uV == 0) { 3522c054c6c7SMaciej Purski possible_uV = target_uV; 3523c054c6c7SMaciej Purski } else { 3524c054c6c7SMaciej Purski /* 3525c054c6c7SMaciej Purski * Correct target voltage, so as it currently isn't 3526c054c6c7SMaciej Purski * violating max_spread 3527c054c6c7SMaciej Purski */ 3528c054c6c7SMaciej Purski possible_uV = max(target_uV, max_current_uV - max_spread); 3529c054c6c7SMaciej Purski possible_uV = min(possible_uV, min_current_uV + max_spread); 3530c054c6c7SMaciej Purski } 3531c054c6c7SMaciej Purski 3532c054c6c7SMaciej Purski if (possible_uV > desired_max_uV) 3533c054c6c7SMaciej Purski return -EINVAL; 3534c054c6c7SMaciej Purski 3535c054c6c7SMaciej Purski done = (possible_uV == target_uV); 3536c054c6c7SMaciej Purski desired_min_uV = possible_uV; 3537c054c6c7SMaciej Purski 3538c054c6c7SMaciej Purski finish: 353985254bcfSDmitry Osipenko /* Apply max_uV_step constraint if necessary */ 354085254bcfSDmitry Osipenko if (state == PM_SUSPEND_ON) { 354185254bcfSDmitry Osipenko ret = regulator_limit_voltage_step(rdev, current_uV, 354285254bcfSDmitry Osipenko &desired_min_uV); 354385254bcfSDmitry Osipenko if (ret < 0) 354485254bcfSDmitry Osipenko return ret; 354585254bcfSDmitry Osipenko 354685254bcfSDmitry Osipenko if (ret == 0) 354785254bcfSDmitry Osipenko done = false; 354885254bcfSDmitry Osipenko } 354985254bcfSDmitry Osipenko 3550c054c6c7SMaciej Purski /* Set current_uV if wasn't done earlier in the code and if necessary */ 3551c054c6c7SMaciej Purski if (n_coupled > 1 && *current_uV == -1) { 3552c054c6c7SMaciej Purski 3553c054c6c7SMaciej Purski if (_regulator_is_enabled(rdev)) { 3554c054c6c7SMaciej Purski ret = _regulator_get_voltage(rdev); 3555c054c6c7SMaciej Purski if (ret < 0) 3556c054c6c7SMaciej Purski return ret; 3557c054c6c7SMaciej Purski 3558c054c6c7SMaciej Purski *current_uV = ret; 3559c054c6c7SMaciej Purski } else { 3560c054c6c7SMaciej Purski *current_uV = desired_min_uV; 3561c054c6c7SMaciej Purski } 3562c054c6c7SMaciej Purski } 3563c054c6c7SMaciej Purski 3564c054c6c7SMaciej Purski *min_uV = desired_min_uV; 3565c054c6c7SMaciej Purski *max_uV = desired_max_uV; 3566c054c6c7SMaciej Purski 3567c054c6c7SMaciej Purski return done; 3568c054c6c7SMaciej Purski } 3569c054c6c7SMaciej Purski 3570c054c6c7SMaciej Purski static int regulator_balance_voltage(struct regulator_dev *rdev, 3571c054c6c7SMaciej Purski suspend_state_t state) 3572c054c6c7SMaciej Purski { 3573c054c6c7SMaciej Purski struct regulator_dev **c_rdevs; 3574c054c6c7SMaciej Purski struct regulator_dev *best_rdev; 3575c054c6c7SMaciej Purski struct coupling_desc *c_desc = &rdev->coupling_desc; 3576c054c6c7SMaciej Purski int i, ret, n_coupled, best_min_uV, best_max_uV, best_c_rdev; 3577c054c6c7SMaciej Purski bool best_c_rdev_done, c_rdev_done[MAX_COUPLED]; 3578c054c6c7SMaciej Purski unsigned int delta, best_delta; 3579c054c6c7SMaciej Purski 3580c054c6c7SMaciej Purski c_rdevs = c_desc->coupled_rdevs; 3581c054c6c7SMaciej Purski n_coupled = c_desc->n_coupled; 3582c054c6c7SMaciej Purski 3583c054c6c7SMaciej Purski /* 3584c054c6c7SMaciej Purski * If system is in a state other than PM_SUSPEND_ON, don't check 3585c054c6c7SMaciej Purski * other coupled regulators. 3586c054c6c7SMaciej Purski */ 3587c054c6c7SMaciej Purski if (state != PM_SUSPEND_ON) 3588c054c6c7SMaciej Purski n_coupled = 1; 3589c054c6c7SMaciej Purski 3590c054c6c7SMaciej Purski if (c_desc->n_resolved < n_coupled) { 3591c054c6c7SMaciej Purski rdev_err(rdev, "Not all coupled regulators registered\n"); 3592c054c6c7SMaciej Purski return -EPERM; 3593c054c6c7SMaciej Purski } 3594c054c6c7SMaciej Purski 3595c054c6c7SMaciej Purski for (i = 0; i < n_coupled; i++) 3596c054c6c7SMaciej Purski c_rdev_done[i] = false; 3597c054c6c7SMaciej Purski 3598c054c6c7SMaciej Purski /* 3599c054c6c7SMaciej Purski * Find the best possible voltage change on each loop. Leave the loop 3600c054c6c7SMaciej Purski * if there isn't any possible change. 3601c054c6c7SMaciej Purski */ 3602c054c6c7SMaciej Purski do { 3603c054c6c7SMaciej Purski best_c_rdev_done = false; 3604c054c6c7SMaciej Purski best_delta = 0; 3605c054c6c7SMaciej Purski best_min_uV = 0; 3606c054c6c7SMaciej Purski best_max_uV = 0; 3607c054c6c7SMaciej Purski best_c_rdev = 0; 3608c054c6c7SMaciej Purski best_rdev = NULL; 3609c054c6c7SMaciej Purski 3610c054c6c7SMaciej Purski /* 3611c054c6c7SMaciej Purski * Find highest difference between optimal voltage 3612c054c6c7SMaciej Purski * and current voltage. 3613c054c6c7SMaciej Purski */ 3614c054c6c7SMaciej Purski for (i = 0; i < n_coupled; i++) { 3615c054c6c7SMaciej Purski /* 3616c054c6c7SMaciej Purski * optimal_uV is the best voltage that can be set for 3617c054c6c7SMaciej Purski * i-th regulator at the moment without violating 3618c054c6c7SMaciej Purski * max_spread constraint in order to balance 3619c054c6c7SMaciej Purski * the coupled voltages. 3620c054c6c7SMaciej Purski */ 3621c054c6c7SMaciej Purski int optimal_uV = 0, optimal_max_uV = 0, current_uV = 0; 3622c054c6c7SMaciej Purski 3623c054c6c7SMaciej Purski if (c_rdev_done[i]) 3624c054c6c7SMaciej Purski continue; 3625c054c6c7SMaciej Purski 3626c054c6c7SMaciej Purski ret = regulator_get_optimal_voltage(c_rdevs[i], 3627c054c6c7SMaciej Purski ¤t_uV, 3628c054c6c7SMaciej Purski &optimal_uV, 3629c054c6c7SMaciej Purski &optimal_max_uV, 3630c054c6c7SMaciej Purski state, n_coupled); 3631c054c6c7SMaciej Purski if (ret < 0) 3632c054c6c7SMaciej Purski goto out; 3633c054c6c7SMaciej Purski 3634c054c6c7SMaciej Purski delta = abs(optimal_uV - current_uV); 3635c054c6c7SMaciej Purski 3636c054c6c7SMaciej Purski if (delta && best_delta <= delta) { 3637c054c6c7SMaciej Purski best_c_rdev_done = ret; 3638c054c6c7SMaciej Purski best_delta = delta; 3639c054c6c7SMaciej Purski best_rdev = c_rdevs[i]; 3640c054c6c7SMaciej Purski best_min_uV = optimal_uV; 3641c054c6c7SMaciej Purski best_max_uV = optimal_max_uV; 3642c054c6c7SMaciej Purski best_c_rdev = i; 3643c054c6c7SMaciej Purski } 3644c054c6c7SMaciej Purski } 3645c054c6c7SMaciej Purski 3646c054c6c7SMaciej Purski /* Nothing to change, return successfully */ 3647c054c6c7SMaciej Purski if (!best_rdev) { 3648c054c6c7SMaciej Purski ret = 0; 3649c054c6c7SMaciej Purski goto out; 3650c054c6c7SMaciej Purski } 36519243a195SMaciej Purski 3652c054c6c7SMaciej Purski ret = regulator_set_voltage_rdev(best_rdev, best_min_uV, 3653c054c6c7SMaciej Purski best_max_uV, state); 36549243a195SMaciej Purski 3655c054c6c7SMaciej Purski if (ret < 0) 3656c054c6c7SMaciej Purski goto out; 3657c054c6c7SMaciej Purski 3658c054c6c7SMaciej Purski c_rdev_done[best_c_rdev] = best_c_rdev_done; 3659c054c6c7SMaciej Purski 3660c054c6c7SMaciej Purski } while (n_coupled > 1); 3661c054c6c7SMaciej Purski 3662c054c6c7SMaciej Purski out: 366369686176SMaciej Purski return ret; 366469686176SMaciej Purski } 366569686176SMaciej Purski 3666a9f226bcSSascha Hauer /** 3667a9f226bcSSascha Hauer * regulator_set_voltage - set regulator output voltage 3668a9f226bcSSascha Hauer * @regulator: regulator source 3669a9f226bcSSascha Hauer * @min_uV: Minimum required voltage in uV 3670a9f226bcSSascha Hauer * @max_uV: Maximum acceptable voltage in uV 3671a9f226bcSSascha Hauer * 3672a9f226bcSSascha Hauer * Sets a voltage regulator to the desired output voltage. This can be set 3673a9f226bcSSascha Hauer * during any regulator state. IOW, regulator can be disabled or enabled. 3674a9f226bcSSascha Hauer * 3675a9f226bcSSascha Hauer * If the regulator is enabled then the voltage will change to the new value 3676a9f226bcSSascha Hauer * immediately otherwise if the regulator is disabled the regulator will 3677a9f226bcSSascha Hauer * output at the new voltage when enabled. 3678a9f226bcSSascha Hauer * 3679a9f226bcSSascha Hauer * NOTE: If the regulator is shared between several devices then the lowest 3680a9f226bcSSascha Hauer * request voltage that meets the system constraints will be used. 3681a9f226bcSSascha Hauer * Regulator system constraints must be set for this regulator before 3682a9f226bcSSascha Hauer * calling this function otherwise this call will fail. 3683a9f226bcSSascha Hauer */ 3684a9f226bcSSascha Hauer int regulator_set_voltage(struct regulator *regulator, int min_uV, int max_uV) 3685a9f226bcSSascha Hauer { 3686f8702f9eSDmitry Osipenko struct ww_acquire_ctx ww_ctx; 3687f8702f9eSDmitry Osipenko int ret; 3688a9f226bcSSascha Hauer 3689f8702f9eSDmitry Osipenko regulator_lock_dependent(regulator->rdev, &ww_ctx); 3690a9f226bcSSascha Hauer 3691c360a6dfSChunyan Zhang ret = regulator_set_voltage_unlocked(regulator, min_uV, max_uV, 3692c360a6dfSChunyan Zhang PM_SUSPEND_ON); 3693a9f226bcSSascha Hauer 3694f8702f9eSDmitry Osipenko regulator_unlock_dependent(regulator->rdev, &ww_ctx); 3695a9f226bcSSascha Hauer 369692d7a558SPaolo Pisati return ret; 3697414c70cbSLiam Girdwood } 3698414c70cbSLiam Girdwood EXPORT_SYMBOL_GPL(regulator_set_voltage); 3699414c70cbSLiam Girdwood 3700f7efad10SChunyan Zhang static inline int regulator_suspend_toggle(struct regulator_dev *rdev, 3701f7efad10SChunyan Zhang suspend_state_t state, bool en) 3702f7efad10SChunyan Zhang { 3703f7efad10SChunyan Zhang struct regulator_state *rstate; 3704f7efad10SChunyan Zhang 3705f7efad10SChunyan Zhang rstate = regulator_get_suspend_state(rdev, state); 3706f7efad10SChunyan Zhang if (rstate == NULL) 3707f7efad10SChunyan Zhang return -EINVAL; 3708f7efad10SChunyan Zhang 3709f7efad10SChunyan Zhang if (!rstate->changeable) 3710f7efad10SChunyan Zhang return -EPERM; 3711f7efad10SChunyan Zhang 37123edd79cfSMarek Szyprowski rstate->enabled = (en) ? ENABLE_IN_SUSPEND : DISABLE_IN_SUSPEND; 3713f7efad10SChunyan Zhang 3714f7efad10SChunyan Zhang return 0; 3715f7efad10SChunyan Zhang } 3716f7efad10SChunyan Zhang 3717f7efad10SChunyan Zhang int regulator_suspend_enable(struct regulator_dev *rdev, 3718f7efad10SChunyan Zhang suspend_state_t state) 3719f7efad10SChunyan Zhang { 3720f7efad10SChunyan Zhang return regulator_suspend_toggle(rdev, state, true); 3721f7efad10SChunyan Zhang } 3722f7efad10SChunyan Zhang EXPORT_SYMBOL_GPL(regulator_suspend_enable); 3723f7efad10SChunyan Zhang 3724f7efad10SChunyan Zhang int regulator_suspend_disable(struct regulator_dev *rdev, 3725f7efad10SChunyan Zhang suspend_state_t state) 3726f7efad10SChunyan Zhang { 3727f7efad10SChunyan Zhang struct regulator *regulator; 3728f7efad10SChunyan Zhang struct regulator_voltage *voltage; 3729f7efad10SChunyan Zhang 3730f7efad10SChunyan Zhang /* 3731f7efad10SChunyan Zhang * if any consumer wants this regulator device keeping on in 3732f7efad10SChunyan Zhang * suspend states, don't set it as disabled. 3733f7efad10SChunyan Zhang */ 3734f7efad10SChunyan Zhang list_for_each_entry(regulator, &rdev->consumer_list, list) { 3735f7efad10SChunyan Zhang voltage = ®ulator->voltage[state]; 3736f7efad10SChunyan Zhang if (voltage->min_uV || voltage->max_uV) 3737f7efad10SChunyan Zhang return 0; 3738f7efad10SChunyan Zhang } 3739f7efad10SChunyan Zhang 3740f7efad10SChunyan Zhang return regulator_suspend_toggle(rdev, state, false); 3741f7efad10SChunyan Zhang } 3742f7efad10SChunyan Zhang EXPORT_SYMBOL_GPL(regulator_suspend_disable); 3743f7efad10SChunyan Zhang 3744f7efad10SChunyan Zhang static int _regulator_set_suspend_voltage(struct regulator *regulator, 3745f7efad10SChunyan Zhang int min_uV, int max_uV, 3746f7efad10SChunyan Zhang suspend_state_t state) 3747f7efad10SChunyan Zhang { 3748f7efad10SChunyan Zhang struct regulator_dev *rdev = regulator->rdev; 3749f7efad10SChunyan Zhang struct regulator_state *rstate; 3750f7efad10SChunyan Zhang 3751f7efad10SChunyan Zhang rstate = regulator_get_suspend_state(rdev, state); 3752f7efad10SChunyan Zhang if (rstate == NULL) 3753f7efad10SChunyan Zhang return -EINVAL; 3754f7efad10SChunyan Zhang 3755f7efad10SChunyan Zhang if (rstate->min_uV == rstate->max_uV) { 3756f7efad10SChunyan Zhang rdev_err(rdev, "The suspend voltage can't be changed!\n"); 3757f7efad10SChunyan Zhang return -EPERM; 3758f7efad10SChunyan Zhang } 3759f7efad10SChunyan Zhang 3760f7efad10SChunyan Zhang return regulator_set_voltage_unlocked(regulator, min_uV, max_uV, state); 3761f7efad10SChunyan Zhang } 3762f7efad10SChunyan Zhang 3763f7efad10SChunyan Zhang int regulator_set_suspend_voltage(struct regulator *regulator, int min_uV, 3764f7efad10SChunyan Zhang int max_uV, suspend_state_t state) 3765f7efad10SChunyan Zhang { 3766f8702f9eSDmitry Osipenko struct ww_acquire_ctx ww_ctx; 3767f8702f9eSDmitry Osipenko int ret; 3768f7efad10SChunyan Zhang 3769f7efad10SChunyan Zhang /* PM_SUSPEND_ON is handled by regulator_set_voltage() */ 3770f7efad10SChunyan Zhang if (regulator_check_states(state) || state == PM_SUSPEND_ON) 3771f7efad10SChunyan Zhang return -EINVAL; 3772f7efad10SChunyan Zhang 3773f8702f9eSDmitry Osipenko regulator_lock_dependent(regulator->rdev, &ww_ctx); 3774f7efad10SChunyan Zhang 3775f7efad10SChunyan Zhang ret = _regulator_set_suspend_voltage(regulator, min_uV, 3776f7efad10SChunyan Zhang max_uV, state); 3777f7efad10SChunyan Zhang 3778f8702f9eSDmitry Osipenko regulator_unlock_dependent(regulator->rdev, &ww_ctx); 3779f7efad10SChunyan Zhang 3780f7efad10SChunyan Zhang return ret; 3781f7efad10SChunyan Zhang } 3782f7efad10SChunyan Zhang EXPORT_SYMBOL_GPL(regulator_set_suspend_voltage); 3783f7efad10SChunyan Zhang 3784606a2562SMark Brown /** 378588cd222bSLinus Walleij * regulator_set_voltage_time - get raise/fall time 378688cd222bSLinus Walleij * @regulator: regulator source 378788cd222bSLinus Walleij * @old_uV: starting voltage in microvolts 378888cd222bSLinus Walleij * @new_uV: target voltage in microvolts 378988cd222bSLinus Walleij * 379088cd222bSLinus Walleij * Provided with the starting and ending voltage, this function attempts to 379188cd222bSLinus Walleij * calculate the time in microseconds required to rise or fall to this new 379288cd222bSLinus Walleij * voltage. 379388cd222bSLinus Walleij */ 379488cd222bSLinus Walleij int regulator_set_voltage_time(struct regulator *regulator, 379588cd222bSLinus Walleij int old_uV, int new_uV) 379688cd222bSLinus Walleij { 379788cd222bSLinus Walleij struct regulator_dev *rdev = regulator->rdev; 3798272e2315SGuodong Xu const struct regulator_ops *ops = rdev->desc->ops; 379988cd222bSLinus Walleij int old_sel = -1; 380088cd222bSLinus Walleij int new_sel = -1; 380188cd222bSLinus Walleij int voltage; 380288cd222bSLinus Walleij int i; 380388cd222bSLinus Walleij 380473e705bfSMatthias Kaehlcke if (ops->set_voltage_time) 380573e705bfSMatthias Kaehlcke return ops->set_voltage_time(rdev, old_uV, new_uV); 380673e705bfSMatthias Kaehlcke else if (!ops->set_voltage_time_sel) 380773e705bfSMatthias Kaehlcke return _regulator_set_voltage_time(rdev, old_uV, new_uV); 380873e705bfSMatthias Kaehlcke 380988cd222bSLinus Walleij /* Currently requires operations to do this */ 381073e705bfSMatthias Kaehlcke if (!ops->list_voltage || !rdev->desc->n_voltages) 381188cd222bSLinus Walleij return -EINVAL; 381288cd222bSLinus Walleij 381388cd222bSLinus Walleij for (i = 0; i < rdev->desc->n_voltages; i++) { 381488cd222bSLinus Walleij /* We only look for exact voltage matches here */ 381588cd222bSLinus Walleij voltage = regulator_list_voltage(regulator, i); 381688cd222bSLinus Walleij if (voltage < 0) 381788cd222bSLinus Walleij return -EINVAL; 381888cd222bSLinus Walleij if (voltage == 0) 381988cd222bSLinus Walleij continue; 382088cd222bSLinus Walleij if (voltage == old_uV) 382188cd222bSLinus Walleij old_sel = i; 382288cd222bSLinus Walleij if (voltage == new_uV) 382388cd222bSLinus Walleij new_sel = i; 382488cd222bSLinus Walleij } 382588cd222bSLinus Walleij 382688cd222bSLinus Walleij if (old_sel < 0 || new_sel < 0) 382788cd222bSLinus Walleij return -EINVAL; 382888cd222bSLinus Walleij 382988cd222bSLinus Walleij return ops->set_voltage_time_sel(rdev, old_sel, new_sel); 383088cd222bSLinus Walleij } 383188cd222bSLinus Walleij EXPORT_SYMBOL_GPL(regulator_set_voltage_time); 383288cd222bSLinus Walleij 383388cd222bSLinus Walleij /** 383498a175b6SYadwinder Singh Brar * regulator_set_voltage_time_sel - get raise/fall time 3835296c6566SRandy Dunlap * @rdev: regulator source device 383698a175b6SYadwinder Singh Brar * @old_selector: selector for starting voltage 383798a175b6SYadwinder Singh Brar * @new_selector: selector for target voltage 383898a175b6SYadwinder Singh Brar * 383998a175b6SYadwinder Singh Brar * Provided with the starting and target voltage selectors, this function 384098a175b6SYadwinder Singh Brar * returns time in microseconds required to rise or fall to this new voltage 384198a175b6SYadwinder Singh Brar * 3842f11d08c3SAxel Lin * Drivers providing ramp_delay in regulation_constraints can use this as their 3843398715abSAxel Lin * set_voltage_time_sel() operation. 384498a175b6SYadwinder Singh Brar */ 384598a175b6SYadwinder Singh Brar int regulator_set_voltage_time_sel(struct regulator_dev *rdev, 384698a175b6SYadwinder Singh Brar unsigned int old_selector, 384798a175b6SYadwinder Singh Brar unsigned int new_selector) 384898a175b6SYadwinder Singh Brar { 3849f11d08c3SAxel Lin int old_volt, new_volt; 3850398715abSAxel Lin 3851f11d08c3SAxel Lin /* sanity check */ 3852f11d08c3SAxel Lin if (!rdev->desc->ops->list_voltage) 3853f11d08c3SAxel Lin return -EINVAL; 3854398715abSAxel Lin 3855f11d08c3SAxel Lin old_volt = rdev->desc->ops->list_voltage(rdev, old_selector); 3856f11d08c3SAxel Lin new_volt = rdev->desc->ops->list_voltage(rdev, new_selector); 3857f11d08c3SAxel Lin 385873e705bfSMatthias Kaehlcke if (rdev->desc->ops->set_voltage_time) 385973e705bfSMatthias Kaehlcke return rdev->desc->ops->set_voltage_time(rdev, old_volt, 386073e705bfSMatthias Kaehlcke new_volt); 386173e705bfSMatthias Kaehlcke else 386273e705bfSMatthias Kaehlcke return _regulator_set_voltage_time(rdev, old_volt, new_volt); 386398a175b6SYadwinder Singh Brar } 3864b19dbf71SMark Brown EXPORT_SYMBOL_GPL(regulator_set_voltage_time_sel); 386598a175b6SYadwinder Singh Brar 386698a175b6SYadwinder Singh Brar /** 3867606a2562SMark Brown * regulator_sync_voltage - re-apply last regulator output voltage 3868606a2562SMark Brown * @regulator: regulator source 3869606a2562SMark Brown * 3870606a2562SMark Brown * Re-apply the last configured voltage. This is intended to be used 3871606a2562SMark Brown * where some external control source the consumer is cooperating with 3872606a2562SMark Brown * has caused the configured voltage to change. 3873606a2562SMark Brown */ 3874606a2562SMark Brown int regulator_sync_voltage(struct regulator *regulator) 3875606a2562SMark Brown { 3876606a2562SMark Brown struct regulator_dev *rdev = regulator->rdev; 3877c360a6dfSChunyan Zhang struct regulator_voltage *voltage = ®ulator->voltage[PM_SUSPEND_ON]; 3878606a2562SMark Brown int ret, min_uV, max_uV; 3879606a2562SMark Brown 388066cf9a7eSMaciej Purski regulator_lock(rdev); 3881606a2562SMark Brown 3882606a2562SMark Brown if (!rdev->desc->ops->set_voltage && 3883606a2562SMark Brown !rdev->desc->ops->set_voltage_sel) { 3884606a2562SMark Brown ret = -EINVAL; 3885606a2562SMark Brown goto out; 3886606a2562SMark Brown } 3887606a2562SMark Brown 3888606a2562SMark Brown /* This is only going to work if we've had a voltage configured. */ 3889c360a6dfSChunyan Zhang if (!voltage->min_uV && !voltage->max_uV) { 3890606a2562SMark Brown ret = -EINVAL; 3891606a2562SMark Brown goto out; 3892606a2562SMark Brown } 3893606a2562SMark Brown 3894c360a6dfSChunyan Zhang min_uV = voltage->min_uV; 3895c360a6dfSChunyan Zhang max_uV = voltage->max_uV; 3896606a2562SMark Brown 3897606a2562SMark Brown /* This should be a paranoia check... */ 3898606a2562SMark Brown ret = regulator_check_voltage(rdev, &min_uV, &max_uV); 3899606a2562SMark Brown if (ret < 0) 3900606a2562SMark Brown goto out; 3901606a2562SMark Brown 3902c360a6dfSChunyan Zhang ret = regulator_check_consumers(rdev, &min_uV, &max_uV, 0); 3903606a2562SMark Brown if (ret < 0) 3904606a2562SMark Brown goto out; 3905606a2562SMark Brown 3906606a2562SMark Brown ret = _regulator_do_set_voltage(rdev, min_uV, max_uV); 3907606a2562SMark Brown 3908606a2562SMark Brown out: 390966cf9a7eSMaciej Purski regulator_unlock(rdev); 3910606a2562SMark Brown return ret; 3911606a2562SMark Brown } 3912606a2562SMark Brown EXPORT_SYMBOL_GPL(regulator_sync_voltage); 3913606a2562SMark Brown 3914414c70cbSLiam Girdwood static int _regulator_get_voltage(struct regulator_dev *rdev) 3915414c70cbSLiam Girdwood { 3916bf5892a8SMark Brown int sel, ret; 3917fef95019SMark Brown bool bypassed; 3918fef95019SMark Brown 3919fef95019SMark Brown if (rdev->desc->ops->get_bypass) { 3920fef95019SMark Brown ret = rdev->desc->ops->get_bypass(rdev, &bypassed); 3921fef95019SMark Brown if (ret < 0) 3922fef95019SMark Brown return ret; 3923fef95019SMark Brown if (bypassed) { 3924fef95019SMark Brown /* if bypassed the regulator must have a supply */ 392545389c47SJon Hunter if (!rdev->supply) { 392645389c47SJon Hunter rdev_err(rdev, 392745389c47SJon Hunter "bypassed regulator has no supply!\n"); 392845389c47SJon Hunter return -EPROBE_DEFER; 392945389c47SJon Hunter } 3930fef95019SMark Brown 3931fef95019SMark Brown return _regulator_get_voltage(rdev->supply->rdev); 3932fef95019SMark Brown } 3933fef95019SMark Brown } 3934476c2d83SMark Brown 3935476c2d83SMark Brown if (rdev->desc->ops->get_voltage_sel) { 3936476c2d83SMark Brown sel = rdev->desc->ops->get_voltage_sel(rdev); 3937476c2d83SMark Brown if (sel < 0) 3938476c2d83SMark Brown return sel; 3939bf5892a8SMark Brown ret = rdev->desc->ops->list_voltage(rdev, sel); 3940cb220d16SAxel Lin } else if (rdev->desc->ops->get_voltage) { 3941bf5892a8SMark Brown ret = rdev->desc->ops->get_voltage(rdev); 3942f7df20ecSMark Brown } else if (rdev->desc->ops->list_voltage) { 3943f7df20ecSMark Brown ret = rdev->desc->ops->list_voltage(rdev, 0); 39445a523605SLaxman Dewangan } else if (rdev->desc->fixed_uV && (rdev->desc->n_voltages == 1)) { 39455a523605SLaxman Dewangan ret = rdev->desc->fixed_uV; 3946e303996eSJavier Martinez Canillas } else if (rdev->supply) { 3947d9b96d35SMark Brown ret = _regulator_get_voltage(rdev->supply->rdev); 3948cb220d16SAxel Lin } else { 3949414c70cbSLiam Girdwood return -EINVAL; 3950cb220d16SAxel Lin } 3951bf5892a8SMark Brown 3952cb220d16SAxel Lin if (ret < 0) 3953cb220d16SAxel Lin return ret; 3954bf5892a8SMark Brown return ret - rdev->constraints->uV_offset; 3955414c70cbSLiam Girdwood } 3956414c70cbSLiam Girdwood 3957414c70cbSLiam Girdwood /** 3958414c70cbSLiam Girdwood * regulator_get_voltage - get regulator output voltage 3959414c70cbSLiam Girdwood * @regulator: regulator source 3960414c70cbSLiam Girdwood * 3961414c70cbSLiam Girdwood * This returns the current regulator voltage in uV. 3962414c70cbSLiam Girdwood * 3963414c70cbSLiam Girdwood * NOTE: If the regulator is disabled it will return the voltage value. This 3964414c70cbSLiam Girdwood * function should not be used to determine regulator state. 3965414c70cbSLiam Girdwood */ 3966414c70cbSLiam Girdwood int regulator_get_voltage(struct regulator *regulator) 3967414c70cbSLiam Girdwood { 3968f8702f9eSDmitry Osipenko struct ww_acquire_ctx ww_ctx; 3969414c70cbSLiam Girdwood int ret; 3970414c70cbSLiam Girdwood 3971f8702f9eSDmitry Osipenko regulator_lock_dependent(regulator->rdev, &ww_ctx); 3972414c70cbSLiam Girdwood ret = _regulator_get_voltage(regulator->rdev); 3973f8702f9eSDmitry Osipenko regulator_unlock_dependent(regulator->rdev, &ww_ctx); 3974414c70cbSLiam Girdwood 3975414c70cbSLiam Girdwood return ret; 3976414c70cbSLiam Girdwood } 3977414c70cbSLiam Girdwood EXPORT_SYMBOL_GPL(regulator_get_voltage); 3978414c70cbSLiam Girdwood 3979414c70cbSLiam Girdwood /** 3980414c70cbSLiam Girdwood * regulator_set_current_limit - set regulator output current limit 3981414c70cbSLiam Girdwood * @regulator: regulator source 3982ce0d10f8SCharles Keepax * @min_uA: Minimum supported current in uA 3983414c70cbSLiam Girdwood * @max_uA: Maximum supported current in uA 3984414c70cbSLiam Girdwood * 3985414c70cbSLiam Girdwood * Sets current sink to the desired output current. This can be set during 3986414c70cbSLiam Girdwood * any regulator state. IOW, regulator can be disabled or enabled. 3987414c70cbSLiam Girdwood * 3988414c70cbSLiam Girdwood * If the regulator is enabled then the current will change to the new value 3989414c70cbSLiam Girdwood * immediately otherwise if the regulator is disabled the regulator will 3990414c70cbSLiam Girdwood * output at the new current when enabled. 3991414c70cbSLiam Girdwood * 3992414c70cbSLiam Girdwood * NOTE: Regulator system constraints must be set for this regulator before 3993414c70cbSLiam Girdwood * calling this function otherwise this call will fail. 3994414c70cbSLiam Girdwood */ 3995414c70cbSLiam Girdwood int regulator_set_current_limit(struct regulator *regulator, 3996414c70cbSLiam Girdwood int min_uA, int max_uA) 3997414c70cbSLiam Girdwood { 3998414c70cbSLiam Girdwood struct regulator_dev *rdev = regulator->rdev; 3999414c70cbSLiam Girdwood int ret; 4000414c70cbSLiam Girdwood 400166cf9a7eSMaciej Purski regulator_lock(rdev); 4002414c70cbSLiam Girdwood 4003414c70cbSLiam Girdwood /* sanity check */ 4004414c70cbSLiam Girdwood if (!rdev->desc->ops->set_current_limit) { 4005414c70cbSLiam Girdwood ret = -EINVAL; 4006414c70cbSLiam Girdwood goto out; 4007414c70cbSLiam Girdwood } 4008414c70cbSLiam Girdwood 4009414c70cbSLiam Girdwood /* constraints check */ 4010414c70cbSLiam Girdwood ret = regulator_check_current_limit(rdev, &min_uA, &max_uA); 4011414c70cbSLiam Girdwood if (ret < 0) 4012414c70cbSLiam Girdwood goto out; 4013414c70cbSLiam Girdwood 4014414c70cbSLiam Girdwood ret = rdev->desc->ops->set_current_limit(rdev, min_uA, max_uA); 4015414c70cbSLiam Girdwood out: 401666cf9a7eSMaciej Purski regulator_unlock(rdev); 4017414c70cbSLiam Girdwood return ret; 4018414c70cbSLiam Girdwood } 4019414c70cbSLiam Girdwood EXPORT_SYMBOL_GPL(regulator_set_current_limit); 4020414c70cbSLiam Girdwood 40217e4d9683SDouglas Anderson static int _regulator_get_current_limit_unlocked(struct regulator_dev *rdev) 40227e4d9683SDouglas Anderson { 40237e4d9683SDouglas Anderson /* sanity check */ 40247e4d9683SDouglas Anderson if (!rdev->desc->ops->get_current_limit) 40257e4d9683SDouglas Anderson return -EINVAL; 40267e4d9683SDouglas Anderson 40277e4d9683SDouglas Anderson return rdev->desc->ops->get_current_limit(rdev); 40287e4d9683SDouglas Anderson } 40297e4d9683SDouglas Anderson 4030414c70cbSLiam Girdwood static int _regulator_get_current_limit(struct regulator_dev *rdev) 4031414c70cbSLiam Girdwood { 4032414c70cbSLiam Girdwood int ret; 4033414c70cbSLiam Girdwood 403466cf9a7eSMaciej Purski regulator_lock(rdev); 40357e4d9683SDouglas Anderson ret = _regulator_get_current_limit_unlocked(rdev); 403666cf9a7eSMaciej Purski regulator_unlock(rdev); 40377e4d9683SDouglas Anderson 4038414c70cbSLiam Girdwood return ret; 4039414c70cbSLiam Girdwood } 4040414c70cbSLiam Girdwood 4041414c70cbSLiam Girdwood /** 4042414c70cbSLiam Girdwood * regulator_get_current_limit - get regulator output current 4043414c70cbSLiam Girdwood * @regulator: regulator source 4044414c70cbSLiam Girdwood * 4045414c70cbSLiam Girdwood * This returns the current supplied by the specified current sink in uA. 4046414c70cbSLiam Girdwood * 4047414c70cbSLiam Girdwood * NOTE: If the regulator is disabled it will return the current value. This 4048414c70cbSLiam Girdwood * function should not be used to determine regulator state. 4049414c70cbSLiam Girdwood */ 4050414c70cbSLiam Girdwood int regulator_get_current_limit(struct regulator *regulator) 4051414c70cbSLiam Girdwood { 4052414c70cbSLiam Girdwood return _regulator_get_current_limit(regulator->rdev); 4053414c70cbSLiam Girdwood } 4054414c70cbSLiam Girdwood EXPORT_SYMBOL_GPL(regulator_get_current_limit); 4055414c70cbSLiam Girdwood 4056414c70cbSLiam Girdwood /** 4057414c70cbSLiam Girdwood * regulator_set_mode - set regulator operating mode 4058414c70cbSLiam Girdwood * @regulator: regulator source 4059414c70cbSLiam Girdwood * @mode: operating mode - one of the REGULATOR_MODE constants 4060414c70cbSLiam Girdwood * 4061414c70cbSLiam Girdwood * Set regulator operating mode to increase regulator efficiency or improve 4062414c70cbSLiam Girdwood * regulation performance. 4063414c70cbSLiam Girdwood * 4064414c70cbSLiam Girdwood * NOTE: Regulator system constraints must be set for this regulator before 4065414c70cbSLiam Girdwood * calling this function otherwise this call will fail. 4066414c70cbSLiam Girdwood */ 4067414c70cbSLiam Girdwood int regulator_set_mode(struct regulator *regulator, unsigned int mode) 4068414c70cbSLiam Girdwood { 4069414c70cbSLiam Girdwood struct regulator_dev *rdev = regulator->rdev; 4070414c70cbSLiam Girdwood int ret; 4071500b4ac9SSundar R Iyer int regulator_curr_mode; 4072414c70cbSLiam Girdwood 407366cf9a7eSMaciej Purski regulator_lock(rdev); 4074414c70cbSLiam Girdwood 4075414c70cbSLiam Girdwood /* sanity check */ 4076414c70cbSLiam Girdwood if (!rdev->desc->ops->set_mode) { 4077414c70cbSLiam Girdwood ret = -EINVAL; 4078414c70cbSLiam Girdwood goto out; 4079414c70cbSLiam Girdwood } 4080414c70cbSLiam Girdwood 4081500b4ac9SSundar R Iyer /* return if the same mode is requested */ 4082500b4ac9SSundar R Iyer if (rdev->desc->ops->get_mode) { 4083500b4ac9SSundar R Iyer regulator_curr_mode = rdev->desc->ops->get_mode(rdev); 4084500b4ac9SSundar R Iyer if (regulator_curr_mode == mode) { 4085500b4ac9SSundar R Iyer ret = 0; 4086500b4ac9SSundar R Iyer goto out; 4087500b4ac9SSundar R Iyer } 4088500b4ac9SSundar R Iyer } 4089500b4ac9SSundar R Iyer 4090414c70cbSLiam Girdwood /* constraints check */ 409122c51b47SAxel Lin ret = regulator_mode_constrain(rdev, &mode); 4092414c70cbSLiam Girdwood if (ret < 0) 4093414c70cbSLiam Girdwood goto out; 4094414c70cbSLiam Girdwood 4095414c70cbSLiam Girdwood ret = rdev->desc->ops->set_mode(rdev, mode); 4096414c70cbSLiam Girdwood out: 409766cf9a7eSMaciej Purski regulator_unlock(rdev); 4098414c70cbSLiam Girdwood return ret; 4099414c70cbSLiam Girdwood } 4100414c70cbSLiam Girdwood EXPORT_SYMBOL_GPL(regulator_set_mode); 4101414c70cbSLiam Girdwood 41027e4d9683SDouglas Anderson static unsigned int _regulator_get_mode_unlocked(struct regulator_dev *rdev) 41037e4d9683SDouglas Anderson { 41047e4d9683SDouglas Anderson /* sanity check */ 41057e4d9683SDouglas Anderson if (!rdev->desc->ops->get_mode) 41067e4d9683SDouglas Anderson return -EINVAL; 41077e4d9683SDouglas Anderson 41087e4d9683SDouglas Anderson return rdev->desc->ops->get_mode(rdev); 41097e4d9683SDouglas Anderson } 41107e4d9683SDouglas Anderson 4111414c70cbSLiam Girdwood static unsigned int _regulator_get_mode(struct regulator_dev *rdev) 4112414c70cbSLiam Girdwood { 4113414c70cbSLiam Girdwood int ret; 4114414c70cbSLiam Girdwood 411566cf9a7eSMaciej Purski regulator_lock(rdev); 41167e4d9683SDouglas Anderson ret = _regulator_get_mode_unlocked(rdev); 411766cf9a7eSMaciej Purski regulator_unlock(rdev); 41187e4d9683SDouglas Anderson 4119414c70cbSLiam Girdwood return ret; 4120414c70cbSLiam Girdwood } 4121414c70cbSLiam Girdwood 4122414c70cbSLiam Girdwood /** 4123414c70cbSLiam Girdwood * regulator_get_mode - get regulator operating mode 4124414c70cbSLiam Girdwood * @regulator: regulator source 4125414c70cbSLiam Girdwood * 4126414c70cbSLiam Girdwood * Get the current regulator operating mode. 4127414c70cbSLiam Girdwood */ 4128414c70cbSLiam Girdwood unsigned int regulator_get_mode(struct regulator *regulator) 4129414c70cbSLiam Girdwood { 4130414c70cbSLiam Girdwood return _regulator_get_mode(regulator->rdev); 4131414c70cbSLiam Girdwood } 4132414c70cbSLiam Girdwood EXPORT_SYMBOL_GPL(regulator_get_mode); 4133414c70cbSLiam Girdwood 41341b5b4221SAxel Haslam static int _regulator_get_error_flags(struct regulator_dev *rdev, 41351b5b4221SAxel Haslam unsigned int *flags) 41361b5b4221SAxel Haslam { 41371b5b4221SAxel Haslam int ret; 41381b5b4221SAxel Haslam 413966cf9a7eSMaciej Purski regulator_lock(rdev); 41401b5b4221SAxel Haslam 41411b5b4221SAxel Haslam /* sanity check */ 41421b5b4221SAxel Haslam if (!rdev->desc->ops->get_error_flags) { 41431b5b4221SAxel Haslam ret = -EINVAL; 41441b5b4221SAxel Haslam goto out; 41451b5b4221SAxel Haslam } 41461b5b4221SAxel Haslam 41471b5b4221SAxel Haslam ret = rdev->desc->ops->get_error_flags(rdev, flags); 41481b5b4221SAxel Haslam out: 414966cf9a7eSMaciej Purski regulator_unlock(rdev); 41501b5b4221SAxel Haslam return ret; 41511b5b4221SAxel Haslam } 41521b5b4221SAxel Haslam 41531b5b4221SAxel Haslam /** 41541b5b4221SAxel Haslam * regulator_get_error_flags - get regulator error information 41551b5b4221SAxel Haslam * @regulator: regulator source 41561b5b4221SAxel Haslam * @flags: pointer to store error flags 41571b5b4221SAxel Haslam * 41581b5b4221SAxel Haslam * Get the current regulator error information. 41591b5b4221SAxel Haslam */ 41601b5b4221SAxel Haslam int regulator_get_error_flags(struct regulator *regulator, 41611b5b4221SAxel Haslam unsigned int *flags) 41621b5b4221SAxel Haslam { 41631b5b4221SAxel Haslam return _regulator_get_error_flags(regulator->rdev, flags); 41641b5b4221SAxel Haslam } 41651b5b4221SAxel Haslam EXPORT_SYMBOL_GPL(regulator_get_error_flags); 41661b5b4221SAxel Haslam 4167414c70cbSLiam Girdwood /** 4168e39ce48fSBjorn Andersson * regulator_set_load - set regulator load 4169414c70cbSLiam Girdwood * @regulator: regulator source 4170414c70cbSLiam Girdwood * @uA_load: load current 4171414c70cbSLiam Girdwood * 4172414c70cbSLiam Girdwood * Notifies the regulator core of a new device load. This is then used by 4173414c70cbSLiam Girdwood * DRMS (if enabled by constraints) to set the most efficient regulator 4174414c70cbSLiam Girdwood * operating mode for the new regulator loading. 4175414c70cbSLiam Girdwood * 4176414c70cbSLiam Girdwood * Consumer devices notify their supply regulator of the maximum power 4177414c70cbSLiam Girdwood * they will require (can be taken from device datasheet in the power 4178414c70cbSLiam Girdwood * consumption tables) when they change operational status and hence power 4179414c70cbSLiam Girdwood * state. Examples of operational state changes that can affect power 4180414c70cbSLiam Girdwood * consumption are :- 4181414c70cbSLiam Girdwood * 4182414c70cbSLiam Girdwood * o Device is opened / closed. 4183414c70cbSLiam Girdwood * o Device I/O is about to begin or has just finished. 4184414c70cbSLiam Girdwood * o Device is idling in between work. 4185414c70cbSLiam Girdwood * 4186414c70cbSLiam Girdwood * This information is also exported via sysfs to userspace. 4187414c70cbSLiam Girdwood * 4188414c70cbSLiam Girdwood * DRMS will sum the total requested load on the regulator and change 4189414c70cbSLiam Girdwood * to the most efficient operating mode if platform constraints allow. 4190414c70cbSLiam Girdwood * 41915451781dSDouglas Anderson * NOTE: when a regulator consumer requests to have a regulator 41925451781dSDouglas Anderson * disabled then any load that consumer requested no longer counts 41935451781dSDouglas Anderson * toward the total requested load. If the regulator is re-enabled 41945451781dSDouglas Anderson * then the previously requested load will start counting again. 41955451781dSDouglas Anderson * 41965451781dSDouglas Anderson * If a regulator is an always-on regulator then an individual consumer's 41975451781dSDouglas Anderson * load will still be removed if that consumer is fully disabled. 41985451781dSDouglas Anderson * 4199e39ce48fSBjorn Andersson * On error a negative errno is returned. 4200414c70cbSLiam Girdwood */ 4201e39ce48fSBjorn Andersson int regulator_set_load(struct regulator *regulator, int uA_load) 4202414c70cbSLiam Girdwood { 4203414c70cbSLiam Girdwood struct regulator_dev *rdev = regulator->rdev; 42045451781dSDouglas Anderson int old_uA_load; 42055451781dSDouglas Anderson int ret = 0; 4206d92d95b6SStephen Boyd 420766cf9a7eSMaciej Purski regulator_lock(rdev); 42085451781dSDouglas Anderson old_uA_load = regulator->uA_load; 4209414c70cbSLiam Girdwood regulator->uA_load = uA_load; 42105451781dSDouglas Anderson if (regulator->enable_count && old_uA_load != uA_load) { 42118460ef38SBjorn Andersson ret = drms_uA_update(rdev); 42125451781dSDouglas Anderson if (ret < 0) 42135451781dSDouglas Anderson regulator->uA_load = old_uA_load; 42145451781dSDouglas Anderson } 421566cf9a7eSMaciej Purski regulator_unlock(rdev); 42168460ef38SBjorn Andersson 4217414c70cbSLiam Girdwood return ret; 4218414c70cbSLiam Girdwood } 4219e39ce48fSBjorn Andersson EXPORT_SYMBOL_GPL(regulator_set_load); 4220414c70cbSLiam Girdwood 4221414c70cbSLiam Girdwood /** 4222f59c8f9fSMark Brown * regulator_allow_bypass - allow the regulator to go into bypass mode 4223f59c8f9fSMark Brown * 4224f59c8f9fSMark Brown * @regulator: Regulator to configure 42259345dfb8SNishanth Menon * @enable: enable or disable bypass mode 4226f59c8f9fSMark Brown * 4227f59c8f9fSMark Brown * Allow the regulator to go into bypass mode if all other consumers 4228f59c8f9fSMark Brown * for the regulator also enable bypass mode and the machine 4229f59c8f9fSMark Brown * constraints allow this. Bypass mode means that the regulator is 4230f59c8f9fSMark Brown * simply passing the input directly to the output with no regulation. 4231f59c8f9fSMark Brown */ 4232f59c8f9fSMark Brown int regulator_allow_bypass(struct regulator *regulator, bool enable) 4233f59c8f9fSMark Brown { 4234f59c8f9fSMark Brown struct regulator_dev *rdev = regulator->rdev; 4235f59c8f9fSMark Brown int ret = 0; 4236f59c8f9fSMark Brown 4237f59c8f9fSMark Brown if (!rdev->desc->ops->set_bypass) 4238f59c8f9fSMark Brown return 0; 4239f59c8f9fSMark Brown 42408a34e979SWEN Pingbo if (!regulator_ops_is_valid(rdev, REGULATOR_CHANGE_BYPASS)) 4241f59c8f9fSMark Brown return 0; 4242f59c8f9fSMark Brown 424366cf9a7eSMaciej Purski regulator_lock(rdev); 4244f59c8f9fSMark Brown 4245f59c8f9fSMark Brown if (enable && !regulator->bypass) { 4246f59c8f9fSMark Brown rdev->bypass_count++; 4247f59c8f9fSMark Brown 4248f59c8f9fSMark Brown if (rdev->bypass_count == rdev->open_count) { 4249f59c8f9fSMark Brown ret = rdev->desc->ops->set_bypass(rdev, enable); 4250f59c8f9fSMark Brown if (ret != 0) 4251f59c8f9fSMark Brown rdev->bypass_count--; 4252f59c8f9fSMark Brown } 4253f59c8f9fSMark Brown 4254f59c8f9fSMark Brown } else if (!enable && regulator->bypass) { 4255f59c8f9fSMark Brown rdev->bypass_count--; 4256f59c8f9fSMark Brown 4257f59c8f9fSMark Brown if (rdev->bypass_count != rdev->open_count) { 4258f59c8f9fSMark Brown ret = rdev->desc->ops->set_bypass(rdev, enable); 4259f59c8f9fSMark Brown if (ret != 0) 4260f59c8f9fSMark Brown rdev->bypass_count++; 4261f59c8f9fSMark Brown } 4262f59c8f9fSMark Brown } 4263f59c8f9fSMark Brown 4264f59c8f9fSMark Brown if (ret == 0) 4265f59c8f9fSMark Brown regulator->bypass = enable; 4266f59c8f9fSMark Brown 426766cf9a7eSMaciej Purski regulator_unlock(rdev); 4268f59c8f9fSMark Brown 4269f59c8f9fSMark Brown return ret; 4270f59c8f9fSMark Brown } 4271f59c8f9fSMark Brown EXPORT_SYMBOL_GPL(regulator_allow_bypass); 4272f59c8f9fSMark Brown 4273f59c8f9fSMark Brown /** 4274414c70cbSLiam Girdwood * regulator_register_notifier - register regulator event notifier 4275414c70cbSLiam Girdwood * @regulator: regulator source 427669279fb9SMark Brown * @nb: notifier block 4277414c70cbSLiam Girdwood * 4278414c70cbSLiam Girdwood * Register notifier block to receive regulator events. 4279414c70cbSLiam Girdwood */ 4280414c70cbSLiam Girdwood int regulator_register_notifier(struct regulator *regulator, 4281414c70cbSLiam Girdwood struct notifier_block *nb) 4282414c70cbSLiam Girdwood { 4283414c70cbSLiam Girdwood return blocking_notifier_chain_register(®ulator->rdev->notifier, 4284414c70cbSLiam Girdwood nb); 4285414c70cbSLiam Girdwood } 4286414c70cbSLiam Girdwood EXPORT_SYMBOL_GPL(regulator_register_notifier); 4287414c70cbSLiam Girdwood 4288414c70cbSLiam Girdwood /** 4289414c70cbSLiam Girdwood * regulator_unregister_notifier - unregister regulator event notifier 4290414c70cbSLiam Girdwood * @regulator: regulator source 429169279fb9SMark Brown * @nb: notifier block 4292414c70cbSLiam Girdwood * 4293414c70cbSLiam Girdwood * Unregister regulator event notifier block. 4294414c70cbSLiam Girdwood */ 4295414c70cbSLiam Girdwood int regulator_unregister_notifier(struct regulator *regulator, 4296414c70cbSLiam Girdwood struct notifier_block *nb) 4297414c70cbSLiam Girdwood { 4298414c70cbSLiam Girdwood return blocking_notifier_chain_unregister(®ulator->rdev->notifier, 4299414c70cbSLiam Girdwood nb); 4300414c70cbSLiam Girdwood } 4301414c70cbSLiam Girdwood EXPORT_SYMBOL_GPL(regulator_unregister_notifier); 4302414c70cbSLiam Girdwood 4303b136fb44SJonathan Cameron /* notify regulator consumers and downstream regulator consumers. 4304b136fb44SJonathan Cameron * Note mutex must be held by caller. 4305b136fb44SJonathan Cameron */ 43067179569aSHeiko Stübner static int _notifier_call_chain(struct regulator_dev *rdev, 4307414c70cbSLiam Girdwood unsigned long event, void *data) 4308414c70cbSLiam Girdwood { 4309414c70cbSLiam Girdwood /* call rdev chain first */ 43107179569aSHeiko Stübner return blocking_notifier_call_chain(&rdev->notifier, event, data); 4311414c70cbSLiam Girdwood } 4312414c70cbSLiam Girdwood 4313414c70cbSLiam Girdwood /** 4314414c70cbSLiam Girdwood * regulator_bulk_get - get multiple regulator consumers 4315414c70cbSLiam Girdwood * 4316414c70cbSLiam Girdwood * @dev: Device to supply 4317414c70cbSLiam Girdwood * @num_consumers: Number of consumers to register 4318414c70cbSLiam Girdwood * @consumers: Configuration of consumers; clients are stored here. 4319414c70cbSLiam Girdwood * 4320414c70cbSLiam Girdwood * @return 0 on success, an errno on failure. 4321414c70cbSLiam Girdwood * 4322414c70cbSLiam Girdwood * This helper function allows drivers to get several regulator 4323414c70cbSLiam Girdwood * consumers in one operation. If any of the regulators cannot be 4324414c70cbSLiam Girdwood * acquired then any regulators that were allocated will be freed 4325414c70cbSLiam Girdwood * before returning to the caller. 4326414c70cbSLiam Girdwood */ 4327414c70cbSLiam Girdwood int regulator_bulk_get(struct device *dev, int num_consumers, 4328414c70cbSLiam Girdwood struct regulator_bulk_data *consumers) 4329414c70cbSLiam Girdwood { 4330414c70cbSLiam Girdwood int i; 4331414c70cbSLiam Girdwood int ret; 4332414c70cbSLiam Girdwood 4333414c70cbSLiam Girdwood for (i = 0; i < num_consumers; i++) 4334414c70cbSLiam Girdwood consumers[i].consumer = NULL; 4335414c70cbSLiam Girdwood 4336414c70cbSLiam Girdwood for (i = 0; i < num_consumers; i++) { 4337565f9b07SBjorn Andersson consumers[i].consumer = regulator_get(dev, 4338565f9b07SBjorn Andersson consumers[i].supply); 4339414c70cbSLiam Girdwood if (IS_ERR(consumers[i].consumer)) { 4340414c70cbSLiam Girdwood ret = PTR_ERR(consumers[i].consumer); 4341414c70cbSLiam Girdwood consumers[i].consumer = NULL; 4342414c70cbSLiam Girdwood goto err; 4343414c70cbSLiam Girdwood } 4344414c70cbSLiam Girdwood } 4345414c70cbSLiam Girdwood 4346414c70cbSLiam Girdwood return 0; 4347414c70cbSLiam Girdwood 4348414c70cbSLiam Girdwood err: 4349b9816363SJorge Ramirez-Ortiz if (ret != -EPROBE_DEFER) 4350b9816363SJorge Ramirez-Ortiz dev_err(dev, "Failed to get supply '%s': %d\n", 4351b9816363SJorge Ramirez-Ortiz consumers[i].supply, ret); 4352b9816363SJorge Ramirez-Ortiz else 4353b9816363SJorge Ramirez-Ortiz dev_dbg(dev, "Failed to get supply '%s', deferring\n", 4354b9816363SJorge Ramirez-Ortiz consumers[i].supply); 4355b9816363SJorge Ramirez-Ortiz 4356b29c7690SAxel Lin while (--i >= 0) 4357414c70cbSLiam Girdwood regulator_put(consumers[i].consumer); 4358414c70cbSLiam Girdwood 4359414c70cbSLiam Girdwood return ret; 4360414c70cbSLiam Girdwood } 4361414c70cbSLiam Girdwood EXPORT_SYMBOL_GPL(regulator_bulk_get); 4362414c70cbSLiam Girdwood 4363f21e0e81SMark Brown static void regulator_bulk_enable_async(void *data, async_cookie_t cookie) 4364f21e0e81SMark Brown { 4365f21e0e81SMark Brown struct regulator_bulk_data *bulk = data; 4366f21e0e81SMark Brown 4367f21e0e81SMark Brown bulk->ret = regulator_enable(bulk->consumer); 4368f21e0e81SMark Brown } 4369f21e0e81SMark Brown 4370414c70cbSLiam Girdwood /** 4371414c70cbSLiam Girdwood * regulator_bulk_enable - enable multiple regulator consumers 4372414c70cbSLiam Girdwood * 4373414c70cbSLiam Girdwood * @num_consumers: Number of consumers 4374414c70cbSLiam Girdwood * @consumers: Consumer data; clients are stored here. 4375414c70cbSLiam Girdwood * @return 0 on success, an errno on failure 4376414c70cbSLiam Girdwood * 4377414c70cbSLiam Girdwood * This convenience API allows consumers to enable multiple regulator 4378414c70cbSLiam Girdwood * clients in a single API call. If any consumers cannot be enabled 4379414c70cbSLiam Girdwood * then any others that were enabled will be disabled again prior to 4380414c70cbSLiam Girdwood * return. 4381414c70cbSLiam Girdwood */ 4382414c70cbSLiam Girdwood int regulator_bulk_enable(int num_consumers, 4383414c70cbSLiam Girdwood struct regulator_bulk_data *consumers) 4384414c70cbSLiam Girdwood { 43852955b47dSDan Williams ASYNC_DOMAIN_EXCLUSIVE(async_domain); 4386414c70cbSLiam Girdwood int i; 4387f21e0e81SMark Brown int ret = 0; 4388414c70cbSLiam Girdwood 43896492bc1bSMark Brown for (i = 0; i < num_consumers; i++) { 4390f21e0e81SMark Brown async_schedule_domain(regulator_bulk_enable_async, 4391f21e0e81SMark Brown &consumers[i], &async_domain); 43926492bc1bSMark Brown } 4393f21e0e81SMark Brown 4394f21e0e81SMark Brown async_synchronize_full_domain(&async_domain); 4395f21e0e81SMark Brown 4396f21e0e81SMark Brown /* If any consumer failed we need to unwind any that succeeded */ 4397414c70cbSLiam Girdwood for (i = 0; i < num_consumers; i++) { 4398f21e0e81SMark Brown if (consumers[i].ret != 0) { 4399f21e0e81SMark Brown ret = consumers[i].ret; 4400414c70cbSLiam Girdwood goto err; 4401414c70cbSLiam Girdwood } 4402f21e0e81SMark Brown } 4403414c70cbSLiam Girdwood 4404414c70cbSLiam Girdwood return 0; 4405414c70cbSLiam Girdwood 4406414c70cbSLiam Girdwood err: 4407fbe31057SAndrzej Hajda for (i = 0; i < num_consumers; i++) { 4408fbe31057SAndrzej Hajda if (consumers[i].ret < 0) 4409fbe31057SAndrzej Hajda pr_err("Failed to enable %s: %d\n", consumers[i].supply, 4410fbe31057SAndrzej Hajda consumers[i].ret); 4411fbe31057SAndrzej Hajda else 4412414c70cbSLiam Girdwood regulator_disable(consumers[i].consumer); 4413fbe31057SAndrzej Hajda } 4414414c70cbSLiam Girdwood 4415414c70cbSLiam Girdwood return ret; 4416414c70cbSLiam Girdwood } 4417414c70cbSLiam Girdwood EXPORT_SYMBOL_GPL(regulator_bulk_enable); 4418414c70cbSLiam Girdwood 4419414c70cbSLiam Girdwood /** 4420414c70cbSLiam Girdwood * regulator_bulk_disable - disable multiple regulator consumers 4421414c70cbSLiam Girdwood * 4422414c70cbSLiam Girdwood * @num_consumers: Number of consumers 4423414c70cbSLiam Girdwood * @consumers: Consumer data; clients are stored here. 4424414c70cbSLiam Girdwood * @return 0 on success, an errno on failure 4425414c70cbSLiam Girdwood * 4426414c70cbSLiam Girdwood * This convenience API allows consumers to disable multiple regulator 442749e22632SSylwester Nawrocki * clients in a single API call. If any consumers cannot be disabled 442849e22632SSylwester Nawrocki * then any others that were disabled will be enabled again prior to 4429414c70cbSLiam Girdwood * return. 4430414c70cbSLiam Girdwood */ 4431414c70cbSLiam Girdwood int regulator_bulk_disable(int num_consumers, 4432414c70cbSLiam Girdwood struct regulator_bulk_data *consumers) 4433414c70cbSLiam Girdwood { 4434414c70cbSLiam Girdwood int i; 443501e86f49SMark Brown int ret, r; 4436414c70cbSLiam Girdwood 443749e22632SSylwester Nawrocki for (i = num_consumers - 1; i >= 0; --i) { 4438414c70cbSLiam Girdwood ret = regulator_disable(consumers[i].consumer); 4439414c70cbSLiam Girdwood if (ret != 0) 4440414c70cbSLiam Girdwood goto err; 4441414c70cbSLiam Girdwood } 4442414c70cbSLiam Girdwood 4443414c70cbSLiam Girdwood return 0; 4444414c70cbSLiam Girdwood 4445414c70cbSLiam Girdwood err: 44465da84fd9SJoe Perches pr_err("Failed to disable %s: %d\n", consumers[i].supply, ret); 444701e86f49SMark Brown for (++i; i < num_consumers; ++i) { 444801e86f49SMark Brown r = regulator_enable(consumers[i].consumer); 444901e86f49SMark Brown if (r != 0) 4450d1642ea7SDmitry Torokhov pr_err("Failed to re-enable %s: %d\n", 445101e86f49SMark Brown consumers[i].supply, r); 445201e86f49SMark Brown } 4453414c70cbSLiam Girdwood 4454414c70cbSLiam Girdwood return ret; 4455414c70cbSLiam Girdwood } 4456414c70cbSLiam Girdwood EXPORT_SYMBOL_GPL(regulator_bulk_disable); 4457414c70cbSLiam Girdwood 4458414c70cbSLiam Girdwood /** 4459e1de2f42SDonggeun Kim * regulator_bulk_force_disable - force disable multiple regulator consumers 4460e1de2f42SDonggeun Kim * 4461e1de2f42SDonggeun Kim * @num_consumers: Number of consumers 4462e1de2f42SDonggeun Kim * @consumers: Consumer data; clients are stored here. 4463e1de2f42SDonggeun Kim * @return 0 on success, an errno on failure 4464e1de2f42SDonggeun Kim * 4465e1de2f42SDonggeun Kim * This convenience API allows consumers to forcibly disable multiple regulator 4466e1de2f42SDonggeun Kim * clients in a single API call. 4467e1de2f42SDonggeun Kim * NOTE: This should be used for situations when device damage will 4468e1de2f42SDonggeun Kim * likely occur if the regulators are not disabled (e.g. over temp). 4469e1de2f42SDonggeun Kim * Although regulator_force_disable function call for some consumers can 4470e1de2f42SDonggeun Kim * return error numbers, the function is called for all consumers. 4471e1de2f42SDonggeun Kim */ 4472e1de2f42SDonggeun Kim int regulator_bulk_force_disable(int num_consumers, 4473e1de2f42SDonggeun Kim struct regulator_bulk_data *consumers) 4474e1de2f42SDonggeun Kim { 4475e1de2f42SDonggeun Kim int i; 4476b8c77ff6SDmitry Torokhov int ret = 0; 4477e1de2f42SDonggeun Kim 4478b8c77ff6SDmitry Torokhov for (i = 0; i < num_consumers; i++) { 4479e1de2f42SDonggeun Kim consumers[i].ret = 4480e1de2f42SDonggeun Kim regulator_force_disable(consumers[i].consumer); 4481e1de2f42SDonggeun Kim 4482b8c77ff6SDmitry Torokhov /* Store first error for reporting */ 4483b8c77ff6SDmitry Torokhov if (consumers[i].ret && !ret) 4484e1de2f42SDonggeun Kim ret = consumers[i].ret; 4485e1de2f42SDonggeun Kim } 4486e1de2f42SDonggeun Kim 4487e1de2f42SDonggeun Kim return ret; 4488e1de2f42SDonggeun Kim } 4489e1de2f42SDonggeun Kim EXPORT_SYMBOL_GPL(regulator_bulk_force_disable); 4490e1de2f42SDonggeun Kim 4491e1de2f42SDonggeun Kim /** 4492414c70cbSLiam Girdwood * regulator_bulk_free - free multiple regulator consumers 4493414c70cbSLiam Girdwood * 4494414c70cbSLiam Girdwood * @num_consumers: Number of consumers 4495414c70cbSLiam Girdwood * @consumers: Consumer data; clients are stored here. 4496414c70cbSLiam Girdwood * 4497414c70cbSLiam Girdwood * This convenience API allows consumers to free multiple regulator 4498414c70cbSLiam Girdwood * clients in a single API call. 4499414c70cbSLiam Girdwood */ 4500414c70cbSLiam Girdwood void regulator_bulk_free(int num_consumers, 4501414c70cbSLiam Girdwood struct regulator_bulk_data *consumers) 4502414c70cbSLiam Girdwood { 4503414c70cbSLiam Girdwood int i; 4504414c70cbSLiam Girdwood 4505414c70cbSLiam Girdwood for (i = 0; i < num_consumers; i++) { 4506414c70cbSLiam Girdwood regulator_put(consumers[i].consumer); 4507414c70cbSLiam Girdwood consumers[i].consumer = NULL; 4508414c70cbSLiam Girdwood } 4509414c70cbSLiam Girdwood } 4510414c70cbSLiam Girdwood EXPORT_SYMBOL_GPL(regulator_bulk_free); 4511414c70cbSLiam Girdwood 4512414c70cbSLiam Girdwood /** 4513414c70cbSLiam Girdwood * regulator_notifier_call_chain - call regulator event notifier 451469279fb9SMark Brown * @rdev: regulator source 4515414c70cbSLiam Girdwood * @event: notifier block 451669279fb9SMark Brown * @data: callback-specific data. 4517414c70cbSLiam Girdwood * 4518414c70cbSLiam Girdwood * Called by regulator drivers to notify clients a regulator event has 4519414c70cbSLiam Girdwood * occurred. We also notify regulator clients downstream. 4520b136fb44SJonathan Cameron * Note lock must be held by caller. 4521414c70cbSLiam Girdwood */ 4522414c70cbSLiam Girdwood int regulator_notifier_call_chain(struct regulator_dev *rdev, 4523414c70cbSLiam Girdwood unsigned long event, void *data) 4524414c70cbSLiam Girdwood { 4525f8702f9eSDmitry Osipenko lockdep_assert_held_once(&rdev->mutex.base); 452670cfef26SKrzysztof Kozlowski 4527414c70cbSLiam Girdwood _notifier_call_chain(rdev, event, data); 4528414c70cbSLiam Girdwood return NOTIFY_DONE; 4529414c70cbSLiam Girdwood 4530414c70cbSLiam Girdwood } 4531414c70cbSLiam Girdwood EXPORT_SYMBOL_GPL(regulator_notifier_call_chain); 4532414c70cbSLiam Girdwood 4533be721979SMark Brown /** 4534be721979SMark Brown * regulator_mode_to_status - convert a regulator mode into a status 4535be721979SMark Brown * 4536be721979SMark Brown * @mode: Mode to convert 4537be721979SMark Brown * 4538be721979SMark Brown * Convert a regulator mode into a status. 4539be721979SMark Brown */ 4540be721979SMark Brown int regulator_mode_to_status(unsigned int mode) 4541be721979SMark Brown { 4542be721979SMark Brown switch (mode) { 4543be721979SMark Brown case REGULATOR_MODE_FAST: 4544be721979SMark Brown return REGULATOR_STATUS_FAST; 4545be721979SMark Brown case REGULATOR_MODE_NORMAL: 4546be721979SMark Brown return REGULATOR_STATUS_NORMAL; 4547be721979SMark Brown case REGULATOR_MODE_IDLE: 4548be721979SMark Brown return REGULATOR_STATUS_IDLE; 454903ffcf3dSKrystian Garbaciak case REGULATOR_MODE_STANDBY: 4550be721979SMark Brown return REGULATOR_STATUS_STANDBY; 4551be721979SMark Brown default: 45521beaf762SKrystian Garbaciak return REGULATOR_STATUS_UNDEFINED; 4553be721979SMark Brown } 4554be721979SMark Brown } 4555be721979SMark Brown EXPORT_SYMBOL_GPL(regulator_mode_to_status); 4556be721979SMark Brown 455739f802d6STakashi Iwai static struct attribute *regulator_dev_attrs[] = { 455839f802d6STakashi Iwai &dev_attr_name.attr, 455939f802d6STakashi Iwai &dev_attr_num_users.attr, 456039f802d6STakashi Iwai &dev_attr_type.attr, 456139f802d6STakashi Iwai &dev_attr_microvolts.attr, 456239f802d6STakashi Iwai &dev_attr_microamps.attr, 456339f802d6STakashi Iwai &dev_attr_opmode.attr, 456439f802d6STakashi Iwai &dev_attr_state.attr, 456539f802d6STakashi Iwai &dev_attr_status.attr, 456639f802d6STakashi Iwai &dev_attr_bypass.attr, 456739f802d6STakashi Iwai &dev_attr_requested_microamps.attr, 456839f802d6STakashi Iwai &dev_attr_min_microvolts.attr, 456939f802d6STakashi Iwai &dev_attr_max_microvolts.attr, 457039f802d6STakashi Iwai &dev_attr_min_microamps.attr, 457139f802d6STakashi Iwai &dev_attr_max_microamps.attr, 457239f802d6STakashi Iwai &dev_attr_suspend_standby_state.attr, 457339f802d6STakashi Iwai &dev_attr_suspend_mem_state.attr, 457439f802d6STakashi Iwai &dev_attr_suspend_disk_state.attr, 457539f802d6STakashi Iwai &dev_attr_suspend_standby_microvolts.attr, 457639f802d6STakashi Iwai &dev_attr_suspend_mem_microvolts.attr, 457739f802d6STakashi Iwai &dev_attr_suspend_disk_microvolts.attr, 457839f802d6STakashi Iwai &dev_attr_suspend_standby_mode.attr, 457939f802d6STakashi Iwai &dev_attr_suspend_mem_mode.attr, 458039f802d6STakashi Iwai &dev_attr_suspend_disk_mode.attr, 458139f802d6STakashi Iwai NULL 458239f802d6STakashi Iwai }; 458339f802d6STakashi Iwai 45847ad68e2fSDavid Brownell /* 45857ad68e2fSDavid Brownell * To avoid cluttering sysfs (and memory) with useless state, only 45867ad68e2fSDavid Brownell * create attributes that can be meaningfully displayed. 45877ad68e2fSDavid Brownell */ 458839f802d6STakashi Iwai static umode_t regulator_attr_is_visible(struct kobject *kobj, 458939f802d6STakashi Iwai struct attribute *attr, int idx) 45907ad68e2fSDavid Brownell { 459139f802d6STakashi Iwai struct device *dev = kobj_to_dev(kobj); 459283080a14SGeliang Tang struct regulator_dev *rdev = dev_to_rdev(dev); 4593272e2315SGuodong Xu const struct regulator_ops *ops = rdev->desc->ops; 459439f802d6STakashi Iwai umode_t mode = attr->mode; 459539f802d6STakashi Iwai 459639f802d6STakashi Iwai /* these three are always present */ 459739f802d6STakashi Iwai if (attr == &dev_attr_name.attr || 459839f802d6STakashi Iwai attr == &dev_attr_num_users.attr || 459939f802d6STakashi Iwai attr == &dev_attr_type.attr) 460039f802d6STakashi Iwai return mode; 46017ad68e2fSDavid Brownell 46027ad68e2fSDavid Brownell /* some attributes need specific methods to be displayed */ 460339f802d6STakashi Iwai if (attr == &dev_attr_microvolts.attr) { 46044c78899bSMark Brown if ((ops->get_voltage && ops->get_voltage(rdev) >= 0) || 4605f2889e65SMark Brown (ops->get_voltage_sel && ops->get_voltage_sel(rdev) >= 0) || 46065a523605SLaxman Dewangan (ops->list_voltage && ops->list_voltage(rdev, 0) >= 0) || 460739f802d6STakashi Iwai (rdev->desc->fixed_uV && rdev->desc->n_voltages == 1)) 460839f802d6STakashi Iwai return mode; 460939f802d6STakashi Iwai return 0; 4610f59c8f9fSMark Brown } 46117ad68e2fSDavid Brownell 461239f802d6STakashi Iwai if (attr == &dev_attr_microamps.attr) 461339f802d6STakashi Iwai return ops->get_current_limit ? mode : 0; 461439f802d6STakashi Iwai 461539f802d6STakashi Iwai if (attr == &dev_attr_opmode.attr) 461639f802d6STakashi Iwai return ops->get_mode ? mode : 0; 461739f802d6STakashi Iwai 461839f802d6STakashi Iwai if (attr == &dev_attr_state.attr) 461939f802d6STakashi Iwai return (rdev->ena_pin || ops->is_enabled) ? mode : 0; 462039f802d6STakashi Iwai 462139f802d6STakashi Iwai if (attr == &dev_attr_status.attr) 462239f802d6STakashi Iwai return ops->get_status ? mode : 0; 462339f802d6STakashi Iwai 462439f802d6STakashi Iwai if (attr == &dev_attr_bypass.attr) 462539f802d6STakashi Iwai return ops->get_bypass ? mode : 0; 462639f802d6STakashi Iwai 46277ad68e2fSDavid Brownell /* constraints need specific supporting methods */ 462839f802d6STakashi Iwai if (attr == &dev_attr_min_microvolts.attr || 462939f802d6STakashi Iwai attr == &dev_attr_max_microvolts.attr) 463039f802d6STakashi Iwai return (ops->set_voltage || ops->set_voltage_sel) ? mode : 0; 463139f802d6STakashi Iwai 463239f802d6STakashi Iwai if (attr == &dev_attr_min_microamps.attr || 463339f802d6STakashi Iwai attr == &dev_attr_max_microamps.attr) 463439f802d6STakashi Iwai return ops->set_current_limit ? mode : 0; 463539f802d6STakashi Iwai 463639f802d6STakashi Iwai if (attr == &dev_attr_suspend_standby_state.attr || 463739f802d6STakashi Iwai attr == &dev_attr_suspend_mem_state.attr || 463839f802d6STakashi Iwai attr == &dev_attr_suspend_disk_state.attr) 463939f802d6STakashi Iwai return mode; 464039f802d6STakashi Iwai 464139f802d6STakashi Iwai if (attr == &dev_attr_suspend_standby_microvolts.attr || 464239f802d6STakashi Iwai attr == &dev_attr_suspend_mem_microvolts.attr || 464339f802d6STakashi Iwai attr == &dev_attr_suspend_disk_microvolts.attr) 464439f802d6STakashi Iwai return ops->set_suspend_voltage ? mode : 0; 464539f802d6STakashi Iwai 464639f802d6STakashi Iwai if (attr == &dev_attr_suspend_standby_mode.attr || 464739f802d6STakashi Iwai attr == &dev_attr_suspend_mem_mode.attr || 464839f802d6STakashi Iwai attr == &dev_attr_suspend_disk_mode.attr) 464939f802d6STakashi Iwai return ops->set_suspend_mode ? mode : 0; 465039f802d6STakashi Iwai 465139f802d6STakashi Iwai return mode; 46527ad68e2fSDavid Brownell } 46537ad68e2fSDavid Brownell 465439f802d6STakashi Iwai static const struct attribute_group regulator_dev_group = { 465539f802d6STakashi Iwai .attrs = regulator_dev_attrs, 465639f802d6STakashi Iwai .is_visible = regulator_attr_is_visible, 465739f802d6STakashi Iwai }; 46587ad68e2fSDavid Brownell 465939f802d6STakashi Iwai static const struct attribute_group *regulator_dev_groups[] = { 466039f802d6STakashi Iwai ®ulator_dev_group, 466139f802d6STakashi Iwai NULL 466239f802d6STakashi Iwai }; 466339f802d6STakashi Iwai 466439f802d6STakashi Iwai static void regulator_dev_release(struct device *dev) 466539f802d6STakashi Iwai { 466639f802d6STakashi Iwai struct regulator_dev *rdev = dev_get_drvdata(dev); 466729f5f486SMark Brown 466829f5f486SMark Brown kfree(rdev->constraints); 466929f5f486SMark Brown of_node_put(rdev->dev.of_node); 467039f802d6STakashi Iwai kfree(rdev); 46717ad68e2fSDavid Brownell } 46727ad68e2fSDavid Brownell 46731130e5b3SMark Brown static void rdev_init_debugfs(struct regulator_dev *rdev) 46741130e5b3SMark Brown { 4675a9eaa813SGuenter Roeck struct device *parent = rdev->dev.parent; 4676a9eaa813SGuenter Roeck const char *rname = rdev_get_name(rdev); 4677a9eaa813SGuenter Roeck char name[NAME_MAX]; 4678a9eaa813SGuenter Roeck 4679a9eaa813SGuenter Roeck /* Avoid duplicate debugfs directory names */ 4680a9eaa813SGuenter Roeck if (parent && rname == rdev->desc->name) { 4681a9eaa813SGuenter Roeck snprintf(name, sizeof(name), "%s-%s", dev_name(parent), 4682a9eaa813SGuenter Roeck rname); 4683a9eaa813SGuenter Roeck rname = name; 4684a9eaa813SGuenter Roeck } 4685a9eaa813SGuenter Roeck 4686a9eaa813SGuenter Roeck rdev->debugfs = debugfs_create_dir(rname, debugfs_root); 468724751434SStephen Boyd if (!rdev->debugfs) { 46881130e5b3SMark Brown rdev_warn(rdev, "Failed to create debugfs directory\n"); 46891130e5b3SMark Brown return; 46901130e5b3SMark Brown } 46911130e5b3SMark Brown 46921130e5b3SMark Brown debugfs_create_u32("use_count", 0444, rdev->debugfs, 46931130e5b3SMark Brown &rdev->use_count); 46941130e5b3SMark Brown debugfs_create_u32("open_count", 0444, rdev->debugfs, 46951130e5b3SMark Brown &rdev->open_count); 4696f59c8f9fSMark Brown debugfs_create_u32("bypass_count", 0444, rdev->debugfs, 4697f59c8f9fSMark Brown &rdev->bypass_count); 46981130e5b3SMark Brown } 46991130e5b3SMark Brown 47005e3ca2b3SJavier Martinez Canillas static int regulator_register_resolve_supply(struct device *dev, void *data) 47015e3ca2b3SJavier Martinez Canillas { 47027ddede6aSJon Hunter struct regulator_dev *rdev = dev_to_rdev(dev); 47037ddede6aSJon Hunter 47047ddede6aSJon Hunter if (regulator_resolve_supply(rdev)) 47057ddede6aSJon Hunter rdev_dbg(rdev, "unable to resolve supply\n"); 47067ddede6aSJon Hunter 47077ddede6aSJon Hunter return 0; 47085e3ca2b3SJavier Martinez Canillas } 47095e3ca2b3SJavier Martinez Canillas 4710f9503385SDmitry Osipenko static void regulator_resolve_coupling(struct regulator_dev *rdev) 4711d3d64537SMaciej Purski { 4712d3d64537SMaciej Purski struct coupling_desc *c_desc = &rdev->coupling_desc; 4713d3d64537SMaciej Purski int n_coupled = c_desc->n_coupled; 4714d3d64537SMaciej Purski struct regulator_dev *c_rdev; 4715d3d64537SMaciej Purski int i; 4716d3d64537SMaciej Purski 4717d3d64537SMaciej Purski for (i = 1; i < n_coupled; i++) { 4718d3d64537SMaciej Purski /* already resolved */ 4719d3d64537SMaciej Purski if (c_desc->coupled_rdevs[i]) 4720d3d64537SMaciej Purski continue; 4721d3d64537SMaciej Purski 4722d3d64537SMaciej Purski c_rdev = of_parse_coupled_regulator(rdev, i - 1); 4723d3d64537SMaciej Purski 4724f9503385SDmitry Osipenko if (!c_rdev) 4725f9503385SDmitry Osipenko continue; 4726f9503385SDmitry Osipenko 4727f9503385SDmitry Osipenko regulator_lock(c_rdev); 4728f9503385SDmitry Osipenko 4729d3d64537SMaciej Purski c_desc->coupled_rdevs[i] = c_rdev; 4730d3d64537SMaciej Purski c_desc->n_resolved++; 4731f9503385SDmitry Osipenko 4732f9503385SDmitry Osipenko regulator_unlock(c_rdev); 4733f9503385SDmitry Osipenko 4734f9503385SDmitry Osipenko regulator_resolve_coupling(c_rdev); 4735d3d64537SMaciej Purski } 4736d3d64537SMaciej Purski } 4737d3d64537SMaciej Purski 47386303f3e7SDmitry Osipenko static void regulator_remove_coupling(struct regulator_dev *rdev) 4739d3d64537SMaciej Purski { 47406303f3e7SDmitry Osipenko struct coupling_desc *__c_desc, *c_desc = &rdev->coupling_desc; 47416303f3e7SDmitry Osipenko struct regulator_dev *__c_rdev, *c_rdev; 47426303f3e7SDmitry Osipenko unsigned int __n_coupled, n_coupled; 47436303f3e7SDmitry Osipenko int i, k; 4744d3d64537SMaciej Purski 47456303f3e7SDmitry Osipenko n_coupled = c_desc->n_coupled; 4746d3d64537SMaciej Purski 47476303f3e7SDmitry Osipenko for (i = 1; i < n_coupled; i++) { 47486303f3e7SDmitry Osipenko c_rdev = c_desc->coupled_rdevs[i]; 4749d3d64537SMaciej Purski 47506303f3e7SDmitry Osipenko if (!c_rdev) 47516303f3e7SDmitry Osipenko continue; 47526303f3e7SDmitry Osipenko 47536303f3e7SDmitry Osipenko regulator_lock(c_rdev); 47546303f3e7SDmitry Osipenko 47556303f3e7SDmitry Osipenko __c_desc = &c_rdev->coupling_desc; 47566303f3e7SDmitry Osipenko __n_coupled = __c_desc->n_coupled; 47576303f3e7SDmitry Osipenko 47586303f3e7SDmitry Osipenko for (k = 1; k < __n_coupled; k++) { 47596303f3e7SDmitry Osipenko __c_rdev = __c_desc->coupled_rdevs[k]; 47606303f3e7SDmitry Osipenko 47616303f3e7SDmitry Osipenko if (__c_rdev == rdev) { 47626303f3e7SDmitry Osipenko __c_desc->coupled_rdevs[k] = NULL; 47636303f3e7SDmitry Osipenko __c_desc->n_resolved--; 47646303f3e7SDmitry Osipenko break; 47656303f3e7SDmitry Osipenko } 4766d3d64537SMaciej Purski } 4767d3d64537SMaciej Purski 47686303f3e7SDmitry Osipenko regulator_unlock(c_rdev); 47696303f3e7SDmitry Osipenko 47706303f3e7SDmitry Osipenko c_desc->coupled_rdevs[i] = NULL; 47716303f3e7SDmitry Osipenko c_desc->n_resolved--; 47726303f3e7SDmitry Osipenko } 47736303f3e7SDmitry Osipenko } 47746303f3e7SDmitry Osipenko 4775f9503385SDmitry Osipenko static int regulator_init_coupling(struct regulator_dev *rdev) 4776d3d64537SMaciej Purski { 4777d3d64537SMaciej Purski int n_phandles; 4778d3d64537SMaciej Purski 4779d3d64537SMaciej Purski if (!IS_ENABLED(CONFIG_OF)) 4780d3d64537SMaciej Purski n_phandles = 0; 4781d3d64537SMaciej Purski else 4782d3d64537SMaciej Purski n_phandles = of_get_n_coupled(rdev); 4783d3d64537SMaciej Purski 4784d3d64537SMaciej Purski if (n_phandles + 1 > MAX_COUPLED) { 4785d3d64537SMaciej Purski rdev_err(rdev, "too many regulators coupled\n"); 4786d3d64537SMaciej Purski return -EPERM; 4787d3d64537SMaciej Purski } 4788d3d64537SMaciej Purski 4789d3d64537SMaciej Purski /* 4790d3d64537SMaciej Purski * Every regulator should always have coupling descriptor filled with 4791d3d64537SMaciej Purski * at least pointer to itself. 4792d3d64537SMaciej Purski */ 4793d3d64537SMaciej Purski rdev->coupling_desc.coupled_rdevs[0] = rdev; 4794d3d64537SMaciej Purski rdev->coupling_desc.n_coupled = n_phandles + 1; 4795d3d64537SMaciej Purski rdev->coupling_desc.n_resolved++; 4796d3d64537SMaciej Purski 4797d3d64537SMaciej Purski /* regulator isn't coupled */ 4798d3d64537SMaciej Purski if (n_phandles == 0) 4799d3d64537SMaciej Purski return 0; 4800d3d64537SMaciej Purski 4801d3d64537SMaciej Purski /* regulator, which can't change its voltage, can't be coupled */ 4802d3d64537SMaciej Purski if (!regulator_ops_is_valid(rdev, REGULATOR_CHANGE_VOLTAGE)) { 4803d3d64537SMaciej Purski rdev_err(rdev, "voltage operation not allowed\n"); 4804d3d64537SMaciej Purski return -EPERM; 4805d3d64537SMaciej Purski } 4806d3d64537SMaciej Purski 4807d3d64537SMaciej Purski if (rdev->constraints->max_spread <= 0) { 4808d3d64537SMaciej Purski rdev_err(rdev, "wrong max_spread value\n"); 4809d3d64537SMaciej Purski return -EPERM; 4810d3d64537SMaciej Purski } 4811d3d64537SMaciej Purski 4812d3d64537SMaciej Purski if (!of_check_coupling_data(rdev)) 4813d3d64537SMaciej Purski return -EPERM; 4814d3d64537SMaciej Purski 4815d3d64537SMaciej Purski return 0; 4816d3d64537SMaciej Purski } 4817d3d64537SMaciej Purski 4818414c70cbSLiam Girdwood /** 4819414c70cbSLiam Girdwood * regulator_register - register regulator 482069279fb9SMark Brown * @regulator_desc: regulator to register 4821f47531b1SKrzysztof Kozlowski * @cfg: runtime configuration for regulator 4822414c70cbSLiam Girdwood * 4823414c70cbSLiam Girdwood * Called by regulator drivers to register a regulator. 48240384618aSAxel Lin * Returns a valid pointer to struct regulator_dev on success 48250384618aSAxel Lin * or an ERR_PTR() on error. 4826414c70cbSLiam Girdwood */ 482765f26846SMark Brown struct regulator_dev * 482865f26846SMark Brown regulator_register(const struct regulator_desc *regulator_desc, 48291b3de223SKrzysztof Kozlowski const struct regulator_config *cfg) 4830414c70cbSLiam Girdwood { 48319a8f5e07SMark Brown const struct regulation_constraints *constraints = NULL; 4832c172708dSMark Brown const struct regulator_init_data *init_data; 48331b3de223SKrzysztof Kozlowski struct regulator_config *config = NULL; 483472dca06fSAniroop Mathur static atomic_t regulator_no = ATOMIC_INIT(-1); 4835414c70cbSLiam Girdwood struct regulator_dev *rdev; 48360edb040dSLinus Walleij bool dangling_cfg_gpiod = false; 48370edb040dSLinus Walleij bool dangling_of_gpiod = false; 483832c8fad4SMark Brown struct device *dev; 4839a5766f11SLiam Girdwood int ret, i; 4840414c70cbSLiam Girdwood 48410edb040dSLinus Walleij if (cfg == NULL) 4842414c70cbSLiam Girdwood return ERR_PTR(-EINVAL); 48430edb040dSLinus Walleij if (cfg->ena_gpiod) 48440edb040dSLinus Walleij dangling_cfg_gpiod = true; 48450edb040dSLinus Walleij if (regulator_desc == NULL) { 48460edb040dSLinus Walleij ret = -EINVAL; 48470edb040dSLinus Walleij goto rinse; 48480edb040dSLinus Walleij } 4849414c70cbSLiam Girdwood 48501b3de223SKrzysztof Kozlowski dev = cfg->dev; 4851dcf70112SMark Brown WARN_ON(!dev); 485232c8fad4SMark Brown 48530edb040dSLinus Walleij if (regulator_desc->name == NULL || regulator_desc->ops == NULL) { 48540edb040dSLinus Walleij ret = -EINVAL; 48550edb040dSLinus Walleij goto rinse; 48560edb040dSLinus Walleij } 4857414c70cbSLiam Girdwood 4858cd78dfc6SDiego Liziero if (regulator_desc->type != REGULATOR_VOLTAGE && 48590edb040dSLinus Walleij regulator_desc->type != REGULATOR_CURRENT) { 48600edb040dSLinus Walleij ret = -EINVAL; 48610edb040dSLinus Walleij goto rinse; 48620edb040dSLinus Walleij } 4863414c70cbSLiam Girdwood 4864476c2d83SMark Brown /* Only one of each should be implemented */ 4865476c2d83SMark Brown WARN_ON(regulator_desc->ops->get_voltage && 4866476c2d83SMark Brown regulator_desc->ops->get_voltage_sel); 4867e8eef82bSMark Brown WARN_ON(regulator_desc->ops->set_voltage && 4868e8eef82bSMark Brown regulator_desc->ops->set_voltage_sel); 4869476c2d83SMark Brown 4870476c2d83SMark Brown /* If we're using selectors we must implement list_voltage. */ 4871476c2d83SMark Brown if (regulator_desc->ops->get_voltage_sel && 4872476c2d83SMark Brown !regulator_desc->ops->list_voltage) { 48730edb040dSLinus Walleij ret = -EINVAL; 48740edb040dSLinus Walleij goto rinse; 4875476c2d83SMark Brown } 4876e8eef82bSMark Brown if (regulator_desc->ops->set_voltage_sel && 4877e8eef82bSMark Brown !regulator_desc->ops->list_voltage) { 48780edb040dSLinus Walleij ret = -EINVAL; 48790edb040dSLinus Walleij goto rinse; 4880e8eef82bSMark Brown } 4881476c2d83SMark Brown 4882414c70cbSLiam Girdwood rdev = kzalloc(sizeof(struct regulator_dev), GFP_KERNEL); 48830edb040dSLinus Walleij if (rdev == NULL) { 48840edb040dSLinus Walleij ret = -ENOMEM; 48850edb040dSLinus Walleij goto rinse; 48860edb040dSLinus Walleij } 4887414c70cbSLiam Girdwood 48881b3de223SKrzysztof Kozlowski /* 48891b3de223SKrzysztof Kozlowski * Duplicate the config so the driver could override it after 48901b3de223SKrzysztof Kozlowski * parsing init data. 48911b3de223SKrzysztof Kozlowski */ 48921b3de223SKrzysztof Kozlowski config = kmemdup(cfg, sizeof(*cfg), GFP_KERNEL); 48931b3de223SKrzysztof Kozlowski if (config == NULL) { 48941b3de223SKrzysztof Kozlowski kfree(rdev); 48950edb040dSLinus Walleij ret = -ENOMEM; 48960edb040dSLinus Walleij goto rinse; 48971b3de223SKrzysztof Kozlowski } 48981b3de223SKrzysztof Kozlowski 4899bfa21a0dSKrzysztof Kozlowski init_data = regulator_of_get_init_data(dev, regulator_desc, config, 4900a0c7b164SMark Brown &rdev->dev.of_node); 49010edb040dSLinus Walleij /* 49020edb040dSLinus Walleij * We need to keep track of any GPIO descriptor coming from the 49030edb040dSLinus Walleij * device tree until we have handled it over to the core. If the 49040edb040dSLinus Walleij * config that was passed in to this function DOES NOT contain 49050edb040dSLinus Walleij * a descriptor, and the config after this call DOES contain 490648f1b4efSKrzysztof Kozlowski * a descriptor, we definitely got one from parsing the device 49070edb040dSLinus Walleij * tree. 49080edb040dSLinus Walleij */ 49090edb040dSLinus Walleij if (!cfg->ena_gpiod && config->ena_gpiod) 49100edb040dSLinus Walleij dangling_of_gpiod = true; 4911a0c7b164SMark Brown if (!init_data) { 4912a0c7b164SMark Brown init_data = config->init_data; 4913a0c7b164SMark Brown rdev->dev.of_node = of_node_get(config->of_node); 4914a0c7b164SMark Brown } 4915a0c7b164SMark Brown 4916f8702f9eSDmitry Osipenko ww_mutex_init(&rdev->mutex, ®ulator_ww_class); 4917c172708dSMark Brown rdev->reg_data = config->driver_data; 4918414c70cbSLiam Girdwood rdev->owner = regulator_desc->owner; 4919414c70cbSLiam Girdwood rdev->desc = regulator_desc; 49203a4b0a07SMark Brown if (config->regmap) 492165b19ce6SMark Brown rdev->regmap = config->regmap; 492252b84dacSAnilKumar Ch else if (dev_get_regmap(dev, NULL)) 49233a4b0a07SMark Brown rdev->regmap = dev_get_regmap(dev, NULL); 492452b84dacSAnilKumar Ch else if (dev->parent) 492552b84dacSAnilKumar Ch rdev->regmap = dev_get_regmap(dev->parent, NULL); 4926414c70cbSLiam Girdwood INIT_LIST_HEAD(&rdev->consumer_list); 4927414c70cbSLiam Girdwood INIT_LIST_HEAD(&rdev->list); 4928414c70cbSLiam Girdwood BLOCKING_INIT_NOTIFIER_HEAD(&rdev->notifier); 4929da07ecd9SMark Brown INIT_DELAYED_WORK(&rdev->disable_work, regulator_disable_work); 4930414c70cbSLiam Girdwood 4931a5766f11SLiam Girdwood /* preform any regulator specific init */ 49329a8f5e07SMark Brown if (init_data && init_data->regulator_init) { 4933a5766f11SLiam Girdwood ret = init_data->regulator_init(rdev->reg_data); 49344fca9545SDavid Brownell if (ret < 0) 49354fca9545SDavid Brownell goto clean; 4936a5766f11SLiam Girdwood } 4937a5766f11SLiam Girdwood 4938541d052dSLinus Walleij if (config->ena_gpiod) { 493945389c47SJon Hunter mutex_lock(®ulator_list_mutex); 4940daad134dSKrzysztof Adamski ret = regulator_ena_gpio_request(rdev, config); 494145389c47SJon Hunter mutex_unlock(®ulator_list_mutex); 4942daad134dSKrzysztof Adamski if (ret != 0) { 4943541d052dSLinus Walleij rdev_err(rdev, "Failed to request enable GPIO: %d\n", 4944541d052dSLinus Walleij ret); 494532165230SKrzysztof Adamski goto clean; 4946daad134dSKrzysztof Adamski } 49470edb040dSLinus Walleij /* The regulator core took over the GPIO descriptor */ 49480edb040dSLinus Walleij dangling_cfg_gpiod = false; 49490edb040dSLinus Walleij dangling_of_gpiod = false; 4950daad134dSKrzysztof Adamski } 4951daad134dSKrzysztof Adamski 4952a5766f11SLiam Girdwood /* register with sysfs */ 4953a5766f11SLiam Girdwood rdev->dev.class = ®ulator_class; 4954a5766f11SLiam Girdwood rdev->dev.parent = dev; 495572dca06fSAniroop Mathur dev_set_name(&rdev->dev, "regulator.%lu", 495639138818SAniroop Mathur (unsigned long) atomic_inc_return(®ulator_no)); 4957a5766f11SLiam Girdwood 495874f544c1SMike Rapoport /* set regulator constraints */ 49599a8f5e07SMark Brown if (init_data) 49609a8f5e07SMark Brown constraints = &init_data->constraints; 49619a8f5e07SMark Brown 49629a8f5e07SMark Brown if (init_data && init_data->supply_regulator) 49636261b06dSBjorn Andersson rdev->supply_name = init_data->supply_regulator; 496469511a45SRajendra Nayak else if (regulator_desc->supply_name) 49656261b06dSBjorn Andersson rdev->supply_name = regulator_desc->supply_name; 496669511a45SRajendra Nayak 496745389c47SJon Hunter /* 496845389c47SJon Hunter * Attempt to resolve the regulator supply, if specified, 496945389c47SJon Hunter * but don't return an error if we fail because we will try 497045389c47SJon Hunter * to resolve it again later as more regulators are added. 497145389c47SJon Hunter */ 497245389c47SJon Hunter if (regulator_resolve_supply(rdev)) 497345389c47SJon Hunter rdev_dbg(rdev, "unable to resolve supply\n"); 497445389c47SJon Hunter 497545389c47SJon Hunter ret = set_machine_constraints(rdev, constraints); 497645389c47SJon Hunter if (ret < 0) 497745389c47SJon Hunter goto wash; 497845389c47SJon Hunter 4979f9503385SDmitry Osipenko ret = regulator_init_coupling(rdev); 4980f9503385SDmitry Osipenko if (ret < 0) 4981d3d64537SMaciej Purski goto wash; 4982d3d64537SMaciej Purski 4983a5766f11SLiam Girdwood /* add consumers devices */ 49849a8f5e07SMark Brown if (init_data) { 498545389c47SJon Hunter mutex_lock(®ulator_list_mutex); 4986a5766f11SLiam Girdwood for (i = 0; i < init_data->num_consumer_supplies; i++) { 4987a5766f11SLiam Girdwood ret = set_consumer_device_supply(rdev, 498840f9244fSMark Brown init_data->consumer_supplies[i].dev_name, 4989a5766f11SLiam Girdwood init_data->consumer_supplies[i].supply); 499023c2f041SMark Brown if (ret < 0) { 499145389c47SJon Hunter mutex_unlock(®ulator_list_mutex); 499223c2f041SMark Brown dev_err(dev, "Failed to set supply %s\n", 499323c2f041SMark Brown init_data->consumer_supplies[i].supply); 4994d4033b54SJani Nikula goto unset_supplies; 4995a5766f11SLiam Girdwood } 499623c2f041SMark Brown } 4997a2151374SJon Hunter mutex_unlock(®ulator_list_mutex); 49989a8f5e07SMark Brown } 4999a5766f11SLiam Girdwood 5000fd086045SMatthias Kaehlcke if (!rdev->desc->ops->get_voltage && 5001fd086045SMatthias Kaehlcke !rdev->desc->ops->list_voltage && 5002fd086045SMatthias Kaehlcke !rdev->desc->fixed_uV) 5003fd086045SMatthias Kaehlcke rdev->is_switch = true; 5004fd086045SMatthias Kaehlcke 5005fb6de923SYu Zhao dev_set_drvdata(&rdev->dev, rdev); 5006c438b9d0SJon Hunter ret = device_register(&rdev->dev); 5007c438b9d0SJon Hunter if (ret != 0) { 5008c438b9d0SJon Hunter put_device(&rdev->dev); 5009c438b9d0SJon Hunter goto unset_supplies; 5010c438b9d0SJon Hunter } 5011c438b9d0SJon Hunter 50121130e5b3SMark Brown rdev_init_debugfs(rdev); 50135e3ca2b3SJavier Martinez Canillas 5014f9503385SDmitry Osipenko /* try to resolve regulators coupling since a new one was registered */ 5015f9503385SDmitry Osipenko mutex_lock(®ulator_list_mutex); 5016f9503385SDmitry Osipenko regulator_resolve_coupling(rdev); 5017f9503385SDmitry Osipenko mutex_unlock(®ulator_list_mutex); 5018f9503385SDmitry Osipenko 50195e3ca2b3SJavier Martinez Canillas /* try to resolve regulators supply since a new one was registered */ 50205e3ca2b3SJavier Martinez Canillas class_for_each_device(®ulator_class, NULL, NULL, 50215e3ca2b3SJavier Martinez Canillas regulator_register_resolve_supply); 50221b3de223SKrzysztof Kozlowski kfree(config); 5023414c70cbSLiam Girdwood return rdev; 50244fca9545SDavid Brownell 5025d4033b54SJani Nikula unset_supplies: 502645389c47SJon Hunter mutex_lock(®ulator_list_mutex); 5027d4033b54SJani Nikula unset_regulator_supplies(rdev); 502845389c47SJon Hunter mutex_unlock(®ulator_list_mutex); 502932165230SKrzysztof Adamski wash: 5030469b640eSBoris Brezillon kfree(rdev->constraints); 503145389c47SJon Hunter mutex_lock(®ulator_list_mutex); 503232165230SKrzysztof Adamski regulator_ena_gpio_free(rdev); 503345389c47SJon Hunter mutex_unlock(®ulator_list_mutex); 50344fca9545SDavid Brownell clean: 50350edb040dSLinus Walleij if (dangling_of_gpiod) 50360edb040dSLinus Walleij gpiod_put(config->ena_gpiod); 50374fca9545SDavid Brownell kfree(rdev); 5038a2151374SJon Hunter kfree(config); 50390edb040dSLinus Walleij rinse: 50400edb040dSLinus Walleij if (dangling_cfg_gpiod) 50410edb040dSLinus Walleij gpiod_put(cfg->ena_gpiod); 5042a2151374SJon Hunter return ERR_PTR(ret); 5043414c70cbSLiam Girdwood } 5044414c70cbSLiam Girdwood EXPORT_SYMBOL_GPL(regulator_register); 5045414c70cbSLiam Girdwood 5046414c70cbSLiam Girdwood /** 5047414c70cbSLiam Girdwood * regulator_unregister - unregister regulator 504869279fb9SMark Brown * @rdev: regulator to unregister 5049414c70cbSLiam Girdwood * 5050414c70cbSLiam Girdwood * Called by regulator drivers to unregister a regulator. 5051414c70cbSLiam Girdwood */ 5052414c70cbSLiam Girdwood void regulator_unregister(struct regulator_dev *rdev) 5053414c70cbSLiam Girdwood { 5054414c70cbSLiam Girdwood if (rdev == NULL) 5055414c70cbSLiam Girdwood return; 5056414c70cbSLiam Girdwood 5057891636eaSMark Brown if (rdev->supply) { 5058891636eaSMark Brown while (rdev->use_count--) 5059891636eaSMark Brown regulator_disable(rdev->supply); 5060e032b376SMark Brown regulator_put(rdev->supply); 5061891636eaSMark Brown } 5062ff9b34b6SDmitry Osipenko 506306377301SCharles Keepax flush_work(&rdev->disable_work.work); 506406377301SCharles Keepax 5065414c70cbSLiam Girdwood mutex_lock(®ulator_list_mutex); 5066ff9b34b6SDmitry Osipenko 50671130e5b3SMark Brown debugfs_remove_recursive(rdev->debugfs); 50686bf87d17SMark Brown WARN_ON(rdev->open_count); 50696303f3e7SDmitry Osipenko regulator_remove_coupling(rdev); 50700f1d747bSMike Rapoport unset_regulator_supplies(rdev); 5071414c70cbSLiam Girdwood list_del(&rdev->list); 5072f19b00daSKim, Milo regulator_ena_gpio_free(rdev); 507358fb5cf5SLothar Waßmann device_unregister(&rdev->dev); 5074ff9b34b6SDmitry Osipenko 5075ff9b34b6SDmitry Osipenko mutex_unlock(®ulator_list_mutex); 5076414c70cbSLiam Girdwood } 5077414c70cbSLiam Girdwood EXPORT_SYMBOL_GPL(regulator_unregister); 5078414c70cbSLiam Girdwood 5079f7efad10SChunyan Zhang #ifdef CONFIG_SUSPEND 5080414c70cbSLiam Girdwood /** 50810380cf7dSpascal paillet * regulator_suspend - prepare regulators for system wide suspend 50821efef7ccSRandy Dunlap * @dev: ``&struct device`` pointer that is passed to _regulator_suspend() 5083414c70cbSLiam Girdwood * 5084414c70cbSLiam Girdwood * Configure each regulator with it's suspend operating parameters for state. 5085414c70cbSLiam Girdwood */ 50860380cf7dSpascal paillet static int regulator_suspend(struct device *dev) 5087414c70cbSLiam Girdwood { 5088cd7e36abSMarek Szyprowski struct regulator_dev *rdev = dev_to_rdev(dev); 5089f7efad10SChunyan Zhang suspend_state_t state = pm_suspend_target_state; 5090cd7e36abSMarek Szyprowski int ret; 5091414c70cbSLiam Girdwood 5092cd7e36abSMarek Szyprowski regulator_lock(rdev); 5093cd7e36abSMarek Szyprowski ret = suspend_set_state(rdev, state); 5094cd7e36abSMarek Szyprowski regulator_unlock(rdev); 5095cd7e36abSMarek Szyprowski 5096cd7e36abSMarek Szyprowski return ret; 5097414c70cbSLiam Girdwood } 5098d3e4eccbSMark Brown 5099cd7e36abSMarek Szyprowski static int regulator_resume(struct device *dev) 510085f3b431STomeu Vizoso { 5101cd7e36abSMarek Szyprowski suspend_state_t state = pm_suspend_target_state; 510285f3b431STomeu Vizoso struct regulator_dev *rdev = dev_to_rdev(dev); 5103f7efad10SChunyan Zhang struct regulator_state *rstate; 5104cd7e36abSMarek Szyprowski int ret = 0; 5105f7efad10SChunyan Zhang 5106cd7e36abSMarek Szyprowski rstate = regulator_get_suspend_state(rdev, state); 5107f7efad10SChunyan Zhang if (rstate == NULL) 510835b5f14eSGeert Uytterhoeven return 0; 510985f3b431STomeu Vizoso 511066cf9a7eSMaciej Purski regulator_lock(rdev); 511185f3b431STomeu Vizoso 51120380cf7dSpascal paillet if (rdev->desc->ops->resume && 5113f7efad10SChunyan Zhang (rstate->enabled == ENABLE_IN_SUSPEND || 5114f7efad10SChunyan Zhang rstate->enabled == DISABLE_IN_SUSPEND)) 51150380cf7dSpascal paillet ret = rdev->desc->ops->resume(rdev); 5116f7efad10SChunyan Zhang 511766cf9a7eSMaciej Purski regulator_unlock(rdev); 511885f3b431STomeu Vizoso 5119f7efad10SChunyan Zhang return ret; 512085f3b431STomeu Vizoso } 5121f7efad10SChunyan Zhang #else /* !CONFIG_SUSPEND */ 5122f7efad10SChunyan Zhang 51230380cf7dSpascal paillet #define regulator_suspend NULL 51240380cf7dSpascal paillet #define regulator_resume NULL 5125f7efad10SChunyan Zhang 5126f7efad10SChunyan Zhang #endif /* !CONFIG_SUSPEND */ 5127f7efad10SChunyan Zhang 5128f7efad10SChunyan Zhang #ifdef CONFIG_PM 5129f7efad10SChunyan Zhang static const struct dev_pm_ops __maybe_unused regulator_pm_ops = { 51300380cf7dSpascal paillet .suspend = regulator_suspend, 51310380cf7dSpascal paillet .resume = regulator_resume, 5132f7efad10SChunyan Zhang }; 5133f7efad10SChunyan Zhang #endif 5134f7efad10SChunyan Zhang 5135285c22deSMark Brown struct class regulator_class = { 5136f7efad10SChunyan Zhang .name = "regulator", 5137f7efad10SChunyan Zhang .dev_release = regulator_dev_release, 5138f7efad10SChunyan Zhang .dev_groups = regulator_dev_groups, 5139f7efad10SChunyan Zhang #ifdef CONFIG_PM 5140f7efad10SChunyan Zhang .pm = ®ulator_pm_ops, 5141f7efad10SChunyan Zhang #endif 5142f7efad10SChunyan Zhang }; 51437a32b589SMyungJoo Ham /** 5144ca725561SMark Brown * regulator_has_full_constraints - the system has fully specified constraints 5145ca725561SMark Brown * 5146ca725561SMark Brown * Calling this function will cause the regulator API to disable all 5147ca725561SMark Brown * regulators which have a zero use count and don't have an always_on 5148ca725561SMark Brown * constraint in a late_initcall. 5149ca725561SMark Brown * 5150ca725561SMark Brown * The intention is that this will become the default behaviour in a 5151ca725561SMark Brown * future kernel release so users are encouraged to use this facility 5152ca725561SMark Brown * now. 5153ca725561SMark Brown */ 5154ca725561SMark Brown void regulator_has_full_constraints(void) 5155ca725561SMark Brown { 5156ca725561SMark Brown has_full_constraints = 1; 5157ca725561SMark Brown } 5158ca725561SMark Brown EXPORT_SYMBOL_GPL(regulator_has_full_constraints); 5159ca725561SMark Brown 5160ca725561SMark Brown /** 5161414c70cbSLiam Girdwood * rdev_get_drvdata - get rdev regulator driver data 516269279fb9SMark Brown * @rdev: regulator 5163414c70cbSLiam Girdwood * 5164414c70cbSLiam Girdwood * Get rdev regulator driver private data. This call can be used in the 5165414c70cbSLiam Girdwood * regulator driver context. 5166414c70cbSLiam Girdwood */ 5167414c70cbSLiam Girdwood void *rdev_get_drvdata(struct regulator_dev *rdev) 5168414c70cbSLiam Girdwood { 5169414c70cbSLiam Girdwood return rdev->reg_data; 5170414c70cbSLiam Girdwood } 5171414c70cbSLiam Girdwood EXPORT_SYMBOL_GPL(rdev_get_drvdata); 5172414c70cbSLiam Girdwood 5173414c70cbSLiam Girdwood /** 5174414c70cbSLiam Girdwood * regulator_get_drvdata - get regulator driver data 5175414c70cbSLiam Girdwood * @regulator: regulator 5176414c70cbSLiam Girdwood * 5177414c70cbSLiam Girdwood * Get regulator driver private data. This call can be used in the consumer 5178414c70cbSLiam Girdwood * driver context when non API regulator specific functions need to be called. 5179414c70cbSLiam Girdwood */ 5180414c70cbSLiam Girdwood void *regulator_get_drvdata(struct regulator *regulator) 5181414c70cbSLiam Girdwood { 5182414c70cbSLiam Girdwood return regulator->rdev->reg_data; 5183414c70cbSLiam Girdwood } 5184414c70cbSLiam Girdwood EXPORT_SYMBOL_GPL(regulator_get_drvdata); 5185414c70cbSLiam Girdwood 5186414c70cbSLiam Girdwood /** 5187414c70cbSLiam Girdwood * regulator_set_drvdata - set regulator driver data 5188414c70cbSLiam Girdwood * @regulator: regulator 5189414c70cbSLiam Girdwood * @data: data 5190414c70cbSLiam Girdwood */ 5191414c70cbSLiam Girdwood void regulator_set_drvdata(struct regulator *regulator, void *data) 5192414c70cbSLiam Girdwood { 5193414c70cbSLiam Girdwood regulator->rdev->reg_data = data; 5194414c70cbSLiam Girdwood } 5195414c70cbSLiam Girdwood EXPORT_SYMBOL_GPL(regulator_set_drvdata); 5196414c70cbSLiam Girdwood 5197414c70cbSLiam Girdwood /** 5198414c70cbSLiam Girdwood * regulator_get_id - get regulator ID 519969279fb9SMark Brown * @rdev: regulator 5200414c70cbSLiam Girdwood */ 5201414c70cbSLiam Girdwood int rdev_get_id(struct regulator_dev *rdev) 5202414c70cbSLiam Girdwood { 5203414c70cbSLiam Girdwood return rdev->desc->id; 5204414c70cbSLiam Girdwood } 5205414c70cbSLiam Girdwood EXPORT_SYMBOL_GPL(rdev_get_id); 5206414c70cbSLiam Girdwood 5207a5766f11SLiam Girdwood struct device *rdev_get_dev(struct regulator_dev *rdev) 5208a5766f11SLiam Girdwood { 5209a5766f11SLiam Girdwood return &rdev->dev; 5210a5766f11SLiam Girdwood } 5211a5766f11SLiam Girdwood EXPORT_SYMBOL_GPL(rdev_get_dev); 5212a5766f11SLiam Girdwood 521303c87b95SBartosz Golaszewski struct regmap *rdev_get_regmap(struct regulator_dev *rdev) 521403c87b95SBartosz Golaszewski { 521503c87b95SBartosz Golaszewski return rdev->regmap; 521603c87b95SBartosz Golaszewski } 521703c87b95SBartosz Golaszewski EXPORT_SYMBOL_GPL(rdev_get_regmap); 521803c87b95SBartosz Golaszewski 5219a5766f11SLiam Girdwood void *regulator_get_init_drvdata(struct regulator_init_data *reg_init_data) 5220a5766f11SLiam Girdwood { 5221a5766f11SLiam Girdwood return reg_init_data->driver_data; 5222a5766f11SLiam Girdwood } 5223a5766f11SLiam Girdwood EXPORT_SYMBOL_GPL(regulator_get_init_drvdata); 5224a5766f11SLiam Girdwood 5225ba55a974SMark Brown #ifdef CONFIG_DEBUG_FS 5226dbc55955SHaishan Zhou static int supply_map_show(struct seq_file *sf, void *data) 5227ba55a974SMark Brown { 5228ba55a974SMark Brown struct regulator_map *map; 5229ba55a974SMark Brown 5230ba55a974SMark Brown list_for_each_entry(map, ®ulator_map_list, list) { 5231dbc55955SHaishan Zhou seq_printf(sf, "%s -> %s.%s\n", 5232ba55a974SMark Brown rdev_get_name(map->regulator), map->dev_name, 5233ba55a974SMark Brown map->supply); 5234ba55a974SMark Brown } 5235ba55a974SMark Brown 5236dbc55955SHaishan Zhou return 0; 5237dbc55955SHaishan Zhou } 52383e60b4fcSYangtao Li DEFINE_SHOW_ATTRIBUTE(supply_map); 5239ba55a974SMark Brown 524085f3b431STomeu Vizoso struct summary_data { 524185f3b431STomeu Vizoso struct seq_file *s; 524285f3b431STomeu Vizoso struct regulator_dev *parent; 524385f3b431STomeu Vizoso int level; 524485f3b431STomeu Vizoso }; 524585f3b431STomeu Vizoso 524685f3b431STomeu Vizoso static void regulator_summary_show_subtree(struct seq_file *s, 524785f3b431STomeu Vizoso struct regulator_dev *rdev, 524885f3b431STomeu Vizoso int level); 524985f3b431STomeu Vizoso 525085f3b431STomeu Vizoso static int regulator_summary_show_children(struct device *dev, void *data) 525185f3b431STomeu Vizoso { 525285f3b431STomeu Vizoso struct regulator_dev *rdev = dev_to_rdev(dev); 525385f3b431STomeu Vizoso struct summary_data *summary_data = data; 525485f3b431STomeu Vizoso 525585f3b431STomeu Vizoso if (rdev->supply && rdev->supply->rdev == summary_data->parent) 525685f3b431STomeu Vizoso regulator_summary_show_subtree(summary_data->s, rdev, 525785f3b431STomeu Vizoso summary_data->level + 1); 525885f3b431STomeu Vizoso 525985f3b431STomeu Vizoso return 0; 526085f3b431STomeu Vizoso } 526185f3b431STomeu Vizoso 52627c225ec9SHeiko Stübner static void regulator_summary_show_subtree(struct seq_file *s, 52637c225ec9SHeiko Stübner struct regulator_dev *rdev, 52647c225ec9SHeiko Stübner int level) 52657c225ec9SHeiko Stübner { 52667c225ec9SHeiko Stübner struct regulation_constraints *c; 52677c225ec9SHeiko Stübner struct regulator *consumer; 526885f3b431STomeu Vizoso struct summary_data summary_data; 52697e4d9683SDouglas Anderson unsigned int opmode; 52707c225ec9SHeiko Stübner 52717c225ec9SHeiko Stübner if (!rdev) 52727c225ec9SHeiko Stübner return; 52737c225ec9SHeiko Stübner 52747e4d9683SDouglas Anderson opmode = _regulator_get_mode_unlocked(rdev); 527501de19d0SDouglas Anderson seq_printf(s, "%*s%-*s %3d %4d %6d %7s ", 52767c225ec9SHeiko Stübner level * 3 + 1, "", 52777c225ec9SHeiko Stübner 30 - level * 3, rdev_get_name(rdev), 527801de19d0SDouglas Anderson rdev->use_count, rdev->open_count, rdev->bypass_count, 52797e4d9683SDouglas Anderson regulator_opmode_to_str(opmode)); 52807c225ec9SHeiko Stübner 528123296099SHeiko Stübner seq_printf(s, "%5dmV ", _regulator_get_voltage(rdev) / 1000); 52827e4d9683SDouglas Anderson seq_printf(s, "%5dmA ", 52837e4d9683SDouglas Anderson _regulator_get_current_limit_unlocked(rdev) / 1000); 52847c225ec9SHeiko Stübner 52857c225ec9SHeiko Stübner c = rdev->constraints; 52867c225ec9SHeiko Stübner if (c) { 52877c225ec9SHeiko Stübner switch (rdev->desc->type) { 52887c225ec9SHeiko Stübner case REGULATOR_VOLTAGE: 52897c225ec9SHeiko Stübner seq_printf(s, "%5dmV %5dmV ", 52907c225ec9SHeiko Stübner c->min_uV / 1000, c->max_uV / 1000); 52917c225ec9SHeiko Stübner break; 52927c225ec9SHeiko Stübner case REGULATOR_CURRENT: 52937c225ec9SHeiko Stübner seq_printf(s, "%5dmA %5dmA ", 52947c225ec9SHeiko Stübner c->min_uA / 1000, c->max_uA / 1000); 52957c225ec9SHeiko Stübner break; 52967c225ec9SHeiko Stübner } 52977c225ec9SHeiko Stübner } 52987c225ec9SHeiko Stübner 52997c225ec9SHeiko Stübner seq_puts(s, "\n"); 53007c225ec9SHeiko Stübner 53017c225ec9SHeiko Stübner list_for_each_entry(consumer, &rdev->consumer_list, list) { 5302e42a46b6SLeonard Crestez if (consumer->dev && consumer->dev->class == ®ulator_class) 53037c225ec9SHeiko Stübner continue; 53047c225ec9SHeiko Stübner 53057c225ec9SHeiko Stübner seq_printf(s, "%*s%-*s ", 53067c225ec9SHeiko Stübner (level + 1) * 3 + 1, "", 5307e42a46b6SLeonard Crestez 30 - (level + 1) * 3, 5308e42a46b6SLeonard Crestez consumer->dev ? dev_name(consumer->dev) : "deviceless"); 53097c225ec9SHeiko Stübner 53107c225ec9SHeiko Stübner switch (rdev->desc->type) { 53117c225ec9SHeiko Stübner case REGULATOR_VOLTAGE: 53125451781dSDouglas Anderson seq_printf(s, "%3d %33dmA%c%5dmV %5dmV", 53135451781dSDouglas Anderson consumer->enable_count, 53147d3827b5SDouglas Anderson consumer->uA_load / 1000, 53155451781dSDouglas Anderson consumer->uA_load && !consumer->enable_count ? 53165451781dSDouglas Anderson '*' : ' ', 5317c360a6dfSChunyan Zhang consumer->voltage[PM_SUSPEND_ON].min_uV / 1000, 5318c360a6dfSChunyan Zhang consumer->voltage[PM_SUSPEND_ON].max_uV / 1000); 53197c225ec9SHeiko Stübner break; 53207c225ec9SHeiko Stübner case REGULATOR_CURRENT: 53217c225ec9SHeiko Stübner break; 53227c225ec9SHeiko Stübner } 53237c225ec9SHeiko Stübner 53247c225ec9SHeiko Stübner seq_puts(s, "\n"); 53257c225ec9SHeiko Stübner } 53267c225ec9SHeiko Stübner 532785f3b431STomeu Vizoso summary_data.s = s; 532885f3b431STomeu Vizoso summary_data.level = level; 532985f3b431STomeu Vizoso summary_data.parent = rdev; 53307c225ec9SHeiko Stübner 533185f3b431STomeu Vizoso class_for_each_device(®ulator_class, NULL, &summary_data, 533285f3b431STomeu Vizoso regulator_summary_show_children); 5333f8702f9eSDmitry Osipenko } 5334f8702f9eSDmitry Osipenko 5335f8702f9eSDmitry Osipenko struct summary_lock_data { 5336f8702f9eSDmitry Osipenko struct ww_acquire_ctx *ww_ctx; 5337f8702f9eSDmitry Osipenko struct regulator_dev **new_contended_rdev; 5338f8702f9eSDmitry Osipenko struct regulator_dev **old_contended_rdev; 5339f8702f9eSDmitry Osipenko }; 5340f8702f9eSDmitry Osipenko 5341f8702f9eSDmitry Osipenko static int regulator_summary_lock_one(struct device *dev, void *data) 5342f8702f9eSDmitry Osipenko { 5343f8702f9eSDmitry Osipenko struct regulator_dev *rdev = dev_to_rdev(dev); 5344f8702f9eSDmitry Osipenko struct summary_lock_data *lock_data = data; 5345f8702f9eSDmitry Osipenko int ret = 0; 5346f8702f9eSDmitry Osipenko 5347f8702f9eSDmitry Osipenko if (rdev != *lock_data->old_contended_rdev) { 5348f8702f9eSDmitry Osipenko ret = regulator_lock_nested(rdev, lock_data->ww_ctx); 5349f8702f9eSDmitry Osipenko 5350f8702f9eSDmitry Osipenko if (ret == -EDEADLK) 5351f8702f9eSDmitry Osipenko *lock_data->new_contended_rdev = rdev; 5352f8702f9eSDmitry Osipenko else 5353f8702f9eSDmitry Osipenko WARN_ON_ONCE(ret); 5354f8702f9eSDmitry Osipenko } else { 5355f8702f9eSDmitry Osipenko *lock_data->old_contended_rdev = NULL; 5356f8702f9eSDmitry Osipenko } 5357f8702f9eSDmitry Osipenko 5358f8702f9eSDmitry Osipenko return ret; 5359f8702f9eSDmitry Osipenko } 5360f8702f9eSDmitry Osipenko 5361f8702f9eSDmitry Osipenko static int regulator_summary_unlock_one(struct device *dev, void *data) 5362f8702f9eSDmitry Osipenko { 5363f8702f9eSDmitry Osipenko struct regulator_dev *rdev = dev_to_rdev(dev); 5364f8702f9eSDmitry Osipenko struct summary_lock_data *lock_data = data; 5365f8702f9eSDmitry Osipenko 5366f8702f9eSDmitry Osipenko if (lock_data) { 5367f8702f9eSDmitry Osipenko if (rdev == *lock_data->new_contended_rdev) 5368f8702f9eSDmitry Osipenko return -EDEADLK; 5369f8702f9eSDmitry Osipenko } 53707e4d9683SDouglas Anderson 53717e4d9683SDouglas Anderson regulator_unlock(rdev); 5372f8702f9eSDmitry Osipenko 5373f8702f9eSDmitry Osipenko return 0; 5374f8702f9eSDmitry Osipenko } 5375f8702f9eSDmitry Osipenko 5376f8702f9eSDmitry Osipenko static int regulator_summary_lock_all(struct ww_acquire_ctx *ww_ctx, 5377f8702f9eSDmitry Osipenko struct regulator_dev **new_contended_rdev, 5378f8702f9eSDmitry Osipenko struct regulator_dev **old_contended_rdev) 5379f8702f9eSDmitry Osipenko { 5380f8702f9eSDmitry Osipenko struct summary_lock_data lock_data; 5381f8702f9eSDmitry Osipenko int ret; 5382f8702f9eSDmitry Osipenko 5383f8702f9eSDmitry Osipenko lock_data.ww_ctx = ww_ctx; 5384f8702f9eSDmitry Osipenko lock_data.new_contended_rdev = new_contended_rdev; 5385f8702f9eSDmitry Osipenko lock_data.old_contended_rdev = old_contended_rdev; 5386f8702f9eSDmitry Osipenko 5387f8702f9eSDmitry Osipenko ret = class_for_each_device(®ulator_class, NULL, &lock_data, 5388f8702f9eSDmitry Osipenko regulator_summary_lock_one); 5389f8702f9eSDmitry Osipenko if (ret) 5390f8702f9eSDmitry Osipenko class_for_each_device(®ulator_class, NULL, &lock_data, 5391f8702f9eSDmitry Osipenko regulator_summary_unlock_one); 5392f8702f9eSDmitry Osipenko 5393f8702f9eSDmitry Osipenko return ret; 5394f8702f9eSDmitry Osipenko } 5395f8702f9eSDmitry Osipenko 5396f8702f9eSDmitry Osipenko static void regulator_summary_lock(struct ww_acquire_ctx *ww_ctx) 5397f8702f9eSDmitry Osipenko { 5398f8702f9eSDmitry Osipenko struct regulator_dev *new_contended_rdev = NULL; 5399f8702f9eSDmitry Osipenko struct regulator_dev *old_contended_rdev = NULL; 5400f8702f9eSDmitry Osipenko int err; 5401f8702f9eSDmitry Osipenko 5402ff9b34b6SDmitry Osipenko mutex_lock(®ulator_list_mutex); 5403ff9b34b6SDmitry Osipenko 5404f8702f9eSDmitry Osipenko ww_acquire_init(ww_ctx, ®ulator_ww_class); 5405f8702f9eSDmitry Osipenko 5406f8702f9eSDmitry Osipenko do { 5407f8702f9eSDmitry Osipenko if (new_contended_rdev) { 5408f8702f9eSDmitry Osipenko ww_mutex_lock_slow(&new_contended_rdev->mutex, ww_ctx); 5409f8702f9eSDmitry Osipenko old_contended_rdev = new_contended_rdev; 5410f8702f9eSDmitry Osipenko old_contended_rdev->ref_cnt++; 5411f8702f9eSDmitry Osipenko } 5412f8702f9eSDmitry Osipenko 5413f8702f9eSDmitry Osipenko err = regulator_summary_lock_all(ww_ctx, 5414f8702f9eSDmitry Osipenko &new_contended_rdev, 5415f8702f9eSDmitry Osipenko &old_contended_rdev); 5416f8702f9eSDmitry Osipenko 5417f8702f9eSDmitry Osipenko if (old_contended_rdev) 5418f8702f9eSDmitry Osipenko regulator_unlock(old_contended_rdev); 5419f8702f9eSDmitry Osipenko 5420f8702f9eSDmitry Osipenko } while (err == -EDEADLK); 5421f8702f9eSDmitry Osipenko 5422f8702f9eSDmitry Osipenko ww_acquire_done(ww_ctx); 5423f8702f9eSDmitry Osipenko } 5424f8702f9eSDmitry Osipenko 5425f8702f9eSDmitry Osipenko static void regulator_summary_unlock(struct ww_acquire_ctx *ww_ctx) 5426f8702f9eSDmitry Osipenko { 5427f8702f9eSDmitry Osipenko class_for_each_device(®ulator_class, NULL, NULL, 5428f8702f9eSDmitry Osipenko regulator_summary_unlock_one); 5429f8702f9eSDmitry Osipenko ww_acquire_fini(ww_ctx); 5430ff9b34b6SDmitry Osipenko 5431ff9b34b6SDmitry Osipenko mutex_unlock(®ulator_list_mutex); 54327c225ec9SHeiko Stübner } 543385f3b431STomeu Vizoso 543485f3b431STomeu Vizoso static int regulator_summary_show_roots(struct device *dev, void *data) 543585f3b431STomeu Vizoso { 543685f3b431STomeu Vizoso struct regulator_dev *rdev = dev_to_rdev(dev); 543785f3b431STomeu Vizoso struct seq_file *s = data; 543885f3b431STomeu Vizoso 543985f3b431STomeu Vizoso if (!rdev->supply) 544085f3b431STomeu Vizoso regulator_summary_show_subtree(s, rdev, 0); 544185f3b431STomeu Vizoso 544285f3b431STomeu Vizoso return 0; 54437c225ec9SHeiko Stübner } 54447c225ec9SHeiko Stübner 54457c225ec9SHeiko Stübner static int regulator_summary_show(struct seq_file *s, void *data) 54467c225ec9SHeiko Stübner { 5447f8702f9eSDmitry Osipenko struct ww_acquire_ctx ww_ctx; 5448f8702f9eSDmitry Osipenko 544901de19d0SDouglas Anderson seq_puts(s, " regulator use open bypass opmode voltage current min max\n"); 545001de19d0SDouglas Anderson seq_puts(s, "---------------------------------------------------------------------------------------\n"); 54517c225ec9SHeiko Stübner 5452f8702f9eSDmitry Osipenko regulator_summary_lock(&ww_ctx); 5453f8702f9eSDmitry Osipenko 545485f3b431STomeu Vizoso class_for_each_device(®ulator_class, NULL, s, 545585f3b431STomeu Vizoso regulator_summary_show_roots); 54567c225ec9SHeiko Stübner 5457f8702f9eSDmitry Osipenko regulator_summary_unlock(&ww_ctx); 5458f8702f9eSDmitry Osipenko 54597c225ec9SHeiko Stübner return 0; 54607c225ec9SHeiko Stübner } 54613e60b4fcSYangtao Li DEFINE_SHOW_ATTRIBUTE(regulator_summary); 54623e60b4fcSYangtao Li #endif /* CONFIG_DEBUG_FS */ 54637c225ec9SHeiko Stübner 5464414c70cbSLiam Girdwood static int __init regulator_init(void) 5465414c70cbSLiam Girdwood { 546634abbd68SMark Brown int ret; 546734abbd68SMark Brown 546834abbd68SMark Brown ret = class_register(®ulator_class); 546934abbd68SMark Brown 54701130e5b3SMark Brown debugfs_root = debugfs_create_dir("regulator", NULL); 547124751434SStephen Boyd if (!debugfs_root) 54721130e5b3SMark Brown pr_warn("regulator: Failed to create debugfs directory\n"); 5473ba55a974SMark Brown 54743e60b4fcSYangtao Li #ifdef CONFIG_DEBUG_FS 5475f4d562c6SMark Brown debugfs_create_file("supply_map", 0444, debugfs_root, NULL, 5476f4d562c6SMark Brown &supply_map_fops); 54771130e5b3SMark Brown 54787c225ec9SHeiko Stübner debugfs_create_file("regulator_summary", 0444, debugfs_root, 547985f3b431STomeu Vizoso NULL, ®ulator_summary_fops); 54803e60b4fcSYangtao Li #endif 548134abbd68SMark Brown regulator_dummy_init(); 548234abbd68SMark Brown 548334abbd68SMark Brown return ret; 5484414c70cbSLiam Girdwood } 5485414c70cbSLiam Girdwood 5486414c70cbSLiam Girdwood /* init early to allow our consumers to complete system booting */ 5487414c70cbSLiam Girdwood core_initcall(regulator_init); 5488ca725561SMark Brown 5489609ca5f3SMark Brown static int __init regulator_late_cleanup(struct device *dev, void *data) 5490ca725561SMark Brown { 5491609ca5f3SMark Brown struct regulator_dev *rdev = dev_to_rdev(dev); 5492609ca5f3SMark Brown const struct regulator_ops *ops = rdev->desc->ops; 5493609ca5f3SMark Brown struct regulation_constraints *c = rdev->constraints; 5494ca725561SMark Brown int enabled, ret; 5495ca725561SMark Brown 549666fda75fSMarkus Pargmann if (c && c->always_on) 5497609ca5f3SMark Brown return 0; 5498ca725561SMark Brown 54998a34e979SWEN Pingbo if (!regulator_ops_is_valid(rdev, REGULATOR_CHANGE_STATUS)) 5500609ca5f3SMark Brown return 0; 5501e9535834SMark Brown 550266cf9a7eSMaciej Purski regulator_lock(rdev); 5503ca725561SMark Brown 5504ca725561SMark Brown if (rdev->use_count) 5505ca725561SMark Brown goto unlock; 5506ca725561SMark Brown 5507ca725561SMark Brown /* If we can't read the status assume it's on. */ 5508ca725561SMark Brown if (ops->is_enabled) 5509ca725561SMark Brown enabled = ops->is_enabled(rdev); 5510ca725561SMark Brown else 5511ca725561SMark Brown enabled = 1; 5512ca725561SMark Brown 5513ca725561SMark Brown if (!enabled) 5514ca725561SMark Brown goto unlock; 5515ca725561SMark Brown 551687b28417SMark Brown if (have_full_constraints()) { 5517609ca5f3SMark Brown /* We log since this may kill the system if it goes 5518609ca5f3SMark Brown * wrong. */ 55195da84fd9SJoe Perches rdev_info(rdev, "disabling\n"); 552066fda75fSMarkus Pargmann ret = _regulator_do_disable(rdev); 55210d25d09dSJingoo Han if (ret != 0) 55225da84fd9SJoe Perches rdev_err(rdev, "couldn't disable: %d\n", ret); 5523ca725561SMark Brown } else { 5524ca725561SMark Brown /* The intention is that in future we will 5525ca725561SMark Brown * assume that full constraints are provided 5526ca725561SMark Brown * so warn even if we aren't going to do 5527ca725561SMark Brown * anything here. 5528ca725561SMark Brown */ 55295da84fd9SJoe Perches rdev_warn(rdev, "incomplete constraints, leaving on\n"); 5530ca725561SMark Brown } 5531ca725561SMark Brown 5532ca725561SMark Brown unlock: 553366cf9a7eSMaciej Purski regulator_unlock(rdev); 5534609ca5f3SMark Brown 5535609ca5f3SMark Brown return 0; 5536ca725561SMark Brown } 5537ca725561SMark Brown 5538609ca5f3SMark Brown static int __init regulator_init_complete(void) 5539609ca5f3SMark Brown { 5540609ca5f3SMark Brown /* 5541609ca5f3SMark Brown * Since DT doesn't provide an idiomatic mechanism for 5542609ca5f3SMark Brown * enabling full constraints and since it's much more natural 5543609ca5f3SMark Brown * with DT to provide them just assume that a DT enabled 5544609ca5f3SMark Brown * system has full constraints. 5545609ca5f3SMark Brown */ 5546609ca5f3SMark Brown if (of_have_populated_dt()) 5547609ca5f3SMark Brown has_full_constraints = true; 5548609ca5f3SMark Brown 55493827b64dSJavier Martinez Canillas /* 55503827b64dSJavier Martinez Canillas * Regulators may had failed to resolve their input supplies 55513827b64dSJavier Martinez Canillas * when were registered, either because the input supply was 55523827b64dSJavier Martinez Canillas * not registered yet or because its parent device was not 55533827b64dSJavier Martinez Canillas * bound yet. So attempt to resolve the input supplies for 55543827b64dSJavier Martinez Canillas * pending regulators before trying to disable unused ones. 55553827b64dSJavier Martinez Canillas */ 55563827b64dSJavier Martinez Canillas class_for_each_device(®ulator_class, NULL, NULL, 55573827b64dSJavier Martinez Canillas regulator_register_resolve_supply); 55583827b64dSJavier Martinez Canillas 5559609ca5f3SMark Brown /* If we have a full configuration then disable any regulators 5560609ca5f3SMark Brown * we have permission to change the status for and which are 5561609ca5f3SMark Brown * not in use or always_on. This is effectively the default 5562609ca5f3SMark Brown * for DT and ACPI as they have full constraints. 5563609ca5f3SMark Brown */ 5564609ca5f3SMark Brown class_for_each_device(®ulator_class, NULL, NULL, 5565609ca5f3SMark Brown regulator_late_cleanup); 5566ca725561SMark Brown 5567ca725561SMark Brown return 0; 5568ca725561SMark Brown } 5569fd482a3eSSaravana Kannan late_initcall_sync(regulator_init_complete); 5570