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 /** 1509f01cd4aSSascha Hauer * regulator_lock_supply - lock a regulator and its supplies 1519f01cd4aSSascha Hauer * @rdev: regulator source 1529f01cd4aSSascha Hauer */ 1539f01cd4aSSascha Hauer static void regulator_lock_supply(struct regulator_dev *rdev) 1549f01cd4aSSascha Hauer { 155fa731ac7SArnd Bergmann int i; 1569f01cd4aSSascha Hauer 15770a7fb80SThierry Reding for (i = 0; rdev; rdev = rdev_get_supply(rdev), i++) 158fa731ac7SArnd Bergmann mutex_lock_nested(&rdev->mutex, i); 1599f01cd4aSSascha Hauer } 1609f01cd4aSSascha Hauer 1619f01cd4aSSascha Hauer /** 1629f01cd4aSSascha Hauer * regulator_unlock_supply - unlock a regulator and its supplies 1639f01cd4aSSascha Hauer * @rdev: regulator source 1649f01cd4aSSascha Hauer */ 1659f01cd4aSSascha Hauer static void regulator_unlock_supply(struct regulator_dev *rdev) 1669f01cd4aSSascha Hauer { 1679f01cd4aSSascha Hauer struct regulator *supply; 1689f01cd4aSSascha Hauer 1699f01cd4aSSascha Hauer while (1) { 1709f01cd4aSSascha Hauer mutex_unlock(&rdev->mutex); 1719f01cd4aSSascha Hauer supply = rdev->supply; 1729f01cd4aSSascha Hauer 1739f01cd4aSSascha Hauer if (!rdev->supply) 1749f01cd4aSSascha Hauer return; 1759f01cd4aSSascha Hauer 1769f01cd4aSSascha Hauer rdev = supply->rdev; 1779f01cd4aSSascha Hauer } 1789f01cd4aSSascha Hauer } 1799f01cd4aSSascha Hauer 1809f01cd4aSSascha Hauer /** 18169511a45SRajendra Nayak * of_get_regulator - get a regulator device node based on supply name 18269511a45SRajendra Nayak * @dev: Device pointer for the consumer (of regulator) device 18369511a45SRajendra Nayak * @supply: regulator supply name 18469511a45SRajendra Nayak * 18569511a45SRajendra Nayak * Extract the regulator device node corresponding to the supply name. 186167d41dcSMaxime Ripard * returns the device node corresponding to the regulator if found, else 18769511a45SRajendra Nayak * returns NULL. 18869511a45SRajendra Nayak */ 18969511a45SRajendra Nayak static struct device_node *of_get_regulator(struct device *dev, const char *supply) 19069511a45SRajendra Nayak { 19169511a45SRajendra Nayak struct device_node *regnode = NULL; 19269511a45SRajendra Nayak char prop_name[32]; /* 32 is max size of property name */ 19369511a45SRajendra Nayak 19469511a45SRajendra Nayak dev_dbg(dev, "Looking up %s-supply from device tree\n", supply); 19569511a45SRajendra Nayak 19669511a45SRajendra Nayak snprintf(prop_name, 32, "%s-supply", supply); 19769511a45SRajendra Nayak regnode = of_parse_phandle(dev->of_node, prop_name, 0); 19869511a45SRajendra Nayak 19969511a45SRajendra Nayak if (!regnode) { 2007799167bSRob Herring dev_dbg(dev, "Looking up %s property in node %pOF failed\n", 2017799167bSRob Herring prop_name, dev->of_node); 20269511a45SRajendra Nayak return NULL; 20369511a45SRajendra Nayak } 20469511a45SRajendra Nayak return regnode; 20569511a45SRajendra Nayak } 20669511a45SRajendra Nayak 207414c70cbSLiam Girdwood /* Platform voltage constraint check */ 208414c70cbSLiam Girdwood static int regulator_check_voltage(struct regulator_dev *rdev, 209414c70cbSLiam Girdwood int *min_uV, int *max_uV) 210414c70cbSLiam Girdwood { 211414c70cbSLiam Girdwood BUG_ON(*min_uV > *max_uV); 212414c70cbSLiam Girdwood 2138a34e979SWEN Pingbo if (!regulator_ops_is_valid(rdev, REGULATOR_CHANGE_VOLTAGE)) { 2147ebcf26cSStephen Boyd rdev_err(rdev, "voltage operation not allowed\n"); 215414c70cbSLiam Girdwood return -EPERM; 216414c70cbSLiam Girdwood } 217414c70cbSLiam Girdwood 218414c70cbSLiam Girdwood if (*max_uV > rdev->constraints->max_uV) 219414c70cbSLiam Girdwood *max_uV = rdev->constraints->max_uV; 220414c70cbSLiam Girdwood if (*min_uV < rdev->constraints->min_uV) 221414c70cbSLiam Girdwood *min_uV = rdev->constraints->min_uV; 222414c70cbSLiam Girdwood 22389f425edSMark Brown if (*min_uV > *max_uV) { 22489f425edSMark Brown rdev_err(rdev, "unsupportable voltage range: %d-%duV\n", 22554abd335SMark Brown *min_uV, *max_uV); 226414c70cbSLiam Girdwood return -EINVAL; 22789f425edSMark Brown } 228414c70cbSLiam Girdwood 229414c70cbSLiam Girdwood return 0; 230414c70cbSLiam Girdwood } 231414c70cbSLiam Girdwood 232f7efad10SChunyan Zhang /* return 0 if the state is valid */ 233f7efad10SChunyan Zhang static int regulator_check_states(suspend_state_t state) 234f7efad10SChunyan Zhang { 235f7efad10SChunyan Zhang return (state > PM_SUSPEND_MAX || state == PM_SUSPEND_TO_IDLE); 236f7efad10SChunyan Zhang } 237f7efad10SChunyan Zhang 23805fda3b1SThomas Petazzoni /* Make sure we select a voltage that suits the needs of all 23905fda3b1SThomas Petazzoni * regulator consumers 24005fda3b1SThomas Petazzoni */ 24105fda3b1SThomas Petazzoni static int regulator_check_consumers(struct regulator_dev *rdev, 242c360a6dfSChunyan Zhang int *min_uV, int *max_uV, 243c360a6dfSChunyan Zhang suspend_state_t state) 24405fda3b1SThomas Petazzoni { 24505fda3b1SThomas Petazzoni struct regulator *regulator; 246c360a6dfSChunyan Zhang struct regulator_voltage *voltage; 24705fda3b1SThomas Petazzoni 24805fda3b1SThomas Petazzoni list_for_each_entry(regulator, &rdev->consumer_list, list) { 249c360a6dfSChunyan Zhang voltage = ®ulator->voltage[state]; 2504aa922c0SMark Brown /* 2514aa922c0SMark Brown * Assume consumers that didn't say anything are OK 2524aa922c0SMark Brown * with anything in the constraint range. 2534aa922c0SMark Brown */ 254c360a6dfSChunyan Zhang if (!voltage->min_uV && !voltage->max_uV) 2554aa922c0SMark Brown continue; 2564aa922c0SMark Brown 257c360a6dfSChunyan Zhang if (*max_uV > voltage->max_uV) 258c360a6dfSChunyan Zhang *max_uV = voltage->max_uV; 259c360a6dfSChunyan Zhang if (*min_uV < voltage->min_uV) 260c360a6dfSChunyan Zhang *min_uV = voltage->min_uV; 26105fda3b1SThomas Petazzoni } 26205fda3b1SThomas Petazzoni 263dd8004afSMark Brown if (*min_uV > *max_uV) { 2649c7b4e8aSRuss Dill rdev_err(rdev, "Restricting voltage, %u-%uuV\n", 2659c7b4e8aSRuss Dill *min_uV, *max_uV); 26605fda3b1SThomas Petazzoni return -EINVAL; 267dd8004afSMark Brown } 26805fda3b1SThomas Petazzoni 26905fda3b1SThomas Petazzoni return 0; 27005fda3b1SThomas Petazzoni } 27105fda3b1SThomas Petazzoni 272414c70cbSLiam Girdwood /* current constraint check */ 273414c70cbSLiam Girdwood static int regulator_check_current_limit(struct regulator_dev *rdev, 274414c70cbSLiam Girdwood int *min_uA, int *max_uA) 275414c70cbSLiam Girdwood { 276414c70cbSLiam Girdwood BUG_ON(*min_uA > *max_uA); 277414c70cbSLiam Girdwood 2788a34e979SWEN Pingbo if (!regulator_ops_is_valid(rdev, REGULATOR_CHANGE_CURRENT)) { 2797ebcf26cSStephen Boyd rdev_err(rdev, "current operation not allowed\n"); 280414c70cbSLiam Girdwood return -EPERM; 281414c70cbSLiam Girdwood } 282414c70cbSLiam Girdwood 283414c70cbSLiam Girdwood if (*max_uA > rdev->constraints->max_uA) 284414c70cbSLiam Girdwood *max_uA = rdev->constraints->max_uA; 285414c70cbSLiam Girdwood if (*min_uA < rdev->constraints->min_uA) 286414c70cbSLiam Girdwood *min_uA = rdev->constraints->min_uA; 287414c70cbSLiam Girdwood 28889f425edSMark Brown if (*min_uA > *max_uA) { 28989f425edSMark Brown rdev_err(rdev, "unsupportable current range: %d-%duA\n", 29054abd335SMark Brown *min_uA, *max_uA); 291414c70cbSLiam Girdwood return -EINVAL; 29289f425edSMark Brown } 293414c70cbSLiam Girdwood 294414c70cbSLiam Girdwood return 0; 295414c70cbSLiam Girdwood } 296414c70cbSLiam Girdwood 297414c70cbSLiam Girdwood /* operating mode constraint check */ 298109c75afSCharles Keepax static int regulator_mode_constrain(struct regulator_dev *rdev, 299109c75afSCharles Keepax unsigned int *mode) 300414c70cbSLiam Girdwood { 3012c608234SMark Brown switch (*mode) { 302e573520bSDavid Brownell case REGULATOR_MODE_FAST: 303e573520bSDavid Brownell case REGULATOR_MODE_NORMAL: 304e573520bSDavid Brownell case REGULATOR_MODE_IDLE: 305e573520bSDavid Brownell case REGULATOR_MODE_STANDBY: 306e573520bSDavid Brownell break; 307e573520bSDavid Brownell default: 30889f425edSMark Brown rdev_err(rdev, "invalid mode %x specified\n", *mode); 309e573520bSDavid Brownell return -EINVAL; 310e573520bSDavid Brownell } 311e573520bSDavid Brownell 3128a34e979SWEN Pingbo if (!regulator_ops_is_valid(rdev, REGULATOR_CHANGE_MODE)) { 3137ebcf26cSStephen Boyd rdev_err(rdev, "mode operation not allowed\n"); 314414c70cbSLiam Girdwood return -EPERM; 315414c70cbSLiam Girdwood } 3162c608234SMark Brown 3172c608234SMark Brown /* The modes are bitmasks, the most power hungry modes having 3182c608234SMark Brown * the lowest values. If the requested mode isn't supported 3192c608234SMark Brown * try higher modes. */ 3202c608234SMark Brown while (*mode) { 3212c608234SMark Brown if (rdev->constraints->valid_modes_mask & *mode) 322414c70cbSLiam Girdwood return 0; 3232c608234SMark Brown *mode /= 2; 3242c608234SMark Brown } 3252c608234SMark Brown 3262c608234SMark Brown return -EINVAL; 327414c70cbSLiam Girdwood } 328414c70cbSLiam Girdwood 329f7efad10SChunyan Zhang static inline struct regulator_state * 330f7efad10SChunyan Zhang regulator_get_suspend_state(struct regulator_dev *rdev, suspend_state_t state) 331f7efad10SChunyan Zhang { 332f7efad10SChunyan Zhang if (rdev->constraints == NULL) 333f7efad10SChunyan Zhang return NULL; 334f7efad10SChunyan Zhang 335f7efad10SChunyan Zhang switch (state) { 336f7efad10SChunyan Zhang case PM_SUSPEND_STANDBY: 337f7efad10SChunyan Zhang return &rdev->constraints->state_standby; 338f7efad10SChunyan Zhang case PM_SUSPEND_MEM: 339f7efad10SChunyan Zhang return &rdev->constraints->state_mem; 340f7efad10SChunyan Zhang case PM_SUSPEND_MAX: 341f7efad10SChunyan Zhang return &rdev->constraints->state_disk; 342f7efad10SChunyan Zhang default: 343f7efad10SChunyan Zhang return NULL; 344f7efad10SChunyan Zhang } 345f7efad10SChunyan Zhang } 346f7efad10SChunyan Zhang 347414c70cbSLiam Girdwood static ssize_t regulator_uV_show(struct device *dev, 348414c70cbSLiam Girdwood struct device_attribute *attr, char *buf) 349414c70cbSLiam Girdwood { 350a5766f11SLiam Girdwood struct regulator_dev *rdev = dev_get_drvdata(dev); 351414c70cbSLiam Girdwood ssize_t ret; 352414c70cbSLiam Girdwood 353414c70cbSLiam Girdwood mutex_lock(&rdev->mutex); 354414c70cbSLiam Girdwood ret = sprintf(buf, "%d\n", _regulator_get_voltage(rdev)); 355414c70cbSLiam Girdwood mutex_unlock(&rdev->mutex); 356414c70cbSLiam Girdwood 357414c70cbSLiam Girdwood return ret; 358414c70cbSLiam Girdwood } 3597ad68e2fSDavid Brownell static DEVICE_ATTR(microvolts, 0444, regulator_uV_show, NULL); 360414c70cbSLiam Girdwood 361414c70cbSLiam Girdwood static ssize_t regulator_uA_show(struct device *dev, 362414c70cbSLiam Girdwood struct device_attribute *attr, char *buf) 363414c70cbSLiam Girdwood { 364a5766f11SLiam Girdwood struct regulator_dev *rdev = dev_get_drvdata(dev); 365414c70cbSLiam Girdwood 366414c70cbSLiam Girdwood return sprintf(buf, "%d\n", _regulator_get_current_limit(rdev)); 367414c70cbSLiam Girdwood } 3687ad68e2fSDavid Brownell static DEVICE_ATTR(microamps, 0444, regulator_uA_show, NULL); 369414c70cbSLiam Girdwood 370587cea27SGreg Kroah-Hartman static ssize_t name_show(struct device *dev, struct device_attribute *attr, 371587cea27SGreg Kroah-Hartman char *buf) 372bc558a60SMark Brown { 373bc558a60SMark Brown struct regulator_dev *rdev = dev_get_drvdata(dev); 374bc558a60SMark Brown 3751083c393SMark Brown return sprintf(buf, "%s\n", rdev_get_name(rdev)); 376bc558a60SMark Brown } 377587cea27SGreg Kroah-Hartman static DEVICE_ATTR_RO(name); 378bc558a60SMark Brown 3794fca9545SDavid Brownell static ssize_t regulator_print_opmode(char *buf, int mode) 380414c70cbSLiam Girdwood { 381414c70cbSLiam Girdwood switch (mode) { 382414c70cbSLiam Girdwood case REGULATOR_MODE_FAST: 383414c70cbSLiam Girdwood return sprintf(buf, "fast\n"); 384414c70cbSLiam Girdwood case REGULATOR_MODE_NORMAL: 385414c70cbSLiam Girdwood return sprintf(buf, "normal\n"); 386414c70cbSLiam Girdwood case REGULATOR_MODE_IDLE: 387414c70cbSLiam Girdwood return sprintf(buf, "idle\n"); 388414c70cbSLiam Girdwood case REGULATOR_MODE_STANDBY: 389414c70cbSLiam Girdwood return sprintf(buf, "standby\n"); 390414c70cbSLiam Girdwood } 391414c70cbSLiam Girdwood return sprintf(buf, "unknown\n"); 392414c70cbSLiam Girdwood } 393414c70cbSLiam Girdwood 3944fca9545SDavid Brownell static ssize_t regulator_opmode_show(struct device *dev, 395414c70cbSLiam Girdwood struct device_attribute *attr, char *buf) 396414c70cbSLiam Girdwood { 397a5766f11SLiam Girdwood struct regulator_dev *rdev = dev_get_drvdata(dev); 398414c70cbSLiam Girdwood 3994fca9545SDavid Brownell return regulator_print_opmode(buf, _regulator_get_mode(rdev)); 4004fca9545SDavid Brownell } 4017ad68e2fSDavid Brownell static DEVICE_ATTR(opmode, 0444, regulator_opmode_show, NULL); 4024fca9545SDavid Brownell 4034fca9545SDavid Brownell static ssize_t regulator_print_state(char *buf, int state) 4044fca9545SDavid Brownell { 405414c70cbSLiam Girdwood if (state > 0) 406414c70cbSLiam Girdwood return sprintf(buf, "enabled\n"); 407414c70cbSLiam Girdwood else if (state == 0) 408414c70cbSLiam Girdwood return sprintf(buf, "disabled\n"); 409414c70cbSLiam Girdwood else 410414c70cbSLiam Girdwood return sprintf(buf, "unknown\n"); 411414c70cbSLiam Girdwood } 412414c70cbSLiam Girdwood 4134fca9545SDavid Brownell static ssize_t regulator_state_show(struct device *dev, 4144fca9545SDavid Brownell struct device_attribute *attr, char *buf) 4154fca9545SDavid Brownell { 4164fca9545SDavid Brownell struct regulator_dev *rdev = dev_get_drvdata(dev); 4179332546fSMark Brown ssize_t ret; 4184fca9545SDavid Brownell 4199332546fSMark Brown mutex_lock(&rdev->mutex); 4209332546fSMark Brown ret = regulator_print_state(buf, _regulator_is_enabled(rdev)); 4219332546fSMark Brown mutex_unlock(&rdev->mutex); 4229332546fSMark Brown 4239332546fSMark Brown return ret; 4244fca9545SDavid Brownell } 4257ad68e2fSDavid Brownell static DEVICE_ATTR(state, 0444, regulator_state_show, NULL); 4264fca9545SDavid Brownell 427853116a1SDavid Brownell static ssize_t regulator_status_show(struct device *dev, 428853116a1SDavid Brownell struct device_attribute *attr, char *buf) 429853116a1SDavid Brownell { 430853116a1SDavid Brownell struct regulator_dev *rdev = dev_get_drvdata(dev); 431853116a1SDavid Brownell int status; 432853116a1SDavid Brownell char *label; 433853116a1SDavid Brownell 434853116a1SDavid Brownell status = rdev->desc->ops->get_status(rdev); 435853116a1SDavid Brownell if (status < 0) 436853116a1SDavid Brownell return status; 437853116a1SDavid Brownell 438853116a1SDavid Brownell switch (status) { 439853116a1SDavid Brownell case REGULATOR_STATUS_OFF: 440853116a1SDavid Brownell label = "off"; 441853116a1SDavid Brownell break; 442853116a1SDavid Brownell case REGULATOR_STATUS_ON: 443853116a1SDavid Brownell label = "on"; 444853116a1SDavid Brownell break; 445853116a1SDavid Brownell case REGULATOR_STATUS_ERROR: 446853116a1SDavid Brownell label = "error"; 447853116a1SDavid Brownell break; 448853116a1SDavid Brownell case REGULATOR_STATUS_FAST: 449853116a1SDavid Brownell label = "fast"; 450853116a1SDavid Brownell break; 451853116a1SDavid Brownell case REGULATOR_STATUS_NORMAL: 452853116a1SDavid Brownell label = "normal"; 453853116a1SDavid Brownell break; 454853116a1SDavid Brownell case REGULATOR_STATUS_IDLE: 455853116a1SDavid Brownell label = "idle"; 456853116a1SDavid Brownell break; 457853116a1SDavid Brownell case REGULATOR_STATUS_STANDBY: 458853116a1SDavid Brownell label = "standby"; 459853116a1SDavid Brownell break; 460f59c8f9fSMark Brown case REGULATOR_STATUS_BYPASS: 461f59c8f9fSMark Brown label = "bypass"; 462f59c8f9fSMark Brown break; 4631beaf762SKrystian Garbaciak case REGULATOR_STATUS_UNDEFINED: 4641beaf762SKrystian Garbaciak label = "undefined"; 4651beaf762SKrystian Garbaciak break; 466853116a1SDavid Brownell default: 467853116a1SDavid Brownell return -ERANGE; 468853116a1SDavid Brownell } 469853116a1SDavid Brownell 470853116a1SDavid Brownell return sprintf(buf, "%s\n", label); 471853116a1SDavid Brownell } 472853116a1SDavid Brownell static DEVICE_ATTR(status, 0444, regulator_status_show, NULL); 473853116a1SDavid Brownell 474414c70cbSLiam Girdwood static ssize_t regulator_min_uA_show(struct device *dev, 475414c70cbSLiam Girdwood struct device_attribute *attr, char *buf) 476414c70cbSLiam Girdwood { 477a5766f11SLiam Girdwood struct regulator_dev *rdev = dev_get_drvdata(dev); 478414c70cbSLiam Girdwood 479414c70cbSLiam Girdwood if (!rdev->constraints) 480414c70cbSLiam Girdwood return sprintf(buf, "constraint not defined\n"); 481414c70cbSLiam Girdwood 482414c70cbSLiam Girdwood return sprintf(buf, "%d\n", rdev->constraints->min_uA); 483414c70cbSLiam Girdwood } 4847ad68e2fSDavid Brownell static DEVICE_ATTR(min_microamps, 0444, regulator_min_uA_show, NULL); 485414c70cbSLiam Girdwood 486414c70cbSLiam Girdwood static ssize_t regulator_max_uA_show(struct device *dev, 487414c70cbSLiam Girdwood struct device_attribute *attr, char *buf) 488414c70cbSLiam Girdwood { 489a5766f11SLiam Girdwood struct regulator_dev *rdev = dev_get_drvdata(dev); 490414c70cbSLiam Girdwood 491414c70cbSLiam Girdwood if (!rdev->constraints) 492414c70cbSLiam Girdwood return sprintf(buf, "constraint not defined\n"); 493414c70cbSLiam Girdwood 494414c70cbSLiam Girdwood return sprintf(buf, "%d\n", rdev->constraints->max_uA); 495414c70cbSLiam Girdwood } 4967ad68e2fSDavid Brownell static DEVICE_ATTR(max_microamps, 0444, regulator_max_uA_show, NULL); 497414c70cbSLiam Girdwood 498414c70cbSLiam Girdwood static ssize_t regulator_min_uV_show(struct device *dev, 499414c70cbSLiam Girdwood struct device_attribute *attr, char *buf) 500414c70cbSLiam Girdwood { 501a5766f11SLiam Girdwood struct regulator_dev *rdev = dev_get_drvdata(dev); 502414c70cbSLiam Girdwood 503414c70cbSLiam Girdwood if (!rdev->constraints) 504414c70cbSLiam Girdwood return sprintf(buf, "constraint not defined\n"); 505414c70cbSLiam Girdwood 506414c70cbSLiam Girdwood return sprintf(buf, "%d\n", rdev->constraints->min_uV); 507414c70cbSLiam Girdwood } 5087ad68e2fSDavid Brownell static DEVICE_ATTR(min_microvolts, 0444, regulator_min_uV_show, NULL); 509414c70cbSLiam Girdwood 510414c70cbSLiam Girdwood static ssize_t regulator_max_uV_show(struct device *dev, 511414c70cbSLiam Girdwood struct device_attribute *attr, char *buf) 512414c70cbSLiam Girdwood { 513a5766f11SLiam Girdwood struct regulator_dev *rdev = dev_get_drvdata(dev); 514414c70cbSLiam Girdwood 515414c70cbSLiam Girdwood if (!rdev->constraints) 516414c70cbSLiam Girdwood return sprintf(buf, "constraint not defined\n"); 517414c70cbSLiam Girdwood 518414c70cbSLiam Girdwood return sprintf(buf, "%d\n", rdev->constraints->max_uV); 519414c70cbSLiam Girdwood } 5207ad68e2fSDavid Brownell static DEVICE_ATTR(max_microvolts, 0444, regulator_max_uV_show, NULL); 521414c70cbSLiam Girdwood 522414c70cbSLiam Girdwood static ssize_t regulator_total_uA_show(struct device *dev, 523414c70cbSLiam Girdwood struct device_attribute *attr, char *buf) 524414c70cbSLiam Girdwood { 525a5766f11SLiam Girdwood struct regulator_dev *rdev = dev_get_drvdata(dev); 526414c70cbSLiam Girdwood struct regulator *regulator; 527414c70cbSLiam Girdwood int uA = 0; 528414c70cbSLiam Girdwood 529414c70cbSLiam Girdwood mutex_lock(&rdev->mutex); 530414c70cbSLiam Girdwood list_for_each_entry(regulator, &rdev->consumer_list, list) 531414c70cbSLiam Girdwood uA += regulator->uA_load; 532414c70cbSLiam Girdwood mutex_unlock(&rdev->mutex); 533414c70cbSLiam Girdwood return sprintf(buf, "%d\n", uA); 534414c70cbSLiam Girdwood } 5357ad68e2fSDavid Brownell static DEVICE_ATTR(requested_microamps, 0444, regulator_total_uA_show, NULL); 536414c70cbSLiam Girdwood 537587cea27SGreg Kroah-Hartman static ssize_t num_users_show(struct device *dev, struct device_attribute *attr, 538587cea27SGreg Kroah-Hartman char *buf) 539414c70cbSLiam Girdwood { 540a5766f11SLiam Girdwood struct regulator_dev *rdev = dev_get_drvdata(dev); 541414c70cbSLiam Girdwood return sprintf(buf, "%d\n", rdev->use_count); 542414c70cbSLiam Girdwood } 543587cea27SGreg Kroah-Hartman static DEVICE_ATTR_RO(num_users); 544414c70cbSLiam Girdwood 545587cea27SGreg Kroah-Hartman static ssize_t type_show(struct device *dev, struct device_attribute *attr, 546587cea27SGreg Kroah-Hartman char *buf) 547414c70cbSLiam Girdwood { 548a5766f11SLiam Girdwood struct regulator_dev *rdev = dev_get_drvdata(dev); 549414c70cbSLiam Girdwood 550414c70cbSLiam Girdwood switch (rdev->desc->type) { 551414c70cbSLiam Girdwood case REGULATOR_VOLTAGE: 552414c70cbSLiam Girdwood return sprintf(buf, "voltage\n"); 553414c70cbSLiam Girdwood case REGULATOR_CURRENT: 554414c70cbSLiam Girdwood return sprintf(buf, "current\n"); 555414c70cbSLiam Girdwood } 556414c70cbSLiam Girdwood return sprintf(buf, "unknown\n"); 557414c70cbSLiam Girdwood } 558587cea27SGreg Kroah-Hartman static DEVICE_ATTR_RO(type); 559414c70cbSLiam Girdwood 560414c70cbSLiam Girdwood static ssize_t regulator_suspend_mem_uV_show(struct device *dev, 561414c70cbSLiam Girdwood struct device_attribute *attr, char *buf) 562414c70cbSLiam Girdwood { 563a5766f11SLiam Girdwood struct regulator_dev *rdev = dev_get_drvdata(dev); 564414c70cbSLiam Girdwood 565414c70cbSLiam Girdwood return sprintf(buf, "%d\n", rdev->constraints->state_mem.uV); 566414c70cbSLiam Girdwood } 5677ad68e2fSDavid Brownell static DEVICE_ATTR(suspend_mem_microvolts, 0444, 5687ad68e2fSDavid Brownell regulator_suspend_mem_uV_show, NULL); 569414c70cbSLiam Girdwood 570414c70cbSLiam Girdwood static ssize_t regulator_suspend_disk_uV_show(struct device *dev, 571414c70cbSLiam Girdwood struct device_attribute *attr, char *buf) 572414c70cbSLiam Girdwood { 573a5766f11SLiam Girdwood struct regulator_dev *rdev = dev_get_drvdata(dev); 574414c70cbSLiam Girdwood 575414c70cbSLiam Girdwood return sprintf(buf, "%d\n", rdev->constraints->state_disk.uV); 576414c70cbSLiam Girdwood } 5777ad68e2fSDavid Brownell static DEVICE_ATTR(suspend_disk_microvolts, 0444, 5787ad68e2fSDavid Brownell regulator_suspend_disk_uV_show, NULL); 579414c70cbSLiam Girdwood 580414c70cbSLiam Girdwood static ssize_t regulator_suspend_standby_uV_show(struct device *dev, 581414c70cbSLiam Girdwood struct device_attribute *attr, char *buf) 582414c70cbSLiam Girdwood { 583a5766f11SLiam Girdwood struct regulator_dev *rdev = dev_get_drvdata(dev); 584414c70cbSLiam Girdwood 585414c70cbSLiam Girdwood return sprintf(buf, "%d\n", rdev->constraints->state_standby.uV); 586414c70cbSLiam Girdwood } 5877ad68e2fSDavid Brownell static DEVICE_ATTR(suspend_standby_microvolts, 0444, 5887ad68e2fSDavid Brownell regulator_suspend_standby_uV_show, NULL); 589414c70cbSLiam Girdwood 590414c70cbSLiam Girdwood static ssize_t regulator_suspend_mem_mode_show(struct device *dev, 591414c70cbSLiam Girdwood struct device_attribute *attr, char *buf) 592414c70cbSLiam Girdwood { 593a5766f11SLiam Girdwood struct regulator_dev *rdev = dev_get_drvdata(dev); 594414c70cbSLiam Girdwood 5954fca9545SDavid Brownell return regulator_print_opmode(buf, 5964fca9545SDavid Brownell rdev->constraints->state_mem.mode); 597414c70cbSLiam Girdwood } 5987ad68e2fSDavid Brownell static DEVICE_ATTR(suspend_mem_mode, 0444, 5997ad68e2fSDavid Brownell regulator_suspend_mem_mode_show, NULL); 600414c70cbSLiam Girdwood 601414c70cbSLiam Girdwood static ssize_t regulator_suspend_disk_mode_show(struct device *dev, 602414c70cbSLiam Girdwood struct device_attribute *attr, char *buf) 603414c70cbSLiam Girdwood { 604a5766f11SLiam Girdwood struct regulator_dev *rdev = dev_get_drvdata(dev); 605414c70cbSLiam Girdwood 6064fca9545SDavid Brownell return regulator_print_opmode(buf, 6074fca9545SDavid Brownell rdev->constraints->state_disk.mode); 608414c70cbSLiam Girdwood } 6097ad68e2fSDavid Brownell static DEVICE_ATTR(suspend_disk_mode, 0444, 6107ad68e2fSDavid Brownell regulator_suspend_disk_mode_show, NULL); 611414c70cbSLiam Girdwood 612414c70cbSLiam Girdwood static ssize_t regulator_suspend_standby_mode_show(struct device *dev, 613414c70cbSLiam Girdwood struct device_attribute *attr, char *buf) 614414c70cbSLiam Girdwood { 615a5766f11SLiam Girdwood struct regulator_dev *rdev = dev_get_drvdata(dev); 616414c70cbSLiam Girdwood 6174fca9545SDavid Brownell return regulator_print_opmode(buf, 6184fca9545SDavid Brownell rdev->constraints->state_standby.mode); 619414c70cbSLiam Girdwood } 6207ad68e2fSDavid Brownell static DEVICE_ATTR(suspend_standby_mode, 0444, 6217ad68e2fSDavid Brownell regulator_suspend_standby_mode_show, NULL); 622414c70cbSLiam Girdwood 623414c70cbSLiam Girdwood static ssize_t regulator_suspend_mem_state_show(struct device *dev, 624414c70cbSLiam Girdwood struct device_attribute *attr, char *buf) 625414c70cbSLiam Girdwood { 626a5766f11SLiam Girdwood struct regulator_dev *rdev = dev_get_drvdata(dev); 627414c70cbSLiam Girdwood 6284fca9545SDavid Brownell return regulator_print_state(buf, 6294fca9545SDavid Brownell rdev->constraints->state_mem.enabled); 630414c70cbSLiam Girdwood } 6317ad68e2fSDavid Brownell static DEVICE_ATTR(suspend_mem_state, 0444, 6327ad68e2fSDavid Brownell regulator_suspend_mem_state_show, NULL); 633414c70cbSLiam Girdwood 634414c70cbSLiam Girdwood static ssize_t regulator_suspend_disk_state_show(struct device *dev, 635414c70cbSLiam Girdwood struct device_attribute *attr, char *buf) 636414c70cbSLiam Girdwood { 637a5766f11SLiam Girdwood struct regulator_dev *rdev = dev_get_drvdata(dev); 638414c70cbSLiam Girdwood 6394fca9545SDavid Brownell return regulator_print_state(buf, 6404fca9545SDavid Brownell rdev->constraints->state_disk.enabled); 641414c70cbSLiam Girdwood } 6427ad68e2fSDavid Brownell static DEVICE_ATTR(suspend_disk_state, 0444, 6437ad68e2fSDavid Brownell regulator_suspend_disk_state_show, NULL); 644414c70cbSLiam Girdwood 645414c70cbSLiam Girdwood static ssize_t regulator_suspend_standby_state_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_state(buf, 6514fca9545SDavid Brownell rdev->constraints->state_standby.enabled); 652414c70cbSLiam Girdwood } 6537ad68e2fSDavid Brownell static DEVICE_ATTR(suspend_standby_state, 0444, 6547ad68e2fSDavid Brownell regulator_suspend_standby_state_show, NULL); 655bc558a60SMark Brown 656f59c8f9fSMark Brown static ssize_t regulator_bypass_show(struct device *dev, 657f59c8f9fSMark Brown struct device_attribute *attr, char *buf) 658f59c8f9fSMark Brown { 659f59c8f9fSMark Brown struct regulator_dev *rdev = dev_get_drvdata(dev); 660f59c8f9fSMark Brown const char *report; 661f59c8f9fSMark Brown bool bypass; 662f59c8f9fSMark Brown int ret; 663f59c8f9fSMark Brown 664f59c8f9fSMark Brown ret = rdev->desc->ops->get_bypass(rdev, &bypass); 665f59c8f9fSMark Brown 666f59c8f9fSMark Brown if (ret != 0) 667f59c8f9fSMark Brown report = "unknown"; 668f59c8f9fSMark Brown else if (bypass) 669f59c8f9fSMark Brown report = "enabled"; 670f59c8f9fSMark Brown else 671f59c8f9fSMark Brown report = "disabled"; 672f59c8f9fSMark Brown 673f59c8f9fSMark Brown return sprintf(buf, "%s\n", report); 674f59c8f9fSMark Brown } 675f59c8f9fSMark Brown static DEVICE_ATTR(bypass, 0444, 676f59c8f9fSMark Brown regulator_bypass_show, NULL); 6777ad68e2fSDavid Brownell 678414c70cbSLiam Girdwood /* Calculate the new optimum regulator operating mode based on the new total 679414c70cbSLiam Girdwood * consumer load. All locks held by caller */ 6808460ef38SBjorn Andersson static int drms_uA_update(struct regulator_dev *rdev) 681414c70cbSLiam Girdwood { 682414c70cbSLiam Girdwood struct regulator *sibling; 683414c70cbSLiam Girdwood int current_uA = 0, output_uV, input_uV, err; 684414c70cbSLiam Girdwood unsigned int mode; 685414c70cbSLiam Girdwood 68670cfef26SKrzysztof Kozlowski lockdep_assert_held_once(&rdev->mutex); 68770cfef26SKrzysztof Kozlowski 6888460ef38SBjorn Andersson /* 6898460ef38SBjorn Andersson * first check to see if we can set modes at all, otherwise just 6908460ef38SBjorn Andersson * tell the consumer everything is OK. 6918460ef38SBjorn Andersson */ 6928a34e979SWEN Pingbo if (!regulator_ops_is_valid(rdev, REGULATOR_CHANGE_DRMS)) 6938460ef38SBjorn Andersson return 0; 6948460ef38SBjorn Andersson 6958f4490e0SBjorn Andersson if (!rdev->desc->ops->get_optimum_mode && 6968f4490e0SBjorn Andersson !rdev->desc->ops->set_load) 6978460ef38SBjorn Andersson return 0; 6988460ef38SBjorn Andersson 6998f4490e0SBjorn Andersson if (!rdev->desc->ops->set_mode && 7008f4490e0SBjorn Andersson !rdev->desc->ops->set_load) 7018460ef38SBjorn Andersson return -EINVAL; 702414c70cbSLiam Girdwood 70357776617SJoonwoo Park /* calc total requested load */ 70457776617SJoonwoo Park list_for_each_entry(sibling, &rdev->consumer_list, list) 70557776617SJoonwoo Park current_uA += sibling->uA_load; 70657776617SJoonwoo Park 70757776617SJoonwoo Park current_uA += rdev->constraints->system_load; 70857776617SJoonwoo Park 70957776617SJoonwoo Park if (rdev->desc->ops->set_load) { 71057776617SJoonwoo Park /* set the optimum mode for our new total regulator load */ 71157776617SJoonwoo Park err = rdev->desc->ops->set_load(rdev, current_uA); 71257776617SJoonwoo Park if (err < 0) 71357776617SJoonwoo Park rdev_err(rdev, "failed to set load %d\n", current_uA); 71457776617SJoonwoo Park } else { 715414c70cbSLiam Girdwood /* get output voltage */ 7161bf5a1f8SMark Brown output_uV = _regulator_get_voltage(rdev); 7178460ef38SBjorn Andersson if (output_uV <= 0) { 7188460ef38SBjorn Andersson rdev_err(rdev, "invalid output voltage found\n"); 7198460ef38SBjorn Andersson return -EINVAL; 7208460ef38SBjorn Andersson } 721414c70cbSLiam Girdwood 722414c70cbSLiam Girdwood /* get input voltage */ 7231bf5a1f8SMark Brown input_uV = 0; 7241bf5a1f8SMark Brown if (rdev->supply) 7253f24f5adSAxel Lin input_uV = regulator_get_voltage(rdev->supply); 7261bf5a1f8SMark Brown if (input_uV <= 0) 727414c70cbSLiam Girdwood input_uV = rdev->constraints->input_uV; 7288460ef38SBjorn Andersson if (input_uV <= 0) { 7298460ef38SBjorn Andersson rdev_err(rdev, "invalid input voltage found\n"); 7308460ef38SBjorn Andersson return -EINVAL; 7318460ef38SBjorn Andersson } 732414c70cbSLiam Girdwood 733414c70cbSLiam Girdwood /* now get the optimum mode for our new total regulator load */ 734414c70cbSLiam Girdwood mode = rdev->desc->ops->get_optimum_mode(rdev, input_uV, 735414c70cbSLiam Girdwood output_uV, current_uA); 736414c70cbSLiam Girdwood 737414c70cbSLiam Girdwood /* check the new mode is allowed */ 7382c608234SMark Brown err = regulator_mode_constrain(rdev, &mode); 7398460ef38SBjorn Andersson if (err < 0) { 7408460ef38SBjorn Andersson rdev_err(rdev, "failed to get optimum mode @ %d uA %d -> %d uV\n", 7418460ef38SBjorn Andersson current_uA, input_uV, output_uV); 7428460ef38SBjorn Andersson return err; 7438460ef38SBjorn Andersson } 7448460ef38SBjorn Andersson 7458460ef38SBjorn Andersson err = rdev->desc->ops->set_mode(rdev, mode); 7468460ef38SBjorn Andersson if (err < 0) 7478460ef38SBjorn Andersson rdev_err(rdev, "failed to set optimum mode %x\n", mode); 7488f4490e0SBjorn Andersson } 7498460ef38SBjorn Andersson 7508460ef38SBjorn Andersson return err; 751414c70cbSLiam Girdwood } 752414c70cbSLiam Girdwood 753414c70cbSLiam Girdwood static int suspend_set_state(struct regulator_dev *rdev, 754f7efad10SChunyan Zhang suspend_state_t state) 755414c70cbSLiam Girdwood { 756414c70cbSLiam Girdwood int ret = 0; 757f7efad10SChunyan Zhang struct regulator_state *rstate; 758f7efad10SChunyan Zhang 759f7efad10SChunyan Zhang rstate = regulator_get_suspend_state(rdev, state); 760f7efad10SChunyan Zhang if (rstate == NULL) 76157a0dd18SMark Brown return 0; 762638f85c5SMark Brown 763638f85c5SMark Brown /* If we have no suspend mode configration don't set anything; 7648ac0e95dSAxel Lin * only warn if the driver implements set_suspend_voltage or 7658ac0e95dSAxel Lin * set_suspend_mode callback. 766638f85c5SMark Brown */ 76772069f99SChunyan Zhang if (rstate->enabled != ENABLE_IN_SUSPEND && 76872069f99SChunyan Zhang rstate->enabled != DISABLE_IN_SUSPEND) { 7698ac0e95dSAxel Lin if (rdev->desc->ops->set_suspend_voltage || 7708ac0e95dSAxel Lin rdev->desc->ops->set_suspend_mode) 7715da84fd9SJoe Perches rdev_warn(rdev, "No configuration\n"); 772638f85c5SMark Brown return 0; 773638f85c5SMark Brown } 774638f85c5SMark Brown 77572069f99SChunyan Zhang if (rstate->enabled == ENABLE_IN_SUSPEND && 77672069f99SChunyan Zhang rdev->desc->ops->set_suspend_enable) 777414c70cbSLiam Girdwood ret = rdev->desc->ops->set_suspend_enable(rdev); 77872069f99SChunyan Zhang else if (rstate->enabled == DISABLE_IN_SUSPEND && 77972069f99SChunyan Zhang rdev->desc->ops->set_suspend_disable) 780414c70cbSLiam Girdwood ret = rdev->desc->ops->set_suspend_disable(rdev); 7818ac0e95dSAxel Lin else /* OK if set_suspend_enable or set_suspend_disable is NULL */ 7828ac0e95dSAxel Lin ret = 0; 7838ac0e95dSAxel Lin 784414c70cbSLiam Girdwood if (ret < 0) { 7855da84fd9SJoe Perches rdev_err(rdev, "failed to enabled/disable\n"); 786414c70cbSLiam Girdwood return ret; 787414c70cbSLiam Girdwood } 788414c70cbSLiam Girdwood 789414c70cbSLiam Girdwood if (rdev->desc->ops->set_suspend_voltage && rstate->uV > 0) { 790414c70cbSLiam Girdwood ret = rdev->desc->ops->set_suspend_voltage(rdev, rstate->uV); 791414c70cbSLiam Girdwood if (ret < 0) { 7925da84fd9SJoe Perches rdev_err(rdev, "failed to set voltage\n"); 793414c70cbSLiam Girdwood return ret; 794414c70cbSLiam Girdwood } 795414c70cbSLiam Girdwood } 796414c70cbSLiam Girdwood 797414c70cbSLiam Girdwood if (rdev->desc->ops->set_suspend_mode && rstate->mode > 0) { 798414c70cbSLiam Girdwood ret = rdev->desc->ops->set_suspend_mode(rdev, rstate->mode); 799414c70cbSLiam Girdwood if (ret < 0) { 8005da84fd9SJoe Perches rdev_err(rdev, "failed to set mode\n"); 801414c70cbSLiam Girdwood return ret; 802414c70cbSLiam Girdwood } 803414c70cbSLiam Girdwood } 804f7efad10SChunyan Zhang 805414c70cbSLiam Girdwood return ret; 806414c70cbSLiam Girdwood } 807414c70cbSLiam Girdwood 808414c70cbSLiam Girdwood static void print_constraints(struct regulator_dev *rdev) 809414c70cbSLiam Girdwood { 810414c70cbSLiam Girdwood struct regulation_constraints *constraints = rdev->constraints; 811a7068e39SStefan Wahren char buf[160] = ""; 8125751a99fSStefan Wahren size_t len = sizeof(buf) - 1; 8138f031b48SMark Brown int count = 0; 8148f031b48SMark Brown int ret; 815414c70cbSLiam Girdwood 8168f031b48SMark Brown if (constraints->min_uV && constraints->max_uV) { 817414c70cbSLiam Girdwood if (constraints->min_uV == constraints->max_uV) 8185751a99fSStefan Wahren count += scnprintf(buf + count, len - count, "%d mV ", 819414c70cbSLiam Girdwood constraints->min_uV / 1000); 820414c70cbSLiam Girdwood else 8215751a99fSStefan Wahren count += scnprintf(buf + count, len - count, 8225751a99fSStefan Wahren "%d <--> %d mV ", 823414c70cbSLiam Girdwood constraints->min_uV / 1000, 824414c70cbSLiam Girdwood constraints->max_uV / 1000); 8258f031b48SMark Brown } 8268f031b48SMark Brown 8278f031b48SMark Brown if (!constraints->min_uV || 8288f031b48SMark Brown constraints->min_uV != constraints->max_uV) { 8298f031b48SMark Brown ret = _regulator_get_voltage(rdev); 8308f031b48SMark Brown if (ret > 0) 8315751a99fSStefan Wahren count += scnprintf(buf + count, len - count, 8325751a99fSStefan Wahren "at %d mV ", ret / 1000); 8338f031b48SMark Brown } 8348f031b48SMark Brown 835bf5892a8SMark Brown if (constraints->uV_offset) 8365751a99fSStefan Wahren count += scnprintf(buf + count, len - count, "%dmV offset ", 837bf5892a8SMark Brown constraints->uV_offset / 1000); 838bf5892a8SMark Brown 8398f031b48SMark Brown if (constraints->min_uA && constraints->max_uA) { 840414c70cbSLiam Girdwood if (constraints->min_uA == constraints->max_uA) 8415751a99fSStefan Wahren count += scnprintf(buf + count, len - count, "%d mA ", 842414c70cbSLiam Girdwood constraints->min_uA / 1000); 843414c70cbSLiam Girdwood else 8445751a99fSStefan Wahren count += scnprintf(buf + count, len - count, 8455751a99fSStefan Wahren "%d <--> %d mA ", 846414c70cbSLiam Girdwood constraints->min_uA / 1000, 847414c70cbSLiam Girdwood constraints->max_uA / 1000); 848414c70cbSLiam Girdwood } 8498f031b48SMark Brown 8508f031b48SMark Brown if (!constraints->min_uA || 8518f031b48SMark Brown constraints->min_uA != constraints->max_uA) { 8528f031b48SMark Brown ret = _regulator_get_current_limit(rdev); 8538f031b48SMark Brown if (ret > 0) 8545751a99fSStefan Wahren count += scnprintf(buf + count, len - count, 8555751a99fSStefan Wahren "at %d mA ", ret / 1000); 8568f031b48SMark Brown } 8578f031b48SMark Brown 858414c70cbSLiam Girdwood if (constraints->valid_modes_mask & REGULATOR_MODE_FAST) 8595751a99fSStefan Wahren count += scnprintf(buf + count, len - count, "fast "); 860414c70cbSLiam Girdwood if (constraints->valid_modes_mask & REGULATOR_MODE_NORMAL) 8615751a99fSStefan Wahren count += scnprintf(buf + count, len - count, "normal "); 862414c70cbSLiam Girdwood if (constraints->valid_modes_mask & REGULATOR_MODE_IDLE) 8635751a99fSStefan Wahren count += scnprintf(buf + count, len - count, "idle "); 864414c70cbSLiam Girdwood if (constraints->valid_modes_mask & REGULATOR_MODE_STANDBY) 8655751a99fSStefan Wahren count += scnprintf(buf + count, len - count, "standby"); 866414c70cbSLiam Girdwood 867215b8b05SUwe Kleine-König if (!count) 8685751a99fSStefan Wahren scnprintf(buf, len, "no parameters"); 869215b8b05SUwe Kleine-König 870194dbaefSMark Brown rdev_dbg(rdev, "%s\n", buf); 8714a682922SMark Brown 8724a682922SMark Brown if ((constraints->min_uV != constraints->max_uV) && 8738a34e979SWEN Pingbo !regulator_ops_is_valid(rdev, REGULATOR_CHANGE_VOLTAGE)) 8744a682922SMark Brown rdev_warn(rdev, 8754a682922SMark Brown "Voltage range but no REGULATOR_CHANGE_VOLTAGE\n"); 876414c70cbSLiam Girdwood } 877414c70cbSLiam Girdwood 878e79055d6SMark Brown static int machine_constraints_voltage(struct regulator_dev *rdev, 8791083c393SMark Brown struct regulation_constraints *constraints) 880e79055d6SMark Brown { 881272e2315SGuodong Xu const struct regulator_ops *ops = rdev->desc->ops; 882af5866c9SMark Brown int ret; 883af5866c9SMark Brown 884af5866c9SMark Brown /* do we need to apply the constraint voltage */ 885af5866c9SMark Brown if (rdev->constraints->apply_uV && 886fa93fd4eSMark Brown rdev->constraints->min_uV && rdev->constraints->max_uV) { 887fa93fd4eSMark Brown int target_min, target_max; 888064d5cd1SAlban Bedel int current_uV = _regulator_get_voltage(rdev); 889064d5cd1SAlban Bedel if (current_uV < 0) { 89069d58839SNishanth Menon rdev_err(rdev, 89169d58839SNishanth Menon "failed to get the current voltage(%d)\n", 89269d58839SNishanth Menon current_uV); 893064d5cd1SAlban Bedel return current_uV; 894064d5cd1SAlban Bedel } 895fa93fd4eSMark Brown 896fa93fd4eSMark Brown /* 897fa93fd4eSMark Brown * If we're below the minimum voltage move up to the 898fa93fd4eSMark Brown * minimum voltage, if we're above the maximum voltage 899fa93fd4eSMark Brown * then move down to the maximum. 900fa93fd4eSMark Brown */ 901fa93fd4eSMark Brown target_min = current_uV; 902fa93fd4eSMark Brown target_max = current_uV; 903fa93fd4eSMark Brown 904fa93fd4eSMark Brown if (current_uV < rdev->constraints->min_uV) { 905fa93fd4eSMark Brown target_min = rdev->constraints->min_uV; 906fa93fd4eSMark Brown target_max = rdev->constraints->min_uV; 907fa93fd4eSMark Brown } 908fa93fd4eSMark Brown 909fa93fd4eSMark Brown if (current_uV > rdev->constraints->max_uV) { 910fa93fd4eSMark Brown target_min = rdev->constraints->max_uV; 911fa93fd4eSMark Brown target_max = rdev->constraints->max_uV; 912fa93fd4eSMark Brown } 913fa93fd4eSMark Brown 914fa93fd4eSMark Brown if (target_min != current_uV || target_max != current_uV) { 91545a91e8fSMark Brown rdev_info(rdev, "Bringing %duV into %d-%duV\n", 91645a91e8fSMark Brown current_uV, target_min, target_max); 917064d5cd1SAlban Bedel ret = _regulator_do_set_voltage( 918fa93fd4eSMark Brown rdev, target_min, target_max); 919af5866c9SMark Brown if (ret < 0) { 920064d5cd1SAlban Bedel rdev_err(rdev, 921fa93fd4eSMark Brown "failed to apply %d-%duV constraint(%d)\n", 922fa93fd4eSMark Brown target_min, target_max, ret); 923af5866c9SMark Brown return ret; 924af5866c9SMark Brown } 925af5866c9SMark Brown } 926064d5cd1SAlban Bedel } 927e79055d6SMark Brown 928e79055d6SMark Brown /* constrain machine-level voltage specs to fit 929e79055d6SMark Brown * the actual range supported by this regulator. 930e79055d6SMark Brown */ 931e79055d6SMark Brown if (ops->list_voltage && rdev->desc->n_voltages) { 932e79055d6SMark Brown int count = rdev->desc->n_voltages; 933e79055d6SMark Brown int i; 934e79055d6SMark Brown int min_uV = INT_MAX; 935e79055d6SMark Brown int max_uV = INT_MIN; 936e79055d6SMark Brown int cmin = constraints->min_uV; 937e79055d6SMark Brown int cmax = constraints->max_uV; 938e79055d6SMark Brown 939e79055d6SMark Brown /* it's safe to autoconfigure fixed-voltage supplies 940e79055d6SMark Brown and the constraints are used by list_voltage. */ 941e79055d6SMark Brown if (count == 1 && !cmin) { 942e79055d6SMark Brown cmin = 1; 943e79055d6SMark Brown cmax = INT_MAX; 944e79055d6SMark Brown constraints->min_uV = cmin; 945e79055d6SMark Brown constraints->max_uV = cmax; 946e79055d6SMark Brown } 947e79055d6SMark Brown 948e79055d6SMark Brown /* voltage constraints are optional */ 949e79055d6SMark Brown if ((cmin == 0) && (cmax == 0)) 950e79055d6SMark Brown return 0; 951e79055d6SMark Brown 952e79055d6SMark Brown /* else require explicit machine-level constraints */ 953e79055d6SMark Brown if (cmin <= 0 || cmax <= 0 || cmax < cmin) { 9545da84fd9SJoe Perches rdev_err(rdev, "invalid voltage constraints\n"); 955e79055d6SMark Brown return -EINVAL; 956e79055d6SMark Brown } 957e79055d6SMark Brown 958e79055d6SMark Brown /* initial: [cmin..cmax] valid, [min_uV..max_uV] not */ 959e79055d6SMark Brown for (i = 0; i < count; i++) { 960e79055d6SMark Brown int value; 961e79055d6SMark Brown 962e79055d6SMark Brown value = ops->list_voltage(rdev, i); 963e79055d6SMark Brown if (value <= 0) 964e79055d6SMark Brown continue; 965e79055d6SMark Brown 966e79055d6SMark Brown /* maybe adjust [min_uV..max_uV] */ 967e79055d6SMark Brown if (value >= cmin && value < min_uV) 968e79055d6SMark Brown min_uV = value; 969e79055d6SMark Brown if (value <= cmax && value > max_uV) 970e79055d6SMark Brown max_uV = value; 971e79055d6SMark Brown } 972e79055d6SMark Brown 973e79055d6SMark Brown /* final: [min_uV..max_uV] valid iff constraints valid */ 974e79055d6SMark Brown if (max_uV < min_uV) { 975fff15befSMark Brown rdev_err(rdev, 976fff15befSMark Brown "unsupportable voltage constraints %u-%uuV\n", 977fff15befSMark Brown min_uV, max_uV); 978e79055d6SMark Brown return -EINVAL; 979e79055d6SMark Brown } 980e79055d6SMark Brown 981e79055d6SMark Brown /* use regulator's subset of machine constraints */ 982e79055d6SMark Brown if (constraints->min_uV < min_uV) { 9835da84fd9SJoe Perches rdev_dbg(rdev, "override min_uV, %d -> %d\n", 9845da84fd9SJoe Perches constraints->min_uV, min_uV); 985e79055d6SMark Brown constraints->min_uV = min_uV; 986e79055d6SMark Brown } 987e79055d6SMark Brown if (constraints->max_uV > max_uV) { 9885da84fd9SJoe Perches rdev_dbg(rdev, "override max_uV, %d -> %d\n", 9895da84fd9SJoe Perches constraints->max_uV, max_uV); 990e79055d6SMark Brown constraints->max_uV = max_uV; 991e79055d6SMark Brown } 992e79055d6SMark Brown } 993e79055d6SMark Brown 994e79055d6SMark Brown return 0; 995e79055d6SMark Brown } 996e79055d6SMark Brown 997f8c1700dSLaxman Dewangan static int machine_constraints_current(struct regulator_dev *rdev, 998f8c1700dSLaxman Dewangan struct regulation_constraints *constraints) 999f8c1700dSLaxman Dewangan { 1000272e2315SGuodong Xu const struct regulator_ops *ops = rdev->desc->ops; 1001f8c1700dSLaxman Dewangan int ret; 1002f8c1700dSLaxman Dewangan 1003f8c1700dSLaxman Dewangan if (!constraints->min_uA && !constraints->max_uA) 1004f8c1700dSLaxman Dewangan return 0; 1005f8c1700dSLaxman Dewangan 1006f8c1700dSLaxman Dewangan if (constraints->min_uA > constraints->max_uA) { 1007f8c1700dSLaxman Dewangan rdev_err(rdev, "Invalid current constraints\n"); 1008f8c1700dSLaxman Dewangan return -EINVAL; 1009f8c1700dSLaxman Dewangan } 1010f8c1700dSLaxman Dewangan 1011f8c1700dSLaxman Dewangan if (!ops->set_current_limit || !ops->get_current_limit) { 1012f8c1700dSLaxman Dewangan rdev_warn(rdev, "Operation of current configuration missing\n"); 1013f8c1700dSLaxman Dewangan return 0; 1014f8c1700dSLaxman Dewangan } 1015f8c1700dSLaxman Dewangan 1016f8c1700dSLaxman Dewangan /* Set regulator current in constraints range */ 1017f8c1700dSLaxman Dewangan ret = ops->set_current_limit(rdev, constraints->min_uA, 1018f8c1700dSLaxman Dewangan constraints->max_uA); 1019f8c1700dSLaxman Dewangan if (ret < 0) { 1020f8c1700dSLaxman Dewangan rdev_err(rdev, "Failed to set current constraint, %d\n", ret); 1021f8c1700dSLaxman Dewangan return ret; 1022f8c1700dSLaxman Dewangan } 1023f8c1700dSLaxman Dewangan 1024f8c1700dSLaxman Dewangan return 0; 1025f8c1700dSLaxman Dewangan } 1026f8c1700dSLaxman Dewangan 102730c21971SMarkus Pargmann static int _regulator_do_enable(struct regulator_dev *rdev); 102830c21971SMarkus Pargmann 1029a5766f11SLiam Girdwood /** 1030a5766f11SLiam Girdwood * set_machine_constraints - sets regulator constraints 103169279fb9SMark Brown * @rdev: regulator source 1032c8e7e464SMark Brown * @constraints: constraints to apply 1033a5766f11SLiam Girdwood * 1034a5766f11SLiam Girdwood * Allows platform initialisation code to define and constrain 1035a5766f11SLiam Girdwood * regulator circuits e.g. valid voltage/current ranges, etc. NOTE: 1036a5766f11SLiam Girdwood * Constraints *must* be set by platform code in order for some 1037a5766f11SLiam Girdwood * regulator operations to proceed i.e. set_voltage, set_current_limit, 1038a5766f11SLiam Girdwood * set_mode. 1039a5766f11SLiam Girdwood */ 1040a5766f11SLiam Girdwood static int set_machine_constraints(struct regulator_dev *rdev, 1041f8c12fe3SMark Brown const struct regulation_constraints *constraints) 1042a5766f11SLiam Girdwood { 1043a5766f11SLiam Girdwood int ret = 0; 1044272e2315SGuodong Xu const struct regulator_ops *ops = rdev->desc->ops; 1045e06f5b4fSMark Brown 10469a8f5e07SMark Brown if (constraints) 1047f8c12fe3SMark Brown rdev->constraints = kmemdup(constraints, sizeof(*constraints), 1048f8c12fe3SMark Brown GFP_KERNEL); 10499a8f5e07SMark Brown else 10509a8f5e07SMark Brown rdev->constraints = kzalloc(sizeof(*constraints), 10519a8f5e07SMark Brown GFP_KERNEL); 1052f8c12fe3SMark Brown if (!rdev->constraints) 1053f8c12fe3SMark Brown return -ENOMEM; 1054af5866c9SMark Brown 1055f8c12fe3SMark Brown ret = machine_constraints_voltage(rdev, rdev->constraints); 1056e79055d6SMark Brown if (ret != 0) 10576333ef46SCharles Keepax return ret; 10583e2b9abdSMark Brown 1059f8c1700dSLaxman Dewangan ret = machine_constraints_current(rdev, rdev->constraints); 1060f8c1700dSLaxman Dewangan if (ret != 0) 10616333ef46SCharles Keepax return ret; 1062f8c1700dSLaxman Dewangan 106336e4f839SStephen Boyd if (rdev->constraints->ilim_uA && ops->set_input_current_limit) { 106436e4f839SStephen Boyd ret = ops->set_input_current_limit(rdev, 106536e4f839SStephen Boyd rdev->constraints->ilim_uA); 106636e4f839SStephen Boyd if (ret < 0) { 106736e4f839SStephen Boyd rdev_err(rdev, "failed to set input limit\n"); 10686333ef46SCharles Keepax return ret; 106936e4f839SStephen Boyd } 107036e4f839SStephen Boyd } 107136e4f839SStephen Boyd 1072a5766f11SLiam Girdwood /* do we need to setup our suspend state */ 10739a8f5e07SMark Brown if (rdev->constraints->initial_state) { 1074f7efad10SChunyan Zhang ret = suspend_set_state(rdev, rdev->constraints->initial_state); 1075e06f5b4fSMark Brown if (ret < 0) { 10765da84fd9SJoe Perches rdev_err(rdev, "failed to set suspend state\n"); 10776333ef46SCharles Keepax return ret; 1078e06f5b4fSMark Brown } 1079e06f5b4fSMark Brown } 1080a5766f11SLiam Girdwood 10819a8f5e07SMark Brown if (rdev->constraints->initial_mode) { 1082a308466cSMark Brown if (!ops->set_mode) { 10835da84fd9SJoe Perches rdev_err(rdev, "no set_mode operation\n"); 10846333ef46SCharles Keepax return -EINVAL; 1085a308466cSMark Brown } 1086a308466cSMark Brown 1087f8c12fe3SMark Brown ret = ops->set_mode(rdev, rdev->constraints->initial_mode); 1088a308466cSMark Brown if (ret < 0) { 10895da84fd9SJoe Perches rdev_err(rdev, "failed to set initial mode: %d\n", ret); 10906333ef46SCharles Keepax return ret; 1091a308466cSMark Brown } 1092a308466cSMark Brown } 1093a308466cSMark Brown 1094cacf90f2SMark Brown /* If the constraints say the regulator should be on at this point 1095cacf90f2SMark Brown * and we have control then make sure it is enabled. 1096cacf90f2SMark Brown */ 109730c21971SMarkus Pargmann if (rdev->constraints->always_on || rdev->constraints->boot_on) { 109830c21971SMarkus Pargmann ret = _regulator_do_enable(rdev); 109930c21971SMarkus Pargmann if (ret < 0 && ret != -EINVAL) { 11005da84fd9SJoe Perches rdev_err(rdev, "failed to enable\n"); 11016333ef46SCharles Keepax return ret; 1102e5fda26cSMark Brown } 1103e5fda26cSMark Brown } 1104e5fda26cSMark Brown 11051653ccf4SYadwinder Singh Brar if ((rdev->constraints->ramp_delay || rdev->constraints->ramp_disable) 11061653ccf4SYadwinder Singh Brar && ops->set_ramp_delay) { 11076f0b2c69SYadwinder Singh Brar ret = ops->set_ramp_delay(rdev, rdev->constraints->ramp_delay); 11086f0b2c69SYadwinder Singh Brar if (ret < 0) { 11096f0b2c69SYadwinder Singh Brar rdev_err(rdev, "failed to set ramp_delay\n"); 11106333ef46SCharles Keepax return ret; 11116f0b2c69SYadwinder Singh Brar } 11126f0b2c69SYadwinder Singh Brar } 11136f0b2c69SYadwinder Singh Brar 111423c779b9SStephen Boyd if (rdev->constraints->pull_down && ops->set_pull_down) { 111523c779b9SStephen Boyd ret = ops->set_pull_down(rdev); 111623c779b9SStephen Boyd if (ret < 0) { 111723c779b9SStephen Boyd rdev_err(rdev, "failed to set pull down\n"); 11186333ef46SCharles Keepax return ret; 111923c779b9SStephen Boyd } 112023c779b9SStephen Boyd } 112123c779b9SStephen Boyd 112257f66b78SStephen Boyd if (rdev->constraints->soft_start && ops->set_soft_start) { 112357f66b78SStephen Boyd ret = ops->set_soft_start(rdev); 112457f66b78SStephen Boyd if (ret < 0) { 112557f66b78SStephen Boyd rdev_err(rdev, "failed to set soft start\n"); 11266333ef46SCharles Keepax return ret; 112757f66b78SStephen Boyd } 112857f66b78SStephen Boyd } 112957f66b78SStephen Boyd 11303a003baeSStephen Boyd if (rdev->constraints->over_current_protection 11313a003baeSStephen Boyd && ops->set_over_current_protection) { 11323a003baeSStephen Boyd ret = ops->set_over_current_protection(rdev); 11333a003baeSStephen Boyd if (ret < 0) { 11343a003baeSStephen Boyd rdev_err(rdev, "failed to set over current protection\n"); 11356333ef46SCharles Keepax return ret; 11363a003baeSStephen Boyd } 11373a003baeSStephen Boyd } 11383a003baeSStephen Boyd 1139670666b9SLaxman Dewangan if (rdev->constraints->active_discharge && ops->set_active_discharge) { 1140670666b9SLaxman Dewangan bool ad_state = (rdev->constraints->active_discharge == 1141670666b9SLaxman Dewangan REGULATOR_ACTIVE_DISCHARGE_ENABLE) ? true : false; 1142670666b9SLaxman Dewangan 1143670666b9SLaxman Dewangan ret = ops->set_active_discharge(rdev, ad_state); 1144670666b9SLaxman Dewangan if (ret < 0) { 1145670666b9SLaxman Dewangan rdev_err(rdev, "failed to set active discharge\n"); 1146670666b9SLaxman Dewangan return ret; 1147670666b9SLaxman Dewangan } 1148670666b9SLaxman Dewangan } 1149670666b9SLaxman Dewangan 1150a5766f11SLiam Girdwood print_constraints(rdev); 11511a6958e7SAxel Lin return 0; 1152a5766f11SLiam Girdwood } 1153a5766f11SLiam Girdwood 1154a5766f11SLiam Girdwood /** 1155a5766f11SLiam Girdwood * set_supply - set regulator supply regulator 115669279fb9SMark Brown * @rdev: regulator name 115769279fb9SMark Brown * @supply_rdev: supply regulator name 1158a5766f11SLiam Girdwood * 1159a5766f11SLiam Girdwood * Called by platform initialisation code to set the supply regulator for this 1160a5766f11SLiam Girdwood * regulator. This ensures that a regulators supply will also be enabled by the 1161a5766f11SLiam Girdwood * core if it's child is enabled. 1162a5766f11SLiam Girdwood */ 1163a5766f11SLiam Girdwood static int set_supply(struct regulator_dev *rdev, 1164a5766f11SLiam Girdwood struct regulator_dev *supply_rdev) 1165a5766f11SLiam Girdwood { 1166a5766f11SLiam Girdwood int err; 1167a5766f11SLiam Girdwood 11683801b86aSMark Brown rdev_info(rdev, "supplied by %s\n", rdev_get_name(supply_rdev)); 11693801b86aSMark Brown 1170e2c09ae7SJavier Martinez Canillas if (!try_module_get(supply_rdev->owner)) 1171e2c09ae7SJavier Martinez Canillas return -ENODEV; 1172e2c09ae7SJavier Martinez Canillas 11733801b86aSMark Brown rdev->supply = create_regulator(supply_rdev, &rdev->dev, "SUPPLY"); 117432c78de8SAxel Lin if (rdev->supply == NULL) { 117532c78de8SAxel Lin err = -ENOMEM; 1176a5766f11SLiam Girdwood return err; 1177a5766f11SLiam Girdwood } 117857ad526aSLaxman Dewangan supply_rdev->open_count++; 1179a5766f11SLiam Girdwood 11803801b86aSMark Brown return 0; 11813801b86aSMark Brown } 11823801b86aSMark Brown 1183a5766f11SLiam Girdwood /** 118406c63f93SRandy Dunlap * set_consumer_device_supply - Bind a regulator to a symbolic supply 118569279fb9SMark Brown * @rdev: regulator source 118640f9244fSMark Brown * @consumer_dev_name: dev_name() string for device supply applies to 1187a5766f11SLiam Girdwood * @supply: symbolic name for supply 1188a5766f11SLiam Girdwood * 1189a5766f11SLiam Girdwood * Allows platform initialisation code to map physical regulator 1190a5766f11SLiam Girdwood * sources to symbolic names for supplies for use by devices. Devices 1191a5766f11SLiam Girdwood * should use these symbolic names to request regulators, avoiding the 1192a5766f11SLiam Girdwood * need to provide board-specific regulator names as platform data. 1193a5766f11SLiam Girdwood */ 1194a5766f11SLiam Girdwood static int set_consumer_device_supply(struct regulator_dev *rdev, 1195737f360dSMark Brown const char *consumer_dev_name, 119640f9244fSMark Brown const char *supply) 1197a5766f11SLiam Girdwood { 1198a5766f11SLiam Girdwood struct regulator_map *node; 11999ed2099eSMark Brown int has_dev; 1200a5766f11SLiam Girdwood 1201a5766f11SLiam Girdwood if (supply == NULL) 1202a5766f11SLiam Girdwood return -EINVAL; 1203a5766f11SLiam Girdwood 12049ed2099eSMark Brown if (consumer_dev_name != NULL) 12059ed2099eSMark Brown has_dev = 1; 12069ed2099eSMark Brown else 12079ed2099eSMark Brown has_dev = 0; 12089ed2099eSMark Brown 12096001e13cSDavid Brownell list_for_each_entry(node, ®ulator_map_list, list) { 121023b5cc2aSJani Nikula if (node->dev_name && consumer_dev_name) { 121123b5cc2aSJani Nikula if (strcmp(node->dev_name, consumer_dev_name) != 0) 12126001e13cSDavid Brownell continue; 121323b5cc2aSJani Nikula } else if (node->dev_name || consumer_dev_name) { 121423b5cc2aSJani Nikula continue; 121523b5cc2aSJani Nikula } 121623b5cc2aSJani Nikula 12176001e13cSDavid Brownell if (strcmp(node->supply, supply) != 0) 12186001e13cSDavid Brownell continue; 12196001e13cSDavid Brownell 1220737f360dSMark Brown pr_debug("%s: %s/%s is '%s' supply; fail %s/%s\n", 1221737f360dSMark Brown consumer_dev_name, 12226001e13cSDavid Brownell dev_name(&node->regulator->dev), 12236001e13cSDavid Brownell node->regulator->desc->name, 12246001e13cSDavid Brownell supply, 12251083c393SMark Brown dev_name(&rdev->dev), rdev_get_name(rdev)); 12266001e13cSDavid Brownell return -EBUSY; 12276001e13cSDavid Brownell } 12286001e13cSDavid Brownell 12299ed2099eSMark Brown node = kzalloc(sizeof(struct regulator_map), GFP_KERNEL); 1230a5766f11SLiam Girdwood if (node == NULL) 1231a5766f11SLiam Girdwood return -ENOMEM; 1232a5766f11SLiam Girdwood 1233a5766f11SLiam Girdwood node->regulator = rdev; 1234a5766f11SLiam Girdwood node->supply = supply; 1235a5766f11SLiam Girdwood 12369ed2099eSMark Brown if (has_dev) { 12379ed2099eSMark Brown node->dev_name = kstrdup(consumer_dev_name, GFP_KERNEL); 123840f9244fSMark Brown if (node->dev_name == NULL) { 123940f9244fSMark Brown kfree(node); 124040f9244fSMark Brown return -ENOMEM; 124140f9244fSMark Brown } 12429ed2099eSMark Brown } 124340f9244fSMark Brown 1244a5766f11SLiam Girdwood list_add(&node->list, ®ulator_map_list); 1245a5766f11SLiam Girdwood return 0; 1246a5766f11SLiam Girdwood } 1247a5766f11SLiam Girdwood 12480f1d747bSMike Rapoport static void unset_regulator_supplies(struct regulator_dev *rdev) 12490f1d747bSMike Rapoport { 12500f1d747bSMike Rapoport struct regulator_map *node, *n; 12510f1d747bSMike Rapoport 12520f1d747bSMike Rapoport list_for_each_entry_safe(node, n, ®ulator_map_list, list) { 12530f1d747bSMike Rapoport if (rdev == node->regulator) { 12540f1d747bSMike Rapoport list_del(&node->list); 125540f9244fSMark Brown kfree(node->dev_name); 12560f1d747bSMike Rapoport kfree(node); 12570f1d747bSMike Rapoport } 12580f1d747bSMike Rapoport } 12590f1d747bSMike Rapoport } 12600f1d747bSMike Rapoport 12612d80a91bSRichard Fitzgerald #ifdef CONFIG_DEBUG_FS 12622d80a91bSRichard Fitzgerald static ssize_t constraint_flags_read_file(struct file *file, 12632d80a91bSRichard Fitzgerald char __user *user_buf, 12642d80a91bSRichard Fitzgerald size_t count, loff_t *ppos) 12652d80a91bSRichard Fitzgerald { 12662d80a91bSRichard Fitzgerald const struct regulator *regulator = file->private_data; 12672d80a91bSRichard Fitzgerald const struct regulation_constraints *c = regulator->rdev->constraints; 12682d80a91bSRichard Fitzgerald char *buf; 12692d80a91bSRichard Fitzgerald ssize_t ret; 12702d80a91bSRichard Fitzgerald 12712d80a91bSRichard Fitzgerald if (!c) 12722d80a91bSRichard Fitzgerald return 0; 12732d80a91bSRichard Fitzgerald 12742d80a91bSRichard Fitzgerald buf = kmalloc(PAGE_SIZE, GFP_KERNEL); 12752d80a91bSRichard Fitzgerald if (!buf) 12762d80a91bSRichard Fitzgerald return -ENOMEM; 12772d80a91bSRichard Fitzgerald 12782d80a91bSRichard Fitzgerald ret = snprintf(buf, PAGE_SIZE, 12792d80a91bSRichard Fitzgerald "always_on: %u\n" 12802d80a91bSRichard Fitzgerald "boot_on: %u\n" 12812d80a91bSRichard Fitzgerald "apply_uV: %u\n" 12822d80a91bSRichard Fitzgerald "ramp_disable: %u\n" 12832d80a91bSRichard Fitzgerald "soft_start: %u\n" 12842d80a91bSRichard Fitzgerald "pull_down: %u\n" 12852d80a91bSRichard Fitzgerald "over_current_protection: %u\n", 12862d80a91bSRichard Fitzgerald c->always_on, 12872d80a91bSRichard Fitzgerald c->boot_on, 12882d80a91bSRichard Fitzgerald c->apply_uV, 12892d80a91bSRichard Fitzgerald c->ramp_disable, 12902d80a91bSRichard Fitzgerald c->soft_start, 12912d80a91bSRichard Fitzgerald c->pull_down, 12922d80a91bSRichard Fitzgerald c->over_current_protection); 12932d80a91bSRichard Fitzgerald 12942d80a91bSRichard Fitzgerald ret = simple_read_from_buffer(user_buf, count, ppos, buf, ret); 12952d80a91bSRichard Fitzgerald kfree(buf); 12962d80a91bSRichard Fitzgerald 12972d80a91bSRichard Fitzgerald return ret; 12982d80a91bSRichard Fitzgerald } 12992d80a91bSRichard Fitzgerald 13002d80a91bSRichard Fitzgerald #endif 13012d80a91bSRichard Fitzgerald 13022d80a91bSRichard Fitzgerald static const struct file_operations constraint_flags_fops = { 13032d80a91bSRichard Fitzgerald #ifdef CONFIG_DEBUG_FS 13042d80a91bSRichard Fitzgerald .open = simple_open, 13052d80a91bSRichard Fitzgerald .read = constraint_flags_read_file, 13062d80a91bSRichard Fitzgerald .llseek = default_llseek, 13072d80a91bSRichard Fitzgerald #endif 13082d80a91bSRichard Fitzgerald }; 13092d80a91bSRichard Fitzgerald 1310f5726ae3SMark Brown #define REG_STR_SIZE 64 1311414c70cbSLiam Girdwood 1312414c70cbSLiam Girdwood static struct regulator *create_regulator(struct regulator_dev *rdev, 1313414c70cbSLiam Girdwood struct device *dev, 1314414c70cbSLiam Girdwood const char *supply_name) 1315414c70cbSLiam Girdwood { 1316414c70cbSLiam Girdwood struct regulator *regulator; 1317414c70cbSLiam Girdwood char buf[REG_STR_SIZE]; 1318414c70cbSLiam Girdwood int err, size; 1319414c70cbSLiam Girdwood 1320414c70cbSLiam Girdwood regulator = kzalloc(sizeof(*regulator), GFP_KERNEL); 1321414c70cbSLiam Girdwood if (regulator == NULL) 1322414c70cbSLiam Girdwood return NULL; 1323414c70cbSLiam Girdwood 1324414c70cbSLiam Girdwood mutex_lock(&rdev->mutex); 1325414c70cbSLiam Girdwood regulator->rdev = rdev; 1326414c70cbSLiam Girdwood list_add(®ulator->list, &rdev->consumer_list); 1327414c70cbSLiam Girdwood 1328414c70cbSLiam Girdwood if (dev) { 1329e2c98eafSShawn Guo regulator->dev = dev; 1330e2c98eafSShawn Guo 1331222cc7b1SMark Brown /* Add a link to the device sysfs entry */ 1332b7cd1b13SBartosz Golaszewski size = snprintf(buf, REG_STR_SIZE, "%s-%s", 1333414c70cbSLiam Girdwood dev->kobj.name, supply_name); 1334414c70cbSLiam Girdwood if (size >= REG_STR_SIZE) 1335222cc7b1SMark Brown goto overflow_err; 1336414c70cbSLiam Girdwood 1337414c70cbSLiam Girdwood regulator->supply_name = kstrdup(buf, GFP_KERNEL); 1338414c70cbSLiam Girdwood if (regulator->supply_name == NULL) 1339222cc7b1SMark Brown goto overflow_err; 1340414c70cbSLiam Girdwood 1341ff268b56SStephen Boyd err = sysfs_create_link_nowarn(&rdev->dev.kobj, &dev->kobj, 1342414c70cbSLiam Girdwood buf); 1343414c70cbSLiam Girdwood if (err) { 1344ff268b56SStephen Boyd rdev_dbg(rdev, "could not add device link %s err %d\n", 13451d7372e1SDaniel Walker dev->kobj.name, err); 1346222cc7b1SMark Brown /* non-fatal */ 1347414c70cbSLiam Girdwood } 13485de70519SMark Brown } else { 13490630b614SStephen Boyd regulator->supply_name = kstrdup_const(supply_name, GFP_KERNEL); 13505de70519SMark Brown if (regulator->supply_name == NULL) 1351222cc7b1SMark Brown goto overflow_err; 1352414c70cbSLiam Girdwood } 13535de70519SMark Brown 13545de70519SMark Brown regulator->debugfs = debugfs_create_dir(regulator->supply_name, 13555de70519SMark Brown rdev->debugfs); 135624751434SStephen Boyd if (!regulator->debugfs) { 1357ad3a942bSStephen Boyd rdev_dbg(rdev, "Failed to create debugfs directory\n"); 13585de70519SMark Brown } else { 13595de70519SMark Brown debugfs_create_u32("uA_load", 0444, regulator->debugfs, 13605de70519SMark Brown ®ulator->uA_load); 13615de70519SMark Brown debugfs_create_u32("min_uV", 0444, regulator->debugfs, 1362c360a6dfSChunyan Zhang ®ulator->voltage[PM_SUSPEND_ON].min_uV); 13635de70519SMark Brown debugfs_create_u32("max_uV", 0444, regulator->debugfs, 1364c360a6dfSChunyan Zhang ®ulator->voltage[PM_SUSPEND_ON].max_uV); 13652d80a91bSRichard Fitzgerald debugfs_create_file("constraint_flags", 0444, 13662d80a91bSRichard Fitzgerald regulator->debugfs, regulator, 13672d80a91bSRichard Fitzgerald &constraint_flags_fops); 13685de70519SMark Brown } 13695de70519SMark Brown 13706492bc1bSMark Brown /* 13716492bc1bSMark Brown * Check now if the regulator is an always on regulator - if 13726492bc1bSMark Brown * it is then we don't need to do nearly so much work for 13736492bc1bSMark Brown * enable/disable calls. 13746492bc1bSMark Brown */ 13758a34e979SWEN Pingbo if (!regulator_ops_is_valid(rdev, REGULATOR_CHANGE_STATUS) && 13766492bc1bSMark Brown _regulator_is_enabled(rdev)) 13776492bc1bSMark Brown regulator->always_on = true; 13786492bc1bSMark Brown 1379414c70cbSLiam Girdwood mutex_unlock(&rdev->mutex); 1380414c70cbSLiam Girdwood return regulator; 1381414c70cbSLiam Girdwood overflow_err: 1382414c70cbSLiam Girdwood list_del(®ulator->list); 1383414c70cbSLiam Girdwood kfree(regulator); 1384414c70cbSLiam Girdwood mutex_unlock(&rdev->mutex); 1385414c70cbSLiam Girdwood return NULL; 1386414c70cbSLiam Girdwood } 1387414c70cbSLiam Girdwood 138831aae2beSMark Brown static int _regulator_get_enable_time(struct regulator_dev *rdev) 138931aae2beSMark Brown { 139000c877c6SLaxman Dewangan if (rdev->constraints && rdev->constraints->enable_time) 139100c877c6SLaxman Dewangan return rdev->constraints->enable_time; 139231aae2beSMark Brown if (!rdev->desc->ops->enable_time) 139379511ed3SMark Brown return rdev->desc->enable_time; 139431aae2beSMark Brown return rdev->desc->ops->enable_time(rdev); 139531aae2beSMark Brown } 139631aae2beSMark Brown 1397a06ccd9cSCharles Keepax static struct regulator_supply_alias *regulator_find_supply_alias( 1398a06ccd9cSCharles Keepax struct device *dev, const char *supply) 1399a06ccd9cSCharles Keepax { 1400a06ccd9cSCharles Keepax struct regulator_supply_alias *map; 1401a06ccd9cSCharles Keepax 1402a06ccd9cSCharles Keepax list_for_each_entry(map, ®ulator_supply_alias_list, list) 1403a06ccd9cSCharles Keepax if (map->src_dev == dev && strcmp(map->src_supply, supply) == 0) 1404a06ccd9cSCharles Keepax return map; 1405a06ccd9cSCharles Keepax 1406a06ccd9cSCharles Keepax return NULL; 1407a06ccd9cSCharles Keepax } 1408a06ccd9cSCharles Keepax 1409a06ccd9cSCharles Keepax static void regulator_supply_alias(struct device **dev, const char **supply) 1410a06ccd9cSCharles Keepax { 1411a06ccd9cSCharles Keepax struct regulator_supply_alias *map; 1412a06ccd9cSCharles Keepax 1413a06ccd9cSCharles Keepax map = regulator_find_supply_alias(*dev, *supply); 1414a06ccd9cSCharles Keepax if (map) { 1415a06ccd9cSCharles Keepax dev_dbg(*dev, "Mapping supply %s to %s,%s\n", 1416a06ccd9cSCharles Keepax *supply, map->alias_supply, 1417a06ccd9cSCharles Keepax dev_name(map->alias_dev)); 1418a06ccd9cSCharles Keepax *dev = map->alias_dev; 1419a06ccd9cSCharles Keepax *supply = map->alias_supply; 1420a06ccd9cSCharles Keepax } 1421a06ccd9cSCharles Keepax } 1422a06ccd9cSCharles Keepax 142385f3b431STomeu Vizoso static int regulator_match(struct device *dev, const void *data) 142485f3b431STomeu Vizoso { 142585f3b431STomeu Vizoso struct regulator_dev *r = dev_to_rdev(dev); 142685f3b431STomeu Vizoso 142785f3b431STomeu Vizoso return strcmp(rdev_get_name(r), data) == 0; 142885f3b431STomeu Vizoso } 142985f3b431STomeu Vizoso 143085f3b431STomeu Vizoso static struct regulator_dev *regulator_lookup_by_name(const char *name) 143185f3b431STomeu Vizoso { 143285f3b431STomeu Vizoso struct device *dev; 143385f3b431STomeu Vizoso 143485f3b431STomeu Vizoso dev = class_find_device(®ulator_class, NULL, name, regulator_match); 143585f3b431STomeu Vizoso 143685f3b431STomeu Vizoso return dev ? dev_to_rdev(dev) : NULL; 143785f3b431STomeu Vizoso } 143885f3b431STomeu Vizoso 143985f3b431STomeu Vizoso /** 144085f3b431STomeu Vizoso * regulator_dev_lookup - lookup a regulator device. 144185f3b431STomeu Vizoso * @dev: device for regulator "consumer". 144285f3b431STomeu Vizoso * @supply: Supply name or regulator ID. 144385f3b431STomeu Vizoso * 144485f3b431STomeu Vizoso * If successful, returns a struct regulator_dev that corresponds to the name 1445163478daSDmitry Torokhov * @supply and with the embedded struct device refcount incremented by one. 1446163478daSDmitry Torokhov * The refcount must be dropped by calling put_device(). 1447163478daSDmitry Torokhov * On failure one of the following ERR-PTR-encoded values is returned: 1448163478daSDmitry Torokhov * -ENODEV if lookup fails permanently, -EPROBE_DEFER if lookup could succeed 1449163478daSDmitry Torokhov * in the future. 145085f3b431STomeu Vizoso */ 145169511a45SRajendra Nayak static struct regulator_dev *regulator_dev_lookup(struct device *dev, 1452163478daSDmitry Torokhov const char *supply) 145369511a45SRajendra Nayak { 145406217197SCharles Keepax struct regulator_dev *r = NULL; 145569511a45SRajendra Nayak struct device_node *node; 1456576ca436SMark Brown struct regulator_map *map; 1457576ca436SMark Brown const char *devname = NULL; 145869511a45SRajendra Nayak 1459a06ccd9cSCharles Keepax regulator_supply_alias(&dev, &supply); 1460a06ccd9cSCharles Keepax 146169511a45SRajendra Nayak /* first do a dt based lookup */ 146269511a45SRajendra Nayak if (dev && dev->of_node) { 146369511a45SRajendra Nayak node = of_get_regulator(dev, supply); 14646d191a5fSMark Brown if (node) { 146585f3b431STomeu Vizoso r = of_find_regulator_by_node(node); 146685f3b431STomeu Vizoso if (r) 146769511a45SRajendra Nayak return r; 1468163478daSDmitry Torokhov 14696d191a5fSMark Brown /* 1470163478daSDmitry Torokhov * We have a node, but there is no device. 1471163478daSDmitry Torokhov * assume it has not registered yet. 14726d191a5fSMark Brown */ 1473163478daSDmitry Torokhov return ERR_PTR(-EPROBE_DEFER); 14746d191a5fSMark Brown } 147569511a45SRajendra Nayak } 147669511a45SRajendra Nayak 147769511a45SRajendra Nayak /* if not found, try doing it non-dt way */ 1478576ca436SMark Brown if (dev) 1479576ca436SMark Brown devname = dev_name(dev); 1480576ca436SMark Brown 148185f3b431STomeu Vizoso mutex_lock(®ulator_list_mutex); 1482576ca436SMark Brown list_for_each_entry(map, ®ulator_map_list, list) { 1483576ca436SMark Brown /* If the mapping has a device set up it must match */ 1484576ca436SMark Brown if (map->dev_name && 1485576ca436SMark Brown (!devname || strcmp(map->dev_name, devname))) 1486576ca436SMark Brown continue; 1487576ca436SMark Brown 148885f3b431STomeu Vizoso if (strcmp(map->supply, supply) == 0 && 148985f3b431STomeu Vizoso get_device(&map->regulator->dev)) { 1490163478daSDmitry Torokhov r = map->regulator; 1491163478daSDmitry Torokhov break; 1492576ca436SMark Brown } 149385f3b431STomeu Vizoso } 149485f3b431STomeu Vizoso mutex_unlock(®ulator_list_mutex); 1495576ca436SMark Brown 1496163478daSDmitry Torokhov if (r) 1497163478daSDmitry Torokhov return r; 1498163478daSDmitry Torokhov 149906217197SCharles Keepax r = regulator_lookup_by_name(supply); 150006217197SCharles Keepax if (r) 150106217197SCharles Keepax return r; 150206217197SCharles Keepax 1503163478daSDmitry Torokhov return ERR_PTR(-ENODEV); 150469511a45SRajendra Nayak } 150569511a45SRajendra Nayak 15066261b06dSBjorn Andersson static int regulator_resolve_supply(struct regulator_dev *rdev) 15076261b06dSBjorn Andersson { 15086261b06dSBjorn Andersson struct regulator_dev *r; 15096261b06dSBjorn Andersson struct device *dev = rdev->dev.parent; 15106261b06dSBjorn Andersson int ret; 15116261b06dSBjorn Andersson 15126261b06dSBjorn Andersson /* No supply to resovle? */ 15136261b06dSBjorn Andersson if (!rdev->supply_name) 15146261b06dSBjorn Andersson return 0; 15156261b06dSBjorn Andersson 15166261b06dSBjorn Andersson /* Supply already resolved? */ 15176261b06dSBjorn Andersson if (rdev->supply) 15186261b06dSBjorn Andersson return 0; 15196261b06dSBjorn Andersson 1520163478daSDmitry Torokhov r = regulator_dev_lookup(dev, rdev->supply_name); 1521163478daSDmitry Torokhov if (IS_ERR(r)) { 1522163478daSDmitry Torokhov ret = PTR_ERR(r); 1523163478daSDmitry Torokhov 152406423121SMark Brown /* Did the lookup explicitly defer for us? */ 152506423121SMark Brown if (ret == -EPROBE_DEFER) 152606423121SMark Brown return ret; 152706423121SMark Brown 15289f7e25edSMark Brown if (have_full_constraints()) { 15299f7e25edSMark Brown r = dummy_regulator_rdev; 153085f3b431STomeu Vizoso get_device(&r->dev); 15319f7e25edSMark Brown } else { 15326261b06dSBjorn Andersson dev_err(dev, "Failed to resolve %s-supply for %s\n", 15336261b06dSBjorn Andersson rdev->supply_name, rdev->desc->name); 15346261b06dSBjorn Andersson return -EPROBE_DEFER; 15356261b06dSBjorn Andersson } 15369f7e25edSMark Brown } 15376261b06dSBjorn Andersson 153866d228a2SJon Hunter /* 153966d228a2SJon Hunter * If the supply's parent device is not the same as the 154066d228a2SJon Hunter * regulator's parent device, then ensure the parent device 154166d228a2SJon Hunter * is bound before we resolve the supply, in case the parent 154266d228a2SJon Hunter * device get probe deferred and unregisters the supply. 154366d228a2SJon Hunter */ 154466d228a2SJon Hunter if (r->dev.parent && r->dev.parent != rdev->dev.parent) { 154566d228a2SJon Hunter if (!device_is_bound(r->dev.parent)) { 154666d228a2SJon Hunter put_device(&r->dev); 154766d228a2SJon Hunter return -EPROBE_DEFER; 154866d228a2SJon Hunter } 154966d228a2SJon Hunter } 155066d228a2SJon Hunter 15516261b06dSBjorn Andersson /* Recursively resolve the supply of the supply */ 15526261b06dSBjorn Andersson ret = regulator_resolve_supply(r); 155385f3b431STomeu Vizoso if (ret < 0) { 155485f3b431STomeu Vizoso put_device(&r->dev); 15556261b06dSBjorn Andersson return ret; 155685f3b431STomeu Vizoso } 15576261b06dSBjorn Andersson 15586261b06dSBjorn Andersson ret = set_supply(rdev, r); 155985f3b431STomeu Vizoso if (ret < 0) { 156085f3b431STomeu Vizoso put_device(&r->dev); 15616261b06dSBjorn Andersson return ret; 156285f3b431STomeu Vizoso } 15636261b06dSBjorn Andersson 15646261b06dSBjorn Andersson /* Cascade always-on state to supply */ 156595a293c7SJavier Martinez Canillas if (_regulator_is_enabled(rdev)) { 15666261b06dSBjorn Andersson ret = regulator_enable(rdev->supply); 156736a1f1b6SJavier Martinez Canillas if (ret < 0) { 156836a1f1b6SJavier Martinez Canillas _regulator_put(rdev->supply); 15698e5356a7SJon Hunter rdev->supply = NULL; 15706261b06dSBjorn Andersson return ret; 15716261b06dSBjorn Andersson } 157236a1f1b6SJavier Martinez Canillas } 15736261b06dSBjorn Andersson 15746261b06dSBjorn Andersson return 0; 15756261b06dSBjorn Andersson } 15766261b06dSBjorn Andersson 15775ffbd136SMark Brown /* Internal regulator request function */ 1578a8bd42a9SDmitry Torokhov struct regulator *_regulator_get(struct device *dev, const char *id, 1579a8bd42a9SDmitry Torokhov enum regulator_get_type get_type) 1580414c70cbSLiam Girdwood { 1581414c70cbSLiam Girdwood struct regulator_dev *rdev; 15827d245afaSDmitry Torokhov struct regulator *regulator; 1583a4d7641fSDmitry Torokhov const char *devname = dev ? dev_name(dev) : "deviceless"; 1584317b5684SMark Brown int ret; 1585414c70cbSLiam Girdwood 1586a8bd42a9SDmitry Torokhov if (get_type >= MAX_GET_TYPE) { 1587a8bd42a9SDmitry Torokhov dev_err(dev, "invalid type %d in %s\n", get_type, __func__); 1588a8bd42a9SDmitry Torokhov return ERR_PTR(-EINVAL); 1589a8bd42a9SDmitry Torokhov } 1590a8bd42a9SDmitry Torokhov 1591414c70cbSLiam Girdwood if (id == NULL) { 15925da84fd9SJoe Perches pr_err("get() with no identifier\n"); 1593043c998fSMark Brown return ERR_PTR(-EINVAL); 1594414c70cbSLiam Girdwood } 1595414c70cbSLiam Girdwood 1596163478daSDmitry Torokhov rdev = regulator_dev_lookup(dev, id); 1597a4d7641fSDmitry Torokhov if (IS_ERR(rdev)) { 1598163478daSDmitry Torokhov ret = PTR_ERR(rdev); 1599ef60abbbSMark Brown 16001e4b545cSNishanth Menon /* 1601a4d7641fSDmitry Torokhov * If regulator_dev_lookup() fails with error other 1602a4d7641fSDmitry Torokhov * than -ENODEV our job here is done, we simply return it. 16031e4b545cSNishanth Menon */ 1604a4d7641fSDmitry Torokhov if (ret != -ENODEV) 1605a4d7641fSDmitry Torokhov return ERR_PTR(ret); 16061e4b545cSNishanth Menon 1607a4d7641fSDmitry Torokhov if (!have_full_constraints()) { 1608a4d7641fSDmitry Torokhov dev_warn(dev, 1609a4d7641fSDmitry Torokhov "incomplete constraints, dummy supplies not allowed\n"); 1610a4d7641fSDmitry Torokhov return ERR_PTR(-ENODEV); 161134abbd68SMark Brown } 161234abbd68SMark Brown 1613a4d7641fSDmitry Torokhov switch (get_type) { 1614a4d7641fSDmitry Torokhov case NORMAL_GET: 1615a4d7641fSDmitry Torokhov /* 1616a4d7641fSDmitry Torokhov * Assume that a regulator is physically present and 1617a4d7641fSDmitry Torokhov * enabled, even if it isn't hooked up, and just 1618a4d7641fSDmitry Torokhov * provide a dummy. 1619a4d7641fSDmitry Torokhov */ 1620a4d7641fSDmitry Torokhov dev_warn(dev, 1621a4d7641fSDmitry Torokhov "%s supply %s not found, using dummy regulator\n", 1622a4d7641fSDmitry Torokhov devname, id); 1623a4d7641fSDmitry Torokhov rdev = dummy_regulator_rdev; 1624a4d7641fSDmitry Torokhov get_device(&rdev->dev); 1625a4d7641fSDmitry Torokhov break; 1626414c70cbSLiam Girdwood 1627a4d7641fSDmitry Torokhov case EXCLUSIVE_GET: 1628a4d7641fSDmitry Torokhov dev_warn(dev, 1629a4d7641fSDmitry Torokhov "dummy supplies not allowed for exclusive requests\n"); 1630a4d7641fSDmitry Torokhov /* fall through */ 1631a4d7641fSDmitry Torokhov 1632a4d7641fSDmitry Torokhov default: 1633a4d7641fSDmitry Torokhov return ERR_PTR(-ENODEV); 1634a4d7641fSDmitry Torokhov } 1635a4d7641fSDmitry Torokhov } 1636a4d7641fSDmitry Torokhov 16375ffbd136SMark Brown if (rdev->exclusive) { 16385ffbd136SMark Brown regulator = ERR_PTR(-EPERM); 163985f3b431STomeu Vizoso put_device(&rdev->dev); 164085f3b431STomeu Vizoso return regulator; 16415ffbd136SMark Brown } 16425ffbd136SMark Brown 1643a8bd42a9SDmitry Torokhov if (get_type == EXCLUSIVE_GET && rdev->open_count) { 16445ffbd136SMark Brown regulator = ERR_PTR(-EBUSY); 164585f3b431STomeu Vizoso put_device(&rdev->dev); 164685f3b431STomeu Vizoso return regulator; 16475ffbd136SMark Brown } 16485ffbd136SMark Brown 16496261b06dSBjorn Andersson ret = regulator_resolve_supply(rdev); 16506261b06dSBjorn Andersson if (ret < 0) { 16516261b06dSBjorn Andersson regulator = ERR_PTR(ret); 165285f3b431STomeu Vizoso put_device(&rdev->dev); 165385f3b431STomeu Vizoso return regulator; 16546261b06dSBjorn Andersson } 16556261b06dSBjorn Andersson 165685f3b431STomeu Vizoso if (!try_module_get(rdev->owner)) { 16577d245afaSDmitry Torokhov regulator = ERR_PTR(-EPROBE_DEFER); 165885f3b431STomeu Vizoso put_device(&rdev->dev); 165985f3b431STomeu Vizoso return regulator; 166085f3b431STomeu Vizoso } 1661a5766f11SLiam Girdwood 1662414c70cbSLiam Girdwood regulator = create_regulator(rdev, dev, id); 1663414c70cbSLiam Girdwood if (regulator == NULL) { 1664414c70cbSLiam Girdwood regulator = ERR_PTR(-ENOMEM); 166585f3b431STomeu Vizoso put_device(&rdev->dev); 1666414c70cbSLiam Girdwood module_put(rdev->owner); 166785f3b431STomeu Vizoso return regulator; 1668414c70cbSLiam Girdwood } 1669414c70cbSLiam Girdwood 16705ffbd136SMark Brown rdev->open_count++; 1671a8bd42a9SDmitry Torokhov if (get_type == EXCLUSIVE_GET) { 16725ffbd136SMark Brown rdev->exclusive = 1; 16735ffbd136SMark Brown 16745ffbd136SMark Brown ret = _regulator_is_enabled(rdev); 16755ffbd136SMark Brown if (ret > 0) 16765ffbd136SMark Brown rdev->use_count = 1; 16775ffbd136SMark Brown else 16785ffbd136SMark Brown rdev->use_count = 0; 16795ffbd136SMark Brown } 16805ffbd136SMark Brown 1681414c70cbSLiam Girdwood return regulator; 1682414c70cbSLiam Girdwood } 16835ffbd136SMark Brown 16845ffbd136SMark Brown /** 16855ffbd136SMark Brown * regulator_get - lookup and obtain a reference to a regulator. 16865ffbd136SMark Brown * @dev: device for regulator "consumer" 16875ffbd136SMark Brown * @id: Supply name or regulator ID. 16885ffbd136SMark Brown * 16895ffbd136SMark Brown * Returns a struct regulator corresponding to the regulator producer, 16905ffbd136SMark Brown * or IS_ERR() condition containing errno. 16915ffbd136SMark Brown * 16925ffbd136SMark Brown * Use of supply names configured via regulator_set_device_supply() is 16935ffbd136SMark Brown * strongly encouraged. It is recommended that the supply name used 16945ffbd136SMark Brown * should match the name used for the supply and/or the relevant 16955ffbd136SMark Brown * device pins in the datasheet. 16965ffbd136SMark Brown */ 16975ffbd136SMark Brown struct regulator *regulator_get(struct device *dev, const char *id) 16985ffbd136SMark Brown { 1699a8bd42a9SDmitry Torokhov return _regulator_get(dev, id, NORMAL_GET); 17005ffbd136SMark Brown } 1701414c70cbSLiam Girdwood EXPORT_SYMBOL_GPL(regulator_get); 1702414c70cbSLiam Girdwood 1703070b9079SStephen Boyd /** 17045ffbd136SMark Brown * regulator_get_exclusive - obtain exclusive access to a regulator. 17055ffbd136SMark Brown * @dev: device for regulator "consumer" 17065ffbd136SMark Brown * @id: Supply name or regulator ID. 17075ffbd136SMark Brown * 17085ffbd136SMark Brown * Returns a struct regulator corresponding to the regulator producer, 17095ffbd136SMark Brown * or IS_ERR() condition containing errno. Other consumers will be 171069c3f723SStephen Boyd * unable to obtain this regulator while this reference is held and the 171169c3f723SStephen Boyd * use count for the regulator will be initialised to reflect the current 171269c3f723SStephen Boyd * state of the regulator. 17135ffbd136SMark Brown * 17145ffbd136SMark Brown * This is intended for use by consumers which cannot tolerate shared 17155ffbd136SMark Brown * use of the regulator such as those which need to force the 17165ffbd136SMark Brown * regulator off for correct operation of the hardware they are 17175ffbd136SMark Brown * controlling. 17185ffbd136SMark Brown * 17195ffbd136SMark Brown * Use of supply names configured via regulator_set_device_supply() is 17205ffbd136SMark Brown * strongly encouraged. It is recommended that the supply name used 17215ffbd136SMark Brown * should match the name used for the supply and/or the relevant 17225ffbd136SMark Brown * device pins in the datasheet. 17235ffbd136SMark Brown */ 17245ffbd136SMark Brown struct regulator *regulator_get_exclusive(struct device *dev, const char *id) 17255ffbd136SMark Brown { 1726a8bd42a9SDmitry Torokhov return _regulator_get(dev, id, EXCLUSIVE_GET); 17275ffbd136SMark Brown } 17285ffbd136SMark Brown EXPORT_SYMBOL_GPL(regulator_get_exclusive); 17295ffbd136SMark Brown 1730de1dd9fdSMark Brown /** 1731de1dd9fdSMark Brown * regulator_get_optional - obtain optional access to a regulator. 1732de1dd9fdSMark Brown * @dev: device for regulator "consumer" 1733de1dd9fdSMark Brown * @id: Supply name or regulator ID. 1734de1dd9fdSMark Brown * 1735de1dd9fdSMark Brown * Returns a struct regulator corresponding to the regulator producer, 173669c3f723SStephen Boyd * or IS_ERR() condition containing errno. 1737de1dd9fdSMark Brown * 1738de1dd9fdSMark Brown * This is intended for use by consumers for devices which can have 1739de1dd9fdSMark Brown * some supplies unconnected in normal use, such as some MMC devices. 1740de1dd9fdSMark Brown * It can allow the regulator core to provide stub supplies for other 1741de1dd9fdSMark Brown * supplies requested using normal regulator_get() calls without 1742de1dd9fdSMark Brown * disrupting the operation of drivers that can handle absent 1743de1dd9fdSMark Brown * supplies. 1744de1dd9fdSMark Brown * 1745de1dd9fdSMark Brown * Use of supply names configured via regulator_set_device_supply() is 1746de1dd9fdSMark Brown * strongly encouraged. It is recommended that the supply name used 1747de1dd9fdSMark Brown * should match the name used for the supply and/or the relevant 1748de1dd9fdSMark Brown * device pins in the datasheet. 1749de1dd9fdSMark Brown */ 1750de1dd9fdSMark Brown struct regulator *regulator_get_optional(struct device *dev, const char *id) 1751de1dd9fdSMark Brown { 1752a8bd42a9SDmitry Torokhov return _regulator_get(dev, id, OPTIONAL_GET); 1753de1dd9fdSMark Brown } 1754de1dd9fdSMark Brown EXPORT_SYMBOL_GPL(regulator_get_optional); 1755de1dd9fdSMark Brown 175683b0302dSAshay Jaiswal /* regulator_list_mutex lock held by regulator_put() */ 175723ff2f0fSCharles Keepax static void _regulator_put(struct regulator *regulator) 1758414c70cbSLiam Girdwood { 1759414c70cbSLiam Girdwood struct regulator_dev *rdev; 1760414c70cbSLiam Girdwood 176193576842SViresh Kumar if (IS_ERR_OR_NULL(regulator)) 1762414c70cbSLiam Girdwood return; 1763414c70cbSLiam Girdwood 176470cfef26SKrzysztof Kozlowski lockdep_assert_held_once(®ulator_list_mutex); 176570cfef26SKrzysztof Kozlowski 1766414c70cbSLiam Girdwood rdev = regulator->rdev; 1767414c70cbSLiam Girdwood 17685de70519SMark Brown debugfs_remove_recursive(regulator->debugfs); 17695de70519SMark Brown 1770414c70cbSLiam Girdwood /* remove any sysfs entries */ 1771e2c98eafSShawn Guo if (regulator->dev) 1772414c70cbSLiam Girdwood sysfs_remove_link(&rdev->dev.kobj, regulator->supply_name); 177383b0302dSAshay Jaiswal mutex_lock(&rdev->mutex); 1774414c70cbSLiam Girdwood list_del(®ulator->list); 1775414c70cbSLiam Girdwood 17765ffbd136SMark Brown rdev->open_count--; 17775ffbd136SMark Brown rdev->exclusive = 0; 177885f3b431STomeu Vizoso put_device(&rdev->dev); 177983b0302dSAshay Jaiswal mutex_unlock(&rdev->mutex); 17805ffbd136SMark Brown 17810630b614SStephen Boyd kfree_const(regulator->supply_name); 17821768514eSMark Brown kfree(regulator); 17831768514eSMark Brown 1784414c70cbSLiam Girdwood module_put(rdev->owner); 178523ff2f0fSCharles Keepax } 178623ff2f0fSCharles Keepax 178723ff2f0fSCharles Keepax /** 178823ff2f0fSCharles Keepax * regulator_put - "free" the regulator source 178923ff2f0fSCharles Keepax * @regulator: regulator source 179023ff2f0fSCharles Keepax * 179123ff2f0fSCharles Keepax * Note: drivers must ensure that all regulator_enable calls made on this 179223ff2f0fSCharles Keepax * regulator source are balanced by regulator_disable calls prior to calling 179323ff2f0fSCharles Keepax * this function. 179423ff2f0fSCharles Keepax */ 179523ff2f0fSCharles Keepax void regulator_put(struct regulator *regulator) 179623ff2f0fSCharles Keepax { 179723ff2f0fSCharles Keepax mutex_lock(®ulator_list_mutex); 179823ff2f0fSCharles Keepax _regulator_put(regulator); 1799414c70cbSLiam Girdwood mutex_unlock(®ulator_list_mutex); 1800414c70cbSLiam Girdwood } 1801414c70cbSLiam Girdwood EXPORT_SYMBOL_GPL(regulator_put); 1802414c70cbSLiam Girdwood 1803a06ccd9cSCharles Keepax /** 1804a06ccd9cSCharles Keepax * regulator_register_supply_alias - Provide device alias for supply lookup 1805a06ccd9cSCharles Keepax * 1806a06ccd9cSCharles Keepax * @dev: device that will be given as the regulator "consumer" 1807a06ccd9cSCharles Keepax * @id: Supply name or regulator ID 1808a06ccd9cSCharles Keepax * @alias_dev: device that should be used to lookup the supply 1809a06ccd9cSCharles Keepax * @alias_id: Supply name or regulator ID that should be used to lookup the 1810a06ccd9cSCharles Keepax * supply 1811a06ccd9cSCharles Keepax * 1812a06ccd9cSCharles Keepax * All lookups for id on dev will instead be conducted for alias_id on 1813a06ccd9cSCharles Keepax * alias_dev. 1814a06ccd9cSCharles Keepax */ 1815a06ccd9cSCharles Keepax int regulator_register_supply_alias(struct device *dev, const char *id, 1816a06ccd9cSCharles Keepax struct device *alias_dev, 1817a06ccd9cSCharles Keepax const char *alias_id) 1818a06ccd9cSCharles Keepax { 1819a06ccd9cSCharles Keepax struct regulator_supply_alias *map; 1820a06ccd9cSCharles Keepax 1821a06ccd9cSCharles Keepax map = regulator_find_supply_alias(dev, id); 1822a06ccd9cSCharles Keepax if (map) 1823a06ccd9cSCharles Keepax return -EEXIST; 1824a06ccd9cSCharles Keepax 1825a06ccd9cSCharles Keepax map = kzalloc(sizeof(struct regulator_supply_alias), GFP_KERNEL); 1826a06ccd9cSCharles Keepax if (!map) 1827a06ccd9cSCharles Keepax return -ENOMEM; 1828a06ccd9cSCharles Keepax 1829a06ccd9cSCharles Keepax map->src_dev = dev; 1830a06ccd9cSCharles Keepax map->src_supply = id; 1831a06ccd9cSCharles Keepax map->alias_dev = alias_dev; 1832a06ccd9cSCharles Keepax map->alias_supply = alias_id; 1833a06ccd9cSCharles Keepax 1834a06ccd9cSCharles Keepax list_add(&map->list, ®ulator_supply_alias_list); 1835a06ccd9cSCharles Keepax 1836a06ccd9cSCharles Keepax pr_info("Adding alias for supply %s,%s -> %s,%s\n", 1837a06ccd9cSCharles Keepax id, dev_name(dev), alias_id, dev_name(alias_dev)); 1838a06ccd9cSCharles Keepax 1839a06ccd9cSCharles Keepax return 0; 1840a06ccd9cSCharles Keepax } 1841a06ccd9cSCharles Keepax EXPORT_SYMBOL_GPL(regulator_register_supply_alias); 1842a06ccd9cSCharles Keepax 1843a06ccd9cSCharles Keepax /** 1844a06ccd9cSCharles Keepax * regulator_unregister_supply_alias - Remove device alias 1845a06ccd9cSCharles Keepax * 1846a06ccd9cSCharles Keepax * @dev: device that will be given as the regulator "consumer" 1847a06ccd9cSCharles Keepax * @id: Supply name or regulator ID 1848a06ccd9cSCharles Keepax * 1849a06ccd9cSCharles Keepax * Remove a lookup alias if one exists for id on dev. 1850a06ccd9cSCharles Keepax */ 1851a06ccd9cSCharles Keepax void regulator_unregister_supply_alias(struct device *dev, const char *id) 1852a06ccd9cSCharles Keepax { 1853a06ccd9cSCharles Keepax struct regulator_supply_alias *map; 1854a06ccd9cSCharles Keepax 1855a06ccd9cSCharles Keepax map = regulator_find_supply_alias(dev, id); 1856a06ccd9cSCharles Keepax if (map) { 1857a06ccd9cSCharles Keepax list_del(&map->list); 1858a06ccd9cSCharles Keepax kfree(map); 1859a06ccd9cSCharles Keepax } 1860a06ccd9cSCharles Keepax } 1861a06ccd9cSCharles Keepax EXPORT_SYMBOL_GPL(regulator_unregister_supply_alias); 1862a06ccd9cSCharles Keepax 1863a06ccd9cSCharles Keepax /** 1864a06ccd9cSCharles Keepax * regulator_bulk_register_supply_alias - register multiple aliases 1865a06ccd9cSCharles Keepax * 1866a06ccd9cSCharles Keepax * @dev: device that will be given as the regulator "consumer" 1867a06ccd9cSCharles Keepax * @id: List of supply names or regulator IDs 1868a06ccd9cSCharles Keepax * @alias_dev: device that should be used to lookup the supply 1869a06ccd9cSCharles Keepax * @alias_id: List of supply names or regulator IDs that should be used to 1870a06ccd9cSCharles Keepax * lookup the supply 1871a06ccd9cSCharles Keepax * @num_id: Number of aliases to register 1872a06ccd9cSCharles Keepax * 1873a06ccd9cSCharles Keepax * @return 0 on success, an errno on failure. 1874a06ccd9cSCharles Keepax * 1875a06ccd9cSCharles Keepax * This helper function allows drivers to register several supply 1876a06ccd9cSCharles Keepax * aliases in one operation. If any of the aliases cannot be 1877a06ccd9cSCharles Keepax * registered any aliases that were registered will be removed 1878a06ccd9cSCharles Keepax * before returning to the caller. 1879a06ccd9cSCharles Keepax */ 18809f8c0fe9SLee Jones int regulator_bulk_register_supply_alias(struct device *dev, 18819f8c0fe9SLee Jones const char *const *id, 1882a06ccd9cSCharles Keepax struct device *alias_dev, 18839f8c0fe9SLee Jones const char *const *alias_id, 1884a06ccd9cSCharles Keepax int num_id) 1885a06ccd9cSCharles Keepax { 1886a06ccd9cSCharles Keepax int i; 1887a06ccd9cSCharles Keepax int ret; 1888a06ccd9cSCharles Keepax 1889a06ccd9cSCharles Keepax for (i = 0; i < num_id; ++i) { 1890a06ccd9cSCharles Keepax ret = regulator_register_supply_alias(dev, id[i], alias_dev, 1891a06ccd9cSCharles Keepax alias_id[i]); 1892a06ccd9cSCharles Keepax if (ret < 0) 1893a06ccd9cSCharles Keepax goto err; 1894a06ccd9cSCharles Keepax } 1895a06ccd9cSCharles Keepax 1896a06ccd9cSCharles Keepax return 0; 1897a06ccd9cSCharles Keepax 1898a06ccd9cSCharles Keepax err: 1899a06ccd9cSCharles Keepax dev_err(dev, 1900a06ccd9cSCharles Keepax "Failed to create supply alias %s,%s -> %s,%s\n", 1901a06ccd9cSCharles Keepax id[i], dev_name(dev), alias_id[i], dev_name(alias_dev)); 1902a06ccd9cSCharles Keepax 1903a06ccd9cSCharles Keepax while (--i >= 0) 1904a06ccd9cSCharles Keepax regulator_unregister_supply_alias(dev, id[i]); 1905a06ccd9cSCharles Keepax 1906a06ccd9cSCharles Keepax return ret; 1907a06ccd9cSCharles Keepax } 1908a06ccd9cSCharles Keepax EXPORT_SYMBOL_GPL(regulator_bulk_register_supply_alias); 1909a06ccd9cSCharles Keepax 1910a06ccd9cSCharles Keepax /** 1911a06ccd9cSCharles Keepax * regulator_bulk_unregister_supply_alias - unregister multiple aliases 1912a06ccd9cSCharles Keepax * 1913a06ccd9cSCharles Keepax * @dev: device that will be given as the regulator "consumer" 1914a06ccd9cSCharles Keepax * @id: List of supply names or regulator IDs 1915a06ccd9cSCharles Keepax * @num_id: Number of aliases to unregister 1916a06ccd9cSCharles Keepax * 1917a06ccd9cSCharles Keepax * This helper function allows drivers to unregister several supply 1918a06ccd9cSCharles Keepax * aliases in one operation. 1919a06ccd9cSCharles Keepax */ 1920a06ccd9cSCharles Keepax void regulator_bulk_unregister_supply_alias(struct device *dev, 19219f8c0fe9SLee Jones const char *const *id, 1922a06ccd9cSCharles Keepax int num_id) 1923a06ccd9cSCharles Keepax { 1924a06ccd9cSCharles Keepax int i; 1925a06ccd9cSCharles Keepax 1926a06ccd9cSCharles Keepax for (i = 0; i < num_id; ++i) 1927a06ccd9cSCharles Keepax regulator_unregister_supply_alias(dev, id[i]); 1928a06ccd9cSCharles Keepax } 1929a06ccd9cSCharles Keepax EXPORT_SYMBOL_GPL(regulator_bulk_unregister_supply_alias); 1930a06ccd9cSCharles Keepax 1931a06ccd9cSCharles Keepax 1932f19b00daSKim, Milo /* Manage enable GPIO list. Same GPIO pin can be shared among regulators */ 1933f19b00daSKim, Milo static int regulator_ena_gpio_request(struct regulator_dev *rdev, 1934f19b00daSKim, Milo const struct regulator_config *config) 1935f19b00daSKim, Milo { 1936f19b00daSKim, Milo struct regulator_enable_gpio *pin; 1937778b28b4SRussell King struct gpio_desc *gpiod; 1938f19b00daSKim, Milo int ret; 1939f19b00daSKim, Milo 1940778b28b4SRussell King gpiod = gpio_to_desc(config->ena_gpio); 1941778b28b4SRussell King 1942f19b00daSKim, Milo list_for_each_entry(pin, ®ulator_ena_gpio_list, list) { 1943778b28b4SRussell King if (pin->gpiod == gpiod) { 1944f19b00daSKim, Milo rdev_dbg(rdev, "GPIO %d is already used\n", 1945f19b00daSKim, Milo config->ena_gpio); 1946f19b00daSKim, Milo goto update_ena_gpio_to_rdev; 1947f19b00daSKim, Milo } 1948f19b00daSKim, Milo } 1949f19b00daSKim, Milo 1950f19b00daSKim, Milo ret = gpio_request_one(config->ena_gpio, 1951f19b00daSKim, Milo GPIOF_DIR_OUT | config->ena_gpio_flags, 1952f19b00daSKim, Milo rdev_get_name(rdev)); 1953f19b00daSKim, Milo if (ret) 1954f19b00daSKim, Milo return ret; 1955f19b00daSKim, Milo 1956f19b00daSKim, Milo pin = kzalloc(sizeof(struct regulator_enable_gpio), GFP_KERNEL); 1957f19b00daSKim, Milo if (pin == NULL) { 1958f19b00daSKim, Milo gpio_free(config->ena_gpio); 1959f19b00daSKim, Milo return -ENOMEM; 1960f19b00daSKim, Milo } 1961f19b00daSKim, Milo 1962778b28b4SRussell King pin->gpiod = gpiod; 1963f19b00daSKim, Milo pin->ena_gpio_invert = config->ena_gpio_invert; 1964f19b00daSKim, Milo list_add(&pin->list, ®ulator_ena_gpio_list); 1965f19b00daSKim, Milo 1966f19b00daSKim, Milo update_ena_gpio_to_rdev: 1967f19b00daSKim, Milo pin->request_count++; 1968f19b00daSKim, Milo rdev->ena_pin = pin; 1969f19b00daSKim, Milo return 0; 1970f19b00daSKim, Milo } 1971f19b00daSKim, Milo 1972f19b00daSKim, Milo static void regulator_ena_gpio_free(struct regulator_dev *rdev) 1973f19b00daSKim, Milo { 1974f19b00daSKim, Milo struct regulator_enable_gpio *pin, *n; 1975f19b00daSKim, Milo 1976f19b00daSKim, Milo if (!rdev->ena_pin) 1977f19b00daSKim, Milo return; 1978f19b00daSKim, Milo 1979f19b00daSKim, Milo /* Free the GPIO only in case of no use */ 1980f19b00daSKim, Milo list_for_each_entry_safe(pin, n, ®ulator_ena_gpio_list, list) { 1981778b28b4SRussell King if (pin->gpiod == rdev->ena_pin->gpiod) { 1982f19b00daSKim, Milo if (pin->request_count <= 1) { 1983f19b00daSKim, Milo pin->request_count = 0; 1984778b28b4SRussell King gpiod_put(pin->gpiod); 1985f19b00daSKim, Milo list_del(&pin->list); 1986f19b00daSKim, Milo kfree(pin); 198760a2362fSSeung-Woo Kim rdev->ena_pin = NULL; 198860a2362fSSeung-Woo Kim return; 1989f19b00daSKim, Milo } else { 1990f19b00daSKim, Milo pin->request_count--; 1991f19b00daSKim, Milo } 1992f19b00daSKim, Milo } 1993f19b00daSKim, Milo } 1994f19b00daSKim, Milo } 1995f19b00daSKim, Milo 1996967cfb18SKim, Milo /** 199731d6eebfSRobert P. J. Day * regulator_ena_gpio_ctrl - balance enable_count of each GPIO and actual GPIO pin control 199831d6eebfSRobert P. J. Day * @rdev: regulator_dev structure 199931d6eebfSRobert P. J. Day * @enable: enable GPIO at initial use? 200031d6eebfSRobert P. J. Day * 2001967cfb18SKim, Milo * GPIO is enabled in case of initial use. (enable_count is 0) 2002967cfb18SKim, Milo * GPIO is disabled when it is not shared any more. (enable_count <= 1) 2003967cfb18SKim, Milo */ 2004967cfb18SKim, Milo static int regulator_ena_gpio_ctrl(struct regulator_dev *rdev, bool enable) 2005967cfb18SKim, Milo { 2006967cfb18SKim, Milo struct regulator_enable_gpio *pin = rdev->ena_pin; 2007967cfb18SKim, Milo 2008967cfb18SKim, Milo if (!pin) 2009967cfb18SKim, Milo return -EINVAL; 2010967cfb18SKim, Milo 2011967cfb18SKim, Milo if (enable) { 2012967cfb18SKim, Milo /* Enable GPIO at initial use */ 2013967cfb18SKim, Milo if (pin->enable_count == 0) 2014778b28b4SRussell King gpiod_set_value_cansleep(pin->gpiod, 2015967cfb18SKim, Milo !pin->ena_gpio_invert); 2016967cfb18SKim, Milo 2017967cfb18SKim, Milo pin->enable_count++; 2018967cfb18SKim, Milo } else { 2019967cfb18SKim, Milo if (pin->enable_count > 1) { 2020967cfb18SKim, Milo pin->enable_count--; 2021967cfb18SKim, Milo return 0; 2022967cfb18SKim, Milo } 2023967cfb18SKim, Milo 2024967cfb18SKim, Milo /* Disable GPIO if not used */ 2025967cfb18SKim, Milo if (pin->enable_count <= 1) { 2026778b28b4SRussell King gpiod_set_value_cansleep(pin->gpiod, 2027967cfb18SKim, Milo pin->ena_gpio_invert); 2028967cfb18SKim, Milo pin->enable_count = 0; 2029967cfb18SKim, Milo } 2030967cfb18SKim, Milo } 2031967cfb18SKim, Milo 2032967cfb18SKim, Milo return 0; 2033967cfb18SKim, Milo } 2034967cfb18SKim, Milo 203579fd1141SGuodong Xu /** 203679fd1141SGuodong Xu * _regulator_enable_delay - a delay helper function 203779fd1141SGuodong Xu * @delay: time to delay in microseconds 203879fd1141SGuodong Xu * 20395df529d4SThierry Reding * Delay for the requested amount of time as per the guidelines in: 20405df529d4SThierry Reding * 20415df529d4SThierry Reding * Documentation/timers/timers-howto.txt 20425df529d4SThierry Reding * 20435df529d4SThierry Reding * The assumption here is that regulators will never be enabled in 20445df529d4SThierry Reding * atomic context and therefore sleeping functions can be used. 20455df529d4SThierry Reding */ 204679fd1141SGuodong Xu static void _regulator_enable_delay(unsigned int delay) 204779fd1141SGuodong Xu { 20485df529d4SThierry Reding unsigned int ms = delay / 1000; 20495df529d4SThierry Reding unsigned int us = delay % 1000; 20505df529d4SThierry Reding 20515df529d4SThierry Reding if (ms > 0) { 20525df529d4SThierry Reding /* 20535df529d4SThierry Reding * For small enough values, handle super-millisecond 20545df529d4SThierry Reding * delays in the usleep_range() call below. 20555df529d4SThierry Reding */ 20565df529d4SThierry Reding if (ms < 20) 20575df529d4SThierry Reding us += ms * 1000; 20585df529d4SThierry Reding else 20595df529d4SThierry Reding msleep(ms); 20605df529d4SThierry Reding } 20615df529d4SThierry Reding 20625df529d4SThierry Reding /* 20635df529d4SThierry Reding * Give the scheduler some room to coalesce with any other 20645df529d4SThierry Reding * wakeup sources. For delays shorter than 10 us, don't even 20655df529d4SThierry Reding * bother setting up high-resolution timers and just busy- 20665df529d4SThierry Reding * loop. 20675df529d4SThierry Reding */ 20685df529d4SThierry Reding if (us >= 10) 20695df529d4SThierry Reding usleep_range(us, us + 100); 20705df529d4SThierry Reding else 20715df529d4SThierry Reding udelay(us); 20725c5659d0SMark Brown } 20735c5659d0SMark Brown 20745c5659d0SMark Brown static int _regulator_do_enable(struct regulator_dev *rdev) 20755c5659d0SMark Brown { 20765c5659d0SMark Brown int ret, delay; 20775c5659d0SMark Brown 20785c5659d0SMark Brown /* Query before enabling in case configuration dependent. */ 20795c5659d0SMark Brown ret = _regulator_get_enable_time(rdev); 20805c5659d0SMark Brown if (ret >= 0) { 20815c5659d0SMark Brown delay = ret; 20825c5659d0SMark Brown } else { 2083414c70cbSLiam Girdwood rdev_warn(rdev, "enable_time() failed: %d\n", ret); 2084414c70cbSLiam Girdwood delay = 0; 2085414c70cbSLiam Girdwood } 20865c5659d0SMark Brown 2087414c70cbSLiam Girdwood trace_regulator_enable(rdev_get_name(rdev)); 2088414c70cbSLiam Girdwood 2089871f5650SGuodong Xu if (rdev->desc->off_on_delay) { 2090871f5650SGuodong Xu /* if needed, keep a distance of off_on_delay from last time 2091871f5650SGuodong Xu * this regulator was disabled. 2092871f5650SGuodong Xu */ 2093871f5650SGuodong Xu unsigned long start_jiffy = jiffies; 2094871f5650SGuodong Xu unsigned long intended, max_delay, remaining; 2095871f5650SGuodong Xu 2096871f5650SGuodong Xu max_delay = usecs_to_jiffies(rdev->desc->off_on_delay); 2097871f5650SGuodong Xu intended = rdev->last_off_jiffy + max_delay; 2098871f5650SGuodong Xu 2099871f5650SGuodong Xu if (time_before(start_jiffy, intended)) { 2100871f5650SGuodong Xu /* calc remaining jiffies to deal with one-time 2101871f5650SGuodong Xu * timer wrapping. 2102871f5650SGuodong Xu * in case of multiple timer wrapping, either it can be 2103871f5650SGuodong Xu * detected by out-of-range remaining, or it cannot be 2104871f5650SGuodong Xu * detected and we gets a panelty of 2105871f5650SGuodong Xu * _regulator_enable_delay(). 2106871f5650SGuodong Xu */ 2107871f5650SGuodong Xu remaining = intended - start_jiffy; 2108871f5650SGuodong Xu if (remaining <= max_delay) 2109871f5650SGuodong Xu _regulator_enable_delay( 2110871f5650SGuodong Xu jiffies_to_usecs(remaining)); 2111871f5650SGuodong Xu } 2112871f5650SGuodong Xu } 2113871f5650SGuodong Xu 2114414c70cbSLiam Girdwood if (rdev->ena_pin) { 211529d62ec5SDoug Anderson if (!rdev->ena_gpio_state) { 21169a2372faSMark Brown ret = regulator_ena_gpio_ctrl(rdev, true); 2117414c70cbSLiam Girdwood if (ret < 0) 2118414c70cbSLiam Girdwood return ret; 21199a2372faSMark Brown rdev->ena_gpio_state = 1; 212029d62ec5SDoug Anderson } 21219a2372faSMark Brown } else if (rdev->desc->ops->enable) { 21229a2372faSMark Brown ret = rdev->desc->ops->enable(rdev); 21239a2372faSMark Brown if (ret < 0) 21249a2372faSMark Brown return ret; 21259a2372faSMark Brown } else { 21269a2372faSMark Brown return -EINVAL; 21275c5659d0SMark Brown } 21289a2372faSMark Brown 21299a2372faSMark Brown /* Allow the regulator to ramp; it would be useful to extend 213031aae2beSMark Brown * this for bulk operations so that the regulators can ramp 2131a7433cffSLinus Walleij * together. */ 21325da84fd9SJoe Perches trace_regulator_enable_delay(rdev_get_name(rdev)); 2133414c70cbSLiam Girdwood 213479fd1141SGuodong Xu _regulator_enable_delay(delay); 2135a7433cffSLinus Walleij 2136414c70cbSLiam Girdwood trace_regulator_enable_complete(rdev_get_name(rdev)); 2137414c70cbSLiam Girdwood 21389a2372faSMark Brown return 0; 21399a2372faSMark Brown } 21409a2372faSMark Brown 2141414c70cbSLiam Girdwood /* locks held by regulator_enable() */ 2142414c70cbSLiam Girdwood static int _regulator_enable(struct regulator_dev *rdev) 2143414c70cbSLiam Girdwood { 2144414c70cbSLiam Girdwood int ret; 2145414c70cbSLiam Girdwood 214670cfef26SKrzysztof Kozlowski lockdep_assert_held_once(&rdev->mutex); 214770cfef26SKrzysztof Kozlowski 2148414c70cbSLiam Girdwood /* check voltage and requested load before enabling */ 21498a34e979SWEN Pingbo if (regulator_ops_is_valid(rdev, REGULATOR_CHANGE_DRMS)) 2150cf7bbcdfSMark Brown drms_uA_update(rdev); 2151cf7bbcdfSMark Brown 2152414c70cbSLiam Girdwood if (rdev->use_count == 0) { 2153cf7bbcdfSMark Brown /* The regulator may on if it's not switchable or left on */ 2154414c70cbSLiam Girdwood ret = _regulator_is_enabled(rdev); 2155414c70cbSLiam Girdwood if (ret == -EINVAL || ret == 0) { 21568a34e979SWEN Pingbo if (!regulator_ops_is_valid(rdev, 21578a34e979SWEN Pingbo REGULATOR_CHANGE_STATUS)) 2158412aec61SDavid Brownell return -EPERM; 2159412aec61SDavid Brownell 2160414c70cbSLiam Girdwood ret = _regulator_do_enable(rdev); 2161412aec61SDavid Brownell if (ret < 0) 2162412aec61SDavid Brownell return ret; 2163412aec61SDavid Brownell 2164264b88c9SHarald Geyer _notifier_call_chain(rdev, REGULATOR_EVENT_ENABLE, 2165264b88c9SHarald Geyer NULL); 2166414c70cbSLiam Girdwood } else if (ret < 0) { 2167414c70cbSLiam Girdwood rdev_err(rdev, "is_enabled() failed: %d\n", ret); 2168414c70cbSLiam Girdwood return ret; 2169414c70cbSLiam Girdwood } 2170414c70cbSLiam Girdwood /* Fallthrough on positive return values - already enabled */ 2171414c70cbSLiam Girdwood } 2172414c70cbSLiam Girdwood 2173414c70cbSLiam Girdwood rdev->use_count++; 2174414c70cbSLiam Girdwood 2175414c70cbSLiam Girdwood return 0; 2176414c70cbSLiam Girdwood } 2177414c70cbSLiam Girdwood 2178414c70cbSLiam Girdwood /** 2179414c70cbSLiam Girdwood * regulator_enable - enable regulator output 2180414c70cbSLiam Girdwood * @regulator: regulator source 2181414c70cbSLiam Girdwood * 2182414c70cbSLiam Girdwood * Request that the regulator be enabled with the regulator output at 2183414c70cbSLiam Girdwood * the predefined voltage or current value. Calls to regulator_enable() 2184414c70cbSLiam Girdwood * must be balanced with calls to regulator_disable(). 2185414c70cbSLiam Girdwood * 2186414c70cbSLiam Girdwood * NOTE: the output value can be set by other drivers, boot loader or may be 2187414c70cbSLiam Girdwood * hardwired in the regulator. 2188414c70cbSLiam Girdwood */ 2189414c70cbSLiam Girdwood int regulator_enable(struct regulator *regulator) 2190414c70cbSLiam Girdwood { 2191414c70cbSLiam Girdwood struct regulator_dev *rdev = regulator->rdev; 2192414c70cbSLiam Girdwood int ret = 0; 2193414c70cbSLiam Girdwood 21946492bc1bSMark Brown if (regulator->always_on) 21956492bc1bSMark Brown return 0; 21966492bc1bSMark Brown 21973801b86aSMark Brown if (rdev->supply) { 21983801b86aSMark Brown ret = regulator_enable(rdev->supply); 21993801b86aSMark Brown if (ret != 0) 22003801b86aSMark Brown return ret; 22013801b86aSMark Brown } 22023801b86aSMark Brown 2203414c70cbSLiam Girdwood mutex_lock(&rdev->mutex); 2204414c70cbSLiam Girdwood ret = _regulator_enable(rdev); 2205414c70cbSLiam Girdwood mutex_unlock(&rdev->mutex); 22063801b86aSMark Brown 2207d1685e4eSHeiko Stübner if (ret != 0 && rdev->supply) 22083801b86aSMark Brown regulator_disable(rdev->supply); 22093801b86aSMark Brown 2210414c70cbSLiam Girdwood return ret; 2211414c70cbSLiam Girdwood } 2212414c70cbSLiam Girdwood EXPORT_SYMBOL_GPL(regulator_enable); 2213414c70cbSLiam Girdwood 22145c5659d0SMark Brown static int _regulator_do_disable(struct regulator_dev *rdev) 22155c5659d0SMark Brown { 22165c5659d0SMark Brown int ret; 22175c5659d0SMark Brown 22185c5659d0SMark Brown trace_regulator_disable(rdev_get_name(rdev)); 22195c5659d0SMark Brown 2220967cfb18SKim, Milo if (rdev->ena_pin) { 222129d62ec5SDoug Anderson if (rdev->ena_gpio_state) { 2222967cfb18SKim, Milo ret = regulator_ena_gpio_ctrl(rdev, false); 2223967cfb18SKim, Milo if (ret < 0) 2224967cfb18SKim, Milo return ret; 22255c5659d0SMark Brown rdev->ena_gpio_state = 0; 222629d62ec5SDoug Anderson } 22275c5659d0SMark Brown 22285c5659d0SMark Brown } else if (rdev->desc->ops->disable) { 22295c5659d0SMark Brown ret = rdev->desc->ops->disable(rdev); 22305c5659d0SMark Brown if (ret != 0) 22315c5659d0SMark Brown return ret; 22325c5659d0SMark Brown } 22335c5659d0SMark Brown 2234871f5650SGuodong Xu /* cares about last_off_jiffy only if off_on_delay is required by 2235871f5650SGuodong Xu * device. 2236871f5650SGuodong Xu */ 2237871f5650SGuodong Xu if (rdev->desc->off_on_delay) 2238871f5650SGuodong Xu rdev->last_off_jiffy = jiffies; 2239871f5650SGuodong Xu 22405c5659d0SMark Brown trace_regulator_disable_complete(rdev_get_name(rdev)); 22415c5659d0SMark Brown 22425c5659d0SMark Brown return 0; 22435c5659d0SMark Brown } 22445c5659d0SMark Brown 2245414c70cbSLiam Girdwood /* locks held by regulator_disable() */ 22463801b86aSMark Brown static int _regulator_disable(struct regulator_dev *rdev) 2247414c70cbSLiam Girdwood { 2248414c70cbSLiam Girdwood int ret = 0; 2249414c70cbSLiam Girdwood 225070cfef26SKrzysztof Kozlowski lockdep_assert_held_once(&rdev->mutex); 225170cfef26SKrzysztof Kozlowski 2252cd94b505SDavid Brownell if (WARN(rdev->use_count <= 0, 225343e7ee33SJoe Perches "unbalanced disables for %s\n", rdev_get_name(rdev))) 2254cd94b505SDavid Brownell return -EIO; 2255cd94b505SDavid Brownell 2256414c70cbSLiam Girdwood /* are we the last user and permitted to disable ? */ 225760ef66fcSMark Brown if (rdev->use_count == 1 && 225860ef66fcSMark Brown (rdev->constraints && !rdev->constraints->always_on)) { 2259414c70cbSLiam Girdwood 2260414c70cbSLiam Girdwood /* we are last user */ 22618a34e979SWEN Pingbo if (regulator_ops_is_valid(rdev, REGULATOR_CHANGE_STATUS)) { 2262a1c8a551SRichard Fitzgerald ret = _notifier_call_chain(rdev, 2263a1c8a551SRichard Fitzgerald REGULATOR_EVENT_PRE_DISABLE, 2264a1c8a551SRichard Fitzgerald NULL); 2265a1c8a551SRichard Fitzgerald if (ret & NOTIFY_STOP_MASK) 2266a1c8a551SRichard Fitzgerald return -EINVAL; 2267a1c8a551SRichard Fitzgerald 22685c5659d0SMark Brown ret = _regulator_do_disable(rdev); 2269414c70cbSLiam Girdwood if (ret < 0) { 22705da84fd9SJoe Perches rdev_err(rdev, "failed to disable\n"); 2271a1c8a551SRichard Fitzgerald _notifier_call_chain(rdev, 2272a1c8a551SRichard Fitzgerald REGULATOR_EVENT_ABORT_DISABLE, 2273a1c8a551SRichard Fitzgerald NULL); 2274414c70cbSLiam Girdwood return ret; 2275414c70cbSLiam Girdwood } 227666fda75fSMarkus Pargmann _notifier_call_chain(rdev, REGULATOR_EVENT_DISABLE, 227766fda75fSMarkus Pargmann NULL); 2278414c70cbSLiam Girdwood } 2279414c70cbSLiam Girdwood 2280414c70cbSLiam Girdwood rdev->use_count = 0; 2281414c70cbSLiam Girdwood } else if (rdev->use_count > 1) { 22828a34e979SWEN Pingbo if (regulator_ops_is_valid(rdev, REGULATOR_CHANGE_DRMS)) 2283414c70cbSLiam Girdwood drms_uA_update(rdev); 2284414c70cbSLiam Girdwood 2285414c70cbSLiam Girdwood rdev->use_count--; 2286414c70cbSLiam Girdwood } 22873801b86aSMark Brown 2288414c70cbSLiam Girdwood return ret; 2289414c70cbSLiam Girdwood } 2290414c70cbSLiam Girdwood 2291414c70cbSLiam Girdwood /** 2292414c70cbSLiam Girdwood * regulator_disable - disable regulator output 2293414c70cbSLiam Girdwood * @regulator: regulator source 2294414c70cbSLiam Girdwood * 2295cf7bbcdfSMark Brown * Disable the regulator output voltage or current. Calls to 2296cf7bbcdfSMark Brown * regulator_enable() must be balanced with calls to 2297cf7bbcdfSMark Brown * regulator_disable(). 229869279fb9SMark Brown * 2299414c70cbSLiam Girdwood * NOTE: this will only disable the regulator output if no other consumer 2300cf7bbcdfSMark Brown * devices have it enabled, the regulator device supports disabling and 2301cf7bbcdfSMark Brown * machine constraints permit this operation. 2302414c70cbSLiam Girdwood */ 2303414c70cbSLiam Girdwood int regulator_disable(struct regulator *regulator) 2304414c70cbSLiam Girdwood { 2305412aec61SDavid Brownell struct regulator_dev *rdev = regulator->rdev; 2306412aec61SDavid Brownell int ret = 0; 2307414c70cbSLiam Girdwood 23086492bc1bSMark Brown if (regulator->always_on) 23096492bc1bSMark Brown return 0; 23106492bc1bSMark Brown 2311412aec61SDavid Brownell mutex_lock(&rdev->mutex); 23123801b86aSMark Brown ret = _regulator_disable(rdev); 2313412aec61SDavid Brownell mutex_unlock(&rdev->mutex); 23148cbf811dSJeffrey Carlyle 23153801b86aSMark Brown if (ret == 0 && rdev->supply) 23163801b86aSMark Brown regulator_disable(rdev->supply); 23178cbf811dSJeffrey Carlyle 2318414c70cbSLiam Girdwood return ret; 2319414c70cbSLiam Girdwood } 2320414c70cbSLiam Girdwood EXPORT_SYMBOL_GPL(regulator_disable); 2321414c70cbSLiam Girdwood 2322414c70cbSLiam Girdwood /* locks held by regulator_force_disable() */ 23233801b86aSMark Brown static int _regulator_force_disable(struct regulator_dev *rdev) 2324414c70cbSLiam Girdwood { 2325414c70cbSLiam Girdwood int ret = 0; 2326414c70cbSLiam Girdwood 232770cfef26SKrzysztof Kozlowski lockdep_assert_held_once(&rdev->mutex); 232870cfef26SKrzysztof Kozlowski 2329a1c8a551SRichard Fitzgerald ret = _notifier_call_chain(rdev, REGULATOR_EVENT_FORCE_DISABLE | 2330a1c8a551SRichard Fitzgerald REGULATOR_EVENT_PRE_DISABLE, NULL); 2331a1c8a551SRichard Fitzgerald if (ret & NOTIFY_STOP_MASK) 2332a1c8a551SRichard Fitzgerald return -EINVAL; 2333a1c8a551SRichard Fitzgerald 233466fda75fSMarkus Pargmann ret = _regulator_do_disable(rdev); 2335414c70cbSLiam Girdwood if (ret < 0) { 23365da84fd9SJoe Perches rdev_err(rdev, "failed to force disable\n"); 2337a1c8a551SRichard Fitzgerald _notifier_call_chain(rdev, REGULATOR_EVENT_FORCE_DISABLE | 2338a1c8a551SRichard Fitzgerald REGULATOR_EVENT_ABORT_DISABLE, NULL); 2339414c70cbSLiam Girdwood return ret; 2340414c70cbSLiam Girdwood } 234166fda75fSMarkus Pargmann 234284b68263SMark Brown _notifier_call_chain(rdev, REGULATOR_EVENT_FORCE_DISABLE | 234384b68263SMark Brown REGULATOR_EVENT_DISABLE, NULL); 2344414c70cbSLiam Girdwood 234566fda75fSMarkus Pargmann return 0; 2346414c70cbSLiam Girdwood } 2347414c70cbSLiam Girdwood 2348414c70cbSLiam Girdwood /** 2349414c70cbSLiam Girdwood * regulator_force_disable - force disable regulator output 2350414c70cbSLiam Girdwood * @regulator: regulator source 2351414c70cbSLiam Girdwood * 2352414c70cbSLiam Girdwood * Forcibly disable the regulator output voltage or current. 2353414c70cbSLiam Girdwood * NOTE: this *will* disable the regulator output even if other consumer 2354414c70cbSLiam Girdwood * devices have it enabled. This should be used for situations when device 2355414c70cbSLiam Girdwood * damage will likely occur if the regulator is not disabled (e.g. over temp). 2356414c70cbSLiam Girdwood */ 2357414c70cbSLiam Girdwood int regulator_force_disable(struct regulator *regulator) 2358414c70cbSLiam Girdwood { 235982d15839SMark Brown struct regulator_dev *rdev = regulator->rdev; 2360414c70cbSLiam Girdwood int ret; 2361414c70cbSLiam Girdwood 236282d15839SMark Brown mutex_lock(&rdev->mutex); 2363414c70cbSLiam Girdwood regulator->uA_load = 0; 23643801b86aSMark Brown ret = _regulator_force_disable(regulator->rdev); 236582d15839SMark Brown mutex_unlock(&rdev->mutex); 23668cbf811dSJeffrey Carlyle 23673801b86aSMark Brown if (rdev->supply) 23683801b86aSMark Brown while (rdev->open_count--) 23693801b86aSMark Brown regulator_disable(rdev->supply); 23708cbf811dSJeffrey Carlyle 2371414c70cbSLiam Girdwood return ret; 2372414c70cbSLiam Girdwood } 2373414c70cbSLiam Girdwood EXPORT_SYMBOL_GPL(regulator_force_disable); 2374414c70cbSLiam Girdwood 2375da07ecd9SMark Brown static void regulator_disable_work(struct work_struct *work) 2376da07ecd9SMark Brown { 2377da07ecd9SMark Brown struct regulator_dev *rdev = container_of(work, struct regulator_dev, 2378da07ecd9SMark Brown disable_work.work); 2379da07ecd9SMark Brown int count, i, ret; 2380da07ecd9SMark Brown 2381da07ecd9SMark Brown mutex_lock(&rdev->mutex); 2382da07ecd9SMark Brown 2383da07ecd9SMark Brown BUG_ON(!rdev->deferred_disables); 2384da07ecd9SMark Brown 2385da07ecd9SMark Brown count = rdev->deferred_disables; 2386da07ecd9SMark Brown rdev->deferred_disables = 0; 2387da07ecd9SMark Brown 2388c9ccaa0cSTirupathi Reddy /* 2389c9ccaa0cSTirupathi Reddy * Workqueue functions queue the new work instance while the previous 2390c9ccaa0cSTirupathi Reddy * work instance is being processed. Cancel the queued work instance 2391c9ccaa0cSTirupathi Reddy * as the work instance under processing does the job of the queued 2392c9ccaa0cSTirupathi Reddy * work instance. 2393c9ccaa0cSTirupathi Reddy */ 2394c9ccaa0cSTirupathi Reddy cancel_delayed_work(&rdev->disable_work); 2395c9ccaa0cSTirupathi Reddy 2396da07ecd9SMark Brown for (i = 0; i < count; i++) { 2397da07ecd9SMark Brown ret = _regulator_disable(rdev); 2398da07ecd9SMark Brown if (ret != 0) 2399da07ecd9SMark Brown rdev_err(rdev, "Deferred disable failed: %d\n", ret); 2400da07ecd9SMark Brown } 2401da07ecd9SMark Brown 2402da07ecd9SMark Brown mutex_unlock(&rdev->mutex); 2403da07ecd9SMark Brown 2404da07ecd9SMark Brown if (rdev->supply) { 2405da07ecd9SMark Brown for (i = 0; i < count; i++) { 2406da07ecd9SMark Brown ret = regulator_disable(rdev->supply); 2407da07ecd9SMark Brown if (ret != 0) { 2408da07ecd9SMark Brown rdev_err(rdev, 2409da07ecd9SMark Brown "Supply disable failed: %d\n", ret); 2410da07ecd9SMark Brown } 2411da07ecd9SMark Brown } 2412da07ecd9SMark Brown } 2413da07ecd9SMark Brown } 2414da07ecd9SMark Brown 2415da07ecd9SMark Brown /** 2416da07ecd9SMark Brown * regulator_disable_deferred - disable regulator output with delay 2417da07ecd9SMark Brown * @regulator: regulator source 2418da07ecd9SMark Brown * @ms: miliseconds until the regulator is disabled 2419da07ecd9SMark Brown * 2420da07ecd9SMark Brown * Execute regulator_disable() on the regulator after a delay. This 2421da07ecd9SMark Brown * is intended for use with devices that require some time to quiesce. 2422da07ecd9SMark Brown * 2423da07ecd9SMark Brown * NOTE: this will only disable the regulator output if no other consumer 2424da07ecd9SMark Brown * devices have it enabled, the regulator device supports disabling and 2425da07ecd9SMark Brown * machine constraints permit this operation. 2426da07ecd9SMark Brown */ 2427da07ecd9SMark Brown int regulator_disable_deferred(struct regulator *regulator, int ms) 2428da07ecd9SMark Brown { 2429da07ecd9SMark Brown struct regulator_dev *rdev = regulator->rdev; 2430da07ecd9SMark Brown 24316492bc1bSMark Brown if (regulator->always_on) 24326492bc1bSMark Brown return 0; 24336492bc1bSMark Brown 24342b5a24a0SMark Brown if (!ms) 24352b5a24a0SMark Brown return regulator_disable(regulator); 24362b5a24a0SMark Brown 2437da07ecd9SMark Brown mutex_lock(&rdev->mutex); 2438da07ecd9SMark Brown rdev->deferred_disables++; 2439c9ccaa0cSTirupathi Reddy mod_delayed_work(system_power_efficient_wq, &rdev->disable_work, 2440c9ccaa0cSTirupathi Reddy msecs_to_jiffies(ms)); 2441da07ecd9SMark Brown mutex_unlock(&rdev->mutex); 2442da07ecd9SMark Brown 2443aa59802dSMark Brown return 0; 2444da07ecd9SMark Brown } 2445da07ecd9SMark Brown EXPORT_SYMBOL_GPL(regulator_disable_deferred); 2446da07ecd9SMark Brown 2447414c70cbSLiam Girdwood static int _regulator_is_enabled(struct regulator_dev *rdev) 2448414c70cbSLiam Girdwood { 244965f73508SMark Brown /* A GPIO control always takes precedence */ 24507b74d149SKim, Milo if (rdev->ena_pin) 245165f73508SMark Brown return rdev->ena_gpio_state; 245265f73508SMark Brown 24539a7f6a4cSMark Brown /* If we don't know then assume that the regulator is always on */ 24549332546fSMark Brown if (!rdev->desc->ops->is_enabled) 24559a7f6a4cSMark Brown return 1; 2456414c70cbSLiam Girdwood 24579332546fSMark Brown return rdev->desc->ops->is_enabled(rdev); 2458414c70cbSLiam Girdwood } 2459414c70cbSLiam Girdwood 24603d67fe95SMaciej Purski static int _regulator_list_voltage(struct regulator_dev *rdev, 24613a40cfc3SSascha Hauer unsigned selector, int lock) 24623a40cfc3SSascha Hauer { 24633a40cfc3SSascha Hauer const struct regulator_ops *ops = rdev->desc->ops; 24643a40cfc3SSascha Hauer int ret; 24653a40cfc3SSascha Hauer 24663a40cfc3SSascha Hauer if (rdev->desc->fixed_uV && rdev->desc->n_voltages == 1 && !selector) 24673a40cfc3SSascha Hauer return rdev->desc->fixed_uV; 24683a40cfc3SSascha Hauer 24693a40cfc3SSascha Hauer if (ops->list_voltage) { 24703a40cfc3SSascha Hauer if (selector >= rdev->desc->n_voltages) 24713a40cfc3SSascha Hauer return -EINVAL; 24723a40cfc3SSascha Hauer if (lock) 24733a40cfc3SSascha Hauer mutex_lock(&rdev->mutex); 24743a40cfc3SSascha Hauer ret = ops->list_voltage(rdev, selector); 24753a40cfc3SSascha Hauer if (lock) 24763a40cfc3SSascha Hauer mutex_unlock(&rdev->mutex); 2477fd086045SMatthias Kaehlcke } else if (rdev->is_switch && rdev->supply) { 24783d67fe95SMaciej Purski ret = _regulator_list_voltage(rdev->supply->rdev, 24793d67fe95SMaciej Purski selector, lock); 24803a40cfc3SSascha Hauer } else { 24813a40cfc3SSascha Hauer return -EINVAL; 24823a40cfc3SSascha Hauer } 24833a40cfc3SSascha Hauer 24843a40cfc3SSascha Hauer if (ret > 0) { 24853a40cfc3SSascha Hauer if (ret < rdev->constraints->min_uV) 24863a40cfc3SSascha Hauer ret = 0; 24873a40cfc3SSascha Hauer else if (ret > rdev->constraints->max_uV) 24883a40cfc3SSascha Hauer ret = 0; 24893a40cfc3SSascha Hauer } 24903a40cfc3SSascha Hauer 24913a40cfc3SSascha Hauer return ret; 24923a40cfc3SSascha Hauer } 24933a40cfc3SSascha Hauer 2494414c70cbSLiam Girdwood /** 2495414c70cbSLiam Girdwood * regulator_is_enabled - is the regulator output enabled 2496414c70cbSLiam Girdwood * @regulator: regulator source 2497414c70cbSLiam Girdwood * 2498412aec61SDavid Brownell * Returns positive if the regulator driver backing the source/client 2499412aec61SDavid Brownell * has requested that the device be enabled, zero if it hasn't, else a 2500412aec61SDavid Brownell * negative errno code. 2501412aec61SDavid Brownell * 2502412aec61SDavid Brownell * Note that the device backing this regulator handle can have multiple 2503412aec61SDavid Brownell * users, so it might be enabled even if regulator_enable() was never 2504412aec61SDavid Brownell * called for this particular source. 2505414c70cbSLiam Girdwood */ 2506414c70cbSLiam Girdwood int regulator_is_enabled(struct regulator *regulator) 2507414c70cbSLiam Girdwood { 25089332546fSMark Brown int ret; 25099332546fSMark Brown 25106492bc1bSMark Brown if (regulator->always_on) 25116492bc1bSMark Brown return 1; 25126492bc1bSMark Brown 25139332546fSMark Brown mutex_lock(®ulator->rdev->mutex); 25149332546fSMark Brown ret = _regulator_is_enabled(regulator->rdev); 25159332546fSMark Brown mutex_unlock(®ulator->rdev->mutex); 25169332546fSMark Brown 25179332546fSMark Brown return ret; 2518414c70cbSLiam Girdwood } 2519414c70cbSLiam Girdwood EXPORT_SYMBOL_GPL(regulator_is_enabled); 2520414c70cbSLiam Girdwood 2521414c70cbSLiam Girdwood /** 25224367cfdcSDavid Brownell * regulator_count_voltages - count regulator_list_voltage() selectors 25234367cfdcSDavid Brownell * @regulator: regulator source 25244367cfdcSDavid Brownell * 25254367cfdcSDavid Brownell * Returns number of selectors, or negative errno. Selectors are 25264367cfdcSDavid Brownell * numbered starting at zero, and typically correspond to bitfields 25274367cfdcSDavid Brownell * in hardware registers. 25284367cfdcSDavid Brownell */ 25294367cfdcSDavid Brownell int regulator_count_voltages(struct regulator *regulator) 25304367cfdcSDavid Brownell { 25314367cfdcSDavid Brownell struct regulator_dev *rdev = regulator->rdev; 25324367cfdcSDavid Brownell 253326988efeSJavier Martinez Canillas if (rdev->desc->n_voltages) 253426988efeSJavier Martinez Canillas return rdev->desc->n_voltages; 253526988efeSJavier Martinez Canillas 2536fd086045SMatthias Kaehlcke if (!rdev->is_switch || !rdev->supply) 253726988efeSJavier Martinez Canillas return -EINVAL; 253826988efeSJavier Martinez Canillas 253926988efeSJavier Martinez Canillas return regulator_count_voltages(rdev->supply); 25404367cfdcSDavid Brownell } 25414367cfdcSDavid Brownell EXPORT_SYMBOL_GPL(regulator_count_voltages); 25424367cfdcSDavid Brownell 25434367cfdcSDavid Brownell /** 25444367cfdcSDavid Brownell * regulator_list_voltage - enumerate supported voltages 25454367cfdcSDavid Brownell * @regulator: regulator source 25464367cfdcSDavid Brownell * @selector: identify voltage to list 25474367cfdcSDavid Brownell * Context: can sleep 25484367cfdcSDavid Brownell * 25494367cfdcSDavid Brownell * Returns a voltage that can be passed to @regulator_set_voltage(), 255088393161SThomas Weber * zero if this selector code can't be used on this system, or a 25514367cfdcSDavid Brownell * negative errno. 25524367cfdcSDavid Brownell */ 25534367cfdcSDavid Brownell int regulator_list_voltage(struct regulator *regulator, unsigned selector) 25544367cfdcSDavid Brownell { 25553d67fe95SMaciej Purski return _regulator_list_voltage(regulator->rdev, selector, 1); 25564367cfdcSDavid Brownell } 25574367cfdcSDavid Brownell EXPORT_SYMBOL_GPL(regulator_list_voltage); 25584367cfdcSDavid Brownell 25594367cfdcSDavid Brownell /** 256004eca28cSTuomas Tynkkynen * regulator_get_regmap - get the regulator's register map 256104eca28cSTuomas Tynkkynen * @regulator: regulator source 256204eca28cSTuomas Tynkkynen * 256304eca28cSTuomas Tynkkynen * Returns the register map for the given regulator, or an ERR_PTR value 256404eca28cSTuomas Tynkkynen * if the regulator doesn't use regmap. 256504eca28cSTuomas Tynkkynen */ 256604eca28cSTuomas Tynkkynen struct regmap *regulator_get_regmap(struct regulator *regulator) 256704eca28cSTuomas Tynkkynen { 256804eca28cSTuomas Tynkkynen struct regmap *map = regulator->rdev->regmap; 256904eca28cSTuomas Tynkkynen 257004eca28cSTuomas Tynkkynen return map ? map : ERR_PTR(-EOPNOTSUPP); 257104eca28cSTuomas Tynkkynen } 257204eca28cSTuomas Tynkkynen 257304eca28cSTuomas Tynkkynen /** 257404eca28cSTuomas Tynkkynen * regulator_get_hardware_vsel_register - get the HW voltage selector register 257504eca28cSTuomas Tynkkynen * @regulator: regulator source 257604eca28cSTuomas Tynkkynen * @vsel_reg: voltage selector register, output parameter 257704eca28cSTuomas Tynkkynen * @vsel_mask: mask for voltage selector bitfield, output parameter 257804eca28cSTuomas Tynkkynen * 257904eca28cSTuomas Tynkkynen * Returns the hardware register offset and bitmask used for setting the 258004eca28cSTuomas Tynkkynen * regulator voltage. This might be useful when configuring voltage-scaling 258104eca28cSTuomas Tynkkynen * hardware or firmware that can make I2C requests behind the kernel's back, 258204eca28cSTuomas Tynkkynen * for example. 258304eca28cSTuomas Tynkkynen * 258404eca28cSTuomas Tynkkynen * On success, the output parameters @vsel_reg and @vsel_mask are filled in 258504eca28cSTuomas Tynkkynen * and 0 is returned, otherwise a negative errno is returned. 258604eca28cSTuomas Tynkkynen */ 258704eca28cSTuomas Tynkkynen int regulator_get_hardware_vsel_register(struct regulator *regulator, 258804eca28cSTuomas Tynkkynen unsigned *vsel_reg, 258904eca28cSTuomas Tynkkynen unsigned *vsel_mask) 259004eca28cSTuomas Tynkkynen { 259104eca28cSTuomas Tynkkynen struct regulator_dev *rdev = regulator->rdev; 259239f5460dSGuodong Xu const struct regulator_ops *ops = rdev->desc->ops; 259304eca28cSTuomas Tynkkynen 259404eca28cSTuomas Tynkkynen if (ops->set_voltage_sel != regulator_set_voltage_sel_regmap) 259504eca28cSTuomas Tynkkynen return -EOPNOTSUPP; 259604eca28cSTuomas Tynkkynen 259704eca28cSTuomas Tynkkynen *vsel_reg = rdev->desc->vsel_reg; 259804eca28cSTuomas Tynkkynen *vsel_mask = rdev->desc->vsel_mask; 259904eca28cSTuomas Tynkkynen 260004eca28cSTuomas Tynkkynen return 0; 260104eca28cSTuomas Tynkkynen } 260204eca28cSTuomas Tynkkynen EXPORT_SYMBOL_GPL(regulator_get_hardware_vsel_register); 260304eca28cSTuomas Tynkkynen 260404eca28cSTuomas Tynkkynen /** 260504eca28cSTuomas Tynkkynen * regulator_list_hardware_vsel - get the HW-specific register value for a selector 260604eca28cSTuomas Tynkkynen * @regulator: regulator source 260704eca28cSTuomas Tynkkynen * @selector: identify voltage to list 260804eca28cSTuomas Tynkkynen * 260904eca28cSTuomas Tynkkynen * Converts the selector to a hardware-specific voltage selector that can be 261004eca28cSTuomas Tynkkynen * directly written to the regulator registers. The address of the voltage 261104eca28cSTuomas Tynkkynen * register can be determined by calling @regulator_get_hardware_vsel_register. 261204eca28cSTuomas Tynkkynen * 261304eca28cSTuomas Tynkkynen * On error a negative errno is returned. 261404eca28cSTuomas Tynkkynen */ 261504eca28cSTuomas Tynkkynen int regulator_list_hardware_vsel(struct regulator *regulator, 261604eca28cSTuomas Tynkkynen unsigned selector) 261704eca28cSTuomas Tynkkynen { 261804eca28cSTuomas Tynkkynen struct regulator_dev *rdev = regulator->rdev; 261939f5460dSGuodong Xu const struct regulator_ops *ops = rdev->desc->ops; 262004eca28cSTuomas Tynkkynen 262104eca28cSTuomas Tynkkynen if (selector >= rdev->desc->n_voltages) 262204eca28cSTuomas Tynkkynen return -EINVAL; 262304eca28cSTuomas Tynkkynen if (ops->set_voltage_sel != regulator_set_voltage_sel_regmap) 262404eca28cSTuomas Tynkkynen return -EOPNOTSUPP; 262504eca28cSTuomas Tynkkynen 262604eca28cSTuomas Tynkkynen return selector; 262704eca28cSTuomas Tynkkynen } 262804eca28cSTuomas Tynkkynen EXPORT_SYMBOL_GPL(regulator_list_hardware_vsel); 262904eca28cSTuomas Tynkkynen 263004eca28cSTuomas Tynkkynen /** 26312a668a8bSPaul Walmsley * regulator_get_linear_step - return the voltage step size between VSEL values 26322a668a8bSPaul Walmsley * @regulator: regulator source 26332a668a8bSPaul Walmsley * 26342a668a8bSPaul Walmsley * Returns the voltage step size between VSEL values for linear 26352a668a8bSPaul Walmsley * regulators, or return 0 if the regulator isn't a linear regulator. 26362a668a8bSPaul Walmsley */ 26372a668a8bSPaul Walmsley unsigned int regulator_get_linear_step(struct regulator *regulator) 26382a668a8bSPaul Walmsley { 26392a668a8bSPaul Walmsley struct regulator_dev *rdev = regulator->rdev; 26402a668a8bSPaul Walmsley 26412a668a8bSPaul Walmsley return rdev->desc->uV_step; 26422a668a8bSPaul Walmsley } 26432a668a8bSPaul Walmsley EXPORT_SYMBOL_GPL(regulator_get_linear_step); 26442a668a8bSPaul Walmsley 26452a668a8bSPaul Walmsley /** 2646a7a1ad90SMark Brown * regulator_is_supported_voltage - check if a voltage range can be supported 2647a7a1ad90SMark Brown * 2648a7a1ad90SMark Brown * @regulator: Regulator to check. 2649a7a1ad90SMark Brown * @min_uV: Minimum required voltage in uV. 2650a7a1ad90SMark Brown * @max_uV: Maximum required voltage in uV. 2651a7a1ad90SMark Brown * 2652a7a1ad90SMark Brown * Returns a boolean or a negative error code. 2653a7a1ad90SMark Brown */ 2654a7a1ad90SMark Brown int regulator_is_supported_voltage(struct regulator *regulator, 2655a7a1ad90SMark Brown int min_uV, int max_uV) 2656a7a1ad90SMark Brown { 2657c5f3939bSMark Brown struct regulator_dev *rdev = regulator->rdev; 2658a7a1ad90SMark Brown int i, voltages, ret; 2659a7a1ad90SMark Brown 2660c5f3939bSMark Brown /* If we can't change voltage check the current voltage */ 26618a34e979SWEN Pingbo if (!regulator_ops_is_valid(rdev, REGULATOR_CHANGE_VOLTAGE)) { 2662c5f3939bSMark Brown ret = regulator_get_voltage(regulator); 2663c5f3939bSMark Brown if (ret >= 0) 26640d25d09dSJingoo Han return min_uV <= ret && ret <= max_uV; 2665c5f3939bSMark Brown else 2666c5f3939bSMark Brown return ret; 2667c5f3939bSMark Brown } 2668c5f3939bSMark Brown 2669bd7a2b60SPawel Moll /* Any voltage within constrains range is fine? */ 2670bd7a2b60SPawel Moll if (rdev->desc->continuous_voltage_range) 2671bd7a2b60SPawel Moll return min_uV >= rdev->constraints->min_uV && 2672bd7a2b60SPawel Moll max_uV <= rdev->constraints->max_uV; 2673bd7a2b60SPawel Moll 2674a7a1ad90SMark Brown ret = regulator_count_voltages(regulator); 2675a7a1ad90SMark Brown if (ret < 0) 2676a7a1ad90SMark Brown return ret; 2677a7a1ad90SMark Brown voltages = ret; 2678a7a1ad90SMark Brown 2679a7a1ad90SMark Brown for (i = 0; i < voltages; i++) { 2680a7a1ad90SMark Brown ret = regulator_list_voltage(regulator, i); 2681a7a1ad90SMark Brown 2682a7a1ad90SMark Brown if (ret >= min_uV && ret <= max_uV) 2683a7a1ad90SMark Brown return 1; 2684a7a1ad90SMark Brown } 2685a7a1ad90SMark Brown 2686a7a1ad90SMark Brown return 0; 2687a7a1ad90SMark Brown } 2688a398eaa2SMark Brown EXPORT_SYMBOL_GPL(regulator_is_supported_voltage); 2689a7a1ad90SMark Brown 2690a204f41eSSascha Hauer static int regulator_map_voltage(struct regulator_dev *rdev, int min_uV, 2691a204f41eSSascha Hauer int max_uV) 2692a204f41eSSascha Hauer { 2693a204f41eSSascha Hauer const struct regulator_desc *desc = rdev->desc; 2694a204f41eSSascha Hauer 2695a204f41eSSascha Hauer if (desc->ops->map_voltage) 2696a204f41eSSascha Hauer return desc->ops->map_voltage(rdev, min_uV, max_uV); 2697a204f41eSSascha Hauer 2698a204f41eSSascha Hauer if (desc->ops->list_voltage == regulator_list_voltage_linear) 2699a204f41eSSascha Hauer return regulator_map_voltage_linear(rdev, min_uV, max_uV); 2700a204f41eSSascha Hauer 2701a204f41eSSascha Hauer if (desc->ops->list_voltage == regulator_list_voltage_linear_range) 2702a204f41eSSascha Hauer return regulator_map_voltage_linear_range(rdev, min_uV, max_uV); 2703a204f41eSSascha Hauer 2704a204f41eSSascha Hauer return regulator_map_voltage_iterate(rdev, min_uV, max_uV); 2705a204f41eSSascha Hauer } 2706a204f41eSSascha Hauer 27077179569aSHeiko Stübner static int _regulator_call_set_voltage(struct regulator_dev *rdev, 27087179569aSHeiko Stübner int min_uV, int max_uV, 27097179569aSHeiko Stübner unsigned *selector) 27107179569aSHeiko Stübner { 27117179569aSHeiko Stübner struct pre_voltage_change_data data; 27127179569aSHeiko Stübner int ret; 27137179569aSHeiko Stübner 27147179569aSHeiko Stübner data.old_uV = _regulator_get_voltage(rdev); 27157179569aSHeiko Stübner data.min_uV = min_uV; 27167179569aSHeiko Stübner data.max_uV = max_uV; 27177179569aSHeiko Stübner ret = _notifier_call_chain(rdev, REGULATOR_EVENT_PRE_VOLTAGE_CHANGE, 27187179569aSHeiko Stübner &data); 27197179569aSHeiko Stübner if (ret & NOTIFY_STOP_MASK) 27207179569aSHeiko Stübner return -EINVAL; 27217179569aSHeiko Stübner 27227179569aSHeiko Stübner ret = rdev->desc->ops->set_voltage(rdev, min_uV, max_uV, selector); 27237179569aSHeiko Stübner if (ret >= 0) 27247179569aSHeiko Stübner return ret; 27257179569aSHeiko Stübner 27267179569aSHeiko Stübner _notifier_call_chain(rdev, REGULATOR_EVENT_ABORT_VOLTAGE_CHANGE, 27277179569aSHeiko Stübner (void *)data.old_uV); 27287179569aSHeiko Stübner 27297179569aSHeiko Stübner return ret; 27307179569aSHeiko Stübner } 27317179569aSHeiko Stübner 27327179569aSHeiko Stübner static int _regulator_call_set_voltage_sel(struct regulator_dev *rdev, 27337179569aSHeiko Stübner int uV, unsigned selector) 27347179569aSHeiko Stübner { 27357179569aSHeiko Stübner struct pre_voltage_change_data data; 27367179569aSHeiko Stübner int ret; 27377179569aSHeiko Stübner 27387179569aSHeiko Stübner data.old_uV = _regulator_get_voltage(rdev); 27397179569aSHeiko Stübner data.min_uV = uV; 27407179569aSHeiko Stübner data.max_uV = uV; 27417179569aSHeiko Stübner ret = _notifier_call_chain(rdev, REGULATOR_EVENT_PRE_VOLTAGE_CHANGE, 27427179569aSHeiko Stübner &data); 27437179569aSHeiko Stübner if (ret & NOTIFY_STOP_MASK) 27447179569aSHeiko Stübner return -EINVAL; 27457179569aSHeiko Stübner 27467179569aSHeiko Stübner ret = rdev->desc->ops->set_voltage_sel(rdev, selector); 27477179569aSHeiko Stübner if (ret >= 0) 27487179569aSHeiko Stübner return ret; 27497179569aSHeiko Stübner 27507179569aSHeiko Stübner _notifier_call_chain(rdev, REGULATOR_EVENT_ABORT_VOLTAGE_CHANGE, 27517179569aSHeiko Stübner (void *)data.old_uV); 27527179569aSHeiko Stübner 27537179569aSHeiko Stübner return ret; 27547179569aSHeiko Stübner } 27557179569aSHeiko Stübner 275673e705bfSMatthias Kaehlcke static int _regulator_set_voltage_time(struct regulator_dev *rdev, 275773e705bfSMatthias Kaehlcke int old_uV, int new_uV) 275873e705bfSMatthias Kaehlcke { 275973e705bfSMatthias Kaehlcke unsigned int ramp_delay = 0; 276073e705bfSMatthias Kaehlcke 276173e705bfSMatthias Kaehlcke if (rdev->constraints->ramp_delay) 276273e705bfSMatthias Kaehlcke ramp_delay = rdev->constraints->ramp_delay; 276373e705bfSMatthias Kaehlcke else if (rdev->desc->ramp_delay) 276473e705bfSMatthias Kaehlcke ramp_delay = rdev->desc->ramp_delay; 2765d6c1dc3fSLaxman Dewangan else if (rdev->constraints->settling_time) 2766d6c1dc3fSLaxman Dewangan return rdev->constraints->settling_time; 27673ffad468SMatthias Kaehlcke else if (rdev->constraints->settling_time_up && 27683ffad468SMatthias Kaehlcke (new_uV > old_uV)) 27693ffad468SMatthias Kaehlcke return rdev->constraints->settling_time_up; 27703ffad468SMatthias Kaehlcke else if (rdev->constraints->settling_time_down && 27713ffad468SMatthias Kaehlcke (new_uV < old_uV)) 27723ffad468SMatthias Kaehlcke return rdev->constraints->settling_time_down; 277373e705bfSMatthias Kaehlcke 277473e705bfSMatthias Kaehlcke if (ramp_delay == 0) { 2775ba14fa1aSH. Nikolaus Schaller rdev_dbg(rdev, "ramp_delay not set\n"); 277673e705bfSMatthias Kaehlcke return 0; 277773e705bfSMatthias Kaehlcke } 277873e705bfSMatthias Kaehlcke 277973e705bfSMatthias Kaehlcke return DIV_ROUND_UP(abs(new_uV - old_uV), ramp_delay); 278073e705bfSMatthias Kaehlcke } 278173e705bfSMatthias Kaehlcke 278275790251SMark Brown static int _regulator_do_set_voltage(struct regulator_dev *rdev, 278375790251SMark Brown int min_uV, int max_uV) 278475790251SMark Brown { 278575790251SMark Brown int ret; 278677af1b26SLinus Walleij int delay = 0; 2787e113d792SMark Brown int best_val = 0; 278875790251SMark Brown unsigned int selector; 2789eba41a5eSAxel Lin int old_selector = -1; 279057995a48SMatthias Kaehlcke const struct regulator_ops *ops = rdev->desc->ops; 279173e705bfSMatthias Kaehlcke int old_uV = _regulator_get_voltage(rdev); 279275790251SMark Brown 279375790251SMark Brown trace_regulator_set_voltage(rdev_get_name(rdev), min_uV, max_uV); 279475790251SMark Brown 2795bf5892a8SMark Brown min_uV += rdev->constraints->uV_offset; 2796bf5892a8SMark Brown max_uV += rdev->constraints->uV_offset; 2797bf5892a8SMark Brown 279877af1b26SLinus Walleij /* 279977af1b26SLinus Walleij * If we can't obtain the old selector there is not enough 280077af1b26SLinus Walleij * info to call set_voltage_time_sel(). 280177af1b26SLinus Walleij */ 28028b7485efSAxel Lin if (_regulator_is_enabled(rdev) && 280357995a48SMatthias Kaehlcke ops->set_voltage_time_sel && ops->get_voltage_sel) { 280457995a48SMatthias Kaehlcke old_selector = ops->get_voltage_sel(rdev); 2805eba41a5eSAxel Lin if (old_selector < 0) 2806eba41a5eSAxel Lin return old_selector; 2807eba41a5eSAxel Lin } 280877af1b26SLinus Walleij 280957995a48SMatthias Kaehlcke if (ops->set_voltage) { 28107179569aSHeiko Stübner ret = _regulator_call_set_voltage(rdev, min_uV, max_uV, 281175790251SMark Brown &selector); 2812e113d792SMark Brown 2813e113d792SMark Brown if (ret >= 0) { 281457995a48SMatthias Kaehlcke if (ops->list_voltage) 281557995a48SMatthias Kaehlcke best_val = ops->list_voltage(rdev, 2816e113d792SMark Brown selector); 2817e113d792SMark Brown else 2818e113d792SMark Brown best_val = _regulator_get_voltage(rdev); 2819e113d792SMark Brown } 2820e113d792SMark Brown 282157995a48SMatthias Kaehlcke } else if (ops->set_voltage_sel) { 2822a204f41eSSascha Hauer ret = regulator_map_voltage(rdev, min_uV, max_uV); 2823e843fc46SMark Brown if (ret >= 0) { 282457995a48SMatthias Kaehlcke best_val = ops->list_voltage(rdev, ret); 2825e113d792SMark Brown if (min_uV <= best_val && max_uV >= best_val) { 2826e843fc46SMark Brown selector = ret; 2827c66a566aSAxel Lin if (old_selector == selector) 2828c66a566aSAxel Lin ret = 0; 2829c66a566aSAxel Lin else 28307179569aSHeiko Stübner ret = _regulator_call_set_voltage_sel( 28317179569aSHeiko Stübner rdev, best_val, selector); 2832e113d792SMark Brown } else { 2833e113d792SMark Brown ret = -EINVAL; 2834e113d792SMark Brown } 2835e843fc46SMark Brown } 2836e8eef82bSMark Brown } else { 2837e8eef82bSMark Brown ret = -EINVAL; 2838e8eef82bSMark Brown } 2839e8eef82bSMark Brown 284031dfe686SMatthias Kaehlcke if (ret) 284131dfe686SMatthias Kaehlcke goto out; 2842eba41a5eSAxel Lin 284373e705bfSMatthias Kaehlcke if (ops->set_voltage_time_sel) { 284473e705bfSMatthias Kaehlcke /* 284573e705bfSMatthias Kaehlcke * Call set_voltage_time_sel if successfully obtained 284673e705bfSMatthias Kaehlcke * old_selector 284773e705bfSMatthias Kaehlcke */ 284873e705bfSMatthias Kaehlcke if (old_selector >= 0 && old_selector != selector) 284973e705bfSMatthias Kaehlcke delay = ops->set_voltage_time_sel(rdev, old_selector, 285073e705bfSMatthias Kaehlcke selector); 285173e705bfSMatthias Kaehlcke } else { 285273e705bfSMatthias Kaehlcke if (old_uV != best_val) { 285373e705bfSMatthias Kaehlcke if (ops->set_voltage_time) 285473e705bfSMatthias Kaehlcke delay = ops->set_voltage_time(rdev, old_uV, 285573e705bfSMatthias Kaehlcke best_val); 285673e705bfSMatthias Kaehlcke else 285773e705bfSMatthias Kaehlcke delay = _regulator_set_voltage_time(rdev, 285873e705bfSMatthias Kaehlcke old_uV, 285973e705bfSMatthias Kaehlcke best_val); 286073e705bfSMatthias Kaehlcke } 286173e705bfSMatthias Kaehlcke } 286273e705bfSMatthias Kaehlcke 2863eba41a5eSAxel Lin if (delay < 0) { 286473e705bfSMatthias Kaehlcke rdev_warn(rdev, "failed to get delay: %d\n", delay); 2865eba41a5eSAxel Lin delay = 0; 2866e8eef82bSMark Brown } 286775790251SMark Brown 286877af1b26SLinus Walleij /* Insert any necessary delays */ 286977af1b26SLinus Walleij if (delay >= 1000) { 287077af1b26SLinus Walleij mdelay(delay / 1000); 287177af1b26SLinus Walleij udelay(delay % 1000); 287277af1b26SLinus Walleij } else if (delay) { 287377af1b26SLinus Walleij udelay(delay); 287477af1b26SLinus Walleij } 287577af1b26SLinus Walleij 287631dfe686SMatthias Kaehlcke if (best_val >= 0) { 28772f6c797fSAxel Lin unsigned long data = best_val; 28782f6c797fSAxel Lin 2879ded06a52SMark Brown _notifier_call_chain(rdev, REGULATOR_EVENT_VOLTAGE_CHANGE, 28802f6c797fSAxel Lin (void *)data); 28812f6c797fSAxel Lin } 2882ded06a52SMark Brown 288331dfe686SMatthias Kaehlcke out: 2884eba41a5eSAxel Lin trace_regulator_set_voltage_complete(rdev_get_name(rdev), best_val); 288575790251SMark Brown 288675790251SMark Brown return ret; 288775790251SMark Brown } 288875790251SMark Brown 2889f7efad10SChunyan Zhang static int _regulator_do_set_suspend_voltage(struct regulator_dev *rdev, 2890f7efad10SChunyan Zhang int min_uV, int max_uV, suspend_state_t state) 2891f7efad10SChunyan Zhang { 2892f7efad10SChunyan Zhang struct regulator_state *rstate; 2893f7efad10SChunyan Zhang int uV, sel; 2894f7efad10SChunyan Zhang 2895f7efad10SChunyan Zhang rstate = regulator_get_suspend_state(rdev, state); 2896f7efad10SChunyan Zhang if (rstate == NULL) 2897f7efad10SChunyan Zhang return -EINVAL; 2898f7efad10SChunyan Zhang 2899f7efad10SChunyan Zhang if (min_uV < rstate->min_uV) 2900f7efad10SChunyan Zhang min_uV = rstate->min_uV; 2901f7efad10SChunyan Zhang if (max_uV > rstate->max_uV) 2902f7efad10SChunyan Zhang max_uV = rstate->max_uV; 2903f7efad10SChunyan Zhang 2904f7efad10SChunyan Zhang sel = regulator_map_voltage(rdev, min_uV, max_uV); 2905f7efad10SChunyan Zhang if (sel < 0) 2906f7efad10SChunyan Zhang return sel; 2907f7efad10SChunyan Zhang 2908f7efad10SChunyan Zhang uV = rdev->desc->ops->list_voltage(rdev, sel); 2909f7efad10SChunyan Zhang if (uV >= min_uV && uV <= max_uV) 2910f7efad10SChunyan Zhang rstate->uV = uV; 2911f7efad10SChunyan Zhang 2912f7efad10SChunyan Zhang return 0; 2913f7efad10SChunyan Zhang } 2914f7efad10SChunyan Zhang 2915a9f226bcSSascha Hauer static int regulator_set_voltage_unlocked(struct regulator *regulator, 2916c360a6dfSChunyan Zhang int min_uV, int max_uV, 2917c360a6dfSChunyan Zhang suspend_state_t state) 2918414c70cbSLiam Girdwood { 2919414c70cbSLiam Girdwood struct regulator_dev *rdev = regulator->rdev; 2920c360a6dfSChunyan Zhang struct regulator_voltage *voltage = ®ulator->voltage[state]; 292195a3c23aSMark Brown int ret = 0; 292292d7a558SPaolo Pisati int old_min_uV, old_max_uV; 2923c00dc359SBjorn Andersson int current_uV; 2924fc42112cSSascha Hauer int best_supply_uV = 0; 2925fc42112cSSascha Hauer int supply_change_uV = 0; 2926414c70cbSLiam Girdwood 292795a3c23aSMark Brown /* If we're setting the same range as last time the change 292895a3c23aSMark Brown * should be a noop (some cpufreq implementations use the same 292995a3c23aSMark Brown * voltage for multiple frequencies, for example). 293095a3c23aSMark Brown */ 2931c360a6dfSChunyan Zhang if (voltage->min_uV == min_uV && voltage->max_uV == max_uV) 293295a3c23aSMark Brown goto out; 293395a3c23aSMark Brown 2934c00dc359SBjorn Andersson /* If we're trying to set a range that overlaps the current voltage, 2935d3fb9800SViresh Kumar * return successfully even though the regulator does not support 2936c00dc359SBjorn Andersson * changing the voltage. 2937c00dc359SBjorn Andersson */ 29388a34e979SWEN Pingbo if (!regulator_ops_is_valid(rdev, REGULATOR_CHANGE_VOLTAGE)) { 2939c00dc359SBjorn Andersson current_uV = _regulator_get_voltage(rdev); 2940c00dc359SBjorn Andersson if (min_uV <= current_uV && current_uV <= max_uV) { 2941c360a6dfSChunyan Zhang voltage->min_uV = min_uV; 2942c360a6dfSChunyan Zhang voltage->max_uV = max_uV; 2943c00dc359SBjorn Andersson goto out; 2944c00dc359SBjorn Andersson } 2945c00dc359SBjorn Andersson } 2946c00dc359SBjorn Andersson 2947414c70cbSLiam Girdwood /* sanity check */ 2948e8eef82bSMark Brown if (!rdev->desc->ops->set_voltage && 2949e8eef82bSMark Brown !rdev->desc->ops->set_voltage_sel) { 2950414c70cbSLiam Girdwood ret = -EINVAL; 2951414c70cbSLiam Girdwood goto out; 2952414c70cbSLiam Girdwood } 2953414c70cbSLiam Girdwood 2954414c70cbSLiam Girdwood /* constraints check */ 2955414c70cbSLiam Girdwood ret = regulator_check_voltage(rdev, &min_uV, &max_uV); 2956414c70cbSLiam Girdwood if (ret < 0) 2957414c70cbSLiam Girdwood goto out; 295892d7a558SPaolo Pisati 295992d7a558SPaolo Pisati /* restore original values in case of error */ 2960c360a6dfSChunyan Zhang old_min_uV = voltage->min_uV; 2961c360a6dfSChunyan Zhang old_max_uV = voltage->max_uV; 2962c360a6dfSChunyan Zhang voltage->min_uV = min_uV; 2963c360a6dfSChunyan Zhang voltage->max_uV = max_uV; 29643a93f2a9SMark Brown 2965c360a6dfSChunyan Zhang ret = regulator_check_consumers(rdev, &min_uV, &max_uV, state); 296605fda3b1SThomas Petazzoni if (ret < 0) 296792d7a558SPaolo Pisati goto out2; 296805fda3b1SThomas Petazzoni 296943fc99f2SMark Brown if (rdev->supply && 297043fc99f2SMark Brown regulator_ops_is_valid(rdev->supply->rdev, 297143fc99f2SMark Brown REGULATOR_CHANGE_VOLTAGE) && 29722c2874b1STirupathi Reddy (rdev->desc->min_dropout_uV || !(rdev->desc->ops->get_voltage || 29732c2874b1STirupathi Reddy rdev->desc->ops->get_voltage_sel))) { 2974fc42112cSSascha Hauer int current_supply_uV; 2975fc42112cSSascha Hauer int selector; 2976fc42112cSSascha Hauer 2977fc42112cSSascha Hauer selector = regulator_map_voltage(rdev, min_uV, max_uV); 2978fc42112cSSascha Hauer if (selector < 0) { 2979fc42112cSSascha Hauer ret = selector; 2980fc42112cSSascha Hauer goto out2; 2981fc42112cSSascha Hauer } 2982fc42112cSSascha Hauer 298300cb9f4fSMark Brown best_supply_uV = _regulator_list_voltage(rdev, selector, 0); 2984fc42112cSSascha Hauer if (best_supply_uV < 0) { 2985fc42112cSSascha Hauer ret = best_supply_uV; 2986fc42112cSSascha Hauer goto out2; 2987fc42112cSSascha Hauer } 2988fc42112cSSascha Hauer 2989fc42112cSSascha Hauer best_supply_uV += rdev->desc->min_dropout_uV; 2990fc42112cSSascha Hauer 2991fc42112cSSascha Hauer current_supply_uV = _regulator_get_voltage(rdev->supply->rdev); 2992fc42112cSSascha Hauer if (current_supply_uV < 0) { 2993fc42112cSSascha Hauer ret = current_supply_uV; 2994fc42112cSSascha Hauer goto out2; 2995fc42112cSSascha Hauer } 2996fc42112cSSascha Hauer 2997fc42112cSSascha Hauer supply_change_uV = best_supply_uV - current_supply_uV; 2998fc42112cSSascha Hauer } 2999fc42112cSSascha Hauer 3000fc42112cSSascha Hauer if (supply_change_uV > 0) { 3001fc42112cSSascha Hauer ret = regulator_set_voltage_unlocked(rdev->supply, 3002c360a6dfSChunyan Zhang best_supply_uV, INT_MAX, state); 3003fc42112cSSascha Hauer if (ret) { 3004fc42112cSSascha Hauer dev_err(&rdev->dev, "Failed to increase supply voltage: %d\n", 3005fc42112cSSascha Hauer ret); 3006fc42112cSSascha Hauer goto out2; 3007fc42112cSSascha Hauer } 3008fc42112cSSascha Hauer } 3009fc42112cSSascha Hauer 3010f7efad10SChunyan Zhang if (state == PM_SUSPEND_ON) 301175790251SMark Brown ret = _regulator_do_set_voltage(rdev, min_uV, max_uV); 3012f7efad10SChunyan Zhang else 3013f7efad10SChunyan Zhang ret = _regulator_do_set_suspend_voltage(rdev, min_uV, 3014f7efad10SChunyan Zhang max_uV, state); 301592d7a558SPaolo Pisati if (ret < 0) 301692d7a558SPaolo Pisati goto out2; 301702fa3ec0SMark Brown 3018fc42112cSSascha Hauer if (supply_change_uV < 0) { 3019fc42112cSSascha Hauer ret = regulator_set_voltage_unlocked(rdev->supply, 3020c360a6dfSChunyan Zhang best_supply_uV, INT_MAX, state); 3021fc42112cSSascha Hauer if (ret) 3022fc42112cSSascha Hauer dev_warn(&rdev->dev, "Failed to decrease supply voltage: %d\n", 3023fc42112cSSascha Hauer ret); 3024fc42112cSSascha Hauer /* No need to fail here */ 3025fc42112cSSascha Hauer ret = 0; 3026fc42112cSSascha Hauer } 3027fc42112cSSascha Hauer 3028414c70cbSLiam Girdwood out: 3029414c70cbSLiam Girdwood return ret; 303092d7a558SPaolo Pisati out2: 3031c360a6dfSChunyan Zhang voltage->min_uV = old_min_uV; 3032c360a6dfSChunyan Zhang voltage->max_uV = old_max_uV; 3033a9f226bcSSascha Hauer 3034a9f226bcSSascha Hauer return ret; 3035a9f226bcSSascha Hauer } 3036a9f226bcSSascha Hauer 3037a9f226bcSSascha Hauer /** 3038a9f226bcSSascha Hauer * regulator_set_voltage - set regulator output voltage 3039a9f226bcSSascha Hauer * @regulator: regulator source 3040a9f226bcSSascha Hauer * @min_uV: Minimum required voltage in uV 3041a9f226bcSSascha Hauer * @max_uV: Maximum acceptable voltage in uV 3042a9f226bcSSascha Hauer * 3043a9f226bcSSascha Hauer * Sets a voltage regulator to the desired output voltage. This can be set 3044a9f226bcSSascha Hauer * during any regulator state. IOW, regulator can be disabled or enabled. 3045a9f226bcSSascha Hauer * 3046a9f226bcSSascha Hauer * If the regulator is enabled then the voltage will change to the new value 3047a9f226bcSSascha Hauer * immediately otherwise if the regulator is disabled the regulator will 3048a9f226bcSSascha Hauer * output at the new voltage when enabled. 3049a9f226bcSSascha Hauer * 3050a9f226bcSSascha Hauer * NOTE: If the regulator is shared between several devices then the lowest 3051a9f226bcSSascha Hauer * request voltage that meets the system constraints will be used. 3052a9f226bcSSascha Hauer * Regulator system constraints must be set for this regulator before 3053a9f226bcSSascha Hauer * calling this function otherwise this call will fail. 3054a9f226bcSSascha Hauer */ 3055a9f226bcSSascha Hauer int regulator_set_voltage(struct regulator *regulator, int min_uV, int max_uV) 3056a9f226bcSSascha Hauer { 3057a9f226bcSSascha Hauer int ret = 0; 3058a9f226bcSSascha Hauer 3059fc42112cSSascha Hauer regulator_lock_supply(regulator->rdev); 3060a9f226bcSSascha Hauer 3061c360a6dfSChunyan Zhang ret = regulator_set_voltage_unlocked(regulator, min_uV, max_uV, 3062c360a6dfSChunyan Zhang PM_SUSPEND_ON); 3063a9f226bcSSascha Hauer 3064fc42112cSSascha Hauer regulator_unlock_supply(regulator->rdev); 3065a9f226bcSSascha Hauer 306692d7a558SPaolo Pisati return ret; 3067414c70cbSLiam Girdwood } 3068414c70cbSLiam Girdwood EXPORT_SYMBOL_GPL(regulator_set_voltage); 3069414c70cbSLiam Girdwood 3070f7efad10SChunyan Zhang static inline int regulator_suspend_toggle(struct regulator_dev *rdev, 3071f7efad10SChunyan Zhang suspend_state_t state, bool en) 3072f7efad10SChunyan Zhang { 3073f7efad10SChunyan Zhang struct regulator_state *rstate; 3074f7efad10SChunyan Zhang 3075f7efad10SChunyan Zhang rstate = regulator_get_suspend_state(rdev, state); 3076f7efad10SChunyan Zhang if (rstate == NULL) 3077f7efad10SChunyan Zhang return -EINVAL; 3078f7efad10SChunyan Zhang 3079f7efad10SChunyan Zhang if (!rstate->changeable) 3080f7efad10SChunyan Zhang return -EPERM; 3081f7efad10SChunyan Zhang 3082f7efad10SChunyan Zhang rstate->enabled = en; 3083f7efad10SChunyan Zhang 3084f7efad10SChunyan Zhang return 0; 3085f7efad10SChunyan Zhang } 3086f7efad10SChunyan Zhang 3087f7efad10SChunyan Zhang int regulator_suspend_enable(struct regulator_dev *rdev, 3088f7efad10SChunyan Zhang suspend_state_t state) 3089f7efad10SChunyan Zhang { 3090f7efad10SChunyan Zhang return regulator_suspend_toggle(rdev, state, true); 3091f7efad10SChunyan Zhang } 3092f7efad10SChunyan Zhang EXPORT_SYMBOL_GPL(regulator_suspend_enable); 3093f7efad10SChunyan Zhang 3094f7efad10SChunyan Zhang int regulator_suspend_disable(struct regulator_dev *rdev, 3095f7efad10SChunyan Zhang suspend_state_t state) 3096f7efad10SChunyan Zhang { 3097f7efad10SChunyan Zhang struct regulator *regulator; 3098f7efad10SChunyan Zhang struct regulator_voltage *voltage; 3099f7efad10SChunyan Zhang 3100f7efad10SChunyan Zhang /* 3101f7efad10SChunyan Zhang * if any consumer wants this regulator device keeping on in 3102f7efad10SChunyan Zhang * suspend states, don't set it as disabled. 3103f7efad10SChunyan Zhang */ 3104f7efad10SChunyan Zhang list_for_each_entry(regulator, &rdev->consumer_list, list) { 3105f7efad10SChunyan Zhang voltage = ®ulator->voltage[state]; 3106f7efad10SChunyan Zhang if (voltage->min_uV || voltage->max_uV) 3107f7efad10SChunyan Zhang return 0; 3108f7efad10SChunyan Zhang } 3109f7efad10SChunyan Zhang 3110f7efad10SChunyan Zhang return regulator_suspend_toggle(rdev, state, false); 3111f7efad10SChunyan Zhang } 3112f7efad10SChunyan Zhang EXPORT_SYMBOL_GPL(regulator_suspend_disable); 3113f7efad10SChunyan Zhang 3114f7efad10SChunyan Zhang static int _regulator_set_suspend_voltage(struct regulator *regulator, 3115f7efad10SChunyan Zhang int min_uV, int max_uV, 3116f7efad10SChunyan Zhang suspend_state_t state) 3117f7efad10SChunyan Zhang { 3118f7efad10SChunyan Zhang struct regulator_dev *rdev = regulator->rdev; 3119f7efad10SChunyan Zhang struct regulator_state *rstate; 3120f7efad10SChunyan Zhang 3121f7efad10SChunyan Zhang rstate = regulator_get_suspend_state(rdev, state); 3122f7efad10SChunyan Zhang if (rstate == NULL) 3123f7efad10SChunyan Zhang return -EINVAL; 3124f7efad10SChunyan Zhang 3125f7efad10SChunyan Zhang if (rstate->min_uV == rstate->max_uV) { 3126f7efad10SChunyan Zhang rdev_err(rdev, "The suspend voltage can't be changed!\n"); 3127f7efad10SChunyan Zhang return -EPERM; 3128f7efad10SChunyan Zhang } 3129f7efad10SChunyan Zhang 3130f7efad10SChunyan Zhang return regulator_set_voltage_unlocked(regulator, min_uV, max_uV, state); 3131f7efad10SChunyan Zhang } 3132f7efad10SChunyan Zhang 3133f7efad10SChunyan Zhang int regulator_set_suspend_voltage(struct regulator *regulator, int min_uV, 3134f7efad10SChunyan Zhang int max_uV, suspend_state_t state) 3135f7efad10SChunyan Zhang { 3136f7efad10SChunyan Zhang int ret = 0; 3137f7efad10SChunyan Zhang 3138f7efad10SChunyan Zhang /* PM_SUSPEND_ON is handled by regulator_set_voltage() */ 3139f7efad10SChunyan Zhang if (regulator_check_states(state) || state == PM_SUSPEND_ON) 3140f7efad10SChunyan Zhang return -EINVAL; 3141f7efad10SChunyan Zhang 3142f7efad10SChunyan Zhang regulator_lock_supply(regulator->rdev); 3143f7efad10SChunyan Zhang 3144f7efad10SChunyan Zhang ret = _regulator_set_suspend_voltage(regulator, min_uV, 3145f7efad10SChunyan Zhang max_uV, state); 3146f7efad10SChunyan Zhang 3147f7efad10SChunyan Zhang regulator_unlock_supply(regulator->rdev); 3148f7efad10SChunyan Zhang 3149f7efad10SChunyan Zhang return ret; 3150f7efad10SChunyan Zhang } 3151f7efad10SChunyan Zhang EXPORT_SYMBOL_GPL(regulator_set_suspend_voltage); 3152f7efad10SChunyan Zhang 3153606a2562SMark Brown /** 315488cd222bSLinus Walleij * regulator_set_voltage_time - get raise/fall time 315588cd222bSLinus Walleij * @regulator: regulator source 315688cd222bSLinus Walleij * @old_uV: starting voltage in microvolts 315788cd222bSLinus Walleij * @new_uV: target voltage in microvolts 315888cd222bSLinus Walleij * 315988cd222bSLinus Walleij * Provided with the starting and ending voltage, this function attempts to 316088cd222bSLinus Walleij * calculate the time in microseconds required to rise or fall to this new 316188cd222bSLinus Walleij * voltage. 316288cd222bSLinus Walleij */ 316388cd222bSLinus Walleij int regulator_set_voltage_time(struct regulator *regulator, 316488cd222bSLinus Walleij int old_uV, int new_uV) 316588cd222bSLinus Walleij { 316688cd222bSLinus Walleij struct regulator_dev *rdev = regulator->rdev; 3167272e2315SGuodong Xu const struct regulator_ops *ops = rdev->desc->ops; 316888cd222bSLinus Walleij int old_sel = -1; 316988cd222bSLinus Walleij int new_sel = -1; 317088cd222bSLinus Walleij int voltage; 317188cd222bSLinus Walleij int i; 317288cd222bSLinus Walleij 317373e705bfSMatthias Kaehlcke if (ops->set_voltage_time) 317473e705bfSMatthias Kaehlcke return ops->set_voltage_time(rdev, old_uV, new_uV); 317573e705bfSMatthias Kaehlcke else if (!ops->set_voltage_time_sel) 317673e705bfSMatthias Kaehlcke return _regulator_set_voltage_time(rdev, old_uV, new_uV); 317773e705bfSMatthias Kaehlcke 317888cd222bSLinus Walleij /* Currently requires operations to do this */ 317973e705bfSMatthias Kaehlcke if (!ops->list_voltage || !rdev->desc->n_voltages) 318088cd222bSLinus Walleij return -EINVAL; 318188cd222bSLinus Walleij 318288cd222bSLinus Walleij for (i = 0; i < rdev->desc->n_voltages; i++) { 318388cd222bSLinus Walleij /* We only look for exact voltage matches here */ 318488cd222bSLinus Walleij voltage = regulator_list_voltage(regulator, i); 318588cd222bSLinus Walleij if (voltage < 0) 318688cd222bSLinus Walleij return -EINVAL; 318788cd222bSLinus Walleij if (voltage == 0) 318888cd222bSLinus Walleij continue; 318988cd222bSLinus Walleij if (voltage == old_uV) 319088cd222bSLinus Walleij old_sel = i; 319188cd222bSLinus Walleij if (voltage == new_uV) 319288cd222bSLinus Walleij new_sel = i; 319388cd222bSLinus Walleij } 319488cd222bSLinus Walleij 319588cd222bSLinus Walleij if (old_sel < 0 || new_sel < 0) 319688cd222bSLinus Walleij return -EINVAL; 319788cd222bSLinus Walleij 319888cd222bSLinus Walleij return ops->set_voltage_time_sel(rdev, old_sel, new_sel); 319988cd222bSLinus Walleij } 320088cd222bSLinus Walleij EXPORT_SYMBOL_GPL(regulator_set_voltage_time); 320188cd222bSLinus Walleij 320288cd222bSLinus Walleij /** 320398a175b6SYadwinder Singh Brar * regulator_set_voltage_time_sel - get raise/fall time 3204296c6566SRandy Dunlap * @rdev: regulator source device 320598a175b6SYadwinder Singh Brar * @old_selector: selector for starting voltage 320698a175b6SYadwinder Singh Brar * @new_selector: selector for target voltage 320798a175b6SYadwinder Singh Brar * 320898a175b6SYadwinder Singh Brar * Provided with the starting and target voltage selectors, this function 320998a175b6SYadwinder Singh Brar * returns time in microseconds required to rise or fall to this new voltage 321098a175b6SYadwinder Singh Brar * 3211f11d08c3SAxel Lin * Drivers providing ramp_delay in regulation_constraints can use this as their 3212398715abSAxel Lin * set_voltage_time_sel() operation. 321398a175b6SYadwinder Singh Brar */ 321498a175b6SYadwinder Singh Brar int regulator_set_voltage_time_sel(struct regulator_dev *rdev, 321598a175b6SYadwinder Singh Brar unsigned int old_selector, 321698a175b6SYadwinder Singh Brar unsigned int new_selector) 321798a175b6SYadwinder Singh Brar { 3218f11d08c3SAxel Lin int old_volt, new_volt; 3219398715abSAxel Lin 3220f11d08c3SAxel Lin /* sanity check */ 3221f11d08c3SAxel Lin if (!rdev->desc->ops->list_voltage) 3222f11d08c3SAxel Lin return -EINVAL; 3223398715abSAxel Lin 3224f11d08c3SAxel Lin old_volt = rdev->desc->ops->list_voltage(rdev, old_selector); 3225f11d08c3SAxel Lin new_volt = rdev->desc->ops->list_voltage(rdev, new_selector); 3226f11d08c3SAxel Lin 322773e705bfSMatthias Kaehlcke if (rdev->desc->ops->set_voltage_time) 322873e705bfSMatthias Kaehlcke return rdev->desc->ops->set_voltage_time(rdev, old_volt, 322973e705bfSMatthias Kaehlcke new_volt); 323073e705bfSMatthias Kaehlcke else 323173e705bfSMatthias Kaehlcke return _regulator_set_voltage_time(rdev, old_volt, new_volt); 323298a175b6SYadwinder Singh Brar } 3233b19dbf71SMark Brown EXPORT_SYMBOL_GPL(regulator_set_voltage_time_sel); 323498a175b6SYadwinder Singh Brar 323598a175b6SYadwinder Singh Brar /** 3236606a2562SMark Brown * regulator_sync_voltage - re-apply last regulator output voltage 3237606a2562SMark Brown * @regulator: regulator source 3238606a2562SMark Brown * 3239606a2562SMark Brown * Re-apply the last configured voltage. This is intended to be used 3240606a2562SMark Brown * where some external control source the consumer is cooperating with 3241606a2562SMark Brown * has caused the configured voltage to change. 3242606a2562SMark Brown */ 3243606a2562SMark Brown int regulator_sync_voltage(struct regulator *regulator) 3244606a2562SMark Brown { 3245606a2562SMark Brown struct regulator_dev *rdev = regulator->rdev; 3246c360a6dfSChunyan Zhang struct regulator_voltage *voltage = ®ulator->voltage[PM_SUSPEND_ON]; 3247606a2562SMark Brown int ret, min_uV, max_uV; 3248606a2562SMark Brown 3249606a2562SMark Brown mutex_lock(&rdev->mutex); 3250606a2562SMark Brown 3251606a2562SMark Brown if (!rdev->desc->ops->set_voltage && 3252606a2562SMark Brown !rdev->desc->ops->set_voltage_sel) { 3253606a2562SMark Brown ret = -EINVAL; 3254606a2562SMark Brown goto out; 3255606a2562SMark Brown } 3256606a2562SMark Brown 3257606a2562SMark Brown /* This is only going to work if we've had a voltage configured. */ 3258c360a6dfSChunyan Zhang if (!voltage->min_uV && !voltage->max_uV) { 3259606a2562SMark Brown ret = -EINVAL; 3260606a2562SMark Brown goto out; 3261606a2562SMark Brown } 3262606a2562SMark Brown 3263c360a6dfSChunyan Zhang min_uV = voltage->min_uV; 3264c360a6dfSChunyan Zhang max_uV = voltage->max_uV; 3265606a2562SMark Brown 3266606a2562SMark Brown /* This should be a paranoia check... */ 3267606a2562SMark Brown ret = regulator_check_voltage(rdev, &min_uV, &max_uV); 3268606a2562SMark Brown if (ret < 0) 3269606a2562SMark Brown goto out; 3270606a2562SMark Brown 3271c360a6dfSChunyan Zhang ret = regulator_check_consumers(rdev, &min_uV, &max_uV, 0); 3272606a2562SMark Brown if (ret < 0) 3273606a2562SMark Brown goto out; 3274606a2562SMark Brown 3275606a2562SMark Brown ret = _regulator_do_set_voltage(rdev, min_uV, max_uV); 3276606a2562SMark Brown 3277606a2562SMark Brown out: 3278606a2562SMark Brown mutex_unlock(&rdev->mutex); 3279606a2562SMark Brown return ret; 3280606a2562SMark Brown } 3281606a2562SMark Brown EXPORT_SYMBOL_GPL(regulator_sync_voltage); 3282606a2562SMark Brown 3283414c70cbSLiam Girdwood static int _regulator_get_voltage(struct regulator_dev *rdev) 3284414c70cbSLiam Girdwood { 3285bf5892a8SMark Brown int sel, ret; 3286fef95019SMark Brown bool bypassed; 3287fef95019SMark Brown 3288fef95019SMark Brown if (rdev->desc->ops->get_bypass) { 3289fef95019SMark Brown ret = rdev->desc->ops->get_bypass(rdev, &bypassed); 3290fef95019SMark Brown if (ret < 0) 3291fef95019SMark Brown return ret; 3292fef95019SMark Brown if (bypassed) { 3293fef95019SMark Brown /* if bypassed the regulator must have a supply */ 329445389c47SJon Hunter if (!rdev->supply) { 329545389c47SJon Hunter rdev_err(rdev, 329645389c47SJon Hunter "bypassed regulator has no supply!\n"); 329745389c47SJon Hunter return -EPROBE_DEFER; 329845389c47SJon Hunter } 3299fef95019SMark Brown 3300fef95019SMark Brown return _regulator_get_voltage(rdev->supply->rdev); 3301fef95019SMark Brown } 3302fef95019SMark Brown } 3303476c2d83SMark Brown 3304476c2d83SMark Brown if (rdev->desc->ops->get_voltage_sel) { 3305476c2d83SMark Brown sel = rdev->desc->ops->get_voltage_sel(rdev); 3306476c2d83SMark Brown if (sel < 0) 3307476c2d83SMark Brown return sel; 3308bf5892a8SMark Brown ret = rdev->desc->ops->list_voltage(rdev, sel); 3309cb220d16SAxel Lin } else if (rdev->desc->ops->get_voltage) { 3310bf5892a8SMark Brown ret = rdev->desc->ops->get_voltage(rdev); 3311f7df20ecSMark Brown } else if (rdev->desc->ops->list_voltage) { 3312f7df20ecSMark Brown ret = rdev->desc->ops->list_voltage(rdev, 0); 33135a523605SLaxman Dewangan } else if (rdev->desc->fixed_uV && (rdev->desc->n_voltages == 1)) { 33145a523605SLaxman Dewangan ret = rdev->desc->fixed_uV; 3315e303996eSJavier Martinez Canillas } else if (rdev->supply) { 3316d9b96d35SMark Brown ret = _regulator_get_voltage(rdev->supply->rdev); 3317cb220d16SAxel Lin } else { 3318414c70cbSLiam Girdwood return -EINVAL; 3319cb220d16SAxel Lin } 3320bf5892a8SMark Brown 3321cb220d16SAxel Lin if (ret < 0) 3322cb220d16SAxel Lin return ret; 3323bf5892a8SMark Brown return ret - rdev->constraints->uV_offset; 3324414c70cbSLiam Girdwood } 3325414c70cbSLiam Girdwood 3326414c70cbSLiam Girdwood /** 3327414c70cbSLiam Girdwood * regulator_get_voltage - get regulator output voltage 3328414c70cbSLiam Girdwood * @regulator: regulator source 3329414c70cbSLiam Girdwood * 3330414c70cbSLiam Girdwood * This returns the current regulator voltage in uV. 3331414c70cbSLiam Girdwood * 3332414c70cbSLiam Girdwood * NOTE: If the regulator is disabled it will return the voltage value. This 3333414c70cbSLiam Girdwood * function should not be used to determine regulator state. 3334414c70cbSLiam Girdwood */ 3335414c70cbSLiam Girdwood int regulator_get_voltage(struct regulator *regulator) 3336414c70cbSLiam Girdwood { 3337414c70cbSLiam Girdwood int ret; 3338414c70cbSLiam Girdwood 3339d9b96d35SMark Brown regulator_lock_supply(regulator->rdev); 3340414c70cbSLiam Girdwood 3341414c70cbSLiam Girdwood ret = _regulator_get_voltage(regulator->rdev); 3342414c70cbSLiam Girdwood 3343d9b96d35SMark Brown regulator_unlock_supply(regulator->rdev); 3344414c70cbSLiam Girdwood 3345414c70cbSLiam Girdwood return ret; 3346414c70cbSLiam Girdwood } 3347414c70cbSLiam Girdwood EXPORT_SYMBOL_GPL(regulator_get_voltage); 3348414c70cbSLiam Girdwood 3349414c70cbSLiam Girdwood /** 3350414c70cbSLiam Girdwood * regulator_set_current_limit - set regulator output current limit 3351414c70cbSLiam Girdwood * @regulator: regulator source 3352ce0d10f8SCharles Keepax * @min_uA: Minimum supported current in uA 3353414c70cbSLiam Girdwood * @max_uA: Maximum supported current in uA 3354414c70cbSLiam Girdwood * 3355414c70cbSLiam Girdwood * Sets current sink to the desired output current. This can be set during 3356414c70cbSLiam Girdwood * any regulator state. IOW, regulator can be disabled or enabled. 3357414c70cbSLiam Girdwood * 3358414c70cbSLiam Girdwood * If the regulator is enabled then the current will change to the new value 3359414c70cbSLiam Girdwood * immediately otherwise if the regulator is disabled the regulator will 3360414c70cbSLiam Girdwood * output at the new current when enabled. 3361414c70cbSLiam Girdwood * 3362414c70cbSLiam Girdwood * NOTE: Regulator system constraints must be set for this regulator before 3363414c70cbSLiam Girdwood * calling this function otherwise this call will fail. 3364414c70cbSLiam Girdwood */ 3365414c70cbSLiam Girdwood int regulator_set_current_limit(struct regulator *regulator, 3366414c70cbSLiam Girdwood int min_uA, int max_uA) 3367414c70cbSLiam Girdwood { 3368414c70cbSLiam Girdwood struct regulator_dev *rdev = regulator->rdev; 3369414c70cbSLiam Girdwood int ret; 3370414c70cbSLiam Girdwood 3371414c70cbSLiam Girdwood mutex_lock(&rdev->mutex); 3372414c70cbSLiam Girdwood 3373414c70cbSLiam Girdwood /* sanity check */ 3374414c70cbSLiam Girdwood if (!rdev->desc->ops->set_current_limit) { 3375414c70cbSLiam Girdwood ret = -EINVAL; 3376414c70cbSLiam Girdwood goto out; 3377414c70cbSLiam Girdwood } 3378414c70cbSLiam Girdwood 3379414c70cbSLiam Girdwood /* constraints check */ 3380414c70cbSLiam Girdwood ret = regulator_check_current_limit(rdev, &min_uA, &max_uA); 3381414c70cbSLiam Girdwood if (ret < 0) 3382414c70cbSLiam Girdwood goto out; 3383414c70cbSLiam Girdwood 3384414c70cbSLiam Girdwood ret = rdev->desc->ops->set_current_limit(rdev, min_uA, max_uA); 3385414c70cbSLiam Girdwood out: 3386414c70cbSLiam Girdwood mutex_unlock(&rdev->mutex); 3387414c70cbSLiam Girdwood return ret; 3388414c70cbSLiam Girdwood } 3389414c70cbSLiam Girdwood EXPORT_SYMBOL_GPL(regulator_set_current_limit); 3390414c70cbSLiam Girdwood 3391414c70cbSLiam Girdwood static int _regulator_get_current_limit(struct regulator_dev *rdev) 3392414c70cbSLiam Girdwood { 3393414c70cbSLiam Girdwood int ret; 3394414c70cbSLiam Girdwood 3395414c70cbSLiam Girdwood mutex_lock(&rdev->mutex); 3396414c70cbSLiam Girdwood 3397414c70cbSLiam Girdwood /* sanity check */ 3398414c70cbSLiam Girdwood if (!rdev->desc->ops->get_current_limit) { 3399414c70cbSLiam Girdwood ret = -EINVAL; 3400414c70cbSLiam Girdwood goto out; 3401414c70cbSLiam Girdwood } 3402414c70cbSLiam Girdwood 3403414c70cbSLiam Girdwood ret = rdev->desc->ops->get_current_limit(rdev); 3404414c70cbSLiam Girdwood out: 3405414c70cbSLiam Girdwood mutex_unlock(&rdev->mutex); 3406414c70cbSLiam Girdwood return ret; 3407414c70cbSLiam Girdwood } 3408414c70cbSLiam Girdwood 3409414c70cbSLiam Girdwood /** 3410414c70cbSLiam Girdwood * regulator_get_current_limit - get regulator output current 3411414c70cbSLiam Girdwood * @regulator: regulator source 3412414c70cbSLiam Girdwood * 3413414c70cbSLiam Girdwood * This returns the current supplied by the specified current sink in uA. 3414414c70cbSLiam Girdwood * 3415414c70cbSLiam Girdwood * NOTE: If the regulator is disabled it will return the current value. This 3416414c70cbSLiam Girdwood * function should not be used to determine regulator state. 3417414c70cbSLiam Girdwood */ 3418414c70cbSLiam Girdwood int regulator_get_current_limit(struct regulator *regulator) 3419414c70cbSLiam Girdwood { 3420414c70cbSLiam Girdwood return _regulator_get_current_limit(regulator->rdev); 3421414c70cbSLiam Girdwood } 3422414c70cbSLiam Girdwood EXPORT_SYMBOL_GPL(regulator_get_current_limit); 3423414c70cbSLiam Girdwood 3424414c70cbSLiam Girdwood /** 3425414c70cbSLiam Girdwood * regulator_set_mode - set regulator operating mode 3426414c70cbSLiam Girdwood * @regulator: regulator source 3427414c70cbSLiam Girdwood * @mode: operating mode - one of the REGULATOR_MODE constants 3428414c70cbSLiam Girdwood * 3429414c70cbSLiam Girdwood * Set regulator operating mode to increase regulator efficiency or improve 3430414c70cbSLiam Girdwood * regulation performance. 3431414c70cbSLiam Girdwood * 3432414c70cbSLiam Girdwood * NOTE: Regulator system constraints must be set for this regulator before 3433414c70cbSLiam Girdwood * calling this function otherwise this call will fail. 3434414c70cbSLiam Girdwood */ 3435414c70cbSLiam Girdwood int regulator_set_mode(struct regulator *regulator, unsigned int mode) 3436414c70cbSLiam Girdwood { 3437414c70cbSLiam Girdwood struct regulator_dev *rdev = regulator->rdev; 3438414c70cbSLiam Girdwood int ret; 3439500b4ac9SSundar R Iyer int regulator_curr_mode; 3440414c70cbSLiam Girdwood 3441414c70cbSLiam Girdwood mutex_lock(&rdev->mutex); 3442414c70cbSLiam Girdwood 3443414c70cbSLiam Girdwood /* sanity check */ 3444414c70cbSLiam Girdwood if (!rdev->desc->ops->set_mode) { 3445414c70cbSLiam Girdwood ret = -EINVAL; 3446414c70cbSLiam Girdwood goto out; 3447414c70cbSLiam Girdwood } 3448414c70cbSLiam Girdwood 3449500b4ac9SSundar R Iyer /* return if the same mode is requested */ 3450500b4ac9SSundar R Iyer if (rdev->desc->ops->get_mode) { 3451500b4ac9SSundar R Iyer regulator_curr_mode = rdev->desc->ops->get_mode(rdev); 3452500b4ac9SSundar R Iyer if (regulator_curr_mode == mode) { 3453500b4ac9SSundar R Iyer ret = 0; 3454500b4ac9SSundar R Iyer goto out; 3455500b4ac9SSundar R Iyer } 3456500b4ac9SSundar R Iyer } 3457500b4ac9SSundar R Iyer 3458414c70cbSLiam Girdwood /* constraints check */ 345922c51b47SAxel Lin ret = regulator_mode_constrain(rdev, &mode); 3460414c70cbSLiam Girdwood if (ret < 0) 3461414c70cbSLiam Girdwood goto out; 3462414c70cbSLiam Girdwood 3463414c70cbSLiam Girdwood ret = rdev->desc->ops->set_mode(rdev, mode); 3464414c70cbSLiam Girdwood out: 3465414c70cbSLiam Girdwood mutex_unlock(&rdev->mutex); 3466414c70cbSLiam Girdwood return ret; 3467414c70cbSLiam Girdwood } 3468414c70cbSLiam Girdwood EXPORT_SYMBOL_GPL(regulator_set_mode); 3469414c70cbSLiam Girdwood 3470414c70cbSLiam Girdwood static unsigned int _regulator_get_mode(struct regulator_dev *rdev) 3471414c70cbSLiam Girdwood { 3472414c70cbSLiam Girdwood int ret; 3473414c70cbSLiam Girdwood 3474414c70cbSLiam Girdwood mutex_lock(&rdev->mutex); 3475414c70cbSLiam Girdwood 3476414c70cbSLiam Girdwood /* sanity check */ 3477414c70cbSLiam Girdwood if (!rdev->desc->ops->get_mode) { 3478414c70cbSLiam Girdwood ret = -EINVAL; 3479414c70cbSLiam Girdwood goto out; 3480414c70cbSLiam Girdwood } 3481414c70cbSLiam Girdwood 3482414c70cbSLiam Girdwood ret = rdev->desc->ops->get_mode(rdev); 3483414c70cbSLiam Girdwood out: 3484414c70cbSLiam Girdwood mutex_unlock(&rdev->mutex); 3485414c70cbSLiam Girdwood return ret; 3486414c70cbSLiam Girdwood } 3487414c70cbSLiam Girdwood 3488414c70cbSLiam Girdwood /** 3489414c70cbSLiam Girdwood * regulator_get_mode - get regulator operating mode 3490414c70cbSLiam Girdwood * @regulator: regulator source 3491414c70cbSLiam Girdwood * 3492414c70cbSLiam Girdwood * Get the current regulator operating mode. 3493414c70cbSLiam Girdwood */ 3494414c70cbSLiam Girdwood unsigned int regulator_get_mode(struct regulator *regulator) 3495414c70cbSLiam Girdwood { 3496414c70cbSLiam Girdwood return _regulator_get_mode(regulator->rdev); 3497414c70cbSLiam Girdwood } 3498414c70cbSLiam Girdwood EXPORT_SYMBOL_GPL(regulator_get_mode); 3499414c70cbSLiam Girdwood 35001b5b4221SAxel Haslam static int _regulator_get_error_flags(struct regulator_dev *rdev, 35011b5b4221SAxel Haslam unsigned int *flags) 35021b5b4221SAxel Haslam { 35031b5b4221SAxel Haslam int ret; 35041b5b4221SAxel Haslam 35051b5b4221SAxel Haslam mutex_lock(&rdev->mutex); 35061b5b4221SAxel Haslam 35071b5b4221SAxel Haslam /* sanity check */ 35081b5b4221SAxel Haslam if (!rdev->desc->ops->get_error_flags) { 35091b5b4221SAxel Haslam ret = -EINVAL; 35101b5b4221SAxel Haslam goto out; 35111b5b4221SAxel Haslam } 35121b5b4221SAxel Haslam 35131b5b4221SAxel Haslam ret = rdev->desc->ops->get_error_flags(rdev, flags); 35141b5b4221SAxel Haslam out: 35151b5b4221SAxel Haslam mutex_unlock(&rdev->mutex); 35161b5b4221SAxel Haslam return ret; 35171b5b4221SAxel Haslam } 35181b5b4221SAxel Haslam 35191b5b4221SAxel Haslam /** 35201b5b4221SAxel Haslam * regulator_get_error_flags - get regulator error information 35211b5b4221SAxel Haslam * @regulator: regulator source 35221b5b4221SAxel Haslam * @flags: pointer to store error flags 35231b5b4221SAxel Haslam * 35241b5b4221SAxel Haslam * Get the current regulator error information. 35251b5b4221SAxel Haslam */ 35261b5b4221SAxel Haslam int regulator_get_error_flags(struct regulator *regulator, 35271b5b4221SAxel Haslam unsigned int *flags) 35281b5b4221SAxel Haslam { 35291b5b4221SAxel Haslam return _regulator_get_error_flags(regulator->rdev, flags); 35301b5b4221SAxel Haslam } 35311b5b4221SAxel Haslam EXPORT_SYMBOL_GPL(regulator_get_error_flags); 35321b5b4221SAxel Haslam 3533414c70cbSLiam Girdwood /** 3534e39ce48fSBjorn Andersson * regulator_set_load - set regulator load 3535414c70cbSLiam Girdwood * @regulator: regulator source 3536414c70cbSLiam Girdwood * @uA_load: load current 3537414c70cbSLiam Girdwood * 3538414c70cbSLiam Girdwood * Notifies the regulator core of a new device load. This is then used by 3539414c70cbSLiam Girdwood * DRMS (if enabled by constraints) to set the most efficient regulator 3540414c70cbSLiam Girdwood * operating mode for the new regulator loading. 3541414c70cbSLiam Girdwood * 3542414c70cbSLiam Girdwood * Consumer devices notify their supply regulator of the maximum power 3543414c70cbSLiam Girdwood * they will require (can be taken from device datasheet in the power 3544414c70cbSLiam Girdwood * consumption tables) when they change operational status and hence power 3545414c70cbSLiam Girdwood * state. Examples of operational state changes that can affect power 3546414c70cbSLiam Girdwood * consumption are :- 3547414c70cbSLiam Girdwood * 3548414c70cbSLiam Girdwood * o Device is opened / closed. 3549414c70cbSLiam Girdwood * o Device I/O is about to begin or has just finished. 3550414c70cbSLiam Girdwood * o Device is idling in between work. 3551414c70cbSLiam Girdwood * 3552414c70cbSLiam Girdwood * This information is also exported via sysfs to userspace. 3553414c70cbSLiam Girdwood * 3554414c70cbSLiam Girdwood * DRMS will sum the total requested load on the regulator and change 3555414c70cbSLiam Girdwood * to the most efficient operating mode if platform constraints allow. 3556414c70cbSLiam Girdwood * 3557e39ce48fSBjorn Andersson * On error a negative errno is returned. 3558414c70cbSLiam Girdwood */ 3559e39ce48fSBjorn Andersson int regulator_set_load(struct regulator *regulator, int uA_load) 3560414c70cbSLiam Girdwood { 3561414c70cbSLiam Girdwood struct regulator_dev *rdev = regulator->rdev; 35628460ef38SBjorn Andersson int ret; 3563d92d95b6SStephen Boyd 3564414c70cbSLiam Girdwood mutex_lock(&rdev->mutex); 3565414c70cbSLiam Girdwood regulator->uA_load = uA_load; 35668460ef38SBjorn Andersson ret = drms_uA_update(rdev); 3567414c70cbSLiam Girdwood mutex_unlock(&rdev->mutex); 35688460ef38SBjorn Andersson 3569414c70cbSLiam Girdwood return ret; 3570414c70cbSLiam Girdwood } 3571e39ce48fSBjorn Andersson EXPORT_SYMBOL_GPL(regulator_set_load); 3572414c70cbSLiam Girdwood 3573414c70cbSLiam Girdwood /** 3574f59c8f9fSMark Brown * regulator_allow_bypass - allow the regulator to go into bypass mode 3575f59c8f9fSMark Brown * 3576f59c8f9fSMark Brown * @regulator: Regulator to configure 35779345dfb8SNishanth Menon * @enable: enable or disable bypass mode 3578f59c8f9fSMark Brown * 3579f59c8f9fSMark Brown * Allow the regulator to go into bypass mode if all other consumers 3580f59c8f9fSMark Brown * for the regulator also enable bypass mode and the machine 3581f59c8f9fSMark Brown * constraints allow this. Bypass mode means that the regulator is 3582f59c8f9fSMark Brown * simply passing the input directly to the output with no regulation. 3583f59c8f9fSMark Brown */ 3584f59c8f9fSMark Brown int regulator_allow_bypass(struct regulator *regulator, bool enable) 3585f59c8f9fSMark Brown { 3586f59c8f9fSMark Brown struct regulator_dev *rdev = regulator->rdev; 3587f59c8f9fSMark Brown int ret = 0; 3588f59c8f9fSMark Brown 3589f59c8f9fSMark Brown if (!rdev->desc->ops->set_bypass) 3590f59c8f9fSMark Brown return 0; 3591f59c8f9fSMark Brown 35928a34e979SWEN Pingbo if (!regulator_ops_is_valid(rdev, REGULATOR_CHANGE_BYPASS)) 3593f59c8f9fSMark Brown return 0; 3594f59c8f9fSMark Brown 3595f59c8f9fSMark Brown mutex_lock(&rdev->mutex); 3596f59c8f9fSMark Brown 3597f59c8f9fSMark Brown if (enable && !regulator->bypass) { 3598f59c8f9fSMark Brown rdev->bypass_count++; 3599f59c8f9fSMark Brown 3600f59c8f9fSMark Brown if (rdev->bypass_count == rdev->open_count) { 3601f59c8f9fSMark Brown ret = rdev->desc->ops->set_bypass(rdev, enable); 3602f59c8f9fSMark Brown if (ret != 0) 3603f59c8f9fSMark Brown rdev->bypass_count--; 3604f59c8f9fSMark Brown } 3605f59c8f9fSMark Brown 3606f59c8f9fSMark Brown } else if (!enable && regulator->bypass) { 3607f59c8f9fSMark Brown rdev->bypass_count--; 3608f59c8f9fSMark Brown 3609f59c8f9fSMark Brown if (rdev->bypass_count != rdev->open_count) { 3610f59c8f9fSMark Brown ret = rdev->desc->ops->set_bypass(rdev, enable); 3611f59c8f9fSMark Brown if (ret != 0) 3612f59c8f9fSMark Brown rdev->bypass_count++; 3613f59c8f9fSMark Brown } 3614f59c8f9fSMark Brown } 3615f59c8f9fSMark Brown 3616f59c8f9fSMark Brown if (ret == 0) 3617f59c8f9fSMark Brown regulator->bypass = enable; 3618f59c8f9fSMark Brown 3619f59c8f9fSMark Brown mutex_unlock(&rdev->mutex); 3620f59c8f9fSMark Brown 3621f59c8f9fSMark Brown return ret; 3622f59c8f9fSMark Brown } 3623f59c8f9fSMark Brown EXPORT_SYMBOL_GPL(regulator_allow_bypass); 3624f59c8f9fSMark Brown 3625f59c8f9fSMark Brown /** 3626414c70cbSLiam Girdwood * regulator_register_notifier - register regulator event notifier 3627414c70cbSLiam Girdwood * @regulator: regulator source 362869279fb9SMark Brown * @nb: notifier block 3629414c70cbSLiam Girdwood * 3630414c70cbSLiam Girdwood * Register notifier block to receive regulator events. 3631414c70cbSLiam Girdwood */ 3632414c70cbSLiam Girdwood int regulator_register_notifier(struct regulator *regulator, 3633414c70cbSLiam Girdwood struct notifier_block *nb) 3634414c70cbSLiam Girdwood { 3635414c70cbSLiam Girdwood return blocking_notifier_chain_register(®ulator->rdev->notifier, 3636414c70cbSLiam Girdwood nb); 3637414c70cbSLiam Girdwood } 3638414c70cbSLiam Girdwood EXPORT_SYMBOL_GPL(regulator_register_notifier); 3639414c70cbSLiam Girdwood 3640414c70cbSLiam Girdwood /** 3641414c70cbSLiam Girdwood * regulator_unregister_notifier - unregister regulator event notifier 3642414c70cbSLiam Girdwood * @regulator: regulator source 364369279fb9SMark Brown * @nb: notifier block 3644414c70cbSLiam Girdwood * 3645414c70cbSLiam Girdwood * Unregister regulator event notifier block. 3646414c70cbSLiam Girdwood */ 3647414c70cbSLiam Girdwood int regulator_unregister_notifier(struct regulator *regulator, 3648414c70cbSLiam Girdwood struct notifier_block *nb) 3649414c70cbSLiam Girdwood { 3650414c70cbSLiam Girdwood return blocking_notifier_chain_unregister(®ulator->rdev->notifier, 3651414c70cbSLiam Girdwood nb); 3652414c70cbSLiam Girdwood } 3653414c70cbSLiam Girdwood EXPORT_SYMBOL_GPL(regulator_unregister_notifier); 3654414c70cbSLiam Girdwood 3655b136fb44SJonathan Cameron /* notify regulator consumers and downstream regulator consumers. 3656b136fb44SJonathan Cameron * Note mutex must be held by caller. 3657b136fb44SJonathan Cameron */ 36587179569aSHeiko Stübner static int _notifier_call_chain(struct regulator_dev *rdev, 3659414c70cbSLiam Girdwood unsigned long event, void *data) 3660414c70cbSLiam Girdwood { 3661414c70cbSLiam Girdwood /* call rdev chain first */ 36627179569aSHeiko Stübner return blocking_notifier_call_chain(&rdev->notifier, event, data); 3663414c70cbSLiam Girdwood } 3664414c70cbSLiam Girdwood 3665414c70cbSLiam Girdwood /** 3666414c70cbSLiam Girdwood * regulator_bulk_get - get multiple regulator consumers 3667414c70cbSLiam Girdwood * 3668414c70cbSLiam Girdwood * @dev: Device to supply 3669414c70cbSLiam Girdwood * @num_consumers: Number of consumers to register 3670414c70cbSLiam Girdwood * @consumers: Configuration of consumers; clients are stored here. 3671414c70cbSLiam Girdwood * 3672414c70cbSLiam Girdwood * @return 0 on success, an errno on failure. 3673414c70cbSLiam Girdwood * 3674414c70cbSLiam Girdwood * This helper function allows drivers to get several regulator 3675414c70cbSLiam Girdwood * consumers in one operation. If any of the regulators cannot be 3676414c70cbSLiam Girdwood * acquired then any regulators that were allocated will be freed 3677414c70cbSLiam Girdwood * before returning to the caller. 3678414c70cbSLiam Girdwood */ 3679414c70cbSLiam Girdwood int regulator_bulk_get(struct device *dev, int num_consumers, 3680414c70cbSLiam Girdwood struct regulator_bulk_data *consumers) 3681414c70cbSLiam Girdwood { 3682414c70cbSLiam Girdwood int i; 3683414c70cbSLiam Girdwood int ret; 3684414c70cbSLiam Girdwood 3685414c70cbSLiam Girdwood for (i = 0; i < num_consumers; i++) 3686414c70cbSLiam Girdwood consumers[i].consumer = NULL; 3687414c70cbSLiam Girdwood 3688414c70cbSLiam Girdwood for (i = 0; i < num_consumers; i++) { 3689565f9b07SBjorn Andersson consumers[i].consumer = regulator_get(dev, 3690565f9b07SBjorn Andersson consumers[i].supply); 3691414c70cbSLiam Girdwood if (IS_ERR(consumers[i].consumer)) { 3692414c70cbSLiam Girdwood ret = PTR_ERR(consumers[i].consumer); 36935b307627SMark Brown dev_err(dev, "Failed to get supply '%s': %d\n", 36945b307627SMark Brown consumers[i].supply, ret); 3695414c70cbSLiam Girdwood consumers[i].consumer = NULL; 3696414c70cbSLiam Girdwood goto err; 3697414c70cbSLiam Girdwood } 3698414c70cbSLiam Girdwood } 3699414c70cbSLiam Girdwood 3700414c70cbSLiam Girdwood return 0; 3701414c70cbSLiam Girdwood 3702414c70cbSLiam Girdwood err: 3703b29c7690SAxel Lin while (--i >= 0) 3704414c70cbSLiam Girdwood regulator_put(consumers[i].consumer); 3705414c70cbSLiam Girdwood 3706414c70cbSLiam Girdwood return ret; 3707414c70cbSLiam Girdwood } 3708414c70cbSLiam Girdwood EXPORT_SYMBOL_GPL(regulator_bulk_get); 3709414c70cbSLiam Girdwood 3710f21e0e81SMark Brown static void regulator_bulk_enable_async(void *data, async_cookie_t cookie) 3711f21e0e81SMark Brown { 3712f21e0e81SMark Brown struct regulator_bulk_data *bulk = data; 3713f21e0e81SMark Brown 3714f21e0e81SMark Brown bulk->ret = regulator_enable(bulk->consumer); 3715f21e0e81SMark Brown } 3716f21e0e81SMark Brown 3717414c70cbSLiam Girdwood /** 3718414c70cbSLiam Girdwood * regulator_bulk_enable - enable multiple regulator consumers 3719414c70cbSLiam Girdwood * 3720414c70cbSLiam Girdwood * @num_consumers: Number of consumers 3721414c70cbSLiam Girdwood * @consumers: Consumer data; clients are stored here. 3722414c70cbSLiam Girdwood * @return 0 on success, an errno on failure 3723414c70cbSLiam Girdwood * 3724414c70cbSLiam Girdwood * This convenience API allows consumers to enable multiple regulator 3725414c70cbSLiam Girdwood * clients in a single API call. If any consumers cannot be enabled 3726414c70cbSLiam Girdwood * then any others that were enabled will be disabled again prior to 3727414c70cbSLiam Girdwood * return. 3728414c70cbSLiam Girdwood */ 3729414c70cbSLiam Girdwood int regulator_bulk_enable(int num_consumers, 3730414c70cbSLiam Girdwood struct regulator_bulk_data *consumers) 3731414c70cbSLiam Girdwood { 37322955b47dSDan Williams ASYNC_DOMAIN_EXCLUSIVE(async_domain); 3733414c70cbSLiam Girdwood int i; 3734f21e0e81SMark Brown int ret = 0; 3735414c70cbSLiam Girdwood 37366492bc1bSMark Brown for (i = 0; i < num_consumers; i++) { 37376492bc1bSMark Brown if (consumers[i].consumer->always_on) 37386492bc1bSMark Brown consumers[i].ret = 0; 37396492bc1bSMark Brown else 3740f21e0e81SMark Brown async_schedule_domain(regulator_bulk_enable_async, 3741f21e0e81SMark Brown &consumers[i], &async_domain); 37426492bc1bSMark Brown } 3743f21e0e81SMark Brown 3744f21e0e81SMark Brown async_synchronize_full_domain(&async_domain); 3745f21e0e81SMark Brown 3746f21e0e81SMark Brown /* If any consumer failed we need to unwind any that succeeded */ 3747414c70cbSLiam Girdwood for (i = 0; i < num_consumers; i++) { 3748f21e0e81SMark Brown if (consumers[i].ret != 0) { 3749f21e0e81SMark Brown ret = consumers[i].ret; 3750414c70cbSLiam Girdwood goto err; 3751414c70cbSLiam Girdwood } 3752f21e0e81SMark Brown } 3753414c70cbSLiam Girdwood 3754414c70cbSLiam Girdwood return 0; 3755414c70cbSLiam Girdwood 3756414c70cbSLiam Girdwood err: 3757fbe31057SAndrzej Hajda for (i = 0; i < num_consumers; i++) { 3758fbe31057SAndrzej Hajda if (consumers[i].ret < 0) 3759fbe31057SAndrzej Hajda pr_err("Failed to enable %s: %d\n", consumers[i].supply, 3760fbe31057SAndrzej Hajda consumers[i].ret); 3761fbe31057SAndrzej Hajda else 3762414c70cbSLiam Girdwood regulator_disable(consumers[i].consumer); 3763fbe31057SAndrzej Hajda } 3764414c70cbSLiam Girdwood 3765414c70cbSLiam Girdwood return ret; 3766414c70cbSLiam Girdwood } 3767414c70cbSLiam Girdwood EXPORT_SYMBOL_GPL(regulator_bulk_enable); 3768414c70cbSLiam Girdwood 3769414c70cbSLiam Girdwood /** 3770414c70cbSLiam Girdwood * regulator_bulk_disable - disable multiple regulator consumers 3771414c70cbSLiam Girdwood * 3772414c70cbSLiam Girdwood * @num_consumers: Number of consumers 3773414c70cbSLiam Girdwood * @consumers: Consumer data; clients are stored here. 3774414c70cbSLiam Girdwood * @return 0 on success, an errno on failure 3775414c70cbSLiam Girdwood * 3776414c70cbSLiam Girdwood * This convenience API allows consumers to disable multiple regulator 377749e22632SSylwester Nawrocki * clients in a single API call. If any consumers cannot be disabled 377849e22632SSylwester Nawrocki * then any others that were disabled will be enabled again prior to 3779414c70cbSLiam Girdwood * return. 3780414c70cbSLiam Girdwood */ 3781414c70cbSLiam Girdwood int regulator_bulk_disable(int num_consumers, 3782414c70cbSLiam Girdwood struct regulator_bulk_data *consumers) 3783414c70cbSLiam Girdwood { 3784414c70cbSLiam Girdwood int i; 378501e86f49SMark Brown int ret, r; 3786414c70cbSLiam Girdwood 378749e22632SSylwester Nawrocki for (i = num_consumers - 1; i >= 0; --i) { 3788414c70cbSLiam Girdwood ret = regulator_disable(consumers[i].consumer); 3789414c70cbSLiam Girdwood if (ret != 0) 3790414c70cbSLiam Girdwood goto err; 3791414c70cbSLiam Girdwood } 3792414c70cbSLiam Girdwood 3793414c70cbSLiam Girdwood return 0; 3794414c70cbSLiam Girdwood 3795414c70cbSLiam Girdwood err: 37965da84fd9SJoe Perches pr_err("Failed to disable %s: %d\n", consumers[i].supply, ret); 379701e86f49SMark Brown for (++i; i < num_consumers; ++i) { 379801e86f49SMark Brown r = regulator_enable(consumers[i].consumer); 379901e86f49SMark Brown if (r != 0) 3800d1642ea7SDmitry Torokhov pr_err("Failed to re-enable %s: %d\n", 380101e86f49SMark Brown consumers[i].supply, r); 380201e86f49SMark Brown } 3803414c70cbSLiam Girdwood 3804414c70cbSLiam Girdwood return ret; 3805414c70cbSLiam Girdwood } 3806414c70cbSLiam Girdwood EXPORT_SYMBOL_GPL(regulator_bulk_disable); 3807414c70cbSLiam Girdwood 3808414c70cbSLiam Girdwood /** 3809e1de2f42SDonggeun Kim * regulator_bulk_force_disable - force disable multiple regulator consumers 3810e1de2f42SDonggeun Kim * 3811e1de2f42SDonggeun Kim * @num_consumers: Number of consumers 3812e1de2f42SDonggeun Kim * @consumers: Consumer data; clients are stored here. 3813e1de2f42SDonggeun Kim * @return 0 on success, an errno on failure 3814e1de2f42SDonggeun Kim * 3815e1de2f42SDonggeun Kim * This convenience API allows consumers to forcibly disable multiple regulator 3816e1de2f42SDonggeun Kim * clients in a single API call. 3817e1de2f42SDonggeun Kim * NOTE: This should be used for situations when device damage will 3818e1de2f42SDonggeun Kim * likely occur if the regulators are not disabled (e.g. over temp). 3819e1de2f42SDonggeun Kim * Although regulator_force_disable function call for some consumers can 3820e1de2f42SDonggeun Kim * return error numbers, the function is called for all consumers. 3821e1de2f42SDonggeun Kim */ 3822e1de2f42SDonggeun Kim int regulator_bulk_force_disable(int num_consumers, 3823e1de2f42SDonggeun Kim struct regulator_bulk_data *consumers) 3824e1de2f42SDonggeun Kim { 3825e1de2f42SDonggeun Kim int i; 3826b8c77ff6SDmitry Torokhov int ret = 0; 3827e1de2f42SDonggeun Kim 3828b8c77ff6SDmitry Torokhov for (i = 0; i < num_consumers; i++) { 3829e1de2f42SDonggeun Kim consumers[i].ret = 3830e1de2f42SDonggeun Kim regulator_force_disable(consumers[i].consumer); 3831e1de2f42SDonggeun Kim 3832b8c77ff6SDmitry Torokhov /* Store first error for reporting */ 3833b8c77ff6SDmitry Torokhov if (consumers[i].ret && !ret) 3834e1de2f42SDonggeun Kim ret = consumers[i].ret; 3835e1de2f42SDonggeun Kim } 3836e1de2f42SDonggeun Kim 3837e1de2f42SDonggeun Kim return ret; 3838e1de2f42SDonggeun Kim } 3839e1de2f42SDonggeun Kim EXPORT_SYMBOL_GPL(regulator_bulk_force_disable); 3840e1de2f42SDonggeun Kim 3841e1de2f42SDonggeun Kim /** 3842414c70cbSLiam Girdwood * regulator_bulk_free - free multiple regulator consumers 3843414c70cbSLiam Girdwood * 3844414c70cbSLiam Girdwood * @num_consumers: Number of consumers 3845414c70cbSLiam Girdwood * @consumers: Consumer data; clients are stored here. 3846414c70cbSLiam Girdwood * 3847414c70cbSLiam Girdwood * This convenience API allows consumers to free multiple regulator 3848414c70cbSLiam Girdwood * clients in a single API call. 3849414c70cbSLiam Girdwood */ 3850414c70cbSLiam Girdwood void regulator_bulk_free(int num_consumers, 3851414c70cbSLiam Girdwood struct regulator_bulk_data *consumers) 3852414c70cbSLiam Girdwood { 3853414c70cbSLiam Girdwood int i; 3854414c70cbSLiam Girdwood 3855414c70cbSLiam Girdwood for (i = 0; i < num_consumers; i++) { 3856414c70cbSLiam Girdwood regulator_put(consumers[i].consumer); 3857414c70cbSLiam Girdwood consumers[i].consumer = NULL; 3858414c70cbSLiam Girdwood } 3859414c70cbSLiam Girdwood } 3860414c70cbSLiam Girdwood EXPORT_SYMBOL_GPL(regulator_bulk_free); 3861414c70cbSLiam Girdwood 3862414c70cbSLiam Girdwood /** 3863414c70cbSLiam Girdwood * regulator_notifier_call_chain - call regulator event notifier 386469279fb9SMark Brown * @rdev: regulator source 3865414c70cbSLiam Girdwood * @event: notifier block 386669279fb9SMark Brown * @data: callback-specific data. 3867414c70cbSLiam Girdwood * 3868414c70cbSLiam Girdwood * Called by regulator drivers to notify clients a regulator event has 3869414c70cbSLiam Girdwood * occurred. We also notify regulator clients downstream. 3870b136fb44SJonathan Cameron * Note lock must be held by caller. 3871414c70cbSLiam Girdwood */ 3872414c70cbSLiam Girdwood int regulator_notifier_call_chain(struct regulator_dev *rdev, 3873414c70cbSLiam Girdwood unsigned long event, void *data) 3874414c70cbSLiam Girdwood { 387570cfef26SKrzysztof Kozlowski lockdep_assert_held_once(&rdev->mutex); 387670cfef26SKrzysztof Kozlowski 3877414c70cbSLiam Girdwood _notifier_call_chain(rdev, event, data); 3878414c70cbSLiam Girdwood return NOTIFY_DONE; 3879414c70cbSLiam Girdwood 3880414c70cbSLiam Girdwood } 3881414c70cbSLiam Girdwood EXPORT_SYMBOL_GPL(regulator_notifier_call_chain); 3882414c70cbSLiam Girdwood 3883be721979SMark Brown /** 3884be721979SMark Brown * regulator_mode_to_status - convert a regulator mode into a status 3885be721979SMark Brown * 3886be721979SMark Brown * @mode: Mode to convert 3887be721979SMark Brown * 3888be721979SMark Brown * Convert a regulator mode into a status. 3889be721979SMark Brown */ 3890be721979SMark Brown int regulator_mode_to_status(unsigned int mode) 3891be721979SMark Brown { 3892be721979SMark Brown switch (mode) { 3893be721979SMark Brown case REGULATOR_MODE_FAST: 3894be721979SMark Brown return REGULATOR_STATUS_FAST; 3895be721979SMark Brown case REGULATOR_MODE_NORMAL: 3896be721979SMark Brown return REGULATOR_STATUS_NORMAL; 3897be721979SMark Brown case REGULATOR_MODE_IDLE: 3898be721979SMark Brown return REGULATOR_STATUS_IDLE; 389903ffcf3dSKrystian Garbaciak case REGULATOR_MODE_STANDBY: 3900be721979SMark Brown return REGULATOR_STATUS_STANDBY; 3901be721979SMark Brown default: 39021beaf762SKrystian Garbaciak return REGULATOR_STATUS_UNDEFINED; 3903be721979SMark Brown } 3904be721979SMark Brown } 3905be721979SMark Brown EXPORT_SYMBOL_GPL(regulator_mode_to_status); 3906be721979SMark Brown 390739f802d6STakashi Iwai static struct attribute *regulator_dev_attrs[] = { 390839f802d6STakashi Iwai &dev_attr_name.attr, 390939f802d6STakashi Iwai &dev_attr_num_users.attr, 391039f802d6STakashi Iwai &dev_attr_type.attr, 391139f802d6STakashi Iwai &dev_attr_microvolts.attr, 391239f802d6STakashi Iwai &dev_attr_microamps.attr, 391339f802d6STakashi Iwai &dev_attr_opmode.attr, 391439f802d6STakashi Iwai &dev_attr_state.attr, 391539f802d6STakashi Iwai &dev_attr_status.attr, 391639f802d6STakashi Iwai &dev_attr_bypass.attr, 391739f802d6STakashi Iwai &dev_attr_requested_microamps.attr, 391839f802d6STakashi Iwai &dev_attr_min_microvolts.attr, 391939f802d6STakashi Iwai &dev_attr_max_microvolts.attr, 392039f802d6STakashi Iwai &dev_attr_min_microamps.attr, 392139f802d6STakashi Iwai &dev_attr_max_microamps.attr, 392239f802d6STakashi Iwai &dev_attr_suspend_standby_state.attr, 392339f802d6STakashi Iwai &dev_attr_suspend_mem_state.attr, 392439f802d6STakashi Iwai &dev_attr_suspend_disk_state.attr, 392539f802d6STakashi Iwai &dev_attr_suspend_standby_microvolts.attr, 392639f802d6STakashi Iwai &dev_attr_suspend_mem_microvolts.attr, 392739f802d6STakashi Iwai &dev_attr_suspend_disk_microvolts.attr, 392839f802d6STakashi Iwai &dev_attr_suspend_standby_mode.attr, 392939f802d6STakashi Iwai &dev_attr_suspend_mem_mode.attr, 393039f802d6STakashi Iwai &dev_attr_suspend_disk_mode.attr, 393139f802d6STakashi Iwai NULL 393239f802d6STakashi Iwai }; 393339f802d6STakashi Iwai 39347ad68e2fSDavid Brownell /* 39357ad68e2fSDavid Brownell * To avoid cluttering sysfs (and memory) with useless state, only 39367ad68e2fSDavid Brownell * create attributes that can be meaningfully displayed. 39377ad68e2fSDavid Brownell */ 393839f802d6STakashi Iwai static umode_t regulator_attr_is_visible(struct kobject *kobj, 393939f802d6STakashi Iwai struct attribute *attr, int idx) 39407ad68e2fSDavid Brownell { 394139f802d6STakashi Iwai struct device *dev = kobj_to_dev(kobj); 394283080a14SGeliang Tang struct regulator_dev *rdev = dev_to_rdev(dev); 3943272e2315SGuodong Xu const struct regulator_ops *ops = rdev->desc->ops; 394439f802d6STakashi Iwai umode_t mode = attr->mode; 394539f802d6STakashi Iwai 394639f802d6STakashi Iwai /* these three are always present */ 394739f802d6STakashi Iwai if (attr == &dev_attr_name.attr || 394839f802d6STakashi Iwai attr == &dev_attr_num_users.attr || 394939f802d6STakashi Iwai attr == &dev_attr_type.attr) 395039f802d6STakashi Iwai return mode; 39517ad68e2fSDavid Brownell 39527ad68e2fSDavid Brownell /* some attributes need specific methods to be displayed */ 395339f802d6STakashi Iwai if (attr == &dev_attr_microvolts.attr) { 39544c78899bSMark Brown if ((ops->get_voltage && ops->get_voltage(rdev) >= 0) || 3955f2889e65SMark Brown (ops->get_voltage_sel && ops->get_voltage_sel(rdev) >= 0) || 39565a523605SLaxman Dewangan (ops->list_voltage && ops->list_voltage(rdev, 0) >= 0) || 395739f802d6STakashi Iwai (rdev->desc->fixed_uV && rdev->desc->n_voltages == 1)) 395839f802d6STakashi Iwai return mode; 395939f802d6STakashi Iwai return 0; 3960f59c8f9fSMark Brown } 39617ad68e2fSDavid Brownell 396239f802d6STakashi Iwai if (attr == &dev_attr_microamps.attr) 396339f802d6STakashi Iwai return ops->get_current_limit ? mode : 0; 396439f802d6STakashi Iwai 396539f802d6STakashi Iwai if (attr == &dev_attr_opmode.attr) 396639f802d6STakashi Iwai return ops->get_mode ? mode : 0; 396739f802d6STakashi Iwai 396839f802d6STakashi Iwai if (attr == &dev_attr_state.attr) 396939f802d6STakashi Iwai return (rdev->ena_pin || ops->is_enabled) ? mode : 0; 397039f802d6STakashi Iwai 397139f802d6STakashi Iwai if (attr == &dev_attr_status.attr) 397239f802d6STakashi Iwai return ops->get_status ? mode : 0; 397339f802d6STakashi Iwai 397439f802d6STakashi Iwai if (attr == &dev_attr_bypass.attr) 397539f802d6STakashi Iwai return ops->get_bypass ? mode : 0; 397639f802d6STakashi Iwai 39777ad68e2fSDavid Brownell /* some attributes are type-specific */ 397839f802d6STakashi Iwai if (attr == &dev_attr_requested_microamps.attr) 397939f802d6STakashi Iwai return rdev->desc->type == REGULATOR_CURRENT ? mode : 0; 39807ad68e2fSDavid Brownell 39817ad68e2fSDavid Brownell /* constraints need specific supporting methods */ 398239f802d6STakashi Iwai if (attr == &dev_attr_min_microvolts.attr || 398339f802d6STakashi Iwai attr == &dev_attr_max_microvolts.attr) 398439f802d6STakashi Iwai return (ops->set_voltage || ops->set_voltage_sel) ? mode : 0; 398539f802d6STakashi Iwai 398639f802d6STakashi Iwai if (attr == &dev_attr_min_microamps.attr || 398739f802d6STakashi Iwai attr == &dev_attr_max_microamps.attr) 398839f802d6STakashi Iwai return ops->set_current_limit ? mode : 0; 398939f802d6STakashi Iwai 399039f802d6STakashi Iwai if (attr == &dev_attr_suspend_standby_state.attr || 399139f802d6STakashi Iwai attr == &dev_attr_suspend_mem_state.attr || 399239f802d6STakashi Iwai attr == &dev_attr_suspend_disk_state.attr) 399339f802d6STakashi Iwai return mode; 399439f802d6STakashi Iwai 399539f802d6STakashi Iwai if (attr == &dev_attr_suspend_standby_microvolts.attr || 399639f802d6STakashi Iwai attr == &dev_attr_suspend_mem_microvolts.attr || 399739f802d6STakashi Iwai attr == &dev_attr_suspend_disk_microvolts.attr) 399839f802d6STakashi Iwai return ops->set_suspend_voltage ? mode : 0; 399939f802d6STakashi Iwai 400039f802d6STakashi Iwai if (attr == &dev_attr_suspend_standby_mode.attr || 400139f802d6STakashi Iwai attr == &dev_attr_suspend_mem_mode.attr || 400239f802d6STakashi Iwai attr == &dev_attr_suspend_disk_mode.attr) 400339f802d6STakashi Iwai return ops->set_suspend_mode ? mode : 0; 400439f802d6STakashi Iwai 400539f802d6STakashi Iwai return mode; 40067ad68e2fSDavid Brownell } 40077ad68e2fSDavid Brownell 400839f802d6STakashi Iwai static const struct attribute_group regulator_dev_group = { 400939f802d6STakashi Iwai .attrs = regulator_dev_attrs, 401039f802d6STakashi Iwai .is_visible = regulator_attr_is_visible, 401139f802d6STakashi Iwai }; 40127ad68e2fSDavid Brownell 401339f802d6STakashi Iwai static const struct attribute_group *regulator_dev_groups[] = { 401439f802d6STakashi Iwai ®ulator_dev_group, 401539f802d6STakashi Iwai NULL 401639f802d6STakashi Iwai }; 401739f802d6STakashi Iwai 401839f802d6STakashi Iwai static void regulator_dev_release(struct device *dev) 401939f802d6STakashi Iwai { 402039f802d6STakashi Iwai struct regulator_dev *rdev = dev_get_drvdata(dev); 402129f5f486SMark Brown 402229f5f486SMark Brown kfree(rdev->constraints); 402329f5f486SMark Brown of_node_put(rdev->dev.of_node); 402439f802d6STakashi Iwai kfree(rdev); 40257ad68e2fSDavid Brownell } 40267ad68e2fSDavid Brownell 40271130e5b3SMark Brown static void rdev_init_debugfs(struct regulator_dev *rdev) 40281130e5b3SMark Brown { 4029a9eaa813SGuenter Roeck struct device *parent = rdev->dev.parent; 4030a9eaa813SGuenter Roeck const char *rname = rdev_get_name(rdev); 4031a9eaa813SGuenter Roeck char name[NAME_MAX]; 4032a9eaa813SGuenter Roeck 4033a9eaa813SGuenter Roeck /* Avoid duplicate debugfs directory names */ 4034a9eaa813SGuenter Roeck if (parent && rname == rdev->desc->name) { 4035a9eaa813SGuenter Roeck snprintf(name, sizeof(name), "%s-%s", dev_name(parent), 4036a9eaa813SGuenter Roeck rname); 4037a9eaa813SGuenter Roeck rname = name; 4038a9eaa813SGuenter Roeck } 4039a9eaa813SGuenter Roeck 4040a9eaa813SGuenter Roeck rdev->debugfs = debugfs_create_dir(rname, debugfs_root); 404124751434SStephen Boyd if (!rdev->debugfs) { 40421130e5b3SMark Brown rdev_warn(rdev, "Failed to create debugfs directory\n"); 40431130e5b3SMark Brown return; 40441130e5b3SMark Brown } 40451130e5b3SMark Brown 40461130e5b3SMark Brown debugfs_create_u32("use_count", 0444, rdev->debugfs, 40471130e5b3SMark Brown &rdev->use_count); 40481130e5b3SMark Brown debugfs_create_u32("open_count", 0444, rdev->debugfs, 40491130e5b3SMark Brown &rdev->open_count); 4050f59c8f9fSMark Brown debugfs_create_u32("bypass_count", 0444, rdev->debugfs, 4051f59c8f9fSMark Brown &rdev->bypass_count); 40521130e5b3SMark Brown } 40531130e5b3SMark Brown 40545e3ca2b3SJavier Martinez Canillas static int regulator_register_resolve_supply(struct device *dev, void *data) 40555e3ca2b3SJavier Martinez Canillas { 40567ddede6aSJon Hunter struct regulator_dev *rdev = dev_to_rdev(dev); 40577ddede6aSJon Hunter 40587ddede6aSJon Hunter if (regulator_resolve_supply(rdev)) 40597ddede6aSJon Hunter rdev_dbg(rdev, "unable to resolve supply\n"); 40607ddede6aSJon Hunter 40617ddede6aSJon Hunter return 0; 40625e3ca2b3SJavier Martinez Canillas } 40635e3ca2b3SJavier Martinez Canillas 4064414c70cbSLiam Girdwood /** 4065414c70cbSLiam Girdwood * regulator_register - register regulator 406669279fb9SMark Brown * @regulator_desc: regulator to register 4067f47531b1SKrzysztof Kozlowski * @cfg: runtime configuration for regulator 4068414c70cbSLiam Girdwood * 4069414c70cbSLiam Girdwood * Called by regulator drivers to register a regulator. 40700384618aSAxel Lin * Returns a valid pointer to struct regulator_dev on success 40710384618aSAxel Lin * or an ERR_PTR() on error. 4072414c70cbSLiam Girdwood */ 407365f26846SMark Brown struct regulator_dev * 407465f26846SMark Brown regulator_register(const struct regulator_desc *regulator_desc, 40751b3de223SKrzysztof Kozlowski const struct regulator_config *cfg) 4076414c70cbSLiam Girdwood { 40779a8f5e07SMark Brown const struct regulation_constraints *constraints = NULL; 4078c172708dSMark Brown const struct regulator_init_data *init_data; 40791b3de223SKrzysztof Kozlowski struct regulator_config *config = NULL; 408072dca06fSAniroop Mathur static atomic_t regulator_no = ATOMIC_INIT(-1); 4081414c70cbSLiam Girdwood struct regulator_dev *rdev; 408232c8fad4SMark Brown struct device *dev; 4083a5766f11SLiam Girdwood int ret, i; 4084414c70cbSLiam Girdwood 40851b3de223SKrzysztof Kozlowski if (regulator_desc == NULL || cfg == NULL) 4086414c70cbSLiam Girdwood return ERR_PTR(-EINVAL); 4087414c70cbSLiam Girdwood 40881b3de223SKrzysztof Kozlowski dev = cfg->dev; 4089dcf70112SMark Brown WARN_ON(!dev); 409032c8fad4SMark Brown 4091414c70cbSLiam Girdwood if (regulator_desc->name == NULL || regulator_desc->ops == NULL) 4092414c70cbSLiam Girdwood return ERR_PTR(-EINVAL); 4093414c70cbSLiam Girdwood 4094cd78dfc6SDiego Liziero if (regulator_desc->type != REGULATOR_VOLTAGE && 4095cd78dfc6SDiego Liziero regulator_desc->type != REGULATOR_CURRENT) 4096414c70cbSLiam Girdwood return ERR_PTR(-EINVAL); 4097414c70cbSLiam Girdwood 4098476c2d83SMark Brown /* Only one of each should be implemented */ 4099476c2d83SMark Brown WARN_ON(regulator_desc->ops->get_voltage && 4100476c2d83SMark Brown regulator_desc->ops->get_voltage_sel); 4101e8eef82bSMark Brown WARN_ON(regulator_desc->ops->set_voltage && 4102e8eef82bSMark Brown regulator_desc->ops->set_voltage_sel); 4103476c2d83SMark Brown 4104476c2d83SMark Brown /* If we're using selectors we must implement list_voltage. */ 4105476c2d83SMark Brown if (regulator_desc->ops->get_voltage_sel && 4106476c2d83SMark Brown !regulator_desc->ops->list_voltage) { 4107476c2d83SMark Brown return ERR_PTR(-EINVAL); 4108476c2d83SMark Brown } 4109e8eef82bSMark Brown if (regulator_desc->ops->set_voltage_sel && 4110e8eef82bSMark Brown !regulator_desc->ops->list_voltage) { 4111e8eef82bSMark Brown return ERR_PTR(-EINVAL); 4112e8eef82bSMark Brown } 4113476c2d83SMark Brown 4114414c70cbSLiam Girdwood rdev = kzalloc(sizeof(struct regulator_dev), GFP_KERNEL); 4115414c70cbSLiam Girdwood if (rdev == NULL) 4116414c70cbSLiam Girdwood return ERR_PTR(-ENOMEM); 4117414c70cbSLiam Girdwood 41181b3de223SKrzysztof Kozlowski /* 41191b3de223SKrzysztof Kozlowski * Duplicate the config so the driver could override it after 41201b3de223SKrzysztof Kozlowski * parsing init data. 41211b3de223SKrzysztof Kozlowski */ 41221b3de223SKrzysztof Kozlowski config = kmemdup(cfg, sizeof(*cfg), GFP_KERNEL); 41231b3de223SKrzysztof Kozlowski if (config == NULL) { 41241b3de223SKrzysztof Kozlowski kfree(rdev); 41251b3de223SKrzysztof Kozlowski return ERR_PTR(-ENOMEM); 41261b3de223SKrzysztof Kozlowski } 41271b3de223SKrzysztof Kozlowski 4128bfa21a0dSKrzysztof Kozlowski init_data = regulator_of_get_init_data(dev, regulator_desc, config, 4129a0c7b164SMark Brown &rdev->dev.of_node); 4130a0c7b164SMark Brown if (!init_data) { 4131a0c7b164SMark Brown init_data = config->init_data; 4132a0c7b164SMark Brown rdev->dev.of_node = of_node_get(config->of_node); 4133a0c7b164SMark Brown } 4134a0c7b164SMark Brown 4135414c70cbSLiam Girdwood mutex_init(&rdev->mutex); 4136c172708dSMark Brown rdev->reg_data = config->driver_data; 4137414c70cbSLiam Girdwood rdev->owner = regulator_desc->owner; 4138414c70cbSLiam Girdwood rdev->desc = regulator_desc; 41393a4b0a07SMark Brown if (config->regmap) 414065b19ce6SMark Brown rdev->regmap = config->regmap; 414152b84dacSAnilKumar Ch else if (dev_get_regmap(dev, NULL)) 41423a4b0a07SMark Brown rdev->regmap = dev_get_regmap(dev, NULL); 414352b84dacSAnilKumar Ch else if (dev->parent) 414452b84dacSAnilKumar Ch rdev->regmap = dev_get_regmap(dev->parent, NULL); 4145414c70cbSLiam Girdwood INIT_LIST_HEAD(&rdev->consumer_list); 4146414c70cbSLiam Girdwood INIT_LIST_HEAD(&rdev->list); 4147414c70cbSLiam Girdwood BLOCKING_INIT_NOTIFIER_HEAD(&rdev->notifier); 4148da07ecd9SMark Brown INIT_DELAYED_WORK(&rdev->disable_work, regulator_disable_work); 4149414c70cbSLiam Girdwood 4150a5766f11SLiam Girdwood /* preform any regulator specific init */ 41519a8f5e07SMark Brown if (init_data && init_data->regulator_init) { 4152a5766f11SLiam Girdwood ret = init_data->regulator_init(rdev->reg_data); 41534fca9545SDavid Brownell if (ret < 0) 41544fca9545SDavid Brownell goto clean; 4155a5766f11SLiam Girdwood } 4156a5766f11SLiam Girdwood 4157daad134dSKrzysztof Adamski if ((config->ena_gpio || config->ena_gpio_initialized) && 4158daad134dSKrzysztof Adamski gpio_is_valid(config->ena_gpio)) { 415945389c47SJon Hunter mutex_lock(®ulator_list_mutex); 4160daad134dSKrzysztof Adamski ret = regulator_ena_gpio_request(rdev, config); 416145389c47SJon Hunter mutex_unlock(®ulator_list_mutex); 4162daad134dSKrzysztof Adamski if (ret != 0) { 4163daad134dSKrzysztof Adamski rdev_err(rdev, "Failed to request enable GPIO%d: %d\n", 4164daad134dSKrzysztof Adamski config->ena_gpio, ret); 416532165230SKrzysztof Adamski goto clean; 4166daad134dSKrzysztof Adamski } 4167daad134dSKrzysztof Adamski } 4168daad134dSKrzysztof Adamski 4169a5766f11SLiam Girdwood /* register with sysfs */ 4170a5766f11SLiam Girdwood rdev->dev.class = ®ulator_class; 4171a5766f11SLiam Girdwood rdev->dev.parent = dev; 417272dca06fSAniroop Mathur dev_set_name(&rdev->dev, "regulator.%lu", 417339138818SAniroop Mathur (unsigned long) atomic_inc_return(®ulator_no)); 4174a5766f11SLiam Girdwood 417574f544c1SMike Rapoport /* set regulator constraints */ 41769a8f5e07SMark Brown if (init_data) 41779a8f5e07SMark Brown constraints = &init_data->constraints; 41789a8f5e07SMark Brown 41799a8f5e07SMark Brown if (init_data && init_data->supply_regulator) 41806261b06dSBjorn Andersson rdev->supply_name = init_data->supply_regulator; 418169511a45SRajendra Nayak else if (regulator_desc->supply_name) 41826261b06dSBjorn Andersson rdev->supply_name = regulator_desc->supply_name; 418369511a45SRajendra Nayak 418445389c47SJon Hunter /* 418545389c47SJon Hunter * Attempt to resolve the regulator supply, if specified, 418645389c47SJon Hunter * but don't return an error if we fail because we will try 418745389c47SJon Hunter * to resolve it again later as more regulators are added. 418845389c47SJon Hunter */ 418945389c47SJon Hunter if (regulator_resolve_supply(rdev)) 419045389c47SJon Hunter rdev_dbg(rdev, "unable to resolve supply\n"); 419145389c47SJon Hunter 419245389c47SJon Hunter ret = set_machine_constraints(rdev, constraints); 419345389c47SJon Hunter if (ret < 0) 419445389c47SJon Hunter goto wash; 419545389c47SJon Hunter 4196a5766f11SLiam Girdwood /* add consumers devices */ 41979a8f5e07SMark Brown if (init_data) { 419845389c47SJon Hunter mutex_lock(®ulator_list_mutex); 4199a5766f11SLiam Girdwood for (i = 0; i < init_data->num_consumer_supplies; i++) { 4200a5766f11SLiam Girdwood ret = set_consumer_device_supply(rdev, 420140f9244fSMark Brown init_data->consumer_supplies[i].dev_name, 4202a5766f11SLiam Girdwood init_data->consumer_supplies[i].supply); 420323c2f041SMark Brown if (ret < 0) { 420445389c47SJon Hunter mutex_unlock(®ulator_list_mutex); 420523c2f041SMark Brown dev_err(dev, "Failed to set supply %s\n", 420623c2f041SMark Brown init_data->consumer_supplies[i].supply); 4207d4033b54SJani Nikula goto unset_supplies; 4208a5766f11SLiam Girdwood } 420923c2f041SMark Brown } 4210a2151374SJon Hunter mutex_unlock(®ulator_list_mutex); 42119a8f5e07SMark Brown } 4212a5766f11SLiam Girdwood 4213fd086045SMatthias Kaehlcke if (!rdev->desc->ops->get_voltage && 4214fd086045SMatthias Kaehlcke !rdev->desc->ops->list_voltage && 4215fd086045SMatthias Kaehlcke !rdev->desc->fixed_uV) 4216fd086045SMatthias Kaehlcke rdev->is_switch = true; 4217fd086045SMatthias Kaehlcke 4218c438b9d0SJon Hunter ret = device_register(&rdev->dev); 4219c438b9d0SJon Hunter if (ret != 0) { 4220c438b9d0SJon Hunter put_device(&rdev->dev); 4221c438b9d0SJon Hunter goto unset_supplies; 4222c438b9d0SJon Hunter } 4223c438b9d0SJon Hunter 4224c438b9d0SJon Hunter dev_set_drvdata(&rdev->dev, rdev); 42251130e5b3SMark Brown rdev_init_debugfs(rdev); 42265e3ca2b3SJavier Martinez Canillas 42275e3ca2b3SJavier Martinez Canillas /* try to resolve regulators supply since a new one was registered */ 42285e3ca2b3SJavier Martinez Canillas class_for_each_device(®ulator_class, NULL, NULL, 42295e3ca2b3SJavier Martinez Canillas regulator_register_resolve_supply); 42301b3de223SKrzysztof Kozlowski kfree(config); 4231414c70cbSLiam Girdwood return rdev; 42324fca9545SDavid Brownell 4233d4033b54SJani Nikula unset_supplies: 423445389c47SJon Hunter mutex_lock(®ulator_list_mutex); 4235d4033b54SJani Nikula unset_regulator_supplies(rdev); 423645389c47SJon Hunter mutex_unlock(®ulator_list_mutex); 423732165230SKrzysztof Adamski wash: 4238469b640eSBoris Brezillon kfree(rdev->constraints); 423945389c47SJon Hunter mutex_lock(®ulator_list_mutex); 424032165230SKrzysztof Adamski regulator_ena_gpio_free(rdev); 424145389c47SJon Hunter mutex_unlock(®ulator_list_mutex); 42424fca9545SDavid Brownell clean: 42434fca9545SDavid Brownell kfree(rdev); 4244a2151374SJon Hunter kfree(config); 4245a2151374SJon Hunter return ERR_PTR(ret); 4246414c70cbSLiam Girdwood } 4247414c70cbSLiam Girdwood EXPORT_SYMBOL_GPL(regulator_register); 4248414c70cbSLiam Girdwood 4249414c70cbSLiam Girdwood /** 4250414c70cbSLiam Girdwood * regulator_unregister - unregister regulator 425169279fb9SMark Brown * @rdev: regulator to unregister 4252414c70cbSLiam Girdwood * 4253414c70cbSLiam Girdwood * Called by regulator drivers to unregister a regulator. 4254414c70cbSLiam Girdwood */ 4255414c70cbSLiam Girdwood void regulator_unregister(struct regulator_dev *rdev) 4256414c70cbSLiam Girdwood { 4257414c70cbSLiam Girdwood if (rdev == NULL) 4258414c70cbSLiam Girdwood return; 4259414c70cbSLiam Girdwood 4260891636eaSMark Brown if (rdev->supply) { 4261891636eaSMark Brown while (rdev->use_count--) 4262891636eaSMark Brown regulator_disable(rdev->supply); 4263e032b376SMark Brown regulator_put(rdev->supply); 4264891636eaSMark Brown } 4265414c70cbSLiam Girdwood mutex_lock(®ulator_list_mutex); 42661130e5b3SMark Brown debugfs_remove_recursive(rdev->debugfs); 426743829731STejun Heo flush_work(&rdev->disable_work.work); 42686bf87d17SMark Brown WARN_ON(rdev->open_count); 42690f1d747bSMike Rapoport unset_regulator_supplies(rdev); 4270414c70cbSLiam Girdwood list_del(&rdev->list); 4271f19b00daSKim, Milo regulator_ena_gpio_free(rdev); 42722c0a303aSMark Brown mutex_unlock(®ulator_list_mutex); 427358fb5cf5SLothar Waßmann device_unregister(&rdev->dev); 4274414c70cbSLiam Girdwood } 4275414c70cbSLiam Girdwood EXPORT_SYMBOL_GPL(regulator_unregister); 4276414c70cbSLiam Girdwood 4277f7efad10SChunyan Zhang #ifdef CONFIG_SUSPEND 4278f7efad10SChunyan Zhang static int _regulator_suspend_late(struct device *dev, void *data) 427985f3b431STomeu Vizoso { 428085f3b431STomeu Vizoso struct regulator_dev *rdev = dev_to_rdev(dev); 4281f7efad10SChunyan Zhang suspend_state_t *state = data; 428285f3b431STomeu Vizoso int ret; 428385f3b431STomeu Vizoso 428485f3b431STomeu Vizoso mutex_lock(&rdev->mutex); 4285f7efad10SChunyan Zhang ret = suspend_set_state(rdev, *state); 428685f3b431STomeu Vizoso mutex_unlock(&rdev->mutex); 428785f3b431STomeu Vizoso 428885f3b431STomeu Vizoso return ret; 428985f3b431STomeu Vizoso } 429085f3b431STomeu Vizoso 4291414c70cbSLiam Girdwood /** 4292f7efad10SChunyan Zhang * regulator_suspend_late - prepare regulators for system wide suspend 4293414c70cbSLiam Girdwood * @state: system suspend state 4294414c70cbSLiam Girdwood * 4295414c70cbSLiam Girdwood * Configure each regulator with it's suspend operating parameters for state. 4296414c70cbSLiam Girdwood */ 4297f7efad10SChunyan Zhang static int regulator_suspend_late(struct device *dev) 4298414c70cbSLiam Girdwood { 4299f7efad10SChunyan Zhang suspend_state_t state = pm_suspend_target_state; 4300414c70cbSLiam Girdwood 430185f3b431STomeu Vizoso return class_for_each_device(®ulator_class, NULL, &state, 4302f7efad10SChunyan Zhang _regulator_suspend_late); 4303414c70cbSLiam Girdwood } 4304f7efad10SChunyan Zhang static int _regulator_resume_early(struct device *dev, void *data) 430585f3b431STomeu Vizoso { 4306f7efad10SChunyan Zhang int ret = 0; 430785f3b431STomeu Vizoso struct regulator_dev *rdev = dev_to_rdev(dev); 4308f7efad10SChunyan Zhang suspend_state_t *state = data; 4309f7efad10SChunyan Zhang struct regulator_state *rstate; 4310f7efad10SChunyan Zhang 4311f7efad10SChunyan Zhang rstate = regulator_get_suspend_state(rdev, *state); 4312f7efad10SChunyan Zhang if (rstate == NULL) 4313f7efad10SChunyan Zhang return -EINVAL; 431485f3b431STomeu Vizoso 431585f3b431STomeu Vizoso mutex_lock(&rdev->mutex); 431685f3b431STomeu Vizoso 4317f7efad10SChunyan Zhang if (rdev->desc->ops->resume_early && 4318f7efad10SChunyan Zhang (rstate->enabled == ENABLE_IN_SUSPEND || 4319f7efad10SChunyan Zhang rstate->enabled == DISABLE_IN_SUSPEND)) 4320f7efad10SChunyan Zhang ret = rdev->desc->ops->resume_early(rdev); 4321f7efad10SChunyan Zhang 432285f3b431STomeu Vizoso mutex_unlock(&rdev->mutex); 432385f3b431STomeu Vizoso 4324f7efad10SChunyan Zhang return ret; 432585f3b431STomeu Vizoso } 432685f3b431STomeu Vizoso 4327f7efad10SChunyan Zhang static int regulator_resume_early(struct device *dev) 43287a32b589SMyungJoo Ham { 4329f7efad10SChunyan Zhang suspend_state_t state = pm_suspend_target_state; 43307a32b589SMyungJoo Ham 4331f7efad10SChunyan Zhang return class_for_each_device(®ulator_class, NULL, &state, 4332f7efad10SChunyan Zhang _regulator_resume_early); 4333f7efad10SChunyan Zhang } 4334f7efad10SChunyan Zhang 4335f7efad10SChunyan Zhang #else /* !CONFIG_SUSPEND */ 4336f7efad10SChunyan Zhang 4337f7efad10SChunyan Zhang #define regulator_suspend_late NULL 4338f7efad10SChunyan Zhang #define regulator_resume_early NULL 4339f7efad10SChunyan Zhang 4340f7efad10SChunyan Zhang #endif /* !CONFIG_SUSPEND */ 4341f7efad10SChunyan Zhang 4342f7efad10SChunyan Zhang #ifdef CONFIG_PM 4343f7efad10SChunyan Zhang static const struct dev_pm_ops __maybe_unused regulator_pm_ops = { 4344f7efad10SChunyan Zhang .suspend_late = regulator_suspend_late, 4345f7efad10SChunyan Zhang .resume_early = regulator_resume_early, 4346f7efad10SChunyan Zhang }; 4347f7efad10SChunyan Zhang #endif 4348f7efad10SChunyan Zhang 4349285c22deSMark Brown struct class regulator_class = { 4350f7efad10SChunyan Zhang .name = "regulator", 4351f7efad10SChunyan Zhang .dev_release = regulator_dev_release, 4352f7efad10SChunyan Zhang .dev_groups = regulator_dev_groups, 4353f7efad10SChunyan Zhang #ifdef CONFIG_PM 4354f7efad10SChunyan Zhang .pm = ®ulator_pm_ops, 4355f7efad10SChunyan Zhang #endif 4356f7efad10SChunyan Zhang }; 43577a32b589SMyungJoo Ham /** 4358ca725561SMark Brown * regulator_has_full_constraints - the system has fully specified constraints 4359ca725561SMark Brown * 4360ca725561SMark Brown * Calling this function will cause the regulator API to disable all 4361ca725561SMark Brown * regulators which have a zero use count and don't have an always_on 4362ca725561SMark Brown * constraint in a late_initcall. 4363ca725561SMark Brown * 4364ca725561SMark Brown * The intention is that this will become the default behaviour in a 4365ca725561SMark Brown * future kernel release so users are encouraged to use this facility 4366ca725561SMark Brown * now. 4367ca725561SMark Brown */ 4368ca725561SMark Brown void regulator_has_full_constraints(void) 4369ca725561SMark Brown { 4370ca725561SMark Brown has_full_constraints = 1; 4371ca725561SMark Brown } 4372ca725561SMark Brown EXPORT_SYMBOL_GPL(regulator_has_full_constraints); 4373ca725561SMark Brown 4374ca725561SMark Brown /** 4375414c70cbSLiam Girdwood * rdev_get_drvdata - get rdev regulator driver data 437669279fb9SMark Brown * @rdev: regulator 4377414c70cbSLiam Girdwood * 4378414c70cbSLiam Girdwood * Get rdev regulator driver private data. This call can be used in the 4379414c70cbSLiam Girdwood * regulator driver context. 4380414c70cbSLiam Girdwood */ 4381414c70cbSLiam Girdwood void *rdev_get_drvdata(struct regulator_dev *rdev) 4382414c70cbSLiam Girdwood { 4383414c70cbSLiam Girdwood return rdev->reg_data; 4384414c70cbSLiam Girdwood } 4385414c70cbSLiam Girdwood EXPORT_SYMBOL_GPL(rdev_get_drvdata); 4386414c70cbSLiam Girdwood 4387414c70cbSLiam Girdwood /** 4388414c70cbSLiam Girdwood * regulator_get_drvdata - get regulator driver data 4389414c70cbSLiam Girdwood * @regulator: regulator 4390414c70cbSLiam Girdwood * 4391414c70cbSLiam Girdwood * Get regulator driver private data. This call can be used in the consumer 4392414c70cbSLiam Girdwood * driver context when non API regulator specific functions need to be called. 4393414c70cbSLiam Girdwood */ 4394414c70cbSLiam Girdwood void *regulator_get_drvdata(struct regulator *regulator) 4395414c70cbSLiam Girdwood { 4396414c70cbSLiam Girdwood return regulator->rdev->reg_data; 4397414c70cbSLiam Girdwood } 4398414c70cbSLiam Girdwood EXPORT_SYMBOL_GPL(regulator_get_drvdata); 4399414c70cbSLiam Girdwood 4400414c70cbSLiam Girdwood /** 4401414c70cbSLiam Girdwood * regulator_set_drvdata - set regulator driver data 4402414c70cbSLiam Girdwood * @regulator: regulator 4403414c70cbSLiam Girdwood * @data: data 4404414c70cbSLiam Girdwood */ 4405414c70cbSLiam Girdwood void regulator_set_drvdata(struct regulator *regulator, void *data) 4406414c70cbSLiam Girdwood { 4407414c70cbSLiam Girdwood regulator->rdev->reg_data = data; 4408414c70cbSLiam Girdwood } 4409414c70cbSLiam Girdwood EXPORT_SYMBOL_GPL(regulator_set_drvdata); 4410414c70cbSLiam Girdwood 4411414c70cbSLiam Girdwood /** 4412414c70cbSLiam Girdwood * regulator_get_id - get regulator ID 441369279fb9SMark Brown * @rdev: regulator 4414414c70cbSLiam Girdwood */ 4415414c70cbSLiam Girdwood int rdev_get_id(struct regulator_dev *rdev) 4416414c70cbSLiam Girdwood { 4417414c70cbSLiam Girdwood return rdev->desc->id; 4418414c70cbSLiam Girdwood } 4419414c70cbSLiam Girdwood EXPORT_SYMBOL_GPL(rdev_get_id); 4420414c70cbSLiam Girdwood 4421a5766f11SLiam Girdwood struct device *rdev_get_dev(struct regulator_dev *rdev) 4422a5766f11SLiam Girdwood { 4423a5766f11SLiam Girdwood return &rdev->dev; 4424a5766f11SLiam Girdwood } 4425a5766f11SLiam Girdwood EXPORT_SYMBOL_GPL(rdev_get_dev); 4426a5766f11SLiam Girdwood 4427a5766f11SLiam Girdwood void *regulator_get_init_drvdata(struct regulator_init_data *reg_init_data) 4428a5766f11SLiam Girdwood { 4429a5766f11SLiam Girdwood return reg_init_data->driver_data; 4430a5766f11SLiam Girdwood } 4431a5766f11SLiam Girdwood EXPORT_SYMBOL_GPL(regulator_get_init_drvdata); 4432a5766f11SLiam Girdwood 4433ba55a974SMark Brown #ifdef CONFIG_DEBUG_FS 4434dbc55955SHaishan Zhou static int supply_map_show(struct seq_file *sf, void *data) 4435ba55a974SMark Brown { 4436ba55a974SMark Brown struct regulator_map *map; 4437ba55a974SMark Brown 4438ba55a974SMark Brown list_for_each_entry(map, ®ulator_map_list, list) { 4439dbc55955SHaishan Zhou seq_printf(sf, "%s -> %s.%s\n", 4440ba55a974SMark Brown rdev_get_name(map->regulator), map->dev_name, 4441ba55a974SMark Brown map->supply); 4442ba55a974SMark Brown } 4443ba55a974SMark Brown 4444dbc55955SHaishan Zhou return 0; 4445dbc55955SHaishan Zhou } 4446ba55a974SMark Brown 4447dbc55955SHaishan Zhou static int supply_map_open(struct inode *inode, struct file *file) 4448dbc55955SHaishan Zhou { 4449dbc55955SHaishan Zhou return single_open(file, supply_map_show, inode->i_private); 4450ba55a974SMark Brown } 445124751434SStephen Boyd #endif 4452ba55a974SMark Brown 4453ba55a974SMark Brown static const struct file_operations supply_map_fops = { 445424751434SStephen Boyd #ifdef CONFIG_DEBUG_FS 4455dbc55955SHaishan Zhou .open = supply_map_open, 4456dbc55955SHaishan Zhou .read = seq_read, 4457dbc55955SHaishan Zhou .llseek = seq_lseek, 4458dbc55955SHaishan Zhou .release = single_release, 4459ba55a974SMark Brown #endif 446024751434SStephen Boyd }; 4461ba55a974SMark Brown 44627c225ec9SHeiko Stübner #ifdef CONFIG_DEBUG_FS 446385f3b431STomeu Vizoso struct summary_data { 446485f3b431STomeu Vizoso struct seq_file *s; 446585f3b431STomeu Vizoso struct regulator_dev *parent; 446685f3b431STomeu Vizoso int level; 446785f3b431STomeu Vizoso }; 446885f3b431STomeu Vizoso 446985f3b431STomeu Vizoso static void regulator_summary_show_subtree(struct seq_file *s, 447085f3b431STomeu Vizoso struct regulator_dev *rdev, 447185f3b431STomeu Vizoso int level); 447285f3b431STomeu Vizoso 447385f3b431STomeu Vizoso static int regulator_summary_show_children(struct device *dev, void *data) 447485f3b431STomeu Vizoso { 447585f3b431STomeu Vizoso struct regulator_dev *rdev = dev_to_rdev(dev); 447685f3b431STomeu Vizoso struct summary_data *summary_data = data; 447785f3b431STomeu Vizoso 447885f3b431STomeu Vizoso if (rdev->supply && rdev->supply->rdev == summary_data->parent) 447985f3b431STomeu Vizoso regulator_summary_show_subtree(summary_data->s, rdev, 448085f3b431STomeu Vizoso summary_data->level + 1); 448185f3b431STomeu Vizoso 448285f3b431STomeu Vizoso return 0; 448385f3b431STomeu Vizoso } 448485f3b431STomeu Vizoso 44857c225ec9SHeiko Stübner static void regulator_summary_show_subtree(struct seq_file *s, 44867c225ec9SHeiko Stübner struct regulator_dev *rdev, 44877c225ec9SHeiko Stübner int level) 44887c225ec9SHeiko Stübner { 44897c225ec9SHeiko Stübner struct regulation_constraints *c; 44907c225ec9SHeiko Stübner struct regulator *consumer; 449185f3b431STomeu Vizoso struct summary_data summary_data; 44927c225ec9SHeiko Stübner 44937c225ec9SHeiko Stübner if (!rdev) 44947c225ec9SHeiko Stübner return; 44957c225ec9SHeiko Stübner 44967c225ec9SHeiko Stübner seq_printf(s, "%*s%-*s %3d %4d %6d ", 44977c225ec9SHeiko Stübner level * 3 + 1, "", 44987c225ec9SHeiko Stübner 30 - level * 3, rdev_get_name(rdev), 44997c225ec9SHeiko Stübner rdev->use_count, rdev->open_count, rdev->bypass_count); 45007c225ec9SHeiko Stübner 450123296099SHeiko Stübner seq_printf(s, "%5dmV ", _regulator_get_voltage(rdev) / 1000); 450223296099SHeiko Stübner seq_printf(s, "%5dmA ", _regulator_get_current_limit(rdev) / 1000); 45037c225ec9SHeiko Stübner 45047c225ec9SHeiko Stübner c = rdev->constraints; 45057c225ec9SHeiko Stübner if (c) { 45067c225ec9SHeiko Stübner switch (rdev->desc->type) { 45077c225ec9SHeiko Stübner case REGULATOR_VOLTAGE: 45087c225ec9SHeiko Stübner seq_printf(s, "%5dmV %5dmV ", 45097c225ec9SHeiko Stübner c->min_uV / 1000, c->max_uV / 1000); 45107c225ec9SHeiko Stübner break; 45117c225ec9SHeiko Stübner case REGULATOR_CURRENT: 45127c225ec9SHeiko Stübner seq_printf(s, "%5dmA %5dmA ", 45137c225ec9SHeiko Stübner c->min_uA / 1000, c->max_uA / 1000); 45147c225ec9SHeiko Stübner break; 45157c225ec9SHeiko Stübner } 45167c225ec9SHeiko Stübner } 45177c225ec9SHeiko Stübner 45187c225ec9SHeiko Stübner seq_puts(s, "\n"); 45197c225ec9SHeiko Stübner 45207c225ec9SHeiko Stübner list_for_each_entry(consumer, &rdev->consumer_list, list) { 4521e42a46b6SLeonard Crestez if (consumer->dev && consumer->dev->class == ®ulator_class) 45227c225ec9SHeiko Stübner continue; 45237c225ec9SHeiko Stübner 45247c225ec9SHeiko Stübner seq_printf(s, "%*s%-*s ", 45257c225ec9SHeiko Stübner (level + 1) * 3 + 1, "", 4526e42a46b6SLeonard Crestez 30 - (level + 1) * 3, 4527e42a46b6SLeonard Crestez consumer->dev ? dev_name(consumer->dev) : "deviceless"); 45287c225ec9SHeiko Stübner 45297c225ec9SHeiko Stübner switch (rdev->desc->type) { 45307c225ec9SHeiko Stübner case REGULATOR_VOLTAGE: 453123296099SHeiko Stübner seq_printf(s, "%37dmV %5dmV", 4532c360a6dfSChunyan Zhang consumer->voltage[PM_SUSPEND_ON].min_uV / 1000, 4533c360a6dfSChunyan Zhang consumer->voltage[PM_SUSPEND_ON].max_uV / 1000); 45347c225ec9SHeiko Stübner break; 45357c225ec9SHeiko Stübner case REGULATOR_CURRENT: 45367c225ec9SHeiko Stübner break; 45377c225ec9SHeiko Stübner } 45387c225ec9SHeiko Stübner 45397c225ec9SHeiko Stübner seq_puts(s, "\n"); 45407c225ec9SHeiko Stübner } 45417c225ec9SHeiko Stübner 454285f3b431STomeu Vizoso summary_data.s = s; 454385f3b431STomeu Vizoso summary_data.level = level; 454485f3b431STomeu Vizoso summary_data.parent = rdev; 45457c225ec9SHeiko Stübner 454685f3b431STomeu Vizoso class_for_each_device(®ulator_class, NULL, &summary_data, 454785f3b431STomeu Vizoso regulator_summary_show_children); 45487c225ec9SHeiko Stübner } 454985f3b431STomeu Vizoso 455085f3b431STomeu Vizoso static int regulator_summary_show_roots(struct device *dev, void *data) 455185f3b431STomeu Vizoso { 455285f3b431STomeu Vizoso struct regulator_dev *rdev = dev_to_rdev(dev); 455385f3b431STomeu Vizoso struct seq_file *s = data; 455485f3b431STomeu Vizoso 455585f3b431STomeu Vizoso if (!rdev->supply) 455685f3b431STomeu Vizoso regulator_summary_show_subtree(s, rdev, 0); 455785f3b431STomeu Vizoso 455885f3b431STomeu Vizoso return 0; 45597c225ec9SHeiko Stübner } 45607c225ec9SHeiko Stübner 45617c225ec9SHeiko Stübner static int regulator_summary_show(struct seq_file *s, void *data) 45627c225ec9SHeiko Stübner { 456323296099SHeiko Stübner seq_puts(s, " regulator use open bypass voltage current min max\n"); 456423296099SHeiko Stübner seq_puts(s, "-------------------------------------------------------------------------------\n"); 45657c225ec9SHeiko Stübner 456685f3b431STomeu Vizoso class_for_each_device(®ulator_class, NULL, s, 456785f3b431STomeu Vizoso regulator_summary_show_roots); 45687c225ec9SHeiko Stübner 45697c225ec9SHeiko Stübner return 0; 45707c225ec9SHeiko Stübner } 45717c225ec9SHeiko Stübner 45727c225ec9SHeiko Stübner static int regulator_summary_open(struct inode *inode, struct file *file) 45737c225ec9SHeiko Stübner { 45747c225ec9SHeiko Stübner return single_open(file, regulator_summary_show, inode->i_private); 45757c225ec9SHeiko Stübner } 45767c225ec9SHeiko Stübner #endif 45777c225ec9SHeiko Stübner 45787c225ec9SHeiko Stübner static const struct file_operations regulator_summary_fops = { 45797c225ec9SHeiko Stübner #ifdef CONFIG_DEBUG_FS 45807c225ec9SHeiko Stübner .open = regulator_summary_open, 45817c225ec9SHeiko Stübner .read = seq_read, 45827c225ec9SHeiko Stübner .llseek = seq_lseek, 45837c225ec9SHeiko Stübner .release = single_release, 45847c225ec9SHeiko Stübner #endif 45857c225ec9SHeiko Stübner }; 45867c225ec9SHeiko Stübner 4587414c70cbSLiam Girdwood static int __init regulator_init(void) 4588414c70cbSLiam Girdwood { 458934abbd68SMark Brown int ret; 459034abbd68SMark Brown 459134abbd68SMark Brown ret = class_register(®ulator_class); 459234abbd68SMark Brown 45931130e5b3SMark Brown debugfs_root = debugfs_create_dir("regulator", NULL); 459424751434SStephen Boyd if (!debugfs_root) 45951130e5b3SMark Brown pr_warn("regulator: Failed to create debugfs directory\n"); 4596ba55a974SMark Brown 4597f4d562c6SMark Brown debugfs_create_file("supply_map", 0444, debugfs_root, NULL, 4598f4d562c6SMark Brown &supply_map_fops); 45991130e5b3SMark Brown 46007c225ec9SHeiko Stübner debugfs_create_file("regulator_summary", 0444, debugfs_root, 460185f3b431STomeu Vizoso NULL, ®ulator_summary_fops); 46027c225ec9SHeiko Stübner 460334abbd68SMark Brown regulator_dummy_init(); 460434abbd68SMark Brown 460534abbd68SMark Brown return ret; 4606414c70cbSLiam Girdwood } 4607414c70cbSLiam Girdwood 4608414c70cbSLiam Girdwood /* init early to allow our consumers to complete system booting */ 4609414c70cbSLiam Girdwood core_initcall(regulator_init); 4610ca725561SMark Brown 4611609ca5f3SMark Brown static int __init regulator_late_cleanup(struct device *dev, void *data) 4612ca725561SMark Brown { 4613609ca5f3SMark Brown struct regulator_dev *rdev = dev_to_rdev(dev); 4614609ca5f3SMark Brown const struct regulator_ops *ops = rdev->desc->ops; 4615609ca5f3SMark Brown struct regulation_constraints *c = rdev->constraints; 4616ca725561SMark Brown int enabled, ret; 4617ca725561SMark Brown 461866fda75fSMarkus Pargmann if (c && c->always_on) 4619609ca5f3SMark Brown return 0; 4620ca725561SMark Brown 46218a34e979SWEN Pingbo if (!regulator_ops_is_valid(rdev, REGULATOR_CHANGE_STATUS)) 4622609ca5f3SMark Brown return 0; 4623e9535834SMark Brown 4624ca725561SMark Brown mutex_lock(&rdev->mutex); 4625ca725561SMark Brown 4626ca725561SMark Brown if (rdev->use_count) 4627ca725561SMark Brown goto unlock; 4628ca725561SMark Brown 4629ca725561SMark Brown /* If we can't read the status assume it's on. */ 4630ca725561SMark Brown if (ops->is_enabled) 4631ca725561SMark Brown enabled = ops->is_enabled(rdev); 4632ca725561SMark Brown else 4633ca725561SMark Brown enabled = 1; 4634ca725561SMark Brown 4635ca725561SMark Brown if (!enabled) 4636ca725561SMark Brown goto unlock; 4637ca725561SMark Brown 463887b28417SMark Brown if (have_full_constraints()) { 4639609ca5f3SMark Brown /* We log since this may kill the system if it goes 4640609ca5f3SMark Brown * wrong. */ 46415da84fd9SJoe Perches rdev_info(rdev, "disabling\n"); 464266fda75fSMarkus Pargmann ret = _regulator_do_disable(rdev); 46430d25d09dSJingoo Han if (ret != 0) 46445da84fd9SJoe Perches rdev_err(rdev, "couldn't disable: %d\n", ret); 4645ca725561SMark Brown } else { 4646ca725561SMark Brown /* The intention is that in future we will 4647ca725561SMark Brown * assume that full constraints are provided 4648ca725561SMark Brown * so warn even if we aren't going to do 4649ca725561SMark Brown * anything here. 4650ca725561SMark Brown */ 46515da84fd9SJoe Perches rdev_warn(rdev, "incomplete constraints, leaving on\n"); 4652ca725561SMark Brown } 4653ca725561SMark Brown 4654ca725561SMark Brown unlock: 4655ca725561SMark Brown mutex_unlock(&rdev->mutex); 4656609ca5f3SMark Brown 4657609ca5f3SMark Brown return 0; 4658ca725561SMark Brown } 4659ca725561SMark Brown 4660609ca5f3SMark Brown static int __init regulator_init_complete(void) 4661609ca5f3SMark Brown { 4662609ca5f3SMark Brown /* 4663609ca5f3SMark Brown * Since DT doesn't provide an idiomatic mechanism for 4664609ca5f3SMark Brown * enabling full constraints and since it's much more natural 4665609ca5f3SMark Brown * with DT to provide them just assume that a DT enabled 4666609ca5f3SMark Brown * system has full constraints. 4667609ca5f3SMark Brown */ 4668609ca5f3SMark Brown if (of_have_populated_dt()) 4669609ca5f3SMark Brown has_full_constraints = true; 4670609ca5f3SMark Brown 46713827b64dSJavier Martinez Canillas /* 46723827b64dSJavier Martinez Canillas * Regulators may had failed to resolve their input supplies 46733827b64dSJavier Martinez Canillas * when were registered, either because the input supply was 46743827b64dSJavier Martinez Canillas * not registered yet or because its parent device was not 46753827b64dSJavier Martinez Canillas * bound yet. So attempt to resolve the input supplies for 46763827b64dSJavier Martinez Canillas * pending regulators before trying to disable unused ones. 46773827b64dSJavier Martinez Canillas */ 46783827b64dSJavier Martinez Canillas class_for_each_device(®ulator_class, NULL, NULL, 46793827b64dSJavier Martinez Canillas regulator_register_resolve_supply); 46803827b64dSJavier Martinez Canillas 4681609ca5f3SMark Brown /* If we have a full configuration then disable any regulators 4682609ca5f3SMark Brown * we have permission to change the status for and which are 4683609ca5f3SMark Brown * not in use or always_on. This is effectively the default 4684609ca5f3SMark Brown * for DT and ACPI as they have full constraints. 4685609ca5f3SMark Brown */ 4686609ca5f3SMark Brown class_for_each_device(®ulator_class, NULL, NULL, 4687609ca5f3SMark Brown regulator_late_cleanup); 4688ca725561SMark Brown 4689ca725561SMark Brown return 0; 4690ca725561SMark Brown } 4691fd482a3eSSaravana Kannan late_initcall_sync(regulator_init_complete); 4692