1414c70cbSLiam Girdwood /* 2414c70cbSLiam Girdwood * core.c -- Voltage/Current Regulator framework. 3414c70cbSLiam Girdwood * 4414c70cbSLiam Girdwood * Copyright 2007, 2008 Wolfson Microelectronics PLC. 5a5766f11SLiam Girdwood * Copyright 2008 SlimLogic Ltd. 6414c70cbSLiam Girdwood * 7a5766f11SLiam Girdwood * Author: Liam Girdwood <lrg@slimlogic.co.uk> 8414c70cbSLiam Girdwood * 9414c70cbSLiam Girdwood * This program is free software; you can redistribute it and/or modify it 10414c70cbSLiam Girdwood * under the terms of the GNU General Public License as published by the 11414c70cbSLiam Girdwood * Free Software Foundation; either version 2 of the License, or (at your 12414c70cbSLiam Girdwood * option) any later version. 13414c70cbSLiam Girdwood * 14414c70cbSLiam Girdwood */ 15414c70cbSLiam Girdwood 16414c70cbSLiam Girdwood #include <linux/kernel.h> 17414c70cbSLiam Girdwood #include <linux/init.h> 181130e5b3SMark Brown #include <linux/debugfs.h> 19414c70cbSLiam Girdwood #include <linux/device.h> 205a0e3ad6STejun Heo #include <linux/slab.h> 21f21e0e81SMark Brown #include <linux/async.h> 22414c70cbSLiam Girdwood #include <linux/err.h> 23414c70cbSLiam Girdwood #include <linux/mutex.h> 24414c70cbSLiam Girdwood #include <linux/suspend.h> 2531aae2beSMark Brown #include <linux/delay.h> 2665f73508SMark Brown #include <linux/gpio.h> 27778b28b4SRussell King #include <linux/gpio/consumer.h> 2869511a45SRajendra Nayak #include <linux/of.h> 2965b19ce6SMark Brown #include <linux/regmap.h> 3069511a45SRajendra Nayak #include <linux/regulator/of_regulator.h> 31414c70cbSLiam Girdwood #include <linux/regulator/consumer.h> 32414c70cbSLiam Girdwood #include <linux/regulator/driver.h> 33414c70cbSLiam Girdwood #include <linux/regulator/machine.h> 3465602c32SPaul Gortmaker #include <linux/module.h> 35414c70cbSLiam Girdwood 3602fa3ec0SMark Brown #define CREATE_TRACE_POINTS 3702fa3ec0SMark Brown #include <trace/events/regulator.h> 3802fa3ec0SMark Brown 3934abbd68SMark Brown #include "dummy.h" 400cdfcc0fSMark Brown #include "internal.h" 4134abbd68SMark Brown 427d51a0dbSMark Brown #define rdev_crit(rdev, fmt, ...) \ 437d51a0dbSMark Brown pr_crit("%s: " fmt, rdev_get_name(rdev), ##__VA_ARGS__) 445da84fd9SJoe Perches #define rdev_err(rdev, fmt, ...) \ 455da84fd9SJoe Perches pr_err("%s: " fmt, rdev_get_name(rdev), ##__VA_ARGS__) 465da84fd9SJoe Perches #define rdev_warn(rdev, fmt, ...) \ 475da84fd9SJoe Perches pr_warn("%s: " fmt, rdev_get_name(rdev), ##__VA_ARGS__) 485da84fd9SJoe Perches #define rdev_info(rdev, fmt, ...) \ 495da84fd9SJoe Perches pr_info("%s: " fmt, rdev_get_name(rdev), ##__VA_ARGS__) 505da84fd9SJoe Perches #define rdev_dbg(rdev, fmt, ...) \ 515da84fd9SJoe Perches pr_debug("%s: " fmt, rdev_get_name(rdev), ##__VA_ARGS__) 525da84fd9SJoe Perches 53414c70cbSLiam Girdwood static DEFINE_MUTEX(regulator_list_mutex); 54414c70cbSLiam Girdwood static LIST_HEAD(regulator_list); 55414c70cbSLiam Girdwood static LIST_HEAD(regulator_map_list); 56f19b00daSKim, Milo static LIST_HEAD(regulator_ena_gpio_list); 57a06ccd9cSCharles Keepax static LIST_HEAD(regulator_supply_alias_list); 5821cf891aSMark Brown static bool has_full_constraints; 59414c70cbSLiam Girdwood 601130e5b3SMark Brown static struct dentry *debugfs_root; 611130e5b3SMark Brown 628dc5390dSMark Brown /* 63414c70cbSLiam Girdwood * struct regulator_map 64414c70cbSLiam Girdwood * 65414c70cbSLiam Girdwood * Used to provide symbolic supply names to devices. 66414c70cbSLiam Girdwood */ 67414c70cbSLiam Girdwood struct regulator_map { 68414c70cbSLiam Girdwood struct list_head list; 6940f9244fSMark Brown const char *dev_name; /* The dev_name() for the consumer */ 70414c70cbSLiam Girdwood const char *supply; 71a5766f11SLiam Girdwood struct regulator_dev *regulator; 72414c70cbSLiam Girdwood }; 73414c70cbSLiam Girdwood 74414c70cbSLiam Girdwood /* 75f19b00daSKim, Milo * struct regulator_enable_gpio 76f19b00daSKim, Milo * 77f19b00daSKim, Milo * Management for shared enable GPIO pin 78f19b00daSKim, Milo */ 79f19b00daSKim, Milo struct regulator_enable_gpio { 80f19b00daSKim, Milo struct list_head list; 81778b28b4SRussell King struct gpio_desc *gpiod; 82f19b00daSKim, Milo u32 enable_count; /* a number of enabled shared GPIO */ 83f19b00daSKim, Milo u32 request_count; /* a number of requested shared GPIO */ 84f19b00daSKim, Milo unsigned int ena_gpio_invert:1; 85f19b00daSKim, Milo }; 86f19b00daSKim, Milo 87a06ccd9cSCharles Keepax /* 88a06ccd9cSCharles Keepax * struct regulator_supply_alias 89a06ccd9cSCharles Keepax * 90a06ccd9cSCharles Keepax * Used to map lookups for a supply onto an alternative device. 91a06ccd9cSCharles Keepax */ 92a06ccd9cSCharles Keepax struct regulator_supply_alias { 93a06ccd9cSCharles Keepax struct list_head list; 94a06ccd9cSCharles Keepax struct device *src_dev; 95a06ccd9cSCharles Keepax const char *src_supply; 96a06ccd9cSCharles Keepax struct device *alias_dev; 97a06ccd9cSCharles Keepax const char *alias_supply; 98a06ccd9cSCharles Keepax }; 99a06ccd9cSCharles Keepax 100414c70cbSLiam Girdwood static int _regulator_is_enabled(struct regulator_dev *rdev); 1013801b86aSMark Brown static int _regulator_disable(struct regulator_dev *rdev); 102414c70cbSLiam Girdwood static int _regulator_get_voltage(struct regulator_dev *rdev); 103414c70cbSLiam Girdwood static int _regulator_get_current_limit(struct regulator_dev *rdev); 104414c70cbSLiam Girdwood static unsigned int _regulator_get_mode(struct regulator_dev *rdev); 1057179569aSHeiko Stübner static int _notifier_call_chain(struct regulator_dev *rdev, 106414c70cbSLiam Girdwood unsigned long event, void *data); 10775790251SMark Brown static int _regulator_do_set_voltage(struct regulator_dev *rdev, 10875790251SMark Brown int min_uV, int max_uV); 1093801b86aSMark Brown static struct regulator *create_regulator(struct regulator_dev *rdev, 1103801b86aSMark Brown struct device *dev, 1113801b86aSMark Brown const char *supply_name); 112414c70cbSLiam Girdwood 1131083c393SMark Brown static const char *rdev_get_name(struct regulator_dev *rdev) 1141083c393SMark Brown { 1151083c393SMark Brown if (rdev->constraints && rdev->constraints->name) 1161083c393SMark Brown return rdev->constraints->name; 1171083c393SMark Brown else if (rdev->desc->name) 1181083c393SMark Brown return rdev->desc->name; 1191083c393SMark Brown else 1201083c393SMark Brown return ""; 1211083c393SMark Brown } 1221083c393SMark Brown 12387b28417SMark Brown static bool have_full_constraints(void) 12487b28417SMark Brown { 12575bc9641SMark Brown return has_full_constraints || of_have_populated_dt(); 12687b28417SMark Brown } 12787b28417SMark Brown 12869511a45SRajendra Nayak /** 12969511a45SRajendra Nayak * of_get_regulator - get a regulator device node based on supply name 13069511a45SRajendra Nayak * @dev: Device pointer for the consumer (of regulator) device 13169511a45SRajendra Nayak * @supply: regulator supply name 13269511a45SRajendra Nayak * 13369511a45SRajendra Nayak * Extract the regulator device node corresponding to the supply name. 134167d41dcSMaxime Ripard * returns the device node corresponding to the regulator if found, else 13569511a45SRajendra Nayak * returns NULL. 13669511a45SRajendra Nayak */ 13769511a45SRajendra Nayak static struct device_node *of_get_regulator(struct device *dev, const char *supply) 13869511a45SRajendra Nayak { 13969511a45SRajendra Nayak struct device_node *regnode = NULL; 14069511a45SRajendra Nayak char prop_name[32]; /* 32 is max size of property name */ 14169511a45SRajendra Nayak 14269511a45SRajendra Nayak dev_dbg(dev, "Looking up %s-supply from device tree\n", supply); 14369511a45SRajendra Nayak 14469511a45SRajendra Nayak snprintf(prop_name, 32, "%s-supply", supply); 14569511a45SRajendra Nayak regnode = of_parse_phandle(dev->of_node, prop_name, 0); 14669511a45SRajendra Nayak 14769511a45SRajendra Nayak if (!regnode) { 14816fbcc3bSRajendra Nayak dev_dbg(dev, "Looking up %s property in node %s failed", 14969511a45SRajendra Nayak prop_name, dev->of_node->full_name); 15069511a45SRajendra Nayak return NULL; 15169511a45SRajendra Nayak } 15269511a45SRajendra Nayak return regnode; 15369511a45SRajendra Nayak } 15469511a45SRajendra Nayak 1556492bc1bSMark Brown static int _regulator_can_change_status(struct regulator_dev *rdev) 1566492bc1bSMark Brown { 1576492bc1bSMark Brown if (!rdev->constraints) 1586492bc1bSMark Brown return 0; 1596492bc1bSMark Brown 1606492bc1bSMark Brown if (rdev->constraints->valid_ops_mask & REGULATOR_CHANGE_STATUS) 1616492bc1bSMark Brown return 1; 1626492bc1bSMark Brown else 1636492bc1bSMark Brown return 0; 1646492bc1bSMark Brown } 1656492bc1bSMark Brown 166414c70cbSLiam Girdwood /* Platform voltage constraint check */ 167414c70cbSLiam Girdwood static int regulator_check_voltage(struct regulator_dev *rdev, 168414c70cbSLiam Girdwood int *min_uV, int *max_uV) 169414c70cbSLiam Girdwood { 170414c70cbSLiam Girdwood BUG_ON(*min_uV > *max_uV); 171414c70cbSLiam Girdwood 172414c70cbSLiam Girdwood if (!rdev->constraints) { 1735da84fd9SJoe Perches rdev_err(rdev, "no constraints\n"); 174414c70cbSLiam Girdwood return -ENODEV; 175414c70cbSLiam Girdwood } 176414c70cbSLiam Girdwood if (!(rdev->constraints->valid_ops_mask & REGULATOR_CHANGE_VOLTAGE)) { 1775da84fd9SJoe Perches rdev_err(rdev, "operation not allowed\n"); 178414c70cbSLiam Girdwood return -EPERM; 179414c70cbSLiam Girdwood } 180414c70cbSLiam Girdwood 181414c70cbSLiam Girdwood if (*max_uV > rdev->constraints->max_uV) 182414c70cbSLiam Girdwood *max_uV = rdev->constraints->max_uV; 183414c70cbSLiam Girdwood if (*min_uV < rdev->constraints->min_uV) 184414c70cbSLiam Girdwood *min_uV = rdev->constraints->min_uV; 185414c70cbSLiam Girdwood 18689f425edSMark Brown if (*min_uV > *max_uV) { 18789f425edSMark Brown rdev_err(rdev, "unsupportable voltage range: %d-%duV\n", 18854abd335SMark Brown *min_uV, *max_uV); 189414c70cbSLiam Girdwood return -EINVAL; 19089f425edSMark Brown } 191414c70cbSLiam Girdwood 192414c70cbSLiam Girdwood return 0; 193414c70cbSLiam Girdwood } 194414c70cbSLiam Girdwood 19505fda3b1SThomas Petazzoni /* Make sure we select a voltage that suits the needs of all 19605fda3b1SThomas Petazzoni * regulator consumers 19705fda3b1SThomas Petazzoni */ 19805fda3b1SThomas Petazzoni static int regulator_check_consumers(struct regulator_dev *rdev, 19905fda3b1SThomas Petazzoni int *min_uV, int *max_uV) 20005fda3b1SThomas Petazzoni { 20105fda3b1SThomas Petazzoni struct regulator *regulator; 20205fda3b1SThomas Petazzoni 20305fda3b1SThomas Petazzoni list_for_each_entry(regulator, &rdev->consumer_list, list) { 2044aa922c0SMark Brown /* 2054aa922c0SMark Brown * Assume consumers that didn't say anything are OK 2064aa922c0SMark Brown * with anything in the constraint range. 2074aa922c0SMark Brown */ 2084aa922c0SMark Brown if (!regulator->min_uV && !regulator->max_uV) 2094aa922c0SMark Brown continue; 2104aa922c0SMark Brown 21105fda3b1SThomas Petazzoni if (*max_uV > regulator->max_uV) 21205fda3b1SThomas Petazzoni *max_uV = regulator->max_uV; 21305fda3b1SThomas Petazzoni if (*min_uV < regulator->min_uV) 21405fda3b1SThomas Petazzoni *min_uV = regulator->min_uV; 21505fda3b1SThomas Petazzoni } 21605fda3b1SThomas Petazzoni 217dd8004afSMark Brown if (*min_uV > *max_uV) { 2189c7b4e8aSRuss Dill rdev_err(rdev, "Restricting voltage, %u-%uuV\n", 2199c7b4e8aSRuss Dill *min_uV, *max_uV); 22005fda3b1SThomas Petazzoni return -EINVAL; 221dd8004afSMark Brown } 22205fda3b1SThomas Petazzoni 22305fda3b1SThomas Petazzoni return 0; 22405fda3b1SThomas Petazzoni } 22505fda3b1SThomas Petazzoni 226414c70cbSLiam Girdwood /* current constraint check */ 227414c70cbSLiam Girdwood static int regulator_check_current_limit(struct regulator_dev *rdev, 228414c70cbSLiam Girdwood int *min_uA, int *max_uA) 229414c70cbSLiam Girdwood { 230414c70cbSLiam Girdwood BUG_ON(*min_uA > *max_uA); 231414c70cbSLiam Girdwood 232414c70cbSLiam Girdwood if (!rdev->constraints) { 2335da84fd9SJoe Perches rdev_err(rdev, "no constraints\n"); 234414c70cbSLiam Girdwood return -ENODEV; 235414c70cbSLiam Girdwood } 236414c70cbSLiam Girdwood if (!(rdev->constraints->valid_ops_mask & REGULATOR_CHANGE_CURRENT)) { 2375da84fd9SJoe Perches rdev_err(rdev, "operation not allowed\n"); 238414c70cbSLiam Girdwood return -EPERM; 239414c70cbSLiam Girdwood } 240414c70cbSLiam Girdwood 241414c70cbSLiam Girdwood if (*max_uA > rdev->constraints->max_uA) 242414c70cbSLiam Girdwood *max_uA = rdev->constraints->max_uA; 243414c70cbSLiam Girdwood if (*min_uA < rdev->constraints->min_uA) 244414c70cbSLiam Girdwood *min_uA = rdev->constraints->min_uA; 245414c70cbSLiam Girdwood 24689f425edSMark Brown if (*min_uA > *max_uA) { 24789f425edSMark Brown rdev_err(rdev, "unsupportable current range: %d-%duA\n", 24854abd335SMark Brown *min_uA, *max_uA); 249414c70cbSLiam Girdwood return -EINVAL; 25089f425edSMark Brown } 251414c70cbSLiam Girdwood 252414c70cbSLiam Girdwood return 0; 253414c70cbSLiam Girdwood } 254414c70cbSLiam Girdwood 255414c70cbSLiam Girdwood /* operating mode constraint check */ 2562c608234SMark Brown static int regulator_mode_constrain(struct regulator_dev *rdev, int *mode) 257414c70cbSLiam Girdwood { 2582c608234SMark Brown switch (*mode) { 259e573520bSDavid Brownell case REGULATOR_MODE_FAST: 260e573520bSDavid Brownell case REGULATOR_MODE_NORMAL: 261e573520bSDavid Brownell case REGULATOR_MODE_IDLE: 262e573520bSDavid Brownell case REGULATOR_MODE_STANDBY: 263e573520bSDavid Brownell break; 264e573520bSDavid Brownell default: 26589f425edSMark Brown rdev_err(rdev, "invalid mode %x specified\n", *mode); 266e573520bSDavid Brownell return -EINVAL; 267e573520bSDavid Brownell } 268e573520bSDavid Brownell 269414c70cbSLiam Girdwood if (!rdev->constraints) { 2705da84fd9SJoe Perches rdev_err(rdev, "no constraints\n"); 271414c70cbSLiam Girdwood return -ENODEV; 272414c70cbSLiam Girdwood } 273414c70cbSLiam Girdwood if (!(rdev->constraints->valid_ops_mask & REGULATOR_CHANGE_MODE)) { 2745da84fd9SJoe Perches rdev_err(rdev, "operation not allowed\n"); 275414c70cbSLiam Girdwood return -EPERM; 276414c70cbSLiam Girdwood } 2772c608234SMark Brown 2782c608234SMark Brown /* The modes are bitmasks, the most power hungry modes having 2792c608234SMark Brown * the lowest values. If the requested mode isn't supported 2802c608234SMark Brown * try higher modes. */ 2812c608234SMark Brown while (*mode) { 2822c608234SMark Brown if (rdev->constraints->valid_modes_mask & *mode) 283414c70cbSLiam Girdwood return 0; 2842c608234SMark Brown *mode /= 2; 2852c608234SMark Brown } 2862c608234SMark Brown 2872c608234SMark Brown return -EINVAL; 288414c70cbSLiam Girdwood } 289414c70cbSLiam Girdwood 290414c70cbSLiam Girdwood /* dynamic regulator mode switching constraint check */ 291414c70cbSLiam Girdwood static int regulator_check_drms(struct regulator_dev *rdev) 292414c70cbSLiam Girdwood { 293414c70cbSLiam Girdwood if (!rdev->constraints) { 2945da84fd9SJoe Perches rdev_err(rdev, "no constraints\n"); 295414c70cbSLiam Girdwood return -ENODEV; 296414c70cbSLiam Girdwood } 297414c70cbSLiam Girdwood if (!(rdev->constraints->valid_ops_mask & REGULATOR_CHANGE_DRMS)) { 2985da84fd9SJoe Perches rdev_err(rdev, "operation not allowed\n"); 299414c70cbSLiam Girdwood return -EPERM; 300414c70cbSLiam Girdwood } 301414c70cbSLiam Girdwood return 0; 302414c70cbSLiam Girdwood } 303414c70cbSLiam Girdwood 304414c70cbSLiam Girdwood static ssize_t regulator_uV_show(struct device *dev, 305414c70cbSLiam Girdwood struct device_attribute *attr, char *buf) 306414c70cbSLiam Girdwood { 307a5766f11SLiam Girdwood struct regulator_dev *rdev = dev_get_drvdata(dev); 308414c70cbSLiam Girdwood ssize_t ret; 309414c70cbSLiam Girdwood 310414c70cbSLiam Girdwood mutex_lock(&rdev->mutex); 311414c70cbSLiam Girdwood ret = sprintf(buf, "%d\n", _regulator_get_voltage(rdev)); 312414c70cbSLiam Girdwood mutex_unlock(&rdev->mutex); 313414c70cbSLiam Girdwood 314414c70cbSLiam Girdwood return ret; 315414c70cbSLiam Girdwood } 3167ad68e2fSDavid Brownell static DEVICE_ATTR(microvolts, 0444, regulator_uV_show, NULL); 317414c70cbSLiam Girdwood 318414c70cbSLiam Girdwood static ssize_t regulator_uA_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 323414c70cbSLiam Girdwood return sprintf(buf, "%d\n", _regulator_get_current_limit(rdev)); 324414c70cbSLiam Girdwood } 3257ad68e2fSDavid Brownell static DEVICE_ATTR(microamps, 0444, regulator_uA_show, NULL); 326414c70cbSLiam Girdwood 327587cea27SGreg Kroah-Hartman static ssize_t name_show(struct device *dev, struct device_attribute *attr, 328587cea27SGreg Kroah-Hartman char *buf) 329bc558a60SMark Brown { 330bc558a60SMark Brown struct regulator_dev *rdev = dev_get_drvdata(dev); 331bc558a60SMark Brown 3321083c393SMark Brown return sprintf(buf, "%s\n", rdev_get_name(rdev)); 333bc558a60SMark Brown } 334587cea27SGreg Kroah-Hartman static DEVICE_ATTR_RO(name); 335bc558a60SMark Brown 3364fca9545SDavid Brownell static ssize_t regulator_print_opmode(char *buf, int mode) 337414c70cbSLiam Girdwood { 338414c70cbSLiam Girdwood switch (mode) { 339414c70cbSLiam Girdwood case REGULATOR_MODE_FAST: 340414c70cbSLiam Girdwood return sprintf(buf, "fast\n"); 341414c70cbSLiam Girdwood case REGULATOR_MODE_NORMAL: 342414c70cbSLiam Girdwood return sprintf(buf, "normal\n"); 343414c70cbSLiam Girdwood case REGULATOR_MODE_IDLE: 344414c70cbSLiam Girdwood return sprintf(buf, "idle\n"); 345414c70cbSLiam Girdwood case REGULATOR_MODE_STANDBY: 346414c70cbSLiam Girdwood return sprintf(buf, "standby\n"); 347414c70cbSLiam Girdwood } 348414c70cbSLiam Girdwood return sprintf(buf, "unknown\n"); 349414c70cbSLiam Girdwood } 350414c70cbSLiam Girdwood 3514fca9545SDavid Brownell static ssize_t regulator_opmode_show(struct device *dev, 352414c70cbSLiam Girdwood struct device_attribute *attr, char *buf) 353414c70cbSLiam Girdwood { 354a5766f11SLiam Girdwood struct regulator_dev *rdev = dev_get_drvdata(dev); 355414c70cbSLiam Girdwood 3564fca9545SDavid Brownell return regulator_print_opmode(buf, _regulator_get_mode(rdev)); 3574fca9545SDavid Brownell } 3587ad68e2fSDavid Brownell static DEVICE_ATTR(opmode, 0444, regulator_opmode_show, NULL); 3594fca9545SDavid Brownell 3604fca9545SDavid Brownell static ssize_t regulator_print_state(char *buf, int state) 3614fca9545SDavid Brownell { 362414c70cbSLiam Girdwood if (state > 0) 363414c70cbSLiam Girdwood return sprintf(buf, "enabled\n"); 364414c70cbSLiam Girdwood else if (state == 0) 365414c70cbSLiam Girdwood return sprintf(buf, "disabled\n"); 366414c70cbSLiam Girdwood else 367414c70cbSLiam Girdwood return sprintf(buf, "unknown\n"); 368414c70cbSLiam Girdwood } 369414c70cbSLiam Girdwood 3704fca9545SDavid Brownell static ssize_t regulator_state_show(struct device *dev, 3714fca9545SDavid Brownell struct device_attribute *attr, char *buf) 3724fca9545SDavid Brownell { 3734fca9545SDavid Brownell struct regulator_dev *rdev = dev_get_drvdata(dev); 3749332546fSMark Brown ssize_t ret; 3754fca9545SDavid Brownell 3769332546fSMark Brown mutex_lock(&rdev->mutex); 3779332546fSMark Brown ret = regulator_print_state(buf, _regulator_is_enabled(rdev)); 3789332546fSMark Brown mutex_unlock(&rdev->mutex); 3799332546fSMark Brown 3809332546fSMark Brown return ret; 3814fca9545SDavid Brownell } 3827ad68e2fSDavid Brownell static DEVICE_ATTR(state, 0444, regulator_state_show, NULL); 3834fca9545SDavid Brownell 384853116a1SDavid Brownell static ssize_t regulator_status_show(struct device *dev, 385853116a1SDavid Brownell struct device_attribute *attr, char *buf) 386853116a1SDavid Brownell { 387853116a1SDavid Brownell struct regulator_dev *rdev = dev_get_drvdata(dev); 388853116a1SDavid Brownell int status; 389853116a1SDavid Brownell char *label; 390853116a1SDavid Brownell 391853116a1SDavid Brownell status = rdev->desc->ops->get_status(rdev); 392853116a1SDavid Brownell if (status < 0) 393853116a1SDavid Brownell return status; 394853116a1SDavid Brownell 395853116a1SDavid Brownell switch (status) { 396853116a1SDavid Brownell case REGULATOR_STATUS_OFF: 397853116a1SDavid Brownell label = "off"; 398853116a1SDavid Brownell break; 399853116a1SDavid Brownell case REGULATOR_STATUS_ON: 400853116a1SDavid Brownell label = "on"; 401853116a1SDavid Brownell break; 402853116a1SDavid Brownell case REGULATOR_STATUS_ERROR: 403853116a1SDavid Brownell label = "error"; 404853116a1SDavid Brownell break; 405853116a1SDavid Brownell case REGULATOR_STATUS_FAST: 406853116a1SDavid Brownell label = "fast"; 407853116a1SDavid Brownell break; 408853116a1SDavid Brownell case REGULATOR_STATUS_NORMAL: 409853116a1SDavid Brownell label = "normal"; 410853116a1SDavid Brownell break; 411853116a1SDavid Brownell case REGULATOR_STATUS_IDLE: 412853116a1SDavid Brownell label = "idle"; 413853116a1SDavid Brownell break; 414853116a1SDavid Brownell case REGULATOR_STATUS_STANDBY: 415853116a1SDavid Brownell label = "standby"; 416853116a1SDavid Brownell break; 417f59c8f9fSMark Brown case REGULATOR_STATUS_BYPASS: 418f59c8f9fSMark Brown label = "bypass"; 419f59c8f9fSMark Brown break; 4201beaf762SKrystian Garbaciak case REGULATOR_STATUS_UNDEFINED: 4211beaf762SKrystian Garbaciak label = "undefined"; 4221beaf762SKrystian Garbaciak break; 423853116a1SDavid Brownell default: 424853116a1SDavid Brownell return -ERANGE; 425853116a1SDavid Brownell } 426853116a1SDavid Brownell 427853116a1SDavid Brownell return sprintf(buf, "%s\n", label); 428853116a1SDavid Brownell } 429853116a1SDavid Brownell static DEVICE_ATTR(status, 0444, regulator_status_show, NULL); 430853116a1SDavid Brownell 431414c70cbSLiam Girdwood static ssize_t regulator_min_uA_show(struct device *dev, 432414c70cbSLiam Girdwood struct device_attribute *attr, char *buf) 433414c70cbSLiam Girdwood { 434a5766f11SLiam Girdwood struct regulator_dev *rdev = dev_get_drvdata(dev); 435414c70cbSLiam Girdwood 436414c70cbSLiam Girdwood if (!rdev->constraints) 437414c70cbSLiam Girdwood return sprintf(buf, "constraint not defined\n"); 438414c70cbSLiam Girdwood 439414c70cbSLiam Girdwood return sprintf(buf, "%d\n", rdev->constraints->min_uA); 440414c70cbSLiam Girdwood } 4417ad68e2fSDavid Brownell static DEVICE_ATTR(min_microamps, 0444, regulator_min_uA_show, NULL); 442414c70cbSLiam Girdwood 443414c70cbSLiam Girdwood static ssize_t regulator_max_uA_show(struct device *dev, 444414c70cbSLiam Girdwood struct device_attribute *attr, char *buf) 445414c70cbSLiam Girdwood { 446a5766f11SLiam Girdwood struct regulator_dev *rdev = dev_get_drvdata(dev); 447414c70cbSLiam Girdwood 448414c70cbSLiam Girdwood if (!rdev->constraints) 449414c70cbSLiam Girdwood return sprintf(buf, "constraint not defined\n"); 450414c70cbSLiam Girdwood 451414c70cbSLiam Girdwood return sprintf(buf, "%d\n", rdev->constraints->max_uA); 452414c70cbSLiam Girdwood } 4537ad68e2fSDavid Brownell static DEVICE_ATTR(max_microamps, 0444, regulator_max_uA_show, NULL); 454414c70cbSLiam Girdwood 455414c70cbSLiam Girdwood static ssize_t regulator_min_uV_show(struct device *dev, 456414c70cbSLiam Girdwood struct device_attribute *attr, char *buf) 457414c70cbSLiam Girdwood { 458a5766f11SLiam Girdwood struct regulator_dev *rdev = dev_get_drvdata(dev); 459414c70cbSLiam Girdwood 460414c70cbSLiam Girdwood if (!rdev->constraints) 461414c70cbSLiam Girdwood return sprintf(buf, "constraint not defined\n"); 462414c70cbSLiam Girdwood 463414c70cbSLiam Girdwood return sprintf(buf, "%d\n", rdev->constraints->min_uV); 464414c70cbSLiam Girdwood } 4657ad68e2fSDavid Brownell static DEVICE_ATTR(min_microvolts, 0444, regulator_min_uV_show, NULL); 466414c70cbSLiam Girdwood 467414c70cbSLiam Girdwood static ssize_t regulator_max_uV_show(struct device *dev, 468414c70cbSLiam Girdwood struct device_attribute *attr, char *buf) 469414c70cbSLiam Girdwood { 470a5766f11SLiam Girdwood struct regulator_dev *rdev = dev_get_drvdata(dev); 471414c70cbSLiam Girdwood 472414c70cbSLiam Girdwood if (!rdev->constraints) 473414c70cbSLiam Girdwood return sprintf(buf, "constraint not defined\n"); 474414c70cbSLiam Girdwood 475414c70cbSLiam Girdwood return sprintf(buf, "%d\n", rdev->constraints->max_uV); 476414c70cbSLiam Girdwood } 4777ad68e2fSDavid Brownell static DEVICE_ATTR(max_microvolts, 0444, regulator_max_uV_show, NULL); 478414c70cbSLiam Girdwood 479414c70cbSLiam Girdwood static ssize_t regulator_total_uA_show(struct device *dev, 480414c70cbSLiam Girdwood struct device_attribute *attr, char *buf) 481414c70cbSLiam Girdwood { 482a5766f11SLiam Girdwood struct regulator_dev *rdev = dev_get_drvdata(dev); 483414c70cbSLiam Girdwood struct regulator *regulator; 484414c70cbSLiam Girdwood int uA = 0; 485414c70cbSLiam Girdwood 486414c70cbSLiam Girdwood mutex_lock(&rdev->mutex); 487414c70cbSLiam Girdwood list_for_each_entry(regulator, &rdev->consumer_list, list) 488414c70cbSLiam Girdwood uA += regulator->uA_load; 489414c70cbSLiam Girdwood mutex_unlock(&rdev->mutex); 490414c70cbSLiam Girdwood return sprintf(buf, "%d\n", uA); 491414c70cbSLiam Girdwood } 4927ad68e2fSDavid Brownell static DEVICE_ATTR(requested_microamps, 0444, regulator_total_uA_show, NULL); 493414c70cbSLiam Girdwood 494587cea27SGreg Kroah-Hartman static ssize_t num_users_show(struct device *dev, struct device_attribute *attr, 495587cea27SGreg Kroah-Hartman char *buf) 496414c70cbSLiam Girdwood { 497a5766f11SLiam Girdwood struct regulator_dev *rdev = dev_get_drvdata(dev); 498414c70cbSLiam Girdwood return sprintf(buf, "%d\n", rdev->use_count); 499414c70cbSLiam Girdwood } 500587cea27SGreg Kroah-Hartman static DEVICE_ATTR_RO(num_users); 501414c70cbSLiam Girdwood 502587cea27SGreg Kroah-Hartman static ssize_t type_show(struct device *dev, struct device_attribute *attr, 503587cea27SGreg Kroah-Hartman char *buf) 504414c70cbSLiam Girdwood { 505a5766f11SLiam Girdwood struct regulator_dev *rdev = dev_get_drvdata(dev); 506414c70cbSLiam Girdwood 507414c70cbSLiam Girdwood switch (rdev->desc->type) { 508414c70cbSLiam Girdwood case REGULATOR_VOLTAGE: 509414c70cbSLiam Girdwood return sprintf(buf, "voltage\n"); 510414c70cbSLiam Girdwood case REGULATOR_CURRENT: 511414c70cbSLiam Girdwood return sprintf(buf, "current\n"); 512414c70cbSLiam Girdwood } 513414c70cbSLiam Girdwood return sprintf(buf, "unknown\n"); 514414c70cbSLiam Girdwood } 515587cea27SGreg Kroah-Hartman static DEVICE_ATTR_RO(type); 516414c70cbSLiam Girdwood 517414c70cbSLiam Girdwood static ssize_t regulator_suspend_mem_uV_show(struct device *dev, 518414c70cbSLiam Girdwood struct device_attribute *attr, char *buf) 519414c70cbSLiam Girdwood { 520a5766f11SLiam Girdwood struct regulator_dev *rdev = dev_get_drvdata(dev); 521414c70cbSLiam Girdwood 522414c70cbSLiam Girdwood return sprintf(buf, "%d\n", rdev->constraints->state_mem.uV); 523414c70cbSLiam Girdwood } 5247ad68e2fSDavid Brownell static DEVICE_ATTR(suspend_mem_microvolts, 0444, 5257ad68e2fSDavid Brownell regulator_suspend_mem_uV_show, NULL); 526414c70cbSLiam Girdwood 527414c70cbSLiam Girdwood static ssize_t regulator_suspend_disk_uV_show(struct device *dev, 528414c70cbSLiam Girdwood struct device_attribute *attr, char *buf) 529414c70cbSLiam Girdwood { 530a5766f11SLiam Girdwood struct regulator_dev *rdev = dev_get_drvdata(dev); 531414c70cbSLiam Girdwood 532414c70cbSLiam Girdwood return sprintf(buf, "%d\n", rdev->constraints->state_disk.uV); 533414c70cbSLiam Girdwood } 5347ad68e2fSDavid Brownell static DEVICE_ATTR(suspend_disk_microvolts, 0444, 5357ad68e2fSDavid Brownell regulator_suspend_disk_uV_show, NULL); 536414c70cbSLiam Girdwood 537414c70cbSLiam Girdwood static ssize_t regulator_suspend_standby_uV_show(struct device *dev, 538414c70cbSLiam Girdwood struct device_attribute *attr, char *buf) 539414c70cbSLiam Girdwood { 540a5766f11SLiam Girdwood struct regulator_dev *rdev = dev_get_drvdata(dev); 541414c70cbSLiam Girdwood 542414c70cbSLiam Girdwood return sprintf(buf, "%d\n", rdev->constraints->state_standby.uV); 543414c70cbSLiam Girdwood } 5447ad68e2fSDavid Brownell static DEVICE_ATTR(suspend_standby_microvolts, 0444, 5457ad68e2fSDavid Brownell regulator_suspend_standby_uV_show, NULL); 546414c70cbSLiam Girdwood 547414c70cbSLiam Girdwood static ssize_t regulator_suspend_mem_mode_show(struct device *dev, 548414c70cbSLiam Girdwood struct device_attribute *attr, char *buf) 549414c70cbSLiam Girdwood { 550a5766f11SLiam Girdwood struct regulator_dev *rdev = dev_get_drvdata(dev); 551414c70cbSLiam Girdwood 5524fca9545SDavid Brownell return regulator_print_opmode(buf, 5534fca9545SDavid Brownell rdev->constraints->state_mem.mode); 554414c70cbSLiam Girdwood } 5557ad68e2fSDavid Brownell static DEVICE_ATTR(suspend_mem_mode, 0444, 5567ad68e2fSDavid Brownell regulator_suspend_mem_mode_show, NULL); 557414c70cbSLiam Girdwood 558414c70cbSLiam Girdwood static ssize_t regulator_suspend_disk_mode_show(struct device *dev, 559414c70cbSLiam Girdwood struct device_attribute *attr, char *buf) 560414c70cbSLiam Girdwood { 561a5766f11SLiam Girdwood struct regulator_dev *rdev = dev_get_drvdata(dev); 562414c70cbSLiam Girdwood 5634fca9545SDavid Brownell return regulator_print_opmode(buf, 5644fca9545SDavid Brownell rdev->constraints->state_disk.mode); 565414c70cbSLiam Girdwood } 5667ad68e2fSDavid Brownell static DEVICE_ATTR(suspend_disk_mode, 0444, 5677ad68e2fSDavid Brownell regulator_suspend_disk_mode_show, NULL); 568414c70cbSLiam Girdwood 569414c70cbSLiam Girdwood static ssize_t regulator_suspend_standby_mode_show(struct device *dev, 570414c70cbSLiam Girdwood struct device_attribute *attr, char *buf) 571414c70cbSLiam Girdwood { 572a5766f11SLiam Girdwood struct regulator_dev *rdev = dev_get_drvdata(dev); 573414c70cbSLiam Girdwood 5744fca9545SDavid Brownell return regulator_print_opmode(buf, 5754fca9545SDavid Brownell rdev->constraints->state_standby.mode); 576414c70cbSLiam Girdwood } 5777ad68e2fSDavid Brownell static DEVICE_ATTR(suspend_standby_mode, 0444, 5787ad68e2fSDavid Brownell regulator_suspend_standby_mode_show, NULL); 579414c70cbSLiam Girdwood 580414c70cbSLiam Girdwood static ssize_t regulator_suspend_mem_state_show(struct device *dev, 581414c70cbSLiam Girdwood struct device_attribute *attr, char *buf) 582414c70cbSLiam Girdwood { 583a5766f11SLiam Girdwood struct regulator_dev *rdev = dev_get_drvdata(dev); 584414c70cbSLiam Girdwood 5854fca9545SDavid Brownell return regulator_print_state(buf, 5864fca9545SDavid Brownell rdev->constraints->state_mem.enabled); 587414c70cbSLiam Girdwood } 5887ad68e2fSDavid Brownell static DEVICE_ATTR(suspend_mem_state, 0444, 5897ad68e2fSDavid Brownell regulator_suspend_mem_state_show, NULL); 590414c70cbSLiam Girdwood 591414c70cbSLiam Girdwood static ssize_t regulator_suspend_disk_state_show(struct device *dev, 592414c70cbSLiam Girdwood struct device_attribute *attr, char *buf) 593414c70cbSLiam Girdwood { 594a5766f11SLiam Girdwood struct regulator_dev *rdev = dev_get_drvdata(dev); 595414c70cbSLiam Girdwood 5964fca9545SDavid Brownell return regulator_print_state(buf, 5974fca9545SDavid Brownell rdev->constraints->state_disk.enabled); 598414c70cbSLiam Girdwood } 5997ad68e2fSDavid Brownell static DEVICE_ATTR(suspend_disk_state, 0444, 6007ad68e2fSDavid Brownell regulator_suspend_disk_state_show, NULL); 601414c70cbSLiam Girdwood 602414c70cbSLiam Girdwood static ssize_t regulator_suspend_standby_state_show(struct device *dev, 603414c70cbSLiam Girdwood struct device_attribute *attr, char *buf) 604414c70cbSLiam Girdwood { 605a5766f11SLiam Girdwood struct regulator_dev *rdev = dev_get_drvdata(dev); 606414c70cbSLiam Girdwood 6074fca9545SDavid Brownell return regulator_print_state(buf, 6084fca9545SDavid Brownell rdev->constraints->state_standby.enabled); 609414c70cbSLiam Girdwood } 6107ad68e2fSDavid Brownell static DEVICE_ATTR(suspend_standby_state, 0444, 6117ad68e2fSDavid Brownell regulator_suspend_standby_state_show, NULL); 612bc558a60SMark Brown 613f59c8f9fSMark Brown static ssize_t regulator_bypass_show(struct device *dev, 614f59c8f9fSMark Brown struct device_attribute *attr, char *buf) 615f59c8f9fSMark Brown { 616f59c8f9fSMark Brown struct regulator_dev *rdev = dev_get_drvdata(dev); 617f59c8f9fSMark Brown const char *report; 618f59c8f9fSMark Brown bool bypass; 619f59c8f9fSMark Brown int ret; 620f59c8f9fSMark Brown 621f59c8f9fSMark Brown ret = rdev->desc->ops->get_bypass(rdev, &bypass); 622f59c8f9fSMark Brown 623f59c8f9fSMark Brown if (ret != 0) 624f59c8f9fSMark Brown report = "unknown"; 625f59c8f9fSMark Brown else if (bypass) 626f59c8f9fSMark Brown report = "enabled"; 627f59c8f9fSMark Brown else 628f59c8f9fSMark Brown report = "disabled"; 629f59c8f9fSMark Brown 630f59c8f9fSMark Brown return sprintf(buf, "%s\n", report); 631f59c8f9fSMark Brown } 632f59c8f9fSMark Brown static DEVICE_ATTR(bypass, 0444, 633f59c8f9fSMark Brown regulator_bypass_show, NULL); 6347ad68e2fSDavid Brownell 635414c70cbSLiam Girdwood /* Calculate the new optimum regulator operating mode based on the new total 636414c70cbSLiam Girdwood * consumer load. All locks held by caller */ 637414c70cbSLiam Girdwood static void drms_uA_update(struct regulator_dev *rdev) 638414c70cbSLiam Girdwood { 639414c70cbSLiam Girdwood struct regulator *sibling; 640414c70cbSLiam Girdwood int current_uA = 0, output_uV, input_uV, err; 641414c70cbSLiam Girdwood unsigned int mode; 642414c70cbSLiam Girdwood 643414c70cbSLiam Girdwood err = regulator_check_drms(rdev); 644414c70cbSLiam Girdwood if (err < 0 || !rdev->desc->ops->get_optimum_mode || 645476c2d83SMark Brown (!rdev->desc->ops->get_voltage && 646476c2d83SMark Brown !rdev->desc->ops->get_voltage_sel) || 647476c2d83SMark Brown !rdev->desc->ops->set_mode) 648414c70cbSLiam Girdwood return; 649414c70cbSLiam Girdwood 650414c70cbSLiam Girdwood /* get output voltage */ 6511bf5a1f8SMark Brown output_uV = _regulator_get_voltage(rdev); 652414c70cbSLiam Girdwood if (output_uV <= 0) 653414c70cbSLiam Girdwood return; 654414c70cbSLiam Girdwood 655414c70cbSLiam Girdwood /* get input voltage */ 6561bf5a1f8SMark Brown input_uV = 0; 6571bf5a1f8SMark Brown if (rdev->supply) 6583f24f5adSAxel Lin input_uV = regulator_get_voltage(rdev->supply); 6591bf5a1f8SMark Brown if (input_uV <= 0) 660414c70cbSLiam Girdwood input_uV = rdev->constraints->input_uV; 661414c70cbSLiam Girdwood if (input_uV <= 0) 662414c70cbSLiam Girdwood return; 663414c70cbSLiam Girdwood 664414c70cbSLiam Girdwood /* calc total requested load */ 665414c70cbSLiam Girdwood list_for_each_entry(sibling, &rdev->consumer_list, list) 666414c70cbSLiam Girdwood current_uA += sibling->uA_load; 667414c70cbSLiam Girdwood 668414c70cbSLiam Girdwood /* now get the optimum mode for our new total regulator load */ 669414c70cbSLiam Girdwood mode = rdev->desc->ops->get_optimum_mode(rdev, input_uV, 670414c70cbSLiam Girdwood output_uV, current_uA); 671414c70cbSLiam Girdwood 672414c70cbSLiam Girdwood /* check the new mode is allowed */ 6732c608234SMark Brown err = regulator_mode_constrain(rdev, &mode); 674414c70cbSLiam Girdwood if (err == 0) 675414c70cbSLiam Girdwood rdev->desc->ops->set_mode(rdev, mode); 676414c70cbSLiam Girdwood } 677414c70cbSLiam Girdwood 678414c70cbSLiam Girdwood static int suspend_set_state(struct regulator_dev *rdev, 679414c70cbSLiam Girdwood struct regulator_state *rstate) 680414c70cbSLiam Girdwood { 681414c70cbSLiam Girdwood int ret = 0; 682638f85c5SMark Brown 683638f85c5SMark Brown /* If we have no suspend mode configration don't set anything; 6848ac0e95dSAxel Lin * only warn if the driver implements set_suspend_voltage or 6858ac0e95dSAxel Lin * set_suspend_mode callback. 686638f85c5SMark Brown */ 687638f85c5SMark Brown if (!rstate->enabled && !rstate->disabled) { 6888ac0e95dSAxel Lin if (rdev->desc->ops->set_suspend_voltage || 6898ac0e95dSAxel Lin rdev->desc->ops->set_suspend_mode) 6905da84fd9SJoe Perches rdev_warn(rdev, "No configuration\n"); 691638f85c5SMark Brown return 0; 692638f85c5SMark Brown } 693638f85c5SMark Brown 694638f85c5SMark Brown if (rstate->enabled && rstate->disabled) { 6955da84fd9SJoe Perches rdev_err(rdev, "invalid configuration\n"); 696638f85c5SMark Brown return -EINVAL; 697638f85c5SMark Brown } 698638f85c5SMark Brown 6998ac0e95dSAxel Lin if (rstate->enabled && rdev->desc->ops->set_suspend_enable) 700414c70cbSLiam Girdwood ret = rdev->desc->ops->set_suspend_enable(rdev); 7018ac0e95dSAxel Lin else if (rstate->disabled && rdev->desc->ops->set_suspend_disable) 702414c70cbSLiam Girdwood ret = rdev->desc->ops->set_suspend_disable(rdev); 7038ac0e95dSAxel Lin else /* OK if set_suspend_enable or set_suspend_disable is NULL */ 7048ac0e95dSAxel Lin ret = 0; 7058ac0e95dSAxel Lin 706414c70cbSLiam Girdwood if (ret < 0) { 7075da84fd9SJoe Perches rdev_err(rdev, "failed to enabled/disable\n"); 708414c70cbSLiam Girdwood return ret; 709414c70cbSLiam Girdwood } 710414c70cbSLiam Girdwood 711414c70cbSLiam Girdwood if (rdev->desc->ops->set_suspend_voltage && rstate->uV > 0) { 712414c70cbSLiam Girdwood ret = rdev->desc->ops->set_suspend_voltage(rdev, rstate->uV); 713414c70cbSLiam Girdwood if (ret < 0) { 7145da84fd9SJoe Perches rdev_err(rdev, "failed to set voltage\n"); 715414c70cbSLiam Girdwood return ret; 716414c70cbSLiam Girdwood } 717414c70cbSLiam Girdwood } 718414c70cbSLiam Girdwood 719414c70cbSLiam Girdwood if (rdev->desc->ops->set_suspend_mode && rstate->mode > 0) { 720414c70cbSLiam Girdwood ret = rdev->desc->ops->set_suspend_mode(rdev, rstate->mode); 721414c70cbSLiam Girdwood if (ret < 0) { 7225da84fd9SJoe Perches rdev_err(rdev, "failed to set mode\n"); 723414c70cbSLiam Girdwood return ret; 724414c70cbSLiam Girdwood } 725414c70cbSLiam Girdwood } 726414c70cbSLiam Girdwood return ret; 727414c70cbSLiam Girdwood } 728414c70cbSLiam Girdwood 729414c70cbSLiam Girdwood /* locks held by caller */ 730414c70cbSLiam Girdwood static int suspend_prepare(struct regulator_dev *rdev, suspend_state_t state) 731414c70cbSLiam Girdwood { 732414c70cbSLiam Girdwood if (!rdev->constraints) 733414c70cbSLiam Girdwood return -EINVAL; 734414c70cbSLiam Girdwood 735414c70cbSLiam Girdwood switch (state) { 736414c70cbSLiam Girdwood case PM_SUSPEND_STANDBY: 737414c70cbSLiam Girdwood return suspend_set_state(rdev, 738414c70cbSLiam Girdwood &rdev->constraints->state_standby); 739414c70cbSLiam Girdwood case PM_SUSPEND_MEM: 740414c70cbSLiam Girdwood return suspend_set_state(rdev, 741414c70cbSLiam Girdwood &rdev->constraints->state_mem); 742414c70cbSLiam Girdwood case PM_SUSPEND_MAX: 743414c70cbSLiam Girdwood return suspend_set_state(rdev, 744414c70cbSLiam Girdwood &rdev->constraints->state_disk); 745414c70cbSLiam Girdwood default: 746414c70cbSLiam Girdwood return -EINVAL; 747414c70cbSLiam Girdwood } 748414c70cbSLiam Girdwood } 749414c70cbSLiam Girdwood 750414c70cbSLiam Girdwood static void print_constraints(struct regulator_dev *rdev) 751414c70cbSLiam Girdwood { 752414c70cbSLiam Girdwood struct regulation_constraints *constraints = rdev->constraints; 753973e9a27SMark Brown char buf[80] = ""; 7548f031b48SMark Brown int count = 0; 7558f031b48SMark Brown int ret; 756414c70cbSLiam Girdwood 7578f031b48SMark Brown if (constraints->min_uV && constraints->max_uV) { 758414c70cbSLiam Girdwood if (constraints->min_uV == constraints->max_uV) 7598f031b48SMark Brown count += sprintf(buf + count, "%d mV ", 760414c70cbSLiam Girdwood constraints->min_uV / 1000); 761414c70cbSLiam Girdwood else 7628f031b48SMark Brown count += sprintf(buf + count, "%d <--> %d mV ", 763414c70cbSLiam Girdwood constraints->min_uV / 1000, 764414c70cbSLiam Girdwood constraints->max_uV / 1000); 7658f031b48SMark Brown } 7668f031b48SMark Brown 7678f031b48SMark Brown if (!constraints->min_uV || 7688f031b48SMark Brown constraints->min_uV != constraints->max_uV) { 7698f031b48SMark Brown ret = _regulator_get_voltage(rdev); 7708f031b48SMark Brown if (ret > 0) 7718f031b48SMark Brown count += sprintf(buf + count, "at %d mV ", ret / 1000); 7728f031b48SMark Brown } 7738f031b48SMark Brown 774bf5892a8SMark Brown if (constraints->uV_offset) 775bf5892a8SMark Brown count += sprintf(buf, "%dmV offset ", 776bf5892a8SMark Brown constraints->uV_offset / 1000); 777bf5892a8SMark Brown 7788f031b48SMark Brown if (constraints->min_uA && constraints->max_uA) { 779414c70cbSLiam Girdwood if (constraints->min_uA == constraints->max_uA) 7808f031b48SMark Brown count += sprintf(buf + count, "%d mA ", 781414c70cbSLiam Girdwood constraints->min_uA / 1000); 782414c70cbSLiam Girdwood else 7838f031b48SMark Brown count += sprintf(buf + count, "%d <--> %d mA ", 784414c70cbSLiam Girdwood constraints->min_uA / 1000, 785414c70cbSLiam Girdwood constraints->max_uA / 1000); 786414c70cbSLiam Girdwood } 7878f031b48SMark Brown 7888f031b48SMark Brown if (!constraints->min_uA || 7898f031b48SMark Brown constraints->min_uA != constraints->max_uA) { 7908f031b48SMark Brown ret = _regulator_get_current_limit(rdev); 7918f031b48SMark Brown if (ret > 0) 792e4a6376bSCyril Chemparathy count += sprintf(buf + count, "at %d mA ", ret / 1000); 7938f031b48SMark Brown } 7948f031b48SMark Brown 795414c70cbSLiam Girdwood if (constraints->valid_modes_mask & REGULATOR_MODE_FAST) 796414c70cbSLiam Girdwood count += sprintf(buf + count, "fast "); 797414c70cbSLiam Girdwood if (constraints->valid_modes_mask & REGULATOR_MODE_NORMAL) 798414c70cbSLiam Girdwood count += sprintf(buf + count, "normal "); 799414c70cbSLiam Girdwood if (constraints->valid_modes_mask & REGULATOR_MODE_IDLE) 800414c70cbSLiam Girdwood count += sprintf(buf + count, "idle "); 801414c70cbSLiam Girdwood if (constraints->valid_modes_mask & REGULATOR_MODE_STANDBY) 802414c70cbSLiam Girdwood count += sprintf(buf + count, "standby"); 803414c70cbSLiam Girdwood 804215b8b05SUwe Kleine-König if (!count) 805215b8b05SUwe Kleine-König sprintf(buf, "no parameters"); 806215b8b05SUwe Kleine-König 807194dbaefSMark Brown rdev_dbg(rdev, "%s\n", buf); 8084a682922SMark Brown 8094a682922SMark Brown if ((constraints->min_uV != constraints->max_uV) && 8104a682922SMark Brown !(constraints->valid_ops_mask & REGULATOR_CHANGE_VOLTAGE)) 8114a682922SMark Brown rdev_warn(rdev, 8124a682922SMark Brown "Voltage range but no REGULATOR_CHANGE_VOLTAGE\n"); 813414c70cbSLiam Girdwood } 814414c70cbSLiam Girdwood 815e79055d6SMark Brown static int machine_constraints_voltage(struct regulator_dev *rdev, 8161083c393SMark Brown struct regulation_constraints *constraints) 817e79055d6SMark Brown { 818272e2315SGuodong Xu const struct regulator_ops *ops = rdev->desc->ops; 819af5866c9SMark Brown int ret; 820af5866c9SMark Brown 821af5866c9SMark Brown /* do we need to apply the constraint voltage */ 822af5866c9SMark Brown if (rdev->constraints->apply_uV && 82375790251SMark Brown rdev->constraints->min_uV == rdev->constraints->max_uV) { 824064d5cd1SAlban Bedel int current_uV = _regulator_get_voltage(rdev); 825064d5cd1SAlban Bedel if (current_uV < 0) { 82669d58839SNishanth Menon rdev_err(rdev, 82769d58839SNishanth Menon "failed to get the current voltage(%d)\n", 82869d58839SNishanth Menon current_uV); 829064d5cd1SAlban Bedel return current_uV; 830064d5cd1SAlban Bedel } 831064d5cd1SAlban Bedel if (current_uV < rdev->constraints->min_uV || 832064d5cd1SAlban Bedel current_uV > rdev->constraints->max_uV) { 833064d5cd1SAlban Bedel ret = _regulator_do_set_voltage( 834064d5cd1SAlban Bedel rdev, rdev->constraints->min_uV, 83575790251SMark Brown rdev->constraints->max_uV); 836af5866c9SMark Brown if (ret < 0) { 837064d5cd1SAlban Bedel rdev_err(rdev, 83869d58839SNishanth Menon "failed to apply %duV constraint(%d)\n", 83969d58839SNishanth Menon rdev->constraints->min_uV, ret); 840af5866c9SMark Brown return ret; 841af5866c9SMark Brown } 842af5866c9SMark Brown } 843064d5cd1SAlban Bedel } 844e79055d6SMark Brown 845e79055d6SMark Brown /* constrain machine-level voltage specs to fit 846e79055d6SMark Brown * the actual range supported by this regulator. 847e79055d6SMark Brown */ 848e79055d6SMark Brown if (ops->list_voltage && rdev->desc->n_voltages) { 849e79055d6SMark Brown int count = rdev->desc->n_voltages; 850e79055d6SMark Brown int i; 851e79055d6SMark Brown int min_uV = INT_MAX; 852e79055d6SMark Brown int max_uV = INT_MIN; 853e79055d6SMark Brown int cmin = constraints->min_uV; 854e79055d6SMark Brown int cmax = constraints->max_uV; 855e79055d6SMark Brown 856e79055d6SMark Brown /* it's safe to autoconfigure fixed-voltage supplies 857e79055d6SMark Brown and the constraints are used by list_voltage. */ 858e79055d6SMark Brown if (count == 1 && !cmin) { 859e79055d6SMark Brown cmin = 1; 860e79055d6SMark Brown cmax = INT_MAX; 861e79055d6SMark Brown constraints->min_uV = cmin; 862e79055d6SMark Brown constraints->max_uV = cmax; 863e79055d6SMark Brown } 864e79055d6SMark Brown 865e79055d6SMark Brown /* voltage constraints are optional */ 866e79055d6SMark Brown if ((cmin == 0) && (cmax == 0)) 867e79055d6SMark Brown return 0; 868e79055d6SMark Brown 869e79055d6SMark Brown /* else require explicit machine-level constraints */ 870e79055d6SMark Brown if (cmin <= 0 || cmax <= 0 || cmax < cmin) { 8715da84fd9SJoe Perches rdev_err(rdev, "invalid voltage constraints\n"); 872e79055d6SMark Brown return -EINVAL; 873e79055d6SMark Brown } 874e79055d6SMark Brown 875e79055d6SMark Brown /* initial: [cmin..cmax] valid, [min_uV..max_uV] not */ 876e79055d6SMark Brown for (i = 0; i < count; i++) { 877e79055d6SMark Brown int value; 878e79055d6SMark Brown 879e79055d6SMark Brown value = ops->list_voltage(rdev, i); 880e79055d6SMark Brown if (value <= 0) 881e79055d6SMark Brown continue; 882e79055d6SMark Brown 883e79055d6SMark Brown /* maybe adjust [min_uV..max_uV] */ 884e79055d6SMark Brown if (value >= cmin && value < min_uV) 885e79055d6SMark Brown min_uV = value; 886e79055d6SMark Brown if (value <= cmax && value > max_uV) 887e79055d6SMark Brown max_uV = value; 888e79055d6SMark Brown } 889e79055d6SMark Brown 890e79055d6SMark Brown /* final: [min_uV..max_uV] valid iff constraints valid */ 891e79055d6SMark Brown if (max_uV < min_uV) { 892fff15befSMark Brown rdev_err(rdev, 893fff15befSMark Brown "unsupportable voltage constraints %u-%uuV\n", 894fff15befSMark Brown min_uV, max_uV); 895e79055d6SMark Brown return -EINVAL; 896e79055d6SMark Brown } 897e79055d6SMark Brown 898e79055d6SMark Brown /* use regulator's subset of machine constraints */ 899e79055d6SMark Brown if (constraints->min_uV < min_uV) { 9005da84fd9SJoe Perches rdev_dbg(rdev, "override min_uV, %d -> %d\n", 9015da84fd9SJoe Perches constraints->min_uV, min_uV); 902e79055d6SMark Brown constraints->min_uV = min_uV; 903e79055d6SMark Brown } 904e79055d6SMark Brown if (constraints->max_uV > max_uV) { 9055da84fd9SJoe Perches rdev_dbg(rdev, "override max_uV, %d -> %d\n", 9065da84fd9SJoe Perches constraints->max_uV, max_uV); 907e79055d6SMark Brown constraints->max_uV = max_uV; 908e79055d6SMark Brown } 909e79055d6SMark Brown } 910e79055d6SMark Brown 911e79055d6SMark Brown return 0; 912e79055d6SMark Brown } 913e79055d6SMark Brown 914f8c1700dSLaxman Dewangan static int machine_constraints_current(struct regulator_dev *rdev, 915f8c1700dSLaxman Dewangan struct regulation_constraints *constraints) 916f8c1700dSLaxman Dewangan { 917272e2315SGuodong Xu const struct regulator_ops *ops = rdev->desc->ops; 918f8c1700dSLaxman Dewangan int ret; 919f8c1700dSLaxman Dewangan 920f8c1700dSLaxman Dewangan if (!constraints->min_uA && !constraints->max_uA) 921f8c1700dSLaxman Dewangan return 0; 922f8c1700dSLaxman Dewangan 923f8c1700dSLaxman Dewangan if (constraints->min_uA > constraints->max_uA) { 924f8c1700dSLaxman Dewangan rdev_err(rdev, "Invalid current constraints\n"); 925f8c1700dSLaxman Dewangan return -EINVAL; 926f8c1700dSLaxman Dewangan } 927f8c1700dSLaxman Dewangan 928f8c1700dSLaxman Dewangan if (!ops->set_current_limit || !ops->get_current_limit) { 929f8c1700dSLaxman Dewangan rdev_warn(rdev, "Operation of current configuration missing\n"); 930f8c1700dSLaxman Dewangan return 0; 931f8c1700dSLaxman Dewangan } 932f8c1700dSLaxman Dewangan 933f8c1700dSLaxman Dewangan /* Set regulator current in constraints range */ 934f8c1700dSLaxman Dewangan ret = ops->set_current_limit(rdev, constraints->min_uA, 935f8c1700dSLaxman Dewangan constraints->max_uA); 936f8c1700dSLaxman Dewangan if (ret < 0) { 937f8c1700dSLaxman Dewangan rdev_err(rdev, "Failed to set current constraint, %d\n", ret); 938f8c1700dSLaxman Dewangan return ret; 939f8c1700dSLaxman Dewangan } 940f8c1700dSLaxman Dewangan 941f8c1700dSLaxman Dewangan return 0; 942f8c1700dSLaxman Dewangan } 943f8c1700dSLaxman Dewangan 94430c21971SMarkus Pargmann static int _regulator_do_enable(struct regulator_dev *rdev); 94530c21971SMarkus Pargmann 946a5766f11SLiam Girdwood /** 947a5766f11SLiam Girdwood * set_machine_constraints - sets regulator constraints 94869279fb9SMark Brown * @rdev: regulator source 949c8e7e464SMark Brown * @constraints: constraints to apply 950a5766f11SLiam Girdwood * 951a5766f11SLiam Girdwood * Allows platform initialisation code to define and constrain 952a5766f11SLiam Girdwood * regulator circuits e.g. valid voltage/current ranges, etc. NOTE: 953a5766f11SLiam Girdwood * Constraints *must* be set by platform code in order for some 954a5766f11SLiam Girdwood * regulator operations to proceed i.e. set_voltage, set_current_limit, 955a5766f11SLiam Girdwood * set_mode. 956a5766f11SLiam Girdwood */ 957a5766f11SLiam Girdwood static int set_machine_constraints(struct regulator_dev *rdev, 958f8c12fe3SMark Brown const struct regulation_constraints *constraints) 959a5766f11SLiam Girdwood { 960a5766f11SLiam Girdwood int ret = 0; 961272e2315SGuodong Xu const struct regulator_ops *ops = rdev->desc->ops; 962e06f5b4fSMark Brown 9639a8f5e07SMark Brown if (constraints) 964f8c12fe3SMark Brown rdev->constraints = kmemdup(constraints, sizeof(*constraints), 965f8c12fe3SMark Brown GFP_KERNEL); 9669a8f5e07SMark Brown else 9679a8f5e07SMark Brown rdev->constraints = kzalloc(sizeof(*constraints), 9689a8f5e07SMark Brown GFP_KERNEL); 969f8c12fe3SMark Brown if (!rdev->constraints) 970f8c12fe3SMark Brown return -ENOMEM; 971af5866c9SMark Brown 972f8c12fe3SMark Brown ret = machine_constraints_voltage(rdev, rdev->constraints); 973e79055d6SMark Brown if (ret != 0) 9743e2b9abdSMark Brown goto out; 9753e2b9abdSMark Brown 976f8c1700dSLaxman Dewangan ret = machine_constraints_current(rdev, rdev->constraints); 977f8c1700dSLaxman Dewangan if (ret != 0) 978f8c1700dSLaxman Dewangan goto out; 979f8c1700dSLaxman Dewangan 980a5766f11SLiam Girdwood /* do we need to setup our suspend state */ 9819a8f5e07SMark Brown if (rdev->constraints->initial_state) { 982f8c12fe3SMark Brown ret = suspend_prepare(rdev, rdev->constraints->initial_state); 983e06f5b4fSMark Brown if (ret < 0) { 9845da84fd9SJoe Perches rdev_err(rdev, "failed to set suspend state\n"); 985e06f5b4fSMark Brown goto out; 986e06f5b4fSMark Brown } 987e06f5b4fSMark Brown } 988a5766f11SLiam Girdwood 9899a8f5e07SMark Brown if (rdev->constraints->initial_mode) { 990a308466cSMark Brown if (!ops->set_mode) { 9915da84fd9SJoe Perches rdev_err(rdev, "no set_mode operation\n"); 992a308466cSMark Brown ret = -EINVAL; 993a308466cSMark Brown goto out; 994a308466cSMark Brown } 995a308466cSMark Brown 996f8c12fe3SMark Brown ret = ops->set_mode(rdev, rdev->constraints->initial_mode); 997a308466cSMark Brown if (ret < 0) { 9985da84fd9SJoe Perches rdev_err(rdev, "failed to set initial mode: %d\n", ret); 999a308466cSMark Brown goto out; 1000a308466cSMark Brown } 1001a308466cSMark Brown } 1002a308466cSMark Brown 1003cacf90f2SMark Brown /* If the constraints say the regulator should be on at this point 1004cacf90f2SMark Brown * and we have control then make sure it is enabled. 1005cacf90f2SMark Brown */ 100630c21971SMarkus Pargmann if (rdev->constraints->always_on || rdev->constraints->boot_on) { 100730c21971SMarkus Pargmann ret = _regulator_do_enable(rdev); 100830c21971SMarkus Pargmann if (ret < 0 && ret != -EINVAL) { 10095da84fd9SJoe Perches rdev_err(rdev, "failed to enable\n"); 1010e5fda26cSMark Brown goto out; 1011e5fda26cSMark Brown } 1012e5fda26cSMark Brown } 1013e5fda26cSMark Brown 10141653ccf4SYadwinder Singh Brar if ((rdev->constraints->ramp_delay || rdev->constraints->ramp_disable) 10151653ccf4SYadwinder Singh Brar && ops->set_ramp_delay) { 10166f0b2c69SYadwinder Singh Brar ret = ops->set_ramp_delay(rdev, rdev->constraints->ramp_delay); 10176f0b2c69SYadwinder Singh Brar if (ret < 0) { 10186f0b2c69SYadwinder Singh Brar rdev_err(rdev, "failed to set ramp_delay\n"); 10196f0b2c69SYadwinder Singh Brar goto out; 10206f0b2c69SYadwinder Singh Brar } 10216f0b2c69SYadwinder Singh Brar } 10226f0b2c69SYadwinder Singh Brar 1023a5766f11SLiam Girdwood print_constraints(rdev); 10241a6958e7SAxel Lin return 0; 1025a5766f11SLiam Girdwood out: 10261a6958e7SAxel Lin kfree(rdev->constraints); 10271a6958e7SAxel Lin rdev->constraints = NULL; 1028a5766f11SLiam Girdwood return ret; 1029a5766f11SLiam Girdwood } 1030a5766f11SLiam Girdwood 1031a5766f11SLiam Girdwood /** 1032a5766f11SLiam Girdwood * set_supply - set regulator supply regulator 103369279fb9SMark Brown * @rdev: regulator name 103469279fb9SMark Brown * @supply_rdev: supply regulator name 1035a5766f11SLiam Girdwood * 1036a5766f11SLiam Girdwood * Called by platform initialisation code to set the supply regulator for this 1037a5766f11SLiam Girdwood * regulator. This ensures that a regulators supply will also be enabled by the 1038a5766f11SLiam Girdwood * core if it's child is enabled. 1039a5766f11SLiam Girdwood */ 1040a5766f11SLiam Girdwood static int set_supply(struct regulator_dev *rdev, 1041a5766f11SLiam Girdwood struct regulator_dev *supply_rdev) 1042a5766f11SLiam Girdwood { 1043a5766f11SLiam Girdwood int err; 1044a5766f11SLiam Girdwood 10453801b86aSMark Brown rdev_info(rdev, "supplied by %s\n", rdev_get_name(supply_rdev)); 10463801b86aSMark Brown 10473801b86aSMark Brown rdev->supply = create_regulator(supply_rdev, &rdev->dev, "SUPPLY"); 104832c78de8SAxel Lin if (rdev->supply == NULL) { 104932c78de8SAxel Lin err = -ENOMEM; 1050a5766f11SLiam Girdwood return err; 1051a5766f11SLiam Girdwood } 105257ad526aSLaxman Dewangan supply_rdev->open_count++; 1053a5766f11SLiam Girdwood 10543801b86aSMark Brown return 0; 10553801b86aSMark Brown } 10563801b86aSMark Brown 1057a5766f11SLiam Girdwood /** 105806c63f93SRandy Dunlap * set_consumer_device_supply - Bind a regulator to a symbolic supply 105969279fb9SMark Brown * @rdev: regulator source 106040f9244fSMark Brown * @consumer_dev_name: dev_name() string for device supply applies to 1061a5766f11SLiam Girdwood * @supply: symbolic name for supply 1062a5766f11SLiam Girdwood * 1063a5766f11SLiam Girdwood * Allows platform initialisation code to map physical regulator 1064a5766f11SLiam Girdwood * sources to symbolic names for supplies for use by devices. Devices 1065a5766f11SLiam Girdwood * should use these symbolic names to request regulators, avoiding the 1066a5766f11SLiam Girdwood * need to provide board-specific regulator names as platform data. 1067a5766f11SLiam Girdwood */ 1068a5766f11SLiam Girdwood static int set_consumer_device_supply(struct regulator_dev *rdev, 1069737f360dSMark Brown const char *consumer_dev_name, 107040f9244fSMark Brown const char *supply) 1071a5766f11SLiam Girdwood { 1072a5766f11SLiam Girdwood struct regulator_map *node; 10739ed2099eSMark Brown int has_dev; 1074a5766f11SLiam Girdwood 1075a5766f11SLiam Girdwood if (supply == NULL) 1076a5766f11SLiam Girdwood return -EINVAL; 1077a5766f11SLiam Girdwood 10789ed2099eSMark Brown if (consumer_dev_name != NULL) 10799ed2099eSMark Brown has_dev = 1; 10809ed2099eSMark Brown else 10819ed2099eSMark Brown has_dev = 0; 10829ed2099eSMark Brown 10836001e13cSDavid Brownell list_for_each_entry(node, ®ulator_map_list, list) { 108423b5cc2aSJani Nikula if (node->dev_name && consumer_dev_name) { 108523b5cc2aSJani Nikula if (strcmp(node->dev_name, consumer_dev_name) != 0) 10866001e13cSDavid Brownell continue; 108723b5cc2aSJani Nikula } else if (node->dev_name || consumer_dev_name) { 108823b5cc2aSJani Nikula continue; 108923b5cc2aSJani Nikula } 109023b5cc2aSJani Nikula 10916001e13cSDavid Brownell if (strcmp(node->supply, supply) != 0) 10926001e13cSDavid Brownell continue; 10936001e13cSDavid Brownell 1094737f360dSMark Brown pr_debug("%s: %s/%s is '%s' supply; fail %s/%s\n", 1095737f360dSMark Brown consumer_dev_name, 10966001e13cSDavid Brownell dev_name(&node->regulator->dev), 10976001e13cSDavid Brownell node->regulator->desc->name, 10986001e13cSDavid Brownell supply, 10991083c393SMark Brown dev_name(&rdev->dev), rdev_get_name(rdev)); 11006001e13cSDavid Brownell return -EBUSY; 11016001e13cSDavid Brownell } 11026001e13cSDavid Brownell 11039ed2099eSMark Brown node = kzalloc(sizeof(struct regulator_map), GFP_KERNEL); 1104a5766f11SLiam Girdwood if (node == NULL) 1105a5766f11SLiam Girdwood return -ENOMEM; 1106a5766f11SLiam Girdwood 1107a5766f11SLiam Girdwood node->regulator = rdev; 1108a5766f11SLiam Girdwood node->supply = supply; 1109a5766f11SLiam Girdwood 11109ed2099eSMark Brown if (has_dev) { 11119ed2099eSMark Brown node->dev_name = kstrdup(consumer_dev_name, GFP_KERNEL); 111240f9244fSMark Brown if (node->dev_name == NULL) { 111340f9244fSMark Brown kfree(node); 111440f9244fSMark Brown return -ENOMEM; 111540f9244fSMark Brown } 11169ed2099eSMark Brown } 111740f9244fSMark Brown 1118a5766f11SLiam Girdwood list_add(&node->list, ®ulator_map_list); 1119a5766f11SLiam Girdwood return 0; 1120a5766f11SLiam Girdwood } 1121a5766f11SLiam Girdwood 11220f1d747bSMike Rapoport static void unset_regulator_supplies(struct regulator_dev *rdev) 11230f1d747bSMike Rapoport { 11240f1d747bSMike Rapoport struct regulator_map *node, *n; 11250f1d747bSMike Rapoport 11260f1d747bSMike Rapoport list_for_each_entry_safe(node, n, ®ulator_map_list, list) { 11270f1d747bSMike Rapoport if (rdev == node->regulator) { 11280f1d747bSMike Rapoport list_del(&node->list); 112940f9244fSMark Brown kfree(node->dev_name); 11300f1d747bSMike Rapoport kfree(node); 11310f1d747bSMike Rapoport } 11320f1d747bSMike Rapoport } 11330f1d747bSMike Rapoport } 11340f1d747bSMike Rapoport 1135f5726ae3SMark Brown #define REG_STR_SIZE 64 1136414c70cbSLiam Girdwood 1137414c70cbSLiam Girdwood static struct regulator *create_regulator(struct regulator_dev *rdev, 1138414c70cbSLiam Girdwood struct device *dev, 1139414c70cbSLiam Girdwood const char *supply_name) 1140414c70cbSLiam Girdwood { 1141414c70cbSLiam Girdwood struct regulator *regulator; 1142414c70cbSLiam Girdwood char buf[REG_STR_SIZE]; 1143414c70cbSLiam Girdwood int err, size; 1144414c70cbSLiam Girdwood 1145414c70cbSLiam Girdwood regulator = kzalloc(sizeof(*regulator), GFP_KERNEL); 1146414c70cbSLiam Girdwood if (regulator == NULL) 1147414c70cbSLiam Girdwood return NULL; 1148414c70cbSLiam Girdwood 1149414c70cbSLiam Girdwood mutex_lock(&rdev->mutex); 1150414c70cbSLiam Girdwood regulator->rdev = rdev; 1151414c70cbSLiam Girdwood list_add(®ulator->list, &rdev->consumer_list); 1152414c70cbSLiam Girdwood 1153414c70cbSLiam Girdwood if (dev) { 1154e2c98eafSShawn Guo regulator->dev = dev; 1155e2c98eafSShawn Guo 1156222cc7b1SMark Brown /* Add a link to the device sysfs entry */ 1157414c70cbSLiam Girdwood size = scnprintf(buf, REG_STR_SIZE, "%s-%s", 1158414c70cbSLiam Girdwood dev->kobj.name, supply_name); 1159414c70cbSLiam Girdwood if (size >= REG_STR_SIZE) 1160222cc7b1SMark Brown goto overflow_err; 1161414c70cbSLiam Girdwood 1162414c70cbSLiam Girdwood regulator->supply_name = kstrdup(buf, GFP_KERNEL); 1163414c70cbSLiam Girdwood if (regulator->supply_name == NULL) 1164222cc7b1SMark Brown goto overflow_err; 1165414c70cbSLiam Girdwood 1166414c70cbSLiam Girdwood err = sysfs_create_link(&rdev->dev.kobj, &dev->kobj, 1167414c70cbSLiam Girdwood buf); 1168414c70cbSLiam Girdwood if (err) { 11695da84fd9SJoe Perches rdev_warn(rdev, "could not add device link %s err %d\n", 11701d7372e1SDaniel Walker dev->kobj.name, err); 1171222cc7b1SMark Brown /* non-fatal */ 1172414c70cbSLiam Girdwood } 11735de70519SMark Brown } else { 11745de70519SMark Brown regulator->supply_name = kstrdup(supply_name, GFP_KERNEL); 11755de70519SMark Brown if (regulator->supply_name == NULL) 1176222cc7b1SMark Brown goto overflow_err; 1177414c70cbSLiam Girdwood } 11785de70519SMark Brown 11795de70519SMark Brown regulator->debugfs = debugfs_create_dir(regulator->supply_name, 11805de70519SMark Brown rdev->debugfs); 118124751434SStephen Boyd if (!regulator->debugfs) { 11825de70519SMark Brown rdev_warn(rdev, "Failed to create debugfs directory\n"); 11835de70519SMark Brown } else { 11845de70519SMark Brown debugfs_create_u32("uA_load", 0444, regulator->debugfs, 11855de70519SMark Brown ®ulator->uA_load); 11865de70519SMark Brown debugfs_create_u32("min_uV", 0444, regulator->debugfs, 11875de70519SMark Brown ®ulator->min_uV); 11885de70519SMark Brown debugfs_create_u32("max_uV", 0444, regulator->debugfs, 11895de70519SMark Brown ®ulator->max_uV); 11905de70519SMark Brown } 11915de70519SMark Brown 11926492bc1bSMark Brown /* 11936492bc1bSMark Brown * Check now if the regulator is an always on regulator - if 11946492bc1bSMark Brown * it is then we don't need to do nearly so much work for 11956492bc1bSMark Brown * enable/disable calls. 11966492bc1bSMark Brown */ 11976492bc1bSMark Brown if (!_regulator_can_change_status(rdev) && 11986492bc1bSMark Brown _regulator_is_enabled(rdev)) 11996492bc1bSMark Brown regulator->always_on = true; 12006492bc1bSMark Brown 1201414c70cbSLiam Girdwood mutex_unlock(&rdev->mutex); 1202414c70cbSLiam Girdwood return regulator; 1203414c70cbSLiam Girdwood overflow_err: 1204414c70cbSLiam Girdwood list_del(®ulator->list); 1205414c70cbSLiam Girdwood kfree(regulator); 1206414c70cbSLiam Girdwood mutex_unlock(&rdev->mutex); 1207414c70cbSLiam Girdwood return NULL; 1208414c70cbSLiam Girdwood } 1209414c70cbSLiam Girdwood 121031aae2beSMark Brown static int _regulator_get_enable_time(struct regulator_dev *rdev) 121131aae2beSMark Brown { 121200c877c6SLaxman Dewangan if (rdev->constraints && rdev->constraints->enable_time) 121300c877c6SLaxman Dewangan return rdev->constraints->enable_time; 121431aae2beSMark Brown if (!rdev->desc->ops->enable_time) 121579511ed3SMark Brown return rdev->desc->enable_time; 121631aae2beSMark Brown return rdev->desc->ops->enable_time(rdev); 121731aae2beSMark Brown } 121831aae2beSMark Brown 1219a06ccd9cSCharles Keepax static struct regulator_supply_alias *regulator_find_supply_alias( 1220a06ccd9cSCharles Keepax struct device *dev, const char *supply) 1221a06ccd9cSCharles Keepax { 1222a06ccd9cSCharles Keepax struct regulator_supply_alias *map; 1223a06ccd9cSCharles Keepax 1224a06ccd9cSCharles Keepax list_for_each_entry(map, ®ulator_supply_alias_list, list) 1225a06ccd9cSCharles Keepax if (map->src_dev == dev && strcmp(map->src_supply, supply) == 0) 1226a06ccd9cSCharles Keepax return map; 1227a06ccd9cSCharles Keepax 1228a06ccd9cSCharles Keepax return NULL; 1229a06ccd9cSCharles Keepax } 1230a06ccd9cSCharles Keepax 1231a06ccd9cSCharles Keepax static void regulator_supply_alias(struct device **dev, const char **supply) 1232a06ccd9cSCharles Keepax { 1233a06ccd9cSCharles Keepax struct regulator_supply_alias *map; 1234a06ccd9cSCharles Keepax 1235a06ccd9cSCharles Keepax map = regulator_find_supply_alias(*dev, *supply); 1236a06ccd9cSCharles Keepax if (map) { 1237a06ccd9cSCharles Keepax dev_dbg(*dev, "Mapping supply %s to %s,%s\n", 1238a06ccd9cSCharles Keepax *supply, map->alias_supply, 1239a06ccd9cSCharles Keepax dev_name(map->alias_dev)); 1240a06ccd9cSCharles Keepax *dev = map->alias_dev; 1241a06ccd9cSCharles Keepax *supply = map->alias_supply; 1242a06ccd9cSCharles Keepax } 1243a06ccd9cSCharles Keepax } 1244a06ccd9cSCharles Keepax 124569511a45SRajendra Nayak static struct regulator_dev *regulator_dev_lookup(struct device *dev, 12466d191a5fSMark Brown const char *supply, 12476d191a5fSMark Brown int *ret) 124869511a45SRajendra Nayak { 124969511a45SRajendra Nayak struct regulator_dev *r; 125069511a45SRajendra Nayak struct device_node *node; 1251576ca436SMark Brown struct regulator_map *map; 1252576ca436SMark Brown const char *devname = NULL; 125369511a45SRajendra Nayak 1254a06ccd9cSCharles Keepax regulator_supply_alias(&dev, &supply); 1255a06ccd9cSCharles Keepax 125669511a45SRajendra Nayak /* first do a dt based lookup */ 125769511a45SRajendra Nayak if (dev && dev->of_node) { 125869511a45SRajendra Nayak node = of_get_regulator(dev, supply); 12596d191a5fSMark Brown if (node) { 126069511a45SRajendra Nayak list_for_each_entry(r, ®ulator_list, list) 126169511a45SRajendra Nayak if (r->dev.parent && 126269511a45SRajendra Nayak node == r->dev.of_node) 126369511a45SRajendra Nayak return r; 1264317b5684SMark Brown *ret = -EPROBE_DEFER; 1265317b5684SMark Brown return NULL; 12666d191a5fSMark Brown } else { 12676d191a5fSMark Brown /* 12686d191a5fSMark Brown * If we couldn't even get the node then it's 12696d191a5fSMark Brown * not just that the device didn't register 12706d191a5fSMark Brown * yet, there's no node and we'll never 12716d191a5fSMark Brown * succeed. 12726d191a5fSMark Brown */ 12736d191a5fSMark Brown *ret = -ENODEV; 12746d191a5fSMark Brown } 127569511a45SRajendra Nayak } 127669511a45SRajendra Nayak 127769511a45SRajendra Nayak /* if not found, try doing it non-dt way */ 1278576ca436SMark Brown if (dev) 1279576ca436SMark Brown devname = dev_name(dev); 1280576ca436SMark Brown 128169511a45SRajendra Nayak list_for_each_entry(r, ®ulator_list, list) 128269511a45SRajendra Nayak if (strcmp(rdev_get_name(r), supply) == 0) 128369511a45SRajendra Nayak return r; 128469511a45SRajendra Nayak 1285576ca436SMark Brown list_for_each_entry(map, ®ulator_map_list, list) { 1286576ca436SMark Brown /* If the mapping has a device set up it must match */ 1287576ca436SMark Brown if (map->dev_name && 1288576ca436SMark Brown (!devname || strcmp(map->dev_name, devname))) 1289576ca436SMark Brown continue; 1290576ca436SMark Brown 1291576ca436SMark Brown if (strcmp(map->supply, supply) == 0) 1292576ca436SMark Brown return map->regulator; 1293576ca436SMark Brown } 1294576ca436SMark Brown 1295576ca436SMark Brown 129669511a45SRajendra Nayak return NULL; 129769511a45SRajendra Nayak } 129869511a45SRajendra Nayak 12995ffbd136SMark Brown /* Internal regulator request function */ 13005ffbd136SMark Brown static struct regulator *_regulator_get(struct device *dev, const char *id, 13014ddfebd3SMark Brown bool exclusive, bool allow_dummy) 1302414c70cbSLiam Girdwood { 1303414c70cbSLiam Girdwood struct regulator_dev *rdev; 130404bf3011SMark Brown struct regulator *regulator = ERR_PTR(-EPROBE_DEFER); 130540f9244fSMark Brown const char *devname = NULL; 1306317b5684SMark Brown int ret; 1307414c70cbSLiam Girdwood 1308414c70cbSLiam Girdwood if (id == NULL) { 13095da84fd9SJoe Perches pr_err("get() with no identifier\n"); 1310043c998fSMark Brown return ERR_PTR(-EINVAL); 1311414c70cbSLiam Girdwood } 1312414c70cbSLiam Girdwood 131340f9244fSMark Brown if (dev) 131440f9244fSMark Brown devname = dev_name(dev); 131540f9244fSMark Brown 1316317b5684SMark Brown if (have_full_constraints()) 1317317b5684SMark Brown ret = -ENODEV; 1318317b5684SMark Brown else 1319317b5684SMark Brown ret = -EPROBE_DEFER; 1320317b5684SMark Brown 1321414c70cbSLiam Girdwood mutex_lock(®ulator_list_mutex); 1322414c70cbSLiam Girdwood 13236d191a5fSMark Brown rdev = regulator_dev_lookup(dev, id, &ret); 132469511a45SRajendra Nayak if (rdev) 132569511a45SRajendra Nayak goto found; 132669511a45SRajendra Nayak 1327ef60abbbSMark Brown regulator = ERR_PTR(ret); 1328ef60abbbSMark Brown 13291e4b545cSNishanth Menon /* 13301e4b545cSNishanth Menon * If we have return value from dev_lookup fail, we do not expect to 13311e4b545cSNishanth Menon * succeed, so, quit with appropriate error value 13321e4b545cSNishanth Menon */ 13330d25d09dSJingoo Han if (ret && ret != -ENODEV) 13341e4b545cSNishanth Menon goto out; 13351e4b545cSNishanth Menon 133634abbd68SMark Brown if (!devname) 133734abbd68SMark Brown devname = "deviceless"; 133834abbd68SMark Brown 13394ddfebd3SMark Brown /* 13404ddfebd3SMark Brown * Assume that a regulator is physically present and enabled 13414ddfebd3SMark Brown * even if it isn't hooked up and just provide a dummy. 134234abbd68SMark Brown */ 134387b28417SMark Brown if (have_full_constraints() && allow_dummy) { 13445da84fd9SJoe Perches pr_warn("%s supply %s not found, using dummy regulator\n", 134534abbd68SMark Brown devname, id); 13464ddfebd3SMark Brown 134734abbd68SMark Brown rdev = dummy_regulator_rdev; 134834abbd68SMark Brown goto found; 13490781719bSHans de Goede /* Don't log an error when called from regulator_get_optional() */ 13500781719bSHans de Goede } else if (!have_full_constraints() || exclusive) { 1351acc3d5ceSShuah Khan dev_warn(dev, "dummy supplies not allowed\n"); 135234abbd68SMark Brown } 135334abbd68SMark Brown 1354414c70cbSLiam Girdwood mutex_unlock(®ulator_list_mutex); 1355414c70cbSLiam Girdwood return regulator; 1356414c70cbSLiam Girdwood 1357414c70cbSLiam Girdwood found: 13585ffbd136SMark Brown if (rdev->exclusive) { 13595ffbd136SMark Brown regulator = ERR_PTR(-EPERM); 13605ffbd136SMark Brown goto out; 13615ffbd136SMark Brown } 13625ffbd136SMark Brown 13635ffbd136SMark Brown if (exclusive && rdev->open_count) { 13645ffbd136SMark Brown regulator = ERR_PTR(-EBUSY); 13655ffbd136SMark Brown goto out; 13665ffbd136SMark Brown } 13675ffbd136SMark Brown 1368a5766f11SLiam Girdwood if (!try_module_get(rdev->owner)) 1369a5766f11SLiam Girdwood goto out; 1370a5766f11SLiam Girdwood 1371414c70cbSLiam Girdwood regulator = create_regulator(rdev, dev, id); 1372414c70cbSLiam Girdwood if (regulator == NULL) { 1373414c70cbSLiam Girdwood regulator = ERR_PTR(-ENOMEM); 1374414c70cbSLiam Girdwood module_put(rdev->owner); 1375bcda4321SAxel Lin goto out; 1376414c70cbSLiam Girdwood } 1377414c70cbSLiam Girdwood 13785ffbd136SMark Brown rdev->open_count++; 13795ffbd136SMark Brown if (exclusive) { 13805ffbd136SMark Brown rdev->exclusive = 1; 13815ffbd136SMark Brown 13825ffbd136SMark Brown ret = _regulator_is_enabled(rdev); 13835ffbd136SMark Brown if (ret > 0) 13845ffbd136SMark Brown rdev->use_count = 1; 13855ffbd136SMark Brown else 13865ffbd136SMark Brown rdev->use_count = 0; 13875ffbd136SMark Brown } 13885ffbd136SMark Brown 1389a5766f11SLiam Girdwood out: 1390414c70cbSLiam Girdwood mutex_unlock(®ulator_list_mutex); 13915ffbd136SMark Brown 1392414c70cbSLiam Girdwood return regulator; 1393414c70cbSLiam Girdwood } 13945ffbd136SMark Brown 13955ffbd136SMark Brown /** 13965ffbd136SMark Brown * regulator_get - lookup and obtain a reference to a regulator. 13975ffbd136SMark Brown * @dev: device for regulator "consumer" 13985ffbd136SMark Brown * @id: Supply name or regulator ID. 13995ffbd136SMark Brown * 14005ffbd136SMark Brown * Returns a struct regulator corresponding to the regulator producer, 14015ffbd136SMark Brown * or IS_ERR() condition containing errno. 14025ffbd136SMark Brown * 14035ffbd136SMark Brown * Use of supply names configured via regulator_set_device_supply() is 14045ffbd136SMark Brown * strongly encouraged. It is recommended that the supply name used 14055ffbd136SMark Brown * should match the name used for the supply and/or the relevant 14065ffbd136SMark Brown * device pins in the datasheet. 14075ffbd136SMark Brown */ 14085ffbd136SMark Brown struct regulator *regulator_get(struct device *dev, const char *id) 14095ffbd136SMark Brown { 14104ddfebd3SMark Brown return _regulator_get(dev, id, false, true); 14115ffbd136SMark Brown } 1412414c70cbSLiam Girdwood EXPORT_SYMBOL_GPL(regulator_get); 1413414c70cbSLiam Girdwood 1414070b9079SStephen Boyd /** 14155ffbd136SMark Brown * regulator_get_exclusive - obtain exclusive access to a regulator. 14165ffbd136SMark Brown * @dev: device for regulator "consumer" 14175ffbd136SMark Brown * @id: Supply name or regulator ID. 14185ffbd136SMark Brown * 14195ffbd136SMark Brown * Returns a struct regulator corresponding to the regulator producer, 14205ffbd136SMark Brown * or IS_ERR() condition containing errno. Other consumers will be 142169c3f723SStephen Boyd * unable to obtain this regulator while this reference is held and the 142269c3f723SStephen Boyd * use count for the regulator will be initialised to reflect the current 142369c3f723SStephen Boyd * state of the regulator. 14245ffbd136SMark Brown * 14255ffbd136SMark Brown * This is intended for use by consumers which cannot tolerate shared 14265ffbd136SMark Brown * use of the regulator such as those which need to force the 14275ffbd136SMark Brown * regulator off for correct operation of the hardware they are 14285ffbd136SMark Brown * controlling. 14295ffbd136SMark Brown * 14305ffbd136SMark Brown * Use of supply names configured via regulator_set_device_supply() is 14315ffbd136SMark Brown * strongly encouraged. It is recommended that the supply name used 14325ffbd136SMark Brown * should match the name used for the supply and/or the relevant 14335ffbd136SMark Brown * device pins in the datasheet. 14345ffbd136SMark Brown */ 14355ffbd136SMark Brown struct regulator *regulator_get_exclusive(struct device *dev, const char *id) 14365ffbd136SMark Brown { 14374ddfebd3SMark Brown return _regulator_get(dev, id, true, false); 14385ffbd136SMark Brown } 14395ffbd136SMark Brown EXPORT_SYMBOL_GPL(regulator_get_exclusive); 14405ffbd136SMark Brown 1441de1dd9fdSMark Brown /** 1442de1dd9fdSMark Brown * regulator_get_optional - obtain optional access to a regulator. 1443de1dd9fdSMark Brown * @dev: device for regulator "consumer" 1444de1dd9fdSMark Brown * @id: Supply name or regulator ID. 1445de1dd9fdSMark Brown * 1446de1dd9fdSMark Brown * Returns a struct regulator corresponding to the regulator producer, 144769c3f723SStephen Boyd * or IS_ERR() condition containing errno. 1448de1dd9fdSMark Brown * 1449de1dd9fdSMark Brown * This is intended for use by consumers for devices which can have 1450de1dd9fdSMark Brown * some supplies unconnected in normal use, such as some MMC devices. 1451de1dd9fdSMark Brown * It can allow the regulator core to provide stub supplies for other 1452de1dd9fdSMark Brown * supplies requested using normal regulator_get() calls without 1453de1dd9fdSMark Brown * disrupting the operation of drivers that can handle absent 1454de1dd9fdSMark Brown * supplies. 1455de1dd9fdSMark Brown * 1456de1dd9fdSMark Brown * Use of supply names configured via regulator_set_device_supply() is 1457de1dd9fdSMark Brown * strongly encouraged. It is recommended that the supply name used 1458de1dd9fdSMark Brown * should match the name used for the supply and/or the relevant 1459de1dd9fdSMark Brown * device pins in the datasheet. 1460de1dd9fdSMark Brown */ 1461de1dd9fdSMark Brown struct regulator *regulator_get_optional(struct device *dev, const char *id) 1462de1dd9fdSMark Brown { 14634ddfebd3SMark Brown return _regulator_get(dev, id, false, false); 1464de1dd9fdSMark Brown } 1465de1dd9fdSMark Brown EXPORT_SYMBOL_GPL(regulator_get_optional); 1466de1dd9fdSMark Brown 146723ff2f0fSCharles Keepax /* Locks held by regulator_put() */ 146823ff2f0fSCharles Keepax static void _regulator_put(struct regulator *regulator) 1469414c70cbSLiam Girdwood { 1470414c70cbSLiam Girdwood struct regulator_dev *rdev; 1471414c70cbSLiam Girdwood 1472414c70cbSLiam Girdwood if (regulator == NULL || IS_ERR(regulator)) 1473414c70cbSLiam Girdwood return; 1474414c70cbSLiam Girdwood 1475414c70cbSLiam Girdwood rdev = regulator->rdev; 1476414c70cbSLiam Girdwood 14775de70519SMark Brown debugfs_remove_recursive(regulator->debugfs); 14785de70519SMark Brown 1479414c70cbSLiam Girdwood /* remove any sysfs entries */ 1480e2c98eafSShawn Guo if (regulator->dev) 1481414c70cbSLiam Girdwood sysfs_remove_link(&rdev->dev.kobj, regulator->supply_name); 14825de70519SMark Brown kfree(regulator->supply_name); 1483414c70cbSLiam Girdwood list_del(®ulator->list); 1484414c70cbSLiam Girdwood kfree(regulator); 1485414c70cbSLiam Girdwood 14865ffbd136SMark Brown rdev->open_count--; 14875ffbd136SMark Brown rdev->exclusive = 0; 14885ffbd136SMark Brown 1489414c70cbSLiam Girdwood module_put(rdev->owner); 149023ff2f0fSCharles Keepax } 149123ff2f0fSCharles Keepax 149223ff2f0fSCharles Keepax /** 149323ff2f0fSCharles Keepax * regulator_put - "free" the regulator source 149423ff2f0fSCharles Keepax * @regulator: regulator source 149523ff2f0fSCharles Keepax * 149623ff2f0fSCharles Keepax * Note: drivers must ensure that all regulator_enable calls made on this 149723ff2f0fSCharles Keepax * regulator source are balanced by regulator_disable calls prior to calling 149823ff2f0fSCharles Keepax * this function. 149923ff2f0fSCharles Keepax */ 150023ff2f0fSCharles Keepax void regulator_put(struct regulator *regulator) 150123ff2f0fSCharles Keepax { 150223ff2f0fSCharles Keepax mutex_lock(®ulator_list_mutex); 150323ff2f0fSCharles Keepax _regulator_put(regulator); 1504414c70cbSLiam Girdwood mutex_unlock(®ulator_list_mutex); 1505414c70cbSLiam Girdwood } 1506414c70cbSLiam Girdwood EXPORT_SYMBOL_GPL(regulator_put); 1507414c70cbSLiam Girdwood 1508a06ccd9cSCharles Keepax /** 1509a06ccd9cSCharles Keepax * regulator_register_supply_alias - Provide device alias for supply lookup 1510a06ccd9cSCharles Keepax * 1511a06ccd9cSCharles Keepax * @dev: device that will be given as the regulator "consumer" 1512a06ccd9cSCharles Keepax * @id: Supply name or regulator ID 1513a06ccd9cSCharles Keepax * @alias_dev: device that should be used to lookup the supply 1514a06ccd9cSCharles Keepax * @alias_id: Supply name or regulator ID that should be used to lookup the 1515a06ccd9cSCharles Keepax * supply 1516a06ccd9cSCharles Keepax * 1517a06ccd9cSCharles Keepax * All lookups for id on dev will instead be conducted for alias_id on 1518a06ccd9cSCharles Keepax * alias_dev. 1519a06ccd9cSCharles Keepax */ 1520a06ccd9cSCharles Keepax int regulator_register_supply_alias(struct device *dev, const char *id, 1521a06ccd9cSCharles Keepax struct device *alias_dev, 1522a06ccd9cSCharles Keepax const char *alias_id) 1523a06ccd9cSCharles Keepax { 1524a06ccd9cSCharles Keepax struct regulator_supply_alias *map; 1525a06ccd9cSCharles Keepax 1526a06ccd9cSCharles Keepax map = regulator_find_supply_alias(dev, id); 1527a06ccd9cSCharles Keepax if (map) 1528a06ccd9cSCharles Keepax return -EEXIST; 1529a06ccd9cSCharles Keepax 1530a06ccd9cSCharles Keepax map = kzalloc(sizeof(struct regulator_supply_alias), GFP_KERNEL); 1531a06ccd9cSCharles Keepax if (!map) 1532a06ccd9cSCharles Keepax return -ENOMEM; 1533a06ccd9cSCharles Keepax 1534a06ccd9cSCharles Keepax map->src_dev = dev; 1535a06ccd9cSCharles Keepax map->src_supply = id; 1536a06ccd9cSCharles Keepax map->alias_dev = alias_dev; 1537a06ccd9cSCharles Keepax map->alias_supply = alias_id; 1538a06ccd9cSCharles Keepax 1539a06ccd9cSCharles Keepax list_add(&map->list, ®ulator_supply_alias_list); 1540a06ccd9cSCharles Keepax 1541a06ccd9cSCharles Keepax pr_info("Adding alias for supply %s,%s -> %s,%s\n", 1542a06ccd9cSCharles Keepax id, dev_name(dev), alias_id, dev_name(alias_dev)); 1543a06ccd9cSCharles Keepax 1544a06ccd9cSCharles Keepax return 0; 1545a06ccd9cSCharles Keepax } 1546a06ccd9cSCharles Keepax EXPORT_SYMBOL_GPL(regulator_register_supply_alias); 1547a06ccd9cSCharles Keepax 1548a06ccd9cSCharles Keepax /** 1549a06ccd9cSCharles Keepax * regulator_unregister_supply_alias - Remove device alias 1550a06ccd9cSCharles Keepax * 1551a06ccd9cSCharles Keepax * @dev: device that will be given as the regulator "consumer" 1552a06ccd9cSCharles Keepax * @id: Supply name or regulator ID 1553a06ccd9cSCharles Keepax * 1554a06ccd9cSCharles Keepax * Remove a lookup alias if one exists for id on dev. 1555a06ccd9cSCharles Keepax */ 1556a06ccd9cSCharles Keepax void regulator_unregister_supply_alias(struct device *dev, const char *id) 1557a06ccd9cSCharles Keepax { 1558a06ccd9cSCharles Keepax struct regulator_supply_alias *map; 1559a06ccd9cSCharles Keepax 1560a06ccd9cSCharles Keepax map = regulator_find_supply_alias(dev, id); 1561a06ccd9cSCharles Keepax if (map) { 1562a06ccd9cSCharles Keepax list_del(&map->list); 1563a06ccd9cSCharles Keepax kfree(map); 1564a06ccd9cSCharles Keepax } 1565a06ccd9cSCharles Keepax } 1566a06ccd9cSCharles Keepax EXPORT_SYMBOL_GPL(regulator_unregister_supply_alias); 1567a06ccd9cSCharles Keepax 1568a06ccd9cSCharles Keepax /** 1569a06ccd9cSCharles Keepax * regulator_bulk_register_supply_alias - register multiple aliases 1570a06ccd9cSCharles Keepax * 1571a06ccd9cSCharles Keepax * @dev: device that will be given as the regulator "consumer" 1572a06ccd9cSCharles Keepax * @id: List of supply names or regulator IDs 1573a06ccd9cSCharles Keepax * @alias_dev: device that should be used to lookup the supply 1574a06ccd9cSCharles Keepax * @alias_id: List of supply names or regulator IDs that should be used to 1575a06ccd9cSCharles Keepax * lookup the supply 1576a06ccd9cSCharles Keepax * @num_id: Number of aliases to register 1577a06ccd9cSCharles Keepax * 1578a06ccd9cSCharles Keepax * @return 0 on success, an errno on failure. 1579a06ccd9cSCharles Keepax * 1580a06ccd9cSCharles Keepax * This helper function allows drivers to register several supply 1581a06ccd9cSCharles Keepax * aliases in one operation. If any of the aliases cannot be 1582a06ccd9cSCharles Keepax * registered any aliases that were registered will be removed 1583a06ccd9cSCharles Keepax * before returning to the caller. 1584a06ccd9cSCharles Keepax */ 15859f8c0fe9SLee Jones int regulator_bulk_register_supply_alias(struct device *dev, 15869f8c0fe9SLee Jones const char *const *id, 1587a06ccd9cSCharles Keepax struct device *alias_dev, 15889f8c0fe9SLee Jones const char *const *alias_id, 1589a06ccd9cSCharles Keepax int num_id) 1590a06ccd9cSCharles Keepax { 1591a06ccd9cSCharles Keepax int i; 1592a06ccd9cSCharles Keepax int ret; 1593a06ccd9cSCharles Keepax 1594a06ccd9cSCharles Keepax for (i = 0; i < num_id; ++i) { 1595a06ccd9cSCharles Keepax ret = regulator_register_supply_alias(dev, id[i], alias_dev, 1596a06ccd9cSCharles Keepax alias_id[i]); 1597a06ccd9cSCharles Keepax if (ret < 0) 1598a06ccd9cSCharles Keepax goto err; 1599a06ccd9cSCharles Keepax } 1600a06ccd9cSCharles Keepax 1601a06ccd9cSCharles Keepax return 0; 1602a06ccd9cSCharles Keepax 1603a06ccd9cSCharles Keepax err: 1604a06ccd9cSCharles Keepax dev_err(dev, 1605a06ccd9cSCharles Keepax "Failed to create supply alias %s,%s -> %s,%s\n", 1606a06ccd9cSCharles Keepax id[i], dev_name(dev), alias_id[i], dev_name(alias_dev)); 1607a06ccd9cSCharles Keepax 1608a06ccd9cSCharles Keepax while (--i >= 0) 1609a06ccd9cSCharles Keepax regulator_unregister_supply_alias(dev, id[i]); 1610a06ccd9cSCharles Keepax 1611a06ccd9cSCharles Keepax return ret; 1612a06ccd9cSCharles Keepax } 1613a06ccd9cSCharles Keepax EXPORT_SYMBOL_GPL(regulator_bulk_register_supply_alias); 1614a06ccd9cSCharles Keepax 1615a06ccd9cSCharles Keepax /** 1616a06ccd9cSCharles Keepax * regulator_bulk_unregister_supply_alias - unregister multiple aliases 1617a06ccd9cSCharles Keepax * 1618a06ccd9cSCharles Keepax * @dev: device that will be given as the regulator "consumer" 1619a06ccd9cSCharles Keepax * @id: List of supply names or regulator IDs 1620a06ccd9cSCharles Keepax * @num_id: Number of aliases to unregister 1621a06ccd9cSCharles Keepax * 1622a06ccd9cSCharles Keepax * This helper function allows drivers to unregister several supply 1623a06ccd9cSCharles Keepax * aliases in one operation. 1624a06ccd9cSCharles Keepax */ 1625a06ccd9cSCharles Keepax void regulator_bulk_unregister_supply_alias(struct device *dev, 16269f8c0fe9SLee Jones const char *const *id, 1627a06ccd9cSCharles Keepax int num_id) 1628a06ccd9cSCharles Keepax { 1629a06ccd9cSCharles Keepax int i; 1630a06ccd9cSCharles Keepax 1631a06ccd9cSCharles Keepax for (i = 0; i < num_id; ++i) 1632a06ccd9cSCharles Keepax regulator_unregister_supply_alias(dev, id[i]); 1633a06ccd9cSCharles Keepax } 1634a06ccd9cSCharles Keepax EXPORT_SYMBOL_GPL(regulator_bulk_unregister_supply_alias); 1635a06ccd9cSCharles Keepax 1636a06ccd9cSCharles Keepax 1637f19b00daSKim, Milo /* Manage enable GPIO list. Same GPIO pin can be shared among regulators */ 1638f19b00daSKim, Milo static int regulator_ena_gpio_request(struct regulator_dev *rdev, 1639f19b00daSKim, Milo const struct regulator_config *config) 1640f19b00daSKim, Milo { 1641f19b00daSKim, Milo struct regulator_enable_gpio *pin; 1642778b28b4SRussell King struct gpio_desc *gpiod; 1643f19b00daSKim, Milo int ret; 1644f19b00daSKim, Milo 1645778b28b4SRussell King gpiod = gpio_to_desc(config->ena_gpio); 1646778b28b4SRussell King 1647f19b00daSKim, Milo list_for_each_entry(pin, ®ulator_ena_gpio_list, list) { 1648778b28b4SRussell King if (pin->gpiod == gpiod) { 1649f19b00daSKim, Milo rdev_dbg(rdev, "GPIO %d is already used\n", 1650f19b00daSKim, Milo config->ena_gpio); 1651f19b00daSKim, Milo goto update_ena_gpio_to_rdev; 1652f19b00daSKim, Milo } 1653f19b00daSKim, Milo } 1654f19b00daSKim, Milo 1655f19b00daSKim, Milo ret = gpio_request_one(config->ena_gpio, 1656f19b00daSKim, Milo GPIOF_DIR_OUT | config->ena_gpio_flags, 1657f19b00daSKim, Milo rdev_get_name(rdev)); 1658f19b00daSKim, Milo if (ret) 1659f19b00daSKim, Milo return ret; 1660f19b00daSKim, Milo 1661f19b00daSKim, Milo pin = kzalloc(sizeof(struct regulator_enable_gpio), GFP_KERNEL); 1662f19b00daSKim, Milo if (pin == NULL) { 1663f19b00daSKim, Milo gpio_free(config->ena_gpio); 1664f19b00daSKim, Milo return -ENOMEM; 1665f19b00daSKim, Milo } 1666f19b00daSKim, Milo 1667778b28b4SRussell King pin->gpiod = gpiod; 1668f19b00daSKim, Milo pin->ena_gpio_invert = config->ena_gpio_invert; 1669f19b00daSKim, Milo list_add(&pin->list, ®ulator_ena_gpio_list); 1670f19b00daSKim, Milo 1671f19b00daSKim, Milo update_ena_gpio_to_rdev: 1672f19b00daSKim, Milo pin->request_count++; 1673f19b00daSKim, Milo rdev->ena_pin = pin; 1674f19b00daSKim, Milo return 0; 1675f19b00daSKim, Milo } 1676f19b00daSKim, Milo 1677f19b00daSKim, Milo static void regulator_ena_gpio_free(struct regulator_dev *rdev) 1678f19b00daSKim, Milo { 1679f19b00daSKim, Milo struct regulator_enable_gpio *pin, *n; 1680f19b00daSKim, Milo 1681f19b00daSKim, Milo if (!rdev->ena_pin) 1682f19b00daSKim, Milo return; 1683f19b00daSKim, Milo 1684f19b00daSKim, Milo /* Free the GPIO only in case of no use */ 1685f19b00daSKim, Milo list_for_each_entry_safe(pin, n, ®ulator_ena_gpio_list, list) { 1686778b28b4SRussell King if (pin->gpiod == rdev->ena_pin->gpiod) { 1687f19b00daSKim, Milo if (pin->request_count <= 1) { 1688f19b00daSKim, Milo pin->request_count = 0; 1689778b28b4SRussell King gpiod_put(pin->gpiod); 1690f19b00daSKim, Milo list_del(&pin->list); 1691f19b00daSKim, Milo kfree(pin); 169260a2362fSSeung-Woo Kim rdev->ena_pin = NULL; 169360a2362fSSeung-Woo Kim return; 1694f19b00daSKim, Milo } else { 1695f19b00daSKim, Milo pin->request_count--; 1696f19b00daSKim, Milo } 1697f19b00daSKim, Milo } 1698f19b00daSKim, Milo } 1699f19b00daSKim, Milo } 1700f19b00daSKim, Milo 1701967cfb18SKim, Milo /** 170231d6eebfSRobert P. J. Day * regulator_ena_gpio_ctrl - balance enable_count of each GPIO and actual GPIO pin control 170331d6eebfSRobert P. J. Day * @rdev: regulator_dev structure 170431d6eebfSRobert P. J. Day * @enable: enable GPIO at initial use? 170531d6eebfSRobert P. J. Day * 1706967cfb18SKim, Milo * GPIO is enabled in case of initial use. (enable_count is 0) 1707967cfb18SKim, Milo * GPIO is disabled when it is not shared any more. (enable_count <= 1) 1708967cfb18SKim, Milo */ 1709967cfb18SKim, Milo static int regulator_ena_gpio_ctrl(struct regulator_dev *rdev, bool enable) 1710967cfb18SKim, Milo { 1711967cfb18SKim, Milo struct regulator_enable_gpio *pin = rdev->ena_pin; 1712967cfb18SKim, Milo 1713967cfb18SKim, Milo if (!pin) 1714967cfb18SKim, Milo return -EINVAL; 1715967cfb18SKim, Milo 1716967cfb18SKim, Milo if (enable) { 1717967cfb18SKim, Milo /* Enable GPIO at initial use */ 1718967cfb18SKim, Milo if (pin->enable_count == 0) 1719778b28b4SRussell King gpiod_set_value_cansleep(pin->gpiod, 1720967cfb18SKim, Milo !pin->ena_gpio_invert); 1721967cfb18SKim, Milo 1722967cfb18SKim, Milo pin->enable_count++; 1723967cfb18SKim, Milo } else { 1724967cfb18SKim, Milo if (pin->enable_count > 1) { 1725967cfb18SKim, Milo pin->enable_count--; 1726967cfb18SKim, Milo return 0; 1727967cfb18SKim, Milo } 1728967cfb18SKim, Milo 1729967cfb18SKim, Milo /* Disable GPIO if not used */ 1730967cfb18SKim, Milo if (pin->enable_count <= 1) { 1731778b28b4SRussell King gpiod_set_value_cansleep(pin->gpiod, 1732967cfb18SKim, Milo pin->ena_gpio_invert); 1733967cfb18SKim, Milo pin->enable_count = 0; 1734967cfb18SKim, Milo } 1735967cfb18SKim, Milo } 1736967cfb18SKim, Milo 1737967cfb18SKim, Milo return 0; 1738967cfb18SKim, Milo } 1739967cfb18SKim, Milo 174079fd1141SGuodong Xu /** 174179fd1141SGuodong Xu * _regulator_enable_delay - a delay helper function 174279fd1141SGuodong Xu * @delay: time to delay in microseconds 174379fd1141SGuodong Xu * 17445df529d4SThierry Reding * Delay for the requested amount of time as per the guidelines in: 17455df529d4SThierry Reding * 17465df529d4SThierry Reding * Documentation/timers/timers-howto.txt 17475df529d4SThierry Reding * 17485df529d4SThierry Reding * The assumption here is that regulators will never be enabled in 17495df529d4SThierry Reding * atomic context and therefore sleeping functions can be used. 17505df529d4SThierry Reding */ 175179fd1141SGuodong Xu static void _regulator_enable_delay(unsigned int delay) 175279fd1141SGuodong Xu { 17535df529d4SThierry Reding unsigned int ms = delay / 1000; 17545df529d4SThierry Reding unsigned int us = delay % 1000; 17555df529d4SThierry Reding 17565df529d4SThierry Reding if (ms > 0) { 17575df529d4SThierry Reding /* 17585df529d4SThierry Reding * For small enough values, handle super-millisecond 17595df529d4SThierry Reding * delays in the usleep_range() call below. 17605df529d4SThierry Reding */ 17615df529d4SThierry Reding if (ms < 20) 17625df529d4SThierry Reding us += ms * 1000; 17635df529d4SThierry Reding else 17645df529d4SThierry Reding msleep(ms); 17655df529d4SThierry Reding } 17665df529d4SThierry Reding 17675df529d4SThierry Reding /* 17685df529d4SThierry Reding * Give the scheduler some room to coalesce with any other 17695df529d4SThierry Reding * wakeup sources. For delays shorter than 10 us, don't even 17705df529d4SThierry Reding * bother setting up high-resolution timers and just busy- 17715df529d4SThierry Reding * loop. 17725df529d4SThierry Reding */ 17735df529d4SThierry Reding if (us >= 10) 17745df529d4SThierry Reding usleep_range(us, us + 100); 17755df529d4SThierry Reding else 17765df529d4SThierry Reding udelay(us); 17775c5659d0SMark Brown } 17785c5659d0SMark Brown 17795c5659d0SMark Brown static int _regulator_do_enable(struct regulator_dev *rdev) 17805c5659d0SMark Brown { 17815c5659d0SMark Brown int ret, delay; 17825c5659d0SMark Brown 17835c5659d0SMark Brown /* Query before enabling in case configuration dependent. */ 17845c5659d0SMark Brown ret = _regulator_get_enable_time(rdev); 17855c5659d0SMark Brown if (ret >= 0) { 17865c5659d0SMark Brown delay = ret; 17875c5659d0SMark Brown } else { 1788414c70cbSLiam Girdwood rdev_warn(rdev, "enable_time() failed: %d\n", ret); 1789414c70cbSLiam Girdwood delay = 0; 1790414c70cbSLiam Girdwood } 17915c5659d0SMark Brown 1792414c70cbSLiam Girdwood trace_regulator_enable(rdev_get_name(rdev)); 1793414c70cbSLiam Girdwood 1794871f5650SGuodong Xu if (rdev->desc->off_on_delay) { 1795871f5650SGuodong Xu /* if needed, keep a distance of off_on_delay from last time 1796871f5650SGuodong Xu * this regulator was disabled. 1797871f5650SGuodong Xu */ 1798871f5650SGuodong Xu unsigned long start_jiffy = jiffies; 1799871f5650SGuodong Xu unsigned long intended, max_delay, remaining; 1800871f5650SGuodong Xu 1801871f5650SGuodong Xu max_delay = usecs_to_jiffies(rdev->desc->off_on_delay); 1802871f5650SGuodong Xu intended = rdev->last_off_jiffy + max_delay; 1803871f5650SGuodong Xu 1804871f5650SGuodong Xu if (time_before(start_jiffy, intended)) { 1805871f5650SGuodong Xu /* calc remaining jiffies to deal with one-time 1806871f5650SGuodong Xu * timer wrapping. 1807871f5650SGuodong Xu * in case of multiple timer wrapping, either it can be 1808871f5650SGuodong Xu * detected by out-of-range remaining, or it cannot be 1809871f5650SGuodong Xu * detected and we gets a panelty of 1810871f5650SGuodong Xu * _regulator_enable_delay(). 1811871f5650SGuodong Xu */ 1812871f5650SGuodong Xu remaining = intended - start_jiffy; 1813871f5650SGuodong Xu if (remaining <= max_delay) 1814871f5650SGuodong Xu _regulator_enable_delay( 1815871f5650SGuodong Xu jiffies_to_usecs(remaining)); 1816871f5650SGuodong Xu } 1817871f5650SGuodong Xu } 1818871f5650SGuodong Xu 1819414c70cbSLiam Girdwood if (rdev->ena_pin) { 18209a2372faSMark Brown ret = regulator_ena_gpio_ctrl(rdev, true); 1821414c70cbSLiam Girdwood if (ret < 0) 1822414c70cbSLiam Girdwood return ret; 18239a2372faSMark Brown rdev->ena_gpio_state = 1; 18249a2372faSMark Brown } else if (rdev->desc->ops->enable) { 18259a2372faSMark Brown ret = rdev->desc->ops->enable(rdev); 18269a2372faSMark Brown if (ret < 0) 18279a2372faSMark Brown return ret; 18289a2372faSMark Brown } else { 18299a2372faSMark Brown return -EINVAL; 18305c5659d0SMark Brown } 18319a2372faSMark Brown 18329a2372faSMark Brown /* Allow the regulator to ramp; it would be useful to extend 183331aae2beSMark Brown * this for bulk operations so that the regulators can ramp 1834a7433cffSLinus Walleij * together. */ 18355da84fd9SJoe Perches trace_regulator_enable_delay(rdev_get_name(rdev)); 1836414c70cbSLiam Girdwood 183779fd1141SGuodong Xu _regulator_enable_delay(delay); 1838a7433cffSLinus Walleij 1839414c70cbSLiam Girdwood trace_regulator_enable_complete(rdev_get_name(rdev)); 1840414c70cbSLiam Girdwood 18419a2372faSMark Brown return 0; 18429a2372faSMark Brown } 18439a2372faSMark Brown 1844414c70cbSLiam Girdwood /* locks held by regulator_enable() */ 1845414c70cbSLiam Girdwood static int _regulator_enable(struct regulator_dev *rdev) 1846414c70cbSLiam Girdwood { 1847414c70cbSLiam Girdwood int ret; 1848414c70cbSLiam Girdwood 1849414c70cbSLiam Girdwood /* check voltage and requested load before enabling */ 1850cf7bbcdfSMark Brown if (rdev->constraints && 1851cf7bbcdfSMark Brown (rdev->constraints->valid_ops_mask & REGULATOR_CHANGE_DRMS)) 1852cf7bbcdfSMark Brown drms_uA_update(rdev); 1853cf7bbcdfSMark Brown 1854414c70cbSLiam Girdwood if (rdev->use_count == 0) { 1855cf7bbcdfSMark Brown /* The regulator may on if it's not switchable or left on */ 1856414c70cbSLiam Girdwood ret = _regulator_is_enabled(rdev); 1857414c70cbSLiam Girdwood if (ret == -EINVAL || ret == 0) { 1858414c70cbSLiam Girdwood if (!_regulator_can_change_status(rdev)) 1859412aec61SDavid Brownell return -EPERM; 1860412aec61SDavid Brownell 1861414c70cbSLiam Girdwood ret = _regulator_do_enable(rdev); 1862412aec61SDavid Brownell if (ret < 0) 1863412aec61SDavid Brownell return ret; 1864412aec61SDavid Brownell 1865414c70cbSLiam Girdwood } else if (ret < 0) { 1866414c70cbSLiam Girdwood rdev_err(rdev, "is_enabled() failed: %d\n", ret); 1867414c70cbSLiam Girdwood return ret; 1868414c70cbSLiam Girdwood } 1869414c70cbSLiam Girdwood /* Fallthrough on positive return values - already enabled */ 1870414c70cbSLiam Girdwood } 1871414c70cbSLiam Girdwood 1872414c70cbSLiam Girdwood rdev->use_count++; 1873414c70cbSLiam Girdwood 1874cd94b505SDavid Brownell return 0; 1875cd94b505SDavid Brownell } 18761083c393SMark Brown 1877cd94b505SDavid Brownell /** 1878cd94b505SDavid Brownell * regulator_enable - enable regulator output 1879414c70cbSLiam Girdwood * @regulator: regulator source 188060ef66fcSMark Brown * 188160ef66fcSMark Brown * Request that the regulator be enabled with the regulator output at 1882414c70cbSLiam Girdwood * the predefined voltage or current value. Calls to regulator_enable() 1883414c70cbSLiam Girdwood * must be balanced with calls to regulator_disable(). 18849a2372faSMark Brown * 18859a2372faSMark Brown * NOTE: the output value can be set by other drivers, boot loader or may be 1886414c70cbSLiam Girdwood * hardwired in the regulator. 1887414c70cbSLiam Girdwood */ 1888414c70cbSLiam Girdwood int regulator_enable(struct regulator *regulator) 18891083c393SMark Brown { 1890414c70cbSLiam Girdwood struct regulator_dev *rdev = regulator->rdev; 1891414c70cbSLiam Girdwood int ret = 0; 189284b68263SMark Brown 18936492bc1bSMark Brown if (regulator->always_on) 18946492bc1bSMark Brown return 0; 18956492bc1bSMark Brown 18963801b86aSMark Brown if (rdev->supply) { 18973801b86aSMark Brown ret = regulator_enable(rdev->supply); 18983801b86aSMark Brown if (ret != 0) 18993801b86aSMark Brown return ret; 19003801b86aSMark Brown } 19013801b86aSMark Brown 1902414c70cbSLiam Girdwood mutex_lock(&rdev->mutex); 1903414c70cbSLiam Girdwood ret = _regulator_enable(rdev); 1904414c70cbSLiam Girdwood mutex_unlock(&rdev->mutex); 19053801b86aSMark Brown 1906d1685e4eSHeiko Stübner if (ret != 0 && rdev->supply) 19073801b86aSMark Brown regulator_disable(rdev->supply); 19083801b86aSMark Brown 1909414c70cbSLiam Girdwood return ret; 1910414c70cbSLiam Girdwood } 1911414c70cbSLiam Girdwood EXPORT_SYMBOL_GPL(regulator_enable); 1912414c70cbSLiam Girdwood 19135c5659d0SMark Brown static int _regulator_do_disable(struct regulator_dev *rdev) 19145c5659d0SMark Brown { 19155c5659d0SMark Brown int ret; 19165c5659d0SMark Brown 19175c5659d0SMark Brown trace_regulator_disable(rdev_get_name(rdev)); 19185c5659d0SMark Brown 1919967cfb18SKim, Milo if (rdev->ena_pin) { 1920967cfb18SKim, Milo ret = regulator_ena_gpio_ctrl(rdev, false); 1921967cfb18SKim, Milo if (ret < 0) 1922967cfb18SKim, Milo return ret; 19235c5659d0SMark Brown rdev->ena_gpio_state = 0; 19245c5659d0SMark Brown 19255c5659d0SMark Brown } else if (rdev->desc->ops->disable) { 19265c5659d0SMark Brown ret = rdev->desc->ops->disable(rdev); 19275c5659d0SMark Brown if (ret != 0) 19285c5659d0SMark Brown return ret; 19295c5659d0SMark Brown } 19305c5659d0SMark Brown 1931871f5650SGuodong Xu /* cares about last_off_jiffy only if off_on_delay is required by 1932871f5650SGuodong Xu * device. 1933871f5650SGuodong Xu */ 1934871f5650SGuodong Xu if (rdev->desc->off_on_delay) 1935871f5650SGuodong Xu rdev->last_off_jiffy = jiffies; 1936871f5650SGuodong Xu 19375c5659d0SMark Brown trace_regulator_disable_complete(rdev_get_name(rdev)); 19385c5659d0SMark Brown 19395c5659d0SMark Brown return 0; 19405c5659d0SMark Brown } 19415c5659d0SMark Brown 1942414c70cbSLiam Girdwood /* locks held by regulator_disable() */ 19433801b86aSMark Brown static int _regulator_disable(struct regulator_dev *rdev) 1944414c70cbSLiam Girdwood { 1945414c70cbSLiam Girdwood int ret = 0; 1946414c70cbSLiam Girdwood 1947414c70cbSLiam Girdwood if (WARN(rdev->use_count <= 0, 194843e7ee33SJoe Perches "unbalanced disables for %s\n", rdev_get_name(rdev))) 1949414c70cbSLiam Girdwood return -EIO; 1950414c70cbSLiam Girdwood 1951414c70cbSLiam Girdwood /* are we the last user and permitted to disable ? */ 1952414c70cbSLiam Girdwood if (rdev->use_count == 1 && 1953414c70cbSLiam Girdwood (rdev->constraints && !rdev->constraints->always_on)) { 1954414c70cbSLiam Girdwood 1955414c70cbSLiam Girdwood /* we are last user */ 19565c5659d0SMark Brown if (_regulator_can_change_status(rdev)) { 1957a1c8a551SRichard Fitzgerald ret = _notifier_call_chain(rdev, 1958a1c8a551SRichard Fitzgerald REGULATOR_EVENT_PRE_DISABLE, 1959a1c8a551SRichard Fitzgerald NULL); 1960a1c8a551SRichard Fitzgerald if (ret & NOTIFY_STOP_MASK) 1961a1c8a551SRichard Fitzgerald return -EINVAL; 1962a1c8a551SRichard Fitzgerald 19635c5659d0SMark Brown ret = _regulator_do_disable(rdev); 1964414c70cbSLiam Girdwood if (ret < 0) { 19655da84fd9SJoe Perches rdev_err(rdev, "failed to disable\n"); 1966a1c8a551SRichard Fitzgerald _notifier_call_chain(rdev, 1967a1c8a551SRichard Fitzgerald REGULATOR_EVENT_ABORT_DISABLE, 1968a1c8a551SRichard Fitzgerald NULL); 1969414c70cbSLiam Girdwood return ret; 1970414c70cbSLiam Girdwood } 197166fda75fSMarkus Pargmann _notifier_call_chain(rdev, REGULATOR_EVENT_DISABLE, 197266fda75fSMarkus Pargmann NULL); 1973414c70cbSLiam Girdwood } 1974414c70cbSLiam Girdwood 1975414c70cbSLiam Girdwood rdev->use_count = 0; 1976414c70cbSLiam Girdwood } else if (rdev->use_count > 1) { 1977414c70cbSLiam Girdwood 1978414c70cbSLiam Girdwood if (rdev->constraints && 1979414c70cbSLiam Girdwood (rdev->constraints->valid_ops_mask & 1980414c70cbSLiam Girdwood REGULATOR_CHANGE_DRMS)) 1981414c70cbSLiam Girdwood drms_uA_update(rdev); 1982414c70cbSLiam Girdwood 1983414c70cbSLiam Girdwood rdev->use_count--; 1984414c70cbSLiam Girdwood } 19853801b86aSMark Brown 1986414c70cbSLiam Girdwood return ret; 1987414c70cbSLiam Girdwood } 1988414c70cbSLiam Girdwood 1989414c70cbSLiam Girdwood /** 1990414c70cbSLiam Girdwood * regulator_disable - disable regulator output 1991414c70cbSLiam Girdwood * @regulator: regulator source 1992414c70cbSLiam Girdwood * 1993cf7bbcdfSMark Brown * Disable the regulator output voltage or current. Calls to 1994cf7bbcdfSMark Brown * regulator_enable() must be balanced with calls to 1995cf7bbcdfSMark Brown * regulator_disable(). 199669279fb9SMark Brown * 1997414c70cbSLiam Girdwood * NOTE: this will only disable the regulator output if no other consumer 1998cf7bbcdfSMark Brown * devices have it enabled, the regulator device supports disabling and 1999cf7bbcdfSMark Brown * machine constraints permit this operation. 2000414c70cbSLiam Girdwood */ 2001414c70cbSLiam Girdwood int regulator_disable(struct regulator *regulator) 2002414c70cbSLiam Girdwood { 2003412aec61SDavid Brownell struct regulator_dev *rdev = regulator->rdev; 2004412aec61SDavid Brownell int ret = 0; 2005414c70cbSLiam Girdwood 20066492bc1bSMark Brown if (regulator->always_on) 20076492bc1bSMark Brown return 0; 20086492bc1bSMark Brown 2009412aec61SDavid Brownell mutex_lock(&rdev->mutex); 20103801b86aSMark Brown ret = _regulator_disable(rdev); 2011412aec61SDavid Brownell mutex_unlock(&rdev->mutex); 20128cbf811dSJeffrey Carlyle 20133801b86aSMark Brown if (ret == 0 && rdev->supply) 20143801b86aSMark Brown regulator_disable(rdev->supply); 20158cbf811dSJeffrey Carlyle 2016414c70cbSLiam Girdwood return ret; 2017414c70cbSLiam Girdwood } 2018414c70cbSLiam Girdwood EXPORT_SYMBOL_GPL(regulator_disable); 2019414c70cbSLiam Girdwood 2020414c70cbSLiam Girdwood /* locks held by regulator_force_disable() */ 20213801b86aSMark Brown static int _regulator_force_disable(struct regulator_dev *rdev) 2022414c70cbSLiam Girdwood { 2023414c70cbSLiam Girdwood int ret = 0; 2024414c70cbSLiam Girdwood 2025a1c8a551SRichard Fitzgerald ret = _notifier_call_chain(rdev, REGULATOR_EVENT_FORCE_DISABLE | 2026a1c8a551SRichard Fitzgerald REGULATOR_EVENT_PRE_DISABLE, NULL); 2027a1c8a551SRichard Fitzgerald if (ret & NOTIFY_STOP_MASK) 2028a1c8a551SRichard Fitzgerald return -EINVAL; 2029a1c8a551SRichard Fitzgerald 203066fda75fSMarkus Pargmann ret = _regulator_do_disable(rdev); 2031414c70cbSLiam Girdwood if (ret < 0) { 20325da84fd9SJoe Perches rdev_err(rdev, "failed to force disable\n"); 2033a1c8a551SRichard Fitzgerald _notifier_call_chain(rdev, REGULATOR_EVENT_FORCE_DISABLE | 2034a1c8a551SRichard Fitzgerald REGULATOR_EVENT_ABORT_DISABLE, NULL); 2035414c70cbSLiam Girdwood return ret; 2036414c70cbSLiam Girdwood } 203766fda75fSMarkus Pargmann 203884b68263SMark Brown _notifier_call_chain(rdev, REGULATOR_EVENT_FORCE_DISABLE | 203984b68263SMark Brown REGULATOR_EVENT_DISABLE, NULL); 2040414c70cbSLiam Girdwood 204166fda75fSMarkus Pargmann return 0; 2042414c70cbSLiam Girdwood } 2043414c70cbSLiam Girdwood 2044414c70cbSLiam Girdwood /** 2045414c70cbSLiam Girdwood * regulator_force_disable - force disable regulator output 2046414c70cbSLiam Girdwood * @regulator: regulator source 2047414c70cbSLiam Girdwood * 2048414c70cbSLiam Girdwood * Forcibly disable the regulator output voltage or current. 2049414c70cbSLiam Girdwood * NOTE: this *will* disable the regulator output even if other consumer 2050414c70cbSLiam Girdwood * devices have it enabled. This should be used for situations when device 2051414c70cbSLiam Girdwood * damage will likely occur if the regulator is not disabled (e.g. over temp). 2052414c70cbSLiam Girdwood */ 2053414c70cbSLiam Girdwood int regulator_force_disable(struct regulator *regulator) 2054414c70cbSLiam Girdwood { 205582d15839SMark Brown struct regulator_dev *rdev = regulator->rdev; 2056414c70cbSLiam Girdwood int ret; 2057414c70cbSLiam Girdwood 205882d15839SMark Brown mutex_lock(&rdev->mutex); 2059414c70cbSLiam Girdwood regulator->uA_load = 0; 20603801b86aSMark Brown ret = _regulator_force_disable(regulator->rdev); 206182d15839SMark Brown mutex_unlock(&rdev->mutex); 20628cbf811dSJeffrey Carlyle 20633801b86aSMark Brown if (rdev->supply) 20643801b86aSMark Brown while (rdev->open_count--) 20653801b86aSMark Brown regulator_disable(rdev->supply); 20668cbf811dSJeffrey Carlyle 2067414c70cbSLiam Girdwood return ret; 2068414c70cbSLiam Girdwood } 2069414c70cbSLiam Girdwood EXPORT_SYMBOL_GPL(regulator_force_disable); 2070414c70cbSLiam Girdwood 2071da07ecd9SMark Brown static void regulator_disable_work(struct work_struct *work) 2072da07ecd9SMark Brown { 2073da07ecd9SMark Brown struct regulator_dev *rdev = container_of(work, struct regulator_dev, 2074da07ecd9SMark Brown disable_work.work); 2075da07ecd9SMark Brown int count, i, ret; 2076da07ecd9SMark Brown 2077da07ecd9SMark Brown mutex_lock(&rdev->mutex); 2078da07ecd9SMark Brown 2079da07ecd9SMark Brown BUG_ON(!rdev->deferred_disables); 2080da07ecd9SMark Brown 2081da07ecd9SMark Brown count = rdev->deferred_disables; 2082da07ecd9SMark Brown rdev->deferred_disables = 0; 2083da07ecd9SMark Brown 2084da07ecd9SMark Brown for (i = 0; i < count; i++) { 2085da07ecd9SMark Brown ret = _regulator_disable(rdev); 2086da07ecd9SMark Brown if (ret != 0) 2087da07ecd9SMark Brown rdev_err(rdev, "Deferred disable failed: %d\n", ret); 2088da07ecd9SMark Brown } 2089da07ecd9SMark Brown 2090da07ecd9SMark Brown mutex_unlock(&rdev->mutex); 2091da07ecd9SMark Brown 2092da07ecd9SMark Brown if (rdev->supply) { 2093da07ecd9SMark Brown for (i = 0; i < count; i++) { 2094da07ecd9SMark Brown ret = regulator_disable(rdev->supply); 2095da07ecd9SMark Brown if (ret != 0) { 2096da07ecd9SMark Brown rdev_err(rdev, 2097da07ecd9SMark Brown "Supply disable failed: %d\n", ret); 2098da07ecd9SMark Brown } 2099da07ecd9SMark Brown } 2100da07ecd9SMark Brown } 2101da07ecd9SMark Brown } 2102da07ecd9SMark Brown 2103da07ecd9SMark Brown /** 2104da07ecd9SMark Brown * regulator_disable_deferred - disable regulator output with delay 2105da07ecd9SMark Brown * @regulator: regulator source 2106da07ecd9SMark Brown * @ms: miliseconds until the regulator is disabled 2107da07ecd9SMark Brown * 2108da07ecd9SMark Brown * Execute regulator_disable() on the regulator after a delay. This 2109da07ecd9SMark Brown * is intended for use with devices that require some time to quiesce. 2110da07ecd9SMark Brown * 2111da07ecd9SMark Brown * NOTE: this will only disable the regulator output if no other consumer 2112da07ecd9SMark Brown * devices have it enabled, the regulator device supports disabling and 2113da07ecd9SMark Brown * machine constraints permit this operation. 2114da07ecd9SMark Brown */ 2115da07ecd9SMark Brown int regulator_disable_deferred(struct regulator *regulator, int ms) 2116da07ecd9SMark Brown { 2117da07ecd9SMark Brown struct regulator_dev *rdev = regulator->rdev; 2118aa59802dSMark Brown int ret; 2119da07ecd9SMark Brown 21206492bc1bSMark Brown if (regulator->always_on) 21216492bc1bSMark Brown return 0; 21226492bc1bSMark Brown 21232b5a24a0SMark Brown if (!ms) 21242b5a24a0SMark Brown return regulator_disable(regulator); 21252b5a24a0SMark Brown 2126da07ecd9SMark Brown mutex_lock(&rdev->mutex); 2127da07ecd9SMark Brown rdev->deferred_disables++; 2128da07ecd9SMark Brown mutex_unlock(&rdev->mutex); 2129da07ecd9SMark Brown 2130070260f0SMark Brown ret = queue_delayed_work(system_power_efficient_wq, 2131070260f0SMark Brown &rdev->disable_work, 2132da07ecd9SMark Brown msecs_to_jiffies(ms)); 2133aa59802dSMark Brown if (ret < 0) 2134aa59802dSMark Brown return ret; 2135aa59802dSMark Brown else 2136aa59802dSMark Brown return 0; 2137da07ecd9SMark Brown } 2138da07ecd9SMark Brown EXPORT_SYMBOL_GPL(regulator_disable_deferred); 2139da07ecd9SMark Brown 2140414c70cbSLiam Girdwood static int _regulator_is_enabled(struct regulator_dev *rdev) 2141414c70cbSLiam Girdwood { 214265f73508SMark Brown /* A GPIO control always takes precedence */ 21437b74d149SKim, Milo if (rdev->ena_pin) 214465f73508SMark Brown return rdev->ena_gpio_state; 214565f73508SMark Brown 21469a7f6a4cSMark Brown /* If we don't know then assume that the regulator is always on */ 21479332546fSMark Brown if (!rdev->desc->ops->is_enabled) 21489a7f6a4cSMark Brown return 1; 2149414c70cbSLiam Girdwood 21509332546fSMark Brown return rdev->desc->ops->is_enabled(rdev); 2151414c70cbSLiam Girdwood } 2152414c70cbSLiam Girdwood 2153414c70cbSLiam Girdwood /** 2154414c70cbSLiam Girdwood * regulator_is_enabled - is the regulator output enabled 2155414c70cbSLiam Girdwood * @regulator: regulator source 2156414c70cbSLiam Girdwood * 2157412aec61SDavid Brownell * Returns positive if the regulator driver backing the source/client 2158412aec61SDavid Brownell * has requested that the device be enabled, zero if it hasn't, else a 2159412aec61SDavid Brownell * negative errno code. 2160412aec61SDavid Brownell * 2161412aec61SDavid Brownell * Note that the device backing this regulator handle can have multiple 2162412aec61SDavid Brownell * users, so it might be enabled even if regulator_enable() was never 2163412aec61SDavid Brownell * called for this particular source. 2164414c70cbSLiam Girdwood */ 2165414c70cbSLiam Girdwood int regulator_is_enabled(struct regulator *regulator) 2166414c70cbSLiam Girdwood { 21679332546fSMark Brown int ret; 21689332546fSMark Brown 21696492bc1bSMark Brown if (regulator->always_on) 21706492bc1bSMark Brown return 1; 21716492bc1bSMark Brown 21729332546fSMark Brown mutex_lock(®ulator->rdev->mutex); 21739332546fSMark Brown ret = _regulator_is_enabled(regulator->rdev); 21749332546fSMark Brown mutex_unlock(®ulator->rdev->mutex); 21759332546fSMark Brown 21769332546fSMark Brown return ret; 2177414c70cbSLiam Girdwood } 2178414c70cbSLiam Girdwood EXPORT_SYMBOL_GPL(regulator_is_enabled); 2179414c70cbSLiam Girdwood 2180414c70cbSLiam Girdwood /** 2181d1e7de30SMarek Szyprowski * regulator_can_change_voltage - check if regulator can change voltage 2182d1e7de30SMarek Szyprowski * @regulator: regulator source 2183d1e7de30SMarek Szyprowski * 2184d1e7de30SMarek Szyprowski * Returns positive if the regulator driver backing the source/client 2185e227867fSMasanari Iida * can change its voltage, false otherwise. Useful for detecting fixed 2186d1e7de30SMarek Szyprowski * or dummy regulators and disabling voltage change logic in the client 2187d1e7de30SMarek Szyprowski * driver. 2188d1e7de30SMarek Szyprowski */ 2189d1e7de30SMarek Szyprowski int regulator_can_change_voltage(struct regulator *regulator) 2190d1e7de30SMarek Szyprowski { 2191d1e7de30SMarek Szyprowski struct regulator_dev *rdev = regulator->rdev; 2192d1e7de30SMarek Szyprowski 2193d1e7de30SMarek Szyprowski if (rdev->constraints && 219419280e40SAxel Lin (rdev->constraints->valid_ops_mask & REGULATOR_CHANGE_VOLTAGE)) { 219519280e40SAxel Lin if (rdev->desc->n_voltages - rdev->desc->linear_min_sel > 1) 2196d1e7de30SMarek Szyprowski return 1; 2197d1e7de30SMarek Szyprowski 219819280e40SAxel Lin if (rdev->desc->continuous_voltage_range && 219919280e40SAxel Lin rdev->constraints->min_uV && rdev->constraints->max_uV && 220019280e40SAxel Lin rdev->constraints->min_uV != rdev->constraints->max_uV) 220119280e40SAxel Lin return 1; 220219280e40SAxel Lin } 220319280e40SAxel Lin 2204d1e7de30SMarek Szyprowski return 0; 2205d1e7de30SMarek Szyprowski } 2206d1e7de30SMarek Szyprowski EXPORT_SYMBOL_GPL(regulator_can_change_voltage); 2207d1e7de30SMarek Szyprowski 2208d1e7de30SMarek Szyprowski /** 22094367cfdcSDavid Brownell * regulator_count_voltages - count regulator_list_voltage() selectors 22104367cfdcSDavid Brownell * @regulator: regulator source 22114367cfdcSDavid Brownell * 22124367cfdcSDavid Brownell * Returns number of selectors, or negative errno. Selectors are 22134367cfdcSDavid Brownell * numbered starting at zero, and typically correspond to bitfields 22144367cfdcSDavid Brownell * in hardware registers. 22154367cfdcSDavid Brownell */ 22164367cfdcSDavid Brownell int regulator_count_voltages(struct regulator *regulator) 22174367cfdcSDavid Brownell { 22184367cfdcSDavid Brownell struct regulator_dev *rdev = regulator->rdev; 22194367cfdcSDavid Brownell 222026988efeSJavier Martinez Canillas if (rdev->desc->n_voltages) 222126988efeSJavier Martinez Canillas return rdev->desc->n_voltages; 222226988efeSJavier Martinez Canillas 222326988efeSJavier Martinez Canillas if (!rdev->supply) 222426988efeSJavier Martinez Canillas return -EINVAL; 222526988efeSJavier Martinez Canillas 222626988efeSJavier Martinez Canillas return regulator_count_voltages(rdev->supply); 22274367cfdcSDavid Brownell } 22284367cfdcSDavid Brownell EXPORT_SYMBOL_GPL(regulator_count_voltages); 22294367cfdcSDavid Brownell 22304367cfdcSDavid Brownell /** 22314367cfdcSDavid Brownell * regulator_list_voltage - enumerate supported voltages 22324367cfdcSDavid Brownell * @regulator: regulator source 22334367cfdcSDavid Brownell * @selector: identify voltage to list 22344367cfdcSDavid Brownell * Context: can sleep 22354367cfdcSDavid Brownell * 22364367cfdcSDavid Brownell * Returns a voltage that can be passed to @regulator_set_voltage(), 223788393161SThomas Weber * zero if this selector code can't be used on this system, or a 22384367cfdcSDavid Brownell * negative errno. 22394367cfdcSDavid Brownell */ 22404367cfdcSDavid Brownell int regulator_list_voltage(struct regulator *regulator, unsigned selector) 22414367cfdcSDavid Brownell { 22424367cfdcSDavid Brownell struct regulator_dev *rdev = regulator->rdev; 2243272e2315SGuodong Xu const struct regulator_ops *ops = rdev->desc->ops; 22444367cfdcSDavid Brownell int ret; 22454367cfdcSDavid Brownell 2246f446043fSGuennadi Liakhovetski if (rdev->desc->fixed_uV && rdev->desc->n_voltages == 1 && !selector) 2247f446043fSGuennadi Liakhovetski return rdev->desc->fixed_uV; 2248f446043fSGuennadi Liakhovetski 224926988efeSJavier Martinez Canillas if (ops->list_voltage) { 225026988efeSJavier Martinez Canillas if (selector >= rdev->desc->n_voltages) 22514367cfdcSDavid Brownell return -EINVAL; 22524367cfdcSDavid Brownell mutex_lock(&rdev->mutex); 22534367cfdcSDavid Brownell ret = ops->list_voltage(rdev, selector); 22544367cfdcSDavid Brownell mutex_unlock(&rdev->mutex); 225526988efeSJavier Martinez Canillas } else if (rdev->supply) { 225626988efeSJavier Martinez Canillas ret = regulator_list_voltage(rdev->supply, selector); 225726988efeSJavier Martinez Canillas } else { 225826988efeSJavier Martinez Canillas return -EINVAL; 225926988efeSJavier Martinez Canillas } 22604367cfdcSDavid Brownell 22614367cfdcSDavid Brownell if (ret > 0) { 22624367cfdcSDavid Brownell if (ret < rdev->constraints->min_uV) 22634367cfdcSDavid Brownell ret = 0; 22644367cfdcSDavid Brownell else if (ret > rdev->constraints->max_uV) 22654367cfdcSDavid Brownell ret = 0; 22664367cfdcSDavid Brownell } 22674367cfdcSDavid Brownell 22684367cfdcSDavid Brownell return ret; 22694367cfdcSDavid Brownell } 22704367cfdcSDavid Brownell EXPORT_SYMBOL_GPL(regulator_list_voltage); 22714367cfdcSDavid Brownell 22724367cfdcSDavid Brownell /** 227304eca28cSTuomas Tynkkynen * regulator_get_regmap - get the regulator's register map 227404eca28cSTuomas Tynkkynen * @regulator: regulator source 227504eca28cSTuomas Tynkkynen * 227604eca28cSTuomas Tynkkynen * Returns the register map for the given regulator, or an ERR_PTR value 227704eca28cSTuomas Tynkkynen * if the regulator doesn't use regmap. 227804eca28cSTuomas Tynkkynen */ 227904eca28cSTuomas Tynkkynen struct regmap *regulator_get_regmap(struct regulator *regulator) 228004eca28cSTuomas Tynkkynen { 228104eca28cSTuomas Tynkkynen struct regmap *map = regulator->rdev->regmap; 228204eca28cSTuomas Tynkkynen 228304eca28cSTuomas Tynkkynen return map ? map : ERR_PTR(-EOPNOTSUPP); 228404eca28cSTuomas Tynkkynen } 228504eca28cSTuomas Tynkkynen 228604eca28cSTuomas Tynkkynen /** 228704eca28cSTuomas Tynkkynen * regulator_get_hardware_vsel_register - get the HW voltage selector register 228804eca28cSTuomas Tynkkynen * @regulator: regulator source 228904eca28cSTuomas Tynkkynen * @vsel_reg: voltage selector register, output parameter 229004eca28cSTuomas Tynkkynen * @vsel_mask: mask for voltage selector bitfield, output parameter 229104eca28cSTuomas Tynkkynen * 229204eca28cSTuomas Tynkkynen * Returns the hardware register offset and bitmask used for setting the 229304eca28cSTuomas Tynkkynen * regulator voltage. This might be useful when configuring voltage-scaling 229404eca28cSTuomas Tynkkynen * hardware or firmware that can make I2C requests behind the kernel's back, 229504eca28cSTuomas Tynkkynen * for example. 229604eca28cSTuomas Tynkkynen * 229704eca28cSTuomas Tynkkynen * On success, the output parameters @vsel_reg and @vsel_mask are filled in 229804eca28cSTuomas Tynkkynen * and 0 is returned, otherwise a negative errno is returned. 229904eca28cSTuomas Tynkkynen */ 230004eca28cSTuomas Tynkkynen int regulator_get_hardware_vsel_register(struct regulator *regulator, 230104eca28cSTuomas Tynkkynen unsigned *vsel_reg, 230204eca28cSTuomas Tynkkynen unsigned *vsel_mask) 230304eca28cSTuomas Tynkkynen { 230404eca28cSTuomas Tynkkynen struct regulator_dev *rdev = regulator->rdev; 230539f5460dSGuodong Xu const struct regulator_ops *ops = rdev->desc->ops; 230604eca28cSTuomas Tynkkynen 230704eca28cSTuomas Tynkkynen if (ops->set_voltage_sel != regulator_set_voltage_sel_regmap) 230804eca28cSTuomas Tynkkynen return -EOPNOTSUPP; 230904eca28cSTuomas Tynkkynen 231004eca28cSTuomas Tynkkynen *vsel_reg = rdev->desc->vsel_reg; 231104eca28cSTuomas Tynkkynen *vsel_mask = rdev->desc->vsel_mask; 231204eca28cSTuomas Tynkkynen 231304eca28cSTuomas Tynkkynen return 0; 231404eca28cSTuomas Tynkkynen } 231504eca28cSTuomas Tynkkynen EXPORT_SYMBOL_GPL(regulator_get_hardware_vsel_register); 231604eca28cSTuomas Tynkkynen 231704eca28cSTuomas Tynkkynen /** 231804eca28cSTuomas Tynkkynen * regulator_list_hardware_vsel - get the HW-specific register value for a selector 231904eca28cSTuomas Tynkkynen * @regulator: regulator source 232004eca28cSTuomas Tynkkynen * @selector: identify voltage to list 232104eca28cSTuomas Tynkkynen * 232204eca28cSTuomas Tynkkynen * Converts the selector to a hardware-specific voltage selector that can be 232304eca28cSTuomas Tynkkynen * directly written to the regulator registers. The address of the voltage 232404eca28cSTuomas Tynkkynen * register can be determined by calling @regulator_get_hardware_vsel_register. 232504eca28cSTuomas Tynkkynen * 232604eca28cSTuomas Tynkkynen * On error a negative errno is returned. 232704eca28cSTuomas Tynkkynen */ 232804eca28cSTuomas Tynkkynen int regulator_list_hardware_vsel(struct regulator *regulator, 232904eca28cSTuomas Tynkkynen unsigned selector) 233004eca28cSTuomas Tynkkynen { 233104eca28cSTuomas Tynkkynen struct regulator_dev *rdev = regulator->rdev; 233239f5460dSGuodong Xu const struct regulator_ops *ops = rdev->desc->ops; 233304eca28cSTuomas Tynkkynen 233404eca28cSTuomas Tynkkynen if (selector >= rdev->desc->n_voltages) 233504eca28cSTuomas Tynkkynen return -EINVAL; 233604eca28cSTuomas Tynkkynen if (ops->set_voltage_sel != regulator_set_voltage_sel_regmap) 233704eca28cSTuomas Tynkkynen return -EOPNOTSUPP; 233804eca28cSTuomas Tynkkynen 233904eca28cSTuomas Tynkkynen return selector; 234004eca28cSTuomas Tynkkynen } 234104eca28cSTuomas Tynkkynen EXPORT_SYMBOL_GPL(regulator_list_hardware_vsel); 234204eca28cSTuomas Tynkkynen 234304eca28cSTuomas Tynkkynen /** 23442a668a8bSPaul Walmsley * regulator_get_linear_step - return the voltage step size between VSEL values 23452a668a8bSPaul Walmsley * @regulator: regulator source 23462a668a8bSPaul Walmsley * 23472a668a8bSPaul Walmsley * Returns the voltage step size between VSEL values for linear 23482a668a8bSPaul Walmsley * regulators, or return 0 if the regulator isn't a linear regulator. 23492a668a8bSPaul Walmsley */ 23502a668a8bSPaul Walmsley unsigned int regulator_get_linear_step(struct regulator *regulator) 23512a668a8bSPaul Walmsley { 23522a668a8bSPaul Walmsley struct regulator_dev *rdev = regulator->rdev; 23532a668a8bSPaul Walmsley 23542a668a8bSPaul Walmsley return rdev->desc->uV_step; 23552a668a8bSPaul Walmsley } 23562a668a8bSPaul Walmsley EXPORT_SYMBOL_GPL(regulator_get_linear_step); 23572a668a8bSPaul Walmsley 23582a668a8bSPaul Walmsley /** 2359a7a1ad90SMark Brown * regulator_is_supported_voltage - check if a voltage range can be supported 2360a7a1ad90SMark Brown * 2361a7a1ad90SMark Brown * @regulator: Regulator to check. 2362a7a1ad90SMark Brown * @min_uV: Minimum required voltage in uV. 2363a7a1ad90SMark Brown * @max_uV: Maximum required voltage in uV. 2364a7a1ad90SMark Brown * 2365a7a1ad90SMark Brown * Returns a boolean or a negative error code. 2366a7a1ad90SMark Brown */ 2367a7a1ad90SMark Brown int regulator_is_supported_voltage(struct regulator *regulator, 2368a7a1ad90SMark Brown int min_uV, int max_uV) 2369a7a1ad90SMark Brown { 2370c5f3939bSMark Brown struct regulator_dev *rdev = regulator->rdev; 2371a7a1ad90SMark Brown int i, voltages, ret; 2372a7a1ad90SMark Brown 2373c5f3939bSMark Brown /* If we can't change voltage check the current voltage */ 2374c5f3939bSMark Brown if (!(rdev->constraints->valid_ops_mask & REGULATOR_CHANGE_VOLTAGE)) { 2375c5f3939bSMark Brown ret = regulator_get_voltage(regulator); 2376c5f3939bSMark Brown if (ret >= 0) 23770d25d09dSJingoo Han return min_uV <= ret && ret <= max_uV; 2378c5f3939bSMark Brown else 2379c5f3939bSMark Brown return ret; 2380c5f3939bSMark Brown } 2381c5f3939bSMark Brown 2382bd7a2b60SPawel Moll /* Any voltage within constrains range is fine? */ 2383bd7a2b60SPawel Moll if (rdev->desc->continuous_voltage_range) 2384bd7a2b60SPawel Moll return min_uV >= rdev->constraints->min_uV && 2385bd7a2b60SPawel Moll max_uV <= rdev->constraints->max_uV; 2386bd7a2b60SPawel Moll 2387a7a1ad90SMark Brown ret = regulator_count_voltages(regulator); 2388a7a1ad90SMark Brown if (ret < 0) 2389a7a1ad90SMark Brown return ret; 2390a7a1ad90SMark Brown voltages = ret; 2391a7a1ad90SMark Brown 2392a7a1ad90SMark Brown for (i = 0; i < voltages; i++) { 2393a7a1ad90SMark Brown ret = regulator_list_voltage(regulator, i); 2394a7a1ad90SMark Brown 2395a7a1ad90SMark Brown if (ret >= min_uV && ret <= max_uV) 2396a7a1ad90SMark Brown return 1; 2397a7a1ad90SMark Brown } 2398a7a1ad90SMark Brown 2399a7a1ad90SMark Brown return 0; 2400a7a1ad90SMark Brown } 2401a398eaa2SMark Brown EXPORT_SYMBOL_GPL(regulator_is_supported_voltage); 2402a7a1ad90SMark Brown 24037179569aSHeiko Stübner static int _regulator_call_set_voltage(struct regulator_dev *rdev, 24047179569aSHeiko Stübner int min_uV, int max_uV, 24057179569aSHeiko Stübner unsigned *selector) 24067179569aSHeiko Stübner { 24077179569aSHeiko Stübner struct pre_voltage_change_data data; 24087179569aSHeiko Stübner int ret; 24097179569aSHeiko Stübner 24107179569aSHeiko Stübner data.old_uV = _regulator_get_voltage(rdev); 24117179569aSHeiko Stübner data.min_uV = min_uV; 24127179569aSHeiko Stübner data.max_uV = max_uV; 24137179569aSHeiko Stübner ret = _notifier_call_chain(rdev, REGULATOR_EVENT_PRE_VOLTAGE_CHANGE, 24147179569aSHeiko Stübner &data); 24157179569aSHeiko Stübner if (ret & NOTIFY_STOP_MASK) 24167179569aSHeiko Stübner return -EINVAL; 24177179569aSHeiko Stübner 24187179569aSHeiko Stübner ret = rdev->desc->ops->set_voltage(rdev, min_uV, max_uV, selector); 24197179569aSHeiko Stübner if (ret >= 0) 24207179569aSHeiko Stübner return ret; 24217179569aSHeiko Stübner 24227179569aSHeiko Stübner _notifier_call_chain(rdev, REGULATOR_EVENT_ABORT_VOLTAGE_CHANGE, 24237179569aSHeiko Stübner (void *)data.old_uV); 24247179569aSHeiko Stübner 24257179569aSHeiko Stübner return ret; 24267179569aSHeiko Stübner } 24277179569aSHeiko Stübner 24287179569aSHeiko Stübner static int _regulator_call_set_voltage_sel(struct regulator_dev *rdev, 24297179569aSHeiko Stübner int uV, unsigned selector) 24307179569aSHeiko Stübner { 24317179569aSHeiko Stübner struct pre_voltage_change_data data; 24327179569aSHeiko Stübner int ret; 24337179569aSHeiko Stübner 24347179569aSHeiko Stübner data.old_uV = _regulator_get_voltage(rdev); 24357179569aSHeiko Stübner data.min_uV = uV; 24367179569aSHeiko Stübner data.max_uV = uV; 24377179569aSHeiko Stübner ret = _notifier_call_chain(rdev, REGULATOR_EVENT_PRE_VOLTAGE_CHANGE, 24387179569aSHeiko Stübner &data); 24397179569aSHeiko Stübner if (ret & NOTIFY_STOP_MASK) 24407179569aSHeiko Stübner return -EINVAL; 24417179569aSHeiko Stübner 24427179569aSHeiko Stübner ret = rdev->desc->ops->set_voltage_sel(rdev, selector); 24437179569aSHeiko Stübner if (ret >= 0) 24447179569aSHeiko Stübner return ret; 24457179569aSHeiko Stübner 24467179569aSHeiko Stübner _notifier_call_chain(rdev, REGULATOR_EVENT_ABORT_VOLTAGE_CHANGE, 24477179569aSHeiko Stübner (void *)data.old_uV); 24487179569aSHeiko Stübner 24497179569aSHeiko Stübner return ret; 24507179569aSHeiko Stübner } 24517179569aSHeiko Stübner 245275790251SMark Brown static int _regulator_do_set_voltage(struct regulator_dev *rdev, 245375790251SMark Brown int min_uV, int max_uV) 245475790251SMark Brown { 245575790251SMark Brown int ret; 245677af1b26SLinus Walleij int delay = 0; 2457e113d792SMark Brown int best_val = 0; 245875790251SMark Brown unsigned int selector; 2459eba41a5eSAxel Lin int old_selector = -1; 246075790251SMark Brown 246175790251SMark Brown trace_regulator_set_voltage(rdev_get_name(rdev), min_uV, max_uV); 246275790251SMark Brown 2463bf5892a8SMark Brown min_uV += rdev->constraints->uV_offset; 2464bf5892a8SMark Brown max_uV += rdev->constraints->uV_offset; 2465bf5892a8SMark Brown 246677af1b26SLinus Walleij /* 246777af1b26SLinus Walleij * If we can't obtain the old selector there is not enough 246877af1b26SLinus Walleij * info to call set_voltage_time_sel(). 246977af1b26SLinus Walleij */ 24708b7485efSAxel Lin if (_regulator_is_enabled(rdev) && 24718b7485efSAxel Lin rdev->desc->ops->set_voltage_time_sel && 247277af1b26SLinus Walleij rdev->desc->ops->get_voltage_sel) { 2473eba41a5eSAxel Lin old_selector = rdev->desc->ops->get_voltage_sel(rdev); 2474eba41a5eSAxel Lin if (old_selector < 0) 2475eba41a5eSAxel Lin return old_selector; 2476eba41a5eSAxel Lin } 247777af1b26SLinus Walleij 247875790251SMark Brown if (rdev->desc->ops->set_voltage) { 24797179569aSHeiko Stübner ret = _regulator_call_set_voltage(rdev, min_uV, max_uV, 248075790251SMark Brown &selector); 2481e113d792SMark Brown 2482e113d792SMark Brown if (ret >= 0) { 2483e113d792SMark Brown if (rdev->desc->ops->list_voltage) 2484e113d792SMark Brown best_val = rdev->desc->ops->list_voltage(rdev, 2485e113d792SMark Brown selector); 2486e113d792SMark Brown else 2487e113d792SMark Brown best_val = _regulator_get_voltage(rdev); 2488e113d792SMark Brown } 2489e113d792SMark Brown 2490e8eef82bSMark Brown } else if (rdev->desc->ops->set_voltage_sel) { 24919152c36aSAxel Lin if (rdev->desc->ops->map_voltage) { 2492e843fc46SMark Brown ret = rdev->desc->ops->map_voltage(rdev, min_uV, 2493e843fc46SMark Brown max_uV); 24949152c36aSAxel Lin } else { 24959152c36aSAxel Lin if (rdev->desc->ops->list_voltage == 24969152c36aSAxel Lin regulator_list_voltage_linear) 24979152c36aSAxel Lin ret = regulator_map_voltage_linear(rdev, 24989152c36aSAxel Lin min_uV, max_uV); 249936698627SAxel Lin else if (rdev->desc->ops->list_voltage == 250036698627SAxel Lin regulator_list_voltage_linear_range) 250136698627SAxel Lin ret = regulator_map_voltage_linear_range(rdev, 250236698627SAxel Lin min_uV, max_uV); 250307351233SAxel Lin else 25049152c36aSAxel Lin ret = regulator_map_voltage_iterate(rdev, 25059152c36aSAxel Lin min_uV, max_uV); 25069152c36aSAxel Lin } 2507e843fc46SMark Brown 2508e843fc46SMark Brown if (ret >= 0) { 2509e113d792SMark Brown best_val = rdev->desc->ops->list_voltage(rdev, ret); 2510e113d792SMark Brown if (min_uV <= best_val && max_uV >= best_val) { 2511e843fc46SMark Brown selector = ret; 2512c66a566aSAxel Lin if (old_selector == selector) 2513c66a566aSAxel Lin ret = 0; 2514c66a566aSAxel Lin else 25157179569aSHeiko Stübner ret = _regulator_call_set_voltage_sel( 25167179569aSHeiko Stübner rdev, best_val, selector); 2517e113d792SMark Brown } else { 2518e113d792SMark Brown ret = -EINVAL; 2519e113d792SMark Brown } 2520e843fc46SMark Brown } 2521e8eef82bSMark Brown } else { 2522e8eef82bSMark Brown ret = -EINVAL; 2523e8eef82bSMark Brown } 2524e8eef82bSMark Brown 2525eba41a5eSAxel Lin /* Call set_voltage_time_sel if successfully obtained old_selector */ 25265b175952SYadwinder Singh Brar if (ret == 0 && !rdev->constraints->ramp_disable && old_selector >= 0 25275b175952SYadwinder Singh Brar && old_selector != selector) { 2528eba41a5eSAxel Lin 2529eba41a5eSAxel Lin delay = rdev->desc->ops->set_voltage_time_sel(rdev, 2530eba41a5eSAxel Lin old_selector, selector); 2531eba41a5eSAxel Lin if (delay < 0) { 2532eba41a5eSAxel Lin rdev_warn(rdev, "set_voltage_time_sel() failed: %d\n", 2533eba41a5eSAxel Lin delay); 2534eba41a5eSAxel Lin delay = 0; 2535e8eef82bSMark Brown } 253675790251SMark Brown 253777af1b26SLinus Walleij /* Insert any necessary delays */ 253877af1b26SLinus Walleij if (delay >= 1000) { 253977af1b26SLinus Walleij mdelay(delay / 1000); 254077af1b26SLinus Walleij udelay(delay % 1000); 254177af1b26SLinus Walleij } else if (delay) { 254277af1b26SLinus Walleij udelay(delay); 254377af1b26SLinus Walleij } 25448b96de31SPhilip Rakity } 254577af1b26SLinus Walleij 25462f6c797fSAxel Lin if (ret == 0 && best_val >= 0) { 25472f6c797fSAxel Lin unsigned long data = best_val; 25482f6c797fSAxel Lin 2549ded06a52SMark Brown _notifier_call_chain(rdev, REGULATOR_EVENT_VOLTAGE_CHANGE, 25502f6c797fSAxel Lin (void *)data); 25512f6c797fSAxel Lin } 2552ded06a52SMark Brown 2553eba41a5eSAxel Lin trace_regulator_set_voltage_complete(rdev_get_name(rdev), best_val); 255475790251SMark Brown 255575790251SMark Brown return ret; 255675790251SMark Brown } 255775790251SMark Brown 2558a7a1ad90SMark Brown /** 2559414c70cbSLiam Girdwood * regulator_set_voltage - set regulator output voltage 2560414c70cbSLiam Girdwood * @regulator: regulator source 2561414c70cbSLiam Girdwood * @min_uV: Minimum required voltage in uV 2562414c70cbSLiam Girdwood * @max_uV: Maximum acceptable voltage in uV 2563414c70cbSLiam Girdwood * 2564414c70cbSLiam Girdwood * Sets a voltage regulator to the desired output voltage. This can be set 2565414c70cbSLiam Girdwood * during any regulator state. IOW, regulator can be disabled or enabled. 2566414c70cbSLiam Girdwood * 2567414c70cbSLiam Girdwood * If the regulator is enabled then the voltage will change to the new value 2568414c70cbSLiam Girdwood * immediately otherwise if the regulator is disabled the regulator will 2569414c70cbSLiam Girdwood * output at the new voltage when enabled. 2570414c70cbSLiam Girdwood * 2571414c70cbSLiam Girdwood * NOTE: If the regulator is shared between several devices then the lowest 2572414c70cbSLiam Girdwood * request voltage that meets the system constraints will be used. 257369279fb9SMark Brown * Regulator system constraints must be set for this regulator before 2574414c70cbSLiam Girdwood * calling this function otherwise this call will fail. 2575414c70cbSLiam Girdwood */ 2576414c70cbSLiam Girdwood int regulator_set_voltage(struct regulator *regulator, int min_uV, int max_uV) 2577414c70cbSLiam Girdwood { 2578414c70cbSLiam Girdwood struct regulator_dev *rdev = regulator->rdev; 257995a3c23aSMark Brown int ret = 0; 258092d7a558SPaolo Pisati int old_min_uV, old_max_uV; 2581c00dc359SBjorn Andersson int current_uV; 2582414c70cbSLiam Girdwood 2583414c70cbSLiam Girdwood mutex_lock(&rdev->mutex); 2584414c70cbSLiam Girdwood 258595a3c23aSMark Brown /* If we're setting the same range as last time the change 258695a3c23aSMark Brown * should be a noop (some cpufreq implementations use the same 258795a3c23aSMark Brown * voltage for multiple frequencies, for example). 258895a3c23aSMark Brown */ 258995a3c23aSMark Brown if (regulator->min_uV == min_uV && regulator->max_uV == max_uV) 259095a3c23aSMark Brown goto out; 259195a3c23aSMark Brown 2592c00dc359SBjorn Andersson /* If we're trying to set a range that overlaps the current voltage, 2593c00dc359SBjorn Andersson * return succesfully even though the regulator does not support 2594c00dc359SBjorn Andersson * changing the voltage. 2595c00dc359SBjorn Andersson */ 2596c00dc359SBjorn Andersson if (!(rdev->constraints->valid_ops_mask & REGULATOR_CHANGE_VOLTAGE)) { 2597c00dc359SBjorn Andersson current_uV = _regulator_get_voltage(rdev); 2598c00dc359SBjorn Andersson if (min_uV <= current_uV && current_uV <= max_uV) { 2599c00dc359SBjorn Andersson regulator->min_uV = min_uV; 2600c00dc359SBjorn Andersson regulator->max_uV = max_uV; 2601c00dc359SBjorn Andersson goto out; 2602c00dc359SBjorn Andersson } 2603c00dc359SBjorn Andersson } 2604c00dc359SBjorn Andersson 2605414c70cbSLiam Girdwood /* sanity check */ 2606e8eef82bSMark Brown if (!rdev->desc->ops->set_voltage && 2607e8eef82bSMark Brown !rdev->desc->ops->set_voltage_sel) { 2608414c70cbSLiam Girdwood ret = -EINVAL; 2609414c70cbSLiam Girdwood goto out; 2610414c70cbSLiam Girdwood } 2611414c70cbSLiam Girdwood 2612414c70cbSLiam Girdwood /* constraints check */ 2613414c70cbSLiam Girdwood ret = regulator_check_voltage(rdev, &min_uV, &max_uV); 2614414c70cbSLiam Girdwood if (ret < 0) 2615414c70cbSLiam Girdwood goto out; 261692d7a558SPaolo Pisati 261792d7a558SPaolo Pisati /* restore original values in case of error */ 261892d7a558SPaolo Pisati old_min_uV = regulator->min_uV; 261992d7a558SPaolo Pisati old_max_uV = regulator->max_uV; 2620414c70cbSLiam Girdwood regulator->min_uV = min_uV; 2621414c70cbSLiam Girdwood regulator->max_uV = max_uV; 26223a93f2a9SMark Brown 262305fda3b1SThomas Petazzoni ret = regulator_check_consumers(rdev, &min_uV, &max_uV); 262405fda3b1SThomas Petazzoni if (ret < 0) 262592d7a558SPaolo Pisati goto out2; 262605fda3b1SThomas Petazzoni 262775790251SMark Brown ret = _regulator_do_set_voltage(rdev, min_uV, max_uV); 262892d7a558SPaolo Pisati if (ret < 0) 262992d7a558SPaolo Pisati goto out2; 263002fa3ec0SMark Brown 2631414c70cbSLiam Girdwood out: 2632414c70cbSLiam Girdwood mutex_unlock(&rdev->mutex); 2633414c70cbSLiam Girdwood return ret; 263492d7a558SPaolo Pisati out2: 263592d7a558SPaolo Pisati regulator->min_uV = old_min_uV; 263692d7a558SPaolo Pisati regulator->max_uV = old_max_uV; 263792d7a558SPaolo Pisati mutex_unlock(&rdev->mutex); 263892d7a558SPaolo Pisati return ret; 2639414c70cbSLiam Girdwood } 2640414c70cbSLiam Girdwood EXPORT_SYMBOL_GPL(regulator_set_voltage); 2641414c70cbSLiam Girdwood 2642606a2562SMark Brown /** 264388cd222bSLinus Walleij * regulator_set_voltage_time - get raise/fall time 264488cd222bSLinus Walleij * @regulator: regulator source 264588cd222bSLinus Walleij * @old_uV: starting voltage in microvolts 264688cd222bSLinus Walleij * @new_uV: target voltage in microvolts 264788cd222bSLinus Walleij * 264888cd222bSLinus Walleij * Provided with the starting and ending voltage, this function attempts to 264988cd222bSLinus Walleij * calculate the time in microseconds required to rise or fall to this new 265088cd222bSLinus Walleij * voltage. 265188cd222bSLinus Walleij */ 265288cd222bSLinus Walleij int regulator_set_voltage_time(struct regulator *regulator, 265388cd222bSLinus Walleij int old_uV, int new_uV) 265488cd222bSLinus Walleij { 265588cd222bSLinus Walleij struct regulator_dev *rdev = regulator->rdev; 2656272e2315SGuodong Xu const struct regulator_ops *ops = rdev->desc->ops; 265788cd222bSLinus Walleij int old_sel = -1; 265888cd222bSLinus Walleij int new_sel = -1; 265988cd222bSLinus Walleij int voltage; 266088cd222bSLinus Walleij int i; 266188cd222bSLinus Walleij 266288cd222bSLinus Walleij /* Currently requires operations to do this */ 266388cd222bSLinus Walleij if (!ops->list_voltage || !ops->set_voltage_time_sel 266488cd222bSLinus Walleij || !rdev->desc->n_voltages) 266588cd222bSLinus Walleij return -EINVAL; 266688cd222bSLinus Walleij 266788cd222bSLinus Walleij for (i = 0; i < rdev->desc->n_voltages; i++) { 266888cd222bSLinus Walleij /* We only look for exact voltage matches here */ 266988cd222bSLinus Walleij voltage = regulator_list_voltage(regulator, i); 267088cd222bSLinus Walleij if (voltage < 0) 267188cd222bSLinus Walleij return -EINVAL; 267288cd222bSLinus Walleij if (voltage == 0) 267388cd222bSLinus Walleij continue; 267488cd222bSLinus Walleij if (voltage == old_uV) 267588cd222bSLinus Walleij old_sel = i; 267688cd222bSLinus Walleij if (voltage == new_uV) 267788cd222bSLinus Walleij new_sel = i; 267888cd222bSLinus Walleij } 267988cd222bSLinus Walleij 268088cd222bSLinus Walleij if (old_sel < 0 || new_sel < 0) 268188cd222bSLinus Walleij return -EINVAL; 268288cd222bSLinus Walleij 268388cd222bSLinus Walleij return ops->set_voltage_time_sel(rdev, old_sel, new_sel); 268488cd222bSLinus Walleij } 268588cd222bSLinus Walleij EXPORT_SYMBOL_GPL(regulator_set_voltage_time); 268688cd222bSLinus Walleij 268788cd222bSLinus Walleij /** 268898a175b6SYadwinder Singh Brar * regulator_set_voltage_time_sel - get raise/fall time 2689296c6566SRandy Dunlap * @rdev: regulator source device 269098a175b6SYadwinder Singh Brar * @old_selector: selector for starting voltage 269198a175b6SYadwinder Singh Brar * @new_selector: selector for target voltage 269298a175b6SYadwinder Singh Brar * 269398a175b6SYadwinder Singh Brar * Provided with the starting and target voltage selectors, this function 269498a175b6SYadwinder Singh Brar * returns time in microseconds required to rise or fall to this new voltage 269598a175b6SYadwinder Singh Brar * 2696f11d08c3SAxel Lin * Drivers providing ramp_delay in regulation_constraints can use this as their 2697398715abSAxel Lin * set_voltage_time_sel() operation. 269898a175b6SYadwinder Singh Brar */ 269998a175b6SYadwinder Singh Brar int regulator_set_voltage_time_sel(struct regulator_dev *rdev, 270098a175b6SYadwinder Singh Brar unsigned int old_selector, 270198a175b6SYadwinder Singh Brar unsigned int new_selector) 270298a175b6SYadwinder Singh Brar { 2703398715abSAxel Lin unsigned int ramp_delay = 0; 2704f11d08c3SAxel Lin int old_volt, new_volt; 2705398715abSAxel Lin 27066f0b2c69SYadwinder Singh Brar if (rdev->constraints->ramp_delay) 2707398715abSAxel Lin ramp_delay = rdev->constraints->ramp_delay; 2708398715abSAxel Lin else if (rdev->desc->ramp_delay) 2709398715abSAxel Lin ramp_delay = rdev->desc->ramp_delay; 2710398715abSAxel Lin 2711398715abSAxel Lin if (ramp_delay == 0) { 27126f0b2c69SYadwinder Singh Brar rdev_warn(rdev, "ramp_delay not set\n"); 2713398715abSAxel Lin return 0; 27146f0b2c69SYadwinder Singh Brar } 2715398715abSAxel Lin 2716f11d08c3SAxel Lin /* sanity check */ 2717f11d08c3SAxel Lin if (!rdev->desc->ops->list_voltage) 2718f11d08c3SAxel Lin return -EINVAL; 2719398715abSAxel Lin 2720f11d08c3SAxel Lin old_volt = rdev->desc->ops->list_voltage(rdev, old_selector); 2721f11d08c3SAxel Lin new_volt = rdev->desc->ops->list_voltage(rdev, new_selector); 2722f11d08c3SAxel Lin 2723f11d08c3SAxel Lin return DIV_ROUND_UP(abs(new_volt - old_volt), ramp_delay); 272498a175b6SYadwinder Singh Brar } 2725b19dbf71SMark Brown EXPORT_SYMBOL_GPL(regulator_set_voltage_time_sel); 272698a175b6SYadwinder Singh Brar 272798a175b6SYadwinder Singh Brar /** 2728606a2562SMark Brown * regulator_sync_voltage - re-apply last regulator output voltage 2729606a2562SMark Brown * @regulator: regulator source 2730606a2562SMark Brown * 2731606a2562SMark Brown * Re-apply the last configured voltage. This is intended to be used 2732606a2562SMark Brown * where some external control source the consumer is cooperating with 2733606a2562SMark Brown * has caused the configured voltage to change. 2734606a2562SMark Brown */ 2735606a2562SMark Brown int regulator_sync_voltage(struct regulator *regulator) 2736606a2562SMark Brown { 2737606a2562SMark Brown struct regulator_dev *rdev = regulator->rdev; 2738606a2562SMark Brown int ret, min_uV, max_uV; 2739606a2562SMark Brown 2740606a2562SMark Brown mutex_lock(&rdev->mutex); 2741606a2562SMark Brown 2742606a2562SMark Brown if (!rdev->desc->ops->set_voltage && 2743606a2562SMark Brown !rdev->desc->ops->set_voltage_sel) { 2744606a2562SMark Brown ret = -EINVAL; 2745606a2562SMark Brown goto out; 2746606a2562SMark Brown } 2747606a2562SMark Brown 2748606a2562SMark Brown /* This is only going to work if we've had a voltage configured. */ 2749606a2562SMark Brown if (!regulator->min_uV && !regulator->max_uV) { 2750606a2562SMark Brown ret = -EINVAL; 2751606a2562SMark Brown goto out; 2752606a2562SMark Brown } 2753606a2562SMark Brown 2754606a2562SMark Brown min_uV = regulator->min_uV; 2755606a2562SMark Brown max_uV = regulator->max_uV; 2756606a2562SMark Brown 2757606a2562SMark Brown /* This should be a paranoia check... */ 2758606a2562SMark Brown ret = regulator_check_voltage(rdev, &min_uV, &max_uV); 2759606a2562SMark Brown if (ret < 0) 2760606a2562SMark Brown goto out; 2761606a2562SMark Brown 2762606a2562SMark Brown ret = regulator_check_consumers(rdev, &min_uV, &max_uV); 2763606a2562SMark Brown if (ret < 0) 2764606a2562SMark Brown goto out; 2765606a2562SMark Brown 2766606a2562SMark Brown ret = _regulator_do_set_voltage(rdev, min_uV, max_uV); 2767606a2562SMark Brown 2768606a2562SMark Brown out: 2769606a2562SMark Brown mutex_unlock(&rdev->mutex); 2770606a2562SMark Brown return ret; 2771606a2562SMark Brown } 2772606a2562SMark Brown EXPORT_SYMBOL_GPL(regulator_sync_voltage); 2773606a2562SMark Brown 2774414c70cbSLiam Girdwood static int _regulator_get_voltage(struct regulator_dev *rdev) 2775414c70cbSLiam Girdwood { 2776bf5892a8SMark Brown int sel, ret; 2777476c2d83SMark Brown 2778476c2d83SMark Brown if (rdev->desc->ops->get_voltage_sel) { 2779476c2d83SMark Brown sel = rdev->desc->ops->get_voltage_sel(rdev); 2780476c2d83SMark Brown if (sel < 0) 2781476c2d83SMark Brown return sel; 2782bf5892a8SMark Brown ret = rdev->desc->ops->list_voltage(rdev, sel); 2783cb220d16SAxel Lin } else if (rdev->desc->ops->get_voltage) { 2784bf5892a8SMark Brown ret = rdev->desc->ops->get_voltage(rdev); 2785f7df20ecSMark Brown } else if (rdev->desc->ops->list_voltage) { 2786f7df20ecSMark Brown ret = rdev->desc->ops->list_voltage(rdev, 0); 27875a523605SLaxman Dewangan } else if (rdev->desc->fixed_uV && (rdev->desc->n_voltages == 1)) { 27885a523605SLaxman Dewangan ret = rdev->desc->fixed_uV; 2789e303996eSJavier Martinez Canillas } else if (rdev->supply) { 2790e303996eSJavier Martinez Canillas ret = regulator_get_voltage(rdev->supply); 2791cb220d16SAxel Lin } else { 2792414c70cbSLiam Girdwood return -EINVAL; 2793cb220d16SAxel Lin } 2794bf5892a8SMark Brown 2795cb220d16SAxel Lin if (ret < 0) 2796cb220d16SAxel Lin return ret; 2797bf5892a8SMark Brown return ret - rdev->constraints->uV_offset; 2798414c70cbSLiam Girdwood } 2799414c70cbSLiam Girdwood 2800414c70cbSLiam Girdwood /** 2801414c70cbSLiam Girdwood * regulator_get_voltage - get regulator output voltage 2802414c70cbSLiam Girdwood * @regulator: regulator source 2803414c70cbSLiam Girdwood * 2804414c70cbSLiam Girdwood * This returns the current regulator voltage in uV. 2805414c70cbSLiam Girdwood * 2806414c70cbSLiam Girdwood * NOTE: If the regulator is disabled it will return the voltage value. This 2807414c70cbSLiam Girdwood * function should not be used to determine regulator state. 2808414c70cbSLiam Girdwood */ 2809414c70cbSLiam Girdwood int regulator_get_voltage(struct regulator *regulator) 2810414c70cbSLiam Girdwood { 2811414c70cbSLiam Girdwood int ret; 2812414c70cbSLiam Girdwood 2813414c70cbSLiam Girdwood mutex_lock(®ulator->rdev->mutex); 2814414c70cbSLiam Girdwood 2815414c70cbSLiam Girdwood ret = _regulator_get_voltage(regulator->rdev); 2816414c70cbSLiam Girdwood 2817414c70cbSLiam Girdwood mutex_unlock(®ulator->rdev->mutex); 2818414c70cbSLiam Girdwood 2819414c70cbSLiam Girdwood return ret; 2820414c70cbSLiam Girdwood } 2821414c70cbSLiam Girdwood EXPORT_SYMBOL_GPL(regulator_get_voltage); 2822414c70cbSLiam Girdwood 2823414c70cbSLiam Girdwood /** 2824414c70cbSLiam Girdwood * regulator_set_current_limit - set regulator output current limit 2825414c70cbSLiam Girdwood * @regulator: regulator source 2826ce0d10f8SCharles Keepax * @min_uA: Minimum supported current in uA 2827414c70cbSLiam Girdwood * @max_uA: Maximum supported current in uA 2828414c70cbSLiam Girdwood * 2829414c70cbSLiam Girdwood * Sets current sink to the desired output current. This can be set during 2830414c70cbSLiam Girdwood * any regulator state. IOW, regulator can be disabled or enabled. 2831414c70cbSLiam Girdwood * 2832414c70cbSLiam Girdwood * If the regulator is enabled then the current will change to the new value 2833414c70cbSLiam Girdwood * immediately otherwise if the regulator is disabled the regulator will 2834414c70cbSLiam Girdwood * output at the new current when enabled. 2835414c70cbSLiam Girdwood * 2836414c70cbSLiam Girdwood * NOTE: Regulator system constraints must be set for this regulator before 2837414c70cbSLiam Girdwood * calling this function otherwise this call will fail. 2838414c70cbSLiam Girdwood */ 2839414c70cbSLiam Girdwood int regulator_set_current_limit(struct regulator *regulator, 2840414c70cbSLiam Girdwood int min_uA, int max_uA) 2841414c70cbSLiam Girdwood { 2842414c70cbSLiam Girdwood struct regulator_dev *rdev = regulator->rdev; 2843414c70cbSLiam Girdwood int ret; 2844414c70cbSLiam Girdwood 2845414c70cbSLiam Girdwood mutex_lock(&rdev->mutex); 2846414c70cbSLiam Girdwood 2847414c70cbSLiam Girdwood /* sanity check */ 2848414c70cbSLiam Girdwood if (!rdev->desc->ops->set_current_limit) { 2849414c70cbSLiam Girdwood ret = -EINVAL; 2850414c70cbSLiam Girdwood goto out; 2851414c70cbSLiam Girdwood } 2852414c70cbSLiam Girdwood 2853414c70cbSLiam Girdwood /* constraints check */ 2854414c70cbSLiam Girdwood ret = regulator_check_current_limit(rdev, &min_uA, &max_uA); 2855414c70cbSLiam Girdwood if (ret < 0) 2856414c70cbSLiam Girdwood goto out; 2857414c70cbSLiam Girdwood 2858414c70cbSLiam Girdwood ret = rdev->desc->ops->set_current_limit(rdev, min_uA, max_uA); 2859414c70cbSLiam Girdwood out: 2860414c70cbSLiam Girdwood mutex_unlock(&rdev->mutex); 2861414c70cbSLiam Girdwood return ret; 2862414c70cbSLiam Girdwood } 2863414c70cbSLiam Girdwood EXPORT_SYMBOL_GPL(regulator_set_current_limit); 2864414c70cbSLiam Girdwood 2865414c70cbSLiam Girdwood static int _regulator_get_current_limit(struct regulator_dev *rdev) 2866414c70cbSLiam Girdwood { 2867414c70cbSLiam Girdwood int ret; 2868414c70cbSLiam Girdwood 2869414c70cbSLiam Girdwood mutex_lock(&rdev->mutex); 2870414c70cbSLiam Girdwood 2871414c70cbSLiam Girdwood /* sanity check */ 2872414c70cbSLiam Girdwood if (!rdev->desc->ops->get_current_limit) { 2873414c70cbSLiam Girdwood ret = -EINVAL; 2874414c70cbSLiam Girdwood goto out; 2875414c70cbSLiam Girdwood } 2876414c70cbSLiam Girdwood 2877414c70cbSLiam Girdwood ret = rdev->desc->ops->get_current_limit(rdev); 2878414c70cbSLiam Girdwood out: 2879414c70cbSLiam Girdwood mutex_unlock(&rdev->mutex); 2880414c70cbSLiam Girdwood return ret; 2881414c70cbSLiam Girdwood } 2882414c70cbSLiam Girdwood 2883414c70cbSLiam Girdwood /** 2884414c70cbSLiam Girdwood * regulator_get_current_limit - get regulator output current 2885414c70cbSLiam Girdwood * @regulator: regulator source 2886414c70cbSLiam Girdwood * 2887414c70cbSLiam Girdwood * This returns the current supplied by the specified current sink in uA. 2888414c70cbSLiam Girdwood * 2889414c70cbSLiam Girdwood * NOTE: If the regulator is disabled it will return the current value. This 2890414c70cbSLiam Girdwood * function should not be used to determine regulator state. 2891414c70cbSLiam Girdwood */ 2892414c70cbSLiam Girdwood int regulator_get_current_limit(struct regulator *regulator) 2893414c70cbSLiam Girdwood { 2894414c70cbSLiam Girdwood return _regulator_get_current_limit(regulator->rdev); 2895414c70cbSLiam Girdwood } 2896414c70cbSLiam Girdwood EXPORT_SYMBOL_GPL(regulator_get_current_limit); 2897414c70cbSLiam Girdwood 2898414c70cbSLiam Girdwood /** 2899414c70cbSLiam Girdwood * regulator_set_mode - set regulator operating mode 2900414c70cbSLiam Girdwood * @regulator: regulator source 2901414c70cbSLiam Girdwood * @mode: operating mode - one of the REGULATOR_MODE constants 2902414c70cbSLiam Girdwood * 2903414c70cbSLiam Girdwood * Set regulator operating mode to increase regulator efficiency or improve 2904414c70cbSLiam Girdwood * regulation performance. 2905414c70cbSLiam Girdwood * 2906414c70cbSLiam Girdwood * NOTE: Regulator system constraints must be set for this regulator before 2907414c70cbSLiam Girdwood * calling this function otherwise this call will fail. 2908414c70cbSLiam Girdwood */ 2909414c70cbSLiam Girdwood int regulator_set_mode(struct regulator *regulator, unsigned int mode) 2910414c70cbSLiam Girdwood { 2911414c70cbSLiam Girdwood struct regulator_dev *rdev = regulator->rdev; 2912414c70cbSLiam Girdwood int ret; 2913500b4ac9SSundar R Iyer int regulator_curr_mode; 2914414c70cbSLiam Girdwood 2915414c70cbSLiam Girdwood mutex_lock(&rdev->mutex); 2916414c70cbSLiam Girdwood 2917414c70cbSLiam Girdwood /* sanity check */ 2918414c70cbSLiam Girdwood if (!rdev->desc->ops->set_mode) { 2919414c70cbSLiam Girdwood ret = -EINVAL; 2920414c70cbSLiam Girdwood goto out; 2921414c70cbSLiam Girdwood } 2922414c70cbSLiam Girdwood 2923500b4ac9SSundar R Iyer /* return if the same mode is requested */ 2924500b4ac9SSundar R Iyer if (rdev->desc->ops->get_mode) { 2925500b4ac9SSundar R Iyer regulator_curr_mode = rdev->desc->ops->get_mode(rdev); 2926500b4ac9SSundar R Iyer if (regulator_curr_mode == mode) { 2927500b4ac9SSundar R Iyer ret = 0; 2928500b4ac9SSundar R Iyer goto out; 2929500b4ac9SSundar R Iyer } 2930500b4ac9SSundar R Iyer } 2931500b4ac9SSundar R Iyer 2932414c70cbSLiam Girdwood /* constraints check */ 293322c51b47SAxel Lin ret = regulator_mode_constrain(rdev, &mode); 2934414c70cbSLiam Girdwood if (ret < 0) 2935414c70cbSLiam Girdwood goto out; 2936414c70cbSLiam Girdwood 2937414c70cbSLiam Girdwood ret = rdev->desc->ops->set_mode(rdev, mode); 2938414c70cbSLiam Girdwood out: 2939414c70cbSLiam Girdwood mutex_unlock(&rdev->mutex); 2940414c70cbSLiam Girdwood return ret; 2941414c70cbSLiam Girdwood } 2942414c70cbSLiam Girdwood EXPORT_SYMBOL_GPL(regulator_set_mode); 2943414c70cbSLiam Girdwood 2944414c70cbSLiam Girdwood static unsigned int _regulator_get_mode(struct regulator_dev *rdev) 2945414c70cbSLiam Girdwood { 2946414c70cbSLiam Girdwood int ret; 2947414c70cbSLiam Girdwood 2948414c70cbSLiam Girdwood mutex_lock(&rdev->mutex); 2949414c70cbSLiam Girdwood 2950414c70cbSLiam Girdwood /* sanity check */ 2951414c70cbSLiam Girdwood if (!rdev->desc->ops->get_mode) { 2952414c70cbSLiam Girdwood ret = -EINVAL; 2953414c70cbSLiam Girdwood goto out; 2954414c70cbSLiam Girdwood } 2955414c70cbSLiam Girdwood 2956414c70cbSLiam Girdwood ret = rdev->desc->ops->get_mode(rdev); 2957414c70cbSLiam Girdwood out: 2958414c70cbSLiam Girdwood mutex_unlock(&rdev->mutex); 2959414c70cbSLiam Girdwood return ret; 2960414c70cbSLiam Girdwood } 2961414c70cbSLiam Girdwood 2962414c70cbSLiam Girdwood /** 2963414c70cbSLiam Girdwood * regulator_get_mode - get regulator operating mode 2964414c70cbSLiam Girdwood * @regulator: regulator source 2965414c70cbSLiam Girdwood * 2966414c70cbSLiam Girdwood * Get the current regulator operating mode. 2967414c70cbSLiam Girdwood */ 2968414c70cbSLiam Girdwood unsigned int regulator_get_mode(struct regulator *regulator) 2969414c70cbSLiam Girdwood { 2970414c70cbSLiam Girdwood return _regulator_get_mode(regulator->rdev); 2971414c70cbSLiam Girdwood } 2972414c70cbSLiam Girdwood EXPORT_SYMBOL_GPL(regulator_get_mode); 2973414c70cbSLiam Girdwood 2974414c70cbSLiam Girdwood /** 2975414c70cbSLiam Girdwood * regulator_set_optimum_mode - set regulator optimum operating mode 2976414c70cbSLiam Girdwood * @regulator: regulator source 2977414c70cbSLiam Girdwood * @uA_load: load current 2978414c70cbSLiam Girdwood * 2979414c70cbSLiam Girdwood * Notifies the regulator core of a new device load. This is then used by 2980414c70cbSLiam Girdwood * DRMS (if enabled by constraints) to set the most efficient regulator 2981414c70cbSLiam Girdwood * operating mode for the new regulator loading. 2982414c70cbSLiam Girdwood * 2983414c70cbSLiam Girdwood * Consumer devices notify their supply regulator of the maximum power 2984414c70cbSLiam Girdwood * they will require (can be taken from device datasheet in the power 2985414c70cbSLiam Girdwood * consumption tables) when they change operational status and hence power 2986414c70cbSLiam Girdwood * state. Examples of operational state changes that can affect power 2987414c70cbSLiam Girdwood * consumption are :- 2988414c70cbSLiam Girdwood * 2989414c70cbSLiam Girdwood * o Device is opened / closed. 2990414c70cbSLiam Girdwood * o Device I/O is about to begin or has just finished. 2991414c70cbSLiam Girdwood * o Device is idling in between work. 2992414c70cbSLiam Girdwood * 2993414c70cbSLiam Girdwood * This information is also exported via sysfs to userspace. 2994414c70cbSLiam Girdwood * 2995414c70cbSLiam Girdwood * DRMS will sum the total requested load on the regulator and change 2996414c70cbSLiam Girdwood * to the most efficient operating mode if platform constraints allow. 2997414c70cbSLiam Girdwood * 2998414c70cbSLiam Girdwood * Returns the new regulator mode or error. 2999414c70cbSLiam Girdwood */ 3000414c70cbSLiam Girdwood int regulator_set_optimum_mode(struct regulator *regulator, int uA_load) 3001414c70cbSLiam Girdwood { 3002414c70cbSLiam Girdwood struct regulator_dev *rdev = regulator->rdev; 3003414c70cbSLiam Girdwood struct regulator *consumer; 3004d92d95b6SStephen Boyd int ret, output_uV, input_uV = 0, total_uA_load = 0; 3005414c70cbSLiam Girdwood unsigned int mode; 3006414c70cbSLiam Girdwood 3007d92d95b6SStephen Boyd if (rdev->supply) 3008d92d95b6SStephen Boyd input_uV = regulator_get_voltage(rdev->supply); 3009d92d95b6SStephen Boyd 3010414c70cbSLiam Girdwood mutex_lock(&rdev->mutex); 3011414c70cbSLiam Girdwood 3012a4b41483SMark Brown /* 3013a4b41483SMark Brown * first check to see if we can set modes at all, otherwise just 3014a4b41483SMark Brown * tell the consumer everything is OK. 3015a4b41483SMark Brown */ 3016414c70cbSLiam Girdwood regulator->uA_load = uA_load; 3017414c70cbSLiam Girdwood ret = regulator_check_drms(rdev); 3018a4b41483SMark Brown if (ret < 0) { 3019a4b41483SMark Brown ret = 0; 3020414c70cbSLiam Girdwood goto out; 3021a4b41483SMark Brown } 3022414c70cbSLiam Girdwood 3023414c70cbSLiam Girdwood if (!rdev->desc->ops->get_optimum_mode) 3024414c70cbSLiam Girdwood goto out; 3025414c70cbSLiam Girdwood 3026a4b41483SMark Brown /* 3027a4b41483SMark Brown * we can actually do this so any errors are indicators of 3028a4b41483SMark Brown * potential real failure. 3029a4b41483SMark Brown */ 3030a4b41483SMark Brown ret = -EINVAL; 3031a4b41483SMark Brown 3032854ccbaeSAxel Lin if (!rdev->desc->ops->set_mode) 3033854ccbaeSAxel Lin goto out; 3034854ccbaeSAxel Lin 3035414c70cbSLiam Girdwood /* get output voltage */ 30361bf5a1f8SMark Brown output_uV = _regulator_get_voltage(rdev); 3037414c70cbSLiam Girdwood if (output_uV <= 0) { 30385da84fd9SJoe Perches rdev_err(rdev, "invalid output voltage found\n"); 3039414c70cbSLiam Girdwood goto out; 3040414c70cbSLiam Girdwood } 3041414c70cbSLiam Girdwood 3042d92d95b6SStephen Boyd /* No supply? Use constraint voltage */ 30431bf5a1f8SMark Brown if (input_uV <= 0) 3044414c70cbSLiam Girdwood input_uV = rdev->constraints->input_uV; 3045414c70cbSLiam Girdwood if (input_uV <= 0) { 30465da84fd9SJoe Perches rdev_err(rdev, "invalid input voltage found\n"); 3047414c70cbSLiam Girdwood goto out; 3048414c70cbSLiam Girdwood } 3049414c70cbSLiam Girdwood 3050414c70cbSLiam Girdwood /* calc total requested load for this regulator */ 3051414c70cbSLiam Girdwood list_for_each_entry(consumer, &rdev->consumer_list, list) 3052414c70cbSLiam Girdwood total_uA_load += consumer->uA_load; 3053414c70cbSLiam Girdwood 3054414c70cbSLiam Girdwood mode = rdev->desc->ops->get_optimum_mode(rdev, 3055414c70cbSLiam Girdwood input_uV, output_uV, 3056414c70cbSLiam Girdwood total_uA_load); 30572c608234SMark Brown ret = regulator_mode_constrain(rdev, &mode); 3058e573520bSDavid Brownell if (ret < 0) { 30595da84fd9SJoe Perches rdev_err(rdev, "failed to get optimum mode @ %d uA %d -> %d uV\n", 3060414c70cbSLiam Girdwood total_uA_load, input_uV, output_uV); 3061414c70cbSLiam Girdwood goto out; 3062414c70cbSLiam Girdwood } 3063414c70cbSLiam Girdwood 3064414c70cbSLiam Girdwood ret = rdev->desc->ops->set_mode(rdev, mode); 3065e573520bSDavid Brownell if (ret < 0) { 30665da84fd9SJoe Perches rdev_err(rdev, "failed to set optimum mode %x\n", mode); 3067414c70cbSLiam Girdwood goto out; 3068414c70cbSLiam Girdwood } 3069414c70cbSLiam Girdwood ret = mode; 3070414c70cbSLiam Girdwood out: 3071414c70cbSLiam Girdwood mutex_unlock(&rdev->mutex); 3072414c70cbSLiam Girdwood return ret; 3073414c70cbSLiam Girdwood } 3074414c70cbSLiam Girdwood EXPORT_SYMBOL_GPL(regulator_set_optimum_mode); 3075414c70cbSLiam Girdwood 3076414c70cbSLiam Girdwood /** 3077f59c8f9fSMark Brown * regulator_allow_bypass - allow the regulator to go into bypass mode 3078f59c8f9fSMark Brown * 3079f59c8f9fSMark Brown * @regulator: Regulator to configure 30809345dfb8SNishanth Menon * @enable: enable or disable bypass mode 3081f59c8f9fSMark Brown * 3082f59c8f9fSMark Brown * Allow the regulator to go into bypass mode if all other consumers 3083f59c8f9fSMark Brown * for the regulator also enable bypass mode and the machine 3084f59c8f9fSMark Brown * constraints allow this. Bypass mode means that the regulator is 3085f59c8f9fSMark Brown * simply passing the input directly to the output with no regulation. 3086f59c8f9fSMark Brown */ 3087f59c8f9fSMark Brown int regulator_allow_bypass(struct regulator *regulator, bool enable) 3088f59c8f9fSMark Brown { 3089f59c8f9fSMark Brown struct regulator_dev *rdev = regulator->rdev; 3090f59c8f9fSMark Brown int ret = 0; 3091f59c8f9fSMark Brown 3092f59c8f9fSMark Brown if (!rdev->desc->ops->set_bypass) 3093f59c8f9fSMark Brown return 0; 3094f59c8f9fSMark Brown 3095f59c8f9fSMark Brown if (rdev->constraints && 3096f59c8f9fSMark Brown !(rdev->constraints->valid_ops_mask & REGULATOR_CHANGE_BYPASS)) 3097f59c8f9fSMark Brown return 0; 3098f59c8f9fSMark Brown 3099f59c8f9fSMark Brown mutex_lock(&rdev->mutex); 3100f59c8f9fSMark Brown 3101f59c8f9fSMark Brown if (enable && !regulator->bypass) { 3102f59c8f9fSMark Brown rdev->bypass_count++; 3103f59c8f9fSMark Brown 3104f59c8f9fSMark Brown if (rdev->bypass_count == rdev->open_count) { 3105f59c8f9fSMark Brown ret = rdev->desc->ops->set_bypass(rdev, enable); 3106f59c8f9fSMark Brown if (ret != 0) 3107f59c8f9fSMark Brown rdev->bypass_count--; 3108f59c8f9fSMark Brown } 3109f59c8f9fSMark Brown 3110f59c8f9fSMark Brown } else if (!enable && regulator->bypass) { 3111f59c8f9fSMark Brown rdev->bypass_count--; 3112f59c8f9fSMark Brown 3113f59c8f9fSMark Brown if (rdev->bypass_count != rdev->open_count) { 3114f59c8f9fSMark Brown ret = rdev->desc->ops->set_bypass(rdev, enable); 3115f59c8f9fSMark Brown if (ret != 0) 3116f59c8f9fSMark Brown rdev->bypass_count++; 3117f59c8f9fSMark Brown } 3118f59c8f9fSMark Brown } 3119f59c8f9fSMark Brown 3120f59c8f9fSMark Brown if (ret == 0) 3121f59c8f9fSMark Brown regulator->bypass = enable; 3122f59c8f9fSMark Brown 3123f59c8f9fSMark Brown mutex_unlock(&rdev->mutex); 3124f59c8f9fSMark Brown 3125f59c8f9fSMark Brown return ret; 3126f59c8f9fSMark Brown } 3127f59c8f9fSMark Brown EXPORT_SYMBOL_GPL(regulator_allow_bypass); 3128f59c8f9fSMark Brown 3129f59c8f9fSMark Brown /** 3130414c70cbSLiam Girdwood * regulator_register_notifier - register regulator event notifier 3131414c70cbSLiam Girdwood * @regulator: regulator source 313269279fb9SMark Brown * @nb: notifier block 3133414c70cbSLiam Girdwood * 3134414c70cbSLiam Girdwood * Register notifier block to receive regulator events. 3135414c70cbSLiam Girdwood */ 3136414c70cbSLiam Girdwood int regulator_register_notifier(struct regulator *regulator, 3137414c70cbSLiam Girdwood struct notifier_block *nb) 3138414c70cbSLiam Girdwood { 3139414c70cbSLiam Girdwood return blocking_notifier_chain_register(®ulator->rdev->notifier, 3140414c70cbSLiam Girdwood nb); 3141414c70cbSLiam Girdwood } 3142414c70cbSLiam Girdwood EXPORT_SYMBOL_GPL(regulator_register_notifier); 3143414c70cbSLiam Girdwood 3144414c70cbSLiam Girdwood /** 3145414c70cbSLiam Girdwood * regulator_unregister_notifier - unregister regulator event notifier 3146414c70cbSLiam Girdwood * @regulator: regulator source 314769279fb9SMark Brown * @nb: notifier block 3148414c70cbSLiam Girdwood * 3149414c70cbSLiam Girdwood * Unregister regulator event notifier block. 3150414c70cbSLiam Girdwood */ 3151414c70cbSLiam Girdwood int regulator_unregister_notifier(struct regulator *regulator, 3152414c70cbSLiam Girdwood struct notifier_block *nb) 3153414c70cbSLiam Girdwood { 3154414c70cbSLiam Girdwood return blocking_notifier_chain_unregister(®ulator->rdev->notifier, 3155414c70cbSLiam Girdwood nb); 3156414c70cbSLiam Girdwood } 3157414c70cbSLiam Girdwood EXPORT_SYMBOL_GPL(regulator_unregister_notifier); 3158414c70cbSLiam Girdwood 3159b136fb44SJonathan Cameron /* notify regulator consumers and downstream regulator consumers. 3160b136fb44SJonathan Cameron * Note mutex must be held by caller. 3161b136fb44SJonathan Cameron */ 31627179569aSHeiko Stübner static int _notifier_call_chain(struct regulator_dev *rdev, 3163414c70cbSLiam Girdwood unsigned long event, void *data) 3164414c70cbSLiam Girdwood { 3165414c70cbSLiam Girdwood /* call rdev chain first */ 31667179569aSHeiko Stübner return blocking_notifier_call_chain(&rdev->notifier, event, data); 3167414c70cbSLiam Girdwood } 3168414c70cbSLiam Girdwood 3169414c70cbSLiam Girdwood /** 3170414c70cbSLiam Girdwood * regulator_bulk_get - get multiple regulator consumers 3171414c70cbSLiam Girdwood * 3172414c70cbSLiam Girdwood * @dev: Device to supply 3173414c70cbSLiam Girdwood * @num_consumers: Number of consumers to register 3174414c70cbSLiam Girdwood * @consumers: Configuration of consumers; clients are stored here. 3175414c70cbSLiam Girdwood * 3176414c70cbSLiam Girdwood * @return 0 on success, an errno on failure. 3177414c70cbSLiam Girdwood * 3178414c70cbSLiam Girdwood * This helper function allows drivers to get several regulator 3179414c70cbSLiam Girdwood * consumers in one operation. If any of the regulators cannot be 3180414c70cbSLiam Girdwood * acquired then any regulators that were allocated will be freed 3181414c70cbSLiam Girdwood * before returning to the caller. 3182414c70cbSLiam Girdwood */ 3183414c70cbSLiam Girdwood int regulator_bulk_get(struct device *dev, int num_consumers, 3184414c70cbSLiam Girdwood struct regulator_bulk_data *consumers) 3185414c70cbSLiam Girdwood { 3186414c70cbSLiam Girdwood int i; 3187414c70cbSLiam Girdwood int ret; 3188414c70cbSLiam Girdwood 3189414c70cbSLiam Girdwood for (i = 0; i < num_consumers; i++) 3190414c70cbSLiam Girdwood consumers[i].consumer = NULL; 3191414c70cbSLiam Girdwood 3192414c70cbSLiam Girdwood for (i = 0; i < num_consumers; i++) { 3193414c70cbSLiam Girdwood consumers[i].consumer = regulator_get(dev, 3194414c70cbSLiam Girdwood consumers[i].supply); 3195414c70cbSLiam Girdwood if (IS_ERR(consumers[i].consumer)) { 3196414c70cbSLiam Girdwood ret = PTR_ERR(consumers[i].consumer); 31975b307627SMark Brown dev_err(dev, "Failed to get supply '%s': %d\n", 31985b307627SMark Brown consumers[i].supply, ret); 3199414c70cbSLiam Girdwood consumers[i].consumer = NULL; 3200414c70cbSLiam Girdwood goto err; 3201414c70cbSLiam Girdwood } 3202414c70cbSLiam Girdwood } 3203414c70cbSLiam Girdwood 3204414c70cbSLiam Girdwood return 0; 3205414c70cbSLiam Girdwood 3206414c70cbSLiam Girdwood err: 3207b29c7690SAxel Lin while (--i >= 0) 3208414c70cbSLiam Girdwood regulator_put(consumers[i].consumer); 3209414c70cbSLiam Girdwood 3210414c70cbSLiam Girdwood return ret; 3211414c70cbSLiam Girdwood } 3212414c70cbSLiam Girdwood EXPORT_SYMBOL_GPL(regulator_bulk_get); 3213414c70cbSLiam Girdwood 3214f21e0e81SMark Brown static void regulator_bulk_enable_async(void *data, async_cookie_t cookie) 3215f21e0e81SMark Brown { 3216f21e0e81SMark Brown struct regulator_bulk_data *bulk = data; 3217f21e0e81SMark Brown 3218f21e0e81SMark Brown bulk->ret = regulator_enable(bulk->consumer); 3219f21e0e81SMark Brown } 3220f21e0e81SMark Brown 3221414c70cbSLiam Girdwood /** 3222414c70cbSLiam Girdwood * regulator_bulk_enable - enable multiple regulator consumers 3223414c70cbSLiam Girdwood * 3224414c70cbSLiam Girdwood * @num_consumers: Number of consumers 3225414c70cbSLiam Girdwood * @consumers: Consumer data; clients are stored here. 3226414c70cbSLiam Girdwood * @return 0 on success, an errno on failure 3227414c70cbSLiam Girdwood * 3228414c70cbSLiam Girdwood * This convenience API allows consumers to enable multiple regulator 3229414c70cbSLiam Girdwood * clients in a single API call. If any consumers cannot be enabled 3230414c70cbSLiam Girdwood * then any others that were enabled will be disabled again prior to 3231414c70cbSLiam Girdwood * return. 3232414c70cbSLiam Girdwood */ 3233414c70cbSLiam Girdwood int regulator_bulk_enable(int num_consumers, 3234414c70cbSLiam Girdwood struct regulator_bulk_data *consumers) 3235414c70cbSLiam Girdwood { 32362955b47dSDan Williams ASYNC_DOMAIN_EXCLUSIVE(async_domain); 3237414c70cbSLiam Girdwood int i; 3238f21e0e81SMark Brown int ret = 0; 3239414c70cbSLiam Girdwood 32406492bc1bSMark Brown for (i = 0; i < num_consumers; i++) { 32416492bc1bSMark Brown if (consumers[i].consumer->always_on) 32426492bc1bSMark Brown consumers[i].ret = 0; 32436492bc1bSMark Brown else 3244f21e0e81SMark Brown async_schedule_domain(regulator_bulk_enable_async, 3245f21e0e81SMark Brown &consumers[i], &async_domain); 32466492bc1bSMark Brown } 3247f21e0e81SMark Brown 3248f21e0e81SMark Brown async_synchronize_full_domain(&async_domain); 3249f21e0e81SMark Brown 3250f21e0e81SMark Brown /* If any consumer failed we need to unwind any that succeeded */ 3251414c70cbSLiam Girdwood for (i = 0; i < num_consumers; i++) { 3252f21e0e81SMark Brown if (consumers[i].ret != 0) { 3253f21e0e81SMark Brown ret = consumers[i].ret; 3254414c70cbSLiam Girdwood goto err; 3255414c70cbSLiam Girdwood } 3256f21e0e81SMark Brown } 3257414c70cbSLiam Girdwood 3258414c70cbSLiam Girdwood return 0; 3259414c70cbSLiam Girdwood 3260414c70cbSLiam Girdwood err: 3261fbe31057SAndrzej Hajda for (i = 0; i < num_consumers; i++) { 3262fbe31057SAndrzej Hajda if (consumers[i].ret < 0) 3263fbe31057SAndrzej Hajda pr_err("Failed to enable %s: %d\n", consumers[i].supply, 3264fbe31057SAndrzej Hajda consumers[i].ret); 3265fbe31057SAndrzej Hajda else 3266414c70cbSLiam Girdwood regulator_disable(consumers[i].consumer); 3267fbe31057SAndrzej Hajda } 3268414c70cbSLiam Girdwood 3269414c70cbSLiam Girdwood return ret; 3270414c70cbSLiam Girdwood } 3271414c70cbSLiam Girdwood EXPORT_SYMBOL_GPL(regulator_bulk_enable); 3272414c70cbSLiam Girdwood 3273414c70cbSLiam Girdwood /** 3274414c70cbSLiam Girdwood * regulator_bulk_disable - disable multiple regulator consumers 3275414c70cbSLiam Girdwood * 3276414c70cbSLiam Girdwood * @num_consumers: Number of consumers 3277414c70cbSLiam Girdwood * @consumers: Consumer data; clients are stored here. 3278414c70cbSLiam Girdwood * @return 0 on success, an errno on failure 3279414c70cbSLiam Girdwood * 3280414c70cbSLiam Girdwood * This convenience API allows consumers to disable multiple regulator 328149e22632SSylwester Nawrocki * clients in a single API call. If any consumers cannot be disabled 328249e22632SSylwester Nawrocki * then any others that were disabled will be enabled again prior to 3283414c70cbSLiam Girdwood * return. 3284414c70cbSLiam Girdwood */ 3285414c70cbSLiam Girdwood int regulator_bulk_disable(int num_consumers, 3286414c70cbSLiam Girdwood struct regulator_bulk_data *consumers) 3287414c70cbSLiam Girdwood { 3288414c70cbSLiam Girdwood int i; 328901e86f49SMark Brown int ret, r; 3290414c70cbSLiam Girdwood 329149e22632SSylwester Nawrocki for (i = num_consumers - 1; i >= 0; --i) { 3292414c70cbSLiam Girdwood ret = regulator_disable(consumers[i].consumer); 3293414c70cbSLiam Girdwood if (ret != 0) 3294414c70cbSLiam Girdwood goto err; 3295414c70cbSLiam Girdwood } 3296414c70cbSLiam Girdwood 3297414c70cbSLiam Girdwood return 0; 3298414c70cbSLiam Girdwood 3299414c70cbSLiam Girdwood err: 33005da84fd9SJoe Perches pr_err("Failed to disable %s: %d\n", consumers[i].supply, ret); 330101e86f49SMark Brown for (++i; i < num_consumers; ++i) { 330201e86f49SMark Brown r = regulator_enable(consumers[i].consumer); 330301e86f49SMark Brown if (r != 0) 330401e86f49SMark Brown pr_err("Failed to reename %s: %d\n", 330501e86f49SMark Brown consumers[i].supply, r); 330601e86f49SMark Brown } 3307414c70cbSLiam Girdwood 3308414c70cbSLiam Girdwood return ret; 3309414c70cbSLiam Girdwood } 3310414c70cbSLiam Girdwood EXPORT_SYMBOL_GPL(regulator_bulk_disable); 3311414c70cbSLiam Girdwood 3312414c70cbSLiam Girdwood /** 3313e1de2f42SDonggeun Kim * regulator_bulk_force_disable - force disable multiple regulator consumers 3314e1de2f42SDonggeun Kim * 3315e1de2f42SDonggeun Kim * @num_consumers: Number of consumers 3316e1de2f42SDonggeun Kim * @consumers: Consumer data; clients are stored here. 3317e1de2f42SDonggeun Kim * @return 0 on success, an errno on failure 3318e1de2f42SDonggeun Kim * 3319e1de2f42SDonggeun Kim * This convenience API allows consumers to forcibly disable multiple regulator 3320e1de2f42SDonggeun Kim * clients in a single API call. 3321e1de2f42SDonggeun Kim * NOTE: This should be used for situations when device damage will 3322e1de2f42SDonggeun Kim * likely occur if the regulators are not disabled (e.g. over temp). 3323e1de2f42SDonggeun Kim * Although regulator_force_disable function call for some consumers can 3324e1de2f42SDonggeun Kim * return error numbers, the function is called for all consumers. 3325e1de2f42SDonggeun Kim */ 3326e1de2f42SDonggeun Kim int regulator_bulk_force_disable(int num_consumers, 3327e1de2f42SDonggeun Kim struct regulator_bulk_data *consumers) 3328e1de2f42SDonggeun Kim { 3329e1de2f42SDonggeun Kim int i; 3330e1de2f42SDonggeun Kim int ret; 3331e1de2f42SDonggeun Kim 3332e1de2f42SDonggeun Kim for (i = 0; i < num_consumers; i++) 3333e1de2f42SDonggeun Kim consumers[i].ret = 3334e1de2f42SDonggeun Kim regulator_force_disable(consumers[i].consumer); 3335e1de2f42SDonggeun Kim 3336e1de2f42SDonggeun Kim for (i = 0; i < num_consumers; i++) { 3337e1de2f42SDonggeun Kim if (consumers[i].ret != 0) { 3338e1de2f42SDonggeun Kim ret = consumers[i].ret; 3339e1de2f42SDonggeun Kim goto out; 3340e1de2f42SDonggeun Kim } 3341e1de2f42SDonggeun Kim } 3342e1de2f42SDonggeun Kim 3343e1de2f42SDonggeun Kim return 0; 3344e1de2f42SDonggeun Kim out: 3345e1de2f42SDonggeun Kim return ret; 3346e1de2f42SDonggeun Kim } 3347e1de2f42SDonggeun Kim EXPORT_SYMBOL_GPL(regulator_bulk_force_disable); 3348e1de2f42SDonggeun Kim 3349e1de2f42SDonggeun Kim /** 3350414c70cbSLiam Girdwood * regulator_bulk_free - free multiple regulator consumers 3351414c70cbSLiam Girdwood * 3352414c70cbSLiam Girdwood * @num_consumers: Number of consumers 3353414c70cbSLiam Girdwood * @consumers: Consumer data; clients are stored here. 3354414c70cbSLiam Girdwood * 3355414c70cbSLiam Girdwood * This convenience API allows consumers to free multiple regulator 3356414c70cbSLiam Girdwood * clients in a single API call. 3357414c70cbSLiam Girdwood */ 3358414c70cbSLiam Girdwood void regulator_bulk_free(int num_consumers, 3359414c70cbSLiam Girdwood struct regulator_bulk_data *consumers) 3360414c70cbSLiam Girdwood { 3361414c70cbSLiam Girdwood int i; 3362414c70cbSLiam Girdwood 3363414c70cbSLiam Girdwood for (i = 0; i < num_consumers; i++) { 3364414c70cbSLiam Girdwood regulator_put(consumers[i].consumer); 3365414c70cbSLiam Girdwood consumers[i].consumer = NULL; 3366414c70cbSLiam Girdwood } 3367414c70cbSLiam Girdwood } 3368414c70cbSLiam Girdwood EXPORT_SYMBOL_GPL(regulator_bulk_free); 3369414c70cbSLiam Girdwood 3370414c70cbSLiam Girdwood /** 3371414c70cbSLiam Girdwood * regulator_notifier_call_chain - call regulator event notifier 337269279fb9SMark Brown * @rdev: regulator source 3373414c70cbSLiam Girdwood * @event: notifier block 337469279fb9SMark Brown * @data: callback-specific data. 3375414c70cbSLiam Girdwood * 3376414c70cbSLiam Girdwood * Called by regulator drivers to notify clients a regulator event has 3377414c70cbSLiam Girdwood * occurred. We also notify regulator clients downstream. 3378b136fb44SJonathan Cameron * Note lock must be held by caller. 3379414c70cbSLiam Girdwood */ 3380414c70cbSLiam Girdwood int regulator_notifier_call_chain(struct regulator_dev *rdev, 3381414c70cbSLiam Girdwood unsigned long event, void *data) 3382414c70cbSLiam Girdwood { 3383414c70cbSLiam Girdwood _notifier_call_chain(rdev, event, data); 3384414c70cbSLiam Girdwood return NOTIFY_DONE; 3385414c70cbSLiam Girdwood 3386414c70cbSLiam Girdwood } 3387414c70cbSLiam Girdwood EXPORT_SYMBOL_GPL(regulator_notifier_call_chain); 3388414c70cbSLiam Girdwood 3389be721979SMark Brown /** 3390be721979SMark Brown * regulator_mode_to_status - convert a regulator mode into a status 3391be721979SMark Brown * 3392be721979SMark Brown * @mode: Mode to convert 3393be721979SMark Brown * 3394be721979SMark Brown * Convert a regulator mode into a status. 3395be721979SMark Brown */ 3396be721979SMark Brown int regulator_mode_to_status(unsigned int mode) 3397be721979SMark Brown { 3398be721979SMark Brown switch (mode) { 3399be721979SMark Brown case REGULATOR_MODE_FAST: 3400be721979SMark Brown return REGULATOR_STATUS_FAST; 3401be721979SMark Brown case REGULATOR_MODE_NORMAL: 3402be721979SMark Brown return REGULATOR_STATUS_NORMAL; 3403be721979SMark Brown case REGULATOR_MODE_IDLE: 3404be721979SMark Brown return REGULATOR_STATUS_IDLE; 340503ffcf3dSKrystian Garbaciak case REGULATOR_MODE_STANDBY: 3406be721979SMark Brown return REGULATOR_STATUS_STANDBY; 3407be721979SMark Brown default: 34081beaf762SKrystian Garbaciak return REGULATOR_STATUS_UNDEFINED; 3409be721979SMark Brown } 3410be721979SMark Brown } 3411be721979SMark Brown EXPORT_SYMBOL_GPL(regulator_mode_to_status); 3412be721979SMark Brown 341339f802d6STakashi Iwai static struct attribute *regulator_dev_attrs[] = { 341439f802d6STakashi Iwai &dev_attr_name.attr, 341539f802d6STakashi Iwai &dev_attr_num_users.attr, 341639f802d6STakashi Iwai &dev_attr_type.attr, 341739f802d6STakashi Iwai &dev_attr_microvolts.attr, 341839f802d6STakashi Iwai &dev_attr_microamps.attr, 341939f802d6STakashi Iwai &dev_attr_opmode.attr, 342039f802d6STakashi Iwai &dev_attr_state.attr, 342139f802d6STakashi Iwai &dev_attr_status.attr, 342239f802d6STakashi Iwai &dev_attr_bypass.attr, 342339f802d6STakashi Iwai &dev_attr_requested_microamps.attr, 342439f802d6STakashi Iwai &dev_attr_min_microvolts.attr, 342539f802d6STakashi Iwai &dev_attr_max_microvolts.attr, 342639f802d6STakashi Iwai &dev_attr_min_microamps.attr, 342739f802d6STakashi Iwai &dev_attr_max_microamps.attr, 342839f802d6STakashi Iwai &dev_attr_suspend_standby_state.attr, 342939f802d6STakashi Iwai &dev_attr_suspend_mem_state.attr, 343039f802d6STakashi Iwai &dev_attr_suspend_disk_state.attr, 343139f802d6STakashi Iwai &dev_attr_suspend_standby_microvolts.attr, 343239f802d6STakashi Iwai &dev_attr_suspend_mem_microvolts.attr, 343339f802d6STakashi Iwai &dev_attr_suspend_disk_microvolts.attr, 343439f802d6STakashi Iwai &dev_attr_suspend_standby_mode.attr, 343539f802d6STakashi Iwai &dev_attr_suspend_mem_mode.attr, 343639f802d6STakashi Iwai &dev_attr_suspend_disk_mode.attr, 343739f802d6STakashi Iwai NULL 343839f802d6STakashi Iwai }; 343939f802d6STakashi Iwai 34407ad68e2fSDavid Brownell /* 34417ad68e2fSDavid Brownell * To avoid cluttering sysfs (and memory) with useless state, only 34427ad68e2fSDavid Brownell * create attributes that can be meaningfully displayed. 34437ad68e2fSDavid Brownell */ 344439f802d6STakashi Iwai static umode_t regulator_attr_is_visible(struct kobject *kobj, 344539f802d6STakashi Iwai struct attribute *attr, int idx) 34467ad68e2fSDavid Brownell { 344739f802d6STakashi Iwai struct device *dev = kobj_to_dev(kobj); 344839f802d6STakashi Iwai struct regulator_dev *rdev = container_of(dev, struct regulator_dev, dev); 3449272e2315SGuodong Xu const struct regulator_ops *ops = rdev->desc->ops; 345039f802d6STakashi Iwai umode_t mode = attr->mode; 345139f802d6STakashi Iwai 345239f802d6STakashi Iwai /* these three are always present */ 345339f802d6STakashi Iwai if (attr == &dev_attr_name.attr || 345439f802d6STakashi Iwai attr == &dev_attr_num_users.attr || 345539f802d6STakashi Iwai attr == &dev_attr_type.attr) 345639f802d6STakashi Iwai return mode; 34577ad68e2fSDavid Brownell 34587ad68e2fSDavid Brownell /* some attributes need specific methods to be displayed */ 345939f802d6STakashi Iwai if (attr == &dev_attr_microvolts.attr) { 34604c78899bSMark Brown if ((ops->get_voltage && ops->get_voltage(rdev) >= 0) || 3461f2889e65SMark Brown (ops->get_voltage_sel && ops->get_voltage_sel(rdev) >= 0) || 34625a523605SLaxman Dewangan (ops->list_voltage && ops->list_voltage(rdev, 0) >= 0) || 346339f802d6STakashi Iwai (rdev->desc->fixed_uV && rdev->desc->n_voltages == 1)) 346439f802d6STakashi Iwai return mode; 346539f802d6STakashi Iwai return 0; 3466f59c8f9fSMark Brown } 34677ad68e2fSDavid Brownell 346839f802d6STakashi Iwai if (attr == &dev_attr_microamps.attr) 346939f802d6STakashi Iwai return ops->get_current_limit ? mode : 0; 347039f802d6STakashi Iwai 347139f802d6STakashi Iwai if (attr == &dev_attr_opmode.attr) 347239f802d6STakashi Iwai return ops->get_mode ? mode : 0; 347339f802d6STakashi Iwai 347439f802d6STakashi Iwai if (attr == &dev_attr_state.attr) 347539f802d6STakashi Iwai return (rdev->ena_pin || ops->is_enabled) ? mode : 0; 347639f802d6STakashi Iwai 347739f802d6STakashi Iwai if (attr == &dev_attr_status.attr) 347839f802d6STakashi Iwai return ops->get_status ? mode : 0; 347939f802d6STakashi Iwai 348039f802d6STakashi Iwai if (attr == &dev_attr_bypass.attr) 348139f802d6STakashi Iwai return ops->get_bypass ? mode : 0; 348239f802d6STakashi Iwai 34837ad68e2fSDavid Brownell /* some attributes are type-specific */ 348439f802d6STakashi Iwai if (attr == &dev_attr_requested_microamps.attr) 348539f802d6STakashi Iwai return rdev->desc->type == REGULATOR_CURRENT ? mode : 0; 34867ad68e2fSDavid Brownell 34877ad68e2fSDavid Brownell /* all the other attributes exist to support constraints; 34887ad68e2fSDavid Brownell * don't show them if there are no constraints, or if the 34897ad68e2fSDavid Brownell * relevant supporting methods are missing. 34907ad68e2fSDavid Brownell */ 34917ad68e2fSDavid Brownell if (!rdev->constraints) 349239f802d6STakashi Iwai return 0; 34937ad68e2fSDavid Brownell 34947ad68e2fSDavid Brownell /* constraints need specific supporting methods */ 349539f802d6STakashi Iwai if (attr == &dev_attr_min_microvolts.attr || 349639f802d6STakashi Iwai attr == &dev_attr_max_microvolts.attr) 349739f802d6STakashi Iwai return (ops->set_voltage || ops->set_voltage_sel) ? mode : 0; 349839f802d6STakashi Iwai 349939f802d6STakashi Iwai if (attr == &dev_attr_min_microamps.attr || 350039f802d6STakashi Iwai attr == &dev_attr_max_microamps.attr) 350139f802d6STakashi Iwai return ops->set_current_limit ? mode : 0; 350239f802d6STakashi Iwai 350339f802d6STakashi Iwai if (attr == &dev_attr_suspend_standby_state.attr || 350439f802d6STakashi Iwai attr == &dev_attr_suspend_mem_state.attr || 350539f802d6STakashi Iwai attr == &dev_attr_suspend_disk_state.attr) 350639f802d6STakashi Iwai return mode; 350739f802d6STakashi Iwai 350839f802d6STakashi Iwai if (attr == &dev_attr_suspend_standby_microvolts.attr || 350939f802d6STakashi Iwai attr == &dev_attr_suspend_mem_microvolts.attr || 351039f802d6STakashi Iwai attr == &dev_attr_suspend_disk_microvolts.attr) 351139f802d6STakashi Iwai return ops->set_suspend_voltage ? mode : 0; 351239f802d6STakashi Iwai 351339f802d6STakashi Iwai if (attr == &dev_attr_suspend_standby_mode.attr || 351439f802d6STakashi Iwai attr == &dev_attr_suspend_mem_mode.attr || 351539f802d6STakashi Iwai attr == &dev_attr_suspend_disk_mode.attr) 351639f802d6STakashi Iwai return ops->set_suspend_mode ? mode : 0; 351739f802d6STakashi Iwai 351839f802d6STakashi Iwai return mode; 35197ad68e2fSDavid Brownell } 35207ad68e2fSDavid Brownell 352139f802d6STakashi Iwai static const struct attribute_group regulator_dev_group = { 352239f802d6STakashi Iwai .attrs = regulator_dev_attrs, 352339f802d6STakashi Iwai .is_visible = regulator_attr_is_visible, 352439f802d6STakashi Iwai }; 35257ad68e2fSDavid Brownell 352639f802d6STakashi Iwai static const struct attribute_group *regulator_dev_groups[] = { 352739f802d6STakashi Iwai ®ulator_dev_group, 352839f802d6STakashi Iwai NULL 352939f802d6STakashi Iwai }; 353039f802d6STakashi Iwai 353139f802d6STakashi Iwai static void regulator_dev_release(struct device *dev) 353239f802d6STakashi Iwai { 353339f802d6STakashi Iwai struct regulator_dev *rdev = dev_get_drvdata(dev); 353439f802d6STakashi Iwai kfree(rdev); 35357ad68e2fSDavid Brownell } 35367ad68e2fSDavid Brownell 353739f802d6STakashi Iwai static struct class regulator_class = { 353839f802d6STakashi Iwai .name = "regulator", 353939f802d6STakashi Iwai .dev_release = regulator_dev_release, 354039f802d6STakashi Iwai .dev_groups = regulator_dev_groups, 354139f802d6STakashi Iwai }; 35427ad68e2fSDavid Brownell 35431130e5b3SMark Brown static void rdev_init_debugfs(struct regulator_dev *rdev) 35441130e5b3SMark Brown { 35451130e5b3SMark Brown rdev->debugfs = debugfs_create_dir(rdev_get_name(rdev), debugfs_root); 354624751434SStephen Boyd if (!rdev->debugfs) { 35471130e5b3SMark Brown rdev_warn(rdev, "Failed to create debugfs directory\n"); 35481130e5b3SMark Brown return; 35491130e5b3SMark Brown } 35501130e5b3SMark Brown 35511130e5b3SMark Brown debugfs_create_u32("use_count", 0444, rdev->debugfs, 35521130e5b3SMark Brown &rdev->use_count); 35531130e5b3SMark Brown debugfs_create_u32("open_count", 0444, rdev->debugfs, 35541130e5b3SMark Brown &rdev->open_count); 3555f59c8f9fSMark Brown debugfs_create_u32("bypass_count", 0444, rdev->debugfs, 3556f59c8f9fSMark Brown &rdev->bypass_count); 35571130e5b3SMark Brown } 35581130e5b3SMark Brown 3559414c70cbSLiam Girdwood /** 3560414c70cbSLiam Girdwood * regulator_register - register regulator 356169279fb9SMark Brown * @regulator_desc: regulator to register 3562c172708dSMark Brown * @config: runtime configuration for regulator 3563414c70cbSLiam Girdwood * 3564414c70cbSLiam Girdwood * Called by regulator drivers to register a regulator. 35650384618aSAxel Lin * Returns a valid pointer to struct regulator_dev on success 35660384618aSAxel Lin * or an ERR_PTR() on error. 3567414c70cbSLiam Girdwood */ 356865f26846SMark Brown struct regulator_dev * 356965f26846SMark Brown regulator_register(const struct regulator_desc *regulator_desc, 3570c172708dSMark Brown const struct regulator_config *config) 3571414c70cbSLiam Girdwood { 35729a8f5e07SMark Brown const struct regulation_constraints *constraints = NULL; 3573c172708dSMark Brown const struct regulator_init_data *init_data; 357472dca06fSAniroop Mathur static atomic_t regulator_no = ATOMIC_INIT(-1); 3575414c70cbSLiam Girdwood struct regulator_dev *rdev; 357632c8fad4SMark Brown struct device *dev; 3577a5766f11SLiam Girdwood int ret, i; 357869511a45SRajendra Nayak const char *supply = NULL; 3579414c70cbSLiam Girdwood 3580c172708dSMark Brown if (regulator_desc == NULL || config == NULL) 3581414c70cbSLiam Girdwood return ERR_PTR(-EINVAL); 3582414c70cbSLiam Girdwood 358332c8fad4SMark Brown dev = config->dev; 3584dcf70112SMark Brown WARN_ON(!dev); 358532c8fad4SMark Brown 3586414c70cbSLiam Girdwood if (regulator_desc->name == NULL || regulator_desc->ops == NULL) 3587414c70cbSLiam Girdwood return ERR_PTR(-EINVAL); 3588414c70cbSLiam Girdwood 3589cd78dfc6SDiego Liziero if (regulator_desc->type != REGULATOR_VOLTAGE && 3590cd78dfc6SDiego Liziero regulator_desc->type != REGULATOR_CURRENT) 3591414c70cbSLiam Girdwood return ERR_PTR(-EINVAL); 3592414c70cbSLiam Girdwood 3593476c2d83SMark Brown /* Only one of each should be implemented */ 3594476c2d83SMark Brown WARN_ON(regulator_desc->ops->get_voltage && 3595476c2d83SMark Brown regulator_desc->ops->get_voltage_sel); 3596e8eef82bSMark Brown WARN_ON(regulator_desc->ops->set_voltage && 3597e8eef82bSMark Brown regulator_desc->ops->set_voltage_sel); 3598476c2d83SMark Brown 3599476c2d83SMark Brown /* If we're using selectors we must implement list_voltage. */ 3600476c2d83SMark Brown if (regulator_desc->ops->get_voltage_sel && 3601476c2d83SMark Brown !regulator_desc->ops->list_voltage) { 3602476c2d83SMark Brown return ERR_PTR(-EINVAL); 3603476c2d83SMark Brown } 3604e8eef82bSMark Brown if (regulator_desc->ops->set_voltage_sel && 3605e8eef82bSMark Brown !regulator_desc->ops->list_voltage) { 3606e8eef82bSMark Brown return ERR_PTR(-EINVAL); 3607e8eef82bSMark Brown } 3608476c2d83SMark Brown 3609414c70cbSLiam Girdwood rdev = kzalloc(sizeof(struct regulator_dev), GFP_KERNEL); 3610414c70cbSLiam Girdwood if (rdev == NULL) 3611414c70cbSLiam Girdwood return ERR_PTR(-ENOMEM); 3612414c70cbSLiam Girdwood 3613a0c7b164SMark Brown init_data = regulator_of_get_init_data(dev, regulator_desc, 3614a0c7b164SMark Brown &rdev->dev.of_node); 3615a0c7b164SMark Brown if (!init_data) { 3616a0c7b164SMark Brown init_data = config->init_data; 3617a0c7b164SMark Brown rdev->dev.of_node = of_node_get(config->of_node); 3618a0c7b164SMark Brown } 3619a0c7b164SMark Brown 3620414c70cbSLiam Girdwood mutex_lock(®ulator_list_mutex); 3621414c70cbSLiam Girdwood 3622414c70cbSLiam Girdwood mutex_init(&rdev->mutex); 3623c172708dSMark Brown rdev->reg_data = config->driver_data; 3624414c70cbSLiam Girdwood rdev->owner = regulator_desc->owner; 3625414c70cbSLiam Girdwood rdev->desc = regulator_desc; 36263a4b0a07SMark Brown if (config->regmap) 362765b19ce6SMark Brown rdev->regmap = config->regmap; 362852b84dacSAnilKumar Ch else if (dev_get_regmap(dev, NULL)) 36293a4b0a07SMark Brown rdev->regmap = dev_get_regmap(dev, NULL); 363052b84dacSAnilKumar Ch else if (dev->parent) 363152b84dacSAnilKumar Ch rdev->regmap = dev_get_regmap(dev->parent, NULL); 3632414c70cbSLiam Girdwood INIT_LIST_HEAD(&rdev->consumer_list); 3633414c70cbSLiam Girdwood INIT_LIST_HEAD(&rdev->list); 3634414c70cbSLiam Girdwood BLOCKING_INIT_NOTIFIER_HEAD(&rdev->notifier); 3635da07ecd9SMark Brown INIT_DELAYED_WORK(&rdev->disable_work, regulator_disable_work); 3636414c70cbSLiam Girdwood 3637a5766f11SLiam Girdwood /* preform any regulator specific init */ 36389a8f5e07SMark Brown if (init_data && init_data->regulator_init) { 3639a5766f11SLiam Girdwood ret = init_data->regulator_init(rdev->reg_data); 36404fca9545SDavid Brownell if (ret < 0) 36414fca9545SDavid Brownell goto clean; 3642a5766f11SLiam Girdwood } 3643a5766f11SLiam Girdwood 3644a5766f11SLiam Girdwood /* register with sysfs */ 3645a5766f11SLiam Girdwood rdev->dev.class = ®ulator_class; 3646a5766f11SLiam Girdwood rdev->dev.parent = dev; 364772dca06fSAniroop Mathur dev_set_name(&rdev->dev, "regulator.%lu", 364839138818SAniroop Mathur (unsigned long) atomic_inc_return(®ulator_no)); 3649a5766f11SLiam Girdwood ret = device_register(&rdev->dev); 3650ad7725cbSVasiliy Kulikov if (ret != 0) { 3651ad7725cbSVasiliy Kulikov put_device(&rdev->dev); 36524fca9545SDavid Brownell goto clean; 3653ad7725cbSVasiliy Kulikov } 3654a5766f11SLiam Girdwood 3655a5766f11SLiam Girdwood dev_set_drvdata(&rdev->dev, rdev); 3656a5766f11SLiam Girdwood 365776f439dfSMarkus Pargmann if ((config->ena_gpio || config->ena_gpio_initialized) && 365876f439dfSMarkus Pargmann gpio_is_valid(config->ena_gpio)) { 3659f19b00daSKim, Milo ret = regulator_ena_gpio_request(rdev, config); 366065f73508SMark Brown if (ret != 0) { 366165f73508SMark Brown rdev_err(rdev, "Failed to request enable GPIO%d: %d\n", 366265f73508SMark Brown config->ena_gpio, ret); 3663b2da55d9SAndrew Lunn goto wash; 366465f73508SMark Brown } 366565f73508SMark Brown 366665f73508SMark Brown if (config->ena_gpio_flags & GPIOF_OUT_INIT_HIGH) 366765f73508SMark Brown rdev->ena_gpio_state = 1; 366865f73508SMark Brown 36697b74d149SKim, Milo if (config->ena_gpio_invert) 367065f73508SMark Brown rdev->ena_gpio_state = !rdev->ena_gpio_state; 367165f73508SMark Brown } 367265f73508SMark Brown 367374f544c1SMike Rapoport /* set regulator constraints */ 36749a8f5e07SMark Brown if (init_data) 36759a8f5e07SMark Brown constraints = &init_data->constraints; 36769a8f5e07SMark Brown 36779a8f5e07SMark Brown ret = set_machine_constraints(rdev, constraints); 367874f544c1SMike Rapoport if (ret < 0) 367974f544c1SMike Rapoport goto scrub; 368074f544c1SMike Rapoport 36819a8f5e07SMark Brown if (init_data && init_data->supply_regulator) 368269511a45SRajendra Nayak supply = init_data->supply_regulator; 368369511a45SRajendra Nayak else if (regulator_desc->supply_name) 368469511a45SRajendra Nayak supply = regulator_desc->supply_name; 368569511a45SRajendra Nayak 368669511a45SRajendra Nayak if (supply) { 36870178f3e2SMark Brown struct regulator_dev *r; 36880178f3e2SMark Brown 36896d191a5fSMark Brown r = regulator_dev_lookup(dev, supply, &ret); 36900178f3e2SMark Brown 36910f7b87f0SAndrew Bresticker if (ret == -ENODEV) { 36920f7b87f0SAndrew Bresticker /* 36930f7b87f0SAndrew Bresticker * No supply was specified for this regulator and 36940f7b87f0SAndrew Bresticker * there will never be one. 36950f7b87f0SAndrew Bresticker */ 36960f7b87f0SAndrew Bresticker ret = 0; 36970f7b87f0SAndrew Bresticker goto add_dev; 36980f7b87f0SAndrew Bresticker } else if (!r) { 369969511a45SRajendra Nayak dev_err(dev, "Failed to find supply %s\n", supply); 370004bf3011SMark Brown ret = -EPROBE_DEFER; 37010178f3e2SMark Brown goto scrub; 37020178f3e2SMark Brown } 37030178f3e2SMark Brown 37040178f3e2SMark Brown ret = set_supply(rdev, r); 37050178f3e2SMark Brown if (ret < 0) 37060178f3e2SMark Brown goto scrub; 3707b2296bd4SLaxman Dewangan 3708b2296bd4SLaxman Dewangan /* Enable supply if rail is enabled */ 3709b1a86831SMark Brown if (_regulator_is_enabled(rdev)) { 3710b2296bd4SLaxman Dewangan ret = regulator_enable(rdev->supply); 3711b2296bd4SLaxman Dewangan if (ret < 0) 3712b2296bd4SLaxman Dewangan goto scrub; 3713b2296bd4SLaxman Dewangan } 37140178f3e2SMark Brown } 37150178f3e2SMark Brown 37160f7b87f0SAndrew Bresticker add_dev: 3717a5766f11SLiam Girdwood /* add consumers devices */ 37189a8f5e07SMark Brown if (init_data) { 3719a5766f11SLiam Girdwood for (i = 0; i < init_data->num_consumer_supplies; i++) { 3720a5766f11SLiam Girdwood ret = set_consumer_device_supply(rdev, 372140f9244fSMark Brown init_data->consumer_supplies[i].dev_name, 3722a5766f11SLiam Girdwood init_data->consumer_supplies[i].supply); 372323c2f041SMark Brown if (ret < 0) { 372423c2f041SMark Brown dev_err(dev, "Failed to set supply %s\n", 372523c2f041SMark Brown init_data->consumer_supplies[i].supply); 3726d4033b54SJani Nikula goto unset_supplies; 3727a5766f11SLiam Girdwood } 372823c2f041SMark Brown } 37299a8f5e07SMark Brown } 3730a5766f11SLiam Girdwood 3731a5766f11SLiam Girdwood list_add(&rdev->list, ®ulator_list); 37321130e5b3SMark Brown 37331130e5b3SMark Brown rdev_init_debugfs(rdev); 3734a5766f11SLiam Girdwood out: 3735414c70cbSLiam Girdwood mutex_unlock(®ulator_list_mutex); 3736414c70cbSLiam Girdwood return rdev; 37374fca9545SDavid Brownell 3738d4033b54SJani Nikula unset_supplies: 3739d4033b54SJani Nikula unset_regulator_supplies(rdev); 3740d4033b54SJani Nikula 37414fca9545SDavid Brownell scrub: 3742e81dba85SMark Brown if (rdev->supply) 374323ff2f0fSCharles Keepax _regulator_put(rdev->supply); 3744f19b00daSKim, Milo regulator_ena_gpio_free(rdev); 37451a6958e7SAxel Lin kfree(rdev->constraints); 3746b2da55d9SAndrew Lunn wash: 37474fca9545SDavid Brownell device_unregister(&rdev->dev); 374853032dafSPaul Walmsley /* device core frees rdev */ 374953032dafSPaul Walmsley rdev = ERR_PTR(ret); 375053032dafSPaul Walmsley goto out; 375153032dafSPaul Walmsley 37524fca9545SDavid Brownell clean: 37534fca9545SDavid Brownell kfree(rdev); 37544fca9545SDavid Brownell rdev = ERR_PTR(ret); 37554fca9545SDavid Brownell goto out; 3756414c70cbSLiam Girdwood } 3757414c70cbSLiam Girdwood EXPORT_SYMBOL_GPL(regulator_register); 3758414c70cbSLiam Girdwood 3759414c70cbSLiam Girdwood /** 3760414c70cbSLiam Girdwood * regulator_unregister - unregister regulator 376169279fb9SMark Brown * @rdev: regulator to unregister 3762414c70cbSLiam Girdwood * 3763414c70cbSLiam Girdwood * Called by regulator drivers to unregister a regulator. 3764414c70cbSLiam Girdwood */ 3765414c70cbSLiam Girdwood void regulator_unregister(struct regulator_dev *rdev) 3766414c70cbSLiam Girdwood { 3767414c70cbSLiam Girdwood if (rdev == NULL) 3768414c70cbSLiam Girdwood return; 3769414c70cbSLiam Girdwood 3770891636eaSMark Brown if (rdev->supply) { 3771891636eaSMark Brown while (rdev->use_count--) 3772891636eaSMark Brown regulator_disable(rdev->supply); 3773e032b376SMark Brown regulator_put(rdev->supply); 3774891636eaSMark Brown } 3775414c70cbSLiam Girdwood mutex_lock(®ulator_list_mutex); 37761130e5b3SMark Brown debugfs_remove_recursive(rdev->debugfs); 377743829731STejun Heo flush_work(&rdev->disable_work.work); 37786bf87d17SMark Brown WARN_ON(rdev->open_count); 37790f1d747bSMike Rapoport unset_regulator_supplies(rdev); 3780414c70cbSLiam Girdwood list_del(&rdev->list); 3781f8c12fe3SMark Brown kfree(rdev->constraints); 3782f19b00daSKim, Milo regulator_ena_gpio_free(rdev); 378363c7c9e1SCharles Keepax of_node_put(rdev->dev.of_node); 378458fb5cf5SLothar Waßmann device_unregister(&rdev->dev); 3785414c70cbSLiam Girdwood mutex_unlock(®ulator_list_mutex); 3786414c70cbSLiam Girdwood } 3787414c70cbSLiam Girdwood EXPORT_SYMBOL_GPL(regulator_unregister); 3788414c70cbSLiam Girdwood 3789414c70cbSLiam Girdwood /** 3790cf7bbcdfSMark Brown * regulator_suspend_prepare - prepare regulators for system wide suspend 3791414c70cbSLiam Girdwood * @state: system suspend state 3792414c70cbSLiam Girdwood * 3793414c70cbSLiam Girdwood * Configure each regulator with it's suspend operating parameters for state. 3794414c70cbSLiam Girdwood * This will usually be called by machine suspend code prior to supending. 3795414c70cbSLiam Girdwood */ 3796414c70cbSLiam Girdwood int regulator_suspend_prepare(suspend_state_t state) 3797414c70cbSLiam Girdwood { 3798414c70cbSLiam Girdwood struct regulator_dev *rdev; 3799414c70cbSLiam Girdwood int ret = 0; 3800414c70cbSLiam Girdwood 3801414c70cbSLiam Girdwood /* ON is handled by regulator active state */ 3802414c70cbSLiam Girdwood if (state == PM_SUSPEND_ON) 3803414c70cbSLiam Girdwood return -EINVAL; 3804414c70cbSLiam Girdwood 3805414c70cbSLiam Girdwood mutex_lock(®ulator_list_mutex); 3806414c70cbSLiam Girdwood list_for_each_entry(rdev, ®ulator_list, list) { 3807414c70cbSLiam Girdwood 3808414c70cbSLiam Girdwood mutex_lock(&rdev->mutex); 3809414c70cbSLiam Girdwood ret = suspend_prepare(rdev, state); 3810414c70cbSLiam Girdwood mutex_unlock(&rdev->mutex); 3811414c70cbSLiam Girdwood 3812414c70cbSLiam Girdwood if (ret < 0) { 38135da84fd9SJoe Perches rdev_err(rdev, "failed to prepare\n"); 3814414c70cbSLiam Girdwood goto out; 3815414c70cbSLiam Girdwood } 3816414c70cbSLiam Girdwood } 3817414c70cbSLiam Girdwood out: 3818414c70cbSLiam Girdwood mutex_unlock(®ulator_list_mutex); 3819414c70cbSLiam Girdwood return ret; 3820414c70cbSLiam Girdwood } 3821414c70cbSLiam Girdwood EXPORT_SYMBOL_GPL(regulator_suspend_prepare); 3822414c70cbSLiam Girdwood 3823414c70cbSLiam Girdwood /** 38247a32b589SMyungJoo Ham * regulator_suspend_finish - resume regulators from system wide suspend 38257a32b589SMyungJoo Ham * 38267a32b589SMyungJoo Ham * Turn on regulators that might be turned off by regulator_suspend_prepare 38277a32b589SMyungJoo Ham * and that should be turned on according to the regulators properties. 38287a32b589SMyungJoo Ham */ 38297a32b589SMyungJoo Ham int regulator_suspend_finish(void) 38307a32b589SMyungJoo Ham { 38317a32b589SMyungJoo Ham struct regulator_dev *rdev; 38327a32b589SMyungJoo Ham int ret = 0, error; 38337a32b589SMyungJoo Ham 38347a32b589SMyungJoo Ham mutex_lock(®ulator_list_mutex); 38357a32b589SMyungJoo Ham list_for_each_entry(rdev, ®ulator_list, list) { 38367a32b589SMyungJoo Ham mutex_lock(&rdev->mutex); 383730c21971SMarkus Pargmann if (rdev->use_count > 0 || rdev->constraints->always_on) { 383830c21971SMarkus Pargmann error = _regulator_do_enable(rdev); 38397a32b589SMyungJoo Ham if (error) 38407a32b589SMyungJoo Ham ret = error; 38417a32b589SMyungJoo Ham } else { 384287b28417SMark Brown if (!have_full_constraints()) 38437a32b589SMyungJoo Ham goto unlock; 3844b1a86831SMark Brown if (!_regulator_is_enabled(rdev)) 38457a32b589SMyungJoo Ham goto unlock; 38467a32b589SMyungJoo Ham 384766fda75fSMarkus Pargmann error = _regulator_do_disable(rdev); 38487a32b589SMyungJoo Ham if (error) 38497a32b589SMyungJoo Ham ret = error; 38507a32b589SMyungJoo Ham } 38517a32b589SMyungJoo Ham unlock: 38527a32b589SMyungJoo Ham mutex_unlock(&rdev->mutex); 38537a32b589SMyungJoo Ham } 38547a32b589SMyungJoo Ham mutex_unlock(®ulator_list_mutex); 38557a32b589SMyungJoo Ham return ret; 38567a32b589SMyungJoo Ham } 38577a32b589SMyungJoo Ham EXPORT_SYMBOL_GPL(regulator_suspend_finish); 38587a32b589SMyungJoo Ham 38597a32b589SMyungJoo Ham /** 3860ca725561SMark Brown * regulator_has_full_constraints - the system has fully specified constraints 3861ca725561SMark Brown * 3862ca725561SMark Brown * Calling this function will cause the regulator API to disable all 3863ca725561SMark Brown * regulators which have a zero use count and don't have an always_on 3864ca725561SMark Brown * constraint in a late_initcall. 3865ca725561SMark Brown * 3866ca725561SMark Brown * The intention is that this will become the default behaviour in a 3867ca725561SMark Brown * future kernel release so users are encouraged to use this facility 3868ca725561SMark Brown * now. 3869ca725561SMark Brown */ 3870ca725561SMark Brown void regulator_has_full_constraints(void) 3871ca725561SMark Brown { 3872ca725561SMark Brown has_full_constraints = 1; 3873ca725561SMark Brown } 3874ca725561SMark Brown EXPORT_SYMBOL_GPL(regulator_has_full_constraints); 3875ca725561SMark Brown 3876ca725561SMark Brown /** 3877414c70cbSLiam Girdwood * rdev_get_drvdata - get rdev regulator driver data 387869279fb9SMark Brown * @rdev: regulator 3879414c70cbSLiam Girdwood * 3880414c70cbSLiam Girdwood * Get rdev regulator driver private data. This call can be used in the 3881414c70cbSLiam Girdwood * regulator driver context. 3882414c70cbSLiam Girdwood */ 3883414c70cbSLiam Girdwood void *rdev_get_drvdata(struct regulator_dev *rdev) 3884414c70cbSLiam Girdwood { 3885414c70cbSLiam Girdwood return rdev->reg_data; 3886414c70cbSLiam Girdwood } 3887414c70cbSLiam Girdwood EXPORT_SYMBOL_GPL(rdev_get_drvdata); 3888414c70cbSLiam Girdwood 3889414c70cbSLiam Girdwood /** 3890414c70cbSLiam Girdwood * regulator_get_drvdata - get regulator driver data 3891414c70cbSLiam Girdwood * @regulator: regulator 3892414c70cbSLiam Girdwood * 3893414c70cbSLiam Girdwood * Get regulator driver private data. This call can be used in the consumer 3894414c70cbSLiam Girdwood * driver context when non API regulator specific functions need to be called. 3895414c70cbSLiam Girdwood */ 3896414c70cbSLiam Girdwood void *regulator_get_drvdata(struct regulator *regulator) 3897414c70cbSLiam Girdwood { 3898414c70cbSLiam Girdwood return regulator->rdev->reg_data; 3899414c70cbSLiam Girdwood } 3900414c70cbSLiam Girdwood EXPORT_SYMBOL_GPL(regulator_get_drvdata); 3901414c70cbSLiam Girdwood 3902414c70cbSLiam Girdwood /** 3903414c70cbSLiam Girdwood * regulator_set_drvdata - set regulator driver data 3904414c70cbSLiam Girdwood * @regulator: regulator 3905414c70cbSLiam Girdwood * @data: data 3906414c70cbSLiam Girdwood */ 3907414c70cbSLiam Girdwood void regulator_set_drvdata(struct regulator *regulator, void *data) 3908414c70cbSLiam Girdwood { 3909414c70cbSLiam Girdwood regulator->rdev->reg_data = data; 3910414c70cbSLiam Girdwood } 3911414c70cbSLiam Girdwood EXPORT_SYMBOL_GPL(regulator_set_drvdata); 3912414c70cbSLiam Girdwood 3913414c70cbSLiam Girdwood /** 3914414c70cbSLiam Girdwood * regulator_get_id - get regulator ID 391569279fb9SMark Brown * @rdev: regulator 3916414c70cbSLiam Girdwood */ 3917414c70cbSLiam Girdwood int rdev_get_id(struct regulator_dev *rdev) 3918414c70cbSLiam Girdwood { 3919414c70cbSLiam Girdwood return rdev->desc->id; 3920414c70cbSLiam Girdwood } 3921414c70cbSLiam Girdwood EXPORT_SYMBOL_GPL(rdev_get_id); 3922414c70cbSLiam Girdwood 3923a5766f11SLiam Girdwood struct device *rdev_get_dev(struct regulator_dev *rdev) 3924a5766f11SLiam Girdwood { 3925a5766f11SLiam Girdwood return &rdev->dev; 3926a5766f11SLiam Girdwood } 3927a5766f11SLiam Girdwood EXPORT_SYMBOL_GPL(rdev_get_dev); 3928a5766f11SLiam Girdwood 3929a5766f11SLiam Girdwood void *regulator_get_init_drvdata(struct regulator_init_data *reg_init_data) 3930a5766f11SLiam Girdwood { 3931a5766f11SLiam Girdwood return reg_init_data->driver_data; 3932a5766f11SLiam Girdwood } 3933a5766f11SLiam Girdwood EXPORT_SYMBOL_GPL(regulator_get_init_drvdata); 3934a5766f11SLiam Girdwood 3935ba55a974SMark Brown #ifdef CONFIG_DEBUG_FS 3936ba55a974SMark Brown static ssize_t supply_map_read_file(struct file *file, char __user *user_buf, 3937ba55a974SMark Brown size_t count, loff_t *ppos) 3938ba55a974SMark Brown { 3939ba55a974SMark Brown char *buf = kmalloc(PAGE_SIZE, GFP_KERNEL); 3940ba55a974SMark Brown ssize_t len, ret = 0; 3941ba55a974SMark Brown struct regulator_map *map; 3942ba55a974SMark Brown 3943ba55a974SMark Brown if (!buf) 3944ba55a974SMark Brown return -ENOMEM; 3945ba55a974SMark Brown 3946ba55a974SMark Brown list_for_each_entry(map, ®ulator_map_list, list) { 3947ba55a974SMark Brown len = snprintf(buf + ret, PAGE_SIZE - ret, 3948ba55a974SMark Brown "%s -> %s.%s\n", 3949ba55a974SMark Brown rdev_get_name(map->regulator), map->dev_name, 3950ba55a974SMark Brown map->supply); 3951ba55a974SMark Brown if (len >= 0) 3952ba55a974SMark Brown ret += len; 3953ba55a974SMark Brown if (ret > PAGE_SIZE) { 3954ba55a974SMark Brown ret = PAGE_SIZE; 3955ba55a974SMark Brown break; 3956ba55a974SMark Brown } 3957ba55a974SMark Brown } 3958ba55a974SMark Brown 3959ba55a974SMark Brown ret = simple_read_from_buffer(user_buf, count, ppos, buf, ret); 3960ba55a974SMark Brown 3961ba55a974SMark Brown kfree(buf); 3962ba55a974SMark Brown 3963ba55a974SMark Brown return ret; 3964ba55a974SMark Brown } 396524751434SStephen Boyd #endif 3966ba55a974SMark Brown 3967ba55a974SMark Brown static const struct file_operations supply_map_fops = { 396824751434SStephen Boyd #ifdef CONFIG_DEBUG_FS 3969ba55a974SMark Brown .read = supply_map_read_file, 3970ba55a974SMark Brown .llseek = default_llseek, 3971ba55a974SMark Brown #endif 397224751434SStephen Boyd }; 3973ba55a974SMark Brown 3974414c70cbSLiam Girdwood static int __init regulator_init(void) 3975414c70cbSLiam Girdwood { 397634abbd68SMark Brown int ret; 397734abbd68SMark Brown 397834abbd68SMark Brown ret = class_register(®ulator_class); 397934abbd68SMark Brown 39801130e5b3SMark Brown debugfs_root = debugfs_create_dir("regulator", NULL); 398124751434SStephen Boyd if (!debugfs_root) 39821130e5b3SMark Brown pr_warn("regulator: Failed to create debugfs directory\n"); 3983ba55a974SMark Brown 3984f4d562c6SMark Brown debugfs_create_file("supply_map", 0444, debugfs_root, NULL, 3985f4d562c6SMark Brown &supply_map_fops); 39861130e5b3SMark Brown 398734abbd68SMark Brown regulator_dummy_init(); 398834abbd68SMark Brown 398934abbd68SMark Brown return ret; 3990414c70cbSLiam Girdwood } 3991414c70cbSLiam Girdwood 3992414c70cbSLiam Girdwood /* init early to allow our consumers to complete system booting */ 3993414c70cbSLiam Girdwood core_initcall(regulator_init); 3994ca725561SMark Brown 3995ca725561SMark Brown static int __init regulator_init_complete(void) 3996ca725561SMark Brown { 3997ca725561SMark Brown struct regulator_dev *rdev; 3998272e2315SGuodong Xu const struct regulator_ops *ops; 3999ca725561SMark Brown struct regulation_constraints *c; 4000ca725561SMark Brown int enabled, ret; 4001ca725561SMark Brown 400286f5fcfcSMark Brown /* 400386f5fcfcSMark Brown * Since DT doesn't provide an idiomatic mechanism for 400486f5fcfcSMark Brown * enabling full constraints and since it's much more natural 400586f5fcfcSMark Brown * with DT to provide them just assume that a DT enabled 400686f5fcfcSMark Brown * system has full constraints. 400786f5fcfcSMark Brown */ 400886f5fcfcSMark Brown if (of_have_populated_dt()) 400986f5fcfcSMark Brown has_full_constraints = true; 401086f5fcfcSMark Brown 4011ca725561SMark Brown mutex_lock(®ulator_list_mutex); 4012ca725561SMark Brown 4013ca725561SMark Brown /* If we have a full configuration then disable any regulators 4014e9535834SMark Brown * we have permission to change the status for and which are 4015e9535834SMark Brown * not in use or always_on. This is effectively the default 4016e9535834SMark Brown * for DT and ACPI as they have full constraints. 4017ca725561SMark Brown */ 4018ca725561SMark Brown list_for_each_entry(rdev, ®ulator_list, list) { 4019ca725561SMark Brown ops = rdev->desc->ops; 4020ca725561SMark Brown c = rdev->constraints; 4021ca725561SMark Brown 402266fda75fSMarkus Pargmann if (c && c->always_on) 4023ca725561SMark Brown continue; 4024ca725561SMark Brown 4025e9535834SMark Brown if (c && !(c->valid_ops_mask & REGULATOR_CHANGE_STATUS)) 4026e9535834SMark Brown continue; 4027e9535834SMark Brown 4028ca725561SMark Brown mutex_lock(&rdev->mutex); 4029ca725561SMark Brown 4030ca725561SMark Brown if (rdev->use_count) 4031ca725561SMark Brown goto unlock; 4032ca725561SMark Brown 4033ca725561SMark Brown /* If we can't read the status assume it's on. */ 4034ca725561SMark Brown if (ops->is_enabled) 4035ca725561SMark Brown enabled = ops->is_enabled(rdev); 4036ca725561SMark Brown else 4037ca725561SMark Brown enabled = 1; 4038ca725561SMark Brown 4039ca725561SMark Brown if (!enabled) 4040ca725561SMark Brown goto unlock; 4041ca725561SMark Brown 404287b28417SMark Brown if (have_full_constraints()) { 4043ca725561SMark Brown /* We log since this may kill the system if it 4044ca725561SMark Brown * goes wrong. */ 40455da84fd9SJoe Perches rdev_info(rdev, "disabling\n"); 404666fda75fSMarkus Pargmann ret = _regulator_do_disable(rdev); 40470d25d09dSJingoo Han if (ret != 0) 40485da84fd9SJoe Perches rdev_err(rdev, "couldn't disable: %d\n", ret); 4049ca725561SMark Brown } else { 4050ca725561SMark Brown /* The intention is that in future we will 4051ca725561SMark Brown * assume that full constraints are provided 4052ca725561SMark Brown * so warn even if we aren't going to do 4053ca725561SMark Brown * anything here. 4054ca725561SMark Brown */ 40555da84fd9SJoe Perches rdev_warn(rdev, "incomplete constraints, leaving on\n"); 4056ca725561SMark Brown } 4057ca725561SMark Brown 4058ca725561SMark Brown unlock: 4059ca725561SMark Brown mutex_unlock(&rdev->mutex); 4060ca725561SMark Brown } 4061ca725561SMark Brown 4062ca725561SMark Brown mutex_unlock(®ulator_list_mutex); 4063ca725561SMark Brown 4064ca725561SMark Brown return 0; 4065ca725561SMark Brown } 4066fd482a3eSSaravana Kannan late_initcall_sync(regulator_init_complete); 4067