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> 2769511a45SRajendra Nayak #include <linux/of.h> 2865b19ce6SMark Brown #include <linux/regmap.h> 2969511a45SRajendra Nayak #include <linux/regulator/of_regulator.h> 30414c70cbSLiam Girdwood #include <linux/regulator/consumer.h> 31414c70cbSLiam Girdwood #include <linux/regulator/driver.h> 32414c70cbSLiam Girdwood #include <linux/regulator/machine.h> 3365602c32SPaul Gortmaker #include <linux/module.h> 34414c70cbSLiam Girdwood 3502fa3ec0SMark Brown #define CREATE_TRACE_POINTS 3602fa3ec0SMark Brown #include <trace/events/regulator.h> 3702fa3ec0SMark Brown 3834abbd68SMark Brown #include "dummy.h" 390cdfcc0fSMark Brown #include "internal.h" 4034abbd68SMark Brown 417d51a0dbSMark Brown #define rdev_crit(rdev, fmt, ...) \ 427d51a0dbSMark Brown pr_crit("%s: " fmt, rdev_get_name(rdev), ##__VA_ARGS__) 435da84fd9SJoe Perches #define rdev_err(rdev, fmt, ...) \ 445da84fd9SJoe Perches pr_err("%s: " fmt, rdev_get_name(rdev), ##__VA_ARGS__) 455da84fd9SJoe Perches #define rdev_warn(rdev, fmt, ...) \ 465da84fd9SJoe Perches pr_warn("%s: " fmt, rdev_get_name(rdev), ##__VA_ARGS__) 475da84fd9SJoe Perches #define rdev_info(rdev, fmt, ...) \ 485da84fd9SJoe Perches pr_info("%s: " fmt, rdev_get_name(rdev), ##__VA_ARGS__) 495da84fd9SJoe Perches #define rdev_dbg(rdev, fmt, ...) \ 505da84fd9SJoe Perches pr_debug("%s: " fmt, rdev_get_name(rdev), ##__VA_ARGS__) 515da84fd9SJoe Perches 52414c70cbSLiam Girdwood static DEFINE_MUTEX(regulator_list_mutex); 53414c70cbSLiam Girdwood static LIST_HEAD(regulator_list); 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; 80f19b00daSKim, Milo int gpio; 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); 104414c70cbSLiam Girdwood static void _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); 111414c70cbSLiam Girdwood 1121083c393SMark Brown static const char *rdev_get_name(struct regulator_dev *rdev) 1131083c393SMark Brown { 1141083c393SMark Brown if (rdev->constraints && rdev->constraints->name) 1151083c393SMark Brown return rdev->constraints->name; 1161083c393SMark Brown else if (rdev->desc->name) 1171083c393SMark Brown return rdev->desc->name; 1181083c393SMark Brown else 1191083c393SMark Brown return ""; 1201083c393SMark Brown } 1211083c393SMark Brown 12269511a45SRajendra Nayak /** 12369511a45SRajendra Nayak * of_get_regulator - get a regulator device node based on supply name 12469511a45SRajendra Nayak * @dev: Device pointer for the consumer (of regulator) device 12569511a45SRajendra Nayak * @supply: regulator supply name 12669511a45SRajendra Nayak * 12769511a45SRajendra Nayak * Extract the regulator device node corresponding to the supply name. 128167d41dcSMaxime Ripard * returns the device node corresponding to the regulator if found, else 12969511a45SRajendra Nayak * returns NULL. 13069511a45SRajendra Nayak */ 13169511a45SRajendra Nayak static struct device_node *of_get_regulator(struct device *dev, const char *supply) 13269511a45SRajendra Nayak { 13369511a45SRajendra Nayak struct device_node *regnode = NULL; 13469511a45SRajendra Nayak char prop_name[32]; /* 32 is max size of property name */ 13569511a45SRajendra Nayak 13669511a45SRajendra Nayak dev_dbg(dev, "Looking up %s-supply from device tree\n", supply); 13769511a45SRajendra Nayak 13869511a45SRajendra Nayak snprintf(prop_name, 32, "%s-supply", supply); 13969511a45SRajendra Nayak regnode = of_parse_phandle(dev->of_node, prop_name, 0); 14069511a45SRajendra Nayak 14169511a45SRajendra Nayak if (!regnode) { 14216fbcc3bSRajendra Nayak dev_dbg(dev, "Looking up %s property in node %s failed", 14369511a45SRajendra Nayak prop_name, dev->of_node->full_name); 14469511a45SRajendra Nayak return NULL; 14569511a45SRajendra Nayak } 14669511a45SRajendra Nayak return regnode; 14769511a45SRajendra Nayak } 14869511a45SRajendra Nayak 1496492bc1bSMark Brown static int _regulator_can_change_status(struct regulator_dev *rdev) 1506492bc1bSMark Brown { 1516492bc1bSMark Brown if (!rdev->constraints) 1526492bc1bSMark Brown return 0; 1536492bc1bSMark Brown 1546492bc1bSMark Brown if (rdev->constraints->valid_ops_mask & REGULATOR_CHANGE_STATUS) 1556492bc1bSMark Brown return 1; 1566492bc1bSMark Brown else 1576492bc1bSMark Brown return 0; 1586492bc1bSMark Brown } 1596492bc1bSMark Brown 160414c70cbSLiam Girdwood /* Platform voltage constraint check */ 161414c70cbSLiam Girdwood static int regulator_check_voltage(struct regulator_dev *rdev, 162414c70cbSLiam Girdwood int *min_uV, int *max_uV) 163414c70cbSLiam Girdwood { 164414c70cbSLiam Girdwood BUG_ON(*min_uV > *max_uV); 165414c70cbSLiam Girdwood 166414c70cbSLiam Girdwood if (!rdev->constraints) { 1675da84fd9SJoe Perches rdev_err(rdev, "no constraints\n"); 168414c70cbSLiam Girdwood return -ENODEV; 169414c70cbSLiam Girdwood } 170414c70cbSLiam Girdwood if (!(rdev->constraints->valid_ops_mask & REGULATOR_CHANGE_VOLTAGE)) { 1715da84fd9SJoe Perches rdev_err(rdev, "operation not allowed\n"); 172414c70cbSLiam Girdwood return -EPERM; 173414c70cbSLiam Girdwood } 174414c70cbSLiam Girdwood 175414c70cbSLiam Girdwood if (*max_uV > rdev->constraints->max_uV) 176414c70cbSLiam Girdwood *max_uV = rdev->constraints->max_uV; 177414c70cbSLiam Girdwood if (*min_uV < rdev->constraints->min_uV) 178414c70cbSLiam Girdwood *min_uV = rdev->constraints->min_uV; 179414c70cbSLiam Girdwood 18089f425edSMark Brown if (*min_uV > *max_uV) { 18189f425edSMark Brown rdev_err(rdev, "unsupportable voltage range: %d-%duV\n", 18254abd335SMark Brown *min_uV, *max_uV); 183414c70cbSLiam Girdwood return -EINVAL; 18489f425edSMark Brown } 185414c70cbSLiam Girdwood 186414c70cbSLiam Girdwood return 0; 187414c70cbSLiam Girdwood } 188414c70cbSLiam Girdwood 18905fda3b1SThomas Petazzoni /* Make sure we select a voltage that suits the needs of all 19005fda3b1SThomas Petazzoni * regulator consumers 19105fda3b1SThomas Petazzoni */ 19205fda3b1SThomas Petazzoni static int regulator_check_consumers(struct regulator_dev *rdev, 19305fda3b1SThomas Petazzoni int *min_uV, int *max_uV) 19405fda3b1SThomas Petazzoni { 19505fda3b1SThomas Petazzoni struct regulator *regulator; 19605fda3b1SThomas Petazzoni 19705fda3b1SThomas Petazzoni list_for_each_entry(regulator, &rdev->consumer_list, list) { 1984aa922c0SMark Brown /* 1994aa922c0SMark Brown * Assume consumers that didn't say anything are OK 2004aa922c0SMark Brown * with anything in the constraint range. 2014aa922c0SMark Brown */ 2024aa922c0SMark Brown if (!regulator->min_uV && !regulator->max_uV) 2034aa922c0SMark Brown continue; 2044aa922c0SMark Brown 20505fda3b1SThomas Petazzoni if (*max_uV > regulator->max_uV) 20605fda3b1SThomas Petazzoni *max_uV = regulator->max_uV; 20705fda3b1SThomas Petazzoni if (*min_uV < regulator->min_uV) 20805fda3b1SThomas Petazzoni *min_uV = regulator->min_uV; 20905fda3b1SThomas Petazzoni } 21005fda3b1SThomas Petazzoni 211dd8004afSMark Brown if (*min_uV > *max_uV) { 2129c7b4e8aSRuss Dill rdev_err(rdev, "Restricting voltage, %u-%uuV\n", 2139c7b4e8aSRuss Dill *min_uV, *max_uV); 21405fda3b1SThomas Petazzoni return -EINVAL; 215dd8004afSMark Brown } 21605fda3b1SThomas Petazzoni 21705fda3b1SThomas Petazzoni return 0; 21805fda3b1SThomas Petazzoni } 21905fda3b1SThomas Petazzoni 220414c70cbSLiam Girdwood /* current constraint check */ 221414c70cbSLiam Girdwood static int regulator_check_current_limit(struct regulator_dev *rdev, 222414c70cbSLiam Girdwood int *min_uA, int *max_uA) 223414c70cbSLiam Girdwood { 224414c70cbSLiam Girdwood BUG_ON(*min_uA > *max_uA); 225414c70cbSLiam Girdwood 226414c70cbSLiam Girdwood if (!rdev->constraints) { 2275da84fd9SJoe Perches rdev_err(rdev, "no constraints\n"); 228414c70cbSLiam Girdwood return -ENODEV; 229414c70cbSLiam Girdwood } 230414c70cbSLiam Girdwood if (!(rdev->constraints->valid_ops_mask & REGULATOR_CHANGE_CURRENT)) { 2315da84fd9SJoe Perches rdev_err(rdev, "operation not allowed\n"); 232414c70cbSLiam Girdwood return -EPERM; 233414c70cbSLiam Girdwood } 234414c70cbSLiam Girdwood 235414c70cbSLiam Girdwood if (*max_uA > rdev->constraints->max_uA) 236414c70cbSLiam Girdwood *max_uA = rdev->constraints->max_uA; 237414c70cbSLiam Girdwood if (*min_uA < rdev->constraints->min_uA) 238414c70cbSLiam Girdwood *min_uA = rdev->constraints->min_uA; 239414c70cbSLiam Girdwood 24089f425edSMark Brown if (*min_uA > *max_uA) { 24189f425edSMark Brown rdev_err(rdev, "unsupportable current range: %d-%duA\n", 24254abd335SMark Brown *min_uA, *max_uA); 243414c70cbSLiam Girdwood return -EINVAL; 24489f425edSMark Brown } 245414c70cbSLiam Girdwood 246414c70cbSLiam Girdwood return 0; 247414c70cbSLiam Girdwood } 248414c70cbSLiam Girdwood 249414c70cbSLiam Girdwood /* operating mode constraint check */ 2502c608234SMark Brown static int regulator_mode_constrain(struct regulator_dev *rdev, int *mode) 251414c70cbSLiam Girdwood { 2522c608234SMark Brown switch (*mode) { 253e573520bSDavid Brownell case REGULATOR_MODE_FAST: 254e573520bSDavid Brownell case REGULATOR_MODE_NORMAL: 255e573520bSDavid Brownell case REGULATOR_MODE_IDLE: 256e573520bSDavid Brownell case REGULATOR_MODE_STANDBY: 257e573520bSDavid Brownell break; 258e573520bSDavid Brownell default: 25989f425edSMark Brown rdev_err(rdev, "invalid mode %x specified\n", *mode); 260e573520bSDavid Brownell return -EINVAL; 261e573520bSDavid Brownell } 262e573520bSDavid Brownell 263414c70cbSLiam Girdwood if (!rdev->constraints) { 2645da84fd9SJoe Perches rdev_err(rdev, "no constraints\n"); 265414c70cbSLiam Girdwood return -ENODEV; 266414c70cbSLiam Girdwood } 267414c70cbSLiam Girdwood if (!(rdev->constraints->valid_ops_mask & REGULATOR_CHANGE_MODE)) { 2685da84fd9SJoe Perches rdev_err(rdev, "operation not allowed\n"); 269414c70cbSLiam Girdwood return -EPERM; 270414c70cbSLiam Girdwood } 2712c608234SMark Brown 2722c608234SMark Brown /* The modes are bitmasks, the most power hungry modes having 2732c608234SMark Brown * the lowest values. If the requested mode isn't supported 2742c608234SMark Brown * try higher modes. */ 2752c608234SMark Brown while (*mode) { 2762c608234SMark Brown if (rdev->constraints->valid_modes_mask & *mode) 277414c70cbSLiam Girdwood return 0; 2782c608234SMark Brown *mode /= 2; 2792c608234SMark Brown } 2802c608234SMark Brown 2812c608234SMark Brown return -EINVAL; 282414c70cbSLiam Girdwood } 283414c70cbSLiam Girdwood 284414c70cbSLiam Girdwood /* dynamic regulator mode switching constraint check */ 285414c70cbSLiam Girdwood static int regulator_check_drms(struct regulator_dev *rdev) 286414c70cbSLiam Girdwood { 287414c70cbSLiam Girdwood if (!rdev->constraints) { 2885da84fd9SJoe Perches rdev_err(rdev, "no constraints\n"); 289414c70cbSLiam Girdwood return -ENODEV; 290414c70cbSLiam Girdwood } 291414c70cbSLiam Girdwood if (!(rdev->constraints->valid_ops_mask & REGULATOR_CHANGE_DRMS)) { 2925da84fd9SJoe Perches rdev_err(rdev, "operation not allowed\n"); 293414c70cbSLiam Girdwood return -EPERM; 294414c70cbSLiam Girdwood } 295414c70cbSLiam Girdwood return 0; 296414c70cbSLiam Girdwood } 297414c70cbSLiam Girdwood 298414c70cbSLiam Girdwood static ssize_t regulator_uV_show(struct device *dev, 299414c70cbSLiam Girdwood struct device_attribute *attr, char *buf) 300414c70cbSLiam Girdwood { 301a5766f11SLiam Girdwood struct regulator_dev *rdev = dev_get_drvdata(dev); 302414c70cbSLiam Girdwood ssize_t ret; 303414c70cbSLiam Girdwood 304414c70cbSLiam Girdwood mutex_lock(&rdev->mutex); 305414c70cbSLiam Girdwood ret = sprintf(buf, "%d\n", _regulator_get_voltage(rdev)); 306414c70cbSLiam Girdwood mutex_unlock(&rdev->mutex); 307414c70cbSLiam Girdwood 308414c70cbSLiam Girdwood return ret; 309414c70cbSLiam Girdwood } 3107ad68e2fSDavid Brownell static DEVICE_ATTR(microvolts, 0444, regulator_uV_show, NULL); 311414c70cbSLiam Girdwood 312414c70cbSLiam Girdwood static ssize_t regulator_uA_show(struct device *dev, 313414c70cbSLiam Girdwood struct device_attribute *attr, char *buf) 314414c70cbSLiam Girdwood { 315a5766f11SLiam Girdwood struct regulator_dev *rdev = dev_get_drvdata(dev); 316414c70cbSLiam Girdwood 317414c70cbSLiam Girdwood return sprintf(buf, "%d\n", _regulator_get_current_limit(rdev)); 318414c70cbSLiam Girdwood } 3197ad68e2fSDavid Brownell static DEVICE_ATTR(microamps, 0444, regulator_uA_show, NULL); 320414c70cbSLiam Girdwood 321587cea27SGreg Kroah-Hartman static ssize_t name_show(struct device *dev, struct device_attribute *attr, 322587cea27SGreg Kroah-Hartman char *buf) 323bc558a60SMark Brown { 324bc558a60SMark Brown struct regulator_dev *rdev = dev_get_drvdata(dev); 325bc558a60SMark Brown 3261083c393SMark Brown return sprintf(buf, "%s\n", rdev_get_name(rdev)); 327bc558a60SMark Brown } 328587cea27SGreg Kroah-Hartman static DEVICE_ATTR_RO(name); 329bc558a60SMark Brown 3304fca9545SDavid Brownell static ssize_t regulator_print_opmode(char *buf, int mode) 331414c70cbSLiam Girdwood { 332414c70cbSLiam Girdwood switch (mode) { 333414c70cbSLiam Girdwood case REGULATOR_MODE_FAST: 334414c70cbSLiam Girdwood return sprintf(buf, "fast\n"); 335414c70cbSLiam Girdwood case REGULATOR_MODE_NORMAL: 336414c70cbSLiam Girdwood return sprintf(buf, "normal\n"); 337414c70cbSLiam Girdwood case REGULATOR_MODE_IDLE: 338414c70cbSLiam Girdwood return sprintf(buf, "idle\n"); 339414c70cbSLiam Girdwood case REGULATOR_MODE_STANDBY: 340414c70cbSLiam Girdwood return sprintf(buf, "standby\n"); 341414c70cbSLiam Girdwood } 342414c70cbSLiam Girdwood return sprintf(buf, "unknown\n"); 343414c70cbSLiam Girdwood } 344414c70cbSLiam Girdwood 3454fca9545SDavid Brownell static ssize_t regulator_opmode_show(struct device *dev, 346414c70cbSLiam Girdwood struct device_attribute *attr, char *buf) 347414c70cbSLiam Girdwood { 348a5766f11SLiam Girdwood struct regulator_dev *rdev = dev_get_drvdata(dev); 349414c70cbSLiam Girdwood 3504fca9545SDavid Brownell return regulator_print_opmode(buf, _regulator_get_mode(rdev)); 3514fca9545SDavid Brownell } 3527ad68e2fSDavid Brownell static DEVICE_ATTR(opmode, 0444, regulator_opmode_show, NULL); 3534fca9545SDavid Brownell 3544fca9545SDavid Brownell static ssize_t regulator_print_state(char *buf, int state) 3554fca9545SDavid Brownell { 356414c70cbSLiam Girdwood if (state > 0) 357414c70cbSLiam Girdwood return sprintf(buf, "enabled\n"); 358414c70cbSLiam Girdwood else if (state == 0) 359414c70cbSLiam Girdwood return sprintf(buf, "disabled\n"); 360414c70cbSLiam Girdwood else 361414c70cbSLiam Girdwood return sprintf(buf, "unknown\n"); 362414c70cbSLiam Girdwood } 363414c70cbSLiam Girdwood 3644fca9545SDavid Brownell static ssize_t regulator_state_show(struct device *dev, 3654fca9545SDavid Brownell struct device_attribute *attr, char *buf) 3664fca9545SDavid Brownell { 3674fca9545SDavid Brownell struct regulator_dev *rdev = dev_get_drvdata(dev); 3689332546fSMark Brown ssize_t ret; 3694fca9545SDavid Brownell 3709332546fSMark Brown mutex_lock(&rdev->mutex); 3719332546fSMark Brown ret = regulator_print_state(buf, _regulator_is_enabled(rdev)); 3729332546fSMark Brown mutex_unlock(&rdev->mutex); 3739332546fSMark Brown 3749332546fSMark Brown return ret; 3754fca9545SDavid Brownell } 3767ad68e2fSDavid Brownell static DEVICE_ATTR(state, 0444, regulator_state_show, NULL); 3774fca9545SDavid Brownell 378853116a1SDavid Brownell static ssize_t regulator_status_show(struct device *dev, 379853116a1SDavid Brownell struct device_attribute *attr, char *buf) 380853116a1SDavid Brownell { 381853116a1SDavid Brownell struct regulator_dev *rdev = dev_get_drvdata(dev); 382853116a1SDavid Brownell int status; 383853116a1SDavid Brownell char *label; 384853116a1SDavid Brownell 385853116a1SDavid Brownell status = rdev->desc->ops->get_status(rdev); 386853116a1SDavid Brownell if (status < 0) 387853116a1SDavid Brownell return status; 388853116a1SDavid Brownell 389853116a1SDavid Brownell switch (status) { 390853116a1SDavid Brownell case REGULATOR_STATUS_OFF: 391853116a1SDavid Brownell label = "off"; 392853116a1SDavid Brownell break; 393853116a1SDavid Brownell case REGULATOR_STATUS_ON: 394853116a1SDavid Brownell label = "on"; 395853116a1SDavid Brownell break; 396853116a1SDavid Brownell case REGULATOR_STATUS_ERROR: 397853116a1SDavid Brownell label = "error"; 398853116a1SDavid Brownell break; 399853116a1SDavid Brownell case REGULATOR_STATUS_FAST: 400853116a1SDavid Brownell label = "fast"; 401853116a1SDavid Brownell break; 402853116a1SDavid Brownell case REGULATOR_STATUS_NORMAL: 403853116a1SDavid Brownell label = "normal"; 404853116a1SDavid Brownell break; 405853116a1SDavid Brownell case REGULATOR_STATUS_IDLE: 406853116a1SDavid Brownell label = "idle"; 407853116a1SDavid Brownell break; 408853116a1SDavid Brownell case REGULATOR_STATUS_STANDBY: 409853116a1SDavid Brownell label = "standby"; 410853116a1SDavid Brownell break; 411f59c8f9fSMark Brown case REGULATOR_STATUS_BYPASS: 412f59c8f9fSMark Brown label = "bypass"; 413f59c8f9fSMark Brown break; 4141beaf762SKrystian Garbaciak case REGULATOR_STATUS_UNDEFINED: 4151beaf762SKrystian Garbaciak label = "undefined"; 4161beaf762SKrystian Garbaciak break; 417853116a1SDavid Brownell default: 418853116a1SDavid Brownell return -ERANGE; 419853116a1SDavid Brownell } 420853116a1SDavid Brownell 421853116a1SDavid Brownell return sprintf(buf, "%s\n", label); 422853116a1SDavid Brownell } 423853116a1SDavid Brownell static DEVICE_ATTR(status, 0444, regulator_status_show, NULL); 424853116a1SDavid Brownell 425414c70cbSLiam Girdwood static ssize_t regulator_min_uA_show(struct device *dev, 426414c70cbSLiam Girdwood struct device_attribute *attr, char *buf) 427414c70cbSLiam Girdwood { 428a5766f11SLiam Girdwood struct regulator_dev *rdev = dev_get_drvdata(dev); 429414c70cbSLiam Girdwood 430414c70cbSLiam Girdwood if (!rdev->constraints) 431414c70cbSLiam Girdwood return sprintf(buf, "constraint not defined\n"); 432414c70cbSLiam Girdwood 433414c70cbSLiam Girdwood return sprintf(buf, "%d\n", rdev->constraints->min_uA); 434414c70cbSLiam Girdwood } 4357ad68e2fSDavid Brownell static DEVICE_ATTR(min_microamps, 0444, regulator_min_uA_show, NULL); 436414c70cbSLiam Girdwood 437414c70cbSLiam Girdwood static ssize_t regulator_max_uA_show(struct device *dev, 438414c70cbSLiam Girdwood struct device_attribute *attr, char *buf) 439414c70cbSLiam Girdwood { 440a5766f11SLiam Girdwood struct regulator_dev *rdev = dev_get_drvdata(dev); 441414c70cbSLiam Girdwood 442414c70cbSLiam Girdwood if (!rdev->constraints) 443414c70cbSLiam Girdwood return sprintf(buf, "constraint not defined\n"); 444414c70cbSLiam Girdwood 445414c70cbSLiam Girdwood return sprintf(buf, "%d\n", rdev->constraints->max_uA); 446414c70cbSLiam Girdwood } 4477ad68e2fSDavid Brownell static DEVICE_ATTR(max_microamps, 0444, regulator_max_uA_show, NULL); 448414c70cbSLiam Girdwood 449414c70cbSLiam Girdwood static ssize_t regulator_min_uV_show(struct device *dev, 450414c70cbSLiam Girdwood struct device_attribute *attr, char *buf) 451414c70cbSLiam Girdwood { 452a5766f11SLiam Girdwood struct regulator_dev *rdev = dev_get_drvdata(dev); 453414c70cbSLiam Girdwood 454414c70cbSLiam Girdwood if (!rdev->constraints) 455414c70cbSLiam Girdwood return sprintf(buf, "constraint not defined\n"); 456414c70cbSLiam Girdwood 457414c70cbSLiam Girdwood return sprintf(buf, "%d\n", rdev->constraints->min_uV); 458414c70cbSLiam Girdwood } 4597ad68e2fSDavid Brownell static DEVICE_ATTR(min_microvolts, 0444, regulator_min_uV_show, NULL); 460414c70cbSLiam Girdwood 461414c70cbSLiam Girdwood static ssize_t regulator_max_uV_show(struct device *dev, 462414c70cbSLiam Girdwood struct device_attribute *attr, char *buf) 463414c70cbSLiam Girdwood { 464a5766f11SLiam Girdwood struct regulator_dev *rdev = dev_get_drvdata(dev); 465414c70cbSLiam Girdwood 466414c70cbSLiam Girdwood if (!rdev->constraints) 467414c70cbSLiam Girdwood return sprintf(buf, "constraint not defined\n"); 468414c70cbSLiam Girdwood 469414c70cbSLiam Girdwood return sprintf(buf, "%d\n", rdev->constraints->max_uV); 470414c70cbSLiam Girdwood } 4717ad68e2fSDavid Brownell static DEVICE_ATTR(max_microvolts, 0444, regulator_max_uV_show, NULL); 472414c70cbSLiam Girdwood 473414c70cbSLiam Girdwood static ssize_t regulator_total_uA_show(struct device *dev, 474414c70cbSLiam Girdwood struct device_attribute *attr, char *buf) 475414c70cbSLiam Girdwood { 476a5766f11SLiam Girdwood struct regulator_dev *rdev = dev_get_drvdata(dev); 477414c70cbSLiam Girdwood struct regulator *regulator; 478414c70cbSLiam Girdwood int uA = 0; 479414c70cbSLiam Girdwood 480414c70cbSLiam Girdwood mutex_lock(&rdev->mutex); 481414c70cbSLiam Girdwood list_for_each_entry(regulator, &rdev->consumer_list, list) 482414c70cbSLiam Girdwood uA += regulator->uA_load; 483414c70cbSLiam Girdwood mutex_unlock(&rdev->mutex); 484414c70cbSLiam Girdwood return sprintf(buf, "%d\n", uA); 485414c70cbSLiam Girdwood } 4867ad68e2fSDavid Brownell static DEVICE_ATTR(requested_microamps, 0444, regulator_total_uA_show, NULL); 487414c70cbSLiam Girdwood 488587cea27SGreg Kroah-Hartman static ssize_t num_users_show(struct device *dev, struct device_attribute *attr, 489587cea27SGreg Kroah-Hartman char *buf) 490414c70cbSLiam Girdwood { 491a5766f11SLiam Girdwood struct regulator_dev *rdev = dev_get_drvdata(dev); 492414c70cbSLiam Girdwood return sprintf(buf, "%d\n", rdev->use_count); 493414c70cbSLiam Girdwood } 494587cea27SGreg Kroah-Hartman static DEVICE_ATTR_RO(num_users); 495414c70cbSLiam Girdwood 496587cea27SGreg Kroah-Hartman static ssize_t type_show(struct device *dev, struct device_attribute *attr, 497587cea27SGreg Kroah-Hartman char *buf) 498414c70cbSLiam Girdwood { 499a5766f11SLiam Girdwood struct regulator_dev *rdev = dev_get_drvdata(dev); 500414c70cbSLiam Girdwood 501414c70cbSLiam Girdwood switch (rdev->desc->type) { 502414c70cbSLiam Girdwood case REGULATOR_VOLTAGE: 503414c70cbSLiam Girdwood return sprintf(buf, "voltage\n"); 504414c70cbSLiam Girdwood case REGULATOR_CURRENT: 505414c70cbSLiam Girdwood return sprintf(buf, "current\n"); 506414c70cbSLiam Girdwood } 507414c70cbSLiam Girdwood return sprintf(buf, "unknown\n"); 508414c70cbSLiam Girdwood } 509587cea27SGreg Kroah-Hartman static DEVICE_ATTR_RO(type); 510414c70cbSLiam Girdwood 511414c70cbSLiam Girdwood static ssize_t regulator_suspend_mem_uV_show(struct device *dev, 512414c70cbSLiam Girdwood struct device_attribute *attr, char *buf) 513414c70cbSLiam Girdwood { 514a5766f11SLiam Girdwood struct regulator_dev *rdev = dev_get_drvdata(dev); 515414c70cbSLiam Girdwood 516414c70cbSLiam Girdwood return sprintf(buf, "%d\n", rdev->constraints->state_mem.uV); 517414c70cbSLiam Girdwood } 5187ad68e2fSDavid Brownell static DEVICE_ATTR(suspend_mem_microvolts, 0444, 5197ad68e2fSDavid Brownell regulator_suspend_mem_uV_show, NULL); 520414c70cbSLiam Girdwood 521414c70cbSLiam Girdwood static ssize_t regulator_suspend_disk_uV_show(struct device *dev, 522414c70cbSLiam Girdwood struct device_attribute *attr, char *buf) 523414c70cbSLiam Girdwood { 524a5766f11SLiam Girdwood struct regulator_dev *rdev = dev_get_drvdata(dev); 525414c70cbSLiam Girdwood 526414c70cbSLiam Girdwood return sprintf(buf, "%d\n", rdev->constraints->state_disk.uV); 527414c70cbSLiam Girdwood } 5287ad68e2fSDavid Brownell static DEVICE_ATTR(suspend_disk_microvolts, 0444, 5297ad68e2fSDavid Brownell regulator_suspend_disk_uV_show, NULL); 530414c70cbSLiam Girdwood 531414c70cbSLiam Girdwood static ssize_t regulator_suspend_standby_uV_show(struct device *dev, 532414c70cbSLiam Girdwood struct device_attribute *attr, char *buf) 533414c70cbSLiam Girdwood { 534a5766f11SLiam Girdwood struct regulator_dev *rdev = dev_get_drvdata(dev); 535414c70cbSLiam Girdwood 536414c70cbSLiam Girdwood return sprintf(buf, "%d\n", rdev->constraints->state_standby.uV); 537414c70cbSLiam Girdwood } 5387ad68e2fSDavid Brownell static DEVICE_ATTR(suspend_standby_microvolts, 0444, 5397ad68e2fSDavid Brownell regulator_suspend_standby_uV_show, NULL); 540414c70cbSLiam Girdwood 541414c70cbSLiam Girdwood static ssize_t regulator_suspend_mem_mode_show(struct device *dev, 542414c70cbSLiam Girdwood struct device_attribute *attr, char *buf) 543414c70cbSLiam Girdwood { 544a5766f11SLiam Girdwood struct regulator_dev *rdev = dev_get_drvdata(dev); 545414c70cbSLiam Girdwood 5464fca9545SDavid Brownell return regulator_print_opmode(buf, 5474fca9545SDavid Brownell rdev->constraints->state_mem.mode); 548414c70cbSLiam Girdwood } 5497ad68e2fSDavid Brownell static DEVICE_ATTR(suspend_mem_mode, 0444, 5507ad68e2fSDavid Brownell regulator_suspend_mem_mode_show, NULL); 551414c70cbSLiam Girdwood 552414c70cbSLiam Girdwood static ssize_t regulator_suspend_disk_mode_show(struct device *dev, 553414c70cbSLiam Girdwood struct device_attribute *attr, char *buf) 554414c70cbSLiam Girdwood { 555a5766f11SLiam Girdwood struct regulator_dev *rdev = dev_get_drvdata(dev); 556414c70cbSLiam Girdwood 5574fca9545SDavid Brownell return regulator_print_opmode(buf, 5584fca9545SDavid Brownell rdev->constraints->state_disk.mode); 559414c70cbSLiam Girdwood } 5607ad68e2fSDavid Brownell static DEVICE_ATTR(suspend_disk_mode, 0444, 5617ad68e2fSDavid Brownell regulator_suspend_disk_mode_show, NULL); 562414c70cbSLiam Girdwood 563414c70cbSLiam Girdwood static ssize_t regulator_suspend_standby_mode_show(struct device *dev, 564414c70cbSLiam Girdwood struct device_attribute *attr, char *buf) 565414c70cbSLiam Girdwood { 566a5766f11SLiam Girdwood struct regulator_dev *rdev = dev_get_drvdata(dev); 567414c70cbSLiam Girdwood 5684fca9545SDavid Brownell return regulator_print_opmode(buf, 5694fca9545SDavid Brownell rdev->constraints->state_standby.mode); 570414c70cbSLiam Girdwood } 5717ad68e2fSDavid Brownell static DEVICE_ATTR(suspend_standby_mode, 0444, 5727ad68e2fSDavid Brownell regulator_suspend_standby_mode_show, NULL); 573414c70cbSLiam Girdwood 574414c70cbSLiam Girdwood static ssize_t regulator_suspend_mem_state_show(struct device *dev, 575414c70cbSLiam Girdwood struct device_attribute *attr, char *buf) 576414c70cbSLiam Girdwood { 577a5766f11SLiam Girdwood struct regulator_dev *rdev = dev_get_drvdata(dev); 578414c70cbSLiam Girdwood 5794fca9545SDavid Brownell return regulator_print_state(buf, 5804fca9545SDavid Brownell rdev->constraints->state_mem.enabled); 581414c70cbSLiam Girdwood } 5827ad68e2fSDavid Brownell static DEVICE_ATTR(suspend_mem_state, 0444, 5837ad68e2fSDavid Brownell regulator_suspend_mem_state_show, NULL); 584414c70cbSLiam Girdwood 585414c70cbSLiam Girdwood static ssize_t regulator_suspend_disk_state_show(struct device *dev, 586414c70cbSLiam Girdwood struct device_attribute *attr, char *buf) 587414c70cbSLiam Girdwood { 588a5766f11SLiam Girdwood struct regulator_dev *rdev = dev_get_drvdata(dev); 589414c70cbSLiam Girdwood 5904fca9545SDavid Brownell return regulator_print_state(buf, 5914fca9545SDavid Brownell rdev->constraints->state_disk.enabled); 592414c70cbSLiam Girdwood } 5937ad68e2fSDavid Brownell static DEVICE_ATTR(suspend_disk_state, 0444, 5947ad68e2fSDavid Brownell regulator_suspend_disk_state_show, NULL); 595414c70cbSLiam Girdwood 596414c70cbSLiam Girdwood static ssize_t regulator_suspend_standby_state_show(struct device *dev, 597414c70cbSLiam Girdwood struct device_attribute *attr, char *buf) 598414c70cbSLiam Girdwood { 599a5766f11SLiam Girdwood struct regulator_dev *rdev = dev_get_drvdata(dev); 600414c70cbSLiam Girdwood 6014fca9545SDavid Brownell return regulator_print_state(buf, 6024fca9545SDavid Brownell rdev->constraints->state_standby.enabled); 603414c70cbSLiam Girdwood } 6047ad68e2fSDavid Brownell static DEVICE_ATTR(suspend_standby_state, 0444, 6057ad68e2fSDavid Brownell regulator_suspend_standby_state_show, NULL); 606bc558a60SMark Brown 607f59c8f9fSMark Brown static ssize_t regulator_bypass_show(struct device *dev, 608f59c8f9fSMark Brown struct device_attribute *attr, char *buf) 609f59c8f9fSMark Brown { 610f59c8f9fSMark Brown struct regulator_dev *rdev = dev_get_drvdata(dev); 611f59c8f9fSMark Brown const char *report; 612f59c8f9fSMark Brown bool bypass; 613f59c8f9fSMark Brown int ret; 614f59c8f9fSMark Brown 615f59c8f9fSMark Brown ret = rdev->desc->ops->get_bypass(rdev, &bypass); 616f59c8f9fSMark Brown 617f59c8f9fSMark Brown if (ret != 0) 618f59c8f9fSMark Brown report = "unknown"; 619f59c8f9fSMark Brown else if (bypass) 620f59c8f9fSMark Brown report = "enabled"; 621f59c8f9fSMark Brown else 622f59c8f9fSMark Brown report = "disabled"; 623f59c8f9fSMark Brown 624f59c8f9fSMark Brown return sprintf(buf, "%s\n", report); 625f59c8f9fSMark Brown } 626f59c8f9fSMark Brown static DEVICE_ATTR(bypass, 0444, 627f59c8f9fSMark Brown regulator_bypass_show, NULL); 6287ad68e2fSDavid Brownell 6297ad68e2fSDavid Brownell /* 6307ad68e2fSDavid Brownell * These are the only attributes are present for all regulators. 6317ad68e2fSDavid Brownell * Other attributes are a function of regulator functionality. 6327ad68e2fSDavid Brownell */ 633587cea27SGreg Kroah-Hartman static struct attribute *regulator_dev_attrs[] = { 634587cea27SGreg Kroah-Hartman &dev_attr_name.attr, 635587cea27SGreg Kroah-Hartman &dev_attr_num_users.attr, 636587cea27SGreg Kroah-Hartman &dev_attr_type.attr, 637587cea27SGreg Kroah-Hartman NULL, 638414c70cbSLiam Girdwood }; 639587cea27SGreg Kroah-Hartman ATTRIBUTE_GROUPS(regulator_dev); 640414c70cbSLiam Girdwood 641414c70cbSLiam Girdwood static void regulator_dev_release(struct device *dev) 642414c70cbSLiam Girdwood { 643a5766f11SLiam Girdwood struct regulator_dev *rdev = dev_get_drvdata(dev); 644414c70cbSLiam Girdwood kfree(rdev); 645414c70cbSLiam Girdwood } 646414c70cbSLiam Girdwood 647414c70cbSLiam Girdwood static struct class regulator_class = { 648414c70cbSLiam Girdwood .name = "regulator", 649414c70cbSLiam Girdwood .dev_release = regulator_dev_release, 650587cea27SGreg Kroah-Hartman .dev_groups = regulator_dev_groups, 651414c70cbSLiam Girdwood }; 652414c70cbSLiam Girdwood 653414c70cbSLiam Girdwood /* Calculate the new optimum regulator operating mode based on the new total 654414c70cbSLiam Girdwood * consumer load. All locks held by caller */ 655414c70cbSLiam Girdwood static void drms_uA_update(struct regulator_dev *rdev) 656414c70cbSLiam Girdwood { 657414c70cbSLiam Girdwood struct regulator *sibling; 658414c70cbSLiam Girdwood int current_uA = 0, output_uV, input_uV, err; 659414c70cbSLiam Girdwood unsigned int mode; 660414c70cbSLiam Girdwood 661414c70cbSLiam Girdwood err = regulator_check_drms(rdev); 662414c70cbSLiam Girdwood if (err < 0 || !rdev->desc->ops->get_optimum_mode || 663476c2d83SMark Brown (!rdev->desc->ops->get_voltage && 664476c2d83SMark Brown !rdev->desc->ops->get_voltage_sel) || 665476c2d83SMark Brown !rdev->desc->ops->set_mode) 666414c70cbSLiam Girdwood return; 667414c70cbSLiam Girdwood 668414c70cbSLiam Girdwood /* get output voltage */ 6691bf5a1f8SMark Brown output_uV = _regulator_get_voltage(rdev); 670414c70cbSLiam Girdwood if (output_uV <= 0) 671414c70cbSLiam Girdwood return; 672414c70cbSLiam Girdwood 673414c70cbSLiam Girdwood /* get input voltage */ 6741bf5a1f8SMark Brown input_uV = 0; 6751bf5a1f8SMark Brown if (rdev->supply) 6763f24f5adSAxel Lin input_uV = regulator_get_voltage(rdev->supply); 6771bf5a1f8SMark Brown if (input_uV <= 0) 678414c70cbSLiam Girdwood input_uV = rdev->constraints->input_uV; 679414c70cbSLiam Girdwood if (input_uV <= 0) 680414c70cbSLiam Girdwood return; 681414c70cbSLiam Girdwood 682414c70cbSLiam Girdwood /* calc total requested load */ 683414c70cbSLiam Girdwood list_for_each_entry(sibling, &rdev->consumer_list, list) 684414c70cbSLiam Girdwood current_uA += sibling->uA_load; 685414c70cbSLiam Girdwood 686414c70cbSLiam Girdwood /* now get the optimum mode for our new total regulator load */ 687414c70cbSLiam Girdwood mode = rdev->desc->ops->get_optimum_mode(rdev, input_uV, 688414c70cbSLiam Girdwood output_uV, current_uA); 689414c70cbSLiam Girdwood 690414c70cbSLiam Girdwood /* check the new mode is allowed */ 6912c608234SMark Brown err = regulator_mode_constrain(rdev, &mode); 692414c70cbSLiam Girdwood if (err == 0) 693414c70cbSLiam Girdwood rdev->desc->ops->set_mode(rdev, mode); 694414c70cbSLiam Girdwood } 695414c70cbSLiam Girdwood 696414c70cbSLiam Girdwood static int suspend_set_state(struct regulator_dev *rdev, 697414c70cbSLiam Girdwood struct regulator_state *rstate) 698414c70cbSLiam Girdwood { 699414c70cbSLiam Girdwood int ret = 0; 700638f85c5SMark Brown 701638f85c5SMark Brown /* If we have no suspend mode configration don't set anything; 7028ac0e95dSAxel Lin * only warn if the driver implements set_suspend_voltage or 7038ac0e95dSAxel Lin * set_suspend_mode callback. 704638f85c5SMark Brown */ 705638f85c5SMark Brown if (!rstate->enabled && !rstate->disabled) { 7068ac0e95dSAxel Lin if (rdev->desc->ops->set_suspend_voltage || 7078ac0e95dSAxel Lin rdev->desc->ops->set_suspend_mode) 7085da84fd9SJoe Perches rdev_warn(rdev, "No configuration\n"); 709638f85c5SMark Brown return 0; 710638f85c5SMark Brown } 711638f85c5SMark Brown 712638f85c5SMark Brown if (rstate->enabled && rstate->disabled) { 7135da84fd9SJoe Perches rdev_err(rdev, "invalid configuration\n"); 714638f85c5SMark Brown return -EINVAL; 715638f85c5SMark Brown } 716638f85c5SMark Brown 7178ac0e95dSAxel Lin if (rstate->enabled && rdev->desc->ops->set_suspend_enable) 718414c70cbSLiam Girdwood ret = rdev->desc->ops->set_suspend_enable(rdev); 7198ac0e95dSAxel Lin else if (rstate->disabled && rdev->desc->ops->set_suspend_disable) 720414c70cbSLiam Girdwood ret = rdev->desc->ops->set_suspend_disable(rdev); 7218ac0e95dSAxel Lin else /* OK if set_suspend_enable or set_suspend_disable is NULL */ 7228ac0e95dSAxel Lin ret = 0; 7238ac0e95dSAxel Lin 724414c70cbSLiam Girdwood if (ret < 0) { 7255da84fd9SJoe Perches rdev_err(rdev, "failed to enabled/disable\n"); 726414c70cbSLiam Girdwood return ret; 727414c70cbSLiam Girdwood } 728414c70cbSLiam Girdwood 729414c70cbSLiam Girdwood if (rdev->desc->ops->set_suspend_voltage && rstate->uV > 0) { 730414c70cbSLiam Girdwood ret = rdev->desc->ops->set_suspend_voltage(rdev, rstate->uV); 731414c70cbSLiam Girdwood if (ret < 0) { 7325da84fd9SJoe Perches rdev_err(rdev, "failed to set voltage\n"); 733414c70cbSLiam Girdwood return ret; 734414c70cbSLiam Girdwood } 735414c70cbSLiam Girdwood } 736414c70cbSLiam Girdwood 737414c70cbSLiam Girdwood if (rdev->desc->ops->set_suspend_mode && rstate->mode > 0) { 738414c70cbSLiam Girdwood ret = rdev->desc->ops->set_suspend_mode(rdev, rstate->mode); 739414c70cbSLiam Girdwood if (ret < 0) { 7405da84fd9SJoe Perches rdev_err(rdev, "failed to set mode\n"); 741414c70cbSLiam Girdwood return ret; 742414c70cbSLiam Girdwood } 743414c70cbSLiam Girdwood } 744414c70cbSLiam Girdwood return ret; 745414c70cbSLiam Girdwood } 746414c70cbSLiam Girdwood 747414c70cbSLiam Girdwood /* locks held by caller */ 748414c70cbSLiam Girdwood static int suspend_prepare(struct regulator_dev *rdev, suspend_state_t state) 749414c70cbSLiam Girdwood { 750414c70cbSLiam Girdwood if (!rdev->constraints) 751414c70cbSLiam Girdwood return -EINVAL; 752414c70cbSLiam Girdwood 753414c70cbSLiam Girdwood switch (state) { 754414c70cbSLiam Girdwood case PM_SUSPEND_STANDBY: 755414c70cbSLiam Girdwood return suspend_set_state(rdev, 756414c70cbSLiam Girdwood &rdev->constraints->state_standby); 757414c70cbSLiam Girdwood case PM_SUSPEND_MEM: 758414c70cbSLiam Girdwood return suspend_set_state(rdev, 759414c70cbSLiam Girdwood &rdev->constraints->state_mem); 760414c70cbSLiam Girdwood case PM_SUSPEND_MAX: 761414c70cbSLiam Girdwood return suspend_set_state(rdev, 762414c70cbSLiam Girdwood &rdev->constraints->state_disk); 763414c70cbSLiam Girdwood default: 764414c70cbSLiam Girdwood return -EINVAL; 765414c70cbSLiam Girdwood } 766414c70cbSLiam Girdwood } 767414c70cbSLiam Girdwood 768414c70cbSLiam Girdwood static void print_constraints(struct regulator_dev *rdev) 769414c70cbSLiam Girdwood { 770414c70cbSLiam Girdwood struct regulation_constraints *constraints = rdev->constraints; 771973e9a27SMark Brown char buf[80] = ""; 7728f031b48SMark Brown int count = 0; 7738f031b48SMark Brown int ret; 774414c70cbSLiam Girdwood 7758f031b48SMark Brown if (constraints->min_uV && constraints->max_uV) { 776414c70cbSLiam Girdwood if (constraints->min_uV == constraints->max_uV) 7778f031b48SMark Brown count += sprintf(buf + count, "%d mV ", 778414c70cbSLiam Girdwood constraints->min_uV / 1000); 779414c70cbSLiam Girdwood else 7808f031b48SMark Brown count += sprintf(buf + count, "%d <--> %d mV ", 781414c70cbSLiam Girdwood constraints->min_uV / 1000, 782414c70cbSLiam Girdwood constraints->max_uV / 1000); 7838f031b48SMark Brown } 7848f031b48SMark Brown 7858f031b48SMark Brown if (!constraints->min_uV || 7868f031b48SMark Brown constraints->min_uV != constraints->max_uV) { 7878f031b48SMark Brown ret = _regulator_get_voltage(rdev); 7888f031b48SMark Brown if (ret > 0) 7898f031b48SMark Brown count += sprintf(buf + count, "at %d mV ", ret / 1000); 7908f031b48SMark Brown } 7918f031b48SMark Brown 792bf5892a8SMark Brown if (constraints->uV_offset) 793bf5892a8SMark Brown count += sprintf(buf, "%dmV offset ", 794bf5892a8SMark Brown constraints->uV_offset / 1000); 795bf5892a8SMark Brown 7968f031b48SMark Brown if (constraints->min_uA && constraints->max_uA) { 797414c70cbSLiam Girdwood if (constraints->min_uA == constraints->max_uA) 7988f031b48SMark Brown count += sprintf(buf + count, "%d mA ", 799414c70cbSLiam Girdwood constraints->min_uA / 1000); 800414c70cbSLiam Girdwood else 8018f031b48SMark Brown count += sprintf(buf + count, "%d <--> %d mA ", 802414c70cbSLiam Girdwood constraints->min_uA / 1000, 803414c70cbSLiam Girdwood constraints->max_uA / 1000); 804414c70cbSLiam Girdwood } 8058f031b48SMark Brown 8068f031b48SMark Brown if (!constraints->min_uA || 8078f031b48SMark Brown constraints->min_uA != constraints->max_uA) { 8088f031b48SMark Brown ret = _regulator_get_current_limit(rdev); 8098f031b48SMark Brown if (ret > 0) 810e4a6376bSCyril Chemparathy count += sprintf(buf + count, "at %d mA ", ret / 1000); 8118f031b48SMark Brown } 8128f031b48SMark Brown 813414c70cbSLiam Girdwood if (constraints->valid_modes_mask & REGULATOR_MODE_FAST) 814414c70cbSLiam Girdwood count += sprintf(buf + count, "fast "); 815414c70cbSLiam Girdwood if (constraints->valid_modes_mask & REGULATOR_MODE_NORMAL) 816414c70cbSLiam Girdwood count += sprintf(buf + count, "normal "); 817414c70cbSLiam Girdwood if (constraints->valid_modes_mask & REGULATOR_MODE_IDLE) 818414c70cbSLiam Girdwood count += sprintf(buf + count, "idle "); 819414c70cbSLiam Girdwood if (constraints->valid_modes_mask & REGULATOR_MODE_STANDBY) 820414c70cbSLiam Girdwood count += sprintf(buf + count, "standby"); 821414c70cbSLiam Girdwood 822215b8b05SUwe Kleine-König if (!count) 823215b8b05SUwe Kleine-König sprintf(buf, "no parameters"); 824215b8b05SUwe Kleine-König 82513ce29f8SMark Brown rdev_info(rdev, "%s\n", buf); 8264a682922SMark Brown 8274a682922SMark Brown if ((constraints->min_uV != constraints->max_uV) && 8284a682922SMark Brown !(constraints->valid_ops_mask & REGULATOR_CHANGE_VOLTAGE)) 8294a682922SMark Brown rdev_warn(rdev, 8304a682922SMark Brown "Voltage range but no REGULATOR_CHANGE_VOLTAGE\n"); 831414c70cbSLiam Girdwood } 832414c70cbSLiam Girdwood 833e79055d6SMark Brown static int machine_constraints_voltage(struct regulator_dev *rdev, 8341083c393SMark Brown struct regulation_constraints *constraints) 835e79055d6SMark Brown { 836e79055d6SMark Brown struct regulator_ops *ops = rdev->desc->ops; 837af5866c9SMark Brown int ret; 838af5866c9SMark Brown 839af5866c9SMark Brown /* do we need to apply the constraint voltage */ 840af5866c9SMark Brown if (rdev->constraints->apply_uV && 84175790251SMark Brown rdev->constraints->min_uV == rdev->constraints->max_uV) { 84275790251SMark Brown ret = _regulator_do_set_voltage(rdev, 8433a93f2a9SMark Brown rdev->constraints->min_uV, 84475790251SMark Brown rdev->constraints->max_uV); 845af5866c9SMark Brown if (ret < 0) { 8465da84fd9SJoe Perches rdev_err(rdev, "failed to apply %duV constraint\n", 8475da84fd9SJoe Perches rdev->constraints->min_uV); 848af5866c9SMark Brown return ret; 849af5866c9SMark Brown } 850af5866c9SMark Brown } 851e79055d6SMark Brown 852e79055d6SMark Brown /* constrain machine-level voltage specs to fit 853e79055d6SMark Brown * the actual range supported by this regulator. 854e79055d6SMark Brown */ 855e79055d6SMark Brown if (ops->list_voltage && rdev->desc->n_voltages) { 856e79055d6SMark Brown int count = rdev->desc->n_voltages; 857e79055d6SMark Brown int i; 858e79055d6SMark Brown int min_uV = INT_MAX; 859e79055d6SMark Brown int max_uV = INT_MIN; 860e79055d6SMark Brown int cmin = constraints->min_uV; 861e79055d6SMark Brown int cmax = constraints->max_uV; 862e79055d6SMark Brown 863e79055d6SMark Brown /* it's safe to autoconfigure fixed-voltage supplies 864e79055d6SMark Brown and the constraints are used by list_voltage. */ 865e79055d6SMark Brown if (count == 1 && !cmin) { 866e79055d6SMark Brown cmin = 1; 867e79055d6SMark Brown cmax = INT_MAX; 868e79055d6SMark Brown constraints->min_uV = cmin; 869e79055d6SMark Brown constraints->max_uV = cmax; 870e79055d6SMark Brown } 871e79055d6SMark Brown 872e79055d6SMark Brown /* voltage constraints are optional */ 873e79055d6SMark Brown if ((cmin == 0) && (cmax == 0)) 874e79055d6SMark Brown return 0; 875e79055d6SMark Brown 876e79055d6SMark Brown /* else require explicit machine-level constraints */ 877e79055d6SMark Brown if (cmin <= 0 || cmax <= 0 || cmax < cmin) { 8785da84fd9SJoe Perches rdev_err(rdev, "invalid voltage constraints\n"); 879e79055d6SMark Brown return -EINVAL; 880e79055d6SMark Brown } 881e79055d6SMark Brown 882e79055d6SMark Brown /* initial: [cmin..cmax] valid, [min_uV..max_uV] not */ 883e79055d6SMark Brown for (i = 0; i < count; i++) { 884e79055d6SMark Brown int value; 885e79055d6SMark Brown 886e79055d6SMark Brown value = ops->list_voltage(rdev, i); 887e79055d6SMark Brown if (value <= 0) 888e79055d6SMark Brown continue; 889e79055d6SMark Brown 890e79055d6SMark Brown /* maybe adjust [min_uV..max_uV] */ 891e79055d6SMark Brown if (value >= cmin && value < min_uV) 892e79055d6SMark Brown min_uV = value; 893e79055d6SMark Brown if (value <= cmax && value > max_uV) 894e79055d6SMark Brown max_uV = value; 895e79055d6SMark Brown } 896e79055d6SMark Brown 897e79055d6SMark Brown /* final: [min_uV..max_uV] valid iff constraints valid */ 898e79055d6SMark Brown if (max_uV < min_uV) { 899fff15befSMark Brown rdev_err(rdev, 900fff15befSMark Brown "unsupportable voltage constraints %u-%uuV\n", 901fff15befSMark Brown min_uV, max_uV); 902e79055d6SMark Brown return -EINVAL; 903e79055d6SMark Brown } 904e79055d6SMark Brown 905e79055d6SMark Brown /* use regulator's subset of machine constraints */ 906e79055d6SMark Brown if (constraints->min_uV < min_uV) { 9075da84fd9SJoe Perches rdev_dbg(rdev, "override min_uV, %d -> %d\n", 9085da84fd9SJoe Perches constraints->min_uV, min_uV); 909e79055d6SMark Brown constraints->min_uV = min_uV; 910e79055d6SMark Brown } 911e79055d6SMark Brown if (constraints->max_uV > max_uV) { 9125da84fd9SJoe Perches rdev_dbg(rdev, "override max_uV, %d -> %d\n", 9135da84fd9SJoe Perches constraints->max_uV, max_uV); 914e79055d6SMark Brown constraints->max_uV = max_uV; 915e79055d6SMark Brown } 916e79055d6SMark Brown } 917e79055d6SMark Brown 918e79055d6SMark Brown return 0; 919e79055d6SMark Brown } 920e79055d6SMark Brown 921f8c1700dSLaxman Dewangan static int machine_constraints_current(struct regulator_dev *rdev, 922f8c1700dSLaxman Dewangan struct regulation_constraints *constraints) 923f8c1700dSLaxman Dewangan { 924f8c1700dSLaxman Dewangan struct regulator_ops *ops = rdev->desc->ops; 925f8c1700dSLaxman Dewangan int ret; 926f8c1700dSLaxman Dewangan 927f8c1700dSLaxman Dewangan if (!constraints->min_uA && !constraints->max_uA) 928f8c1700dSLaxman Dewangan return 0; 929f8c1700dSLaxman Dewangan 930f8c1700dSLaxman Dewangan if (constraints->min_uA > constraints->max_uA) { 931f8c1700dSLaxman Dewangan rdev_err(rdev, "Invalid current constraints\n"); 932f8c1700dSLaxman Dewangan return -EINVAL; 933f8c1700dSLaxman Dewangan } 934f8c1700dSLaxman Dewangan 935f8c1700dSLaxman Dewangan if (!ops->set_current_limit || !ops->get_current_limit) { 936f8c1700dSLaxman Dewangan rdev_warn(rdev, "Operation of current configuration missing\n"); 937f8c1700dSLaxman Dewangan return 0; 938f8c1700dSLaxman Dewangan } 939f8c1700dSLaxman Dewangan 940f8c1700dSLaxman Dewangan /* Set regulator current in constraints range */ 941f8c1700dSLaxman Dewangan ret = ops->set_current_limit(rdev, constraints->min_uA, 942f8c1700dSLaxman Dewangan constraints->max_uA); 943f8c1700dSLaxman Dewangan if (ret < 0) { 944f8c1700dSLaxman Dewangan rdev_err(rdev, "Failed to set current constraint, %d\n", ret); 945f8c1700dSLaxman Dewangan return ret; 946f8c1700dSLaxman Dewangan } 947f8c1700dSLaxman Dewangan 948f8c1700dSLaxman Dewangan return 0; 949f8c1700dSLaxman Dewangan } 950f8c1700dSLaxman Dewangan 951a5766f11SLiam Girdwood /** 952a5766f11SLiam Girdwood * set_machine_constraints - sets regulator constraints 95369279fb9SMark Brown * @rdev: regulator source 954c8e7e464SMark Brown * @constraints: constraints to apply 955a5766f11SLiam Girdwood * 956a5766f11SLiam Girdwood * Allows platform initialisation code to define and constrain 957a5766f11SLiam Girdwood * regulator circuits e.g. valid voltage/current ranges, etc. NOTE: 958a5766f11SLiam Girdwood * Constraints *must* be set by platform code in order for some 959a5766f11SLiam Girdwood * regulator operations to proceed i.e. set_voltage, set_current_limit, 960a5766f11SLiam Girdwood * set_mode. 961a5766f11SLiam Girdwood */ 962a5766f11SLiam Girdwood static int set_machine_constraints(struct regulator_dev *rdev, 963f8c12fe3SMark Brown const struct regulation_constraints *constraints) 964a5766f11SLiam Girdwood { 965a5766f11SLiam Girdwood int ret = 0; 966e5fda26cSMark Brown struct regulator_ops *ops = rdev->desc->ops; 967e06f5b4fSMark Brown 9689a8f5e07SMark Brown if (constraints) 969f8c12fe3SMark Brown rdev->constraints = kmemdup(constraints, sizeof(*constraints), 970f8c12fe3SMark Brown GFP_KERNEL); 9719a8f5e07SMark Brown else 9729a8f5e07SMark Brown rdev->constraints = kzalloc(sizeof(*constraints), 9739a8f5e07SMark Brown GFP_KERNEL); 974f8c12fe3SMark Brown if (!rdev->constraints) 975f8c12fe3SMark Brown return -ENOMEM; 976af5866c9SMark Brown 977f8c12fe3SMark Brown ret = machine_constraints_voltage(rdev, rdev->constraints); 978e79055d6SMark Brown if (ret != 0) 9793e2b9abdSMark Brown goto out; 9803e2b9abdSMark Brown 981f8c1700dSLaxman Dewangan ret = machine_constraints_current(rdev, rdev->constraints); 982f8c1700dSLaxman Dewangan if (ret != 0) 983f8c1700dSLaxman Dewangan goto out; 984f8c1700dSLaxman Dewangan 985a5766f11SLiam Girdwood /* do we need to setup our suspend state */ 9869a8f5e07SMark Brown if (rdev->constraints->initial_state) { 987f8c12fe3SMark Brown ret = suspend_prepare(rdev, rdev->constraints->initial_state); 988e06f5b4fSMark Brown if (ret < 0) { 9895da84fd9SJoe Perches rdev_err(rdev, "failed to set suspend state\n"); 990e06f5b4fSMark Brown goto out; 991e06f5b4fSMark Brown } 992e06f5b4fSMark Brown } 993a5766f11SLiam Girdwood 9949a8f5e07SMark Brown if (rdev->constraints->initial_mode) { 995a308466cSMark Brown if (!ops->set_mode) { 9965da84fd9SJoe Perches rdev_err(rdev, "no set_mode operation\n"); 997a308466cSMark Brown ret = -EINVAL; 998a308466cSMark Brown goto out; 999a308466cSMark Brown } 1000a308466cSMark Brown 1001f8c12fe3SMark Brown ret = ops->set_mode(rdev, rdev->constraints->initial_mode); 1002a308466cSMark Brown if (ret < 0) { 10035da84fd9SJoe Perches rdev_err(rdev, "failed to set initial mode: %d\n", ret); 1004a308466cSMark Brown goto out; 1005a308466cSMark Brown } 1006a308466cSMark Brown } 1007a308466cSMark Brown 1008cacf90f2SMark Brown /* If the constraints say the regulator should be on at this point 1009cacf90f2SMark Brown * and we have control then make sure it is enabled. 1010cacf90f2SMark Brown */ 1011f8c12fe3SMark Brown if ((rdev->constraints->always_on || rdev->constraints->boot_on) && 1012f8c12fe3SMark Brown ops->enable) { 1013e5fda26cSMark Brown ret = ops->enable(rdev); 1014e5fda26cSMark Brown if (ret < 0) { 10155da84fd9SJoe Perches rdev_err(rdev, "failed to enable\n"); 1016e5fda26cSMark Brown goto out; 1017e5fda26cSMark Brown } 1018e5fda26cSMark Brown } 1019e5fda26cSMark Brown 10201653ccf4SYadwinder Singh Brar if ((rdev->constraints->ramp_delay || rdev->constraints->ramp_disable) 10211653ccf4SYadwinder Singh Brar && ops->set_ramp_delay) { 10226f0b2c69SYadwinder Singh Brar ret = ops->set_ramp_delay(rdev, rdev->constraints->ramp_delay); 10236f0b2c69SYadwinder Singh Brar if (ret < 0) { 10246f0b2c69SYadwinder Singh Brar rdev_err(rdev, "failed to set ramp_delay\n"); 10256f0b2c69SYadwinder Singh Brar goto out; 10266f0b2c69SYadwinder Singh Brar } 10276f0b2c69SYadwinder Singh Brar } 10286f0b2c69SYadwinder Singh Brar 1029a5766f11SLiam Girdwood print_constraints(rdev); 10301a6958e7SAxel Lin return 0; 1031a5766f11SLiam Girdwood out: 10321a6958e7SAxel Lin kfree(rdev->constraints); 10331a6958e7SAxel Lin rdev->constraints = NULL; 1034a5766f11SLiam Girdwood return ret; 1035a5766f11SLiam Girdwood } 1036a5766f11SLiam Girdwood 1037a5766f11SLiam Girdwood /** 1038a5766f11SLiam Girdwood * set_supply - set regulator supply regulator 103969279fb9SMark Brown * @rdev: regulator name 104069279fb9SMark Brown * @supply_rdev: supply regulator name 1041a5766f11SLiam Girdwood * 1042a5766f11SLiam Girdwood * Called by platform initialisation code to set the supply regulator for this 1043a5766f11SLiam Girdwood * regulator. This ensures that a regulators supply will also be enabled by the 1044a5766f11SLiam Girdwood * core if it's child is enabled. 1045a5766f11SLiam Girdwood */ 1046a5766f11SLiam Girdwood static int set_supply(struct regulator_dev *rdev, 1047a5766f11SLiam Girdwood struct regulator_dev *supply_rdev) 1048a5766f11SLiam Girdwood { 1049a5766f11SLiam Girdwood int err; 1050a5766f11SLiam Girdwood 10513801b86aSMark Brown rdev_info(rdev, "supplied by %s\n", rdev_get_name(supply_rdev)); 10523801b86aSMark Brown 10533801b86aSMark Brown rdev->supply = create_regulator(supply_rdev, &rdev->dev, "SUPPLY"); 105432c78de8SAxel Lin if (rdev->supply == NULL) { 105532c78de8SAxel Lin err = -ENOMEM; 1056a5766f11SLiam Girdwood return err; 1057a5766f11SLiam Girdwood } 105857ad526aSLaxman Dewangan supply_rdev->open_count++; 1059a5766f11SLiam Girdwood 10603801b86aSMark Brown return 0; 10613801b86aSMark Brown } 10623801b86aSMark Brown 1063a5766f11SLiam Girdwood /** 106406c63f93SRandy Dunlap * set_consumer_device_supply - Bind a regulator to a symbolic supply 106569279fb9SMark Brown * @rdev: regulator source 106640f9244fSMark Brown * @consumer_dev_name: dev_name() string for device supply applies to 1067a5766f11SLiam Girdwood * @supply: symbolic name for supply 1068a5766f11SLiam Girdwood * 1069a5766f11SLiam Girdwood * Allows platform initialisation code to map physical regulator 1070a5766f11SLiam Girdwood * sources to symbolic names for supplies for use by devices. Devices 1071a5766f11SLiam Girdwood * should use these symbolic names to request regulators, avoiding the 1072a5766f11SLiam Girdwood * need to provide board-specific regulator names as platform data. 1073a5766f11SLiam Girdwood */ 1074a5766f11SLiam Girdwood static int set_consumer_device_supply(struct regulator_dev *rdev, 1075737f360dSMark Brown const char *consumer_dev_name, 107640f9244fSMark Brown const char *supply) 1077a5766f11SLiam Girdwood { 1078a5766f11SLiam Girdwood struct regulator_map *node; 10799ed2099eSMark Brown int has_dev; 1080a5766f11SLiam Girdwood 1081a5766f11SLiam Girdwood if (supply == NULL) 1082a5766f11SLiam Girdwood return -EINVAL; 1083a5766f11SLiam Girdwood 10849ed2099eSMark Brown if (consumer_dev_name != NULL) 10859ed2099eSMark Brown has_dev = 1; 10869ed2099eSMark Brown else 10879ed2099eSMark Brown has_dev = 0; 10889ed2099eSMark Brown 10896001e13cSDavid Brownell list_for_each_entry(node, ®ulator_map_list, list) { 109023b5cc2aSJani Nikula if (node->dev_name && consumer_dev_name) { 109123b5cc2aSJani Nikula if (strcmp(node->dev_name, consumer_dev_name) != 0) 10926001e13cSDavid Brownell continue; 109323b5cc2aSJani Nikula } else if (node->dev_name || consumer_dev_name) { 109423b5cc2aSJani Nikula continue; 109523b5cc2aSJani Nikula } 109623b5cc2aSJani Nikula 10976001e13cSDavid Brownell if (strcmp(node->supply, supply) != 0) 10986001e13cSDavid Brownell continue; 10996001e13cSDavid Brownell 1100737f360dSMark Brown pr_debug("%s: %s/%s is '%s' supply; fail %s/%s\n", 1101737f360dSMark Brown consumer_dev_name, 11026001e13cSDavid Brownell dev_name(&node->regulator->dev), 11036001e13cSDavid Brownell node->regulator->desc->name, 11046001e13cSDavid Brownell supply, 11051083c393SMark Brown dev_name(&rdev->dev), rdev_get_name(rdev)); 11066001e13cSDavid Brownell return -EBUSY; 11076001e13cSDavid Brownell } 11086001e13cSDavid Brownell 11099ed2099eSMark Brown node = kzalloc(sizeof(struct regulator_map), GFP_KERNEL); 1110a5766f11SLiam Girdwood if (node == NULL) 1111a5766f11SLiam Girdwood return -ENOMEM; 1112a5766f11SLiam Girdwood 1113a5766f11SLiam Girdwood node->regulator = rdev; 1114a5766f11SLiam Girdwood node->supply = supply; 1115a5766f11SLiam Girdwood 11169ed2099eSMark Brown if (has_dev) { 11179ed2099eSMark Brown node->dev_name = kstrdup(consumer_dev_name, GFP_KERNEL); 111840f9244fSMark Brown if (node->dev_name == NULL) { 111940f9244fSMark Brown kfree(node); 112040f9244fSMark Brown return -ENOMEM; 112140f9244fSMark Brown } 11229ed2099eSMark Brown } 112340f9244fSMark Brown 1124a5766f11SLiam Girdwood list_add(&node->list, ®ulator_map_list); 1125a5766f11SLiam Girdwood return 0; 1126a5766f11SLiam Girdwood } 1127a5766f11SLiam Girdwood 11280f1d747bSMike Rapoport static void unset_regulator_supplies(struct regulator_dev *rdev) 11290f1d747bSMike Rapoport { 11300f1d747bSMike Rapoport struct regulator_map *node, *n; 11310f1d747bSMike Rapoport 11320f1d747bSMike Rapoport list_for_each_entry_safe(node, n, ®ulator_map_list, list) { 11330f1d747bSMike Rapoport if (rdev == node->regulator) { 11340f1d747bSMike Rapoport list_del(&node->list); 113540f9244fSMark Brown kfree(node->dev_name); 11360f1d747bSMike Rapoport kfree(node); 11370f1d747bSMike Rapoport } 11380f1d747bSMike Rapoport } 11390f1d747bSMike Rapoport } 11400f1d747bSMike Rapoport 1141f5726ae3SMark Brown #define REG_STR_SIZE 64 1142414c70cbSLiam Girdwood 1143414c70cbSLiam Girdwood static struct regulator *create_regulator(struct regulator_dev *rdev, 1144414c70cbSLiam Girdwood struct device *dev, 1145414c70cbSLiam Girdwood const char *supply_name) 1146414c70cbSLiam Girdwood { 1147414c70cbSLiam Girdwood struct regulator *regulator; 1148414c70cbSLiam Girdwood char buf[REG_STR_SIZE]; 1149414c70cbSLiam Girdwood int err, size; 1150414c70cbSLiam Girdwood 1151414c70cbSLiam Girdwood regulator = kzalloc(sizeof(*regulator), GFP_KERNEL); 1152414c70cbSLiam Girdwood if (regulator == NULL) 1153414c70cbSLiam Girdwood return NULL; 1154414c70cbSLiam Girdwood 1155414c70cbSLiam Girdwood mutex_lock(&rdev->mutex); 1156414c70cbSLiam Girdwood regulator->rdev = rdev; 1157414c70cbSLiam Girdwood list_add(®ulator->list, &rdev->consumer_list); 1158414c70cbSLiam Girdwood 1159414c70cbSLiam Girdwood if (dev) { 1160e2c98eafSShawn Guo regulator->dev = dev; 1161e2c98eafSShawn Guo 1162222cc7b1SMark Brown /* Add a link to the device sysfs entry */ 1163414c70cbSLiam Girdwood size = scnprintf(buf, REG_STR_SIZE, "%s-%s", 1164414c70cbSLiam Girdwood dev->kobj.name, supply_name); 1165414c70cbSLiam Girdwood if (size >= REG_STR_SIZE) 1166222cc7b1SMark Brown goto overflow_err; 1167414c70cbSLiam Girdwood 1168414c70cbSLiam Girdwood regulator->supply_name = kstrdup(buf, GFP_KERNEL); 1169414c70cbSLiam Girdwood if (regulator->supply_name == NULL) 1170222cc7b1SMark Brown goto overflow_err; 1171414c70cbSLiam Girdwood 1172414c70cbSLiam Girdwood err = sysfs_create_link(&rdev->dev.kobj, &dev->kobj, 1173414c70cbSLiam Girdwood buf); 1174414c70cbSLiam Girdwood if (err) { 11755da84fd9SJoe Perches rdev_warn(rdev, "could not add device link %s err %d\n", 11761d7372e1SDaniel Walker dev->kobj.name, err); 1177222cc7b1SMark Brown /* non-fatal */ 1178414c70cbSLiam Girdwood } 11795de70519SMark Brown } else { 11805de70519SMark Brown regulator->supply_name = kstrdup(supply_name, GFP_KERNEL); 11815de70519SMark Brown if (regulator->supply_name == NULL) 1182222cc7b1SMark Brown goto overflow_err; 1183414c70cbSLiam Girdwood } 11845de70519SMark Brown 11855de70519SMark Brown regulator->debugfs = debugfs_create_dir(regulator->supply_name, 11865de70519SMark Brown rdev->debugfs); 118724751434SStephen Boyd if (!regulator->debugfs) { 11885de70519SMark Brown rdev_warn(rdev, "Failed to create debugfs directory\n"); 11895de70519SMark Brown } else { 11905de70519SMark Brown debugfs_create_u32("uA_load", 0444, regulator->debugfs, 11915de70519SMark Brown ®ulator->uA_load); 11925de70519SMark Brown debugfs_create_u32("min_uV", 0444, regulator->debugfs, 11935de70519SMark Brown ®ulator->min_uV); 11945de70519SMark Brown debugfs_create_u32("max_uV", 0444, regulator->debugfs, 11955de70519SMark Brown ®ulator->max_uV); 11965de70519SMark Brown } 11975de70519SMark Brown 11986492bc1bSMark Brown /* 11996492bc1bSMark Brown * Check now if the regulator is an always on regulator - if 12006492bc1bSMark Brown * it is then we don't need to do nearly so much work for 12016492bc1bSMark Brown * enable/disable calls. 12026492bc1bSMark Brown */ 12036492bc1bSMark Brown if (!_regulator_can_change_status(rdev) && 12046492bc1bSMark Brown _regulator_is_enabled(rdev)) 12056492bc1bSMark Brown regulator->always_on = true; 12066492bc1bSMark Brown 1207414c70cbSLiam Girdwood mutex_unlock(&rdev->mutex); 1208414c70cbSLiam Girdwood return regulator; 1209414c70cbSLiam Girdwood overflow_err: 1210414c70cbSLiam Girdwood list_del(®ulator->list); 1211414c70cbSLiam Girdwood kfree(regulator); 1212414c70cbSLiam Girdwood mutex_unlock(&rdev->mutex); 1213414c70cbSLiam Girdwood return NULL; 1214414c70cbSLiam Girdwood } 1215414c70cbSLiam Girdwood 121631aae2beSMark Brown static int _regulator_get_enable_time(struct regulator_dev *rdev) 121731aae2beSMark Brown { 121800c877c6SLaxman Dewangan if (rdev->constraints && rdev->constraints->enable_time) 121900c877c6SLaxman Dewangan return rdev->constraints->enable_time; 122031aae2beSMark Brown if (!rdev->desc->ops->enable_time) 122179511ed3SMark Brown return rdev->desc->enable_time; 122231aae2beSMark Brown return rdev->desc->ops->enable_time(rdev); 122331aae2beSMark Brown } 122431aae2beSMark Brown 1225a06ccd9cSCharles Keepax static struct regulator_supply_alias *regulator_find_supply_alias( 1226a06ccd9cSCharles Keepax struct device *dev, const char *supply) 1227a06ccd9cSCharles Keepax { 1228a06ccd9cSCharles Keepax struct regulator_supply_alias *map; 1229a06ccd9cSCharles Keepax 1230a06ccd9cSCharles Keepax list_for_each_entry(map, ®ulator_supply_alias_list, list) 1231a06ccd9cSCharles Keepax if (map->src_dev == dev && strcmp(map->src_supply, supply) == 0) 1232a06ccd9cSCharles Keepax return map; 1233a06ccd9cSCharles Keepax 1234a06ccd9cSCharles Keepax return NULL; 1235a06ccd9cSCharles Keepax } 1236a06ccd9cSCharles Keepax 1237a06ccd9cSCharles Keepax static void regulator_supply_alias(struct device **dev, const char **supply) 1238a06ccd9cSCharles Keepax { 1239a06ccd9cSCharles Keepax struct regulator_supply_alias *map; 1240a06ccd9cSCharles Keepax 1241a06ccd9cSCharles Keepax map = regulator_find_supply_alias(*dev, *supply); 1242a06ccd9cSCharles Keepax if (map) { 1243a06ccd9cSCharles Keepax dev_dbg(*dev, "Mapping supply %s to %s,%s\n", 1244a06ccd9cSCharles Keepax *supply, map->alias_supply, 1245a06ccd9cSCharles Keepax dev_name(map->alias_dev)); 1246a06ccd9cSCharles Keepax *dev = map->alias_dev; 1247a06ccd9cSCharles Keepax *supply = map->alias_supply; 1248a06ccd9cSCharles Keepax } 1249a06ccd9cSCharles Keepax } 1250a06ccd9cSCharles Keepax 125169511a45SRajendra Nayak static struct regulator_dev *regulator_dev_lookup(struct device *dev, 12526d191a5fSMark Brown const char *supply, 12536d191a5fSMark Brown int *ret) 125469511a45SRajendra Nayak { 125569511a45SRajendra Nayak struct regulator_dev *r; 125669511a45SRajendra Nayak struct device_node *node; 1257576ca436SMark Brown struct regulator_map *map; 1258576ca436SMark Brown const char *devname = NULL; 125969511a45SRajendra Nayak 1260a06ccd9cSCharles Keepax regulator_supply_alias(&dev, &supply); 1261a06ccd9cSCharles Keepax 126269511a45SRajendra Nayak /* first do a dt based lookup */ 126369511a45SRajendra Nayak if (dev && dev->of_node) { 126469511a45SRajendra Nayak node = of_get_regulator(dev, supply); 12656d191a5fSMark Brown if (node) { 126669511a45SRajendra Nayak list_for_each_entry(r, ®ulator_list, list) 126769511a45SRajendra Nayak if (r->dev.parent && 126869511a45SRajendra Nayak node == r->dev.of_node) 126969511a45SRajendra Nayak return r; 12706d191a5fSMark Brown } else { 12716d191a5fSMark Brown /* 12726d191a5fSMark Brown * If we couldn't even get the node then it's 12736d191a5fSMark Brown * not just that the device didn't register 12746d191a5fSMark Brown * yet, there's no node and we'll never 12756d191a5fSMark Brown * succeed. 12766d191a5fSMark Brown */ 12776d191a5fSMark Brown *ret = -ENODEV; 12786d191a5fSMark Brown } 127969511a45SRajendra Nayak } 128069511a45SRajendra Nayak 128169511a45SRajendra Nayak /* if not found, try doing it non-dt way */ 1282576ca436SMark Brown if (dev) 1283576ca436SMark Brown devname = dev_name(dev); 1284576ca436SMark Brown 128569511a45SRajendra Nayak list_for_each_entry(r, ®ulator_list, list) 128669511a45SRajendra Nayak if (strcmp(rdev_get_name(r), supply) == 0) 128769511a45SRajendra Nayak return r; 128869511a45SRajendra Nayak 1289576ca436SMark Brown list_for_each_entry(map, ®ulator_map_list, list) { 1290576ca436SMark Brown /* If the mapping has a device set up it must match */ 1291576ca436SMark Brown if (map->dev_name && 1292576ca436SMark Brown (!devname || strcmp(map->dev_name, devname))) 1293576ca436SMark Brown continue; 1294576ca436SMark Brown 1295576ca436SMark Brown if (strcmp(map->supply, supply) == 0) 1296576ca436SMark Brown return map->regulator; 1297576ca436SMark Brown } 1298576ca436SMark Brown 1299576ca436SMark Brown 130069511a45SRajendra Nayak return NULL; 130169511a45SRajendra Nayak } 130269511a45SRajendra Nayak 13035ffbd136SMark Brown /* Internal regulator request function */ 13045ffbd136SMark Brown static struct regulator *_regulator_get(struct device *dev, const char *id, 13054ddfebd3SMark Brown bool exclusive, bool allow_dummy) 1306414c70cbSLiam Girdwood { 1307414c70cbSLiam Girdwood struct regulator_dev *rdev; 130804bf3011SMark Brown struct regulator *regulator = ERR_PTR(-EPROBE_DEFER); 130940f9244fSMark Brown const char *devname = NULL; 13109b92da1fSMark Brown int ret = -EPROBE_DEFER; 1311414c70cbSLiam Girdwood 1312414c70cbSLiam Girdwood if (id == NULL) { 13135da84fd9SJoe Perches pr_err("get() with no identifier\n"); 1314043c998fSMark Brown return ERR_PTR(-EINVAL); 1315414c70cbSLiam Girdwood } 1316414c70cbSLiam Girdwood 131740f9244fSMark Brown if (dev) 131840f9244fSMark Brown devname = dev_name(dev); 131940f9244fSMark Brown 1320414c70cbSLiam Girdwood mutex_lock(®ulator_list_mutex); 1321414c70cbSLiam Girdwood 13226d191a5fSMark Brown rdev = regulator_dev_lookup(dev, id, &ret); 132369511a45SRajendra Nayak if (rdev) 132469511a45SRajendra Nayak goto found; 132569511a45SRajendra Nayak 1326ef60abbbSMark Brown regulator = ERR_PTR(ret); 1327ef60abbbSMark Brown 13281e4b545cSNishanth Menon /* 13291e4b545cSNishanth Menon * If we have return value from dev_lookup fail, we do not expect to 13301e4b545cSNishanth Menon * succeed, so, quit with appropriate error value 13311e4b545cSNishanth Menon */ 13324ddfebd3SMark Brown if (ret && ret != -ENODEV) { 13331e4b545cSNishanth Menon goto out; 13341e4b545cSNishanth Menon } 13351e4b545cSNishanth Menon 133634abbd68SMark Brown if (!devname) 133734abbd68SMark Brown devname = "deviceless"; 133834abbd68SMark Brown 13394ddfebd3SMark Brown /* 13404ddfebd3SMark Brown * Assume that a regulator is physically present and enabled 13414ddfebd3SMark Brown * even if it isn't hooked up and just provide a dummy. 134234abbd68SMark Brown */ 13434ddfebd3SMark Brown if (has_full_constraints && allow_dummy) { 13445da84fd9SJoe Perches pr_warn("%s supply %s not found, using dummy regulator\n", 134534abbd68SMark Brown devname, id); 13464ddfebd3SMark Brown 134734abbd68SMark Brown rdev = dummy_regulator_rdev; 134834abbd68SMark Brown goto found; 13494ddfebd3SMark Brown } else { 13504ddfebd3SMark Brown dev_err(dev, "dummy supplies not allowed\n"); 135134abbd68SMark Brown } 135234abbd68SMark Brown 1353414c70cbSLiam Girdwood mutex_unlock(®ulator_list_mutex); 1354414c70cbSLiam Girdwood return regulator; 1355414c70cbSLiam Girdwood 1356414c70cbSLiam Girdwood found: 13575ffbd136SMark Brown if (rdev->exclusive) { 13585ffbd136SMark Brown regulator = ERR_PTR(-EPERM); 13595ffbd136SMark Brown goto out; 13605ffbd136SMark Brown } 13615ffbd136SMark Brown 13625ffbd136SMark Brown if (exclusive && rdev->open_count) { 13635ffbd136SMark Brown regulator = ERR_PTR(-EBUSY); 13645ffbd136SMark Brown goto out; 13655ffbd136SMark Brown } 13665ffbd136SMark Brown 1367a5766f11SLiam Girdwood if (!try_module_get(rdev->owner)) 1368a5766f11SLiam Girdwood goto out; 1369a5766f11SLiam Girdwood 1370414c70cbSLiam Girdwood regulator = create_regulator(rdev, dev, id); 1371414c70cbSLiam Girdwood if (regulator == NULL) { 1372414c70cbSLiam Girdwood regulator = ERR_PTR(-ENOMEM); 1373414c70cbSLiam Girdwood module_put(rdev->owner); 1374bcda4321SAxel Lin goto out; 1375414c70cbSLiam Girdwood } 1376414c70cbSLiam Girdwood 13775ffbd136SMark Brown rdev->open_count++; 13785ffbd136SMark Brown if (exclusive) { 13795ffbd136SMark Brown rdev->exclusive = 1; 13805ffbd136SMark Brown 13815ffbd136SMark Brown ret = _regulator_is_enabled(rdev); 13825ffbd136SMark Brown if (ret > 0) 13835ffbd136SMark Brown rdev->use_count = 1; 13845ffbd136SMark Brown else 13855ffbd136SMark Brown rdev->use_count = 0; 13865ffbd136SMark Brown } 13875ffbd136SMark Brown 1388a5766f11SLiam Girdwood out: 1389414c70cbSLiam Girdwood mutex_unlock(®ulator_list_mutex); 13905ffbd136SMark Brown 1391414c70cbSLiam Girdwood return regulator; 1392414c70cbSLiam Girdwood } 13935ffbd136SMark Brown 13945ffbd136SMark Brown /** 13955ffbd136SMark Brown * regulator_get - lookup and obtain a reference to a regulator. 13965ffbd136SMark Brown * @dev: device for regulator "consumer" 13975ffbd136SMark Brown * @id: Supply name or regulator ID. 13985ffbd136SMark Brown * 13995ffbd136SMark Brown * Returns a struct regulator corresponding to the regulator producer, 14005ffbd136SMark Brown * or IS_ERR() condition containing errno. 14015ffbd136SMark Brown * 14025ffbd136SMark Brown * Use of supply names configured via regulator_set_device_supply() is 14035ffbd136SMark Brown * strongly encouraged. It is recommended that the supply name used 14045ffbd136SMark Brown * should match the name used for the supply and/or the relevant 14055ffbd136SMark Brown * device pins in the datasheet. 14065ffbd136SMark Brown */ 14075ffbd136SMark Brown struct regulator *regulator_get(struct device *dev, const char *id) 14085ffbd136SMark Brown { 14094ddfebd3SMark Brown return _regulator_get(dev, id, false, true); 14105ffbd136SMark Brown } 1411414c70cbSLiam Girdwood EXPORT_SYMBOL_GPL(regulator_get); 1412414c70cbSLiam Girdwood 1413070b9079SStephen Boyd /** 14145ffbd136SMark Brown * regulator_get_exclusive - obtain exclusive access to a regulator. 14155ffbd136SMark Brown * @dev: device for regulator "consumer" 14165ffbd136SMark Brown * @id: Supply name or regulator ID. 14175ffbd136SMark Brown * 14185ffbd136SMark Brown * Returns a struct regulator corresponding to the regulator producer, 14195ffbd136SMark Brown * or IS_ERR() condition containing errno. Other consumers will be 14205ffbd136SMark Brown * unable to obtain this reference is held and the use count for the 14215ffbd136SMark Brown * regulator will be initialised to reflect the current state of the 14225ffbd136SMark Brown * regulator. 14235ffbd136SMark Brown * 14245ffbd136SMark Brown * This is intended for use by consumers which cannot tolerate shared 14255ffbd136SMark Brown * use of the regulator such as those which need to force the 14265ffbd136SMark Brown * regulator off for correct operation of the hardware they are 14275ffbd136SMark Brown * controlling. 14285ffbd136SMark Brown * 14295ffbd136SMark Brown * Use of supply names configured via regulator_set_device_supply() is 14305ffbd136SMark Brown * strongly encouraged. It is recommended that the supply name used 14315ffbd136SMark Brown * should match the name used for the supply and/or the relevant 14325ffbd136SMark Brown * device pins in the datasheet. 14335ffbd136SMark Brown */ 14345ffbd136SMark Brown struct regulator *regulator_get_exclusive(struct device *dev, const char *id) 14355ffbd136SMark Brown { 14364ddfebd3SMark Brown return _regulator_get(dev, id, true, false); 14375ffbd136SMark Brown } 14385ffbd136SMark Brown EXPORT_SYMBOL_GPL(regulator_get_exclusive); 14395ffbd136SMark Brown 1440de1dd9fdSMark Brown /** 1441de1dd9fdSMark Brown * regulator_get_optional - obtain optional access to a regulator. 1442de1dd9fdSMark Brown * @dev: device for regulator "consumer" 1443de1dd9fdSMark Brown * @id: Supply name or regulator ID. 1444de1dd9fdSMark Brown * 1445de1dd9fdSMark Brown * Returns a struct regulator corresponding to the regulator producer, 1446de1dd9fdSMark Brown * or IS_ERR() condition containing errno. Other consumers will be 1447de1dd9fdSMark Brown * unable to obtain this reference is held and the use count for the 1448de1dd9fdSMark Brown * regulator will be initialised to reflect the current state of the 1449de1dd9fdSMark Brown * regulator. 1450de1dd9fdSMark Brown * 1451de1dd9fdSMark Brown * This is intended for use by consumers for devices which can have 1452de1dd9fdSMark Brown * some supplies unconnected in normal use, such as some MMC devices. 1453de1dd9fdSMark Brown * It can allow the regulator core to provide stub supplies for other 1454de1dd9fdSMark Brown * supplies requested using normal regulator_get() calls without 1455de1dd9fdSMark Brown * disrupting the operation of drivers that can handle absent 1456de1dd9fdSMark Brown * supplies. 1457de1dd9fdSMark Brown * 1458de1dd9fdSMark Brown * Use of supply names configured via regulator_set_device_supply() is 1459de1dd9fdSMark Brown * strongly encouraged. It is recommended that the supply name used 1460de1dd9fdSMark Brown * should match the name used for the supply and/or the relevant 1461de1dd9fdSMark Brown * device pins in the datasheet. 1462de1dd9fdSMark Brown */ 1463de1dd9fdSMark Brown struct regulator *regulator_get_optional(struct device *dev, const char *id) 1464de1dd9fdSMark Brown { 14654ddfebd3SMark Brown return _regulator_get(dev, id, false, false); 1466de1dd9fdSMark Brown } 1467de1dd9fdSMark Brown EXPORT_SYMBOL_GPL(regulator_get_optional); 1468de1dd9fdSMark Brown 146923ff2f0fSCharles Keepax /* Locks held by regulator_put() */ 147023ff2f0fSCharles Keepax static void _regulator_put(struct regulator *regulator) 1471414c70cbSLiam Girdwood { 1472414c70cbSLiam Girdwood struct regulator_dev *rdev; 1473414c70cbSLiam Girdwood 1474414c70cbSLiam Girdwood if (regulator == NULL || IS_ERR(regulator)) 1475414c70cbSLiam Girdwood return; 1476414c70cbSLiam Girdwood 1477414c70cbSLiam Girdwood rdev = regulator->rdev; 1478414c70cbSLiam Girdwood 14795de70519SMark Brown debugfs_remove_recursive(regulator->debugfs); 14805de70519SMark Brown 1481414c70cbSLiam Girdwood /* remove any sysfs entries */ 1482e2c98eafSShawn Guo if (regulator->dev) 1483414c70cbSLiam Girdwood sysfs_remove_link(&rdev->dev.kobj, regulator->supply_name); 14845de70519SMark Brown kfree(regulator->supply_name); 1485414c70cbSLiam Girdwood list_del(®ulator->list); 1486414c70cbSLiam Girdwood kfree(regulator); 1487414c70cbSLiam Girdwood 14885ffbd136SMark Brown rdev->open_count--; 14895ffbd136SMark Brown rdev->exclusive = 0; 14905ffbd136SMark Brown 1491414c70cbSLiam Girdwood module_put(rdev->owner); 149223ff2f0fSCharles Keepax } 149323ff2f0fSCharles Keepax 149423ff2f0fSCharles Keepax /** 149523ff2f0fSCharles Keepax * regulator_put - "free" the regulator source 149623ff2f0fSCharles Keepax * @regulator: regulator source 149723ff2f0fSCharles Keepax * 149823ff2f0fSCharles Keepax * Note: drivers must ensure that all regulator_enable calls made on this 149923ff2f0fSCharles Keepax * regulator source are balanced by regulator_disable calls prior to calling 150023ff2f0fSCharles Keepax * this function. 150123ff2f0fSCharles Keepax */ 150223ff2f0fSCharles Keepax void regulator_put(struct regulator *regulator) 150323ff2f0fSCharles Keepax { 150423ff2f0fSCharles Keepax mutex_lock(®ulator_list_mutex); 150523ff2f0fSCharles Keepax _regulator_put(regulator); 1506414c70cbSLiam Girdwood mutex_unlock(®ulator_list_mutex); 1507414c70cbSLiam Girdwood } 1508414c70cbSLiam Girdwood EXPORT_SYMBOL_GPL(regulator_put); 1509414c70cbSLiam Girdwood 1510a06ccd9cSCharles Keepax /** 1511a06ccd9cSCharles Keepax * regulator_register_supply_alias - Provide device alias for supply lookup 1512a06ccd9cSCharles Keepax * 1513a06ccd9cSCharles Keepax * @dev: device that will be given as the regulator "consumer" 1514a06ccd9cSCharles Keepax * @id: Supply name or regulator ID 1515a06ccd9cSCharles Keepax * @alias_dev: device that should be used to lookup the supply 1516a06ccd9cSCharles Keepax * @alias_id: Supply name or regulator ID that should be used to lookup the 1517a06ccd9cSCharles Keepax * supply 1518a06ccd9cSCharles Keepax * 1519a06ccd9cSCharles Keepax * All lookups for id on dev will instead be conducted for alias_id on 1520a06ccd9cSCharles Keepax * alias_dev. 1521a06ccd9cSCharles Keepax */ 1522a06ccd9cSCharles Keepax int regulator_register_supply_alias(struct device *dev, const char *id, 1523a06ccd9cSCharles Keepax struct device *alias_dev, 1524a06ccd9cSCharles Keepax const char *alias_id) 1525a06ccd9cSCharles Keepax { 1526a06ccd9cSCharles Keepax struct regulator_supply_alias *map; 1527a06ccd9cSCharles Keepax 1528a06ccd9cSCharles Keepax map = regulator_find_supply_alias(dev, id); 1529a06ccd9cSCharles Keepax if (map) 1530a06ccd9cSCharles Keepax return -EEXIST; 1531a06ccd9cSCharles Keepax 1532a06ccd9cSCharles Keepax map = kzalloc(sizeof(struct regulator_supply_alias), GFP_KERNEL); 1533a06ccd9cSCharles Keepax if (!map) 1534a06ccd9cSCharles Keepax return -ENOMEM; 1535a06ccd9cSCharles Keepax 1536a06ccd9cSCharles Keepax map->src_dev = dev; 1537a06ccd9cSCharles Keepax map->src_supply = id; 1538a06ccd9cSCharles Keepax map->alias_dev = alias_dev; 1539a06ccd9cSCharles Keepax map->alias_supply = alias_id; 1540a06ccd9cSCharles Keepax 1541a06ccd9cSCharles Keepax list_add(&map->list, ®ulator_supply_alias_list); 1542a06ccd9cSCharles Keepax 1543a06ccd9cSCharles Keepax pr_info("Adding alias for supply %s,%s -> %s,%s\n", 1544a06ccd9cSCharles Keepax id, dev_name(dev), alias_id, dev_name(alias_dev)); 1545a06ccd9cSCharles Keepax 1546a06ccd9cSCharles Keepax return 0; 1547a06ccd9cSCharles Keepax } 1548a06ccd9cSCharles Keepax EXPORT_SYMBOL_GPL(regulator_register_supply_alias); 1549a06ccd9cSCharles Keepax 1550a06ccd9cSCharles Keepax /** 1551a06ccd9cSCharles Keepax * regulator_unregister_supply_alias - Remove device alias 1552a06ccd9cSCharles Keepax * 1553a06ccd9cSCharles Keepax * @dev: device that will be given as the regulator "consumer" 1554a06ccd9cSCharles Keepax * @id: Supply name or regulator ID 1555a06ccd9cSCharles Keepax * 1556a06ccd9cSCharles Keepax * Remove a lookup alias if one exists for id on dev. 1557a06ccd9cSCharles Keepax */ 1558a06ccd9cSCharles Keepax void regulator_unregister_supply_alias(struct device *dev, const char *id) 1559a06ccd9cSCharles Keepax { 1560a06ccd9cSCharles Keepax struct regulator_supply_alias *map; 1561a06ccd9cSCharles Keepax 1562a06ccd9cSCharles Keepax map = regulator_find_supply_alias(dev, id); 1563a06ccd9cSCharles Keepax if (map) { 1564a06ccd9cSCharles Keepax list_del(&map->list); 1565a06ccd9cSCharles Keepax kfree(map); 1566a06ccd9cSCharles Keepax } 1567a06ccd9cSCharles Keepax } 1568a06ccd9cSCharles Keepax EXPORT_SYMBOL_GPL(regulator_unregister_supply_alias); 1569a06ccd9cSCharles Keepax 1570a06ccd9cSCharles Keepax /** 1571a06ccd9cSCharles Keepax * regulator_bulk_register_supply_alias - register multiple aliases 1572a06ccd9cSCharles Keepax * 1573a06ccd9cSCharles Keepax * @dev: device that will be given as the regulator "consumer" 1574a06ccd9cSCharles Keepax * @id: List of supply names or regulator IDs 1575a06ccd9cSCharles Keepax * @alias_dev: device that should be used to lookup the supply 1576a06ccd9cSCharles Keepax * @alias_id: List of supply names or regulator IDs that should be used to 1577a06ccd9cSCharles Keepax * lookup the supply 1578a06ccd9cSCharles Keepax * @num_id: Number of aliases to register 1579a06ccd9cSCharles Keepax * 1580a06ccd9cSCharles Keepax * @return 0 on success, an errno on failure. 1581a06ccd9cSCharles Keepax * 1582a06ccd9cSCharles Keepax * This helper function allows drivers to register several supply 1583a06ccd9cSCharles Keepax * aliases in one operation. If any of the aliases cannot be 1584a06ccd9cSCharles Keepax * registered any aliases that were registered will be removed 1585a06ccd9cSCharles Keepax * before returning to the caller. 1586a06ccd9cSCharles Keepax */ 1587a06ccd9cSCharles Keepax int regulator_bulk_register_supply_alias(struct device *dev, const char **id, 1588a06ccd9cSCharles Keepax struct device *alias_dev, 1589a06ccd9cSCharles Keepax const char **alias_id, 1590a06ccd9cSCharles Keepax int num_id) 1591a06ccd9cSCharles Keepax { 1592a06ccd9cSCharles Keepax int i; 1593a06ccd9cSCharles Keepax int ret; 1594a06ccd9cSCharles Keepax 1595a06ccd9cSCharles Keepax for (i = 0; i < num_id; ++i) { 1596a06ccd9cSCharles Keepax ret = regulator_register_supply_alias(dev, id[i], alias_dev, 1597a06ccd9cSCharles Keepax alias_id[i]); 1598a06ccd9cSCharles Keepax if (ret < 0) 1599a06ccd9cSCharles Keepax goto err; 1600a06ccd9cSCharles Keepax } 1601a06ccd9cSCharles Keepax 1602a06ccd9cSCharles Keepax return 0; 1603a06ccd9cSCharles Keepax 1604a06ccd9cSCharles Keepax err: 1605a06ccd9cSCharles Keepax dev_err(dev, 1606a06ccd9cSCharles Keepax "Failed to create supply alias %s,%s -> %s,%s\n", 1607a06ccd9cSCharles Keepax id[i], dev_name(dev), alias_id[i], dev_name(alias_dev)); 1608a06ccd9cSCharles Keepax 1609a06ccd9cSCharles Keepax while (--i >= 0) 1610a06ccd9cSCharles Keepax regulator_unregister_supply_alias(dev, id[i]); 1611a06ccd9cSCharles Keepax 1612a06ccd9cSCharles Keepax return ret; 1613a06ccd9cSCharles Keepax } 1614a06ccd9cSCharles Keepax EXPORT_SYMBOL_GPL(regulator_bulk_register_supply_alias); 1615a06ccd9cSCharles Keepax 1616a06ccd9cSCharles Keepax /** 1617a06ccd9cSCharles Keepax * regulator_bulk_unregister_supply_alias - unregister multiple aliases 1618a06ccd9cSCharles Keepax * 1619a06ccd9cSCharles Keepax * @dev: device that will be given as the regulator "consumer" 1620a06ccd9cSCharles Keepax * @id: List of supply names or regulator IDs 1621a06ccd9cSCharles Keepax * @num_id: Number of aliases to unregister 1622a06ccd9cSCharles Keepax * 1623a06ccd9cSCharles Keepax * This helper function allows drivers to unregister several supply 1624a06ccd9cSCharles Keepax * aliases in one operation. 1625a06ccd9cSCharles Keepax */ 1626a06ccd9cSCharles Keepax void regulator_bulk_unregister_supply_alias(struct device *dev, 1627a06ccd9cSCharles Keepax const char **id, 1628a06ccd9cSCharles Keepax int num_id) 1629a06ccd9cSCharles Keepax { 1630a06ccd9cSCharles Keepax int i; 1631a06ccd9cSCharles Keepax 1632a06ccd9cSCharles Keepax for (i = 0; i < num_id; ++i) 1633a06ccd9cSCharles Keepax regulator_unregister_supply_alias(dev, id[i]); 1634a06ccd9cSCharles Keepax } 1635a06ccd9cSCharles Keepax EXPORT_SYMBOL_GPL(regulator_bulk_unregister_supply_alias); 1636a06ccd9cSCharles Keepax 1637a06ccd9cSCharles Keepax 1638f19b00daSKim, Milo /* Manage enable GPIO list. Same GPIO pin can be shared among regulators */ 1639f19b00daSKim, Milo static int regulator_ena_gpio_request(struct regulator_dev *rdev, 1640f19b00daSKim, Milo const struct regulator_config *config) 1641f19b00daSKim, Milo { 1642f19b00daSKim, Milo struct regulator_enable_gpio *pin; 1643f19b00daSKim, Milo int ret; 1644f19b00daSKim, Milo 1645f19b00daSKim, Milo list_for_each_entry(pin, ®ulator_ena_gpio_list, list) { 1646f19b00daSKim, Milo if (pin->gpio == config->ena_gpio) { 1647f19b00daSKim, Milo rdev_dbg(rdev, "GPIO %d is already used\n", 1648f19b00daSKim, Milo config->ena_gpio); 1649f19b00daSKim, Milo goto update_ena_gpio_to_rdev; 1650f19b00daSKim, Milo } 1651f19b00daSKim, Milo } 1652f19b00daSKim, Milo 1653f19b00daSKim, Milo ret = gpio_request_one(config->ena_gpio, 1654f19b00daSKim, Milo GPIOF_DIR_OUT | config->ena_gpio_flags, 1655f19b00daSKim, Milo rdev_get_name(rdev)); 1656f19b00daSKim, Milo if (ret) 1657f19b00daSKim, Milo return ret; 1658f19b00daSKim, Milo 1659f19b00daSKim, Milo pin = kzalloc(sizeof(struct regulator_enable_gpio), GFP_KERNEL); 1660f19b00daSKim, Milo if (pin == NULL) { 1661f19b00daSKim, Milo gpio_free(config->ena_gpio); 1662f19b00daSKim, Milo return -ENOMEM; 1663f19b00daSKim, Milo } 1664f19b00daSKim, Milo 1665f19b00daSKim, Milo pin->gpio = config->ena_gpio; 1666f19b00daSKim, Milo pin->ena_gpio_invert = config->ena_gpio_invert; 1667f19b00daSKim, Milo list_add(&pin->list, ®ulator_ena_gpio_list); 1668f19b00daSKim, Milo 1669f19b00daSKim, Milo update_ena_gpio_to_rdev: 1670f19b00daSKim, Milo pin->request_count++; 1671f19b00daSKim, Milo rdev->ena_pin = pin; 1672f19b00daSKim, Milo return 0; 1673f19b00daSKim, Milo } 1674f19b00daSKim, Milo 1675f19b00daSKim, Milo static void regulator_ena_gpio_free(struct regulator_dev *rdev) 1676f19b00daSKim, Milo { 1677f19b00daSKim, Milo struct regulator_enable_gpio *pin, *n; 1678f19b00daSKim, Milo 1679f19b00daSKim, Milo if (!rdev->ena_pin) 1680f19b00daSKim, Milo return; 1681f19b00daSKim, Milo 1682f19b00daSKim, Milo /* Free the GPIO only in case of no use */ 1683f19b00daSKim, Milo list_for_each_entry_safe(pin, n, ®ulator_ena_gpio_list, list) { 1684f19b00daSKim, Milo if (pin->gpio == rdev->ena_pin->gpio) { 1685f19b00daSKim, Milo if (pin->request_count <= 1) { 1686f19b00daSKim, Milo pin->request_count = 0; 1687f19b00daSKim, Milo gpio_free(pin->gpio); 1688f19b00daSKim, Milo list_del(&pin->list); 1689f19b00daSKim, Milo kfree(pin); 1690f19b00daSKim, Milo } else { 1691f19b00daSKim, Milo pin->request_count--; 1692f19b00daSKim, Milo } 1693f19b00daSKim, Milo } 1694f19b00daSKim, Milo } 1695f19b00daSKim, Milo } 1696f19b00daSKim, Milo 1697967cfb18SKim, Milo /** 169831d6eebfSRobert P. J. Day * regulator_ena_gpio_ctrl - balance enable_count of each GPIO and actual GPIO pin control 169931d6eebfSRobert P. J. Day * @rdev: regulator_dev structure 170031d6eebfSRobert P. J. Day * @enable: enable GPIO at initial use? 170131d6eebfSRobert P. J. Day * 1702967cfb18SKim, Milo * GPIO is enabled in case of initial use. (enable_count is 0) 1703967cfb18SKim, Milo * GPIO is disabled when it is not shared any more. (enable_count <= 1) 1704967cfb18SKim, Milo */ 1705967cfb18SKim, Milo static int regulator_ena_gpio_ctrl(struct regulator_dev *rdev, bool enable) 1706967cfb18SKim, Milo { 1707967cfb18SKim, Milo struct regulator_enable_gpio *pin = rdev->ena_pin; 1708967cfb18SKim, Milo 1709967cfb18SKim, Milo if (!pin) 1710967cfb18SKim, Milo return -EINVAL; 1711967cfb18SKim, Milo 1712967cfb18SKim, Milo if (enable) { 1713967cfb18SKim, Milo /* Enable GPIO at initial use */ 1714967cfb18SKim, Milo if (pin->enable_count == 0) 1715967cfb18SKim, Milo gpio_set_value_cansleep(pin->gpio, 1716967cfb18SKim, Milo !pin->ena_gpio_invert); 1717967cfb18SKim, Milo 1718967cfb18SKim, Milo pin->enable_count++; 1719967cfb18SKim, Milo } else { 1720967cfb18SKim, Milo if (pin->enable_count > 1) { 1721967cfb18SKim, Milo pin->enable_count--; 1722967cfb18SKim, Milo return 0; 1723967cfb18SKim, Milo } 1724967cfb18SKim, Milo 1725967cfb18SKim, Milo /* Disable GPIO if not used */ 1726967cfb18SKim, Milo if (pin->enable_count <= 1) { 1727967cfb18SKim, Milo gpio_set_value_cansleep(pin->gpio, 1728967cfb18SKim, Milo pin->ena_gpio_invert); 1729967cfb18SKim, Milo pin->enable_count = 0; 1730967cfb18SKim, Milo } 1731967cfb18SKim, Milo } 1732967cfb18SKim, Milo 1733967cfb18SKim, Milo return 0; 1734967cfb18SKim, Milo } 1735967cfb18SKim, Milo 17365c5659d0SMark Brown static int _regulator_do_enable(struct regulator_dev *rdev) 17375c5659d0SMark Brown { 17385c5659d0SMark Brown int ret, delay; 17395c5659d0SMark Brown 17405c5659d0SMark Brown /* Query before enabling in case configuration dependent. */ 17415c5659d0SMark Brown ret = _regulator_get_enable_time(rdev); 17425c5659d0SMark Brown if (ret >= 0) { 17435c5659d0SMark Brown delay = ret; 17445c5659d0SMark Brown } else { 17455c5659d0SMark Brown rdev_warn(rdev, "enable_time() failed: %d\n", ret); 17465c5659d0SMark Brown delay = 0; 17475c5659d0SMark Brown } 17485c5659d0SMark Brown 17495c5659d0SMark Brown trace_regulator_enable(rdev_get_name(rdev)); 17505c5659d0SMark Brown 1751967cfb18SKim, Milo if (rdev->ena_pin) { 1752967cfb18SKim, Milo ret = regulator_ena_gpio_ctrl(rdev, true); 1753967cfb18SKim, Milo if (ret < 0) 1754967cfb18SKim, Milo return ret; 175565f73508SMark Brown rdev->ena_gpio_state = 1; 175665f73508SMark Brown } else if (rdev->desc->ops->enable) { 17575c5659d0SMark Brown ret = rdev->desc->ops->enable(rdev); 17585c5659d0SMark Brown if (ret < 0) 17595c5659d0SMark Brown return ret; 17605c5659d0SMark Brown } else { 17615c5659d0SMark Brown return -EINVAL; 17625c5659d0SMark Brown } 17635c5659d0SMark Brown 17645c5659d0SMark Brown /* Allow the regulator to ramp; it would be useful to extend 17655c5659d0SMark Brown * this for bulk operations so that the regulators can ramp 17665c5659d0SMark Brown * together. */ 17675c5659d0SMark Brown trace_regulator_enable_delay(rdev_get_name(rdev)); 17685c5659d0SMark Brown 17695df529d4SThierry Reding /* 17705df529d4SThierry Reding * Delay for the requested amount of time as per the guidelines in: 17715df529d4SThierry Reding * 17725df529d4SThierry Reding * Documentation/timers/timers-howto.txt 17735df529d4SThierry Reding * 17745df529d4SThierry Reding * The assumption here is that regulators will never be enabled in 17755df529d4SThierry Reding * atomic context and therefore sleeping functions can be used. 17765df529d4SThierry Reding */ 17775df529d4SThierry Reding if (delay) { 17785df529d4SThierry Reding unsigned int ms = delay / 1000; 17795df529d4SThierry Reding unsigned int us = delay % 1000; 17805df529d4SThierry Reding 17815df529d4SThierry Reding if (ms > 0) { 17825df529d4SThierry Reding /* 17835df529d4SThierry Reding * For small enough values, handle super-millisecond 17845df529d4SThierry Reding * delays in the usleep_range() call below. 17855df529d4SThierry Reding */ 17865df529d4SThierry Reding if (ms < 20) 17875df529d4SThierry Reding us += ms * 1000; 17885df529d4SThierry Reding else 17895df529d4SThierry Reding msleep(ms); 17905df529d4SThierry Reding } 17915df529d4SThierry Reding 17925df529d4SThierry Reding /* 17935df529d4SThierry Reding * Give the scheduler some room to coalesce with any other 17945df529d4SThierry Reding * wakeup sources. For delays shorter than 10 us, don't even 17955df529d4SThierry Reding * bother setting up high-resolution timers and just busy- 17965df529d4SThierry Reding * loop. 17975df529d4SThierry Reding */ 17985df529d4SThierry Reding if (us >= 10) 17995df529d4SThierry Reding usleep_range(us, us + 100); 18005df529d4SThierry Reding else 18015df529d4SThierry Reding udelay(us); 18025c5659d0SMark Brown } 18035c5659d0SMark Brown 18045c5659d0SMark Brown trace_regulator_enable_complete(rdev_get_name(rdev)); 18055c5659d0SMark Brown 18065c5659d0SMark Brown return 0; 18075c5659d0SMark Brown } 18085c5659d0SMark Brown 1809414c70cbSLiam Girdwood /* locks held by regulator_enable() */ 1810414c70cbSLiam Girdwood static int _regulator_enable(struct regulator_dev *rdev) 1811414c70cbSLiam Girdwood { 18125c5659d0SMark Brown int ret; 1813414c70cbSLiam Girdwood 1814414c70cbSLiam Girdwood /* check voltage and requested load before enabling */ 1815414c70cbSLiam Girdwood if (rdev->constraints && 18169a2372faSMark Brown (rdev->constraints->valid_ops_mask & REGULATOR_CHANGE_DRMS)) 1817414c70cbSLiam Girdwood drms_uA_update(rdev); 1818414c70cbSLiam Girdwood 18199a2372faSMark Brown if (rdev->use_count == 0) { 18209a2372faSMark Brown /* The regulator may on if it's not switchable or left on */ 18219a2372faSMark Brown ret = _regulator_is_enabled(rdev); 18229a2372faSMark Brown if (ret == -EINVAL || ret == 0) { 18239a2372faSMark Brown if (!_regulator_can_change_status(rdev)) 18249a2372faSMark Brown return -EPERM; 18259a2372faSMark Brown 18265c5659d0SMark Brown ret = _regulator_do_enable(rdev); 18279a2372faSMark Brown if (ret < 0) 18289a2372faSMark Brown return ret; 182931aae2beSMark Brown 1830a7433cffSLinus Walleij } else if (ret < 0) { 18315da84fd9SJoe Perches rdev_err(rdev, "is_enabled() failed: %d\n", ret); 1832414c70cbSLiam Girdwood return ret; 1833414c70cbSLiam Girdwood } 1834a7433cffSLinus Walleij /* Fallthrough on positive return values - already enabled */ 1835414c70cbSLiam Girdwood } 1836414c70cbSLiam Girdwood 18379a2372faSMark Brown rdev->use_count++; 18389a2372faSMark Brown 18399a2372faSMark Brown return 0; 1840414c70cbSLiam Girdwood } 1841414c70cbSLiam Girdwood 1842414c70cbSLiam Girdwood /** 1843414c70cbSLiam Girdwood * regulator_enable - enable regulator output 1844414c70cbSLiam Girdwood * @regulator: regulator source 1845414c70cbSLiam Girdwood * 1846cf7bbcdfSMark Brown * Request that the regulator be enabled with the regulator output at 1847cf7bbcdfSMark Brown * the predefined voltage or current value. Calls to regulator_enable() 1848cf7bbcdfSMark Brown * must be balanced with calls to regulator_disable(). 1849cf7bbcdfSMark Brown * 1850414c70cbSLiam Girdwood * NOTE: the output value can be set by other drivers, boot loader or may be 1851cf7bbcdfSMark Brown * hardwired in the regulator. 1852414c70cbSLiam Girdwood */ 1853414c70cbSLiam Girdwood int regulator_enable(struct regulator *regulator) 1854414c70cbSLiam Girdwood { 1855412aec61SDavid Brownell struct regulator_dev *rdev = regulator->rdev; 1856412aec61SDavid Brownell int ret = 0; 1857414c70cbSLiam Girdwood 18586492bc1bSMark Brown if (regulator->always_on) 18596492bc1bSMark Brown return 0; 18606492bc1bSMark Brown 18613801b86aSMark Brown if (rdev->supply) { 18623801b86aSMark Brown ret = regulator_enable(rdev->supply); 18633801b86aSMark Brown if (ret != 0) 18643801b86aSMark Brown return ret; 18653801b86aSMark Brown } 18663801b86aSMark Brown 1867412aec61SDavid Brownell mutex_lock(&rdev->mutex); 1868412aec61SDavid Brownell ret = _regulator_enable(rdev); 1869412aec61SDavid Brownell mutex_unlock(&rdev->mutex); 18703801b86aSMark Brown 1871d1685e4eSHeiko Stübner if (ret != 0 && rdev->supply) 18723801b86aSMark Brown regulator_disable(rdev->supply); 18733801b86aSMark Brown 1874414c70cbSLiam Girdwood return ret; 1875414c70cbSLiam Girdwood } 1876414c70cbSLiam Girdwood EXPORT_SYMBOL_GPL(regulator_enable); 1877414c70cbSLiam Girdwood 18785c5659d0SMark Brown static int _regulator_do_disable(struct regulator_dev *rdev) 18795c5659d0SMark Brown { 18805c5659d0SMark Brown int ret; 18815c5659d0SMark Brown 18825c5659d0SMark Brown trace_regulator_disable(rdev_get_name(rdev)); 18835c5659d0SMark Brown 1884967cfb18SKim, Milo if (rdev->ena_pin) { 1885967cfb18SKim, Milo ret = regulator_ena_gpio_ctrl(rdev, false); 1886967cfb18SKim, Milo if (ret < 0) 1887967cfb18SKim, Milo return ret; 18885c5659d0SMark Brown rdev->ena_gpio_state = 0; 18895c5659d0SMark Brown 18905c5659d0SMark Brown } else if (rdev->desc->ops->disable) { 18915c5659d0SMark Brown ret = rdev->desc->ops->disable(rdev); 18925c5659d0SMark Brown if (ret != 0) 18935c5659d0SMark Brown return ret; 18945c5659d0SMark Brown } 18955c5659d0SMark Brown 18965c5659d0SMark Brown trace_regulator_disable_complete(rdev_get_name(rdev)); 18975c5659d0SMark Brown 18985c5659d0SMark Brown _notifier_call_chain(rdev, REGULATOR_EVENT_DISABLE, 18995c5659d0SMark Brown NULL); 19005c5659d0SMark Brown return 0; 19015c5659d0SMark Brown } 19025c5659d0SMark Brown 1903414c70cbSLiam Girdwood /* locks held by regulator_disable() */ 19043801b86aSMark Brown static int _regulator_disable(struct regulator_dev *rdev) 1905414c70cbSLiam Girdwood { 1906414c70cbSLiam Girdwood int ret = 0; 1907414c70cbSLiam Girdwood 1908cd94b505SDavid Brownell if (WARN(rdev->use_count <= 0, 190943e7ee33SJoe Perches "unbalanced disables for %s\n", rdev_get_name(rdev))) 1910cd94b505SDavid Brownell return -EIO; 1911cd94b505SDavid Brownell 1912414c70cbSLiam Girdwood /* are we the last user and permitted to disable ? */ 191360ef66fcSMark Brown if (rdev->use_count == 1 && 191460ef66fcSMark Brown (rdev->constraints && !rdev->constraints->always_on)) { 1915414c70cbSLiam Girdwood 1916414c70cbSLiam Girdwood /* we are last user */ 19175c5659d0SMark Brown if (_regulator_can_change_status(rdev)) { 19185c5659d0SMark Brown ret = _regulator_do_disable(rdev); 1919414c70cbSLiam Girdwood if (ret < 0) { 19205da84fd9SJoe Perches rdev_err(rdev, "failed to disable\n"); 1921414c70cbSLiam Girdwood return ret; 1922414c70cbSLiam Girdwood } 1923414c70cbSLiam Girdwood } 1924414c70cbSLiam Girdwood 1925414c70cbSLiam Girdwood rdev->use_count = 0; 1926414c70cbSLiam Girdwood } else if (rdev->use_count > 1) { 1927414c70cbSLiam Girdwood 1928414c70cbSLiam Girdwood if (rdev->constraints && 1929414c70cbSLiam Girdwood (rdev->constraints->valid_ops_mask & 1930414c70cbSLiam Girdwood REGULATOR_CHANGE_DRMS)) 1931414c70cbSLiam Girdwood drms_uA_update(rdev); 1932414c70cbSLiam Girdwood 1933414c70cbSLiam Girdwood rdev->use_count--; 1934414c70cbSLiam Girdwood } 19353801b86aSMark Brown 1936414c70cbSLiam Girdwood return ret; 1937414c70cbSLiam Girdwood } 1938414c70cbSLiam Girdwood 1939414c70cbSLiam Girdwood /** 1940414c70cbSLiam Girdwood * regulator_disable - disable regulator output 1941414c70cbSLiam Girdwood * @regulator: regulator source 1942414c70cbSLiam Girdwood * 1943cf7bbcdfSMark Brown * Disable the regulator output voltage or current. Calls to 1944cf7bbcdfSMark Brown * regulator_enable() must be balanced with calls to 1945cf7bbcdfSMark Brown * regulator_disable(). 194669279fb9SMark Brown * 1947414c70cbSLiam Girdwood * NOTE: this will only disable the regulator output if no other consumer 1948cf7bbcdfSMark Brown * devices have it enabled, the regulator device supports disabling and 1949cf7bbcdfSMark Brown * machine constraints permit this operation. 1950414c70cbSLiam Girdwood */ 1951414c70cbSLiam Girdwood int regulator_disable(struct regulator *regulator) 1952414c70cbSLiam Girdwood { 1953412aec61SDavid Brownell struct regulator_dev *rdev = regulator->rdev; 1954412aec61SDavid Brownell int ret = 0; 1955414c70cbSLiam Girdwood 19566492bc1bSMark Brown if (regulator->always_on) 19576492bc1bSMark Brown return 0; 19586492bc1bSMark Brown 1959412aec61SDavid Brownell mutex_lock(&rdev->mutex); 19603801b86aSMark Brown ret = _regulator_disable(rdev); 1961412aec61SDavid Brownell mutex_unlock(&rdev->mutex); 19628cbf811dSJeffrey Carlyle 19633801b86aSMark Brown if (ret == 0 && rdev->supply) 19643801b86aSMark Brown regulator_disable(rdev->supply); 19658cbf811dSJeffrey Carlyle 1966414c70cbSLiam Girdwood return ret; 1967414c70cbSLiam Girdwood } 1968414c70cbSLiam Girdwood EXPORT_SYMBOL_GPL(regulator_disable); 1969414c70cbSLiam Girdwood 1970414c70cbSLiam Girdwood /* locks held by regulator_force_disable() */ 19713801b86aSMark Brown static int _regulator_force_disable(struct regulator_dev *rdev) 1972414c70cbSLiam Girdwood { 1973414c70cbSLiam Girdwood int ret = 0; 1974414c70cbSLiam Girdwood 1975414c70cbSLiam Girdwood /* force disable */ 1976414c70cbSLiam Girdwood if (rdev->desc->ops->disable) { 1977414c70cbSLiam Girdwood /* ah well, who wants to live forever... */ 1978414c70cbSLiam Girdwood ret = rdev->desc->ops->disable(rdev); 1979414c70cbSLiam Girdwood if (ret < 0) { 19805da84fd9SJoe Perches rdev_err(rdev, "failed to force disable\n"); 1981414c70cbSLiam Girdwood return ret; 1982414c70cbSLiam Girdwood } 1983414c70cbSLiam Girdwood /* notify other consumers that power has been forced off */ 198484b68263SMark Brown _notifier_call_chain(rdev, REGULATOR_EVENT_FORCE_DISABLE | 198584b68263SMark Brown REGULATOR_EVENT_DISABLE, NULL); 1986414c70cbSLiam Girdwood } 1987414c70cbSLiam Girdwood 1988414c70cbSLiam Girdwood return ret; 1989414c70cbSLiam Girdwood } 1990414c70cbSLiam Girdwood 1991414c70cbSLiam Girdwood /** 1992414c70cbSLiam Girdwood * regulator_force_disable - force disable regulator output 1993414c70cbSLiam Girdwood * @regulator: regulator source 1994414c70cbSLiam Girdwood * 1995414c70cbSLiam Girdwood * Forcibly disable the regulator output voltage or current. 1996414c70cbSLiam Girdwood * NOTE: this *will* disable the regulator output even if other consumer 1997414c70cbSLiam Girdwood * devices have it enabled. This should be used for situations when device 1998414c70cbSLiam Girdwood * damage will likely occur if the regulator is not disabled (e.g. over temp). 1999414c70cbSLiam Girdwood */ 2000414c70cbSLiam Girdwood int regulator_force_disable(struct regulator *regulator) 2001414c70cbSLiam Girdwood { 200282d15839SMark Brown struct regulator_dev *rdev = regulator->rdev; 2003414c70cbSLiam Girdwood int ret; 2004414c70cbSLiam Girdwood 200582d15839SMark Brown mutex_lock(&rdev->mutex); 2006414c70cbSLiam Girdwood regulator->uA_load = 0; 20073801b86aSMark Brown ret = _regulator_force_disable(regulator->rdev); 200882d15839SMark Brown mutex_unlock(&rdev->mutex); 20098cbf811dSJeffrey Carlyle 20103801b86aSMark Brown if (rdev->supply) 20113801b86aSMark Brown while (rdev->open_count--) 20123801b86aSMark Brown regulator_disable(rdev->supply); 20138cbf811dSJeffrey Carlyle 2014414c70cbSLiam Girdwood return ret; 2015414c70cbSLiam Girdwood } 2016414c70cbSLiam Girdwood EXPORT_SYMBOL_GPL(regulator_force_disable); 2017414c70cbSLiam Girdwood 2018da07ecd9SMark Brown static void regulator_disable_work(struct work_struct *work) 2019da07ecd9SMark Brown { 2020da07ecd9SMark Brown struct regulator_dev *rdev = container_of(work, struct regulator_dev, 2021da07ecd9SMark Brown disable_work.work); 2022da07ecd9SMark Brown int count, i, ret; 2023da07ecd9SMark Brown 2024da07ecd9SMark Brown mutex_lock(&rdev->mutex); 2025da07ecd9SMark Brown 2026da07ecd9SMark Brown BUG_ON(!rdev->deferred_disables); 2027da07ecd9SMark Brown 2028da07ecd9SMark Brown count = rdev->deferred_disables; 2029da07ecd9SMark Brown rdev->deferred_disables = 0; 2030da07ecd9SMark Brown 2031da07ecd9SMark Brown for (i = 0; i < count; i++) { 2032da07ecd9SMark Brown ret = _regulator_disable(rdev); 2033da07ecd9SMark Brown if (ret != 0) 2034da07ecd9SMark Brown rdev_err(rdev, "Deferred disable failed: %d\n", ret); 2035da07ecd9SMark Brown } 2036da07ecd9SMark Brown 2037da07ecd9SMark Brown mutex_unlock(&rdev->mutex); 2038da07ecd9SMark Brown 2039da07ecd9SMark Brown if (rdev->supply) { 2040da07ecd9SMark Brown for (i = 0; i < count; i++) { 2041da07ecd9SMark Brown ret = regulator_disable(rdev->supply); 2042da07ecd9SMark Brown if (ret != 0) { 2043da07ecd9SMark Brown rdev_err(rdev, 2044da07ecd9SMark Brown "Supply disable failed: %d\n", ret); 2045da07ecd9SMark Brown } 2046da07ecd9SMark Brown } 2047da07ecd9SMark Brown } 2048da07ecd9SMark Brown } 2049da07ecd9SMark Brown 2050da07ecd9SMark Brown /** 2051da07ecd9SMark Brown * regulator_disable_deferred - disable regulator output with delay 2052da07ecd9SMark Brown * @regulator: regulator source 2053da07ecd9SMark Brown * @ms: miliseconds until the regulator is disabled 2054da07ecd9SMark Brown * 2055da07ecd9SMark Brown * Execute regulator_disable() on the regulator after a delay. This 2056da07ecd9SMark Brown * is intended for use with devices that require some time to quiesce. 2057da07ecd9SMark Brown * 2058da07ecd9SMark Brown * NOTE: this will only disable the regulator output if no other consumer 2059da07ecd9SMark Brown * devices have it enabled, the regulator device supports disabling and 2060da07ecd9SMark Brown * machine constraints permit this operation. 2061da07ecd9SMark Brown */ 2062da07ecd9SMark Brown int regulator_disable_deferred(struct regulator *regulator, int ms) 2063da07ecd9SMark Brown { 2064da07ecd9SMark Brown struct regulator_dev *rdev = regulator->rdev; 2065aa59802dSMark Brown int ret; 2066da07ecd9SMark Brown 20676492bc1bSMark Brown if (regulator->always_on) 20686492bc1bSMark Brown return 0; 20696492bc1bSMark Brown 20702b5a24a0SMark Brown if (!ms) 20712b5a24a0SMark Brown return regulator_disable(regulator); 20722b5a24a0SMark Brown 2073da07ecd9SMark Brown mutex_lock(&rdev->mutex); 2074da07ecd9SMark Brown rdev->deferred_disables++; 2075da07ecd9SMark Brown mutex_unlock(&rdev->mutex); 2076da07ecd9SMark Brown 2077070260f0SMark Brown ret = queue_delayed_work(system_power_efficient_wq, 2078070260f0SMark Brown &rdev->disable_work, 2079da07ecd9SMark Brown msecs_to_jiffies(ms)); 2080aa59802dSMark Brown if (ret < 0) 2081aa59802dSMark Brown return ret; 2082aa59802dSMark Brown else 2083aa59802dSMark Brown return 0; 2084da07ecd9SMark Brown } 2085da07ecd9SMark Brown EXPORT_SYMBOL_GPL(regulator_disable_deferred); 2086da07ecd9SMark Brown 2087414c70cbSLiam Girdwood static int _regulator_is_enabled(struct regulator_dev *rdev) 2088414c70cbSLiam Girdwood { 208965f73508SMark Brown /* A GPIO control always takes precedence */ 20907b74d149SKim, Milo if (rdev->ena_pin) 209165f73508SMark Brown return rdev->ena_gpio_state; 209265f73508SMark Brown 20939a7f6a4cSMark Brown /* If we don't know then assume that the regulator is always on */ 20949332546fSMark Brown if (!rdev->desc->ops->is_enabled) 20959a7f6a4cSMark Brown return 1; 2096414c70cbSLiam Girdwood 20979332546fSMark Brown return rdev->desc->ops->is_enabled(rdev); 2098414c70cbSLiam Girdwood } 2099414c70cbSLiam Girdwood 2100414c70cbSLiam Girdwood /** 2101414c70cbSLiam Girdwood * regulator_is_enabled - is the regulator output enabled 2102414c70cbSLiam Girdwood * @regulator: regulator source 2103414c70cbSLiam Girdwood * 2104412aec61SDavid Brownell * Returns positive if the regulator driver backing the source/client 2105412aec61SDavid Brownell * has requested that the device be enabled, zero if it hasn't, else a 2106412aec61SDavid Brownell * negative errno code. 2107412aec61SDavid Brownell * 2108412aec61SDavid Brownell * Note that the device backing this regulator handle can have multiple 2109412aec61SDavid Brownell * users, so it might be enabled even if regulator_enable() was never 2110412aec61SDavid Brownell * called for this particular source. 2111414c70cbSLiam Girdwood */ 2112414c70cbSLiam Girdwood int regulator_is_enabled(struct regulator *regulator) 2113414c70cbSLiam Girdwood { 21149332546fSMark Brown int ret; 21159332546fSMark Brown 21166492bc1bSMark Brown if (regulator->always_on) 21176492bc1bSMark Brown return 1; 21186492bc1bSMark Brown 21199332546fSMark Brown mutex_lock(®ulator->rdev->mutex); 21209332546fSMark Brown ret = _regulator_is_enabled(regulator->rdev); 21219332546fSMark Brown mutex_unlock(®ulator->rdev->mutex); 21229332546fSMark Brown 21239332546fSMark Brown return ret; 2124414c70cbSLiam Girdwood } 2125414c70cbSLiam Girdwood EXPORT_SYMBOL_GPL(regulator_is_enabled); 2126414c70cbSLiam Girdwood 2127414c70cbSLiam Girdwood /** 2128d1e7de30SMarek Szyprowski * regulator_can_change_voltage - check if regulator can change voltage 2129d1e7de30SMarek Szyprowski * @regulator: regulator source 2130d1e7de30SMarek Szyprowski * 2131d1e7de30SMarek Szyprowski * Returns positive if the regulator driver backing the source/client 2132d1e7de30SMarek Szyprowski * can change its voltage, false otherwise. Usefull for detecting fixed 2133d1e7de30SMarek Szyprowski * or dummy regulators and disabling voltage change logic in the client 2134d1e7de30SMarek Szyprowski * driver. 2135d1e7de30SMarek Szyprowski */ 2136d1e7de30SMarek Szyprowski int regulator_can_change_voltage(struct regulator *regulator) 2137d1e7de30SMarek Szyprowski { 2138d1e7de30SMarek Szyprowski struct regulator_dev *rdev = regulator->rdev; 2139d1e7de30SMarek Szyprowski 2140d1e7de30SMarek Szyprowski if (rdev->constraints && 214119280e40SAxel Lin (rdev->constraints->valid_ops_mask & REGULATOR_CHANGE_VOLTAGE)) { 214219280e40SAxel Lin if (rdev->desc->n_voltages - rdev->desc->linear_min_sel > 1) 2143d1e7de30SMarek Szyprowski return 1; 2144d1e7de30SMarek Szyprowski 214519280e40SAxel Lin if (rdev->desc->continuous_voltage_range && 214619280e40SAxel Lin rdev->constraints->min_uV && rdev->constraints->max_uV && 214719280e40SAxel Lin rdev->constraints->min_uV != rdev->constraints->max_uV) 214819280e40SAxel Lin return 1; 214919280e40SAxel Lin } 215019280e40SAxel Lin 2151d1e7de30SMarek Szyprowski return 0; 2152d1e7de30SMarek Szyprowski } 2153d1e7de30SMarek Szyprowski EXPORT_SYMBOL_GPL(regulator_can_change_voltage); 2154d1e7de30SMarek Szyprowski 2155d1e7de30SMarek Szyprowski /** 21564367cfdcSDavid Brownell * regulator_count_voltages - count regulator_list_voltage() selectors 21574367cfdcSDavid Brownell * @regulator: regulator source 21584367cfdcSDavid Brownell * 21594367cfdcSDavid Brownell * Returns number of selectors, or negative errno. Selectors are 21604367cfdcSDavid Brownell * numbered starting at zero, and typically correspond to bitfields 21614367cfdcSDavid Brownell * in hardware registers. 21624367cfdcSDavid Brownell */ 21634367cfdcSDavid Brownell int regulator_count_voltages(struct regulator *regulator) 21644367cfdcSDavid Brownell { 21654367cfdcSDavid Brownell struct regulator_dev *rdev = regulator->rdev; 21664367cfdcSDavid Brownell 21674367cfdcSDavid Brownell return rdev->desc->n_voltages ? : -EINVAL; 21684367cfdcSDavid Brownell } 21694367cfdcSDavid Brownell EXPORT_SYMBOL_GPL(regulator_count_voltages); 21704367cfdcSDavid Brownell 21714367cfdcSDavid Brownell /** 21724367cfdcSDavid Brownell * regulator_list_voltage - enumerate supported voltages 21734367cfdcSDavid Brownell * @regulator: regulator source 21744367cfdcSDavid Brownell * @selector: identify voltage to list 21754367cfdcSDavid Brownell * Context: can sleep 21764367cfdcSDavid Brownell * 21774367cfdcSDavid Brownell * Returns a voltage that can be passed to @regulator_set_voltage(), 217888393161SThomas Weber * zero if this selector code can't be used on this system, or a 21794367cfdcSDavid Brownell * negative errno. 21804367cfdcSDavid Brownell */ 21814367cfdcSDavid Brownell int regulator_list_voltage(struct regulator *regulator, unsigned selector) 21824367cfdcSDavid Brownell { 21834367cfdcSDavid Brownell struct regulator_dev *rdev = regulator->rdev; 21844367cfdcSDavid Brownell struct regulator_ops *ops = rdev->desc->ops; 21854367cfdcSDavid Brownell int ret; 21864367cfdcSDavid Brownell 2187f446043fSGuennadi Liakhovetski if (rdev->desc->fixed_uV && rdev->desc->n_voltages == 1 && !selector) 2188f446043fSGuennadi Liakhovetski return rdev->desc->fixed_uV; 2189f446043fSGuennadi Liakhovetski 21904367cfdcSDavid Brownell if (!ops->list_voltage || selector >= rdev->desc->n_voltages) 21914367cfdcSDavid Brownell return -EINVAL; 21924367cfdcSDavid Brownell 21934367cfdcSDavid Brownell mutex_lock(&rdev->mutex); 21944367cfdcSDavid Brownell ret = ops->list_voltage(rdev, selector); 21954367cfdcSDavid Brownell mutex_unlock(&rdev->mutex); 21964367cfdcSDavid Brownell 21974367cfdcSDavid Brownell if (ret > 0) { 21984367cfdcSDavid Brownell if (ret < rdev->constraints->min_uV) 21994367cfdcSDavid Brownell ret = 0; 22004367cfdcSDavid Brownell else if (ret > rdev->constraints->max_uV) 22014367cfdcSDavid Brownell ret = 0; 22024367cfdcSDavid Brownell } 22034367cfdcSDavid Brownell 22044367cfdcSDavid Brownell return ret; 22054367cfdcSDavid Brownell } 22064367cfdcSDavid Brownell EXPORT_SYMBOL_GPL(regulator_list_voltage); 22074367cfdcSDavid Brownell 22084367cfdcSDavid Brownell /** 22092a668a8bSPaul Walmsley * regulator_get_linear_step - return the voltage step size between VSEL values 22102a668a8bSPaul Walmsley * @regulator: regulator source 22112a668a8bSPaul Walmsley * 22122a668a8bSPaul Walmsley * Returns the voltage step size between VSEL values for linear 22132a668a8bSPaul Walmsley * regulators, or return 0 if the regulator isn't a linear regulator. 22142a668a8bSPaul Walmsley */ 22152a668a8bSPaul Walmsley unsigned int regulator_get_linear_step(struct regulator *regulator) 22162a668a8bSPaul Walmsley { 22172a668a8bSPaul Walmsley struct regulator_dev *rdev = regulator->rdev; 22182a668a8bSPaul Walmsley 22192a668a8bSPaul Walmsley return rdev->desc->uV_step; 22202a668a8bSPaul Walmsley } 22212a668a8bSPaul Walmsley EXPORT_SYMBOL_GPL(regulator_get_linear_step); 22222a668a8bSPaul Walmsley 22232a668a8bSPaul Walmsley /** 2224a7a1ad90SMark Brown * regulator_is_supported_voltage - check if a voltage range can be supported 2225a7a1ad90SMark Brown * 2226a7a1ad90SMark Brown * @regulator: Regulator to check. 2227a7a1ad90SMark Brown * @min_uV: Minimum required voltage in uV. 2228a7a1ad90SMark Brown * @max_uV: Maximum required voltage in uV. 2229a7a1ad90SMark Brown * 2230a7a1ad90SMark Brown * Returns a boolean or a negative error code. 2231a7a1ad90SMark Brown */ 2232a7a1ad90SMark Brown int regulator_is_supported_voltage(struct regulator *regulator, 2233a7a1ad90SMark Brown int min_uV, int max_uV) 2234a7a1ad90SMark Brown { 2235c5f3939bSMark Brown struct regulator_dev *rdev = regulator->rdev; 2236a7a1ad90SMark Brown int i, voltages, ret; 2237a7a1ad90SMark Brown 2238c5f3939bSMark Brown /* If we can't change voltage check the current voltage */ 2239c5f3939bSMark Brown if (!(rdev->constraints->valid_ops_mask & REGULATOR_CHANGE_VOLTAGE)) { 2240c5f3939bSMark Brown ret = regulator_get_voltage(regulator); 2241c5f3939bSMark Brown if (ret >= 0) 2242f0f98b19SMarek Szyprowski return (min_uV <= ret && ret <= max_uV); 2243c5f3939bSMark Brown else 2244c5f3939bSMark Brown return ret; 2245c5f3939bSMark Brown } 2246c5f3939bSMark Brown 2247bd7a2b60SPawel Moll /* Any voltage within constrains range is fine? */ 2248bd7a2b60SPawel Moll if (rdev->desc->continuous_voltage_range) 2249bd7a2b60SPawel Moll return min_uV >= rdev->constraints->min_uV && 2250bd7a2b60SPawel Moll max_uV <= rdev->constraints->max_uV; 2251bd7a2b60SPawel Moll 2252a7a1ad90SMark Brown ret = regulator_count_voltages(regulator); 2253a7a1ad90SMark Brown if (ret < 0) 2254a7a1ad90SMark Brown return ret; 2255a7a1ad90SMark Brown voltages = ret; 2256a7a1ad90SMark Brown 2257a7a1ad90SMark Brown for (i = 0; i < voltages; i++) { 2258a7a1ad90SMark Brown ret = regulator_list_voltage(regulator, i); 2259a7a1ad90SMark Brown 2260a7a1ad90SMark Brown if (ret >= min_uV && ret <= max_uV) 2261a7a1ad90SMark Brown return 1; 2262a7a1ad90SMark Brown } 2263a7a1ad90SMark Brown 2264a7a1ad90SMark Brown return 0; 2265a7a1ad90SMark Brown } 2266a398eaa2SMark Brown EXPORT_SYMBOL_GPL(regulator_is_supported_voltage); 2267a7a1ad90SMark Brown 226875790251SMark Brown static int _regulator_do_set_voltage(struct regulator_dev *rdev, 226975790251SMark Brown int min_uV, int max_uV) 227075790251SMark Brown { 227175790251SMark Brown int ret; 227277af1b26SLinus Walleij int delay = 0; 2273e113d792SMark Brown int best_val = 0; 227475790251SMark Brown unsigned int selector; 2275eba41a5eSAxel Lin int old_selector = -1; 227675790251SMark Brown 227775790251SMark Brown trace_regulator_set_voltage(rdev_get_name(rdev), min_uV, max_uV); 227875790251SMark Brown 2279bf5892a8SMark Brown min_uV += rdev->constraints->uV_offset; 2280bf5892a8SMark Brown max_uV += rdev->constraints->uV_offset; 2281bf5892a8SMark Brown 228277af1b26SLinus Walleij /* 228377af1b26SLinus Walleij * If we can't obtain the old selector there is not enough 228477af1b26SLinus Walleij * info to call set_voltage_time_sel(). 228577af1b26SLinus Walleij */ 22868b7485efSAxel Lin if (_regulator_is_enabled(rdev) && 22878b7485efSAxel Lin rdev->desc->ops->set_voltage_time_sel && 228877af1b26SLinus Walleij rdev->desc->ops->get_voltage_sel) { 2289eba41a5eSAxel Lin old_selector = rdev->desc->ops->get_voltage_sel(rdev); 2290eba41a5eSAxel Lin if (old_selector < 0) 2291eba41a5eSAxel Lin return old_selector; 2292eba41a5eSAxel Lin } 229377af1b26SLinus Walleij 229475790251SMark Brown if (rdev->desc->ops->set_voltage) { 229575790251SMark Brown ret = rdev->desc->ops->set_voltage(rdev, min_uV, max_uV, 229675790251SMark Brown &selector); 2297e113d792SMark Brown 2298e113d792SMark Brown if (ret >= 0) { 2299e113d792SMark Brown if (rdev->desc->ops->list_voltage) 2300e113d792SMark Brown best_val = rdev->desc->ops->list_voltage(rdev, 2301e113d792SMark Brown selector); 2302e113d792SMark Brown else 2303e113d792SMark Brown best_val = _regulator_get_voltage(rdev); 2304e113d792SMark Brown } 2305e113d792SMark Brown 2306e8eef82bSMark Brown } else if (rdev->desc->ops->set_voltage_sel) { 23079152c36aSAxel Lin if (rdev->desc->ops->map_voltage) { 2308e843fc46SMark Brown ret = rdev->desc->ops->map_voltage(rdev, min_uV, 2309e843fc46SMark Brown max_uV); 23109152c36aSAxel Lin } else { 23119152c36aSAxel Lin if (rdev->desc->ops->list_voltage == 23129152c36aSAxel Lin regulator_list_voltage_linear) 23139152c36aSAxel Lin ret = regulator_map_voltage_linear(rdev, 23149152c36aSAxel Lin min_uV, max_uV); 231507351233SAxel Lin else 23169152c36aSAxel Lin ret = regulator_map_voltage_iterate(rdev, 23179152c36aSAxel Lin min_uV, max_uV); 23189152c36aSAxel Lin } 2319e843fc46SMark Brown 2320e843fc46SMark Brown if (ret >= 0) { 2321e113d792SMark Brown best_val = rdev->desc->ops->list_voltage(rdev, ret); 2322e113d792SMark Brown if (min_uV <= best_val && max_uV >= best_val) { 2323e843fc46SMark Brown selector = ret; 2324c66a566aSAxel Lin if (old_selector == selector) 2325c66a566aSAxel Lin ret = 0; 2326c66a566aSAxel Lin else 2327c66a566aSAxel Lin ret = rdev->desc->ops->set_voltage_sel( 2328c66a566aSAxel Lin rdev, ret); 2329e113d792SMark Brown } else { 2330e113d792SMark Brown ret = -EINVAL; 2331e113d792SMark Brown } 2332e843fc46SMark Brown } 2333e8eef82bSMark Brown } else { 2334e8eef82bSMark Brown ret = -EINVAL; 2335e8eef82bSMark Brown } 2336e8eef82bSMark Brown 2337eba41a5eSAxel Lin /* Call set_voltage_time_sel if successfully obtained old_selector */ 23385b175952SYadwinder Singh Brar if (ret == 0 && !rdev->constraints->ramp_disable && old_selector >= 0 23395b175952SYadwinder Singh Brar && old_selector != selector) { 2340eba41a5eSAxel Lin 2341eba41a5eSAxel Lin delay = rdev->desc->ops->set_voltage_time_sel(rdev, 2342eba41a5eSAxel Lin old_selector, selector); 2343eba41a5eSAxel Lin if (delay < 0) { 2344eba41a5eSAxel Lin rdev_warn(rdev, "set_voltage_time_sel() failed: %d\n", 2345eba41a5eSAxel Lin delay); 2346eba41a5eSAxel Lin delay = 0; 2347e8eef82bSMark Brown } 234875790251SMark Brown 234977af1b26SLinus Walleij /* Insert any necessary delays */ 235077af1b26SLinus Walleij if (delay >= 1000) { 235177af1b26SLinus Walleij mdelay(delay / 1000); 235277af1b26SLinus Walleij udelay(delay % 1000); 235377af1b26SLinus Walleij } else if (delay) { 235477af1b26SLinus Walleij udelay(delay); 235577af1b26SLinus Walleij } 23568b96de31SPhilip Rakity } 235777af1b26SLinus Walleij 23582f6c797fSAxel Lin if (ret == 0 && best_val >= 0) { 23592f6c797fSAxel Lin unsigned long data = best_val; 23602f6c797fSAxel Lin 2361ded06a52SMark Brown _notifier_call_chain(rdev, REGULATOR_EVENT_VOLTAGE_CHANGE, 23622f6c797fSAxel Lin (void *)data); 23632f6c797fSAxel Lin } 2364ded06a52SMark Brown 2365eba41a5eSAxel Lin trace_regulator_set_voltage_complete(rdev_get_name(rdev), best_val); 236675790251SMark Brown 236775790251SMark Brown return ret; 236875790251SMark Brown } 236975790251SMark Brown 2370a7a1ad90SMark Brown /** 2371414c70cbSLiam Girdwood * regulator_set_voltage - set regulator output voltage 2372414c70cbSLiam Girdwood * @regulator: regulator source 2373414c70cbSLiam Girdwood * @min_uV: Minimum required voltage in uV 2374414c70cbSLiam Girdwood * @max_uV: Maximum acceptable voltage in uV 2375414c70cbSLiam Girdwood * 2376414c70cbSLiam Girdwood * Sets a voltage regulator to the desired output voltage. This can be set 2377414c70cbSLiam Girdwood * during any regulator state. IOW, regulator can be disabled or enabled. 2378414c70cbSLiam Girdwood * 2379414c70cbSLiam Girdwood * If the regulator is enabled then the voltage will change to the new value 2380414c70cbSLiam Girdwood * immediately otherwise if the regulator is disabled the regulator will 2381414c70cbSLiam Girdwood * output at the new voltage when enabled. 2382414c70cbSLiam Girdwood * 2383414c70cbSLiam Girdwood * NOTE: If the regulator is shared between several devices then the lowest 2384414c70cbSLiam Girdwood * request voltage that meets the system constraints will be used. 238569279fb9SMark Brown * Regulator system constraints must be set for this regulator before 2386414c70cbSLiam Girdwood * calling this function otherwise this call will fail. 2387414c70cbSLiam Girdwood */ 2388414c70cbSLiam Girdwood int regulator_set_voltage(struct regulator *regulator, int min_uV, int max_uV) 2389414c70cbSLiam Girdwood { 2390414c70cbSLiam Girdwood struct regulator_dev *rdev = regulator->rdev; 239195a3c23aSMark Brown int ret = 0; 239292d7a558SPaolo Pisati int old_min_uV, old_max_uV; 2393414c70cbSLiam Girdwood 2394414c70cbSLiam Girdwood mutex_lock(&rdev->mutex); 2395414c70cbSLiam Girdwood 239695a3c23aSMark Brown /* If we're setting the same range as last time the change 239795a3c23aSMark Brown * should be a noop (some cpufreq implementations use the same 239895a3c23aSMark Brown * voltage for multiple frequencies, for example). 239995a3c23aSMark Brown */ 240095a3c23aSMark Brown if (regulator->min_uV == min_uV && regulator->max_uV == max_uV) 240195a3c23aSMark Brown goto out; 240295a3c23aSMark Brown 2403414c70cbSLiam Girdwood /* sanity check */ 2404e8eef82bSMark Brown if (!rdev->desc->ops->set_voltage && 2405e8eef82bSMark Brown !rdev->desc->ops->set_voltage_sel) { 2406414c70cbSLiam Girdwood ret = -EINVAL; 2407414c70cbSLiam Girdwood goto out; 2408414c70cbSLiam Girdwood } 2409414c70cbSLiam Girdwood 2410414c70cbSLiam Girdwood /* constraints check */ 2411414c70cbSLiam Girdwood ret = regulator_check_voltage(rdev, &min_uV, &max_uV); 2412414c70cbSLiam Girdwood if (ret < 0) 2413414c70cbSLiam Girdwood goto out; 241492d7a558SPaolo Pisati 241592d7a558SPaolo Pisati /* restore original values in case of error */ 241692d7a558SPaolo Pisati old_min_uV = regulator->min_uV; 241792d7a558SPaolo Pisati old_max_uV = regulator->max_uV; 2418414c70cbSLiam Girdwood regulator->min_uV = min_uV; 2419414c70cbSLiam Girdwood regulator->max_uV = max_uV; 24203a93f2a9SMark Brown 242105fda3b1SThomas Petazzoni ret = regulator_check_consumers(rdev, &min_uV, &max_uV); 242205fda3b1SThomas Petazzoni if (ret < 0) 242392d7a558SPaolo Pisati goto out2; 242405fda3b1SThomas Petazzoni 242575790251SMark Brown ret = _regulator_do_set_voltage(rdev, min_uV, max_uV); 242692d7a558SPaolo Pisati if (ret < 0) 242792d7a558SPaolo Pisati goto out2; 242802fa3ec0SMark Brown 2429414c70cbSLiam Girdwood out: 2430414c70cbSLiam Girdwood mutex_unlock(&rdev->mutex); 2431414c70cbSLiam Girdwood return ret; 243292d7a558SPaolo Pisati out2: 243392d7a558SPaolo Pisati regulator->min_uV = old_min_uV; 243492d7a558SPaolo Pisati regulator->max_uV = old_max_uV; 243592d7a558SPaolo Pisati mutex_unlock(&rdev->mutex); 243692d7a558SPaolo Pisati return ret; 2437414c70cbSLiam Girdwood } 2438414c70cbSLiam Girdwood EXPORT_SYMBOL_GPL(regulator_set_voltage); 2439414c70cbSLiam Girdwood 2440606a2562SMark Brown /** 244188cd222bSLinus Walleij * regulator_set_voltage_time - get raise/fall time 244288cd222bSLinus Walleij * @regulator: regulator source 244388cd222bSLinus Walleij * @old_uV: starting voltage in microvolts 244488cd222bSLinus Walleij * @new_uV: target voltage in microvolts 244588cd222bSLinus Walleij * 244688cd222bSLinus Walleij * Provided with the starting and ending voltage, this function attempts to 244788cd222bSLinus Walleij * calculate the time in microseconds required to rise or fall to this new 244888cd222bSLinus Walleij * voltage. 244988cd222bSLinus Walleij */ 245088cd222bSLinus Walleij int regulator_set_voltage_time(struct regulator *regulator, 245188cd222bSLinus Walleij int old_uV, int new_uV) 245288cd222bSLinus Walleij { 245388cd222bSLinus Walleij struct regulator_dev *rdev = regulator->rdev; 245488cd222bSLinus Walleij struct regulator_ops *ops = rdev->desc->ops; 245588cd222bSLinus Walleij int old_sel = -1; 245688cd222bSLinus Walleij int new_sel = -1; 245788cd222bSLinus Walleij int voltage; 245888cd222bSLinus Walleij int i; 245988cd222bSLinus Walleij 246088cd222bSLinus Walleij /* Currently requires operations to do this */ 246188cd222bSLinus Walleij if (!ops->list_voltage || !ops->set_voltage_time_sel 246288cd222bSLinus Walleij || !rdev->desc->n_voltages) 246388cd222bSLinus Walleij return -EINVAL; 246488cd222bSLinus Walleij 246588cd222bSLinus Walleij for (i = 0; i < rdev->desc->n_voltages; i++) { 246688cd222bSLinus Walleij /* We only look for exact voltage matches here */ 246788cd222bSLinus Walleij voltage = regulator_list_voltage(regulator, i); 246888cd222bSLinus Walleij if (voltage < 0) 246988cd222bSLinus Walleij return -EINVAL; 247088cd222bSLinus Walleij if (voltage == 0) 247188cd222bSLinus Walleij continue; 247288cd222bSLinus Walleij if (voltage == old_uV) 247388cd222bSLinus Walleij old_sel = i; 247488cd222bSLinus Walleij if (voltage == new_uV) 247588cd222bSLinus Walleij new_sel = i; 247688cd222bSLinus Walleij } 247788cd222bSLinus Walleij 247888cd222bSLinus Walleij if (old_sel < 0 || new_sel < 0) 247988cd222bSLinus Walleij return -EINVAL; 248088cd222bSLinus Walleij 248188cd222bSLinus Walleij return ops->set_voltage_time_sel(rdev, old_sel, new_sel); 248288cd222bSLinus Walleij } 248388cd222bSLinus Walleij EXPORT_SYMBOL_GPL(regulator_set_voltage_time); 248488cd222bSLinus Walleij 248588cd222bSLinus Walleij /** 248698a175b6SYadwinder Singh Brar * regulator_set_voltage_time_sel - get raise/fall time 2487296c6566SRandy Dunlap * @rdev: regulator source device 248898a175b6SYadwinder Singh Brar * @old_selector: selector for starting voltage 248998a175b6SYadwinder Singh Brar * @new_selector: selector for target voltage 249098a175b6SYadwinder Singh Brar * 249198a175b6SYadwinder Singh Brar * Provided with the starting and target voltage selectors, this function 249298a175b6SYadwinder Singh Brar * returns time in microseconds required to rise or fall to this new voltage 249398a175b6SYadwinder Singh Brar * 2494f11d08c3SAxel Lin * Drivers providing ramp_delay in regulation_constraints can use this as their 2495398715abSAxel Lin * set_voltage_time_sel() operation. 249698a175b6SYadwinder Singh Brar */ 249798a175b6SYadwinder Singh Brar int regulator_set_voltage_time_sel(struct regulator_dev *rdev, 249898a175b6SYadwinder Singh Brar unsigned int old_selector, 249998a175b6SYadwinder Singh Brar unsigned int new_selector) 250098a175b6SYadwinder Singh Brar { 2501398715abSAxel Lin unsigned int ramp_delay = 0; 2502f11d08c3SAxel Lin int old_volt, new_volt; 2503398715abSAxel Lin 25046f0b2c69SYadwinder Singh Brar if (rdev->constraints->ramp_delay) 2505398715abSAxel Lin ramp_delay = rdev->constraints->ramp_delay; 2506398715abSAxel Lin else if (rdev->desc->ramp_delay) 2507398715abSAxel Lin ramp_delay = rdev->desc->ramp_delay; 2508398715abSAxel Lin 2509398715abSAxel Lin if (ramp_delay == 0) { 25106f0b2c69SYadwinder Singh Brar rdev_warn(rdev, "ramp_delay not set\n"); 2511398715abSAxel Lin return 0; 25126f0b2c69SYadwinder Singh Brar } 2513398715abSAxel Lin 2514f11d08c3SAxel Lin /* sanity check */ 2515f11d08c3SAxel Lin if (!rdev->desc->ops->list_voltage) 2516f11d08c3SAxel Lin return -EINVAL; 2517398715abSAxel Lin 2518f11d08c3SAxel Lin old_volt = rdev->desc->ops->list_voltage(rdev, old_selector); 2519f11d08c3SAxel Lin new_volt = rdev->desc->ops->list_voltage(rdev, new_selector); 2520f11d08c3SAxel Lin 2521f11d08c3SAxel Lin return DIV_ROUND_UP(abs(new_volt - old_volt), ramp_delay); 252298a175b6SYadwinder Singh Brar } 2523b19dbf71SMark Brown EXPORT_SYMBOL_GPL(regulator_set_voltage_time_sel); 252498a175b6SYadwinder Singh Brar 252598a175b6SYadwinder Singh Brar /** 2526606a2562SMark Brown * regulator_sync_voltage - re-apply last regulator output voltage 2527606a2562SMark Brown * @regulator: regulator source 2528606a2562SMark Brown * 2529606a2562SMark Brown * Re-apply the last configured voltage. This is intended to be used 2530606a2562SMark Brown * where some external control source the consumer is cooperating with 2531606a2562SMark Brown * has caused the configured voltage to change. 2532606a2562SMark Brown */ 2533606a2562SMark Brown int regulator_sync_voltage(struct regulator *regulator) 2534606a2562SMark Brown { 2535606a2562SMark Brown struct regulator_dev *rdev = regulator->rdev; 2536606a2562SMark Brown int ret, min_uV, max_uV; 2537606a2562SMark Brown 2538606a2562SMark Brown mutex_lock(&rdev->mutex); 2539606a2562SMark Brown 2540606a2562SMark Brown if (!rdev->desc->ops->set_voltage && 2541606a2562SMark Brown !rdev->desc->ops->set_voltage_sel) { 2542606a2562SMark Brown ret = -EINVAL; 2543606a2562SMark Brown goto out; 2544606a2562SMark Brown } 2545606a2562SMark Brown 2546606a2562SMark Brown /* This is only going to work if we've had a voltage configured. */ 2547606a2562SMark Brown if (!regulator->min_uV && !regulator->max_uV) { 2548606a2562SMark Brown ret = -EINVAL; 2549606a2562SMark Brown goto out; 2550606a2562SMark Brown } 2551606a2562SMark Brown 2552606a2562SMark Brown min_uV = regulator->min_uV; 2553606a2562SMark Brown max_uV = regulator->max_uV; 2554606a2562SMark Brown 2555606a2562SMark Brown /* This should be a paranoia check... */ 2556606a2562SMark Brown ret = regulator_check_voltage(rdev, &min_uV, &max_uV); 2557606a2562SMark Brown if (ret < 0) 2558606a2562SMark Brown goto out; 2559606a2562SMark Brown 2560606a2562SMark Brown ret = regulator_check_consumers(rdev, &min_uV, &max_uV); 2561606a2562SMark Brown if (ret < 0) 2562606a2562SMark Brown goto out; 2563606a2562SMark Brown 2564606a2562SMark Brown ret = _regulator_do_set_voltage(rdev, min_uV, max_uV); 2565606a2562SMark Brown 2566606a2562SMark Brown out: 2567606a2562SMark Brown mutex_unlock(&rdev->mutex); 2568606a2562SMark Brown return ret; 2569606a2562SMark Brown } 2570606a2562SMark Brown EXPORT_SYMBOL_GPL(regulator_sync_voltage); 2571606a2562SMark Brown 2572414c70cbSLiam Girdwood static int _regulator_get_voltage(struct regulator_dev *rdev) 2573414c70cbSLiam Girdwood { 2574bf5892a8SMark Brown int sel, ret; 2575476c2d83SMark Brown 2576476c2d83SMark Brown if (rdev->desc->ops->get_voltage_sel) { 2577476c2d83SMark Brown sel = rdev->desc->ops->get_voltage_sel(rdev); 2578476c2d83SMark Brown if (sel < 0) 2579476c2d83SMark Brown return sel; 2580bf5892a8SMark Brown ret = rdev->desc->ops->list_voltage(rdev, sel); 2581cb220d16SAxel Lin } else if (rdev->desc->ops->get_voltage) { 2582bf5892a8SMark Brown ret = rdev->desc->ops->get_voltage(rdev); 2583f7df20ecSMark Brown } else if (rdev->desc->ops->list_voltage) { 2584f7df20ecSMark Brown ret = rdev->desc->ops->list_voltage(rdev, 0); 25855a523605SLaxman Dewangan } else if (rdev->desc->fixed_uV && (rdev->desc->n_voltages == 1)) { 25865a523605SLaxman Dewangan ret = rdev->desc->fixed_uV; 2587cb220d16SAxel Lin } else { 2588414c70cbSLiam Girdwood return -EINVAL; 2589cb220d16SAxel Lin } 2590bf5892a8SMark Brown 2591cb220d16SAxel Lin if (ret < 0) 2592cb220d16SAxel Lin return ret; 2593bf5892a8SMark Brown return ret - rdev->constraints->uV_offset; 2594414c70cbSLiam Girdwood } 2595414c70cbSLiam Girdwood 2596414c70cbSLiam Girdwood /** 2597414c70cbSLiam Girdwood * regulator_get_voltage - get regulator output voltage 2598414c70cbSLiam Girdwood * @regulator: regulator source 2599414c70cbSLiam Girdwood * 2600414c70cbSLiam Girdwood * This returns the current regulator voltage in uV. 2601414c70cbSLiam Girdwood * 2602414c70cbSLiam Girdwood * NOTE: If the regulator is disabled it will return the voltage value. This 2603414c70cbSLiam Girdwood * function should not be used to determine regulator state. 2604414c70cbSLiam Girdwood */ 2605414c70cbSLiam Girdwood int regulator_get_voltage(struct regulator *regulator) 2606414c70cbSLiam Girdwood { 2607414c70cbSLiam Girdwood int ret; 2608414c70cbSLiam Girdwood 2609414c70cbSLiam Girdwood mutex_lock(®ulator->rdev->mutex); 2610414c70cbSLiam Girdwood 2611414c70cbSLiam Girdwood ret = _regulator_get_voltage(regulator->rdev); 2612414c70cbSLiam Girdwood 2613414c70cbSLiam Girdwood mutex_unlock(®ulator->rdev->mutex); 2614414c70cbSLiam Girdwood 2615414c70cbSLiam Girdwood return ret; 2616414c70cbSLiam Girdwood } 2617414c70cbSLiam Girdwood EXPORT_SYMBOL_GPL(regulator_get_voltage); 2618414c70cbSLiam Girdwood 2619414c70cbSLiam Girdwood /** 2620414c70cbSLiam Girdwood * regulator_set_current_limit - set regulator output current limit 2621414c70cbSLiam Girdwood * @regulator: regulator source 2622ce0d10f8SCharles Keepax * @min_uA: Minimum supported current in uA 2623414c70cbSLiam Girdwood * @max_uA: Maximum supported current in uA 2624414c70cbSLiam Girdwood * 2625414c70cbSLiam Girdwood * Sets current sink to the desired output current. This can be set during 2626414c70cbSLiam Girdwood * any regulator state. IOW, regulator can be disabled or enabled. 2627414c70cbSLiam Girdwood * 2628414c70cbSLiam Girdwood * If the regulator is enabled then the current will change to the new value 2629414c70cbSLiam Girdwood * immediately otherwise if the regulator is disabled the regulator will 2630414c70cbSLiam Girdwood * output at the new current when enabled. 2631414c70cbSLiam Girdwood * 2632414c70cbSLiam Girdwood * NOTE: Regulator system constraints must be set for this regulator before 2633414c70cbSLiam Girdwood * calling this function otherwise this call will fail. 2634414c70cbSLiam Girdwood */ 2635414c70cbSLiam Girdwood int regulator_set_current_limit(struct regulator *regulator, 2636414c70cbSLiam Girdwood int min_uA, int max_uA) 2637414c70cbSLiam Girdwood { 2638414c70cbSLiam Girdwood struct regulator_dev *rdev = regulator->rdev; 2639414c70cbSLiam Girdwood int ret; 2640414c70cbSLiam Girdwood 2641414c70cbSLiam Girdwood mutex_lock(&rdev->mutex); 2642414c70cbSLiam Girdwood 2643414c70cbSLiam Girdwood /* sanity check */ 2644414c70cbSLiam Girdwood if (!rdev->desc->ops->set_current_limit) { 2645414c70cbSLiam Girdwood ret = -EINVAL; 2646414c70cbSLiam Girdwood goto out; 2647414c70cbSLiam Girdwood } 2648414c70cbSLiam Girdwood 2649414c70cbSLiam Girdwood /* constraints check */ 2650414c70cbSLiam Girdwood ret = regulator_check_current_limit(rdev, &min_uA, &max_uA); 2651414c70cbSLiam Girdwood if (ret < 0) 2652414c70cbSLiam Girdwood goto out; 2653414c70cbSLiam Girdwood 2654414c70cbSLiam Girdwood ret = rdev->desc->ops->set_current_limit(rdev, min_uA, max_uA); 2655414c70cbSLiam Girdwood out: 2656414c70cbSLiam Girdwood mutex_unlock(&rdev->mutex); 2657414c70cbSLiam Girdwood return ret; 2658414c70cbSLiam Girdwood } 2659414c70cbSLiam Girdwood EXPORT_SYMBOL_GPL(regulator_set_current_limit); 2660414c70cbSLiam Girdwood 2661414c70cbSLiam Girdwood static int _regulator_get_current_limit(struct regulator_dev *rdev) 2662414c70cbSLiam Girdwood { 2663414c70cbSLiam Girdwood int ret; 2664414c70cbSLiam Girdwood 2665414c70cbSLiam Girdwood mutex_lock(&rdev->mutex); 2666414c70cbSLiam Girdwood 2667414c70cbSLiam Girdwood /* sanity check */ 2668414c70cbSLiam Girdwood if (!rdev->desc->ops->get_current_limit) { 2669414c70cbSLiam Girdwood ret = -EINVAL; 2670414c70cbSLiam Girdwood goto out; 2671414c70cbSLiam Girdwood } 2672414c70cbSLiam Girdwood 2673414c70cbSLiam Girdwood ret = rdev->desc->ops->get_current_limit(rdev); 2674414c70cbSLiam Girdwood out: 2675414c70cbSLiam Girdwood mutex_unlock(&rdev->mutex); 2676414c70cbSLiam Girdwood return ret; 2677414c70cbSLiam Girdwood } 2678414c70cbSLiam Girdwood 2679414c70cbSLiam Girdwood /** 2680414c70cbSLiam Girdwood * regulator_get_current_limit - get regulator output current 2681414c70cbSLiam Girdwood * @regulator: regulator source 2682414c70cbSLiam Girdwood * 2683414c70cbSLiam Girdwood * This returns the current supplied by the specified current sink in uA. 2684414c70cbSLiam Girdwood * 2685414c70cbSLiam Girdwood * NOTE: If the regulator is disabled it will return the current value. This 2686414c70cbSLiam Girdwood * function should not be used to determine regulator state. 2687414c70cbSLiam Girdwood */ 2688414c70cbSLiam Girdwood int regulator_get_current_limit(struct regulator *regulator) 2689414c70cbSLiam Girdwood { 2690414c70cbSLiam Girdwood return _regulator_get_current_limit(regulator->rdev); 2691414c70cbSLiam Girdwood } 2692414c70cbSLiam Girdwood EXPORT_SYMBOL_GPL(regulator_get_current_limit); 2693414c70cbSLiam Girdwood 2694414c70cbSLiam Girdwood /** 2695414c70cbSLiam Girdwood * regulator_set_mode - set regulator operating mode 2696414c70cbSLiam Girdwood * @regulator: regulator source 2697414c70cbSLiam Girdwood * @mode: operating mode - one of the REGULATOR_MODE constants 2698414c70cbSLiam Girdwood * 2699414c70cbSLiam Girdwood * Set regulator operating mode to increase regulator efficiency or improve 2700414c70cbSLiam Girdwood * regulation performance. 2701414c70cbSLiam Girdwood * 2702414c70cbSLiam Girdwood * NOTE: Regulator system constraints must be set for this regulator before 2703414c70cbSLiam Girdwood * calling this function otherwise this call will fail. 2704414c70cbSLiam Girdwood */ 2705414c70cbSLiam Girdwood int regulator_set_mode(struct regulator *regulator, unsigned int mode) 2706414c70cbSLiam Girdwood { 2707414c70cbSLiam Girdwood struct regulator_dev *rdev = regulator->rdev; 2708414c70cbSLiam Girdwood int ret; 2709500b4ac9SSundar R Iyer int regulator_curr_mode; 2710414c70cbSLiam Girdwood 2711414c70cbSLiam Girdwood mutex_lock(&rdev->mutex); 2712414c70cbSLiam Girdwood 2713414c70cbSLiam Girdwood /* sanity check */ 2714414c70cbSLiam Girdwood if (!rdev->desc->ops->set_mode) { 2715414c70cbSLiam Girdwood ret = -EINVAL; 2716414c70cbSLiam Girdwood goto out; 2717414c70cbSLiam Girdwood } 2718414c70cbSLiam Girdwood 2719500b4ac9SSundar R Iyer /* return if the same mode is requested */ 2720500b4ac9SSundar R Iyer if (rdev->desc->ops->get_mode) { 2721500b4ac9SSundar R Iyer regulator_curr_mode = rdev->desc->ops->get_mode(rdev); 2722500b4ac9SSundar R Iyer if (regulator_curr_mode == mode) { 2723500b4ac9SSundar R Iyer ret = 0; 2724500b4ac9SSundar R Iyer goto out; 2725500b4ac9SSundar R Iyer } 2726500b4ac9SSundar R Iyer } 2727500b4ac9SSundar R Iyer 2728414c70cbSLiam Girdwood /* constraints check */ 272922c51b47SAxel Lin ret = regulator_mode_constrain(rdev, &mode); 2730414c70cbSLiam Girdwood if (ret < 0) 2731414c70cbSLiam Girdwood goto out; 2732414c70cbSLiam Girdwood 2733414c70cbSLiam Girdwood ret = rdev->desc->ops->set_mode(rdev, mode); 2734414c70cbSLiam Girdwood out: 2735414c70cbSLiam Girdwood mutex_unlock(&rdev->mutex); 2736414c70cbSLiam Girdwood return ret; 2737414c70cbSLiam Girdwood } 2738414c70cbSLiam Girdwood EXPORT_SYMBOL_GPL(regulator_set_mode); 2739414c70cbSLiam Girdwood 2740414c70cbSLiam Girdwood static unsigned int _regulator_get_mode(struct regulator_dev *rdev) 2741414c70cbSLiam Girdwood { 2742414c70cbSLiam Girdwood int ret; 2743414c70cbSLiam Girdwood 2744414c70cbSLiam Girdwood mutex_lock(&rdev->mutex); 2745414c70cbSLiam Girdwood 2746414c70cbSLiam Girdwood /* sanity check */ 2747414c70cbSLiam Girdwood if (!rdev->desc->ops->get_mode) { 2748414c70cbSLiam Girdwood ret = -EINVAL; 2749414c70cbSLiam Girdwood goto out; 2750414c70cbSLiam Girdwood } 2751414c70cbSLiam Girdwood 2752414c70cbSLiam Girdwood ret = rdev->desc->ops->get_mode(rdev); 2753414c70cbSLiam Girdwood out: 2754414c70cbSLiam Girdwood mutex_unlock(&rdev->mutex); 2755414c70cbSLiam Girdwood return ret; 2756414c70cbSLiam Girdwood } 2757414c70cbSLiam Girdwood 2758414c70cbSLiam Girdwood /** 2759414c70cbSLiam Girdwood * regulator_get_mode - get regulator operating mode 2760414c70cbSLiam Girdwood * @regulator: regulator source 2761414c70cbSLiam Girdwood * 2762414c70cbSLiam Girdwood * Get the current regulator operating mode. 2763414c70cbSLiam Girdwood */ 2764414c70cbSLiam Girdwood unsigned int regulator_get_mode(struct regulator *regulator) 2765414c70cbSLiam Girdwood { 2766414c70cbSLiam Girdwood return _regulator_get_mode(regulator->rdev); 2767414c70cbSLiam Girdwood } 2768414c70cbSLiam Girdwood EXPORT_SYMBOL_GPL(regulator_get_mode); 2769414c70cbSLiam Girdwood 2770414c70cbSLiam Girdwood /** 2771414c70cbSLiam Girdwood * regulator_set_optimum_mode - set regulator optimum operating mode 2772414c70cbSLiam Girdwood * @regulator: regulator source 2773414c70cbSLiam Girdwood * @uA_load: load current 2774414c70cbSLiam Girdwood * 2775414c70cbSLiam Girdwood * Notifies the regulator core of a new device load. This is then used by 2776414c70cbSLiam Girdwood * DRMS (if enabled by constraints) to set the most efficient regulator 2777414c70cbSLiam Girdwood * operating mode for the new regulator loading. 2778414c70cbSLiam Girdwood * 2779414c70cbSLiam Girdwood * Consumer devices notify their supply regulator of the maximum power 2780414c70cbSLiam Girdwood * they will require (can be taken from device datasheet in the power 2781414c70cbSLiam Girdwood * consumption tables) when they change operational status and hence power 2782414c70cbSLiam Girdwood * state. Examples of operational state changes that can affect power 2783414c70cbSLiam Girdwood * consumption are :- 2784414c70cbSLiam Girdwood * 2785414c70cbSLiam Girdwood * o Device is opened / closed. 2786414c70cbSLiam Girdwood * o Device I/O is about to begin or has just finished. 2787414c70cbSLiam Girdwood * o Device is idling in between work. 2788414c70cbSLiam Girdwood * 2789414c70cbSLiam Girdwood * This information is also exported via sysfs to userspace. 2790414c70cbSLiam Girdwood * 2791414c70cbSLiam Girdwood * DRMS will sum the total requested load on the regulator and change 2792414c70cbSLiam Girdwood * to the most efficient operating mode if platform constraints allow. 2793414c70cbSLiam Girdwood * 2794414c70cbSLiam Girdwood * Returns the new regulator mode or error. 2795414c70cbSLiam Girdwood */ 2796414c70cbSLiam Girdwood int regulator_set_optimum_mode(struct regulator *regulator, int uA_load) 2797414c70cbSLiam Girdwood { 2798414c70cbSLiam Girdwood struct regulator_dev *rdev = regulator->rdev; 2799414c70cbSLiam Girdwood struct regulator *consumer; 2800d92d95b6SStephen Boyd int ret, output_uV, input_uV = 0, total_uA_load = 0; 2801414c70cbSLiam Girdwood unsigned int mode; 2802414c70cbSLiam Girdwood 2803d92d95b6SStephen Boyd if (rdev->supply) 2804d92d95b6SStephen Boyd input_uV = regulator_get_voltage(rdev->supply); 2805d92d95b6SStephen Boyd 2806414c70cbSLiam Girdwood mutex_lock(&rdev->mutex); 2807414c70cbSLiam Girdwood 2808a4b41483SMark Brown /* 2809a4b41483SMark Brown * first check to see if we can set modes at all, otherwise just 2810a4b41483SMark Brown * tell the consumer everything is OK. 2811a4b41483SMark Brown */ 2812414c70cbSLiam Girdwood regulator->uA_load = uA_load; 2813414c70cbSLiam Girdwood ret = regulator_check_drms(rdev); 2814a4b41483SMark Brown if (ret < 0) { 2815a4b41483SMark Brown ret = 0; 2816414c70cbSLiam Girdwood goto out; 2817a4b41483SMark Brown } 2818414c70cbSLiam Girdwood 2819414c70cbSLiam Girdwood if (!rdev->desc->ops->get_optimum_mode) 2820414c70cbSLiam Girdwood goto out; 2821414c70cbSLiam Girdwood 2822a4b41483SMark Brown /* 2823a4b41483SMark Brown * we can actually do this so any errors are indicators of 2824a4b41483SMark Brown * potential real failure. 2825a4b41483SMark Brown */ 2826a4b41483SMark Brown ret = -EINVAL; 2827a4b41483SMark Brown 2828854ccbaeSAxel Lin if (!rdev->desc->ops->set_mode) 2829854ccbaeSAxel Lin goto out; 2830854ccbaeSAxel Lin 2831414c70cbSLiam Girdwood /* get output voltage */ 28321bf5a1f8SMark Brown output_uV = _regulator_get_voltage(rdev); 2833414c70cbSLiam Girdwood if (output_uV <= 0) { 28345da84fd9SJoe Perches rdev_err(rdev, "invalid output voltage found\n"); 2835414c70cbSLiam Girdwood goto out; 2836414c70cbSLiam Girdwood } 2837414c70cbSLiam Girdwood 2838d92d95b6SStephen Boyd /* No supply? Use constraint voltage */ 28391bf5a1f8SMark Brown if (input_uV <= 0) 2840414c70cbSLiam Girdwood input_uV = rdev->constraints->input_uV; 2841414c70cbSLiam Girdwood if (input_uV <= 0) { 28425da84fd9SJoe Perches rdev_err(rdev, "invalid input voltage found\n"); 2843414c70cbSLiam Girdwood goto out; 2844414c70cbSLiam Girdwood } 2845414c70cbSLiam Girdwood 2846414c70cbSLiam Girdwood /* calc total requested load for this regulator */ 2847414c70cbSLiam Girdwood list_for_each_entry(consumer, &rdev->consumer_list, list) 2848414c70cbSLiam Girdwood total_uA_load += consumer->uA_load; 2849414c70cbSLiam Girdwood 2850414c70cbSLiam Girdwood mode = rdev->desc->ops->get_optimum_mode(rdev, 2851414c70cbSLiam Girdwood input_uV, output_uV, 2852414c70cbSLiam Girdwood total_uA_load); 28532c608234SMark Brown ret = regulator_mode_constrain(rdev, &mode); 2854e573520bSDavid Brownell if (ret < 0) { 28555da84fd9SJoe Perches rdev_err(rdev, "failed to get optimum mode @ %d uA %d -> %d uV\n", 2856414c70cbSLiam Girdwood total_uA_load, input_uV, output_uV); 2857414c70cbSLiam Girdwood goto out; 2858414c70cbSLiam Girdwood } 2859414c70cbSLiam Girdwood 2860414c70cbSLiam Girdwood ret = rdev->desc->ops->set_mode(rdev, mode); 2861e573520bSDavid Brownell if (ret < 0) { 28625da84fd9SJoe Perches rdev_err(rdev, "failed to set optimum mode %x\n", mode); 2863414c70cbSLiam Girdwood goto out; 2864414c70cbSLiam Girdwood } 2865414c70cbSLiam Girdwood ret = mode; 2866414c70cbSLiam Girdwood out: 2867414c70cbSLiam Girdwood mutex_unlock(&rdev->mutex); 2868414c70cbSLiam Girdwood return ret; 2869414c70cbSLiam Girdwood } 2870414c70cbSLiam Girdwood EXPORT_SYMBOL_GPL(regulator_set_optimum_mode); 2871414c70cbSLiam Girdwood 2872414c70cbSLiam Girdwood /** 2873f59c8f9fSMark Brown * regulator_allow_bypass - allow the regulator to go into bypass mode 2874f59c8f9fSMark Brown * 2875f59c8f9fSMark Brown * @regulator: Regulator to configure 28769345dfb8SNishanth Menon * @enable: enable or disable bypass mode 2877f59c8f9fSMark Brown * 2878f59c8f9fSMark Brown * Allow the regulator to go into bypass mode if all other consumers 2879f59c8f9fSMark Brown * for the regulator also enable bypass mode and the machine 2880f59c8f9fSMark Brown * constraints allow this. Bypass mode means that the regulator is 2881f59c8f9fSMark Brown * simply passing the input directly to the output with no regulation. 2882f59c8f9fSMark Brown */ 2883f59c8f9fSMark Brown int regulator_allow_bypass(struct regulator *regulator, bool enable) 2884f59c8f9fSMark Brown { 2885f59c8f9fSMark Brown struct regulator_dev *rdev = regulator->rdev; 2886f59c8f9fSMark Brown int ret = 0; 2887f59c8f9fSMark Brown 2888f59c8f9fSMark Brown if (!rdev->desc->ops->set_bypass) 2889f59c8f9fSMark Brown return 0; 2890f59c8f9fSMark Brown 2891f59c8f9fSMark Brown if (rdev->constraints && 2892f59c8f9fSMark Brown !(rdev->constraints->valid_ops_mask & REGULATOR_CHANGE_BYPASS)) 2893f59c8f9fSMark Brown return 0; 2894f59c8f9fSMark Brown 2895f59c8f9fSMark Brown mutex_lock(&rdev->mutex); 2896f59c8f9fSMark Brown 2897f59c8f9fSMark Brown if (enable && !regulator->bypass) { 2898f59c8f9fSMark Brown rdev->bypass_count++; 2899f59c8f9fSMark Brown 2900f59c8f9fSMark Brown if (rdev->bypass_count == rdev->open_count) { 2901f59c8f9fSMark Brown ret = rdev->desc->ops->set_bypass(rdev, enable); 2902f59c8f9fSMark Brown if (ret != 0) 2903f59c8f9fSMark Brown rdev->bypass_count--; 2904f59c8f9fSMark Brown } 2905f59c8f9fSMark Brown 2906f59c8f9fSMark Brown } else if (!enable && regulator->bypass) { 2907f59c8f9fSMark Brown rdev->bypass_count--; 2908f59c8f9fSMark Brown 2909f59c8f9fSMark Brown if (rdev->bypass_count != rdev->open_count) { 2910f59c8f9fSMark Brown ret = rdev->desc->ops->set_bypass(rdev, enable); 2911f59c8f9fSMark Brown if (ret != 0) 2912f59c8f9fSMark Brown rdev->bypass_count++; 2913f59c8f9fSMark Brown } 2914f59c8f9fSMark Brown } 2915f59c8f9fSMark Brown 2916f59c8f9fSMark Brown if (ret == 0) 2917f59c8f9fSMark Brown regulator->bypass = enable; 2918f59c8f9fSMark Brown 2919f59c8f9fSMark Brown mutex_unlock(&rdev->mutex); 2920f59c8f9fSMark Brown 2921f59c8f9fSMark Brown return ret; 2922f59c8f9fSMark Brown } 2923f59c8f9fSMark Brown EXPORT_SYMBOL_GPL(regulator_allow_bypass); 2924f59c8f9fSMark Brown 2925f59c8f9fSMark Brown /** 2926414c70cbSLiam Girdwood * regulator_register_notifier - register regulator event notifier 2927414c70cbSLiam Girdwood * @regulator: regulator source 292869279fb9SMark Brown * @nb: notifier block 2929414c70cbSLiam Girdwood * 2930414c70cbSLiam Girdwood * Register notifier block to receive regulator events. 2931414c70cbSLiam Girdwood */ 2932414c70cbSLiam Girdwood int regulator_register_notifier(struct regulator *regulator, 2933414c70cbSLiam Girdwood struct notifier_block *nb) 2934414c70cbSLiam Girdwood { 2935414c70cbSLiam Girdwood return blocking_notifier_chain_register(®ulator->rdev->notifier, 2936414c70cbSLiam Girdwood nb); 2937414c70cbSLiam Girdwood } 2938414c70cbSLiam Girdwood EXPORT_SYMBOL_GPL(regulator_register_notifier); 2939414c70cbSLiam Girdwood 2940414c70cbSLiam Girdwood /** 2941414c70cbSLiam Girdwood * regulator_unregister_notifier - unregister regulator event notifier 2942414c70cbSLiam Girdwood * @regulator: regulator source 294369279fb9SMark Brown * @nb: notifier block 2944414c70cbSLiam Girdwood * 2945414c70cbSLiam Girdwood * Unregister regulator event notifier block. 2946414c70cbSLiam Girdwood */ 2947414c70cbSLiam Girdwood int regulator_unregister_notifier(struct regulator *regulator, 2948414c70cbSLiam Girdwood struct notifier_block *nb) 2949414c70cbSLiam Girdwood { 2950414c70cbSLiam Girdwood return blocking_notifier_chain_unregister(®ulator->rdev->notifier, 2951414c70cbSLiam Girdwood nb); 2952414c70cbSLiam Girdwood } 2953414c70cbSLiam Girdwood EXPORT_SYMBOL_GPL(regulator_unregister_notifier); 2954414c70cbSLiam Girdwood 2955b136fb44SJonathan Cameron /* notify regulator consumers and downstream regulator consumers. 2956b136fb44SJonathan Cameron * Note mutex must be held by caller. 2957b136fb44SJonathan Cameron */ 2958414c70cbSLiam Girdwood static void _notifier_call_chain(struct regulator_dev *rdev, 2959414c70cbSLiam Girdwood unsigned long event, void *data) 2960414c70cbSLiam Girdwood { 2961414c70cbSLiam Girdwood /* call rdev chain first */ 2962d8493d21SMark Brown blocking_notifier_call_chain(&rdev->notifier, event, data); 2963414c70cbSLiam Girdwood } 2964414c70cbSLiam Girdwood 2965414c70cbSLiam Girdwood /** 2966414c70cbSLiam Girdwood * regulator_bulk_get - get multiple regulator consumers 2967414c70cbSLiam Girdwood * 2968414c70cbSLiam Girdwood * @dev: Device to supply 2969414c70cbSLiam Girdwood * @num_consumers: Number of consumers to register 2970414c70cbSLiam Girdwood * @consumers: Configuration of consumers; clients are stored here. 2971414c70cbSLiam Girdwood * 2972414c70cbSLiam Girdwood * @return 0 on success, an errno on failure. 2973414c70cbSLiam Girdwood * 2974414c70cbSLiam Girdwood * This helper function allows drivers to get several regulator 2975414c70cbSLiam Girdwood * consumers in one operation. If any of the regulators cannot be 2976414c70cbSLiam Girdwood * acquired then any regulators that were allocated will be freed 2977414c70cbSLiam Girdwood * before returning to the caller. 2978414c70cbSLiam Girdwood */ 2979414c70cbSLiam Girdwood int regulator_bulk_get(struct device *dev, int num_consumers, 2980414c70cbSLiam Girdwood struct regulator_bulk_data *consumers) 2981414c70cbSLiam Girdwood { 2982414c70cbSLiam Girdwood int i; 2983414c70cbSLiam Girdwood int ret; 2984414c70cbSLiam Girdwood 2985414c70cbSLiam Girdwood for (i = 0; i < num_consumers; i++) 2986414c70cbSLiam Girdwood consumers[i].consumer = NULL; 2987414c70cbSLiam Girdwood 2988414c70cbSLiam Girdwood for (i = 0; i < num_consumers; i++) { 2989414c70cbSLiam Girdwood consumers[i].consumer = regulator_get(dev, 2990414c70cbSLiam Girdwood consumers[i].supply); 2991414c70cbSLiam Girdwood if (IS_ERR(consumers[i].consumer)) { 2992414c70cbSLiam Girdwood ret = PTR_ERR(consumers[i].consumer); 29935b307627SMark Brown dev_err(dev, "Failed to get supply '%s': %d\n", 29945b307627SMark Brown consumers[i].supply, ret); 2995414c70cbSLiam Girdwood consumers[i].consumer = NULL; 2996414c70cbSLiam Girdwood goto err; 2997414c70cbSLiam Girdwood } 2998414c70cbSLiam Girdwood } 2999414c70cbSLiam Girdwood 3000414c70cbSLiam Girdwood return 0; 3001414c70cbSLiam Girdwood 3002414c70cbSLiam Girdwood err: 3003b29c7690SAxel Lin while (--i >= 0) 3004414c70cbSLiam Girdwood regulator_put(consumers[i].consumer); 3005414c70cbSLiam Girdwood 3006414c70cbSLiam Girdwood return ret; 3007414c70cbSLiam Girdwood } 3008414c70cbSLiam Girdwood EXPORT_SYMBOL_GPL(regulator_bulk_get); 3009414c70cbSLiam Girdwood 3010f21e0e81SMark Brown static void regulator_bulk_enable_async(void *data, async_cookie_t cookie) 3011f21e0e81SMark Brown { 3012f21e0e81SMark Brown struct regulator_bulk_data *bulk = data; 3013f21e0e81SMark Brown 3014f21e0e81SMark Brown bulk->ret = regulator_enable(bulk->consumer); 3015f21e0e81SMark Brown } 3016f21e0e81SMark Brown 3017414c70cbSLiam Girdwood /** 3018414c70cbSLiam Girdwood * regulator_bulk_enable - enable multiple regulator consumers 3019414c70cbSLiam Girdwood * 3020414c70cbSLiam Girdwood * @num_consumers: Number of consumers 3021414c70cbSLiam Girdwood * @consumers: Consumer data; clients are stored here. 3022414c70cbSLiam Girdwood * @return 0 on success, an errno on failure 3023414c70cbSLiam Girdwood * 3024414c70cbSLiam Girdwood * This convenience API allows consumers to enable multiple regulator 3025414c70cbSLiam Girdwood * clients in a single API call. If any consumers cannot be enabled 3026414c70cbSLiam Girdwood * then any others that were enabled will be disabled again prior to 3027414c70cbSLiam Girdwood * return. 3028414c70cbSLiam Girdwood */ 3029414c70cbSLiam Girdwood int regulator_bulk_enable(int num_consumers, 3030414c70cbSLiam Girdwood struct regulator_bulk_data *consumers) 3031414c70cbSLiam Girdwood { 30322955b47dSDan Williams ASYNC_DOMAIN_EXCLUSIVE(async_domain); 3033414c70cbSLiam Girdwood int i; 3034f21e0e81SMark Brown int ret = 0; 3035414c70cbSLiam Girdwood 30366492bc1bSMark Brown for (i = 0; i < num_consumers; i++) { 30376492bc1bSMark Brown if (consumers[i].consumer->always_on) 30386492bc1bSMark Brown consumers[i].ret = 0; 30396492bc1bSMark Brown else 3040f21e0e81SMark Brown async_schedule_domain(regulator_bulk_enable_async, 3041f21e0e81SMark Brown &consumers[i], &async_domain); 30426492bc1bSMark Brown } 3043f21e0e81SMark Brown 3044f21e0e81SMark Brown async_synchronize_full_domain(&async_domain); 3045f21e0e81SMark Brown 3046f21e0e81SMark Brown /* If any consumer failed we need to unwind any that succeeded */ 3047414c70cbSLiam Girdwood for (i = 0; i < num_consumers; i++) { 3048f21e0e81SMark Brown if (consumers[i].ret != 0) { 3049f21e0e81SMark Brown ret = consumers[i].ret; 3050414c70cbSLiam Girdwood goto err; 3051414c70cbSLiam Girdwood } 3052f21e0e81SMark Brown } 3053414c70cbSLiam Girdwood 3054414c70cbSLiam Girdwood return 0; 3055414c70cbSLiam Girdwood 3056414c70cbSLiam Girdwood err: 3057fbe31057SAndrzej Hajda for (i = 0; i < num_consumers; i++) { 3058fbe31057SAndrzej Hajda if (consumers[i].ret < 0) 3059fbe31057SAndrzej Hajda pr_err("Failed to enable %s: %d\n", consumers[i].supply, 3060fbe31057SAndrzej Hajda consumers[i].ret); 3061fbe31057SAndrzej Hajda else 3062414c70cbSLiam Girdwood regulator_disable(consumers[i].consumer); 3063fbe31057SAndrzej Hajda } 3064414c70cbSLiam Girdwood 3065414c70cbSLiam Girdwood return ret; 3066414c70cbSLiam Girdwood } 3067414c70cbSLiam Girdwood EXPORT_SYMBOL_GPL(regulator_bulk_enable); 3068414c70cbSLiam Girdwood 3069414c70cbSLiam Girdwood /** 3070414c70cbSLiam Girdwood * regulator_bulk_disable - disable multiple regulator consumers 3071414c70cbSLiam Girdwood * 3072414c70cbSLiam Girdwood * @num_consumers: Number of consumers 3073414c70cbSLiam Girdwood * @consumers: Consumer data; clients are stored here. 3074414c70cbSLiam Girdwood * @return 0 on success, an errno on failure 3075414c70cbSLiam Girdwood * 3076414c70cbSLiam Girdwood * This convenience API allows consumers to disable multiple regulator 307749e22632SSylwester Nawrocki * clients in a single API call. If any consumers cannot be disabled 307849e22632SSylwester Nawrocki * then any others that were disabled will be enabled again prior to 3079414c70cbSLiam Girdwood * return. 3080414c70cbSLiam Girdwood */ 3081414c70cbSLiam Girdwood int regulator_bulk_disable(int num_consumers, 3082414c70cbSLiam Girdwood struct regulator_bulk_data *consumers) 3083414c70cbSLiam Girdwood { 3084414c70cbSLiam Girdwood int i; 308501e86f49SMark Brown int ret, r; 3086414c70cbSLiam Girdwood 308749e22632SSylwester Nawrocki for (i = num_consumers - 1; i >= 0; --i) { 3088414c70cbSLiam Girdwood ret = regulator_disable(consumers[i].consumer); 3089414c70cbSLiam Girdwood if (ret != 0) 3090414c70cbSLiam Girdwood goto err; 3091414c70cbSLiam Girdwood } 3092414c70cbSLiam Girdwood 3093414c70cbSLiam Girdwood return 0; 3094414c70cbSLiam Girdwood 3095414c70cbSLiam Girdwood err: 30965da84fd9SJoe Perches pr_err("Failed to disable %s: %d\n", consumers[i].supply, ret); 309701e86f49SMark Brown for (++i; i < num_consumers; ++i) { 309801e86f49SMark Brown r = regulator_enable(consumers[i].consumer); 309901e86f49SMark Brown if (r != 0) 310001e86f49SMark Brown pr_err("Failed to reename %s: %d\n", 310101e86f49SMark Brown consumers[i].supply, r); 310201e86f49SMark Brown } 3103414c70cbSLiam Girdwood 3104414c70cbSLiam Girdwood return ret; 3105414c70cbSLiam Girdwood } 3106414c70cbSLiam Girdwood EXPORT_SYMBOL_GPL(regulator_bulk_disable); 3107414c70cbSLiam Girdwood 3108414c70cbSLiam Girdwood /** 3109e1de2f42SDonggeun Kim * regulator_bulk_force_disable - force disable multiple regulator consumers 3110e1de2f42SDonggeun Kim * 3111e1de2f42SDonggeun Kim * @num_consumers: Number of consumers 3112e1de2f42SDonggeun Kim * @consumers: Consumer data; clients are stored here. 3113e1de2f42SDonggeun Kim * @return 0 on success, an errno on failure 3114e1de2f42SDonggeun Kim * 3115e1de2f42SDonggeun Kim * This convenience API allows consumers to forcibly disable multiple regulator 3116e1de2f42SDonggeun Kim * clients in a single API call. 3117e1de2f42SDonggeun Kim * NOTE: This should be used for situations when device damage will 3118e1de2f42SDonggeun Kim * likely occur if the regulators are not disabled (e.g. over temp). 3119e1de2f42SDonggeun Kim * Although regulator_force_disable function call for some consumers can 3120e1de2f42SDonggeun Kim * return error numbers, the function is called for all consumers. 3121e1de2f42SDonggeun Kim */ 3122e1de2f42SDonggeun Kim int regulator_bulk_force_disable(int num_consumers, 3123e1de2f42SDonggeun Kim struct regulator_bulk_data *consumers) 3124e1de2f42SDonggeun Kim { 3125e1de2f42SDonggeun Kim int i; 3126e1de2f42SDonggeun Kim int ret; 3127e1de2f42SDonggeun Kim 3128e1de2f42SDonggeun Kim for (i = 0; i < num_consumers; i++) 3129e1de2f42SDonggeun Kim consumers[i].ret = 3130e1de2f42SDonggeun Kim regulator_force_disable(consumers[i].consumer); 3131e1de2f42SDonggeun Kim 3132e1de2f42SDonggeun Kim for (i = 0; i < num_consumers; i++) { 3133e1de2f42SDonggeun Kim if (consumers[i].ret != 0) { 3134e1de2f42SDonggeun Kim ret = consumers[i].ret; 3135e1de2f42SDonggeun Kim goto out; 3136e1de2f42SDonggeun Kim } 3137e1de2f42SDonggeun Kim } 3138e1de2f42SDonggeun Kim 3139e1de2f42SDonggeun Kim return 0; 3140e1de2f42SDonggeun Kim out: 3141e1de2f42SDonggeun Kim return ret; 3142e1de2f42SDonggeun Kim } 3143e1de2f42SDonggeun Kim EXPORT_SYMBOL_GPL(regulator_bulk_force_disable); 3144e1de2f42SDonggeun Kim 3145e1de2f42SDonggeun Kim /** 3146414c70cbSLiam Girdwood * regulator_bulk_free - free multiple regulator consumers 3147414c70cbSLiam Girdwood * 3148414c70cbSLiam Girdwood * @num_consumers: Number of consumers 3149414c70cbSLiam Girdwood * @consumers: Consumer data; clients are stored here. 3150414c70cbSLiam Girdwood * 3151414c70cbSLiam Girdwood * This convenience API allows consumers to free multiple regulator 3152414c70cbSLiam Girdwood * clients in a single API call. 3153414c70cbSLiam Girdwood */ 3154414c70cbSLiam Girdwood void regulator_bulk_free(int num_consumers, 3155414c70cbSLiam Girdwood struct regulator_bulk_data *consumers) 3156414c70cbSLiam Girdwood { 3157414c70cbSLiam Girdwood int i; 3158414c70cbSLiam Girdwood 3159414c70cbSLiam Girdwood for (i = 0; i < num_consumers; i++) { 3160414c70cbSLiam Girdwood regulator_put(consumers[i].consumer); 3161414c70cbSLiam Girdwood consumers[i].consumer = NULL; 3162414c70cbSLiam Girdwood } 3163414c70cbSLiam Girdwood } 3164414c70cbSLiam Girdwood EXPORT_SYMBOL_GPL(regulator_bulk_free); 3165414c70cbSLiam Girdwood 3166414c70cbSLiam Girdwood /** 3167414c70cbSLiam Girdwood * regulator_notifier_call_chain - call regulator event notifier 316869279fb9SMark Brown * @rdev: regulator source 3169414c70cbSLiam Girdwood * @event: notifier block 317069279fb9SMark Brown * @data: callback-specific data. 3171414c70cbSLiam Girdwood * 3172414c70cbSLiam Girdwood * Called by regulator drivers to notify clients a regulator event has 3173414c70cbSLiam Girdwood * occurred. We also notify regulator clients downstream. 3174b136fb44SJonathan Cameron * Note lock must be held by caller. 3175414c70cbSLiam Girdwood */ 3176414c70cbSLiam Girdwood int regulator_notifier_call_chain(struct regulator_dev *rdev, 3177414c70cbSLiam Girdwood unsigned long event, void *data) 3178414c70cbSLiam Girdwood { 3179414c70cbSLiam Girdwood _notifier_call_chain(rdev, event, data); 3180414c70cbSLiam Girdwood return NOTIFY_DONE; 3181414c70cbSLiam Girdwood 3182414c70cbSLiam Girdwood } 3183414c70cbSLiam Girdwood EXPORT_SYMBOL_GPL(regulator_notifier_call_chain); 3184414c70cbSLiam Girdwood 3185be721979SMark Brown /** 3186be721979SMark Brown * regulator_mode_to_status - convert a regulator mode into a status 3187be721979SMark Brown * 3188be721979SMark Brown * @mode: Mode to convert 3189be721979SMark Brown * 3190be721979SMark Brown * Convert a regulator mode into a status. 3191be721979SMark Brown */ 3192be721979SMark Brown int regulator_mode_to_status(unsigned int mode) 3193be721979SMark Brown { 3194be721979SMark Brown switch (mode) { 3195be721979SMark Brown case REGULATOR_MODE_FAST: 3196be721979SMark Brown return REGULATOR_STATUS_FAST; 3197be721979SMark Brown case REGULATOR_MODE_NORMAL: 3198be721979SMark Brown return REGULATOR_STATUS_NORMAL; 3199be721979SMark Brown case REGULATOR_MODE_IDLE: 3200be721979SMark Brown return REGULATOR_STATUS_IDLE; 320103ffcf3dSKrystian Garbaciak case REGULATOR_MODE_STANDBY: 3202be721979SMark Brown return REGULATOR_STATUS_STANDBY; 3203be721979SMark Brown default: 32041beaf762SKrystian Garbaciak return REGULATOR_STATUS_UNDEFINED; 3205be721979SMark Brown } 3206be721979SMark Brown } 3207be721979SMark Brown EXPORT_SYMBOL_GPL(regulator_mode_to_status); 3208be721979SMark Brown 32097ad68e2fSDavid Brownell /* 32107ad68e2fSDavid Brownell * To avoid cluttering sysfs (and memory) with useless state, only 32117ad68e2fSDavid Brownell * create attributes that can be meaningfully displayed. 32127ad68e2fSDavid Brownell */ 32137ad68e2fSDavid Brownell static int add_regulator_attributes(struct regulator_dev *rdev) 32147ad68e2fSDavid Brownell { 32157ad68e2fSDavid Brownell struct device *dev = &rdev->dev; 32167ad68e2fSDavid Brownell struct regulator_ops *ops = rdev->desc->ops; 32177ad68e2fSDavid Brownell int status = 0; 32187ad68e2fSDavid Brownell 32197ad68e2fSDavid Brownell /* some attributes need specific methods to be displayed */ 32204c78899bSMark Brown if ((ops->get_voltage && ops->get_voltage(rdev) >= 0) || 3221f2889e65SMark Brown (ops->get_voltage_sel && ops->get_voltage_sel(rdev) >= 0) || 32225a523605SLaxman Dewangan (ops->list_voltage && ops->list_voltage(rdev, 0) >= 0) || 32235a523605SLaxman Dewangan (rdev->desc->fixed_uV && (rdev->desc->n_voltages == 1))) { 32247ad68e2fSDavid Brownell status = device_create_file(dev, &dev_attr_microvolts); 32257ad68e2fSDavid Brownell if (status < 0) 32267ad68e2fSDavid Brownell return status; 32277ad68e2fSDavid Brownell } 32287ad68e2fSDavid Brownell if (ops->get_current_limit) { 32297ad68e2fSDavid Brownell status = device_create_file(dev, &dev_attr_microamps); 32307ad68e2fSDavid Brownell if (status < 0) 32317ad68e2fSDavid Brownell return status; 32327ad68e2fSDavid Brownell } 32337ad68e2fSDavid Brownell if (ops->get_mode) { 32347ad68e2fSDavid Brownell status = device_create_file(dev, &dev_attr_opmode); 32357ad68e2fSDavid Brownell if (status < 0) 32367ad68e2fSDavid Brownell return status; 32377ad68e2fSDavid Brownell } 32387b74d149SKim, Milo if (rdev->ena_pin || ops->is_enabled) { 32397ad68e2fSDavid Brownell status = device_create_file(dev, &dev_attr_state); 32407ad68e2fSDavid Brownell if (status < 0) 32417ad68e2fSDavid Brownell return status; 32427ad68e2fSDavid Brownell } 3243853116a1SDavid Brownell if (ops->get_status) { 3244853116a1SDavid Brownell status = device_create_file(dev, &dev_attr_status); 3245853116a1SDavid Brownell if (status < 0) 3246853116a1SDavid Brownell return status; 3247853116a1SDavid Brownell } 3248f59c8f9fSMark Brown if (ops->get_bypass) { 3249f59c8f9fSMark Brown status = device_create_file(dev, &dev_attr_bypass); 3250f59c8f9fSMark Brown if (status < 0) 3251f59c8f9fSMark Brown return status; 3252f59c8f9fSMark Brown } 32537ad68e2fSDavid Brownell 32547ad68e2fSDavid Brownell /* some attributes are type-specific */ 32557ad68e2fSDavid Brownell if (rdev->desc->type == REGULATOR_CURRENT) { 32567ad68e2fSDavid Brownell status = device_create_file(dev, &dev_attr_requested_microamps); 32577ad68e2fSDavid Brownell if (status < 0) 32587ad68e2fSDavid Brownell return status; 32597ad68e2fSDavid Brownell } 32607ad68e2fSDavid Brownell 32617ad68e2fSDavid Brownell /* all the other attributes exist to support constraints; 32627ad68e2fSDavid Brownell * don't show them if there are no constraints, or if the 32637ad68e2fSDavid Brownell * relevant supporting methods are missing. 32647ad68e2fSDavid Brownell */ 32657ad68e2fSDavid Brownell if (!rdev->constraints) 32667ad68e2fSDavid Brownell return status; 32677ad68e2fSDavid Brownell 32687ad68e2fSDavid Brownell /* constraints need specific supporting methods */ 3269e8eef82bSMark Brown if (ops->set_voltage || ops->set_voltage_sel) { 32707ad68e2fSDavid Brownell status = device_create_file(dev, &dev_attr_min_microvolts); 32717ad68e2fSDavid Brownell if (status < 0) 32727ad68e2fSDavid Brownell return status; 32737ad68e2fSDavid Brownell status = device_create_file(dev, &dev_attr_max_microvolts); 32747ad68e2fSDavid Brownell if (status < 0) 32757ad68e2fSDavid Brownell return status; 32767ad68e2fSDavid Brownell } 32777ad68e2fSDavid Brownell if (ops->set_current_limit) { 32787ad68e2fSDavid Brownell status = device_create_file(dev, &dev_attr_min_microamps); 32797ad68e2fSDavid Brownell if (status < 0) 32807ad68e2fSDavid Brownell return status; 32817ad68e2fSDavid Brownell status = device_create_file(dev, &dev_attr_max_microamps); 32827ad68e2fSDavid Brownell if (status < 0) 32837ad68e2fSDavid Brownell return status; 32847ad68e2fSDavid Brownell } 32857ad68e2fSDavid Brownell 32867ad68e2fSDavid Brownell status = device_create_file(dev, &dev_attr_suspend_standby_state); 32877ad68e2fSDavid Brownell if (status < 0) 32887ad68e2fSDavid Brownell return status; 32897ad68e2fSDavid Brownell status = device_create_file(dev, &dev_attr_suspend_mem_state); 32907ad68e2fSDavid Brownell if (status < 0) 32917ad68e2fSDavid Brownell return status; 32927ad68e2fSDavid Brownell status = device_create_file(dev, &dev_attr_suspend_disk_state); 32937ad68e2fSDavid Brownell if (status < 0) 32947ad68e2fSDavid Brownell return status; 32957ad68e2fSDavid Brownell 32967ad68e2fSDavid Brownell if (ops->set_suspend_voltage) { 32977ad68e2fSDavid Brownell status = device_create_file(dev, 32987ad68e2fSDavid Brownell &dev_attr_suspend_standby_microvolts); 32997ad68e2fSDavid Brownell if (status < 0) 33007ad68e2fSDavid Brownell return status; 33017ad68e2fSDavid Brownell status = device_create_file(dev, 33027ad68e2fSDavid Brownell &dev_attr_suspend_mem_microvolts); 33037ad68e2fSDavid Brownell if (status < 0) 33047ad68e2fSDavid Brownell return status; 33057ad68e2fSDavid Brownell status = device_create_file(dev, 33067ad68e2fSDavid Brownell &dev_attr_suspend_disk_microvolts); 33077ad68e2fSDavid Brownell if (status < 0) 33087ad68e2fSDavid Brownell return status; 33097ad68e2fSDavid Brownell } 33107ad68e2fSDavid Brownell 33117ad68e2fSDavid Brownell if (ops->set_suspend_mode) { 33127ad68e2fSDavid Brownell status = device_create_file(dev, 33137ad68e2fSDavid Brownell &dev_attr_suspend_standby_mode); 33147ad68e2fSDavid Brownell if (status < 0) 33157ad68e2fSDavid Brownell return status; 33167ad68e2fSDavid Brownell status = device_create_file(dev, 33177ad68e2fSDavid Brownell &dev_attr_suspend_mem_mode); 33187ad68e2fSDavid Brownell if (status < 0) 33197ad68e2fSDavid Brownell return status; 33207ad68e2fSDavid Brownell status = device_create_file(dev, 33217ad68e2fSDavid Brownell &dev_attr_suspend_disk_mode); 33227ad68e2fSDavid Brownell if (status < 0) 33237ad68e2fSDavid Brownell return status; 33247ad68e2fSDavid Brownell } 33257ad68e2fSDavid Brownell 33267ad68e2fSDavid Brownell return status; 33277ad68e2fSDavid Brownell } 33287ad68e2fSDavid Brownell 33291130e5b3SMark Brown static void rdev_init_debugfs(struct regulator_dev *rdev) 33301130e5b3SMark Brown { 33311130e5b3SMark Brown rdev->debugfs = debugfs_create_dir(rdev_get_name(rdev), debugfs_root); 333224751434SStephen Boyd if (!rdev->debugfs) { 33331130e5b3SMark Brown rdev_warn(rdev, "Failed to create debugfs directory\n"); 33341130e5b3SMark Brown return; 33351130e5b3SMark Brown } 33361130e5b3SMark Brown 33371130e5b3SMark Brown debugfs_create_u32("use_count", 0444, rdev->debugfs, 33381130e5b3SMark Brown &rdev->use_count); 33391130e5b3SMark Brown debugfs_create_u32("open_count", 0444, rdev->debugfs, 33401130e5b3SMark Brown &rdev->open_count); 3341f59c8f9fSMark Brown debugfs_create_u32("bypass_count", 0444, rdev->debugfs, 3342f59c8f9fSMark Brown &rdev->bypass_count); 33431130e5b3SMark Brown } 33441130e5b3SMark Brown 3345414c70cbSLiam Girdwood /** 3346414c70cbSLiam Girdwood * regulator_register - register regulator 334769279fb9SMark Brown * @regulator_desc: regulator to register 3348c172708dSMark Brown * @config: runtime configuration for regulator 3349414c70cbSLiam Girdwood * 3350414c70cbSLiam Girdwood * Called by regulator drivers to register a regulator. 33510384618aSAxel Lin * Returns a valid pointer to struct regulator_dev on success 33520384618aSAxel Lin * or an ERR_PTR() on error. 3353414c70cbSLiam Girdwood */ 335465f26846SMark Brown struct regulator_dev * 335565f26846SMark Brown regulator_register(const struct regulator_desc *regulator_desc, 3356c172708dSMark Brown const struct regulator_config *config) 3357414c70cbSLiam Girdwood { 33589a8f5e07SMark Brown const struct regulation_constraints *constraints = NULL; 3359c172708dSMark Brown const struct regulator_init_data *init_data; 3360414c70cbSLiam Girdwood static atomic_t regulator_no = ATOMIC_INIT(0); 3361414c70cbSLiam Girdwood struct regulator_dev *rdev; 336232c8fad4SMark Brown struct device *dev; 3363a5766f11SLiam Girdwood int ret, i; 336469511a45SRajendra Nayak const char *supply = NULL; 3365414c70cbSLiam Girdwood 3366c172708dSMark Brown if (regulator_desc == NULL || config == NULL) 3367414c70cbSLiam Girdwood return ERR_PTR(-EINVAL); 3368414c70cbSLiam Girdwood 336932c8fad4SMark Brown dev = config->dev; 3370dcf70112SMark Brown WARN_ON(!dev); 337132c8fad4SMark Brown 3372414c70cbSLiam Girdwood if (regulator_desc->name == NULL || regulator_desc->ops == NULL) 3373414c70cbSLiam Girdwood return ERR_PTR(-EINVAL); 3374414c70cbSLiam Girdwood 3375cd78dfc6SDiego Liziero if (regulator_desc->type != REGULATOR_VOLTAGE && 3376cd78dfc6SDiego Liziero regulator_desc->type != REGULATOR_CURRENT) 3377414c70cbSLiam Girdwood return ERR_PTR(-EINVAL); 3378414c70cbSLiam Girdwood 3379476c2d83SMark Brown /* Only one of each should be implemented */ 3380476c2d83SMark Brown WARN_ON(regulator_desc->ops->get_voltage && 3381476c2d83SMark Brown regulator_desc->ops->get_voltage_sel); 3382e8eef82bSMark Brown WARN_ON(regulator_desc->ops->set_voltage && 3383e8eef82bSMark Brown regulator_desc->ops->set_voltage_sel); 3384476c2d83SMark Brown 3385476c2d83SMark Brown /* If we're using selectors we must implement list_voltage. */ 3386476c2d83SMark Brown if (regulator_desc->ops->get_voltage_sel && 3387476c2d83SMark Brown !regulator_desc->ops->list_voltage) { 3388476c2d83SMark Brown return ERR_PTR(-EINVAL); 3389476c2d83SMark Brown } 3390e8eef82bSMark Brown if (regulator_desc->ops->set_voltage_sel && 3391e8eef82bSMark Brown !regulator_desc->ops->list_voltage) { 3392e8eef82bSMark Brown return ERR_PTR(-EINVAL); 3393e8eef82bSMark Brown } 3394476c2d83SMark Brown 3395c172708dSMark Brown init_data = config->init_data; 3396c172708dSMark Brown 3397414c70cbSLiam Girdwood rdev = kzalloc(sizeof(struct regulator_dev), GFP_KERNEL); 3398414c70cbSLiam Girdwood if (rdev == NULL) 3399414c70cbSLiam Girdwood return ERR_PTR(-ENOMEM); 3400414c70cbSLiam Girdwood 3401414c70cbSLiam Girdwood mutex_lock(®ulator_list_mutex); 3402414c70cbSLiam Girdwood 3403414c70cbSLiam Girdwood mutex_init(&rdev->mutex); 3404c172708dSMark Brown rdev->reg_data = config->driver_data; 3405414c70cbSLiam Girdwood rdev->owner = regulator_desc->owner; 3406414c70cbSLiam Girdwood rdev->desc = regulator_desc; 34073a4b0a07SMark Brown if (config->regmap) 340865b19ce6SMark Brown rdev->regmap = config->regmap; 340952b84dacSAnilKumar Ch else if (dev_get_regmap(dev, NULL)) 34103a4b0a07SMark Brown rdev->regmap = dev_get_regmap(dev, NULL); 341152b84dacSAnilKumar Ch else if (dev->parent) 341252b84dacSAnilKumar Ch rdev->regmap = dev_get_regmap(dev->parent, NULL); 3413414c70cbSLiam Girdwood INIT_LIST_HEAD(&rdev->consumer_list); 3414414c70cbSLiam Girdwood INIT_LIST_HEAD(&rdev->list); 3415414c70cbSLiam Girdwood BLOCKING_INIT_NOTIFIER_HEAD(&rdev->notifier); 3416da07ecd9SMark Brown INIT_DELAYED_WORK(&rdev->disable_work, regulator_disable_work); 3417414c70cbSLiam Girdwood 3418a5766f11SLiam Girdwood /* preform any regulator specific init */ 34199a8f5e07SMark Brown if (init_data && init_data->regulator_init) { 3420a5766f11SLiam Girdwood ret = init_data->regulator_init(rdev->reg_data); 34214fca9545SDavid Brownell if (ret < 0) 34224fca9545SDavid Brownell goto clean; 3423a5766f11SLiam Girdwood } 3424a5766f11SLiam Girdwood 3425a5766f11SLiam Girdwood /* register with sysfs */ 3426a5766f11SLiam Girdwood rdev->dev.class = ®ulator_class; 3427c172708dSMark Brown rdev->dev.of_node = config->of_node; 3428a5766f11SLiam Girdwood rdev->dev.parent = dev; 3429812460a9SKay Sievers dev_set_name(&rdev->dev, "regulator.%d", 3430812460a9SKay Sievers atomic_inc_return(®ulator_no) - 1); 3431a5766f11SLiam Girdwood ret = device_register(&rdev->dev); 3432ad7725cbSVasiliy Kulikov if (ret != 0) { 3433ad7725cbSVasiliy Kulikov put_device(&rdev->dev); 34344fca9545SDavid Brownell goto clean; 3435ad7725cbSVasiliy Kulikov } 3436a5766f11SLiam Girdwood 3437a5766f11SLiam Girdwood dev_set_drvdata(&rdev->dev, rdev); 3438a5766f11SLiam Girdwood 3439b2a1ef47SMarek Szyprowski if (config->ena_gpio && gpio_is_valid(config->ena_gpio)) { 3440f19b00daSKim, Milo ret = regulator_ena_gpio_request(rdev, config); 344165f73508SMark Brown if (ret != 0) { 344265f73508SMark Brown rdev_err(rdev, "Failed to request enable GPIO%d: %d\n", 344365f73508SMark Brown config->ena_gpio, ret); 3444b2da55d9SAndrew Lunn goto wash; 344565f73508SMark Brown } 344665f73508SMark Brown 344765f73508SMark Brown if (config->ena_gpio_flags & GPIOF_OUT_INIT_HIGH) 344865f73508SMark Brown rdev->ena_gpio_state = 1; 344965f73508SMark Brown 34507b74d149SKim, Milo if (config->ena_gpio_invert) 345165f73508SMark Brown rdev->ena_gpio_state = !rdev->ena_gpio_state; 345265f73508SMark Brown } 345365f73508SMark Brown 345474f544c1SMike Rapoport /* set regulator constraints */ 34559a8f5e07SMark Brown if (init_data) 34569a8f5e07SMark Brown constraints = &init_data->constraints; 34579a8f5e07SMark Brown 34589a8f5e07SMark Brown ret = set_machine_constraints(rdev, constraints); 345974f544c1SMike Rapoport if (ret < 0) 346074f544c1SMike Rapoport goto scrub; 346174f544c1SMike Rapoport 34627ad68e2fSDavid Brownell /* add attributes supported by this regulator */ 34637ad68e2fSDavid Brownell ret = add_regulator_attributes(rdev); 34647ad68e2fSDavid Brownell if (ret < 0) 34657ad68e2fSDavid Brownell goto scrub; 34667ad68e2fSDavid Brownell 34679a8f5e07SMark Brown if (init_data && init_data->supply_regulator) 346869511a45SRajendra Nayak supply = init_data->supply_regulator; 346969511a45SRajendra Nayak else if (regulator_desc->supply_name) 347069511a45SRajendra Nayak supply = regulator_desc->supply_name; 347169511a45SRajendra Nayak 347269511a45SRajendra Nayak if (supply) { 34730178f3e2SMark Brown struct regulator_dev *r; 34740178f3e2SMark Brown 34756d191a5fSMark Brown r = regulator_dev_lookup(dev, supply, &ret); 34760178f3e2SMark Brown 34770f7b87f0SAndrew Bresticker if (ret == -ENODEV) { 34780f7b87f0SAndrew Bresticker /* 34790f7b87f0SAndrew Bresticker * No supply was specified for this regulator and 34800f7b87f0SAndrew Bresticker * there will never be one. 34810f7b87f0SAndrew Bresticker */ 34820f7b87f0SAndrew Bresticker ret = 0; 34830f7b87f0SAndrew Bresticker goto add_dev; 34840f7b87f0SAndrew Bresticker } else if (!r) { 348569511a45SRajendra Nayak dev_err(dev, "Failed to find supply %s\n", supply); 348604bf3011SMark Brown ret = -EPROBE_DEFER; 34870178f3e2SMark Brown goto scrub; 34880178f3e2SMark Brown } 34890178f3e2SMark Brown 34900178f3e2SMark Brown ret = set_supply(rdev, r); 34910178f3e2SMark Brown if (ret < 0) 34920178f3e2SMark Brown goto scrub; 3493b2296bd4SLaxman Dewangan 3494b2296bd4SLaxman Dewangan /* Enable supply if rail is enabled */ 3495b1a86831SMark Brown if (_regulator_is_enabled(rdev)) { 3496b2296bd4SLaxman Dewangan ret = regulator_enable(rdev->supply); 3497b2296bd4SLaxman Dewangan if (ret < 0) 3498b2296bd4SLaxman Dewangan goto scrub; 3499b2296bd4SLaxman Dewangan } 35000178f3e2SMark Brown } 35010178f3e2SMark Brown 35020f7b87f0SAndrew Bresticker add_dev: 3503a5766f11SLiam Girdwood /* add consumers devices */ 35049a8f5e07SMark Brown if (init_data) { 3505a5766f11SLiam Girdwood for (i = 0; i < init_data->num_consumer_supplies; i++) { 3506a5766f11SLiam Girdwood ret = set_consumer_device_supply(rdev, 350740f9244fSMark Brown init_data->consumer_supplies[i].dev_name, 3508a5766f11SLiam Girdwood init_data->consumer_supplies[i].supply); 350923c2f041SMark Brown if (ret < 0) { 351023c2f041SMark Brown dev_err(dev, "Failed to set supply %s\n", 351123c2f041SMark Brown init_data->consumer_supplies[i].supply); 3512d4033b54SJani Nikula goto unset_supplies; 3513a5766f11SLiam Girdwood } 351423c2f041SMark Brown } 35159a8f5e07SMark Brown } 3516a5766f11SLiam Girdwood 3517a5766f11SLiam Girdwood list_add(&rdev->list, ®ulator_list); 35181130e5b3SMark Brown 35191130e5b3SMark Brown rdev_init_debugfs(rdev); 3520a5766f11SLiam Girdwood out: 3521414c70cbSLiam Girdwood mutex_unlock(®ulator_list_mutex); 3522414c70cbSLiam Girdwood return rdev; 35234fca9545SDavid Brownell 3524d4033b54SJani Nikula unset_supplies: 3525d4033b54SJani Nikula unset_regulator_supplies(rdev); 3526d4033b54SJani Nikula 35274fca9545SDavid Brownell scrub: 3528e81dba85SMark Brown if (rdev->supply) 352923ff2f0fSCharles Keepax _regulator_put(rdev->supply); 3530f19b00daSKim, Milo regulator_ena_gpio_free(rdev); 35311a6958e7SAxel Lin kfree(rdev->constraints); 3532b2da55d9SAndrew Lunn wash: 35334fca9545SDavid Brownell device_unregister(&rdev->dev); 353453032dafSPaul Walmsley /* device core frees rdev */ 353553032dafSPaul Walmsley rdev = ERR_PTR(ret); 353653032dafSPaul Walmsley goto out; 353753032dafSPaul Walmsley 35384fca9545SDavid Brownell clean: 35394fca9545SDavid Brownell kfree(rdev); 35404fca9545SDavid Brownell rdev = ERR_PTR(ret); 35414fca9545SDavid Brownell goto out; 3542414c70cbSLiam Girdwood } 3543414c70cbSLiam Girdwood EXPORT_SYMBOL_GPL(regulator_register); 3544414c70cbSLiam Girdwood 3545414c70cbSLiam Girdwood /** 3546414c70cbSLiam Girdwood * regulator_unregister - unregister regulator 354769279fb9SMark Brown * @rdev: regulator to unregister 3548414c70cbSLiam Girdwood * 3549414c70cbSLiam Girdwood * Called by regulator drivers to unregister a regulator. 3550414c70cbSLiam Girdwood */ 3551414c70cbSLiam Girdwood void regulator_unregister(struct regulator_dev *rdev) 3552414c70cbSLiam Girdwood { 3553414c70cbSLiam Girdwood if (rdev == NULL) 3554414c70cbSLiam Girdwood return; 3555414c70cbSLiam Girdwood 3556891636eaSMark Brown if (rdev->supply) { 3557891636eaSMark Brown while (rdev->use_count--) 3558891636eaSMark Brown regulator_disable(rdev->supply); 3559e032b376SMark Brown regulator_put(rdev->supply); 3560891636eaSMark Brown } 3561414c70cbSLiam Girdwood mutex_lock(®ulator_list_mutex); 35621130e5b3SMark Brown debugfs_remove_recursive(rdev->debugfs); 356343829731STejun Heo flush_work(&rdev->disable_work.work); 35646bf87d17SMark Brown WARN_ON(rdev->open_count); 35650f1d747bSMike Rapoport unset_regulator_supplies(rdev); 3566414c70cbSLiam Girdwood list_del(&rdev->list); 3567f8c12fe3SMark Brown kfree(rdev->constraints); 3568f19b00daSKim, Milo regulator_ena_gpio_free(rdev); 356958fb5cf5SLothar Waßmann device_unregister(&rdev->dev); 3570414c70cbSLiam Girdwood mutex_unlock(®ulator_list_mutex); 3571414c70cbSLiam Girdwood } 3572414c70cbSLiam Girdwood EXPORT_SYMBOL_GPL(regulator_unregister); 3573414c70cbSLiam Girdwood 3574414c70cbSLiam Girdwood /** 3575cf7bbcdfSMark Brown * regulator_suspend_prepare - prepare regulators for system wide suspend 3576414c70cbSLiam Girdwood * @state: system suspend state 3577414c70cbSLiam Girdwood * 3578414c70cbSLiam Girdwood * Configure each regulator with it's suspend operating parameters for state. 3579414c70cbSLiam Girdwood * This will usually be called by machine suspend code prior to supending. 3580414c70cbSLiam Girdwood */ 3581414c70cbSLiam Girdwood int regulator_suspend_prepare(suspend_state_t state) 3582414c70cbSLiam Girdwood { 3583414c70cbSLiam Girdwood struct regulator_dev *rdev; 3584414c70cbSLiam Girdwood int ret = 0; 3585414c70cbSLiam Girdwood 3586414c70cbSLiam Girdwood /* ON is handled by regulator active state */ 3587414c70cbSLiam Girdwood if (state == PM_SUSPEND_ON) 3588414c70cbSLiam Girdwood return -EINVAL; 3589414c70cbSLiam Girdwood 3590414c70cbSLiam Girdwood mutex_lock(®ulator_list_mutex); 3591414c70cbSLiam Girdwood list_for_each_entry(rdev, ®ulator_list, list) { 3592414c70cbSLiam Girdwood 3593414c70cbSLiam Girdwood mutex_lock(&rdev->mutex); 3594414c70cbSLiam Girdwood ret = suspend_prepare(rdev, state); 3595414c70cbSLiam Girdwood mutex_unlock(&rdev->mutex); 3596414c70cbSLiam Girdwood 3597414c70cbSLiam Girdwood if (ret < 0) { 35985da84fd9SJoe Perches rdev_err(rdev, "failed to prepare\n"); 3599414c70cbSLiam Girdwood goto out; 3600414c70cbSLiam Girdwood } 3601414c70cbSLiam Girdwood } 3602414c70cbSLiam Girdwood out: 3603414c70cbSLiam Girdwood mutex_unlock(®ulator_list_mutex); 3604414c70cbSLiam Girdwood return ret; 3605414c70cbSLiam Girdwood } 3606414c70cbSLiam Girdwood EXPORT_SYMBOL_GPL(regulator_suspend_prepare); 3607414c70cbSLiam Girdwood 3608414c70cbSLiam Girdwood /** 36097a32b589SMyungJoo Ham * regulator_suspend_finish - resume regulators from system wide suspend 36107a32b589SMyungJoo Ham * 36117a32b589SMyungJoo Ham * Turn on regulators that might be turned off by regulator_suspend_prepare 36127a32b589SMyungJoo Ham * and that should be turned on according to the regulators properties. 36137a32b589SMyungJoo Ham */ 36147a32b589SMyungJoo Ham int regulator_suspend_finish(void) 36157a32b589SMyungJoo Ham { 36167a32b589SMyungJoo Ham struct regulator_dev *rdev; 36177a32b589SMyungJoo Ham int ret = 0, error; 36187a32b589SMyungJoo Ham 36197a32b589SMyungJoo Ham mutex_lock(®ulator_list_mutex); 36207a32b589SMyungJoo Ham list_for_each_entry(rdev, ®ulator_list, list) { 36217a32b589SMyungJoo Ham struct regulator_ops *ops = rdev->desc->ops; 36227a32b589SMyungJoo Ham 36237a32b589SMyungJoo Ham mutex_lock(&rdev->mutex); 36247a32b589SMyungJoo Ham if ((rdev->use_count > 0 || rdev->constraints->always_on) && 36257a32b589SMyungJoo Ham ops->enable) { 36267a32b589SMyungJoo Ham error = ops->enable(rdev); 36277a32b589SMyungJoo Ham if (error) 36287a32b589SMyungJoo Ham ret = error; 36297a32b589SMyungJoo Ham } else { 36307a32b589SMyungJoo Ham if (!has_full_constraints) 36317a32b589SMyungJoo Ham goto unlock; 36327a32b589SMyungJoo Ham if (!ops->disable) 36337a32b589SMyungJoo Ham goto unlock; 3634b1a86831SMark Brown if (!_regulator_is_enabled(rdev)) 36357a32b589SMyungJoo Ham goto unlock; 36367a32b589SMyungJoo Ham 36377a32b589SMyungJoo Ham error = ops->disable(rdev); 36387a32b589SMyungJoo Ham if (error) 36397a32b589SMyungJoo Ham ret = error; 36407a32b589SMyungJoo Ham } 36417a32b589SMyungJoo Ham unlock: 36427a32b589SMyungJoo Ham mutex_unlock(&rdev->mutex); 36437a32b589SMyungJoo Ham } 36447a32b589SMyungJoo Ham mutex_unlock(®ulator_list_mutex); 36457a32b589SMyungJoo Ham return ret; 36467a32b589SMyungJoo Ham } 36477a32b589SMyungJoo Ham EXPORT_SYMBOL_GPL(regulator_suspend_finish); 36487a32b589SMyungJoo Ham 36497a32b589SMyungJoo Ham /** 3650ca725561SMark Brown * regulator_has_full_constraints - the system has fully specified constraints 3651ca725561SMark Brown * 3652ca725561SMark Brown * Calling this function will cause the regulator API to disable all 3653ca725561SMark Brown * regulators which have a zero use count and don't have an always_on 3654ca725561SMark Brown * constraint in a late_initcall. 3655ca725561SMark Brown * 3656ca725561SMark Brown * The intention is that this will become the default behaviour in a 3657ca725561SMark Brown * future kernel release so users are encouraged to use this facility 3658ca725561SMark Brown * now. 3659ca725561SMark Brown */ 3660ca725561SMark Brown void regulator_has_full_constraints(void) 3661ca725561SMark Brown { 3662ca725561SMark Brown has_full_constraints = 1; 3663ca725561SMark Brown } 3664ca725561SMark Brown EXPORT_SYMBOL_GPL(regulator_has_full_constraints); 3665ca725561SMark Brown 3666ca725561SMark Brown /** 3667414c70cbSLiam Girdwood * rdev_get_drvdata - get rdev regulator driver data 366869279fb9SMark Brown * @rdev: regulator 3669414c70cbSLiam Girdwood * 3670414c70cbSLiam Girdwood * Get rdev regulator driver private data. This call can be used in the 3671414c70cbSLiam Girdwood * regulator driver context. 3672414c70cbSLiam Girdwood */ 3673414c70cbSLiam Girdwood void *rdev_get_drvdata(struct regulator_dev *rdev) 3674414c70cbSLiam Girdwood { 3675414c70cbSLiam Girdwood return rdev->reg_data; 3676414c70cbSLiam Girdwood } 3677414c70cbSLiam Girdwood EXPORT_SYMBOL_GPL(rdev_get_drvdata); 3678414c70cbSLiam Girdwood 3679414c70cbSLiam Girdwood /** 3680414c70cbSLiam Girdwood * regulator_get_drvdata - get regulator driver data 3681414c70cbSLiam Girdwood * @regulator: regulator 3682414c70cbSLiam Girdwood * 3683414c70cbSLiam Girdwood * Get regulator driver private data. This call can be used in the consumer 3684414c70cbSLiam Girdwood * driver context when non API regulator specific functions need to be called. 3685414c70cbSLiam Girdwood */ 3686414c70cbSLiam Girdwood void *regulator_get_drvdata(struct regulator *regulator) 3687414c70cbSLiam Girdwood { 3688414c70cbSLiam Girdwood return regulator->rdev->reg_data; 3689414c70cbSLiam Girdwood } 3690414c70cbSLiam Girdwood EXPORT_SYMBOL_GPL(regulator_get_drvdata); 3691414c70cbSLiam Girdwood 3692414c70cbSLiam Girdwood /** 3693414c70cbSLiam Girdwood * regulator_set_drvdata - set regulator driver data 3694414c70cbSLiam Girdwood * @regulator: regulator 3695414c70cbSLiam Girdwood * @data: data 3696414c70cbSLiam Girdwood */ 3697414c70cbSLiam Girdwood void regulator_set_drvdata(struct regulator *regulator, void *data) 3698414c70cbSLiam Girdwood { 3699414c70cbSLiam Girdwood regulator->rdev->reg_data = data; 3700414c70cbSLiam Girdwood } 3701414c70cbSLiam Girdwood EXPORT_SYMBOL_GPL(regulator_set_drvdata); 3702414c70cbSLiam Girdwood 3703414c70cbSLiam Girdwood /** 3704414c70cbSLiam Girdwood * regulator_get_id - get regulator ID 370569279fb9SMark Brown * @rdev: regulator 3706414c70cbSLiam Girdwood */ 3707414c70cbSLiam Girdwood int rdev_get_id(struct regulator_dev *rdev) 3708414c70cbSLiam Girdwood { 3709414c70cbSLiam Girdwood return rdev->desc->id; 3710414c70cbSLiam Girdwood } 3711414c70cbSLiam Girdwood EXPORT_SYMBOL_GPL(rdev_get_id); 3712414c70cbSLiam Girdwood 3713a5766f11SLiam Girdwood struct device *rdev_get_dev(struct regulator_dev *rdev) 3714a5766f11SLiam Girdwood { 3715a5766f11SLiam Girdwood return &rdev->dev; 3716a5766f11SLiam Girdwood } 3717a5766f11SLiam Girdwood EXPORT_SYMBOL_GPL(rdev_get_dev); 3718a5766f11SLiam Girdwood 3719a5766f11SLiam Girdwood void *regulator_get_init_drvdata(struct regulator_init_data *reg_init_data) 3720a5766f11SLiam Girdwood { 3721a5766f11SLiam Girdwood return reg_init_data->driver_data; 3722a5766f11SLiam Girdwood } 3723a5766f11SLiam Girdwood EXPORT_SYMBOL_GPL(regulator_get_init_drvdata); 3724a5766f11SLiam Girdwood 3725ba55a974SMark Brown #ifdef CONFIG_DEBUG_FS 3726ba55a974SMark Brown static ssize_t supply_map_read_file(struct file *file, char __user *user_buf, 3727ba55a974SMark Brown size_t count, loff_t *ppos) 3728ba55a974SMark Brown { 3729ba55a974SMark Brown char *buf = kmalloc(PAGE_SIZE, GFP_KERNEL); 3730ba55a974SMark Brown ssize_t len, ret = 0; 3731ba55a974SMark Brown struct regulator_map *map; 3732ba55a974SMark Brown 3733ba55a974SMark Brown if (!buf) 3734ba55a974SMark Brown return -ENOMEM; 3735ba55a974SMark Brown 3736ba55a974SMark Brown list_for_each_entry(map, ®ulator_map_list, list) { 3737ba55a974SMark Brown len = snprintf(buf + ret, PAGE_SIZE - ret, 3738ba55a974SMark Brown "%s -> %s.%s\n", 3739ba55a974SMark Brown rdev_get_name(map->regulator), map->dev_name, 3740ba55a974SMark Brown map->supply); 3741ba55a974SMark Brown if (len >= 0) 3742ba55a974SMark Brown ret += len; 3743ba55a974SMark Brown if (ret > PAGE_SIZE) { 3744ba55a974SMark Brown ret = PAGE_SIZE; 3745ba55a974SMark Brown break; 3746ba55a974SMark Brown } 3747ba55a974SMark Brown } 3748ba55a974SMark Brown 3749ba55a974SMark Brown ret = simple_read_from_buffer(user_buf, count, ppos, buf, ret); 3750ba55a974SMark Brown 3751ba55a974SMark Brown kfree(buf); 3752ba55a974SMark Brown 3753ba55a974SMark Brown return ret; 3754ba55a974SMark Brown } 375524751434SStephen Boyd #endif 3756ba55a974SMark Brown 3757ba55a974SMark Brown static const struct file_operations supply_map_fops = { 375824751434SStephen Boyd #ifdef CONFIG_DEBUG_FS 3759ba55a974SMark Brown .read = supply_map_read_file, 3760ba55a974SMark Brown .llseek = default_llseek, 3761ba55a974SMark Brown #endif 376224751434SStephen Boyd }; 3763ba55a974SMark Brown 3764414c70cbSLiam Girdwood static int __init regulator_init(void) 3765414c70cbSLiam Girdwood { 376634abbd68SMark Brown int ret; 376734abbd68SMark Brown 376834abbd68SMark Brown ret = class_register(®ulator_class); 376934abbd68SMark Brown 37701130e5b3SMark Brown debugfs_root = debugfs_create_dir("regulator", NULL); 377124751434SStephen Boyd if (!debugfs_root) 37721130e5b3SMark Brown pr_warn("regulator: Failed to create debugfs directory\n"); 3773ba55a974SMark Brown 3774f4d562c6SMark Brown debugfs_create_file("supply_map", 0444, debugfs_root, NULL, 3775f4d562c6SMark Brown &supply_map_fops); 37761130e5b3SMark Brown 377734abbd68SMark Brown regulator_dummy_init(); 377834abbd68SMark Brown 377934abbd68SMark Brown return ret; 3780414c70cbSLiam Girdwood } 3781414c70cbSLiam Girdwood 3782414c70cbSLiam Girdwood /* init early to allow our consumers to complete system booting */ 3783414c70cbSLiam Girdwood core_initcall(regulator_init); 3784ca725561SMark Brown 3785ca725561SMark Brown static int __init regulator_init_complete(void) 3786ca725561SMark Brown { 3787ca725561SMark Brown struct regulator_dev *rdev; 3788ca725561SMark Brown struct regulator_ops *ops; 3789ca725561SMark Brown struct regulation_constraints *c; 3790ca725561SMark Brown int enabled, ret; 3791ca725561SMark Brown 379286f5fcfcSMark Brown /* 379386f5fcfcSMark Brown * Since DT doesn't provide an idiomatic mechanism for 379486f5fcfcSMark Brown * enabling full constraints and since it's much more natural 379586f5fcfcSMark Brown * with DT to provide them just assume that a DT enabled 379686f5fcfcSMark Brown * system has full constraints. 379786f5fcfcSMark Brown */ 379886f5fcfcSMark Brown if (of_have_populated_dt()) 379986f5fcfcSMark Brown has_full_constraints = true; 380086f5fcfcSMark Brown 3801ca725561SMark Brown mutex_lock(®ulator_list_mutex); 3802ca725561SMark Brown 3803ca725561SMark Brown /* If we have a full configuration then disable any regulators 3804ca725561SMark Brown * which are not in use or always_on. This will become the 3805ca725561SMark Brown * default behaviour in the future. 3806ca725561SMark Brown */ 3807ca725561SMark Brown list_for_each_entry(rdev, ®ulator_list, list) { 3808ca725561SMark Brown ops = rdev->desc->ops; 3809ca725561SMark Brown c = rdev->constraints; 3810ca725561SMark Brown 3811f25e0b4fSMark Brown if (!ops->disable || (c && c->always_on)) 3812ca725561SMark Brown continue; 3813ca725561SMark Brown 3814ca725561SMark Brown mutex_lock(&rdev->mutex); 3815ca725561SMark Brown 3816ca725561SMark Brown if (rdev->use_count) 3817ca725561SMark Brown goto unlock; 3818ca725561SMark Brown 3819ca725561SMark Brown /* If we can't read the status assume it's on. */ 3820ca725561SMark Brown if (ops->is_enabled) 3821ca725561SMark Brown enabled = ops->is_enabled(rdev); 3822ca725561SMark Brown else 3823ca725561SMark Brown enabled = 1; 3824ca725561SMark Brown 3825ca725561SMark Brown if (!enabled) 3826ca725561SMark Brown goto unlock; 3827ca725561SMark Brown 3828ca725561SMark Brown if (has_full_constraints) { 3829ca725561SMark Brown /* We log since this may kill the system if it 3830ca725561SMark Brown * goes wrong. */ 38315da84fd9SJoe Perches rdev_info(rdev, "disabling\n"); 3832ca725561SMark Brown ret = ops->disable(rdev); 3833ca725561SMark Brown if (ret != 0) { 38345da84fd9SJoe Perches rdev_err(rdev, "couldn't disable: %d\n", ret); 3835ca725561SMark Brown } 3836ca725561SMark Brown } else { 3837ca725561SMark Brown /* The intention is that in future we will 3838ca725561SMark Brown * assume that full constraints are provided 3839ca725561SMark Brown * so warn even if we aren't going to do 3840ca725561SMark Brown * anything here. 3841ca725561SMark Brown */ 38425da84fd9SJoe Perches rdev_warn(rdev, "incomplete constraints, leaving on\n"); 3843ca725561SMark Brown } 3844ca725561SMark Brown 3845ca725561SMark Brown unlock: 3846ca725561SMark Brown mutex_unlock(&rdev->mutex); 3847ca725561SMark Brown } 3848ca725561SMark Brown 3849ca725561SMark Brown mutex_unlock(®ulator_list_mutex); 3850ca725561SMark Brown 3851ca725561SMark Brown return 0; 3852ca725561SMark Brown } 3853ca725561SMark Brown late_initcall(regulator_init_complete); 3854