1414c70cbSLiam Girdwood /* 2414c70cbSLiam Girdwood * core.c -- Voltage/Current Regulator framework. 3414c70cbSLiam Girdwood * 4414c70cbSLiam Girdwood * Copyright 2007, 2008 Wolfson Microelectronics PLC. 5a5766f11SLiam Girdwood * Copyright 2008 SlimLogic Ltd. 6414c70cbSLiam Girdwood * 7a5766f11SLiam Girdwood * Author: Liam Girdwood <lrg@slimlogic.co.uk> 8414c70cbSLiam Girdwood * 9414c70cbSLiam Girdwood * This program is free software; you can redistribute it and/or modify it 10414c70cbSLiam Girdwood * under the terms of the GNU General Public License as published by the 11414c70cbSLiam Girdwood * Free Software Foundation; either version 2 of the License, or (at your 12414c70cbSLiam Girdwood * option) any later version. 13414c70cbSLiam Girdwood * 14414c70cbSLiam Girdwood */ 15414c70cbSLiam Girdwood 16414c70cbSLiam Girdwood #include <linux/kernel.h> 17414c70cbSLiam Girdwood #include <linux/init.h> 181130e5b3SMark Brown #include <linux/debugfs.h> 19414c70cbSLiam Girdwood #include <linux/device.h> 205a0e3ad6STejun Heo #include <linux/slab.h> 21f21e0e81SMark Brown #include <linux/async.h> 22414c70cbSLiam Girdwood #include <linux/err.h> 23414c70cbSLiam Girdwood #include <linux/mutex.h> 24414c70cbSLiam Girdwood #include <linux/suspend.h> 2531aae2beSMark Brown #include <linux/delay.h> 2665f73508SMark Brown #include <linux/gpio.h> 2769511a45SRajendra Nayak #include <linux/of.h> 2865b19ce6SMark Brown #include <linux/regmap.h> 2969511a45SRajendra Nayak #include <linux/regulator/of_regulator.h> 30414c70cbSLiam Girdwood #include <linux/regulator/consumer.h> 31414c70cbSLiam Girdwood #include <linux/regulator/driver.h> 32414c70cbSLiam Girdwood #include <linux/regulator/machine.h> 3365602c32SPaul Gortmaker #include <linux/module.h> 34414c70cbSLiam Girdwood 3502fa3ec0SMark Brown #define CREATE_TRACE_POINTS 3602fa3ec0SMark Brown #include <trace/events/regulator.h> 3702fa3ec0SMark Brown 3834abbd68SMark Brown #include "dummy.h" 390cdfcc0fSMark Brown #include "internal.h" 4034abbd68SMark Brown 417d51a0dbSMark Brown #define rdev_crit(rdev, fmt, ...) \ 427d51a0dbSMark Brown pr_crit("%s: " fmt, rdev_get_name(rdev), ##__VA_ARGS__) 435da84fd9SJoe Perches #define rdev_err(rdev, fmt, ...) \ 445da84fd9SJoe Perches pr_err("%s: " fmt, rdev_get_name(rdev), ##__VA_ARGS__) 455da84fd9SJoe Perches #define rdev_warn(rdev, fmt, ...) \ 465da84fd9SJoe Perches pr_warn("%s: " fmt, rdev_get_name(rdev), ##__VA_ARGS__) 475da84fd9SJoe Perches #define rdev_info(rdev, fmt, ...) \ 485da84fd9SJoe Perches pr_info("%s: " fmt, rdev_get_name(rdev), ##__VA_ARGS__) 495da84fd9SJoe Perches #define rdev_dbg(rdev, fmt, ...) \ 505da84fd9SJoe Perches pr_debug("%s: " fmt, rdev_get_name(rdev), ##__VA_ARGS__) 515da84fd9SJoe Perches 52414c70cbSLiam Girdwood static DEFINE_MUTEX(regulator_list_mutex); 53414c70cbSLiam Girdwood static LIST_HEAD(regulator_list); 54414c70cbSLiam Girdwood static LIST_HEAD(regulator_map_list); 55f19b00daSKim, Milo static LIST_HEAD(regulator_ena_gpio_list); 56a06ccd9cSCharles Keepax static LIST_HEAD(regulator_supply_alias_list); 5721cf891aSMark Brown static bool has_full_constraints; 58414c70cbSLiam Girdwood 591130e5b3SMark Brown static struct dentry *debugfs_root; 601130e5b3SMark Brown 618dc5390dSMark Brown /* 62414c70cbSLiam Girdwood * struct regulator_map 63414c70cbSLiam Girdwood * 64414c70cbSLiam Girdwood * Used to provide symbolic supply names to devices. 65414c70cbSLiam Girdwood */ 66414c70cbSLiam Girdwood struct regulator_map { 67414c70cbSLiam Girdwood struct list_head list; 6840f9244fSMark Brown const char *dev_name; /* The dev_name() for the consumer */ 69414c70cbSLiam Girdwood const char *supply; 70a5766f11SLiam Girdwood struct regulator_dev *regulator; 71414c70cbSLiam Girdwood }; 72414c70cbSLiam Girdwood 73414c70cbSLiam Girdwood /* 74f19b00daSKim, Milo * struct regulator_enable_gpio 75f19b00daSKim, Milo * 76f19b00daSKim, Milo * Management for shared enable GPIO pin 77f19b00daSKim, Milo */ 78f19b00daSKim, Milo struct regulator_enable_gpio { 79f19b00daSKim, Milo struct list_head list; 80f19b00daSKim, Milo int gpio; 81f19b00daSKim, Milo u32 enable_count; /* a number of enabled shared GPIO */ 82f19b00daSKim, Milo u32 request_count; /* a number of requested shared GPIO */ 83f19b00daSKim, Milo unsigned int ena_gpio_invert:1; 84f19b00daSKim, Milo }; 85f19b00daSKim, Milo 86a06ccd9cSCharles Keepax /* 87a06ccd9cSCharles Keepax * struct regulator_supply_alias 88a06ccd9cSCharles Keepax * 89a06ccd9cSCharles Keepax * Used to map lookups for a supply onto an alternative device. 90a06ccd9cSCharles Keepax */ 91a06ccd9cSCharles Keepax struct regulator_supply_alias { 92a06ccd9cSCharles Keepax struct list_head list; 93a06ccd9cSCharles Keepax struct device *src_dev; 94a06ccd9cSCharles Keepax const char *src_supply; 95a06ccd9cSCharles Keepax struct device *alias_dev; 96a06ccd9cSCharles Keepax const char *alias_supply; 97a06ccd9cSCharles Keepax }; 98a06ccd9cSCharles Keepax 99414c70cbSLiam Girdwood static int _regulator_is_enabled(struct regulator_dev *rdev); 1003801b86aSMark Brown static int _regulator_disable(struct regulator_dev *rdev); 101414c70cbSLiam Girdwood static int _regulator_get_voltage(struct regulator_dev *rdev); 102414c70cbSLiam Girdwood static int _regulator_get_current_limit(struct regulator_dev *rdev); 103414c70cbSLiam Girdwood static unsigned int _regulator_get_mode(struct regulator_dev *rdev); 104414c70cbSLiam Girdwood static void _notifier_call_chain(struct regulator_dev *rdev, 105414c70cbSLiam Girdwood unsigned long event, void *data); 10675790251SMark Brown static int _regulator_do_set_voltage(struct regulator_dev *rdev, 10775790251SMark Brown int min_uV, int max_uV); 1083801b86aSMark Brown static struct regulator *create_regulator(struct regulator_dev *rdev, 1093801b86aSMark Brown struct device *dev, 1103801b86aSMark Brown const char *supply_name); 111414c70cbSLiam Girdwood 1121083c393SMark Brown static const char *rdev_get_name(struct regulator_dev *rdev) 1131083c393SMark Brown { 1141083c393SMark Brown if (rdev->constraints && rdev->constraints->name) 1151083c393SMark Brown return rdev->constraints->name; 1161083c393SMark Brown else if (rdev->desc->name) 1171083c393SMark Brown return rdev->desc->name; 1181083c393SMark Brown else 1191083c393SMark Brown return ""; 1201083c393SMark Brown } 1211083c393SMark Brown 12287b28417SMark Brown static bool have_full_constraints(void) 12387b28417SMark Brown { 12475bc9641SMark Brown return has_full_constraints || of_have_populated_dt(); 12587b28417SMark Brown } 12687b28417SMark Brown 12769511a45SRajendra Nayak /** 12869511a45SRajendra Nayak * of_get_regulator - get a regulator device node based on supply name 12969511a45SRajendra Nayak * @dev: Device pointer for the consumer (of regulator) device 13069511a45SRajendra Nayak * @supply: regulator supply name 13169511a45SRajendra Nayak * 13269511a45SRajendra Nayak * Extract the regulator device node corresponding to the supply name. 133167d41dcSMaxime Ripard * returns the device node corresponding to the regulator if found, else 13469511a45SRajendra Nayak * returns NULL. 13569511a45SRajendra Nayak */ 13669511a45SRajendra Nayak static struct device_node *of_get_regulator(struct device *dev, const char *supply) 13769511a45SRajendra Nayak { 13869511a45SRajendra Nayak struct device_node *regnode = NULL; 13969511a45SRajendra Nayak char prop_name[32]; /* 32 is max size of property name */ 14069511a45SRajendra Nayak 14169511a45SRajendra Nayak dev_dbg(dev, "Looking up %s-supply from device tree\n", supply); 14269511a45SRajendra Nayak 14369511a45SRajendra Nayak snprintf(prop_name, 32, "%s-supply", supply); 14469511a45SRajendra Nayak regnode = of_parse_phandle(dev->of_node, prop_name, 0); 14569511a45SRajendra Nayak 14669511a45SRajendra Nayak if (!regnode) { 14716fbcc3bSRajendra Nayak dev_dbg(dev, "Looking up %s property in node %s failed", 14869511a45SRajendra Nayak prop_name, dev->of_node->full_name); 14969511a45SRajendra Nayak return NULL; 15069511a45SRajendra Nayak } 15169511a45SRajendra Nayak return regnode; 15269511a45SRajendra Nayak } 15369511a45SRajendra Nayak 1546492bc1bSMark Brown static int _regulator_can_change_status(struct regulator_dev *rdev) 1556492bc1bSMark Brown { 1566492bc1bSMark Brown if (!rdev->constraints) 1576492bc1bSMark Brown return 0; 1586492bc1bSMark Brown 1596492bc1bSMark Brown if (rdev->constraints->valid_ops_mask & REGULATOR_CHANGE_STATUS) 1606492bc1bSMark Brown return 1; 1616492bc1bSMark Brown else 1626492bc1bSMark Brown return 0; 1636492bc1bSMark Brown } 1646492bc1bSMark Brown 165414c70cbSLiam Girdwood /* Platform voltage constraint check */ 166414c70cbSLiam Girdwood static int regulator_check_voltage(struct regulator_dev *rdev, 167414c70cbSLiam Girdwood int *min_uV, int *max_uV) 168414c70cbSLiam Girdwood { 169414c70cbSLiam Girdwood BUG_ON(*min_uV > *max_uV); 170414c70cbSLiam Girdwood 171414c70cbSLiam Girdwood if (!rdev->constraints) { 1725da84fd9SJoe Perches rdev_err(rdev, "no constraints\n"); 173414c70cbSLiam Girdwood return -ENODEV; 174414c70cbSLiam Girdwood } 175414c70cbSLiam Girdwood if (!(rdev->constraints->valid_ops_mask & REGULATOR_CHANGE_VOLTAGE)) { 1765da84fd9SJoe Perches rdev_err(rdev, "operation not allowed\n"); 177414c70cbSLiam Girdwood return -EPERM; 178414c70cbSLiam Girdwood } 179414c70cbSLiam Girdwood 180414c70cbSLiam Girdwood if (*max_uV > rdev->constraints->max_uV) 181414c70cbSLiam Girdwood *max_uV = rdev->constraints->max_uV; 182414c70cbSLiam Girdwood if (*min_uV < rdev->constraints->min_uV) 183414c70cbSLiam Girdwood *min_uV = rdev->constraints->min_uV; 184414c70cbSLiam Girdwood 18589f425edSMark Brown if (*min_uV > *max_uV) { 18689f425edSMark Brown rdev_err(rdev, "unsupportable voltage range: %d-%duV\n", 18754abd335SMark Brown *min_uV, *max_uV); 188414c70cbSLiam Girdwood return -EINVAL; 18989f425edSMark Brown } 190414c70cbSLiam Girdwood 191414c70cbSLiam Girdwood return 0; 192414c70cbSLiam Girdwood } 193414c70cbSLiam Girdwood 19405fda3b1SThomas Petazzoni /* Make sure we select a voltage that suits the needs of all 19505fda3b1SThomas Petazzoni * regulator consumers 19605fda3b1SThomas Petazzoni */ 19705fda3b1SThomas Petazzoni static int regulator_check_consumers(struct regulator_dev *rdev, 19805fda3b1SThomas Petazzoni int *min_uV, int *max_uV) 19905fda3b1SThomas Petazzoni { 20005fda3b1SThomas Petazzoni struct regulator *regulator; 20105fda3b1SThomas Petazzoni 20205fda3b1SThomas Petazzoni list_for_each_entry(regulator, &rdev->consumer_list, list) { 2034aa922c0SMark Brown /* 2044aa922c0SMark Brown * Assume consumers that didn't say anything are OK 2054aa922c0SMark Brown * with anything in the constraint range. 2064aa922c0SMark Brown */ 2074aa922c0SMark Brown if (!regulator->min_uV && !regulator->max_uV) 2084aa922c0SMark Brown continue; 2094aa922c0SMark Brown 21005fda3b1SThomas Petazzoni if (*max_uV > regulator->max_uV) 21105fda3b1SThomas Petazzoni *max_uV = regulator->max_uV; 21205fda3b1SThomas Petazzoni if (*min_uV < regulator->min_uV) 21305fda3b1SThomas Petazzoni *min_uV = regulator->min_uV; 21405fda3b1SThomas Petazzoni } 21505fda3b1SThomas Petazzoni 216dd8004afSMark Brown if (*min_uV > *max_uV) { 2179c7b4e8aSRuss Dill rdev_err(rdev, "Restricting voltage, %u-%uuV\n", 2189c7b4e8aSRuss Dill *min_uV, *max_uV); 21905fda3b1SThomas Petazzoni return -EINVAL; 220dd8004afSMark Brown } 22105fda3b1SThomas Petazzoni 22205fda3b1SThomas Petazzoni return 0; 22305fda3b1SThomas Petazzoni } 22405fda3b1SThomas Petazzoni 225414c70cbSLiam Girdwood /* current constraint check */ 226414c70cbSLiam Girdwood static int regulator_check_current_limit(struct regulator_dev *rdev, 227414c70cbSLiam Girdwood int *min_uA, int *max_uA) 228414c70cbSLiam Girdwood { 229414c70cbSLiam Girdwood BUG_ON(*min_uA > *max_uA); 230414c70cbSLiam Girdwood 231414c70cbSLiam Girdwood if (!rdev->constraints) { 2325da84fd9SJoe Perches rdev_err(rdev, "no constraints\n"); 233414c70cbSLiam Girdwood return -ENODEV; 234414c70cbSLiam Girdwood } 235414c70cbSLiam Girdwood if (!(rdev->constraints->valid_ops_mask & REGULATOR_CHANGE_CURRENT)) { 2365da84fd9SJoe Perches rdev_err(rdev, "operation not allowed\n"); 237414c70cbSLiam Girdwood return -EPERM; 238414c70cbSLiam Girdwood } 239414c70cbSLiam Girdwood 240414c70cbSLiam Girdwood if (*max_uA > rdev->constraints->max_uA) 241414c70cbSLiam Girdwood *max_uA = rdev->constraints->max_uA; 242414c70cbSLiam Girdwood if (*min_uA < rdev->constraints->min_uA) 243414c70cbSLiam Girdwood *min_uA = rdev->constraints->min_uA; 244414c70cbSLiam Girdwood 24589f425edSMark Brown if (*min_uA > *max_uA) { 24689f425edSMark Brown rdev_err(rdev, "unsupportable current range: %d-%duA\n", 24754abd335SMark Brown *min_uA, *max_uA); 248414c70cbSLiam Girdwood return -EINVAL; 24989f425edSMark Brown } 250414c70cbSLiam Girdwood 251414c70cbSLiam Girdwood return 0; 252414c70cbSLiam Girdwood } 253414c70cbSLiam Girdwood 254414c70cbSLiam Girdwood /* operating mode constraint check */ 2552c608234SMark Brown static int regulator_mode_constrain(struct regulator_dev *rdev, int *mode) 256414c70cbSLiam Girdwood { 2572c608234SMark Brown switch (*mode) { 258e573520bSDavid Brownell case REGULATOR_MODE_FAST: 259e573520bSDavid Brownell case REGULATOR_MODE_NORMAL: 260e573520bSDavid Brownell case REGULATOR_MODE_IDLE: 261e573520bSDavid Brownell case REGULATOR_MODE_STANDBY: 262e573520bSDavid Brownell break; 263e573520bSDavid Brownell default: 26489f425edSMark Brown rdev_err(rdev, "invalid mode %x specified\n", *mode); 265e573520bSDavid Brownell return -EINVAL; 266e573520bSDavid Brownell } 267e573520bSDavid Brownell 268414c70cbSLiam Girdwood if (!rdev->constraints) { 2695da84fd9SJoe Perches rdev_err(rdev, "no constraints\n"); 270414c70cbSLiam Girdwood return -ENODEV; 271414c70cbSLiam Girdwood } 272414c70cbSLiam Girdwood if (!(rdev->constraints->valid_ops_mask & REGULATOR_CHANGE_MODE)) { 2735da84fd9SJoe Perches rdev_err(rdev, "operation not allowed\n"); 274414c70cbSLiam Girdwood return -EPERM; 275414c70cbSLiam Girdwood } 2762c608234SMark Brown 2772c608234SMark Brown /* The modes are bitmasks, the most power hungry modes having 2782c608234SMark Brown * the lowest values. If the requested mode isn't supported 2792c608234SMark Brown * try higher modes. */ 2802c608234SMark Brown while (*mode) { 2812c608234SMark Brown if (rdev->constraints->valid_modes_mask & *mode) 282414c70cbSLiam Girdwood return 0; 2832c608234SMark Brown *mode /= 2; 2842c608234SMark Brown } 2852c608234SMark Brown 2862c608234SMark Brown return -EINVAL; 287414c70cbSLiam Girdwood } 288414c70cbSLiam Girdwood 289414c70cbSLiam Girdwood /* dynamic regulator mode switching constraint check */ 290414c70cbSLiam Girdwood static int regulator_check_drms(struct regulator_dev *rdev) 291414c70cbSLiam Girdwood { 292414c70cbSLiam Girdwood if (!rdev->constraints) { 2935da84fd9SJoe Perches rdev_err(rdev, "no constraints\n"); 294414c70cbSLiam Girdwood return -ENODEV; 295414c70cbSLiam Girdwood } 296414c70cbSLiam Girdwood if (!(rdev->constraints->valid_ops_mask & REGULATOR_CHANGE_DRMS)) { 2975da84fd9SJoe Perches rdev_err(rdev, "operation not allowed\n"); 298414c70cbSLiam Girdwood return -EPERM; 299414c70cbSLiam Girdwood } 300414c70cbSLiam Girdwood return 0; 301414c70cbSLiam Girdwood } 302414c70cbSLiam Girdwood 303414c70cbSLiam Girdwood static ssize_t regulator_uV_show(struct device *dev, 304414c70cbSLiam Girdwood struct device_attribute *attr, char *buf) 305414c70cbSLiam Girdwood { 306a5766f11SLiam Girdwood struct regulator_dev *rdev = dev_get_drvdata(dev); 307414c70cbSLiam Girdwood ssize_t ret; 308414c70cbSLiam Girdwood 309414c70cbSLiam Girdwood mutex_lock(&rdev->mutex); 310414c70cbSLiam Girdwood ret = sprintf(buf, "%d\n", _regulator_get_voltage(rdev)); 311414c70cbSLiam Girdwood mutex_unlock(&rdev->mutex); 312414c70cbSLiam Girdwood 313414c70cbSLiam Girdwood return ret; 314414c70cbSLiam Girdwood } 3157ad68e2fSDavid Brownell static DEVICE_ATTR(microvolts, 0444, regulator_uV_show, NULL); 316414c70cbSLiam Girdwood 317414c70cbSLiam Girdwood static ssize_t regulator_uA_show(struct device *dev, 318414c70cbSLiam Girdwood struct device_attribute *attr, char *buf) 319414c70cbSLiam Girdwood { 320a5766f11SLiam Girdwood struct regulator_dev *rdev = dev_get_drvdata(dev); 321414c70cbSLiam Girdwood 322414c70cbSLiam Girdwood return sprintf(buf, "%d\n", _regulator_get_current_limit(rdev)); 323414c70cbSLiam Girdwood } 3247ad68e2fSDavid Brownell static DEVICE_ATTR(microamps, 0444, regulator_uA_show, NULL); 325414c70cbSLiam Girdwood 326587cea27SGreg Kroah-Hartman static ssize_t name_show(struct device *dev, struct device_attribute *attr, 327587cea27SGreg Kroah-Hartman char *buf) 328bc558a60SMark Brown { 329bc558a60SMark Brown struct regulator_dev *rdev = dev_get_drvdata(dev); 330bc558a60SMark Brown 3311083c393SMark Brown return sprintf(buf, "%s\n", rdev_get_name(rdev)); 332bc558a60SMark Brown } 333587cea27SGreg Kroah-Hartman static DEVICE_ATTR_RO(name); 334bc558a60SMark Brown 3354fca9545SDavid Brownell static ssize_t regulator_print_opmode(char *buf, int mode) 336414c70cbSLiam Girdwood { 337414c70cbSLiam Girdwood switch (mode) { 338414c70cbSLiam Girdwood case REGULATOR_MODE_FAST: 339414c70cbSLiam Girdwood return sprintf(buf, "fast\n"); 340414c70cbSLiam Girdwood case REGULATOR_MODE_NORMAL: 341414c70cbSLiam Girdwood return sprintf(buf, "normal\n"); 342414c70cbSLiam Girdwood case REGULATOR_MODE_IDLE: 343414c70cbSLiam Girdwood return sprintf(buf, "idle\n"); 344414c70cbSLiam Girdwood case REGULATOR_MODE_STANDBY: 345414c70cbSLiam Girdwood return sprintf(buf, "standby\n"); 346414c70cbSLiam Girdwood } 347414c70cbSLiam Girdwood return sprintf(buf, "unknown\n"); 348414c70cbSLiam Girdwood } 349414c70cbSLiam Girdwood 3504fca9545SDavid Brownell static ssize_t regulator_opmode_show(struct device *dev, 351414c70cbSLiam Girdwood struct device_attribute *attr, char *buf) 352414c70cbSLiam Girdwood { 353a5766f11SLiam Girdwood struct regulator_dev *rdev = dev_get_drvdata(dev); 354414c70cbSLiam Girdwood 3554fca9545SDavid Brownell return regulator_print_opmode(buf, _regulator_get_mode(rdev)); 3564fca9545SDavid Brownell } 3577ad68e2fSDavid Brownell static DEVICE_ATTR(opmode, 0444, regulator_opmode_show, NULL); 3584fca9545SDavid Brownell 3594fca9545SDavid Brownell static ssize_t regulator_print_state(char *buf, int state) 3604fca9545SDavid Brownell { 361414c70cbSLiam Girdwood if (state > 0) 362414c70cbSLiam Girdwood return sprintf(buf, "enabled\n"); 363414c70cbSLiam Girdwood else if (state == 0) 364414c70cbSLiam Girdwood return sprintf(buf, "disabled\n"); 365414c70cbSLiam Girdwood else 366414c70cbSLiam Girdwood return sprintf(buf, "unknown\n"); 367414c70cbSLiam Girdwood } 368414c70cbSLiam Girdwood 3694fca9545SDavid Brownell static ssize_t regulator_state_show(struct device *dev, 3704fca9545SDavid Brownell struct device_attribute *attr, char *buf) 3714fca9545SDavid Brownell { 3724fca9545SDavid Brownell struct regulator_dev *rdev = dev_get_drvdata(dev); 3739332546fSMark Brown ssize_t ret; 3744fca9545SDavid Brownell 3759332546fSMark Brown mutex_lock(&rdev->mutex); 3769332546fSMark Brown ret = regulator_print_state(buf, _regulator_is_enabled(rdev)); 3779332546fSMark Brown mutex_unlock(&rdev->mutex); 3789332546fSMark Brown 3799332546fSMark Brown return ret; 3804fca9545SDavid Brownell } 3817ad68e2fSDavid Brownell static DEVICE_ATTR(state, 0444, regulator_state_show, NULL); 3824fca9545SDavid Brownell 383853116a1SDavid Brownell static ssize_t regulator_status_show(struct device *dev, 384853116a1SDavid Brownell struct device_attribute *attr, char *buf) 385853116a1SDavid Brownell { 386853116a1SDavid Brownell struct regulator_dev *rdev = dev_get_drvdata(dev); 387853116a1SDavid Brownell int status; 388853116a1SDavid Brownell char *label; 389853116a1SDavid Brownell 390853116a1SDavid Brownell status = rdev->desc->ops->get_status(rdev); 391853116a1SDavid Brownell if (status < 0) 392853116a1SDavid Brownell return status; 393853116a1SDavid Brownell 394853116a1SDavid Brownell switch (status) { 395853116a1SDavid Brownell case REGULATOR_STATUS_OFF: 396853116a1SDavid Brownell label = "off"; 397853116a1SDavid Brownell break; 398853116a1SDavid Brownell case REGULATOR_STATUS_ON: 399853116a1SDavid Brownell label = "on"; 400853116a1SDavid Brownell break; 401853116a1SDavid Brownell case REGULATOR_STATUS_ERROR: 402853116a1SDavid Brownell label = "error"; 403853116a1SDavid Brownell break; 404853116a1SDavid Brownell case REGULATOR_STATUS_FAST: 405853116a1SDavid Brownell label = "fast"; 406853116a1SDavid Brownell break; 407853116a1SDavid Brownell case REGULATOR_STATUS_NORMAL: 408853116a1SDavid Brownell label = "normal"; 409853116a1SDavid Brownell break; 410853116a1SDavid Brownell case REGULATOR_STATUS_IDLE: 411853116a1SDavid Brownell label = "idle"; 412853116a1SDavid Brownell break; 413853116a1SDavid Brownell case REGULATOR_STATUS_STANDBY: 414853116a1SDavid Brownell label = "standby"; 415853116a1SDavid Brownell break; 416f59c8f9fSMark Brown case REGULATOR_STATUS_BYPASS: 417f59c8f9fSMark Brown label = "bypass"; 418f59c8f9fSMark Brown break; 4191beaf762SKrystian Garbaciak case REGULATOR_STATUS_UNDEFINED: 4201beaf762SKrystian Garbaciak label = "undefined"; 4211beaf762SKrystian Garbaciak break; 422853116a1SDavid Brownell default: 423853116a1SDavid Brownell return -ERANGE; 424853116a1SDavid Brownell } 425853116a1SDavid Brownell 426853116a1SDavid Brownell return sprintf(buf, "%s\n", label); 427853116a1SDavid Brownell } 428853116a1SDavid Brownell static DEVICE_ATTR(status, 0444, regulator_status_show, NULL); 429853116a1SDavid Brownell 430414c70cbSLiam Girdwood static ssize_t regulator_min_uA_show(struct device *dev, 431414c70cbSLiam Girdwood struct device_attribute *attr, char *buf) 432414c70cbSLiam Girdwood { 433a5766f11SLiam Girdwood struct regulator_dev *rdev = dev_get_drvdata(dev); 434414c70cbSLiam Girdwood 435414c70cbSLiam Girdwood if (!rdev->constraints) 436414c70cbSLiam Girdwood return sprintf(buf, "constraint not defined\n"); 437414c70cbSLiam Girdwood 438414c70cbSLiam Girdwood return sprintf(buf, "%d\n", rdev->constraints->min_uA); 439414c70cbSLiam Girdwood } 4407ad68e2fSDavid Brownell static DEVICE_ATTR(min_microamps, 0444, regulator_min_uA_show, NULL); 441414c70cbSLiam Girdwood 442414c70cbSLiam Girdwood static ssize_t regulator_max_uA_show(struct device *dev, 443414c70cbSLiam Girdwood struct device_attribute *attr, char *buf) 444414c70cbSLiam Girdwood { 445a5766f11SLiam Girdwood struct regulator_dev *rdev = dev_get_drvdata(dev); 446414c70cbSLiam Girdwood 447414c70cbSLiam Girdwood if (!rdev->constraints) 448414c70cbSLiam Girdwood return sprintf(buf, "constraint not defined\n"); 449414c70cbSLiam Girdwood 450414c70cbSLiam Girdwood return sprintf(buf, "%d\n", rdev->constraints->max_uA); 451414c70cbSLiam Girdwood } 4527ad68e2fSDavid Brownell static DEVICE_ATTR(max_microamps, 0444, regulator_max_uA_show, NULL); 453414c70cbSLiam Girdwood 454414c70cbSLiam Girdwood static ssize_t regulator_min_uV_show(struct device *dev, 455414c70cbSLiam Girdwood struct device_attribute *attr, char *buf) 456414c70cbSLiam Girdwood { 457a5766f11SLiam Girdwood struct regulator_dev *rdev = dev_get_drvdata(dev); 458414c70cbSLiam Girdwood 459414c70cbSLiam Girdwood if (!rdev->constraints) 460414c70cbSLiam Girdwood return sprintf(buf, "constraint not defined\n"); 461414c70cbSLiam Girdwood 462414c70cbSLiam Girdwood return sprintf(buf, "%d\n", rdev->constraints->min_uV); 463414c70cbSLiam Girdwood } 4647ad68e2fSDavid Brownell static DEVICE_ATTR(min_microvolts, 0444, regulator_min_uV_show, NULL); 465414c70cbSLiam Girdwood 466414c70cbSLiam Girdwood static ssize_t regulator_max_uV_show(struct device *dev, 467414c70cbSLiam Girdwood struct device_attribute *attr, char *buf) 468414c70cbSLiam Girdwood { 469a5766f11SLiam Girdwood struct regulator_dev *rdev = dev_get_drvdata(dev); 470414c70cbSLiam Girdwood 471414c70cbSLiam Girdwood if (!rdev->constraints) 472414c70cbSLiam Girdwood return sprintf(buf, "constraint not defined\n"); 473414c70cbSLiam Girdwood 474414c70cbSLiam Girdwood return sprintf(buf, "%d\n", rdev->constraints->max_uV); 475414c70cbSLiam Girdwood } 4767ad68e2fSDavid Brownell static DEVICE_ATTR(max_microvolts, 0444, regulator_max_uV_show, NULL); 477414c70cbSLiam Girdwood 478414c70cbSLiam Girdwood static ssize_t regulator_total_uA_show(struct device *dev, 479414c70cbSLiam Girdwood struct device_attribute *attr, char *buf) 480414c70cbSLiam Girdwood { 481a5766f11SLiam Girdwood struct regulator_dev *rdev = dev_get_drvdata(dev); 482414c70cbSLiam Girdwood struct regulator *regulator; 483414c70cbSLiam Girdwood int uA = 0; 484414c70cbSLiam Girdwood 485414c70cbSLiam Girdwood mutex_lock(&rdev->mutex); 486414c70cbSLiam Girdwood list_for_each_entry(regulator, &rdev->consumer_list, list) 487414c70cbSLiam Girdwood uA += regulator->uA_load; 488414c70cbSLiam Girdwood mutex_unlock(&rdev->mutex); 489414c70cbSLiam Girdwood return sprintf(buf, "%d\n", uA); 490414c70cbSLiam Girdwood } 4917ad68e2fSDavid Brownell static DEVICE_ATTR(requested_microamps, 0444, regulator_total_uA_show, NULL); 492414c70cbSLiam Girdwood 493587cea27SGreg Kroah-Hartman static ssize_t num_users_show(struct device *dev, struct device_attribute *attr, 494587cea27SGreg Kroah-Hartman char *buf) 495414c70cbSLiam Girdwood { 496a5766f11SLiam Girdwood struct regulator_dev *rdev = dev_get_drvdata(dev); 497414c70cbSLiam Girdwood return sprintf(buf, "%d\n", rdev->use_count); 498414c70cbSLiam Girdwood } 499587cea27SGreg Kroah-Hartman static DEVICE_ATTR_RO(num_users); 500414c70cbSLiam Girdwood 501587cea27SGreg Kroah-Hartman static ssize_t type_show(struct device *dev, struct device_attribute *attr, 502587cea27SGreg Kroah-Hartman char *buf) 503414c70cbSLiam Girdwood { 504a5766f11SLiam Girdwood struct regulator_dev *rdev = dev_get_drvdata(dev); 505414c70cbSLiam Girdwood 506414c70cbSLiam Girdwood switch (rdev->desc->type) { 507414c70cbSLiam Girdwood case REGULATOR_VOLTAGE: 508414c70cbSLiam Girdwood return sprintf(buf, "voltage\n"); 509414c70cbSLiam Girdwood case REGULATOR_CURRENT: 510414c70cbSLiam Girdwood return sprintf(buf, "current\n"); 511414c70cbSLiam Girdwood } 512414c70cbSLiam Girdwood return sprintf(buf, "unknown\n"); 513414c70cbSLiam Girdwood } 514587cea27SGreg Kroah-Hartman static DEVICE_ATTR_RO(type); 515414c70cbSLiam Girdwood 516414c70cbSLiam Girdwood static ssize_t regulator_suspend_mem_uV_show(struct device *dev, 517414c70cbSLiam Girdwood struct device_attribute *attr, char *buf) 518414c70cbSLiam Girdwood { 519a5766f11SLiam Girdwood struct regulator_dev *rdev = dev_get_drvdata(dev); 520414c70cbSLiam Girdwood 521414c70cbSLiam Girdwood return sprintf(buf, "%d\n", rdev->constraints->state_mem.uV); 522414c70cbSLiam Girdwood } 5237ad68e2fSDavid Brownell static DEVICE_ATTR(suspend_mem_microvolts, 0444, 5247ad68e2fSDavid Brownell regulator_suspend_mem_uV_show, NULL); 525414c70cbSLiam Girdwood 526414c70cbSLiam Girdwood static ssize_t regulator_suspend_disk_uV_show(struct device *dev, 527414c70cbSLiam Girdwood struct device_attribute *attr, char *buf) 528414c70cbSLiam Girdwood { 529a5766f11SLiam Girdwood struct regulator_dev *rdev = dev_get_drvdata(dev); 530414c70cbSLiam Girdwood 531414c70cbSLiam Girdwood return sprintf(buf, "%d\n", rdev->constraints->state_disk.uV); 532414c70cbSLiam Girdwood } 5337ad68e2fSDavid Brownell static DEVICE_ATTR(suspend_disk_microvolts, 0444, 5347ad68e2fSDavid Brownell regulator_suspend_disk_uV_show, NULL); 535414c70cbSLiam Girdwood 536414c70cbSLiam Girdwood static ssize_t regulator_suspend_standby_uV_show(struct device *dev, 537414c70cbSLiam Girdwood struct device_attribute *attr, char *buf) 538414c70cbSLiam Girdwood { 539a5766f11SLiam Girdwood struct regulator_dev *rdev = dev_get_drvdata(dev); 540414c70cbSLiam Girdwood 541414c70cbSLiam Girdwood return sprintf(buf, "%d\n", rdev->constraints->state_standby.uV); 542414c70cbSLiam Girdwood } 5437ad68e2fSDavid Brownell static DEVICE_ATTR(suspend_standby_microvolts, 0444, 5447ad68e2fSDavid Brownell regulator_suspend_standby_uV_show, NULL); 545414c70cbSLiam Girdwood 546414c70cbSLiam Girdwood static ssize_t regulator_suspend_mem_mode_show(struct device *dev, 547414c70cbSLiam Girdwood struct device_attribute *attr, char *buf) 548414c70cbSLiam Girdwood { 549a5766f11SLiam Girdwood struct regulator_dev *rdev = dev_get_drvdata(dev); 550414c70cbSLiam Girdwood 5514fca9545SDavid Brownell return regulator_print_opmode(buf, 5524fca9545SDavid Brownell rdev->constraints->state_mem.mode); 553414c70cbSLiam Girdwood } 5547ad68e2fSDavid Brownell static DEVICE_ATTR(suspend_mem_mode, 0444, 5557ad68e2fSDavid Brownell regulator_suspend_mem_mode_show, NULL); 556414c70cbSLiam Girdwood 557414c70cbSLiam Girdwood static ssize_t regulator_suspend_disk_mode_show(struct device *dev, 558414c70cbSLiam Girdwood struct device_attribute *attr, char *buf) 559414c70cbSLiam Girdwood { 560a5766f11SLiam Girdwood struct regulator_dev *rdev = dev_get_drvdata(dev); 561414c70cbSLiam Girdwood 5624fca9545SDavid Brownell return regulator_print_opmode(buf, 5634fca9545SDavid Brownell rdev->constraints->state_disk.mode); 564414c70cbSLiam Girdwood } 5657ad68e2fSDavid Brownell static DEVICE_ATTR(suspend_disk_mode, 0444, 5667ad68e2fSDavid Brownell regulator_suspend_disk_mode_show, NULL); 567414c70cbSLiam Girdwood 568414c70cbSLiam Girdwood static ssize_t regulator_suspend_standby_mode_show(struct device *dev, 569414c70cbSLiam Girdwood struct device_attribute *attr, char *buf) 570414c70cbSLiam Girdwood { 571a5766f11SLiam Girdwood struct regulator_dev *rdev = dev_get_drvdata(dev); 572414c70cbSLiam Girdwood 5734fca9545SDavid Brownell return regulator_print_opmode(buf, 5744fca9545SDavid Brownell rdev->constraints->state_standby.mode); 575414c70cbSLiam Girdwood } 5767ad68e2fSDavid Brownell static DEVICE_ATTR(suspend_standby_mode, 0444, 5777ad68e2fSDavid Brownell regulator_suspend_standby_mode_show, NULL); 578414c70cbSLiam Girdwood 579414c70cbSLiam Girdwood static ssize_t regulator_suspend_mem_state_show(struct device *dev, 580414c70cbSLiam Girdwood struct device_attribute *attr, char *buf) 581414c70cbSLiam Girdwood { 582a5766f11SLiam Girdwood struct regulator_dev *rdev = dev_get_drvdata(dev); 583414c70cbSLiam Girdwood 5844fca9545SDavid Brownell return regulator_print_state(buf, 5854fca9545SDavid Brownell rdev->constraints->state_mem.enabled); 586414c70cbSLiam Girdwood } 5877ad68e2fSDavid Brownell static DEVICE_ATTR(suspend_mem_state, 0444, 5887ad68e2fSDavid Brownell regulator_suspend_mem_state_show, NULL); 589414c70cbSLiam Girdwood 590414c70cbSLiam Girdwood static ssize_t regulator_suspend_disk_state_show(struct device *dev, 591414c70cbSLiam Girdwood struct device_attribute *attr, char *buf) 592414c70cbSLiam Girdwood { 593a5766f11SLiam Girdwood struct regulator_dev *rdev = dev_get_drvdata(dev); 594414c70cbSLiam Girdwood 5954fca9545SDavid Brownell return regulator_print_state(buf, 5964fca9545SDavid Brownell rdev->constraints->state_disk.enabled); 597414c70cbSLiam Girdwood } 5987ad68e2fSDavid Brownell static DEVICE_ATTR(suspend_disk_state, 0444, 5997ad68e2fSDavid Brownell regulator_suspend_disk_state_show, NULL); 600414c70cbSLiam Girdwood 601414c70cbSLiam Girdwood static ssize_t regulator_suspend_standby_state_show(struct device *dev, 602414c70cbSLiam Girdwood struct device_attribute *attr, char *buf) 603414c70cbSLiam Girdwood { 604a5766f11SLiam Girdwood struct regulator_dev *rdev = dev_get_drvdata(dev); 605414c70cbSLiam Girdwood 6064fca9545SDavid Brownell return regulator_print_state(buf, 6074fca9545SDavid Brownell rdev->constraints->state_standby.enabled); 608414c70cbSLiam Girdwood } 6097ad68e2fSDavid Brownell static DEVICE_ATTR(suspend_standby_state, 0444, 6107ad68e2fSDavid Brownell regulator_suspend_standby_state_show, NULL); 611bc558a60SMark Brown 612f59c8f9fSMark Brown static ssize_t regulator_bypass_show(struct device *dev, 613f59c8f9fSMark Brown struct device_attribute *attr, char *buf) 614f59c8f9fSMark Brown { 615f59c8f9fSMark Brown struct regulator_dev *rdev = dev_get_drvdata(dev); 616f59c8f9fSMark Brown const char *report; 617f59c8f9fSMark Brown bool bypass; 618f59c8f9fSMark Brown int ret; 619f59c8f9fSMark Brown 620f59c8f9fSMark Brown ret = rdev->desc->ops->get_bypass(rdev, &bypass); 621f59c8f9fSMark Brown 622f59c8f9fSMark Brown if (ret != 0) 623f59c8f9fSMark Brown report = "unknown"; 624f59c8f9fSMark Brown else if (bypass) 625f59c8f9fSMark Brown report = "enabled"; 626f59c8f9fSMark Brown else 627f59c8f9fSMark Brown report = "disabled"; 628f59c8f9fSMark Brown 629f59c8f9fSMark Brown return sprintf(buf, "%s\n", report); 630f59c8f9fSMark Brown } 631f59c8f9fSMark Brown static DEVICE_ATTR(bypass, 0444, 632f59c8f9fSMark Brown regulator_bypass_show, NULL); 6337ad68e2fSDavid Brownell 6347ad68e2fSDavid Brownell /* 6357ad68e2fSDavid Brownell * These are the only attributes are present for all regulators. 6367ad68e2fSDavid Brownell * Other attributes are a function of regulator functionality. 6377ad68e2fSDavid Brownell */ 638587cea27SGreg Kroah-Hartman static struct attribute *regulator_dev_attrs[] = { 639587cea27SGreg Kroah-Hartman &dev_attr_name.attr, 640587cea27SGreg Kroah-Hartman &dev_attr_num_users.attr, 641587cea27SGreg Kroah-Hartman &dev_attr_type.attr, 642587cea27SGreg Kroah-Hartman NULL, 643414c70cbSLiam Girdwood }; 644587cea27SGreg Kroah-Hartman ATTRIBUTE_GROUPS(regulator_dev); 645414c70cbSLiam Girdwood 646414c70cbSLiam Girdwood static void regulator_dev_release(struct device *dev) 647414c70cbSLiam Girdwood { 648a5766f11SLiam Girdwood struct regulator_dev *rdev = dev_get_drvdata(dev); 649414c70cbSLiam Girdwood kfree(rdev); 650414c70cbSLiam Girdwood } 651414c70cbSLiam Girdwood 652414c70cbSLiam Girdwood static struct class regulator_class = { 653414c70cbSLiam Girdwood .name = "regulator", 654414c70cbSLiam Girdwood .dev_release = regulator_dev_release, 655587cea27SGreg Kroah-Hartman .dev_groups = regulator_dev_groups, 656414c70cbSLiam Girdwood }; 657414c70cbSLiam Girdwood 658414c70cbSLiam Girdwood /* Calculate the new optimum regulator operating mode based on the new total 659414c70cbSLiam Girdwood * consumer load. All locks held by caller */ 660414c70cbSLiam Girdwood static void drms_uA_update(struct regulator_dev *rdev) 661414c70cbSLiam Girdwood { 662414c70cbSLiam Girdwood struct regulator *sibling; 663414c70cbSLiam Girdwood int current_uA = 0, output_uV, input_uV, err; 664414c70cbSLiam Girdwood unsigned int mode; 665414c70cbSLiam Girdwood 666414c70cbSLiam Girdwood err = regulator_check_drms(rdev); 667414c70cbSLiam Girdwood if (err < 0 || !rdev->desc->ops->get_optimum_mode || 668476c2d83SMark Brown (!rdev->desc->ops->get_voltage && 669476c2d83SMark Brown !rdev->desc->ops->get_voltage_sel) || 670476c2d83SMark Brown !rdev->desc->ops->set_mode) 671414c70cbSLiam Girdwood return; 672414c70cbSLiam Girdwood 673414c70cbSLiam Girdwood /* get output voltage */ 6741bf5a1f8SMark Brown output_uV = _regulator_get_voltage(rdev); 675414c70cbSLiam Girdwood if (output_uV <= 0) 676414c70cbSLiam Girdwood return; 677414c70cbSLiam Girdwood 678414c70cbSLiam Girdwood /* get input voltage */ 6791bf5a1f8SMark Brown input_uV = 0; 6801bf5a1f8SMark Brown if (rdev->supply) 6813f24f5adSAxel Lin input_uV = regulator_get_voltage(rdev->supply); 6821bf5a1f8SMark Brown if (input_uV <= 0) 683414c70cbSLiam Girdwood input_uV = rdev->constraints->input_uV; 684414c70cbSLiam Girdwood if (input_uV <= 0) 685414c70cbSLiam Girdwood return; 686414c70cbSLiam Girdwood 687414c70cbSLiam Girdwood /* calc total requested load */ 688414c70cbSLiam Girdwood list_for_each_entry(sibling, &rdev->consumer_list, list) 689414c70cbSLiam Girdwood current_uA += sibling->uA_load; 690414c70cbSLiam Girdwood 691414c70cbSLiam Girdwood /* now get the optimum mode for our new total regulator load */ 692414c70cbSLiam Girdwood mode = rdev->desc->ops->get_optimum_mode(rdev, input_uV, 693414c70cbSLiam Girdwood output_uV, current_uA); 694414c70cbSLiam Girdwood 695414c70cbSLiam Girdwood /* check the new mode is allowed */ 6962c608234SMark Brown err = regulator_mode_constrain(rdev, &mode); 697414c70cbSLiam Girdwood if (err == 0) 698414c70cbSLiam Girdwood rdev->desc->ops->set_mode(rdev, mode); 699414c70cbSLiam Girdwood } 700414c70cbSLiam Girdwood 701414c70cbSLiam Girdwood static int suspend_set_state(struct regulator_dev *rdev, 702414c70cbSLiam Girdwood struct regulator_state *rstate) 703414c70cbSLiam Girdwood { 704414c70cbSLiam Girdwood int ret = 0; 705638f85c5SMark Brown 706638f85c5SMark Brown /* If we have no suspend mode configration don't set anything; 7078ac0e95dSAxel Lin * only warn if the driver implements set_suspend_voltage or 7088ac0e95dSAxel Lin * set_suspend_mode callback. 709638f85c5SMark Brown */ 710638f85c5SMark Brown if (!rstate->enabled && !rstate->disabled) { 7118ac0e95dSAxel Lin if (rdev->desc->ops->set_suspend_voltage || 7128ac0e95dSAxel Lin rdev->desc->ops->set_suspend_mode) 7135da84fd9SJoe Perches rdev_warn(rdev, "No configuration\n"); 714638f85c5SMark Brown return 0; 715638f85c5SMark Brown } 716638f85c5SMark Brown 717638f85c5SMark Brown if (rstate->enabled && rstate->disabled) { 7185da84fd9SJoe Perches rdev_err(rdev, "invalid configuration\n"); 719638f85c5SMark Brown return -EINVAL; 720638f85c5SMark Brown } 721638f85c5SMark Brown 7228ac0e95dSAxel Lin if (rstate->enabled && rdev->desc->ops->set_suspend_enable) 723414c70cbSLiam Girdwood ret = rdev->desc->ops->set_suspend_enable(rdev); 7248ac0e95dSAxel Lin else if (rstate->disabled && rdev->desc->ops->set_suspend_disable) 725414c70cbSLiam Girdwood ret = rdev->desc->ops->set_suspend_disable(rdev); 7268ac0e95dSAxel Lin else /* OK if set_suspend_enable or set_suspend_disable is NULL */ 7278ac0e95dSAxel Lin ret = 0; 7288ac0e95dSAxel Lin 729414c70cbSLiam Girdwood if (ret < 0) { 7305da84fd9SJoe Perches rdev_err(rdev, "failed to enabled/disable\n"); 731414c70cbSLiam Girdwood return ret; 732414c70cbSLiam Girdwood } 733414c70cbSLiam Girdwood 734414c70cbSLiam Girdwood if (rdev->desc->ops->set_suspend_voltage && rstate->uV > 0) { 735414c70cbSLiam Girdwood ret = rdev->desc->ops->set_suspend_voltage(rdev, rstate->uV); 736414c70cbSLiam Girdwood if (ret < 0) { 7375da84fd9SJoe Perches rdev_err(rdev, "failed to set voltage\n"); 738414c70cbSLiam Girdwood return ret; 739414c70cbSLiam Girdwood } 740414c70cbSLiam Girdwood } 741414c70cbSLiam Girdwood 742414c70cbSLiam Girdwood if (rdev->desc->ops->set_suspend_mode && rstate->mode > 0) { 743414c70cbSLiam Girdwood ret = rdev->desc->ops->set_suspend_mode(rdev, rstate->mode); 744414c70cbSLiam Girdwood if (ret < 0) { 7455da84fd9SJoe Perches rdev_err(rdev, "failed to set mode\n"); 746414c70cbSLiam Girdwood return ret; 747414c70cbSLiam Girdwood } 748414c70cbSLiam Girdwood } 749414c70cbSLiam Girdwood return ret; 750414c70cbSLiam Girdwood } 751414c70cbSLiam Girdwood 752414c70cbSLiam Girdwood /* locks held by caller */ 753414c70cbSLiam Girdwood static int suspend_prepare(struct regulator_dev *rdev, suspend_state_t state) 754414c70cbSLiam Girdwood { 755414c70cbSLiam Girdwood if (!rdev->constraints) 756414c70cbSLiam Girdwood return -EINVAL; 757414c70cbSLiam Girdwood 758414c70cbSLiam Girdwood switch (state) { 759414c70cbSLiam Girdwood case PM_SUSPEND_STANDBY: 760414c70cbSLiam Girdwood return suspend_set_state(rdev, 761414c70cbSLiam Girdwood &rdev->constraints->state_standby); 762414c70cbSLiam Girdwood case PM_SUSPEND_MEM: 763414c70cbSLiam Girdwood return suspend_set_state(rdev, 764414c70cbSLiam Girdwood &rdev->constraints->state_mem); 765414c70cbSLiam Girdwood case PM_SUSPEND_MAX: 766414c70cbSLiam Girdwood return suspend_set_state(rdev, 767414c70cbSLiam Girdwood &rdev->constraints->state_disk); 768414c70cbSLiam Girdwood default: 769414c70cbSLiam Girdwood return -EINVAL; 770414c70cbSLiam Girdwood } 771414c70cbSLiam Girdwood } 772414c70cbSLiam Girdwood 773414c70cbSLiam Girdwood static void print_constraints(struct regulator_dev *rdev) 774414c70cbSLiam Girdwood { 775414c70cbSLiam Girdwood struct regulation_constraints *constraints = rdev->constraints; 776973e9a27SMark Brown char buf[80] = ""; 7778f031b48SMark Brown int count = 0; 7788f031b48SMark Brown int ret; 779414c70cbSLiam Girdwood 7808f031b48SMark Brown if (constraints->min_uV && constraints->max_uV) { 781414c70cbSLiam Girdwood if (constraints->min_uV == constraints->max_uV) 7828f031b48SMark Brown count += sprintf(buf + count, "%d mV ", 783414c70cbSLiam Girdwood constraints->min_uV / 1000); 784414c70cbSLiam Girdwood else 7858f031b48SMark Brown count += sprintf(buf + count, "%d <--> %d mV ", 786414c70cbSLiam Girdwood constraints->min_uV / 1000, 787414c70cbSLiam Girdwood constraints->max_uV / 1000); 7888f031b48SMark Brown } 7898f031b48SMark Brown 7908f031b48SMark Brown if (!constraints->min_uV || 7918f031b48SMark Brown constraints->min_uV != constraints->max_uV) { 7928f031b48SMark Brown ret = _regulator_get_voltage(rdev); 7938f031b48SMark Brown if (ret > 0) 7948f031b48SMark Brown count += sprintf(buf + count, "at %d mV ", ret / 1000); 7958f031b48SMark Brown } 7968f031b48SMark Brown 797bf5892a8SMark Brown if (constraints->uV_offset) 798bf5892a8SMark Brown count += sprintf(buf, "%dmV offset ", 799bf5892a8SMark Brown constraints->uV_offset / 1000); 800bf5892a8SMark Brown 8018f031b48SMark Brown if (constraints->min_uA && constraints->max_uA) { 802414c70cbSLiam Girdwood if (constraints->min_uA == constraints->max_uA) 8038f031b48SMark Brown count += sprintf(buf + count, "%d mA ", 804414c70cbSLiam Girdwood constraints->min_uA / 1000); 805414c70cbSLiam Girdwood else 8068f031b48SMark Brown count += sprintf(buf + count, "%d <--> %d mA ", 807414c70cbSLiam Girdwood constraints->min_uA / 1000, 808414c70cbSLiam Girdwood constraints->max_uA / 1000); 809414c70cbSLiam Girdwood } 8108f031b48SMark Brown 8118f031b48SMark Brown if (!constraints->min_uA || 8128f031b48SMark Brown constraints->min_uA != constraints->max_uA) { 8138f031b48SMark Brown ret = _regulator_get_current_limit(rdev); 8148f031b48SMark Brown if (ret > 0) 815e4a6376bSCyril Chemparathy count += sprintf(buf + count, "at %d mA ", ret / 1000); 8168f031b48SMark Brown } 8178f031b48SMark Brown 818414c70cbSLiam Girdwood if (constraints->valid_modes_mask & REGULATOR_MODE_FAST) 819414c70cbSLiam Girdwood count += sprintf(buf + count, "fast "); 820414c70cbSLiam Girdwood if (constraints->valid_modes_mask & REGULATOR_MODE_NORMAL) 821414c70cbSLiam Girdwood count += sprintf(buf + count, "normal "); 822414c70cbSLiam Girdwood if (constraints->valid_modes_mask & REGULATOR_MODE_IDLE) 823414c70cbSLiam Girdwood count += sprintf(buf + count, "idle "); 824414c70cbSLiam Girdwood if (constraints->valid_modes_mask & REGULATOR_MODE_STANDBY) 825414c70cbSLiam Girdwood count += sprintf(buf + count, "standby"); 826414c70cbSLiam Girdwood 827215b8b05SUwe Kleine-König if (!count) 828215b8b05SUwe Kleine-König sprintf(buf, "no parameters"); 829215b8b05SUwe Kleine-König 83013ce29f8SMark Brown rdev_info(rdev, "%s\n", buf); 8314a682922SMark Brown 8324a682922SMark Brown if ((constraints->min_uV != constraints->max_uV) && 8334a682922SMark Brown !(constraints->valid_ops_mask & REGULATOR_CHANGE_VOLTAGE)) 8344a682922SMark Brown rdev_warn(rdev, 8354a682922SMark Brown "Voltage range but no REGULATOR_CHANGE_VOLTAGE\n"); 836414c70cbSLiam Girdwood } 837414c70cbSLiam Girdwood 838e79055d6SMark Brown static int machine_constraints_voltage(struct regulator_dev *rdev, 8391083c393SMark Brown struct regulation_constraints *constraints) 840e79055d6SMark Brown { 841e79055d6SMark Brown struct regulator_ops *ops = rdev->desc->ops; 842af5866c9SMark Brown int ret; 843af5866c9SMark Brown 844af5866c9SMark Brown /* do we need to apply the constraint voltage */ 845af5866c9SMark Brown if (rdev->constraints->apply_uV && 84675790251SMark Brown rdev->constraints->min_uV == rdev->constraints->max_uV) { 84775790251SMark Brown ret = _regulator_do_set_voltage(rdev, 8483a93f2a9SMark Brown rdev->constraints->min_uV, 84975790251SMark Brown rdev->constraints->max_uV); 850af5866c9SMark Brown if (ret < 0) { 8515da84fd9SJoe Perches rdev_err(rdev, "failed to apply %duV constraint\n", 8525da84fd9SJoe Perches rdev->constraints->min_uV); 853af5866c9SMark Brown return ret; 854af5866c9SMark Brown } 855af5866c9SMark Brown } 856e79055d6SMark Brown 857e79055d6SMark Brown /* constrain machine-level voltage specs to fit 858e79055d6SMark Brown * the actual range supported by this regulator. 859e79055d6SMark Brown */ 860e79055d6SMark Brown if (ops->list_voltage && rdev->desc->n_voltages) { 861e79055d6SMark Brown int count = rdev->desc->n_voltages; 862e79055d6SMark Brown int i; 863e79055d6SMark Brown int min_uV = INT_MAX; 864e79055d6SMark Brown int max_uV = INT_MIN; 865e79055d6SMark Brown int cmin = constraints->min_uV; 866e79055d6SMark Brown int cmax = constraints->max_uV; 867e79055d6SMark Brown 868e79055d6SMark Brown /* it's safe to autoconfigure fixed-voltage supplies 869e79055d6SMark Brown and the constraints are used by list_voltage. */ 870e79055d6SMark Brown if (count == 1 && !cmin) { 871e79055d6SMark Brown cmin = 1; 872e79055d6SMark Brown cmax = INT_MAX; 873e79055d6SMark Brown constraints->min_uV = cmin; 874e79055d6SMark Brown constraints->max_uV = cmax; 875e79055d6SMark Brown } 876e79055d6SMark Brown 877e79055d6SMark Brown /* voltage constraints are optional */ 878e79055d6SMark Brown if ((cmin == 0) && (cmax == 0)) 879e79055d6SMark Brown return 0; 880e79055d6SMark Brown 881e79055d6SMark Brown /* else require explicit machine-level constraints */ 882e79055d6SMark Brown if (cmin <= 0 || cmax <= 0 || cmax < cmin) { 8835da84fd9SJoe Perches rdev_err(rdev, "invalid voltage constraints\n"); 884e79055d6SMark Brown return -EINVAL; 885e79055d6SMark Brown } 886e79055d6SMark Brown 887e79055d6SMark Brown /* initial: [cmin..cmax] valid, [min_uV..max_uV] not */ 888e79055d6SMark Brown for (i = 0; i < count; i++) { 889e79055d6SMark Brown int value; 890e79055d6SMark Brown 891e79055d6SMark Brown value = ops->list_voltage(rdev, i); 892e79055d6SMark Brown if (value <= 0) 893e79055d6SMark Brown continue; 894e79055d6SMark Brown 895e79055d6SMark Brown /* maybe adjust [min_uV..max_uV] */ 896e79055d6SMark Brown if (value >= cmin && value < min_uV) 897e79055d6SMark Brown min_uV = value; 898e79055d6SMark Brown if (value <= cmax && value > max_uV) 899e79055d6SMark Brown max_uV = value; 900e79055d6SMark Brown } 901e79055d6SMark Brown 902e79055d6SMark Brown /* final: [min_uV..max_uV] valid iff constraints valid */ 903e79055d6SMark Brown if (max_uV < min_uV) { 904fff15befSMark Brown rdev_err(rdev, 905fff15befSMark Brown "unsupportable voltage constraints %u-%uuV\n", 906fff15befSMark Brown min_uV, max_uV); 907e79055d6SMark Brown return -EINVAL; 908e79055d6SMark Brown } 909e79055d6SMark Brown 910e79055d6SMark Brown /* use regulator's subset of machine constraints */ 911e79055d6SMark Brown if (constraints->min_uV < min_uV) { 9125da84fd9SJoe Perches rdev_dbg(rdev, "override min_uV, %d -> %d\n", 9135da84fd9SJoe Perches constraints->min_uV, min_uV); 914e79055d6SMark Brown constraints->min_uV = min_uV; 915e79055d6SMark Brown } 916e79055d6SMark Brown if (constraints->max_uV > max_uV) { 9175da84fd9SJoe Perches rdev_dbg(rdev, "override max_uV, %d -> %d\n", 9185da84fd9SJoe Perches constraints->max_uV, max_uV); 919e79055d6SMark Brown constraints->max_uV = max_uV; 920e79055d6SMark Brown } 921e79055d6SMark Brown } 922e79055d6SMark Brown 923e79055d6SMark Brown return 0; 924e79055d6SMark Brown } 925e79055d6SMark Brown 926f8c1700dSLaxman Dewangan static int machine_constraints_current(struct regulator_dev *rdev, 927f8c1700dSLaxman Dewangan struct regulation_constraints *constraints) 928f8c1700dSLaxman Dewangan { 929f8c1700dSLaxman Dewangan struct regulator_ops *ops = rdev->desc->ops; 930f8c1700dSLaxman Dewangan int ret; 931f8c1700dSLaxman Dewangan 932f8c1700dSLaxman Dewangan if (!constraints->min_uA && !constraints->max_uA) 933f8c1700dSLaxman Dewangan return 0; 934f8c1700dSLaxman Dewangan 935f8c1700dSLaxman Dewangan if (constraints->min_uA > constraints->max_uA) { 936f8c1700dSLaxman Dewangan rdev_err(rdev, "Invalid current constraints\n"); 937f8c1700dSLaxman Dewangan return -EINVAL; 938f8c1700dSLaxman Dewangan } 939f8c1700dSLaxman Dewangan 940f8c1700dSLaxman Dewangan if (!ops->set_current_limit || !ops->get_current_limit) { 941f8c1700dSLaxman Dewangan rdev_warn(rdev, "Operation of current configuration missing\n"); 942f8c1700dSLaxman Dewangan return 0; 943f8c1700dSLaxman Dewangan } 944f8c1700dSLaxman Dewangan 945f8c1700dSLaxman Dewangan /* Set regulator current in constraints range */ 946f8c1700dSLaxman Dewangan ret = ops->set_current_limit(rdev, constraints->min_uA, 947f8c1700dSLaxman Dewangan constraints->max_uA); 948f8c1700dSLaxman Dewangan if (ret < 0) { 949f8c1700dSLaxman Dewangan rdev_err(rdev, "Failed to set current constraint, %d\n", ret); 950f8c1700dSLaxman Dewangan return ret; 951f8c1700dSLaxman Dewangan } 952f8c1700dSLaxman Dewangan 953f8c1700dSLaxman Dewangan return 0; 954f8c1700dSLaxman Dewangan } 955f8c1700dSLaxman Dewangan 95630c21971SMarkus Pargmann static int _regulator_do_enable(struct regulator_dev *rdev); 95730c21971SMarkus Pargmann 958a5766f11SLiam Girdwood /** 959a5766f11SLiam Girdwood * set_machine_constraints - sets regulator constraints 96069279fb9SMark Brown * @rdev: regulator source 961c8e7e464SMark Brown * @constraints: constraints to apply 962a5766f11SLiam Girdwood * 963a5766f11SLiam Girdwood * Allows platform initialisation code to define and constrain 964a5766f11SLiam Girdwood * regulator circuits e.g. valid voltage/current ranges, etc. NOTE: 965a5766f11SLiam Girdwood * Constraints *must* be set by platform code in order for some 966a5766f11SLiam Girdwood * regulator operations to proceed i.e. set_voltage, set_current_limit, 967a5766f11SLiam Girdwood * set_mode. 968a5766f11SLiam Girdwood */ 969a5766f11SLiam Girdwood static int set_machine_constraints(struct regulator_dev *rdev, 970f8c12fe3SMark Brown const struct regulation_constraints *constraints) 971a5766f11SLiam Girdwood { 972a5766f11SLiam Girdwood int ret = 0; 973e5fda26cSMark Brown struct regulator_ops *ops = rdev->desc->ops; 974e06f5b4fSMark Brown 9759a8f5e07SMark Brown if (constraints) 976f8c12fe3SMark Brown rdev->constraints = kmemdup(constraints, sizeof(*constraints), 977f8c12fe3SMark Brown GFP_KERNEL); 9789a8f5e07SMark Brown else 9799a8f5e07SMark Brown rdev->constraints = kzalloc(sizeof(*constraints), 9809a8f5e07SMark Brown GFP_KERNEL); 981f8c12fe3SMark Brown if (!rdev->constraints) 982f8c12fe3SMark Brown return -ENOMEM; 983af5866c9SMark Brown 984f8c12fe3SMark Brown ret = machine_constraints_voltage(rdev, rdev->constraints); 985e79055d6SMark Brown if (ret != 0) 9863e2b9abdSMark Brown goto out; 9873e2b9abdSMark Brown 988f8c1700dSLaxman Dewangan ret = machine_constraints_current(rdev, rdev->constraints); 989f8c1700dSLaxman Dewangan if (ret != 0) 990f8c1700dSLaxman Dewangan goto out; 991f8c1700dSLaxman Dewangan 992a5766f11SLiam Girdwood /* do we need to setup our suspend state */ 9939a8f5e07SMark Brown if (rdev->constraints->initial_state) { 994f8c12fe3SMark Brown ret = suspend_prepare(rdev, rdev->constraints->initial_state); 995e06f5b4fSMark Brown if (ret < 0) { 9965da84fd9SJoe Perches rdev_err(rdev, "failed to set suspend state\n"); 997e06f5b4fSMark Brown goto out; 998e06f5b4fSMark Brown } 999e06f5b4fSMark Brown } 1000a5766f11SLiam Girdwood 10019a8f5e07SMark Brown if (rdev->constraints->initial_mode) { 1002a308466cSMark Brown if (!ops->set_mode) { 10035da84fd9SJoe Perches rdev_err(rdev, "no set_mode operation\n"); 1004a308466cSMark Brown ret = -EINVAL; 1005a308466cSMark Brown goto out; 1006a308466cSMark Brown } 1007a308466cSMark Brown 1008f8c12fe3SMark Brown ret = ops->set_mode(rdev, rdev->constraints->initial_mode); 1009a308466cSMark Brown if (ret < 0) { 10105da84fd9SJoe Perches rdev_err(rdev, "failed to set initial mode: %d\n", ret); 1011a308466cSMark Brown goto out; 1012a308466cSMark Brown } 1013a308466cSMark Brown } 1014a308466cSMark Brown 1015cacf90f2SMark Brown /* If the constraints say the regulator should be on at this point 1016cacf90f2SMark Brown * and we have control then make sure it is enabled. 1017cacf90f2SMark Brown */ 101830c21971SMarkus Pargmann if (rdev->constraints->always_on || rdev->constraints->boot_on) { 101930c21971SMarkus Pargmann ret = _regulator_do_enable(rdev); 102030c21971SMarkus Pargmann if (ret < 0 && ret != -EINVAL) { 10215da84fd9SJoe Perches rdev_err(rdev, "failed to enable\n"); 1022e5fda26cSMark Brown goto out; 1023e5fda26cSMark Brown } 1024e5fda26cSMark Brown } 1025e5fda26cSMark Brown 10261653ccf4SYadwinder Singh Brar if ((rdev->constraints->ramp_delay || rdev->constraints->ramp_disable) 10271653ccf4SYadwinder Singh Brar && ops->set_ramp_delay) { 10286f0b2c69SYadwinder Singh Brar ret = ops->set_ramp_delay(rdev, rdev->constraints->ramp_delay); 10296f0b2c69SYadwinder Singh Brar if (ret < 0) { 10306f0b2c69SYadwinder Singh Brar rdev_err(rdev, "failed to set ramp_delay\n"); 10316f0b2c69SYadwinder Singh Brar goto out; 10326f0b2c69SYadwinder Singh Brar } 10336f0b2c69SYadwinder Singh Brar } 10346f0b2c69SYadwinder Singh Brar 1035a5766f11SLiam Girdwood print_constraints(rdev); 10361a6958e7SAxel Lin return 0; 1037a5766f11SLiam Girdwood out: 10381a6958e7SAxel Lin kfree(rdev->constraints); 10391a6958e7SAxel Lin rdev->constraints = NULL; 1040a5766f11SLiam Girdwood return ret; 1041a5766f11SLiam Girdwood } 1042a5766f11SLiam Girdwood 1043a5766f11SLiam Girdwood /** 1044a5766f11SLiam Girdwood * set_supply - set regulator supply regulator 104569279fb9SMark Brown * @rdev: regulator name 104669279fb9SMark Brown * @supply_rdev: supply regulator name 1047a5766f11SLiam Girdwood * 1048a5766f11SLiam Girdwood * Called by platform initialisation code to set the supply regulator for this 1049a5766f11SLiam Girdwood * regulator. This ensures that a regulators supply will also be enabled by the 1050a5766f11SLiam Girdwood * core if it's child is enabled. 1051a5766f11SLiam Girdwood */ 1052a5766f11SLiam Girdwood static int set_supply(struct regulator_dev *rdev, 1053a5766f11SLiam Girdwood struct regulator_dev *supply_rdev) 1054a5766f11SLiam Girdwood { 1055a5766f11SLiam Girdwood int err; 1056a5766f11SLiam Girdwood 10573801b86aSMark Brown rdev_info(rdev, "supplied by %s\n", rdev_get_name(supply_rdev)); 10583801b86aSMark Brown 10593801b86aSMark Brown rdev->supply = create_regulator(supply_rdev, &rdev->dev, "SUPPLY"); 106032c78de8SAxel Lin if (rdev->supply == NULL) { 106132c78de8SAxel Lin err = -ENOMEM; 1062a5766f11SLiam Girdwood return err; 1063a5766f11SLiam Girdwood } 106457ad526aSLaxman Dewangan supply_rdev->open_count++; 1065a5766f11SLiam Girdwood 10663801b86aSMark Brown return 0; 10673801b86aSMark Brown } 10683801b86aSMark Brown 1069a5766f11SLiam Girdwood /** 107006c63f93SRandy Dunlap * set_consumer_device_supply - Bind a regulator to a symbolic supply 107169279fb9SMark Brown * @rdev: regulator source 107240f9244fSMark Brown * @consumer_dev_name: dev_name() string for device supply applies to 1073a5766f11SLiam Girdwood * @supply: symbolic name for supply 1074a5766f11SLiam Girdwood * 1075a5766f11SLiam Girdwood * Allows platform initialisation code to map physical regulator 1076a5766f11SLiam Girdwood * sources to symbolic names for supplies for use by devices. Devices 1077a5766f11SLiam Girdwood * should use these symbolic names to request regulators, avoiding the 1078a5766f11SLiam Girdwood * need to provide board-specific regulator names as platform data. 1079a5766f11SLiam Girdwood */ 1080a5766f11SLiam Girdwood static int set_consumer_device_supply(struct regulator_dev *rdev, 1081737f360dSMark Brown const char *consumer_dev_name, 108240f9244fSMark Brown const char *supply) 1083a5766f11SLiam Girdwood { 1084a5766f11SLiam Girdwood struct regulator_map *node; 10859ed2099eSMark Brown int has_dev; 1086a5766f11SLiam Girdwood 1087a5766f11SLiam Girdwood if (supply == NULL) 1088a5766f11SLiam Girdwood return -EINVAL; 1089a5766f11SLiam Girdwood 10909ed2099eSMark Brown if (consumer_dev_name != NULL) 10919ed2099eSMark Brown has_dev = 1; 10929ed2099eSMark Brown else 10939ed2099eSMark Brown has_dev = 0; 10949ed2099eSMark Brown 10956001e13cSDavid Brownell list_for_each_entry(node, ®ulator_map_list, list) { 109623b5cc2aSJani Nikula if (node->dev_name && consumer_dev_name) { 109723b5cc2aSJani Nikula if (strcmp(node->dev_name, consumer_dev_name) != 0) 10986001e13cSDavid Brownell continue; 109923b5cc2aSJani Nikula } else if (node->dev_name || consumer_dev_name) { 110023b5cc2aSJani Nikula continue; 110123b5cc2aSJani Nikula } 110223b5cc2aSJani Nikula 11036001e13cSDavid Brownell if (strcmp(node->supply, supply) != 0) 11046001e13cSDavid Brownell continue; 11056001e13cSDavid Brownell 1106737f360dSMark Brown pr_debug("%s: %s/%s is '%s' supply; fail %s/%s\n", 1107737f360dSMark Brown consumer_dev_name, 11086001e13cSDavid Brownell dev_name(&node->regulator->dev), 11096001e13cSDavid Brownell node->regulator->desc->name, 11106001e13cSDavid Brownell supply, 11111083c393SMark Brown dev_name(&rdev->dev), rdev_get_name(rdev)); 11126001e13cSDavid Brownell return -EBUSY; 11136001e13cSDavid Brownell } 11146001e13cSDavid Brownell 11159ed2099eSMark Brown node = kzalloc(sizeof(struct regulator_map), GFP_KERNEL); 1116a5766f11SLiam Girdwood if (node == NULL) 1117a5766f11SLiam Girdwood return -ENOMEM; 1118a5766f11SLiam Girdwood 1119a5766f11SLiam Girdwood node->regulator = rdev; 1120a5766f11SLiam Girdwood node->supply = supply; 1121a5766f11SLiam Girdwood 11229ed2099eSMark Brown if (has_dev) { 11239ed2099eSMark Brown node->dev_name = kstrdup(consumer_dev_name, GFP_KERNEL); 112440f9244fSMark Brown if (node->dev_name == NULL) { 112540f9244fSMark Brown kfree(node); 112640f9244fSMark Brown return -ENOMEM; 112740f9244fSMark Brown } 11289ed2099eSMark Brown } 112940f9244fSMark Brown 1130a5766f11SLiam Girdwood list_add(&node->list, ®ulator_map_list); 1131a5766f11SLiam Girdwood return 0; 1132a5766f11SLiam Girdwood } 1133a5766f11SLiam Girdwood 11340f1d747bSMike Rapoport static void unset_regulator_supplies(struct regulator_dev *rdev) 11350f1d747bSMike Rapoport { 11360f1d747bSMike Rapoport struct regulator_map *node, *n; 11370f1d747bSMike Rapoport 11380f1d747bSMike Rapoport list_for_each_entry_safe(node, n, ®ulator_map_list, list) { 11390f1d747bSMike Rapoport if (rdev == node->regulator) { 11400f1d747bSMike Rapoport list_del(&node->list); 114140f9244fSMark Brown kfree(node->dev_name); 11420f1d747bSMike Rapoport kfree(node); 11430f1d747bSMike Rapoport } 11440f1d747bSMike Rapoport } 11450f1d747bSMike Rapoport } 11460f1d747bSMike Rapoport 1147f5726ae3SMark Brown #define REG_STR_SIZE 64 1148414c70cbSLiam Girdwood 1149414c70cbSLiam Girdwood static struct regulator *create_regulator(struct regulator_dev *rdev, 1150414c70cbSLiam Girdwood struct device *dev, 1151414c70cbSLiam Girdwood const char *supply_name) 1152414c70cbSLiam Girdwood { 1153414c70cbSLiam Girdwood struct regulator *regulator; 1154414c70cbSLiam Girdwood char buf[REG_STR_SIZE]; 1155414c70cbSLiam Girdwood int err, size; 1156414c70cbSLiam Girdwood 1157414c70cbSLiam Girdwood regulator = kzalloc(sizeof(*regulator), GFP_KERNEL); 1158414c70cbSLiam Girdwood if (regulator == NULL) 1159414c70cbSLiam Girdwood return NULL; 1160414c70cbSLiam Girdwood 1161414c70cbSLiam Girdwood mutex_lock(&rdev->mutex); 1162414c70cbSLiam Girdwood regulator->rdev = rdev; 1163414c70cbSLiam Girdwood list_add(®ulator->list, &rdev->consumer_list); 1164414c70cbSLiam Girdwood 1165414c70cbSLiam Girdwood if (dev) { 1166e2c98eafSShawn Guo regulator->dev = dev; 1167e2c98eafSShawn Guo 1168222cc7b1SMark Brown /* Add a link to the device sysfs entry */ 1169414c70cbSLiam Girdwood size = scnprintf(buf, REG_STR_SIZE, "%s-%s", 1170414c70cbSLiam Girdwood dev->kobj.name, supply_name); 1171414c70cbSLiam Girdwood if (size >= REG_STR_SIZE) 1172222cc7b1SMark Brown goto overflow_err; 1173414c70cbSLiam Girdwood 1174414c70cbSLiam Girdwood regulator->supply_name = kstrdup(buf, GFP_KERNEL); 1175414c70cbSLiam Girdwood if (regulator->supply_name == NULL) 1176222cc7b1SMark Brown goto overflow_err; 1177414c70cbSLiam Girdwood 1178414c70cbSLiam Girdwood err = sysfs_create_link(&rdev->dev.kobj, &dev->kobj, 1179414c70cbSLiam Girdwood buf); 1180414c70cbSLiam Girdwood if (err) { 11815da84fd9SJoe Perches rdev_warn(rdev, "could not add device link %s err %d\n", 11821d7372e1SDaniel Walker dev->kobj.name, err); 1183222cc7b1SMark Brown /* non-fatal */ 1184414c70cbSLiam Girdwood } 11855de70519SMark Brown } else { 11865de70519SMark Brown regulator->supply_name = kstrdup(supply_name, GFP_KERNEL); 11875de70519SMark Brown if (regulator->supply_name == NULL) 1188222cc7b1SMark Brown goto overflow_err; 1189414c70cbSLiam Girdwood } 11905de70519SMark Brown 11915de70519SMark Brown regulator->debugfs = debugfs_create_dir(regulator->supply_name, 11925de70519SMark Brown rdev->debugfs); 119324751434SStephen Boyd if (!regulator->debugfs) { 11945de70519SMark Brown rdev_warn(rdev, "Failed to create debugfs directory\n"); 11955de70519SMark Brown } else { 11965de70519SMark Brown debugfs_create_u32("uA_load", 0444, regulator->debugfs, 11975de70519SMark Brown ®ulator->uA_load); 11985de70519SMark Brown debugfs_create_u32("min_uV", 0444, regulator->debugfs, 11995de70519SMark Brown ®ulator->min_uV); 12005de70519SMark Brown debugfs_create_u32("max_uV", 0444, regulator->debugfs, 12015de70519SMark Brown ®ulator->max_uV); 12025de70519SMark Brown } 12035de70519SMark Brown 12046492bc1bSMark Brown /* 12056492bc1bSMark Brown * Check now if the regulator is an always on regulator - if 12066492bc1bSMark Brown * it is then we don't need to do nearly so much work for 12076492bc1bSMark Brown * enable/disable calls. 12086492bc1bSMark Brown */ 12096492bc1bSMark Brown if (!_regulator_can_change_status(rdev) && 12106492bc1bSMark Brown _regulator_is_enabled(rdev)) 12116492bc1bSMark Brown regulator->always_on = true; 12126492bc1bSMark Brown 1213414c70cbSLiam Girdwood mutex_unlock(&rdev->mutex); 1214414c70cbSLiam Girdwood return regulator; 1215414c70cbSLiam Girdwood overflow_err: 1216414c70cbSLiam Girdwood list_del(®ulator->list); 1217414c70cbSLiam Girdwood kfree(regulator); 1218414c70cbSLiam Girdwood mutex_unlock(&rdev->mutex); 1219414c70cbSLiam Girdwood return NULL; 1220414c70cbSLiam Girdwood } 1221414c70cbSLiam Girdwood 122231aae2beSMark Brown static int _regulator_get_enable_time(struct regulator_dev *rdev) 122331aae2beSMark Brown { 122400c877c6SLaxman Dewangan if (rdev->constraints && rdev->constraints->enable_time) 122500c877c6SLaxman Dewangan return rdev->constraints->enable_time; 122631aae2beSMark Brown if (!rdev->desc->ops->enable_time) 122779511ed3SMark Brown return rdev->desc->enable_time; 122831aae2beSMark Brown return rdev->desc->ops->enable_time(rdev); 122931aae2beSMark Brown } 123031aae2beSMark Brown 1231a06ccd9cSCharles Keepax static struct regulator_supply_alias *regulator_find_supply_alias( 1232a06ccd9cSCharles Keepax struct device *dev, const char *supply) 1233a06ccd9cSCharles Keepax { 1234a06ccd9cSCharles Keepax struct regulator_supply_alias *map; 1235a06ccd9cSCharles Keepax 1236a06ccd9cSCharles Keepax list_for_each_entry(map, ®ulator_supply_alias_list, list) 1237a06ccd9cSCharles Keepax if (map->src_dev == dev && strcmp(map->src_supply, supply) == 0) 1238a06ccd9cSCharles Keepax return map; 1239a06ccd9cSCharles Keepax 1240a06ccd9cSCharles Keepax return NULL; 1241a06ccd9cSCharles Keepax } 1242a06ccd9cSCharles Keepax 1243a06ccd9cSCharles Keepax static void regulator_supply_alias(struct device **dev, const char **supply) 1244a06ccd9cSCharles Keepax { 1245a06ccd9cSCharles Keepax struct regulator_supply_alias *map; 1246a06ccd9cSCharles Keepax 1247a06ccd9cSCharles Keepax map = regulator_find_supply_alias(*dev, *supply); 1248a06ccd9cSCharles Keepax if (map) { 1249a06ccd9cSCharles Keepax dev_dbg(*dev, "Mapping supply %s to %s,%s\n", 1250a06ccd9cSCharles Keepax *supply, map->alias_supply, 1251a06ccd9cSCharles Keepax dev_name(map->alias_dev)); 1252a06ccd9cSCharles Keepax *dev = map->alias_dev; 1253a06ccd9cSCharles Keepax *supply = map->alias_supply; 1254a06ccd9cSCharles Keepax } 1255a06ccd9cSCharles Keepax } 1256a06ccd9cSCharles Keepax 125769511a45SRajendra Nayak static struct regulator_dev *regulator_dev_lookup(struct device *dev, 12586d191a5fSMark Brown const char *supply, 12596d191a5fSMark Brown int *ret) 126069511a45SRajendra Nayak { 126169511a45SRajendra Nayak struct regulator_dev *r; 126269511a45SRajendra Nayak struct device_node *node; 1263576ca436SMark Brown struct regulator_map *map; 1264576ca436SMark Brown const char *devname = NULL; 126569511a45SRajendra Nayak 1266a06ccd9cSCharles Keepax regulator_supply_alias(&dev, &supply); 1267a06ccd9cSCharles Keepax 126869511a45SRajendra Nayak /* first do a dt based lookup */ 126969511a45SRajendra Nayak if (dev && dev->of_node) { 127069511a45SRajendra Nayak node = of_get_regulator(dev, supply); 12716d191a5fSMark Brown if (node) { 127269511a45SRajendra Nayak list_for_each_entry(r, ®ulator_list, list) 127369511a45SRajendra Nayak if (r->dev.parent && 127469511a45SRajendra Nayak node == r->dev.of_node) 127569511a45SRajendra Nayak return r; 1276317b5684SMark Brown *ret = -EPROBE_DEFER; 1277317b5684SMark Brown return NULL; 12786d191a5fSMark Brown } else { 12796d191a5fSMark Brown /* 12806d191a5fSMark Brown * If we couldn't even get the node then it's 12816d191a5fSMark Brown * not just that the device didn't register 12826d191a5fSMark Brown * yet, there's no node and we'll never 12836d191a5fSMark Brown * succeed. 12846d191a5fSMark Brown */ 12856d191a5fSMark Brown *ret = -ENODEV; 12866d191a5fSMark Brown } 128769511a45SRajendra Nayak } 128869511a45SRajendra Nayak 128969511a45SRajendra Nayak /* if not found, try doing it non-dt way */ 1290576ca436SMark Brown if (dev) 1291576ca436SMark Brown devname = dev_name(dev); 1292576ca436SMark Brown 129369511a45SRajendra Nayak list_for_each_entry(r, ®ulator_list, list) 129469511a45SRajendra Nayak if (strcmp(rdev_get_name(r), supply) == 0) 129569511a45SRajendra Nayak return r; 129669511a45SRajendra Nayak 1297576ca436SMark Brown list_for_each_entry(map, ®ulator_map_list, list) { 1298576ca436SMark Brown /* If the mapping has a device set up it must match */ 1299576ca436SMark Brown if (map->dev_name && 1300576ca436SMark Brown (!devname || strcmp(map->dev_name, devname))) 1301576ca436SMark Brown continue; 1302576ca436SMark Brown 1303576ca436SMark Brown if (strcmp(map->supply, supply) == 0) 1304576ca436SMark Brown return map->regulator; 1305576ca436SMark Brown } 1306576ca436SMark Brown 1307576ca436SMark Brown 130869511a45SRajendra Nayak return NULL; 130969511a45SRajendra Nayak } 131069511a45SRajendra Nayak 13115ffbd136SMark Brown /* Internal regulator request function */ 13125ffbd136SMark Brown static struct regulator *_regulator_get(struct device *dev, const char *id, 13134ddfebd3SMark Brown bool exclusive, bool allow_dummy) 1314414c70cbSLiam Girdwood { 1315414c70cbSLiam Girdwood struct regulator_dev *rdev; 131604bf3011SMark Brown struct regulator *regulator = ERR_PTR(-EPROBE_DEFER); 131740f9244fSMark Brown const char *devname = NULL; 1318317b5684SMark Brown int ret; 1319414c70cbSLiam Girdwood 1320414c70cbSLiam Girdwood if (id == NULL) { 13215da84fd9SJoe Perches pr_err("get() with no identifier\n"); 1322043c998fSMark Brown return ERR_PTR(-EINVAL); 1323414c70cbSLiam Girdwood } 1324414c70cbSLiam Girdwood 132540f9244fSMark Brown if (dev) 132640f9244fSMark Brown devname = dev_name(dev); 132740f9244fSMark Brown 1328317b5684SMark Brown if (have_full_constraints()) 1329317b5684SMark Brown ret = -ENODEV; 1330317b5684SMark Brown else 1331317b5684SMark Brown ret = -EPROBE_DEFER; 1332317b5684SMark Brown 1333414c70cbSLiam Girdwood mutex_lock(®ulator_list_mutex); 1334414c70cbSLiam Girdwood 13356d191a5fSMark Brown rdev = regulator_dev_lookup(dev, id, &ret); 133669511a45SRajendra Nayak if (rdev) 133769511a45SRajendra Nayak goto found; 133869511a45SRajendra Nayak 1339ef60abbbSMark Brown regulator = ERR_PTR(ret); 1340ef60abbbSMark Brown 13411e4b545cSNishanth Menon /* 13421e4b545cSNishanth Menon * If we have return value from dev_lookup fail, we do not expect to 13431e4b545cSNishanth Menon * succeed, so, quit with appropriate error value 13441e4b545cSNishanth Menon */ 13450d25d09dSJingoo Han if (ret && ret != -ENODEV) 13461e4b545cSNishanth Menon goto out; 13471e4b545cSNishanth Menon 134834abbd68SMark Brown if (!devname) 134934abbd68SMark Brown devname = "deviceless"; 135034abbd68SMark Brown 13514ddfebd3SMark Brown /* 13524ddfebd3SMark Brown * Assume that a regulator is physically present and enabled 13534ddfebd3SMark Brown * even if it isn't hooked up and just provide a dummy. 135434abbd68SMark Brown */ 135587b28417SMark Brown if (have_full_constraints() && allow_dummy) { 13565da84fd9SJoe Perches pr_warn("%s supply %s not found, using dummy regulator\n", 135734abbd68SMark Brown devname, id); 13584ddfebd3SMark Brown 135934abbd68SMark Brown rdev = dummy_regulator_rdev; 136034abbd68SMark Brown goto found; 13610781719bSHans de Goede /* Don't log an error when called from regulator_get_optional() */ 13620781719bSHans de Goede } else if (!have_full_constraints() || exclusive) { 1363acc3d5ceSShuah Khan dev_warn(dev, "dummy supplies not allowed\n"); 136434abbd68SMark Brown } 136534abbd68SMark Brown 1366414c70cbSLiam Girdwood mutex_unlock(®ulator_list_mutex); 1367414c70cbSLiam Girdwood return regulator; 1368414c70cbSLiam Girdwood 1369414c70cbSLiam Girdwood found: 13705ffbd136SMark Brown if (rdev->exclusive) { 13715ffbd136SMark Brown regulator = ERR_PTR(-EPERM); 13725ffbd136SMark Brown goto out; 13735ffbd136SMark Brown } 13745ffbd136SMark Brown 13755ffbd136SMark Brown if (exclusive && rdev->open_count) { 13765ffbd136SMark Brown regulator = ERR_PTR(-EBUSY); 13775ffbd136SMark Brown goto out; 13785ffbd136SMark Brown } 13795ffbd136SMark Brown 1380a5766f11SLiam Girdwood if (!try_module_get(rdev->owner)) 1381a5766f11SLiam Girdwood goto out; 1382a5766f11SLiam Girdwood 1383414c70cbSLiam Girdwood regulator = create_regulator(rdev, dev, id); 1384414c70cbSLiam Girdwood if (regulator == NULL) { 1385414c70cbSLiam Girdwood regulator = ERR_PTR(-ENOMEM); 1386414c70cbSLiam Girdwood module_put(rdev->owner); 1387bcda4321SAxel Lin goto out; 1388414c70cbSLiam Girdwood } 1389414c70cbSLiam Girdwood 13905ffbd136SMark Brown rdev->open_count++; 13915ffbd136SMark Brown if (exclusive) { 13925ffbd136SMark Brown rdev->exclusive = 1; 13935ffbd136SMark Brown 13945ffbd136SMark Brown ret = _regulator_is_enabled(rdev); 13955ffbd136SMark Brown if (ret > 0) 13965ffbd136SMark Brown rdev->use_count = 1; 13975ffbd136SMark Brown else 13985ffbd136SMark Brown rdev->use_count = 0; 13995ffbd136SMark Brown } 14005ffbd136SMark Brown 1401a5766f11SLiam Girdwood out: 1402414c70cbSLiam Girdwood mutex_unlock(®ulator_list_mutex); 14035ffbd136SMark Brown 1404414c70cbSLiam Girdwood return regulator; 1405414c70cbSLiam Girdwood } 14065ffbd136SMark Brown 14075ffbd136SMark Brown /** 14085ffbd136SMark Brown * regulator_get - lookup and obtain a reference to a regulator. 14095ffbd136SMark Brown * @dev: device for regulator "consumer" 14105ffbd136SMark Brown * @id: Supply name or regulator ID. 14115ffbd136SMark Brown * 14125ffbd136SMark Brown * Returns a struct regulator corresponding to the regulator producer, 14135ffbd136SMark Brown * or IS_ERR() condition containing errno. 14145ffbd136SMark Brown * 14155ffbd136SMark Brown * Use of supply names configured via regulator_set_device_supply() is 14165ffbd136SMark Brown * strongly encouraged. It is recommended that the supply name used 14175ffbd136SMark Brown * should match the name used for the supply and/or the relevant 14185ffbd136SMark Brown * device pins in the datasheet. 14195ffbd136SMark Brown */ 14205ffbd136SMark Brown struct regulator *regulator_get(struct device *dev, const char *id) 14215ffbd136SMark Brown { 14224ddfebd3SMark Brown return _regulator_get(dev, id, false, true); 14235ffbd136SMark Brown } 1424414c70cbSLiam Girdwood EXPORT_SYMBOL_GPL(regulator_get); 1425414c70cbSLiam Girdwood 1426070b9079SStephen Boyd /** 14275ffbd136SMark Brown * regulator_get_exclusive - obtain exclusive access to a regulator. 14285ffbd136SMark Brown * @dev: device for regulator "consumer" 14295ffbd136SMark Brown * @id: Supply name or regulator ID. 14305ffbd136SMark Brown * 14315ffbd136SMark Brown * Returns a struct regulator corresponding to the regulator producer, 14325ffbd136SMark Brown * or IS_ERR() condition containing errno. Other consumers will be 14335ffbd136SMark Brown * unable to obtain this reference is held and the use count for the 14345ffbd136SMark Brown * regulator will be initialised to reflect the current state of the 14355ffbd136SMark Brown * regulator. 14365ffbd136SMark Brown * 14375ffbd136SMark Brown * This is intended for use by consumers which cannot tolerate shared 14385ffbd136SMark Brown * use of the regulator such as those which need to force the 14395ffbd136SMark Brown * regulator off for correct operation of the hardware they are 14405ffbd136SMark Brown * controlling. 14415ffbd136SMark Brown * 14425ffbd136SMark Brown * Use of supply names configured via regulator_set_device_supply() is 14435ffbd136SMark Brown * strongly encouraged. It is recommended that the supply name used 14445ffbd136SMark Brown * should match the name used for the supply and/or the relevant 14455ffbd136SMark Brown * device pins in the datasheet. 14465ffbd136SMark Brown */ 14475ffbd136SMark Brown struct regulator *regulator_get_exclusive(struct device *dev, const char *id) 14485ffbd136SMark Brown { 14494ddfebd3SMark Brown return _regulator_get(dev, id, true, false); 14505ffbd136SMark Brown } 14515ffbd136SMark Brown EXPORT_SYMBOL_GPL(regulator_get_exclusive); 14525ffbd136SMark Brown 1453de1dd9fdSMark Brown /** 1454de1dd9fdSMark Brown * regulator_get_optional - obtain optional access to a regulator. 1455de1dd9fdSMark Brown * @dev: device for regulator "consumer" 1456de1dd9fdSMark Brown * @id: Supply name or regulator ID. 1457de1dd9fdSMark Brown * 1458de1dd9fdSMark Brown * Returns a struct regulator corresponding to the regulator producer, 1459de1dd9fdSMark Brown * or IS_ERR() condition containing errno. Other consumers will be 1460de1dd9fdSMark Brown * unable to obtain this reference is held and the use count for the 1461de1dd9fdSMark Brown * regulator will be initialised to reflect the current state of the 1462de1dd9fdSMark Brown * regulator. 1463de1dd9fdSMark Brown * 1464de1dd9fdSMark Brown * This is intended for use by consumers for devices which can have 1465de1dd9fdSMark Brown * some supplies unconnected in normal use, such as some MMC devices. 1466de1dd9fdSMark Brown * It can allow the regulator core to provide stub supplies for other 1467de1dd9fdSMark Brown * supplies requested using normal regulator_get() calls without 1468de1dd9fdSMark Brown * disrupting the operation of drivers that can handle absent 1469de1dd9fdSMark Brown * supplies. 1470de1dd9fdSMark Brown * 1471de1dd9fdSMark Brown * Use of supply names configured via regulator_set_device_supply() is 1472de1dd9fdSMark Brown * strongly encouraged. It is recommended that the supply name used 1473de1dd9fdSMark Brown * should match the name used for the supply and/or the relevant 1474de1dd9fdSMark Brown * device pins in the datasheet. 1475de1dd9fdSMark Brown */ 1476de1dd9fdSMark Brown struct regulator *regulator_get_optional(struct device *dev, const char *id) 1477de1dd9fdSMark Brown { 14784ddfebd3SMark Brown return _regulator_get(dev, id, false, false); 1479de1dd9fdSMark Brown } 1480de1dd9fdSMark Brown EXPORT_SYMBOL_GPL(regulator_get_optional); 1481de1dd9fdSMark Brown 148223ff2f0fSCharles Keepax /* Locks held by regulator_put() */ 148323ff2f0fSCharles Keepax static void _regulator_put(struct regulator *regulator) 1484414c70cbSLiam Girdwood { 1485414c70cbSLiam Girdwood struct regulator_dev *rdev; 1486414c70cbSLiam Girdwood 1487414c70cbSLiam Girdwood if (regulator == NULL || IS_ERR(regulator)) 1488414c70cbSLiam Girdwood return; 1489414c70cbSLiam Girdwood 1490414c70cbSLiam Girdwood rdev = regulator->rdev; 1491414c70cbSLiam Girdwood 14925de70519SMark Brown debugfs_remove_recursive(regulator->debugfs); 14935de70519SMark Brown 1494414c70cbSLiam Girdwood /* remove any sysfs entries */ 1495e2c98eafSShawn Guo if (regulator->dev) 1496414c70cbSLiam Girdwood sysfs_remove_link(&rdev->dev.kobj, regulator->supply_name); 14975de70519SMark Brown kfree(regulator->supply_name); 1498414c70cbSLiam Girdwood list_del(®ulator->list); 1499414c70cbSLiam Girdwood kfree(regulator); 1500414c70cbSLiam Girdwood 15015ffbd136SMark Brown rdev->open_count--; 15025ffbd136SMark Brown rdev->exclusive = 0; 15035ffbd136SMark Brown 1504414c70cbSLiam Girdwood module_put(rdev->owner); 150523ff2f0fSCharles Keepax } 150623ff2f0fSCharles Keepax 150723ff2f0fSCharles Keepax /** 150823ff2f0fSCharles Keepax * regulator_put - "free" the regulator source 150923ff2f0fSCharles Keepax * @regulator: regulator source 151023ff2f0fSCharles Keepax * 151123ff2f0fSCharles Keepax * Note: drivers must ensure that all regulator_enable calls made on this 151223ff2f0fSCharles Keepax * regulator source are balanced by regulator_disable calls prior to calling 151323ff2f0fSCharles Keepax * this function. 151423ff2f0fSCharles Keepax */ 151523ff2f0fSCharles Keepax void regulator_put(struct regulator *regulator) 151623ff2f0fSCharles Keepax { 151723ff2f0fSCharles Keepax mutex_lock(®ulator_list_mutex); 151823ff2f0fSCharles Keepax _regulator_put(regulator); 1519414c70cbSLiam Girdwood mutex_unlock(®ulator_list_mutex); 1520414c70cbSLiam Girdwood } 1521414c70cbSLiam Girdwood EXPORT_SYMBOL_GPL(regulator_put); 1522414c70cbSLiam Girdwood 1523a06ccd9cSCharles Keepax /** 1524a06ccd9cSCharles Keepax * regulator_register_supply_alias - Provide device alias for supply lookup 1525a06ccd9cSCharles Keepax * 1526a06ccd9cSCharles Keepax * @dev: device that will be given as the regulator "consumer" 1527a06ccd9cSCharles Keepax * @id: Supply name or regulator ID 1528a06ccd9cSCharles Keepax * @alias_dev: device that should be used to lookup the supply 1529a06ccd9cSCharles Keepax * @alias_id: Supply name or regulator ID that should be used to lookup the 1530a06ccd9cSCharles Keepax * supply 1531a06ccd9cSCharles Keepax * 1532a06ccd9cSCharles Keepax * All lookups for id on dev will instead be conducted for alias_id on 1533a06ccd9cSCharles Keepax * alias_dev. 1534a06ccd9cSCharles Keepax */ 1535a06ccd9cSCharles Keepax int regulator_register_supply_alias(struct device *dev, const char *id, 1536a06ccd9cSCharles Keepax struct device *alias_dev, 1537a06ccd9cSCharles Keepax const char *alias_id) 1538a06ccd9cSCharles Keepax { 1539a06ccd9cSCharles Keepax struct regulator_supply_alias *map; 1540a06ccd9cSCharles Keepax 1541a06ccd9cSCharles Keepax map = regulator_find_supply_alias(dev, id); 1542a06ccd9cSCharles Keepax if (map) 1543a06ccd9cSCharles Keepax return -EEXIST; 1544a06ccd9cSCharles Keepax 1545a06ccd9cSCharles Keepax map = kzalloc(sizeof(struct regulator_supply_alias), GFP_KERNEL); 1546a06ccd9cSCharles Keepax if (!map) 1547a06ccd9cSCharles Keepax return -ENOMEM; 1548a06ccd9cSCharles Keepax 1549a06ccd9cSCharles Keepax map->src_dev = dev; 1550a06ccd9cSCharles Keepax map->src_supply = id; 1551a06ccd9cSCharles Keepax map->alias_dev = alias_dev; 1552a06ccd9cSCharles Keepax map->alias_supply = alias_id; 1553a06ccd9cSCharles Keepax 1554a06ccd9cSCharles Keepax list_add(&map->list, ®ulator_supply_alias_list); 1555a06ccd9cSCharles Keepax 1556a06ccd9cSCharles Keepax pr_info("Adding alias for supply %s,%s -> %s,%s\n", 1557a06ccd9cSCharles Keepax id, dev_name(dev), alias_id, dev_name(alias_dev)); 1558a06ccd9cSCharles Keepax 1559a06ccd9cSCharles Keepax return 0; 1560a06ccd9cSCharles Keepax } 1561a06ccd9cSCharles Keepax EXPORT_SYMBOL_GPL(regulator_register_supply_alias); 1562a06ccd9cSCharles Keepax 1563a06ccd9cSCharles Keepax /** 1564a06ccd9cSCharles Keepax * regulator_unregister_supply_alias - Remove device alias 1565a06ccd9cSCharles Keepax * 1566a06ccd9cSCharles Keepax * @dev: device that will be given as the regulator "consumer" 1567a06ccd9cSCharles Keepax * @id: Supply name or regulator ID 1568a06ccd9cSCharles Keepax * 1569a06ccd9cSCharles Keepax * Remove a lookup alias if one exists for id on dev. 1570a06ccd9cSCharles Keepax */ 1571a06ccd9cSCharles Keepax void regulator_unregister_supply_alias(struct device *dev, const char *id) 1572a06ccd9cSCharles Keepax { 1573a06ccd9cSCharles Keepax struct regulator_supply_alias *map; 1574a06ccd9cSCharles Keepax 1575a06ccd9cSCharles Keepax map = regulator_find_supply_alias(dev, id); 1576a06ccd9cSCharles Keepax if (map) { 1577a06ccd9cSCharles Keepax list_del(&map->list); 1578a06ccd9cSCharles Keepax kfree(map); 1579a06ccd9cSCharles Keepax } 1580a06ccd9cSCharles Keepax } 1581a06ccd9cSCharles Keepax EXPORT_SYMBOL_GPL(regulator_unregister_supply_alias); 1582a06ccd9cSCharles Keepax 1583a06ccd9cSCharles Keepax /** 1584a06ccd9cSCharles Keepax * regulator_bulk_register_supply_alias - register multiple aliases 1585a06ccd9cSCharles Keepax * 1586a06ccd9cSCharles Keepax * @dev: device that will be given as the regulator "consumer" 1587a06ccd9cSCharles Keepax * @id: List of supply names or regulator IDs 1588a06ccd9cSCharles Keepax * @alias_dev: device that should be used to lookup the supply 1589a06ccd9cSCharles Keepax * @alias_id: List of supply names or regulator IDs that should be used to 1590a06ccd9cSCharles Keepax * lookup the supply 1591a06ccd9cSCharles Keepax * @num_id: Number of aliases to register 1592a06ccd9cSCharles Keepax * 1593a06ccd9cSCharles Keepax * @return 0 on success, an errno on failure. 1594a06ccd9cSCharles Keepax * 1595a06ccd9cSCharles Keepax * This helper function allows drivers to register several supply 1596a06ccd9cSCharles Keepax * aliases in one operation. If any of the aliases cannot be 1597a06ccd9cSCharles Keepax * registered any aliases that were registered will be removed 1598a06ccd9cSCharles Keepax * before returning to the caller. 1599a06ccd9cSCharles Keepax */ 1600a06ccd9cSCharles Keepax int regulator_bulk_register_supply_alias(struct device *dev, const char **id, 1601a06ccd9cSCharles Keepax struct device *alias_dev, 1602a06ccd9cSCharles Keepax const char **alias_id, 1603a06ccd9cSCharles Keepax int num_id) 1604a06ccd9cSCharles Keepax { 1605a06ccd9cSCharles Keepax int i; 1606a06ccd9cSCharles Keepax int ret; 1607a06ccd9cSCharles Keepax 1608a06ccd9cSCharles Keepax for (i = 0; i < num_id; ++i) { 1609a06ccd9cSCharles Keepax ret = regulator_register_supply_alias(dev, id[i], alias_dev, 1610a06ccd9cSCharles Keepax alias_id[i]); 1611a06ccd9cSCharles Keepax if (ret < 0) 1612a06ccd9cSCharles Keepax goto err; 1613a06ccd9cSCharles Keepax } 1614a06ccd9cSCharles Keepax 1615a06ccd9cSCharles Keepax return 0; 1616a06ccd9cSCharles Keepax 1617a06ccd9cSCharles Keepax err: 1618a06ccd9cSCharles Keepax dev_err(dev, 1619a06ccd9cSCharles Keepax "Failed to create supply alias %s,%s -> %s,%s\n", 1620a06ccd9cSCharles Keepax id[i], dev_name(dev), alias_id[i], dev_name(alias_dev)); 1621a06ccd9cSCharles Keepax 1622a06ccd9cSCharles Keepax while (--i >= 0) 1623a06ccd9cSCharles Keepax regulator_unregister_supply_alias(dev, id[i]); 1624a06ccd9cSCharles Keepax 1625a06ccd9cSCharles Keepax return ret; 1626a06ccd9cSCharles Keepax } 1627a06ccd9cSCharles Keepax EXPORT_SYMBOL_GPL(regulator_bulk_register_supply_alias); 1628a06ccd9cSCharles Keepax 1629a06ccd9cSCharles Keepax /** 1630a06ccd9cSCharles Keepax * regulator_bulk_unregister_supply_alias - unregister multiple aliases 1631a06ccd9cSCharles Keepax * 1632a06ccd9cSCharles Keepax * @dev: device that will be given as the regulator "consumer" 1633a06ccd9cSCharles Keepax * @id: List of supply names or regulator IDs 1634a06ccd9cSCharles Keepax * @num_id: Number of aliases to unregister 1635a06ccd9cSCharles Keepax * 1636a06ccd9cSCharles Keepax * This helper function allows drivers to unregister several supply 1637a06ccd9cSCharles Keepax * aliases in one operation. 1638a06ccd9cSCharles Keepax */ 1639a06ccd9cSCharles Keepax void regulator_bulk_unregister_supply_alias(struct device *dev, 1640a06ccd9cSCharles Keepax const char **id, 1641a06ccd9cSCharles Keepax int num_id) 1642a06ccd9cSCharles Keepax { 1643a06ccd9cSCharles Keepax int i; 1644a06ccd9cSCharles Keepax 1645a06ccd9cSCharles Keepax for (i = 0; i < num_id; ++i) 1646a06ccd9cSCharles Keepax regulator_unregister_supply_alias(dev, id[i]); 1647a06ccd9cSCharles Keepax } 1648a06ccd9cSCharles Keepax EXPORT_SYMBOL_GPL(regulator_bulk_unregister_supply_alias); 1649a06ccd9cSCharles Keepax 1650a06ccd9cSCharles Keepax 1651f19b00daSKim, Milo /* Manage enable GPIO list. Same GPIO pin can be shared among regulators */ 1652f19b00daSKim, Milo static int regulator_ena_gpio_request(struct regulator_dev *rdev, 1653f19b00daSKim, Milo const struct regulator_config *config) 1654f19b00daSKim, Milo { 1655f19b00daSKim, Milo struct regulator_enable_gpio *pin; 1656f19b00daSKim, Milo int ret; 1657f19b00daSKim, Milo 1658f19b00daSKim, Milo list_for_each_entry(pin, ®ulator_ena_gpio_list, list) { 1659f19b00daSKim, Milo if (pin->gpio == config->ena_gpio) { 1660f19b00daSKim, Milo rdev_dbg(rdev, "GPIO %d is already used\n", 1661f19b00daSKim, Milo config->ena_gpio); 1662f19b00daSKim, Milo goto update_ena_gpio_to_rdev; 1663f19b00daSKim, Milo } 1664f19b00daSKim, Milo } 1665f19b00daSKim, Milo 1666f19b00daSKim, Milo ret = gpio_request_one(config->ena_gpio, 1667f19b00daSKim, Milo GPIOF_DIR_OUT | config->ena_gpio_flags, 1668f19b00daSKim, Milo rdev_get_name(rdev)); 1669f19b00daSKim, Milo if (ret) 1670f19b00daSKim, Milo return ret; 1671f19b00daSKim, Milo 1672f19b00daSKim, Milo pin = kzalloc(sizeof(struct regulator_enable_gpio), GFP_KERNEL); 1673f19b00daSKim, Milo if (pin == NULL) { 1674f19b00daSKim, Milo gpio_free(config->ena_gpio); 1675f19b00daSKim, Milo return -ENOMEM; 1676f19b00daSKim, Milo } 1677f19b00daSKim, Milo 1678f19b00daSKim, Milo pin->gpio = config->ena_gpio; 1679f19b00daSKim, Milo pin->ena_gpio_invert = config->ena_gpio_invert; 1680f19b00daSKim, Milo list_add(&pin->list, ®ulator_ena_gpio_list); 1681f19b00daSKim, Milo 1682f19b00daSKim, Milo update_ena_gpio_to_rdev: 1683f19b00daSKim, Milo pin->request_count++; 1684f19b00daSKim, Milo rdev->ena_pin = pin; 1685f19b00daSKim, Milo return 0; 1686f19b00daSKim, Milo } 1687f19b00daSKim, Milo 1688f19b00daSKim, Milo static void regulator_ena_gpio_free(struct regulator_dev *rdev) 1689f19b00daSKim, Milo { 1690f19b00daSKim, Milo struct regulator_enable_gpio *pin, *n; 1691f19b00daSKim, Milo 1692f19b00daSKim, Milo if (!rdev->ena_pin) 1693f19b00daSKim, Milo return; 1694f19b00daSKim, Milo 1695f19b00daSKim, Milo /* Free the GPIO only in case of no use */ 1696f19b00daSKim, Milo list_for_each_entry_safe(pin, n, ®ulator_ena_gpio_list, list) { 1697f19b00daSKim, Milo if (pin->gpio == rdev->ena_pin->gpio) { 1698f19b00daSKim, Milo if (pin->request_count <= 1) { 1699f19b00daSKim, Milo pin->request_count = 0; 1700f19b00daSKim, Milo gpio_free(pin->gpio); 1701f19b00daSKim, Milo list_del(&pin->list); 1702f19b00daSKim, Milo kfree(pin); 1703f19b00daSKim, Milo } else { 1704f19b00daSKim, Milo pin->request_count--; 1705f19b00daSKim, Milo } 1706f19b00daSKim, Milo } 1707f19b00daSKim, Milo } 1708f19b00daSKim, Milo } 1709f19b00daSKim, Milo 1710967cfb18SKim, Milo /** 171131d6eebfSRobert P. J. Day * regulator_ena_gpio_ctrl - balance enable_count of each GPIO and actual GPIO pin control 171231d6eebfSRobert P. J. Day * @rdev: regulator_dev structure 171331d6eebfSRobert P. J. Day * @enable: enable GPIO at initial use? 171431d6eebfSRobert P. J. Day * 1715967cfb18SKim, Milo * GPIO is enabled in case of initial use. (enable_count is 0) 1716967cfb18SKim, Milo * GPIO is disabled when it is not shared any more. (enable_count <= 1) 1717967cfb18SKim, Milo */ 1718967cfb18SKim, Milo static int regulator_ena_gpio_ctrl(struct regulator_dev *rdev, bool enable) 1719967cfb18SKim, Milo { 1720967cfb18SKim, Milo struct regulator_enable_gpio *pin = rdev->ena_pin; 1721967cfb18SKim, Milo 1722967cfb18SKim, Milo if (!pin) 1723967cfb18SKim, Milo return -EINVAL; 1724967cfb18SKim, Milo 1725967cfb18SKim, Milo if (enable) { 1726967cfb18SKim, Milo /* Enable GPIO at initial use */ 1727967cfb18SKim, Milo if (pin->enable_count == 0) 1728967cfb18SKim, Milo gpio_set_value_cansleep(pin->gpio, 1729967cfb18SKim, Milo !pin->ena_gpio_invert); 1730967cfb18SKim, Milo 1731967cfb18SKim, Milo pin->enable_count++; 1732967cfb18SKim, Milo } else { 1733967cfb18SKim, Milo if (pin->enable_count > 1) { 1734967cfb18SKim, Milo pin->enable_count--; 1735967cfb18SKim, Milo return 0; 1736967cfb18SKim, Milo } 1737967cfb18SKim, Milo 1738967cfb18SKim, Milo /* Disable GPIO if not used */ 1739967cfb18SKim, Milo if (pin->enable_count <= 1) { 1740967cfb18SKim, Milo gpio_set_value_cansleep(pin->gpio, 1741967cfb18SKim, Milo pin->ena_gpio_invert); 1742967cfb18SKim, Milo pin->enable_count = 0; 1743967cfb18SKim, Milo } 1744967cfb18SKim, Milo } 1745967cfb18SKim, Milo 1746967cfb18SKim, Milo return 0; 1747967cfb18SKim, Milo } 1748967cfb18SKim, Milo 17495c5659d0SMark Brown static int _regulator_do_enable(struct regulator_dev *rdev) 17505c5659d0SMark Brown { 17515c5659d0SMark Brown int ret, delay; 17525c5659d0SMark Brown 17535c5659d0SMark Brown /* Query before enabling in case configuration dependent. */ 17545c5659d0SMark Brown ret = _regulator_get_enable_time(rdev); 17555c5659d0SMark Brown if (ret >= 0) { 17565c5659d0SMark Brown delay = ret; 17575c5659d0SMark Brown } else { 17585c5659d0SMark Brown rdev_warn(rdev, "enable_time() failed: %d\n", ret); 17595c5659d0SMark Brown delay = 0; 17605c5659d0SMark Brown } 17615c5659d0SMark Brown 17625c5659d0SMark Brown trace_regulator_enable(rdev_get_name(rdev)); 17635c5659d0SMark Brown 1764967cfb18SKim, Milo if (rdev->ena_pin) { 1765967cfb18SKim, Milo ret = regulator_ena_gpio_ctrl(rdev, true); 1766967cfb18SKim, Milo if (ret < 0) 1767967cfb18SKim, Milo return ret; 176865f73508SMark Brown rdev->ena_gpio_state = 1; 176965f73508SMark Brown } else if (rdev->desc->ops->enable) { 17705c5659d0SMark Brown ret = rdev->desc->ops->enable(rdev); 17715c5659d0SMark Brown if (ret < 0) 17725c5659d0SMark Brown return ret; 17735c5659d0SMark Brown } else { 17745c5659d0SMark Brown return -EINVAL; 17755c5659d0SMark Brown } 17765c5659d0SMark Brown 17775c5659d0SMark Brown /* Allow the regulator to ramp; it would be useful to extend 17785c5659d0SMark Brown * this for bulk operations so that the regulators can ramp 17795c5659d0SMark Brown * together. */ 17805c5659d0SMark Brown trace_regulator_enable_delay(rdev_get_name(rdev)); 17815c5659d0SMark Brown 17825df529d4SThierry Reding /* 17835df529d4SThierry Reding * Delay for the requested amount of time as per the guidelines in: 17845df529d4SThierry Reding * 17855df529d4SThierry Reding * Documentation/timers/timers-howto.txt 17865df529d4SThierry Reding * 17875df529d4SThierry Reding * The assumption here is that regulators will never be enabled in 17885df529d4SThierry Reding * atomic context and therefore sleeping functions can be used. 17895df529d4SThierry Reding */ 17905df529d4SThierry Reding if (delay) { 17915df529d4SThierry Reding unsigned int ms = delay / 1000; 17925df529d4SThierry Reding unsigned int us = delay % 1000; 17935df529d4SThierry Reding 17945df529d4SThierry Reding if (ms > 0) { 17955df529d4SThierry Reding /* 17965df529d4SThierry Reding * For small enough values, handle super-millisecond 17975df529d4SThierry Reding * delays in the usleep_range() call below. 17985df529d4SThierry Reding */ 17995df529d4SThierry Reding if (ms < 20) 18005df529d4SThierry Reding us += ms * 1000; 18015df529d4SThierry Reding else 18025df529d4SThierry Reding msleep(ms); 18035df529d4SThierry Reding } 18045df529d4SThierry Reding 18055df529d4SThierry Reding /* 18065df529d4SThierry Reding * Give the scheduler some room to coalesce with any other 18075df529d4SThierry Reding * wakeup sources. For delays shorter than 10 us, don't even 18085df529d4SThierry Reding * bother setting up high-resolution timers and just busy- 18095df529d4SThierry Reding * loop. 18105df529d4SThierry Reding */ 18115df529d4SThierry Reding if (us >= 10) 18125df529d4SThierry Reding usleep_range(us, us + 100); 18135df529d4SThierry Reding else 18145df529d4SThierry Reding udelay(us); 18155c5659d0SMark Brown } 18165c5659d0SMark Brown 18175c5659d0SMark Brown trace_regulator_enable_complete(rdev_get_name(rdev)); 18185c5659d0SMark Brown 18195c5659d0SMark Brown return 0; 18205c5659d0SMark Brown } 18215c5659d0SMark Brown 1822414c70cbSLiam Girdwood /* locks held by regulator_enable() */ 1823414c70cbSLiam Girdwood static int _regulator_enable(struct regulator_dev *rdev) 1824414c70cbSLiam Girdwood { 18255c5659d0SMark Brown int ret; 1826414c70cbSLiam Girdwood 1827414c70cbSLiam Girdwood /* check voltage and requested load before enabling */ 1828414c70cbSLiam Girdwood if (rdev->constraints && 18299a2372faSMark Brown (rdev->constraints->valid_ops_mask & REGULATOR_CHANGE_DRMS)) 1830414c70cbSLiam Girdwood drms_uA_update(rdev); 1831414c70cbSLiam Girdwood 18329a2372faSMark Brown if (rdev->use_count == 0) { 18339a2372faSMark Brown /* The regulator may on if it's not switchable or left on */ 18349a2372faSMark Brown ret = _regulator_is_enabled(rdev); 18359a2372faSMark Brown if (ret == -EINVAL || ret == 0) { 18369a2372faSMark Brown if (!_regulator_can_change_status(rdev)) 18379a2372faSMark Brown return -EPERM; 18389a2372faSMark Brown 18395c5659d0SMark Brown ret = _regulator_do_enable(rdev); 18409a2372faSMark Brown if (ret < 0) 18419a2372faSMark Brown return ret; 184231aae2beSMark Brown 1843a7433cffSLinus Walleij } else if (ret < 0) { 18445da84fd9SJoe Perches rdev_err(rdev, "is_enabled() failed: %d\n", ret); 1845414c70cbSLiam Girdwood return ret; 1846414c70cbSLiam Girdwood } 1847a7433cffSLinus Walleij /* Fallthrough on positive return values - already enabled */ 1848414c70cbSLiam Girdwood } 1849414c70cbSLiam Girdwood 18509a2372faSMark Brown rdev->use_count++; 18519a2372faSMark Brown 18529a2372faSMark Brown return 0; 1853414c70cbSLiam Girdwood } 1854414c70cbSLiam Girdwood 1855414c70cbSLiam Girdwood /** 1856414c70cbSLiam Girdwood * regulator_enable - enable regulator output 1857414c70cbSLiam Girdwood * @regulator: regulator source 1858414c70cbSLiam Girdwood * 1859cf7bbcdfSMark Brown * Request that the regulator be enabled with the regulator output at 1860cf7bbcdfSMark Brown * the predefined voltage or current value. Calls to regulator_enable() 1861cf7bbcdfSMark Brown * must be balanced with calls to regulator_disable(). 1862cf7bbcdfSMark Brown * 1863414c70cbSLiam Girdwood * NOTE: the output value can be set by other drivers, boot loader or may be 1864cf7bbcdfSMark Brown * hardwired in the regulator. 1865414c70cbSLiam Girdwood */ 1866414c70cbSLiam Girdwood int regulator_enable(struct regulator *regulator) 1867414c70cbSLiam Girdwood { 1868412aec61SDavid Brownell struct regulator_dev *rdev = regulator->rdev; 1869412aec61SDavid Brownell int ret = 0; 1870414c70cbSLiam Girdwood 18716492bc1bSMark Brown if (regulator->always_on) 18726492bc1bSMark Brown return 0; 18736492bc1bSMark Brown 18743801b86aSMark Brown if (rdev->supply) { 18753801b86aSMark Brown ret = regulator_enable(rdev->supply); 18763801b86aSMark Brown if (ret != 0) 18773801b86aSMark Brown return ret; 18783801b86aSMark Brown } 18793801b86aSMark Brown 1880412aec61SDavid Brownell mutex_lock(&rdev->mutex); 1881412aec61SDavid Brownell ret = _regulator_enable(rdev); 1882412aec61SDavid Brownell mutex_unlock(&rdev->mutex); 18833801b86aSMark Brown 1884d1685e4eSHeiko Stübner if (ret != 0 && rdev->supply) 18853801b86aSMark Brown regulator_disable(rdev->supply); 18863801b86aSMark Brown 1887414c70cbSLiam Girdwood return ret; 1888414c70cbSLiam Girdwood } 1889414c70cbSLiam Girdwood EXPORT_SYMBOL_GPL(regulator_enable); 1890414c70cbSLiam Girdwood 18915c5659d0SMark Brown static int _regulator_do_disable(struct regulator_dev *rdev) 18925c5659d0SMark Brown { 18935c5659d0SMark Brown int ret; 18945c5659d0SMark Brown 18955c5659d0SMark Brown trace_regulator_disable(rdev_get_name(rdev)); 18965c5659d0SMark Brown 1897967cfb18SKim, Milo if (rdev->ena_pin) { 1898967cfb18SKim, Milo ret = regulator_ena_gpio_ctrl(rdev, false); 1899967cfb18SKim, Milo if (ret < 0) 1900967cfb18SKim, Milo return ret; 19015c5659d0SMark Brown rdev->ena_gpio_state = 0; 19025c5659d0SMark Brown 19035c5659d0SMark Brown } else if (rdev->desc->ops->disable) { 19045c5659d0SMark Brown ret = rdev->desc->ops->disable(rdev); 19055c5659d0SMark Brown if (ret != 0) 19065c5659d0SMark Brown return ret; 19075c5659d0SMark Brown } 19085c5659d0SMark Brown 19095c5659d0SMark Brown trace_regulator_disable_complete(rdev_get_name(rdev)); 19105c5659d0SMark Brown 19115c5659d0SMark Brown return 0; 19125c5659d0SMark Brown } 19135c5659d0SMark Brown 1914414c70cbSLiam Girdwood /* locks held by regulator_disable() */ 19153801b86aSMark Brown static int _regulator_disable(struct regulator_dev *rdev) 1916414c70cbSLiam Girdwood { 1917414c70cbSLiam Girdwood int ret = 0; 1918414c70cbSLiam Girdwood 1919cd94b505SDavid Brownell if (WARN(rdev->use_count <= 0, 192043e7ee33SJoe Perches "unbalanced disables for %s\n", rdev_get_name(rdev))) 1921cd94b505SDavid Brownell return -EIO; 1922cd94b505SDavid Brownell 1923414c70cbSLiam Girdwood /* are we the last user and permitted to disable ? */ 192460ef66fcSMark Brown if (rdev->use_count == 1 && 192560ef66fcSMark Brown (rdev->constraints && !rdev->constraints->always_on)) { 1926414c70cbSLiam Girdwood 1927414c70cbSLiam Girdwood /* we are last user */ 19285c5659d0SMark Brown if (_regulator_can_change_status(rdev)) { 19295c5659d0SMark Brown ret = _regulator_do_disable(rdev); 1930414c70cbSLiam Girdwood if (ret < 0) { 19315da84fd9SJoe Perches rdev_err(rdev, "failed to disable\n"); 1932414c70cbSLiam Girdwood return ret; 1933414c70cbSLiam Girdwood } 193466fda75fSMarkus Pargmann _notifier_call_chain(rdev, REGULATOR_EVENT_DISABLE, 193566fda75fSMarkus Pargmann NULL); 1936414c70cbSLiam Girdwood } 1937414c70cbSLiam Girdwood 1938414c70cbSLiam Girdwood rdev->use_count = 0; 1939414c70cbSLiam Girdwood } else if (rdev->use_count > 1) { 1940414c70cbSLiam Girdwood 1941414c70cbSLiam Girdwood if (rdev->constraints && 1942414c70cbSLiam Girdwood (rdev->constraints->valid_ops_mask & 1943414c70cbSLiam Girdwood REGULATOR_CHANGE_DRMS)) 1944414c70cbSLiam Girdwood drms_uA_update(rdev); 1945414c70cbSLiam Girdwood 1946414c70cbSLiam Girdwood rdev->use_count--; 1947414c70cbSLiam Girdwood } 19483801b86aSMark Brown 1949414c70cbSLiam Girdwood return ret; 1950414c70cbSLiam Girdwood } 1951414c70cbSLiam Girdwood 1952414c70cbSLiam Girdwood /** 1953414c70cbSLiam Girdwood * regulator_disable - disable regulator output 1954414c70cbSLiam Girdwood * @regulator: regulator source 1955414c70cbSLiam Girdwood * 1956cf7bbcdfSMark Brown * Disable the regulator output voltage or current. Calls to 1957cf7bbcdfSMark Brown * regulator_enable() must be balanced with calls to 1958cf7bbcdfSMark Brown * regulator_disable(). 195969279fb9SMark Brown * 1960414c70cbSLiam Girdwood * NOTE: this will only disable the regulator output if no other consumer 1961cf7bbcdfSMark Brown * devices have it enabled, the regulator device supports disabling and 1962cf7bbcdfSMark Brown * machine constraints permit this operation. 1963414c70cbSLiam Girdwood */ 1964414c70cbSLiam Girdwood int regulator_disable(struct regulator *regulator) 1965414c70cbSLiam Girdwood { 1966412aec61SDavid Brownell struct regulator_dev *rdev = regulator->rdev; 1967412aec61SDavid Brownell int ret = 0; 1968414c70cbSLiam Girdwood 19696492bc1bSMark Brown if (regulator->always_on) 19706492bc1bSMark Brown return 0; 19716492bc1bSMark Brown 1972412aec61SDavid Brownell mutex_lock(&rdev->mutex); 19733801b86aSMark Brown ret = _regulator_disable(rdev); 1974412aec61SDavid Brownell mutex_unlock(&rdev->mutex); 19758cbf811dSJeffrey Carlyle 19763801b86aSMark Brown if (ret == 0 && rdev->supply) 19773801b86aSMark Brown regulator_disable(rdev->supply); 19788cbf811dSJeffrey Carlyle 1979414c70cbSLiam Girdwood return ret; 1980414c70cbSLiam Girdwood } 1981414c70cbSLiam Girdwood EXPORT_SYMBOL_GPL(regulator_disable); 1982414c70cbSLiam Girdwood 1983414c70cbSLiam Girdwood /* locks held by regulator_force_disable() */ 19843801b86aSMark Brown static int _regulator_force_disable(struct regulator_dev *rdev) 1985414c70cbSLiam Girdwood { 1986414c70cbSLiam Girdwood int ret = 0; 1987414c70cbSLiam Girdwood 198866fda75fSMarkus Pargmann ret = _regulator_do_disable(rdev); 1989414c70cbSLiam Girdwood if (ret < 0) { 19905da84fd9SJoe Perches rdev_err(rdev, "failed to force disable\n"); 1991414c70cbSLiam Girdwood return ret; 1992414c70cbSLiam Girdwood } 199366fda75fSMarkus Pargmann 199484b68263SMark Brown _notifier_call_chain(rdev, REGULATOR_EVENT_FORCE_DISABLE | 199584b68263SMark Brown REGULATOR_EVENT_DISABLE, NULL); 1996414c70cbSLiam Girdwood 199766fda75fSMarkus Pargmann return 0; 1998414c70cbSLiam Girdwood } 1999414c70cbSLiam Girdwood 2000414c70cbSLiam Girdwood /** 2001414c70cbSLiam Girdwood * regulator_force_disable - force disable regulator output 2002414c70cbSLiam Girdwood * @regulator: regulator source 2003414c70cbSLiam Girdwood * 2004414c70cbSLiam Girdwood * Forcibly disable the regulator output voltage or current. 2005414c70cbSLiam Girdwood * NOTE: this *will* disable the regulator output even if other consumer 2006414c70cbSLiam Girdwood * devices have it enabled. This should be used for situations when device 2007414c70cbSLiam Girdwood * damage will likely occur if the regulator is not disabled (e.g. over temp). 2008414c70cbSLiam Girdwood */ 2009414c70cbSLiam Girdwood int regulator_force_disable(struct regulator *regulator) 2010414c70cbSLiam Girdwood { 201182d15839SMark Brown struct regulator_dev *rdev = regulator->rdev; 2012414c70cbSLiam Girdwood int ret; 2013414c70cbSLiam Girdwood 201482d15839SMark Brown mutex_lock(&rdev->mutex); 2015414c70cbSLiam Girdwood regulator->uA_load = 0; 20163801b86aSMark Brown ret = _regulator_force_disable(regulator->rdev); 201782d15839SMark Brown mutex_unlock(&rdev->mutex); 20188cbf811dSJeffrey Carlyle 20193801b86aSMark Brown if (rdev->supply) 20203801b86aSMark Brown while (rdev->open_count--) 20213801b86aSMark Brown regulator_disable(rdev->supply); 20228cbf811dSJeffrey Carlyle 2023414c70cbSLiam Girdwood return ret; 2024414c70cbSLiam Girdwood } 2025414c70cbSLiam Girdwood EXPORT_SYMBOL_GPL(regulator_force_disable); 2026414c70cbSLiam Girdwood 2027da07ecd9SMark Brown static void regulator_disable_work(struct work_struct *work) 2028da07ecd9SMark Brown { 2029da07ecd9SMark Brown struct regulator_dev *rdev = container_of(work, struct regulator_dev, 2030da07ecd9SMark Brown disable_work.work); 2031da07ecd9SMark Brown int count, i, ret; 2032da07ecd9SMark Brown 2033da07ecd9SMark Brown mutex_lock(&rdev->mutex); 2034da07ecd9SMark Brown 2035da07ecd9SMark Brown BUG_ON(!rdev->deferred_disables); 2036da07ecd9SMark Brown 2037da07ecd9SMark Brown count = rdev->deferred_disables; 2038da07ecd9SMark Brown rdev->deferred_disables = 0; 2039da07ecd9SMark Brown 2040da07ecd9SMark Brown for (i = 0; i < count; i++) { 2041da07ecd9SMark Brown ret = _regulator_disable(rdev); 2042da07ecd9SMark Brown if (ret != 0) 2043da07ecd9SMark Brown rdev_err(rdev, "Deferred disable failed: %d\n", ret); 2044da07ecd9SMark Brown } 2045da07ecd9SMark Brown 2046da07ecd9SMark Brown mutex_unlock(&rdev->mutex); 2047da07ecd9SMark Brown 2048da07ecd9SMark Brown if (rdev->supply) { 2049da07ecd9SMark Brown for (i = 0; i < count; i++) { 2050da07ecd9SMark Brown ret = regulator_disable(rdev->supply); 2051da07ecd9SMark Brown if (ret != 0) { 2052da07ecd9SMark Brown rdev_err(rdev, 2053da07ecd9SMark Brown "Supply disable failed: %d\n", ret); 2054da07ecd9SMark Brown } 2055da07ecd9SMark Brown } 2056da07ecd9SMark Brown } 2057da07ecd9SMark Brown } 2058da07ecd9SMark Brown 2059da07ecd9SMark Brown /** 2060da07ecd9SMark Brown * regulator_disable_deferred - disable regulator output with delay 2061da07ecd9SMark Brown * @regulator: regulator source 2062da07ecd9SMark Brown * @ms: miliseconds until the regulator is disabled 2063da07ecd9SMark Brown * 2064da07ecd9SMark Brown * Execute regulator_disable() on the regulator after a delay. This 2065da07ecd9SMark Brown * is intended for use with devices that require some time to quiesce. 2066da07ecd9SMark Brown * 2067da07ecd9SMark Brown * NOTE: this will only disable the regulator output if no other consumer 2068da07ecd9SMark Brown * devices have it enabled, the regulator device supports disabling and 2069da07ecd9SMark Brown * machine constraints permit this operation. 2070da07ecd9SMark Brown */ 2071da07ecd9SMark Brown int regulator_disable_deferred(struct regulator *regulator, int ms) 2072da07ecd9SMark Brown { 2073da07ecd9SMark Brown struct regulator_dev *rdev = regulator->rdev; 2074aa59802dSMark Brown int ret; 2075da07ecd9SMark Brown 20766492bc1bSMark Brown if (regulator->always_on) 20776492bc1bSMark Brown return 0; 20786492bc1bSMark Brown 20792b5a24a0SMark Brown if (!ms) 20802b5a24a0SMark Brown return regulator_disable(regulator); 20812b5a24a0SMark Brown 2082da07ecd9SMark Brown mutex_lock(&rdev->mutex); 2083da07ecd9SMark Brown rdev->deferred_disables++; 2084da07ecd9SMark Brown mutex_unlock(&rdev->mutex); 2085da07ecd9SMark Brown 2086070260f0SMark Brown ret = queue_delayed_work(system_power_efficient_wq, 2087070260f0SMark Brown &rdev->disable_work, 2088da07ecd9SMark Brown msecs_to_jiffies(ms)); 2089aa59802dSMark Brown if (ret < 0) 2090aa59802dSMark Brown return ret; 2091aa59802dSMark Brown else 2092aa59802dSMark Brown return 0; 2093da07ecd9SMark Brown } 2094da07ecd9SMark Brown EXPORT_SYMBOL_GPL(regulator_disable_deferred); 2095da07ecd9SMark Brown 2096414c70cbSLiam Girdwood static int _regulator_is_enabled(struct regulator_dev *rdev) 2097414c70cbSLiam Girdwood { 209865f73508SMark Brown /* A GPIO control always takes precedence */ 20997b74d149SKim, Milo if (rdev->ena_pin) 210065f73508SMark Brown return rdev->ena_gpio_state; 210165f73508SMark Brown 21029a7f6a4cSMark Brown /* If we don't know then assume that the regulator is always on */ 21039332546fSMark Brown if (!rdev->desc->ops->is_enabled) 21049a7f6a4cSMark Brown return 1; 2105414c70cbSLiam Girdwood 21069332546fSMark Brown return rdev->desc->ops->is_enabled(rdev); 2107414c70cbSLiam Girdwood } 2108414c70cbSLiam Girdwood 2109414c70cbSLiam Girdwood /** 2110414c70cbSLiam Girdwood * regulator_is_enabled - is the regulator output enabled 2111414c70cbSLiam Girdwood * @regulator: regulator source 2112414c70cbSLiam Girdwood * 2113412aec61SDavid Brownell * Returns positive if the regulator driver backing the source/client 2114412aec61SDavid Brownell * has requested that the device be enabled, zero if it hasn't, else a 2115412aec61SDavid Brownell * negative errno code. 2116412aec61SDavid Brownell * 2117412aec61SDavid Brownell * Note that the device backing this regulator handle can have multiple 2118412aec61SDavid Brownell * users, so it might be enabled even if regulator_enable() was never 2119412aec61SDavid Brownell * called for this particular source. 2120414c70cbSLiam Girdwood */ 2121414c70cbSLiam Girdwood int regulator_is_enabled(struct regulator *regulator) 2122414c70cbSLiam Girdwood { 21239332546fSMark Brown int ret; 21249332546fSMark Brown 21256492bc1bSMark Brown if (regulator->always_on) 21266492bc1bSMark Brown return 1; 21276492bc1bSMark Brown 21289332546fSMark Brown mutex_lock(®ulator->rdev->mutex); 21299332546fSMark Brown ret = _regulator_is_enabled(regulator->rdev); 21309332546fSMark Brown mutex_unlock(®ulator->rdev->mutex); 21319332546fSMark Brown 21329332546fSMark Brown return ret; 2133414c70cbSLiam Girdwood } 2134414c70cbSLiam Girdwood EXPORT_SYMBOL_GPL(regulator_is_enabled); 2135414c70cbSLiam Girdwood 2136414c70cbSLiam Girdwood /** 2137d1e7de30SMarek Szyprowski * regulator_can_change_voltage - check if regulator can change voltage 2138d1e7de30SMarek Szyprowski * @regulator: regulator source 2139d1e7de30SMarek Szyprowski * 2140d1e7de30SMarek Szyprowski * Returns positive if the regulator driver backing the source/client 2141e227867fSMasanari Iida * can change its voltage, false otherwise. Useful for detecting fixed 2142d1e7de30SMarek Szyprowski * or dummy regulators and disabling voltage change logic in the client 2143d1e7de30SMarek Szyprowski * driver. 2144d1e7de30SMarek Szyprowski */ 2145d1e7de30SMarek Szyprowski int regulator_can_change_voltage(struct regulator *regulator) 2146d1e7de30SMarek Szyprowski { 2147d1e7de30SMarek Szyprowski struct regulator_dev *rdev = regulator->rdev; 2148d1e7de30SMarek Szyprowski 2149d1e7de30SMarek Szyprowski if (rdev->constraints && 215019280e40SAxel Lin (rdev->constraints->valid_ops_mask & REGULATOR_CHANGE_VOLTAGE)) { 215119280e40SAxel Lin if (rdev->desc->n_voltages - rdev->desc->linear_min_sel > 1) 2152d1e7de30SMarek Szyprowski return 1; 2153d1e7de30SMarek Szyprowski 215419280e40SAxel Lin if (rdev->desc->continuous_voltage_range && 215519280e40SAxel Lin rdev->constraints->min_uV && rdev->constraints->max_uV && 215619280e40SAxel Lin rdev->constraints->min_uV != rdev->constraints->max_uV) 215719280e40SAxel Lin return 1; 215819280e40SAxel Lin } 215919280e40SAxel Lin 2160d1e7de30SMarek Szyprowski return 0; 2161d1e7de30SMarek Szyprowski } 2162d1e7de30SMarek Szyprowski EXPORT_SYMBOL_GPL(regulator_can_change_voltage); 2163d1e7de30SMarek Szyprowski 2164d1e7de30SMarek Szyprowski /** 21654367cfdcSDavid Brownell * regulator_count_voltages - count regulator_list_voltage() selectors 21664367cfdcSDavid Brownell * @regulator: regulator source 21674367cfdcSDavid Brownell * 21684367cfdcSDavid Brownell * Returns number of selectors, or negative errno. Selectors are 21694367cfdcSDavid Brownell * numbered starting at zero, and typically correspond to bitfields 21704367cfdcSDavid Brownell * in hardware registers. 21714367cfdcSDavid Brownell */ 21724367cfdcSDavid Brownell int regulator_count_voltages(struct regulator *regulator) 21734367cfdcSDavid Brownell { 21744367cfdcSDavid Brownell struct regulator_dev *rdev = regulator->rdev; 21754367cfdcSDavid Brownell 21764367cfdcSDavid Brownell return rdev->desc->n_voltages ? : -EINVAL; 21774367cfdcSDavid Brownell } 21784367cfdcSDavid Brownell EXPORT_SYMBOL_GPL(regulator_count_voltages); 21794367cfdcSDavid Brownell 21804367cfdcSDavid Brownell /** 21814367cfdcSDavid Brownell * regulator_list_voltage - enumerate supported voltages 21824367cfdcSDavid Brownell * @regulator: regulator source 21834367cfdcSDavid Brownell * @selector: identify voltage to list 21844367cfdcSDavid Brownell * Context: can sleep 21854367cfdcSDavid Brownell * 21864367cfdcSDavid Brownell * Returns a voltage that can be passed to @regulator_set_voltage(), 218788393161SThomas Weber * zero if this selector code can't be used on this system, or a 21884367cfdcSDavid Brownell * negative errno. 21894367cfdcSDavid Brownell */ 21904367cfdcSDavid Brownell int regulator_list_voltage(struct regulator *regulator, unsigned selector) 21914367cfdcSDavid Brownell { 21924367cfdcSDavid Brownell struct regulator_dev *rdev = regulator->rdev; 21934367cfdcSDavid Brownell struct regulator_ops *ops = rdev->desc->ops; 21944367cfdcSDavid Brownell int ret; 21954367cfdcSDavid Brownell 2196f446043fSGuennadi Liakhovetski if (rdev->desc->fixed_uV && rdev->desc->n_voltages == 1 && !selector) 2197f446043fSGuennadi Liakhovetski return rdev->desc->fixed_uV; 2198f446043fSGuennadi Liakhovetski 21994367cfdcSDavid Brownell if (!ops->list_voltage || selector >= rdev->desc->n_voltages) 22004367cfdcSDavid Brownell return -EINVAL; 22014367cfdcSDavid Brownell 22024367cfdcSDavid Brownell mutex_lock(&rdev->mutex); 22034367cfdcSDavid Brownell ret = ops->list_voltage(rdev, selector); 22044367cfdcSDavid Brownell mutex_unlock(&rdev->mutex); 22054367cfdcSDavid Brownell 22064367cfdcSDavid Brownell if (ret > 0) { 22074367cfdcSDavid Brownell if (ret < rdev->constraints->min_uV) 22084367cfdcSDavid Brownell ret = 0; 22094367cfdcSDavid Brownell else if (ret > rdev->constraints->max_uV) 22104367cfdcSDavid Brownell ret = 0; 22114367cfdcSDavid Brownell } 22124367cfdcSDavid Brownell 22134367cfdcSDavid Brownell return ret; 22144367cfdcSDavid Brownell } 22154367cfdcSDavid Brownell EXPORT_SYMBOL_GPL(regulator_list_voltage); 22164367cfdcSDavid Brownell 22174367cfdcSDavid Brownell /** 22182a668a8bSPaul Walmsley * regulator_get_linear_step - return the voltage step size between VSEL values 22192a668a8bSPaul Walmsley * @regulator: regulator source 22202a668a8bSPaul Walmsley * 22212a668a8bSPaul Walmsley * Returns the voltage step size between VSEL values for linear 22222a668a8bSPaul Walmsley * regulators, or return 0 if the regulator isn't a linear regulator. 22232a668a8bSPaul Walmsley */ 22242a668a8bSPaul Walmsley unsigned int regulator_get_linear_step(struct regulator *regulator) 22252a668a8bSPaul Walmsley { 22262a668a8bSPaul Walmsley struct regulator_dev *rdev = regulator->rdev; 22272a668a8bSPaul Walmsley 22282a668a8bSPaul Walmsley return rdev->desc->uV_step; 22292a668a8bSPaul Walmsley } 22302a668a8bSPaul Walmsley EXPORT_SYMBOL_GPL(regulator_get_linear_step); 22312a668a8bSPaul Walmsley 22322a668a8bSPaul Walmsley /** 2233a7a1ad90SMark Brown * regulator_is_supported_voltage - check if a voltage range can be supported 2234a7a1ad90SMark Brown * 2235a7a1ad90SMark Brown * @regulator: Regulator to check. 2236a7a1ad90SMark Brown * @min_uV: Minimum required voltage in uV. 2237a7a1ad90SMark Brown * @max_uV: Maximum required voltage in uV. 2238a7a1ad90SMark Brown * 2239a7a1ad90SMark Brown * Returns a boolean or a negative error code. 2240a7a1ad90SMark Brown */ 2241a7a1ad90SMark Brown int regulator_is_supported_voltage(struct regulator *regulator, 2242a7a1ad90SMark Brown int min_uV, int max_uV) 2243a7a1ad90SMark Brown { 2244c5f3939bSMark Brown struct regulator_dev *rdev = regulator->rdev; 2245a7a1ad90SMark Brown int i, voltages, ret; 2246a7a1ad90SMark Brown 2247c5f3939bSMark Brown /* If we can't change voltage check the current voltage */ 2248c5f3939bSMark Brown if (!(rdev->constraints->valid_ops_mask & REGULATOR_CHANGE_VOLTAGE)) { 2249c5f3939bSMark Brown ret = regulator_get_voltage(regulator); 2250c5f3939bSMark Brown if (ret >= 0) 22510d25d09dSJingoo Han return min_uV <= ret && ret <= max_uV; 2252c5f3939bSMark Brown else 2253c5f3939bSMark Brown return ret; 2254c5f3939bSMark Brown } 2255c5f3939bSMark Brown 2256bd7a2b60SPawel Moll /* Any voltage within constrains range is fine? */ 2257bd7a2b60SPawel Moll if (rdev->desc->continuous_voltage_range) 2258bd7a2b60SPawel Moll return min_uV >= rdev->constraints->min_uV && 2259bd7a2b60SPawel Moll max_uV <= rdev->constraints->max_uV; 2260bd7a2b60SPawel Moll 2261a7a1ad90SMark Brown ret = regulator_count_voltages(regulator); 2262a7a1ad90SMark Brown if (ret < 0) 2263a7a1ad90SMark Brown return ret; 2264a7a1ad90SMark Brown voltages = ret; 2265a7a1ad90SMark Brown 2266a7a1ad90SMark Brown for (i = 0; i < voltages; i++) { 2267a7a1ad90SMark Brown ret = regulator_list_voltage(regulator, i); 2268a7a1ad90SMark Brown 2269a7a1ad90SMark Brown if (ret >= min_uV && ret <= max_uV) 2270a7a1ad90SMark Brown return 1; 2271a7a1ad90SMark Brown } 2272a7a1ad90SMark Brown 2273a7a1ad90SMark Brown return 0; 2274a7a1ad90SMark Brown } 2275a398eaa2SMark Brown EXPORT_SYMBOL_GPL(regulator_is_supported_voltage); 2276a7a1ad90SMark Brown 227775790251SMark Brown static int _regulator_do_set_voltage(struct regulator_dev *rdev, 227875790251SMark Brown int min_uV, int max_uV) 227975790251SMark Brown { 228075790251SMark Brown int ret; 228177af1b26SLinus Walleij int delay = 0; 2282e113d792SMark Brown int best_val = 0; 228375790251SMark Brown unsigned int selector; 2284eba41a5eSAxel Lin int old_selector = -1; 228575790251SMark Brown 228675790251SMark Brown trace_regulator_set_voltage(rdev_get_name(rdev), min_uV, max_uV); 228775790251SMark Brown 2288bf5892a8SMark Brown min_uV += rdev->constraints->uV_offset; 2289bf5892a8SMark Brown max_uV += rdev->constraints->uV_offset; 2290bf5892a8SMark Brown 229177af1b26SLinus Walleij /* 229277af1b26SLinus Walleij * If we can't obtain the old selector there is not enough 229377af1b26SLinus Walleij * info to call set_voltage_time_sel(). 229477af1b26SLinus Walleij */ 22958b7485efSAxel Lin if (_regulator_is_enabled(rdev) && 22968b7485efSAxel Lin rdev->desc->ops->set_voltage_time_sel && 229777af1b26SLinus Walleij rdev->desc->ops->get_voltage_sel) { 2298eba41a5eSAxel Lin old_selector = rdev->desc->ops->get_voltage_sel(rdev); 2299eba41a5eSAxel Lin if (old_selector < 0) 2300eba41a5eSAxel Lin return old_selector; 2301eba41a5eSAxel Lin } 230277af1b26SLinus Walleij 230375790251SMark Brown if (rdev->desc->ops->set_voltage) { 230475790251SMark Brown ret = rdev->desc->ops->set_voltage(rdev, min_uV, max_uV, 230575790251SMark Brown &selector); 2306e113d792SMark Brown 2307e113d792SMark Brown if (ret >= 0) { 2308e113d792SMark Brown if (rdev->desc->ops->list_voltage) 2309e113d792SMark Brown best_val = rdev->desc->ops->list_voltage(rdev, 2310e113d792SMark Brown selector); 2311e113d792SMark Brown else 2312e113d792SMark Brown best_val = _regulator_get_voltage(rdev); 2313e113d792SMark Brown } 2314e113d792SMark Brown 2315e8eef82bSMark Brown } else if (rdev->desc->ops->set_voltage_sel) { 23169152c36aSAxel Lin if (rdev->desc->ops->map_voltage) { 2317e843fc46SMark Brown ret = rdev->desc->ops->map_voltage(rdev, min_uV, 2318e843fc46SMark Brown max_uV); 23199152c36aSAxel Lin } else { 23209152c36aSAxel Lin if (rdev->desc->ops->list_voltage == 23219152c36aSAxel Lin regulator_list_voltage_linear) 23229152c36aSAxel Lin ret = regulator_map_voltage_linear(rdev, 23239152c36aSAxel Lin min_uV, max_uV); 232407351233SAxel Lin else 23259152c36aSAxel Lin ret = regulator_map_voltage_iterate(rdev, 23269152c36aSAxel Lin min_uV, max_uV); 23279152c36aSAxel Lin } 2328e843fc46SMark Brown 2329e843fc46SMark Brown if (ret >= 0) { 2330e113d792SMark Brown best_val = rdev->desc->ops->list_voltage(rdev, ret); 2331e113d792SMark Brown if (min_uV <= best_val && max_uV >= best_val) { 2332e843fc46SMark Brown selector = ret; 2333c66a566aSAxel Lin if (old_selector == selector) 2334c66a566aSAxel Lin ret = 0; 2335c66a566aSAxel Lin else 2336c66a566aSAxel Lin ret = rdev->desc->ops->set_voltage_sel( 2337c66a566aSAxel Lin rdev, ret); 2338e113d792SMark Brown } else { 2339e113d792SMark Brown ret = -EINVAL; 2340e113d792SMark Brown } 2341e843fc46SMark Brown } 2342e8eef82bSMark Brown } else { 2343e8eef82bSMark Brown ret = -EINVAL; 2344e8eef82bSMark Brown } 2345e8eef82bSMark Brown 2346eba41a5eSAxel Lin /* Call set_voltage_time_sel if successfully obtained old_selector */ 23475b175952SYadwinder Singh Brar if (ret == 0 && !rdev->constraints->ramp_disable && old_selector >= 0 23485b175952SYadwinder Singh Brar && old_selector != selector) { 2349eba41a5eSAxel Lin 2350eba41a5eSAxel Lin delay = rdev->desc->ops->set_voltage_time_sel(rdev, 2351eba41a5eSAxel Lin old_selector, selector); 2352eba41a5eSAxel Lin if (delay < 0) { 2353eba41a5eSAxel Lin rdev_warn(rdev, "set_voltage_time_sel() failed: %d\n", 2354eba41a5eSAxel Lin delay); 2355eba41a5eSAxel Lin delay = 0; 2356e8eef82bSMark Brown } 235775790251SMark Brown 235877af1b26SLinus Walleij /* Insert any necessary delays */ 235977af1b26SLinus Walleij if (delay >= 1000) { 236077af1b26SLinus Walleij mdelay(delay / 1000); 236177af1b26SLinus Walleij udelay(delay % 1000); 236277af1b26SLinus Walleij } else if (delay) { 236377af1b26SLinus Walleij udelay(delay); 236477af1b26SLinus Walleij } 23658b96de31SPhilip Rakity } 236677af1b26SLinus Walleij 23672f6c797fSAxel Lin if (ret == 0 && best_val >= 0) { 23682f6c797fSAxel Lin unsigned long data = best_val; 23692f6c797fSAxel Lin 2370ded06a52SMark Brown _notifier_call_chain(rdev, REGULATOR_EVENT_VOLTAGE_CHANGE, 23712f6c797fSAxel Lin (void *)data); 23722f6c797fSAxel Lin } 2373ded06a52SMark Brown 2374eba41a5eSAxel Lin trace_regulator_set_voltage_complete(rdev_get_name(rdev), best_val); 237575790251SMark Brown 237675790251SMark Brown return ret; 237775790251SMark Brown } 237875790251SMark Brown 2379a7a1ad90SMark Brown /** 2380414c70cbSLiam Girdwood * regulator_set_voltage - set regulator output voltage 2381414c70cbSLiam Girdwood * @regulator: regulator source 2382414c70cbSLiam Girdwood * @min_uV: Minimum required voltage in uV 2383414c70cbSLiam Girdwood * @max_uV: Maximum acceptable voltage in uV 2384414c70cbSLiam Girdwood * 2385414c70cbSLiam Girdwood * Sets a voltage regulator to the desired output voltage. This can be set 2386414c70cbSLiam Girdwood * during any regulator state. IOW, regulator can be disabled or enabled. 2387414c70cbSLiam Girdwood * 2388414c70cbSLiam Girdwood * If the regulator is enabled then the voltage will change to the new value 2389414c70cbSLiam Girdwood * immediately otherwise if the regulator is disabled the regulator will 2390414c70cbSLiam Girdwood * output at the new voltage when enabled. 2391414c70cbSLiam Girdwood * 2392414c70cbSLiam Girdwood * NOTE: If the regulator is shared between several devices then the lowest 2393414c70cbSLiam Girdwood * request voltage that meets the system constraints will be used. 239469279fb9SMark Brown * Regulator system constraints must be set for this regulator before 2395414c70cbSLiam Girdwood * calling this function otherwise this call will fail. 2396414c70cbSLiam Girdwood */ 2397414c70cbSLiam Girdwood int regulator_set_voltage(struct regulator *regulator, int min_uV, int max_uV) 2398414c70cbSLiam Girdwood { 2399414c70cbSLiam Girdwood struct regulator_dev *rdev = regulator->rdev; 240095a3c23aSMark Brown int ret = 0; 240192d7a558SPaolo Pisati int old_min_uV, old_max_uV; 2402c00dc359SBjorn Andersson int current_uV; 2403414c70cbSLiam Girdwood 2404414c70cbSLiam Girdwood mutex_lock(&rdev->mutex); 2405414c70cbSLiam Girdwood 240695a3c23aSMark Brown /* If we're setting the same range as last time the change 240795a3c23aSMark Brown * should be a noop (some cpufreq implementations use the same 240895a3c23aSMark Brown * voltage for multiple frequencies, for example). 240995a3c23aSMark Brown */ 241095a3c23aSMark Brown if (regulator->min_uV == min_uV && regulator->max_uV == max_uV) 241195a3c23aSMark Brown goto out; 241295a3c23aSMark Brown 2413c00dc359SBjorn Andersson /* If we're trying to set a range that overlaps the current voltage, 2414c00dc359SBjorn Andersson * return succesfully even though the regulator does not support 2415c00dc359SBjorn Andersson * changing the voltage. 2416c00dc359SBjorn Andersson */ 2417c00dc359SBjorn Andersson if (!(rdev->constraints->valid_ops_mask & REGULATOR_CHANGE_VOLTAGE)) { 2418c00dc359SBjorn Andersson current_uV = _regulator_get_voltage(rdev); 2419c00dc359SBjorn Andersson if (min_uV <= current_uV && current_uV <= max_uV) { 2420c00dc359SBjorn Andersson regulator->min_uV = min_uV; 2421c00dc359SBjorn Andersson regulator->max_uV = max_uV; 2422c00dc359SBjorn Andersson goto out; 2423c00dc359SBjorn Andersson } 2424c00dc359SBjorn Andersson } 2425c00dc359SBjorn Andersson 2426414c70cbSLiam Girdwood /* sanity check */ 2427e8eef82bSMark Brown if (!rdev->desc->ops->set_voltage && 2428e8eef82bSMark Brown !rdev->desc->ops->set_voltage_sel) { 2429414c70cbSLiam Girdwood ret = -EINVAL; 2430414c70cbSLiam Girdwood goto out; 2431414c70cbSLiam Girdwood } 2432414c70cbSLiam Girdwood 2433414c70cbSLiam Girdwood /* constraints check */ 2434414c70cbSLiam Girdwood ret = regulator_check_voltage(rdev, &min_uV, &max_uV); 2435414c70cbSLiam Girdwood if (ret < 0) 2436414c70cbSLiam Girdwood goto out; 243792d7a558SPaolo Pisati 243892d7a558SPaolo Pisati /* restore original values in case of error */ 243992d7a558SPaolo Pisati old_min_uV = regulator->min_uV; 244092d7a558SPaolo Pisati old_max_uV = regulator->max_uV; 2441414c70cbSLiam Girdwood regulator->min_uV = min_uV; 2442414c70cbSLiam Girdwood regulator->max_uV = max_uV; 24433a93f2a9SMark Brown 244405fda3b1SThomas Petazzoni ret = regulator_check_consumers(rdev, &min_uV, &max_uV); 244505fda3b1SThomas Petazzoni if (ret < 0) 244692d7a558SPaolo Pisati goto out2; 244705fda3b1SThomas Petazzoni 244875790251SMark Brown ret = _regulator_do_set_voltage(rdev, min_uV, max_uV); 244992d7a558SPaolo Pisati if (ret < 0) 245092d7a558SPaolo Pisati goto out2; 245102fa3ec0SMark Brown 2452414c70cbSLiam Girdwood out: 2453414c70cbSLiam Girdwood mutex_unlock(&rdev->mutex); 2454414c70cbSLiam Girdwood return ret; 245592d7a558SPaolo Pisati out2: 245692d7a558SPaolo Pisati regulator->min_uV = old_min_uV; 245792d7a558SPaolo Pisati regulator->max_uV = old_max_uV; 245892d7a558SPaolo Pisati mutex_unlock(&rdev->mutex); 245992d7a558SPaolo Pisati return ret; 2460414c70cbSLiam Girdwood } 2461414c70cbSLiam Girdwood EXPORT_SYMBOL_GPL(regulator_set_voltage); 2462414c70cbSLiam Girdwood 2463606a2562SMark Brown /** 246488cd222bSLinus Walleij * regulator_set_voltage_time - get raise/fall time 246588cd222bSLinus Walleij * @regulator: regulator source 246688cd222bSLinus Walleij * @old_uV: starting voltage in microvolts 246788cd222bSLinus Walleij * @new_uV: target voltage in microvolts 246888cd222bSLinus Walleij * 246988cd222bSLinus Walleij * Provided with the starting and ending voltage, this function attempts to 247088cd222bSLinus Walleij * calculate the time in microseconds required to rise or fall to this new 247188cd222bSLinus Walleij * voltage. 247288cd222bSLinus Walleij */ 247388cd222bSLinus Walleij int regulator_set_voltage_time(struct regulator *regulator, 247488cd222bSLinus Walleij int old_uV, int new_uV) 247588cd222bSLinus Walleij { 247688cd222bSLinus Walleij struct regulator_dev *rdev = regulator->rdev; 247788cd222bSLinus Walleij struct regulator_ops *ops = rdev->desc->ops; 247888cd222bSLinus Walleij int old_sel = -1; 247988cd222bSLinus Walleij int new_sel = -1; 248088cd222bSLinus Walleij int voltage; 248188cd222bSLinus Walleij int i; 248288cd222bSLinus Walleij 248388cd222bSLinus Walleij /* Currently requires operations to do this */ 248488cd222bSLinus Walleij if (!ops->list_voltage || !ops->set_voltage_time_sel 248588cd222bSLinus Walleij || !rdev->desc->n_voltages) 248688cd222bSLinus Walleij return -EINVAL; 248788cd222bSLinus Walleij 248888cd222bSLinus Walleij for (i = 0; i < rdev->desc->n_voltages; i++) { 248988cd222bSLinus Walleij /* We only look for exact voltage matches here */ 249088cd222bSLinus Walleij voltage = regulator_list_voltage(regulator, i); 249188cd222bSLinus Walleij if (voltage < 0) 249288cd222bSLinus Walleij return -EINVAL; 249388cd222bSLinus Walleij if (voltage == 0) 249488cd222bSLinus Walleij continue; 249588cd222bSLinus Walleij if (voltage == old_uV) 249688cd222bSLinus Walleij old_sel = i; 249788cd222bSLinus Walleij if (voltage == new_uV) 249888cd222bSLinus Walleij new_sel = i; 249988cd222bSLinus Walleij } 250088cd222bSLinus Walleij 250188cd222bSLinus Walleij if (old_sel < 0 || new_sel < 0) 250288cd222bSLinus Walleij return -EINVAL; 250388cd222bSLinus Walleij 250488cd222bSLinus Walleij return ops->set_voltage_time_sel(rdev, old_sel, new_sel); 250588cd222bSLinus Walleij } 250688cd222bSLinus Walleij EXPORT_SYMBOL_GPL(regulator_set_voltage_time); 250788cd222bSLinus Walleij 250888cd222bSLinus Walleij /** 250998a175b6SYadwinder Singh Brar * regulator_set_voltage_time_sel - get raise/fall time 2510296c6566SRandy Dunlap * @rdev: regulator source device 251198a175b6SYadwinder Singh Brar * @old_selector: selector for starting voltage 251298a175b6SYadwinder Singh Brar * @new_selector: selector for target voltage 251398a175b6SYadwinder Singh Brar * 251498a175b6SYadwinder Singh Brar * Provided with the starting and target voltage selectors, this function 251598a175b6SYadwinder Singh Brar * returns time in microseconds required to rise or fall to this new voltage 251698a175b6SYadwinder Singh Brar * 2517f11d08c3SAxel Lin * Drivers providing ramp_delay in regulation_constraints can use this as their 2518398715abSAxel Lin * set_voltage_time_sel() operation. 251998a175b6SYadwinder Singh Brar */ 252098a175b6SYadwinder Singh Brar int regulator_set_voltage_time_sel(struct regulator_dev *rdev, 252198a175b6SYadwinder Singh Brar unsigned int old_selector, 252298a175b6SYadwinder Singh Brar unsigned int new_selector) 252398a175b6SYadwinder Singh Brar { 2524398715abSAxel Lin unsigned int ramp_delay = 0; 2525f11d08c3SAxel Lin int old_volt, new_volt; 2526398715abSAxel Lin 25276f0b2c69SYadwinder Singh Brar if (rdev->constraints->ramp_delay) 2528398715abSAxel Lin ramp_delay = rdev->constraints->ramp_delay; 2529398715abSAxel Lin else if (rdev->desc->ramp_delay) 2530398715abSAxel Lin ramp_delay = rdev->desc->ramp_delay; 2531398715abSAxel Lin 2532398715abSAxel Lin if (ramp_delay == 0) { 25336f0b2c69SYadwinder Singh Brar rdev_warn(rdev, "ramp_delay not set\n"); 2534398715abSAxel Lin return 0; 25356f0b2c69SYadwinder Singh Brar } 2536398715abSAxel Lin 2537f11d08c3SAxel Lin /* sanity check */ 2538f11d08c3SAxel Lin if (!rdev->desc->ops->list_voltage) 2539f11d08c3SAxel Lin return -EINVAL; 2540398715abSAxel Lin 2541f11d08c3SAxel Lin old_volt = rdev->desc->ops->list_voltage(rdev, old_selector); 2542f11d08c3SAxel Lin new_volt = rdev->desc->ops->list_voltage(rdev, new_selector); 2543f11d08c3SAxel Lin 2544f11d08c3SAxel Lin return DIV_ROUND_UP(abs(new_volt - old_volt), ramp_delay); 254598a175b6SYadwinder Singh Brar } 2546b19dbf71SMark Brown EXPORT_SYMBOL_GPL(regulator_set_voltage_time_sel); 254798a175b6SYadwinder Singh Brar 254898a175b6SYadwinder Singh Brar /** 2549606a2562SMark Brown * regulator_sync_voltage - re-apply last regulator output voltage 2550606a2562SMark Brown * @regulator: regulator source 2551606a2562SMark Brown * 2552606a2562SMark Brown * Re-apply the last configured voltage. This is intended to be used 2553606a2562SMark Brown * where some external control source the consumer is cooperating with 2554606a2562SMark Brown * has caused the configured voltage to change. 2555606a2562SMark Brown */ 2556606a2562SMark Brown int regulator_sync_voltage(struct regulator *regulator) 2557606a2562SMark Brown { 2558606a2562SMark Brown struct regulator_dev *rdev = regulator->rdev; 2559606a2562SMark Brown int ret, min_uV, max_uV; 2560606a2562SMark Brown 2561606a2562SMark Brown mutex_lock(&rdev->mutex); 2562606a2562SMark Brown 2563606a2562SMark Brown if (!rdev->desc->ops->set_voltage && 2564606a2562SMark Brown !rdev->desc->ops->set_voltage_sel) { 2565606a2562SMark Brown ret = -EINVAL; 2566606a2562SMark Brown goto out; 2567606a2562SMark Brown } 2568606a2562SMark Brown 2569606a2562SMark Brown /* This is only going to work if we've had a voltage configured. */ 2570606a2562SMark Brown if (!regulator->min_uV && !regulator->max_uV) { 2571606a2562SMark Brown ret = -EINVAL; 2572606a2562SMark Brown goto out; 2573606a2562SMark Brown } 2574606a2562SMark Brown 2575606a2562SMark Brown min_uV = regulator->min_uV; 2576606a2562SMark Brown max_uV = regulator->max_uV; 2577606a2562SMark Brown 2578606a2562SMark Brown /* This should be a paranoia check... */ 2579606a2562SMark Brown ret = regulator_check_voltage(rdev, &min_uV, &max_uV); 2580606a2562SMark Brown if (ret < 0) 2581606a2562SMark Brown goto out; 2582606a2562SMark Brown 2583606a2562SMark Brown ret = regulator_check_consumers(rdev, &min_uV, &max_uV); 2584606a2562SMark Brown if (ret < 0) 2585606a2562SMark Brown goto out; 2586606a2562SMark Brown 2587606a2562SMark Brown ret = _regulator_do_set_voltage(rdev, min_uV, max_uV); 2588606a2562SMark Brown 2589606a2562SMark Brown out: 2590606a2562SMark Brown mutex_unlock(&rdev->mutex); 2591606a2562SMark Brown return ret; 2592606a2562SMark Brown } 2593606a2562SMark Brown EXPORT_SYMBOL_GPL(regulator_sync_voltage); 2594606a2562SMark Brown 2595414c70cbSLiam Girdwood static int _regulator_get_voltage(struct regulator_dev *rdev) 2596414c70cbSLiam Girdwood { 2597bf5892a8SMark Brown int sel, ret; 2598476c2d83SMark Brown 2599476c2d83SMark Brown if (rdev->desc->ops->get_voltage_sel) { 2600476c2d83SMark Brown sel = rdev->desc->ops->get_voltage_sel(rdev); 2601476c2d83SMark Brown if (sel < 0) 2602476c2d83SMark Brown return sel; 2603bf5892a8SMark Brown ret = rdev->desc->ops->list_voltage(rdev, sel); 2604cb220d16SAxel Lin } else if (rdev->desc->ops->get_voltage) { 2605bf5892a8SMark Brown ret = rdev->desc->ops->get_voltage(rdev); 2606f7df20ecSMark Brown } else if (rdev->desc->ops->list_voltage) { 2607f7df20ecSMark Brown ret = rdev->desc->ops->list_voltage(rdev, 0); 26085a523605SLaxman Dewangan } else if (rdev->desc->fixed_uV && (rdev->desc->n_voltages == 1)) { 26095a523605SLaxman Dewangan ret = rdev->desc->fixed_uV; 2610cb220d16SAxel Lin } else { 2611414c70cbSLiam Girdwood return -EINVAL; 2612cb220d16SAxel Lin } 2613bf5892a8SMark Brown 2614cb220d16SAxel Lin if (ret < 0) 2615cb220d16SAxel Lin return ret; 2616bf5892a8SMark Brown return ret - rdev->constraints->uV_offset; 2617414c70cbSLiam Girdwood } 2618414c70cbSLiam Girdwood 2619414c70cbSLiam Girdwood /** 2620414c70cbSLiam Girdwood * regulator_get_voltage - get regulator output voltage 2621414c70cbSLiam Girdwood * @regulator: regulator source 2622414c70cbSLiam Girdwood * 2623414c70cbSLiam Girdwood * This returns the current regulator voltage in uV. 2624414c70cbSLiam Girdwood * 2625414c70cbSLiam Girdwood * NOTE: If the regulator is disabled it will return the voltage value. This 2626414c70cbSLiam Girdwood * function should not be used to determine regulator state. 2627414c70cbSLiam Girdwood */ 2628414c70cbSLiam Girdwood int regulator_get_voltage(struct regulator *regulator) 2629414c70cbSLiam Girdwood { 2630414c70cbSLiam Girdwood int ret; 2631414c70cbSLiam Girdwood 2632414c70cbSLiam Girdwood mutex_lock(®ulator->rdev->mutex); 2633414c70cbSLiam Girdwood 2634414c70cbSLiam Girdwood ret = _regulator_get_voltage(regulator->rdev); 2635414c70cbSLiam Girdwood 2636414c70cbSLiam Girdwood mutex_unlock(®ulator->rdev->mutex); 2637414c70cbSLiam Girdwood 2638414c70cbSLiam Girdwood return ret; 2639414c70cbSLiam Girdwood } 2640414c70cbSLiam Girdwood EXPORT_SYMBOL_GPL(regulator_get_voltage); 2641414c70cbSLiam Girdwood 2642414c70cbSLiam Girdwood /** 2643414c70cbSLiam Girdwood * regulator_set_current_limit - set regulator output current limit 2644414c70cbSLiam Girdwood * @regulator: regulator source 2645ce0d10f8SCharles Keepax * @min_uA: Minimum supported current in uA 2646414c70cbSLiam Girdwood * @max_uA: Maximum supported current in uA 2647414c70cbSLiam Girdwood * 2648414c70cbSLiam Girdwood * Sets current sink to the desired output current. This can be set during 2649414c70cbSLiam Girdwood * any regulator state. IOW, regulator can be disabled or enabled. 2650414c70cbSLiam Girdwood * 2651414c70cbSLiam Girdwood * If the regulator is enabled then the current will change to the new value 2652414c70cbSLiam Girdwood * immediately otherwise if the regulator is disabled the regulator will 2653414c70cbSLiam Girdwood * output at the new current when enabled. 2654414c70cbSLiam Girdwood * 2655414c70cbSLiam Girdwood * NOTE: Regulator system constraints must be set for this regulator before 2656414c70cbSLiam Girdwood * calling this function otherwise this call will fail. 2657414c70cbSLiam Girdwood */ 2658414c70cbSLiam Girdwood int regulator_set_current_limit(struct regulator *regulator, 2659414c70cbSLiam Girdwood int min_uA, int max_uA) 2660414c70cbSLiam Girdwood { 2661414c70cbSLiam Girdwood struct regulator_dev *rdev = regulator->rdev; 2662414c70cbSLiam Girdwood int ret; 2663414c70cbSLiam Girdwood 2664414c70cbSLiam Girdwood mutex_lock(&rdev->mutex); 2665414c70cbSLiam Girdwood 2666414c70cbSLiam Girdwood /* sanity check */ 2667414c70cbSLiam Girdwood if (!rdev->desc->ops->set_current_limit) { 2668414c70cbSLiam Girdwood ret = -EINVAL; 2669414c70cbSLiam Girdwood goto out; 2670414c70cbSLiam Girdwood } 2671414c70cbSLiam Girdwood 2672414c70cbSLiam Girdwood /* constraints check */ 2673414c70cbSLiam Girdwood ret = regulator_check_current_limit(rdev, &min_uA, &max_uA); 2674414c70cbSLiam Girdwood if (ret < 0) 2675414c70cbSLiam Girdwood goto out; 2676414c70cbSLiam Girdwood 2677414c70cbSLiam Girdwood ret = rdev->desc->ops->set_current_limit(rdev, min_uA, max_uA); 2678414c70cbSLiam Girdwood out: 2679414c70cbSLiam Girdwood mutex_unlock(&rdev->mutex); 2680414c70cbSLiam Girdwood return ret; 2681414c70cbSLiam Girdwood } 2682414c70cbSLiam Girdwood EXPORT_SYMBOL_GPL(regulator_set_current_limit); 2683414c70cbSLiam Girdwood 2684414c70cbSLiam Girdwood static int _regulator_get_current_limit(struct regulator_dev *rdev) 2685414c70cbSLiam Girdwood { 2686414c70cbSLiam Girdwood int ret; 2687414c70cbSLiam Girdwood 2688414c70cbSLiam Girdwood mutex_lock(&rdev->mutex); 2689414c70cbSLiam Girdwood 2690414c70cbSLiam Girdwood /* sanity check */ 2691414c70cbSLiam Girdwood if (!rdev->desc->ops->get_current_limit) { 2692414c70cbSLiam Girdwood ret = -EINVAL; 2693414c70cbSLiam Girdwood goto out; 2694414c70cbSLiam Girdwood } 2695414c70cbSLiam Girdwood 2696414c70cbSLiam Girdwood ret = rdev->desc->ops->get_current_limit(rdev); 2697414c70cbSLiam Girdwood out: 2698414c70cbSLiam Girdwood mutex_unlock(&rdev->mutex); 2699414c70cbSLiam Girdwood return ret; 2700414c70cbSLiam Girdwood } 2701414c70cbSLiam Girdwood 2702414c70cbSLiam Girdwood /** 2703414c70cbSLiam Girdwood * regulator_get_current_limit - get regulator output current 2704414c70cbSLiam Girdwood * @regulator: regulator source 2705414c70cbSLiam Girdwood * 2706414c70cbSLiam Girdwood * This returns the current supplied by the specified current sink in uA. 2707414c70cbSLiam Girdwood * 2708414c70cbSLiam Girdwood * NOTE: If the regulator is disabled it will return the current value. This 2709414c70cbSLiam Girdwood * function should not be used to determine regulator state. 2710414c70cbSLiam Girdwood */ 2711414c70cbSLiam Girdwood int regulator_get_current_limit(struct regulator *regulator) 2712414c70cbSLiam Girdwood { 2713414c70cbSLiam Girdwood return _regulator_get_current_limit(regulator->rdev); 2714414c70cbSLiam Girdwood } 2715414c70cbSLiam Girdwood EXPORT_SYMBOL_GPL(regulator_get_current_limit); 2716414c70cbSLiam Girdwood 2717414c70cbSLiam Girdwood /** 2718414c70cbSLiam Girdwood * regulator_set_mode - set regulator operating mode 2719414c70cbSLiam Girdwood * @regulator: regulator source 2720414c70cbSLiam Girdwood * @mode: operating mode - one of the REGULATOR_MODE constants 2721414c70cbSLiam Girdwood * 2722414c70cbSLiam Girdwood * Set regulator operating mode to increase regulator efficiency or improve 2723414c70cbSLiam Girdwood * regulation performance. 2724414c70cbSLiam Girdwood * 2725414c70cbSLiam Girdwood * NOTE: Regulator system constraints must be set for this regulator before 2726414c70cbSLiam Girdwood * calling this function otherwise this call will fail. 2727414c70cbSLiam Girdwood */ 2728414c70cbSLiam Girdwood int regulator_set_mode(struct regulator *regulator, unsigned int mode) 2729414c70cbSLiam Girdwood { 2730414c70cbSLiam Girdwood struct regulator_dev *rdev = regulator->rdev; 2731414c70cbSLiam Girdwood int ret; 2732500b4ac9SSundar R Iyer int regulator_curr_mode; 2733414c70cbSLiam Girdwood 2734414c70cbSLiam Girdwood mutex_lock(&rdev->mutex); 2735414c70cbSLiam Girdwood 2736414c70cbSLiam Girdwood /* sanity check */ 2737414c70cbSLiam Girdwood if (!rdev->desc->ops->set_mode) { 2738414c70cbSLiam Girdwood ret = -EINVAL; 2739414c70cbSLiam Girdwood goto out; 2740414c70cbSLiam Girdwood } 2741414c70cbSLiam Girdwood 2742500b4ac9SSundar R Iyer /* return if the same mode is requested */ 2743500b4ac9SSundar R Iyer if (rdev->desc->ops->get_mode) { 2744500b4ac9SSundar R Iyer regulator_curr_mode = rdev->desc->ops->get_mode(rdev); 2745500b4ac9SSundar R Iyer if (regulator_curr_mode == mode) { 2746500b4ac9SSundar R Iyer ret = 0; 2747500b4ac9SSundar R Iyer goto out; 2748500b4ac9SSundar R Iyer } 2749500b4ac9SSundar R Iyer } 2750500b4ac9SSundar R Iyer 2751414c70cbSLiam Girdwood /* constraints check */ 275222c51b47SAxel Lin ret = regulator_mode_constrain(rdev, &mode); 2753414c70cbSLiam Girdwood if (ret < 0) 2754414c70cbSLiam Girdwood goto out; 2755414c70cbSLiam Girdwood 2756414c70cbSLiam Girdwood ret = rdev->desc->ops->set_mode(rdev, mode); 2757414c70cbSLiam Girdwood out: 2758414c70cbSLiam Girdwood mutex_unlock(&rdev->mutex); 2759414c70cbSLiam Girdwood return ret; 2760414c70cbSLiam Girdwood } 2761414c70cbSLiam Girdwood EXPORT_SYMBOL_GPL(regulator_set_mode); 2762414c70cbSLiam Girdwood 2763414c70cbSLiam Girdwood static unsigned int _regulator_get_mode(struct regulator_dev *rdev) 2764414c70cbSLiam Girdwood { 2765414c70cbSLiam Girdwood int ret; 2766414c70cbSLiam Girdwood 2767414c70cbSLiam Girdwood mutex_lock(&rdev->mutex); 2768414c70cbSLiam Girdwood 2769414c70cbSLiam Girdwood /* sanity check */ 2770414c70cbSLiam Girdwood if (!rdev->desc->ops->get_mode) { 2771414c70cbSLiam Girdwood ret = -EINVAL; 2772414c70cbSLiam Girdwood goto out; 2773414c70cbSLiam Girdwood } 2774414c70cbSLiam Girdwood 2775414c70cbSLiam Girdwood ret = rdev->desc->ops->get_mode(rdev); 2776414c70cbSLiam Girdwood out: 2777414c70cbSLiam Girdwood mutex_unlock(&rdev->mutex); 2778414c70cbSLiam Girdwood return ret; 2779414c70cbSLiam Girdwood } 2780414c70cbSLiam Girdwood 2781414c70cbSLiam Girdwood /** 2782414c70cbSLiam Girdwood * regulator_get_mode - get regulator operating mode 2783414c70cbSLiam Girdwood * @regulator: regulator source 2784414c70cbSLiam Girdwood * 2785414c70cbSLiam Girdwood * Get the current regulator operating mode. 2786414c70cbSLiam Girdwood */ 2787414c70cbSLiam Girdwood unsigned int regulator_get_mode(struct regulator *regulator) 2788414c70cbSLiam Girdwood { 2789414c70cbSLiam Girdwood return _regulator_get_mode(regulator->rdev); 2790414c70cbSLiam Girdwood } 2791414c70cbSLiam Girdwood EXPORT_SYMBOL_GPL(regulator_get_mode); 2792414c70cbSLiam Girdwood 2793414c70cbSLiam Girdwood /** 2794414c70cbSLiam Girdwood * regulator_set_optimum_mode - set regulator optimum operating mode 2795414c70cbSLiam Girdwood * @regulator: regulator source 2796414c70cbSLiam Girdwood * @uA_load: load current 2797414c70cbSLiam Girdwood * 2798414c70cbSLiam Girdwood * Notifies the regulator core of a new device load. This is then used by 2799414c70cbSLiam Girdwood * DRMS (if enabled by constraints) to set the most efficient regulator 2800414c70cbSLiam Girdwood * operating mode for the new regulator loading. 2801414c70cbSLiam Girdwood * 2802414c70cbSLiam Girdwood * Consumer devices notify their supply regulator of the maximum power 2803414c70cbSLiam Girdwood * they will require (can be taken from device datasheet in the power 2804414c70cbSLiam Girdwood * consumption tables) when they change operational status and hence power 2805414c70cbSLiam Girdwood * state. Examples of operational state changes that can affect power 2806414c70cbSLiam Girdwood * consumption are :- 2807414c70cbSLiam Girdwood * 2808414c70cbSLiam Girdwood * o Device is opened / closed. 2809414c70cbSLiam Girdwood * o Device I/O is about to begin or has just finished. 2810414c70cbSLiam Girdwood * o Device is idling in between work. 2811414c70cbSLiam Girdwood * 2812414c70cbSLiam Girdwood * This information is also exported via sysfs to userspace. 2813414c70cbSLiam Girdwood * 2814414c70cbSLiam Girdwood * DRMS will sum the total requested load on the regulator and change 2815414c70cbSLiam Girdwood * to the most efficient operating mode if platform constraints allow. 2816414c70cbSLiam Girdwood * 2817414c70cbSLiam Girdwood * Returns the new regulator mode or error. 2818414c70cbSLiam Girdwood */ 2819414c70cbSLiam Girdwood int regulator_set_optimum_mode(struct regulator *regulator, int uA_load) 2820414c70cbSLiam Girdwood { 2821414c70cbSLiam Girdwood struct regulator_dev *rdev = regulator->rdev; 2822414c70cbSLiam Girdwood struct regulator *consumer; 2823d92d95b6SStephen Boyd int ret, output_uV, input_uV = 0, total_uA_load = 0; 2824414c70cbSLiam Girdwood unsigned int mode; 2825414c70cbSLiam Girdwood 2826d92d95b6SStephen Boyd if (rdev->supply) 2827d92d95b6SStephen Boyd input_uV = regulator_get_voltage(rdev->supply); 2828d92d95b6SStephen Boyd 2829414c70cbSLiam Girdwood mutex_lock(&rdev->mutex); 2830414c70cbSLiam Girdwood 2831a4b41483SMark Brown /* 2832a4b41483SMark Brown * first check to see if we can set modes at all, otherwise just 2833a4b41483SMark Brown * tell the consumer everything is OK. 2834a4b41483SMark Brown */ 2835414c70cbSLiam Girdwood regulator->uA_load = uA_load; 2836414c70cbSLiam Girdwood ret = regulator_check_drms(rdev); 2837a4b41483SMark Brown if (ret < 0) { 2838a4b41483SMark Brown ret = 0; 2839414c70cbSLiam Girdwood goto out; 2840a4b41483SMark Brown } 2841414c70cbSLiam Girdwood 2842414c70cbSLiam Girdwood if (!rdev->desc->ops->get_optimum_mode) 2843414c70cbSLiam Girdwood goto out; 2844414c70cbSLiam Girdwood 2845a4b41483SMark Brown /* 2846a4b41483SMark Brown * we can actually do this so any errors are indicators of 2847a4b41483SMark Brown * potential real failure. 2848a4b41483SMark Brown */ 2849a4b41483SMark Brown ret = -EINVAL; 2850a4b41483SMark Brown 2851854ccbaeSAxel Lin if (!rdev->desc->ops->set_mode) 2852854ccbaeSAxel Lin goto out; 2853854ccbaeSAxel Lin 2854414c70cbSLiam Girdwood /* get output voltage */ 28551bf5a1f8SMark Brown output_uV = _regulator_get_voltage(rdev); 2856414c70cbSLiam Girdwood if (output_uV <= 0) { 28575da84fd9SJoe Perches rdev_err(rdev, "invalid output voltage found\n"); 2858414c70cbSLiam Girdwood goto out; 2859414c70cbSLiam Girdwood } 2860414c70cbSLiam Girdwood 2861d92d95b6SStephen Boyd /* No supply? Use constraint voltage */ 28621bf5a1f8SMark Brown if (input_uV <= 0) 2863414c70cbSLiam Girdwood input_uV = rdev->constraints->input_uV; 2864414c70cbSLiam Girdwood if (input_uV <= 0) { 28655da84fd9SJoe Perches rdev_err(rdev, "invalid input voltage found\n"); 2866414c70cbSLiam Girdwood goto out; 2867414c70cbSLiam Girdwood } 2868414c70cbSLiam Girdwood 2869414c70cbSLiam Girdwood /* calc total requested load for this regulator */ 2870414c70cbSLiam Girdwood list_for_each_entry(consumer, &rdev->consumer_list, list) 2871414c70cbSLiam Girdwood total_uA_load += consumer->uA_load; 2872414c70cbSLiam Girdwood 2873414c70cbSLiam Girdwood mode = rdev->desc->ops->get_optimum_mode(rdev, 2874414c70cbSLiam Girdwood input_uV, output_uV, 2875414c70cbSLiam Girdwood total_uA_load); 28762c608234SMark Brown ret = regulator_mode_constrain(rdev, &mode); 2877e573520bSDavid Brownell if (ret < 0) { 28785da84fd9SJoe Perches rdev_err(rdev, "failed to get optimum mode @ %d uA %d -> %d uV\n", 2879414c70cbSLiam Girdwood total_uA_load, input_uV, output_uV); 2880414c70cbSLiam Girdwood goto out; 2881414c70cbSLiam Girdwood } 2882414c70cbSLiam Girdwood 2883414c70cbSLiam Girdwood ret = rdev->desc->ops->set_mode(rdev, mode); 2884e573520bSDavid Brownell if (ret < 0) { 28855da84fd9SJoe Perches rdev_err(rdev, "failed to set optimum mode %x\n", mode); 2886414c70cbSLiam Girdwood goto out; 2887414c70cbSLiam Girdwood } 2888414c70cbSLiam Girdwood ret = mode; 2889414c70cbSLiam Girdwood out: 2890414c70cbSLiam Girdwood mutex_unlock(&rdev->mutex); 2891414c70cbSLiam Girdwood return ret; 2892414c70cbSLiam Girdwood } 2893414c70cbSLiam Girdwood EXPORT_SYMBOL_GPL(regulator_set_optimum_mode); 2894414c70cbSLiam Girdwood 2895414c70cbSLiam Girdwood /** 2896f59c8f9fSMark Brown * regulator_allow_bypass - allow the regulator to go into bypass mode 2897f59c8f9fSMark Brown * 2898f59c8f9fSMark Brown * @regulator: Regulator to configure 28999345dfb8SNishanth Menon * @enable: enable or disable bypass mode 2900f59c8f9fSMark Brown * 2901f59c8f9fSMark Brown * Allow the regulator to go into bypass mode if all other consumers 2902f59c8f9fSMark Brown * for the regulator also enable bypass mode and the machine 2903f59c8f9fSMark Brown * constraints allow this. Bypass mode means that the regulator is 2904f59c8f9fSMark Brown * simply passing the input directly to the output with no regulation. 2905f59c8f9fSMark Brown */ 2906f59c8f9fSMark Brown int regulator_allow_bypass(struct regulator *regulator, bool enable) 2907f59c8f9fSMark Brown { 2908f59c8f9fSMark Brown struct regulator_dev *rdev = regulator->rdev; 2909f59c8f9fSMark Brown int ret = 0; 2910f59c8f9fSMark Brown 2911f59c8f9fSMark Brown if (!rdev->desc->ops->set_bypass) 2912f59c8f9fSMark Brown return 0; 2913f59c8f9fSMark Brown 2914f59c8f9fSMark Brown if (rdev->constraints && 2915f59c8f9fSMark Brown !(rdev->constraints->valid_ops_mask & REGULATOR_CHANGE_BYPASS)) 2916f59c8f9fSMark Brown return 0; 2917f59c8f9fSMark Brown 2918f59c8f9fSMark Brown mutex_lock(&rdev->mutex); 2919f59c8f9fSMark Brown 2920f59c8f9fSMark Brown if (enable && !regulator->bypass) { 2921f59c8f9fSMark Brown rdev->bypass_count++; 2922f59c8f9fSMark Brown 2923f59c8f9fSMark Brown if (rdev->bypass_count == rdev->open_count) { 2924f59c8f9fSMark Brown ret = rdev->desc->ops->set_bypass(rdev, enable); 2925f59c8f9fSMark Brown if (ret != 0) 2926f59c8f9fSMark Brown rdev->bypass_count--; 2927f59c8f9fSMark Brown } 2928f59c8f9fSMark Brown 2929f59c8f9fSMark Brown } else if (!enable && regulator->bypass) { 2930f59c8f9fSMark Brown rdev->bypass_count--; 2931f59c8f9fSMark Brown 2932f59c8f9fSMark Brown if (rdev->bypass_count != rdev->open_count) { 2933f59c8f9fSMark Brown ret = rdev->desc->ops->set_bypass(rdev, enable); 2934f59c8f9fSMark Brown if (ret != 0) 2935f59c8f9fSMark Brown rdev->bypass_count++; 2936f59c8f9fSMark Brown } 2937f59c8f9fSMark Brown } 2938f59c8f9fSMark Brown 2939f59c8f9fSMark Brown if (ret == 0) 2940f59c8f9fSMark Brown regulator->bypass = enable; 2941f59c8f9fSMark Brown 2942f59c8f9fSMark Brown mutex_unlock(&rdev->mutex); 2943f59c8f9fSMark Brown 2944f59c8f9fSMark Brown return ret; 2945f59c8f9fSMark Brown } 2946f59c8f9fSMark Brown EXPORT_SYMBOL_GPL(regulator_allow_bypass); 2947f59c8f9fSMark Brown 2948f59c8f9fSMark Brown /** 2949414c70cbSLiam Girdwood * regulator_register_notifier - register regulator event notifier 2950414c70cbSLiam Girdwood * @regulator: regulator source 295169279fb9SMark Brown * @nb: notifier block 2952414c70cbSLiam Girdwood * 2953414c70cbSLiam Girdwood * Register notifier block to receive regulator events. 2954414c70cbSLiam Girdwood */ 2955414c70cbSLiam Girdwood int regulator_register_notifier(struct regulator *regulator, 2956414c70cbSLiam Girdwood struct notifier_block *nb) 2957414c70cbSLiam Girdwood { 2958414c70cbSLiam Girdwood return blocking_notifier_chain_register(®ulator->rdev->notifier, 2959414c70cbSLiam Girdwood nb); 2960414c70cbSLiam Girdwood } 2961414c70cbSLiam Girdwood EXPORT_SYMBOL_GPL(regulator_register_notifier); 2962414c70cbSLiam Girdwood 2963414c70cbSLiam Girdwood /** 2964414c70cbSLiam Girdwood * regulator_unregister_notifier - unregister regulator event notifier 2965414c70cbSLiam Girdwood * @regulator: regulator source 296669279fb9SMark Brown * @nb: notifier block 2967414c70cbSLiam Girdwood * 2968414c70cbSLiam Girdwood * Unregister regulator event notifier block. 2969414c70cbSLiam Girdwood */ 2970414c70cbSLiam Girdwood int regulator_unregister_notifier(struct regulator *regulator, 2971414c70cbSLiam Girdwood struct notifier_block *nb) 2972414c70cbSLiam Girdwood { 2973414c70cbSLiam Girdwood return blocking_notifier_chain_unregister(®ulator->rdev->notifier, 2974414c70cbSLiam Girdwood nb); 2975414c70cbSLiam Girdwood } 2976414c70cbSLiam Girdwood EXPORT_SYMBOL_GPL(regulator_unregister_notifier); 2977414c70cbSLiam Girdwood 2978b136fb44SJonathan Cameron /* notify regulator consumers and downstream regulator consumers. 2979b136fb44SJonathan Cameron * Note mutex must be held by caller. 2980b136fb44SJonathan Cameron */ 2981414c70cbSLiam Girdwood static void _notifier_call_chain(struct regulator_dev *rdev, 2982414c70cbSLiam Girdwood unsigned long event, void *data) 2983414c70cbSLiam Girdwood { 2984414c70cbSLiam Girdwood /* call rdev chain first */ 2985d8493d21SMark Brown blocking_notifier_call_chain(&rdev->notifier, event, data); 2986414c70cbSLiam Girdwood } 2987414c70cbSLiam Girdwood 2988414c70cbSLiam Girdwood /** 2989414c70cbSLiam Girdwood * regulator_bulk_get - get multiple regulator consumers 2990414c70cbSLiam Girdwood * 2991414c70cbSLiam Girdwood * @dev: Device to supply 2992414c70cbSLiam Girdwood * @num_consumers: Number of consumers to register 2993414c70cbSLiam Girdwood * @consumers: Configuration of consumers; clients are stored here. 2994414c70cbSLiam Girdwood * 2995414c70cbSLiam Girdwood * @return 0 on success, an errno on failure. 2996414c70cbSLiam Girdwood * 2997414c70cbSLiam Girdwood * This helper function allows drivers to get several regulator 2998414c70cbSLiam Girdwood * consumers in one operation. If any of the regulators cannot be 2999414c70cbSLiam Girdwood * acquired then any regulators that were allocated will be freed 3000414c70cbSLiam Girdwood * before returning to the caller. 3001414c70cbSLiam Girdwood */ 3002414c70cbSLiam Girdwood int regulator_bulk_get(struct device *dev, int num_consumers, 3003414c70cbSLiam Girdwood struct regulator_bulk_data *consumers) 3004414c70cbSLiam Girdwood { 3005414c70cbSLiam Girdwood int i; 3006414c70cbSLiam Girdwood int ret; 3007414c70cbSLiam Girdwood 3008414c70cbSLiam Girdwood for (i = 0; i < num_consumers; i++) 3009414c70cbSLiam Girdwood consumers[i].consumer = NULL; 3010414c70cbSLiam Girdwood 3011414c70cbSLiam Girdwood for (i = 0; i < num_consumers; i++) { 3012414c70cbSLiam Girdwood consumers[i].consumer = regulator_get(dev, 3013414c70cbSLiam Girdwood consumers[i].supply); 3014414c70cbSLiam Girdwood if (IS_ERR(consumers[i].consumer)) { 3015414c70cbSLiam Girdwood ret = PTR_ERR(consumers[i].consumer); 30165b307627SMark Brown dev_err(dev, "Failed to get supply '%s': %d\n", 30175b307627SMark Brown consumers[i].supply, ret); 3018414c70cbSLiam Girdwood consumers[i].consumer = NULL; 3019414c70cbSLiam Girdwood goto err; 3020414c70cbSLiam Girdwood } 3021414c70cbSLiam Girdwood } 3022414c70cbSLiam Girdwood 3023414c70cbSLiam Girdwood return 0; 3024414c70cbSLiam Girdwood 3025414c70cbSLiam Girdwood err: 3026b29c7690SAxel Lin while (--i >= 0) 3027414c70cbSLiam Girdwood regulator_put(consumers[i].consumer); 3028414c70cbSLiam Girdwood 3029414c70cbSLiam Girdwood return ret; 3030414c70cbSLiam Girdwood } 3031414c70cbSLiam Girdwood EXPORT_SYMBOL_GPL(regulator_bulk_get); 3032414c70cbSLiam Girdwood 3033f21e0e81SMark Brown static void regulator_bulk_enable_async(void *data, async_cookie_t cookie) 3034f21e0e81SMark Brown { 3035f21e0e81SMark Brown struct regulator_bulk_data *bulk = data; 3036f21e0e81SMark Brown 3037f21e0e81SMark Brown bulk->ret = regulator_enable(bulk->consumer); 3038f21e0e81SMark Brown } 3039f21e0e81SMark Brown 3040414c70cbSLiam Girdwood /** 3041414c70cbSLiam Girdwood * regulator_bulk_enable - enable multiple regulator consumers 3042414c70cbSLiam Girdwood * 3043414c70cbSLiam Girdwood * @num_consumers: Number of consumers 3044414c70cbSLiam Girdwood * @consumers: Consumer data; clients are stored here. 3045414c70cbSLiam Girdwood * @return 0 on success, an errno on failure 3046414c70cbSLiam Girdwood * 3047414c70cbSLiam Girdwood * This convenience API allows consumers to enable multiple regulator 3048414c70cbSLiam Girdwood * clients in a single API call. If any consumers cannot be enabled 3049414c70cbSLiam Girdwood * then any others that were enabled will be disabled again prior to 3050414c70cbSLiam Girdwood * return. 3051414c70cbSLiam Girdwood */ 3052414c70cbSLiam Girdwood int regulator_bulk_enable(int num_consumers, 3053414c70cbSLiam Girdwood struct regulator_bulk_data *consumers) 3054414c70cbSLiam Girdwood { 30552955b47dSDan Williams ASYNC_DOMAIN_EXCLUSIVE(async_domain); 3056414c70cbSLiam Girdwood int i; 3057f21e0e81SMark Brown int ret = 0; 3058414c70cbSLiam Girdwood 30596492bc1bSMark Brown for (i = 0; i < num_consumers; i++) { 30606492bc1bSMark Brown if (consumers[i].consumer->always_on) 30616492bc1bSMark Brown consumers[i].ret = 0; 30626492bc1bSMark Brown else 3063f21e0e81SMark Brown async_schedule_domain(regulator_bulk_enable_async, 3064f21e0e81SMark Brown &consumers[i], &async_domain); 30656492bc1bSMark Brown } 3066f21e0e81SMark Brown 3067f21e0e81SMark Brown async_synchronize_full_domain(&async_domain); 3068f21e0e81SMark Brown 3069f21e0e81SMark Brown /* If any consumer failed we need to unwind any that succeeded */ 3070414c70cbSLiam Girdwood for (i = 0; i < num_consumers; i++) { 3071f21e0e81SMark Brown if (consumers[i].ret != 0) { 3072f21e0e81SMark Brown ret = consumers[i].ret; 3073414c70cbSLiam Girdwood goto err; 3074414c70cbSLiam Girdwood } 3075f21e0e81SMark Brown } 3076414c70cbSLiam Girdwood 3077414c70cbSLiam Girdwood return 0; 3078414c70cbSLiam Girdwood 3079414c70cbSLiam Girdwood err: 3080fbe31057SAndrzej Hajda for (i = 0; i < num_consumers; i++) { 3081fbe31057SAndrzej Hajda if (consumers[i].ret < 0) 3082fbe31057SAndrzej Hajda pr_err("Failed to enable %s: %d\n", consumers[i].supply, 3083fbe31057SAndrzej Hajda consumers[i].ret); 3084fbe31057SAndrzej Hajda else 3085414c70cbSLiam Girdwood regulator_disable(consumers[i].consumer); 3086fbe31057SAndrzej Hajda } 3087414c70cbSLiam Girdwood 3088414c70cbSLiam Girdwood return ret; 3089414c70cbSLiam Girdwood } 3090414c70cbSLiam Girdwood EXPORT_SYMBOL_GPL(regulator_bulk_enable); 3091414c70cbSLiam Girdwood 3092414c70cbSLiam Girdwood /** 3093414c70cbSLiam Girdwood * regulator_bulk_disable - disable multiple regulator consumers 3094414c70cbSLiam Girdwood * 3095414c70cbSLiam Girdwood * @num_consumers: Number of consumers 3096414c70cbSLiam Girdwood * @consumers: Consumer data; clients are stored here. 3097414c70cbSLiam Girdwood * @return 0 on success, an errno on failure 3098414c70cbSLiam Girdwood * 3099414c70cbSLiam Girdwood * This convenience API allows consumers to disable multiple regulator 310049e22632SSylwester Nawrocki * clients in a single API call. If any consumers cannot be disabled 310149e22632SSylwester Nawrocki * then any others that were disabled will be enabled again prior to 3102414c70cbSLiam Girdwood * return. 3103414c70cbSLiam Girdwood */ 3104414c70cbSLiam Girdwood int regulator_bulk_disable(int num_consumers, 3105414c70cbSLiam Girdwood struct regulator_bulk_data *consumers) 3106414c70cbSLiam Girdwood { 3107414c70cbSLiam Girdwood int i; 310801e86f49SMark Brown int ret, r; 3109414c70cbSLiam Girdwood 311049e22632SSylwester Nawrocki for (i = num_consumers - 1; i >= 0; --i) { 3111414c70cbSLiam Girdwood ret = regulator_disable(consumers[i].consumer); 3112414c70cbSLiam Girdwood if (ret != 0) 3113414c70cbSLiam Girdwood goto err; 3114414c70cbSLiam Girdwood } 3115414c70cbSLiam Girdwood 3116414c70cbSLiam Girdwood return 0; 3117414c70cbSLiam Girdwood 3118414c70cbSLiam Girdwood err: 31195da84fd9SJoe Perches pr_err("Failed to disable %s: %d\n", consumers[i].supply, ret); 312001e86f49SMark Brown for (++i; i < num_consumers; ++i) { 312101e86f49SMark Brown r = regulator_enable(consumers[i].consumer); 312201e86f49SMark Brown if (r != 0) 312301e86f49SMark Brown pr_err("Failed to reename %s: %d\n", 312401e86f49SMark Brown consumers[i].supply, r); 312501e86f49SMark Brown } 3126414c70cbSLiam Girdwood 3127414c70cbSLiam Girdwood return ret; 3128414c70cbSLiam Girdwood } 3129414c70cbSLiam Girdwood EXPORT_SYMBOL_GPL(regulator_bulk_disable); 3130414c70cbSLiam Girdwood 3131414c70cbSLiam Girdwood /** 3132e1de2f42SDonggeun Kim * regulator_bulk_force_disable - force disable multiple regulator consumers 3133e1de2f42SDonggeun Kim * 3134e1de2f42SDonggeun Kim * @num_consumers: Number of consumers 3135e1de2f42SDonggeun Kim * @consumers: Consumer data; clients are stored here. 3136e1de2f42SDonggeun Kim * @return 0 on success, an errno on failure 3137e1de2f42SDonggeun Kim * 3138e1de2f42SDonggeun Kim * This convenience API allows consumers to forcibly disable multiple regulator 3139e1de2f42SDonggeun Kim * clients in a single API call. 3140e1de2f42SDonggeun Kim * NOTE: This should be used for situations when device damage will 3141e1de2f42SDonggeun Kim * likely occur if the regulators are not disabled (e.g. over temp). 3142e1de2f42SDonggeun Kim * Although regulator_force_disable function call for some consumers can 3143e1de2f42SDonggeun Kim * return error numbers, the function is called for all consumers. 3144e1de2f42SDonggeun Kim */ 3145e1de2f42SDonggeun Kim int regulator_bulk_force_disable(int num_consumers, 3146e1de2f42SDonggeun Kim struct regulator_bulk_data *consumers) 3147e1de2f42SDonggeun Kim { 3148e1de2f42SDonggeun Kim int i; 3149e1de2f42SDonggeun Kim int ret; 3150e1de2f42SDonggeun Kim 3151e1de2f42SDonggeun Kim for (i = 0; i < num_consumers; i++) 3152e1de2f42SDonggeun Kim consumers[i].ret = 3153e1de2f42SDonggeun Kim regulator_force_disable(consumers[i].consumer); 3154e1de2f42SDonggeun Kim 3155e1de2f42SDonggeun Kim for (i = 0; i < num_consumers; i++) { 3156e1de2f42SDonggeun Kim if (consumers[i].ret != 0) { 3157e1de2f42SDonggeun Kim ret = consumers[i].ret; 3158e1de2f42SDonggeun Kim goto out; 3159e1de2f42SDonggeun Kim } 3160e1de2f42SDonggeun Kim } 3161e1de2f42SDonggeun Kim 3162e1de2f42SDonggeun Kim return 0; 3163e1de2f42SDonggeun Kim out: 3164e1de2f42SDonggeun Kim return ret; 3165e1de2f42SDonggeun Kim } 3166e1de2f42SDonggeun Kim EXPORT_SYMBOL_GPL(regulator_bulk_force_disable); 3167e1de2f42SDonggeun Kim 3168e1de2f42SDonggeun Kim /** 3169414c70cbSLiam Girdwood * regulator_bulk_free - free multiple regulator consumers 3170414c70cbSLiam Girdwood * 3171414c70cbSLiam Girdwood * @num_consumers: Number of consumers 3172414c70cbSLiam Girdwood * @consumers: Consumer data; clients are stored here. 3173414c70cbSLiam Girdwood * 3174414c70cbSLiam Girdwood * This convenience API allows consumers to free multiple regulator 3175414c70cbSLiam Girdwood * clients in a single API call. 3176414c70cbSLiam Girdwood */ 3177414c70cbSLiam Girdwood void regulator_bulk_free(int num_consumers, 3178414c70cbSLiam Girdwood struct regulator_bulk_data *consumers) 3179414c70cbSLiam Girdwood { 3180414c70cbSLiam Girdwood int i; 3181414c70cbSLiam Girdwood 3182414c70cbSLiam Girdwood for (i = 0; i < num_consumers; i++) { 3183414c70cbSLiam Girdwood regulator_put(consumers[i].consumer); 3184414c70cbSLiam Girdwood consumers[i].consumer = NULL; 3185414c70cbSLiam Girdwood } 3186414c70cbSLiam Girdwood } 3187414c70cbSLiam Girdwood EXPORT_SYMBOL_GPL(regulator_bulk_free); 3188414c70cbSLiam Girdwood 3189414c70cbSLiam Girdwood /** 3190414c70cbSLiam Girdwood * regulator_notifier_call_chain - call regulator event notifier 319169279fb9SMark Brown * @rdev: regulator source 3192414c70cbSLiam Girdwood * @event: notifier block 319369279fb9SMark Brown * @data: callback-specific data. 3194414c70cbSLiam Girdwood * 3195414c70cbSLiam Girdwood * Called by regulator drivers to notify clients a regulator event has 3196414c70cbSLiam Girdwood * occurred. We also notify regulator clients downstream. 3197b136fb44SJonathan Cameron * Note lock must be held by caller. 3198414c70cbSLiam Girdwood */ 3199414c70cbSLiam Girdwood int regulator_notifier_call_chain(struct regulator_dev *rdev, 3200414c70cbSLiam Girdwood unsigned long event, void *data) 3201414c70cbSLiam Girdwood { 3202414c70cbSLiam Girdwood _notifier_call_chain(rdev, event, data); 3203414c70cbSLiam Girdwood return NOTIFY_DONE; 3204414c70cbSLiam Girdwood 3205414c70cbSLiam Girdwood } 3206414c70cbSLiam Girdwood EXPORT_SYMBOL_GPL(regulator_notifier_call_chain); 3207414c70cbSLiam Girdwood 3208be721979SMark Brown /** 3209be721979SMark Brown * regulator_mode_to_status - convert a regulator mode into a status 3210be721979SMark Brown * 3211be721979SMark Brown * @mode: Mode to convert 3212be721979SMark Brown * 3213be721979SMark Brown * Convert a regulator mode into a status. 3214be721979SMark Brown */ 3215be721979SMark Brown int regulator_mode_to_status(unsigned int mode) 3216be721979SMark Brown { 3217be721979SMark Brown switch (mode) { 3218be721979SMark Brown case REGULATOR_MODE_FAST: 3219be721979SMark Brown return REGULATOR_STATUS_FAST; 3220be721979SMark Brown case REGULATOR_MODE_NORMAL: 3221be721979SMark Brown return REGULATOR_STATUS_NORMAL; 3222be721979SMark Brown case REGULATOR_MODE_IDLE: 3223be721979SMark Brown return REGULATOR_STATUS_IDLE; 322403ffcf3dSKrystian Garbaciak case REGULATOR_MODE_STANDBY: 3225be721979SMark Brown return REGULATOR_STATUS_STANDBY; 3226be721979SMark Brown default: 32271beaf762SKrystian Garbaciak return REGULATOR_STATUS_UNDEFINED; 3228be721979SMark Brown } 3229be721979SMark Brown } 3230be721979SMark Brown EXPORT_SYMBOL_GPL(regulator_mode_to_status); 3231be721979SMark Brown 32327ad68e2fSDavid Brownell /* 32337ad68e2fSDavid Brownell * To avoid cluttering sysfs (and memory) with useless state, only 32347ad68e2fSDavid Brownell * create attributes that can be meaningfully displayed. 32357ad68e2fSDavid Brownell */ 32367ad68e2fSDavid Brownell static int add_regulator_attributes(struct regulator_dev *rdev) 32377ad68e2fSDavid Brownell { 32387ad68e2fSDavid Brownell struct device *dev = &rdev->dev; 32397ad68e2fSDavid Brownell struct regulator_ops *ops = rdev->desc->ops; 32407ad68e2fSDavid Brownell int status = 0; 32417ad68e2fSDavid Brownell 32427ad68e2fSDavid Brownell /* some attributes need specific methods to be displayed */ 32434c78899bSMark Brown if ((ops->get_voltage && ops->get_voltage(rdev) >= 0) || 3244f2889e65SMark Brown (ops->get_voltage_sel && ops->get_voltage_sel(rdev) >= 0) || 32455a523605SLaxman Dewangan (ops->list_voltage && ops->list_voltage(rdev, 0) >= 0) || 32465a523605SLaxman Dewangan (rdev->desc->fixed_uV && (rdev->desc->n_voltages == 1))) { 32477ad68e2fSDavid Brownell status = device_create_file(dev, &dev_attr_microvolts); 32487ad68e2fSDavid Brownell if (status < 0) 32497ad68e2fSDavid Brownell return status; 32507ad68e2fSDavid Brownell } 32517ad68e2fSDavid Brownell if (ops->get_current_limit) { 32527ad68e2fSDavid Brownell status = device_create_file(dev, &dev_attr_microamps); 32537ad68e2fSDavid Brownell if (status < 0) 32547ad68e2fSDavid Brownell return status; 32557ad68e2fSDavid Brownell } 32567ad68e2fSDavid Brownell if (ops->get_mode) { 32577ad68e2fSDavid Brownell status = device_create_file(dev, &dev_attr_opmode); 32587ad68e2fSDavid Brownell if (status < 0) 32597ad68e2fSDavid Brownell return status; 32607ad68e2fSDavid Brownell } 32617b74d149SKim, Milo if (rdev->ena_pin || ops->is_enabled) { 32627ad68e2fSDavid Brownell status = device_create_file(dev, &dev_attr_state); 32637ad68e2fSDavid Brownell if (status < 0) 32647ad68e2fSDavid Brownell return status; 32657ad68e2fSDavid Brownell } 3266853116a1SDavid Brownell if (ops->get_status) { 3267853116a1SDavid Brownell status = device_create_file(dev, &dev_attr_status); 3268853116a1SDavid Brownell if (status < 0) 3269853116a1SDavid Brownell return status; 3270853116a1SDavid Brownell } 3271f59c8f9fSMark Brown if (ops->get_bypass) { 3272f59c8f9fSMark Brown status = device_create_file(dev, &dev_attr_bypass); 3273f59c8f9fSMark Brown if (status < 0) 3274f59c8f9fSMark Brown return status; 3275f59c8f9fSMark Brown } 32767ad68e2fSDavid Brownell 32777ad68e2fSDavid Brownell /* some attributes are type-specific */ 32787ad68e2fSDavid Brownell if (rdev->desc->type == REGULATOR_CURRENT) { 32797ad68e2fSDavid Brownell status = device_create_file(dev, &dev_attr_requested_microamps); 32807ad68e2fSDavid Brownell if (status < 0) 32817ad68e2fSDavid Brownell return status; 32827ad68e2fSDavid Brownell } 32837ad68e2fSDavid Brownell 32847ad68e2fSDavid Brownell /* all the other attributes exist to support constraints; 32857ad68e2fSDavid Brownell * don't show them if there are no constraints, or if the 32867ad68e2fSDavid Brownell * relevant supporting methods are missing. 32877ad68e2fSDavid Brownell */ 32887ad68e2fSDavid Brownell if (!rdev->constraints) 32897ad68e2fSDavid Brownell return status; 32907ad68e2fSDavid Brownell 32917ad68e2fSDavid Brownell /* constraints need specific supporting methods */ 3292e8eef82bSMark Brown if (ops->set_voltage || ops->set_voltage_sel) { 32937ad68e2fSDavid Brownell status = device_create_file(dev, &dev_attr_min_microvolts); 32947ad68e2fSDavid Brownell if (status < 0) 32957ad68e2fSDavid Brownell return status; 32967ad68e2fSDavid Brownell status = device_create_file(dev, &dev_attr_max_microvolts); 32977ad68e2fSDavid Brownell if (status < 0) 32987ad68e2fSDavid Brownell return status; 32997ad68e2fSDavid Brownell } 33007ad68e2fSDavid Brownell if (ops->set_current_limit) { 33017ad68e2fSDavid Brownell status = device_create_file(dev, &dev_attr_min_microamps); 33027ad68e2fSDavid Brownell if (status < 0) 33037ad68e2fSDavid Brownell return status; 33047ad68e2fSDavid Brownell status = device_create_file(dev, &dev_attr_max_microamps); 33057ad68e2fSDavid Brownell if (status < 0) 33067ad68e2fSDavid Brownell return status; 33077ad68e2fSDavid Brownell } 33087ad68e2fSDavid Brownell 33097ad68e2fSDavid Brownell status = device_create_file(dev, &dev_attr_suspend_standby_state); 33107ad68e2fSDavid Brownell if (status < 0) 33117ad68e2fSDavid Brownell return status; 33127ad68e2fSDavid Brownell status = device_create_file(dev, &dev_attr_suspend_mem_state); 33137ad68e2fSDavid Brownell if (status < 0) 33147ad68e2fSDavid Brownell return status; 33157ad68e2fSDavid Brownell status = device_create_file(dev, &dev_attr_suspend_disk_state); 33167ad68e2fSDavid Brownell if (status < 0) 33177ad68e2fSDavid Brownell return status; 33187ad68e2fSDavid Brownell 33197ad68e2fSDavid Brownell if (ops->set_suspend_voltage) { 33207ad68e2fSDavid Brownell status = device_create_file(dev, 33217ad68e2fSDavid Brownell &dev_attr_suspend_standby_microvolts); 33227ad68e2fSDavid Brownell if (status < 0) 33237ad68e2fSDavid Brownell return status; 33247ad68e2fSDavid Brownell status = device_create_file(dev, 33257ad68e2fSDavid Brownell &dev_attr_suspend_mem_microvolts); 33267ad68e2fSDavid Brownell if (status < 0) 33277ad68e2fSDavid Brownell return status; 33287ad68e2fSDavid Brownell status = device_create_file(dev, 33297ad68e2fSDavid Brownell &dev_attr_suspend_disk_microvolts); 33307ad68e2fSDavid Brownell if (status < 0) 33317ad68e2fSDavid Brownell return status; 33327ad68e2fSDavid Brownell } 33337ad68e2fSDavid Brownell 33347ad68e2fSDavid Brownell if (ops->set_suspend_mode) { 33357ad68e2fSDavid Brownell status = device_create_file(dev, 33367ad68e2fSDavid Brownell &dev_attr_suspend_standby_mode); 33377ad68e2fSDavid Brownell if (status < 0) 33387ad68e2fSDavid Brownell return status; 33397ad68e2fSDavid Brownell status = device_create_file(dev, 33407ad68e2fSDavid Brownell &dev_attr_suspend_mem_mode); 33417ad68e2fSDavid Brownell if (status < 0) 33427ad68e2fSDavid Brownell return status; 33437ad68e2fSDavid Brownell status = device_create_file(dev, 33447ad68e2fSDavid Brownell &dev_attr_suspend_disk_mode); 33457ad68e2fSDavid Brownell if (status < 0) 33467ad68e2fSDavid Brownell return status; 33477ad68e2fSDavid Brownell } 33487ad68e2fSDavid Brownell 33497ad68e2fSDavid Brownell return status; 33507ad68e2fSDavid Brownell } 33517ad68e2fSDavid Brownell 33521130e5b3SMark Brown static void rdev_init_debugfs(struct regulator_dev *rdev) 33531130e5b3SMark Brown { 33541130e5b3SMark Brown rdev->debugfs = debugfs_create_dir(rdev_get_name(rdev), debugfs_root); 335524751434SStephen Boyd if (!rdev->debugfs) { 33561130e5b3SMark Brown rdev_warn(rdev, "Failed to create debugfs directory\n"); 33571130e5b3SMark Brown return; 33581130e5b3SMark Brown } 33591130e5b3SMark Brown 33601130e5b3SMark Brown debugfs_create_u32("use_count", 0444, rdev->debugfs, 33611130e5b3SMark Brown &rdev->use_count); 33621130e5b3SMark Brown debugfs_create_u32("open_count", 0444, rdev->debugfs, 33631130e5b3SMark Brown &rdev->open_count); 3364f59c8f9fSMark Brown debugfs_create_u32("bypass_count", 0444, rdev->debugfs, 3365f59c8f9fSMark Brown &rdev->bypass_count); 33661130e5b3SMark Brown } 33671130e5b3SMark Brown 3368414c70cbSLiam Girdwood /** 3369414c70cbSLiam Girdwood * regulator_register - register regulator 337069279fb9SMark Brown * @regulator_desc: regulator to register 3371c172708dSMark Brown * @config: runtime configuration for regulator 3372414c70cbSLiam Girdwood * 3373414c70cbSLiam Girdwood * Called by regulator drivers to register a regulator. 33740384618aSAxel Lin * Returns a valid pointer to struct regulator_dev on success 33750384618aSAxel Lin * or an ERR_PTR() on error. 3376414c70cbSLiam Girdwood */ 337765f26846SMark Brown struct regulator_dev * 337865f26846SMark Brown regulator_register(const struct regulator_desc *regulator_desc, 3379c172708dSMark Brown const struct regulator_config *config) 3380414c70cbSLiam Girdwood { 33819a8f5e07SMark Brown const struct regulation_constraints *constraints = NULL; 3382c172708dSMark Brown const struct regulator_init_data *init_data; 3383414c70cbSLiam Girdwood static atomic_t regulator_no = ATOMIC_INIT(0); 3384414c70cbSLiam Girdwood struct regulator_dev *rdev; 338532c8fad4SMark Brown struct device *dev; 3386a5766f11SLiam Girdwood int ret, i; 338769511a45SRajendra Nayak const char *supply = NULL; 3388414c70cbSLiam Girdwood 3389c172708dSMark Brown if (regulator_desc == NULL || config == NULL) 3390414c70cbSLiam Girdwood return ERR_PTR(-EINVAL); 3391414c70cbSLiam Girdwood 339232c8fad4SMark Brown dev = config->dev; 3393dcf70112SMark Brown WARN_ON(!dev); 339432c8fad4SMark Brown 3395414c70cbSLiam Girdwood if (regulator_desc->name == NULL || regulator_desc->ops == NULL) 3396414c70cbSLiam Girdwood return ERR_PTR(-EINVAL); 3397414c70cbSLiam Girdwood 3398cd78dfc6SDiego Liziero if (regulator_desc->type != REGULATOR_VOLTAGE && 3399cd78dfc6SDiego Liziero regulator_desc->type != REGULATOR_CURRENT) 3400414c70cbSLiam Girdwood return ERR_PTR(-EINVAL); 3401414c70cbSLiam Girdwood 3402476c2d83SMark Brown /* Only one of each should be implemented */ 3403476c2d83SMark Brown WARN_ON(regulator_desc->ops->get_voltage && 3404476c2d83SMark Brown regulator_desc->ops->get_voltage_sel); 3405e8eef82bSMark Brown WARN_ON(regulator_desc->ops->set_voltage && 3406e8eef82bSMark Brown regulator_desc->ops->set_voltage_sel); 3407476c2d83SMark Brown 3408476c2d83SMark Brown /* If we're using selectors we must implement list_voltage. */ 3409476c2d83SMark Brown if (regulator_desc->ops->get_voltage_sel && 3410476c2d83SMark Brown !regulator_desc->ops->list_voltage) { 3411476c2d83SMark Brown return ERR_PTR(-EINVAL); 3412476c2d83SMark Brown } 3413e8eef82bSMark Brown if (regulator_desc->ops->set_voltage_sel && 3414e8eef82bSMark Brown !regulator_desc->ops->list_voltage) { 3415e8eef82bSMark Brown return ERR_PTR(-EINVAL); 3416e8eef82bSMark Brown } 3417476c2d83SMark Brown 3418c172708dSMark Brown init_data = config->init_data; 3419c172708dSMark Brown 3420414c70cbSLiam Girdwood rdev = kzalloc(sizeof(struct regulator_dev), GFP_KERNEL); 3421414c70cbSLiam Girdwood if (rdev == NULL) 3422414c70cbSLiam Girdwood return ERR_PTR(-ENOMEM); 3423414c70cbSLiam Girdwood 3424414c70cbSLiam Girdwood mutex_lock(®ulator_list_mutex); 3425414c70cbSLiam Girdwood 3426414c70cbSLiam Girdwood mutex_init(&rdev->mutex); 3427c172708dSMark Brown rdev->reg_data = config->driver_data; 3428414c70cbSLiam Girdwood rdev->owner = regulator_desc->owner; 3429414c70cbSLiam Girdwood rdev->desc = regulator_desc; 34303a4b0a07SMark Brown if (config->regmap) 343165b19ce6SMark Brown rdev->regmap = config->regmap; 343252b84dacSAnilKumar Ch else if (dev_get_regmap(dev, NULL)) 34333a4b0a07SMark Brown rdev->regmap = dev_get_regmap(dev, NULL); 343452b84dacSAnilKumar Ch else if (dev->parent) 343552b84dacSAnilKumar Ch rdev->regmap = dev_get_regmap(dev->parent, NULL); 3436414c70cbSLiam Girdwood INIT_LIST_HEAD(&rdev->consumer_list); 3437414c70cbSLiam Girdwood INIT_LIST_HEAD(&rdev->list); 3438414c70cbSLiam Girdwood BLOCKING_INIT_NOTIFIER_HEAD(&rdev->notifier); 3439da07ecd9SMark Brown INIT_DELAYED_WORK(&rdev->disable_work, regulator_disable_work); 3440414c70cbSLiam Girdwood 3441a5766f11SLiam Girdwood /* preform any regulator specific init */ 34429a8f5e07SMark Brown if (init_data && init_data->regulator_init) { 3443a5766f11SLiam Girdwood ret = init_data->regulator_init(rdev->reg_data); 34444fca9545SDavid Brownell if (ret < 0) 34454fca9545SDavid Brownell goto clean; 3446a5766f11SLiam Girdwood } 3447a5766f11SLiam Girdwood 3448a5766f11SLiam Girdwood /* register with sysfs */ 3449a5766f11SLiam Girdwood rdev->dev.class = ®ulator_class; 345063c7c9e1SCharles Keepax rdev->dev.of_node = of_node_get(config->of_node); 3451a5766f11SLiam Girdwood rdev->dev.parent = dev; 3452812460a9SKay Sievers dev_set_name(&rdev->dev, "regulator.%d", 3453812460a9SKay Sievers atomic_inc_return(®ulator_no) - 1); 3454a5766f11SLiam Girdwood ret = device_register(&rdev->dev); 3455ad7725cbSVasiliy Kulikov if (ret != 0) { 3456ad7725cbSVasiliy Kulikov put_device(&rdev->dev); 34574fca9545SDavid Brownell goto clean; 3458ad7725cbSVasiliy Kulikov } 3459a5766f11SLiam Girdwood 3460a5766f11SLiam Girdwood dev_set_drvdata(&rdev->dev, rdev); 3461a5766f11SLiam Girdwood 3462b2a1ef47SMarek Szyprowski if (config->ena_gpio && gpio_is_valid(config->ena_gpio)) { 3463f19b00daSKim, Milo ret = regulator_ena_gpio_request(rdev, config); 346465f73508SMark Brown if (ret != 0) { 346565f73508SMark Brown rdev_err(rdev, "Failed to request enable GPIO%d: %d\n", 346665f73508SMark Brown config->ena_gpio, ret); 3467b2da55d9SAndrew Lunn goto wash; 346865f73508SMark Brown } 346965f73508SMark Brown 347065f73508SMark Brown if (config->ena_gpio_flags & GPIOF_OUT_INIT_HIGH) 347165f73508SMark Brown rdev->ena_gpio_state = 1; 347265f73508SMark Brown 34737b74d149SKim, Milo if (config->ena_gpio_invert) 347465f73508SMark Brown rdev->ena_gpio_state = !rdev->ena_gpio_state; 347565f73508SMark Brown } 347665f73508SMark Brown 347774f544c1SMike Rapoport /* set regulator constraints */ 34789a8f5e07SMark Brown if (init_data) 34799a8f5e07SMark Brown constraints = &init_data->constraints; 34809a8f5e07SMark Brown 34819a8f5e07SMark Brown ret = set_machine_constraints(rdev, constraints); 348274f544c1SMike Rapoport if (ret < 0) 348374f544c1SMike Rapoport goto scrub; 348474f544c1SMike Rapoport 34857ad68e2fSDavid Brownell /* add attributes supported by this regulator */ 34867ad68e2fSDavid Brownell ret = add_regulator_attributes(rdev); 34877ad68e2fSDavid Brownell if (ret < 0) 34887ad68e2fSDavid Brownell goto scrub; 34897ad68e2fSDavid Brownell 34909a8f5e07SMark Brown if (init_data && init_data->supply_regulator) 349169511a45SRajendra Nayak supply = init_data->supply_regulator; 349269511a45SRajendra Nayak else if (regulator_desc->supply_name) 349369511a45SRajendra Nayak supply = regulator_desc->supply_name; 349469511a45SRajendra Nayak 349569511a45SRajendra Nayak if (supply) { 34960178f3e2SMark Brown struct regulator_dev *r; 34970178f3e2SMark Brown 34986d191a5fSMark Brown r = regulator_dev_lookup(dev, supply, &ret); 34990178f3e2SMark Brown 35000f7b87f0SAndrew Bresticker if (ret == -ENODEV) { 35010f7b87f0SAndrew Bresticker /* 35020f7b87f0SAndrew Bresticker * No supply was specified for this regulator and 35030f7b87f0SAndrew Bresticker * there will never be one. 35040f7b87f0SAndrew Bresticker */ 35050f7b87f0SAndrew Bresticker ret = 0; 35060f7b87f0SAndrew Bresticker goto add_dev; 35070f7b87f0SAndrew Bresticker } else if (!r) { 350869511a45SRajendra Nayak dev_err(dev, "Failed to find supply %s\n", supply); 350904bf3011SMark Brown ret = -EPROBE_DEFER; 35100178f3e2SMark Brown goto scrub; 35110178f3e2SMark Brown } 35120178f3e2SMark Brown 35130178f3e2SMark Brown ret = set_supply(rdev, r); 35140178f3e2SMark Brown if (ret < 0) 35150178f3e2SMark Brown goto scrub; 3516b2296bd4SLaxman Dewangan 3517b2296bd4SLaxman Dewangan /* Enable supply if rail is enabled */ 3518b1a86831SMark Brown if (_regulator_is_enabled(rdev)) { 3519b2296bd4SLaxman Dewangan ret = regulator_enable(rdev->supply); 3520b2296bd4SLaxman Dewangan if (ret < 0) 3521b2296bd4SLaxman Dewangan goto scrub; 3522b2296bd4SLaxman Dewangan } 35230178f3e2SMark Brown } 35240178f3e2SMark Brown 35250f7b87f0SAndrew Bresticker add_dev: 3526a5766f11SLiam Girdwood /* add consumers devices */ 35279a8f5e07SMark Brown if (init_data) { 3528a5766f11SLiam Girdwood for (i = 0; i < init_data->num_consumer_supplies; i++) { 3529a5766f11SLiam Girdwood ret = set_consumer_device_supply(rdev, 353040f9244fSMark Brown init_data->consumer_supplies[i].dev_name, 3531a5766f11SLiam Girdwood init_data->consumer_supplies[i].supply); 353223c2f041SMark Brown if (ret < 0) { 353323c2f041SMark Brown dev_err(dev, "Failed to set supply %s\n", 353423c2f041SMark Brown init_data->consumer_supplies[i].supply); 3535d4033b54SJani Nikula goto unset_supplies; 3536a5766f11SLiam Girdwood } 353723c2f041SMark Brown } 35389a8f5e07SMark Brown } 3539a5766f11SLiam Girdwood 3540a5766f11SLiam Girdwood list_add(&rdev->list, ®ulator_list); 35411130e5b3SMark Brown 35421130e5b3SMark Brown rdev_init_debugfs(rdev); 3543a5766f11SLiam Girdwood out: 3544414c70cbSLiam Girdwood mutex_unlock(®ulator_list_mutex); 3545414c70cbSLiam Girdwood return rdev; 35464fca9545SDavid Brownell 3547d4033b54SJani Nikula unset_supplies: 3548d4033b54SJani Nikula unset_regulator_supplies(rdev); 3549d4033b54SJani Nikula 35504fca9545SDavid Brownell scrub: 3551e81dba85SMark Brown if (rdev->supply) 355223ff2f0fSCharles Keepax _regulator_put(rdev->supply); 3553f19b00daSKim, Milo regulator_ena_gpio_free(rdev); 35541a6958e7SAxel Lin kfree(rdev->constraints); 3555b2da55d9SAndrew Lunn wash: 35564fca9545SDavid Brownell device_unregister(&rdev->dev); 355753032dafSPaul Walmsley /* device core frees rdev */ 355853032dafSPaul Walmsley rdev = ERR_PTR(ret); 355953032dafSPaul Walmsley goto out; 356053032dafSPaul Walmsley 35614fca9545SDavid Brownell clean: 35624fca9545SDavid Brownell kfree(rdev); 35634fca9545SDavid Brownell rdev = ERR_PTR(ret); 35644fca9545SDavid Brownell goto out; 3565414c70cbSLiam Girdwood } 3566414c70cbSLiam Girdwood EXPORT_SYMBOL_GPL(regulator_register); 3567414c70cbSLiam Girdwood 3568414c70cbSLiam Girdwood /** 3569414c70cbSLiam Girdwood * regulator_unregister - unregister regulator 357069279fb9SMark Brown * @rdev: regulator to unregister 3571414c70cbSLiam Girdwood * 3572414c70cbSLiam Girdwood * Called by regulator drivers to unregister a regulator. 3573414c70cbSLiam Girdwood */ 3574414c70cbSLiam Girdwood void regulator_unregister(struct regulator_dev *rdev) 3575414c70cbSLiam Girdwood { 3576414c70cbSLiam Girdwood if (rdev == NULL) 3577414c70cbSLiam Girdwood return; 3578414c70cbSLiam Girdwood 3579891636eaSMark Brown if (rdev->supply) { 3580891636eaSMark Brown while (rdev->use_count--) 3581891636eaSMark Brown regulator_disable(rdev->supply); 3582e032b376SMark Brown regulator_put(rdev->supply); 3583891636eaSMark Brown } 3584414c70cbSLiam Girdwood mutex_lock(®ulator_list_mutex); 35851130e5b3SMark Brown debugfs_remove_recursive(rdev->debugfs); 358643829731STejun Heo flush_work(&rdev->disable_work.work); 35876bf87d17SMark Brown WARN_ON(rdev->open_count); 35880f1d747bSMike Rapoport unset_regulator_supplies(rdev); 3589414c70cbSLiam Girdwood list_del(&rdev->list); 3590f8c12fe3SMark Brown kfree(rdev->constraints); 3591f19b00daSKim, Milo regulator_ena_gpio_free(rdev); 359263c7c9e1SCharles Keepax of_node_put(rdev->dev.of_node); 359358fb5cf5SLothar Waßmann device_unregister(&rdev->dev); 3594414c70cbSLiam Girdwood mutex_unlock(®ulator_list_mutex); 3595414c70cbSLiam Girdwood } 3596414c70cbSLiam Girdwood EXPORT_SYMBOL_GPL(regulator_unregister); 3597414c70cbSLiam Girdwood 3598414c70cbSLiam Girdwood /** 3599cf7bbcdfSMark Brown * regulator_suspend_prepare - prepare regulators for system wide suspend 3600414c70cbSLiam Girdwood * @state: system suspend state 3601414c70cbSLiam Girdwood * 3602414c70cbSLiam Girdwood * Configure each regulator with it's suspend operating parameters for state. 3603414c70cbSLiam Girdwood * This will usually be called by machine suspend code prior to supending. 3604414c70cbSLiam Girdwood */ 3605414c70cbSLiam Girdwood int regulator_suspend_prepare(suspend_state_t state) 3606414c70cbSLiam Girdwood { 3607414c70cbSLiam Girdwood struct regulator_dev *rdev; 3608414c70cbSLiam Girdwood int ret = 0; 3609414c70cbSLiam Girdwood 3610414c70cbSLiam Girdwood /* ON is handled by regulator active state */ 3611414c70cbSLiam Girdwood if (state == PM_SUSPEND_ON) 3612414c70cbSLiam Girdwood return -EINVAL; 3613414c70cbSLiam Girdwood 3614414c70cbSLiam Girdwood mutex_lock(®ulator_list_mutex); 3615414c70cbSLiam Girdwood list_for_each_entry(rdev, ®ulator_list, list) { 3616414c70cbSLiam Girdwood 3617414c70cbSLiam Girdwood mutex_lock(&rdev->mutex); 3618414c70cbSLiam Girdwood ret = suspend_prepare(rdev, state); 3619414c70cbSLiam Girdwood mutex_unlock(&rdev->mutex); 3620414c70cbSLiam Girdwood 3621414c70cbSLiam Girdwood if (ret < 0) { 36225da84fd9SJoe Perches rdev_err(rdev, "failed to prepare\n"); 3623414c70cbSLiam Girdwood goto out; 3624414c70cbSLiam Girdwood } 3625414c70cbSLiam Girdwood } 3626414c70cbSLiam Girdwood out: 3627414c70cbSLiam Girdwood mutex_unlock(®ulator_list_mutex); 3628414c70cbSLiam Girdwood return ret; 3629414c70cbSLiam Girdwood } 3630414c70cbSLiam Girdwood EXPORT_SYMBOL_GPL(regulator_suspend_prepare); 3631414c70cbSLiam Girdwood 3632414c70cbSLiam Girdwood /** 36337a32b589SMyungJoo Ham * regulator_suspend_finish - resume regulators from system wide suspend 36347a32b589SMyungJoo Ham * 36357a32b589SMyungJoo Ham * Turn on regulators that might be turned off by regulator_suspend_prepare 36367a32b589SMyungJoo Ham * and that should be turned on according to the regulators properties. 36377a32b589SMyungJoo Ham */ 36387a32b589SMyungJoo Ham int regulator_suspend_finish(void) 36397a32b589SMyungJoo Ham { 36407a32b589SMyungJoo Ham struct regulator_dev *rdev; 36417a32b589SMyungJoo Ham int ret = 0, error; 36427a32b589SMyungJoo Ham 36437a32b589SMyungJoo Ham mutex_lock(®ulator_list_mutex); 36447a32b589SMyungJoo Ham list_for_each_entry(rdev, ®ulator_list, list) { 36457a32b589SMyungJoo Ham mutex_lock(&rdev->mutex); 364630c21971SMarkus Pargmann if (rdev->use_count > 0 || rdev->constraints->always_on) { 364730c21971SMarkus Pargmann error = _regulator_do_enable(rdev); 36487a32b589SMyungJoo Ham if (error) 36497a32b589SMyungJoo Ham ret = error; 36507a32b589SMyungJoo Ham } else { 365187b28417SMark Brown if (!have_full_constraints()) 36527a32b589SMyungJoo Ham goto unlock; 3653b1a86831SMark Brown if (!_regulator_is_enabled(rdev)) 36547a32b589SMyungJoo Ham goto unlock; 36557a32b589SMyungJoo Ham 365666fda75fSMarkus Pargmann error = _regulator_do_disable(rdev); 36577a32b589SMyungJoo Ham if (error) 36587a32b589SMyungJoo Ham ret = error; 36597a32b589SMyungJoo Ham } 36607a32b589SMyungJoo Ham unlock: 36617a32b589SMyungJoo Ham mutex_unlock(&rdev->mutex); 36627a32b589SMyungJoo Ham } 36637a32b589SMyungJoo Ham mutex_unlock(®ulator_list_mutex); 36647a32b589SMyungJoo Ham return ret; 36657a32b589SMyungJoo Ham } 36667a32b589SMyungJoo Ham EXPORT_SYMBOL_GPL(regulator_suspend_finish); 36677a32b589SMyungJoo Ham 36687a32b589SMyungJoo Ham /** 3669ca725561SMark Brown * regulator_has_full_constraints - the system has fully specified constraints 3670ca725561SMark Brown * 3671ca725561SMark Brown * Calling this function will cause the regulator API to disable all 3672ca725561SMark Brown * regulators which have a zero use count and don't have an always_on 3673ca725561SMark Brown * constraint in a late_initcall. 3674ca725561SMark Brown * 3675ca725561SMark Brown * The intention is that this will become the default behaviour in a 3676ca725561SMark Brown * future kernel release so users are encouraged to use this facility 3677ca725561SMark Brown * now. 3678ca725561SMark Brown */ 3679ca725561SMark Brown void regulator_has_full_constraints(void) 3680ca725561SMark Brown { 3681ca725561SMark Brown has_full_constraints = 1; 3682ca725561SMark Brown } 3683ca725561SMark Brown EXPORT_SYMBOL_GPL(regulator_has_full_constraints); 3684ca725561SMark Brown 3685ca725561SMark Brown /** 3686414c70cbSLiam Girdwood * rdev_get_drvdata - get rdev regulator driver data 368769279fb9SMark Brown * @rdev: regulator 3688414c70cbSLiam Girdwood * 3689414c70cbSLiam Girdwood * Get rdev regulator driver private data. This call can be used in the 3690414c70cbSLiam Girdwood * regulator driver context. 3691414c70cbSLiam Girdwood */ 3692414c70cbSLiam Girdwood void *rdev_get_drvdata(struct regulator_dev *rdev) 3693414c70cbSLiam Girdwood { 3694414c70cbSLiam Girdwood return rdev->reg_data; 3695414c70cbSLiam Girdwood } 3696414c70cbSLiam Girdwood EXPORT_SYMBOL_GPL(rdev_get_drvdata); 3697414c70cbSLiam Girdwood 3698414c70cbSLiam Girdwood /** 3699414c70cbSLiam Girdwood * regulator_get_drvdata - get regulator driver data 3700414c70cbSLiam Girdwood * @regulator: regulator 3701414c70cbSLiam Girdwood * 3702414c70cbSLiam Girdwood * Get regulator driver private data. This call can be used in the consumer 3703414c70cbSLiam Girdwood * driver context when non API regulator specific functions need to be called. 3704414c70cbSLiam Girdwood */ 3705414c70cbSLiam Girdwood void *regulator_get_drvdata(struct regulator *regulator) 3706414c70cbSLiam Girdwood { 3707414c70cbSLiam Girdwood return regulator->rdev->reg_data; 3708414c70cbSLiam Girdwood } 3709414c70cbSLiam Girdwood EXPORT_SYMBOL_GPL(regulator_get_drvdata); 3710414c70cbSLiam Girdwood 3711414c70cbSLiam Girdwood /** 3712414c70cbSLiam Girdwood * regulator_set_drvdata - set regulator driver data 3713414c70cbSLiam Girdwood * @regulator: regulator 3714414c70cbSLiam Girdwood * @data: data 3715414c70cbSLiam Girdwood */ 3716414c70cbSLiam Girdwood void regulator_set_drvdata(struct regulator *regulator, void *data) 3717414c70cbSLiam Girdwood { 3718414c70cbSLiam Girdwood regulator->rdev->reg_data = data; 3719414c70cbSLiam Girdwood } 3720414c70cbSLiam Girdwood EXPORT_SYMBOL_GPL(regulator_set_drvdata); 3721414c70cbSLiam Girdwood 3722414c70cbSLiam Girdwood /** 3723414c70cbSLiam Girdwood * regulator_get_id - get regulator ID 372469279fb9SMark Brown * @rdev: regulator 3725414c70cbSLiam Girdwood */ 3726414c70cbSLiam Girdwood int rdev_get_id(struct regulator_dev *rdev) 3727414c70cbSLiam Girdwood { 3728414c70cbSLiam Girdwood return rdev->desc->id; 3729414c70cbSLiam Girdwood } 3730414c70cbSLiam Girdwood EXPORT_SYMBOL_GPL(rdev_get_id); 3731414c70cbSLiam Girdwood 3732a5766f11SLiam Girdwood struct device *rdev_get_dev(struct regulator_dev *rdev) 3733a5766f11SLiam Girdwood { 3734a5766f11SLiam Girdwood return &rdev->dev; 3735a5766f11SLiam Girdwood } 3736a5766f11SLiam Girdwood EXPORT_SYMBOL_GPL(rdev_get_dev); 3737a5766f11SLiam Girdwood 3738a5766f11SLiam Girdwood void *regulator_get_init_drvdata(struct regulator_init_data *reg_init_data) 3739a5766f11SLiam Girdwood { 3740a5766f11SLiam Girdwood return reg_init_data->driver_data; 3741a5766f11SLiam Girdwood } 3742a5766f11SLiam Girdwood EXPORT_SYMBOL_GPL(regulator_get_init_drvdata); 3743a5766f11SLiam Girdwood 3744ba55a974SMark Brown #ifdef CONFIG_DEBUG_FS 3745ba55a974SMark Brown static ssize_t supply_map_read_file(struct file *file, char __user *user_buf, 3746ba55a974SMark Brown size_t count, loff_t *ppos) 3747ba55a974SMark Brown { 3748ba55a974SMark Brown char *buf = kmalloc(PAGE_SIZE, GFP_KERNEL); 3749ba55a974SMark Brown ssize_t len, ret = 0; 3750ba55a974SMark Brown struct regulator_map *map; 3751ba55a974SMark Brown 3752ba55a974SMark Brown if (!buf) 3753ba55a974SMark Brown return -ENOMEM; 3754ba55a974SMark Brown 3755ba55a974SMark Brown list_for_each_entry(map, ®ulator_map_list, list) { 3756ba55a974SMark Brown len = snprintf(buf + ret, PAGE_SIZE - ret, 3757ba55a974SMark Brown "%s -> %s.%s\n", 3758ba55a974SMark Brown rdev_get_name(map->regulator), map->dev_name, 3759ba55a974SMark Brown map->supply); 3760ba55a974SMark Brown if (len >= 0) 3761ba55a974SMark Brown ret += len; 3762ba55a974SMark Brown if (ret > PAGE_SIZE) { 3763ba55a974SMark Brown ret = PAGE_SIZE; 3764ba55a974SMark Brown break; 3765ba55a974SMark Brown } 3766ba55a974SMark Brown } 3767ba55a974SMark Brown 3768ba55a974SMark Brown ret = simple_read_from_buffer(user_buf, count, ppos, buf, ret); 3769ba55a974SMark Brown 3770ba55a974SMark Brown kfree(buf); 3771ba55a974SMark Brown 3772ba55a974SMark Brown return ret; 3773ba55a974SMark Brown } 377424751434SStephen Boyd #endif 3775ba55a974SMark Brown 3776ba55a974SMark Brown static const struct file_operations supply_map_fops = { 377724751434SStephen Boyd #ifdef CONFIG_DEBUG_FS 3778ba55a974SMark Brown .read = supply_map_read_file, 3779ba55a974SMark Brown .llseek = default_llseek, 3780ba55a974SMark Brown #endif 378124751434SStephen Boyd }; 3782ba55a974SMark Brown 3783414c70cbSLiam Girdwood static int __init regulator_init(void) 3784414c70cbSLiam Girdwood { 378534abbd68SMark Brown int ret; 378634abbd68SMark Brown 378734abbd68SMark Brown ret = class_register(®ulator_class); 378834abbd68SMark Brown 37891130e5b3SMark Brown debugfs_root = debugfs_create_dir("regulator", NULL); 379024751434SStephen Boyd if (!debugfs_root) 37911130e5b3SMark Brown pr_warn("regulator: Failed to create debugfs directory\n"); 3792ba55a974SMark Brown 3793f4d562c6SMark Brown debugfs_create_file("supply_map", 0444, debugfs_root, NULL, 3794f4d562c6SMark Brown &supply_map_fops); 37951130e5b3SMark Brown 379634abbd68SMark Brown regulator_dummy_init(); 379734abbd68SMark Brown 379834abbd68SMark Brown return ret; 3799414c70cbSLiam Girdwood } 3800414c70cbSLiam Girdwood 3801414c70cbSLiam Girdwood /* init early to allow our consumers to complete system booting */ 3802414c70cbSLiam Girdwood core_initcall(regulator_init); 3803ca725561SMark Brown 3804ca725561SMark Brown static int __init regulator_init_complete(void) 3805ca725561SMark Brown { 3806ca725561SMark Brown struct regulator_dev *rdev; 3807ca725561SMark Brown struct regulator_ops *ops; 3808ca725561SMark Brown struct regulation_constraints *c; 3809ca725561SMark Brown int enabled, ret; 3810ca725561SMark Brown 381186f5fcfcSMark Brown /* 381286f5fcfcSMark Brown * Since DT doesn't provide an idiomatic mechanism for 381386f5fcfcSMark Brown * enabling full constraints and since it's much more natural 381486f5fcfcSMark Brown * with DT to provide them just assume that a DT enabled 381586f5fcfcSMark Brown * system has full constraints. 381686f5fcfcSMark Brown */ 381786f5fcfcSMark Brown if (of_have_populated_dt()) 381886f5fcfcSMark Brown has_full_constraints = true; 381986f5fcfcSMark Brown 3820ca725561SMark Brown mutex_lock(®ulator_list_mutex); 3821ca725561SMark Brown 3822ca725561SMark Brown /* If we have a full configuration then disable any regulators 3823ca725561SMark Brown * which are not in use or always_on. This will become the 3824ca725561SMark Brown * default behaviour in the future. 3825ca725561SMark Brown */ 3826ca725561SMark Brown list_for_each_entry(rdev, ®ulator_list, list) { 3827ca725561SMark Brown ops = rdev->desc->ops; 3828ca725561SMark Brown c = rdev->constraints; 3829ca725561SMark Brown 383066fda75fSMarkus Pargmann if (c && c->always_on) 3831ca725561SMark Brown continue; 3832ca725561SMark Brown 3833ca725561SMark Brown mutex_lock(&rdev->mutex); 3834ca725561SMark Brown 3835ca725561SMark Brown if (rdev->use_count) 3836ca725561SMark Brown goto unlock; 3837ca725561SMark Brown 3838ca725561SMark Brown /* If we can't read the status assume it's on. */ 3839ca725561SMark Brown if (ops->is_enabled) 3840ca725561SMark Brown enabled = ops->is_enabled(rdev); 3841ca725561SMark Brown else 3842ca725561SMark Brown enabled = 1; 3843ca725561SMark Brown 3844ca725561SMark Brown if (!enabled) 3845ca725561SMark Brown goto unlock; 3846ca725561SMark Brown 384787b28417SMark Brown if (have_full_constraints()) { 3848ca725561SMark Brown /* We log since this may kill the system if it 3849ca725561SMark Brown * goes wrong. */ 38505da84fd9SJoe Perches rdev_info(rdev, "disabling\n"); 385166fda75fSMarkus Pargmann ret = _regulator_do_disable(rdev); 38520d25d09dSJingoo Han if (ret != 0) 38535da84fd9SJoe Perches rdev_err(rdev, "couldn't disable: %d\n", ret); 3854ca725561SMark Brown } else { 3855ca725561SMark Brown /* The intention is that in future we will 3856ca725561SMark Brown * assume that full constraints are provided 3857ca725561SMark Brown * so warn even if we aren't going to do 3858ca725561SMark Brown * anything here. 3859ca725561SMark Brown */ 38605da84fd9SJoe Perches rdev_warn(rdev, "incomplete constraints, leaving on\n"); 3861ca725561SMark Brown } 3862ca725561SMark Brown 3863ca725561SMark Brown unlock: 3864ca725561SMark Brown mutex_unlock(&rdev->mutex); 3865ca725561SMark Brown } 3866ca725561SMark Brown 3867ca725561SMark Brown mutex_unlock(®ulator_list_mutex); 3868ca725561SMark Brown 3869ca725561SMark Brown return 0; 3870ca725561SMark Brown } 3871ca725561SMark Brown late_initcall(regulator_init_complete); 3872