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> 2669511a45SRajendra Nayak #include <linux/of.h> 2765b19ce6SMark Brown #include <linux/regmap.h> 2869511a45SRajendra Nayak #include <linux/regulator/of_regulator.h> 29414c70cbSLiam Girdwood #include <linux/regulator/consumer.h> 30414c70cbSLiam Girdwood #include <linux/regulator/driver.h> 31414c70cbSLiam Girdwood #include <linux/regulator/machine.h> 3265602c32SPaul Gortmaker #include <linux/module.h> 33414c70cbSLiam Girdwood 3402fa3ec0SMark Brown #define CREATE_TRACE_POINTS 3502fa3ec0SMark Brown #include <trace/events/regulator.h> 3602fa3ec0SMark Brown 3734abbd68SMark Brown #include "dummy.h" 3834abbd68SMark Brown 397d51a0dbSMark Brown #define rdev_crit(rdev, fmt, ...) \ 407d51a0dbSMark Brown pr_crit("%s: " fmt, rdev_get_name(rdev), ##__VA_ARGS__) 415da84fd9SJoe Perches #define rdev_err(rdev, fmt, ...) \ 425da84fd9SJoe Perches pr_err("%s: " fmt, rdev_get_name(rdev), ##__VA_ARGS__) 435da84fd9SJoe Perches #define rdev_warn(rdev, fmt, ...) \ 445da84fd9SJoe Perches pr_warn("%s: " fmt, rdev_get_name(rdev), ##__VA_ARGS__) 455da84fd9SJoe Perches #define rdev_info(rdev, fmt, ...) \ 465da84fd9SJoe Perches pr_info("%s: " fmt, rdev_get_name(rdev), ##__VA_ARGS__) 475da84fd9SJoe Perches #define rdev_dbg(rdev, fmt, ...) \ 485da84fd9SJoe Perches pr_debug("%s: " fmt, rdev_get_name(rdev), ##__VA_ARGS__) 495da84fd9SJoe Perches 50414c70cbSLiam Girdwood static DEFINE_MUTEX(regulator_list_mutex); 51414c70cbSLiam Girdwood static LIST_HEAD(regulator_list); 52414c70cbSLiam Girdwood static LIST_HEAD(regulator_map_list); 5321cf891aSMark Brown static bool has_full_constraints; 54688fe99aSMark Brown static bool board_wants_dummy_regulator; 55414c70cbSLiam Girdwood 561130e5b3SMark Brown static struct dentry *debugfs_root; 571130e5b3SMark Brown 588dc5390dSMark Brown /* 59414c70cbSLiam Girdwood * struct regulator_map 60414c70cbSLiam Girdwood * 61414c70cbSLiam Girdwood * Used to provide symbolic supply names to devices. 62414c70cbSLiam Girdwood */ 63414c70cbSLiam Girdwood struct regulator_map { 64414c70cbSLiam Girdwood struct list_head list; 6540f9244fSMark Brown const char *dev_name; /* The dev_name() for the consumer */ 66414c70cbSLiam Girdwood const char *supply; 67a5766f11SLiam Girdwood struct regulator_dev *regulator; 68414c70cbSLiam Girdwood }; 69414c70cbSLiam Girdwood 70414c70cbSLiam Girdwood /* 71414c70cbSLiam Girdwood * struct regulator 72414c70cbSLiam Girdwood * 73414c70cbSLiam Girdwood * One for each consumer device. 74414c70cbSLiam Girdwood */ 75414c70cbSLiam Girdwood struct regulator { 76414c70cbSLiam Girdwood struct device *dev; 77414c70cbSLiam Girdwood struct list_head list; 786492bc1bSMark Brown unsigned int always_on:1; 79414c70cbSLiam Girdwood int uA_load; 80414c70cbSLiam Girdwood int min_uV; 81414c70cbSLiam Girdwood int max_uV; 82414c70cbSLiam Girdwood char *supply_name; 83414c70cbSLiam Girdwood struct device_attribute dev_attr; 84414c70cbSLiam Girdwood struct regulator_dev *rdev; 855de70519SMark Brown struct dentry *debugfs; 86414c70cbSLiam Girdwood }; 87414c70cbSLiam Girdwood 88414c70cbSLiam Girdwood static int _regulator_is_enabled(struct regulator_dev *rdev); 893801b86aSMark Brown static int _regulator_disable(struct regulator_dev *rdev); 90414c70cbSLiam Girdwood static int _regulator_get_voltage(struct regulator_dev *rdev); 91414c70cbSLiam Girdwood static int _regulator_get_current_limit(struct regulator_dev *rdev); 92414c70cbSLiam Girdwood static unsigned int _regulator_get_mode(struct regulator_dev *rdev); 93414c70cbSLiam Girdwood static void _notifier_call_chain(struct regulator_dev *rdev, 94414c70cbSLiam Girdwood unsigned long event, void *data); 9575790251SMark Brown static int _regulator_do_set_voltage(struct regulator_dev *rdev, 9675790251SMark Brown int min_uV, int max_uV); 973801b86aSMark Brown static struct regulator *create_regulator(struct regulator_dev *rdev, 983801b86aSMark Brown struct device *dev, 993801b86aSMark Brown const char *supply_name); 100414c70cbSLiam Girdwood 1011083c393SMark Brown static const char *rdev_get_name(struct regulator_dev *rdev) 1021083c393SMark Brown { 1031083c393SMark Brown if (rdev->constraints && rdev->constraints->name) 1041083c393SMark Brown return rdev->constraints->name; 1051083c393SMark Brown else if (rdev->desc->name) 1061083c393SMark Brown return rdev->desc->name; 1071083c393SMark Brown else 1081083c393SMark Brown return ""; 1091083c393SMark Brown } 1101083c393SMark Brown 111414c70cbSLiam Girdwood /* gets the regulator for a given consumer device */ 112414c70cbSLiam Girdwood static struct regulator *get_device_regulator(struct device *dev) 113414c70cbSLiam Girdwood { 114414c70cbSLiam Girdwood struct regulator *regulator = NULL; 115414c70cbSLiam Girdwood struct regulator_dev *rdev; 116414c70cbSLiam Girdwood 117414c70cbSLiam Girdwood mutex_lock(®ulator_list_mutex); 118414c70cbSLiam Girdwood list_for_each_entry(rdev, ®ulator_list, list) { 119414c70cbSLiam Girdwood mutex_lock(&rdev->mutex); 120414c70cbSLiam Girdwood list_for_each_entry(regulator, &rdev->consumer_list, list) { 121414c70cbSLiam Girdwood if (regulator->dev == dev) { 122414c70cbSLiam Girdwood mutex_unlock(&rdev->mutex); 123414c70cbSLiam Girdwood mutex_unlock(®ulator_list_mutex); 124414c70cbSLiam Girdwood return regulator; 125414c70cbSLiam Girdwood } 126414c70cbSLiam Girdwood } 127414c70cbSLiam Girdwood mutex_unlock(&rdev->mutex); 128414c70cbSLiam Girdwood } 129414c70cbSLiam Girdwood mutex_unlock(®ulator_list_mutex); 130414c70cbSLiam Girdwood return NULL; 131414c70cbSLiam Girdwood } 132414c70cbSLiam Girdwood 13369511a45SRajendra Nayak /** 13469511a45SRajendra Nayak * of_get_regulator - get a regulator device node based on supply name 13569511a45SRajendra Nayak * @dev: Device pointer for the consumer (of regulator) device 13669511a45SRajendra Nayak * @supply: regulator supply name 13769511a45SRajendra Nayak * 13869511a45SRajendra Nayak * Extract the regulator device node corresponding to the supply name. 13969511a45SRajendra Nayak * retruns the device node corresponding to the regulator if found, else 14069511a45SRajendra Nayak * returns NULL. 14169511a45SRajendra Nayak */ 14269511a45SRajendra Nayak static struct device_node *of_get_regulator(struct device *dev, const char *supply) 14369511a45SRajendra Nayak { 14469511a45SRajendra Nayak struct device_node *regnode = NULL; 14569511a45SRajendra Nayak char prop_name[32]; /* 32 is max size of property name */ 14669511a45SRajendra Nayak 14769511a45SRajendra Nayak dev_dbg(dev, "Looking up %s-supply from device tree\n", supply); 14869511a45SRajendra Nayak 14969511a45SRajendra Nayak snprintf(prop_name, 32, "%s-supply", supply); 15069511a45SRajendra Nayak regnode = of_parse_phandle(dev->of_node, prop_name, 0); 15169511a45SRajendra Nayak 15269511a45SRajendra Nayak if (!regnode) { 15316fbcc3bSRajendra Nayak dev_dbg(dev, "Looking up %s property in node %s failed", 15469511a45SRajendra Nayak prop_name, dev->of_node->full_name); 15569511a45SRajendra Nayak return NULL; 15669511a45SRajendra Nayak } 15769511a45SRajendra Nayak return regnode; 15869511a45SRajendra Nayak } 15969511a45SRajendra Nayak 1606492bc1bSMark Brown static int _regulator_can_change_status(struct regulator_dev *rdev) 1616492bc1bSMark Brown { 1626492bc1bSMark Brown if (!rdev->constraints) 1636492bc1bSMark Brown return 0; 1646492bc1bSMark Brown 1656492bc1bSMark Brown if (rdev->constraints->valid_ops_mask & REGULATOR_CHANGE_STATUS) 1666492bc1bSMark Brown return 1; 1676492bc1bSMark Brown else 1686492bc1bSMark Brown return 0; 1696492bc1bSMark Brown } 1706492bc1bSMark Brown 171414c70cbSLiam Girdwood /* Platform voltage constraint check */ 172414c70cbSLiam Girdwood static int regulator_check_voltage(struct regulator_dev *rdev, 173414c70cbSLiam Girdwood int *min_uV, int *max_uV) 174414c70cbSLiam Girdwood { 175414c70cbSLiam Girdwood BUG_ON(*min_uV > *max_uV); 176414c70cbSLiam Girdwood 177414c70cbSLiam Girdwood if (!rdev->constraints) { 1785da84fd9SJoe Perches rdev_err(rdev, "no constraints\n"); 179414c70cbSLiam Girdwood return -ENODEV; 180414c70cbSLiam Girdwood } 181414c70cbSLiam Girdwood if (!(rdev->constraints->valid_ops_mask & REGULATOR_CHANGE_VOLTAGE)) { 1825da84fd9SJoe Perches rdev_err(rdev, "operation not allowed\n"); 183414c70cbSLiam Girdwood return -EPERM; 184414c70cbSLiam Girdwood } 185414c70cbSLiam Girdwood 186414c70cbSLiam Girdwood if (*max_uV > rdev->constraints->max_uV) 187414c70cbSLiam Girdwood *max_uV = rdev->constraints->max_uV; 188414c70cbSLiam Girdwood if (*min_uV < rdev->constraints->min_uV) 189414c70cbSLiam Girdwood *min_uV = rdev->constraints->min_uV; 190414c70cbSLiam Girdwood 19189f425edSMark Brown if (*min_uV > *max_uV) { 19289f425edSMark Brown rdev_err(rdev, "unsupportable voltage range: %d-%duV\n", 19354abd335SMark Brown *min_uV, *max_uV); 194414c70cbSLiam Girdwood return -EINVAL; 19589f425edSMark Brown } 196414c70cbSLiam Girdwood 197414c70cbSLiam Girdwood return 0; 198414c70cbSLiam Girdwood } 199414c70cbSLiam Girdwood 20005fda3b1SThomas Petazzoni /* Make sure we select a voltage that suits the needs of all 20105fda3b1SThomas Petazzoni * regulator consumers 20205fda3b1SThomas Petazzoni */ 20305fda3b1SThomas Petazzoni static int regulator_check_consumers(struct regulator_dev *rdev, 20405fda3b1SThomas Petazzoni int *min_uV, int *max_uV) 20505fda3b1SThomas Petazzoni { 20605fda3b1SThomas Petazzoni struct regulator *regulator; 20705fda3b1SThomas Petazzoni 20805fda3b1SThomas Petazzoni list_for_each_entry(regulator, &rdev->consumer_list, list) { 2094aa922c0SMark Brown /* 2104aa922c0SMark Brown * Assume consumers that didn't say anything are OK 2114aa922c0SMark Brown * with anything in the constraint range. 2124aa922c0SMark Brown */ 2134aa922c0SMark Brown if (!regulator->min_uV && !regulator->max_uV) 2144aa922c0SMark Brown continue; 2154aa922c0SMark Brown 21605fda3b1SThomas Petazzoni if (*max_uV > regulator->max_uV) 21705fda3b1SThomas Petazzoni *max_uV = regulator->max_uV; 21805fda3b1SThomas Petazzoni if (*min_uV < regulator->min_uV) 21905fda3b1SThomas Petazzoni *min_uV = regulator->min_uV; 22005fda3b1SThomas Petazzoni } 22105fda3b1SThomas Petazzoni 22205fda3b1SThomas Petazzoni if (*min_uV > *max_uV) 22305fda3b1SThomas Petazzoni return -EINVAL; 22405fda3b1SThomas Petazzoni 22505fda3b1SThomas Petazzoni return 0; 22605fda3b1SThomas Petazzoni } 22705fda3b1SThomas Petazzoni 228414c70cbSLiam Girdwood /* current constraint check */ 229414c70cbSLiam Girdwood static int regulator_check_current_limit(struct regulator_dev *rdev, 230414c70cbSLiam Girdwood int *min_uA, int *max_uA) 231414c70cbSLiam Girdwood { 232414c70cbSLiam Girdwood BUG_ON(*min_uA > *max_uA); 233414c70cbSLiam Girdwood 234414c70cbSLiam Girdwood if (!rdev->constraints) { 2355da84fd9SJoe Perches rdev_err(rdev, "no constraints\n"); 236414c70cbSLiam Girdwood return -ENODEV; 237414c70cbSLiam Girdwood } 238414c70cbSLiam Girdwood if (!(rdev->constraints->valid_ops_mask & REGULATOR_CHANGE_CURRENT)) { 2395da84fd9SJoe Perches rdev_err(rdev, "operation not allowed\n"); 240414c70cbSLiam Girdwood return -EPERM; 241414c70cbSLiam Girdwood } 242414c70cbSLiam Girdwood 243414c70cbSLiam Girdwood if (*max_uA > rdev->constraints->max_uA) 244414c70cbSLiam Girdwood *max_uA = rdev->constraints->max_uA; 245414c70cbSLiam Girdwood if (*min_uA < rdev->constraints->min_uA) 246414c70cbSLiam Girdwood *min_uA = rdev->constraints->min_uA; 247414c70cbSLiam Girdwood 24889f425edSMark Brown if (*min_uA > *max_uA) { 24989f425edSMark Brown rdev_err(rdev, "unsupportable current range: %d-%duA\n", 25054abd335SMark Brown *min_uA, *max_uA); 251414c70cbSLiam Girdwood return -EINVAL; 25289f425edSMark Brown } 253414c70cbSLiam Girdwood 254414c70cbSLiam Girdwood return 0; 255414c70cbSLiam Girdwood } 256414c70cbSLiam Girdwood 257414c70cbSLiam Girdwood /* operating mode constraint check */ 2582c608234SMark Brown static int regulator_mode_constrain(struct regulator_dev *rdev, int *mode) 259414c70cbSLiam Girdwood { 2602c608234SMark Brown switch (*mode) { 261e573520bSDavid Brownell case REGULATOR_MODE_FAST: 262e573520bSDavid Brownell case REGULATOR_MODE_NORMAL: 263e573520bSDavid Brownell case REGULATOR_MODE_IDLE: 264e573520bSDavid Brownell case REGULATOR_MODE_STANDBY: 265e573520bSDavid Brownell break; 266e573520bSDavid Brownell default: 26789f425edSMark Brown rdev_err(rdev, "invalid mode %x specified\n", *mode); 268e573520bSDavid Brownell return -EINVAL; 269e573520bSDavid Brownell } 270e573520bSDavid Brownell 271414c70cbSLiam Girdwood if (!rdev->constraints) { 2725da84fd9SJoe Perches rdev_err(rdev, "no constraints\n"); 273414c70cbSLiam Girdwood return -ENODEV; 274414c70cbSLiam Girdwood } 275414c70cbSLiam Girdwood if (!(rdev->constraints->valid_ops_mask & REGULATOR_CHANGE_MODE)) { 2765da84fd9SJoe Perches rdev_err(rdev, "operation not allowed\n"); 277414c70cbSLiam Girdwood return -EPERM; 278414c70cbSLiam Girdwood } 2792c608234SMark Brown 2802c608234SMark Brown /* The modes are bitmasks, the most power hungry modes having 2812c608234SMark Brown * the lowest values. If the requested mode isn't supported 2822c608234SMark Brown * try higher modes. */ 2832c608234SMark Brown while (*mode) { 2842c608234SMark Brown if (rdev->constraints->valid_modes_mask & *mode) 285414c70cbSLiam Girdwood return 0; 2862c608234SMark Brown *mode /= 2; 2872c608234SMark Brown } 2882c608234SMark Brown 2892c608234SMark Brown return -EINVAL; 290414c70cbSLiam Girdwood } 291414c70cbSLiam Girdwood 292414c70cbSLiam Girdwood /* dynamic regulator mode switching constraint check */ 293414c70cbSLiam Girdwood static int regulator_check_drms(struct regulator_dev *rdev) 294414c70cbSLiam Girdwood { 295414c70cbSLiam Girdwood if (!rdev->constraints) { 2965da84fd9SJoe Perches rdev_err(rdev, "no constraints\n"); 297414c70cbSLiam Girdwood return -ENODEV; 298414c70cbSLiam Girdwood } 299414c70cbSLiam Girdwood if (!(rdev->constraints->valid_ops_mask & REGULATOR_CHANGE_DRMS)) { 3005da84fd9SJoe Perches rdev_err(rdev, "operation not allowed\n"); 301414c70cbSLiam Girdwood return -EPERM; 302414c70cbSLiam Girdwood } 303414c70cbSLiam Girdwood return 0; 304414c70cbSLiam Girdwood } 305414c70cbSLiam Girdwood 306414c70cbSLiam Girdwood static ssize_t device_requested_uA_show(struct device *dev, 307414c70cbSLiam Girdwood struct device_attribute *attr, char *buf) 308414c70cbSLiam Girdwood { 309414c70cbSLiam Girdwood struct regulator *regulator; 310414c70cbSLiam Girdwood 311414c70cbSLiam Girdwood regulator = get_device_regulator(dev); 312414c70cbSLiam Girdwood if (regulator == NULL) 313414c70cbSLiam Girdwood return 0; 314414c70cbSLiam Girdwood 315414c70cbSLiam Girdwood return sprintf(buf, "%d\n", regulator->uA_load); 316414c70cbSLiam Girdwood } 317414c70cbSLiam Girdwood 318414c70cbSLiam Girdwood static ssize_t regulator_uV_show(struct device *dev, 319414c70cbSLiam Girdwood struct device_attribute *attr, char *buf) 320414c70cbSLiam Girdwood { 321a5766f11SLiam Girdwood struct regulator_dev *rdev = dev_get_drvdata(dev); 322414c70cbSLiam Girdwood ssize_t ret; 323414c70cbSLiam Girdwood 324414c70cbSLiam Girdwood mutex_lock(&rdev->mutex); 325414c70cbSLiam Girdwood ret = sprintf(buf, "%d\n", _regulator_get_voltage(rdev)); 326414c70cbSLiam Girdwood mutex_unlock(&rdev->mutex); 327414c70cbSLiam Girdwood 328414c70cbSLiam Girdwood return ret; 329414c70cbSLiam Girdwood } 3307ad68e2fSDavid Brownell static DEVICE_ATTR(microvolts, 0444, regulator_uV_show, NULL); 331414c70cbSLiam Girdwood 332414c70cbSLiam Girdwood static ssize_t regulator_uA_show(struct device *dev, 333414c70cbSLiam Girdwood struct device_attribute *attr, char *buf) 334414c70cbSLiam Girdwood { 335a5766f11SLiam Girdwood struct regulator_dev *rdev = dev_get_drvdata(dev); 336414c70cbSLiam Girdwood 337414c70cbSLiam Girdwood return sprintf(buf, "%d\n", _regulator_get_current_limit(rdev)); 338414c70cbSLiam Girdwood } 3397ad68e2fSDavid Brownell static DEVICE_ATTR(microamps, 0444, regulator_uA_show, NULL); 340414c70cbSLiam Girdwood 341bc558a60SMark Brown static ssize_t regulator_name_show(struct device *dev, 342bc558a60SMark Brown struct device_attribute *attr, char *buf) 343bc558a60SMark Brown { 344bc558a60SMark Brown struct regulator_dev *rdev = dev_get_drvdata(dev); 345bc558a60SMark Brown 3461083c393SMark Brown return sprintf(buf, "%s\n", rdev_get_name(rdev)); 347bc558a60SMark Brown } 348bc558a60SMark Brown 3494fca9545SDavid Brownell static ssize_t regulator_print_opmode(char *buf, int mode) 350414c70cbSLiam Girdwood { 351414c70cbSLiam Girdwood switch (mode) { 352414c70cbSLiam Girdwood case REGULATOR_MODE_FAST: 353414c70cbSLiam Girdwood return sprintf(buf, "fast\n"); 354414c70cbSLiam Girdwood case REGULATOR_MODE_NORMAL: 355414c70cbSLiam Girdwood return sprintf(buf, "normal\n"); 356414c70cbSLiam Girdwood case REGULATOR_MODE_IDLE: 357414c70cbSLiam Girdwood return sprintf(buf, "idle\n"); 358414c70cbSLiam Girdwood case REGULATOR_MODE_STANDBY: 359414c70cbSLiam Girdwood return sprintf(buf, "standby\n"); 360414c70cbSLiam Girdwood } 361414c70cbSLiam Girdwood return sprintf(buf, "unknown\n"); 362414c70cbSLiam Girdwood } 363414c70cbSLiam Girdwood 3644fca9545SDavid Brownell static ssize_t regulator_opmode_show(struct device *dev, 365414c70cbSLiam Girdwood struct device_attribute *attr, char *buf) 366414c70cbSLiam Girdwood { 367a5766f11SLiam Girdwood struct regulator_dev *rdev = dev_get_drvdata(dev); 368414c70cbSLiam Girdwood 3694fca9545SDavid Brownell return regulator_print_opmode(buf, _regulator_get_mode(rdev)); 3704fca9545SDavid Brownell } 3717ad68e2fSDavid Brownell static DEVICE_ATTR(opmode, 0444, regulator_opmode_show, NULL); 3724fca9545SDavid Brownell 3734fca9545SDavid Brownell static ssize_t regulator_print_state(char *buf, int state) 3744fca9545SDavid Brownell { 375414c70cbSLiam Girdwood if (state > 0) 376414c70cbSLiam Girdwood return sprintf(buf, "enabled\n"); 377414c70cbSLiam Girdwood else if (state == 0) 378414c70cbSLiam Girdwood return sprintf(buf, "disabled\n"); 379414c70cbSLiam Girdwood else 380414c70cbSLiam Girdwood return sprintf(buf, "unknown\n"); 381414c70cbSLiam Girdwood } 382414c70cbSLiam Girdwood 3834fca9545SDavid Brownell static ssize_t regulator_state_show(struct device *dev, 3844fca9545SDavid Brownell struct device_attribute *attr, char *buf) 3854fca9545SDavid Brownell { 3864fca9545SDavid Brownell struct regulator_dev *rdev = dev_get_drvdata(dev); 3879332546fSMark Brown ssize_t ret; 3884fca9545SDavid Brownell 3899332546fSMark Brown mutex_lock(&rdev->mutex); 3909332546fSMark Brown ret = regulator_print_state(buf, _regulator_is_enabled(rdev)); 3919332546fSMark Brown mutex_unlock(&rdev->mutex); 3929332546fSMark Brown 3939332546fSMark Brown return ret; 3944fca9545SDavid Brownell } 3957ad68e2fSDavid Brownell static DEVICE_ATTR(state, 0444, regulator_state_show, NULL); 3964fca9545SDavid Brownell 397853116a1SDavid Brownell static ssize_t regulator_status_show(struct device *dev, 398853116a1SDavid Brownell struct device_attribute *attr, char *buf) 399853116a1SDavid Brownell { 400853116a1SDavid Brownell struct regulator_dev *rdev = dev_get_drvdata(dev); 401853116a1SDavid Brownell int status; 402853116a1SDavid Brownell char *label; 403853116a1SDavid Brownell 404853116a1SDavid Brownell status = rdev->desc->ops->get_status(rdev); 405853116a1SDavid Brownell if (status < 0) 406853116a1SDavid Brownell return status; 407853116a1SDavid Brownell 408853116a1SDavid Brownell switch (status) { 409853116a1SDavid Brownell case REGULATOR_STATUS_OFF: 410853116a1SDavid Brownell label = "off"; 411853116a1SDavid Brownell break; 412853116a1SDavid Brownell case REGULATOR_STATUS_ON: 413853116a1SDavid Brownell label = "on"; 414853116a1SDavid Brownell break; 415853116a1SDavid Brownell case REGULATOR_STATUS_ERROR: 416853116a1SDavid Brownell label = "error"; 417853116a1SDavid Brownell break; 418853116a1SDavid Brownell case REGULATOR_STATUS_FAST: 419853116a1SDavid Brownell label = "fast"; 420853116a1SDavid Brownell break; 421853116a1SDavid Brownell case REGULATOR_STATUS_NORMAL: 422853116a1SDavid Brownell label = "normal"; 423853116a1SDavid Brownell break; 424853116a1SDavid Brownell case REGULATOR_STATUS_IDLE: 425853116a1SDavid Brownell label = "idle"; 426853116a1SDavid Brownell break; 427853116a1SDavid Brownell case REGULATOR_STATUS_STANDBY: 428853116a1SDavid Brownell label = "standby"; 429853116a1SDavid Brownell break; 430853116a1SDavid Brownell default: 431853116a1SDavid Brownell return -ERANGE; 432853116a1SDavid Brownell } 433853116a1SDavid Brownell 434853116a1SDavid Brownell return sprintf(buf, "%s\n", label); 435853116a1SDavid Brownell } 436853116a1SDavid Brownell static DEVICE_ATTR(status, 0444, regulator_status_show, NULL); 437853116a1SDavid Brownell 438414c70cbSLiam Girdwood static ssize_t regulator_min_uA_show(struct device *dev, 439414c70cbSLiam Girdwood struct device_attribute *attr, char *buf) 440414c70cbSLiam Girdwood { 441a5766f11SLiam Girdwood struct regulator_dev *rdev = dev_get_drvdata(dev); 442414c70cbSLiam Girdwood 443414c70cbSLiam Girdwood if (!rdev->constraints) 444414c70cbSLiam Girdwood return sprintf(buf, "constraint not defined\n"); 445414c70cbSLiam Girdwood 446414c70cbSLiam Girdwood return sprintf(buf, "%d\n", rdev->constraints->min_uA); 447414c70cbSLiam Girdwood } 4487ad68e2fSDavid Brownell static DEVICE_ATTR(min_microamps, 0444, regulator_min_uA_show, NULL); 449414c70cbSLiam Girdwood 450414c70cbSLiam Girdwood static ssize_t regulator_max_uA_show(struct device *dev, 451414c70cbSLiam Girdwood struct device_attribute *attr, char *buf) 452414c70cbSLiam Girdwood { 453a5766f11SLiam Girdwood struct regulator_dev *rdev = dev_get_drvdata(dev); 454414c70cbSLiam Girdwood 455414c70cbSLiam Girdwood if (!rdev->constraints) 456414c70cbSLiam Girdwood return sprintf(buf, "constraint not defined\n"); 457414c70cbSLiam Girdwood 458414c70cbSLiam Girdwood return sprintf(buf, "%d\n", rdev->constraints->max_uA); 459414c70cbSLiam Girdwood } 4607ad68e2fSDavid Brownell static DEVICE_ATTR(max_microamps, 0444, regulator_max_uA_show, NULL); 461414c70cbSLiam Girdwood 462414c70cbSLiam Girdwood static ssize_t regulator_min_uV_show(struct device *dev, 463414c70cbSLiam Girdwood struct device_attribute *attr, char *buf) 464414c70cbSLiam Girdwood { 465a5766f11SLiam Girdwood struct regulator_dev *rdev = dev_get_drvdata(dev); 466414c70cbSLiam Girdwood 467414c70cbSLiam Girdwood if (!rdev->constraints) 468414c70cbSLiam Girdwood return sprintf(buf, "constraint not defined\n"); 469414c70cbSLiam Girdwood 470414c70cbSLiam Girdwood return sprintf(buf, "%d\n", rdev->constraints->min_uV); 471414c70cbSLiam Girdwood } 4727ad68e2fSDavid Brownell static DEVICE_ATTR(min_microvolts, 0444, regulator_min_uV_show, NULL); 473414c70cbSLiam Girdwood 474414c70cbSLiam Girdwood static ssize_t regulator_max_uV_show(struct device *dev, 475414c70cbSLiam Girdwood struct device_attribute *attr, char *buf) 476414c70cbSLiam Girdwood { 477a5766f11SLiam Girdwood struct regulator_dev *rdev = dev_get_drvdata(dev); 478414c70cbSLiam Girdwood 479414c70cbSLiam Girdwood if (!rdev->constraints) 480414c70cbSLiam Girdwood return sprintf(buf, "constraint not defined\n"); 481414c70cbSLiam Girdwood 482414c70cbSLiam Girdwood return sprintf(buf, "%d\n", rdev->constraints->max_uV); 483414c70cbSLiam Girdwood } 4847ad68e2fSDavid Brownell static DEVICE_ATTR(max_microvolts, 0444, regulator_max_uV_show, NULL); 485414c70cbSLiam Girdwood 486414c70cbSLiam Girdwood static ssize_t regulator_total_uA_show(struct device *dev, 487414c70cbSLiam Girdwood struct device_attribute *attr, char *buf) 488414c70cbSLiam Girdwood { 489a5766f11SLiam Girdwood struct regulator_dev *rdev = dev_get_drvdata(dev); 490414c70cbSLiam Girdwood struct regulator *regulator; 491414c70cbSLiam Girdwood int uA = 0; 492414c70cbSLiam Girdwood 493414c70cbSLiam Girdwood mutex_lock(&rdev->mutex); 494414c70cbSLiam Girdwood list_for_each_entry(regulator, &rdev->consumer_list, list) 495414c70cbSLiam Girdwood uA += regulator->uA_load; 496414c70cbSLiam Girdwood mutex_unlock(&rdev->mutex); 497414c70cbSLiam Girdwood return sprintf(buf, "%d\n", uA); 498414c70cbSLiam Girdwood } 4997ad68e2fSDavid Brownell static DEVICE_ATTR(requested_microamps, 0444, regulator_total_uA_show, NULL); 500414c70cbSLiam Girdwood 501414c70cbSLiam Girdwood static ssize_t regulator_num_users_show(struct device *dev, 502414c70cbSLiam Girdwood struct device_attribute *attr, char *buf) 503414c70cbSLiam Girdwood { 504a5766f11SLiam Girdwood struct regulator_dev *rdev = dev_get_drvdata(dev); 505414c70cbSLiam Girdwood return sprintf(buf, "%d\n", rdev->use_count); 506414c70cbSLiam Girdwood } 507414c70cbSLiam Girdwood 508414c70cbSLiam Girdwood static ssize_t regulator_type_show(struct device *dev, 509414c70cbSLiam Girdwood struct device_attribute *attr, char *buf) 510414c70cbSLiam Girdwood { 511a5766f11SLiam Girdwood struct regulator_dev *rdev = dev_get_drvdata(dev); 512414c70cbSLiam Girdwood 513414c70cbSLiam Girdwood switch (rdev->desc->type) { 514414c70cbSLiam Girdwood case REGULATOR_VOLTAGE: 515414c70cbSLiam Girdwood return sprintf(buf, "voltage\n"); 516414c70cbSLiam Girdwood case REGULATOR_CURRENT: 517414c70cbSLiam Girdwood return sprintf(buf, "current\n"); 518414c70cbSLiam Girdwood } 519414c70cbSLiam Girdwood return sprintf(buf, "unknown\n"); 520414c70cbSLiam Girdwood } 521414c70cbSLiam Girdwood 522414c70cbSLiam Girdwood static ssize_t regulator_suspend_mem_uV_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 527414c70cbSLiam Girdwood return sprintf(buf, "%d\n", rdev->constraints->state_mem.uV); 528414c70cbSLiam Girdwood } 5297ad68e2fSDavid Brownell static DEVICE_ATTR(suspend_mem_microvolts, 0444, 5307ad68e2fSDavid Brownell regulator_suspend_mem_uV_show, NULL); 531414c70cbSLiam Girdwood 532414c70cbSLiam Girdwood static ssize_t regulator_suspend_disk_uV_show(struct device *dev, 533414c70cbSLiam Girdwood struct device_attribute *attr, char *buf) 534414c70cbSLiam Girdwood { 535a5766f11SLiam Girdwood struct regulator_dev *rdev = dev_get_drvdata(dev); 536414c70cbSLiam Girdwood 537414c70cbSLiam Girdwood return sprintf(buf, "%d\n", rdev->constraints->state_disk.uV); 538414c70cbSLiam Girdwood } 5397ad68e2fSDavid Brownell static DEVICE_ATTR(suspend_disk_microvolts, 0444, 5407ad68e2fSDavid Brownell regulator_suspend_disk_uV_show, NULL); 541414c70cbSLiam Girdwood 542414c70cbSLiam Girdwood static ssize_t regulator_suspend_standby_uV_show(struct device *dev, 543414c70cbSLiam Girdwood struct device_attribute *attr, char *buf) 544414c70cbSLiam Girdwood { 545a5766f11SLiam Girdwood struct regulator_dev *rdev = dev_get_drvdata(dev); 546414c70cbSLiam Girdwood 547414c70cbSLiam Girdwood return sprintf(buf, "%d\n", rdev->constraints->state_standby.uV); 548414c70cbSLiam Girdwood } 5497ad68e2fSDavid Brownell static DEVICE_ATTR(suspend_standby_microvolts, 0444, 5507ad68e2fSDavid Brownell regulator_suspend_standby_uV_show, NULL); 551414c70cbSLiam Girdwood 552414c70cbSLiam Girdwood static ssize_t regulator_suspend_mem_mode_show(struct device *dev, 553414c70cbSLiam Girdwood struct device_attribute *attr, char *buf) 554414c70cbSLiam Girdwood { 555a5766f11SLiam Girdwood struct regulator_dev *rdev = dev_get_drvdata(dev); 556414c70cbSLiam Girdwood 5574fca9545SDavid Brownell return regulator_print_opmode(buf, 5584fca9545SDavid Brownell rdev->constraints->state_mem.mode); 559414c70cbSLiam Girdwood } 5607ad68e2fSDavid Brownell static DEVICE_ATTR(suspend_mem_mode, 0444, 5617ad68e2fSDavid Brownell regulator_suspend_mem_mode_show, NULL); 562414c70cbSLiam Girdwood 563414c70cbSLiam Girdwood static ssize_t regulator_suspend_disk_mode_show(struct device *dev, 564414c70cbSLiam Girdwood struct device_attribute *attr, char *buf) 565414c70cbSLiam Girdwood { 566a5766f11SLiam Girdwood struct regulator_dev *rdev = dev_get_drvdata(dev); 567414c70cbSLiam Girdwood 5684fca9545SDavid Brownell return regulator_print_opmode(buf, 5694fca9545SDavid Brownell rdev->constraints->state_disk.mode); 570414c70cbSLiam Girdwood } 5717ad68e2fSDavid Brownell static DEVICE_ATTR(suspend_disk_mode, 0444, 5727ad68e2fSDavid Brownell regulator_suspend_disk_mode_show, NULL); 573414c70cbSLiam Girdwood 574414c70cbSLiam Girdwood static ssize_t regulator_suspend_standby_mode_show(struct device *dev, 575414c70cbSLiam Girdwood struct device_attribute *attr, char *buf) 576414c70cbSLiam Girdwood { 577a5766f11SLiam Girdwood struct regulator_dev *rdev = dev_get_drvdata(dev); 578414c70cbSLiam Girdwood 5794fca9545SDavid Brownell return regulator_print_opmode(buf, 5804fca9545SDavid Brownell rdev->constraints->state_standby.mode); 581414c70cbSLiam Girdwood } 5827ad68e2fSDavid Brownell static DEVICE_ATTR(suspend_standby_mode, 0444, 5837ad68e2fSDavid Brownell regulator_suspend_standby_mode_show, NULL); 584414c70cbSLiam Girdwood 585414c70cbSLiam Girdwood static ssize_t regulator_suspend_mem_state_show(struct device *dev, 586414c70cbSLiam Girdwood struct device_attribute *attr, char *buf) 587414c70cbSLiam Girdwood { 588a5766f11SLiam Girdwood struct regulator_dev *rdev = dev_get_drvdata(dev); 589414c70cbSLiam Girdwood 5904fca9545SDavid Brownell return regulator_print_state(buf, 5914fca9545SDavid Brownell rdev->constraints->state_mem.enabled); 592414c70cbSLiam Girdwood } 5937ad68e2fSDavid Brownell static DEVICE_ATTR(suspend_mem_state, 0444, 5947ad68e2fSDavid Brownell regulator_suspend_mem_state_show, NULL); 595414c70cbSLiam Girdwood 596414c70cbSLiam Girdwood static ssize_t regulator_suspend_disk_state_show(struct device *dev, 597414c70cbSLiam Girdwood struct device_attribute *attr, char *buf) 598414c70cbSLiam Girdwood { 599a5766f11SLiam Girdwood struct regulator_dev *rdev = dev_get_drvdata(dev); 600414c70cbSLiam Girdwood 6014fca9545SDavid Brownell return regulator_print_state(buf, 6024fca9545SDavid Brownell rdev->constraints->state_disk.enabled); 603414c70cbSLiam Girdwood } 6047ad68e2fSDavid Brownell static DEVICE_ATTR(suspend_disk_state, 0444, 6057ad68e2fSDavid Brownell regulator_suspend_disk_state_show, NULL); 606414c70cbSLiam Girdwood 607414c70cbSLiam Girdwood static ssize_t regulator_suspend_standby_state_show(struct device *dev, 608414c70cbSLiam Girdwood struct device_attribute *attr, char *buf) 609414c70cbSLiam Girdwood { 610a5766f11SLiam Girdwood struct regulator_dev *rdev = dev_get_drvdata(dev); 611414c70cbSLiam Girdwood 6124fca9545SDavid Brownell return regulator_print_state(buf, 6134fca9545SDavid Brownell rdev->constraints->state_standby.enabled); 614414c70cbSLiam Girdwood } 6157ad68e2fSDavid Brownell static DEVICE_ATTR(suspend_standby_state, 0444, 6167ad68e2fSDavid Brownell regulator_suspend_standby_state_show, NULL); 617bc558a60SMark Brown 6187ad68e2fSDavid Brownell 6197ad68e2fSDavid Brownell /* 6207ad68e2fSDavid Brownell * These are the only attributes are present for all regulators. 6217ad68e2fSDavid Brownell * Other attributes are a function of regulator functionality. 6227ad68e2fSDavid Brownell */ 623414c70cbSLiam Girdwood static struct device_attribute regulator_dev_attrs[] = { 624bc558a60SMark Brown __ATTR(name, 0444, regulator_name_show, NULL), 625414c70cbSLiam Girdwood __ATTR(num_users, 0444, regulator_num_users_show, NULL), 626414c70cbSLiam Girdwood __ATTR(type, 0444, regulator_type_show, NULL), 627414c70cbSLiam Girdwood __ATTR_NULL, 628414c70cbSLiam Girdwood }; 629414c70cbSLiam Girdwood 630414c70cbSLiam Girdwood static void regulator_dev_release(struct device *dev) 631414c70cbSLiam Girdwood { 632a5766f11SLiam Girdwood struct regulator_dev *rdev = dev_get_drvdata(dev); 633414c70cbSLiam Girdwood kfree(rdev); 634414c70cbSLiam Girdwood } 635414c70cbSLiam Girdwood 636414c70cbSLiam Girdwood static struct class regulator_class = { 637414c70cbSLiam Girdwood .name = "regulator", 638414c70cbSLiam Girdwood .dev_release = regulator_dev_release, 639414c70cbSLiam Girdwood .dev_attrs = regulator_dev_attrs, 640414c70cbSLiam Girdwood }; 641414c70cbSLiam Girdwood 642414c70cbSLiam Girdwood /* Calculate the new optimum regulator operating mode based on the new total 643414c70cbSLiam Girdwood * consumer load. All locks held by caller */ 644414c70cbSLiam Girdwood static void drms_uA_update(struct regulator_dev *rdev) 645414c70cbSLiam Girdwood { 646414c70cbSLiam Girdwood struct regulator *sibling; 647414c70cbSLiam Girdwood int current_uA = 0, output_uV, input_uV, err; 648414c70cbSLiam Girdwood unsigned int mode; 649414c70cbSLiam Girdwood 650414c70cbSLiam Girdwood err = regulator_check_drms(rdev); 651414c70cbSLiam Girdwood if (err < 0 || !rdev->desc->ops->get_optimum_mode || 652476c2d83SMark Brown (!rdev->desc->ops->get_voltage && 653476c2d83SMark Brown !rdev->desc->ops->get_voltage_sel) || 654476c2d83SMark Brown !rdev->desc->ops->set_mode) 655414c70cbSLiam Girdwood return; 656414c70cbSLiam Girdwood 657414c70cbSLiam Girdwood /* get output voltage */ 6581bf5a1f8SMark Brown output_uV = _regulator_get_voltage(rdev); 659414c70cbSLiam Girdwood if (output_uV <= 0) 660414c70cbSLiam Girdwood return; 661414c70cbSLiam Girdwood 662414c70cbSLiam Girdwood /* get input voltage */ 6631bf5a1f8SMark Brown input_uV = 0; 6641bf5a1f8SMark Brown if (rdev->supply) 6653f24f5adSAxel Lin input_uV = regulator_get_voltage(rdev->supply); 6661bf5a1f8SMark Brown if (input_uV <= 0) 667414c70cbSLiam Girdwood input_uV = rdev->constraints->input_uV; 668414c70cbSLiam Girdwood if (input_uV <= 0) 669414c70cbSLiam Girdwood return; 670414c70cbSLiam Girdwood 671414c70cbSLiam Girdwood /* calc total requested load */ 672414c70cbSLiam Girdwood list_for_each_entry(sibling, &rdev->consumer_list, list) 673414c70cbSLiam Girdwood current_uA += sibling->uA_load; 674414c70cbSLiam Girdwood 675414c70cbSLiam Girdwood /* now get the optimum mode for our new total regulator load */ 676414c70cbSLiam Girdwood mode = rdev->desc->ops->get_optimum_mode(rdev, input_uV, 677414c70cbSLiam Girdwood output_uV, current_uA); 678414c70cbSLiam Girdwood 679414c70cbSLiam Girdwood /* check the new mode is allowed */ 6802c608234SMark Brown err = regulator_mode_constrain(rdev, &mode); 681414c70cbSLiam Girdwood if (err == 0) 682414c70cbSLiam Girdwood rdev->desc->ops->set_mode(rdev, mode); 683414c70cbSLiam Girdwood } 684414c70cbSLiam Girdwood 685414c70cbSLiam Girdwood static int suspend_set_state(struct regulator_dev *rdev, 686414c70cbSLiam Girdwood struct regulator_state *rstate) 687414c70cbSLiam Girdwood { 688414c70cbSLiam Girdwood int ret = 0; 689638f85c5SMark Brown 690638f85c5SMark Brown /* If we have no suspend mode configration don't set anything; 6918ac0e95dSAxel Lin * only warn if the driver implements set_suspend_voltage or 6928ac0e95dSAxel Lin * set_suspend_mode callback. 693638f85c5SMark Brown */ 694638f85c5SMark Brown if (!rstate->enabled && !rstate->disabled) { 6958ac0e95dSAxel Lin if (rdev->desc->ops->set_suspend_voltage || 6968ac0e95dSAxel Lin rdev->desc->ops->set_suspend_mode) 6975da84fd9SJoe Perches rdev_warn(rdev, "No configuration\n"); 698638f85c5SMark Brown return 0; 699638f85c5SMark Brown } 700638f85c5SMark Brown 701638f85c5SMark Brown if (rstate->enabled && rstate->disabled) { 7025da84fd9SJoe Perches rdev_err(rdev, "invalid configuration\n"); 703638f85c5SMark Brown return -EINVAL; 704638f85c5SMark Brown } 705638f85c5SMark Brown 7068ac0e95dSAxel Lin if (rstate->enabled && rdev->desc->ops->set_suspend_enable) 707414c70cbSLiam Girdwood ret = rdev->desc->ops->set_suspend_enable(rdev); 7088ac0e95dSAxel Lin else if (rstate->disabled && rdev->desc->ops->set_suspend_disable) 709414c70cbSLiam Girdwood ret = rdev->desc->ops->set_suspend_disable(rdev); 7108ac0e95dSAxel Lin else /* OK if set_suspend_enable or set_suspend_disable is NULL */ 7118ac0e95dSAxel Lin ret = 0; 7128ac0e95dSAxel Lin 713414c70cbSLiam Girdwood if (ret < 0) { 7145da84fd9SJoe Perches rdev_err(rdev, "failed to enabled/disable\n"); 715414c70cbSLiam Girdwood return ret; 716414c70cbSLiam Girdwood } 717414c70cbSLiam Girdwood 718414c70cbSLiam Girdwood if (rdev->desc->ops->set_suspend_voltage && rstate->uV > 0) { 719414c70cbSLiam Girdwood ret = rdev->desc->ops->set_suspend_voltage(rdev, rstate->uV); 720414c70cbSLiam Girdwood if (ret < 0) { 7215da84fd9SJoe Perches rdev_err(rdev, "failed to set voltage\n"); 722414c70cbSLiam Girdwood return ret; 723414c70cbSLiam Girdwood } 724414c70cbSLiam Girdwood } 725414c70cbSLiam Girdwood 726414c70cbSLiam Girdwood if (rdev->desc->ops->set_suspend_mode && rstate->mode > 0) { 727414c70cbSLiam Girdwood ret = rdev->desc->ops->set_suspend_mode(rdev, rstate->mode); 728414c70cbSLiam Girdwood if (ret < 0) { 7295da84fd9SJoe Perches rdev_err(rdev, "failed to set mode\n"); 730414c70cbSLiam Girdwood return ret; 731414c70cbSLiam Girdwood } 732414c70cbSLiam Girdwood } 733414c70cbSLiam Girdwood return ret; 734414c70cbSLiam Girdwood } 735414c70cbSLiam Girdwood 736414c70cbSLiam Girdwood /* locks held by caller */ 737414c70cbSLiam Girdwood static int suspend_prepare(struct regulator_dev *rdev, suspend_state_t state) 738414c70cbSLiam Girdwood { 739414c70cbSLiam Girdwood if (!rdev->constraints) 740414c70cbSLiam Girdwood return -EINVAL; 741414c70cbSLiam Girdwood 742414c70cbSLiam Girdwood switch (state) { 743414c70cbSLiam Girdwood case PM_SUSPEND_STANDBY: 744414c70cbSLiam Girdwood return suspend_set_state(rdev, 745414c70cbSLiam Girdwood &rdev->constraints->state_standby); 746414c70cbSLiam Girdwood case PM_SUSPEND_MEM: 747414c70cbSLiam Girdwood return suspend_set_state(rdev, 748414c70cbSLiam Girdwood &rdev->constraints->state_mem); 749414c70cbSLiam Girdwood case PM_SUSPEND_MAX: 750414c70cbSLiam Girdwood return suspend_set_state(rdev, 751414c70cbSLiam Girdwood &rdev->constraints->state_disk); 752414c70cbSLiam Girdwood default: 753414c70cbSLiam Girdwood return -EINVAL; 754414c70cbSLiam Girdwood } 755414c70cbSLiam Girdwood } 756414c70cbSLiam Girdwood 757414c70cbSLiam Girdwood static void print_constraints(struct regulator_dev *rdev) 758414c70cbSLiam Girdwood { 759414c70cbSLiam Girdwood struct regulation_constraints *constraints = rdev->constraints; 760973e9a27SMark Brown char buf[80] = ""; 7618f031b48SMark Brown int count = 0; 7628f031b48SMark Brown int ret; 763414c70cbSLiam Girdwood 7648f031b48SMark Brown if (constraints->min_uV && constraints->max_uV) { 765414c70cbSLiam Girdwood if (constraints->min_uV == constraints->max_uV) 7668f031b48SMark Brown count += sprintf(buf + count, "%d mV ", 767414c70cbSLiam Girdwood constraints->min_uV / 1000); 768414c70cbSLiam Girdwood else 7698f031b48SMark Brown count += sprintf(buf + count, "%d <--> %d mV ", 770414c70cbSLiam Girdwood constraints->min_uV / 1000, 771414c70cbSLiam Girdwood constraints->max_uV / 1000); 7728f031b48SMark Brown } 7738f031b48SMark Brown 7748f031b48SMark Brown if (!constraints->min_uV || 7758f031b48SMark Brown constraints->min_uV != constraints->max_uV) { 7768f031b48SMark Brown ret = _regulator_get_voltage(rdev); 7778f031b48SMark Brown if (ret > 0) 7788f031b48SMark Brown count += sprintf(buf + count, "at %d mV ", ret / 1000); 7798f031b48SMark Brown } 7808f031b48SMark Brown 781bf5892a8SMark Brown if (constraints->uV_offset) 782bf5892a8SMark Brown count += sprintf(buf, "%dmV offset ", 783bf5892a8SMark Brown constraints->uV_offset / 1000); 784bf5892a8SMark Brown 7858f031b48SMark Brown if (constraints->min_uA && constraints->max_uA) { 786414c70cbSLiam Girdwood if (constraints->min_uA == constraints->max_uA) 7878f031b48SMark Brown count += sprintf(buf + count, "%d mA ", 788414c70cbSLiam Girdwood constraints->min_uA / 1000); 789414c70cbSLiam Girdwood else 7908f031b48SMark Brown count += sprintf(buf + count, "%d <--> %d mA ", 791414c70cbSLiam Girdwood constraints->min_uA / 1000, 792414c70cbSLiam Girdwood constraints->max_uA / 1000); 793414c70cbSLiam Girdwood } 7948f031b48SMark Brown 7958f031b48SMark Brown if (!constraints->min_uA || 7968f031b48SMark Brown constraints->min_uA != constraints->max_uA) { 7978f031b48SMark Brown ret = _regulator_get_current_limit(rdev); 7988f031b48SMark Brown if (ret > 0) 799e4a6376bSCyril Chemparathy count += sprintf(buf + count, "at %d mA ", ret / 1000); 8008f031b48SMark Brown } 8018f031b48SMark Brown 802414c70cbSLiam Girdwood if (constraints->valid_modes_mask & REGULATOR_MODE_FAST) 803414c70cbSLiam Girdwood count += sprintf(buf + count, "fast "); 804414c70cbSLiam Girdwood if (constraints->valid_modes_mask & REGULATOR_MODE_NORMAL) 805414c70cbSLiam Girdwood count += sprintf(buf + count, "normal "); 806414c70cbSLiam Girdwood if (constraints->valid_modes_mask & REGULATOR_MODE_IDLE) 807414c70cbSLiam Girdwood count += sprintf(buf + count, "idle "); 808414c70cbSLiam Girdwood if (constraints->valid_modes_mask & REGULATOR_MODE_STANDBY) 809414c70cbSLiam Girdwood count += sprintf(buf + count, "standby"); 810414c70cbSLiam Girdwood 81113ce29f8SMark Brown rdev_info(rdev, "%s\n", buf); 8124a682922SMark Brown 8134a682922SMark Brown if ((constraints->min_uV != constraints->max_uV) && 8144a682922SMark Brown !(constraints->valid_ops_mask & REGULATOR_CHANGE_VOLTAGE)) 8154a682922SMark Brown rdev_warn(rdev, 8164a682922SMark Brown "Voltage range but no REGULATOR_CHANGE_VOLTAGE\n"); 817414c70cbSLiam Girdwood } 818414c70cbSLiam Girdwood 819e79055d6SMark Brown static int machine_constraints_voltage(struct regulator_dev *rdev, 8201083c393SMark Brown struct regulation_constraints *constraints) 821e79055d6SMark Brown { 822e79055d6SMark Brown struct regulator_ops *ops = rdev->desc->ops; 823af5866c9SMark Brown int ret; 824af5866c9SMark Brown 825af5866c9SMark Brown /* do we need to apply the constraint voltage */ 826af5866c9SMark Brown if (rdev->constraints->apply_uV && 82775790251SMark Brown rdev->constraints->min_uV == rdev->constraints->max_uV) { 82875790251SMark Brown ret = _regulator_do_set_voltage(rdev, 8293a93f2a9SMark Brown rdev->constraints->min_uV, 83075790251SMark Brown rdev->constraints->max_uV); 831af5866c9SMark Brown if (ret < 0) { 8325da84fd9SJoe Perches rdev_err(rdev, "failed to apply %duV constraint\n", 8335da84fd9SJoe Perches rdev->constraints->min_uV); 834af5866c9SMark Brown return ret; 835af5866c9SMark Brown } 836af5866c9SMark Brown } 837e79055d6SMark Brown 838e79055d6SMark Brown /* constrain machine-level voltage specs to fit 839e79055d6SMark Brown * the actual range supported by this regulator. 840e79055d6SMark Brown */ 841e79055d6SMark Brown if (ops->list_voltage && rdev->desc->n_voltages) { 842e79055d6SMark Brown int count = rdev->desc->n_voltages; 843e79055d6SMark Brown int i; 844e79055d6SMark Brown int min_uV = INT_MAX; 845e79055d6SMark Brown int max_uV = INT_MIN; 846e79055d6SMark Brown int cmin = constraints->min_uV; 847e79055d6SMark Brown int cmax = constraints->max_uV; 848e79055d6SMark Brown 849e79055d6SMark Brown /* it's safe to autoconfigure fixed-voltage supplies 850e79055d6SMark Brown and the constraints are used by list_voltage. */ 851e79055d6SMark Brown if (count == 1 && !cmin) { 852e79055d6SMark Brown cmin = 1; 853e79055d6SMark Brown cmax = INT_MAX; 854e79055d6SMark Brown constraints->min_uV = cmin; 855e79055d6SMark Brown constraints->max_uV = cmax; 856e79055d6SMark Brown } 857e79055d6SMark Brown 858e79055d6SMark Brown /* voltage constraints are optional */ 859e79055d6SMark Brown if ((cmin == 0) && (cmax == 0)) 860e79055d6SMark Brown return 0; 861e79055d6SMark Brown 862e79055d6SMark Brown /* else require explicit machine-level constraints */ 863e79055d6SMark Brown if (cmin <= 0 || cmax <= 0 || cmax < cmin) { 8645da84fd9SJoe Perches rdev_err(rdev, "invalid voltage constraints\n"); 865e79055d6SMark Brown return -EINVAL; 866e79055d6SMark Brown } 867e79055d6SMark Brown 868e79055d6SMark Brown /* initial: [cmin..cmax] valid, [min_uV..max_uV] not */ 869e79055d6SMark Brown for (i = 0; i < count; i++) { 870e79055d6SMark Brown int value; 871e79055d6SMark Brown 872e79055d6SMark Brown value = ops->list_voltage(rdev, i); 873e79055d6SMark Brown if (value <= 0) 874e79055d6SMark Brown continue; 875e79055d6SMark Brown 876e79055d6SMark Brown /* maybe adjust [min_uV..max_uV] */ 877e79055d6SMark Brown if (value >= cmin && value < min_uV) 878e79055d6SMark Brown min_uV = value; 879e79055d6SMark Brown if (value <= cmax && value > max_uV) 880e79055d6SMark Brown max_uV = value; 881e79055d6SMark Brown } 882e79055d6SMark Brown 883e79055d6SMark Brown /* final: [min_uV..max_uV] valid iff constraints valid */ 884e79055d6SMark Brown if (max_uV < min_uV) { 8855da84fd9SJoe Perches rdev_err(rdev, "unsupportable voltage constraints\n"); 886e79055d6SMark Brown return -EINVAL; 887e79055d6SMark Brown } 888e79055d6SMark Brown 889e79055d6SMark Brown /* use regulator's subset of machine constraints */ 890e79055d6SMark Brown if (constraints->min_uV < min_uV) { 8915da84fd9SJoe Perches rdev_dbg(rdev, "override min_uV, %d -> %d\n", 8925da84fd9SJoe Perches constraints->min_uV, min_uV); 893e79055d6SMark Brown constraints->min_uV = min_uV; 894e79055d6SMark Brown } 895e79055d6SMark Brown if (constraints->max_uV > max_uV) { 8965da84fd9SJoe Perches rdev_dbg(rdev, "override max_uV, %d -> %d\n", 8975da84fd9SJoe Perches constraints->max_uV, max_uV); 898e79055d6SMark Brown constraints->max_uV = max_uV; 899e79055d6SMark Brown } 900e79055d6SMark Brown } 901e79055d6SMark Brown 902e79055d6SMark Brown return 0; 903e79055d6SMark Brown } 904e79055d6SMark Brown 905a5766f11SLiam Girdwood /** 906a5766f11SLiam Girdwood * set_machine_constraints - sets regulator constraints 90769279fb9SMark Brown * @rdev: regulator source 908c8e7e464SMark Brown * @constraints: constraints to apply 909a5766f11SLiam Girdwood * 910a5766f11SLiam Girdwood * Allows platform initialisation code to define and constrain 911a5766f11SLiam Girdwood * regulator circuits e.g. valid voltage/current ranges, etc. NOTE: 912a5766f11SLiam Girdwood * Constraints *must* be set by platform code in order for some 913a5766f11SLiam Girdwood * regulator operations to proceed i.e. set_voltage, set_current_limit, 914a5766f11SLiam Girdwood * set_mode. 915a5766f11SLiam Girdwood */ 916a5766f11SLiam Girdwood static int set_machine_constraints(struct regulator_dev *rdev, 917f8c12fe3SMark Brown const struct regulation_constraints *constraints) 918a5766f11SLiam Girdwood { 919a5766f11SLiam Girdwood int ret = 0; 920e5fda26cSMark Brown struct regulator_ops *ops = rdev->desc->ops; 921e06f5b4fSMark Brown 9229a8f5e07SMark Brown if (constraints) 923f8c12fe3SMark Brown rdev->constraints = kmemdup(constraints, sizeof(*constraints), 924f8c12fe3SMark Brown GFP_KERNEL); 9259a8f5e07SMark Brown else 9269a8f5e07SMark Brown rdev->constraints = kzalloc(sizeof(*constraints), 9279a8f5e07SMark Brown GFP_KERNEL); 928f8c12fe3SMark Brown if (!rdev->constraints) 929f8c12fe3SMark Brown return -ENOMEM; 930af5866c9SMark Brown 931f8c12fe3SMark Brown ret = machine_constraints_voltage(rdev, rdev->constraints); 932e79055d6SMark Brown if (ret != 0) 9333e2b9abdSMark Brown goto out; 9343e2b9abdSMark Brown 935a5766f11SLiam Girdwood /* do we need to setup our suspend state */ 9369a8f5e07SMark Brown if (rdev->constraints->initial_state) { 937f8c12fe3SMark Brown ret = suspend_prepare(rdev, rdev->constraints->initial_state); 938e06f5b4fSMark Brown if (ret < 0) { 9395da84fd9SJoe Perches rdev_err(rdev, "failed to set suspend state\n"); 940e06f5b4fSMark Brown goto out; 941e06f5b4fSMark Brown } 942e06f5b4fSMark Brown } 943a5766f11SLiam Girdwood 9449a8f5e07SMark Brown if (rdev->constraints->initial_mode) { 945a308466cSMark Brown if (!ops->set_mode) { 9465da84fd9SJoe Perches rdev_err(rdev, "no set_mode operation\n"); 947a308466cSMark Brown ret = -EINVAL; 948a308466cSMark Brown goto out; 949a308466cSMark Brown } 950a308466cSMark Brown 951f8c12fe3SMark Brown ret = ops->set_mode(rdev, rdev->constraints->initial_mode); 952a308466cSMark Brown if (ret < 0) { 9535da84fd9SJoe Perches rdev_err(rdev, "failed to set initial mode: %d\n", ret); 954a308466cSMark Brown goto out; 955a308466cSMark Brown } 956a308466cSMark Brown } 957a308466cSMark Brown 958cacf90f2SMark Brown /* If the constraints say the regulator should be on at this point 959cacf90f2SMark Brown * and we have control then make sure it is enabled. 960cacf90f2SMark Brown */ 961f8c12fe3SMark Brown if ((rdev->constraints->always_on || rdev->constraints->boot_on) && 962f8c12fe3SMark Brown ops->enable) { 963e5fda26cSMark Brown ret = ops->enable(rdev); 964e5fda26cSMark Brown if (ret < 0) { 9655da84fd9SJoe Perches rdev_err(rdev, "failed to enable\n"); 966e5fda26cSMark Brown goto out; 967e5fda26cSMark Brown } 968e5fda26cSMark Brown } 969e5fda26cSMark Brown 9706f0b2c69SYadwinder Singh Brar if (rdev->constraints->ramp_delay && ops->set_ramp_delay) { 9716f0b2c69SYadwinder Singh Brar ret = ops->set_ramp_delay(rdev, rdev->constraints->ramp_delay); 9726f0b2c69SYadwinder Singh Brar if (ret < 0) { 9736f0b2c69SYadwinder Singh Brar rdev_err(rdev, "failed to set ramp_delay\n"); 9746f0b2c69SYadwinder Singh Brar goto out; 9756f0b2c69SYadwinder Singh Brar } 9766f0b2c69SYadwinder Singh Brar } 9776f0b2c69SYadwinder Singh Brar 978a5766f11SLiam Girdwood print_constraints(rdev); 9791a6958e7SAxel Lin return 0; 980a5766f11SLiam Girdwood out: 9811a6958e7SAxel Lin kfree(rdev->constraints); 9821a6958e7SAxel Lin rdev->constraints = NULL; 983a5766f11SLiam Girdwood return ret; 984a5766f11SLiam Girdwood } 985a5766f11SLiam Girdwood 986a5766f11SLiam Girdwood /** 987a5766f11SLiam Girdwood * set_supply - set regulator supply regulator 98869279fb9SMark Brown * @rdev: regulator name 98969279fb9SMark Brown * @supply_rdev: supply regulator name 990a5766f11SLiam Girdwood * 991a5766f11SLiam Girdwood * Called by platform initialisation code to set the supply regulator for this 992a5766f11SLiam Girdwood * regulator. This ensures that a regulators supply will also be enabled by the 993a5766f11SLiam Girdwood * core if it's child is enabled. 994a5766f11SLiam Girdwood */ 995a5766f11SLiam Girdwood static int set_supply(struct regulator_dev *rdev, 996a5766f11SLiam Girdwood struct regulator_dev *supply_rdev) 997a5766f11SLiam Girdwood { 998a5766f11SLiam Girdwood int err; 999a5766f11SLiam Girdwood 10003801b86aSMark Brown rdev_info(rdev, "supplied by %s\n", rdev_get_name(supply_rdev)); 10013801b86aSMark Brown 10023801b86aSMark Brown rdev->supply = create_regulator(supply_rdev, &rdev->dev, "SUPPLY"); 100332c78de8SAxel Lin if (rdev->supply == NULL) { 100432c78de8SAxel Lin err = -ENOMEM; 1005a5766f11SLiam Girdwood return err; 1006a5766f11SLiam Girdwood } 1007a5766f11SLiam Girdwood 10083801b86aSMark Brown return 0; 10093801b86aSMark Brown } 10103801b86aSMark Brown 1011a5766f11SLiam Girdwood /** 101206c63f93SRandy Dunlap * set_consumer_device_supply - Bind a regulator to a symbolic supply 101369279fb9SMark Brown * @rdev: regulator source 101440f9244fSMark Brown * @consumer_dev_name: dev_name() string for device supply applies to 1015a5766f11SLiam Girdwood * @supply: symbolic name for supply 1016a5766f11SLiam Girdwood * 1017a5766f11SLiam Girdwood * Allows platform initialisation code to map physical regulator 1018a5766f11SLiam Girdwood * sources to symbolic names for supplies for use by devices. Devices 1019a5766f11SLiam Girdwood * should use these symbolic names to request regulators, avoiding the 1020a5766f11SLiam Girdwood * need to provide board-specific regulator names as platform data. 1021a5766f11SLiam Girdwood */ 1022a5766f11SLiam Girdwood static int set_consumer_device_supply(struct regulator_dev *rdev, 1023737f360dSMark Brown const char *consumer_dev_name, 102440f9244fSMark Brown const char *supply) 1025a5766f11SLiam Girdwood { 1026a5766f11SLiam Girdwood struct regulator_map *node; 10279ed2099eSMark Brown int has_dev; 1028a5766f11SLiam Girdwood 1029a5766f11SLiam Girdwood if (supply == NULL) 1030a5766f11SLiam Girdwood return -EINVAL; 1031a5766f11SLiam Girdwood 10329ed2099eSMark Brown if (consumer_dev_name != NULL) 10339ed2099eSMark Brown has_dev = 1; 10349ed2099eSMark Brown else 10359ed2099eSMark Brown has_dev = 0; 10369ed2099eSMark Brown 10376001e13cSDavid Brownell list_for_each_entry(node, ®ulator_map_list, list) { 103823b5cc2aSJani Nikula if (node->dev_name && consumer_dev_name) { 103923b5cc2aSJani Nikula if (strcmp(node->dev_name, consumer_dev_name) != 0) 10406001e13cSDavid Brownell continue; 104123b5cc2aSJani Nikula } else if (node->dev_name || consumer_dev_name) { 104223b5cc2aSJani Nikula continue; 104323b5cc2aSJani Nikula } 104423b5cc2aSJani Nikula 10456001e13cSDavid Brownell if (strcmp(node->supply, supply) != 0) 10466001e13cSDavid Brownell continue; 10476001e13cSDavid Brownell 1048737f360dSMark Brown pr_debug("%s: %s/%s is '%s' supply; fail %s/%s\n", 1049737f360dSMark Brown consumer_dev_name, 10506001e13cSDavid Brownell dev_name(&node->regulator->dev), 10516001e13cSDavid Brownell node->regulator->desc->name, 10526001e13cSDavid Brownell supply, 10531083c393SMark Brown dev_name(&rdev->dev), rdev_get_name(rdev)); 10546001e13cSDavid Brownell return -EBUSY; 10556001e13cSDavid Brownell } 10566001e13cSDavid Brownell 10579ed2099eSMark Brown node = kzalloc(sizeof(struct regulator_map), GFP_KERNEL); 1058a5766f11SLiam Girdwood if (node == NULL) 1059a5766f11SLiam Girdwood return -ENOMEM; 1060a5766f11SLiam Girdwood 1061a5766f11SLiam Girdwood node->regulator = rdev; 1062a5766f11SLiam Girdwood node->supply = supply; 1063a5766f11SLiam Girdwood 10649ed2099eSMark Brown if (has_dev) { 10659ed2099eSMark Brown node->dev_name = kstrdup(consumer_dev_name, GFP_KERNEL); 106640f9244fSMark Brown if (node->dev_name == NULL) { 106740f9244fSMark Brown kfree(node); 106840f9244fSMark Brown return -ENOMEM; 106940f9244fSMark Brown } 10709ed2099eSMark Brown } 107140f9244fSMark Brown 1072a5766f11SLiam Girdwood list_add(&node->list, ®ulator_map_list); 1073a5766f11SLiam Girdwood return 0; 1074a5766f11SLiam Girdwood } 1075a5766f11SLiam Girdwood 10760f1d747bSMike Rapoport static void unset_regulator_supplies(struct regulator_dev *rdev) 10770f1d747bSMike Rapoport { 10780f1d747bSMike Rapoport struct regulator_map *node, *n; 10790f1d747bSMike Rapoport 10800f1d747bSMike Rapoport list_for_each_entry_safe(node, n, ®ulator_map_list, list) { 10810f1d747bSMike Rapoport if (rdev == node->regulator) { 10820f1d747bSMike Rapoport list_del(&node->list); 108340f9244fSMark Brown kfree(node->dev_name); 10840f1d747bSMike Rapoport kfree(node); 10850f1d747bSMike Rapoport } 10860f1d747bSMike Rapoport } 10870f1d747bSMike Rapoport } 10880f1d747bSMike Rapoport 1089f5726ae3SMark Brown #define REG_STR_SIZE 64 1090414c70cbSLiam Girdwood 1091414c70cbSLiam Girdwood static struct regulator *create_regulator(struct regulator_dev *rdev, 1092414c70cbSLiam Girdwood struct device *dev, 1093414c70cbSLiam Girdwood const char *supply_name) 1094414c70cbSLiam Girdwood { 1095414c70cbSLiam Girdwood struct regulator *regulator; 1096414c70cbSLiam Girdwood char buf[REG_STR_SIZE]; 1097414c70cbSLiam Girdwood int err, size; 1098414c70cbSLiam Girdwood 1099414c70cbSLiam Girdwood regulator = kzalloc(sizeof(*regulator), GFP_KERNEL); 1100414c70cbSLiam Girdwood if (regulator == NULL) 1101414c70cbSLiam Girdwood return NULL; 1102414c70cbSLiam Girdwood 1103414c70cbSLiam Girdwood mutex_lock(&rdev->mutex); 1104414c70cbSLiam Girdwood regulator->rdev = rdev; 1105414c70cbSLiam Girdwood list_add(®ulator->list, &rdev->consumer_list); 1106414c70cbSLiam Girdwood 1107414c70cbSLiam Girdwood if (dev) { 1108414c70cbSLiam Girdwood /* create a 'requested_microamps_name' sysfs entry */ 1109e0eaedefSMark Brown size = scnprintf(buf, REG_STR_SIZE, 1110e0eaedefSMark Brown "microamps_requested_%s-%s", 1111e0eaedefSMark Brown dev_name(dev), supply_name); 1112414c70cbSLiam Girdwood if (size >= REG_STR_SIZE) 1113414c70cbSLiam Girdwood goto overflow_err; 1114414c70cbSLiam Girdwood 1115414c70cbSLiam Girdwood regulator->dev = dev; 11164f26a2abSAmeya Palande sysfs_attr_init(®ulator->dev_attr.attr); 1117414c70cbSLiam Girdwood regulator->dev_attr.attr.name = kstrdup(buf, GFP_KERNEL); 1118414c70cbSLiam Girdwood if (regulator->dev_attr.attr.name == NULL) 1119414c70cbSLiam Girdwood goto attr_name_err; 1120414c70cbSLiam Girdwood 1121414c70cbSLiam Girdwood regulator->dev_attr.attr.mode = 0444; 1122414c70cbSLiam Girdwood regulator->dev_attr.show = device_requested_uA_show; 1123414c70cbSLiam Girdwood err = device_create_file(dev, ®ulator->dev_attr); 1124414c70cbSLiam Girdwood if (err < 0) { 11255da84fd9SJoe Perches rdev_warn(rdev, "could not add regulator_dev requested microamps sysfs entry\n"); 1126414c70cbSLiam Girdwood goto attr_name_err; 1127414c70cbSLiam Girdwood } 1128414c70cbSLiam Girdwood 1129414c70cbSLiam Girdwood /* also add a link to the device sysfs entry */ 1130414c70cbSLiam Girdwood size = scnprintf(buf, REG_STR_SIZE, "%s-%s", 1131414c70cbSLiam Girdwood dev->kobj.name, supply_name); 1132414c70cbSLiam Girdwood if (size >= REG_STR_SIZE) 1133414c70cbSLiam Girdwood goto attr_err; 1134414c70cbSLiam Girdwood 1135414c70cbSLiam Girdwood regulator->supply_name = kstrdup(buf, GFP_KERNEL); 1136414c70cbSLiam Girdwood if (regulator->supply_name == NULL) 1137414c70cbSLiam Girdwood goto attr_err; 1138414c70cbSLiam Girdwood 1139414c70cbSLiam Girdwood err = sysfs_create_link(&rdev->dev.kobj, &dev->kobj, 1140414c70cbSLiam Girdwood buf); 1141414c70cbSLiam Girdwood if (err) { 11425da84fd9SJoe Perches rdev_warn(rdev, "could not add device link %s err %d\n", 11431d7372e1SDaniel Walker dev->kobj.name, err); 1144414c70cbSLiam Girdwood goto link_name_err; 1145414c70cbSLiam Girdwood } 11465de70519SMark Brown } else { 11475de70519SMark Brown regulator->supply_name = kstrdup(supply_name, GFP_KERNEL); 11485de70519SMark Brown if (regulator->supply_name == NULL) 11495de70519SMark Brown goto attr_err; 1150414c70cbSLiam Girdwood } 11515de70519SMark Brown 11525de70519SMark Brown regulator->debugfs = debugfs_create_dir(regulator->supply_name, 11535de70519SMark Brown rdev->debugfs); 115424751434SStephen Boyd if (!regulator->debugfs) { 11555de70519SMark Brown rdev_warn(rdev, "Failed to create debugfs directory\n"); 11565de70519SMark Brown } else { 11575de70519SMark Brown debugfs_create_u32("uA_load", 0444, regulator->debugfs, 11585de70519SMark Brown ®ulator->uA_load); 11595de70519SMark Brown debugfs_create_u32("min_uV", 0444, regulator->debugfs, 11605de70519SMark Brown ®ulator->min_uV); 11615de70519SMark Brown debugfs_create_u32("max_uV", 0444, regulator->debugfs, 11625de70519SMark Brown ®ulator->max_uV); 11635de70519SMark Brown } 11645de70519SMark Brown 11656492bc1bSMark Brown /* 11666492bc1bSMark Brown * Check now if the regulator is an always on regulator - if 11676492bc1bSMark Brown * it is then we don't need to do nearly so much work for 11686492bc1bSMark Brown * enable/disable calls. 11696492bc1bSMark Brown */ 11706492bc1bSMark Brown if (!_regulator_can_change_status(rdev) && 11716492bc1bSMark Brown _regulator_is_enabled(rdev)) 11726492bc1bSMark Brown regulator->always_on = true; 11736492bc1bSMark Brown 1174414c70cbSLiam Girdwood mutex_unlock(&rdev->mutex); 1175414c70cbSLiam Girdwood return regulator; 1176414c70cbSLiam Girdwood link_name_err: 1177414c70cbSLiam Girdwood kfree(regulator->supply_name); 1178414c70cbSLiam Girdwood attr_err: 1179414c70cbSLiam Girdwood device_remove_file(regulator->dev, ®ulator->dev_attr); 1180414c70cbSLiam Girdwood attr_name_err: 1181414c70cbSLiam Girdwood kfree(regulator->dev_attr.attr.name); 1182414c70cbSLiam Girdwood overflow_err: 1183414c70cbSLiam Girdwood list_del(®ulator->list); 1184414c70cbSLiam Girdwood kfree(regulator); 1185414c70cbSLiam Girdwood mutex_unlock(&rdev->mutex); 1186414c70cbSLiam Girdwood return NULL; 1187414c70cbSLiam Girdwood } 1188414c70cbSLiam Girdwood 118931aae2beSMark Brown static int _regulator_get_enable_time(struct regulator_dev *rdev) 119031aae2beSMark Brown { 119131aae2beSMark Brown if (!rdev->desc->ops->enable_time) 119231aae2beSMark Brown return 0; 119331aae2beSMark Brown return rdev->desc->ops->enable_time(rdev); 119431aae2beSMark Brown } 119531aae2beSMark Brown 119669511a45SRajendra Nayak static struct regulator_dev *regulator_dev_lookup(struct device *dev, 11976d191a5fSMark Brown const char *supply, 11986d191a5fSMark Brown int *ret) 119969511a45SRajendra Nayak { 120069511a45SRajendra Nayak struct regulator_dev *r; 120169511a45SRajendra Nayak struct device_node *node; 1202576ca436SMark Brown struct regulator_map *map; 1203576ca436SMark Brown const char *devname = NULL; 120469511a45SRajendra Nayak 120569511a45SRajendra Nayak /* first do a dt based lookup */ 120669511a45SRajendra Nayak if (dev && dev->of_node) { 120769511a45SRajendra Nayak node = of_get_regulator(dev, supply); 12086d191a5fSMark Brown if (node) { 120969511a45SRajendra Nayak list_for_each_entry(r, ®ulator_list, list) 121069511a45SRajendra Nayak if (r->dev.parent && 121169511a45SRajendra Nayak node == r->dev.of_node) 121269511a45SRajendra Nayak return r; 12136d191a5fSMark Brown } else { 12146d191a5fSMark Brown /* 12156d191a5fSMark Brown * If we couldn't even get the node then it's 12166d191a5fSMark Brown * not just that the device didn't register 12176d191a5fSMark Brown * yet, there's no node and we'll never 12186d191a5fSMark Brown * succeed. 12196d191a5fSMark Brown */ 12206d191a5fSMark Brown *ret = -ENODEV; 12216d191a5fSMark Brown } 122269511a45SRajendra Nayak } 122369511a45SRajendra Nayak 122469511a45SRajendra Nayak /* if not found, try doing it non-dt way */ 1225576ca436SMark Brown if (dev) 1226576ca436SMark Brown devname = dev_name(dev); 1227576ca436SMark Brown 122869511a45SRajendra Nayak list_for_each_entry(r, ®ulator_list, list) 122969511a45SRajendra Nayak if (strcmp(rdev_get_name(r), supply) == 0) 123069511a45SRajendra Nayak return r; 123169511a45SRajendra Nayak 1232576ca436SMark Brown list_for_each_entry(map, ®ulator_map_list, list) { 1233576ca436SMark Brown /* If the mapping has a device set up it must match */ 1234576ca436SMark Brown if (map->dev_name && 1235576ca436SMark Brown (!devname || strcmp(map->dev_name, devname))) 1236576ca436SMark Brown continue; 1237576ca436SMark Brown 1238576ca436SMark Brown if (strcmp(map->supply, supply) == 0) 1239576ca436SMark Brown return map->regulator; 1240576ca436SMark Brown } 1241576ca436SMark Brown 1242576ca436SMark Brown 124369511a45SRajendra Nayak return NULL; 124469511a45SRajendra Nayak } 124569511a45SRajendra Nayak 12465ffbd136SMark Brown /* Internal regulator request function */ 12475ffbd136SMark Brown static struct regulator *_regulator_get(struct device *dev, const char *id, 12485ffbd136SMark Brown int exclusive) 1249414c70cbSLiam Girdwood { 1250414c70cbSLiam Girdwood struct regulator_dev *rdev; 125104bf3011SMark Brown struct regulator *regulator = ERR_PTR(-EPROBE_DEFER); 125240f9244fSMark Brown const char *devname = NULL; 12535ffbd136SMark Brown int ret; 1254414c70cbSLiam Girdwood 1255414c70cbSLiam Girdwood if (id == NULL) { 12565da84fd9SJoe Perches pr_err("get() with no identifier\n"); 1257414c70cbSLiam Girdwood return regulator; 1258414c70cbSLiam Girdwood } 1259414c70cbSLiam Girdwood 126040f9244fSMark Brown if (dev) 126140f9244fSMark Brown devname = dev_name(dev); 126240f9244fSMark Brown 1263414c70cbSLiam Girdwood mutex_lock(®ulator_list_mutex); 1264414c70cbSLiam Girdwood 12656d191a5fSMark Brown rdev = regulator_dev_lookup(dev, id, &ret); 126669511a45SRajendra Nayak if (rdev) 126769511a45SRajendra Nayak goto found; 126869511a45SRajendra Nayak 1269688fe99aSMark Brown if (board_wants_dummy_regulator) { 1270688fe99aSMark Brown rdev = dummy_regulator_rdev; 1271688fe99aSMark Brown goto found; 1272688fe99aSMark Brown } 1273688fe99aSMark Brown 127434abbd68SMark Brown #ifdef CONFIG_REGULATOR_DUMMY 127534abbd68SMark Brown if (!devname) 127634abbd68SMark Brown devname = "deviceless"; 127734abbd68SMark Brown 127834abbd68SMark Brown /* If the board didn't flag that it was fully constrained then 127934abbd68SMark Brown * substitute in a dummy regulator so consumers can continue. 128034abbd68SMark Brown */ 128134abbd68SMark Brown if (!has_full_constraints) { 12825da84fd9SJoe Perches pr_warn("%s supply %s not found, using dummy regulator\n", 128334abbd68SMark Brown devname, id); 128434abbd68SMark Brown rdev = dummy_regulator_rdev; 128534abbd68SMark Brown goto found; 128634abbd68SMark Brown } 128734abbd68SMark Brown #endif 128834abbd68SMark Brown 1289414c70cbSLiam Girdwood mutex_unlock(®ulator_list_mutex); 1290414c70cbSLiam Girdwood return regulator; 1291414c70cbSLiam Girdwood 1292414c70cbSLiam Girdwood found: 12935ffbd136SMark Brown if (rdev->exclusive) { 12945ffbd136SMark Brown regulator = ERR_PTR(-EPERM); 12955ffbd136SMark Brown goto out; 12965ffbd136SMark Brown } 12975ffbd136SMark Brown 12985ffbd136SMark Brown if (exclusive && rdev->open_count) { 12995ffbd136SMark Brown regulator = ERR_PTR(-EBUSY); 13005ffbd136SMark Brown goto out; 13015ffbd136SMark Brown } 13025ffbd136SMark Brown 1303a5766f11SLiam Girdwood if (!try_module_get(rdev->owner)) 1304a5766f11SLiam Girdwood goto out; 1305a5766f11SLiam Girdwood 1306414c70cbSLiam Girdwood regulator = create_regulator(rdev, dev, id); 1307414c70cbSLiam Girdwood if (regulator == NULL) { 1308414c70cbSLiam Girdwood regulator = ERR_PTR(-ENOMEM); 1309414c70cbSLiam Girdwood module_put(rdev->owner); 1310bcda4321SAxel Lin goto out; 1311414c70cbSLiam Girdwood } 1312414c70cbSLiam Girdwood 13135ffbd136SMark Brown rdev->open_count++; 13145ffbd136SMark Brown if (exclusive) { 13155ffbd136SMark Brown rdev->exclusive = 1; 13165ffbd136SMark Brown 13175ffbd136SMark Brown ret = _regulator_is_enabled(rdev); 13185ffbd136SMark Brown if (ret > 0) 13195ffbd136SMark Brown rdev->use_count = 1; 13205ffbd136SMark Brown else 13215ffbd136SMark Brown rdev->use_count = 0; 13225ffbd136SMark Brown } 13235ffbd136SMark Brown 1324a5766f11SLiam Girdwood out: 1325414c70cbSLiam Girdwood mutex_unlock(®ulator_list_mutex); 13265ffbd136SMark Brown 1327414c70cbSLiam Girdwood return regulator; 1328414c70cbSLiam Girdwood } 13295ffbd136SMark Brown 13305ffbd136SMark Brown /** 13315ffbd136SMark Brown * regulator_get - lookup and obtain a reference to a regulator. 13325ffbd136SMark Brown * @dev: device for regulator "consumer" 13335ffbd136SMark Brown * @id: Supply name or regulator ID. 13345ffbd136SMark Brown * 13355ffbd136SMark Brown * Returns a struct regulator corresponding to the regulator producer, 13365ffbd136SMark Brown * or IS_ERR() condition containing errno. 13375ffbd136SMark Brown * 13385ffbd136SMark Brown * Use of supply names configured via regulator_set_device_supply() is 13395ffbd136SMark Brown * strongly encouraged. It is recommended that the supply name used 13405ffbd136SMark Brown * should match the name used for the supply and/or the relevant 13415ffbd136SMark Brown * device pins in the datasheet. 13425ffbd136SMark Brown */ 13435ffbd136SMark Brown struct regulator *regulator_get(struct device *dev, const char *id) 13445ffbd136SMark Brown { 13455ffbd136SMark Brown return _regulator_get(dev, id, 0); 13465ffbd136SMark Brown } 1347414c70cbSLiam Girdwood EXPORT_SYMBOL_GPL(regulator_get); 1348414c70cbSLiam Girdwood 1349070b9079SStephen Boyd static void devm_regulator_release(struct device *dev, void *res) 1350070b9079SStephen Boyd { 1351070b9079SStephen Boyd regulator_put(*(struct regulator **)res); 1352070b9079SStephen Boyd } 1353070b9079SStephen Boyd 1354070b9079SStephen Boyd /** 1355070b9079SStephen Boyd * devm_regulator_get - Resource managed regulator_get() 1356070b9079SStephen Boyd * @dev: device for regulator "consumer" 1357070b9079SStephen Boyd * @id: Supply name or regulator ID. 1358070b9079SStephen Boyd * 1359070b9079SStephen Boyd * Managed regulator_get(). Regulators returned from this function are 1360070b9079SStephen Boyd * automatically regulator_put() on driver detach. See regulator_get() for more 1361070b9079SStephen Boyd * information. 1362070b9079SStephen Boyd */ 1363070b9079SStephen Boyd struct regulator *devm_regulator_get(struct device *dev, const char *id) 1364070b9079SStephen Boyd { 1365070b9079SStephen Boyd struct regulator **ptr, *regulator; 1366070b9079SStephen Boyd 1367070b9079SStephen Boyd ptr = devres_alloc(devm_regulator_release, sizeof(*ptr), GFP_KERNEL); 1368070b9079SStephen Boyd if (!ptr) 1369070b9079SStephen Boyd return ERR_PTR(-ENOMEM); 1370070b9079SStephen Boyd 1371070b9079SStephen Boyd regulator = regulator_get(dev, id); 1372070b9079SStephen Boyd if (!IS_ERR(regulator)) { 1373070b9079SStephen Boyd *ptr = regulator; 1374070b9079SStephen Boyd devres_add(dev, ptr); 1375070b9079SStephen Boyd } else { 1376070b9079SStephen Boyd devres_free(ptr); 1377070b9079SStephen Boyd } 1378070b9079SStephen Boyd 1379070b9079SStephen Boyd return regulator; 1380070b9079SStephen Boyd } 1381070b9079SStephen Boyd EXPORT_SYMBOL_GPL(devm_regulator_get); 1382070b9079SStephen Boyd 1383414c70cbSLiam Girdwood /** 13845ffbd136SMark Brown * regulator_get_exclusive - obtain exclusive access to a regulator. 13855ffbd136SMark Brown * @dev: device for regulator "consumer" 13865ffbd136SMark Brown * @id: Supply name or regulator ID. 13875ffbd136SMark Brown * 13885ffbd136SMark Brown * Returns a struct regulator corresponding to the regulator producer, 13895ffbd136SMark Brown * or IS_ERR() condition containing errno. Other consumers will be 13905ffbd136SMark Brown * unable to obtain this reference is held and the use count for the 13915ffbd136SMark Brown * regulator will be initialised to reflect the current state of the 13925ffbd136SMark Brown * regulator. 13935ffbd136SMark Brown * 13945ffbd136SMark Brown * This is intended for use by consumers which cannot tolerate shared 13955ffbd136SMark Brown * use of the regulator such as those which need to force the 13965ffbd136SMark Brown * regulator off for correct operation of the hardware they are 13975ffbd136SMark Brown * controlling. 13985ffbd136SMark Brown * 13995ffbd136SMark Brown * Use of supply names configured via regulator_set_device_supply() is 14005ffbd136SMark Brown * strongly encouraged. It is recommended that the supply name used 14015ffbd136SMark Brown * should match the name used for the supply and/or the relevant 14025ffbd136SMark Brown * device pins in the datasheet. 14035ffbd136SMark Brown */ 14045ffbd136SMark Brown struct regulator *regulator_get_exclusive(struct device *dev, const char *id) 14055ffbd136SMark Brown { 14065ffbd136SMark Brown return _regulator_get(dev, id, 1); 14075ffbd136SMark Brown } 14085ffbd136SMark Brown EXPORT_SYMBOL_GPL(regulator_get_exclusive); 14095ffbd136SMark Brown 14105ffbd136SMark Brown /** 1411414c70cbSLiam Girdwood * regulator_put - "free" the regulator source 1412414c70cbSLiam Girdwood * @regulator: regulator source 1413414c70cbSLiam Girdwood * 1414414c70cbSLiam Girdwood * Note: drivers must ensure that all regulator_enable calls made on this 1415414c70cbSLiam Girdwood * regulator source are balanced by regulator_disable calls prior to calling 1416414c70cbSLiam Girdwood * this function. 1417414c70cbSLiam Girdwood */ 1418414c70cbSLiam Girdwood void regulator_put(struct regulator *regulator) 1419414c70cbSLiam Girdwood { 1420414c70cbSLiam Girdwood struct regulator_dev *rdev; 1421414c70cbSLiam Girdwood 1422414c70cbSLiam Girdwood if (regulator == NULL || IS_ERR(regulator)) 1423414c70cbSLiam Girdwood return; 1424414c70cbSLiam Girdwood 1425414c70cbSLiam Girdwood mutex_lock(®ulator_list_mutex); 1426414c70cbSLiam Girdwood rdev = regulator->rdev; 1427414c70cbSLiam Girdwood 14285de70519SMark Brown debugfs_remove_recursive(regulator->debugfs); 14295de70519SMark Brown 1430414c70cbSLiam Girdwood /* remove any sysfs entries */ 1431414c70cbSLiam Girdwood if (regulator->dev) { 1432414c70cbSLiam Girdwood sysfs_remove_link(&rdev->dev.kobj, regulator->supply_name); 1433414c70cbSLiam Girdwood device_remove_file(regulator->dev, ®ulator->dev_attr); 1434414c70cbSLiam Girdwood kfree(regulator->dev_attr.attr.name); 1435414c70cbSLiam Girdwood } 14365de70519SMark Brown kfree(regulator->supply_name); 1437414c70cbSLiam Girdwood list_del(®ulator->list); 1438414c70cbSLiam Girdwood kfree(regulator); 1439414c70cbSLiam Girdwood 14405ffbd136SMark Brown rdev->open_count--; 14415ffbd136SMark Brown rdev->exclusive = 0; 14425ffbd136SMark Brown 1443414c70cbSLiam Girdwood module_put(rdev->owner); 1444414c70cbSLiam Girdwood mutex_unlock(®ulator_list_mutex); 1445414c70cbSLiam Girdwood } 1446414c70cbSLiam Girdwood EXPORT_SYMBOL_GPL(regulator_put); 1447414c70cbSLiam Girdwood 1448d5ad34f7SMark Brown static int devm_regulator_match(struct device *dev, void *res, void *data) 1449d5ad34f7SMark Brown { 1450d5ad34f7SMark Brown struct regulator **r = res; 1451d5ad34f7SMark Brown if (!r || !*r) { 1452d5ad34f7SMark Brown WARN_ON(!r || !*r); 1453d5ad34f7SMark Brown return 0; 1454d5ad34f7SMark Brown } 1455d5ad34f7SMark Brown return *r == data; 1456d5ad34f7SMark Brown } 1457d5ad34f7SMark Brown 1458d5ad34f7SMark Brown /** 1459d5ad34f7SMark Brown * devm_regulator_put - Resource managed regulator_put() 1460d5ad34f7SMark Brown * @regulator: regulator to free 1461d5ad34f7SMark Brown * 1462d5ad34f7SMark Brown * Deallocate a regulator allocated with devm_regulator_get(). Normally 1463d5ad34f7SMark Brown * this function will not need to be called and the resource management 1464d5ad34f7SMark Brown * code will ensure that the resource is freed. 1465d5ad34f7SMark Brown */ 1466d5ad34f7SMark Brown void devm_regulator_put(struct regulator *regulator) 1467d5ad34f7SMark Brown { 1468d5ad34f7SMark Brown int rc; 1469d5ad34f7SMark Brown 1470361ff501SMark Brown rc = devres_release(regulator->dev, devm_regulator_release, 1471d5ad34f7SMark Brown devm_regulator_match, regulator); 1472968c2c17SMark Brown if (rc == 0) 1473968c2c17SMark Brown regulator_put(regulator); 1474968c2c17SMark Brown else 1475d5ad34f7SMark Brown WARN_ON(rc); 1476d5ad34f7SMark Brown } 1477d5ad34f7SMark Brown EXPORT_SYMBOL_GPL(devm_regulator_put); 1478d5ad34f7SMark Brown 1479414c70cbSLiam Girdwood /* locks held by regulator_enable() */ 1480414c70cbSLiam Girdwood static int _regulator_enable(struct regulator_dev *rdev) 1481414c70cbSLiam Girdwood { 148231aae2beSMark Brown int ret, delay; 1483414c70cbSLiam Girdwood 1484414c70cbSLiam Girdwood /* check voltage and requested load before enabling */ 1485414c70cbSLiam Girdwood if (rdev->constraints && 14869a2372faSMark Brown (rdev->constraints->valid_ops_mask & REGULATOR_CHANGE_DRMS)) 1487414c70cbSLiam Girdwood drms_uA_update(rdev); 1488414c70cbSLiam Girdwood 14899a2372faSMark Brown if (rdev->use_count == 0) { 14909a2372faSMark Brown /* The regulator may on if it's not switchable or left on */ 14919a2372faSMark Brown ret = _regulator_is_enabled(rdev); 14929a2372faSMark Brown if (ret == -EINVAL || ret == 0) { 14939a2372faSMark Brown if (!_regulator_can_change_status(rdev)) 14949a2372faSMark Brown return -EPERM; 14959a2372faSMark Brown 149631aae2beSMark Brown if (!rdev->desc->ops->enable) 149731aae2beSMark Brown return -EINVAL; 149831aae2beSMark Brown 149931aae2beSMark Brown /* Query before enabling in case configuration 150025985edcSLucas De Marchi * dependent. */ 150131aae2beSMark Brown ret = _regulator_get_enable_time(rdev); 150231aae2beSMark Brown if (ret >= 0) { 150331aae2beSMark Brown delay = ret; 150431aae2beSMark Brown } else { 15055da84fd9SJoe Perches rdev_warn(rdev, "enable_time() failed: %d\n", 150631aae2beSMark Brown ret); 150731aae2beSMark Brown delay = 0; 150831aae2beSMark Brown } 150931aae2beSMark Brown 151002fa3ec0SMark Brown trace_regulator_enable(rdev_get_name(rdev)); 151102fa3ec0SMark Brown 151231aae2beSMark Brown /* Allow the regulator to ramp; it would be useful 151331aae2beSMark Brown * to extend this for bulk operations so that the 151431aae2beSMark Brown * regulators can ramp together. */ 1515414c70cbSLiam Girdwood ret = rdev->desc->ops->enable(rdev); 15169a2372faSMark Brown if (ret < 0) 15179a2372faSMark Brown return ret; 151831aae2beSMark Brown 151902fa3ec0SMark Brown trace_regulator_enable_delay(rdev_get_name(rdev)); 152002fa3ec0SMark Brown 1521e36c1df8SAxel Lin if (delay >= 1000) { 152231aae2beSMark Brown mdelay(delay / 1000); 1523e36c1df8SAxel Lin udelay(delay % 1000); 1524e36c1df8SAxel Lin } else if (delay) { 152531aae2beSMark Brown udelay(delay); 1526e36c1df8SAxel Lin } 152731aae2beSMark Brown 152802fa3ec0SMark Brown trace_regulator_enable_complete(rdev_get_name(rdev)); 152902fa3ec0SMark Brown 1530a7433cffSLinus Walleij } else if (ret < 0) { 15315da84fd9SJoe Perches rdev_err(rdev, "is_enabled() failed: %d\n", ret); 1532414c70cbSLiam Girdwood return ret; 1533414c70cbSLiam Girdwood } 1534a7433cffSLinus Walleij /* Fallthrough on positive return values - already enabled */ 1535414c70cbSLiam Girdwood } 1536414c70cbSLiam Girdwood 15379a2372faSMark Brown rdev->use_count++; 15389a2372faSMark Brown 15399a2372faSMark Brown return 0; 1540414c70cbSLiam Girdwood } 1541414c70cbSLiam Girdwood 1542414c70cbSLiam Girdwood /** 1543414c70cbSLiam Girdwood * regulator_enable - enable regulator output 1544414c70cbSLiam Girdwood * @regulator: regulator source 1545414c70cbSLiam Girdwood * 1546cf7bbcdfSMark Brown * Request that the regulator be enabled with the regulator output at 1547cf7bbcdfSMark Brown * the predefined voltage or current value. Calls to regulator_enable() 1548cf7bbcdfSMark Brown * must be balanced with calls to regulator_disable(). 1549cf7bbcdfSMark Brown * 1550414c70cbSLiam Girdwood * NOTE: the output value can be set by other drivers, boot loader or may be 1551cf7bbcdfSMark Brown * hardwired in the regulator. 1552414c70cbSLiam Girdwood */ 1553414c70cbSLiam Girdwood int regulator_enable(struct regulator *regulator) 1554414c70cbSLiam Girdwood { 1555412aec61SDavid Brownell struct regulator_dev *rdev = regulator->rdev; 1556412aec61SDavid Brownell int ret = 0; 1557414c70cbSLiam Girdwood 15586492bc1bSMark Brown if (regulator->always_on) 15596492bc1bSMark Brown return 0; 15606492bc1bSMark Brown 15613801b86aSMark Brown if (rdev->supply) { 15623801b86aSMark Brown ret = regulator_enable(rdev->supply); 15633801b86aSMark Brown if (ret != 0) 15643801b86aSMark Brown return ret; 15653801b86aSMark Brown } 15663801b86aSMark Brown 1567412aec61SDavid Brownell mutex_lock(&rdev->mutex); 1568412aec61SDavid Brownell ret = _regulator_enable(rdev); 1569412aec61SDavid Brownell mutex_unlock(&rdev->mutex); 15703801b86aSMark Brown 1571d1685e4eSHeiko Stübner if (ret != 0 && rdev->supply) 15723801b86aSMark Brown regulator_disable(rdev->supply); 15733801b86aSMark Brown 1574414c70cbSLiam Girdwood return ret; 1575414c70cbSLiam Girdwood } 1576414c70cbSLiam Girdwood EXPORT_SYMBOL_GPL(regulator_enable); 1577414c70cbSLiam Girdwood 1578414c70cbSLiam Girdwood /* locks held by regulator_disable() */ 15793801b86aSMark Brown static int _regulator_disable(struct regulator_dev *rdev) 1580414c70cbSLiam Girdwood { 1581414c70cbSLiam Girdwood int ret = 0; 1582414c70cbSLiam Girdwood 1583cd94b505SDavid Brownell if (WARN(rdev->use_count <= 0, 158443e7ee33SJoe Perches "unbalanced disables for %s\n", rdev_get_name(rdev))) 1585cd94b505SDavid Brownell return -EIO; 1586cd94b505SDavid Brownell 1587414c70cbSLiam Girdwood /* are we the last user and permitted to disable ? */ 158860ef66fcSMark Brown if (rdev->use_count == 1 && 158960ef66fcSMark Brown (rdev->constraints && !rdev->constraints->always_on)) { 1590414c70cbSLiam Girdwood 1591414c70cbSLiam Girdwood /* we are last user */ 15929a2372faSMark Brown if (_regulator_can_change_status(rdev) && 15939a2372faSMark Brown rdev->desc->ops->disable) { 159402fa3ec0SMark Brown trace_regulator_disable(rdev_get_name(rdev)); 159502fa3ec0SMark Brown 1596414c70cbSLiam Girdwood ret = rdev->desc->ops->disable(rdev); 1597414c70cbSLiam Girdwood if (ret < 0) { 15985da84fd9SJoe Perches rdev_err(rdev, "failed to disable\n"); 1599414c70cbSLiam Girdwood return ret; 1600414c70cbSLiam Girdwood } 160184b68263SMark Brown 160202fa3ec0SMark Brown trace_regulator_disable_complete(rdev_get_name(rdev)); 160302fa3ec0SMark Brown 160484b68263SMark Brown _notifier_call_chain(rdev, REGULATOR_EVENT_DISABLE, 160584b68263SMark Brown NULL); 1606414c70cbSLiam Girdwood } 1607414c70cbSLiam Girdwood 1608414c70cbSLiam Girdwood rdev->use_count = 0; 1609414c70cbSLiam Girdwood } else if (rdev->use_count > 1) { 1610414c70cbSLiam Girdwood 1611414c70cbSLiam Girdwood if (rdev->constraints && 1612414c70cbSLiam Girdwood (rdev->constraints->valid_ops_mask & 1613414c70cbSLiam Girdwood REGULATOR_CHANGE_DRMS)) 1614414c70cbSLiam Girdwood drms_uA_update(rdev); 1615414c70cbSLiam Girdwood 1616414c70cbSLiam Girdwood rdev->use_count--; 1617414c70cbSLiam Girdwood } 16183801b86aSMark Brown 1619414c70cbSLiam Girdwood return ret; 1620414c70cbSLiam Girdwood } 1621414c70cbSLiam Girdwood 1622414c70cbSLiam Girdwood /** 1623414c70cbSLiam Girdwood * regulator_disable - disable regulator output 1624414c70cbSLiam Girdwood * @regulator: regulator source 1625414c70cbSLiam Girdwood * 1626cf7bbcdfSMark Brown * Disable the regulator output voltage or current. Calls to 1627cf7bbcdfSMark Brown * regulator_enable() must be balanced with calls to 1628cf7bbcdfSMark Brown * regulator_disable(). 162969279fb9SMark Brown * 1630414c70cbSLiam Girdwood * NOTE: this will only disable the regulator output if no other consumer 1631cf7bbcdfSMark Brown * devices have it enabled, the regulator device supports disabling and 1632cf7bbcdfSMark Brown * machine constraints permit this operation. 1633414c70cbSLiam Girdwood */ 1634414c70cbSLiam Girdwood int regulator_disable(struct regulator *regulator) 1635414c70cbSLiam Girdwood { 1636412aec61SDavid Brownell struct regulator_dev *rdev = regulator->rdev; 1637412aec61SDavid Brownell int ret = 0; 1638414c70cbSLiam Girdwood 16396492bc1bSMark Brown if (regulator->always_on) 16406492bc1bSMark Brown return 0; 16416492bc1bSMark Brown 1642412aec61SDavid Brownell mutex_lock(&rdev->mutex); 16433801b86aSMark Brown ret = _regulator_disable(rdev); 1644412aec61SDavid Brownell mutex_unlock(&rdev->mutex); 16458cbf811dSJeffrey Carlyle 16463801b86aSMark Brown if (ret == 0 && rdev->supply) 16473801b86aSMark Brown regulator_disable(rdev->supply); 16488cbf811dSJeffrey Carlyle 1649414c70cbSLiam Girdwood return ret; 1650414c70cbSLiam Girdwood } 1651414c70cbSLiam Girdwood EXPORT_SYMBOL_GPL(regulator_disable); 1652414c70cbSLiam Girdwood 1653414c70cbSLiam Girdwood /* locks held by regulator_force_disable() */ 16543801b86aSMark Brown static int _regulator_force_disable(struct regulator_dev *rdev) 1655414c70cbSLiam Girdwood { 1656414c70cbSLiam Girdwood int ret = 0; 1657414c70cbSLiam Girdwood 1658414c70cbSLiam Girdwood /* force disable */ 1659414c70cbSLiam Girdwood if (rdev->desc->ops->disable) { 1660414c70cbSLiam Girdwood /* ah well, who wants to live forever... */ 1661414c70cbSLiam Girdwood ret = rdev->desc->ops->disable(rdev); 1662414c70cbSLiam Girdwood if (ret < 0) { 16635da84fd9SJoe Perches rdev_err(rdev, "failed to force disable\n"); 1664414c70cbSLiam Girdwood return ret; 1665414c70cbSLiam Girdwood } 1666414c70cbSLiam Girdwood /* notify other consumers that power has been forced off */ 166784b68263SMark Brown _notifier_call_chain(rdev, REGULATOR_EVENT_FORCE_DISABLE | 166884b68263SMark Brown REGULATOR_EVENT_DISABLE, NULL); 1669414c70cbSLiam Girdwood } 1670414c70cbSLiam Girdwood 1671414c70cbSLiam Girdwood return ret; 1672414c70cbSLiam Girdwood } 1673414c70cbSLiam Girdwood 1674414c70cbSLiam Girdwood /** 1675414c70cbSLiam Girdwood * regulator_force_disable - force disable regulator output 1676414c70cbSLiam Girdwood * @regulator: regulator source 1677414c70cbSLiam Girdwood * 1678414c70cbSLiam Girdwood * Forcibly disable the regulator output voltage or current. 1679414c70cbSLiam Girdwood * NOTE: this *will* disable the regulator output even if other consumer 1680414c70cbSLiam Girdwood * devices have it enabled. This should be used for situations when device 1681414c70cbSLiam Girdwood * damage will likely occur if the regulator is not disabled (e.g. over temp). 1682414c70cbSLiam Girdwood */ 1683414c70cbSLiam Girdwood int regulator_force_disable(struct regulator *regulator) 1684414c70cbSLiam Girdwood { 168582d15839SMark Brown struct regulator_dev *rdev = regulator->rdev; 1686414c70cbSLiam Girdwood int ret; 1687414c70cbSLiam Girdwood 168882d15839SMark Brown mutex_lock(&rdev->mutex); 1689414c70cbSLiam Girdwood regulator->uA_load = 0; 16903801b86aSMark Brown ret = _regulator_force_disable(regulator->rdev); 169182d15839SMark Brown mutex_unlock(&rdev->mutex); 16928cbf811dSJeffrey Carlyle 16933801b86aSMark Brown if (rdev->supply) 16943801b86aSMark Brown while (rdev->open_count--) 16953801b86aSMark Brown regulator_disable(rdev->supply); 16968cbf811dSJeffrey Carlyle 1697414c70cbSLiam Girdwood return ret; 1698414c70cbSLiam Girdwood } 1699414c70cbSLiam Girdwood EXPORT_SYMBOL_GPL(regulator_force_disable); 1700414c70cbSLiam Girdwood 1701da07ecd9SMark Brown static void regulator_disable_work(struct work_struct *work) 1702da07ecd9SMark Brown { 1703da07ecd9SMark Brown struct regulator_dev *rdev = container_of(work, struct regulator_dev, 1704da07ecd9SMark Brown disable_work.work); 1705da07ecd9SMark Brown int count, i, ret; 1706da07ecd9SMark Brown 1707da07ecd9SMark Brown mutex_lock(&rdev->mutex); 1708da07ecd9SMark Brown 1709da07ecd9SMark Brown BUG_ON(!rdev->deferred_disables); 1710da07ecd9SMark Brown 1711da07ecd9SMark Brown count = rdev->deferred_disables; 1712da07ecd9SMark Brown rdev->deferred_disables = 0; 1713da07ecd9SMark Brown 1714da07ecd9SMark Brown for (i = 0; i < count; i++) { 1715da07ecd9SMark Brown ret = _regulator_disable(rdev); 1716da07ecd9SMark Brown if (ret != 0) 1717da07ecd9SMark Brown rdev_err(rdev, "Deferred disable failed: %d\n", ret); 1718da07ecd9SMark Brown } 1719da07ecd9SMark Brown 1720da07ecd9SMark Brown mutex_unlock(&rdev->mutex); 1721da07ecd9SMark Brown 1722da07ecd9SMark Brown if (rdev->supply) { 1723da07ecd9SMark Brown for (i = 0; i < count; i++) { 1724da07ecd9SMark Brown ret = regulator_disable(rdev->supply); 1725da07ecd9SMark Brown if (ret != 0) { 1726da07ecd9SMark Brown rdev_err(rdev, 1727da07ecd9SMark Brown "Supply disable failed: %d\n", ret); 1728da07ecd9SMark Brown } 1729da07ecd9SMark Brown } 1730da07ecd9SMark Brown } 1731da07ecd9SMark Brown } 1732da07ecd9SMark Brown 1733da07ecd9SMark Brown /** 1734da07ecd9SMark Brown * regulator_disable_deferred - disable regulator output with delay 1735da07ecd9SMark Brown * @regulator: regulator source 1736da07ecd9SMark Brown * @ms: miliseconds until the regulator is disabled 1737da07ecd9SMark Brown * 1738da07ecd9SMark Brown * Execute regulator_disable() on the regulator after a delay. This 1739da07ecd9SMark Brown * is intended for use with devices that require some time to quiesce. 1740da07ecd9SMark Brown * 1741da07ecd9SMark Brown * NOTE: this will only disable the regulator output if no other consumer 1742da07ecd9SMark Brown * devices have it enabled, the regulator device supports disabling and 1743da07ecd9SMark Brown * machine constraints permit this operation. 1744da07ecd9SMark Brown */ 1745da07ecd9SMark Brown int regulator_disable_deferred(struct regulator *regulator, int ms) 1746da07ecd9SMark Brown { 1747da07ecd9SMark Brown struct regulator_dev *rdev = regulator->rdev; 1748aa59802dSMark Brown int ret; 1749da07ecd9SMark Brown 17506492bc1bSMark Brown if (regulator->always_on) 17516492bc1bSMark Brown return 0; 17526492bc1bSMark Brown 1753da07ecd9SMark Brown mutex_lock(&rdev->mutex); 1754da07ecd9SMark Brown rdev->deferred_disables++; 1755da07ecd9SMark Brown mutex_unlock(&rdev->mutex); 1756da07ecd9SMark Brown 1757aa59802dSMark Brown ret = schedule_delayed_work(&rdev->disable_work, 1758da07ecd9SMark Brown msecs_to_jiffies(ms)); 1759aa59802dSMark Brown if (ret < 0) 1760aa59802dSMark Brown return ret; 1761aa59802dSMark Brown else 1762aa59802dSMark Brown return 0; 1763da07ecd9SMark Brown } 1764da07ecd9SMark Brown EXPORT_SYMBOL_GPL(regulator_disable_deferred); 1765da07ecd9SMark Brown 1766cd6dffb4SMark Brown /** 1767cd6dffb4SMark Brown * regulator_is_enabled_regmap - standard is_enabled() for regmap users 1768cd6dffb4SMark Brown * 1769cd6dffb4SMark Brown * @rdev: regulator to operate on 1770cd6dffb4SMark Brown * 1771cd6dffb4SMark Brown * Regulators that use regmap for their register I/O can set the 1772cd6dffb4SMark Brown * enable_reg and enable_mask fields in their descriptor and then use 1773cd6dffb4SMark Brown * this as their is_enabled operation, saving some code. 1774cd6dffb4SMark Brown */ 1775cd6dffb4SMark Brown int regulator_is_enabled_regmap(struct regulator_dev *rdev) 1776cd6dffb4SMark Brown { 1777cd6dffb4SMark Brown unsigned int val; 1778cd6dffb4SMark Brown int ret; 1779cd6dffb4SMark Brown 1780cd6dffb4SMark Brown ret = regmap_read(rdev->regmap, rdev->desc->enable_reg, &val); 1781cd6dffb4SMark Brown if (ret != 0) 1782cd6dffb4SMark Brown return ret; 1783cd6dffb4SMark Brown 1784cd6dffb4SMark Brown return (val & rdev->desc->enable_mask) != 0; 1785cd6dffb4SMark Brown } 1786cd6dffb4SMark Brown EXPORT_SYMBOL_GPL(regulator_is_enabled_regmap); 1787cd6dffb4SMark Brown 1788cd6dffb4SMark Brown /** 1789cd6dffb4SMark Brown * regulator_enable_regmap - standard enable() for regmap users 1790cd6dffb4SMark Brown * 1791cd6dffb4SMark Brown * @rdev: regulator to operate on 1792cd6dffb4SMark Brown * 1793cd6dffb4SMark Brown * Regulators that use regmap for their register I/O can set the 1794cd6dffb4SMark Brown * enable_reg and enable_mask fields in their descriptor and then use 1795cd6dffb4SMark Brown * this as their enable() operation, saving some code. 1796cd6dffb4SMark Brown */ 1797cd6dffb4SMark Brown int regulator_enable_regmap(struct regulator_dev *rdev) 1798cd6dffb4SMark Brown { 1799cd6dffb4SMark Brown return regmap_update_bits(rdev->regmap, rdev->desc->enable_reg, 1800cd6dffb4SMark Brown rdev->desc->enable_mask, 1801cd6dffb4SMark Brown rdev->desc->enable_mask); 1802cd6dffb4SMark Brown } 1803cd6dffb4SMark Brown EXPORT_SYMBOL_GPL(regulator_enable_regmap); 1804cd6dffb4SMark Brown 1805cd6dffb4SMark Brown /** 1806cd6dffb4SMark Brown * regulator_disable_regmap - standard disable() for regmap users 1807cd6dffb4SMark Brown * 1808cd6dffb4SMark Brown * @rdev: regulator to operate on 1809cd6dffb4SMark Brown * 1810cd6dffb4SMark Brown * Regulators that use regmap for their register I/O can set the 1811cd6dffb4SMark Brown * enable_reg and enable_mask fields in their descriptor and then use 1812cd6dffb4SMark Brown * this as their disable() operation, saving some code. 1813cd6dffb4SMark Brown */ 1814cd6dffb4SMark Brown int regulator_disable_regmap(struct regulator_dev *rdev) 1815cd6dffb4SMark Brown { 1816cd6dffb4SMark Brown return regmap_update_bits(rdev->regmap, rdev->desc->enable_reg, 1817cd6dffb4SMark Brown rdev->desc->enable_mask, 0); 1818cd6dffb4SMark Brown } 1819cd6dffb4SMark Brown EXPORT_SYMBOL_GPL(regulator_disable_regmap); 1820cd6dffb4SMark Brown 1821414c70cbSLiam Girdwood static int _regulator_is_enabled(struct regulator_dev *rdev) 1822414c70cbSLiam Girdwood { 18239a7f6a4cSMark Brown /* If we don't know then assume that the regulator is always on */ 18249332546fSMark Brown if (!rdev->desc->ops->is_enabled) 18259a7f6a4cSMark Brown return 1; 1826414c70cbSLiam Girdwood 18279332546fSMark Brown return rdev->desc->ops->is_enabled(rdev); 1828414c70cbSLiam Girdwood } 1829414c70cbSLiam Girdwood 1830414c70cbSLiam Girdwood /** 1831414c70cbSLiam Girdwood * regulator_is_enabled - is the regulator output enabled 1832414c70cbSLiam Girdwood * @regulator: regulator source 1833414c70cbSLiam Girdwood * 1834412aec61SDavid Brownell * Returns positive if the regulator driver backing the source/client 1835412aec61SDavid Brownell * has requested that the device be enabled, zero if it hasn't, else a 1836412aec61SDavid Brownell * negative errno code. 1837412aec61SDavid Brownell * 1838412aec61SDavid Brownell * Note that the device backing this regulator handle can have multiple 1839412aec61SDavid Brownell * users, so it might be enabled even if regulator_enable() was never 1840412aec61SDavid Brownell * called for this particular source. 1841414c70cbSLiam Girdwood */ 1842414c70cbSLiam Girdwood int regulator_is_enabled(struct regulator *regulator) 1843414c70cbSLiam Girdwood { 18449332546fSMark Brown int ret; 18459332546fSMark Brown 18466492bc1bSMark Brown if (regulator->always_on) 18476492bc1bSMark Brown return 1; 18486492bc1bSMark Brown 18499332546fSMark Brown mutex_lock(®ulator->rdev->mutex); 18509332546fSMark Brown ret = _regulator_is_enabled(regulator->rdev); 18519332546fSMark Brown mutex_unlock(®ulator->rdev->mutex); 18529332546fSMark Brown 18539332546fSMark Brown return ret; 1854414c70cbSLiam Girdwood } 1855414c70cbSLiam Girdwood EXPORT_SYMBOL_GPL(regulator_is_enabled); 1856414c70cbSLiam Girdwood 1857414c70cbSLiam Girdwood /** 18584367cfdcSDavid Brownell * regulator_count_voltages - count regulator_list_voltage() selectors 18594367cfdcSDavid Brownell * @regulator: regulator source 18604367cfdcSDavid Brownell * 18614367cfdcSDavid Brownell * Returns number of selectors, or negative errno. Selectors are 18624367cfdcSDavid Brownell * numbered starting at zero, and typically correspond to bitfields 18634367cfdcSDavid Brownell * in hardware registers. 18644367cfdcSDavid Brownell */ 18654367cfdcSDavid Brownell int regulator_count_voltages(struct regulator *regulator) 18664367cfdcSDavid Brownell { 18674367cfdcSDavid Brownell struct regulator_dev *rdev = regulator->rdev; 18684367cfdcSDavid Brownell 18694367cfdcSDavid Brownell return rdev->desc->n_voltages ? : -EINVAL; 18704367cfdcSDavid Brownell } 18714367cfdcSDavid Brownell EXPORT_SYMBOL_GPL(regulator_count_voltages); 18724367cfdcSDavid Brownell 18734367cfdcSDavid Brownell /** 1874bca7bbffSMark Brown * regulator_list_voltage_linear - List voltages with simple calculation 1875bca7bbffSMark Brown * 1876bca7bbffSMark Brown * @rdev: Regulator device 1877bca7bbffSMark Brown * @selector: Selector to convert into a voltage 1878bca7bbffSMark Brown * 1879bca7bbffSMark Brown * Regulators with a simple linear mapping between voltages and 1880bca7bbffSMark Brown * selectors can set min_uV and uV_step in the regulator descriptor 1881bca7bbffSMark Brown * and then use this function as their list_voltage() operation, 1882bca7bbffSMark Brown */ 1883bca7bbffSMark Brown int regulator_list_voltage_linear(struct regulator_dev *rdev, 1884bca7bbffSMark Brown unsigned int selector) 1885bca7bbffSMark Brown { 1886bca7bbffSMark Brown if (selector >= rdev->desc->n_voltages) 1887bca7bbffSMark Brown return -EINVAL; 1888bca7bbffSMark Brown 1889bca7bbffSMark Brown return rdev->desc->min_uV + (rdev->desc->uV_step * selector); 1890bca7bbffSMark Brown } 1891bca7bbffSMark Brown EXPORT_SYMBOL_GPL(regulator_list_voltage_linear); 1892bca7bbffSMark Brown 1893bca7bbffSMark Brown /** 1894cffc9592SAxel Lin * regulator_list_voltage_table - List voltages with table based mapping 1895cffc9592SAxel Lin * 1896cffc9592SAxel Lin * @rdev: Regulator device 1897cffc9592SAxel Lin * @selector: Selector to convert into a voltage 1898cffc9592SAxel Lin * 1899cffc9592SAxel Lin * Regulators with table based mapping between voltages and 1900cffc9592SAxel Lin * selectors can set volt_table in the regulator descriptor 1901cffc9592SAxel Lin * and then use this function as their list_voltage() operation. 1902cffc9592SAxel Lin */ 1903cffc9592SAxel Lin int regulator_list_voltage_table(struct regulator_dev *rdev, 1904cffc9592SAxel Lin unsigned int selector) 1905cffc9592SAxel Lin { 1906cffc9592SAxel Lin if (!rdev->desc->volt_table) { 1907cffc9592SAxel Lin BUG_ON(!rdev->desc->volt_table); 1908cffc9592SAxel Lin return -EINVAL; 1909cffc9592SAxel Lin } 1910cffc9592SAxel Lin 1911cffc9592SAxel Lin if (selector >= rdev->desc->n_voltages) 1912cffc9592SAxel Lin return -EINVAL; 1913cffc9592SAxel Lin 1914cffc9592SAxel Lin return rdev->desc->volt_table[selector]; 1915cffc9592SAxel Lin } 1916cffc9592SAxel Lin EXPORT_SYMBOL_GPL(regulator_list_voltage_table); 1917cffc9592SAxel Lin 1918cffc9592SAxel Lin /** 19194367cfdcSDavid Brownell * regulator_list_voltage - enumerate supported voltages 19204367cfdcSDavid Brownell * @regulator: regulator source 19214367cfdcSDavid Brownell * @selector: identify voltage to list 19224367cfdcSDavid Brownell * Context: can sleep 19234367cfdcSDavid Brownell * 19244367cfdcSDavid Brownell * Returns a voltage that can be passed to @regulator_set_voltage(), 192588393161SThomas Weber * zero if this selector code can't be used on this system, or a 19264367cfdcSDavid Brownell * negative errno. 19274367cfdcSDavid Brownell */ 19284367cfdcSDavid Brownell int regulator_list_voltage(struct regulator *regulator, unsigned selector) 19294367cfdcSDavid Brownell { 19304367cfdcSDavid Brownell struct regulator_dev *rdev = regulator->rdev; 19314367cfdcSDavid Brownell struct regulator_ops *ops = rdev->desc->ops; 19324367cfdcSDavid Brownell int ret; 19334367cfdcSDavid Brownell 19344367cfdcSDavid Brownell if (!ops->list_voltage || selector >= rdev->desc->n_voltages) 19354367cfdcSDavid Brownell return -EINVAL; 19364367cfdcSDavid Brownell 19374367cfdcSDavid Brownell mutex_lock(&rdev->mutex); 19384367cfdcSDavid Brownell ret = ops->list_voltage(rdev, selector); 19394367cfdcSDavid Brownell mutex_unlock(&rdev->mutex); 19404367cfdcSDavid Brownell 19414367cfdcSDavid Brownell if (ret > 0) { 19424367cfdcSDavid Brownell if (ret < rdev->constraints->min_uV) 19434367cfdcSDavid Brownell ret = 0; 19444367cfdcSDavid Brownell else if (ret > rdev->constraints->max_uV) 19454367cfdcSDavid Brownell ret = 0; 19464367cfdcSDavid Brownell } 19474367cfdcSDavid Brownell 19484367cfdcSDavid Brownell return ret; 19494367cfdcSDavid Brownell } 19504367cfdcSDavid Brownell EXPORT_SYMBOL_GPL(regulator_list_voltage); 19514367cfdcSDavid Brownell 19524367cfdcSDavid Brownell /** 1953a7a1ad90SMark Brown * regulator_is_supported_voltage - check if a voltage range can be supported 1954a7a1ad90SMark Brown * 1955a7a1ad90SMark Brown * @regulator: Regulator to check. 1956a7a1ad90SMark Brown * @min_uV: Minimum required voltage in uV. 1957a7a1ad90SMark Brown * @max_uV: Maximum required voltage in uV. 1958a7a1ad90SMark Brown * 1959a7a1ad90SMark Brown * Returns a boolean or a negative error code. 1960a7a1ad90SMark Brown */ 1961a7a1ad90SMark Brown int regulator_is_supported_voltage(struct regulator *regulator, 1962a7a1ad90SMark Brown int min_uV, int max_uV) 1963a7a1ad90SMark Brown { 1964a7a1ad90SMark Brown int i, voltages, ret; 1965a7a1ad90SMark Brown 1966a7a1ad90SMark Brown ret = regulator_count_voltages(regulator); 1967a7a1ad90SMark Brown if (ret < 0) 1968a7a1ad90SMark Brown return ret; 1969a7a1ad90SMark Brown voltages = ret; 1970a7a1ad90SMark Brown 1971a7a1ad90SMark Brown for (i = 0; i < voltages; i++) { 1972a7a1ad90SMark Brown ret = regulator_list_voltage(regulator, i); 1973a7a1ad90SMark Brown 1974a7a1ad90SMark Brown if (ret >= min_uV && ret <= max_uV) 1975a7a1ad90SMark Brown return 1; 1976a7a1ad90SMark Brown } 1977a7a1ad90SMark Brown 1978a7a1ad90SMark Brown return 0; 1979a7a1ad90SMark Brown } 1980a398eaa2SMark Brown EXPORT_SYMBOL_GPL(regulator_is_supported_voltage); 1981a7a1ad90SMark Brown 19824ab5b3d9SMark Brown /** 19834ab5b3d9SMark Brown * regulator_get_voltage_sel_regmap - standard get_voltage_sel for regmap users 19844ab5b3d9SMark Brown * 19854ab5b3d9SMark Brown * @rdev: regulator to operate on 19864ab5b3d9SMark Brown * 19874ab5b3d9SMark Brown * Regulators that use regmap for their register I/O can set the 19884ab5b3d9SMark Brown * vsel_reg and vsel_mask fields in their descriptor and then use this 19894ab5b3d9SMark Brown * as their get_voltage_vsel operation, saving some code. 19904ab5b3d9SMark Brown */ 19914ab5b3d9SMark Brown int regulator_get_voltage_sel_regmap(struct regulator_dev *rdev) 19924ab5b3d9SMark Brown { 19934ab5b3d9SMark Brown unsigned int val; 19944ab5b3d9SMark Brown int ret; 19954ab5b3d9SMark Brown 19964ab5b3d9SMark Brown ret = regmap_read(rdev->regmap, rdev->desc->vsel_reg, &val); 19974ab5b3d9SMark Brown if (ret != 0) 19984ab5b3d9SMark Brown return ret; 19994ab5b3d9SMark Brown 20004ab5b3d9SMark Brown val &= rdev->desc->vsel_mask; 20014ab5b3d9SMark Brown val >>= ffs(rdev->desc->vsel_mask) - 1; 20024ab5b3d9SMark Brown 20034ab5b3d9SMark Brown return val; 20044ab5b3d9SMark Brown } 20054ab5b3d9SMark Brown EXPORT_SYMBOL_GPL(regulator_get_voltage_sel_regmap); 20064ab5b3d9SMark Brown 20074ab5b3d9SMark Brown /** 20084ab5b3d9SMark Brown * regulator_set_voltage_sel_regmap - standard set_voltage_sel for regmap users 20094ab5b3d9SMark Brown * 20104ab5b3d9SMark Brown * @rdev: regulator to operate on 20114ab5b3d9SMark Brown * @sel: Selector to set 20124ab5b3d9SMark Brown * 20134ab5b3d9SMark Brown * Regulators that use regmap for their register I/O can set the 20144ab5b3d9SMark Brown * vsel_reg and vsel_mask fields in their descriptor and then use this 20154ab5b3d9SMark Brown * as their set_voltage_vsel operation, saving some code. 20164ab5b3d9SMark Brown */ 20174ab5b3d9SMark Brown int regulator_set_voltage_sel_regmap(struct regulator_dev *rdev, unsigned sel) 20184ab5b3d9SMark Brown { 20194ab5b3d9SMark Brown sel <<= ffs(rdev->desc->vsel_mask) - 1; 20204ab5b3d9SMark Brown 20214ab5b3d9SMark Brown return regmap_update_bits(rdev->regmap, rdev->desc->vsel_reg, 20224ab5b3d9SMark Brown rdev->desc->vsel_mask, sel); 20234ab5b3d9SMark Brown } 20244ab5b3d9SMark Brown EXPORT_SYMBOL_GPL(regulator_set_voltage_sel_regmap); 20254ab5b3d9SMark Brown 2026e843fc46SMark Brown /** 2027e843fc46SMark Brown * regulator_map_voltage_iterate - map_voltage() based on list_voltage() 2028e843fc46SMark Brown * 2029e843fc46SMark Brown * @rdev: Regulator to operate on 2030e843fc46SMark Brown * @min_uV: Lower bound for voltage 2031e843fc46SMark Brown * @max_uV: Upper bound for voltage 2032e843fc46SMark Brown * 2033e843fc46SMark Brown * Drivers implementing set_voltage_sel() and list_voltage() can use 2034e843fc46SMark Brown * this as their map_voltage() operation. It will find a suitable 2035e843fc46SMark Brown * voltage by calling list_voltage() until it gets something in bounds 2036e843fc46SMark Brown * for the requested voltages. 2037e843fc46SMark Brown */ 2038e843fc46SMark Brown int regulator_map_voltage_iterate(struct regulator_dev *rdev, 203975790251SMark Brown int min_uV, int max_uV) 204075790251SMark Brown { 2041e8eef82bSMark Brown int best_val = INT_MAX; 2042e843fc46SMark Brown int selector = 0; 2043e843fc46SMark Brown int i, ret; 2044e8eef82bSMark Brown 2045e8eef82bSMark Brown /* Find the smallest voltage that falls within the specified 2046e8eef82bSMark Brown * range. 2047e8eef82bSMark Brown */ 2048e8eef82bSMark Brown for (i = 0; i < rdev->desc->n_voltages; i++) { 2049e8eef82bSMark Brown ret = rdev->desc->ops->list_voltage(rdev, i); 2050e8eef82bSMark Brown if (ret < 0) 2051e8eef82bSMark Brown continue; 2052e8eef82bSMark Brown 2053e8eef82bSMark Brown if (ret < best_val && ret >= min_uV && ret <= max_uV) { 2054e8eef82bSMark Brown best_val = ret; 2055e8eef82bSMark Brown selector = i; 2056e8eef82bSMark Brown } 2057e8eef82bSMark Brown } 2058e8eef82bSMark Brown 2059e843fc46SMark Brown if (best_val != INT_MAX) 2060e843fc46SMark Brown return selector; 2061e843fc46SMark Brown else 2062e843fc46SMark Brown return -EINVAL; 2063e843fc46SMark Brown } 2064e843fc46SMark Brown EXPORT_SYMBOL_GPL(regulator_map_voltage_iterate); 2065e843fc46SMark Brown 2066bca7bbffSMark Brown /** 2067bca7bbffSMark Brown * regulator_map_voltage_linear - map_voltage() for simple linear mappings 2068bca7bbffSMark Brown * 2069bca7bbffSMark Brown * @rdev: Regulator to operate on 2070bca7bbffSMark Brown * @min_uV: Lower bound for voltage 2071bca7bbffSMark Brown * @max_uV: Upper bound for voltage 2072bca7bbffSMark Brown * 2073bca7bbffSMark Brown * Drivers providing min_uV and uV_step in their regulator_desc can 2074bca7bbffSMark Brown * use this as their map_voltage() operation. 2075bca7bbffSMark Brown */ 2076bca7bbffSMark Brown int regulator_map_voltage_linear(struct regulator_dev *rdev, 2077bca7bbffSMark Brown int min_uV, int max_uV) 2078bca7bbffSMark Brown { 2079bca7bbffSMark Brown int ret, voltage; 2080bca7bbffSMark Brown 20815a6881e8SAxel Lin /* Allow uV_step to be 0 for fixed voltage */ 20825a6881e8SAxel Lin if (rdev->desc->n_voltages == 1 && rdev->desc->uV_step == 0) { 20835a6881e8SAxel Lin if (min_uV <= rdev->desc->min_uV && rdev->desc->min_uV <= max_uV) 20845a6881e8SAxel Lin return 0; 20855a6881e8SAxel Lin else 20865a6881e8SAxel Lin return -EINVAL; 20875a6881e8SAxel Lin } 20885a6881e8SAxel Lin 2089bca7bbffSMark Brown if (!rdev->desc->uV_step) { 2090bca7bbffSMark Brown BUG_ON(!rdev->desc->uV_step); 2091bca7bbffSMark Brown return -EINVAL; 2092bca7bbffSMark Brown } 2093bca7bbffSMark Brown 2094ccfcb1c3SAxel Lin ret = DIV_ROUND_UP(min_uV - rdev->desc->min_uV, rdev->desc->uV_step); 2095bca7bbffSMark Brown if (ret < 0) 2096bca7bbffSMark Brown return ret; 2097bca7bbffSMark Brown 2098bca7bbffSMark Brown /* Map back into a voltage to verify we're still in bounds */ 2099bca7bbffSMark Brown voltage = rdev->desc->ops->list_voltage(rdev, ret); 2100bca7bbffSMark Brown if (voltage < min_uV || voltage > max_uV) 2101bca7bbffSMark Brown return -EINVAL; 2102bca7bbffSMark Brown 2103bca7bbffSMark Brown return ret; 2104bca7bbffSMark Brown } 2105bca7bbffSMark Brown EXPORT_SYMBOL_GPL(regulator_map_voltage_linear); 2106bca7bbffSMark Brown 2107a7a1ad90SMark Brown static int _regulator_do_set_voltage(struct regulator_dev *rdev, 2108a7a1ad90SMark Brown int min_uV, int max_uV) 2109a7a1ad90SMark Brown { 2110a7a1ad90SMark Brown int ret; 211175790251SMark Brown int delay = 0; 2112e843fc46SMark Brown int best_val; 211375790251SMark Brown unsigned int selector; 2114eba41a5eSAxel Lin int old_selector = -1; 211575790251SMark Brown 211675790251SMark Brown trace_regulator_set_voltage(rdev_get_name(rdev), min_uV, max_uV); 211775790251SMark Brown 211875790251SMark Brown min_uV += rdev->constraints->uV_offset; 211975790251SMark Brown max_uV += rdev->constraints->uV_offset; 212075790251SMark Brown 212177af1b26SLinus Walleij /* 212277af1b26SLinus Walleij * If we can't obtain the old selector there is not enough 212377af1b26SLinus Walleij * info to call set_voltage_time_sel(). 212477af1b26SLinus Walleij */ 21258b7485efSAxel Lin if (_regulator_is_enabled(rdev) && 21268b7485efSAxel Lin rdev->desc->ops->set_voltage_time_sel && 212777af1b26SLinus Walleij rdev->desc->ops->get_voltage_sel) { 2128eba41a5eSAxel Lin old_selector = rdev->desc->ops->get_voltage_sel(rdev); 2129eba41a5eSAxel Lin if (old_selector < 0) 2130eba41a5eSAxel Lin return old_selector; 2131eba41a5eSAxel Lin } 213277af1b26SLinus Walleij 213375790251SMark Brown if (rdev->desc->ops->set_voltage) { 213475790251SMark Brown ret = rdev->desc->ops->set_voltage(rdev, min_uV, max_uV, 213575790251SMark Brown &selector); 2136e8eef82bSMark Brown } else if (rdev->desc->ops->set_voltage_sel) { 2137e843fc46SMark Brown if (rdev->desc->ops->map_voltage) 2138e843fc46SMark Brown ret = rdev->desc->ops->map_voltage(rdev, min_uV, 2139e843fc46SMark Brown max_uV); 214007351233SAxel Lin else 2141e843fc46SMark Brown ret = regulator_map_voltage_iterate(rdev, min_uV, 2142e843fc46SMark Brown max_uV); 2143e843fc46SMark Brown 2144e843fc46SMark Brown if (ret >= 0) { 2145e843fc46SMark Brown selector = ret; 2146e843fc46SMark Brown ret = rdev->desc->ops->set_voltage_sel(rdev, ret); 2147e843fc46SMark Brown } 2148e8eef82bSMark Brown } else { 2149e8eef82bSMark Brown ret = -EINVAL; 2150e8eef82bSMark Brown } 2151e8eef82bSMark Brown 2152e843fc46SMark Brown if (rdev->desc->ops->list_voltage) 2153e843fc46SMark Brown best_val = rdev->desc->ops->list_voltage(rdev, selector); 2154e843fc46SMark Brown else 2155e843fc46SMark Brown best_val = -1; 2156e843fc46SMark Brown 2157eba41a5eSAxel Lin /* Call set_voltage_time_sel if successfully obtained old_selector */ 21588b7485efSAxel Lin if (_regulator_is_enabled(rdev) && ret == 0 && old_selector >= 0 && 2159eba41a5eSAxel Lin rdev->desc->ops->set_voltage_time_sel) { 2160eba41a5eSAxel Lin 2161eba41a5eSAxel Lin delay = rdev->desc->ops->set_voltage_time_sel(rdev, 2162eba41a5eSAxel Lin old_selector, selector); 2163eba41a5eSAxel Lin if (delay < 0) { 2164eba41a5eSAxel Lin rdev_warn(rdev, "set_voltage_time_sel() failed: %d\n", 2165eba41a5eSAxel Lin delay); 2166eba41a5eSAxel Lin delay = 0; 2167e8eef82bSMark Brown } 216875790251SMark Brown } 216975790251SMark Brown 217077af1b26SLinus Walleij /* Insert any necessary delays */ 217177af1b26SLinus Walleij if (delay >= 1000) { 217277af1b26SLinus Walleij mdelay(delay / 1000); 217377af1b26SLinus Walleij udelay(delay % 1000); 217477af1b26SLinus Walleij } else if (delay) { 217577af1b26SLinus Walleij udelay(delay); 217677af1b26SLinus Walleij } 217777af1b26SLinus Walleij 2178ded06a52SMark Brown if (ret == 0) 2179ded06a52SMark Brown _notifier_call_chain(rdev, REGULATOR_EVENT_VOLTAGE_CHANGE, 2180ded06a52SMark Brown NULL); 2181ded06a52SMark Brown 2182eba41a5eSAxel Lin trace_regulator_set_voltage_complete(rdev_get_name(rdev), best_val); 218375790251SMark Brown 218475790251SMark Brown return ret; 218575790251SMark Brown } 218675790251SMark Brown 2187a7a1ad90SMark Brown /** 2188414c70cbSLiam Girdwood * regulator_set_voltage - set regulator output voltage 2189414c70cbSLiam Girdwood * @regulator: regulator source 2190414c70cbSLiam Girdwood * @min_uV: Minimum required voltage in uV 2191414c70cbSLiam Girdwood * @max_uV: Maximum acceptable voltage in uV 2192414c70cbSLiam Girdwood * 2193414c70cbSLiam Girdwood * Sets a voltage regulator to the desired output voltage. This can be set 2194414c70cbSLiam Girdwood * during any regulator state. IOW, regulator can be disabled or enabled. 2195414c70cbSLiam Girdwood * 2196414c70cbSLiam Girdwood * If the regulator is enabled then the voltage will change to the new value 2197414c70cbSLiam Girdwood * immediately otherwise if the regulator is disabled the regulator will 2198414c70cbSLiam Girdwood * output at the new voltage when enabled. 2199414c70cbSLiam Girdwood * 2200414c70cbSLiam Girdwood * NOTE: If the regulator is shared between several devices then the lowest 2201414c70cbSLiam Girdwood * request voltage that meets the system constraints will be used. 220269279fb9SMark Brown * Regulator system constraints must be set for this regulator before 2203414c70cbSLiam Girdwood * calling this function otherwise this call will fail. 2204414c70cbSLiam Girdwood */ 2205414c70cbSLiam Girdwood int regulator_set_voltage(struct regulator *regulator, int min_uV, int max_uV) 2206414c70cbSLiam Girdwood { 2207414c70cbSLiam Girdwood struct regulator_dev *rdev = regulator->rdev; 220895a3c23aSMark Brown int ret = 0; 2209414c70cbSLiam Girdwood 2210414c70cbSLiam Girdwood mutex_lock(&rdev->mutex); 2211414c70cbSLiam Girdwood 221295a3c23aSMark Brown /* If we're setting the same range as last time the change 221395a3c23aSMark Brown * should be a noop (some cpufreq implementations use the same 221495a3c23aSMark Brown * voltage for multiple frequencies, for example). 221595a3c23aSMark Brown */ 221695a3c23aSMark Brown if (regulator->min_uV == min_uV && regulator->max_uV == max_uV) 221795a3c23aSMark Brown goto out; 221895a3c23aSMark Brown 2219414c70cbSLiam Girdwood /* sanity check */ 2220e8eef82bSMark Brown if (!rdev->desc->ops->set_voltage && 2221e8eef82bSMark Brown !rdev->desc->ops->set_voltage_sel) { 2222414c70cbSLiam Girdwood ret = -EINVAL; 2223414c70cbSLiam Girdwood goto out; 2224414c70cbSLiam Girdwood } 2225414c70cbSLiam Girdwood 2226414c70cbSLiam Girdwood /* constraints check */ 2227414c70cbSLiam Girdwood ret = regulator_check_voltage(rdev, &min_uV, &max_uV); 2228414c70cbSLiam Girdwood if (ret < 0) 2229414c70cbSLiam Girdwood goto out; 2230414c70cbSLiam Girdwood regulator->min_uV = min_uV; 2231414c70cbSLiam Girdwood regulator->max_uV = max_uV; 22323a93f2a9SMark Brown 223305fda3b1SThomas Petazzoni ret = regulator_check_consumers(rdev, &min_uV, &max_uV); 223405fda3b1SThomas Petazzoni if (ret < 0) 223505fda3b1SThomas Petazzoni goto out; 223605fda3b1SThomas Petazzoni 223775790251SMark Brown ret = _regulator_do_set_voltage(rdev, min_uV, max_uV); 223802fa3ec0SMark Brown 2239414c70cbSLiam Girdwood out: 2240414c70cbSLiam Girdwood mutex_unlock(&rdev->mutex); 2241414c70cbSLiam Girdwood return ret; 2242414c70cbSLiam Girdwood } 2243414c70cbSLiam Girdwood EXPORT_SYMBOL_GPL(regulator_set_voltage); 2244414c70cbSLiam Girdwood 2245606a2562SMark Brown /** 224688cd222bSLinus Walleij * regulator_set_voltage_time - get raise/fall time 224788cd222bSLinus Walleij * @regulator: regulator source 224888cd222bSLinus Walleij * @old_uV: starting voltage in microvolts 224988cd222bSLinus Walleij * @new_uV: target voltage in microvolts 225088cd222bSLinus Walleij * 225188cd222bSLinus Walleij * Provided with the starting and ending voltage, this function attempts to 225288cd222bSLinus Walleij * calculate the time in microseconds required to rise or fall to this new 225388cd222bSLinus Walleij * voltage. 225488cd222bSLinus Walleij */ 225588cd222bSLinus Walleij int regulator_set_voltage_time(struct regulator *regulator, 225688cd222bSLinus Walleij int old_uV, int new_uV) 225788cd222bSLinus Walleij { 225888cd222bSLinus Walleij struct regulator_dev *rdev = regulator->rdev; 225988cd222bSLinus Walleij struct regulator_ops *ops = rdev->desc->ops; 226088cd222bSLinus Walleij int old_sel = -1; 226188cd222bSLinus Walleij int new_sel = -1; 226288cd222bSLinus Walleij int voltage; 226388cd222bSLinus Walleij int i; 226488cd222bSLinus Walleij 226588cd222bSLinus Walleij /* Currently requires operations to do this */ 226688cd222bSLinus Walleij if (!ops->list_voltage || !ops->set_voltage_time_sel 226788cd222bSLinus Walleij || !rdev->desc->n_voltages) 226888cd222bSLinus Walleij return -EINVAL; 226988cd222bSLinus Walleij 227088cd222bSLinus Walleij for (i = 0; i < rdev->desc->n_voltages; i++) { 227188cd222bSLinus Walleij /* We only look for exact voltage matches here */ 227288cd222bSLinus Walleij voltage = regulator_list_voltage(regulator, i); 227388cd222bSLinus Walleij if (voltage < 0) 227488cd222bSLinus Walleij return -EINVAL; 227588cd222bSLinus Walleij if (voltage == 0) 227688cd222bSLinus Walleij continue; 227788cd222bSLinus Walleij if (voltage == old_uV) 227888cd222bSLinus Walleij old_sel = i; 227988cd222bSLinus Walleij if (voltage == new_uV) 228088cd222bSLinus Walleij new_sel = i; 228188cd222bSLinus Walleij } 228288cd222bSLinus Walleij 228388cd222bSLinus Walleij if (old_sel < 0 || new_sel < 0) 228488cd222bSLinus Walleij return -EINVAL; 228588cd222bSLinus Walleij 228688cd222bSLinus Walleij return ops->set_voltage_time_sel(rdev, old_sel, new_sel); 228788cd222bSLinus Walleij } 228888cd222bSLinus Walleij EXPORT_SYMBOL_GPL(regulator_set_voltage_time); 228988cd222bSLinus Walleij 229088cd222bSLinus Walleij /** 229198a175b6SYadwinder Singh Brar *regulator_set_voltage_time_sel - get raise/fall time 229298a175b6SYadwinder Singh Brar * @regulator: regulator source 229398a175b6SYadwinder Singh Brar * @old_selector: selector for starting voltage 229498a175b6SYadwinder Singh Brar * @new_selector: selector for target voltage 229598a175b6SYadwinder Singh Brar * 229698a175b6SYadwinder Singh Brar * Provided with the starting and target voltage selectors, this function 229798a175b6SYadwinder Singh Brar * returns time in microseconds required to rise or fall to this new voltage 229898a175b6SYadwinder Singh Brar * 2299398715abSAxel Lin * Drivers providing uV_step or volt_table in their regulator_desc and 2300398715abSAxel Lin * ramp_delay in regulation_constraints can use this as their 2301398715abSAxel Lin * set_voltage_time_sel() operation. 230298a175b6SYadwinder Singh Brar */ 230398a175b6SYadwinder Singh Brar int regulator_set_voltage_time_sel(struct regulator_dev *rdev, 230498a175b6SYadwinder Singh Brar unsigned int old_selector, 230598a175b6SYadwinder Singh Brar unsigned int new_selector) 230698a175b6SYadwinder Singh Brar { 2307398715abSAxel Lin unsigned int ramp_delay = 0; 2308398715abSAxel Lin 23096f0b2c69SYadwinder Singh Brar if (rdev->constraints->ramp_delay) 2310398715abSAxel Lin ramp_delay = rdev->constraints->ramp_delay; 2311398715abSAxel Lin else if (rdev->desc->ramp_delay) 2312398715abSAxel Lin ramp_delay = rdev->desc->ramp_delay; 2313398715abSAxel Lin 2314398715abSAxel Lin if (ramp_delay == 0) { 23156f0b2c69SYadwinder Singh Brar rdev_warn(rdev, "ramp_delay not set\n"); 2316398715abSAxel Lin return 0; 23176f0b2c69SYadwinder Singh Brar } 2318398715abSAxel Lin 2319398715abSAxel Lin if (rdev->desc->uV_step) { 2320398715abSAxel Lin return DIV_ROUND_UP(rdev->desc->uV_step * 2321398715abSAxel Lin abs(new_selector - old_selector), 2322398715abSAxel Lin ramp_delay * 1000); 2323398715abSAxel Lin } else if (rdev->desc->volt_table) { 2324398715abSAxel Lin return DIV_ROUND_UP(abs(rdev->desc->volt_table[new_selector] - 2325398715abSAxel Lin rdev->desc->volt_table[old_selector]), 2326398715abSAxel Lin ramp_delay * 1000); 2327398715abSAxel Lin } else { 2328398715abSAxel Lin rdev_warn(rdev, "Unsupported voltage mapping settings\n"); 2329398715abSAxel Lin } 2330398715abSAxel Lin 233198a175b6SYadwinder Singh Brar return 0; 233298a175b6SYadwinder Singh Brar } 233398a175b6SYadwinder Singh Brar 233498a175b6SYadwinder Singh Brar /** 2335606a2562SMark Brown * regulator_sync_voltage - re-apply last regulator output voltage 2336606a2562SMark Brown * @regulator: regulator source 2337606a2562SMark Brown * 2338606a2562SMark Brown * Re-apply the last configured voltage. This is intended to be used 2339606a2562SMark Brown * where some external control source the consumer is cooperating with 2340606a2562SMark Brown * has caused the configured voltage to change. 2341606a2562SMark Brown */ 2342606a2562SMark Brown int regulator_sync_voltage(struct regulator *regulator) 2343606a2562SMark Brown { 2344606a2562SMark Brown struct regulator_dev *rdev = regulator->rdev; 2345606a2562SMark Brown int ret, min_uV, max_uV; 2346606a2562SMark Brown 2347606a2562SMark Brown mutex_lock(&rdev->mutex); 2348606a2562SMark Brown 2349606a2562SMark Brown if (!rdev->desc->ops->set_voltage && 2350606a2562SMark Brown !rdev->desc->ops->set_voltage_sel) { 2351606a2562SMark Brown ret = -EINVAL; 2352606a2562SMark Brown goto out; 2353606a2562SMark Brown } 2354606a2562SMark Brown 2355606a2562SMark Brown /* This is only going to work if we've had a voltage configured. */ 2356606a2562SMark Brown if (!regulator->min_uV && !regulator->max_uV) { 2357606a2562SMark Brown ret = -EINVAL; 2358606a2562SMark Brown goto out; 2359606a2562SMark Brown } 2360606a2562SMark Brown 2361606a2562SMark Brown min_uV = regulator->min_uV; 2362606a2562SMark Brown max_uV = regulator->max_uV; 2363606a2562SMark Brown 2364606a2562SMark Brown /* This should be a paranoia check... */ 2365606a2562SMark Brown ret = regulator_check_voltage(rdev, &min_uV, &max_uV); 2366606a2562SMark Brown if (ret < 0) 2367606a2562SMark Brown goto out; 2368606a2562SMark Brown 2369606a2562SMark Brown ret = regulator_check_consumers(rdev, &min_uV, &max_uV); 2370606a2562SMark Brown if (ret < 0) 2371606a2562SMark Brown goto out; 2372606a2562SMark Brown 2373606a2562SMark Brown ret = _regulator_do_set_voltage(rdev, min_uV, max_uV); 2374606a2562SMark Brown 2375606a2562SMark Brown out: 2376606a2562SMark Brown mutex_unlock(&rdev->mutex); 2377606a2562SMark Brown return ret; 2378606a2562SMark Brown } 2379606a2562SMark Brown EXPORT_SYMBOL_GPL(regulator_sync_voltage); 2380606a2562SMark Brown 2381414c70cbSLiam Girdwood static int _regulator_get_voltage(struct regulator_dev *rdev) 2382414c70cbSLiam Girdwood { 2383bf5892a8SMark Brown int sel, ret; 2384476c2d83SMark Brown 2385476c2d83SMark Brown if (rdev->desc->ops->get_voltage_sel) { 2386476c2d83SMark Brown sel = rdev->desc->ops->get_voltage_sel(rdev); 2387476c2d83SMark Brown if (sel < 0) 2388476c2d83SMark Brown return sel; 2389bf5892a8SMark Brown ret = rdev->desc->ops->list_voltage(rdev, sel); 2390cb220d16SAxel Lin } else if (rdev->desc->ops->get_voltage) { 2391bf5892a8SMark Brown ret = rdev->desc->ops->get_voltage(rdev); 2392cb220d16SAxel Lin } else { 2393414c70cbSLiam Girdwood return -EINVAL; 2394cb220d16SAxel Lin } 2395bf5892a8SMark Brown 2396cb220d16SAxel Lin if (ret < 0) 2397cb220d16SAxel Lin return ret; 2398bf5892a8SMark Brown return ret - rdev->constraints->uV_offset; 2399414c70cbSLiam Girdwood } 2400414c70cbSLiam Girdwood 2401414c70cbSLiam Girdwood /** 2402414c70cbSLiam Girdwood * regulator_get_voltage - get regulator output voltage 2403414c70cbSLiam Girdwood * @regulator: regulator source 2404414c70cbSLiam Girdwood * 2405414c70cbSLiam Girdwood * This returns the current regulator voltage in uV. 2406414c70cbSLiam Girdwood * 2407414c70cbSLiam Girdwood * NOTE: If the regulator is disabled it will return the voltage value. This 2408414c70cbSLiam Girdwood * function should not be used to determine regulator state. 2409414c70cbSLiam Girdwood */ 2410414c70cbSLiam Girdwood int regulator_get_voltage(struct regulator *regulator) 2411414c70cbSLiam Girdwood { 2412414c70cbSLiam Girdwood int ret; 2413414c70cbSLiam Girdwood 2414414c70cbSLiam Girdwood mutex_lock(®ulator->rdev->mutex); 2415414c70cbSLiam Girdwood 2416414c70cbSLiam Girdwood ret = _regulator_get_voltage(regulator->rdev); 2417414c70cbSLiam Girdwood 2418414c70cbSLiam Girdwood mutex_unlock(®ulator->rdev->mutex); 2419414c70cbSLiam Girdwood 2420414c70cbSLiam Girdwood return ret; 2421414c70cbSLiam Girdwood } 2422414c70cbSLiam Girdwood EXPORT_SYMBOL_GPL(regulator_get_voltage); 2423414c70cbSLiam Girdwood 2424414c70cbSLiam Girdwood /** 2425414c70cbSLiam Girdwood * regulator_set_current_limit - set regulator output current limit 2426414c70cbSLiam Girdwood * @regulator: regulator source 2427414c70cbSLiam Girdwood * @min_uA: Minimuum supported current in uA 2428414c70cbSLiam Girdwood * @max_uA: Maximum supported current in uA 2429414c70cbSLiam Girdwood * 2430414c70cbSLiam Girdwood * Sets current sink to the desired output current. This can be set during 2431414c70cbSLiam Girdwood * any regulator state. IOW, regulator can be disabled or enabled. 2432414c70cbSLiam Girdwood * 2433414c70cbSLiam Girdwood * If the regulator is enabled then the current will change to the new value 2434414c70cbSLiam Girdwood * immediately otherwise if the regulator is disabled the regulator will 2435414c70cbSLiam Girdwood * output at the new current when enabled. 2436414c70cbSLiam Girdwood * 2437414c70cbSLiam Girdwood * NOTE: Regulator system constraints must be set for this regulator before 2438414c70cbSLiam Girdwood * calling this function otherwise this call will fail. 2439414c70cbSLiam Girdwood */ 2440414c70cbSLiam Girdwood int regulator_set_current_limit(struct regulator *regulator, 2441414c70cbSLiam Girdwood int min_uA, int max_uA) 2442414c70cbSLiam Girdwood { 2443414c70cbSLiam Girdwood struct regulator_dev *rdev = regulator->rdev; 2444414c70cbSLiam Girdwood int ret; 2445414c70cbSLiam Girdwood 2446414c70cbSLiam Girdwood mutex_lock(&rdev->mutex); 2447414c70cbSLiam Girdwood 2448414c70cbSLiam Girdwood /* sanity check */ 2449414c70cbSLiam Girdwood if (!rdev->desc->ops->set_current_limit) { 2450414c70cbSLiam Girdwood ret = -EINVAL; 2451414c70cbSLiam Girdwood goto out; 2452414c70cbSLiam Girdwood } 2453414c70cbSLiam Girdwood 2454414c70cbSLiam Girdwood /* constraints check */ 2455414c70cbSLiam Girdwood ret = regulator_check_current_limit(rdev, &min_uA, &max_uA); 2456414c70cbSLiam Girdwood if (ret < 0) 2457414c70cbSLiam Girdwood goto out; 2458414c70cbSLiam Girdwood 2459414c70cbSLiam Girdwood ret = rdev->desc->ops->set_current_limit(rdev, min_uA, max_uA); 2460414c70cbSLiam Girdwood out: 2461414c70cbSLiam Girdwood mutex_unlock(&rdev->mutex); 2462414c70cbSLiam Girdwood return ret; 2463414c70cbSLiam Girdwood } 2464414c70cbSLiam Girdwood EXPORT_SYMBOL_GPL(regulator_set_current_limit); 2465414c70cbSLiam Girdwood 2466414c70cbSLiam Girdwood static int _regulator_get_current_limit(struct regulator_dev *rdev) 2467414c70cbSLiam Girdwood { 2468414c70cbSLiam Girdwood int ret; 2469414c70cbSLiam Girdwood 2470414c70cbSLiam Girdwood mutex_lock(&rdev->mutex); 2471414c70cbSLiam Girdwood 2472414c70cbSLiam Girdwood /* sanity check */ 2473414c70cbSLiam Girdwood if (!rdev->desc->ops->get_current_limit) { 2474414c70cbSLiam Girdwood ret = -EINVAL; 2475414c70cbSLiam Girdwood goto out; 2476414c70cbSLiam Girdwood } 2477414c70cbSLiam Girdwood 2478414c70cbSLiam Girdwood ret = rdev->desc->ops->get_current_limit(rdev); 2479414c70cbSLiam Girdwood out: 2480414c70cbSLiam Girdwood mutex_unlock(&rdev->mutex); 2481414c70cbSLiam Girdwood return ret; 2482414c70cbSLiam Girdwood } 2483414c70cbSLiam Girdwood 2484414c70cbSLiam Girdwood /** 2485414c70cbSLiam Girdwood * regulator_get_current_limit - get regulator output current 2486414c70cbSLiam Girdwood * @regulator: regulator source 2487414c70cbSLiam Girdwood * 2488414c70cbSLiam Girdwood * This returns the current supplied by the specified current sink in uA. 2489414c70cbSLiam Girdwood * 2490414c70cbSLiam Girdwood * NOTE: If the regulator is disabled it will return the current value. This 2491414c70cbSLiam Girdwood * function should not be used to determine regulator state. 2492414c70cbSLiam Girdwood */ 2493414c70cbSLiam Girdwood int regulator_get_current_limit(struct regulator *regulator) 2494414c70cbSLiam Girdwood { 2495414c70cbSLiam Girdwood return _regulator_get_current_limit(regulator->rdev); 2496414c70cbSLiam Girdwood } 2497414c70cbSLiam Girdwood EXPORT_SYMBOL_GPL(regulator_get_current_limit); 2498414c70cbSLiam Girdwood 2499414c70cbSLiam Girdwood /** 2500414c70cbSLiam Girdwood * regulator_set_mode - set regulator operating mode 2501414c70cbSLiam Girdwood * @regulator: regulator source 2502414c70cbSLiam Girdwood * @mode: operating mode - one of the REGULATOR_MODE constants 2503414c70cbSLiam Girdwood * 2504414c70cbSLiam Girdwood * Set regulator operating mode to increase regulator efficiency or improve 2505414c70cbSLiam Girdwood * regulation performance. 2506414c70cbSLiam Girdwood * 2507414c70cbSLiam Girdwood * NOTE: Regulator system constraints must be set for this regulator before 2508414c70cbSLiam Girdwood * calling this function otherwise this call will fail. 2509414c70cbSLiam Girdwood */ 2510414c70cbSLiam Girdwood int regulator_set_mode(struct regulator *regulator, unsigned int mode) 2511414c70cbSLiam Girdwood { 2512414c70cbSLiam Girdwood struct regulator_dev *rdev = regulator->rdev; 2513414c70cbSLiam Girdwood int ret; 2514500b4ac9SSundar R Iyer int regulator_curr_mode; 2515414c70cbSLiam Girdwood 2516414c70cbSLiam Girdwood mutex_lock(&rdev->mutex); 2517414c70cbSLiam Girdwood 2518414c70cbSLiam Girdwood /* sanity check */ 2519414c70cbSLiam Girdwood if (!rdev->desc->ops->set_mode) { 2520414c70cbSLiam Girdwood ret = -EINVAL; 2521414c70cbSLiam Girdwood goto out; 2522414c70cbSLiam Girdwood } 2523414c70cbSLiam Girdwood 2524500b4ac9SSundar R Iyer /* return if the same mode is requested */ 2525500b4ac9SSundar R Iyer if (rdev->desc->ops->get_mode) { 2526500b4ac9SSundar R Iyer regulator_curr_mode = rdev->desc->ops->get_mode(rdev); 2527500b4ac9SSundar R Iyer if (regulator_curr_mode == mode) { 2528500b4ac9SSundar R Iyer ret = 0; 2529500b4ac9SSundar R Iyer goto out; 2530500b4ac9SSundar R Iyer } 2531500b4ac9SSundar R Iyer } 2532500b4ac9SSundar R Iyer 2533414c70cbSLiam Girdwood /* constraints check */ 253422c51b47SAxel Lin ret = regulator_mode_constrain(rdev, &mode); 2535414c70cbSLiam Girdwood if (ret < 0) 2536414c70cbSLiam Girdwood goto out; 2537414c70cbSLiam Girdwood 2538414c70cbSLiam Girdwood ret = rdev->desc->ops->set_mode(rdev, mode); 2539414c70cbSLiam Girdwood out: 2540414c70cbSLiam Girdwood mutex_unlock(&rdev->mutex); 2541414c70cbSLiam Girdwood return ret; 2542414c70cbSLiam Girdwood } 2543414c70cbSLiam Girdwood EXPORT_SYMBOL_GPL(regulator_set_mode); 2544414c70cbSLiam Girdwood 2545414c70cbSLiam Girdwood static unsigned int _regulator_get_mode(struct regulator_dev *rdev) 2546414c70cbSLiam Girdwood { 2547414c70cbSLiam Girdwood int ret; 2548414c70cbSLiam Girdwood 2549414c70cbSLiam Girdwood mutex_lock(&rdev->mutex); 2550414c70cbSLiam Girdwood 2551414c70cbSLiam Girdwood /* sanity check */ 2552414c70cbSLiam Girdwood if (!rdev->desc->ops->get_mode) { 2553414c70cbSLiam Girdwood ret = -EINVAL; 2554414c70cbSLiam Girdwood goto out; 2555414c70cbSLiam Girdwood } 2556414c70cbSLiam Girdwood 2557414c70cbSLiam Girdwood ret = rdev->desc->ops->get_mode(rdev); 2558414c70cbSLiam Girdwood out: 2559414c70cbSLiam Girdwood mutex_unlock(&rdev->mutex); 2560414c70cbSLiam Girdwood return ret; 2561414c70cbSLiam Girdwood } 2562414c70cbSLiam Girdwood 2563414c70cbSLiam Girdwood /** 2564414c70cbSLiam Girdwood * regulator_get_mode - get regulator operating mode 2565414c70cbSLiam Girdwood * @regulator: regulator source 2566414c70cbSLiam Girdwood * 2567414c70cbSLiam Girdwood * Get the current regulator operating mode. 2568414c70cbSLiam Girdwood */ 2569414c70cbSLiam Girdwood unsigned int regulator_get_mode(struct regulator *regulator) 2570414c70cbSLiam Girdwood { 2571414c70cbSLiam Girdwood return _regulator_get_mode(regulator->rdev); 2572414c70cbSLiam Girdwood } 2573414c70cbSLiam Girdwood EXPORT_SYMBOL_GPL(regulator_get_mode); 2574414c70cbSLiam Girdwood 2575414c70cbSLiam Girdwood /** 2576414c70cbSLiam Girdwood * regulator_set_optimum_mode - set regulator optimum operating mode 2577414c70cbSLiam Girdwood * @regulator: regulator source 2578414c70cbSLiam Girdwood * @uA_load: load current 2579414c70cbSLiam Girdwood * 2580414c70cbSLiam Girdwood * Notifies the regulator core of a new device load. This is then used by 2581414c70cbSLiam Girdwood * DRMS (if enabled by constraints) to set the most efficient regulator 2582414c70cbSLiam Girdwood * operating mode for the new regulator loading. 2583414c70cbSLiam Girdwood * 2584414c70cbSLiam Girdwood * Consumer devices notify their supply regulator of the maximum power 2585414c70cbSLiam Girdwood * they will require (can be taken from device datasheet in the power 2586414c70cbSLiam Girdwood * consumption tables) when they change operational status and hence power 2587414c70cbSLiam Girdwood * state. Examples of operational state changes that can affect power 2588414c70cbSLiam Girdwood * consumption are :- 2589414c70cbSLiam Girdwood * 2590414c70cbSLiam Girdwood * o Device is opened / closed. 2591414c70cbSLiam Girdwood * o Device I/O is about to begin or has just finished. 2592414c70cbSLiam Girdwood * o Device is idling in between work. 2593414c70cbSLiam Girdwood * 2594414c70cbSLiam Girdwood * This information is also exported via sysfs to userspace. 2595414c70cbSLiam Girdwood * 2596414c70cbSLiam Girdwood * DRMS will sum the total requested load on the regulator and change 2597414c70cbSLiam Girdwood * to the most efficient operating mode if platform constraints allow. 2598414c70cbSLiam Girdwood * 2599414c70cbSLiam Girdwood * Returns the new regulator mode or error. 2600414c70cbSLiam Girdwood */ 2601414c70cbSLiam Girdwood int regulator_set_optimum_mode(struct regulator *regulator, int uA_load) 2602414c70cbSLiam Girdwood { 2603414c70cbSLiam Girdwood struct regulator_dev *rdev = regulator->rdev; 2604414c70cbSLiam Girdwood struct regulator *consumer; 2605414c70cbSLiam Girdwood int ret, output_uV, input_uV, total_uA_load = 0; 2606414c70cbSLiam Girdwood unsigned int mode; 2607414c70cbSLiam Girdwood 2608414c70cbSLiam Girdwood mutex_lock(&rdev->mutex); 2609414c70cbSLiam Girdwood 2610a4b41483SMark Brown /* 2611a4b41483SMark Brown * first check to see if we can set modes at all, otherwise just 2612a4b41483SMark Brown * tell the consumer everything is OK. 2613a4b41483SMark Brown */ 2614414c70cbSLiam Girdwood regulator->uA_load = uA_load; 2615414c70cbSLiam Girdwood ret = regulator_check_drms(rdev); 2616a4b41483SMark Brown if (ret < 0) { 2617a4b41483SMark Brown ret = 0; 2618414c70cbSLiam Girdwood goto out; 2619a4b41483SMark Brown } 2620414c70cbSLiam Girdwood 2621414c70cbSLiam Girdwood if (!rdev->desc->ops->get_optimum_mode) 2622414c70cbSLiam Girdwood goto out; 2623414c70cbSLiam Girdwood 2624a4b41483SMark Brown /* 2625a4b41483SMark Brown * we can actually do this so any errors are indicators of 2626a4b41483SMark Brown * potential real failure. 2627a4b41483SMark Brown */ 2628a4b41483SMark Brown ret = -EINVAL; 2629a4b41483SMark Brown 2630854ccbaeSAxel Lin if (!rdev->desc->ops->set_mode) 2631854ccbaeSAxel Lin goto out; 2632854ccbaeSAxel Lin 2633414c70cbSLiam Girdwood /* get output voltage */ 26341bf5a1f8SMark Brown output_uV = _regulator_get_voltage(rdev); 2635414c70cbSLiam Girdwood if (output_uV <= 0) { 26365da84fd9SJoe Perches rdev_err(rdev, "invalid output voltage found\n"); 2637414c70cbSLiam Girdwood goto out; 2638414c70cbSLiam Girdwood } 2639414c70cbSLiam Girdwood 2640414c70cbSLiam Girdwood /* get input voltage */ 26411bf5a1f8SMark Brown input_uV = 0; 26421bf5a1f8SMark Brown if (rdev->supply) 26433801b86aSMark Brown input_uV = regulator_get_voltage(rdev->supply); 26441bf5a1f8SMark Brown if (input_uV <= 0) 2645414c70cbSLiam Girdwood input_uV = rdev->constraints->input_uV; 2646414c70cbSLiam Girdwood if (input_uV <= 0) { 26475da84fd9SJoe Perches rdev_err(rdev, "invalid input voltage found\n"); 2648414c70cbSLiam Girdwood goto out; 2649414c70cbSLiam Girdwood } 2650414c70cbSLiam Girdwood 2651414c70cbSLiam Girdwood /* calc total requested load for this regulator */ 2652414c70cbSLiam Girdwood list_for_each_entry(consumer, &rdev->consumer_list, list) 2653414c70cbSLiam Girdwood total_uA_load += consumer->uA_load; 2654414c70cbSLiam Girdwood 2655414c70cbSLiam Girdwood mode = rdev->desc->ops->get_optimum_mode(rdev, 2656414c70cbSLiam Girdwood input_uV, output_uV, 2657414c70cbSLiam Girdwood total_uA_load); 26582c608234SMark Brown ret = regulator_mode_constrain(rdev, &mode); 2659e573520bSDavid Brownell if (ret < 0) { 26605da84fd9SJoe Perches rdev_err(rdev, "failed to get optimum mode @ %d uA %d -> %d uV\n", 2661414c70cbSLiam Girdwood total_uA_load, input_uV, output_uV); 2662414c70cbSLiam Girdwood goto out; 2663414c70cbSLiam Girdwood } 2664414c70cbSLiam Girdwood 2665414c70cbSLiam Girdwood ret = rdev->desc->ops->set_mode(rdev, mode); 2666e573520bSDavid Brownell if (ret < 0) { 26675da84fd9SJoe Perches rdev_err(rdev, "failed to set optimum mode %x\n", mode); 2668414c70cbSLiam Girdwood goto out; 2669414c70cbSLiam Girdwood } 2670414c70cbSLiam Girdwood ret = mode; 2671414c70cbSLiam Girdwood out: 2672414c70cbSLiam Girdwood mutex_unlock(&rdev->mutex); 2673414c70cbSLiam Girdwood return ret; 2674414c70cbSLiam Girdwood } 2675414c70cbSLiam Girdwood EXPORT_SYMBOL_GPL(regulator_set_optimum_mode); 2676414c70cbSLiam Girdwood 2677414c70cbSLiam Girdwood /** 2678414c70cbSLiam Girdwood * regulator_register_notifier - register regulator event notifier 2679414c70cbSLiam Girdwood * @regulator: regulator source 268069279fb9SMark Brown * @nb: notifier block 2681414c70cbSLiam Girdwood * 2682414c70cbSLiam Girdwood * Register notifier block to receive regulator events. 2683414c70cbSLiam Girdwood */ 2684414c70cbSLiam Girdwood int regulator_register_notifier(struct regulator *regulator, 2685414c70cbSLiam Girdwood struct notifier_block *nb) 2686414c70cbSLiam Girdwood { 2687414c70cbSLiam Girdwood return blocking_notifier_chain_register(®ulator->rdev->notifier, 2688414c70cbSLiam Girdwood nb); 2689414c70cbSLiam Girdwood } 2690414c70cbSLiam Girdwood EXPORT_SYMBOL_GPL(regulator_register_notifier); 2691414c70cbSLiam Girdwood 2692414c70cbSLiam Girdwood /** 2693414c70cbSLiam Girdwood * regulator_unregister_notifier - unregister regulator event notifier 2694414c70cbSLiam Girdwood * @regulator: regulator source 269569279fb9SMark Brown * @nb: notifier block 2696414c70cbSLiam Girdwood * 2697414c70cbSLiam Girdwood * Unregister regulator event notifier block. 2698414c70cbSLiam Girdwood */ 2699414c70cbSLiam Girdwood int regulator_unregister_notifier(struct regulator *regulator, 2700414c70cbSLiam Girdwood struct notifier_block *nb) 2701414c70cbSLiam Girdwood { 2702414c70cbSLiam Girdwood return blocking_notifier_chain_unregister(®ulator->rdev->notifier, 2703414c70cbSLiam Girdwood nb); 2704414c70cbSLiam Girdwood } 2705414c70cbSLiam Girdwood EXPORT_SYMBOL_GPL(regulator_unregister_notifier); 2706414c70cbSLiam Girdwood 2707b136fb44SJonathan Cameron /* notify regulator consumers and downstream regulator consumers. 2708b136fb44SJonathan Cameron * Note mutex must be held by caller. 2709b136fb44SJonathan Cameron */ 2710414c70cbSLiam Girdwood static void _notifier_call_chain(struct regulator_dev *rdev, 2711414c70cbSLiam Girdwood unsigned long event, void *data) 2712414c70cbSLiam Girdwood { 2713414c70cbSLiam Girdwood /* call rdev chain first */ 2714414c70cbSLiam Girdwood blocking_notifier_call_chain(&rdev->notifier, event, NULL); 2715414c70cbSLiam Girdwood } 2716414c70cbSLiam Girdwood 2717414c70cbSLiam Girdwood /** 2718414c70cbSLiam Girdwood * regulator_bulk_get - get multiple regulator consumers 2719414c70cbSLiam Girdwood * 2720414c70cbSLiam Girdwood * @dev: Device to supply 2721414c70cbSLiam Girdwood * @num_consumers: Number of consumers to register 2722414c70cbSLiam Girdwood * @consumers: Configuration of consumers; clients are stored here. 2723414c70cbSLiam Girdwood * 2724414c70cbSLiam Girdwood * @return 0 on success, an errno on failure. 2725414c70cbSLiam Girdwood * 2726414c70cbSLiam Girdwood * This helper function allows drivers to get several regulator 2727414c70cbSLiam Girdwood * consumers in one operation. If any of the regulators cannot be 2728414c70cbSLiam Girdwood * acquired then any regulators that were allocated will be freed 2729414c70cbSLiam Girdwood * before returning to the caller. 2730414c70cbSLiam Girdwood */ 2731414c70cbSLiam Girdwood int regulator_bulk_get(struct device *dev, int num_consumers, 2732414c70cbSLiam Girdwood struct regulator_bulk_data *consumers) 2733414c70cbSLiam Girdwood { 2734414c70cbSLiam Girdwood int i; 2735414c70cbSLiam Girdwood int ret; 2736414c70cbSLiam Girdwood 2737414c70cbSLiam Girdwood for (i = 0; i < num_consumers; i++) 2738414c70cbSLiam Girdwood consumers[i].consumer = NULL; 2739414c70cbSLiam Girdwood 2740414c70cbSLiam Girdwood for (i = 0; i < num_consumers; i++) { 2741414c70cbSLiam Girdwood consumers[i].consumer = regulator_get(dev, 2742414c70cbSLiam Girdwood consumers[i].supply); 2743414c70cbSLiam Girdwood if (IS_ERR(consumers[i].consumer)) { 2744414c70cbSLiam Girdwood ret = PTR_ERR(consumers[i].consumer); 27455b307627SMark Brown dev_err(dev, "Failed to get supply '%s': %d\n", 27465b307627SMark Brown consumers[i].supply, ret); 2747414c70cbSLiam Girdwood consumers[i].consumer = NULL; 2748414c70cbSLiam Girdwood goto err; 2749414c70cbSLiam Girdwood } 2750414c70cbSLiam Girdwood } 2751414c70cbSLiam Girdwood 2752414c70cbSLiam Girdwood return 0; 2753414c70cbSLiam Girdwood 2754414c70cbSLiam Girdwood err: 2755b29c7690SAxel Lin while (--i >= 0) 2756414c70cbSLiam Girdwood regulator_put(consumers[i].consumer); 2757414c70cbSLiam Girdwood 2758414c70cbSLiam Girdwood return ret; 2759414c70cbSLiam Girdwood } 2760414c70cbSLiam Girdwood EXPORT_SYMBOL_GPL(regulator_bulk_get); 2761414c70cbSLiam Girdwood 2762e6e74030SMark Brown /** 2763e6e74030SMark Brown * devm_regulator_bulk_get - managed get multiple regulator consumers 2764e6e74030SMark Brown * 2765e6e74030SMark Brown * @dev: Device to supply 2766e6e74030SMark Brown * @num_consumers: Number of consumers to register 2767e6e74030SMark Brown * @consumers: Configuration of consumers; clients are stored here. 2768e6e74030SMark Brown * 2769e6e74030SMark Brown * @return 0 on success, an errno on failure. 2770e6e74030SMark Brown * 2771e6e74030SMark Brown * This helper function allows drivers to get several regulator 2772e6e74030SMark Brown * consumers in one operation with management, the regulators will 2773e6e74030SMark Brown * automatically be freed when the device is unbound. If any of the 2774e6e74030SMark Brown * regulators cannot be acquired then any regulators that were 2775e6e74030SMark Brown * allocated will be freed before returning to the caller. 2776e6e74030SMark Brown */ 2777e6e74030SMark Brown int devm_regulator_bulk_get(struct device *dev, int num_consumers, 2778e6e74030SMark Brown struct regulator_bulk_data *consumers) 2779e6e74030SMark Brown { 2780e6e74030SMark Brown int i; 2781e6e74030SMark Brown int ret; 2782e6e74030SMark Brown 2783e6e74030SMark Brown for (i = 0; i < num_consumers; i++) 2784e6e74030SMark Brown consumers[i].consumer = NULL; 2785e6e74030SMark Brown 2786e6e74030SMark Brown for (i = 0; i < num_consumers; i++) { 2787e6e74030SMark Brown consumers[i].consumer = devm_regulator_get(dev, 2788e6e74030SMark Brown consumers[i].supply); 2789e6e74030SMark Brown if (IS_ERR(consumers[i].consumer)) { 2790e6e74030SMark Brown ret = PTR_ERR(consumers[i].consumer); 2791e6e74030SMark Brown dev_err(dev, "Failed to get supply '%s': %d\n", 2792e6e74030SMark Brown consumers[i].supply, ret); 2793e6e74030SMark Brown consumers[i].consumer = NULL; 2794e6e74030SMark Brown goto err; 2795e6e74030SMark Brown } 2796e6e74030SMark Brown } 2797e6e74030SMark Brown 2798e6e74030SMark Brown return 0; 2799e6e74030SMark Brown 2800e6e74030SMark Brown err: 2801e6e74030SMark Brown for (i = 0; i < num_consumers && consumers[i].consumer; i++) 2802e6e74030SMark Brown devm_regulator_put(consumers[i].consumer); 2803e6e74030SMark Brown 2804e6e74030SMark Brown return ret; 2805e6e74030SMark Brown } 2806e6e74030SMark Brown EXPORT_SYMBOL_GPL(devm_regulator_bulk_get); 2807e6e74030SMark Brown 2808f21e0e81SMark Brown static void regulator_bulk_enable_async(void *data, async_cookie_t cookie) 2809f21e0e81SMark Brown { 2810f21e0e81SMark Brown struct regulator_bulk_data *bulk = data; 2811f21e0e81SMark Brown 2812f21e0e81SMark Brown bulk->ret = regulator_enable(bulk->consumer); 2813f21e0e81SMark Brown } 2814f21e0e81SMark Brown 2815414c70cbSLiam Girdwood /** 2816414c70cbSLiam Girdwood * regulator_bulk_enable - enable multiple regulator consumers 2817414c70cbSLiam Girdwood * 2818414c70cbSLiam Girdwood * @num_consumers: Number of consumers 2819414c70cbSLiam Girdwood * @consumers: Consumer data; clients are stored here. 2820414c70cbSLiam Girdwood * @return 0 on success, an errno on failure 2821414c70cbSLiam Girdwood * 2822414c70cbSLiam Girdwood * This convenience API allows consumers to enable multiple regulator 2823414c70cbSLiam Girdwood * clients in a single API call. If any consumers cannot be enabled 2824414c70cbSLiam Girdwood * then any others that were enabled will be disabled again prior to 2825414c70cbSLiam Girdwood * return. 2826414c70cbSLiam Girdwood */ 2827414c70cbSLiam Girdwood int regulator_bulk_enable(int num_consumers, 2828414c70cbSLiam Girdwood struct regulator_bulk_data *consumers) 2829414c70cbSLiam Girdwood { 2830f21e0e81SMark Brown LIST_HEAD(async_domain); 2831414c70cbSLiam Girdwood int i; 2832f21e0e81SMark Brown int ret = 0; 2833414c70cbSLiam Girdwood 28346492bc1bSMark Brown for (i = 0; i < num_consumers; i++) { 28356492bc1bSMark Brown if (consumers[i].consumer->always_on) 28366492bc1bSMark Brown consumers[i].ret = 0; 28376492bc1bSMark Brown else 2838f21e0e81SMark Brown async_schedule_domain(regulator_bulk_enable_async, 2839f21e0e81SMark Brown &consumers[i], &async_domain); 28406492bc1bSMark Brown } 2841f21e0e81SMark Brown 2842f21e0e81SMark Brown async_synchronize_full_domain(&async_domain); 2843f21e0e81SMark Brown 2844f21e0e81SMark Brown /* If any consumer failed we need to unwind any that succeeded */ 2845414c70cbSLiam Girdwood for (i = 0; i < num_consumers; i++) { 2846f21e0e81SMark Brown if (consumers[i].ret != 0) { 2847f21e0e81SMark Brown ret = consumers[i].ret; 2848414c70cbSLiam Girdwood goto err; 2849414c70cbSLiam Girdwood } 2850f21e0e81SMark Brown } 2851414c70cbSLiam Girdwood 2852414c70cbSLiam Girdwood return 0; 2853414c70cbSLiam Girdwood 2854414c70cbSLiam Girdwood err: 2855b29c7690SAxel Lin pr_err("Failed to enable %s: %d\n", consumers[i].supply, ret); 2856b29c7690SAxel Lin while (--i >= 0) 2857414c70cbSLiam Girdwood regulator_disable(consumers[i].consumer); 2858414c70cbSLiam Girdwood 2859414c70cbSLiam Girdwood return ret; 2860414c70cbSLiam Girdwood } 2861414c70cbSLiam Girdwood EXPORT_SYMBOL_GPL(regulator_bulk_enable); 2862414c70cbSLiam Girdwood 2863414c70cbSLiam Girdwood /** 2864414c70cbSLiam Girdwood * regulator_bulk_disable - disable multiple regulator consumers 2865414c70cbSLiam Girdwood * 2866414c70cbSLiam Girdwood * @num_consumers: Number of consumers 2867414c70cbSLiam Girdwood * @consumers: Consumer data; clients are stored here. 2868414c70cbSLiam Girdwood * @return 0 on success, an errno on failure 2869414c70cbSLiam Girdwood * 2870414c70cbSLiam Girdwood * This convenience API allows consumers to disable multiple regulator 287149e22632SSylwester Nawrocki * clients in a single API call. If any consumers cannot be disabled 287249e22632SSylwester Nawrocki * then any others that were disabled will be enabled again prior to 2873414c70cbSLiam Girdwood * return. 2874414c70cbSLiam Girdwood */ 2875414c70cbSLiam Girdwood int regulator_bulk_disable(int num_consumers, 2876414c70cbSLiam Girdwood struct regulator_bulk_data *consumers) 2877414c70cbSLiam Girdwood { 2878414c70cbSLiam Girdwood int i; 287901e86f49SMark Brown int ret, r; 2880414c70cbSLiam Girdwood 288149e22632SSylwester Nawrocki for (i = num_consumers - 1; i >= 0; --i) { 2882414c70cbSLiam Girdwood ret = regulator_disable(consumers[i].consumer); 2883414c70cbSLiam Girdwood if (ret != 0) 2884414c70cbSLiam Girdwood goto err; 2885414c70cbSLiam Girdwood } 2886414c70cbSLiam Girdwood 2887414c70cbSLiam Girdwood return 0; 2888414c70cbSLiam Girdwood 2889414c70cbSLiam Girdwood err: 28905da84fd9SJoe Perches pr_err("Failed to disable %s: %d\n", consumers[i].supply, ret); 289101e86f49SMark Brown for (++i; i < num_consumers; ++i) { 289201e86f49SMark Brown r = regulator_enable(consumers[i].consumer); 289301e86f49SMark Brown if (r != 0) 289401e86f49SMark Brown pr_err("Failed to reename %s: %d\n", 289501e86f49SMark Brown consumers[i].supply, r); 289601e86f49SMark Brown } 2897414c70cbSLiam Girdwood 2898414c70cbSLiam Girdwood return ret; 2899414c70cbSLiam Girdwood } 2900414c70cbSLiam Girdwood EXPORT_SYMBOL_GPL(regulator_bulk_disable); 2901414c70cbSLiam Girdwood 2902414c70cbSLiam Girdwood /** 2903e1de2f42SDonggeun Kim * regulator_bulk_force_disable - force disable multiple regulator consumers 2904e1de2f42SDonggeun Kim * 2905e1de2f42SDonggeun Kim * @num_consumers: Number of consumers 2906e1de2f42SDonggeun Kim * @consumers: Consumer data; clients are stored here. 2907e1de2f42SDonggeun Kim * @return 0 on success, an errno on failure 2908e1de2f42SDonggeun Kim * 2909e1de2f42SDonggeun Kim * This convenience API allows consumers to forcibly disable multiple regulator 2910e1de2f42SDonggeun Kim * clients in a single API call. 2911e1de2f42SDonggeun Kim * NOTE: This should be used for situations when device damage will 2912e1de2f42SDonggeun Kim * likely occur if the regulators are not disabled (e.g. over temp). 2913e1de2f42SDonggeun Kim * Although regulator_force_disable function call for some consumers can 2914e1de2f42SDonggeun Kim * return error numbers, the function is called for all consumers. 2915e1de2f42SDonggeun Kim */ 2916e1de2f42SDonggeun Kim int regulator_bulk_force_disable(int num_consumers, 2917e1de2f42SDonggeun Kim struct regulator_bulk_data *consumers) 2918e1de2f42SDonggeun Kim { 2919e1de2f42SDonggeun Kim int i; 2920e1de2f42SDonggeun Kim int ret; 2921e1de2f42SDonggeun Kim 2922e1de2f42SDonggeun Kim for (i = 0; i < num_consumers; i++) 2923e1de2f42SDonggeun Kim consumers[i].ret = 2924e1de2f42SDonggeun Kim regulator_force_disable(consumers[i].consumer); 2925e1de2f42SDonggeun Kim 2926e1de2f42SDonggeun Kim for (i = 0; i < num_consumers; i++) { 2927e1de2f42SDonggeun Kim if (consumers[i].ret != 0) { 2928e1de2f42SDonggeun Kim ret = consumers[i].ret; 2929e1de2f42SDonggeun Kim goto out; 2930e1de2f42SDonggeun Kim } 2931e1de2f42SDonggeun Kim } 2932e1de2f42SDonggeun Kim 2933e1de2f42SDonggeun Kim return 0; 2934e1de2f42SDonggeun Kim out: 2935e1de2f42SDonggeun Kim return ret; 2936e1de2f42SDonggeun Kim } 2937e1de2f42SDonggeun Kim EXPORT_SYMBOL_GPL(regulator_bulk_force_disable); 2938e1de2f42SDonggeun Kim 2939e1de2f42SDonggeun Kim /** 2940414c70cbSLiam Girdwood * regulator_bulk_free - free multiple regulator consumers 2941414c70cbSLiam Girdwood * 2942414c70cbSLiam Girdwood * @num_consumers: Number of consumers 2943414c70cbSLiam Girdwood * @consumers: Consumer data; clients are stored here. 2944414c70cbSLiam Girdwood * 2945414c70cbSLiam Girdwood * This convenience API allows consumers to free multiple regulator 2946414c70cbSLiam Girdwood * clients in a single API call. 2947414c70cbSLiam Girdwood */ 2948414c70cbSLiam Girdwood void regulator_bulk_free(int num_consumers, 2949414c70cbSLiam Girdwood struct regulator_bulk_data *consumers) 2950414c70cbSLiam Girdwood { 2951414c70cbSLiam Girdwood int i; 2952414c70cbSLiam Girdwood 2953414c70cbSLiam Girdwood for (i = 0; i < num_consumers; i++) { 2954414c70cbSLiam Girdwood regulator_put(consumers[i].consumer); 2955414c70cbSLiam Girdwood consumers[i].consumer = NULL; 2956414c70cbSLiam Girdwood } 2957414c70cbSLiam Girdwood } 2958414c70cbSLiam Girdwood EXPORT_SYMBOL_GPL(regulator_bulk_free); 2959414c70cbSLiam Girdwood 2960414c70cbSLiam Girdwood /** 2961414c70cbSLiam Girdwood * regulator_notifier_call_chain - call regulator event notifier 296269279fb9SMark Brown * @rdev: regulator source 2963414c70cbSLiam Girdwood * @event: notifier block 296469279fb9SMark Brown * @data: callback-specific data. 2965414c70cbSLiam Girdwood * 2966414c70cbSLiam Girdwood * Called by regulator drivers to notify clients a regulator event has 2967414c70cbSLiam Girdwood * occurred. We also notify regulator clients downstream. 2968b136fb44SJonathan Cameron * Note lock must be held by caller. 2969414c70cbSLiam Girdwood */ 2970414c70cbSLiam Girdwood int regulator_notifier_call_chain(struct regulator_dev *rdev, 2971414c70cbSLiam Girdwood unsigned long event, void *data) 2972414c70cbSLiam Girdwood { 2973414c70cbSLiam Girdwood _notifier_call_chain(rdev, event, data); 2974414c70cbSLiam Girdwood return NOTIFY_DONE; 2975414c70cbSLiam Girdwood 2976414c70cbSLiam Girdwood } 2977414c70cbSLiam Girdwood EXPORT_SYMBOL_GPL(regulator_notifier_call_chain); 2978414c70cbSLiam Girdwood 2979be721979SMark Brown /** 2980be721979SMark Brown * regulator_mode_to_status - convert a regulator mode into a status 2981be721979SMark Brown * 2982be721979SMark Brown * @mode: Mode to convert 2983be721979SMark Brown * 2984be721979SMark Brown * Convert a regulator mode into a status. 2985be721979SMark Brown */ 2986be721979SMark Brown int regulator_mode_to_status(unsigned int mode) 2987be721979SMark Brown { 2988be721979SMark Brown switch (mode) { 2989be721979SMark Brown case REGULATOR_MODE_FAST: 2990be721979SMark Brown return REGULATOR_STATUS_FAST; 2991be721979SMark Brown case REGULATOR_MODE_NORMAL: 2992be721979SMark Brown return REGULATOR_STATUS_NORMAL; 2993be721979SMark Brown case REGULATOR_MODE_IDLE: 2994be721979SMark Brown return REGULATOR_STATUS_IDLE; 2995be721979SMark Brown case REGULATOR_STATUS_STANDBY: 2996be721979SMark Brown return REGULATOR_STATUS_STANDBY; 2997be721979SMark Brown default: 2998be721979SMark Brown return 0; 2999be721979SMark Brown } 3000be721979SMark Brown } 3001be721979SMark Brown EXPORT_SYMBOL_GPL(regulator_mode_to_status); 3002be721979SMark Brown 30037ad68e2fSDavid Brownell /* 30047ad68e2fSDavid Brownell * To avoid cluttering sysfs (and memory) with useless state, only 30057ad68e2fSDavid Brownell * create attributes that can be meaningfully displayed. 30067ad68e2fSDavid Brownell */ 30077ad68e2fSDavid Brownell static int add_regulator_attributes(struct regulator_dev *rdev) 30087ad68e2fSDavid Brownell { 30097ad68e2fSDavid Brownell struct device *dev = &rdev->dev; 30107ad68e2fSDavid Brownell struct regulator_ops *ops = rdev->desc->ops; 30117ad68e2fSDavid Brownell int status = 0; 30127ad68e2fSDavid Brownell 30137ad68e2fSDavid Brownell /* some attributes need specific methods to be displayed */ 30144c78899bSMark Brown if ((ops->get_voltage && ops->get_voltage(rdev) >= 0) || 30154c78899bSMark Brown (ops->get_voltage_sel && ops->get_voltage_sel(rdev) >= 0)) { 30167ad68e2fSDavid Brownell status = device_create_file(dev, &dev_attr_microvolts); 30177ad68e2fSDavid Brownell if (status < 0) 30187ad68e2fSDavid Brownell return status; 30197ad68e2fSDavid Brownell } 30207ad68e2fSDavid Brownell if (ops->get_current_limit) { 30217ad68e2fSDavid Brownell status = device_create_file(dev, &dev_attr_microamps); 30227ad68e2fSDavid Brownell if (status < 0) 30237ad68e2fSDavid Brownell return status; 30247ad68e2fSDavid Brownell } 30257ad68e2fSDavid Brownell if (ops->get_mode) { 30267ad68e2fSDavid Brownell status = device_create_file(dev, &dev_attr_opmode); 30277ad68e2fSDavid Brownell if (status < 0) 30287ad68e2fSDavid Brownell return status; 30297ad68e2fSDavid Brownell } 30307ad68e2fSDavid Brownell if (ops->is_enabled) { 30317ad68e2fSDavid Brownell status = device_create_file(dev, &dev_attr_state); 30327ad68e2fSDavid Brownell if (status < 0) 30337ad68e2fSDavid Brownell return status; 30347ad68e2fSDavid Brownell } 3035853116a1SDavid Brownell if (ops->get_status) { 3036853116a1SDavid Brownell status = device_create_file(dev, &dev_attr_status); 3037853116a1SDavid Brownell if (status < 0) 3038853116a1SDavid Brownell return status; 3039853116a1SDavid Brownell } 30407ad68e2fSDavid Brownell 30417ad68e2fSDavid Brownell /* some attributes are type-specific */ 30427ad68e2fSDavid Brownell if (rdev->desc->type == REGULATOR_CURRENT) { 30437ad68e2fSDavid Brownell status = device_create_file(dev, &dev_attr_requested_microamps); 30447ad68e2fSDavid Brownell if (status < 0) 30457ad68e2fSDavid Brownell return status; 30467ad68e2fSDavid Brownell } 30477ad68e2fSDavid Brownell 30487ad68e2fSDavid Brownell /* all the other attributes exist to support constraints; 30497ad68e2fSDavid Brownell * don't show them if there are no constraints, or if the 30507ad68e2fSDavid Brownell * relevant supporting methods are missing. 30517ad68e2fSDavid Brownell */ 30527ad68e2fSDavid Brownell if (!rdev->constraints) 30537ad68e2fSDavid Brownell return status; 30547ad68e2fSDavid Brownell 30557ad68e2fSDavid Brownell /* constraints need specific supporting methods */ 3056e8eef82bSMark Brown if (ops->set_voltage || ops->set_voltage_sel) { 30577ad68e2fSDavid Brownell status = device_create_file(dev, &dev_attr_min_microvolts); 30587ad68e2fSDavid Brownell if (status < 0) 30597ad68e2fSDavid Brownell return status; 30607ad68e2fSDavid Brownell status = device_create_file(dev, &dev_attr_max_microvolts); 30617ad68e2fSDavid Brownell if (status < 0) 30627ad68e2fSDavid Brownell return status; 30637ad68e2fSDavid Brownell } 30647ad68e2fSDavid Brownell if (ops->set_current_limit) { 30657ad68e2fSDavid Brownell status = device_create_file(dev, &dev_attr_min_microamps); 30667ad68e2fSDavid Brownell if (status < 0) 30677ad68e2fSDavid Brownell return status; 30687ad68e2fSDavid Brownell status = device_create_file(dev, &dev_attr_max_microamps); 30697ad68e2fSDavid Brownell if (status < 0) 30707ad68e2fSDavid Brownell return status; 30717ad68e2fSDavid Brownell } 30727ad68e2fSDavid Brownell 30737ad68e2fSDavid Brownell status = device_create_file(dev, &dev_attr_suspend_standby_state); 30747ad68e2fSDavid Brownell if (status < 0) 30757ad68e2fSDavid Brownell return status; 30767ad68e2fSDavid Brownell status = device_create_file(dev, &dev_attr_suspend_mem_state); 30777ad68e2fSDavid Brownell if (status < 0) 30787ad68e2fSDavid Brownell return status; 30797ad68e2fSDavid Brownell status = device_create_file(dev, &dev_attr_suspend_disk_state); 30807ad68e2fSDavid Brownell if (status < 0) 30817ad68e2fSDavid Brownell return status; 30827ad68e2fSDavid Brownell 30837ad68e2fSDavid Brownell if (ops->set_suspend_voltage) { 30847ad68e2fSDavid Brownell status = device_create_file(dev, 30857ad68e2fSDavid Brownell &dev_attr_suspend_standby_microvolts); 30867ad68e2fSDavid Brownell if (status < 0) 30877ad68e2fSDavid Brownell return status; 30887ad68e2fSDavid Brownell status = device_create_file(dev, 30897ad68e2fSDavid Brownell &dev_attr_suspend_mem_microvolts); 30907ad68e2fSDavid Brownell if (status < 0) 30917ad68e2fSDavid Brownell return status; 30927ad68e2fSDavid Brownell status = device_create_file(dev, 30937ad68e2fSDavid Brownell &dev_attr_suspend_disk_microvolts); 30947ad68e2fSDavid Brownell if (status < 0) 30957ad68e2fSDavid Brownell return status; 30967ad68e2fSDavid Brownell } 30977ad68e2fSDavid Brownell 30987ad68e2fSDavid Brownell if (ops->set_suspend_mode) { 30997ad68e2fSDavid Brownell status = device_create_file(dev, 31007ad68e2fSDavid Brownell &dev_attr_suspend_standby_mode); 31017ad68e2fSDavid Brownell if (status < 0) 31027ad68e2fSDavid Brownell return status; 31037ad68e2fSDavid Brownell status = device_create_file(dev, 31047ad68e2fSDavid Brownell &dev_attr_suspend_mem_mode); 31057ad68e2fSDavid Brownell if (status < 0) 31067ad68e2fSDavid Brownell return status; 31077ad68e2fSDavid Brownell status = device_create_file(dev, 31087ad68e2fSDavid Brownell &dev_attr_suspend_disk_mode); 31097ad68e2fSDavid Brownell if (status < 0) 31107ad68e2fSDavid Brownell return status; 31117ad68e2fSDavid Brownell } 31127ad68e2fSDavid Brownell 31137ad68e2fSDavid Brownell return status; 31147ad68e2fSDavid Brownell } 31157ad68e2fSDavid Brownell 31161130e5b3SMark Brown static void rdev_init_debugfs(struct regulator_dev *rdev) 31171130e5b3SMark Brown { 31181130e5b3SMark Brown rdev->debugfs = debugfs_create_dir(rdev_get_name(rdev), debugfs_root); 311924751434SStephen Boyd if (!rdev->debugfs) { 31201130e5b3SMark Brown rdev_warn(rdev, "Failed to create debugfs directory\n"); 31211130e5b3SMark Brown return; 31221130e5b3SMark Brown } 31231130e5b3SMark Brown 31241130e5b3SMark Brown debugfs_create_u32("use_count", 0444, rdev->debugfs, 31251130e5b3SMark Brown &rdev->use_count); 31261130e5b3SMark Brown debugfs_create_u32("open_count", 0444, rdev->debugfs, 31271130e5b3SMark Brown &rdev->open_count); 31281130e5b3SMark Brown } 31291130e5b3SMark Brown 3130414c70cbSLiam Girdwood /** 3131414c70cbSLiam Girdwood * regulator_register - register regulator 313269279fb9SMark Brown * @regulator_desc: regulator to register 3133c172708dSMark Brown * @config: runtime configuration for regulator 3134414c70cbSLiam Girdwood * 3135414c70cbSLiam Girdwood * Called by regulator drivers to register a regulator. 3136414c70cbSLiam Girdwood * Returns 0 on success. 3137414c70cbSLiam Girdwood */ 313865f26846SMark Brown struct regulator_dev * 313965f26846SMark Brown regulator_register(const struct regulator_desc *regulator_desc, 3140c172708dSMark Brown const struct regulator_config *config) 3141414c70cbSLiam Girdwood { 31429a8f5e07SMark Brown const struct regulation_constraints *constraints = NULL; 3143c172708dSMark Brown const struct regulator_init_data *init_data; 3144414c70cbSLiam Girdwood static atomic_t regulator_no = ATOMIC_INIT(0); 3145414c70cbSLiam Girdwood struct regulator_dev *rdev; 314632c8fad4SMark Brown struct device *dev; 3147a5766f11SLiam Girdwood int ret, i; 314869511a45SRajendra Nayak const char *supply = NULL; 3149414c70cbSLiam Girdwood 3150c172708dSMark Brown if (regulator_desc == NULL || config == NULL) 3151414c70cbSLiam Girdwood return ERR_PTR(-EINVAL); 3152414c70cbSLiam Girdwood 315332c8fad4SMark Brown dev = config->dev; 3154dcf70112SMark Brown WARN_ON(!dev); 315532c8fad4SMark Brown 3156414c70cbSLiam Girdwood if (regulator_desc->name == NULL || regulator_desc->ops == NULL) 3157414c70cbSLiam Girdwood return ERR_PTR(-EINVAL); 3158414c70cbSLiam Girdwood 3159cd78dfc6SDiego Liziero if (regulator_desc->type != REGULATOR_VOLTAGE && 3160cd78dfc6SDiego Liziero regulator_desc->type != REGULATOR_CURRENT) 3161414c70cbSLiam Girdwood return ERR_PTR(-EINVAL); 3162414c70cbSLiam Girdwood 3163476c2d83SMark Brown /* Only one of each should be implemented */ 3164476c2d83SMark Brown WARN_ON(regulator_desc->ops->get_voltage && 3165476c2d83SMark Brown regulator_desc->ops->get_voltage_sel); 3166e8eef82bSMark Brown WARN_ON(regulator_desc->ops->set_voltage && 3167e8eef82bSMark Brown regulator_desc->ops->set_voltage_sel); 3168476c2d83SMark Brown 3169476c2d83SMark Brown /* If we're using selectors we must implement list_voltage. */ 3170476c2d83SMark Brown if (regulator_desc->ops->get_voltage_sel && 3171476c2d83SMark Brown !regulator_desc->ops->list_voltage) { 3172476c2d83SMark Brown return ERR_PTR(-EINVAL); 3173476c2d83SMark Brown } 3174e8eef82bSMark Brown if (regulator_desc->ops->set_voltage_sel && 3175e8eef82bSMark Brown !regulator_desc->ops->list_voltage) { 3176e8eef82bSMark Brown return ERR_PTR(-EINVAL); 3177e8eef82bSMark Brown } 3178476c2d83SMark Brown 3179c172708dSMark Brown init_data = config->init_data; 3180c172708dSMark Brown 3181414c70cbSLiam Girdwood rdev = kzalloc(sizeof(struct regulator_dev), GFP_KERNEL); 3182414c70cbSLiam Girdwood if (rdev == NULL) 3183414c70cbSLiam Girdwood return ERR_PTR(-ENOMEM); 3184414c70cbSLiam Girdwood 3185414c70cbSLiam Girdwood mutex_lock(®ulator_list_mutex); 3186414c70cbSLiam Girdwood 3187414c70cbSLiam Girdwood mutex_init(&rdev->mutex); 3188c172708dSMark Brown rdev->reg_data = config->driver_data; 3189414c70cbSLiam Girdwood rdev->owner = regulator_desc->owner; 3190414c70cbSLiam Girdwood rdev->desc = regulator_desc; 31913a4b0a07SMark Brown if (config->regmap) 319265b19ce6SMark Brown rdev->regmap = config->regmap; 31933a4b0a07SMark Brown else 31943a4b0a07SMark Brown rdev->regmap = dev_get_regmap(dev, NULL); 3195414c70cbSLiam Girdwood INIT_LIST_HEAD(&rdev->consumer_list); 3196414c70cbSLiam Girdwood INIT_LIST_HEAD(&rdev->list); 3197414c70cbSLiam Girdwood BLOCKING_INIT_NOTIFIER_HEAD(&rdev->notifier); 3198da07ecd9SMark Brown INIT_DELAYED_WORK(&rdev->disable_work, regulator_disable_work); 3199414c70cbSLiam Girdwood 3200a5766f11SLiam Girdwood /* preform any regulator specific init */ 32019a8f5e07SMark Brown if (init_data && init_data->regulator_init) { 3202a5766f11SLiam Girdwood ret = init_data->regulator_init(rdev->reg_data); 32034fca9545SDavid Brownell if (ret < 0) 32044fca9545SDavid Brownell goto clean; 3205a5766f11SLiam Girdwood } 3206a5766f11SLiam Girdwood 3207a5766f11SLiam Girdwood /* register with sysfs */ 3208a5766f11SLiam Girdwood rdev->dev.class = ®ulator_class; 3209c172708dSMark Brown rdev->dev.of_node = config->of_node; 3210a5766f11SLiam Girdwood rdev->dev.parent = dev; 3211812460a9SKay Sievers dev_set_name(&rdev->dev, "regulator.%d", 3212812460a9SKay Sievers atomic_inc_return(®ulator_no) - 1); 3213a5766f11SLiam Girdwood ret = device_register(&rdev->dev); 3214ad7725cbSVasiliy Kulikov if (ret != 0) { 3215ad7725cbSVasiliy Kulikov put_device(&rdev->dev); 32164fca9545SDavid Brownell goto clean; 3217ad7725cbSVasiliy Kulikov } 3218a5766f11SLiam Girdwood 3219a5766f11SLiam Girdwood dev_set_drvdata(&rdev->dev, rdev); 3220a5766f11SLiam Girdwood 322174f544c1SMike Rapoport /* set regulator constraints */ 32229a8f5e07SMark Brown if (init_data) 32239a8f5e07SMark Brown constraints = &init_data->constraints; 32249a8f5e07SMark Brown 32259a8f5e07SMark Brown ret = set_machine_constraints(rdev, constraints); 322674f544c1SMike Rapoport if (ret < 0) 322774f544c1SMike Rapoport goto scrub; 322874f544c1SMike Rapoport 32297ad68e2fSDavid Brownell /* add attributes supported by this regulator */ 32307ad68e2fSDavid Brownell ret = add_regulator_attributes(rdev); 32317ad68e2fSDavid Brownell if (ret < 0) 32327ad68e2fSDavid Brownell goto scrub; 32337ad68e2fSDavid Brownell 32349a8f5e07SMark Brown if (init_data && init_data->supply_regulator) 323569511a45SRajendra Nayak supply = init_data->supply_regulator; 323669511a45SRajendra Nayak else if (regulator_desc->supply_name) 323769511a45SRajendra Nayak supply = regulator_desc->supply_name; 323869511a45SRajendra Nayak 323969511a45SRajendra Nayak if (supply) { 32400178f3e2SMark Brown struct regulator_dev *r; 32410178f3e2SMark Brown 32426d191a5fSMark Brown r = regulator_dev_lookup(dev, supply, &ret); 32430178f3e2SMark Brown 324469511a45SRajendra Nayak if (!r) { 324569511a45SRajendra Nayak dev_err(dev, "Failed to find supply %s\n", supply); 324604bf3011SMark Brown ret = -EPROBE_DEFER; 32470178f3e2SMark Brown goto scrub; 32480178f3e2SMark Brown } 32490178f3e2SMark Brown 32500178f3e2SMark Brown ret = set_supply(rdev, r); 32510178f3e2SMark Brown if (ret < 0) 32520178f3e2SMark Brown goto scrub; 3253b2296bd4SLaxman Dewangan 3254b2296bd4SLaxman Dewangan /* Enable supply if rail is enabled */ 3255b1a86831SMark Brown if (_regulator_is_enabled(rdev)) { 3256b2296bd4SLaxman Dewangan ret = regulator_enable(rdev->supply); 3257b2296bd4SLaxman Dewangan if (ret < 0) 3258b2296bd4SLaxman Dewangan goto scrub; 3259b2296bd4SLaxman Dewangan } 32600178f3e2SMark Brown } 32610178f3e2SMark Brown 3262a5766f11SLiam Girdwood /* add consumers devices */ 32639a8f5e07SMark Brown if (init_data) { 3264a5766f11SLiam Girdwood for (i = 0; i < init_data->num_consumer_supplies; i++) { 3265a5766f11SLiam Girdwood ret = set_consumer_device_supply(rdev, 326640f9244fSMark Brown init_data->consumer_supplies[i].dev_name, 3267a5766f11SLiam Girdwood init_data->consumer_supplies[i].supply); 326823c2f041SMark Brown if (ret < 0) { 326923c2f041SMark Brown dev_err(dev, "Failed to set supply %s\n", 327023c2f041SMark Brown init_data->consumer_supplies[i].supply); 3271d4033b54SJani Nikula goto unset_supplies; 3272a5766f11SLiam Girdwood } 327323c2f041SMark Brown } 32749a8f5e07SMark Brown } 3275a5766f11SLiam Girdwood 3276a5766f11SLiam Girdwood list_add(&rdev->list, ®ulator_list); 32771130e5b3SMark Brown 32781130e5b3SMark Brown rdev_init_debugfs(rdev); 3279a5766f11SLiam Girdwood out: 3280414c70cbSLiam Girdwood mutex_unlock(®ulator_list_mutex); 3281414c70cbSLiam Girdwood return rdev; 32824fca9545SDavid Brownell 3283d4033b54SJani Nikula unset_supplies: 3284d4033b54SJani Nikula unset_regulator_supplies(rdev); 3285d4033b54SJani Nikula 32864fca9545SDavid Brownell scrub: 3287e81dba85SMark Brown if (rdev->supply) 3288e81dba85SMark Brown regulator_put(rdev->supply); 32891a6958e7SAxel Lin kfree(rdev->constraints); 32904fca9545SDavid Brownell device_unregister(&rdev->dev); 329153032dafSPaul Walmsley /* device core frees rdev */ 329253032dafSPaul Walmsley rdev = ERR_PTR(ret); 329353032dafSPaul Walmsley goto out; 329453032dafSPaul Walmsley 32954fca9545SDavid Brownell clean: 32964fca9545SDavid Brownell kfree(rdev); 32974fca9545SDavid Brownell rdev = ERR_PTR(ret); 32984fca9545SDavid Brownell goto out; 3299414c70cbSLiam Girdwood } 3300414c70cbSLiam Girdwood EXPORT_SYMBOL_GPL(regulator_register); 3301414c70cbSLiam Girdwood 3302414c70cbSLiam Girdwood /** 3303414c70cbSLiam Girdwood * regulator_unregister - unregister regulator 330469279fb9SMark Brown * @rdev: regulator to unregister 3305414c70cbSLiam Girdwood * 3306414c70cbSLiam Girdwood * Called by regulator drivers to unregister a regulator. 3307414c70cbSLiam Girdwood */ 3308414c70cbSLiam Girdwood void regulator_unregister(struct regulator_dev *rdev) 3309414c70cbSLiam Girdwood { 3310414c70cbSLiam Girdwood if (rdev == NULL) 3311414c70cbSLiam Girdwood return; 3312414c70cbSLiam Girdwood 3313e032b376SMark Brown if (rdev->supply) 3314e032b376SMark Brown regulator_put(rdev->supply); 3315414c70cbSLiam Girdwood mutex_lock(®ulator_list_mutex); 33161130e5b3SMark Brown debugfs_remove_recursive(rdev->debugfs); 3317da07ecd9SMark Brown flush_work_sync(&rdev->disable_work.work); 33186bf87d17SMark Brown WARN_ON(rdev->open_count); 33190f1d747bSMike Rapoport unset_regulator_supplies(rdev); 3320414c70cbSLiam Girdwood list_del(&rdev->list); 3321f8c12fe3SMark Brown kfree(rdev->constraints); 332258fb5cf5SLothar Waßmann device_unregister(&rdev->dev); 3323414c70cbSLiam Girdwood mutex_unlock(®ulator_list_mutex); 3324414c70cbSLiam Girdwood } 3325414c70cbSLiam Girdwood EXPORT_SYMBOL_GPL(regulator_unregister); 3326414c70cbSLiam Girdwood 3327414c70cbSLiam Girdwood /** 3328cf7bbcdfSMark Brown * regulator_suspend_prepare - prepare regulators for system wide suspend 3329414c70cbSLiam Girdwood * @state: system suspend state 3330414c70cbSLiam Girdwood * 3331414c70cbSLiam Girdwood * Configure each regulator with it's suspend operating parameters for state. 3332414c70cbSLiam Girdwood * This will usually be called by machine suspend code prior to supending. 3333414c70cbSLiam Girdwood */ 3334414c70cbSLiam Girdwood int regulator_suspend_prepare(suspend_state_t state) 3335414c70cbSLiam Girdwood { 3336414c70cbSLiam Girdwood struct regulator_dev *rdev; 3337414c70cbSLiam Girdwood int ret = 0; 3338414c70cbSLiam Girdwood 3339414c70cbSLiam Girdwood /* ON is handled by regulator active state */ 3340414c70cbSLiam Girdwood if (state == PM_SUSPEND_ON) 3341414c70cbSLiam Girdwood return -EINVAL; 3342414c70cbSLiam Girdwood 3343414c70cbSLiam Girdwood mutex_lock(®ulator_list_mutex); 3344414c70cbSLiam Girdwood list_for_each_entry(rdev, ®ulator_list, list) { 3345414c70cbSLiam Girdwood 3346414c70cbSLiam Girdwood mutex_lock(&rdev->mutex); 3347414c70cbSLiam Girdwood ret = suspend_prepare(rdev, state); 3348414c70cbSLiam Girdwood mutex_unlock(&rdev->mutex); 3349414c70cbSLiam Girdwood 3350414c70cbSLiam Girdwood if (ret < 0) { 33515da84fd9SJoe Perches rdev_err(rdev, "failed to prepare\n"); 3352414c70cbSLiam Girdwood goto out; 3353414c70cbSLiam Girdwood } 3354414c70cbSLiam Girdwood } 3355414c70cbSLiam Girdwood out: 3356414c70cbSLiam Girdwood mutex_unlock(®ulator_list_mutex); 3357414c70cbSLiam Girdwood return ret; 3358414c70cbSLiam Girdwood } 3359414c70cbSLiam Girdwood EXPORT_SYMBOL_GPL(regulator_suspend_prepare); 3360414c70cbSLiam Girdwood 3361414c70cbSLiam Girdwood /** 33627a32b589SMyungJoo Ham * regulator_suspend_finish - resume regulators from system wide suspend 33637a32b589SMyungJoo Ham * 33647a32b589SMyungJoo Ham * Turn on regulators that might be turned off by regulator_suspend_prepare 33657a32b589SMyungJoo Ham * and that should be turned on according to the regulators properties. 33667a32b589SMyungJoo Ham */ 33677a32b589SMyungJoo Ham int regulator_suspend_finish(void) 33687a32b589SMyungJoo Ham { 33697a32b589SMyungJoo Ham struct regulator_dev *rdev; 33707a32b589SMyungJoo Ham int ret = 0, error; 33717a32b589SMyungJoo Ham 33727a32b589SMyungJoo Ham mutex_lock(®ulator_list_mutex); 33737a32b589SMyungJoo Ham list_for_each_entry(rdev, ®ulator_list, list) { 33747a32b589SMyungJoo Ham struct regulator_ops *ops = rdev->desc->ops; 33757a32b589SMyungJoo Ham 33767a32b589SMyungJoo Ham mutex_lock(&rdev->mutex); 33777a32b589SMyungJoo Ham if ((rdev->use_count > 0 || rdev->constraints->always_on) && 33787a32b589SMyungJoo Ham ops->enable) { 33797a32b589SMyungJoo Ham error = ops->enable(rdev); 33807a32b589SMyungJoo Ham if (error) 33817a32b589SMyungJoo Ham ret = error; 33827a32b589SMyungJoo Ham } else { 33837a32b589SMyungJoo Ham if (!has_full_constraints) 33847a32b589SMyungJoo Ham goto unlock; 33857a32b589SMyungJoo Ham if (!ops->disable) 33867a32b589SMyungJoo Ham goto unlock; 3387b1a86831SMark Brown if (!_regulator_is_enabled(rdev)) 33887a32b589SMyungJoo Ham goto unlock; 33897a32b589SMyungJoo Ham 33907a32b589SMyungJoo Ham error = ops->disable(rdev); 33917a32b589SMyungJoo Ham if (error) 33927a32b589SMyungJoo Ham ret = error; 33937a32b589SMyungJoo Ham } 33947a32b589SMyungJoo Ham unlock: 33957a32b589SMyungJoo Ham mutex_unlock(&rdev->mutex); 33967a32b589SMyungJoo Ham } 33977a32b589SMyungJoo Ham mutex_unlock(®ulator_list_mutex); 33987a32b589SMyungJoo Ham return ret; 33997a32b589SMyungJoo Ham } 34007a32b589SMyungJoo Ham EXPORT_SYMBOL_GPL(regulator_suspend_finish); 34017a32b589SMyungJoo Ham 34027a32b589SMyungJoo Ham /** 3403ca725561SMark Brown * regulator_has_full_constraints - the system has fully specified constraints 3404ca725561SMark Brown * 3405ca725561SMark Brown * Calling this function will cause the regulator API to disable all 3406ca725561SMark Brown * regulators which have a zero use count and don't have an always_on 3407ca725561SMark Brown * constraint in a late_initcall. 3408ca725561SMark Brown * 3409ca725561SMark Brown * The intention is that this will become the default behaviour in a 3410ca725561SMark Brown * future kernel release so users are encouraged to use this facility 3411ca725561SMark Brown * now. 3412ca725561SMark Brown */ 3413ca725561SMark Brown void regulator_has_full_constraints(void) 3414ca725561SMark Brown { 3415ca725561SMark Brown has_full_constraints = 1; 3416ca725561SMark Brown } 3417ca725561SMark Brown EXPORT_SYMBOL_GPL(regulator_has_full_constraints); 3418ca725561SMark Brown 3419ca725561SMark Brown /** 3420688fe99aSMark Brown * regulator_use_dummy_regulator - Provide a dummy regulator when none is found 3421688fe99aSMark Brown * 3422688fe99aSMark Brown * Calling this function will cause the regulator API to provide a 3423688fe99aSMark Brown * dummy regulator to consumers if no physical regulator is found, 3424688fe99aSMark Brown * allowing most consumers to proceed as though a regulator were 3425688fe99aSMark Brown * configured. This allows systems such as those with software 3426688fe99aSMark Brown * controllable regulators for the CPU core only to be brought up more 3427688fe99aSMark Brown * readily. 3428688fe99aSMark Brown */ 3429688fe99aSMark Brown void regulator_use_dummy_regulator(void) 3430688fe99aSMark Brown { 3431688fe99aSMark Brown board_wants_dummy_regulator = true; 3432688fe99aSMark Brown } 3433688fe99aSMark Brown EXPORT_SYMBOL_GPL(regulator_use_dummy_regulator); 3434688fe99aSMark Brown 3435688fe99aSMark Brown /** 3436414c70cbSLiam Girdwood * rdev_get_drvdata - get rdev regulator driver data 343769279fb9SMark Brown * @rdev: regulator 3438414c70cbSLiam Girdwood * 3439414c70cbSLiam Girdwood * Get rdev regulator driver private data. This call can be used in the 3440414c70cbSLiam Girdwood * regulator driver context. 3441414c70cbSLiam Girdwood */ 3442414c70cbSLiam Girdwood void *rdev_get_drvdata(struct regulator_dev *rdev) 3443414c70cbSLiam Girdwood { 3444414c70cbSLiam Girdwood return rdev->reg_data; 3445414c70cbSLiam Girdwood } 3446414c70cbSLiam Girdwood EXPORT_SYMBOL_GPL(rdev_get_drvdata); 3447414c70cbSLiam Girdwood 3448414c70cbSLiam Girdwood /** 3449414c70cbSLiam Girdwood * regulator_get_drvdata - get regulator driver data 3450414c70cbSLiam Girdwood * @regulator: regulator 3451414c70cbSLiam Girdwood * 3452414c70cbSLiam Girdwood * Get regulator driver private data. This call can be used in the consumer 3453414c70cbSLiam Girdwood * driver context when non API regulator specific functions need to be called. 3454414c70cbSLiam Girdwood */ 3455414c70cbSLiam Girdwood void *regulator_get_drvdata(struct regulator *regulator) 3456414c70cbSLiam Girdwood { 3457414c70cbSLiam Girdwood return regulator->rdev->reg_data; 3458414c70cbSLiam Girdwood } 3459414c70cbSLiam Girdwood EXPORT_SYMBOL_GPL(regulator_get_drvdata); 3460414c70cbSLiam Girdwood 3461414c70cbSLiam Girdwood /** 3462414c70cbSLiam Girdwood * regulator_set_drvdata - set regulator driver data 3463414c70cbSLiam Girdwood * @regulator: regulator 3464414c70cbSLiam Girdwood * @data: data 3465414c70cbSLiam Girdwood */ 3466414c70cbSLiam Girdwood void regulator_set_drvdata(struct regulator *regulator, void *data) 3467414c70cbSLiam Girdwood { 3468414c70cbSLiam Girdwood regulator->rdev->reg_data = data; 3469414c70cbSLiam Girdwood } 3470414c70cbSLiam Girdwood EXPORT_SYMBOL_GPL(regulator_set_drvdata); 3471414c70cbSLiam Girdwood 3472414c70cbSLiam Girdwood /** 3473414c70cbSLiam Girdwood * regulator_get_id - get regulator ID 347469279fb9SMark Brown * @rdev: regulator 3475414c70cbSLiam Girdwood */ 3476414c70cbSLiam Girdwood int rdev_get_id(struct regulator_dev *rdev) 3477414c70cbSLiam Girdwood { 3478414c70cbSLiam Girdwood return rdev->desc->id; 3479414c70cbSLiam Girdwood } 3480414c70cbSLiam Girdwood EXPORT_SYMBOL_GPL(rdev_get_id); 3481414c70cbSLiam Girdwood 3482a5766f11SLiam Girdwood struct device *rdev_get_dev(struct regulator_dev *rdev) 3483a5766f11SLiam Girdwood { 3484a5766f11SLiam Girdwood return &rdev->dev; 3485a5766f11SLiam Girdwood } 3486a5766f11SLiam Girdwood EXPORT_SYMBOL_GPL(rdev_get_dev); 3487a5766f11SLiam Girdwood 3488a5766f11SLiam Girdwood void *regulator_get_init_drvdata(struct regulator_init_data *reg_init_data) 3489a5766f11SLiam Girdwood { 3490a5766f11SLiam Girdwood return reg_init_data->driver_data; 3491a5766f11SLiam Girdwood } 3492a5766f11SLiam Girdwood EXPORT_SYMBOL_GPL(regulator_get_init_drvdata); 3493a5766f11SLiam Girdwood 3494ba55a974SMark Brown #ifdef CONFIG_DEBUG_FS 3495ba55a974SMark Brown static ssize_t supply_map_read_file(struct file *file, char __user *user_buf, 3496ba55a974SMark Brown size_t count, loff_t *ppos) 3497ba55a974SMark Brown { 3498ba55a974SMark Brown char *buf = kmalloc(PAGE_SIZE, GFP_KERNEL); 3499ba55a974SMark Brown ssize_t len, ret = 0; 3500ba55a974SMark Brown struct regulator_map *map; 3501ba55a974SMark Brown 3502ba55a974SMark Brown if (!buf) 3503ba55a974SMark Brown return -ENOMEM; 3504ba55a974SMark Brown 3505ba55a974SMark Brown list_for_each_entry(map, ®ulator_map_list, list) { 3506ba55a974SMark Brown len = snprintf(buf + ret, PAGE_SIZE - ret, 3507ba55a974SMark Brown "%s -> %s.%s\n", 3508ba55a974SMark Brown rdev_get_name(map->regulator), map->dev_name, 3509ba55a974SMark Brown map->supply); 3510ba55a974SMark Brown if (len >= 0) 3511ba55a974SMark Brown ret += len; 3512ba55a974SMark Brown if (ret > PAGE_SIZE) { 3513ba55a974SMark Brown ret = PAGE_SIZE; 3514ba55a974SMark Brown break; 3515ba55a974SMark Brown } 3516ba55a974SMark Brown } 3517ba55a974SMark Brown 3518ba55a974SMark Brown ret = simple_read_from_buffer(user_buf, count, ppos, buf, ret); 3519ba55a974SMark Brown 3520ba55a974SMark Brown kfree(buf); 3521ba55a974SMark Brown 3522ba55a974SMark Brown return ret; 3523ba55a974SMark Brown } 352424751434SStephen Boyd #endif 3525ba55a974SMark Brown 3526ba55a974SMark Brown static const struct file_operations supply_map_fops = { 352724751434SStephen Boyd #ifdef CONFIG_DEBUG_FS 3528ba55a974SMark Brown .read = supply_map_read_file, 3529ba55a974SMark Brown .llseek = default_llseek, 3530ba55a974SMark Brown #endif 353124751434SStephen Boyd }; 3532ba55a974SMark Brown 3533414c70cbSLiam Girdwood static int __init regulator_init(void) 3534414c70cbSLiam Girdwood { 353534abbd68SMark Brown int ret; 353634abbd68SMark Brown 353734abbd68SMark Brown ret = class_register(®ulator_class); 353834abbd68SMark Brown 35391130e5b3SMark Brown debugfs_root = debugfs_create_dir("regulator", NULL); 354024751434SStephen Boyd if (!debugfs_root) 35411130e5b3SMark Brown pr_warn("regulator: Failed to create debugfs directory\n"); 3542ba55a974SMark Brown 3543f4d562c6SMark Brown debugfs_create_file("supply_map", 0444, debugfs_root, NULL, 3544f4d562c6SMark Brown &supply_map_fops); 35451130e5b3SMark Brown 354634abbd68SMark Brown regulator_dummy_init(); 354734abbd68SMark Brown 354834abbd68SMark Brown return ret; 3549414c70cbSLiam Girdwood } 3550414c70cbSLiam Girdwood 3551414c70cbSLiam Girdwood /* init early to allow our consumers to complete system booting */ 3552414c70cbSLiam Girdwood core_initcall(regulator_init); 3553ca725561SMark Brown 3554ca725561SMark Brown static int __init regulator_init_complete(void) 3555ca725561SMark Brown { 3556ca725561SMark Brown struct regulator_dev *rdev; 3557ca725561SMark Brown struct regulator_ops *ops; 3558ca725561SMark Brown struct regulation_constraints *c; 3559ca725561SMark Brown int enabled, ret; 3560ca725561SMark Brown 3561ca725561SMark Brown mutex_lock(®ulator_list_mutex); 3562ca725561SMark Brown 3563ca725561SMark Brown /* If we have a full configuration then disable any regulators 3564ca725561SMark Brown * which are not in use or always_on. This will become the 3565ca725561SMark Brown * default behaviour in the future. 3566ca725561SMark Brown */ 3567ca725561SMark Brown list_for_each_entry(rdev, ®ulator_list, list) { 3568ca725561SMark Brown ops = rdev->desc->ops; 3569ca725561SMark Brown c = rdev->constraints; 3570ca725561SMark Brown 3571f25e0b4fSMark Brown if (!ops->disable || (c && c->always_on)) 3572ca725561SMark Brown continue; 3573ca725561SMark Brown 3574ca725561SMark Brown mutex_lock(&rdev->mutex); 3575ca725561SMark Brown 3576ca725561SMark Brown if (rdev->use_count) 3577ca725561SMark Brown goto unlock; 3578ca725561SMark Brown 3579ca725561SMark Brown /* If we can't read the status assume it's on. */ 3580ca725561SMark Brown if (ops->is_enabled) 3581ca725561SMark Brown enabled = ops->is_enabled(rdev); 3582ca725561SMark Brown else 3583ca725561SMark Brown enabled = 1; 3584ca725561SMark Brown 3585ca725561SMark Brown if (!enabled) 3586ca725561SMark Brown goto unlock; 3587ca725561SMark Brown 3588ca725561SMark Brown if (has_full_constraints) { 3589ca725561SMark Brown /* We log since this may kill the system if it 3590ca725561SMark Brown * goes wrong. */ 35915da84fd9SJoe Perches rdev_info(rdev, "disabling\n"); 3592ca725561SMark Brown ret = ops->disable(rdev); 3593ca725561SMark Brown if (ret != 0) { 35945da84fd9SJoe Perches rdev_err(rdev, "couldn't disable: %d\n", ret); 3595ca725561SMark Brown } 3596ca725561SMark Brown } else { 3597ca725561SMark Brown /* The intention is that in future we will 3598ca725561SMark Brown * assume that full constraints are provided 3599ca725561SMark Brown * so warn even if we aren't going to do 3600ca725561SMark Brown * anything here. 3601ca725561SMark Brown */ 36025da84fd9SJoe Perches rdev_warn(rdev, "incomplete constraints, leaving on\n"); 3603ca725561SMark Brown } 3604ca725561SMark Brown 3605ca725561SMark Brown unlock: 3606ca725561SMark Brown mutex_unlock(&rdev->mutex); 3607ca725561SMark Brown } 3608ca725561SMark Brown 3609ca725561SMark Brown mutex_unlock(®ulator_list_mutex); 3610ca725561SMark Brown 3611ca725561SMark Brown return 0; 3612ca725561SMark Brown } 3613ca725561SMark Brown late_initcall(regulator_init_complete); 3614