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 */ 6378460ef38SBjorn Andersson static int 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 6438460ef38SBjorn Andersson /* 6448460ef38SBjorn Andersson * first check to see if we can set modes at all, otherwise just 6458460ef38SBjorn Andersson * tell the consumer everything is OK. 6468460ef38SBjorn Andersson */ 647414c70cbSLiam Girdwood err = regulator_check_drms(rdev); 6488460ef38SBjorn Andersson if (err < 0) 6498460ef38SBjorn Andersson return 0; 6508460ef38SBjorn Andersson 6518f4490e0SBjorn Andersson if (!rdev->desc->ops->get_optimum_mode && 6528f4490e0SBjorn Andersson !rdev->desc->ops->set_load) 6538460ef38SBjorn Andersson return 0; 6548460ef38SBjorn Andersson 6558f4490e0SBjorn Andersson if (!rdev->desc->ops->set_mode && 6568f4490e0SBjorn Andersson !rdev->desc->ops->set_load) 6578460ef38SBjorn Andersson return -EINVAL; 658414c70cbSLiam Girdwood 659414c70cbSLiam Girdwood /* get output voltage */ 6601bf5a1f8SMark Brown output_uV = _regulator_get_voltage(rdev); 6618460ef38SBjorn Andersson if (output_uV <= 0) { 6628460ef38SBjorn Andersson rdev_err(rdev, "invalid output voltage found\n"); 6638460ef38SBjorn Andersson return -EINVAL; 6648460ef38SBjorn Andersson } 665414c70cbSLiam Girdwood 666414c70cbSLiam Girdwood /* get input voltage */ 6671bf5a1f8SMark Brown input_uV = 0; 6681bf5a1f8SMark Brown if (rdev->supply) 6693f24f5adSAxel Lin input_uV = regulator_get_voltage(rdev->supply); 6701bf5a1f8SMark Brown if (input_uV <= 0) 671414c70cbSLiam Girdwood input_uV = rdev->constraints->input_uV; 6728460ef38SBjorn Andersson if (input_uV <= 0) { 6738460ef38SBjorn Andersson rdev_err(rdev, "invalid input voltage found\n"); 6748460ef38SBjorn Andersson return -EINVAL; 6758460ef38SBjorn Andersson } 676414c70cbSLiam Girdwood 677414c70cbSLiam Girdwood /* calc total requested load */ 678414c70cbSLiam Girdwood list_for_each_entry(sibling, &rdev->consumer_list, list) 679414c70cbSLiam Girdwood current_uA += sibling->uA_load; 680414c70cbSLiam Girdwood 68122a10bcaSStephen Boyd current_uA += rdev->constraints->system_load; 68222a10bcaSStephen Boyd 6838f4490e0SBjorn Andersson if (rdev->desc->ops->set_load) { 6848f4490e0SBjorn Andersson /* set the optimum mode for our new total regulator load */ 6858f4490e0SBjorn Andersson err = rdev->desc->ops->set_load(rdev, current_uA); 6868f4490e0SBjorn Andersson if (err < 0) 6878f4490e0SBjorn Andersson rdev_err(rdev, "failed to set load %d\n", current_uA); 6888f4490e0SBjorn Andersson } else { 689414c70cbSLiam Girdwood /* now get the optimum mode for our new total regulator load */ 690414c70cbSLiam Girdwood mode = rdev->desc->ops->get_optimum_mode(rdev, input_uV, 691414c70cbSLiam Girdwood output_uV, current_uA); 692414c70cbSLiam Girdwood 693414c70cbSLiam Girdwood /* check the new mode is allowed */ 6942c608234SMark Brown err = regulator_mode_constrain(rdev, &mode); 6958460ef38SBjorn Andersson if (err < 0) { 6968460ef38SBjorn Andersson rdev_err(rdev, "failed to get optimum mode @ %d uA %d -> %d uV\n", 6978460ef38SBjorn Andersson current_uA, input_uV, output_uV); 6988460ef38SBjorn Andersson return err; 6998460ef38SBjorn Andersson } 7008460ef38SBjorn Andersson 7018460ef38SBjorn Andersson err = rdev->desc->ops->set_mode(rdev, mode); 7028460ef38SBjorn Andersson if (err < 0) 7038460ef38SBjorn Andersson rdev_err(rdev, "failed to set optimum mode %x\n", mode); 7048f4490e0SBjorn Andersson } 7058460ef38SBjorn Andersson 7068460ef38SBjorn Andersson return err; 707414c70cbSLiam Girdwood } 708414c70cbSLiam Girdwood 709414c70cbSLiam Girdwood static int suspend_set_state(struct regulator_dev *rdev, 710414c70cbSLiam Girdwood struct regulator_state *rstate) 711414c70cbSLiam Girdwood { 712414c70cbSLiam Girdwood int ret = 0; 713638f85c5SMark Brown 714638f85c5SMark Brown /* If we have no suspend mode configration don't set anything; 7158ac0e95dSAxel Lin * only warn if the driver implements set_suspend_voltage or 7168ac0e95dSAxel Lin * set_suspend_mode callback. 717638f85c5SMark Brown */ 718638f85c5SMark Brown if (!rstate->enabled && !rstate->disabled) { 7198ac0e95dSAxel Lin if (rdev->desc->ops->set_suspend_voltage || 7208ac0e95dSAxel Lin rdev->desc->ops->set_suspend_mode) 7215da84fd9SJoe Perches rdev_warn(rdev, "No configuration\n"); 722638f85c5SMark Brown return 0; 723638f85c5SMark Brown } 724638f85c5SMark Brown 725638f85c5SMark Brown if (rstate->enabled && rstate->disabled) { 7265da84fd9SJoe Perches rdev_err(rdev, "invalid configuration\n"); 727638f85c5SMark Brown return -EINVAL; 728638f85c5SMark Brown } 729638f85c5SMark Brown 7308ac0e95dSAxel Lin if (rstate->enabled && rdev->desc->ops->set_suspend_enable) 731414c70cbSLiam Girdwood ret = rdev->desc->ops->set_suspend_enable(rdev); 7328ac0e95dSAxel Lin else if (rstate->disabled && rdev->desc->ops->set_suspend_disable) 733414c70cbSLiam Girdwood ret = rdev->desc->ops->set_suspend_disable(rdev); 7348ac0e95dSAxel Lin else /* OK if set_suspend_enable or set_suspend_disable is NULL */ 7358ac0e95dSAxel Lin ret = 0; 7368ac0e95dSAxel Lin 737414c70cbSLiam Girdwood if (ret < 0) { 7385da84fd9SJoe Perches rdev_err(rdev, "failed to enabled/disable\n"); 739414c70cbSLiam Girdwood return ret; 740414c70cbSLiam Girdwood } 741414c70cbSLiam Girdwood 742414c70cbSLiam Girdwood if (rdev->desc->ops->set_suspend_voltage && rstate->uV > 0) { 743414c70cbSLiam Girdwood ret = rdev->desc->ops->set_suspend_voltage(rdev, rstate->uV); 744414c70cbSLiam Girdwood if (ret < 0) { 7455da84fd9SJoe Perches rdev_err(rdev, "failed to set voltage\n"); 746414c70cbSLiam Girdwood return ret; 747414c70cbSLiam Girdwood } 748414c70cbSLiam Girdwood } 749414c70cbSLiam Girdwood 750414c70cbSLiam Girdwood if (rdev->desc->ops->set_suspend_mode && rstate->mode > 0) { 751414c70cbSLiam Girdwood ret = rdev->desc->ops->set_suspend_mode(rdev, rstate->mode); 752414c70cbSLiam Girdwood if (ret < 0) { 7535da84fd9SJoe Perches rdev_err(rdev, "failed to set mode\n"); 754414c70cbSLiam Girdwood return ret; 755414c70cbSLiam Girdwood } 756414c70cbSLiam Girdwood } 757414c70cbSLiam Girdwood return ret; 758414c70cbSLiam Girdwood } 759414c70cbSLiam Girdwood 760414c70cbSLiam Girdwood /* locks held by caller */ 761414c70cbSLiam Girdwood static int suspend_prepare(struct regulator_dev *rdev, suspend_state_t state) 762414c70cbSLiam Girdwood { 763414c70cbSLiam Girdwood if (!rdev->constraints) 764414c70cbSLiam Girdwood return -EINVAL; 765414c70cbSLiam Girdwood 766414c70cbSLiam Girdwood switch (state) { 767414c70cbSLiam Girdwood case PM_SUSPEND_STANDBY: 768414c70cbSLiam Girdwood return suspend_set_state(rdev, 769414c70cbSLiam Girdwood &rdev->constraints->state_standby); 770414c70cbSLiam Girdwood case PM_SUSPEND_MEM: 771414c70cbSLiam Girdwood return suspend_set_state(rdev, 772414c70cbSLiam Girdwood &rdev->constraints->state_mem); 773414c70cbSLiam Girdwood case PM_SUSPEND_MAX: 774414c70cbSLiam Girdwood return suspend_set_state(rdev, 775414c70cbSLiam Girdwood &rdev->constraints->state_disk); 776414c70cbSLiam Girdwood default: 777414c70cbSLiam Girdwood return -EINVAL; 778414c70cbSLiam Girdwood } 779414c70cbSLiam Girdwood } 780414c70cbSLiam Girdwood 781414c70cbSLiam Girdwood static void print_constraints(struct regulator_dev *rdev) 782414c70cbSLiam Girdwood { 783414c70cbSLiam Girdwood struct regulation_constraints *constraints = rdev->constraints; 784973e9a27SMark Brown char buf[80] = ""; 7858f031b48SMark Brown int count = 0; 7868f031b48SMark Brown int ret; 787414c70cbSLiam Girdwood 7888f031b48SMark Brown if (constraints->min_uV && constraints->max_uV) { 789414c70cbSLiam Girdwood if (constraints->min_uV == constraints->max_uV) 7908f031b48SMark Brown count += sprintf(buf + count, "%d mV ", 791414c70cbSLiam Girdwood constraints->min_uV / 1000); 792414c70cbSLiam Girdwood else 7938f031b48SMark Brown count += sprintf(buf + count, "%d <--> %d mV ", 794414c70cbSLiam Girdwood constraints->min_uV / 1000, 795414c70cbSLiam Girdwood constraints->max_uV / 1000); 7968f031b48SMark Brown } 7978f031b48SMark Brown 7988f031b48SMark Brown if (!constraints->min_uV || 7998f031b48SMark Brown constraints->min_uV != constraints->max_uV) { 8008f031b48SMark Brown ret = _regulator_get_voltage(rdev); 8018f031b48SMark Brown if (ret > 0) 8028f031b48SMark Brown count += sprintf(buf + count, "at %d mV ", ret / 1000); 8038f031b48SMark Brown } 8048f031b48SMark Brown 805bf5892a8SMark Brown if (constraints->uV_offset) 806bf5892a8SMark Brown count += sprintf(buf, "%dmV offset ", 807bf5892a8SMark Brown constraints->uV_offset / 1000); 808bf5892a8SMark Brown 8098f031b48SMark Brown if (constraints->min_uA && constraints->max_uA) { 810414c70cbSLiam Girdwood if (constraints->min_uA == constraints->max_uA) 8118f031b48SMark Brown count += sprintf(buf + count, "%d mA ", 812414c70cbSLiam Girdwood constraints->min_uA / 1000); 813414c70cbSLiam Girdwood else 8148f031b48SMark Brown count += sprintf(buf + count, "%d <--> %d mA ", 815414c70cbSLiam Girdwood constraints->min_uA / 1000, 816414c70cbSLiam Girdwood constraints->max_uA / 1000); 817414c70cbSLiam Girdwood } 8188f031b48SMark Brown 8198f031b48SMark Brown if (!constraints->min_uA || 8208f031b48SMark Brown constraints->min_uA != constraints->max_uA) { 8218f031b48SMark Brown ret = _regulator_get_current_limit(rdev); 8228f031b48SMark Brown if (ret > 0) 823e4a6376bSCyril Chemparathy count += sprintf(buf + count, "at %d mA ", ret / 1000); 8248f031b48SMark Brown } 8258f031b48SMark Brown 826414c70cbSLiam Girdwood if (constraints->valid_modes_mask & REGULATOR_MODE_FAST) 827414c70cbSLiam Girdwood count += sprintf(buf + count, "fast "); 828414c70cbSLiam Girdwood if (constraints->valid_modes_mask & REGULATOR_MODE_NORMAL) 829414c70cbSLiam Girdwood count += sprintf(buf + count, "normal "); 830414c70cbSLiam Girdwood if (constraints->valid_modes_mask & REGULATOR_MODE_IDLE) 831414c70cbSLiam Girdwood count += sprintf(buf + count, "idle "); 832414c70cbSLiam Girdwood if (constraints->valid_modes_mask & REGULATOR_MODE_STANDBY) 833414c70cbSLiam Girdwood count += sprintf(buf + count, "standby"); 834414c70cbSLiam Girdwood 835215b8b05SUwe Kleine-König if (!count) 836215b8b05SUwe Kleine-König sprintf(buf, "no parameters"); 837215b8b05SUwe Kleine-König 838194dbaefSMark Brown rdev_dbg(rdev, "%s\n", buf); 8394a682922SMark Brown 8404a682922SMark Brown if ((constraints->min_uV != constraints->max_uV) && 8414a682922SMark Brown !(constraints->valid_ops_mask & REGULATOR_CHANGE_VOLTAGE)) 8424a682922SMark Brown rdev_warn(rdev, 8434a682922SMark Brown "Voltage range but no REGULATOR_CHANGE_VOLTAGE\n"); 844414c70cbSLiam Girdwood } 845414c70cbSLiam Girdwood 846e79055d6SMark Brown static int machine_constraints_voltage(struct regulator_dev *rdev, 8471083c393SMark Brown struct regulation_constraints *constraints) 848e79055d6SMark Brown { 849272e2315SGuodong Xu const struct regulator_ops *ops = rdev->desc->ops; 850af5866c9SMark Brown int ret; 851af5866c9SMark Brown 852af5866c9SMark Brown /* do we need to apply the constraint voltage */ 853af5866c9SMark Brown if (rdev->constraints->apply_uV && 85475790251SMark Brown rdev->constraints->min_uV == rdev->constraints->max_uV) { 855064d5cd1SAlban Bedel int current_uV = _regulator_get_voltage(rdev); 856064d5cd1SAlban Bedel if (current_uV < 0) { 85769d58839SNishanth Menon rdev_err(rdev, 85869d58839SNishanth Menon "failed to get the current voltage(%d)\n", 85969d58839SNishanth Menon current_uV); 860064d5cd1SAlban Bedel return current_uV; 861064d5cd1SAlban Bedel } 862064d5cd1SAlban Bedel if (current_uV < rdev->constraints->min_uV || 863064d5cd1SAlban Bedel current_uV > rdev->constraints->max_uV) { 864064d5cd1SAlban Bedel ret = _regulator_do_set_voltage( 865064d5cd1SAlban Bedel rdev, rdev->constraints->min_uV, 86675790251SMark Brown rdev->constraints->max_uV); 867af5866c9SMark Brown if (ret < 0) { 868064d5cd1SAlban Bedel rdev_err(rdev, 86969d58839SNishanth Menon "failed to apply %duV constraint(%d)\n", 87069d58839SNishanth Menon rdev->constraints->min_uV, ret); 871af5866c9SMark Brown return ret; 872af5866c9SMark Brown } 873af5866c9SMark Brown } 874064d5cd1SAlban Bedel } 875e79055d6SMark Brown 876e79055d6SMark Brown /* constrain machine-level voltage specs to fit 877e79055d6SMark Brown * the actual range supported by this regulator. 878e79055d6SMark Brown */ 879e79055d6SMark Brown if (ops->list_voltage && rdev->desc->n_voltages) { 880e79055d6SMark Brown int count = rdev->desc->n_voltages; 881e79055d6SMark Brown int i; 882e79055d6SMark Brown int min_uV = INT_MAX; 883e79055d6SMark Brown int max_uV = INT_MIN; 884e79055d6SMark Brown int cmin = constraints->min_uV; 885e79055d6SMark Brown int cmax = constraints->max_uV; 886e79055d6SMark Brown 887e79055d6SMark Brown /* it's safe to autoconfigure fixed-voltage supplies 888e79055d6SMark Brown and the constraints are used by list_voltage. */ 889e79055d6SMark Brown if (count == 1 && !cmin) { 890e79055d6SMark Brown cmin = 1; 891e79055d6SMark Brown cmax = INT_MAX; 892e79055d6SMark Brown constraints->min_uV = cmin; 893e79055d6SMark Brown constraints->max_uV = cmax; 894e79055d6SMark Brown } 895e79055d6SMark Brown 896e79055d6SMark Brown /* voltage constraints are optional */ 897e79055d6SMark Brown if ((cmin == 0) && (cmax == 0)) 898e79055d6SMark Brown return 0; 899e79055d6SMark Brown 900e79055d6SMark Brown /* else require explicit machine-level constraints */ 901e79055d6SMark Brown if (cmin <= 0 || cmax <= 0 || cmax < cmin) { 9025da84fd9SJoe Perches rdev_err(rdev, "invalid voltage constraints\n"); 903e79055d6SMark Brown return -EINVAL; 904e79055d6SMark Brown } 905e79055d6SMark Brown 906e79055d6SMark Brown /* initial: [cmin..cmax] valid, [min_uV..max_uV] not */ 907e79055d6SMark Brown for (i = 0; i < count; i++) { 908e79055d6SMark Brown int value; 909e79055d6SMark Brown 910e79055d6SMark Brown value = ops->list_voltage(rdev, i); 911e79055d6SMark Brown if (value <= 0) 912e79055d6SMark Brown continue; 913e79055d6SMark Brown 914e79055d6SMark Brown /* maybe adjust [min_uV..max_uV] */ 915e79055d6SMark Brown if (value >= cmin && value < min_uV) 916e79055d6SMark Brown min_uV = value; 917e79055d6SMark Brown if (value <= cmax && value > max_uV) 918e79055d6SMark Brown max_uV = value; 919e79055d6SMark Brown } 920e79055d6SMark Brown 921e79055d6SMark Brown /* final: [min_uV..max_uV] valid iff constraints valid */ 922e79055d6SMark Brown if (max_uV < min_uV) { 923fff15befSMark Brown rdev_err(rdev, 924fff15befSMark Brown "unsupportable voltage constraints %u-%uuV\n", 925fff15befSMark Brown min_uV, max_uV); 926e79055d6SMark Brown return -EINVAL; 927e79055d6SMark Brown } 928e79055d6SMark Brown 929e79055d6SMark Brown /* use regulator's subset of machine constraints */ 930e79055d6SMark Brown if (constraints->min_uV < min_uV) { 9315da84fd9SJoe Perches rdev_dbg(rdev, "override min_uV, %d -> %d\n", 9325da84fd9SJoe Perches constraints->min_uV, min_uV); 933e79055d6SMark Brown constraints->min_uV = min_uV; 934e79055d6SMark Brown } 935e79055d6SMark Brown if (constraints->max_uV > max_uV) { 9365da84fd9SJoe Perches rdev_dbg(rdev, "override max_uV, %d -> %d\n", 9375da84fd9SJoe Perches constraints->max_uV, max_uV); 938e79055d6SMark Brown constraints->max_uV = max_uV; 939e79055d6SMark Brown } 940e79055d6SMark Brown } 941e79055d6SMark Brown 942e79055d6SMark Brown return 0; 943e79055d6SMark Brown } 944e79055d6SMark Brown 945f8c1700dSLaxman Dewangan static int machine_constraints_current(struct regulator_dev *rdev, 946f8c1700dSLaxman Dewangan struct regulation_constraints *constraints) 947f8c1700dSLaxman Dewangan { 948272e2315SGuodong Xu const struct regulator_ops *ops = rdev->desc->ops; 949f8c1700dSLaxman Dewangan int ret; 950f8c1700dSLaxman Dewangan 951f8c1700dSLaxman Dewangan if (!constraints->min_uA && !constraints->max_uA) 952f8c1700dSLaxman Dewangan return 0; 953f8c1700dSLaxman Dewangan 954f8c1700dSLaxman Dewangan if (constraints->min_uA > constraints->max_uA) { 955f8c1700dSLaxman Dewangan rdev_err(rdev, "Invalid current constraints\n"); 956f8c1700dSLaxman Dewangan return -EINVAL; 957f8c1700dSLaxman Dewangan } 958f8c1700dSLaxman Dewangan 959f8c1700dSLaxman Dewangan if (!ops->set_current_limit || !ops->get_current_limit) { 960f8c1700dSLaxman Dewangan rdev_warn(rdev, "Operation of current configuration missing\n"); 961f8c1700dSLaxman Dewangan return 0; 962f8c1700dSLaxman Dewangan } 963f8c1700dSLaxman Dewangan 964f8c1700dSLaxman Dewangan /* Set regulator current in constraints range */ 965f8c1700dSLaxman Dewangan ret = ops->set_current_limit(rdev, constraints->min_uA, 966f8c1700dSLaxman Dewangan constraints->max_uA); 967f8c1700dSLaxman Dewangan if (ret < 0) { 968f8c1700dSLaxman Dewangan rdev_err(rdev, "Failed to set current constraint, %d\n", ret); 969f8c1700dSLaxman Dewangan return ret; 970f8c1700dSLaxman Dewangan } 971f8c1700dSLaxman Dewangan 972f8c1700dSLaxman Dewangan return 0; 973f8c1700dSLaxman Dewangan } 974f8c1700dSLaxman Dewangan 97530c21971SMarkus Pargmann static int _regulator_do_enable(struct regulator_dev *rdev); 97630c21971SMarkus Pargmann 977a5766f11SLiam Girdwood /** 978a5766f11SLiam Girdwood * set_machine_constraints - sets regulator constraints 97969279fb9SMark Brown * @rdev: regulator source 980c8e7e464SMark Brown * @constraints: constraints to apply 981a5766f11SLiam Girdwood * 982a5766f11SLiam Girdwood * Allows platform initialisation code to define and constrain 983a5766f11SLiam Girdwood * regulator circuits e.g. valid voltage/current ranges, etc. NOTE: 984a5766f11SLiam Girdwood * Constraints *must* be set by platform code in order for some 985a5766f11SLiam Girdwood * regulator operations to proceed i.e. set_voltage, set_current_limit, 986a5766f11SLiam Girdwood * set_mode. 987a5766f11SLiam Girdwood */ 988a5766f11SLiam Girdwood static int set_machine_constraints(struct regulator_dev *rdev, 989f8c12fe3SMark Brown const struct regulation_constraints *constraints) 990a5766f11SLiam Girdwood { 991a5766f11SLiam Girdwood int ret = 0; 992272e2315SGuodong Xu const struct regulator_ops *ops = rdev->desc->ops; 993e06f5b4fSMark Brown 9949a8f5e07SMark Brown if (constraints) 995f8c12fe3SMark Brown rdev->constraints = kmemdup(constraints, sizeof(*constraints), 996f8c12fe3SMark Brown GFP_KERNEL); 9979a8f5e07SMark Brown else 9989a8f5e07SMark Brown rdev->constraints = kzalloc(sizeof(*constraints), 9999a8f5e07SMark Brown GFP_KERNEL); 1000f8c12fe3SMark Brown if (!rdev->constraints) 1001f8c12fe3SMark Brown return -ENOMEM; 1002af5866c9SMark Brown 1003f8c12fe3SMark Brown ret = machine_constraints_voltage(rdev, rdev->constraints); 1004e79055d6SMark Brown if (ret != 0) 10053e2b9abdSMark Brown goto out; 10063e2b9abdSMark Brown 1007f8c1700dSLaxman Dewangan ret = machine_constraints_current(rdev, rdev->constraints); 1008f8c1700dSLaxman Dewangan if (ret != 0) 1009f8c1700dSLaxman Dewangan goto out; 1010f8c1700dSLaxman Dewangan 101136e4f839SStephen Boyd if (rdev->constraints->ilim_uA && ops->set_input_current_limit) { 101236e4f839SStephen Boyd ret = ops->set_input_current_limit(rdev, 101336e4f839SStephen Boyd rdev->constraints->ilim_uA); 101436e4f839SStephen Boyd if (ret < 0) { 101536e4f839SStephen Boyd rdev_err(rdev, "failed to set input limit\n"); 101636e4f839SStephen Boyd goto out; 101736e4f839SStephen Boyd } 101836e4f839SStephen Boyd } 101936e4f839SStephen Boyd 1020a5766f11SLiam Girdwood /* do we need to setup our suspend state */ 10219a8f5e07SMark Brown if (rdev->constraints->initial_state) { 1022f8c12fe3SMark Brown ret = suspend_prepare(rdev, rdev->constraints->initial_state); 1023e06f5b4fSMark Brown if (ret < 0) { 10245da84fd9SJoe Perches rdev_err(rdev, "failed to set suspend state\n"); 1025e06f5b4fSMark Brown goto out; 1026e06f5b4fSMark Brown } 1027e06f5b4fSMark Brown } 1028a5766f11SLiam Girdwood 10299a8f5e07SMark Brown if (rdev->constraints->initial_mode) { 1030a308466cSMark Brown if (!ops->set_mode) { 10315da84fd9SJoe Perches rdev_err(rdev, "no set_mode operation\n"); 1032a308466cSMark Brown ret = -EINVAL; 1033a308466cSMark Brown goto out; 1034a308466cSMark Brown } 1035a308466cSMark Brown 1036f8c12fe3SMark Brown ret = ops->set_mode(rdev, rdev->constraints->initial_mode); 1037a308466cSMark Brown if (ret < 0) { 10385da84fd9SJoe Perches rdev_err(rdev, "failed to set initial mode: %d\n", ret); 1039a308466cSMark Brown goto out; 1040a308466cSMark Brown } 1041a308466cSMark Brown } 1042a308466cSMark Brown 1043cacf90f2SMark Brown /* If the constraints say the regulator should be on at this point 1044cacf90f2SMark Brown * and we have control then make sure it is enabled. 1045cacf90f2SMark Brown */ 104630c21971SMarkus Pargmann if (rdev->constraints->always_on || rdev->constraints->boot_on) { 104730c21971SMarkus Pargmann ret = _regulator_do_enable(rdev); 104830c21971SMarkus Pargmann if (ret < 0 && ret != -EINVAL) { 10495da84fd9SJoe Perches rdev_err(rdev, "failed to enable\n"); 1050e5fda26cSMark Brown goto out; 1051e5fda26cSMark Brown } 1052e5fda26cSMark Brown } 1053e5fda26cSMark Brown 10541653ccf4SYadwinder Singh Brar if ((rdev->constraints->ramp_delay || rdev->constraints->ramp_disable) 10551653ccf4SYadwinder Singh Brar && ops->set_ramp_delay) { 10566f0b2c69SYadwinder Singh Brar ret = ops->set_ramp_delay(rdev, rdev->constraints->ramp_delay); 10576f0b2c69SYadwinder Singh Brar if (ret < 0) { 10586f0b2c69SYadwinder Singh Brar rdev_err(rdev, "failed to set ramp_delay\n"); 10596f0b2c69SYadwinder Singh Brar goto out; 10606f0b2c69SYadwinder Singh Brar } 10616f0b2c69SYadwinder Singh Brar } 10626f0b2c69SYadwinder Singh Brar 106323c779b9SStephen Boyd if (rdev->constraints->pull_down && ops->set_pull_down) { 106423c779b9SStephen Boyd ret = ops->set_pull_down(rdev); 106523c779b9SStephen Boyd if (ret < 0) { 106623c779b9SStephen Boyd rdev_err(rdev, "failed to set pull down\n"); 106723c779b9SStephen Boyd goto out; 106823c779b9SStephen Boyd } 106923c779b9SStephen Boyd } 107023c779b9SStephen Boyd 107157f66b78SStephen Boyd if (rdev->constraints->soft_start && ops->set_soft_start) { 107257f66b78SStephen Boyd ret = ops->set_soft_start(rdev); 107357f66b78SStephen Boyd if (ret < 0) { 107457f66b78SStephen Boyd rdev_err(rdev, "failed to set soft start\n"); 107557f66b78SStephen Boyd goto out; 107657f66b78SStephen Boyd } 107757f66b78SStephen Boyd } 107857f66b78SStephen Boyd 1079a5766f11SLiam Girdwood print_constraints(rdev); 10801a6958e7SAxel Lin return 0; 1081a5766f11SLiam Girdwood out: 10821a6958e7SAxel Lin kfree(rdev->constraints); 10831a6958e7SAxel Lin rdev->constraints = NULL; 1084a5766f11SLiam Girdwood return ret; 1085a5766f11SLiam Girdwood } 1086a5766f11SLiam Girdwood 1087a5766f11SLiam Girdwood /** 1088a5766f11SLiam Girdwood * set_supply - set regulator supply regulator 108969279fb9SMark Brown * @rdev: regulator name 109069279fb9SMark Brown * @supply_rdev: supply regulator name 1091a5766f11SLiam Girdwood * 1092a5766f11SLiam Girdwood * Called by platform initialisation code to set the supply regulator for this 1093a5766f11SLiam Girdwood * regulator. This ensures that a regulators supply will also be enabled by the 1094a5766f11SLiam Girdwood * core if it's child is enabled. 1095a5766f11SLiam Girdwood */ 1096a5766f11SLiam Girdwood static int set_supply(struct regulator_dev *rdev, 1097a5766f11SLiam Girdwood struct regulator_dev *supply_rdev) 1098a5766f11SLiam Girdwood { 1099a5766f11SLiam Girdwood int err; 1100a5766f11SLiam Girdwood 11013801b86aSMark Brown rdev_info(rdev, "supplied by %s\n", rdev_get_name(supply_rdev)); 11023801b86aSMark Brown 11033801b86aSMark Brown rdev->supply = create_regulator(supply_rdev, &rdev->dev, "SUPPLY"); 110432c78de8SAxel Lin if (rdev->supply == NULL) { 110532c78de8SAxel Lin err = -ENOMEM; 1106a5766f11SLiam Girdwood return err; 1107a5766f11SLiam Girdwood } 110857ad526aSLaxman Dewangan supply_rdev->open_count++; 1109a5766f11SLiam Girdwood 11103801b86aSMark Brown return 0; 11113801b86aSMark Brown } 11123801b86aSMark Brown 1113a5766f11SLiam Girdwood /** 111406c63f93SRandy Dunlap * set_consumer_device_supply - Bind a regulator to a symbolic supply 111569279fb9SMark Brown * @rdev: regulator source 111640f9244fSMark Brown * @consumer_dev_name: dev_name() string for device supply applies to 1117a5766f11SLiam Girdwood * @supply: symbolic name for supply 1118a5766f11SLiam Girdwood * 1119a5766f11SLiam Girdwood * Allows platform initialisation code to map physical regulator 1120a5766f11SLiam Girdwood * sources to symbolic names for supplies for use by devices. Devices 1121a5766f11SLiam Girdwood * should use these symbolic names to request regulators, avoiding the 1122a5766f11SLiam Girdwood * need to provide board-specific regulator names as platform data. 1123a5766f11SLiam Girdwood */ 1124a5766f11SLiam Girdwood static int set_consumer_device_supply(struct regulator_dev *rdev, 1125737f360dSMark Brown const char *consumer_dev_name, 112640f9244fSMark Brown const char *supply) 1127a5766f11SLiam Girdwood { 1128a5766f11SLiam Girdwood struct regulator_map *node; 11299ed2099eSMark Brown int has_dev; 1130a5766f11SLiam Girdwood 1131a5766f11SLiam Girdwood if (supply == NULL) 1132a5766f11SLiam Girdwood return -EINVAL; 1133a5766f11SLiam Girdwood 11349ed2099eSMark Brown if (consumer_dev_name != NULL) 11359ed2099eSMark Brown has_dev = 1; 11369ed2099eSMark Brown else 11379ed2099eSMark Brown has_dev = 0; 11389ed2099eSMark Brown 11396001e13cSDavid Brownell list_for_each_entry(node, ®ulator_map_list, list) { 114023b5cc2aSJani Nikula if (node->dev_name && consumer_dev_name) { 114123b5cc2aSJani Nikula if (strcmp(node->dev_name, consumer_dev_name) != 0) 11426001e13cSDavid Brownell continue; 114323b5cc2aSJani Nikula } else if (node->dev_name || consumer_dev_name) { 114423b5cc2aSJani Nikula continue; 114523b5cc2aSJani Nikula } 114623b5cc2aSJani Nikula 11476001e13cSDavid Brownell if (strcmp(node->supply, supply) != 0) 11486001e13cSDavid Brownell continue; 11496001e13cSDavid Brownell 1150737f360dSMark Brown pr_debug("%s: %s/%s is '%s' supply; fail %s/%s\n", 1151737f360dSMark Brown consumer_dev_name, 11526001e13cSDavid Brownell dev_name(&node->regulator->dev), 11536001e13cSDavid Brownell node->regulator->desc->name, 11546001e13cSDavid Brownell supply, 11551083c393SMark Brown dev_name(&rdev->dev), rdev_get_name(rdev)); 11566001e13cSDavid Brownell return -EBUSY; 11576001e13cSDavid Brownell } 11586001e13cSDavid Brownell 11599ed2099eSMark Brown node = kzalloc(sizeof(struct regulator_map), GFP_KERNEL); 1160a5766f11SLiam Girdwood if (node == NULL) 1161a5766f11SLiam Girdwood return -ENOMEM; 1162a5766f11SLiam Girdwood 1163a5766f11SLiam Girdwood node->regulator = rdev; 1164a5766f11SLiam Girdwood node->supply = supply; 1165a5766f11SLiam Girdwood 11669ed2099eSMark Brown if (has_dev) { 11679ed2099eSMark Brown node->dev_name = kstrdup(consumer_dev_name, GFP_KERNEL); 116840f9244fSMark Brown if (node->dev_name == NULL) { 116940f9244fSMark Brown kfree(node); 117040f9244fSMark Brown return -ENOMEM; 117140f9244fSMark Brown } 11729ed2099eSMark Brown } 117340f9244fSMark Brown 1174a5766f11SLiam Girdwood list_add(&node->list, ®ulator_map_list); 1175a5766f11SLiam Girdwood return 0; 1176a5766f11SLiam Girdwood } 1177a5766f11SLiam Girdwood 11780f1d747bSMike Rapoport static void unset_regulator_supplies(struct regulator_dev *rdev) 11790f1d747bSMike Rapoport { 11800f1d747bSMike Rapoport struct regulator_map *node, *n; 11810f1d747bSMike Rapoport 11820f1d747bSMike Rapoport list_for_each_entry_safe(node, n, ®ulator_map_list, list) { 11830f1d747bSMike Rapoport if (rdev == node->regulator) { 11840f1d747bSMike Rapoport list_del(&node->list); 118540f9244fSMark Brown kfree(node->dev_name); 11860f1d747bSMike Rapoport kfree(node); 11870f1d747bSMike Rapoport } 11880f1d747bSMike Rapoport } 11890f1d747bSMike Rapoport } 11900f1d747bSMike Rapoport 1191f5726ae3SMark Brown #define REG_STR_SIZE 64 1192414c70cbSLiam Girdwood 1193414c70cbSLiam Girdwood static struct regulator *create_regulator(struct regulator_dev *rdev, 1194414c70cbSLiam Girdwood struct device *dev, 1195414c70cbSLiam Girdwood const char *supply_name) 1196414c70cbSLiam Girdwood { 1197414c70cbSLiam Girdwood struct regulator *regulator; 1198414c70cbSLiam Girdwood char buf[REG_STR_SIZE]; 1199414c70cbSLiam Girdwood int err, size; 1200414c70cbSLiam Girdwood 1201414c70cbSLiam Girdwood regulator = kzalloc(sizeof(*regulator), GFP_KERNEL); 1202414c70cbSLiam Girdwood if (regulator == NULL) 1203414c70cbSLiam Girdwood return NULL; 1204414c70cbSLiam Girdwood 1205414c70cbSLiam Girdwood mutex_lock(&rdev->mutex); 1206414c70cbSLiam Girdwood regulator->rdev = rdev; 1207414c70cbSLiam Girdwood list_add(®ulator->list, &rdev->consumer_list); 1208414c70cbSLiam Girdwood 1209414c70cbSLiam Girdwood if (dev) { 1210e2c98eafSShawn Guo regulator->dev = dev; 1211e2c98eafSShawn Guo 1212222cc7b1SMark Brown /* Add a link to the device sysfs entry */ 1213414c70cbSLiam Girdwood size = scnprintf(buf, REG_STR_SIZE, "%s-%s", 1214414c70cbSLiam Girdwood dev->kobj.name, supply_name); 1215414c70cbSLiam Girdwood if (size >= REG_STR_SIZE) 1216222cc7b1SMark Brown goto overflow_err; 1217414c70cbSLiam Girdwood 1218414c70cbSLiam Girdwood regulator->supply_name = kstrdup(buf, GFP_KERNEL); 1219414c70cbSLiam Girdwood if (regulator->supply_name == NULL) 1220222cc7b1SMark Brown goto overflow_err; 1221414c70cbSLiam Girdwood 1222414c70cbSLiam Girdwood err = sysfs_create_link(&rdev->dev.kobj, &dev->kobj, 1223414c70cbSLiam Girdwood buf); 1224414c70cbSLiam Girdwood if (err) { 12255da84fd9SJoe Perches rdev_warn(rdev, "could not add device link %s err %d\n", 12261d7372e1SDaniel Walker dev->kobj.name, err); 1227222cc7b1SMark Brown /* non-fatal */ 1228414c70cbSLiam Girdwood } 12295de70519SMark Brown } else { 12305de70519SMark Brown regulator->supply_name = kstrdup(supply_name, GFP_KERNEL); 12315de70519SMark Brown if (regulator->supply_name == NULL) 1232222cc7b1SMark Brown goto overflow_err; 1233414c70cbSLiam Girdwood } 12345de70519SMark Brown 12355de70519SMark Brown regulator->debugfs = debugfs_create_dir(regulator->supply_name, 12365de70519SMark Brown rdev->debugfs); 123724751434SStephen Boyd if (!regulator->debugfs) { 12385de70519SMark Brown rdev_warn(rdev, "Failed to create debugfs directory\n"); 12395de70519SMark Brown } else { 12405de70519SMark Brown debugfs_create_u32("uA_load", 0444, regulator->debugfs, 12415de70519SMark Brown ®ulator->uA_load); 12425de70519SMark Brown debugfs_create_u32("min_uV", 0444, regulator->debugfs, 12435de70519SMark Brown ®ulator->min_uV); 12445de70519SMark Brown debugfs_create_u32("max_uV", 0444, regulator->debugfs, 12455de70519SMark Brown ®ulator->max_uV); 12465de70519SMark Brown } 12475de70519SMark Brown 12486492bc1bSMark Brown /* 12496492bc1bSMark Brown * Check now if the regulator is an always on regulator - if 12506492bc1bSMark Brown * it is then we don't need to do nearly so much work for 12516492bc1bSMark Brown * enable/disable calls. 12526492bc1bSMark Brown */ 12536492bc1bSMark Brown if (!_regulator_can_change_status(rdev) && 12546492bc1bSMark Brown _regulator_is_enabled(rdev)) 12556492bc1bSMark Brown regulator->always_on = true; 12566492bc1bSMark Brown 1257414c70cbSLiam Girdwood mutex_unlock(&rdev->mutex); 1258414c70cbSLiam Girdwood return regulator; 1259414c70cbSLiam Girdwood overflow_err: 1260414c70cbSLiam Girdwood list_del(®ulator->list); 1261414c70cbSLiam Girdwood kfree(regulator); 1262414c70cbSLiam Girdwood mutex_unlock(&rdev->mutex); 1263414c70cbSLiam Girdwood return NULL; 1264414c70cbSLiam Girdwood } 1265414c70cbSLiam Girdwood 126631aae2beSMark Brown static int _regulator_get_enable_time(struct regulator_dev *rdev) 126731aae2beSMark Brown { 126800c877c6SLaxman Dewangan if (rdev->constraints && rdev->constraints->enable_time) 126900c877c6SLaxman Dewangan return rdev->constraints->enable_time; 127031aae2beSMark Brown if (!rdev->desc->ops->enable_time) 127179511ed3SMark Brown return rdev->desc->enable_time; 127231aae2beSMark Brown return rdev->desc->ops->enable_time(rdev); 127331aae2beSMark Brown } 127431aae2beSMark Brown 1275a06ccd9cSCharles Keepax static struct regulator_supply_alias *regulator_find_supply_alias( 1276a06ccd9cSCharles Keepax struct device *dev, const char *supply) 1277a06ccd9cSCharles Keepax { 1278a06ccd9cSCharles Keepax struct regulator_supply_alias *map; 1279a06ccd9cSCharles Keepax 1280a06ccd9cSCharles Keepax list_for_each_entry(map, ®ulator_supply_alias_list, list) 1281a06ccd9cSCharles Keepax if (map->src_dev == dev && strcmp(map->src_supply, supply) == 0) 1282a06ccd9cSCharles Keepax return map; 1283a06ccd9cSCharles Keepax 1284a06ccd9cSCharles Keepax return NULL; 1285a06ccd9cSCharles Keepax } 1286a06ccd9cSCharles Keepax 1287a06ccd9cSCharles Keepax static void regulator_supply_alias(struct device **dev, const char **supply) 1288a06ccd9cSCharles Keepax { 1289a06ccd9cSCharles Keepax struct regulator_supply_alias *map; 1290a06ccd9cSCharles Keepax 1291a06ccd9cSCharles Keepax map = regulator_find_supply_alias(*dev, *supply); 1292a06ccd9cSCharles Keepax if (map) { 1293a06ccd9cSCharles Keepax dev_dbg(*dev, "Mapping supply %s to %s,%s\n", 1294a06ccd9cSCharles Keepax *supply, map->alias_supply, 1295a06ccd9cSCharles Keepax dev_name(map->alias_dev)); 1296a06ccd9cSCharles Keepax *dev = map->alias_dev; 1297a06ccd9cSCharles Keepax *supply = map->alias_supply; 1298a06ccd9cSCharles Keepax } 1299a06ccd9cSCharles Keepax } 1300a06ccd9cSCharles Keepax 130169511a45SRajendra Nayak static struct regulator_dev *regulator_dev_lookup(struct device *dev, 13026d191a5fSMark Brown const char *supply, 13036d191a5fSMark Brown int *ret) 130469511a45SRajendra Nayak { 130569511a45SRajendra Nayak struct regulator_dev *r; 130669511a45SRajendra Nayak struct device_node *node; 1307576ca436SMark Brown struct regulator_map *map; 1308576ca436SMark Brown const char *devname = NULL; 130969511a45SRajendra Nayak 1310a06ccd9cSCharles Keepax regulator_supply_alias(&dev, &supply); 1311a06ccd9cSCharles Keepax 131269511a45SRajendra Nayak /* first do a dt based lookup */ 131369511a45SRajendra Nayak if (dev && dev->of_node) { 131469511a45SRajendra Nayak node = of_get_regulator(dev, supply); 13156d191a5fSMark Brown if (node) { 131669511a45SRajendra Nayak list_for_each_entry(r, ®ulator_list, list) 131769511a45SRajendra Nayak if (r->dev.parent && 131869511a45SRajendra Nayak node == r->dev.of_node) 131969511a45SRajendra Nayak return r; 1320317b5684SMark Brown *ret = -EPROBE_DEFER; 1321317b5684SMark Brown return NULL; 13226d191a5fSMark Brown } else { 13236d191a5fSMark Brown /* 13246d191a5fSMark Brown * If we couldn't even get the node then it's 13256d191a5fSMark Brown * not just that the device didn't register 13266d191a5fSMark Brown * yet, there's no node and we'll never 13276d191a5fSMark Brown * succeed. 13286d191a5fSMark Brown */ 13296d191a5fSMark Brown *ret = -ENODEV; 13306d191a5fSMark Brown } 133169511a45SRajendra Nayak } 133269511a45SRajendra Nayak 133369511a45SRajendra Nayak /* if not found, try doing it non-dt way */ 1334576ca436SMark Brown if (dev) 1335576ca436SMark Brown devname = dev_name(dev); 1336576ca436SMark Brown 133769511a45SRajendra Nayak list_for_each_entry(r, ®ulator_list, list) 133869511a45SRajendra Nayak if (strcmp(rdev_get_name(r), supply) == 0) 133969511a45SRajendra Nayak return r; 134069511a45SRajendra Nayak 1341576ca436SMark Brown list_for_each_entry(map, ®ulator_map_list, list) { 1342576ca436SMark Brown /* If the mapping has a device set up it must match */ 1343576ca436SMark Brown if (map->dev_name && 1344576ca436SMark Brown (!devname || strcmp(map->dev_name, devname))) 1345576ca436SMark Brown continue; 1346576ca436SMark Brown 1347576ca436SMark Brown if (strcmp(map->supply, supply) == 0) 1348576ca436SMark Brown return map->regulator; 1349576ca436SMark Brown } 1350576ca436SMark Brown 1351576ca436SMark Brown 135269511a45SRajendra Nayak return NULL; 135369511a45SRajendra Nayak } 135469511a45SRajendra Nayak 13556261b06dSBjorn Andersson static int regulator_resolve_supply(struct regulator_dev *rdev) 13566261b06dSBjorn Andersson { 13576261b06dSBjorn Andersson struct regulator_dev *r; 13586261b06dSBjorn Andersson struct device *dev = rdev->dev.parent; 13596261b06dSBjorn Andersson int ret; 13606261b06dSBjorn Andersson 13616261b06dSBjorn Andersson /* No supply to resovle? */ 13626261b06dSBjorn Andersson if (!rdev->supply_name) 13636261b06dSBjorn Andersson return 0; 13646261b06dSBjorn Andersson 13656261b06dSBjorn Andersson /* Supply already resolved? */ 13666261b06dSBjorn Andersson if (rdev->supply) 13676261b06dSBjorn Andersson return 0; 13686261b06dSBjorn Andersson 13696261b06dSBjorn Andersson r = regulator_dev_lookup(dev, rdev->supply_name, &ret); 13706261b06dSBjorn Andersson if (ret == -ENODEV) { 13716261b06dSBjorn Andersson /* 13726261b06dSBjorn Andersson * No supply was specified for this regulator and 13736261b06dSBjorn Andersson * there will never be one. 13746261b06dSBjorn Andersson */ 13756261b06dSBjorn Andersson return 0; 13766261b06dSBjorn Andersson } 13776261b06dSBjorn Andersson 13786261b06dSBjorn Andersson if (!r) { 13796261b06dSBjorn Andersson dev_err(dev, "Failed to resolve %s-supply for %s\n", 13806261b06dSBjorn Andersson rdev->supply_name, rdev->desc->name); 13816261b06dSBjorn Andersson return -EPROBE_DEFER; 13826261b06dSBjorn Andersson } 13836261b06dSBjorn Andersson 13846261b06dSBjorn Andersson /* Recursively resolve the supply of the supply */ 13856261b06dSBjorn Andersson ret = regulator_resolve_supply(r); 13866261b06dSBjorn Andersson if (ret < 0) 13876261b06dSBjorn Andersson return ret; 13886261b06dSBjorn Andersson 13896261b06dSBjorn Andersson ret = set_supply(rdev, r); 13906261b06dSBjorn Andersson if (ret < 0) 13916261b06dSBjorn Andersson return ret; 13926261b06dSBjorn Andersson 13936261b06dSBjorn Andersson /* Cascade always-on state to supply */ 13946261b06dSBjorn Andersson if (_regulator_is_enabled(rdev)) { 13956261b06dSBjorn Andersson ret = regulator_enable(rdev->supply); 13966261b06dSBjorn Andersson if (ret < 0) 13976261b06dSBjorn Andersson return ret; 13986261b06dSBjorn Andersson } 13996261b06dSBjorn Andersson 14006261b06dSBjorn Andersson return 0; 14016261b06dSBjorn Andersson } 14026261b06dSBjorn Andersson 14035ffbd136SMark Brown /* Internal regulator request function */ 14045ffbd136SMark Brown static struct regulator *_regulator_get(struct device *dev, const char *id, 14054ddfebd3SMark Brown bool exclusive, bool allow_dummy) 1406414c70cbSLiam Girdwood { 1407414c70cbSLiam Girdwood struct regulator_dev *rdev; 140804bf3011SMark Brown struct regulator *regulator = ERR_PTR(-EPROBE_DEFER); 140940f9244fSMark Brown const char *devname = NULL; 1410317b5684SMark Brown int ret; 1411414c70cbSLiam Girdwood 1412414c70cbSLiam Girdwood if (id == NULL) { 14135da84fd9SJoe Perches pr_err("get() with no identifier\n"); 1414043c998fSMark Brown return ERR_PTR(-EINVAL); 1415414c70cbSLiam Girdwood } 1416414c70cbSLiam Girdwood 141740f9244fSMark Brown if (dev) 141840f9244fSMark Brown devname = dev_name(dev); 141940f9244fSMark Brown 1420317b5684SMark Brown if (have_full_constraints()) 1421317b5684SMark Brown ret = -ENODEV; 1422317b5684SMark Brown else 1423317b5684SMark Brown ret = -EPROBE_DEFER; 1424317b5684SMark Brown 1425414c70cbSLiam Girdwood mutex_lock(®ulator_list_mutex); 1426414c70cbSLiam Girdwood 14276d191a5fSMark Brown rdev = regulator_dev_lookup(dev, id, &ret); 142869511a45SRajendra Nayak if (rdev) 142969511a45SRajendra Nayak goto found; 143069511a45SRajendra Nayak 1431ef60abbbSMark Brown regulator = ERR_PTR(ret); 1432ef60abbbSMark Brown 14331e4b545cSNishanth Menon /* 14341e4b545cSNishanth Menon * If we have return value from dev_lookup fail, we do not expect to 14351e4b545cSNishanth Menon * succeed, so, quit with appropriate error value 14361e4b545cSNishanth Menon */ 14370d25d09dSJingoo Han if (ret && ret != -ENODEV) 14381e4b545cSNishanth Menon goto out; 14391e4b545cSNishanth Menon 144034abbd68SMark Brown if (!devname) 144134abbd68SMark Brown devname = "deviceless"; 144234abbd68SMark Brown 14434ddfebd3SMark Brown /* 14444ddfebd3SMark Brown * Assume that a regulator is physically present and enabled 14454ddfebd3SMark Brown * even if it isn't hooked up and just provide a dummy. 144634abbd68SMark Brown */ 144787b28417SMark Brown if (have_full_constraints() && allow_dummy) { 14485da84fd9SJoe Perches pr_warn("%s supply %s not found, using dummy regulator\n", 144934abbd68SMark Brown devname, id); 14504ddfebd3SMark Brown 145134abbd68SMark Brown rdev = dummy_regulator_rdev; 145234abbd68SMark Brown goto found; 14530781719bSHans de Goede /* Don't log an error when called from regulator_get_optional() */ 14540781719bSHans de Goede } else if (!have_full_constraints() || exclusive) { 1455acc3d5ceSShuah Khan dev_warn(dev, "dummy supplies not allowed\n"); 145634abbd68SMark Brown } 145734abbd68SMark Brown 1458414c70cbSLiam Girdwood mutex_unlock(®ulator_list_mutex); 1459414c70cbSLiam Girdwood return regulator; 1460414c70cbSLiam Girdwood 1461414c70cbSLiam Girdwood found: 14625ffbd136SMark Brown if (rdev->exclusive) { 14635ffbd136SMark Brown regulator = ERR_PTR(-EPERM); 14645ffbd136SMark Brown goto out; 14655ffbd136SMark Brown } 14665ffbd136SMark Brown 14675ffbd136SMark Brown if (exclusive && rdev->open_count) { 14685ffbd136SMark Brown regulator = ERR_PTR(-EBUSY); 14695ffbd136SMark Brown goto out; 14705ffbd136SMark Brown } 14715ffbd136SMark Brown 14726261b06dSBjorn Andersson ret = regulator_resolve_supply(rdev); 14736261b06dSBjorn Andersson if (ret < 0) { 14746261b06dSBjorn Andersson regulator = ERR_PTR(ret); 14756261b06dSBjorn Andersson goto out; 14766261b06dSBjorn Andersson } 14776261b06dSBjorn Andersson 1478a5766f11SLiam Girdwood if (!try_module_get(rdev->owner)) 1479a5766f11SLiam Girdwood goto out; 1480a5766f11SLiam Girdwood 1481414c70cbSLiam Girdwood regulator = create_regulator(rdev, dev, id); 1482414c70cbSLiam Girdwood if (regulator == NULL) { 1483414c70cbSLiam Girdwood regulator = ERR_PTR(-ENOMEM); 1484414c70cbSLiam Girdwood module_put(rdev->owner); 1485bcda4321SAxel Lin goto out; 1486414c70cbSLiam Girdwood } 1487414c70cbSLiam Girdwood 14885ffbd136SMark Brown rdev->open_count++; 14895ffbd136SMark Brown if (exclusive) { 14905ffbd136SMark Brown rdev->exclusive = 1; 14915ffbd136SMark Brown 14925ffbd136SMark Brown ret = _regulator_is_enabled(rdev); 14935ffbd136SMark Brown if (ret > 0) 14945ffbd136SMark Brown rdev->use_count = 1; 14955ffbd136SMark Brown else 14965ffbd136SMark Brown rdev->use_count = 0; 14975ffbd136SMark Brown } 14985ffbd136SMark Brown 1499a5766f11SLiam Girdwood out: 1500414c70cbSLiam Girdwood mutex_unlock(®ulator_list_mutex); 15015ffbd136SMark Brown 1502414c70cbSLiam Girdwood return regulator; 1503414c70cbSLiam Girdwood } 15045ffbd136SMark Brown 15055ffbd136SMark Brown /** 15065ffbd136SMark Brown * regulator_get - lookup and obtain a reference to a regulator. 15075ffbd136SMark Brown * @dev: device for regulator "consumer" 15085ffbd136SMark Brown * @id: Supply name or regulator ID. 15095ffbd136SMark Brown * 15105ffbd136SMark Brown * Returns a struct regulator corresponding to the regulator producer, 15115ffbd136SMark Brown * or IS_ERR() condition containing errno. 15125ffbd136SMark Brown * 15135ffbd136SMark Brown * Use of supply names configured via regulator_set_device_supply() is 15145ffbd136SMark Brown * strongly encouraged. It is recommended that the supply name used 15155ffbd136SMark Brown * should match the name used for the supply and/or the relevant 15165ffbd136SMark Brown * device pins in the datasheet. 15175ffbd136SMark Brown */ 15185ffbd136SMark Brown struct regulator *regulator_get(struct device *dev, const char *id) 15195ffbd136SMark Brown { 15204ddfebd3SMark Brown return _regulator_get(dev, id, false, true); 15215ffbd136SMark Brown } 1522414c70cbSLiam Girdwood EXPORT_SYMBOL_GPL(regulator_get); 1523414c70cbSLiam Girdwood 1524070b9079SStephen Boyd /** 15255ffbd136SMark Brown * regulator_get_exclusive - obtain exclusive access to a regulator. 15265ffbd136SMark Brown * @dev: device for regulator "consumer" 15275ffbd136SMark Brown * @id: Supply name or regulator ID. 15285ffbd136SMark Brown * 15295ffbd136SMark Brown * Returns a struct regulator corresponding to the regulator producer, 15305ffbd136SMark Brown * or IS_ERR() condition containing errno. Other consumers will be 153169c3f723SStephen Boyd * unable to obtain this regulator while this reference is held and the 153269c3f723SStephen Boyd * use count for the regulator will be initialised to reflect the current 153369c3f723SStephen Boyd * state of the regulator. 15345ffbd136SMark Brown * 15355ffbd136SMark Brown * This is intended for use by consumers which cannot tolerate shared 15365ffbd136SMark Brown * use of the regulator such as those which need to force the 15375ffbd136SMark Brown * regulator off for correct operation of the hardware they are 15385ffbd136SMark Brown * controlling. 15395ffbd136SMark Brown * 15405ffbd136SMark Brown * Use of supply names configured via regulator_set_device_supply() is 15415ffbd136SMark Brown * strongly encouraged. It is recommended that the supply name used 15425ffbd136SMark Brown * should match the name used for the supply and/or the relevant 15435ffbd136SMark Brown * device pins in the datasheet. 15445ffbd136SMark Brown */ 15455ffbd136SMark Brown struct regulator *regulator_get_exclusive(struct device *dev, const char *id) 15465ffbd136SMark Brown { 15474ddfebd3SMark Brown return _regulator_get(dev, id, true, false); 15485ffbd136SMark Brown } 15495ffbd136SMark Brown EXPORT_SYMBOL_GPL(regulator_get_exclusive); 15505ffbd136SMark Brown 1551de1dd9fdSMark Brown /** 1552de1dd9fdSMark Brown * regulator_get_optional - obtain optional access to a regulator. 1553de1dd9fdSMark Brown * @dev: device for regulator "consumer" 1554de1dd9fdSMark Brown * @id: Supply name or regulator ID. 1555de1dd9fdSMark Brown * 1556de1dd9fdSMark Brown * Returns a struct regulator corresponding to the regulator producer, 155769c3f723SStephen Boyd * or IS_ERR() condition containing errno. 1558de1dd9fdSMark Brown * 1559de1dd9fdSMark Brown * This is intended for use by consumers for devices which can have 1560de1dd9fdSMark Brown * some supplies unconnected in normal use, such as some MMC devices. 1561de1dd9fdSMark Brown * It can allow the regulator core to provide stub supplies for other 1562de1dd9fdSMark Brown * supplies requested using normal regulator_get() calls without 1563de1dd9fdSMark Brown * disrupting the operation of drivers that can handle absent 1564de1dd9fdSMark Brown * supplies. 1565de1dd9fdSMark Brown * 1566de1dd9fdSMark Brown * Use of supply names configured via regulator_set_device_supply() is 1567de1dd9fdSMark Brown * strongly encouraged. It is recommended that the supply name used 1568de1dd9fdSMark Brown * should match the name used for the supply and/or the relevant 1569de1dd9fdSMark Brown * device pins in the datasheet. 1570de1dd9fdSMark Brown */ 1571de1dd9fdSMark Brown struct regulator *regulator_get_optional(struct device *dev, const char *id) 1572de1dd9fdSMark Brown { 15734ddfebd3SMark Brown return _regulator_get(dev, id, false, false); 1574de1dd9fdSMark Brown } 1575de1dd9fdSMark Brown EXPORT_SYMBOL_GPL(regulator_get_optional); 1576de1dd9fdSMark Brown 157783b0302dSAshay Jaiswal /* regulator_list_mutex lock held by regulator_put() */ 157823ff2f0fSCharles Keepax static void _regulator_put(struct regulator *regulator) 1579414c70cbSLiam Girdwood { 1580414c70cbSLiam Girdwood struct regulator_dev *rdev; 1581414c70cbSLiam Girdwood 1582414c70cbSLiam Girdwood if (regulator == NULL || IS_ERR(regulator)) 1583414c70cbSLiam Girdwood return; 1584414c70cbSLiam Girdwood 1585414c70cbSLiam Girdwood rdev = regulator->rdev; 1586414c70cbSLiam Girdwood 15875de70519SMark Brown debugfs_remove_recursive(regulator->debugfs); 15885de70519SMark Brown 1589414c70cbSLiam Girdwood /* remove any sysfs entries */ 1590e2c98eafSShawn Guo if (regulator->dev) 1591414c70cbSLiam Girdwood sysfs_remove_link(&rdev->dev.kobj, regulator->supply_name); 159283b0302dSAshay Jaiswal mutex_lock(&rdev->mutex); 15935de70519SMark Brown kfree(regulator->supply_name); 1594414c70cbSLiam Girdwood list_del(®ulator->list); 1595414c70cbSLiam Girdwood kfree(regulator); 1596414c70cbSLiam Girdwood 15975ffbd136SMark Brown rdev->open_count--; 15985ffbd136SMark Brown rdev->exclusive = 0; 159983b0302dSAshay Jaiswal mutex_unlock(&rdev->mutex); 16005ffbd136SMark Brown 1601414c70cbSLiam Girdwood module_put(rdev->owner); 160223ff2f0fSCharles Keepax } 160323ff2f0fSCharles Keepax 160423ff2f0fSCharles Keepax /** 160523ff2f0fSCharles Keepax * regulator_put - "free" the regulator source 160623ff2f0fSCharles Keepax * @regulator: regulator source 160723ff2f0fSCharles Keepax * 160823ff2f0fSCharles Keepax * Note: drivers must ensure that all regulator_enable calls made on this 160923ff2f0fSCharles Keepax * regulator source are balanced by regulator_disable calls prior to calling 161023ff2f0fSCharles Keepax * this function. 161123ff2f0fSCharles Keepax */ 161223ff2f0fSCharles Keepax void regulator_put(struct regulator *regulator) 161323ff2f0fSCharles Keepax { 161423ff2f0fSCharles Keepax mutex_lock(®ulator_list_mutex); 161523ff2f0fSCharles Keepax _regulator_put(regulator); 1616414c70cbSLiam Girdwood mutex_unlock(®ulator_list_mutex); 1617414c70cbSLiam Girdwood } 1618414c70cbSLiam Girdwood EXPORT_SYMBOL_GPL(regulator_put); 1619414c70cbSLiam Girdwood 1620a06ccd9cSCharles Keepax /** 1621a06ccd9cSCharles Keepax * regulator_register_supply_alias - Provide device alias for supply lookup 1622a06ccd9cSCharles Keepax * 1623a06ccd9cSCharles Keepax * @dev: device that will be given as the regulator "consumer" 1624a06ccd9cSCharles Keepax * @id: Supply name or regulator ID 1625a06ccd9cSCharles Keepax * @alias_dev: device that should be used to lookup the supply 1626a06ccd9cSCharles Keepax * @alias_id: Supply name or regulator ID that should be used to lookup the 1627a06ccd9cSCharles Keepax * supply 1628a06ccd9cSCharles Keepax * 1629a06ccd9cSCharles Keepax * All lookups for id on dev will instead be conducted for alias_id on 1630a06ccd9cSCharles Keepax * alias_dev. 1631a06ccd9cSCharles Keepax */ 1632a06ccd9cSCharles Keepax int regulator_register_supply_alias(struct device *dev, const char *id, 1633a06ccd9cSCharles Keepax struct device *alias_dev, 1634a06ccd9cSCharles Keepax const char *alias_id) 1635a06ccd9cSCharles Keepax { 1636a06ccd9cSCharles Keepax struct regulator_supply_alias *map; 1637a06ccd9cSCharles Keepax 1638a06ccd9cSCharles Keepax map = regulator_find_supply_alias(dev, id); 1639a06ccd9cSCharles Keepax if (map) 1640a06ccd9cSCharles Keepax return -EEXIST; 1641a06ccd9cSCharles Keepax 1642a06ccd9cSCharles Keepax map = kzalloc(sizeof(struct regulator_supply_alias), GFP_KERNEL); 1643a06ccd9cSCharles Keepax if (!map) 1644a06ccd9cSCharles Keepax return -ENOMEM; 1645a06ccd9cSCharles Keepax 1646a06ccd9cSCharles Keepax map->src_dev = dev; 1647a06ccd9cSCharles Keepax map->src_supply = id; 1648a06ccd9cSCharles Keepax map->alias_dev = alias_dev; 1649a06ccd9cSCharles Keepax map->alias_supply = alias_id; 1650a06ccd9cSCharles Keepax 1651a06ccd9cSCharles Keepax list_add(&map->list, ®ulator_supply_alias_list); 1652a06ccd9cSCharles Keepax 1653a06ccd9cSCharles Keepax pr_info("Adding alias for supply %s,%s -> %s,%s\n", 1654a06ccd9cSCharles Keepax id, dev_name(dev), alias_id, dev_name(alias_dev)); 1655a06ccd9cSCharles Keepax 1656a06ccd9cSCharles Keepax return 0; 1657a06ccd9cSCharles Keepax } 1658a06ccd9cSCharles Keepax EXPORT_SYMBOL_GPL(regulator_register_supply_alias); 1659a06ccd9cSCharles Keepax 1660a06ccd9cSCharles Keepax /** 1661a06ccd9cSCharles Keepax * regulator_unregister_supply_alias - Remove device alias 1662a06ccd9cSCharles Keepax * 1663a06ccd9cSCharles Keepax * @dev: device that will be given as the regulator "consumer" 1664a06ccd9cSCharles Keepax * @id: Supply name or regulator ID 1665a06ccd9cSCharles Keepax * 1666a06ccd9cSCharles Keepax * Remove a lookup alias if one exists for id on dev. 1667a06ccd9cSCharles Keepax */ 1668a06ccd9cSCharles Keepax void regulator_unregister_supply_alias(struct device *dev, const char *id) 1669a06ccd9cSCharles Keepax { 1670a06ccd9cSCharles Keepax struct regulator_supply_alias *map; 1671a06ccd9cSCharles Keepax 1672a06ccd9cSCharles Keepax map = regulator_find_supply_alias(dev, id); 1673a06ccd9cSCharles Keepax if (map) { 1674a06ccd9cSCharles Keepax list_del(&map->list); 1675a06ccd9cSCharles Keepax kfree(map); 1676a06ccd9cSCharles Keepax } 1677a06ccd9cSCharles Keepax } 1678a06ccd9cSCharles Keepax EXPORT_SYMBOL_GPL(regulator_unregister_supply_alias); 1679a06ccd9cSCharles Keepax 1680a06ccd9cSCharles Keepax /** 1681a06ccd9cSCharles Keepax * regulator_bulk_register_supply_alias - register multiple aliases 1682a06ccd9cSCharles Keepax * 1683a06ccd9cSCharles Keepax * @dev: device that will be given as the regulator "consumer" 1684a06ccd9cSCharles Keepax * @id: List of supply names or regulator IDs 1685a06ccd9cSCharles Keepax * @alias_dev: device that should be used to lookup the supply 1686a06ccd9cSCharles Keepax * @alias_id: List of supply names or regulator IDs that should be used to 1687a06ccd9cSCharles Keepax * lookup the supply 1688a06ccd9cSCharles Keepax * @num_id: Number of aliases to register 1689a06ccd9cSCharles Keepax * 1690a06ccd9cSCharles Keepax * @return 0 on success, an errno on failure. 1691a06ccd9cSCharles Keepax * 1692a06ccd9cSCharles Keepax * This helper function allows drivers to register several supply 1693a06ccd9cSCharles Keepax * aliases in one operation. If any of the aliases cannot be 1694a06ccd9cSCharles Keepax * registered any aliases that were registered will be removed 1695a06ccd9cSCharles Keepax * before returning to the caller. 1696a06ccd9cSCharles Keepax */ 16979f8c0fe9SLee Jones int regulator_bulk_register_supply_alias(struct device *dev, 16989f8c0fe9SLee Jones const char *const *id, 1699a06ccd9cSCharles Keepax struct device *alias_dev, 17009f8c0fe9SLee Jones const char *const *alias_id, 1701a06ccd9cSCharles Keepax int num_id) 1702a06ccd9cSCharles Keepax { 1703a06ccd9cSCharles Keepax int i; 1704a06ccd9cSCharles Keepax int ret; 1705a06ccd9cSCharles Keepax 1706a06ccd9cSCharles Keepax for (i = 0; i < num_id; ++i) { 1707a06ccd9cSCharles Keepax ret = regulator_register_supply_alias(dev, id[i], alias_dev, 1708a06ccd9cSCharles Keepax alias_id[i]); 1709a06ccd9cSCharles Keepax if (ret < 0) 1710a06ccd9cSCharles Keepax goto err; 1711a06ccd9cSCharles Keepax } 1712a06ccd9cSCharles Keepax 1713a06ccd9cSCharles Keepax return 0; 1714a06ccd9cSCharles Keepax 1715a06ccd9cSCharles Keepax err: 1716a06ccd9cSCharles Keepax dev_err(dev, 1717a06ccd9cSCharles Keepax "Failed to create supply alias %s,%s -> %s,%s\n", 1718a06ccd9cSCharles Keepax id[i], dev_name(dev), alias_id[i], dev_name(alias_dev)); 1719a06ccd9cSCharles Keepax 1720a06ccd9cSCharles Keepax while (--i >= 0) 1721a06ccd9cSCharles Keepax regulator_unregister_supply_alias(dev, id[i]); 1722a06ccd9cSCharles Keepax 1723a06ccd9cSCharles Keepax return ret; 1724a06ccd9cSCharles Keepax } 1725a06ccd9cSCharles Keepax EXPORT_SYMBOL_GPL(regulator_bulk_register_supply_alias); 1726a06ccd9cSCharles Keepax 1727a06ccd9cSCharles Keepax /** 1728a06ccd9cSCharles Keepax * regulator_bulk_unregister_supply_alias - unregister multiple aliases 1729a06ccd9cSCharles Keepax * 1730a06ccd9cSCharles Keepax * @dev: device that will be given as the regulator "consumer" 1731a06ccd9cSCharles Keepax * @id: List of supply names or regulator IDs 1732a06ccd9cSCharles Keepax * @num_id: Number of aliases to unregister 1733a06ccd9cSCharles Keepax * 1734a06ccd9cSCharles Keepax * This helper function allows drivers to unregister several supply 1735a06ccd9cSCharles Keepax * aliases in one operation. 1736a06ccd9cSCharles Keepax */ 1737a06ccd9cSCharles Keepax void regulator_bulk_unregister_supply_alias(struct device *dev, 17389f8c0fe9SLee Jones const char *const *id, 1739a06ccd9cSCharles Keepax int num_id) 1740a06ccd9cSCharles Keepax { 1741a06ccd9cSCharles Keepax int i; 1742a06ccd9cSCharles Keepax 1743a06ccd9cSCharles Keepax for (i = 0; i < num_id; ++i) 1744a06ccd9cSCharles Keepax regulator_unregister_supply_alias(dev, id[i]); 1745a06ccd9cSCharles Keepax } 1746a06ccd9cSCharles Keepax EXPORT_SYMBOL_GPL(regulator_bulk_unregister_supply_alias); 1747a06ccd9cSCharles Keepax 1748a06ccd9cSCharles Keepax 1749f19b00daSKim, Milo /* Manage enable GPIO list. Same GPIO pin can be shared among regulators */ 1750f19b00daSKim, Milo static int regulator_ena_gpio_request(struct regulator_dev *rdev, 1751f19b00daSKim, Milo const struct regulator_config *config) 1752f19b00daSKim, Milo { 1753f19b00daSKim, Milo struct regulator_enable_gpio *pin; 1754778b28b4SRussell King struct gpio_desc *gpiod; 1755f19b00daSKim, Milo int ret; 1756f19b00daSKim, Milo 1757778b28b4SRussell King gpiod = gpio_to_desc(config->ena_gpio); 1758778b28b4SRussell King 1759f19b00daSKim, Milo list_for_each_entry(pin, ®ulator_ena_gpio_list, list) { 1760778b28b4SRussell King if (pin->gpiod == gpiod) { 1761f19b00daSKim, Milo rdev_dbg(rdev, "GPIO %d is already used\n", 1762f19b00daSKim, Milo config->ena_gpio); 1763f19b00daSKim, Milo goto update_ena_gpio_to_rdev; 1764f19b00daSKim, Milo } 1765f19b00daSKim, Milo } 1766f19b00daSKim, Milo 1767f19b00daSKim, Milo ret = gpio_request_one(config->ena_gpio, 1768f19b00daSKim, Milo GPIOF_DIR_OUT | config->ena_gpio_flags, 1769f19b00daSKim, Milo rdev_get_name(rdev)); 1770f19b00daSKim, Milo if (ret) 1771f19b00daSKim, Milo return ret; 1772f19b00daSKim, Milo 1773f19b00daSKim, Milo pin = kzalloc(sizeof(struct regulator_enable_gpio), GFP_KERNEL); 1774f19b00daSKim, Milo if (pin == NULL) { 1775f19b00daSKim, Milo gpio_free(config->ena_gpio); 1776f19b00daSKim, Milo return -ENOMEM; 1777f19b00daSKim, Milo } 1778f19b00daSKim, Milo 1779778b28b4SRussell King pin->gpiod = gpiod; 1780f19b00daSKim, Milo pin->ena_gpio_invert = config->ena_gpio_invert; 1781f19b00daSKim, Milo list_add(&pin->list, ®ulator_ena_gpio_list); 1782f19b00daSKim, Milo 1783f19b00daSKim, Milo update_ena_gpio_to_rdev: 1784f19b00daSKim, Milo pin->request_count++; 1785f19b00daSKim, Milo rdev->ena_pin = pin; 1786f19b00daSKim, Milo return 0; 1787f19b00daSKim, Milo } 1788f19b00daSKim, Milo 1789f19b00daSKim, Milo static void regulator_ena_gpio_free(struct regulator_dev *rdev) 1790f19b00daSKim, Milo { 1791f19b00daSKim, Milo struct regulator_enable_gpio *pin, *n; 1792f19b00daSKim, Milo 1793f19b00daSKim, Milo if (!rdev->ena_pin) 1794f19b00daSKim, Milo return; 1795f19b00daSKim, Milo 1796f19b00daSKim, Milo /* Free the GPIO only in case of no use */ 1797f19b00daSKim, Milo list_for_each_entry_safe(pin, n, ®ulator_ena_gpio_list, list) { 1798778b28b4SRussell King if (pin->gpiod == rdev->ena_pin->gpiod) { 1799f19b00daSKim, Milo if (pin->request_count <= 1) { 1800f19b00daSKim, Milo pin->request_count = 0; 1801778b28b4SRussell King gpiod_put(pin->gpiod); 1802f19b00daSKim, Milo list_del(&pin->list); 1803f19b00daSKim, Milo kfree(pin); 180460a2362fSSeung-Woo Kim rdev->ena_pin = NULL; 180560a2362fSSeung-Woo Kim return; 1806f19b00daSKim, Milo } else { 1807f19b00daSKim, Milo pin->request_count--; 1808f19b00daSKim, Milo } 1809f19b00daSKim, Milo } 1810f19b00daSKim, Milo } 1811f19b00daSKim, Milo } 1812f19b00daSKim, Milo 1813967cfb18SKim, Milo /** 181431d6eebfSRobert P. J. Day * regulator_ena_gpio_ctrl - balance enable_count of each GPIO and actual GPIO pin control 181531d6eebfSRobert P. J. Day * @rdev: regulator_dev structure 181631d6eebfSRobert P. J. Day * @enable: enable GPIO at initial use? 181731d6eebfSRobert P. J. Day * 1818967cfb18SKim, Milo * GPIO is enabled in case of initial use. (enable_count is 0) 1819967cfb18SKim, Milo * GPIO is disabled when it is not shared any more. (enable_count <= 1) 1820967cfb18SKim, Milo */ 1821967cfb18SKim, Milo static int regulator_ena_gpio_ctrl(struct regulator_dev *rdev, bool enable) 1822967cfb18SKim, Milo { 1823967cfb18SKim, Milo struct regulator_enable_gpio *pin = rdev->ena_pin; 1824967cfb18SKim, Milo 1825967cfb18SKim, Milo if (!pin) 1826967cfb18SKim, Milo return -EINVAL; 1827967cfb18SKim, Milo 1828967cfb18SKim, Milo if (enable) { 1829967cfb18SKim, Milo /* Enable GPIO at initial use */ 1830967cfb18SKim, Milo if (pin->enable_count == 0) 1831778b28b4SRussell King gpiod_set_value_cansleep(pin->gpiod, 1832967cfb18SKim, Milo !pin->ena_gpio_invert); 1833967cfb18SKim, Milo 1834967cfb18SKim, Milo pin->enable_count++; 1835967cfb18SKim, Milo } else { 1836967cfb18SKim, Milo if (pin->enable_count > 1) { 1837967cfb18SKim, Milo pin->enable_count--; 1838967cfb18SKim, Milo return 0; 1839967cfb18SKim, Milo } 1840967cfb18SKim, Milo 1841967cfb18SKim, Milo /* Disable GPIO if not used */ 1842967cfb18SKim, Milo if (pin->enable_count <= 1) { 1843778b28b4SRussell King gpiod_set_value_cansleep(pin->gpiod, 1844967cfb18SKim, Milo pin->ena_gpio_invert); 1845967cfb18SKim, Milo pin->enable_count = 0; 1846967cfb18SKim, Milo } 1847967cfb18SKim, Milo } 1848967cfb18SKim, Milo 1849967cfb18SKim, Milo return 0; 1850967cfb18SKim, Milo } 1851967cfb18SKim, Milo 185279fd1141SGuodong Xu /** 185379fd1141SGuodong Xu * _regulator_enable_delay - a delay helper function 185479fd1141SGuodong Xu * @delay: time to delay in microseconds 185579fd1141SGuodong Xu * 18565df529d4SThierry Reding * Delay for the requested amount of time as per the guidelines in: 18575df529d4SThierry Reding * 18585df529d4SThierry Reding * Documentation/timers/timers-howto.txt 18595df529d4SThierry Reding * 18605df529d4SThierry Reding * The assumption here is that regulators will never be enabled in 18615df529d4SThierry Reding * atomic context and therefore sleeping functions can be used. 18625df529d4SThierry Reding */ 186379fd1141SGuodong Xu static void _regulator_enable_delay(unsigned int delay) 186479fd1141SGuodong Xu { 18655df529d4SThierry Reding unsigned int ms = delay / 1000; 18665df529d4SThierry Reding unsigned int us = delay % 1000; 18675df529d4SThierry Reding 18685df529d4SThierry Reding if (ms > 0) { 18695df529d4SThierry Reding /* 18705df529d4SThierry Reding * For small enough values, handle super-millisecond 18715df529d4SThierry Reding * delays in the usleep_range() call below. 18725df529d4SThierry Reding */ 18735df529d4SThierry Reding if (ms < 20) 18745df529d4SThierry Reding us += ms * 1000; 18755df529d4SThierry Reding else 18765df529d4SThierry Reding msleep(ms); 18775df529d4SThierry Reding } 18785df529d4SThierry Reding 18795df529d4SThierry Reding /* 18805df529d4SThierry Reding * Give the scheduler some room to coalesce with any other 18815df529d4SThierry Reding * wakeup sources. For delays shorter than 10 us, don't even 18825df529d4SThierry Reding * bother setting up high-resolution timers and just busy- 18835df529d4SThierry Reding * loop. 18845df529d4SThierry Reding */ 18855df529d4SThierry Reding if (us >= 10) 18865df529d4SThierry Reding usleep_range(us, us + 100); 18875df529d4SThierry Reding else 18885df529d4SThierry Reding udelay(us); 18895c5659d0SMark Brown } 18905c5659d0SMark Brown 18915c5659d0SMark Brown static int _regulator_do_enable(struct regulator_dev *rdev) 18925c5659d0SMark Brown { 18935c5659d0SMark Brown int ret, delay; 18945c5659d0SMark Brown 18955c5659d0SMark Brown /* Query before enabling in case configuration dependent. */ 18965c5659d0SMark Brown ret = _regulator_get_enable_time(rdev); 18975c5659d0SMark Brown if (ret >= 0) { 18985c5659d0SMark Brown delay = ret; 18995c5659d0SMark Brown } else { 1900414c70cbSLiam Girdwood rdev_warn(rdev, "enable_time() failed: %d\n", ret); 1901414c70cbSLiam Girdwood delay = 0; 1902414c70cbSLiam Girdwood } 19035c5659d0SMark Brown 1904414c70cbSLiam Girdwood trace_regulator_enable(rdev_get_name(rdev)); 1905414c70cbSLiam Girdwood 1906871f5650SGuodong Xu if (rdev->desc->off_on_delay) { 1907871f5650SGuodong Xu /* if needed, keep a distance of off_on_delay from last time 1908871f5650SGuodong Xu * this regulator was disabled. 1909871f5650SGuodong Xu */ 1910871f5650SGuodong Xu unsigned long start_jiffy = jiffies; 1911871f5650SGuodong Xu unsigned long intended, max_delay, remaining; 1912871f5650SGuodong Xu 1913871f5650SGuodong Xu max_delay = usecs_to_jiffies(rdev->desc->off_on_delay); 1914871f5650SGuodong Xu intended = rdev->last_off_jiffy + max_delay; 1915871f5650SGuodong Xu 1916871f5650SGuodong Xu if (time_before(start_jiffy, intended)) { 1917871f5650SGuodong Xu /* calc remaining jiffies to deal with one-time 1918871f5650SGuodong Xu * timer wrapping. 1919871f5650SGuodong Xu * in case of multiple timer wrapping, either it can be 1920871f5650SGuodong Xu * detected by out-of-range remaining, or it cannot be 1921871f5650SGuodong Xu * detected and we gets a panelty of 1922871f5650SGuodong Xu * _regulator_enable_delay(). 1923871f5650SGuodong Xu */ 1924871f5650SGuodong Xu remaining = intended - start_jiffy; 1925871f5650SGuodong Xu if (remaining <= max_delay) 1926871f5650SGuodong Xu _regulator_enable_delay( 1927871f5650SGuodong Xu jiffies_to_usecs(remaining)); 1928871f5650SGuodong Xu } 1929871f5650SGuodong Xu } 1930871f5650SGuodong Xu 1931414c70cbSLiam Girdwood if (rdev->ena_pin) { 193229d62ec5SDoug Anderson if (!rdev->ena_gpio_state) { 19339a2372faSMark Brown ret = regulator_ena_gpio_ctrl(rdev, true); 1934414c70cbSLiam Girdwood if (ret < 0) 1935414c70cbSLiam Girdwood return ret; 19369a2372faSMark Brown rdev->ena_gpio_state = 1; 193729d62ec5SDoug Anderson } 19389a2372faSMark Brown } else if (rdev->desc->ops->enable) { 19399a2372faSMark Brown ret = rdev->desc->ops->enable(rdev); 19409a2372faSMark Brown if (ret < 0) 19419a2372faSMark Brown return ret; 19429a2372faSMark Brown } else { 19439a2372faSMark Brown return -EINVAL; 19445c5659d0SMark Brown } 19459a2372faSMark Brown 19469a2372faSMark Brown /* Allow the regulator to ramp; it would be useful to extend 194731aae2beSMark Brown * this for bulk operations so that the regulators can ramp 1948a7433cffSLinus Walleij * together. */ 19495da84fd9SJoe Perches trace_regulator_enable_delay(rdev_get_name(rdev)); 1950414c70cbSLiam Girdwood 195179fd1141SGuodong Xu _regulator_enable_delay(delay); 1952a7433cffSLinus Walleij 1953414c70cbSLiam Girdwood trace_regulator_enable_complete(rdev_get_name(rdev)); 1954414c70cbSLiam Girdwood 19559a2372faSMark Brown return 0; 19569a2372faSMark Brown } 19579a2372faSMark Brown 1958414c70cbSLiam Girdwood /* locks held by regulator_enable() */ 1959414c70cbSLiam Girdwood static int _regulator_enable(struct regulator_dev *rdev) 1960414c70cbSLiam Girdwood { 1961414c70cbSLiam Girdwood int ret; 1962414c70cbSLiam Girdwood 1963414c70cbSLiam Girdwood /* check voltage and requested load before enabling */ 1964cf7bbcdfSMark Brown if (rdev->constraints && 1965cf7bbcdfSMark Brown (rdev->constraints->valid_ops_mask & REGULATOR_CHANGE_DRMS)) 1966cf7bbcdfSMark Brown drms_uA_update(rdev); 1967cf7bbcdfSMark Brown 1968414c70cbSLiam Girdwood if (rdev->use_count == 0) { 1969cf7bbcdfSMark Brown /* The regulator may on if it's not switchable or left on */ 1970414c70cbSLiam Girdwood ret = _regulator_is_enabled(rdev); 1971414c70cbSLiam Girdwood if (ret == -EINVAL || ret == 0) { 1972414c70cbSLiam Girdwood if (!_regulator_can_change_status(rdev)) 1973412aec61SDavid Brownell return -EPERM; 1974412aec61SDavid Brownell 1975414c70cbSLiam Girdwood ret = _regulator_do_enable(rdev); 1976412aec61SDavid Brownell if (ret < 0) 1977412aec61SDavid Brownell return ret; 1978412aec61SDavid Brownell 1979414c70cbSLiam Girdwood } else if (ret < 0) { 1980414c70cbSLiam Girdwood rdev_err(rdev, "is_enabled() failed: %d\n", ret); 1981414c70cbSLiam Girdwood return ret; 1982414c70cbSLiam Girdwood } 1983414c70cbSLiam Girdwood /* Fallthrough on positive return values - already enabled */ 1984414c70cbSLiam Girdwood } 1985414c70cbSLiam Girdwood 1986414c70cbSLiam Girdwood rdev->use_count++; 1987414c70cbSLiam Girdwood 1988cd94b505SDavid Brownell return 0; 1989cd94b505SDavid Brownell } 19901083c393SMark Brown 1991cd94b505SDavid Brownell /** 1992cd94b505SDavid Brownell * regulator_enable - enable regulator output 1993414c70cbSLiam Girdwood * @regulator: regulator source 199460ef66fcSMark Brown * 199560ef66fcSMark Brown * Request that the regulator be enabled with the regulator output at 1996414c70cbSLiam Girdwood * the predefined voltage or current value. Calls to regulator_enable() 1997414c70cbSLiam Girdwood * must be balanced with calls to regulator_disable(). 19989a2372faSMark Brown * 19999a2372faSMark Brown * NOTE: the output value can be set by other drivers, boot loader or may be 2000414c70cbSLiam Girdwood * hardwired in the regulator. 2001414c70cbSLiam Girdwood */ 2002414c70cbSLiam Girdwood int regulator_enable(struct regulator *regulator) 20031083c393SMark Brown { 2004414c70cbSLiam Girdwood struct regulator_dev *rdev = regulator->rdev; 2005414c70cbSLiam Girdwood int ret = 0; 200684b68263SMark Brown 20076492bc1bSMark Brown if (regulator->always_on) 20086492bc1bSMark Brown return 0; 20096492bc1bSMark Brown 20103801b86aSMark Brown if (rdev->supply) { 20113801b86aSMark Brown ret = regulator_enable(rdev->supply); 20123801b86aSMark Brown if (ret != 0) 20133801b86aSMark Brown return ret; 20143801b86aSMark Brown } 20153801b86aSMark Brown 2016414c70cbSLiam Girdwood mutex_lock(&rdev->mutex); 2017414c70cbSLiam Girdwood ret = _regulator_enable(rdev); 2018414c70cbSLiam Girdwood mutex_unlock(&rdev->mutex); 20193801b86aSMark Brown 2020d1685e4eSHeiko Stübner if (ret != 0 && rdev->supply) 20213801b86aSMark Brown regulator_disable(rdev->supply); 20223801b86aSMark Brown 2023414c70cbSLiam Girdwood return ret; 2024414c70cbSLiam Girdwood } 2025414c70cbSLiam Girdwood EXPORT_SYMBOL_GPL(regulator_enable); 2026414c70cbSLiam Girdwood 20275c5659d0SMark Brown static int _regulator_do_disable(struct regulator_dev *rdev) 20285c5659d0SMark Brown { 20295c5659d0SMark Brown int ret; 20305c5659d0SMark Brown 20315c5659d0SMark Brown trace_regulator_disable(rdev_get_name(rdev)); 20325c5659d0SMark Brown 2033967cfb18SKim, Milo if (rdev->ena_pin) { 203429d62ec5SDoug Anderson if (rdev->ena_gpio_state) { 2035967cfb18SKim, Milo ret = regulator_ena_gpio_ctrl(rdev, false); 2036967cfb18SKim, Milo if (ret < 0) 2037967cfb18SKim, Milo return ret; 20385c5659d0SMark Brown rdev->ena_gpio_state = 0; 203929d62ec5SDoug Anderson } 20405c5659d0SMark Brown 20415c5659d0SMark Brown } else if (rdev->desc->ops->disable) { 20425c5659d0SMark Brown ret = rdev->desc->ops->disable(rdev); 20435c5659d0SMark Brown if (ret != 0) 20445c5659d0SMark Brown return ret; 20455c5659d0SMark Brown } 20465c5659d0SMark Brown 2047871f5650SGuodong Xu /* cares about last_off_jiffy only if off_on_delay is required by 2048871f5650SGuodong Xu * device. 2049871f5650SGuodong Xu */ 2050871f5650SGuodong Xu if (rdev->desc->off_on_delay) 2051871f5650SGuodong Xu rdev->last_off_jiffy = jiffies; 2052871f5650SGuodong Xu 20535c5659d0SMark Brown trace_regulator_disable_complete(rdev_get_name(rdev)); 20545c5659d0SMark Brown 20555c5659d0SMark Brown return 0; 20565c5659d0SMark Brown } 20575c5659d0SMark Brown 2058414c70cbSLiam Girdwood /* locks held by regulator_disable() */ 20593801b86aSMark Brown static int _regulator_disable(struct regulator_dev *rdev) 2060414c70cbSLiam Girdwood { 2061414c70cbSLiam Girdwood int ret = 0; 2062414c70cbSLiam Girdwood 2063414c70cbSLiam Girdwood if (WARN(rdev->use_count <= 0, 206443e7ee33SJoe Perches "unbalanced disables for %s\n", rdev_get_name(rdev))) 2065414c70cbSLiam Girdwood return -EIO; 2066414c70cbSLiam Girdwood 2067414c70cbSLiam Girdwood /* are we the last user and permitted to disable ? */ 2068414c70cbSLiam Girdwood if (rdev->use_count == 1 && 2069414c70cbSLiam Girdwood (rdev->constraints && !rdev->constraints->always_on)) { 2070414c70cbSLiam Girdwood 2071414c70cbSLiam Girdwood /* we are last user */ 20725c5659d0SMark Brown if (_regulator_can_change_status(rdev)) { 2073a1c8a551SRichard Fitzgerald ret = _notifier_call_chain(rdev, 2074a1c8a551SRichard Fitzgerald REGULATOR_EVENT_PRE_DISABLE, 2075a1c8a551SRichard Fitzgerald NULL); 2076a1c8a551SRichard Fitzgerald if (ret & NOTIFY_STOP_MASK) 2077a1c8a551SRichard Fitzgerald return -EINVAL; 2078a1c8a551SRichard Fitzgerald 20795c5659d0SMark Brown ret = _regulator_do_disable(rdev); 2080414c70cbSLiam Girdwood if (ret < 0) { 20815da84fd9SJoe Perches rdev_err(rdev, "failed to disable\n"); 2082a1c8a551SRichard Fitzgerald _notifier_call_chain(rdev, 2083a1c8a551SRichard Fitzgerald REGULATOR_EVENT_ABORT_DISABLE, 2084a1c8a551SRichard Fitzgerald NULL); 2085414c70cbSLiam Girdwood return ret; 2086414c70cbSLiam Girdwood } 208766fda75fSMarkus Pargmann _notifier_call_chain(rdev, REGULATOR_EVENT_DISABLE, 208866fda75fSMarkus Pargmann NULL); 2089414c70cbSLiam Girdwood } 2090414c70cbSLiam Girdwood 2091414c70cbSLiam Girdwood rdev->use_count = 0; 2092414c70cbSLiam Girdwood } else if (rdev->use_count > 1) { 2093414c70cbSLiam Girdwood 2094414c70cbSLiam Girdwood if (rdev->constraints && 2095414c70cbSLiam Girdwood (rdev->constraints->valid_ops_mask & 2096414c70cbSLiam Girdwood REGULATOR_CHANGE_DRMS)) 2097414c70cbSLiam Girdwood drms_uA_update(rdev); 2098414c70cbSLiam Girdwood 2099414c70cbSLiam Girdwood rdev->use_count--; 2100414c70cbSLiam Girdwood } 21013801b86aSMark Brown 2102414c70cbSLiam Girdwood return ret; 2103414c70cbSLiam Girdwood } 2104414c70cbSLiam Girdwood 2105414c70cbSLiam Girdwood /** 2106414c70cbSLiam Girdwood * regulator_disable - disable regulator output 2107414c70cbSLiam Girdwood * @regulator: regulator source 2108414c70cbSLiam Girdwood * 2109cf7bbcdfSMark Brown * Disable the regulator output voltage or current. Calls to 2110cf7bbcdfSMark Brown * regulator_enable() must be balanced with calls to 2111cf7bbcdfSMark Brown * regulator_disable(). 211269279fb9SMark Brown * 2113414c70cbSLiam Girdwood * NOTE: this will only disable the regulator output if no other consumer 2114cf7bbcdfSMark Brown * devices have it enabled, the regulator device supports disabling and 2115cf7bbcdfSMark Brown * machine constraints permit this operation. 2116414c70cbSLiam Girdwood */ 2117414c70cbSLiam Girdwood int regulator_disable(struct regulator *regulator) 2118414c70cbSLiam Girdwood { 2119412aec61SDavid Brownell struct regulator_dev *rdev = regulator->rdev; 2120412aec61SDavid Brownell int ret = 0; 2121414c70cbSLiam Girdwood 21226492bc1bSMark Brown if (regulator->always_on) 21236492bc1bSMark Brown return 0; 21246492bc1bSMark Brown 2125412aec61SDavid Brownell mutex_lock(&rdev->mutex); 21263801b86aSMark Brown ret = _regulator_disable(rdev); 2127412aec61SDavid Brownell mutex_unlock(&rdev->mutex); 21288cbf811dSJeffrey Carlyle 21293801b86aSMark Brown if (ret == 0 && rdev->supply) 21303801b86aSMark Brown regulator_disable(rdev->supply); 21318cbf811dSJeffrey Carlyle 2132414c70cbSLiam Girdwood return ret; 2133414c70cbSLiam Girdwood } 2134414c70cbSLiam Girdwood EXPORT_SYMBOL_GPL(regulator_disable); 2135414c70cbSLiam Girdwood 2136414c70cbSLiam Girdwood /* locks held by regulator_force_disable() */ 21373801b86aSMark Brown static int _regulator_force_disable(struct regulator_dev *rdev) 2138414c70cbSLiam Girdwood { 2139414c70cbSLiam Girdwood int ret = 0; 2140414c70cbSLiam Girdwood 2141a1c8a551SRichard Fitzgerald ret = _notifier_call_chain(rdev, REGULATOR_EVENT_FORCE_DISABLE | 2142a1c8a551SRichard Fitzgerald REGULATOR_EVENT_PRE_DISABLE, NULL); 2143a1c8a551SRichard Fitzgerald if (ret & NOTIFY_STOP_MASK) 2144a1c8a551SRichard Fitzgerald return -EINVAL; 2145a1c8a551SRichard Fitzgerald 214666fda75fSMarkus Pargmann ret = _regulator_do_disable(rdev); 2147414c70cbSLiam Girdwood if (ret < 0) { 21485da84fd9SJoe Perches rdev_err(rdev, "failed to force disable\n"); 2149a1c8a551SRichard Fitzgerald _notifier_call_chain(rdev, REGULATOR_EVENT_FORCE_DISABLE | 2150a1c8a551SRichard Fitzgerald REGULATOR_EVENT_ABORT_DISABLE, NULL); 2151414c70cbSLiam Girdwood return ret; 2152414c70cbSLiam Girdwood } 215366fda75fSMarkus Pargmann 215484b68263SMark Brown _notifier_call_chain(rdev, REGULATOR_EVENT_FORCE_DISABLE | 215584b68263SMark Brown REGULATOR_EVENT_DISABLE, NULL); 2156414c70cbSLiam Girdwood 215766fda75fSMarkus Pargmann return 0; 2158414c70cbSLiam Girdwood } 2159414c70cbSLiam Girdwood 2160414c70cbSLiam Girdwood /** 2161414c70cbSLiam Girdwood * regulator_force_disable - force disable regulator output 2162414c70cbSLiam Girdwood * @regulator: regulator source 2163414c70cbSLiam Girdwood * 2164414c70cbSLiam Girdwood * Forcibly disable the regulator output voltage or current. 2165414c70cbSLiam Girdwood * NOTE: this *will* disable the regulator output even if other consumer 2166414c70cbSLiam Girdwood * devices have it enabled. This should be used for situations when device 2167414c70cbSLiam Girdwood * damage will likely occur if the regulator is not disabled (e.g. over temp). 2168414c70cbSLiam Girdwood */ 2169414c70cbSLiam Girdwood int regulator_force_disable(struct regulator *regulator) 2170414c70cbSLiam Girdwood { 217182d15839SMark Brown struct regulator_dev *rdev = regulator->rdev; 2172414c70cbSLiam Girdwood int ret; 2173414c70cbSLiam Girdwood 217482d15839SMark Brown mutex_lock(&rdev->mutex); 2175414c70cbSLiam Girdwood regulator->uA_load = 0; 21763801b86aSMark Brown ret = _regulator_force_disable(regulator->rdev); 217782d15839SMark Brown mutex_unlock(&rdev->mutex); 21788cbf811dSJeffrey Carlyle 21793801b86aSMark Brown if (rdev->supply) 21803801b86aSMark Brown while (rdev->open_count--) 21813801b86aSMark Brown regulator_disable(rdev->supply); 21828cbf811dSJeffrey Carlyle 2183414c70cbSLiam Girdwood return ret; 2184414c70cbSLiam Girdwood } 2185414c70cbSLiam Girdwood EXPORT_SYMBOL_GPL(regulator_force_disable); 2186414c70cbSLiam Girdwood 2187da07ecd9SMark Brown static void regulator_disable_work(struct work_struct *work) 2188da07ecd9SMark Brown { 2189da07ecd9SMark Brown struct regulator_dev *rdev = container_of(work, struct regulator_dev, 2190da07ecd9SMark Brown disable_work.work); 2191da07ecd9SMark Brown int count, i, ret; 2192da07ecd9SMark Brown 2193da07ecd9SMark Brown mutex_lock(&rdev->mutex); 2194da07ecd9SMark Brown 2195da07ecd9SMark Brown BUG_ON(!rdev->deferred_disables); 2196da07ecd9SMark Brown 2197da07ecd9SMark Brown count = rdev->deferred_disables; 2198da07ecd9SMark Brown rdev->deferred_disables = 0; 2199da07ecd9SMark Brown 2200da07ecd9SMark Brown for (i = 0; i < count; i++) { 2201da07ecd9SMark Brown ret = _regulator_disable(rdev); 2202da07ecd9SMark Brown if (ret != 0) 2203da07ecd9SMark Brown rdev_err(rdev, "Deferred disable failed: %d\n", ret); 2204da07ecd9SMark Brown } 2205da07ecd9SMark Brown 2206da07ecd9SMark Brown mutex_unlock(&rdev->mutex); 2207da07ecd9SMark Brown 2208da07ecd9SMark Brown if (rdev->supply) { 2209da07ecd9SMark Brown for (i = 0; i < count; i++) { 2210da07ecd9SMark Brown ret = regulator_disable(rdev->supply); 2211da07ecd9SMark Brown if (ret != 0) { 2212da07ecd9SMark Brown rdev_err(rdev, 2213da07ecd9SMark Brown "Supply disable failed: %d\n", ret); 2214da07ecd9SMark Brown } 2215da07ecd9SMark Brown } 2216da07ecd9SMark Brown } 2217da07ecd9SMark Brown } 2218da07ecd9SMark Brown 2219da07ecd9SMark Brown /** 2220da07ecd9SMark Brown * regulator_disable_deferred - disable regulator output with delay 2221da07ecd9SMark Brown * @regulator: regulator source 2222da07ecd9SMark Brown * @ms: miliseconds until the regulator is disabled 2223da07ecd9SMark Brown * 2224da07ecd9SMark Brown * Execute regulator_disable() on the regulator after a delay. This 2225da07ecd9SMark Brown * is intended for use with devices that require some time to quiesce. 2226da07ecd9SMark Brown * 2227da07ecd9SMark Brown * NOTE: this will only disable the regulator output if no other consumer 2228da07ecd9SMark Brown * devices have it enabled, the regulator device supports disabling and 2229da07ecd9SMark Brown * machine constraints permit this operation. 2230da07ecd9SMark Brown */ 2231da07ecd9SMark Brown int regulator_disable_deferred(struct regulator *regulator, int ms) 2232da07ecd9SMark Brown { 2233da07ecd9SMark Brown struct regulator_dev *rdev = regulator->rdev; 2234aa59802dSMark Brown int ret; 2235da07ecd9SMark Brown 22366492bc1bSMark Brown if (regulator->always_on) 22376492bc1bSMark Brown return 0; 22386492bc1bSMark Brown 22392b5a24a0SMark Brown if (!ms) 22402b5a24a0SMark Brown return regulator_disable(regulator); 22412b5a24a0SMark Brown 2242da07ecd9SMark Brown mutex_lock(&rdev->mutex); 2243da07ecd9SMark Brown rdev->deferred_disables++; 2244da07ecd9SMark Brown mutex_unlock(&rdev->mutex); 2245da07ecd9SMark Brown 2246070260f0SMark Brown ret = queue_delayed_work(system_power_efficient_wq, 2247070260f0SMark Brown &rdev->disable_work, 2248da07ecd9SMark Brown msecs_to_jiffies(ms)); 2249aa59802dSMark Brown if (ret < 0) 2250aa59802dSMark Brown return ret; 2251aa59802dSMark Brown else 2252aa59802dSMark Brown return 0; 2253da07ecd9SMark Brown } 2254da07ecd9SMark Brown EXPORT_SYMBOL_GPL(regulator_disable_deferred); 2255da07ecd9SMark Brown 2256414c70cbSLiam Girdwood static int _regulator_is_enabled(struct regulator_dev *rdev) 2257414c70cbSLiam Girdwood { 225865f73508SMark Brown /* A GPIO control always takes precedence */ 22597b74d149SKim, Milo if (rdev->ena_pin) 226065f73508SMark Brown return rdev->ena_gpio_state; 226165f73508SMark Brown 22629a7f6a4cSMark Brown /* If we don't know then assume that the regulator is always on */ 22639332546fSMark Brown if (!rdev->desc->ops->is_enabled) 22649a7f6a4cSMark Brown return 1; 2265414c70cbSLiam Girdwood 22669332546fSMark Brown return rdev->desc->ops->is_enabled(rdev); 2267414c70cbSLiam Girdwood } 2268414c70cbSLiam Girdwood 2269414c70cbSLiam Girdwood /** 2270414c70cbSLiam Girdwood * regulator_is_enabled - is the regulator output enabled 2271414c70cbSLiam Girdwood * @regulator: regulator source 2272414c70cbSLiam Girdwood * 2273412aec61SDavid Brownell * Returns positive if the regulator driver backing the source/client 2274412aec61SDavid Brownell * has requested that the device be enabled, zero if it hasn't, else a 2275412aec61SDavid Brownell * negative errno code. 2276412aec61SDavid Brownell * 2277412aec61SDavid Brownell * Note that the device backing this regulator handle can have multiple 2278412aec61SDavid Brownell * users, so it might be enabled even if regulator_enable() was never 2279412aec61SDavid Brownell * called for this particular source. 2280414c70cbSLiam Girdwood */ 2281414c70cbSLiam Girdwood int regulator_is_enabled(struct regulator *regulator) 2282414c70cbSLiam Girdwood { 22839332546fSMark Brown int ret; 22849332546fSMark Brown 22856492bc1bSMark Brown if (regulator->always_on) 22866492bc1bSMark Brown return 1; 22876492bc1bSMark Brown 22889332546fSMark Brown mutex_lock(®ulator->rdev->mutex); 22899332546fSMark Brown ret = _regulator_is_enabled(regulator->rdev); 22909332546fSMark Brown mutex_unlock(®ulator->rdev->mutex); 22919332546fSMark Brown 22929332546fSMark Brown return ret; 2293414c70cbSLiam Girdwood } 2294414c70cbSLiam Girdwood EXPORT_SYMBOL_GPL(regulator_is_enabled); 2295414c70cbSLiam Girdwood 2296414c70cbSLiam Girdwood /** 2297d1e7de30SMarek Szyprowski * regulator_can_change_voltage - check if regulator can change voltage 2298d1e7de30SMarek Szyprowski * @regulator: regulator source 2299d1e7de30SMarek Szyprowski * 2300d1e7de30SMarek Szyprowski * Returns positive if the regulator driver backing the source/client 2301e227867fSMasanari Iida * can change its voltage, false otherwise. Useful for detecting fixed 2302d1e7de30SMarek Szyprowski * or dummy regulators and disabling voltage change logic in the client 2303d1e7de30SMarek Szyprowski * driver. 2304d1e7de30SMarek Szyprowski */ 2305d1e7de30SMarek Szyprowski int regulator_can_change_voltage(struct regulator *regulator) 2306d1e7de30SMarek Szyprowski { 2307d1e7de30SMarek Szyprowski struct regulator_dev *rdev = regulator->rdev; 2308d1e7de30SMarek Szyprowski 2309d1e7de30SMarek Szyprowski if (rdev->constraints && 231019280e40SAxel Lin (rdev->constraints->valid_ops_mask & REGULATOR_CHANGE_VOLTAGE)) { 231119280e40SAxel Lin if (rdev->desc->n_voltages - rdev->desc->linear_min_sel > 1) 2312d1e7de30SMarek Szyprowski return 1; 2313d1e7de30SMarek Szyprowski 231419280e40SAxel Lin if (rdev->desc->continuous_voltage_range && 231519280e40SAxel Lin rdev->constraints->min_uV && rdev->constraints->max_uV && 231619280e40SAxel Lin rdev->constraints->min_uV != rdev->constraints->max_uV) 231719280e40SAxel Lin return 1; 231819280e40SAxel Lin } 231919280e40SAxel Lin 2320d1e7de30SMarek Szyprowski return 0; 2321d1e7de30SMarek Szyprowski } 2322d1e7de30SMarek Szyprowski EXPORT_SYMBOL_GPL(regulator_can_change_voltage); 2323d1e7de30SMarek Szyprowski 2324d1e7de30SMarek Szyprowski /** 23254367cfdcSDavid Brownell * regulator_count_voltages - count regulator_list_voltage() selectors 23264367cfdcSDavid Brownell * @regulator: regulator source 23274367cfdcSDavid Brownell * 23284367cfdcSDavid Brownell * Returns number of selectors, or negative errno. Selectors are 23294367cfdcSDavid Brownell * numbered starting at zero, and typically correspond to bitfields 23304367cfdcSDavid Brownell * in hardware registers. 23314367cfdcSDavid Brownell */ 23324367cfdcSDavid Brownell int regulator_count_voltages(struct regulator *regulator) 23334367cfdcSDavid Brownell { 23344367cfdcSDavid Brownell struct regulator_dev *rdev = regulator->rdev; 23354367cfdcSDavid Brownell 233626988efeSJavier Martinez Canillas if (rdev->desc->n_voltages) 233726988efeSJavier Martinez Canillas return rdev->desc->n_voltages; 233826988efeSJavier Martinez Canillas 233926988efeSJavier Martinez Canillas if (!rdev->supply) 234026988efeSJavier Martinez Canillas return -EINVAL; 234126988efeSJavier Martinez Canillas 234226988efeSJavier Martinez Canillas return regulator_count_voltages(rdev->supply); 23434367cfdcSDavid Brownell } 23444367cfdcSDavid Brownell EXPORT_SYMBOL_GPL(regulator_count_voltages); 23454367cfdcSDavid Brownell 23464367cfdcSDavid Brownell /** 23474367cfdcSDavid Brownell * regulator_list_voltage - enumerate supported voltages 23484367cfdcSDavid Brownell * @regulator: regulator source 23494367cfdcSDavid Brownell * @selector: identify voltage to list 23504367cfdcSDavid Brownell * Context: can sleep 23514367cfdcSDavid Brownell * 23524367cfdcSDavid Brownell * Returns a voltage that can be passed to @regulator_set_voltage(), 235388393161SThomas Weber * zero if this selector code can't be used on this system, or a 23544367cfdcSDavid Brownell * negative errno. 23554367cfdcSDavid Brownell */ 23564367cfdcSDavid Brownell int regulator_list_voltage(struct regulator *regulator, unsigned selector) 23574367cfdcSDavid Brownell { 23584367cfdcSDavid Brownell struct regulator_dev *rdev = regulator->rdev; 2359272e2315SGuodong Xu const struct regulator_ops *ops = rdev->desc->ops; 23604367cfdcSDavid Brownell int ret; 23614367cfdcSDavid Brownell 2362f446043fSGuennadi Liakhovetski if (rdev->desc->fixed_uV && rdev->desc->n_voltages == 1 && !selector) 2363f446043fSGuennadi Liakhovetski return rdev->desc->fixed_uV; 2364f446043fSGuennadi Liakhovetski 236526988efeSJavier Martinez Canillas if (ops->list_voltage) { 236626988efeSJavier Martinez Canillas if (selector >= rdev->desc->n_voltages) 23674367cfdcSDavid Brownell return -EINVAL; 23684367cfdcSDavid Brownell mutex_lock(&rdev->mutex); 23694367cfdcSDavid Brownell ret = ops->list_voltage(rdev, selector); 23704367cfdcSDavid Brownell mutex_unlock(&rdev->mutex); 237126988efeSJavier Martinez Canillas } else if (rdev->supply) { 237226988efeSJavier Martinez Canillas ret = regulator_list_voltage(rdev->supply, selector); 237326988efeSJavier Martinez Canillas } else { 237426988efeSJavier Martinez Canillas return -EINVAL; 237526988efeSJavier Martinez Canillas } 23764367cfdcSDavid Brownell 23774367cfdcSDavid Brownell if (ret > 0) { 23784367cfdcSDavid Brownell if (ret < rdev->constraints->min_uV) 23794367cfdcSDavid Brownell ret = 0; 23804367cfdcSDavid Brownell else if (ret > rdev->constraints->max_uV) 23814367cfdcSDavid Brownell ret = 0; 23824367cfdcSDavid Brownell } 23834367cfdcSDavid Brownell 23844367cfdcSDavid Brownell return ret; 23854367cfdcSDavid Brownell } 23864367cfdcSDavid Brownell EXPORT_SYMBOL_GPL(regulator_list_voltage); 23874367cfdcSDavid Brownell 23884367cfdcSDavid Brownell /** 238904eca28cSTuomas Tynkkynen * regulator_get_regmap - get the regulator's register map 239004eca28cSTuomas Tynkkynen * @regulator: regulator source 239104eca28cSTuomas Tynkkynen * 239204eca28cSTuomas Tynkkynen * Returns the register map for the given regulator, or an ERR_PTR value 239304eca28cSTuomas Tynkkynen * if the regulator doesn't use regmap. 239404eca28cSTuomas Tynkkynen */ 239504eca28cSTuomas Tynkkynen struct regmap *regulator_get_regmap(struct regulator *regulator) 239604eca28cSTuomas Tynkkynen { 239704eca28cSTuomas Tynkkynen struct regmap *map = regulator->rdev->regmap; 239804eca28cSTuomas Tynkkynen 239904eca28cSTuomas Tynkkynen return map ? map : ERR_PTR(-EOPNOTSUPP); 240004eca28cSTuomas Tynkkynen } 240104eca28cSTuomas Tynkkynen 240204eca28cSTuomas Tynkkynen /** 240304eca28cSTuomas Tynkkynen * regulator_get_hardware_vsel_register - get the HW voltage selector register 240404eca28cSTuomas Tynkkynen * @regulator: regulator source 240504eca28cSTuomas Tynkkynen * @vsel_reg: voltage selector register, output parameter 240604eca28cSTuomas Tynkkynen * @vsel_mask: mask for voltage selector bitfield, output parameter 240704eca28cSTuomas Tynkkynen * 240804eca28cSTuomas Tynkkynen * Returns the hardware register offset and bitmask used for setting the 240904eca28cSTuomas Tynkkynen * regulator voltage. This might be useful when configuring voltage-scaling 241004eca28cSTuomas Tynkkynen * hardware or firmware that can make I2C requests behind the kernel's back, 241104eca28cSTuomas Tynkkynen * for example. 241204eca28cSTuomas Tynkkynen * 241304eca28cSTuomas Tynkkynen * On success, the output parameters @vsel_reg and @vsel_mask are filled in 241404eca28cSTuomas Tynkkynen * and 0 is returned, otherwise a negative errno is returned. 241504eca28cSTuomas Tynkkynen */ 241604eca28cSTuomas Tynkkynen int regulator_get_hardware_vsel_register(struct regulator *regulator, 241704eca28cSTuomas Tynkkynen unsigned *vsel_reg, 241804eca28cSTuomas Tynkkynen unsigned *vsel_mask) 241904eca28cSTuomas Tynkkynen { 242004eca28cSTuomas Tynkkynen struct regulator_dev *rdev = regulator->rdev; 242139f5460dSGuodong Xu const struct regulator_ops *ops = rdev->desc->ops; 242204eca28cSTuomas Tynkkynen 242304eca28cSTuomas Tynkkynen if (ops->set_voltage_sel != regulator_set_voltage_sel_regmap) 242404eca28cSTuomas Tynkkynen return -EOPNOTSUPP; 242504eca28cSTuomas Tynkkynen 242604eca28cSTuomas Tynkkynen *vsel_reg = rdev->desc->vsel_reg; 242704eca28cSTuomas Tynkkynen *vsel_mask = rdev->desc->vsel_mask; 242804eca28cSTuomas Tynkkynen 242904eca28cSTuomas Tynkkynen return 0; 243004eca28cSTuomas Tynkkynen } 243104eca28cSTuomas Tynkkynen EXPORT_SYMBOL_GPL(regulator_get_hardware_vsel_register); 243204eca28cSTuomas Tynkkynen 243304eca28cSTuomas Tynkkynen /** 243404eca28cSTuomas Tynkkynen * regulator_list_hardware_vsel - get the HW-specific register value for a selector 243504eca28cSTuomas Tynkkynen * @regulator: regulator source 243604eca28cSTuomas Tynkkynen * @selector: identify voltage to list 243704eca28cSTuomas Tynkkynen * 243804eca28cSTuomas Tynkkynen * Converts the selector to a hardware-specific voltage selector that can be 243904eca28cSTuomas Tynkkynen * directly written to the regulator registers. The address of the voltage 244004eca28cSTuomas Tynkkynen * register can be determined by calling @regulator_get_hardware_vsel_register. 244104eca28cSTuomas Tynkkynen * 244204eca28cSTuomas Tynkkynen * On error a negative errno is returned. 244304eca28cSTuomas Tynkkynen */ 244404eca28cSTuomas Tynkkynen int regulator_list_hardware_vsel(struct regulator *regulator, 244504eca28cSTuomas Tynkkynen unsigned selector) 244604eca28cSTuomas Tynkkynen { 244704eca28cSTuomas Tynkkynen struct regulator_dev *rdev = regulator->rdev; 244839f5460dSGuodong Xu const struct regulator_ops *ops = rdev->desc->ops; 244904eca28cSTuomas Tynkkynen 245004eca28cSTuomas Tynkkynen if (selector >= rdev->desc->n_voltages) 245104eca28cSTuomas Tynkkynen return -EINVAL; 245204eca28cSTuomas Tynkkynen if (ops->set_voltage_sel != regulator_set_voltage_sel_regmap) 245304eca28cSTuomas Tynkkynen return -EOPNOTSUPP; 245404eca28cSTuomas Tynkkynen 245504eca28cSTuomas Tynkkynen return selector; 245604eca28cSTuomas Tynkkynen } 245704eca28cSTuomas Tynkkynen EXPORT_SYMBOL_GPL(regulator_list_hardware_vsel); 245804eca28cSTuomas Tynkkynen 245904eca28cSTuomas Tynkkynen /** 24602a668a8bSPaul Walmsley * regulator_get_linear_step - return the voltage step size between VSEL values 24612a668a8bSPaul Walmsley * @regulator: regulator source 24622a668a8bSPaul Walmsley * 24632a668a8bSPaul Walmsley * Returns the voltage step size between VSEL values for linear 24642a668a8bSPaul Walmsley * regulators, or return 0 if the regulator isn't a linear regulator. 24652a668a8bSPaul Walmsley */ 24662a668a8bSPaul Walmsley unsigned int regulator_get_linear_step(struct regulator *regulator) 24672a668a8bSPaul Walmsley { 24682a668a8bSPaul Walmsley struct regulator_dev *rdev = regulator->rdev; 24692a668a8bSPaul Walmsley 24702a668a8bSPaul Walmsley return rdev->desc->uV_step; 24712a668a8bSPaul Walmsley } 24722a668a8bSPaul Walmsley EXPORT_SYMBOL_GPL(regulator_get_linear_step); 24732a668a8bSPaul Walmsley 24742a668a8bSPaul Walmsley /** 2475a7a1ad90SMark Brown * regulator_is_supported_voltage - check if a voltage range can be supported 2476a7a1ad90SMark Brown * 2477a7a1ad90SMark Brown * @regulator: Regulator to check. 2478a7a1ad90SMark Brown * @min_uV: Minimum required voltage in uV. 2479a7a1ad90SMark Brown * @max_uV: Maximum required voltage in uV. 2480a7a1ad90SMark Brown * 2481a7a1ad90SMark Brown * Returns a boolean or a negative error code. 2482a7a1ad90SMark Brown */ 2483a7a1ad90SMark Brown int regulator_is_supported_voltage(struct regulator *regulator, 2484a7a1ad90SMark Brown int min_uV, int max_uV) 2485a7a1ad90SMark Brown { 2486c5f3939bSMark Brown struct regulator_dev *rdev = regulator->rdev; 2487a7a1ad90SMark Brown int i, voltages, ret; 2488a7a1ad90SMark Brown 2489c5f3939bSMark Brown /* If we can't change voltage check the current voltage */ 2490c5f3939bSMark Brown if (!(rdev->constraints->valid_ops_mask & REGULATOR_CHANGE_VOLTAGE)) { 2491c5f3939bSMark Brown ret = regulator_get_voltage(regulator); 2492c5f3939bSMark Brown if (ret >= 0) 24930d25d09dSJingoo Han return min_uV <= ret && ret <= max_uV; 2494c5f3939bSMark Brown else 2495c5f3939bSMark Brown return ret; 2496c5f3939bSMark Brown } 2497c5f3939bSMark Brown 2498bd7a2b60SPawel Moll /* Any voltage within constrains range is fine? */ 2499bd7a2b60SPawel Moll if (rdev->desc->continuous_voltage_range) 2500bd7a2b60SPawel Moll return min_uV >= rdev->constraints->min_uV && 2501bd7a2b60SPawel Moll max_uV <= rdev->constraints->max_uV; 2502bd7a2b60SPawel Moll 2503a7a1ad90SMark Brown ret = regulator_count_voltages(regulator); 2504a7a1ad90SMark Brown if (ret < 0) 2505a7a1ad90SMark Brown return ret; 2506a7a1ad90SMark Brown voltages = ret; 2507a7a1ad90SMark Brown 2508a7a1ad90SMark Brown for (i = 0; i < voltages; i++) { 2509a7a1ad90SMark Brown ret = regulator_list_voltage(regulator, i); 2510a7a1ad90SMark Brown 2511a7a1ad90SMark Brown if (ret >= min_uV && ret <= max_uV) 2512a7a1ad90SMark Brown return 1; 2513a7a1ad90SMark Brown } 2514a7a1ad90SMark Brown 2515a7a1ad90SMark Brown return 0; 2516a7a1ad90SMark Brown } 2517a398eaa2SMark Brown EXPORT_SYMBOL_GPL(regulator_is_supported_voltage); 2518a7a1ad90SMark Brown 25197179569aSHeiko Stübner static int _regulator_call_set_voltage(struct regulator_dev *rdev, 25207179569aSHeiko Stübner int min_uV, int max_uV, 25217179569aSHeiko Stübner unsigned *selector) 25227179569aSHeiko Stübner { 25237179569aSHeiko Stübner struct pre_voltage_change_data data; 25247179569aSHeiko Stübner int ret; 25257179569aSHeiko Stübner 25267179569aSHeiko Stübner data.old_uV = _regulator_get_voltage(rdev); 25277179569aSHeiko Stübner data.min_uV = min_uV; 25287179569aSHeiko Stübner data.max_uV = max_uV; 25297179569aSHeiko Stübner ret = _notifier_call_chain(rdev, REGULATOR_EVENT_PRE_VOLTAGE_CHANGE, 25307179569aSHeiko Stübner &data); 25317179569aSHeiko Stübner if (ret & NOTIFY_STOP_MASK) 25327179569aSHeiko Stübner return -EINVAL; 25337179569aSHeiko Stübner 25347179569aSHeiko Stübner ret = rdev->desc->ops->set_voltage(rdev, min_uV, max_uV, selector); 25357179569aSHeiko Stübner if (ret >= 0) 25367179569aSHeiko Stübner return ret; 25377179569aSHeiko Stübner 25387179569aSHeiko Stübner _notifier_call_chain(rdev, REGULATOR_EVENT_ABORT_VOLTAGE_CHANGE, 25397179569aSHeiko Stübner (void *)data.old_uV); 25407179569aSHeiko Stübner 25417179569aSHeiko Stübner return ret; 25427179569aSHeiko Stübner } 25437179569aSHeiko Stübner 25447179569aSHeiko Stübner static int _regulator_call_set_voltage_sel(struct regulator_dev *rdev, 25457179569aSHeiko Stübner int uV, unsigned selector) 25467179569aSHeiko Stübner { 25477179569aSHeiko Stübner struct pre_voltage_change_data data; 25487179569aSHeiko Stübner int ret; 25497179569aSHeiko Stübner 25507179569aSHeiko Stübner data.old_uV = _regulator_get_voltage(rdev); 25517179569aSHeiko Stübner data.min_uV = uV; 25527179569aSHeiko Stübner data.max_uV = uV; 25537179569aSHeiko Stübner ret = _notifier_call_chain(rdev, REGULATOR_EVENT_PRE_VOLTAGE_CHANGE, 25547179569aSHeiko Stübner &data); 25557179569aSHeiko Stübner if (ret & NOTIFY_STOP_MASK) 25567179569aSHeiko Stübner return -EINVAL; 25577179569aSHeiko Stübner 25587179569aSHeiko Stübner ret = rdev->desc->ops->set_voltage_sel(rdev, selector); 25597179569aSHeiko Stübner if (ret >= 0) 25607179569aSHeiko Stübner return ret; 25617179569aSHeiko Stübner 25627179569aSHeiko Stübner _notifier_call_chain(rdev, REGULATOR_EVENT_ABORT_VOLTAGE_CHANGE, 25637179569aSHeiko Stübner (void *)data.old_uV); 25647179569aSHeiko Stübner 25657179569aSHeiko Stübner return ret; 25667179569aSHeiko Stübner } 25677179569aSHeiko Stübner 256875790251SMark Brown static int _regulator_do_set_voltage(struct regulator_dev *rdev, 256975790251SMark Brown int min_uV, int max_uV) 257075790251SMark Brown { 257175790251SMark Brown int ret; 257277af1b26SLinus Walleij int delay = 0; 2573e113d792SMark Brown int best_val = 0; 257475790251SMark Brown unsigned int selector; 2575eba41a5eSAxel Lin int old_selector = -1; 257675790251SMark Brown 257775790251SMark Brown trace_regulator_set_voltage(rdev_get_name(rdev), min_uV, max_uV); 257875790251SMark Brown 2579bf5892a8SMark Brown min_uV += rdev->constraints->uV_offset; 2580bf5892a8SMark Brown max_uV += rdev->constraints->uV_offset; 2581bf5892a8SMark Brown 258277af1b26SLinus Walleij /* 258377af1b26SLinus Walleij * If we can't obtain the old selector there is not enough 258477af1b26SLinus Walleij * info to call set_voltage_time_sel(). 258577af1b26SLinus Walleij */ 25868b7485efSAxel Lin if (_regulator_is_enabled(rdev) && 25878b7485efSAxel Lin rdev->desc->ops->set_voltage_time_sel && 258877af1b26SLinus Walleij rdev->desc->ops->get_voltage_sel) { 2589eba41a5eSAxel Lin old_selector = rdev->desc->ops->get_voltage_sel(rdev); 2590eba41a5eSAxel Lin if (old_selector < 0) 2591eba41a5eSAxel Lin return old_selector; 2592eba41a5eSAxel Lin } 259377af1b26SLinus Walleij 259475790251SMark Brown if (rdev->desc->ops->set_voltage) { 25957179569aSHeiko Stübner ret = _regulator_call_set_voltage(rdev, min_uV, max_uV, 259675790251SMark Brown &selector); 2597e113d792SMark Brown 2598e113d792SMark Brown if (ret >= 0) { 2599e113d792SMark Brown if (rdev->desc->ops->list_voltage) 2600e113d792SMark Brown best_val = rdev->desc->ops->list_voltage(rdev, 2601e113d792SMark Brown selector); 2602e113d792SMark Brown else 2603e113d792SMark Brown best_val = _regulator_get_voltage(rdev); 2604e113d792SMark Brown } 2605e113d792SMark Brown 2606e8eef82bSMark Brown } else if (rdev->desc->ops->set_voltage_sel) { 26079152c36aSAxel Lin if (rdev->desc->ops->map_voltage) { 2608e843fc46SMark Brown ret = rdev->desc->ops->map_voltage(rdev, min_uV, 2609e843fc46SMark Brown max_uV); 26109152c36aSAxel Lin } else { 26119152c36aSAxel Lin if (rdev->desc->ops->list_voltage == 26129152c36aSAxel Lin regulator_list_voltage_linear) 26139152c36aSAxel Lin ret = regulator_map_voltage_linear(rdev, 26149152c36aSAxel Lin min_uV, max_uV); 261536698627SAxel Lin else if (rdev->desc->ops->list_voltage == 261636698627SAxel Lin regulator_list_voltage_linear_range) 261736698627SAxel Lin ret = regulator_map_voltage_linear_range(rdev, 261836698627SAxel Lin min_uV, max_uV); 261907351233SAxel Lin else 26209152c36aSAxel Lin ret = regulator_map_voltage_iterate(rdev, 26219152c36aSAxel Lin min_uV, max_uV); 26229152c36aSAxel Lin } 2623e843fc46SMark Brown 2624e843fc46SMark Brown if (ret >= 0) { 2625e113d792SMark Brown best_val = rdev->desc->ops->list_voltage(rdev, ret); 2626e113d792SMark Brown if (min_uV <= best_val && max_uV >= best_val) { 2627e843fc46SMark Brown selector = ret; 2628c66a566aSAxel Lin if (old_selector == selector) 2629c66a566aSAxel Lin ret = 0; 2630c66a566aSAxel Lin else 26317179569aSHeiko Stübner ret = _regulator_call_set_voltage_sel( 26327179569aSHeiko Stübner rdev, best_val, selector); 2633e113d792SMark Brown } else { 2634e113d792SMark Brown ret = -EINVAL; 2635e113d792SMark Brown } 2636e843fc46SMark Brown } 2637e8eef82bSMark Brown } else { 2638e8eef82bSMark Brown ret = -EINVAL; 2639e8eef82bSMark Brown } 2640e8eef82bSMark Brown 2641eba41a5eSAxel Lin /* Call set_voltage_time_sel if successfully obtained old_selector */ 26425b175952SYadwinder Singh Brar if (ret == 0 && !rdev->constraints->ramp_disable && old_selector >= 0 26435b175952SYadwinder Singh Brar && old_selector != selector) { 2644eba41a5eSAxel Lin 2645eba41a5eSAxel Lin delay = rdev->desc->ops->set_voltage_time_sel(rdev, 2646eba41a5eSAxel Lin old_selector, selector); 2647eba41a5eSAxel Lin if (delay < 0) { 2648eba41a5eSAxel Lin rdev_warn(rdev, "set_voltage_time_sel() failed: %d\n", 2649eba41a5eSAxel Lin delay); 2650eba41a5eSAxel Lin delay = 0; 2651e8eef82bSMark Brown } 265275790251SMark Brown 265377af1b26SLinus Walleij /* Insert any necessary delays */ 265477af1b26SLinus Walleij if (delay >= 1000) { 265577af1b26SLinus Walleij mdelay(delay / 1000); 265677af1b26SLinus Walleij udelay(delay % 1000); 265777af1b26SLinus Walleij } else if (delay) { 265877af1b26SLinus Walleij udelay(delay); 265977af1b26SLinus Walleij } 26608b96de31SPhilip Rakity } 266177af1b26SLinus Walleij 26622f6c797fSAxel Lin if (ret == 0 && best_val >= 0) { 26632f6c797fSAxel Lin unsigned long data = best_val; 26642f6c797fSAxel Lin 2665ded06a52SMark Brown _notifier_call_chain(rdev, REGULATOR_EVENT_VOLTAGE_CHANGE, 26662f6c797fSAxel Lin (void *)data); 26672f6c797fSAxel Lin } 2668ded06a52SMark Brown 2669eba41a5eSAxel Lin trace_regulator_set_voltage_complete(rdev_get_name(rdev), best_val); 267075790251SMark Brown 267175790251SMark Brown return ret; 267275790251SMark Brown } 267375790251SMark Brown 2674a7a1ad90SMark Brown /** 2675414c70cbSLiam Girdwood * regulator_set_voltage - set regulator output voltage 2676414c70cbSLiam Girdwood * @regulator: regulator source 2677414c70cbSLiam Girdwood * @min_uV: Minimum required voltage in uV 2678414c70cbSLiam Girdwood * @max_uV: Maximum acceptable voltage in uV 2679414c70cbSLiam Girdwood * 2680414c70cbSLiam Girdwood * Sets a voltage regulator to the desired output voltage. This can be set 2681414c70cbSLiam Girdwood * during any regulator state. IOW, regulator can be disabled or enabled. 2682414c70cbSLiam Girdwood * 2683414c70cbSLiam Girdwood * If the regulator is enabled then the voltage will change to the new value 2684414c70cbSLiam Girdwood * immediately otherwise if the regulator is disabled the regulator will 2685414c70cbSLiam Girdwood * output at the new voltage when enabled. 2686414c70cbSLiam Girdwood * 2687414c70cbSLiam Girdwood * NOTE: If the regulator is shared between several devices then the lowest 2688414c70cbSLiam Girdwood * request voltage that meets the system constraints will be used. 268969279fb9SMark Brown * Regulator system constraints must be set for this regulator before 2690414c70cbSLiam Girdwood * calling this function otherwise this call will fail. 2691414c70cbSLiam Girdwood */ 2692414c70cbSLiam Girdwood int regulator_set_voltage(struct regulator *regulator, int min_uV, int max_uV) 2693414c70cbSLiam Girdwood { 2694414c70cbSLiam Girdwood struct regulator_dev *rdev = regulator->rdev; 269595a3c23aSMark Brown int ret = 0; 269692d7a558SPaolo Pisati int old_min_uV, old_max_uV; 2697c00dc359SBjorn Andersson int current_uV; 2698414c70cbSLiam Girdwood 2699414c70cbSLiam Girdwood mutex_lock(&rdev->mutex); 2700414c70cbSLiam Girdwood 270195a3c23aSMark Brown /* If we're setting the same range as last time the change 270295a3c23aSMark Brown * should be a noop (some cpufreq implementations use the same 270395a3c23aSMark Brown * voltage for multiple frequencies, for example). 270495a3c23aSMark Brown */ 270595a3c23aSMark Brown if (regulator->min_uV == min_uV && regulator->max_uV == max_uV) 270695a3c23aSMark Brown goto out; 270795a3c23aSMark Brown 2708c00dc359SBjorn Andersson /* If we're trying to set a range that overlaps the current voltage, 2709c00dc359SBjorn Andersson * return succesfully even though the regulator does not support 2710c00dc359SBjorn Andersson * changing the voltage. 2711c00dc359SBjorn Andersson */ 2712c00dc359SBjorn Andersson if (!(rdev->constraints->valid_ops_mask & REGULATOR_CHANGE_VOLTAGE)) { 2713c00dc359SBjorn Andersson current_uV = _regulator_get_voltage(rdev); 2714c00dc359SBjorn Andersson if (min_uV <= current_uV && current_uV <= max_uV) { 2715c00dc359SBjorn Andersson regulator->min_uV = min_uV; 2716c00dc359SBjorn Andersson regulator->max_uV = max_uV; 2717c00dc359SBjorn Andersson goto out; 2718c00dc359SBjorn Andersson } 2719c00dc359SBjorn Andersson } 2720c00dc359SBjorn Andersson 2721414c70cbSLiam Girdwood /* sanity check */ 2722e8eef82bSMark Brown if (!rdev->desc->ops->set_voltage && 2723e8eef82bSMark Brown !rdev->desc->ops->set_voltage_sel) { 2724414c70cbSLiam Girdwood ret = -EINVAL; 2725414c70cbSLiam Girdwood goto out; 2726414c70cbSLiam Girdwood } 2727414c70cbSLiam Girdwood 2728414c70cbSLiam Girdwood /* constraints check */ 2729414c70cbSLiam Girdwood ret = regulator_check_voltage(rdev, &min_uV, &max_uV); 2730414c70cbSLiam Girdwood if (ret < 0) 2731414c70cbSLiam Girdwood goto out; 273292d7a558SPaolo Pisati 273392d7a558SPaolo Pisati /* restore original values in case of error */ 273492d7a558SPaolo Pisati old_min_uV = regulator->min_uV; 273592d7a558SPaolo Pisati old_max_uV = regulator->max_uV; 2736414c70cbSLiam Girdwood regulator->min_uV = min_uV; 2737414c70cbSLiam Girdwood regulator->max_uV = max_uV; 27383a93f2a9SMark Brown 273905fda3b1SThomas Petazzoni ret = regulator_check_consumers(rdev, &min_uV, &max_uV); 274005fda3b1SThomas Petazzoni if (ret < 0) 274192d7a558SPaolo Pisati goto out2; 274205fda3b1SThomas Petazzoni 274375790251SMark Brown ret = _regulator_do_set_voltage(rdev, min_uV, max_uV); 274492d7a558SPaolo Pisati if (ret < 0) 274592d7a558SPaolo Pisati goto out2; 274602fa3ec0SMark Brown 2747414c70cbSLiam Girdwood out: 2748414c70cbSLiam Girdwood mutex_unlock(&rdev->mutex); 2749414c70cbSLiam Girdwood return ret; 275092d7a558SPaolo Pisati out2: 275192d7a558SPaolo Pisati regulator->min_uV = old_min_uV; 275292d7a558SPaolo Pisati regulator->max_uV = old_max_uV; 275392d7a558SPaolo Pisati mutex_unlock(&rdev->mutex); 275492d7a558SPaolo Pisati return ret; 2755414c70cbSLiam Girdwood } 2756414c70cbSLiam Girdwood EXPORT_SYMBOL_GPL(regulator_set_voltage); 2757414c70cbSLiam Girdwood 2758606a2562SMark Brown /** 275988cd222bSLinus Walleij * regulator_set_voltage_time - get raise/fall time 276088cd222bSLinus Walleij * @regulator: regulator source 276188cd222bSLinus Walleij * @old_uV: starting voltage in microvolts 276288cd222bSLinus Walleij * @new_uV: target voltage in microvolts 276388cd222bSLinus Walleij * 276488cd222bSLinus Walleij * Provided with the starting and ending voltage, this function attempts to 276588cd222bSLinus Walleij * calculate the time in microseconds required to rise or fall to this new 276688cd222bSLinus Walleij * voltage. 276788cd222bSLinus Walleij */ 276888cd222bSLinus Walleij int regulator_set_voltage_time(struct regulator *regulator, 276988cd222bSLinus Walleij int old_uV, int new_uV) 277088cd222bSLinus Walleij { 277188cd222bSLinus Walleij struct regulator_dev *rdev = regulator->rdev; 2772272e2315SGuodong Xu const struct regulator_ops *ops = rdev->desc->ops; 277388cd222bSLinus Walleij int old_sel = -1; 277488cd222bSLinus Walleij int new_sel = -1; 277588cd222bSLinus Walleij int voltage; 277688cd222bSLinus Walleij int i; 277788cd222bSLinus Walleij 277888cd222bSLinus Walleij /* Currently requires operations to do this */ 277988cd222bSLinus Walleij if (!ops->list_voltage || !ops->set_voltage_time_sel 278088cd222bSLinus Walleij || !rdev->desc->n_voltages) 278188cd222bSLinus Walleij return -EINVAL; 278288cd222bSLinus Walleij 278388cd222bSLinus Walleij for (i = 0; i < rdev->desc->n_voltages; i++) { 278488cd222bSLinus Walleij /* We only look for exact voltage matches here */ 278588cd222bSLinus Walleij voltage = regulator_list_voltage(regulator, i); 278688cd222bSLinus Walleij if (voltage < 0) 278788cd222bSLinus Walleij return -EINVAL; 278888cd222bSLinus Walleij if (voltage == 0) 278988cd222bSLinus Walleij continue; 279088cd222bSLinus Walleij if (voltage == old_uV) 279188cd222bSLinus Walleij old_sel = i; 279288cd222bSLinus Walleij if (voltage == new_uV) 279388cd222bSLinus Walleij new_sel = i; 279488cd222bSLinus Walleij } 279588cd222bSLinus Walleij 279688cd222bSLinus Walleij if (old_sel < 0 || new_sel < 0) 279788cd222bSLinus Walleij return -EINVAL; 279888cd222bSLinus Walleij 279988cd222bSLinus Walleij return ops->set_voltage_time_sel(rdev, old_sel, new_sel); 280088cd222bSLinus Walleij } 280188cd222bSLinus Walleij EXPORT_SYMBOL_GPL(regulator_set_voltage_time); 280288cd222bSLinus Walleij 280388cd222bSLinus Walleij /** 280498a175b6SYadwinder Singh Brar * regulator_set_voltage_time_sel - get raise/fall time 2805296c6566SRandy Dunlap * @rdev: regulator source device 280698a175b6SYadwinder Singh Brar * @old_selector: selector for starting voltage 280798a175b6SYadwinder Singh Brar * @new_selector: selector for target voltage 280898a175b6SYadwinder Singh Brar * 280998a175b6SYadwinder Singh Brar * Provided with the starting and target voltage selectors, this function 281098a175b6SYadwinder Singh Brar * returns time in microseconds required to rise or fall to this new voltage 281198a175b6SYadwinder Singh Brar * 2812f11d08c3SAxel Lin * Drivers providing ramp_delay in regulation_constraints can use this as their 2813398715abSAxel Lin * set_voltage_time_sel() operation. 281498a175b6SYadwinder Singh Brar */ 281598a175b6SYadwinder Singh Brar int regulator_set_voltage_time_sel(struct regulator_dev *rdev, 281698a175b6SYadwinder Singh Brar unsigned int old_selector, 281798a175b6SYadwinder Singh Brar unsigned int new_selector) 281898a175b6SYadwinder Singh Brar { 2819398715abSAxel Lin unsigned int ramp_delay = 0; 2820f11d08c3SAxel Lin int old_volt, new_volt; 2821398715abSAxel Lin 28226f0b2c69SYadwinder Singh Brar if (rdev->constraints->ramp_delay) 2823398715abSAxel Lin ramp_delay = rdev->constraints->ramp_delay; 2824398715abSAxel Lin else if (rdev->desc->ramp_delay) 2825398715abSAxel Lin ramp_delay = rdev->desc->ramp_delay; 2826398715abSAxel Lin 2827398715abSAxel Lin if (ramp_delay == 0) { 28286f0b2c69SYadwinder Singh Brar rdev_warn(rdev, "ramp_delay not set\n"); 2829398715abSAxel Lin return 0; 28306f0b2c69SYadwinder Singh Brar } 2831398715abSAxel Lin 2832f11d08c3SAxel Lin /* sanity check */ 2833f11d08c3SAxel Lin if (!rdev->desc->ops->list_voltage) 2834f11d08c3SAxel Lin return -EINVAL; 2835398715abSAxel Lin 2836f11d08c3SAxel Lin old_volt = rdev->desc->ops->list_voltage(rdev, old_selector); 2837f11d08c3SAxel Lin new_volt = rdev->desc->ops->list_voltage(rdev, new_selector); 2838f11d08c3SAxel Lin 2839f11d08c3SAxel Lin return DIV_ROUND_UP(abs(new_volt - old_volt), ramp_delay); 284098a175b6SYadwinder Singh Brar } 2841b19dbf71SMark Brown EXPORT_SYMBOL_GPL(regulator_set_voltage_time_sel); 284298a175b6SYadwinder Singh Brar 284398a175b6SYadwinder Singh Brar /** 2844606a2562SMark Brown * regulator_sync_voltage - re-apply last regulator output voltage 2845606a2562SMark Brown * @regulator: regulator source 2846606a2562SMark Brown * 2847606a2562SMark Brown * Re-apply the last configured voltage. This is intended to be used 2848606a2562SMark Brown * where some external control source the consumer is cooperating with 2849606a2562SMark Brown * has caused the configured voltage to change. 2850606a2562SMark Brown */ 2851606a2562SMark Brown int regulator_sync_voltage(struct regulator *regulator) 2852606a2562SMark Brown { 2853606a2562SMark Brown struct regulator_dev *rdev = regulator->rdev; 2854606a2562SMark Brown int ret, min_uV, max_uV; 2855606a2562SMark Brown 2856606a2562SMark Brown mutex_lock(&rdev->mutex); 2857606a2562SMark Brown 2858606a2562SMark Brown if (!rdev->desc->ops->set_voltage && 2859606a2562SMark Brown !rdev->desc->ops->set_voltage_sel) { 2860606a2562SMark Brown ret = -EINVAL; 2861606a2562SMark Brown goto out; 2862606a2562SMark Brown } 2863606a2562SMark Brown 2864606a2562SMark Brown /* This is only going to work if we've had a voltage configured. */ 2865606a2562SMark Brown if (!regulator->min_uV && !regulator->max_uV) { 2866606a2562SMark Brown ret = -EINVAL; 2867606a2562SMark Brown goto out; 2868606a2562SMark Brown } 2869606a2562SMark Brown 2870606a2562SMark Brown min_uV = regulator->min_uV; 2871606a2562SMark Brown max_uV = regulator->max_uV; 2872606a2562SMark Brown 2873606a2562SMark Brown /* This should be a paranoia check... */ 2874606a2562SMark Brown ret = regulator_check_voltage(rdev, &min_uV, &max_uV); 2875606a2562SMark Brown if (ret < 0) 2876606a2562SMark Brown goto out; 2877606a2562SMark Brown 2878606a2562SMark Brown ret = regulator_check_consumers(rdev, &min_uV, &max_uV); 2879606a2562SMark Brown if (ret < 0) 2880606a2562SMark Brown goto out; 2881606a2562SMark Brown 2882606a2562SMark Brown ret = _regulator_do_set_voltage(rdev, min_uV, max_uV); 2883606a2562SMark Brown 2884606a2562SMark Brown out: 2885606a2562SMark Brown mutex_unlock(&rdev->mutex); 2886606a2562SMark Brown return ret; 2887606a2562SMark Brown } 2888606a2562SMark Brown EXPORT_SYMBOL_GPL(regulator_sync_voltage); 2889606a2562SMark Brown 2890414c70cbSLiam Girdwood static int _regulator_get_voltage(struct regulator_dev *rdev) 2891414c70cbSLiam Girdwood { 2892bf5892a8SMark Brown int sel, ret; 2893476c2d83SMark Brown 2894476c2d83SMark Brown if (rdev->desc->ops->get_voltage_sel) { 2895476c2d83SMark Brown sel = rdev->desc->ops->get_voltage_sel(rdev); 2896476c2d83SMark Brown if (sel < 0) 2897476c2d83SMark Brown return sel; 2898bf5892a8SMark Brown ret = rdev->desc->ops->list_voltage(rdev, sel); 2899cb220d16SAxel Lin } else if (rdev->desc->ops->get_voltage) { 2900bf5892a8SMark Brown ret = rdev->desc->ops->get_voltage(rdev); 2901f7df20ecSMark Brown } else if (rdev->desc->ops->list_voltage) { 2902f7df20ecSMark Brown ret = rdev->desc->ops->list_voltage(rdev, 0); 29035a523605SLaxman Dewangan } else if (rdev->desc->fixed_uV && (rdev->desc->n_voltages == 1)) { 29045a523605SLaxman Dewangan ret = rdev->desc->fixed_uV; 2905e303996eSJavier Martinez Canillas } else if (rdev->supply) { 2906e303996eSJavier Martinez Canillas ret = regulator_get_voltage(rdev->supply); 2907cb220d16SAxel Lin } else { 2908414c70cbSLiam Girdwood return -EINVAL; 2909cb220d16SAxel Lin } 2910bf5892a8SMark Brown 2911cb220d16SAxel Lin if (ret < 0) 2912cb220d16SAxel Lin return ret; 2913bf5892a8SMark Brown return ret - rdev->constraints->uV_offset; 2914414c70cbSLiam Girdwood } 2915414c70cbSLiam Girdwood 2916414c70cbSLiam Girdwood /** 2917414c70cbSLiam Girdwood * regulator_get_voltage - get regulator output voltage 2918414c70cbSLiam Girdwood * @regulator: regulator source 2919414c70cbSLiam Girdwood * 2920414c70cbSLiam Girdwood * This returns the current regulator voltage in uV. 2921414c70cbSLiam Girdwood * 2922414c70cbSLiam Girdwood * NOTE: If the regulator is disabled it will return the voltage value. This 2923414c70cbSLiam Girdwood * function should not be used to determine regulator state. 2924414c70cbSLiam Girdwood */ 2925414c70cbSLiam Girdwood int regulator_get_voltage(struct regulator *regulator) 2926414c70cbSLiam Girdwood { 2927414c70cbSLiam Girdwood int ret; 2928414c70cbSLiam Girdwood 2929414c70cbSLiam Girdwood mutex_lock(®ulator->rdev->mutex); 2930414c70cbSLiam Girdwood 2931414c70cbSLiam Girdwood ret = _regulator_get_voltage(regulator->rdev); 2932414c70cbSLiam Girdwood 2933414c70cbSLiam Girdwood mutex_unlock(®ulator->rdev->mutex); 2934414c70cbSLiam Girdwood 2935414c70cbSLiam Girdwood return ret; 2936414c70cbSLiam Girdwood } 2937414c70cbSLiam Girdwood EXPORT_SYMBOL_GPL(regulator_get_voltage); 2938414c70cbSLiam Girdwood 2939414c70cbSLiam Girdwood /** 2940414c70cbSLiam Girdwood * regulator_set_current_limit - set regulator output current limit 2941414c70cbSLiam Girdwood * @regulator: regulator source 2942ce0d10f8SCharles Keepax * @min_uA: Minimum supported current in uA 2943414c70cbSLiam Girdwood * @max_uA: Maximum supported current in uA 2944414c70cbSLiam Girdwood * 2945414c70cbSLiam Girdwood * Sets current sink to the desired output current. This can be set during 2946414c70cbSLiam Girdwood * any regulator state. IOW, regulator can be disabled or enabled. 2947414c70cbSLiam Girdwood * 2948414c70cbSLiam Girdwood * If the regulator is enabled then the current will change to the new value 2949414c70cbSLiam Girdwood * immediately otherwise if the regulator is disabled the regulator will 2950414c70cbSLiam Girdwood * output at the new current when enabled. 2951414c70cbSLiam Girdwood * 2952414c70cbSLiam Girdwood * NOTE: Regulator system constraints must be set for this regulator before 2953414c70cbSLiam Girdwood * calling this function otherwise this call will fail. 2954414c70cbSLiam Girdwood */ 2955414c70cbSLiam Girdwood int regulator_set_current_limit(struct regulator *regulator, 2956414c70cbSLiam Girdwood int min_uA, int max_uA) 2957414c70cbSLiam Girdwood { 2958414c70cbSLiam Girdwood struct regulator_dev *rdev = regulator->rdev; 2959414c70cbSLiam Girdwood int ret; 2960414c70cbSLiam Girdwood 2961414c70cbSLiam Girdwood mutex_lock(&rdev->mutex); 2962414c70cbSLiam Girdwood 2963414c70cbSLiam Girdwood /* sanity check */ 2964414c70cbSLiam Girdwood if (!rdev->desc->ops->set_current_limit) { 2965414c70cbSLiam Girdwood ret = -EINVAL; 2966414c70cbSLiam Girdwood goto out; 2967414c70cbSLiam Girdwood } 2968414c70cbSLiam Girdwood 2969414c70cbSLiam Girdwood /* constraints check */ 2970414c70cbSLiam Girdwood ret = regulator_check_current_limit(rdev, &min_uA, &max_uA); 2971414c70cbSLiam Girdwood if (ret < 0) 2972414c70cbSLiam Girdwood goto out; 2973414c70cbSLiam Girdwood 2974414c70cbSLiam Girdwood ret = rdev->desc->ops->set_current_limit(rdev, min_uA, max_uA); 2975414c70cbSLiam Girdwood out: 2976414c70cbSLiam Girdwood mutex_unlock(&rdev->mutex); 2977414c70cbSLiam Girdwood return ret; 2978414c70cbSLiam Girdwood } 2979414c70cbSLiam Girdwood EXPORT_SYMBOL_GPL(regulator_set_current_limit); 2980414c70cbSLiam Girdwood 2981414c70cbSLiam Girdwood static int _regulator_get_current_limit(struct regulator_dev *rdev) 2982414c70cbSLiam Girdwood { 2983414c70cbSLiam Girdwood int ret; 2984414c70cbSLiam Girdwood 2985414c70cbSLiam Girdwood mutex_lock(&rdev->mutex); 2986414c70cbSLiam Girdwood 2987414c70cbSLiam Girdwood /* sanity check */ 2988414c70cbSLiam Girdwood if (!rdev->desc->ops->get_current_limit) { 2989414c70cbSLiam Girdwood ret = -EINVAL; 2990414c70cbSLiam Girdwood goto out; 2991414c70cbSLiam Girdwood } 2992414c70cbSLiam Girdwood 2993414c70cbSLiam Girdwood ret = rdev->desc->ops->get_current_limit(rdev); 2994414c70cbSLiam Girdwood out: 2995414c70cbSLiam Girdwood mutex_unlock(&rdev->mutex); 2996414c70cbSLiam Girdwood return ret; 2997414c70cbSLiam Girdwood } 2998414c70cbSLiam Girdwood 2999414c70cbSLiam Girdwood /** 3000414c70cbSLiam Girdwood * regulator_get_current_limit - get regulator output current 3001414c70cbSLiam Girdwood * @regulator: regulator source 3002414c70cbSLiam Girdwood * 3003414c70cbSLiam Girdwood * This returns the current supplied by the specified current sink in uA. 3004414c70cbSLiam Girdwood * 3005414c70cbSLiam Girdwood * NOTE: If the regulator is disabled it will return the current value. This 3006414c70cbSLiam Girdwood * function should not be used to determine regulator state. 3007414c70cbSLiam Girdwood */ 3008414c70cbSLiam Girdwood int regulator_get_current_limit(struct regulator *regulator) 3009414c70cbSLiam Girdwood { 3010414c70cbSLiam Girdwood return _regulator_get_current_limit(regulator->rdev); 3011414c70cbSLiam Girdwood } 3012414c70cbSLiam Girdwood EXPORT_SYMBOL_GPL(regulator_get_current_limit); 3013414c70cbSLiam Girdwood 3014414c70cbSLiam Girdwood /** 3015414c70cbSLiam Girdwood * regulator_set_mode - set regulator operating mode 3016414c70cbSLiam Girdwood * @regulator: regulator source 3017414c70cbSLiam Girdwood * @mode: operating mode - one of the REGULATOR_MODE constants 3018414c70cbSLiam Girdwood * 3019414c70cbSLiam Girdwood * Set regulator operating mode to increase regulator efficiency or improve 3020414c70cbSLiam Girdwood * regulation performance. 3021414c70cbSLiam Girdwood * 3022414c70cbSLiam Girdwood * NOTE: Regulator system constraints must be set for this regulator before 3023414c70cbSLiam Girdwood * calling this function otherwise this call will fail. 3024414c70cbSLiam Girdwood */ 3025414c70cbSLiam Girdwood int regulator_set_mode(struct regulator *regulator, unsigned int mode) 3026414c70cbSLiam Girdwood { 3027414c70cbSLiam Girdwood struct regulator_dev *rdev = regulator->rdev; 3028414c70cbSLiam Girdwood int ret; 3029500b4ac9SSundar R Iyer int regulator_curr_mode; 3030414c70cbSLiam Girdwood 3031414c70cbSLiam Girdwood mutex_lock(&rdev->mutex); 3032414c70cbSLiam Girdwood 3033414c70cbSLiam Girdwood /* sanity check */ 3034414c70cbSLiam Girdwood if (!rdev->desc->ops->set_mode) { 3035414c70cbSLiam Girdwood ret = -EINVAL; 3036414c70cbSLiam Girdwood goto out; 3037414c70cbSLiam Girdwood } 3038414c70cbSLiam Girdwood 3039500b4ac9SSundar R Iyer /* return if the same mode is requested */ 3040500b4ac9SSundar R Iyer if (rdev->desc->ops->get_mode) { 3041500b4ac9SSundar R Iyer regulator_curr_mode = rdev->desc->ops->get_mode(rdev); 3042500b4ac9SSundar R Iyer if (regulator_curr_mode == mode) { 3043500b4ac9SSundar R Iyer ret = 0; 3044500b4ac9SSundar R Iyer goto out; 3045500b4ac9SSundar R Iyer } 3046500b4ac9SSundar R Iyer } 3047500b4ac9SSundar R Iyer 3048414c70cbSLiam Girdwood /* constraints check */ 304922c51b47SAxel Lin ret = regulator_mode_constrain(rdev, &mode); 3050414c70cbSLiam Girdwood if (ret < 0) 3051414c70cbSLiam Girdwood goto out; 3052414c70cbSLiam Girdwood 3053414c70cbSLiam Girdwood ret = rdev->desc->ops->set_mode(rdev, mode); 3054414c70cbSLiam Girdwood out: 3055414c70cbSLiam Girdwood mutex_unlock(&rdev->mutex); 3056414c70cbSLiam Girdwood return ret; 3057414c70cbSLiam Girdwood } 3058414c70cbSLiam Girdwood EXPORT_SYMBOL_GPL(regulator_set_mode); 3059414c70cbSLiam Girdwood 3060414c70cbSLiam Girdwood static unsigned int _regulator_get_mode(struct regulator_dev *rdev) 3061414c70cbSLiam Girdwood { 3062414c70cbSLiam Girdwood int ret; 3063414c70cbSLiam Girdwood 3064414c70cbSLiam Girdwood mutex_lock(&rdev->mutex); 3065414c70cbSLiam Girdwood 3066414c70cbSLiam Girdwood /* sanity check */ 3067414c70cbSLiam Girdwood if (!rdev->desc->ops->get_mode) { 3068414c70cbSLiam Girdwood ret = -EINVAL; 3069414c70cbSLiam Girdwood goto out; 3070414c70cbSLiam Girdwood } 3071414c70cbSLiam Girdwood 3072414c70cbSLiam Girdwood ret = rdev->desc->ops->get_mode(rdev); 3073414c70cbSLiam Girdwood out: 3074414c70cbSLiam Girdwood mutex_unlock(&rdev->mutex); 3075414c70cbSLiam Girdwood return ret; 3076414c70cbSLiam Girdwood } 3077414c70cbSLiam Girdwood 3078414c70cbSLiam Girdwood /** 3079414c70cbSLiam Girdwood * regulator_get_mode - get regulator operating mode 3080414c70cbSLiam Girdwood * @regulator: regulator source 3081414c70cbSLiam Girdwood * 3082414c70cbSLiam Girdwood * Get the current regulator operating mode. 3083414c70cbSLiam Girdwood */ 3084414c70cbSLiam Girdwood unsigned int regulator_get_mode(struct regulator *regulator) 3085414c70cbSLiam Girdwood { 3086414c70cbSLiam Girdwood return _regulator_get_mode(regulator->rdev); 3087414c70cbSLiam Girdwood } 3088414c70cbSLiam Girdwood EXPORT_SYMBOL_GPL(regulator_get_mode); 3089414c70cbSLiam Girdwood 3090414c70cbSLiam Girdwood /** 3091e39ce48fSBjorn Andersson * regulator_set_load - set regulator load 3092414c70cbSLiam Girdwood * @regulator: regulator source 3093414c70cbSLiam Girdwood * @uA_load: load current 3094414c70cbSLiam Girdwood * 3095414c70cbSLiam Girdwood * Notifies the regulator core of a new device load. This is then used by 3096414c70cbSLiam Girdwood * DRMS (if enabled by constraints) to set the most efficient regulator 3097414c70cbSLiam Girdwood * operating mode for the new regulator loading. 3098414c70cbSLiam Girdwood * 3099414c70cbSLiam Girdwood * Consumer devices notify their supply regulator of the maximum power 3100414c70cbSLiam Girdwood * they will require (can be taken from device datasheet in the power 3101414c70cbSLiam Girdwood * consumption tables) when they change operational status and hence power 3102414c70cbSLiam Girdwood * state. Examples of operational state changes that can affect power 3103414c70cbSLiam Girdwood * consumption are :- 3104414c70cbSLiam Girdwood * 3105414c70cbSLiam Girdwood * o Device is opened / closed. 3106414c70cbSLiam Girdwood * o Device I/O is about to begin or has just finished. 3107414c70cbSLiam Girdwood * o Device is idling in between work. 3108414c70cbSLiam Girdwood * 3109414c70cbSLiam Girdwood * This information is also exported via sysfs to userspace. 3110414c70cbSLiam Girdwood * 3111414c70cbSLiam Girdwood * DRMS will sum the total requested load on the regulator and change 3112414c70cbSLiam Girdwood * to the most efficient operating mode if platform constraints allow. 3113414c70cbSLiam Girdwood * 3114e39ce48fSBjorn Andersson * On error a negative errno is returned. 3115414c70cbSLiam Girdwood */ 3116e39ce48fSBjorn Andersson int regulator_set_load(struct regulator *regulator, int uA_load) 3117414c70cbSLiam Girdwood { 3118414c70cbSLiam Girdwood struct regulator_dev *rdev = regulator->rdev; 31198460ef38SBjorn Andersson int ret; 3120d92d95b6SStephen Boyd 3121414c70cbSLiam Girdwood mutex_lock(&rdev->mutex); 3122414c70cbSLiam Girdwood regulator->uA_load = uA_load; 31238460ef38SBjorn Andersson ret = drms_uA_update(rdev); 3124414c70cbSLiam Girdwood mutex_unlock(&rdev->mutex); 31258460ef38SBjorn Andersson 3126414c70cbSLiam Girdwood return ret; 3127414c70cbSLiam Girdwood } 3128e39ce48fSBjorn Andersson EXPORT_SYMBOL_GPL(regulator_set_load); 3129414c70cbSLiam Girdwood 3130414c70cbSLiam Girdwood /** 3131f59c8f9fSMark Brown * regulator_allow_bypass - allow the regulator to go into bypass mode 3132f59c8f9fSMark Brown * 3133f59c8f9fSMark Brown * @regulator: Regulator to configure 31349345dfb8SNishanth Menon * @enable: enable or disable bypass mode 3135f59c8f9fSMark Brown * 3136f59c8f9fSMark Brown * Allow the regulator to go into bypass mode if all other consumers 3137f59c8f9fSMark Brown * for the regulator also enable bypass mode and the machine 3138f59c8f9fSMark Brown * constraints allow this. Bypass mode means that the regulator is 3139f59c8f9fSMark Brown * simply passing the input directly to the output with no regulation. 3140f59c8f9fSMark Brown */ 3141f59c8f9fSMark Brown int regulator_allow_bypass(struct regulator *regulator, bool enable) 3142f59c8f9fSMark Brown { 3143f59c8f9fSMark Brown struct regulator_dev *rdev = regulator->rdev; 3144f59c8f9fSMark Brown int ret = 0; 3145f59c8f9fSMark Brown 3146f59c8f9fSMark Brown if (!rdev->desc->ops->set_bypass) 3147f59c8f9fSMark Brown return 0; 3148f59c8f9fSMark Brown 3149f59c8f9fSMark Brown if (rdev->constraints && 3150f59c8f9fSMark Brown !(rdev->constraints->valid_ops_mask & REGULATOR_CHANGE_BYPASS)) 3151f59c8f9fSMark Brown return 0; 3152f59c8f9fSMark Brown 3153f59c8f9fSMark Brown mutex_lock(&rdev->mutex); 3154f59c8f9fSMark Brown 3155f59c8f9fSMark Brown if (enable && !regulator->bypass) { 3156f59c8f9fSMark Brown rdev->bypass_count++; 3157f59c8f9fSMark Brown 3158f59c8f9fSMark Brown if (rdev->bypass_count == rdev->open_count) { 3159f59c8f9fSMark Brown ret = rdev->desc->ops->set_bypass(rdev, enable); 3160f59c8f9fSMark Brown if (ret != 0) 3161f59c8f9fSMark Brown rdev->bypass_count--; 3162f59c8f9fSMark Brown } 3163f59c8f9fSMark Brown 3164f59c8f9fSMark Brown } else if (!enable && regulator->bypass) { 3165f59c8f9fSMark Brown rdev->bypass_count--; 3166f59c8f9fSMark Brown 3167f59c8f9fSMark Brown if (rdev->bypass_count != rdev->open_count) { 3168f59c8f9fSMark Brown ret = rdev->desc->ops->set_bypass(rdev, enable); 3169f59c8f9fSMark Brown if (ret != 0) 3170f59c8f9fSMark Brown rdev->bypass_count++; 3171f59c8f9fSMark Brown } 3172f59c8f9fSMark Brown } 3173f59c8f9fSMark Brown 3174f59c8f9fSMark Brown if (ret == 0) 3175f59c8f9fSMark Brown regulator->bypass = enable; 3176f59c8f9fSMark Brown 3177f59c8f9fSMark Brown mutex_unlock(&rdev->mutex); 3178f59c8f9fSMark Brown 3179f59c8f9fSMark Brown return ret; 3180f59c8f9fSMark Brown } 3181f59c8f9fSMark Brown EXPORT_SYMBOL_GPL(regulator_allow_bypass); 3182f59c8f9fSMark Brown 3183f59c8f9fSMark Brown /** 3184414c70cbSLiam Girdwood * regulator_register_notifier - register regulator event notifier 3185414c70cbSLiam Girdwood * @regulator: regulator source 318669279fb9SMark Brown * @nb: notifier block 3187414c70cbSLiam Girdwood * 3188414c70cbSLiam Girdwood * Register notifier block to receive regulator events. 3189414c70cbSLiam Girdwood */ 3190414c70cbSLiam Girdwood int regulator_register_notifier(struct regulator *regulator, 3191414c70cbSLiam Girdwood struct notifier_block *nb) 3192414c70cbSLiam Girdwood { 3193414c70cbSLiam Girdwood return blocking_notifier_chain_register(®ulator->rdev->notifier, 3194414c70cbSLiam Girdwood nb); 3195414c70cbSLiam Girdwood } 3196414c70cbSLiam Girdwood EXPORT_SYMBOL_GPL(regulator_register_notifier); 3197414c70cbSLiam Girdwood 3198414c70cbSLiam Girdwood /** 3199414c70cbSLiam Girdwood * regulator_unregister_notifier - unregister regulator event notifier 3200414c70cbSLiam Girdwood * @regulator: regulator source 320169279fb9SMark Brown * @nb: notifier block 3202414c70cbSLiam Girdwood * 3203414c70cbSLiam Girdwood * Unregister regulator event notifier block. 3204414c70cbSLiam Girdwood */ 3205414c70cbSLiam Girdwood int regulator_unregister_notifier(struct regulator *regulator, 3206414c70cbSLiam Girdwood struct notifier_block *nb) 3207414c70cbSLiam Girdwood { 3208414c70cbSLiam Girdwood return blocking_notifier_chain_unregister(®ulator->rdev->notifier, 3209414c70cbSLiam Girdwood nb); 3210414c70cbSLiam Girdwood } 3211414c70cbSLiam Girdwood EXPORT_SYMBOL_GPL(regulator_unregister_notifier); 3212414c70cbSLiam Girdwood 3213b136fb44SJonathan Cameron /* notify regulator consumers and downstream regulator consumers. 3214b136fb44SJonathan Cameron * Note mutex must be held by caller. 3215b136fb44SJonathan Cameron */ 32167179569aSHeiko Stübner static int _notifier_call_chain(struct regulator_dev *rdev, 3217414c70cbSLiam Girdwood unsigned long event, void *data) 3218414c70cbSLiam Girdwood { 3219414c70cbSLiam Girdwood /* call rdev chain first */ 32207179569aSHeiko Stübner return blocking_notifier_call_chain(&rdev->notifier, event, data); 3221414c70cbSLiam Girdwood } 3222414c70cbSLiam Girdwood 3223414c70cbSLiam Girdwood /** 3224414c70cbSLiam Girdwood * regulator_bulk_get - get multiple regulator consumers 3225414c70cbSLiam Girdwood * 3226414c70cbSLiam Girdwood * @dev: Device to supply 3227414c70cbSLiam Girdwood * @num_consumers: Number of consumers to register 3228414c70cbSLiam Girdwood * @consumers: Configuration of consumers; clients are stored here. 3229414c70cbSLiam Girdwood * 3230414c70cbSLiam Girdwood * @return 0 on success, an errno on failure. 3231414c70cbSLiam Girdwood * 3232414c70cbSLiam Girdwood * This helper function allows drivers to get several regulator 3233414c70cbSLiam Girdwood * consumers in one operation. If any of the regulators cannot be 3234414c70cbSLiam Girdwood * acquired then any regulators that were allocated will be freed 3235414c70cbSLiam Girdwood * before returning to the caller. 3236414c70cbSLiam Girdwood */ 3237414c70cbSLiam Girdwood int regulator_bulk_get(struct device *dev, int num_consumers, 3238414c70cbSLiam Girdwood struct regulator_bulk_data *consumers) 3239414c70cbSLiam Girdwood { 3240414c70cbSLiam Girdwood int i; 3241414c70cbSLiam Girdwood int ret; 3242414c70cbSLiam Girdwood 3243414c70cbSLiam Girdwood for (i = 0; i < num_consumers; i++) 3244414c70cbSLiam Girdwood consumers[i].consumer = NULL; 3245414c70cbSLiam Girdwood 3246414c70cbSLiam Girdwood for (i = 0; i < num_consumers; i++) { 3247414c70cbSLiam Girdwood consumers[i].consumer = regulator_get(dev, 3248414c70cbSLiam Girdwood consumers[i].supply); 3249414c70cbSLiam Girdwood if (IS_ERR(consumers[i].consumer)) { 3250414c70cbSLiam Girdwood ret = PTR_ERR(consumers[i].consumer); 32515b307627SMark Brown dev_err(dev, "Failed to get supply '%s': %d\n", 32525b307627SMark Brown consumers[i].supply, ret); 3253414c70cbSLiam Girdwood consumers[i].consumer = NULL; 3254414c70cbSLiam Girdwood goto err; 3255414c70cbSLiam Girdwood } 3256414c70cbSLiam Girdwood } 3257414c70cbSLiam Girdwood 3258414c70cbSLiam Girdwood return 0; 3259414c70cbSLiam Girdwood 3260414c70cbSLiam Girdwood err: 3261b29c7690SAxel Lin while (--i >= 0) 3262414c70cbSLiam Girdwood regulator_put(consumers[i].consumer); 3263414c70cbSLiam Girdwood 3264414c70cbSLiam Girdwood return ret; 3265414c70cbSLiam Girdwood } 3266414c70cbSLiam Girdwood EXPORT_SYMBOL_GPL(regulator_bulk_get); 3267414c70cbSLiam Girdwood 3268f21e0e81SMark Brown static void regulator_bulk_enable_async(void *data, async_cookie_t cookie) 3269f21e0e81SMark Brown { 3270f21e0e81SMark Brown struct regulator_bulk_data *bulk = data; 3271f21e0e81SMark Brown 3272f21e0e81SMark Brown bulk->ret = regulator_enable(bulk->consumer); 3273f21e0e81SMark Brown } 3274f21e0e81SMark Brown 3275414c70cbSLiam Girdwood /** 3276414c70cbSLiam Girdwood * regulator_bulk_enable - enable multiple regulator consumers 3277414c70cbSLiam Girdwood * 3278414c70cbSLiam Girdwood * @num_consumers: Number of consumers 3279414c70cbSLiam Girdwood * @consumers: Consumer data; clients are stored here. 3280414c70cbSLiam Girdwood * @return 0 on success, an errno on failure 3281414c70cbSLiam Girdwood * 3282414c70cbSLiam Girdwood * This convenience API allows consumers to enable multiple regulator 3283414c70cbSLiam Girdwood * clients in a single API call. If any consumers cannot be enabled 3284414c70cbSLiam Girdwood * then any others that were enabled will be disabled again prior to 3285414c70cbSLiam Girdwood * return. 3286414c70cbSLiam Girdwood */ 3287414c70cbSLiam Girdwood int regulator_bulk_enable(int num_consumers, 3288414c70cbSLiam Girdwood struct regulator_bulk_data *consumers) 3289414c70cbSLiam Girdwood { 32902955b47dSDan Williams ASYNC_DOMAIN_EXCLUSIVE(async_domain); 3291414c70cbSLiam Girdwood int i; 3292f21e0e81SMark Brown int ret = 0; 3293414c70cbSLiam Girdwood 32946492bc1bSMark Brown for (i = 0; i < num_consumers; i++) { 32956492bc1bSMark Brown if (consumers[i].consumer->always_on) 32966492bc1bSMark Brown consumers[i].ret = 0; 32976492bc1bSMark Brown else 3298f21e0e81SMark Brown async_schedule_domain(regulator_bulk_enable_async, 3299f21e0e81SMark Brown &consumers[i], &async_domain); 33006492bc1bSMark Brown } 3301f21e0e81SMark Brown 3302f21e0e81SMark Brown async_synchronize_full_domain(&async_domain); 3303f21e0e81SMark Brown 3304f21e0e81SMark Brown /* If any consumer failed we need to unwind any that succeeded */ 3305414c70cbSLiam Girdwood for (i = 0; i < num_consumers; i++) { 3306f21e0e81SMark Brown if (consumers[i].ret != 0) { 3307f21e0e81SMark Brown ret = consumers[i].ret; 3308414c70cbSLiam Girdwood goto err; 3309414c70cbSLiam Girdwood } 3310f21e0e81SMark Brown } 3311414c70cbSLiam Girdwood 3312414c70cbSLiam Girdwood return 0; 3313414c70cbSLiam Girdwood 3314414c70cbSLiam Girdwood err: 3315fbe31057SAndrzej Hajda for (i = 0; i < num_consumers; i++) { 3316fbe31057SAndrzej Hajda if (consumers[i].ret < 0) 3317fbe31057SAndrzej Hajda pr_err("Failed to enable %s: %d\n", consumers[i].supply, 3318fbe31057SAndrzej Hajda consumers[i].ret); 3319fbe31057SAndrzej Hajda else 3320414c70cbSLiam Girdwood regulator_disable(consumers[i].consumer); 3321fbe31057SAndrzej Hajda } 3322414c70cbSLiam Girdwood 3323414c70cbSLiam Girdwood return ret; 3324414c70cbSLiam Girdwood } 3325414c70cbSLiam Girdwood EXPORT_SYMBOL_GPL(regulator_bulk_enable); 3326414c70cbSLiam Girdwood 3327414c70cbSLiam Girdwood /** 3328414c70cbSLiam Girdwood * regulator_bulk_disable - disable multiple regulator consumers 3329414c70cbSLiam Girdwood * 3330414c70cbSLiam Girdwood * @num_consumers: Number of consumers 3331414c70cbSLiam Girdwood * @consumers: Consumer data; clients are stored here. 3332414c70cbSLiam Girdwood * @return 0 on success, an errno on failure 3333414c70cbSLiam Girdwood * 3334414c70cbSLiam Girdwood * This convenience API allows consumers to disable multiple regulator 333549e22632SSylwester Nawrocki * clients in a single API call. If any consumers cannot be disabled 333649e22632SSylwester Nawrocki * then any others that were disabled will be enabled again prior to 3337414c70cbSLiam Girdwood * return. 3338414c70cbSLiam Girdwood */ 3339414c70cbSLiam Girdwood int regulator_bulk_disable(int num_consumers, 3340414c70cbSLiam Girdwood struct regulator_bulk_data *consumers) 3341414c70cbSLiam Girdwood { 3342414c70cbSLiam Girdwood int i; 334301e86f49SMark Brown int ret, r; 3344414c70cbSLiam Girdwood 334549e22632SSylwester Nawrocki for (i = num_consumers - 1; i >= 0; --i) { 3346414c70cbSLiam Girdwood ret = regulator_disable(consumers[i].consumer); 3347414c70cbSLiam Girdwood if (ret != 0) 3348414c70cbSLiam Girdwood goto err; 3349414c70cbSLiam Girdwood } 3350414c70cbSLiam Girdwood 3351414c70cbSLiam Girdwood return 0; 3352414c70cbSLiam Girdwood 3353414c70cbSLiam Girdwood err: 33545da84fd9SJoe Perches pr_err("Failed to disable %s: %d\n", consumers[i].supply, ret); 335501e86f49SMark Brown for (++i; i < num_consumers; ++i) { 335601e86f49SMark Brown r = regulator_enable(consumers[i].consumer); 335701e86f49SMark Brown if (r != 0) 335801e86f49SMark Brown pr_err("Failed to reename %s: %d\n", 335901e86f49SMark Brown consumers[i].supply, r); 336001e86f49SMark Brown } 3361414c70cbSLiam Girdwood 3362414c70cbSLiam Girdwood return ret; 3363414c70cbSLiam Girdwood } 3364414c70cbSLiam Girdwood EXPORT_SYMBOL_GPL(regulator_bulk_disable); 3365414c70cbSLiam Girdwood 3366414c70cbSLiam Girdwood /** 3367e1de2f42SDonggeun Kim * regulator_bulk_force_disable - force disable multiple regulator consumers 3368e1de2f42SDonggeun Kim * 3369e1de2f42SDonggeun Kim * @num_consumers: Number of consumers 3370e1de2f42SDonggeun Kim * @consumers: Consumer data; clients are stored here. 3371e1de2f42SDonggeun Kim * @return 0 on success, an errno on failure 3372e1de2f42SDonggeun Kim * 3373e1de2f42SDonggeun Kim * This convenience API allows consumers to forcibly disable multiple regulator 3374e1de2f42SDonggeun Kim * clients in a single API call. 3375e1de2f42SDonggeun Kim * NOTE: This should be used for situations when device damage will 3376e1de2f42SDonggeun Kim * likely occur if the regulators are not disabled (e.g. over temp). 3377e1de2f42SDonggeun Kim * Although regulator_force_disable function call for some consumers can 3378e1de2f42SDonggeun Kim * return error numbers, the function is called for all consumers. 3379e1de2f42SDonggeun Kim */ 3380e1de2f42SDonggeun Kim int regulator_bulk_force_disable(int num_consumers, 3381e1de2f42SDonggeun Kim struct regulator_bulk_data *consumers) 3382e1de2f42SDonggeun Kim { 3383e1de2f42SDonggeun Kim int i; 3384e1de2f42SDonggeun Kim int ret; 3385e1de2f42SDonggeun Kim 3386e1de2f42SDonggeun Kim for (i = 0; i < num_consumers; i++) 3387e1de2f42SDonggeun Kim consumers[i].ret = 3388e1de2f42SDonggeun Kim regulator_force_disable(consumers[i].consumer); 3389e1de2f42SDonggeun Kim 3390e1de2f42SDonggeun Kim for (i = 0; i < num_consumers; i++) { 3391e1de2f42SDonggeun Kim if (consumers[i].ret != 0) { 3392e1de2f42SDonggeun Kim ret = consumers[i].ret; 3393e1de2f42SDonggeun Kim goto out; 3394e1de2f42SDonggeun Kim } 3395e1de2f42SDonggeun Kim } 3396e1de2f42SDonggeun Kim 3397e1de2f42SDonggeun Kim return 0; 3398e1de2f42SDonggeun Kim out: 3399e1de2f42SDonggeun Kim return ret; 3400e1de2f42SDonggeun Kim } 3401e1de2f42SDonggeun Kim EXPORT_SYMBOL_GPL(regulator_bulk_force_disable); 3402e1de2f42SDonggeun Kim 3403e1de2f42SDonggeun Kim /** 3404414c70cbSLiam Girdwood * regulator_bulk_free - free multiple regulator consumers 3405414c70cbSLiam Girdwood * 3406414c70cbSLiam Girdwood * @num_consumers: Number of consumers 3407414c70cbSLiam Girdwood * @consumers: Consumer data; clients are stored here. 3408414c70cbSLiam Girdwood * 3409414c70cbSLiam Girdwood * This convenience API allows consumers to free multiple regulator 3410414c70cbSLiam Girdwood * clients in a single API call. 3411414c70cbSLiam Girdwood */ 3412414c70cbSLiam Girdwood void regulator_bulk_free(int num_consumers, 3413414c70cbSLiam Girdwood struct regulator_bulk_data *consumers) 3414414c70cbSLiam Girdwood { 3415414c70cbSLiam Girdwood int i; 3416414c70cbSLiam Girdwood 3417414c70cbSLiam Girdwood for (i = 0; i < num_consumers; i++) { 3418414c70cbSLiam Girdwood regulator_put(consumers[i].consumer); 3419414c70cbSLiam Girdwood consumers[i].consumer = NULL; 3420414c70cbSLiam Girdwood } 3421414c70cbSLiam Girdwood } 3422414c70cbSLiam Girdwood EXPORT_SYMBOL_GPL(regulator_bulk_free); 3423414c70cbSLiam Girdwood 3424414c70cbSLiam Girdwood /** 3425414c70cbSLiam Girdwood * regulator_notifier_call_chain - call regulator event notifier 342669279fb9SMark Brown * @rdev: regulator source 3427414c70cbSLiam Girdwood * @event: notifier block 342869279fb9SMark Brown * @data: callback-specific data. 3429414c70cbSLiam Girdwood * 3430414c70cbSLiam Girdwood * Called by regulator drivers to notify clients a regulator event has 3431414c70cbSLiam Girdwood * occurred. We also notify regulator clients downstream. 3432b136fb44SJonathan Cameron * Note lock must be held by caller. 3433414c70cbSLiam Girdwood */ 3434414c70cbSLiam Girdwood int regulator_notifier_call_chain(struct regulator_dev *rdev, 3435414c70cbSLiam Girdwood unsigned long event, void *data) 3436414c70cbSLiam Girdwood { 3437414c70cbSLiam Girdwood _notifier_call_chain(rdev, event, data); 3438414c70cbSLiam Girdwood return NOTIFY_DONE; 3439414c70cbSLiam Girdwood 3440414c70cbSLiam Girdwood } 3441414c70cbSLiam Girdwood EXPORT_SYMBOL_GPL(regulator_notifier_call_chain); 3442414c70cbSLiam Girdwood 3443be721979SMark Brown /** 3444be721979SMark Brown * regulator_mode_to_status - convert a regulator mode into a status 3445be721979SMark Brown * 3446be721979SMark Brown * @mode: Mode to convert 3447be721979SMark Brown * 3448be721979SMark Brown * Convert a regulator mode into a status. 3449be721979SMark Brown */ 3450be721979SMark Brown int regulator_mode_to_status(unsigned int mode) 3451be721979SMark Brown { 3452be721979SMark Brown switch (mode) { 3453be721979SMark Brown case REGULATOR_MODE_FAST: 3454be721979SMark Brown return REGULATOR_STATUS_FAST; 3455be721979SMark Brown case REGULATOR_MODE_NORMAL: 3456be721979SMark Brown return REGULATOR_STATUS_NORMAL; 3457be721979SMark Brown case REGULATOR_MODE_IDLE: 3458be721979SMark Brown return REGULATOR_STATUS_IDLE; 345903ffcf3dSKrystian Garbaciak case REGULATOR_MODE_STANDBY: 3460be721979SMark Brown return REGULATOR_STATUS_STANDBY; 3461be721979SMark Brown default: 34621beaf762SKrystian Garbaciak return REGULATOR_STATUS_UNDEFINED; 3463be721979SMark Brown } 3464be721979SMark Brown } 3465be721979SMark Brown EXPORT_SYMBOL_GPL(regulator_mode_to_status); 3466be721979SMark Brown 346739f802d6STakashi Iwai static struct attribute *regulator_dev_attrs[] = { 346839f802d6STakashi Iwai &dev_attr_name.attr, 346939f802d6STakashi Iwai &dev_attr_num_users.attr, 347039f802d6STakashi Iwai &dev_attr_type.attr, 347139f802d6STakashi Iwai &dev_attr_microvolts.attr, 347239f802d6STakashi Iwai &dev_attr_microamps.attr, 347339f802d6STakashi Iwai &dev_attr_opmode.attr, 347439f802d6STakashi Iwai &dev_attr_state.attr, 347539f802d6STakashi Iwai &dev_attr_status.attr, 347639f802d6STakashi Iwai &dev_attr_bypass.attr, 347739f802d6STakashi Iwai &dev_attr_requested_microamps.attr, 347839f802d6STakashi Iwai &dev_attr_min_microvolts.attr, 347939f802d6STakashi Iwai &dev_attr_max_microvolts.attr, 348039f802d6STakashi Iwai &dev_attr_min_microamps.attr, 348139f802d6STakashi Iwai &dev_attr_max_microamps.attr, 348239f802d6STakashi Iwai &dev_attr_suspend_standby_state.attr, 348339f802d6STakashi Iwai &dev_attr_suspend_mem_state.attr, 348439f802d6STakashi Iwai &dev_attr_suspend_disk_state.attr, 348539f802d6STakashi Iwai &dev_attr_suspend_standby_microvolts.attr, 348639f802d6STakashi Iwai &dev_attr_suspend_mem_microvolts.attr, 348739f802d6STakashi Iwai &dev_attr_suspend_disk_microvolts.attr, 348839f802d6STakashi Iwai &dev_attr_suspend_standby_mode.attr, 348939f802d6STakashi Iwai &dev_attr_suspend_mem_mode.attr, 349039f802d6STakashi Iwai &dev_attr_suspend_disk_mode.attr, 349139f802d6STakashi Iwai NULL 349239f802d6STakashi Iwai }; 349339f802d6STakashi Iwai 34947ad68e2fSDavid Brownell /* 34957ad68e2fSDavid Brownell * To avoid cluttering sysfs (and memory) with useless state, only 34967ad68e2fSDavid Brownell * create attributes that can be meaningfully displayed. 34977ad68e2fSDavid Brownell */ 349839f802d6STakashi Iwai static umode_t regulator_attr_is_visible(struct kobject *kobj, 349939f802d6STakashi Iwai struct attribute *attr, int idx) 35007ad68e2fSDavid Brownell { 350139f802d6STakashi Iwai struct device *dev = kobj_to_dev(kobj); 350239f802d6STakashi Iwai struct regulator_dev *rdev = container_of(dev, struct regulator_dev, dev); 3503272e2315SGuodong Xu const struct regulator_ops *ops = rdev->desc->ops; 350439f802d6STakashi Iwai umode_t mode = attr->mode; 350539f802d6STakashi Iwai 350639f802d6STakashi Iwai /* these three are always present */ 350739f802d6STakashi Iwai if (attr == &dev_attr_name.attr || 350839f802d6STakashi Iwai attr == &dev_attr_num_users.attr || 350939f802d6STakashi Iwai attr == &dev_attr_type.attr) 351039f802d6STakashi Iwai return mode; 35117ad68e2fSDavid Brownell 35127ad68e2fSDavid Brownell /* some attributes need specific methods to be displayed */ 351339f802d6STakashi Iwai if (attr == &dev_attr_microvolts.attr) { 35144c78899bSMark Brown if ((ops->get_voltage && ops->get_voltage(rdev) >= 0) || 3515f2889e65SMark Brown (ops->get_voltage_sel && ops->get_voltage_sel(rdev) >= 0) || 35165a523605SLaxman Dewangan (ops->list_voltage && ops->list_voltage(rdev, 0) >= 0) || 351739f802d6STakashi Iwai (rdev->desc->fixed_uV && rdev->desc->n_voltages == 1)) 351839f802d6STakashi Iwai return mode; 351939f802d6STakashi Iwai return 0; 3520f59c8f9fSMark Brown } 35217ad68e2fSDavid Brownell 352239f802d6STakashi Iwai if (attr == &dev_attr_microamps.attr) 352339f802d6STakashi Iwai return ops->get_current_limit ? mode : 0; 352439f802d6STakashi Iwai 352539f802d6STakashi Iwai if (attr == &dev_attr_opmode.attr) 352639f802d6STakashi Iwai return ops->get_mode ? mode : 0; 352739f802d6STakashi Iwai 352839f802d6STakashi Iwai if (attr == &dev_attr_state.attr) 352939f802d6STakashi Iwai return (rdev->ena_pin || ops->is_enabled) ? mode : 0; 353039f802d6STakashi Iwai 353139f802d6STakashi Iwai if (attr == &dev_attr_status.attr) 353239f802d6STakashi Iwai return ops->get_status ? mode : 0; 353339f802d6STakashi Iwai 353439f802d6STakashi Iwai if (attr == &dev_attr_bypass.attr) 353539f802d6STakashi Iwai return ops->get_bypass ? mode : 0; 353639f802d6STakashi Iwai 35377ad68e2fSDavid Brownell /* some attributes are type-specific */ 353839f802d6STakashi Iwai if (attr == &dev_attr_requested_microamps.attr) 353939f802d6STakashi Iwai return rdev->desc->type == REGULATOR_CURRENT ? mode : 0; 35407ad68e2fSDavid Brownell 35417ad68e2fSDavid Brownell /* constraints need specific supporting methods */ 354239f802d6STakashi Iwai if (attr == &dev_attr_min_microvolts.attr || 354339f802d6STakashi Iwai attr == &dev_attr_max_microvolts.attr) 354439f802d6STakashi Iwai return (ops->set_voltage || ops->set_voltage_sel) ? mode : 0; 354539f802d6STakashi Iwai 354639f802d6STakashi Iwai if (attr == &dev_attr_min_microamps.attr || 354739f802d6STakashi Iwai attr == &dev_attr_max_microamps.attr) 354839f802d6STakashi Iwai return ops->set_current_limit ? mode : 0; 354939f802d6STakashi Iwai 355039f802d6STakashi Iwai if (attr == &dev_attr_suspend_standby_state.attr || 355139f802d6STakashi Iwai attr == &dev_attr_suspend_mem_state.attr || 355239f802d6STakashi Iwai attr == &dev_attr_suspend_disk_state.attr) 355339f802d6STakashi Iwai return mode; 355439f802d6STakashi Iwai 355539f802d6STakashi Iwai if (attr == &dev_attr_suspend_standby_microvolts.attr || 355639f802d6STakashi Iwai attr == &dev_attr_suspend_mem_microvolts.attr || 355739f802d6STakashi Iwai attr == &dev_attr_suspend_disk_microvolts.attr) 355839f802d6STakashi Iwai return ops->set_suspend_voltage ? mode : 0; 355939f802d6STakashi Iwai 356039f802d6STakashi Iwai if (attr == &dev_attr_suspend_standby_mode.attr || 356139f802d6STakashi Iwai attr == &dev_attr_suspend_mem_mode.attr || 356239f802d6STakashi Iwai attr == &dev_attr_suspend_disk_mode.attr) 356339f802d6STakashi Iwai return ops->set_suspend_mode ? mode : 0; 356439f802d6STakashi Iwai 356539f802d6STakashi Iwai return mode; 35667ad68e2fSDavid Brownell } 35677ad68e2fSDavid Brownell 356839f802d6STakashi Iwai static const struct attribute_group regulator_dev_group = { 356939f802d6STakashi Iwai .attrs = regulator_dev_attrs, 357039f802d6STakashi Iwai .is_visible = regulator_attr_is_visible, 357139f802d6STakashi Iwai }; 35727ad68e2fSDavid Brownell 357339f802d6STakashi Iwai static const struct attribute_group *regulator_dev_groups[] = { 357439f802d6STakashi Iwai ®ulator_dev_group, 357539f802d6STakashi Iwai NULL 357639f802d6STakashi Iwai }; 357739f802d6STakashi Iwai 357839f802d6STakashi Iwai static void regulator_dev_release(struct device *dev) 357939f802d6STakashi Iwai { 358039f802d6STakashi Iwai struct regulator_dev *rdev = dev_get_drvdata(dev); 358139f802d6STakashi Iwai kfree(rdev); 35827ad68e2fSDavid Brownell } 35837ad68e2fSDavid Brownell 358439f802d6STakashi Iwai static struct class regulator_class = { 358539f802d6STakashi Iwai .name = "regulator", 358639f802d6STakashi Iwai .dev_release = regulator_dev_release, 358739f802d6STakashi Iwai .dev_groups = regulator_dev_groups, 358839f802d6STakashi Iwai }; 35897ad68e2fSDavid Brownell 35901130e5b3SMark Brown static void rdev_init_debugfs(struct regulator_dev *rdev) 35911130e5b3SMark Brown { 3592a9eaa813SGuenter Roeck struct device *parent = rdev->dev.parent; 3593a9eaa813SGuenter Roeck const char *rname = rdev_get_name(rdev); 3594a9eaa813SGuenter Roeck char name[NAME_MAX]; 3595a9eaa813SGuenter Roeck 3596a9eaa813SGuenter Roeck /* Avoid duplicate debugfs directory names */ 3597a9eaa813SGuenter Roeck if (parent && rname == rdev->desc->name) { 3598a9eaa813SGuenter Roeck snprintf(name, sizeof(name), "%s-%s", dev_name(parent), 3599a9eaa813SGuenter Roeck rname); 3600a9eaa813SGuenter Roeck rname = name; 3601a9eaa813SGuenter Roeck } 3602a9eaa813SGuenter Roeck 3603a9eaa813SGuenter Roeck rdev->debugfs = debugfs_create_dir(rname, debugfs_root); 360424751434SStephen Boyd if (!rdev->debugfs) { 36051130e5b3SMark Brown rdev_warn(rdev, "Failed to create debugfs directory\n"); 36061130e5b3SMark Brown return; 36071130e5b3SMark Brown } 36081130e5b3SMark Brown 36091130e5b3SMark Brown debugfs_create_u32("use_count", 0444, rdev->debugfs, 36101130e5b3SMark Brown &rdev->use_count); 36111130e5b3SMark Brown debugfs_create_u32("open_count", 0444, rdev->debugfs, 36121130e5b3SMark Brown &rdev->open_count); 3613f59c8f9fSMark Brown debugfs_create_u32("bypass_count", 0444, rdev->debugfs, 3614f59c8f9fSMark Brown &rdev->bypass_count); 36151130e5b3SMark Brown } 36161130e5b3SMark Brown 3617414c70cbSLiam Girdwood /** 3618414c70cbSLiam Girdwood * regulator_register - register regulator 361969279fb9SMark Brown * @regulator_desc: regulator to register 3620f47531b1SKrzysztof Kozlowski * @cfg: runtime configuration for regulator 3621414c70cbSLiam Girdwood * 3622414c70cbSLiam Girdwood * Called by regulator drivers to register a regulator. 36230384618aSAxel Lin * Returns a valid pointer to struct regulator_dev on success 36240384618aSAxel Lin * or an ERR_PTR() on error. 3625414c70cbSLiam Girdwood */ 362665f26846SMark Brown struct regulator_dev * 362765f26846SMark Brown regulator_register(const struct regulator_desc *regulator_desc, 36281b3de223SKrzysztof Kozlowski const struct regulator_config *cfg) 3629414c70cbSLiam Girdwood { 36309a8f5e07SMark Brown const struct regulation_constraints *constraints = NULL; 3631c172708dSMark Brown const struct regulator_init_data *init_data; 36321b3de223SKrzysztof Kozlowski struct regulator_config *config = NULL; 363372dca06fSAniroop Mathur static atomic_t regulator_no = ATOMIC_INIT(-1); 3634414c70cbSLiam Girdwood struct regulator_dev *rdev; 363532c8fad4SMark Brown struct device *dev; 3636a5766f11SLiam Girdwood int ret, i; 3637414c70cbSLiam Girdwood 36381b3de223SKrzysztof Kozlowski if (regulator_desc == NULL || cfg == NULL) 3639414c70cbSLiam Girdwood return ERR_PTR(-EINVAL); 3640414c70cbSLiam Girdwood 36411b3de223SKrzysztof Kozlowski dev = cfg->dev; 3642dcf70112SMark Brown WARN_ON(!dev); 364332c8fad4SMark Brown 3644414c70cbSLiam Girdwood if (regulator_desc->name == NULL || regulator_desc->ops == NULL) 3645414c70cbSLiam Girdwood return ERR_PTR(-EINVAL); 3646414c70cbSLiam Girdwood 3647cd78dfc6SDiego Liziero if (regulator_desc->type != REGULATOR_VOLTAGE && 3648cd78dfc6SDiego Liziero regulator_desc->type != REGULATOR_CURRENT) 3649414c70cbSLiam Girdwood return ERR_PTR(-EINVAL); 3650414c70cbSLiam Girdwood 3651476c2d83SMark Brown /* Only one of each should be implemented */ 3652476c2d83SMark Brown WARN_ON(regulator_desc->ops->get_voltage && 3653476c2d83SMark Brown regulator_desc->ops->get_voltage_sel); 3654e8eef82bSMark Brown WARN_ON(regulator_desc->ops->set_voltage && 3655e8eef82bSMark Brown regulator_desc->ops->set_voltage_sel); 3656476c2d83SMark Brown 3657476c2d83SMark Brown /* If we're using selectors we must implement list_voltage. */ 3658476c2d83SMark Brown if (regulator_desc->ops->get_voltage_sel && 3659476c2d83SMark Brown !regulator_desc->ops->list_voltage) { 3660476c2d83SMark Brown return ERR_PTR(-EINVAL); 3661476c2d83SMark Brown } 3662e8eef82bSMark Brown if (regulator_desc->ops->set_voltage_sel && 3663e8eef82bSMark Brown !regulator_desc->ops->list_voltage) { 3664e8eef82bSMark Brown return ERR_PTR(-EINVAL); 3665e8eef82bSMark Brown } 3666476c2d83SMark Brown 3667414c70cbSLiam Girdwood rdev = kzalloc(sizeof(struct regulator_dev), GFP_KERNEL); 3668414c70cbSLiam Girdwood if (rdev == NULL) 3669414c70cbSLiam Girdwood return ERR_PTR(-ENOMEM); 3670414c70cbSLiam Girdwood 36711b3de223SKrzysztof Kozlowski /* 36721b3de223SKrzysztof Kozlowski * Duplicate the config so the driver could override it after 36731b3de223SKrzysztof Kozlowski * parsing init data. 36741b3de223SKrzysztof Kozlowski */ 36751b3de223SKrzysztof Kozlowski config = kmemdup(cfg, sizeof(*cfg), GFP_KERNEL); 36761b3de223SKrzysztof Kozlowski if (config == NULL) { 36771b3de223SKrzysztof Kozlowski kfree(rdev); 36781b3de223SKrzysztof Kozlowski return ERR_PTR(-ENOMEM); 36791b3de223SKrzysztof Kozlowski } 36801b3de223SKrzysztof Kozlowski 3681bfa21a0dSKrzysztof Kozlowski init_data = regulator_of_get_init_data(dev, regulator_desc, config, 3682a0c7b164SMark Brown &rdev->dev.of_node); 3683a0c7b164SMark Brown if (!init_data) { 3684a0c7b164SMark Brown init_data = config->init_data; 3685a0c7b164SMark Brown rdev->dev.of_node = of_node_get(config->of_node); 3686a0c7b164SMark Brown } 3687a0c7b164SMark Brown 3688414c70cbSLiam Girdwood mutex_lock(®ulator_list_mutex); 3689414c70cbSLiam Girdwood 3690414c70cbSLiam Girdwood mutex_init(&rdev->mutex); 3691c172708dSMark Brown rdev->reg_data = config->driver_data; 3692414c70cbSLiam Girdwood rdev->owner = regulator_desc->owner; 3693414c70cbSLiam Girdwood rdev->desc = regulator_desc; 36943a4b0a07SMark Brown if (config->regmap) 369565b19ce6SMark Brown rdev->regmap = config->regmap; 369652b84dacSAnilKumar Ch else if (dev_get_regmap(dev, NULL)) 36973a4b0a07SMark Brown rdev->regmap = dev_get_regmap(dev, NULL); 369852b84dacSAnilKumar Ch else if (dev->parent) 369952b84dacSAnilKumar Ch rdev->regmap = dev_get_regmap(dev->parent, NULL); 3700414c70cbSLiam Girdwood INIT_LIST_HEAD(&rdev->consumer_list); 3701414c70cbSLiam Girdwood INIT_LIST_HEAD(&rdev->list); 3702414c70cbSLiam Girdwood BLOCKING_INIT_NOTIFIER_HEAD(&rdev->notifier); 3703da07ecd9SMark Brown INIT_DELAYED_WORK(&rdev->disable_work, regulator_disable_work); 3704414c70cbSLiam Girdwood 3705a5766f11SLiam Girdwood /* preform any regulator specific init */ 37069a8f5e07SMark Brown if (init_data && init_data->regulator_init) { 3707a5766f11SLiam Girdwood ret = init_data->regulator_init(rdev->reg_data); 37084fca9545SDavid Brownell if (ret < 0) 37094fca9545SDavid Brownell goto clean; 3710a5766f11SLiam Girdwood } 3711a5766f11SLiam Girdwood 3712a5766f11SLiam Girdwood /* register with sysfs */ 3713a5766f11SLiam Girdwood rdev->dev.class = ®ulator_class; 3714a5766f11SLiam Girdwood rdev->dev.parent = dev; 371572dca06fSAniroop Mathur dev_set_name(&rdev->dev, "regulator.%lu", 371639138818SAniroop Mathur (unsigned long) atomic_inc_return(®ulator_no)); 3717a5766f11SLiam Girdwood ret = device_register(&rdev->dev); 3718ad7725cbSVasiliy Kulikov if (ret != 0) { 3719ad7725cbSVasiliy Kulikov put_device(&rdev->dev); 37204fca9545SDavid Brownell goto clean; 3721ad7725cbSVasiliy Kulikov } 3722a5766f11SLiam Girdwood 3723a5766f11SLiam Girdwood dev_set_drvdata(&rdev->dev, rdev); 3724a5766f11SLiam Girdwood 372576f439dfSMarkus Pargmann if ((config->ena_gpio || config->ena_gpio_initialized) && 372676f439dfSMarkus Pargmann gpio_is_valid(config->ena_gpio)) { 3727f19b00daSKim, Milo ret = regulator_ena_gpio_request(rdev, config); 372865f73508SMark Brown if (ret != 0) { 372965f73508SMark Brown rdev_err(rdev, "Failed to request enable GPIO%d: %d\n", 373065f73508SMark Brown config->ena_gpio, ret); 3731b2da55d9SAndrew Lunn goto wash; 373265f73508SMark Brown } 373365f73508SMark Brown } 373465f73508SMark Brown 373574f544c1SMike Rapoport /* set regulator constraints */ 37369a8f5e07SMark Brown if (init_data) 37379a8f5e07SMark Brown constraints = &init_data->constraints; 37389a8f5e07SMark Brown 37399a8f5e07SMark Brown ret = set_machine_constraints(rdev, constraints); 374074f544c1SMike Rapoport if (ret < 0) 374174f544c1SMike Rapoport goto scrub; 374274f544c1SMike Rapoport 37439a8f5e07SMark Brown if (init_data && init_data->supply_regulator) 37446261b06dSBjorn Andersson rdev->supply_name = init_data->supply_regulator; 374569511a45SRajendra Nayak else if (regulator_desc->supply_name) 37466261b06dSBjorn Andersson rdev->supply_name = regulator_desc->supply_name; 374769511a45SRajendra Nayak 3748a5766f11SLiam Girdwood /* add consumers devices */ 37499a8f5e07SMark Brown if (init_data) { 3750a5766f11SLiam Girdwood for (i = 0; i < init_data->num_consumer_supplies; i++) { 3751a5766f11SLiam Girdwood ret = set_consumer_device_supply(rdev, 375240f9244fSMark Brown init_data->consumer_supplies[i].dev_name, 3753a5766f11SLiam Girdwood init_data->consumer_supplies[i].supply); 375423c2f041SMark Brown if (ret < 0) { 375523c2f041SMark Brown dev_err(dev, "Failed to set supply %s\n", 375623c2f041SMark Brown init_data->consumer_supplies[i].supply); 3757d4033b54SJani Nikula goto unset_supplies; 3758a5766f11SLiam Girdwood } 375923c2f041SMark Brown } 37609a8f5e07SMark Brown } 3761a5766f11SLiam Girdwood 3762a5766f11SLiam Girdwood list_add(&rdev->list, ®ulator_list); 37631130e5b3SMark Brown 37641130e5b3SMark Brown rdev_init_debugfs(rdev); 3765a5766f11SLiam Girdwood out: 3766414c70cbSLiam Girdwood mutex_unlock(®ulator_list_mutex); 37671b3de223SKrzysztof Kozlowski kfree(config); 3768414c70cbSLiam Girdwood return rdev; 37694fca9545SDavid Brownell 3770d4033b54SJani Nikula unset_supplies: 3771d4033b54SJani Nikula unset_regulator_supplies(rdev); 3772d4033b54SJani Nikula 37734fca9545SDavid Brownell scrub: 3774f19b00daSKim, Milo regulator_ena_gpio_free(rdev); 37751a6958e7SAxel Lin kfree(rdev->constraints); 3776b2da55d9SAndrew Lunn wash: 37774fca9545SDavid Brownell device_unregister(&rdev->dev); 377853032dafSPaul Walmsley /* device core frees rdev */ 377953032dafSPaul Walmsley rdev = ERR_PTR(ret); 378053032dafSPaul Walmsley goto out; 378153032dafSPaul Walmsley 37824fca9545SDavid Brownell clean: 37834fca9545SDavid Brownell kfree(rdev); 37844fca9545SDavid Brownell rdev = ERR_PTR(ret); 37854fca9545SDavid Brownell goto out; 3786414c70cbSLiam Girdwood } 3787414c70cbSLiam Girdwood EXPORT_SYMBOL_GPL(regulator_register); 3788414c70cbSLiam Girdwood 3789414c70cbSLiam Girdwood /** 3790414c70cbSLiam Girdwood * regulator_unregister - unregister regulator 379169279fb9SMark Brown * @rdev: regulator to unregister 3792414c70cbSLiam Girdwood * 3793414c70cbSLiam Girdwood * Called by regulator drivers to unregister a regulator. 3794414c70cbSLiam Girdwood */ 3795414c70cbSLiam Girdwood void regulator_unregister(struct regulator_dev *rdev) 3796414c70cbSLiam Girdwood { 3797414c70cbSLiam Girdwood if (rdev == NULL) 3798414c70cbSLiam Girdwood return; 3799414c70cbSLiam Girdwood 3800891636eaSMark Brown if (rdev->supply) { 3801891636eaSMark Brown while (rdev->use_count--) 3802891636eaSMark Brown regulator_disable(rdev->supply); 3803e032b376SMark Brown regulator_put(rdev->supply); 3804891636eaSMark Brown } 3805414c70cbSLiam Girdwood mutex_lock(®ulator_list_mutex); 38061130e5b3SMark Brown debugfs_remove_recursive(rdev->debugfs); 380743829731STejun Heo flush_work(&rdev->disable_work.work); 38086bf87d17SMark Brown WARN_ON(rdev->open_count); 38090f1d747bSMike Rapoport unset_regulator_supplies(rdev); 3810414c70cbSLiam Girdwood list_del(&rdev->list); 3811f8c12fe3SMark Brown kfree(rdev->constraints); 3812f19b00daSKim, Milo regulator_ena_gpio_free(rdev); 381363c7c9e1SCharles Keepax of_node_put(rdev->dev.of_node); 381458fb5cf5SLothar Waßmann device_unregister(&rdev->dev); 3815414c70cbSLiam Girdwood mutex_unlock(®ulator_list_mutex); 3816414c70cbSLiam Girdwood } 3817414c70cbSLiam Girdwood EXPORT_SYMBOL_GPL(regulator_unregister); 3818414c70cbSLiam Girdwood 3819414c70cbSLiam Girdwood /** 3820cf7bbcdfSMark Brown * regulator_suspend_prepare - prepare regulators for system wide suspend 3821414c70cbSLiam Girdwood * @state: system suspend state 3822414c70cbSLiam Girdwood * 3823414c70cbSLiam Girdwood * Configure each regulator with it's suspend operating parameters for state. 3824414c70cbSLiam Girdwood * This will usually be called by machine suspend code prior to supending. 3825414c70cbSLiam Girdwood */ 3826414c70cbSLiam Girdwood int regulator_suspend_prepare(suspend_state_t state) 3827414c70cbSLiam Girdwood { 3828414c70cbSLiam Girdwood struct regulator_dev *rdev; 3829414c70cbSLiam Girdwood int ret = 0; 3830414c70cbSLiam Girdwood 3831414c70cbSLiam Girdwood /* ON is handled by regulator active state */ 3832414c70cbSLiam Girdwood if (state == PM_SUSPEND_ON) 3833414c70cbSLiam Girdwood return -EINVAL; 3834414c70cbSLiam Girdwood 3835414c70cbSLiam Girdwood mutex_lock(®ulator_list_mutex); 3836414c70cbSLiam Girdwood list_for_each_entry(rdev, ®ulator_list, list) { 3837414c70cbSLiam Girdwood 3838414c70cbSLiam Girdwood mutex_lock(&rdev->mutex); 3839414c70cbSLiam Girdwood ret = suspend_prepare(rdev, state); 3840414c70cbSLiam Girdwood mutex_unlock(&rdev->mutex); 3841414c70cbSLiam Girdwood 3842414c70cbSLiam Girdwood if (ret < 0) { 38435da84fd9SJoe Perches rdev_err(rdev, "failed to prepare\n"); 3844414c70cbSLiam Girdwood goto out; 3845414c70cbSLiam Girdwood } 3846414c70cbSLiam Girdwood } 3847414c70cbSLiam Girdwood out: 3848414c70cbSLiam Girdwood mutex_unlock(®ulator_list_mutex); 3849414c70cbSLiam Girdwood return ret; 3850414c70cbSLiam Girdwood } 3851414c70cbSLiam Girdwood EXPORT_SYMBOL_GPL(regulator_suspend_prepare); 3852414c70cbSLiam Girdwood 3853414c70cbSLiam Girdwood /** 38547a32b589SMyungJoo Ham * regulator_suspend_finish - resume regulators from system wide suspend 38557a32b589SMyungJoo Ham * 38567a32b589SMyungJoo Ham * Turn on regulators that might be turned off by regulator_suspend_prepare 38577a32b589SMyungJoo Ham * and that should be turned on according to the regulators properties. 38587a32b589SMyungJoo Ham */ 38597a32b589SMyungJoo Ham int regulator_suspend_finish(void) 38607a32b589SMyungJoo Ham { 38617a32b589SMyungJoo Ham struct regulator_dev *rdev; 38627a32b589SMyungJoo Ham int ret = 0, error; 38637a32b589SMyungJoo Ham 38647a32b589SMyungJoo Ham mutex_lock(®ulator_list_mutex); 38657a32b589SMyungJoo Ham list_for_each_entry(rdev, ®ulator_list, list) { 38667a32b589SMyungJoo Ham mutex_lock(&rdev->mutex); 386730c21971SMarkus Pargmann if (rdev->use_count > 0 || rdev->constraints->always_on) { 38680548bf4fSJavier Martinez Canillas if (!_regulator_is_enabled(rdev)) { 386930c21971SMarkus Pargmann error = _regulator_do_enable(rdev); 38707a32b589SMyungJoo Ham if (error) 38717a32b589SMyungJoo Ham ret = error; 38720548bf4fSJavier Martinez Canillas } 38737a32b589SMyungJoo Ham } else { 387487b28417SMark Brown if (!have_full_constraints()) 38757a32b589SMyungJoo Ham goto unlock; 3876b1a86831SMark Brown if (!_regulator_is_enabled(rdev)) 38777a32b589SMyungJoo Ham goto unlock; 38787a32b589SMyungJoo Ham 387966fda75fSMarkus Pargmann error = _regulator_do_disable(rdev); 38807a32b589SMyungJoo Ham if (error) 38817a32b589SMyungJoo Ham ret = error; 38827a32b589SMyungJoo Ham } 38837a32b589SMyungJoo Ham unlock: 38847a32b589SMyungJoo Ham mutex_unlock(&rdev->mutex); 38857a32b589SMyungJoo Ham } 38867a32b589SMyungJoo Ham mutex_unlock(®ulator_list_mutex); 38877a32b589SMyungJoo Ham return ret; 38887a32b589SMyungJoo Ham } 38897a32b589SMyungJoo Ham EXPORT_SYMBOL_GPL(regulator_suspend_finish); 38907a32b589SMyungJoo Ham 38917a32b589SMyungJoo Ham /** 3892ca725561SMark Brown * regulator_has_full_constraints - the system has fully specified constraints 3893ca725561SMark Brown * 3894ca725561SMark Brown * Calling this function will cause the regulator API to disable all 3895ca725561SMark Brown * regulators which have a zero use count and don't have an always_on 3896ca725561SMark Brown * constraint in a late_initcall. 3897ca725561SMark Brown * 3898ca725561SMark Brown * The intention is that this will become the default behaviour in a 3899ca725561SMark Brown * future kernel release so users are encouraged to use this facility 3900ca725561SMark Brown * now. 3901ca725561SMark Brown */ 3902ca725561SMark Brown void regulator_has_full_constraints(void) 3903ca725561SMark Brown { 3904ca725561SMark Brown has_full_constraints = 1; 3905ca725561SMark Brown } 3906ca725561SMark Brown EXPORT_SYMBOL_GPL(regulator_has_full_constraints); 3907ca725561SMark Brown 3908ca725561SMark Brown /** 3909414c70cbSLiam Girdwood * rdev_get_drvdata - get rdev regulator driver data 391069279fb9SMark Brown * @rdev: regulator 3911414c70cbSLiam Girdwood * 3912414c70cbSLiam Girdwood * Get rdev regulator driver private data. This call can be used in the 3913414c70cbSLiam Girdwood * regulator driver context. 3914414c70cbSLiam Girdwood */ 3915414c70cbSLiam Girdwood void *rdev_get_drvdata(struct regulator_dev *rdev) 3916414c70cbSLiam Girdwood { 3917414c70cbSLiam Girdwood return rdev->reg_data; 3918414c70cbSLiam Girdwood } 3919414c70cbSLiam Girdwood EXPORT_SYMBOL_GPL(rdev_get_drvdata); 3920414c70cbSLiam Girdwood 3921414c70cbSLiam Girdwood /** 3922414c70cbSLiam Girdwood * regulator_get_drvdata - get regulator driver data 3923414c70cbSLiam Girdwood * @regulator: regulator 3924414c70cbSLiam Girdwood * 3925414c70cbSLiam Girdwood * Get regulator driver private data. This call can be used in the consumer 3926414c70cbSLiam Girdwood * driver context when non API regulator specific functions need to be called. 3927414c70cbSLiam Girdwood */ 3928414c70cbSLiam Girdwood void *regulator_get_drvdata(struct regulator *regulator) 3929414c70cbSLiam Girdwood { 3930414c70cbSLiam Girdwood return regulator->rdev->reg_data; 3931414c70cbSLiam Girdwood } 3932414c70cbSLiam Girdwood EXPORT_SYMBOL_GPL(regulator_get_drvdata); 3933414c70cbSLiam Girdwood 3934414c70cbSLiam Girdwood /** 3935414c70cbSLiam Girdwood * regulator_set_drvdata - set regulator driver data 3936414c70cbSLiam Girdwood * @regulator: regulator 3937414c70cbSLiam Girdwood * @data: data 3938414c70cbSLiam Girdwood */ 3939414c70cbSLiam Girdwood void regulator_set_drvdata(struct regulator *regulator, void *data) 3940414c70cbSLiam Girdwood { 3941414c70cbSLiam Girdwood regulator->rdev->reg_data = data; 3942414c70cbSLiam Girdwood } 3943414c70cbSLiam Girdwood EXPORT_SYMBOL_GPL(regulator_set_drvdata); 3944414c70cbSLiam Girdwood 3945414c70cbSLiam Girdwood /** 3946414c70cbSLiam Girdwood * regulator_get_id - get regulator ID 394769279fb9SMark Brown * @rdev: regulator 3948414c70cbSLiam Girdwood */ 3949414c70cbSLiam Girdwood int rdev_get_id(struct regulator_dev *rdev) 3950414c70cbSLiam Girdwood { 3951414c70cbSLiam Girdwood return rdev->desc->id; 3952414c70cbSLiam Girdwood } 3953414c70cbSLiam Girdwood EXPORT_SYMBOL_GPL(rdev_get_id); 3954414c70cbSLiam Girdwood 3955a5766f11SLiam Girdwood struct device *rdev_get_dev(struct regulator_dev *rdev) 3956a5766f11SLiam Girdwood { 3957a5766f11SLiam Girdwood return &rdev->dev; 3958a5766f11SLiam Girdwood } 3959a5766f11SLiam Girdwood EXPORT_SYMBOL_GPL(rdev_get_dev); 3960a5766f11SLiam Girdwood 3961a5766f11SLiam Girdwood void *regulator_get_init_drvdata(struct regulator_init_data *reg_init_data) 3962a5766f11SLiam Girdwood { 3963a5766f11SLiam Girdwood return reg_init_data->driver_data; 3964a5766f11SLiam Girdwood } 3965a5766f11SLiam Girdwood EXPORT_SYMBOL_GPL(regulator_get_init_drvdata); 3966a5766f11SLiam Girdwood 3967ba55a974SMark Brown #ifdef CONFIG_DEBUG_FS 3968ba55a974SMark Brown static ssize_t supply_map_read_file(struct file *file, char __user *user_buf, 3969ba55a974SMark Brown size_t count, loff_t *ppos) 3970ba55a974SMark Brown { 3971ba55a974SMark Brown char *buf = kmalloc(PAGE_SIZE, GFP_KERNEL); 3972ba55a974SMark Brown ssize_t len, ret = 0; 3973ba55a974SMark Brown struct regulator_map *map; 3974ba55a974SMark Brown 3975ba55a974SMark Brown if (!buf) 3976ba55a974SMark Brown return -ENOMEM; 3977ba55a974SMark Brown 3978ba55a974SMark Brown list_for_each_entry(map, ®ulator_map_list, list) { 3979ba55a974SMark Brown len = snprintf(buf + ret, PAGE_SIZE - ret, 3980ba55a974SMark Brown "%s -> %s.%s\n", 3981ba55a974SMark Brown rdev_get_name(map->regulator), map->dev_name, 3982ba55a974SMark Brown map->supply); 3983ba55a974SMark Brown if (len >= 0) 3984ba55a974SMark Brown ret += len; 3985ba55a974SMark Brown if (ret > PAGE_SIZE) { 3986ba55a974SMark Brown ret = PAGE_SIZE; 3987ba55a974SMark Brown break; 3988ba55a974SMark Brown } 3989ba55a974SMark Brown } 3990ba55a974SMark Brown 3991ba55a974SMark Brown ret = simple_read_from_buffer(user_buf, count, ppos, buf, ret); 3992ba55a974SMark Brown 3993ba55a974SMark Brown kfree(buf); 3994ba55a974SMark Brown 3995ba55a974SMark Brown return ret; 3996ba55a974SMark Brown } 399724751434SStephen Boyd #endif 3998ba55a974SMark Brown 3999ba55a974SMark Brown static const struct file_operations supply_map_fops = { 400024751434SStephen Boyd #ifdef CONFIG_DEBUG_FS 4001ba55a974SMark Brown .read = supply_map_read_file, 4002ba55a974SMark Brown .llseek = default_llseek, 4003ba55a974SMark Brown #endif 400424751434SStephen Boyd }; 4005ba55a974SMark Brown 40067c225ec9SHeiko Stübner #ifdef CONFIG_DEBUG_FS 40077c225ec9SHeiko Stübner static void regulator_summary_show_subtree(struct seq_file *s, 40087c225ec9SHeiko Stübner struct regulator_dev *rdev, 40097c225ec9SHeiko Stübner int level) 40107c225ec9SHeiko Stübner { 40117c225ec9SHeiko Stübner struct list_head *list = s->private; 40127c225ec9SHeiko Stübner struct regulator_dev *child; 40137c225ec9SHeiko Stübner struct regulation_constraints *c; 40147c225ec9SHeiko Stübner struct regulator *consumer; 40157c225ec9SHeiko Stübner 40167c225ec9SHeiko Stübner if (!rdev) 40177c225ec9SHeiko Stübner return; 40187c225ec9SHeiko Stübner 40197c225ec9SHeiko Stübner seq_printf(s, "%*s%-*s %3d %4d %6d ", 40207c225ec9SHeiko Stübner level * 3 + 1, "", 40217c225ec9SHeiko Stübner 30 - level * 3, rdev_get_name(rdev), 40227c225ec9SHeiko Stübner rdev->use_count, rdev->open_count, rdev->bypass_count); 40237c225ec9SHeiko Stübner 402423296099SHeiko Stübner seq_printf(s, "%5dmV ", _regulator_get_voltage(rdev) / 1000); 402523296099SHeiko Stübner seq_printf(s, "%5dmA ", _regulator_get_current_limit(rdev) / 1000); 40267c225ec9SHeiko Stübner 40277c225ec9SHeiko Stübner c = rdev->constraints; 40287c225ec9SHeiko Stübner if (c) { 40297c225ec9SHeiko Stübner switch (rdev->desc->type) { 40307c225ec9SHeiko Stübner case REGULATOR_VOLTAGE: 40317c225ec9SHeiko Stübner seq_printf(s, "%5dmV %5dmV ", 40327c225ec9SHeiko Stübner c->min_uV / 1000, c->max_uV / 1000); 40337c225ec9SHeiko Stübner break; 40347c225ec9SHeiko Stübner case REGULATOR_CURRENT: 40357c225ec9SHeiko Stübner seq_printf(s, "%5dmA %5dmA ", 40367c225ec9SHeiko Stübner c->min_uA / 1000, c->max_uA / 1000); 40377c225ec9SHeiko Stübner break; 40387c225ec9SHeiko Stübner } 40397c225ec9SHeiko Stübner } 40407c225ec9SHeiko Stübner 40417c225ec9SHeiko Stübner seq_puts(s, "\n"); 40427c225ec9SHeiko Stübner 40437c225ec9SHeiko Stübner list_for_each_entry(consumer, &rdev->consumer_list, list) { 40447c225ec9SHeiko Stübner if (consumer->dev->class == ®ulator_class) 40457c225ec9SHeiko Stübner continue; 40467c225ec9SHeiko Stübner 40477c225ec9SHeiko Stübner seq_printf(s, "%*s%-*s ", 40487c225ec9SHeiko Stübner (level + 1) * 3 + 1, "", 40497c225ec9SHeiko Stübner 30 - (level + 1) * 3, dev_name(consumer->dev)); 40507c225ec9SHeiko Stübner 40517c225ec9SHeiko Stübner switch (rdev->desc->type) { 40527c225ec9SHeiko Stübner case REGULATOR_VOLTAGE: 405323296099SHeiko Stübner seq_printf(s, "%37dmV %5dmV", 40547c225ec9SHeiko Stübner consumer->min_uV / 1000, 40557c225ec9SHeiko Stübner consumer->max_uV / 1000); 40567c225ec9SHeiko Stübner break; 40577c225ec9SHeiko Stübner case REGULATOR_CURRENT: 40587c225ec9SHeiko Stübner break; 40597c225ec9SHeiko Stübner } 40607c225ec9SHeiko Stübner 40617c225ec9SHeiko Stübner seq_puts(s, "\n"); 40627c225ec9SHeiko Stübner } 40637c225ec9SHeiko Stübner 40647c225ec9SHeiko Stübner list_for_each_entry(child, list, list) { 40657c225ec9SHeiko Stübner /* handle only non-root regulators supplied by current rdev */ 40667c225ec9SHeiko Stübner if (!child->supply || child->supply->rdev != rdev) 40677c225ec9SHeiko Stübner continue; 40687c225ec9SHeiko Stübner 40697c225ec9SHeiko Stübner regulator_summary_show_subtree(s, child, level + 1); 40707c225ec9SHeiko Stübner } 40717c225ec9SHeiko Stübner } 40727c225ec9SHeiko Stübner 40737c225ec9SHeiko Stübner static int regulator_summary_show(struct seq_file *s, void *data) 40747c225ec9SHeiko Stübner { 40757c225ec9SHeiko Stübner struct list_head *list = s->private; 40767c225ec9SHeiko Stübner struct regulator_dev *rdev; 40777c225ec9SHeiko Stübner 407823296099SHeiko Stübner seq_puts(s, " regulator use open bypass voltage current min max\n"); 407923296099SHeiko Stübner seq_puts(s, "-------------------------------------------------------------------------------\n"); 40807c225ec9SHeiko Stübner 40817c225ec9SHeiko Stübner mutex_lock(®ulator_list_mutex); 40827c225ec9SHeiko Stübner 40837c225ec9SHeiko Stübner list_for_each_entry(rdev, list, list) { 40847c225ec9SHeiko Stübner if (rdev->supply) 40857c225ec9SHeiko Stübner continue; 40867c225ec9SHeiko Stübner 40877c225ec9SHeiko Stübner regulator_summary_show_subtree(s, rdev, 0); 40887c225ec9SHeiko Stübner } 40897c225ec9SHeiko Stübner 40907c225ec9SHeiko Stübner mutex_unlock(®ulator_list_mutex); 40917c225ec9SHeiko Stübner 40927c225ec9SHeiko Stübner return 0; 40937c225ec9SHeiko Stübner } 40947c225ec9SHeiko Stübner 40957c225ec9SHeiko Stübner static int regulator_summary_open(struct inode *inode, struct file *file) 40967c225ec9SHeiko Stübner { 40977c225ec9SHeiko Stübner return single_open(file, regulator_summary_show, inode->i_private); 40987c225ec9SHeiko Stübner } 40997c225ec9SHeiko Stübner #endif 41007c225ec9SHeiko Stübner 41017c225ec9SHeiko Stübner static const struct file_operations regulator_summary_fops = { 41027c225ec9SHeiko Stübner #ifdef CONFIG_DEBUG_FS 41037c225ec9SHeiko Stübner .open = regulator_summary_open, 41047c225ec9SHeiko Stübner .read = seq_read, 41057c225ec9SHeiko Stübner .llseek = seq_lseek, 41067c225ec9SHeiko Stübner .release = single_release, 41077c225ec9SHeiko Stübner #endif 41087c225ec9SHeiko Stübner }; 41097c225ec9SHeiko Stübner 4110414c70cbSLiam Girdwood static int __init regulator_init(void) 4111414c70cbSLiam Girdwood { 411234abbd68SMark Brown int ret; 411334abbd68SMark Brown 411434abbd68SMark Brown ret = class_register(®ulator_class); 411534abbd68SMark Brown 41161130e5b3SMark Brown debugfs_root = debugfs_create_dir("regulator", NULL); 411724751434SStephen Boyd if (!debugfs_root) 41181130e5b3SMark Brown pr_warn("regulator: Failed to create debugfs directory\n"); 4119ba55a974SMark Brown 4120f4d562c6SMark Brown debugfs_create_file("supply_map", 0444, debugfs_root, NULL, 4121f4d562c6SMark Brown &supply_map_fops); 41221130e5b3SMark Brown 41237c225ec9SHeiko Stübner debugfs_create_file("regulator_summary", 0444, debugfs_root, 41247c225ec9SHeiko Stübner ®ulator_list, ®ulator_summary_fops); 41257c225ec9SHeiko Stübner 412634abbd68SMark Brown regulator_dummy_init(); 412734abbd68SMark Brown 412834abbd68SMark Brown return ret; 4129414c70cbSLiam Girdwood } 4130414c70cbSLiam Girdwood 4131414c70cbSLiam Girdwood /* init early to allow our consumers to complete system booting */ 4132414c70cbSLiam Girdwood core_initcall(regulator_init); 4133ca725561SMark Brown 4134ca725561SMark Brown static int __init regulator_init_complete(void) 4135ca725561SMark Brown { 4136ca725561SMark Brown struct regulator_dev *rdev; 4137272e2315SGuodong Xu const struct regulator_ops *ops; 4138ca725561SMark Brown struct regulation_constraints *c; 4139ca725561SMark Brown int enabled, ret; 4140ca725561SMark Brown 414186f5fcfcSMark Brown /* 414286f5fcfcSMark Brown * Since DT doesn't provide an idiomatic mechanism for 414386f5fcfcSMark Brown * enabling full constraints and since it's much more natural 414486f5fcfcSMark Brown * with DT to provide them just assume that a DT enabled 414586f5fcfcSMark Brown * system has full constraints. 414686f5fcfcSMark Brown */ 414786f5fcfcSMark Brown if (of_have_populated_dt()) 414886f5fcfcSMark Brown has_full_constraints = true; 414986f5fcfcSMark Brown 4150ca725561SMark Brown mutex_lock(®ulator_list_mutex); 4151ca725561SMark Brown 4152ca725561SMark Brown /* If we have a full configuration then disable any regulators 4153e9535834SMark Brown * we have permission to change the status for and which are 4154e9535834SMark Brown * not in use or always_on. This is effectively the default 4155e9535834SMark Brown * for DT and ACPI as they have full constraints. 4156ca725561SMark Brown */ 4157ca725561SMark Brown list_for_each_entry(rdev, ®ulator_list, list) { 4158ca725561SMark Brown ops = rdev->desc->ops; 4159ca725561SMark Brown c = rdev->constraints; 4160ca725561SMark Brown 416166fda75fSMarkus Pargmann if (c && c->always_on) 4162ca725561SMark Brown continue; 4163ca725561SMark Brown 4164e9535834SMark Brown if (c && !(c->valid_ops_mask & REGULATOR_CHANGE_STATUS)) 4165e9535834SMark Brown continue; 4166e9535834SMark Brown 4167ca725561SMark Brown mutex_lock(&rdev->mutex); 4168ca725561SMark Brown 4169ca725561SMark Brown if (rdev->use_count) 4170ca725561SMark Brown goto unlock; 4171ca725561SMark Brown 4172ca725561SMark Brown /* If we can't read the status assume it's on. */ 4173ca725561SMark Brown if (ops->is_enabled) 4174ca725561SMark Brown enabled = ops->is_enabled(rdev); 4175ca725561SMark Brown else 4176ca725561SMark Brown enabled = 1; 4177ca725561SMark Brown 4178ca725561SMark Brown if (!enabled) 4179ca725561SMark Brown goto unlock; 4180ca725561SMark Brown 418187b28417SMark Brown if (have_full_constraints()) { 4182ca725561SMark Brown /* We log since this may kill the system if it 4183ca725561SMark Brown * goes wrong. */ 41845da84fd9SJoe Perches rdev_info(rdev, "disabling\n"); 418566fda75fSMarkus Pargmann ret = _regulator_do_disable(rdev); 41860d25d09dSJingoo Han if (ret != 0) 41875da84fd9SJoe Perches rdev_err(rdev, "couldn't disable: %d\n", ret); 4188ca725561SMark Brown } else { 4189ca725561SMark Brown /* The intention is that in future we will 4190ca725561SMark Brown * assume that full constraints are provided 4191ca725561SMark Brown * so warn even if we aren't going to do 4192ca725561SMark Brown * anything here. 4193ca725561SMark Brown */ 41945da84fd9SJoe Perches rdev_warn(rdev, "incomplete constraints, leaving on\n"); 4195ca725561SMark Brown } 4196ca725561SMark Brown 4197ca725561SMark Brown unlock: 4198ca725561SMark Brown mutex_unlock(&rdev->mutex); 4199ca725561SMark Brown } 4200ca725561SMark Brown 4201ca725561SMark Brown mutex_unlock(®ulator_list_mutex); 4202ca725561SMark Brown 4203ca725561SMark Brown return 0; 4204ca725561SMark Brown } 4205fd482a3eSSaravana Kannan late_initcall_sync(regulator_init_complete); 4206