1414c70cbSLiam Girdwood /* 2414c70cbSLiam Girdwood * core.c -- Voltage/Current Regulator framework. 3414c70cbSLiam Girdwood * 4414c70cbSLiam Girdwood * Copyright 2007, 2008 Wolfson Microelectronics PLC. 5a5766f11SLiam Girdwood * Copyright 2008 SlimLogic Ltd. 6414c70cbSLiam Girdwood * 7a5766f11SLiam Girdwood * Author: Liam Girdwood <lrg@slimlogic.co.uk> 8414c70cbSLiam Girdwood * 9414c70cbSLiam Girdwood * This program is free software; you can redistribute it and/or modify it 10414c70cbSLiam Girdwood * under the terms of the GNU General Public License as published by the 11414c70cbSLiam Girdwood * Free Software Foundation; either version 2 of the License, or (at your 12414c70cbSLiam Girdwood * option) any later version. 13414c70cbSLiam Girdwood * 14414c70cbSLiam Girdwood */ 15414c70cbSLiam Girdwood 16414c70cbSLiam Girdwood #include <linux/kernel.h> 17414c70cbSLiam Girdwood #include <linux/init.h> 181130e5b3SMark Brown #include <linux/debugfs.h> 19414c70cbSLiam Girdwood #include <linux/device.h> 205a0e3ad6STejun Heo #include <linux/slab.h> 21f21e0e81SMark Brown #include <linux/async.h> 22414c70cbSLiam Girdwood #include <linux/err.h> 23414c70cbSLiam Girdwood #include <linux/mutex.h> 24414c70cbSLiam Girdwood #include <linux/suspend.h> 2531aae2beSMark Brown #include <linux/delay.h> 2665f73508SMark Brown #include <linux/gpio.h> 27778b28b4SRussell King #include <linux/gpio/consumer.h> 2869511a45SRajendra Nayak #include <linux/of.h> 2965b19ce6SMark Brown #include <linux/regmap.h> 3069511a45SRajendra Nayak #include <linux/regulator/of_regulator.h> 31414c70cbSLiam Girdwood #include <linux/regulator/consumer.h> 32414c70cbSLiam Girdwood #include <linux/regulator/driver.h> 33414c70cbSLiam Girdwood #include <linux/regulator/machine.h> 3465602c32SPaul Gortmaker #include <linux/module.h> 35414c70cbSLiam Girdwood 3602fa3ec0SMark Brown #define CREATE_TRACE_POINTS 3702fa3ec0SMark Brown #include <trace/events/regulator.h> 3802fa3ec0SMark Brown 3934abbd68SMark Brown #include "dummy.h" 400cdfcc0fSMark Brown #include "internal.h" 4134abbd68SMark Brown 427d51a0dbSMark Brown #define rdev_crit(rdev, fmt, ...) \ 437d51a0dbSMark Brown pr_crit("%s: " fmt, rdev_get_name(rdev), ##__VA_ARGS__) 445da84fd9SJoe Perches #define rdev_err(rdev, fmt, ...) \ 455da84fd9SJoe Perches pr_err("%s: " fmt, rdev_get_name(rdev), ##__VA_ARGS__) 465da84fd9SJoe Perches #define rdev_warn(rdev, fmt, ...) \ 475da84fd9SJoe Perches pr_warn("%s: " fmt, rdev_get_name(rdev), ##__VA_ARGS__) 485da84fd9SJoe Perches #define rdev_info(rdev, fmt, ...) \ 495da84fd9SJoe Perches pr_info("%s: " fmt, rdev_get_name(rdev), ##__VA_ARGS__) 505da84fd9SJoe Perches #define rdev_dbg(rdev, fmt, ...) \ 515da84fd9SJoe Perches pr_debug("%s: " fmt, rdev_get_name(rdev), ##__VA_ARGS__) 525da84fd9SJoe Perches 53414c70cbSLiam Girdwood static DEFINE_MUTEX(regulator_list_mutex); 54414c70cbSLiam Girdwood static LIST_HEAD(regulator_map_list); 55f19b00daSKim, Milo static LIST_HEAD(regulator_ena_gpio_list); 56a06ccd9cSCharles Keepax static LIST_HEAD(regulator_supply_alias_list); 5721cf891aSMark Brown static bool has_full_constraints; 58414c70cbSLiam Girdwood 591130e5b3SMark Brown static struct dentry *debugfs_root; 601130e5b3SMark Brown 618dc5390dSMark Brown /* 62414c70cbSLiam Girdwood * struct regulator_map 63414c70cbSLiam Girdwood * 64414c70cbSLiam Girdwood * Used to provide symbolic supply names to devices. 65414c70cbSLiam Girdwood */ 66414c70cbSLiam Girdwood struct regulator_map { 67414c70cbSLiam Girdwood struct list_head list; 6840f9244fSMark Brown const char *dev_name; /* The dev_name() for the consumer */ 69414c70cbSLiam Girdwood const char *supply; 70a5766f11SLiam Girdwood struct regulator_dev *regulator; 71414c70cbSLiam Girdwood }; 72414c70cbSLiam Girdwood 73414c70cbSLiam Girdwood /* 74f19b00daSKim, Milo * struct regulator_enable_gpio 75f19b00daSKim, Milo * 76f19b00daSKim, Milo * Management for shared enable GPIO pin 77f19b00daSKim, Milo */ 78f19b00daSKim, Milo struct regulator_enable_gpio { 79f19b00daSKim, Milo struct list_head list; 80778b28b4SRussell King struct gpio_desc *gpiod; 81f19b00daSKim, Milo u32 enable_count; /* a number of enabled shared GPIO */ 82f19b00daSKim, Milo u32 request_count; /* a number of requested shared GPIO */ 83f19b00daSKim, Milo unsigned int ena_gpio_invert:1; 84f19b00daSKim, Milo }; 85f19b00daSKim, Milo 86a06ccd9cSCharles Keepax /* 87a06ccd9cSCharles Keepax * struct regulator_supply_alias 88a06ccd9cSCharles Keepax * 89a06ccd9cSCharles Keepax * Used to map lookups for a supply onto an alternative device. 90a06ccd9cSCharles Keepax */ 91a06ccd9cSCharles Keepax struct regulator_supply_alias { 92a06ccd9cSCharles Keepax struct list_head list; 93a06ccd9cSCharles Keepax struct device *src_dev; 94a06ccd9cSCharles Keepax const char *src_supply; 95a06ccd9cSCharles Keepax struct device *alias_dev; 96a06ccd9cSCharles Keepax const char *alias_supply; 97a06ccd9cSCharles Keepax }; 98a06ccd9cSCharles Keepax 99414c70cbSLiam Girdwood static int _regulator_is_enabled(struct regulator_dev *rdev); 1003801b86aSMark Brown static int _regulator_disable(struct regulator_dev *rdev); 101414c70cbSLiam Girdwood static int _regulator_get_voltage(struct regulator_dev *rdev); 102414c70cbSLiam Girdwood static int _regulator_get_current_limit(struct regulator_dev *rdev); 103414c70cbSLiam Girdwood static unsigned int _regulator_get_mode(struct regulator_dev *rdev); 1047179569aSHeiko Stübner static int _notifier_call_chain(struct regulator_dev *rdev, 105414c70cbSLiam Girdwood unsigned long event, void *data); 10675790251SMark Brown static int _regulator_do_set_voltage(struct regulator_dev *rdev, 10775790251SMark Brown int min_uV, int max_uV); 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 14170a7fb80SThierry Reding static inline struct regulator_dev *rdev_get_supply(struct regulator_dev *rdev) 14270a7fb80SThierry Reding { 14370a7fb80SThierry Reding if (rdev && rdev->supply) 14470a7fb80SThierry Reding return rdev->supply->rdev; 14570a7fb80SThierry Reding 14670a7fb80SThierry Reding return NULL; 14770a7fb80SThierry Reding } 14870a7fb80SThierry Reding 14969511a45SRajendra Nayak /** 15066cf9a7eSMaciej Purski * regulator_lock_nested - lock a single regulator 15166cf9a7eSMaciej Purski * @rdev: regulator source 15266cf9a7eSMaciej Purski * @subclass: mutex subclass used for lockdep 15366cf9a7eSMaciej Purski * 15466cf9a7eSMaciej Purski * This function can be called many times by one task on 15566cf9a7eSMaciej Purski * a single regulator and its mutex will be locked only 15666cf9a7eSMaciej Purski * once. If a task, which is calling this function is other 15766cf9a7eSMaciej Purski * than the one, which initially locked the mutex, it will 15866cf9a7eSMaciej Purski * wait on mutex. 15966cf9a7eSMaciej Purski */ 16066cf9a7eSMaciej Purski static void regulator_lock_nested(struct regulator_dev *rdev, 16166cf9a7eSMaciej Purski unsigned int subclass) 16266cf9a7eSMaciej Purski { 16366cf9a7eSMaciej Purski if (!mutex_trylock(&rdev->mutex)) { 16466cf9a7eSMaciej Purski if (rdev->mutex_owner == current) { 16566cf9a7eSMaciej Purski rdev->ref_cnt++; 16666cf9a7eSMaciej Purski return; 16766cf9a7eSMaciej Purski } 16866cf9a7eSMaciej Purski mutex_lock_nested(&rdev->mutex, subclass); 16966cf9a7eSMaciej Purski } 17066cf9a7eSMaciej Purski 17166cf9a7eSMaciej Purski rdev->ref_cnt = 1; 17266cf9a7eSMaciej Purski rdev->mutex_owner = current; 17366cf9a7eSMaciej Purski } 17466cf9a7eSMaciej Purski 17566cf9a7eSMaciej Purski static inline void regulator_lock(struct regulator_dev *rdev) 17666cf9a7eSMaciej Purski { 17766cf9a7eSMaciej Purski regulator_lock_nested(rdev, 0); 17866cf9a7eSMaciej Purski } 17966cf9a7eSMaciej Purski 18066cf9a7eSMaciej Purski /** 18166cf9a7eSMaciej Purski * regulator_unlock - unlock a single regulator 18266cf9a7eSMaciej Purski * @rdev: regulator_source 18366cf9a7eSMaciej Purski * 18466cf9a7eSMaciej Purski * This function unlocks the mutex when the 18566cf9a7eSMaciej Purski * reference counter reaches 0. 18666cf9a7eSMaciej Purski */ 18766cf9a7eSMaciej Purski static void regulator_unlock(struct regulator_dev *rdev) 18866cf9a7eSMaciej Purski { 18966cf9a7eSMaciej Purski if (rdev->ref_cnt != 0) { 19066cf9a7eSMaciej Purski rdev->ref_cnt--; 19166cf9a7eSMaciej Purski 19266cf9a7eSMaciej Purski if (!rdev->ref_cnt) { 19366cf9a7eSMaciej Purski rdev->mutex_owner = NULL; 19466cf9a7eSMaciej Purski mutex_unlock(&rdev->mutex); 19566cf9a7eSMaciej Purski } 19666cf9a7eSMaciej Purski } 19766cf9a7eSMaciej Purski } 19866cf9a7eSMaciej Purski 19938de19faSMark Brown /** 20038de19faSMark Brown * regulator_lock_supply - lock a regulator and its supplies 20138de19faSMark Brown * @rdev: regulator source 20238de19faSMark Brown */ 20338de19faSMark Brown static void regulator_lock_supply(struct regulator_dev *rdev) 2049f01cd4aSSascha Hauer { 205fa731ac7SArnd Bergmann int i; 2069f01cd4aSSascha Hauer 20738de19faSMark Brown for (i = 0; rdev; rdev = rdev_get_supply(rdev), i++) 20838de19faSMark Brown regulator_lock_nested(rdev, i); 2099f01cd4aSSascha Hauer } 2109f01cd4aSSascha Hauer 2119f01cd4aSSascha Hauer /** 21238de19faSMark Brown * regulator_unlock_supply - unlock a regulator and its supplies 2139f01cd4aSSascha Hauer * @rdev: regulator source 2149f01cd4aSSascha Hauer */ 21538de19faSMark Brown static void regulator_unlock_supply(struct regulator_dev *rdev) 2169f01cd4aSSascha Hauer { 21738de19faSMark Brown struct regulator *supply; 2189f01cd4aSSascha Hauer 21938de19faSMark Brown while (1) { 22038de19faSMark Brown regulator_unlock(rdev); 22138de19faSMark Brown supply = rdev->supply; 2229f01cd4aSSascha Hauer 22338de19faSMark Brown if (!rdev->supply) 22438de19faSMark Brown return; 2259f01cd4aSSascha Hauer 22638de19faSMark Brown rdev = supply->rdev; 2279f01cd4aSSascha Hauer } 2289f01cd4aSSascha Hauer } 2299f01cd4aSSascha Hauer 2309f01cd4aSSascha Hauer /** 23169511a45SRajendra Nayak * of_get_regulator - get a regulator device node based on supply name 23269511a45SRajendra Nayak * @dev: Device pointer for the consumer (of regulator) device 23369511a45SRajendra Nayak * @supply: regulator supply name 23469511a45SRajendra Nayak * 23569511a45SRajendra Nayak * Extract the regulator device node corresponding to the supply name. 236167d41dcSMaxime Ripard * returns the device node corresponding to the regulator if found, else 23769511a45SRajendra Nayak * returns NULL. 23869511a45SRajendra Nayak */ 23969511a45SRajendra Nayak static struct device_node *of_get_regulator(struct device *dev, const char *supply) 24069511a45SRajendra Nayak { 24169511a45SRajendra Nayak struct device_node *regnode = NULL; 24269511a45SRajendra Nayak char prop_name[32]; /* 32 is max size of property name */ 24369511a45SRajendra Nayak 24469511a45SRajendra Nayak dev_dbg(dev, "Looking up %s-supply from device tree\n", supply); 24569511a45SRajendra Nayak 24669511a45SRajendra Nayak snprintf(prop_name, 32, "%s-supply", supply); 24769511a45SRajendra Nayak regnode = of_parse_phandle(dev->of_node, prop_name, 0); 24869511a45SRajendra Nayak 24969511a45SRajendra Nayak if (!regnode) { 2507799167bSRob Herring dev_dbg(dev, "Looking up %s property in node %pOF failed\n", 2517799167bSRob Herring prop_name, dev->of_node); 25269511a45SRajendra Nayak return NULL; 25369511a45SRajendra Nayak } 25469511a45SRajendra Nayak return regnode; 25569511a45SRajendra Nayak } 25669511a45SRajendra Nayak 257414c70cbSLiam Girdwood /* Platform voltage constraint check */ 258414c70cbSLiam Girdwood static int regulator_check_voltage(struct regulator_dev *rdev, 259414c70cbSLiam Girdwood int *min_uV, int *max_uV) 260414c70cbSLiam Girdwood { 261414c70cbSLiam Girdwood BUG_ON(*min_uV > *max_uV); 262414c70cbSLiam Girdwood 2638a34e979SWEN Pingbo if (!regulator_ops_is_valid(rdev, REGULATOR_CHANGE_VOLTAGE)) { 2647ebcf26cSStephen Boyd rdev_err(rdev, "voltage operation not allowed\n"); 265414c70cbSLiam Girdwood return -EPERM; 266414c70cbSLiam Girdwood } 267414c70cbSLiam Girdwood 268414c70cbSLiam Girdwood if (*max_uV > rdev->constraints->max_uV) 269414c70cbSLiam Girdwood *max_uV = rdev->constraints->max_uV; 270414c70cbSLiam Girdwood if (*min_uV < rdev->constraints->min_uV) 271414c70cbSLiam Girdwood *min_uV = rdev->constraints->min_uV; 272414c70cbSLiam Girdwood 27389f425edSMark Brown if (*min_uV > *max_uV) { 27489f425edSMark Brown rdev_err(rdev, "unsupportable voltage range: %d-%duV\n", 27554abd335SMark Brown *min_uV, *max_uV); 276414c70cbSLiam Girdwood return -EINVAL; 27789f425edSMark Brown } 278414c70cbSLiam Girdwood 279414c70cbSLiam Girdwood return 0; 280414c70cbSLiam Girdwood } 281414c70cbSLiam Girdwood 282f7efad10SChunyan Zhang /* return 0 if the state is valid */ 283f7efad10SChunyan Zhang static int regulator_check_states(suspend_state_t state) 284f7efad10SChunyan Zhang { 285f7efad10SChunyan Zhang return (state > PM_SUSPEND_MAX || state == PM_SUSPEND_TO_IDLE); 286f7efad10SChunyan Zhang } 287f7efad10SChunyan Zhang 28805fda3b1SThomas Petazzoni /* Make sure we select a voltage that suits the needs of all 28905fda3b1SThomas Petazzoni * regulator consumers 29005fda3b1SThomas Petazzoni */ 29105fda3b1SThomas Petazzoni static int regulator_check_consumers(struct regulator_dev *rdev, 292c360a6dfSChunyan Zhang int *min_uV, int *max_uV, 293c360a6dfSChunyan Zhang suspend_state_t state) 29405fda3b1SThomas Petazzoni { 29505fda3b1SThomas Petazzoni struct regulator *regulator; 296c360a6dfSChunyan Zhang struct regulator_voltage *voltage; 29705fda3b1SThomas Petazzoni 29805fda3b1SThomas Petazzoni list_for_each_entry(regulator, &rdev->consumer_list, list) { 299c360a6dfSChunyan Zhang voltage = ®ulator->voltage[state]; 3004aa922c0SMark Brown /* 3014aa922c0SMark Brown * Assume consumers that didn't say anything are OK 3024aa922c0SMark Brown * with anything in the constraint range. 3034aa922c0SMark Brown */ 304c360a6dfSChunyan Zhang if (!voltage->min_uV && !voltage->max_uV) 3054aa922c0SMark Brown continue; 3064aa922c0SMark Brown 307c360a6dfSChunyan Zhang if (*max_uV > voltage->max_uV) 308c360a6dfSChunyan Zhang *max_uV = voltage->max_uV; 309c360a6dfSChunyan Zhang if (*min_uV < voltage->min_uV) 310c360a6dfSChunyan Zhang *min_uV = voltage->min_uV; 31105fda3b1SThomas Petazzoni } 31205fda3b1SThomas Petazzoni 313dd8004afSMark Brown if (*min_uV > *max_uV) { 3149c7b4e8aSRuss Dill rdev_err(rdev, "Restricting voltage, %u-%uuV\n", 3159c7b4e8aSRuss Dill *min_uV, *max_uV); 31605fda3b1SThomas Petazzoni return -EINVAL; 317dd8004afSMark Brown } 31805fda3b1SThomas Petazzoni 31905fda3b1SThomas Petazzoni return 0; 32005fda3b1SThomas Petazzoni } 32105fda3b1SThomas Petazzoni 322414c70cbSLiam Girdwood /* current constraint check */ 323414c70cbSLiam Girdwood static int regulator_check_current_limit(struct regulator_dev *rdev, 324414c70cbSLiam Girdwood int *min_uA, int *max_uA) 325414c70cbSLiam Girdwood { 326414c70cbSLiam Girdwood BUG_ON(*min_uA > *max_uA); 327414c70cbSLiam Girdwood 3288a34e979SWEN Pingbo if (!regulator_ops_is_valid(rdev, REGULATOR_CHANGE_CURRENT)) { 3297ebcf26cSStephen Boyd rdev_err(rdev, "current operation not allowed\n"); 330414c70cbSLiam Girdwood return -EPERM; 331414c70cbSLiam Girdwood } 332414c70cbSLiam Girdwood 333414c70cbSLiam Girdwood if (*max_uA > rdev->constraints->max_uA) 334414c70cbSLiam Girdwood *max_uA = rdev->constraints->max_uA; 335414c70cbSLiam Girdwood if (*min_uA < rdev->constraints->min_uA) 336414c70cbSLiam Girdwood *min_uA = rdev->constraints->min_uA; 337414c70cbSLiam Girdwood 33889f425edSMark Brown if (*min_uA > *max_uA) { 33989f425edSMark Brown rdev_err(rdev, "unsupportable current range: %d-%duA\n", 34054abd335SMark Brown *min_uA, *max_uA); 341414c70cbSLiam Girdwood return -EINVAL; 34289f425edSMark Brown } 343414c70cbSLiam Girdwood 344414c70cbSLiam Girdwood return 0; 345414c70cbSLiam Girdwood } 346414c70cbSLiam Girdwood 347414c70cbSLiam Girdwood /* operating mode constraint check */ 348109c75afSCharles Keepax static int regulator_mode_constrain(struct regulator_dev *rdev, 349109c75afSCharles Keepax unsigned int *mode) 350414c70cbSLiam Girdwood { 3512c608234SMark Brown switch (*mode) { 352e573520bSDavid Brownell case REGULATOR_MODE_FAST: 353e573520bSDavid Brownell case REGULATOR_MODE_NORMAL: 354e573520bSDavid Brownell case REGULATOR_MODE_IDLE: 355e573520bSDavid Brownell case REGULATOR_MODE_STANDBY: 356e573520bSDavid Brownell break; 357e573520bSDavid Brownell default: 35889f425edSMark Brown rdev_err(rdev, "invalid mode %x specified\n", *mode); 359e573520bSDavid Brownell return -EINVAL; 360e573520bSDavid Brownell } 361e573520bSDavid Brownell 3628a34e979SWEN Pingbo if (!regulator_ops_is_valid(rdev, REGULATOR_CHANGE_MODE)) { 3637ebcf26cSStephen Boyd rdev_err(rdev, "mode operation not allowed\n"); 364414c70cbSLiam Girdwood return -EPERM; 365414c70cbSLiam Girdwood } 3662c608234SMark Brown 3672c608234SMark Brown /* The modes are bitmasks, the most power hungry modes having 3682c608234SMark Brown * the lowest values. If the requested mode isn't supported 3692c608234SMark Brown * try higher modes. */ 3702c608234SMark Brown while (*mode) { 3712c608234SMark Brown if (rdev->constraints->valid_modes_mask & *mode) 372414c70cbSLiam Girdwood return 0; 3732c608234SMark Brown *mode /= 2; 3742c608234SMark Brown } 3752c608234SMark Brown 3762c608234SMark Brown return -EINVAL; 377414c70cbSLiam Girdwood } 378414c70cbSLiam Girdwood 379f7efad10SChunyan Zhang static inline struct regulator_state * 380f7efad10SChunyan Zhang regulator_get_suspend_state(struct regulator_dev *rdev, suspend_state_t state) 381f7efad10SChunyan Zhang { 382f7efad10SChunyan Zhang if (rdev->constraints == NULL) 383f7efad10SChunyan Zhang return NULL; 384f7efad10SChunyan Zhang 385f7efad10SChunyan Zhang switch (state) { 386f7efad10SChunyan Zhang case PM_SUSPEND_STANDBY: 387f7efad10SChunyan Zhang return &rdev->constraints->state_standby; 388f7efad10SChunyan Zhang case PM_SUSPEND_MEM: 389f7efad10SChunyan Zhang return &rdev->constraints->state_mem; 390f7efad10SChunyan Zhang case PM_SUSPEND_MAX: 391f7efad10SChunyan Zhang return &rdev->constraints->state_disk; 392f7efad10SChunyan Zhang default: 393f7efad10SChunyan Zhang return NULL; 394f7efad10SChunyan Zhang } 395f7efad10SChunyan Zhang } 396f7efad10SChunyan Zhang 397414c70cbSLiam Girdwood static ssize_t regulator_uV_show(struct device *dev, 398414c70cbSLiam Girdwood struct device_attribute *attr, char *buf) 399414c70cbSLiam Girdwood { 400a5766f11SLiam Girdwood struct regulator_dev *rdev = dev_get_drvdata(dev); 401414c70cbSLiam Girdwood ssize_t ret; 402414c70cbSLiam Girdwood 40366cf9a7eSMaciej Purski regulator_lock(rdev); 404414c70cbSLiam Girdwood ret = sprintf(buf, "%d\n", _regulator_get_voltage(rdev)); 40566cf9a7eSMaciej Purski regulator_unlock(rdev); 406414c70cbSLiam Girdwood 407414c70cbSLiam Girdwood return ret; 408414c70cbSLiam Girdwood } 4097ad68e2fSDavid Brownell static DEVICE_ATTR(microvolts, 0444, regulator_uV_show, NULL); 410414c70cbSLiam Girdwood 411414c70cbSLiam Girdwood static ssize_t regulator_uA_show(struct device *dev, 412414c70cbSLiam Girdwood struct device_attribute *attr, char *buf) 413414c70cbSLiam Girdwood { 414a5766f11SLiam Girdwood struct regulator_dev *rdev = dev_get_drvdata(dev); 415414c70cbSLiam Girdwood 416414c70cbSLiam Girdwood return sprintf(buf, "%d\n", _regulator_get_current_limit(rdev)); 417414c70cbSLiam Girdwood } 4187ad68e2fSDavid Brownell static DEVICE_ATTR(microamps, 0444, regulator_uA_show, NULL); 419414c70cbSLiam Girdwood 420587cea27SGreg Kroah-Hartman static ssize_t name_show(struct device *dev, struct device_attribute *attr, 421587cea27SGreg Kroah-Hartman char *buf) 422bc558a60SMark Brown { 423bc558a60SMark Brown struct regulator_dev *rdev = dev_get_drvdata(dev); 424bc558a60SMark Brown 4251083c393SMark Brown return sprintf(buf, "%s\n", rdev_get_name(rdev)); 426bc558a60SMark Brown } 427587cea27SGreg Kroah-Hartman static DEVICE_ATTR_RO(name); 428bc558a60SMark Brown 42901de19d0SDouglas Anderson static const char *regulator_opmode_to_str(int mode) 430414c70cbSLiam Girdwood { 431414c70cbSLiam Girdwood switch (mode) { 432414c70cbSLiam Girdwood case REGULATOR_MODE_FAST: 43301de19d0SDouglas Anderson return "fast"; 434414c70cbSLiam Girdwood case REGULATOR_MODE_NORMAL: 43501de19d0SDouglas Anderson return "normal"; 436414c70cbSLiam Girdwood case REGULATOR_MODE_IDLE: 43701de19d0SDouglas Anderson return "idle"; 438414c70cbSLiam Girdwood case REGULATOR_MODE_STANDBY: 43901de19d0SDouglas Anderson return "standby"; 440414c70cbSLiam Girdwood } 44101de19d0SDouglas Anderson return "unknown"; 44201de19d0SDouglas Anderson } 44301de19d0SDouglas Anderson 44401de19d0SDouglas Anderson static ssize_t regulator_print_opmode(char *buf, int mode) 44501de19d0SDouglas Anderson { 44601de19d0SDouglas Anderson return sprintf(buf, "%s\n", regulator_opmode_to_str(mode)); 447414c70cbSLiam Girdwood } 448414c70cbSLiam Girdwood 4494fca9545SDavid Brownell static ssize_t regulator_opmode_show(struct device *dev, 450414c70cbSLiam Girdwood struct device_attribute *attr, char *buf) 451414c70cbSLiam Girdwood { 452a5766f11SLiam Girdwood struct regulator_dev *rdev = dev_get_drvdata(dev); 453414c70cbSLiam Girdwood 4544fca9545SDavid Brownell return regulator_print_opmode(buf, _regulator_get_mode(rdev)); 4554fca9545SDavid Brownell } 4567ad68e2fSDavid Brownell static DEVICE_ATTR(opmode, 0444, regulator_opmode_show, NULL); 4574fca9545SDavid Brownell 4584fca9545SDavid Brownell static ssize_t regulator_print_state(char *buf, int state) 4594fca9545SDavid Brownell { 460414c70cbSLiam Girdwood if (state > 0) 461414c70cbSLiam Girdwood return sprintf(buf, "enabled\n"); 462414c70cbSLiam Girdwood else if (state == 0) 463414c70cbSLiam Girdwood return sprintf(buf, "disabled\n"); 464414c70cbSLiam Girdwood else 465414c70cbSLiam Girdwood return sprintf(buf, "unknown\n"); 466414c70cbSLiam Girdwood } 467414c70cbSLiam Girdwood 4684fca9545SDavid Brownell static ssize_t regulator_state_show(struct device *dev, 4694fca9545SDavid Brownell struct device_attribute *attr, char *buf) 4704fca9545SDavid Brownell { 4714fca9545SDavid Brownell struct regulator_dev *rdev = dev_get_drvdata(dev); 4729332546fSMark Brown ssize_t ret; 4734fca9545SDavid Brownell 47466cf9a7eSMaciej Purski regulator_lock(rdev); 4759332546fSMark Brown ret = regulator_print_state(buf, _regulator_is_enabled(rdev)); 47666cf9a7eSMaciej Purski regulator_unlock(rdev); 4779332546fSMark Brown 4789332546fSMark Brown return ret; 4794fca9545SDavid Brownell } 4807ad68e2fSDavid Brownell static DEVICE_ATTR(state, 0444, regulator_state_show, NULL); 4814fca9545SDavid Brownell 482853116a1SDavid Brownell static ssize_t regulator_status_show(struct device *dev, 483853116a1SDavid Brownell struct device_attribute *attr, char *buf) 484853116a1SDavid Brownell { 485853116a1SDavid Brownell struct regulator_dev *rdev = dev_get_drvdata(dev); 486853116a1SDavid Brownell int status; 487853116a1SDavid Brownell char *label; 488853116a1SDavid Brownell 489853116a1SDavid Brownell status = rdev->desc->ops->get_status(rdev); 490853116a1SDavid Brownell if (status < 0) 491853116a1SDavid Brownell return status; 492853116a1SDavid Brownell 493853116a1SDavid Brownell switch (status) { 494853116a1SDavid Brownell case REGULATOR_STATUS_OFF: 495853116a1SDavid Brownell label = "off"; 496853116a1SDavid Brownell break; 497853116a1SDavid Brownell case REGULATOR_STATUS_ON: 498853116a1SDavid Brownell label = "on"; 499853116a1SDavid Brownell break; 500853116a1SDavid Brownell case REGULATOR_STATUS_ERROR: 501853116a1SDavid Brownell label = "error"; 502853116a1SDavid Brownell break; 503853116a1SDavid Brownell case REGULATOR_STATUS_FAST: 504853116a1SDavid Brownell label = "fast"; 505853116a1SDavid Brownell break; 506853116a1SDavid Brownell case REGULATOR_STATUS_NORMAL: 507853116a1SDavid Brownell label = "normal"; 508853116a1SDavid Brownell break; 509853116a1SDavid Brownell case REGULATOR_STATUS_IDLE: 510853116a1SDavid Brownell label = "idle"; 511853116a1SDavid Brownell break; 512853116a1SDavid Brownell case REGULATOR_STATUS_STANDBY: 513853116a1SDavid Brownell label = "standby"; 514853116a1SDavid Brownell break; 515f59c8f9fSMark Brown case REGULATOR_STATUS_BYPASS: 516f59c8f9fSMark Brown label = "bypass"; 517f59c8f9fSMark Brown break; 5181beaf762SKrystian Garbaciak case REGULATOR_STATUS_UNDEFINED: 5191beaf762SKrystian Garbaciak label = "undefined"; 5201beaf762SKrystian Garbaciak break; 521853116a1SDavid Brownell default: 522853116a1SDavid Brownell return -ERANGE; 523853116a1SDavid Brownell } 524853116a1SDavid Brownell 525853116a1SDavid Brownell return sprintf(buf, "%s\n", label); 526853116a1SDavid Brownell } 527853116a1SDavid Brownell static DEVICE_ATTR(status, 0444, regulator_status_show, NULL); 528853116a1SDavid Brownell 529414c70cbSLiam Girdwood static ssize_t regulator_min_uA_show(struct device *dev, 530414c70cbSLiam Girdwood struct device_attribute *attr, char *buf) 531414c70cbSLiam Girdwood { 532a5766f11SLiam Girdwood struct regulator_dev *rdev = dev_get_drvdata(dev); 533414c70cbSLiam Girdwood 534414c70cbSLiam Girdwood if (!rdev->constraints) 535414c70cbSLiam Girdwood return sprintf(buf, "constraint not defined\n"); 536414c70cbSLiam Girdwood 537414c70cbSLiam Girdwood return sprintf(buf, "%d\n", rdev->constraints->min_uA); 538414c70cbSLiam Girdwood } 5397ad68e2fSDavid Brownell static DEVICE_ATTR(min_microamps, 0444, regulator_min_uA_show, NULL); 540414c70cbSLiam Girdwood 541414c70cbSLiam Girdwood static ssize_t regulator_max_uA_show(struct device *dev, 542414c70cbSLiam Girdwood struct device_attribute *attr, char *buf) 543414c70cbSLiam Girdwood { 544a5766f11SLiam Girdwood struct regulator_dev *rdev = dev_get_drvdata(dev); 545414c70cbSLiam Girdwood 546414c70cbSLiam Girdwood if (!rdev->constraints) 547414c70cbSLiam Girdwood return sprintf(buf, "constraint not defined\n"); 548414c70cbSLiam Girdwood 549414c70cbSLiam Girdwood return sprintf(buf, "%d\n", rdev->constraints->max_uA); 550414c70cbSLiam Girdwood } 5517ad68e2fSDavid Brownell static DEVICE_ATTR(max_microamps, 0444, regulator_max_uA_show, NULL); 552414c70cbSLiam Girdwood 553414c70cbSLiam Girdwood static ssize_t regulator_min_uV_show(struct device *dev, 554414c70cbSLiam Girdwood struct device_attribute *attr, char *buf) 555414c70cbSLiam Girdwood { 556a5766f11SLiam Girdwood struct regulator_dev *rdev = dev_get_drvdata(dev); 557414c70cbSLiam Girdwood 558414c70cbSLiam Girdwood if (!rdev->constraints) 559414c70cbSLiam Girdwood return sprintf(buf, "constraint not defined\n"); 560414c70cbSLiam Girdwood 561414c70cbSLiam Girdwood return sprintf(buf, "%d\n", rdev->constraints->min_uV); 562414c70cbSLiam Girdwood } 5637ad68e2fSDavid Brownell static DEVICE_ATTR(min_microvolts, 0444, regulator_min_uV_show, NULL); 564414c70cbSLiam Girdwood 565414c70cbSLiam Girdwood static ssize_t regulator_max_uV_show(struct device *dev, 566414c70cbSLiam Girdwood struct device_attribute *attr, char *buf) 567414c70cbSLiam Girdwood { 568a5766f11SLiam Girdwood struct regulator_dev *rdev = dev_get_drvdata(dev); 569414c70cbSLiam Girdwood 570414c70cbSLiam Girdwood if (!rdev->constraints) 571414c70cbSLiam Girdwood return sprintf(buf, "constraint not defined\n"); 572414c70cbSLiam Girdwood 573414c70cbSLiam Girdwood return sprintf(buf, "%d\n", rdev->constraints->max_uV); 574414c70cbSLiam Girdwood } 5757ad68e2fSDavid Brownell static DEVICE_ATTR(max_microvolts, 0444, regulator_max_uV_show, NULL); 576414c70cbSLiam Girdwood 577414c70cbSLiam Girdwood static ssize_t regulator_total_uA_show(struct device *dev, 578414c70cbSLiam Girdwood struct device_attribute *attr, char *buf) 579414c70cbSLiam Girdwood { 580a5766f11SLiam Girdwood struct regulator_dev *rdev = dev_get_drvdata(dev); 581414c70cbSLiam Girdwood struct regulator *regulator; 582414c70cbSLiam Girdwood int uA = 0; 583414c70cbSLiam Girdwood 58466cf9a7eSMaciej Purski regulator_lock(rdev); 585414c70cbSLiam Girdwood list_for_each_entry(regulator, &rdev->consumer_list, list) 586414c70cbSLiam Girdwood uA += regulator->uA_load; 58766cf9a7eSMaciej Purski regulator_unlock(rdev); 588414c70cbSLiam Girdwood return sprintf(buf, "%d\n", uA); 589414c70cbSLiam Girdwood } 5907ad68e2fSDavid Brownell static DEVICE_ATTR(requested_microamps, 0444, regulator_total_uA_show, NULL); 591414c70cbSLiam Girdwood 592587cea27SGreg Kroah-Hartman static ssize_t num_users_show(struct device *dev, struct device_attribute *attr, 593587cea27SGreg Kroah-Hartman char *buf) 594414c70cbSLiam Girdwood { 595a5766f11SLiam Girdwood struct regulator_dev *rdev = dev_get_drvdata(dev); 596414c70cbSLiam Girdwood return sprintf(buf, "%d\n", rdev->use_count); 597414c70cbSLiam Girdwood } 598587cea27SGreg Kroah-Hartman static DEVICE_ATTR_RO(num_users); 599414c70cbSLiam Girdwood 600587cea27SGreg Kroah-Hartman static ssize_t type_show(struct device *dev, struct device_attribute *attr, 601587cea27SGreg Kroah-Hartman char *buf) 602414c70cbSLiam Girdwood { 603a5766f11SLiam Girdwood struct regulator_dev *rdev = dev_get_drvdata(dev); 604414c70cbSLiam Girdwood 605414c70cbSLiam Girdwood switch (rdev->desc->type) { 606414c70cbSLiam Girdwood case REGULATOR_VOLTAGE: 607414c70cbSLiam Girdwood return sprintf(buf, "voltage\n"); 608414c70cbSLiam Girdwood case REGULATOR_CURRENT: 609414c70cbSLiam Girdwood return sprintf(buf, "current\n"); 610414c70cbSLiam Girdwood } 611414c70cbSLiam Girdwood return sprintf(buf, "unknown\n"); 612414c70cbSLiam Girdwood } 613587cea27SGreg Kroah-Hartman static DEVICE_ATTR_RO(type); 614414c70cbSLiam Girdwood 615414c70cbSLiam Girdwood static ssize_t regulator_suspend_mem_uV_show(struct device *dev, 616414c70cbSLiam Girdwood struct device_attribute *attr, char *buf) 617414c70cbSLiam Girdwood { 618a5766f11SLiam Girdwood struct regulator_dev *rdev = dev_get_drvdata(dev); 619414c70cbSLiam Girdwood 620414c70cbSLiam Girdwood return sprintf(buf, "%d\n", rdev->constraints->state_mem.uV); 621414c70cbSLiam Girdwood } 6227ad68e2fSDavid Brownell static DEVICE_ATTR(suspend_mem_microvolts, 0444, 6237ad68e2fSDavid Brownell regulator_suspend_mem_uV_show, NULL); 624414c70cbSLiam Girdwood 625414c70cbSLiam Girdwood static ssize_t regulator_suspend_disk_uV_show(struct device *dev, 626414c70cbSLiam Girdwood struct device_attribute *attr, char *buf) 627414c70cbSLiam Girdwood { 628a5766f11SLiam Girdwood struct regulator_dev *rdev = dev_get_drvdata(dev); 629414c70cbSLiam Girdwood 630414c70cbSLiam Girdwood return sprintf(buf, "%d\n", rdev->constraints->state_disk.uV); 631414c70cbSLiam Girdwood } 6327ad68e2fSDavid Brownell static DEVICE_ATTR(suspend_disk_microvolts, 0444, 6337ad68e2fSDavid Brownell regulator_suspend_disk_uV_show, NULL); 634414c70cbSLiam Girdwood 635414c70cbSLiam Girdwood static ssize_t regulator_suspend_standby_uV_show(struct device *dev, 636414c70cbSLiam Girdwood struct device_attribute *attr, char *buf) 637414c70cbSLiam Girdwood { 638a5766f11SLiam Girdwood struct regulator_dev *rdev = dev_get_drvdata(dev); 639414c70cbSLiam Girdwood 640414c70cbSLiam Girdwood return sprintf(buf, "%d\n", rdev->constraints->state_standby.uV); 641414c70cbSLiam Girdwood } 6427ad68e2fSDavid Brownell static DEVICE_ATTR(suspend_standby_microvolts, 0444, 6437ad68e2fSDavid Brownell regulator_suspend_standby_uV_show, NULL); 644414c70cbSLiam Girdwood 645414c70cbSLiam Girdwood static ssize_t regulator_suspend_mem_mode_show(struct device *dev, 646414c70cbSLiam Girdwood struct device_attribute *attr, char *buf) 647414c70cbSLiam Girdwood { 648a5766f11SLiam Girdwood struct regulator_dev *rdev = dev_get_drvdata(dev); 649414c70cbSLiam Girdwood 6504fca9545SDavid Brownell return regulator_print_opmode(buf, 6514fca9545SDavid Brownell rdev->constraints->state_mem.mode); 652414c70cbSLiam Girdwood } 6537ad68e2fSDavid Brownell static DEVICE_ATTR(suspend_mem_mode, 0444, 6547ad68e2fSDavid Brownell regulator_suspend_mem_mode_show, NULL); 655414c70cbSLiam Girdwood 656414c70cbSLiam Girdwood static ssize_t regulator_suspend_disk_mode_show(struct device *dev, 657414c70cbSLiam Girdwood struct device_attribute *attr, char *buf) 658414c70cbSLiam Girdwood { 659a5766f11SLiam Girdwood struct regulator_dev *rdev = dev_get_drvdata(dev); 660414c70cbSLiam Girdwood 6614fca9545SDavid Brownell return regulator_print_opmode(buf, 6624fca9545SDavid Brownell rdev->constraints->state_disk.mode); 663414c70cbSLiam Girdwood } 6647ad68e2fSDavid Brownell static DEVICE_ATTR(suspend_disk_mode, 0444, 6657ad68e2fSDavid Brownell regulator_suspend_disk_mode_show, NULL); 666414c70cbSLiam Girdwood 667414c70cbSLiam Girdwood static ssize_t regulator_suspend_standby_mode_show(struct device *dev, 668414c70cbSLiam Girdwood struct device_attribute *attr, char *buf) 669414c70cbSLiam Girdwood { 670a5766f11SLiam Girdwood struct regulator_dev *rdev = dev_get_drvdata(dev); 671414c70cbSLiam Girdwood 6724fca9545SDavid Brownell return regulator_print_opmode(buf, 6734fca9545SDavid Brownell rdev->constraints->state_standby.mode); 674414c70cbSLiam Girdwood } 6757ad68e2fSDavid Brownell static DEVICE_ATTR(suspend_standby_mode, 0444, 6767ad68e2fSDavid Brownell regulator_suspend_standby_mode_show, NULL); 677414c70cbSLiam Girdwood 678414c70cbSLiam Girdwood static ssize_t regulator_suspend_mem_state_show(struct device *dev, 679414c70cbSLiam Girdwood struct device_attribute *attr, char *buf) 680414c70cbSLiam Girdwood { 681a5766f11SLiam Girdwood struct regulator_dev *rdev = dev_get_drvdata(dev); 682414c70cbSLiam Girdwood 6834fca9545SDavid Brownell return regulator_print_state(buf, 6844fca9545SDavid Brownell rdev->constraints->state_mem.enabled); 685414c70cbSLiam Girdwood } 6867ad68e2fSDavid Brownell static DEVICE_ATTR(suspend_mem_state, 0444, 6877ad68e2fSDavid Brownell regulator_suspend_mem_state_show, NULL); 688414c70cbSLiam Girdwood 689414c70cbSLiam Girdwood static ssize_t regulator_suspend_disk_state_show(struct device *dev, 690414c70cbSLiam Girdwood struct device_attribute *attr, char *buf) 691414c70cbSLiam Girdwood { 692a5766f11SLiam Girdwood struct regulator_dev *rdev = dev_get_drvdata(dev); 693414c70cbSLiam Girdwood 6944fca9545SDavid Brownell return regulator_print_state(buf, 6954fca9545SDavid Brownell rdev->constraints->state_disk.enabled); 696414c70cbSLiam Girdwood } 6977ad68e2fSDavid Brownell static DEVICE_ATTR(suspend_disk_state, 0444, 6987ad68e2fSDavid Brownell regulator_suspend_disk_state_show, NULL); 699414c70cbSLiam Girdwood 700414c70cbSLiam Girdwood static ssize_t regulator_suspend_standby_state_show(struct device *dev, 701414c70cbSLiam Girdwood struct device_attribute *attr, char *buf) 702414c70cbSLiam Girdwood { 703a5766f11SLiam Girdwood struct regulator_dev *rdev = dev_get_drvdata(dev); 704414c70cbSLiam Girdwood 7054fca9545SDavid Brownell return regulator_print_state(buf, 7064fca9545SDavid Brownell rdev->constraints->state_standby.enabled); 707414c70cbSLiam Girdwood } 7087ad68e2fSDavid Brownell static DEVICE_ATTR(suspend_standby_state, 0444, 7097ad68e2fSDavid Brownell regulator_suspend_standby_state_show, NULL); 710bc558a60SMark Brown 711f59c8f9fSMark Brown static ssize_t regulator_bypass_show(struct device *dev, 712f59c8f9fSMark Brown struct device_attribute *attr, char *buf) 713f59c8f9fSMark Brown { 714f59c8f9fSMark Brown struct regulator_dev *rdev = dev_get_drvdata(dev); 715f59c8f9fSMark Brown const char *report; 716f59c8f9fSMark Brown bool bypass; 717f59c8f9fSMark Brown int ret; 718f59c8f9fSMark Brown 719f59c8f9fSMark Brown ret = rdev->desc->ops->get_bypass(rdev, &bypass); 720f59c8f9fSMark Brown 721f59c8f9fSMark Brown if (ret != 0) 722f59c8f9fSMark Brown report = "unknown"; 723f59c8f9fSMark Brown else if (bypass) 724f59c8f9fSMark Brown report = "enabled"; 725f59c8f9fSMark Brown else 726f59c8f9fSMark Brown report = "disabled"; 727f59c8f9fSMark Brown 728f59c8f9fSMark Brown return sprintf(buf, "%s\n", report); 729f59c8f9fSMark Brown } 730f59c8f9fSMark Brown static DEVICE_ATTR(bypass, 0444, 731f59c8f9fSMark Brown regulator_bypass_show, NULL); 7327ad68e2fSDavid Brownell 733414c70cbSLiam Girdwood /* Calculate the new optimum regulator operating mode based on the new total 734414c70cbSLiam Girdwood * consumer load. All locks held by caller */ 7358460ef38SBjorn Andersson static int drms_uA_update(struct regulator_dev *rdev) 736414c70cbSLiam Girdwood { 737414c70cbSLiam Girdwood struct regulator *sibling; 738414c70cbSLiam Girdwood int current_uA = 0, output_uV, input_uV, err; 739414c70cbSLiam Girdwood unsigned int mode; 740414c70cbSLiam Girdwood 74170cfef26SKrzysztof Kozlowski lockdep_assert_held_once(&rdev->mutex); 74270cfef26SKrzysztof Kozlowski 7438460ef38SBjorn Andersson /* 7448460ef38SBjorn Andersson * first check to see if we can set modes at all, otherwise just 7458460ef38SBjorn Andersson * tell the consumer everything is OK. 7468460ef38SBjorn Andersson */ 7478a34e979SWEN Pingbo if (!regulator_ops_is_valid(rdev, REGULATOR_CHANGE_DRMS)) 7488460ef38SBjorn Andersson return 0; 7498460ef38SBjorn Andersson 7508f4490e0SBjorn Andersson if (!rdev->desc->ops->get_optimum_mode && 7518f4490e0SBjorn Andersson !rdev->desc->ops->set_load) 7528460ef38SBjorn Andersson return 0; 7538460ef38SBjorn Andersson 7548f4490e0SBjorn Andersson if (!rdev->desc->ops->set_mode && 7558f4490e0SBjorn Andersson !rdev->desc->ops->set_load) 7568460ef38SBjorn Andersson return -EINVAL; 757414c70cbSLiam Girdwood 75857776617SJoonwoo Park /* calc total requested load */ 75957776617SJoonwoo Park list_for_each_entry(sibling, &rdev->consumer_list, list) 76057776617SJoonwoo Park current_uA += sibling->uA_load; 76157776617SJoonwoo Park 76257776617SJoonwoo Park current_uA += rdev->constraints->system_load; 76357776617SJoonwoo Park 76457776617SJoonwoo Park if (rdev->desc->ops->set_load) { 76557776617SJoonwoo Park /* set the optimum mode for our new total regulator load */ 76657776617SJoonwoo Park err = rdev->desc->ops->set_load(rdev, current_uA); 76757776617SJoonwoo Park if (err < 0) 76857776617SJoonwoo Park rdev_err(rdev, "failed to set load %d\n", current_uA); 76957776617SJoonwoo Park } else { 770414c70cbSLiam Girdwood /* get output voltage */ 7711bf5a1f8SMark Brown output_uV = _regulator_get_voltage(rdev); 7728460ef38SBjorn Andersson if (output_uV <= 0) { 7738460ef38SBjorn Andersson rdev_err(rdev, "invalid output voltage found\n"); 7748460ef38SBjorn Andersson return -EINVAL; 7758460ef38SBjorn Andersson } 776414c70cbSLiam Girdwood 777414c70cbSLiam Girdwood /* get input voltage */ 7781bf5a1f8SMark Brown input_uV = 0; 7791bf5a1f8SMark Brown if (rdev->supply) 7803f24f5adSAxel Lin input_uV = regulator_get_voltage(rdev->supply); 7811bf5a1f8SMark Brown if (input_uV <= 0) 782414c70cbSLiam Girdwood input_uV = rdev->constraints->input_uV; 7838460ef38SBjorn Andersson if (input_uV <= 0) { 7848460ef38SBjorn Andersson rdev_err(rdev, "invalid input voltage found\n"); 7858460ef38SBjorn Andersson return -EINVAL; 7868460ef38SBjorn Andersson } 787414c70cbSLiam Girdwood 788414c70cbSLiam Girdwood /* now get the optimum mode for our new total regulator load */ 789414c70cbSLiam Girdwood mode = rdev->desc->ops->get_optimum_mode(rdev, input_uV, 790414c70cbSLiam Girdwood output_uV, current_uA); 791414c70cbSLiam Girdwood 792414c70cbSLiam Girdwood /* check the new mode is allowed */ 7932c608234SMark Brown err = regulator_mode_constrain(rdev, &mode); 7948460ef38SBjorn Andersson if (err < 0) { 7958460ef38SBjorn Andersson rdev_err(rdev, "failed to get optimum mode @ %d uA %d -> %d uV\n", 7968460ef38SBjorn Andersson current_uA, input_uV, output_uV); 7978460ef38SBjorn Andersson return err; 7988460ef38SBjorn Andersson } 7998460ef38SBjorn Andersson 8008460ef38SBjorn Andersson err = rdev->desc->ops->set_mode(rdev, mode); 8018460ef38SBjorn Andersson if (err < 0) 8028460ef38SBjorn Andersson rdev_err(rdev, "failed to set optimum mode %x\n", mode); 8038f4490e0SBjorn Andersson } 8048460ef38SBjorn Andersson 8058460ef38SBjorn Andersson return err; 806414c70cbSLiam Girdwood } 807414c70cbSLiam Girdwood 808414c70cbSLiam Girdwood static int suspend_set_state(struct regulator_dev *rdev, 809f7efad10SChunyan Zhang suspend_state_t state) 810414c70cbSLiam Girdwood { 811414c70cbSLiam Girdwood int ret = 0; 812f7efad10SChunyan Zhang struct regulator_state *rstate; 813f7efad10SChunyan Zhang 814f7efad10SChunyan Zhang rstate = regulator_get_suspend_state(rdev, state); 815f7efad10SChunyan Zhang if (rstate == NULL) 81657a0dd18SMark Brown return 0; 817638f85c5SMark Brown 818638f85c5SMark Brown /* If we have no suspend mode configration don't set anything; 8198ac0e95dSAxel Lin * only warn if the driver implements set_suspend_voltage or 8208ac0e95dSAxel Lin * set_suspend_mode callback. 821638f85c5SMark Brown */ 82272069f99SChunyan Zhang if (rstate->enabled != ENABLE_IN_SUSPEND && 82372069f99SChunyan Zhang rstate->enabled != DISABLE_IN_SUSPEND) { 8248ac0e95dSAxel Lin if (rdev->desc->ops->set_suspend_voltage || 8258ac0e95dSAxel Lin rdev->desc->ops->set_suspend_mode) 8265da84fd9SJoe Perches rdev_warn(rdev, "No configuration\n"); 827638f85c5SMark Brown return 0; 828638f85c5SMark Brown } 829638f85c5SMark Brown 83072069f99SChunyan Zhang if (rstate->enabled == ENABLE_IN_SUSPEND && 83172069f99SChunyan Zhang rdev->desc->ops->set_suspend_enable) 832414c70cbSLiam Girdwood ret = rdev->desc->ops->set_suspend_enable(rdev); 83372069f99SChunyan Zhang else if (rstate->enabled == DISABLE_IN_SUSPEND && 83472069f99SChunyan Zhang rdev->desc->ops->set_suspend_disable) 835414c70cbSLiam Girdwood ret = rdev->desc->ops->set_suspend_disable(rdev); 8368ac0e95dSAxel Lin else /* OK if set_suspend_enable or set_suspend_disable is NULL */ 8378ac0e95dSAxel Lin ret = 0; 8388ac0e95dSAxel Lin 839414c70cbSLiam Girdwood if (ret < 0) { 8405da84fd9SJoe Perches rdev_err(rdev, "failed to enabled/disable\n"); 841414c70cbSLiam Girdwood return ret; 842414c70cbSLiam Girdwood } 843414c70cbSLiam Girdwood 844414c70cbSLiam Girdwood if (rdev->desc->ops->set_suspend_voltage && rstate->uV > 0) { 845414c70cbSLiam Girdwood ret = rdev->desc->ops->set_suspend_voltage(rdev, rstate->uV); 846414c70cbSLiam Girdwood if (ret < 0) { 8475da84fd9SJoe Perches rdev_err(rdev, "failed to set voltage\n"); 848414c70cbSLiam Girdwood return ret; 849414c70cbSLiam Girdwood } 850414c70cbSLiam Girdwood } 851414c70cbSLiam Girdwood 852414c70cbSLiam Girdwood if (rdev->desc->ops->set_suspend_mode && rstate->mode > 0) { 853414c70cbSLiam Girdwood ret = rdev->desc->ops->set_suspend_mode(rdev, rstate->mode); 854414c70cbSLiam Girdwood if (ret < 0) { 8555da84fd9SJoe Perches rdev_err(rdev, "failed to set mode\n"); 856414c70cbSLiam Girdwood return ret; 857414c70cbSLiam Girdwood } 858414c70cbSLiam Girdwood } 859f7efad10SChunyan Zhang 860414c70cbSLiam Girdwood return ret; 861414c70cbSLiam Girdwood } 862414c70cbSLiam Girdwood 863414c70cbSLiam Girdwood static void print_constraints(struct regulator_dev *rdev) 864414c70cbSLiam Girdwood { 865414c70cbSLiam Girdwood struct regulation_constraints *constraints = rdev->constraints; 866a7068e39SStefan Wahren char buf[160] = ""; 8675751a99fSStefan Wahren size_t len = sizeof(buf) - 1; 8688f031b48SMark Brown int count = 0; 8698f031b48SMark Brown int ret; 870414c70cbSLiam Girdwood 8718f031b48SMark Brown if (constraints->min_uV && constraints->max_uV) { 872414c70cbSLiam Girdwood if (constraints->min_uV == constraints->max_uV) 8735751a99fSStefan Wahren count += scnprintf(buf + count, len - count, "%d mV ", 874414c70cbSLiam Girdwood constraints->min_uV / 1000); 875414c70cbSLiam Girdwood else 8765751a99fSStefan Wahren count += scnprintf(buf + count, len - count, 8775751a99fSStefan Wahren "%d <--> %d mV ", 878414c70cbSLiam Girdwood constraints->min_uV / 1000, 879414c70cbSLiam Girdwood constraints->max_uV / 1000); 8808f031b48SMark Brown } 8818f031b48SMark Brown 8828f031b48SMark Brown if (!constraints->min_uV || 8838f031b48SMark Brown constraints->min_uV != constraints->max_uV) { 8848f031b48SMark Brown ret = _regulator_get_voltage(rdev); 8858f031b48SMark Brown if (ret > 0) 8865751a99fSStefan Wahren count += scnprintf(buf + count, len - count, 8875751a99fSStefan Wahren "at %d mV ", ret / 1000); 8888f031b48SMark Brown } 8898f031b48SMark Brown 890bf5892a8SMark Brown if (constraints->uV_offset) 8915751a99fSStefan Wahren count += scnprintf(buf + count, len - count, "%dmV offset ", 892bf5892a8SMark Brown constraints->uV_offset / 1000); 893bf5892a8SMark Brown 8948f031b48SMark Brown if (constraints->min_uA && constraints->max_uA) { 895414c70cbSLiam Girdwood if (constraints->min_uA == constraints->max_uA) 8965751a99fSStefan Wahren count += scnprintf(buf + count, len - count, "%d mA ", 897414c70cbSLiam Girdwood constraints->min_uA / 1000); 898414c70cbSLiam Girdwood else 8995751a99fSStefan Wahren count += scnprintf(buf + count, len - count, 9005751a99fSStefan Wahren "%d <--> %d mA ", 901414c70cbSLiam Girdwood constraints->min_uA / 1000, 902414c70cbSLiam Girdwood constraints->max_uA / 1000); 903414c70cbSLiam Girdwood } 9048f031b48SMark Brown 9058f031b48SMark Brown if (!constraints->min_uA || 9068f031b48SMark Brown constraints->min_uA != constraints->max_uA) { 9078f031b48SMark Brown ret = _regulator_get_current_limit(rdev); 9088f031b48SMark Brown if (ret > 0) 9095751a99fSStefan Wahren count += scnprintf(buf + count, len - count, 9105751a99fSStefan Wahren "at %d mA ", ret / 1000); 9118f031b48SMark Brown } 9128f031b48SMark Brown 913414c70cbSLiam Girdwood if (constraints->valid_modes_mask & REGULATOR_MODE_FAST) 9145751a99fSStefan Wahren count += scnprintf(buf + count, len - count, "fast "); 915414c70cbSLiam Girdwood if (constraints->valid_modes_mask & REGULATOR_MODE_NORMAL) 9165751a99fSStefan Wahren count += scnprintf(buf + count, len - count, "normal "); 917414c70cbSLiam Girdwood if (constraints->valid_modes_mask & REGULATOR_MODE_IDLE) 9185751a99fSStefan Wahren count += scnprintf(buf + count, len - count, "idle "); 919414c70cbSLiam Girdwood if (constraints->valid_modes_mask & REGULATOR_MODE_STANDBY) 9205751a99fSStefan Wahren count += scnprintf(buf + count, len - count, "standby"); 921414c70cbSLiam Girdwood 922215b8b05SUwe Kleine-König if (!count) 9235751a99fSStefan Wahren scnprintf(buf, len, "no parameters"); 924215b8b05SUwe Kleine-König 925194dbaefSMark Brown rdev_dbg(rdev, "%s\n", buf); 9264a682922SMark Brown 9274a682922SMark Brown if ((constraints->min_uV != constraints->max_uV) && 9288a34e979SWEN Pingbo !regulator_ops_is_valid(rdev, REGULATOR_CHANGE_VOLTAGE)) 9294a682922SMark Brown rdev_warn(rdev, 9304a682922SMark Brown "Voltage range but no REGULATOR_CHANGE_VOLTAGE\n"); 931414c70cbSLiam Girdwood } 932414c70cbSLiam Girdwood 933e79055d6SMark Brown static int machine_constraints_voltage(struct regulator_dev *rdev, 9341083c393SMark Brown struct regulation_constraints *constraints) 935e79055d6SMark Brown { 936272e2315SGuodong Xu const struct regulator_ops *ops = rdev->desc->ops; 937af5866c9SMark Brown int ret; 938af5866c9SMark Brown 939af5866c9SMark Brown /* do we need to apply the constraint voltage */ 940af5866c9SMark Brown if (rdev->constraints->apply_uV && 941fa93fd4eSMark Brown rdev->constraints->min_uV && rdev->constraints->max_uV) { 942fa93fd4eSMark Brown int target_min, target_max; 943064d5cd1SAlban Bedel int current_uV = _regulator_get_voltage(rdev); 94484b3a7c9SDouglas Anderson 94584b3a7c9SDouglas Anderson if (current_uV == -ENOTRECOVERABLE) { 94684b3a7c9SDouglas Anderson /* This regulator can't be read and must be initted */ 94784b3a7c9SDouglas Anderson rdev_info(rdev, "Setting %d-%duV\n", 94884b3a7c9SDouglas Anderson rdev->constraints->min_uV, 94984b3a7c9SDouglas Anderson rdev->constraints->max_uV); 95084b3a7c9SDouglas Anderson _regulator_do_set_voltage(rdev, 95184b3a7c9SDouglas Anderson rdev->constraints->min_uV, 95284b3a7c9SDouglas Anderson rdev->constraints->max_uV); 95384b3a7c9SDouglas Anderson current_uV = _regulator_get_voltage(rdev); 95484b3a7c9SDouglas Anderson } 95584b3a7c9SDouglas Anderson 956064d5cd1SAlban Bedel if (current_uV < 0) { 95769d58839SNishanth Menon rdev_err(rdev, 95869d58839SNishanth Menon "failed to get the current voltage(%d)\n", 95969d58839SNishanth Menon current_uV); 960064d5cd1SAlban Bedel return current_uV; 961064d5cd1SAlban Bedel } 962fa93fd4eSMark Brown 963fa93fd4eSMark Brown /* 964fa93fd4eSMark Brown * If we're below the minimum voltage move up to the 965fa93fd4eSMark Brown * minimum voltage, if we're above the maximum voltage 966fa93fd4eSMark Brown * then move down to the maximum. 967fa93fd4eSMark Brown */ 968fa93fd4eSMark Brown target_min = current_uV; 969fa93fd4eSMark Brown target_max = current_uV; 970fa93fd4eSMark Brown 971fa93fd4eSMark Brown if (current_uV < rdev->constraints->min_uV) { 972fa93fd4eSMark Brown target_min = rdev->constraints->min_uV; 973fa93fd4eSMark Brown target_max = rdev->constraints->min_uV; 974fa93fd4eSMark Brown } 975fa93fd4eSMark Brown 976fa93fd4eSMark Brown if (current_uV > rdev->constraints->max_uV) { 977fa93fd4eSMark Brown target_min = rdev->constraints->max_uV; 978fa93fd4eSMark Brown target_max = rdev->constraints->max_uV; 979fa93fd4eSMark Brown } 980fa93fd4eSMark Brown 981fa93fd4eSMark Brown if (target_min != current_uV || target_max != current_uV) { 98245a91e8fSMark Brown rdev_info(rdev, "Bringing %duV into %d-%duV\n", 98345a91e8fSMark Brown current_uV, target_min, target_max); 984064d5cd1SAlban Bedel ret = _regulator_do_set_voltage( 985fa93fd4eSMark Brown rdev, target_min, target_max); 986af5866c9SMark Brown if (ret < 0) { 987064d5cd1SAlban Bedel rdev_err(rdev, 988fa93fd4eSMark Brown "failed to apply %d-%duV constraint(%d)\n", 989fa93fd4eSMark Brown target_min, target_max, ret); 990af5866c9SMark Brown return ret; 991af5866c9SMark Brown } 992af5866c9SMark Brown } 993064d5cd1SAlban Bedel } 994e79055d6SMark Brown 995e79055d6SMark Brown /* constrain machine-level voltage specs to fit 996e79055d6SMark Brown * the actual range supported by this regulator. 997e79055d6SMark Brown */ 998e79055d6SMark Brown if (ops->list_voltage && rdev->desc->n_voltages) { 999e79055d6SMark Brown int count = rdev->desc->n_voltages; 1000e79055d6SMark Brown int i; 1001e79055d6SMark Brown int min_uV = INT_MAX; 1002e79055d6SMark Brown int max_uV = INT_MIN; 1003e79055d6SMark Brown int cmin = constraints->min_uV; 1004e79055d6SMark Brown int cmax = constraints->max_uV; 1005e79055d6SMark Brown 1006e79055d6SMark Brown /* it's safe to autoconfigure fixed-voltage supplies 1007e79055d6SMark Brown and the constraints are used by list_voltage. */ 1008e79055d6SMark Brown if (count == 1 && !cmin) { 1009e79055d6SMark Brown cmin = 1; 1010e79055d6SMark Brown cmax = INT_MAX; 1011e79055d6SMark Brown constraints->min_uV = cmin; 1012e79055d6SMark Brown constraints->max_uV = cmax; 1013e79055d6SMark Brown } 1014e79055d6SMark Brown 1015e79055d6SMark Brown /* voltage constraints are optional */ 1016e79055d6SMark Brown if ((cmin == 0) && (cmax == 0)) 1017e79055d6SMark Brown return 0; 1018e79055d6SMark Brown 1019e79055d6SMark Brown /* else require explicit machine-level constraints */ 1020e79055d6SMark Brown if (cmin <= 0 || cmax <= 0 || cmax < cmin) { 10215da84fd9SJoe Perches rdev_err(rdev, "invalid voltage constraints\n"); 1022e79055d6SMark Brown return -EINVAL; 1023e79055d6SMark Brown } 1024e79055d6SMark Brown 1025e79055d6SMark Brown /* initial: [cmin..cmax] valid, [min_uV..max_uV] not */ 1026e79055d6SMark Brown for (i = 0; i < count; i++) { 1027e79055d6SMark Brown int value; 1028e79055d6SMark Brown 1029e79055d6SMark Brown value = ops->list_voltage(rdev, i); 1030e79055d6SMark Brown if (value <= 0) 1031e79055d6SMark Brown continue; 1032e79055d6SMark Brown 1033e79055d6SMark Brown /* maybe adjust [min_uV..max_uV] */ 1034e79055d6SMark Brown if (value >= cmin && value < min_uV) 1035e79055d6SMark Brown min_uV = value; 1036e79055d6SMark Brown if (value <= cmax && value > max_uV) 1037e79055d6SMark Brown max_uV = value; 1038e79055d6SMark Brown } 1039e79055d6SMark Brown 1040e79055d6SMark Brown /* final: [min_uV..max_uV] valid iff constraints valid */ 1041e79055d6SMark Brown if (max_uV < min_uV) { 1042fff15befSMark Brown rdev_err(rdev, 1043fff15befSMark Brown "unsupportable voltage constraints %u-%uuV\n", 1044fff15befSMark Brown min_uV, max_uV); 1045e79055d6SMark Brown return -EINVAL; 1046e79055d6SMark Brown } 1047e79055d6SMark Brown 1048e79055d6SMark Brown /* use regulator's subset of machine constraints */ 1049e79055d6SMark Brown if (constraints->min_uV < min_uV) { 10505da84fd9SJoe Perches rdev_dbg(rdev, "override min_uV, %d -> %d\n", 10515da84fd9SJoe Perches constraints->min_uV, min_uV); 1052e79055d6SMark Brown constraints->min_uV = min_uV; 1053e79055d6SMark Brown } 1054e79055d6SMark Brown if (constraints->max_uV > max_uV) { 10555da84fd9SJoe Perches rdev_dbg(rdev, "override max_uV, %d -> %d\n", 10565da84fd9SJoe Perches constraints->max_uV, max_uV); 1057e79055d6SMark Brown constraints->max_uV = max_uV; 1058e79055d6SMark Brown } 1059e79055d6SMark Brown } 1060e79055d6SMark Brown 1061e79055d6SMark Brown return 0; 1062e79055d6SMark Brown } 1063e79055d6SMark Brown 1064f8c1700dSLaxman Dewangan static int machine_constraints_current(struct regulator_dev *rdev, 1065f8c1700dSLaxman Dewangan struct regulation_constraints *constraints) 1066f8c1700dSLaxman Dewangan { 1067272e2315SGuodong Xu const struct regulator_ops *ops = rdev->desc->ops; 1068f8c1700dSLaxman Dewangan int ret; 1069f8c1700dSLaxman Dewangan 1070f8c1700dSLaxman Dewangan if (!constraints->min_uA && !constraints->max_uA) 1071f8c1700dSLaxman Dewangan return 0; 1072f8c1700dSLaxman Dewangan 1073f8c1700dSLaxman Dewangan if (constraints->min_uA > constraints->max_uA) { 1074f8c1700dSLaxman Dewangan rdev_err(rdev, "Invalid current constraints\n"); 1075f8c1700dSLaxman Dewangan return -EINVAL; 1076f8c1700dSLaxman Dewangan } 1077f8c1700dSLaxman Dewangan 1078f8c1700dSLaxman Dewangan if (!ops->set_current_limit || !ops->get_current_limit) { 1079f8c1700dSLaxman Dewangan rdev_warn(rdev, "Operation of current configuration missing\n"); 1080f8c1700dSLaxman Dewangan return 0; 1081f8c1700dSLaxman Dewangan } 1082f8c1700dSLaxman Dewangan 1083f8c1700dSLaxman Dewangan /* Set regulator current in constraints range */ 1084f8c1700dSLaxman Dewangan ret = ops->set_current_limit(rdev, constraints->min_uA, 1085f8c1700dSLaxman Dewangan constraints->max_uA); 1086f8c1700dSLaxman Dewangan if (ret < 0) { 1087f8c1700dSLaxman Dewangan rdev_err(rdev, "Failed to set current constraint, %d\n", ret); 1088f8c1700dSLaxman Dewangan return ret; 1089f8c1700dSLaxman Dewangan } 1090f8c1700dSLaxman Dewangan 1091f8c1700dSLaxman Dewangan return 0; 1092f8c1700dSLaxman Dewangan } 1093f8c1700dSLaxman Dewangan 109430c21971SMarkus Pargmann static int _regulator_do_enable(struct regulator_dev *rdev); 109530c21971SMarkus Pargmann 1096a5766f11SLiam Girdwood /** 1097a5766f11SLiam Girdwood * set_machine_constraints - sets regulator constraints 109869279fb9SMark Brown * @rdev: regulator source 1099c8e7e464SMark Brown * @constraints: constraints to apply 1100a5766f11SLiam Girdwood * 1101a5766f11SLiam Girdwood * Allows platform initialisation code to define and constrain 1102a5766f11SLiam Girdwood * regulator circuits e.g. valid voltage/current ranges, etc. NOTE: 1103a5766f11SLiam Girdwood * Constraints *must* be set by platform code in order for some 1104a5766f11SLiam Girdwood * regulator operations to proceed i.e. set_voltage, set_current_limit, 1105a5766f11SLiam Girdwood * set_mode. 1106a5766f11SLiam Girdwood */ 1107a5766f11SLiam Girdwood static int set_machine_constraints(struct regulator_dev *rdev, 1108f8c12fe3SMark Brown const struct regulation_constraints *constraints) 1109a5766f11SLiam Girdwood { 1110a5766f11SLiam Girdwood int ret = 0; 1111272e2315SGuodong Xu const struct regulator_ops *ops = rdev->desc->ops; 1112e06f5b4fSMark Brown 11139a8f5e07SMark Brown if (constraints) 1114f8c12fe3SMark Brown rdev->constraints = kmemdup(constraints, sizeof(*constraints), 1115f8c12fe3SMark Brown GFP_KERNEL); 11169a8f5e07SMark Brown else 11179a8f5e07SMark Brown rdev->constraints = kzalloc(sizeof(*constraints), 11189a8f5e07SMark Brown GFP_KERNEL); 1119f8c12fe3SMark Brown if (!rdev->constraints) 1120f8c12fe3SMark Brown return -ENOMEM; 1121af5866c9SMark Brown 1122f8c12fe3SMark Brown ret = machine_constraints_voltage(rdev, rdev->constraints); 1123e79055d6SMark Brown if (ret != 0) 11246333ef46SCharles Keepax return ret; 11253e2b9abdSMark Brown 1126f8c1700dSLaxman Dewangan ret = machine_constraints_current(rdev, rdev->constraints); 1127f8c1700dSLaxman Dewangan if (ret != 0) 11286333ef46SCharles Keepax return ret; 1129f8c1700dSLaxman Dewangan 113036e4f839SStephen Boyd if (rdev->constraints->ilim_uA && ops->set_input_current_limit) { 113136e4f839SStephen Boyd ret = ops->set_input_current_limit(rdev, 113236e4f839SStephen Boyd rdev->constraints->ilim_uA); 113336e4f839SStephen Boyd if (ret < 0) { 113436e4f839SStephen Boyd rdev_err(rdev, "failed to set input limit\n"); 11356333ef46SCharles Keepax return ret; 113636e4f839SStephen Boyd } 113736e4f839SStephen Boyd } 113836e4f839SStephen Boyd 1139a5766f11SLiam Girdwood /* do we need to setup our suspend state */ 11409a8f5e07SMark Brown if (rdev->constraints->initial_state) { 1141f7efad10SChunyan Zhang ret = suspend_set_state(rdev, rdev->constraints->initial_state); 1142e06f5b4fSMark Brown if (ret < 0) { 11435da84fd9SJoe Perches rdev_err(rdev, "failed to set suspend state\n"); 11446333ef46SCharles Keepax return ret; 1145e06f5b4fSMark Brown } 1146e06f5b4fSMark Brown } 1147a5766f11SLiam Girdwood 11489a8f5e07SMark Brown if (rdev->constraints->initial_mode) { 1149a308466cSMark Brown if (!ops->set_mode) { 11505da84fd9SJoe Perches rdev_err(rdev, "no set_mode operation\n"); 11516333ef46SCharles Keepax return -EINVAL; 1152a308466cSMark Brown } 1153a308466cSMark Brown 1154f8c12fe3SMark Brown ret = ops->set_mode(rdev, rdev->constraints->initial_mode); 1155a308466cSMark Brown if (ret < 0) { 11565da84fd9SJoe Perches rdev_err(rdev, "failed to set initial mode: %d\n", ret); 11576333ef46SCharles Keepax return ret; 1158a308466cSMark Brown } 1159a308466cSMark Brown } 1160a308466cSMark Brown 1161cacf90f2SMark Brown /* If the constraints say the regulator should be on at this point 1162cacf90f2SMark Brown * and we have control then make sure it is enabled. 1163cacf90f2SMark Brown */ 116430c21971SMarkus Pargmann if (rdev->constraints->always_on || rdev->constraints->boot_on) { 116530c21971SMarkus Pargmann ret = _regulator_do_enable(rdev); 116630c21971SMarkus Pargmann if (ret < 0 && ret != -EINVAL) { 11675da84fd9SJoe Perches rdev_err(rdev, "failed to enable\n"); 11686333ef46SCharles Keepax return ret; 1169e5fda26cSMark Brown } 1170e5fda26cSMark Brown } 1171e5fda26cSMark Brown 11721653ccf4SYadwinder Singh Brar if ((rdev->constraints->ramp_delay || rdev->constraints->ramp_disable) 11731653ccf4SYadwinder Singh Brar && ops->set_ramp_delay) { 11746f0b2c69SYadwinder Singh Brar ret = ops->set_ramp_delay(rdev, rdev->constraints->ramp_delay); 11756f0b2c69SYadwinder Singh Brar if (ret < 0) { 11766f0b2c69SYadwinder Singh Brar rdev_err(rdev, "failed to set ramp_delay\n"); 11776333ef46SCharles Keepax return ret; 11786f0b2c69SYadwinder Singh Brar } 11796f0b2c69SYadwinder Singh Brar } 11806f0b2c69SYadwinder Singh Brar 118123c779b9SStephen Boyd if (rdev->constraints->pull_down && ops->set_pull_down) { 118223c779b9SStephen Boyd ret = ops->set_pull_down(rdev); 118323c779b9SStephen Boyd if (ret < 0) { 118423c779b9SStephen Boyd rdev_err(rdev, "failed to set pull down\n"); 11856333ef46SCharles Keepax return ret; 118623c779b9SStephen Boyd } 118723c779b9SStephen Boyd } 118823c779b9SStephen Boyd 118957f66b78SStephen Boyd if (rdev->constraints->soft_start && ops->set_soft_start) { 119057f66b78SStephen Boyd ret = ops->set_soft_start(rdev); 119157f66b78SStephen Boyd if (ret < 0) { 119257f66b78SStephen Boyd rdev_err(rdev, "failed to set soft start\n"); 11936333ef46SCharles Keepax return ret; 119457f66b78SStephen Boyd } 119557f66b78SStephen Boyd } 119657f66b78SStephen Boyd 11973a003baeSStephen Boyd if (rdev->constraints->over_current_protection 11983a003baeSStephen Boyd && ops->set_over_current_protection) { 11993a003baeSStephen Boyd ret = ops->set_over_current_protection(rdev); 12003a003baeSStephen Boyd if (ret < 0) { 12013a003baeSStephen Boyd rdev_err(rdev, "failed to set over current protection\n"); 12026333ef46SCharles Keepax return ret; 12033a003baeSStephen Boyd } 12043a003baeSStephen Boyd } 12053a003baeSStephen Boyd 1206670666b9SLaxman Dewangan if (rdev->constraints->active_discharge && ops->set_active_discharge) { 1207670666b9SLaxman Dewangan bool ad_state = (rdev->constraints->active_discharge == 1208670666b9SLaxman Dewangan REGULATOR_ACTIVE_DISCHARGE_ENABLE) ? true : false; 1209670666b9SLaxman Dewangan 1210670666b9SLaxman Dewangan ret = ops->set_active_discharge(rdev, ad_state); 1211670666b9SLaxman Dewangan if (ret < 0) { 1212670666b9SLaxman Dewangan rdev_err(rdev, "failed to set active discharge\n"); 1213670666b9SLaxman Dewangan return ret; 1214670666b9SLaxman Dewangan } 1215670666b9SLaxman Dewangan } 1216670666b9SLaxman Dewangan 1217a5766f11SLiam Girdwood print_constraints(rdev); 12181a6958e7SAxel Lin return 0; 1219a5766f11SLiam Girdwood } 1220a5766f11SLiam Girdwood 1221a5766f11SLiam Girdwood /** 1222a5766f11SLiam Girdwood * set_supply - set regulator supply regulator 122369279fb9SMark Brown * @rdev: regulator name 122469279fb9SMark Brown * @supply_rdev: supply regulator name 1225a5766f11SLiam Girdwood * 1226a5766f11SLiam Girdwood * Called by platform initialisation code to set the supply regulator for this 1227a5766f11SLiam Girdwood * regulator. This ensures that a regulators supply will also be enabled by the 1228a5766f11SLiam Girdwood * core if it's child is enabled. 1229a5766f11SLiam Girdwood */ 1230a5766f11SLiam Girdwood static int set_supply(struct regulator_dev *rdev, 1231a5766f11SLiam Girdwood struct regulator_dev *supply_rdev) 1232a5766f11SLiam Girdwood { 1233a5766f11SLiam Girdwood int err; 1234a5766f11SLiam Girdwood 12353801b86aSMark Brown rdev_info(rdev, "supplied by %s\n", rdev_get_name(supply_rdev)); 12363801b86aSMark Brown 1237e2c09ae7SJavier Martinez Canillas if (!try_module_get(supply_rdev->owner)) 1238e2c09ae7SJavier Martinez Canillas return -ENODEV; 1239e2c09ae7SJavier Martinez Canillas 12403801b86aSMark Brown rdev->supply = create_regulator(supply_rdev, &rdev->dev, "SUPPLY"); 124132c78de8SAxel Lin if (rdev->supply == NULL) { 124232c78de8SAxel Lin err = -ENOMEM; 1243a5766f11SLiam Girdwood return err; 1244a5766f11SLiam Girdwood } 124557ad526aSLaxman Dewangan supply_rdev->open_count++; 1246a5766f11SLiam Girdwood 12473801b86aSMark Brown return 0; 12483801b86aSMark Brown } 12493801b86aSMark Brown 1250a5766f11SLiam Girdwood /** 125106c63f93SRandy Dunlap * set_consumer_device_supply - Bind a regulator to a symbolic supply 125269279fb9SMark Brown * @rdev: regulator source 125340f9244fSMark Brown * @consumer_dev_name: dev_name() string for device supply applies to 1254a5766f11SLiam Girdwood * @supply: symbolic name for supply 1255a5766f11SLiam Girdwood * 1256a5766f11SLiam Girdwood * Allows platform initialisation code to map physical regulator 1257a5766f11SLiam Girdwood * sources to symbolic names for supplies for use by devices. Devices 1258a5766f11SLiam Girdwood * should use these symbolic names to request regulators, avoiding the 1259a5766f11SLiam Girdwood * need to provide board-specific regulator names as platform data. 1260a5766f11SLiam Girdwood */ 1261a5766f11SLiam Girdwood static int set_consumer_device_supply(struct regulator_dev *rdev, 1262737f360dSMark Brown const char *consumer_dev_name, 126340f9244fSMark Brown const char *supply) 1264a5766f11SLiam Girdwood { 1265a5766f11SLiam Girdwood struct regulator_map *node; 12669ed2099eSMark Brown int has_dev; 1267a5766f11SLiam Girdwood 1268a5766f11SLiam Girdwood if (supply == NULL) 1269a5766f11SLiam Girdwood return -EINVAL; 1270a5766f11SLiam Girdwood 12719ed2099eSMark Brown if (consumer_dev_name != NULL) 12729ed2099eSMark Brown has_dev = 1; 12739ed2099eSMark Brown else 12749ed2099eSMark Brown has_dev = 0; 12759ed2099eSMark Brown 12766001e13cSDavid Brownell list_for_each_entry(node, ®ulator_map_list, list) { 127723b5cc2aSJani Nikula if (node->dev_name && consumer_dev_name) { 127823b5cc2aSJani Nikula if (strcmp(node->dev_name, consumer_dev_name) != 0) 12796001e13cSDavid Brownell continue; 128023b5cc2aSJani Nikula } else if (node->dev_name || consumer_dev_name) { 128123b5cc2aSJani Nikula continue; 128223b5cc2aSJani Nikula } 128323b5cc2aSJani Nikula 12846001e13cSDavid Brownell if (strcmp(node->supply, supply) != 0) 12856001e13cSDavid Brownell continue; 12866001e13cSDavid Brownell 1287737f360dSMark Brown pr_debug("%s: %s/%s is '%s' supply; fail %s/%s\n", 1288737f360dSMark Brown consumer_dev_name, 12896001e13cSDavid Brownell dev_name(&node->regulator->dev), 12906001e13cSDavid Brownell node->regulator->desc->name, 12916001e13cSDavid Brownell supply, 12921083c393SMark Brown dev_name(&rdev->dev), rdev_get_name(rdev)); 12936001e13cSDavid Brownell return -EBUSY; 12946001e13cSDavid Brownell } 12956001e13cSDavid Brownell 12969ed2099eSMark Brown node = kzalloc(sizeof(struct regulator_map), GFP_KERNEL); 1297a5766f11SLiam Girdwood if (node == NULL) 1298a5766f11SLiam Girdwood return -ENOMEM; 1299a5766f11SLiam Girdwood 1300a5766f11SLiam Girdwood node->regulator = rdev; 1301a5766f11SLiam Girdwood node->supply = supply; 1302a5766f11SLiam Girdwood 13039ed2099eSMark Brown if (has_dev) { 13049ed2099eSMark Brown node->dev_name = kstrdup(consumer_dev_name, GFP_KERNEL); 130540f9244fSMark Brown if (node->dev_name == NULL) { 130640f9244fSMark Brown kfree(node); 130740f9244fSMark Brown return -ENOMEM; 130840f9244fSMark Brown } 13099ed2099eSMark Brown } 131040f9244fSMark Brown 1311a5766f11SLiam Girdwood list_add(&node->list, ®ulator_map_list); 1312a5766f11SLiam Girdwood return 0; 1313a5766f11SLiam Girdwood } 1314a5766f11SLiam Girdwood 13150f1d747bSMike Rapoport static void unset_regulator_supplies(struct regulator_dev *rdev) 13160f1d747bSMike Rapoport { 13170f1d747bSMike Rapoport struct regulator_map *node, *n; 13180f1d747bSMike Rapoport 13190f1d747bSMike Rapoport list_for_each_entry_safe(node, n, ®ulator_map_list, list) { 13200f1d747bSMike Rapoport if (rdev == node->regulator) { 13210f1d747bSMike Rapoport list_del(&node->list); 132240f9244fSMark Brown kfree(node->dev_name); 13230f1d747bSMike Rapoport kfree(node); 13240f1d747bSMike Rapoport } 13250f1d747bSMike Rapoport } 13260f1d747bSMike Rapoport } 13270f1d747bSMike Rapoport 13282d80a91bSRichard Fitzgerald #ifdef CONFIG_DEBUG_FS 13292d80a91bSRichard Fitzgerald static ssize_t constraint_flags_read_file(struct file *file, 13302d80a91bSRichard Fitzgerald char __user *user_buf, 13312d80a91bSRichard Fitzgerald size_t count, loff_t *ppos) 13322d80a91bSRichard Fitzgerald { 13332d80a91bSRichard Fitzgerald const struct regulator *regulator = file->private_data; 13342d80a91bSRichard Fitzgerald const struct regulation_constraints *c = regulator->rdev->constraints; 13352d80a91bSRichard Fitzgerald char *buf; 13362d80a91bSRichard Fitzgerald ssize_t ret; 13372d80a91bSRichard Fitzgerald 13382d80a91bSRichard Fitzgerald if (!c) 13392d80a91bSRichard Fitzgerald return 0; 13402d80a91bSRichard Fitzgerald 13412d80a91bSRichard Fitzgerald buf = kmalloc(PAGE_SIZE, GFP_KERNEL); 13422d80a91bSRichard Fitzgerald if (!buf) 13432d80a91bSRichard Fitzgerald return -ENOMEM; 13442d80a91bSRichard Fitzgerald 13452d80a91bSRichard Fitzgerald ret = snprintf(buf, PAGE_SIZE, 13462d80a91bSRichard Fitzgerald "always_on: %u\n" 13472d80a91bSRichard Fitzgerald "boot_on: %u\n" 13482d80a91bSRichard Fitzgerald "apply_uV: %u\n" 13492d80a91bSRichard Fitzgerald "ramp_disable: %u\n" 13502d80a91bSRichard Fitzgerald "soft_start: %u\n" 13512d80a91bSRichard Fitzgerald "pull_down: %u\n" 13522d80a91bSRichard Fitzgerald "over_current_protection: %u\n", 13532d80a91bSRichard Fitzgerald c->always_on, 13542d80a91bSRichard Fitzgerald c->boot_on, 13552d80a91bSRichard Fitzgerald c->apply_uV, 13562d80a91bSRichard Fitzgerald c->ramp_disable, 13572d80a91bSRichard Fitzgerald c->soft_start, 13582d80a91bSRichard Fitzgerald c->pull_down, 13592d80a91bSRichard Fitzgerald c->over_current_protection); 13602d80a91bSRichard Fitzgerald 13612d80a91bSRichard Fitzgerald ret = simple_read_from_buffer(user_buf, count, ppos, buf, ret); 13622d80a91bSRichard Fitzgerald kfree(buf); 13632d80a91bSRichard Fitzgerald 13642d80a91bSRichard Fitzgerald return ret; 13652d80a91bSRichard Fitzgerald } 13662d80a91bSRichard Fitzgerald 13672d80a91bSRichard Fitzgerald #endif 13682d80a91bSRichard Fitzgerald 13692d80a91bSRichard Fitzgerald static const struct file_operations constraint_flags_fops = { 13702d80a91bSRichard Fitzgerald #ifdef CONFIG_DEBUG_FS 13712d80a91bSRichard Fitzgerald .open = simple_open, 13722d80a91bSRichard Fitzgerald .read = constraint_flags_read_file, 13732d80a91bSRichard Fitzgerald .llseek = default_llseek, 13742d80a91bSRichard Fitzgerald #endif 13752d80a91bSRichard Fitzgerald }; 13762d80a91bSRichard Fitzgerald 1377f5726ae3SMark Brown #define REG_STR_SIZE 64 1378414c70cbSLiam Girdwood 1379414c70cbSLiam Girdwood static struct regulator *create_regulator(struct regulator_dev *rdev, 1380414c70cbSLiam Girdwood struct device *dev, 1381414c70cbSLiam Girdwood const char *supply_name) 1382414c70cbSLiam Girdwood { 1383414c70cbSLiam Girdwood struct regulator *regulator; 1384414c70cbSLiam Girdwood char buf[REG_STR_SIZE]; 1385414c70cbSLiam Girdwood int err, size; 1386414c70cbSLiam Girdwood 1387414c70cbSLiam Girdwood regulator = kzalloc(sizeof(*regulator), GFP_KERNEL); 1388414c70cbSLiam Girdwood if (regulator == NULL) 1389414c70cbSLiam Girdwood return NULL; 1390414c70cbSLiam Girdwood 139166cf9a7eSMaciej Purski regulator_lock(rdev); 1392414c70cbSLiam Girdwood regulator->rdev = rdev; 1393414c70cbSLiam Girdwood list_add(®ulator->list, &rdev->consumer_list); 1394414c70cbSLiam Girdwood 1395414c70cbSLiam Girdwood if (dev) { 1396e2c98eafSShawn Guo regulator->dev = dev; 1397e2c98eafSShawn Guo 1398222cc7b1SMark Brown /* Add a link to the device sysfs entry */ 1399b7cd1b13SBartosz Golaszewski size = snprintf(buf, REG_STR_SIZE, "%s-%s", 1400414c70cbSLiam Girdwood dev->kobj.name, supply_name); 1401414c70cbSLiam Girdwood if (size >= REG_STR_SIZE) 1402222cc7b1SMark Brown goto overflow_err; 1403414c70cbSLiam Girdwood 1404414c70cbSLiam Girdwood regulator->supply_name = kstrdup(buf, GFP_KERNEL); 1405414c70cbSLiam Girdwood if (regulator->supply_name == NULL) 1406222cc7b1SMark Brown goto overflow_err; 1407414c70cbSLiam Girdwood 1408ff268b56SStephen Boyd err = sysfs_create_link_nowarn(&rdev->dev.kobj, &dev->kobj, 1409414c70cbSLiam Girdwood buf); 1410414c70cbSLiam Girdwood if (err) { 1411ff268b56SStephen Boyd rdev_dbg(rdev, "could not add device link %s err %d\n", 14121d7372e1SDaniel Walker dev->kobj.name, err); 1413222cc7b1SMark Brown /* non-fatal */ 1414414c70cbSLiam Girdwood } 14155de70519SMark Brown } else { 14160630b614SStephen Boyd regulator->supply_name = kstrdup_const(supply_name, GFP_KERNEL); 14175de70519SMark Brown if (regulator->supply_name == NULL) 1418222cc7b1SMark Brown goto overflow_err; 1419414c70cbSLiam Girdwood } 14205de70519SMark Brown 14215de70519SMark Brown regulator->debugfs = debugfs_create_dir(regulator->supply_name, 14225de70519SMark Brown rdev->debugfs); 142324751434SStephen Boyd if (!regulator->debugfs) { 1424ad3a942bSStephen Boyd rdev_dbg(rdev, "Failed to create debugfs directory\n"); 14255de70519SMark Brown } else { 14265de70519SMark Brown debugfs_create_u32("uA_load", 0444, regulator->debugfs, 14275de70519SMark Brown ®ulator->uA_load); 14285de70519SMark Brown debugfs_create_u32("min_uV", 0444, regulator->debugfs, 1429c360a6dfSChunyan Zhang ®ulator->voltage[PM_SUSPEND_ON].min_uV); 14305de70519SMark Brown debugfs_create_u32("max_uV", 0444, regulator->debugfs, 1431c360a6dfSChunyan Zhang ®ulator->voltage[PM_SUSPEND_ON].max_uV); 14322d80a91bSRichard Fitzgerald debugfs_create_file("constraint_flags", 0444, 14332d80a91bSRichard Fitzgerald regulator->debugfs, regulator, 14342d80a91bSRichard Fitzgerald &constraint_flags_fops); 14355de70519SMark Brown } 14365de70519SMark Brown 14376492bc1bSMark Brown /* 14386492bc1bSMark Brown * Check now if the regulator is an always on regulator - if 14396492bc1bSMark Brown * it is then we don't need to do nearly so much work for 14406492bc1bSMark Brown * enable/disable calls. 14416492bc1bSMark Brown */ 14428a34e979SWEN Pingbo if (!regulator_ops_is_valid(rdev, REGULATOR_CHANGE_STATUS) && 14436492bc1bSMark Brown _regulator_is_enabled(rdev)) 14446492bc1bSMark Brown regulator->always_on = true; 14456492bc1bSMark Brown 144666cf9a7eSMaciej Purski regulator_unlock(rdev); 1447414c70cbSLiam Girdwood return regulator; 1448414c70cbSLiam Girdwood overflow_err: 1449414c70cbSLiam Girdwood list_del(®ulator->list); 1450414c70cbSLiam Girdwood kfree(regulator); 145166cf9a7eSMaciej Purski regulator_unlock(rdev); 1452414c70cbSLiam Girdwood return NULL; 1453414c70cbSLiam Girdwood } 1454414c70cbSLiam Girdwood 145531aae2beSMark Brown static int _regulator_get_enable_time(struct regulator_dev *rdev) 145631aae2beSMark Brown { 145700c877c6SLaxman Dewangan if (rdev->constraints && rdev->constraints->enable_time) 145800c877c6SLaxman Dewangan return rdev->constraints->enable_time; 145931aae2beSMark Brown if (!rdev->desc->ops->enable_time) 146079511ed3SMark Brown return rdev->desc->enable_time; 146131aae2beSMark Brown return rdev->desc->ops->enable_time(rdev); 146231aae2beSMark Brown } 146331aae2beSMark Brown 1464a06ccd9cSCharles Keepax static struct regulator_supply_alias *regulator_find_supply_alias( 1465a06ccd9cSCharles Keepax struct device *dev, const char *supply) 1466a06ccd9cSCharles Keepax { 1467a06ccd9cSCharles Keepax struct regulator_supply_alias *map; 1468a06ccd9cSCharles Keepax 1469a06ccd9cSCharles Keepax list_for_each_entry(map, ®ulator_supply_alias_list, list) 1470a06ccd9cSCharles Keepax if (map->src_dev == dev && strcmp(map->src_supply, supply) == 0) 1471a06ccd9cSCharles Keepax return map; 1472a06ccd9cSCharles Keepax 1473a06ccd9cSCharles Keepax return NULL; 1474a06ccd9cSCharles Keepax } 1475a06ccd9cSCharles Keepax 1476a06ccd9cSCharles Keepax static void regulator_supply_alias(struct device **dev, const char **supply) 1477a06ccd9cSCharles Keepax { 1478a06ccd9cSCharles Keepax struct regulator_supply_alias *map; 1479a06ccd9cSCharles Keepax 1480a06ccd9cSCharles Keepax map = regulator_find_supply_alias(*dev, *supply); 1481a06ccd9cSCharles Keepax if (map) { 1482a06ccd9cSCharles Keepax dev_dbg(*dev, "Mapping supply %s to %s,%s\n", 1483a06ccd9cSCharles Keepax *supply, map->alias_supply, 1484a06ccd9cSCharles Keepax dev_name(map->alias_dev)); 1485a06ccd9cSCharles Keepax *dev = map->alias_dev; 1486a06ccd9cSCharles Keepax *supply = map->alias_supply; 1487a06ccd9cSCharles Keepax } 1488a06ccd9cSCharles Keepax } 1489a06ccd9cSCharles Keepax 149085f3b431STomeu Vizoso static int regulator_match(struct device *dev, const void *data) 149185f3b431STomeu Vizoso { 149285f3b431STomeu Vizoso struct regulator_dev *r = dev_to_rdev(dev); 149385f3b431STomeu Vizoso 149485f3b431STomeu Vizoso return strcmp(rdev_get_name(r), data) == 0; 149585f3b431STomeu Vizoso } 149685f3b431STomeu Vizoso 149785f3b431STomeu Vizoso static struct regulator_dev *regulator_lookup_by_name(const char *name) 149885f3b431STomeu Vizoso { 149985f3b431STomeu Vizoso struct device *dev; 150085f3b431STomeu Vizoso 150185f3b431STomeu Vizoso dev = class_find_device(®ulator_class, NULL, name, regulator_match); 150285f3b431STomeu Vizoso 150385f3b431STomeu Vizoso return dev ? dev_to_rdev(dev) : NULL; 150485f3b431STomeu Vizoso } 150585f3b431STomeu Vizoso 150685f3b431STomeu Vizoso /** 150785f3b431STomeu Vizoso * regulator_dev_lookup - lookup a regulator device. 150885f3b431STomeu Vizoso * @dev: device for regulator "consumer". 150985f3b431STomeu Vizoso * @supply: Supply name or regulator ID. 151085f3b431STomeu Vizoso * 151185f3b431STomeu Vizoso * If successful, returns a struct regulator_dev that corresponds to the name 1512163478daSDmitry Torokhov * @supply and with the embedded struct device refcount incremented by one. 1513163478daSDmitry Torokhov * The refcount must be dropped by calling put_device(). 1514163478daSDmitry Torokhov * On failure one of the following ERR-PTR-encoded values is returned: 1515163478daSDmitry Torokhov * -ENODEV if lookup fails permanently, -EPROBE_DEFER if lookup could succeed 1516163478daSDmitry Torokhov * in the future. 151785f3b431STomeu Vizoso */ 151869511a45SRajendra Nayak static struct regulator_dev *regulator_dev_lookup(struct device *dev, 1519163478daSDmitry Torokhov const char *supply) 152069511a45SRajendra Nayak { 152106217197SCharles Keepax struct regulator_dev *r = NULL; 152269511a45SRajendra Nayak struct device_node *node; 1523576ca436SMark Brown struct regulator_map *map; 1524576ca436SMark Brown const char *devname = NULL; 152569511a45SRajendra Nayak 1526a06ccd9cSCharles Keepax regulator_supply_alias(&dev, &supply); 1527a06ccd9cSCharles Keepax 152869511a45SRajendra Nayak /* first do a dt based lookup */ 152969511a45SRajendra Nayak if (dev && dev->of_node) { 153069511a45SRajendra Nayak node = of_get_regulator(dev, supply); 15316d191a5fSMark Brown if (node) { 153285f3b431STomeu Vizoso r = of_find_regulator_by_node(node); 153385f3b431STomeu Vizoso if (r) 153469511a45SRajendra Nayak return r; 1535163478daSDmitry Torokhov 15366d191a5fSMark Brown /* 1537163478daSDmitry Torokhov * We have a node, but there is no device. 1538163478daSDmitry Torokhov * assume it has not registered yet. 15396d191a5fSMark Brown */ 1540163478daSDmitry Torokhov return ERR_PTR(-EPROBE_DEFER); 15416d191a5fSMark Brown } 154269511a45SRajendra Nayak } 154369511a45SRajendra Nayak 154469511a45SRajendra Nayak /* if not found, try doing it non-dt way */ 1545576ca436SMark Brown if (dev) 1546576ca436SMark Brown devname = dev_name(dev); 1547576ca436SMark Brown 154885f3b431STomeu Vizoso mutex_lock(®ulator_list_mutex); 1549576ca436SMark Brown list_for_each_entry(map, ®ulator_map_list, list) { 1550576ca436SMark Brown /* If the mapping has a device set up it must match */ 1551576ca436SMark Brown if (map->dev_name && 1552576ca436SMark Brown (!devname || strcmp(map->dev_name, devname))) 1553576ca436SMark Brown continue; 1554576ca436SMark Brown 155585f3b431STomeu Vizoso if (strcmp(map->supply, supply) == 0 && 155685f3b431STomeu Vizoso get_device(&map->regulator->dev)) { 1557163478daSDmitry Torokhov r = map->regulator; 1558163478daSDmitry Torokhov break; 1559576ca436SMark Brown } 156085f3b431STomeu Vizoso } 156185f3b431STomeu Vizoso mutex_unlock(®ulator_list_mutex); 1562576ca436SMark Brown 1563163478daSDmitry Torokhov if (r) 1564163478daSDmitry Torokhov return r; 1565163478daSDmitry Torokhov 156606217197SCharles Keepax r = regulator_lookup_by_name(supply); 156706217197SCharles Keepax if (r) 156806217197SCharles Keepax return r; 156906217197SCharles Keepax 1570163478daSDmitry Torokhov return ERR_PTR(-ENODEV); 157169511a45SRajendra Nayak } 157269511a45SRajendra Nayak 15736261b06dSBjorn Andersson static int regulator_resolve_supply(struct regulator_dev *rdev) 15746261b06dSBjorn Andersson { 15756261b06dSBjorn Andersson struct regulator_dev *r; 15766261b06dSBjorn Andersson struct device *dev = rdev->dev.parent; 15776261b06dSBjorn Andersson int ret; 15786261b06dSBjorn Andersson 15796261b06dSBjorn Andersson /* No supply to resovle? */ 15806261b06dSBjorn Andersson if (!rdev->supply_name) 15816261b06dSBjorn Andersson return 0; 15826261b06dSBjorn Andersson 15836261b06dSBjorn Andersson /* Supply already resolved? */ 15846261b06dSBjorn Andersson if (rdev->supply) 15856261b06dSBjorn Andersson return 0; 15866261b06dSBjorn Andersson 1587163478daSDmitry Torokhov r = regulator_dev_lookup(dev, rdev->supply_name); 1588163478daSDmitry Torokhov if (IS_ERR(r)) { 1589163478daSDmitry Torokhov ret = PTR_ERR(r); 1590163478daSDmitry Torokhov 159106423121SMark Brown /* Did the lookup explicitly defer for us? */ 159206423121SMark Brown if (ret == -EPROBE_DEFER) 159306423121SMark Brown return ret; 159406423121SMark Brown 15959f7e25edSMark Brown if (have_full_constraints()) { 15969f7e25edSMark Brown r = dummy_regulator_rdev; 159785f3b431STomeu Vizoso get_device(&r->dev); 15989f7e25edSMark Brown } else { 15996261b06dSBjorn Andersson dev_err(dev, "Failed to resolve %s-supply for %s\n", 16006261b06dSBjorn Andersson rdev->supply_name, rdev->desc->name); 16016261b06dSBjorn Andersson return -EPROBE_DEFER; 16026261b06dSBjorn Andersson } 16039f7e25edSMark Brown } 16046261b06dSBjorn Andersson 160566d228a2SJon Hunter /* 160666d228a2SJon Hunter * If the supply's parent device is not the same as the 160766d228a2SJon Hunter * regulator's parent device, then ensure the parent device 160866d228a2SJon Hunter * is bound before we resolve the supply, in case the parent 160966d228a2SJon Hunter * device get probe deferred and unregisters the supply. 161066d228a2SJon Hunter */ 161166d228a2SJon Hunter if (r->dev.parent && r->dev.parent != rdev->dev.parent) { 161266d228a2SJon Hunter if (!device_is_bound(r->dev.parent)) { 161366d228a2SJon Hunter put_device(&r->dev); 161466d228a2SJon Hunter return -EPROBE_DEFER; 161566d228a2SJon Hunter } 161666d228a2SJon Hunter } 161766d228a2SJon Hunter 16186261b06dSBjorn Andersson /* Recursively resolve the supply of the supply */ 16196261b06dSBjorn Andersson ret = regulator_resolve_supply(r); 162085f3b431STomeu Vizoso if (ret < 0) { 162185f3b431STomeu Vizoso put_device(&r->dev); 16226261b06dSBjorn Andersson return ret; 162385f3b431STomeu Vizoso } 16246261b06dSBjorn Andersson 16256261b06dSBjorn Andersson ret = set_supply(rdev, r); 162685f3b431STomeu Vizoso if (ret < 0) { 162785f3b431STomeu Vizoso put_device(&r->dev); 16286261b06dSBjorn Andersson return ret; 162985f3b431STomeu Vizoso } 16306261b06dSBjorn Andersson 16316261b06dSBjorn Andersson /* Cascade always-on state to supply */ 163295a293c7SJavier Martinez Canillas if (_regulator_is_enabled(rdev)) { 16336261b06dSBjorn Andersson ret = regulator_enable(rdev->supply); 163436a1f1b6SJavier Martinez Canillas if (ret < 0) { 163536a1f1b6SJavier Martinez Canillas _regulator_put(rdev->supply); 16368e5356a7SJon Hunter rdev->supply = NULL; 16376261b06dSBjorn Andersson return ret; 16386261b06dSBjorn Andersson } 163936a1f1b6SJavier Martinez Canillas } 16406261b06dSBjorn Andersson 16416261b06dSBjorn Andersson return 0; 16426261b06dSBjorn Andersson } 16436261b06dSBjorn Andersson 16445ffbd136SMark Brown /* Internal regulator request function */ 1645a8bd42a9SDmitry Torokhov struct regulator *_regulator_get(struct device *dev, const char *id, 1646a8bd42a9SDmitry Torokhov enum regulator_get_type get_type) 1647414c70cbSLiam Girdwood { 1648414c70cbSLiam Girdwood struct regulator_dev *rdev; 16497d245afaSDmitry Torokhov struct regulator *regulator; 1650a4d7641fSDmitry Torokhov const char *devname = dev ? dev_name(dev) : "deviceless"; 1651317b5684SMark Brown int ret; 1652414c70cbSLiam Girdwood 1653a8bd42a9SDmitry Torokhov if (get_type >= MAX_GET_TYPE) { 1654a8bd42a9SDmitry Torokhov dev_err(dev, "invalid type %d in %s\n", get_type, __func__); 1655a8bd42a9SDmitry Torokhov return ERR_PTR(-EINVAL); 1656a8bd42a9SDmitry Torokhov } 1657a8bd42a9SDmitry Torokhov 1658414c70cbSLiam Girdwood if (id == NULL) { 16595da84fd9SJoe Perches pr_err("get() with no identifier\n"); 1660043c998fSMark Brown return ERR_PTR(-EINVAL); 1661414c70cbSLiam Girdwood } 1662414c70cbSLiam Girdwood 1663163478daSDmitry Torokhov rdev = regulator_dev_lookup(dev, id); 1664a4d7641fSDmitry Torokhov if (IS_ERR(rdev)) { 1665163478daSDmitry Torokhov ret = PTR_ERR(rdev); 1666ef60abbbSMark Brown 16671e4b545cSNishanth Menon /* 1668a4d7641fSDmitry Torokhov * If regulator_dev_lookup() fails with error other 1669a4d7641fSDmitry Torokhov * than -ENODEV our job here is done, we simply return it. 16701e4b545cSNishanth Menon */ 1671a4d7641fSDmitry Torokhov if (ret != -ENODEV) 1672a4d7641fSDmitry Torokhov return ERR_PTR(ret); 16731e4b545cSNishanth Menon 1674a4d7641fSDmitry Torokhov if (!have_full_constraints()) { 1675a4d7641fSDmitry Torokhov dev_warn(dev, 1676a4d7641fSDmitry Torokhov "incomplete constraints, dummy supplies not allowed\n"); 1677a4d7641fSDmitry Torokhov return ERR_PTR(-ENODEV); 167834abbd68SMark Brown } 167934abbd68SMark Brown 1680a4d7641fSDmitry Torokhov switch (get_type) { 1681a4d7641fSDmitry Torokhov case NORMAL_GET: 1682a4d7641fSDmitry Torokhov /* 1683a4d7641fSDmitry Torokhov * Assume that a regulator is physically present and 1684a4d7641fSDmitry Torokhov * enabled, even if it isn't hooked up, and just 1685a4d7641fSDmitry Torokhov * provide a dummy. 1686a4d7641fSDmitry Torokhov */ 1687a4d7641fSDmitry Torokhov dev_warn(dev, 1688a4d7641fSDmitry Torokhov "%s supply %s not found, using dummy regulator\n", 1689a4d7641fSDmitry Torokhov devname, id); 1690a4d7641fSDmitry Torokhov rdev = dummy_regulator_rdev; 1691a4d7641fSDmitry Torokhov get_device(&rdev->dev); 1692a4d7641fSDmitry Torokhov break; 1693414c70cbSLiam Girdwood 1694a4d7641fSDmitry Torokhov case EXCLUSIVE_GET: 1695a4d7641fSDmitry Torokhov dev_warn(dev, 1696a4d7641fSDmitry Torokhov "dummy supplies not allowed for exclusive requests\n"); 1697a4d7641fSDmitry Torokhov /* fall through */ 1698a4d7641fSDmitry Torokhov 1699a4d7641fSDmitry Torokhov default: 1700a4d7641fSDmitry Torokhov return ERR_PTR(-ENODEV); 1701a4d7641fSDmitry Torokhov } 1702a4d7641fSDmitry Torokhov } 1703a4d7641fSDmitry Torokhov 17045ffbd136SMark Brown if (rdev->exclusive) { 17055ffbd136SMark Brown regulator = ERR_PTR(-EPERM); 170685f3b431STomeu Vizoso put_device(&rdev->dev); 170785f3b431STomeu Vizoso return regulator; 17085ffbd136SMark Brown } 17095ffbd136SMark Brown 1710a8bd42a9SDmitry Torokhov if (get_type == EXCLUSIVE_GET && rdev->open_count) { 17115ffbd136SMark Brown regulator = ERR_PTR(-EBUSY); 171285f3b431STomeu Vizoso put_device(&rdev->dev); 171385f3b431STomeu Vizoso return regulator; 17145ffbd136SMark Brown } 17155ffbd136SMark Brown 17166261b06dSBjorn Andersson ret = regulator_resolve_supply(rdev); 17176261b06dSBjorn Andersson if (ret < 0) { 17186261b06dSBjorn Andersson regulator = ERR_PTR(ret); 171985f3b431STomeu Vizoso put_device(&rdev->dev); 172085f3b431STomeu Vizoso return regulator; 17216261b06dSBjorn Andersson } 17226261b06dSBjorn Andersson 172385f3b431STomeu Vizoso if (!try_module_get(rdev->owner)) { 17247d245afaSDmitry Torokhov regulator = ERR_PTR(-EPROBE_DEFER); 172585f3b431STomeu Vizoso put_device(&rdev->dev); 172685f3b431STomeu Vizoso return regulator; 172785f3b431STomeu Vizoso } 1728a5766f11SLiam Girdwood 1729414c70cbSLiam Girdwood regulator = create_regulator(rdev, dev, id); 1730414c70cbSLiam Girdwood if (regulator == NULL) { 1731414c70cbSLiam Girdwood regulator = ERR_PTR(-ENOMEM); 173285f3b431STomeu Vizoso put_device(&rdev->dev); 1733414c70cbSLiam Girdwood module_put(rdev->owner); 173485f3b431STomeu Vizoso return regulator; 1735414c70cbSLiam Girdwood } 1736414c70cbSLiam Girdwood 17375ffbd136SMark Brown rdev->open_count++; 1738a8bd42a9SDmitry Torokhov if (get_type == EXCLUSIVE_GET) { 17395ffbd136SMark Brown rdev->exclusive = 1; 17405ffbd136SMark Brown 17415ffbd136SMark Brown ret = _regulator_is_enabled(rdev); 17425ffbd136SMark Brown if (ret > 0) 17435ffbd136SMark Brown rdev->use_count = 1; 17445ffbd136SMark Brown else 17455ffbd136SMark Brown rdev->use_count = 0; 17465ffbd136SMark Brown } 17475ffbd136SMark Brown 1748ed1ae2ddSpascal paillet device_link_add(dev, &rdev->dev, DL_FLAG_STATELESS); 1749ed1ae2ddSpascal paillet 1750414c70cbSLiam Girdwood return regulator; 1751414c70cbSLiam Girdwood } 17525ffbd136SMark Brown 17535ffbd136SMark Brown /** 17545ffbd136SMark Brown * regulator_get - lookup and obtain a reference to a regulator. 17555ffbd136SMark Brown * @dev: device for regulator "consumer" 17565ffbd136SMark Brown * @id: Supply name or regulator ID. 17575ffbd136SMark Brown * 17585ffbd136SMark Brown * Returns a struct regulator corresponding to the regulator producer, 17595ffbd136SMark Brown * or IS_ERR() condition containing errno. 17605ffbd136SMark Brown * 17615ffbd136SMark Brown * Use of supply names configured via regulator_set_device_supply() is 17625ffbd136SMark Brown * strongly encouraged. It is recommended that the supply name used 17635ffbd136SMark Brown * should match the name used for the supply and/or the relevant 17645ffbd136SMark Brown * device pins in the datasheet. 17655ffbd136SMark Brown */ 17665ffbd136SMark Brown struct regulator *regulator_get(struct device *dev, const char *id) 17675ffbd136SMark Brown { 1768a8bd42a9SDmitry Torokhov return _regulator_get(dev, id, NORMAL_GET); 17695ffbd136SMark Brown } 1770414c70cbSLiam Girdwood EXPORT_SYMBOL_GPL(regulator_get); 1771414c70cbSLiam Girdwood 1772070b9079SStephen Boyd /** 17735ffbd136SMark Brown * regulator_get_exclusive - obtain exclusive access to a regulator. 17745ffbd136SMark Brown * @dev: device for regulator "consumer" 17755ffbd136SMark Brown * @id: Supply name or regulator ID. 17765ffbd136SMark Brown * 17775ffbd136SMark Brown * Returns a struct regulator corresponding to the regulator producer, 17785ffbd136SMark Brown * or IS_ERR() condition containing errno. Other consumers will be 177969c3f723SStephen Boyd * unable to obtain this regulator while this reference is held and the 178069c3f723SStephen Boyd * use count for the regulator will be initialised to reflect the current 178169c3f723SStephen Boyd * state of the regulator. 17825ffbd136SMark Brown * 17835ffbd136SMark Brown * This is intended for use by consumers which cannot tolerate shared 17845ffbd136SMark Brown * use of the regulator such as those which need to force the 17855ffbd136SMark Brown * regulator off for correct operation of the hardware they are 17865ffbd136SMark Brown * controlling. 17875ffbd136SMark Brown * 17885ffbd136SMark Brown * Use of supply names configured via regulator_set_device_supply() is 17895ffbd136SMark Brown * strongly encouraged. It is recommended that the supply name used 17905ffbd136SMark Brown * should match the name used for the supply and/or the relevant 17915ffbd136SMark Brown * device pins in the datasheet. 17925ffbd136SMark Brown */ 17935ffbd136SMark Brown struct regulator *regulator_get_exclusive(struct device *dev, const char *id) 17945ffbd136SMark Brown { 1795a8bd42a9SDmitry Torokhov return _regulator_get(dev, id, EXCLUSIVE_GET); 17965ffbd136SMark Brown } 17975ffbd136SMark Brown EXPORT_SYMBOL_GPL(regulator_get_exclusive); 17985ffbd136SMark Brown 1799de1dd9fdSMark Brown /** 1800de1dd9fdSMark Brown * regulator_get_optional - obtain optional access to a regulator. 1801de1dd9fdSMark Brown * @dev: device for regulator "consumer" 1802de1dd9fdSMark Brown * @id: Supply name or regulator ID. 1803de1dd9fdSMark Brown * 1804de1dd9fdSMark Brown * Returns a struct regulator corresponding to the regulator producer, 180569c3f723SStephen Boyd * or IS_ERR() condition containing errno. 1806de1dd9fdSMark Brown * 1807de1dd9fdSMark Brown * This is intended for use by consumers for devices which can have 1808de1dd9fdSMark Brown * some supplies unconnected in normal use, such as some MMC devices. 1809de1dd9fdSMark Brown * It can allow the regulator core to provide stub supplies for other 1810de1dd9fdSMark Brown * supplies requested using normal regulator_get() calls without 1811de1dd9fdSMark Brown * disrupting the operation of drivers that can handle absent 1812de1dd9fdSMark Brown * supplies. 1813de1dd9fdSMark Brown * 1814de1dd9fdSMark Brown * Use of supply names configured via regulator_set_device_supply() is 1815de1dd9fdSMark Brown * strongly encouraged. It is recommended that the supply name used 1816de1dd9fdSMark Brown * should match the name used for the supply and/or the relevant 1817de1dd9fdSMark Brown * device pins in the datasheet. 1818de1dd9fdSMark Brown */ 1819de1dd9fdSMark Brown struct regulator *regulator_get_optional(struct device *dev, const char *id) 1820de1dd9fdSMark Brown { 1821a8bd42a9SDmitry Torokhov return _regulator_get(dev, id, OPTIONAL_GET); 1822de1dd9fdSMark Brown } 1823de1dd9fdSMark Brown EXPORT_SYMBOL_GPL(regulator_get_optional); 1824de1dd9fdSMark Brown 182583b0302dSAshay Jaiswal /* regulator_list_mutex lock held by regulator_put() */ 182623ff2f0fSCharles Keepax static void _regulator_put(struct regulator *regulator) 1827414c70cbSLiam Girdwood { 1828414c70cbSLiam Girdwood struct regulator_dev *rdev; 1829414c70cbSLiam Girdwood 183093576842SViresh Kumar if (IS_ERR_OR_NULL(regulator)) 1831414c70cbSLiam Girdwood return; 1832414c70cbSLiam Girdwood 183370cfef26SKrzysztof Kozlowski lockdep_assert_held_once(®ulator_list_mutex); 183470cfef26SKrzysztof Kozlowski 1835414c70cbSLiam Girdwood rdev = regulator->rdev; 1836414c70cbSLiam Girdwood 18375de70519SMark Brown debugfs_remove_recursive(regulator->debugfs); 18385de70519SMark Brown 1839ed1ae2ddSpascal paillet if (regulator->dev) { 1840ed1ae2ddSpascal paillet int count = 0; 1841ed1ae2ddSpascal paillet struct regulator *r; 1842ed1ae2ddSpascal paillet 1843ed1ae2ddSpascal paillet list_for_each_entry(r, &rdev->consumer_list, list) 1844ed1ae2ddSpascal paillet if (r->dev == regulator->dev) 1845ed1ae2ddSpascal paillet count++; 1846ed1ae2ddSpascal paillet 1847ed1ae2ddSpascal paillet if (count == 1) 1848ed1ae2ddSpascal paillet device_link_remove(regulator->dev, &rdev->dev); 1849ed1ae2ddSpascal paillet 1850414c70cbSLiam Girdwood /* remove any sysfs entries */ 1851414c70cbSLiam Girdwood sysfs_remove_link(&rdev->dev.kobj, regulator->supply_name); 1852ed1ae2ddSpascal paillet } 1853ed1ae2ddSpascal paillet 185466cf9a7eSMaciej Purski regulator_lock(rdev); 1855414c70cbSLiam Girdwood list_del(®ulator->list); 1856414c70cbSLiam Girdwood 18575ffbd136SMark Brown rdev->open_count--; 18585ffbd136SMark Brown rdev->exclusive = 0; 185985f3b431STomeu Vizoso put_device(&rdev->dev); 186066cf9a7eSMaciej Purski regulator_unlock(rdev); 18615ffbd136SMark Brown 18620630b614SStephen Boyd kfree_const(regulator->supply_name); 18631768514eSMark Brown kfree(regulator); 18641768514eSMark Brown 1865414c70cbSLiam Girdwood module_put(rdev->owner); 186623ff2f0fSCharles Keepax } 186723ff2f0fSCharles Keepax 186823ff2f0fSCharles Keepax /** 186923ff2f0fSCharles Keepax * regulator_put - "free" the regulator source 187023ff2f0fSCharles Keepax * @regulator: regulator source 187123ff2f0fSCharles Keepax * 187223ff2f0fSCharles Keepax * Note: drivers must ensure that all regulator_enable calls made on this 187323ff2f0fSCharles Keepax * regulator source are balanced by regulator_disable calls prior to calling 187423ff2f0fSCharles Keepax * this function. 187523ff2f0fSCharles Keepax */ 187623ff2f0fSCharles Keepax void regulator_put(struct regulator *regulator) 187723ff2f0fSCharles Keepax { 187823ff2f0fSCharles Keepax mutex_lock(®ulator_list_mutex); 187923ff2f0fSCharles Keepax _regulator_put(regulator); 1880414c70cbSLiam Girdwood mutex_unlock(®ulator_list_mutex); 1881414c70cbSLiam Girdwood } 1882414c70cbSLiam Girdwood EXPORT_SYMBOL_GPL(regulator_put); 1883414c70cbSLiam Girdwood 1884a06ccd9cSCharles Keepax /** 1885a06ccd9cSCharles Keepax * regulator_register_supply_alias - Provide device alias for supply lookup 1886a06ccd9cSCharles Keepax * 1887a06ccd9cSCharles Keepax * @dev: device that will be given as the regulator "consumer" 1888a06ccd9cSCharles Keepax * @id: Supply name or regulator ID 1889a06ccd9cSCharles Keepax * @alias_dev: device that should be used to lookup the supply 1890a06ccd9cSCharles Keepax * @alias_id: Supply name or regulator ID that should be used to lookup the 1891a06ccd9cSCharles Keepax * supply 1892a06ccd9cSCharles Keepax * 1893a06ccd9cSCharles Keepax * All lookups for id on dev will instead be conducted for alias_id on 1894a06ccd9cSCharles Keepax * alias_dev. 1895a06ccd9cSCharles Keepax */ 1896a06ccd9cSCharles Keepax int regulator_register_supply_alias(struct device *dev, const char *id, 1897a06ccd9cSCharles Keepax struct device *alias_dev, 1898a06ccd9cSCharles Keepax const char *alias_id) 1899a06ccd9cSCharles Keepax { 1900a06ccd9cSCharles Keepax struct regulator_supply_alias *map; 1901a06ccd9cSCharles Keepax 1902a06ccd9cSCharles Keepax map = regulator_find_supply_alias(dev, id); 1903a06ccd9cSCharles Keepax if (map) 1904a06ccd9cSCharles Keepax return -EEXIST; 1905a06ccd9cSCharles Keepax 1906a06ccd9cSCharles Keepax map = kzalloc(sizeof(struct regulator_supply_alias), GFP_KERNEL); 1907a06ccd9cSCharles Keepax if (!map) 1908a06ccd9cSCharles Keepax return -ENOMEM; 1909a06ccd9cSCharles Keepax 1910a06ccd9cSCharles Keepax map->src_dev = dev; 1911a06ccd9cSCharles Keepax map->src_supply = id; 1912a06ccd9cSCharles Keepax map->alias_dev = alias_dev; 1913a06ccd9cSCharles Keepax map->alias_supply = alias_id; 1914a06ccd9cSCharles Keepax 1915a06ccd9cSCharles Keepax list_add(&map->list, ®ulator_supply_alias_list); 1916a06ccd9cSCharles Keepax 1917a06ccd9cSCharles Keepax pr_info("Adding alias for supply %s,%s -> %s,%s\n", 1918a06ccd9cSCharles Keepax id, dev_name(dev), alias_id, dev_name(alias_dev)); 1919a06ccd9cSCharles Keepax 1920a06ccd9cSCharles Keepax return 0; 1921a06ccd9cSCharles Keepax } 1922a06ccd9cSCharles Keepax EXPORT_SYMBOL_GPL(regulator_register_supply_alias); 1923a06ccd9cSCharles Keepax 1924a06ccd9cSCharles Keepax /** 1925a06ccd9cSCharles Keepax * regulator_unregister_supply_alias - Remove device alias 1926a06ccd9cSCharles Keepax * 1927a06ccd9cSCharles Keepax * @dev: device that will be given as the regulator "consumer" 1928a06ccd9cSCharles Keepax * @id: Supply name or regulator ID 1929a06ccd9cSCharles Keepax * 1930a06ccd9cSCharles Keepax * Remove a lookup alias if one exists for id on dev. 1931a06ccd9cSCharles Keepax */ 1932a06ccd9cSCharles Keepax void regulator_unregister_supply_alias(struct device *dev, const char *id) 1933a06ccd9cSCharles Keepax { 1934a06ccd9cSCharles Keepax struct regulator_supply_alias *map; 1935a06ccd9cSCharles Keepax 1936a06ccd9cSCharles Keepax map = regulator_find_supply_alias(dev, id); 1937a06ccd9cSCharles Keepax if (map) { 1938a06ccd9cSCharles Keepax list_del(&map->list); 1939a06ccd9cSCharles Keepax kfree(map); 1940a06ccd9cSCharles Keepax } 1941a06ccd9cSCharles Keepax } 1942a06ccd9cSCharles Keepax EXPORT_SYMBOL_GPL(regulator_unregister_supply_alias); 1943a06ccd9cSCharles Keepax 1944a06ccd9cSCharles Keepax /** 1945a06ccd9cSCharles Keepax * regulator_bulk_register_supply_alias - register multiple aliases 1946a06ccd9cSCharles Keepax * 1947a06ccd9cSCharles Keepax * @dev: device that will be given as the regulator "consumer" 1948a06ccd9cSCharles Keepax * @id: List of supply names or regulator IDs 1949a06ccd9cSCharles Keepax * @alias_dev: device that should be used to lookup the supply 1950a06ccd9cSCharles Keepax * @alias_id: List of supply names or regulator IDs that should be used to 1951a06ccd9cSCharles Keepax * lookup the supply 1952a06ccd9cSCharles Keepax * @num_id: Number of aliases to register 1953a06ccd9cSCharles Keepax * 1954a06ccd9cSCharles Keepax * @return 0 on success, an errno on failure. 1955a06ccd9cSCharles Keepax * 1956a06ccd9cSCharles Keepax * This helper function allows drivers to register several supply 1957a06ccd9cSCharles Keepax * aliases in one operation. If any of the aliases cannot be 1958a06ccd9cSCharles Keepax * registered any aliases that were registered will be removed 1959a06ccd9cSCharles Keepax * before returning to the caller. 1960a06ccd9cSCharles Keepax */ 19619f8c0fe9SLee Jones int regulator_bulk_register_supply_alias(struct device *dev, 19629f8c0fe9SLee Jones const char *const *id, 1963a06ccd9cSCharles Keepax struct device *alias_dev, 19649f8c0fe9SLee Jones const char *const *alias_id, 1965a06ccd9cSCharles Keepax int num_id) 1966a06ccd9cSCharles Keepax { 1967a06ccd9cSCharles Keepax int i; 1968a06ccd9cSCharles Keepax int ret; 1969a06ccd9cSCharles Keepax 1970a06ccd9cSCharles Keepax for (i = 0; i < num_id; ++i) { 1971a06ccd9cSCharles Keepax ret = regulator_register_supply_alias(dev, id[i], alias_dev, 1972a06ccd9cSCharles Keepax alias_id[i]); 1973a06ccd9cSCharles Keepax if (ret < 0) 1974a06ccd9cSCharles Keepax goto err; 1975a06ccd9cSCharles Keepax } 1976a06ccd9cSCharles Keepax 1977a06ccd9cSCharles Keepax return 0; 1978a06ccd9cSCharles Keepax 1979a06ccd9cSCharles Keepax err: 1980a06ccd9cSCharles Keepax dev_err(dev, 1981a06ccd9cSCharles Keepax "Failed to create supply alias %s,%s -> %s,%s\n", 1982a06ccd9cSCharles Keepax id[i], dev_name(dev), alias_id[i], dev_name(alias_dev)); 1983a06ccd9cSCharles Keepax 1984a06ccd9cSCharles Keepax while (--i >= 0) 1985a06ccd9cSCharles Keepax regulator_unregister_supply_alias(dev, id[i]); 1986a06ccd9cSCharles Keepax 1987a06ccd9cSCharles Keepax return ret; 1988a06ccd9cSCharles Keepax } 1989a06ccd9cSCharles Keepax EXPORT_SYMBOL_GPL(regulator_bulk_register_supply_alias); 1990a06ccd9cSCharles Keepax 1991a06ccd9cSCharles Keepax /** 1992a06ccd9cSCharles Keepax * regulator_bulk_unregister_supply_alias - unregister multiple aliases 1993a06ccd9cSCharles Keepax * 1994a06ccd9cSCharles Keepax * @dev: device that will be given as the regulator "consumer" 1995a06ccd9cSCharles Keepax * @id: List of supply names or regulator IDs 1996a06ccd9cSCharles Keepax * @num_id: Number of aliases to unregister 1997a06ccd9cSCharles Keepax * 1998a06ccd9cSCharles Keepax * This helper function allows drivers to unregister several supply 1999a06ccd9cSCharles Keepax * aliases in one operation. 2000a06ccd9cSCharles Keepax */ 2001a06ccd9cSCharles Keepax void regulator_bulk_unregister_supply_alias(struct device *dev, 20029f8c0fe9SLee Jones const char *const *id, 2003a06ccd9cSCharles Keepax int num_id) 2004a06ccd9cSCharles Keepax { 2005a06ccd9cSCharles Keepax int i; 2006a06ccd9cSCharles Keepax 2007a06ccd9cSCharles Keepax for (i = 0; i < num_id; ++i) 2008a06ccd9cSCharles Keepax regulator_unregister_supply_alias(dev, id[i]); 2009a06ccd9cSCharles Keepax } 2010a06ccd9cSCharles Keepax EXPORT_SYMBOL_GPL(regulator_bulk_unregister_supply_alias); 2011a06ccd9cSCharles Keepax 2012a06ccd9cSCharles Keepax 2013f19b00daSKim, Milo /* Manage enable GPIO list. Same GPIO pin can be shared among regulators */ 2014f19b00daSKim, Milo static int regulator_ena_gpio_request(struct regulator_dev *rdev, 2015f19b00daSKim, Milo const struct regulator_config *config) 2016f19b00daSKim, Milo { 2017f19b00daSKim, Milo struct regulator_enable_gpio *pin; 2018778b28b4SRussell King struct gpio_desc *gpiod; 2019f19b00daSKim, Milo int ret; 2020f19b00daSKim, Milo 2021e45e290aSLinus Walleij if (config->ena_gpiod) 2022e45e290aSLinus Walleij gpiod = config->ena_gpiod; 2023e45e290aSLinus Walleij else 2024778b28b4SRussell King gpiod = gpio_to_desc(config->ena_gpio); 2025778b28b4SRussell King 2026f19b00daSKim, Milo list_for_each_entry(pin, ®ulator_ena_gpio_list, list) { 2027778b28b4SRussell King if (pin->gpiod == gpiod) { 2028f19b00daSKim, Milo rdev_dbg(rdev, "GPIO %d is already used\n", 2029f19b00daSKim, Milo config->ena_gpio); 2030f19b00daSKim, Milo goto update_ena_gpio_to_rdev; 2031f19b00daSKim, Milo } 2032f19b00daSKim, Milo } 2033f19b00daSKim, Milo 2034e45e290aSLinus Walleij if (!config->ena_gpiod) { 2035f19b00daSKim, Milo ret = gpio_request_one(config->ena_gpio, 2036f19b00daSKim, Milo GPIOF_DIR_OUT | config->ena_gpio_flags, 2037f19b00daSKim, Milo rdev_get_name(rdev)); 2038f19b00daSKim, Milo if (ret) 2039f19b00daSKim, Milo return ret; 2040e45e290aSLinus Walleij } 2041f19b00daSKim, Milo 2042f19b00daSKim, Milo pin = kzalloc(sizeof(struct regulator_enable_gpio), GFP_KERNEL); 2043f19b00daSKim, Milo if (pin == NULL) { 2044e45e290aSLinus Walleij if (!config->ena_gpiod) 2045f19b00daSKim, Milo gpio_free(config->ena_gpio); 2046f19b00daSKim, Milo return -ENOMEM; 2047f19b00daSKim, Milo } 2048f19b00daSKim, Milo 2049778b28b4SRussell King pin->gpiod = gpiod; 2050f19b00daSKim, Milo pin->ena_gpio_invert = config->ena_gpio_invert; 2051f19b00daSKim, Milo list_add(&pin->list, ®ulator_ena_gpio_list); 2052f19b00daSKim, Milo 2053f19b00daSKim, Milo update_ena_gpio_to_rdev: 2054f19b00daSKim, Milo pin->request_count++; 2055f19b00daSKim, Milo rdev->ena_pin = pin; 2056f19b00daSKim, Milo return 0; 2057f19b00daSKim, Milo } 2058f19b00daSKim, Milo 2059f19b00daSKim, Milo static void regulator_ena_gpio_free(struct regulator_dev *rdev) 2060f19b00daSKim, Milo { 2061f19b00daSKim, Milo struct regulator_enable_gpio *pin, *n; 2062f19b00daSKim, Milo 2063f19b00daSKim, Milo if (!rdev->ena_pin) 2064f19b00daSKim, Milo return; 2065f19b00daSKim, Milo 2066f19b00daSKim, Milo /* Free the GPIO only in case of no use */ 2067f19b00daSKim, Milo list_for_each_entry_safe(pin, n, ®ulator_ena_gpio_list, list) { 2068778b28b4SRussell King if (pin->gpiod == rdev->ena_pin->gpiod) { 2069f19b00daSKim, Milo if (pin->request_count <= 1) { 2070f19b00daSKim, Milo pin->request_count = 0; 2071778b28b4SRussell King gpiod_put(pin->gpiod); 2072f19b00daSKim, Milo list_del(&pin->list); 2073f19b00daSKim, Milo kfree(pin); 207460a2362fSSeung-Woo Kim rdev->ena_pin = NULL; 207560a2362fSSeung-Woo Kim return; 2076f19b00daSKim, Milo } else { 2077f19b00daSKim, Milo pin->request_count--; 2078f19b00daSKim, Milo } 2079f19b00daSKim, Milo } 2080f19b00daSKim, Milo } 2081f19b00daSKim, Milo } 2082f19b00daSKim, Milo 2083967cfb18SKim, Milo /** 208431d6eebfSRobert P. J. Day * regulator_ena_gpio_ctrl - balance enable_count of each GPIO and actual GPIO pin control 208531d6eebfSRobert P. J. Day * @rdev: regulator_dev structure 208631d6eebfSRobert P. J. Day * @enable: enable GPIO at initial use? 208731d6eebfSRobert P. J. Day * 2088967cfb18SKim, Milo * GPIO is enabled in case of initial use. (enable_count is 0) 2089967cfb18SKim, Milo * GPIO is disabled when it is not shared any more. (enable_count <= 1) 2090967cfb18SKim, Milo */ 2091967cfb18SKim, Milo static int regulator_ena_gpio_ctrl(struct regulator_dev *rdev, bool enable) 2092967cfb18SKim, Milo { 2093967cfb18SKim, Milo struct regulator_enable_gpio *pin = rdev->ena_pin; 2094967cfb18SKim, Milo 2095967cfb18SKim, Milo if (!pin) 2096967cfb18SKim, Milo return -EINVAL; 2097967cfb18SKim, Milo 2098967cfb18SKim, Milo if (enable) { 2099967cfb18SKim, Milo /* Enable GPIO at initial use */ 2100967cfb18SKim, Milo if (pin->enable_count == 0) 2101778b28b4SRussell King gpiod_set_value_cansleep(pin->gpiod, 2102967cfb18SKim, Milo !pin->ena_gpio_invert); 2103967cfb18SKim, Milo 2104967cfb18SKim, Milo pin->enable_count++; 2105967cfb18SKim, Milo } else { 2106967cfb18SKim, Milo if (pin->enable_count > 1) { 2107967cfb18SKim, Milo pin->enable_count--; 2108967cfb18SKim, Milo return 0; 2109967cfb18SKim, Milo } 2110967cfb18SKim, Milo 2111967cfb18SKim, Milo /* Disable GPIO if not used */ 2112967cfb18SKim, Milo if (pin->enable_count <= 1) { 2113778b28b4SRussell King gpiod_set_value_cansleep(pin->gpiod, 2114967cfb18SKim, Milo pin->ena_gpio_invert); 2115967cfb18SKim, Milo pin->enable_count = 0; 2116967cfb18SKim, Milo } 2117967cfb18SKim, Milo } 2118967cfb18SKim, Milo 2119967cfb18SKim, Milo return 0; 2120967cfb18SKim, Milo } 2121967cfb18SKim, Milo 212279fd1141SGuodong Xu /** 212379fd1141SGuodong Xu * _regulator_enable_delay - a delay helper function 212479fd1141SGuodong Xu * @delay: time to delay in microseconds 212579fd1141SGuodong Xu * 21265df529d4SThierry Reding * Delay for the requested amount of time as per the guidelines in: 21275df529d4SThierry Reding * 21285df529d4SThierry Reding * Documentation/timers/timers-howto.txt 21295df529d4SThierry Reding * 21305df529d4SThierry Reding * The assumption here is that regulators will never be enabled in 21315df529d4SThierry Reding * atomic context and therefore sleeping functions can be used. 21325df529d4SThierry Reding */ 213379fd1141SGuodong Xu static void _regulator_enable_delay(unsigned int delay) 213479fd1141SGuodong Xu { 21355df529d4SThierry Reding unsigned int ms = delay / 1000; 21365df529d4SThierry Reding unsigned int us = delay % 1000; 21375df529d4SThierry Reding 21385df529d4SThierry Reding if (ms > 0) { 21395df529d4SThierry Reding /* 21405df529d4SThierry Reding * For small enough values, handle super-millisecond 21415df529d4SThierry Reding * delays in the usleep_range() call below. 21425df529d4SThierry Reding */ 21435df529d4SThierry Reding if (ms < 20) 21445df529d4SThierry Reding us += ms * 1000; 21455df529d4SThierry Reding else 21465df529d4SThierry Reding msleep(ms); 21475df529d4SThierry Reding } 21485df529d4SThierry Reding 21495df529d4SThierry Reding /* 21505df529d4SThierry Reding * Give the scheduler some room to coalesce with any other 21515df529d4SThierry Reding * wakeup sources. For delays shorter than 10 us, don't even 21525df529d4SThierry Reding * bother setting up high-resolution timers and just busy- 21535df529d4SThierry Reding * loop. 21545df529d4SThierry Reding */ 21555df529d4SThierry Reding if (us >= 10) 21565df529d4SThierry Reding usleep_range(us, us + 100); 21575df529d4SThierry Reding else 21585df529d4SThierry Reding udelay(us); 21595c5659d0SMark Brown } 21605c5659d0SMark Brown 21615c5659d0SMark Brown static int _regulator_do_enable(struct regulator_dev *rdev) 21625c5659d0SMark Brown { 21635c5659d0SMark Brown int ret, delay; 21645c5659d0SMark Brown 21655c5659d0SMark Brown /* Query before enabling in case configuration dependent. */ 21665c5659d0SMark Brown ret = _regulator_get_enable_time(rdev); 21675c5659d0SMark Brown if (ret >= 0) { 21685c5659d0SMark Brown delay = ret; 21695c5659d0SMark Brown } else { 2170414c70cbSLiam Girdwood rdev_warn(rdev, "enable_time() failed: %d\n", ret); 2171414c70cbSLiam Girdwood delay = 0; 2172414c70cbSLiam Girdwood } 21735c5659d0SMark Brown 2174414c70cbSLiam Girdwood trace_regulator_enable(rdev_get_name(rdev)); 2175414c70cbSLiam Girdwood 2176871f5650SGuodong Xu if (rdev->desc->off_on_delay) { 2177871f5650SGuodong Xu /* if needed, keep a distance of off_on_delay from last time 2178871f5650SGuodong Xu * this regulator was disabled. 2179871f5650SGuodong Xu */ 2180871f5650SGuodong Xu unsigned long start_jiffy = jiffies; 2181871f5650SGuodong Xu unsigned long intended, max_delay, remaining; 2182871f5650SGuodong Xu 2183871f5650SGuodong Xu max_delay = usecs_to_jiffies(rdev->desc->off_on_delay); 2184871f5650SGuodong Xu intended = rdev->last_off_jiffy + max_delay; 2185871f5650SGuodong Xu 2186871f5650SGuodong Xu if (time_before(start_jiffy, intended)) { 2187871f5650SGuodong Xu /* calc remaining jiffies to deal with one-time 2188871f5650SGuodong Xu * timer wrapping. 2189871f5650SGuodong Xu * in case of multiple timer wrapping, either it can be 2190871f5650SGuodong Xu * detected by out-of-range remaining, or it cannot be 2191871f5650SGuodong Xu * detected and we gets a panelty of 2192871f5650SGuodong Xu * _regulator_enable_delay(). 2193871f5650SGuodong Xu */ 2194871f5650SGuodong Xu remaining = intended - start_jiffy; 2195871f5650SGuodong Xu if (remaining <= max_delay) 2196871f5650SGuodong Xu _regulator_enable_delay( 2197871f5650SGuodong Xu jiffies_to_usecs(remaining)); 2198871f5650SGuodong Xu } 2199871f5650SGuodong Xu } 2200871f5650SGuodong Xu 2201414c70cbSLiam Girdwood if (rdev->ena_pin) { 220229d62ec5SDoug Anderson if (!rdev->ena_gpio_state) { 22039a2372faSMark Brown ret = regulator_ena_gpio_ctrl(rdev, true); 2204414c70cbSLiam Girdwood if (ret < 0) 2205414c70cbSLiam Girdwood return ret; 22069a2372faSMark Brown rdev->ena_gpio_state = 1; 220729d62ec5SDoug Anderson } 22089a2372faSMark Brown } else if (rdev->desc->ops->enable) { 22099a2372faSMark Brown ret = rdev->desc->ops->enable(rdev); 22109a2372faSMark Brown if (ret < 0) 22119a2372faSMark Brown return ret; 22129a2372faSMark Brown } else { 22139a2372faSMark Brown return -EINVAL; 22145c5659d0SMark Brown } 22159a2372faSMark Brown 22169a2372faSMark Brown /* Allow the regulator to ramp; it would be useful to extend 221731aae2beSMark Brown * this for bulk operations so that the regulators can ramp 2218a7433cffSLinus Walleij * together. */ 22195da84fd9SJoe Perches trace_regulator_enable_delay(rdev_get_name(rdev)); 2220414c70cbSLiam Girdwood 222179fd1141SGuodong Xu _regulator_enable_delay(delay); 2222a7433cffSLinus Walleij 2223414c70cbSLiam Girdwood trace_regulator_enable_complete(rdev_get_name(rdev)); 2224414c70cbSLiam Girdwood 22259a2372faSMark Brown return 0; 22269a2372faSMark Brown } 22279a2372faSMark Brown 2228414c70cbSLiam Girdwood /* locks held by regulator_enable() */ 2229414c70cbSLiam Girdwood static int _regulator_enable(struct regulator_dev *rdev) 2230414c70cbSLiam Girdwood { 2231414c70cbSLiam Girdwood int ret; 2232414c70cbSLiam Girdwood 223370cfef26SKrzysztof Kozlowski lockdep_assert_held_once(&rdev->mutex); 223470cfef26SKrzysztof Kozlowski 2235414c70cbSLiam Girdwood /* check voltage and requested load before enabling */ 22368a34e979SWEN Pingbo if (regulator_ops_is_valid(rdev, REGULATOR_CHANGE_DRMS)) 2237cf7bbcdfSMark Brown drms_uA_update(rdev); 2238cf7bbcdfSMark Brown 2239414c70cbSLiam Girdwood if (rdev->use_count == 0) { 2240cf7bbcdfSMark Brown /* The regulator may on if it's not switchable or left on */ 2241414c70cbSLiam Girdwood ret = _regulator_is_enabled(rdev); 2242414c70cbSLiam Girdwood if (ret == -EINVAL || ret == 0) { 22438a34e979SWEN Pingbo if (!regulator_ops_is_valid(rdev, 22448a34e979SWEN Pingbo REGULATOR_CHANGE_STATUS)) 2245412aec61SDavid Brownell return -EPERM; 2246412aec61SDavid Brownell 2247414c70cbSLiam Girdwood ret = _regulator_do_enable(rdev); 2248412aec61SDavid Brownell if (ret < 0) 2249412aec61SDavid Brownell return ret; 2250412aec61SDavid Brownell 2251264b88c9SHarald Geyer _notifier_call_chain(rdev, REGULATOR_EVENT_ENABLE, 2252264b88c9SHarald Geyer NULL); 2253414c70cbSLiam Girdwood } else if (ret < 0) { 2254414c70cbSLiam Girdwood rdev_err(rdev, "is_enabled() failed: %d\n", ret); 2255414c70cbSLiam Girdwood return ret; 2256414c70cbSLiam Girdwood } 2257414c70cbSLiam Girdwood /* Fallthrough on positive return values - already enabled */ 2258414c70cbSLiam Girdwood } 2259414c70cbSLiam Girdwood 2260414c70cbSLiam Girdwood rdev->use_count++; 2261414c70cbSLiam Girdwood 2262414c70cbSLiam Girdwood return 0; 2263414c70cbSLiam Girdwood } 2264414c70cbSLiam Girdwood 2265414c70cbSLiam Girdwood /** 2266414c70cbSLiam Girdwood * regulator_enable - enable regulator output 2267414c70cbSLiam Girdwood * @regulator: regulator source 2268414c70cbSLiam Girdwood * 2269414c70cbSLiam Girdwood * Request that the regulator be enabled with the regulator output at 2270414c70cbSLiam Girdwood * the predefined voltage or current value. Calls to regulator_enable() 2271414c70cbSLiam Girdwood * must be balanced with calls to regulator_disable(). 2272414c70cbSLiam Girdwood * 2273414c70cbSLiam Girdwood * NOTE: the output value can be set by other drivers, boot loader or may be 2274414c70cbSLiam Girdwood * hardwired in the regulator. 2275414c70cbSLiam Girdwood */ 2276414c70cbSLiam Girdwood int regulator_enable(struct regulator *regulator) 2277414c70cbSLiam Girdwood { 2278414c70cbSLiam Girdwood struct regulator_dev *rdev = regulator->rdev; 2279414c70cbSLiam Girdwood int ret = 0; 2280414c70cbSLiam Girdwood 22816492bc1bSMark Brown if (regulator->always_on) 22826492bc1bSMark Brown return 0; 22836492bc1bSMark Brown 22843801b86aSMark Brown if (rdev->supply) { 22853801b86aSMark Brown ret = regulator_enable(rdev->supply); 22863801b86aSMark Brown if (ret != 0) 22873801b86aSMark Brown return ret; 22883801b86aSMark Brown } 22893801b86aSMark Brown 229038de19faSMark Brown mutex_lock(&rdev->mutex); 2291414c70cbSLiam Girdwood ret = _regulator_enable(rdev); 229238de19faSMark Brown mutex_unlock(&rdev->mutex); 22933801b86aSMark Brown 2294d1685e4eSHeiko Stübner if (ret != 0 && rdev->supply) 22953801b86aSMark Brown regulator_disable(rdev->supply); 22963801b86aSMark Brown 2297414c70cbSLiam Girdwood return ret; 2298414c70cbSLiam Girdwood } 2299414c70cbSLiam Girdwood EXPORT_SYMBOL_GPL(regulator_enable); 2300414c70cbSLiam Girdwood 23015c5659d0SMark Brown static int _regulator_do_disable(struct regulator_dev *rdev) 23025c5659d0SMark Brown { 23035c5659d0SMark Brown int ret; 23045c5659d0SMark Brown 23055c5659d0SMark Brown trace_regulator_disable(rdev_get_name(rdev)); 23065c5659d0SMark Brown 2307967cfb18SKim, Milo if (rdev->ena_pin) { 230829d62ec5SDoug Anderson if (rdev->ena_gpio_state) { 2309967cfb18SKim, Milo ret = regulator_ena_gpio_ctrl(rdev, false); 2310967cfb18SKim, Milo if (ret < 0) 2311967cfb18SKim, Milo return ret; 23125c5659d0SMark Brown rdev->ena_gpio_state = 0; 231329d62ec5SDoug Anderson } 23145c5659d0SMark Brown 23155c5659d0SMark Brown } else if (rdev->desc->ops->disable) { 23165c5659d0SMark Brown ret = rdev->desc->ops->disable(rdev); 23175c5659d0SMark Brown if (ret != 0) 23185c5659d0SMark Brown return ret; 23195c5659d0SMark Brown } 23205c5659d0SMark Brown 2321871f5650SGuodong Xu /* cares about last_off_jiffy only if off_on_delay is required by 2322871f5650SGuodong Xu * device. 2323871f5650SGuodong Xu */ 2324871f5650SGuodong Xu if (rdev->desc->off_on_delay) 2325871f5650SGuodong Xu rdev->last_off_jiffy = jiffies; 2326871f5650SGuodong Xu 23275c5659d0SMark Brown trace_regulator_disable_complete(rdev_get_name(rdev)); 23285c5659d0SMark Brown 23295c5659d0SMark Brown return 0; 23305c5659d0SMark Brown } 23315c5659d0SMark Brown 2332414c70cbSLiam Girdwood /* locks held by regulator_disable() */ 23333801b86aSMark Brown static int _regulator_disable(struct regulator_dev *rdev) 2334414c70cbSLiam Girdwood { 2335414c70cbSLiam Girdwood int ret = 0; 2336414c70cbSLiam Girdwood 233770cfef26SKrzysztof Kozlowski lockdep_assert_held_once(&rdev->mutex); 233870cfef26SKrzysztof Kozlowski 2339cd94b505SDavid Brownell if (WARN(rdev->use_count <= 0, 234043e7ee33SJoe Perches "unbalanced disables for %s\n", rdev_get_name(rdev))) 2341cd94b505SDavid Brownell return -EIO; 2342cd94b505SDavid Brownell 2343414c70cbSLiam Girdwood /* are we the last user and permitted to disable ? */ 234460ef66fcSMark Brown if (rdev->use_count == 1 && 234560ef66fcSMark Brown (rdev->constraints && !rdev->constraints->always_on)) { 2346414c70cbSLiam Girdwood 2347414c70cbSLiam Girdwood /* we are last user */ 23488a34e979SWEN Pingbo if (regulator_ops_is_valid(rdev, REGULATOR_CHANGE_STATUS)) { 2349a1c8a551SRichard Fitzgerald ret = _notifier_call_chain(rdev, 2350a1c8a551SRichard Fitzgerald REGULATOR_EVENT_PRE_DISABLE, 2351a1c8a551SRichard Fitzgerald NULL); 2352a1c8a551SRichard Fitzgerald if (ret & NOTIFY_STOP_MASK) 2353a1c8a551SRichard Fitzgerald return -EINVAL; 2354a1c8a551SRichard Fitzgerald 23555c5659d0SMark Brown ret = _regulator_do_disable(rdev); 2356414c70cbSLiam Girdwood if (ret < 0) { 23575da84fd9SJoe Perches rdev_err(rdev, "failed to disable\n"); 2358a1c8a551SRichard Fitzgerald _notifier_call_chain(rdev, 2359a1c8a551SRichard Fitzgerald REGULATOR_EVENT_ABORT_DISABLE, 2360a1c8a551SRichard Fitzgerald NULL); 2361414c70cbSLiam Girdwood return ret; 2362414c70cbSLiam Girdwood } 236366fda75fSMarkus Pargmann _notifier_call_chain(rdev, REGULATOR_EVENT_DISABLE, 236466fda75fSMarkus Pargmann NULL); 2365414c70cbSLiam Girdwood } 2366414c70cbSLiam Girdwood 2367414c70cbSLiam Girdwood rdev->use_count = 0; 2368414c70cbSLiam Girdwood } else if (rdev->use_count > 1) { 23698a34e979SWEN Pingbo if (regulator_ops_is_valid(rdev, REGULATOR_CHANGE_DRMS)) 2370414c70cbSLiam Girdwood drms_uA_update(rdev); 2371414c70cbSLiam Girdwood 2372414c70cbSLiam Girdwood rdev->use_count--; 2373414c70cbSLiam Girdwood } 23743801b86aSMark Brown 2375414c70cbSLiam Girdwood return ret; 2376414c70cbSLiam Girdwood } 2377414c70cbSLiam Girdwood 2378414c70cbSLiam Girdwood /** 2379414c70cbSLiam Girdwood * regulator_disable - disable regulator output 2380414c70cbSLiam Girdwood * @regulator: regulator source 2381414c70cbSLiam Girdwood * 2382cf7bbcdfSMark Brown * Disable the regulator output voltage or current. Calls to 2383cf7bbcdfSMark Brown * regulator_enable() must be balanced with calls to 2384cf7bbcdfSMark Brown * regulator_disable(). 238569279fb9SMark Brown * 2386414c70cbSLiam Girdwood * NOTE: this will only disable the regulator output if no other consumer 2387cf7bbcdfSMark Brown * devices have it enabled, the regulator device supports disabling and 2388cf7bbcdfSMark Brown * machine constraints permit this operation. 2389414c70cbSLiam Girdwood */ 2390414c70cbSLiam Girdwood int regulator_disable(struct regulator *regulator) 2391414c70cbSLiam Girdwood { 2392412aec61SDavid Brownell struct regulator_dev *rdev = regulator->rdev; 2393412aec61SDavid Brownell int ret = 0; 2394414c70cbSLiam Girdwood 23956492bc1bSMark Brown if (regulator->always_on) 23966492bc1bSMark Brown return 0; 23976492bc1bSMark Brown 239838de19faSMark Brown mutex_lock(&rdev->mutex); 23993801b86aSMark Brown ret = _regulator_disable(rdev); 240038de19faSMark Brown mutex_unlock(&rdev->mutex); 24018cbf811dSJeffrey Carlyle 24023801b86aSMark Brown if (ret == 0 && rdev->supply) 24033801b86aSMark Brown regulator_disable(rdev->supply); 24048cbf811dSJeffrey Carlyle 2405414c70cbSLiam Girdwood return ret; 2406414c70cbSLiam Girdwood } 2407414c70cbSLiam Girdwood EXPORT_SYMBOL_GPL(regulator_disable); 2408414c70cbSLiam Girdwood 2409414c70cbSLiam Girdwood /* locks held by regulator_force_disable() */ 24103801b86aSMark Brown static int _regulator_force_disable(struct regulator_dev *rdev) 2411414c70cbSLiam Girdwood { 2412414c70cbSLiam Girdwood int ret = 0; 2413414c70cbSLiam Girdwood 241470cfef26SKrzysztof Kozlowski lockdep_assert_held_once(&rdev->mutex); 241570cfef26SKrzysztof Kozlowski 2416a1c8a551SRichard Fitzgerald ret = _notifier_call_chain(rdev, REGULATOR_EVENT_FORCE_DISABLE | 2417a1c8a551SRichard Fitzgerald REGULATOR_EVENT_PRE_DISABLE, NULL); 2418a1c8a551SRichard Fitzgerald if (ret & NOTIFY_STOP_MASK) 2419a1c8a551SRichard Fitzgerald return -EINVAL; 2420a1c8a551SRichard Fitzgerald 242166fda75fSMarkus Pargmann ret = _regulator_do_disable(rdev); 2422414c70cbSLiam Girdwood if (ret < 0) { 24235da84fd9SJoe Perches rdev_err(rdev, "failed to force disable\n"); 2424a1c8a551SRichard Fitzgerald _notifier_call_chain(rdev, REGULATOR_EVENT_FORCE_DISABLE | 2425a1c8a551SRichard Fitzgerald REGULATOR_EVENT_ABORT_DISABLE, NULL); 2426414c70cbSLiam Girdwood return ret; 2427414c70cbSLiam Girdwood } 242866fda75fSMarkus Pargmann 242984b68263SMark Brown _notifier_call_chain(rdev, REGULATOR_EVENT_FORCE_DISABLE | 243084b68263SMark Brown REGULATOR_EVENT_DISABLE, NULL); 2431414c70cbSLiam Girdwood 243266fda75fSMarkus Pargmann return 0; 2433414c70cbSLiam Girdwood } 2434414c70cbSLiam Girdwood 2435414c70cbSLiam Girdwood /** 2436414c70cbSLiam Girdwood * regulator_force_disable - force disable regulator output 2437414c70cbSLiam Girdwood * @regulator: regulator source 2438414c70cbSLiam Girdwood * 2439414c70cbSLiam Girdwood * Forcibly disable the regulator output voltage or current. 2440414c70cbSLiam Girdwood * NOTE: this *will* disable the regulator output even if other consumer 2441414c70cbSLiam Girdwood * devices have it enabled. This should be used for situations when device 2442414c70cbSLiam Girdwood * damage will likely occur if the regulator is not disabled (e.g. over temp). 2443414c70cbSLiam Girdwood */ 2444414c70cbSLiam Girdwood int regulator_force_disable(struct regulator *regulator) 2445414c70cbSLiam Girdwood { 244682d15839SMark Brown struct regulator_dev *rdev = regulator->rdev; 2447414c70cbSLiam Girdwood int ret; 2448414c70cbSLiam Girdwood 244938de19faSMark Brown mutex_lock(&rdev->mutex); 2450414c70cbSLiam Girdwood regulator->uA_load = 0; 24513801b86aSMark Brown ret = _regulator_force_disable(regulator->rdev); 245238de19faSMark Brown mutex_unlock(&rdev->mutex); 24538cbf811dSJeffrey Carlyle 24543801b86aSMark Brown if (rdev->supply) 24553801b86aSMark Brown while (rdev->open_count--) 24563801b86aSMark Brown regulator_disable(rdev->supply); 24578cbf811dSJeffrey Carlyle 2458414c70cbSLiam Girdwood return ret; 2459414c70cbSLiam Girdwood } 2460414c70cbSLiam Girdwood EXPORT_SYMBOL_GPL(regulator_force_disable); 2461414c70cbSLiam Girdwood 2462da07ecd9SMark Brown static void regulator_disable_work(struct work_struct *work) 2463da07ecd9SMark Brown { 2464da07ecd9SMark Brown struct regulator_dev *rdev = container_of(work, struct regulator_dev, 2465da07ecd9SMark Brown disable_work.work); 2466da07ecd9SMark Brown int count, i, ret; 2467da07ecd9SMark Brown 246866cf9a7eSMaciej Purski regulator_lock(rdev); 2469da07ecd9SMark Brown 2470da07ecd9SMark Brown BUG_ON(!rdev->deferred_disables); 2471da07ecd9SMark Brown 2472da07ecd9SMark Brown count = rdev->deferred_disables; 2473da07ecd9SMark Brown rdev->deferred_disables = 0; 2474da07ecd9SMark Brown 2475c9ccaa0cSTirupathi Reddy /* 2476c9ccaa0cSTirupathi Reddy * Workqueue functions queue the new work instance while the previous 2477c9ccaa0cSTirupathi Reddy * work instance is being processed. Cancel the queued work instance 2478c9ccaa0cSTirupathi Reddy * as the work instance under processing does the job of the queued 2479c9ccaa0cSTirupathi Reddy * work instance. 2480c9ccaa0cSTirupathi Reddy */ 2481c9ccaa0cSTirupathi Reddy cancel_delayed_work(&rdev->disable_work); 2482c9ccaa0cSTirupathi Reddy 2483da07ecd9SMark Brown for (i = 0; i < count; i++) { 2484da07ecd9SMark Brown ret = _regulator_disable(rdev); 2485da07ecd9SMark Brown if (ret != 0) 2486da07ecd9SMark Brown rdev_err(rdev, "Deferred disable failed: %d\n", ret); 2487da07ecd9SMark Brown } 2488da07ecd9SMark Brown 248966cf9a7eSMaciej Purski regulator_unlock(rdev); 2490da07ecd9SMark Brown 2491da07ecd9SMark Brown if (rdev->supply) { 2492da07ecd9SMark Brown for (i = 0; i < count; i++) { 2493da07ecd9SMark Brown ret = regulator_disable(rdev->supply); 2494da07ecd9SMark Brown if (ret != 0) { 2495da07ecd9SMark Brown rdev_err(rdev, 2496da07ecd9SMark Brown "Supply disable failed: %d\n", ret); 2497da07ecd9SMark Brown } 2498da07ecd9SMark Brown } 2499da07ecd9SMark Brown } 2500da07ecd9SMark Brown } 2501da07ecd9SMark Brown 2502da07ecd9SMark Brown /** 2503da07ecd9SMark Brown * regulator_disable_deferred - disable regulator output with delay 2504da07ecd9SMark Brown * @regulator: regulator source 2505da07ecd9SMark Brown * @ms: miliseconds until the regulator is disabled 2506da07ecd9SMark Brown * 2507da07ecd9SMark Brown * Execute regulator_disable() on the regulator after a delay. This 2508da07ecd9SMark Brown * is intended for use with devices that require some time to quiesce. 2509da07ecd9SMark Brown * 2510da07ecd9SMark Brown * NOTE: this will only disable the regulator output if no other consumer 2511da07ecd9SMark Brown * devices have it enabled, the regulator device supports disabling and 2512da07ecd9SMark Brown * machine constraints permit this operation. 2513da07ecd9SMark Brown */ 2514da07ecd9SMark Brown int regulator_disable_deferred(struct regulator *regulator, int ms) 2515da07ecd9SMark Brown { 2516da07ecd9SMark Brown struct regulator_dev *rdev = regulator->rdev; 2517da07ecd9SMark Brown 25186492bc1bSMark Brown if (regulator->always_on) 25196492bc1bSMark Brown return 0; 25206492bc1bSMark Brown 25212b5a24a0SMark Brown if (!ms) 25222b5a24a0SMark Brown return regulator_disable(regulator); 25232b5a24a0SMark Brown 252466cf9a7eSMaciej Purski regulator_lock(rdev); 2525da07ecd9SMark Brown rdev->deferred_disables++; 2526c9ccaa0cSTirupathi Reddy mod_delayed_work(system_power_efficient_wq, &rdev->disable_work, 2527c9ccaa0cSTirupathi Reddy msecs_to_jiffies(ms)); 252866cf9a7eSMaciej Purski regulator_unlock(rdev); 2529da07ecd9SMark Brown 2530aa59802dSMark Brown return 0; 2531da07ecd9SMark Brown } 2532da07ecd9SMark Brown EXPORT_SYMBOL_GPL(regulator_disable_deferred); 2533da07ecd9SMark Brown 2534414c70cbSLiam Girdwood static int _regulator_is_enabled(struct regulator_dev *rdev) 2535414c70cbSLiam Girdwood { 253665f73508SMark Brown /* A GPIO control always takes precedence */ 25377b74d149SKim, Milo if (rdev->ena_pin) 253865f73508SMark Brown return rdev->ena_gpio_state; 253965f73508SMark Brown 25409a7f6a4cSMark Brown /* If we don't know then assume that the regulator is always on */ 25419332546fSMark Brown if (!rdev->desc->ops->is_enabled) 25429a7f6a4cSMark Brown return 1; 2543414c70cbSLiam Girdwood 25449332546fSMark Brown return rdev->desc->ops->is_enabled(rdev); 2545414c70cbSLiam Girdwood } 2546414c70cbSLiam Girdwood 25473d67fe95SMaciej Purski static int _regulator_list_voltage(struct regulator_dev *rdev, 25483a40cfc3SSascha Hauer unsigned selector, int lock) 25493a40cfc3SSascha Hauer { 25503a40cfc3SSascha Hauer const struct regulator_ops *ops = rdev->desc->ops; 25513a40cfc3SSascha Hauer int ret; 25523a40cfc3SSascha Hauer 25533a40cfc3SSascha Hauer if (rdev->desc->fixed_uV && rdev->desc->n_voltages == 1 && !selector) 25543a40cfc3SSascha Hauer return rdev->desc->fixed_uV; 25553a40cfc3SSascha Hauer 25563a40cfc3SSascha Hauer if (ops->list_voltage) { 25573a40cfc3SSascha Hauer if (selector >= rdev->desc->n_voltages) 25583a40cfc3SSascha Hauer return -EINVAL; 25593a40cfc3SSascha Hauer if (lock) 256066cf9a7eSMaciej Purski regulator_lock(rdev); 25613a40cfc3SSascha Hauer ret = ops->list_voltage(rdev, selector); 25623a40cfc3SSascha Hauer if (lock) 256366cf9a7eSMaciej Purski regulator_unlock(rdev); 2564fd086045SMatthias Kaehlcke } else if (rdev->is_switch && rdev->supply) { 25653d67fe95SMaciej Purski ret = _regulator_list_voltage(rdev->supply->rdev, 25663d67fe95SMaciej Purski selector, lock); 25673a40cfc3SSascha Hauer } else { 25683a40cfc3SSascha Hauer return -EINVAL; 25693a40cfc3SSascha Hauer } 25703a40cfc3SSascha Hauer 25713a40cfc3SSascha Hauer if (ret > 0) { 25723a40cfc3SSascha Hauer if (ret < rdev->constraints->min_uV) 25733a40cfc3SSascha Hauer ret = 0; 25743a40cfc3SSascha Hauer else if (ret > rdev->constraints->max_uV) 25753a40cfc3SSascha Hauer ret = 0; 25763a40cfc3SSascha Hauer } 25773a40cfc3SSascha Hauer 25783a40cfc3SSascha Hauer return ret; 25793a40cfc3SSascha Hauer } 25803a40cfc3SSascha Hauer 2581414c70cbSLiam Girdwood /** 2582414c70cbSLiam Girdwood * regulator_is_enabled - is the regulator output enabled 2583414c70cbSLiam Girdwood * @regulator: regulator source 2584414c70cbSLiam Girdwood * 2585412aec61SDavid Brownell * Returns positive if the regulator driver backing the source/client 2586412aec61SDavid Brownell * has requested that the device be enabled, zero if it hasn't, else a 2587412aec61SDavid Brownell * negative errno code. 2588412aec61SDavid Brownell * 2589412aec61SDavid Brownell * Note that the device backing this regulator handle can have multiple 2590412aec61SDavid Brownell * users, so it might be enabled even if regulator_enable() was never 2591412aec61SDavid Brownell * called for this particular source. 2592414c70cbSLiam Girdwood */ 2593414c70cbSLiam Girdwood int regulator_is_enabled(struct regulator *regulator) 2594414c70cbSLiam Girdwood { 25959332546fSMark Brown int ret; 25969332546fSMark Brown 25976492bc1bSMark Brown if (regulator->always_on) 25986492bc1bSMark Brown return 1; 25996492bc1bSMark Brown 260038de19faSMark Brown mutex_lock(®ulator->rdev->mutex); 26019332546fSMark Brown ret = _regulator_is_enabled(regulator->rdev); 260238de19faSMark Brown mutex_unlock(®ulator->rdev->mutex); 26039332546fSMark Brown 26049332546fSMark Brown return ret; 2605414c70cbSLiam Girdwood } 2606414c70cbSLiam Girdwood EXPORT_SYMBOL_GPL(regulator_is_enabled); 2607414c70cbSLiam Girdwood 2608414c70cbSLiam Girdwood /** 26094367cfdcSDavid Brownell * regulator_count_voltages - count regulator_list_voltage() selectors 26104367cfdcSDavid Brownell * @regulator: regulator source 26114367cfdcSDavid Brownell * 26124367cfdcSDavid Brownell * Returns number of selectors, or negative errno. Selectors are 26134367cfdcSDavid Brownell * numbered starting at zero, and typically correspond to bitfields 26144367cfdcSDavid Brownell * in hardware registers. 26154367cfdcSDavid Brownell */ 26164367cfdcSDavid Brownell int regulator_count_voltages(struct regulator *regulator) 26174367cfdcSDavid Brownell { 26184367cfdcSDavid Brownell struct regulator_dev *rdev = regulator->rdev; 26194367cfdcSDavid Brownell 262026988efeSJavier Martinez Canillas if (rdev->desc->n_voltages) 262126988efeSJavier Martinez Canillas return rdev->desc->n_voltages; 262226988efeSJavier Martinez Canillas 2623fd086045SMatthias Kaehlcke if (!rdev->is_switch || !rdev->supply) 262426988efeSJavier Martinez Canillas return -EINVAL; 262526988efeSJavier Martinez Canillas 262626988efeSJavier Martinez Canillas return regulator_count_voltages(rdev->supply); 26274367cfdcSDavid Brownell } 26284367cfdcSDavid Brownell EXPORT_SYMBOL_GPL(regulator_count_voltages); 26294367cfdcSDavid Brownell 26304367cfdcSDavid Brownell /** 26314367cfdcSDavid Brownell * regulator_list_voltage - enumerate supported voltages 26324367cfdcSDavid Brownell * @regulator: regulator source 26334367cfdcSDavid Brownell * @selector: identify voltage to list 26344367cfdcSDavid Brownell * Context: can sleep 26354367cfdcSDavid Brownell * 26364367cfdcSDavid Brownell * Returns a voltage that can be passed to @regulator_set_voltage(), 263788393161SThomas Weber * zero if this selector code can't be used on this system, or a 26384367cfdcSDavid Brownell * negative errno. 26394367cfdcSDavid Brownell */ 26404367cfdcSDavid Brownell int regulator_list_voltage(struct regulator *regulator, unsigned selector) 26414367cfdcSDavid Brownell { 26423d67fe95SMaciej Purski return _regulator_list_voltage(regulator->rdev, selector, 1); 26434367cfdcSDavid Brownell } 26444367cfdcSDavid Brownell EXPORT_SYMBOL_GPL(regulator_list_voltage); 26454367cfdcSDavid Brownell 26464367cfdcSDavid Brownell /** 264704eca28cSTuomas Tynkkynen * regulator_get_regmap - get the regulator's register map 264804eca28cSTuomas Tynkkynen * @regulator: regulator source 264904eca28cSTuomas Tynkkynen * 265004eca28cSTuomas Tynkkynen * Returns the register map for the given regulator, or an ERR_PTR value 265104eca28cSTuomas Tynkkynen * if the regulator doesn't use regmap. 265204eca28cSTuomas Tynkkynen */ 265304eca28cSTuomas Tynkkynen struct regmap *regulator_get_regmap(struct regulator *regulator) 265404eca28cSTuomas Tynkkynen { 265504eca28cSTuomas Tynkkynen struct regmap *map = regulator->rdev->regmap; 265604eca28cSTuomas Tynkkynen 265704eca28cSTuomas Tynkkynen return map ? map : ERR_PTR(-EOPNOTSUPP); 265804eca28cSTuomas Tynkkynen } 265904eca28cSTuomas Tynkkynen 266004eca28cSTuomas Tynkkynen /** 266104eca28cSTuomas Tynkkynen * regulator_get_hardware_vsel_register - get the HW voltage selector register 266204eca28cSTuomas Tynkkynen * @regulator: regulator source 266304eca28cSTuomas Tynkkynen * @vsel_reg: voltage selector register, output parameter 266404eca28cSTuomas Tynkkynen * @vsel_mask: mask for voltage selector bitfield, output parameter 266504eca28cSTuomas Tynkkynen * 266604eca28cSTuomas Tynkkynen * Returns the hardware register offset and bitmask used for setting the 266704eca28cSTuomas Tynkkynen * regulator voltage. This might be useful when configuring voltage-scaling 266804eca28cSTuomas Tynkkynen * hardware or firmware that can make I2C requests behind the kernel's back, 266904eca28cSTuomas Tynkkynen * for example. 267004eca28cSTuomas Tynkkynen * 267104eca28cSTuomas Tynkkynen * On success, the output parameters @vsel_reg and @vsel_mask are filled in 267204eca28cSTuomas Tynkkynen * and 0 is returned, otherwise a negative errno is returned. 267304eca28cSTuomas Tynkkynen */ 267404eca28cSTuomas Tynkkynen int regulator_get_hardware_vsel_register(struct regulator *regulator, 267504eca28cSTuomas Tynkkynen unsigned *vsel_reg, 267604eca28cSTuomas Tynkkynen unsigned *vsel_mask) 267704eca28cSTuomas Tynkkynen { 267804eca28cSTuomas Tynkkynen struct regulator_dev *rdev = regulator->rdev; 267939f5460dSGuodong Xu const struct regulator_ops *ops = rdev->desc->ops; 268004eca28cSTuomas Tynkkynen 268104eca28cSTuomas Tynkkynen if (ops->set_voltage_sel != regulator_set_voltage_sel_regmap) 268204eca28cSTuomas Tynkkynen return -EOPNOTSUPP; 268304eca28cSTuomas Tynkkynen 268404eca28cSTuomas Tynkkynen *vsel_reg = rdev->desc->vsel_reg; 268504eca28cSTuomas Tynkkynen *vsel_mask = rdev->desc->vsel_mask; 268604eca28cSTuomas Tynkkynen 268704eca28cSTuomas Tynkkynen return 0; 268804eca28cSTuomas Tynkkynen } 268904eca28cSTuomas Tynkkynen EXPORT_SYMBOL_GPL(regulator_get_hardware_vsel_register); 269004eca28cSTuomas Tynkkynen 269104eca28cSTuomas Tynkkynen /** 269204eca28cSTuomas Tynkkynen * regulator_list_hardware_vsel - get the HW-specific register value for a selector 269304eca28cSTuomas Tynkkynen * @regulator: regulator source 269404eca28cSTuomas Tynkkynen * @selector: identify voltage to list 269504eca28cSTuomas Tynkkynen * 269604eca28cSTuomas Tynkkynen * Converts the selector to a hardware-specific voltage selector that can be 269704eca28cSTuomas Tynkkynen * directly written to the regulator registers. The address of the voltage 269804eca28cSTuomas Tynkkynen * register can be determined by calling @regulator_get_hardware_vsel_register. 269904eca28cSTuomas Tynkkynen * 270004eca28cSTuomas Tynkkynen * On error a negative errno is returned. 270104eca28cSTuomas Tynkkynen */ 270204eca28cSTuomas Tynkkynen int regulator_list_hardware_vsel(struct regulator *regulator, 270304eca28cSTuomas Tynkkynen unsigned selector) 270404eca28cSTuomas Tynkkynen { 270504eca28cSTuomas Tynkkynen struct regulator_dev *rdev = regulator->rdev; 270639f5460dSGuodong Xu const struct regulator_ops *ops = rdev->desc->ops; 270704eca28cSTuomas Tynkkynen 270804eca28cSTuomas Tynkkynen if (selector >= rdev->desc->n_voltages) 270904eca28cSTuomas Tynkkynen return -EINVAL; 271004eca28cSTuomas Tynkkynen if (ops->set_voltage_sel != regulator_set_voltage_sel_regmap) 271104eca28cSTuomas Tynkkynen return -EOPNOTSUPP; 271204eca28cSTuomas Tynkkynen 271304eca28cSTuomas Tynkkynen return selector; 271404eca28cSTuomas Tynkkynen } 271504eca28cSTuomas Tynkkynen EXPORT_SYMBOL_GPL(regulator_list_hardware_vsel); 271604eca28cSTuomas Tynkkynen 271704eca28cSTuomas Tynkkynen /** 27182a668a8bSPaul Walmsley * regulator_get_linear_step - return the voltage step size between VSEL values 27192a668a8bSPaul Walmsley * @regulator: regulator source 27202a668a8bSPaul Walmsley * 27212a668a8bSPaul Walmsley * Returns the voltage step size between VSEL values for linear 27222a668a8bSPaul Walmsley * regulators, or return 0 if the regulator isn't a linear regulator. 27232a668a8bSPaul Walmsley */ 27242a668a8bSPaul Walmsley unsigned int regulator_get_linear_step(struct regulator *regulator) 27252a668a8bSPaul Walmsley { 27262a668a8bSPaul Walmsley struct regulator_dev *rdev = regulator->rdev; 27272a668a8bSPaul Walmsley 27282a668a8bSPaul Walmsley return rdev->desc->uV_step; 27292a668a8bSPaul Walmsley } 27302a668a8bSPaul Walmsley EXPORT_SYMBOL_GPL(regulator_get_linear_step); 27312a668a8bSPaul Walmsley 27322a668a8bSPaul Walmsley /** 2733a7a1ad90SMark Brown * regulator_is_supported_voltage - check if a voltage range can be supported 2734a7a1ad90SMark Brown * 2735a7a1ad90SMark Brown * @regulator: Regulator to check. 2736a7a1ad90SMark Brown * @min_uV: Minimum required voltage in uV. 2737a7a1ad90SMark Brown * @max_uV: Maximum required voltage in uV. 2738a7a1ad90SMark Brown * 2739a7a1ad90SMark Brown * Returns a boolean or a negative error code. 2740a7a1ad90SMark Brown */ 2741a7a1ad90SMark Brown int regulator_is_supported_voltage(struct regulator *regulator, 2742a7a1ad90SMark Brown int min_uV, int max_uV) 2743a7a1ad90SMark Brown { 2744c5f3939bSMark Brown struct regulator_dev *rdev = regulator->rdev; 2745a7a1ad90SMark Brown int i, voltages, ret; 2746a7a1ad90SMark Brown 2747c5f3939bSMark Brown /* If we can't change voltage check the current voltage */ 27488a34e979SWEN Pingbo if (!regulator_ops_is_valid(rdev, REGULATOR_CHANGE_VOLTAGE)) { 2749c5f3939bSMark Brown ret = regulator_get_voltage(regulator); 2750c5f3939bSMark Brown if (ret >= 0) 27510d25d09dSJingoo Han return min_uV <= ret && ret <= max_uV; 2752c5f3939bSMark Brown else 2753c5f3939bSMark Brown return ret; 2754c5f3939bSMark Brown } 2755c5f3939bSMark Brown 2756bd7a2b60SPawel Moll /* Any voltage within constrains range is fine? */ 2757bd7a2b60SPawel Moll if (rdev->desc->continuous_voltage_range) 2758bd7a2b60SPawel Moll return min_uV >= rdev->constraints->min_uV && 2759bd7a2b60SPawel Moll max_uV <= rdev->constraints->max_uV; 2760bd7a2b60SPawel Moll 2761a7a1ad90SMark Brown ret = regulator_count_voltages(regulator); 2762a7a1ad90SMark Brown if (ret < 0) 2763a7a1ad90SMark Brown return ret; 2764a7a1ad90SMark Brown voltages = ret; 2765a7a1ad90SMark Brown 2766a7a1ad90SMark Brown for (i = 0; i < voltages; i++) { 2767a7a1ad90SMark Brown ret = regulator_list_voltage(regulator, i); 2768a7a1ad90SMark Brown 2769a7a1ad90SMark Brown if (ret >= min_uV && ret <= max_uV) 2770a7a1ad90SMark Brown return 1; 2771a7a1ad90SMark Brown } 2772a7a1ad90SMark Brown 2773a7a1ad90SMark Brown return 0; 2774a7a1ad90SMark Brown } 2775a398eaa2SMark Brown EXPORT_SYMBOL_GPL(regulator_is_supported_voltage); 2776a7a1ad90SMark Brown 2777a204f41eSSascha Hauer static int regulator_map_voltage(struct regulator_dev *rdev, int min_uV, 2778a204f41eSSascha Hauer int max_uV) 2779a204f41eSSascha Hauer { 2780a204f41eSSascha Hauer const struct regulator_desc *desc = rdev->desc; 2781a204f41eSSascha Hauer 2782a204f41eSSascha Hauer if (desc->ops->map_voltage) 2783a204f41eSSascha Hauer return desc->ops->map_voltage(rdev, min_uV, max_uV); 2784a204f41eSSascha Hauer 2785a204f41eSSascha Hauer if (desc->ops->list_voltage == regulator_list_voltage_linear) 2786a204f41eSSascha Hauer return regulator_map_voltage_linear(rdev, min_uV, max_uV); 2787a204f41eSSascha Hauer 2788a204f41eSSascha Hauer if (desc->ops->list_voltage == regulator_list_voltage_linear_range) 2789a204f41eSSascha Hauer return regulator_map_voltage_linear_range(rdev, min_uV, max_uV); 2790a204f41eSSascha Hauer 2791a204f41eSSascha Hauer return regulator_map_voltage_iterate(rdev, min_uV, max_uV); 2792a204f41eSSascha Hauer } 2793a204f41eSSascha Hauer 27947179569aSHeiko Stübner static int _regulator_call_set_voltage(struct regulator_dev *rdev, 27957179569aSHeiko Stübner int min_uV, int max_uV, 27967179569aSHeiko Stübner unsigned *selector) 27977179569aSHeiko Stübner { 27987179569aSHeiko Stübner struct pre_voltage_change_data data; 27997179569aSHeiko Stübner int ret; 28007179569aSHeiko Stübner 28017179569aSHeiko Stübner data.old_uV = _regulator_get_voltage(rdev); 28027179569aSHeiko Stübner data.min_uV = min_uV; 28037179569aSHeiko Stübner data.max_uV = max_uV; 28047179569aSHeiko Stübner ret = _notifier_call_chain(rdev, REGULATOR_EVENT_PRE_VOLTAGE_CHANGE, 28057179569aSHeiko Stübner &data); 28067179569aSHeiko Stübner if (ret & NOTIFY_STOP_MASK) 28077179569aSHeiko Stübner return -EINVAL; 28087179569aSHeiko Stübner 28097179569aSHeiko Stübner ret = rdev->desc->ops->set_voltage(rdev, min_uV, max_uV, selector); 28107179569aSHeiko Stübner if (ret >= 0) 28117179569aSHeiko Stübner return ret; 28127179569aSHeiko Stübner 28137179569aSHeiko Stübner _notifier_call_chain(rdev, REGULATOR_EVENT_ABORT_VOLTAGE_CHANGE, 28147179569aSHeiko Stübner (void *)data.old_uV); 28157179569aSHeiko Stübner 28167179569aSHeiko Stübner return ret; 28177179569aSHeiko Stübner } 28187179569aSHeiko Stübner 28197179569aSHeiko Stübner static int _regulator_call_set_voltage_sel(struct regulator_dev *rdev, 28207179569aSHeiko Stübner int uV, unsigned selector) 28217179569aSHeiko Stübner { 28227179569aSHeiko Stübner struct pre_voltage_change_data data; 28237179569aSHeiko Stübner int ret; 28247179569aSHeiko Stübner 28257179569aSHeiko Stübner data.old_uV = _regulator_get_voltage(rdev); 28267179569aSHeiko Stübner data.min_uV = uV; 28277179569aSHeiko Stübner data.max_uV = uV; 28287179569aSHeiko Stübner ret = _notifier_call_chain(rdev, REGULATOR_EVENT_PRE_VOLTAGE_CHANGE, 28297179569aSHeiko Stübner &data); 28307179569aSHeiko Stübner if (ret & NOTIFY_STOP_MASK) 28317179569aSHeiko Stübner return -EINVAL; 28327179569aSHeiko Stübner 28337179569aSHeiko Stübner ret = rdev->desc->ops->set_voltage_sel(rdev, selector); 28347179569aSHeiko Stübner if (ret >= 0) 28357179569aSHeiko Stübner return ret; 28367179569aSHeiko Stübner 28377179569aSHeiko Stübner _notifier_call_chain(rdev, REGULATOR_EVENT_ABORT_VOLTAGE_CHANGE, 28387179569aSHeiko Stübner (void *)data.old_uV); 28397179569aSHeiko Stübner 28407179569aSHeiko Stübner return ret; 28417179569aSHeiko Stübner } 28427179569aSHeiko Stübner 284373e705bfSMatthias Kaehlcke static int _regulator_set_voltage_time(struct regulator_dev *rdev, 284473e705bfSMatthias Kaehlcke int old_uV, int new_uV) 284573e705bfSMatthias Kaehlcke { 284673e705bfSMatthias Kaehlcke unsigned int ramp_delay = 0; 284773e705bfSMatthias Kaehlcke 284873e705bfSMatthias Kaehlcke if (rdev->constraints->ramp_delay) 284973e705bfSMatthias Kaehlcke ramp_delay = rdev->constraints->ramp_delay; 285073e705bfSMatthias Kaehlcke else if (rdev->desc->ramp_delay) 285173e705bfSMatthias Kaehlcke ramp_delay = rdev->desc->ramp_delay; 2852d6c1dc3fSLaxman Dewangan else if (rdev->constraints->settling_time) 2853d6c1dc3fSLaxman Dewangan return rdev->constraints->settling_time; 28543ffad468SMatthias Kaehlcke else if (rdev->constraints->settling_time_up && 28553ffad468SMatthias Kaehlcke (new_uV > old_uV)) 28563ffad468SMatthias Kaehlcke return rdev->constraints->settling_time_up; 28573ffad468SMatthias Kaehlcke else if (rdev->constraints->settling_time_down && 28583ffad468SMatthias Kaehlcke (new_uV < old_uV)) 28593ffad468SMatthias Kaehlcke return rdev->constraints->settling_time_down; 286073e705bfSMatthias Kaehlcke 286173e705bfSMatthias Kaehlcke if (ramp_delay == 0) { 2862ba14fa1aSH. Nikolaus Schaller rdev_dbg(rdev, "ramp_delay not set\n"); 286373e705bfSMatthias Kaehlcke return 0; 286473e705bfSMatthias Kaehlcke } 286573e705bfSMatthias Kaehlcke 286673e705bfSMatthias Kaehlcke return DIV_ROUND_UP(abs(new_uV - old_uV), ramp_delay); 286773e705bfSMatthias Kaehlcke } 286873e705bfSMatthias Kaehlcke 286975790251SMark Brown static int _regulator_do_set_voltage(struct regulator_dev *rdev, 287075790251SMark Brown int min_uV, int max_uV) 287175790251SMark Brown { 287275790251SMark Brown int ret; 287377af1b26SLinus Walleij int delay = 0; 2874e113d792SMark Brown int best_val = 0; 287575790251SMark Brown unsigned int selector; 2876eba41a5eSAxel Lin int old_selector = -1; 287757995a48SMatthias Kaehlcke const struct regulator_ops *ops = rdev->desc->ops; 287873e705bfSMatthias Kaehlcke int old_uV = _regulator_get_voltage(rdev); 287975790251SMark Brown 288075790251SMark Brown trace_regulator_set_voltage(rdev_get_name(rdev), min_uV, max_uV); 288175790251SMark Brown 2882bf5892a8SMark Brown min_uV += rdev->constraints->uV_offset; 2883bf5892a8SMark Brown max_uV += rdev->constraints->uV_offset; 2884bf5892a8SMark Brown 288577af1b26SLinus Walleij /* 288677af1b26SLinus Walleij * If we can't obtain the old selector there is not enough 288777af1b26SLinus Walleij * info to call set_voltage_time_sel(). 288877af1b26SLinus Walleij */ 28898b7485efSAxel Lin if (_regulator_is_enabled(rdev) && 289057995a48SMatthias Kaehlcke ops->set_voltage_time_sel && ops->get_voltage_sel) { 289157995a48SMatthias Kaehlcke old_selector = ops->get_voltage_sel(rdev); 2892eba41a5eSAxel Lin if (old_selector < 0) 2893eba41a5eSAxel Lin return old_selector; 2894eba41a5eSAxel Lin } 289577af1b26SLinus Walleij 289657995a48SMatthias Kaehlcke if (ops->set_voltage) { 28977179569aSHeiko Stübner ret = _regulator_call_set_voltage(rdev, min_uV, max_uV, 289875790251SMark Brown &selector); 2899e113d792SMark Brown 2900e113d792SMark Brown if (ret >= 0) { 290157995a48SMatthias Kaehlcke if (ops->list_voltage) 290257995a48SMatthias Kaehlcke best_val = ops->list_voltage(rdev, 2903e113d792SMark Brown selector); 2904e113d792SMark Brown else 2905e113d792SMark Brown best_val = _regulator_get_voltage(rdev); 2906e113d792SMark Brown } 2907e113d792SMark Brown 290857995a48SMatthias Kaehlcke } else if (ops->set_voltage_sel) { 2909a204f41eSSascha Hauer ret = regulator_map_voltage(rdev, min_uV, max_uV); 2910e843fc46SMark Brown if (ret >= 0) { 291157995a48SMatthias Kaehlcke best_val = ops->list_voltage(rdev, ret); 2912e113d792SMark Brown if (min_uV <= best_val && max_uV >= best_val) { 2913e843fc46SMark Brown selector = ret; 2914c66a566aSAxel Lin if (old_selector == selector) 2915c66a566aSAxel Lin ret = 0; 2916c66a566aSAxel Lin else 29177179569aSHeiko Stübner ret = _regulator_call_set_voltage_sel( 29187179569aSHeiko Stübner rdev, best_val, selector); 2919e113d792SMark Brown } else { 2920e113d792SMark Brown ret = -EINVAL; 2921e113d792SMark Brown } 2922e843fc46SMark Brown } 2923e8eef82bSMark Brown } else { 2924e8eef82bSMark Brown ret = -EINVAL; 2925e8eef82bSMark Brown } 2926e8eef82bSMark Brown 292731dfe686SMatthias Kaehlcke if (ret) 292831dfe686SMatthias Kaehlcke goto out; 2929eba41a5eSAxel Lin 293073e705bfSMatthias Kaehlcke if (ops->set_voltage_time_sel) { 293173e705bfSMatthias Kaehlcke /* 293273e705bfSMatthias Kaehlcke * Call set_voltage_time_sel if successfully obtained 293373e705bfSMatthias Kaehlcke * old_selector 293473e705bfSMatthias Kaehlcke */ 293573e705bfSMatthias Kaehlcke if (old_selector >= 0 && old_selector != selector) 293673e705bfSMatthias Kaehlcke delay = ops->set_voltage_time_sel(rdev, old_selector, 293773e705bfSMatthias Kaehlcke selector); 293873e705bfSMatthias Kaehlcke } else { 293973e705bfSMatthias Kaehlcke if (old_uV != best_val) { 294073e705bfSMatthias Kaehlcke if (ops->set_voltage_time) 294173e705bfSMatthias Kaehlcke delay = ops->set_voltage_time(rdev, old_uV, 294273e705bfSMatthias Kaehlcke best_val); 294373e705bfSMatthias Kaehlcke else 294473e705bfSMatthias Kaehlcke delay = _regulator_set_voltage_time(rdev, 294573e705bfSMatthias Kaehlcke old_uV, 294673e705bfSMatthias Kaehlcke best_val); 294773e705bfSMatthias Kaehlcke } 294873e705bfSMatthias Kaehlcke } 294973e705bfSMatthias Kaehlcke 2950eba41a5eSAxel Lin if (delay < 0) { 295173e705bfSMatthias Kaehlcke rdev_warn(rdev, "failed to get delay: %d\n", delay); 2952eba41a5eSAxel Lin delay = 0; 2953e8eef82bSMark Brown } 295475790251SMark Brown 295577af1b26SLinus Walleij /* Insert any necessary delays */ 295677af1b26SLinus Walleij if (delay >= 1000) { 295777af1b26SLinus Walleij mdelay(delay / 1000); 295877af1b26SLinus Walleij udelay(delay % 1000); 295977af1b26SLinus Walleij } else if (delay) { 296077af1b26SLinus Walleij udelay(delay); 296177af1b26SLinus Walleij } 296277af1b26SLinus Walleij 296331dfe686SMatthias Kaehlcke if (best_val >= 0) { 29642f6c797fSAxel Lin unsigned long data = best_val; 29652f6c797fSAxel Lin 2966ded06a52SMark Brown _notifier_call_chain(rdev, REGULATOR_EVENT_VOLTAGE_CHANGE, 29672f6c797fSAxel Lin (void *)data); 29682f6c797fSAxel Lin } 2969ded06a52SMark Brown 297031dfe686SMatthias Kaehlcke out: 2971eba41a5eSAxel Lin trace_regulator_set_voltage_complete(rdev_get_name(rdev), best_val); 297275790251SMark Brown 297375790251SMark Brown return ret; 297475790251SMark Brown } 297575790251SMark Brown 2976f7efad10SChunyan Zhang static int _regulator_do_set_suspend_voltage(struct regulator_dev *rdev, 2977f7efad10SChunyan Zhang int min_uV, int max_uV, suspend_state_t state) 2978f7efad10SChunyan Zhang { 2979f7efad10SChunyan Zhang struct regulator_state *rstate; 2980f7efad10SChunyan Zhang int uV, sel; 2981f7efad10SChunyan Zhang 2982f7efad10SChunyan Zhang rstate = regulator_get_suspend_state(rdev, state); 2983f7efad10SChunyan Zhang if (rstate == NULL) 2984f7efad10SChunyan Zhang return -EINVAL; 2985f7efad10SChunyan Zhang 2986f7efad10SChunyan Zhang if (min_uV < rstate->min_uV) 2987f7efad10SChunyan Zhang min_uV = rstate->min_uV; 2988f7efad10SChunyan Zhang if (max_uV > rstate->max_uV) 2989f7efad10SChunyan Zhang max_uV = rstate->max_uV; 2990f7efad10SChunyan Zhang 2991f7efad10SChunyan Zhang sel = regulator_map_voltage(rdev, min_uV, max_uV); 2992f7efad10SChunyan Zhang if (sel < 0) 2993f7efad10SChunyan Zhang return sel; 2994f7efad10SChunyan Zhang 2995f7efad10SChunyan Zhang uV = rdev->desc->ops->list_voltage(rdev, sel); 2996f7efad10SChunyan Zhang if (uV >= min_uV && uV <= max_uV) 2997f7efad10SChunyan Zhang rstate->uV = uV; 2998f7efad10SChunyan Zhang 2999f7efad10SChunyan Zhang return 0; 3000f7efad10SChunyan Zhang } 3001f7efad10SChunyan Zhang 3002a9f226bcSSascha Hauer static int regulator_set_voltage_unlocked(struct regulator *regulator, 3003c360a6dfSChunyan Zhang int min_uV, int max_uV, 3004c360a6dfSChunyan Zhang suspend_state_t state) 3005414c70cbSLiam Girdwood { 3006414c70cbSLiam Girdwood struct regulator_dev *rdev = regulator->rdev; 3007c360a6dfSChunyan Zhang struct regulator_voltage *voltage = ®ulator->voltage[state]; 300895a3c23aSMark Brown int ret = 0; 300992d7a558SPaolo Pisati int old_min_uV, old_max_uV; 3010c00dc359SBjorn Andersson int current_uV; 301138de19faSMark Brown int best_supply_uV = 0; 301238de19faSMark Brown int supply_change_uV = 0; 3013414c70cbSLiam Girdwood 301495a3c23aSMark Brown /* If we're setting the same range as last time the change 301595a3c23aSMark Brown * should be a noop (some cpufreq implementations use the same 301695a3c23aSMark Brown * voltage for multiple frequencies, for example). 301795a3c23aSMark Brown */ 3018c360a6dfSChunyan Zhang if (voltage->min_uV == min_uV && voltage->max_uV == max_uV) 301995a3c23aSMark Brown goto out; 302095a3c23aSMark Brown 3021c00dc359SBjorn Andersson /* If we're trying to set a range that overlaps the current voltage, 3022d3fb9800SViresh Kumar * return successfully even though the regulator does not support 3023c00dc359SBjorn Andersson * changing the voltage. 3024c00dc359SBjorn Andersson */ 30258a34e979SWEN Pingbo if (!regulator_ops_is_valid(rdev, REGULATOR_CHANGE_VOLTAGE)) { 3026c00dc359SBjorn Andersson current_uV = _regulator_get_voltage(rdev); 3027c00dc359SBjorn Andersson if (min_uV <= current_uV && current_uV <= max_uV) { 3028c360a6dfSChunyan Zhang voltage->min_uV = min_uV; 3029c360a6dfSChunyan Zhang voltage->max_uV = max_uV; 3030c00dc359SBjorn Andersson goto out; 3031c00dc359SBjorn Andersson } 3032c00dc359SBjorn Andersson } 3033c00dc359SBjorn Andersson 3034414c70cbSLiam Girdwood /* sanity check */ 3035e8eef82bSMark Brown if (!rdev->desc->ops->set_voltage && 3036e8eef82bSMark Brown !rdev->desc->ops->set_voltage_sel) { 3037414c70cbSLiam Girdwood ret = -EINVAL; 3038414c70cbSLiam Girdwood goto out; 3039414c70cbSLiam Girdwood } 3040414c70cbSLiam Girdwood 3041414c70cbSLiam Girdwood /* constraints check */ 3042414c70cbSLiam Girdwood ret = regulator_check_voltage(rdev, &min_uV, &max_uV); 3043414c70cbSLiam Girdwood if (ret < 0) 3044414c70cbSLiam Girdwood goto out; 304592d7a558SPaolo Pisati 304692d7a558SPaolo Pisati /* restore original values in case of error */ 3047c360a6dfSChunyan Zhang old_min_uV = voltage->min_uV; 3048c360a6dfSChunyan Zhang old_max_uV = voltage->max_uV; 3049c360a6dfSChunyan Zhang voltage->min_uV = min_uV; 3050c360a6dfSChunyan Zhang voltage->max_uV = max_uV; 30513a93f2a9SMark Brown 3052c360a6dfSChunyan Zhang ret = regulator_check_consumers(rdev, &min_uV, &max_uV, state); 305305fda3b1SThomas Petazzoni if (ret < 0) 305492d7a558SPaolo Pisati goto out2; 305505fda3b1SThomas Petazzoni 305643fc99f2SMark Brown if (rdev->supply && 305743fc99f2SMark Brown regulator_ops_is_valid(rdev->supply->rdev, 305843fc99f2SMark Brown REGULATOR_CHANGE_VOLTAGE) && 30592c2874b1STirupathi Reddy (rdev->desc->min_dropout_uV || !(rdev->desc->ops->get_voltage || 30602c2874b1STirupathi Reddy rdev->desc->ops->get_voltage_sel))) { 3061fc42112cSSascha Hauer int current_supply_uV; 3062fc42112cSSascha Hauer int selector; 3063fc42112cSSascha Hauer 3064fc42112cSSascha Hauer selector = regulator_map_voltage(rdev, min_uV, max_uV); 3065fc42112cSSascha Hauer if (selector < 0) { 3066fc42112cSSascha Hauer ret = selector; 306738de19faSMark Brown goto out2; 3068fc42112cSSascha Hauer } 3069fc42112cSSascha Hauer 307000cb9f4fSMark Brown best_supply_uV = _regulator_list_voltage(rdev, selector, 0); 3071fc42112cSSascha Hauer if (best_supply_uV < 0) { 3072fc42112cSSascha Hauer ret = best_supply_uV; 307338de19faSMark Brown goto out2; 3074fc42112cSSascha Hauer } 3075fc42112cSSascha Hauer 3076fc42112cSSascha Hauer best_supply_uV += rdev->desc->min_dropout_uV; 3077fc42112cSSascha Hauer 3078fc42112cSSascha Hauer current_supply_uV = _regulator_get_voltage(rdev->supply->rdev); 3079fc42112cSSascha Hauer if (current_supply_uV < 0) { 3080fc42112cSSascha Hauer ret = current_supply_uV; 308138de19faSMark Brown goto out2; 3082fc42112cSSascha Hauer } 3083fc42112cSSascha Hauer 3084fc42112cSSascha Hauer supply_change_uV = best_supply_uV - current_supply_uV; 3085fc42112cSSascha Hauer } 3086fc42112cSSascha Hauer 3087fc42112cSSascha Hauer if (supply_change_uV > 0) { 3088fc42112cSSascha Hauer ret = regulator_set_voltage_unlocked(rdev->supply, 3089c360a6dfSChunyan Zhang best_supply_uV, INT_MAX, state); 3090fc42112cSSascha Hauer if (ret) { 3091fc42112cSSascha Hauer dev_err(&rdev->dev, "Failed to increase supply voltage: %d\n", 3092fc42112cSSascha Hauer ret); 309338de19faSMark Brown goto out2; 3094fc42112cSSascha Hauer } 3095fc42112cSSascha Hauer } 3096fc42112cSSascha Hauer 3097f7efad10SChunyan Zhang if (state == PM_SUSPEND_ON) 309875790251SMark Brown ret = _regulator_do_set_voltage(rdev, min_uV, max_uV); 3099f7efad10SChunyan Zhang else 3100f7efad10SChunyan Zhang ret = _regulator_do_set_suspend_voltage(rdev, min_uV, 3101f7efad10SChunyan Zhang max_uV, state); 310292d7a558SPaolo Pisati if (ret < 0) 310338de19faSMark Brown goto out2; 310402fa3ec0SMark Brown 3105fc42112cSSascha Hauer if (supply_change_uV < 0) { 3106fc42112cSSascha Hauer ret = regulator_set_voltage_unlocked(rdev->supply, 3107c360a6dfSChunyan Zhang best_supply_uV, INT_MAX, state); 3108fc42112cSSascha Hauer if (ret) 3109fc42112cSSascha Hauer dev_warn(&rdev->dev, "Failed to decrease supply voltage: %d\n", 3110fc42112cSSascha Hauer ret); 3111fc42112cSSascha Hauer /* No need to fail here */ 3112fc42112cSSascha Hauer ret = 0; 3113fc42112cSSascha Hauer } 3114fc42112cSSascha Hauer 3115414c70cbSLiam Girdwood out: 3116414c70cbSLiam Girdwood return ret; 311738de19faSMark Brown out2: 311838de19faSMark Brown voltage->min_uV = old_min_uV; 311938de19faSMark Brown voltage->max_uV = old_max_uV; 3120a9f226bcSSascha Hauer 312169686176SMaciej Purski return ret; 312269686176SMaciej Purski } 312369686176SMaciej Purski 3124a9f226bcSSascha Hauer /** 3125a9f226bcSSascha Hauer * regulator_set_voltage - set regulator output voltage 3126a9f226bcSSascha Hauer * @regulator: regulator source 3127a9f226bcSSascha Hauer * @min_uV: Minimum required voltage in uV 3128a9f226bcSSascha Hauer * @max_uV: Maximum acceptable voltage in uV 3129a9f226bcSSascha Hauer * 3130a9f226bcSSascha Hauer * Sets a voltage regulator to the desired output voltage. This can be set 3131a9f226bcSSascha Hauer * during any regulator state. IOW, regulator can be disabled or enabled. 3132a9f226bcSSascha Hauer * 3133a9f226bcSSascha Hauer * If the regulator is enabled then the voltage will change to the new value 3134a9f226bcSSascha Hauer * immediately otherwise if the regulator is disabled the regulator will 3135a9f226bcSSascha Hauer * output at the new voltage when enabled. 3136a9f226bcSSascha Hauer * 3137a9f226bcSSascha Hauer * NOTE: If the regulator is shared between several devices then the lowest 3138a9f226bcSSascha Hauer * request voltage that meets the system constraints will be used. 3139a9f226bcSSascha Hauer * Regulator system constraints must be set for this regulator before 3140a9f226bcSSascha Hauer * calling this function otherwise this call will fail. 3141a9f226bcSSascha Hauer */ 3142a9f226bcSSascha Hauer int regulator_set_voltage(struct regulator *regulator, int min_uV, int max_uV) 3143a9f226bcSSascha Hauer { 3144a9f226bcSSascha Hauer int ret = 0; 3145a9f226bcSSascha Hauer 314638de19faSMark Brown regulator_lock_supply(regulator->rdev); 3147a9f226bcSSascha Hauer 3148c360a6dfSChunyan Zhang ret = regulator_set_voltage_unlocked(regulator, min_uV, max_uV, 3149c360a6dfSChunyan Zhang PM_SUSPEND_ON); 3150a9f226bcSSascha Hauer 315138de19faSMark Brown regulator_unlock_supply(regulator->rdev); 3152a9f226bcSSascha Hauer 315392d7a558SPaolo Pisati return ret; 3154414c70cbSLiam Girdwood } 3155414c70cbSLiam Girdwood EXPORT_SYMBOL_GPL(regulator_set_voltage); 3156414c70cbSLiam Girdwood 3157f7efad10SChunyan Zhang static inline int regulator_suspend_toggle(struct regulator_dev *rdev, 3158f7efad10SChunyan Zhang suspend_state_t state, bool en) 3159f7efad10SChunyan Zhang { 3160f7efad10SChunyan Zhang struct regulator_state *rstate; 3161f7efad10SChunyan Zhang 3162f7efad10SChunyan Zhang rstate = regulator_get_suspend_state(rdev, state); 3163f7efad10SChunyan Zhang if (rstate == NULL) 3164f7efad10SChunyan Zhang return -EINVAL; 3165f7efad10SChunyan Zhang 3166f7efad10SChunyan Zhang if (!rstate->changeable) 3167f7efad10SChunyan Zhang return -EPERM; 3168f7efad10SChunyan Zhang 3169f7efad10SChunyan Zhang rstate->enabled = en; 3170f7efad10SChunyan Zhang 3171f7efad10SChunyan Zhang return 0; 3172f7efad10SChunyan Zhang } 3173f7efad10SChunyan Zhang 3174f7efad10SChunyan Zhang int regulator_suspend_enable(struct regulator_dev *rdev, 3175f7efad10SChunyan Zhang suspend_state_t state) 3176f7efad10SChunyan Zhang { 3177f7efad10SChunyan Zhang return regulator_suspend_toggle(rdev, state, true); 3178f7efad10SChunyan Zhang } 3179f7efad10SChunyan Zhang EXPORT_SYMBOL_GPL(regulator_suspend_enable); 3180f7efad10SChunyan Zhang 3181f7efad10SChunyan Zhang int regulator_suspend_disable(struct regulator_dev *rdev, 3182f7efad10SChunyan Zhang suspend_state_t state) 3183f7efad10SChunyan Zhang { 3184f7efad10SChunyan Zhang struct regulator *regulator; 3185f7efad10SChunyan Zhang struct regulator_voltage *voltage; 3186f7efad10SChunyan Zhang 3187f7efad10SChunyan Zhang /* 3188f7efad10SChunyan Zhang * if any consumer wants this regulator device keeping on in 3189f7efad10SChunyan Zhang * suspend states, don't set it as disabled. 3190f7efad10SChunyan Zhang */ 3191f7efad10SChunyan Zhang list_for_each_entry(regulator, &rdev->consumer_list, list) { 3192f7efad10SChunyan Zhang voltage = ®ulator->voltage[state]; 3193f7efad10SChunyan Zhang if (voltage->min_uV || voltage->max_uV) 3194f7efad10SChunyan Zhang return 0; 3195f7efad10SChunyan Zhang } 3196f7efad10SChunyan Zhang 3197f7efad10SChunyan Zhang return regulator_suspend_toggle(rdev, state, false); 3198f7efad10SChunyan Zhang } 3199f7efad10SChunyan Zhang EXPORT_SYMBOL_GPL(regulator_suspend_disable); 3200f7efad10SChunyan Zhang 3201f7efad10SChunyan Zhang static int _regulator_set_suspend_voltage(struct regulator *regulator, 3202f7efad10SChunyan Zhang int min_uV, int max_uV, 3203f7efad10SChunyan Zhang suspend_state_t state) 3204f7efad10SChunyan Zhang { 3205f7efad10SChunyan Zhang struct regulator_dev *rdev = regulator->rdev; 3206f7efad10SChunyan Zhang struct regulator_state *rstate; 3207f7efad10SChunyan Zhang 3208f7efad10SChunyan Zhang rstate = regulator_get_suspend_state(rdev, state); 3209f7efad10SChunyan Zhang if (rstate == NULL) 3210f7efad10SChunyan Zhang return -EINVAL; 3211f7efad10SChunyan Zhang 3212f7efad10SChunyan Zhang if (rstate->min_uV == rstate->max_uV) { 3213f7efad10SChunyan Zhang rdev_err(rdev, "The suspend voltage can't be changed!\n"); 3214f7efad10SChunyan Zhang return -EPERM; 3215f7efad10SChunyan Zhang } 3216f7efad10SChunyan Zhang 3217f7efad10SChunyan Zhang return regulator_set_voltage_unlocked(regulator, min_uV, max_uV, state); 3218f7efad10SChunyan Zhang } 3219f7efad10SChunyan Zhang 3220f7efad10SChunyan Zhang int regulator_set_suspend_voltage(struct regulator *regulator, int min_uV, 3221f7efad10SChunyan Zhang int max_uV, suspend_state_t state) 3222f7efad10SChunyan Zhang { 3223f7efad10SChunyan Zhang int ret = 0; 3224f7efad10SChunyan Zhang 3225f7efad10SChunyan Zhang /* PM_SUSPEND_ON is handled by regulator_set_voltage() */ 3226f7efad10SChunyan Zhang if (regulator_check_states(state) || state == PM_SUSPEND_ON) 3227f7efad10SChunyan Zhang return -EINVAL; 3228f7efad10SChunyan Zhang 322938de19faSMark Brown regulator_lock_supply(regulator->rdev); 3230f7efad10SChunyan Zhang 3231f7efad10SChunyan Zhang ret = _regulator_set_suspend_voltage(regulator, min_uV, 3232f7efad10SChunyan Zhang max_uV, state); 3233f7efad10SChunyan Zhang 323438de19faSMark Brown regulator_unlock_supply(regulator->rdev); 3235f7efad10SChunyan Zhang 3236f7efad10SChunyan Zhang return ret; 3237f7efad10SChunyan Zhang } 3238f7efad10SChunyan Zhang EXPORT_SYMBOL_GPL(regulator_set_suspend_voltage); 3239f7efad10SChunyan Zhang 3240606a2562SMark Brown /** 324188cd222bSLinus Walleij * regulator_set_voltage_time - get raise/fall time 324288cd222bSLinus Walleij * @regulator: regulator source 324388cd222bSLinus Walleij * @old_uV: starting voltage in microvolts 324488cd222bSLinus Walleij * @new_uV: target voltage in microvolts 324588cd222bSLinus Walleij * 324688cd222bSLinus Walleij * Provided with the starting and ending voltage, this function attempts to 324788cd222bSLinus Walleij * calculate the time in microseconds required to rise or fall to this new 324888cd222bSLinus Walleij * voltage. 324988cd222bSLinus Walleij */ 325088cd222bSLinus Walleij int regulator_set_voltage_time(struct regulator *regulator, 325188cd222bSLinus Walleij int old_uV, int new_uV) 325288cd222bSLinus Walleij { 325388cd222bSLinus Walleij struct regulator_dev *rdev = regulator->rdev; 3254272e2315SGuodong Xu const struct regulator_ops *ops = rdev->desc->ops; 325588cd222bSLinus Walleij int old_sel = -1; 325688cd222bSLinus Walleij int new_sel = -1; 325788cd222bSLinus Walleij int voltage; 325888cd222bSLinus Walleij int i; 325988cd222bSLinus Walleij 326073e705bfSMatthias Kaehlcke if (ops->set_voltage_time) 326173e705bfSMatthias Kaehlcke return ops->set_voltage_time(rdev, old_uV, new_uV); 326273e705bfSMatthias Kaehlcke else if (!ops->set_voltage_time_sel) 326373e705bfSMatthias Kaehlcke return _regulator_set_voltage_time(rdev, old_uV, new_uV); 326473e705bfSMatthias Kaehlcke 326588cd222bSLinus Walleij /* Currently requires operations to do this */ 326673e705bfSMatthias Kaehlcke if (!ops->list_voltage || !rdev->desc->n_voltages) 326788cd222bSLinus Walleij return -EINVAL; 326888cd222bSLinus Walleij 326988cd222bSLinus Walleij for (i = 0; i < rdev->desc->n_voltages; i++) { 327088cd222bSLinus Walleij /* We only look for exact voltage matches here */ 327188cd222bSLinus Walleij voltage = regulator_list_voltage(regulator, i); 327288cd222bSLinus Walleij if (voltage < 0) 327388cd222bSLinus Walleij return -EINVAL; 327488cd222bSLinus Walleij if (voltage == 0) 327588cd222bSLinus Walleij continue; 327688cd222bSLinus Walleij if (voltage == old_uV) 327788cd222bSLinus Walleij old_sel = i; 327888cd222bSLinus Walleij if (voltage == new_uV) 327988cd222bSLinus Walleij new_sel = i; 328088cd222bSLinus Walleij } 328188cd222bSLinus Walleij 328288cd222bSLinus Walleij if (old_sel < 0 || new_sel < 0) 328388cd222bSLinus Walleij return -EINVAL; 328488cd222bSLinus Walleij 328588cd222bSLinus Walleij return ops->set_voltage_time_sel(rdev, old_sel, new_sel); 328688cd222bSLinus Walleij } 328788cd222bSLinus Walleij EXPORT_SYMBOL_GPL(regulator_set_voltage_time); 328888cd222bSLinus Walleij 328988cd222bSLinus Walleij /** 329098a175b6SYadwinder Singh Brar * regulator_set_voltage_time_sel - get raise/fall time 3291296c6566SRandy Dunlap * @rdev: regulator source device 329298a175b6SYadwinder Singh Brar * @old_selector: selector for starting voltage 329398a175b6SYadwinder Singh Brar * @new_selector: selector for target voltage 329498a175b6SYadwinder Singh Brar * 329598a175b6SYadwinder Singh Brar * Provided with the starting and target voltage selectors, this function 329698a175b6SYadwinder Singh Brar * returns time in microseconds required to rise or fall to this new voltage 329798a175b6SYadwinder Singh Brar * 3298f11d08c3SAxel Lin * Drivers providing ramp_delay in regulation_constraints can use this as their 3299398715abSAxel Lin * set_voltage_time_sel() operation. 330098a175b6SYadwinder Singh Brar */ 330198a175b6SYadwinder Singh Brar int regulator_set_voltage_time_sel(struct regulator_dev *rdev, 330298a175b6SYadwinder Singh Brar unsigned int old_selector, 330398a175b6SYadwinder Singh Brar unsigned int new_selector) 330498a175b6SYadwinder Singh Brar { 3305f11d08c3SAxel Lin int old_volt, new_volt; 3306398715abSAxel Lin 3307f11d08c3SAxel Lin /* sanity check */ 3308f11d08c3SAxel Lin if (!rdev->desc->ops->list_voltage) 3309f11d08c3SAxel Lin return -EINVAL; 3310398715abSAxel Lin 3311f11d08c3SAxel Lin old_volt = rdev->desc->ops->list_voltage(rdev, old_selector); 3312f11d08c3SAxel Lin new_volt = rdev->desc->ops->list_voltage(rdev, new_selector); 3313f11d08c3SAxel Lin 331473e705bfSMatthias Kaehlcke if (rdev->desc->ops->set_voltage_time) 331573e705bfSMatthias Kaehlcke return rdev->desc->ops->set_voltage_time(rdev, old_volt, 331673e705bfSMatthias Kaehlcke new_volt); 331773e705bfSMatthias Kaehlcke else 331873e705bfSMatthias Kaehlcke return _regulator_set_voltage_time(rdev, old_volt, new_volt); 331998a175b6SYadwinder Singh Brar } 3320b19dbf71SMark Brown EXPORT_SYMBOL_GPL(regulator_set_voltage_time_sel); 332198a175b6SYadwinder Singh Brar 332298a175b6SYadwinder Singh Brar /** 3323606a2562SMark Brown * regulator_sync_voltage - re-apply last regulator output voltage 3324606a2562SMark Brown * @regulator: regulator source 3325606a2562SMark Brown * 3326606a2562SMark Brown * Re-apply the last configured voltage. This is intended to be used 3327606a2562SMark Brown * where some external control source the consumer is cooperating with 3328606a2562SMark Brown * has caused the configured voltage to change. 3329606a2562SMark Brown */ 3330606a2562SMark Brown int regulator_sync_voltage(struct regulator *regulator) 3331606a2562SMark Brown { 3332606a2562SMark Brown struct regulator_dev *rdev = regulator->rdev; 3333c360a6dfSChunyan Zhang struct regulator_voltage *voltage = ®ulator->voltage[PM_SUSPEND_ON]; 3334606a2562SMark Brown int ret, min_uV, max_uV; 3335606a2562SMark Brown 333666cf9a7eSMaciej Purski regulator_lock(rdev); 3337606a2562SMark Brown 3338606a2562SMark Brown if (!rdev->desc->ops->set_voltage && 3339606a2562SMark Brown !rdev->desc->ops->set_voltage_sel) { 3340606a2562SMark Brown ret = -EINVAL; 3341606a2562SMark Brown goto out; 3342606a2562SMark Brown } 3343606a2562SMark Brown 3344606a2562SMark Brown /* This is only going to work if we've had a voltage configured. */ 3345c360a6dfSChunyan Zhang if (!voltage->min_uV && !voltage->max_uV) { 3346606a2562SMark Brown ret = -EINVAL; 3347606a2562SMark Brown goto out; 3348606a2562SMark Brown } 3349606a2562SMark Brown 3350c360a6dfSChunyan Zhang min_uV = voltage->min_uV; 3351c360a6dfSChunyan Zhang max_uV = voltage->max_uV; 3352606a2562SMark Brown 3353606a2562SMark Brown /* This should be a paranoia check... */ 3354606a2562SMark Brown ret = regulator_check_voltage(rdev, &min_uV, &max_uV); 3355606a2562SMark Brown if (ret < 0) 3356606a2562SMark Brown goto out; 3357606a2562SMark Brown 3358c360a6dfSChunyan Zhang ret = regulator_check_consumers(rdev, &min_uV, &max_uV, 0); 3359606a2562SMark Brown if (ret < 0) 3360606a2562SMark Brown goto out; 3361606a2562SMark Brown 3362606a2562SMark Brown ret = _regulator_do_set_voltage(rdev, min_uV, max_uV); 3363606a2562SMark Brown 3364606a2562SMark Brown out: 336566cf9a7eSMaciej Purski regulator_unlock(rdev); 3366606a2562SMark Brown return ret; 3367606a2562SMark Brown } 3368606a2562SMark Brown EXPORT_SYMBOL_GPL(regulator_sync_voltage); 3369606a2562SMark Brown 3370414c70cbSLiam Girdwood static int _regulator_get_voltage(struct regulator_dev *rdev) 3371414c70cbSLiam Girdwood { 3372bf5892a8SMark Brown int sel, ret; 3373fef95019SMark Brown bool bypassed; 3374fef95019SMark Brown 3375fef95019SMark Brown if (rdev->desc->ops->get_bypass) { 3376fef95019SMark Brown ret = rdev->desc->ops->get_bypass(rdev, &bypassed); 3377fef95019SMark Brown if (ret < 0) 3378fef95019SMark Brown return ret; 3379fef95019SMark Brown if (bypassed) { 3380fef95019SMark Brown /* if bypassed the regulator must have a supply */ 338145389c47SJon Hunter if (!rdev->supply) { 338245389c47SJon Hunter rdev_err(rdev, 338345389c47SJon Hunter "bypassed regulator has no supply!\n"); 338445389c47SJon Hunter return -EPROBE_DEFER; 338545389c47SJon Hunter } 3386fef95019SMark Brown 3387fef95019SMark Brown return _regulator_get_voltage(rdev->supply->rdev); 3388fef95019SMark Brown } 3389fef95019SMark Brown } 3390476c2d83SMark Brown 3391476c2d83SMark Brown if (rdev->desc->ops->get_voltage_sel) { 3392476c2d83SMark Brown sel = rdev->desc->ops->get_voltage_sel(rdev); 3393476c2d83SMark Brown if (sel < 0) 3394476c2d83SMark Brown return sel; 3395bf5892a8SMark Brown ret = rdev->desc->ops->list_voltage(rdev, sel); 3396cb220d16SAxel Lin } else if (rdev->desc->ops->get_voltage) { 3397bf5892a8SMark Brown ret = rdev->desc->ops->get_voltage(rdev); 3398f7df20ecSMark Brown } else if (rdev->desc->ops->list_voltage) { 3399f7df20ecSMark Brown ret = rdev->desc->ops->list_voltage(rdev, 0); 34005a523605SLaxman Dewangan } else if (rdev->desc->fixed_uV && (rdev->desc->n_voltages == 1)) { 34015a523605SLaxman Dewangan ret = rdev->desc->fixed_uV; 3402e303996eSJavier Martinez Canillas } else if (rdev->supply) { 3403d9b96d35SMark Brown ret = _regulator_get_voltage(rdev->supply->rdev); 3404cb220d16SAxel Lin } else { 3405414c70cbSLiam Girdwood return -EINVAL; 3406cb220d16SAxel Lin } 3407bf5892a8SMark Brown 3408cb220d16SAxel Lin if (ret < 0) 3409cb220d16SAxel Lin return ret; 3410bf5892a8SMark Brown return ret - rdev->constraints->uV_offset; 3411414c70cbSLiam Girdwood } 3412414c70cbSLiam Girdwood 3413414c70cbSLiam Girdwood /** 3414414c70cbSLiam Girdwood * regulator_get_voltage - get regulator output voltage 3415414c70cbSLiam Girdwood * @regulator: regulator source 3416414c70cbSLiam Girdwood * 3417414c70cbSLiam Girdwood * This returns the current regulator voltage in uV. 3418414c70cbSLiam Girdwood * 3419414c70cbSLiam Girdwood * NOTE: If the regulator is disabled it will return the voltage value. This 3420414c70cbSLiam Girdwood * function should not be used to determine regulator state. 3421414c70cbSLiam Girdwood */ 3422414c70cbSLiam Girdwood int regulator_get_voltage(struct regulator *regulator) 3423414c70cbSLiam Girdwood { 3424414c70cbSLiam Girdwood int ret; 3425414c70cbSLiam Girdwood 342638de19faSMark Brown regulator_lock_supply(regulator->rdev); 3427414c70cbSLiam Girdwood 3428414c70cbSLiam Girdwood ret = _regulator_get_voltage(regulator->rdev); 3429414c70cbSLiam Girdwood 343038de19faSMark Brown regulator_unlock_supply(regulator->rdev); 3431414c70cbSLiam Girdwood 3432414c70cbSLiam Girdwood return ret; 3433414c70cbSLiam Girdwood } 3434414c70cbSLiam Girdwood EXPORT_SYMBOL_GPL(regulator_get_voltage); 3435414c70cbSLiam Girdwood 3436414c70cbSLiam Girdwood /** 3437414c70cbSLiam Girdwood * regulator_set_current_limit - set regulator output current limit 3438414c70cbSLiam Girdwood * @regulator: regulator source 3439ce0d10f8SCharles Keepax * @min_uA: Minimum supported current in uA 3440414c70cbSLiam Girdwood * @max_uA: Maximum supported current in uA 3441414c70cbSLiam Girdwood * 3442414c70cbSLiam Girdwood * Sets current sink to the desired output current. This can be set during 3443414c70cbSLiam Girdwood * any regulator state. IOW, regulator can be disabled or enabled. 3444414c70cbSLiam Girdwood * 3445414c70cbSLiam Girdwood * If the regulator is enabled then the current will change to the new value 3446414c70cbSLiam Girdwood * immediately otherwise if the regulator is disabled the regulator will 3447414c70cbSLiam Girdwood * output at the new current when enabled. 3448414c70cbSLiam Girdwood * 3449414c70cbSLiam Girdwood * NOTE: Regulator system constraints must be set for this regulator before 3450414c70cbSLiam Girdwood * calling this function otherwise this call will fail. 3451414c70cbSLiam Girdwood */ 3452414c70cbSLiam Girdwood int regulator_set_current_limit(struct regulator *regulator, 3453414c70cbSLiam Girdwood int min_uA, int max_uA) 3454414c70cbSLiam Girdwood { 3455414c70cbSLiam Girdwood struct regulator_dev *rdev = regulator->rdev; 3456414c70cbSLiam Girdwood int ret; 3457414c70cbSLiam Girdwood 345866cf9a7eSMaciej Purski regulator_lock(rdev); 3459414c70cbSLiam Girdwood 3460414c70cbSLiam Girdwood /* sanity check */ 3461414c70cbSLiam Girdwood if (!rdev->desc->ops->set_current_limit) { 3462414c70cbSLiam Girdwood ret = -EINVAL; 3463414c70cbSLiam Girdwood goto out; 3464414c70cbSLiam Girdwood } 3465414c70cbSLiam Girdwood 3466414c70cbSLiam Girdwood /* constraints check */ 3467414c70cbSLiam Girdwood ret = regulator_check_current_limit(rdev, &min_uA, &max_uA); 3468414c70cbSLiam Girdwood if (ret < 0) 3469414c70cbSLiam Girdwood goto out; 3470414c70cbSLiam Girdwood 3471414c70cbSLiam Girdwood ret = rdev->desc->ops->set_current_limit(rdev, min_uA, max_uA); 3472414c70cbSLiam Girdwood out: 347366cf9a7eSMaciej Purski regulator_unlock(rdev); 3474414c70cbSLiam Girdwood return ret; 3475414c70cbSLiam Girdwood } 3476414c70cbSLiam Girdwood EXPORT_SYMBOL_GPL(regulator_set_current_limit); 3477414c70cbSLiam Girdwood 3478414c70cbSLiam Girdwood static int _regulator_get_current_limit(struct regulator_dev *rdev) 3479414c70cbSLiam Girdwood { 3480414c70cbSLiam Girdwood int ret; 3481414c70cbSLiam Girdwood 348266cf9a7eSMaciej Purski regulator_lock(rdev); 3483414c70cbSLiam Girdwood 3484414c70cbSLiam Girdwood /* sanity check */ 3485414c70cbSLiam Girdwood if (!rdev->desc->ops->get_current_limit) { 3486414c70cbSLiam Girdwood ret = -EINVAL; 3487414c70cbSLiam Girdwood goto out; 3488414c70cbSLiam Girdwood } 3489414c70cbSLiam Girdwood 3490414c70cbSLiam Girdwood ret = rdev->desc->ops->get_current_limit(rdev); 3491414c70cbSLiam Girdwood out: 349266cf9a7eSMaciej Purski regulator_unlock(rdev); 3493414c70cbSLiam Girdwood return ret; 3494414c70cbSLiam Girdwood } 3495414c70cbSLiam Girdwood 3496414c70cbSLiam Girdwood /** 3497414c70cbSLiam Girdwood * regulator_get_current_limit - get regulator output current 3498414c70cbSLiam Girdwood * @regulator: regulator source 3499414c70cbSLiam Girdwood * 3500414c70cbSLiam Girdwood * This returns the current supplied by the specified current sink in uA. 3501414c70cbSLiam Girdwood * 3502414c70cbSLiam Girdwood * NOTE: If the regulator is disabled it will return the current value. This 3503414c70cbSLiam Girdwood * function should not be used to determine regulator state. 3504414c70cbSLiam Girdwood */ 3505414c70cbSLiam Girdwood int regulator_get_current_limit(struct regulator *regulator) 3506414c70cbSLiam Girdwood { 3507414c70cbSLiam Girdwood return _regulator_get_current_limit(regulator->rdev); 3508414c70cbSLiam Girdwood } 3509414c70cbSLiam Girdwood EXPORT_SYMBOL_GPL(regulator_get_current_limit); 3510414c70cbSLiam Girdwood 3511414c70cbSLiam Girdwood /** 3512414c70cbSLiam Girdwood * regulator_set_mode - set regulator operating mode 3513414c70cbSLiam Girdwood * @regulator: regulator source 3514414c70cbSLiam Girdwood * @mode: operating mode - one of the REGULATOR_MODE constants 3515414c70cbSLiam Girdwood * 3516414c70cbSLiam Girdwood * Set regulator operating mode to increase regulator efficiency or improve 3517414c70cbSLiam Girdwood * regulation performance. 3518414c70cbSLiam Girdwood * 3519414c70cbSLiam Girdwood * NOTE: Regulator system constraints must be set for this regulator before 3520414c70cbSLiam Girdwood * calling this function otherwise this call will fail. 3521414c70cbSLiam Girdwood */ 3522414c70cbSLiam Girdwood int regulator_set_mode(struct regulator *regulator, unsigned int mode) 3523414c70cbSLiam Girdwood { 3524414c70cbSLiam Girdwood struct regulator_dev *rdev = regulator->rdev; 3525414c70cbSLiam Girdwood int ret; 3526500b4ac9SSundar R Iyer int regulator_curr_mode; 3527414c70cbSLiam Girdwood 352866cf9a7eSMaciej Purski regulator_lock(rdev); 3529414c70cbSLiam Girdwood 3530414c70cbSLiam Girdwood /* sanity check */ 3531414c70cbSLiam Girdwood if (!rdev->desc->ops->set_mode) { 3532414c70cbSLiam Girdwood ret = -EINVAL; 3533414c70cbSLiam Girdwood goto out; 3534414c70cbSLiam Girdwood } 3535414c70cbSLiam Girdwood 3536500b4ac9SSundar R Iyer /* return if the same mode is requested */ 3537500b4ac9SSundar R Iyer if (rdev->desc->ops->get_mode) { 3538500b4ac9SSundar R Iyer regulator_curr_mode = rdev->desc->ops->get_mode(rdev); 3539500b4ac9SSundar R Iyer if (regulator_curr_mode == mode) { 3540500b4ac9SSundar R Iyer ret = 0; 3541500b4ac9SSundar R Iyer goto out; 3542500b4ac9SSundar R Iyer } 3543500b4ac9SSundar R Iyer } 3544500b4ac9SSundar R Iyer 3545414c70cbSLiam Girdwood /* constraints check */ 354622c51b47SAxel Lin ret = regulator_mode_constrain(rdev, &mode); 3547414c70cbSLiam Girdwood if (ret < 0) 3548414c70cbSLiam Girdwood goto out; 3549414c70cbSLiam Girdwood 3550414c70cbSLiam Girdwood ret = rdev->desc->ops->set_mode(rdev, mode); 3551414c70cbSLiam Girdwood out: 355266cf9a7eSMaciej Purski regulator_unlock(rdev); 3553414c70cbSLiam Girdwood return ret; 3554414c70cbSLiam Girdwood } 3555414c70cbSLiam Girdwood EXPORT_SYMBOL_GPL(regulator_set_mode); 3556414c70cbSLiam Girdwood 3557414c70cbSLiam Girdwood static unsigned int _regulator_get_mode(struct regulator_dev *rdev) 3558414c70cbSLiam Girdwood { 3559414c70cbSLiam Girdwood int ret; 3560414c70cbSLiam Girdwood 356166cf9a7eSMaciej Purski regulator_lock(rdev); 3562414c70cbSLiam Girdwood 3563414c70cbSLiam Girdwood /* sanity check */ 3564414c70cbSLiam Girdwood if (!rdev->desc->ops->get_mode) { 3565414c70cbSLiam Girdwood ret = -EINVAL; 3566414c70cbSLiam Girdwood goto out; 3567414c70cbSLiam Girdwood } 3568414c70cbSLiam Girdwood 3569414c70cbSLiam Girdwood ret = rdev->desc->ops->get_mode(rdev); 3570414c70cbSLiam Girdwood out: 357166cf9a7eSMaciej Purski regulator_unlock(rdev); 3572414c70cbSLiam Girdwood return ret; 3573414c70cbSLiam Girdwood } 3574414c70cbSLiam Girdwood 3575414c70cbSLiam Girdwood /** 3576414c70cbSLiam Girdwood * regulator_get_mode - get regulator operating mode 3577414c70cbSLiam Girdwood * @regulator: regulator source 3578414c70cbSLiam Girdwood * 3579414c70cbSLiam Girdwood * Get the current regulator operating mode. 3580414c70cbSLiam Girdwood */ 3581414c70cbSLiam Girdwood unsigned int regulator_get_mode(struct regulator *regulator) 3582414c70cbSLiam Girdwood { 3583414c70cbSLiam Girdwood return _regulator_get_mode(regulator->rdev); 3584414c70cbSLiam Girdwood } 3585414c70cbSLiam Girdwood EXPORT_SYMBOL_GPL(regulator_get_mode); 3586414c70cbSLiam Girdwood 35871b5b4221SAxel Haslam static int _regulator_get_error_flags(struct regulator_dev *rdev, 35881b5b4221SAxel Haslam unsigned int *flags) 35891b5b4221SAxel Haslam { 35901b5b4221SAxel Haslam int ret; 35911b5b4221SAxel Haslam 359266cf9a7eSMaciej Purski regulator_lock(rdev); 35931b5b4221SAxel Haslam 35941b5b4221SAxel Haslam /* sanity check */ 35951b5b4221SAxel Haslam if (!rdev->desc->ops->get_error_flags) { 35961b5b4221SAxel Haslam ret = -EINVAL; 35971b5b4221SAxel Haslam goto out; 35981b5b4221SAxel Haslam } 35991b5b4221SAxel Haslam 36001b5b4221SAxel Haslam ret = rdev->desc->ops->get_error_flags(rdev, flags); 36011b5b4221SAxel Haslam out: 360266cf9a7eSMaciej Purski regulator_unlock(rdev); 36031b5b4221SAxel Haslam return ret; 36041b5b4221SAxel Haslam } 36051b5b4221SAxel Haslam 36061b5b4221SAxel Haslam /** 36071b5b4221SAxel Haslam * regulator_get_error_flags - get regulator error information 36081b5b4221SAxel Haslam * @regulator: regulator source 36091b5b4221SAxel Haslam * @flags: pointer to store error flags 36101b5b4221SAxel Haslam * 36111b5b4221SAxel Haslam * Get the current regulator error information. 36121b5b4221SAxel Haslam */ 36131b5b4221SAxel Haslam int regulator_get_error_flags(struct regulator *regulator, 36141b5b4221SAxel Haslam unsigned int *flags) 36151b5b4221SAxel Haslam { 36161b5b4221SAxel Haslam return _regulator_get_error_flags(regulator->rdev, flags); 36171b5b4221SAxel Haslam } 36181b5b4221SAxel Haslam EXPORT_SYMBOL_GPL(regulator_get_error_flags); 36191b5b4221SAxel Haslam 3620414c70cbSLiam Girdwood /** 3621e39ce48fSBjorn Andersson * regulator_set_load - set regulator load 3622414c70cbSLiam Girdwood * @regulator: regulator source 3623414c70cbSLiam Girdwood * @uA_load: load current 3624414c70cbSLiam Girdwood * 3625414c70cbSLiam Girdwood * Notifies the regulator core of a new device load. This is then used by 3626414c70cbSLiam Girdwood * DRMS (if enabled by constraints) to set the most efficient regulator 3627414c70cbSLiam Girdwood * operating mode for the new regulator loading. 3628414c70cbSLiam Girdwood * 3629414c70cbSLiam Girdwood * Consumer devices notify their supply regulator of the maximum power 3630414c70cbSLiam Girdwood * they will require (can be taken from device datasheet in the power 3631414c70cbSLiam Girdwood * consumption tables) when they change operational status and hence power 3632414c70cbSLiam Girdwood * state. Examples of operational state changes that can affect power 3633414c70cbSLiam Girdwood * consumption are :- 3634414c70cbSLiam Girdwood * 3635414c70cbSLiam Girdwood * o Device is opened / closed. 3636414c70cbSLiam Girdwood * o Device I/O is about to begin or has just finished. 3637414c70cbSLiam Girdwood * o Device is idling in between work. 3638414c70cbSLiam Girdwood * 3639414c70cbSLiam Girdwood * This information is also exported via sysfs to userspace. 3640414c70cbSLiam Girdwood * 3641414c70cbSLiam Girdwood * DRMS will sum the total requested load on the regulator and change 3642414c70cbSLiam Girdwood * to the most efficient operating mode if platform constraints allow. 3643414c70cbSLiam Girdwood * 3644e39ce48fSBjorn Andersson * On error a negative errno is returned. 3645414c70cbSLiam Girdwood */ 3646e39ce48fSBjorn Andersson int regulator_set_load(struct regulator *regulator, int uA_load) 3647414c70cbSLiam Girdwood { 3648414c70cbSLiam Girdwood struct regulator_dev *rdev = regulator->rdev; 36498460ef38SBjorn Andersson int ret; 3650d92d95b6SStephen Boyd 365166cf9a7eSMaciej Purski regulator_lock(rdev); 3652414c70cbSLiam Girdwood regulator->uA_load = uA_load; 36538460ef38SBjorn Andersson ret = drms_uA_update(rdev); 365466cf9a7eSMaciej Purski regulator_unlock(rdev); 36558460ef38SBjorn Andersson 3656414c70cbSLiam Girdwood return ret; 3657414c70cbSLiam Girdwood } 3658e39ce48fSBjorn Andersson EXPORT_SYMBOL_GPL(regulator_set_load); 3659414c70cbSLiam Girdwood 3660414c70cbSLiam Girdwood /** 3661f59c8f9fSMark Brown * regulator_allow_bypass - allow the regulator to go into bypass mode 3662f59c8f9fSMark Brown * 3663f59c8f9fSMark Brown * @regulator: Regulator to configure 36649345dfb8SNishanth Menon * @enable: enable or disable bypass mode 3665f59c8f9fSMark Brown * 3666f59c8f9fSMark Brown * Allow the regulator to go into bypass mode if all other consumers 3667f59c8f9fSMark Brown * for the regulator also enable bypass mode and the machine 3668f59c8f9fSMark Brown * constraints allow this. Bypass mode means that the regulator is 3669f59c8f9fSMark Brown * simply passing the input directly to the output with no regulation. 3670f59c8f9fSMark Brown */ 3671f59c8f9fSMark Brown int regulator_allow_bypass(struct regulator *regulator, bool enable) 3672f59c8f9fSMark Brown { 3673f59c8f9fSMark Brown struct regulator_dev *rdev = regulator->rdev; 3674f59c8f9fSMark Brown int ret = 0; 3675f59c8f9fSMark Brown 3676f59c8f9fSMark Brown if (!rdev->desc->ops->set_bypass) 3677f59c8f9fSMark Brown return 0; 3678f59c8f9fSMark Brown 36798a34e979SWEN Pingbo if (!regulator_ops_is_valid(rdev, REGULATOR_CHANGE_BYPASS)) 3680f59c8f9fSMark Brown return 0; 3681f59c8f9fSMark Brown 368266cf9a7eSMaciej Purski regulator_lock(rdev); 3683f59c8f9fSMark Brown 3684f59c8f9fSMark Brown if (enable && !regulator->bypass) { 3685f59c8f9fSMark Brown rdev->bypass_count++; 3686f59c8f9fSMark Brown 3687f59c8f9fSMark Brown if (rdev->bypass_count == rdev->open_count) { 3688f59c8f9fSMark Brown ret = rdev->desc->ops->set_bypass(rdev, enable); 3689f59c8f9fSMark Brown if (ret != 0) 3690f59c8f9fSMark Brown rdev->bypass_count--; 3691f59c8f9fSMark Brown } 3692f59c8f9fSMark Brown 3693f59c8f9fSMark Brown } else if (!enable && regulator->bypass) { 3694f59c8f9fSMark Brown rdev->bypass_count--; 3695f59c8f9fSMark Brown 3696f59c8f9fSMark Brown if (rdev->bypass_count != rdev->open_count) { 3697f59c8f9fSMark Brown ret = rdev->desc->ops->set_bypass(rdev, enable); 3698f59c8f9fSMark Brown if (ret != 0) 3699f59c8f9fSMark Brown rdev->bypass_count++; 3700f59c8f9fSMark Brown } 3701f59c8f9fSMark Brown } 3702f59c8f9fSMark Brown 3703f59c8f9fSMark Brown if (ret == 0) 3704f59c8f9fSMark Brown regulator->bypass = enable; 3705f59c8f9fSMark Brown 370666cf9a7eSMaciej Purski regulator_unlock(rdev); 3707f59c8f9fSMark Brown 3708f59c8f9fSMark Brown return ret; 3709f59c8f9fSMark Brown } 3710f59c8f9fSMark Brown EXPORT_SYMBOL_GPL(regulator_allow_bypass); 3711f59c8f9fSMark Brown 3712f59c8f9fSMark Brown /** 3713414c70cbSLiam Girdwood * regulator_register_notifier - register regulator event notifier 3714414c70cbSLiam Girdwood * @regulator: regulator source 371569279fb9SMark Brown * @nb: notifier block 3716414c70cbSLiam Girdwood * 3717414c70cbSLiam Girdwood * Register notifier block to receive regulator events. 3718414c70cbSLiam Girdwood */ 3719414c70cbSLiam Girdwood int regulator_register_notifier(struct regulator *regulator, 3720414c70cbSLiam Girdwood struct notifier_block *nb) 3721414c70cbSLiam Girdwood { 3722414c70cbSLiam Girdwood return blocking_notifier_chain_register(®ulator->rdev->notifier, 3723414c70cbSLiam Girdwood nb); 3724414c70cbSLiam Girdwood } 3725414c70cbSLiam Girdwood EXPORT_SYMBOL_GPL(regulator_register_notifier); 3726414c70cbSLiam Girdwood 3727414c70cbSLiam Girdwood /** 3728414c70cbSLiam Girdwood * regulator_unregister_notifier - unregister regulator event notifier 3729414c70cbSLiam Girdwood * @regulator: regulator source 373069279fb9SMark Brown * @nb: notifier block 3731414c70cbSLiam Girdwood * 3732414c70cbSLiam Girdwood * Unregister regulator event notifier block. 3733414c70cbSLiam Girdwood */ 3734414c70cbSLiam Girdwood int regulator_unregister_notifier(struct regulator *regulator, 3735414c70cbSLiam Girdwood struct notifier_block *nb) 3736414c70cbSLiam Girdwood { 3737414c70cbSLiam Girdwood return blocking_notifier_chain_unregister(®ulator->rdev->notifier, 3738414c70cbSLiam Girdwood nb); 3739414c70cbSLiam Girdwood } 3740414c70cbSLiam Girdwood EXPORT_SYMBOL_GPL(regulator_unregister_notifier); 3741414c70cbSLiam Girdwood 3742b136fb44SJonathan Cameron /* notify regulator consumers and downstream regulator consumers. 3743b136fb44SJonathan Cameron * Note mutex must be held by caller. 3744b136fb44SJonathan Cameron */ 37457179569aSHeiko Stübner static int _notifier_call_chain(struct regulator_dev *rdev, 3746414c70cbSLiam Girdwood unsigned long event, void *data) 3747414c70cbSLiam Girdwood { 3748414c70cbSLiam Girdwood /* call rdev chain first */ 37497179569aSHeiko Stübner return blocking_notifier_call_chain(&rdev->notifier, event, data); 3750414c70cbSLiam Girdwood } 3751414c70cbSLiam Girdwood 3752414c70cbSLiam Girdwood /** 3753414c70cbSLiam Girdwood * regulator_bulk_get - get multiple regulator consumers 3754414c70cbSLiam Girdwood * 3755414c70cbSLiam Girdwood * @dev: Device to supply 3756414c70cbSLiam Girdwood * @num_consumers: Number of consumers to register 3757414c70cbSLiam Girdwood * @consumers: Configuration of consumers; clients are stored here. 3758414c70cbSLiam Girdwood * 3759414c70cbSLiam Girdwood * @return 0 on success, an errno on failure. 3760414c70cbSLiam Girdwood * 3761414c70cbSLiam Girdwood * This helper function allows drivers to get several regulator 3762414c70cbSLiam Girdwood * consumers in one operation. If any of the regulators cannot be 3763414c70cbSLiam Girdwood * acquired then any regulators that were allocated will be freed 3764414c70cbSLiam Girdwood * before returning to the caller. 3765414c70cbSLiam Girdwood */ 3766414c70cbSLiam Girdwood int regulator_bulk_get(struct device *dev, int num_consumers, 3767414c70cbSLiam Girdwood struct regulator_bulk_data *consumers) 3768414c70cbSLiam Girdwood { 3769414c70cbSLiam Girdwood int i; 3770414c70cbSLiam Girdwood int ret; 3771414c70cbSLiam Girdwood 3772414c70cbSLiam Girdwood for (i = 0; i < num_consumers; i++) 3773414c70cbSLiam Girdwood consumers[i].consumer = NULL; 3774414c70cbSLiam Girdwood 3775414c70cbSLiam Girdwood for (i = 0; i < num_consumers; i++) { 3776565f9b07SBjorn Andersson consumers[i].consumer = regulator_get(dev, 3777565f9b07SBjorn Andersson consumers[i].supply); 3778414c70cbSLiam Girdwood if (IS_ERR(consumers[i].consumer)) { 3779414c70cbSLiam Girdwood ret = PTR_ERR(consumers[i].consumer); 37805b307627SMark Brown dev_err(dev, "Failed to get supply '%s': %d\n", 37815b307627SMark Brown consumers[i].supply, ret); 3782414c70cbSLiam Girdwood consumers[i].consumer = NULL; 3783414c70cbSLiam Girdwood goto err; 3784414c70cbSLiam Girdwood } 3785414c70cbSLiam Girdwood } 3786414c70cbSLiam Girdwood 3787414c70cbSLiam Girdwood return 0; 3788414c70cbSLiam Girdwood 3789414c70cbSLiam Girdwood err: 3790b29c7690SAxel Lin while (--i >= 0) 3791414c70cbSLiam Girdwood regulator_put(consumers[i].consumer); 3792414c70cbSLiam Girdwood 3793414c70cbSLiam Girdwood return ret; 3794414c70cbSLiam Girdwood } 3795414c70cbSLiam Girdwood EXPORT_SYMBOL_GPL(regulator_bulk_get); 3796414c70cbSLiam Girdwood 3797f21e0e81SMark Brown static void regulator_bulk_enable_async(void *data, async_cookie_t cookie) 3798f21e0e81SMark Brown { 3799f21e0e81SMark Brown struct regulator_bulk_data *bulk = data; 3800f21e0e81SMark Brown 3801f21e0e81SMark Brown bulk->ret = regulator_enable(bulk->consumer); 3802f21e0e81SMark Brown } 3803f21e0e81SMark Brown 3804414c70cbSLiam Girdwood /** 3805414c70cbSLiam Girdwood * regulator_bulk_enable - enable multiple regulator consumers 3806414c70cbSLiam Girdwood * 3807414c70cbSLiam Girdwood * @num_consumers: Number of consumers 3808414c70cbSLiam Girdwood * @consumers: Consumer data; clients are stored here. 3809414c70cbSLiam Girdwood * @return 0 on success, an errno on failure 3810414c70cbSLiam Girdwood * 3811414c70cbSLiam Girdwood * This convenience API allows consumers to enable multiple regulator 3812414c70cbSLiam Girdwood * clients in a single API call. If any consumers cannot be enabled 3813414c70cbSLiam Girdwood * then any others that were enabled will be disabled again prior to 3814414c70cbSLiam Girdwood * return. 3815414c70cbSLiam Girdwood */ 3816414c70cbSLiam Girdwood int regulator_bulk_enable(int num_consumers, 3817414c70cbSLiam Girdwood struct regulator_bulk_data *consumers) 3818414c70cbSLiam Girdwood { 38192955b47dSDan Williams ASYNC_DOMAIN_EXCLUSIVE(async_domain); 3820414c70cbSLiam Girdwood int i; 3821f21e0e81SMark Brown int ret = 0; 3822414c70cbSLiam Girdwood 38236492bc1bSMark Brown for (i = 0; i < num_consumers; i++) { 38246492bc1bSMark Brown if (consumers[i].consumer->always_on) 38256492bc1bSMark Brown consumers[i].ret = 0; 38266492bc1bSMark Brown else 3827f21e0e81SMark Brown async_schedule_domain(regulator_bulk_enable_async, 3828f21e0e81SMark Brown &consumers[i], &async_domain); 38296492bc1bSMark Brown } 3830f21e0e81SMark Brown 3831f21e0e81SMark Brown async_synchronize_full_domain(&async_domain); 3832f21e0e81SMark Brown 3833f21e0e81SMark Brown /* If any consumer failed we need to unwind any that succeeded */ 3834414c70cbSLiam Girdwood for (i = 0; i < num_consumers; i++) { 3835f21e0e81SMark Brown if (consumers[i].ret != 0) { 3836f21e0e81SMark Brown ret = consumers[i].ret; 3837414c70cbSLiam Girdwood goto err; 3838414c70cbSLiam Girdwood } 3839f21e0e81SMark Brown } 3840414c70cbSLiam Girdwood 3841414c70cbSLiam Girdwood return 0; 3842414c70cbSLiam Girdwood 3843414c70cbSLiam Girdwood err: 3844fbe31057SAndrzej Hajda for (i = 0; i < num_consumers; i++) { 3845fbe31057SAndrzej Hajda if (consumers[i].ret < 0) 3846fbe31057SAndrzej Hajda pr_err("Failed to enable %s: %d\n", consumers[i].supply, 3847fbe31057SAndrzej Hajda consumers[i].ret); 3848fbe31057SAndrzej Hajda else 3849414c70cbSLiam Girdwood regulator_disable(consumers[i].consumer); 3850fbe31057SAndrzej Hajda } 3851414c70cbSLiam Girdwood 3852414c70cbSLiam Girdwood return ret; 3853414c70cbSLiam Girdwood } 3854414c70cbSLiam Girdwood EXPORT_SYMBOL_GPL(regulator_bulk_enable); 3855414c70cbSLiam Girdwood 3856414c70cbSLiam Girdwood /** 3857414c70cbSLiam Girdwood * regulator_bulk_disable - disable multiple regulator consumers 3858414c70cbSLiam Girdwood * 3859414c70cbSLiam Girdwood * @num_consumers: Number of consumers 3860414c70cbSLiam Girdwood * @consumers: Consumer data; clients are stored here. 3861414c70cbSLiam Girdwood * @return 0 on success, an errno on failure 3862414c70cbSLiam Girdwood * 3863414c70cbSLiam Girdwood * This convenience API allows consumers to disable multiple regulator 386449e22632SSylwester Nawrocki * clients in a single API call. If any consumers cannot be disabled 386549e22632SSylwester Nawrocki * then any others that were disabled will be enabled again prior to 3866414c70cbSLiam Girdwood * return. 3867414c70cbSLiam Girdwood */ 3868414c70cbSLiam Girdwood int regulator_bulk_disable(int num_consumers, 3869414c70cbSLiam Girdwood struct regulator_bulk_data *consumers) 3870414c70cbSLiam Girdwood { 3871414c70cbSLiam Girdwood int i; 387201e86f49SMark Brown int ret, r; 3873414c70cbSLiam Girdwood 387449e22632SSylwester Nawrocki for (i = num_consumers - 1; i >= 0; --i) { 3875414c70cbSLiam Girdwood ret = regulator_disable(consumers[i].consumer); 3876414c70cbSLiam Girdwood if (ret != 0) 3877414c70cbSLiam Girdwood goto err; 3878414c70cbSLiam Girdwood } 3879414c70cbSLiam Girdwood 3880414c70cbSLiam Girdwood return 0; 3881414c70cbSLiam Girdwood 3882414c70cbSLiam Girdwood err: 38835da84fd9SJoe Perches pr_err("Failed to disable %s: %d\n", consumers[i].supply, ret); 388401e86f49SMark Brown for (++i; i < num_consumers; ++i) { 388501e86f49SMark Brown r = regulator_enable(consumers[i].consumer); 388601e86f49SMark Brown if (r != 0) 3887d1642ea7SDmitry Torokhov pr_err("Failed to re-enable %s: %d\n", 388801e86f49SMark Brown consumers[i].supply, r); 388901e86f49SMark Brown } 3890414c70cbSLiam Girdwood 3891414c70cbSLiam Girdwood return ret; 3892414c70cbSLiam Girdwood } 3893414c70cbSLiam Girdwood EXPORT_SYMBOL_GPL(regulator_bulk_disable); 3894414c70cbSLiam Girdwood 3895414c70cbSLiam Girdwood /** 3896e1de2f42SDonggeun Kim * regulator_bulk_force_disable - force disable multiple regulator consumers 3897e1de2f42SDonggeun Kim * 3898e1de2f42SDonggeun Kim * @num_consumers: Number of consumers 3899e1de2f42SDonggeun Kim * @consumers: Consumer data; clients are stored here. 3900e1de2f42SDonggeun Kim * @return 0 on success, an errno on failure 3901e1de2f42SDonggeun Kim * 3902e1de2f42SDonggeun Kim * This convenience API allows consumers to forcibly disable multiple regulator 3903e1de2f42SDonggeun Kim * clients in a single API call. 3904e1de2f42SDonggeun Kim * NOTE: This should be used for situations when device damage will 3905e1de2f42SDonggeun Kim * likely occur if the regulators are not disabled (e.g. over temp). 3906e1de2f42SDonggeun Kim * Although regulator_force_disable function call for some consumers can 3907e1de2f42SDonggeun Kim * return error numbers, the function is called for all consumers. 3908e1de2f42SDonggeun Kim */ 3909e1de2f42SDonggeun Kim int regulator_bulk_force_disable(int num_consumers, 3910e1de2f42SDonggeun Kim struct regulator_bulk_data *consumers) 3911e1de2f42SDonggeun Kim { 3912e1de2f42SDonggeun Kim int i; 3913b8c77ff6SDmitry Torokhov int ret = 0; 3914e1de2f42SDonggeun Kim 3915b8c77ff6SDmitry Torokhov for (i = 0; i < num_consumers; i++) { 3916e1de2f42SDonggeun Kim consumers[i].ret = 3917e1de2f42SDonggeun Kim regulator_force_disable(consumers[i].consumer); 3918e1de2f42SDonggeun Kim 3919b8c77ff6SDmitry Torokhov /* Store first error for reporting */ 3920b8c77ff6SDmitry Torokhov if (consumers[i].ret && !ret) 3921e1de2f42SDonggeun Kim ret = consumers[i].ret; 3922e1de2f42SDonggeun Kim } 3923e1de2f42SDonggeun Kim 3924e1de2f42SDonggeun Kim return ret; 3925e1de2f42SDonggeun Kim } 3926e1de2f42SDonggeun Kim EXPORT_SYMBOL_GPL(regulator_bulk_force_disable); 3927e1de2f42SDonggeun Kim 3928e1de2f42SDonggeun Kim /** 3929414c70cbSLiam Girdwood * regulator_bulk_free - free multiple regulator consumers 3930414c70cbSLiam Girdwood * 3931414c70cbSLiam Girdwood * @num_consumers: Number of consumers 3932414c70cbSLiam Girdwood * @consumers: Consumer data; clients are stored here. 3933414c70cbSLiam Girdwood * 3934414c70cbSLiam Girdwood * This convenience API allows consumers to free multiple regulator 3935414c70cbSLiam Girdwood * clients in a single API call. 3936414c70cbSLiam Girdwood */ 3937414c70cbSLiam Girdwood void regulator_bulk_free(int num_consumers, 3938414c70cbSLiam Girdwood struct regulator_bulk_data *consumers) 3939414c70cbSLiam Girdwood { 3940414c70cbSLiam Girdwood int i; 3941414c70cbSLiam Girdwood 3942414c70cbSLiam Girdwood for (i = 0; i < num_consumers; i++) { 3943414c70cbSLiam Girdwood regulator_put(consumers[i].consumer); 3944414c70cbSLiam Girdwood consumers[i].consumer = NULL; 3945414c70cbSLiam Girdwood } 3946414c70cbSLiam Girdwood } 3947414c70cbSLiam Girdwood EXPORT_SYMBOL_GPL(regulator_bulk_free); 3948414c70cbSLiam Girdwood 3949414c70cbSLiam Girdwood /** 3950414c70cbSLiam Girdwood * regulator_notifier_call_chain - call regulator event notifier 395169279fb9SMark Brown * @rdev: regulator source 3952414c70cbSLiam Girdwood * @event: notifier block 395369279fb9SMark Brown * @data: callback-specific data. 3954414c70cbSLiam Girdwood * 3955414c70cbSLiam Girdwood * Called by regulator drivers to notify clients a regulator event has 3956414c70cbSLiam Girdwood * occurred. We also notify regulator clients downstream. 3957b136fb44SJonathan Cameron * Note lock must be held by caller. 3958414c70cbSLiam Girdwood */ 3959414c70cbSLiam Girdwood int regulator_notifier_call_chain(struct regulator_dev *rdev, 3960414c70cbSLiam Girdwood unsigned long event, void *data) 3961414c70cbSLiam Girdwood { 396270cfef26SKrzysztof Kozlowski lockdep_assert_held_once(&rdev->mutex); 396370cfef26SKrzysztof Kozlowski 3964414c70cbSLiam Girdwood _notifier_call_chain(rdev, event, data); 3965414c70cbSLiam Girdwood return NOTIFY_DONE; 3966414c70cbSLiam Girdwood 3967414c70cbSLiam Girdwood } 3968414c70cbSLiam Girdwood EXPORT_SYMBOL_GPL(regulator_notifier_call_chain); 3969414c70cbSLiam Girdwood 3970be721979SMark Brown /** 3971be721979SMark Brown * regulator_mode_to_status - convert a regulator mode into a status 3972be721979SMark Brown * 3973be721979SMark Brown * @mode: Mode to convert 3974be721979SMark Brown * 3975be721979SMark Brown * Convert a regulator mode into a status. 3976be721979SMark Brown */ 3977be721979SMark Brown int regulator_mode_to_status(unsigned int mode) 3978be721979SMark Brown { 3979be721979SMark Brown switch (mode) { 3980be721979SMark Brown case REGULATOR_MODE_FAST: 3981be721979SMark Brown return REGULATOR_STATUS_FAST; 3982be721979SMark Brown case REGULATOR_MODE_NORMAL: 3983be721979SMark Brown return REGULATOR_STATUS_NORMAL; 3984be721979SMark Brown case REGULATOR_MODE_IDLE: 3985be721979SMark Brown return REGULATOR_STATUS_IDLE; 398603ffcf3dSKrystian Garbaciak case REGULATOR_MODE_STANDBY: 3987be721979SMark Brown return REGULATOR_STATUS_STANDBY; 3988be721979SMark Brown default: 39891beaf762SKrystian Garbaciak return REGULATOR_STATUS_UNDEFINED; 3990be721979SMark Brown } 3991be721979SMark Brown } 3992be721979SMark Brown EXPORT_SYMBOL_GPL(regulator_mode_to_status); 3993be721979SMark Brown 399439f802d6STakashi Iwai static struct attribute *regulator_dev_attrs[] = { 399539f802d6STakashi Iwai &dev_attr_name.attr, 399639f802d6STakashi Iwai &dev_attr_num_users.attr, 399739f802d6STakashi Iwai &dev_attr_type.attr, 399839f802d6STakashi Iwai &dev_attr_microvolts.attr, 399939f802d6STakashi Iwai &dev_attr_microamps.attr, 400039f802d6STakashi Iwai &dev_attr_opmode.attr, 400139f802d6STakashi Iwai &dev_attr_state.attr, 400239f802d6STakashi Iwai &dev_attr_status.attr, 400339f802d6STakashi Iwai &dev_attr_bypass.attr, 400439f802d6STakashi Iwai &dev_attr_requested_microamps.attr, 400539f802d6STakashi Iwai &dev_attr_min_microvolts.attr, 400639f802d6STakashi Iwai &dev_attr_max_microvolts.attr, 400739f802d6STakashi Iwai &dev_attr_min_microamps.attr, 400839f802d6STakashi Iwai &dev_attr_max_microamps.attr, 400939f802d6STakashi Iwai &dev_attr_suspend_standby_state.attr, 401039f802d6STakashi Iwai &dev_attr_suspend_mem_state.attr, 401139f802d6STakashi Iwai &dev_attr_suspend_disk_state.attr, 401239f802d6STakashi Iwai &dev_attr_suspend_standby_microvolts.attr, 401339f802d6STakashi Iwai &dev_attr_suspend_mem_microvolts.attr, 401439f802d6STakashi Iwai &dev_attr_suspend_disk_microvolts.attr, 401539f802d6STakashi Iwai &dev_attr_suspend_standby_mode.attr, 401639f802d6STakashi Iwai &dev_attr_suspend_mem_mode.attr, 401739f802d6STakashi Iwai &dev_attr_suspend_disk_mode.attr, 401839f802d6STakashi Iwai NULL 401939f802d6STakashi Iwai }; 402039f802d6STakashi Iwai 40217ad68e2fSDavid Brownell /* 40227ad68e2fSDavid Brownell * To avoid cluttering sysfs (and memory) with useless state, only 40237ad68e2fSDavid Brownell * create attributes that can be meaningfully displayed. 40247ad68e2fSDavid Brownell */ 402539f802d6STakashi Iwai static umode_t regulator_attr_is_visible(struct kobject *kobj, 402639f802d6STakashi Iwai struct attribute *attr, int idx) 40277ad68e2fSDavid Brownell { 402839f802d6STakashi Iwai struct device *dev = kobj_to_dev(kobj); 402983080a14SGeliang Tang struct regulator_dev *rdev = dev_to_rdev(dev); 4030272e2315SGuodong Xu const struct regulator_ops *ops = rdev->desc->ops; 403139f802d6STakashi Iwai umode_t mode = attr->mode; 403239f802d6STakashi Iwai 403339f802d6STakashi Iwai /* these three are always present */ 403439f802d6STakashi Iwai if (attr == &dev_attr_name.attr || 403539f802d6STakashi Iwai attr == &dev_attr_num_users.attr || 403639f802d6STakashi Iwai attr == &dev_attr_type.attr) 403739f802d6STakashi Iwai return mode; 40387ad68e2fSDavid Brownell 40397ad68e2fSDavid Brownell /* some attributes need specific methods to be displayed */ 404039f802d6STakashi Iwai if (attr == &dev_attr_microvolts.attr) { 40414c78899bSMark Brown if ((ops->get_voltage && ops->get_voltage(rdev) >= 0) || 4042f2889e65SMark Brown (ops->get_voltage_sel && ops->get_voltage_sel(rdev) >= 0) || 40435a523605SLaxman Dewangan (ops->list_voltage && ops->list_voltage(rdev, 0) >= 0) || 404439f802d6STakashi Iwai (rdev->desc->fixed_uV && rdev->desc->n_voltages == 1)) 404539f802d6STakashi Iwai return mode; 404639f802d6STakashi Iwai return 0; 4047f59c8f9fSMark Brown } 40487ad68e2fSDavid Brownell 404939f802d6STakashi Iwai if (attr == &dev_attr_microamps.attr) 405039f802d6STakashi Iwai return ops->get_current_limit ? mode : 0; 405139f802d6STakashi Iwai 405239f802d6STakashi Iwai if (attr == &dev_attr_opmode.attr) 405339f802d6STakashi Iwai return ops->get_mode ? mode : 0; 405439f802d6STakashi Iwai 405539f802d6STakashi Iwai if (attr == &dev_attr_state.attr) 405639f802d6STakashi Iwai return (rdev->ena_pin || ops->is_enabled) ? mode : 0; 405739f802d6STakashi Iwai 405839f802d6STakashi Iwai if (attr == &dev_attr_status.attr) 405939f802d6STakashi Iwai return ops->get_status ? mode : 0; 406039f802d6STakashi Iwai 406139f802d6STakashi Iwai if (attr == &dev_attr_bypass.attr) 406239f802d6STakashi Iwai return ops->get_bypass ? mode : 0; 406339f802d6STakashi Iwai 40647ad68e2fSDavid Brownell /* some attributes are type-specific */ 406539f802d6STakashi Iwai if (attr == &dev_attr_requested_microamps.attr) 406639f802d6STakashi Iwai return rdev->desc->type == REGULATOR_CURRENT ? mode : 0; 40677ad68e2fSDavid Brownell 40687ad68e2fSDavid Brownell /* constraints need specific supporting methods */ 406939f802d6STakashi Iwai if (attr == &dev_attr_min_microvolts.attr || 407039f802d6STakashi Iwai attr == &dev_attr_max_microvolts.attr) 407139f802d6STakashi Iwai return (ops->set_voltage || ops->set_voltage_sel) ? mode : 0; 407239f802d6STakashi Iwai 407339f802d6STakashi Iwai if (attr == &dev_attr_min_microamps.attr || 407439f802d6STakashi Iwai attr == &dev_attr_max_microamps.attr) 407539f802d6STakashi Iwai return ops->set_current_limit ? mode : 0; 407639f802d6STakashi Iwai 407739f802d6STakashi Iwai if (attr == &dev_attr_suspend_standby_state.attr || 407839f802d6STakashi Iwai attr == &dev_attr_suspend_mem_state.attr || 407939f802d6STakashi Iwai attr == &dev_attr_suspend_disk_state.attr) 408039f802d6STakashi Iwai return mode; 408139f802d6STakashi Iwai 408239f802d6STakashi Iwai if (attr == &dev_attr_suspend_standby_microvolts.attr || 408339f802d6STakashi Iwai attr == &dev_attr_suspend_mem_microvolts.attr || 408439f802d6STakashi Iwai attr == &dev_attr_suspend_disk_microvolts.attr) 408539f802d6STakashi Iwai return ops->set_suspend_voltage ? mode : 0; 408639f802d6STakashi Iwai 408739f802d6STakashi Iwai if (attr == &dev_attr_suspend_standby_mode.attr || 408839f802d6STakashi Iwai attr == &dev_attr_suspend_mem_mode.attr || 408939f802d6STakashi Iwai attr == &dev_attr_suspend_disk_mode.attr) 409039f802d6STakashi Iwai return ops->set_suspend_mode ? mode : 0; 409139f802d6STakashi Iwai 409239f802d6STakashi Iwai return mode; 40937ad68e2fSDavid Brownell } 40947ad68e2fSDavid Brownell 409539f802d6STakashi Iwai static const struct attribute_group regulator_dev_group = { 409639f802d6STakashi Iwai .attrs = regulator_dev_attrs, 409739f802d6STakashi Iwai .is_visible = regulator_attr_is_visible, 409839f802d6STakashi Iwai }; 40997ad68e2fSDavid Brownell 410039f802d6STakashi Iwai static const struct attribute_group *regulator_dev_groups[] = { 410139f802d6STakashi Iwai ®ulator_dev_group, 410239f802d6STakashi Iwai NULL 410339f802d6STakashi Iwai }; 410439f802d6STakashi Iwai 410539f802d6STakashi Iwai static void regulator_dev_release(struct device *dev) 410639f802d6STakashi Iwai { 410739f802d6STakashi Iwai struct regulator_dev *rdev = dev_get_drvdata(dev); 410829f5f486SMark Brown 410929f5f486SMark Brown kfree(rdev->constraints); 411029f5f486SMark Brown of_node_put(rdev->dev.of_node); 411139f802d6STakashi Iwai kfree(rdev); 41127ad68e2fSDavid Brownell } 41137ad68e2fSDavid Brownell 41141130e5b3SMark Brown static void rdev_init_debugfs(struct regulator_dev *rdev) 41151130e5b3SMark Brown { 4116a9eaa813SGuenter Roeck struct device *parent = rdev->dev.parent; 4117a9eaa813SGuenter Roeck const char *rname = rdev_get_name(rdev); 4118a9eaa813SGuenter Roeck char name[NAME_MAX]; 4119a9eaa813SGuenter Roeck 4120a9eaa813SGuenter Roeck /* Avoid duplicate debugfs directory names */ 4121a9eaa813SGuenter Roeck if (parent && rname == rdev->desc->name) { 4122a9eaa813SGuenter Roeck snprintf(name, sizeof(name), "%s-%s", dev_name(parent), 4123a9eaa813SGuenter Roeck rname); 4124a9eaa813SGuenter Roeck rname = name; 4125a9eaa813SGuenter Roeck } 4126a9eaa813SGuenter Roeck 4127a9eaa813SGuenter Roeck rdev->debugfs = debugfs_create_dir(rname, debugfs_root); 412824751434SStephen Boyd if (!rdev->debugfs) { 41291130e5b3SMark Brown rdev_warn(rdev, "Failed to create debugfs directory\n"); 41301130e5b3SMark Brown return; 41311130e5b3SMark Brown } 41321130e5b3SMark Brown 41331130e5b3SMark Brown debugfs_create_u32("use_count", 0444, rdev->debugfs, 41341130e5b3SMark Brown &rdev->use_count); 41351130e5b3SMark Brown debugfs_create_u32("open_count", 0444, rdev->debugfs, 41361130e5b3SMark Brown &rdev->open_count); 4137f59c8f9fSMark Brown debugfs_create_u32("bypass_count", 0444, rdev->debugfs, 4138f59c8f9fSMark Brown &rdev->bypass_count); 41391130e5b3SMark Brown } 41401130e5b3SMark Brown 41415e3ca2b3SJavier Martinez Canillas static int regulator_register_resolve_supply(struct device *dev, void *data) 41425e3ca2b3SJavier Martinez Canillas { 41437ddede6aSJon Hunter struct regulator_dev *rdev = dev_to_rdev(dev); 41447ddede6aSJon Hunter 41457ddede6aSJon Hunter if (regulator_resolve_supply(rdev)) 41467ddede6aSJon Hunter rdev_dbg(rdev, "unable to resolve supply\n"); 41477ddede6aSJon Hunter 41487ddede6aSJon Hunter return 0; 41495e3ca2b3SJavier Martinez Canillas } 41505e3ca2b3SJavier Martinez Canillas 4151d3d64537SMaciej Purski static int regulator_fill_coupling_array(struct regulator_dev *rdev) 4152d3d64537SMaciej Purski { 4153d3d64537SMaciej Purski struct coupling_desc *c_desc = &rdev->coupling_desc; 4154d3d64537SMaciej Purski int n_coupled = c_desc->n_coupled; 4155d3d64537SMaciej Purski struct regulator_dev *c_rdev; 4156d3d64537SMaciej Purski int i; 4157d3d64537SMaciej Purski 4158d3d64537SMaciej Purski for (i = 1; i < n_coupled; i++) { 4159d3d64537SMaciej Purski /* already resolved */ 4160d3d64537SMaciej Purski if (c_desc->coupled_rdevs[i]) 4161d3d64537SMaciej Purski continue; 4162d3d64537SMaciej Purski 4163d3d64537SMaciej Purski c_rdev = of_parse_coupled_regulator(rdev, i - 1); 4164d3d64537SMaciej Purski 4165d3d64537SMaciej Purski if (c_rdev) { 4166d3d64537SMaciej Purski c_desc->coupled_rdevs[i] = c_rdev; 4167d3d64537SMaciej Purski c_desc->n_resolved++; 4168d3d64537SMaciej Purski } 4169d3d64537SMaciej Purski } 4170d3d64537SMaciej Purski 4171d3d64537SMaciej Purski if (rdev->coupling_desc.n_resolved < n_coupled) 4172d3d64537SMaciej Purski return -1; 4173d3d64537SMaciej Purski else 4174d3d64537SMaciej Purski return 0; 4175d3d64537SMaciej Purski } 4176d3d64537SMaciej Purski 4177d3d64537SMaciej Purski static int regulator_register_fill_coupling_array(struct device *dev, 4178d3d64537SMaciej Purski void *data) 4179d3d64537SMaciej Purski { 4180d3d64537SMaciej Purski struct regulator_dev *rdev = dev_to_rdev(dev); 4181d3d64537SMaciej Purski 4182d3d64537SMaciej Purski if (!IS_ENABLED(CONFIG_OF)) 4183d3d64537SMaciej Purski return 0; 4184d3d64537SMaciej Purski 4185d3d64537SMaciej Purski if (regulator_fill_coupling_array(rdev)) 4186d3d64537SMaciej Purski rdev_dbg(rdev, "unable to resolve coupling\n"); 4187d3d64537SMaciej Purski 4188d3d64537SMaciej Purski return 0; 4189d3d64537SMaciej Purski } 4190d3d64537SMaciej Purski 4191d3d64537SMaciej Purski static int regulator_resolve_coupling(struct regulator_dev *rdev) 4192d3d64537SMaciej Purski { 4193d3d64537SMaciej Purski int n_phandles; 4194d3d64537SMaciej Purski 4195d3d64537SMaciej Purski if (!IS_ENABLED(CONFIG_OF)) 4196d3d64537SMaciej Purski n_phandles = 0; 4197d3d64537SMaciej Purski else 4198d3d64537SMaciej Purski n_phandles = of_get_n_coupled(rdev); 4199d3d64537SMaciej Purski 4200d3d64537SMaciej Purski if (n_phandles + 1 > MAX_COUPLED) { 4201d3d64537SMaciej Purski rdev_err(rdev, "too many regulators coupled\n"); 4202d3d64537SMaciej Purski return -EPERM; 4203d3d64537SMaciej Purski } 4204d3d64537SMaciej Purski 4205d3d64537SMaciej Purski /* 4206d3d64537SMaciej Purski * Every regulator should always have coupling descriptor filled with 4207d3d64537SMaciej Purski * at least pointer to itself. 4208d3d64537SMaciej Purski */ 4209d3d64537SMaciej Purski rdev->coupling_desc.coupled_rdevs[0] = rdev; 4210d3d64537SMaciej Purski rdev->coupling_desc.n_coupled = n_phandles + 1; 4211d3d64537SMaciej Purski rdev->coupling_desc.n_resolved++; 4212d3d64537SMaciej Purski 4213d3d64537SMaciej Purski /* regulator isn't coupled */ 4214d3d64537SMaciej Purski if (n_phandles == 0) 4215d3d64537SMaciej Purski return 0; 4216d3d64537SMaciej Purski 4217d3d64537SMaciej Purski /* regulator, which can't change its voltage, can't be coupled */ 4218d3d64537SMaciej Purski if (!regulator_ops_is_valid(rdev, REGULATOR_CHANGE_VOLTAGE)) { 4219d3d64537SMaciej Purski rdev_err(rdev, "voltage operation not allowed\n"); 4220d3d64537SMaciej Purski return -EPERM; 4221d3d64537SMaciej Purski } 4222d3d64537SMaciej Purski 4223d3d64537SMaciej Purski if (rdev->constraints->max_spread <= 0) { 4224d3d64537SMaciej Purski rdev_err(rdev, "wrong max_spread value\n"); 4225d3d64537SMaciej Purski return -EPERM; 4226d3d64537SMaciej Purski } 4227d3d64537SMaciej Purski 4228d3d64537SMaciej Purski if (!of_check_coupling_data(rdev)) 4229d3d64537SMaciej Purski return -EPERM; 4230d3d64537SMaciej Purski 4231d3d64537SMaciej Purski /* 4232d3d64537SMaciej Purski * After everything has been checked, try to fill rdevs array 4233d3d64537SMaciej Purski * with pointers to regulators parsed from device tree. If some 4234d3d64537SMaciej Purski * regulators are not registered yet, retry in late init call 4235d3d64537SMaciej Purski */ 4236d3d64537SMaciej Purski regulator_fill_coupling_array(rdev); 4237d3d64537SMaciej Purski 4238d3d64537SMaciej Purski return 0; 4239d3d64537SMaciej Purski } 4240d3d64537SMaciej Purski 4241414c70cbSLiam Girdwood /** 4242414c70cbSLiam Girdwood * regulator_register - register regulator 424369279fb9SMark Brown * @regulator_desc: regulator to register 4244f47531b1SKrzysztof Kozlowski * @cfg: runtime configuration for regulator 4245414c70cbSLiam Girdwood * 4246414c70cbSLiam Girdwood * Called by regulator drivers to register a regulator. 42470384618aSAxel Lin * Returns a valid pointer to struct regulator_dev on success 42480384618aSAxel Lin * or an ERR_PTR() on error. 4249414c70cbSLiam Girdwood */ 425065f26846SMark Brown struct regulator_dev * 425165f26846SMark Brown regulator_register(const struct regulator_desc *regulator_desc, 42521b3de223SKrzysztof Kozlowski const struct regulator_config *cfg) 4253414c70cbSLiam Girdwood { 42549a8f5e07SMark Brown const struct regulation_constraints *constraints = NULL; 4255c172708dSMark Brown const struct regulator_init_data *init_data; 42561b3de223SKrzysztof Kozlowski struct regulator_config *config = NULL; 425772dca06fSAniroop Mathur static atomic_t regulator_no = ATOMIC_INIT(-1); 4258414c70cbSLiam Girdwood struct regulator_dev *rdev; 425932c8fad4SMark Brown struct device *dev; 4260a5766f11SLiam Girdwood int ret, i; 4261414c70cbSLiam Girdwood 42621b3de223SKrzysztof Kozlowski if (regulator_desc == NULL || cfg == NULL) 4263414c70cbSLiam Girdwood return ERR_PTR(-EINVAL); 4264414c70cbSLiam Girdwood 42651b3de223SKrzysztof Kozlowski dev = cfg->dev; 4266dcf70112SMark Brown WARN_ON(!dev); 426732c8fad4SMark Brown 4268414c70cbSLiam Girdwood if (regulator_desc->name == NULL || regulator_desc->ops == NULL) 4269414c70cbSLiam Girdwood return ERR_PTR(-EINVAL); 4270414c70cbSLiam Girdwood 4271cd78dfc6SDiego Liziero if (regulator_desc->type != REGULATOR_VOLTAGE && 4272cd78dfc6SDiego Liziero regulator_desc->type != REGULATOR_CURRENT) 4273414c70cbSLiam Girdwood return ERR_PTR(-EINVAL); 4274414c70cbSLiam Girdwood 4275476c2d83SMark Brown /* Only one of each should be implemented */ 4276476c2d83SMark Brown WARN_ON(regulator_desc->ops->get_voltage && 4277476c2d83SMark Brown regulator_desc->ops->get_voltage_sel); 4278e8eef82bSMark Brown WARN_ON(regulator_desc->ops->set_voltage && 4279e8eef82bSMark Brown regulator_desc->ops->set_voltage_sel); 4280476c2d83SMark Brown 4281476c2d83SMark Brown /* If we're using selectors we must implement list_voltage. */ 4282476c2d83SMark Brown if (regulator_desc->ops->get_voltage_sel && 4283476c2d83SMark Brown !regulator_desc->ops->list_voltage) { 4284476c2d83SMark Brown return ERR_PTR(-EINVAL); 4285476c2d83SMark Brown } 4286e8eef82bSMark Brown if (regulator_desc->ops->set_voltage_sel && 4287e8eef82bSMark Brown !regulator_desc->ops->list_voltage) { 4288e8eef82bSMark Brown return ERR_PTR(-EINVAL); 4289e8eef82bSMark Brown } 4290476c2d83SMark Brown 4291414c70cbSLiam Girdwood rdev = kzalloc(sizeof(struct regulator_dev), GFP_KERNEL); 4292414c70cbSLiam Girdwood if (rdev == NULL) 4293414c70cbSLiam Girdwood return ERR_PTR(-ENOMEM); 4294414c70cbSLiam Girdwood 42951b3de223SKrzysztof Kozlowski /* 42961b3de223SKrzysztof Kozlowski * Duplicate the config so the driver could override it after 42971b3de223SKrzysztof Kozlowski * parsing init data. 42981b3de223SKrzysztof Kozlowski */ 42991b3de223SKrzysztof Kozlowski config = kmemdup(cfg, sizeof(*cfg), GFP_KERNEL); 43001b3de223SKrzysztof Kozlowski if (config == NULL) { 43011b3de223SKrzysztof Kozlowski kfree(rdev); 43021b3de223SKrzysztof Kozlowski return ERR_PTR(-ENOMEM); 43031b3de223SKrzysztof Kozlowski } 43041b3de223SKrzysztof Kozlowski 4305bfa21a0dSKrzysztof Kozlowski init_data = regulator_of_get_init_data(dev, regulator_desc, config, 4306a0c7b164SMark Brown &rdev->dev.of_node); 4307a0c7b164SMark Brown if (!init_data) { 4308a0c7b164SMark Brown init_data = config->init_data; 4309a0c7b164SMark Brown rdev->dev.of_node = of_node_get(config->of_node); 4310a0c7b164SMark Brown } 4311a0c7b164SMark Brown 4312414c70cbSLiam Girdwood mutex_init(&rdev->mutex); 4313c172708dSMark Brown rdev->reg_data = config->driver_data; 4314414c70cbSLiam Girdwood rdev->owner = regulator_desc->owner; 4315414c70cbSLiam Girdwood rdev->desc = regulator_desc; 43163a4b0a07SMark Brown if (config->regmap) 431765b19ce6SMark Brown rdev->regmap = config->regmap; 431852b84dacSAnilKumar Ch else if (dev_get_regmap(dev, NULL)) 43193a4b0a07SMark Brown rdev->regmap = dev_get_regmap(dev, NULL); 432052b84dacSAnilKumar Ch else if (dev->parent) 432152b84dacSAnilKumar Ch rdev->regmap = dev_get_regmap(dev->parent, NULL); 4322414c70cbSLiam Girdwood INIT_LIST_HEAD(&rdev->consumer_list); 4323414c70cbSLiam Girdwood INIT_LIST_HEAD(&rdev->list); 4324414c70cbSLiam Girdwood BLOCKING_INIT_NOTIFIER_HEAD(&rdev->notifier); 4325da07ecd9SMark Brown INIT_DELAYED_WORK(&rdev->disable_work, regulator_disable_work); 4326414c70cbSLiam Girdwood 4327a5766f11SLiam Girdwood /* preform any regulator specific init */ 43289a8f5e07SMark Brown if (init_data && init_data->regulator_init) { 4329a5766f11SLiam Girdwood ret = init_data->regulator_init(rdev->reg_data); 43304fca9545SDavid Brownell if (ret < 0) 43314fca9545SDavid Brownell goto clean; 4332a5766f11SLiam Girdwood } 4333a5766f11SLiam Girdwood 4334e45e290aSLinus Walleij if (config->ena_gpiod || 4335e45e290aSLinus Walleij ((config->ena_gpio || config->ena_gpio_initialized) && 4336e45e290aSLinus Walleij gpio_is_valid(config->ena_gpio))) { 433745389c47SJon Hunter mutex_lock(®ulator_list_mutex); 4338daad134dSKrzysztof Adamski ret = regulator_ena_gpio_request(rdev, config); 433945389c47SJon Hunter mutex_unlock(®ulator_list_mutex); 4340daad134dSKrzysztof Adamski if (ret != 0) { 4341daad134dSKrzysztof Adamski rdev_err(rdev, "Failed to request enable GPIO%d: %d\n", 4342daad134dSKrzysztof Adamski config->ena_gpio, ret); 434332165230SKrzysztof Adamski goto clean; 4344daad134dSKrzysztof Adamski } 4345daad134dSKrzysztof Adamski } 4346daad134dSKrzysztof Adamski 4347a5766f11SLiam Girdwood /* register with sysfs */ 4348a5766f11SLiam Girdwood rdev->dev.class = ®ulator_class; 4349a5766f11SLiam Girdwood rdev->dev.parent = dev; 435072dca06fSAniroop Mathur dev_set_name(&rdev->dev, "regulator.%lu", 435139138818SAniroop Mathur (unsigned long) atomic_inc_return(®ulator_no)); 4352a5766f11SLiam Girdwood 435374f544c1SMike Rapoport /* set regulator constraints */ 43549a8f5e07SMark Brown if (init_data) 43559a8f5e07SMark Brown constraints = &init_data->constraints; 43569a8f5e07SMark Brown 43579a8f5e07SMark Brown if (init_data && init_data->supply_regulator) 43586261b06dSBjorn Andersson rdev->supply_name = init_data->supply_regulator; 435969511a45SRajendra Nayak else if (regulator_desc->supply_name) 43606261b06dSBjorn Andersson rdev->supply_name = regulator_desc->supply_name; 436169511a45SRajendra Nayak 436245389c47SJon Hunter /* 436345389c47SJon Hunter * Attempt to resolve the regulator supply, if specified, 436445389c47SJon Hunter * but don't return an error if we fail because we will try 436545389c47SJon Hunter * to resolve it again later as more regulators are added. 436645389c47SJon Hunter */ 436745389c47SJon Hunter if (regulator_resolve_supply(rdev)) 436845389c47SJon Hunter rdev_dbg(rdev, "unable to resolve supply\n"); 436945389c47SJon Hunter 437045389c47SJon Hunter ret = set_machine_constraints(rdev, constraints); 437145389c47SJon Hunter if (ret < 0) 437245389c47SJon Hunter goto wash; 437345389c47SJon Hunter 4374d3d64537SMaciej Purski mutex_lock(®ulator_list_mutex); 4375d3d64537SMaciej Purski ret = regulator_resolve_coupling(rdev); 4376d3d64537SMaciej Purski mutex_unlock(®ulator_list_mutex); 4377d3d64537SMaciej Purski 4378d3d64537SMaciej Purski if (ret != 0) 4379d3d64537SMaciej Purski goto wash; 4380d3d64537SMaciej Purski 4381a5766f11SLiam Girdwood /* add consumers devices */ 43829a8f5e07SMark Brown if (init_data) { 438345389c47SJon Hunter mutex_lock(®ulator_list_mutex); 4384a5766f11SLiam Girdwood for (i = 0; i < init_data->num_consumer_supplies; i++) { 4385a5766f11SLiam Girdwood ret = set_consumer_device_supply(rdev, 438640f9244fSMark Brown init_data->consumer_supplies[i].dev_name, 4387a5766f11SLiam Girdwood init_data->consumer_supplies[i].supply); 438823c2f041SMark Brown if (ret < 0) { 438945389c47SJon Hunter mutex_unlock(®ulator_list_mutex); 439023c2f041SMark Brown dev_err(dev, "Failed to set supply %s\n", 439123c2f041SMark Brown init_data->consumer_supplies[i].supply); 4392d4033b54SJani Nikula goto unset_supplies; 4393a5766f11SLiam Girdwood } 439423c2f041SMark Brown } 4395a2151374SJon Hunter mutex_unlock(®ulator_list_mutex); 43969a8f5e07SMark Brown } 4397a5766f11SLiam Girdwood 4398fd086045SMatthias Kaehlcke if (!rdev->desc->ops->get_voltage && 4399fd086045SMatthias Kaehlcke !rdev->desc->ops->list_voltage && 4400fd086045SMatthias Kaehlcke !rdev->desc->fixed_uV) 4401fd086045SMatthias Kaehlcke rdev->is_switch = true; 4402fd086045SMatthias Kaehlcke 4403c438b9d0SJon Hunter ret = device_register(&rdev->dev); 4404c438b9d0SJon Hunter if (ret != 0) { 4405c438b9d0SJon Hunter put_device(&rdev->dev); 4406c438b9d0SJon Hunter goto unset_supplies; 4407c438b9d0SJon Hunter } 4408c438b9d0SJon Hunter 4409c438b9d0SJon Hunter dev_set_drvdata(&rdev->dev, rdev); 44101130e5b3SMark Brown rdev_init_debugfs(rdev); 44115e3ca2b3SJavier Martinez Canillas 44125e3ca2b3SJavier Martinez Canillas /* try to resolve regulators supply since a new one was registered */ 44135e3ca2b3SJavier Martinez Canillas class_for_each_device(®ulator_class, NULL, NULL, 44145e3ca2b3SJavier Martinez Canillas regulator_register_resolve_supply); 44151b3de223SKrzysztof Kozlowski kfree(config); 4416414c70cbSLiam Girdwood return rdev; 44174fca9545SDavid Brownell 4418d4033b54SJani Nikula unset_supplies: 441945389c47SJon Hunter mutex_lock(®ulator_list_mutex); 4420d4033b54SJani Nikula unset_regulator_supplies(rdev); 442145389c47SJon Hunter mutex_unlock(®ulator_list_mutex); 442232165230SKrzysztof Adamski wash: 4423469b640eSBoris Brezillon kfree(rdev->constraints); 442445389c47SJon Hunter mutex_lock(®ulator_list_mutex); 442532165230SKrzysztof Adamski regulator_ena_gpio_free(rdev); 442645389c47SJon Hunter mutex_unlock(®ulator_list_mutex); 44274fca9545SDavid Brownell clean: 44284fca9545SDavid Brownell kfree(rdev); 4429a2151374SJon Hunter kfree(config); 4430a2151374SJon Hunter return ERR_PTR(ret); 4431414c70cbSLiam Girdwood } 4432414c70cbSLiam Girdwood EXPORT_SYMBOL_GPL(regulator_register); 4433414c70cbSLiam Girdwood 4434414c70cbSLiam Girdwood /** 4435414c70cbSLiam Girdwood * regulator_unregister - unregister regulator 443669279fb9SMark Brown * @rdev: regulator to unregister 4437414c70cbSLiam Girdwood * 4438414c70cbSLiam Girdwood * Called by regulator drivers to unregister a regulator. 4439414c70cbSLiam Girdwood */ 4440414c70cbSLiam Girdwood void regulator_unregister(struct regulator_dev *rdev) 4441414c70cbSLiam Girdwood { 4442414c70cbSLiam Girdwood if (rdev == NULL) 4443414c70cbSLiam Girdwood return; 4444414c70cbSLiam Girdwood 4445891636eaSMark Brown if (rdev->supply) { 4446891636eaSMark Brown while (rdev->use_count--) 4447891636eaSMark Brown regulator_disable(rdev->supply); 4448e032b376SMark Brown regulator_put(rdev->supply); 4449891636eaSMark Brown } 4450414c70cbSLiam Girdwood mutex_lock(®ulator_list_mutex); 44511130e5b3SMark Brown debugfs_remove_recursive(rdev->debugfs); 445243829731STejun Heo flush_work(&rdev->disable_work.work); 44536bf87d17SMark Brown WARN_ON(rdev->open_count); 44540f1d747bSMike Rapoport unset_regulator_supplies(rdev); 4455414c70cbSLiam Girdwood list_del(&rdev->list); 4456f19b00daSKim, Milo regulator_ena_gpio_free(rdev); 44572c0a303aSMark Brown mutex_unlock(®ulator_list_mutex); 445858fb5cf5SLothar Waßmann device_unregister(&rdev->dev); 4459414c70cbSLiam Girdwood } 4460414c70cbSLiam Girdwood EXPORT_SYMBOL_GPL(regulator_unregister); 4461414c70cbSLiam Girdwood 4462f7efad10SChunyan Zhang #ifdef CONFIG_SUSPEND 44630380cf7dSpascal paillet static int _regulator_suspend(struct device *dev, void *data) 446485f3b431STomeu Vizoso { 446585f3b431STomeu Vizoso struct regulator_dev *rdev = dev_to_rdev(dev); 4466f7efad10SChunyan Zhang suspend_state_t *state = data; 446785f3b431STomeu Vizoso int ret; 446885f3b431STomeu Vizoso 446966cf9a7eSMaciej Purski regulator_lock(rdev); 4470f7efad10SChunyan Zhang ret = suspend_set_state(rdev, *state); 447166cf9a7eSMaciej Purski regulator_unlock(rdev); 447285f3b431STomeu Vizoso 447385f3b431STomeu Vizoso return ret; 447485f3b431STomeu Vizoso } 447585f3b431STomeu Vizoso 4476414c70cbSLiam Girdwood /** 44770380cf7dSpascal paillet * regulator_suspend - prepare regulators for system wide suspend 4478414c70cbSLiam Girdwood * @state: system suspend state 4479414c70cbSLiam Girdwood * 4480414c70cbSLiam Girdwood * Configure each regulator with it's suspend operating parameters for state. 4481414c70cbSLiam Girdwood */ 44820380cf7dSpascal paillet static int regulator_suspend(struct device *dev) 4483414c70cbSLiam Girdwood { 4484f7efad10SChunyan Zhang suspend_state_t state = pm_suspend_target_state; 4485414c70cbSLiam Girdwood 448685f3b431STomeu Vizoso return class_for_each_device(®ulator_class, NULL, &state, 44870380cf7dSpascal paillet _regulator_suspend); 4488414c70cbSLiam Girdwood } 4489d3e4eccbSMark Brown 44900380cf7dSpascal paillet static int _regulator_resume(struct device *dev, void *data) 449185f3b431STomeu Vizoso { 4492f7efad10SChunyan Zhang int ret = 0; 449385f3b431STomeu Vizoso struct regulator_dev *rdev = dev_to_rdev(dev); 4494f7efad10SChunyan Zhang suspend_state_t *state = data; 4495f7efad10SChunyan Zhang struct regulator_state *rstate; 4496f7efad10SChunyan Zhang 4497f7efad10SChunyan Zhang rstate = regulator_get_suspend_state(rdev, *state); 4498f7efad10SChunyan Zhang if (rstate == NULL) 449935b5f14eSGeert Uytterhoeven return 0; 450085f3b431STomeu Vizoso 450166cf9a7eSMaciej Purski regulator_lock(rdev); 450285f3b431STomeu Vizoso 45030380cf7dSpascal paillet if (rdev->desc->ops->resume && 4504f7efad10SChunyan Zhang (rstate->enabled == ENABLE_IN_SUSPEND || 4505f7efad10SChunyan Zhang rstate->enabled == DISABLE_IN_SUSPEND)) 45060380cf7dSpascal paillet ret = rdev->desc->ops->resume(rdev); 4507f7efad10SChunyan Zhang 450866cf9a7eSMaciej Purski regulator_unlock(rdev); 450985f3b431STomeu Vizoso 4510f7efad10SChunyan Zhang return ret; 451185f3b431STomeu Vizoso } 451285f3b431STomeu Vizoso 45130380cf7dSpascal paillet static int regulator_resume(struct device *dev) 45147a32b589SMyungJoo Ham { 4515f7efad10SChunyan Zhang suspend_state_t state = pm_suspend_target_state; 45167a32b589SMyungJoo Ham 4517f7efad10SChunyan Zhang return class_for_each_device(®ulator_class, NULL, &state, 45180380cf7dSpascal paillet _regulator_resume); 4519f7efad10SChunyan Zhang } 4520f7efad10SChunyan Zhang 4521f7efad10SChunyan Zhang #else /* !CONFIG_SUSPEND */ 4522f7efad10SChunyan Zhang 45230380cf7dSpascal paillet #define regulator_suspend NULL 45240380cf7dSpascal paillet #define regulator_resume NULL 4525f7efad10SChunyan Zhang 4526f7efad10SChunyan Zhang #endif /* !CONFIG_SUSPEND */ 4527f7efad10SChunyan Zhang 4528f7efad10SChunyan Zhang #ifdef CONFIG_PM 4529f7efad10SChunyan Zhang static const struct dev_pm_ops __maybe_unused regulator_pm_ops = { 45300380cf7dSpascal paillet .suspend = regulator_suspend, 45310380cf7dSpascal paillet .resume = regulator_resume, 4532f7efad10SChunyan Zhang }; 4533f7efad10SChunyan Zhang #endif 4534f7efad10SChunyan Zhang 4535285c22deSMark Brown struct class regulator_class = { 4536f7efad10SChunyan Zhang .name = "regulator", 4537f7efad10SChunyan Zhang .dev_release = regulator_dev_release, 4538f7efad10SChunyan Zhang .dev_groups = regulator_dev_groups, 4539f7efad10SChunyan Zhang #ifdef CONFIG_PM 4540f7efad10SChunyan Zhang .pm = ®ulator_pm_ops, 4541f7efad10SChunyan Zhang #endif 4542f7efad10SChunyan Zhang }; 45437a32b589SMyungJoo Ham /** 4544ca725561SMark Brown * regulator_has_full_constraints - the system has fully specified constraints 4545ca725561SMark Brown * 4546ca725561SMark Brown * Calling this function will cause the regulator API to disable all 4547ca725561SMark Brown * regulators which have a zero use count and don't have an always_on 4548ca725561SMark Brown * constraint in a late_initcall. 4549ca725561SMark Brown * 4550ca725561SMark Brown * The intention is that this will become the default behaviour in a 4551ca725561SMark Brown * future kernel release so users are encouraged to use this facility 4552ca725561SMark Brown * now. 4553ca725561SMark Brown */ 4554ca725561SMark Brown void regulator_has_full_constraints(void) 4555ca725561SMark Brown { 4556ca725561SMark Brown has_full_constraints = 1; 4557ca725561SMark Brown } 4558ca725561SMark Brown EXPORT_SYMBOL_GPL(regulator_has_full_constraints); 4559ca725561SMark Brown 4560ca725561SMark Brown /** 4561414c70cbSLiam Girdwood * rdev_get_drvdata - get rdev regulator driver data 456269279fb9SMark Brown * @rdev: regulator 4563414c70cbSLiam Girdwood * 4564414c70cbSLiam Girdwood * Get rdev regulator driver private data. This call can be used in the 4565414c70cbSLiam Girdwood * regulator driver context. 4566414c70cbSLiam Girdwood */ 4567414c70cbSLiam Girdwood void *rdev_get_drvdata(struct regulator_dev *rdev) 4568414c70cbSLiam Girdwood { 4569414c70cbSLiam Girdwood return rdev->reg_data; 4570414c70cbSLiam Girdwood } 4571414c70cbSLiam Girdwood EXPORT_SYMBOL_GPL(rdev_get_drvdata); 4572414c70cbSLiam Girdwood 4573414c70cbSLiam Girdwood /** 4574414c70cbSLiam Girdwood * regulator_get_drvdata - get regulator driver data 4575414c70cbSLiam Girdwood * @regulator: regulator 4576414c70cbSLiam Girdwood * 4577414c70cbSLiam Girdwood * Get regulator driver private data. This call can be used in the consumer 4578414c70cbSLiam Girdwood * driver context when non API regulator specific functions need to be called. 4579414c70cbSLiam Girdwood */ 4580414c70cbSLiam Girdwood void *regulator_get_drvdata(struct regulator *regulator) 4581414c70cbSLiam Girdwood { 4582414c70cbSLiam Girdwood return regulator->rdev->reg_data; 4583414c70cbSLiam Girdwood } 4584414c70cbSLiam Girdwood EXPORT_SYMBOL_GPL(regulator_get_drvdata); 4585414c70cbSLiam Girdwood 4586414c70cbSLiam Girdwood /** 4587414c70cbSLiam Girdwood * regulator_set_drvdata - set regulator driver data 4588414c70cbSLiam Girdwood * @regulator: regulator 4589414c70cbSLiam Girdwood * @data: data 4590414c70cbSLiam Girdwood */ 4591414c70cbSLiam Girdwood void regulator_set_drvdata(struct regulator *regulator, void *data) 4592414c70cbSLiam Girdwood { 4593414c70cbSLiam Girdwood regulator->rdev->reg_data = data; 4594414c70cbSLiam Girdwood } 4595414c70cbSLiam Girdwood EXPORT_SYMBOL_GPL(regulator_set_drvdata); 4596414c70cbSLiam Girdwood 4597414c70cbSLiam Girdwood /** 4598414c70cbSLiam Girdwood * regulator_get_id - get regulator ID 459969279fb9SMark Brown * @rdev: regulator 4600414c70cbSLiam Girdwood */ 4601414c70cbSLiam Girdwood int rdev_get_id(struct regulator_dev *rdev) 4602414c70cbSLiam Girdwood { 4603414c70cbSLiam Girdwood return rdev->desc->id; 4604414c70cbSLiam Girdwood } 4605414c70cbSLiam Girdwood EXPORT_SYMBOL_GPL(rdev_get_id); 4606414c70cbSLiam Girdwood 4607a5766f11SLiam Girdwood struct device *rdev_get_dev(struct regulator_dev *rdev) 4608a5766f11SLiam Girdwood { 4609a5766f11SLiam Girdwood return &rdev->dev; 4610a5766f11SLiam Girdwood } 4611a5766f11SLiam Girdwood EXPORT_SYMBOL_GPL(rdev_get_dev); 4612a5766f11SLiam Girdwood 4613a5766f11SLiam Girdwood void *regulator_get_init_drvdata(struct regulator_init_data *reg_init_data) 4614a5766f11SLiam Girdwood { 4615a5766f11SLiam Girdwood return reg_init_data->driver_data; 4616a5766f11SLiam Girdwood } 4617a5766f11SLiam Girdwood EXPORT_SYMBOL_GPL(regulator_get_init_drvdata); 4618a5766f11SLiam Girdwood 4619ba55a974SMark Brown #ifdef CONFIG_DEBUG_FS 4620dbc55955SHaishan Zhou static int supply_map_show(struct seq_file *sf, void *data) 4621ba55a974SMark Brown { 4622ba55a974SMark Brown struct regulator_map *map; 4623ba55a974SMark Brown 4624ba55a974SMark Brown list_for_each_entry(map, ®ulator_map_list, list) { 4625dbc55955SHaishan Zhou seq_printf(sf, "%s -> %s.%s\n", 4626ba55a974SMark Brown rdev_get_name(map->regulator), map->dev_name, 4627ba55a974SMark Brown map->supply); 4628ba55a974SMark Brown } 4629ba55a974SMark Brown 4630dbc55955SHaishan Zhou return 0; 4631dbc55955SHaishan Zhou } 4632ba55a974SMark Brown 4633dbc55955SHaishan Zhou static int supply_map_open(struct inode *inode, struct file *file) 4634dbc55955SHaishan Zhou { 4635dbc55955SHaishan Zhou return single_open(file, supply_map_show, inode->i_private); 4636ba55a974SMark Brown } 463724751434SStephen Boyd #endif 4638ba55a974SMark Brown 4639ba55a974SMark Brown static const struct file_operations supply_map_fops = { 464024751434SStephen Boyd #ifdef CONFIG_DEBUG_FS 4641dbc55955SHaishan Zhou .open = supply_map_open, 4642dbc55955SHaishan Zhou .read = seq_read, 4643dbc55955SHaishan Zhou .llseek = seq_lseek, 4644dbc55955SHaishan Zhou .release = single_release, 4645ba55a974SMark Brown #endif 464624751434SStephen Boyd }; 4647ba55a974SMark Brown 46487c225ec9SHeiko Stübner #ifdef CONFIG_DEBUG_FS 464985f3b431STomeu Vizoso struct summary_data { 465085f3b431STomeu Vizoso struct seq_file *s; 465185f3b431STomeu Vizoso struct regulator_dev *parent; 465285f3b431STomeu Vizoso int level; 465385f3b431STomeu Vizoso }; 465485f3b431STomeu Vizoso 465585f3b431STomeu Vizoso static void regulator_summary_show_subtree(struct seq_file *s, 465685f3b431STomeu Vizoso struct regulator_dev *rdev, 465785f3b431STomeu Vizoso int level); 465885f3b431STomeu Vizoso 465985f3b431STomeu Vizoso static int regulator_summary_show_children(struct device *dev, void *data) 466085f3b431STomeu Vizoso { 466185f3b431STomeu Vizoso struct regulator_dev *rdev = dev_to_rdev(dev); 466285f3b431STomeu Vizoso struct summary_data *summary_data = data; 466385f3b431STomeu Vizoso 466485f3b431STomeu Vizoso if (rdev->supply && rdev->supply->rdev == summary_data->parent) 466585f3b431STomeu Vizoso regulator_summary_show_subtree(summary_data->s, rdev, 466685f3b431STomeu Vizoso summary_data->level + 1); 466785f3b431STomeu Vizoso 466885f3b431STomeu Vizoso return 0; 466985f3b431STomeu Vizoso } 467085f3b431STomeu Vizoso 46717c225ec9SHeiko Stübner static void regulator_summary_show_subtree(struct seq_file *s, 46727c225ec9SHeiko Stübner struct regulator_dev *rdev, 46737c225ec9SHeiko Stübner int level) 46747c225ec9SHeiko Stübner { 46757c225ec9SHeiko Stübner struct regulation_constraints *c; 46767c225ec9SHeiko Stübner struct regulator *consumer; 467785f3b431STomeu Vizoso struct summary_data summary_data; 46787c225ec9SHeiko Stübner 46797c225ec9SHeiko Stübner if (!rdev) 46807c225ec9SHeiko Stübner return; 46817c225ec9SHeiko Stübner 468201de19d0SDouglas Anderson seq_printf(s, "%*s%-*s %3d %4d %6d %7s ", 46837c225ec9SHeiko Stübner level * 3 + 1, "", 46847c225ec9SHeiko Stübner 30 - level * 3, rdev_get_name(rdev), 468501de19d0SDouglas Anderson rdev->use_count, rdev->open_count, rdev->bypass_count, 468601de19d0SDouglas Anderson regulator_opmode_to_str(_regulator_get_mode(rdev))); 46877c225ec9SHeiko Stübner 468823296099SHeiko Stübner seq_printf(s, "%5dmV ", _regulator_get_voltage(rdev) / 1000); 468923296099SHeiko Stübner seq_printf(s, "%5dmA ", _regulator_get_current_limit(rdev) / 1000); 46907c225ec9SHeiko Stübner 46917c225ec9SHeiko Stübner c = rdev->constraints; 46927c225ec9SHeiko Stübner if (c) { 46937c225ec9SHeiko Stübner switch (rdev->desc->type) { 46947c225ec9SHeiko Stübner case REGULATOR_VOLTAGE: 46957c225ec9SHeiko Stübner seq_printf(s, "%5dmV %5dmV ", 46967c225ec9SHeiko Stübner c->min_uV / 1000, c->max_uV / 1000); 46977c225ec9SHeiko Stübner break; 46987c225ec9SHeiko Stübner case REGULATOR_CURRENT: 46997c225ec9SHeiko Stübner seq_printf(s, "%5dmA %5dmA ", 47007c225ec9SHeiko Stübner c->min_uA / 1000, c->max_uA / 1000); 47017c225ec9SHeiko Stübner break; 47027c225ec9SHeiko Stübner } 47037c225ec9SHeiko Stübner } 47047c225ec9SHeiko Stübner 47057c225ec9SHeiko Stübner seq_puts(s, "\n"); 47067c225ec9SHeiko Stübner 47077c225ec9SHeiko Stübner list_for_each_entry(consumer, &rdev->consumer_list, list) { 4708e42a46b6SLeonard Crestez if (consumer->dev && consumer->dev->class == ®ulator_class) 47097c225ec9SHeiko Stübner continue; 47107c225ec9SHeiko Stübner 47117c225ec9SHeiko Stübner seq_printf(s, "%*s%-*s ", 47127c225ec9SHeiko Stübner (level + 1) * 3 + 1, "", 4713e42a46b6SLeonard Crestez 30 - (level + 1) * 3, 4714e42a46b6SLeonard Crestez consumer->dev ? dev_name(consumer->dev) : "deviceless"); 47157c225ec9SHeiko Stübner 47167c225ec9SHeiko Stübner switch (rdev->desc->type) { 47177c225ec9SHeiko Stübner case REGULATOR_VOLTAGE: 471801de19d0SDouglas Anderson seq_printf(s, "%45dmV %5dmV", 4719c360a6dfSChunyan Zhang consumer->voltage[PM_SUSPEND_ON].min_uV / 1000, 4720c360a6dfSChunyan Zhang consumer->voltage[PM_SUSPEND_ON].max_uV / 1000); 47217c225ec9SHeiko Stübner break; 47227c225ec9SHeiko Stübner case REGULATOR_CURRENT: 47237c225ec9SHeiko Stübner break; 47247c225ec9SHeiko Stübner } 47257c225ec9SHeiko Stübner 47267c225ec9SHeiko Stübner seq_puts(s, "\n"); 47277c225ec9SHeiko Stübner } 47287c225ec9SHeiko Stübner 472985f3b431STomeu Vizoso summary_data.s = s; 473085f3b431STomeu Vizoso summary_data.level = level; 473185f3b431STomeu Vizoso summary_data.parent = rdev; 47327c225ec9SHeiko Stübner 473385f3b431STomeu Vizoso class_for_each_device(®ulator_class, NULL, &summary_data, 473485f3b431STomeu Vizoso regulator_summary_show_children); 47357c225ec9SHeiko Stübner } 473685f3b431STomeu Vizoso 473785f3b431STomeu Vizoso static int regulator_summary_show_roots(struct device *dev, void *data) 473885f3b431STomeu Vizoso { 473985f3b431STomeu Vizoso struct regulator_dev *rdev = dev_to_rdev(dev); 474085f3b431STomeu Vizoso struct seq_file *s = data; 474185f3b431STomeu Vizoso 474285f3b431STomeu Vizoso if (!rdev->supply) 474385f3b431STomeu Vizoso regulator_summary_show_subtree(s, rdev, 0); 474485f3b431STomeu Vizoso 474585f3b431STomeu Vizoso return 0; 47467c225ec9SHeiko Stübner } 47477c225ec9SHeiko Stübner 47487c225ec9SHeiko Stübner static int regulator_summary_show(struct seq_file *s, void *data) 47497c225ec9SHeiko Stübner { 475001de19d0SDouglas Anderson seq_puts(s, " regulator use open bypass opmode voltage current min max\n"); 475101de19d0SDouglas Anderson seq_puts(s, "---------------------------------------------------------------------------------------\n"); 47527c225ec9SHeiko Stübner 475385f3b431STomeu Vizoso class_for_each_device(®ulator_class, NULL, s, 475485f3b431STomeu Vizoso regulator_summary_show_roots); 47557c225ec9SHeiko Stübner 47567c225ec9SHeiko Stübner return 0; 47577c225ec9SHeiko Stübner } 47587c225ec9SHeiko Stübner 47597c225ec9SHeiko Stübner static int regulator_summary_open(struct inode *inode, struct file *file) 47607c225ec9SHeiko Stübner { 47617c225ec9SHeiko Stübner return single_open(file, regulator_summary_show, inode->i_private); 47627c225ec9SHeiko Stübner } 47637c225ec9SHeiko Stübner #endif 47647c225ec9SHeiko Stübner 47657c225ec9SHeiko Stübner static const struct file_operations regulator_summary_fops = { 47667c225ec9SHeiko Stübner #ifdef CONFIG_DEBUG_FS 47677c225ec9SHeiko Stübner .open = regulator_summary_open, 47687c225ec9SHeiko Stübner .read = seq_read, 47697c225ec9SHeiko Stübner .llseek = seq_lseek, 47707c225ec9SHeiko Stübner .release = single_release, 47717c225ec9SHeiko Stübner #endif 47727c225ec9SHeiko Stübner }; 47737c225ec9SHeiko Stübner 4774414c70cbSLiam Girdwood static int __init regulator_init(void) 4775414c70cbSLiam Girdwood { 477634abbd68SMark Brown int ret; 477734abbd68SMark Brown 477834abbd68SMark Brown ret = class_register(®ulator_class); 477934abbd68SMark Brown 47801130e5b3SMark Brown debugfs_root = debugfs_create_dir("regulator", NULL); 478124751434SStephen Boyd if (!debugfs_root) 47821130e5b3SMark Brown pr_warn("regulator: Failed to create debugfs directory\n"); 4783ba55a974SMark Brown 4784f4d562c6SMark Brown debugfs_create_file("supply_map", 0444, debugfs_root, NULL, 4785f4d562c6SMark Brown &supply_map_fops); 47861130e5b3SMark Brown 47877c225ec9SHeiko Stübner debugfs_create_file("regulator_summary", 0444, debugfs_root, 478885f3b431STomeu Vizoso NULL, ®ulator_summary_fops); 47897c225ec9SHeiko Stübner 479034abbd68SMark Brown regulator_dummy_init(); 479134abbd68SMark Brown 479234abbd68SMark Brown return ret; 4793414c70cbSLiam Girdwood } 4794414c70cbSLiam Girdwood 4795414c70cbSLiam Girdwood /* init early to allow our consumers to complete system booting */ 4796414c70cbSLiam Girdwood core_initcall(regulator_init); 4797ca725561SMark Brown 4798609ca5f3SMark Brown static int __init regulator_late_cleanup(struct device *dev, void *data) 4799ca725561SMark Brown { 4800609ca5f3SMark Brown struct regulator_dev *rdev = dev_to_rdev(dev); 4801609ca5f3SMark Brown const struct regulator_ops *ops = rdev->desc->ops; 4802609ca5f3SMark Brown struct regulation_constraints *c = rdev->constraints; 4803ca725561SMark Brown int enabled, ret; 4804ca725561SMark Brown 480566fda75fSMarkus Pargmann if (c && c->always_on) 4806609ca5f3SMark Brown return 0; 4807ca725561SMark Brown 48088a34e979SWEN Pingbo if (!regulator_ops_is_valid(rdev, REGULATOR_CHANGE_STATUS)) 4809609ca5f3SMark Brown return 0; 4810e9535834SMark Brown 481166cf9a7eSMaciej Purski regulator_lock(rdev); 4812ca725561SMark Brown 4813ca725561SMark Brown if (rdev->use_count) 4814ca725561SMark Brown goto unlock; 4815ca725561SMark Brown 4816ca725561SMark Brown /* If we can't read the status assume it's on. */ 4817ca725561SMark Brown if (ops->is_enabled) 4818ca725561SMark Brown enabled = ops->is_enabled(rdev); 4819ca725561SMark Brown else 4820ca725561SMark Brown enabled = 1; 4821ca725561SMark Brown 4822ca725561SMark Brown if (!enabled) 4823ca725561SMark Brown goto unlock; 4824ca725561SMark Brown 482587b28417SMark Brown if (have_full_constraints()) { 4826609ca5f3SMark Brown /* We log since this may kill the system if it goes 4827609ca5f3SMark Brown * wrong. */ 48285da84fd9SJoe Perches rdev_info(rdev, "disabling\n"); 482966fda75fSMarkus Pargmann ret = _regulator_do_disable(rdev); 48300d25d09dSJingoo Han if (ret != 0) 48315da84fd9SJoe Perches rdev_err(rdev, "couldn't disable: %d\n", ret); 4832ca725561SMark Brown } else { 4833ca725561SMark Brown /* The intention is that in future we will 4834ca725561SMark Brown * assume that full constraints are provided 4835ca725561SMark Brown * so warn even if we aren't going to do 4836ca725561SMark Brown * anything here. 4837ca725561SMark Brown */ 48385da84fd9SJoe Perches rdev_warn(rdev, "incomplete constraints, leaving on\n"); 4839ca725561SMark Brown } 4840ca725561SMark Brown 4841ca725561SMark Brown unlock: 484266cf9a7eSMaciej Purski regulator_unlock(rdev); 4843609ca5f3SMark Brown 4844609ca5f3SMark Brown return 0; 4845ca725561SMark Brown } 4846ca725561SMark Brown 4847609ca5f3SMark Brown static int __init regulator_init_complete(void) 4848609ca5f3SMark Brown { 4849609ca5f3SMark Brown /* 4850609ca5f3SMark Brown * Since DT doesn't provide an idiomatic mechanism for 4851609ca5f3SMark Brown * enabling full constraints and since it's much more natural 4852609ca5f3SMark Brown * with DT to provide them just assume that a DT enabled 4853609ca5f3SMark Brown * system has full constraints. 4854609ca5f3SMark Brown */ 4855609ca5f3SMark Brown if (of_have_populated_dt()) 4856609ca5f3SMark Brown has_full_constraints = true; 4857609ca5f3SMark Brown 48583827b64dSJavier Martinez Canillas /* 48593827b64dSJavier Martinez Canillas * Regulators may had failed to resolve their input supplies 48603827b64dSJavier Martinez Canillas * when were registered, either because the input supply was 48613827b64dSJavier Martinez Canillas * not registered yet or because its parent device was not 48623827b64dSJavier Martinez Canillas * bound yet. So attempt to resolve the input supplies for 48633827b64dSJavier Martinez Canillas * pending regulators before trying to disable unused ones. 48643827b64dSJavier Martinez Canillas */ 48653827b64dSJavier Martinez Canillas class_for_each_device(®ulator_class, NULL, NULL, 48663827b64dSJavier Martinez Canillas regulator_register_resolve_supply); 48673827b64dSJavier Martinez Canillas 4868609ca5f3SMark Brown /* If we have a full configuration then disable any regulators 4869609ca5f3SMark Brown * we have permission to change the status for and which are 4870609ca5f3SMark Brown * not in use or always_on. This is effectively the default 4871609ca5f3SMark Brown * for DT and ACPI as they have full constraints. 4872609ca5f3SMark Brown */ 4873609ca5f3SMark Brown class_for_each_device(®ulator_class, NULL, NULL, 4874609ca5f3SMark Brown regulator_late_cleanup); 4875ca725561SMark Brown 4876d3d64537SMaciej Purski class_for_each_device(®ulator_class, NULL, NULL, 4877d3d64537SMaciej Purski regulator_register_fill_coupling_array); 4878d3d64537SMaciej Purski 4879ca725561SMark Brown return 0; 4880ca725561SMark Brown } 4881fd482a3eSSaravana Kannan late_initcall_sync(regulator_init_complete); 4882