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" 3934abbd68SMark Brown 407d51a0dbSMark Brown #define rdev_crit(rdev, fmt, ...) \ 417d51a0dbSMark Brown pr_crit("%s: " fmt, rdev_get_name(rdev), ##__VA_ARGS__) 425da84fd9SJoe Perches #define rdev_err(rdev, fmt, ...) \ 435da84fd9SJoe Perches pr_err("%s: " fmt, rdev_get_name(rdev), ##__VA_ARGS__) 445da84fd9SJoe Perches #define rdev_warn(rdev, fmt, ...) \ 455da84fd9SJoe Perches pr_warn("%s: " fmt, rdev_get_name(rdev), ##__VA_ARGS__) 465da84fd9SJoe Perches #define rdev_info(rdev, fmt, ...) \ 475da84fd9SJoe Perches pr_info("%s: " fmt, rdev_get_name(rdev), ##__VA_ARGS__) 485da84fd9SJoe Perches #define rdev_dbg(rdev, fmt, ...) \ 495da84fd9SJoe Perches pr_debug("%s: " fmt, rdev_get_name(rdev), ##__VA_ARGS__) 505da84fd9SJoe Perches 51414c70cbSLiam Girdwood static DEFINE_MUTEX(regulator_list_mutex); 52414c70cbSLiam Girdwood static LIST_HEAD(regulator_list); 53414c70cbSLiam Girdwood static LIST_HEAD(regulator_map_list); 54f19b00daSKim, Milo static LIST_HEAD(regulator_ena_gpio_list); 5521cf891aSMark Brown static bool has_full_constraints; 56688fe99aSMark Brown static bool board_wants_dummy_regulator; 57414c70cbSLiam Girdwood 581130e5b3SMark Brown static struct dentry *debugfs_root; 591130e5b3SMark Brown 608dc5390dSMark Brown /* 61414c70cbSLiam Girdwood * struct regulator_map 62414c70cbSLiam Girdwood * 63414c70cbSLiam Girdwood * Used to provide symbolic supply names to devices. 64414c70cbSLiam Girdwood */ 65414c70cbSLiam Girdwood struct regulator_map { 66414c70cbSLiam Girdwood struct list_head list; 6740f9244fSMark Brown const char *dev_name; /* The dev_name() for the consumer */ 68414c70cbSLiam Girdwood const char *supply; 69a5766f11SLiam Girdwood struct regulator_dev *regulator; 70414c70cbSLiam Girdwood }; 71414c70cbSLiam Girdwood 72414c70cbSLiam Girdwood /* 73f19b00daSKim, Milo * struct regulator_enable_gpio 74f19b00daSKim, Milo * 75f19b00daSKim, Milo * Management for shared enable GPIO pin 76f19b00daSKim, Milo */ 77f19b00daSKim, Milo struct regulator_enable_gpio { 78f19b00daSKim, Milo struct list_head list; 79f19b00daSKim, Milo int gpio; 80f19b00daSKim, Milo u32 enable_count; /* a number of enabled shared GPIO */ 81f19b00daSKim, Milo u32 request_count; /* a number of requested shared GPIO */ 82f19b00daSKim, Milo unsigned int ena_gpio_invert:1; 83f19b00daSKim, Milo }; 84f19b00daSKim, Milo 85f19b00daSKim, Milo /* 86414c70cbSLiam Girdwood * struct regulator 87414c70cbSLiam Girdwood * 88414c70cbSLiam Girdwood * One for each consumer device. 89414c70cbSLiam Girdwood */ 90414c70cbSLiam Girdwood struct regulator { 91414c70cbSLiam Girdwood struct device *dev; 92414c70cbSLiam Girdwood struct list_head list; 936492bc1bSMark Brown unsigned int always_on:1; 94f59c8f9fSMark Brown unsigned int bypass:1; 95414c70cbSLiam Girdwood int uA_load; 96414c70cbSLiam Girdwood int min_uV; 97414c70cbSLiam Girdwood int max_uV; 98414c70cbSLiam Girdwood char *supply_name; 99414c70cbSLiam Girdwood struct device_attribute dev_attr; 100414c70cbSLiam Girdwood struct regulator_dev *rdev; 1015de70519SMark Brown struct dentry *debugfs; 102414c70cbSLiam Girdwood }; 103414c70cbSLiam Girdwood 104414c70cbSLiam Girdwood static int _regulator_is_enabled(struct regulator_dev *rdev); 1053801b86aSMark Brown static int _regulator_disable(struct regulator_dev *rdev); 106414c70cbSLiam Girdwood static int _regulator_get_voltage(struct regulator_dev *rdev); 107414c70cbSLiam Girdwood static int _regulator_get_current_limit(struct regulator_dev *rdev); 108414c70cbSLiam Girdwood static unsigned int _regulator_get_mode(struct regulator_dev *rdev); 109414c70cbSLiam Girdwood static void _notifier_call_chain(struct regulator_dev *rdev, 110414c70cbSLiam Girdwood unsigned long event, void *data); 11175790251SMark Brown static int _regulator_do_set_voltage(struct regulator_dev *rdev, 11275790251SMark Brown int min_uV, int max_uV); 1133801b86aSMark Brown static struct regulator *create_regulator(struct regulator_dev *rdev, 1143801b86aSMark Brown struct device *dev, 1153801b86aSMark Brown const char *supply_name); 116414c70cbSLiam Girdwood 1171083c393SMark Brown static const char *rdev_get_name(struct regulator_dev *rdev) 1181083c393SMark Brown { 1191083c393SMark Brown if (rdev->constraints && rdev->constraints->name) 1201083c393SMark Brown return rdev->constraints->name; 1211083c393SMark Brown else if (rdev->desc->name) 1221083c393SMark Brown return rdev->desc->name; 1231083c393SMark Brown else 1241083c393SMark Brown return ""; 1251083c393SMark Brown } 1261083c393SMark 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 326bc558a60SMark Brown static ssize_t regulator_name_show(struct device *dev, 327bc558a60SMark Brown struct device_attribute *attr, 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 } 333bc558a60SMark Brown 3344fca9545SDavid Brownell static ssize_t regulator_print_opmode(char *buf, int mode) 335414c70cbSLiam Girdwood { 336414c70cbSLiam Girdwood switch (mode) { 337414c70cbSLiam Girdwood case REGULATOR_MODE_FAST: 338414c70cbSLiam Girdwood return sprintf(buf, "fast\n"); 339414c70cbSLiam Girdwood case REGULATOR_MODE_NORMAL: 340414c70cbSLiam Girdwood return sprintf(buf, "normal\n"); 341414c70cbSLiam Girdwood case REGULATOR_MODE_IDLE: 342414c70cbSLiam Girdwood return sprintf(buf, "idle\n"); 343414c70cbSLiam Girdwood case REGULATOR_MODE_STANDBY: 344414c70cbSLiam Girdwood return sprintf(buf, "standby\n"); 345414c70cbSLiam Girdwood } 346414c70cbSLiam Girdwood return sprintf(buf, "unknown\n"); 347414c70cbSLiam Girdwood } 348414c70cbSLiam Girdwood 3494fca9545SDavid Brownell static ssize_t regulator_opmode_show(struct device *dev, 350414c70cbSLiam Girdwood struct device_attribute *attr, char *buf) 351414c70cbSLiam Girdwood { 352a5766f11SLiam Girdwood struct regulator_dev *rdev = dev_get_drvdata(dev); 353414c70cbSLiam Girdwood 3544fca9545SDavid Brownell return regulator_print_opmode(buf, _regulator_get_mode(rdev)); 3554fca9545SDavid Brownell } 3567ad68e2fSDavid Brownell static DEVICE_ATTR(opmode, 0444, regulator_opmode_show, NULL); 3574fca9545SDavid Brownell 3584fca9545SDavid Brownell static ssize_t regulator_print_state(char *buf, int state) 3594fca9545SDavid Brownell { 360414c70cbSLiam Girdwood if (state > 0) 361414c70cbSLiam Girdwood return sprintf(buf, "enabled\n"); 362414c70cbSLiam Girdwood else if (state == 0) 363414c70cbSLiam Girdwood return sprintf(buf, "disabled\n"); 364414c70cbSLiam Girdwood else 365414c70cbSLiam Girdwood return sprintf(buf, "unknown\n"); 366414c70cbSLiam Girdwood } 367414c70cbSLiam Girdwood 3684fca9545SDavid Brownell static ssize_t regulator_state_show(struct device *dev, 3694fca9545SDavid Brownell struct device_attribute *attr, char *buf) 3704fca9545SDavid Brownell { 3714fca9545SDavid Brownell struct regulator_dev *rdev = dev_get_drvdata(dev); 3729332546fSMark Brown ssize_t ret; 3734fca9545SDavid Brownell 3749332546fSMark Brown mutex_lock(&rdev->mutex); 3759332546fSMark Brown ret = regulator_print_state(buf, _regulator_is_enabled(rdev)); 3769332546fSMark Brown mutex_unlock(&rdev->mutex); 3779332546fSMark Brown 3789332546fSMark Brown return ret; 3794fca9545SDavid Brownell } 3807ad68e2fSDavid Brownell static DEVICE_ATTR(state, 0444, regulator_state_show, NULL); 3814fca9545SDavid Brownell 382853116a1SDavid Brownell static ssize_t regulator_status_show(struct device *dev, 383853116a1SDavid Brownell struct device_attribute *attr, char *buf) 384853116a1SDavid Brownell { 385853116a1SDavid Brownell struct regulator_dev *rdev = dev_get_drvdata(dev); 386853116a1SDavid Brownell int status; 387853116a1SDavid Brownell char *label; 388853116a1SDavid Brownell 389853116a1SDavid Brownell status = rdev->desc->ops->get_status(rdev); 390853116a1SDavid Brownell if (status < 0) 391853116a1SDavid Brownell return status; 392853116a1SDavid Brownell 393853116a1SDavid Brownell switch (status) { 394853116a1SDavid Brownell case REGULATOR_STATUS_OFF: 395853116a1SDavid Brownell label = "off"; 396853116a1SDavid Brownell break; 397853116a1SDavid Brownell case REGULATOR_STATUS_ON: 398853116a1SDavid Brownell label = "on"; 399853116a1SDavid Brownell break; 400853116a1SDavid Brownell case REGULATOR_STATUS_ERROR: 401853116a1SDavid Brownell label = "error"; 402853116a1SDavid Brownell break; 403853116a1SDavid Brownell case REGULATOR_STATUS_FAST: 404853116a1SDavid Brownell label = "fast"; 405853116a1SDavid Brownell break; 406853116a1SDavid Brownell case REGULATOR_STATUS_NORMAL: 407853116a1SDavid Brownell label = "normal"; 408853116a1SDavid Brownell break; 409853116a1SDavid Brownell case REGULATOR_STATUS_IDLE: 410853116a1SDavid Brownell label = "idle"; 411853116a1SDavid Brownell break; 412853116a1SDavid Brownell case REGULATOR_STATUS_STANDBY: 413853116a1SDavid Brownell label = "standby"; 414853116a1SDavid Brownell break; 415f59c8f9fSMark Brown case REGULATOR_STATUS_BYPASS: 416f59c8f9fSMark Brown label = "bypass"; 417f59c8f9fSMark Brown break; 4181beaf762SKrystian Garbaciak case REGULATOR_STATUS_UNDEFINED: 4191beaf762SKrystian Garbaciak label = "undefined"; 4201beaf762SKrystian Garbaciak break; 421853116a1SDavid Brownell default: 422853116a1SDavid Brownell return -ERANGE; 423853116a1SDavid Brownell } 424853116a1SDavid Brownell 425853116a1SDavid Brownell return sprintf(buf, "%s\n", label); 426853116a1SDavid Brownell } 427853116a1SDavid Brownell static DEVICE_ATTR(status, 0444, regulator_status_show, NULL); 428853116a1SDavid Brownell 429414c70cbSLiam Girdwood static ssize_t regulator_min_uA_show(struct device *dev, 430414c70cbSLiam Girdwood struct device_attribute *attr, char *buf) 431414c70cbSLiam Girdwood { 432a5766f11SLiam Girdwood struct regulator_dev *rdev = dev_get_drvdata(dev); 433414c70cbSLiam Girdwood 434414c70cbSLiam Girdwood if (!rdev->constraints) 435414c70cbSLiam Girdwood return sprintf(buf, "constraint not defined\n"); 436414c70cbSLiam Girdwood 437414c70cbSLiam Girdwood return sprintf(buf, "%d\n", rdev->constraints->min_uA); 438414c70cbSLiam Girdwood } 4397ad68e2fSDavid Brownell static DEVICE_ATTR(min_microamps, 0444, regulator_min_uA_show, NULL); 440414c70cbSLiam Girdwood 441414c70cbSLiam Girdwood static ssize_t regulator_max_uA_show(struct device *dev, 442414c70cbSLiam Girdwood struct device_attribute *attr, char *buf) 443414c70cbSLiam Girdwood { 444a5766f11SLiam Girdwood struct regulator_dev *rdev = dev_get_drvdata(dev); 445414c70cbSLiam Girdwood 446414c70cbSLiam Girdwood if (!rdev->constraints) 447414c70cbSLiam Girdwood return sprintf(buf, "constraint not defined\n"); 448414c70cbSLiam Girdwood 449414c70cbSLiam Girdwood return sprintf(buf, "%d\n", rdev->constraints->max_uA); 450414c70cbSLiam Girdwood } 4517ad68e2fSDavid Brownell static DEVICE_ATTR(max_microamps, 0444, regulator_max_uA_show, NULL); 452414c70cbSLiam Girdwood 453414c70cbSLiam Girdwood static ssize_t regulator_min_uV_show(struct device *dev, 454414c70cbSLiam Girdwood struct device_attribute *attr, char *buf) 455414c70cbSLiam Girdwood { 456a5766f11SLiam Girdwood struct regulator_dev *rdev = dev_get_drvdata(dev); 457414c70cbSLiam Girdwood 458414c70cbSLiam Girdwood if (!rdev->constraints) 459414c70cbSLiam Girdwood return sprintf(buf, "constraint not defined\n"); 460414c70cbSLiam Girdwood 461414c70cbSLiam Girdwood return sprintf(buf, "%d\n", rdev->constraints->min_uV); 462414c70cbSLiam Girdwood } 4637ad68e2fSDavid Brownell static DEVICE_ATTR(min_microvolts, 0444, regulator_min_uV_show, NULL); 464414c70cbSLiam Girdwood 465414c70cbSLiam Girdwood static ssize_t regulator_max_uV_show(struct device *dev, 466414c70cbSLiam Girdwood struct device_attribute *attr, char *buf) 467414c70cbSLiam Girdwood { 468a5766f11SLiam Girdwood struct regulator_dev *rdev = dev_get_drvdata(dev); 469414c70cbSLiam Girdwood 470414c70cbSLiam Girdwood if (!rdev->constraints) 471414c70cbSLiam Girdwood return sprintf(buf, "constraint not defined\n"); 472414c70cbSLiam Girdwood 473414c70cbSLiam Girdwood return sprintf(buf, "%d\n", rdev->constraints->max_uV); 474414c70cbSLiam Girdwood } 4757ad68e2fSDavid Brownell static DEVICE_ATTR(max_microvolts, 0444, regulator_max_uV_show, NULL); 476414c70cbSLiam Girdwood 477414c70cbSLiam Girdwood static ssize_t regulator_total_uA_show(struct device *dev, 478414c70cbSLiam Girdwood struct device_attribute *attr, char *buf) 479414c70cbSLiam Girdwood { 480a5766f11SLiam Girdwood struct regulator_dev *rdev = dev_get_drvdata(dev); 481414c70cbSLiam Girdwood struct regulator *regulator; 482414c70cbSLiam Girdwood int uA = 0; 483414c70cbSLiam Girdwood 484414c70cbSLiam Girdwood mutex_lock(&rdev->mutex); 485414c70cbSLiam Girdwood list_for_each_entry(regulator, &rdev->consumer_list, list) 486414c70cbSLiam Girdwood uA += regulator->uA_load; 487414c70cbSLiam Girdwood mutex_unlock(&rdev->mutex); 488414c70cbSLiam Girdwood return sprintf(buf, "%d\n", uA); 489414c70cbSLiam Girdwood } 4907ad68e2fSDavid Brownell static DEVICE_ATTR(requested_microamps, 0444, regulator_total_uA_show, NULL); 491414c70cbSLiam Girdwood 492414c70cbSLiam Girdwood static ssize_t regulator_num_users_show(struct device *dev, 493414c70cbSLiam Girdwood struct device_attribute *attr, char *buf) 494414c70cbSLiam Girdwood { 495a5766f11SLiam Girdwood struct regulator_dev *rdev = dev_get_drvdata(dev); 496414c70cbSLiam Girdwood return sprintf(buf, "%d\n", rdev->use_count); 497414c70cbSLiam Girdwood } 498414c70cbSLiam Girdwood 499414c70cbSLiam Girdwood static ssize_t regulator_type_show(struct device *dev, 500414c70cbSLiam Girdwood struct device_attribute *attr, char *buf) 501414c70cbSLiam Girdwood { 502a5766f11SLiam Girdwood struct regulator_dev *rdev = dev_get_drvdata(dev); 503414c70cbSLiam Girdwood 504414c70cbSLiam Girdwood switch (rdev->desc->type) { 505414c70cbSLiam Girdwood case REGULATOR_VOLTAGE: 506414c70cbSLiam Girdwood return sprintf(buf, "voltage\n"); 507414c70cbSLiam Girdwood case REGULATOR_CURRENT: 508414c70cbSLiam Girdwood return sprintf(buf, "current\n"); 509414c70cbSLiam Girdwood } 510414c70cbSLiam Girdwood return sprintf(buf, "unknown\n"); 511414c70cbSLiam Girdwood } 512414c70cbSLiam Girdwood 513414c70cbSLiam Girdwood static ssize_t regulator_suspend_mem_uV_show(struct device *dev, 514414c70cbSLiam Girdwood struct device_attribute *attr, char *buf) 515414c70cbSLiam Girdwood { 516a5766f11SLiam Girdwood struct regulator_dev *rdev = dev_get_drvdata(dev); 517414c70cbSLiam Girdwood 518414c70cbSLiam Girdwood return sprintf(buf, "%d\n", rdev->constraints->state_mem.uV); 519414c70cbSLiam Girdwood } 5207ad68e2fSDavid Brownell static DEVICE_ATTR(suspend_mem_microvolts, 0444, 5217ad68e2fSDavid Brownell regulator_suspend_mem_uV_show, NULL); 522414c70cbSLiam Girdwood 523414c70cbSLiam Girdwood static ssize_t regulator_suspend_disk_uV_show(struct device *dev, 524414c70cbSLiam Girdwood struct device_attribute *attr, char *buf) 525414c70cbSLiam Girdwood { 526a5766f11SLiam Girdwood struct regulator_dev *rdev = dev_get_drvdata(dev); 527414c70cbSLiam Girdwood 528414c70cbSLiam Girdwood return sprintf(buf, "%d\n", rdev->constraints->state_disk.uV); 529414c70cbSLiam Girdwood } 5307ad68e2fSDavid Brownell static DEVICE_ATTR(suspend_disk_microvolts, 0444, 5317ad68e2fSDavid Brownell regulator_suspend_disk_uV_show, NULL); 532414c70cbSLiam Girdwood 533414c70cbSLiam Girdwood static ssize_t regulator_suspend_standby_uV_show(struct device *dev, 534414c70cbSLiam Girdwood struct device_attribute *attr, char *buf) 535414c70cbSLiam Girdwood { 536a5766f11SLiam Girdwood struct regulator_dev *rdev = dev_get_drvdata(dev); 537414c70cbSLiam Girdwood 538414c70cbSLiam Girdwood return sprintf(buf, "%d\n", rdev->constraints->state_standby.uV); 539414c70cbSLiam Girdwood } 5407ad68e2fSDavid Brownell static DEVICE_ATTR(suspend_standby_microvolts, 0444, 5417ad68e2fSDavid Brownell regulator_suspend_standby_uV_show, NULL); 542414c70cbSLiam Girdwood 543414c70cbSLiam Girdwood static ssize_t regulator_suspend_mem_mode_show(struct device *dev, 544414c70cbSLiam Girdwood struct device_attribute *attr, char *buf) 545414c70cbSLiam Girdwood { 546a5766f11SLiam Girdwood struct regulator_dev *rdev = dev_get_drvdata(dev); 547414c70cbSLiam Girdwood 5484fca9545SDavid Brownell return regulator_print_opmode(buf, 5494fca9545SDavid Brownell rdev->constraints->state_mem.mode); 550414c70cbSLiam Girdwood } 5517ad68e2fSDavid Brownell static DEVICE_ATTR(suspend_mem_mode, 0444, 5527ad68e2fSDavid Brownell regulator_suspend_mem_mode_show, NULL); 553414c70cbSLiam Girdwood 554414c70cbSLiam Girdwood static ssize_t regulator_suspend_disk_mode_show(struct device *dev, 555414c70cbSLiam Girdwood struct device_attribute *attr, char *buf) 556414c70cbSLiam Girdwood { 557a5766f11SLiam Girdwood struct regulator_dev *rdev = dev_get_drvdata(dev); 558414c70cbSLiam Girdwood 5594fca9545SDavid Brownell return regulator_print_opmode(buf, 5604fca9545SDavid Brownell rdev->constraints->state_disk.mode); 561414c70cbSLiam Girdwood } 5627ad68e2fSDavid Brownell static DEVICE_ATTR(suspend_disk_mode, 0444, 5637ad68e2fSDavid Brownell regulator_suspend_disk_mode_show, NULL); 564414c70cbSLiam Girdwood 565414c70cbSLiam Girdwood static ssize_t regulator_suspend_standby_mode_show(struct device *dev, 566414c70cbSLiam Girdwood struct device_attribute *attr, char *buf) 567414c70cbSLiam Girdwood { 568a5766f11SLiam Girdwood struct regulator_dev *rdev = dev_get_drvdata(dev); 569414c70cbSLiam Girdwood 5704fca9545SDavid Brownell return regulator_print_opmode(buf, 5714fca9545SDavid Brownell rdev->constraints->state_standby.mode); 572414c70cbSLiam Girdwood } 5737ad68e2fSDavid Brownell static DEVICE_ATTR(suspend_standby_mode, 0444, 5747ad68e2fSDavid Brownell regulator_suspend_standby_mode_show, NULL); 575414c70cbSLiam Girdwood 576414c70cbSLiam Girdwood static ssize_t regulator_suspend_mem_state_show(struct device *dev, 577414c70cbSLiam Girdwood struct device_attribute *attr, char *buf) 578414c70cbSLiam Girdwood { 579a5766f11SLiam Girdwood struct regulator_dev *rdev = dev_get_drvdata(dev); 580414c70cbSLiam Girdwood 5814fca9545SDavid Brownell return regulator_print_state(buf, 5824fca9545SDavid Brownell rdev->constraints->state_mem.enabled); 583414c70cbSLiam Girdwood } 5847ad68e2fSDavid Brownell static DEVICE_ATTR(suspend_mem_state, 0444, 5857ad68e2fSDavid Brownell regulator_suspend_mem_state_show, NULL); 586414c70cbSLiam Girdwood 587414c70cbSLiam Girdwood static ssize_t regulator_suspend_disk_state_show(struct device *dev, 588414c70cbSLiam Girdwood struct device_attribute *attr, char *buf) 589414c70cbSLiam Girdwood { 590a5766f11SLiam Girdwood struct regulator_dev *rdev = dev_get_drvdata(dev); 591414c70cbSLiam Girdwood 5924fca9545SDavid Brownell return regulator_print_state(buf, 5934fca9545SDavid Brownell rdev->constraints->state_disk.enabled); 594414c70cbSLiam Girdwood } 5957ad68e2fSDavid Brownell static DEVICE_ATTR(suspend_disk_state, 0444, 5967ad68e2fSDavid Brownell regulator_suspend_disk_state_show, NULL); 597414c70cbSLiam Girdwood 598414c70cbSLiam Girdwood static ssize_t regulator_suspend_standby_state_show(struct device *dev, 599414c70cbSLiam Girdwood struct device_attribute *attr, char *buf) 600414c70cbSLiam Girdwood { 601a5766f11SLiam Girdwood struct regulator_dev *rdev = dev_get_drvdata(dev); 602414c70cbSLiam Girdwood 6034fca9545SDavid Brownell return regulator_print_state(buf, 6044fca9545SDavid Brownell rdev->constraints->state_standby.enabled); 605414c70cbSLiam Girdwood } 6067ad68e2fSDavid Brownell static DEVICE_ATTR(suspend_standby_state, 0444, 6077ad68e2fSDavid Brownell regulator_suspend_standby_state_show, NULL); 608bc558a60SMark Brown 609f59c8f9fSMark Brown static ssize_t regulator_bypass_show(struct device *dev, 610f59c8f9fSMark Brown struct device_attribute *attr, char *buf) 611f59c8f9fSMark Brown { 612f59c8f9fSMark Brown struct regulator_dev *rdev = dev_get_drvdata(dev); 613f59c8f9fSMark Brown const char *report; 614f59c8f9fSMark Brown bool bypass; 615f59c8f9fSMark Brown int ret; 616f59c8f9fSMark Brown 617f59c8f9fSMark Brown ret = rdev->desc->ops->get_bypass(rdev, &bypass); 618f59c8f9fSMark Brown 619f59c8f9fSMark Brown if (ret != 0) 620f59c8f9fSMark Brown report = "unknown"; 621f59c8f9fSMark Brown else if (bypass) 622f59c8f9fSMark Brown report = "enabled"; 623f59c8f9fSMark Brown else 624f59c8f9fSMark Brown report = "disabled"; 625f59c8f9fSMark Brown 626f59c8f9fSMark Brown return sprintf(buf, "%s\n", report); 627f59c8f9fSMark Brown } 628f59c8f9fSMark Brown static DEVICE_ATTR(bypass, 0444, 629f59c8f9fSMark Brown regulator_bypass_show, NULL); 6307ad68e2fSDavid Brownell 6317ad68e2fSDavid Brownell /* 6327ad68e2fSDavid Brownell * These are the only attributes are present for all regulators. 6337ad68e2fSDavid Brownell * Other attributes are a function of regulator functionality. 6347ad68e2fSDavid Brownell */ 635414c70cbSLiam Girdwood static struct device_attribute regulator_dev_attrs[] = { 636bc558a60SMark Brown __ATTR(name, 0444, regulator_name_show, NULL), 637414c70cbSLiam Girdwood __ATTR(num_users, 0444, regulator_num_users_show, NULL), 638414c70cbSLiam Girdwood __ATTR(type, 0444, regulator_type_show, NULL), 639414c70cbSLiam Girdwood __ATTR_NULL, 640414c70cbSLiam Girdwood }; 641414c70cbSLiam Girdwood 642414c70cbSLiam Girdwood static void regulator_dev_release(struct device *dev) 643414c70cbSLiam Girdwood { 644a5766f11SLiam Girdwood struct regulator_dev *rdev = dev_get_drvdata(dev); 645414c70cbSLiam Girdwood kfree(rdev); 646414c70cbSLiam Girdwood } 647414c70cbSLiam Girdwood 648414c70cbSLiam Girdwood static struct class regulator_class = { 649414c70cbSLiam Girdwood .name = "regulator", 650414c70cbSLiam Girdwood .dev_release = regulator_dev_release, 651414c70cbSLiam Girdwood .dev_attrs = regulator_dev_attrs, 652414c70cbSLiam Girdwood }; 653414c70cbSLiam Girdwood 654414c70cbSLiam Girdwood /* Calculate the new optimum regulator operating mode based on the new total 655414c70cbSLiam Girdwood * consumer load. All locks held by caller */ 656414c70cbSLiam Girdwood static void drms_uA_update(struct regulator_dev *rdev) 657414c70cbSLiam Girdwood { 658414c70cbSLiam Girdwood struct regulator *sibling; 659414c70cbSLiam Girdwood int current_uA = 0, output_uV, input_uV, err; 660414c70cbSLiam Girdwood unsigned int mode; 661414c70cbSLiam Girdwood 662414c70cbSLiam Girdwood err = regulator_check_drms(rdev); 663414c70cbSLiam Girdwood if (err < 0 || !rdev->desc->ops->get_optimum_mode || 664476c2d83SMark Brown (!rdev->desc->ops->get_voltage && 665476c2d83SMark Brown !rdev->desc->ops->get_voltage_sel) || 666476c2d83SMark Brown !rdev->desc->ops->set_mode) 667414c70cbSLiam Girdwood return; 668414c70cbSLiam Girdwood 669414c70cbSLiam Girdwood /* get output voltage */ 6701bf5a1f8SMark Brown output_uV = _regulator_get_voltage(rdev); 671414c70cbSLiam Girdwood if (output_uV <= 0) 672414c70cbSLiam Girdwood return; 673414c70cbSLiam Girdwood 674414c70cbSLiam Girdwood /* get input voltage */ 6751bf5a1f8SMark Brown input_uV = 0; 6761bf5a1f8SMark Brown if (rdev->supply) 6773f24f5adSAxel Lin input_uV = regulator_get_voltage(rdev->supply); 6781bf5a1f8SMark Brown if (input_uV <= 0) 679414c70cbSLiam Girdwood input_uV = rdev->constraints->input_uV; 680414c70cbSLiam Girdwood if (input_uV <= 0) 681414c70cbSLiam Girdwood return; 682414c70cbSLiam Girdwood 683414c70cbSLiam Girdwood /* calc total requested load */ 684414c70cbSLiam Girdwood list_for_each_entry(sibling, &rdev->consumer_list, list) 685414c70cbSLiam Girdwood current_uA += sibling->uA_load; 686414c70cbSLiam Girdwood 687414c70cbSLiam Girdwood /* now get the optimum mode for our new total regulator load */ 688414c70cbSLiam Girdwood mode = rdev->desc->ops->get_optimum_mode(rdev, input_uV, 689414c70cbSLiam Girdwood output_uV, current_uA); 690414c70cbSLiam Girdwood 691414c70cbSLiam Girdwood /* check the new mode is allowed */ 6922c608234SMark Brown err = regulator_mode_constrain(rdev, &mode); 693414c70cbSLiam Girdwood if (err == 0) 694414c70cbSLiam Girdwood rdev->desc->ops->set_mode(rdev, mode); 695414c70cbSLiam Girdwood } 696414c70cbSLiam Girdwood 697414c70cbSLiam Girdwood static int suspend_set_state(struct regulator_dev *rdev, 698414c70cbSLiam Girdwood struct regulator_state *rstate) 699414c70cbSLiam Girdwood { 700414c70cbSLiam Girdwood int ret = 0; 701638f85c5SMark Brown 702638f85c5SMark Brown /* If we have no suspend mode configration don't set anything; 7038ac0e95dSAxel Lin * only warn if the driver implements set_suspend_voltage or 7048ac0e95dSAxel Lin * set_suspend_mode callback. 705638f85c5SMark Brown */ 706638f85c5SMark Brown if (!rstate->enabled && !rstate->disabled) { 7078ac0e95dSAxel Lin if (rdev->desc->ops->set_suspend_voltage || 7088ac0e95dSAxel Lin rdev->desc->ops->set_suspend_mode) 7095da84fd9SJoe Perches rdev_warn(rdev, "No configuration\n"); 710638f85c5SMark Brown return 0; 711638f85c5SMark Brown } 712638f85c5SMark Brown 713638f85c5SMark Brown if (rstate->enabled && rstate->disabled) { 7145da84fd9SJoe Perches rdev_err(rdev, "invalid configuration\n"); 715638f85c5SMark Brown return -EINVAL; 716638f85c5SMark Brown } 717638f85c5SMark Brown 7188ac0e95dSAxel Lin if (rstate->enabled && rdev->desc->ops->set_suspend_enable) 719414c70cbSLiam Girdwood ret = rdev->desc->ops->set_suspend_enable(rdev); 7208ac0e95dSAxel Lin else if (rstate->disabled && rdev->desc->ops->set_suspend_disable) 721414c70cbSLiam Girdwood ret = rdev->desc->ops->set_suspend_disable(rdev); 7228ac0e95dSAxel Lin else /* OK if set_suspend_enable or set_suspend_disable is NULL */ 7238ac0e95dSAxel Lin ret = 0; 7248ac0e95dSAxel Lin 725414c70cbSLiam Girdwood if (ret < 0) { 7265da84fd9SJoe Perches rdev_err(rdev, "failed to enabled/disable\n"); 727414c70cbSLiam Girdwood return ret; 728414c70cbSLiam Girdwood } 729414c70cbSLiam Girdwood 730414c70cbSLiam Girdwood if (rdev->desc->ops->set_suspend_voltage && rstate->uV > 0) { 731414c70cbSLiam Girdwood ret = rdev->desc->ops->set_suspend_voltage(rdev, rstate->uV); 732414c70cbSLiam Girdwood if (ret < 0) { 7335da84fd9SJoe Perches rdev_err(rdev, "failed to set voltage\n"); 734414c70cbSLiam Girdwood return ret; 735414c70cbSLiam Girdwood } 736414c70cbSLiam Girdwood } 737414c70cbSLiam Girdwood 738414c70cbSLiam Girdwood if (rdev->desc->ops->set_suspend_mode && rstate->mode > 0) { 739414c70cbSLiam Girdwood ret = rdev->desc->ops->set_suspend_mode(rdev, rstate->mode); 740414c70cbSLiam Girdwood if (ret < 0) { 7415da84fd9SJoe Perches rdev_err(rdev, "failed to set mode\n"); 742414c70cbSLiam Girdwood return ret; 743414c70cbSLiam Girdwood } 744414c70cbSLiam Girdwood } 745414c70cbSLiam Girdwood return ret; 746414c70cbSLiam Girdwood } 747414c70cbSLiam Girdwood 748414c70cbSLiam Girdwood /* locks held by caller */ 749414c70cbSLiam Girdwood static int suspend_prepare(struct regulator_dev *rdev, suspend_state_t state) 750414c70cbSLiam Girdwood { 751414c70cbSLiam Girdwood if (!rdev->constraints) 752414c70cbSLiam Girdwood return -EINVAL; 753414c70cbSLiam Girdwood 754414c70cbSLiam Girdwood switch (state) { 755414c70cbSLiam Girdwood case PM_SUSPEND_STANDBY: 756414c70cbSLiam Girdwood return suspend_set_state(rdev, 757414c70cbSLiam Girdwood &rdev->constraints->state_standby); 758414c70cbSLiam Girdwood case PM_SUSPEND_MEM: 759414c70cbSLiam Girdwood return suspend_set_state(rdev, 760414c70cbSLiam Girdwood &rdev->constraints->state_mem); 761414c70cbSLiam Girdwood case PM_SUSPEND_MAX: 762414c70cbSLiam Girdwood return suspend_set_state(rdev, 763414c70cbSLiam Girdwood &rdev->constraints->state_disk); 764414c70cbSLiam Girdwood default: 765414c70cbSLiam Girdwood return -EINVAL; 766414c70cbSLiam Girdwood } 767414c70cbSLiam Girdwood } 768414c70cbSLiam Girdwood 769414c70cbSLiam Girdwood static void print_constraints(struct regulator_dev *rdev) 770414c70cbSLiam Girdwood { 771414c70cbSLiam Girdwood struct regulation_constraints *constraints = rdev->constraints; 772973e9a27SMark Brown char buf[80] = ""; 7738f031b48SMark Brown int count = 0; 7748f031b48SMark Brown int ret; 775414c70cbSLiam Girdwood 7768f031b48SMark Brown if (constraints->min_uV && constraints->max_uV) { 777414c70cbSLiam Girdwood if (constraints->min_uV == constraints->max_uV) 7788f031b48SMark Brown count += sprintf(buf + count, "%d mV ", 779414c70cbSLiam Girdwood constraints->min_uV / 1000); 780414c70cbSLiam Girdwood else 7818f031b48SMark Brown count += sprintf(buf + count, "%d <--> %d mV ", 782414c70cbSLiam Girdwood constraints->min_uV / 1000, 783414c70cbSLiam Girdwood constraints->max_uV / 1000); 7848f031b48SMark Brown } 7858f031b48SMark Brown 7868f031b48SMark Brown if (!constraints->min_uV || 7878f031b48SMark Brown constraints->min_uV != constraints->max_uV) { 7888f031b48SMark Brown ret = _regulator_get_voltage(rdev); 7898f031b48SMark Brown if (ret > 0) 7908f031b48SMark Brown count += sprintf(buf + count, "at %d mV ", ret / 1000); 7918f031b48SMark Brown } 7928f031b48SMark Brown 793bf5892a8SMark Brown if (constraints->uV_offset) 794bf5892a8SMark Brown count += sprintf(buf, "%dmV offset ", 795bf5892a8SMark Brown constraints->uV_offset / 1000); 796bf5892a8SMark Brown 7978f031b48SMark Brown if (constraints->min_uA && constraints->max_uA) { 798414c70cbSLiam Girdwood if (constraints->min_uA == constraints->max_uA) 7998f031b48SMark Brown count += sprintf(buf + count, "%d mA ", 800414c70cbSLiam Girdwood constraints->min_uA / 1000); 801414c70cbSLiam Girdwood else 8028f031b48SMark Brown count += sprintf(buf + count, "%d <--> %d mA ", 803414c70cbSLiam Girdwood constraints->min_uA / 1000, 804414c70cbSLiam Girdwood constraints->max_uA / 1000); 805414c70cbSLiam Girdwood } 8068f031b48SMark Brown 8078f031b48SMark Brown if (!constraints->min_uA || 8088f031b48SMark Brown constraints->min_uA != constraints->max_uA) { 8098f031b48SMark Brown ret = _regulator_get_current_limit(rdev); 8108f031b48SMark Brown if (ret > 0) 811e4a6376bSCyril Chemparathy count += sprintf(buf + count, "at %d mA ", ret / 1000); 8128f031b48SMark Brown } 8138f031b48SMark Brown 814414c70cbSLiam Girdwood if (constraints->valid_modes_mask & REGULATOR_MODE_FAST) 815414c70cbSLiam Girdwood count += sprintf(buf + count, "fast "); 816414c70cbSLiam Girdwood if (constraints->valid_modes_mask & REGULATOR_MODE_NORMAL) 817414c70cbSLiam Girdwood count += sprintf(buf + count, "normal "); 818414c70cbSLiam Girdwood if (constraints->valid_modes_mask & REGULATOR_MODE_IDLE) 819414c70cbSLiam Girdwood count += sprintf(buf + count, "idle "); 820414c70cbSLiam Girdwood if (constraints->valid_modes_mask & REGULATOR_MODE_STANDBY) 821414c70cbSLiam Girdwood count += sprintf(buf + count, "standby"); 822414c70cbSLiam Girdwood 823215b8b05SUwe Kleine-König if (!count) 824215b8b05SUwe Kleine-König sprintf(buf, "no parameters"); 825215b8b05SUwe Kleine-König 82613ce29f8SMark Brown rdev_info(rdev, "%s\n", buf); 8274a682922SMark Brown 8284a682922SMark Brown if ((constraints->min_uV != constraints->max_uV) && 8294a682922SMark Brown !(constraints->valid_ops_mask & REGULATOR_CHANGE_VOLTAGE)) 8304a682922SMark Brown rdev_warn(rdev, 8314a682922SMark Brown "Voltage range but no REGULATOR_CHANGE_VOLTAGE\n"); 832414c70cbSLiam Girdwood } 833414c70cbSLiam Girdwood 834e79055d6SMark Brown static int machine_constraints_voltage(struct regulator_dev *rdev, 8351083c393SMark Brown struct regulation_constraints *constraints) 836e79055d6SMark Brown { 837e79055d6SMark Brown struct regulator_ops *ops = rdev->desc->ops; 838af5866c9SMark Brown int ret; 839af5866c9SMark Brown 840af5866c9SMark Brown /* do we need to apply the constraint voltage */ 841af5866c9SMark Brown if (rdev->constraints->apply_uV && 84275790251SMark Brown rdev->constraints->min_uV == rdev->constraints->max_uV) { 84375790251SMark Brown ret = _regulator_do_set_voltage(rdev, 8443a93f2a9SMark Brown rdev->constraints->min_uV, 84575790251SMark Brown rdev->constraints->max_uV); 846af5866c9SMark Brown if (ret < 0) { 8475da84fd9SJoe Perches rdev_err(rdev, "failed to apply %duV constraint\n", 8485da84fd9SJoe Perches rdev->constraints->min_uV); 849af5866c9SMark Brown return ret; 850af5866c9SMark Brown } 851af5866c9SMark Brown } 852e79055d6SMark Brown 853e79055d6SMark Brown /* constrain machine-level voltage specs to fit 854e79055d6SMark Brown * the actual range supported by this regulator. 855e79055d6SMark Brown */ 856e79055d6SMark Brown if (ops->list_voltage && rdev->desc->n_voltages) { 857e79055d6SMark Brown int count = rdev->desc->n_voltages; 858e79055d6SMark Brown int i; 859e79055d6SMark Brown int min_uV = INT_MAX; 860e79055d6SMark Brown int max_uV = INT_MIN; 861e79055d6SMark Brown int cmin = constraints->min_uV; 862e79055d6SMark Brown int cmax = constraints->max_uV; 863e79055d6SMark Brown 864e79055d6SMark Brown /* it's safe to autoconfigure fixed-voltage supplies 865e79055d6SMark Brown and the constraints are used by list_voltage. */ 866e79055d6SMark Brown if (count == 1 && !cmin) { 867e79055d6SMark Brown cmin = 1; 868e79055d6SMark Brown cmax = INT_MAX; 869e79055d6SMark Brown constraints->min_uV = cmin; 870e79055d6SMark Brown constraints->max_uV = cmax; 871e79055d6SMark Brown } 872e79055d6SMark Brown 873e79055d6SMark Brown /* voltage constraints are optional */ 874e79055d6SMark Brown if ((cmin == 0) && (cmax == 0)) 875e79055d6SMark Brown return 0; 876e79055d6SMark Brown 877e79055d6SMark Brown /* else require explicit machine-level constraints */ 878e79055d6SMark Brown if (cmin <= 0 || cmax <= 0 || cmax < cmin) { 8795da84fd9SJoe Perches rdev_err(rdev, "invalid voltage constraints\n"); 880e79055d6SMark Brown return -EINVAL; 881e79055d6SMark Brown } 882e79055d6SMark Brown 883e79055d6SMark Brown /* initial: [cmin..cmax] valid, [min_uV..max_uV] not */ 884e79055d6SMark Brown for (i = 0; i < count; i++) { 885e79055d6SMark Brown int value; 886e79055d6SMark Brown 887e79055d6SMark Brown value = ops->list_voltage(rdev, i); 888e79055d6SMark Brown if (value <= 0) 889e79055d6SMark Brown continue; 890e79055d6SMark Brown 891e79055d6SMark Brown /* maybe adjust [min_uV..max_uV] */ 892e79055d6SMark Brown if (value >= cmin && value < min_uV) 893e79055d6SMark Brown min_uV = value; 894e79055d6SMark Brown if (value <= cmax && value > max_uV) 895e79055d6SMark Brown max_uV = value; 896e79055d6SMark Brown } 897e79055d6SMark Brown 898e79055d6SMark Brown /* final: [min_uV..max_uV] valid iff constraints valid */ 899e79055d6SMark Brown if (max_uV < min_uV) { 900fff15befSMark Brown rdev_err(rdev, 901fff15befSMark Brown "unsupportable voltage constraints %u-%uuV\n", 902fff15befSMark Brown min_uV, max_uV); 903e79055d6SMark Brown return -EINVAL; 904e79055d6SMark Brown } 905e79055d6SMark Brown 906e79055d6SMark Brown /* use regulator's subset of machine constraints */ 907e79055d6SMark Brown if (constraints->min_uV < min_uV) { 9085da84fd9SJoe Perches rdev_dbg(rdev, "override min_uV, %d -> %d\n", 9095da84fd9SJoe Perches constraints->min_uV, min_uV); 910e79055d6SMark Brown constraints->min_uV = min_uV; 911e79055d6SMark Brown } 912e79055d6SMark Brown if (constraints->max_uV > max_uV) { 9135da84fd9SJoe Perches rdev_dbg(rdev, "override max_uV, %d -> %d\n", 9145da84fd9SJoe Perches constraints->max_uV, max_uV); 915e79055d6SMark Brown constraints->max_uV = max_uV; 916e79055d6SMark Brown } 917e79055d6SMark Brown } 918e79055d6SMark Brown 919e79055d6SMark Brown return 0; 920e79055d6SMark Brown } 921e79055d6SMark Brown 922a5766f11SLiam Girdwood /** 923a5766f11SLiam Girdwood * set_machine_constraints - sets regulator constraints 92469279fb9SMark Brown * @rdev: regulator source 925c8e7e464SMark Brown * @constraints: constraints to apply 926a5766f11SLiam Girdwood * 927a5766f11SLiam Girdwood * Allows platform initialisation code to define and constrain 928a5766f11SLiam Girdwood * regulator circuits e.g. valid voltage/current ranges, etc. NOTE: 929a5766f11SLiam Girdwood * Constraints *must* be set by platform code in order for some 930a5766f11SLiam Girdwood * regulator operations to proceed i.e. set_voltage, set_current_limit, 931a5766f11SLiam Girdwood * set_mode. 932a5766f11SLiam Girdwood */ 933a5766f11SLiam Girdwood static int set_machine_constraints(struct regulator_dev *rdev, 934f8c12fe3SMark Brown const struct regulation_constraints *constraints) 935a5766f11SLiam Girdwood { 936a5766f11SLiam Girdwood int ret = 0; 937e5fda26cSMark Brown struct regulator_ops *ops = rdev->desc->ops; 938e06f5b4fSMark Brown 9399a8f5e07SMark Brown if (constraints) 940f8c12fe3SMark Brown rdev->constraints = kmemdup(constraints, sizeof(*constraints), 941f8c12fe3SMark Brown GFP_KERNEL); 9429a8f5e07SMark Brown else 9439a8f5e07SMark Brown rdev->constraints = kzalloc(sizeof(*constraints), 9449a8f5e07SMark Brown GFP_KERNEL); 945f8c12fe3SMark Brown if (!rdev->constraints) 946f8c12fe3SMark Brown return -ENOMEM; 947af5866c9SMark Brown 948f8c12fe3SMark Brown ret = machine_constraints_voltage(rdev, rdev->constraints); 949e79055d6SMark Brown if (ret != 0) 9503e2b9abdSMark Brown goto out; 9513e2b9abdSMark Brown 952a5766f11SLiam Girdwood /* do we need to setup our suspend state */ 9539a8f5e07SMark Brown if (rdev->constraints->initial_state) { 954f8c12fe3SMark Brown ret = suspend_prepare(rdev, rdev->constraints->initial_state); 955e06f5b4fSMark Brown if (ret < 0) { 9565da84fd9SJoe Perches rdev_err(rdev, "failed to set suspend state\n"); 957e06f5b4fSMark Brown goto out; 958e06f5b4fSMark Brown } 959e06f5b4fSMark Brown } 960a5766f11SLiam Girdwood 9619a8f5e07SMark Brown if (rdev->constraints->initial_mode) { 962a308466cSMark Brown if (!ops->set_mode) { 9635da84fd9SJoe Perches rdev_err(rdev, "no set_mode operation\n"); 964a308466cSMark Brown ret = -EINVAL; 965a308466cSMark Brown goto out; 966a308466cSMark Brown } 967a308466cSMark Brown 968f8c12fe3SMark Brown ret = ops->set_mode(rdev, rdev->constraints->initial_mode); 969a308466cSMark Brown if (ret < 0) { 9705da84fd9SJoe Perches rdev_err(rdev, "failed to set initial mode: %d\n", ret); 971a308466cSMark Brown goto out; 972a308466cSMark Brown } 973a308466cSMark Brown } 974a308466cSMark Brown 975cacf90f2SMark Brown /* If the constraints say the regulator should be on at this point 976cacf90f2SMark Brown * and we have control then make sure it is enabled. 977cacf90f2SMark Brown */ 978f8c12fe3SMark Brown if ((rdev->constraints->always_on || rdev->constraints->boot_on) && 979f8c12fe3SMark Brown ops->enable) { 980e5fda26cSMark Brown ret = ops->enable(rdev); 981e5fda26cSMark Brown if (ret < 0) { 9825da84fd9SJoe Perches rdev_err(rdev, "failed to enable\n"); 983e5fda26cSMark Brown goto out; 984e5fda26cSMark Brown } 985e5fda26cSMark Brown } 986e5fda26cSMark Brown 9876f0b2c69SYadwinder Singh Brar if (rdev->constraints->ramp_delay && ops->set_ramp_delay) { 9886f0b2c69SYadwinder Singh Brar ret = ops->set_ramp_delay(rdev, rdev->constraints->ramp_delay); 9896f0b2c69SYadwinder Singh Brar if (ret < 0) { 9906f0b2c69SYadwinder Singh Brar rdev_err(rdev, "failed to set ramp_delay\n"); 9916f0b2c69SYadwinder Singh Brar goto out; 9926f0b2c69SYadwinder Singh Brar } 9936f0b2c69SYadwinder Singh Brar } 9946f0b2c69SYadwinder Singh Brar 995a5766f11SLiam Girdwood print_constraints(rdev); 9961a6958e7SAxel Lin return 0; 997a5766f11SLiam Girdwood out: 9981a6958e7SAxel Lin kfree(rdev->constraints); 9991a6958e7SAxel Lin rdev->constraints = NULL; 1000a5766f11SLiam Girdwood return ret; 1001a5766f11SLiam Girdwood } 1002a5766f11SLiam Girdwood 1003a5766f11SLiam Girdwood /** 1004a5766f11SLiam Girdwood * set_supply - set regulator supply regulator 100569279fb9SMark Brown * @rdev: regulator name 100669279fb9SMark Brown * @supply_rdev: supply regulator name 1007a5766f11SLiam Girdwood * 1008a5766f11SLiam Girdwood * Called by platform initialisation code to set the supply regulator for this 1009a5766f11SLiam Girdwood * regulator. This ensures that a regulators supply will also be enabled by the 1010a5766f11SLiam Girdwood * core if it's child is enabled. 1011a5766f11SLiam Girdwood */ 1012a5766f11SLiam Girdwood static int set_supply(struct regulator_dev *rdev, 1013a5766f11SLiam Girdwood struct regulator_dev *supply_rdev) 1014a5766f11SLiam Girdwood { 1015a5766f11SLiam Girdwood int err; 1016a5766f11SLiam Girdwood 10173801b86aSMark Brown rdev_info(rdev, "supplied by %s\n", rdev_get_name(supply_rdev)); 10183801b86aSMark Brown 10193801b86aSMark Brown rdev->supply = create_regulator(supply_rdev, &rdev->dev, "SUPPLY"); 102032c78de8SAxel Lin if (rdev->supply == NULL) { 102132c78de8SAxel Lin err = -ENOMEM; 1022a5766f11SLiam Girdwood return err; 1023a5766f11SLiam Girdwood } 102457ad526aSLaxman Dewangan supply_rdev->open_count++; 1025a5766f11SLiam Girdwood 10263801b86aSMark Brown return 0; 10273801b86aSMark Brown } 10283801b86aSMark Brown 1029a5766f11SLiam Girdwood /** 103006c63f93SRandy Dunlap * set_consumer_device_supply - Bind a regulator to a symbolic supply 103169279fb9SMark Brown * @rdev: regulator source 103240f9244fSMark Brown * @consumer_dev_name: dev_name() string for device supply applies to 1033a5766f11SLiam Girdwood * @supply: symbolic name for supply 1034a5766f11SLiam Girdwood * 1035a5766f11SLiam Girdwood * Allows platform initialisation code to map physical regulator 1036a5766f11SLiam Girdwood * sources to symbolic names for supplies for use by devices. Devices 1037a5766f11SLiam Girdwood * should use these symbolic names to request regulators, avoiding the 1038a5766f11SLiam Girdwood * need to provide board-specific regulator names as platform data. 1039a5766f11SLiam Girdwood */ 1040a5766f11SLiam Girdwood static int set_consumer_device_supply(struct regulator_dev *rdev, 1041737f360dSMark Brown const char *consumer_dev_name, 104240f9244fSMark Brown const char *supply) 1043a5766f11SLiam Girdwood { 1044a5766f11SLiam Girdwood struct regulator_map *node; 10459ed2099eSMark Brown int has_dev; 1046a5766f11SLiam Girdwood 1047a5766f11SLiam Girdwood if (supply == NULL) 1048a5766f11SLiam Girdwood return -EINVAL; 1049a5766f11SLiam Girdwood 10509ed2099eSMark Brown if (consumer_dev_name != NULL) 10519ed2099eSMark Brown has_dev = 1; 10529ed2099eSMark Brown else 10539ed2099eSMark Brown has_dev = 0; 10549ed2099eSMark Brown 10556001e13cSDavid Brownell list_for_each_entry(node, ®ulator_map_list, list) { 105623b5cc2aSJani Nikula if (node->dev_name && consumer_dev_name) { 105723b5cc2aSJani Nikula if (strcmp(node->dev_name, consumer_dev_name) != 0) 10586001e13cSDavid Brownell continue; 105923b5cc2aSJani Nikula } else if (node->dev_name || consumer_dev_name) { 106023b5cc2aSJani Nikula continue; 106123b5cc2aSJani Nikula } 106223b5cc2aSJani Nikula 10636001e13cSDavid Brownell if (strcmp(node->supply, supply) != 0) 10646001e13cSDavid Brownell continue; 10656001e13cSDavid Brownell 1066737f360dSMark Brown pr_debug("%s: %s/%s is '%s' supply; fail %s/%s\n", 1067737f360dSMark Brown consumer_dev_name, 10686001e13cSDavid Brownell dev_name(&node->regulator->dev), 10696001e13cSDavid Brownell node->regulator->desc->name, 10706001e13cSDavid Brownell supply, 10711083c393SMark Brown dev_name(&rdev->dev), rdev_get_name(rdev)); 10726001e13cSDavid Brownell return -EBUSY; 10736001e13cSDavid Brownell } 10746001e13cSDavid Brownell 10759ed2099eSMark Brown node = kzalloc(sizeof(struct regulator_map), GFP_KERNEL); 1076a5766f11SLiam Girdwood if (node == NULL) 1077a5766f11SLiam Girdwood return -ENOMEM; 1078a5766f11SLiam Girdwood 1079a5766f11SLiam Girdwood node->regulator = rdev; 1080a5766f11SLiam Girdwood node->supply = supply; 1081a5766f11SLiam Girdwood 10829ed2099eSMark Brown if (has_dev) { 10839ed2099eSMark Brown node->dev_name = kstrdup(consumer_dev_name, GFP_KERNEL); 108440f9244fSMark Brown if (node->dev_name == NULL) { 108540f9244fSMark Brown kfree(node); 108640f9244fSMark Brown return -ENOMEM; 108740f9244fSMark Brown } 10889ed2099eSMark Brown } 108940f9244fSMark Brown 1090a5766f11SLiam Girdwood list_add(&node->list, ®ulator_map_list); 1091a5766f11SLiam Girdwood return 0; 1092a5766f11SLiam Girdwood } 1093a5766f11SLiam Girdwood 10940f1d747bSMike Rapoport static void unset_regulator_supplies(struct regulator_dev *rdev) 10950f1d747bSMike Rapoport { 10960f1d747bSMike Rapoport struct regulator_map *node, *n; 10970f1d747bSMike Rapoport 10980f1d747bSMike Rapoport list_for_each_entry_safe(node, n, ®ulator_map_list, list) { 10990f1d747bSMike Rapoport if (rdev == node->regulator) { 11000f1d747bSMike Rapoport list_del(&node->list); 110140f9244fSMark Brown kfree(node->dev_name); 11020f1d747bSMike Rapoport kfree(node); 11030f1d747bSMike Rapoport } 11040f1d747bSMike Rapoport } 11050f1d747bSMike Rapoport } 11060f1d747bSMike Rapoport 1107f5726ae3SMark Brown #define REG_STR_SIZE 64 1108414c70cbSLiam Girdwood 1109414c70cbSLiam Girdwood static struct regulator *create_regulator(struct regulator_dev *rdev, 1110414c70cbSLiam Girdwood struct device *dev, 1111414c70cbSLiam Girdwood const char *supply_name) 1112414c70cbSLiam Girdwood { 1113414c70cbSLiam Girdwood struct regulator *regulator; 1114414c70cbSLiam Girdwood char buf[REG_STR_SIZE]; 1115414c70cbSLiam Girdwood int err, size; 1116414c70cbSLiam Girdwood 1117414c70cbSLiam Girdwood regulator = kzalloc(sizeof(*regulator), GFP_KERNEL); 1118414c70cbSLiam Girdwood if (regulator == NULL) 1119414c70cbSLiam Girdwood return NULL; 1120414c70cbSLiam Girdwood 1121414c70cbSLiam Girdwood mutex_lock(&rdev->mutex); 1122414c70cbSLiam Girdwood regulator->rdev = rdev; 1123414c70cbSLiam Girdwood list_add(®ulator->list, &rdev->consumer_list); 1124414c70cbSLiam Girdwood 1125414c70cbSLiam Girdwood if (dev) { 1126e2c98eafSShawn Guo regulator->dev = dev; 1127e2c98eafSShawn Guo 1128222cc7b1SMark Brown /* Add a link to the device sysfs entry */ 1129414c70cbSLiam Girdwood size = scnprintf(buf, REG_STR_SIZE, "%s-%s", 1130414c70cbSLiam Girdwood dev->kobj.name, supply_name); 1131414c70cbSLiam Girdwood if (size >= REG_STR_SIZE) 1132222cc7b1SMark Brown goto overflow_err; 1133414c70cbSLiam Girdwood 1134414c70cbSLiam Girdwood regulator->supply_name = kstrdup(buf, GFP_KERNEL); 1135414c70cbSLiam Girdwood if (regulator->supply_name == NULL) 1136222cc7b1SMark Brown goto overflow_err; 1137414c70cbSLiam Girdwood 1138414c70cbSLiam Girdwood err = sysfs_create_link(&rdev->dev.kobj, &dev->kobj, 1139414c70cbSLiam Girdwood buf); 1140414c70cbSLiam Girdwood if (err) { 11415da84fd9SJoe Perches rdev_warn(rdev, "could not add device link %s err %d\n", 11421d7372e1SDaniel Walker dev->kobj.name, err); 1143222cc7b1SMark Brown /* non-fatal */ 1144414c70cbSLiam Girdwood } 11455de70519SMark Brown } else { 11465de70519SMark Brown regulator->supply_name = kstrdup(supply_name, GFP_KERNEL); 11475de70519SMark Brown if (regulator->supply_name == NULL) 1148222cc7b1SMark Brown goto overflow_err; 1149414c70cbSLiam Girdwood } 11505de70519SMark Brown 11515de70519SMark Brown regulator->debugfs = debugfs_create_dir(regulator->supply_name, 11525de70519SMark Brown rdev->debugfs); 115324751434SStephen Boyd if (!regulator->debugfs) { 11545de70519SMark Brown rdev_warn(rdev, "Failed to create debugfs directory\n"); 11555de70519SMark Brown } else { 11565de70519SMark Brown debugfs_create_u32("uA_load", 0444, regulator->debugfs, 11575de70519SMark Brown ®ulator->uA_load); 11585de70519SMark Brown debugfs_create_u32("min_uV", 0444, regulator->debugfs, 11595de70519SMark Brown ®ulator->min_uV); 11605de70519SMark Brown debugfs_create_u32("max_uV", 0444, regulator->debugfs, 11615de70519SMark Brown ®ulator->max_uV); 11625de70519SMark Brown } 11635de70519SMark Brown 11646492bc1bSMark Brown /* 11656492bc1bSMark Brown * Check now if the regulator is an always on regulator - if 11666492bc1bSMark Brown * it is then we don't need to do nearly so much work for 11676492bc1bSMark Brown * enable/disable calls. 11686492bc1bSMark Brown */ 11696492bc1bSMark Brown if (!_regulator_can_change_status(rdev) && 11706492bc1bSMark Brown _regulator_is_enabled(rdev)) 11716492bc1bSMark Brown regulator->always_on = true; 11726492bc1bSMark Brown 1173414c70cbSLiam Girdwood mutex_unlock(&rdev->mutex); 1174414c70cbSLiam Girdwood return regulator; 1175414c70cbSLiam Girdwood overflow_err: 1176414c70cbSLiam Girdwood list_del(®ulator->list); 1177414c70cbSLiam Girdwood kfree(regulator); 1178414c70cbSLiam Girdwood mutex_unlock(&rdev->mutex); 1179414c70cbSLiam Girdwood return NULL; 1180414c70cbSLiam Girdwood } 1181414c70cbSLiam Girdwood 118231aae2beSMark Brown static int _regulator_get_enable_time(struct regulator_dev *rdev) 118331aae2beSMark Brown { 118431aae2beSMark Brown if (!rdev->desc->ops->enable_time) 118579511ed3SMark Brown return rdev->desc->enable_time; 118631aae2beSMark Brown return rdev->desc->ops->enable_time(rdev); 118731aae2beSMark Brown } 118831aae2beSMark Brown 118969511a45SRajendra Nayak static struct regulator_dev *regulator_dev_lookup(struct device *dev, 11906d191a5fSMark Brown const char *supply, 11916d191a5fSMark Brown int *ret) 119269511a45SRajendra Nayak { 119369511a45SRajendra Nayak struct regulator_dev *r; 119469511a45SRajendra Nayak struct device_node *node; 1195576ca436SMark Brown struct regulator_map *map; 1196576ca436SMark Brown const char *devname = NULL; 119769511a45SRajendra Nayak 119869511a45SRajendra Nayak /* first do a dt based lookup */ 119969511a45SRajendra Nayak if (dev && dev->of_node) { 120069511a45SRajendra Nayak node = of_get_regulator(dev, supply); 12016d191a5fSMark Brown if (node) { 120269511a45SRajendra Nayak list_for_each_entry(r, ®ulator_list, list) 120369511a45SRajendra Nayak if (r->dev.parent && 120469511a45SRajendra Nayak node == r->dev.of_node) 120569511a45SRajendra Nayak return r; 12066d191a5fSMark Brown } else { 12076d191a5fSMark Brown /* 12086d191a5fSMark Brown * If we couldn't even get the node then it's 12096d191a5fSMark Brown * not just that the device didn't register 12106d191a5fSMark Brown * yet, there's no node and we'll never 12116d191a5fSMark Brown * succeed. 12126d191a5fSMark Brown */ 12136d191a5fSMark Brown *ret = -ENODEV; 12146d191a5fSMark Brown } 121569511a45SRajendra Nayak } 121669511a45SRajendra Nayak 121769511a45SRajendra Nayak /* if not found, try doing it non-dt way */ 1218576ca436SMark Brown if (dev) 1219576ca436SMark Brown devname = dev_name(dev); 1220576ca436SMark Brown 122169511a45SRajendra Nayak list_for_each_entry(r, ®ulator_list, list) 122269511a45SRajendra Nayak if (strcmp(rdev_get_name(r), supply) == 0) 122369511a45SRajendra Nayak return r; 122469511a45SRajendra Nayak 1225576ca436SMark Brown list_for_each_entry(map, ®ulator_map_list, list) { 1226576ca436SMark Brown /* If the mapping has a device set up it must match */ 1227576ca436SMark Brown if (map->dev_name && 1228576ca436SMark Brown (!devname || strcmp(map->dev_name, devname))) 1229576ca436SMark Brown continue; 1230576ca436SMark Brown 1231576ca436SMark Brown if (strcmp(map->supply, supply) == 0) 1232576ca436SMark Brown return map->regulator; 1233576ca436SMark Brown } 1234576ca436SMark Brown 1235576ca436SMark Brown 123669511a45SRajendra Nayak return NULL; 123769511a45SRajendra Nayak } 123869511a45SRajendra Nayak 12395ffbd136SMark Brown /* Internal regulator request function */ 12405ffbd136SMark Brown static struct regulator *_regulator_get(struct device *dev, const char *id, 12415ffbd136SMark Brown int exclusive) 1242414c70cbSLiam Girdwood { 1243414c70cbSLiam Girdwood struct regulator_dev *rdev; 124404bf3011SMark Brown struct regulator *regulator = ERR_PTR(-EPROBE_DEFER); 124540f9244fSMark Brown const char *devname = NULL; 12461e4b545cSNishanth Menon int ret = 0; 1247414c70cbSLiam Girdwood 1248414c70cbSLiam Girdwood if (id == NULL) { 12495da84fd9SJoe Perches pr_err("get() with no identifier\n"); 1250414c70cbSLiam Girdwood return regulator; 1251414c70cbSLiam Girdwood } 1252414c70cbSLiam Girdwood 125340f9244fSMark Brown if (dev) 125440f9244fSMark Brown devname = dev_name(dev); 125540f9244fSMark Brown 1256414c70cbSLiam Girdwood mutex_lock(®ulator_list_mutex); 1257414c70cbSLiam Girdwood 12586d191a5fSMark Brown rdev = regulator_dev_lookup(dev, id, &ret); 125969511a45SRajendra Nayak if (rdev) 126069511a45SRajendra Nayak goto found; 126169511a45SRajendra Nayak 12621e4b545cSNishanth Menon /* 12631e4b545cSNishanth Menon * If we have return value from dev_lookup fail, we do not expect to 12641e4b545cSNishanth Menon * succeed, so, quit with appropriate error value 12651e4b545cSNishanth Menon */ 12661e4b545cSNishanth Menon if (ret) { 12671e4b545cSNishanth Menon regulator = ERR_PTR(ret); 12681e4b545cSNishanth Menon goto out; 12691e4b545cSNishanth Menon } 12701e4b545cSNishanth Menon 1271688fe99aSMark Brown if (board_wants_dummy_regulator) { 1272688fe99aSMark Brown rdev = dummy_regulator_rdev; 1273688fe99aSMark Brown goto found; 1274688fe99aSMark Brown } 1275688fe99aSMark Brown 127634abbd68SMark Brown #ifdef CONFIG_REGULATOR_DUMMY 127734abbd68SMark Brown if (!devname) 127834abbd68SMark Brown devname = "deviceless"; 127934abbd68SMark Brown 128034abbd68SMark Brown /* If the board didn't flag that it was fully constrained then 128134abbd68SMark Brown * substitute in a dummy regulator so consumers can continue. 128234abbd68SMark Brown */ 128334abbd68SMark Brown if (!has_full_constraints) { 12845da84fd9SJoe Perches pr_warn("%s supply %s not found, using dummy regulator\n", 128534abbd68SMark Brown devname, id); 128634abbd68SMark Brown rdev = dummy_regulator_rdev; 128734abbd68SMark Brown goto found; 128834abbd68SMark Brown } 128934abbd68SMark Brown #endif 129034abbd68SMark Brown 1291414c70cbSLiam Girdwood mutex_unlock(®ulator_list_mutex); 1292414c70cbSLiam Girdwood return regulator; 1293414c70cbSLiam Girdwood 1294414c70cbSLiam Girdwood found: 12955ffbd136SMark Brown if (rdev->exclusive) { 12965ffbd136SMark Brown regulator = ERR_PTR(-EPERM); 12975ffbd136SMark Brown goto out; 12985ffbd136SMark Brown } 12995ffbd136SMark Brown 13005ffbd136SMark Brown if (exclusive && rdev->open_count) { 13015ffbd136SMark Brown regulator = ERR_PTR(-EBUSY); 13025ffbd136SMark Brown goto out; 13035ffbd136SMark Brown } 13045ffbd136SMark Brown 1305a5766f11SLiam Girdwood if (!try_module_get(rdev->owner)) 1306a5766f11SLiam Girdwood goto out; 1307a5766f11SLiam Girdwood 1308414c70cbSLiam Girdwood regulator = create_regulator(rdev, dev, id); 1309414c70cbSLiam Girdwood if (regulator == NULL) { 1310414c70cbSLiam Girdwood regulator = ERR_PTR(-ENOMEM); 1311414c70cbSLiam Girdwood module_put(rdev->owner); 1312bcda4321SAxel Lin goto out; 1313414c70cbSLiam Girdwood } 1314414c70cbSLiam Girdwood 13155ffbd136SMark Brown rdev->open_count++; 13165ffbd136SMark Brown if (exclusive) { 13175ffbd136SMark Brown rdev->exclusive = 1; 13185ffbd136SMark Brown 13195ffbd136SMark Brown ret = _regulator_is_enabled(rdev); 13205ffbd136SMark Brown if (ret > 0) 13215ffbd136SMark Brown rdev->use_count = 1; 13225ffbd136SMark Brown else 13235ffbd136SMark Brown rdev->use_count = 0; 13245ffbd136SMark Brown } 13255ffbd136SMark Brown 1326a5766f11SLiam Girdwood out: 1327414c70cbSLiam Girdwood mutex_unlock(®ulator_list_mutex); 13285ffbd136SMark Brown 1329414c70cbSLiam Girdwood return regulator; 1330414c70cbSLiam Girdwood } 13315ffbd136SMark Brown 13325ffbd136SMark Brown /** 13335ffbd136SMark Brown * regulator_get - lookup and obtain a reference to a regulator. 13345ffbd136SMark Brown * @dev: device for regulator "consumer" 13355ffbd136SMark Brown * @id: Supply name or regulator ID. 13365ffbd136SMark Brown * 13375ffbd136SMark Brown * Returns a struct regulator corresponding to the regulator producer, 13385ffbd136SMark Brown * or IS_ERR() condition containing errno. 13395ffbd136SMark Brown * 13405ffbd136SMark Brown * Use of supply names configured via regulator_set_device_supply() is 13415ffbd136SMark Brown * strongly encouraged. It is recommended that the supply name used 13425ffbd136SMark Brown * should match the name used for the supply and/or the relevant 13435ffbd136SMark Brown * device pins in the datasheet. 13445ffbd136SMark Brown */ 13455ffbd136SMark Brown struct regulator *regulator_get(struct device *dev, const char *id) 13465ffbd136SMark Brown { 13475ffbd136SMark Brown return _regulator_get(dev, id, 0); 13485ffbd136SMark Brown } 1349414c70cbSLiam Girdwood EXPORT_SYMBOL_GPL(regulator_get); 1350414c70cbSLiam Girdwood 1351070b9079SStephen Boyd static void devm_regulator_release(struct device *dev, void *res) 1352070b9079SStephen Boyd { 1353070b9079SStephen Boyd regulator_put(*(struct regulator **)res); 1354070b9079SStephen Boyd } 1355070b9079SStephen Boyd 1356070b9079SStephen Boyd /** 1357070b9079SStephen Boyd * devm_regulator_get - Resource managed regulator_get() 1358070b9079SStephen Boyd * @dev: device for regulator "consumer" 1359070b9079SStephen Boyd * @id: Supply name or regulator ID. 1360070b9079SStephen Boyd * 1361070b9079SStephen Boyd * Managed regulator_get(). Regulators returned from this function are 1362070b9079SStephen Boyd * automatically regulator_put() on driver detach. See regulator_get() for more 1363070b9079SStephen Boyd * information. 1364070b9079SStephen Boyd */ 1365070b9079SStephen Boyd struct regulator *devm_regulator_get(struct device *dev, const char *id) 1366070b9079SStephen Boyd { 1367070b9079SStephen Boyd struct regulator **ptr, *regulator; 1368070b9079SStephen Boyd 1369070b9079SStephen Boyd ptr = devres_alloc(devm_regulator_release, sizeof(*ptr), GFP_KERNEL); 1370070b9079SStephen Boyd if (!ptr) 1371070b9079SStephen Boyd return ERR_PTR(-ENOMEM); 1372070b9079SStephen Boyd 1373070b9079SStephen Boyd regulator = regulator_get(dev, id); 1374070b9079SStephen Boyd if (!IS_ERR(regulator)) { 1375070b9079SStephen Boyd *ptr = regulator; 1376070b9079SStephen Boyd devres_add(dev, ptr); 1377070b9079SStephen Boyd } else { 1378070b9079SStephen Boyd devres_free(ptr); 1379070b9079SStephen Boyd } 1380070b9079SStephen Boyd 1381070b9079SStephen Boyd return regulator; 1382070b9079SStephen Boyd } 1383070b9079SStephen Boyd EXPORT_SYMBOL_GPL(devm_regulator_get); 1384070b9079SStephen Boyd 1385414c70cbSLiam Girdwood /** 13865ffbd136SMark Brown * regulator_get_exclusive - obtain exclusive access to a regulator. 13875ffbd136SMark Brown * @dev: device for regulator "consumer" 13885ffbd136SMark Brown * @id: Supply name or regulator ID. 13895ffbd136SMark Brown * 13905ffbd136SMark Brown * Returns a struct regulator corresponding to the regulator producer, 13915ffbd136SMark Brown * or IS_ERR() condition containing errno. Other consumers will be 13925ffbd136SMark Brown * unable to obtain this reference is held and the use count for the 13935ffbd136SMark Brown * regulator will be initialised to reflect the current state of the 13945ffbd136SMark Brown * regulator. 13955ffbd136SMark Brown * 13965ffbd136SMark Brown * This is intended for use by consumers which cannot tolerate shared 13975ffbd136SMark Brown * use of the regulator such as those which need to force the 13985ffbd136SMark Brown * regulator off for correct operation of the hardware they are 13995ffbd136SMark Brown * controlling. 14005ffbd136SMark Brown * 14015ffbd136SMark Brown * Use of supply names configured via regulator_set_device_supply() is 14025ffbd136SMark Brown * strongly encouraged. It is recommended that the supply name used 14035ffbd136SMark Brown * should match the name used for the supply and/or the relevant 14045ffbd136SMark Brown * device pins in the datasheet. 14055ffbd136SMark Brown */ 14065ffbd136SMark Brown struct regulator *regulator_get_exclusive(struct device *dev, const char *id) 14075ffbd136SMark Brown { 14085ffbd136SMark Brown return _regulator_get(dev, id, 1); 14095ffbd136SMark Brown } 14105ffbd136SMark Brown EXPORT_SYMBOL_GPL(regulator_get_exclusive); 14115ffbd136SMark Brown 141223ff2f0fSCharles Keepax /* Locks held by regulator_put() */ 141323ff2f0fSCharles Keepax static void _regulator_put(struct regulator *regulator) 1414414c70cbSLiam Girdwood { 1415414c70cbSLiam Girdwood struct regulator_dev *rdev; 1416414c70cbSLiam Girdwood 1417414c70cbSLiam Girdwood if (regulator == NULL || IS_ERR(regulator)) 1418414c70cbSLiam Girdwood return; 1419414c70cbSLiam Girdwood 1420414c70cbSLiam Girdwood rdev = regulator->rdev; 1421414c70cbSLiam Girdwood 14225de70519SMark Brown debugfs_remove_recursive(regulator->debugfs); 14235de70519SMark Brown 1424414c70cbSLiam Girdwood /* remove any sysfs entries */ 1425e2c98eafSShawn Guo if (regulator->dev) 1426414c70cbSLiam Girdwood sysfs_remove_link(&rdev->dev.kobj, regulator->supply_name); 14275de70519SMark Brown kfree(regulator->supply_name); 1428414c70cbSLiam Girdwood list_del(®ulator->list); 1429414c70cbSLiam Girdwood kfree(regulator); 1430414c70cbSLiam Girdwood 14315ffbd136SMark Brown rdev->open_count--; 14325ffbd136SMark Brown rdev->exclusive = 0; 14335ffbd136SMark Brown 1434414c70cbSLiam Girdwood module_put(rdev->owner); 143523ff2f0fSCharles Keepax } 143623ff2f0fSCharles Keepax 143723ff2f0fSCharles Keepax /** 143823ff2f0fSCharles Keepax * regulator_put - "free" the regulator source 143923ff2f0fSCharles Keepax * @regulator: regulator source 144023ff2f0fSCharles Keepax * 144123ff2f0fSCharles Keepax * Note: drivers must ensure that all regulator_enable calls made on this 144223ff2f0fSCharles Keepax * regulator source are balanced by regulator_disable calls prior to calling 144323ff2f0fSCharles Keepax * this function. 144423ff2f0fSCharles Keepax */ 144523ff2f0fSCharles Keepax void regulator_put(struct regulator *regulator) 144623ff2f0fSCharles Keepax { 144723ff2f0fSCharles Keepax mutex_lock(®ulator_list_mutex); 144823ff2f0fSCharles Keepax _regulator_put(regulator); 1449414c70cbSLiam Girdwood mutex_unlock(®ulator_list_mutex); 1450414c70cbSLiam Girdwood } 1451414c70cbSLiam Girdwood EXPORT_SYMBOL_GPL(regulator_put); 1452414c70cbSLiam Girdwood 1453d5ad34f7SMark Brown static int devm_regulator_match(struct device *dev, void *res, void *data) 1454d5ad34f7SMark Brown { 1455d5ad34f7SMark Brown struct regulator **r = res; 1456d5ad34f7SMark Brown if (!r || !*r) { 1457d5ad34f7SMark Brown WARN_ON(!r || !*r); 1458d5ad34f7SMark Brown return 0; 1459d5ad34f7SMark Brown } 1460d5ad34f7SMark Brown return *r == data; 1461d5ad34f7SMark Brown } 1462d5ad34f7SMark Brown 1463d5ad34f7SMark Brown /** 1464d5ad34f7SMark Brown * devm_regulator_put - Resource managed regulator_put() 1465d5ad34f7SMark Brown * @regulator: regulator to free 1466d5ad34f7SMark Brown * 1467d5ad34f7SMark Brown * Deallocate a regulator allocated with devm_regulator_get(). Normally 1468d5ad34f7SMark Brown * this function will not need to be called and the resource management 1469d5ad34f7SMark Brown * code will ensure that the resource is freed. 1470d5ad34f7SMark Brown */ 1471d5ad34f7SMark Brown void devm_regulator_put(struct regulator *regulator) 1472d5ad34f7SMark Brown { 1473d5ad34f7SMark Brown int rc; 1474d5ad34f7SMark Brown 1475361ff501SMark Brown rc = devres_release(regulator->dev, devm_regulator_release, 1476d5ad34f7SMark Brown devm_regulator_match, regulator); 1477230a5a1cSMark Brown if (rc != 0) 1478d5ad34f7SMark Brown WARN_ON(rc); 1479d5ad34f7SMark Brown } 1480d5ad34f7SMark Brown EXPORT_SYMBOL_GPL(devm_regulator_put); 1481d5ad34f7SMark Brown 1482f19b00daSKim, Milo /* Manage enable GPIO list. Same GPIO pin can be shared among regulators */ 1483f19b00daSKim, Milo static int regulator_ena_gpio_request(struct regulator_dev *rdev, 1484f19b00daSKim, Milo const struct regulator_config *config) 1485f19b00daSKim, Milo { 1486f19b00daSKim, Milo struct regulator_enable_gpio *pin; 1487f19b00daSKim, Milo int ret; 1488f19b00daSKim, Milo 1489f19b00daSKim, Milo list_for_each_entry(pin, ®ulator_ena_gpio_list, list) { 1490f19b00daSKim, Milo if (pin->gpio == config->ena_gpio) { 1491f19b00daSKim, Milo rdev_dbg(rdev, "GPIO %d is already used\n", 1492f19b00daSKim, Milo config->ena_gpio); 1493f19b00daSKim, Milo goto update_ena_gpio_to_rdev; 1494f19b00daSKim, Milo } 1495f19b00daSKim, Milo } 1496f19b00daSKim, Milo 1497f19b00daSKim, Milo ret = gpio_request_one(config->ena_gpio, 1498f19b00daSKim, Milo GPIOF_DIR_OUT | config->ena_gpio_flags, 1499f19b00daSKim, Milo rdev_get_name(rdev)); 1500f19b00daSKim, Milo if (ret) 1501f19b00daSKim, Milo return ret; 1502f19b00daSKim, Milo 1503f19b00daSKim, Milo pin = kzalloc(sizeof(struct regulator_enable_gpio), GFP_KERNEL); 1504f19b00daSKim, Milo if (pin == NULL) { 1505f19b00daSKim, Milo gpio_free(config->ena_gpio); 1506f19b00daSKim, Milo return -ENOMEM; 1507f19b00daSKim, Milo } 1508f19b00daSKim, Milo 1509f19b00daSKim, Milo pin->gpio = config->ena_gpio; 1510f19b00daSKim, Milo pin->ena_gpio_invert = config->ena_gpio_invert; 1511f19b00daSKim, Milo list_add(&pin->list, ®ulator_ena_gpio_list); 1512f19b00daSKim, Milo 1513f19b00daSKim, Milo update_ena_gpio_to_rdev: 1514f19b00daSKim, Milo pin->request_count++; 1515f19b00daSKim, Milo rdev->ena_pin = pin; 1516f19b00daSKim, Milo return 0; 1517f19b00daSKim, Milo } 1518f19b00daSKim, Milo 1519f19b00daSKim, Milo static void regulator_ena_gpio_free(struct regulator_dev *rdev) 1520f19b00daSKim, Milo { 1521f19b00daSKim, Milo struct regulator_enable_gpio *pin, *n; 1522f19b00daSKim, Milo 1523f19b00daSKim, Milo if (!rdev->ena_pin) 1524f19b00daSKim, Milo return; 1525f19b00daSKim, Milo 1526f19b00daSKim, Milo /* Free the GPIO only in case of no use */ 1527f19b00daSKim, Milo list_for_each_entry_safe(pin, n, ®ulator_ena_gpio_list, list) { 1528f19b00daSKim, Milo if (pin->gpio == rdev->ena_pin->gpio) { 1529f19b00daSKim, Milo if (pin->request_count <= 1) { 1530f19b00daSKim, Milo pin->request_count = 0; 1531f19b00daSKim, Milo gpio_free(pin->gpio); 1532f19b00daSKim, Milo list_del(&pin->list); 1533f19b00daSKim, Milo kfree(pin); 1534f19b00daSKim, Milo } else { 1535f19b00daSKim, Milo pin->request_count--; 1536f19b00daSKim, Milo } 1537f19b00daSKim, Milo } 1538f19b00daSKim, Milo } 1539f19b00daSKim, Milo } 1540f19b00daSKim, Milo 1541967cfb18SKim, Milo /** 154231d6eebfSRobert P. J. Day * regulator_ena_gpio_ctrl - balance enable_count of each GPIO and actual GPIO pin control 154331d6eebfSRobert P. J. Day * @rdev: regulator_dev structure 154431d6eebfSRobert P. J. Day * @enable: enable GPIO at initial use? 154531d6eebfSRobert P. J. Day * 1546967cfb18SKim, Milo * GPIO is enabled in case of initial use. (enable_count is 0) 1547967cfb18SKim, Milo * GPIO is disabled when it is not shared any more. (enable_count <= 1) 1548967cfb18SKim, Milo */ 1549967cfb18SKim, Milo static int regulator_ena_gpio_ctrl(struct regulator_dev *rdev, bool enable) 1550967cfb18SKim, Milo { 1551967cfb18SKim, Milo struct regulator_enable_gpio *pin = rdev->ena_pin; 1552967cfb18SKim, Milo 1553967cfb18SKim, Milo if (!pin) 1554967cfb18SKim, Milo return -EINVAL; 1555967cfb18SKim, Milo 1556967cfb18SKim, Milo if (enable) { 1557967cfb18SKim, Milo /* Enable GPIO at initial use */ 1558967cfb18SKim, Milo if (pin->enable_count == 0) 1559967cfb18SKim, Milo gpio_set_value_cansleep(pin->gpio, 1560967cfb18SKim, Milo !pin->ena_gpio_invert); 1561967cfb18SKim, Milo 1562967cfb18SKim, Milo pin->enable_count++; 1563967cfb18SKim, Milo } else { 1564967cfb18SKim, Milo if (pin->enable_count > 1) { 1565967cfb18SKim, Milo pin->enable_count--; 1566967cfb18SKim, Milo return 0; 1567967cfb18SKim, Milo } 1568967cfb18SKim, Milo 1569967cfb18SKim, Milo /* Disable GPIO if not used */ 1570967cfb18SKim, Milo if (pin->enable_count <= 1) { 1571967cfb18SKim, Milo gpio_set_value_cansleep(pin->gpio, 1572967cfb18SKim, Milo pin->ena_gpio_invert); 1573967cfb18SKim, Milo pin->enable_count = 0; 1574967cfb18SKim, Milo } 1575967cfb18SKim, Milo } 1576967cfb18SKim, Milo 1577967cfb18SKim, Milo return 0; 1578967cfb18SKim, Milo } 1579967cfb18SKim, Milo 15805c5659d0SMark Brown static int _regulator_do_enable(struct regulator_dev *rdev) 15815c5659d0SMark Brown { 15825c5659d0SMark Brown int ret, delay; 15835c5659d0SMark Brown 15845c5659d0SMark Brown /* Query before enabling in case configuration dependent. */ 15855c5659d0SMark Brown ret = _regulator_get_enable_time(rdev); 15865c5659d0SMark Brown if (ret >= 0) { 15875c5659d0SMark Brown delay = ret; 15885c5659d0SMark Brown } else { 15895c5659d0SMark Brown rdev_warn(rdev, "enable_time() failed: %d\n", ret); 15905c5659d0SMark Brown delay = 0; 15915c5659d0SMark Brown } 15925c5659d0SMark Brown 15935c5659d0SMark Brown trace_regulator_enable(rdev_get_name(rdev)); 15945c5659d0SMark Brown 1595967cfb18SKim, Milo if (rdev->ena_pin) { 1596967cfb18SKim, Milo ret = regulator_ena_gpio_ctrl(rdev, true); 1597967cfb18SKim, Milo if (ret < 0) 1598967cfb18SKim, Milo return ret; 159965f73508SMark Brown rdev->ena_gpio_state = 1; 160065f73508SMark Brown } else if (rdev->desc->ops->enable) { 16015c5659d0SMark Brown ret = rdev->desc->ops->enable(rdev); 16025c5659d0SMark Brown if (ret < 0) 16035c5659d0SMark Brown return ret; 16045c5659d0SMark Brown } else { 16055c5659d0SMark Brown return -EINVAL; 16065c5659d0SMark Brown } 16075c5659d0SMark Brown 16085c5659d0SMark Brown /* Allow the regulator to ramp; it would be useful to extend 16095c5659d0SMark Brown * this for bulk operations so that the regulators can ramp 16105c5659d0SMark Brown * together. */ 16115c5659d0SMark Brown trace_regulator_enable_delay(rdev_get_name(rdev)); 16125c5659d0SMark Brown 16135c5659d0SMark Brown if (delay >= 1000) { 16145c5659d0SMark Brown mdelay(delay / 1000); 16155c5659d0SMark Brown udelay(delay % 1000); 16165c5659d0SMark Brown } else if (delay) { 16175c5659d0SMark Brown udelay(delay); 16185c5659d0SMark Brown } 16195c5659d0SMark Brown 16205c5659d0SMark Brown trace_regulator_enable_complete(rdev_get_name(rdev)); 16215c5659d0SMark Brown 16225c5659d0SMark Brown return 0; 16235c5659d0SMark Brown } 16245c5659d0SMark Brown 1625414c70cbSLiam Girdwood /* locks held by regulator_enable() */ 1626414c70cbSLiam Girdwood static int _regulator_enable(struct regulator_dev *rdev) 1627414c70cbSLiam Girdwood { 16285c5659d0SMark Brown int ret; 1629414c70cbSLiam Girdwood 1630414c70cbSLiam Girdwood /* check voltage and requested load before enabling */ 1631414c70cbSLiam Girdwood if (rdev->constraints && 16329a2372faSMark Brown (rdev->constraints->valid_ops_mask & REGULATOR_CHANGE_DRMS)) 1633414c70cbSLiam Girdwood drms_uA_update(rdev); 1634414c70cbSLiam Girdwood 16359a2372faSMark Brown if (rdev->use_count == 0) { 16369a2372faSMark Brown /* The regulator may on if it's not switchable or left on */ 16379a2372faSMark Brown ret = _regulator_is_enabled(rdev); 16389a2372faSMark Brown if (ret == -EINVAL || ret == 0) { 16399a2372faSMark Brown if (!_regulator_can_change_status(rdev)) 16409a2372faSMark Brown return -EPERM; 16419a2372faSMark Brown 16425c5659d0SMark Brown ret = _regulator_do_enable(rdev); 16439a2372faSMark Brown if (ret < 0) 16449a2372faSMark Brown return ret; 164531aae2beSMark Brown 1646a7433cffSLinus Walleij } else if (ret < 0) { 16475da84fd9SJoe Perches rdev_err(rdev, "is_enabled() failed: %d\n", ret); 1648414c70cbSLiam Girdwood return ret; 1649414c70cbSLiam Girdwood } 1650a7433cffSLinus Walleij /* Fallthrough on positive return values - already enabled */ 1651414c70cbSLiam Girdwood } 1652414c70cbSLiam Girdwood 16539a2372faSMark Brown rdev->use_count++; 16549a2372faSMark Brown 16559a2372faSMark Brown return 0; 1656414c70cbSLiam Girdwood } 1657414c70cbSLiam Girdwood 1658414c70cbSLiam Girdwood /** 1659414c70cbSLiam Girdwood * regulator_enable - enable regulator output 1660414c70cbSLiam Girdwood * @regulator: regulator source 1661414c70cbSLiam Girdwood * 1662cf7bbcdfSMark Brown * Request that the regulator be enabled with the regulator output at 1663cf7bbcdfSMark Brown * the predefined voltage or current value. Calls to regulator_enable() 1664cf7bbcdfSMark Brown * must be balanced with calls to regulator_disable(). 1665cf7bbcdfSMark Brown * 1666414c70cbSLiam Girdwood * NOTE: the output value can be set by other drivers, boot loader or may be 1667cf7bbcdfSMark Brown * hardwired in the regulator. 1668414c70cbSLiam Girdwood */ 1669414c70cbSLiam Girdwood int regulator_enable(struct regulator *regulator) 1670414c70cbSLiam Girdwood { 1671412aec61SDavid Brownell struct regulator_dev *rdev = regulator->rdev; 1672412aec61SDavid Brownell int ret = 0; 1673414c70cbSLiam Girdwood 16746492bc1bSMark Brown if (regulator->always_on) 16756492bc1bSMark Brown return 0; 16766492bc1bSMark Brown 16773801b86aSMark Brown if (rdev->supply) { 16783801b86aSMark Brown ret = regulator_enable(rdev->supply); 16793801b86aSMark Brown if (ret != 0) 16803801b86aSMark Brown return ret; 16813801b86aSMark Brown } 16823801b86aSMark Brown 1683412aec61SDavid Brownell mutex_lock(&rdev->mutex); 1684412aec61SDavid Brownell ret = _regulator_enable(rdev); 1685412aec61SDavid Brownell mutex_unlock(&rdev->mutex); 16863801b86aSMark Brown 1687d1685e4eSHeiko Stübner if (ret != 0 && rdev->supply) 16883801b86aSMark Brown regulator_disable(rdev->supply); 16893801b86aSMark Brown 1690414c70cbSLiam Girdwood return ret; 1691414c70cbSLiam Girdwood } 1692414c70cbSLiam Girdwood EXPORT_SYMBOL_GPL(regulator_enable); 1693414c70cbSLiam Girdwood 16945c5659d0SMark Brown static int _regulator_do_disable(struct regulator_dev *rdev) 16955c5659d0SMark Brown { 16965c5659d0SMark Brown int ret; 16975c5659d0SMark Brown 16985c5659d0SMark Brown trace_regulator_disable(rdev_get_name(rdev)); 16995c5659d0SMark Brown 1700967cfb18SKim, Milo if (rdev->ena_pin) { 1701967cfb18SKim, Milo ret = regulator_ena_gpio_ctrl(rdev, false); 1702967cfb18SKim, Milo if (ret < 0) 1703967cfb18SKim, Milo return ret; 17045c5659d0SMark Brown rdev->ena_gpio_state = 0; 17055c5659d0SMark Brown 17065c5659d0SMark Brown } else if (rdev->desc->ops->disable) { 17075c5659d0SMark Brown ret = rdev->desc->ops->disable(rdev); 17085c5659d0SMark Brown if (ret != 0) 17095c5659d0SMark Brown return ret; 17105c5659d0SMark Brown } 17115c5659d0SMark Brown 17125c5659d0SMark Brown trace_regulator_disable_complete(rdev_get_name(rdev)); 17135c5659d0SMark Brown 17145c5659d0SMark Brown _notifier_call_chain(rdev, REGULATOR_EVENT_DISABLE, 17155c5659d0SMark Brown NULL); 17165c5659d0SMark Brown return 0; 17175c5659d0SMark Brown } 17185c5659d0SMark Brown 1719414c70cbSLiam Girdwood /* locks held by regulator_disable() */ 17203801b86aSMark Brown static int _regulator_disable(struct regulator_dev *rdev) 1721414c70cbSLiam Girdwood { 1722414c70cbSLiam Girdwood int ret = 0; 1723414c70cbSLiam Girdwood 1724cd94b505SDavid Brownell if (WARN(rdev->use_count <= 0, 172543e7ee33SJoe Perches "unbalanced disables for %s\n", rdev_get_name(rdev))) 1726cd94b505SDavid Brownell return -EIO; 1727cd94b505SDavid Brownell 1728414c70cbSLiam Girdwood /* are we the last user and permitted to disable ? */ 172960ef66fcSMark Brown if (rdev->use_count == 1 && 173060ef66fcSMark Brown (rdev->constraints && !rdev->constraints->always_on)) { 1731414c70cbSLiam Girdwood 1732414c70cbSLiam Girdwood /* we are last user */ 17335c5659d0SMark Brown if (_regulator_can_change_status(rdev)) { 17345c5659d0SMark Brown ret = _regulator_do_disable(rdev); 1735414c70cbSLiam Girdwood if (ret < 0) { 17365da84fd9SJoe Perches rdev_err(rdev, "failed to disable\n"); 1737414c70cbSLiam Girdwood return ret; 1738414c70cbSLiam Girdwood } 1739414c70cbSLiam Girdwood } 1740414c70cbSLiam Girdwood 1741414c70cbSLiam Girdwood rdev->use_count = 0; 1742414c70cbSLiam Girdwood } else if (rdev->use_count > 1) { 1743414c70cbSLiam Girdwood 1744414c70cbSLiam Girdwood if (rdev->constraints && 1745414c70cbSLiam Girdwood (rdev->constraints->valid_ops_mask & 1746414c70cbSLiam Girdwood REGULATOR_CHANGE_DRMS)) 1747414c70cbSLiam Girdwood drms_uA_update(rdev); 1748414c70cbSLiam Girdwood 1749414c70cbSLiam Girdwood rdev->use_count--; 1750414c70cbSLiam Girdwood } 17513801b86aSMark Brown 1752414c70cbSLiam Girdwood return ret; 1753414c70cbSLiam Girdwood } 1754414c70cbSLiam Girdwood 1755414c70cbSLiam Girdwood /** 1756414c70cbSLiam Girdwood * regulator_disable - disable regulator output 1757414c70cbSLiam Girdwood * @regulator: regulator source 1758414c70cbSLiam Girdwood * 1759cf7bbcdfSMark Brown * Disable the regulator output voltage or current. Calls to 1760cf7bbcdfSMark Brown * regulator_enable() must be balanced with calls to 1761cf7bbcdfSMark Brown * regulator_disable(). 176269279fb9SMark Brown * 1763414c70cbSLiam Girdwood * NOTE: this will only disable the regulator output if no other consumer 1764cf7bbcdfSMark Brown * devices have it enabled, the regulator device supports disabling and 1765cf7bbcdfSMark Brown * machine constraints permit this operation. 1766414c70cbSLiam Girdwood */ 1767414c70cbSLiam Girdwood int regulator_disable(struct regulator *regulator) 1768414c70cbSLiam Girdwood { 1769412aec61SDavid Brownell struct regulator_dev *rdev = regulator->rdev; 1770412aec61SDavid Brownell int ret = 0; 1771414c70cbSLiam Girdwood 17726492bc1bSMark Brown if (regulator->always_on) 17736492bc1bSMark Brown return 0; 17746492bc1bSMark Brown 1775412aec61SDavid Brownell mutex_lock(&rdev->mutex); 17763801b86aSMark Brown ret = _regulator_disable(rdev); 1777412aec61SDavid Brownell mutex_unlock(&rdev->mutex); 17788cbf811dSJeffrey Carlyle 17793801b86aSMark Brown if (ret == 0 && rdev->supply) 17803801b86aSMark Brown regulator_disable(rdev->supply); 17818cbf811dSJeffrey Carlyle 1782414c70cbSLiam Girdwood return ret; 1783414c70cbSLiam Girdwood } 1784414c70cbSLiam Girdwood EXPORT_SYMBOL_GPL(regulator_disable); 1785414c70cbSLiam Girdwood 1786414c70cbSLiam Girdwood /* locks held by regulator_force_disable() */ 17873801b86aSMark Brown static int _regulator_force_disable(struct regulator_dev *rdev) 1788414c70cbSLiam Girdwood { 1789414c70cbSLiam Girdwood int ret = 0; 1790414c70cbSLiam Girdwood 1791414c70cbSLiam Girdwood /* force disable */ 1792414c70cbSLiam Girdwood if (rdev->desc->ops->disable) { 1793414c70cbSLiam Girdwood /* ah well, who wants to live forever... */ 1794414c70cbSLiam Girdwood ret = rdev->desc->ops->disable(rdev); 1795414c70cbSLiam Girdwood if (ret < 0) { 17965da84fd9SJoe Perches rdev_err(rdev, "failed to force disable\n"); 1797414c70cbSLiam Girdwood return ret; 1798414c70cbSLiam Girdwood } 1799414c70cbSLiam Girdwood /* notify other consumers that power has been forced off */ 180084b68263SMark Brown _notifier_call_chain(rdev, REGULATOR_EVENT_FORCE_DISABLE | 180184b68263SMark Brown REGULATOR_EVENT_DISABLE, NULL); 1802414c70cbSLiam Girdwood } 1803414c70cbSLiam Girdwood 1804414c70cbSLiam Girdwood return ret; 1805414c70cbSLiam Girdwood } 1806414c70cbSLiam Girdwood 1807414c70cbSLiam Girdwood /** 1808414c70cbSLiam Girdwood * regulator_force_disable - force disable regulator output 1809414c70cbSLiam Girdwood * @regulator: regulator source 1810414c70cbSLiam Girdwood * 1811414c70cbSLiam Girdwood * Forcibly disable the regulator output voltage or current. 1812414c70cbSLiam Girdwood * NOTE: this *will* disable the regulator output even if other consumer 1813414c70cbSLiam Girdwood * devices have it enabled. This should be used for situations when device 1814414c70cbSLiam Girdwood * damage will likely occur if the regulator is not disabled (e.g. over temp). 1815414c70cbSLiam Girdwood */ 1816414c70cbSLiam Girdwood int regulator_force_disable(struct regulator *regulator) 1817414c70cbSLiam Girdwood { 181882d15839SMark Brown struct regulator_dev *rdev = regulator->rdev; 1819414c70cbSLiam Girdwood int ret; 1820414c70cbSLiam Girdwood 182182d15839SMark Brown mutex_lock(&rdev->mutex); 1822414c70cbSLiam Girdwood regulator->uA_load = 0; 18233801b86aSMark Brown ret = _regulator_force_disable(regulator->rdev); 182482d15839SMark Brown mutex_unlock(&rdev->mutex); 18258cbf811dSJeffrey Carlyle 18263801b86aSMark Brown if (rdev->supply) 18273801b86aSMark Brown while (rdev->open_count--) 18283801b86aSMark Brown regulator_disable(rdev->supply); 18298cbf811dSJeffrey Carlyle 1830414c70cbSLiam Girdwood return ret; 1831414c70cbSLiam Girdwood } 1832414c70cbSLiam Girdwood EXPORT_SYMBOL_GPL(regulator_force_disable); 1833414c70cbSLiam Girdwood 1834da07ecd9SMark Brown static void regulator_disable_work(struct work_struct *work) 1835da07ecd9SMark Brown { 1836da07ecd9SMark Brown struct regulator_dev *rdev = container_of(work, struct regulator_dev, 1837da07ecd9SMark Brown disable_work.work); 1838da07ecd9SMark Brown int count, i, ret; 1839da07ecd9SMark Brown 1840da07ecd9SMark Brown mutex_lock(&rdev->mutex); 1841da07ecd9SMark Brown 1842da07ecd9SMark Brown BUG_ON(!rdev->deferred_disables); 1843da07ecd9SMark Brown 1844da07ecd9SMark Brown count = rdev->deferred_disables; 1845da07ecd9SMark Brown rdev->deferred_disables = 0; 1846da07ecd9SMark Brown 1847da07ecd9SMark Brown for (i = 0; i < count; i++) { 1848da07ecd9SMark Brown ret = _regulator_disable(rdev); 1849da07ecd9SMark Brown if (ret != 0) 1850da07ecd9SMark Brown rdev_err(rdev, "Deferred disable failed: %d\n", ret); 1851da07ecd9SMark Brown } 1852da07ecd9SMark Brown 1853da07ecd9SMark Brown mutex_unlock(&rdev->mutex); 1854da07ecd9SMark Brown 1855da07ecd9SMark Brown if (rdev->supply) { 1856da07ecd9SMark Brown for (i = 0; i < count; i++) { 1857da07ecd9SMark Brown ret = regulator_disable(rdev->supply); 1858da07ecd9SMark Brown if (ret != 0) { 1859da07ecd9SMark Brown rdev_err(rdev, 1860da07ecd9SMark Brown "Supply disable failed: %d\n", ret); 1861da07ecd9SMark Brown } 1862da07ecd9SMark Brown } 1863da07ecd9SMark Brown } 1864da07ecd9SMark Brown } 1865da07ecd9SMark Brown 1866da07ecd9SMark Brown /** 1867da07ecd9SMark Brown * regulator_disable_deferred - disable regulator output with delay 1868da07ecd9SMark Brown * @regulator: regulator source 1869da07ecd9SMark Brown * @ms: miliseconds until the regulator is disabled 1870da07ecd9SMark Brown * 1871da07ecd9SMark Brown * Execute regulator_disable() on the regulator after a delay. This 1872da07ecd9SMark Brown * is intended for use with devices that require some time to quiesce. 1873da07ecd9SMark Brown * 1874da07ecd9SMark Brown * NOTE: this will only disable the regulator output if no other consumer 1875da07ecd9SMark Brown * devices have it enabled, the regulator device supports disabling and 1876da07ecd9SMark Brown * machine constraints permit this operation. 1877da07ecd9SMark Brown */ 1878da07ecd9SMark Brown int regulator_disable_deferred(struct regulator *regulator, int ms) 1879da07ecd9SMark Brown { 1880da07ecd9SMark Brown struct regulator_dev *rdev = regulator->rdev; 1881aa59802dSMark Brown int ret; 1882da07ecd9SMark Brown 18836492bc1bSMark Brown if (regulator->always_on) 18846492bc1bSMark Brown return 0; 18856492bc1bSMark Brown 18862b5a24a0SMark Brown if (!ms) 18872b5a24a0SMark Brown return regulator_disable(regulator); 18882b5a24a0SMark Brown 1889da07ecd9SMark Brown mutex_lock(&rdev->mutex); 1890da07ecd9SMark Brown rdev->deferred_disables++; 1891da07ecd9SMark Brown mutex_unlock(&rdev->mutex); 1892da07ecd9SMark Brown 1893070260f0SMark Brown ret = queue_delayed_work(system_power_efficient_wq, 1894070260f0SMark Brown &rdev->disable_work, 1895da07ecd9SMark Brown msecs_to_jiffies(ms)); 1896aa59802dSMark Brown if (ret < 0) 1897aa59802dSMark Brown return ret; 1898aa59802dSMark Brown else 1899aa59802dSMark Brown return 0; 1900da07ecd9SMark Brown } 1901da07ecd9SMark Brown EXPORT_SYMBOL_GPL(regulator_disable_deferred); 1902da07ecd9SMark Brown 1903cd6dffb4SMark Brown /** 1904cd6dffb4SMark Brown * regulator_is_enabled_regmap - standard is_enabled() for regmap users 1905cd6dffb4SMark Brown * 1906cd6dffb4SMark Brown * @rdev: regulator to operate on 1907cd6dffb4SMark Brown * 1908cd6dffb4SMark Brown * Regulators that use regmap for their register I/O can set the 1909cd6dffb4SMark Brown * enable_reg and enable_mask fields in their descriptor and then use 1910cd6dffb4SMark Brown * this as their is_enabled operation, saving some code. 1911cd6dffb4SMark Brown */ 1912cd6dffb4SMark Brown int regulator_is_enabled_regmap(struct regulator_dev *rdev) 1913cd6dffb4SMark Brown { 1914cd6dffb4SMark Brown unsigned int val; 1915cd6dffb4SMark Brown int ret; 1916cd6dffb4SMark Brown 1917cd6dffb4SMark Brown ret = regmap_read(rdev->regmap, rdev->desc->enable_reg, &val); 1918cd6dffb4SMark Brown if (ret != 0) 1919cd6dffb4SMark Brown return ret; 1920cd6dffb4SMark Brown 192151dcdafcSAxel Lin if (rdev->desc->enable_is_inverted) 192251dcdafcSAxel Lin return (val & rdev->desc->enable_mask) == 0; 192351dcdafcSAxel Lin else 1924cd6dffb4SMark Brown return (val & rdev->desc->enable_mask) != 0; 1925cd6dffb4SMark Brown } 1926cd6dffb4SMark Brown EXPORT_SYMBOL_GPL(regulator_is_enabled_regmap); 1927cd6dffb4SMark Brown 1928cd6dffb4SMark Brown /** 1929cd6dffb4SMark Brown * regulator_enable_regmap - standard enable() for regmap users 1930cd6dffb4SMark Brown * 1931cd6dffb4SMark Brown * @rdev: regulator to operate on 1932cd6dffb4SMark Brown * 1933cd6dffb4SMark Brown * Regulators that use regmap for their register I/O can set the 1934cd6dffb4SMark Brown * enable_reg and enable_mask fields in their descriptor and then use 1935cd6dffb4SMark Brown * this as their enable() operation, saving some code. 1936cd6dffb4SMark Brown */ 1937cd6dffb4SMark Brown int regulator_enable_regmap(struct regulator_dev *rdev) 1938cd6dffb4SMark Brown { 193951dcdafcSAxel Lin unsigned int val; 194051dcdafcSAxel Lin 194151dcdafcSAxel Lin if (rdev->desc->enable_is_inverted) 194251dcdafcSAxel Lin val = 0; 194351dcdafcSAxel Lin else 194451dcdafcSAxel Lin val = rdev->desc->enable_mask; 194551dcdafcSAxel Lin 1946cd6dffb4SMark Brown return regmap_update_bits(rdev->regmap, rdev->desc->enable_reg, 194751dcdafcSAxel Lin rdev->desc->enable_mask, val); 1948cd6dffb4SMark Brown } 1949cd6dffb4SMark Brown EXPORT_SYMBOL_GPL(regulator_enable_regmap); 1950cd6dffb4SMark Brown 1951cd6dffb4SMark Brown /** 1952cd6dffb4SMark Brown * regulator_disable_regmap - standard disable() for regmap users 1953cd6dffb4SMark Brown * 1954cd6dffb4SMark Brown * @rdev: regulator to operate on 1955cd6dffb4SMark Brown * 1956cd6dffb4SMark Brown * Regulators that use regmap for their register I/O can set the 1957cd6dffb4SMark Brown * enable_reg and enable_mask fields in their descriptor and then use 1958cd6dffb4SMark Brown * this as their disable() operation, saving some code. 1959cd6dffb4SMark Brown */ 1960cd6dffb4SMark Brown int regulator_disable_regmap(struct regulator_dev *rdev) 1961cd6dffb4SMark Brown { 196251dcdafcSAxel Lin unsigned int val; 196351dcdafcSAxel Lin 196451dcdafcSAxel Lin if (rdev->desc->enable_is_inverted) 196551dcdafcSAxel Lin val = rdev->desc->enable_mask; 196651dcdafcSAxel Lin else 196751dcdafcSAxel Lin val = 0; 196851dcdafcSAxel Lin 1969cd6dffb4SMark Brown return regmap_update_bits(rdev->regmap, rdev->desc->enable_reg, 197051dcdafcSAxel Lin rdev->desc->enable_mask, val); 1971cd6dffb4SMark Brown } 1972cd6dffb4SMark Brown EXPORT_SYMBOL_GPL(regulator_disable_regmap); 1973cd6dffb4SMark Brown 1974414c70cbSLiam Girdwood static int _regulator_is_enabled(struct regulator_dev *rdev) 1975414c70cbSLiam Girdwood { 197665f73508SMark Brown /* A GPIO control always takes precedence */ 19777b74d149SKim, Milo if (rdev->ena_pin) 197865f73508SMark Brown return rdev->ena_gpio_state; 197965f73508SMark Brown 19809a7f6a4cSMark Brown /* If we don't know then assume that the regulator is always on */ 19819332546fSMark Brown if (!rdev->desc->ops->is_enabled) 19829a7f6a4cSMark Brown return 1; 1983414c70cbSLiam Girdwood 19849332546fSMark Brown return rdev->desc->ops->is_enabled(rdev); 1985414c70cbSLiam Girdwood } 1986414c70cbSLiam Girdwood 1987414c70cbSLiam Girdwood /** 1988414c70cbSLiam Girdwood * regulator_is_enabled - is the regulator output enabled 1989414c70cbSLiam Girdwood * @regulator: regulator source 1990414c70cbSLiam Girdwood * 1991412aec61SDavid Brownell * Returns positive if the regulator driver backing the source/client 1992412aec61SDavid Brownell * has requested that the device be enabled, zero if it hasn't, else a 1993412aec61SDavid Brownell * negative errno code. 1994412aec61SDavid Brownell * 1995412aec61SDavid Brownell * Note that the device backing this regulator handle can have multiple 1996412aec61SDavid Brownell * users, so it might be enabled even if regulator_enable() was never 1997412aec61SDavid Brownell * called for this particular source. 1998414c70cbSLiam Girdwood */ 1999414c70cbSLiam Girdwood int regulator_is_enabled(struct regulator *regulator) 2000414c70cbSLiam Girdwood { 20019332546fSMark Brown int ret; 20029332546fSMark Brown 20036492bc1bSMark Brown if (regulator->always_on) 20046492bc1bSMark Brown return 1; 20056492bc1bSMark Brown 20069332546fSMark Brown mutex_lock(®ulator->rdev->mutex); 20079332546fSMark Brown ret = _regulator_is_enabled(regulator->rdev); 20089332546fSMark Brown mutex_unlock(®ulator->rdev->mutex); 20099332546fSMark Brown 20109332546fSMark Brown return ret; 2011414c70cbSLiam Girdwood } 2012414c70cbSLiam Girdwood EXPORT_SYMBOL_GPL(regulator_is_enabled); 2013414c70cbSLiam Girdwood 2014414c70cbSLiam Girdwood /** 2015d1e7de30SMarek Szyprowski * regulator_can_change_voltage - check if regulator can change voltage 2016d1e7de30SMarek Szyprowski * @regulator: regulator source 2017d1e7de30SMarek Szyprowski * 2018d1e7de30SMarek Szyprowski * Returns positive if the regulator driver backing the source/client 2019d1e7de30SMarek Szyprowski * can change its voltage, false otherwise. Usefull for detecting fixed 2020d1e7de30SMarek Szyprowski * or dummy regulators and disabling voltage change logic in the client 2021d1e7de30SMarek Szyprowski * driver. 2022d1e7de30SMarek Szyprowski */ 2023d1e7de30SMarek Szyprowski int regulator_can_change_voltage(struct regulator *regulator) 2024d1e7de30SMarek Szyprowski { 2025d1e7de30SMarek Szyprowski struct regulator_dev *rdev = regulator->rdev; 2026d1e7de30SMarek Szyprowski 2027d1e7de30SMarek Szyprowski if (rdev->constraints && 202819280e40SAxel Lin (rdev->constraints->valid_ops_mask & REGULATOR_CHANGE_VOLTAGE)) { 202919280e40SAxel Lin if (rdev->desc->n_voltages - rdev->desc->linear_min_sel > 1) 2030d1e7de30SMarek Szyprowski return 1; 2031d1e7de30SMarek Szyprowski 203219280e40SAxel Lin if (rdev->desc->continuous_voltage_range && 203319280e40SAxel Lin rdev->constraints->min_uV && rdev->constraints->max_uV && 203419280e40SAxel Lin rdev->constraints->min_uV != rdev->constraints->max_uV) 203519280e40SAxel Lin return 1; 203619280e40SAxel Lin } 203719280e40SAxel Lin 2038d1e7de30SMarek Szyprowski return 0; 2039d1e7de30SMarek Szyprowski } 2040d1e7de30SMarek Szyprowski EXPORT_SYMBOL_GPL(regulator_can_change_voltage); 2041d1e7de30SMarek Szyprowski 2042d1e7de30SMarek Szyprowski /** 20434367cfdcSDavid Brownell * regulator_count_voltages - count regulator_list_voltage() selectors 20444367cfdcSDavid Brownell * @regulator: regulator source 20454367cfdcSDavid Brownell * 20464367cfdcSDavid Brownell * Returns number of selectors, or negative errno. Selectors are 20474367cfdcSDavid Brownell * numbered starting at zero, and typically correspond to bitfields 20484367cfdcSDavid Brownell * in hardware registers. 20494367cfdcSDavid Brownell */ 20504367cfdcSDavid Brownell int regulator_count_voltages(struct regulator *regulator) 20514367cfdcSDavid Brownell { 20524367cfdcSDavid Brownell struct regulator_dev *rdev = regulator->rdev; 20534367cfdcSDavid Brownell 20544367cfdcSDavid Brownell return rdev->desc->n_voltages ? : -EINVAL; 20554367cfdcSDavid Brownell } 20564367cfdcSDavid Brownell EXPORT_SYMBOL_GPL(regulator_count_voltages); 20574367cfdcSDavid Brownell 20584367cfdcSDavid Brownell /** 2059bca7bbffSMark Brown * regulator_list_voltage_linear - List voltages with simple calculation 2060bca7bbffSMark Brown * 2061bca7bbffSMark Brown * @rdev: Regulator device 2062bca7bbffSMark Brown * @selector: Selector to convert into a voltage 2063bca7bbffSMark Brown * 2064bca7bbffSMark Brown * Regulators with a simple linear mapping between voltages and 2065bca7bbffSMark Brown * selectors can set min_uV and uV_step in the regulator descriptor 2066bca7bbffSMark Brown * and then use this function as their list_voltage() operation, 2067bca7bbffSMark Brown */ 2068bca7bbffSMark Brown int regulator_list_voltage_linear(struct regulator_dev *rdev, 2069bca7bbffSMark Brown unsigned int selector) 2070bca7bbffSMark Brown { 2071bca7bbffSMark Brown if (selector >= rdev->desc->n_voltages) 2072bca7bbffSMark Brown return -EINVAL; 207333234e79SAxel Lin if (selector < rdev->desc->linear_min_sel) 207433234e79SAxel Lin return 0; 207533234e79SAxel Lin 207633234e79SAxel Lin selector -= rdev->desc->linear_min_sel; 2077bca7bbffSMark Brown 2078bca7bbffSMark Brown return rdev->desc->min_uV + (rdev->desc->uV_step * selector); 2079bca7bbffSMark Brown } 2080bca7bbffSMark Brown EXPORT_SYMBOL_GPL(regulator_list_voltage_linear); 2081bca7bbffSMark Brown 2082bca7bbffSMark Brown /** 2083cffc9592SAxel Lin * regulator_list_voltage_table - List voltages with table based mapping 2084cffc9592SAxel Lin * 2085cffc9592SAxel Lin * @rdev: Regulator device 2086cffc9592SAxel Lin * @selector: Selector to convert into a voltage 2087cffc9592SAxel Lin * 2088cffc9592SAxel Lin * Regulators with table based mapping between voltages and 2089cffc9592SAxel Lin * selectors can set volt_table in the regulator descriptor 2090cffc9592SAxel Lin * and then use this function as their list_voltage() operation. 2091cffc9592SAxel Lin */ 2092cffc9592SAxel Lin int regulator_list_voltage_table(struct regulator_dev *rdev, 2093cffc9592SAxel Lin unsigned int selector) 2094cffc9592SAxel Lin { 2095cffc9592SAxel Lin if (!rdev->desc->volt_table) { 2096cffc9592SAxel Lin BUG_ON(!rdev->desc->volt_table); 2097cffc9592SAxel Lin return -EINVAL; 2098cffc9592SAxel Lin } 2099cffc9592SAxel Lin 2100cffc9592SAxel Lin if (selector >= rdev->desc->n_voltages) 2101cffc9592SAxel Lin return -EINVAL; 2102cffc9592SAxel Lin 2103cffc9592SAxel Lin return rdev->desc->volt_table[selector]; 2104cffc9592SAxel Lin } 2105cffc9592SAxel Lin EXPORT_SYMBOL_GPL(regulator_list_voltage_table); 2106cffc9592SAxel Lin 2107cffc9592SAxel Lin /** 21084367cfdcSDavid Brownell * regulator_list_voltage - enumerate supported voltages 21094367cfdcSDavid Brownell * @regulator: regulator source 21104367cfdcSDavid Brownell * @selector: identify voltage to list 21114367cfdcSDavid Brownell * Context: can sleep 21124367cfdcSDavid Brownell * 21134367cfdcSDavid Brownell * Returns a voltage that can be passed to @regulator_set_voltage(), 211488393161SThomas Weber * zero if this selector code can't be used on this system, or a 21154367cfdcSDavid Brownell * negative errno. 21164367cfdcSDavid Brownell */ 21174367cfdcSDavid Brownell int regulator_list_voltage(struct regulator *regulator, unsigned selector) 21184367cfdcSDavid Brownell { 21194367cfdcSDavid Brownell struct regulator_dev *rdev = regulator->rdev; 21204367cfdcSDavid Brownell struct regulator_ops *ops = rdev->desc->ops; 21214367cfdcSDavid Brownell int ret; 21224367cfdcSDavid Brownell 21234367cfdcSDavid Brownell if (!ops->list_voltage || selector >= rdev->desc->n_voltages) 21244367cfdcSDavid Brownell return -EINVAL; 21254367cfdcSDavid Brownell 21264367cfdcSDavid Brownell mutex_lock(&rdev->mutex); 21274367cfdcSDavid Brownell ret = ops->list_voltage(rdev, selector); 21284367cfdcSDavid Brownell mutex_unlock(&rdev->mutex); 21294367cfdcSDavid Brownell 21304367cfdcSDavid Brownell if (ret > 0) { 21314367cfdcSDavid Brownell if (ret < rdev->constraints->min_uV) 21324367cfdcSDavid Brownell ret = 0; 21334367cfdcSDavid Brownell else if (ret > rdev->constraints->max_uV) 21344367cfdcSDavid Brownell ret = 0; 21354367cfdcSDavid Brownell } 21364367cfdcSDavid Brownell 21374367cfdcSDavid Brownell return ret; 21384367cfdcSDavid Brownell } 21394367cfdcSDavid Brownell EXPORT_SYMBOL_GPL(regulator_list_voltage); 21404367cfdcSDavid Brownell 21414367cfdcSDavid Brownell /** 21422a668a8bSPaul Walmsley * regulator_get_linear_step - return the voltage step size between VSEL values 21432a668a8bSPaul Walmsley * @regulator: regulator source 21442a668a8bSPaul Walmsley * 21452a668a8bSPaul Walmsley * Returns the voltage step size between VSEL values for linear 21462a668a8bSPaul Walmsley * regulators, or return 0 if the regulator isn't a linear regulator. 21472a668a8bSPaul Walmsley */ 21482a668a8bSPaul Walmsley unsigned int regulator_get_linear_step(struct regulator *regulator) 21492a668a8bSPaul Walmsley { 21502a668a8bSPaul Walmsley struct regulator_dev *rdev = regulator->rdev; 21512a668a8bSPaul Walmsley 21522a668a8bSPaul Walmsley return rdev->desc->uV_step; 21532a668a8bSPaul Walmsley } 21542a668a8bSPaul Walmsley EXPORT_SYMBOL_GPL(regulator_get_linear_step); 21552a668a8bSPaul Walmsley 21562a668a8bSPaul Walmsley /** 2157a7a1ad90SMark Brown * regulator_is_supported_voltage - check if a voltage range can be supported 2158a7a1ad90SMark Brown * 2159a7a1ad90SMark Brown * @regulator: Regulator to check. 2160a7a1ad90SMark Brown * @min_uV: Minimum required voltage in uV. 2161a7a1ad90SMark Brown * @max_uV: Maximum required voltage in uV. 2162a7a1ad90SMark Brown * 2163a7a1ad90SMark Brown * Returns a boolean or a negative error code. 2164a7a1ad90SMark Brown */ 2165a7a1ad90SMark Brown int regulator_is_supported_voltage(struct regulator *regulator, 2166a7a1ad90SMark Brown int min_uV, int max_uV) 2167a7a1ad90SMark Brown { 2168c5f3939bSMark Brown struct regulator_dev *rdev = regulator->rdev; 2169a7a1ad90SMark Brown int i, voltages, ret; 2170a7a1ad90SMark Brown 2171c5f3939bSMark Brown /* If we can't change voltage check the current voltage */ 2172c5f3939bSMark Brown if (!(rdev->constraints->valid_ops_mask & REGULATOR_CHANGE_VOLTAGE)) { 2173c5f3939bSMark Brown ret = regulator_get_voltage(regulator); 2174c5f3939bSMark Brown if (ret >= 0) 2175f0f98b19SMarek Szyprowski return (min_uV <= ret && ret <= max_uV); 2176c5f3939bSMark Brown else 2177c5f3939bSMark Brown return ret; 2178c5f3939bSMark Brown } 2179c5f3939bSMark Brown 2180bd7a2b60SPawel Moll /* Any voltage within constrains range is fine? */ 2181bd7a2b60SPawel Moll if (rdev->desc->continuous_voltage_range) 2182bd7a2b60SPawel Moll return min_uV >= rdev->constraints->min_uV && 2183bd7a2b60SPawel Moll max_uV <= rdev->constraints->max_uV; 2184bd7a2b60SPawel Moll 2185a7a1ad90SMark Brown ret = regulator_count_voltages(regulator); 2186a7a1ad90SMark Brown if (ret < 0) 2187a7a1ad90SMark Brown return ret; 2188a7a1ad90SMark Brown voltages = ret; 2189a7a1ad90SMark Brown 2190a7a1ad90SMark Brown for (i = 0; i < voltages; i++) { 2191a7a1ad90SMark Brown ret = regulator_list_voltage(regulator, i); 2192a7a1ad90SMark Brown 2193a7a1ad90SMark Brown if (ret >= min_uV && ret <= max_uV) 2194a7a1ad90SMark Brown return 1; 2195a7a1ad90SMark Brown } 2196a7a1ad90SMark Brown 2197a7a1ad90SMark Brown return 0; 2198a7a1ad90SMark Brown } 2199a398eaa2SMark Brown EXPORT_SYMBOL_GPL(regulator_is_supported_voltage); 2200a7a1ad90SMark Brown 22014ab5b3d9SMark Brown /** 22024ab5b3d9SMark Brown * regulator_get_voltage_sel_regmap - standard get_voltage_sel for regmap users 22034ab5b3d9SMark Brown * 22044ab5b3d9SMark Brown * @rdev: regulator to operate on 22054ab5b3d9SMark Brown * 22064ab5b3d9SMark Brown * Regulators that use regmap for their register I/O can set the 22074ab5b3d9SMark Brown * vsel_reg and vsel_mask fields in their descriptor and then use this 22084ab5b3d9SMark Brown * as their get_voltage_vsel operation, saving some code. 22094ab5b3d9SMark Brown */ 22104ab5b3d9SMark Brown int regulator_get_voltage_sel_regmap(struct regulator_dev *rdev) 22114ab5b3d9SMark Brown { 22124ab5b3d9SMark Brown unsigned int val; 22134ab5b3d9SMark Brown int ret; 22144ab5b3d9SMark Brown 22154ab5b3d9SMark Brown ret = regmap_read(rdev->regmap, rdev->desc->vsel_reg, &val); 22164ab5b3d9SMark Brown if (ret != 0) 22174ab5b3d9SMark Brown return ret; 22184ab5b3d9SMark Brown 22194ab5b3d9SMark Brown val &= rdev->desc->vsel_mask; 22204ab5b3d9SMark Brown val >>= ffs(rdev->desc->vsel_mask) - 1; 22214ab5b3d9SMark Brown 22224ab5b3d9SMark Brown return val; 22234ab5b3d9SMark Brown } 22244ab5b3d9SMark Brown EXPORT_SYMBOL_GPL(regulator_get_voltage_sel_regmap); 22254ab5b3d9SMark Brown 22264ab5b3d9SMark Brown /** 22274ab5b3d9SMark Brown * regulator_set_voltage_sel_regmap - standard set_voltage_sel for regmap users 22284ab5b3d9SMark Brown * 22294ab5b3d9SMark Brown * @rdev: regulator to operate on 22304ab5b3d9SMark Brown * @sel: Selector to set 22314ab5b3d9SMark Brown * 22324ab5b3d9SMark Brown * Regulators that use regmap for their register I/O can set the 22334ab5b3d9SMark Brown * vsel_reg and vsel_mask fields in their descriptor and then use this 22344ab5b3d9SMark Brown * as their set_voltage_vsel operation, saving some code. 22354ab5b3d9SMark Brown */ 22364ab5b3d9SMark Brown int regulator_set_voltage_sel_regmap(struct regulator_dev *rdev, unsigned sel) 22374ab5b3d9SMark Brown { 2238c8520b4cSAxel Lin int ret; 2239c8520b4cSAxel Lin 22404ab5b3d9SMark Brown sel <<= ffs(rdev->desc->vsel_mask) - 1; 22414ab5b3d9SMark Brown 2242c8520b4cSAxel Lin ret = regmap_update_bits(rdev->regmap, rdev->desc->vsel_reg, 22434ab5b3d9SMark Brown rdev->desc->vsel_mask, sel); 2244c8520b4cSAxel Lin if (ret) 2245c8520b4cSAxel Lin return ret; 2246c8520b4cSAxel Lin 2247c8520b4cSAxel Lin if (rdev->desc->apply_bit) 2248c8520b4cSAxel Lin ret = regmap_update_bits(rdev->regmap, rdev->desc->apply_reg, 2249c8520b4cSAxel Lin rdev->desc->apply_bit, 2250c8520b4cSAxel Lin rdev->desc->apply_bit); 2251c8520b4cSAxel Lin return ret; 22524ab5b3d9SMark Brown } 22534ab5b3d9SMark Brown EXPORT_SYMBOL_GPL(regulator_set_voltage_sel_regmap); 22544ab5b3d9SMark Brown 2255e843fc46SMark Brown /** 2256e843fc46SMark Brown * regulator_map_voltage_iterate - map_voltage() based on list_voltage() 2257e843fc46SMark Brown * 2258e843fc46SMark Brown * @rdev: Regulator to operate on 2259e843fc46SMark Brown * @min_uV: Lower bound for voltage 2260e843fc46SMark Brown * @max_uV: Upper bound for voltage 2261e843fc46SMark Brown * 2262e843fc46SMark Brown * Drivers implementing set_voltage_sel() and list_voltage() can use 2263e843fc46SMark Brown * this as their map_voltage() operation. It will find a suitable 2264e843fc46SMark Brown * voltage by calling list_voltage() until it gets something in bounds 2265e843fc46SMark Brown * for the requested voltages. 2266e843fc46SMark Brown */ 2267e843fc46SMark Brown int regulator_map_voltage_iterate(struct regulator_dev *rdev, 226875790251SMark Brown int min_uV, int max_uV) 226975790251SMark Brown { 2270e8eef82bSMark Brown int best_val = INT_MAX; 2271e843fc46SMark Brown int selector = 0; 2272e843fc46SMark Brown int i, ret; 2273e8eef82bSMark Brown 2274e8eef82bSMark Brown /* Find the smallest voltage that falls within the specified 2275e8eef82bSMark Brown * range. 2276e8eef82bSMark Brown */ 2277e8eef82bSMark Brown for (i = 0; i < rdev->desc->n_voltages; i++) { 2278e8eef82bSMark Brown ret = rdev->desc->ops->list_voltage(rdev, i); 2279e8eef82bSMark Brown if (ret < 0) 2280e8eef82bSMark Brown continue; 2281e8eef82bSMark Brown 2282e8eef82bSMark Brown if (ret < best_val && ret >= min_uV && ret <= max_uV) { 2283e8eef82bSMark Brown best_val = ret; 2284e8eef82bSMark Brown selector = i; 2285e8eef82bSMark Brown } 2286e8eef82bSMark Brown } 2287e8eef82bSMark Brown 2288e843fc46SMark Brown if (best_val != INT_MAX) 2289e843fc46SMark Brown return selector; 2290e843fc46SMark Brown else 2291e843fc46SMark Brown return -EINVAL; 2292e843fc46SMark Brown } 2293e843fc46SMark Brown EXPORT_SYMBOL_GPL(regulator_map_voltage_iterate); 2294e843fc46SMark Brown 2295bca7bbffSMark Brown /** 2296fcf371eeSAxel Lin * regulator_map_voltage_ascend - map_voltage() for ascendant voltage list 2297fcf371eeSAxel Lin * 2298fcf371eeSAxel Lin * @rdev: Regulator to operate on 2299fcf371eeSAxel Lin * @min_uV: Lower bound for voltage 2300fcf371eeSAxel Lin * @max_uV: Upper bound for voltage 2301fcf371eeSAxel Lin * 2302fcf371eeSAxel Lin * Drivers that have ascendant voltage list can use this as their 2303fcf371eeSAxel Lin * map_voltage() operation. 2304fcf371eeSAxel Lin */ 2305fcf371eeSAxel Lin int regulator_map_voltage_ascend(struct regulator_dev *rdev, 2306fcf371eeSAxel Lin int min_uV, int max_uV) 2307fcf371eeSAxel Lin { 2308fcf371eeSAxel Lin int i, ret; 2309fcf371eeSAxel Lin 2310fcf371eeSAxel Lin for (i = 0; i < rdev->desc->n_voltages; i++) { 2311fcf371eeSAxel Lin ret = rdev->desc->ops->list_voltage(rdev, i); 2312fcf371eeSAxel Lin if (ret < 0) 2313fcf371eeSAxel Lin continue; 2314fcf371eeSAxel Lin 2315fcf371eeSAxel Lin if (ret > max_uV) 2316fcf371eeSAxel Lin break; 2317fcf371eeSAxel Lin 2318fcf371eeSAxel Lin if (ret >= min_uV && ret <= max_uV) 2319fcf371eeSAxel Lin return i; 2320fcf371eeSAxel Lin } 2321fcf371eeSAxel Lin 2322fcf371eeSAxel Lin return -EINVAL; 2323fcf371eeSAxel Lin } 2324fcf371eeSAxel Lin EXPORT_SYMBOL_GPL(regulator_map_voltage_ascend); 2325fcf371eeSAxel Lin 2326fcf371eeSAxel Lin /** 2327bca7bbffSMark Brown * regulator_map_voltage_linear - map_voltage() for simple linear mappings 2328bca7bbffSMark Brown * 2329bca7bbffSMark Brown * @rdev: Regulator to operate on 2330bca7bbffSMark Brown * @min_uV: Lower bound for voltage 2331bca7bbffSMark Brown * @max_uV: Upper bound for voltage 2332bca7bbffSMark Brown * 2333bca7bbffSMark Brown * Drivers providing min_uV and uV_step in their regulator_desc can 2334bca7bbffSMark Brown * use this as their map_voltage() operation. 2335bca7bbffSMark Brown */ 2336bca7bbffSMark Brown int regulator_map_voltage_linear(struct regulator_dev *rdev, 2337bca7bbffSMark Brown int min_uV, int max_uV) 2338bca7bbffSMark Brown { 2339bca7bbffSMark Brown int ret, voltage; 2340bca7bbffSMark Brown 23415a6881e8SAxel Lin /* Allow uV_step to be 0 for fixed voltage */ 23425a6881e8SAxel Lin if (rdev->desc->n_voltages == 1 && rdev->desc->uV_step == 0) { 23435a6881e8SAxel Lin if (min_uV <= rdev->desc->min_uV && rdev->desc->min_uV <= max_uV) 23445a6881e8SAxel Lin return 0; 23455a6881e8SAxel Lin else 23465a6881e8SAxel Lin return -EINVAL; 23475a6881e8SAxel Lin } 23485a6881e8SAxel Lin 2349bca7bbffSMark Brown if (!rdev->desc->uV_step) { 2350bca7bbffSMark Brown BUG_ON(!rdev->desc->uV_step); 2351bca7bbffSMark Brown return -EINVAL; 2352bca7bbffSMark Brown } 2353bca7bbffSMark Brown 23540bdc81e4SAxel Lin if (min_uV < rdev->desc->min_uV) 23550bdc81e4SAxel Lin min_uV = rdev->desc->min_uV; 23560bdc81e4SAxel Lin 2357ccfcb1c3SAxel Lin ret = DIV_ROUND_UP(min_uV - rdev->desc->min_uV, rdev->desc->uV_step); 2358bca7bbffSMark Brown if (ret < 0) 2359bca7bbffSMark Brown return ret; 2360bca7bbffSMark Brown 236133234e79SAxel Lin ret += rdev->desc->linear_min_sel; 236233234e79SAxel Lin 2363bca7bbffSMark Brown /* Map back into a voltage to verify we're still in bounds */ 2364bca7bbffSMark Brown voltage = rdev->desc->ops->list_voltage(rdev, ret); 2365bca7bbffSMark Brown if (voltage < min_uV || voltage > max_uV) 2366bca7bbffSMark Brown return -EINVAL; 2367bca7bbffSMark Brown 2368bca7bbffSMark Brown return ret; 2369bca7bbffSMark Brown } 2370bca7bbffSMark Brown EXPORT_SYMBOL_GPL(regulator_map_voltage_linear); 2371bca7bbffSMark Brown 2372a7a1ad90SMark Brown static int _regulator_do_set_voltage(struct regulator_dev *rdev, 2373a7a1ad90SMark Brown int min_uV, int max_uV) 2374a7a1ad90SMark Brown { 2375a7a1ad90SMark Brown int ret; 237675790251SMark Brown int delay = 0; 2377e113d792SMark Brown int best_val = 0; 237875790251SMark Brown unsigned int selector; 2379eba41a5eSAxel Lin int old_selector = -1; 238075790251SMark Brown 238175790251SMark Brown trace_regulator_set_voltage(rdev_get_name(rdev), min_uV, max_uV); 238275790251SMark Brown 238375790251SMark Brown min_uV += rdev->constraints->uV_offset; 238475790251SMark Brown max_uV += rdev->constraints->uV_offset; 238575790251SMark Brown 238677af1b26SLinus Walleij /* 238777af1b26SLinus Walleij * If we can't obtain the old selector there is not enough 238877af1b26SLinus Walleij * info to call set_voltage_time_sel(). 238977af1b26SLinus Walleij */ 23908b7485efSAxel Lin if (_regulator_is_enabled(rdev) && 23918b7485efSAxel Lin rdev->desc->ops->set_voltage_time_sel && 239277af1b26SLinus Walleij rdev->desc->ops->get_voltage_sel) { 2393eba41a5eSAxel Lin old_selector = rdev->desc->ops->get_voltage_sel(rdev); 2394eba41a5eSAxel Lin if (old_selector < 0) 2395eba41a5eSAxel Lin return old_selector; 2396eba41a5eSAxel Lin } 239777af1b26SLinus Walleij 239875790251SMark Brown if (rdev->desc->ops->set_voltage) { 239975790251SMark Brown ret = rdev->desc->ops->set_voltage(rdev, min_uV, max_uV, 240075790251SMark Brown &selector); 2401e113d792SMark Brown 2402e113d792SMark Brown if (ret >= 0) { 2403e113d792SMark Brown if (rdev->desc->ops->list_voltage) 2404e113d792SMark Brown best_val = rdev->desc->ops->list_voltage(rdev, 2405e113d792SMark Brown selector); 2406e113d792SMark Brown else 2407e113d792SMark Brown best_val = _regulator_get_voltage(rdev); 2408e113d792SMark Brown } 2409e113d792SMark Brown 2410e8eef82bSMark Brown } else if (rdev->desc->ops->set_voltage_sel) { 24119152c36aSAxel Lin if (rdev->desc->ops->map_voltage) { 2412e843fc46SMark Brown ret = rdev->desc->ops->map_voltage(rdev, min_uV, 2413e843fc46SMark Brown max_uV); 24149152c36aSAxel Lin } else { 24159152c36aSAxel Lin if (rdev->desc->ops->list_voltage == 24169152c36aSAxel Lin regulator_list_voltage_linear) 24179152c36aSAxel Lin ret = regulator_map_voltage_linear(rdev, 24189152c36aSAxel Lin min_uV, max_uV); 241907351233SAxel Lin else 24209152c36aSAxel Lin ret = regulator_map_voltage_iterate(rdev, 24219152c36aSAxel Lin min_uV, max_uV); 24229152c36aSAxel Lin } 2423e843fc46SMark Brown 2424e843fc46SMark Brown if (ret >= 0) { 2425e113d792SMark Brown best_val = rdev->desc->ops->list_voltage(rdev, ret); 2426e113d792SMark Brown if (min_uV <= best_val && max_uV >= best_val) { 2427e843fc46SMark Brown selector = ret; 2428c66a566aSAxel Lin if (old_selector == selector) 2429c66a566aSAxel Lin ret = 0; 2430c66a566aSAxel Lin else 2431c66a566aSAxel Lin ret = rdev->desc->ops->set_voltage_sel( 2432c66a566aSAxel Lin rdev, ret); 2433e113d792SMark Brown } else { 2434e113d792SMark Brown ret = -EINVAL; 2435e113d792SMark Brown } 2436e843fc46SMark Brown } 2437e8eef82bSMark Brown } else { 2438e8eef82bSMark Brown ret = -EINVAL; 2439e8eef82bSMark Brown } 2440e8eef82bSMark Brown 2441eba41a5eSAxel Lin /* Call set_voltage_time_sel if successfully obtained old_selector */ 24425aff3a8bSMark Brown if (ret == 0 && _regulator_is_enabled(rdev) && old_selector >= 0 && 2443c66a566aSAxel Lin old_selector != selector && rdev->desc->ops->set_voltage_time_sel) { 2444eba41a5eSAxel Lin 2445eba41a5eSAxel Lin delay = rdev->desc->ops->set_voltage_time_sel(rdev, 2446eba41a5eSAxel Lin old_selector, selector); 2447eba41a5eSAxel Lin if (delay < 0) { 2448eba41a5eSAxel Lin rdev_warn(rdev, "set_voltage_time_sel() failed: %d\n", 2449eba41a5eSAxel Lin delay); 2450eba41a5eSAxel Lin delay = 0; 2451e8eef82bSMark Brown } 245275790251SMark Brown 245377af1b26SLinus Walleij /* Insert any necessary delays */ 245477af1b26SLinus Walleij if (delay >= 1000) { 245577af1b26SLinus Walleij mdelay(delay / 1000); 245677af1b26SLinus Walleij udelay(delay % 1000); 245777af1b26SLinus Walleij } else if (delay) { 245877af1b26SLinus Walleij udelay(delay); 245977af1b26SLinus Walleij } 24608b96de31SPhilip Rakity } 246177af1b26SLinus Walleij 24622f6c797fSAxel Lin if (ret == 0 && best_val >= 0) { 24632f6c797fSAxel Lin unsigned long data = best_val; 24642f6c797fSAxel Lin 2465ded06a52SMark Brown _notifier_call_chain(rdev, REGULATOR_EVENT_VOLTAGE_CHANGE, 24662f6c797fSAxel Lin (void *)data); 24672f6c797fSAxel Lin } 2468ded06a52SMark Brown 2469eba41a5eSAxel Lin trace_regulator_set_voltage_complete(rdev_get_name(rdev), best_val); 247075790251SMark Brown 247175790251SMark Brown return ret; 247275790251SMark Brown } 247375790251SMark Brown 2474a7a1ad90SMark Brown /** 2475414c70cbSLiam Girdwood * regulator_set_voltage - set regulator output voltage 2476414c70cbSLiam Girdwood * @regulator: regulator source 2477414c70cbSLiam Girdwood * @min_uV: Minimum required voltage in uV 2478414c70cbSLiam Girdwood * @max_uV: Maximum acceptable voltage in uV 2479414c70cbSLiam Girdwood * 2480414c70cbSLiam Girdwood * Sets a voltage regulator to the desired output voltage. This can be set 2481414c70cbSLiam Girdwood * during any regulator state. IOW, regulator can be disabled or enabled. 2482414c70cbSLiam Girdwood * 2483414c70cbSLiam Girdwood * If the regulator is enabled then the voltage will change to the new value 2484414c70cbSLiam Girdwood * immediately otherwise if the regulator is disabled the regulator will 2485414c70cbSLiam Girdwood * output at the new voltage when enabled. 2486414c70cbSLiam Girdwood * 2487414c70cbSLiam Girdwood * NOTE: If the regulator is shared between several devices then the lowest 2488414c70cbSLiam Girdwood * request voltage that meets the system constraints will be used. 248969279fb9SMark Brown * Regulator system constraints must be set for this regulator before 2490414c70cbSLiam Girdwood * calling this function otherwise this call will fail. 2491414c70cbSLiam Girdwood */ 2492414c70cbSLiam Girdwood int regulator_set_voltage(struct regulator *regulator, int min_uV, int max_uV) 2493414c70cbSLiam Girdwood { 2494414c70cbSLiam Girdwood struct regulator_dev *rdev = regulator->rdev; 249595a3c23aSMark Brown int ret = 0; 249692d7a558SPaolo Pisati int old_min_uV, old_max_uV; 2497414c70cbSLiam Girdwood 2498414c70cbSLiam Girdwood mutex_lock(&rdev->mutex); 2499414c70cbSLiam Girdwood 250095a3c23aSMark Brown /* If we're setting the same range as last time the change 250195a3c23aSMark Brown * should be a noop (some cpufreq implementations use the same 250295a3c23aSMark Brown * voltage for multiple frequencies, for example). 250395a3c23aSMark Brown */ 250495a3c23aSMark Brown if (regulator->min_uV == min_uV && regulator->max_uV == max_uV) 250595a3c23aSMark Brown goto out; 250695a3c23aSMark Brown 2507414c70cbSLiam Girdwood /* sanity check */ 2508e8eef82bSMark Brown if (!rdev->desc->ops->set_voltage && 2509e8eef82bSMark Brown !rdev->desc->ops->set_voltage_sel) { 2510414c70cbSLiam Girdwood ret = -EINVAL; 2511414c70cbSLiam Girdwood goto out; 2512414c70cbSLiam Girdwood } 2513414c70cbSLiam Girdwood 2514414c70cbSLiam Girdwood /* constraints check */ 2515414c70cbSLiam Girdwood ret = regulator_check_voltage(rdev, &min_uV, &max_uV); 2516414c70cbSLiam Girdwood if (ret < 0) 2517414c70cbSLiam Girdwood goto out; 251892d7a558SPaolo Pisati 251992d7a558SPaolo Pisati /* restore original values in case of error */ 252092d7a558SPaolo Pisati old_min_uV = regulator->min_uV; 252192d7a558SPaolo Pisati old_max_uV = regulator->max_uV; 2522414c70cbSLiam Girdwood regulator->min_uV = min_uV; 2523414c70cbSLiam Girdwood regulator->max_uV = max_uV; 25243a93f2a9SMark Brown 252505fda3b1SThomas Petazzoni ret = regulator_check_consumers(rdev, &min_uV, &max_uV); 252605fda3b1SThomas Petazzoni if (ret < 0) 252792d7a558SPaolo Pisati goto out2; 252805fda3b1SThomas Petazzoni 252975790251SMark Brown ret = _regulator_do_set_voltage(rdev, min_uV, max_uV); 253092d7a558SPaolo Pisati if (ret < 0) 253192d7a558SPaolo Pisati goto out2; 253202fa3ec0SMark Brown 2533414c70cbSLiam Girdwood out: 2534414c70cbSLiam Girdwood mutex_unlock(&rdev->mutex); 2535414c70cbSLiam Girdwood return ret; 253692d7a558SPaolo Pisati out2: 253792d7a558SPaolo Pisati regulator->min_uV = old_min_uV; 253892d7a558SPaolo Pisati regulator->max_uV = old_max_uV; 253992d7a558SPaolo Pisati mutex_unlock(&rdev->mutex); 254092d7a558SPaolo Pisati return ret; 2541414c70cbSLiam Girdwood } 2542414c70cbSLiam Girdwood EXPORT_SYMBOL_GPL(regulator_set_voltage); 2543414c70cbSLiam Girdwood 2544606a2562SMark Brown /** 254588cd222bSLinus Walleij * regulator_set_voltage_time - get raise/fall time 254688cd222bSLinus Walleij * @regulator: regulator source 254788cd222bSLinus Walleij * @old_uV: starting voltage in microvolts 254888cd222bSLinus Walleij * @new_uV: target voltage in microvolts 254988cd222bSLinus Walleij * 255088cd222bSLinus Walleij * Provided with the starting and ending voltage, this function attempts to 255188cd222bSLinus Walleij * calculate the time in microseconds required to rise or fall to this new 255288cd222bSLinus Walleij * voltage. 255388cd222bSLinus Walleij */ 255488cd222bSLinus Walleij int regulator_set_voltage_time(struct regulator *regulator, 255588cd222bSLinus Walleij int old_uV, int new_uV) 255688cd222bSLinus Walleij { 255788cd222bSLinus Walleij struct regulator_dev *rdev = regulator->rdev; 255888cd222bSLinus Walleij struct regulator_ops *ops = rdev->desc->ops; 255988cd222bSLinus Walleij int old_sel = -1; 256088cd222bSLinus Walleij int new_sel = -1; 256188cd222bSLinus Walleij int voltage; 256288cd222bSLinus Walleij int i; 256388cd222bSLinus Walleij 256488cd222bSLinus Walleij /* Currently requires operations to do this */ 256588cd222bSLinus Walleij if (!ops->list_voltage || !ops->set_voltage_time_sel 256688cd222bSLinus Walleij || !rdev->desc->n_voltages) 256788cd222bSLinus Walleij return -EINVAL; 256888cd222bSLinus Walleij 256988cd222bSLinus Walleij for (i = 0; i < rdev->desc->n_voltages; i++) { 257088cd222bSLinus Walleij /* We only look for exact voltage matches here */ 257188cd222bSLinus Walleij voltage = regulator_list_voltage(regulator, i); 257288cd222bSLinus Walleij if (voltage < 0) 257388cd222bSLinus Walleij return -EINVAL; 257488cd222bSLinus Walleij if (voltage == 0) 257588cd222bSLinus Walleij continue; 257688cd222bSLinus Walleij if (voltage == old_uV) 257788cd222bSLinus Walleij old_sel = i; 257888cd222bSLinus Walleij if (voltage == new_uV) 257988cd222bSLinus Walleij new_sel = i; 258088cd222bSLinus Walleij } 258188cd222bSLinus Walleij 258288cd222bSLinus Walleij if (old_sel < 0 || new_sel < 0) 258388cd222bSLinus Walleij return -EINVAL; 258488cd222bSLinus Walleij 258588cd222bSLinus Walleij return ops->set_voltage_time_sel(rdev, old_sel, new_sel); 258688cd222bSLinus Walleij } 258788cd222bSLinus Walleij EXPORT_SYMBOL_GPL(regulator_set_voltage_time); 258888cd222bSLinus Walleij 258988cd222bSLinus Walleij /** 259098a175b6SYadwinder Singh Brar * regulator_set_voltage_time_sel - get raise/fall time 2591296c6566SRandy Dunlap * @rdev: regulator source device 259298a175b6SYadwinder Singh Brar * @old_selector: selector for starting voltage 259398a175b6SYadwinder Singh Brar * @new_selector: selector for target voltage 259498a175b6SYadwinder Singh Brar * 259598a175b6SYadwinder Singh Brar * Provided with the starting and target voltage selectors, this function 259698a175b6SYadwinder Singh Brar * returns time in microseconds required to rise or fall to this new voltage 259798a175b6SYadwinder Singh Brar * 2598f11d08c3SAxel Lin * Drivers providing ramp_delay in regulation_constraints can use this as their 2599398715abSAxel Lin * set_voltage_time_sel() operation. 260098a175b6SYadwinder Singh Brar */ 260198a175b6SYadwinder Singh Brar int regulator_set_voltage_time_sel(struct regulator_dev *rdev, 260298a175b6SYadwinder Singh Brar unsigned int old_selector, 260398a175b6SYadwinder Singh Brar unsigned int new_selector) 260498a175b6SYadwinder Singh Brar { 2605398715abSAxel Lin unsigned int ramp_delay = 0; 2606f11d08c3SAxel Lin int old_volt, new_volt; 2607398715abSAxel Lin 26086f0b2c69SYadwinder Singh Brar if (rdev->constraints->ramp_delay) 2609398715abSAxel Lin ramp_delay = rdev->constraints->ramp_delay; 2610398715abSAxel Lin else if (rdev->desc->ramp_delay) 2611398715abSAxel Lin ramp_delay = rdev->desc->ramp_delay; 2612398715abSAxel Lin 2613398715abSAxel Lin if (ramp_delay == 0) { 26146f0b2c69SYadwinder Singh Brar rdev_warn(rdev, "ramp_delay not set\n"); 2615398715abSAxel Lin return 0; 26166f0b2c69SYadwinder Singh Brar } 2617398715abSAxel Lin 2618f11d08c3SAxel Lin /* sanity check */ 2619f11d08c3SAxel Lin if (!rdev->desc->ops->list_voltage) 2620f11d08c3SAxel Lin return -EINVAL; 2621398715abSAxel Lin 2622f11d08c3SAxel Lin old_volt = rdev->desc->ops->list_voltage(rdev, old_selector); 2623f11d08c3SAxel Lin new_volt = rdev->desc->ops->list_voltage(rdev, new_selector); 2624f11d08c3SAxel Lin 2625f11d08c3SAxel Lin return DIV_ROUND_UP(abs(new_volt - old_volt), ramp_delay); 262698a175b6SYadwinder Singh Brar } 2627b19dbf71SMark Brown EXPORT_SYMBOL_GPL(regulator_set_voltage_time_sel); 262898a175b6SYadwinder Singh Brar 262998a175b6SYadwinder Singh Brar /** 2630606a2562SMark Brown * regulator_sync_voltage - re-apply last regulator output voltage 2631606a2562SMark Brown * @regulator: regulator source 2632606a2562SMark Brown * 2633606a2562SMark Brown * Re-apply the last configured voltage. This is intended to be used 2634606a2562SMark Brown * where some external control source the consumer is cooperating with 2635606a2562SMark Brown * has caused the configured voltage to change. 2636606a2562SMark Brown */ 2637606a2562SMark Brown int regulator_sync_voltage(struct regulator *regulator) 2638606a2562SMark Brown { 2639606a2562SMark Brown struct regulator_dev *rdev = regulator->rdev; 2640606a2562SMark Brown int ret, min_uV, max_uV; 2641606a2562SMark Brown 2642606a2562SMark Brown mutex_lock(&rdev->mutex); 2643606a2562SMark Brown 2644606a2562SMark Brown if (!rdev->desc->ops->set_voltage && 2645606a2562SMark Brown !rdev->desc->ops->set_voltage_sel) { 2646606a2562SMark Brown ret = -EINVAL; 2647606a2562SMark Brown goto out; 2648606a2562SMark Brown } 2649606a2562SMark Brown 2650606a2562SMark Brown /* This is only going to work if we've had a voltage configured. */ 2651606a2562SMark Brown if (!regulator->min_uV && !regulator->max_uV) { 2652606a2562SMark Brown ret = -EINVAL; 2653606a2562SMark Brown goto out; 2654606a2562SMark Brown } 2655606a2562SMark Brown 2656606a2562SMark Brown min_uV = regulator->min_uV; 2657606a2562SMark Brown max_uV = regulator->max_uV; 2658606a2562SMark Brown 2659606a2562SMark Brown /* This should be a paranoia check... */ 2660606a2562SMark Brown ret = regulator_check_voltage(rdev, &min_uV, &max_uV); 2661606a2562SMark Brown if (ret < 0) 2662606a2562SMark Brown goto out; 2663606a2562SMark Brown 2664606a2562SMark Brown ret = regulator_check_consumers(rdev, &min_uV, &max_uV); 2665606a2562SMark Brown if (ret < 0) 2666606a2562SMark Brown goto out; 2667606a2562SMark Brown 2668606a2562SMark Brown ret = _regulator_do_set_voltage(rdev, min_uV, max_uV); 2669606a2562SMark Brown 2670606a2562SMark Brown out: 2671606a2562SMark Brown mutex_unlock(&rdev->mutex); 2672606a2562SMark Brown return ret; 2673606a2562SMark Brown } 2674606a2562SMark Brown EXPORT_SYMBOL_GPL(regulator_sync_voltage); 2675606a2562SMark Brown 2676414c70cbSLiam Girdwood static int _regulator_get_voltage(struct regulator_dev *rdev) 2677414c70cbSLiam Girdwood { 2678bf5892a8SMark Brown int sel, ret; 2679476c2d83SMark Brown 2680476c2d83SMark Brown if (rdev->desc->ops->get_voltage_sel) { 2681476c2d83SMark Brown sel = rdev->desc->ops->get_voltage_sel(rdev); 2682476c2d83SMark Brown if (sel < 0) 2683476c2d83SMark Brown return sel; 2684bf5892a8SMark Brown ret = rdev->desc->ops->list_voltage(rdev, sel); 2685cb220d16SAxel Lin } else if (rdev->desc->ops->get_voltage) { 2686bf5892a8SMark Brown ret = rdev->desc->ops->get_voltage(rdev); 2687f7df20ecSMark Brown } else if (rdev->desc->ops->list_voltage) { 2688f7df20ecSMark Brown ret = rdev->desc->ops->list_voltage(rdev, 0); 2689cb220d16SAxel Lin } else { 2690414c70cbSLiam Girdwood return -EINVAL; 2691cb220d16SAxel Lin } 2692bf5892a8SMark Brown 2693cb220d16SAxel Lin if (ret < 0) 2694cb220d16SAxel Lin return ret; 2695bf5892a8SMark Brown return ret - rdev->constraints->uV_offset; 2696414c70cbSLiam Girdwood } 2697414c70cbSLiam Girdwood 2698414c70cbSLiam Girdwood /** 2699414c70cbSLiam Girdwood * regulator_get_voltage - get regulator output voltage 2700414c70cbSLiam Girdwood * @regulator: regulator source 2701414c70cbSLiam Girdwood * 2702414c70cbSLiam Girdwood * This returns the current regulator voltage in uV. 2703414c70cbSLiam Girdwood * 2704414c70cbSLiam Girdwood * NOTE: If the regulator is disabled it will return the voltage value. This 2705414c70cbSLiam Girdwood * function should not be used to determine regulator state. 2706414c70cbSLiam Girdwood */ 2707414c70cbSLiam Girdwood int regulator_get_voltage(struct regulator *regulator) 2708414c70cbSLiam Girdwood { 2709414c70cbSLiam Girdwood int ret; 2710414c70cbSLiam Girdwood 2711414c70cbSLiam Girdwood mutex_lock(®ulator->rdev->mutex); 2712414c70cbSLiam Girdwood 2713414c70cbSLiam Girdwood ret = _regulator_get_voltage(regulator->rdev); 2714414c70cbSLiam Girdwood 2715414c70cbSLiam Girdwood mutex_unlock(®ulator->rdev->mutex); 2716414c70cbSLiam Girdwood 2717414c70cbSLiam Girdwood return ret; 2718414c70cbSLiam Girdwood } 2719414c70cbSLiam Girdwood EXPORT_SYMBOL_GPL(regulator_get_voltage); 2720414c70cbSLiam Girdwood 2721414c70cbSLiam Girdwood /** 2722414c70cbSLiam Girdwood * regulator_set_current_limit - set regulator output current limit 2723414c70cbSLiam Girdwood * @regulator: regulator source 2724ce0d10f8SCharles Keepax * @min_uA: Minimum supported current in uA 2725414c70cbSLiam Girdwood * @max_uA: Maximum supported current in uA 2726414c70cbSLiam Girdwood * 2727414c70cbSLiam Girdwood * Sets current sink to the desired output current. This can be set during 2728414c70cbSLiam Girdwood * any regulator state. IOW, regulator can be disabled or enabled. 2729414c70cbSLiam Girdwood * 2730414c70cbSLiam Girdwood * If the regulator is enabled then the current will change to the new value 2731414c70cbSLiam Girdwood * immediately otherwise if the regulator is disabled the regulator will 2732414c70cbSLiam Girdwood * output at the new current when enabled. 2733414c70cbSLiam Girdwood * 2734414c70cbSLiam Girdwood * NOTE: Regulator system constraints must be set for this regulator before 2735414c70cbSLiam Girdwood * calling this function otherwise this call will fail. 2736414c70cbSLiam Girdwood */ 2737414c70cbSLiam Girdwood int regulator_set_current_limit(struct regulator *regulator, 2738414c70cbSLiam Girdwood int min_uA, int max_uA) 2739414c70cbSLiam Girdwood { 2740414c70cbSLiam Girdwood struct regulator_dev *rdev = regulator->rdev; 2741414c70cbSLiam Girdwood int ret; 2742414c70cbSLiam Girdwood 2743414c70cbSLiam Girdwood mutex_lock(&rdev->mutex); 2744414c70cbSLiam Girdwood 2745414c70cbSLiam Girdwood /* sanity check */ 2746414c70cbSLiam Girdwood if (!rdev->desc->ops->set_current_limit) { 2747414c70cbSLiam Girdwood ret = -EINVAL; 2748414c70cbSLiam Girdwood goto out; 2749414c70cbSLiam Girdwood } 2750414c70cbSLiam Girdwood 2751414c70cbSLiam Girdwood /* constraints check */ 2752414c70cbSLiam Girdwood ret = regulator_check_current_limit(rdev, &min_uA, &max_uA); 2753414c70cbSLiam Girdwood if (ret < 0) 2754414c70cbSLiam Girdwood goto out; 2755414c70cbSLiam Girdwood 2756414c70cbSLiam Girdwood ret = rdev->desc->ops->set_current_limit(rdev, min_uA, max_uA); 2757414c70cbSLiam Girdwood out: 2758414c70cbSLiam Girdwood mutex_unlock(&rdev->mutex); 2759414c70cbSLiam Girdwood return ret; 2760414c70cbSLiam Girdwood } 2761414c70cbSLiam Girdwood EXPORT_SYMBOL_GPL(regulator_set_current_limit); 2762414c70cbSLiam Girdwood 2763414c70cbSLiam Girdwood static int _regulator_get_current_limit(struct regulator_dev *rdev) 2764414c70cbSLiam Girdwood { 2765414c70cbSLiam Girdwood int ret; 2766414c70cbSLiam Girdwood 2767414c70cbSLiam Girdwood mutex_lock(&rdev->mutex); 2768414c70cbSLiam Girdwood 2769414c70cbSLiam Girdwood /* sanity check */ 2770414c70cbSLiam Girdwood if (!rdev->desc->ops->get_current_limit) { 2771414c70cbSLiam Girdwood ret = -EINVAL; 2772414c70cbSLiam Girdwood goto out; 2773414c70cbSLiam Girdwood } 2774414c70cbSLiam Girdwood 2775414c70cbSLiam Girdwood ret = rdev->desc->ops->get_current_limit(rdev); 2776414c70cbSLiam Girdwood out: 2777414c70cbSLiam Girdwood mutex_unlock(&rdev->mutex); 2778414c70cbSLiam Girdwood return ret; 2779414c70cbSLiam Girdwood } 2780414c70cbSLiam Girdwood 2781414c70cbSLiam Girdwood /** 2782414c70cbSLiam Girdwood * regulator_get_current_limit - get regulator output current 2783414c70cbSLiam Girdwood * @regulator: regulator source 2784414c70cbSLiam Girdwood * 2785414c70cbSLiam Girdwood * This returns the current supplied by the specified current sink in uA. 2786414c70cbSLiam Girdwood * 2787414c70cbSLiam Girdwood * NOTE: If the regulator is disabled it will return the current value. This 2788414c70cbSLiam Girdwood * function should not be used to determine regulator state. 2789414c70cbSLiam Girdwood */ 2790414c70cbSLiam Girdwood int regulator_get_current_limit(struct regulator *regulator) 2791414c70cbSLiam Girdwood { 2792414c70cbSLiam Girdwood return _regulator_get_current_limit(regulator->rdev); 2793414c70cbSLiam Girdwood } 2794414c70cbSLiam Girdwood EXPORT_SYMBOL_GPL(regulator_get_current_limit); 2795414c70cbSLiam Girdwood 2796414c70cbSLiam Girdwood /** 2797414c70cbSLiam Girdwood * regulator_set_mode - set regulator operating mode 2798414c70cbSLiam Girdwood * @regulator: regulator source 2799414c70cbSLiam Girdwood * @mode: operating mode - one of the REGULATOR_MODE constants 2800414c70cbSLiam Girdwood * 2801414c70cbSLiam Girdwood * Set regulator operating mode to increase regulator efficiency or improve 2802414c70cbSLiam Girdwood * regulation performance. 2803414c70cbSLiam Girdwood * 2804414c70cbSLiam Girdwood * NOTE: Regulator system constraints must be set for this regulator before 2805414c70cbSLiam Girdwood * calling this function otherwise this call will fail. 2806414c70cbSLiam Girdwood */ 2807414c70cbSLiam Girdwood int regulator_set_mode(struct regulator *regulator, unsigned int mode) 2808414c70cbSLiam Girdwood { 2809414c70cbSLiam Girdwood struct regulator_dev *rdev = regulator->rdev; 2810414c70cbSLiam Girdwood int ret; 2811500b4ac9SSundar R Iyer int regulator_curr_mode; 2812414c70cbSLiam Girdwood 2813414c70cbSLiam Girdwood mutex_lock(&rdev->mutex); 2814414c70cbSLiam Girdwood 2815414c70cbSLiam Girdwood /* sanity check */ 2816414c70cbSLiam Girdwood if (!rdev->desc->ops->set_mode) { 2817414c70cbSLiam Girdwood ret = -EINVAL; 2818414c70cbSLiam Girdwood goto out; 2819414c70cbSLiam Girdwood } 2820414c70cbSLiam Girdwood 2821500b4ac9SSundar R Iyer /* return if the same mode is requested */ 2822500b4ac9SSundar R Iyer if (rdev->desc->ops->get_mode) { 2823500b4ac9SSundar R Iyer regulator_curr_mode = rdev->desc->ops->get_mode(rdev); 2824500b4ac9SSundar R Iyer if (regulator_curr_mode == mode) { 2825500b4ac9SSundar R Iyer ret = 0; 2826500b4ac9SSundar R Iyer goto out; 2827500b4ac9SSundar R Iyer } 2828500b4ac9SSundar R Iyer } 2829500b4ac9SSundar R Iyer 2830414c70cbSLiam Girdwood /* constraints check */ 283122c51b47SAxel Lin ret = regulator_mode_constrain(rdev, &mode); 2832414c70cbSLiam Girdwood if (ret < 0) 2833414c70cbSLiam Girdwood goto out; 2834414c70cbSLiam Girdwood 2835414c70cbSLiam Girdwood ret = rdev->desc->ops->set_mode(rdev, mode); 2836414c70cbSLiam Girdwood out: 2837414c70cbSLiam Girdwood mutex_unlock(&rdev->mutex); 2838414c70cbSLiam Girdwood return ret; 2839414c70cbSLiam Girdwood } 2840414c70cbSLiam Girdwood EXPORT_SYMBOL_GPL(regulator_set_mode); 2841414c70cbSLiam Girdwood 2842414c70cbSLiam Girdwood static unsigned int _regulator_get_mode(struct regulator_dev *rdev) 2843414c70cbSLiam Girdwood { 2844414c70cbSLiam Girdwood int ret; 2845414c70cbSLiam Girdwood 2846414c70cbSLiam Girdwood mutex_lock(&rdev->mutex); 2847414c70cbSLiam Girdwood 2848414c70cbSLiam Girdwood /* sanity check */ 2849414c70cbSLiam Girdwood if (!rdev->desc->ops->get_mode) { 2850414c70cbSLiam Girdwood ret = -EINVAL; 2851414c70cbSLiam Girdwood goto out; 2852414c70cbSLiam Girdwood } 2853414c70cbSLiam Girdwood 2854414c70cbSLiam Girdwood ret = rdev->desc->ops->get_mode(rdev); 2855414c70cbSLiam Girdwood out: 2856414c70cbSLiam Girdwood mutex_unlock(&rdev->mutex); 2857414c70cbSLiam Girdwood return ret; 2858414c70cbSLiam Girdwood } 2859414c70cbSLiam Girdwood 2860414c70cbSLiam Girdwood /** 2861414c70cbSLiam Girdwood * regulator_get_mode - get regulator operating mode 2862414c70cbSLiam Girdwood * @regulator: regulator source 2863414c70cbSLiam Girdwood * 2864414c70cbSLiam Girdwood * Get the current regulator operating mode. 2865414c70cbSLiam Girdwood */ 2866414c70cbSLiam Girdwood unsigned int regulator_get_mode(struct regulator *regulator) 2867414c70cbSLiam Girdwood { 2868414c70cbSLiam Girdwood return _regulator_get_mode(regulator->rdev); 2869414c70cbSLiam Girdwood } 2870414c70cbSLiam Girdwood EXPORT_SYMBOL_GPL(regulator_get_mode); 2871414c70cbSLiam Girdwood 2872414c70cbSLiam Girdwood /** 2873414c70cbSLiam Girdwood * regulator_set_optimum_mode - set regulator optimum operating mode 2874414c70cbSLiam Girdwood * @regulator: regulator source 2875414c70cbSLiam Girdwood * @uA_load: load current 2876414c70cbSLiam Girdwood * 2877414c70cbSLiam Girdwood * Notifies the regulator core of a new device load. This is then used by 2878414c70cbSLiam Girdwood * DRMS (if enabled by constraints) to set the most efficient regulator 2879414c70cbSLiam Girdwood * operating mode for the new regulator loading. 2880414c70cbSLiam Girdwood * 2881414c70cbSLiam Girdwood * Consumer devices notify their supply regulator of the maximum power 2882414c70cbSLiam Girdwood * they will require (can be taken from device datasheet in the power 2883414c70cbSLiam Girdwood * consumption tables) when they change operational status and hence power 2884414c70cbSLiam Girdwood * state. Examples of operational state changes that can affect power 2885414c70cbSLiam Girdwood * consumption are :- 2886414c70cbSLiam Girdwood * 2887414c70cbSLiam Girdwood * o Device is opened / closed. 2888414c70cbSLiam Girdwood * o Device I/O is about to begin or has just finished. 2889414c70cbSLiam Girdwood * o Device is idling in between work. 2890414c70cbSLiam Girdwood * 2891414c70cbSLiam Girdwood * This information is also exported via sysfs to userspace. 2892414c70cbSLiam Girdwood * 2893414c70cbSLiam Girdwood * DRMS will sum the total requested load on the regulator and change 2894414c70cbSLiam Girdwood * to the most efficient operating mode if platform constraints allow. 2895414c70cbSLiam Girdwood * 2896414c70cbSLiam Girdwood * Returns the new regulator mode or error. 2897414c70cbSLiam Girdwood */ 2898414c70cbSLiam Girdwood int regulator_set_optimum_mode(struct regulator *regulator, int uA_load) 2899414c70cbSLiam Girdwood { 2900414c70cbSLiam Girdwood struct regulator_dev *rdev = regulator->rdev; 2901414c70cbSLiam Girdwood struct regulator *consumer; 2902d92d95b6SStephen Boyd int ret, output_uV, input_uV = 0, total_uA_load = 0; 2903414c70cbSLiam Girdwood unsigned int mode; 2904414c70cbSLiam Girdwood 2905d92d95b6SStephen Boyd if (rdev->supply) 2906d92d95b6SStephen Boyd input_uV = regulator_get_voltage(rdev->supply); 2907d92d95b6SStephen Boyd 2908414c70cbSLiam Girdwood mutex_lock(&rdev->mutex); 2909414c70cbSLiam Girdwood 2910a4b41483SMark Brown /* 2911a4b41483SMark Brown * first check to see if we can set modes at all, otherwise just 2912a4b41483SMark Brown * tell the consumer everything is OK. 2913a4b41483SMark Brown */ 2914414c70cbSLiam Girdwood regulator->uA_load = uA_load; 2915414c70cbSLiam Girdwood ret = regulator_check_drms(rdev); 2916a4b41483SMark Brown if (ret < 0) { 2917a4b41483SMark Brown ret = 0; 2918414c70cbSLiam Girdwood goto out; 2919a4b41483SMark Brown } 2920414c70cbSLiam Girdwood 2921414c70cbSLiam Girdwood if (!rdev->desc->ops->get_optimum_mode) 2922414c70cbSLiam Girdwood goto out; 2923414c70cbSLiam Girdwood 2924a4b41483SMark Brown /* 2925a4b41483SMark Brown * we can actually do this so any errors are indicators of 2926a4b41483SMark Brown * potential real failure. 2927a4b41483SMark Brown */ 2928a4b41483SMark Brown ret = -EINVAL; 2929a4b41483SMark Brown 2930854ccbaeSAxel Lin if (!rdev->desc->ops->set_mode) 2931854ccbaeSAxel Lin goto out; 2932854ccbaeSAxel Lin 2933414c70cbSLiam Girdwood /* get output voltage */ 29341bf5a1f8SMark Brown output_uV = _regulator_get_voltage(rdev); 2935414c70cbSLiam Girdwood if (output_uV <= 0) { 29365da84fd9SJoe Perches rdev_err(rdev, "invalid output voltage found\n"); 2937414c70cbSLiam Girdwood goto out; 2938414c70cbSLiam Girdwood } 2939414c70cbSLiam Girdwood 2940d92d95b6SStephen Boyd /* No supply? Use constraint voltage */ 29411bf5a1f8SMark Brown if (input_uV <= 0) 2942414c70cbSLiam Girdwood input_uV = rdev->constraints->input_uV; 2943414c70cbSLiam Girdwood if (input_uV <= 0) { 29445da84fd9SJoe Perches rdev_err(rdev, "invalid input voltage found\n"); 2945414c70cbSLiam Girdwood goto out; 2946414c70cbSLiam Girdwood } 2947414c70cbSLiam Girdwood 2948414c70cbSLiam Girdwood /* calc total requested load for this regulator */ 2949414c70cbSLiam Girdwood list_for_each_entry(consumer, &rdev->consumer_list, list) 2950414c70cbSLiam Girdwood total_uA_load += consumer->uA_load; 2951414c70cbSLiam Girdwood 2952414c70cbSLiam Girdwood mode = rdev->desc->ops->get_optimum_mode(rdev, 2953414c70cbSLiam Girdwood input_uV, output_uV, 2954414c70cbSLiam Girdwood total_uA_load); 29552c608234SMark Brown ret = regulator_mode_constrain(rdev, &mode); 2956e573520bSDavid Brownell if (ret < 0) { 29575da84fd9SJoe Perches rdev_err(rdev, "failed to get optimum mode @ %d uA %d -> %d uV\n", 2958414c70cbSLiam Girdwood total_uA_load, input_uV, output_uV); 2959414c70cbSLiam Girdwood goto out; 2960414c70cbSLiam Girdwood } 2961414c70cbSLiam Girdwood 2962414c70cbSLiam Girdwood ret = rdev->desc->ops->set_mode(rdev, mode); 2963e573520bSDavid Brownell if (ret < 0) { 29645da84fd9SJoe Perches rdev_err(rdev, "failed to set optimum mode %x\n", mode); 2965414c70cbSLiam Girdwood goto out; 2966414c70cbSLiam Girdwood } 2967414c70cbSLiam Girdwood ret = mode; 2968414c70cbSLiam Girdwood out: 2969414c70cbSLiam Girdwood mutex_unlock(&rdev->mutex); 2970414c70cbSLiam Girdwood return ret; 2971414c70cbSLiam Girdwood } 2972414c70cbSLiam Girdwood EXPORT_SYMBOL_GPL(regulator_set_optimum_mode); 2973414c70cbSLiam Girdwood 2974414c70cbSLiam Girdwood /** 2975df367931SMark Brown * regulator_set_bypass_regmap - Default set_bypass() using regmap 2976df367931SMark Brown * 2977df367931SMark Brown * @rdev: device to operate on. 2978df367931SMark Brown * @enable: state to set. 2979df367931SMark Brown */ 2980df367931SMark Brown int regulator_set_bypass_regmap(struct regulator_dev *rdev, bool enable) 2981df367931SMark Brown { 2982df367931SMark Brown unsigned int val; 2983df367931SMark Brown 2984df367931SMark Brown if (enable) 2985df367931SMark Brown val = rdev->desc->bypass_mask; 2986df367931SMark Brown else 2987df367931SMark Brown val = 0; 2988df367931SMark Brown 2989df367931SMark Brown return regmap_update_bits(rdev->regmap, rdev->desc->bypass_reg, 2990df367931SMark Brown rdev->desc->bypass_mask, val); 2991df367931SMark Brown } 2992df367931SMark Brown EXPORT_SYMBOL_GPL(regulator_set_bypass_regmap); 2993df367931SMark Brown 2994df367931SMark Brown /** 2995df367931SMark Brown * regulator_get_bypass_regmap - Default get_bypass() using regmap 2996df367931SMark Brown * 2997df367931SMark Brown * @rdev: device to operate on. 2998df367931SMark Brown * @enable: current state. 2999df367931SMark Brown */ 3000df367931SMark Brown int regulator_get_bypass_regmap(struct regulator_dev *rdev, bool *enable) 3001df367931SMark Brown { 3002df367931SMark Brown unsigned int val; 3003df367931SMark Brown int ret; 3004df367931SMark Brown 3005df367931SMark Brown ret = regmap_read(rdev->regmap, rdev->desc->bypass_reg, &val); 3006df367931SMark Brown if (ret != 0) 3007df367931SMark Brown return ret; 3008df367931SMark Brown 3009df367931SMark Brown *enable = val & rdev->desc->bypass_mask; 3010df367931SMark Brown 3011df367931SMark Brown return 0; 3012df367931SMark Brown } 3013df367931SMark Brown EXPORT_SYMBOL_GPL(regulator_get_bypass_regmap); 3014df367931SMark Brown 3015df367931SMark Brown /** 3016f59c8f9fSMark Brown * regulator_allow_bypass - allow the regulator to go into bypass mode 3017f59c8f9fSMark Brown * 3018f59c8f9fSMark Brown * @regulator: Regulator to configure 30199345dfb8SNishanth Menon * @enable: enable or disable bypass mode 3020f59c8f9fSMark Brown * 3021f59c8f9fSMark Brown * Allow the regulator to go into bypass mode if all other consumers 3022f59c8f9fSMark Brown * for the regulator also enable bypass mode and the machine 3023f59c8f9fSMark Brown * constraints allow this. Bypass mode means that the regulator is 3024f59c8f9fSMark Brown * simply passing the input directly to the output with no regulation. 3025f59c8f9fSMark Brown */ 3026f59c8f9fSMark Brown int regulator_allow_bypass(struct regulator *regulator, bool enable) 3027f59c8f9fSMark Brown { 3028f59c8f9fSMark Brown struct regulator_dev *rdev = regulator->rdev; 3029f59c8f9fSMark Brown int ret = 0; 3030f59c8f9fSMark Brown 3031f59c8f9fSMark Brown if (!rdev->desc->ops->set_bypass) 3032f59c8f9fSMark Brown return 0; 3033f59c8f9fSMark Brown 3034f59c8f9fSMark Brown if (rdev->constraints && 3035f59c8f9fSMark Brown !(rdev->constraints->valid_ops_mask & REGULATOR_CHANGE_BYPASS)) 3036f59c8f9fSMark Brown return 0; 3037f59c8f9fSMark Brown 3038f59c8f9fSMark Brown mutex_lock(&rdev->mutex); 3039f59c8f9fSMark Brown 3040f59c8f9fSMark Brown if (enable && !regulator->bypass) { 3041f59c8f9fSMark Brown rdev->bypass_count++; 3042f59c8f9fSMark Brown 3043f59c8f9fSMark Brown if (rdev->bypass_count == rdev->open_count) { 3044f59c8f9fSMark Brown ret = rdev->desc->ops->set_bypass(rdev, enable); 3045f59c8f9fSMark Brown if (ret != 0) 3046f59c8f9fSMark Brown rdev->bypass_count--; 3047f59c8f9fSMark Brown } 3048f59c8f9fSMark Brown 3049f59c8f9fSMark Brown } else if (!enable && regulator->bypass) { 3050f59c8f9fSMark Brown rdev->bypass_count--; 3051f59c8f9fSMark Brown 3052f59c8f9fSMark Brown if (rdev->bypass_count != rdev->open_count) { 3053f59c8f9fSMark Brown ret = rdev->desc->ops->set_bypass(rdev, enable); 3054f59c8f9fSMark Brown if (ret != 0) 3055f59c8f9fSMark Brown rdev->bypass_count++; 3056f59c8f9fSMark Brown } 3057f59c8f9fSMark Brown } 3058f59c8f9fSMark Brown 3059f59c8f9fSMark Brown if (ret == 0) 3060f59c8f9fSMark Brown regulator->bypass = enable; 3061f59c8f9fSMark Brown 3062f59c8f9fSMark Brown mutex_unlock(&rdev->mutex); 3063f59c8f9fSMark Brown 3064f59c8f9fSMark Brown return ret; 3065f59c8f9fSMark Brown } 3066f59c8f9fSMark Brown EXPORT_SYMBOL_GPL(regulator_allow_bypass); 3067f59c8f9fSMark Brown 3068f59c8f9fSMark Brown /** 3069414c70cbSLiam Girdwood * regulator_register_notifier - register regulator event notifier 3070414c70cbSLiam Girdwood * @regulator: regulator source 307169279fb9SMark Brown * @nb: notifier block 3072414c70cbSLiam Girdwood * 3073414c70cbSLiam Girdwood * Register notifier block to receive regulator events. 3074414c70cbSLiam Girdwood */ 3075414c70cbSLiam Girdwood int regulator_register_notifier(struct regulator *regulator, 3076414c70cbSLiam Girdwood struct notifier_block *nb) 3077414c70cbSLiam Girdwood { 3078414c70cbSLiam Girdwood return blocking_notifier_chain_register(®ulator->rdev->notifier, 3079414c70cbSLiam Girdwood nb); 3080414c70cbSLiam Girdwood } 3081414c70cbSLiam Girdwood EXPORT_SYMBOL_GPL(regulator_register_notifier); 3082414c70cbSLiam Girdwood 3083414c70cbSLiam Girdwood /** 3084414c70cbSLiam Girdwood * regulator_unregister_notifier - unregister regulator event notifier 3085414c70cbSLiam Girdwood * @regulator: regulator source 308669279fb9SMark Brown * @nb: notifier block 3087414c70cbSLiam Girdwood * 3088414c70cbSLiam Girdwood * Unregister regulator event notifier block. 3089414c70cbSLiam Girdwood */ 3090414c70cbSLiam Girdwood int regulator_unregister_notifier(struct regulator *regulator, 3091414c70cbSLiam Girdwood struct notifier_block *nb) 3092414c70cbSLiam Girdwood { 3093414c70cbSLiam Girdwood return blocking_notifier_chain_unregister(®ulator->rdev->notifier, 3094414c70cbSLiam Girdwood nb); 3095414c70cbSLiam Girdwood } 3096414c70cbSLiam Girdwood EXPORT_SYMBOL_GPL(regulator_unregister_notifier); 3097414c70cbSLiam Girdwood 3098b136fb44SJonathan Cameron /* notify regulator consumers and downstream regulator consumers. 3099b136fb44SJonathan Cameron * Note mutex must be held by caller. 3100b136fb44SJonathan Cameron */ 3101414c70cbSLiam Girdwood static void _notifier_call_chain(struct regulator_dev *rdev, 3102414c70cbSLiam Girdwood unsigned long event, void *data) 3103414c70cbSLiam Girdwood { 3104414c70cbSLiam Girdwood /* call rdev chain first */ 3105d8493d21SMark Brown blocking_notifier_call_chain(&rdev->notifier, event, data); 3106414c70cbSLiam Girdwood } 3107414c70cbSLiam Girdwood 3108414c70cbSLiam Girdwood /** 3109414c70cbSLiam Girdwood * regulator_bulk_get - get multiple regulator consumers 3110414c70cbSLiam Girdwood * 3111414c70cbSLiam Girdwood * @dev: Device to supply 3112414c70cbSLiam Girdwood * @num_consumers: Number of consumers to register 3113414c70cbSLiam Girdwood * @consumers: Configuration of consumers; clients are stored here. 3114414c70cbSLiam Girdwood * 3115414c70cbSLiam Girdwood * @return 0 on success, an errno on failure. 3116414c70cbSLiam Girdwood * 3117414c70cbSLiam Girdwood * This helper function allows drivers to get several regulator 3118414c70cbSLiam Girdwood * consumers in one operation. If any of the regulators cannot be 3119414c70cbSLiam Girdwood * acquired then any regulators that were allocated will be freed 3120414c70cbSLiam Girdwood * before returning to the caller. 3121414c70cbSLiam Girdwood */ 3122414c70cbSLiam Girdwood int regulator_bulk_get(struct device *dev, int num_consumers, 3123414c70cbSLiam Girdwood struct regulator_bulk_data *consumers) 3124414c70cbSLiam Girdwood { 3125414c70cbSLiam Girdwood int i; 3126414c70cbSLiam Girdwood int ret; 3127414c70cbSLiam Girdwood 3128414c70cbSLiam Girdwood for (i = 0; i < num_consumers; i++) 3129414c70cbSLiam Girdwood consumers[i].consumer = NULL; 3130414c70cbSLiam Girdwood 3131414c70cbSLiam Girdwood for (i = 0; i < num_consumers; i++) { 3132414c70cbSLiam Girdwood consumers[i].consumer = regulator_get(dev, 3133414c70cbSLiam Girdwood consumers[i].supply); 3134414c70cbSLiam Girdwood if (IS_ERR(consumers[i].consumer)) { 3135414c70cbSLiam Girdwood ret = PTR_ERR(consumers[i].consumer); 31365b307627SMark Brown dev_err(dev, "Failed to get supply '%s': %d\n", 31375b307627SMark Brown consumers[i].supply, ret); 3138414c70cbSLiam Girdwood consumers[i].consumer = NULL; 3139414c70cbSLiam Girdwood goto err; 3140414c70cbSLiam Girdwood } 3141414c70cbSLiam Girdwood } 3142414c70cbSLiam Girdwood 3143414c70cbSLiam Girdwood return 0; 3144414c70cbSLiam Girdwood 3145414c70cbSLiam Girdwood err: 3146b29c7690SAxel Lin while (--i >= 0) 3147414c70cbSLiam Girdwood regulator_put(consumers[i].consumer); 3148414c70cbSLiam Girdwood 3149414c70cbSLiam Girdwood return ret; 3150414c70cbSLiam Girdwood } 3151414c70cbSLiam Girdwood EXPORT_SYMBOL_GPL(regulator_bulk_get); 3152414c70cbSLiam Girdwood 3153e6e74030SMark Brown /** 3154e6e74030SMark Brown * devm_regulator_bulk_get - managed get multiple regulator consumers 3155e6e74030SMark Brown * 3156e6e74030SMark Brown * @dev: Device to supply 3157e6e74030SMark Brown * @num_consumers: Number of consumers to register 3158e6e74030SMark Brown * @consumers: Configuration of consumers; clients are stored here. 3159e6e74030SMark Brown * 3160e6e74030SMark Brown * @return 0 on success, an errno on failure. 3161e6e74030SMark Brown * 3162e6e74030SMark Brown * This helper function allows drivers to get several regulator 3163e6e74030SMark Brown * consumers in one operation with management, the regulators will 3164e6e74030SMark Brown * automatically be freed when the device is unbound. If any of the 3165e6e74030SMark Brown * regulators cannot be acquired then any regulators that were 3166e6e74030SMark Brown * allocated will be freed before returning to the caller. 3167e6e74030SMark Brown */ 3168e6e74030SMark Brown int devm_regulator_bulk_get(struct device *dev, int num_consumers, 3169e6e74030SMark Brown struct regulator_bulk_data *consumers) 3170e6e74030SMark Brown { 3171e6e74030SMark Brown int i; 3172e6e74030SMark Brown int ret; 3173e6e74030SMark Brown 3174e6e74030SMark Brown for (i = 0; i < num_consumers; i++) 3175e6e74030SMark Brown consumers[i].consumer = NULL; 3176e6e74030SMark Brown 3177e6e74030SMark Brown for (i = 0; i < num_consumers; i++) { 3178e6e74030SMark Brown consumers[i].consumer = devm_regulator_get(dev, 3179e6e74030SMark Brown consumers[i].supply); 3180e6e74030SMark Brown if (IS_ERR(consumers[i].consumer)) { 3181e6e74030SMark Brown ret = PTR_ERR(consumers[i].consumer); 3182e6e74030SMark Brown dev_err(dev, "Failed to get supply '%s': %d\n", 3183e6e74030SMark Brown consumers[i].supply, ret); 3184e6e74030SMark Brown consumers[i].consumer = NULL; 3185e6e74030SMark Brown goto err; 3186e6e74030SMark Brown } 3187e6e74030SMark Brown } 3188e6e74030SMark Brown 3189e6e74030SMark Brown return 0; 3190e6e74030SMark Brown 3191e6e74030SMark Brown err: 3192e6e74030SMark Brown for (i = 0; i < num_consumers && consumers[i].consumer; i++) 3193e6e74030SMark Brown devm_regulator_put(consumers[i].consumer); 3194e6e74030SMark Brown 3195e6e74030SMark Brown return ret; 3196e6e74030SMark Brown } 3197e6e74030SMark Brown EXPORT_SYMBOL_GPL(devm_regulator_bulk_get); 3198e6e74030SMark Brown 3199f21e0e81SMark Brown static void regulator_bulk_enable_async(void *data, async_cookie_t cookie) 3200f21e0e81SMark Brown { 3201f21e0e81SMark Brown struct regulator_bulk_data *bulk = data; 3202f21e0e81SMark Brown 3203f21e0e81SMark Brown bulk->ret = regulator_enable(bulk->consumer); 3204f21e0e81SMark Brown } 3205f21e0e81SMark Brown 3206414c70cbSLiam Girdwood /** 3207414c70cbSLiam Girdwood * regulator_bulk_enable - enable multiple regulator consumers 3208414c70cbSLiam Girdwood * 3209414c70cbSLiam Girdwood * @num_consumers: Number of consumers 3210414c70cbSLiam Girdwood * @consumers: Consumer data; clients are stored here. 3211414c70cbSLiam Girdwood * @return 0 on success, an errno on failure 3212414c70cbSLiam Girdwood * 3213414c70cbSLiam Girdwood * This convenience API allows consumers to enable multiple regulator 3214414c70cbSLiam Girdwood * clients in a single API call. If any consumers cannot be enabled 3215414c70cbSLiam Girdwood * then any others that were enabled will be disabled again prior to 3216414c70cbSLiam Girdwood * return. 3217414c70cbSLiam Girdwood */ 3218414c70cbSLiam Girdwood int regulator_bulk_enable(int num_consumers, 3219414c70cbSLiam Girdwood struct regulator_bulk_data *consumers) 3220414c70cbSLiam Girdwood { 32212955b47dSDan Williams ASYNC_DOMAIN_EXCLUSIVE(async_domain); 3222414c70cbSLiam Girdwood int i; 3223f21e0e81SMark Brown int ret = 0; 3224414c70cbSLiam Girdwood 32256492bc1bSMark Brown for (i = 0; i < num_consumers; i++) { 32266492bc1bSMark Brown if (consumers[i].consumer->always_on) 32276492bc1bSMark Brown consumers[i].ret = 0; 32286492bc1bSMark Brown else 3229f21e0e81SMark Brown async_schedule_domain(regulator_bulk_enable_async, 3230f21e0e81SMark Brown &consumers[i], &async_domain); 32316492bc1bSMark Brown } 3232f21e0e81SMark Brown 3233f21e0e81SMark Brown async_synchronize_full_domain(&async_domain); 3234f21e0e81SMark Brown 3235f21e0e81SMark Brown /* If any consumer failed we need to unwind any that succeeded */ 3236414c70cbSLiam Girdwood for (i = 0; i < num_consumers; i++) { 3237f21e0e81SMark Brown if (consumers[i].ret != 0) { 3238f21e0e81SMark Brown ret = consumers[i].ret; 3239414c70cbSLiam Girdwood goto err; 3240414c70cbSLiam Girdwood } 3241f21e0e81SMark Brown } 3242414c70cbSLiam Girdwood 3243414c70cbSLiam Girdwood return 0; 3244414c70cbSLiam Girdwood 3245414c70cbSLiam Girdwood err: 3246fbe31057SAndrzej Hajda for (i = 0; i < num_consumers; i++) { 3247fbe31057SAndrzej Hajda if (consumers[i].ret < 0) 3248fbe31057SAndrzej Hajda pr_err("Failed to enable %s: %d\n", consumers[i].supply, 3249fbe31057SAndrzej Hajda consumers[i].ret); 3250fbe31057SAndrzej Hajda else 3251414c70cbSLiam Girdwood regulator_disable(consumers[i].consumer); 3252fbe31057SAndrzej Hajda } 3253414c70cbSLiam Girdwood 3254414c70cbSLiam Girdwood return ret; 3255414c70cbSLiam Girdwood } 3256414c70cbSLiam Girdwood EXPORT_SYMBOL_GPL(regulator_bulk_enable); 3257414c70cbSLiam Girdwood 3258414c70cbSLiam Girdwood /** 3259414c70cbSLiam Girdwood * regulator_bulk_disable - disable multiple regulator consumers 3260414c70cbSLiam Girdwood * 3261414c70cbSLiam Girdwood * @num_consumers: Number of consumers 3262414c70cbSLiam Girdwood * @consumers: Consumer data; clients are stored here. 3263414c70cbSLiam Girdwood * @return 0 on success, an errno on failure 3264414c70cbSLiam Girdwood * 3265414c70cbSLiam Girdwood * This convenience API allows consumers to disable multiple regulator 326649e22632SSylwester Nawrocki * clients in a single API call. If any consumers cannot be disabled 326749e22632SSylwester Nawrocki * then any others that were disabled will be enabled again prior to 3268414c70cbSLiam Girdwood * return. 3269414c70cbSLiam Girdwood */ 3270414c70cbSLiam Girdwood int regulator_bulk_disable(int num_consumers, 3271414c70cbSLiam Girdwood struct regulator_bulk_data *consumers) 3272414c70cbSLiam Girdwood { 3273414c70cbSLiam Girdwood int i; 327401e86f49SMark Brown int ret, r; 3275414c70cbSLiam Girdwood 327649e22632SSylwester Nawrocki for (i = num_consumers - 1; i >= 0; --i) { 3277414c70cbSLiam Girdwood ret = regulator_disable(consumers[i].consumer); 3278414c70cbSLiam Girdwood if (ret != 0) 3279414c70cbSLiam Girdwood goto err; 3280414c70cbSLiam Girdwood } 3281414c70cbSLiam Girdwood 3282414c70cbSLiam Girdwood return 0; 3283414c70cbSLiam Girdwood 3284414c70cbSLiam Girdwood err: 32855da84fd9SJoe Perches pr_err("Failed to disable %s: %d\n", consumers[i].supply, ret); 328601e86f49SMark Brown for (++i; i < num_consumers; ++i) { 328701e86f49SMark Brown r = regulator_enable(consumers[i].consumer); 328801e86f49SMark Brown if (r != 0) 328901e86f49SMark Brown pr_err("Failed to reename %s: %d\n", 329001e86f49SMark Brown consumers[i].supply, r); 329101e86f49SMark Brown } 3292414c70cbSLiam Girdwood 3293414c70cbSLiam Girdwood return ret; 3294414c70cbSLiam Girdwood } 3295414c70cbSLiam Girdwood EXPORT_SYMBOL_GPL(regulator_bulk_disable); 3296414c70cbSLiam Girdwood 3297414c70cbSLiam Girdwood /** 3298e1de2f42SDonggeun Kim * regulator_bulk_force_disable - force disable multiple regulator consumers 3299e1de2f42SDonggeun Kim * 3300e1de2f42SDonggeun Kim * @num_consumers: Number of consumers 3301e1de2f42SDonggeun Kim * @consumers: Consumer data; clients are stored here. 3302e1de2f42SDonggeun Kim * @return 0 on success, an errno on failure 3303e1de2f42SDonggeun Kim * 3304e1de2f42SDonggeun Kim * This convenience API allows consumers to forcibly disable multiple regulator 3305e1de2f42SDonggeun Kim * clients in a single API call. 3306e1de2f42SDonggeun Kim * NOTE: This should be used for situations when device damage will 3307e1de2f42SDonggeun Kim * likely occur if the regulators are not disabled (e.g. over temp). 3308e1de2f42SDonggeun Kim * Although regulator_force_disable function call for some consumers can 3309e1de2f42SDonggeun Kim * return error numbers, the function is called for all consumers. 3310e1de2f42SDonggeun Kim */ 3311e1de2f42SDonggeun Kim int regulator_bulk_force_disable(int num_consumers, 3312e1de2f42SDonggeun Kim struct regulator_bulk_data *consumers) 3313e1de2f42SDonggeun Kim { 3314e1de2f42SDonggeun Kim int i; 3315e1de2f42SDonggeun Kim int ret; 3316e1de2f42SDonggeun Kim 3317e1de2f42SDonggeun Kim for (i = 0; i < num_consumers; i++) 3318e1de2f42SDonggeun Kim consumers[i].ret = 3319e1de2f42SDonggeun Kim regulator_force_disable(consumers[i].consumer); 3320e1de2f42SDonggeun Kim 3321e1de2f42SDonggeun Kim for (i = 0; i < num_consumers; i++) { 3322e1de2f42SDonggeun Kim if (consumers[i].ret != 0) { 3323e1de2f42SDonggeun Kim ret = consumers[i].ret; 3324e1de2f42SDonggeun Kim goto out; 3325e1de2f42SDonggeun Kim } 3326e1de2f42SDonggeun Kim } 3327e1de2f42SDonggeun Kim 3328e1de2f42SDonggeun Kim return 0; 3329e1de2f42SDonggeun Kim out: 3330e1de2f42SDonggeun Kim return ret; 3331e1de2f42SDonggeun Kim } 3332e1de2f42SDonggeun Kim EXPORT_SYMBOL_GPL(regulator_bulk_force_disable); 3333e1de2f42SDonggeun Kim 3334e1de2f42SDonggeun Kim /** 3335414c70cbSLiam Girdwood * regulator_bulk_free - free multiple regulator consumers 3336414c70cbSLiam Girdwood * 3337414c70cbSLiam Girdwood * @num_consumers: Number of consumers 3338414c70cbSLiam Girdwood * @consumers: Consumer data; clients are stored here. 3339414c70cbSLiam Girdwood * 3340414c70cbSLiam Girdwood * This convenience API allows consumers to free multiple regulator 3341414c70cbSLiam Girdwood * clients in a single API call. 3342414c70cbSLiam Girdwood */ 3343414c70cbSLiam Girdwood void regulator_bulk_free(int num_consumers, 3344414c70cbSLiam Girdwood struct regulator_bulk_data *consumers) 3345414c70cbSLiam Girdwood { 3346414c70cbSLiam Girdwood int i; 3347414c70cbSLiam Girdwood 3348414c70cbSLiam Girdwood for (i = 0; i < num_consumers; i++) { 3349414c70cbSLiam Girdwood regulator_put(consumers[i].consumer); 3350414c70cbSLiam Girdwood consumers[i].consumer = NULL; 3351414c70cbSLiam Girdwood } 3352414c70cbSLiam Girdwood } 3353414c70cbSLiam Girdwood EXPORT_SYMBOL_GPL(regulator_bulk_free); 3354414c70cbSLiam Girdwood 3355414c70cbSLiam Girdwood /** 3356414c70cbSLiam Girdwood * regulator_notifier_call_chain - call regulator event notifier 335769279fb9SMark Brown * @rdev: regulator source 3358414c70cbSLiam Girdwood * @event: notifier block 335969279fb9SMark Brown * @data: callback-specific data. 3360414c70cbSLiam Girdwood * 3361414c70cbSLiam Girdwood * Called by regulator drivers to notify clients a regulator event has 3362414c70cbSLiam Girdwood * occurred. We also notify regulator clients downstream. 3363b136fb44SJonathan Cameron * Note lock must be held by caller. 3364414c70cbSLiam Girdwood */ 3365414c70cbSLiam Girdwood int regulator_notifier_call_chain(struct regulator_dev *rdev, 3366414c70cbSLiam Girdwood unsigned long event, void *data) 3367414c70cbSLiam Girdwood { 3368414c70cbSLiam Girdwood _notifier_call_chain(rdev, event, data); 3369414c70cbSLiam Girdwood return NOTIFY_DONE; 3370414c70cbSLiam Girdwood 3371414c70cbSLiam Girdwood } 3372414c70cbSLiam Girdwood EXPORT_SYMBOL_GPL(regulator_notifier_call_chain); 3373414c70cbSLiam Girdwood 3374be721979SMark Brown /** 3375be721979SMark Brown * regulator_mode_to_status - convert a regulator mode into a status 3376be721979SMark Brown * 3377be721979SMark Brown * @mode: Mode to convert 3378be721979SMark Brown * 3379be721979SMark Brown * Convert a regulator mode into a status. 3380be721979SMark Brown */ 3381be721979SMark Brown int regulator_mode_to_status(unsigned int mode) 3382be721979SMark Brown { 3383be721979SMark Brown switch (mode) { 3384be721979SMark Brown case REGULATOR_MODE_FAST: 3385be721979SMark Brown return REGULATOR_STATUS_FAST; 3386be721979SMark Brown case REGULATOR_MODE_NORMAL: 3387be721979SMark Brown return REGULATOR_STATUS_NORMAL; 3388be721979SMark Brown case REGULATOR_MODE_IDLE: 3389be721979SMark Brown return REGULATOR_STATUS_IDLE; 339003ffcf3dSKrystian Garbaciak case REGULATOR_MODE_STANDBY: 3391be721979SMark Brown return REGULATOR_STATUS_STANDBY; 3392be721979SMark Brown default: 33931beaf762SKrystian Garbaciak return REGULATOR_STATUS_UNDEFINED; 3394be721979SMark Brown } 3395be721979SMark Brown } 3396be721979SMark Brown EXPORT_SYMBOL_GPL(regulator_mode_to_status); 3397be721979SMark Brown 33987ad68e2fSDavid Brownell /* 33997ad68e2fSDavid Brownell * To avoid cluttering sysfs (and memory) with useless state, only 34007ad68e2fSDavid Brownell * create attributes that can be meaningfully displayed. 34017ad68e2fSDavid Brownell */ 34027ad68e2fSDavid Brownell static int add_regulator_attributes(struct regulator_dev *rdev) 34037ad68e2fSDavid Brownell { 34047ad68e2fSDavid Brownell struct device *dev = &rdev->dev; 34057ad68e2fSDavid Brownell struct regulator_ops *ops = rdev->desc->ops; 34067ad68e2fSDavid Brownell int status = 0; 34077ad68e2fSDavid Brownell 34087ad68e2fSDavid Brownell /* some attributes need specific methods to be displayed */ 34094c78899bSMark Brown if ((ops->get_voltage && ops->get_voltage(rdev) >= 0) || 3410f2889e65SMark Brown (ops->get_voltage_sel && ops->get_voltage_sel(rdev) >= 0) || 3411f2889e65SMark Brown (ops->list_voltage && ops->list_voltage(rdev, 0) >= 0)) { 34127ad68e2fSDavid Brownell status = device_create_file(dev, &dev_attr_microvolts); 34137ad68e2fSDavid Brownell if (status < 0) 34147ad68e2fSDavid Brownell return status; 34157ad68e2fSDavid Brownell } 34167ad68e2fSDavid Brownell if (ops->get_current_limit) { 34177ad68e2fSDavid Brownell status = device_create_file(dev, &dev_attr_microamps); 34187ad68e2fSDavid Brownell if (status < 0) 34197ad68e2fSDavid Brownell return status; 34207ad68e2fSDavid Brownell } 34217ad68e2fSDavid Brownell if (ops->get_mode) { 34227ad68e2fSDavid Brownell status = device_create_file(dev, &dev_attr_opmode); 34237ad68e2fSDavid Brownell if (status < 0) 34247ad68e2fSDavid Brownell return status; 34257ad68e2fSDavid Brownell } 34267b74d149SKim, Milo if (rdev->ena_pin || ops->is_enabled) { 34277ad68e2fSDavid Brownell status = device_create_file(dev, &dev_attr_state); 34287ad68e2fSDavid Brownell if (status < 0) 34297ad68e2fSDavid Brownell return status; 34307ad68e2fSDavid Brownell } 3431853116a1SDavid Brownell if (ops->get_status) { 3432853116a1SDavid Brownell status = device_create_file(dev, &dev_attr_status); 3433853116a1SDavid Brownell if (status < 0) 3434853116a1SDavid Brownell return status; 3435853116a1SDavid Brownell } 3436f59c8f9fSMark Brown if (ops->get_bypass) { 3437f59c8f9fSMark Brown status = device_create_file(dev, &dev_attr_bypass); 3438f59c8f9fSMark Brown if (status < 0) 3439f59c8f9fSMark Brown return status; 3440f59c8f9fSMark Brown } 34417ad68e2fSDavid Brownell 34427ad68e2fSDavid Brownell /* some attributes are type-specific */ 34437ad68e2fSDavid Brownell if (rdev->desc->type == REGULATOR_CURRENT) { 34447ad68e2fSDavid Brownell status = device_create_file(dev, &dev_attr_requested_microamps); 34457ad68e2fSDavid Brownell if (status < 0) 34467ad68e2fSDavid Brownell return status; 34477ad68e2fSDavid Brownell } 34487ad68e2fSDavid Brownell 34497ad68e2fSDavid Brownell /* all the other attributes exist to support constraints; 34507ad68e2fSDavid Brownell * don't show them if there are no constraints, or if the 34517ad68e2fSDavid Brownell * relevant supporting methods are missing. 34527ad68e2fSDavid Brownell */ 34537ad68e2fSDavid Brownell if (!rdev->constraints) 34547ad68e2fSDavid Brownell return status; 34557ad68e2fSDavid Brownell 34567ad68e2fSDavid Brownell /* constraints need specific supporting methods */ 3457e8eef82bSMark Brown if (ops->set_voltage || ops->set_voltage_sel) { 34587ad68e2fSDavid Brownell status = device_create_file(dev, &dev_attr_min_microvolts); 34597ad68e2fSDavid Brownell if (status < 0) 34607ad68e2fSDavid Brownell return status; 34617ad68e2fSDavid Brownell status = device_create_file(dev, &dev_attr_max_microvolts); 34627ad68e2fSDavid Brownell if (status < 0) 34637ad68e2fSDavid Brownell return status; 34647ad68e2fSDavid Brownell } 34657ad68e2fSDavid Brownell if (ops->set_current_limit) { 34667ad68e2fSDavid Brownell status = device_create_file(dev, &dev_attr_min_microamps); 34677ad68e2fSDavid Brownell if (status < 0) 34687ad68e2fSDavid Brownell return status; 34697ad68e2fSDavid Brownell status = device_create_file(dev, &dev_attr_max_microamps); 34707ad68e2fSDavid Brownell if (status < 0) 34717ad68e2fSDavid Brownell return status; 34727ad68e2fSDavid Brownell } 34737ad68e2fSDavid Brownell 34747ad68e2fSDavid Brownell status = device_create_file(dev, &dev_attr_suspend_standby_state); 34757ad68e2fSDavid Brownell if (status < 0) 34767ad68e2fSDavid Brownell return status; 34777ad68e2fSDavid Brownell status = device_create_file(dev, &dev_attr_suspend_mem_state); 34787ad68e2fSDavid Brownell if (status < 0) 34797ad68e2fSDavid Brownell return status; 34807ad68e2fSDavid Brownell status = device_create_file(dev, &dev_attr_suspend_disk_state); 34817ad68e2fSDavid Brownell if (status < 0) 34827ad68e2fSDavid Brownell return status; 34837ad68e2fSDavid Brownell 34847ad68e2fSDavid Brownell if (ops->set_suspend_voltage) { 34857ad68e2fSDavid Brownell status = device_create_file(dev, 34867ad68e2fSDavid Brownell &dev_attr_suspend_standby_microvolts); 34877ad68e2fSDavid Brownell if (status < 0) 34887ad68e2fSDavid Brownell return status; 34897ad68e2fSDavid Brownell status = device_create_file(dev, 34907ad68e2fSDavid Brownell &dev_attr_suspend_mem_microvolts); 34917ad68e2fSDavid Brownell if (status < 0) 34927ad68e2fSDavid Brownell return status; 34937ad68e2fSDavid Brownell status = device_create_file(dev, 34947ad68e2fSDavid Brownell &dev_attr_suspend_disk_microvolts); 34957ad68e2fSDavid Brownell if (status < 0) 34967ad68e2fSDavid Brownell return status; 34977ad68e2fSDavid Brownell } 34987ad68e2fSDavid Brownell 34997ad68e2fSDavid Brownell if (ops->set_suspend_mode) { 35007ad68e2fSDavid Brownell status = device_create_file(dev, 35017ad68e2fSDavid Brownell &dev_attr_suspend_standby_mode); 35027ad68e2fSDavid Brownell if (status < 0) 35037ad68e2fSDavid Brownell return status; 35047ad68e2fSDavid Brownell status = device_create_file(dev, 35057ad68e2fSDavid Brownell &dev_attr_suspend_mem_mode); 35067ad68e2fSDavid Brownell if (status < 0) 35077ad68e2fSDavid Brownell return status; 35087ad68e2fSDavid Brownell status = device_create_file(dev, 35097ad68e2fSDavid Brownell &dev_attr_suspend_disk_mode); 35107ad68e2fSDavid Brownell if (status < 0) 35117ad68e2fSDavid Brownell return status; 35127ad68e2fSDavid Brownell } 35137ad68e2fSDavid Brownell 35147ad68e2fSDavid Brownell return status; 35157ad68e2fSDavid Brownell } 35167ad68e2fSDavid Brownell 35171130e5b3SMark Brown static void rdev_init_debugfs(struct regulator_dev *rdev) 35181130e5b3SMark Brown { 35191130e5b3SMark Brown rdev->debugfs = debugfs_create_dir(rdev_get_name(rdev), debugfs_root); 352024751434SStephen Boyd if (!rdev->debugfs) { 35211130e5b3SMark Brown rdev_warn(rdev, "Failed to create debugfs directory\n"); 35221130e5b3SMark Brown return; 35231130e5b3SMark Brown } 35241130e5b3SMark Brown 35251130e5b3SMark Brown debugfs_create_u32("use_count", 0444, rdev->debugfs, 35261130e5b3SMark Brown &rdev->use_count); 35271130e5b3SMark Brown debugfs_create_u32("open_count", 0444, rdev->debugfs, 35281130e5b3SMark Brown &rdev->open_count); 3529f59c8f9fSMark Brown debugfs_create_u32("bypass_count", 0444, rdev->debugfs, 3530f59c8f9fSMark Brown &rdev->bypass_count); 35311130e5b3SMark Brown } 35321130e5b3SMark Brown 3533414c70cbSLiam Girdwood /** 3534414c70cbSLiam Girdwood * regulator_register - register regulator 353569279fb9SMark Brown * @regulator_desc: regulator to register 3536c172708dSMark Brown * @config: runtime configuration for regulator 3537414c70cbSLiam Girdwood * 3538414c70cbSLiam Girdwood * Called by regulator drivers to register a regulator. 35390384618aSAxel Lin * Returns a valid pointer to struct regulator_dev on success 35400384618aSAxel Lin * or an ERR_PTR() on error. 3541414c70cbSLiam Girdwood */ 354265f26846SMark Brown struct regulator_dev * 354365f26846SMark Brown regulator_register(const struct regulator_desc *regulator_desc, 3544c172708dSMark Brown const struct regulator_config *config) 3545414c70cbSLiam Girdwood { 35469a8f5e07SMark Brown const struct regulation_constraints *constraints = NULL; 3547c172708dSMark Brown const struct regulator_init_data *init_data; 3548414c70cbSLiam Girdwood static atomic_t regulator_no = ATOMIC_INIT(0); 3549414c70cbSLiam Girdwood struct regulator_dev *rdev; 355032c8fad4SMark Brown struct device *dev; 3551a5766f11SLiam Girdwood int ret, i; 355269511a45SRajendra Nayak const char *supply = NULL; 3553414c70cbSLiam Girdwood 3554c172708dSMark Brown if (regulator_desc == NULL || config == NULL) 3555414c70cbSLiam Girdwood return ERR_PTR(-EINVAL); 3556414c70cbSLiam Girdwood 355732c8fad4SMark Brown dev = config->dev; 3558dcf70112SMark Brown WARN_ON(!dev); 355932c8fad4SMark Brown 3560414c70cbSLiam Girdwood if (regulator_desc->name == NULL || regulator_desc->ops == NULL) 3561414c70cbSLiam Girdwood return ERR_PTR(-EINVAL); 3562414c70cbSLiam Girdwood 3563cd78dfc6SDiego Liziero if (regulator_desc->type != REGULATOR_VOLTAGE && 3564cd78dfc6SDiego Liziero regulator_desc->type != REGULATOR_CURRENT) 3565414c70cbSLiam Girdwood return ERR_PTR(-EINVAL); 3566414c70cbSLiam Girdwood 3567476c2d83SMark Brown /* Only one of each should be implemented */ 3568476c2d83SMark Brown WARN_ON(regulator_desc->ops->get_voltage && 3569476c2d83SMark Brown regulator_desc->ops->get_voltage_sel); 3570e8eef82bSMark Brown WARN_ON(regulator_desc->ops->set_voltage && 3571e8eef82bSMark Brown regulator_desc->ops->set_voltage_sel); 3572476c2d83SMark Brown 3573476c2d83SMark Brown /* If we're using selectors we must implement list_voltage. */ 3574476c2d83SMark Brown if (regulator_desc->ops->get_voltage_sel && 3575476c2d83SMark Brown !regulator_desc->ops->list_voltage) { 3576476c2d83SMark Brown return ERR_PTR(-EINVAL); 3577476c2d83SMark Brown } 3578e8eef82bSMark Brown if (regulator_desc->ops->set_voltage_sel && 3579e8eef82bSMark Brown !regulator_desc->ops->list_voltage) { 3580e8eef82bSMark Brown return ERR_PTR(-EINVAL); 3581e8eef82bSMark Brown } 3582476c2d83SMark Brown 3583c172708dSMark Brown init_data = config->init_data; 3584c172708dSMark Brown 3585414c70cbSLiam Girdwood rdev = kzalloc(sizeof(struct regulator_dev), GFP_KERNEL); 3586414c70cbSLiam Girdwood if (rdev == NULL) 3587414c70cbSLiam Girdwood return ERR_PTR(-ENOMEM); 3588414c70cbSLiam Girdwood 3589414c70cbSLiam Girdwood mutex_lock(®ulator_list_mutex); 3590414c70cbSLiam Girdwood 3591414c70cbSLiam Girdwood mutex_init(&rdev->mutex); 3592c172708dSMark Brown rdev->reg_data = config->driver_data; 3593414c70cbSLiam Girdwood rdev->owner = regulator_desc->owner; 3594414c70cbSLiam Girdwood rdev->desc = regulator_desc; 35953a4b0a07SMark Brown if (config->regmap) 359665b19ce6SMark Brown rdev->regmap = config->regmap; 359752b84dacSAnilKumar Ch else if (dev_get_regmap(dev, NULL)) 35983a4b0a07SMark Brown rdev->regmap = dev_get_regmap(dev, NULL); 359952b84dacSAnilKumar Ch else if (dev->parent) 360052b84dacSAnilKumar Ch rdev->regmap = dev_get_regmap(dev->parent, NULL); 3601414c70cbSLiam Girdwood INIT_LIST_HEAD(&rdev->consumer_list); 3602414c70cbSLiam Girdwood INIT_LIST_HEAD(&rdev->list); 3603414c70cbSLiam Girdwood BLOCKING_INIT_NOTIFIER_HEAD(&rdev->notifier); 3604da07ecd9SMark Brown INIT_DELAYED_WORK(&rdev->disable_work, regulator_disable_work); 3605414c70cbSLiam Girdwood 3606a5766f11SLiam Girdwood /* preform any regulator specific init */ 36079a8f5e07SMark Brown if (init_data && init_data->regulator_init) { 3608a5766f11SLiam Girdwood ret = init_data->regulator_init(rdev->reg_data); 36094fca9545SDavid Brownell if (ret < 0) 36104fca9545SDavid Brownell goto clean; 3611a5766f11SLiam Girdwood } 3612a5766f11SLiam Girdwood 3613a5766f11SLiam Girdwood /* register with sysfs */ 3614a5766f11SLiam Girdwood rdev->dev.class = ®ulator_class; 3615c172708dSMark Brown rdev->dev.of_node = config->of_node; 3616a5766f11SLiam Girdwood rdev->dev.parent = dev; 3617812460a9SKay Sievers dev_set_name(&rdev->dev, "regulator.%d", 3618812460a9SKay Sievers atomic_inc_return(®ulator_no) - 1); 3619a5766f11SLiam Girdwood ret = device_register(&rdev->dev); 3620ad7725cbSVasiliy Kulikov if (ret != 0) { 3621ad7725cbSVasiliy Kulikov put_device(&rdev->dev); 36224fca9545SDavid Brownell goto clean; 3623ad7725cbSVasiliy Kulikov } 3624a5766f11SLiam Girdwood 3625a5766f11SLiam Girdwood dev_set_drvdata(&rdev->dev, rdev); 3626a5766f11SLiam Girdwood 3627b2a1ef47SMarek Szyprowski if (config->ena_gpio && gpio_is_valid(config->ena_gpio)) { 3628f19b00daSKim, Milo ret = regulator_ena_gpio_request(rdev, config); 362965f73508SMark Brown if (ret != 0) { 363065f73508SMark Brown rdev_err(rdev, "Failed to request enable GPIO%d: %d\n", 363165f73508SMark Brown config->ena_gpio, ret); 3632b2da55d9SAndrew Lunn goto wash; 363365f73508SMark Brown } 363465f73508SMark Brown 363565f73508SMark Brown if (config->ena_gpio_flags & GPIOF_OUT_INIT_HIGH) 363665f73508SMark Brown rdev->ena_gpio_state = 1; 363765f73508SMark Brown 36387b74d149SKim, Milo if (config->ena_gpio_invert) 363965f73508SMark Brown rdev->ena_gpio_state = !rdev->ena_gpio_state; 364065f73508SMark Brown } 364165f73508SMark Brown 364274f544c1SMike Rapoport /* set regulator constraints */ 36439a8f5e07SMark Brown if (init_data) 36449a8f5e07SMark Brown constraints = &init_data->constraints; 36459a8f5e07SMark Brown 36469a8f5e07SMark Brown ret = set_machine_constraints(rdev, constraints); 364774f544c1SMike Rapoport if (ret < 0) 364874f544c1SMike Rapoport goto scrub; 364974f544c1SMike Rapoport 36507ad68e2fSDavid Brownell /* add attributes supported by this regulator */ 36517ad68e2fSDavid Brownell ret = add_regulator_attributes(rdev); 36527ad68e2fSDavid Brownell if (ret < 0) 36537ad68e2fSDavid Brownell goto scrub; 36547ad68e2fSDavid Brownell 36559a8f5e07SMark Brown if (init_data && init_data->supply_regulator) 365669511a45SRajendra Nayak supply = init_data->supply_regulator; 365769511a45SRajendra Nayak else if (regulator_desc->supply_name) 365869511a45SRajendra Nayak supply = regulator_desc->supply_name; 365969511a45SRajendra Nayak 366069511a45SRajendra Nayak if (supply) { 36610178f3e2SMark Brown struct regulator_dev *r; 36620178f3e2SMark Brown 36636d191a5fSMark Brown r = regulator_dev_lookup(dev, supply, &ret); 36640178f3e2SMark Brown 36650f7b87f0SAndrew Bresticker if (ret == -ENODEV) { 36660f7b87f0SAndrew Bresticker /* 36670f7b87f0SAndrew Bresticker * No supply was specified for this regulator and 36680f7b87f0SAndrew Bresticker * there will never be one. 36690f7b87f0SAndrew Bresticker */ 36700f7b87f0SAndrew Bresticker ret = 0; 36710f7b87f0SAndrew Bresticker goto add_dev; 36720f7b87f0SAndrew Bresticker } else if (!r) { 367369511a45SRajendra Nayak dev_err(dev, "Failed to find supply %s\n", supply); 367404bf3011SMark Brown ret = -EPROBE_DEFER; 36750178f3e2SMark Brown goto scrub; 36760178f3e2SMark Brown } 36770178f3e2SMark Brown 36780178f3e2SMark Brown ret = set_supply(rdev, r); 36790178f3e2SMark Brown if (ret < 0) 36800178f3e2SMark Brown goto scrub; 3681b2296bd4SLaxman Dewangan 3682b2296bd4SLaxman Dewangan /* Enable supply if rail is enabled */ 3683b1a86831SMark Brown if (_regulator_is_enabled(rdev)) { 3684b2296bd4SLaxman Dewangan ret = regulator_enable(rdev->supply); 3685b2296bd4SLaxman Dewangan if (ret < 0) 3686b2296bd4SLaxman Dewangan goto scrub; 3687b2296bd4SLaxman Dewangan } 36880178f3e2SMark Brown } 36890178f3e2SMark Brown 36900f7b87f0SAndrew Bresticker add_dev: 3691a5766f11SLiam Girdwood /* add consumers devices */ 36929a8f5e07SMark Brown if (init_data) { 3693a5766f11SLiam Girdwood for (i = 0; i < init_data->num_consumer_supplies; i++) { 3694a5766f11SLiam Girdwood ret = set_consumer_device_supply(rdev, 369540f9244fSMark Brown init_data->consumer_supplies[i].dev_name, 3696a5766f11SLiam Girdwood init_data->consumer_supplies[i].supply); 369723c2f041SMark Brown if (ret < 0) { 369823c2f041SMark Brown dev_err(dev, "Failed to set supply %s\n", 369923c2f041SMark Brown init_data->consumer_supplies[i].supply); 3700d4033b54SJani Nikula goto unset_supplies; 3701a5766f11SLiam Girdwood } 370223c2f041SMark Brown } 37039a8f5e07SMark Brown } 3704a5766f11SLiam Girdwood 3705a5766f11SLiam Girdwood list_add(&rdev->list, ®ulator_list); 37061130e5b3SMark Brown 37071130e5b3SMark Brown rdev_init_debugfs(rdev); 3708a5766f11SLiam Girdwood out: 3709414c70cbSLiam Girdwood mutex_unlock(®ulator_list_mutex); 3710414c70cbSLiam Girdwood return rdev; 37114fca9545SDavid Brownell 3712d4033b54SJani Nikula unset_supplies: 3713d4033b54SJani Nikula unset_regulator_supplies(rdev); 3714d4033b54SJani Nikula 37154fca9545SDavid Brownell scrub: 3716e81dba85SMark Brown if (rdev->supply) 371723ff2f0fSCharles Keepax _regulator_put(rdev->supply); 3718f19b00daSKim, Milo regulator_ena_gpio_free(rdev); 37191a6958e7SAxel Lin kfree(rdev->constraints); 3720b2da55d9SAndrew Lunn wash: 37214fca9545SDavid Brownell device_unregister(&rdev->dev); 372253032dafSPaul Walmsley /* device core frees rdev */ 372353032dafSPaul Walmsley rdev = ERR_PTR(ret); 372453032dafSPaul Walmsley goto out; 372553032dafSPaul Walmsley 37264fca9545SDavid Brownell clean: 37274fca9545SDavid Brownell kfree(rdev); 37284fca9545SDavid Brownell rdev = ERR_PTR(ret); 37294fca9545SDavid Brownell goto out; 3730414c70cbSLiam Girdwood } 3731414c70cbSLiam Girdwood EXPORT_SYMBOL_GPL(regulator_register); 3732414c70cbSLiam Girdwood 3733414c70cbSLiam Girdwood /** 3734414c70cbSLiam Girdwood * regulator_unregister - unregister regulator 373569279fb9SMark Brown * @rdev: regulator to unregister 3736414c70cbSLiam Girdwood * 3737414c70cbSLiam Girdwood * Called by regulator drivers to unregister a regulator. 3738414c70cbSLiam Girdwood */ 3739414c70cbSLiam Girdwood void regulator_unregister(struct regulator_dev *rdev) 3740414c70cbSLiam Girdwood { 3741414c70cbSLiam Girdwood if (rdev == NULL) 3742414c70cbSLiam Girdwood return; 3743414c70cbSLiam Girdwood 3744891636eaSMark Brown if (rdev->supply) { 3745891636eaSMark Brown while (rdev->use_count--) 3746891636eaSMark Brown regulator_disable(rdev->supply); 3747e032b376SMark Brown regulator_put(rdev->supply); 3748891636eaSMark Brown } 3749414c70cbSLiam Girdwood mutex_lock(®ulator_list_mutex); 37501130e5b3SMark Brown debugfs_remove_recursive(rdev->debugfs); 375143829731STejun Heo flush_work(&rdev->disable_work.work); 37526bf87d17SMark Brown WARN_ON(rdev->open_count); 37530f1d747bSMike Rapoport unset_regulator_supplies(rdev); 3754414c70cbSLiam Girdwood list_del(&rdev->list); 3755f8c12fe3SMark Brown kfree(rdev->constraints); 3756f19b00daSKim, Milo regulator_ena_gpio_free(rdev); 375758fb5cf5SLothar Waßmann device_unregister(&rdev->dev); 3758414c70cbSLiam Girdwood mutex_unlock(®ulator_list_mutex); 3759414c70cbSLiam Girdwood } 3760414c70cbSLiam Girdwood EXPORT_SYMBOL_GPL(regulator_unregister); 3761414c70cbSLiam Girdwood 3762414c70cbSLiam Girdwood /** 3763cf7bbcdfSMark Brown * regulator_suspend_prepare - prepare regulators for system wide suspend 3764414c70cbSLiam Girdwood * @state: system suspend state 3765414c70cbSLiam Girdwood * 3766414c70cbSLiam Girdwood * Configure each regulator with it's suspend operating parameters for state. 3767414c70cbSLiam Girdwood * This will usually be called by machine suspend code prior to supending. 3768414c70cbSLiam Girdwood */ 3769414c70cbSLiam Girdwood int regulator_suspend_prepare(suspend_state_t state) 3770414c70cbSLiam Girdwood { 3771414c70cbSLiam Girdwood struct regulator_dev *rdev; 3772414c70cbSLiam Girdwood int ret = 0; 3773414c70cbSLiam Girdwood 3774414c70cbSLiam Girdwood /* ON is handled by regulator active state */ 3775414c70cbSLiam Girdwood if (state == PM_SUSPEND_ON) 3776414c70cbSLiam Girdwood return -EINVAL; 3777414c70cbSLiam Girdwood 3778414c70cbSLiam Girdwood mutex_lock(®ulator_list_mutex); 3779414c70cbSLiam Girdwood list_for_each_entry(rdev, ®ulator_list, list) { 3780414c70cbSLiam Girdwood 3781414c70cbSLiam Girdwood mutex_lock(&rdev->mutex); 3782414c70cbSLiam Girdwood ret = suspend_prepare(rdev, state); 3783414c70cbSLiam Girdwood mutex_unlock(&rdev->mutex); 3784414c70cbSLiam Girdwood 3785414c70cbSLiam Girdwood if (ret < 0) { 37865da84fd9SJoe Perches rdev_err(rdev, "failed to prepare\n"); 3787414c70cbSLiam Girdwood goto out; 3788414c70cbSLiam Girdwood } 3789414c70cbSLiam Girdwood } 3790414c70cbSLiam Girdwood out: 3791414c70cbSLiam Girdwood mutex_unlock(®ulator_list_mutex); 3792414c70cbSLiam Girdwood return ret; 3793414c70cbSLiam Girdwood } 3794414c70cbSLiam Girdwood EXPORT_SYMBOL_GPL(regulator_suspend_prepare); 3795414c70cbSLiam Girdwood 3796414c70cbSLiam Girdwood /** 37977a32b589SMyungJoo Ham * regulator_suspend_finish - resume regulators from system wide suspend 37987a32b589SMyungJoo Ham * 37997a32b589SMyungJoo Ham * Turn on regulators that might be turned off by regulator_suspend_prepare 38007a32b589SMyungJoo Ham * and that should be turned on according to the regulators properties. 38017a32b589SMyungJoo Ham */ 38027a32b589SMyungJoo Ham int regulator_suspend_finish(void) 38037a32b589SMyungJoo Ham { 38047a32b589SMyungJoo Ham struct regulator_dev *rdev; 38057a32b589SMyungJoo Ham int ret = 0, error; 38067a32b589SMyungJoo Ham 38077a32b589SMyungJoo Ham mutex_lock(®ulator_list_mutex); 38087a32b589SMyungJoo Ham list_for_each_entry(rdev, ®ulator_list, list) { 38097a32b589SMyungJoo Ham struct regulator_ops *ops = rdev->desc->ops; 38107a32b589SMyungJoo Ham 38117a32b589SMyungJoo Ham mutex_lock(&rdev->mutex); 38127a32b589SMyungJoo Ham if ((rdev->use_count > 0 || rdev->constraints->always_on) && 38137a32b589SMyungJoo Ham ops->enable) { 38147a32b589SMyungJoo Ham error = ops->enable(rdev); 38157a32b589SMyungJoo Ham if (error) 38167a32b589SMyungJoo Ham ret = error; 38177a32b589SMyungJoo Ham } else { 38187a32b589SMyungJoo Ham if (!has_full_constraints) 38197a32b589SMyungJoo Ham goto unlock; 38207a32b589SMyungJoo Ham if (!ops->disable) 38217a32b589SMyungJoo Ham goto unlock; 3822b1a86831SMark Brown if (!_regulator_is_enabled(rdev)) 38237a32b589SMyungJoo Ham goto unlock; 38247a32b589SMyungJoo Ham 38257a32b589SMyungJoo Ham error = ops->disable(rdev); 38267a32b589SMyungJoo Ham if (error) 38277a32b589SMyungJoo Ham ret = error; 38287a32b589SMyungJoo Ham } 38297a32b589SMyungJoo Ham unlock: 38307a32b589SMyungJoo Ham mutex_unlock(&rdev->mutex); 38317a32b589SMyungJoo Ham } 38327a32b589SMyungJoo Ham mutex_unlock(®ulator_list_mutex); 38337a32b589SMyungJoo Ham return ret; 38347a32b589SMyungJoo Ham } 38357a32b589SMyungJoo Ham EXPORT_SYMBOL_GPL(regulator_suspend_finish); 38367a32b589SMyungJoo Ham 38377a32b589SMyungJoo Ham /** 3838ca725561SMark Brown * regulator_has_full_constraints - the system has fully specified constraints 3839ca725561SMark Brown * 3840ca725561SMark Brown * Calling this function will cause the regulator API to disable all 3841ca725561SMark Brown * regulators which have a zero use count and don't have an always_on 3842ca725561SMark Brown * constraint in a late_initcall. 3843ca725561SMark Brown * 3844ca725561SMark Brown * The intention is that this will become the default behaviour in a 3845ca725561SMark Brown * future kernel release so users are encouraged to use this facility 3846ca725561SMark Brown * now. 3847ca725561SMark Brown */ 3848ca725561SMark Brown void regulator_has_full_constraints(void) 3849ca725561SMark Brown { 3850ca725561SMark Brown has_full_constraints = 1; 3851ca725561SMark Brown } 3852ca725561SMark Brown EXPORT_SYMBOL_GPL(regulator_has_full_constraints); 3853ca725561SMark Brown 3854ca725561SMark Brown /** 3855688fe99aSMark Brown * regulator_use_dummy_regulator - Provide a dummy regulator when none is found 3856688fe99aSMark Brown * 3857688fe99aSMark Brown * Calling this function will cause the regulator API to provide a 3858688fe99aSMark Brown * dummy regulator to consumers if no physical regulator is found, 3859688fe99aSMark Brown * allowing most consumers to proceed as though a regulator were 3860688fe99aSMark Brown * configured. This allows systems such as those with software 3861688fe99aSMark Brown * controllable regulators for the CPU core only to be brought up more 3862688fe99aSMark Brown * readily. 3863688fe99aSMark Brown */ 3864688fe99aSMark Brown void regulator_use_dummy_regulator(void) 3865688fe99aSMark Brown { 3866688fe99aSMark Brown board_wants_dummy_regulator = true; 3867688fe99aSMark Brown } 3868688fe99aSMark Brown EXPORT_SYMBOL_GPL(regulator_use_dummy_regulator); 3869688fe99aSMark Brown 3870688fe99aSMark Brown /** 3871414c70cbSLiam Girdwood * rdev_get_drvdata - get rdev regulator driver data 387269279fb9SMark Brown * @rdev: regulator 3873414c70cbSLiam Girdwood * 3874414c70cbSLiam Girdwood * Get rdev regulator driver private data. This call can be used in the 3875414c70cbSLiam Girdwood * regulator driver context. 3876414c70cbSLiam Girdwood */ 3877414c70cbSLiam Girdwood void *rdev_get_drvdata(struct regulator_dev *rdev) 3878414c70cbSLiam Girdwood { 3879414c70cbSLiam Girdwood return rdev->reg_data; 3880414c70cbSLiam Girdwood } 3881414c70cbSLiam Girdwood EXPORT_SYMBOL_GPL(rdev_get_drvdata); 3882414c70cbSLiam Girdwood 3883414c70cbSLiam Girdwood /** 3884414c70cbSLiam Girdwood * regulator_get_drvdata - get regulator driver data 3885414c70cbSLiam Girdwood * @regulator: regulator 3886414c70cbSLiam Girdwood * 3887414c70cbSLiam Girdwood * Get regulator driver private data. This call can be used in the consumer 3888414c70cbSLiam Girdwood * driver context when non API regulator specific functions need to be called. 3889414c70cbSLiam Girdwood */ 3890414c70cbSLiam Girdwood void *regulator_get_drvdata(struct regulator *regulator) 3891414c70cbSLiam Girdwood { 3892414c70cbSLiam Girdwood return regulator->rdev->reg_data; 3893414c70cbSLiam Girdwood } 3894414c70cbSLiam Girdwood EXPORT_SYMBOL_GPL(regulator_get_drvdata); 3895414c70cbSLiam Girdwood 3896414c70cbSLiam Girdwood /** 3897414c70cbSLiam Girdwood * regulator_set_drvdata - set regulator driver data 3898414c70cbSLiam Girdwood * @regulator: regulator 3899414c70cbSLiam Girdwood * @data: data 3900414c70cbSLiam Girdwood */ 3901414c70cbSLiam Girdwood void regulator_set_drvdata(struct regulator *regulator, void *data) 3902414c70cbSLiam Girdwood { 3903414c70cbSLiam Girdwood regulator->rdev->reg_data = data; 3904414c70cbSLiam Girdwood } 3905414c70cbSLiam Girdwood EXPORT_SYMBOL_GPL(regulator_set_drvdata); 3906414c70cbSLiam Girdwood 3907414c70cbSLiam Girdwood /** 3908414c70cbSLiam Girdwood * regulator_get_id - get regulator ID 390969279fb9SMark Brown * @rdev: regulator 3910414c70cbSLiam Girdwood */ 3911414c70cbSLiam Girdwood int rdev_get_id(struct regulator_dev *rdev) 3912414c70cbSLiam Girdwood { 3913414c70cbSLiam Girdwood return rdev->desc->id; 3914414c70cbSLiam Girdwood } 3915414c70cbSLiam Girdwood EXPORT_SYMBOL_GPL(rdev_get_id); 3916414c70cbSLiam Girdwood 3917a5766f11SLiam Girdwood struct device *rdev_get_dev(struct regulator_dev *rdev) 3918a5766f11SLiam Girdwood { 3919a5766f11SLiam Girdwood return &rdev->dev; 3920a5766f11SLiam Girdwood } 3921a5766f11SLiam Girdwood EXPORT_SYMBOL_GPL(rdev_get_dev); 3922a5766f11SLiam Girdwood 3923a5766f11SLiam Girdwood void *regulator_get_init_drvdata(struct regulator_init_data *reg_init_data) 3924a5766f11SLiam Girdwood { 3925a5766f11SLiam Girdwood return reg_init_data->driver_data; 3926a5766f11SLiam Girdwood } 3927a5766f11SLiam Girdwood EXPORT_SYMBOL_GPL(regulator_get_init_drvdata); 3928a5766f11SLiam Girdwood 3929ba55a974SMark Brown #ifdef CONFIG_DEBUG_FS 3930ba55a974SMark Brown static ssize_t supply_map_read_file(struct file *file, char __user *user_buf, 3931ba55a974SMark Brown size_t count, loff_t *ppos) 3932ba55a974SMark Brown { 3933ba55a974SMark Brown char *buf = kmalloc(PAGE_SIZE, GFP_KERNEL); 3934ba55a974SMark Brown ssize_t len, ret = 0; 3935ba55a974SMark Brown struct regulator_map *map; 3936ba55a974SMark Brown 3937ba55a974SMark Brown if (!buf) 3938ba55a974SMark Brown return -ENOMEM; 3939ba55a974SMark Brown 3940ba55a974SMark Brown list_for_each_entry(map, ®ulator_map_list, list) { 3941ba55a974SMark Brown len = snprintf(buf + ret, PAGE_SIZE - ret, 3942ba55a974SMark Brown "%s -> %s.%s\n", 3943ba55a974SMark Brown rdev_get_name(map->regulator), map->dev_name, 3944ba55a974SMark Brown map->supply); 3945ba55a974SMark Brown if (len >= 0) 3946ba55a974SMark Brown ret += len; 3947ba55a974SMark Brown if (ret > PAGE_SIZE) { 3948ba55a974SMark Brown ret = PAGE_SIZE; 3949ba55a974SMark Brown break; 3950ba55a974SMark Brown } 3951ba55a974SMark Brown } 3952ba55a974SMark Brown 3953ba55a974SMark Brown ret = simple_read_from_buffer(user_buf, count, ppos, buf, ret); 3954ba55a974SMark Brown 3955ba55a974SMark Brown kfree(buf); 3956ba55a974SMark Brown 3957ba55a974SMark Brown return ret; 3958ba55a974SMark Brown } 395924751434SStephen Boyd #endif 3960ba55a974SMark Brown 3961ba55a974SMark Brown static const struct file_operations supply_map_fops = { 396224751434SStephen Boyd #ifdef CONFIG_DEBUG_FS 3963ba55a974SMark Brown .read = supply_map_read_file, 3964ba55a974SMark Brown .llseek = default_llseek, 3965ba55a974SMark Brown #endif 396624751434SStephen Boyd }; 3967ba55a974SMark Brown 3968414c70cbSLiam Girdwood static int __init regulator_init(void) 3969414c70cbSLiam Girdwood { 397034abbd68SMark Brown int ret; 397134abbd68SMark Brown 397234abbd68SMark Brown ret = class_register(®ulator_class); 397334abbd68SMark Brown 39741130e5b3SMark Brown debugfs_root = debugfs_create_dir("regulator", NULL); 397524751434SStephen Boyd if (!debugfs_root) 39761130e5b3SMark Brown pr_warn("regulator: Failed to create debugfs directory\n"); 3977ba55a974SMark Brown 3978f4d562c6SMark Brown debugfs_create_file("supply_map", 0444, debugfs_root, NULL, 3979f4d562c6SMark Brown &supply_map_fops); 39801130e5b3SMark Brown 398134abbd68SMark Brown regulator_dummy_init(); 398234abbd68SMark Brown 398334abbd68SMark Brown return ret; 3984414c70cbSLiam Girdwood } 3985414c70cbSLiam Girdwood 3986414c70cbSLiam Girdwood /* init early to allow our consumers to complete system booting */ 3987414c70cbSLiam Girdwood core_initcall(regulator_init); 3988ca725561SMark Brown 3989ca725561SMark Brown static int __init regulator_init_complete(void) 3990ca725561SMark Brown { 3991ca725561SMark Brown struct regulator_dev *rdev; 3992ca725561SMark Brown struct regulator_ops *ops; 3993ca725561SMark Brown struct regulation_constraints *c; 3994ca725561SMark Brown int enabled, ret; 3995ca725561SMark Brown 399686f5fcfcSMark Brown /* 399786f5fcfcSMark Brown * Since DT doesn't provide an idiomatic mechanism for 399886f5fcfcSMark Brown * enabling full constraints and since it's much more natural 399986f5fcfcSMark Brown * with DT to provide them just assume that a DT enabled 400086f5fcfcSMark Brown * system has full constraints. 400186f5fcfcSMark Brown */ 400286f5fcfcSMark Brown if (of_have_populated_dt()) 400386f5fcfcSMark Brown has_full_constraints = true; 400486f5fcfcSMark Brown 4005ca725561SMark Brown mutex_lock(®ulator_list_mutex); 4006ca725561SMark Brown 4007ca725561SMark Brown /* If we have a full configuration then disable any regulators 4008ca725561SMark Brown * which are not in use or always_on. This will become the 4009ca725561SMark Brown * default behaviour in the future. 4010ca725561SMark Brown */ 4011ca725561SMark Brown list_for_each_entry(rdev, ®ulator_list, list) { 4012ca725561SMark Brown ops = rdev->desc->ops; 4013ca725561SMark Brown c = rdev->constraints; 4014ca725561SMark Brown 4015f25e0b4fSMark Brown if (!ops->disable || (c && c->always_on)) 4016ca725561SMark Brown continue; 4017ca725561SMark Brown 4018ca725561SMark Brown mutex_lock(&rdev->mutex); 4019ca725561SMark Brown 4020ca725561SMark Brown if (rdev->use_count) 4021ca725561SMark Brown goto unlock; 4022ca725561SMark Brown 4023ca725561SMark Brown /* If we can't read the status assume it's on. */ 4024ca725561SMark Brown if (ops->is_enabled) 4025ca725561SMark Brown enabled = ops->is_enabled(rdev); 4026ca725561SMark Brown else 4027ca725561SMark Brown enabled = 1; 4028ca725561SMark Brown 4029ca725561SMark Brown if (!enabled) 4030ca725561SMark Brown goto unlock; 4031ca725561SMark Brown 4032ca725561SMark Brown if (has_full_constraints) { 4033ca725561SMark Brown /* We log since this may kill the system if it 4034ca725561SMark Brown * goes wrong. */ 40355da84fd9SJoe Perches rdev_info(rdev, "disabling\n"); 4036ca725561SMark Brown ret = ops->disable(rdev); 4037ca725561SMark Brown if (ret != 0) { 40385da84fd9SJoe Perches rdev_err(rdev, "couldn't disable: %d\n", ret); 4039ca725561SMark Brown } 4040ca725561SMark Brown } else { 4041ca725561SMark Brown /* The intention is that in future we will 4042ca725561SMark Brown * assume that full constraints are provided 4043ca725561SMark Brown * so warn even if we aren't going to do 4044ca725561SMark Brown * anything here. 4045ca725561SMark Brown */ 40465da84fd9SJoe Perches rdev_warn(rdev, "incomplete constraints, leaving on\n"); 4047ca725561SMark Brown } 4048ca725561SMark Brown 4049ca725561SMark Brown unlock: 4050ca725561SMark Brown mutex_unlock(&rdev->mutex); 4051ca725561SMark Brown } 4052ca725561SMark Brown 4053ca725561SMark Brown mutex_unlock(®ulator_list_mutex); 4054ca725561SMark Brown 4055ca725561SMark Brown return 0; 4056ca725561SMark Brown } 4057ca725561SMark Brown late_initcall(regulator_init_complete); 4058