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 13845ffbd136SMark Brown /** 1385414c70cbSLiam Girdwood * regulator_put - "free" the regulator source 1386414c70cbSLiam Girdwood * @regulator: regulator source 1387414c70cbSLiam Girdwood * 1388414c70cbSLiam Girdwood * Note: drivers must ensure that all regulator_enable calls made on this 1389414c70cbSLiam Girdwood * regulator source are balanced by regulator_disable calls prior to calling 1390414c70cbSLiam Girdwood * this function. 1391414c70cbSLiam Girdwood */ 1392414c70cbSLiam Girdwood void regulator_put(struct regulator *regulator) 1393414c70cbSLiam Girdwood { 1394414c70cbSLiam Girdwood struct regulator_dev *rdev; 1395414c70cbSLiam Girdwood 1396414c70cbSLiam Girdwood if (regulator == NULL || IS_ERR(regulator)) 1397414c70cbSLiam Girdwood return; 1398414c70cbSLiam Girdwood 1399414c70cbSLiam Girdwood mutex_lock(®ulator_list_mutex); 1400414c70cbSLiam Girdwood rdev = regulator->rdev; 1401414c70cbSLiam Girdwood 14025de70519SMark Brown debugfs_remove_recursive(regulator->debugfs); 14035de70519SMark Brown 1404414c70cbSLiam Girdwood /* remove any sysfs entries */ 1405e2c98eafSShawn Guo if (regulator->dev) 1406414c70cbSLiam Girdwood sysfs_remove_link(&rdev->dev.kobj, regulator->supply_name); 14075de70519SMark Brown kfree(regulator->supply_name); 1408414c70cbSLiam Girdwood list_del(®ulator->list); 1409414c70cbSLiam Girdwood kfree(regulator); 1410414c70cbSLiam Girdwood 14115ffbd136SMark Brown rdev->open_count--; 14125ffbd136SMark Brown rdev->exclusive = 0; 14135ffbd136SMark Brown 1414414c70cbSLiam Girdwood module_put(rdev->owner); 1415414c70cbSLiam Girdwood mutex_unlock(®ulator_list_mutex); 1416414c70cbSLiam Girdwood } 1417414c70cbSLiam Girdwood EXPORT_SYMBOL_GPL(regulator_put); 1418414c70cbSLiam Girdwood 1419d5ad34f7SMark Brown static int devm_regulator_match(struct device *dev, void *res, void *data) 1420d5ad34f7SMark Brown { 1421d5ad34f7SMark Brown struct regulator **r = res; 1422d5ad34f7SMark Brown if (!r || !*r) { 1423d5ad34f7SMark Brown WARN_ON(!r || !*r); 1424d5ad34f7SMark Brown return 0; 1425d5ad34f7SMark Brown } 1426d5ad34f7SMark Brown return *r == data; 1427d5ad34f7SMark Brown } 1428d5ad34f7SMark Brown 1429d5ad34f7SMark Brown /** 1430d5ad34f7SMark Brown * devm_regulator_put - Resource managed regulator_put() 1431d5ad34f7SMark Brown * @regulator: regulator to free 1432d5ad34f7SMark Brown * 1433d5ad34f7SMark Brown * Deallocate a regulator allocated with devm_regulator_get(). Normally 1434d5ad34f7SMark Brown * this function will not need to be called and the resource management 1435d5ad34f7SMark Brown * code will ensure that the resource is freed. 1436d5ad34f7SMark Brown */ 1437d5ad34f7SMark Brown void devm_regulator_put(struct regulator *regulator) 1438d5ad34f7SMark Brown { 1439d5ad34f7SMark Brown int rc; 1440d5ad34f7SMark Brown 1441361ff501SMark Brown rc = devres_release(regulator->dev, devm_regulator_release, 1442d5ad34f7SMark Brown devm_regulator_match, regulator); 1443230a5a1cSMark Brown if (rc != 0) 1444d5ad34f7SMark Brown WARN_ON(rc); 1445d5ad34f7SMark Brown } 1446d5ad34f7SMark Brown EXPORT_SYMBOL_GPL(devm_regulator_put); 1447d5ad34f7SMark Brown 14485c5659d0SMark Brown static int _regulator_do_enable(struct regulator_dev *rdev) 14495c5659d0SMark Brown { 14505c5659d0SMark Brown int ret, delay; 14515c5659d0SMark Brown 14525c5659d0SMark Brown /* Query before enabling in case configuration dependent. */ 14535c5659d0SMark Brown ret = _regulator_get_enable_time(rdev); 14545c5659d0SMark Brown if (ret >= 0) { 14555c5659d0SMark Brown delay = ret; 14565c5659d0SMark Brown } else { 14575c5659d0SMark Brown rdev_warn(rdev, "enable_time() failed: %d\n", ret); 14585c5659d0SMark Brown delay = 0; 14595c5659d0SMark Brown } 14605c5659d0SMark Brown 14615c5659d0SMark Brown trace_regulator_enable(rdev_get_name(rdev)); 14625c5659d0SMark Brown 146365f73508SMark Brown if (rdev->ena_gpio) { 146465f73508SMark Brown gpio_set_value_cansleep(rdev->ena_gpio, 146565f73508SMark Brown !rdev->ena_gpio_invert); 146665f73508SMark Brown rdev->ena_gpio_state = 1; 146765f73508SMark Brown } else if (rdev->desc->ops->enable) { 14685c5659d0SMark Brown ret = rdev->desc->ops->enable(rdev); 14695c5659d0SMark Brown if (ret < 0) 14705c5659d0SMark Brown return ret; 14715c5659d0SMark Brown } else { 14725c5659d0SMark Brown return -EINVAL; 14735c5659d0SMark Brown } 14745c5659d0SMark Brown 14755c5659d0SMark Brown /* Allow the regulator to ramp; it would be useful to extend 14765c5659d0SMark Brown * this for bulk operations so that the regulators can ramp 14775c5659d0SMark Brown * together. */ 14785c5659d0SMark Brown trace_regulator_enable_delay(rdev_get_name(rdev)); 14795c5659d0SMark Brown 14805c5659d0SMark Brown if (delay >= 1000) { 14815c5659d0SMark Brown mdelay(delay / 1000); 14825c5659d0SMark Brown udelay(delay % 1000); 14835c5659d0SMark Brown } else if (delay) { 14845c5659d0SMark Brown udelay(delay); 14855c5659d0SMark Brown } 14865c5659d0SMark Brown 14875c5659d0SMark Brown trace_regulator_enable_complete(rdev_get_name(rdev)); 14885c5659d0SMark Brown 14895c5659d0SMark Brown return 0; 14905c5659d0SMark Brown } 14915c5659d0SMark Brown 1492414c70cbSLiam Girdwood /* locks held by regulator_enable() */ 1493414c70cbSLiam Girdwood static int _regulator_enable(struct regulator_dev *rdev) 1494414c70cbSLiam Girdwood { 14955c5659d0SMark Brown int ret; 1496414c70cbSLiam Girdwood 1497414c70cbSLiam Girdwood /* check voltage and requested load before enabling */ 1498414c70cbSLiam Girdwood if (rdev->constraints && 14999a2372faSMark Brown (rdev->constraints->valid_ops_mask & REGULATOR_CHANGE_DRMS)) 1500414c70cbSLiam Girdwood drms_uA_update(rdev); 1501414c70cbSLiam Girdwood 15029a2372faSMark Brown if (rdev->use_count == 0) { 15039a2372faSMark Brown /* The regulator may on if it's not switchable or left on */ 15049a2372faSMark Brown ret = _regulator_is_enabled(rdev); 15059a2372faSMark Brown if (ret == -EINVAL || ret == 0) { 15069a2372faSMark Brown if (!_regulator_can_change_status(rdev)) 15079a2372faSMark Brown return -EPERM; 15089a2372faSMark Brown 15095c5659d0SMark Brown ret = _regulator_do_enable(rdev); 15109a2372faSMark Brown if (ret < 0) 15119a2372faSMark Brown return ret; 151231aae2beSMark Brown 1513a7433cffSLinus Walleij } else if (ret < 0) { 15145da84fd9SJoe Perches rdev_err(rdev, "is_enabled() failed: %d\n", ret); 1515414c70cbSLiam Girdwood return ret; 1516414c70cbSLiam Girdwood } 1517a7433cffSLinus Walleij /* Fallthrough on positive return values - already enabled */ 1518414c70cbSLiam Girdwood } 1519414c70cbSLiam Girdwood 15209a2372faSMark Brown rdev->use_count++; 15219a2372faSMark Brown 15229a2372faSMark Brown return 0; 1523414c70cbSLiam Girdwood } 1524414c70cbSLiam Girdwood 1525414c70cbSLiam Girdwood /** 1526414c70cbSLiam Girdwood * regulator_enable - enable regulator output 1527414c70cbSLiam Girdwood * @regulator: regulator source 1528414c70cbSLiam Girdwood * 1529cf7bbcdfSMark Brown * Request that the regulator be enabled with the regulator output at 1530cf7bbcdfSMark Brown * the predefined voltage or current value. Calls to regulator_enable() 1531cf7bbcdfSMark Brown * must be balanced with calls to regulator_disable(). 1532cf7bbcdfSMark Brown * 1533414c70cbSLiam Girdwood * NOTE: the output value can be set by other drivers, boot loader or may be 1534cf7bbcdfSMark Brown * hardwired in the regulator. 1535414c70cbSLiam Girdwood */ 1536414c70cbSLiam Girdwood int regulator_enable(struct regulator *regulator) 1537414c70cbSLiam Girdwood { 1538412aec61SDavid Brownell struct regulator_dev *rdev = regulator->rdev; 1539412aec61SDavid Brownell int ret = 0; 1540414c70cbSLiam Girdwood 15416492bc1bSMark Brown if (regulator->always_on) 15426492bc1bSMark Brown return 0; 15436492bc1bSMark Brown 15443801b86aSMark Brown if (rdev->supply) { 15453801b86aSMark Brown ret = regulator_enable(rdev->supply); 15463801b86aSMark Brown if (ret != 0) 15473801b86aSMark Brown return ret; 15483801b86aSMark Brown } 15493801b86aSMark Brown 1550412aec61SDavid Brownell mutex_lock(&rdev->mutex); 1551412aec61SDavid Brownell ret = _regulator_enable(rdev); 1552412aec61SDavid Brownell mutex_unlock(&rdev->mutex); 15533801b86aSMark Brown 1554d1685e4eSHeiko Stübner if (ret != 0 && rdev->supply) 15553801b86aSMark Brown regulator_disable(rdev->supply); 15563801b86aSMark Brown 1557414c70cbSLiam Girdwood return ret; 1558414c70cbSLiam Girdwood } 1559414c70cbSLiam Girdwood EXPORT_SYMBOL_GPL(regulator_enable); 1560414c70cbSLiam Girdwood 15615c5659d0SMark Brown static int _regulator_do_disable(struct regulator_dev *rdev) 15625c5659d0SMark Brown { 15635c5659d0SMark Brown int ret; 15645c5659d0SMark Brown 15655c5659d0SMark Brown trace_regulator_disable(rdev_get_name(rdev)); 15665c5659d0SMark Brown 15675c5659d0SMark Brown if (rdev->ena_gpio) { 15685c5659d0SMark Brown gpio_set_value_cansleep(rdev->ena_gpio, 15695c5659d0SMark Brown rdev->ena_gpio_invert); 15705c5659d0SMark Brown rdev->ena_gpio_state = 0; 15715c5659d0SMark Brown 15725c5659d0SMark Brown } else if (rdev->desc->ops->disable) { 15735c5659d0SMark Brown ret = rdev->desc->ops->disable(rdev); 15745c5659d0SMark Brown if (ret != 0) 15755c5659d0SMark Brown return ret; 15765c5659d0SMark Brown } 15775c5659d0SMark Brown 15785c5659d0SMark Brown trace_regulator_disable_complete(rdev_get_name(rdev)); 15795c5659d0SMark Brown 15805c5659d0SMark Brown _notifier_call_chain(rdev, REGULATOR_EVENT_DISABLE, 15815c5659d0SMark Brown NULL); 15825c5659d0SMark Brown return 0; 15835c5659d0SMark Brown } 15845c5659d0SMark Brown 1585414c70cbSLiam Girdwood /* locks held by regulator_disable() */ 15863801b86aSMark Brown static int _regulator_disable(struct regulator_dev *rdev) 1587414c70cbSLiam Girdwood { 1588414c70cbSLiam Girdwood int ret = 0; 1589414c70cbSLiam Girdwood 1590cd94b505SDavid Brownell if (WARN(rdev->use_count <= 0, 159143e7ee33SJoe Perches "unbalanced disables for %s\n", rdev_get_name(rdev))) 1592cd94b505SDavid Brownell return -EIO; 1593cd94b505SDavid Brownell 1594414c70cbSLiam Girdwood /* are we the last user and permitted to disable ? */ 159560ef66fcSMark Brown if (rdev->use_count == 1 && 159660ef66fcSMark Brown (rdev->constraints && !rdev->constraints->always_on)) { 1597414c70cbSLiam Girdwood 1598414c70cbSLiam Girdwood /* we are last user */ 15995c5659d0SMark Brown if (_regulator_can_change_status(rdev)) { 16005c5659d0SMark Brown ret = _regulator_do_disable(rdev); 1601414c70cbSLiam Girdwood if (ret < 0) { 16025da84fd9SJoe Perches rdev_err(rdev, "failed to disable\n"); 1603414c70cbSLiam Girdwood return ret; 1604414c70cbSLiam Girdwood } 1605414c70cbSLiam Girdwood } 1606414c70cbSLiam Girdwood 1607414c70cbSLiam Girdwood rdev->use_count = 0; 1608414c70cbSLiam Girdwood } else if (rdev->use_count > 1) { 1609414c70cbSLiam Girdwood 1610414c70cbSLiam Girdwood if (rdev->constraints && 1611414c70cbSLiam Girdwood (rdev->constraints->valid_ops_mask & 1612414c70cbSLiam Girdwood REGULATOR_CHANGE_DRMS)) 1613414c70cbSLiam Girdwood drms_uA_update(rdev); 1614414c70cbSLiam Girdwood 1615414c70cbSLiam Girdwood rdev->use_count--; 1616414c70cbSLiam Girdwood } 16173801b86aSMark Brown 1618414c70cbSLiam Girdwood return ret; 1619414c70cbSLiam Girdwood } 1620414c70cbSLiam Girdwood 1621414c70cbSLiam Girdwood /** 1622414c70cbSLiam Girdwood * regulator_disable - disable regulator output 1623414c70cbSLiam Girdwood * @regulator: regulator source 1624414c70cbSLiam Girdwood * 1625cf7bbcdfSMark Brown * Disable the regulator output voltage or current. Calls to 1626cf7bbcdfSMark Brown * regulator_enable() must be balanced with calls to 1627cf7bbcdfSMark Brown * regulator_disable(). 162869279fb9SMark Brown * 1629414c70cbSLiam Girdwood * NOTE: this will only disable the regulator output if no other consumer 1630cf7bbcdfSMark Brown * devices have it enabled, the regulator device supports disabling and 1631cf7bbcdfSMark Brown * machine constraints permit this operation. 1632414c70cbSLiam Girdwood */ 1633414c70cbSLiam Girdwood int regulator_disable(struct regulator *regulator) 1634414c70cbSLiam Girdwood { 1635412aec61SDavid Brownell struct regulator_dev *rdev = regulator->rdev; 1636412aec61SDavid Brownell int ret = 0; 1637414c70cbSLiam Girdwood 16386492bc1bSMark Brown if (regulator->always_on) 16396492bc1bSMark Brown return 0; 16406492bc1bSMark Brown 1641412aec61SDavid Brownell mutex_lock(&rdev->mutex); 16423801b86aSMark Brown ret = _regulator_disable(rdev); 1643412aec61SDavid Brownell mutex_unlock(&rdev->mutex); 16448cbf811dSJeffrey Carlyle 16453801b86aSMark Brown if (ret == 0 && rdev->supply) 16463801b86aSMark Brown regulator_disable(rdev->supply); 16478cbf811dSJeffrey Carlyle 1648414c70cbSLiam Girdwood return ret; 1649414c70cbSLiam Girdwood } 1650414c70cbSLiam Girdwood EXPORT_SYMBOL_GPL(regulator_disable); 1651414c70cbSLiam Girdwood 1652414c70cbSLiam Girdwood /* locks held by regulator_force_disable() */ 16533801b86aSMark Brown static int _regulator_force_disable(struct regulator_dev *rdev) 1654414c70cbSLiam Girdwood { 1655414c70cbSLiam Girdwood int ret = 0; 1656414c70cbSLiam Girdwood 1657414c70cbSLiam Girdwood /* force disable */ 1658414c70cbSLiam Girdwood if (rdev->desc->ops->disable) { 1659414c70cbSLiam Girdwood /* ah well, who wants to live forever... */ 1660414c70cbSLiam Girdwood ret = rdev->desc->ops->disable(rdev); 1661414c70cbSLiam Girdwood if (ret < 0) { 16625da84fd9SJoe Perches rdev_err(rdev, "failed to force disable\n"); 1663414c70cbSLiam Girdwood return ret; 1664414c70cbSLiam Girdwood } 1665414c70cbSLiam Girdwood /* notify other consumers that power has been forced off */ 166684b68263SMark Brown _notifier_call_chain(rdev, REGULATOR_EVENT_FORCE_DISABLE | 166784b68263SMark Brown REGULATOR_EVENT_DISABLE, NULL); 1668414c70cbSLiam Girdwood } 1669414c70cbSLiam Girdwood 1670414c70cbSLiam Girdwood return ret; 1671414c70cbSLiam Girdwood } 1672414c70cbSLiam Girdwood 1673414c70cbSLiam Girdwood /** 1674414c70cbSLiam Girdwood * regulator_force_disable - force disable regulator output 1675414c70cbSLiam Girdwood * @regulator: regulator source 1676414c70cbSLiam Girdwood * 1677414c70cbSLiam Girdwood * Forcibly disable the regulator output voltage or current. 1678414c70cbSLiam Girdwood * NOTE: this *will* disable the regulator output even if other consumer 1679414c70cbSLiam Girdwood * devices have it enabled. This should be used for situations when device 1680414c70cbSLiam Girdwood * damage will likely occur if the regulator is not disabled (e.g. over temp). 1681414c70cbSLiam Girdwood */ 1682414c70cbSLiam Girdwood int regulator_force_disable(struct regulator *regulator) 1683414c70cbSLiam Girdwood { 168482d15839SMark Brown struct regulator_dev *rdev = regulator->rdev; 1685414c70cbSLiam Girdwood int ret; 1686414c70cbSLiam Girdwood 168782d15839SMark Brown mutex_lock(&rdev->mutex); 1688414c70cbSLiam Girdwood regulator->uA_load = 0; 16893801b86aSMark Brown ret = _regulator_force_disable(regulator->rdev); 169082d15839SMark Brown mutex_unlock(&rdev->mutex); 16918cbf811dSJeffrey Carlyle 16923801b86aSMark Brown if (rdev->supply) 16933801b86aSMark Brown while (rdev->open_count--) 16943801b86aSMark Brown regulator_disable(rdev->supply); 16958cbf811dSJeffrey Carlyle 1696414c70cbSLiam Girdwood return ret; 1697414c70cbSLiam Girdwood } 1698414c70cbSLiam Girdwood EXPORT_SYMBOL_GPL(regulator_force_disable); 1699414c70cbSLiam Girdwood 1700da07ecd9SMark Brown static void regulator_disable_work(struct work_struct *work) 1701da07ecd9SMark Brown { 1702da07ecd9SMark Brown struct regulator_dev *rdev = container_of(work, struct regulator_dev, 1703da07ecd9SMark Brown disable_work.work); 1704da07ecd9SMark Brown int count, i, ret; 1705da07ecd9SMark Brown 1706da07ecd9SMark Brown mutex_lock(&rdev->mutex); 1707da07ecd9SMark Brown 1708da07ecd9SMark Brown BUG_ON(!rdev->deferred_disables); 1709da07ecd9SMark Brown 1710da07ecd9SMark Brown count = rdev->deferred_disables; 1711da07ecd9SMark Brown rdev->deferred_disables = 0; 1712da07ecd9SMark Brown 1713da07ecd9SMark Brown for (i = 0; i < count; i++) { 1714da07ecd9SMark Brown ret = _regulator_disable(rdev); 1715da07ecd9SMark Brown if (ret != 0) 1716da07ecd9SMark Brown rdev_err(rdev, "Deferred disable failed: %d\n", ret); 1717da07ecd9SMark Brown } 1718da07ecd9SMark Brown 1719da07ecd9SMark Brown mutex_unlock(&rdev->mutex); 1720da07ecd9SMark Brown 1721da07ecd9SMark Brown if (rdev->supply) { 1722da07ecd9SMark Brown for (i = 0; i < count; i++) { 1723da07ecd9SMark Brown ret = regulator_disable(rdev->supply); 1724da07ecd9SMark Brown if (ret != 0) { 1725da07ecd9SMark Brown rdev_err(rdev, 1726da07ecd9SMark Brown "Supply disable failed: %d\n", ret); 1727da07ecd9SMark Brown } 1728da07ecd9SMark Brown } 1729da07ecd9SMark Brown } 1730da07ecd9SMark Brown } 1731da07ecd9SMark Brown 1732da07ecd9SMark Brown /** 1733da07ecd9SMark Brown * regulator_disable_deferred - disable regulator output with delay 1734da07ecd9SMark Brown * @regulator: regulator source 1735da07ecd9SMark Brown * @ms: miliseconds until the regulator is disabled 1736da07ecd9SMark Brown * 1737da07ecd9SMark Brown * Execute regulator_disable() on the regulator after a delay. This 1738da07ecd9SMark Brown * is intended for use with devices that require some time to quiesce. 1739da07ecd9SMark Brown * 1740da07ecd9SMark Brown * NOTE: this will only disable the regulator output if no other consumer 1741da07ecd9SMark Brown * devices have it enabled, the regulator device supports disabling and 1742da07ecd9SMark Brown * machine constraints permit this operation. 1743da07ecd9SMark Brown */ 1744da07ecd9SMark Brown int regulator_disable_deferred(struct regulator *regulator, int ms) 1745da07ecd9SMark Brown { 1746da07ecd9SMark Brown struct regulator_dev *rdev = regulator->rdev; 1747aa59802dSMark Brown int ret; 1748da07ecd9SMark Brown 17496492bc1bSMark Brown if (regulator->always_on) 17506492bc1bSMark Brown return 0; 17516492bc1bSMark Brown 17522b5a24a0SMark Brown if (!ms) 17532b5a24a0SMark Brown return regulator_disable(regulator); 17542b5a24a0SMark Brown 1755da07ecd9SMark Brown mutex_lock(&rdev->mutex); 1756da07ecd9SMark Brown rdev->deferred_disables++; 1757da07ecd9SMark Brown mutex_unlock(&rdev->mutex); 1758da07ecd9SMark Brown 1759aa59802dSMark Brown ret = schedule_delayed_work(&rdev->disable_work, 1760da07ecd9SMark Brown msecs_to_jiffies(ms)); 1761aa59802dSMark Brown if (ret < 0) 1762aa59802dSMark Brown return ret; 1763aa59802dSMark Brown else 1764aa59802dSMark Brown return 0; 1765da07ecd9SMark Brown } 1766da07ecd9SMark Brown EXPORT_SYMBOL_GPL(regulator_disable_deferred); 1767da07ecd9SMark Brown 1768cd6dffb4SMark Brown /** 1769cd6dffb4SMark Brown * regulator_is_enabled_regmap - standard is_enabled() for regmap users 1770cd6dffb4SMark Brown * 1771cd6dffb4SMark Brown * @rdev: regulator to operate on 1772cd6dffb4SMark Brown * 1773cd6dffb4SMark Brown * Regulators that use regmap for their register I/O can set the 1774cd6dffb4SMark Brown * enable_reg and enable_mask fields in their descriptor and then use 1775cd6dffb4SMark Brown * this as their is_enabled operation, saving some code. 1776cd6dffb4SMark Brown */ 1777cd6dffb4SMark Brown int regulator_is_enabled_regmap(struct regulator_dev *rdev) 1778cd6dffb4SMark Brown { 1779cd6dffb4SMark Brown unsigned int val; 1780cd6dffb4SMark Brown int ret; 1781cd6dffb4SMark Brown 1782cd6dffb4SMark Brown ret = regmap_read(rdev->regmap, rdev->desc->enable_reg, &val); 1783cd6dffb4SMark Brown if (ret != 0) 1784cd6dffb4SMark Brown return ret; 1785cd6dffb4SMark Brown 1786cd6dffb4SMark Brown return (val & rdev->desc->enable_mask) != 0; 1787cd6dffb4SMark Brown } 1788cd6dffb4SMark Brown EXPORT_SYMBOL_GPL(regulator_is_enabled_regmap); 1789cd6dffb4SMark Brown 1790cd6dffb4SMark Brown /** 1791cd6dffb4SMark Brown * regulator_enable_regmap - standard enable() for regmap users 1792cd6dffb4SMark Brown * 1793cd6dffb4SMark Brown * @rdev: regulator to operate on 1794cd6dffb4SMark Brown * 1795cd6dffb4SMark Brown * Regulators that use regmap for their register I/O can set the 1796cd6dffb4SMark Brown * enable_reg and enable_mask fields in their descriptor and then use 1797cd6dffb4SMark Brown * this as their enable() operation, saving some code. 1798cd6dffb4SMark Brown */ 1799cd6dffb4SMark Brown int regulator_enable_regmap(struct regulator_dev *rdev) 1800cd6dffb4SMark Brown { 1801cd6dffb4SMark Brown return regmap_update_bits(rdev->regmap, rdev->desc->enable_reg, 1802cd6dffb4SMark Brown rdev->desc->enable_mask, 1803cd6dffb4SMark Brown rdev->desc->enable_mask); 1804cd6dffb4SMark Brown } 1805cd6dffb4SMark Brown EXPORT_SYMBOL_GPL(regulator_enable_regmap); 1806cd6dffb4SMark Brown 1807cd6dffb4SMark Brown /** 1808cd6dffb4SMark Brown * regulator_disable_regmap - standard disable() for regmap users 1809cd6dffb4SMark Brown * 1810cd6dffb4SMark Brown * @rdev: regulator to operate on 1811cd6dffb4SMark Brown * 1812cd6dffb4SMark Brown * Regulators that use regmap for their register I/O can set the 1813cd6dffb4SMark Brown * enable_reg and enable_mask fields in their descriptor and then use 1814cd6dffb4SMark Brown * this as their disable() operation, saving some code. 1815cd6dffb4SMark Brown */ 1816cd6dffb4SMark Brown int regulator_disable_regmap(struct regulator_dev *rdev) 1817cd6dffb4SMark Brown { 1818cd6dffb4SMark Brown return regmap_update_bits(rdev->regmap, rdev->desc->enable_reg, 1819cd6dffb4SMark Brown rdev->desc->enable_mask, 0); 1820cd6dffb4SMark Brown } 1821cd6dffb4SMark Brown EXPORT_SYMBOL_GPL(regulator_disable_regmap); 1822cd6dffb4SMark Brown 1823414c70cbSLiam Girdwood static int _regulator_is_enabled(struct regulator_dev *rdev) 1824414c70cbSLiam Girdwood { 182565f73508SMark Brown /* A GPIO control always takes precedence */ 182665f73508SMark Brown if (rdev->ena_gpio) 182765f73508SMark Brown return rdev->ena_gpio_state; 182865f73508SMark Brown 18299a7f6a4cSMark Brown /* If we don't know then assume that the regulator is always on */ 18309332546fSMark Brown if (!rdev->desc->ops->is_enabled) 18319a7f6a4cSMark Brown return 1; 1832414c70cbSLiam Girdwood 18339332546fSMark Brown return rdev->desc->ops->is_enabled(rdev); 1834414c70cbSLiam Girdwood } 1835414c70cbSLiam Girdwood 1836414c70cbSLiam Girdwood /** 1837414c70cbSLiam Girdwood * regulator_is_enabled - is the regulator output enabled 1838414c70cbSLiam Girdwood * @regulator: regulator source 1839414c70cbSLiam Girdwood * 1840412aec61SDavid Brownell * Returns positive if the regulator driver backing the source/client 1841412aec61SDavid Brownell * has requested that the device be enabled, zero if it hasn't, else a 1842412aec61SDavid Brownell * negative errno code. 1843412aec61SDavid Brownell * 1844412aec61SDavid Brownell * Note that the device backing this regulator handle can have multiple 1845412aec61SDavid Brownell * users, so it might be enabled even if regulator_enable() was never 1846412aec61SDavid Brownell * called for this particular source. 1847414c70cbSLiam Girdwood */ 1848414c70cbSLiam Girdwood int regulator_is_enabled(struct regulator *regulator) 1849414c70cbSLiam Girdwood { 18509332546fSMark Brown int ret; 18519332546fSMark Brown 18526492bc1bSMark Brown if (regulator->always_on) 18536492bc1bSMark Brown return 1; 18546492bc1bSMark Brown 18559332546fSMark Brown mutex_lock(®ulator->rdev->mutex); 18569332546fSMark Brown ret = _regulator_is_enabled(regulator->rdev); 18579332546fSMark Brown mutex_unlock(®ulator->rdev->mutex); 18589332546fSMark Brown 18599332546fSMark Brown return ret; 1860414c70cbSLiam Girdwood } 1861414c70cbSLiam Girdwood EXPORT_SYMBOL_GPL(regulator_is_enabled); 1862414c70cbSLiam Girdwood 1863414c70cbSLiam Girdwood /** 18644367cfdcSDavid Brownell * regulator_count_voltages - count regulator_list_voltage() selectors 18654367cfdcSDavid Brownell * @regulator: regulator source 18664367cfdcSDavid Brownell * 18674367cfdcSDavid Brownell * Returns number of selectors, or negative errno. Selectors are 18684367cfdcSDavid Brownell * numbered starting at zero, and typically correspond to bitfields 18694367cfdcSDavid Brownell * in hardware registers. 18704367cfdcSDavid Brownell */ 18714367cfdcSDavid Brownell int regulator_count_voltages(struct regulator *regulator) 18724367cfdcSDavid Brownell { 18734367cfdcSDavid Brownell struct regulator_dev *rdev = regulator->rdev; 18744367cfdcSDavid Brownell 18754367cfdcSDavid Brownell return rdev->desc->n_voltages ? : -EINVAL; 18764367cfdcSDavid Brownell } 18774367cfdcSDavid Brownell EXPORT_SYMBOL_GPL(regulator_count_voltages); 18784367cfdcSDavid Brownell 18794367cfdcSDavid Brownell /** 1880bca7bbffSMark Brown * regulator_list_voltage_linear - List voltages with simple calculation 1881bca7bbffSMark Brown * 1882bca7bbffSMark Brown * @rdev: Regulator device 1883bca7bbffSMark Brown * @selector: Selector to convert into a voltage 1884bca7bbffSMark Brown * 1885bca7bbffSMark Brown * Regulators with a simple linear mapping between voltages and 1886bca7bbffSMark Brown * selectors can set min_uV and uV_step in the regulator descriptor 1887bca7bbffSMark Brown * and then use this function as their list_voltage() operation, 1888bca7bbffSMark Brown */ 1889bca7bbffSMark Brown int regulator_list_voltage_linear(struct regulator_dev *rdev, 1890bca7bbffSMark Brown unsigned int selector) 1891bca7bbffSMark Brown { 1892bca7bbffSMark Brown if (selector >= rdev->desc->n_voltages) 1893bca7bbffSMark Brown return -EINVAL; 1894bca7bbffSMark Brown 1895bca7bbffSMark Brown return rdev->desc->min_uV + (rdev->desc->uV_step * selector); 1896bca7bbffSMark Brown } 1897bca7bbffSMark Brown EXPORT_SYMBOL_GPL(regulator_list_voltage_linear); 1898bca7bbffSMark Brown 1899bca7bbffSMark Brown /** 1900cffc9592SAxel Lin * regulator_list_voltage_table - List voltages with table based mapping 1901cffc9592SAxel Lin * 1902cffc9592SAxel Lin * @rdev: Regulator device 1903cffc9592SAxel Lin * @selector: Selector to convert into a voltage 1904cffc9592SAxel Lin * 1905cffc9592SAxel Lin * Regulators with table based mapping between voltages and 1906cffc9592SAxel Lin * selectors can set volt_table in the regulator descriptor 1907cffc9592SAxel Lin * and then use this function as their list_voltage() operation. 1908cffc9592SAxel Lin */ 1909cffc9592SAxel Lin int regulator_list_voltage_table(struct regulator_dev *rdev, 1910cffc9592SAxel Lin unsigned int selector) 1911cffc9592SAxel Lin { 1912cffc9592SAxel Lin if (!rdev->desc->volt_table) { 1913cffc9592SAxel Lin BUG_ON(!rdev->desc->volt_table); 1914cffc9592SAxel Lin return -EINVAL; 1915cffc9592SAxel Lin } 1916cffc9592SAxel Lin 1917cffc9592SAxel Lin if (selector >= rdev->desc->n_voltages) 1918cffc9592SAxel Lin return -EINVAL; 1919cffc9592SAxel Lin 1920cffc9592SAxel Lin return rdev->desc->volt_table[selector]; 1921cffc9592SAxel Lin } 1922cffc9592SAxel Lin EXPORT_SYMBOL_GPL(regulator_list_voltage_table); 1923cffc9592SAxel Lin 1924cffc9592SAxel Lin /** 19254367cfdcSDavid Brownell * regulator_list_voltage - enumerate supported voltages 19264367cfdcSDavid Brownell * @regulator: regulator source 19274367cfdcSDavid Brownell * @selector: identify voltage to list 19284367cfdcSDavid Brownell * Context: can sleep 19294367cfdcSDavid Brownell * 19304367cfdcSDavid Brownell * Returns a voltage that can be passed to @regulator_set_voltage(), 193188393161SThomas Weber * zero if this selector code can't be used on this system, or a 19324367cfdcSDavid Brownell * negative errno. 19334367cfdcSDavid Brownell */ 19344367cfdcSDavid Brownell int regulator_list_voltage(struct regulator *regulator, unsigned selector) 19354367cfdcSDavid Brownell { 19364367cfdcSDavid Brownell struct regulator_dev *rdev = regulator->rdev; 19374367cfdcSDavid Brownell struct regulator_ops *ops = rdev->desc->ops; 19384367cfdcSDavid Brownell int ret; 19394367cfdcSDavid Brownell 19404367cfdcSDavid Brownell if (!ops->list_voltage || selector >= rdev->desc->n_voltages) 19414367cfdcSDavid Brownell return -EINVAL; 19424367cfdcSDavid Brownell 19434367cfdcSDavid Brownell mutex_lock(&rdev->mutex); 19444367cfdcSDavid Brownell ret = ops->list_voltage(rdev, selector); 19454367cfdcSDavid Brownell mutex_unlock(&rdev->mutex); 19464367cfdcSDavid Brownell 19474367cfdcSDavid Brownell if (ret > 0) { 19484367cfdcSDavid Brownell if (ret < rdev->constraints->min_uV) 19494367cfdcSDavid Brownell ret = 0; 19504367cfdcSDavid Brownell else if (ret > rdev->constraints->max_uV) 19514367cfdcSDavid Brownell ret = 0; 19524367cfdcSDavid Brownell } 19534367cfdcSDavid Brownell 19544367cfdcSDavid Brownell return ret; 19554367cfdcSDavid Brownell } 19564367cfdcSDavid Brownell EXPORT_SYMBOL_GPL(regulator_list_voltage); 19574367cfdcSDavid Brownell 19584367cfdcSDavid Brownell /** 1959a7a1ad90SMark Brown * regulator_is_supported_voltage - check if a voltage range can be supported 1960a7a1ad90SMark Brown * 1961a7a1ad90SMark Brown * @regulator: Regulator to check. 1962a7a1ad90SMark Brown * @min_uV: Minimum required voltage in uV. 1963a7a1ad90SMark Brown * @max_uV: Maximum required voltage in uV. 1964a7a1ad90SMark Brown * 1965a7a1ad90SMark Brown * Returns a boolean or a negative error code. 1966a7a1ad90SMark Brown */ 1967a7a1ad90SMark Brown int regulator_is_supported_voltage(struct regulator *regulator, 1968a7a1ad90SMark Brown int min_uV, int max_uV) 1969a7a1ad90SMark Brown { 1970c5f3939bSMark Brown struct regulator_dev *rdev = regulator->rdev; 1971a7a1ad90SMark Brown int i, voltages, ret; 1972a7a1ad90SMark Brown 1973c5f3939bSMark Brown /* If we can't change voltage check the current voltage */ 1974c5f3939bSMark Brown if (!(rdev->constraints->valid_ops_mask & REGULATOR_CHANGE_VOLTAGE)) { 1975c5f3939bSMark Brown ret = regulator_get_voltage(regulator); 1976c5f3939bSMark Brown if (ret >= 0) 1977c5f3939bSMark Brown return (min_uV >= ret && ret <= max_uV); 1978c5f3939bSMark Brown else 1979c5f3939bSMark Brown return ret; 1980c5f3939bSMark Brown } 1981c5f3939bSMark Brown 1982a7a1ad90SMark Brown ret = regulator_count_voltages(regulator); 1983a7a1ad90SMark Brown if (ret < 0) 1984a7a1ad90SMark Brown return ret; 1985a7a1ad90SMark Brown voltages = ret; 1986a7a1ad90SMark Brown 1987a7a1ad90SMark Brown for (i = 0; i < voltages; i++) { 1988a7a1ad90SMark Brown ret = regulator_list_voltage(regulator, i); 1989a7a1ad90SMark Brown 1990a7a1ad90SMark Brown if (ret >= min_uV && ret <= max_uV) 1991a7a1ad90SMark Brown return 1; 1992a7a1ad90SMark Brown } 1993a7a1ad90SMark Brown 1994a7a1ad90SMark Brown return 0; 1995a7a1ad90SMark Brown } 1996a398eaa2SMark Brown EXPORT_SYMBOL_GPL(regulator_is_supported_voltage); 1997a7a1ad90SMark Brown 19984ab5b3d9SMark Brown /** 19994ab5b3d9SMark Brown * regulator_get_voltage_sel_regmap - standard get_voltage_sel for regmap users 20004ab5b3d9SMark Brown * 20014ab5b3d9SMark Brown * @rdev: regulator to operate on 20024ab5b3d9SMark Brown * 20034ab5b3d9SMark Brown * Regulators that use regmap for their register I/O can set the 20044ab5b3d9SMark Brown * vsel_reg and vsel_mask fields in their descriptor and then use this 20054ab5b3d9SMark Brown * as their get_voltage_vsel operation, saving some code. 20064ab5b3d9SMark Brown */ 20074ab5b3d9SMark Brown int regulator_get_voltage_sel_regmap(struct regulator_dev *rdev) 20084ab5b3d9SMark Brown { 20094ab5b3d9SMark Brown unsigned int val; 20104ab5b3d9SMark Brown int ret; 20114ab5b3d9SMark Brown 20124ab5b3d9SMark Brown ret = regmap_read(rdev->regmap, rdev->desc->vsel_reg, &val); 20134ab5b3d9SMark Brown if (ret != 0) 20144ab5b3d9SMark Brown return ret; 20154ab5b3d9SMark Brown 20164ab5b3d9SMark Brown val &= rdev->desc->vsel_mask; 20174ab5b3d9SMark Brown val >>= ffs(rdev->desc->vsel_mask) - 1; 20184ab5b3d9SMark Brown 20194ab5b3d9SMark Brown return val; 20204ab5b3d9SMark Brown } 20214ab5b3d9SMark Brown EXPORT_SYMBOL_GPL(regulator_get_voltage_sel_regmap); 20224ab5b3d9SMark Brown 20234ab5b3d9SMark Brown /** 20244ab5b3d9SMark Brown * regulator_set_voltage_sel_regmap - standard set_voltage_sel for regmap users 20254ab5b3d9SMark Brown * 20264ab5b3d9SMark Brown * @rdev: regulator to operate on 20274ab5b3d9SMark Brown * @sel: Selector to set 20284ab5b3d9SMark Brown * 20294ab5b3d9SMark Brown * Regulators that use regmap for their register I/O can set the 20304ab5b3d9SMark Brown * vsel_reg and vsel_mask fields in their descriptor and then use this 20314ab5b3d9SMark Brown * as their set_voltage_vsel operation, saving some code. 20324ab5b3d9SMark Brown */ 20334ab5b3d9SMark Brown int regulator_set_voltage_sel_regmap(struct regulator_dev *rdev, unsigned sel) 20344ab5b3d9SMark Brown { 20354ab5b3d9SMark Brown sel <<= ffs(rdev->desc->vsel_mask) - 1; 20364ab5b3d9SMark Brown 20374ab5b3d9SMark Brown return regmap_update_bits(rdev->regmap, rdev->desc->vsel_reg, 20384ab5b3d9SMark Brown rdev->desc->vsel_mask, sel); 20394ab5b3d9SMark Brown } 20404ab5b3d9SMark Brown EXPORT_SYMBOL_GPL(regulator_set_voltage_sel_regmap); 20414ab5b3d9SMark Brown 2042e843fc46SMark Brown /** 2043e843fc46SMark Brown * regulator_map_voltage_iterate - map_voltage() based on list_voltage() 2044e843fc46SMark Brown * 2045e843fc46SMark Brown * @rdev: Regulator to operate on 2046e843fc46SMark Brown * @min_uV: Lower bound for voltage 2047e843fc46SMark Brown * @max_uV: Upper bound for voltage 2048e843fc46SMark Brown * 2049e843fc46SMark Brown * Drivers implementing set_voltage_sel() and list_voltage() can use 2050e843fc46SMark Brown * this as their map_voltage() operation. It will find a suitable 2051e843fc46SMark Brown * voltage by calling list_voltage() until it gets something in bounds 2052e843fc46SMark Brown * for the requested voltages. 2053e843fc46SMark Brown */ 2054e843fc46SMark Brown int regulator_map_voltage_iterate(struct regulator_dev *rdev, 205575790251SMark Brown int min_uV, int max_uV) 205675790251SMark Brown { 2057e8eef82bSMark Brown int best_val = INT_MAX; 2058e843fc46SMark Brown int selector = 0; 2059e843fc46SMark Brown int i, ret; 2060e8eef82bSMark Brown 2061e8eef82bSMark Brown /* Find the smallest voltage that falls within the specified 2062e8eef82bSMark Brown * range. 2063e8eef82bSMark Brown */ 2064e8eef82bSMark Brown for (i = 0; i < rdev->desc->n_voltages; i++) { 2065e8eef82bSMark Brown ret = rdev->desc->ops->list_voltage(rdev, i); 2066e8eef82bSMark Brown if (ret < 0) 2067e8eef82bSMark Brown continue; 2068e8eef82bSMark Brown 2069e8eef82bSMark Brown if (ret < best_val && ret >= min_uV && ret <= max_uV) { 2070e8eef82bSMark Brown best_val = ret; 2071e8eef82bSMark Brown selector = i; 2072e8eef82bSMark Brown } 2073e8eef82bSMark Brown } 2074e8eef82bSMark Brown 2075e843fc46SMark Brown if (best_val != INT_MAX) 2076e843fc46SMark Brown return selector; 2077e843fc46SMark Brown else 2078e843fc46SMark Brown return -EINVAL; 2079e843fc46SMark Brown } 2080e843fc46SMark Brown EXPORT_SYMBOL_GPL(regulator_map_voltage_iterate); 2081e843fc46SMark Brown 2082bca7bbffSMark Brown /** 2083bca7bbffSMark Brown * regulator_map_voltage_linear - map_voltage() for simple linear mappings 2084bca7bbffSMark Brown * 2085bca7bbffSMark Brown * @rdev: Regulator to operate on 2086bca7bbffSMark Brown * @min_uV: Lower bound for voltage 2087bca7bbffSMark Brown * @max_uV: Upper bound for voltage 2088bca7bbffSMark Brown * 2089bca7bbffSMark Brown * Drivers providing min_uV and uV_step in their regulator_desc can 2090bca7bbffSMark Brown * use this as their map_voltage() operation. 2091bca7bbffSMark Brown */ 2092bca7bbffSMark Brown int regulator_map_voltage_linear(struct regulator_dev *rdev, 2093bca7bbffSMark Brown int min_uV, int max_uV) 2094bca7bbffSMark Brown { 2095bca7bbffSMark Brown int ret, voltage; 2096bca7bbffSMark Brown 20975a6881e8SAxel Lin /* Allow uV_step to be 0 for fixed voltage */ 20985a6881e8SAxel Lin if (rdev->desc->n_voltages == 1 && rdev->desc->uV_step == 0) { 20995a6881e8SAxel Lin if (min_uV <= rdev->desc->min_uV && rdev->desc->min_uV <= max_uV) 21005a6881e8SAxel Lin return 0; 21015a6881e8SAxel Lin else 21025a6881e8SAxel Lin return -EINVAL; 21035a6881e8SAxel Lin } 21045a6881e8SAxel Lin 2105bca7bbffSMark Brown if (!rdev->desc->uV_step) { 2106bca7bbffSMark Brown BUG_ON(!rdev->desc->uV_step); 2107bca7bbffSMark Brown return -EINVAL; 2108bca7bbffSMark Brown } 2109bca7bbffSMark Brown 21100bdc81e4SAxel Lin if (min_uV < rdev->desc->min_uV) 21110bdc81e4SAxel Lin min_uV = rdev->desc->min_uV; 21120bdc81e4SAxel Lin 2113ccfcb1c3SAxel Lin ret = DIV_ROUND_UP(min_uV - rdev->desc->min_uV, rdev->desc->uV_step); 2114bca7bbffSMark Brown if (ret < 0) 2115bca7bbffSMark Brown return ret; 2116bca7bbffSMark Brown 2117bca7bbffSMark Brown /* Map back into a voltage to verify we're still in bounds */ 2118bca7bbffSMark Brown voltage = rdev->desc->ops->list_voltage(rdev, ret); 2119bca7bbffSMark Brown if (voltage < min_uV || voltage > max_uV) 2120bca7bbffSMark Brown return -EINVAL; 2121bca7bbffSMark Brown 2122bca7bbffSMark Brown return ret; 2123bca7bbffSMark Brown } 2124bca7bbffSMark Brown EXPORT_SYMBOL_GPL(regulator_map_voltage_linear); 2125bca7bbffSMark Brown 2126a7a1ad90SMark Brown static int _regulator_do_set_voltage(struct regulator_dev *rdev, 2127a7a1ad90SMark Brown int min_uV, int max_uV) 2128a7a1ad90SMark Brown { 2129a7a1ad90SMark Brown int ret; 213075790251SMark Brown int delay = 0; 2131e113d792SMark Brown int best_val = 0; 213275790251SMark Brown unsigned int selector; 2133eba41a5eSAxel Lin int old_selector = -1; 213475790251SMark Brown 213575790251SMark Brown trace_regulator_set_voltage(rdev_get_name(rdev), min_uV, max_uV); 213675790251SMark Brown 213775790251SMark Brown min_uV += rdev->constraints->uV_offset; 213875790251SMark Brown max_uV += rdev->constraints->uV_offset; 213975790251SMark Brown 214077af1b26SLinus Walleij /* 214177af1b26SLinus Walleij * If we can't obtain the old selector there is not enough 214277af1b26SLinus Walleij * info to call set_voltage_time_sel(). 214377af1b26SLinus Walleij */ 21448b7485efSAxel Lin if (_regulator_is_enabled(rdev) && 21458b7485efSAxel Lin rdev->desc->ops->set_voltage_time_sel && 214677af1b26SLinus Walleij rdev->desc->ops->get_voltage_sel) { 2147eba41a5eSAxel Lin old_selector = rdev->desc->ops->get_voltage_sel(rdev); 2148eba41a5eSAxel Lin if (old_selector < 0) 2149eba41a5eSAxel Lin return old_selector; 2150eba41a5eSAxel Lin } 215177af1b26SLinus Walleij 215275790251SMark Brown if (rdev->desc->ops->set_voltage) { 215375790251SMark Brown ret = rdev->desc->ops->set_voltage(rdev, min_uV, max_uV, 215475790251SMark Brown &selector); 2155e113d792SMark Brown 2156e113d792SMark Brown if (ret >= 0) { 2157e113d792SMark Brown if (rdev->desc->ops->list_voltage) 2158e113d792SMark Brown best_val = rdev->desc->ops->list_voltage(rdev, 2159e113d792SMark Brown selector); 2160e113d792SMark Brown else 2161e113d792SMark Brown best_val = _regulator_get_voltage(rdev); 2162e113d792SMark Brown } 2163e113d792SMark Brown 2164e8eef82bSMark Brown } else if (rdev->desc->ops->set_voltage_sel) { 21659152c36aSAxel Lin if (rdev->desc->ops->map_voltage) { 2166e843fc46SMark Brown ret = rdev->desc->ops->map_voltage(rdev, min_uV, 2167e843fc46SMark Brown max_uV); 21689152c36aSAxel Lin } else { 21699152c36aSAxel Lin if (rdev->desc->ops->list_voltage == 21709152c36aSAxel Lin regulator_list_voltage_linear) 21719152c36aSAxel Lin ret = regulator_map_voltage_linear(rdev, 21729152c36aSAxel Lin min_uV, max_uV); 217307351233SAxel Lin else 21749152c36aSAxel Lin ret = regulator_map_voltage_iterate(rdev, 21759152c36aSAxel Lin min_uV, max_uV); 21769152c36aSAxel Lin } 2177e843fc46SMark Brown 2178e843fc46SMark Brown if (ret >= 0) { 2179e113d792SMark Brown best_val = rdev->desc->ops->list_voltage(rdev, ret); 2180e113d792SMark Brown if (min_uV <= best_val && max_uV >= best_val) { 2181e843fc46SMark Brown selector = ret; 2182e113d792SMark Brown ret = rdev->desc->ops->set_voltage_sel(rdev, 2183e113d792SMark Brown ret); 2184e113d792SMark Brown } else { 2185e113d792SMark Brown ret = -EINVAL; 2186e113d792SMark Brown } 2187e843fc46SMark Brown } 2188e8eef82bSMark Brown } else { 2189e8eef82bSMark Brown ret = -EINVAL; 2190e8eef82bSMark Brown } 2191e8eef82bSMark Brown 2192eba41a5eSAxel Lin /* Call set_voltage_time_sel if successfully obtained old_selector */ 21935aff3a8bSMark Brown if (ret == 0 && _regulator_is_enabled(rdev) && old_selector >= 0 && 2194eba41a5eSAxel Lin rdev->desc->ops->set_voltage_time_sel) { 2195eba41a5eSAxel Lin 2196eba41a5eSAxel Lin delay = rdev->desc->ops->set_voltage_time_sel(rdev, 2197eba41a5eSAxel Lin old_selector, selector); 2198eba41a5eSAxel Lin if (delay < 0) { 2199eba41a5eSAxel Lin rdev_warn(rdev, "set_voltage_time_sel() failed: %d\n", 2200eba41a5eSAxel Lin delay); 2201eba41a5eSAxel Lin delay = 0; 2202e8eef82bSMark Brown } 220375790251SMark Brown 220477af1b26SLinus Walleij /* Insert any necessary delays */ 220577af1b26SLinus Walleij if (delay >= 1000) { 220677af1b26SLinus Walleij mdelay(delay / 1000); 220777af1b26SLinus Walleij udelay(delay % 1000); 220877af1b26SLinus Walleij } else if (delay) { 220977af1b26SLinus Walleij udelay(delay); 221077af1b26SLinus Walleij } 22118b96de31SPhilip Rakity } 221277af1b26SLinus Walleij 22132f6c797fSAxel Lin if (ret == 0 && best_val >= 0) { 22142f6c797fSAxel Lin unsigned long data = best_val; 22152f6c797fSAxel Lin 2216ded06a52SMark Brown _notifier_call_chain(rdev, REGULATOR_EVENT_VOLTAGE_CHANGE, 22172f6c797fSAxel Lin (void *)data); 22182f6c797fSAxel Lin } 2219ded06a52SMark Brown 2220eba41a5eSAxel Lin trace_regulator_set_voltage_complete(rdev_get_name(rdev), best_val); 222175790251SMark Brown 222275790251SMark Brown return ret; 222375790251SMark Brown } 222475790251SMark Brown 2225a7a1ad90SMark Brown /** 2226414c70cbSLiam Girdwood * regulator_set_voltage - set regulator output voltage 2227414c70cbSLiam Girdwood * @regulator: regulator source 2228414c70cbSLiam Girdwood * @min_uV: Minimum required voltage in uV 2229414c70cbSLiam Girdwood * @max_uV: Maximum acceptable voltage in uV 2230414c70cbSLiam Girdwood * 2231414c70cbSLiam Girdwood * Sets a voltage regulator to the desired output voltage. This can be set 2232414c70cbSLiam Girdwood * during any regulator state. IOW, regulator can be disabled or enabled. 2233414c70cbSLiam Girdwood * 2234414c70cbSLiam Girdwood * If the regulator is enabled then the voltage will change to the new value 2235414c70cbSLiam Girdwood * immediately otherwise if the regulator is disabled the regulator will 2236414c70cbSLiam Girdwood * output at the new voltage when enabled. 2237414c70cbSLiam Girdwood * 2238414c70cbSLiam Girdwood * NOTE: If the regulator is shared between several devices then the lowest 2239414c70cbSLiam Girdwood * request voltage that meets the system constraints will be used. 224069279fb9SMark Brown * Regulator system constraints must be set for this regulator before 2241414c70cbSLiam Girdwood * calling this function otherwise this call will fail. 2242414c70cbSLiam Girdwood */ 2243414c70cbSLiam Girdwood int regulator_set_voltage(struct regulator *regulator, int min_uV, int max_uV) 2244414c70cbSLiam Girdwood { 2245414c70cbSLiam Girdwood struct regulator_dev *rdev = regulator->rdev; 224695a3c23aSMark Brown int ret = 0; 2247414c70cbSLiam Girdwood 2248414c70cbSLiam Girdwood mutex_lock(&rdev->mutex); 2249414c70cbSLiam Girdwood 225095a3c23aSMark Brown /* If we're setting the same range as last time the change 225195a3c23aSMark Brown * should be a noop (some cpufreq implementations use the same 225295a3c23aSMark Brown * voltage for multiple frequencies, for example). 225395a3c23aSMark Brown */ 225495a3c23aSMark Brown if (regulator->min_uV == min_uV && regulator->max_uV == max_uV) 225595a3c23aSMark Brown goto out; 225695a3c23aSMark Brown 2257414c70cbSLiam Girdwood /* sanity check */ 2258e8eef82bSMark Brown if (!rdev->desc->ops->set_voltage && 2259e8eef82bSMark Brown !rdev->desc->ops->set_voltage_sel) { 2260414c70cbSLiam Girdwood ret = -EINVAL; 2261414c70cbSLiam Girdwood goto out; 2262414c70cbSLiam Girdwood } 2263414c70cbSLiam Girdwood 2264414c70cbSLiam Girdwood /* constraints check */ 2265414c70cbSLiam Girdwood ret = regulator_check_voltage(rdev, &min_uV, &max_uV); 2266414c70cbSLiam Girdwood if (ret < 0) 2267414c70cbSLiam Girdwood goto out; 2268414c70cbSLiam Girdwood regulator->min_uV = min_uV; 2269414c70cbSLiam Girdwood regulator->max_uV = max_uV; 22703a93f2a9SMark Brown 227105fda3b1SThomas Petazzoni ret = regulator_check_consumers(rdev, &min_uV, &max_uV); 227205fda3b1SThomas Petazzoni if (ret < 0) 227305fda3b1SThomas Petazzoni goto out; 227405fda3b1SThomas Petazzoni 227575790251SMark Brown ret = _regulator_do_set_voltage(rdev, min_uV, max_uV); 227602fa3ec0SMark Brown 2277414c70cbSLiam Girdwood out: 2278414c70cbSLiam Girdwood mutex_unlock(&rdev->mutex); 2279414c70cbSLiam Girdwood return ret; 2280414c70cbSLiam Girdwood } 2281414c70cbSLiam Girdwood EXPORT_SYMBOL_GPL(regulator_set_voltage); 2282414c70cbSLiam Girdwood 2283606a2562SMark Brown /** 228488cd222bSLinus Walleij * regulator_set_voltage_time - get raise/fall time 228588cd222bSLinus Walleij * @regulator: regulator source 228688cd222bSLinus Walleij * @old_uV: starting voltage in microvolts 228788cd222bSLinus Walleij * @new_uV: target voltage in microvolts 228888cd222bSLinus Walleij * 228988cd222bSLinus Walleij * Provided with the starting and ending voltage, this function attempts to 229088cd222bSLinus Walleij * calculate the time in microseconds required to rise or fall to this new 229188cd222bSLinus Walleij * voltage. 229288cd222bSLinus Walleij */ 229388cd222bSLinus Walleij int regulator_set_voltage_time(struct regulator *regulator, 229488cd222bSLinus Walleij int old_uV, int new_uV) 229588cd222bSLinus Walleij { 229688cd222bSLinus Walleij struct regulator_dev *rdev = regulator->rdev; 229788cd222bSLinus Walleij struct regulator_ops *ops = rdev->desc->ops; 229888cd222bSLinus Walleij int old_sel = -1; 229988cd222bSLinus Walleij int new_sel = -1; 230088cd222bSLinus Walleij int voltage; 230188cd222bSLinus Walleij int i; 230288cd222bSLinus Walleij 230388cd222bSLinus Walleij /* Currently requires operations to do this */ 230488cd222bSLinus Walleij if (!ops->list_voltage || !ops->set_voltage_time_sel 230588cd222bSLinus Walleij || !rdev->desc->n_voltages) 230688cd222bSLinus Walleij return -EINVAL; 230788cd222bSLinus Walleij 230888cd222bSLinus Walleij for (i = 0; i < rdev->desc->n_voltages; i++) { 230988cd222bSLinus Walleij /* We only look for exact voltage matches here */ 231088cd222bSLinus Walleij voltage = regulator_list_voltage(regulator, i); 231188cd222bSLinus Walleij if (voltage < 0) 231288cd222bSLinus Walleij return -EINVAL; 231388cd222bSLinus Walleij if (voltage == 0) 231488cd222bSLinus Walleij continue; 231588cd222bSLinus Walleij if (voltage == old_uV) 231688cd222bSLinus Walleij old_sel = i; 231788cd222bSLinus Walleij if (voltage == new_uV) 231888cd222bSLinus Walleij new_sel = i; 231988cd222bSLinus Walleij } 232088cd222bSLinus Walleij 232188cd222bSLinus Walleij if (old_sel < 0 || new_sel < 0) 232288cd222bSLinus Walleij return -EINVAL; 232388cd222bSLinus Walleij 232488cd222bSLinus Walleij return ops->set_voltage_time_sel(rdev, old_sel, new_sel); 232588cd222bSLinus Walleij } 232688cd222bSLinus Walleij EXPORT_SYMBOL_GPL(regulator_set_voltage_time); 232788cd222bSLinus Walleij 232888cd222bSLinus Walleij /** 232998a175b6SYadwinder Singh Brar * regulator_set_voltage_time_sel - get raise/fall time 2330296c6566SRandy Dunlap * @rdev: regulator source device 233198a175b6SYadwinder Singh Brar * @old_selector: selector for starting voltage 233298a175b6SYadwinder Singh Brar * @new_selector: selector for target voltage 233398a175b6SYadwinder Singh Brar * 233498a175b6SYadwinder Singh Brar * Provided with the starting and target voltage selectors, this function 233598a175b6SYadwinder Singh Brar * returns time in microseconds required to rise or fall to this new voltage 233698a175b6SYadwinder Singh Brar * 2337f11d08c3SAxel Lin * Drivers providing ramp_delay in regulation_constraints can use this as their 2338398715abSAxel Lin * set_voltage_time_sel() operation. 233998a175b6SYadwinder Singh Brar */ 234098a175b6SYadwinder Singh Brar int regulator_set_voltage_time_sel(struct regulator_dev *rdev, 234198a175b6SYadwinder Singh Brar unsigned int old_selector, 234298a175b6SYadwinder Singh Brar unsigned int new_selector) 234398a175b6SYadwinder Singh Brar { 2344398715abSAxel Lin unsigned int ramp_delay = 0; 2345f11d08c3SAxel Lin int old_volt, new_volt; 2346398715abSAxel Lin 23476f0b2c69SYadwinder Singh Brar if (rdev->constraints->ramp_delay) 2348398715abSAxel Lin ramp_delay = rdev->constraints->ramp_delay; 2349398715abSAxel Lin else if (rdev->desc->ramp_delay) 2350398715abSAxel Lin ramp_delay = rdev->desc->ramp_delay; 2351398715abSAxel Lin 2352398715abSAxel Lin if (ramp_delay == 0) { 23536f0b2c69SYadwinder Singh Brar rdev_warn(rdev, "ramp_delay not set\n"); 2354398715abSAxel Lin return 0; 23556f0b2c69SYadwinder Singh Brar } 2356398715abSAxel Lin 2357f11d08c3SAxel Lin /* sanity check */ 2358f11d08c3SAxel Lin if (!rdev->desc->ops->list_voltage) 2359f11d08c3SAxel Lin return -EINVAL; 2360398715abSAxel Lin 2361f11d08c3SAxel Lin old_volt = rdev->desc->ops->list_voltage(rdev, old_selector); 2362f11d08c3SAxel Lin new_volt = rdev->desc->ops->list_voltage(rdev, new_selector); 2363f11d08c3SAxel Lin 2364f11d08c3SAxel Lin return DIV_ROUND_UP(abs(new_volt - old_volt), ramp_delay); 236598a175b6SYadwinder Singh Brar } 2366b19dbf71SMark Brown EXPORT_SYMBOL_GPL(regulator_set_voltage_time_sel); 236798a175b6SYadwinder Singh Brar 236898a175b6SYadwinder Singh Brar /** 2369606a2562SMark Brown * regulator_sync_voltage - re-apply last regulator output voltage 2370606a2562SMark Brown * @regulator: regulator source 2371606a2562SMark Brown * 2372606a2562SMark Brown * Re-apply the last configured voltage. This is intended to be used 2373606a2562SMark Brown * where some external control source the consumer is cooperating with 2374606a2562SMark Brown * has caused the configured voltage to change. 2375606a2562SMark Brown */ 2376606a2562SMark Brown int regulator_sync_voltage(struct regulator *regulator) 2377606a2562SMark Brown { 2378606a2562SMark Brown struct regulator_dev *rdev = regulator->rdev; 2379606a2562SMark Brown int ret, min_uV, max_uV; 2380606a2562SMark Brown 2381606a2562SMark Brown mutex_lock(&rdev->mutex); 2382606a2562SMark Brown 2383606a2562SMark Brown if (!rdev->desc->ops->set_voltage && 2384606a2562SMark Brown !rdev->desc->ops->set_voltage_sel) { 2385606a2562SMark Brown ret = -EINVAL; 2386606a2562SMark Brown goto out; 2387606a2562SMark Brown } 2388606a2562SMark Brown 2389606a2562SMark Brown /* This is only going to work if we've had a voltage configured. */ 2390606a2562SMark Brown if (!regulator->min_uV && !regulator->max_uV) { 2391606a2562SMark Brown ret = -EINVAL; 2392606a2562SMark Brown goto out; 2393606a2562SMark Brown } 2394606a2562SMark Brown 2395606a2562SMark Brown min_uV = regulator->min_uV; 2396606a2562SMark Brown max_uV = regulator->max_uV; 2397606a2562SMark Brown 2398606a2562SMark Brown /* This should be a paranoia check... */ 2399606a2562SMark Brown ret = regulator_check_voltage(rdev, &min_uV, &max_uV); 2400606a2562SMark Brown if (ret < 0) 2401606a2562SMark Brown goto out; 2402606a2562SMark Brown 2403606a2562SMark Brown ret = regulator_check_consumers(rdev, &min_uV, &max_uV); 2404606a2562SMark Brown if (ret < 0) 2405606a2562SMark Brown goto out; 2406606a2562SMark Brown 2407606a2562SMark Brown ret = _regulator_do_set_voltage(rdev, min_uV, max_uV); 2408606a2562SMark Brown 2409606a2562SMark Brown out: 2410606a2562SMark Brown mutex_unlock(&rdev->mutex); 2411606a2562SMark Brown return ret; 2412606a2562SMark Brown } 2413606a2562SMark Brown EXPORT_SYMBOL_GPL(regulator_sync_voltage); 2414606a2562SMark Brown 2415414c70cbSLiam Girdwood static int _regulator_get_voltage(struct regulator_dev *rdev) 2416414c70cbSLiam Girdwood { 2417bf5892a8SMark Brown int sel, ret; 2418476c2d83SMark Brown 2419476c2d83SMark Brown if (rdev->desc->ops->get_voltage_sel) { 2420476c2d83SMark Brown sel = rdev->desc->ops->get_voltage_sel(rdev); 2421476c2d83SMark Brown if (sel < 0) 2422476c2d83SMark Brown return sel; 2423bf5892a8SMark Brown ret = rdev->desc->ops->list_voltage(rdev, sel); 2424cb220d16SAxel Lin } else if (rdev->desc->ops->get_voltage) { 2425bf5892a8SMark Brown ret = rdev->desc->ops->get_voltage(rdev); 2426f7df20ecSMark Brown } else if (rdev->desc->ops->list_voltage) { 2427f7df20ecSMark Brown ret = rdev->desc->ops->list_voltage(rdev, 0); 2428cb220d16SAxel Lin } else { 2429414c70cbSLiam Girdwood return -EINVAL; 2430cb220d16SAxel Lin } 2431bf5892a8SMark Brown 2432cb220d16SAxel Lin if (ret < 0) 2433cb220d16SAxel Lin return ret; 2434bf5892a8SMark Brown return ret - rdev->constraints->uV_offset; 2435414c70cbSLiam Girdwood } 2436414c70cbSLiam Girdwood 2437414c70cbSLiam Girdwood /** 2438414c70cbSLiam Girdwood * regulator_get_voltage - get regulator output voltage 2439414c70cbSLiam Girdwood * @regulator: regulator source 2440414c70cbSLiam Girdwood * 2441414c70cbSLiam Girdwood * This returns the current regulator voltage in uV. 2442414c70cbSLiam Girdwood * 2443414c70cbSLiam Girdwood * NOTE: If the regulator is disabled it will return the voltage value. This 2444414c70cbSLiam Girdwood * function should not be used to determine regulator state. 2445414c70cbSLiam Girdwood */ 2446414c70cbSLiam Girdwood int regulator_get_voltage(struct regulator *regulator) 2447414c70cbSLiam Girdwood { 2448414c70cbSLiam Girdwood int ret; 2449414c70cbSLiam Girdwood 2450414c70cbSLiam Girdwood mutex_lock(®ulator->rdev->mutex); 2451414c70cbSLiam Girdwood 2452414c70cbSLiam Girdwood ret = _regulator_get_voltage(regulator->rdev); 2453414c70cbSLiam Girdwood 2454414c70cbSLiam Girdwood mutex_unlock(®ulator->rdev->mutex); 2455414c70cbSLiam Girdwood 2456414c70cbSLiam Girdwood return ret; 2457414c70cbSLiam Girdwood } 2458414c70cbSLiam Girdwood EXPORT_SYMBOL_GPL(regulator_get_voltage); 2459414c70cbSLiam Girdwood 2460414c70cbSLiam Girdwood /** 2461414c70cbSLiam Girdwood * regulator_set_current_limit - set regulator output current limit 2462414c70cbSLiam Girdwood * @regulator: regulator source 2463414c70cbSLiam Girdwood * @min_uA: Minimuum supported current in uA 2464414c70cbSLiam Girdwood * @max_uA: Maximum supported current in uA 2465414c70cbSLiam Girdwood * 2466414c70cbSLiam Girdwood * Sets current sink to the desired output current. This can be set during 2467414c70cbSLiam Girdwood * any regulator state. IOW, regulator can be disabled or enabled. 2468414c70cbSLiam Girdwood * 2469414c70cbSLiam Girdwood * If the regulator is enabled then the current will change to the new value 2470414c70cbSLiam Girdwood * immediately otherwise if the regulator is disabled the regulator will 2471414c70cbSLiam Girdwood * output at the new current when enabled. 2472414c70cbSLiam Girdwood * 2473414c70cbSLiam Girdwood * NOTE: Regulator system constraints must be set for this regulator before 2474414c70cbSLiam Girdwood * calling this function otherwise this call will fail. 2475414c70cbSLiam Girdwood */ 2476414c70cbSLiam Girdwood int regulator_set_current_limit(struct regulator *regulator, 2477414c70cbSLiam Girdwood int min_uA, int max_uA) 2478414c70cbSLiam Girdwood { 2479414c70cbSLiam Girdwood struct regulator_dev *rdev = regulator->rdev; 2480414c70cbSLiam Girdwood int ret; 2481414c70cbSLiam Girdwood 2482414c70cbSLiam Girdwood mutex_lock(&rdev->mutex); 2483414c70cbSLiam Girdwood 2484414c70cbSLiam Girdwood /* sanity check */ 2485414c70cbSLiam Girdwood if (!rdev->desc->ops->set_current_limit) { 2486414c70cbSLiam Girdwood ret = -EINVAL; 2487414c70cbSLiam Girdwood goto out; 2488414c70cbSLiam Girdwood } 2489414c70cbSLiam Girdwood 2490414c70cbSLiam Girdwood /* constraints check */ 2491414c70cbSLiam Girdwood ret = regulator_check_current_limit(rdev, &min_uA, &max_uA); 2492414c70cbSLiam Girdwood if (ret < 0) 2493414c70cbSLiam Girdwood goto out; 2494414c70cbSLiam Girdwood 2495414c70cbSLiam Girdwood ret = rdev->desc->ops->set_current_limit(rdev, min_uA, max_uA); 2496414c70cbSLiam Girdwood out: 2497414c70cbSLiam Girdwood mutex_unlock(&rdev->mutex); 2498414c70cbSLiam Girdwood return ret; 2499414c70cbSLiam Girdwood } 2500414c70cbSLiam Girdwood EXPORT_SYMBOL_GPL(regulator_set_current_limit); 2501414c70cbSLiam Girdwood 2502414c70cbSLiam Girdwood static int _regulator_get_current_limit(struct regulator_dev *rdev) 2503414c70cbSLiam Girdwood { 2504414c70cbSLiam Girdwood int ret; 2505414c70cbSLiam Girdwood 2506414c70cbSLiam Girdwood mutex_lock(&rdev->mutex); 2507414c70cbSLiam Girdwood 2508414c70cbSLiam Girdwood /* sanity check */ 2509414c70cbSLiam Girdwood if (!rdev->desc->ops->get_current_limit) { 2510414c70cbSLiam Girdwood ret = -EINVAL; 2511414c70cbSLiam Girdwood goto out; 2512414c70cbSLiam Girdwood } 2513414c70cbSLiam Girdwood 2514414c70cbSLiam Girdwood ret = rdev->desc->ops->get_current_limit(rdev); 2515414c70cbSLiam Girdwood out: 2516414c70cbSLiam Girdwood mutex_unlock(&rdev->mutex); 2517414c70cbSLiam Girdwood return ret; 2518414c70cbSLiam Girdwood } 2519414c70cbSLiam Girdwood 2520414c70cbSLiam Girdwood /** 2521414c70cbSLiam Girdwood * regulator_get_current_limit - get regulator output current 2522414c70cbSLiam Girdwood * @regulator: regulator source 2523414c70cbSLiam Girdwood * 2524414c70cbSLiam Girdwood * This returns the current supplied by the specified current sink in uA. 2525414c70cbSLiam Girdwood * 2526414c70cbSLiam Girdwood * NOTE: If the regulator is disabled it will return the current value. This 2527414c70cbSLiam Girdwood * function should not be used to determine regulator state. 2528414c70cbSLiam Girdwood */ 2529414c70cbSLiam Girdwood int regulator_get_current_limit(struct regulator *regulator) 2530414c70cbSLiam Girdwood { 2531414c70cbSLiam Girdwood return _regulator_get_current_limit(regulator->rdev); 2532414c70cbSLiam Girdwood } 2533414c70cbSLiam Girdwood EXPORT_SYMBOL_GPL(regulator_get_current_limit); 2534414c70cbSLiam Girdwood 2535414c70cbSLiam Girdwood /** 2536414c70cbSLiam Girdwood * regulator_set_mode - set regulator operating mode 2537414c70cbSLiam Girdwood * @regulator: regulator source 2538414c70cbSLiam Girdwood * @mode: operating mode - one of the REGULATOR_MODE constants 2539414c70cbSLiam Girdwood * 2540414c70cbSLiam Girdwood * Set regulator operating mode to increase regulator efficiency or improve 2541414c70cbSLiam Girdwood * regulation performance. 2542414c70cbSLiam Girdwood * 2543414c70cbSLiam Girdwood * NOTE: Regulator system constraints must be set for this regulator before 2544414c70cbSLiam Girdwood * calling this function otherwise this call will fail. 2545414c70cbSLiam Girdwood */ 2546414c70cbSLiam Girdwood int regulator_set_mode(struct regulator *regulator, unsigned int mode) 2547414c70cbSLiam Girdwood { 2548414c70cbSLiam Girdwood struct regulator_dev *rdev = regulator->rdev; 2549414c70cbSLiam Girdwood int ret; 2550500b4ac9SSundar R Iyer int regulator_curr_mode; 2551414c70cbSLiam Girdwood 2552414c70cbSLiam Girdwood mutex_lock(&rdev->mutex); 2553414c70cbSLiam Girdwood 2554414c70cbSLiam Girdwood /* sanity check */ 2555414c70cbSLiam Girdwood if (!rdev->desc->ops->set_mode) { 2556414c70cbSLiam Girdwood ret = -EINVAL; 2557414c70cbSLiam Girdwood goto out; 2558414c70cbSLiam Girdwood } 2559414c70cbSLiam Girdwood 2560500b4ac9SSundar R Iyer /* return if the same mode is requested */ 2561500b4ac9SSundar R Iyer if (rdev->desc->ops->get_mode) { 2562500b4ac9SSundar R Iyer regulator_curr_mode = rdev->desc->ops->get_mode(rdev); 2563500b4ac9SSundar R Iyer if (regulator_curr_mode == mode) { 2564500b4ac9SSundar R Iyer ret = 0; 2565500b4ac9SSundar R Iyer goto out; 2566500b4ac9SSundar R Iyer } 2567500b4ac9SSundar R Iyer } 2568500b4ac9SSundar R Iyer 2569414c70cbSLiam Girdwood /* constraints check */ 257022c51b47SAxel Lin ret = regulator_mode_constrain(rdev, &mode); 2571414c70cbSLiam Girdwood if (ret < 0) 2572414c70cbSLiam Girdwood goto out; 2573414c70cbSLiam Girdwood 2574414c70cbSLiam Girdwood ret = rdev->desc->ops->set_mode(rdev, mode); 2575414c70cbSLiam Girdwood out: 2576414c70cbSLiam Girdwood mutex_unlock(&rdev->mutex); 2577414c70cbSLiam Girdwood return ret; 2578414c70cbSLiam Girdwood } 2579414c70cbSLiam Girdwood EXPORT_SYMBOL_GPL(regulator_set_mode); 2580414c70cbSLiam Girdwood 2581414c70cbSLiam Girdwood static unsigned int _regulator_get_mode(struct regulator_dev *rdev) 2582414c70cbSLiam Girdwood { 2583414c70cbSLiam Girdwood int ret; 2584414c70cbSLiam Girdwood 2585414c70cbSLiam Girdwood mutex_lock(&rdev->mutex); 2586414c70cbSLiam Girdwood 2587414c70cbSLiam Girdwood /* sanity check */ 2588414c70cbSLiam Girdwood if (!rdev->desc->ops->get_mode) { 2589414c70cbSLiam Girdwood ret = -EINVAL; 2590414c70cbSLiam Girdwood goto out; 2591414c70cbSLiam Girdwood } 2592414c70cbSLiam Girdwood 2593414c70cbSLiam Girdwood ret = rdev->desc->ops->get_mode(rdev); 2594414c70cbSLiam Girdwood out: 2595414c70cbSLiam Girdwood mutex_unlock(&rdev->mutex); 2596414c70cbSLiam Girdwood return ret; 2597414c70cbSLiam Girdwood } 2598414c70cbSLiam Girdwood 2599414c70cbSLiam Girdwood /** 2600414c70cbSLiam Girdwood * regulator_get_mode - get regulator operating mode 2601414c70cbSLiam Girdwood * @regulator: regulator source 2602414c70cbSLiam Girdwood * 2603414c70cbSLiam Girdwood * Get the current regulator operating mode. 2604414c70cbSLiam Girdwood */ 2605414c70cbSLiam Girdwood unsigned int regulator_get_mode(struct regulator *regulator) 2606414c70cbSLiam Girdwood { 2607414c70cbSLiam Girdwood return _regulator_get_mode(regulator->rdev); 2608414c70cbSLiam Girdwood } 2609414c70cbSLiam Girdwood EXPORT_SYMBOL_GPL(regulator_get_mode); 2610414c70cbSLiam Girdwood 2611414c70cbSLiam Girdwood /** 2612414c70cbSLiam Girdwood * regulator_set_optimum_mode - set regulator optimum operating mode 2613414c70cbSLiam Girdwood * @regulator: regulator source 2614414c70cbSLiam Girdwood * @uA_load: load current 2615414c70cbSLiam Girdwood * 2616414c70cbSLiam Girdwood * Notifies the regulator core of a new device load. This is then used by 2617414c70cbSLiam Girdwood * DRMS (if enabled by constraints) to set the most efficient regulator 2618414c70cbSLiam Girdwood * operating mode for the new regulator loading. 2619414c70cbSLiam Girdwood * 2620414c70cbSLiam Girdwood * Consumer devices notify their supply regulator of the maximum power 2621414c70cbSLiam Girdwood * they will require (can be taken from device datasheet in the power 2622414c70cbSLiam Girdwood * consumption tables) when they change operational status and hence power 2623414c70cbSLiam Girdwood * state. Examples of operational state changes that can affect power 2624414c70cbSLiam Girdwood * consumption are :- 2625414c70cbSLiam Girdwood * 2626414c70cbSLiam Girdwood * o Device is opened / closed. 2627414c70cbSLiam Girdwood * o Device I/O is about to begin or has just finished. 2628414c70cbSLiam Girdwood * o Device is idling in between work. 2629414c70cbSLiam Girdwood * 2630414c70cbSLiam Girdwood * This information is also exported via sysfs to userspace. 2631414c70cbSLiam Girdwood * 2632414c70cbSLiam Girdwood * DRMS will sum the total requested load on the regulator and change 2633414c70cbSLiam Girdwood * to the most efficient operating mode if platform constraints allow. 2634414c70cbSLiam Girdwood * 2635414c70cbSLiam Girdwood * Returns the new regulator mode or error. 2636414c70cbSLiam Girdwood */ 2637414c70cbSLiam Girdwood int regulator_set_optimum_mode(struct regulator *regulator, int uA_load) 2638414c70cbSLiam Girdwood { 2639414c70cbSLiam Girdwood struct regulator_dev *rdev = regulator->rdev; 2640414c70cbSLiam Girdwood struct regulator *consumer; 2641d92d95b6SStephen Boyd int ret, output_uV, input_uV = 0, total_uA_load = 0; 2642414c70cbSLiam Girdwood unsigned int mode; 2643414c70cbSLiam Girdwood 2644d92d95b6SStephen Boyd if (rdev->supply) 2645d92d95b6SStephen Boyd input_uV = regulator_get_voltage(rdev->supply); 2646d92d95b6SStephen Boyd 2647414c70cbSLiam Girdwood mutex_lock(&rdev->mutex); 2648414c70cbSLiam Girdwood 2649a4b41483SMark Brown /* 2650a4b41483SMark Brown * first check to see if we can set modes at all, otherwise just 2651a4b41483SMark Brown * tell the consumer everything is OK. 2652a4b41483SMark Brown */ 2653414c70cbSLiam Girdwood regulator->uA_load = uA_load; 2654414c70cbSLiam Girdwood ret = regulator_check_drms(rdev); 2655a4b41483SMark Brown if (ret < 0) { 2656a4b41483SMark Brown ret = 0; 2657414c70cbSLiam Girdwood goto out; 2658a4b41483SMark Brown } 2659414c70cbSLiam Girdwood 2660414c70cbSLiam Girdwood if (!rdev->desc->ops->get_optimum_mode) 2661414c70cbSLiam Girdwood goto out; 2662414c70cbSLiam Girdwood 2663a4b41483SMark Brown /* 2664a4b41483SMark Brown * we can actually do this so any errors are indicators of 2665a4b41483SMark Brown * potential real failure. 2666a4b41483SMark Brown */ 2667a4b41483SMark Brown ret = -EINVAL; 2668a4b41483SMark Brown 2669854ccbaeSAxel Lin if (!rdev->desc->ops->set_mode) 2670854ccbaeSAxel Lin goto out; 2671854ccbaeSAxel Lin 2672414c70cbSLiam Girdwood /* get output voltage */ 26731bf5a1f8SMark Brown output_uV = _regulator_get_voltage(rdev); 2674414c70cbSLiam Girdwood if (output_uV <= 0) { 26755da84fd9SJoe Perches rdev_err(rdev, "invalid output voltage found\n"); 2676414c70cbSLiam Girdwood goto out; 2677414c70cbSLiam Girdwood } 2678414c70cbSLiam Girdwood 2679d92d95b6SStephen Boyd /* No supply? Use constraint voltage */ 26801bf5a1f8SMark Brown if (input_uV <= 0) 2681414c70cbSLiam Girdwood input_uV = rdev->constraints->input_uV; 2682414c70cbSLiam Girdwood if (input_uV <= 0) { 26835da84fd9SJoe Perches rdev_err(rdev, "invalid input voltage found\n"); 2684414c70cbSLiam Girdwood goto out; 2685414c70cbSLiam Girdwood } 2686414c70cbSLiam Girdwood 2687414c70cbSLiam Girdwood /* calc total requested load for this regulator */ 2688414c70cbSLiam Girdwood list_for_each_entry(consumer, &rdev->consumer_list, list) 2689414c70cbSLiam Girdwood total_uA_load += consumer->uA_load; 2690414c70cbSLiam Girdwood 2691414c70cbSLiam Girdwood mode = rdev->desc->ops->get_optimum_mode(rdev, 2692414c70cbSLiam Girdwood input_uV, output_uV, 2693414c70cbSLiam Girdwood total_uA_load); 26942c608234SMark Brown ret = regulator_mode_constrain(rdev, &mode); 2695e573520bSDavid Brownell if (ret < 0) { 26965da84fd9SJoe Perches rdev_err(rdev, "failed to get optimum mode @ %d uA %d -> %d uV\n", 2697414c70cbSLiam Girdwood total_uA_load, input_uV, output_uV); 2698414c70cbSLiam Girdwood goto out; 2699414c70cbSLiam Girdwood } 2700414c70cbSLiam Girdwood 2701414c70cbSLiam Girdwood ret = rdev->desc->ops->set_mode(rdev, mode); 2702e573520bSDavid Brownell if (ret < 0) { 27035da84fd9SJoe Perches rdev_err(rdev, "failed to set optimum mode %x\n", mode); 2704414c70cbSLiam Girdwood goto out; 2705414c70cbSLiam Girdwood } 2706414c70cbSLiam Girdwood ret = mode; 2707414c70cbSLiam Girdwood out: 2708414c70cbSLiam Girdwood mutex_unlock(&rdev->mutex); 2709414c70cbSLiam Girdwood return ret; 2710414c70cbSLiam Girdwood } 2711414c70cbSLiam Girdwood EXPORT_SYMBOL_GPL(regulator_set_optimum_mode); 2712414c70cbSLiam Girdwood 2713414c70cbSLiam Girdwood /** 2714df367931SMark Brown * regulator_set_bypass_regmap - Default set_bypass() using regmap 2715df367931SMark Brown * 2716df367931SMark Brown * @rdev: device to operate on. 2717df367931SMark Brown * @enable: state to set. 2718df367931SMark Brown */ 2719df367931SMark Brown int regulator_set_bypass_regmap(struct regulator_dev *rdev, bool enable) 2720df367931SMark Brown { 2721df367931SMark Brown unsigned int val; 2722df367931SMark Brown 2723df367931SMark Brown if (enable) 2724df367931SMark Brown val = rdev->desc->bypass_mask; 2725df367931SMark Brown else 2726df367931SMark Brown val = 0; 2727df367931SMark Brown 2728df367931SMark Brown return regmap_update_bits(rdev->regmap, rdev->desc->bypass_reg, 2729df367931SMark Brown rdev->desc->bypass_mask, val); 2730df367931SMark Brown } 2731df367931SMark Brown EXPORT_SYMBOL_GPL(regulator_set_bypass_regmap); 2732df367931SMark Brown 2733df367931SMark Brown /** 2734df367931SMark Brown * regulator_get_bypass_regmap - Default get_bypass() using regmap 2735df367931SMark Brown * 2736df367931SMark Brown * @rdev: device to operate on. 2737df367931SMark Brown * @enable: current state. 2738df367931SMark Brown */ 2739df367931SMark Brown int regulator_get_bypass_regmap(struct regulator_dev *rdev, bool *enable) 2740df367931SMark Brown { 2741df367931SMark Brown unsigned int val; 2742df367931SMark Brown int ret; 2743df367931SMark Brown 2744df367931SMark Brown ret = regmap_read(rdev->regmap, rdev->desc->bypass_reg, &val); 2745df367931SMark Brown if (ret != 0) 2746df367931SMark Brown return ret; 2747df367931SMark Brown 2748df367931SMark Brown *enable = val & rdev->desc->bypass_mask; 2749df367931SMark Brown 2750df367931SMark Brown return 0; 2751df367931SMark Brown } 2752df367931SMark Brown EXPORT_SYMBOL_GPL(regulator_get_bypass_regmap); 2753df367931SMark Brown 2754df367931SMark Brown /** 2755f59c8f9fSMark Brown * regulator_allow_bypass - allow the regulator to go into bypass mode 2756f59c8f9fSMark Brown * 2757f59c8f9fSMark Brown * @regulator: Regulator to configure 2758f59c8f9fSMark Brown * @allow: enable or disable bypass mode 2759f59c8f9fSMark Brown * 2760f59c8f9fSMark Brown * Allow the regulator to go into bypass mode if all other consumers 2761f59c8f9fSMark Brown * for the regulator also enable bypass mode and the machine 2762f59c8f9fSMark Brown * constraints allow this. Bypass mode means that the regulator is 2763f59c8f9fSMark Brown * simply passing the input directly to the output with no regulation. 2764f59c8f9fSMark Brown */ 2765f59c8f9fSMark Brown int regulator_allow_bypass(struct regulator *regulator, bool enable) 2766f59c8f9fSMark Brown { 2767f59c8f9fSMark Brown struct regulator_dev *rdev = regulator->rdev; 2768f59c8f9fSMark Brown int ret = 0; 2769f59c8f9fSMark Brown 2770f59c8f9fSMark Brown if (!rdev->desc->ops->set_bypass) 2771f59c8f9fSMark Brown return 0; 2772f59c8f9fSMark Brown 2773f59c8f9fSMark Brown if (rdev->constraints && 2774f59c8f9fSMark Brown !(rdev->constraints->valid_ops_mask & REGULATOR_CHANGE_BYPASS)) 2775f59c8f9fSMark Brown return 0; 2776f59c8f9fSMark Brown 2777f59c8f9fSMark Brown mutex_lock(&rdev->mutex); 2778f59c8f9fSMark Brown 2779f59c8f9fSMark Brown if (enable && !regulator->bypass) { 2780f59c8f9fSMark Brown rdev->bypass_count++; 2781f59c8f9fSMark Brown 2782f59c8f9fSMark Brown if (rdev->bypass_count == rdev->open_count) { 2783f59c8f9fSMark Brown ret = rdev->desc->ops->set_bypass(rdev, enable); 2784f59c8f9fSMark Brown if (ret != 0) 2785f59c8f9fSMark Brown rdev->bypass_count--; 2786f59c8f9fSMark Brown } 2787f59c8f9fSMark Brown 2788f59c8f9fSMark Brown } else if (!enable && regulator->bypass) { 2789f59c8f9fSMark Brown rdev->bypass_count--; 2790f59c8f9fSMark Brown 2791f59c8f9fSMark Brown if (rdev->bypass_count != rdev->open_count) { 2792f59c8f9fSMark Brown ret = rdev->desc->ops->set_bypass(rdev, enable); 2793f59c8f9fSMark Brown if (ret != 0) 2794f59c8f9fSMark Brown rdev->bypass_count++; 2795f59c8f9fSMark Brown } 2796f59c8f9fSMark Brown } 2797f59c8f9fSMark Brown 2798f59c8f9fSMark Brown if (ret == 0) 2799f59c8f9fSMark Brown regulator->bypass = enable; 2800f59c8f9fSMark Brown 2801f59c8f9fSMark Brown mutex_unlock(&rdev->mutex); 2802f59c8f9fSMark Brown 2803f59c8f9fSMark Brown return ret; 2804f59c8f9fSMark Brown } 2805f59c8f9fSMark Brown EXPORT_SYMBOL_GPL(regulator_allow_bypass); 2806f59c8f9fSMark Brown 2807f59c8f9fSMark Brown /** 2808414c70cbSLiam Girdwood * regulator_register_notifier - register regulator event notifier 2809414c70cbSLiam Girdwood * @regulator: regulator source 281069279fb9SMark Brown * @nb: notifier block 2811414c70cbSLiam Girdwood * 2812414c70cbSLiam Girdwood * Register notifier block to receive regulator events. 2813414c70cbSLiam Girdwood */ 2814414c70cbSLiam Girdwood int regulator_register_notifier(struct regulator *regulator, 2815414c70cbSLiam Girdwood struct notifier_block *nb) 2816414c70cbSLiam Girdwood { 2817414c70cbSLiam Girdwood return blocking_notifier_chain_register(®ulator->rdev->notifier, 2818414c70cbSLiam Girdwood nb); 2819414c70cbSLiam Girdwood } 2820414c70cbSLiam Girdwood EXPORT_SYMBOL_GPL(regulator_register_notifier); 2821414c70cbSLiam Girdwood 2822414c70cbSLiam Girdwood /** 2823414c70cbSLiam Girdwood * regulator_unregister_notifier - unregister regulator event notifier 2824414c70cbSLiam Girdwood * @regulator: regulator source 282569279fb9SMark Brown * @nb: notifier block 2826414c70cbSLiam Girdwood * 2827414c70cbSLiam Girdwood * Unregister regulator event notifier block. 2828414c70cbSLiam Girdwood */ 2829414c70cbSLiam Girdwood int regulator_unregister_notifier(struct regulator *regulator, 2830414c70cbSLiam Girdwood struct notifier_block *nb) 2831414c70cbSLiam Girdwood { 2832414c70cbSLiam Girdwood return blocking_notifier_chain_unregister(®ulator->rdev->notifier, 2833414c70cbSLiam Girdwood nb); 2834414c70cbSLiam Girdwood } 2835414c70cbSLiam Girdwood EXPORT_SYMBOL_GPL(regulator_unregister_notifier); 2836414c70cbSLiam Girdwood 2837b136fb44SJonathan Cameron /* notify regulator consumers and downstream regulator consumers. 2838b136fb44SJonathan Cameron * Note mutex must be held by caller. 2839b136fb44SJonathan Cameron */ 2840414c70cbSLiam Girdwood static void _notifier_call_chain(struct regulator_dev *rdev, 2841414c70cbSLiam Girdwood unsigned long event, void *data) 2842414c70cbSLiam Girdwood { 2843414c70cbSLiam Girdwood /* call rdev chain first */ 2844d8493d21SMark Brown blocking_notifier_call_chain(&rdev->notifier, event, data); 2845414c70cbSLiam Girdwood } 2846414c70cbSLiam Girdwood 2847414c70cbSLiam Girdwood /** 2848414c70cbSLiam Girdwood * regulator_bulk_get - get multiple regulator consumers 2849414c70cbSLiam Girdwood * 2850414c70cbSLiam Girdwood * @dev: Device to supply 2851414c70cbSLiam Girdwood * @num_consumers: Number of consumers to register 2852414c70cbSLiam Girdwood * @consumers: Configuration of consumers; clients are stored here. 2853414c70cbSLiam Girdwood * 2854414c70cbSLiam Girdwood * @return 0 on success, an errno on failure. 2855414c70cbSLiam Girdwood * 2856414c70cbSLiam Girdwood * This helper function allows drivers to get several regulator 2857414c70cbSLiam Girdwood * consumers in one operation. If any of the regulators cannot be 2858414c70cbSLiam Girdwood * acquired then any regulators that were allocated will be freed 2859414c70cbSLiam Girdwood * before returning to the caller. 2860414c70cbSLiam Girdwood */ 2861414c70cbSLiam Girdwood int regulator_bulk_get(struct device *dev, int num_consumers, 2862414c70cbSLiam Girdwood struct regulator_bulk_data *consumers) 2863414c70cbSLiam Girdwood { 2864414c70cbSLiam Girdwood int i; 2865414c70cbSLiam Girdwood int ret; 2866414c70cbSLiam Girdwood 2867414c70cbSLiam Girdwood for (i = 0; i < num_consumers; i++) 2868414c70cbSLiam Girdwood consumers[i].consumer = NULL; 2869414c70cbSLiam Girdwood 2870414c70cbSLiam Girdwood for (i = 0; i < num_consumers; i++) { 2871414c70cbSLiam Girdwood consumers[i].consumer = regulator_get(dev, 2872414c70cbSLiam Girdwood consumers[i].supply); 2873414c70cbSLiam Girdwood if (IS_ERR(consumers[i].consumer)) { 2874414c70cbSLiam Girdwood ret = PTR_ERR(consumers[i].consumer); 28755b307627SMark Brown dev_err(dev, "Failed to get supply '%s': %d\n", 28765b307627SMark Brown consumers[i].supply, ret); 2877414c70cbSLiam Girdwood consumers[i].consumer = NULL; 2878414c70cbSLiam Girdwood goto err; 2879414c70cbSLiam Girdwood } 2880414c70cbSLiam Girdwood } 2881414c70cbSLiam Girdwood 2882414c70cbSLiam Girdwood return 0; 2883414c70cbSLiam Girdwood 2884414c70cbSLiam Girdwood err: 2885b29c7690SAxel Lin while (--i >= 0) 2886414c70cbSLiam Girdwood regulator_put(consumers[i].consumer); 2887414c70cbSLiam Girdwood 2888414c70cbSLiam Girdwood return ret; 2889414c70cbSLiam Girdwood } 2890414c70cbSLiam Girdwood EXPORT_SYMBOL_GPL(regulator_bulk_get); 2891414c70cbSLiam Girdwood 2892e6e74030SMark Brown /** 2893e6e74030SMark Brown * devm_regulator_bulk_get - managed get multiple regulator consumers 2894e6e74030SMark Brown * 2895e6e74030SMark Brown * @dev: Device to supply 2896e6e74030SMark Brown * @num_consumers: Number of consumers to register 2897e6e74030SMark Brown * @consumers: Configuration of consumers; clients are stored here. 2898e6e74030SMark Brown * 2899e6e74030SMark Brown * @return 0 on success, an errno on failure. 2900e6e74030SMark Brown * 2901e6e74030SMark Brown * This helper function allows drivers to get several regulator 2902e6e74030SMark Brown * consumers in one operation with management, the regulators will 2903e6e74030SMark Brown * automatically be freed when the device is unbound. If any of the 2904e6e74030SMark Brown * regulators cannot be acquired then any regulators that were 2905e6e74030SMark Brown * allocated will be freed before returning to the caller. 2906e6e74030SMark Brown */ 2907e6e74030SMark Brown int devm_regulator_bulk_get(struct device *dev, int num_consumers, 2908e6e74030SMark Brown struct regulator_bulk_data *consumers) 2909e6e74030SMark Brown { 2910e6e74030SMark Brown int i; 2911e6e74030SMark Brown int ret; 2912e6e74030SMark Brown 2913e6e74030SMark Brown for (i = 0; i < num_consumers; i++) 2914e6e74030SMark Brown consumers[i].consumer = NULL; 2915e6e74030SMark Brown 2916e6e74030SMark Brown for (i = 0; i < num_consumers; i++) { 2917e6e74030SMark Brown consumers[i].consumer = devm_regulator_get(dev, 2918e6e74030SMark Brown consumers[i].supply); 2919e6e74030SMark Brown if (IS_ERR(consumers[i].consumer)) { 2920e6e74030SMark Brown ret = PTR_ERR(consumers[i].consumer); 2921e6e74030SMark Brown dev_err(dev, "Failed to get supply '%s': %d\n", 2922e6e74030SMark Brown consumers[i].supply, ret); 2923e6e74030SMark Brown consumers[i].consumer = NULL; 2924e6e74030SMark Brown goto err; 2925e6e74030SMark Brown } 2926e6e74030SMark Brown } 2927e6e74030SMark Brown 2928e6e74030SMark Brown return 0; 2929e6e74030SMark Brown 2930e6e74030SMark Brown err: 2931e6e74030SMark Brown for (i = 0; i < num_consumers && consumers[i].consumer; i++) 2932e6e74030SMark Brown devm_regulator_put(consumers[i].consumer); 2933e6e74030SMark Brown 2934e6e74030SMark Brown return ret; 2935e6e74030SMark Brown } 2936e6e74030SMark Brown EXPORT_SYMBOL_GPL(devm_regulator_bulk_get); 2937e6e74030SMark Brown 2938f21e0e81SMark Brown static void regulator_bulk_enable_async(void *data, async_cookie_t cookie) 2939f21e0e81SMark Brown { 2940f21e0e81SMark Brown struct regulator_bulk_data *bulk = data; 2941f21e0e81SMark Brown 2942f21e0e81SMark Brown bulk->ret = regulator_enable(bulk->consumer); 2943f21e0e81SMark Brown } 2944f21e0e81SMark Brown 2945414c70cbSLiam Girdwood /** 2946414c70cbSLiam Girdwood * regulator_bulk_enable - enable multiple regulator consumers 2947414c70cbSLiam Girdwood * 2948414c70cbSLiam Girdwood * @num_consumers: Number of consumers 2949414c70cbSLiam Girdwood * @consumers: Consumer data; clients are stored here. 2950414c70cbSLiam Girdwood * @return 0 on success, an errno on failure 2951414c70cbSLiam Girdwood * 2952414c70cbSLiam Girdwood * This convenience API allows consumers to enable multiple regulator 2953414c70cbSLiam Girdwood * clients in a single API call. If any consumers cannot be enabled 2954414c70cbSLiam Girdwood * then any others that were enabled will be disabled again prior to 2955414c70cbSLiam Girdwood * return. 2956414c70cbSLiam Girdwood */ 2957414c70cbSLiam Girdwood int regulator_bulk_enable(int num_consumers, 2958414c70cbSLiam Girdwood struct regulator_bulk_data *consumers) 2959414c70cbSLiam Girdwood { 29602955b47dSDan Williams ASYNC_DOMAIN_EXCLUSIVE(async_domain); 2961414c70cbSLiam Girdwood int i; 2962f21e0e81SMark Brown int ret = 0; 2963414c70cbSLiam Girdwood 29646492bc1bSMark Brown for (i = 0; i < num_consumers; i++) { 29656492bc1bSMark Brown if (consumers[i].consumer->always_on) 29666492bc1bSMark Brown consumers[i].ret = 0; 29676492bc1bSMark Brown else 2968f21e0e81SMark Brown async_schedule_domain(regulator_bulk_enable_async, 2969f21e0e81SMark Brown &consumers[i], &async_domain); 29706492bc1bSMark Brown } 2971f21e0e81SMark Brown 2972f21e0e81SMark Brown async_synchronize_full_domain(&async_domain); 2973f21e0e81SMark Brown 2974f21e0e81SMark Brown /* If any consumer failed we need to unwind any that succeeded */ 2975414c70cbSLiam Girdwood for (i = 0; i < num_consumers; i++) { 2976f21e0e81SMark Brown if (consumers[i].ret != 0) { 2977f21e0e81SMark Brown ret = consumers[i].ret; 2978414c70cbSLiam Girdwood goto err; 2979414c70cbSLiam Girdwood } 2980f21e0e81SMark Brown } 2981414c70cbSLiam Girdwood 2982414c70cbSLiam Girdwood return 0; 2983414c70cbSLiam Girdwood 2984414c70cbSLiam Girdwood err: 2985b29c7690SAxel Lin pr_err("Failed to enable %s: %d\n", consumers[i].supply, ret); 2986b29c7690SAxel Lin while (--i >= 0) 2987414c70cbSLiam Girdwood regulator_disable(consumers[i].consumer); 2988414c70cbSLiam Girdwood 2989414c70cbSLiam Girdwood return ret; 2990414c70cbSLiam Girdwood } 2991414c70cbSLiam Girdwood EXPORT_SYMBOL_GPL(regulator_bulk_enable); 2992414c70cbSLiam Girdwood 2993414c70cbSLiam Girdwood /** 2994414c70cbSLiam Girdwood * regulator_bulk_disable - disable multiple regulator consumers 2995414c70cbSLiam Girdwood * 2996414c70cbSLiam Girdwood * @num_consumers: Number of consumers 2997414c70cbSLiam Girdwood * @consumers: Consumer data; clients are stored here. 2998414c70cbSLiam Girdwood * @return 0 on success, an errno on failure 2999414c70cbSLiam Girdwood * 3000414c70cbSLiam Girdwood * This convenience API allows consumers to disable multiple regulator 300149e22632SSylwester Nawrocki * clients in a single API call. If any consumers cannot be disabled 300249e22632SSylwester Nawrocki * then any others that were disabled will be enabled again prior to 3003414c70cbSLiam Girdwood * return. 3004414c70cbSLiam Girdwood */ 3005414c70cbSLiam Girdwood int regulator_bulk_disable(int num_consumers, 3006414c70cbSLiam Girdwood struct regulator_bulk_data *consumers) 3007414c70cbSLiam Girdwood { 3008414c70cbSLiam Girdwood int i; 300901e86f49SMark Brown int ret, r; 3010414c70cbSLiam Girdwood 301149e22632SSylwester Nawrocki for (i = num_consumers - 1; i >= 0; --i) { 3012414c70cbSLiam Girdwood ret = regulator_disable(consumers[i].consumer); 3013414c70cbSLiam Girdwood if (ret != 0) 3014414c70cbSLiam Girdwood goto err; 3015414c70cbSLiam Girdwood } 3016414c70cbSLiam Girdwood 3017414c70cbSLiam Girdwood return 0; 3018414c70cbSLiam Girdwood 3019414c70cbSLiam Girdwood err: 30205da84fd9SJoe Perches pr_err("Failed to disable %s: %d\n", consumers[i].supply, ret); 302101e86f49SMark Brown for (++i; i < num_consumers; ++i) { 302201e86f49SMark Brown r = regulator_enable(consumers[i].consumer); 302301e86f49SMark Brown if (r != 0) 302401e86f49SMark Brown pr_err("Failed to reename %s: %d\n", 302501e86f49SMark Brown consumers[i].supply, r); 302601e86f49SMark Brown } 3027414c70cbSLiam Girdwood 3028414c70cbSLiam Girdwood return ret; 3029414c70cbSLiam Girdwood } 3030414c70cbSLiam Girdwood EXPORT_SYMBOL_GPL(regulator_bulk_disable); 3031414c70cbSLiam Girdwood 3032414c70cbSLiam Girdwood /** 3033e1de2f42SDonggeun Kim * regulator_bulk_force_disable - force disable multiple regulator consumers 3034e1de2f42SDonggeun Kim * 3035e1de2f42SDonggeun Kim * @num_consumers: Number of consumers 3036e1de2f42SDonggeun Kim * @consumers: Consumer data; clients are stored here. 3037e1de2f42SDonggeun Kim * @return 0 on success, an errno on failure 3038e1de2f42SDonggeun Kim * 3039e1de2f42SDonggeun Kim * This convenience API allows consumers to forcibly disable multiple regulator 3040e1de2f42SDonggeun Kim * clients in a single API call. 3041e1de2f42SDonggeun Kim * NOTE: This should be used for situations when device damage will 3042e1de2f42SDonggeun Kim * likely occur if the regulators are not disabled (e.g. over temp). 3043e1de2f42SDonggeun Kim * Although regulator_force_disable function call for some consumers can 3044e1de2f42SDonggeun Kim * return error numbers, the function is called for all consumers. 3045e1de2f42SDonggeun Kim */ 3046e1de2f42SDonggeun Kim int regulator_bulk_force_disable(int num_consumers, 3047e1de2f42SDonggeun Kim struct regulator_bulk_data *consumers) 3048e1de2f42SDonggeun Kim { 3049e1de2f42SDonggeun Kim int i; 3050e1de2f42SDonggeun Kim int ret; 3051e1de2f42SDonggeun Kim 3052e1de2f42SDonggeun Kim for (i = 0; i < num_consumers; i++) 3053e1de2f42SDonggeun Kim consumers[i].ret = 3054e1de2f42SDonggeun Kim regulator_force_disable(consumers[i].consumer); 3055e1de2f42SDonggeun Kim 3056e1de2f42SDonggeun Kim for (i = 0; i < num_consumers; i++) { 3057e1de2f42SDonggeun Kim if (consumers[i].ret != 0) { 3058e1de2f42SDonggeun Kim ret = consumers[i].ret; 3059e1de2f42SDonggeun Kim goto out; 3060e1de2f42SDonggeun Kim } 3061e1de2f42SDonggeun Kim } 3062e1de2f42SDonggeun Kim 3063e1de2f42SDonggeun Kim return 0; 3064e1de2f42SDonggeun Kim out: 3065e1de2f42SDonggeun Kim return ret; 3066e1de2f42SDonggeun Kim } 3067e1de2f42SDonggeun Kim EXPORT_SYMBOL_GPL(regulator_bulk_force_disable); 3068e1de2f42SDonggeun Kim 3069e1de2f42SDonggeun Kim /** 3070414c70cbSLiam Girdwood * regulator_bulk_free - free multiple regulator consumers 3071414c70cbSLiam Girdwood * 3072414c70cbSLiam Girdwood * @num_consumers: Number of consumers 3073414c70cbSLiam Girdwood * @consumers: Consumer data; clients are stored here. 3074414c70cbSLiam Girdwood * 3075414c70cbSLiam Girdwood * This convenience API allows consumers to free multiple regulator 3076414c70cbSLiam Girdwood * clients in a single API call. 3077414c70cbSLiam Girdwood */ 3078414c70cbSLiam Girdwood void regulator_bulk_free(int num_consumers, 3079414c70cbSLiam Girdwood struct regulator_bulk_data *consumers) 3080414c70cbSLiam Girdwood { 3081414c70cbSLiam Girdwood int i; 3082414c70cbSLiam Girdwood 3083414c70cbSLiam Girdwood for (i = 0; i < num_consumers; i++) { 3084414c70cbSLiam Girdwood regulator_put(consumers[i].consumer); 3085414c70cbSLiam Girdwood consumers[i].consumer = NULL; 3086414c70cbSLiam Girdwood } 3087414c70cbSLiam Girdwood } 3088414c70cbSLiam Girdwood EXPORT_SYMBOL_GPL(regulator_bulk_free); 3089414c70cbSLiam Girdwood 3090414c70cbSLiam Girdwood /** 3091414c70cbSLiam Girdwood * regulator_notifier_call_chain - call regulator event notifier 309269279fb9SMark Brown * @rdev: regulator source 3093414c70cbSLiam Girdwood * @event: notifier block 309469279fb9SMark Brown * @data: callback-specific data. 3095414c70cbSLiam Girdwood * 3096414c70cbSLiam Girdwood * Called by regulator drivers to notify clients a regulator event has 3097414c70cbSLiam Girdwood * occurred. We also notify regulator clients downstream. 3098b136fb44SJonathan Cameron * Note lock must be held by caller. 3099414c70cbSLiam Girdwood */ 3100414c70cbSLiam Girdwood int regulator_notifier_call_chain(struct regulator_dev *rdev, 3101414c70cbSLiam Girdwood unsigned long event, void *data) 3102414c70cbSLiam Girdwood { 3103414c70cbSLiam Girdwood _notifier_call_chain(rdev, event, data); 3104414c70cbSLiam Girdwood return NOTIFY_DONE; 3105414c70cbSLiam Girdwood 3106414c70cbSLiam Girdwood } 3107414c70cbSLiam Girdwood EXPORT_SYMBOL_GPL(regulator_notifier_call_chain); 3108414c70cbSLiam Girdwood 3109be721979SMark Brown /** 3110be721979SMark Brown * regulator_mode_to_status - convert a regulator mode into a status 3111be721979SMark Brown * 3112be721979SMark Brown * @mode: Mode to convert 3113be721979SMark Brown * 3114be721979SMark Brown * Convert a regulator mode into a status. 3115be721979SMark Brown */ 3116be721979SMark Brown int regulator_mode_to_status(unsigned int mode) 3117be721979SMark Brown { 3118be721979SMark Brown switch (mode) { 3119be721979SMark Brown case REGULATOR_MODE_FAST: 3120be721979SMark Brown return REGULATOR_STATUS_FAST; 3121be721979SMark Brown case REGULATOR_MODE_NORMAL: 3122be721979SMark Brown return REGULATOR_STATUS_NORMAL; 3123be721979SMark Brown case REGULATOR_MODE_IDLE: 3124be721979SMark Brown return REGULATOR_STATUS_IDLE; 312503ffcf3dSKrystian Garbaciak case REGULATOR_MODE_STANDBY: 3126be721979SMark Brown return REGULATOR_STATUS_STANDBY; 3127be721979SMark Brown default: 31281beaf762SKrystian Garbaciak return REGULATOR_STATUS_UNDEFINED; 3129be721979SMark Brown } 3130be721979SMark Brown } 3131be721979SMark Brown EXPORT_SYMBOL_GPL(regulator_mode_to_status); 3132be721979SMark Brown 31337ad68e2fSDavid Brownell /* 31347ad68e2fSDavid Brownell * To avoid cluttering sysfs (and memory) with useless state, only 31357ad68e2fSDavid Brownell * create attributes that can be meaningfully displayed. 31367ad68e2fSDavid Brownell */ 31377ad68e2fSDavid Brownell static int add_regulator_attributes(struct regulator_dev *rdev) 31387ad68e2fSDavid Brownell { 31397ad68e2fSDavid Brownell struct device *dev = &rdev->dev; 31407ad68e2fSDavid Brownell struct regulator_ops *ops = rdev->desc->ops; 31417ad68e2fSDavid Brownell int status = 0; 31427ad68e2fSDavid Brownell 31437ad68e2fSDavid Brownell /* some attributes need specific methods to be displayed */ 31444c78899bSMark Brown if ((ops->get_voltage && ops->get_voltage(rdev) >= 0) || 3145f2889e65SMark Brown (ops->get_voltage_sel && ops->get_voltage_sel(rdev) >= 0) || 3146f2889e65SMark Brown (ops->list_voltage && ops->list_voltage(rdev, 0) >= 0)) { 31477ad68e2fSDavid Brownell status = device_create_file(dev, &dev_attr_microvolts); 31487ad68e2fSDavid Brownell if (status < 0) 31497ad68e2fSDavid Brownell return status; 31507ad68e2fSDavid Brownell } 31517ad68e2fSDavid Brownell if (ops->get_current_limit) { 31527ad68e2fSDavid Brownell status = device_create_file(dev, &dev_attr_microamps); 31537ad68e2fSDavid Brownell if (status < 0) 31547ad68e2fSDavid Brownell return status; 31557ad68e2fSDavid Brownell } 31567ad68e2fSDavid Brownell if (ops->get_mode) { 31577ad68e2fSDavid Brownell status = device_create_file(dev, &dev_attr_opmode); 31587ad68e2fSDavid Brownell if (status < 0) 31597ad68e2fSDavid Brownell return status; 31607ad68e2fSDavid Brownell } 31617ad68e2fSDavid Brownell if (ops->is_enabled) { 31627ad68e2fSDavid Brownell status = device_create_file(dev, &dev_attr_state); 31637ad68e2fSDavid Brownell if (status < 0) 31647ad68e2fSDavid Brownell return status; 31657ad68e2fSDavid Brownell } 3166853116a1SDavid Brownell if (ops->get_status) { 3167853116a1SDavid Brownell status = device_create_file(dev, &dev_attr_status); 3168853116a1SDavid Brownell if (status < 0) 3169853116a1SDavid Brownell return status; 3170853116a1SDavid Brownell } 3171f59c8f9fSMark Brown if (ops->get_bypass) { 3172f59c8f9fSMark Brown status = device_create_file(dev, &dev_attr_bypass); 3173f59c8f9fSMark Brown if (status < 0) 3174f59c8f9fSMark Brown return status; 3175f59c8f9fSMark Brown } 31767ad68e2fSDavid Brownell 31777ad68e2fSDavid Brownell /* some attributes are type-specific */ 31787ad68e2fSDavid Brownell if (rdev->desc->type == REGULATOR_CURRENT) { 31797ad68e2fSDavid Brownell status = device_create_file(dev, &dev_attr_requested_microamps); 31807ad68e2fSDavid Brownell if (status < 0) 31817ad68e2fSDavid Brownell return status; 31827ad68e2fSDavid Brownell } 31837ad68e2fSDavid Brownell 31847ad68e2fSDavid Brownell /* all the other attributes exist to support constraints; 31857ad68e2fSDavid Brownell * don't show them if there are no constraints, or if the 31867ad68e2fSDavid Brownell * relevant supporting methods are missing. 31877ad68e2fSDavid Brownell */ 31887ad68e2fSDavid Brownell if (!rdev->constraints) 31897ad68e2fSDavid Brownell return status; 31907ad68e2fSDavid Brownell 31917ad68e2fSDavid Brownell /* constraints need specific supporting methods */ 3192e8eef82bSMark Brown if (ops->set_voltage || ops->set_voltage_sel) { 31937ad68e2fSDavid Brownell status = device_create_file(dev, &dev_attr_min_microvolts); 31947ad68e2fSDavid Brownell if (status < 0) 31957ad68e2fSDavid Brownell return status; 31967ad68e2fSDavid Brownell status = device_create_file(dev, &dev_attr_max_microvolts); 31977ad68e2fSDavid Brownell if (status < 0) 31987ad68e2fSDavid Brownell return status; 31997ad68e2fSDavid Brownell } 32007ad68e2fSDavid Brownell if (ops->set_current_limit) { 32017ad68e2fSDavid Brownell status = device_create_file(dev, &dev_attr_min_microamps); 32027ad68e2fSDavid Brownell if (status < 0) 32037ad68e2fSDavid Brownell return status; 32047ad68e2fSDavid Brownell status = device_create_file(dev, &dev_attr_max_microamps); 32057ad68e2fSDavid Brownell if (status < 0) 32067ad68e2fSDavid Brownell return status; 32077ad68e2fSDavid Brownell } 32087ad68e2fSDavid Brownell 32097ad68e2fSDavid Brownell status = device_create_file(dev, &dev_attr_suspend_standby_state); 32107ad68e2fSDavid Brownell if (status < 0) 32117ad68e2fSDavid Brownell return status; 32127ad68e2fSDavid Brownell status = device_create_file(dev, &dev_attr_suspend_mem_state); 32137ad68e2fSDavid Brownell if (status < 0) 32147ad68e2fSDavid Brownell return status; 32157ad68e2fSDavid Brownell status = device_create_file(dev, &dev_attr_suspend_disk_state); 32167ad68e2fSDavid Brownell if (status < 0) 32177ad68e2fSDavid Brownell return status; 32187ad68e2fSDavid Brownell 32197ad68e2fSDavid Brownell if (ops->set_suspend_voltage) { 32207ad68e2fSDavid Brownell status = device_create_file(dev, 32217ad68e2fSDavid Brownell &dev_attr_suspend_standby_microvolts); 32227ad68e2fSDavid Brownell if (status < 0) 32237ad68e2fSDavid Brownell return status; 32247ad68e2fSDavid Brownell status = device_create_file(dev, 32257ad68e2fSDavid Brownell &dev_attr_suspend_mem_microvolts); 32267ad68e2fSDavid Brownell if (status < 0) 32277ad68e2fSDavid Brownell return status; 32287ad68e2fSDavid Brownell status = device_create_file(dev, 32297ad68e2fSDavid Brownell &dev_attr_suspend_disk_microvolts); 32307ad68e2fSDavid Brownell if (status < 0) 32317ad68e2fSDavid Brownell return status; 32327ad68e2fSDavid Brownell } 32337ad68e2fSDavid Brownell 32347ad68e2fSDavid Brownell if (ops->set_suspend_mode) { 32357ad68e2fSDavid Brownell status = device_create_file(dev, 32367ad68e2fSDavid Brownell &dev_attr_suspend_standby_mode); 32377ad68e2fSDavid Brownell if (status < 0) 32387ad68e2fSDavid Brownell return status; 32397ad68e2fSDavid Brownell status = device_create_file(dev, 32407ad68e2fSDavid Brownell &dev_attr_suspend_mem_mode); 32417ad68e2fSDavid Brownell if (status < 0) 32427ad68e2fSDavid Brownell return status; 32437ad68e2fSDavid Brownell status = device_create_file(dev, 32447ad68e2fSDavid Brownell &dev_attr_suspend_disk_mode); 32457ad68e2fSDavid Brownell if (status < 0) 32467ad68e2fSDavid Brownell return status; 32477ad68e2fSDavid Brownell } 32487ad68e2fSDavid Brownell 32497ad68e2fSDavid Brownell return status; 32507ad68e2fSDavid Brownell } 32517ad68e2fSDavid Brownell 32521130e5b3SMark Brown static void rdev_init_debugfs(struct regulator_dev *rdev) 32531130e5b3SMark Brown { 32541130e5b3SMark Brown rdev->debugfs = debugfs_create_dir(rdev_get_name(rdev), debugfs_root); 325524751434SStephen Boyd if (!rdev->debugfs) { 32561130e5b3SMark Brown rdev_warn(rdev, "Failed to create debugfs directory\n"); 32571130e5b3SMark Brown return; 32581130e5b3SMark Brown } 32591130e5b3SMark Brown 32601130e5b3SMark Brown debugfs_create_u32("use_count", 0444, rdev->debugfs, 32611130e5b3SMark Brown &rdev->use_count); 32621130e5b3SMark Brown debugfs_create_u32("open_count", 0444, rdev->debugfs, 32631130e5b3SMark Brown &rdev->open_count); 3264f59c8f9fSMark Brown debugfs_create_u32("bypass_count", 0444, rdev->debugfs, 3265f59c8f9fSMark Brown &rdev->bypass_count); 32661130e5b3SMark Brown } 32671130e5b3SMark Brown 3268414c70cbSLiam Girdwood /** 3269414c70cbSLiam Girdwood * regulator_register - register regulator 327069279fb9SMark Brown * @regulator_desc: regulator to register 3271c172708dSMark Brown * @config: runtime configuration for regulator 3272414c70cbSLiam Girdwood * 3273414c70cbSLiam Girdwood * Called by regulator drivers to register a regulator. 3274414c70cbSLiam Girdwood * Returns 0 on success. 3275414c70cbSLiam Girdwood */ 327665f26846SMark Brown struct regulator_dev * 327765f26846SMark Brown regulator_register(const struct regulator_desc *regulator_desc, 3278c172708dSMark Brown const struct regulator_config *config) 3279414c70cbSLiam Girdwood { 32809a8f5e07SMark Brown const struct regulation_constraints *constraints = NULL; 3281c172708dSMark Brown const struct regulator_init_data *init_data; 3282414c70cbSLiam Girdwood static atomic_t regulator_no = ATOMIC_INIT(0); 3283414c70cbSLiam Girdwood struct regulator_dev *rdev; 328432c8fad4SMark Brown struct device *dev; 3285a5766f11SLiam Girdwood int ret, i; 328669511a45SRajendra Nayak const char *supply = NULL; 3287414c70cbSLiam Girdwood 3288c172708dSMark Brown if (regulator_desc == NULL || config == NULL) 3289414c70cbSLiam Girdwood return ERR_PTR(-EINVAL); 3290414c70cbSLiam Girdwood 329132c8fad4SMark Brown dev = config->dev; 3292dcf70112SMark Brown WARN_ON(!dev); 329332c8fad4SMark Brown 3294414c70cbSLiam Girdwood if (regulator_desc->name == NULL || regulator_desc->ops == NULL) 3295414c70cbSLiam Girdwood return ERR_PTR(-EINVAL); 3296414c70cbSLiam Girdwood 3297cd78dfc6SDiego Liziero if (regulator_desc->type != REGULATOR_VOLTAGE && 3298cd78dfc6SDiego Liziero regulator_desc->type != REGULATOR_CURRENT) 3299414c70cbSLiam Girdwood return ERR_PTR(-EINVAL); 3300414c70cbSLiam Girdwood 3301476c2d83SMark Brown /* Only one of each should be implemented */ 3302476c2d83SMark Brown WARN_ON(regulator_desc->ops->get_voltage && 3303476c2d83SMark Brown regulator_desc->ops->get_voltage_sel); 3304e8eef82bSMark Brown WARN_ON(regulator_desc->ops->set_voltage && 3305e8eef82bSMark Brown regulator_desc->ops->set_voltage_sel); 3306476c2d83SMark Brown 3307476c2d83SMark Brown /* If we're using selectors we must implement list_voltage. */ 3308476c2d83SMark Brown if (regulator_desc->ops->get_voltage_sel && 3309476c2d83SMark Brown !regulator_desc->ops->list_voltage) { 3310476c2d83SMark Brown return ERR_PTR(-EINVAL); 3311476c2d83SMark Brown } 3312e8eef82bSMark Brown if (regulator_desc->ops->set_voltage_sel && 3313e8eef82bSMark Brown !regulator_desc->ops->list_voltage) { 3314e8eef82bSMark Brown return ERR_PTR(-EINVAL); 3315e8eef82bSMark Brown } 3316476c2d83SMark Brown 3317c172708dSMark Brown init_data = config->init_data; 3318c172708dSMark Brown 3319414c70cbSLiam Girdwood rdev = kzalloc(sizeof(struct regulator_dev), GFP_KERNEL); 3320414c70cbSLiam Girdwood if (rdev == NULL) 3321414c70cbSLiam Girdwood return ERR_PTR(-ENOMEM); 3322414c70cbSLiam Girdwood 3323414c70cbSLiam Girdwood mutex_lock(®ulator_list_mutex); 3324414c70cbSLiam Girdwood 3325414c70cbSLiam Girdwood mutex_init(&rdev->mutex); 3326c172708dSMark Brown rdev->reg_data = config->driver_data; 3327414c70cbSLiam Girdwood rdev->owner = regulator_desc->owner; 3328414c70cbSLiam Girdwood rdev->desc = regulator_desc; 33293a4b0a07SMark Brown if (config->regmap) 333065b19ce6SMark Brown rdev->regmap = config->regmap; 333152b84dacSAnilKumar Ch else if (dev_get_regmap(dev, NULL)) 33323a4b0a07SMark Brown rdev->regmap = dev_get_regmap(dev, NULL); 333352b84dacSAnilKumar Ch else if (dev->parent) 333452b84dacSAnilKumar Ch rdev->regmap = dev_get_regmap(dev->parent, NULL); 3335414c70cbSLiam Girdwood INIT_LIST_HEAD(&rdev->consumer_list); 3336414c70cbSLiam Girdwood INIT_LIST_HEAD(&rdev->list); 3337414c70cbSLiam Girdwood BLOCKING_INIT_NOTIFIER_HEAD(&rdev->notifier); 3338da07ecd9SMark Brown INIT_DELAYED_WORK(&rdev->disable_work, regulator_disable_work); 3339414c70cbSLiam Girdwood 3340a5766f11SLiam Girdwood /* preform any regulator specific init */ 33419a8f5e07SMark Brown if (init_data && init_data->regulator_init) { 3342a5766f11SLiam Girdwood ret = init_data->regulator_init(rdev->reg_data); 33434fca9545SDavid Brownell if (ret < 0) 33444fca9545SDavid Brownell goto clean; 3345a5766f11SLiam Girdwood } 3346a5766f11SLiam Girdwood 3347a5766f11SLiam Girdwood /* register with sysfs */ 3348a5766f11SLiam Girdwood rdev->dev.class = ®ulator_class; 3349c172708dSMark Brown rdev->dev.of_node = config->of_node; 3350a5766f11SLiam Girdwood rdev->dev.parent = dev; 3351812460a9SKay Sievers dev_set_name(&rdev->dev, "regulator.%d", 3352812460a9SKay Sievers atomic_inc_return(®ulator_no) - 1); 3353a5766f11SLiam Girdwood ret = device_register(&rdev->dev); 3354ad7725cbSVasiliy Kulikov if (ret != 0) { 3355ad7725cbSVasiliy Kulikov put_device(&rdev->dev); 33564fca9545SDavid Brownell goto clean; 3357ad7725cbSVasiliy Kulikov } 3358a5766f11SLiam Girdwood 3359a5766f11SLiam Girdwood dev_set_drvdata(&rdev->dev, rdev); 3360a5766f11SLiam Girdwood 3361b2a1ef47SMarek Szyprowski if (config->ena_gpio && gpio_is_valid(config->ena_gpio)) { 336265f73508SMark Brown ret = gpio_request_one(config->ena_gpio, 336365f73508SMark Brown GPIOF_DIR_OUT | config->ena_gpio_flags, 336465f73508SMark Brown rdev_get_name(rdev)); 336565f73508SMark Brown if (ret != 0) { 336665f73508SMark Brown rdev_err(rdev, "Failed to request enable GPIO%d: %d\n", 336765f73508SMark Brown config->ena_gpio, ret); 3368b2da55d9SAndrew Lunn goto wash; 336965f73508SMark Brown } 337065f73508SMark Brown 337165f73508SMark Brown rdev->ena_gpio = config->ena_gpio; 337265f73508SMark Brown rdev->ena_gpio_invert = config->ena_gpio_invert; 337365f73508SMark Brown 337465f73508SMark Brown if (config->ena_gpio_flags & GPIOF_OUT_INIT_HIGH) 337565f73508SMark Brown rdev->ena_gpio_state = 1; 337665f73508SMark Brown 337765f73508SMark Brown if (rdev->ena_gpio_invert) 337865f73508SMark Brown rdev->ena_gpio_state = !rdev->ena_gpio_state; 337965f73508SMark Brown } 338065f73508SMark Brown 338174f544c1SMike Rapoport /* set regulator constraints */ 33829a8f5e07SMark Brown if (init_data) 33839a8f5e07SMark Brown constraints = &init_data->constraints; 33849a8f5e07SMark Brown 33859a8f5e07SMark Brown ret = set_machine_constraints(rdev, constraints); 338674f544c1SMike Rapoport if (ret < 0) 338774f544c1SMike Rapoport goto scrub; 338874f544c1SMike Rapoport 33897ad68e2fSDavid Brownell /* add attributes supported by this regulator */ 33907ad68e2fSDavid Brownell ret = add_regulator_attributes(rdev); 33917ad68e2fSDavid Brownell if (ret < 0) 33927ad68e2fSDavid Brownell goto scrub; 33937ad68e2fSDavid Brownell 33949a8f5e07SMark Brown if (init_data && init_data->supply_regulator) 339569511a45SRajendra Nayak supply = init_data->supply_regulator; 339669511a45SRajendra Nayak else if (regulator_desc->supply_name) 339769511a45SRajendra Nayak supply = regulator_desc->supply_name; 339869511a45SRajendra Nayak 339969511a45SRajendra Nayak if (supply) { 34000178f3e2SMark Brown struct regulator_dev *r; 34010178f3e2SMark Brown 34026d191a5fSMark Brown r = regulator_dev_lookup(dev, supply, &ret); 34030178f3e2SMark Brown 340469511a45SRajendra Nayak if (!r) { 340569511a45SRajendra Nayak dev_err(dev, "Failed to find supply %s\n", supply); 340604bf3011SMark Brown ret = -EPROBE_DEFER; 34070178f3e2SMark Brown goto scrub; 34080178f3e2SMark Brown } 34090178f3e2SMark Brown 34100178f3e2SMark Brown ret = set_supply(rdev, r); 34110178f3e2SMark Brown if (ret < 0) 34120178f3e2SMark Brown goto scrub; 3413b2296bd4SLaxman Dewangan 3414b2296bd4SLaxman Dewangan /* Enable supply if rail is enabled */ 3415b1a86831SMark Brown if (_regulator_is_enabled(rdev)) { 3416b2296bd4SLaxman Dewangan ret = regulator_enable(rdev->supply); 3417b2296bd4SLaxman Dewangan if (ret < 0) 3418b2296bd4SLaxman Dewangan goto scrub; 3419b2296bd4SLaxman Dewangan } 34200178f3e2SMark Brown } 34210178f3e2SMark Brown 3422a5766f11SLiam Girdwood /* add consumers devices */ 34239a8f5e07SMark Brown if (init_data) { 3424a5766f11SLiam Girdwood for (i = 0; i < init_data->num_consumer_supplies; i++) { 3425a5766f11SLiam Girdwood ret = set_consumer_device_supply(rdev, 342640f9244fSMark Brown init_data->consumer_supplies[i].dev_name, 3427a5766f11SLiam Girdwood init_data->consumer_supplies[i].supply); 342823c2f041SMark Brown if (ret < 0) { 342923c2f041SMark Brown dev_err(dev, "Failed to set supply %s\n", 343023c2f041SMark Brown init_data->consumer_supplies[i].supply); 3431d4033b54SJani Nikula goto unset_supplies; 3432a5766f11SLiam Girdwood } 343323c2f041SMark Brown } 34349a8f5e07SMark Brown } 3435a5766f11SLiam Girdwood 3436a5766f11SLiam Girdwood list_add(&rdev->list, ®ulator_list); 34371130e5b3SMark Brown 34381130e5b3SMark Brown rdev_init_debugfs(rdev); 3439a5766f11SLiam Girdwood out: 3440414c70cbSLiam Girdwood mutex_unlock(®ulator_list_mutex); 3441414c70cbSLiam Girdwood return rdev; 34424fca9545SDavid Brownell 3443d4033b54SJani Nikula unset_supplies: 3444d4033b54SJani Nikula unset_regulator_supplies(rdev); 3445d4033b54SJani Nikula 34464fca9545SDavid Brownell scrub: 3447e81dba85SMark Brown if (rdev->supply) 3448e81dba85SMark Brown regulator_put(rdev->supply); 344965f73508SMark Brown if (rdev->ena_gpio) 345065f73508SMark Brown gpio_free(rdev->ena_gpio); 34511a6958e7SAxel Lin kfree(rdev->constraints); 3452b2da55d9SAndrew Lunn wash: 34534fca9545SDavid Brownell device_unregister(&rdev->dev); 345453032dafSPaul Walmsley /* device core frees rdev */ 345553032dafSPaul Walmsley rdev = ERR_PTR(ret); 345653032dafSPaul Walmsley goto out; 345753032dafSPaul Walmsley 34584fca9545SDavid Brownell clean: 34594fca9545SDavid Brownell kfree(rdev); 34604fca9545SDavid Brownell rdev = ERR_PTR(ret); 34614fca9545SDavid Brownell goto out; 3462414c70cbSLiam Girdwood } 3463414c70cbSLiam Girdwood EXPORT_SYMBOL_GPL(regulator_register); 3464414c70cbSLiam Girdwood 3465414c70cbSLiam Girdwood /** 3466414c70cbSLiam Girdwood * regulator_unregister - unregister regulator 346769279fb9SMark Brown * @rdev: regulator to unregister 3468414c70cbSLiam Girdwood * 3469414c70cbSLiam Girdwood * Called by regulator drivers to unregister a regulator. 3470414c70cbSLiam Girdwood */ 3471414c70cbSLiam Girdwood void regulator_unregister(struct regulator_dev *rdev) 3472414c70cbSLiam Girdwood { 3473414c70cbSLiam Girdwood if (rdev == NULL) 3474414c70cbSLiam Girdwood return; 3475414c70cbSLiam Girdwood 3476e032b376SMark Brown if (rdev->supply) 3477e032b376SMark Brown regulator_put(rdev->supply); 3478414c70cbSLiam Girdwood mutex_lock(®ulator_list_mutex); 34791130e5b3SMark Brown debugfs_remove_recursive(rdev->debugfs); 348043829731STejun Heo flush_work(&rdev->disable_work.work); 34816bf87d17SMark Brown WARN_ON(rdev->open_count); 34820f1d747bSMike Rapoport unset_regulator_supplies(rdev); 3483414c70cbSLiam Girdwood list_del(&rdev->list); 3484f8c12fe3SMark Brown kfree(rdev->constraints); 348565f73508SMark Brown if (rdev->ena_gpio) 348665f73508SMark Brown gpio_free(rdev->ena_gpio); 348758fb5cf5SLothar Waßmann device_unregister(&rdev->dev); 3488414c70cbSLiam Girdwood mutex_unlock(®ulator_list_mutex); 3489414c70cbSLiam Girdwood } 3490414c70cbSLiam Girdwood EXPORT_SYMBOL_GPL(regulator_unregister); 3491414c70cbSLiam Girdwood 3492414c70cbSLiam Girdwood /** 3493cf7bbcdfSMark Brown * regulator_suspend_prepare - prepare regulators for system wide suspend 3494414c70cbSLiam Girdwood * @state: system suspend state 3495414c70cbSLiam Girdwood * 3496414c70cbSLiam Girdwood * Configure each regulator with it's suspend operating parameters for state. 3497414c70cbSLiam Girdwood * This will usually be called by machine suspend code prior to supending. 3498414c70cbSLiam Girdwood */ 3499414c70cbSLiam Girdwood int regulator_suspend_prepare(suspend_state_t state) 3500414c70cbSLiam Girdwood { 3501414c70cbSLiam Girdwood struct regulator_dev *rdev; 3502414c70cbSLiam Girdwood int ret = 0; 3503414c70cbSLiam Girdwood 3504414c70cbSLiam Girdwood /* ON is handled by regulator active state */ 3505414c70cbSLiam Girdwood if (state == PM_SUSPEND_ON) 3506414c70cbSLiam Girdwood return -EINVAL; 3507414c70cbSLiam Girdwood 3508414c70cbSLiam Girdwood mutex_lock(®ulator_list_mutex); 3509414c70cbSLiam Girdwood list_for_each_entry(rdev, ®ulator_list, list) { 3510414c70cbSLiam Girdwood 3511414c70cbSLiam Girdwood mutex_lock(&rdev->mutex); 3512414c70cbSLiam Girdwood ret = suspend_prepare(rdev, state); 3513414c70cbSLiam Girdwood mutex_unlock(&rdev->mutex); 3514414c70cbSLiam Girdwood 3515414c70cbSLiam Girdwood if (ret < 0) { 35165da84fd9SJoe Perches rdev_err(rdev, "failed to prepare\n"); 3517414c70cbSLiam Girdwood goto out; 3518414c70cbSLiam Girdwood } 3519414c70cbSLiam Girdwood } 3520414c70cbSLiam Girdwood out: 3521414c70cbSLiam Girdwood mutex_unlock(®ulator_list_mutex); 3522414c70cbSLiam Girdwood return ret; 3523414c70cbSLiam Girdwood } 3524414c70cbSLiam Girdwood EXPORT_SYMBOL_GPL(regulator_suspend_prepare); 3525414c70cbSLiam Girdwood 3526414c70cbSLiam Girdwood /** 35277a32b589SMyungJoo Ham * regulator_suspend_finish - resume regulators from system wide suspend 35287a32b589SMyungJoo Ham * 35297a32b589SMyungJoo Ham * Turn on regulators that might be turned off by regulator_suspend_prepare 35307a32b589SMyungJoo Ham * and that should be turned on according to the regulators properties. 35317a32b589SMyungJoo Ham */ 35327a32b589SMyungJoo Ham int regulator_suspend_finish(void) 35337a32b589SMyungJoo Ham { 35347a32b589SMyungJoo Ham struct regulator_dev *rdev; 35357a32b589SMyungJoo Ham int ret = 0, error; 35367a32b589SMyungJoo Ham 35377a32b589SMyungJoo Ham mutex_lock(®ulator_list_mutex); 35387a32b589SMyungJoo Ham list_for_each_entry(rdev, ®ulator_list, list) { 35397a32b589SMyungJoo Ham struct regulator_ops *ops = rdev->desc->ops; 35407a32b589SMyungJoo Ham 35417a32b589SMyungJoo Ham mutex_lock(&rdev->mutex); 35427a32b589SMyungJoo Ham if ((rdev->use_count > 0 || rdev->constraints->always_on) && 35437a32b589SMyungJoo Ham ops->enable) { 35447a32b589SMyungJoo Ham error = ops->enable(rdev); 35457a32b589SMyungJoo Ham if (error) 35467a32b589SMyungJoo Ham ret = error; 35477a32b589SMyungJoo Ham } else { 35487a32b589SMyungJoo Ham if (!has_full_constraints) 35497a32b589SMyungJoo Ham goto unlock; 35507a32b589SMyungJoo Ham if (!ops->disable) 35517a32b589SMyungJoo Ham goto unlock; 3552b1a86831SMark Brown if (!_regulator_is_enabled(rdev)) 35537a32b589SMyungJoo Ham goto unlock; 35547a32b589SMyungJoo Ham 35557a32b589SMyungJoo Ham error = ops->disable(rdev); 35567a32b589SMyungJoo Ham if (error) 35577a32b589SMyungJoo Ham ret = error; 35587a32b589SMyungJoo Ham } 35597a32b589SMyungJoo Ham unlock: 35607a32b589SMyungJoo Ham mutex_unlock(&rdev->mutex); 35617a32b589SMyungJoo Ham } 35627a32b589SMyungJoo Ham mutex_unlock(®ulator_list_mutex); 35637a32b589SMyungJoo Ham return ret; 35647a32b589SMyungJoo Ham } 35657a32b589SMyungJoo Ham EXPORT_SYMBOL_GPL(regulator_suspend_finish); 35667a32b589SMyungJoo Ham 35677a32b589SMyungJoo Ham /** 3568ca725561SMark Brown * regulator_has_full_constraints - the system has fully specified constraints 3569ca725561SMark Brown * 3570ca725561SMark Brown * Calling this function will cause the regulator API to disable all 3571ca725561SMark Brown * regulators which have a zero use count and don't have an always_on 3572ca725561SMark Brown * constraint in a late_initcall. 3573ca725561SMark Brown * 3574ca725561SMark Brown * The intention is that this will become the default behaviour in a 3575ca725561SMark Brown * future kernel release so users are encouraged to use this facility 3576ca725561SMark Brown * now. 3577ca725561SMark Brown */ 3578ca725561SMark Brown void regulator_has_full_constraints(void) 3579ca725561SMark Brown { 3580ca725561SMark Brown has_full_constraints = 1; 3581ca725561SMark Brown } 3582ca725561SMark Brown EXPORT_SYMBOL_GPL(regulator_has_full_constraints); 3583ca725561SMark Brown 3584ca725561SMark Brown /** 3585688fe99aSMark Brown * regulator_use_dummy_regulator - Provide a dummy regulator when none is found 3586688fe99aSMark Brown * 3587688fe99aSMark Brown * Calling this function will cause the regulator API to provide a 3588688fe99aSMark Brown * dummy regulator to consumers if no physical regulator is found, 3589688fe99aSMark Brown * allowing most consumers to proceed as though a regulator were 3590688fe99aSMark Brown * configured. This allows systems such as those with software 3591688fe99aSMark Brown * controllable regulators for the CPU core only to be brought up more 3592688fe99aSMark Brown * readily. 3593688fe99aSMark Brown */ 3594688fe99aSMark Brown void regulator_use_dummy_regulator(void) 3595688fe99aSMark Brown { 3596688fe99aSMark Brown board_wants_dummy_regulator = true; 3597688fe99aSMark Brown } 3598688fe99aSMark Brown EXPORT_SYMBOL_GPL(regulator_use_dummy_regulator); 3599688fe99aSMark Brown 3600688fe99aSMark Brown /** 3601414c70cbSLiam Girdwood * rdev_get_drvdata - get rdev regulator driver data 360269279fb9SMark Brown * @rdev: regulator 3603414c70cbSLiam Girdwood * 3604414c70cbSLiam Girdwood * Get rdev regulator driver private data. This call can be used in the 3605414c70cbSLiam Girdwood * regulator driver context. 3606414c70cbSLiam Girdwood */ 3607414c70cbSLiam Girdwood void *rdev_get_drvdata(struct regulator_dev *rdev) 3608414c70cbSLiam Girdwood { 3609414c70cbSLiam Girdwood return rdev->reg_data; 3610414c70cbSLiam Girdwood } 3611414c70cbSLiam Girdwood EXPORT_SYMBOL_GPL(rdev_get_drvdata); 3612414c70cbSLiam Girdwood 3613414c70cbSLiam Girdwood /** 3614414c70cbSLiam Girdwood * regulator_get_drvdata - get regulator driver data 3615414c70cbSLiam Girdwood * @regulator: regulator 3616414c70cbSLiam Girdwood * 3617414c70cbSLiam Girdwood * Get regulator driver private data. This call can be used in the consumer 3618414c70cbSLiam Girdwood * driver context when non API regulator specific functions need to be called. 3619414c70cbSLiam Girdwood */ 3620414c70cbSLiam Girdwood void *regulator_get_drvdata(struct regulator *regulator) 3621414c70cbSLiam Girdwood { 3622414c70cbSLiam Girdwood return regulator->rdev->reg_data; 3623414c70cbSLiam Girdwood } 3624414c70cbSLiam Girdwood EXPORT_SYMBOL_GPL(regulator_get_drvdata); 3625414c70cbSLiam Girdwood 3626414c70cbSLiam Girdwood /** 3627414c70cbSLiam Girdwood * regulator_set_drvdata - set regulator driver data 3628414c70cbSLiam Girdwood * @regulator: regulator 3629414c70cbSLiam Girdwood * @data: data 3630414c70cbSLiam Girdwood */ 3631414c70cbSLiam Girdwood void regulator_set_drvdata(struct regulator *regulator, void *data) 3632414c70cbSLiam Girdwood { 3633414c70cbSLiam Girdwood regulator->rdev->reg_data = data; 3634414c70cbSLiam Girdwood } 3635414c70cbSLiam Girdwood EXPORT_SYMBOL_GPL(regulator_set_drvdata); 3636414c70cbSLiam Girdwood 3637414c70cbSLiam Girdwood /** 3638414c70cbSLiam Girdwood * regulator_get_id - get regulator ID 363969279fb9SMark Brown * @rdev: regulator 3640414c70cbSLiam Girdwood */ 3641414c70cbSLiam Girdwood int rdev_get_id(struct regulator_dev *rdev) 3642414c70cbSLiam Girdwood { 3643414c70cbSLiam Girdwood return rdev->desc->id; 3644414c70cbSLiam Girdwood } 3645414c70cbSLiam Girdwood EXPORT_SYMBOL_GPL(rdev_get_id); 3646414c70cbSLiam Girdwood 3647a5766f11SLiam Girdwood struct device *rdev_get_dev(struct regulator_dev *rdev) 3648a5766f11SLiam Girdwood { 3649a5766f11SLiam Girdwood return &rdev->dev; 3650a5766f11SLiam Girdwood } 3651a5766f11SLiam Girdwood EXPORT_SYMBOL_GPL(rdev_get_dev); 3652a5766f11SLiam Girdwood 3653a5766f11SLiam Girdwood void *regulator_get_init_drvdata(struct regulator_init_data *reg_init_data) 3654a5766f11SLiam Girdwood { 3655a5766f11SLiam Girdwood return reg_init_data->driver_data; 3656a5766f11SLiam Girdwood } 3657a5766f11SLiam Girdwood EXPORT_SYMBOL_GPL(regulator_get_init_drvdata); 3658a5766f11SLiam Girdwood 3659ba55a974SMark Brown #ifdef CONFIG_DEBUG_FS 3660ba55a974SMark Brown static ssize_t supply_map_read_file(struct file *file, char __user *user_buf, 3661ba55a974SMark Brown size_t count, loff_t *ppos) 3662ba55a974SMark Brown { 3663ba55a974SMark Brown char *buf = kmalloc(PAGE_SIZE, GFP_KERNEL); 3664ba55a974SMark Brown ssize_t len, ret = 0; 3665ba55a974SMark Brown struct regulator_map *map; 3666ba55a974SMark Brown 3667ba55a974SMark Brown if (!buf) 3668ba55a974SMark Brown return -ENOMEM; 3669ba55a974SMark Brown 3670ba55a974SMark Brown list_for_each_entry(map, ®ulator_map_list, list) { 3671ba55a974SMark Brown len = snprintf(buf + ret, PAGE_SIZE - ret, 3672ba55a974SMark Brown "%s -> %s.%s\n", 3673ba55a974SMark Brown rdev_get_name(map->regulator), map->dev_name, 3674ba55a974SMark Brown map->supply); 3675ba55a974SMark Brown if (len >= 0) 3676ba55a974SMark Brown ret += len; 3677ba55a974SMark Brown if (ret > PAGE_SIZE) { 3678ba55a974SMark Brown ret = PAGE_SIZE; 3679ba55a974SMark Brown break; 3680ba55a974SMark Brown } 3681ba55a974SMark Brown } 3682ba55a974SMark Brown 3683ba55a974SMark Brown ret = simple_read_from_buffer(user_buf, count, ppos, buf, ret); 3684ba55a974SMark Brown 3685ba55a974SMark Brown kfree(buf); 3686ba55a974SMark Brown 3687ba55a974SMark Brown return ret; 3688ba55a974SMark Brown } 368924751434SStephen Boyd #endif 3690ba55a974SMark Brown 3691ba55a974SMark Brown static const struct file_operations supply_map_fops = { 369224751434SStephen Boyd #ifdef CONFIG_DEBUG_FS 3693ba55a974SMark Brown .read = supply_map_read_file, 3694ba55a974SMark Brown .llseek = default_llseek, 3695ba55a974SMark Brown #endif 369624751434SStephen Boyd }; 3697ba55a974SMark Brown 3698414c70cbSLiam Girdwood static int __init regulator_init(void) 3699414c70cbSLiam Girdwood { 370034abbd68SMark Brown int ret; 370134abbd68SMark Brown 370234abbd68SMark Brown ret = class_register(®ulator_class); 370334abbd68SMark Brown 37041130e5b3SMark Brown debugfs_root = debugfs_create_dir("regulator", NULL); 370524751434SStephen Boyd if (!debugfs_root) 37061130e5b3SMark Brown pr_warn("regulator: Failed to create debugfs directory\n"); 3707ba55a974SMark Brown 3708f4d562c6SMark Brown debugfs_create_file("supply_map", 0444, debugfs_root, NULL, 3709f4d562c6SMark Brown &supply_map_fops); 37101130e5b3SMark Brown 371134abbd68SMark Brown regulator_dummy_init(); 371234abbd68SMark Brown 371334abbd68SMark Brown return ret; 3714414c70cbSLiam Girdwood } 3715414c70cbSLiam Girdwood 3716414c70cbSLiam Girdwood /* init early to allow our consumers to complete system booting */ 3717414c70cbSLiam Girdwood core_initcall(regulator_init); 3718ca725561SMark Brown 3719ca725561SMark Brown static int __init regulator_init_complete(void) 3720ca725561SMark Brown { 3721ca725561SMark Brown struct regulator_dev *rdev; 3722ca725561SMark Brown struct regulator_ops *ops; 3723ca725561SMark Brown struct regulation_constraints *c; 3724ca725561SMark Brown int enabled, ret; 3725ca725561SMark Brown 372686f5fcfcSMark Brown /* 372786f5fcfcSMark Brown * Since DT doesn't provide an idiomatic mechanism for 372886f5fcfcSMark Brown * enabling full constraints and since it's much more natural 372986f5fcfcSMark Brown * with DT to provide them just assume that a DT enabled 373086f5fcfcSMark Brown * system has full constraints. 373186f5fcfcSMark Brown */ 373286f5fcfcSMark Brown if (of_have_populated_dt()) 373386f5fcfcSMark Brown has_full_constraints = true; 373486f5fcfcSMark Brown 3735ca725561SMark Brown mutex_lock(®ulator_list_mutex); 3736ca725561SMark Brown 3737ca725561SMark Brown /* If we have a full configuration then disable any regulators 3738ca725561SMark Brown * which are not in use or always_on. This will become the 3739ca725561SMark Brown * default behaviour in the future. 3740ca725561SMark Brown */ 3741ca725561SMark Brown list_for_each_entry(rdev, ®ulator_list, list) { 3742ca725561SMark Brown ops = rdev->desc->ops; 3743ca725561SMark Brown c = rdev->constraints; 3744ca725561SMark Brown 3745f25e0b4fSMark Brown if (!ops->disable || (c && c->always_on)) 3746ca725561SMark Brown continue; 3747ca725561SMark Brown 3748ca725561SMark Brown mutex_lock(&rdev->mutex); 3749ca725561SMark Brown 3750ca725561SMark Brown if (rdev->use_count) 3751ca725561SMark Brown goto unlock; 3752ca725561SMark Brown 3753ca725561SMark Brown /* If we can't read the status assume it's on. */ 3754ca725561SMark Brown if (ops->is_enabled) 3755ca725561SMark Brown enabled = ops->is_enabled(rdev); 3756ca725561SMark Brown else 3757ca725561SMark Brown enabled = 1; 3758ca725561SMark Brown 3759ca725561SMark Brown if (!enabled) 3760ca725561SMark Brown goto unlock; 3761ca725561SMark Brown 3762ca725561SMark Brown if (has_full_constraints) { 3763ca725561SMark Brown /* We log since this may kill the system if it 3764ca725561SMark Brown * goes wrong. */ 37655da84fd9SJoe Perches rdev_info(rdev, "disabling\n"); 3766ca725561SMark Brown ret = ops->disable(rdev); 3767ca725561SMark Brown if (ret != 0) { 37685da84fd9SJoe Perches rdev_err(rdev, "couldn't disable: %d\n", ret); 3769ca725561SMark Brown } 3770ca725561SMark Brown } else { 3771ca725561SMark Brown /* The intention is that in future we will 3772ca725561SMark Brown * assume that full constraints are provided 3773ca725561SMark Brown * so warn even if we aren't going to do 3774ca725561SMark Brown * anything here. 3775ca725561SMark Brown */ 37765da84fd9SJoe Perches rdev_warn(rdev, "incomplete constraints, leaving on\n"); 3777ca725561SMark Brown } 3778ca725561SMark Brown 3779ca725561SMark Brown unlock: 3780ca725561SMark Brown mutex_unlock(&rdev->mutex); 3781ca725561SMark Brown } 3782ca725561SMark Brown 3783ca725561SMark Brown mutex_unlock(®ulator_list_mutex); 3784ca725561SMark Brown 3785ca725561SMark Brown return 0; 3786ca725561SMark Brown } 3787ca725561SMark Brown late_initcall(regulator_init_complete); 3788