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; 80414c70cbSLiam Girdwood int uA_load; 81414c70cbSLiam Girdwood int min_uV; 82414c70cbSLiam Girdwood int max_uV; 83414c70cbSLiam Girdwood char *supply_name; 84414c70cbSLiam Girdwood struct device_attribute dev_attr; 85414c70cbSLiam Girdwood struct regulator_dev *rdev; 865de70519SMark Brown struct dentry *debugfs; 87414c70cbSLiam Girdwood }; 88414c70cbSLiam Girdwood 89414c70cbSLiam Girdwood static int _regulator_is_enabled(struct regulator_dev *rdev); 903801b86aSMark Brown static int _regulator_disable(struct regulator_dev *rdev); 91414c70cbSLiam Girdwood static int _regulator_get_voltage(struct regulator_dev *rdev); 92414c70cbSLiam Girdwood static int _regulator_get_current_limit(struct regulator_dev *rdev); 93414c70cbSLiam Girdwood static unsigned int _regulator_get_mode(struct regulator_dev *rdev); 94414c70cbSLiam Girdwood static void _notifier_call_chain(struct regulator_dev *rdev, 95414c70cbSLiam Girdwood unsigned long event, void *data); 9675790251SMark Brown static int _regulator_do_set_voltage(struct regulator_dev *rdev, 9775790251SMark Brown int min_uV, int max_uV); 983801b86aSMark Brown static struct regulator *create_regulator(struct regulator_dev *rdev, 993801b86aSMark Brown struct device *dev, 1003801b86aSMark Brown const char *supply_name); 101414c70cbSLiam Girdwood 1021083c393SMark Brown static const char *rdev_get_name(struct regulator_dev *rdev) 1031083c393SMark Brown { 1041083c393SMark Brown if (rdev->constraints && rdev->constraints->name) 1051083c393SMark Brown return rdev->constraints->name; 1061083c393SMark Brown else if (rdev->desc->name) 1071083c393SMark Brown return rdev->desc->name; 1081083c393SMark Brown else 1091083c393SMark Brown return ""; 1101083c393SMark Brown } 1111083c393SMark Brown 11269511a45SRajendra Nayak /** 11369511a45SRajendra Nayak * of_get_regulator - get a regulator device node based on supply name 11469511a45SRajendra Nayak * @dev: Device pointer for the consumer (of regulator) device 11569511a45SRajendra Nayak * @supply: regulator supply name 11669511a45SRajendra Nayak * 11769511a45SRajendra Nayak * Extract the regulator device node corresponding to the supply name. 11869511a45SRajendra Nayak * retruns the device node corresponding to the regulator if found, else 11969511a45SRajendra Nayak * returns NULL. 12069511a45SRajendra Nayak */ 12169511a45SRajendra Nayak static struct device_node *of_get_regulator(struct device *dev, const char *supply) 12269511a45SRajendra Nayak { 12369511a45SRajendra Nayak struct device_node *regnode = NULL; 12469511a45SRajendra Nayak char prop_name[32]; /* 32 is max size of property name */ 12569511a45SRajendra Nayak 12669511a45SRajendra Nayak dev_dbg(dev, "Looking up %s-supply from device tree\n", supply); 12769511a45SRajendra Nayak 12869511a45SRajendra Nayak snprintf(prop_name, 32, "%s-supply", supply); 12969511a45SRajendra Nayak regnode = of_parse_phandle(dev->of_node, prop_name, 0); 13069511a45SRajendra Nayak 13169511a45SRajendra Nayak if (!regnode) { 13216fbcc3bSRajendra Nayak dev_dbg(dev, "Looking up %s property in node %s failed", 13369511a45SRajendra Nayak prop_name, dev->of_node->full_name); 13469511a45SRajendra Nayak return NULL; 13569511a45SRajendra Nayak } 13669511a45SRajendra Nayak return regnode; 13769511a45SRajendra Nayak } 13869511a45SRajendra Nayak 1396492bc1bSMark Brown static int _regulator_can_change_status(struct regulator_dev *rdev) 1406492bc1bSMark Brown { 1416492bc1bSMark Brown if (!rdev->constraints) 1426492bc1bSMark Brown return 0; 1436492bc1bSMark Brown 1446492bc1bSMark Brown if (rdev->constraints->valid_ops_mask & REGULATOR_CHANGE_STATUS) 1456492bc1bSMark Brown return 1; 1466492bc1bSMark Brown else 1476492bc1bSMark Brown return 0; 1486492bc1bSMark Brown } 1496492bc1bSMark Brown 150414c70cbSLiam Girdwood /* Platform voltage constraint check */ 151414c70cbSLiam Girdwood static int regulator_check_voltage(struct regulator_dev *rdev, 152414c70cbSLiam Girdwood int *min_uV, int *max_uV) 153414c70cbSLiam Girdwood { 154414c70cbSLiam Girdwood BUG_ON(*min_uV > *max_uV); 155414c70cbSLiam Girdwood 156414c70cbSLiam Girdwood if (!rdev->constraints) { 1575da84fd9SJoe Perches rdev_err(rdev, "no constraints\n"); 158414c70cbSLiam Girdwood return -ENODEV; 159414c70cbSLiam Girdwood } 160414c70cbSLiam Girdwood if (!(rdev->constraints->valid_ops_mask & REGULATOR_CHANGE_VOLTAGE)) { 1615da84fd9SJoe Perches rdev_err(rdev, "operation not allowed\n"); 162414c70cbSLiam Girdwood return -EPERM; 163414c70cbSLiam Girdwood } 164414c70cbSLiam Girdwood 165414c70cbSLiam Girdwood if (*max_uV > rdev->constraints->max_uV) 166414c70cbSLiam Girdwood *max_uV = rdev->constraints->max_uV; 167414c70cbSLiam Girdwood if (*min_uV < rdev->constraints->min_uV) 168414c70cbSLiam Girdwood *min_uV = rdev->constraints->min_uV; 169414c70cbSLiam Girdwood 17089f425edSMark Brown if (*min_uV > *max_uV) { 17189f425edSMark Brown rdev_err(rdev, "unsupportable voltage range: %d-%duV\n", 17254abd335SMark Brown *min_uV, *max_uV); 173414c70cbSLiam Girdwood return -EINVAL; 17489f425edSMark Brown } 175414c70cbSLiam Girdwood 176414c70cbSLiam Girdwood return 0; 177414c70cbSLiam Girdwood } 178414c70cbSLiam Girdwood 17905fda3b1SThomas Petazzoni /* Make sure we select a voltage that suits the needs of all 18005fda3b1SThomas Petazzoni * regulator consumers 18105fda3b1SThomas Petazzoni */ 18205fda3b1SThomas Petazzoni static int regulator_check_consumers(struct regulator_dev *rdev, 18305fda3b1SThomas Petazzoni int *min_uV, int *max_uV) 18405fda3b1SThomas Petazzoni { 18505fda3b1SThomas Petazzoni struct regulator *regulator; 18605fda3b1SThomas Petazzoni 18705fda3b1SThomas Petazzoni list_for_each_entry(regulator, &rdev->consumer_list, list) { 1884aa922c0SMark Brown /* 1894aa922c0SMark Brown * Assume consumers that didn't say anything are OK 1904aa922c0SMark Brown * with anything in the constraint range. 1914aa922c0SMark Brown */ 1924aa922c0SMark Brown if (!regulator->min_uV && !regulator->max_uV) 1934aa922c0SMark Brown continue; 1944aa922c0SMark Brown 19505fda3b1SThomas Petazzoni if (*max_uV > regulator->max_uV) 19605fda3b1SThomas Petazzoni *max_uV = regulator->max_uV; 19705fda3b1SThomas Petazzoni if (*min_uV < regulator->min_uV) 19805fda3b1SThomas Petazzoni *min_uV = regulator->min_uV; 19905fda3b1SThomas Petazzoni } 20005fda3b1SThomas Petazzoni 20105fda3b1SThomas Petazzoni if (*min_uV > *max_uV) 20205fda3b1SThomas Petazzoni return -EINVAL; 20305fda3b1SThomas Petazzoni 20405fda3b1SThomas Petazzoni return 0; 20505fda3b1SThomas Petazzoni } 20605fda3b1SThomas Petazzoni 207414c70cbSLiam Girdwood /* current constraint check */ 208414c70cbSLiam Girdwood static int regulator_check_current_limit(struct regulator_dev *rdev, 209414c70cbSLiam Girdwood int *min_uA, int *max_uA) 210414c70cbSLiam Girdwood { 211414c70cbSLiam Girdwood BUG_ON(*min_uA > *max_uA); 212414c70cbSLiam Girdwood 213414c70cbSLiam Girdwood if (!rdev->constraints) { 2145da84fd9SJoe Perches rdev_err(rdev, "no constraints\n"); 215414c70cbSLiam Girdwood return -ENODEV; 216414c70cbSLiam Girdwood } 217414c70cbSLiam Girdwood if (!(rdev->constraints->valid_ops_mask & REGULATOR_CHANGE_CURRENT)) { 2185da84fd9SJoe Perches rdev_err(rdev, "operation not allowed\n"); 219414c70cbSLiam Girdwood return -EPERM; 220414c70cbSLiam Girdwood } 221414c70cbSLiam Girdwood 222414c70cbSLiam Girdwood if (*max_uA > rdev->constraints->max_uA) 223414c70cbSLiam Girdwood *max_uA = rdev->constraints->max_uA; 224414c70cbSLiam Girdwood if (*min_uA < rdev->constraints->min_uA) 225414c70cbSLiam Girdwood *min_uA = rdev->constraints->min_uA; 226414c70cbSLiam Girdwood 22789f425edSMark Brown if (*min_uA > *max_uA) { 22889f425edSMark Brown rdev_err(rdev, "unsupportable current range: %d-%duA\n", 22954abd335SMark Brown *min_uA, *max_uA); 230414c70cbSLiam Girdwood return -EINVAL; 23189f425edSMark Brown } 232414c70cbSLiam Girdwood 233414c70cbSLiam Girdwood return 0; 234414c70cbSLiam Girdwood } 235414c70cbSLiam Girdwood 236414c70cbSLiam Girdwood /* operating mode constraint check */ 2372c608234SMark Brown static int regulator_mode_constrain(struct regulator_dev *rdev, int *mode) 238414c70cbSLiam Girdwood { 2392c608234SMark Brown switch (*mode) { 240e573520bSDavid Brownell case REGULATOR_MODE_FAST: 241e573520bSDavid Brownell case REGULATOR_MODE_NORMAL: 242e573520bSDavid Brownell case REGULATOR_MODE_IDLE: 243e573520bSDavid Brownell case REGULATOR_MODE_STANDBY: 244e573520bSDavid Brownell break; 245e573520bSDavid Brownell default: 24689f425edSMark Brown rdev_err(rdev, "invalid mode %x specified\n", *mode); 247e573520bSDavid Brownell return -EINVAL; 248e573520bSDavid Brownell } 249e573520bSDavid Brownell 250414c70cbSLiam Girdwood if (!rdev->constraints) { 2515da84fd9SJoe Perches rdev_err(rdev, "no constraints\n"); 252414c70cbSLiam Girdwood return -ENODEV; 253414c70cbSLiam Girdwood } 254414c70cbSLiam Girdwood if (!(rdev->constraints->valid_ops_mask & REGULATOR_CHANGE_MODE)) { 2555da84fd9SJoe Perches rdev_err(rdev, "operation not allowed\n"); 256414c70cbSLiam Girdwood return -EPERM; 257414c70cbSLiam Girdwood } 2582c608234SMark Brown 2592c608234SMark Brown /* The modes are bitmasks, the most power hungry modes having 2602c608234SMark Brown * the lowest values. If the requested mode isn't supported 2612c608234SMark Brown * try higher modes. */ 2622c608234SMark Brown while (*mode) { 2632c608234SMark Brown if (rdev->constraints->valid_modes_mask & *mode) 264414c70cbSLiam Girdwood return 0; 2652c608234SMark Brown *mode /= 2; 2662c608234SMark Brown } 2672c608234SMark Brown 2682c608234SMark Brown return -EINVAL; 269414c70cbSLiam Girdwood } 270414c70cbSLiam Girdwood 271414c70cbSLiam Girdwood /* dynamic regulator mode switching constraint check */ 272414c70cbSLiam Girdwood static int regulator_check_drms(struct regulator_dev *rdev) 273414c70cbSLiam Girdwood { 274414c70cbSLiam Girdwood if (!rdev->constraints) { 2755da84fd9SJoe Perches rdev_err(rdev, "no constraints\n"); 276414c70cbSLiam Girdwood return -ENODEV; 277414c70cbSLiam Girdwood } 278414c70cbSLiam Girdwood if (!(rdev->constraints->valid_ops_mask & REGULATOR_CHANGE_DRMS)) { 2795da84fd9SJoe Perches rdev_err(rdev, "operation not allowed\n"); 280414c70cbSLiam Girdwood return -EPERM; 281414c70cbSLiam Girdwood } 282414c70cbSLiam Girdwood return 0; 283414c70cbSLiam Girdwood } 284414c70cbSLiam Girdwood 285414c70cbSLiam Girdwood static ssize_t regulator_uV_show(struct device *dev, 286414c70cbSLiam Girdwood struct device_attribute *attr, char *buf) 287414c70cbSLiam Girdwood { 288a5766f11SLiam Girdwood struct regulator_dev *rdev = dev_get_drvdata(dev); 289414c70cbSLiam Girdwood ssize_t ret; 290414c70cbSLiam Girdwood 291414c70cbSLiam Girdwood mutex_lock(&rdev->mutex); 292414c70cbSLiam Girdwood ret = sprintf(buf, "%d\n", _regulator_get_voltage(rdev)); 293414c70cbSLiam Girdwood mutex_unlock(&rdev->mutex); 294414c70cbSLiam Girdwood 295414c70cbSLiam Girdwood return ret; 296414c70cbSLiam Girdwood } 2977ad68e2fSDavid Brownell static DEVICE_ATTR(microvolts, 0444, regulator_uV_show, NULL); 298414c70cbSLiam Girdwood 299414c70cbSLiam Girdwood static ssize_t regulator_uA_show(struct device *dev, 300414c70cbSLiam Girdwood struct device_attribute *attr, char *buf) 301414c70cbSLiam Girdwood { 302a5766f11SLiam Girdwood struct regulator_dev *rdev = dev_get_drvdata(dev); 303414c70cbSLiam Girdwood 304414c70cbSLiam Girdwood return sprintf(buf, "%d\n", _regulator_get_current_limit(rdev)); 305414c70cbSLiam Girdwood } 3067ad68e2fSDavid Brownell static DEVICE_ATTR(microamps, 0444, regulator_uA_show, NULL); 307414c70cbSLiam Girdwood 308bc558a60SMark Brown static ssize_t regulator_name_show(struct device *dev, 309bc558a60SMark Brown struct device_attribute *attr, char *buf) 310bc558a60SMark Brown { 311bc558a60SMark Brown struct regulator_dev *rdev = dev_get_drvdata(dev); 312bc558a60SMark Brown 3131083c393SMark Brown return sprintf(buf, "%s\n", rdev_get_name(rdev)); 314bc558a60SMark Brown } 315bc558a60SMark Brown 3164fca9545SDavid Brownell static ssize_t regulator_print_opmode(char *buf, int mode) 317414c70cbSLiam Girdwood { 318414c70cbSLiam Girdwood switch (mode) { 319414c70cbSLiam Girdwood case REGULATOR_MODE_FAST: 320414c70cbSLiam Girdwood return sprintf(buf, "fast\n"); 321414c70cbSLiam Girdwood case REGULATOR_MODE_NORMAL: 322414c70cbSLiam Girdwood return sprintf(buf, "normal\n"); 323414c70cbSLiam Girdwood case REGULATOR_MODE_IDLE: 324414c70cbSLiam Girdwood return sprintf(buf, "idle\n"); 325414c70cbSLiam Girdwood case REGULATOR_MODE_STANDBY: 326414c70cbSLiam Girdwood return sprintf(buf, "standby\n"); 327414c70cbSLiam Girdwood } 328414c70cbSLiam Girdwood return sprintf(buf, "unknown\n"); 329414c70cbSLiam Girdwood } 330414c70cbSLiam Girdwood 3314fca9545SDavid Brownell static ssize_t regulator_opmode_show(struct device *dev, 332414c70cbSLiam Girdwood struct device_attribute *attr, char *buf) 333414c70cbSLiam Girdwood { 334a5766f11SLiam Girdwood struct regulator_dev *rdev = dev_get_drvdata(dev); 335414c70cbSLiam Girdwood 3364fca9545SDavid Brownell return regulator_print_opmode(buf, _regulator_get_mode(rdev)); 3374fca9545SDavid Brownell } 3387ad68e2fSDavid Brownell static DEVICE_ATTR(opmode, 0444, regulator_opmode_show, NULL); 3394fca9545SDavid Brownell 3404fca9545SDavid Brownell static ssize_t regulator_print_state(char *buf, int state) 3414fca9545SDavid Brownell { 342414c70cbSLiam Girdwood if (state > 0) 343414c70cbSLiam Girdwood return sprintf(buf, "enabled\n"); 344414c70cbSLiam Girdwood else if (state == 0) 345414c70cbSLiam Girdwood return sprintf(buf, "disabled\n"); 346414c70cbSLiam Girdwood else 347414c70cbSLiam Girdwood return sprintf(buf, "unknown\n"); 348414c70cbSLiam Girdwood } 349414c70cbSLiam Girdwood 3504fca9545SDavid Brownell static ssize_t regulator_state_show(struct device *dev, 3514fca9545SDavid Brownell struct device_attribute *attr, char *buf) 3524fca9545SDavid Brownell { 3534fca9545SDavid Brownell struct regulator_dev *rdev = dev_get_drvdata(dev); 3549332546fSMark Brown ssize_t ret; 3554fca9545SDavid Brownell 3569332546fSMark Brown mutex_lock(&rdev->mutex); 3579332546fSMark Brown ret = regulator_print_state(buf, _regulator_is_enabled(rdev)); 3589332546fSMark Brown mutex_unlock(&rdev->mutex); 3599332546fSMark Brown 3609332546fSMark Brown return ret; 3614fca9545SDavid Brownell } 3627ad68e2fSDavid Brownell static DEVICE_ATTR(state, 0444, regulator_state_show, NULL); 3634fca9545SDavid Brownell 364853116a1SDavid Brownell static ssize_t regulator_status_show(struct device *dev, 365853116a1SDavid Brownell struct device_attribute *attr, char *buf) 366853116a1SDavid Brownell { 367853116a1SDavid Brownell struct regulator_dev *rdev = dev_get_drvdata(dev); 368853116a1SDavid Brownell int status; 369853116a1SDavid Brownell char *label; 370853116a1SDavid Brownell 371853116a1SDavid Brownell status = rdev->desc->ops->get_status(rdev); 372853116a1SDavid Brownell if (status < 0) 373853116a1SDavid Brownell return status; 374853116a1SDavid Brownell 375853116a1SDavid Brownell switch (status) { 376853116a1SDavid Brownell case REGULATOR_STATUS_OFF: 377853116a1SDavid Brownell label = "off"; 378853116a1SDavid Brownell break; 379853116a1SDavid Brownell case REGULATOR_STATUS_ON: 380853116a1SDavid Brownell label = "on"; 381853116a1SDavid Brownell break; 382853116a1SDavid Brownell case REGULATOR_STATUS_ERROR: 383853116a1SDavid Brownell label = "error"; 384853116a1SDavid Brownell break; 385853116a1SDavid Brownell case REGULATOR_STATUS_FAST: 386853116a1SDavid Brownell label = "fast"; 387853116a1SDavid Brownell break; 388853116a1SDavid Brownell case REGULATOR_STATUS_NORMAL: 389853116a1SDavid Brownell label = "normal"; 390853116a1SDavid Brownell break; 391853116a1SDavid Brownell case REGULATOR_STATUS_IDLE: 392853116a1SDavid Brownell label = "idle"; 393853116a1SDavid Brownell break; 394853116a1SDavid Brownell case REGULATOR_STATUS_STANDBY: 395853116a1SDavid Brownell label = "standby"; 396853116a1SDavid Brownell break; 3971beaf762SKrystian Garbaciak case REGULATOR_STATUS_UNDEFINED: 3981beaf762SKrystian Garbaciak label = "undefined"; 3991beaf762SKrystian Garbaciak break; 400853116a1SDavid Brownell default: 401853116a1SDavid Brownell return -ERANGE; 402853116a1SDavid Brownell } 403853116a1SDavid Brownell 404853116a1SDavid Brownell return sprintf(buf, "%s\n", label); 405853116a1SDavid Brownell } 406853116a1SDavid Brownell static DEVICE_ATTR(status, 0444, regulator_status_show, NULL); 407853116a1SDavid Brownell 408414c70cbSLiam Girdwood static ssize_t regulator_min_uA_show(struct device *dev, 409414c70cbSLiam Girdwood struct device_attribute *attr, char *buf) 410414c70cbSLiam Girdwood { 411a5766f11SLiam Girdwood struct regulator_dev *rdev = dev_get_drvdata(dev); 412414c70cbSLiam Girdwood 413414c70cbSLiam Girdwood if (!rdev->constraints) 414414c70cbSLiam Girdwood return sprintf(buf, "constraint not defined\n"); 415414c70cbSLiam Girdwood 416414c70cbSLiam Girdwood return sprintf(buf, "%d\n", rdev->constraints->min_uA); 417414c70cbSLiam Girdwood } 4187ad68e2fSDavid Brownell static DEVICE_ATTR(min_microamps, 0444, regulator_min_uA_show, NULL); 419414c70cbSLiam Girdwood 420414c70cbSLiam Girdwood static ssize_t regulator_max_uA_show(struct device *dev, 421414c70cbSLiam Girdwood struct device_attribute *attr, char *buf) 422414c70cbSLiam Girdwood { 423a5766f11SLiam Girdwood struct regulator_dev *rdev = dev_get_drvdata(dev); 424414c70cbSLiam Girdwood 425414c70cbSLiam Girdwood if (!rdev->constraints) 426414c70cbSLiam Girdwood return sprintf(buf, "constraint not defined\n"); 427414c70cbSLiam Girdwood 428414c70cbSLiam Girdwood return sprintf(buf, "%d\n", rdev->constraints->max_uA); 429414c70cbSLiam Girdwood } 4307ad68e2fSDavid Brownell static DEVICE_ATTR(max_microamps, 0444, regulator_max_uA_show, NULL); 431414c70cbSLiam Girdwood 432414c70cbSLiam Girdwood static ssize_t regulator_min_uV_show(struct device *dev, 433414c70cbSLiam Girdwood struct device_attribute *attr, char *buf) 434414c70cbSLiam Girdwood { 435a5766f11SLiam Girdwood struct regulator_dev *rdev = dev_get_drvdata(dev); 436414c70cbSLiam Girdwood 437414c70cbSLiam Girdwood if (!rdev->constraints) 438414c70cbSLiam Girdwood return sprintf(buf, "constraint not defined\n"); 439414c70cbSLiam Girdwood 440414c70cbSLiam Girdwood return sprintf(buf, "%d\n", rdev->constraints->min_uV); 441414c70cbSLiam Girdwood } 4427ad68e2fSDavid Brownell static DEVICE_ATTR(min_microvolts, 0444, regulator_min_uV_show, NULL); 443414c70cbSLiam Girdwood 444414c70cbSLiam Girdwood static ssize_t regulator_max_uV_show(struct device *dev, 445414c70cbSLiam Girdwood struct device_attribute *attr, char *buf) 446414c70cbSLiam Girdwood { 447a5766f11SLiam Girdwood struct regulator_dev *rdev = dev_get_drvdata(dev); 448414c70cbSLiam Girdwood 449414c70cbSLiam Girdwood if (!rdev->constraints) 450414c70cbSLiam Girdwood return sprintf(buf, "constraint not defined\n"); 451414c70cbSLiam Girdwood 452414c70cbSLiam Girdwood return sprintf(buf, "%d\n", rdev->constraints->max_uV); 453414c70cbSLiam Girdwood } 4547ad68e2fSDavid Brownell static DEVICE_ATTR(max_microvolts, 0444, regulator_max_uV_show, NULL); 455414c70cbSLiam Girdwood 456414c70cbSLiam Girdwood static ssize_t regulator_total_uA_show(struct device *dev, 457414c70cbSLiam Girdwood struct device_attribute *attr, char *buf) 458414c70cbSLiam Girdwood { 459a5766f11SLiam Girdwood struct regulator_dev *rdev = dev_get_drvdata(dev); 460414c70cbSLiam Girdwood struct regulator *regulator; 461414c70cbSLiam Girdwood int uA = 0; 462414c70cbSLiam Girdwood 463414c70cbSLiam Girdwood mutex_lock(&rdev->mutex); 464414c70cbSLiam Girdwood list_for_each_entry(regulator, &rdev->consumer_list, list) 465414c70cbSLiam Girdwood uA += regulator->uA_load; 466414c70cbSLiam Girdwood mutex_unlock(&rdev->mutex); 467414c70cbSLiam Girdwood return sprintf(buf, "%d\n", uA); 468414c70cbSLiam Girdwood } 4697ad68e2fSDavid Brownell static DEVICE_ATTR(requested_microamps, 0444, regulator_total_uA_show, NULL); 470414c70cbSLiam Girdwood 471414c70cbSLiam Girdwood static ssize_t regulator_num_users_show(struct device *dev, 472414c70cbSLiam Girdwood struct device_attribute *attr, char *buf) 473414c70cbSLiam Girdwood { 474a5766f11SLiam Girdwood struct regulator_dev *rdev = dev_get_drvdata(dev); 475414c70cbSLiam Girdwood return sprintf(buf, "%d\n", rdev->use_count); 476414c70cbSLiam Girdwood } 477414c70cbSLiam Girdwood 478414c70cbSLiam Girdwood static ssize_t regulator_type_show(struct device *dev, 479414c70cbSLiam Girdwood struct device_attribute *attr, char *buf) 480414c70cbSLiam Girdwood { 481a5766f11SLiam Girdwood struct regulator_dev *rdev = dev_get_drvdata(dev); 482414c70cbSLiam Girdwood 483414c70cbSLiam Girdwood switch (rdev->desc->type) { 484414c70cbSLiam Girdwood case REGULATOR_VOLTAGE: 485414c70cbSLiam Girdwood return sprintf(buf, "voltage\n"); 486414c70cbSLiam Girdwood case REGULATOR_CURRENT: 487414c70cbSLiam Girdwood return sprintf(buf, "current\n"); 488414c70cbSLiam Girdwood } 489414c70cbSLiam Girdwood return sprintf(buf, "unknown\n"); 490414c70cbSLiam Girdwood } 491414c70cbSLiam Girdwood 492414c70cbSLiam Girdwood static ssize_t regulator_suspend_mem_uV_show(struct device *dev, 493414c70cbSLiam Girdwood struct device_attribute *attr, char *buf) 494414c70cbSLiam Girdwood { 495a5766f11SLiam Girdwood struct regulator_dev *rdev = dev_get_drvdata(dev); 496414c70cbSLiam Girdwood 497414c70cbSLiam Girdwood return sprintf(buf, "%d\n", rdev->constraints->state_mem.uV); 498414c70cbSLiam Girdwood } 4997ad68e2fSDavid Brownell static DEVICE_ATTR(suspend_mem_microvolts, 0444, 5007ad68e2fSDavid Brownell regulator_suspend_mem_uV_show, NULL); 501414c70cbSLiam Girdwood 502414c70cbSLiam Girdwood static ssize_t regulator_suspend_disk_uV_show(struct device *dev, 503414c70cbSLiam Girdwood struct device_attribute *attr, char *buf) 504414c70cbSLiam Girdwood { 505a5766f11SLiam Girdwood struct regulator_dev *rdev = dev_get_drvdata(dev); 506414c70cbSLiam Girdwood 507414c70cbSLiam Girdwood return sprintf(buf, "%d\n", rdev->constraints->state_disk.uV); 508414c70cbSLiam Girdwood } 5097ad68e2fSDavid Brownell static DEVICE_ATTR(suspend_disk_microvolts, 0444, 5107ad68e2fSDavid Brownell regulator_suspend_disk_uV_show, NULL); 511414c70cbSLiam Girdwood 512414c70cbSLiam Girdwood static ssize_t regulator_suspend_standby_uV_show(struct device *dev, 513414c70cbSLiam Girdwood struct device_attribute *attr, char *buf) 514414c70cbSLiam Girdwood { 515a5766f11SLiam Girdwood struct regulator_dev *rdev = dev_get_drvdata(dev); 516414c70cbSLiam Girdwood 517414c70cbSLiam Girdwood return sprintf(buf, "%d\n", rdev->constraints->state_standby.uV); 518414c70cbSLiam Girdwood } 5197ad68e2fSDavid Brownell static DEVICE_ATTR(suspend_standby_microvolts, 0444, 5207ad68e2fSDavid Brownell regulator_suspend_standby_uV_show, NULL); 521414c70cbSLiam Girdwood 522414c70cbSLiam Girdwood static ssize_t regulator_suspend_mem_mode_show(struct device *dev, 523414c70cbSLiam Girdwood struct device_attribute *attr, char *buf) 524414c70cbSLiam Girdwood { 525a5766f11SLiam Girdwood struct regulator_dev *rdev = dev_get_drvdata(dev); 526414c70cbSLiam Girdwood 5274fca9545SDavid Brownell return regulator_print_opmode(buf, 5284fca9545SDavid Brownell rdev->constraints->state_mem.mode); 529414c70cbSLiam Girdwood } 5307ad68e2fSDavid Brownell static DEVICE_ATTR(suspend_mem_mode, 0444, 5317ad68e2fSDavid Brownell regulator_suspend_mem_mode_show, NULL); 532414c70cbSLiam Girdwood 533414c70cbSLiam Girdwood static ssize_t regulator_suspend_disk_mode_show(struct device *dev, 534414c70cbSLiam Girdwood struct device_attribute *attr, char *buf) 535414c70cbSLiam Girdwood { 536a5766f11SLiam Girdwood struct regulator_dev *rdev = dev_get_drvdata(dev); 537414c70cbSLiam Girdwood 5384fca9545SDavid Brownell return regulator_print_opmode(buf, 5394fca9545SDavid Brownell rdev->constraints->state_disk.mode); 540414c70cbSLiam Girdwood } 5417ad68e2fSDavid Brownell static DEVICE_ATTR(suspend_disk_mode, 0444, 5427ad68e2fSDavid Brownell regulator_suspend_disk_mode_show, NULL); 543414c70cbSLiam Girdwood 544414c70cbSLiam Girdwood static ssize_t regulator_suspend_standby_mode_show(struct device *dev, 545414c70cbSLiam Girdwood struct device_attribute *attr, char *buf) 546414c70cbSLiam Girdwood { 547a5766f11SLiam Girdwood struct regulator_dev *rdev = dev_get_drvdata(dev); 548414c70cbSLiam Girdwood 5494fca9545SDavid Brownell return regulator_print_opmode(buf, 5504fca9545SDavid Brownell rdev->constraints->state_standby.mode); 551414c70cbSLiam Girdwood } 5527ad68e2fSDavid Brownell static DEVICE_ATTR(suspend_standby_mode, 0444, 5537ad68e2fSDavid Brownell regulator_suspend_standby_mode_show, NULL); 554414c70cbSLiam Girdwood 555414c70cbSLiam Girdwood static ssize_t regulator_suspend_mem_state_show(struct device *dev, 556414c70cbSLiam Girdwood struct device_attribute *attr, char *buf) 557414c70cbSLiam Girdwood { 558a5766f11SLiam Girdwood struct regulator_dev *rdev = dev_get_drvdata(dev); 559414c70cbSLiam Girdwood 5604fca9545SDavid Brownell return regulator_print_state(buf, 5614fca9545SDavid Brownell rdev->constraints->state_mem.enabled); 562414c70cbSLiam Girdwood } 5637ad68e2fSDavid Brownell static DEVICE_ATTR(suspend_mem_state, 0444, 5647ad68e2fSDavid Brownell regulator_suspend_mem_state_show, NULL); 565414c70cbSLiam Girdwood 566414c70cbSLiam Girdwood static ssize_t regulator_suspend_disk_state_show(struct device *dev, 567414c70cbSLiam Girdwood struct device_attribute *attr, char *buf) 568414c70cbSLiam Girdwood { 569a5766f11SLiam Girdwood struct regulator_dev *rdev = dev_get_drvdata(dev); 570414c70cbSLiam Girdwood 5714fca9545SDavid Brownell return regulator_print_state(buf, 5724fca9545SDavid Brownell rdev->constraints->state_disk.enabled); 573414c70cbSLiam Girdwood } 5747ad68e2fSDavid Brownell static DEVICE_ATTR(suspend_disk_state, 0444, 5757ad68e2fSDavid Brownell regulator_suspend_disk_state_show, NULL); 576414c70cbSLiam Girdwood 577414c70cbSLiam Girdwood static ssize_t regulator_suspend_standby_state_show(struct device *dev, 578414c70cbSLiam Girdwood struct device_attribute *attr, char *buf) 579414c70cbSLiam Girdwood { 580a5766f11SLiam Girdwood struct regulator_dev *rdev = dev_get_drvdata(dev); 581414c70cbSLiam Girdwood 5824fca9545SDavid Brownell return regulator_print_state(buf, 5834fca9545SDavid Brownell rdev->constraints->state_standby.enabled); 584414c70cbSLiam Girdwood } 5857ad68e2fSDavid Brownell static DEVICE_ATTR(suspend_standby_state, 0444, 5867ad68e2fSDavid Brownell regulator_suspend_standby_state_show, NULL); 587bc558a60SMark Brown 5887ad68e2fSDavid Brownell 5897ad68e2fSDavid Brownell /* 5907ad68e2fSDavid Brownell * These are the only attributes are present for all regulators. 5917ad68e2fSDavid Brownell * Other attributes are a function of regulator functionality. 5927ad68e2fSDavid Brownell */ 593414c70cbSLiam Girdwood static struct device_attribute regulator_dev_attrs[] = { 594bc558a60SMark Brown __ATTR(name, 0444, regulator_name_show, NULL), 595414c70cbSLiam Girdwood __ATTR(num_users, 0444, regulator_num_users_show, NULL), 596414c70cbSLiam Girdwood __ATTR(type, 0444, regulator_type_show, NULL), 597414c70cbSLiam Girdwood __ATTR_NULL, 598414c70cbSLiam Girdwood }; 599414c70cbSLiam Girdwood 600414c70cbSLiam Girdwood static void regulator_dev_release(struct device *dev) 601414c70cbSLiam Girdwood { 602a5766f11SLiam Girdwood struct regulator_dev *rdev = dev_get_drvdata(dev); 603414c70cbSLiam Girdwood kfree(rdev); 604414c70cbSLiam Girdwood } 605414c70cbSLiam Girdwood 606414c70cbSLiam Girdwood static struct class regulator_class = { 607414c70cbSLiam Girdwood .name = "regulator", 608414c70cbSLiam Girdwood .dev_release = regulator_dev_release, 609414c70cbSLiam Girdwood .dev_attrs = regulator_dev_attrs, 610414c70cbSLiam Girdwood }; 611414c70cbSLiam Girdwood 612414c70cbSLiam Girdwood /* Calculate the new optimum regulator operating mode based on the new total 613414c70cbSLiam Girdwood * consumer load. All locks held by caller */ 614414c70cbSLiam Girdwood static void drms_uA_update(struct regulator_dev *rdev) 615414c70cbSLiam Girdwood { 616414c70cbSLiam Girdwood struct regulator *sibling; 617414c70cbSLiam Girdwood int current_uA = 0, output_uV, input_uV, err; 618414c70cbSLiam Girdwood unsigned int mode; 619414c70cbSLiam Girdwood 620414c70cbSLiam Girdwood err = regulator_check_drms(rdev); 621414c70cbSLiam Girdwood if (err < 0 || !rdev->desc->ops->get_optimum_mode || 622476c2d83SMark Brown (!rdev->desc->ops->get_voltage && 623476c2d83SMark Brown !rdev->desc->ops->get_voltage_sel) || 624476c2d83SMark Brown !rdev->desc->ops->set_mode) 625414c70cbSLiam Girdwood return; 626414c70cbSLiam Girdwood 627414c70cbSLiam Girdwood /* get output voltage */ 6281bf5a1f8SMark Brown output_uV = _regulator_get_voltage(rdev); 629414c70cbSLiam Girdwood if (output_uV <= 0) 630414c70cbSLiam Girdwood return; 631414c70cbSLiam Girdwood 632414c70cbSLiam Girdwood /* get input voltage */ 6331bf5a1f8SMark Brown input_uV = 0; 6341bf5a1f8SMark Brown if (rdev->supply) 6353f24f5adSAxel Lin input_uV = regulator_get_voltage(rdev->supply); 6361bf5a1f8SMark Brown if (input_uV <= 0) 637414c70cbSLiam Girdwood input_uV = rdev->constraints->input_uV; 638414c70cbSLiam Girdwood if (input_uV <= 0) 639414c70cbSLiam Girdwood return; 640414c70cbSLiam Girdwood 641414c70cbSLiam Girdwood /* calc total requested load */ 642414c70cbSLiam Girdwood list_for_each_entry(sibling, &rdev->consumer_list, list) 643414c70cbSLiam Girdwood current_uA += sibling->uA_load; 644414c70cbSLiam Girdwood 645414c70cbSLiam Girdwood /* now get the optimum mode for our new total regulator load */ 646414c70cbSLiam Girdwood mode = rdev->desc->ops->get_optimum_mode(rdev, input_uV, 647414c70cbSLiam Girdwood output_uV, current_uA); 648414c70cbSLiam Girdwood 649414c70cbSLiam Girdwood /* check the new mode is allowed */ 6502c608234SMark Brown err = regulator_mode_constrain(rdev, &mode); 651414c70cbSLiam Girdwood if (err == 0) 652414c70cbSLiam Girdwood rdev->desc->ops->set_mode(rdev, mode); 653414c70cbSLiam Girdwood } 654414c70cbSLiam Girdwood 655414c70cbSLiam Girdwood static int suspend_set_state(struct regulator_dev *rdev, 656414c70cbSLiam Girdwood struct regulator_state *rstate) 657414c70cbSLiam Girdwood { 658414c70cbSLiam Girdwood int ret = 0; 659638f85c5SMark Brown 660638f85c5SMark Brown /* If we have no suspend mode configration don't set anything; 6618ac0e95dSAxel Lin * only warn if the driver implements set_suspend_voltage or 6628ac0e95dSAxel Lin * set_suspend_mode callback. 663638f85c5SMark Brown */ 664638f85c5SMark Brown if (!rstate->enabled && !rstate->disabled) { 6658ac0e95dSAxel Lin if (rdev->desc->ops->set_suspend_voltage || 6668ac0e95dSAxel Lin rdev->desc->ops->set_suspend_mode) 6675da84fd9SJoe Perches rdev_warn(rdev, "No configuration\n"); 668638f85c5SMark Brown return 0; 669638f85c5SMark Brown } 670638f85c5SMark Brown 671638f85c5SMark Brown if (rstate->enabled && rstate->disabled) { 6725da84fd9SJoe Perches rdev_err(rdev, "invalid configuration\n"); 673638f85c5SMark Brown return -EINVAL; 674638f85c5SMark Brown } 675638f85c5SMark Brown 6768ac0e95dSAxel Lin if (rstate->enabled && rdev->desc->ops->set_suspend_enable) 677414c70cbSLiam Girdwood ret = rdev->desc->ops->set_suspend_enable(rdev); 6788ac0e95dSAxel Lin else if (rstate->disabled && rdev->desc->ops->set_suspend_disable) 679414c70cbSLiam Girdwood ret = rdev->desc->ops->set_suspend_disable(rdev); 6808ac0e95dSAxel Lin else /* OK if set_suspend_enable or set_suspend_disable is NULL */ 6818ac0e95dSAxel Lin ret = 0; 6828ac0e95dSAxel Lin 683414c70cbSLiam Girdwood if (ret < 0) { 6845da84fd9SJoe Perches rdev_err(rdev, "failed to enabled/disable\n"); 685414c70cbSLiam Girdwood return ret; 686414c70cbSLiam Girdwood } 687414c70cbSLiam Girdwood 688414c70cbSLiam Girdwood if (rdev->desc->ops->set_suspend_voltage && rstate->uV > 0) { 689414c70cbSLiam Girdwood ret = rdev->desc->ops->set_suspend_voltage(rdev, rstate->uV); 690414c70cbSLiam Girdwood if (ret < 0) { 6915da84fd9SJoe Perches rdev_err(rdev, "failed to set voltage\n"); 692414c70cbSLiam Girdwood return ret; 693414c70cbSLiam Girdwood } 694414c70cbSLiam Girdwood } 695414c70cbSLiam Girdwood 696414c70cbSLiam Girdwood if (rdev->desc->ops->set_suspend_mode && rstate->mode > 0) { 697414c70cbSLiam Girdwood ret = rdev->desc->ops->set_suspend_mode(rdev, rstate->mode); 698414c70cbSLiam Girdwood if (ret < 0) { 6995da84fd9SJoe Perches rdev_err(rdev, "failed to set mode\n"); 700414c70cbSLiam Girdwood return ret; 701414c70cbSLiam Girdwood } 702414c70cbSLiam Girdwood } 703414c70cbSLiam Girdwood return ret; 704414c70cbSLiam Girdwood } 705414c70cbSLiam Girdwood 706414c70cbSLiam Girdwood /* locks held by caller */ 707414c70cbSLiam Girdwood static int suspend_prepare(struct regulator_dev *rdev, suspend_state_t state) 708414c70cbSLiam Girdwood { 709414c70cbSLiam Girdwood if (!rdev->constraints) 710414c70cbSLiam Girdwood return -EINVAL; 711414c70cbSLiam Girdwood 712414c70cbSLiam Girdwood switch (state) { 713414c70cbSLiam Girdwood case PM_SUSPEND_STANDBY: 714414c70cbSLiam Girdwood return suspend_set_state(rdev, 715414c70cbSLiam Girdwood &rdev->constraints->state_standby); 716414c70cbSLiam Girdwood case PM_SUSPEND_MEM: 717414c70cbSLiam Girdwood return suspend_set_state(rdev, 718414c70cbSLiam Girdwood &rdev->constraints->state_mem); 719414c70cbSLiam Girdwood case PM_SUSPEND_MAX: 720414c70cbSLiam Girdwood return suspend_set_state(rdev, 721414c70cbSLiam Girdwood &rdev->constraints->state_disk); 722414c70cbSLiam Girdwood default: 723414c70cbSLiam Girdwood return -EINVAL; 724414c70cbSLiam Girdwood } 725414c70cbSLiam Girdwood } 726414c70cbSLiam Girdwood 727414c70cbSLiam Girdwood static void print_constraints(struct regulator_dev *rdev) 728414c70cbSLiam Girdwood { 729414c70cbSLiam Girdwood struct regulation_constraints *constraints = rdev->constraints; 730973e9a27SMark Brown char buf[80] = ""; 7318f031b48SMark Brown int count = 0; 7328f031b48SMark Brown int ret; 733414c70cbSLiam Girdwood 7348f031b48SMark Brown if (constraints->min_uV && constraints->max_uV) { 735414c70cbSLiam Girdwood if (constraints->min_uV == constraints->max_uV) 7368f031b48SMark Brown count += sprintf(buf + count, "%d mV ", 737414c70cbSLiam Girdwood constraints->min_uV / 1000); 738414c70cbSLiam Girdwood else 7398f031b48SMark Brown count += sprintf(buf + count, "%d <--> %d mV ", 740414c70cbSLiam Girdwood constraints->min_uV / 1000, 741414c70cbSLiam Girdwood constraints->max_uV / 1000); 7428f031b48SMark Brown } 7438f031b48SMark Brown 7448f031b48SMark Brown if (!constraints->min_uV || 7458f031b48SMark Brown constraints->min_uV != constraints->max_uV) { 7468f031b48SMark Brown ret = _regulator_get_voltage(rdev); 7478f031b48SMark Brown if (ret > 0) 7488f031b48SMark Brown count += sprintf(buf + count, "at %d mV ", ret / 1000); 7498f031b48SMark Brown } 7508f031b48SMark Brown 751bf5892a8SMark Brown if (constraints->uV_offset) 752bf5892a8SMark Brown count += sprintf(buf, "%dmV offset ", 753bf5892a8SMark Brown constraints->uV_offset / 1000); 754bf5892a8SMark Brown 7558f031b48SMark Brown if (constraints->min_uA && constraints->max_uA) { 756414c70cbSLiam Girdwood if (constraints->min_uA == constraints->max_uA) 7578f031b48SMark Brown count += sprintf(buf + count, "%d mA ", 758414c70cbSLiam Girdwood constraints->min_uA / 1000); 759414c70cbSLiam Girdwood else 7608f031b48SMark Brown count += sprintf(buf + count, "%d <--> %d mA ", 761414c70cbSLiam Girdwood constraints->min_uA / 1000, 762414c70cbSLiam Girdwood constraints->max_uA / 1000); 763414c70cbSLiam Girdwood } 7648f031b48SMark Brown 7658f031b48SMark Brown if (!constraints->min_uA || 7668f031b48SMark Brown constraints->min_uA != constraints->max_uA) { 7678f031b48SMark Brown ret = _regulator_get_current_limit(rdev); 7688f031b48SMark Brown if (ret > 0) 769e4a6376bSCyril Chemparathy count += sprintf(buf + count, "at %d mA ", ret / 1000); 7708f031b48SMark Brown } 7718f031b48SMark Brown 772414c70cbSLiam Girdwood if (constraints->valid_modes_mask & REGULATOR_MODE_FAST) 773414c70cbSLiam Girdwood count += sprintf(buf + count, "fast "); 774414c70cbSLiam Girdwood if (constraints->valid_modes_mask & REGULATOR_MODE_NORMAL) 775414c70cbSLiam Girdwood count += sprintf(buf + count, "normal "); 776414c70cbSLiam Girdwood if (constraints->valid_modes_mask & REGULATOR_MODE_IDLE) 777414c70cbSLiam Girdwood count += sprintf(buf + count, "idle "); 778414c70cbSLiam Girdwood if (constraints->valid_modes_mask & REGULATOR_MODE_STANDBY) 779414c70cbSLiam Girdwood count += sprintf(buf + count, "standby"); 780414c70cbSLiam Girdwood 781215b8b05SUwe Kleine-König if (!count) 782215b8b05SUwe Kleine-König sprintf(buf, "no parameters"); 783215b8b05SUwe Kleine-König 78413ce29f8SMark Brown rdev_info(rdev, "%s\n", buf); 7854a682922SMark Brown 7864a682922SMark Brown if ((constraints->min_uV != constraints->max_uV) && 7874a682922SMark Brown !(constraints->valid_ops_mask & REGULATOR_CHANGE_VOLTAGE)) 7884a682922SMark Brown rdev_warn(rdev, 7894a682922SMark Brown "Voltage range but no REGULATOR_CHANGE_VOLTAGE\n"); 790414c70cbSLiam Girdwood } 791414c70cbSLiam Girdwood 792e79055d6SMark Brown static int machine_constraints_voltage(struct regulator_dev *rdev, 7931083c393SMark Brown struct regulation_constraints *constraints) 794e79055d6SMark Brown { 795e79055d6SMark Brown struct regulator_ops *ops = rdev->desc->ops; 796af5866c9SMark Brown int ret; 797af5866c9SMark Brown 798af5866c9SMark Brown /* do we need to apply the constraint voltage */ 799af5866c9SMark Brown if (rdev->constraints->apply_uV && 80075790251SMark Brown rdev->constraints->min_uV == rdev->constraints->max_uV) { 80175790251SMark Brown ret = _regulator_do_set_voltage(rdev, 8023a93f2a9SMark Brown rdev->constraints->min_uV, 80375790251SMark Brown rdev->constraints->max_uV); 804af5866c9SMark Brown if (ret < 0) { 8055da84fd9SJoe Perches rdev_err(rdev, "failed to apply %duV constraint\n", 8065da84fd9SJoe Perches rdev->constraints->min_uV); 807af5866c9SMark Brown return ret; 808af5866c9SMark Brown } 809af5866c9SMark Brown } 810e79055d6SMark Brown 811e79055d6SMark Brown /* constrain machine-level voltage specs to fit 812e79055d6SMark Brown * the actual range supported by this regulator. 813e79055d6SMark Brown */ 814e79055d6SMark Brown if (ops->list_voltage && rdev->desc->n_voltages) { 815e79055d6SMark Brown int count = rdev->desc->n_voltages; 816e79055d6SMark Brown int i; 817e79055d6SMark Brown int min_uV = INT_MAX; 818e79055d6SMark Brown int max_uV = INT_MIN; 819e79055d6SMark Brown int cmin = constraints->min_uV; 820e79055d6SMark Brown int cmax = constraints->max_uV; 821e79055d6SMark Brown 822e79055d6SMark Brown /* it's safe to autoconfigure fixed-voltage supplies 823e79055d6SMark Brown and the constraints are used by list_voltage. */ 824e79055d6SMark Brown if (count == 1 && !cmin) { 825e79055d6SMark Brown cmin = 1; 826e79055d6SMark Brown cmax = INT_MAX; 827e79055d6SMark Brown constraints->min_uV = cmin; 828e79055d6SMark Brown constraints->max_uV = cmax; 829e79055d6SMark Brown } 830e79055d6SMark Brown 831e79055d6SMark Brown /* voltage constraints are optional */ 832e79055d6SMark Brown if ((cmin == 0) && (cmax == 0)) 833e79055d6SMark Brown return 0; 834e79055d6SMark Brown 835e79055d6SMark Brown /* else require explicit machine-level constraints */ 836e79055d6SMark Brown if (cmin <= 0 || cmax <= 0 || cmax < cmin) { 8375da84fd9SJoe Perches rdev_err(rdev, "invalid voltage constraints\n"); 838e79055d6SMark Brown return -EINVAL; 839e79055d6SMark Brown } 840e79055d6SMark Brown 841e79055d6SMark Brown /* initial: [cmin..cmax] valid, [min_uV..max_uV] not */ 842e79055d6SMark Brown for (i = 0; i < count; i++) { 843e79055d6SMark Brown int value; 844e79055d6SMark Brown 845e79055d6SMark Brown value = ops->list_voltage(rdev, i); 846e79055d6SMark Brown if (value <= 0) 847e79055d6SMark Brown continue; 848e79055d6SMark Brown 849e79055d6SMark Brown /* maybe adjust [min_uV..max_uV] */ 850e79055d6SMark Brown if (value >= cmin && value < min_uV) 851e79055d6SMark Brown min_uV = value; 852e79055d6SMark Brown if (value <= cmax && value > max_uV) 853e79055d6SMark Brown max_uV = value; 854e79055d6SMark Brown } 855e79055d6SMark Brown 856e79055d6SMark Brown /* final: [min_uV..max_uV] valid iff constraints valid */ 857e79055d6SMark Brown if (max_uV < min_uV) { 8585da84fd9SJoe Perches rdev_err(rdev, "unsupportable voltage constraints\n"); 859e79055d6SMark Brown return -EINVAL; 860e79055d6SMark Brown } 861e79055d6SMark Brown 862e79055d6SMark Brown /* use regulator's subset of machine constraints */ 863e79055d6SMark Brown if (constraints->min_uV < min_uV) { 8645da84fd9SJoe Perches rdev_dbg(rdev, "override min_uV, %d -> %d\n", 8655da84fd9SJoe Perches constraints->min_uV, min_uV); 866e79055d6SMark Brown constraints->min_uV = min_uV; 867e79055d6SMark Brown } 868e79055d6SMark Brown if (constraints->max_uV > max_uV) { 8695da84fd9SJoe Perches rdev_dbg(rdev, "override max_uV, %d -> %d\n", 8705da84fd9SJoe Perches constraints->max_uV, max_uV); 871e79055d6SMark Brown constraints->max_uV = max_uV; 872e79055d6SMark Brown } 873e79055d6SMark Brown } 874e79055d6SMark Brown 875e79055d6SMark Brown return 0; 876e79055d6SMark Brown } 877e79055d6SMark Brown 878a5766f11SLiam Girdwood /** 879a5766f11SLiam Girdwood * set_machine_constraints - sets regulator constraints 88069279fb9SMark Brown * @rdev: regulator source 881c8e7e464SMark Brown * @constraints: constraints to apply 882a5766f11SLiam Girdwood * 883a5766f11SLiam Girdwood * Allows platform initialisation code to define and constrain 884a5766f11SLiam Girdwood * regulator circuits e.g. valid voltage/current ranges, etc. NOTE: 885a5766f11SLiam Girdwood * Constraints *must* be set by platform code in order for some 886a5766f11SLiam Girdwood * regulator operations to proceed i.e. set_voltage, set_current_limit, 887a5766f11SLiam Girdwood * set_mode. 888a5766f11SLiam Girdwood */ 889a5766f11SLiam Girdwood static int set_machine_constraints(struct regulator_dev *rdev, 890f8c12fe3SMark Brown const struct regulation_constraints *constraints) 891a5766f11SLiam Girdwood { 892a5766f11SLiam Girdwood int ret = 0; 893e5fda26cSMark Brown struct regulator_ops *ops = rdev->desc->ops; 894e06f5b4fSMark Brown 8959a8f5e07SMark Brown if (constraints) 896f8c12fe3SMark Brown rdev->constraints = kmemdup(constraints, sizeof(*constraints), 897f8c12fe3SMark Brown GFP_KERNEL); 8989a8f5e07SMark Brown else 8999a8f5e07SMark Brown rdev->constraints = kzalloc(sizeof(*constraints), 9009a8f5e07SMark Brown GFP_KERNEL); 901f8c12fe3SMark Brown if (!rdev->constraints) 902f8c12fe3SMark Brown return -ENOMEM; 903af5866c9SMark Brown 904f8c12fe3SMark Brown ret = machine_constraints_voltage(rdev, rdev->constraints); 905e79055d6SMark Brown if (ret != 0) 9063e2b9abdSMark Brown goto out; 9073e2b9abdSMark Brown 908a5766f11SLiam Girdwood /* do we need to setup our suspend state */ 9099a8f5e07SMark Brown if (rdev->constraints->initial_state) { 910f8c12fe3SMark Brown ret = suspend_prepare(rdev, rdev->constraints->initial_state); 911e06f5b4fSMark Brown if (ret < 0) { 9125da84fd9SJoe Perches rdev_err(rdev, "failed to set suspend state\n"); 913e06f5b4fSMark Brown goto out; 914e06f5b4fSMark Brown } 915e06f5b4fSMark Brown } 916a5766f11SLiam Girdwood 9179a8f5e07SMark Brown if (rdev->constraints->initial_mode) { 918a308466cSMark Brown if (!ops->set_mode) { 9195da84fd9SJoe Perches rdev_err(rdev, "no set_mode operation\n"); 920a308466cSMark Brown ret = -EINVAL; 921a308466cSMark Brown goto out; 922a308466cSMark Brown } 923a308466cSMark Brown 924f8c12fe3SMark Brown ret = ops->set_mode(rdev, rdev->constraints->initial_mode); 925a308466cSMark Brown if (ret < 0) { 9265da84fd9SJoe Perches rdev_err(rdev, "failed to set initial mode: %d\n", ret); 927a308466cSMark Brown goto out; 928a308466cSMark Brown } 929a308466cSMark Brown } 930a308466cSMark Brown 931cacf90f2SMark Brown /* If the constraints say the regulator should be on at this point 932cacf90f2SMark Brown * and we have control then make sure it is enabled. 933cacf90f2SMark Brown */ 934f8c12fe3SMark Brown if ((rdev->constraints->always_on || rdev->constraints->boot_on) && 935f8c12fe3SMark Brown ops->enable) { 936e5fda26cSMark Brown ret = ops->enable(rdev); 937e5fda26cSMark Brown if (ret < 0) { 9385da84fd9SJoe Perches rdev_err(rdev, "failed to enable\n"); 939e5fda26cSMark Brown goto out; 940e5fda26cSMark Brown } 941e5fda26cSMark Brown } 942e5fda26cSMark Brown 9436f0b2c69SYadwinder Singh Brar if (rdev->constraints->ramp_delay && ops->set_ramp_delay) { 9446f0b2c69SYadwinder Singh Brar ret = ops->set_ramp_delay(rdev, rdev->constraints->ramp_delay); 9456f0b2c69SYadwinder Singh Brar if (ret < 0) { 9466f0b2c69SYadwinder Singh Brar rdev_err(rdev, "failed to set ramp_delay\n"); 9476f0b2c69SYadwinder Singh Brar goto out; 9486f0b2c69SYadwinder Singh Brar } 9496f0b2c69SYadwinder Singh Brar } 9506f0b2c69SYadwinder Singh Brar 951a5766f11SLiam Girdwood print_constraints(rdev); 9521a6958e7SAxel Lin return 0; 953a5766f11SLiam Girdwood out: 9541a6958e7SAxel Lin kfree(rdev->constraints); 9551a6958e7SAxel Lin rdev->constraints = NULL; 956a5766f11SLiam Girdwood return ret; 957a5766f11SLiam Girdwood } 958a5766f11SLiam Girdwood 959a5766f11SLiam Girdwood /** 960a5766f11SLiam Girdwood * set_supply - set regulator supply regulator 96169279fb9SMark Brown * @rdev: regulator name 96269279fb9SMark Brown * @supply_rdev: supply regulator name 963a5766f11SLiam Girdwood * 964a5766f11SLiam Girdwood * Called by platform initialisation code to set the supply regulator for this 965a5766f11SLiam Girdwood * regulator. This ensures that a regulators supply will also be enabled by the 966a5766f11SLiam Girdwood * core if it's child is enabled. 967a5766f11SLiam Girdwood */ 968a5766f11SLiam Girdwood static int set_supply(struct regulator_dev *rdev, 969a5766f11SLiam Girdwood struct regulator_dev *supply_rdev) 970a5766f11SLiam Girdwood { 971a5766f11SLiam Girdwood int err; 972a5766f11SLiam Girdwood 9733801b86aSMark Brown rdev_info(rdev, "supplied by %s\n", rdev_get_name(supply_rdev)); 9743801b86aSMark Brown 9753801b86aSMark Brown rdev->supply = create_regulator(supply_rdev, &rdev->dev, "SUPPLY"); 97632c78de8SAxel Lin if (rdev->supply == NULL) { 97732c78de8SAxel Lin err = -ENOMEM; 978a5766f11SLiam Girdwood return err; 979a5766f11SLiam Girdwood } 98057ad526aSLaxman Dewangan supply_rdev->open_count++; 981a5766f11SLiam Girdwood 9823801b86aSMark Brown return 0; 9833801b86aSMark Brown } 9843801b86aSMark Brown 985a5766f11SLiam Girdwood /** 98606c63f93SRandy Dunlap * set_consumer_device_supply - Bind a regulator to a symbolic supply 98769279fb9SMark Brown * @rdev: regulator source 98840f9244fSMark Brown * @consumer_dev_name: dev_name() string for device supply applies to 989a5766f11SLiam Girdwood * @supply: symbolic name for supply 990a5766f11SLiam Girdwood * 991a5766f11SLiam Girdwood * Allows platform initialisation code to map physical regulator 992a5766f11SLiam Girdwood * sources to symbolic names for supplies for use by devices. Devices 993a5766f11SLiam Girdwood * should use these symbolic names to request regulators, avoiding the 994a5766f11SLiam Girdwood * need to provide board-specific regulator names as platform data. 995a5766f11SLiam Girdwood */ 996a5766f11SLiam Girdwood static int set_consumer_device_supply(struct regulator_dev *rdev, 997737f360dSMark Brown const char *consumer_dev_name, 99840f9244fSMark Brown const char *supply) 999a5766f11SLiam Girdwood { 1000a5766f11SLiam Girdwood struct regulator_map *node; 10019ed2099eSMark Brown int has_dev; 1002a5766f11SLiam Girdwood 1003a5766f11SLiam Girdwood if (supply == NULL) 1004a5766f11SLiam Girdwood return -EINVAL; 1005a5766f11SLiam Girdwood 10069ed2099eSMark Brown if (consumer_dev_name != NULL) 10079ed2099eSMark Brown has_dev = 1; 10089ed2099eSMark Brown else 10099ed2099eSMark Brown has_dev = 0; 10109ed2099eSMark Brown 10116001e13cSDavid Brownell list_for_each_entry(node, ®ulator_map_list, list) { 101223b5cc2aSJani Nikula if (node->dev_name && consumer_dev_name) { 101323b5cc2aSJani Nikula if (strcmp(node->dev_name, consumer_dev_name) != 0) 10146001e13cSDavid Brownell continue; 101523b5cc2aSJani Nikula } else if (node->dev_name || consumer_dev_name) { 101623b5cc2aSJani Nikula continue; 101723b5cc2aSJani Nikula } 101823b5cc2aSJani Nikula 10196001e13cSDavid Brownell if (strcmp(node->supply, supply) != 0) 10206001e13cSDavid Brownell continue; 10216001e13cSDavid Brownell 1022737f360dSMark Brown pr_debug("%s: %s/%s is '%s' supply; fail %s/%s\n", 1023737f360dSMark Brown consumer_dev_name, 10246001e13cSDavid Brownell dev_name(&node->regulator->dev), 10256001e13cSDavid Brownell node->regulator->desc->name, 10266001e13cSDavid Brownell supply, 10271083c393SMark Brown dev_name(&rdev->dev), rdev_get_name(rdev)); 10286001e13cSDavid Brownell return -EBUSY; 10296001e13cSDavid Brownell } 10306001e13cSDavid Brownell 10319ed2099eSMark Brown node = kzalloc(sizeof(struct regulator_map), GFP_KERNEL); 1032a5766f11SLiam Girdwood if (node == NULL) 1033a5766f11SLiam Girdwood return -ENOMEM; 1034a5766f11SLiam Girdwood 1035a5766f11SLiam Girdwood node->regulator = rdev; 1036a5766f11SLiam Girdwood node->supply = supply; 1037a5766f11SLiam Girdwood 10389ed2099eSMark Brown if (has_dev) { 10399ed2099eSMark Brown node->dev_name = kstrdup(consumer_dev_name, GFP_KERNEL); 104040f9244fSMark Brown if (node->dev_name == NULL) { 104140f9244fSMark Brown kfree(node); 104240f9244fSMark Brown return -ENOMEM; 104340f9244fSMark Brown } 10449ed2099eSMark Brown } 104540f9244fSMark Brown 1046a5766f11SLiam Girdwood list_add(&node->list, ®ulator_map_list); 1047a5766f11SLiam Girdwood return 0; 1048a5766f11SLiam Girdwood } 1049a5766f11SLiam Girdwood 10500f1d747bSMike Rapoport static void unset_regulator_supplies(struct regulator_dev *rdev) 10510f1d747bSMike Rapoport { 10520f1d747bSMike Rapoport struct regulator_map *node, *n; 10530f1d747bSMike Rapoport 10540f1d747bSMike Rapoport list_for_each_entry_safe(node, n, ®ulator_map_list, list) { 10550f1d747bSMike Rapoport if (rdev == node->regulator) { 10560f1d747bSMike Rapoport list_del(&node->list); 105740f9244fSMark Brown kfree(node->dev_name); 10580f1d747bSMike Rapoport kfree(node); 10590f1d747bSMike Rapoport } 10600f1d747bSMike Rapoport } 10610f1d747bSMike Rapoport } 10620f1d747bSMike Rapoport 1063f5726ae3SMark Brown #define REG_STR_SIZE 64 1064414c70cbSLiam Girdwood 1065414c70cbSLiam Girdwood static struct regulator *create_regulator(struct regulator_dev *rdev, 1066414c70cbSLiam Girdwood struct device *dev, 1067414c70cbSLiam Girdwood const char *supply_name) 1068414c70cbSLiam Girdwood { 1069414c70cbSLiam Girdwood struct regulator *regulator; 1070414c70cbSLiam Girdwood char buf[REG_STR_SIZE]; 1071414c70cbSLiam Girdwood int err, size; 1072414c70cbSLiam Girdwood 1073414c70cbSLiam Girdwood regulator = kzalloc(sizeof(*regulator), GFP_KERNEL); 1074414c70cbSLiam Girdwood if (regulator == NULL) 1075414c70cbSLiam Girdwood return NULL; 1076414c70cbSLiam Girdwood 1077414c70cbSLiam Girdwood mutex_lock(&rdev->mutex); 1078414c70cbSLiam Girdwood regulator->rdev = rdev; 1079414c70cbSLiam Girdwood list_add(®ulator->list, &rdev->consumer_list); 1080414c70cbSLiam Girdwood 1081414c70cbSLiam Girdwood if (dev) { 1082e2c98eafSShawn Guo regulator->dev = dev; 1083e2c98eafSShawn Guo 1084222cc7b1SMark Brown /* Add a link to the device sysfs entry */ 1085414c70cbSLiam Girdwood size = scnprintf(buf, REG_STR_SIZE, "%s-%s", 1086414c70cbSLiam Girdwood dev->kobj.name, supply_name); 1087414c70cbSLiam Girdwood if (size >= REG_STR_SIZE) 1088222cc7b1SMark Brown goto overflow_err; 1089414c70cbSLiam Girdwood 1090414c70cbSLiam Girdwood regulator->supply_name = kstrdup(buf, GFP_KERNEL); 1091414c70cbSLiam Girdwood if (regulator->supply_name == NULL) 1092222cc7b1SMark Brown goto overflow_err; 1093414c70cbSLiam Girdwood 1094414c70cbSLiam Girdwood err = sysfs_create_link(&rdev->dev.kobj, &dev->kobj, 1095414c70cbSLiam Girdwood buf); 1096414c70cbSLiam Girdwood if (err) { 10975da84fd9SJoe Perches rdev_warn(rdev, "could not add device link %s err %d\n", 10981d7372e1SDaniel Walker dev->kobj.name, err); 1099222cc7b1SMark Brown /* non-fatal */ 1100414c70cbSLiam Girdwood } 11015de70519SMark Brown } else { 11025de70519SMark Brown regulator->supply_name = kstrdup(supply_name, GFP_KERNEL); 11035de70519SMark Brown if (regulator->supply_name == NULL) 1104222cc7b1SMark Brown goto overflow_err; 1105414c70cbSLiam Girdwood } 11065de70519SMark Brown 11075de70519SMark Brown regulator->debugfs = debugfs_create_dir(regulator->supply_name, 11085de70519SMark Brown rdev->debugfs); 110924751434SStephen Boyd if (!regulator->debugfs) { 11105de70519SMark Brown rdev_warn(rdev, "Failed to create debugfs directory\n"); 11115de70519SMark Brown } else { 11125de70519SMark Brown debugfs_create_u32("uA_load", 0444, regulator->debugfs, 11135de70519SMark Brown ®ulator->uA_load); 11145de70519SMark Brown debugfs_create_u32("min_uV", 0444, regulator->debugfs, 11155de70519SMark Brown ®ulator->min_uV); 11165de70519SMark Brown debugfs_create_u32("max_uV", 0444, regulator->debugfs, 11175de70519SMark Brown ®ulator->max_uV); 11185de70519SMark Brown } 11195de70519SMark Brown 11206492bc1bSMark Brown /* 11216492bc1bSMark Brown * Check now if the regulator is an always on regulator - if 11226492bc1bSMark Brown * it is then we don't need to do nearly so much work for 11236492bc1bSMark Brown * enable/disable calls. 11246492bc1bSMark Brown */ 11256492bc1bSMark Brown if (!_regulator_can_change_status(rdev) && 11266492bc1bSMark Brown _regulator_is_enabled(rdev)) 11276492bc1bSMark Brown regulator->always_on = true; 11286492bc1bSMark Brown 1129414c70cbSLiam Girdwood mutex_unlock(&rdev->mutex); 1130414c70cbSLiam Girdwood return regulator; 1131414c70cbSLiam Girdwood overflow_err: 1132414c70cbSLiam Girdwood list_del(®ulator->list); 1133414c70cbSLiam Girdwood kfree(regulator); 1134414c70cbSLiam Girdwood mutex_unlock(&rdev->mutex); 1135414c70cbSLiam Girdwood return NULL; 1136414c70cbSLiam Girdwood } 1137414c70cbSLiam Girdwood 113831aae2beSMark Brown static int _regulator_get_enable_time(struct regulator_dev *rdev) 113931aae2beSMark Brown { 114031aae2beSMark Brown if (!rdev->desc->ops->enable_time) 114179511ed3SMark Brown return rdev->desc->enable_time; 114231aae2beSMark Brown return rdev->desc->ops->enable_time(rdev); 114331aae2beSMark Brown } 114431aae2beSMark Brown 114569511a45SRajendra Nayak static struct regulator_dev *regulator_dev_lookup(struct device *dev, 11466d191a5fSMark Brown const char *supply, 11476d191a5fSMark Brown int *ret) 114869511a45SRajendra Nayak { 114969511a45SRajendra Nayak struct regulator_dev *r; 115069511a45SRajendra Nayak struct device_node *node; 1151576ca436SMark Brown struct regulator_map *map; 1152576ca436SMark Brown const char *devname = NULL; 115369511a45SRajendra Nayak 115469511a45SRajendra Nayak /* first do a dt based lookup */ 115569511a45SRajendra Nayak if (dev && dev->of_node) { 115669511a45SRajendra Nayak node = of_get_regulator(dev, supply); 11576d191a5fSMark Brown if (node) { 115869511a45SRajendra Nayak list_for_each_entry(r, ®ulator_list, list) 115969511a45SRajendra Nayak if (r->dev.parent && 116069511a45SRajendra Nayak node == r->dev.of_node) 116169511a45SRajendra Nayak return r; 11626d191a5fSMark Brown } else { 11636d191a5fSMark Brown /* 11646d191a5fSMark Brown * If we couldn't even get the node then it's 11656d191a5fSMark Brown * not just that the device didn't register 11666d191a5fSMark Brown * yet, there's no node and we'll never 11676d191a5fSMark Brown * succeed. 11686d191a5fSMark Brown */ 11696d191a5fSMark Brown *ret = -ENODEV; 11706d191a5fSMark Brown } 117169511a45SRajendra Nayak } 117269511a45SRajendra Nayak 117369511a45SRajendra Nayak /* if not found, try doing it non-dt way */ 1174576ca436SMark Brown if (dev) 1175576ca436SMark Brown devname = dev_name(dev); 1176576ca436SMark Brown 117769511a45SRajendra Nayak list_for_each_entry(r, ®ulator_list, list) 117869511a45SRajendra Nayak if (strcmp(rdev_get_name(r), supply) == 0) 117969511a45SRajendra Nayak return r; 118069511a45SRajendra Nayak 1181576ca436SMark Brown list_for_each_entry(map, ®ulator_map_list, list) { 1182576ca436SMark Brown /* If the mapping has a device set up it must match */ 1183576ca436SMark Brown if (map->dev_name && 1184576ca436SMark Brown (!devname || strcmp(map->dev_name, devname))) 1185576ca436SMark Brown continue; 1186576ca436SMark Brown 1187576ca436SMark Brown if (strcmp(map->supply, supply) == 0) 1188576ca436SMark Brown return map->regulator; 1189576ca436SMark Brown } 1190576ca436SMark Brown 1191576ca436SMark Brown 119269511a45SRajendra Nayak return NULL; 119369511a45SRajendra Nayak } 119469511a45SRajendra Nayak 11955ffbd136SMark Brown /* Internal regulator request function */ 11965ffbd136SMark Brown static struct regulator *_regulator_get(struct device *dev, const char *id, 11975ffbd136SMark Brown int exclusive) 1198414c70cbSLiam Girdwood { 1199414c70cbSLiam Girdwood struct regulator_dev *rdev; 120004bf3011SMark Brown struct regulator *regulator = ERR_PTR(-EPROBE_DEFER); 120140f9244fSMark Brown const char *devname = NULL; 12025ffbd136SMark Brown int ret; 1203414c70cbSLiam Girdwood 1204414c70cbSLiam Girdwood if (id == NULL) { 12055da84fd9SJoe Perches pr_err("get() with no identifier\n"); 1206414c70cbSLiam Girdwood return regulator; 1207414c70cbSLiam Girdwood } 1208414c70cbSLiam Girdwood 120940f9244fSMark Brown if (dev) 121040f9244fSMark Brown devname = dev_name(dev); 121140f9244fSMark Brown 1212414c70cbSLiam Girdwood mutex_lock(®ulator_list_mutex); 1213414c70cbSLiam Girdwood 12146d191a5fSMark Brown rdev = regulator_dev_lookup(dev, id, &ret); 121569511a45SRajendra Nayak if (rdev) 121669511a45SRajendra Nayak goto found; 121769511a45SRajendra Nayak 1218688fe99aSMark Brown if (board_wants_dummy_regulator) { 1219688fe99aSMark Brown rdev = dummy_regulator_rdev; 1220688fe99aSMark Brown goto found; 1221688fe99aSMark Brown } 1222688fe99aSMark Brown 122334abbd68SMark Brown #ifdef CONFIG_REGULATOR_DUMMY 122434abbd68SMark Brown if (!devname) 122534abbd68SMark Brown devname = "deviceless"; 122634abbd68SMark Brown 122734abbd68SMark Brown /* If the board didn't flag that it was fully constrained then 122834abbd68SMark Brown * substitute in a dummy regulator so consumers can continue. 122934abbd68SMark Brown */ 123034abbd68SMark Brown if (!has_full_constraints) { 12315da84fd9SJoe Perches pr_warn("%s supply %s not found, using dummy regulator\n", 123234abbd68SMark Brown devname, id); 123334abbd68SMark Brown rdev = dummy_regulator_rdev; 123434abbd68SMark Brown goto found; 123534abbd68SMark Brown } 123634abbd68SMark Brown #endif 123734abbd68SMark Brown 1238414c70cbSLiam Girdwood mutex_unlock(®ulator_list_mutex); 1239414c70cbSLiam Girdwood return regulator; 1240414c70cbSLiam Girdwood 1241414c70cbSLiam Girdwood found: 12425ffbd136SMark Brown if (rdev->exclusive) { 12435ffbd136SMark Brown regulator = ERR_PTR(-EPERM); 12445ffbd136SMark Brown goto out; 12455ffbd136SMark Brown } 12465ffbd136SMark Brown 12475ffbd136SMark Brown if (exclusive && rdev->open_count) { 12485ffbd136SMark Brown regulator = ERR_PTR(-EBUSY); 12495ffbd136SMark Brown goto out; 12505ffbd136SMark Brown } 12515ffbd136SMark Brown 1252a5766f11SLiam Girdwood if (!try_module_get(rdev->owner)) 1253a5766f11SLiam Girdwood goto out; 1254a5766f11SLiam Girdwood 1255414c70cbSLiam Girdwood regulator = create_regulator(rdev, dev, id); 1256414c70cbSLiam Girdwood if (regulator == NULL) { 1257414c70cbSLiam Girdwood regulator = ERR_PTR(-ENOMEM); 1258414c70cbSLiam Girdwood module_put(rdev->owner); 1259bcda4321SAxel Lin goto out; 1260414c70cbSLiam Girdwood } 1261414c70cbSLiam Girdwood 12625ffbd136SMark Brown rdev->open_count++; 12635ffbd136SMark Brown if (exclusive) { 12645ffbd136SMark Brown rdev->exclusive = 1; 12655ffbd136SMark Brown 12665ffbd136SMark Brown ret = _regulator_is_enabled(rdev); 12675ffbd136SMark Brown if (ret > 0) 12685ffbd136SMark Brown rdev->use_count = 1; 12695ffbd136SMark Brown else 12705ffbd136SMark Brown rdev->use_count = 0; 12715ffbd136SMark Brown } 12725ffbd136SMark Brown 1273a5766f11SLiam Girdwood out: 1274414c70cbSLiam Girdwood mutex_unlock(®ulator_list_mutex); 12755ffbd136SMark Brown 1276414c70cbSLiam Girdwood return regulator; 1277414c70cbSLiam Girdwood } 12785ffbd136SMark Brown 12795ffbd136SMark Brown /** 12805ffbd136SMark Brown * regulator_get - lookup and obtain a reference to a regulator. 12815ffbd136SMark Brown * @dev: device for regulator "consumer" 12825ffbd136SMark Brown * @id: Supply name or regulator ID. 12835ffbd136SMark Brown * 12845ffbd136SMark Brown * Returns a struct regulator corresponding to the regulator producer, 12855ffbd136SMark Brown * or IS_ERR() condition containing errno. 12865ffbd136SMark Brown * 12875ffbd136SMark Brown * Use of supply names configured via regulator_set_device_supply() is 12885ffbd136SMark Brown * strongly encouraged. It is recommended that the supply name used 12895ffbd136SMark Brown * should match the name used for the supply and/or the relevant 12905ffbd136SMark Brown * device pins in the datasheet. 12915ffbd136SMark Brown */ 12925ffbd136SMark Brown struct regulator *regulator_get(struct device *dev, const char *id) 12935ffbd136SMark Brown { 12945ffbd136SMark Brown return _regulator_get(dev, id, 0); 12955ffbd136SMark Brown } 1296414c70cbSLiam Girdwood EXPORT_SYMBOL_GPL(regulator_get); 1297414c70cbSLiam Girdwood 1298070b9079SStephen Boyd static void devm_regulator_release(struct device *dev, void *res) 1299070b9079SStephen Boyd { 1300070b9079SStephen Boyd regulator_put(*(struct regulator **)res); 1301070b9079SStephen Boyd } 1302070b9079SStephen Boyd 1303070b9079SStephen Boyd /** 1304070b9079SStephen Boyd * devm_regulator_get - Resource managed regulator_get() 1305070b9079SStephen Boyd * @dev: device for regulator "consumer" 1306070b9079SStephen Boyd * @id: Supply name or regulator ID. 1307070b9079SStephen Boyd * 1308070b9079SStephen Boyd * Managed regulator_get(). Regulators returned from this function are 1309070b9079SStephen Boyd * automatically regulator_put() on driver detach. See regulator_get() for more 1310070b9079SStephen Boyd * information. 1311070b9079SStephen Boyd */ 1312070b9079SStephen Boyd struct regulator *devm_regulator_get(struct device *dev, const char *id) 1313070b9079SStephen Boyd { 1314070b9079SStephen Boyd struct regulator **ptr, *regulator; 1315070b9079SStephen Boyd 1316070b9079SStephen Boyd ptr = devres_alloc(devm_regulator_release, sizeof(*ptr), GFP_KERNEL); 1317070b9079SStephen Boyd if (!ptr) 1318070b9079SStephen Boyd return ERR_PTR(-ENOMEM); 1319070b9079SStephen Boyd 1320070b9079SStephen Boyd regulator = regulator_get(dev, id); 1321070b9079SStephen Boyd if (!IS_ERR(regulator)) { 1322070b9079SStephen Boyd *ptr = regulator; 1323070b9079SStephen Boyd devres_add(dev, ptr); 1324070b9079SStephen Boyd } else { 1325070b9079SStephen Boyd devres_free(ptr); 1326070b9079SStephen Boyd } 1327070b9079SStephen Boyd 1328070b9079SStephen Boyd return regulator; 1329070b9079SStephen Boyd } 1330070b9079SStephen Boyd EXPORT_SYMBOL_GPL(devm_regulator_get); 1331070b9079SStephen Boyd 1332414c70cbSLiam Girdwood /** 13335ffbd136SMark Brown * regulator_get_exclusive - obtain exclusive access to a regulator. 13345ffbd136SMark Brown * @dev: device for regulator "consumer" 13355ffbd136SMark Brown * @id: Supply name or regulator ID. 13365ffbd136SMark Brown * 13375ffbd136SMark Brown * Returns a struct regulator corresponding to the regulator producer, 13385ffbd136SMark Brown * or IS_ERR() condition containing errno. Other consumers will be 13395ffbd136SMark Brown * unable to obtain this reference is held and the use count for the 13405ffbd136SMark Brown * regulator will be initialised to reflect the current state of the 13415ffbd136SMark Brown * regulator. 13425ffbd136SMark Brown * 13435ffbd136SMark Brown * This is intended for use by consumers which cannot tolerate shared 13445ffbd136SMark Brown * use of the regulator such as those which need to force the 13455ffbd136SMark Brown * regulator off for correct operation of the hardware they are 13465ffbd136SMark Brown * controlling. 13475ffbd136SMark Brown * 13485ffbd136SMark Brown * Use of supply names configured via regulator_set_device_supply() is 13495ffbd136SMark Brown * strongly encouraged. It is recommended that the supply name used 13505ffbd136SMark Brown * should match the name used for the supply and/or the relevant 13515ffbd136SMark Brown * device pins in the datasheet. 13525ffbd136SMark Brown */ 13535ffbd136SMark Brown struct regulator *regulator_get_exclusive(struct device *dev, const char *id) 13545ffbd136SMark Brown { 13555ffbd136SMark Brown return _regulator_get(dev, id, 1); 13565ffbd136SMark Brown } 13575ffbd136SMark Brown EXPORT_SYMBOL_GPL(regulator_get_exclusive); 13585ffbd136SMark Brown 13595ffbd136SMark Brown /** 1360414c70cbSLiam Girdwood * regulator_put - "free" the regulator source 1361414c70cbSLiam Girdwood * @regulator: regulator source 1362414c70cbSLiam Girdwood * 1363414c70cbSLiam Girdwood * Note: drivers must ensure that all regulator_enable calls made on this 1364414c70cbSLiam Girdwood * regulator source are balanced by regulator_disable calls prior to calling 1365414c70cbSLiam Girdwood * this function. 1366414c70cbSLiam Girdwood */ 1367414c70cbSLiam Girdwood void regulator_put(struct regulator *regulator) 1368414c70cbSLiam Girdwood { 1369414c70cbSLiam Girdwood struct regulator_dev *rdev; 1370414c70cbSLiam Girdwood 1371414c70cbSLiam Girdwood if (regulator == NULL || IS_ERR(regulator)) 1372414c70cbSLiam Girdwood return; 1373414c70cbSLiam Girdwood 1374414c70cbSLiam Girdwood mutex_lock(®ulator_list_mutex); 1375414c70cbSLiam Girdwood rdev = regulator->rdev; 1376414c70cbSLiam Girdwood 13775de70519SMark Brown debugfs_remove_recursive(regulator->debugfs); 13785de70519SMark Brown 1379414c70cbSLiam Girdwood /* remove any sysfs entries */ 1380e2c98eafSShawn Guo if (regulator->dev) 1381414c70cbSLiam Girdwood sysfs_remove_link(&rdev->dev.kobj, regulator->supply_name); 13825de70519SMark Brown kfree(regulator->supply_name); 1383414c70cbSLiam Girdwood list_del(®ulator->list); 1384414c70cbSLiam Girdwood kfree(regulator); 1385414c70cbSLiam Girdwood 13865ffbd136SMark Brown rdev->open_count--; 13875ffbd136SMark Brown rdev->exclusive = 0; 13885ffbd136SMark Brown 1389414c70cbSLiam Girdwood module_put(rdev->owner); 1390414c70cbSLiam Girdwood mutex_unlock(®ulator_list_mutex); 1391414c70cbSLiam Girdwood } 1392414c70cbSLiam Girdwood EXPORT_SYMBOL_GPL(regulator_put); 1393414c70cbSLiam Girdwood 1394d5ad34f7SMark Brown static int devm_regulator_match(struct device *dev, void *res, void *data) 1395d5ad34f7SMark Brown { 1396d5ad34f7SMark Brown struct regulator **r = res; 1397d5ad34f7SMark Brown if (!r || !*r) { 1398d5ad34f7SMark Brown WARN_ON(!r || !*r); 1399d5ad34f7SMark Brown return 0; 1400d5ad34f7SMark Brown } 1401d5ad34f7SMark Brown return *r == data; 1402d5ad34f7SMark Brown } 1403d5ad34f7SMark Brown 1404d5ad34f7SMark Brown /** 1405d5ad34f7SMark Brown * devm_regulator_put - Resource managed regulator_put() 1406d5ad34f7SMark Brown * @regulator: regulator to free 1407d5ad34f7SMark Brown * 1408d5ad34f7SMark Brown * Deallocate a regulator allocated with devm_regulator_get(). Normally 1409d5ad34f7SMark Brown * this function will not need to be called and the resource management 1410d5ad34f7SMark Brown * code will ensure that the resource is freed. 1411d5ad34f7SMark Brown */ 1412d5ad34f7SMark Brown void devm_regulator_put(struct regulator *regulator) 1413d5ad34f7SMark Brown { 1414d5ad34f7SMark Brown int rc; 1415d5ad34f7SMark Brown 1416361ff501SMark Brown rc = devres_release(regulator->dev, devm_regulator_release, 1417d5ad34f7SMark Brown devm_regulator_match, regulator); 1418230a5a1cSMark Brown if (rc != 0) 1419d5ad34f7SMark Brown WARN_ON(rc); 1420d5ad34f7SMark Brown } 1421d5ad34f7SMark Brown EXPORT_SYMBOL_GPL(devm_regulator_put); 1422d5ad34f7SMark Brown 14235c5659d0SMark Brown static int _regulator_do_enable(struct regulator_dev *rdev) 14245c5659d0SMark Brown { 14255c5659d0SMark Brown int ret, delay; 14265c5659d0SMark Brown 14275c5659d0SMark Brown /* Query before enabling in case configuration dependent. */ 14285c5659d0SMark Brown ret = _regulator_get_enable_time(rdev); 14295c5659d0SMark Brown if (ret >= 0) { 14305c5659d0SMark Brown delay = ret; 14315c5659d0SMark Brown } else { 14325c5659d0SMark Brown rdev_warn(rdev, "enable_time() failed: %d\n", ret); 14335c5659d0SMark Brown delay = 0; 14345c5659d0SMark Brown } 14355c5659d0SMark Brown 14365c5659d0SMark Brown trace_regulator_enable(rdev_get_name(rdev)); 14375c5659d0SMark Brown 143865f73508SMark Brown if (rdev->ena_gpio) { 143965f73508SMark Brown gpio_set_value_cansleep(rdev->ena_gpio, 144065f73508SMark Brown !rdev->ena_gpio_invert); 144165f73508SMark Brown rdev->ena_gpio_state = 1; 144265f73508SMark Brown } else if (rdev->desc->ops->enable) { 14435c5659d0SMark Brown ret = rdev->desc->ops->enable(rdev); 14445c5659d0SMark Brown if (ret < 0) 14455c5659d0SMark Brown return ret; 14465c5659d0SMark Brown } else { 14475c5659d0SMark Brown return -EINVAL; 14485c5659d0SMark Brown } 14495c5659d0SMark Brown 14505c5659d0SMark Brown /* Allow the regulator to ramp; it would be useful to extend 14515c5659d0SMark Brown * this for bulk operations so that the regulators can ramp 14525c5659d0SMark Brown * together. */ 14535c5659d0SMark Brown trace_regulator_enable_delay(rdev_get_name(rdev)); 14545c5659d0SMark Brown 14555c5659d0SMark Brown if (delay >= 1000) { 14565c5659d0SMark Brown mdelay(delay / 1000); 14575c5659d0SMark Brown udelay(delay % 1000); 14585c5659d0SMark Brown } else if (delay) { 14595c5659d0SMark Brown udelay(delay); 14605c5659d0SMark Brown } 14615c5659d0SMark Brown 14625c5659d0SMark Brown trace_regulator_enable_complete(rdev_get_name(rdev)); 14635c5659d0SMark Brown 14645c5659d0SMark Brown return 0; 14655c5659d0SMark Brown } 14665c5659d0SMark Brown 1467414c70cbSLiam Girdwood /* locks held by regulator_enable() */ 1468414c70cbSLiam Girdwood static int _regulator_enable(struct regulator_dev *rdev) 1469414c70cbSLiam Girdwood { 14705c5659d0SMark Brown int ret; 1471414c70cbSLiam Girdwood 1472414c70cbSLiam Girdwood /* check voltage and requested load before enabling */ 1473414c70cbSLiam Girdwood if (rdev->constraints && 14749a2372faSMark Brown (rdev->constraints->valid_ops_mask & REGULATOR_CHANGE_DRMS)) 1475414c70cbSLiam Girdwood drms_uA_update(rdev); 1476414c70cbSLiam Girdwood 14779a2372faSMark Brown if (rdev->use_count == 0) { 14789a2372faSMark Brown /* The regulator may on if it's not switchable or left on */ 14799a2372faSMark Brown ret = _regulator_is_enabled(rdev); 14809a2372faSMark Brown if (ret == -EINVAL || ret == 0) { 14819a2372faSMark Brown if (!_regulator_can_change_status(rdev)) 14829a2372faSMark Brown return -EPERM; 14839a2372faSMark Brown 14845c5659d0SMark Brown ret = _regulator_do_enable(rdev); 14859a2372faSMark Brown if (ret < 0) 14869a2372faSMark Brown return ret; 148731aae2beSMark Brown 1488a7433cffSLinus Walleij } else if (ret < 0) { 14895da84fd9SJoe Perches rdev_err(rdev, "is_enabled() failed: %d\n", ret); 1490414c70cbSLiam Girdwood return ret; 1491414c70cbSLiam Girdwood } 1492a7433cffSLinus Walleij /* Fallthrough on positive return values - already enabled */ 1493414c70cbSLiam Girdwood } 1494414c70cbSLiam Girdwood 14959a2372faSMark Brown rdev->use_count++; 14969a2372faSMark Brown 14979a2372faSMark Brown return 0; 1498414c70cbSLiam Girdwood } 1499414c70cbSLiam Girdwood 1500414c70cbSLiam Girdwood /** 1501414c70cbSLiam Girdwood * regulator_enable - enable regulator output 1502414c70cbSLiam Girdwood * @regulator: regulator source 1503414c70cbSLiam Girdwood * 1504cf7bbcdfSMark Brown * Request that the regulator be enabled with the regulator output at 1505cf7bbcdfSMark Brown * the predefined voltage or current value. Calls to regulator_enable() 1506cf7bbcdfSMark Brown * must be balanced with calls to regulator_disable(). 1507cf7bbcdfSMark Brown * 1508414c70cbSLiam Girdwood * NOTE: the output value can be set by other drivers, boot loader or may be 1509cf7bbcdfSMark Brown * hardwired in the regulator. 1510414c70cbSLiam Girdwood */ 1511414c70cbSLiam Girdwood int regulator_enable(struct regulator *regulator) 1512414c70cbSLiam Girdwood { 1513412aec61SDavid Brownell struct regulator_dev *rdev = regulator->rdev; 1514412aec61SDavid Brownell int ret = 0; 1515414c70cbSLiam Girdwood 15166492bc1bSMark Brown if (regulator->always_on) 15176492bc1bSMark Brown return 0; 15186492bc1bSMark Brown 15193801b86aSMark Brown if (rdev->supply) { 15203801b86aSMark Brown ret = regulator_enable(rdev->supply); 15213801b86aSMark Brown if (ret != 0) 15223801b86aSMark Brown return ret; 15233801b86aSMark Brown } 15243801b86aSMark Brown 1525412aec61SDavid Brownell mutex_lock(&rdev->mutex); 1526412aec61SDavid Brownell ret = _regulator_enable(rdev); 1527412aec61SDavid Brownell mutex_unlock(&rdev->mutex); 15283801b86aSMark Brown 1529d1685e4eSHeiko Stübner if (ret != 0 && rdev->supply) 15303801b86aSMark Brown regulator_disable(rdev->supply); 15313801b86aSMark Brown 1532414c70cbSLiam Girdwood return ret; 1533414c70cbSLiam Girdwood } 1534414c70cbSLiam Girdwood EXPORT_SYMBOL_GPL(regulator_enable); 1535414c70cbSLiam Girdwood 15365c5659d0SMark Brown static int _regulator_do_disable(struct regulator_dev *rdev) 15375c5659d0SMark Brown { 15385c5659d0SMark Brown int ret; 15395c5659d0SMark Brown 15405c5659d0SMark Brown trace_regulator_disable(rdev_get_name(rdev)); 15415c5659d0SMark Brown 15425c5659d0SMark Brown if (rdev->ena_gpio) { 15435c5659d0SMark Brown gpio_set_value_cansleep(rdev->ena_gpio, 15445c5659d0SMark Brown rdev->ena_gpio_invert); 15455c5659d0SMark Brown rdev->ena_gpio_state = 0; 15465c5659d0SMark Brown 15475c5659d0SMark Brown } else if (rdev->desc->ops->disable) { 15485c5659d0SMark Brown ret = rdev->desc->ops->disable(rdev); 15495c5659d0SMark Brown if (ret != 0) 15505c5659d0SMark Brown return ret; 15515c5659d0SMark Brown } 15525c5659d0SMark Brown 15535c5659d0SMark Brown trace_regulator_disable_complete(rdev_get_name(rdev)); 15545c5659d0SMark Brown 15555c5659d0SMark Brown _notifier_call_chain(rdev, REGULATOR_EVENT_DISABLE, 15565c5659d0SMark Brown NULL); 15575c5659d0SMark Brown return 0; 15585c5659d0SMark Brown } 15595c5659d0SMark Brown 1560414c70cbSLiam Girdwood /* locks held by regulator_disable() */ 15613801b86aSMark Brown static int _regulator_disable(struct regulator_dev *rdev) 1562414c70cbSLiam Girdwood { 1563414c70cbSLiam Girdwood int ret = 0; 1564414c70cbSLiam Girdwood 1565cd94b505SDavid Brownell if (WARN(rdev->use_count <= 0, 156643e7ee33SJoe Perches "unbalanced disables for %s\n", rdev_get_name(rdev))) 1567cd94b505SDavid Brownell return -EIO; 1568cd94b505SDavid Brownell 1569414c70cbSLiam Girdwood /* are we the last user and permitted to disable ? */ 157060ef66fcSMark Brown if (rdev->use_count == 1 && 157160ef66fcSMark Brown (rdev->constraints && !rdev->constraints->always_on)) { 1572414c70cbSLiam Girdwood 1573414c70cbSLiam Girdwood /* we are last user */ 15745c5659d0SMark Brown if (_regulator_can_change_status(rdev)) { 15755c5659d0SMark Brown ret = _regulator_do_disable(rdev); 1576414c70cbSLiam Girdwood if (ret < 0) { 15775da84fd9SJoe Perches rdev_err(rdev, "failed to disable\n"); 1578414c70cbSLiam Girdwood return ret; 1579414c70cbSLiam Girdwood } 1580414c70cbSLiam Girdwood } 1581414c70cbSLiam Girdwood 1582414c70cbSLiam Girdwood rdev->use_count = 0; 1583414c70cbSLiam Girdwood } else if (rdev->use_count > 1) { 1584414c70cbSLiam Girdwood 1585414c70cbSLiam Girdwood if (rdev->constraints && 1586414c70cbSLiam Girdwood (rdev->constraints->valid_ops_mask & 1587414c70cbSLiam Girdwood REGULATOR_CHANGE_DRMS)) 1588414c70cbSLiam Girdwood drms_uA_update(rdev); 1589414c70cbSLiam Girdwood 1590414c70cbSLiam Girdwood rdev->use_count--; 1591414c70cbSLiam Girdwood } 15923801b86aSMark Brown 1593414c70cbSLiam Girdwood return ret; 1594414c70cbSLiam Girdwood } 1595414c70cbSLiam Girdwood 1596414c70cbSLiam Girdwood /** 1597414c70cbSLiam Girdwood * regulator_disable - disable regulator output 1598414c70cbSLiam Girdwood * @regulator: regulator source 1599414c70cbSLiam Girdwood * 1600cf7bbcdfSMark Brown * Disable the regulator output voltage or current. Calls to 1601cf7bbcdfSMark Brown * regulator_enable() must be balanced with calls to 1602cf7bbcdfSMark Brown * regulator_disable(). 160369279fb9SMark Brown * 1604414c70cbSLiam Girdwood * NOTE: this will only disable the regulator output if no other consumer 1605cf7bbcdfSMark Brown * devices have it enabled, the regulator device supports disabling and 1606cf7bbcdfSMark Brown * machine constraints permit this operation. 1607414c70cbSLiam Girdwood */ 1608414c70cbSLiam Girdwood int regulator_disable(struct regulator *regulator) 1609414c70cbSLiam Girdwood { 1610412aec61SDavid Brownell struct regulator_dev *rdev = regulator->rdev; 1611412aec61SDavid Brownell int ret = 0; 1612414c70cbSLiam Girdwood 16136492bc1bSMark Brown if (regulator->always_on) 16146492bc1bSMark Brown return 0; 16156492bc1bSMark Brown 1616412aec61SDavid Brownell mutex_lock(&rdev->mutex); 16173801b86aSMark Brown ret = _regulator_disable(rdev); 1618412aec61SDavid Brownell mutex_unlock(&rdev->mutex); 16198cbf811dSJeffrey Carlyle 16203801b86aSMark Brown if (ret == 0 && rdev->supply) 16213801b86aSMark Brown regulator_disable(rdev->supply); 16228cbf811dSJeffrey Carlyle 1623414c70cbSLiam Girdwood return ret; 1624414c70cbSLiam Girdwood } 1625414c70cbSLiam Girdwood EXPORT_SYMBOL_GPL(regulator_disable); 1626414c70cbSLiam Girdwood 1627414c70cbSLiam Girdwood /* locks held by regulator_force_disable() */ 16283801b86aSMark Brown static int _regulator_force_disable(struct regulator_dev *rdev) 1629414c70cbSLiam Girdwood { 1630414c70cbSLiam Girdwood int ret = 0; 1631414c70cbSLiam Girdwood 1632414c70cbSLiam Girdwood /* force disable */ 1633414c70cbSLiam Girdwood if (rdev->desc->ops->disable) { 1634414c70cbSLiam Girdwood /* ah well, who wants to live forever... */ 1635414c70cbSLiam Girdwood ret = rdev->desc->ops->disable(rdev); 1636414c70cbSLiam Girdwood if (ret < 0) { 16375da84fd9SJoe Perches rdev_err(rdev, "failed to force disable\n"); 1638414c70cbSLiam Girdwood return ret; 1639414c70cbSLiam Girdwood } 1640414c70cbSLiam Girdwood /* notify other consumers that power has been forced off */ 164184b68263SMark Brown _notifier_call_chain(rdev, REGULATOR_EVENT_FORCE_DISABLE | 164284b68263SMark Brown REGULATOR_EVENT_DISABLE, NULL); 1643414c70cbSLiam Girdwood } 1644414c70cbSLiam Girdwood 1645414c70cbSLiam Girdwood return ret; 1646414c70cbSLiam Girdwood } 1647414c70cbSLiam Girdwood 1648414c70cbSLiam Girdwood /** 1649414c70cbSLiam Girdwood * regulator_force_disable - force disable regulator output 1650414c70cbSLiam Girdwood * @regulator: regulator source 1651414c70cbSLiam Girdwood * 1652414c70cbSLiam Girdwood * Forcibly disable the regulator output voltage or current. 1653414c70cbSLiam Girdwood * NOTE: this *will* disable the regulator output even if other consumer 1654414c70cbSLiam Girdwood * devices have it enabled. This should be used for situations when device 1655414c70cbSLiam Girdwood * damage will likely occur if the regulator is not disabled (e.g. over temp). 1656414c70cbSLiam Girdwood */ 1657414c70cbSLiam Girdwood int regulator_force_disable(struct regulator *regulator) 1658414c70cbSLiam Girdwood { 165982d15839SMark Brown struct regulator_dev *rdev = regulator->rdev; 1660414c70cbSLiam Girdwood int ret; 1661414c70cbSLiam Girdwood 166282d15839SMark Brown mutex_lock(&rdev->mutex); 1663414c70cbSLiam Girdwood regulator->uA_load = 0; 16643801b86aSMark Brown ret = _regulator_force_disable(regulator->rdev); 166582d15839SMark Brown mutex_unlock(&rdev->mutex); 16668cbf811dSJeffrey Carlyle 16673801b86aSMark Brown if (rdev->supply) 16683801b86aSMark Brown while (rdev->open_count--) 16693801b86aSMark Brown regulator_disable(rdev->supply); 16708cbf811dSJeffrey Carlyle 1671414c70cbSLiam Girdwood return ret; 1672414c70cbSLiam Girdwood } 1673414c70cbSLiam Girdwood EXPORT_SYMBOL_GPL(regulator_force_disable); 1674414c70cbSLiam Girdwood 1675da07ecd9SMark Brown static void regulator_disable_work(struct work_struct *work) 1676da07ecd9SMark Brown { 1677da07ecd9SMark Brown struct regulator_dev *rdev = container_of(work, struct regulator_dev, 1678da07ecd9SMark Brown disable_work.work); 1679da07ecd9SMark Brown int count, i, ret; 1680da07ecd9SMark Brown 1681da07ecd9SMark Brown mutex_lock(&rdev->mutex); 1682da07ecd9SMark Brown 1683da07ecd9SMark Brown BUG_ON(!rdev->deferred_disables); 1684da07ecd9SMark Brown 1685da07ecd9SMark Brown count = rdev->deferred_disables; 1686da07ecd9SMark Brown rdev->deferred_disables = 0; 1687da07ecd9SMark Brown 1688da07ecd9SMark Brown for (i = 0; i < count; i++) { 1689da07ecd9SMark Brown ret = _regulator_disable(rdev); 1690da07ecd9SMark Brown if (ret != 0) 1691da07ecd9SMark Brown rdev_err(rdev, "Deferred disable failed: %d\n", ret); 1692da07ecd9SMark Brown } 1693da07ecd9SMark Brown 1694da07ecd9SMark Brown mutex_unlock(&rdev->mutex); 1695da07ecd9SMark Brown 1696da07ecd9SMark Brown if (rdev->supply) { 1697da07ecd9SMark Brown for (i = 0; i < count; i++) { 1698da07ecd9SMark Brown ret = regulator_disable(rdev->supply); 1699da07ecd9SMark Brown if (ret != 0) { 1700da07ecd9SMark Brown rdev_err(rdev, 1701da07ecd9SMark Brown "Supply disable failed: %d\n", ret); 1702da07ecd9SMark Brown } 1703da07ecd9SMark Brown } 1704da07ecd9SMark Brown } 1705da07ecd9SMark Brown } 1706da07ecd9SMark Brown 1707da07ecd9SMark Brown /** 1708da07ecd9SMark Brown * regulator_disable_deferred - disable regulator output with delay 1709da07ecd9SMark Brown * @regulator: regulator source 1710da07ecd9SMark Brown * @ms: miliseconds until the regulator is disabled 1711da07ecd9SMark Brown * 1712da07ecd9SMark Brown * Execute regulator_disable() on the regulator after a delay. This 1713da07ecd9SMark Brown * is intended for use with devices that require some time to quiesce. 1714da07ecd9SMark Brown * 1715da07ecd9SMark Brown * NOTE: this will only disable the regulator output if no other consumer 1716da07ecd9SMark Brown * devices have it enabled, the regulator device supports disabling and 1717da07ecd9SMark Brown * machine constraints permit this operation. 1718da07ecd9SMark Brown */ 1719da07ecd9SMark Brown int regulator_disable_deferred(struct regulator *regulator, int ms) 1720da07ecd9SMark Brown { 1721da07ecd9SMark Brown struct regulator_dev *rdev = regulator->rdev; 1722aa59802dSMark Brown int ret; 1723da07ecd9SMark Brown 17246492bc1bSMark Brown if (regulator->always_on) 17256492bc1bSMark Brown return 0; 17266492bc1bSMark Brown 1727da07ecd9SMark Brown mutex_lock(&rdev->mutex); 1728da07ecd9SMark Brown rdev->deferred_disables++; 1729da07ecd9SMark Brown mutex_unlock(&rdev->mutex); 1730da07ecd9SMark Brown 1731aa59802dSMark Brown ret = schedule_delayed_work(&rdev->disable_work, 1732da07ecd9SMark Brown msecs_to_jiffies(ms)); 1733aa59802dSMark Brown if (ret < 0) 1734aa59802dSMark Brown return ret; 1735aa59802dSMark Brown else 1736aa59802dSMark Brown return 0; 1737da07ecd9SMark Brown } 1738da07ecd9SMark Brown EXPORT_SYMBOL_GPL(regulator_disable_deferred); 1739da07ecd9SMark Brown 1740cd6dffb4SMark Brown /** 1741cd6dffb4SMark Brown * regulator_is_enabled_regmap - standard is_enabled() for regmap users 1742cd6dffb4SMark Brown * 1743cd6dffb4SMark Brown * @rdev: regulator to operate on 1744cd6dffb4SMark Brown * 1745cd6dffb4SMark Brown * Regulators that use regmap for their register I/O can set the 1746cd6dffb4SMark Brown * enable_reg and enable_mask fields in their descriptor and then use 1747cd6dffb4SMark Brown * this as their is_enabled operation, saving some code. 1748cd6dffb4SMark Brown */ 1749cd6dffb4SMark Brown int regulator_is_enabled_regmap(struct regulator_dev *rdev) 1750cd6dffb4SMark Brown { 1751cd6dffb4SMark Brown unsigned int val; 1752cd6dffb4SMark Brown int ret; 1753cd6dffb4SMark Brown 1754cd6dffb4SMark Brown ret = regmap_read(rdev->regmap, rdev->desc->enable_reg, &val); 1755cd6dffb4SMark Brown if (ret != 0) 1756cd6dffb4SMark Brown return ret; 1757cd6dffb4SMark Brown 1758cd6dffb4SMark Brown return (val & rdev->desc->enable_mask) != 0; 1759cd6dffb4SMark Brown } 1760cd6dffb4SMark Brown EXPORT_SYMBOL_GPL(regulator_is_enabled_regmap); 1761cd6dffb4SMark Brown 1762cd6dffb4SMark Brown /** 1763cd6dffb4SMark Brown * regulator_enable_regmap - standard enable() for regmap users 1764cd6dffb4SMark Brown * 1765cd6dffb4SMark Brown * @rdev: regulator to operate on 1766cd6dffb4SMark Brown * 1767cd6dffb4SMark Brown * Regulators that use regmap for their register I/O can set the 1768cd6dffb4SMark Brown * enable_reg and enable_mask fields in their descriptor and then use 1769cd6dffb4SMark Brown * this as their enable() operation, saving some code. 1770cd6dffb4SMark Brown */ 1771cd6dffb4SMark Brown int regulator_enable_regmap(struct regulator_dev *rdev) 1772cd6dffb4SMark Brown { 1773cd6dffb4SMark Brown return regmap_update_bits(rdev->regmap, rdev->desc->enable_reg, 1774cd6dffb4SMark Brown rdev->desc->enable_mask, 1775cd6dffb4SMark Brown rdev->desc->enable_mask); 1776cd6dffb4SMark Brown } 1777cd6dffb4SMark Brown EXPORT_SYMBOL_GPL(regulator_enable_regmap); 1778cd6dffb4SMark Brown 1779cd6dffb4SMark Brown /** 1780cd6dffb4SMark Brown * regulator_disable_regmap - standard disable() for regmap users 1781cd6dffb4SMark Brown * 1782cd6dffb4SMark Brown * @rdev: regulator to operate on 1783cd6dffb4SMark Brown * 1784cd6dffb4SMark Brown * Regulators that use regmap for their register I/O can set the 1785cd6dffb4SMark Brown * enable_reg and enable_mask fields in their descriptor and then use 1786cd6dffb4SMark Brown * this as their disable() operation, saving some code. 1787cd6dffb4SMark Brown */ 1788cd6dffb4SMark Brown int regulator_disable_regmap(struct regulator_dev *rdev) 1789cd6dffb4SMark Brown { 1790cd6dffb4SMark Brown return regmap_update_bits(rdev->regmap, rdev->desc->enable_reg, 1791cd6dffb4SMark Brown rdev->desc->enable_mask, 0); 1792cd6dffb4SMark Brown } 1793cd6dffb4SMark Brown EXPORT_SYMBOL_GPL(regulator_disable_regmap); 1794cd6dffb4SMark Brown 1795414c70cbSLiam Girdwood static int _regulator_is_enabled(struct regulator_dev *rdev) 1796414c70cbSLiam Girdwood { 179765f73508SMark Brown /* A GPIO control always takes precedence */ 179865f73508SMark Brown if (rdev->ena_gpio) 179965f73508SMark Brown return rdev->ena_gpio_state; 180065f73508SMark Brown 18019a7f6a4cSMark Brown /* If we don't know then assume that the regulator is always on */ 18029332546fSMark Brown if (!rdev->desc->ops->is_enabled) 18039a7f6a4cSMark Brown return 1; 1804414c70cbSLiam Girdwood 18059332546fSMark Brown return rdev->desc->ops->is_enabled(rdev); 1806414c70cbSLiam Girdwood } 1807414c70cbSLiam Girdwood 1808414c70cbSLiam Girdwood /** 1809414c70cbSLiam Girdwood * regulator_is_enabled - is the regulator output enabled 1810414c70cbSLiam Girdwood * @regulator: regulator source 1811414c70cbSLiam Girdwood * 1812412aec61SDavid Brownell * Returns positive if the regulator driver backing the source/client 1813412aec61SDavid Brownell * has requested that the device be enabled, zero if it hasn't, else a 1814412aec61SDavid Brownell * negative errno code. 1815412aec61SDavid Brownell * 1816412aec61SDavid Brownell * Note that the device backing this regulator handle can have multiple 1817412aec61SDavid Brownell * users, so it might be enabled even if regulator_enable() was never 1818412aec61SDavid Brownell * called for this particular source. 1819414c70cbSLiam Girdwood */ 1820414c70cbSLiam Girdwood int regulator_is_enabled(struct regulator *regulator) 1821414c70cbSLiam Girdwood { 18229332546fSMark Brown int ret; 18239332546fSMark Brown 18246492bc1bSMark Brown if (regulator->always_on) 18256492bc1bSMark Brown return 1; 18266492bc1bSMark Brown 18279332546fSMark Brown mutex_lock(®ulator->rdev->mutex); 18289332546fSMark Brown ret = _regulator_is_enabled(regulator->rdev); 18299332546fSMark Brown mutex_unlock(®ulator->rdev->mutex); 18309332546fSMark Brown 18319332546fSMark Brown return ret; 1832414c70cbSLiam Girdwood } 1833414c70cbSLiam Girdwood EXPORT_SYMBOL_GPL(regulator_is_enabled); 1834414c70cbSLiam Girdwood 1835414c70cbSLiam Girdwood /** 18364367cfdcSDavid Brownell * regulator_count_voltages - count regulator_list_voltage() selectors 18374367cfdcSDavid Brownell * @regulator: regulator source 18384367cfdcSDavid Brownell * 18394367cfdcSDavid Brownell * Returns number of selectors, or negative errno. Selectors are 18404367cfdcSDavid Brownell * numbered starting at zero, and typically correspond to bitfields 18414367cfdcSDavid Brownell * in hardware registers. 18424367cfdcSDavid Brownell */ 18434367cfdcSDavid Brownell int regulator_count_voltages(struct regulator *regulator) 18444367cfdcSDavid Brownell { 18454367cfdcSDavid Brownell struct regulator_dev *rdev = regulator->rdev; 18464367cfdcSDavid Brownell 18474367cfdcSDavid Brownell return rdev->desc->n_voltages ? : -EINVAL; 18484367cfdcSDavid Brownell } 18494367cfdcSDavid Brownell EXPORT_SYMBOL_GPL(regulator_count_voltages); 18504367cfdcSDavid Brownell 18514367cfdcSDavid Brownell /** 1852bca7bbffSMark Brown * regulator_list_voltage_linear - List voltages with simple calculation 1853bca7bbffSMark Brown * 1854bca7bbffSMark Brown * @rdev: Regulator device 1855bca7bbffSMark Brown * @selector: Selector to convert into a voltage 1856bca7bbffSMark Brown * 1857bca7bbffSMark Brown * Regulators with a simple linear mapping between voltages and 1858bca7bbffSMark Brown * selectors can set min_uV and uV_step in the regulator descriptor 1859bca7bbffSMark Brown * and then use this function as their list_voltage() operation, 1860bca7bbffSMark Brown */ 1861bca7bbffSMark Brown int regulator_list_voltage_linear(struct regulator_dev *rdev, 1862bca7bbffSMark Brown unsigned int selector) 1863bca7bbffSMark Brown { 1864bca7bbffSMark Brown if (selector >= rdev->desc->n_voltages) 1865bca7bbffSMark Brown return -EINVAL; 1866bca7bbffSMark Brown 1867bca7bbffSMark Brown return rdev->desc->min_uV + (rdev->desc->uV_step * selector); 1868bca7bbffSMark Brown } 1869bca7bbffSMark Brown EXPORT_SYMBOL_GPL(regulator_list_voltage_linear); 1870bca7bbffSMark Brown 1871bca7bbffSMark Brown /** 1872cffc9592SAxel Lin * regulator_list_voltage_table - List voltages with table based mapping 1873cffc9592SAxel Lin * 1874cffc9592SAxel Lin * @rdev: Regulator device 1875cffc9592SAxel Lin * @selector: Selector to convert into a voltage 1876cffc9592SAxel Lin * 1877cffc9592SAxel Lin * Regulators with table based mapping between voltages and 1878cffc9592SAxel Lin * selectors can set volt_table in the regulator descriptor 1879cffc9592SAxel Lin * and then use this function as their list_voltage() operation. 1880cffc9592SAxel Lin */ 1881cffc9592SAxel Lin int regulator_list_voltage_table(struct regulator_dev *rdev, 1882cffc9592SAxel Lin unsigned int selector) 1883cffc9592SAxel Lin { 1884cffc9592SAxel Lin if (!rdev->desc->volt_table) { 1885cffc9592SAxel Lin BUG_ON(!rdev->desc->volt_table); 1886cffc9592SAxel Lin return -EINVAL; 1887cffc9592SAxel Lin } 1888cffc9592SAxel Lin 1889cffc9592SAxel Lin if (selector >= rdev->desc->n_voltages) 1890cffc9592SAxel Lin return -EINVAL; 1891cffc9592SAxel Lin 1892cffc9592SAxel Lin return rdev->desc->volt_table[selector]; 1893cffc9592SAxel Lin } 1894cffc9592SAxel Lin EXPORT_SYMBOL_GPL(regulator_list_voltage_table); 1895cffc9592SAxel Lin 1896cffc9592SAxel Lin /** 18974367cfdcSDavid Brownell * regulator_list_voltage - enumerate supported voltages 18984367cfdcSDavid Brownell * @regulator: regulator source 18994367cfdcSDavid Brownell * @selector: identify voltage to list 19004367cfdcSDavid Brownell * Context: can sleep 19014367cfdcSDavid Brownell * 19024367cfdcSDavid Brownell * Returns a voltage that can be passed to @regulator_set_voltage(), 190388393161SThomas Weber * zero if this selector code can't be used on this system, or a 19044367cfdcSDavid Brownell * negative errno. 19054367cfdcSDavid Brownell */ 19064367cfdcSDavid Brownell int regulator_list_voltage(struct regulator *regulator, unsigned selector) 19074367cfdcSDavid Brownell { 19084367cfdcSDavid Brownell struct regulator_dev *rdev = regulator->rdev; 19094367cfdcSDavid Brownell struct regulator_ops *ops = rdev->desc->ops; 19104367cfdcSDavid Brownell int ret; 19114367cfdcSDavid Brownell 19124367cfdcSDavid Brownell if (!ops->list_voltage || selector >= rdev->desc->n_voltages) 19134367cfdcSDavid Brownell return -EINVAL; 19144367cfdcSDavid Brownell 19154367cfdcSDavid Brownell mutex_lock(&rdev->mutex); 19164367cfdcSDavid Brownell ret = ops->list_voltage(rdev, selector); 19174367cfdcSDavid Brownell mutex_unlock(&rdev->mutex); 19184367cfdcSDavid Brownell 19194367cfdcSDavid Brownell if (ret > 0) { 19204367cfdcSDavid Brownell if (ret < rdev->constraints->min_uV) 19214367cfdcSDavid Brownell ret = 0; 19224367cfdcSDavid Brownell else if (ret > rdev->constraints->max_uV) 19234367cfdcSDavid Brownell ret = 0; 19244367cfdcSDavid Brownell } 19254367cfdcSDavid Brownell 19264367cfdcSDavid Brownell return ret; 19274367cfdcSDavid Brownell } 19284367cfdcSDavid Brownell EXPORT_SYMBOL_GPL(regulator_list_voltage); 19294367cfdcSDavid Brownell 19304367cfdcSDavid Brownell /** 1931a7a1ad90SMark Brown * regulator_is_supported_voltage - check if a voltage range can be supported 1932a7a1ad90SMark Brown * 1933a7a1ad90SMark Brown * @regulator: Regulator to check. 1934a7a1ad90SMark Brown * @min_uV: Minimum required voltage in uV. 1935a7a1ad90SMark Brown * @max_uV: Maximum required voltage in uV. 1936a7a1ad90SMark Brown * 1937a7a1ad90SMark Brown * Returns a boolean or a negative error code. 1938a7a1ad90SMark Brown */ 1939a7a1ad90SMark Brown int regulator_is_supported_voltage(struct regulator *regulator, 1940a7a1ad90SMark Brown int min_uV, int max_uV) 1941a7a1ad90SMark Brown { 1942c5f3939bSMark Brown struct regulator_dev *rdev = regulator->rdev; 1943a7a1ad90SMark Brown int i, voltages, ret; 1944a7a1ad90SMark Brown 1945c5f3939bSMark Brown /* If we can't change voltage check the current voltage */ 1946c5f3939bSMark Brown if (!(rdev->constraints->valid_ops_mask & REGULATOR_CHANGE_VOLTAGE)) { 1947c5f3939bSMark Brown ret = regulator_get_voltage(regulator); 1948c5f3939bSMark Brown if (ret >= 0) 1949c5f3939bSMark Brown return (min_uV >= ret && ret <= max_uV); 1950c5f3939bSMark Brown else 1951c5f3939bSMark Brown return ret; 1952c5f3939bSMark Brown } 1953c5f3939bSMark Brown 1954a7a1ad90SMark Brown ret = regulator_count_voltages(regulator); 1955a7a1ad90SMark Brown if (ret < 0) 1956a7a1ad90SMark Brown return ret; 1957a7a1ad90SMark Brown voltages = ret; 1958a7a1ad90SMark Brown 1959a7a1ad90SMark Brown for (i = 0; i < voltages; i++) { 1960a7a1ad90SMark Brown ret = regulator_list_voltage(regulator, i); 1961a7a1ad90SMark Brown 1962a7a1ad90SMark Brown if (ret >= min_uV && ret <= max_uV) 1963a7a1ad90SMark Brown return 1; 1964a7a1ad90SMark Brown } 1965a7a1ad90SMark Brown 1966a7a1ad90SMark Brown return 0; 1967a7a1ad90SMark Brown } 1968a398eaa2SMark Brown EXPORT_SYMBOL_GPL(regulator_is_supported_voltage); 1969a7a1ad90SMark Brown 19704ab5b3d9SMark Brown /** 19714ab5b3d9SMark Brown * regulator_get_voltage_sel_regmap - standard get_voltage_sel for regmap users 19724ab5b3d9SMark Brown * 19734ab5b3d9SMark Brown * @rdev: regulator to operate on 19744ab5b3d9SMark Brown * 19754ab5b3d9SMark Brown * Regulators that use regmap for their register I/O can set the 19764ab5b3d9SMark Brown * vsel_reg and vsel_mask fields in their descriptor and then use this 19774ab5b3d9SMark Brown * as their get_voltage_vsel operation, saving some code. 19784ab5b3d9SMark Brown */ 19794ab5b3d9SMark Brown int regulator_get_voltage_sel_regmap(struct regulator_dev *rdev) 19804ab5b3d9SMark Brown { 19814ab5b3d9SMark Brown unsigned int val; 19824ab5b3d9SMark Brown int ret; 19834ab5b3d9SMark Brown 19844ab5b3d9SMark Brown ret = regmap_read(rdev->regmap, rdev->desc->vsel_reg, &val); 19854ab5b3d9SMark Brown if (ret != 0) 19864ab5b3d9SMark Brown return ret; 19874ab5b3d9SMark Brown 19884ab5b3d9SMark Brown val &= rdev->desc->vsel_mask; 19894ab5b3d9SMark Brown val >>= ffs(rdev->desc->vsel_mask) - 1; 19904ab5b3d9SMark Brown 19914ab5b3d9SMark Brown return val; 19924ab5b3d9SMark Brown } 19934ab5b3d9SMark Brown EXPORT_SYMBOL_GPL(regulator_get_voltage_sel_regmap); 19944ab5b3d9SMark Brown 19954ab5b3d9SMark Brown /** 19964ab5b3d9SMark Brown * regulator_set_voltage_sel_regmap - standard set_voltage_sel for regmap users 19974ab5b3d9SMark Brown * 19984ab5b3d9SMark Brown * @rdev: regulator to operate on 19994ab5b3d9SMark Brown * @sel: Selector to set 20004ab5b3d9SMark Brown * 20014ab5b3d9SMark Brown * Regulators that use regmap for their register I/O can set the 20024ab5b3d9SMark Brown * vsel_reg and vsel_mask fields in their descriptor and then use this 20034ab5b3d9SMark Brown * as their set_voltage_vsel operation, saving some code. 20044ab5b3d9SMark Brown */ 20054ab5b3d9SMark Brown int regulator_set_voltage_sel_regmap(struct regulator_dev *rdev, unsigned sel) 20064ab5b3d9SMark Brown { 20074ab5b3d9SMark Brown sel <<= ffs(rdev->desc->vsel_mask) - 1; 20084ab5b3d9SMark Brown 20094ab5b3d9SMark Brown return regmap_update_bits(rdev->regmap, rdev->desc->vsel_reg, 20104ab5b3d9SMark Brown rdev->desc->vsel_mask, sel); 20114ab5b3d9SMark Brown } 20124ab5b3d9SMark Brown EXPORT_SYMBOL_GPL(regulator_set_voltage_sel_regmap); 20134ab5b3d9SMark Brown 2014e843fc46SMark Brown /** 2015e843fc46SMark Brown * regulator_map_voltage_iterate - map_voltage() based on list_voltage() 2016e843fc46SMark Brown * 2017e843fc46SMark Brown * @rdev: Regulator to operate on 2018e843fc46SMark Brown * @min_uV: Lower bound for voltage 2019e843fc46SMark Brown * @max_uV: Upper bound for voltage 2020e843fc46SMark Brown * 2021e843fc46SMark Brown * Drivers implementing set_voltage_sel() and list_voltage() can use 2022e843fc46SMark Brown * this as their map_voltage() operation. It will find a suitable 2023e843fc46SMark Brown * voltage by calling list_voltage() until it gets something in bounds 2024e843fc46SMark Brown * for the requested voltages. 2025e843fc46SMark Brown */ 2026e843fc46SMark Brown int regulator_map_voltage_iterate(struct regulator_dev *rdev, 202775790251SMark Brown int min_uV, int max_uV) 202875790251SMark Brown { 2029e8eef82bSMark Brown int best_val = INT_MAX; 2030e843fc46SMark Brown int selector = 0; 2031e843fc46SMark Brown int i, ret; 2032e8eef82bSMark Brown 2033e8eef82bSMark Brown /* Find the smallest voltage that falls within the specified 2034e8eef82bSMark Brown * range. 2035e8eef82bSMark Brown */ 2036e8eef82bSMark Brown for (i = 0; i < rdev->desc->n_voltages; i++) { 2037e8eef82bSMark Brown ret = rdev->desc->ops->list_voltage(rdev, i); 2038e8eef82bSMark Brown if (ret < 0) 2039e8eef82bSMark Brown continue; 2040e8eef82bSMark Brown 2041e8eef82bSMark Brown if (ret < best_val && ret >= min_uV && ret <= max_uV) { 2042e8eef82bSMark Brown best_val = ret; 2043e8eef82bSMark Brown selector = i; 2044e8eef82bSMark Brown } 2045e8eef82bSMark Brown } 2046e8eef82bSMark Brown 2047e843fc46SMark Brown if (best_val != INT_MAX) 2048e843fc46SMark Brown return selector; 2049e843fc46SMark Brown else 2050e843fc46SMark Brown return -EINVAL; 2051e843fc46SMark Brown } 2052e843fc46SMark Brown EXPORT_SYMBOL_GPL(regulator_map_voltage_iterate); 2053e843fc46SMark Brown 2054bca7bbffSMark Brown /** 2055bca7bbffSMark Brown * regulator_map_voltage_linear - map_voltage() for simple linear mappings 2056bca7bbffSMark Brown * 2057bca7bbffSMark Brown * @rdev: Regulator to operate on 2058bca7bbffSMark Brown * @min_uV: Lower bound for voltage 2059bca7bbffSMark Brown * @max_uV: Upper bound for voltage 2060bca7bbffSMark Brown * 2061bca7bbffSMark Brown * Drivers providing min_uV and uV_step in their regulator_desc can 2062bca7bbffSMark Brown * use this as their map_voltage() operation. 2063bca7bbffSMark Brown */ 2064bca7bbffSMark Brown int regulator_map_voltage_linear(struct regulator_dev *rdev, 2065bca7bbffSMark Brown int min_uV, int max_uV) 2066bca7bbffSMark Brown { 2067bca7bbffSMark Brown int ret, voltage; 2068bca7bbffSMark Brown 20695a6881e8SAxel Lin /* Allow uV_step to be 0 for fixed voltage */ 20705a6881e8SAxel Lin if (rdev->desc->n_voltages == 1 && rdev->desc->uV_step == 0) { 20715a6881e8SAxel Lin if (min_uV <= rdev->desc->min_uV && rdev->desc->min_uV <= max_uV) 20725a6881e8SAxel Lin return 0; 20735a6881e8SAxel Lin else 20745a6881e8SAxel Lin return -EINVAL; 20755a6881e8SAxel Lin } 20765a6881e8SAxel Lin 2077bca7bbffSMark Brown if (!rdev->desc->uV_step) { 2078bca7bbffSMark Brown BUG_ON(!rdev->desc->uV_step); 2079bca7bbffSMark Brown return -EINVAL; 2080bca7bbffSMark Brown } 2081bca7bbffSMark Brown 20820bdc81e4SAxel Lin if (min_uV < rdev->desc->min_uV) 20830bdc81e4SAxel Lin min_uV = rdev->desc->min_uV; 20840bdc81e4SAxel Lin 2085ccfcb1c3SAxel Lin ret = DIV_ROUND_UP(min_uV - rdev->desc->min_uV, rdev->desc->uV_step); 2086bca7bbffSMark Brown if (ret < 0) 2087bca7bbffSMark Brown return ret; 2088bca7bbffSMark Brown 2089bca7bbffSMark Brown /* Map back into a voltage to verify we're still in bounds */ 2090bca7bbffSMark Brown voltage = rdev->desc->ops->list_voltage(rdev, ret); 2091bca7bbffSMark Brown if (voltage < min_uV || voltage > max_uV) 2092bca7bbffSMark Brown return -EINVAL; 2093bca7bbffSMark Brown 2094bca7bbffSMark Brown return ret; 2095bca7bbffSMark Brown } 2096bca7bbffSMark Brown EXPORT_SYMBOL_GPL(regulator_map_voltage_linear); 2097bca7bbffSMark Brown 2098a7a1ad90SMark Brown static int _regulator_do_set_voltage(struct regulator_dev *rdev, 2099a7a1ad90SMark Brown int min_uV, int max_uV) 2100a7a1ad90SMark Brown { 2101a7a1ad90SMark Brown int ret; 210275790251SMark Brown int delay = 0; 2103e113d792SMark Brown int best_val = 0; 210475790251SMark Brown unsigned int selector; 2105eba41a5eSAxel Lin int old_selector = -1; 210675790251SMark Brown 210775790251SMark Brown trace_regulator_set_voltage(rdev_get_name(rdev), min_uV, max_uV); 210875790251SMark Brown 210975790251SMark Brown min_uV += rdev->constraints->uV_offset; 211075790251SMark Brown max_uV += rdev->constraints->uV_offset; 211175790251SMark Brown 211277af1b26SLinus Walleij /* 211377af1b26SLinus Walleij * If we can't obtain the old selector there is not enough 211477af1b26SLinus Walleij * info to call set_voltage_time_sel(). 211577af1b26SLinus Walleij */ 21168b7485efSAxel Lin if (_regulator_is_enabled(rdev) && 21178b7485efSAxel Lin rdev->desc->ops->set_voltage_time_sel && 211877af1b26SLinus Walleij rdev->desc->ops->get_voltage_sel) { 2119eba41a5eSAxel Lin old_selector = rdev->desc->ops->get_voltage_sel(rdev); 2120eba41a5eSAxel Lin if (old_selector < 0) 2121eba41a5eSAxel Lin return old_selector; 2122eba41a5eSAxel Lin } 212377af1b26SLinus Walleij 212475790251SMark Brown if (rdev->desc->ops->set_voltage) { 212575790251SMark Brown ret = rdev->desc->ops->set_voltage(rdev, min_uV, max_uV, 212675790251SMark Brown &selector); 2127e113d792SMark Brown 2128e113d792SMark Brown if (ret >= 0) { 2129e113d792SMark Brown if (rdev->desc->ops->list_voltage) 2130e113d792SMark Brown best_val = rdev->desc->ops->list_voltage(rdev, 2131e113d792SMark Brown selector); 2132e113d792SMark Brown else 2133e113d792SMark Brown best_val = _regulator_get_voltage(rdev); 2134e113d792SMark Brown } 2135e113d792SMark Brown 2136e8eef82bSMark Brown } else if (rdev->desc->ops->set_voltage_sel) { 21379152c36aSAxel Lin if (rdev->desc->ops->map_voltage) { 2138e843fc46SMark Brown ret = rdev->desc->ops->map_voltage(rdev, min_uV, 2139e843fc46SMark Brown max_uV); 21409152c36aSAxel Lin } else { 21419152c36aSAxel Lin if (rdev->desc->ops->list_voltage == 21429152c36aSAxel Lin regulator_list_voltage_linear) 21439152c36aSAxel Lin ret = regulator_map_voltage_linear(rdev, 21449152c36aSAxel Lin min_uV, max_uV); 214507351233SAxel Lin else 21469152c36aSAxel Lin ret = regulator_map_voltage_iterate(rdev, 21479152c36aSAxel Lin min_uV, max_uV); 21489152c36aSAxel Lin } 2149e843fc46SMark Brown 2150e843fc46SMark Brown if (ret >= 0) { 2151e113d792SMark Brown best_val = rdev->desc->ops->list_voltage(rdev, ret); 2152e113d792SMark Brown if (min_uV <= best_val && max_uV >= best_val) { 2153e843fc46SMark Brown selector = ret; 2154e113d792SMark Brown ret = rdev->desc->ops->set_voltage_sel(rdev, 2155e113d792SMark Brown ret); 2156e113d792SMark Brown } else { 2157e113d792SMark Brown ret = -EINVAL; 2158e113d792SMark Brown } 2159e843fc46SMark Brown } 2160e8eef82bSMark Brown } else { 2161e8eef82bSMark Brown ret = -EINVAL; 2162e8eef82bSMark Brown } 2163e8eef82bSMark Brown 2164eba41a5eSAxel Lin /* Call set_voltage_time_sel if successfully obtained old_selector */ 21655aff3a8bSMark Brown if (ret == 0 && _regulator_is_enabled(rdev) && old_selector >= 0 && 2166eba41a5eSAxel Lin rdev->desc->ops->set_voltage_time_sel) { 2167eba41a5eSAxel Lin 2168eba41a5eSAxel Lin delay = rdev->desc->ops->set_voltage_time_sel(rdev, 2169eba41a5eSAxel Lin old_selector, selector); 2170eba41a5eSAxel Lin if (delay < 0) { 2171eba41a5eSAxel Lin rdev_warn(rdev, "set_voltage_time_sel() failed: %d\n", 2172eba41a5eSAxel Lin delay); 2173eba41a5eSAxel Lin delay = 0; 2174e8eef82bSMark Brown } 217575790251SMark Brown 217677af1b26SLinus Walleij /* Insert any necessary delays */ 217777af1b26SLinus Walleij if (delay >= 1000) { 217877af1b26SLinus Walleij mdelay(delay / 1000); 217977af1b26SLinus Walleij udelay(delay % 1000); 218077af1b26SLinus Walleij } else if (delay) { 218177af1b26SLinus Walleij udelay(delay); 218277af1b26SLinus Walleij } 21838b96de31SPhilip Rakity } 218477af1b26SLinus Walleij 21852f6c797fSAxel Lin if (ret == 0 && best_val >= 0) { 21862f6c797fSAxel Lin unsigned long data = best_val; 21872f6c797fSAxel Lin 2188ded06a52SMark Brown _notifier_call_chain(rdev, REGULATOR_EVENT_VOLTAGE_CHANGE, 21892f6c797fSAxel Lin (void *)data); 21902f6c797fSAxel Lin } 2191ded06a52SMark Brown 2192eba41a5eSAxel Lin trace_regulator_set_voltage_complete(rdev_get_name(rdev), best_val); 219375790251SMark Brown 219475790251SMark Brown return ret; 219575790251SMark Brown } 219675790251SMark Brown 2197a7a1ad90SMark Brown /** 2198414c70cbSLiam Girdwood * regulator_set_voltage - set regulator output voltage 2199414c70cbSLiam Girdwood * @regulator: regulator source 2200414c70cbSLiam Girdwood * @min_uV: Minimum required voltage in uV 2201414c70cbSLiam Girdwood * @max_uV: Maximum acceptable voltage in uV 2202414c70cbSLiam Girdwood * 2203414c70cbSLiam Girdwood * Sets a voltage regulator to the desired output voltage. This can be set 2204414c70cbSLiam Girdwood * during any regulator state. IOW, regulator can be disabled or enabled. 2205414c70cbSLiam Girdwood * 2206414c70cbSLiam Girdwood * If the regulator is enabled then the voltage will change to the new value 2207414c70cbSLiam Girdwood * immediately otherwise if the regulator is disabled the regulator will 2208414c70cbSLiam Girdwood * output at the new voltage when enabled. 2209414c70cbSLiam Girdwood * 2210414c70cbSLiam Girdwood * NOTE: If the regulator is shared between several devices then the lowest 2211414c70cbSLiam Girdwood * request voltage that meets the system constraints will be used. 221269279fb9SMark Brown * Regulator system constraints must be set for this regulator before 2213414c70cbSLiam Girdwood * calling this function otherwise this call will fail. 2214414c70cbSLiam Girdwood */ 2215414c70cbSLiam Girdwood int regulator_set_voltage(struct regulator *regulator, int min_uV, int max_uV) 2216414c70cbSLiam Girdwood { 2217414c70cbSLiam Girdwood struct regulator_dev *rdev = regulator->rdev; 221895a3c23aSMark Brown int ret = 0; 2219414c70cbSLiam Girdwood 2220414c70cbSLiam Girdwood mutex_lock(&rdev->mutex); 2221414c70cbSLiam Girdwood 222295a3c23aSMark Brown /* If we're setting the same range as last time the change 222395a3c23aSMark Brown * should be a noop (some cpufreq implementations use the same 222495a3c23aSMark Brown * voltage for multiple frequencies, for example). 222595a3c23aSMark Brown */ 222695a3c23aSMark Brown if (regulator->min_uV == min_uV && regulator->max_uV == max_uV) 222795a3c23aSMark Brown goto out; 222895a3c23aSMark Brown 2229414c70cbSLiam Girdwood /* sanity check */ 2230e8eef82bSMark Brown if (!rdev->desc->ops->set_voltage && 2231e8eef82bSMark Brown !rdev->desc->ops->set_voltage_sel) { 2232414c70cbSLiam Girdwood ret = -EINVAL; 2233414c70cbSLiam Girdwood goto out; 2234414c70cbSLiam Girdwood } 2235414c70cbSLiam Girdwood 2236414c70cbSLiam Girdwood /* constraints check */ 2237414c70cbSLiam Girdwood ret = regulator_check_voltage(rdev, &min_uV, &max_uV); 2238414c70cbSLiam Girdwood if (ret < 0) 2239414c70cbSLiam Girdwood goto out; 2240414c70cbSLiam Girdwood regulator->min_uV = min_uV; 2241414c70cbSLiam Girdwood regulator->max_uV = max_uV; 22423a93f2a9SMark Brown 224305fda3b1SThomas Petazzoni ret = regulator_check_consumers(rdev, &min_uV, &max_uV); 224405fda3b1SThomas Petazzoni if (ret < 0) 224505fda3b1SThomas Petazzoni goto out; 224605fda3b1SThomas Petazzoni 224775790251SMark Brown ret = _regulator_do_set_voltage(rdev, min_uV, max_uV); 224802fa3ec0SMark Brown 2249414c70cbSLiam Girdwood out: 2250414c70cbSLiam Girdwood mutex_unlock(&rdev->mutex); 2251414c70cbSLiam Girdwood return ret; 2252414c70cbSLiam Girdwood } 2253414c70cbSLiam Girdwood EXPORT_SYMBOL_GPL(regulator_set_voltage); 2254414c70cbSLiam Girdwood 2255606a2562SMark Brown /** 225688cd222bSLinus Walleij * regulator_set_voltage_time - get raise/fall time 225788cd222bSLinus Walleij * @regulator: regulator source 225888cd222bSLinus Walleij * @old_uV: starting voltage in microvolts 225988cd222bSLinus Walleij * @new_uV: target voltage in microvolts 226088cd222bSLinus Walleij * 226188cd222bSLinus Walleij * Provided with the starting and ending voltage, this function attempts to 226288cd222bSLinus Walleij * calculate the time in microseconds required to rise or fall to this new 226388cd222bSLinus Walleij * voltage. 226488cd222bSLinus Walleij */ 226588cd222bSLinus Walleij int regulator_set_voltage_time(struct regulator *regulator, 226688cd222bSLinus Walleij int old_uV, int new_uV) 226788cd222bSLinus Walleij { 226888cd222bSLinus Walleij struct regulator_dev *rdev = regulator->rdev; 226988cd222bSLinus Walleij struct regulator_ops *ops = rdev->desc->ops; 227088cd222bSLinus Walleij int old_sel = -1; 227188cd222bSLinus Walleij int new_sel = -1; 227288cd222bSLinus Walleij int voltage; 227388cd222bSLinus Walleij int i; 227488cd222bSLinus Walleij 227588cd222bSLinus Walleij /* Currently requires operations to do this */ 227688cd222bSLinus Walleij if (!ops->list_voltage || !ops->set_voltage_time_sel 227788cd222bSLinus Walleij || !rdev->desc->n_voltages) 227888cd222bSLinus Walleij return -EINVAL; 227988cd222bSLinus Walleij 228088cd222bSLinus Walleij for (i = 0; i < rdev->desc->n_voltages; i++) { 228188cd222bSLinus Walleij /* We only look for exact voltage matches here */ 228288cd222bSLinus Walleij voltage = regulator_list_voltage(regulator, i); 228388cd222bSLinus Walleij if (voltage < 0) 228488cd222bSLinus Walleij return -EINVAL; 228588cd222bSLinus Walleij if (voltage == 0) 228688cd222bSLinus Walleij continue; 228788cd222bSLinus Walleij if (voltage == old_uV) 228888cd222bSLinus Walleij old_sel = i; 228988cd222bSLinus Walleij if (voltage == new_uV) 229088cd222bSLinus Walleij new_sel = i; 229188cd222bSLinus Walleij } 229288cd222bSLinus Walleij 229388cd222bSLinus Walleij if (old_sel < 0 || new_sel < 0) 229488cd222bSLinus Walleij return -EINVAL; 229588cd222bSLinus Walleij 229688cd222bSLinus Walleij return ops->set_voltage_time_sel(rdev, old_sel, new_sel); 229788cd222bSLinus Walleij } 229888cd222bSLinus Walleij EXPORT_SYMBOL_GPL(regulator_set_voltage_time); 229988cd222bSLinus Walleij 230088cd222bSLinus Walleij /** 230198a175b6SYadwinder Singh Brar *regulator_set_voltage_time_sel - get raise/fall time 230298a175b6SYadwinder Singh Brar * @regulator: regulator source 230398a175b6SYadwinder Singh Brar * @old_selector: selector for starting voltage 230498a175b6SYadwinder Singh Brar * @new_selector: selector for target voltage 230598a175b6SYadwinder Singh Brar * 230698a175b6SYadwinder Singh Brar * Provided with the starting and target voltage selectors, this function 230798a175b6SYadwinder Singh Brar * returns time in microseconds required to rise or fall to this new voltage 230898a175b6SYadwinder Singh Brar * 2309f11d08c3SAxel Lin * Drivers providing ramp_delay in regulation_constraints can use this as their 2310398715abSAxel Lin * set_voltage_time_sel() operation. 231198a175b6SYadwinder Singh Brar */ 231298a175b6SYadwinder Singh Brar int regulator_set_voltage_time_sel(struct regulator_dev *rdev, 231398a175b6SYadwinder Singh Brar unsigned int old_selector, 231498a175b6SYadwinder Singh Brar unsigned int new_selector) 231598a175b6SYadwinder Singh Brar { 2316398715abSAxel Lin unsigned int ramp_delay = 0; 2317f11d08c3SAxel Lin int old_volt, new_volt; 2318398715abSAxel Lin 23196f0b2c69SYadwinder Singh Brar if (rdev->constraints->ramp_delay) 2320398715abSAxel Lin ramp_delay = rdev->constraints->ramp_delay; 2321398715abSAxel Lin else if (rdev->desc->ramp_delay) 2322398715abSAxel Lin ramp_delay = rdev->desc->ramp_delay; 2323398715abSAxel Lin 2324398715abSAxel Lin if (ramp_delay == 0) { 23256f0b2c69SYadwinder Singh Brar rdev_warn(rdev, "ramp_delay not set\n"); 2326398715abSAxel Lin return 0; 23276f0b2c69SYadwinder Singh Brar } 2328398715abSAxel Lin 2329f11d08c3SAxel Lin /* sanity check */ 2330f11d08c3SAxel Lin if (!rdev->desc->ops->list_voltage) 2331f11d08c3SAxel Lin return -EINVAL; 2332398715abSAxel Lin 2333f11d08c3SAxel Lin old_volt = rdev->desc->ops->list_voltage(rdev, old_selector); 2334f11d08c3SAxel Lin new_volt = rdev->desc->ops->list_voltage(rdev, new_selector); 2335f11d08c3SAxel Lin 2336f11d08c3SAxel Lin return DIV_ROUND_UP(abs(new_volt - old_volt), ramp_delay); 233798a175b6SYadwinder Singh Brar } 2338b19dbf71SMark Brown EXPORT_SYMBOL_GPL(regulator_set_voltage_time_sel); 233998a175b6SYadwinder Singh Brar 234098a175b6SYadwinder Singh Brar /** 2341606a2562SMark Brown * regulator_sync_voltage - re-apply last regulator output voltage 2342606a2562SMark Brown * @regulator: regulator source 2343606a2562SMark Brown * 2344606a2562SMark Brown * Re-apply the last configured voltage. This is intended to be used 2345606a2562SMark Brown * where some external control source the consumer is cooperating with 2346606a2562SMark Brown * has caused the configured voltage to change. 2347606a2562SMark Brown */ 2348606a2562SMark Brown int regulator_sync_voltage(struct regulator *regulator) 2349606a2562SMark Brown { 2350606a2562SMark Brown struct regulator_dev *rdev = regulator->rdev; 2351606a2562SMark Brown int ret, min_uV, max_uV; 2352606a2562SMark Brown 2353606a2562SMark Brown mutex_lock(&rdev->mutex); 2354606a2562SMark Brown 2355606a2562SMark Brown if (!rdev->desc->ops->set_voltage && 2356606a2562SMark Brown !rdev->desc->ops->set_voltage_sel) { 2357606a2562SMark Brown ret = -EINVAL; 2358606a2562SMark Brown goto out; 2359606a2562SMark Brown } 2360606a2562SMark Brown 2361606a2562SMark Brown /* This is only going to work if we've had a voltage configured. */ 2362606a2562SMark Brown if (!regulator->min_uV && !regulator->max_uV) { 2363606a2562SMark Brown ret = -EINVAL; 2364606a2562SMark Brown goto out; 2365606a2562SMark Brown } 2366606a2562SMark Brown 2367606a2562SMark Brown min_uV = regulator->min_uV; 2368606a2562SMark Brown max_uV = regulator->max_uV; 2369606a2562SMark Brown 2370606a2562SMark Brown /* This should be a paranoia check... */ 2371606a2562SMark Brown ret = regulator_check_voltage(rdev, &min_uV, &max_uV); 2372606a2562SMark Brown if (ret < 0) 2373606a2562SMark Brown goto out; 2374606a2562SMark Brown 2375606a2562SMark Brown ret = regulator_check_consumers(rdev, &min_uV, &max_uV); 2376606a2562SMark Brown if (ret < 0) 2377606a2562SMark Brown goto out; 2378606a2562SMark Brown 2379606a2562SMark Brown ret = _regulator_do_set_voltage(rdev, min_uV, max_uV); 2380606a2562SMark Brown 2381606a2562SMark Brown out: 2382606a2562SMark Brown mutex_unlock(&rdev->mutex); 2383606a2562SMark Brown return ret; 2384606a2562SMark Brown } 2385606a2562SMark Brown EXPORT_SYMBOL_GPL(regulator_sync_voltage); 2386606a2562SMark Brown 2387414c70cbSLiam Girdwood static int _regulator_get_voltage(struct regulator_dev *rdev) 2388414c70cbSLiam Girdwood { 2389bf5892a8SMark Brown int sel, ret; 2390476c2d83SMark Brown 2391476c2d83SMark Brown if (rdev->desc->ops->get_voltage_sel) { 2392476c2d83SMark Brown sel = rdev->desc->ops->get_voltage_sel(rdev); 2393476c2d83SMark Brown if (sel < 0) 2394476c2d83SMark Brown return sel; 2395bf5892a8SMark Brown ret = rdev->desc->ops->list_voltage(rdev, sel); 2396cb220d16SAxel Lin } else if (rdev->desc->ops->get_voltage) { 2397bf5892a8SMark Brown ret = rdev->desc->ops->get_voltage(rdev); 2398cb220d16SAxel Lin } else { 2399414c70cbSLiam Girdwood return -EINVAL; 2400cb220d16SAxel Lin } 2401bf5892a8SMark Brown 2402cb220d16SAxel Lin if (ret < 0) 2403cb220d16SAxel Lin return ret; 2404bf5892a8SMark Brown return ret - rdev->constraints->uV_offset; 2405414c70cbSLiam Girdwood } 2406414c70cbSLiam Girdwood 2407414c70cbSLiam Girdwood /** 2408414c70cbSLiam Girdwood * regulator_get_voltage - get regulator output voltage 2409414c70cbSLiam Girdwood * @regulator: regulator source 2410414c70cbSLiam Girdwood * 2411414c70cbSLiam Girdwood * This returns the current regulator voltage in uV. 2412414c70cbSLiam Girdwood * 2413414c70cbSLiam Girdwood * NOTE: If the regulator is disabled it will return the voltage value. This 2414414c70cbSLiam Girdwood * function should not be used to determine regulator state. 2415414c70cbSLiam Girdwood */ 2416414c70cbSLiam Girdwood int regulator_get_voltage(struct regulator *regulator) 2417414c70cbSLiam Girdwood { 2418414c70cbSLiam Girdwood int ret; 2419414c70cbSLiam Girdwood 2420414c70cbSLiam Girdwood mutex_lock(®ulator->rdev->mutex); 2421414c70cbSLiam Girdwood 2422414c70cbSLiam Girdwood ret = _regulator_get_voltage(regulator->rdev); 2423414c70cbSLiam Girdwood 2424414c70cbSLiam Girdwood mutex_unlock(®ulator->rdev->mutex); 2425414c70cbSLiam Girdwood 2426414c70cbSLiam Girdwood return ret; 2427414c70cbSLiam Girdwood } 2428414c70cbSLiam Girdwood EXPORT_SYMBOL_GPL(regulator_get_voltage); 2429414c70cbSLiam Girdwood 2430414c70cbSLiam Girdwood /** 2431414c70cbSLiam Girdwood * regulator_set_current_limit - set regulator output current limit 2432414c70cbSLiam Girdwood * @regulator: regulator source 2433414c70cbSLiam Girdwood * @min_uA: Minimuum supported current in uA 2434414c70cbSLiam Girdwood * @max_uA: Maximum supported current in uA 2435414c70cbSLiam Girdwood * 2436414c70cbSLiam Girdwood * Sets current sink to the desired output current. This can be set during 2437414c70cbSLiam Girdwood * any regulator state. IOW, regulator can be disabled or enabled. 2438414c70cbSLiam Girdwood * 2439414c70cbSLiam Girdwood * If the regulator is enabled then the current will change to the new value 2440414c70cbSLiam Girdwood * immediately otherwise if the regulator is disabled the regulator will 2441414c70cbSLiam Girdwood * output at the new current when enabled. 2442414c70cbSLiam Girdwood * 2443414c70cbSLiam Girdwood * NOTE: Regulator system constraints must be set for this regulator before 2444414c70cbSLiam Girdwood * calling this function otherwise this call will fail. 2445414c70cbSLiam Girdwood */ 2446414c70cbSLiam Girdwood int regulator_set_current_limit(struct regulator *regulator, 2447414c70cbSLiam Girdwood int min_uA, int max_uA) 2448414c70cbSLiam Girdwood { 2449414c70cbSLiam Girdwood struct regulator_dev *rdev = regulator->rdev; 2450414c70cbSLiam Girdwood int ret; 2451414c70cbSLiam Girdwood 2452414c70cbSLiam Girdwood mutex_lock(&rdev->mutex); 2453414c70cbSLiam Girdwood 2454414c70cbSLiam Girdwood /* sanity check */ 2455414c70cbSLiam Girdwood if (!rdev->desc->ops->set_current_limit) { 2456414c70cbSLiam Girdwood ret = -EINVAL; 2457414c70cbSLiam Girdwood goto out; 2458414c70cbSLiam Girdwood } 2459414c70cbSLiam Girdwood 2460414c70cbSLiam Girdwood /* constraints check */ 2461414c70cbSLiam Girdwood ret = regulator_check_current_limit(rdev, &min_uA, &max_uA); 2462414c70cbSLiam Girdwood if (ret < 0) 2463414c70cbSLiam Girdwood goto out; 2464414c70cbSLiam Girdwood 2465414c70cbSLiam Girdwood ret = rdev->desc->ops->set_current_limit(rdev, min_uA, max_uA); 2466414c70cbSLiam Girdwood out: 2467414c70cbSLiam Girdwood mutex_unlock(&rdev->mutex); 2468414c70cbSLiam Girdwood return ret; 2469414c70cbSLiam Girdwood } 2470414c70cbSLiam Girdwood EXPORT_SYMBOL_GPL(regulator_set_current_limit); 2471414c70cbSLiam Girdwood 2472414c70cbSLiam Girdwood static int _regulator_get_current_limit(struct regulator_dev *rdev) 2473414c70cbSLiam Girdwood { 2474414c70cbSLiam Girdwood int ret; 2475414c70cbSLiam Girdwood 2476414c70cbSLiam Girdwood mutex_lock(&rdev->mutex); 2477414c70cbSLiam Girdwood 2478414c70cbSLiam Girdwood /* sanity check */ 2479414c70cbSLiam Girdwood if (!rdev->desc->ops->get_current_limit) { 2480414c70cbSLiam Girdwood ret = -EINVAL; 2481414c70cbSLiam Girdwood goto out; 2482414c70cbSLiam Girdwood } 2483414c70cbSLiam Girdwood 2484414c70cbSLiam Girdwood ret = rdev->desc->ops->get_current_limit(rdev); 2485414c70cbSLiam Girdwood out: 2486414c70cbSLiam Girdwood mutex_unlock(&rdev->mutex); 2487414c70cbSLiam Girdwood return ret; 2488414c70cbSLiam Girdwood } 2489414c70cbSLiam Girdwood 2490414c70cbSLiam Girdwood /** 2491414c70cbSLiam Girdwood * regulator_get_current_limit - get regulator output current 2492414c70cbSLiam Girdwood * @regulator: regulator source 2493414c70cbSLiam Girdwood * 2494414c70cbSLiam Girdwood * This returns the current supplied by the specified current sink in uA. 2495414c70cbSLiam Girdwood * 2496414c70cbSLiam Girdwood * NOTE: If the regulator is disabled it will return the current value. This 2497414c70cbSLiam Girdwood * function should not be used to determine regulator state. 2498414c70cbSLiam Girdwood */ 2499414c70cbSLiam Girdwood int regulator_get_current_limit(struct regulator *regulator) 2500414c70cbSLiam Girdwood { 2501414c70cbSLiam Girdwood return _regulator_get_current_limit(regulator->rdev); 2502414c70cbSLiam Girdwood } 2503414c70cbSLiam Girdwood EXPORT_SYMBOL_GPL(regulator_get_current_limit); 2504414c70cbSLiam Girdwood 2505414c70cbSLiam Girdwood /** 2506414c70cbSLiam Girdwood * regulator_set_mode - set regulator operating mode 2507414c70cbSLiam Girdwood * @regulator: regulator source 2508414c70cbSLiam Girdwood * @mode: operating mode - one of the REGULATOR_MODE constants 2509414c70cbSLiam Girdwood * 2510414c70cbSLiam Girdwood * Set regulator operating mode to increase regulator efficiency or improve 2511414c70cbSLiam Girdwood * regulation performance. 2512414c70cbSLiam Girdwood * 2513414c70cbSLiam Girdwood * NOTE: Regulator system constraints must be set for this regulator before 2514414c70cbSLiam Girdwood * calling this function otherwise this call will fail. 2515414c70cbSLiam Girdwood */ 2516414c70cbSLiam Girdwood int regulator_set_mode(struct regulator *regulator, unsigned int mode) 2517414c70cbSLiam Girdwood { 2518414c70cbSLiam Girdwood struct regulator_dev *rdev = regulator->rdev; 2519414c70cbSLiam Girdwood int ret; 2520500b4ac9SSundar R Iyer int regulator_curr_mode; 2521414c70cbSLiam Girdwood 2522414c70cbSLiam Girdwood mutex_lock(&rdev->mutex); 2523414c70cbSLiam Girdwood 2524414c70cbSLiam Girdwood /* sanity check */ 2525414c70cbSLiam Girdwood if (!rdev->desc->ops->set_mode) { 2526414c70cbSLiam Girdwood ret = -EINVAL; 2527414c70cbSLiam Girdwood goto out; 2528414c70cbSLiam Girdwood } 2529414c70cbSLiam Girdwood 2530500b4ac9SSundar R Iyer /* return if the same mode is requested */ 2531500b4ac9SSundar R Iyer if (rdev->desc->ops->get_mode) { 2532500b4ac9SSundar R Iyer regulator_curr_mode = rdev->desc->ops->get_mode(rdev); 2533500b4ac9SSundar R Iyer if (regulator_curr_mode == mode) { 2534500b4ac9SSundar R Iyer ret = 0; 2535500b4ac9SSundar R Iyer goto out; 2536500b4ac9SSundar R Iyer } 2537500b4ac9SSundar R Iyer } 2538500b4ac9SSundar R Iyer 2539414c70cbSLiam Girdwood /* constraints check */ 254022c51b47SAxel Lin ret = regulator_mode_constrain(rdev, &mode); 2541414c70cbSLiam Girdwood if (ret < 0) 2542414c70cbSLiam Girdwood goto out; 2543414c70cbSLiam Girdwood 2544414c70cbSLiam Girdwood ret = rdev->desc->ops->set_mode(rdev, mode); 2545414c70cbSLiam Girdwood out: 2546414c70cbSLiam Girdwood mutex_unlock(&rdev->mutex); 2547414c70cbSLiam Girdwood return ret; 2548414c70cbSLiam Girdwood } 2549414c70cbSLiam Girdwood EXPORT_SYMBOL_GPL(regulator_set_mode); 2550414c70cbSLiam Girdwood 2551414c70cbSLiam Girdwood static unsigned int _regulator_get_mode(struct regulator_dev *rdev) 2552414c70cbSLiam Girdwood { 2553414c70cbSLiam Girdwood int ret; 2554414c70cbSLiam Girdwood 2555414c70cbSLiam Girdwood mutex_lock(&rdev->mutex); 2556414c70cbSLiam Girdwood 2557414c70cbSLiam Girdwood /* sanity check */ 2558414c70cbSLiam Girdwood if (!rdev->desc->ops->get_mode) { 2559414c70cbSLiam Girdwood ret = -EINVAL; 2560414c70cbSLiam Girdwood goto out; 2561414c70cbSLiam Girdwood } 2562414c70cbSLiam Girdwood 2563414c70cbSLiam Girdwood ret = rdev->desc->ops->get_mode(rdev); 2564414c70cbSLiam Girdwood out: 2565414c70cbSLiam Girdwood mutex_unlock(&rdev->mutex); 2566414c70cbSLiam Girdwood return ret; 2567414c70cbSLiam Girdwood } 2568414c70cbSLiam Girdwood 2569414c70cbSLiam Girdwood /** 2570414c70cbSLiam Girdwood * regulator_get_mode - get regulator operating mode 2571414c70cbSLiam Girdwood * @regulator: regulator source 2572414c70cbSLiam Girdwood * 2573414c70cbSLiam Girdwood * Get the current regulator operating mode. 2574414c70cbSLiam Girdwood */ 2575414c70cbSLiam Girdwood unsigned int regulator_get_mode(struct regulator *regulator) 2576414c70cbSLiam Girdwood { 2577414c70cbSLiam Girdwood return _regulator_get_mode(regulator->rdev); 2578414c70cbSLiam Girdwood } 2579414c70cbSLiam Girdwood EXPORT_SYMBOL_GPL(regulator_get_mode); 2580414c70cbSLiam Girdwood 2581414c70cbSLiam Girdwood /** 2582414c70cbSLiam Girdwood * regulator_set_optimum_mode - set regulator optimum operating mode 2583414c70cbSLiam Girdwood * @regulator: regulator source 2584414c70cbSLiam Girdwood * @uA_load: load current 2585414c70cbSLiam Girdwood * 2586414c70cbSLiam Girdwood * Notifies the regulator core of a new device load. This is then used by 2587414c70cbSLiam Girdwood * DRMS (if enabled by constraints) to set the most efficient regulator 2588414c70cbSLiam Girdwood * operating mode for the new regulator loading. 2589414c70cbSLiam Girdwood * 2590414c70cbSLiam Girdwood * Consumer devices notify their supply regulator of the maximum power 2591414c70cbSLiam Girdwood * they will require (can be taken from device datasheet in the power 2592414c70cbSLiam Girdwood * consumption tables) when they change operational status and hence power 2593414c70cbSLiam Girdwood * state. Examples of operational state changes that can affect power 2594414c70cbSLiam Girdwood * consumption are :- 2595414c70cbSLiam Girdwood * 2596414c70cbSLiam Girdwood * o Device is opened / closed. 2597414c70cbSLiam Girdwood * o Device I/O is about to begin or has just finished. 2598414c70cbSLiam Girdwood * o Device is idling in between work. 2599414c70cbSLiam Girdwood * 2600414c70cbSLiam Girdwood * This information is also exported via sysfs to userspace. 2601414c70cbSLiam Girdwood * 2602414c70cbSLiam Girdwood * DRMS will sum the total requested load on the regulator and change 2603414c70cbSLiam Girdwood * to the most efficient operating mode if platform constraints allow. 2604414c70cbSLiam Girdwood * 2605414c70cbSLiam Girdwood * Returns the new regulator mode or error. 2606414c70cbSLiam Girdwood */ 2607414c70cbSLiam Girdwood int regulator_set_optimum_mode(struct regulator *regulator, int uA_load) 2608414c70cbSLiam Girdwood { 2609414c70cbSLiam Girdwood struct regulator_dev *rdev = regulator->rdev; 2610414c70cbSLiam Girdwood struct regulator *consumer; 2611d92d95b6SStephen Boyd int ret, output_uV, input_uV = 0, total_uA_load = 0; 2612414c70cbSLiam Girdwood unsigned int mode; 2613414c70cbSLiam Girdwood 2614d92d95b6SStephen Boyd if (rdev->supply) 2615d92d95b6SStephen Boyd input_uV = regulator_get_voltage(rdev->supply); 2616d92d95b6SStephen Boyd 2617414c70cbSLiam Girdwood mutex_lock(&rdev->mutex); 2618414c70cbSLiam Girdwood 2619a4b41483SMark Brown /* 2620a4b41483SMark Brown * first check to see if we can set modes at all, otherwise just 2621a4b41483SMark Brown * tell the consumer everything is OK. 2622a4b41483SMark Brown */ 2623414c70cbSLiam Girdwood regulator->uA_load = uA_load; 2624414c70cbSLiam Girdwood ret = regulator_check_drms(rdev); 2625a4b41483SMark Brown if (ret < 0) { 2626a4b41483SMark Brown ret = 0; 2627414c70cbSLiam Girdwood goto out; 2628a4b41483SMark Brown } 2629414c70cbSLiam Girdwood 2630414c70cbSLiam Girdwood if (!rdev->desc->ops->get_optimum_mode) 2631414c70cbSLiam Girdwood goto out; 2632414c70cbSLiam Girdwood 2633a4b41483SMark Brown /* 2634a4b41483SMark Brown * we can actually do this so any errors are indicators of 2635a4b41483SMark Brown * potential real failure. 2636a4b41483SMark Brown */ 2637a4b41483SMark Brown ret = -EINVAL; 2638a4b41483SMark Brown 2639854ccbaeSAxel Lin if (!rdev->desc->ops->set_mode) 2640854ccbaeSAxel Lin goto out; 2641854ccbaeSAxel Lin 2642414c70cbSLiam Girdwood /* get output voltage */ 26431bf5a1f8SMark Brown output_uV = _regulator_get_voltage(rdev); 2644414c70cbSLiam Girdwood if (output_uV <= 0) { 26455da84fd9SJoe Perches rdev_err(rdev, "invalid output voltage found\n"); 2646414c70cbSLiam Girdwood goto out; 2647414c70cbSLiam Girdwood } 2648414c70cbSLiam Girdwood 2649d92d95b6SStephen Boyd /* No supply? Use constraint voltage */ 26501bf5a1f8SMark Brown if (input_uV <= 0) 2651414c70cbSLiam Girdwood input_uV = rdev->constraints->input_uV; 2652414c70cbSLiam Girdwood if (input_uV <= 0) { 26535da84fd9SJoe Perches rdev_err(rdev, "invalid input voltage found\n"); 2654414c70cbSLiam Girdwood goto out; 2655414c70cbSLiam Girdwood } 2656414c70cbSLiam Girdwood 2657414c70cbSLiam Girdwood /* calc total requested load for this regulator */ 2658414c70cbSLiam Girdwood list_for_each_entry(consumer, &rdev->consumer_list, list) 2659414c70cbSLiam Girdwood total_uA_load += consumer->uA_load; 2660414c70cbSLiam Girdwood 2661414c70cbSLiam Girdwood mode = rdev->desc->ops->get_optimum_mode(rdev, 2662414c70cbSLiam Girdwood input_uV, output_uV, 2663414c70cbSLiam Girdwood total_uA_load); 26642c608234SMark Brown ret = regulator_mode_constrain(rdev, &mode); 2665e573520bSDavid Brownell if (ret < 0) { 26665da84fd9SJoe Perches rdev_err(rdev, "failed to get optimum mode @ %d uA %d -> %d uV\n", 2667414c70cbSLiam Girdwood total_uA_load, input_uV, output_uV); 2668414c70cbSLiam Girdwood goto out; 2669414c70cbSLiam Girdwood } 2670414c70cbSLiam Girdwood 2671414c70cbSLiam Girdwood ret = rdev->desc->ops->set_mode(rdev, mode); 2672e573520bSDavid Brownell if (ret < 0) { 26735da84fd9SJoe Perches rdev_err(rdev, "failed to set optimum mode %x\n", mode); 2674414c70cbSLiam Girdwood goto out; 2675414c70cbSLiam Girdwood } 2676414c70cbSLiam Girdwood ret = mode; 2677414c70cbSLiam Girdwood out: 2678414c70cbSLiam Girdwood mutex_unlock(&rdev->mutex); 2679414c70cbSLiam Girdwood return ret; 2680414c70cbSLiam Girdwood } 2681414c70cbSLiam Girdwood EXPORT_SYMBOL_GPL(regulator_set_optimum_mode); 2682414c70cbSLiam Girdwood 2683414c70cbSLiam Girdwood /** 2684414c70cbSLiam Girdwood * regulator_register_notifier - register regulator event notifier 2685414c70cbSLiam Girdwood * @regulator: regulator source 268669279fb9SMark Brown * @nb: notifier block 2687414c70cbSLiam Girdwood * 2688414c70cbSLiam Girdwood * Register notifier block to receive regulator events. 2689414c70cbSLiam Girdwood */ 2690414c70cbSLiam Girdwood int regulator_register_notifier(struct regulator *regulator, 2691414c70cbSLiam Girdwood struct notifier_block *nb) 2692414c70cbSLiam Girdwood { 2693414c70cbSLiam Girdwood return blocking_notifier_chain_register(®ulator->rdev->notifier, 2694414c70cbSLiam Girdwood nb); 2695414c70cbSLiam Girdwood } 2696414c70cbSLiam Girdwood EXPORT_SYMBOL_GPL(regulator_register_notifier); 2697414c70cbSLiam Girdwood 2698414c70cbSLiam Girdwood /** 2699414c70cbSLiam Girdwood * regulator_unregister_notifier - unregister regulator event notifier 2700414c70cbSLiam Girdwood * @regulator: regulator source 270169279fb9SMark Brown * @nb: notifier block 2702414c70cbSLiam Girdwood * 2703414c70cbSLiam Girdwood * Unregister regulator event notifier block. 2704414c70cbSLiam Girdwood */ 2705414c70cbSLiam Girdwood int regulator_unregister_notifier(struct regulator *regulator, 2706414c70cbSLiam Girdwood struct notifier_block *nb) 2707414c70cbSLiam Girdwood { 2708414c70cbSLiam Girdwood return blocking_notifier_chain_unregister(®ulator->rdev->notifier, 2709414c70cbSLiam Girdwood nb); 2710414c70cbSLiam Girdwood } 2711414c70cbSLiam Girdwood EXPORT_SYMBOL_GPL(regulator_unregister_notifier); 2712414c70cbSLiam Girdwood 2713b136fb44SJonathan Cameron /* notify regulator consumers and downstream regulator consumers. 2714b136fb44SJonathan Cameron * Note mutex must be held by caller. 2715b136fb44SJonathan Cameron */ 2716414c70cbSLiam Girdwood static void _notifier_call_chain(struct regulator_dev *rdev, 2717414c70cbSLiam Girdwood unsigned long event, void *data) 2718414c70cbSLiam Girdwood { 2719414c70cbSLiam Girdwood /* call rdev chain first */ 2720d8493d21SMark Brown blocking_notifier_call_chain(&rdev->notifier, event, data); 2721414c70cbSLiam Girdwood } 2722414c70cbSLiam Girdwood 2723414c70cbSLiam Girdwood /** 2724414c70cbSLiam Girdwood * regulator_bulk_get - get multiple regulator consumers 2725414c70cbSLiam Girdwood * 2726414c70cbSLiam Girdwood * @dev: Device to supply 2727414c70cbSLiam Girdwood * @num_consumers: Number of consumers to register 2728414c70cbSLiam Girdwood * @consumers: Configuration of consumers; clients are stored here. 2729414c70cbSLiam Girdwood * 2730414c70cbSLiam Girdwood * @return 0 on success, an errno on failure. 2731414c70cbSLiam Girdwood * 2732414c70cbSLiam Girdwood * This helper function allows drivers to get several regulator 2733414c70cbSLiam Girdwood * consumers in one operation. If any of the regulators cannot be 2734414c70cbSLiam Girdwood * acquired then any regulators that were allocated will be freed 2735414c70cbSLiam Girdwood * before returning to the caller. 2736414c70cbSLiam Girdwood */ 2737414c70cbSLiam Girdwood int regulator_bulk_get(struct device *dev, int num_consumers, 2738414c70cbSLiam Girdwood struct regulator_bulk_data *consumers) 2739414c70cbSLiam Girdwood { 2740414c70cbSLiam Girdwood int i; 2741414c70cbSLiam Girdwood int ret; 2742414c70cbSLiam Girdwood 2743414c70cbSLiam Girdwood for (i = 0; i < num_consumers; i++) 2744414c70cbSLiam Girdwood consumers[i].consumer = NULL; 2745414c70cbSLiam Girdwood 2746414c70cbSLiam Girdwood for (i = 0; i < num_consumers; i++) { 2747414c70cbSLiam Girdwood consumers[i].consumer = regulator_get(dev, 2748414c70cbSLiam Girdwood consumers[i].supply); 2749414c70cbSLiam Girdwood if (IS_ERR(consumers[i].consumer)) { 2750414c70cbSLiam Girdwood ret = PTR_ERR(consumers[i].consumer); 27515b307627SMark Brown dev_err(dev, "Failed to get supply '%s': %d\n", 27525b307627SMark Brown consumers[i].supply, ret); 2753414c70cbSLiam Girdwood consumers[i].consumer = NULL; 2754414c70cbSLiam Girdwood goto err; 2755414c70cbSLiam Girdwood } 2756414c70cbSLiam Girdwood } 2757414c70cbSLiam Girdwood 2758414c70cbSLiam Girdwood return 0; 2759414c70cbSLiam Girdwood 2760414c70cbSLiam Girdwood err: 2761b29c7690SAxel Lin while (--i >= 0) 2762414c70cbSLiam Girdwood regulator_put(consumers[i].consumer); 2763414c70cbSLiam Girdwood 2764414c70cbSLiam Girdwood return ret; 2765414c70cbSLiam Girdwood } 2766414c70cbSLiam Girdwood EXPORT_SYMBOL_GPL(regulator_bulk_get); 2767414c70cbSLiam Girdwood 2768e6e74030SMark Brown /** 2769e6e74030SMark Brown * devm_regulator_bulk_get - managed get multiple regulator consumers 2770e6e74030SMark Brown * 2771e6e74030SMark Brown * @dev: Device to supply 2772e6e74030SMark Brown * @num_consumers: Number of consumers to register 2773e6e74030SMark Brown * @consumers: Configuration of consumers; clients are stored here. 2774e6e74030SMark Brown * 2775e6e74030SMark Brown * @return 0 on success, an errno on failure. 2776e6e74030SMark Brown * 2777e6e74030SMark Brown * This helper function allows drivers to get several regulator 2778e6e74030SMark Brown * consumers in one operation with management, the regulators will 2779e6e74030SMark Brown * automatically be freed when the device is unbound. If any of the 2780e6e74030SMark Brown * regulators cannot be acquired then any regulators that were 2781e6e74030SMark Brown * allocated will be freed before returning to the caller. 2782e6e74030SMark Brown */ 2783e6e74030SMark Brown int devm_regulator_bulk_get(struct device *dev, int num_consumers, 2784e6e74030SMark Brown struct regulator_bulk_data *consumers) 2785e6e74030SMark Brown { 2786e6e74030SMark Brown int i; 2787e6e74030SMark Brown int ret; 2788e6e74030SMark Brown 2789e6e74030SMark Brown for (i = 0; i < num_consumers; i++) 2790e6e74030SMark Brown consumers[i].consumer = NULL; 2791e6e74030SMark Brown 2792e6e74030SMark Brown for (i = 0; i < num_consumers; i++) { 2793e6e74030SMark Brown consumers[i].consumer = devm_regulator_get(dev, 2794e6e74030SMark Brown consumers[i].supply); 2795e6e74030SMark Brown if (IS_ERR(consumers[i].consumer)) { 2796e6e74030SMark Brown ret = PTR_ERR(consumers[i].consumer); 2797e6e74030SMark Brown dev_err(dev, "Failed to get supply '%s': %d\n", 2798e6e74030SMark Brown consumers[i].supply, ret); 2799e6e74030SMark Brown consumers[i].consumer = NULL; 2800e6e74030SMark Brown goto err; 2801e6e74030SMark Brown } 2802e6e74030SMark Brown } 2803e6e74030SMark Brown 2804e6e74030SMark Brown return 0; 2805e6e74030SMark Brown 2806e6e74030SMark Brown err: 2807e6e74030SMark Brown for (i = 0; i < num_consumers && consumers[i].consumer; i++) 2808e6e74030SMark Brown devm_regulator_put(consumers[i].consumer); 2809e6e74030SMark Brown 2810e6e74030SMark Brown return ret; 2811e6e74030SMark Brown } 2812e6e74030SMark Brown EXPORT_SYMBOL_GPL(devm_regulator_bulk_get); 2813e6e74030SMark Brown 2814f21e0e81SMark Brown static void regulator_bulk_enable_async(void *data, async_cookie_t cookie) 2815f21e0e81SMark Brown { 2816f21e0e81SMark Brown struct regulator_bulk_data *bulk = data; 2817f21e0e81SMark Brown 2818f21e0e81SMark Brown bulk->ret = regulator_enable(bulk->consumer); 2819f21e0e81SMark Brown } 2820f21e0e81SMark Brown 2821414c70cbSLiam Girdwood /** 2822414c70cbSLiam Girdwood * regulator_bulk_enable - enable multiple regulator consumers 2823414c70cbSLiam Girdwood * 2824414c70cbSLiam Girdwood * @num_consumers: Number of consumers 2825414c70cbSLiam Girdwood * @consumers: Consumer data; clients are stored here. 2826414c70cbSLiam Girdwood * @return 0 on success, an errno on failure 2827414c70cbSLiam Girdwood * 2828414c70cbSLiam Girdwood * This convenience API allows consumers to enable multiple regulator 2829414c70cbSLiam Girdwood * clients in a single API call. If any consumers cannot be enabled 2830414c70cbSLiam Girdwood * then any others that were enabled will be disabled again prior to 2831414c70cbSLiam Girdwood * return. 2832414c70cbSLiam Girdwood */ 2833414c70cbSLiam Girdwood int regulator_bulk_enable(int num_consumers, 2834414c70cbSLiam Girdwood struct regulator_bulk_data *consumers) 2835414c70cbSLiam Girdwood { 28362955b47dSDan Williams ASYNC_DOMAIN_EXCLUSIVE(async_domain); 2837414c70cbSLiam Girdwood int i; 2838f21e0e81SMark Brown int ret = 0; 2839414c70cbSLiam Girdwood 28406492bc1bSMark Brown for (i = 0; i < num_consumers; i++) { 28416492bc1bSMark Brown if (consumers[i].consumer->always_on) 28426492bc1bSMark Brown consumers[i].ret = 0; 28436492bc1bSMark Brown else 2844f21e0e81SMark Brown async_schedule_domain(regulator_bulk_enable_async, 2845f21e0e81SMark Brown &consumers[i], &async_domain); 28466492bc1bSMark Brown } 2847f21e0e81SMark Brown 2848f21e0e81SMark Brown async_synchronize_full_domain(&async_domain); 2849f21e0e81SMark Brown 2850f21e0e81SMark Brown /* If any consumer failed we need to unwind any that succeeded */ 2851414c70cbSLiam Girdwood for (i = 0; i < num_consumers; i++) { 2852f21e0e81SMark Brown if (consumers[i].ret != 0) { 2853f21e0e81SMark Brown ret = consumers[i].ret; 2854414c70cbSLiam Girdwood goto err; 2855414c70cbSLiam Girdwood } 2856f21e0e81SMark Brown } 2857414c70cbSLiam Girdwood 2858414c70cbSLiam Girdwood return 0; 2859414c70cbSLiam Girdwood 2860414c70cbSLiam Girdwood err: 2861b29c7690SAxel Lin pr_err("Failed to enable %s: %d\n", consumers[i].supply, ret); 2862b29c7690SAxel Lin while (--i >= 0) 2863414c70cbSLiam Girdwood regulator_disable(consumers[i].consumer); 2864414c70cbSLiam Girdwood 2865414c70cbSLiam Girdwood return ret; 2866414c70cbSLiam Girdwood } 2867414c70cbSLiam Girdwood EXPORT_SYMBOL_GPL(regulator_bulk_enable); 2868414c70cbSLiam Girdwood 2869414c70cbSLiam Girdwood /** 2870414c70cbSLiam Girdwood * regulator_bulk_disable - disable multiple regulator consumers 2871414c70cbSLiam Girdwood * 2872414c70cbSLiam Girdwood * @num_consumers: Number of consumers 2873414c70cbSLiam Girdwood * @consumers: Consumer data; clients are stored here. 2874414c70cbSLiam Girdwood * @return 0 on success, an errno on failure 2875414c70cbSLiam Girdwood * 2876414c70cbSLiam Girdwood * This convenience API allows consumers to disable multiple regulator 287749e22632SSylwester Nawrocki * clients in a single API call. If any consumers cannot be disabled 287849e22632SSylwester Nawrocki * then any others that were disabled will be enabled again prior to 2879414c70cbSLiam Girdwood * return. 2880414c70cbSLiam Girdwood */ 2881414c70cbSLiam Girdwood int regulator_bulk_disable(int num_consumers, 2882414c70cbSLiam Girdwood struct regulator_bulk_data *consumers) 2883414c70cbSLiam Girdwood { 2884414c70cbSLiam Girdwood int i; 288501e86f49SMark Brown int ret, r; 2886414c70cbSLiam Girdwood 288749e22632SSylwester Nawrocki for (i = num_consumers - 1; i >= 0; --i) { 2888414c70cbSLiam Girdwood ret = regulator_disable(consumers[i].consumer); 2889414c70cbSLiam Girdwood if (ret != 0) 2890414c70cbSLiam Girdwood goto err; 2891414c70cbSLiam Girdwood } 2892414c70cbSLiam Girdwood 2893414c70cbSLiam Girdwood return 0; 2894414c70cbSLiam Girdwood 2895414c70cbSLiam Girdwood err: 28965da84fd9SJoe Perches pr_err("Failed to disable %s: %d\n", consumers[i].supply, ret); 289701e86f49SMark Brown for (++i; i < num_consumers; ++i) { 289801e86f49SMark Brown r = regulator_enable(consumers[i].consumer); 289901e86f49SMark Brown if (r != 0) 290001e86f49SMark Brown pr_err("Failed to reename %s: %d\n", 290101e86f49SMark Brown consumers[i].supply, r); 290201e86f49SMark Brown } 2903414c70cbSLiam Girdwood 2904414c70cbSLiam Girdwood return ret; 2905414c70cbSLiam Girdwood } 2906414c70cbSLiam Girdwood EXPORT_SYMBOL_GPL(regulator_bulk_disable); 2907414c70cbSLiam Girdwood 2908414c70cbSLiam Girdwood /** 2909e1de2f42SDonggeun Kim * regulator_bulk_force_disable - force disable multiple regulator consumers 2910e1de2f42SDonggeun Kim * 2911e1de2f42SDonggeun Kim * @num_consumers: Number of consumers 2912e1de2f42SDonggeun Kim * @consumers: Consumer data; clients are stored here. 2913e1de2f42SDonggeun Kim * @return 0 on success, an errno on failure 2914e1de2f42SDonggeun Kim * 2915e1de2f42SDonggeun Kim * This convenience API allows consumers to forcibly disable multiple regulator 2916e1de2f42SDonggeun Kim * clients in a single API call. 2917e1de2f42SDonggeun Kim * NOTE: This should be used for situations when device damage will 2918e1de2f42SDonggeun Kim * likely occur if the regulators are not disabled (e.g. over temp). 2919e1de2f42SDonggeun Kim * Although regulator_force_disable function call for some consumers can 2920e1de2f42SDonggeun Kim * return error numbers, the function is called for all consumers. 2921e1de2f42SDonggeun Kim */ 2922e1de2f42SDonggeun Kim int regulator_bulk_force_disable(int num_consumers, 2923e1de2f42SDonggeun Kim struct regulator_bulk_data *consumers) 2924e1de2f42SDonggeun Kim { 2925e1de2f42SDonggeun Kim int i; 2926e1de2f42SDonggeun Kim int ret; 2927e1de2f42SDonggeun Kim 2928e1de2f42SDonggeun Kim for (i = 0; i < num_consumers; i++) 2929e1de2f42SDonggeun Kim consumers[i].ret = 2930e1de2f42SDonggeun Kim regulator_force_disable(consumers[i].consumer); 2931e1de2f42SDonggeun Kim 2932e1de2f42SDonggeun Kim for (i = 0; i < num_consumers; i++) { 2933e1de2f42SDonggeun Kim if (consumers[i].ret != 0) { 2934e1de2f42SDonggeun Kim ret = consumers[i].ret; 2935e1de2f42SDonggeun Kim goto out; 2936e1de2f42SDonggeun Kim } 2937e1de2f42SDonggeun Kim } 2938e1de2f42SDonggeun Kim 2939e1de2f42SDonggeun Kim return 0; 2940e1de2f42SDonggeun Kim out: 2941e1de2f42SDonggeun Kim return ret; 2942e1de2f42SDonggeun Kim } 2943e1de2f42SDonggeun Kim EXPORT_SYMBOL_GPL(regulator_bulk_force_disable); 2944e1de2f42SDonggeun Kim 2945e1de2f42SDonggeun Kim /** 2946414c70cbSLiam Girdwood * regulator_bulk_free - free multiple regulator consumers 2947414c70cbSLiam Girdwood * 2948414c70cbSLiam Girdwood * @num_consumers: Number of consumers 2949414c70cbSLiam Girdwood * @consumers: Consumer data; clients are stored here. 2950414c70cbSLiam Girdwood * 2951414c70cbSLiam Girdwood * This convenience API allows consumers to free multiple regulator 2952414c70cbSLiam Girdwood * clients in a single API call. 2953414c70cbSLiam Girdwood */ 2954414c70cbSLiam Girdwood void regulator_bulk_free(int num_consumers, 2955414c70cbSLiam Girdwood struct regulator_bulk_data *consumers) 2956414c70cbSLiam Girdwood { 2957414c70cbSLiam Girdwood int i; 2958414c70cbSLiam Girdwood 2959414c70cbSLiam Girdwood for (i = 0; i < num_consumers; i++) { 2960414c70cbSLiam Girdwood regulator_put(consumers[i].consumer); 2961414c70cbSLiam Girdwood consumers[i].consumer = NULL; 2962414c70cbSLiam Girdwood } 2963414c70cbSLiam Girdwood } 2964414c70cbSLiam Girdwood EXPORT_SYMBOL_GPL(regulator_bulk_free); 2965414c70cbSLiam Girdwood 2966414c70cbSLiam Girdwood /** 2967414c70cbSLiam Girdwood * regulator_notifier_call_chain - call regulator event notifier 296869279fb9SMark Brown * @rdev: regulator source 2969414c70cbSLiam Girdwood * @event: notifier block 297069279fb9SMark Brown * @data: callback-specific data. 2971414c70cbSLiam Girdwood * 2972414c70cbSLiam Girdwood * Called by regulator drivers to notify clients a regulator event has 2973414c70cbSLiam Girdwood * occurred. We also notify regulator clients downstream. 2974b136fb44SJonathan Cameron * Note lock must be held by caller. 2975414c70cbSLiam Girdwood */ 2976414c70cbSLiam Girdwood int regulator_notifier_call_chain(struct regulator_dev *rdev, 2977414c70cbSLiam Girdwood unsigned long event, void *data) 2978414c70cbSLiam Girdwood { 2979414c70cbSLiam Girdwood _notifier_call_chain(rdev, event, data); 2980414c70cbSLiam Girdwood return NOTIFY_DONE; 2981414c70cbSLiam Girdwood 2982414c70cbSLiam Girdwood } 2983414c70cbSLiam Girdwood EXPORT_SYMBOL_GPL(regulator_notifier_call_chain); 2984414c70cbSLiam Girdwood 2985be721979SMark Brown /** 2986be721979SMark Brown * regulator_mode_to_status - convert a regulator mode into a status 2987be721979SMark Brown * 2988be721979SMark Brown * @mode: Mode to convert 2989be721979SMark Brown * 2990be721979SMark Brown * Convert a regulator mode into a status. 2991be721979SMark Brown */ 2992be721979SMark Brown int regulator_mode_to_status(unsigned int mode) 2993be721979SMark Brown { 2994be721979SMark Brown switch (mode) { 2995be721979SMark Brown case REGULATOR_MODE_FAST: 2996be721979SMark Brown return REGULATOR_STATUS_FAST; 2997be721979SMark Brown case REGULATOR_MODE_NORMAL: 2998be721979SMark Brown return REGULATOR_STATUS_NORMAL; 2999be721979SMark Brown case REGULATOR_MODE_IDLE: 3000be721979SMark Brown return REGULATOR_STATUS_IDLE; 300103ffcf3dSKrystian Garbaciak case REGULATOR_MODE_STANDBY: 3002be721979SMark Brown return REGULATOR_STATUS_STANDBY; 3003be721979SMark Brown default: 30041beaf762SKrystian Garbaciak return REGULATOR_STATUS_UNDEFINED; 3005be721979SMark Brown } 3006be721979SMark Brown } 3007be721979SMark Brown EXPORT_SYMBOL_GPL(regulator_mode_to_status); 3008be721979SMark Brown 30097ad68e2fSDavid Brownell /* 30107ad68e2fSDavid Brownell * To avoid cluttering sysfs (and memory) with useless state, only 30117ad68e2fSDavid Brownell * create attributes that can be meaningfully displayed. 30127ad68e2fSDavid Brownell */ 30137ad68e2fSDavid Brownell static int add_regulator_attributes(struct regulator_dev *rdev) 30147ad68e2fSDavid Brownell { 30157ad68e2fSDavid Brownell struct device *dev = &rdev->dev; 30167ad68e2fSDavid Brownell struct regulator_ops *ops = rdev->desc->ops; 30177ad68e2fSDavid Brownell int status = 0; 30187ad68e2fSDavid Brownell 30197ad68e2fSDavid Brownell /* some attributes need specific methods to be displayed */ 30204c78899bSMark Brown if ((ops->get_voltage && ops->get_voltage(rdev) >= 0) || 30214c78899bSMark Brown (ops->get_voltage_sel && ops->get_voltage_sel(rdev) >= 0)) { 30227ad68e2fSDavid Brownell status = device_create_file(dev, &dev_attr_microvolts); 30237ad68e2fSDavid Brownell if (status < 0) 30247ad68e2fSDavid Brownell return status; 30257ad68e2fSDavid Brownell } 30267ad68e2fSDavid Brownell if (ops->get_current_limit) { 30277ad68e2fSDavid Brownell status = device_create_file(dev, &dev_attr_microamps); 30287ad68e2fSDavid Brownell if (status < 0) 30297ad68e2fSDavid Brownell return status; 30307ad68e2fSDavid Brownell } 30317ad68e2fSDavid Brownell if (ops->get_mode) { 30327ad68e2fSDavid Brownell status = device_create_file(dev, &dev_attr_opmode); 30337ad68e2fSDavid Brownell if (status < 0) 30347ad68e2fSDavid Brownell return status; 30357ad68e2fSDavid Brownell } 30367ad68e2fSDavid Brownell if (ops->is_enabled) { 30377ad68e2fSDavid Brownell status = device_create_file(dev, &dev_attr_state); 30387ad68e2fSDavid Brownell if (status < 0) 30397ad68e2fSDavid Brownell return status; 30407ad68e2fSDavid Brownell } 3041853116a1SDavid Brownell if (ops->get_status) { 3042853116a1SDavid Brownell status = device_create_file(dev, &dev_attr_status); 3043853116a1SDavid Brownell if (status < 0) 3044853116a1SDavid Brownell return status; 3045853116a1SDavid Brownell } 30467ad68e2fSDavid Brownell 30477ad68e2fSDavid Brownell /* some attributes are type-specific */ 30487ad68e2fSDavid Brownell if (rdev->desc->type == REGULATOR_CURRENT) { 30497ad68e2fSDavid Brownell status = device_create_file(dev, &dev_attr_requested_microamps); 30507ad68e2fSDavid Brownell if (status < 0) 30517ad68e2fSDavid Brownell return status; 30527ad68e2fSDavid Brownell } 30537ad68e2fSDavid Brownell 30547ad68e2fSDavid Brownell /* all the other attributes exist to support constraints; 30557ad68e2fSDavid Brownell * don't show them if there are no constraints, or if the 30567ad68e2fSDavid Brownell * relevant supporting methods are missing. 30577ad68e2fSDavid Brownell */ 30587ad68e2fSDavid Brownell if (!rdev->constraints) 30597ad68e2fSDavid Brownell return status; 30607ad68e2fSDavid Brownell 30617ad68e2fSDavid Brownell /* constraints need specific supporting methods */ 3062e8eef82bSMark Brown if (ops->set_voltage || ops->set_voltage_sel) { 30637ad68e2fSDavid Brownell status = device_create_file(dev, &dev_attr_min_microvolts); 30647ad68e2fSDavid Brownell if (status < 0) 30657ad68e2fSDavid Brownell return status; 30667ad68e2fSDavid Brownell status = device_create_file(dev, &dev_attr_max_microvolts); 30677ad68e2fSDavid Brownell if (status < 0) 30687ad68e2fSDavid Brownell return status; 30697ad68e2fSDavid Brownell } 30707ad68e2fSDavid Brownell if (ops->set_current_limit) { 30717ad68e2fSDavid Brownell status = device_create_file(dev, &dev_attr_min_microamps); 30727ad68e2fSDavid Brownell if (status < 0) 30737ad68e2fSDavid Brownell return status; 30747ad68e2fSDavid Brownell status = device_create_file(dev, &dev_attr_max_microamps); 30757ad68e2fSDavid Brownell if (status < 0) 30767ad68e2fSDavid Brownell return status; 30777ad68e2fSDavid Brownell } 30787ad68e2fSDavid Brownell 30797ad68e2fSDavid Brownell status = device_create_file(dev, &dev_attr_suspend_standby_state); 30807ad68e2fSDavid Brownell if (status < 0) 30817ad68e2fSDavid Brownell return status; 30827ad68e2fSDavid Brownell status = device_create_file(dev, &dev_attr_suspend_mem_state); 30837ad68e2fSDavid Brownell if (status < 0) 30847ad68e2fSDavid Brownell return status; 30857ad68e2fSDavid Brownell status = device_create_file(dev, &dev_attr_suspend_disk_state); 30867ad68e2fSDavid Brownell if (status < 0) 30877ad68e2fSDavid Brownell return status; 30887ad68e2fSDavid Brownell 30897ad68e2fSDavid Brownell if (ops->set_suspend_voltage) { 30907ad68e2fSDavid Brownell status = device_create_file(dev, 30917ad68e2fSDavid Brownell &dev_attr_suspend_standby_microvolts); 30927ad68e2fSDavid Brownell if (status < 0) 30937ad68e2fSDavid Brownell return status; 30947ad68e2fSDavid Brownell status = device_create_file(dev, 30957ad68e2fSDavid Brownell &dev_attr_suspend_mem_microvolts); 30967ad68e2fSDavid Brownell if (status < 0) 30977ad68e2fSDavid Brownell return status; 30987ad68e2fSDavid Brownell status = device_create_file(dev, 30997ad68e2fSDavid Brownell &dev_attr_suspend_disk_microvolts); 31007ad68e2fSDavid Brownell if (status < 0) 31017ad68e2fSDavid Brownell return status; 31027ad68e2fSDavid Brownell } 31037ad68e2fSDavid Brownell 31047ad68e2fSDavid Brownell if (ops->set_suspend_mode) { 31057ad68e2fSDavid Brownell status = device_create_file(dev, 31067ad68e2fSDavid Brownell &dev_attr_suspend_standby_mode); 31077ad68e2fSDavid Brownell if (status < 0) 31087ad68e2fSDavid Brownell return status; 31097ad68e2fSDavid Brownell status = device_create_file(dev, 31107ad68e2fSDavid Brownell &dev_attr_suspend_mem_mode); 31117ad68e2fSDavid Brownell if (status < 0) 31127ad68e2fSDavid Brownell return status; 31137ad68e2fSDavid Brownell status = device_create_file(dev, 31147ad68e2fSDavid Brownell &dev_attr_suspend_disk_mode); 31157ad68e2fSDavid Brownell if (status < 0) 31167ad68e2fSDavid Brownell return status; 31177ad68e2fSDavid Brownell } 31187ad68e2fSDavid Brownell 31197ad68e2fSDavid Brownell return status; 31207ad68e2fSDavid Brownell } 31217ad68e2fSDavid Brownell 31221130e5b3SMark Brown static void rdev_init_debugfs(struct regulator_dev *rdev) 31231130e5b3SMark Brown { 31241130e5b3SMark Brown rdev->debugfs = debugfs_create_dir(rdev_get_name(rdev), debugfs_root); 312524751434SStephen Boyd if (!rdev->debugfs) { 31261130e5b3SMark Brown rdev_warn(rdev, "Failed to create debugfs directory\n"); 31271130e5b3SMark Brown return; 31281130e5b3SMark Brown } 31291130e5b3SMark Brown 31301130e5b3SMark Brown debugfs_create_u32("use_count", 0444, rdev->debugfs, 31311130e5b3SMark Brown &rdev->use_count); 31321130e5b3SMark Brown debugfs_create_u32("open_count", 0444, rdev->debugfs, 31331130e5b3SMark Brown &rdev->open_count); 31341130e5b3SMark Brown } 31351130e5b3SMark Brown 3136414c70cbSLiam Girdwood /** 3137414c70cbSLiam Girdwood * regulator_register - register regulator 313869279fb9SMark Brown * @regulator_desc: regulator to register 3139c172708dSMark Brown * @config: runtime configuration for regulator 3140414c70cbSLiam Girdwood * 3141414c70cbSLiam Girdwood * Called by regulator drivers to register a regulator. 3142414c70cbSLiam Girdwood * Returns 0 on success. 3143414c70cbSLiam Girdwood */ 314465f26846SMark Brown struct regulator_dev * 314565f26846SMark Brown regulator_register(const struct regulator_desc *regulator_desc, 3146c172708dSMark Brown const struct regulator_config *config) 3147414c70cbSLiam Girdwood { 31489a8f5e07SMark Brown const struct regulation_constraints *constraints = NULL; 3149c172708dSMark Brown const struct regulator_init_data *init_data; 3150414c70cbSLiam Girdwood static atomic_t regulator_no = ATOMIC_INIT(0); 3151414c70cbSLiam Girdwood struct regulator_dev *rdev; 315232c8fad4SMark Brown struct device *dev; 3153a5766f11SLiam Girdwood int ret, i; 315469511a45SRajendra Nayak const char *supply = NULL; 3155414c70cbSLiam Girdwood 3156c172708dSMark Brown if (regulator_desc == NULL || config == NULL) 3157414c70cbSLiam Girdwood return ERR_PTR(-EINVAL); 3158414c70cbSLiam Girdwood 315932c8fad4SMark Brown dev = config->dev; 3160dcf70112SMark Brown WARN_ON(!dev); 316132c8fad4SMark Brown 3162414c70cbSLiam Girdwood if (regulator_desc->name == NULL || regulator_desc->ops == NULL) 3163414c70cbSLiam Girdwood return ERR_PTR(-EINVAL); 3164414c70cbSLiam Girdwood 3165cd78dfc6SDiego Liziero if (regulator_desc->type != REGULATOR_VOLTAGE && 3166cd78dfc6SDiego Liziero regulator_desc->type != REGULATOR_CURRENT) 3167414c70cbSLiam Girdwood return ERR_PTR(-EINVAL); 3168414c70cbSLiam Girdwood 3169476c2d83SMark Brown /* Only one of each should be implemented */ 3170476c2d83SMark Brown WARN_ON(regulator_desc->ops->get_voltage && 3171476c2d83SMark Brown regulator_desc->ops->get_voltage_sel); 3172e8eef82bSMark Brown WARN_ON(regulator_desc->ops->set_voltage && 3173e8eef82bSMark Brown regulator_desc->ops->set_voltage_sel); 3174476c2d83SMark Brown 3175476c2d83SMark Brown /* If we're using selectors we must implement list_voltage. */ 3176476c2d83SMark Brown if (regulator_desc->ops->get_voltage_sel && 3177476c2d83SMark Brown !regulator_desc->ops->list_voltage) { 3178476c2d83SMark Brown return ERR_PTR(-EINVAL); 3179476c2d83SMark Brown } 3180e8eef82bSMark Brown if (regulator_desc->ops->set_voltage_sel && 3181e8eef82bSMark Brown !regulator_desc->ops->list_voltage) { 3182e8eef82bSMark Brown return ERR_PTR(-EINVAL); 3183e8eef82bSMark Brown } 3184476c2d83SMark Brown 3185c172708dSMark Brown init_data = config->init_data; 3186c172708dSMark Brown 3187414c70cbSLiam Girdwood rdev = kzalloc(sizeof(struct regulator_dev), GFP_KERNEL); 3188414c70cbSLiam Girdwood if (rdev == NULL) 3189414c70cbSLiam Girdwood return ERR_PTR(-ENOMEM); 3190414c70cbSLiam Girdwood 3191414c70cbSLiam Girdwood mutex_lock(®ulator_list_mutex); 3192414c70cbSLiam Girdwood 3193414c70cbSLiam Girdwood mutex_init(&rdev->mutex); 3194c172708dSMark Brown rdev->reg_data = config->driver_data; 3195414c70cbSLiam Girdwood rdev->owner = regulator_desc->owner; 3196414c70cbSLiam Girdwood rdev->desc = regulator_desc; 31973a4b0a07SMark Brown if (config->regmap) 319865b19ce6SMark Brown rdev->regmap = config->regmap; 31993a4b0a07SMark Brown else 32003a4b0a07SMark Brown rdev->regmap = dev_get_regmap(dev, NULL); 3201414c70cbSLiam Girdwood INIT_LIST_HEAD(&rdev->consumer_list); 3202414c70cbSLiam Girdwood INIT_LIST_HEAD(&rdev->list); 3203414c70cbSLiam Girdwood BLOCKING_INIT_NOTIFIER_HEAD(&rdev->notifier); 3204da07ecd9SMark Brown INIT_DELAYED_WORK(&rdev->disable_work, regulator_disable_work); 3205414c70cbSLiam Girdwood 3206a5766f11SLiam Girdwood /* preform any regulator specific init */ 32079a8f5e07SMark Brown if (init_data && init_data->regulator_init) { 3208a5766f11SLiam Girdwood ret = init_data->regulator_init(rdev->reg_data); 32094fca9545SDavid Brownell if (ret < 0) 32104fca9545SDavid Brownell goto clean; 3211a5766f11SLiam Girdwood } 3212a5766f11SLiam Girdwood 3213a5766f11SLiam Girdwood /* register with sysfs */ 3214a5766f11SLiam Girdwood rdev->dev.class = ®ulator_class; 3215c172708dSMark Brown rdev->dev.of_node = config->of_node; 3216a5766f11SLiam Girdwood rdev->dev.parent = dev; 3217812460a9SKay Sievers dev_set_name(&rdev->dev, "regulator.%d", 3218812460a9SKay Sievers atomic_inc_return(®ulator_no) - 1); 3219a5766f11SLiam Girdwood ret = device_register(&rdev->dev); 3220ad7725cbSVasiliy Kulikov if (ret != 0) { 3221ad7725cbSVasiliy Kulikov put_device(&rdev->dev); 32224fca9545SDavid Brownell goto clean; 3223ad7725cbSVasiliy Kulikov } 3224a5766f11SLiam Girdwood 3225a5766f11SLiam Girdwood dev_set_drvdata(&rdev->dev, rdev); 3226a5766f11SLiam Girdwood 322765f73508SMark Brown if (config->ena_gpio) { 322865f73508SMark Brown ret = gpio_request_one(config->ena_gpio, 322965f73508SMark Brown GPIOF_DIR_OUT | config->ena_gpio_flags, 323065f73508SMark Brown rdev_get_name(rdev)); 323165f73508SMark Brown if (ret != 0) { 323265f73508SMark Brown rdev_err(rdev, "Failed to request enable GPIO%d: %d\n", 323365f73508SMark Brown config->ena_gpio, ret); 323465f73508SMark Brown goto clean; 323565f73508SMark Brown } 323665f73508SMark Brown 323765f73508SMark Brown rdev->ena_gpio = config->ena_gpio; 323865f73508SMark Brown rdev->ena_gpio_invert = config->ena_gpio_invert; 323965f73508SMark Brown 324065f73508SMark Brown if (config->ena_gpio_flags & GPIOF_OUT_INIT_HIGH) 324165f73508SMark Brown rdev->ena_gpio_state = 1; 324265f73508SMark Brown 324365f73508SMark Brown if (rdev->ena_gpio_invert) 324465f73508SMark Brown rdev->ena_gpio_state = !rdev->ena_gpio_state; 324565f73508SMark Brown } 324665f73508SMark Brown 324774f544c1SMike Rapoport /* set regulator constraints */ 32489a8f5e07SMark Brown if (init_data) 32499a8f5e07SMark Brown constraints = &init_data->constraints; 32509a8f5e07SMark Brown 32519a8f5e07SMark Brown ret = set_machine_constraints(rdev, constraints); 325274f544c1SMike Rapoport if (ret < 0) 325374f544c1SMike Rapoport goto scrub; 325474f544c1SMike Rapoport 32557ad68e2fSDavid Brownell /* add attributes supported by this regulator */ 32567ad68e2fSDavid Brownell ret = add_regulator_attributes(rdev); 32577ad68e2fSDavid Brownell if (ret < 0) 32587ad68e2fSDavid Brownell goto scrub; 32597ad68e2fSDavid Brownell 32609a8f5e07SMark Brown if (init_data && init_data->supply_regulator) 326169511a45SRajendra Nayak supply = init_data->supply_regulator; 326269511a45SRajendra Nayak else if (regulator_desc->supply_name) 326369511a45SRajendra Nayak supply = regulator_desc->supply_name; 326469511a45SRajendra Nayak 326569511a45SRajendra Nayak if (supply) { 32660178f3e2SMark Brown struct regulator_dev *r; 32670178f3e2SMark Brown 32686d191a5fSMark Brown r = regulator_dev_lookup(dev, supply, &ret); 32690178f3e2SMark Brown 327069511a45SRajendra Nayak if (!r) { 327169511a45SRajendra Nayak dev_err(dev, "Failed to find supply %s\n", supply); 327204bf3011SMark Brown ret = -EPROBE_DEFER; 32730178f3e2SMark Brown goto scrub; 32740178f3e2SMark Brown } 32750178f3e2SMark Brown 32760178f3e2SMark Brown ret = set_supply(rdev, r); 32770178f3e2SMark Brown if (ret < 0) 32780178f3e2SMark Brown goto scrub; 3279b2296bd4SLaxman Dewangan 3280b2296bd4SLaxman Dewangan /* Enable supply if rail is enabled */ 3281b1a86831SMark Brown if (_regulator_is_enabled(rdev)) { 3282b2296bd4SLaxman Dewangan ret = regulator_enable(rdev->supply); 3283b2296bd4SLaxman Dewangan if (ret < 0) 3284b2296bd4SLaxman Dewangan goto scrub; 3285b2296bd4SLaxman Dewangan } 32860178f3e2SMark Brown } 32870178f3e2SMark Brown 3288a5766f11SLiam Girdwood /* add consumers devices */ 32899a8f5e07SMark Brown if (init_data) { 3290a5766f11SLiam Girdwood for (i = 0; i < init_data->num_consumer_supplies; i++) { 3291a5766f11SLiam Girdwood ret = set_consumer_device_supply(rdev, 329240f9244fSMark Brown init_data->consumer_supplies[i].dev_name, 3293a5766f11SLiam Girdwood init_data->consumer_supplies[i].supply); 329423c2f041SMark Brown if (ret < 0) { 329523c2f041SMark Brown dev_err(dev, "Failed to set supply %s\n", 329623c2f041SMark Brown init_data->consumer_supplies[i].supply); 3297d4033b54SJani Nikula goto unset_supplies; 3298a5766f11SLiam Girdwood } 329923c2f041SMark Brown } 33009a8f5e07SMark Brown } 3301a5766f11SLiam Girdwood 3302a5766f11SLiam Girdwood list_add(&rdev->list, ®ulator_list); 33031130e5b3SMark Brown 33041130e5b3SMark Brown rdev_init_debugfs(rdev); 3305a5766f11SLiam Girdwood out: 3306414c70cbSLiam Girdwood mutex_unlock(®ulator_list_mutex); 3307414c70cbSLiam Girdwood return rdev; 33084fca9545SDavid Brownell 3309d4033b54SJani Nikula unset_supplies: 3310d4033b54SJani Nikula unset_regulator_supplies(rdev); 3311d4033b54SJani Nikula 33124fca9545SDavid Brownell scrub: 3313e81dba85SMark Brown if (rdev->supply) 3314e81dba85SMark Brown regulator_put(rdev->supply); 331565f73508SMark Brown if (rdev->ena_gpio) 331665f73508SMark Brown gpio_free(rdev->ena_gpio); 33171a6958e7SAxel Lin kfree(rdev->constraints); 33184fca9545SDavid Brownell device_unregister(&rdev->dev); 331953032dafSPaul Walmsley /* device core frees rdev */ 332053032dafSPaul Walmsley rdev = ERR_PTR(ret); 332153032dafSPaul Walmsley goto out; 332253032dafSPaul Walmsley 33234fca9545SDavid Brownell clean: 33244fca9545SDavid Brownell kfree(rdev); 33254fca9545SDavid Brownell rdev = ERR_PTR(ret); 33264fca9545SDavid Brownell goto out; 3327414c70cbSLiam Girdwood } 3328414c70cbSLiam Girdwood EXPORT_SYMBOL_GPL(regulator_register); 3329414c70cbSLiam Girdwood 3330414c70cbSLiam Girdwood /** 3331414c70cbSLiam Girdwood * regulator_unregister - unregister regulator 333269279fb9SMark Brown * @rdev: regulator to unregister 3333414c70cbSLiam Girdwood * 3334414c70cbSLiam Girdwood * Called by regulator drivers to unregister a regulator. 3335414c70cbSLiam Girdwood */ 3336414c70cbSLiam Girdwood void regulator_unregister(struct regulator_dev *rdev) 3337414c70cbSLiam Girdwood { 3338414c70cbSLiam Girdwood if (rdev == NULL) 3339414c70cbSLiam Girdwood return; 3340414c70cbSLiam Girdwood 3341e032b376SMark Brown if (rdev->supply) 3342e032b376SMark Brown regulator_put(rdev->supply); 3343414c70cbSLiam Girdwood mutex_lock(®ulator_list_mutex); 33441130e5b3SMark Brown debugfs_remove_recursive(rdev->debugfs); 3345da07ecd9SMark Brown flush_work_sync(&rdev->disable_work.work); 33466bf87d17SMark Brown WARN_ON(rdev->open_count); 33470f1d747bSMike Rapoport unset_regulator_supplies(rdev); 3348414c70cbSLiam Girdwood list_del(&rdev->list); 3349f8c12fe3SMark Brown kfree(rdev->constraints); 335065f73508SMark Brown if (rdev->ena_gpio) 335165f73508SMark Brown gpio_free(rdev->ena_gpio); 335258fb5cf5SLothar Waßmann device_unregister(&rdev->dev); 3353414c70cbSLiam Girdwood mutex_unlock(®ulator_list_mutex); 3354414c70cbSLiam Girdwood } 3355414c70cbSLiam Girdwood EXPORT_SYMBOL_GPL(regulator_unregister); 3356414c70cbSLiam Girdwood 3357414c70cbSLiam Girdwood /** 3358cf7bbcdfSMark Brown * regulator_suspend_prepare - prepare regulators for system wide suspend 3359414c70cbSLiam Girdwood * @state: system suspend state 3360414c70cbSLiam Girdwood * 3361414c70cbSLiam Girdwood * Configure each regulator with it's suspend operating parameters for state. 3362414c70cbSLiam Girdwood * This will usually be called by machine suspend code prior to supending. 3363414c70cbSLiam Girdwood */ 3364414c70cbSLiam Girdwood int regulator_suspend_prepare(suspend_state_t state) 3365414c70cbSLiam Girdwood { 3366414c70cbSLiam Girdwood struct regulator_dev *rdev; 3367414c70cbSLiam Girdwood int ret = 0; 3368414c70cbSLiam Girdwood 3369414c70cbSLiam Girdwood /* ON is handled by regulator active state */ 3370414c70cbSLiam Girdwood if (state == PM_SUSPEND_ON) 3371414c70cbSLiam Girdwood return -EINVAL; 3372414c70cbSLiam Girdwood 3373414c70cbSLiam Girdwood mutex_lock(®ulator_list_mutex); 3374414c70cbSLiam Girdwood list_for_each_entry(rdev, ®ulator_list, list) { 3375414c70cbSLiam Girdwood 3376414c70cbSLiam Girdwood mutex_lock(&rdev->mutex); 3377414c70cbSLiam Girdwood ret = suspend_prepare(rdev, state); 3378414c70cbSLiam Girdwood mutex_unlock(&rdev->mutex); 3379414c70cbSLiam Girdwood 3380414c70cbSLiam Girdwood if (ret < 0) { 33815da84fd9SJoe Perches rdev_err(rdev, "failed to prepare\n"); 3382414c70cbSLiam Girdwood goto out; 3383414c70cbSLiam Girdwood } 3384414c70cbSLiam Girdwood } 3385414c70cbSLiam Girdwood out: 3386414c70cbSLiam Girdwood mutex_unlock(®ulator_list_mutex); 3387414c70cbSLiam Girdwood return ret; 3388414c70cbSLiam Girdwood } 3389414c70cbSLiam Girdwood EXPORT_SYMBOL_GPL(regulator_suspend_prepare); 3390414c70cbSLiam Girdwood 3391414c70cbSLiam Girdwood /** 33927a32b589SMyungJoo Ham * regulator_suspend_finish - resume regulators from system wide suspend 33937a32b589SMyungJoo Ham * 33947a32b589SMyungJoo Ham * Turn on regulators that might be turned off by regulator_suspend_prepare 33957a32b589SMyungJoo Ham * and that should be turned on according to the regulators properties. 33967a32b589SMyungJoo Ham */ 33977a32b589SMyungJoo Ham int regulator_suspend_finish(void) 33987a32b589SMyungJoo Ham { 33997a32b589SMyungJoo Ham struct regulator_dev *rdev; 34007a32b589SMyungJoo Ham int ret = 0, error; 34017a32b589SMyungJoo Ham 34027a32b589SMyungJoo Ham mutex_lock(®ulator_list_mutex); 34037a32b589SMyungJoo Ham list_for_each_entry(rdev, ®ulator_list, list) { 34047a32b589SMyungJoo Ham struct regulator_ops *ops = rdev->desc->ops; 34057a32b589SMyungJoo Ham 34067a32b589SMyungJoo Ham mutex_lock(&rdev->mutex); 34077a32b589SMyungJoo Ham if ((rdev->use_count > 0 || rdev->constraints->always_on) && 34087a32b589SMyungJoo Ham ops->enable) { 34097a32b589SMyungJoo Ham error = ops->enable(rdev); 34107a32b589SMyungJoo Ham if (error) 34117a32b589SMyungJoo Ham ret = error; 34127a32b589SMyungJoo Ham } else { 34137a32b589SMyungJoo Ham if (!has_full_constraints) 34147a32b589SMyungJoo Ham goto unlock; 34157a32b589SMyungJoo Ham if (!ops->disable) 34167a32b589SMyungJoo Ham goto unlock; 3417b1a86831SMark Brown if (!_regulator_is_enabled(rdev)) 34187a32b589SMyungJoo Ham goto unlock; 34197a32b589SMyungJoo Ham 34207a32b589SMyungJoo Ham error = ops->disable(rdev); 34217a32b589SMyungJoo Ham if (error) 34227a32b589SMyungJoo Ham ret = error; 34237a32b589SMyungJoo Ham } 34247a32b589SMyungJoo Ham unlock: 34257a32b589SMyungJoo Ham mutex_unlock(&rdev->mutex); 34267a32b589SMyungJoo Ham } 34277a32b589SMyungJoo Ham mutex_unlock(®ulator_list_mutex); 34287a32b589SMyungJoo Ham return ret; 34297a32b589SMyungJoo Ham } 34307a32b589SMyungJoo Ham EXPORT_SYMBOL_GPL(regulator_suspend_finish); 34317a32b589SMyungJoo Ham 34327a32b589SMyungJoo Ham /** 3433ca725561SMark Brown * regulator_has_full_constraints - the system has fully specified constraints 3434ca725561SMark Brown * 3435ca725561SMark Brown * Calling this function will cause the regulator API to disable all 3436ca725561SMark Brown * regulators which have a zero use count and don't have an always_on 3437ca725561SMark Brown * constraint in a late_initcall. 3438ca725561SMark Brown * 3439ca725561SMark Brown * The intention is that this will become the default behaviour in a 3440ca725561SMark Brown * future kernel release so users are encouraged to use this facility 3441ca725561SMark Brown * now. 3442ca725561SMark Brown */ 3443ca725561SMark Brown void regulator_has_full_constraints(void) 3444ca725561SMark Brown { 3445ca725561SMark Brown has_full_constraints = 1; 3446ca725561SMark Brown } 3447ca725561SMark Brown EXPORT_SYMBOL_GPL(regulator_has_full_constraints); 3448ca725561SMark Brown 3449ca725561SMark Brown /** 3450688fe99aSMark Brown * regulator_use_dummy_regulator - Provide a dummy regulator when none is found 3451688fe99aSMark Brown * 3452688fe99aSMark Brown * Calling this function will cause the regulator API to provide a 3453688fe99aSMark Brown * dummy regulator to consumers if no physical regulator is found, 3454688fe99aSMark Brown * allowing most consumers to proceed as though a regulator were 3455688fe99aSMark Brown * configured. This allows systems such as those with software 3456688fe99aSMark Brown * controllable regulators for the CPU core only to be brought up more 3457688fe99aSMark Brown * readily. 3458688fe99aSMark Brown */ 3459688fe99aSMark Brown void regulator_use_dummy_regulator(void) 3460688fe99aSMark Brown { 3461688fe99aSMark Brown board_wants_dummy_regulator = true; 3462688fe99aSMark Brown } 3463688fe99aSMark Brown EXPORT_SYMBOL_GPL(regulator_use_dummy_regulator); 3464688fe99aSMark Brown 3465688fe99aSMark Brown /** 3466414c70cbSLiam Girdwood * rdev_get_drvdata - get rdev regulator driver data 346769279fb9SMark Brown * @rdev: regulator 3468414c70cbSLiam Girdwood * 3469414c70cbSLiam Girdwood * Get rdev regulator driver private data. This call can be used in the 3470414c70cbSLiam Girdwood * regulator driver context. 3471414c70cbSLiam Girdwood */ 3472414c70cbSLiam Girdwood void *rdev_get_drvdata(struct regulator_dev *rdev) 3473414c70cbSLiam Girdwood { 3474414c70cbSLiam Girdwood return rdev->reg_data; 3475414c70cbSLiam Girdwood } 3476414c70cbSLiam Girdwood EXPORT_SYMBOL_GPL(rdev_get_drvdata); 3477414c70cbSLiam Girdwood 3478414c70cbSLiam Girdwood /** 3479414c70cbSLiam Girdwood * regulator_get_drvdata - get regulator driver data 3480414c70cbSLiam Girdwood * @regulator: regulator 3481414c70cbSLiam Girdwood * 3482414c70cbSLiam Girdwood * Get regulator driver private data. This call can be used in the consumer 3483414c70cbSLiam Girdwood * driver context when non API regulator specific functions need to be called. 3484414c70cbSLiam Girdwood */ 3485414c70cbSLiam Girdwood void *regulator_get_drvdata(struct regulator *regulator) 3486414c70cbSLiam Girdwood { 3487414c70cbSLiam Girdwood return regulator->rdev->reg_data; 3488414c70cbSLiam Girdwood } 3489414c70cbSLiam Girdwood EXPORT_SYMBOL_GPL(regulator_get_drvdata); 3490414c70cbSLiam Girdwood 3491414c70cbSLiam Girdwood /** 3492414c70cbSLiam Girdwood * regulator_set_drvdata - set regulator driver data 3493414c70cbSLiam Girdwood * @regulator: regulator 3494414c70cbSLiam Girdwood * @data: data 3495414c70cbSLiam Girdwood */ 3496414c70cbSLiam Girdwood void regulator_set_drvdata(struct regulator *regulator, void *data) 3497414c70cbSLiam Girdwood { 3498414c70cbSLiam Girdwood regulator->rdev->reg_data = data; 3499414c70cbSLiam Girdwood } 3500414c70cbSLiam Girdwood EXPORT_SYMBOL_GPL(regulator_set_drvdata); 3501414c70cbSLiam Girdwood 3502414c70cbSLiam Girdwood /** 3503414c70cbSLiam Girdwood * regulator_get_id - get regulator ID 350469279fb9SMark Brown * @rdev: regulator 3505414c70cbSLiam Girdwood */ 3506414c70cbSLiam Girdwood int rdev_get_id(struct regulator_dev *rdev) 3507414c70cbSLiam Girdwood { 3508414c70cbSLiam Girdwood return rdev->desc->id; 3509414c70cbSLiam Girdwood } 3510414c70cbSLiam Girdwood EXPORT_SYMBOL_GPL(rdev_get_id); 3511414c70cbSLiam Girdwood 3512a5766f11SLiam Girdwood struct device *rdev_get_dev(struct regulator_dev *rdev) 3513a5766f11SLiam Girdwood { 3514a5766f11SLiam Girdwood return &rdev->dev; 3515a5766f11SLiam Girdwood } 3516a5766f11SLiam Girdwood EXPORT_SYMBOL_GPL(rdev_get_dev); 3517a5766f11SLiam Girdwood 3518a5766f11SLiam Girdwood void *regulator_get_init_drvdata(struct regulator_init_data *reg_init_data) 3519a5766f11SLiam Girdwood { 3520a5766f11SLiam Girdwood return reg_init_data->driver_data; 3521a5766f11SLiam Girdwood } 3522a5766f11SLiam Girdwood EXPORT_SYMBOL_GPL(regulator_get_init_drvdata); 3523a5766f11SLiam Girdwood 3524ba55a974SMark Brown #ifdef CONFIG_DEBUG_FS 3525ba55a974SMark Brown static ssize_t supply_map_read_file(struct file *file, char __user *user_buf, 3526ba55a974SMark Brown size_t count, loff_t *ppos) 3527ba55a974SMark Brown { 3528ba55a974SMark Brown char *buf = kmalloc(PAGE_SIZE, GFP_KERNEL); 3529ba55a974SMark Brown ssize_t len, ret = 0; 3530ba55a974SMark Brown struct regulator_map *map; 3531ba55a974SMark Brown 3532ba55a974SMark Brown if (!buf) 3533ba55a974SMark Brown return -ENOMEM; 3534ba55a974SMark Brown 3535ba55a974SMark Brown list_for_each_entry(map, ®ulator_map_list, list) { 3536ba55a974SMark Brown len = snprintf(buf + ret, PAGE_SIZE - ret, 3537ba55a974SMark Brown "%s -> %s.%s\n", 3538ba55a974SMark Brown rdev_get_name(map->regulator), map->dev_name, 3539ba55a974SMark Brown map->supply); 3540ba55a974SMark Brown if (len >= 0) 3541ba55a974SMark Brown ret += len; 3542ba55a974SMark Brown if (ret > PAGE_SIZE) { 3543ba55a974SMark Brown ret = PAGE_SIZE; 3544ba55a974SMark Brown break; 3545ba55a974SMark Brown } 3546ba55a974SMark Brown } 3547ba55a974SMark Brown 3548ba55a974SMark Brown ret = simple_read_from_buffer(user_buf, count, ppos, buf, ret); 3549ba55a974SMark Brown 3550ba55a974SMark Brown kfree(buf); 3551ba55a974SMark Brown 3552ba55a974SMark Brown return ret; 3553ba55a974SMark Brown } 355424751434SStephen Boyd #endif 3555ba55a974SMark Brown 3556ba55a974SMark Brown static const struct file_operations supply_map_fops = { 355724751434SStephen Boyd #ifdef CONFIG_DEBUG_FS 3558ba55a974SMark Brown .read = supply_map_read_file, 3559ba55a974SMark Brown .llseek = default_llseek, 3560ba55a974SMark Brown #endif 356124751434SStephen Boyd }; 3562ba55a974SMark Brown 3563414c70cbSLiam Girdwood static int __init regulator_init(void) 3564414c70cbSLiam Girdwood { 356534abbd68SMark Brown int ret; 356634abbd68SMark Brown 356734abbd68SMark Brown ret = class_register(®ulator_class); 356834abbd68SMark Brown 35691130e5b3SMark Brown debugfs_root = debugfs_create_dir("regulator", NULL); 357024751434SStephen Boyd if (!debugfs_root) 35711130e5b3SMark Brown pr_warn("regulator: Failed to create debugfs directory\n"); 3572ba55a974SMark Brown 3573f4d562c6SMark Brown debugfs_create_file("supply_map", 0444, debugfs_root, NULL, 3574f4d562c6SMark Brown &supply_map_fops); 35751130e5b3SMark Brown 357634abbd68SMark Brown regulator_dummy_init(); 357734abbd68SMark Brown 357834abbd68SMark Brown return ret; 3579414c70cbSLiam Girdwood } 3580414c70cbSLiam Girdwood 3581414c70cbSLiam Girdwood /* init early to allow our consumers to complete system booting */ 3582414c70cbSLiam Girdwood core_initcall(regulator_init); 3583ca725561SMark Brown 3584ca725561SMark Brown static int __init regulator_init_complete(void) 3585ca725561SMark Brown { 3586ca725561SMark Brown struct regulator_dev *rdev; 3587ca725561SMark Brown struct regulator_ops *ops; 3588ca725561SMark Brown struct regulation_constraints *c; 3589ca725561SMark Brown int enabled, ret; 3590ca725561SMark Brown 359186f5fcfcSMark Brown /* 359286f5fcfcSMark Brown * Since DT doesn't provide an idiomatic mechanism for 359386f5fcfcSMark Brown * enabling full constraints and since it's much more natural 359486f5fcfcSMark Brown * with DT to provide them just assume that a DT enabled 359586f5fcfcSMark Brown * system has full constraints. 359686f5fcfcSMark Brown */ 359786f5fcfcSMark Brown if (of_have_populated_dt()) 359886f5fcfcSMark Brown has_full_constraints = true; 359986f5fcfcSMark Brown 3600ca725561SMark Brown mutex_lock(®ulator_list_mutex); 3601ca725561SMark Brown 3602ca725561SMark Brown /* If we have a full configuration then disable any regulators 3603ca725561SMark Brown * which are not in use or always_on. This will become the 3604ca725561SMark Brown * default behaviour in the future. 3605ca725561SMark Brown */ 3606ca725561SMark Brown list_for_each_entry(rdev, ®ulator_list, list) { 3607ca725561SMark Brown ops = rdev->desc->ops; 3608ca725561SMark Brown c = rdev->constraints; 3609ca725561SMark Brown 3610f25e0b4fSMark Brown if (!ops->disable || (c && c->always_on)) 3611ca725561SMark Brown continue; 3612ca725561SMark Brown 3613ca725561SMark Brown mutex_lock(&rdev->mutex); 3614ca725561SMark Brown 3615ca725561SMark Brown if (rdev->use_count) 3616ca725561SMark Brown goto unlock; 3617ca725561SMark Brown 3618ca725561SMark Brown /* If we can't read the status assume it's on. */ 3619ca725561SMark Brown if (ops->is_enabled) 3620ca725561SMark Brown enabled = ops->is_enabled(rdev); 3621ca725561SMark Brown else 3622ca725561SMark Brown enabled = 1; 3623ca725561SMark Brown 3624ca725561SMark Brown if (!enabled) 3625ca725561SMark Brown goto unlock; 3626ca725561SMark Brown 3627ca725561SMark Brown if (has_full_constraints) { 3628ca725561SMark Brown /* We log since this may kill the system if it 3629ca725561SMark Brown * goes wrong. */ 36305da84fd9SJoe Perches rdev_info(rdev, "disabling\n"); 3631ca725561SMark Brown ret = ops->disable(rdev); 3632ca725561SMark Brown if (ret != 0) { 36335da84fd9SJoe Perches rdev_err(rdev, "couldn't disable: %d\n", ret); 3634ca725561SMark Brown } 3635ca725561SMark Brown } else { 3636ca725561SMark Brown /* The intention is that in future we will 3637ca725561SMark Brown * assume that full constraints are provided 3638ca725561SMark Brown * so warn even if we aren't going to do 3639ca725561SMark Brown * anything here. 3640ca725561SMark Brown */ 36415da84fd9SJoe Perches rdev_warn(rdev, "incomplete constraints, leaving on\n"); 3642ca725561SMark Brown } 3643ca725561SMark Brown 3644ca725561SMark Brown unlock: 3645ca725561SMark Brown mutex_unlock(&rdev->mutex); 3646ca725561SMark Brown } 3647ca725561SMark Brown 3648ca725561SMark Brown mutex_unlock(®ulator_list_mutex); 3649ca725561SMark Brown 3650ca725561SMark Brown return 0; 3651ca725561SMark Brown } 3652ca725561SMark Brown late_initcall(regulator_init_complete); 3653