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" 3934abbd68SMark Brown 407d51a0dbSMark Brown #define rdev_crit(rdev, fmt, ...) \ 417d51a0dbSMark Brown pr_crit("%s: " fmt, rdev_get_name(rdev), ##__VA_ARGS__) 425da84fd9SJoe Perches #define rdev_err(rdev, fmt, ...) \ 435da84fd9SJoe Perches pr_err("%s: " fmt, rdev_get_name(rdev), ##__VA_ARGS__) 445da84fd9SJoe Perches #define rdev_warn(rdev, fmt, ...) \ 455da84fd9SJoe Perches pr_warn("%s: " fmt, rdev_get_name(rdev), ##__VA_ARGS__) 465da84fd9SJoe Perches #define rdev_info(rdev, fmt, ...) \ 475da84fd9SJoe Perches pr_info("%s: " fmt, rdev_get_name(rdev), ##__VA_ARGS__) 485da84fd9SJoe Perches #define rdev_dbg(rdev, fmt, ...) \ 495da84fd9SJoe Perches pr_debug("%s: " fmt, rdev_get_name(rdev), ##__VA_ARGS__) 505da84fd9SJoe Perches 51414c70cbSLiam Girdwood static DEFINE_MUTEX(regulator_list_mutex); 52414c70cbSLiam Girdwood static LIST_HEAD(regulator_list); 53414c70cbSLiam Girdwood static LIST_HEAD(regulator_map_list); 5421cf891aSMark Brown static bool has_full_constraints; 55688fe99aSMark Brown static bool board_wants_dummy_regulator; 56414c70cbSLiam Girdwood 571130e5b3SMark Brown static struct dentry *debugfs_root; 581130e5b3SMark Brown 598dc5390dSMark Brown /* 60414c70cbSLiam Girdwood * struct regulator_map 61414c70cbSLiam Girdwood * 62414c70cbSLiam Girdwood * Used to provide symbolic supply names to devices. 63414c70cbSLiam Girdwood */ 64414c70cbSLiam Girdwood struct regulator_map { 65414c70cbSLiam Girdwood struct list_head list; 6640f9244fSMark Brown const char *dev_name; /* The dev_name() for the consumer */ 67414c70cbSLiam Girdwood const char *supply; 68a5766f11SLiam Girdwood struct regulator_dev *regulator; 69414c70cbSLiam Girdwood }; 70414c70cbSLiam Girdwood 71414c70cbSLiam Girdwood /* 72414c70cbSLiam Girdwood * struct regulator 73414c70cbSLiam Girdwood * 74414c70cbSLiam Girdwood * One for each consumer device. 75414c70cbSLiam Girdwood */ 76414c70cbSLiam Girdwood struct regulator { 77414c70cbSLiam Girdwood struct device *dev; 78414c70cbSLiam Girdwood struct list_head list; 796492bc1bSMark Brown unsigned int always_on:1; 80f59c8f9fSMark Brown unsigned int bypass:1; 81414c70cbSLiam Girdwood int uA_load; 82414c70cbSLiam Girdwood int min_uV; 83414c70cbSLiam Girdwood int max_uV; 84414c70cbSLiam Girdwood char *supply_name; 85414c70cbSLiam Girdwood struct device_attribute dev_attr; 86414c70cbSLiam Girdwood struct regulator_dev *rdev; 875de70519SMark Brown struct dentry *debugfs; 88414c70cbSLiam Girdwood }; 89414c70cbSLiam Girdwood 90414c70cbSLiam Girdwood static int _regulator_is_enabled(struct regulator_dev *rdev); 913801b86aSMark Brown static int _regulator_disable(struct regulator_dev *rdev); 92414c70cbSLiam Girdwood static int _regulator_get_voltage(struct regulator_dev *rdev); 93414c70cbSLiam Girdwood static int _regulator_get_current_limit(struct regulator_dev *rdev); 94414c70cbSLiam Girdwood static unsigned int _regulator_get_mode(struct regulator_dev *rdev); 95414c70cbSLiam Girdwood static void _notifier_call_chain(struct regulator_dev *rdev, 96414c70cbSLiam Girdwood unsigned long event, void *data); 9775790251SMark Brown static int _regulator_do_set_voltage(struct regulator_dev *rdev, 9875790251SMark Brown int min_uV, int max_uV); 993801b86aSMark Brown static struct regulator *create_regulator(struct regulator_dev *rdev, 1003801b86aSMark Brown struct device *dev, 1013801b86aSMark Brown const char *supply_name); 102414c70cbSLiam Girdwood 1031083c393SMark Brown static const char *rdev_get_name(struct regulator_dev *rdev) 1041083c393SMark Brown { 1051083c393SMark Brown if (rdev->constraints && rdev->constraints->name) 1061083c393SMark Brown return rdev->constraints->name; 1071083c393SMark Brown else if (rdev->desc->name) 1081083c393SMark Brown return rdev->desc->name; 1091083c393SMark Brown else 1101083c393SMark Brown return ""; 1111083c393SMark Brown } 1121083c393SMark Brown 11369511a45SRajendra Nayak /** 11469511a45SRajendra Nayak * of_get_regulator - get a regulator device node based on supply name 11569511a45SRajendra Nayak * @dev: Device pointer for the consumer (of regulator) device 11669511a45SRajendra Nayak * @supply: regulator supply name 11769511a45SRajendra Nayak * 11869511a45SRajendra Nayak * Extract the regulator device node corresponding to the supply name. 11969511a45SRajendra Nayak * retruns the device node corresponding to the regulator if found, else 12069511a45SRajendra Nayak * returns NULL. 12169511a45SRajendra Nayak */ 12269511a45SRajendra Nayak static struct device_node *of_get_regulator(struct device *dev, const char *supply) 12369511a45SRajendra Nayak { 12469511a45SRajendra Nayak struct device_node *regnode = NULL; 12569511a45SRajendra Nayak char prop_name[32]; /* 32 is max size of property name */ 12669511a45SRajendra Nayak 12769511a45SRajendra Nayak dev_dbg(dev, "Looking up %s-supply from device tree\n", supply); 12869511a45SRajendra Nayak 12969511a45SRajendra Nayak snprintf(prop_name, 32, "%s-supply", supply); 13069511a45SRajendra Nayak regnode = of_parse_phandle(dev->of_node, prop_name, 0); 13169511a45SRajendra Nayak 13269511a45SRajendra Nayak if (!regnode) { 13316fbcc3bSRajendra Nayak dev_dbg(dev, "Looking up %s property in node %s failed", 13469511a45SRajendra Nayak prop_name, dev->of_node->full_name); 13569511a45SRajendra Nayak return NULL; 13669511a45SRajendra Nayak } 13769511a45SRajendra Nayak return regnode; 13869511a45SRajendra Nayak } 13969511a45SRajendra Nayak 1406492bc1bSMark Brown static int _regulator_can_change_status(struct regulator_dev *rdev) 1416492bc1bSMark Brown { 1426492bc1bSMark Brown if (!rdev->constraints) 1436492bc1bSMark Brown return 0; 1446492bc1bSMark Brown 1456492bc1bSMark Brown if (rdev->constraints->valid_ops_mask & REGULATOR_CHANGE_STATUS) 1466492bc1bSMark Brown return 1; 1476492bc1bSMark Brown else 1486492bc1bSMark Brown return 0; 1496492bc1bSMark Brown } 1506492bc1bSMark Brown 151414c70cbSLiam Girdwood /* Platform voltage constraint check */ 152414c70cbSLiam Girdwood static int regulator_check_voltage(struct regulator_dev *rdev, 153414c70cbSLiam Girdwood int *min_uV, int *max_uV) 154414c70cbSLiam Girdwood { 155414c70cbSLiam Girdwood BUG_ON(*min_uV > *max_uV); 156414c70cbSLiam Girdwood 157414c70cbSLiam Girdwood if (!rdev->constraints) { 1585da84fd9SJoe Perches rdev_err(rdev, "no constraints\n"); 159414c70cbSLiam Girdwood return -ENODEV; 160414c70cbSLiam Girdwood } 161414c70cbSLiam Girdwood if (!(rdev->constraints->valid_ops_mask & REGULATOR_CHANGE_VOLTAGE)) { 1625da84fd9SJoe Perches rdev_err(rdev, "operation not allowed\n"); 163414c70cbSLiam Girdwood return -EPERM; 164414c70cbSLiam Girdwood } 165414c70cbSLiam Girdwood 166414c70cbSLiam Girdwood if (*max_uV > rdev->constraints->max_uV) 167414c70cbSLiam Girdwood *max_uV = rdev->constraints->max_uV; 168414c70cbSLiam Girdwood if (*min_uV < rdev->constraints->min_uV) 169414c70cbSLiam Girdwood *min_uV = rdev->constraints->min_uV; 170414c70cbSLiam Girdwood 17189f425edSMark Brown if (*min_uV > *max_uV) { 17289f425edSMark Brown rdev_err(rdev, "unsupportable voltage range: %d-%duV\n", 17354abd335SMark Brown *min_uV, *max_uV); 174414c70cbSLiam Girdwood return -EINVAL; 17589f425edSMark Brown } 176414c70cbSLiam Girdwood 177414c70cbSLiam Girdwood return 0; 178414c70cbSLiam Girdwood } 179414c70cbSLiam Girdwood 18005fda3b1SThomas Petazzoni /* Make sure we select a voltage that suits the needs of all 18105fda3b1SThomas Petazzoni * regulator consumers 18205fda3b1SThomas Petazzoni */ 18305fda3b1SThomas Petazzoni static int regulator_check_consumers(struct regulator_dev *rdev, 18405fda3b1SThomas Petazzoni int *min_uV, int *max_uV) 18505fda3b1SThomas Petazzoni { 18605fda3b1SThomas Petazzoni struct regulator *regulator; 18705fda3b1SThomas Petazzoni 18805fda3b1SThomas Petazzoni list_for_each_entry(regulator, &rdev->consumer_list, list) { 1894aa922c0SMark Brown /* 1904aa922c0SMark Brown * Assume consumers that didn't say anything are OK 1914aa922c0SMark Brown * with anything in the constraint range. 1924aa922c0SMark Brown */ 1934aa922c0SMark Brown if (!regulator->min_uV && !regulator->max_uV) 1944aa922c0SMark Brown continue; 1954aa922c0SMark Brown 19605fda3b1SThomas Petazzoni if (*max_uV > regulator->max_uV) 19705fda3b1SThomas Petazzoni *max_uV = regulator->max_uV; 19805fda3b1SThomas Petazzoni if (*min_uV < regulator->min_uV) 19905fda3b1SThomas Petazzoni *min_uV = regulator->min_uV; 20005fda3b1SThomas Petazzoni } 20105fda3b1SThomas Petazzoni 20205fda3b1SThomas Petazzoni if (*min_uV > *max_uV) 20305fda3b1SThomas Petazzoni return -EINVAL; 20405fda3b1SThomas Petazzoni 20505fda3b1SThomas Petazzoni return 0; 20605fda3b1SThomas Petazzoni } 20705fda3b1SThomas Petazzoni 208414c70cbSLiam Girdwood /* current constraint check */ 209414c70cbSLiam Girdwood static int regulator_check_current_limit(struct regulator_dev *rdev, 210414c70cbSLiam Girdwood int *min_uA, int *max_uA) 211414c70cbSLiam Girdwood { 212414c70cbSLiam Girdwood BUG_ON(*min_uA > *max_uA); 213414c70cbSLiam Girdwood 214414c70cbSLiam Girdwood if (!rdev->constraints) { 2155da84fd9SJoe Perches rdev_err(rdev, "no constraints\n"); 216414c70cbSLiam Girdwood return -ENODEV; 217414c70cbSLiam Girdwood } 218414c70cbSLiam Girdwood if (!(rdev->constraints->valid_ops_mask & REGULATOR_CHANGE_CURRENT)) { 2195da84fd9SJoe Perches rdev_err(rdev, "operation not allowed\n"); 220414c70cbSLiam Girdwood return -EPERM; 221414c70cbSLiam Girdwood } 222414c70cbSLiam Girdwood 223414c70cbSLiam Girdwood if (*max_uA > rdev->constraints->max_uA) 224414c70cbSLiam Girdwood *max_uA = rdev->constraints->max_uA; 225414c70cbSLiam Girdwood if (*min_uA < rdev->constraints->min_uA) 226414c70cbSLiam Girdwood *min_uA = rdev->constraints->min_uA; 227414c70cbSLiam Girdwood 22889f425edSMark Brown if (*min_uA > *max_uA) { 22989f425edSMark Brown rdev_err(rdev, "unsupportable current range: %d-%duA\n", 23054abd335SMark Brown *min_uA, *max_uA); 231414c70cbSLiam Girdwood return -EINVAL; 23289f425edSMark Brown } 233414c70cbSLiam Girdwood 234414c70cbSLiam Girdwood return 0; 235414c70cbSLiam Girdwood } 236414c70cbSLiam Girdwood 237414c70cbSLiam Girdwood /* operating mode constraint check */ 2382c608234SMark Brown static int regulator_mode_constrain(struct regulator_dev *rdev, int *mode) 239414c70cbSLiam Girdwood { 2402c608234SMark Brown switch (*mode) { 241e573520bSDavid Brownell case REGULATOR_MODE_FAST: 242e573520bSDavid Brownell case REGULATOR_MODE_NORMAL: 243e573520bSDavid Brownell case REGULATOR_MODE_IDLE: 244e573520bSDavid Brownell case REGULATOR_MODE_STANDBY: 245e573520bSDavid Brownell break; 246e573520bSDavid Brownell default: 24789f425edSMark Brown rdev_err(rdev, "invalid mode %x specified\n", *mode); 248e573520bSDavid Brownell return -EINVAL; 249e573520bSDavid Brownell } 250e573520bSDavid Brownell 251414c70cbSLiam Girdwood if (!rdev->constraints) { 2525da84fd9SJoe Perches rdev_err(rdev, "no constraints\n"); 253414c70cbSLiam Girdwood return -ENODEV; 254414c70cbSLiam Girdwood } 255414c70cbSLiam Girdwood if (!(rdev->constraints->valid_ops_mask & REGULATOR_CHANGE_MODE)) { 2565da84fd9SJoe Perches rdev_err(rdev, "operation not allowed\n"); 257414c70cbSLiam Girdwood return -EPERM; 258414c70cbSLiam Girdwood } 2592c608234SMark Brown 2602c608234SMark Brown /* The modes are bitmasks, the most power hungry modes having 2612c608234SMark Brown * the lowest values. If the requested mode isn't supported 2622c608234SMark Brown * try higher modes. */ 2632c608234SMark Brown while (*mode) { 2642c608234SMark Brown if (rdev->constraints->valid_modes_mask & *mode) 265414c70cbSLiam Girdwood return 0; 2662c608234SMark Brown *mode /= 2; 2672c608234SMark Brown } 2682c608234SMark Brown 2692c608234SMark Brown return -EINVAL; 270414c70cbSLiam Girdwood } 271414c70cbSLiam Girdwood 272414c70cbSLiam Girdwood /* dynamic regulator mode switching constraint check */ 273414c70cbSLiam Girdwood static int regulator_check_drms(struct regulator_dev *rdev) 274414c70cbSLiam Girdwood { 275414c70cbSLiam Girdwood if (!rdev->constraints) { 2765da84fd9SJoe Perches rdev_err(rdev, "no constraints\n"); 277414c70cbSLiam Girdwood return -ENODEV; 278414c70cbSLiam Girdwood } 279414c70cbSLiam Girdwood if (!(rdev->constraints->valid_ops_mask & REGULATOR_CHANGE_DRMS)) { 2805da84fd9SJoe Perches rdev_err(rdev, "operation not allowed\n"); 281414c70cbSLiam Girdwood return -EPERM; 282414c70cbSLiam Girdwood } 283414c70cbSLiam Girdwood return 0; 284414c70cbSLiam Girdwood } 285414c70cbSLiam Girdwood 286414c70cbSLiam Girdwood static ssize_t regulator_uV_show(struct device *dev, 287414c70cbSLiam Girdwood struct device_attribute *attr, char *buf) 288414c70cbSLiam Girdwood { 289a5766f11SLiam Girdwood struct regulator_dev *rdev = dev_get_drvdata(dev); 290414c70cbSLiam Girdwood ssize_t ret; 291414c70cbSLiam Girdwood 292414c70cbSLiam Girdwood mutex_lock(&rdev->mutex); 293414c70cbSLiam Girdwood ret = sprintf(buf, "%d\n", _regulator_get_voltage(rdev)); 294414c70cbSLiam Girdwood mutex_unlock(&rdev->mutex); 295414c70cbSLiam Girdwood 296414c70cbSLiam Girdwood return ret; 297414c70cbSLiam Girdwood } 2987ad68e2fSDavid Brownell static DEVICE_ATTR(microvolts, 0444, regulator_uV_show, NULL); 299414c70cbSLiam Girdwood 300414c70cbSLiam Girdwood static ssize_t regulator_uA_show(struct device *dev, 301414c70cbSLiam Girdwood struct device_attribute *attr, char *buf) 302414c70cbSLiam Girdwood { 303a5766f11SLiam Girdwood struct regulator_dev *rdev = dev_get_drvdata(dev); 304414c70cbSLiam Girdwood 305414c70cbSLiam Girdwood return sprintf(buf, "%d\n", _regulator_get_current_limit(rdev)); 306414c70cbSLiam Girdwood } 3077ad68e2fSDavid Brownell static DEVICE_ATTR(microamps, 0444, regulator_uA_show, NULL); 308414c70cbSLiam Girdwood 309bc558a60SMark Brown static ssize_t regulator_name_show(struct device *dev, 310bc558a60SMark Brown struct device_attribute *attr, char *buf) 311bc558a60SMark Brown { 312bc558a60SMark Brown struct regulator_dev *rdev = dev_get_drvdata(dev); 313bc558a60SMark Brown 3141083c393SMark Brown return sprintf(buf, "%s\n", rdev_get_name(rdev)); 315bc558a60SMark Brown } 316bc558a60SMark Brown 3174fca9545SDavid Brownell static ssize_t regulator_print_opmode(char *buf, int mode) 318414c70cbSLiam Girdwood { 319414c70cbSLiam Girdwood switch (mode) { 320414c70cbSLiam Girdwood case REGULATOR_MODE_FAST: 321414c70cbSLiam Girdwood return sprintf(buf, "fast\n"); 322414c70cbSLiam Girdwood case REGULATOR_MODE_NORMAL: 323414c70cbSLiam Girdwood return sprintf(buf, "normal\n"); 324414c70cbSLiam Girdwood case REGULATOR_MODE_IDLE: 325414c70cbSLiam Girdwood return sprintf(buf, "idle\n"); 326414c70cbSLiam Girdwood case REGULATOR_MODE_STANDBY: 327414c70cbSLiam Girdwood return sprintf(buf, "standby\n"); 328414c70cbSLiam Girdwood } 329414c70cbSLiam Girdwood return sprintf(buf, "unknown\n"); 330414c70cbSLiam Girdwood } 331414c70cbSLiam Girdwood 3324fca9545SDavid Brownell static ssize_t regulator_opmode_show(struct device *dev, 333414c70cbSLiam Girdwood struct device_attribute *attr, char *buf) 334414c70cbSLiam Girdwood { 335a5766f11SLiam Girdwood struct regulator_dev *rdev = dev_get_drvdata(dev); 336414c70cbSLiam Girdwood 3374fca9545SDavid Brownell return regulator_print_opmode(buf, _regulator_get_mode(rdev)); 3384fca9545SDavid Brownell } 3397ad68e2fSDavid Brownell static DEVICE_ATTR(opmode, 0444, regulator_opmode_show, NULL); 3404fca9545SDavid Brownell 3414fca9545SDavid Brownell static ssize_t regulator_print_state(char *buf, int state) 3424fca9545SDavid Brownell { 343414c70cbSLiam Girdwood if (state > 0) 344414c70cbSLiam Girdwood return sprintf(buf, "enabled\n"); 345414c70cbSLiam Girdwood else if (state == 0) 346414c70cbSLiam Girdwood return sprintf(buf, "disabled\n"); 347414c70cbSLiam Girdwood else 348414c70cbSLiam Girdwood return sprintf(buf, "unknown\n"); 349414c70cbSLiam Girdwood } 350414c70cbSLiam Girdwood 3514fca9545SDavid Brownell static ssize_t regulator_state_show(struct device *dev, 3524fca9545SDavid Brownell struct device_attribute *attr, char *buf) 3534fca9545SDavid Brownell { 3544fca9545SDavid Brownell struct regulator_dev *rdev = dev_get_drvdata(dev); 3559332546fSMark Brown ssize_t ret; 3564fca9545SDavid Brownell 3579332546fSMark Brown mutex_lock(&rdev->mutex); 3589332546fSMark Brown ret = regulator_print_state(buf, _regulator_is_enabled(rdev)); 3599332546fSMark Brown mutex_unlock(&rdev->mutex); 3609332546fSMark Brown 3619332546fSMark Brown return ret; 3624fca9545SDavid Brownell } 3637ad68e2fSDavid Brownell static DEVICE_ATTR(state, 0444, regulator_state_show, NULL); 3644fca9545SDavid Brownell 365853116a1SDavid Brownell static ssize_t regulator_status_show(struct device *dev, 366853116a1SDavid Brownell struct device_attribute *attr, char *buf) 367853116a1SDavid Brownell { 368853116a1SDavid Brownell struct regulator_dev *rdev = dev_get_drvdata(dev); 369853116a1SDavid Brownell int status; 370853116a1SDavid Brownell char *label; 371853116a1SDavid Brownell 372853116a1SDavid Brownell status = rdev->desc->ops->get_status(rdev); 373853116a1SDavid Brownell if (status < 0) 374853116a1SDavid Brownell return status; 375853116a1SDavid Brownell 376853116a1SDavid Brownell switch (status) { 377853116a1SDavid Brownell case REGULATOR_STATUS_OFF: 378853116a1SDavid Brownell label = "off"; 379853116a1SDavid Brownell break; 380853116a1SDavid Brownell case REGULATOR_STATUS_ON: 381853116a1SDavid Brownell label = "on"; 382853116a1SDavid Brownell break; 383853116a1SDavid Brownell case REGULATOR_STATUS_ERROR: 384853116a1SDavid Brownell label = "error"; 385853116a1SDavid Brownell break; 386853116a1SDavid Brownell case REGULATOR_STATUS_FAST: 387853116a1SDavid Brownell label = "fast"; 388853116a1SDavid Brownell break; 389853116a1SDavid Brownell case REGULATOR_STATUS_NORMAL: 390853116a1SDavid Brownell label = "normal"; 391853116a1SDavid Brownell break; 392853116a1SDavid Brownell case REGULATOR_STATUS_IDLE: 393853116a1SDavid Brownell label = "idle"; 394853116a1SDavid Brownell break; 395853116a1SDavid Brownell case REGULATOR_STATUS_STANDBY: 396853116a1SDavid Brownell label = "standby"; 397853116a1SDavid Brownell break; 398f59c8f9fSMark Brown case REGULATOR_STATUS_BYPASS: 399f59c8f9fSMark Brown label = "bypass"; 400f59c8f9fSMark Brown break; 4011beaf762SKrystian Garbaciak case REGULATOR_STATUS_UNDEFINED: 4021beaf762SKrystian Garbaciak label = "undefined"; 4031beaf762SKrystian Garbaciak break; 404853116a1SDavid Brownell default: 405853116a1SDavid Brownell return -ERANGE; 406853116a1SDavid Brownell } 407853116a1SDavid Brownell 408853116a1SDavid Brownell return sprintf(buf, "%s\n", label); 409853116a1SDavid Brownell } 410853116a1SDavid Brownell static DEVICE_ATTR(status, 0444, regulator_status_show, NULL); 411853116a1SDavid Brownell 412414c70cbSLiam Girdwood static ssize_t regulator_min_uA_show(struct device *dev, 413414c70cbSLiam Girdwood struct device_attribute *attr, char *buf) 414414c70cbSLiam Girdwood { 415a5766f11SLiam Girdwood struct regulator_dev *rdev = dev_get_drvdata(dev); 416414c70cbSLiam Girdwood 417414c70cbSLiam Girdwood if (!rdev->constraints) 418414c70cbSLiam Girdwood return sprintf(buf, "constraint not defined\n"); 419414c70cbSLiam Girdwood 420414c70cbSLiam Girdwood return sprintf(buf, "%d\n", rdev->constraints->min_uA); 421414c70cbSLiam Girdwood } 4227ad68e2fSDavid Brownell static DEVICE_ATTR(min_microamps, 0444, regulator_min_uA_show, NULL); 423414c70cbSLiam Girdwood 424414c70cbSLiam Girdwood static ssize_t regulator_max_uA_show(struct device *dev, 425414c70cbSLiam Girdwood struct device_attribute *attr, char *buf) 426414c70cbSLiam Girdwood { 427a5766f11SLiam Girdwood struct regulator_dev *rdev = dev_get_drvdata(dev); 428414c70cbSLiam Girdwood 429414c70cbSLiam Girdwood if (!rdev->constraints) 430414c70cbSLiam Girdwood return sprintf(buf, "constraint not defined\n"); 431414c70cbSLiam Girdwood 432414c70cbSLiam Girdwood return sprintf(buf, "%d\n", rdev->constraints->max_uA); 433414c70cbSLiam Girdwood } 4347ad68e2fSDavid Brownell static DEVICE_ATTR(max_microamps, 0444, regulator_max_uA_show, NULL); 435414c70cbSLiam Girdwood 436414c70cbSLiam Girdwood static ssize_t regulator_min_uV_show(struct device *dev, 437414c70cbSLiam Girdwood struct device_attribute *attr, char *buf) 438414c70cbSLiam Girdwood { 439a5766f11SLiam Girdwood struct regulator_dev *rdev = dev_get_drvdata(dev); 440414c70cbSLiam Girdwood 441414c70cbSLiam Girdwood if (!rdev->constraints) 442414c70cbSLiam Girdwood return sprintf(buf, "constraint not defined\n"); 443414c70cbSLiam Girdwood 444414c70cbSLiam Girdwood return sprintf(buf, "%d\n", rdev->constraints->min_uV); 445414c70cbSLiam Girdwood } 4467ad68e2fSDavid Brownell static DEVICE_ATTR(min_microvolts, 0444, regulator_min_uV_show, NULL); 447414c70cbSLiam Girdwood 448414c70cbSLiam Girdwood static ssize_t regulator_max_uV_show(struct device *dev, 449414c70cbSLiam Girdwood struct device_attribute *attr, char *buf) 450414c70cbSLiam Girdwood { 451a5766f11SLiam Girdwood struct regulator_dev *rdev = dev_get_drvdata(dev); 452414c70cbSLiam Girdwood 453414c70cbSLiam Girdwood if (!rdev->constraints) 454414c70cbSLiam Girdwood return sprintf(buf, "constraint not defined\n"); 455414c70cbSLiam Girdwood 456414c70cbSLiam Girdwood return sprintf(buf, "%d\n", rdev->constraints->max_uV); 457414c70cbSLiam Girdwood } 4587ad68e2fSDavid Brownell static DEVICE_ATTR(max_microvolts, 0444, regulator_max_uV_show, NULL); 459414c70cbSLiam Girdwood 460414c70cbSLiam Girdwood static ssize_t regulator_total_uA_show(struct device *dev, 461414c70cbSLiam Girdwood struct device_attribute *attr, char *buf) 462414c70cbSLiam Girdwood { 463a5766f11SLiam Girdwood struct regulator_dev *rdev = dev_get_drvdata(dev); 464414c70cbSLiam Girdwood struct regulator *regulator; 465414c70cbSLiam Girdwood int uA = 0; 466414c70cbSLiam Girdwood 467414c70cbSLiam Girdwood mutex_lock(&rdev->mutex); 468414c70cbSLiam Girdwood list_for_each_entry(regulator, &rdev->consumer_list, list) 469414c70cbSLiam Girdwood uA += regulator->uA_load; 470414c70cbSLiam Girdwood mutex_unlock(&rdev->mutex); 471414c70cbSLiam Girdwood return sprintf(buf, "%d\n", uA); 472414c70cbSLiam Girdwood } 4737ad68e2fSDavid Brownell static DEVICE_ATTR(requested_microamps, 0444, regulator_total_uA_show, NULL); 474414c70cbSLiam Girdwood 475414c70cbSLiam Girdwood static ssize_t regulator_num_users_show(struct device *dev, 476414c70cbSLiam Girdwood struct device_attribute *attr, char *buf) 477414c70cbSLiam Girdwood { 478a5766f11SLiam Girdwood struct regulator_dev *rdev = dev_get_drvdata(dev); 479414c70cbSLiam Girdwood return sprintf(buf, "%d\n", rdev->use_count); 480414c70cbSLiam Girdwood } 481414c70cbSLiam Girdwood 482414c70cbSLiam Girdwood static ssize_t regulator_type_show(struct device *dev, 483414c70cbSLiam Girdwood struct device_attribute *attr, char *buf) 484414c70cbSLiam Girdwood { 485a5766f11SLiam Girdwood struct regulator_dev *rdev = dev_get_drvdata(dev); 486414c70cbSLiam Girdwood 487414c70cbSLiam Girdwood switch (rdev->desc->type) { 488414c70cbSLiam Girdwood case REGULATOR_VOLTAGE: 489414c70cbSLiam Girdwood return sprintf(buf, "voltage\n"); 490414c70cbSLiam Girdwood case REGULATOR_CURRENT: 491414c70cbSLiam Girdwood return sprintf(buf, "current\n"); 492414c70cbSLiam Girdwood } 493414c70cbSLiam Girdwood return sprintf(buf, "unknown\n"); 494414c70cbSLiam Girdwood } 495414c70cbSLiam Girdwood 496414c70cbSLiam Girdwood static ssize_t regulator_suspend_mem_uV_show(struct device *dev, 497414c70cbSLiam Girdwood struct device_attribute *attr, char *buf) 498414c70cbSLiam Girdwood { 499a5766f11SLiam Girdwood struct regulator_dev *rdev = dev_get_drvdata(dev); 500414c70cbSLiam Girdwood 501414c70cbSLiam Girdwood return sprintf(buf, "%d\n", rdev->constraints->state_mem.uV); 502414c70cbSLiam Girdwood } 5037ad68e2fSDavid Brownell static DEVICE_ATTR(suspend_mem_microvolts, 0444, 5047ad68e2fSDavid Brownell regulator_suspend_mem_uV_show, NULL); 505414c70cbSLiam Girdwood 506414c70cbSLiam Girdwood static ssize_t regulator_suspend_disk_uV_show(struct device *dev, 507414c70cbSLiam Girdwood struct device_attribute *attr, char *buf) 508414c70cbSLiam Girdwood { 509a5766f11SLiam Girdwood struct regulator_dev *rdev = dev_get_drvdata(dev); 510414c70cbSLiam Girdwood 511414c70cbSLiam Girdwood return sprintf(buf, "%d\n", rdev->constraints->state_disk.uV); 512414c70cbSLiam Girdwood } 5137ad68e2fSDavid Brownell static DEVICE_ATTR(suspend_disk_microvolts, 0444, 5147ad68e2fSDavid Brownell regulator_suspend_disk_uV_show, NULL); 515414c70cbSLiam Girdwood 516414c70cbSLiam Girdwood static ssize_t regulator_suspend_standby_uV_show(struct device *dev, 517414c70cbSLiam Girdwood struct device_attribute *attr, char *buf) 518414c70cbSLiam Girdwood { 519a5766f11SLiam Girdwood struct regulator_dev *rdev = dev_get_drvdata(dev); 520414c70cbSLiam Girdwood 521414c70cbSLiam Girdwood return sprintf(buf, "%d\n", rdev->constraints->state_standby.uV); 522414c70cbSLiam Girdwood } 5237ad68e2fSDavid Brownell static DEVICE_ATTR(suspend_standby_microvolts, 0444, 5247ad68e2fSDavid Brownell regulator_suspend_standby_uV_show, NULL); 525414c70cbSLiam Girdwood 526414c70cbSLiam Girdwood static ssize_t regulator_suspend_mem_mode_show(struct device *dev, 527414c70cbSLiam Girdwood struct device_attribute *attr, char *buf) 528414c70cbSLiam Girdwood { 529a5766f11SLiam Girdwood struct regulator_dev *rdev = dev_get_drvdata(dev); 530414c70cbSLiam Girdwood 5314fca9545SDavid Brownell return regulator_print_opmode(buf, 5324fca9545SDavid Brownell rdev->constraints->state_mem.mode); 533414c70cbSLiam Girdwood } 5347ad68e2fSDavid Brownell static DEVICE_ATTR(suspend_mem_mode, 0444, 5357ad68e2fSDavid Brownell regulator_suspend_mem_mode_show, NULL); 536414c70cbSLiam Girdwood 537414c70cbSLiam Girdwood static ssize_t regulator_suspend_disk_mode_show(struct device *dev, 538414c70cbSLiam Girdwood struct device_attribute *attr, char *buf) 539414c70cbSLiam Girdwood { 540a5766f11SLiam Girdwood struct regulator_dev *rdev = dev_get_drvdata(dev); 541414c70cbSLiam Girdwood 5424fca9545SDavid Brownell return regulator_print_opmode(buf, 5434fca9545SDavid Brownell rdev->constraints->state_disk.mode); 544414c70cbSLiam Girdwood } 5457ad68e2fSDavid Brownell static DEVICE_ATTR(suspend_disk_mode, 0444, 5467ad68e2fSDavid Brownell regulator_suspend_disk_mode_show, NULL); 547414c70cbSLiam Girdwood 548414c70cbSLiam Girdwood static ssize_t regulator_suspend_standby_mode_show(struct device *dev, 549414c70cbSLiam Girdwood struct device_attribute *attr, char *buf) 550414c70cbSLiam Girdwood { 551a5766f11SLiam Girdwood struct regulator_dev *rdev = dev_get_drvdata(dev); 552414c70cbSLiam Girdwood 5534fca9545SDavid Brownell return regulator_print_opmode(buf, 5544fca9545SDavid Brownell rdev->constraints->state_standby.mode); 555414c70cbSLiam Girdwood } 5567ad68e2fSDavid Brownell static DEVICE_ATTR(suspend_standby_mode, 0444, 5577ad68e2fSDavid Brownell regulator_suspend_standby_mode_show, NULL); 558414c70cbSLiam Girdwood 559414c70cbSLiam Girdwood static ssize_t regulator_suspend_mem_state_show(struct device *dev, 560414c70cbSLiam Girdwood struct device_attribute *attr, char *buf) 561414c70cbSLiam Girdwood { 562a5766f11SLiam Girdwood struct regulator_dev *rdev = dev_get_drvdata(dev); 563414c70cbSLiam Girdwood 5644fca9545SDavid Brownell return regulator_print_state(buf, 5654fca9545SDavid Brownell rdev->constraints->state_mem.enabled); 566414c70cbSLiam Girdwood } 5677ad68e2fSDavid Brownell static DEVICE_ATTR(suspend_mem_state, 0444, 5687ad68e2fSDavid Brownell regulator_suspend_mem_state_show, NULL); 569414c70cbSLiam Girdwood 570414c70cbSLiam Girdwood static ssize_t regulator_suspend_disk_state_show(struct device *dev, 571414c70cbSLiam Girdwood struct device_attribute *attr, char *buf) 572414c70cbSLiam Girdwood { 573a5766f11SLiam Girdwood struct regulator_dev *rdev = dev_get_drvdata(dev); 574414c70cbSLiam Girdwood 5754fca9545SDavid Brownell return regulator_print_state(buf, 5764fca9545SDavid Brownell rdev->constraints->state_disk.enabled); 577414c70cbSLiam Girdwood } 5787ad68e2fSDavid Brownell static DEVICE_ATTR(suspend_disk_state, 0444, 5797ad68e2fSDavid Brownell regulator_suspend_disk_state_show, NULL); 580414c70cbSLiam Girdwood 581414c70cbSLiam Girdwood static ssize_t regulator_suspend_standby_state_show(struct device *dev, 582414c70cbSLiam Girdwood struct device_attribute *attr, char *buf) 583414c70cbSLiam Girdwood { 584a5766f11SLiam Girdwood struct regulator_dev *rdev = dev_get_drvdata(dev); 585414c70cbSLiam Girdwood 5864fca9545SDavid Brownell return regulator_print_state(buf, 5874fca9545SDavid Brownell rdev->constraints->state_standby.enabled); 588414c70cbSLiam Girdwood } 5897ad68e2fSDavid Brownell static DEVICE_ATTR(suspend_standby_state, 0444, 5907ad68e2fSDavid Brownell regulator_suspend_standby_state_show, NULL); 591bc558a60SMark Brown 592f59c8f9fSMark Brown static ssize_t regulator_bypass_show(struct device *dev, 593f59c8f9fSMark Brown struct device_attribute *attr, char *buf) 594f59c8f9fSMark Brown { 595f59c8f9fSMark Brown struct regulator_dev *rdev = dev_get_drvdata(dev); 596f59c8f9fSMark Brown const char *report; 597f59c8f9fSMark Brown bool bypass; 598f59c8f9fSMark Brown int ret; 599f59c8f9fSMark Brown 600f59c8f9fSMark Brown ret = rdev->desc->ops->get_bypass(rdev, &bypass); 601f59c8f9fSMark Brown 602f59c8f9fSMark Brown if (ret != 0) 603f59c8f9fSMark Brown report = "unknown"; 604f59c8f9fSMark Brown else if (bypass) 605f59c8f9fSMark Brown report = "enabled"; 606f59c8f9fSMark Brown else 607f59c8f9fSMark Brown report = "disabled"; 608f59c8f9fSMark Brown 609f59c8f9fSMark Brown return sprintf(buf, "%s\n", report); 610f59c8f9fSMark Brown } 611f59c8f9fSMark Brown static DEVICE_ATTR(bypass, 0444, 612f59c8f9fSMark Brown regulator_bypass_show, NULL); 6137ad68e2fSDavid Brownell 6147ad68e2fSDavid Brownell /* 6157ad68e2fSDavid Brownell * These are the only attributes are present for all regulators. 6167ad68e2fSDavid Brownell * Other attributes are a function of regulator functionality. 6177ad68e2fSDavid Brownell */ 618414c70cbSLiam Girdwood static struct device_attribute regulator_dev_attrs[] = { 619bc558a60SMark Brown __ATTR(name, 0444, regulator_name_show, NULL), 620414c70cbSLiam Girdwood __ATTR(num_users, 0444, regulator_num_users_show, NULL), 621414c70cbSLiam Girdwood __ATTR(type, 0444, regulator_type_show, NULL), 622414c70cbSLiam Girdwood __ATTR_NULL, 623414c70cbSLiam Girdwood }; 624414c70cbSLiam Girdwood 625414c70cbSLiam Girdwood static void regulator_dev_release(struct device *dev) 626414c70cbSLiam Girdwood { 627a5766f11SLiam Girdwood struct regulator_dev *rdev = dev_get_drvdata(dev); 628414c70cbSLiam Girdwood kfree(rdev); 629414c70cbSLiam Girdwood } 630414c70cbSLiam Girdwood 631414c70cbSLiam Girdwood static struct class regulator_class = { 632414c70cbSLiam Girdwood .name = "regulator", 633414c70cbSLiam Girdwood .dev_release = regulator_dev_release, 634414c70cbSLiam Girdwood .dev_attrs = regulator_dev_attrs, 635414c70cbSLiam Girdwood }; 636414c70cbSLiam Girdwood 637414c70cbSLiam Girdwood /* Calculate the new optimum regulator operating mode based on the new total 638414c70cbSLiam Girdwood * consumer load. All locks held by caller */ 639414c70cbSLiam Girdwood static void drms_uA_update(struct regulator_dev *rdev) 640414c70cbSLiam Girdwood { 641414c70cbSLiam Girdwood struct regulator *sibling; 642414c70cbSLiam Girdwood int current_uA = 0, output_uV, input_uV, err; 643414c70cbSLiam Girdwood unsigned int mode; 644414c70cbSLiam Girdwood 645414c70cbSLiam Girdwood err = regulator_check_drms(rdev); 646414c70cbSLiam Girdwood if (err < 0 || !rdev->desc->ops->get_optimum_mode || 647476c2d83SMark Brown (!rdev->desc->ops->get_voltage && 648476c2d83SMark Brown !rdev->desc->ops->get_voltage_sel) || 649476c2d83SMark Brown !rdev->desc->ops->set_mode) 650414c70cbSLiam Girdwood return; 651414c70cbSLiam Girdwood 652414c70cbSLiam Girdwood /* get output voltage */ 6531bf5a1f8SMark Brown output_uV = _regulator_get_voltage(rdev); 654414c70cbSLiam Girdwood if (output_uV <= 0) 655414c70cbSLiam Girdwood return; 656414c70cbSLiam Girdwood 657414c70cbSLiam Girdwood /* get input voltage */ 6581bf5a1f8SMark Brown input_uV = 0; 6591bf5a1f8SMark Brown if (rdev->supply) 6603f24f5adSAxel Lin input_uV = regulator_get_voltage(rdev->supply); 6611bf5a1f8SMark Brown if (input_uV <= 0) 662414c70cbSLiam Girdwood input_uV = rdev->constraints->input_uV; 663414c70cbSLiam Girdwood if (input_uV <= 0) 664414c70cbSLiam Girdwood return; 665414c70cbSLiam Girdwood 666414c70cbSLiam Girdwood /* calc total requested load */ 667414c70cbSLiam Girdwood list_for_each_entry(sibling, &rdev->consumer_list, list) 668414c70cbSLiam Girdwood current_uA += sibling->uA_load; 669414c70cbSLiam Girdwood 670414c70cbSLiam Girdwood /* now get the optimum mode for our new total regulator load */ 671414c70cbSLiam Girdwood mode = rdev->desc->ops->get_optimum_mode(rdev, input_uV, 672414c70cbSLiam Girdwood output_uV, current_uA); 673414c70cbSLiam Girdwood 674414c70cbSLiam Girdwood /* check the new mode is allowed */ 6752c608234SMark Brown err = regulator_mode_constrain(rdev, &mode); 676414c70cbSLiam Girdwood if (err == 0) 677414c70cbSLiam Girdwood rdev->desc->ops->set_mode(rdev, mode); 678414c70cbSLiam Girdwood } 679414c70cbSLiam Girdwood 680414c70cbSLiam Girdwood static int suspend_set_state(struct regulator_dev *rdev, 681414c70cbSLiam Girdwood struct regulator_state *rstate) 682414c70cbSLiam Girdwood { 683414c70cbSLiam Girdwood int ret = 0; 684638f85c5SMark Brown 685638f85c5SMark Brown /* If we have no suspend mode configration don't set anything; 6868ac0e95dSAxel Lin * only warn if the driver implements set_suspend_voltage or 6878ac0e95dSAxel Lin * set_suspend_mode callback. 688638f85c5SMark Brown */ 689638f85c5SMark Brown if (!rstate->enabled && !rstate->disabled) { 6908ac0e95dSAxel Lin if (rdev->desc->ops->set_suspend_voltage || 6918ac0e95dSAxel Lin rdev->desc->ops->set_suspend_mode) 6925da84fd9SJoe Perches rdev_warn(rdev, "No configuration\n"); 693638f85c5SMark Brown return 0; 694638f85c5SMark Brown } 695638f85c5SMark Brown 696638f85c5SMark Brown if (rstate->enabled && rstate->disabled) { 6975da84fd9SJoe Perches rdev_err(rdev, "invalid configuration\n"); 698638f85c5SMark Brown return -EINVAL; 699638f85c5SMark Brown } 700638f85c5SMark Brown 7018ac0e95dSAxel Lin if (rstate->enabled && rdev->desc->ops->set_suspend_enable) 702414c70cbSLiam Girdwood ret = rdev->desc->ops->set_suspend_enable(rdev); 7038ac0e95dSAxel Lin else if (rstate->disabled && rdev->desc->ops->set_suspend_disable) 704414c70cbSLiam Girdwood ret = rdev->desc->ops->set_suspend_disable(rdev); 7058ac0e95dSAxel Lin else /* OK if set_suspend_enable or set_suspend_disable is NULL */ 7068ac0e95dSAxel Lin ret = 0; 7078ac0e95dSAxel Lin 708414c70cbSLiam Girdwood if (ret < 0) { 7095da84fd9SJoe Perches rdev_err(rdev, "failed to enabled/disable\n"); 710414c70cbSLiam Girdwood return ret; 711414c70cbSLiam Girdwood } 712414c70cbSLiam Girdwood 713414c70cbSLiam Girdwood if (rdev->desc->ops->set_suspend_voltage && rstate->uV > 0) { 714414c70cbSLiam Girdwood ret = rdev->desc->ops->set_suspend_voltage(rdev, rstate->uV); 715414c70cbSLiam Girdwood if (ret < 0) { 7165da84fd9SJoe Perches rdev_err(rdev, "failed to set voltage\n"); 717414c70cbSLiam Girdwood return ret; 718414c70cbSLiam Girdwood } 719414c70cbSLiam Girdwood } 720414c70cbSLiam Girdwood 721414c70cbSLiam Girdwood if (rdev->desc->ops->set_suspend_mode && rstate->mode > 0) { 722414c70cbSLiam Girdwood ret = rdev->desc->ops->set_suspend_mode(rdev, rstate->mode); 723414c70cbSLiam Girdwood if (ret < 0) { 7245da84fd9SJoe Perches rdev_err(rdev, "failed to set mode\n"); 725414c70cbSLiam Girdwood return ret; 726414c70cbSLiam Girdwood } 727414c70cbSLiam Girdwood } 728414c70cbSLiam Girdwood return ret; 729414c70cbSLiam Girdwood } 730414c70cbSLiam Girdwood 731414c70cbSLiam Girdwood /* locks held by caller */ 732414c70cbSLiam Girdwood static int suspend_prepare(struct regulator_dev *rdev, suspend_state_t state) 733414c70cbSLiam Girdwood { 734414c70cbSLiam Girdwood if (!rdev->constraints) 735414c70cbSLiam Girdwood return -EINVAL; 736414c70cbSLiam Girdwood 737414c70cbSLiam Girdwood switch (state) { 738414c70cbSLiam Girdwood case PM_SUSPEND_STANDBY: 739414c70cbSLiam Girdwood return suspend_set_state(rdev, 740414c70cbSLiam Girdwood &rdev->constraints->state_standby); 741414c70cbSLiam Girdwood case PM_SUSPEND_MEM: 742414c70cbSLiam Girdwood return suspend_set_state(rdev, 743414c70cbSLiam Girdwood &rdev->constraints->state_mem); 744414c70cbSLiam Girdwood case PM_SUSPEND_MAX: 745414c70cbSLiam Girdwood return suspend_set_state(rdev, 746414c70cbSLiam Girdwood &rdev->constraints->state_disk); 747414c70cbSLiam Girdwood default: 748414c70cbSLiam Girdwood return -EINVAL; 749414c70cbSLiam Girdwood } 750414c70cbSLiam Girdwood } 751414c70cbSLiam Girdwood 752414c70cbSLiam Girdwood static void print_constraints(struct regulator_dev *rdev) 753414c70cbSLiam Girdwood { 754414c70cbSLiam Girdwood struct regulation_constraints *constraints = rdev->constraints; 755973e9a27SMark Brown char buf[80] = ""; 7568f031b48SMark Brown int count = 0; 7578f031b48SMark Brown int ret; 758414c70cbSLiam Girdwood 7598f031b48SMark Brown if (constraints->min_uV && constraints->max_uV) { 760414c70cbSLiam Girdwood if (constraints->min_uV == constraints->max_uV) 7618f031b48SMark Brown count += sprintf(buf + count, "%d mV ", 762414c70cbSLiam Girdwood constraints->min_uV / 1000); 763414c70cbSLiam Girdwood else 7648f031b48SMark Brown count += sprintf(buf + count, "%d <--> %d mV ", 765414c70cbSLiam Girdwood constraints->min_uV / 1000, 766414c70cbSLiam Girdwood constraints->max_uV / 1000); 7678f031b48SMark Brown } 7688f031b48SMark Brown 7698f031b48SMark Brown if (!constraints->min_uV || 7708f031b48SMark Brown constraints->min_uV != constraints->max_uV) { 7718f031b48SMark Brown ret = _regulator_get_voltage(rdev); 7728f031b48SMark Brown if (ret > 0) 7738f031b48SMark Brown count += sprintf(buf + count, "at %d mV ", ret / 1000); 7748f031b48SMark Brown } 7758f031b48SMark Brown 776bf5892a8SMark Brown if (constraints->uV_offset) 777bf5892a8SMark Brown count += sprintf(buf, "%dmV offset ", 778bf5892a8SMark Brown constraints->uV_offset / 1000); 779bf5892a8SMark Brown 7808f031b48SMark Brown if (constraints->min_uA && constraints->max_uA) { 781414c70cbSLiam Girdwood if (constraints->min_uA == constraints->max_uA) 7828f031b48SMark Brown count += sprintf(buf + count, "%d mA ", 783414c70cbSLiam Girdwood constraints->min_uA / 1000); 784414c70cbSLiam Girdwood else 7858f031b48SMark Brown count += sprintf(buf + count, "%d <--> %d mA ", 786414c70cbSLiam Girdwood constraints->min_uA / 1000, 787414c70cbSLiam Girdwood constraints->max_uA / 1000); 788414c70cbSLiam Girdwood } 7898f031b48SMark Brown 7908f031b48SMark Brown if (!constraints->min_uA || 7918f031b48SMark Brown constraints->min_uA != constraints->max_uA) { 7928f031b48SMark Brown ret = _regulator_get_current_limit(rdev); 7938f031b48SMark Brown if (ret > 0) 794e4a6376bSCyril Chemparathy count += sprintf(buf + count, "at %d mA ", ret / 1000); 7958f031b48SMark Brown } 7968f031b48SMark Brown 797414c70cbSLiam Girdwood if (constraints->valid_modes_mask & REGULATOR_MODE_FAST) 798414c70cbSLiam Girdwood count += sprintf(buf + count, "fast "); 799414c70cbSLiam Girdwood if (constraints->valid_modes_mask & REGULATOR_MODE_NORMAL) 800414c70cbSLiam Girdwood count += sprintf(buf + count, "normal "); 801414c70cbSLiam Girdwood if (constraints->valid_modes_mask & REGULATOR_MODE_IDLE) 802414c70cbSLiam Girdwood count += sprintf(buf + count, "idle "); 803414c70cbSLiam Girdwood if (constraints->valid_modes_mask & REGULATOR_MODE_STANDBY) 804414c70cbSLiam Girdwood count += sprintf(buf + count, "standby"); 805414c70cbSLiam Girdwood 806215b8b05SUwe Kleine-König if (!count) 807215b8b05SUwe Kleine-König sprintf(buf, "no parameters"); 808215b8b05SUwe Kleine-König 80913ce29f8SMark Brown rdev_info(rdev, "%s\n", buf); 8104a682922SMark Brown 8114a682922SMark Brown if ((constraints->min_uV != constraints->max_uV) && 8124a682922SMark Brown !(constraints->valid_ops_mask & REGULATOR_CHANGE_VOLTAGE)) 8134a682922SMark Brown rdev_warn(rdev, 8144a682922SMark Brown "Voltage range but no REGULATOR_CHANGE_VOLTAGE\n"); 815414c70cbSLiam Girdwood } 816414c70cbSLiam Girdwood 817e79055d6SMark Brown static int machine_constraints_voltage(struct regulator_dev *rdev, 8181083c393SMark Brown struct regulation_constraints *constraints) 819e79055d6SMark Brown { 820e79055d6SMark Brown struct regulator_ops *ops = rdev->desc->ops; 821af5866c9SMark Brown int ret; 822af5866c9SMark Brown 823af5866c9SMark Brown /* do we need to apply the constraint voltage */ 824af5866c9SMark Brown if (rdev->constraints->apply_uV && 82575790251SMark Brown rdev->constraints->min_uV == rdev->constraints->max_uV) { 82675790251SMark Brown ret = _regulator_do_set_voltage(rdev, 8273a93f2a9SMark Brown rdev->constraints->min_uV, 82875790251SMark Brown rdev->constraints->max_uV); 829af5866c9SMark Brown if (ret < 0) { 8305da84fd9SJoe Perches rdev_err(rdev, "failed to apply %duV constraint\n", 8315da84fd9SJoe Perches rdev->constraints->min_uV); 832af5866c9SMark Brown return ret; 833af5866c9SMark Brown } 834af5866c9SMark Brown } 835e79055d6SMark Brown 836e79055d6SMark Brown /* constrain machine-level voltage specs to fit 837e79055d6SMark Brown * the actual range supported by this regulator. 838e79055d6SMark Brown */ 839e79055d6SMark Brown if (ops->list_voltage && rdev->desc->n_voltages) { 840e79055d6SMark Brown int count = rdev->desc->n_voltages; 841e79055d6SMark Brown int i; 842e79055d6SMark Brown int min_uV = INT_MAX; 843e79055d6SMark Brown int max_uV = INT_MIN; 844e79055d6SMark Brown int cmin = constraints->min_uV; 845e79055d6SMark Brown int cmax = constraints->max_uV; 846e79055d6SMark Brown 847e79055d6SMark Brown /* it's safe to autoconfigure fixed-voltage supplies 848e79055d6SMark Brown and the constraints are used by list_voltage. */ 849e79055d6SMark Brown if (count == 1 && !cmin) { 850e79055d6SMark Brown cmin = 1; 851e79055d6SMark Brown cmax = INT_MAX; 852e79055d6SMark Brown constraints->min_uV = cmin; 853e79055d6SMark Brown constraints->max_uV = cmax; 854e79055d6SMark Brown } 855e79055d6SMark Brown 856e79055d6SMark Brown /* voltage constraints are optional */ 857e79055d6SMark Brown if ((cmin == 0) && (cmax == 0)) 858e79055d6SMark Brown return 0; 859e79055d6SMark Brown 860e79055d6SMark Brown /* else require explicit machine-level constraints */ 861e79055d6SMark Brown if (cmin <= 0 || cmax <= 0 || cmax < cmin) { 8625da84fd9SJoe Perches rdev_err(rdev, "invalid voltage constraints\n"); 863e79055d6SMark Brown return -EINVAL; 864e79055d6SMark Brown } 865e79055d6SMark Brown 866e79055d6SMark Brown /* initial: [cmin..cmax] valid, [min_uV..max_uV] not */ 867e79055d6SMark Brown for (i = 0; i < count; i++) { 868e79055d6SMark Brown int value; 869e79055d6SMark Brown 870e79055d6SMark Brown value = ops->list_voltage(rdev, i); 871e79055d6SMark Brown if (value <= 0) 872e79055d6SMark Brown continue; 873e79055d6SMark Brown 874e79055d6SMark Brown /* maybe adjust [min_uV..max_uV] */ 875e79055d6SMark Brown if (value >= cmin && value < min_uV) 876e79055d6SMark Brown min_uV = value; 877e79055d6SMark Brown if (value <= cmax && value > max_uV) 878e79055d6SMark Brown max_uV = value; 879e79055d6SMark Brown } 880e79055d6SMark Brown 881e79055d6SMark Brown /* final: [min_uV..max_uV] valid iff constraints valid */ 882e79055d6SMark Brown if (max_uV < min_uV) { 8835da84fd9SJoe Perches rdev_err(rdev, "unsupportable voltage constraints\n"); 884e79055d6SMark Brown return -EINVAL; 885e79055d6SMark Brown } 886e79055d6SMark Brown 887e79055d6SMark Brown /* use regulator's subset of machine constraints */ 888e79055d6SMark Brown if (constraints->min_uV < min_uV) { 8895da84fd9SJoe Perches rdev_dbg(rdev, "override min_uV, %d -> %d\n", 8905da84fd9SJoe Perches constraints->min_uV, min_uV); 891e79055d6SMark Brown constraints->min_uV = min_uV; 892e79055d6SMark Brown } 893e79055d6SMark Brown if (constraints->max_uV > max_uV) { 8945da84fd9SJoe Perches rdev_dbg(rdev, "override max_uV, %d -> %d\n", 8955da84fd9SJoe Perches constraints->max_uV, max_uV); 896e79055d6SMark Brown constraints->max_uV = max_uV; 897e79055d6SMark Brown } 898e79055d6SMark Brown } 899e79055d6SMark Brown 900e79055d6SMark Brown return 0; 901e79055d6SMark Brown } 902e79055d6SMark Brown 903a5766f11SLiam Girdwood /** 904a5766f11SLiam Girdwood * set_machine_constraints - sets regulator constraints 90569279fb9SMark Brown * @rdev: regulator source 906c8e7e464SMark Brown * @constraints: constraints to apply 907a5766f11SLiam Girdwood * 908a5766f11SLiam Girdwood * Allows platform initialisation code to define and constrain 909a5766f11SLiam Girdwood * regulator circuits e.g. valid voltage/current ranges, etc. NOTE: 910a5766f11SLiam Girdwood * Constraints *must* be set by platform code in order for some 911a5766f11SLiam Girdwood * regulator operations to proceed i.e. set_voltage, set_current_limit, 912a5766f11SLiam Girdwood * set_mode. 913a5766f11SLiam Girdwood */ 914a5766f11SLiam Girdwood static int set_machine_constraints(struct regulator_dev *rdev, 915f8c12fe3SMark Brown const struct regulation_constraints *constraints) 916a5766f11SLiam Girdwood { 917a5766f11SLiam Girdwood int ret = 0; 918e5fda26cSMark Brown struct regulator_ops *ops = rdev->desc->ops; 919e06f5b4fSMark Brown 9209a8f5e07SMark Brown if (constraints) 921f8c12fe3SMark Brown rdev->constraints = kmemdup(constraints, sizeof(*constraints), 922f8c12fe3SMark Brown GFP_KERNEL); 9239a8f5e07SMark Brown else 9249a8f5e07SMark Brown rdev->constraints = kzalloc(sizeof(*constraints), 9259a8f5e07SMark Brown GFP_KERNEL); 926f8c12fe3SMark Brown if (!rdev->constraints) 927f8c12fe3SMark Brown return -ENOMEM; 928af5866c9SMark Brown 929f8c12fe3SMark Brown ret = machine_constraints_voltage(rdev, rdev->constraints); 930e79055d6SMark Brown if (ret != 0) 9313e2b9abdSMark Brown goto out; 9323e2b9abdSMark Brown 933a5766f11SLiam Girdwood /* do we need to setup our suspend state */ 9349a8f5e07SMark Brown if (rdev->constraints->initial_state) { 935f8c12fe3SMark Brown ret = suspend_prepare(rdev, rdev->constraints->initial_state); 936e06f5b4fSMark Brown if (ret < 0) { 9375da84fd9SJoe Perches rdev_err(rdev, "failed to set suspend state\n"); 938e06f5b4fSMark Brown goto out; 939e06f5b4fSMark Brown } 940e06f5b4fSMark Brown } 941a5766f11SLiam Girdwood 9429a8f5e07SMark Brown if (rdev->constraints->initial_mode) { 943a308466cSMark Brown if (!ops->set_mode) { 9445da84fd9SJoe Perches rdev_err(rdev, "no set_mode operation\n"); 945a308466cSMark Brown ret = -EINVAL; 946a308466cSMark Brown goto out; 947a308466cSMark Brown } 948a308466cSMark Brown 949f8c12fe3SMark Brown ret = ops->set_mode(rdev, rdev->constraints->initial_mode); 950a308466cSMark Brown if (ret < 0) { 9515da84fd9SJoe Perches rdev_err(rdev, "failed to set initial mode: %d\n", ret); 952a308466cSMark Brown goto out; 953a308466cSMark Brown } 954a308466cSMark Brown } 955a308466cSMark Brown 956cacf90f2SMark Brown /* If the constraints say the regulator should be on at this point 957cacf90f2SMark Brown * and we have control then make sure it is enabled. 958cacf90f2SMark Brown */ 959f8c12fe3SMark Brown if ((rdev->constraints->always_on || rdev->constraints->boot_on) && 960f8c12fe3SMark Brown ops->enable) { 961e5fda26cSMark Brown ret = ops->enable(rdev); 962e5fda26cSMark Brown if (ret < 0) { 9635da84fd9SJoe Perches rdev_err(rdev, "failed to enable\n"); 964e5fda26cSMark Brown goto out; 965e5fda26cSMark Brown } 966e5fda26cSMark Brown } 967e5fda26cSMark Brown 9686f0b2c69SYadwinder Singh Brar if (rdev->constraints->ramp_delay && ops->set_ramp_delay) { 9696f0b2c69SYadwinder Singh Brar ret = ops->set_ramp_delay(rdev, rdev->constraints->ramp_delay); 9706f0b2c69SYadwinder Singh Brar if (ret < 0) { 9716f0b2c69SYadwinder Singh Brar rdev_err(rdev, "failed to set ramp_delay\n"); 9726f0b2c69SYadwinder Singh Brar goto out; 9736f0b2c69SYadwinder Singh Brar } 9746f0b2c69SYadwinder Singh Brar } 9756f0b2c69SYadwinder Singh Brar 976a5766f11SLiam Girdwood print_constraints(rdev); 9771a6958e7SAxel Lin return 0; 978a5766f11SLiam Girdwood out: 9791a6958e7SAxel Lin kfree(rdev->constraints); 9801a6958e7SAxel Lin rdev->constraints = NULL; 981a5766f11SLiam Girdwood return ret; 982a5766f11SLiam Girdwood } 983a5766f11SLiam Girdwood 984a5766f11SLiam Girdwood /** 985a5766f11SLiam Girdwood * set_supply - set regulator supply regulator 98669279fb9SMark Brown * @rdev: regulator name 98769279fb9SMark Brown * @supply_rdev: supply regulator name 988a5766f11SLiam Girdwood * 989a5766f11SLiam Girdwood * Called by platform initialisation code to set the supply regulator for this 990a5766f11SLiam Girdwood * regulator. This ensures that a regulators supply will also be enabled by the 991a5766f11SLiam Girdwood * core if it's child is enabled. 992a5766f11SLiam Girdwood */ 993a5766f11SLiam Girdwood static int set_supply(struct regulator_dev *rdev, 994a5766f11SLiam Girdwood struct regulator_dev *supply_rdev) 995a5766f11SLiam Girdwood { 996a5766f11SLiam Girdwood int err; 997a5766f11SLiam Girdwood 9983801b86aSMark Brown rdev_info(rdev, "supplied by %s\n", rdev_get_name(supply_rdev)); 9993801b86aSMark Brown 10003801b86aSMark Brown rdev->supply = create_regulator(supply_rdev, &rdev->dev, "SUPPLY"); 100132c78de8SAxel Lin if (rdev->supply == NULL) { 100232c78de8SAxel Lin err = -ENOMEM; 1003a5766f11SLiam Girdwood return err; 1004a5766f11SLiam Girdwood } 100557ad526aSLaxman Dewangan supply_rdev->open_count++; 1006a5766f11SLiam Girdwood 10073801b86aSMark Brown return 0; 10083801b86aSMark Brown } 10093801b86aSMark Brown 1010a5766f11SLiam Girdwood /** 101106c63f93SRandy Dunlap * set_consumer_device_supply - Bind a regulator to a symbolic supply 101269279fb9SMark Brown * @rdev: regulator source 101340f9244fSMark Brown * @consumer_dev_name: dev_name() string for device supply applies to 1014a5766f11SLiam Girdwood * @supply: symbolic name for supply 1015a5766f11SLiam Girdwood * 1016a5766f11SLiam Girdwood * Allows platform initialisation code to map physical regulator 1017a5766f11SLiam Girdwood * sources to symbolic names for supplies for use by devices. Devices 1018a5766f11SLiam Girdwood * should use these symbolic names to request regulators, avoiding the 1019a5766f11SLiam Girdwood * need to provide board-specific regulator names as platform data. 1020a5766f11SLiam Girdwood */ 1021a5766f11SLiam Girdwood static int set_consumer_device_supply(struct regulator_dev *rdev, 1022737f360dSMark Brown const char *consumer_dev_name, 102340f9244fSMark Brown const char *supply) 1024a5766f11SLiam Girdwood { 1025a5766f11SLiam Girdwood struct regulator_map *node; 10269ed2099eSMark Brown int has_dev; 1027a5766f11SLiam Girdwood 1028a5766f11SLiam Girdwood if (supply == NULL) 1029a5766f11SLiam Girdwood return -EINVAL; 1030a5766f11SLiam Girdwood 10319ed2099eSMark Brown if (consumer_dev_name != NULL) 10329ed2099eSMark Brown has_dev = 1; 10339ed2099eSMark Brown else 10349ed2099eSMark Brown has_dev = 0; 10359ed2099eSMark Brown 10366001e13cSDavid Brownell list_for_each_entry(node, ®ulator_map_list, list) { 103723b5cc2aSJani Nikula if (node->dev_name && consumer_dev_name) { 103823b5cc2aSJani Nikula if (strcmp(node->dev_name, consumer_dev_name) != 0) 10396001e13cSDavid Brownell continue; 104023b5cc2aSJani Nikula } else if (node->dev_name || consumer_dev_name) { 104123b5cc2aSJani Nikula continue; 104223b5cc2aSJani Nikula } 104323b5cc2aSJani Nikula 10446001e13cSDavid Brownell if (strcmp(node->supply, supply) != 0) 10456001e13cSDavid Brownell continue; 10466001e13cSDavid Brownell 1047737f360dSMark Brown pr_debug("%s: %s/%s is '%s' supply; fail %s/%s\n", 1048737f360dSMark Brown consumer_dev_name, 10496001e13cSDavid Brownell dev_name(&node->regulator->dev), 10506001e13cSDavid Brownell node->regulator->desc->name, 10516001e13cSDavid Brownell supply, 10521083c393SMark Brown dev_name(&rdev->dev), rdev_get_name(rdev)); 10536001e13cSDavid Brownell return -EBUSY; 10546001e13cSDavid Brownell } 10556001e13cSDavid Brownell 10569ed2099eSMark Brown node = kzalloc(sizeof(struct regulator_map), GFP_KERNEL); 1057a5766f11SLiam Girdwood if (node == NULL) 1058a5766f11SLiam Girdwood return -ENOMEM; 1059a5766f11SLiam Girdwood 1060a5766f11SLiam Girdwood node->regulator = rdev; 1061a5766f11SLiam Girdwood node->supply = supply; 1062a5766f11SLiam Girdwood 10639ed2099eSMark Brown if (has_dev) { 10649ed2099eSMark Brown node->dev_name = kstrdup(consumer_dev_name, GFP_KERNEL); 106540f9244fSMark Brown if (node->dev_name == NULL) { 106640f9244fSMark Brown kfree(node); 106740f9244fSMark Brown return -ENOMEM; 106840f9244fSMark Brown } 10699ed2099eSMark Brown } 107040f9244fSMark Brown 1071a5766f11SLiam Girdwood list_add(&node->list, ®ulator_map_list); 1072a5766f11SLiam Girdwood return 0; 1073a5766f11SLiam Girdwood } 1074a5766f11SLiam Girdwood 10750f1d747bSMike Rapoport static void unset_regulator_supplies(struct regulator_dev *rdev) 10760f1d747bSMike Rapoport { 10770f1d747bSMike Rapoport struct regulator_map *node, *n; 10780f1d747bSMike Rapoport 10790f1d747bSMike Rapoport list_for_each_entry_safe(node, n, ®ulator_map_list, list) { 10800f1d747bSMike Rapoport if (rdev == node->regulator) { 10810f1d747bSMike Rapoport list_del(&node->list); 108240f9244fSMark Brown kfree(node->dev_name); 10830f1d747bSMike Rapoport kfree(node); 10840f1d747bSMike Rapoport } 10850f1d747bSMike Rapoport } 10860f1d747bSMike Rapoport } 10870f1d747bSMike Rapoport 1088f5726ae3SMark Brown #define REG_STR_SIZE 64 1089414c70cbSLiam Girdwood 1090414c70cbSLiam Girdwood static struct regulator *create_regulator(struct regulator_dev *rdev, 1091414c70cbSLiam Girdwood struct device *dev, 1092414c70cbSLiam Girdwood const char *supply_name) 1093414c70cbSLiam Girdwood { 1094414c70cbSLiam Girdwood struct regulator *regulator; 1095414c70cbSLiam Girdwood char buf[REG_STR_SIZE]; 1096414c70cbSLiam Girdwood int err, size; 1097414c70cbSLiam Girdwood 1098414c70cbSLiam Girdwood regulator = kzalloc(sizeof(*regulator), GFP_KERNEL); 1099414c70cbSLiam Girdwood if (regulator == NULL) 1100414c70cbSLiam Girdwood return NULL; 1101414c70cbSLiam Girdwood 1102414c70cbSLiam Girdwood mutex_lock(&rdev->mutex); 1103414c70cbSLiam Girdwood regulator->rdev = rdev; 1104414c70cbSLiam Girdwood list_add(®ulator->list, &rdev->consumer_list); 1105414c70cbSLiam Girdwood 1106414c70cbSLiam Girdwood if (dev) { 1107e2c98eafSShawn Guo regulator->dev = dev; 1108e2c98eafSShawn Guo 1109222cc7b1SMark Brown /* Add a link to the device sysfs entry */ 1110414c70cbSLiam Girdwood size = scnprintf(buf, REG_STR_SIZE, "%s-%s", 1111414c70cbSLiam Girdwood dev->kobj.name, supply_name); 1112414c70cbSLiam Girdwood if (size >= REG_STR_SIZE) 1113222cc7b1SMark Brown goto overflow_err; 1114414c70cbSLiam Girdwood 1115414c70cbSLiam Girdwood regulator->supply_name = kstrdup(buf, GFP_KERNEL); 1116414c70cbSLiam Girdwood if (regulator->supply_name == NULL) 1117222cc7b1SMark Brown goto overflow_err; 1118414c70cbSLiam Girdwood 1119414c70cbSLiam Girdwood err = sysfs_create_link(&rdev->dev.kobj, &dev->kobj, 1120414c70cbSLiam Girdwood buf); 1121414c70cbSLiam Girdwood if (err) { 11225da84fd9SJoe Perches rdev_warn(rdev, "could not add device link %s err %d\n", 11231d7372e1SDaniel Walker dev->kobj.name, err); 1124222cc7b1SMark Brown /* non-fatal */ 1125414c70cbSLiam Girdwood } 11265de70519SMark Brown } else { 11275de70519SMark Brown regulator->supply_name = kstrdup(supply_name, GFP_KERNEL); 11285de70519SMark Brown if (regulator->supply_name == NULL) 1129222cc7b1SMark Brown goto overflow_err; 1130414c70cbSLiam Girdwood } 11315de70519SMark Brown 11325de70519SMark Brown regulator->debugfs = debugfs_create_dir(regulator->supply_name, 11335de70519SMark Brown rdev->debugfs); 113424751434SStephen Boyd if (!regulator->debugfs) { 11355de70519SMark Brown rdev_warn(rdev, "Failed to create debugfs directory\n"); 11365de70519SMark Brown } else { 11375de70519SMark Brown debugfs_create_u32("uA_load", 0444, regulator->debugfs, 11385de70519SMark Brown ®ulator->uA_load); 11395de70519SMark Brown debugfs_create_u32("min_uV", 0444, regulator->debugfs, 11405de70519SMark Brown ®ulator->min_uV); 11415de70519SMark Brown debugfs_create_u32("max_uV", 0444, regulator->debugfs, 11425de70519SMark Brown ®ulator->max_uV); 11435de70519SMark Brown } 11445de70519SMark Brown 11456492bc1bSMark Brown /* 11466492bc1bSMark Brown * Check now if the regulator is an always on regulator - if 11476492bc1bSMark Brown * it is then we don't need to do nearly so much work for 11486492bc1bSMark Brown * enable/disable calls. 11496492bc1bSMark Brown */ 11506492bc1bSMark Brown if (!_regulator_can_change_status(rdev) && 11516492bc1bSMark Brown _regulator_is_enabled(rdev)) 11526492bc1bSMark Brown regulator->always_on = true; 11536492bc1bSMark Brown 1154414c70cbSLiam Girdwood mutex_unlock(&rdev->mutex); 1155414c70cbSLiam Girdwood return regulator; 1156414c70cbSLiam Girdwood overflow_err: 1157414c70cbSLiam Girdwood list_del(®ulator->list); 1158414c70cbSLiam Girdwood kfree(regulator); 1159414c70cbSLiam Girdwood mutex_unlock(&rdev->mutex); 1160414c70cbSLiam Girdwood return NULL; 1161414c70cbSLiam Girdwood } 1162414c70cbSLiam Girdwood 116331aae2beSMark Brown static int _regulator_get_enable_time(struct regulator_dev *rdev) 116431aae2beSMark Brown { 116531aae2beSMark Brown if (!rdev->desc->ops->enable_time) 116679511ed3SMark Brown return rdev->desc->enable_time; 116731aae2beSMark Brown return rdev->desc->ops->enable_time(rdev); 116831aae2beSMark Brown } 116931aae2beSMark Brown 117069511a45SRajendra Nayak static struct regulator_dev *regulator_dev_lookup(struct device *dev, 11716d191a5fSMark Brown const char *supply, 11726d191a5fSMark Brown int *ret) 117369511a45SRajendra Nayak { 117469511a45SRajendra Nayak struct regulator_dev *r; 117569511a45SRajendra Nayak struct device_node *node; 1176576ca436SMark Brown struct regulator_map *map; 1177576ca436SMark Brown const char *devname = NULL; 117869511a45SRajendra Nayak 117969511a45SRajendra Nayak /* first do a dt based lookup */ 118069511a45SRajendra Nayak if (dev && dev->of_node) { 118169511a45SRajendra Nayak node = of_get_regulator(dev, supply); 11826d191a5fSMark Brown if (node) { 118369511a45SRajendra Nayak list_for_each_entry(r, ®ulator_list, list) 118469511a45SRajendra Nayak if (r->dev.parent && 118569511a45SRajendra Nayak node == r->dev.of_node) 118669511a45SRajendra Nayak return r; 11876d191a5fSMark Brown } else { 11886d191a5fSMark Brown /* 11896d191a5fSMark Brown * If we couldn't even get the node then it's 11906d191a5fSMark Brown * not just that the device didn't register 11916d191a5fSMark Brown * yet, there's no node and we'll never 11926d191a5fSMark Brown * succeed. 11936d191a5fSMark Brown */ 11946d191a5fSMark Brown *ret = -ENODEV; 11956d191a5fSMark Brown } 119669511a45SRajendra Nayak } 119769511a45SRajendra Nayak 119869511a45SRajendra Nayak /* if not found, try doing it non-dt way */ 1199576ca436SMark Brown if (dev) 1200576ca436SMark Brown devname = dev_name(dev); 1201576ca436SMark Brown 120269511a45SRajendra Nayak list_for_each_entry(r, ®ulator_list, list) 120369511a45SRajendra Nayak if (strcmp(rdev_get_name(r), supply) == 0) 120469511a45SRajendra Nayak return r; 120569511a45SRajendra Nayak 1206576ca436SMark Brown list_for_each_entry(map, ®ulator_map_list, list) { 1207576ca436SMark Brown /* If the mapping has a device set up it must match */ 1208576ca436SMark Brown if (map->dev_name && 1209576ca436SMark Brown (!devname || strcmp(map->dev_name, devname))) 1210576ca436SMark Brown continue; 1211576ca436SMark Brown 1212576ca436SMark Brown if (strcmp(map->supply, supply) == 0) 1213576ca436SMark Brown return map->regulator; 1214576ca436SMark Brown } 1215576ca436SMark Brown 1216576ca436SMark Brown 121769511a45SRajendra Nayak return NULL; 121869511a45SRajendra Nayak } 121969511a45SRajendra Nayak 12205ffbd136SMark Brown /* Internal regulator request function */ 12215ffbd136SMark Brown static struct regulator *_regulator_get(struct device *dev, const char *id, 12225ffbd136SMark Brown int exclusive) 1223414c70cbSLiam Girdwood { 1224414c70cbSLiam Girdwood struct regulator_dev *rdev; 122504bf3011SMark Brown struct regulator *regulator = ERR_PTR(-EPROBE_DEFER); 122640f9244fSMark Brown const char *devname = NULL; 12275ffbd136SMark Brown int ret; 1228414c70cbSLiam Girdwood 1229414c70cbSLiam Girdwood if (id == NULL) { 12305da84fd9SJoe Perches pr_err("get() with no identifier\n"); 1231414c70cbSLiam Girdwood return regulator; 1232414c70cbSLiam Girdwood } 1233414c70cbSLiam Girdwood 123440f9244fSMark Brown if (dev) 123540f9244fSMark Brown devname = dev_name(dev); 123640f9244fSMark Brown 1237414c70cbSLiam Girdwood mutex_lock(®ulator_list_mutex); 1238414c70cbSLiam Girdwood 12396d191a5fSMark Brown rdev = regulator_dev_lookup(dev, id, &ret); 124069511a45SRajendra Nayak if (rdev) 124169511a45SRajendra Nayak goto found; 124269511a45SRajendra Nayak 1243688fe99aSMark Brown if (board_wants_dummy_regulator) { 1244688fe99aSMark Brown rdev = dummy_regulator_rdev; 1245688fe99aSMark Brown goto found; 1246688fe99aSMark Brown } 1247688fe99aSMark Brown 124834abbd68SMark Brown #ifdef CONFIG_REGULATOR_DUMMY 124934abbd68SMark Brown if (!devname) 125034abbd68SMark Brown devname = "deviceless"; 125134abbd68SMark Brown 125234abbd68SMark Brown /* If the board didn't flag that it was fully constrained then 125334abbd68SMark Brown * substitute in a dummy regulator so consumers can continue. 125434abbd68SMark Brown */ 125534abbd68SMark Brown if (!has_full_constraints) { 12565da84fd9SJoe Perches pr_warn("%s supply %s not found, using dummy regulator\n", 125734abbd68SMark Brown devname, id); 125834abbd68SMark Brown rdev = dummy_regulator_rdev; 125934abbd68SMark Brown goto found; 126034abbd68SMark Brown } 126134abbd68SMark Brown #endif 126234abbd68SMark Brown 1263414c70cbSLiam Girdwood mutex_unlock(®ulator_list_mutex); 1264414c70cbSLiam Girdwood return regulator; 1265414c70cbSLiam Girdwood 1266414c70cbSLiam Girdwood found: 12675ffbd136SMark Brown if (rdev->exclusive) { 12685ffbd136SMark Brown regulator = ERR_PTR(-EPERM); 12695ffbd136SMark Brown goto out; 12705ffbd136SMark Brown } 12715ffbd136SMark Brown 12725ffbd136SMark Brown if (exclusive && rdev->open_count) { 12735ffbd136SMark Brown regulator = ERR_PTR(-EBUSY); 12745ffbd136SMark Brown goto out; 12755ffbd136SMark Brown } 12765ffbd136SMark Brown 1277a5766f11SLiam Girdwood if (!try_module_get(rdev->owner)) 1278a5766f11SLiam Girdwood goto out; 1279a5766f11SLiam Girdwood 1280414c70cbSLiam Girdwood regulator = create_regulator(rdev, dev, id); 1281414c70cbSLiam Girdwood if (regulator == NULL) { 1282414c70cbSLiam Girdwood regulator = ERR_PTR(-ENOMEM); 1283414c70cbSLiam Girdwood module_put(rdev->owner); 1284bcda4321SAxel Lin goto out; 1285414c70cbSLiam Girdwood } 1286414c70cbSLiam Girdwood 12875ffbd136SMark Brown rdev->open_count++; 12885ffbd136SMark Brown if (exclusive) { 12895ffbd136SMark Brown rdev->exclusive = 1; 12905ffbd136SMark Brown 12915ffbd136SMark Brown ret = _regulator_is_enabled(rdev); 12925ffbd136SMark Brown if (ret > 0) 12935ffbd136SMark Brown rdev->use_count = 1; 12945ffbd136SMark Brown else 12955ffbd136SMark Brown rdev->use_count = 0; 12965ffbd136SMark Brown } 12975ffbd136SMark Brown 1298a5766f11SLiam Girdwood out: 1299414c70cbSLiam Girdwood mutex_unlock(®ulator_list_mutex); 13005ffbd136SMark Brown 1301414c70cbSLiam Girdwood return regulator; 1302414c70cbSLiam Girdwood } 13035ffbd136SMark Brown 13045ffbd136SMark Brown /** 13055ffbd136SMark Brown * regulator_get - lookup and obtain a reference to a regulator. 13065ffbd136SMark Brown * @dev: device for regulator "consumer" 13075ffbd136SMark Brown * @id: Supply name or regulator ID. 13085ffbd136SMark Brown * 13095ffbd136SMark Brown * Returns a struct regulator corresponding to the regulator producer, 13105ffbd136SMark Brown * or IS_ERR() condition containing errno. 13115ffbd136SMark Brown * 13125ffbd136SMark Brown * Use of supply names configured via regulator_set_device_supply() is 13135ffbd136SMark Brown * strongly encouraged. It is recommended that the supply name used 13145ffbd136SMark Brown * should match the name used for the supply and/or the relevant 13155ffbd136SMark Brown * device pins in the datasheet. 13165ffbd136SMark Brown */ 13175ffbd136SMark Brown struct regulator *regulator_get(struct device *dev, const char *id) 13185ffbd136SMark Brown { 13195ffbd136SMark Brown return _regulator_get(dev, id, 0); 13205ffbd136SMark Brown } 1321414c70cbSLiam Girdwood EXPORT_SYMBOL_GPL(regulator_get); 1322414c70cbSLiam Girdwood 1323070b9079SStephen Boyd static void devm_regulator_release(struct device *dev, void *res) 1324070b9079SStephen Boyd { 1325070b9079SStephen Boyd regulator_put(*(struct regulator **)res); 1326070b9079SStephen Boyd } 1327070b9079SStephen Boyd 1328070b9079SStephen Boyd /** 1329070b9079SStephen Boyd * devm_regulator_get - Resource managed regulator_get() 1330070b9079SStephen Boyd * @dev: device for regulator "consumer" 1331070b9079SStephen Boyd * @id: Supply name or regulator ID. 1332070b9079SStephen Boyd * 1333070b9079SStephen Boyd * Managed regulator_get(). Regulators returned from this function are 1334070b9079SStephen Boyd * automatically regulator_put() on driver detach. See regulator_get() for more 1335070b9079SStephen Boyd * information. 1336070b9079SStephen Boyd */ 1337070b9079SStephen Boyd struct regulator *devm_regulator_get(struct device *dev, const char *id) 1338070b9079SStephen Boyd { 1339070b9079SStephen Boyd struct regulator **ptr, *regulator; 1340070b9079SStephen Boyd 1341070b9079SStephen Boyd ptr = devres_alloc(devm_regulator_release, sizeof(*ptr), GFP_KERNEL); 1342070b9079SStephen Boyd if (!ptr) 1343070b9079SStephen Boyd return ERR_PTR(-ENOMEM); 1344070b9079SStephen Boyd 1345070b9079SStephen Boyd regulator = regulator_get(dev, id); 1346070b9079SStephen Boyd if (!IS_ERR(regulator)) { 1347070b9079SStephen Boyd *ptr = regulator; 1348070b9079SStephen Boyd devres_add(dev, ptr); 1349070b9079SStephen Boyd } else { 1350070b9079SStephen Boyd devres_free(ptr); 1351070b9079SStephen Boyd } 1352070b9079SStephen Boyd 1353070b9079SStephen Boyd return regulator; 1354070b9079SStephen Boyd } 1355070b9079SStephen Boyd EXPORT_SYMBOL_GPL(devm_regulator_get); 1356070b9079SStephen Boyd 1357414c70cbSLiam Girdwood /** 13585ffbd136SMark Brown * regulator_get_exclusive - obtain exclusive access to a regulator. 13595ffbd136SMark Brown * @dev: device for regulator "consumer" 13605ffbd136SMark Brown * @id: Supply name or regulator ID. 13615ffbd136SMark Brown * 13625ffbd136SMark Brown * Returns a struct regulator corresponding to the regulator producer, 13635ffbd136SMark Brown * or IS_ERR() condition containing errno. Other consumers will be 13645ffbd136SMark Brown * unable to obtain this reference is held and the use count for the 13655ffbd136SMark Brown * regulator will be initialised to reflect the current state of the 13665ffbd136SMark Brown * regulator. 13675ffbd136SMark Brown * 13685ffbd136SMark Brown * This is intended for use by consumers which cannot tolerate shared 13695ffbd136SMark Brown * use of the regulator such as those which need to force the 13705ffbd136SMark Brown * regulator off for correct operation of the hardware they are 13715ffbd136SMark Brown * controlling. 13725ffbd136SMark Brown * 13735ffbd136SMark Brown * Use of supply names configured via regulator_set_device_supply() is 13745ffbd136SMark Brown * strongly encouraged. It is recommended that the supply name used 13755ffbd136SMark Brown * should match the name used for the supply and/or the relevant 13765ffbd136SMark Brown * device pins in the datasheet. 13775ffbd136SMark Brown */ 13785ffbd136SMark Brown struct regulator *regulator_get_exclusive(struct device *dev, const char *id) 13795ffbd136SMark Brown { 13805ffbd136SMark Brown return _regulator_get(dev, id, 1); 13815ffbd136SMark Brown } 13825ffbd136SMark Brown EXPORT_SYMBOL_GPL(regulator_get_exclusive); 13835ffbd136SMark Brown 138423ff2f0fSCharles Keepax /* Locks held by regulator_put() */ 138523ff2f0fSCharles Keepax static void _regulator_put(struct regulator *regulator) 1386414c70cbSLiam Girdwood { 1387414c70cbSLiam Girdwood struct regulator_dev *rdev; 1388414c70cbSLiam Girdwood 1389414c70cbSLiam Girdwood if (regulator == NULL || IS_ERR(regulator)) 1390414c70cbSLiam Girdwood return; 1391414c70cbSLiam Girdwood 1392414c70cbSLiam Girdwood rdev = regulator->rdev; 1393414c70cbSLiam Girdwood 13945de70519SMark Brown debugfs_remove_recursive(regulator->debugfs); 13955de70519SMark Brown 1396414c70cbSLiam Girdwood /* remove any sysfs entries */ 1397e2c98eafSShawn Guo if (regulator->dev) 1398414c70cbSLiam Girdwood sysfs_remove_link(&rdev->dev.kobj, regulator->supply_name); 13995de70519SMark Brown kfree(regulator->supply_name); 1400414c70cbSLiam Girdwood list_del(®ulator->list); 1401414c70cbSLiam Girdwood kfree(regulator); 1402414c70cbSLiam Girdwood 14035ffbd136SMark Brown rdev->open_count--; 14045ffbd136SMark Brown rdev->exclusive = 0; 14055ffbd136SMark Brown 1406414c70cbSLiam Girdwood module_put(rdev->owner); 140723ff2f0fSCharles Keepax } 140823ff2f0fSCharles Keepax 140923ff2f0fSCharles Keepax /** 141023ff2f0fSCharles Keepax * regulator_put - "free" the regulator source 141123ff2f0fSCharles Keepax * @regulator: regulator source 141223ff2f0fSCharles Keepax * 141323ff2f0fSCharles Keepax * Note: drivers must ensure that all regulator_enable calls made on this 141423ff2f0fSCharles Keepax * regulator source are balanced by regulator_disable calls prior to calling 141523ff2f0fSCharles Keepax * this function. 141623ff2f0fSCharles Keepax */ 141723ff2f0fSCharles Keepax void regulator_put(struct regulator *regulator) 141823ff2f0fSCharles Keepax { 141923ff2f0fSCharles Keepax mutex_lock(®ulator_list_mutex); 142023ff2f0fSCharles Keepax _regulator_put(regulator); 1421414c70cbSLiam Girdwood mutex_unlock(®ulator_list_mutex); 1422414c70cbSLiam Girdwood } 1423414c70cbSLiam Girdwood EXPORT_SYMBOL_GPL(regulator_put); 1424414c70cbSLiam Girdwood 1425d5ad34f7SMark Brown static int devm_regulator_match(struct device *dev, void *res, void *data) 1426d5ad34f7SMark Brown { 1427d5ad34f7SMark Brown struct regulator **r = res; 1428d5ad34f7SMark Brown if (!r || !*r) { 1429d5ad34f7SMark Brown WARN_ON(!r || !*r); 1430d5ad34f7SMark Brown return 0; 1431d5ad34f7SMark Brown } 1432d5ad34f7SMark Brown return *r == data; 1433d5ad34f7SMark Brown } 1434d5ad34f7SMark Brown 1435d5ad34f7SMark Brown /** 1436d5ad34f7SMark Brown * devm_regulator_put - Resource managed regulator_put() 1437d5ad34f7SMark Brown * @regulator: regulator to free 1438d5ad34f7SMark Brown * 1439d5ad34f7SMark Brown * Deallocate a regulator allocated with devm_regulator_get(). Normally 1440d5ad34f7SMark Brown * this function will not need to be called and the resource management 1441d5ad34f7SMark Brown * code will ensure that the resource is freed. 1442d5ad34f7SMark Brown */ 1443d5ad34f7SMark Brown void devm_regulator_put(struct regulator *regulator) 1444d5ad34f7SMark Brown { 1445d5ad34f7SMark Brown int rc; 1446d5ad34f7SMark Brown 1447361ff501SMark Brown rc = devres_release(regulator->dev, devm_regulator_release, 1448d5ad34f7SMark Brown devm_regulator_match, regulator); 1449230a5a1cSMark Brown if (rc != 0) 1450d5ad34f7SMark Brown WARN_ON(rc); 1451d5ad34f7SMark Brown } 1452d5ad34f7SMark Brown EXPORT_SYMBOL_GPL(devm_regulator_put); 1453d5ad34f7SMark Brown 14545c5659d0SMark Brown static int _regulator_do_enable(struct regulator_dev *rdev) 14555c5659d0SMark Brown { 14565c5659d0SMark Brown int ret, delay; 14575c5659d0SMark Brown 14585c5659d0SMark Brown /* Query before enabling in case configuration dependent. */ 14595c5659d0SMark Brown ret = _regulator_get_enable_time(rdev); 14605c5659d0SMark Brown if (ret >= 0) { 14615c5659d0SMark Brown delay = ret; 14625c5659d0SMark Brown } else { 14635c5659d0SMark Brown rdev_warn(rdev, "enable_time() failed: %d\n", ret); 14645c5659d0SMark Brown delay = 0; 14655c5659d0SMark Brown } 14665c5659d0SMark Brown 14675c5659d0SMark Brown trace_regulator_enable(rdev_get_name(rdev)); 14685c5659d0SMark Brown 146965f73508SMark Brown if (rdev->ena_gpio) { 147065f73508SMark Brown gpio_set_value_cansleep(rdev->ena_gpio, 147165f73508SMark Brown !rdev->ena_gpio_invert); 147265f73508SMark Brown rdev->ena_gpio_state = 1; 147365f73508SMark Brown } else if (rdev->desc->ops->enable) { 14745c5659d0SMark Brown ret = rdev->desc->ops->enable(rdev); 14755c5659d0SMark Brown if (ret < 0) 14765c5659d0SMark Brown return ret; 14775c5659d0SMark Brown } else { 14785c5659d0SMark Brown return -EINVAL; 14795c5659d0SMark Brown } 14805c5659d0SMark Brown 14815c5659d0SMark Brown /* Allow the regulator to ramp; it would be useful to extend 14825c5659d0SMark Brown * this for bulk operations so that the regulators can ramp 14835c5659d0SMark Brown * together. */ 14845c5659d0SMark Brown trace_regulator_enable_delay(rdev_get_name(rdev)); 14855c5659d0SMark Brown 14865c5659d0SMark Brown if (delay >= 1000) { 14875c5659d0SMark Brown mdelay(delay / 1000); 14885c5659d0SMark Brown udelay(delay % 1000); 14895c5659d0SMark Brown } else if (delay) { 14905c5659d0SMark Brown udelay(delay); 14915c5659d0SMark Brown } 14925c5659d0SMark Brown 14935c5659d0SMark Brown trace_regulator_enable_complete(rdev_get_name(rdev)); 14945c5659d0SMark Brown 14955c5659d0SMark Brown return 0; 14965c5659d0SMark Brown } 14975c5659d0SMark Brown 1498414c70cbSLiam Girdwood /* locks held by regulator_enable() */ 1499414c70cbSLiam Girdwood static int _regulator_enable(struct regulator_dev *rdev) 1500414c70cbSLiam Girdwood { 15015c5659d0SMark Brown int ret; 1502414c70cbSLiam Girdwood 1503414c70cbSLiam Girdwood /* check voltage and requested load before enabling */ 1504414c70cbSLiam Girdwood if (rdev->constraints && 15059a2372faSMark Brown (rdev->constraints->valid_ops_mask & REGULATOR_CHANGE_DRMS)) 1506414c70cbSLiam Girdwood drms_uA_update(rdev); 1507414c70cbSLiam Girdwood 15089a2372faSMark Brown if (rdev->use_count == 0) { 15099a2372faSMark Brown /* The regulator may on if it's not switchable or left on */ 15109a2372faSMark Brown ret = _regulator_is_enabled(rdev); 15119a2372faSMark Brown if (ret == -EINVAL || ret == 0) { 15129a2372faSMark Brown if (!_regulator_can_change_status(rdev)) 15139a2372faSMark Brown return -EPERM; 15149a2372faSMark Brown 15155c5659d0SMark Brown ret = _regulator_do_enable(rdev); 15169a2372faSMark Brown if (ret < 0) 15179a2372faSMark Brown return ret; 151831aae2beSMark Brown 1519a7433cffSLinus Walleij } else if (ret < 0) { 15205da84fd9SJoe Perches rdev_err(rdev, "is_enabled() failed: %d\n", ret); 1521414c70cbSLiam Girdwood return ret; 1522414c70cbSLiam Girdwood } 1523a7433cffSLinus Walleij /* Fallthrough on positive return values - already enabled */ 1524414c70cbSLiam Girdwood } 1525414c70cbSLiam Girdwood 15269a2372faSMark Brown rdev->use_count++; 15279a2372faSMark Brown 15289a2372faSMark Brown return 0; 1529414c70cbSLiam Girdwood } 1530414c70cbSLiam Girdwood 1531414c70cbSLiam Girdwood /** 1532414c70cbSLiam Girdwood * regulator_enable - enable regulator output 1533414c70cbSLiam Girdwood * @regulator: regulator source 1534414c70cbSLiam Girdwood * 1535cf7bbcdfSMark Brown * Request that the regulator be enabled with the regulator output at 1536cf7bbcdfSMark Brown * the predefined voltage or current value. Calls to regulator_enable() 1537cf7bbcdfSMark Brown * must be balanced with calls to regulator_disable(). 1538cf7bbcdfSMark Brown * 1539414c70cbSLiam Girdwood * NOTE: the output value can be set by other drivers, boot loader or may be 1540cf7bbcdfSMark Brown * hardwired in the regulator. 1541414c70cbSLiam Girdwood */ 1542414c70cbSLiam Girdwood int regulator_enable(struct regulator *regulator) 1543414c70cbSLiam Girdwood { 1544412aec61SDavid Brownell struct regulator_dev *rdev = regulator->rdev; 1545412aec61SDavid Brownell int ret = 0; 1546414c70cbSLiam Girdwood 15476492bc1bSMark Brown if (regulator->always_on) 15486492bc1bSMark Brown return 0; 15496492bc1bSMark Brown 15503801b86aSMark Brown if (rdev->supply) { 15513801b86aSMark Brown ret = regulator_enable(rdev->supply); 15523801b86aSMark Brown if (ret != 0) 15533801b86aSMark Brown return ret; 15543801b86aSMark Brown } 15553801b86aSMark Brown 1556412aec61SDavid Brownell mutex_lock(&rdev->mutex); 1557412aec61SDavid Brownell ret = _regulator_enable(rdev); 1558412aec61SDavid Brownell mutex_unlock(&rdev->mutex); 15593801b86aSMark Brown 1560d1685e4eSHeiko Stübner if (ret != 0 && rdev->supply) 15613801b86aSMark Brown regulator_disable(rdev->supply); 15623801b86aSMark Brown 1563414c70cbSLiam Girdwood return ret; 1564414c70cbSLiam Girdwood } 1565414c70cbSLiam Girdwood EXPORT_SYMBOL_GPL(regulator_enable); 1566414c70cbSLiam Girdwood 15675c5659d0SMark Brown static int _regulator_do_disable(struct regulator_dev *rdev) 15685c5659d0SMark Brown { 15695c5659d0SMark Brown int ret; 15705c5659d0SMark Brown 15715c5659d0SMark Brown trace_regulator_disable(rdev_get_name(rdev)); 15725c5659d0SMark Brown 15735c5659d0SMark Brown if (rdev->ena_gpio) { 15745c5659d0SMark Brown gpio_set_value_cansleep(rdev->ena_gpio, 15755c5659d0SMark Brown rdev->ena_gpio_invert); 15765c5659d0SMark Brown rdev->ena_gpio_state = 0; 15775c5659d0SMark Brown 15785c5659d0SMark Brown } else if (rdev->desc->ops->disable) { 15795c5659d0SMark Brown ret = rdev->desc->ops->disable(rdev); 15805c5659d0SMark Brown if (ret != 0) 15815c5659d0SMark Brown return ret; 15825c5659d0SMark Brown } 15835c5659d0SMark Brown 15845c5659d0SMark Brown trace_regulator_disable_complete(rdev_get_name(rdev)); 15855c5659d0SMark Brown 15865c5659d0SMark Brown _notifier_call_chain(rdev, REGULATOR_EVENT_DISABLE, 15875c5659d0SMark Brown NULL); 15885c5659d0SMark Brown return 0; 15895c5659d0SMark Brown } 15905c5659d0SMark Brown 1591414c70cbSLiam Girdwood /* locks held by regulator_disable() */ 15923801b86aSMark Brown static int _regulator_disable(struct regulator_dev *rdev) 1593414c70cbSLiam Girdwood { 1594414c70cbSLiam Girdwood int ret = 0; 1595414c70cbSLiam Girdwood 1596cd94b505SDavid Brownell if (WARN(rdev->use_count <= 0, 159743e7ee33SJoe Perches "unbalanced disables for %s\n", rdev_get_name(rdev))) 1598cd94b505SDavid Brownell return -EIO; 1599cd94b505SDavid Brownell 1600414c70cbSLiam Girdwood /* are we the last user and permitted to disable ? */ 160160ef66fcSMark Brown if (rdev->use_count == 1 && 160260ef66fcSMark Brown (rdev->constraints && !rdev->constraints->always_on)) { 1603414c70cbSLiam Girdwood 1604414c70cbSLiam Girdwood /* we are last user */ 16055c5659d0SMark Brown if (_regulator_can_change_status(rdev)) { 16065c5659d0SMark Brown ret = _regulator_do_disable(rdev); 1607414c70cbSLiam Girdwood if (ret < 0) { 16085da84fd9SJoe Perches rdev_err(rdev, "failed to disable\n"); 1609414c70cbSLiam Girdwood return ret; 1610414c70cbSLiam Girdwood } 1611414c70cbSLiam Girdwood } 1612414c70cbSLiam Girdwood 1613414c70cbSLiam Girdwood rdev->use_count = 0; 1614414c70cbSLiam Girdwood } else if (rdev->use_count > 1) { 1615414c70cbSLiam Girdwood 1616414c70cbSLiam Girdwood if (rdev->constraints && 1617414c70cbSLiam Girdwood (rdev->constraints->valid_ops_mask & 1618414c70cbSLiam Girdwood REGULATOR_CHANGE_DRMS)) 1619414c70cbSLiam Girdwood drms_uA_update(rdev); 1620414c70cbSLiam Girdwood 1621414c70cbSLiam Girdwood rdev->use_count--; 1622414c70cbSLiam Girdwood } 16233801b86aSMark Brown 1624414c70cbSLiam Girdwood return ret; 1625414c70cbSLiam Girdwood } 1626414c70cbSLiam Girdwood 1627414c70cbSLiam Girdwood /** 1628414c70cbSLiam Girdwood * regulator_disable - disable regulator output 1629414c70cbSLiam Girdwood * @regulator: regulator source 1630414c70cbSLiam Girdwood * 1631cf7bbcdfSMark Brown * Disable the regulator output voltage or current. Calls to 1632cf7bbcdfSMark Brown * regulator_enable() must be balanced with calls to 1633cf7bbcdfSMark Brown * regulator_disable(). 163469279fb9SMark Brown * 1635414c70cbSLiam Girdwood * NOTE: this will only disable the regulator output if no other consumer 1636cf7bbcdfSMark Brown * devices have it enabled, the regulator device supports disabling and 1637cf7bbcdfSMark Brown * machine constraints permit this operation. 1638414c70cbSLiam Girdwood */ 1639414c70cbSLiam Girdwood int regulator_disable(struct regulator *regulator) 1640414c70cbSLiam Girdwood { 1641412aec61SDavid Brownell struct regulator_dev *rdev = regulator->rdev; 1642412aec61SDavid Brownell int ret = 0; 1643414c70cbSLiam Girdwood 16446492bc1bSMark Brown if (regulator->always_on) 16456492bc1bSMark Brown return 0; 16466492bc1bSMark Brown 1647412aec61SDavid Brownell mutex_lock(&rdev->mutex); 16483801b86aSMark Brown ret = _regulator_disable(rdev); 1649412aec61SDavid Brownell mutex_unlock(&rdev->mutex); 16508cbf811dSJeffrey Carlyle 16513801b86aSMark Brown if (ret == 0 && rdev->supply) 16523801b86aSMark Brown regulator_disable(rdev->supply); 16538cbf811dSJeffrey Carlyle 1654414c70cbSLiam Girdwood return ret; 1655414c70cbSLiam Girdwood } 1656414c70cbSLiam Girdwood EXPORT_SYMBOL_GPL(regulator_disable); 1657414c70cbSLiam Girdwood 1658414c70cbSLiam Girdwood /* locks held by regulator_force_disable() */ 16593801b86aSMark Brown static int _regulator_force_disable(struct regulator_dev *rdev) 1660414c70cbSLiam Girdwood { 1661414c70cbSLiam Girdwood int ret = 0; 1662414c70cbSLiam Girdwood 1663414c70cbSLiam Girdwood /* force disable */ 1664414c70cbSLiam Girdwood if (rdev->desc->ops->disable) { 1665414c70cbSLiam Girdwood /* ah well, who wants to live forever... */ 1666414c70cbSLiam Girdwood ret = rdev->desc->ops->disable(rdev); 1667414c70cbSLiam Girdwood if (ret < 0) { 16685da84fd9SJoe Perches rdev_err(rdev, "failed to force disable\n"); 1669414c70cbSLiam Girdwood return ret; 1670414c70cbSLiam Girdwood } 1671414c70cbSLiam Girdwood /* notify other consumers that power has been forced off */ 167284b68263SMark Brown _notifier_call_chain(rdev, REGULATOR_EVENT_FORCE_DISABLE | 167384b68263SMark Brown REGULATOR_EVENT_DISABLE, NULL); 1674414c70cbSLiam Girdwood } 1675414c70cbSLiam Girdwood 1676414c70cbSLiam Girdwood return ret; 1677414c70cbSLiam Girdwood } 1678414c70cbSLiam Girdwood 1679414c70cbSLiam Girdwood /** 1680414c70cbSLiam Girdwood * regulator_force_disable - force disable regulator output 1681414c70cbSLiam Girdwood * @regulator: regulator source 1682414c70cbSLiam Girdwood * 1683414c70cbSLiam Girdwood * Forcibly disable the regulator output voltage or current. 1684414c70cbSLiam Girdwood * NOTE: this *will* disable the regulator output even if other consumer 1685414c70cbSLiam Girdwood * devices have it enabled. This should be used for situations when device 1686414c70cbSLiam Girdwood * damage will likely occur if the regulator is not disabled (e.g. over temp). 1687414c70cbSLiam Girdwood */ 1688414c70cbSLiam Girdwood int regulator_force_disable(struct regulator *regulator) 1689414c70cbSLiam Girdwood { 169082d15839SMark Brown struct regulator_dev *rdev = regulator->rdev; 1691414c70cbSLiam Girdwood int ret; 1692414c70cbSLiam Girdwood 169382d15839SMark Brown mutex_lock(&rdev->mutex); 1694414c70cbSLiam Girdwood regulator->uA_load = 0; 16953801b86aSMark Brown ret = _regulator_force_disable(regulator->rdev); 169682d15839SMark Brown mutex_unlock(&rdev->mutex); 16978cbf811dSJeffrey Carlyle 16983801b86aSMark Brown if (rdev->supply) 16993801b86aSMark Brown while (rdev->open_count--) 17003801b86aSMark Brown regulator_disable(rdev->supply); 17018cbf811dSJeffrey Carlyle 1702414c70cbSLiam Girdwood return ret; 1703414c70cbSLiam Girdwood } 1704414c70cbSLiam Girdwood EXPORT_SYMBOL_GPL(regulator_force_disable); 1705414c70cbSLiam Girdwood 1706da07ecd9SMark Brown static void regulator_disable_work(struct work_struct *work) 1707da07ecd9SMark Brown { 1708da07ecd9SMark Brown struct regulator_dev *rdev = container_of(work, struct regulator_dev, 1709da07ecd9SMark Brown disable_work.work); 1710da07ecd9SMark Brown int count, i, ret; 1711da07ecd9SMark Brown 1712da07ecd9SMark Brown mutex_lock(&rdev->mutex); 1713da07ecd9SMark Brown 1714da07ecd9SMark Brown BUG_ON(!rdev->deferred_disables); 1715da07ecd9SMark Brown 1716da07ecd9SMark Brown count = rdev->deferred_disables; 1717da07ecd9SMark Brown rdev->deferred_disables = 0; 1718da07ecd9SMark Brown 1719da07ecd9SMark Brown for (i = 0; i < count; i++) { 1720da07ecd9SMark Brown ret = _regulator_disable(rdev); 1721da07ecd9SMark Brown if (ret != 0) 1722da07ecd9SMark Brown rdev_err(rdev, "Deferred disable failed: %d\n", ret); 1723da07ecd9SMark Brown } 1724da07ecd9SMark Brown 1725da07ecd9SMark Brown mutex_unlock(&rdev->mutex); 1726da07ecd9SMark Brown 1727da07ecd9SMark Brown if (rdev->supply) { 1728da07ecd9SMark Brown for (i = 0; i < count; i++) { 1729da07ecd9SMark Brown ret = regulator_disable(rdev->supply); 1730da07ecd9SMark Brown if (ret != 0) { 1731da07ecd9SMark Brown rdev_err(rdev, 1732da07ecd9SMark Brown "Supply disable failed: %d\n", ret); 1733da07ecd9SMark Brown } 1734da07ecd9SMark Brown } 1735da07ecd9SMark Brown } 1736da07ecd9SMark Brown } 1737da07ecd9SMark Brown 1738da07ecd9SMark Brown /** 1739da07ecd9SMark Brown * regulator_disable_deferred - disable regulator output with delay 1740da07ecd9SMark Brown * @regulator: regulator source 1741da07ecd9SMark Brown * @ms: miliseconds until the regulator is disabled 1742da07ecd9SMark Brown * 1743da07ecd9SMark Brown * Execute regulator_disable() on the regulator after a delay. This 1744da07ecd9SMark Brown * is intended for use with devices that require some time to quiesce. 1745da07ecd9SMark Brown * 1746da07ecd9SMark Brown * NOTE: this will only disable the regulator output if no other consumer 1747da07ecd9SMark Brown * devices have it enabled, the regulator device supports disabling and 1748da07ecd9SMark Brown * machine constraints permit this operation. 1749da07ecd9SMark Brown */ 1750da07ecd9SMark Brown int regulator_disable_deferred(struct regulator *regulator, int ms) 1751da07ecd9SMark Brown { 1752da07ecd9SMark Brown struct regulator_dev *rdev = regulator->rdev; 1753aa59802dSMark Brown int ret; 1754da07ecd9SMark Brown 17556492bc1bSMark Brown if (regulator->always_on) 17566492bc1bSMark Brown return 0; 17576492bc1bSMark Brown 17582b5a24a0SMark Brown if (!ms) 17592b5a24a0SMark Brown return regulator_disable(regulator); 17602b5a24a0SMark Brown 1761da07ecd9SMark Brown mutex_lock(&rdev->mutex); 1762da07ecd9SMark Brown rdev->deferred_disables++; 1763da07ecd9SMark Brown mutex_unlock(&rdev->mutex); 1764da07ecd9SMark Brown 1765aa59802dSMark Brown ret = schedule_delayed_work(&rdev->disable_work, 1766da07ecd9SMark Brown msecs_to_jiffies(ms)); 1767aa59802dSMark Brown if (ret < 0) 1768aa59802dSMark Brown return ret; 1769aa59802dSMark Brown else 1770aa59802dSMark Brown return 0; 1771da07ecd9SMark Brown } 1772da07ecd9SMark Brown EXPORT_SYMBOL_GPL(regulator_disable_deferred); 1773da07ecd9SMark Brown 1774cd6dffb4SMark Brown /** 1775cd6dffb4SMark Brown * regulator_is_enabled_regmap - standard is_enabled() for regmap users 1776cd6dffb4SMark Brown * 1777cd6dffb4SMark Brown * @rdev: regulator to operate on 1778cd6dffb4SMark Brown * 1779cd6dffb4SMark Brown * Regulators that use regmap for their register I/O can set the 1780cd6dffb4SMark Brown * enable_reg and enable_mask fields in their descriptor and then use 1781cd6dffb4SMark Brown * this as their is_enabled operation, saving some code. 1782cd6dffb4SMark Brown */ 1783cd6dffb4SMark Brown int regulator_is_enabled_regmap(struct regulator_dev *rdev) 1784cd6dffb4SMark Brown { 1785cd6dffb4SMark Brown unsigned int val; 1786cd6dffb4SMark Brown int ret; 1787cd6dffb4SMark Brown 1788cd6dffb4SMark Brown ret = regmap_read(rdev->regmap, rdev->desc->enable_reg, &val); 1789cd6dffb4SMark Brown if (ret != 0) 1790cd6dffb4SMark Brown return ret; 1791cd6dffb4SMark Brown 1792cd6dffb4SMark Brown return (val & rdev->desc->enable_mask) != 0; 1793cd6dffb4SMark Brown } 1794cd6dffb4SMark Brown EXPORT_SYMBOL_GPL(regulator_is_enabled_regmap); 1795cd6dffb4SMark Brown 1796cd6dffb4SMark Brown /** 1797cd6dffb4SMark Brown * regulator_enable_regmap - standard enable() for regmap users 1798cd6dffb4SMark Brown * 1799cd6dffb4SMark Brown * @rdev: regulator to operate on 1800cd6dffb4SMark Brown * 1801cd6dffb4SMark Brown * Regulators that use regmap for their register I/O can set the 1802cd6dffb4SMark Brown * enable_reg and enable_mask fields in their descriptor and then use 1803cd6dffb4SMark Brown * this as their enable() operation, saving some code. 1804cd6dffb4SMark Brown */ 1805cd6dffb4SMark Brown int regulator_enable_regmap(struct regulator_dev *rdev) 1806cd6dffb4SMark Brown { 1807cd6dffb4SMark Brown return regmap_update_bits(rdev->regmap, rdev->desc->enable_reg, 1808cd6dffb4SMark Brown rdev->desc->enable_mask, 1809cd6dffb4SMark Brown rdev->desc->enable_mask); 1810cd6dffb4SMark Brown } 1811cd6dffb4SMark Brown EXPORT_SYMBOL_GPL(regulator_enable_regmap); 1812cd6dffb4SMark Brown 1813cd6dffb4SMark Brown /** 1814cd6dffb4SMark Brown * regulator_disable_regmap - standard disable() for regmap users 1815cd6dffb4SMark Brown * 1816cd6dffb4SMark Brown * @rdev: regulator to operate on 1817cd6dffb4SMark Brown * 1818cd6dffb4SMark Brown * Regulators that use regmap for their register I/O can set the 1819cd6dffb4SMark Brown * enable_reg and enable_mask fields in their descriptor and then use 1820cd6dffb4SMark Brown * this as their disable() operation, saving some code. 1821cd6dffb4SMark Brown */ 1822cd6dffb4SMark Brown int regulator_disable_regmap(struct regulator_dev *rdev) 1823cd6dffb4SMark Brown { 1824cd6dffb4SMark Brown return regmap_update_bits(rdev->regmap, rdev->desc->enable_reg, 1825cd6dffb4SMark Brown rdev->desc->enable_mask, 0); 1826cd6dffb4SMark Brown } 1827cd6dffb4SMark Brown EXPORT_SYMBOL_GPL(regulator_disable_regmap); 1828cd6dffb4SMark Brown 1829414c70cbSLiam Girdwood static int _regulator_is_enabled(struct regulator_dev *rdev) 1830414c70cbSLiam Girdwood { 183165f73508SMark Brown /* A GPIO control always takes precedence */ 183265f73508SMark Brown if (rdev->ena_gpio) 183365f73508SMark Brown return rdev->ena_gpio_state; 183465f73508SMark Brown 18359a7f6a4cSMark Brown /* If we don't know then assume that the regulator is always on */ 18369332546fSMark Brown if (!rdev->desc->ops->is_enabled) 18379a7f6a4cSMark Brown return 1; 1838414c70cbSLiam Girdwood 18399332546fSMark Brown return rdev->desc->ops->is_enabled(rdev); 1840414c70cbSLiam Girdwood } 1841414c70cbSLiam Girdwood 1842414c70cbSLiam Girdwood /** 1843414c70cbSLiam Girdwood * regulator_is_enabled - is the regulator output enabled 1844414c70cbSLiam Girdwood * @regulator: regulator source 1845414c70cbSLiam Girdwood * 1846412aec61SDavid Brownell * Returns positive if the regulator driver backing the source/client 1847412aec61SDavid Brownell * has requested that the device be enabled, zero if it hasn't, else a 1848412aec61SDavid Brownell * negative errno code. 1849412aec61SDavid Brownell * 1850412aec61SDavid Brownell * Note that the device backing this regulator handle can have multiple 1851412aec61SDavid Brownell * users, so it might be enabled even if regulator_enable() was never 1852412aec61SDavid Brownell * called for this particular source. 1853414c70cbSLiam Girdwood */ 1854414c70cbSLiam Girdwood int regulator_is_enabled(struct regulator *regulator) 1855414c70cbSLiam Girdwood { 18569332546fSMark Brown int ret; 18579332546fSMark Brown 18586492bc1bSMark Brown if (regulator->always_on) 18596492bc1bSMark Brown return 1; 18606492bc1bSMark Brown 18619332546fSMark Brown mutex_lock(®ulator->rdev->mutex); 18629332546fSMark Brown ret = _regulator_is_enabled(regulator->rdev); 18639332546fSMark Brown mutex_unlock(®ulator->rdev->mutex); 18649332546fSMark Brown 18659332546fSMark Brown return ret; 1866414c70cbSLiam Girdwood } 1867414c70cbSLiam Girdwood EXPORT_SYMBOL_GPL(regulator_is_enabled); 1868414c70cbSLiam Girdwood 1869414c70cbSLiam Girdwood /** 18704367cfdcSDavid Brownell * regulator_count_voltages - count regulator_list_voltage() selectors 18714367cfdcSDavid Brownell * @regulator: regulator source 18724367cfdcSDavid Brownell * 18734367cfdcSDavid Brownell * Returns number of selectors, or negative errno. Selectors are 18744367cfdcSDavid Brownell * numbered starting at zero, and typically correspond to bitfields 18754367cfdcSDavid Brownell * in hardware registers. 18764367cfdcSDavid Brownell */ 18774367cfdcSDavid Brownell int regulator_count_voltages(struct regulator *regulator) 18784367cfdcSDavid Brownell { 18794367cfdcSDavid Brownell struct regulator_dev *rdev = regulator->rdev; 18804367cfdcSDavid Brownell 18814367cfdcSDavid Brownell return rdev->desc->n_voltages ? : -EINVAL; 18824367cfdcSDavid Brownell } 18834367cfdcSDavid Brownell EXPORT_SYMBOL_GPL(regulator_count_voltages); 18844367cfdcSDavid Brownell 18854367cfdcSDavid Brownell /** 1886bca7bbffSMark Brown * regulator_list_voltage_linear - List voltages with simple calculation 1887bca7bbffSMark Brown * 1888bca7bbffSMark Brown * @rdev: Regulator device 1889bca7bbffSMark Brown * @selector: Selector to convert into a voltage 1890bca7bbffSMark Brown * 1891bca7bbffSMark Brown * Regulators with a simple linear mapping between voltages and 1892bca7bbffSMark Brown * selectors can set min_uV and uV_step in the regulator descriptor 1893bca7bbffSMark Brown * and then use this function as their list_voltage() operation, 1894bca7bbffSMark Brown */ 1895bca7bbffSMark Brown int regulator_list_voltage_linear(struct regulator_dev *rdev, 1896bca7bbffSMark Brown unsigned int selector) 1897bca7bbffSMark Brown { 1898bca7bbffSMark Brown if (selector >= rdev->desc->n_voltages) 1899bca7bbffSMark Brown return -EINVAL; 190033234e79SAxel Lin if (selector < rdev->desc->linear_min_sel) 190133234e79SAxel Lin return 0; 190233234e79SAxel Lin 190333234e79SAxel Lin selector -= rdev->desc->linear_min_sel; 1904bca7bbffSMark Brown 1905bca7bbffSMark Brown return rdev->desc->min_uV + (rdev->desc->uV_step * selector); 1906bca7bbffSMark Brown } 1907bca7bbffSMark Brown EXPORT_SYMBOL_GPL(regulator_list_voltage_linear); 1908bca7bbffSMark Brown 1909bca7bbffSMark Brown /** 1910cffc9592SAxel Lin * regulator_list_voltage_table - List voltages with table based mapping 1911cffc9592SAxel Lin * 1912cffc9592SAxel Lin * @rdev: Regulator device 1913cffc9592SAxel Lin * @selector: Selector to convert into a voltage 1914cffc9592SAxel Lin * 1915cffc9592SAxel Lin * Regulators with table based mapping between voltages and 1916cffc9592SAxel Lin * selectors can set volt_table in the regulator descriptor 1917cffc9592SAxel Lin * and then use this function as their list_voltage() operation. 1918cffc9592SAxel Lin */ 1919cffc9592SAxel Lin int regulator_list_voltage_table(struct regulator_dev *rdev, 1920cffc9592SAxel Lin unsigned int selector) 1921cffc9592SAxel Lin { 1922cffc9592SAxel Lin if (!rdev->desc->volt_table) { 1923cffc9592SAxel Lin BUG_ON(!rdev->desc->volt_table); 1924cffc9592SAxel Lin return -EINVAL; 1925cffc9592SAxel Lin } 1926cffc9592SAxel Lin 1927cffc9592SAxel Lin if (selector >= rdev->desc->n_voltages) 1928cffc9592SAxel Lin return -EINVAL; 1929cffc9592SAxel Lin 1930cffc9592SAxel Lin return rdev->desc->volt_table[selector]; 1931cffc9592SAxel Lin } 1932cffc9592SAxel Lin EXPORT_SYMBOL_GPL(regulator_list_voltage_table); 1933cffc9592SAxel Lin 1934cffc9592SAxel Lin /** 19354367cfdcSDavid Brownell * regulator_list_voltage - enumerate supported voltages 19364367cfdcSDavid Brownell * @regulator: regulator source 19374367cfdcSDavid Brownell * @selector: identify voltage to list 19384367cfdcSDavid Brownell * Context: can sleep 19394367cfdcSDavid Brownell * 19404367cfdcSDavid Brownell * Returns a voltage that can be passed to @regulator_set_voltage(), 194188393161SThomas Weber * zero if this selector code can't be used on this system, or a 19424367cfdcSDavid Brownell * negative errno. 19434367cfdcSDavid Brownell */ 19444367cfdcSDavid Brownell int regulator_list_voltage(struct regulator *regulator, unsigned selector) 19454367cfdcSDavid Brownell { 19464367cfdcSDavid Brownell struct regulator_dev *rdev = regulator->rdev; 19474367cfdcSDavid Brownell struct regulator_ops *ops = rdev->desc->ops; 19484367cfdcSDavid Brownell int ret; 19494367cfdcSDavid Brownell 19504367cfdcSDavid Brownell if (!ops->list_voltage || selector >= rdev->desc->n_voltages) 19514367cfdcSDavid Brownell return -EINVAL; 19524367cfdcSDavid Brownell 19534367cfdcSDavid Brownell mutex_lock(&rdev->mutex); 19544367cfdcSDavid Brownell ret = ops->list_voltage(rdev, selector); 19554367cfdcSDavid Brownell mutex_unlock(&rdev->mutex); 19564367cfdcSDavid Brownell 19574367cfdcSDavid Brownell if (ret > 0) { 19584367cfdcSDavid Brownell if (ret < rdev->constraints->min_uV) 19594367cfdcSDavid Brownell ret = 0; 19604367cfdcSDavid Brownell else if (ret > rdev->constraints->max_uV) 19614367cfdcSDavid Brownell ret = 0; 19624367cfdcSDavid Brownell } 19634367cfdcSDavid Brownell 19644367cfdcSDavid Brownell return ret; 19654367cfdcSDavid Brownell } 19664367cfdcSDavid Brownell EXPORT_SYMBOL_GPL(regulator_list_voltage); 19674367cfdcSDavid Brownell 19684367cfdcSDavid Brownell /** 1969a7a1ad90SMark Brown * regulator_is_supported_voltage - check if a voltage range can be supported 1970a7a1ad90SMark Brown * 1971a7a1ad90SMark Brown * @regulator: Regulator to check. 1972a7a1ad90SMark Brown * @min_uV: Minimum required voltage in uV. 1973a7a1ad90SMark Brown * @max_uV: Maximum required voltage in uV. 1974a7a1ad90SMark Brown * 1975a7a1ad90SMark Brown * Returns a boolean or a negative error code. 1976a7a1ad90SMark Brown */ 1977a7a1ad90SMark Brown int regulator_is_supported_voltage(struct regulator *regulator, 1978a7a1ad90SMark Brown int min_uV, int max_uV) 1979a7a1ad90SMark Brown { 1980c5f3939bSMark Brown struct regulator_dev *rdev = regulator->rdev; 1981a7a1ad90SMark Brown int i, voltages, ret; 1982a7a1ad90SMark Brown 1983c5f3939bSMark Brown /* If we can't change voltage check the current voltage */ 1984c5f3939bSMark Brown if (!(rdev->constraints->valid_ops_mask & REGULATOR_CHANGE_VOLTAGE)) { 1985c5f3939bSMark Brown ret = regulator_get_voltage(regulator); 1986c5f3939bSMark Brown if (ret >= 0) 1987f0f98b19SMarek Szyprowski return (min_uV <= ret && ret <= max_uV); 1988c5f3939bSMark Brown else 1989c5f3939bSMark Brown return ret; 1990c5f3939bSMark Brown } 1991c5f3939bSMark Brown 1992a7a1ad90SMark Brown ret = regulator_count_voltages(regulator); 1993a7a1ad90SMark Brown if (ret < 0) 1994a7a1ad90SMark Brown return ret; 1995a7a1ad90SMark Brown voltages = ret; 1996a7a1ad90SMark Brown 1997a7a1ad90SMark Brown for (i = 0; i < voltages; i++) { 1998a7a1ad90SMark Brown ret = regulator_list_voltage(regulator, i); 1999a7a1ad90SMark Brown 2000a7a1ad90SMark Brown if (ret >= min_uV && ret <= max_uV) 2001a7a1ad90SMark Brown return 1; 2002a7a1ad90SMark Brown } 2003a7a1ad90SMark Brown 2004a7a1ad90SMark Brown return 0; 2005a7a1ad90SMark Brown } 2006a398eaa2SMark Brown EXPORT_SYMBOL_GPL(regulator_is_supported_voltage); 2007a7a1ad90SMark Brown 20084ab5b3d9SMark Brown /** 20094ab5b3d9SMark Brown * regulator_get_voltage_sel_regmap - standard get_voltage_sel for regmap users 20104ab5b3d9SMark Brown * 20114ab5b3d9SMark Brown * @rdev: regulator to operate on 20124ab5b3d9SMark Brown * 20134ab5b3d9SMark Brown * Regulators that use regmap for their register I/O can set the 20144ab5b3d9SMark Brown * vsel_reg and vsel_mask fields in their descriptor and then use this 20154ab5b3d9SMark Brown * as their get_voltage_vsel operation, saving some code. 20164ab5b3d9SMark Brown */ 20174ab5b3d9SMark Brown int regulator_get_voltage_sel_regmap(struct regulator_dev *rdev) 20184ab5b3d9SMark Brown { 20194ab5b3d9SMark Brown unsigned int val; 20204ab5b3d9SMark Brown int ret; 20214ab5b3d9SMark Brown 20224ab5b3d9SMark Brown ret = regmap_read(rdev->regmap, rdev->desc->vsel_reg, &val); 20234ab5b3d9SMark Brown if (ret != 0) 20244ab5b3d9SMark Brown return ret; 20254ab5b3d9SMark Brown 20264ab5b3d9SMark Brown val &= rdev->desc->vsel_mask; 20274ab5b3d9SMark Brown val >>= ffs(rdev->desc->vsel_mask) - 1; 20284ab5b3d9SMark Brown 20294ab5b3d9SMark Brown return val; 20304ab5b3d9SMark Brown } 20314ab5b3d9SMark Brown EXPORT_SYMBOL_GPL(regulator_get_voltage_sel_regmap); 20324ab5b3d9SMark Brown 20334ab5b3d9SMark Brown /** 20344ab5b3d9SMark Brown * regulator_set_voltage_sel_regmap - standard set_voltage_sel for regmap users 20354ab5b3d9SMark Brown * 20364ab5b3d9SMark Brown * @rdev: regulator to operate on 20374ab5b3d9SMark Brown * @sel: Selector to set 20384ab5b3d9SMark Brown * 20394ab5b3d9SMark Brown * Regulators that use regmap for their register I/O can set the 20404ab5b3d9SMark Brown * vsel_reg and vsel_mask fields in their descriptor and then use this 20414ab5b3d9SMark Brown * as their set_voltage_vsel operation, saving some code. 20424ab5b3d9SMark Brown */ 20434ab5b3d9SMark Brown int regulator_set_voltage_sel_regmap(struct regulator_dev *rdev, unsigned sel) 20444ab5b3d9SMark Brown { 20454ab5b3d9SMark Brown sel <<= ffs(rdev->desc->vsel_mask) - 1; 20464ab5b3d9SMark Brown 20474ab5b3d9SMark Brown return regmap_update_bits(rdev->regmap, rdev->desc->vsel_reg, 20484ab5b3d9SMark Brown rdev->desc->vsel_mask, sel); 20494ab5b3d9SMark Brown } 20504ab5b3d9SMark Brown EXPORT_SYMBOL_GPL(regulator_set_voltage_sel_regmap); 20514ab5b3d9SMark Brown 2052e843fc46SMark Brown /** 2053e843fc46SMark Brown * regulator_map_voltage_iterate - map_voltage() based on list_voltage() 2054e843fc46SMark Brown * 2055e843fc46SMark Brown * @rdev: Regulator to operate on 2056e843fc46SMark Brown * @min_uV: Lower bound for voltage 2057e843fc46SMark Brown * @max_uV: Upper bound for voltage 2058e843fc46SMark Brown * 2059e843fc46SMark Brown * Drivers implementing set_voltage_sel() and list_voltage() can use 2060e843fc46SMark Brown * this as their map_voltage() operation. It will find a suitable 2061e843fc46SMark Brown * voltage by calling list_voltage() until it gets something in bounds 2062e843fc46SMark Brown * for the requested voltages. 2063e843fc46SMark Brown */ 2064e843fc46SMark Brown int regulator_map_voltage_iterate(struct regulator_dev *rdev, 206575790251SMark Brown int min_uV, int max_uV) 206675790251SMark Brown { 2067e8eef82bSMark Brown int best_val = INT_MAX; 2068e843fc46SMark Brown int selector = 0; 2069e843fc46SMark Brown int i, ret; 2070e8eef82bSMark Brown 2071e8eef82bSMark Brown /* Find the smallest voltage that falls within the specified 2072e8eef82bSMark Brown * range. 2073e8eef82bSMark Brown */ 2074e8eef82bSMark Brown for (i = 0; i < rdev->desc->n_voltages; i++) { 2075e8eef82bSMark Brown ret = rdev->desc->ops->list_voltage(rdev, i); 2076e8eef82bSMark Brown if (ret < 0) 2077e8eef82bSMark Brown continue; 2078e8eef82bSMark Brown 2079e8eef82bSMark Brown if (ret < best_val && ret >= min_uV && ret <= max_uV) { 2080e8eef82bSMark Brown best_val = ret; 2081e8eef82bSMark Brown selector = i; 2082e8eef82bSMark Brown } 2083e8eef82bSMark Brown } 2084e8eef82bSMark Brown 2085e843fc46SMark Brown if (best_val != INT_MAX) 2086e843fc46SMark Brown return selector; 2087e843fc46SMark Brown else 2088e843fc46SMark Brown return -EINVAL; 2089e843fc46SMark Brown } 2090e843fc46SMark Brown EXPORT_SYMBOL_GPL(regulator_map_voltage_iterate); 2091e843fc46SMark Brown 2092bca7bbffSMark Brown /** 2093bca7bbffSMark Brown * regulator_map_voltage_linear - map_voltage() for simple linear mappings 2094bca7bbffSMark Brown * 2095bca7bbffSMark Brown * @rdev: Regulator to operate on 2096bca7bbffSMark Brown * @min_uV: Lower bound for voltage 2097bca7bbffSMark Brown * @max_uV: Upper bound for voltage 2098bca7bbffSMark Brown * 2099bca7bbffSMark Brown * Drivers providing min_uV and uV_step in their regulator_desc can 2100bca7bbffSMark Brown * use this as their map_voltage() operation. 2101bca7bbffSMark Brown */ 2102bca7bbffSMark Brown int regulator_map_voltage_linear(struct regulator_dev *rdev, 2103bca7bbffSMark Brown int min_uV, int max_uV) 2104bca7bbffSMark Brown { 2105bca7bbffSMark Brown int ret, voltage; 2106bca7bbffSMark Brown 21075a6881e8SAxel Lin /* Allow uV_step to be 0 for fixed voltage */ 21085a6881e8SAxel Lin if (rdev->desc->n_voltages == 1 && rdev->desc->uV_step == 0) { 21095a6881e8SAxel Lin if (min_uV <= rdev->desc->min_uV && rdev->desc->min_uV <= max_uV) 21105a6881e8SAxel Lin return 0; 21115a6881e8SAxel Lin else 21125a6881e8SAxel Lin return -EINVAL; 21135a6881e8SAxel Lin } 21145a6881e8SAxel Lin 2115bca7bbffSMark Brown if (!rdev->desc->uV_step) { 2116bca7bbffSMark Brown BUG_ON(!rdev->desc->uV_step); 2117bca7bbffSMark Brown return -EINVAL; 2118bca7bbffSMark Brown } 2119bca7bbffSMark Brown 21200bdc81e4SAxel Lin if (min_uV < rdev->desc->min_uV) 21210bdc81e4SAxel Lin min_uV = rdev->desc->min_uV; 21220bdc81e4SAxel Lin 2123ccfcb1c3SAxel Lin ret = DIV_ROUND_UP(min_uV - rdev->desc->min_uV, rdev->desc->uV_step); 2124bca7bbffSMark Brown if (ret < 0) 2125bca7bbffSMark Brown return ret; 2126bca7bbffSMark Brown 212733234e79SAxel Lin ret += rdev->desc->linear_min_sel; 212833234e79SAxel Lin 2129bca7bbffSMark Brown /* Map back into a voltage to verify we're still in bounds */ 2130bca7bbffSMark Brown voltage = rdev->desc->ops->list_voltage(rdev, ret); 2131bca7bbffSMark Brown if (voltage < min_uV || voltage > max_uV) 2132bca7bbffSMark Brown return -EINVAL; 2133bca7bbffSMark Brown 2134bca7bbffSMark Brown return ret; 2135bca7bbffSMark Brown } 2136bca7bbffSMark Brown EXPORT_SYMBOL_GPL(regulator_map_voltage_linear); 2137bca7bbffSMark Brown 2138a7a1ad90SMark Brown static int _regulator_do_set_voltage(struct regulator_dev *rdev, 2139a7a1ad90SMark Brown int min_uV, int max_uV) 2140a7a1ad90SMark Brown { 2141a7a1ad90SMark Brown int ret; 214275790251SMark Brown int delay = 0; 2143e113d792SMark Brown int best_val = 0; 214475790251SMark Brown unsigned int selector; 2145eba41a5eSAxel Lin int old_selector = -1; 214675790251SMark Brown 214775790251SMark Brown trace_regulator_set_voltage(rdev_get_name(rdev), min_uV, max_uV); 214875790251SMark Brown 214975790251SMark Brown min_uV += rdev->constraints->uV_offset; 215075790251SMark Brown max_uV += rdev->constraints->uV_offset; 215175790251SMark Brown 215277af1b26SLinus Walleij /* 215377af1b26SLinus Walleij * If we can't obtain the old selector there is not enough 215477af1b26SLinus Walleij * info to call set_voltage_time_sel(). 215577af1b26SLinus Walleij */ 21568b7485efSAxel Lin if (_regulator_is_enabled(rdev) && 21578b7485efSAxel Lin rdev->desc->ops->set_voltage_time_sel && 215877af1b26SLinus Walleij rdev->desc->ops->get_voltage_sel) { 2159eba41a5eSAxel Lin old_selector = rdev->desc->ops->get_voltage_sel(rdev); 2160eba41a5eSAxel Lin if (old_selector < 0) 2161eba41a5eSAxel Lin return old_selector; 2162eba41a5eSAxel Lin } 216377af1b26SLinus Walleij 216475790251SMark Brown if (rdev->desc->ops->set_voltage) { 216575790251SMark Brown ret = rdev->desc->ops->set_voltage(rdev, min_uV, max_uV, 216675790251SMark Brown &selector); 2167e113d792SMark Brown 2168e113d792SMark Brown if (ret >= 0) { 2169e113d792SMark Brown if (rdev->desc->ops->list_voltage) 2170e113d792SMark Brown best_val = rdev->desc->ops->list_voltage(rdev, 2171e113d792SMark Brown selector); 2172e113d792SMark Brown else 2173e113d792SMark Brown best_val = _regulator_get_voltage(rdev); 2174e113d792SMark Brown } 2175e113d792SMark Brown 2176e8eef82bSMark Brown } else if (rdev->desc->ops->set_voltage_sel) { 21779152c36aSAxel Lin if (rdev->desc->ops->map_voltage) { 2178e843fc46SMark Brown ret = rdev->desc->ops->map_voltage(rdev, min_uV, 2179e843fc46SMark Brown max_uV); 21809152c36aSAxel Lin } else { 21819152c36aSAxel Lin if (rdev->desc->ops->list_voltage == 21829152c36aSAxel Lin regulator_list_voltage_linear) 21839152c36aSAxel Lin ret = regulator_map_voltage_linear(rdev, 21849152c36aSAxel Lin min_uV, max_uV); 218507351233SAxel Lin else 21869152c36aSAxel Lin ret = regulator_map_voltage_iterate(rdev, 21879152c36aSAxel Lin min_uV, max_uV); 21889152c36aSAxel Lin } 2189e843fc46SMark Brown 2190e843fc46SMark Brown if (ret >= 0) { 2191e113d792SMark Brown best_val = rdev->desc->ops->list_voltage(rdev, ret); 2192e113d792SMark Brown if (min_uV <= best_val && max_uV >= best_val) { 2193e843fc46SMark Brown selector = ret; 2194e113d792SMark Brown ret = rdev->desc->ops->set_voltage_sel(rdev, 2195e113d792SMark Brown ret); 2196e113d792SMark Brown } else { 2197e113d792SMark Brown ret = -EINVAL; 2198e113d792SMark Brown } 2199e843fc46SMark Brown } 2200e8eef82bSMark Brown } else { 2201e8eef82bSMark Brown ret = -EINVAL; 2202e8eef82bSMark Brown } 2203e8eef82bSMark Brown 2204eba41a5eSAxel Lin /* Call set_voltage_time_sel if successfully obtained old_selector */ 22055aff3a8bSMark Brown if (ret == 0 && _regulator_is_enabled(rdev) && old_selector >= 0 && 2206eba41a5eSAxel Lin rdev->desc->ops->set_voltage_time_sel) { 2207eba41a5eSAxel Lin 2208eba41a5eSAxel Lin delay = rdev->desc->ops->set_voltage_time_sel(rdev, 2209eba41a5eSAxel Lin old_selector, selector); 2210eba41a5eSAxel Lin if (delay < 0) { 2211eba41a5eSAxel Lin rdev_warn(rdev, "set_voltage_time_sel() failed: %d\n", 2212eba41a5eSAxel Lin delay); 2213eba41a5eSAxel Lin delay = 0; 2214e8eef82bSMark Brown } 221575790251SMark Brown 221677af1b26SLinus Walleij /* Insert any necessary delays */ 221777af1b26SLinus Walleij if (delay >= 1000) { 221877af1b26SLinus Walleij mdelay(delay / 1000); 221977af1b26SLinus Walleij udelay(delay % 1000); 222077af1b26SLinus Walleij } else if (delay) { 222177af1b26SLinus Walleij udelay(delay); 222277af1b26SLinus Walleij } 22238b96de31SPhilip Rakity } 222477af1b26SLinus Walleij 22252f6c797fSAxel Lin if (ret == 0 && best_val >= 0) { 22262f6c797fSAxel Lin unsigned long data = best_val; 22272f6c797fSAxel Lin 2228ded06a52SMark Brown _notifier_call_chain(rdev, REGULATOR_EVENT_VOLTAGE_CHANGE, 22292f6c797fSAxel Lin (void *)data); 22302f6c797fSAxel Lin } 2231ded06a52SMark Brown 2232eba41a5eSAxel Lin trace_regulator_set_voltage_complete(rdev_get_name(rdev), best_val); 223375790251SMark Brown 223475790251SMark Brown return ret; 223575790251SMark Brown } 223675790251SMark Brown 2237a7a1ad90SMark Brown /** 2238414c70cbSLiam Girdwood * regulator_set_voltage - set regulator output voltage 2239414c70cbSLiam Girdwood * @regulator: regulator source 2240414c70cbSLiam Girdwood * @min_uV: Minimum required voltage in uV 2241414c70cbSLiam Girdwood * @max_uV: Maximum acceptable voltage in uV 2242414c70cbSLiam Girdwood * 2243414c70cbSLiam Girdwood * Sets a voltage regulator to the desired output voltage. This can be set 2244414c70cbSLiam Girdwood * during any regulator state. IOW, regulator can be disabled or enabled. 2245414c70cbSLiam Girdwood * 2246414c70cbSLiam Girdwood * If the regulator is enabled then the voltage will change to the new value 2247414c70cbSLiam Girdwood * immediately otherwise if the regulator is disabled the regulator will 2248414c70cbSLiam Girdwood * output at the new voltage when enabled. 2249414c70cbSLiam Girdwood * 2250414c70cbSLiam Girdwood * NOTE: If the regulator is shared between several devices then the lowest 2251414c70cbSLiam Girdwood * request voltage that meets the system constraints will be used. 225269279fb9SMark Brown * Regulator system constraints must be set for this regulator before 2253414c70cbSLiam Girdwood * calling this function otherwise this call will fail. 2254414c70cbSLiam Girdwood */ 2255414c70cbSLiam Girdwood int regulator_set_voltage(struct regulator *regulator, int min_uV, int max_uV) 2256414c70cbSLiam Girdwood { 2257414c70cbSLiam Girdwood struct regulator_dev *rdev = regulator->rdev; 225895a3c23aSMark Brown int ret = 0; 2259414c70cbSLiam Girdwood 2260414c70cbSLiam Girdwood mutex_lock(&rdev->mutex); 2261414c70cbSLiam Girdwood 226295a3c23aSMark Brown /* If we're setting the same range as last time the change 226395a3c23aSMark Brown * should be a noop (some cpufreq implementations use the same 226495a3c23aSMark Brown * voltage for multiple frequencies, for example). 226595a3c23aSMark Brown */ 226695a3c23aSMark Brown if (regulator->min_uV == min_uV && regulator->max_uV == max_uV) 226795a3c23aSMark Brown goto out; 226895a3c23aSMark Brown 2269414c70cbSLiam Girdwood /* sanity check */ 2270e8eef82bSMark Brown if (!rdev->desc->ops->set_voltage && 2271e8eef82bSMark Brown !rdev->desc->ops->set_voltage_sel) { 2272414c70cbSLiam Girdwood ret = -EINVAL; 2273414c70cbSLiam Girdwood goto out; 2274414c70cbSLiam Girdwood } 2275414c70cbSLiam Girdwood 2276414c70cbSLiam Girdwood /* constraints check */ 2277414c70cbSLiam Girdwood ret = regulator_check_voltage(rdev, &min_uV, &max_uV); 2278414c70cbSLiam Girdwood if (ret < 0) 2279414c70cbSLiam Girdwood goto out; 2280414c70cbSLiam Girdwood regulator->min_uV = min_uV; 2281414c70cbSLiam Girdwood regulator->max_uV = max_uV; 22823a93f2a9SMark Brown 228305fda3b1SThomas Petazzoni ret = regulator_check_consumers(rdev, &min_uV, &max_uV); 228405fda3b1SThomas Petazzoni if (ret < 0) 228505fda3b1SThomas Petazzoni goto out; 228605fda3b1SThomas Petazzoni 228775790251SMark Brown ret = _regulator_do_set_voltage(rdev, min_uV, max_uV); 228802fa3ec0SMark Brown 2289414c70cbSLiam Girdwood out: 2290414c70cbSLiam Girdwood mutex_unlock(&rdev->mutex); 2291414c70cbSLiam Girdwood return ret; 2292414c70cbSLiam Girdwood } 2293414c70cbSLiam Girdwood EXPORT_SYMBOL_GPL(regulator_set_voltage); 2294414c70cbSLiam Girdwood 2295606a2562SMark Brown /** 229688cd222bSLinus Walleij * regulator_set_voltage_time - get raise/fall time 229788cd222bSLinus Walleij * @regulator: regulator source 229888cd222bSLinus Walleij * @old_uV: starting voltage in microvolts 229988cd222bSLinus Walleij * @new_uV: target voltage in microvolts 230088cd222bSLinus Walleij * 230188cd222bSLinus Walleij * Provided with the starting and ending voltage, this function attempts to 230288cd222bSLinus Walleij * calculate the time in microseconds required to rise or fall to this new 230388cd222bSLinus Walleij * voltage. 230488cd222bSLinus Walleij */ 230588cd222bSLinus Walleij int regulator_set_voltage_time(struct regulator *regulator, 230688cd222bSLinus Walleij int old_uV, int new_uV) 230788cd222bSLinus Walleij { 230888cd222bSLinus Walleij struct regulator_dev *rdev = regulator->rdev; 230988cd222bSLinus Walleij struct regulator_ops *ops = rdev->desc->ops; 231088cd222bSLinus Walleij int old_sel = -1; 231188cd222bSLinus Walleij int new_sel = -1; 231288cd222bSLinus Walleij int voltage; 231388cd222bSLinus Walleij int i; 231488cd222bSLinus Walleij 231588cd222bSLinus Walleij /* Currently requires operations to do this */ 231688cd222bSLinus Walleij if (!ops->list_voltage || !ops->set_voltage_time_sel 231788cd222bSLinus Walleij || !rdev->desc->n_voltages) 231888cd222bSLinus Walleij return -EINVAL; 231988cd222bSLinus Walleij 232088cd222bSLinus Walleij for (i = 0; i < rdev->desc->n_voltages; i++) { 232188cd222bSLinus Walleij /* We only look for exact voltage matches here */ 232288cd222bSLinus Walleij voltage = regulator_list_voltage(regulator, i); 232388cd222bSLinus Walleij if (voltage < 0) 232488cd222bSLinus Walleij return -EINVAL; 232588cd222bSLinus Walleij if (voltage == 0) 232688cd222bSLinus Walleij continue; 232788cd222bSLinus Walleij if (voltage == old_uV) 232888cd222bSLinus Walleij old_sel = i; 232988cd222bSLinus Walleij if (voltage == new_uV) 233088cd222bSLinus Walleij new_sel = i; 233188cd222bSLinus Walleij } 233288cd222bSLinus Walleij 233388cd222bSLinus Walleij if (old_sel < 0 || new_sel < 0) 233488cd222bSLinus Walleij return -EINVAL; 233588cd222bSLinus Walleij 233688cd222bSLinus Walleij return ops->set_voltage_time_sel(rdev, old_sel, new_sel); 233788cd222bSLinus Walleij } 233888cd222bSLinus Walleij EXPORT_SYMBOL_GPL(regulator_set_voltage_time); 233988cd222bSLinus Walleij 234088cd222bSLinus Walleij /** 234198a175b6SYadwinder Singh Brar * regulator_set_voltage_time_sel - get raise/fall time 2342296c6566SRandy Dunlap * @rdev: regulator source device 234398a175b6SYadwinder Singh Brar * @old_selector: selector for starting voltage 234498a175b6SYadwinder Singh Brar * @new_selector: selector for target voltage 234598a175b6SYadwinder Singh Brar * 234698a175b6SYadwinder Singh Brar * Provided with the starting and target voltage selectors, this function 234798a175b6SYadwinder Singh Brar * returns time in microseconds required to rise or fall to this new voltage 234898a175b6SYadwinder Singh Brar * 2349f11d08c3SAxel Lin * Drivers providing ramp_delay in regulation_constraints can use this as their 2350398715abSAxel Lin * set_voltage_time_sel() operation. 235198a175b6SYadwinder Singh Brar */ 235298a175b6SYadwinder Singh Brar int regulator_set_voltage_time_sel(struct regulator_dev *rdev, 235398a175b6SYadwinder Singh Brar unsigned int old_selector, 235498a175b6SYadwinder Singh Brar unsigned int new_selector) 235598a175b6SYadwinder Singh Brar { 2356398715abSAxel Lin unsigned int ramp_delay = 0; 2357f11d08c3SAxel Lin int old_volt, new_volt; 2358398715abSAxel Lin 23596f0b2c69SYadwinder Singh Brar if (rdev->constraints->ramp_delay) 2360398715abSAxel Lin ramp_delay = rdev->constraints->ramp_delay; 2361398715abSAxel Lin else if (rdev->desc->ramp_delay) 2362398715abSAxel Lin ramp_delay = rdev->desc->ramp_delay; 2363398715abSAxel Lin 2364398715abSAxel Lin if (ramp_delay == 0) { 23656f0b2c69SYadwinder Singh Brar rdev_warn(rdev, "ramp_delay not set\n"); 2366398715abSAxel Lin return 0; 23676f0b2c69SYadwinder Singh Brar } 2368398715abSAxel Lin 2369f11d08c3SAxel Lin /* sanity check */ 2370f11d08c3SAxel Lin if (!rdev->desc->ops->list_voltage) 2371f11d08c3SAxel Lin return -EINVAL; 2372398715abSAxel Lin 2373f11d08c3SAxel Lin old_volt = rdev->desc->ops->list_voltage(rdev, old_selector); 2374f11d08c3SAxel Lin new_volt = rdev->desc->ops->list_voltage(rdev, new_selector); 2375f11d08c3SAxel Lin 2376f11d08c3SAxel Lin return DIV_ROUND_UP(abs(new_volt - old_volt), ramp_delay); 237798a175b6SYadwinder Singh Brar } 2378b19dbf71SMark Brown EXPORT_SYMBOL_GPL(regulator_set_voltage_time_sel); 237998a175b6SYadwinder Singh Brar 238098a175b6SYadwinder Singh Brar /** 2381606a2562SMark Brown * regulator_sync_voltage - re-apply last regulator output voltage 2382606a2562SMark Brown * @regulator: regulator source 2383606a2562SMark Brown * 2384606a2562SMark Brown * Re-apply the last configured voltage. This is intended to be used 2385606a2562SMark Brown * where some external control source the consumer is cooperating with 2386606a2562SMark Brown * has caused the configured voltage to change. 2387606a2562SMark Brown */ 2388606a2562SMark Brown int regulator_sync_voltage(struct regulator *regulator) 2389606a2562SMark Brown { 2390606a2562SMark Brown struct regulator_dev *rdev = regulator->rdev; 2391606a2562SMark Brown int ret, min_uV, max_uV; 2392606a2562SMark Brown 2393606a2562SMark Brown mutex_lock(&rdev->mutex); 2394606a2562SMark Brown 2395606a2562SMark Brown if (!rdev->desc->ops->set_voltage && 2396606a2562SMark Brown !rdev->desc->ops->set_voltage_sel) { 2397606a2562SMark Brown ret = -EINVAL; 2398606a2562SMark Brown goto out; 2399606a2562SMark Brown } 2400606a2562SMark Brown 2401606a2562SMark Brown /* This is only going to work if we've had a voltage configured. */ 2402606a2562SMark Brown if (!regulator->min_uV && !regulator->max_uV) { 2403606a2562SMark Brown ret = -EINVAL; 2404606a2562SMark Brown goto out; 2405606a2562SMark Brown } 2406606a2562SMark Brown 2407606a2562SMark Brown min_uV = regulator->min_uV; 2408606a2562SMark Brown max_uV = regulator->max_uV; 2409606a2562SMark Brown 2410606a2562SMark Brown /* This should be a paranoia check... */ 2411606a2562SMark Brown ret = regulator_check_voltage(rdev, &min_uV, &max_uV); 2412606a2562SMark Brown if (ret < 0) 2413606a2562SMark Brown goto out; 2414606a2562SMark Brown 2415606a2562SMark Brown ret = regulator_check_consumers(rdev, &min_uV, &max_uV); 2416606a2562SMark Brown if (ret < 0) 2417606a2562SMark Brown goto out; 2418606a2562SMark Brown 2419606a2562SMark Brown ret = _regulator_do_set_voltage(rdev, min_uV, max_uV); 2420606a2562SMark Brown 2421606a2562SMark Brown out: 2422606a2562SMark Brown mutex_unlock(&rdev->mutex); 2423606a2562SMark Brown return ret; 2424606a2562SMark Brown } 2425606a2562SMark Brown EXPORT_SYMBOL_GPL(regulator_sync_voltage); 2426606a2562SMark Brown 2427414c70cbSLiam Girdwood static int _regulator_get_voltage(struct regulator_dev *rdev) 2428414c70cbSLiam Girdwood { 2429bf5892a8SMark Brown int sel, ret; 2430476c2d83SMark Brown 2431476c2d83SMark Brown if (rdev->desc->ops->get_voltage_sel) { 2432476c2d83SMark Brown sel = rdev->desc->ops->get_voltage_sel(rdev); 2433476c2d83SMark Brown if (sel < 0) 2434476c2d83SMark Brown return sel; 2435bf5892a8SMark Brown ret = rdev->desc->ops->list_voltage(rdev, sel); 2436cb220d16SAxel Lin } else if (rdev->desc->ops->get_voltage) { 2437bf5892a8SMark Brown ret = rdev->desc->ops->get_voltage(rdev); 2438f7df20ecSMark Brown } else if (rdev->desc->ops->list_voltage) { 2439f7df20ecSMark Brown ret = rdev->desc->ops->list_voltage(rdev, 0); 2440cb220d16SAxel Lin } else { 2441414c70cbSLiam Girdwood return -EINVAL; 2442cb220d16SAxel Lin } 2443bf5892a8SMark Brown 2444cb220d16SAxel Lin if (ret < 0) 2445cb220d16SAxel Lin return ret; 2446bf5892a8SMark Brown return ret - rdev->constraints->uV_offset; 2447414c70cbSLiam Girdwood } 2448414c70cbSLiam Girdwood 2449414c70cbSLiam Girdwood /** 2450414c70cbSLiam Girdwood * regulator_get_voltage - get regulator output voltage 2451414c70cbSLiam Girdwood * @regulator: regulator source 2452414c70cbSLiam Girdwood * 2453414c70cbSLiam Girdwood * This returns the current regulator voltage in uV. 2454414c70cbSLiam Girdwood * 2455414c70cbSLiam Girdwood * NOTE: If the regulator is disabled it will return the voltage value. This 2456414c70cbSLiam Girdwood * function should not be used to determine regulator state. 2457414c70cbSLiam Girdwood */ 2458414c70cbSLiam Girdwood int regulator_get_voltage(struct regulator *regulator) 2459414c70cbSLiam Girdwood { 2460414c70cbSLiam Girdwood int ret; 2461414c70cbSLiam Girdwood 2462414c70cbSLiam Girdwood mutex_lock(®ulator->rdev->mutex); 2463414c70cbSLiam Girdwood 2464414c70cbSLiam Girdwood ret = _regulator_get_voltage(regulator->rdev); 2465414c70cbSLiam Girdwood 2466414c70cbSLiam Girdwood mutex_unlock(®ulator->rdev->mutex); 2467414c70cbSLiam Girdwood 2468414c70cbSLiam Girdwood return ret; 2469414c70cbSLiam Girdwood } 2470414c70cbSLiam Girdwood EXPORT_SYMBOL_GPL(regulator_get_voltage); 2471414c70cbSLiam Girdwood 2472414c70cbSLiam Girdwood /** 2473414c70cbSLiam Girdwood * regulator_set_current_limit - set regulator output current limit 2474414c70cbSLiam Girdwood * @regulator: regulator source 2475414c70cbSLiam Girdwood * @min_uA: Minimuum supported current in uA 2476414c70cbSLiam Girdwood * @max_uA: Maximum supported current in uA 2477414c70cbSLiam Girdwood * 2478414c70cbSLiam Girdwood * Sets current sink to the desired output current. This can be set during 2479414c70cbSLiam Girdwood * any regulator state. IOW, regulator can be disabled or enabled. 2480414c70cbSLiam Girdwood * 2481414c70cbSLiam Girdwood * If the regulator is enabled then the current will change to the new value 2482414c70cbSLiam Girdwood * immediately otherwise if the regulator is disabled the regulator will 2483414c70cbSLiam Girdwood * output at the new current when enabled. 2484414c70cbSLiam Girdwood * 2485414c70cbSLiam Girdwood * NOTE: Regulator system constraints must be set for this regulator before 2486414c70cbSLiam Girdwood * calling this function otherwise this call will fail. 2487414c70cbSLiam Girdwood */ 2488414c70cbSLiam Girdwood int regulator_set_current_limit(struct regulator *regulator, 2489414c70cbSLiam Girdwood int min_uA, int max_uA) 2490414c70cbSLiam Girdwood { 2491414c70cbSLiam Girdwood struct regulator_dev *rdev = regulator->rdev; 2492414c70cbSLiam Girdwood int ret; 2493414c70cbSLiam Girdwood 2494414c70cbSLiam Girdwood mutex_lock(&rdev->mutex); 2495414c70cbSLiam Girdwood 2496414c70cbSLiam Girdwood /* sanity check */ 2497414c70cbSLiam Girdwood if (!rdev->desc->ops->set_current_limit) { 2498414c70cbSLiam Girdwood ret = -EINVAL; 2499414c70cbSLiam Girdwood goto out; 2500414c70cbSLiam Girdwood } 2501414c70cbSLiam Girdwood 2502414c70cbSLiam Girdwood /* constraints check */ 2503414c70cbSLiam Girdwood ret = regulator_check_current_limit(rdev, &min_uA, &max_uA); 2504414c70cbSLiam Girdwood if (ret < 0) 2505414c70cbSLiam Girdwood goto out; 2506414c70cbSLiam Girdwood 2507414c70cbSLiam Girdwood ret = rdev->desc->ops->set_current_limit(rdev, min_uA, max_uA); 2508414c70cbSLiam Girdwood out: 2509414c70cbSLiam Girdwood mutex_unlock(&rdev->mutex); 2510414c70cbSLiam Girdwood return ret; 2511414c70cbSLiam Girdwood } 2512414c70cbSLiam Girdwood EXPORT_SYMBOL_GPL(regulator_set_current_limit); 2513414c70cbSLiam Girdwood 2514414c70cbSLiam Girdwood static int _regulator_get_current_limit(struct regulator_dev *rdev) 2515414c70cbSLiam Girdwood { 2516414c70cbSLiam Girdwood int ret; 2517414c70cbSLiam Girdwood 2518414c70cbSLiam Girdwood mutex_lock(&rdev->mutex); 2519414c70cbSLiam Girdwood 2520414c70cbSLiam Girdwood /* sanity check */ 2521414c70cbSLiam Girdwood if (!rdev->desc->ops->get_current_limit) { 2522414c70cbSLiam Girdwood ret = -EINVAL; 2523414c70cbSLiam Girdwood goto out; 2524414c70cbSLiam Girdwood } 2525414c70cbSLiam Girdwood 2526414c70cbSLiam Girdwood ret = rdev->desc->ops->get_current_limit(rdev); 2527414c70cbSLiam Girdwood out: 2528414c70cbSLiam Girdwood mutex_unlock(&rdev->mutex); 2529414c70cbSLiam Girdwood return ret; 2530414c70cbSLiam Girdwood } 2531414c70cbSLiam Girdwood 2532414c70cbSLiam Girdwood /** 2533414c70cbSLiam Girdwood * regulator_get_current_limit - get regulator output current 2534414c70cbSLiam Girdwood * @regulator: regulator source 2535414c70cbSLiam Girdwood * 2536414c70cbSLiam Girdwood * This returns the current supplied by the specified current sink in uA. 2537414c70cbSLiam Girdwood * 2538414c70cbSLiam Girdwood * NOTE: If the regulator is disabled it will return the current value. This 2539414c70cbSLiam Girdwood * function should not be used to determine regulator state. 2540414c70cbSLiam Girdwood */ 2541414c70cbSLiam Girdwood int regulator_get_current_limit(struct regulator *regulator) 2542414c70cbSLiam Girdwood { 2543414c70cbSLiam Girdwood return _regulator_get_current_limit(regulator->rdev); 2544414c70cbSLiam Girdwood } 2545414c70cbSLiam Girdwood EXPORT_SYMBOL_GPL(regulator_get_current_limit); 2546414c70cbSLiam Girdwood 2547414c70cbSLiam Girdwood /** 2548414c70cbSLiam Girdwood * regulator_set_mode - set regulator operating mode 2549414c70cbSLiam Girdwood * @regulator: regulator source 2550414c70cbSLiam Girdwood * @mode: operating mode - one of the REGULATOR_MODE constants 2551414c70cbSLiam Girdwood * 2552414c70cbSLiam Girdwood * Set regulator operating mode to increase regulator efficiency or improve 2553414c70cbSLiam Girdwood * regulation performance. 2554414c70cbSLiam Girdwood * 2555414c70cbSLiam Girdwood * NOTE: Regulator system constraints must be set for this regulator before 2556414c70cbSLiam Girdwood * calling this function otherwise this call will fail. 2557414c70cbSLiam Girdwood */ 2558414c70cbSLiam Girdwood int regulator_set_mode(struct regulator *regulator, unsigned int mode) 2559414c70cbSLiam Girdwood { 2560414c70cbSLiam Girdwood struct regulator_dev *rdev = regulator->rdev; 2561414c70cbSLiam Girdwood int ret; 2562500b4ac9SSundar R Iyer int regulator_curr_mode; 2563414c70cbSLiam Girdwood 2564414c70cbSLiam Girdwood mutex_lock(&rdev->mutex); 2565414c70cbSLiam Girdwood 2566414c70cbSLiam Girdwood /* sanity check */ 2567414c70cbSLiam Girdwood if (!rdev->desc->ops->set_mode) { 2568414c70cbSLiam Girdwood ret = -EINVAL; 2569414c70cbSLiam Girdwood goto out; 2570414c70cbSLiam Girdwood } 2571414c70cbSLiam Girdwood 2572500b4ac9SSundar R Iyer /* return if the same mode is requested */ 2573500b4ac9SSundar R Iyer if (rdev->desc->ops->get_mode) { 2574500b4ac9SSundar R Iyer regulator_curr_mode = rdev->desc->ops->get_mode(rdev); 2575500b4ac9SSundar R Iyer if (regulator_curr_mode == mode) { 2576500b4ac9SSundar R Iyer ret = 0; 2577500b4ac9SSundar R Iyer goto out; 2578500b4ac9SSundar R Iyer } 2579500b4ac9SSundar R Iyer } 2580500b4ac9SSundar R Iyer 2581414c70cbSLiam Girdwood /* constraints check */ 258222c51b47SAxel Lin ret = regulator_mode_constrain(rdev, &mode); 2583414c70cbSLiam Girdwood if (ret < 0) 2584414c70cbSLiam Girdwood goto out; 2585414c70cbSLiam Girdwood 2586414c70cbSLiam Girdwood ret = rdev->desc->ops->set_mode(rdev, mode); 2587414c70cbSLiam Girdwood out: 2588414c70cbSLiam Girdwood mutex_unlock(&rdev->mutex); 2589414c70cbSLiam Girdwood return ret; 2590414c70cbSLiam Girdwood } 2591414c70cbSLiam Girdwood EXPORT_SYMBOL_GPL(regulator_set_mode); 2592414c70cbSLiam Girdwood 2593414c70cbSLiam Girdwood static unsigned int _regulator_get_mode(struct regulator_dev *rdev) 2594414c70cbSLiam Girdwood { 2595414c70cbSLiam Girdwood int ret; 2596414c70cbSLiam Girdwood 2597414c70cbSLiam Girdwood mutex_lock(&rdev->mutex); 2598414c70cbSLiam Girdwood 2599414c70cbSLiam Girdwood /* sanity check */ 2600414c70cbSLiam Girdwood if (!rdev->desc->ops->get_mode) { 2601414c70cbSLiam Girdwood ret = -EINVAL; 2602414c70cbSLiam Girdwood goto out; 2603414c70cbSLiam Girdwood } 2604414c70cbSLiam Girdwood 2605414c70cbSLiam Girdwood ret = rdev->desc->ops->get_mode(rdev); 2606414c70cbSLiam Girdwood out: 2607414c70cbSLiam Girdwood mutex_unlock(&rdev->mutex); 2608414c70cbSLiam Girdwood return ret; 2609414c70cbSLiam Girdwood } 2610414c70cbSLiam Girdwood 2611414c70cbSLiam Girdwood /** 2612414c70cbSLiam Girdwood * regulator_get_mode - get regulator operating mode 2613414c70cbSLiam Girdwood * @regulator: regulator source 2614414c70cbSLiam Girdwood * 2615414c70cbSLiam Girdwood * Get the current regulator operating mode. 2616414c70cbSLiam Girdwood */ 2617414c70cbSLiam Girdwood unsigned int regulator_get_mode(struct regulator *regulator) 2618414c70cbSLiam Girdwood { 2619414c70cbSLiam Girdwood return _regulator_get_mode(regulator->rdev); 2620414c70cbSLiam Girdwood } 2621414c70cbSLiam Girdwood EXPORT_SYMBOL_GPL(regulator_get_mode); 2622414c70cbSLiam Girdwood 2623414c70cbSLiam Girdwood /** 2624414c70cbSLiam Girdwood * regulator_set_optimum_mode - set regulator optimum operating mode 2625414c70cbSLiam Girdwood * @regulator: regulator source 2626414c70cbSLiam Girdwood * @uA_load: load current 2627414c70cbSLiam Girdwood * 2628414c70cbSLiam Girdwood * Notifies the regulator core of a new device load. This is then used by 2629414c70cbSLiam Girdwood * DRMS (if enabled by constraints) to set the most efficient regulator 2630414c70cbSLiam Girdwood * operating mode for the new regulator loading. 2631414c70cbSLiam Girdwood * 2632414c70cbSLiam Girdwood * Consumer devices notify their supply regulator of the maximum power 2633414c70cbSLiam Girdwood * they will require (can be taken from device datasheet in the power 2634414c70cbSLiam Girdwood * consumption tables) when they change operational status and hence power 2635414c70cbSLiam Girdwood * state. Examples of operational state changes that can affect power 2636414c70cbSLiam Girdwood * consumption are :- 2637414c70cbSLiam Girdwood * 2638414c70cbSLiam Girdwood * o Device is opened / closed. 2639414c70cbSLiam Girdwood * o Device I/O is about to begin or has just finished. 2640414c70cbSLiam Girdwood * o Device is idling in between work. 2641414c70cbSLiam Girdwood * 2642414c70cbSLiam Girdwood * This information is also exported via sysfs to userspace. 2643414c70cbSLiam Girdwood * 2644414c70cbSLiam Girdwood * DRMS will sum the total requested load on the regulator and change 2645414c70cbSLiam Girdwood * to the most efficient operating mode if platform constraints allow. 2646414c70cbSLiam Girdwood * 2647414c70cbSLiam Girdwood * Returns the new regulator mode or error. 2648414c70cbSLiam Girdwood */ 2649414c70cbSLiam Girdwood int regulator_set_optimum_mode(struct regulator *regulator, int uA_load) 2650414c70cbSLiam Girdwood { 2651414c70cbSLiam Girdwood struct regulator_dev *rdev = regulator->rdev; 2652414c70cbSLiam Girdwood struct regulator *consumer; 2653d92d95b6SStephen Boyd int ret, output_uV, input_uV = 0, total_uA_load = 0; 2654414c70cbSLiam Girdwood unsigned int mode; 2655414c70cbSLiam Girdwood 2656d92d95b6SStephen Boyd if (rdev->supply) 2657d92d95b6SStephen Boyd input_uV = regulator_get_voltage(rdev->supply); 2658d92d95b6SStephen Boyd 2659414c70cbSLiam Girdwood mutex_lock(&rdev->mutex); 2660414c70cbSLiam Girdwood 2661a4b41483SMark Brown /* 2662a4b41483SMark Brown * first check to see if we can set modes at all, otherwise just 2663a4b41483SMark Brown * tell the consumer everything is OK. 2664a4b41483SMark Brown */ 2665414c70cbSLiam Girdwood regulator->uA_load = uA_load; 2666414c70cbSLiam Girdwood ret = regulator_check_drms(rdev); 2667a4b41483SMark Brown if (ret < 0) { 2668a4b41483SMark Brown ret = 0; 2669414c70cbSLiam Girdwood goto out; 2670a4b41483SMark Brown } 2671414c70cbSLiam Girdwood 2672414c70cbSLiam Girdwood if (!rdev->desc->ops->get_optimum_mode) 2673414c70cbSLiam Girdwood goto out; 2674414c70cbSLiam Girdwood 2675a4b41483SMark Brown /* 2676a4b41483SMark Brown * we can actually do this so any errors are indicators of 2677a4b41483SMark Brown * potential real failure. 2678a4b41483SMark Brown */ 2679a4b41483SMark Brown ret = -EINVAL; 2680a4b41483SMark Brown 2681854ccbaeSAxel Lin if (!rdev->desc->ops->set_mode) 2682854ccbaeSAxel Lin goto out; 2683854ccbaeSAxel Lin 2684414c70cbSLiam Girdwood /* get output voltage */ 26851bf5a1f8SMark Brown output_uV = _regulator_get_voltage(rdev); 2686414c70cbSLiam Girdwood if (output_uV <= 0) { 26875da84fd9SJoe Perches rdev_err(rdev, "invalid output voltage found\n"); 2688414c70cbSLiam Girdwood goto out; 2689414c70cbSLiam Girdwood } 2690414c70cbSLiam Girdwood 2691d92d95b6SStephen Boyd /* No supply? Use constraint voltage */ 26921bf5a1f8SMark Brown if (input_uV <= 0) 2693414c70cbSLiam Girdwood input_uV = rdev->constraints->input_uV; 2694414c70cbSLiam Girdwood if (input_uV <= 0) { 26955da84fd9SJoe Perches rdev_err(rdev, "invalid input voltage found\n"); 2696414c70cbSLiam Girdwood goto out; 2697414c70cbSLiam Girdwood } 2698414c70cbSLiam Girdwood 2699414c70cbSLiam Girdwood /* calc total requested load for this regulator */ 2700414c70cbSLiam Girdwood list_for_each_entry(consumer, &rdev->consumer_list, list) 2701414c70cbSLiam Girdwood total_uA_load += consumer->uA_load; 2702414c70cbSLiam Girdwood 2703414c70cbSLiam Girdwood mode = rdev->desc->ops->get_optimum_mode(rdev, 2704414c70cbSLiam Girdwood input_uV, output_uV, 2705414c70cbSLiam Girdwood total_uA_load); 27062c608234SMark Brown ret = regulator_mode_constrain(rdev, &mode); 2707e573520bSDavid Brownell if (ret < 0) { 27085da84fd9SJoe Perches rdev_err(rdev, "failed to get optimum mode @ %d uA %d -> %d uV\n", 2709414c70cbSLiam Girdwood total_uA_load, input_uV, output_uV); 2710414c70cbSLiam Girdwood goto out; 2711414c70cbSLiam Girdwood } 2712414c70cbSLiam Girdwood 2713414c70cbSLiam Girdwood ret = rdev->desc->ops->set_mode(rdev, mode); 2714e573520bSDavid Brownell if (ret < 0) { 27155da84fd9SJoe Perches rdev_err(rdev, "failed to set optimum mode %x\n", mode); 2716414c70cbSLiam Girdwood goto out; 2717414c70cbSLiam Girdwood } 2718414c70cbSLiam Girdwood ret = mode; 2719414c70cbSLiam Girdwood out: 2720414c70cbSLiam Girdwood mutex_unlock(&rdev->mutex); 2721414c70cbSLiam Girdwood return ret; 2722414c70cbSLiam Girdwood } 2723414c70cbSLiam Girdwood EXPORT_SYMBOL_GPL(regulator_set_optimum_mode); 2724414c70cbSLiam Girdwood 2725414c70cbSLiam Girdwood /** 2726df367931SMark Brown * regulator_set_bypass_regmap - Default set_bypass() using regmap 2727df367931SMark Brown * 2728df367931SMark Brown * @rdev: device to operate on. 2729df367931SMark Brown * @enable: state to set. 2730df367931SMark Brown */ 2731df367931SMark Brown int regulator_set_bypass_regmap(struct regulator_dev *rdev, bool enable) 2732df367931SMark Brown { 2733df367931SMark Brown unsigned int val; 2734df367931SMark Brown 2735df367931SMark Brown if (enable) 2736df367931SMark Brown val = rdev->desc->bypass_mask; 2737df367931SMark Brown else 2738df367931SMark Brown val = 0; 2739df367931SMark Brown 2740df367931SMark Brown return regmap_update_bits(rdev->regmap, rdev->desc->bypass_reg, 2741df367931SMark Brown rdev->desc->bypass_mask, val); 2742df367931SMark Brown } 2743df367931SMark Brown EXPORT_SYMBOL_GPL(regulator_set_bypass_regmap); 2744df367931SMark Brown 2745df367931SMark Brown /** 2746df367931SMark Brown * regulator_get_bypass_regmap - Default get_bypass() using regmap 2747df367931SMark Brown * 2748df367931SMark Brown * @rdev: device to operate on. 2749df367931SMark Brown * @enable: current state. 2750df367931SMark Brown */ 2751df367931SMark Brown int regulator_get_bypass_regmap(struct regulator_dev *rdev, bool *enable) 2752df367931SMark Brown { 2753df367931SMark Brown unsigned int val; 2754df367931SMark Brown int ret; 2755df367931SMark Brown 2756df367931SMark Brown ret = regmap_read(rdev->regmap, rdev->desc->bypass_reg, &val); 2757df367931SMark Brown if (ret != 0) 2758df367931SMark Brown return ret; 2759df367931SMark Brown 2760df367931SMark Brown *enable = val & rdev->desc->bypass_mask; 2761df367931SMark Brown 2762df367931SMark Brown return 0; 2763df367931SMark Brown } 2764df367931SMark Brown EXPORT_SYMBOL_GPL(regulator_get_bypass_regmap); 2765df367931SMark Brown 2766df367931SMark Brown /** 2767f59c8f9fSMark Brown * regulator_allow_bypass - allow the regulator to go into bypass mode 2768f59c8f9fSMark Brown * 2769f59c8f9fSMark Brown * @regulator: Regulator to configure 2770f59c8f9fSMark Brown * @allow: enable or disable bypass mode 2771f59c8f9fSMark Brown * 2772f59c8f9fSMark Brown * Allow the regulator to go into bypass mode if all other consumers 2773f59c8f9fSMark Brown * for the regulator also enable bypass mode and the machine 2774f59c8f9fSMark Brown * constraints allow this. Bypass mode means that the regulator is 2775f59c8f9fSMark Brown * simply passing the input directly to the output with no regulation. 2776f59c8f9fSMark Brown */ 2777f59c8f9fSMark Brown int regulator_allow_bypass(struct regulator *regulator, bool enable) 2778f59c8f9fSMark Brown { 2779f59c8f9fSMark Brown struct regulator_dev *rdev = regulator->rdev; 2780f59c8f9fSMark Brown int ret = 0; 2781f59c8f9fSMark Brown 2782f59c8f9fSMark Brown if (!rdev->desc->ops->set_bypass) 2783f59c8f9fSMark Brown return 0; 2784f59c8f9fSMark Brown 2785f59c8f9fSMark Brown if (rdev->constraints && 2786f59c8f9fSMark Brown !(rdev->constraints->valid_ops_mask & REGULATOR_CHANGE_BYPASS)) 2787f59c8f9fSMark Brown return 0; 2788f59c8f9fSMark Brown 2789f59c8f9fSMark Brown mutex_lock(&rdev->mutex); 2790f59c8f9fSMark Brown 2791f59c8f9fSMark Brown if (enable && !regulator->bypass) { 2792f59c8f9fSMark Brown rdev->bypass_count++; 2793f59c8f9fSMark Brown 2794f59c8f9fSMark Brown if (rdev->bypass_count == rdev->open_count) { 2795f59c8f9fSMark Brown ret = rdev->desc->ops->set_bypass(rdev, enable); 2796f59c8f9fSMark Brown if (ret != 0) 2797f59c8f9fSMark Brown rdev->bypass_count--; 2798f59c8f9fSMark Brown } 2799f59c8f9fSMark Brown 2800f59c8f9fSMark Brown } else if (!enable && regulator->bypass) { 2801f59c8f9fSMark Brown rdev->bypass_count--; 2802f59c8f9fSMark Brown 2803f59c8f9fSMark Brown if (rdev->bypass_count != rdev->open_count) { 2804f59c8f9fSMark Brown ret = rdev->desc->ops->set_bypass(rdev, enable); 2805f59c8f9fSMark Brown if (ret != 0) 2806f59c8f9fSMark Brown rdev->bypass_count++; 2807f59c8f9fSMark Brown } 2808f59c8f9fSMark Brown } 2809f59c8f9fSMark Brown 2810f59c8f9fSMark Brown if (ret == 0) 2811f59c8f9fSMark Brown regulator->bypass = enable; 2812f59c8f9fSMark Brown 2813f59c8f9fSMark Brown mutex_unlock(&rdev->mutex); 2814f59c8f9fSMark Brown 2815f59c8f9fSMark Brown return ret; 2816f59c8f9fSMark Brown } 2817f59c8f9fSMark Brown EXPORT_SYMBOL_GPL(regulator_allow_bypass); 2818f59c8f9fSMark Brown 2819f59c8f9fSMark Brown /** 2820414c70cbSLiam Girdwood * regulator_register_notifier - register regulator event notifier 2821414c70cbSLiam Girdwood * @regulator: regulator source 282269279fb9SMark Brown * @nb: notifier block 2823414c70cbSLiam Girdwood * 2824414c70cbSLiam Girdwood * Register notifier block to receive regulator events. 2825414c70cbSLiam Girdwood */ 2826414c70cbSLiam Girdwood int regulator_register_notifier(struct regulator *regulator, 2827414c70cbSLiam Girdwood struct notifier_block *nb) 2828414c70cbSLiam Girdwood { 2829414c70cbSLiam Girdwood return blocking_notifier_chain_register(®ulator->rdev->notifier, 2830414c70cbSLiam Girdwood nb); 2831414c70cbSLiam Girdwood } 2832414c70cbSLiam Girdwood EXPORT_SYMBOL_GPL(regulator_register_notifier); 2833414c70cbSLiam Girdwood 2834414c70cbSLiam Girdwood /** 2835414c70cbSLiam Girdwood * regulator_unregister_notifier - unregister regulator event notifier 2836414c70cbSLiam Girdwood * @regulator: regulator source 283769279fb9SMark Brown * @nb: notifier block 2838414c70cbSLiam Girdwood * 2839414c70cbSLiam Girdwood * Unregister regulator event notifier block. 2840414c70cbSLiam Girdwood */ 2841414c70cbSLiam Girdwood int regulator_unregister_notifier(struct regulator *regulator, 2842414c70cbSLiam Girdwood struct notifier_block *nb) 2843414c70cbSLiam Girdwood { 2844414c70cbSLiam Girdwood return blocking_notifier_chain_unregister(®ulator->rdev->notifier, 2845414c70cbSLiam Girdwood nb); 2846414c70cbSLiam Girdwood } 2847414c70cbSLiam Girdwood EXPORT_SYMBOL_GPL(regulator_unregister_notifier); 2848414c70cbSLiam Girdwood 2849b136fb44SJonathan Cameron /* notify regulator consumers and downstream regulator consumers. 2850b136fb44SJonathan Cameron * Note mutex must be held by caller. 2851b136fb44SJonathan Cameron */ 2852414c70cbSLiam Girdwood static void _notifier_call_chain(struct regulator_dev *rdev, 2853414c70cbSLiam Girdwood unsigned long event, void *data) 2854414c70cbSLiam Girdwood { 2855414c70cbSLiam Girdwood /* call rdev chain first */ 2856d8493d21SMark Brown blocking_notifier_call_chain(&rdev->notifier, event, data); 2857414c70cbSLiam Girdwood } 2858414c70cbSLiam Girdwood 2859414c70cbSLiam Girdwood /** 2860414c70cbSLiam Girdwood * regulator_bulk_get - get multiple regulator consumers 2861414c70cbSLiam Girdwood * 2862414c70cbSLiam Girdwood * @dev: Device to supply 2863414c70cbSLiam Girdwood * @num_consumers: Number of consumers to register 2864414c70cbSLiam Girdwood * @consumers: Configuration of consumers; clients are stored here. 2865414c70cbSLiam Girdwood * 2866414c70cbSLiam Girdwood * @return 0 on success, an errno on failure. 2867414c70cbSLiam Girdwood * 2868414c70cbSLiam Girdwood * This helper function allows drivers to get several regulator 2869414c70cbSLiam Girdwood * consumers in one operation. If any of the regulators cannot be 2870414c70cbSLiam Girdwood * acquired then any regulators that were allocated will be freed 2871414c70cbSLiam Girdwood * before returning to the caller. 2872414c70cbSLiam Girdwood */ 2873414c70cbSLiam Girdwood int regulator_bulk_get(struct device *dev, int num_consumers, 2874414c70cbSLiam Girdwood struct regulator_bulk_data *consumers) 2875414c70cbSLiam Girdwood { 2876414c70cbSLiam Girdwood int i; 2877414c70cbSLiam Girdwood int ret; 2878414c70cbSLiam Girdwood 2879414c70cbSLiam Girdwood for (i = 0; i < num_consumers; i++) 2880414c70cbSLiam Girdwood consumers[i].consumer = NULL; 2881414c70cbSLiam Girdwood 2882414c70cbSLiam Girdwood for (i = 0; i < num_consumers; i++) { 2883414c70cbSLiam Girdwood consumers[i].consumer = regulator_get(dev, 2884414c70cbSLiam Girdwood consumers[i].supply); 2885414c70cbSLiam Girdwood if (IS_ERR(consumers[i].consumer)) { 2886414c70cbSLiam Girdwood ret = PTR_ERR(consumers[i].consumer); 28875b307627SMark Brown dev_err(dev, "Failed to get supply '%s': %d\n", 28885b307627SMark Brown consumers[i].supply, ret); 2889414c70cbSLiam Girdwood consumers[i].consumer = NULL; 2890414c70cbSLiam Girdwood goto err; 2891414c70cbSLiam Girdwood } 2892414c70cbSLiam Girdwood } 2893414c70cbSLiam Girdwood 2894414c70cbSLiam Girdwood return 0; 2895414c70cbSLiam Girdwood 2896414c70cbSLiam Girdwood err: 2897b29c7690SAxel Lin while (--i >= 0) 2898414c70cbSLiam Girdwood regulator_put(consumers[i].consumer); 2899414c70cbSLiam Girdwood 2900414c70cbSLiam Girdwood return ret; 2901414c70cbSLiam Girdwood } 2902414c70cbSLiam Girdwood EXPORT_SYMBOL_GPL(regulator_bulk_get); 2903414c70cbSLiam Girdwood 2904e6e74030SMark Brown /** 2905e6e74030SMark Brown * devm_regulator_bulk_get - managed get multiple regulator consumers 2906e6e74030SMark Brown * 2907e6e74030SMark Brown * @dev: Device to supply 2908e6e74030SMark Brown * @num_consumers: Number of consumers to register 2909e6e74030SMark Brown * @consumers: Configuration of consumers; clients are stored here. 2910e6e74030SMark Brown * 2911e6e74030SMark Brown * @return 0 on success, an errno on failure. 2912e6e74030SMark Brown * 2913e6e74030SMark Brown * This helper function allows drivers to get several regulator 2914e6e74030SMark Brown * consumers in one operation with management, the regulators will 2915e6e74030SMark Brown * automatically be freed when the device is unbound. If any of the 2916e6e74030SMark Brown * regulators cannot be acquired then any regulators that were 2917e6e74030SMark Brown * allocated will be freed before returning to the caller. 2918e6e74030SMark Brown */ 2919e6e74030SMark Brown int devm_regulator_bulk_get(struct device *dev, int num_consumers, 2920e6e74030SMark Brown struct regulator_bulk_data *consumers) 2921e6e74030SMark Brown { 2922e6e74030SMark Brown int i; 2923e6e74030SMark Brown int ret; 2924e6e74030SMark Brown 2925e6e74030SMark Brown for (i = 0; i < num_consumers; i++) 2926e6e74030SMark Brown consumers[i].consumer = NULL; 2927e6e74030SMark Brown 2928e6e74030SMark Brown for (i = 0; i < num_consumers; i++) { 2929e6e74030SMark Brown consumers[i].consumer = devm_regulator_get(dev, 2930e6e74030SMark Brown consumers[i].supply); 2931e6e74030SMark Brown if (IS_ERR(consumers[i].consumer)) { 2932e6e74030SMark Brown ret = PTR_ERR(consumers[i].consumer); 2933e6e74030SMark Brown dev_err(dev, "Failed to get supply '%s': %d\n", 2934e6e74030SMark Brown consumers[i].supply, ret); 2935e6e74030SMark Brown consumers[i].consumer = NULL; 2936e6e74030SMark Brown goto err; 2937e6e74030SMark Brown } 2938e6e74030SMark Brown } 2939e6e74030SMark Brown 2940e6e74030SMark Brown return 0; 2941e6e74030SMark Brown 2942e6e74030SMark Brown err: 2943e6e74030SMark Brown for (i = 0; i < num_consumers && consumers[i].consumer; i++) 2944e6e74030SMark Brown devm_regulator_put(consumers[i].consumer); 2945e6e74030SMark Brown 2946e6e74030SMark Brown return ret; 2947e6e74030SMark Brown } 2948e6e74030SMark Brown EXPORT_SYMBOL_GPL(devm_regulator_bulk_get); 2949e6e74030SMark Brown 2950f21e0e81SMark Brown static void regulator_bulk_enable_async(void *data, async_cookie_t cookie) 2951f21e0e81SMark Brown { 2952f21e0e81SMark Brown struct regulator_bulk_data *bulk = data; 2953f21e0e81SMark Brown 2954f21e0e81SMark Brown bulk->ret = regulator_enable(bulk->consumer); 2955f21e0e81SMark Brown } 2956f21e0e81SMark Brown 2957414c70cbSLiam Girdwood /** 2958414c70cbSLiam Girdwood * regulator_bulk_enable - enable multiple regulator consumers 2959414c70cbSLiam Girdwood * 2960414c70cbSLiam Girdwood * @num_consumers: Number of consumers 2961414c70cbSLiam Girdwood * @consumers: Consumer data; clients are stored here. 2962414c70cbSLiam Girdwood * @return 0 on success, an errno on failure 2963414c70cbSLiam Girdwood * 2964414c70cbSLiam Girdwood * This convenience API allows consumers to enable multiple regulator 2965414c70cbSLiam Girdwood * clients in a single API call. If any consumers cannot be enabled 2966414c70cbSLiam Girdwood * then any others that were enabled will be disabled again prior to 2967414c70cbSLiam Girdwood * return. 2968414c70cbSLiam Girdwood */ 2969414c70cbSLiam Girdwood int regulator_bulk_enable(int num_consumers, 2970414c70cbSLiam Girdwood struct regulator_bulk_data *consumers) 2971414c70cbSLiam Girdwood { 29722955b47dSDan Williams ASYNC_DOMAIN_EXCLUSIVE(async_domain); 2973414c70cbSLiam Girdwood int i; 2974f21e0e81SMark Brown int ret = 0; 2975414c70cbSLiam Girdwood 29766492bc1bSMark Brown for (i = 0; i < num_consumers; i++) { 29776492bc1bSMark Brown if (consumers[i].consumer->always_on) 29786492bc1bSMark Brown consumers[i].ret = 0; 29796492bc1bSMark Brown else 2980f21e0e81SMark Brown async_schedule_domain(regulator_bulk_enable_async, 2981f21e0e81SMark Brown &consumers[i], &async_domain); 29826492bc1bSMark Brown } 2983f21e0e81SMark Brown 2984f21e0e81SMark Brown async_synchronize_full_domain(&async_domain); 2985f21e0e81SMark Brown 2986f21e0e81SMark Brown /* If any consumer failed we need to unwind any that succeeded */ 2987414c70cbSLiam Girdwood for (i = 0; i < num_consumers; i++) { 2988f21e0e81SMark Brown if (consumers[i].ret != 0) { 2989f21e0e81SMark Brown ret = consumers[i].ret; 2990414c70cbSLiam Girdwood goto err; 2991414c70cbSLiam Girdwood } 2992f21e0e81SMark Brown } 2993414c70cbSLiam Girdwood 2994414c70cbSLiam Girdwood return 0; 2995414c70cbSLiam Girdwood 2996414c70cbSLiam Girdwood err: 2997b29c7690SAxel Lin pr_err("Failed to enable %s: %d\n", consumers[i].supply, ret); 2998b29c7690SAxel Lin while (--i >= 0) 2999414c70cbSLiam Girdwood regulator_disable(consumers[i].consumer); 3000414c70cbSLiam Girdwood 3001414c70cbSLiam Girdwood return ret; 3002414c70cbSLiam Girdwood } 3003414c70cbSLiam Girdwood EXPORT_SYMBOL_GPL(regulator_bulk_enable); 3004414c70cbSLiam Girdwood 3005414c70cbSLiam Girdwood /** 3006414c70cbSLiam Girdwood * regulator_bulk_disable - disable multiple regulator consumers 3007414c70cbSLiam Girdwood * 3008414c70cbSLiam Girdwood * @num_consumers: Number of consumers 3009414c70cbSLiam Girdwood * @consumers: Consumer data; clients are stored here. 3010414c70cbSLiam Girdwood * @return 0 on success, an errno on failure 3011414c70cbSLiam Girdwood * 3012414c70cbSLiam Girdwood * This convenience API allows consumers to disable multiple regulator 301349e22632SSylwester Nawrocki * clients in a single API call. If any consumers cannot be disabled 301449e22632SSylwester Nawrocki * then any others that were disabled will be enabled again prior to 3015414c70cbSLiam Girdwood * return. 3016414c70cbSLiam Girdwood */ 3017414c70cbSLiam Girdwood int regulator_bulk_disable(int num_consumers, 3018414c70cbSLiam Girdwood struct regulator_bulk_data *consumers) 3019414c70cbSLiam Girdwood { 3020414c70cbSLiam Girdwood int i; 302101e86f49SMark Brown int ret, r; 3022414c70cbSLiam Girdwood 302349e22632SSylwester Nawrocki for (i = num_consumers - 1; i >= 0; --i) { 3024414c70cbSLiam Girdwood ret = regulator_disable(consumers[i].consumer); 3025414c70cbSLiam Girdwood if (ret != 0) 3026414c70cbSLiam Girdwood goto err; 3027414c70cbSLiam Girdwood } 3028414c70cbSLiam Girdwood 3029414c70cbSLiam Girdwood return 0; 3030414c70cbSLiam Girdwood 3031414c70cbSLiam Girdwood err: 30325da84fd9SJoe Perches pr_err("Failed to disable %s: %d\n", consumers[i].supply, ret); 303301e86f49SMark Brown for (++i; i < num_consumers; ++i) { 303401e86f49SMark Brown r = regulator_enable(consumers[i].consumer); 303501e86f49SMark Brown if (r != 0) 303601e86f49SMark Brown pr_err("Failed to reename %s: %d\n", 303701e86f49SMark Brown consumers[i].supply, r); 303801e86f49SMark Brown } 3039414c70cbSLiam Girdwood 3040414c70cbSLiam Girdwood return ret; 3041414c70cbSLiam Girdwood } 3042414c70cbSLiam Girdwood EXPORT_SYMBOL_GPL(regulator_bulk_disable); 3043414c70cbSLiam Girdwood 3044414c70cbSLiam Girdwood /** 3045e1de2f42SDonggeun Kim * regulator_bulk_force_disable - force disable multiple regulator consumers 3046e1de2f42SDonggeun Kim * 3047e1de2f42SDonggeun Kim * @num_consumers: Number of consumers 3048e1de2f42SDonggeun Kim * @consumers: Consumer data; clients are stored here. 3049e1de2f42SDonggeun Kim * @return 0 on success, an errno on failure 3050e1de2f42SDonggeun Kim * 3051e1de2f42SDonggeun Kim * This convenience API allows consumers to forcibly disable multiple regulator 3052e1de2f42SDonggeun Kim * clients in a single API call. 3053e1de2f42SDonggeun Kim * NOTE: This should be used for situations when device damage will 3054e1de2f42SDonggeun Kim * likely occur if the regulators are not disabled (e.g. over temp). 3055e1de2f42SDonggeun Kim * Although regulator_force_disable function call for some consumers can 3056e1de2f42SDonggeun Kim * return error numbers, the function is called for all consumers. 3057e1de2f42SDonggeun Kim */ 3058e1de2f42SDonggeun Kim int regulator_bulk_force_disable(int num_consumers, 3059e1de2f42SDonggeun Kim struct regulator_bulk_data *consumers) 3060e1de2f42SDonggeun Kim { 3061e1de2f42SDonggeun Kim int i; 3062e1de2f42SDonggeun Kim int ret; 3063e1de2f42SDonggeun Kim 3064e1de2f42SDonggeun Kim for (i = 0; i < num_consumers; i++) 3065e1de2f42SDonggeun Kim consumers[i].ret = 3066e1de2f42SDonggeun Kim regulator_force_disable(consumers[i].consumer); 3067e1de2f42SDonggeun Kim 3068e1de2f42SDonggeun Kim for (i = 0; i < num_consumers; i++) { 3069e1de2f42SDonggeun Kim if (consumers[i].ret != 0) { 3070e1de2f42SDonggeun Kim ret = consumers[i].ret; 3071e1de2f42SDonggeun Kim goto out; 3072e1de2f42SDonggeun Kim } 3073e1de2f42SDonggeun Kim } 3074e1de2f42SDonggeun Kim 3075e1de2f42SDonggeun Kim return 0; 3076e1de2f42SDonggeun Kim out: 3077e1de2f42SDonggeun Kim return ret; 3078e1de2f42SDonggeun Kim } 3079e1de2f42SDonggeun Kim EXPORT_SYMBOL_GPL(regulator_bulk_force_disable); 3080e1de2f42SDonggeun Kim 3081e1de2f42SDonggeun Kim /** 3082414c70cbSLiam Girdwood * regulator_bulk_free - free multiple regulator consumers 3083414c70cbSLiam Girdwood * 3084414c70cbSLiam Girdwood * @num_consumers: Number of consumers 3085414c70cbSLiam Girdwood * @consumers: Consumer data; clients are stored here. 3086414c70cbSLiam Girdwood * 3087414c70cbSLiam Girdwood * This convenience API allows consumers to free multiple regulator 3088414c70cbSLiam Girdwood * clients in a single API call. 3089414c70cbSLiam Girdwood */ 3090414c70cbSLiam Girdwood void regulator_bulk_free(int num_consumers, 3091414c70cbSLiam Girdwood struct regulator_bulk_data *consumers) 3092414c70cbSLiam Girdwood { 3093414c70cbSLiam Girdwood int i; 3094414c70cbSLiam Girdwood 3095414c70cbSLiam Girdwood for (i = 0; i < num_consumers; i++) { 3096414c70cbSLiam Girdwood regulator_put(consumers[i].consumer); 3097414c70cbSLiam Girdwood consumers[i].consumer = NULL; 3098414c70cbSLiam Girdwood } 3099414c70cbSLiam Girdwood } 3100414c70cbSLiam Girdwood EXPORT_SYMBOL_GPL(regulator_bulk_free); 3101414c70cbSLiam Girdwood 3102414c70cbSLiam Girdwood /** 3103414c70cbSLiam Girdwood * regulator_notifier_call_chain - call regulator event notifier 310469279fb9SMark Brown * @rdev: regulator source 3105414c70cbSLiam Girdwood * @event: notifier block 310669279fb9SMark Brown * @data: callback-specific data. 3107414c70cbSLiam Girdwood * 3108414c70cbSLiam Girdwood * Called by regulator drivers to notify clients a regulator event has 3109414c70cbSLiam Girdwood * occurred. We also notify regulator clients downstream. 3110b136fb44SJonathan Cameron * Note lock must be held by caller. 3111414c70cbSLiam Girdwood */ 3112414c70cbSLiam Girdwood int regulator_notifier_call_chain(struct regulator_dev *rdev, 3113414c70cbSLiam Girdwood unsigned long event, void *data) 3114414c70cbSLiam Girdwood { 3115414c70cbSLiam Girdwood _notifier_call_chain(rdev, event, data); 3116414c70cbSLiam Girdwood return NOTIFY_DONE; 3117414c70cbSLiam Girdwood 3118414c70cbSLiam Girdwood } 3119414c70cbSLiam Girdwood EXPORT_SYMBOL_GPL(regulator_notifier_call_chain); 3120414c70cbSLiam Girdwood 3121be721979SMark Brown /** 3122be721979SMark Brown * regulator_mode_to_status - convert a regulator mode into a status 3123be721979SMark Brown * 3124be721979SMark Brown * @mode: Mode to convert 3125be721979SMark Brown * 3126be721979SMark Brown * Convert a regulator mode into a status. 3127be721979SMark Brown */ 3128be721979SMark Brown int regulator_mode_to_status(unsigned int mode) 3129be721979SMark Brown { 3130be721979SMark Brown switch (mode) { 3131be721979SMark Brown case REGULATOR_MODE_FAST: 3132be721979SMark Brown return REGULATOR_STATUS_FAST; 3133be721979SMark Brown case REGULATOR_MODE_NORMAL: 3134be721979SMark Brown return REGULATOR_STATUS_NORMAL; 3135be721979SMark Brown case REGULATOR_MODE_IDLE: 3136be721979SMark Brown return REGULATOR_STATUS_IDLE; 313703ffcf3dSKrystian Garbaciak case REGULATOR_MODE_STANDBY: 3138be721979SMark Brown return REGULATOR_STATUS_STANDBY; 3139be721979SMark Brown default: 31401beaf762SKrystian Garbaciak return REGULATOR_STATUS_UNDEFINED; 3141be721979SMark Brown } 3142be721979SMark Brown } 3143be721979SMark Brown EXPORT_SYMBOL_GPL(regulator_mode_to_status); 3144be721979SMark Brown 31457ad68e2fSDavid Brownell /* 31467ad68e2fSDavid Brownell * To avoid cluttering sysfs (and memory) with useless state, only 31477ad68e2fSDavid Brownell * create attributes that can be meaningfully displayed. 31487ad68e2fSDavid Brownell */ 31497ad68e2fSDavid Brownell static int add_regulator_attributes(struct regulator_dev *rdev) 31507ad68e2fSDavid Brownell { 31517ad68e2fSDavid Brownell struct device *dev = &rdev->dev; 31527ad68e2fSDavid Brownell struct regulator_ops *ops = rdev->desc->ops; 31537ad68e2fSDavid Brownell int status = 0; 31547ad68e2fSDavid Brownell 31557ad68e2fSDavid Brownell /* some attributes need specific methods to be displayed */ 31564c78899bSMark Brown if ((ops->get_voltage && ops->get_voltage(rdev) >= 0) || 3157f2889e65SMark Brown (ops->get_voltage_sel && ops->get_voltage_sel(rdev) >= 0) || 3158f2889e65SMark Brown (ops->list_voltage && ops->list_voltage(rdev, 0) >= 0)) { 31597ad68e2fSDavid Brownell status = device_create_file(dev, &dev_attr_microvolts); 31607ad68e2fSDavid Brownell if (status < 0) 31617ad68e2fSDavid Brownell return status; 31627ad68e2fSDavid Brownell } 31637ad68e2fSDavid Brownell if (ops->get_current_limit) { 31647ad68e2fSDavid Brownell status = device_create_file(dev, &dev_attr_microamps); 31657ad68e2fSDavid Brownell if (status < 0) 31667ad68e2fSDavid Brownell return status; 31677ad68e2fSDavid Brownell } 31687ad68e2fSDavid Brownell if (ops->get_mode) { 31697ad68e2fSDavid Brownell status = device_create_file(dev, &dev_attr_opmode); 31707ad68e2fSDavid Brownell if (status < 0) 31717ad68e2fSDavid Brownell return status; 31727ad68e2fSDavid Brownell } 31737ad68e2fSDavid Brownell if (ops->is_enabled) { 31747ad68e2fSDavid Brownell status = device_create_file(dev, &dev_attr_state); 31757ad68e2fSDavid Brownell if (status < 0) 31767ad68e2fSDavid Brownell return status; 31777ad68e2fSDavid Brownell } 3178853116a1SDavid Brownell if (ops->get_status) { 3179853116a1SDavid Brownell status = device_create_file(dev, &dev_attr_status); 3180853116a1SDavid Brownell if (status < 0) 3181853116a1SDavid Brownell return status; 3182853116a1SDavid Brownell } 3183f59c8f9fSMark Brown if (ops->get_bypass) { 3184f59c8f9fSMark Brown status = device_create_file(dev, &dev_attr_bypass); 3185f59c8f9fSMark Brown if (status < 0) 3186f59c8f9fSMark Brown return status; 3187f59c8f9fSMark Brown } 31887ad68e2fSDavid Brownell 31897ad68e2fSDavid Brownell /* some attributes are type-specific */ 31907ad68e2fSDavid Brownell if (rdev->desc->type == REGULATOR_CURRENT) { 31917ad68e2fSDavid Brownell status = device_create_file(dev, &dev_attr_requested_microamps); 31927ad68e2fSDavid Brownell if (status < 0) 31937ad68e2fSDavid Brownell return status; 31947ad68e2fSDavid Brownell } 31957ad68e2fSDavid Brownell 31967ad68e2fSDavid Brownell /* all the other attributes exist to support constraints; 31977ad68e2fSDavid Brownell * don't show them if there are no constraints, or if the 31987ad68e2fSDavid Brownell * relevant supporting methods are missing. 31997ad68e2fSDavid Brownell */ 32007ad68e2fSDavid Brownell if (!rdev->constraints) 32017ad68e2fSDavid Brownell return status; 32027ad68e2fSDavid Brownell 32037ad68e2fSDavid Brownell /* constraints need specific supporting methods */ 3204e8eef82bSMark Brown if (ops->set_voltage || ops->set_voltage_sel) { 32057ad68e2fSDavid Brownell status = device_create_file(dev, &dev_attr_min_microvolts); 32067ad68e2fSDavid Brownell if (status < 0) 32077ad68e2fSDavid Brownell return status; 32087ad68e2fSDavid Brownell status = device_create_file(dev, &dev_attr_max_microvolts); 32097ad68e2fSDavid Brownell if (status < 0) 32107ad68e2fSDavid Brownell return status; 32117ad68e2fSDavid Brownell } 32127ad68e2fSDavid Brownell if (ops->set_current_limit) { 32137ad68e2fSDavid Brownell status = device_create_file(dev, &dev_attr_min_microamps); 32147ad68e2fSDavid Brownell if (status < 0) 32157ad68e2fSDavid Brownell return status; 32167ad68e2fSDavid Brownell status = device_create_file(dev, &dev_attr_max_microamps); 32177ad68e2fSDavid Brownell if (status < 0) 32187ad68e2fSDavid Brownell return status; 32197ad68e2fSDavid Brownell } 32207ad68e2fSDavid Brownell 32217ad68e2fSDavid Brownell status = device_create_file(dev, &dev_attr_suspend_standby_state); 32227ad68e2fSDavid Brownell if (status < 0) 32237ad68e2fSDavid Brownell return status; 32247ad68e2fSDavid Brownell status = device_create_file(dev, &dev_attr_suspend_mem_state); 32257ad68e2fSDavid Brownell if (status < 0) 32267ad68e2fSDavid Brownell return status; 32277ad68e2fSDavid Brownell status = device_create_file(dev, &dev_attr_suspend_disk_state); 32287ad68e2fSDavid Brownell if (status < 0) 32297ad68e2fSDavid Brownell return status; 32307ad68e2fSDavid Brownell 32317ad68e2fSDavid Brownell if (ops->set_suspend_voltage) { 32327ad68e2fSDavid Brownell status = device_create_file(dev, 32337ad68e2fSDavid Brownell &dev_attr_suspend_standby_microvolts); 32347ad68e2fSDavid Brownell if (status < 0) 32357ad68e2fSDavid Brownell return status; 32367ad68e2fSDavid Brownell status = device_create_file(dev, 32377ad68e2fSDavid Brownell &dev_attr_suspend_mem_microvolts); 32387ad68e2fSDavid Brownell if (status < 0) 32397ad68e2fSDavid Brownell return status; 32407ad68e2fSDavid Brownell status = device_create_file(dev, 32417ad68e2fSDavid Brownell &dev_attr_suspend_disk_microvolts); 32427ad68e2fSDavid Brownell if (status < 0) 32437ad68e2fSDavid Brownell return status; 32447ad68e2fSDavid Brownell } 32457ad68e2fSDavid Brownell 32467ad68e2fSDavid Brownell if (ops->set_suspend_mode) { 32477ad68e2fSDavid Brownell status = device_create_file(dev, 32487ad68e2fSDavid Brownell &dev_attr_suspend_standby_mode); 32497ad68e2fSDavid Brownell if (status < 0) 32507ad68e2fSDavid Brownell return status; 32517ad68e2fSDavid Brownell status = device_create_file(dev, 32527ad68e2fSDavid Brownell &dev_attr_suspend_mem_mode); 32537ad68e2fSDavid Brownell if (status < 0) 32547ad68e2fSDavid Brownell return status; 32557ad68e2fSDavid Brownell status = device_create_file(dev, 32567ad68e2fSDavid Brownell &dev_attr_suspend_disk_mode); 32577ad68e2fSDavid Brownell if (status < 0) 32587ad68e2fSDavid Brownell return status; 32597ad68e2fSDavid Brownell } 32607ad68e2fSDavid Brownell 32617ad68e2fSDavid Brownell return status; 32627ad68e2fSDavid Brownell } 32637ad68e2fSDavid Brownell 32641130e5b3SMark Brown static void rdev_init_debugfs(struct regulator_dev *rdev) 32651130e5b3SMark Brown { 32661130e5b3SMark Brown rdev->debugfs = debugfs_create_dir(rdev_get_name(rdev), debugfs_root); 326724751434SStephen Boyd if (!rdev->debugfs) { 32681130e5b3SMark Brown rdev_warn(rdev, "Failed to create debugfs directory\n"); 32691130e5b3SMark Brown return; 32701130e5b3SMark Brown } 32711130e5b3SMark Brown 32721130e5b3SMark Brown debugfs_create_u32("use_count", 0444, rdev->debugfs, 32731130e5b3SMark Brown &rdev->use_count); 32741130e5b3SMark Brown debugfs_create_u32("open_count", 0444, rdev->debugfs, 32751130e5b3SMark Brown &rdev->open_count); 3276f59c8f9fSMark Brown debugfs_create_u32("bypass_count", 0444, rdev->debugfs, 3277f59c8f9fSMark Brown &rdev->bypass_count); 32781130e5b3SMark Brown } 32791130e5b3SMark Brown 3280414c70cbSLiam Girdwood /** 3281414c70cbSLiam Girdwood * regulator_register - register regulator 328269279fb9SMark Brown * @regulator_desc: regulator to register 3283c172708dSMark Brown * @config: runtime configuration for regulator 3284414c70cbSLiam Girdwood * 3285414c70cbSLiam Girdwood * Called by regulator drivers to register a regulator. 3286414c70cbSLiam Girdwood * Returns 0 on success. 3287414c70cbSLiam Girdwood */ 328865f26846SMark Brown struct regulator_dev * 328965f26846SMark Brown regulator_register(const struct regulator_desc *regulator_desc, 3290c172708dSMark Brown const struct regulator_config *config) 3291414c70cbSLiam Girdwood { 32929a8f5e07SMark Brown const struct regulation_constraints *constraints = NULL; 3293c172708dSMark Brown const struct regulator_init_data *init_data; 3294414c70cbSLiam Girdwood static atomic_t regulator_no = ATOMIC_INIT(0); 3295414c70cbSLiam Girdwood struct regulator_dev *rdev; 329632c8fad4SMark Brown struct device *dev; 3297a5766f11SLiam Girdwood int ret, i; 329869511a45SRajendra Nayak const char *supply = NULL; 3299414c70cbSLiam Girdwood 3300c172708dSMark Brown if (regulator_desc == NULL || config == NULL) 3301414c70cbSLiam Girdwood return ERR_PTR(-EINVAL); 3302414c70cbSLiam Girdwood 330332c8fad4SMark Brown dev = config->dev; 3304dcf70112SMark Brown WARN_ON(!dev); 330532c8fad4SMark Brown 3306414c70cbSLiam Girdwood if (regulator_desc->name == NULL || regulator_desc->ops == NULL) 3307414c70cbSLiam Girdwood return ERR_PTR(-EINVAL); 3308414c70cbSLiam Girdwood 3309cd78dfc6SDiego Liziero if (regulator_desc->type != REGULATOR_VOLTAGE && 3310cd78dfc6SDiego Liziero regulator_desc->type != REGULATOR_CURRENT) 3311414c70cbSLiam Girdwood return ERR_PTR(-EINVAL); 3312414c70cbSLiam Girdwood 3313476c2d83SMark Brown /* Only one of each should be implemented */ 3314476c2d83SMark Brown WARN_ON(regulator_desc->ops->get_voltage && 3315476c2d83SMark Brown regulator_desc->ops->get_voltage_sel); 3316e8eef82bSMark Brown WARN_ON(regulator_desc->ops->set_voltage && 3317e8eef82bSMark Brown regulator_desc->ops->set_voltage_sel); 3318476c2d83SMark Brown 3319476c2d83SMark Brown /* If we're using selectors we must implement list_voltage. */ 3320476c2d83SMark Brown if (regulator_desc->ops->get_voltage_sel && 3321476c2d83SMark Brown !regulator_desc->ops->list_voltage) { 3322476c2d83SMark Brown return ERR_PTR(-EINVAL); 3323476c2d83SMark Brown } 3324e8eef82bSMark Brown if (regulator_desc->ops->set_voltage_sel && 3325e8eef82bSMark Brown !regulator_desc->ops->list_voltage) { 3326e8eef82bSMark Brown return ERR_PTR(-EINVAL); 3327e8eef82bSMark Brown } 3328476c2d83SMark Brown 3329c172708dSMark Brown init_data = config->init_data; 3330c172708dSMark Brown 3331414c70cbSLiam Girdwood rdev = kzalloc(sizeof(struct regulator_dev), GFP_KERNEL); 3332414c70cbSLiam Girdwood if (rdev == NULL) 3333414c70cbSLiam Girdwood return ERR_PTR(-ENOMEM); 3334414c70cbSLiam Girdwood 3335414c70cbSLiam Girdwood mutex_lock(®ulator_list_mutex); 3336414c70cbSLiam Girdwood 3337414c70cbSLiam Girdwood mutex_init(&rdev->mutex); 3338c172708dSMark Brown rdev->reg_data = config->driver_data; 3339414c70cbSLiam Girdwood rdev->owner = regulator_desc->owner; 3340414c70cbSLiam Girdwood rdev->desc = regulator_desc; 33413a4b0a07SMark Brown if (config->regmap) 334265b19ce6SMark Brown rdev->regmap = config->regmap; 334352b84dacSAnilKumar Ch else if (dev_get_regmap(dev, NULL)) 33443a4b0a07SMark Brown rdev->regmap = dev_get_regmap(dev, NULL); 334552b84dacSAnilKumar Ch else if (dev->parent) 334652b84dacSAnilKumar Ch rdev->regmap = dev_get_regmap(dev->parent, NULL); 3347414c70cbSLiam Girdwood INIT_LIST_HEAD(&rdev->consumer_list); 3348414c70cbSLiam Girdwood INIT_LIST_HEAD(&rdev->list); 3349414c70cbSLiam Girdwood BLOCKING_INIT_NOTIFIER_HEAD(&rdev->notifier); 3350da07ecd9SMark Brown INIT_DELAYED_WORK(&rdev->disable_work, regulator_disable_work); 3351414c70cbSLiam Girdwood 3352a5766f11SLiam Girdwood /* preform any regulator specific init */ 33539a8f5e07SMark Brown if (init_data && init_data->regulator_init) { 3354a5766f11SLiam Girdwood ret = init_data->regulator_init(rdev->reg_data); 33554fca9545SDavid Brownell if (ret < 0) 33564fca9545SDavid Brownell goto clean; 3357a5766f11SLiam Girdwood } 3358a5766f11SLiam Girdwood 3359a5766f11SLiam Girdwood /* register with sysfs */ 3360a5766f11SLiam Girdwood rdev->dev.class = ®ulator_class; 3361c172708dSMark Brown rdev->dev.of_node = config->of_node; 3362a5766f11SLiam Girdwood rdev->dev.parent = dev; 3363812460a9SKay Sievers dev_set_name(&rdev->dev, "regulator.%d", 3364812460a9SKay Sievers atomic_inc_return(®ulator_no) - 1); 3365a5766f11SLiam Girdwood ret = device_register(&rdev->dev); 3366ad7725cbSVasiliy Kulikov if (ret != 0) { 3367ad7725cbSVasiliy Kulikov put_device(&rdev->dev); 33684fca9545SDavid Brownell goto clean; 3369ad7725cbSVasiliy Kulikov } 3370a5766f11SLiam Girdwood 3371a5766f11SLiam Girdwood dev_set_drvdata(&rdev->dev, rdev); 3372a5766f11SLiam Girdwood 3373b2a1ef47SMarek Szyprowski if (config->ena_gpio && gpio_is_valid(config->ena_gpio)) { 337465f73508SMark Brown ret = gpio_request_one(config->ena_gpio, 337565f73508SMark Brown GPIOF_DIR_OUT | config->ena_gpio_flags, 337665f73508SMark Brown rdev_get_name(rdev)); 337765f73508SMark Brown if (ret != 0) { 337865f73508SMark Brown rdev_err(rdev, "Failed to request enable GPIO%d: %d\n", 337965f73508SMark Brown config->ena_gpio, ret); 3380b2da55d9SAndrew Lunn goto wash; 338165f73508SMark Brown } 338265f73508SMark Brown 338365f73508SMark Brown rdev->ena_gpio = config->ena_gpio; 338465f73508SMark Brown rdev->ena_gpio_invert = config->ena_gpio_invert; 338565f73508SMark Brown 338665f73508SMark Brown if (config->ena_gpio_flags & GPIOF_OUT_INIT_HIGH) 338765f73508SMark Brown rdev->ena_gpio_state = 1; 338865f73508SMark Brown 338965f73508SMark Brown if (rdev->ena_gpio_invert) 339065f73508SMark Brown rdev->ena_gpio_state = !rdev->ena_gpio_state; 339165f73508SMark Brown } 339265f73508SMark Brown 339374f544c1SMike Rapoport /* set regulator constraints */ 33949a8f5e07SMark Brown if (init_data) 33959a8f5e07SMark Brown constraints = &init_data->constraints; 33969a8f5e07SMark Brown 33979a8f5e07SMark Brown ret = set_machine_constraints(rdev, constraints); 339874f544c1SMike Rapoport if (ret < 0) 339974f544c1SMike Rapoport goto scrub; 340074f544c1SMike Rapoport 34017ad68e2fSDavid Brownell /* add attributes supported by this regulator */ 34027ad68e2fSDavid Brownell ret = add_regulator_attributes(rdev); 34037ad68e2fSDavid Brownell if (ret < 0) 34047ad68e2fSDavid Brownell goto scrub; 34057ad68e2fSDavid Brownell 34069a8f5e07SMark Brown if (init_data && init_data->supply_regulator) 340769511a45SRajendra Nayak supply = init_data->supply_regulator; 340869511a45SRajendra Nayak else if (regulator_desc->supply_name) 340969511a45SRajendra Nayak supply = regulator_desc->supply_name; 341069511a45SRajendra Nayak 341169511a45SRajendra Nayak if (supply) { 34120178f3e2SMark Brown struct regulator_dev *r; 34130178f3e2SMark Brown 34146d191a5fSMark Brown r = regulator_dev_lookup(dev, supply, &ret); 34150178f3e2SMark Brown 341669511a45SRajendra Nayak if (!r) { 341769511a45SRajendra Nayak dev_err(dev, "Failed to find supply %s\n", supply); 341804bf3011SMark Brown ret = -EPROBE_DEFER; 34190178f3e2SMark Brown goto scrub; 34200178f3e2SMark Brown } 34210178f3e2SMark Brown 34220178f3e2SMark Brown ret = set_supply(rdev, r); 34230178f3e2SMark Brown if (ret < 0) 34240178f3e2SMark Brown goto scrub; 3425b2296bd4SLaxman Dewangan 3426b2296bd4SLaxman Dewangan /* Enable supply if rail is enabled */ 3427b1a86831SMark Brown if (_regulator_is_enabled(rdev)) { 3428b2296bd4SLaxman Dewangan ret = regulator_enable(rdev->supply); 3429b2296bd4SLaxman Dewangan if (ret < 0) 3430b2296bd4SLaxman Dewangan goto scrub; 3431b2296bd4SLaxman Dewangan } 34320178f3e2SMark Brown } 34330178f3e2SMark Brown 3434a5766f11SLiam Girdwood /* add consumers devices */ 34359a8f5e07SMark Brown if (init_data) { 3436a5766f11SLiam Girdwood for (i = 0; i < init_data->num_consumer_supplies; i++) { 3437a5766f11SLiam Girdwood ret = set_consumer_device_supply(rdev, 343840f9244fSMark Brown init_data->consumer_supplies[i].dev_name, 3439a5766f11SLiam Girdwood init_data->consumer_supplies[i].supply); 344023c2f041SMark Brown if (ret < 0) { 344123c2f041SMark Brown dev_err(dev, "Failed to set supply %s\n", 344223c2f041SMark Brown init_data->consumer_supplies[i].supply); 3443d4033b54SJani Nikula goto unset_supplies; 3444a5766f11SLiam Girdwood } 344523c2f041SMark Brown } 34469a8f5e07SMark Brown } 3447a5766f11SLiam Girdwood 3448a5766f11SLiam Girdwood list_add(&rdev->list, ®ulator_list); 34491130e5b3SMark Brown 34501130e5b3SMark Brown rdev_init_debugfs(rdev); 3451a5766f11SLiam Girdwood out: 3452414c70cbSLiam Girdwood mutex_unlock(®ulator_list_mutex); 3453414c70cbSLiam Girdwood return rdev; 34544fca9545SDavid Brownell 3455d4033b54SJani Nikula unset_supplies: 3456d4033b54SJani Nikula unset_regulator_supplies(rdev); 3457d4033b54SJani Nikula 34584fca9545SDavid Brownell scrub: 3459e81dba85SMark Brown if (rdev->supply) 346023ff2f0fSCharles Keepax _regulator_put(rdev->supply); 346165f73508SMark Brown if (rdev->ena_gpio) 346265f73508SMark Brown gpio_free(rdev->ena_gpio); 34631a6958e7SAxel Lin kfree(rdev->constraints); 3464b2da55d9SAndrew Lunn wash: 34654fca9545SDavid Brownell device_unregister(&rdev->dev); 346653032dafSPaul Walmsley /* device core frees rdev */ 346753032dafSPaul Walmsley rdev = ERR_PTR(ret); 346853032dafSPaul Walmsley goto out; 346953032dafSPaul Walmsley 34704fca9545SDavid Brownell clean: 34714fca9545SDavid Brownell kfree(rdev); 34724fca9545SDavid Brownell rdev = ERR_PTR(ret); 34734fca9545SDavid Brownell goto out; 3474414c70cbSLiam Girdwood } 3475414c70cbSLiam Girdwood EXPORT_SYMBOL_GPL(regulator_register); 3476414c70cbSLiam Girdwood 3477414c70cbSLiam Girdwood /** 3478414c70cbSLiam Girdwood * regulator_unregister - unregister regulator 347969279fb9SMark Brown * @rdev: regulator to unregister 3480414c70cbSLiam Girdwood * 3481414c70cbSLiam Girdwood * Called by regulator drivers to unregister a regulator. 3482414c70cbSLiam Girdwood */ 3483414c70cbSLiam Girdwood void regulator_unregister(struct regulator_dev *rdev) 3484414c70cbSLiam Girdwood { 3485414c70cbSLiam Girdwood if (rdev == NULL) 3486414c70cbSLiam Girdwood return; 3487414c70cbSLiam Girdwood 3488e032b376SMark Brown if (rdev->supply) 3489e032b376SMark Brown regulator_put(rdev->supply); 3490414c70cbSLiam Girdwood mutex_lock(®ulator_list_mutex); 34911130e5b3SMark Brown debugfs_remove_recursive(rdev->debugfs); 349243829731STejun Heo flush_work(&rdev->disable_work.work); 34936bf87d17SMark Brown WARN_ON(rdev->open_count); 34940f1d747bSMike Rapoport unset_regulator_supplies(rdev); 3495414c70cbSLiam Girdwood list_del(&rdev->list); 3496f8c12fe3SMark Brown kfree(rdev->constraints); 349765f73508SMark Brown if (rdev->ena_gpio) 349865f73508SMark Brown gpio_free(rdev->ena_gpio); 349958fb5cf5SLothar Waßmann device_unregister(&rdev->dev); 3500414c70cbSLiam Girdwood mutex_unlock(®ulator_list_mutex); 3501414c70cbSLiam Girdwood } 3502414c70cbSLiam Girdwood EXPORT_SYMBOL_GPL(regulator_unregister); 3503414c70cbSLiam Girdwood 3504414c70cbSLiam Girdwood /** 3505cf7bbcdfSMark Brown * regulator_suspend_prepare - prepare regulators for system wide suspend 3506414c70cbSLiam Girdwood * @state: system suspend state 3507414c70cbSLiam Girdwood * 3508414c70cbSLiam Girdwood * Configure each regulator with it's suspend operating parameters for state. 3509414c70cbSLiam Girdwood * This will usually be called by machine suspend code prior to supending. 3510414c70cbSLiam Girdwood */ 3511414c70cbSLiam Girdwood int regulator_suspend_prepare(suspend_state_t state) 3512414c70cbSLiam Girdwood { 3513414c70cbSLiam Girdwood struct regulator_dev *rdev; 3514414c70cbSLiam Girdwood int ret = 0; 3515414c70cbSLiam Girdwood 3516414c70cbSLiam Girdwood /* ON is handled by regulator active state */ 3517414c70cbSLiam Girdwood if (state == PM_SUSPEND_ON) 3518414c70cbSLiam Girdwood return -EINVAL; 3519414c70cbSLiam Girdwood 3520414c70cbSLiam Girdwood mutex_lock(®ulator_list_mutex); 3521414c70cbSLiam Girdwood list_for_each_entry(rdev, ®ulator_list, list) { 3522414c70cbSLiam Girdwood 3523414c70cbSLiam Girdwood mutex_lock(&rdev->mutex); 3524414c70cbSLiam Girdwood ret = suspend_prepare(rdev, state); 3525414c70cbSLiam Girdwood mutex_unlock(&rdev->mutex); 3526414c70cbSLiam Girdwood 3527414c70cbSLiam Girdwood if (ret < 0) { 35285da84fd9SJoe Perches rdev_err(rdev, "failed to prepare\n"); 3529414c70cbSLiam Girdwood goto out; 3530414c70cbSLiam Girdwood } 3531414c70cbSLiam Girdwood } 3532414c70cbSLiam Girdwood out: 3533414c70cbSLiam Girdwood mutex_unlock(®ulator_list_mutex); 3534414c70cbSLiam Girdwood return ret; 3535414c70cbSLiam Girdwood } 3536414c70cbSLiam Girdwood EXPORT_SYMBOL_GPL(regulator_suspend_prepare); 3537414c70cbSLiam Girdwood 3538414c70cbSLiam Girdwood /** 35397a32b589SMyungJoo Ham * regulator_suspend_finish - resume regulators from system wide suspend 35407a32b589SMyungJoo Ham * 35417a32b589SMyungJoo Ham * Turn on regulators that might be turned off by regulator_suspend_prepare 35427a32b589SMyungJoo Ham * and that should be turned on according to the regulators properties. 35437a32b589SMyungJoo Ham */ 35447a32b589SMyungJoo Ham int regulator_suspend_finish(void) 35457a32b589SMyungJoo Ham { 35467a32b589SMyungJoo Ham struct regulator_dev *rdev; 35477a32b589SMyungJoo Ham int ret = 0, error; 35487a32b589SMyungJoo Ham 35497a32b589SMyungJoo Ham mutex_lock(®ulator_list_mutex); 35507a32b589SMyungJoo Ham list_for_each_entry(rdev, ®ulator_list, list) { 35517a32b589SMyungJoo Ham struct regulator_ops *ops = rdev->desc->ops; 35527a32b589SMyungJoo Ham 35537a32b589SMyungJoo Ham mutex_lock(&rdev->mutex); 35547a32b589SMyungJoo Ham if ((rdev->use_count > 0 || rdev->constraints->always_on) && 35557a32b589SMyungJoo Ham ops->enable) { 35567a32b589SMyungJoo Ham error = ops->enable(rdev); 35577a32b589SMyungJoo Ham if (error) 35587a32b589SMyungJoo Ham ret = error; 35597a32b589SMyungJoo Ham } else { 35607a32b589SMyungJoo Ham if (!has_full_constraints) 35617a32b589SMyungJoo Ham goto unlock; 35627a32b589SMyungJoo Ham if (!ops->disable) 35637a32b589SMyungJoo Ham goto unlock; 3564b1a86831SMark Brown if (!_regulator_is_enabled(rdev)) 35657a32b589SMyungJoo Ham goto unlock; 35667a32b589SMyungJoo Ham 35677a32b589SMyungJoo Ham error = ops->disable(rdev); 35687a32b589SMyungJoo Ham if (error) 35697a32b589SMyungJoo Ham ret = error; 35707a32b589SMyungJoo Ham } 35717a32b589SMyungJoo Ham unlock: 35727a32b589SMyungJoo Ham mutex_unlock(&rdev->mutex); 35737a32b589SMyungJoo Ham } 35747a32b589SMyungJoo Ham mutex_unlock(®ulator_list_mutex); 35757a32b589SMyungJoo Ham return ret; 35767a32b589SMyungJoo Ham } 35777a32b589SMyungJoo Ham EXPORT_SYMBOL_GPL(regulator_suspend_finish); 35787a32b589SMyungJoo Ham 35797a32b589SMyungJoo Ham /** 3580ca725561SMark Brown * regulator_has_full_constraints - the system has fully specified constraints 3581ca725561SMark Brown * 3582ca725561SMark Brown * Calling this function will cause the regulator API to disable all 3583ca725561SMark Brown * regulators which have a zero use count and don't have an always_on 3584ca725561SMark Brown * constraint in a late_initcall. 3585ca725561SMark Brown * 3586ca725561SMark Brown * The intention is that this will become the default behaviour in a 3587ca725561SMark Brown * future kernel release so users are encouraged to use this facility 3588ca725561SMark Brown * now. 3589ca725561SMark Brown */ 3590ca725561SMark Brown void regulator_has_full_constraints(void) 3591ca725561SMark Brown { 3592ca725561SMark Brown has_full_constraints = 1; 3593ca725561SMark Brown } 3594ca725561SMark Brown EXPORT_SYMBOL_GPL(regulator_has_full_constraints); 3595ca725561SMark Brown 3596ca725561SMark Brown /** 3597688fe99aSMark Brown * regulator_use_dummy_regulator - Provide a dummy regulator when none is found 3598688fe99aSMark Brown * 3599688fe99aSMark Brown * Calling this function will cause the regulator API to provide a 3600688fe99aSMark Brown * dummy regulator to consumers if no physical regulator is found, 3601688fe99aSMark Brown * allowing most consumers to proceed as though a regulator were 3602688fe99aSMark Brown * configured. This allows systems such as those with software 3603688fe99aSMark Brown * controllable regulators for the CPU core only to be brought up more 3604688fe99aSMark Brown * readily. 3605688fe99aSMark Brown */ 3606688fe99aSMark Brown void regulator_use_dummy_regulator(void) 3607688fe99aSMark Brown { 3608688fe99aSMark Brown board_wants_dummy_regulator = true; 3609688fe99aSMark Brown } 3610688fe99aSMark Brown EXPORT_SYMBOL_GPL(regulator_use_dummy_regulator); 3611688fe99aSMark Brown 3612688fe99aSMark Brown /** 3613414c70cbSLiam Girdwood * rdev_get_drvdata - get rdev regulator driver data 361469279fb9SMark Brown * @rdev: regulator 3615414c70cbSLiam Girdwood * 3616414c70cbSLiam Girdwood * Get rdev regulator driver private data. This call can be used in the 3617414c70cbSLiam Girdwood * regulator driver context. 3618414c70cbSLiam Girdwood */ 3619414c70cbSLiam Girdwood void *rdev_get_drvdata(struct regulator_dev *rdev) 3620414c70cbSLiam Girdwood { 3621414c70cbSLiam Girdwood return rdev->reg_data; 3622414c70cbSLiam Girdwood } 3623414c70cbSLiam Girdwood EXPORT_SYMBOL_GPL(rdev_get_drvdata); 3624414c70cbSLiam Girdwood 3625414c70cbSLiam Girdwood /** 3626414c70cbSLiam Girdwood * regulator_get_drvdata - get regulator driver data 3627414c70cbSLiam Girdwood * @regulator: regulator 3628414c70cbSLiam Girdwood * 3629414c70cbSLiam Girdwood * Get regulator driver private data. This call can be used in the consumer 3630414c70cbSLiam Girdwood * driver context when non API regulator specific functions need to be called. 3631414c70cbSLiam Girdwood */ 3632414c70cbSLiam Girdwood void *regulator_get_drvdata(struct regulator *regulator) 3633414c70cbSLiam Girdwood { 3634414c70cbSLiam Girdwood return regulator->rdev->reg_data; 3635414c70cbSLiam Girdwood } 3636414c70cbSLiam Girdwood EXPORT_SYMBOL_GPL(regulator_get_drvdata); 3637414c70cbSLiam Girdwood 3638414c70cbSLiam Girdwood /** 3639414c70cbSLiam Girdwood * regulator_set_drvdata - set regulator driver data 3640414c70cbSLiam Girdwood * @regulator: regulator 3641414c70cbSLiam Girdwood * @data: data 3642414c70cbSLiam Girdwood */ 3643414c70cbSLiam Girdwood void regulator_set_drvdata(struct regulator *regulator, void *data) 3644414c70cbSLiam Girdwood { 3645414c70cbSLiam Girdwood regulator->rdev->reg_data = data; 3646414c70cbSLiam Girdwood } 3647414c70cbSLiam Girdwood EXPORT_SYMBOL_GPL(regulator_set_drvdata); 3648414c70cbSLiam Girdwood 3649414c70cbSLiam Girdwood /** 3650414c70cbSLiam Girdwood * regulator_get_id - get regulator ID 365169279fb9SMark Brown * @rdev: regulator 3652414c70cbSLiam Girdwood */ 3653414c70cbSLiam Girdwood int rdev_get_id(struct regulator_dev *rdev) 3654414c70cbSLiam Girdwood { 3655414c70cbSLiam Girdwood return rdev->desc->id; 3656414c70cbSLiam Girdwood } 3657414c70cbSLiam Girdwood EXPORT_SYMBOL_GPL(rdev_get_id); 3658414c70cbSLiam Girdwood 3659a5766f11SLiam Girdwood struct device *rdev_get_dev(struct regulator_dev *rdev) 3660a5766f11SLiam Girdwood { 3661a5766f11SLiam Girdwood return &rdev->dev; 3662a5766f11SLiam Girdwood } 3663a5766f11SLiam Girdwood EXPORT_SYMBOL_GPL(rdev_get_dev); 3664a5766f11SLiam Girdwood 3665a5766f11SLiam Girdwood void *regulator_get_init_drvdata(struct regulator_init_data *reg_init_data) 3666a5766f11SLiam Girdwood { 3667a5766f11SLiam Girdwood return reg_init_data->driver_data; 3668a5766f11SLiam Girdwood } 3669a5766f11SLiam Girdwood EXPORT_SYMBOL_GPL(regulator_get_init_drvdata); 3670a5766f11SLiam Girdwood 3671ba55a974SMark Brown #ifdef CONFIG_DEBUG_FS 3672ba55a974SMark Brown static ssize_t supply_map_read_file(struct file *file, char __user *user_buf, 3673ba55a974SMark Brown size_t count, loff_t *ppos) 3674ba55a974SMark Brown { 3675ba55a974SMark Brown char *buf = kmalloc(PAGE_SIZE, GFP_KERNEL); 3676ba55a974SMark Brown ssize_t len, ret = 0; 3677ba55a974SMark Brown struct regulator_map *map; 3678ba55a974SMark Brown 3679ba55a974SMark Brown if (!buf) 3680ba55a974SMark Brown return -ENOMEM; 3681ba55a974SMark Brown 3682ba55a974SMark Brown list_for_each_entry(map, ®ulator_map_list, list) { 3683ba55a974SMark Brown len = snprintf(buf + ret, PAGE_SIZE - ret, 3684ba55a974SMark Brown "%s -> %s.%s\n", 3685ba55a974SMark Brown rdev_get_name(map->regulator), map->dev_name, 3686ba55a974SMark Brown map->supply); 3687ba55a974SMark Brown if (len >= 0) 3688ba55a974SMark Brown ret += len; 3689ba55a974SMark Brown if (ret > PAGE_SIZE) { 3690ba55a974SMark Brown ret = PAGE_SIZE; 3691ba55a974SMark Brown break; 3692ba55a974SMark Brown } 3693ba55a974SMark Brown } 3694ba55a974SMark Brown 3695ba55a974SMark Brown ret = simple_read_from_buffer(user_buf, count, ppos, buf, ret); 3696ba55a974SMark Brown 3697ba55a974SMark Brown kfree(buf); 3698ba55a974SMark Brown 3699ba55a974SMark Brown return ret; 3700ba55a974SMark Brown } 370124751434SStephen Boyd #endif 3702ba55a974SMark Brown 3703ba55a974SMark Brown static const struct file_operations supply_map_fops = { 370424751434SStephen Boyd #ifdef CONFIG_DEBUG_FS 3705ba55a974SMark Brown .read = supply_map_read_file, 3706ba55a974SMark Brown .llseek = default_llseek, 3707ba55a974SMark Brown #endif 370824751434SStephen Boyd }; 3709ba55a974SMark Brown 3710414c70cbSLiam Girdwood static int __init regulator_init(void) 3711414c70cbSLiam Girdwood { 371234abbd68SMark Brown int ret; 371334abbd68SMark Brown 371434abbd68SMark Brown ret = class_register(®ulator_class); 371534abbd68SMark Brown 37161130e5b3SMark Brown debugfs_root = debugfs_create_dir("regulator", NULL); 371724751434SStephen Boyd if (!debugfs_root) 37181130e5b3SMark Brown pr_warn("regulator: Failed to create debugfs directory\n"); 3719ba55a974SMark Brown 3720f4d562c6SMark Brown debugfs_create_file("supply_map", 0444, debugfs_root, NULL, 3721f4d562c6SMark Brown &supply_map_fops); 37221130e5b3SMark Brown 372334abbd68SMark Brown regulator_dummy_init(); 372434abbd68SMark Brown 372534abbd68SMark Brown return ret; 3726414c70cbSLiam Girdwood } 3727414c70cbSLiam Girdwood 3728414c70cbSLiam Girdwood /* init early to allow our consumers to complete system booting */ 3729414c70cbSLiam Girdwood core_initcall(regulator_init); 3730ca725561SMark Brown 3731ca725561SMark Brown static int __init regulator_init_complete(void) 3732ca725561SMark Brown { 3733ca725561SMark Brown struct regulator_dev *rdev; 3734ca725561SMark Brown struct regulator_ops *ops; 3735ca725561SMark Brown struct regulation_constraints *c; 3736ca725561SMark Brown int enabled, ret; 3737ca725561SMark Brown 373886f5fcfcSMark Brown /* 373986f5fcfcSMark Brown * Since DT doesn't provide an idiomatic mechanism for 374086f5fcfcSMark Brown * enabling full constraints and since it's much more natural 374186f5fcfcSMark Brown * with DT to provide them just assume that a DT enabled 374286f5fcfcSMark Brown * system has full constraints. 374386f5fcfcSMark Brown */ 374486f5fcfcSMark Brown if (of_have_populated_dt()) 374586f5fcfcSMark Brown has_full_constraints = true; 374686f5fcfcSMark Brown 3747ca725561SMark Brown mutex_lock(®ulator_list_mutex); 3748ca725561SMark Brown 3749ca725561SMark Brown /* If we have a full configuration then disable any regulators 3750ca725561SMark Brown * which are not in use or always_on. This will become the 3751ca725561SMark Brown * default behaviour in the future. 3752ca725561SMark Brown */ 3753ca725561SMark Brown list_for_each_entry(rdev, ®ulator_list, list) { 3754ca725561SMark Brown ops = rdev->desc->ops; 3755ca725561SMark Brown c = rdev->constraints; 3756ca725561SMark Brown 3757f25e0b4fSMark Brown if (!ops->disable || (c && c->always_on)) 3758ca725561SMark Brown continue; 3759ca725561SMark Brown 3760ca725561SMark Brown mutex_lock(&rdev->mutex); 3761ca725561SMark Brown 3762ca725561SMark Brown if (rdev->use_count) 3763ca725561SMark Brown goto unlock; 3764ca725561SMark Brown 3765ca725561SMark Brown /* If we can't read the status assume it's on. */ 3766ca725561SMark Brown if (ops->is_enabled) 3767ca725561SMark Brown enabled = ops->is_enabled(rdev); 3768ca725561SMark Brown else 3769ca725561SMark Brown enabled = 1; 3770ca725561SMark Brown 3771ca725561SMark Brown if (!enabled) 3772ca725561SMark Brown goto unlock; 3773ca725561SMark Brown 3774ca725561SMark Brown if (has_full_constraints) { 3775ca725561SMark Brown /* We log since this may kill the system if it 3776ca725561SMark Brown * goes wrong. */ 37775da84fd9SJoe Perches rdev_info(rdev, "disabling\n"); 3778ca725561SMark Brown ret = ops->disable(rdev); 3779ca725561SMark Brown if (ret != 0) { 37805da84fd9SJoe Perches rdev_err(rdev, "couldn't disable: %d\n", ret); 3781ca725561SMark Brown } 3782ca725561SMark Brown } else { 3783ca725561SMark Brown /* The intention is that in future we will 3784ca725561SMark Brown * assume that full constraints are provided 3785ca725561SMark Brown * so warn even if we aren't going to do 3786ca725561SMark Brown * anything here. 3787ca725561SMark Brown */ 37885da84fd9SJoe Perches rdev_warn(rdev, "incomplete constraints, leaving on\n"); 3789ca725561SMark Brown } 3790ca725561SMark Brown 3791ca725561SMark Brown unlock: 3792ca725561SMark Brown mutex_unlock(&rdev->mutex); 3793ca725561SMark Brown } 3794ca725561SMark Brown 3795ca725561SMark Brown mutex_unlock(®ulator_list_mutex); 3796ca725561SMark Brown 3797ca725561SMark Brown return 0; 3798ca725561SMark Brown } 3799ca725561SMark Brown late_initcall(regulator_init_complete); 3800