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 956a5766f11SLiam Girdwood /** 957a5766f11SLiam Girdwood * set_machine_constraints - sets regulator constraints 95869279fb9SMark Brown * @rdev: regulator source 959c8e7e464SMark Brown * @constraints: constraints to apply 960a5766f11SLiam Girdwood * 961a5766f11SLiam Girdwood * Allows platform initialisation code to define and constrain 962a5766f11SLiam Girdwood * regulator circuits e.g. valid voltage/current ranges, etc. NOTE: 963a5766f11SLiam Girdwood * Constraints *must* be set by platform code in order for some 964a5766f11SLiam Girdwood * regulator operations to proceed i.e. set_voltage, set_current_limit, 965a5766f11SLiam Girdwood * set_mode. 966a5766f11SLiam Girdwood */ 967a5766f11SLiam Girdwood static int set_machine_constraints(struct regulator_dev *rdev, 968f8c12fe3SMark Brown const struct regulation_constraints *constraints) 969a5766f11SLiam Girdwood { 970a5766f11SLiam Girdwood int ret = 0; 971e5fda26cSMark Brown struct regulator_ops *ops = rdev->desc->ops; 972e06f5b4fSMark Brown 9739a8f5e07SMark Brown if (constraints) 974f8c12fe3SMark Brown rdev->constraints = kmemdup(constraints, sizeof(*constraints), 975f8c12fe3SMark Brown GFP_KERNEL); 9769a8f5e07SMark Brown else 9779a8f5e07SMark Brown rdev->constraints = kzalloc(sizeof(*constraints), 9789a8f5e07SMark Brown GFP_KERNEL); 979f8c12fe3SMark Brown if (!rdev->constraints) 980f8c12fe3SMark Brown return -ENOMEM; 981af5866c9SMark Brown 982f8c12fe3SMark Brown ret = machine_constraints_voltage(rdev, rdev->constraints); 983e79055d6SMark Brown if (ret != 0) 9843e2b9abdSMark Brown goto out; 9853e2b9abdSMark Brown 986f8c1700dSLaxman Dewangan ret = machine_constraints_current(rdev, rdev->constraints); 987f8c1700dSLaxman Dewangan if (ret != 0) 988f8c1700dSLaxman Dewangan goto out; 989f8c1700dSLaxman Dewangan 990a5766f11SLiam Girdwood /* do we need to setup our suspend state */ 9919a8f5e07SMark Brown if (rdev->constraints->initial_state) { 992f8c12fe3SMark Brown ret = suspend_prepare(rdev, rdev->constraints->initial_state); 993e06f5b4fSMark Brown if (ret < 0) { 9945da84fd9SJoe Perches rdev_err(rdev, "failed to set suspend state\n"); 995e06f5b4fSMark Brown goto out; 996e06f5b4fSMark Brown } 997e06f5b4fSMark Brown } 998a5766f11SLiam Girdwood 9999a8f5e07SMark Brown if (rdev->constraints->initial_mode) { 1000a308466cSMark Brown if (!ops->set_mode) { 10015da84fd9SJoe Perches rdev_err(rdev, "no set_mode operation\n"); 1002a308466cSMark Brown ret = -EINVAL; 1003a308466cSMark Brown goto out; 1004a308466cSMark Brown } 1005a308466cSMark Brown 1006f8c12fe3SMark Brown ret = ops->set_mode(rdev, rdev->constraints->initial_mode); 1007a308466cSMark Brown if (ret < 0) { 10085da84fd9SJoe Perches rdev_err(rdev, "failed to set initial mode: %d\n", ret); 1009a308466cSMark Brown goto out; 1010a308466cSMark Brown } 1011a308466cSMark Brown } 1012a308466cSMark Brown 1013cacf90f2SMark Brown /* If the constraints say the regulator should be on at this point 1014cacf90f2SMark Brown * and we have control then make sure it is enabled. 1015cacf90f2SMark Brown */ 1016f8c12fe3SMark Brown if ((rdev->constraints->always_on || rdev->constraints->boot_on) && 1017f8c12fe3SMark Brown ops->enable) { 1018e5fda26cSMark Brown ret = ops->enable(rdev); 1019e5fda26cSMark Brown if (ret < 0) { 10205da84fd9SJoe Perches rdev_err(rdev, "failed to enable\n"); 1021e5fda26cSMark Brown goto out; 1022e5fda26cSMark Brown } 1023e5fda26cSMark Brown } 1024e5fda26cSMark Brown 10251653ccf4SYadwinder Singh Brar if ((rdev->constraints->ramp_delay || rdev->constraints->ramp_disable) 10261653ccf4SYadwinder Singh Brar && ops->set_ramp_delay) { 10276f0b2c69SYadwinder Singh Brar ret = ops->set_ramp_delay(rdev, rdev->constraints->ramp_delay); 10286f0b2c69SYadwinder Singh Brar if (ret < 0) { 10296f0b2c69SYadwinder Singh Brar rdev_err(rdev, "failed to set ramp_delay\n"); 10306f0b2c69SYadwinder Singh Brar goto out; 10316f0b2c69SYadwinder Singh Brar } 10326f0b2c69SYadwinder Singh Brar } 10336f0b2c69SYadwinder Singh Brar 1034a5766f11SLiam Girdwood print_constraints(rdev); 10351a6958e7SAxel Lin return 0; 1036a5766f11SLiam Girdwood out: 10371a6958e7SAxel Lin kfree(rdev->constraints); 10381a6958e7SAxel Lin rdev->constraints = NULL; 1039a5766f11SLiam Girdwood return ret; 1040a5766f11SLiam Girdwood } 1041a5766f11SLiam Girdwood 1042a5766f11SLiam Girdwood /** 1043a5766f11SLiam Girdwood * set_supply - set regulator supply regulator 104469279fb9SMark Brown * @rdev: regulator name 104569279fb9SMark Brown * @supply_rdev: supply regulator name 1046a5766f11SLiam Girdwood * 1047a5766f11SLiam Girdwood * Called by platform initialisation code to set the supply regulator for this 1048a5766f11SLiam Girdwood * regulator. This ensures that a regulators supply will also be enabled by the 1049a5766f11SLiam Girdwood * core if it's child is enabled. 1050a5766f11SLiam Girdwood */ 1051a5766f11SLiam Girdwood static int set_supply(struct regulator_dev *rdev, 1052a5766f11SLiam Girdwood struct regulator_dev *supply_rdev) 1053a5766f11SLiam Girdwood { 1054a5766f11SLiam Girdwood int err; 1055a5766f11SLiam Girdwood 10563801b86aSMark Brown rdev_info(rdev, "supplied by %s\n", rdev_get_name(supply_rdev)); 10573801b86aSMark Brown 10583801b86aSMark Brown rdev->supply = create_regulator(supply_rdev, &rdev->dev, "SUPPLY"); 105932c78de8SAxel Lin if (rdev->supply == NULL) { 106032c78de8SAxel Lin err = -ENOMEM; 1061a5766f11SLiam Girdwood return err; 1062a5766f11SLiam Girdwood } 106357ad526aSLaxman Dewangan supply_rdev->open_count++; 1064a5766f11SLiam Girdwood 10653801b86aSMark Brown return 0; 10663801b86aSMark Brown } 10673801b86aSMark Brown 1068a5766f11SLiam Girdwood /** 106906c63f93SRandy Dunlap * set_consumer_device_supply - Bind a regulator to a symbolic supply 107069279fb9SMark Brown * @rdev: regulator source 107140f9244fSMark Brown * @consumer_dev_name: dev_name() string for device supply applies to 1072a5766f11SLiam Girdwood * @supply: symbolic name for supply 1073a5766f11SLiam Girdwood * 1074a5766f11SLiam Girdwood * Allows platform initialisation code to map physical regulator 1075a5766f11SLiam Girdwood * sources to symbolic names for supplies for use by devices. Devices 1076a5766f11SLiam Girdwood * should use these symbolic names to request regulators, avoiding the 1077a5766f11SLiam Girdwood * need to provide board-specific regulator names as platform data. 1078a5766f11SLiam Girdwood */ 1079a5766f11SLiam Girdwood static int set_consumer_device_supply(struct regulator_dev *rdev, 1080737f360dSMark Brown const char *consumer_dev_name, 108140f9244fSMark Brown const char *supply) 1082a5766f11SLiam Girdwood { 1083a5766f11SLiam Girdwood struct regulator_map *node; 10849ed2099eSMark Brown int has_dev; 1085a5766f11SLiam Girdwood 1086a5766f11SLiam Girdwood if (supply == NULL) 1087a5766f11SLiam Girdwood return -EINVAL; 1088a5766f11SLiam Girdwood 10899ed2099eSMark Brown if (consumer_dev_name != NULL) 10909ed2099eSMark Brown has_dev = 1; 10919ed2099eSMark Brown else 10929ed2099eSMark Brown has_dev = 0; 10939ed2099eSMark Brown 10946001e13cSDavid Brownell list_for_each_entry(node, ®ulator_map_list, list) { 109523b5cc2aSJani Nikula if (node->dev_name && consumer_dev_name) { 109623b5cc2aSJani Nikula if (strcmp(node->dev_name, consumer_dev_name) != 0) 10976001e13cSDavid Brownell continue; 109823b5cc2aSJani Nikula } else if (node->dev_name || consumer_dev_name) { 109923b5cc2aSJani Nikula continue; 110023b5cc2aSJani Nikula } 110123b5cc2aSJani Nikula 11026001e13cSDavid Brownell if (strcmp(node->supply, supply) != 0) 11036001e13cSDavid Brownell continue; 11046001e13cSDavid Brownell 1105737f360dSMark Brown pr_debug("%s: %s/%s is '%s' supply; fail %s/%s\n", 1106737f360dSMark Brown consumer_dev_name, 11076001e13cSDavid Brownell dev_name(&node->regulator->dev), 11086001e13cSDavid Brownell node->regulator->desc->name, 11096001e13cSDavid Brownell supply, 11101083c393SMark Brown dev_name(&rdev->dev), rdev_get_name(rdev)); 11116001e13cSDavid Brownell return -EBUSY; 11126001e13cSDavid Brownell } 11136001e13cSDavid Brownell 11149ed2099eSMark Brown node = kzalloc(sizeof(struct regulator_map), GFP_KERNEL); 1115a5766f11SLiam Girdwood if (node == NULL) 1116a5766f11SLiam Girdwood return -ENOMEM; 1117a5766f11SLiam Girdwood 1118a5766f11SLiam Girdwood node->regulator = rdev; 1119a5766f11SLiam Girdwood node->supply = supply; 1120a5766f11SLiam Girdwood 11219ed2099eSMark Brown if (has_dev) { 11229ed2099eSMark Brown node->dev_name = kstrdup(consumer_dev_name, GFP_KERNEL); 112340f9244fSMark Brown if (node->dev_name == NULL) { 112440f9244fSMark Brown kfree(node); 112540f9244fSMark Brown return -ENOMEM; 112640f9244fSMark Brown } 11279ed2099eSMark Brown } 112840f9244fSMark Brown 1129a5766f11SLiam Girdwood list_add(&node->list, ®ulator_map_list); 1130a5766f11SLiam Girdwood return 0; 1131a5766f11SLiam Girdwood } 1132a5766f11SLiam Girdwood 11330f1d747bSMike Rapoport static void unset_regulator_supplies(struct regulator_dev *rdev) 11340f1d747bSMike Rapoport { 11350f1d747bSMike Rapoport struct regulator_map *node, *n; 11360f1d747bSMike Rapoport 11370f1d747bSMike Rapoport list_for_each_entry_safe(node, n, ®ulator_map_list, list) { 11380f1d747bSMike Rapoport if (rdev == node->regulator) { 11390f1d747bSMike Rapoport list_del(&node->list); 114040f9244fSMark Brown kfree(node->dev_name); 11410f1d747bSMike Rapoport kfree(node); 11420f1d747bSMike Rapoport } 11430f1d747bSMike Rapoport } 11440f1d747bSMike Rapoport } 11450f1d747bSMike Rapoport 1146f5726ae3SMark Brown #define REG_STR_SIZE 64 1147414c70cbSLiam Girdwood 1148414c70cbSLiam Girdwood static struct regulator *create_regulator(struct regulator_dev *rdev, 1149414c70cbSLiam Girdwood struct device *dev, 1150414c70cbSLiam Girdwood const char *supply_name) 1151414c70cbSLiam Girdwood { 1152414c70cbSLiam Girdwood struct regulator *regulator; 1153414c70cbSLiam Girdwood char buf[REG_STR_SIZE]; 1154414c70cbSLiam Girdwood int err, size; 1155414c70cbSLiam Girdwood 1156414c70cbSLiam Girdwood regulator = kzalloc(sizeof(*regulator), GFP_KERNEL); 1157414c70cbSLiam Girdwood if (regulator == NULL) 1158414c70cbSLiam Girdwood return NULL; 1159414c70cbSLiam Girdwood 1160414c70cbSLiam Girdwood mutex_lock(&rdev->mutex); 1161414c70cbSLiam Girdwood regulator->rdev = rdev; 1162414c70cbSLiam Girdwood list_add(®ulator->list, &rdev->consumer_list); 1163414c70cbSLiam Girdwood 1164414c70cbSLiam Girdwood if (dev) { 1165e2c98eafSShawn Guo regulator->dev = dev; 1166e2c98eafSShawn Guo 1167222cc7b1SMark Brown /* Add a link to the device sysfs entry */ 1168414c70cbSLiam Girdwood size = scnprintf(buf, REG_STR_SIZE, "%s-%s", 1169414c70cbSLiam Girdwood dev->kobj.name, supply_name); 1170414c70cbSLiam Girdwood if (size >= REG_STR_SIZE) 1171222cc7b1SMark Brown goto overflow_err; 1172414c70cbSLiam Girdwood 1173414c70cbSLiam Girdwood regulator->supply_name = kstrdup(buf, GFP_KERNEL); 1174414c70cbSLiam Girdwood if (regulator->supply_name == NULL) 1175222cc7b1SMark Brown goto overflow_err; 1176414c70cbSLiam Girdwood 1177414c70cbSLiam Girdwood err = sysfs_create_link(&rdev->dev.kobj, &dev->kobj, 1178414c70cbSLiam Girdwood buf); 1179414c70cbSLiam Girdwood if (err) { 11805da84fd9SJoe Perches rdev_warn(rdev, "could not add device link %s err %d\n", 11811d7372e1SDaniel Walker dev->kobj.name, err); 1182222cc7b1SMark Brown /* non-fatal */ 1183414c70cbSLiam Girdwood } 11845de70519SMark Brown } else { 11855de70519SMark Brown regulator->supply_name = kstrdup(supply_name, GFP_KERNEL); 11865de70519SMark Brown if (regulator->supply_name == NULL) 1187222cc7b1SMark Brown goto overflow_err; 1188414c70cbSLiam Girdwood } 11895de70519SMark Brown 11905de70519SMark Brown regulator->debugfs = debugfs_create_dir(regulator->supply_name, 11915de70519SMark Brown rdev->debugfs); 119224751434SStephen Boyd if (!regulator->debugfs) { 11935de70519SMark Brown rdev_warn(rdev, "Failed to create debugfs directory\n"); 11945de70519SMark Brown } else { 11955de70519SMark Brown debugfs_create_u32("uA_load", 0444, regulator->debugfs, 11965de70519SMark Brown ®ulator->uA_load); 11975de70519SMark Brown debugfs_create_u32("min_uV", 0444, regulator->debugfs, 11985de70519SMark Brown ®ulator->min_uV); 11995de70519SMark Brown debugfs_create_u32("max_uV", 0444, regulator->debugfs, 12005de70519SMark Brown ®ulator->max_uV); 12015de70519SMark Brown } 12025de70519SMark Brown 12036492bc1bSMark Brown /* 12046492bc1bSMark Brown * Check now if the regulator is an always on regulator - if 12056492bc1bSMark Brown * it is then we don't need to do nearly so much work for 12066492bc1bSMark Brown * enable/disable calls. 12076492bc1bSMark Brown */ 12086492bc1bSMark Brown if (!_regulator_can_change_status(rdev) && 12096492bc1bSMark Brown _regulator_is_enabled(rdev)) 12106492bc1bSMark Brown regulator->always_on = true; 12116492bc1bSMark Brown 1212414c70cbSLiam Girdwood mutex_unlock(&rdev->mutex); 1213414c70cbSLiam Girdwood return regulator; 1214414c70cbSLiam Girdwood overflow_err: 1215414c70cbSLiam Girdwood list_del(®ulator->list); 1216414c70cbSLiam Girdwood kfree(regulator); 1217414c70cbSLiam Girdwood mutex_unlock(&rdev->mutex); 1218414c70cbSLiam Girdwood return NULL; 1219414c70cbSLiam Girdwood } 1220414c70cbSLiam Girdwood 122131aae2beSMark Brown static int _regulator_get_enable_time(struct regulator_dev *rdev) 122231aae2beSMark Brown { 122300c877c6SLaxman Dewangan if (rdev->constraints && rdev->constraints->enable_time) 122400c877c6SLaxman Dewangan return rdev->constraints->enable_time; 122531aae2beSMark Brown if (!rdev->desc->ops->enable_time) 122679511ed3SMark Brown return rdev->desc->enable_time; 122731aae2beSMark Brown return rdev->desc->ops->enable_time(rdev); 122831aae2beSMark Brown } 122931aae2beSMark Brown 1230a06ccd9cSCharles Keepax static struct regulator_supply_alias *regulator_find_supply_alias( 1231a06ccd9cSCharles Keepax struct device *dev, const char *supply) 1232a06ccd9cSCharles Keepax { 1233a06ccd9cSCharles Keepax struct regulator_supply_alias *map; 1234a06ccd9cSCharles Keepax 1235a06ccd9cSCharles Keepax list_for_each_entry(map, ®ulator_supply_alias_list, list) 1236a06ccd9cSCharles Keepax if (map->src_dev == dev && strcmp(map->src_supply, supply) == 0) 1237a06ccd9cSCharles Keepax return map; 1238a06ccd9cSCharles Keepax 1239a06ccd9cSCharles Keepax return NULL; 1240a06ccd9cSCharles Keepax } 1241a06ccd9cSCharles Keepax 1242a06ccd9cSCharles Keepax static void regulator_supply_alias(struct device **dev, const char **supply) 1243a06ccd9cSCharles Keepax { 1244a06ccd9cSCharles Keepax struct regulator_supply_alias *map; 1245a06ccd9cSCharles Keepax 1246a06ccd9cSCharles Keepax map = regulator_find_supply_alias(*dev, *supply); 1247a06ccd9cSCharles Keepax if (map) { 1248a06ccd9cSCharles Keepax dev_dbg(*dev, "Mapping supply %s to %s,%s\n", 1249a06ccd9cSCharles Keepax *supply, map->alias_supply, 1250a06ccd9cSCharles Keepax dev_name(map->alias_dev)); 1251a06ccd9cSCharles Keepax *dev = map->alias_dev; 1252a06ccd9cSCharles Keepax *supply = map->alias_supply; 1253a06ccd9cSCharles Keepax } 1254a06ccd9cSCharles Keepax } 1255a06ccd9cSCharles Keepax 125669511a45SRajendra Nayak static struct regulator_dev *regulator_dev_lookup(struct device *dev, 12576d191a5fSMark Brown const char *supply, 12586d191a5fSMark Brown int *ret) 125969511a45SRajendra Nayak { 126069511a45SRajendra Nayak struct regulator_dev *r; 126169511a45SRajendra Nayak struct device_node *node; 1262576ca436SMark Brown struct regulator_map *map; 1263576ca436SMark Brown const char *devname = NULL; 126469511a45SRajendra Nayak 1265a06ccd9cSCharles Keepax regulator_supply_alias(&dev, &supply); 1266a06ccd9cSCharles Keepax 126769511a45SRajendra Nayak /* first do a dt based lookup */ 126869511a45SRajendra Nayak if (dev && dev->of_node) { 126969511a45SRajendra Nayak node = of_get_regulator(dev, supply); 12706d191a5fSMark Brown if (node) { 127169511a45SRajendra Nayak list_for_each_entry(r, ®ulator_list, list) 127269511a45SRajendra Nayak if (r->dev.parent && 127369511a45SRajendra Nayak node == r->dev.of_node) 127469511a45SRajendra Nayak return r; 12756d191a5fSMark Brown } else { 12766d191a5fSMark Brown /* 12776d191a5fSMark Brown * If we couldn't even get the node then it's 12786d191a5fSMark Brown * not just that the device didn't register 12796d191a5fSMark Brown * yet, there's no node and we'll never 12806d191a5fSMark Brown * succeed. 12816d191a5fSMark Brown */ 12826d191a5fSMark Brown *ret = -ENODEV; 12836d191a5fSMark Brown } 128469511a45SRajendra Nayak } 128569511a45SRajendra Nayak 128669511a45SRajendra Nayak /* if not found, try doing it non-dt way */ 1287576ca436SMark Brown if (dev) 1288576ca436SMark Brown devname = dev_name(dev); 1289576ca436SMark Brown 129069511a45SRajendra Nayak list_for_each_entry(r, ®ulator_list, list) 129169511a45SRajendra Nayak if (strcmp(rdev_get_name(r), supply) == 0) 129269511a45SRajendra Nayak return r; 129369511a45SRajendra Nayak 1294576ca436SMark Brown list_for_each_entry(map, ®ulator_map_list, list) { 1295576ca436SMark Brown /* If the mapping has a device set up it must match */ 1296576ca436SMark Brown if (map->dev_name && 1297576ca436SMark Brown (!devname || strcmp(map->dev_name, devname))) 1298576ca436SMark Brown continue; 1299576ca436SMark Brown 1300576ca436SMark Brown if (strcmp(map->supply, supply) == 0) 1301576ca436SMark Brown return map->regulator; 1302576ca436SMark Brown } 1303576ca436SMark Brown 1304576ca436SMark Brown 130569511a45SRajendra Nayak return NULL; 130669511a45SRajendra Nayak } 130769511a45SRajendra Nayak 13085ffbd136SMark Brown /* Internal regulator request function */ 13095ffbd136SMark Brown static struct regulator *_regulator_get(struct device *dev, const char *id, 13104ddfebd3SMark Brown bool exclusive, bool allow_dummy) 1311414c70cbSLiam Girdwood { 1312414c70cbSLiam Girdwood struct regulator_dev *rdev; 131304bf3011SMark Brown struct regulator *regulator = ERR_PTR(-EPROBE_DEFER); 131440f9244fSMark Brown const char *devname = NULL; 13159b92da1fSMark Brown int ret = -EPROBE_DEFER; 1316414c70cbSLiam Girdwood 1317414c70cbSLiam Girdwood if (id == NULL) { 13185da84fd9SJoe Perches pr_err("get() with no identifier\n"); 1319043c998fSMark Brown return ERR_PTR(-EINVAL); 1320414c70cbSLiam Girdwood } 1321414c70cbSLiam Girdwood 132240f9244fSMark Brown if (dev) 132340f9244fSMark Brown devname = dev_name(dev); 132440f9244fSMark Brown 1325414c70cbSLiam Girdwood mutex_lock(®ulator_list_mutex); 1326414c70cbSLiam Girdwood 13276d191a5fSMark Brown rdev = regulator_dev_lookup(dev, id, &ret); 132869511a45SRajendra Nayak if (rdev) 132969511a45SRajendra Nayak goto found; 133069511a45SRajendra Nayak 1331ef60abbbSMark Brown regulator = ERR_PTR(ret); 1332ef60abbbSMark Brown 13331e4b545cSNishanth Menon /* 13341e4b545cSNishanth Menon * If we have return value from dev_lookup fail, we do not expect to 13351e4b545cSNishanth Menon * succeed, so, quit with appropriate error value 13361e4b545cSNishanth Menon */ 13370d25d09dSJingoo Han if (ret && ret != -ENODEV) 13381e4b545cSNishanth Menon goto out; 13391e4b545cSNishanth Menon 134034abbd68SMark Brown if (!devname) 134134abbd68SMark Brown devname = "deviceless"; 134234abbd68SMark Brown 13434ddfebd3SMark Brown /* 13444ddfebd3SMark Brown * Assume that a regulator is physically present and enabled 13454ddfebd3SMark Brown * even if it isn't hooked up and just provide a dummy. 134634abbd68SMark Brown */ 134787b28417SMark Brown if (have_full_constraints() && allow_dummy) { 13485da84fd9SJoe Perches pr_warn("%s supply %s not found, using dummy regulator\n", 134934abbd68SMark Brown devname, id); 13504ddfebd3SMark Brown 135134abbd68SMark Brown rdev = dummy_regulator_rdev; 135234abbd68SMark Brown goto found; 13530781719bSHans de Goede /* Don't log an error when called from regulator_get_optional() */ 13540781719bSHans de Goede } else if (!have_full_constraints() || exclusive) { 1355acc3d5ceSShuah Khan dev_warn(dev, "dummy supplies not allowed\n"); 135634abbd68SMark Brown } 135734abbd68SMark Brown 1358414c70cbSLiam Girdwood mutex_unlock(®ulator_list_mutex); 1359414c70cbSLiam Girdwood return regulator; 1360414c70cbSLiam Girdwood 1361414c70cbSLiam Girdwood found: 13625ffbd136SMark Brown if (rdev->exclusive) { 13635ffbd136SMark Brown regulator = ERR_PTR(-EPERM); 13645ffbd136SMark Brown goto out; 13655ffbd136SMark Brown } 13665ffbd136SMark Brown 13675ffbd136SMark Brown if (exclusive && rdev->open_count) { 13685ffbd136SMark Brown regulator = ERR_PTR(-EBUSY); 13695ffbd136SMark Brown goto out; 13705ffbd136SMark Brown } 13715ffbd136SMark Brown 1372a5766f11SLiam Girdwood if (!try_module_get(rdev->owner)) 1373a5766f11SLiam Girdwood goto out; 1374a5766f11SLiam Girdwood 1375414c70cbSLiam Girdwood regulator = create_regulator(rdev, dev, id); 1376414c70cbSLiam Girdwood if (regulator == NULL) { 1377414c70cbSLiam Girdwood regulator = ERR_PTR(-ENOMEM); 1378414c70cbSLiam Girdwood module_put(rdev->owner); 1379bcda4321SAxel Lin goto out; 1380414c70cbSLiam Girdwood } 1381414c70cbSLiam Girdwood 13825ffbd136SMark Brown rdev->open_count++; 13835ffbd136SMark Brown if (exclusive) { 13845ffbd136SMark Brown rdev->exclusive = 1; 13855ffbd136SMark Brown 13865ffbd136SMark Brown ret = _regulator_is_enabled(rdev); 13875ffbd136SMark Brown if (ret > 0) 13885ffbd136SMark Brown rdev->use_count = 1; 13895ffbd136SMark Brown else 13905ffbd136SMark Brown rdev->use_count = 0; 13915ffbd136SMark Brown } 13925ffbd136SMark Brown 1393a5766f11SLiam Girdwood out: 1394414c70cbSLiam Girdwood mutex_unlock(®ulator_list_mutex); 13955ffbd136SMark Brown 1396414c70cbSLiam Girdwood return regulator; 1397414c70cbSLiam Girdwood } 13985ffbd136SMark Brown 13995ffbd136SMark Brown /** 14005ffbd136SMark Brown * regulator_get - lookup and obtain a reference to a regulator. 14015ffbd136SMark Brown * @dev: device for regulator "consumer" 14025ffbd136SMark Brown * @id: Supply name or regulator ID. 14035ffbd136SMark Brown * 14045ffbd136SMark Brown * Returns a struct regulator corresponding to the regulator producer, 14055ffbd136SMark Brown * or IS_ERR() condition containing errno. 14065ffbd136SMark Brown * 14075ffbd136SMark Brown * Use of supply names configured via regulator_set_device_supply() is 14085ffbd136SMark Brown * strongly encouraged. It is recommended that the supply name used 14095ffbd136SMark Brown * should match the name used for the supply and/or the relevant 14105ffbd136SMark Brown * device pins in the datasheet. 14115ffbd136SMark Brown */ 14125ffbd136SMark Brown struct regulator *regulator_get(struct device *dev, const char *id) 14135ffbd136SMark Brown { 14144ddfebd3SMark Brown return _regulator_get(dev, id, false, true); 14155ffbd136SMark Brown } 1416414c70cbSLiam Girdwood EXPORT_SYMBOL_GPL(regulator_get); 1417414c70cbSLiam Girdwood 1418070b9079SStephen Boyd /** 14195ffbd136SMark Brown * regulator_get_exclusive - obtain exclusive access to a regulator. 14205ffbd136SMark Brown * @dev: device for regulator "consumer" 14215ffbd136SMark Brown * @id: Supply name or regulator ID. 14225ffbd136SMark Brown * 14235ffbd136SMark Brown * Returns a struct regulator corresponding to the regulator producer, 14245ffbd136SMark Brown * or IS_ERR() condition containing errno. Other consumers will be 14255ffbd136SMark Brown * unable to obtain this reference is held and the use count for the 14265ffbd136SMark Brown * regulator will be initialised to reflect the current state of the 14275ffbd136SMark Brown * regulator. 14285ffbd136SMark Brown * 14295ffbd136SMark Brown * This is intended for use by consumers which cannot tolerate shared 14305ffbd136SMark Brown * use of the regulator such as those which need to force the 14315ffbd136SMark Brown * regulator off for correct operation of the hardware they are 14325ffbd136SMark Brown * controlling. 14335ffbd136SMark Brown * 14345ffbd136SMark Brown * Use of supply names configured via regulator_set_device_supply() is 14355ffbd136SMark Brown * strongly encouraged. It is recommended that the supply name used 14365ffbd136SMark Brown * should match the name used for the supply and/or the relevant 14375ffbd136SMark Brown * device pins in the datasheet. 14385ffbd136SMark Brown */ 14395ffbd136SMark Brown struct regulator *regulator_get_exclusive(struct device *dev, const char *id) 14405ffbd136SMark Brown { 14414ddfebd3SMark Brown return _regulator_get(dev, id, true, false); 14425ffbd136SMark Brown } 14435ffbd136SMark Brown EXPORT_SYMBOL_GPL(regulator_get_exclusive); 14445ffbd136SMark Brown 1445de1dd9fdSMark Brown /** 1446de1dd9fdSMark Brown * regulator_get_optional - obtain optional access to a regulator. 1447de1dd9fdSMark Brown * @dev: device for regulator "consumer" 1448de1dd9fdSMark Brown * @id: Supply name or regulator ID. 1449de1dd9fdSMark Brown * 1450de1dd9fdSMark Brown * Returns a struct regulator corresponding to the regulator producer, 1451de1dd9fdSMark Brown * or IS_ERR() condition containing errno. Other consumers will be 1452de1dd9fdSMark Brown * unable to obtain this reference is held and the use count for the 1453de1dd9fdSMark Brown * regulator will be initialised to reflect the current state of the 1454de1dd9fdSMark Brown * regulator. 1455de1dd9fdSMark Brown * 1456de1dd9fdSMark Brown * This is intended for use by consumers for devices which can have 1457de1dd9fdSMark Brown * some supplies unconnected in normal use, such as some MMC devices. 1458de1dd9fdSMark Brown * It can allow the regulator core to provide stub supplies for other 1459de1dd9fdSMark Brown * supplies requested using normal regulator_get() calls without 1460de1dd9fdSMark Brown * disrupting the operation of drivers that can handle absent 1461de1dd9fdSMark Brown * supplies. 1462de1dd9fdSMark Brown * 1463de1dd9fdSMark Brown * Use of supply names configured via regulator_set_device_supply() is 1464de1dd9fdSMark Brown * strongly encouraged. It is recommended that the supply name used 1465de1dd9fdSMark Brown * should match the name used for the supply and/or the relevant 1466de1dd9fdSMark Brown * device pins in the datasheet. 1467de1dd9fdSMark Brown */ 1468de1dd9fdSMark Brown struct regulator *regulator_get_optional(struct device *dev, const char *id) 1469de1dd9fdSMark Brown { 14704ddfebd3SMark Brown return _regulator_get(dev, id, false, false); 1471de1dd9fdSMark Brown } 1472de1dd9fdSMark Brown EXPORT_SYMBOL_GPL(regulator_get_optional); 1473de1dd9fdSMark Brown 147423ff2f0fSCharles Keepax /* Locks held by regulator_put() */ 147523ff2f0fSCharles Keepax static void _regulator_put(struct regulator *regulator) 1476414c70cbSLiam Girdwood { 1477414c70cbSLiam Girdwood struct regulator_dev *rdev; 1478414c70cbSLiam Girdwood 1479414c70cbSLiam Girdwood if (regulator == NULL || IS_ERR(regulator)) 1480414c70cbSLiam Girdwood return; 1481414c70cbSLiam Girdwood 1482414c70cbSLiam Girdwood rdev = regulator->rdev; 1483414c70cbSLiam Girdwood 14845de70519SMark Brown debugfs_remove_recursive(regulator->debugfs); 14855de70519SMark Brown 1486414c70cbSLiam Girdwood /* remove any sysfs entries */ 1487e2c98eafSShawn Guo if (regulator->dev) 1488414c70cbSLiam Girdwood sysfs_remove_link(&rdev->dev.kobj, regulator->supply_name); 14895de70519SMark Brown kfree(regulator->supply_name); 1490414c70cbSLiam Girdwood list_del(®ulator->list); 1491414c70cbSLiam Girdwood kfree(regulator); 1492414c70cbSLiam Girdwood 14935ffbd136SMark Brown rdev->open_count--; 14945ffbd136SMark Brown rdev->exclusive = 0; 14955ffbd136SMark Brown 1496414c70cbSLiam Girdwood module_put(rdev->owner); 149723ff2f0fSCharles Keepax } 149823ff2f0fSCharles Keepax 149923ff2f0fSCharles Keepax /** 150023ff2f0fSCharles Keepax * regulator_put - "free" the regulator source 150123ff2f0fSCharles Keepax * @regulator: regulator source 150223ff2f0fSCharles Keepax * 150323ff2f0fSCharles Keepax * Note: drivers must ensure that all regulator_enable calls made on this 150423ff2f0fSCharles Keepax * regulator source are balanced by regulator_disable calls prior to calling 150523ff2f0fSCharles Keepax * this function. 150623ff2f0fSCharles Keepax */ 150723ff2f0fSCharles Keepax void regulator_put(struct regulator *regulator) 150823ff2f0fSCharles Keepax { 150923ff2f0fSCharles Keepax mutex_lock(®ulator_list_mutex); 151023ff2f0fSCharles Keepax _regulator_put(regulator); 1511414c70cbSLiam Girdwood mutex_unlock(®ulator_list_mutex); 1512414c70cbSLiam Girdwood } 1513414c70cbSLiam Girdwood EXPORT_SYMBOL_GPL(regulator_put); 1514414c70cbSLiam Girdwood 1515a06ccd9cSCharles Keepax /** 1516a06ccd9cSCharles Keepax * regulator_register_supply_alias - Provide device alias for supply lookup 1517a06ccd9cSCharles Keepax * 1518a06ccd9cSCharles Keepax * @dev: device that will be given as the regulator "consumer" 1519a06ccd9cSCharles Keepax * @id: Supply name or regulator ID 1520a06ccd9cSCharles Keepax * @alias_dev: device that should be used to lookup the supply 1521a06ccd9cSCharles Keepax * @alias_id: Supply name or regulator ID that should be used to lookup the 1522a06ccd9cSCharles Keepax * supply 1523a06ccd9cSCharles Keepax * 1524a06ccd9cSCharles Keepax * All lookups for id on dev will instead be conducted for alias_id on 1525a06ccd9cSCharles Keepax * alias_dev. 1526a06ccd9cSCharles Keepax */ 1527a06ccd9cSCharles Keepax int regulator_register_supply_alias(struct device *dev, const char *id, 1528a06ccd9cSCharles Keepax struct device *alias_dev, 1529a06ccd9cSCharles Keepax const char *alias_id) 1530a06ccd9cSCharles Keepax { 1531a06ccd9cSCharles Keepax struct regulator_supply_alias *map; 1532a06ccd9cSCharles Keepax 1533a06ccd9cSCharles Keepax map = regulator_find_supply_alias(dev, id); 1534a06ccd9cSCharles Keepax if (map) 1535a06ccd9cSCharles Keepax return -EEXIST; 1536a06ccd9cSCharles Keepax 1537a06ccd9cSCharles Keepax map = kzalloc(sizeof(struct regulator_supply_alias), GFP_KERNEL); 1538a06ccd9cSCharles Keepax if (!map) 1539a06ccd9cSCharles Keepax return -ENOMEM; 1540a06ccd9cSCharles Keepax 1541a06ccd9cSCharles Keepax map->src_dev = dev; 1542a06ccd9cSCharles Keepax map->src_supply = id; 1543a06ccd9cSCharles Keepax map->alias_dev = alias_dev; 1544a06ccd9cSCharles Keepax map->alias_supply = alias_id; 1545a06ccd9cSCharles Keepax 1546a06ccd9cSCharles Keepax list_add(&map->list, ®ulator_supply_alias_list); 1547a06ccd9cSCharles Keepax 1548a06ccd9cSCharles Keepax pr_info("Adding alias for supply %s,%s -> %s,%s\n", 1549a06ccd9cSCharles Keepax id, dev_name(dev), alias_id, dev_name(alias_dev)); 1550a06ccd9cSCharles Keepax 1551a06ccd9cSCharles Keepax return 0; 1552a06ccd9cSCharles Keepax } 1553a06ccd9cSCharles Keepax EXPORT_SYMBOL_GPL(regulator_register_supply_alias); 1554a06ccd9cSCharles Keepax 1555a06ccd9cSCharles Keepax /** 1556a06ccd9cSCharles Keepax * regulator_unregister_supply_alias - Remove device alias 1557a06ccd9cSCharles Keepax * 1558a06ccd9cSCharles Keepax * @dev: device that will be given as the regulator "consumer" 1559a06ccd9cSCharles Keepax * @id: Supply name or regulator ID 1560a06ccd9cSCharles Keepax * 1561a06ccd9cSCharles Keepax * Remove a lookup alias if one exists for id on dev. 1562a06ccd9cSCharles Keepax */ 1563a06ccd9cSCharles Keepax void regulator_unregister_supply_alias(struct device *dev, const char *id) 1564a06ccd9cSCharles Keepax { 1565a06ccd9cSCharles Keepax struct regulator_supply_alias *map; 1566a06ccd9cSCharles Keepax 1567a06ccd9cSCharles Keepax map = regulator_find_supply_alias(dev, id); 1568a06ccd9cSCharles Keepax if (map) { 1569a06ccd9cSCharles Keepax list_del(&map->list); 1570a06ccd9cSCharles Keepax kfree(map); 1571a06ccd9cSCharles Keepax } 1572a06ccd9cSCharles Keepax } 1573a06ccd9cSCharles Keepax EXPORT_SYMBOL_GPL(regulator_unregister_supply_alias); 1574a06ccd9cSCharles Keepax 1575a06ccd9cSCharles Keepax /** 1576a06ccd9cSCharles Keepax * regulator_bulk_register_supply_alias - register multiple aliases 1577a06ccd9cSCharles Keepax * 1578a06ccd9cSCharles Keepax * @dev: device that will be given as the regulator "consumer" 1579a06ccd9cSCharles Keepax * @id: List of supply names or regulator IDs 1580a06ccd9cSCharles Keepax * @alias_dev: device that should be used to lookup the supply 1581a06ccd9cSCharles Keepax * @alias_id: List of supply names or regulator IDs that should be used to 1582a06ccd9cSCharles Keepax * lookup the supply 1583a06ccd9cSCharles Keepax * @num_id: Number of aliases to register 1584a06ccd9cSCharles Keepax * 1585a06ccd9cSCharles Keepax * @return 0 on success, an errno on failure. 1586a06ccd9cSCharles Keepax * 1587a06ccd9cSCharles Keepax * This helper function allows drivers to register several supply 1588a06ccd9cSCharles Keepax * aliases in one operation. If any of the aliases cannot be 1589a06ccd9cSCharles Keepax * registered any aliases that were registered will be removed 1590a06ccd9cSCharles Keepax * before returning to the caller. 1591a06ccd9cSCharles Keepax */ 1592a06ccd9cSCharles Keepax int regulator_bulk_register_supply_alias(struct device *dev, const char **id, 1593a06ccd9cSCharles Keepax struct device *alias_dev, 1594a06ccd9cSCharles Keepax const char **alias_id, 1595a06ccd9cSCharles Keepax int num_id) 1596a06ccd9cSCharles Keepax { 1597a06ccd9cSCharles Keepax int i; 1598a06ccd9cSCharles Keepax int ret; 1599a06ccd9cSCharles Keepax 1600a06ccd9cSCharles Keepax for (i = 0; i < num_id; ++i) { 1601a06ccd9cSCharles Keepax ret = regulator_register_supply_alias(dev, id[i], alias_dev, 1602a06ccd9cSCharles Keepax alias_id[i]); 1603a06ccd9cSCharles Keepax if (ret < 0) 1604a06ccd9cSCharles Keepax goto err; 1605a06ccd9cSCharles Keepax } 1606a06ccd9cSCharles Keepax 1607a06ccd9cSCharles Keepax return 0; 1608a06ccd9cSCharles Keepax 1609a06ccd9cSCharles Keepax err: 1610a06ccd9cSCharles Keepax dev_err(dev, 1611a06ccd9cSCharles Keepax "Failed to create supply alias %s,%s -> %s,%s\n", 1612a06ccd9cSCharles Keepax id[i], dev_name(dev), alias_id[i], dev_name(alias_dev)); 1613a06ccd9cSCharles Keepax 1614a06ccd9cSCharles Keepax while (--i >= 0) 1615a06ccd9cSCharles Keepax regulator_unregister_supply_alias(dev, id[i]); 1616a06ccd9cSCharles Keepax 1617a06ccd9cSCharles Keepax return ret; 1618a06ccd9cSCharles Keepax } 1619a06ccd9cSCharles Keepax EXPORT_SYMBOL_GPL(regulator_bulk_register_supply_alias); 1620a06ccd9cSCharles Keepax 1621a06ccd9cSCharles Keepax /** 1622a06ccd9cSCharles Keepax * regulator_bulk_unregister_supply_alias - unregister multiple aliases 1623a06ccd9cSCharles Keepax * 1624a06ccd9cSCharles Keepax * @dev: device that will be given as the regulator "consumer" 1625a06ccd9cSCharles Keepax * @id: List of supply names or regulator IDs 1626a06ccd9cSCharles Keepax * @num_id: Number of aliases to unregister 1627a06ccd9cSCharles Keepax * 1628a06ccd9cSCharles Keepax * This helper function allows drivers to unregister several supply 1629a06ccd9cSCharles Keepax * aliases in one operation. 1630a06ccd9cSCharles Keepax */ 1631a06ccd9cSCharles Keepax void regulator_bulk_unregister_supply_alias(struct device *dev, 1632a06ccd9cSCharles Keepax const char **id, 1633a06ccd9cSCharles Keepax int num_id) 1634a06ccd9cSCharles Keepax { 1635a06ccd9cSCharles Keepax int i; 1636a06ccd9cSCharles Keepax 1637a06ccd9cSCharles Keepax for (i = 0; i < num_id; ++i) 1638a06ccd9cSCharles Keepax regulator_unregister_supply_alias(dev, id[i]); 1639a06ccd9cSCharles Keepax } 1640a06ccd9cSCharles Keepax EXPORT_SYMBOL_GPL(regulator_bulk_unregister_supply_alias); 1641a06ccd9cSCharles Keepax 1642a06ccd9cSCharles Keepax 1643f19b00daSKim, Milo /* Manage enable GPIO list. Same GPIO pin can be shared among regulators */ 1644f19b00daSKim, Milo static int regulator_ena_gpio_request(struct regulator_dev *rdev, 1645f19b00daSKim, Milo const struct regulator_config *config) 1646f19b00daSKim, Milo { 1647f19b00daSKim, Milo struct regulator_enable_gpio *pin; 1648f19b00daSKim, Milo int ret; 1649f19b00daSKim, Milo 1650f19b00daSKim, Milo list_for_each_entry(pin, ®ulator_ena_gpio_list, list) { 1651f19b00daSKim, Milo if (pin->gpio == config->ena_gpio) { 1652f19b00daSKim, Milo rdev_dbg(rdev, "GPIO %d is already used\n", 1653f19b00daSKim, Milo config->ena_gpio); 1654f19b00daSKim, Milo goto update_ena_gpio_to_rdev; 1655f19b00daSKim, Milo } 1656f19b00daSKim, Milo } 1657f19b00daSKim, Milo 1658f19b00daSKim, Milo ret = gpio_request_one(config->ena_gpio, 1659f19b00daSKim, Milo GPIOF_DIR_OUT | config->ena_gpio_flags, 1660f19b00daSKim, Milo rdev_get_name(rdev)); 1661f19b00daSKim, Milo if (ret) 1662f19b00daSKim, Milo return ret; 1663f19b00daSKim, Milo 1664f19b00daSKim, Milo pin = kzalloc(sizeof(struct regulator_enable_gpio), GFP_KERNEL); 1665f19b00daSKim, Milo if (pin == NULL) { 1666f19b00daSKim, Milo gpio_free(config->ena_gpio); 1667f19b00daSKim, Milo return -ENOMEM; 1668f19b00daSKim, Milo } 1669f19b00daSKim, Milo 1670f19b00daSKim, Milo pin->gpio = config->ena_gpio; 1671f19b00daSKim, Milo pin->ena_gpio_invert = config->ena_gpio_invert; 1672f19b00daSKim, Milo list_add(&pin->list, ®ulator_ena_gpio_list); 1673f19b00daSKim, Milo 1674f19b00daSKim, Milo update_ena_gpio_to_rdev: 1675f19b00daSKim, Milo pin->request_count++; 1676f19b00daSKim, Milo rdev->ena_pin = pin; 1677f19b00daSKim, Milo return 0; 1678f19b00daSKim, Milo } 1679f19b00daSKim, Milo 1680f19b00daSKim, Milo static void regulator_ena_gpio_free(struct regulator_dev *rdev) 1681f19b00daSKim, Milo { 1682f19b00daSKim, Milo struct regulator_enable_gpio *pin, *n; 1683f19b00daSKim, Milo 1684f19b00daSKim, Milo if (!rdev->ena_pin) 1685f19b00daSKim, Milo return; 1686f19b00daSKim, Milo 1687f19b00daSKim, Milo /* Free the GPIO only in case of no use */ 1688f19b00daSKim, Milo list_for_each_entry_safe(pin, n, ®ulator_ena_gpio_list, list) { 1689f19b00daSKim, Milo if (pin->gpio == rdev->ena_pin->gpio) { 1690f19b00daSKim, Milo if (pin->request_count <= 1) { 1691f19b00daSKim, Milo pin->request_count = 0; 1692f19b00daSKim, Milo gpio_free(pin->gpio); 1693f19b00daSKim, Milo list_del(&pin->list); 1694f19b00daSKim, Milo kfree(pin); 1695f19b00daSKim, Milo } else { 1696f19b00daSKim, Milo pin->request_count--; 1697f19b00daSKim, Milo } 1698f19b00daSKim, Milo } 1699f19b00daSKim, Milo } 1700f19b00daSKim, Milo } 1701f19b00daSKim, Milo 1702967cfb18SKim, Milo /** 170331d6eebfSRobert P. J. Day * regulator_ena_gpio_ctrl - balance enable_count of each GPIO and actual GPIO pin control 170431d6eebfSRobert P. J. Day * @rdev: regulator_dev structure 170531d6eebfSRobert P. J. Day * @enable: enable GPIO at initial use? 170631d6eebfSRobert P. J. Day * 1707967cfb18SKim, Milo * GPIO is enabled in case of initial use. (enable_count is 0) 1708967cfb18SKim, Milo * GPIO is disabled when it is not shared any more. (enable_count <= 1) 1709967cfb18SKim, Milo */ 1710967cfb18SKim, Milo static int regulator_ena_gpio_ctrl(struct regulator_dev *rdev, bool enable) 1711967cfb18SKim, Milo { 1712967cfb18SKim, Milo struct regulator_enable_gpio *pin = rdev->ena_pin; 1713967cfb18SKim, Milo 1714967cfb18SKim, Milo if (!pin) 1715967cfb18SKim, Milo return -EINVAL; 1716967cfb18SKim, Milo 1717967cfb18SKim, Milo if (enable) { 1718967cfb18SKim, Milo /* Enable GPIO at initial use */ 1719967cfb18SKim, Milo if (pin->enable_count == 0) 1720967cfb18SKim, Milo gpio_set_value_cansleep(pin->gpio, 1721967cfb18SKim, Milo !pin->ena_gpio_invert); 1722967cfb18SKim, Milo 1723967cfb18SKim, Milo pin->enable_count++; 1724967cfb18SKim, Milo } else { 1725967cfb18SKim, Milo if (pin->enable_count > 1) { 1726967cfb18SKim, Milo pin->enable_count--; 1727967cfb18SKim, Milo return 0; 1728967cfb18SKim, Milo } 1729967cfb18SKim, Milo 1730967cfb18SKim, Milo /* Disable GPIO if not used */ 1731967cfb18SKim, Milo if (pin->enable_count <= 1) { 1732967cfb18SKim, Milo gpio_set_value_cansleep(pin->gpio, 1733967cfb18SKim, Milo pin->ena_gpio_invert); 1734967cfb18SKim, Milo pin->enable_count = 0; 1735967cfb18SKim, Milo } 1736967cfb18SKim, Milo } 1737967cfb18SKim, Milo 1738967cfb18SKim, Milo return 0; 1739967cfb18SKim, Milo } 1740967cfb18SKim, Milo 17415c5659d0SMark Brown static int _regulator_do_enable(struct regulator_dev *rdev) 17425c5659d0SMark Brown { 17435c5659d0SMark Brown int ret, delay; 17445c5659d0SMark Brown 17455c5659d0SMark Brown /* Query before enabling in case configuration dependent. */ 17465c5659d0SMark Brown ret = _regulator_get_enable_time(rdev); 17475c5659d0SMark Brown if (ret >= 0) { 17485c5659d0SMark Brown delay = ret; 17495c5659d0SMark Brown } else { 17505c5659d0SMark Brown rdev_warn(rdev, "enable_time() failed: %d\n", ret); 17515c5659d0SMark Brown delay = 0; 17525c5659d0SMark Brown } 17535c5659d0SMark Brown 17545c5659d0SMark Brown trace_regulator_enable(rdev_get_name(rdev)); 17555c5659d0SMark Brown 1756967cfb18SKim, Milo if (rdev->ena_pin) { 1757967cfb18SKim, Milo ret = regulator_ena_gpio_ctrl(rdev, true); 1758967cfb18SKim, Milo if (ret < 0) 1759967cfb18SKim, Milo return ret; 176065f73508SMark Brown rdev->ena_gpio_state = 1; 176165f73508SMark Brown } else if (rdev->desc->ops->enable) { 17625c5659d0SMark Brown ret = rdev->desc->ops->enable(rdev); 17635c5659d0SMark Brown if (ret < 0) 17645c5659d0SMark Brown return ret; 17655c5659d0SMark Brown } else { 17665c5659d0SMark Brown return -EINVAL; 17675c5659d0SMark Brown } 17685c5659d0SMark Brown 17695c5659d0SMark Brown /* Allow the regulator to ramp; it would be useful to extend 17705c5659d0SMark Brown * this for bulk operations so that the regulators can ramp 17715c5659d0SMark Brown * together. */ 17725c5659d0SMark Brown trace_regulator_enable_delay(rdev_get_name(rdev)); 17735c5659d0SMark Brown 17745df529d4SThierry Reding /* 17755df529d4SThierry Reding * Delay for the requested amount of time as per the guidelines in: 17765df529d4SThierry Reding * 17775df529d4SThierry Reding * Documentation/timers/timers-howto.txt 17785df529d4SThierry Reding * 17795df529d4SThierry Reding * The assumption here is that regulators will never be enabled in 17805df529d4SThierry Reding * atomic context and therefore sleeping functions can be used. 17815df529d4SThierry Reding */ 17825df529d4SThierry Reding if (delay) { 17835df529d4SThierry Reding unsigned int ms = delay / 1000; 17845df529d4SThierry Reding unsigned int us = delay % 1000; 17855df529d4SThierry Reding 17865df529d4SThierry Reding if (ms > 0) { 17875df529d4SThierry Reding /* 17885df529d4SThierry Reding * For small enough values, handle super-millisecond 17895df529d4SThierry Reding * delays in the usleep_range() call below. 17905df529d4SThierry Reding */ 17915df529d4SThierry Reding if (ms < 20) 17925df529d4SThierry Reding us += ms * 1000; 17935df529d4SThierry Reding else 17945df529d4SThierry Reding msleep(ms); 17955df529d4SThierry Reding } 17965df529d4SThierry Reding 17975df529d4SThierry Reding /* 17985df529d4SThierry Reding * Give the scheduler some room to coalesce with any other 17995df529d4SThierry Reding * wakeup sources. For delays shorter than 10 us, don't even 18005df529d4SThierry Reding * bother setting up high-resolution timers and just busy- 18015df529d4SThierry Reding * loop. 18025df529d4SThierry Reding */ 18035df529d4SThierry Reding if (us >= 10) 18045df529d4SThierry Reding usleep_range(us, us + 100); 18055df529d4SThierry Reding else 18065df529d4SThierry Reding udelay(us); 18075c5659d0SMark Brown } 18085c5659d0SMark Brown 18095c5659d0SMark Brown trace_regulator_enable_complete(rdev_get_name(rdev)); 18105c5659d0SMark Brown 18115c5659d0SMark Brown return 0; 18125c5659d0SMark Brown } 18135c5659d0SMark Brown 1814414c70cbSLiam Girdwood /* locks held by regulator_enable() */ 1815414c70cbSLiam Girdwood static int _regulator_enable(struct regulator_dev *rdev) 1816414c70cbSLiam Girdwood { 18175c5659d0SMark Brown int ret; 1818414c70cbSLiam Girdwood 1819414c70cbSLiam Girdwood /* check voltage and requested load before enabling */ 1820414c70cbSLiam Girdwood if (rdev->constraints && 18219a2372faSMark Brown (rdev->constraints->valid_ops_mask & REGULATOR_CHANGE_DRMS)) 1822414c70cbSLiam Girdwood drms_uA_update(rdev); 1823414c70cbSLiam Girdwood 18249a2372faSMark Brown if (rdev->use_count == 0) { 18259a2372faSMark Brown /* The regulator may on if it's not switchable or left on */ 18269a2372faSMark Brown ret = _regulator_is_enabled(rdev); 18279a2372faSMark Brown if (ret == -EINVAL || ret == 0) { 18289a2372faSMark Brown if (!_regulator_can_change_status(rdev)) 18299a2372faSMark Brown return -EPERM; 18309a2372faSMark Brown 18315c5659d0SMark Brown ret = _regulator_do_enable(rdev); 18329a2372faSMark Brown if (ret < 0) 18339a2372faSMark Brown return ret; 183431aae2beSMark Brown 1835a7433cffSLinus Walleij } else if (ret < 0) { 18365da84fd9SJoe Perches rdev_err(rdev, "is_enabled() failed: %d\n", ret); 1837414c70cbSLiam Girdwood return ret; 1838414c70cbSLiam Girdwood } 1839a7433cffSLinus Walleij /* Fallthrough on positive return values - already enabled */ 1840414c70cbSLiam Girdwood } 1841414c70cbSLiam Girdwood 18429a2372faSMark Brown rdev->use_count++; 18439a2372faSMark Brown 18449a2372faSMark Brown return 0; 1845414c70cbSLiam Girdwood } 1846414c70cbSLiam Girdwood 1847414c70cbSLiam Girdwood /** 1848414c70cbSLiam Girdwood * regulator_enable - enable regulator output 1849414c70cbSLiam Girdwood * @regulator: regulator source 1850414c70cbSLiam Girdwood * 1851cf7bbcdfSMark Brown * Request that the regulator be enabled with the regulator output at 1852cf7bbcdfSMark Brown * the predefined voltage or current value. Calls to regulator_enable() 1853cf7bbcdfSMark Brown * must be balanced with calls to regulator_disable(). 1854cf7bbcdfSMark Brown * 1855414c70cbSLiam Girdwood * NOTE: the output value can be set by other drivers, boot loader or may be 1856cf7bbcdfSMark Brown * hardwired in the regulator. 1857414c70cbSLiam Girdwood */ 1858414c70cbSLiam Girdwood int regulator_enable(struct regulator *regulator) 1859414c70cbSLiam Girdwood { 1860412aec61SDavid Brownell struct regulator_dev *rdev = regulator->rdev; 1861412aec61SDavid Brownell int ret = 0; 1862414c70cbSLiam Girdwood 18636492bc1bSMark Brown if (regulator->always_on) 18646492bc1bSMark Brown return 0; 18656492bc1bSMark Brown 18663801b86aSMark Brown if (rdev->supply) { 18673801b86aSMark Brown ret = regulator_enable(rdev->supply); 18683801b86aSMark Brown if (ret != 0) 18693801b86aSMark Brown return ret; 18703801b86aSMark Brown } 18713801b86aSMark Brown 1872412aec61SDavid Brownell mutex_lock(&rdev->mutex); 1873412aec61SDavid Brownell ret = _regulator_enable(rdev); 1874412aec61SDavid Brownell mutex_unlock(&rdev->mutex); 18753801b86aSMark Brown 1876d1685e4eSHeiko Stübner if (ret != 0 && rdev->supply) 18773801b86aSMark Brown regulator_disable(rdev->supply); 18783801b86aSMark Brown 1879414c70cbSLiam Girdwood return ret; 1880414c70cbSLiam Girdwood } 1881414c70cbSLiam Girdwood EXPORT_SYMBOL_GPL(regulator_enable); 1882414c70cbSLiam Girdwood 18835c5659d0SMark Brown static int _regulator_do_disable(struct regulator_dev *rdev) 18845c5659d0SMark Brown { 18855c5659d0SMark Brown int ret; 18865c5659d0SMark Brown 18875c5659d0SMark Brown trace_regulator_disable(rdev_get_name(rdev)); 18885c5659d0SMark Brown 1889967cfb18SKim, Milo if (rdev->ena_pin) { 1890967cfb18SKim, Milo ret = regulator_ena_gpio_ctrl(rdev, false); 1891967cfb18SKim, Milo if (ret < 0) 1892967cfb18SKim, Milo return ret; 18935c5659d0SMark Brown rdev->ena_gpio_state = 0; 18945c5659d0SMark Brown 18955c5659d0SMark Brown } else if (rdev->desc->ops->disable) { 18965c5659d0SMark Brown ret = rdev->desc->ops->disable(rdev); 18975c5659d0SMark Brown if (ret != 0) 18985c5659d0SMark Brown return ret; 18995c5659d0SMark Brown } 19005c5659d0SMark Brown 19015c5659d0SMark Brown trace_regulator_disable_complete(rdev_get_name(rdev)); 19025c5659d0SMark Brown 19035c5659d0SMark Brown _notifier_call_chain(rdev, REGULATOR_EVENT_DISABLE, 19045c5659d0SMark Brown NULL); 19055c5659d0SMark Brown return 0; 19065c5659d0SMark Brown } 19075c5659d0SMark Brown 1908414c70cbSLiam Girdwood /* locks held by regulator_disable() */ 19093801b86aSMark Brown static int _regulator_disable(struct regulator_dev *rdev) 1910414c70cbSLiam Girdwood { 1911414c70cbSLiam Girdwood int ret = 0; 1912414c70cbSLiam Girdwood 1913cd94b505SDavid Brownell if (WARN(rdev->use_count <= 0, 191443e7ee33SJoe Perches "unbalanced disables for %s\n", rdev_get_name(rdev))) 1915cd94b505SDavid Brownell return -EIO; 1916cd94b505SDavid Brownell 1917414c70cbSLiam Girdwood /* are we the last user and permitted to disable ? */ 191860ef66fcSMark Brown if (rdev->use_count == 1 && 191960ef66fcSMark Brown (rdev->constraints && !rdev->constraints->always_on)) { 1920414c70cbSLiam Girdwood 1921414c70cbSLiam Girdwood /* we are last user */ 19225c5659d0SMark Brown if (_regulator_can_change_status(rdev)) { 19235c5659d0SMark Brown ret = _regulator_do_disable(rdev); 1924414c70cbSLiam Girdwood if (ret < 0) { 19255da84fd9SJoe Perches rdev_err(rdev, "failed to disable\n"); 1926414c70cbSLiam Girdwood return ret; 1927414c70cbSLiam Girdwood } 1928414c70cbSLiam Girdwood } 1929414c70cbSLiam Girdwood 1930414c70cbSLiam Girdwood rdev->use_count = 0; 1931414c70cbSLiam Girdwood } else if (rdev->use_count > 1) { 1932414c70cbSLiam Girdwood 1933414c70cbSLiam Girdwood if (rdev->constraints && 1934414c70cbSLiam Girdwood (rdev->constraints->valid_ops_mask & 1935414c70cbSLiam Girdwood REGULATOR_CHANGE_DRMS)) 1936414c70cbSLiam Girdwood drms_uA_update(rdev); 1937414c70cbSLiam Girdwood 1938414c70cbSLiam Girdwood rdev->use_count--; 1939414c70cbSLiam Girdwood } 19403801b86aSMark Brown 1941414c70cbSLiam Girdwood return ret; 1942414c70cbSLiam Girdwood } 1943414c70cbSLiam Girdwood 1944414c70cbSLiam Girdwood /** 1945414c70cbSLiam Girdwood * regulator_disable - disable regulator output 1946414c70cbSLiam Girdwood * @regulator: regulator source 1947414c70cbSLiam Girdwood * 1948cf7bbcdfSMark Brown * Disable the regulator output voltage or current. Calls to 1949cf7bbcdfSMark Brown * regulator_enable() must be balanced with calls to 1950cf7bbcdfSMark Brown * regulator_disable(). 195169279fb9SMark Brown * 1952414c70cbSLiam Girdwood * NOTE: this will only disable the regulator output if no other consumer 1953cf7bbcdfSMark Brown * devices have it enabled, the regulator device supports disabling and 1954cf7bbcdfSMark Brown * machine constraints permit this operation. 1955414c70cbSLiam Girdwood */ 1956414c70cbSLiam Girdwood int regulator_disable(struct regulator *regulator) 1957414c70cbSLiam Girdwood { 1958412aec61SDavid Brownell struct regulator_dev *rdev = regulator->rdev; 1959412aec61SDavid Brownell int ret = 0; 1960414c70cbSLiam Girdwood 19616492bc1bSMark Brown if (regulator->always_on) 19626492bc1bSMark Brown return 0; 19636492bc1bSMark Brown 1964412aec61SDavid Brownell mutex_lock(&rdev->mutex); 19653801b86aSMark Brown ret = _regulator_disable(rdev); 1966412aec61SDavid Brownell mutex_unlock(&rdev->mutex); 19678cbf811dSJeffrey Carlyle 19683801b86aSMark Brown if (ret == 0 && rdev->supply) 19693801b86aSMark Brown regulator_disable(rdev->supply); 19708cbf811dSJeffrey Carlyle 1971414c70cbSLiam Girdwood return ret; 1972414c70cbSLiam Girdwood } 1973414c70cbSLiam Girdwood EXPORT_SYMBOL_GPL(regulator_disable); 1974414c70cbSLiam Girdwood 1975414c70cbSLiam Girdwood /* locks held by regulator_force_disable() */ 19763801b86aSMark Brown static int _regulator_force_disable(struct regulator_dev *rdev) 1977414c70cbSLiam Girdwood { 1978414c70cbSLiam Girdwood int ret = 0; 1979414c70cbSLiam Girdwood 1980414c70cbSLiam Girdwood /* force disable */ 1981414c70cbSLiam Girdwood if (rdev->desc->ops->disable) { 1982414c70cbSLiam Girdwood /* ah well, who wants to live forever... */ 1983414c70cbSLiam Girdwood ret = rdev->desc->ops->disable(rdev); 1984414c70cbSLiam Girdwood if (ret < 0) { 19855da84fd9SJoe Perches rdev_err(rdev, "failed to force disable\n"); 1986414c70cbSLiam Girdwood return ret; 1987414c70cbSLiam Girdwood } 1988414c70cbSLiam Girdwood /* notify other consumers that power has been forced off */ 198984b68263SMark Brown _notifier_call_chain(rdev, REGULATOR_EVENT_FORCE_DISABLE | 199084b68263SMark Brown REGULATOR_EVENT_DISABLE, NULL); 1991414c70cbSLiam Girdwood } 1992414c70cbSLiam Girdwood 1993414c70cbSLiam Girdwood return ret; 1994414c70cbSLiam Girdwood } 1995414c70cbSLiam Girdwood 1996414c70cbSLiam Girdwood /** 1997414c70cbSLiam Girdwood * regulator_force_disable - force disable regulator output 1998414c70cbSLiam Girdwood * @regulator: regulator source 1999414c70cbSLiam Girdwood * 2000414c70cbSLiam Girdwood * Forcibly disable the regulator output voltage or current. 2001414c70cbSLiam Girdwood * NOTE: this *will* disable the regulator output even if other consumer 2002414c70cbSLiam Girdwood * devices have it enabled. This should be used for situations when device 2003414c70cbSLiam Girdwood * damage will likely occur if the regulator is not disabled (e.g. over temp). 2004414c70cbSLiam Girdwood */ 2005414c70cbSLiam Girdwood int regulator_force_disable(struct regulator *regulator) 2006414c70cbSLiam Girdwood { 200782d15839SMark Brown struct regulator_dev *rdev = regulator->rdev; 2008414c70cbSLiam Girdwood int ret; 2009414c70cbSLiam Girdwood 201082d15839SMark Brown mutex_lock(&rdev->mutex); 2011414c70cbSLiam Girdwood regulator->uA_load = 0; 20123801b86aSMark Brown ret = _regulator_force_disable(regulator->rdev); 201382d15839SMark Brown mutex_unlock(&rdev->mutex); 20148cbf811dSJeffrey Carlyle 20153801b86aSMark Brown if (rdev->supply) 20163801b86aSMark Brown while (rdev->open_count--) 20173801b86aSMark Brown regulator_disable(rdev->supply); 20188cbf811dSJeffrey Carlyle 2019414c70cbSLiam Girdwood return ret; 2020414c70cbSLiam Girdwood } 2021414c70cbSLiam Girdwood EXPORT_SYMBOL_GPL(regulator_force_disable); 2022414c70cbSLiam Girdwood 2023da07ecd9SMark Brown static void regulator_disable_work(struct work_struct *work) 2024da07ecd9SMark Brown { 2025da07ecd9SMark Brown struct regulator_dev *rdev = container_of(work, struct regulator_dev, 2026da07ecd9SMark Brown disable_work.work); 2027da07ecd9SMark Brown int count, i, ret; 2028da07ecd9SMark Brown 2029da07ecd9SMark Brown mutex_lock(&rdev->mutex); 2030da07ecd9SMark Brown 2031da07ecd9SMark Brown BUG_ON(!rdev->deferred_disables); 2032da07ecd9SMark Brown 2033da07ecd9SMark Brown count = rdev->deferred_disables; 2034da07ecd9SMark Brown rdev->deferred_disables = 0; 2035da07ecd9SMark Brown 2036da07ecd9SMark Brown for (i = 0; i < count; i++) { 2037da07ecd9SMark Brown ret = _regulator_disable(rdev); 2038da07ecd9SMark Brown if (ret != 0) 2039da07ecd9SMark Brown rdev_err(rdev, "Deferred disable failed: %d\n", ret); 2040da07ecd9SMark Brown } 2041da07ecd9SMark Brown 2042da07ecd9SMark Brown mutex_unlock(&rdev->mutex); 2043da07ecd9SMark Brown 2044da07ecd9SMark Brown if (rdev->supply) { 2045da07ecd9SMark Brown for (i = 0; i < count; i++) { 2046da07ecd9SMark Brown ret = regulator_disable(rdev->supply); 2047da07ecd9SMark Brown if (ret != 0) { 2048da07ecd9SMark Brown rdev_err(rdev, 2049da07ecd9SMark Brown "Supply disable failed: %d\n", ret); 2050da07ecd9SMark Brown } 2051da07ecd9SMark Brown } 2052da07ecd9SMark Brown } 2053da07ecd9SMark Brown } 2054da07ecd9SMark Brown 2055da07ecd9SMark Brown /** 2056da07ecd9SMark Brown * regulator_disable_deferred - disable regulator output with delay 2057da07ecd9SMark Brown * @regulator: regulator source 2058da07ecd9SMark Brown * @ms: miliseconds until the regulator is disabled 2059da07ecd9SMark Brown * 2060da07ecd9SMark Brown * Execute regulator_disable() on the regulator after a delay. This 2061da07ecd9SMark Brown * is intended for use with devices that require some time to quiesce. 2062da07ecd9SMark Brown * 2063da07ecd9SMark Brown * NOTE: this will only disable the regulator output if no other consumer 2064da07ecd9SMark Brown * devices have it enabled, the regulator device supports disabling and 2065da07ecd9SMark Brown * machine constraints permit this operation. 2066da07ecd9SMark Brown */ 2067da07ecd9SMark Brown int regulator_disable_deferred(struct regulator *regulator, int ms) 2068da07ecd9SMark Brown { 2069da07ecd9SMark Brown struct regulator_dev *rdev = regulator->rdev; 2070aa59802dSMark Brown int ret; 2071da07ecd9SMark Brown 20726492bc1bSMark Brown if (regulator->always_on) 20736492bc1bSMark Brown return 0; 20746492bc1bSMark Brown 20752b5a24a0SMark Brown if (!ms) 20762b5a24a0SMark Brown return regulator_disable(regulator); 20772b5a24a0SMark Brown 2078da07ecd9SMark Brown mutex_lock(&rdev->mutex); 2079da07ecd9SMark Brown rdev->deferred_disables++; 2080da07ecd9SMark Brown mutex_unlock(&rdev->mutex); 2081da07ecd9SMark Brown 2082070260f0SMark Brown ret = queue_delayed_work(system_power_efficient_wq, 2083070260f0SMark Brown &rdev->disable_work, 2084da07ecd9SMark Brown msecs_to_jiffies(ms)); 2085aa59802dSMark Brown if (ret < 0) 2086aa59802dSMark Brown return ret; 2087aa59802dSMark Brown else 2088aa59802dSMark Brown return 0; 2089da07ecd9SMark Brown } 2090da07ecd9SMark Brown EXPORT_SYMBOL_GPL(regulator_disable_deferred); 2091da07ecd9SMark Brown 2092414c70cbSLiam Girdwood static int _regulator_is_enabled(struct regulator_dev *rdev) 2093414c70cbSLiam Girdwood { 209465f73508SMark Brown /* A GPIO control always takes precedence */ 20957b74d149SKim, Milo if (rdev->ena_pin) 209665f73508SMark Brown return rdev->ena_gpio_state; 209765f73508SMark Brown 20989a7f6a4cSMark Brown /* If we don't know then assume that the regulator is always on */ 20999332546fSMark Brown if (!rdev->desc->ops->is_enabled) 21009a7f6a4cSMark Brown return 1; 2101414c70cbSLiam Girdwood 21029332546fSMark Brown return rdev->desc->ops->is_enabled(rdev); 2103414c70cbSLiam Girdwood } 2104414c70cbSLiam Girdwood 2105414c70cbSLiam Girdwood /** 2106414c70cbSLiam Girdwood * regulator_is_enabled - is the regulator output enabled 2107414c70cbSLiam Girdwood * @regulator: regulator source 2108414c70cbSLiam Girdwood * 2109412aec61SDavid Brownell * Returns positive if the regulator driver backing the source/client 2110412aec61SDavid Brownell * has requested that the device be enabled, zero if it hasn't, else a 2111412aec61SDavid Brownell * negative errno code. 2112412aec61SDavid Brownell * 2113412aec61SDavid Brownell * Note that the device backing this regulator handle can have multiple 2114412aec61SDavid Brownell * users, so it might be enabled even if regulator_enable() was never 2115412aec61SDavid Brownell * called for this particular source. 2116414c70cbSLiam Girdwood */ 2117414c70cbSLiam Girdwood int regulator_is_enabled(struct regulator *regulator) 2118414c70cbSLiam Girdwood { 21199332546fSMark Brown int ret; 21209332546fSMark Brown 21216492bc1bSMark Brown if (regulator->always_on) 21226492bc1bSMark Brown return 1; 21236492bc1bSMark Brown 21249332546fSMark Brown mutex_lock(®ulator->rdev->mutex); 21259332546fSMark Brown ret = _regulator_is_enabled(regulator->rdev); 21269332546fSMark Brown mutex_unlock(®ulator->rdev->mutex); 21279332546fSMark Brown 21289332546fSMark Brown return ret; 2129414c70cbSLiam Girdwood } 2130414c70cbSLiam Girdwood EXPORT_SYMBOL_GPL(regulator_is_enabled); 2131414c70cbSLiam Girdwood 2132414c70cbSLiam Girdwood /** 2133d1e7de30SMarek Szyprowski * regulator_can_change_voltage - check if regulator can change voltage 2134d1e7de30SMarek Szyprowski * @regulator: regulator source 2135d1e7de30SMarek Szyprowski * 2136d1e7de30SMarek Szyprowski * Returns positive if the regulator driver backing the source/client 2137d1e7de30SMarek Szyprowski * can change its voltage, false otherwise. Usefull for detecting fixed 2138d1e7de30SMarek Szyprowski * or dummy regulators and disabling voltage change logic in the client 2139d1e7de30SMarek Szyprowski * driver. 2140d1e7de30SMarek Szyprowski */ 2141d1e7de30SMarek Szyprowski int regulator_can_change_voltage(struct regulator *regulator) 2142d1e7de30SMarek Szyprowski { 2143d1e7de30SMarek Szyprowski struct regulator_dev *rdev = regulator->rdev; 2144d1e7de30SMarek Szyprowski 2145d1e7de30SMarek Szyprowski if (rdev->constraints && 214619280e40SAxel Lin (rdev->constraints->valid_ops_mask & REGULATOR_CHANGE_VOLTAGE)) { 214719280e40SAxel Lin if (rdev->desc->n_voltages - rdev->desc->linear_min_sel > 1) 2148d1e7de30SMarek Szyprowski return 1; 2149d1e7de30SMarek Szyprowski 215019280e40SAxel Lin if (rdev->desc->continuous_voltage_range && 215119280e40SAxel Lin rdev->constraints->min_uV && rdev->constraints->max_uV && 215219280e40SAxel Lin rdev->constraints->min_uV != rdev->constraints->max_uV) 215319280e40SAxel Lin return 1; 215419280e40SAxel Lin } 215519280e40SAxel Lin 2156d1e7de30SMarek Szyprowski return 0; 2157d1e7de30SMarek Szyprowski } 2158d1e7de30SMarek Szyprowski EXPORT_SYMBOL_GPL(regulator_can_change_voltage); 2159d1e7de30SMarek Szyprowski 2160d1e7de30SMarek Szyprowski /** 21614367cfdcSDavid Brownell * regulator_count_voltages - count regulator_list_voltage() selectors 21624367cfdcSDavid Brownell * @regulator: regulator source 21634367cfdcSDavid Brownell * 21644367cfdcSDavid Brownell * Returns number of selectors, or negative errno. Selectors are 21654367cfdcSDavid Brownell * numbered starting at zero, and typically correspond to bitfields 21664367cfdcSDavid Brownell * in hardware registers. 21674367cfdcSDavid Brownell */ 21684367cfdcSDavid Brownell int regulator_count_voltages(struct regulator *regulator) 21694367cfdcSDavid Brownell { 21704367cfdcSDavid Brownell struct regulator_dev *rdev = regulator->rdev; 21714367cfdcSDavid Brownell 21724367cfdcSDavid Brownell return rdev->desc->n_voltages ? : -EINVAL; 21734367cfdcSDavid Brownell } 21744367cfdcSDavid Brownell EXPORT_SYMBOL_GPL(regulator_count_voltages); 21754367cfdcSDavid Brownell 21764367cfdcSDavid Brownell /** 21774367cfdcSDavid Brownell * regulator_list_voltage - enumerate supported voltages 21784367cfdcSDavid Brownell * @regulator: regulator source 21794367cfdcSDavid Brownell * @selector: identify voltage to list 21804367cfdcSDavid Brownell * Context: can sleep 21814367cfdcSDavid Brownell * 21824367cfdcSDavid Brownell * Returns a voltage that can be passed to @regulator_set_voltage(), 218388393161SThomas Weber * zero if this selector code can't be used on this system, or a 21844367cfdcSDavid Brownell * negative errno. 21854367cfdcSDavid Brownell */ 21864367cfdcSDavid Brownell int regulator_list_voltage(struct regulator *regulator, unsigned selector) 21874367cfdcSDavid Brownell { 21884367cfdcSDavid Brownell struct regulator_dev *rdev = regulator->rdev; 21894367cfdcSDavid Brownell struct regulator_ops *ops = rdev->desc->ops; 21904367cfdcSDavid Brownell int ret; 21914367cfdcSDavid Brownell 2192f446043fSGuennadi Liakhovetski if (rdev->desc->fixed_uV && rdev->desc->n_voltages == 1 && !selector) 2193f446043fSGuennadi Liakhovetski return rdev->desc->fixed_uV; 2194f446043fSGuennadi Liakhovetski 21954367cfdcSDavid Brownell if (!ops->list_voltage || selector >= rdev->desc->n_voltages) 21964367cfdcSDavid Brownell return -EINVAL; 21974367cfdcSDavid Brownell 21984367cfdcSDavid Brownell mutex_lock(&rdev->mutex); 21994367cfdcSDavid Brownell ret = ops->list_voltage(rdev, selector); 22004367cfdcSDavid Brownell mutex_unlock(&rdev->mutex); 22014367cfdcSDavid Brownell 22024367cfdcSDavid Brownell if (ret > 0) { 22034367cfdcSDavid Brownell if (ret < rdev->constraints->min_uV) 22044367cfdcSDavid Brownell ret = 0; 22054367cfdcSDavid Brownell else if (ret > rdev->constraints->max_uV) 22064367cfdcSDavid Brownell ret = 0; 22074367cfdcSDavid Brownell } 22084367cfdcSDavid Brownell 22094367cfdcSDavid Brownell return ret; 22104367cfdcSDavid Brownell } 22114367cfdcSDavid Brownell EXPORT_SYMBOL_GPL(regulator_list_voltage); 22124367cfdcSDavid Brownell 22134367cfdcSDavid Brownell /** 22142a668a8bSPaul Walmsley * regulator_get_linear_step - return the voltage step size between VSEL values 22152a668a8bSPaul Walmsley * @regulator: regulator source 22162a668a8bSPaul Walmsley * 22172a668a8bSPaul Walmsley * Returns the voltage step size between VSEL values for linear 22182a668a8bSPaul Walmsley * regulators, or return 0 if the regulator isn't a linear regulator. 22192a668a8bSPaul Walmsley */ 22202a668a8bSPaul Walmsley unsigned int regulator_get_linear_step(struct regulator *regulator) 22212a668a8bSPaul Walmsley { 22222a668a8bSPaul Walmsley struct regulator_dev *rdev = regulator->rdev; 22232a668a8bSPaul Walmsley 22242a668a8bSPaul Walmsley return rdev->desc->uV_step; 22252a668a8bSPaul Walmsley } 22262a668a8bSPaul Walmsley EXPORT_SYMBOL_GPL(regulator_get_linear_step); 22272a668a8bSPaul Walmsley 22282a668a8bSPaul Walmsley /** 2229a7a1ad90SMark Brown * regulator_is_supported_voltage - check if a voltage range can be supported 2230a7a1ad90SMark Brown * 2231a7a1ad90SMark Brown * @regulator: Regulator to check. 2232a7a1ad90SMark Brown * @min_uV: Minimum required voltage in uV. 2233a7a1ad90SMark Brown * @max_uV: Maximum required voltage in uV. 2234a7a1ad90SMark Brown * 2235a7a1ad90SMark Brown * Returns a boolean or a negative error code. 2236a7a1ad90SMark Brown */ 2237a7a1ad90SMark Brown int regulator_is_supported_voltage(struct regulator *regulator, 2238a7a1ad90SMark Brown int min_uV, int max_uV) 2239a7a1ad90SMark Brown { 2240c5f3939bSMark Brown struct regulator_dev *rdev = regulator->rdev; 2241a7a1ad90SMark Brown int i, voltages, ret; 2242a7a1ad90SMark Brown 2243c5f3939bSMark Brown /* If we can't change voltage check the current voltage */ 2244c5f3939bSMark Brown if (!(rdev->constraints->valid_ops_mask & REGULATOR_CHANGE_VOLTAGE)) { 2245c5f3939bSMark Brown ret = regulator_get_voltage(regulator); 2246c5f3939bSMark Brown if (ret >= 0) 22470d25d09dSJingoo Han return min_uV <= ret && ret <= max_uV; 2248c5f3939bSMark Brown else 2249c5f3939bSMark Brown return ret; 2250c5f3939bSMark Brown } 2251c5f3939bSMark Brown 2252bd7a2b60SPawel Moll /* Any voltage within constrains range is fine? */ 2253bd7a2b60SPawel Moll if (rdev->desc->continuous_voltage_range) 2254bd7a2b60SPawel Moll return min_uV >= rdev->constraints->min_uV && 2255bd7a2b60SPawel Moll max_uV <= rdev->constraints->max_uV; 2256bd7a2b60SPawel Moll 2257a7a1ad90SMark Brown ret = regulator_count_voltages(regulator); 2258a7a1ad90SMark Brown if (ret < 0) 2259a7a1ad90SMark Brown return ret; 2260a7a1ad90SMark Brown voltages = ret; 2261a7a1ad90SMark Brown 2262a7a1ad90SMark Brown for (i = 0; i < voltages; i++) { 2263a7a1ad90SMark Brown ret = regulator_list_voltage(regulator, i); 2264a7a1ad90SMark Brown 2265a7a1ad90SMark Brown if (ret >= min_uV && ret <= max_uV) 2266a7a1ad90SMark Brown return 1; 2267a7a1ad90SMark Brown } 2268a7a1ad90SMark Brown 2269a7a1ad90SMark Brown return 0; 2270a7a1ad90SMark Brown } 2271a398eaa2SMark Brown EXPORT_SYMBOL_GPL(regulator_is_supported_voltage); 2272a7a1ad90SMark Brown 227375790251SMark Brown static int _regulator_do_set_voltage(struct regulator_dev *rdev, 227475790251SMark Brown int min_uV, int max_uV) 227575790251SMark Brown { 227675790251SMark Brown int ret; 227777af1b26SLinus Walleij int delay = 0; 2278e113d792SMark Brown int best_val = 0; 227975790251SMark Brown unsigned int selector; 2280eba41a5eSAxel Lin int old_selector = -1; 228175790251SMark Brown 228275790251SMark Brown trace_regulator_set_voltage(rdev_get_name(rdev), min_uV, max_uV); 228375790251SMark Brown 2284bf5892a8SMark Brown min_uV += rdev->constraints->uV_offset; 2285bf5892a8SMark Brown max_uV += rdev->constraints->uV_offset; 2286bf5892a8SMark Brown 228777af1b26SLinus Walleij /* 228877af1b26SLinus Walleij * If we can't obtain the old selector there is not enough 228977af1b26SLinus Walleij * info to call set_voltage_time_sel(). 229077af1b26SLinus Walleij */ 22918b7485efSAxel Lin if (_regulator_is_enabled(rdev) && 22928b7485efSAxel Lin rdev->desc->ops->set_voltage_time_sel && 229377af1b26SLinus Walleij rdev->desc->ops->get_voltage_sel) { 2294eba41a5eSAxel Lin old_selector = rdev->desc->ops->get_voltage_sel(rdev); 2295eba41a5eSAxel Lin if (old_selector < 0) 2296eba41a5eSAxel Lin return old_selector; 2297eba41a5eSAxel Lin } 229877af1b26SLinus Walleij 229975790251SMark Brown if (rdev->desc->ops->set_voltage) { 230075790251SMark Brown ret = rdev->desc->ops->set_voltage(rdev, min_uV, max_uV, 230175790251SMark Brown &selector); 2302e113d792SMark Brown 2303e113d792SMark Brown if (ret >= 0) { 2304e113d792SMark Brown if (rdev->desc->ops->list_voltage) 2305e113d792SMark Brown best_val = rdev->desc->ops->list_voltage(rdev, 2306e113d792SMark Brown selector); 2307e113d792SMark Brown else 2308e113d792SMark Brown best_val = _regulator_get_voltage(rdev); 2309e113d792SMark Brown } 2310e113d792SMark Brown 2311e8eef82bSMark Brown } else if (rdev->desc->ops->set_voltage_sel) { 23129152c36aSAxel Lin if (rdev->desc->ops->map_voltage) { 2313e843fc46SMark Brown ret = rdev->desc->ops->map_voltage(rdev, min_uV, 2314e843fc46SMark Brown max_uV); 23159152c36aSAxel Lin } else { 23169152c36aSAxel Lin if (rdev->desc->ops->list_voltage == 23179152c36aSAxel Lin regulator_list_voltage_linear) 23189152c36aSAxel Lin ret = regulator_map_voltage_linear(rdev, 23199152c36aSAxel Lin min_uV, max_uV); 232007351233SAxel Lin else 23219152c36aSAxel Lin ret = regulator_map_voltage_iterate(rdev, 23229152c36aSAxel Lin min_uV, max_uV); 23239152c36aSAxel Lin } 2324e843fc46SMark Brown 2325e843fc46SMark Brown if (ret >= 0) { 2326e113d792SMark Brown best_val = rdev->desc->ops->list_voltage(rdev, ret); 2327e113d792SMark Brown if (min_uV <= best_val && max_uV >= best_val) { 2328e843fc46SMark Brown selector = ret; 2329c66a566aSAxel Lin if (old_selector == selector) 2330c66a566aSAxel Lin ret = 0; 2331c66a566aSAxel Lin else 2332c66a566aSAxel Lin ret = rdev->desc->ops->set_voltage_sel( 2333c66a566aSAxel Lin rdev, ret); 2334e113d792SMark Brown } else { 2335e113d792SMark Brown ret = -EINVAL; 2336e113d792SMark Brown } 2337e843fc46SMark Brown } 2338e8eef82bSMark Brown } else { 2339e8eef82bSMark Brown ret = -EINVAL; 2340e8eef82bSMark Brown } 2341e8eef82bSMark Brown 2342eba41a5eSAxel Lin /* Call set_voltage_time_sel if successfully obtained old_selector */ 23435b175952SYadwinder Singh Brar if (ret == 0 && !rdev->constraints->ramp_disable && old_selector >= 0 23445b175952SYadwinder Singh Brar && old_selector != selector) { 2345eba41a5eSAxel Lin 2346eba41a5eSAxel Lin delay = rdev->desc->ops->set_voltage_time_sel(rdev, 2347eba41a5eSAxel Lin old_selector, selector); 2348eba41a5eSAxel Lin if (delay < 0) { 2349eba41a5eSAxel Lin rdev_warn(rdev, "set_voltage_time_sel() failed: %d\n", 2350eba41a5eSAxel Lin delay); 2351eba41a5eSAxel Lin delay = 0; 2352e8eef82bSMark Brown } 235375790251SMark Brown 235477af1b26SLinus Walleij /* Insert any necessary delays */ 235577af1b26SLinus Walleij if (delay >= 1000) { 235677af1b26SLinus Walleij mdelay(delay / 1000); 235777af1b26SLinus Walleij udelay(delay % 1000); 235877af1b26SLinus Walleij } else if (delay) { 235977af1b26SLinus Walleij udelay(delay); 236077af1b26SLinus Walleij } 23618b96de31SPhilip Rakity } 236277af1b26SLinus Walleij 23632f6c797fSAxel Lin if (ret == 0 && best_val >= 0) { 23642f6c797fSAxel Lin unsigned long data = best_val; 23652f6c797fSAxel Lin 2366ded06a52SMark Brown _notifier_call_chain(rdev, REGULATOR_EVENT_VOLTAGE_CHANGE, 23672f6c797fSAxel Lin (void *)data); 23682f6c797fSAxel Lin } 2369ded06a52SMark Brown 2370eba41a5eSAxel Lin trace_regulator_set_voltage_complete(rdev_get_name(rdev), best_val); 237175790251SMark Brown 237275790251SMark Brown return ret; 237375790251SMark Brown } 237475790251SMark Brown 2375a7a1ad90SMark Brown /** 2376414c70cbSLiam Girdwood * regulator_set_voltage - set regulator output voltage 2377414c70cbSLiam Girdwood * @regulator: regulator source 2378414c70cbSLiam Girdwood * @min_uV: Minimum required voltage in uV 2379414c70cbSLiam Girdwood * @max_uV: Maximum acceptable voltage in uV 2380414c70cbSLiam Girdwood * 2381414c70cbSLiam Girdwood * Sets a voltage regulator to the desired output voltage. This can be set 2382414c70cbSLiam Girdwood * during any regulator state. IOW, regulator can be disabled or enabled. 2383414c70cbSLiam Girdwood * 2384414c70cbSLiam Girdwood * If the regulator is enabled then the voltage will change to the new value 2385414c70cbSLiam Girdwood * immediately otherwise if the regulator is disabled the regulator will 2386414c70cbSLiam Girdwood * output at the new voltage when enabled. 2387414c70cbSLiam Girdwood * 2388414c70cbSLiam Girdwood * NOTE: If the regulator is shared between several devices then the lowest 2389414c70cbSLiam Girdwood * request voltage that meets the system constraints will be used. 239069279fb9SMark Brown * Regulator system constraints must be set for this regulator before 2391414c70cbSLiam Girdwood * calling this function otherwise this call will fail. 2392414c70cbSLiam Girdwood */ 2393414c70cbSLiam Girdwood int regulator_set_voltage(struct regulator *regulator, int min_uV, int max_uV) 2394414c70cbSLiam Girdwood { 2395414c70cbSLiam Girdwood struct regulator_dev *rdev = regulator->rdev; 239695a3c23aSMark Brown int ret = 0; 239792d7a558SPaolo Pisati int old_min_uV, old_max_uV; 2398414c70cbSLiam Girdwood 2399414c70cbSLiam Girdwood mutex_lock(&rdev->mutex); 2400414c70cbSLiam Girdwood 240195a3c23aSMark Brown /* If we're setting the same range as last time the change 240295a3c23aSMark Brown * should be a noop (some cpufreq implementations use the same 240395a3c23aSMark Brown * voltage for multiple frequencies, for example). 240495a3c23aSMark Brown */ 240595a3c23aSMark Brown if (regulator->min_uV == min_uV && regulator->max_uV == max_uV) 240695a3c23aSMark Brown goto out; 240795a3c23aSMark Brown 2408414c70cbSLiam Girdwood /* sanity check */ 2409e8eef82bSMark Brown if (!rdev->desc->ops->set_voltage && 2410e8eef82bSMark Brown !rdev->desc->ops->set_voltage_sel) { 2411414c70cbSLiam Girdwood ret = -EINVAL; 2412414c70cbSLiam Girdwood goto out; 2413414c70cbSLiam Girdwood } 2414414c70cbSLiam Girdwood 2415414c70cbSLiam Girdwood /* constraints check */ 2416414c70cbSLiam Girdwood ret = regulator_check_voltage(rdev, &min_uV, &max_uV); 2417414c70cbSLiam Girdwood if (ret < 0) 2418414c70cbSLiam Girdwood goto out; 241992d7a558SPaolo Pisati 242092d7a558SPaolo Pisati /* restore original values in case of error */ 242192d7a558SPaolo Pisati old_min_uV = regulator->min_uV; 242292d7a558SPaolo Pisati old_max_uV = regulator->max_uV; 2423414c70cbSLiam Girdwood regulator->min_uV = min_uV; 2424414c70cbSLiam Girdwood regulator->max_uV = max_uV; 24253a93f2a9SMark Brown 242605fda3b1SThomas Petazzoni ret = regulator_check_consumers(rdev, &min_uV, &max_uV); 242705fda3b1SThomas Petazzoni if (ret < 0) 242892d7a558SPaolo Pisati goto out2; 242905fda3b1SThomas Petazzoni 243075790251SMark Brown ret = _regulator_do_set_voltage(rdev, min_uV, max_uV); 243192d7a558SPaolo Pisati if (ret < 0) 243292d7a558SPaolo Pisati goto out2; 243302fa3ec0SMark Brown 2434414c70cbSLiam Girdwood out: 2435414c70cbSLiam Girdwood mutex_unlock(&rdev->mutex); 2436414c70cbSLiam Girdwood return ret; 243792d7a558SPaolo Pisati out2: 243892d7a558SPaolo Pisati regulator->min_uV = old_min_uV; 243992d7a558SPaolo Pisati regulator->max_uV = old_max_uV; 244092d7a558SPaolo Pisati mutex_unlock(&rdev->mutex); 244192d7a558SPaolo Pisati return ret; 2442414c70cbSLiam Girdwood } 2443414c70cbSLiam Girdwood EXPORT_SYMBOL_GPL(regulator_set_voltage); 2444414c70cbSLiam Girdwood 2445606a2562SMark Brown /** 244688cd222bSLinus Walleij * regulator_set_voltage_time - get raise/fall time 244788cd222bSLinus Walleij * @regulator: regulator source 244888cd222bSLinus Walleij * @old_uV: starting voltage in microvolts 244988cd222bSLinus Walleij * @new_uV: target voltage in microvolts 245088cd222bSLinus Walleij * 245188cd222bSLinus Walleij * Provided with the starting and ending voltage, this function attempts to 245288cd222bSLinus Walleij * calculate the time in microseconds required to rise or fall to this new 245388cd222bSLinus Walleij * voltage. 245488cd222bSLinus Walleij */ 245588cd222bSLinus Walleij int regulator_set_voltage_time(struct regulator *regulator, 245688cd222bSLinus Walleij int old_uV, int new_uV) 245788cd222bSLinus Walleij { 245888cd222bSLinus Walleij struct regulator_dev *rdev = regulator->rdev; 245988cd222bSLinus Walleij struct regulator_ops *ops = rdev->desc->ops; 246088cd222bSLinus Walleij int old_sel = -1; 246188cd222bSLinus Walleij int new_sel = -1; 246288cd222bSLinus Walleij int voltage; 246388cd222bSLinus Walleij int i; 246488cd222bSLinus Walleij 246588cd222bSLinus Walleij /* Currently requires operations to do this */ 246688cd222bSLinus Walleij if (!ops->list_voltage || !ops->set_voltage_time_sel 246788cd222bSLinus Walleij || !rdev->desc->n_voltages) 246888cd222bSLinus Walleij return -EINVAL; 246988cd222bSLinus Walleij 247088cd222bSLinus Walleij for (i = 0; i < rdev->desc->n_voltages; i++) { 247188cd222bSLinus Walleij /* We only look for exact voltage matches here */ 247288cd222bSLinus Walleij voltage = regulator_list_voltage(regulator, i); 247388cd222bSLinus Walleij if (voltage < 0) 247488cd222bSLinus Walleij return -EINVAL; 247588cd222bSLinus Walleij if (voltage == 0) 247688cd222bSLinus Walleij continue; 247788cd222bSLinus Walleij if (voltage == old_uV) 247888cd222bSLinus Walleij old_sel = i; 247988cd222bSLinus Walleij if (voltage == new_uV) 248088cd222bSLinus Walleij new_sel = i; 248188cd222bSLinus Walleij } 248288cd222bSLinus Walleij 248388cd222bSLinus Walleij if (old_sel < 0 || new_sel < 0) 248488cd222bSLinus Walleij return -EINVAL; 248588cd222bSLinus Walleij 248688cd222bSLinus Walleij return ops->set_voltage_time_sel(rdev, old_sel, new_sel); 248788cd222bSLinus Walleij } 248888cd222bSLinus Walleij EXPORT_SYMBOL_GPL(regulator_set_voltage_time); 248988cd222bSLinus Walleij 249088cd222bSLinus Walleij /** 249198a175b6SYadwinder Singh Brar * regulator_set_voltage_time_sel - get raise/fall time 2492296c6566SRandy Dunlap * @rdev: regulator source device 249398a175b6SYadwinder Singh Brar * @old_selector: selector for starting voltage 249498a175b6SYadwinder Singh Brar * @new_selector: selector for target voltage 249598a175b6SYadwinder Singh Brar * 249698a175b6SYadwinder Singh Brar * Provided with the starting and target voltage selectors, this function 249798a175b6SYadwinder Singh Brar * returns time in microseconds required to rise or fall to this new voltage 249898a175b6SYadwinder Singh Brar * 2499f11d08c3SAxel Lin * Drivers providing ramp_delay in regulation_constraints can use this as their 2500398715abSAxel Lin * set_voltage_time_sel() operation. 250198a175b6SYadwinder Singh Brar */ 250298a175b6SYadwinder Singh Brar int regulator_set_voltage_time_sel(struct regulator_dev *rdev, 250398a175b6SYadwinder Singh Brar unsigned int old_selector, 250498a175b6SYadwinder Singh Brar unsigned int new_selector) 250598a175b6SYadwinder Singh Brar { 2506398715abSAxel Lin unsigned int ramp_delay = 0; 2507f11d08c3SAxel Lin int old_volt, new_volt; 2508398715abSAxel Lin 25096f0b2c69SYadwinder Singh Brar if (rdev->constraints->ramp_delay) 2510398715abSAxel Lin ramp_delay = rdev->constraints->ramp_delay; 2511398715abSAxel Lin else if (rdev->desc->ramp_delay) 2512398715abSAxel Lin ramp_delay = rdev->desc->ramp_delay; 2513398715abSAxel Lin 2514398715abSAxel Lin if (ramp_delay == 0) { 25156f0b2c69SYadwinder Singh Brar rdev_warn(rdev, "ramp_delay not set\n"); 2516398715abSAxel Lin return 0; 25176f0b2c69SYadwinder Singh Brar } 2518398715abSAxel Lin 2519f11d08c3SAxel Lin /* sanity check */ 2520f11d08c3SAxel Lin if (!rdev->desc->ops->list_voltage) 2521f11d08c3SAxel Lin return -EINVAL; 2522398715abSAxel Lin 2523f11d08c3SAxel Lin old_volt = rdev->desc->ops->list_voltage(rdev, old_selector); 2524f11d08c3SAxel Lin new_volt = rdev->desc->ops->list_voltage(rdev, new_selector); 2525f11d08c3SAxel Lin 2526f11d08c3SAxel Lin return DIV_ROUND_UP(abs(new_volt - old_volt), ramp_delay); 252798a175b6SYadwinder Singh Brar } 2528b19dbf71SMark Brown EXPORT_SYMBOL_GPL(regulator_set_voltage_time_sel); 252998a175b6SYadwinder Singh Brar 253098a175b6SYadwinder Singh Brar /** 2531606a2562SMark Brown * regulator_sync_voltage - re-apply last regulator output voltage 2532606a2562SMark Brown * @regulator: regulator source 2533606a2562SMark Brown * 2534606a2562SMark Brown * Re-apply the last configured voltage. This is intended to be used 2535606a2562SMark Brown * where some external control source the consumer is cooperating with 2536606a2562SMark Brown * has caused the configured voltage to change. 2537606a2562SMark Brown */ 2538606a2562SMark Brown int regulator_sync_voltage(struct regulator *regulator) 2539606a2562SMark Brown { 2540606a2562SMark Brown struct regulator_dev *rdev = regulator->rdev; 2541606a2562SMark Brown int ret, min_uV, max_uV; 2542606a2562SMark Brown 2543606a2562SMark Brown mutex_lock(&rdev->mutex); 2544606a2562SMark Brown 2545606a2562SMark Brown if (!rdev->desc->ops->set_voltage && 2546606a2562SMark Brown !rdev->desc->ops->set_voltage_sel) { 2547606a2562SMark Brown ret = -EINVAL; 2548606a2562SMark Brown goto out; 2549606a2562SMark Brown } 2550606a2562SMark Brown 2551606a2562SMark Brown /* This is only going to work if we've had a voltage configured. */ 2552606a2562SMark Brown if (!regulator->min_uV && !regulator->max_uV) { 2553606a2562SMark Brown ret = -EINVAL; 2554606a2562SMark Brown goto out; 2555606a2562SMark Brown } 2556606a2562SMark Brown 2557606a2562SMark Brown min_uV = regulator->min_uV; 2558606a2562SMark Brown max_uV = regulator->max_uV; 2559606a2562SMark Brown 2560606a2562SMark Brown /* This should be a paranoia check... */ 2561606a2562SMark Brown ret = regulator_check_voltage(rdev, &min_uV, &max_uV); 2562606a2562SMark Brown if (ret < 0) 2563606a2562SMark Brown goto out; 2564606a2562SMark Brown 2565606a2562SMark Brown ret = regulator_check_consumers(rdev, &min_uV, &max_uV); 2566606a2562SMark Brown if (ret < 0) 2567606a2562SMark Brown goto out; 2568606a2562SMark Brown 2569606a2562SMark Brown ret = _regulator_do_set_voltage(rdev, min_uV, max_uV); 2570606a2562SMark Brown 2571606a2562SMark Brown out: 2572606a2562SMark Brown mutex_unlock(&rdev->mutex); 2573606a2562SMark Brown return ret; 2574606a2562SMark Brown } 2575606a2562SMark Brown EXPORT_SYMBOL_GPL(regulator_sync_voltage); 2576606a2562SMark Brown 2577414c70cbSLiam Girdwood static int _regulator_get_voltage(struct regulator_dev *rdev) 2578414c70cbSLiam Girdwood { 2579bf5892a8SMark Brown int sel, ret; 2580476c2d83SMark Brown 2581476c2d83SMark Brown if (rdev->desc->ops->get_voltage_sel) { 2582476c2d83SMark Brown sel = rdev->desc->ops->get_voltage_sel(rdev); 2583476c2d83SMark Brown if (sel < 0) 2584476c2d83SMark Brown return sel; 2585bf5892a8SMark Brown ret = rdev->desc->ops->list_voltage(rdev, sel); 2586cb220d16SAxel Lin } else if (rdev->desc->ops->get_voltage) { 2587bf5892a8SMark Brown ret = rdev->desc->ops->get_voltage(rdev); 2588f7df20ecSMark Brown } else if (rdev->desc->ops->list_voltage) { 2589f7df20ecSMark Brown ret = rdev->desc->ops->list_voltage(rdev, 0); 25905a523605SLaxman Dewangan } else if (rdev->desc->fixed_uV && (rdev->desc->n_voltages == 1)) { 25915a523605SLaxman Dewangan ret = rdev->desc->fixed_uV; 2592cb220d16SAxel Lin } else { 2593414c70cbSLiam Girdwood return -EINVAL; 2594cb220d16SAxel Lin } 2595bf5892a8SMark Brown 2596cb220d16SAxel Lin if (ret < 0) 2597cb220d16SAxel Lin return ret; 2598bf5892a8SMark Brown return ret - rdev->constraints->uV_offset; 2599414c70cbSLiam Girdwood } 2600414c70cbSLiam Girdwood 2601414c70cbSLiam Girdwood /** 2602414c70cbSLiam Girdwood * regulator_get_voltage - get regulator output voltage 2603414c70cbSLiam Girdwood * @regulator: regulator source 2604414c70cbSLiam Girdwood * 2605414c70cbSLiam Girdwood * This returns the current regulator voltage in uV. 2606414c70cbSLiam Girdwood * 2607414c70cbSLiam Girdwood * NOTE: If the regulator is disabled it will return the voltage value. This 2608414c70cbSLiam Girdwood * function should not be used to determine regulator state. 2609414c70cbSLiam Girdwood */ 2610414c70cbSLiam Girdwood int regulator_get_voltage(struct regulator *regulator) 2611414c70cbSLiam Girdwood { 2612414c70cbSLiam Girdwood int ret; 2613414c70cbSLiam Girdwood 2614414c70cbSLiam Girdwood mutex_lock(®ulator->rdev->mutex); 2615414c70cbSLiam Girdwood 2616414c70cbSLiam Girdwood ret = _regulator_get_voltage(regulator->rdev); 2617414c70cbSLiam Girdwood 2618414c70cbSLiam Girdwood mutex_unlock(®ulator->rdev->mutex); 2619414c70cbSLiam Girdwood 2620414c70cbSLiam Girdwood return ret; 2621414c70cbSLiam Girdwood } 2622414c70cbSLiam Girdwood EXPORT_SYMBOL_GPL(regulator_get_voltage); 2623414c70cbSLiam Girdwood 2624414c70cbSLiam Girdwood /** 2625414c70cbSLiam Girdwood * regulator_set_current_limit - set regulator output current limit 2626414c70cbSLiam Girdwood * @regulator: regulator source 2627ce0d10f8SCharles Keepax * @min_uA: Minimum supported current in uA 2628414c70cbSLiam Girdwood * @max_uA: Maximum supported current in uA 2629414c70cbSLiam Girdwood * 2630414c70cbSLiam Girdwood * Sets current sink to the desired output current. This can be set during 2631414c70cbSLiam Girdwood * any regulator state. IOW, regulator can be disabled or enabled. 2632414c70cbSLiam Girdwood * 2633414c70cbSLiam Girdwood * If the regulator is enabled then the current will change to the new value 2634414c70cbSLiam Girdwood * immediately otherwise if the regulator is disabled the regulator will 2635414c70cbSLiam Girdwood * output at the new current when enabled. 2636414c70cbSLiam Girdwood * 2637414c70cbSLiam Girdwood * NOTE: Regulator system constraints must be set for this regulator before 2638414c70cbSLiam Girdwood * calling this function otherwise this call will fail. 2639414c70cbSLiam Girdwood */ 2640414c70cbSLiam Girdwood int regulator_set_current_limit(struct regulator *regulator, 2641414c70cbSLiam Girdwood int min_uA, int max_uA) 2642414c70cbSLiam Girdwood { 2643414c70cbSLiam Girdwood struct regulator_dev *rdev = regulator->rdev; 2644414c70cbSLiam Girdwood int ret; 2645414c70cbSLiam Girdwood 2646414c70cbSLiam Girdwood mutex_lock(&rdev->mutex); 2647414c70cbSLiam Girdwood 2648414c70cbSLiam Girdwood /* sanity check */ 2649414c70cbSLiam Girdwood if (!rdev->desc->ops->set_current_limit) { 2650414c70cbSLiam Girdwood ret = -EINVAL; 2651414c70cbSLiam Girdwood goto out; 2652414c70cbSLiam Girdwood } 2653414c70cbSLiam Girdwood 2654414c70cbSLiam Girdwood /* constraints check */ 2655414c70cbSLiam Girdwood ret = regulator_check_current_limit(rdev, &min_uA, &max_uA); 2656414c70cbSLiam Girdwood if (ret < 0) 2657414c70cbSLiam Girdwood goto out; 2658414c70cbSLiam Girdwood 2659414c70cbSLiam Girdwood ret = rdev->desc->ops->set_current_limit(rdev, min_uA, max_uA); 2660414c70cbSLiam Girdwood out: 2661414c70cbSLiam Girdwood mutex_unlock(&rdev->mutex); 2662414c70cbSLiam Girdwood return ret; 2663414c70cbSLiam Girdwood } 2664414c70cbSLiam Girdwood EXPORT_SYMBOL_GPL(regulator_set_current_limit); 2665414c70cbSLiam Girdwood 2666414c70cbSLiam Girdwood static int _regulator_get_current_limit(struct regulator_dev *rdev) 2667414c70cbSLiam Girdwood { 2668414c70cbSLiam Girdwood int ret; 2669414c70cbSLiam Girdwood 2670414c70cbSLiam Girdwood mutex_lock(&rdev->mutex); 2671414c70cbSLiam Girdwood 2672414c70cbSLiam Girdwood /* sanity check */ 2673414c70cbSLiam Girdwood if (!rdev->desc->ops->get_current_limit) { 2674414c70cbSLiam Girdwood ret = -EINVAL; 2675414c70cbSLiam Girdwood goto out; 2676414c70cbSLiam Girdwood } 2677414c70cbSLiam Girdwood 2678414c70cbSLiam Girdwood ret = rdev->desc->ops->get_current_limit(rdev); 2679414c70cbSLiam Girdwood out: 2680414c70cbSLiam Girdwood mutex_unlock(&rdev->mutex); 2681414c70cbSLiam Girdwood return ret; 2682414c70cbSLiam Girdwood } 2683414c70cbSLiam Girdwood 2684414c70cbSLiam Girdwood /** 2685414c70cbSLiam Girdwood * regulator_get_current_limit - get regulator output current 2686414c70cbSLiam Girdwood * @regulator: regulator source 2687414c70cbSLiam Girdwood * 2688414c70cbSLiam Girdwood * This returns the current supplied by the specified current sink in uA. 2689414c70cbSLiam Girdwood * 2690414c70cbSLiam Girdwood * NOTE: If the regulator is disabled it will return the current value. This 2691414c70cbSLiam Girdwood * function should not be used to determine regulator state. 2692414c70cbSLiam Girdwood */ 2693414c70cbSLiam Girdwood int regulator_get_current_limit(struct regulator *regulator) 2694414c70cbSLiam Girdwood { 2695414c70cbSLiam Girdwood return _regulator_get_current_limit(regulator->rdev); 2696414c70cbSLiam Girdwood } 2697414c70cbSLiam Girdwood EXPORT_SYMBOL_GPL(regulator_get_current_limit); 2698414c70cbSLiam Girdwood 2699414c70cbSLiam Girdwood /** 2700414c70cbSLiam Girdwood * regulator_set_mode - set regulator operating mode 2701414c70cbSLiam Girdwood * @regulator: regulator source 2702414c70cbSLiam Girdwood * @mode: operating mode - one of the REGULATOR_MODE constants 2703414c70cbSLiam Girdwood * 2704414c70cbSLiam Girdwood * Set regulator operating mode to increase regulator efficiency or improve 2705414c70cbSLiam Girdwood * regulation performance. 2706414c70cbSLiam Girdwood * 2707414c70cbSLiam Girdwood * NOTE: Regulator system constraints must be set for this regulator before 2708414c70cbSLiam Girdwood * calling this function otherwise this call will fail. 2709414c70cbSLiam Girdwood */ 2710414c70cbSLiam Girdwood int regulator_set_mode(struct regulator *regulator, unsigned int mode) 2711414c70cbSLiam Girdwood { 2712414c70cbSLiam Girdwood struct regulator_dev *rdev = regulator->rdev; 2713414c70cbSLiam Girdwood int ret; 2714500b4ac9SSundar R Iyer int regulator_curr_mode; 2715414c70cbSLiam Girdwood 2716414c70cbSLiam Girdwood mutex_lock(&rdev->mutex); 2717414c70cbSLiam Girdwood 2718414c70cbSLiam Girdwood /* sanity check */ 2719414c70cbSLiam Girdwood if (!rdev->desc->ops->set_mode) { 2720414c70cbSLiam Girdwood ret = -EINVAL; 2721414c70cbSLiam Girdwood goto out; 2722414c70cbSLiam Girdwood } 2723414c70cbSLiam Girdwood 2724500b4ac9SSundar R Iyer /* return if the same mode is requested */ 2725500b4ac9SSundar R Iyer if (rdev->desc->ops->get_mode) { 2726500b4ac9SSundar R Iyer regulator_curr_mode = rdev->desc->ops->get_mode(rdev); 2727500b4ac9SSundar R Iyer if (regulator_curr_mode == mode) { 2728500b4ac9SSundar R Iyer ret = 0; 2729500b4ac9SSundar R Iyer goto out; 2730500b4ac9SSundar R Iyer } 2731500b4ac9SSundar R Iyer } 2732500b4ac9SSundar R Iyer 2733414c70cbSLiam Girdwood /* constraints check */ 273422c51b47SAxel Lin ret = regulator_mode_constrain(rdev, &mode); 2735414c70cbSLiam Girdwood if (ret < 0) 2736414c70cbSLiam Girdwood goto out; 2737414c70cbSLiam Girdwood 2738414c70cbSLiam Girdwood ret = rdev->desc->ops->set_mode(rdev, mode); 2739414c70cbSLiam Girdwood out: 2740414c70cbSLiam Girdwood mutex_unlock(&rdev->mutex); 2741414c70cbSLiam Girdwood return ret; 2742414c70cbSLiam Girdwood } 2743414c70cbSLiam Girdwood EXPORT_SYMBOL_GPL(regulator_set_mode); 2744414c70cbSLiam Girdwood 2745414c70cbSLiam Girdwood static unsigned int _regulator_get_mode(struct regulator_dev *rdev) 2746414c70cbSLiam Girdwood { 2747414c70cbSLiam Girdwood int ret; 2748414c70cbSLiam Girdwood 2749414c70cbSLiam Girdwood mutex_lock(&rdev->mutex); 2750414c70cbSLiam Girdwood 2751414c70cbSLiam Girdwood /* sanity check */ 2752414c70cbSLiam Girdwood if (!rdev->desc->ops->get_mode) { 2753414c70cbSLiam Girdwood ret = -EINVAL; 2754414c70cbSLiam Girdwood goto out; 2755414c70cbSLiam Girdwood } 2756414c70cbSLiam Girdwood 2757414c70cbSLiam Girdwood ret = rdev->desc->ops->get_mode(rdev); 2758414c70cbSLiam Girdwood out: 2759414c70cbSLiam Girdwood mutex_unlock(&rdev->mutex); 2760414c70cbSLiam Girdwood return ret; 2761414c70cbSLiam Girdwood } 2762414c70cbSLiam Girdwood 2763414c70cbSLiam Girdwood /** 2764414c70cbSLiam Girdwood * regulator_get_mode - get regulator operating mode 2765414c70cbSLiam Girdwood * @regulator: regulator source 2766414c70cbSLiam Girdwood * 2767414c70cbSLiam Girdwood * Get the current regulator operating mode. 2768414c70cbSLiam Girdwood */ 2769414c70cbSLiam Girdwood unsigned int regulator_get_mode(struct regulator *regulator) 2770414c70cbSLiam Girdwood { 2771414c70cbSLiam Girdwood return _regulator_get_mode(regulator->rdev); 2772414c70cbSLiam Girdwood } 2773414c70cbSLiam Girdwood EXPORT_SYMBOL_GPL(regulator_get_mode); 2774414c70cbSLiam Girdwood 2775414c70cbSLiam Girdwood /** 2776414c70cbSLiam Girdwood * regulator_set_optimum_mode - set regulator optimum operating mode 2777414c70cbSLiam Girdwood * @regulator: regulator source 2778414c70cbSLiam Girdwood * @uA_load: load current 2779414c70cbSLiam Girdwood * 2780414c70cbSLiam Girdwood * Notifies the regulator core of a new device load. This is then used by 2781414c70cbSLiam Girdwood * DRMS (if enabled by constraints) to set the most efficient regulator 2782414c70cbSLiam Girdwood * operating mode for the new regulator loading. 2783414c70cbSLiam Girdwood * 2784414c70cbSLiam Girdwood * Consumer devices notify their supply regulator of the maximum power 2785414c70cbSLiam Girdwood * they will require (can be taken from device datasheet in the power 2786414c70cbSLiam Girdwood * consumption tables) when they change operational status and hence power 2787414c70cbSLiam Girdwood * state. Examples of operational state changes that can affect power 2788414c70cbSLiam Girdwood * consumption are :- 2789414c70cbSLiam Girdwood * 2790414c70cbSLiam Girdwood * o Device is opened / closed. 2791414c70cbSLiam Girdwood * o Device I/O is about to begin or has just finished. 2792414c70cbSLiam Girdwood * o Device is idling in between work. 2793414c70cbSLiam Girdwood * 2794414c70cbSLiam Girdwood * This information is also exported via sysfs to userspace. 2795414c70cbSLiam Girdwood * 2796414c70cbSLiam Girdwood * DRMS will sum the total requested load on the regulator and change 2797414c70cbSLiam Girdwood * to the most efficient operating mode if platform constraints allow. 2798414c70cbSLiam Girdwood * 2799414c70cbSLiam Girdwood * Returns the new regulator mode or error. 2800414c70cbSLiam Girdwood */ 2801414c70cbSLiam Girdwood int regulator_set_optimum_mode(struct regulator *regulator, int uA_load) 2802414c70cbSLiam Girdwood { 2803414c70cbSLiam Girdwood struct regulator_dev *rdev = regulator->rdev; 2804414c70cbSLiam Girdwood struct regulator *consumer; 2805d92d95b6SStephen Boyd int ret, output_uV, input_uV = 0, total_uA_load = 0; 2806414c70cbSLiam Girdwood unsigned int mode; 2807414c70cbSLiam Girdwood 2808d92d95b6SStephen Boyd if (rdev->supply) 2809d92d95b6SStephen Boyd input_uV = regulator_get_voltage(rdev->supply); 2810d92d95b6SStephen Boyd 2811414c70cbSLiam Girdwood mutex_lock(&rdev->mutex); 2812414c70cbSLiam Girdwood 2813a4b41483SMark Brown /* 2814a4b41483SMark Brown * first check to see if we can set modes at all, otherwise just 2815a4b41483SMark Brown * tell the consumer everything is OK. 2816a4b41483SMark Brown */ 2817414c70cbSLiam Girdwood regulator->uA_load = uA_load; 2818414c70cbSLiam Girdwood ret = regulator_check_drms(rdev); 2819a4b41483SMark Brown if (ret < 0) { 2820a4b41483SMark Brown ret = 0; 2821414c70cbSLiam Girdwood goto out; 2822a4b41483SMark Brown } 2823414c70cbSLiam Girdwood 2824414c70cbSLiam Girdwood if (!rdev->desc->ops->get_optimum_mode) 2825414c70cbSLiam Girdwood goto out; 2826414c70cbSLiam Girdwood 2827a4b41483SMark Brown /* 2828a4b41483SMark Brown * we can actually do this so any errors are indicators of 2829a4b41483SMark Brown * potential real failure. 2830a4b41483SMark Brown */ 2831a4b41483SMark Brown ret = -EINVAL; 2832a4b41483SMark Brown 2833854ccbaeSAxel Lin if (!rdev->desc->ops->set_mode) 2834854ccbaeSAxel Lin goto out; 2835854ccbaeSAxel Lin 2836414c70cbSLiam Girdwood /* get output voltage */ 28371bf5a1f8SMark Brown output_uV = _regulator_get_voltage(rdev); 2838414c70cbSLiam Girdwood if (output_uV <= 0) { 28395da84fd9SJoe Perches rdev_err(rdev, "invalid output voltage found\n"); 2840414c70cbSLiam Girdwood goto out; 2841414c70cbSLiam Girdwood } 2842414c70cbSLiam Girdwood 2843d92d95b6SStephen Boyd /* No supply? Use constraint voltage */ 28441bf5a1f8SMark Brown if (input_uV <= 0) 2845414c70cbSLiam Girdwood input_uV = rdev->constraints->input_uV; 2846414c70cbSLiam Girdwood if (input_uV <= 0) { 28475da84fd9SJoe Perches rdev_err(rdev, "invalid input voltage found\n"); 2848414c70cbSLiam Girdwood goto out; 2849414c70cbSLiam Girdwood } 2850414c70cbSLiam Girdwood 2851414c70cbSLiam Girdwood /* calc total requested load for this regulator */ 2852414c70cbSLiam Girdwood list_for_each_entry(consumer, &rdev->consumer_list, list) 2853414c70cbSLiam Girdwood total_uA_load += consumer->uA_load; 2854414c70cbSLiam Girdwood 2855414c70cbSLiam Girdwood mode = rdev->desc->ops->get_optimum_mode(rdev, 2856414c70cbSLiam Girdwood input_uV, output_uV, 2857414c70cbSLiam Girdwood total_uA_load); 28582c608234SMark Brown ret = regulator_mode_constrain(rdev, &mode); 2859e573520bSDavid Brownell if (ret < 0) { 28605da84fd9SJoe Perches rdev_err(rdev, "failed to get optimum mode @ %d uA %d -> %d uV\n", 2861414c70cbSLiam Girdwood total_uA_load, input_uV, output_uV); 2862414c70cbSLiam Girdwood goto out; 2863414c70cbSLiam Girdwood } 2864414c70cbSLiam Girdwood 2865414c70cbSLiam Girdwood ret = rdev->desc->ops->set_mode(rdev, mode); 2866e573520bSDavid Brownell if (ret < 0) { 28675da84fd9SJoe Perches rdev_err(rdev, "failed to set optimum mode %x\n", mode); 2868414c70cbSLiam Girdwood goto out; 2869414c70cbSLiam Girdwood } 2870414c70cbSLiam Girdwood ret = mode; 2871414c70cbSLiam Girdwood out: 2872414c70cbSLiam Girdwood mutex_unlock(&rdev->mutex); 2873414c70cbSLiam Girdwood return ret; 2874414c70cbSLiam Girdwood } 2875414c70cbSLiam Girdwood EXPORT_SYMBOL_GPL(regulator_set_optimum_mode); 2876414c70cbSLiam Girdwood 2877414c70cbSLiam Girdwood /** 2878f59c8f9fSMark Brown * regulator_allow_bypass - allow the regulator to go into bypass mode 2879f59c8f9fSMark Brown * 2880f59c8f9fSMark Brown * @regulator: Regulator to configure 28819345dfb8SNishanth Menon * @enable: enable or disable bypass mode 2882f59c8f9fSMark Brown * 2883f59c8f9fSMark Brown * Allow the regulator to go into bypass mode if all other consumers 2884f59c8f9fSMark Brown * for the regulator also enable bypass mode and the machine 2885f59c8f9fSMark Brown * constraints allow this. Bypass mode means that the regulator is 2886f59c8f9fSMark Brown * simply passing the input directly to the output with no regulation. 2887f59c8f9fSMark Brown */ 2888f59c8f9fSMark Brown int regulator_allow_bypass(struct regulator *regulator, bool enable) 2889f59c8f9fSMark Brown { 2890f59c8f9fSMark Brown struct regulator_dev *rdev = regulator->rdev; 2891f59c8f9fSMark Brown int ret = 0; 2892f59c8f9fSMark Brown 2893f59c8f9fSMark Brown if (!rdev->desc->ops->set_bypass) 2894f59c8f9fSMark Brown return 0; 2895f59c8f9fSMark Brown 2896f59c8f9fSMark Brown if (rdev->constraints && 2897f59c8f9fSMark Brown !(rdev->constraints->valid_ops_mask & REGULATOR_CHANGE_BYPASS)) 2898f59c8f9fSMark Brown return 0; 2899f59c8f9fSMark Brown 2900f59c8f9fSMark Brown mutex_lock(&rdev->mutex); 2901f59c8f9fSMark Brown 2902f59c8f9fSMark Brown if (enable && !regulator->bypass) { 2903f59c8f9fSMark Brown rdev->bypass_count++; 2904f59c8f9fSMark Brown 2905f59c8f9fSMark Brown if (rdev->bypass_count == rdev->open_count) { 2906f59c8f9fSMark Brown ret = rdev->desc->ops->set_bypass(rdev, enable); 2907f59c8f9fSMark Brown if (ret != 0) 2908f59c8f9fSMark Brown rdev->bypass_count--; 2909f59c8f9fSMark Brown } 2910f59c8f9fSMark Brown 2911f59c8f9fSMark Brown } else if (!enable && regulator->bypass) { 2912f59c8f9fSMark Brown rdev->bypass_count--; 2913f59c8f9fSMark Brown 2914f59c8f9fSMark Brown if (rdev->bypass_count != rdev->open_count) { 2915f59c8f9fSMark Brown ret = rdev->desc->ops->set_bypass(rdev, enable); 2916f59c8f9fSMark Brown if (ret != 0) 2917f59c8f9fSMark Brown rdev->bypass_count++; 2918f59c8f9fSMark Brown } 2919f59c8f9fSMark Brown } 2920f59c8f9fSMark Brown 2921f59c8f9fSMark Brown if (ret == 0) 2922f59c8f9fSMark Brown regulator->bypass = enable; 2923f59c8f9fSMark Brown 2924f59c8f9fSMark Brown mutex_unlock(&rdev->mutex); 2925f59c8f9fSMark Brown 2926f59c8f9fSMark Brown return ret; 2927f59c8f9fSMark Brown } 2928f59c8f9fSMark Brown EXPORT_SYMBOL_GPL(regulator_allow_bypass); 2929f59c8f9fSMark Brown 2930f59c8f9fSMark Brown /** 2931414c70cbSLiam Girdwood * regulator_register_notifier - register regulator event notifier 2932414c70cbSLiam Girdwood * @regulator: regulator source 293369279fb9SMark Brown * @nb: notifier block 2934414c70cbSLiam Girdwood * 2935414c70cbSLiam Girdwood * Register notifier block to receive regulator events. 2936414c70cbSLiam Girdwood */ 2937414c70cbSLiam Girdwood int regulator_register_notifier(struct regulator *regulator, 2938414c70cbSLiam Girdwood struct notifier_block *nb) 2939414c70cbSLiam Girdwood { 2940414c70cbSLiam Girdwood return blocking_notifier_chain_register(®ulator->rdev->notifier, 2941414c70cbSLiam Girdwood nb); 2942414c70cbSLiam Girdwood } 2943414c70cbSLiam Girdwood EXPORT_SYMBOL_GPL(regulator_register_notifier); 2944414c70cbSLiam Girdwood 2945414c70cbSLiam Girdwood /** 2946414c70cbSLiam Girdwood * regulator_unregister_notifier - unregister regulator event notifier 2947414c70cbSLiam Girdwood * @regulator: regulator source 294869279fb9SMark Brown * @nb: notifier block 2949414c70cbSLiam Girdwood * 2950414c70cbSLiam Girdwood * Unregister regulator event notifier block. 2951414c70cbSLiam Girdwood */ 2952414c70cbSLiam Girdwood int regulator_unregister_notifier(struct regulator *regulator, 2953414c70cbSLiam Girdwood struct notifier_block *nb) 2954414c70cbSLiam Girdwood { 2955414c70cbSLiam Girdwood return blocking_notifier_chain_unregister(®ulator->rdev->notifier, 2956414c70cbSLiam Girdwood nb); 2957414c70cbSLiam Girdwood } 2958414c70cbSLiam Girdwood EXPORT_SYMBOL_GPL(regulator_unregister_notifier); 2959414c70cbSLiam Girdwood 2960b136fb44SJonathan Cameron /* notify regulator consumers and downstream regulator consumers. 2961b136fb44SJonathan Cameron * Note mutex must be held by caller. 2962b136fb44SJonathan Cameron */ 2963414c70cbSLiam Girdwood static void _notifier_call_chain(struct regulator_dev *rdev, 2964414c70cbSLiam Girdwood unsigned long event, void *data) 2965414c70cbSLiam Girdwood { 2966414c70cbSLiam Girdwood /* call rdev chain first */ 2967d8493d21SMark Brown blocking_notifier_call_chain(&rdev->notifier, event, data); 2968414c70cbSLiam Girdwood } 2969414c70cbSLiam Girdwood 2970414c70cbSLiam Girdwood /** 2971414c70cbSLiam Girdwood * regulator_bulk_get - get multiple regulator consumers 2972414c70cbSLiam Girdwood * 2973414c70cbSLiam Girdwood * @dev: Device to supply 2974414c70cbSLiam Girdwood * @num_consumers: Number of consumers to register 2975414c70cbSLiam Girdwood * @consumers: Configuration of consumers; clients are stored here. 2976414c70cbSLiam Girdwood * 2977414c70cbSLiam Girdwood * @return 0 on success, an errno on failure. 2978414c70cbSLiam Girdwood * 2979414c70cbSLiam Girdwood * This helper function allows drivers to get several regulator 2980414c70cbSLiam Girdwood * consumers in one operation. If any of the regulators cannot be 2981414c70cbSLiam Girdwood * acquired then any regulators that were allocated will be freed 2982414c70cbSLiam Girdwood * before returning to the caller. 2983414c70cbSLiam Girdwood */ 2984414c70cbSLiam Girdwood int regulator_bulk_get(struct device *dev, int num_consumers, 2985414c70cbSLiam Girdwood struct regulator_bulk_data *consumers) 2986414c70cbSLiam Girdwood { 2987414c70cbSLiam Girdwood int i; 2988414c70cbSLiam Girdwood int ret; 2989414c70cbSLiam Girdwood 2990414c70cbSLiam Girdwood for (i = 0; i < num_consumers; i++) 2991414c70cbSLiam Girdwood consumers[i].consumer = NULL; 2992414c70cbSLiam Girdwood 2993414c70cbSLiam Girdwood for (i = 0; i < num_consumers; i++) { 2994414c70cbSLiam Girdwood consumers[i].consumer = regulator_get(dev, 2995414c70cbSLiam Girdwood consumers[i].supply); 2996414c70cbSLiam Girdwood if (IS_ERR(consumers[i].consumer)) { 2997414c70cbSLiam Girdwood ret = PTR_ERR(consumers[i].consumer); 29985b307627SMark Brown dev_err(dev, "Failed to get supply '%s': %d\n", 29995b307627SMark Brown consumers[i].supply, ret); 3000414c70cbSLiam Girdwood consumers[i].consumer = NULL; 3001414c70cbSLiam Girdwood goto err; 3002414c70cbSLiam Girdwood } 3003414c70cbSLiam Girdwood } 3004414c70cbSLiam Girdwood 3005414c70cbSLiam Girdwood return 0; 3006414c70cbSLiam Girdwood 3007414c70cbSLiam Girdwood err: 3008b29c7690SAxel Lin while (--i >= 0) 3009414c70cbSLiam Girdwood regulator_put(consumers[i].consumer); 3010414c70cbSLiam Girdwood 3011414c70cbSLiam Girdwood return ret; 3012414c70cbSLiam Girdwood } 3013414c70cbSLiam Girdwood EXPORT_SYMBOL_GPL(regulator_bulk_get); 3014414c70cbSLiam Girdwood 3015f21e0e81SMark Brown static void regulator_bulk_enable_async(void *data, async_cookie_t cookie) 3016f21e0e81SMark Brown { 3017f21e0e81SMark Brown struct regulator_bulk_data *bulk = data; 3018f21e0e81SMark Brown 3019f21e0e81SMark Brown bulk->ret = regulator_enable(bulk->consumer); 3020f21e0e81SMark Brown } 3021f21e0e81SMark Brown 3022414c70cbSLiam Girdwood /** 3023414c70cbSLiam Girdwood * regulator_bulk_enable - enable multiple regulator consumers 3024414c70cbSLiam Girdwood * 3025414c70cbSLiam Girdwood * @num_consumers: Number of consumers 3026414c70cbSLiam Girdwood * @consumers: Consumer data; clients are stored here. 3027414c70cbSLiam Girdwood * @return 0 on success, an errno on failure 3028414c70cbSLiam Girdwood * 3029414c70cbSLiam Girdwood * This convenience API allows consumers to enable multiple regulator 3030414c70cbSLiam Girdwood * clients in a single API call. If any consumers cannot be enabled 3031414c70cbSLiam Girdwood * then any others that were enabled will be disabled again prior to 3032414c70cbSLiam Girdwood * return. 3033414c70cbSLiam Girdwood */ 3034414c70cbSLiam Girdwood int regulator_bulk_enable(int num_consumers, 3035414c70cbSLiam Girdwood struct regulator_bulk_data *consumers) 3036414c70cbSLiam Girdwood { 30372955b47dSDan Williams ASYNC_DOMAIN_EXCLUSIVE(async_domain); 3038414c70cbSLiam Girdwood int i; 3039f21e0e81SMark Brown int ret = 0; 3040414c70cbSLiam Girdwood 30416492bc1bSMark Brown for (i = 0; i < num_consumers; i++) { 30426492bc1bSMark Brown if (consumers[i].consumer->always_on) 30436492bc1bSMark Brown consumers[i].ret = 0; 30446492bc1bSMark Brown else 3045f21e0e81SMark Brown async_schedule_domain(regulator_bulk_enable_async, 3046f21e0e81SMark Brown &consumers[i], &async_domain); 30476492bc1bSMark Brown } 3048f21e0e81SMark Brown 3049f21e0e81SMark Brown async_synchronize_full_domain(&async_domain); 3050f21e0e81SMark Brown 3051f21e0e81SMark Brown /* If any consumer failed we need to unwind any that succeeded */ 3052414c70cbSLiam Girdwood for (i = 0; i < num_consumers; i++) { 3053f21e0e81SMark Brown if (consumers[i].ret != 0) { 3054f21e0e81SMark Brown ret = consumers[i].ret; 3055414c70cbSLiam Girdwood goto err; 3056414c70cbSLiam Girdwood } 3057f21e0e81SMark Brown } 3058414c70cbSLiam Girdwood 3059414c70cbSLiam Girdwood return 0; 3060414c70cbSLiam Girdwood 3061414c70cbSLiam Girdwood err: 3062fbe31057SAndrzej Hajda for (i = 0; i < num_consumers; i++) { 3063fbe31057SAndrzej Hajda if (consumers[i].ret < 0) 3064fbe31057SAndrzej Hajda pr_err("Failed to enable %s: %d\n", consumers[i].supply, 3065fbe31057SAndrzej Hajda consumers[i].ret); 3066fbe31057SAndrzej Hajda else 3067414c70cbSLiam Girdwood regulator_disable(consumers[i].consumer); 3068fbe31057SAndrzej Hajda } 3069414c70cbSLiam Girdwood 3070414c70cbSLiam Girdwood return ret; 3071414c70cbSLiam Girdwood } 3072414c70cbSLiam Girdwood EXPORT_SYMBOL_GPL(regulator_bulk_enable); 3073414c70cbSLiam Girdwood 3074414c70cbSLiam Girdwood /** 3075414c70cbSLiam Girdwood * regulator_bulk_disable - disable multiple regulator consumers 3076414c70cbSLiam Girdwood * 3077414c70cbSLiam Girdwood * @num_consumers: Number of consumers 3078414c70cbSLiam Girdwood * @consumers: Consumer data; clients are stored here. 3079414c70cbSLiam Girdwood * @return 0 on success, an errno on failure 3080414c70cbSLiam Girdwood * 3081414c70cbSLiam Girdwood * This convenience API allows consumers to disable multiple regulator 308249e22632SSylwester Nawrocki * clients in a single API call. If any consumers cannot be disabled 308349e22632SSylwester Nawrocki * then any others that were disabled will be enabled again prior to 3084414c70cbSLiam Girdwood * return. 3085414c70cbSLiam Girdwood */ 3086414c70cbSLiam Girdwood int regulator_bulk_disable(int num_consumers, 3087414c70cbSLiam Girdwood struct regulator_bulk_data *consumers) 3088414c70cbSLiam Girdwood { 3089414c70cbSLiam Girdwood int i; 309001e86f49SMark Brown int ret, r; 3091414c70cbSLiam Girdwood 309249e22632SSylwester Nawrocki for (i = num_consumers - 1; i >= 0; --i) { 3093414c70cbSLiam Girdwood ret = regulator_disable(consumers[i].consumer); 3094414c70cbSLiam Girdwood if (ret != 0) 3095414c70cbSLiam Girdwood goto err; 3096414c70cbSLiam Girdwood } 3097414c70cbSLiam Girdwood 3098414c70cbSLiam Girdwood return 0; 3099414c70cbSLiam Girdwood 3100414c70cbSLiam Girdwood err: 31015da84fd9SJoe Perches pr_err("Failed to disable %s: %d\n", consumers[i].supply, ret); 310201e86f49SMark Brown for (++i; i < num_consumers; ++i) { 310301e86f49SMark Brown r = regulator_enable(consumers[i].consumer); 310401e86f49SMark Brown if (r != 0) 310501e86f49SMark Brown pr_err("Failed to reename %s: %d\n", 310601e86f49SMark Brown consumers[i].supply, r); 310701e86f49SMark Brown } 3108414c70cbSLiam Girdwood 3109414c70cbSLiam Girdwood return ret; 3110414c70cbSLiam Girdwood } 3111414c70cbSLiam Girdwood EXPORT_SYMBOL_GPL(regulator_bulk_disable); 3112414c70cbSLiam Girdwood 3113414c70cbSLiam Girdwood /** 3114e1de2f42SDonggeun Kim * regulator_bulk_force_disable - force disable multiple regulator consumers 3115e1de2f42SDonggeun Kim * 3116e1de2f42SDonggeun Kim * @num_consumers: Number of consumers 3117e1de2f42SDonggeun Kim * @consumers: Consumer data; clients are stored here. 3118e1de2f42SDonggeun Kim * @return 0 on success, an errno on failure 3119e1de2f42SDonggeun Kim * 3120e1de2f42SDonggeun Kim * This convenience API allows consumers to forcibly disable multiple regulator 3121e1de2f42SDonggeun Kim * clients in a single API call. 3122e1de2f42SDonggeun Kim * NOTE: This should be used for situations when device damage will 3123e1de2f42SDonggeun Kim * likely occur if the regulators are not disabled (e.g. over temp). 3124e1de2f42SDonggeun Kim * Although regulator_force_disable function call for some consumers can 3125e1de2f42SDonggeun Kim * return error numbers, the function is called for all consumers. 3126e1de2f42SDonggeun Kim */ 3127e1de2f42SDonggeun Kim int regulator_bulk_force_disable(int num_consumers, 3128e1de2f42SDonggeun Kim struct regulator_bulk_data *consumers) 3129e1de2f42SDonggeun Kim { 3130e1de2f42SDonggeun Kim int i; 3131e1de2f42SDonggeun Kim int ret; 3132e1de2f42SDonggeun Kim 3133e1de2f42SDonggeun Kim for (i = 0; i < num_consumers; i++) 3134e1de2f42SDonggeun Kim consumers[i].ret = 3135e1de2f42SDonggeun Kim regulator_force_disable(consumers[i].consumer); 3136e1de2f42SDonggeun Kim 3137e1de2f42SDonggeun Kim for (i = 0; i < num_consumers; i++) { 3138e1de2f42SDonggeun Kim if (consumers[i].ret != 0) { 3139e1de2f42SDonggeun Kim ret = consumers[i].ret; 3140e1de2f42SDonggeun Kim goto out; 3141e1de2f42SDonggeun Kim } 3142e1de2f42SDonggeun Kim } 3143e1de2f42SDonggeun Kim 3144e1de2f42SDonggeun Kim return 0; 3145e1de2f42SDonggeun Kim out: 3146e1de2f42SDonggeun Kim return ret; 3147e1de2f42SDonggeun Kim } 3148e1de2f42SDonggeun Kim EXPORT_SYMBOL_GPL(regulator_bulk_force_disable); 3149e1de2f42SDonggeun Kim 3150e1de2f42SDonggeun Kim /** 3151414c70cbSLiam Girdwood * regulator_bulk_free - free multiple regulator consumers 3152414c70cbSLiam Girdwood * 3153414c70cbSLiam Girdwood * @num_consumers: Number of consumers 3154414c70cbSLiam Girdwood * @consumers: Consumer data; clients are stored here. 3155414c70cbSLiam Girdwood * 3156414c70cbSLiam Girdwood * This convenience API allows consumers to free multiple regulator 3157414c70cbSLiam Girdwood * clients in a single API call. 3158414c70cbSLiam Girdwood */ 3159414c70cbSLiam Girdwood void regulator_bulk_free(int num_consumers, 3160414c70cbSLiam Girdwood struct regulator_bulk_data *consumers) 3161414c70cbSLiam Girdwood { 3162414c70cbSLiam Girdwood int i; 3163414c70cbSLiam Girdwood 3164414c70cbSLiam Girdwood for (i = 0; i < num_consumers; i++) { 3165414c70cbSLiam Girdwood regulator_put(consumers[i].consumer); 3166414c70cbSLiam Girdwood consumers[i].consumer = NULL; 3167414c70cbSLiam Girdwood } 3168414c70cbSLiam Girdwood } 3169414c70cbSLiam Girdwood EXPORT_SYMBOL_GPL(regulator_bulk_free); 3170414c70cbSLiam Girdwood 3171414c70cbSLiam Girdwood /** 3172414c70cbSLiam Girdwood * regulator_notifier_call_chain - call regulator event notifier 317369279fb9SMark Brown * @rdev: regulator source 3174414c70cbSLiam Girdwood * @event: notifier block 317569279fb9SMark Brown * @data: callback-specific data. 3176414c70cbSLiam Girdwood * 3177414c70cbSLiam Girdwood * Called by regulator drivers to notify clients a regulator event has 3178414c70cbSLiam Girdwood * occurred. We also notify regulator clients downstream. 3179b136fb44SJonathan Cameron * Note lock must be held by caller. 3180414c70cbSLiam Girdwood */ 3181414c70cbSLiam Girdwood int regulator_notifier_call_chain(struct regulator_dev *rdev, 3182414c70cbSLiam Girdwood unsigned long event, void *data) 3183414c70cbSLiam Girdwood { 3184414c70cbSLiam Girdwood _notifier_call_chain(rdev, event, data); 3185414c70cbSLiam Girdwood return NOTIFY_DONE; 3186414c70cbSLiam Girdwood 3187414c70cbSLiam Girdwood } 3188414c70cbSLiam Girdwood EXPORT_SYMBOL_GPL(regulator_notifier_call_chain); 3189414c70cbSLiam Girdwood 3190be721979SMark Brown /** 3191be721979SMark Brown * regulator_mode_to_status - convert a regulator mode into a status 3192be721979SMark Brown * 3193be721979SMark Brown * @mode: Mode to convert 3194be721979SMark Brown * 3195be721979SMark Brown * Convert a regulator mode into a status. 3196be721979SMark Brown */ 3197be721979SMark Brown int regulator_mode_to_status(unsigned int mode) 3198be721979SMark Brown { 3199be721979SMark Brown switch (mode) { 3200be721979SMark Brown case REGULATOR_MODE_FAST: 3201be721979SMark Brown return REGULATOR_STATUS_FAST; 3202be721979SMark Brown case REGULATOR_MODE_NORMAL: 3203be721979SMark Brown return REGULATOR_STATUS_NORMAL; 3204be721979SMark Brown case REGULATOR_MODE_IDLE: 3205be721979SMark Brown return REGULATOR_STATUS_IDLE; 320603ffcf3dSKrystian Garbaciak case REGULATOR_MODE_STANDBY: 3207be721979SMark Brown return REGULATOR_STATUS_STANDBY; 3208be721979SMark Brown default: 32091beaf762SKrystian Garbaciak return REGULATOR_STATUS_UNDEFINED; 3210be721979SMark Brown } 3211be721979SMark Brown } 3212be721979SMark Brown EXPORT_SYMBOL_GPL(regulator_mode_to_status); 3213be721979SMark Brown 32147ad68e2fSDavid Brownell /* 32157ad68e2fSDavid Brownell * To avoid cluttering sysfs (and memory) with useless state, only 32167ad68e2fSDavid Brownell * create attributes that can be meaningfully displayed. 32177ad68e2fSDavid Brownell */ 32187ad68e2fSDavid Brownell static int add_regulator_attributes(struct regulator_dev *rdev) 32197ad68e2fSDavid Brownell { 32207ad68e2fSDavid Brownell struct device *dev = &rdev->dev; 32217ad68e2fSDavid Brownell struct regulator_ops *ops = rdev->desc->ops; 32227ad68e2fSDavid Brownell int status = 0; 32237ad68e2fSDavid Brownell 32247ad68e2fSDavid Brownell /* some attributes need specific methods to be displayed */ 32254c78899bSMark Brown if ((ops->get_voltage && ops->get_voltage(rdev) >= 0) || 3226f2889e65SMark Brown (ops->get_voltage_sel && ops->get_voltage_sel(rdev) >= 0) || 32275a523605SLaxman Dewangan (ops->list_voltage && ops->list_voltage(rdev, 0) >= 0) || 32285a523605SLaxman Dewangan (rdev->desc->fixed_uV && (rdev->desc->n_voltages == 1))) { 32297ad68e2fSDavid Brownell status = device_create_file(dev, &dev_attr_microvolts); 32307ad68e2fSDavid Brownell if (status < 0) 32317ad68e2fSDavid Brownell return status; 32327ad68e2fSDavid Brownell } 32337ad68e2fSDavid Brownell if (ops->get_current_limit) { 32347ad68e2fSDavid Brownell status = device_create_file(dev, &dev_attr_microamps); 32357ad68e2fSDavid Brownell if (status < 0) 32367ad68e2fSDavid Brownell return status; 32377ad68e2fSDavid Brownell } 32387ad68e2fSDavid Brownell if (ops->get_mode) { 32397ad68e2fSDavid Brownell status = device_create_file(dev, &dev_attr_opmode); 32407ad68e2fSDavid Brownell if (status < 0) 32417ad68e2fSDavid Brownell return status; 32427ad68e2fSDavid Brownell } 32437b74d149SKim, Milo if (rdev->ena_pin || ops->is_enabled) { 32447ad68e2fSDavid Brownell status = device_create_file(dev, &dev_attr_state); 32457ad68e2fSDavid Brownell if (status < 0) 32467ad68e2fSDavid Brownell return status; 32477ad68e2fSDavid Brownell } 3248853116a1SDavid Brownell if (ops->get_status) { 3249853116a1SDavid Brownell status = device_create_file(dev, &dev_attr_status); 3250853116a1SDavid Brownell if (status < 0) 3251853116a1SDavid Brownell return status; 3252853116a1SDavid Brownell } 3253f59c8f9fSMark Brown if (ops->get_bypass) { 3254f59c8f9fSMark Brown status = device_create_file(dev, &dev_attr_bypass); 3255f59c8f9fSMark Brown if (status < 0) 3256f59c8f9fSMark Brown return status; 3257f59c8f9fSMark Brown } 32587ad68e2fSDavid Brownell 32597ad68e2fSDavid Brownell /* some attributes are type-specific */ 32607ad68e2fSDavid Brownell if (rdev->desc->type == REGULATOR_CURRENT) { 32617ad68e2fSDavid Brownell status = device_create_file(dev, &dev_attr_requested_microamps); 32627ad68e2fSDavid Brownell if (status < 0) 32637ad68e2fSDavid Brownell return status; 32647ad68e2fSDavid Brownell } 32657ad68e2fSDavid Brownell 32667ad68e2fSDavid Brownell /* all the other attributes exist to support constraints; 32677ad68e2fSDavid Brownell * don't show them if there are no constraints, or if the 32687ad68e2fSDavid Brownell * relevant supporting methods are missing. 32697ad68e2fSDavid Brownell */ 32707ad68e2fSDavid Brownell if (!rdev->constraints) 32717ad68e2fSDavid Brownell return status; 32727ad68e2fSDavid Brownell 32737ad68e2fSDavid Brownell /* constraints need specific supporting methods */ 3274e8eef82bSMark Brown if (ops->set_voltage || ops->set_voltage_sel) { 32757ad68e2fSDavid Brownell status = device_create_file(dev, &dev_attr_min_microvolts); 32767ad68e2fSDavid Brownell if (status < 0) 32777ad68e2fSDavid Brownell return status; 32787ad68e2fSDavid Brownell status = device_create_file(dev, &dev_attr_max_microvolts); 32797ad68e2fSDavid Brownell if (status < 0) 32807ad68e2fSDavid Brownell return status; 32817ad68e2fSDavid Brownell } 32827ad68e2fSDavid Brownell if (ops->set_current_limit) { 32837ad68e2fSDavid Brownell status = device_create_file(dev, &dev_attr_min_microamps); 32847ad68e2fSDavid Brownell if (status < 0) 32857ad68e2fSDavid Brownell return status; 32867ad68e2fSDavid Brownell status = device_create_file(dev, &dev_attr_max_microamps); 32877ad68e2fSDavid Brownell if (status < 0) 32887ad68e2fSDavid Brownell return status; 32897ad68e2fSDavid Brownell } 32907ad68e2fSDavid Brownell 32917ad68e2fSDavid Brownell status = device_create_file(dev, &dev_attr_suspend_standby_state); 32927ad68e2fSDavid Brownell if (status < 0) 32937ad68e2fSDavid Brownell return status; 32947ad68e2fSDavid Brownell status = device_create_file(dev, &dev_attr_suspend_mem_state); 32957ad68e2fSDavid Brownell if (status < 0) 32967ad68e2fSDavid Brownell return status; 32977ad68e2fSDavid Brownell status = device_create_file(dev, &dev_attr_suspend_disk_state); 32987ad68e2fSDavid Brownell if (status < 0) 32997ad68e2fSDavid Brownell return status; 33007ad68e2fSDavid Brownell 33017ad68e2fSDavid Brownell if (ops->set_suspend_voltage) { 33027ad68e2fSDavid Brownell status = device_create_file(dev, 33037ad68e2fSDavid Brownell &dev_attr_suspend_standby_microvolts); 33047ad68e2fSDavid Brownell if (status < 0) 33057ad68e2fSDavid Brownell return status; 33067ad68e2fSDavid Brownell status = device_create_file(dev, 33077ad68e2fSDavid Brownell &dev_attr_suspend_mem_microvolts); 33087ad68e2fSDavid Brownell if (status < 0) 33097ad68e2fSDavid Brownell return status; 33107ad68e2fSDavid Brownell status = device_create_file(dev, 33117ad68e2fSDavid Brownell &dev_attr_suspend_disk_microvolts); 33127ad68e2fSDavid Brownell if (status < 0) 33137ad68e2fSDavid Brownell return status; 33147ad68e2fSDavid Brownell } 33157ad68e2fSDavid Brownell 33167ad68e2fSDavid Brownell if (ops->set_suspend_mode) { 33177ad68e2fSDavid Brownell status = device_create_file(dev, 33187ad68e2fSDavid Brownell &dev_attr_suspend_standby_mode); 33197ad68e2fSDavid Brownell if (status < 0) 33207ad68e2fSDavid Brownell return status; 33217ad68e2fSDavid Brownell status = device_create_file(dev, 33227ad68e2fSDavid Brownell &dev_attr_suspend_mem_mode); 33237ad68e2fSDavid Brownell if (status < 0) 33247ad68e2fSDavid Brownell return status; 33257ad68e2fSDavid Brownell status = device_create_file(dev, 33267ad68e2fSDavid Brownell &dev_attr_suspend_disk_mode); 33277ad68e2fSDavid Brownell if (status < 0) 33287ad68e2fSDavid Brownell return status; 33297ad68e2fSDavid Brownell } 33307ad68e2fSDavid Brownell 33317ad68e2fSDavid Brownell return status; 33327ad68e2fSDavid Brownell } 33337ad68e2fSDavid Brownell 33341130e5b3SMark Brown static void rdev_init_debugfs(struct regulator_dev *rdev) 33351130e5b3SMark Brown { 33361130e5b3SMark Brown rdev->debugfs = debugfs_create_dir(rdev_get_name(rdev), debugfs_root); 333724751434SStephen Boyd if (!rdev->debugfs) { 33381130e5b3SMark Brown rdev_warn(rdev, "Failed to create debugfs directory\n"); 33391130e5b3SMark Brown return; 33401130e5b3SMark Brown } 33411130e5b3SMark Brown 33421130e5b3SMark Brown debugfs_create_u32("use_count", 0444, rdev->debugfs, 33431130e5b3SMark Brown &rdev->use_count); 33441130e5b3SMark Brown debugfs_create_u32("open_count", 0444, rdev->debugfs, 33451130e5b3SMark Brown &rdev->open_count); 3346f59c8f9fSMark Brown debugfs_create_u32("bypass_count", 0444, rdev->debugfs, 3347f59c8f9fSMark Brown &rdev->bypass_count); 33481130e5b3SMark Brown } 33491130e5b3SMark Brown 3350414c70cbSLiam Girdwood /** 3351414c70cbSLiam Girdwood * regulator_register - register regulator 335269279fb9SMark Brown * @regulator_desc: regulator to register 3353c172708dSMark Brown * @config: runtime configuration for regulator 3354414c70cbSLiam Girdwood * 3355414c70cbSLiam Girdwood * Called by regulator drivers to register a regulator. 33560384618aSAxel Lin * Returns a valid pointer to struct regulator_dev on success 33570384618aSAxel Lin * or an ERR_PTR() on error. 3358414c70cbSLiam Girdwood */ 335965f26846SMark Brown struct regulator_dev * 336065f26846SMark Brown regulator_register(const struct regulator_desc *regulator_desc, 3361c172708dSMark Brown const struct regulator_config *config) 3362414c70cbSLiam Girdwood { 33639a8f5e07SMark Brown const struct regulation_constraints *constraints = NULL; 3364c172708dSMark Brown const struct regulator_init_data *init_data; 3365414c70cbSLiam Girdwood static atomic_t regulator_no = ATOMIC_INIT(0); 3366414c70cbSLiam Girdwood struct regulator_dev *rdev; 336732c8fad4SMark Brown struct device *dev; 3368a5766f11SLiam Girdwood int ret, i; 336969511a45SRajendra Nayak const char *supply = NULL; 3370414c70cbSLiam Girdwood 3371c172708dSMark Brown if (regulator_desc == NULL || config == NULL) 3372414c70cbSLiam Girdwood return ERR_PTR(-EINVAL); 3373414c70cbSLiam Girdwood 337432c8fad4SMark Brown dev = config->dev; 3375dcf70112SMark Brown WARN_ON(!dev); 337632c8fad4SMark Brown 3377414c70cbSLiam Girdwood if (regulator_desc->name == NULL || regulator_desc->ops == NULL) 3378414c70cbSLiam Girdwood return ERR_PTR(-EINVAL); 3379414c70cbSLiam Girdwood 3380cd78dfc6SDiego Liziero if (regulator_desc->type != REGULATOR_VOLTAGE && 3381cd78dfc6SDiego Liziero regulator_desc->type != REGULATOR_CURRENT) 3382414c70cbSLiam Girdwood return ERR_PTR(-EINVAL); 3383414c70cbSLiam Girdwood 3384476c2d83SMark Brown /* Only one of each should be implemented */ 3385476c2d83SMark Brown WARN_ON(regulator_desc->ops->get_voltage && 3386476c2d83SMark Brown regulator_desc->ops->get_voltage_sel); 3387e8eef82bSMark Brown WARN_ON(regulator_desc->ops->set_voltage && 3388e8eef82bSMark Brown regulator_desc->ops->set_voltage_sel); 3389476c2d83SMark Brown 3390476c2d83SMark Brown /* If we're using selectors we must implement list_voltage. */ 3391476c2d83SMark Brown if (regulator_desc->ops->get_voltage_sel && 3392476c2d83SMark Brown !regulator_desc->ops->list_voltage) { 3393476c2d83SMark Brown return ERR_PTR(-EINVAL); 3394476c2d83SMark Brown } 3395e8eef82bSMark Brown if (regulator_desc->ops->set_voltage_sel && 3396e8eef82bSMark Brown !regulator_desc->ops->list_voltage) { 3397e8eef82bSMark Brown return ERR_PTR(-EINVAL); 3398e8eef82bSMark Brown } 3399476c2d83SMark Brown 3400c172708dSMark Brown init_data = config->init_data; 3401c172708dSMark Brown 3402414c70cbSLiam Girdwood rdev = kzalloc(sizeof(struct regulator_dev), GFP_KERNEL); 3403414c70cbSLiam Girdwood if (rdev == NULL) 3404414c70cbSLiam Girdwood return ERR_PTR(-ENOMEM); 3405414c70cbSLiam Girdwood 3406414c70cbSLiam Girdwood mutex_lock(®ulator_list_mutex); 3407414c70cbSLiam Girdwood 3408414c70cbSLiam Girdwood mutex_init(&rdev->mutex); 3409c172708dSMark Brown rdev->reg_data = config->driver_data; 3410414c70cbSLiam Girdwood rdev->owner = regulator_desc->owner; 3411414c70cbSLiam Girdwood rdev->desc = regulator_desc; 34123a4b0a07SMark Brown if (config->regmap) 341365b19ce6SMark Brown rdev->regmap = config->regmap; 341452b84dacSAnilKumar Ch else if (dev_get_regmap(dev, NULL)) 34153a4b0a07SMark Brown rdev->regmap = dev_get_regmap(dev, NULL); 341652b84dacSAnilKumar Ch else if (dev->parent) 341752b84dacSAnilKumar Ch rdev->regmap = dev_get_regmap(dev->parent, NULL); 3418414c70cbSLiam Girdwood INIT_LIST_HEAD(&rdev->consumer_list); 3419414c70cbSLiam Girdwood INIT_LIST_HEAD(&rdev->list); 3420414c70cbSLiam Girdwood BLOCKING_INIT_NOTIFIER_HEAD(&rdev->notifier); 3421da07ecd9SMark Brown INIT_DELAYED_WORK(&rdev->disable_work, regulator_disable_work); 3422414c70cbSLiam Girdwood 3423a5766f11SLiam Girdwood /* preform any regulator specific init */ 34249a8f5e07SMark Brown if (init_data && init_data->regulator_init) { 3425a5766f11SLiam Girdwood ret = init_data->regulator_init(rdev->reg_data); 34264fca9545SDavid Brownell if (ret < 0) 34274fca9545SDavid Brownell goto clean; 3428a5766f11SLiam Girdwood } 3429a5766f11SLiam Girdwood 3430a5766f11SLiam Girdwood /* register with sysfs */ 3431a5766f11SLiam Girdwood rdev->dev.class = ®ulator_class; 3432c172708dSMark Brown rdev->dev.of_node = config->of_node; 3433a5766f11SLiam Girdwood rdev->dev.parent = dev; 3434812460a9SKay Sievers dev_set_name(&rdev->dev, "regulator.%d", 3435812460a9SKay Sievers atomic_inc_return(®ulator_no) - 1); 3436a5766f11SLiam Girdwood ret = device_register(&rdev->dev); 3437ad7725cbSVasiliy Kulikov if (ret != 0) { 3438ad7725cbSVasiliy Kulikov put_device(&rdev->dev); 34394fca9545SDavid Brownell goto clean; 3440ad7725cbSVasiliy Kulikov } 3441a5766f11SLiam Girdwood 3442a5766f11SLiam Girdwood dev_set_drvdata(&rdev->dev, rdev); 3443a5766f11SLiam Girdwood 3444b2a1ef47SMarek Szyprowski if (config->ena_gpio && gpio_is_valid(config->ena_gpio)) { 3445f19b00daSKim, Milo ret = regulator_ena_gpio_request(rdev, config); 344665f73508SMark Brown if (ret != 0) { 344765f73508SMark Brown rdev_err(rdev, "Failed to request enable GPIO%d: %d\n", 344865f73508SMark Brown config->ena_gpio, ret); 3449b2da55d9SAndrew Lunn goto wash; 345065f73508SMark Brown } 345165f73508SMark Brown 345265f73508SMark Brown if (config->ena_gpio_flags & GPIOF_OUT_INIT_HIGH) 345365f73508SMark Brown rdev->ena_gpio_state = 1; 345465f73508SMark Brown 34557b74d149SKim, Milo if (config->ena_gpio_invert) 345665f73508SMark Brown rdev->ena_gpio_state = !rdev->ena_gpio_state; 345765f73508SMark Brown } 345865f73508SMark Brown 345974f544c1SMike Rapoport /* set regulator constraints */ 34609a8f5e07SMark Brown if (init_data) 34619a8f5e07SMark Brown constraints = &init_data->constraints; 34629a8f5e07SMark Brown 34639a8f5e07SMark Brown ret = set_machine_constraints(rdev, constraints); 346474f544c1SMike Rapoport if (ret < 0) 346574f544c1SMike Rapoport goto scrub; 346674f544c1SMike Rapoport 34677ad68e2fSDavid Brownell /* add attributes supported by this regulator */ 34687ad68e2fSDavid Brownell ret = add_regulator_attributes(rdev); 34697ad68e2fSDavid Brownell if (ret < 0) 34707ad68e2fSDavid Brownell goto scrub; 34717ad68e2fSDavid Brownell 34729a8f5e07SMark Brown if (init_data && init_data->supply_regulator) 347369511a45SRajendra Nayak supply = init_data->supply_regulator; 347469511a45SRajendra Nayak else if (regulator_desc->supply_name) 347569511a45SRajendra Nayak supply = regulator_desc->supply_name; 347669511a45SRajendra Nayak 347769511a45SRajendra Nayak if (supply) { 34780178f3e2SMark Brown struct regulator_dev *r; 34790178f3e2SMark Brown 34806d191a5fSMark Brown r = regulator_dev_lookup(dev, supply, &ret); 34810178f3e2SMark Brown 34820f7b87f0SAndrew Bresticker if (ret == -ENODEV) { 34830f7b87f0SAndrew Bresticker /* 34840f7b87f0SAndrew Bresticker * No supply was specified for this regulator and 34850f7b87f0SAndrew Bresticker * there will never be one. 34860f7b87f0SAndrew Bresticker */ 34870f7b87f0SAndrew Bresticker ret = 0; 34880f7b87f0SAndrew Bresticker goto add_dev; 34890f7b87f0SAndrew Bresticker } else if (!r) { 349069511a45SRajendra Nayak dev_err(dev, "Failed to find supply %s\n", supply); 349104bf3011SMark Brown ret = -EPROBE_DEFER; 34920178f3e2SMark Brown goto scrub; 34930178f3e2SMark Brown } 34940178f3e2SMark Brown 34950178f3e2SMark Brown ret = set_supply(rdev, r); 34960178f3e2SMark Brown if (ret < 0) 34970178f3e2SMark Brown goto scrub; 3498b2296bd4SLaxman Dewangan 3499b2296bd4SLaxman Dewangan /* Enable supply if rail is enabled */ 3500b1a86831SMark Brown if (_regulator_is_enabled(rdev)) { 3501b2296bd4SLaxman Dewangan ret = regulator_enable(rdev->supply); 3502b2296bd4SLaxman Dewangan if (ret < 0) 3503b2296bd4SLaxman Dewangan goto scrub; 3504b2296bd4SLaxman Dewangan } 35050178f3e2SMark Brown } 35060178f3e2SMark Brown 35070f7b87f0SAndrew Bresticker add_dev: 3508a5766f11SLiam Girdwood /* add consumers devices */ 35099a8f5e07SMark Brown if (init_data) { 3510a5766f11SLiam Girdwood for (i = 0; i < init_data->num_consumer_supplies; i++) { 3511a5766f11SLiam Girdwood ret = set_consumer_device_supply(rdev, 351240f9244fSMark Brown init_data->consumer_supplies[i].dev_name, 3513a5766f11SLiam Girdwood init_data->consumer_supplies[i].supply); 351423c2f041SMark Brown if (ret < 0) { 351523c2f041SMark Brown dev_err(dev, "Failed to set supply %s\n", 351623c2f041SMark Brown init_data->consumer_supplies[i].supply); 3517d4033b54SJani Nikula goto unset_supplies; 3518a5766f11SLiam Girdwood } 351923c2f041SMark Brown } 35209a8f5e07SMark Brown } 3521a5766f11SLiam Girdwood 3522a5766f11SLiam Girdwood list_add(&rdev->list, ®ulator_list); 35231130e5b3SMark Brown 35241130e5b3SMark Brown rdev_init_debugfs(rdev); 3525a5766f11SLiam Girdwood out: 3526414c70cbSLiam Girdwood mutex_unlock(®ulator_list_mutex); 3527414c70cbSLiam Girdwood return rdev; 35284fca9545SDavid Brownell 3529d4033b54SJani Nikula unset_supplies: 3530d4033b54SJani Nikula unset_regulator_supplies(rdev); 3531d4033b54SJani Nikula 35324fca9545SDavid Brownell scrub: 3533e81dba85SMark Brown if (rdev->supply) 353423ff2f0fSCharles Keepax _regulator_put(rdev->supply); 3535f19b00daSKim, Milo regulator_ena_gpio_free(rdev); 35361a6958e7SAxel Lin kfree(rdev->constraints); 3537b2da55d9SAndrew Lunn wash: 35384fca9545SDavid Brownell device_unregister(&rdev->dev); 353953032dafSPaul Walmsley /* device core frees rdev */ 354053032dafSPaul Walmsley rdev = ERR_PTR(ret); 354153032dafSPaul Walmsley goto out; 354253032dafSPaul Walmsley 35434fca9545SDavid Brownell clean: 35444fca9545SDavid Brownell kfree(rdev); 35454fca9545SDavid Brownell rdev = ERR_PTR(ret); 35464fca9545SDavid Brownell goto out; 3547414c70cbSLiam Girdwood } 3548414c70cbSLiam Girdwood EXPORT_SYMBOL_GPL(regulator_register); 3549414c70cbSLiam Girdwood 3550414c70cbSLiam Girdwood /** 3551414c70cbSLiam Girdwood * regulator_unregister - unregister regulator 355269279fb9SMark Brown * @rdev: regulator to unregister 3553414c70cbSLiam Girdwood * 3554414c70cbSLiam Girdwood * Called by regulator drivers to unregister a regulator. 3555414c70cbSLiam Girdwood */ 3556414c70cbSLiam Girdwood void regulator_unregister(struct regulator_dev *rdev) 3557414c70cbSLiam Girdwood { 3558414c70cbSLiam Girdwood if (rdev == NULL) 3559414c70cbSLiam Girdwood return; 3560414c70cbSLiam Girdwood 3561891636eaSMark Brown if (rdev->supply) { 3562891636eaSMark Brown while (rdev->use_count--) 3563891636eaSMark Brown regulator_disable(rdev->supply); 3564e032b376SMark Brown regulator_put(rdev->supply); 3565891636eaSMark Brown } 3566414c70cbSLiam Girdwood mutex_lock(®ulator_list_mutex); 35671130e5b3SMark Brown debugfs_remove_recursive(rdev->debugfs); 356843829731STejun Heo flush_work(&rdev->disable_work.work); 35696bf87d17SMark Brown WARN_ON(rdev->open_count); 35700f1d747bSMike Rapoport unset_regulator_supplies(rdev); 3571414c70cbSLiam Girdwood list_del(&rdev->list); 3572f8c12fe3SMark Brown kfree(rdev->constraints); 3573f19b00daSKim, Milo regulator_ena_gpio_free(rdev); 357458fb5cf5SLothar Waßmann device_unregister(&rdev->dev); 3575414c70cbSLiam Girdwood mutex_unlock(®ulator_list_mutex); 3576414c70cbSLiam Girdwood } 3577414c70cbSLiam Girdwood EXPORT_SYMBOL_GPL(regulator_unregister); 3578414c70cbSLiam Girdwood 3579414c70cbSLiam Girdwood /** 3580cf7bbcdfSMark Brown * regulator_suspend_prepare - prepare regulators for system wide suspend 3581414c70cbSLiam Girdwood * @state: system suspend state 3582414c70cbSLiam Girdwood * 3583414c70cbSLiam Girdwood * Configure each regulator with it's suspend operating parameters for state. 3584414c70cbSLiam Girdwood * This will usually be called by machine suspend code prior to supending. 3585414c70cbSLiam Girdwood */ 3586414c70cbSLiam Girdwood int regulator_suspend_prepare(suspend_state_t state) 3587414c70cbSLiam Girdwood { 3588414c70cbSLiam Girdwood struct regulator_dev *rdev; 3589414c70cbSLiam Girdwood int ret = 0; 3590414c70cbSLiam Girdwood 3591414c70cbSLiam Girdwood /* ON is handled by regulator active state */ 3592414c70cbSLiam Girdwood if (state == PM_SUSPEND_ON) 3593414c70cbSLiam Girdwood return -EINVAL; 3594414c70cbSLiam Girdwood 3595414c70cbSLiam Girdwood mutex_lock(®ulator_list_mutex); 3596414c70cbSLiam Girdwood list_for_each_entry(rdev, ®ulator_list, list) { 3597414c70cbSLiam Girdwood 3598414c70cbSLiam Girdwood mutex_lock(&rdev->mutex); 3599414c70cbSLiam Girdwood ret = suspend_prepare(rdev, state); 3600414c70cbSLiam Girdwood mutex_unlock(&rdev->mutex); 3601414c70cbSLiam Girdwood 3602414c70cbSLiam Girdwood if (ret < 0) { 36035da84fd9SJoe Perches rdev_err(rdev, "failed to prepare\n"); 3604414c70cbSLiam Girdwood goto out; 3605414c70cbSLiam Girdwood } 3606414c70cbSLiam Girdwood } 3607414c70cbSLiam Girdwood out: 3608414c70cbSLiam Girdwood mutex_unlock(®ulator_list_mutex); 3609414c70cbSLiam Girdwood return ret; 3610414c70cbSLiam Girdwood } 3611414c70cbSLiam Girdwood EXPORT_SYMBOL_GPL(regulator_suspend_prepare); 3612414c70cbSLiam Girdwood 3613414c70cbSLiam Girdwood /** 36147a32b589SMyungJoo Ham * regulator_suspend_finish - resume regulators from system wide suspend 36157a32b589SMyungJoo Ham * 36167a32b589SMyungJoo Ham * Turn on regulators that might be turned off by regulator_suspend_prepare 36177a32b589SMyungJoo Ham * and that should be turned on according to the regulators properties. 36187a32b589SMyungJoo Ham */ 36197a32b589SMyungJoo Ham int regulator_suspend_finish(void) 36207a32b589SMyungJoo Ham { 36217a32b589SMyungJoo Ham struct regulator_dev *rdev; 36227a32b589SMyungJoo Ham int ret = 0, error; 36237a32b589SMyungJoo Ham 36247a32b589SMyungJoo Ham mutex_lock(®ulator_list_mutex); 36257a32b589SMyungJoo Ham list_for_each_entry(rdev, ®ulator_list, list) { 36267a32b589SMyungJoo Ham struct regulator_ops *ops = rdev->desc->ops; 36277a32b589SMyungJoo Ham 36287a32b589SMyungJoo Ham mutex_lock(&rdev->mutex); 36297a32b589SMyungJoo Ham if ((rdev->use_count > 0 || rdev->constraints->always_on) && 36307a32b589SMyungJoo Ham ops->enable) { 36317a32b589SMyungJoo Ham error = ops->enable(rdev); 36327a32b589SMyungJoo Ham if (error) 36337a32b589SMyungJoo Ham ret = error; 36347a32b589SMyungJoo Ham } else { 363587b28417SMark Brown if (!have_full_constraints()) 36367a32b589SMyungJoo Ham goto unlock; 36377a32b589SMyungJoo Ham if (!ops->disable) 36387a32b589SMyungJoo Ham goto unlock; 3639b1a86831SMark Brown if (!_regulator_is_enabled(rdev)) 36407a32b589SMyungJoo Ham goto unlock; 36417a32b589SMyungJoo Ham 36427a32b589SMyungJoo Ham error = ops->disable(rdev); 36437a32b589SMyungJoo Ham if (error) 36447a32b589SMyungJoo Ham ret = error; 36457a32b589SMyungJoo Ham } 36467a32b589SMyungJoo Ham unlock: 36477a32b589SMyungJoo Ham mutex_unlock(&rdev->mutex); 36487a32b589SMyungJoo Ham } 36497a32b589SMyungJoo Ham mutex_unlock(®ulator_list_mutex); 36507a32b589SMyungJoo Ham return ret; 36517a32b589SMyungJoo Ham } 36527a32b589SMyungJoo Ham EXPORT_SYMBOL_GPL(regulator_suspend_finish); 36537a32b589SMyungJoo Ham 36547a32b589SMyungJoo Ham /** 3655ca725561SMark Brown * regulator_has_full_constraints - the system has fully specified constraints 3656ca725561SMark Brown * 3657ca725561SMark Brown * Calling this function will cause the regulator API to disable all 3658ca725561SMark Brown * regulators which have a zero use count and don't have an always_on 3659ca725561SMark Brown * constraint in a late_initcall. 3660ca725561SMark Brown * 3661ca725561SMark Brown * The intention is that this will become the default behaviour in a 3662ca725561SMark Brown * future kernel release so users are encouraged to use this facility 3663ca725561SMark Brown * now. 3664ca725561SMark Brown */ 3665ca725561SMark Brown void regulator_has_full_constraints(void) 3666ca725561SMark Brown { 3667ca725561SMark Brown has_full_constraints = 1; 3668ca725561SMark Brown } 3669ca725561SMark Brown EXPORT_SYMBOL_GPL(regulator_has_full_constraints); 3670ca725561SMark Brown 3671ca725561SMark Brown /** 3672414c70cbSLiam Girdwood * rdev_get_drvdata - get rdev regulator driver data 367369279fb9SMark Brown * @rdev: regulator 3674414c70cbSLiam Girdwood * 3675414c70cbSLiam Girdwood * Get rdev regulator driver private data. This call can be used in the 3676414c70cbSLiam Girdwood * regulator driver context. 3677414c70cbSLiam Girdwood */ 3678414c70cbSLiam Girdwood void *rdev_get_drvdata(struct regulator_dev *rdev) 3679414c70cbSLiam Girdwood { 3680414c70cbSLiam Girdwood return rdev->reg_data; 3681414c70cbSLiam Girdwood } 3682414c70cbSLiam Girdwood EXPORT_SYMBOL_GPL(rdev_get_drvdata); 3683414c70cbSLiam Girdwood 3684414c70cbSLiam Girdwood /** 3685414c70cbSLiam Girdwood * regulator_get_drvdata - get regulator driver data 3686414c70cbSLiam Girdwood * @regulator: regulator 3687414c70cbSLiam Girdwood * 3688414c70cbSLiam Girdwood * Get regulator driver private data. This call can be used in the consumer 3689414c70cbSLiam Girdwood * driver context when non API regulator specific functions need to be called. 3690414c70cbSLiam Girdwood */ 3691414c70cbSLiam Girdwood void *regulator_get_drvdata(struct regulator *regulator) 3692414c70cbSLiam Girdwood { 3693414c70cbSLiam Girdwood return regulator->rdev->reg_data; 3694414c70cbSLiam Girdwood } 3695414c70cbSLiam Girdwood EXPORT_SYMBOL_GPL(regulator_get_drvdata); 3696414c70cbSLiam Girdwood 3697414c70cbSLiam Girdwood /** 3698414c70cbSLiam Girdwood * regulator_set_drvdata - set regulator driver data 3699414c70cbSLiam Girdwood * @regulator: regulator 3700414c70cbSLiam Girdwood * @data: data 3701414c70cbSLiam Girdwood */ 3702414c70cbSLiam Girdwood void regulator_set_drvdata(struct regulator *regulator, void *data) 3703414c70cbSLiam Girdwood { 3704414c70cbSLiam Girdwood regulator->rdev->reg_data = data; 3705414c70cbSLiam Girdwood } 3706414c70cbSLiam Girdwood EXPORT_SYMBOL_GPL(regulator_set_drvdata); 3707414c70cbSLiam Girdwood 3708414c70cbSLiam Girdwood /** 3709414c70cbSLiam Girdwood * regulator_get_id - get regulator ID 371069279fb9SMark Brown * @rdev: regulator 3711414c70cbSLiam Girdwood */ 3712414c70cbSLiam Girdwood int rdev_get_id(struct regulator_dev *rdev) 3713414c70cbSLiam Girdwood { 3714414c70cbSLiam Girdwood return rdev->desc->id; 3715414c70cbSLiam Girdwood } 3716414c70cbSLiam Girdwood EXPORT_SYMBOL_GPL(rdev_get_id); 3717414c70cbSLiam Girdwood 3718a5766f11SLiam Girdwood struct device *rdev_get_dev(struct regulator_dev *rdev) 3719a5766f11SLiam Girdwood { 3720a5766f11SLiam Girdwood return &rdev->dev; 3721a5766f11SLiam Girdwood } 3722a5766f11SLiam Girdwood EXPORT_SYMBOL_GPL(rdev_get_dev); 3723a5766f11SLiam Girdwood 3724a5766f11SLiam Girdwood void *regulator_get_init_drvdata(struct regulator_init_data *reg_init_data) 3725a5766f11SLiam Girdwood { 3726a5766f11SLiam Girdwood return reg_init_data->driver_data; 3727a5766f11SLiam Girdwood } 3728a5766f11SLiam Girdwood EXPORT_SYMBOL_GPL(regulator_get_init_drvdata); 3729a5766f11SLiam Girdwood 3730ba55a974SMark Brown #ifdef CONFIG_DEBUG_FS 3731ba55a974SMark Brown static ssize_t supply_map_read_file(struct file *file, char __user *user_buf, 3732ba55a974SMark Brown size_t count, loff_t *ppos) 3733ba55a974SMark Brown { 3734ba55a974SMark Brown char *buf = kmalloc(PAGE_SIZE, GFP_KERNEL); 3735ba55a974SMark Brown ssize_t len, ret = 0; 3736ba55a974SMark Brown struct regulator_map *map; 3737ba55a974SMark Brown 3738ba55a974SMark Brown if (!buf) 3739ba55a974SMark Brown return -ENOMEM; 3740ba55a974SMark Brown 3741ba55a974SMark Brown list_for_each_entry(map, ®ulator_map_list, list) { 3742ba55a974SMark Brown len = snprintf(buf + ret, PAGE_SIZE - ret, 3743ba55a974SMark Brown "%s -> %s.%s\n", 3744ba55a974SMark Brown rdev_get_name(map->regulator), map->dev_name, 3745ba55a974SMark Brown map->supply); 3746ba55a974SMark Brown if (len >= 0) 3747ba55a974SMark Brown ret += len; 3748ba55a974SMark Brown if (ret > PAGE_SIZE) { 3749ba55a974SMark Brown ret = PAGE_SIZE; 3750ba55a974SMark Brown break; 3751ba55a974SMark Brown } 3752ba55a974SMark Brown } 3753ba55a974SMark Brown 3754ba55a974SMark Brown ret = simple_read_from_buffer(user_buf, count, ppos, buf, ret); 3755ba55a974SMark Brown 3756ba55a974SMark Brown kfree(buf); 3757ba55a974SMark Brown 3758ba55a974SMark Brown return ret; 3759ba55a974SMark Brown } 376024751434SStephen Boyd #endif 3761ba55a974SMark Brown 3762ba55a974SMark Brown static const struct file_operations supply_map_fops = { 376324751434SStephen Boyd #ifdef CONFIG_DEBUG_FS 3764ba55a974SMark Brown .read = supply_map_read_file, 3765ba55a974SMark Brown .llseek = default_llseek, 3766ba55a974SMark Brown #endif 376724751434SStephen Boyd }; 3768ba55a974SMark Brown 3769414c70cbSLiam Girdwood static int __init regulator_init(void) 3770414c70cbSLiam Girdwood { 377134abbd68SMark Brown int ret; 377234abbd68SMark Brown 377334abbd68SMark Brown ret = class_register(®ulator_class); 377434abbd68SMark Brown 37751130e5b3SMark Brown debugfs_root = debugfs_create_dir("regulator", NULL); 377624751434SStephen Boyd if (!debugfs_root) 37771130e5b3SMark Brown pr_warn("regulator: Failed to create debugfs directory\n"); 3778ba55a974SMark Brown 3779f4d562c6SMark Brown debugfs_create_file("supply_map", 0444, debugfs_root, NULL, 3780f4d562c6SMark Brown &supply_map_fops); 37811130e5b3SMark Brown 378234abbd68SMark Brown regulator_dummy_init(); 378334abbd68SMark Brown 378434abbd68SMark Brown return ret; 3785414c70cbSLiam Girdwood } 3786414c70cbSLiam Girdwood 3787414c70cbSLiam Girdwood /* init early to allow our consumers to complete system booting */ 3788414c70cbSLiam Girdwood core_initcall(regulator_init); 3789ca725561SMark Brown 3790ca725561SMark Brown static int __init regulator_init_complete(void) 3791ca725561SMark Brown { 3792ca725561SMark Brown struct regulator_dev *rdev; 3793ca725561SMark Brown struct regulator_ops *ops; 3794ca725561SMark Brown struct regulation_constraints *c; 3795ca725561SMark Brown int enabled, ret; 3796ca725561SMark Brown 379786f5fcfcSMark Brown /* 379886f5fcfcSMark Brown * Since DT doesn't provide an idiomatic mechanism for 379986f5fcfcSMark Brown * enabling full constraints and since it's much more natural 380086f5fcfcSMark Brown * with DT to provide them just assume that a DT enabled 380186f5fcfcSMark Brown * system has full constraints. 380286f5fcfcSMark Brown */ 380386f5fcfcSMark Brown if (of_have_populated_dt()) 380486f5fcfcSMark Brown has_full_constraints = true; 380586f5fcfcSMark Brown 3806ca725561SMark Brown mutex_lock(®ulator_list_mutex); 3807ca725561SMark Brown 3808ca725561SMark Brown /* If we have a full configuration then disable any regulators 3809ca725561SMark Brown * which are not in use or always_on. This will become the 3810ca725561SMark Brown * default behaviour in the future. 3811ca725561SMark Brown */ 3812ca725561SMark Brown list_for_each_entry(rdev, ®ulator_list, list) { 3813ca725561SMark Brown ops = rdev->desc->ops; 3814ca725561SMark Brown c = rdev->constraints; 3815ca725561SMark Brown 3816f25e0b4fSMark Brown if (!ops->disable || (c && c->always_on)) 3817ca725561SMark Brown continue; 3818ca725561SMark Brown 3819ca725561SMark Brown mutex_lock(&rdev->mutex); 3820ca725561SMark Brown 3821ca725561SMark Brown if (rdev->use_count) 3822ca725561SMark Brown goto unlock; 3823ca725561SMark Brown 3824ca725561SMark Brown /* If we can't read the status assume it's on. */ 3825ca725561SMark Brown if (ops->is_enabled) 3826ca725561SMark Brown enabled = ops->is_enabled(rdev); 3827ca725561SMark Brown else 3828ca725561SMark Brown enabled = 1; 3829ca725561SMark Brown 3830ca725561SMark Brown if (!enabled) 3831ca725561SMark Brown goto unlock; 3832ca725561SMark Brown 383387b28417SMark Brown if (have_full_constraints()) { 3834ca725561SMark Brown /* We log since this may kill the system if it 3835ca725561SMark Brown * goes wrong. */ 38365da84fd9SJoe Perches rdev_info(rdev, "disabling\n"); 3837ca725561SMark Brown ret = ops->disable(rdev); 38380d25d09dSJingoo Han if (ret != 0) 38395da84fd9SJoe Perches rdev_err(rdev, "couldn't disable: %d\n", ret); 3840ca725561SMark Brown } else { 3841ca725561SMark Brown /* The intention is that in future we will 3842ca725561SMark Brown * assume that full constraints are provided 3843ca725561SMark Brown * so warn even if we aren't going to do 3844ca725561SMark Brown * anything here. 3845ca725561SMark Brown */ 38465da84fd9SJoe Perches rdev_warn(rdev, "incomplete constraints, leaving on\n"); 3847ca725561SMark Brown } 3848ca725561SMark Brown 3849ca725561SMark Brown unlock: 3850ca725561SMark Brown mutex_unlock(&rdev->mutex); 3851ca725561SMark Brown } 3852ca725561SMark Brown 3853ca725561SMark Brown mutex_unlock(®ulator_list_mutex); 3854ca725561SMark Brown 3855ca725561SMark Brown return 0; 3856ca725561SMark Brown } 3857ca725561SMark Brown late_initcall(regulator_init_complete); 3858