1414c70cbSLiam Girdwood /* 2414c70cbSLiam Girdwood * core.c -- Voltage/Current Regulator framework. 3414c70cbSLiam Girdwood * 4414c70cbSLiam Girdwood * Copyright 2007, 2008 Wolfson Microelectronics PLC. 5a5766f11SLiam Girdwood * Copyright 2008 SlimLogic Ltd. 6414c70cbSLiam Girdwood * 7a5766f11SLiam Girdwood * Author: Liam Girdwood <lrg@slimlogic.co.uk> 8414c70cbSLiam Girdwood * 9414c70cbSLiam Girdwood * This program is free software; you can redistribute it and/or modify it 10414c70cbSLiam Girdwood * under the terms of the GNU General Public License as published by the 11414c70cbSLiam Girdwood * Free Software Foundation; either version 2 of the License, or (at your 12414c70cbSLiam Girdwood * option) any later version. 13414c70cbSLiam Girdwood * 14414c70cbSLiam Girdwood */ 15414c70cbSLiam Girdwood 16414c70cbSLiam Girdwood #include <linux/kernel.h> 17414c70cbSLiam Girdwood #include <linux/init.h> 181130e5b3SMark Brown #include <linux/debugfs.h> 19414c70cbSLiam Girdwood #include <linux/device.h> 205a0e3ad6STejun Heo #include <linux/slab.h> 21f21e0e81SMark Brown #include <linux/async.h> 22414c70cbSLiam Girdwood #include <linux/err.h> 23414c70cbSLiam Girdwood #include <linux/mutex.h> 24414c70cbSLiam Girdwood #include <linux/suspend.h> 2531aae2beSMark Brown #include <linux/delay.h> 2665f73508SMark Brown #include <linux/gpio.h> 27778b28b4SRussell King #include <linux/gpio/consumer.h> 2869511a45SRajendra Nayak #include <linux/of.h> 2965b19ce6SMark Brown #include <linux/regmap.h> 3069511a45SRajendra Nayak #include <linux/regulator/of_regulator.h> 31414c70cbSLiam Girdwood #include <linux/regulator/consumer.h> 32414c70cbSLiam Girdwood #include <linux/regulator/driver.h> 33414c70cbSLiam Girdwood #include <linux/regulator/machine.h> 3465602c32SPaul Gortmaker #include <linux/module.h> 35414c70cbSLiam Girdwood 3602fa3ec0SMark Brown #define CREATE_TRACE_POINTS 3702fa3ec0SMark Brown #include <trace/events/regulator.h> 3802fa3ec0SMark Brown 3934abbd68SMark Brown #include "dummy.h" 400cdfcc0fSMark Brown #include "internal.h" 4134abbd68SMark Brown 427d51a0dbSMark Brown #define rdev_crit(rdev, fmt, ...) \ 437d51a0dbSMark Brown pr_crit("%s: " fmt, rdev_get_name(rdev), ##__VA_ARGS__) 445da84fd9SJoe Perches #define rdev_err(rdev, fmt, ...) \ 455da84fd9SJoe Perches pr_err("%s: " fmt, rdev_get_name(rdev), ##__VA_ARGS__) 465da84fd9SJoe Perches #define rdev_warn(rdev, fmt, ...) \ 475da84fd9SJoe Perches pr_warn("%s: " fmt, rdev_get_name(rdev), ##__VA_ARGS__) 485da84fd9SJoe Perches #define rdev_info(rdev, fmt, ...) \ 495da84fd9SJoe Perches pr_info("%s: " fmt, rdev_get_name(rdev), ##__VA_ARGS__) 505da84fd9SJoe Perches #define rdev_dbg(rdev, fmt, ...) \ 515da84fd9SJoe Perches pr_debug("%s: " fmt, rdev_get_name(rdev), ##__VA_ARGS__) 525da84fd9SJoe Perches 53414c70cbSLiam Girdwood static DEFINE_MUTEX(regulator_list_mutex); 54414c70cbSLiam Girdwood static LIST_HEAD(regulator_map_list); 55f19b00daSKim, Milo static LIST_HEAD(regulator_ena_gpio_list); 56a06ccd9cSCharles Keepax static LIST_HEAD(regulator_supply_alias_list); 5721cf891aSMark Brown static bool has_full_constraints; 58414c70cbSLiam Girdwood 591130e5b3SMark Brown static struct dentry *debugfs_root; 601130e5b3SMark Brown 6185f3b431STomeu Vizoso static struct class regulator_class; 6285f3b431STomeu Vizoso 638dc5390dSMark Brown /* 64414c70cbSLiam Girdwood * struct regulator_map 65414c70cbSLiam Girdwood * 66414c70cbSLiam Girdwood * Used to provide symbolic supply names to devices. 67414c70cbSLiam Girdwood */ 68414c70cbSLiam Girdwood struct regulator_map { 69414c70cbSLiam Girdwood struct list_head list; 7040f9244fSMark Brown const char *dev_name; /* The dev_name() for the consumer */ 71414c70cbSLiam Girdwood const char *supply; 72a5766f11SLiam Girdwood struct regulator_dev *regulator; 73414c70cbSLiam Girdwood }; 74414c70cbSLiam Girdwood 75414c70cbSLiam Girdwood /* 76f19b00daSKim, Milo * struct regulator_enable_gpio 77f19b00daSKim, Milo * 78f19b00daSKim, Milo * Management for shared enable GPIO pin 79f19b00daSKim, Milo */ 80f19b00daSKim, Milo struct regulator_enable_gpio { 81f19b00daSKim, Milo struct list_head list; 82778b28b4SRussell King struct gpio_desc *gpiod; 83f19b00daSKim, Milo u32 enable_count; /* a number of enabled shared GPIO */ 84f19b00daSKim, Milo u32 request_count; /* a number of requested shared GPIO */ 85f19b00daSKim, Milo unsigned int ena_gpio_invert:1; 86f19b00daSKim, Milo }; 87f19b00daSKim, Milo 88a06ccd9cSCharles Keepax /* 89a06ccd9cSCharles Keepax * struct regulator_supply_alias 90a06ccd9cSCharles Keepax * 91a06ccd9cSCharles Keepax * Used to map lookups for a supply onto an alternative device. 92a06ccd9cSCharles Keepax */ 93a06ccd9cSCharles Keepax struct regulator_supply_alias { 94a06ccd9cSCharles Keepax struct list_head list; 95a06ccd9cSCharles Keepax struct device *src_dev; 96a06ccd9cSCharles Keepax const char *src_supply; 97a06ccd9cSCharles Keepax struct device *alias_dev; 98a06ccd9cSCharles Keepax const char *alias_supply; 99a06ccd9cSCharles Keepax }; 100a06ccd9cSCharles Keepax 101414c70cbSLiam Girdwood static int _regulator_is_enabled(struct regulator_dev *rdev); 1023801b86aSMark Brown static int _regulator_disable(struct regulator_dev *rdev); 103414c70cbSLiam Girdwood static int _regulator_get_voltage(struct regulator_dev *rdev); 104414c70cbSLiam Girdwood static int _regulator_get_current_limit(struct regulator_dev *rdev); 105414c70cbSLiam Girdwood static unsigned int _regulator_get_mode(struct regulator_dev *rdev); 1067179569aSHeiko Stübner static int _notifier_call_chain(struct regulator_dev *rdev, 107414c70cbSLiam Girdwood unsigned long event, void *data); 10875790251SMark Brown static int _regulator_do_set_voltage(struct regulator_dev *rdev, 10975790251SMark Brown int min_uV, int max_uV); 1103801b86aSMark Brown static struct regulator *create_regulator(struct regulator_dev *rdev, 1113801b86aSMark Brown struct device *dev, 1123801b86aSMark Brown const char *supply_name); 11336a1f1b6SJavier Martinez Canillas static void _regulator_put(struct regulator *regulator); 114414c70cbSLiam Girdwood 115609ca5f3SMark Brown static struct regulator_dev *dev_to_rdev(struct device *dev) 116609ca5f3SMark Brown { 117609ca5f3SMark Brown return container_of(dev, struct regulator_dev, dev); 118609ca5f3SMark Brown } 119414c70cbSLiam Girdwood 1201083c393SMark Brown static const char *rdev_get_name(struct regulator_dev *rdev) 1211083c393SMark Brown { 1221083c393SMark Brown if (rdev->constraints && rdev->constraints->name) 1231083c393SMark Brown return rdev->constraints->name; 1241083c393SMark Brown else if (rdev->desc->name) 1251083c393SMark Brown return rdev->desc->name; 1261083c393SMark Brown else 1271083c393SMark Brown return ""; 1281083c393SMark Brown } 1291083c393SMark Brown 13087b28417SMark Brown static bool have_full_constraints(void) 13187b28417SMark Brown { 13275bc9641SMark Brown return has_full_constraints || of_have_populated_dt(); 13387b28417SMark Brown } 13487b28417SMark Brown 1358a34e979SWEN Pingbo static bool regulator_ops_is_valid(struct regulator_dev *rdev, int ops) 1368a34e979SWEN Pingbo { 1378a34e979SWEN Pingbo if (!rdev->constraints) { 1388a34e979SWEN Pingbo rdev_err(rdev, "no constraints\n"); 1398a34e979SWEN Pingbo return false; 1408a34e979SWEN Pingbo } 1418a34e979SWEN Pingbo 1428a34e979SWEN Pingbo if (rdev->constraints->valid_ops_mask & ops) 1438a34e979SWEN Pingbo return true; 1448a34e979SWEN Pingbo 1458a34e979SWEN Pingbo return false; 1468a34e979SWEN Pingbo } 1478a34e979SWEN Pingbo 14870a7fb80SThierry Reding static inline struct regulator_dev *rdev_get_supply(struct regulator_dev *rdev) 14970a7fb80SThierry Reding { 15070a7fb80SThierry Reding if (rdev && rdev->supply) 15170a7fb80SThierry Reding return rdev->supply->rdev; 15270a7fb80SThierry Reding 15370a7fb80SThierry Reding return NULL; 15470a7fb80SThierry Reding } 15570a7fb80SThierry Reding 15669511a45SRajendra Nayak /** 1579f01cd4aSSascha Hauer * regulator_lock_supply - lock a regulator and its supplies 1589f01cd4aSSascha Hauer * @rdev: regulator source 1599f01cd4aSSascha Hauer */ 1609f01cd4aSSascha Hauer static void regulator_lock_supply(struct regulator_dev *rdev) 1619f01cd4aSSascha Hauer { 162fa731ac7SArnd Bergmann int i; 1639f01cd4aSSascha Hauer 16470a7fb80SThierry Reding for (i = 0; rdev; rdev = rdev_get_supply(rdev), i++) 165fa731ac7SArnd Bergmann mutex_lock_nested(&rdev->mutex, i); 1669f01cd4aSSascha Hauer } 1679f01cd4aSSascha Hauer 1689f01cd4aSSascha Hauer /** 1699f01cd4aSSascha Hauer * regulator_unlock_supply - unlock a regulator and its supplies 1709f01cd4aSSascha Hauer * @rdev: regulator source 1719f01cd4aSSascha Hauer */ 1729f01cd4aSSascha Hauer static void regulator_unlock_supply(struct regulator_dev *rdev) 1739f01cd4aSSascha Hauer { 1749f01cd4aSSascha Hauer struct regulator *supply; 1759f01cd4aSSascha Hauer 1769f01cd4aSSascha Hauer while (1) { 1779f01cd4aSSascha Hauer mutex_unlock(&rdev->mutex); 1789f01cd4aSSascha Hauer supply = rdev->supply; 1799f01cd4aSSascha Hauer 1809f01cd4aSSascha Hauer if (!rdev->supply) 1819f01cd4aSSascha Hauer return; 1829f01cd4aSSascha Hauer 1839f01cd4aSSascha Hauer rdev = supply->rdev; 1849f01cd4aSSascha Hauer } 1859f01cd4aSSascha Hauer } 1869f01cd4aSSascha Hauer 1879f01cd4aSSascha Hauer /** 18869511a45SRajendra Nayak * of_get_regulator - get a regulator device node based on supply name 18969511a45SRajendra Nayak * @dev: Device pointer for the consumer (of regulator) device 19069511a45SRajendra Nayak * @supply: regulator supply name 19169511a45SRajendra Nayak * 19269511a45SRajendra Nayak * Extract the regulator device node corresponding to the supply name. 193167d41dcSMaxime Ripard * returns the device node corresponding to the regulator if found, else 19469511a45SRajendra Nayak * returns NULL. 19569511a45SRajendra Nayak */ 19669511a45SRajendra Nayak static struct device_node *of_get_regulator(struct device *dev, const char *supply) 19769511a45SRajendra Nayak { 19869511a45SRajendra Nayak struct device_node *regnode = NULL; 19969511a45SRajendra Nayak char prop_name[32]; /* 32 is max size of property name */ 20069511a45SRajendra Nayak 20169511a45SRajendra Nayak dev_dbg(dev, "Looking up %s-supply from device tree\n", supply); 20269511a45SRajendra Nayak 20369511a45SRajendra Nayak snprintf(prop_name, 32, "%s-supply", supply); 20469511a45SRajendra Nayak regnode = of_parse_phandle(dev->of_node, prop_name, 0); 20569511a45SRajendra Nayak 20669511a45SRajendra Nayak if (!regnode) { 207b2661e98SDavid Lechner dev_dbg(dev, "Looking up %s property in node %s failed\n", 20869511a45SRajendra Nayak prop_name, dev->of_node->full_name); 20969511a45SRajendra Nayak return NULL; 21069511a45SRajendra Nayak } 21169511a45SRajendra Nayak return regnode; 21269511a45SRajendra Nayak } 21369511a45SRajendra Nayak 214414c70cbSLiam Girdwood /* Platform voltage constraint check */ 215414c70cbSLiam Girdwood static int regulator_check_voltage(struct regulator_dev *rdev, 216414c70cbSLiam Girdwood int *min_uV, int *max_uV) 217414c70cbSLiam Girdwood { 218414c70cbSLiam Girdwood BUG_ON(*min_uV > *max_uV); 219414c70cbSLiam Girdwood 2208a34e979SWEN Pingbo if (!regulator_ops_is_valid(rdev, REGULATOR_CHANGE_VOLTAGE)) { 2217ebcf26cSStephen Boyd rdev_err(rdev, "voltage operation not allowed\n"); 222414c70cbSLiam Girdwood return -EPERM; 223414c70cbSLiam Girdwood } 224414c70cbSLiam Girdwood 225414c70cbSLiam Girdwood if (*max_uV > rdev->constraints->max_uV) 226414c70cbSLiam Girdwood *max_uV = rdev->constraints->max_uV; 227414c70cbSLiam Girdwood if (*min_uV < rdev->constraints->min_uV) 228414c70cbSLiam Girdwood *min_uV = rdev->constraints->min_uV; 229414c70cbSLiam Girdwood 23089f425edSMark Brown if (*min_uV > *max_uV) { 23189f425edSMark Brown rdev_err(rdev, "unsupportable voltage range: %d-%duV\n", 23254abd335SMark Brown *min_uV, *max_uV); 233414c70cbSLiam Girdwood return -EINVAL; 23489f425edSMark Brown } 235414c70cbSLiam Girdwood 236414c70cbSLiam Girdwood return 0; 237414c70cbSLiam Girdwood } 238414c70cbSLiam Girdwood 23905fda3b1SThomas Petazzoni /* Make sure we select a voltage that suits the needs of all 24005fda3b1SThomas Petazzoni * regulator consumers 24105fda3b1SThomas Petazzoni */ 24205fda3b1SThomas Petazzoni static int regulator_check_consumers(struct regulator_dev *rdev, 24305fda3b1SThomas Petazzoni int *min_uV, int *max_uV) 24405fda3b1SThomas Petazzoni { 24505fda3b1SThomas Petazzoni struct regulator *regulator; 24605fda3b1SThomas Petazzoni 24705fda3b1SThomas Petazzoni list_for_each_entry(regulator, &rdev->consumer_list, list) { 2484aa922c0SMark Brown /* 2494aa922c0SMark Brown * Assume consumers that didn't say anything are OK 2504aa922c0SMark Brown * with anything in the constraint range. 2514aa922c0SMark Brown */ 2524aa922c0SMark Brown if (!regulator->min_uV && !regulator->max_uV) 2534aa922c0SMark Brown continue; 2544aa922c0SMark Brown 25505fda3b1SThomas Petazzoni if (*max_uV > regulator->max_uV) 25605fda3b1SThomas Petazzoni *max_uV = regulator->max_uV; 25705fda3b1SThomas Petazzoni if (*min_uV < regulator->min_uV) 25805fda3b1SThomas Petazzoni *min_uV = regulator->min_uV; 25905fda3b1SThomas Petazzoni } 26005fda3b1SThomas Petazzoni 261dd8004afSMark Brown if (*min_uV > *max_uV) { 2629c7b4e8aSRuss Dill rdev_err(rdev, "Restricting voltage, %u-%uuV\n", 2639c7b4e8aSRuss Dill *min_uV, *max_uV); 26405fda3b1SThomas Petazzoni return -EINVAL; 265dd8004afSMark Brown } 26605fda3b1SThomas Petazzoni 26705fda3b1SThomas Petazzoni return 0; 26805fda3b1SThomas Petazzoni } 26905fda3b1SThomas Petazzoni 270414c70cbSLiam Girdwood /* current constraint check */ 271414c70cbSLiam Girdwood static int regulator_check_current_limit(struct regulator_dev *rdev, 272414c70cbSLiam Girdwood int *min_uA, int *max_uA) 273414c70cbSLiam Girdwood { 274414c70cbSLiam Girdwood BUG_ON(*min_uA > *max_uA); 275414c70cbSLiam Girdwood 2768a34e979SWEN Pingbo if (!regulator_ops_is_valid(rdev, REGULATOR_CHANGE_CURRENT)) { 2777ebcf26cSStephen Boyd rdev_err(rdev, "current operation not allowed\n"); 278414c70cbSLiam Girdwood return -EPERM; 279414c70cbSLiam Girdwood } 280414c70cbSLiam Girdwood 281414c70cbSLiam Girdwood if (*max_uA > rdev->constraints->max_uA) 282414c70cbSLiam Girdwood *max_uA = rdev->constraints->max_uA; 283414c70cbSLiam Girdwood if (*min_uA < rdev->constraints->min_uA) 284414c70cbSLiam Girdwood *min_uA = rdev->constraints->min_uA; 285414c70cbSLiam Girdwood 28689f425edSMark Brown if (*min_uA > *max_uA) { 28789f425edSMark Brown rdev_err(rdev, "unsupportable current range: %d-%duA\n", 28854abd335SMark Brown *min_uA, *max_uA); 289414c70cbSLiam Girdwood return -EINVAL; 29089f425edSMark Brown } 291414c70cbSLiam Girdwood 292414c70cbSLiam Girdwood return 0; 293414c70cbSLiam Girdwood } 294414c70cbSLiam Girdwood 295414c70cbSLiam Girdwood /* operating mode constraint check */ 296109c75afSCharles Keepax static int regulator_mode_constrain(struct regulator_dev *rdev, 297109c75afSCharles Keepax unsigned int *mode) 298414c70cbSLiam Girdwood { 2992c608234SMark Brown switch (*mode) { 300e573520bSDavid Brownell case REGULATOR_MODE_FAST: 301e573520bSDavid Brownell case REGULATOR_MODE_NORMAL: 302e573520bSDavid Brownell case REGULATOR_MODE_IDLE: 303e573520bSDavid Brownell case REGULATOR_MODE_STANDBY: 304e573520bSDavid Brownell break; 305e573520bSDavid Brownell default: 30689f425edSMark Brown rdev_err(rdev, "invalid mode %x specified\n", *mode); 307e573520bSDavid Brownell return -EINVAL; 308e573520bSDavid Brownell } 309e573520bSDavid Brownell 3108a34e979SWEN Pingbo if (!regulator_ops_is_valid(rdev, REGULATOR_CHANGE_MODE)) { 3117ebcf26cSStephen Boyd rdev_err(rdev, "mode operation not allowed\n"); 312414c70cbSLiam Girdwood return -EPERM; 313414c70cbSLiam Girdwood } 3142c608234SMark Brown 3152c608234SMark Brown /* The modes are bitmasks, the most power hungry modes having 3162c608234SMark Brown * the lowest values. If the requested mode isn't supported 3172c608234SMark Brown * try higher modes. */ 3182c608234SMark Brown while (*mode) { 3192c608234SMark Brown if (rdev->constraints->valid_modes_mask & *mode) 320414c70cbSLiam Girdwood return 0; 3212c608234SMark Brown *mode /= 2; 3222c608234SMark Brown } 3232c608234SMark Brown 3242c608234SMark Brown return -EINVAL; 325414c70cbSLiam Girdwood } 326414c70cbSLiam Girdwood 327414c70cbSLiam Girdwood static ssize_t regulator_uV_show(struct device *dev, 328414c70cbSLiam Girdwood struct device_attribute *attr, char *buf) 329414c70cbSLiam Girdwood { 330a5766f11SLiam Girdwood struct regulator_dev *rdev = dev_get_drvdata(dev); 331414c70cbSLiam Girdwood ssize_t ret; 332414c70cbSLiam Girdwood 333414c70cbSLiam Girdwood mutex_lock(&rdev->mutex); 334414c70cbSLiam Girdwood ret = sprintf(buf, "%d\n", _regulator_get_voltage(rdev)); 335414c70cbSLiam Girdwood mutex_unlock(&rdev->mutex); 336414c70cbSLiam Girdwood 337414c70cbSLiam Girdwood return ret; 338414c70cbSLiam Girdwood } 3397ad68e2fSDavid Brownell static DEVICE_ATTR(microvolts, 0444, regulator_uV_show, NULL); 340414c70cbSLiam Girdwood 341414c70cbSLiam Girdwood static ssize_t regulator_uA_show(struct device *dev, 342414c70cbSLiam Girdwood struct device_attribute *attr, char *buf) 343414c70cbSLiam Girdwood { 344a5766f11SLiam Girdwood struct regulator_dev *rdev = dev_get_drvdata(dev); 345414c70cbSLiam Girdwood 346414c70cbSLiam Girdwood return sprintf(buf, "%d\n", _regulator_get_current_limit(rdev)); 347414c70cbSLiam Girdwood } 3487ad68e2fSDavid Brownell static DEVICE_ATTR(microamps, 0444, regulator_uA_show, NULL); 349414c70cbSLiam Girdwood 350587cea27SGreg Kroah-Hartman static ssize_t name_show(struct device *dev, struct device_attribute *attr, 351587cea27SGreg Kroah-Hartman char *buf) 352bc558a60SMark Brown { 353bc558a60SMark Brown struct regulator_dev *rdev = dev_get_drvdata(dev); 354bc558a60SMark Brown 3551083c393SMark Brown return sprintf(buf, "%s\n", rdev_get_name(rdev)); 356bc558a60SMark Brown } 357587cea27SGreg Kroah-Hartman static DEVICE_ATTR_RO(name); 358bc558a60SMark Brown 3594fca9545SDavid Brownell static ssize_t regulator_print_opmode(char *buf, int mode) 360414c70cbSLiam Girdwood { 361414c70cbSLiam Girdwood switch (mode) { 362414c70cbSLiam Girdwood case REGULATOR_MODE_FAST: 363414c70cbSLiam Girdwood return sprintf(buf, "fast\n"); 364414c70cbSLiam Girdwood case REGULATOR_MODE_NORMAL: 365414c70cbSLiam Girdwood return sprintf(buf, "normal\n"); 366414c70cbSLiam Girdwood case REGULATOR_MODE_IDLE: 367414c70cbSLiam Girdwood return sprintf(buf, "idle\n"); 368414c70cbSLiam Girdwood case REGULATOR_MODE_STANDBY: 369414c70cbSLiam Girdwood return sprintf(buf, "standby\n"); 370414c70cbSLiam Girdwood } 371414c70cbSLiam Girdwood return sprintf(buf, "unknown\n"); 372414c70cbSLiam Girdwood } 373414c70cbSLiam Girdwood 3744fca9545SDavid Brownell static ssize_t regulator_opmode_show(struct device *dev, 375414c70cbSLiam Girdwood struct device_attribute *attr, char *buf) 376414c70cbSLiam Girdwood { 377a5766f11SLiam Girdwood struct regulator_dev *rdev = dev_get_drvdata(dev); 378414c70cbSLiam Girdwood 3794fca9545SDavid Brownell return regulator_print_opmode(buf, _regulator_get_mode(rdev)); 3804fca9545SDavid Brownell } 3817ad68e2fSDavid Brownell static DEVICE_ATTR(opmode, 0444, regulator_opmode_show, NULL); 3824fca9545SDavid Brownell 3834fca9545SDavid Brownell static ssize_t regulator_print_state(char *buf, int state) 3844fca9545SDavid Brownell { 385414c70cbSLiam Girdwood if (state > 0) 386414c70cbSLiam Girdwood return sprintf(buf, "enabled\n"); 387414c70cbSLiam Girdwood else if (state == 0) 388414c70cbSLiam Girdwood return sprintf(buf, "disabled\n"); 389414c70cbSLiam Girdwood else 390414c70cbSLiam Girdwood return sprintf(buf, "unknown\n"); 391414c70cbSLiam Girdwood } 392414c70cbSLiam Girdwood 3934fca9545SDavid Brownell static ssize_t regulator_state_show(struct device *dev, 3944fca9545SDavid Brownell struct device_attribute *attr, char *buf) 3954fca9545SDavid Brownell { 3964fca9545SDavid Brownell struct regulator_dev *rdev = dev_get_drvdata(dev); 3979332546fSMark Brown ssize_t ret; 3984fca9545SDavid Brownell 3999332546fSMark Brown mutex_lock(&rdev->mutex); 4009332546fSMark Brown ret = regulator_print_state(buf, _regulator_is_enabled(rdev)); 4019332546fSMark Brown mutex_unlock(&rdev->mutex); 4029332546fSMark Brown 4039332546fSMark Brown return ret; 4044fca9545SDavid Brownell } 4057ad68e2fSDavid Brownell static DEVICE_ATTR(state, 0444, regulator_state_show, NULL); 4064fca9545SDavid Brownell 407853116a1SDavid Brownell static ssize_t regulator_status_show(struct device *dev, 408853116a1SDavid Brownell struct device_attribute *attr, char *buf) 409853116a1SDavid Brownell { 410853116a1SDavid Brownell struct regulator_dev *rdev = dev_get_drvdata(dev); 411853116a1SDavid Brownell int status; 412853116a1SDavid Brownell char *label; 413853116a1SDavid Brownell 414853116a1SDavid Brownell status = rdev->desc->ops->get_status(rdev); 415853116a1SDavid Brownell if (status < 0) 416853116a1SDavid Brownell return status; 417853116a1SDavid Brownell 418853116a1SDavid Brownell switch (status) { 419853116a1SDavid Brownell case REGULATOR_STATUS_OFF: 420853116a1SDavid Brownell label = "off"; 421853116a1SDavid Brownell break; 422853116a1SDavid Brownell case REGULATOR_STATUS_ON: 423853116a1SDavid Brownell label = "on"; 424853116a1SDavid Brownell break; 425853116a1SDavid Brownell case REGULATOR_STATUS_ERROR: 426853116a1SDavid Brownell label = "error"; 427853116a1SDavid Brownell break; 428853116a1SDavid Brownell case REGULATOR_STATUS_FAST: 429853116a1SDavid Brownell label = "fast"; 430853116a1SDavid Brownell break; 431853116a1SDavid Brownell case REGULATOR_STATUS_NORMAL: 432853116a1SDavid Brownell label = "normal"; 433853116a1SDavid Brownell break; 434853116a1SDavid Brownell case REGULATOR_STATUS_IDLE: 435853116a1SDavid Brownell label = "idle"; 436853116a1SDavid Brownell break; 437853116a1SDavid Brownell case REGULATOR_STATUS_STANDBY: 438853116a1SDavid Brownell label = "standby"; 439853116a1SDavid Brownell break; 440f59c8f9fSMark Brown case REGULATOR_STATUS_BYPASS: 441f59c8f9fSMark Brown label = "bypass"; 442f59c8f9fSMark Brown break; 4431beaf762SKrystian Garbaciak case REGULATOR_STATUS_UNDEFINED: 4441beaf762SKrystian Garbaciak label = "undefined"; 4451beaf762SKrystian Garbaciak break; 446853116a1SDavid Brownell default: 447853116a1SDavid Brownell return -ERANGE; 448853116a1SDavid Brownell } 449853116a1SDavid Brownell 450853116a1SDavid Brownell return sprintf(buf, "%s\n", label); 451853116a1SDavid Brownell } 452853116a1SDavid Brownell static DEVICE_ATTR(status, 0444, regulator_status_show, NULL); 453853116a1SDavid Brownell 454414c70cbSLiam Girdwood static ssize_t regulator_min_uA_show(struct device *dev, 455414c70cbSLiam Girdwood struct device_attribute *attr, char *buf) 456414c70cbSLiam Girdwood { 457a5766f11SLiam Girdwood struct regulator_dev *rdev = dev_get_drvdata(dev); 458414c70cbSLiam Girdwood 459414c70cbSLiam Girdwood if (!rdev->constraints) 460414c70cbSLiam Girdwood return sprintf(buf, "constraint not defined\n"); 461414c70cbSLiam Girdwood 462414c70cbSLiam Girdwood return sprintf(buf, "%d\n", rdev->constraints->min_uA); 463414c70cbSLiam Girdwood } 4647ad68e2fSDavid Brownell static DEVICE_ATTR(min_microamps, 0444, regulator_min_uA_show, NULL); 465414c70cbSLiam Girdwood 466414c70cbSLiam Girdwood static ssize_t regulator_max_uA_show(struct device *dev, 467414c70cbSLiam Girdwood struct device_attribute *attr, char *buf) 468414c70cbSLiam Girdwood { 469a5766f11SLiam Girdwood struct regulator_dev *rdev = dev_get_drvdata(dev); 470414c70cbSLiam Girdwood 471414c70cbSLiam Girdwood if (!rdev->constraints) 472414c70cbSLiam Girdwood return sprintf(buf, "constraint not defined\n"); 473414c70cbSLiam Girdwood 474414c70cbSLiam Girdwood return sprintf(buf, "%d\n", rdev->constraints->max_uA); 475414c70cbSLiam Girdwood } 4767ad68e2fSDavid Brownell static DEVICE_ATTR(max_microamps, 0444, regulator_max_uA_show, NULL); 477414c70cbSLiam Girdwood 478414c70cbSLiam Girdwood static ssize_t regulator_min_uV_show(struct device *dev, 479414c70cbSLiam Girdwood struct device_attribute *attr, char *buf) 480414c70cbSLiam Girdwood { 481a5766f11SLiam Girdwood struct regulator_dev *rdev = dev_get_drvdata(dev); 482414c70cbSLiam Girdwood 483414c70cbSLiam Girdwood if (!rdev->constraints) 484414c70cbSLiam Girdwood return sprintf(buf, "constraint not defined\n"); 485414c70cbSLiam Girdwood 486414c70cbSLiam Girdwood return sprintf(buf, "%d\n", rdev->constraints->min_uV); 487414c70cbSLiam Girdwood } 4887ad68e2fSDavid Brownell static DEVICE_ATTR(min_microvolts, 0444, regulator_min_uV_show, NULL); 489414c70cbSLiam Girdwood 490414c70cbSLiam Girdwood static ssize_t regulator_max_uV_show(struct device *dev, 491414c70cbSLiam Girdwood struct device_attribute *attr, char *buf) 492414c70cbSLiam Girdwood { 493a5766f11SLiam Girdwood struct regulator_dev *rdev = dev_get_drvdata(dev); 494414c70cbSLiam Girdwood 495414c70cbSLiam Girdwood if (!rdev->constraints) 496414c70cbSLiam Girdwood return sprintf(buf, "constraint not defined\n"); 497414c70cbSLiam Girdwood 498414c70cbSLiam Girdwood return sprintf(buf, "%d\n", rdev->constraints->max_uV); 499414c70cbSLiam Girdwood } 5007ad68e2fSDavid Brownell static DEVICE_ATTR(max_microvolts, 0444, regulator_max_uV_show, NULL); 501414c70cbSLiam Girdwood 502414c70cbSLiam Girdwood static ssize_t regulator_total_uA_show(struct device *dev, 503414c70cbSLiam Girdwood struct device_attribute *attr, char *buf) 504414c70cbSLiam Girdwood { 505a5766f11SLiam Girdwood struct regulator_dev *rdev = dev_get_drvdata(dev); 506414c70cbSLiam Girdwood struct regulator *regulator; 507414c70cbSLiam Girdwood int uA = 0; 508414c70cbSLiam Girdwood 509414c70cbSLiam Girdwood mutex_lock(&rdev->mutex); 510414c70cbSLiam Girdwood list_for_each_entry(regulator, &rdev->consumer_list, list) 511414c70cbSLiam Girdwood uA += regulator->uA_load; 512414c70cbSLiam Girdwood mutex_unlock(&rdev->mutex); 513414c70cbSLiam Girdwood return sprintf(buf, "%d\n", uA); 514414c70cbSLiam Girdwood } 5157ad68e2fSDavid Brownell static DEVICE_ATTR(requested_microamps, 0444, regulator_total_uA_show, NULL); 516414c70cbSLiam Girdwood 517587cea27SGreg Kroah-Hartman static ssize_t num_users_show(struct device *dev, struct device_attribute *attr, 518587cea27SGreg Kroah-Hartman char *buf) 519414c70cbSLiam Girdwood { 520a5766f11SLiam Girdwood struct regulator_dev *rdev = dev_get_drvdata(dev); 521414c70cbSLiam Girdwood return sprintf(buf, "%d\n", rdev->use_count); 522414c70cbSLiam Girdwood } 523587cea27SGreg Kroah-Hartman static DEVICE_ATTR_RO(num_users); 524414c70cbSLiam Girdwood 525587cea27SGreg Kroah-Hartman static ssize_t type_show(struct device *dev, struct device_attribute *attr, 526587cea27SGreg Kroah-Hartman char *buf) 527414c70cbSLiam Girdwood { 528a5766f11SLiam Girdwood struct regulator_dev *rdev = dev_get_drvdata(dev); 529414c70cbSLiam Girdwood 530414c70cbSLiam Girdwood switch (rdev->desc->type) { 531414c70cbSLiam Girdwood case REGULATOR_VOLTAGE: 532414c70cbSLiam Girdwood return sprintf(buf, "voltage\n"); 533414c70cbSLiam Girdwood case REGULATOR_CURRENT: 534414c70cbSLiam Girdwood return sprintf(buf, "current\n"); 535414c70cbSLiam Girdwood } 536414c70cbSLiam Girdwood return sprintf(buf, "unknown\n"); 537414c70cbSLiam Girdwood } 538587cea27SGreg Kroah-Hartman static DEVICE_ATTR_RO(type); 539414c70cbSLiam Girdwood 540414c70cbSLiam Girdwood static ssize_t regulator_suspend_mem_uV_show(struct device *dev, 541414c70cbSLiam Girdwood struct device_attribute *attr, char *buf) 542414c70cbSLiam Girdwood { 543a5766f11SLiam Girdwood struct regulator_dev *rdev = dev_get_drvdata(dev); 544414c70cbSLiam Girdwood 545414c70cbSLiam Girdwood return sprintf(buf, "%d\n", rdev->constraints->state_mem.uV); 546414c70cbSLiam Girdwood } 5477ad68e2fSDavid Brownell static DEVICE_ATTR(suspend_mem_microvolts, 0444, 5487ad68e2fSDavid Brownell regulator_suspend_mem_uV_show, NULL); 549414c70cbSLiam Girdwood 550414c70cbSLiam Girdwood static ssize_t regulator_suspend_disk_uV_show(struct device *dev, 551414c70cbSLiam Girdwood struct device_attribute *attr, char *buf) 552414c70cbSLiam Girdwood { 553a5766f11SLiam Girdwood struct regulator_dev *rdev = dev_get_drvdata(dev); 554414c70cbSLiam Girdwood 555414c70cbSLiam Girdwood return sprintf(buf, "%d\n", rdev->constraints->state_disk.uV); 556414c70cbSLiam Girdwood } 5577ad68e2fSDavid Brownell static DEVICE_ATTR(suspend_disk_microvolts, 0444, 5587ad68e2fSDavid Brownell regulator_suspend_disk_uV_show, NULL); 559414c70cbSLiam Girdwood 560414c70cbSLiam Girdwood static ssize_t regulator_suspend_standby_uV_show(struct device *dev, 561414c70cbSLiam Girdwood struct device_attribute *attr, char *buf) 562414c70cbSLiam Girdwood { 563a5766f11SLiam Girdwood struct regulator_dev *rdev = dev_get_drvdata(dev); 564414c70cbSLiam Girdwood 565414c70cbSLiam Girdwood return sprintf(buf, "%d\n", rdev->constraints->state_standby.uV); 566414c70cbSLiam Girdwood } 5677ad68e2fSDavid Brownell static DEVICE_ATTR(suspend_standby_microvolts, 0444, 5687ad68e2fSDavid Brownell regulator_suspend_standby_uV_show, NULL); 569414c70cbSLiam Girdwood 570414c70cbSLiam Girdwood static ssize_t regulator_suspend_mem_mode_show(struct device *dev, 571414c70cbSLiam Girdwood struct device_attribute *attr, char *buf) 572414c70cbSLiam Girdwood { 573a5766f11SLiam Girdwood struct regulator_dev *rdev = dev_get_drvdata(dev); 574414c70cbSLiam Girdwood 5754fca9545SDavid Brownell return regulator_print_opmode(buf, 5764fca9545SDavid Brownell rdev->constraints->state_mem.mode); 577414c70cbSLiam Girdwood } 5787ad68e2fSDavid Brownell static DEVICE_ATTR(suspend_mem_mode, 0444, 5797ad68e2fSDavid Brownell regulator_suspend_mem_mode_show, NULL); 580414c70cbSLiam Girdwood 581414c70cbSLiam Girdwood static ssize_t regulator_suspend_disk_mode_show(struct device *dev, 582414c70cbSLiam Girdwood struct device_attribute *attr, char *buf) 583414c70cbSLiam Girdwood { 584a5766f11SLiam Girdwood struct regulator_dev *rdev = dev_get_drvdata(dev); 585414c70cbSLiam Girdwood 5864fca9545SDavid Brownell return regulator_print_opmode(buf, 5874fca9545SDavid Brownell rdev->constraints->state_disk.mode); 588414c70cbSLiam Girdwood } 5897ad68e2fSDavid Brownell static DEVICE_ATTR(suspend_disk_mode, 0444, 5907ad68e2fSDavid Brownell regulator_suspend_disk_mode_show, NULL); 591414c70cbSLiam Girdwood 592414c70cbSLiam Girdwood static ssize_t regulator_suspend_standby_mode_show(struct device *dev, 593414c70cbSLiam Girdwood struct device_attribute *attr, char *buf) 594414c70cbSLiam Girdwood { 595a5766f11SLiam Girdwood struct regulator_dev *rdev = dev_get_drvdata(dev); 596414c70cbSLiam Girdwood 5974fca9545SDavid Brownell return regulator_print_opmode(buf, 5984fca9545SDavid Brownell rdev->constraints->state_standby.mode); 599414c70cbSLiam Girdwood } 6007ad68e2fSDavid Brownell static DEVICE_ATTR(suspend_standby_mode, 0444, 6017ad68e2fSDavid Brownell regulator_suspend_standby_mode_show, NULL); 602414c70cbSLiam Girdwood 603414c70cbSLiam Girdwood static ssize_t regulator_suspend_mem_state_show(struct device *dev, 604414c70cbSLiam Girdwood struct device_attribute *attr, char *buf) 605414c70cbSLiam Girdwood { 606a5766f11SLiam Girdwood struct regulator_dev *rdev = dev_get_drvdata(dev); 607414c70cbSLiam Girdwood 6084fca9545SDavid Brownell return regulator_print_state(buf, 6094fca9545SDavid Brownell rdev->constraints->state_mem.enabled); 610414c70cbSLiam Girdwood } 6117ad68e2fSDavid Brownell static DEVICE_ATTR(suspend_mem_state, 0444, 6127ad68e2fSDavid Brownell regulator_suspend_mem_state_show, NULL); 613414c70cbSLiam Girdwood 614414c70cbSLiam Girdwood static ssize_t regulator_suspend_disk_state_show(struct device *dev, 615414c70cbSLiam Girdwood struct device_attribute *attr, char *buf) 616414c70cbSLiam Girdwood { 617a5766f11SLiam Girdwood struct regulator_dev *rdev = dev_get_drvdata(dev); 618414c70cbSLiam Girdwood 6194fca9545SDavid Brownell return regulator_print_state(buf, 6204fca9545SDavid Brownell rdev->constraints->state_disk.enabled); 621414c70cbSLiam Girdwood } 6227ad68e2fSDavid Brownell static DEVICE_ATTR(suspend_disk_state, 0444, 6237ad68e2fSDavid Brownell regulator_suspend_disk_state_show, NULL); 624414c70cbSLiam Girdwood 625414c70cbSLiam Girdwood static ssize_t regulator_suspend_standby_state_show(struct device *dev, 626414c70cbSLiam Girdwood struct device_attribute *attr, char *buf) 627414c70cbSLiam Girdwood { 628a5766f11SLiam Girdwood struct regulator_dev *rdev = dev_get_drvdata(dev); 629414c70cbSLiam Girdwood 6304fca9545SDavid Brownell return regulator_print_state(buf, 6314fca9545SDavid Brownell rdev->constraints->state_standby.enabled); 632414c70cbSLiam Girdwood } 6337ad68e2fSDavid Brownell static DEVICE_ATTR(suspend_standby_state, 0444, 6347ad68e2fSDavid Brownell regulator_suspend_standby_state_show, NULL); 635bc558a60SMark Brown 636f59c8f9fSMark Brown static ssize_t regulator_bypass_show(struct device *dev, 637f59c8f9fSMark Brown struct device_attribute *attr, char *buf) 638f59c8f9fSMark Brown { 639f59c8f9fSMark Brown struct regulator_dev *rdev = dev_get_drvdata(dev); 640f59c8f9fSMark Brown const char *report; 641f59c8f9fSMark Brown bool bypass; 642f59c8f9fSMark Brown int ret; 643f59c8f9fSMark Brown 644f59c8f9fSMark Brown ret = rdev->desc->ops->get_bypass(rdev, &bypass); 645f59c8f9fSMark Brown 646f59c8f9fSMark Brown if (ret != 0) 647f59c8f9fSMark Brown report = "unknown"; 648f59c8f9fSMark Brown else if (bypass) 649f59c8f9fSMark Brown report = "enabled"; 650f59c8f9fSMark Brown else 651f59c8f9fSMark Brown report = "disabled"; 652f59c8f9fSMark Brown 653f59c8f9fSMark Brown return sprintf(buf, "%s\n", report); 654f59c8f9fSMark Brown } 655f59c8f9fSMark Brown static DEVICE_ATTR(bypass, 0444, 656f59c8f9fSMark Brown regulator_bypass_show, NULL); 6577ad68e2fSDavid Brownell 658414c70cbSLiam Girdwood /* Calculate the new optimum regulator operating mode based on the new total 659414c70cbSLiam Girdwood * consumer load. All locks held by caller */ 6608460ef38SBjorn Andersson static int drms_uA_update(struct regulator_dev *rdev) 661414c70cbSLiam Girdwood { 662414c70cbSLiam Girdwood struct regulator *sibling; 663414c70cbSLiam Girdwood int current_uA = 0, output_uV, input_uV, err; 664414c70cbSLiam Girdwood unsigned int mode; 665414c70cbSLiam Girdwood 66670cfef26SKrzysztof Kozlowski lockdep_assert_held_once(&rdev->mutex); 66770cfef26SKrzysztof Kozlowski 6688460ef38SBjorn Andersson /* 6698460ef38SBjorn Andersson * first check to see if we can set modes at all, otherwise just 6708460ef38SBjorn Andersson * tell the consumer everything is OK. 6718460ef38SBjorn Andersson */ 6728a34e979SWEN Pingbo if (!regulator_ops_is_valid(rdev, REGULATOR_CHANGE_DRMS)) 6738460ef38SBjorn Andersson return 0; 6748460ef38SBjorn Andersson 6758f4490e0SBjorn Andersson if (!rdev->desc->ops->get_optimum_mode && 6768f4490e0SBjorn Andersson !rdev->desc->ops->set_load) 6778460ef38SBjorn Andersson return 0; 6788460ef38SBjorn Andersson 6798f4490e0SBjorn Andersson if (!rdev->desc->ops->set_mode && 6808f4490e0SBjorn Andersson !rdev->desc->ops->set_load) 6818460ef38SBjorn Andersson return -EINVAL; 682414c70cbSLiam Girdwood 68357776617SJoonwoo Park /* calc total requested load */ 68457776617SJoonwoo Park list_for_each_entry(sibling, &rdev->consumer_list, list) 68557776617SJoonwoo Park current_uA += sibling->uA_load; 68657776617SJoonwoo Park 68757776617SJoonwoo Park current_uA += rdev->constraints->system_load; 68857776617SJoonwoo Park 68957776617SJoonwoo Park if (rdev->desc->ops->set_load) { 69057776617SJoonwoo Park /* set the optimum mode for our new total regulator load */ 69157776617SJoonwoo Park err = rdev->desc->ops->set_load(rdev, current_uA); 69257776617SJoonwoo Park if (err < 0) 69357776617SJoonwoo Park rdev_err(rdev, "failed to set load %d\n", current_uA); 69457776617SJoonwoo Park } else { 695414c70cbSLiam Girdwood /* get output voltage */ 6961bf5a1f8SMark Brown output_uV = _regulator_get_voltage(rdev); 6978460ef38SBjorn Andersson if (output_uV <= 0) { 6988460ef38SBjorn Andersson rdev_err(rdev, "invalid output voltage found\n"); 6998460ef38SBjorn Andersson return -EINVAL; 7008460ef38SBjorn Andersson } 701414c70cbSLiam Girdwood 702414c70cbSLiam Girdwood /* get input voltage */ 7031bf5a1f8SMark Brown input_uV = 0; 7041bf5a1f8SMark Brown if (rdev->supply) 7053f24f5adSAxel Lin input_uV = regulator_get_voltage(rdev->supply); 7061bf5a1f8SMark Brown if (input_uV <= 0) 707414c70cbSLiam Girdwood input_uV = rdev->constraints->input_uV; 7088460ef38SBjorn Andersson if (input_uV <= 0) { 7098460ef38SBjorn Andersson rdev_err(rdev, "invalid input voltage found\n"); 7108460ef38SBjorn Andersson return -EINVAL; 7118460ef38SBjorn Andersson } 712414c70cbSLiam Girdwood 713414c70cbSLiam Girdwood /* now get the optimum mode for our new total regulator load */ 714414c70cbSLiam Girdwood mode = rdev->desc->ops->get_optimum_mode(rdev, input_uV, 715414c70cbSLiam Girdwood output_uV, current_uA); 716414c70cbSLiam Girdwood 717414c70cbSLiam Girdwood /* check the new mode is allowed */ 7182c608234SMark Brown err = regulator_mode_constrain(rdev, &mode); 7198460ef38SBjorn Andersson if (err < 0) { 7208460ef38SBjorn Andersson rdev_err(rdev, "failed to get optimum mode @ %d uA %d -> %d uV\n", 7218460ef38SBjorn Andersson current_uA, input_uV, output_uV); 7228460ef38SBjorn Andersson return err; 7238460ef38SBjorn Andersson } 7248460ef38SBjorn Andersson 7258460ef38SBjorn Andersson err = rdev->desc->ops->set_mode(rdev, mode); 7268460ef38SBjorn Andersson if (err < 0) 7278460ef38SBjorn Andersson rdev_err(rdev, "failed to set optimum mode %x\n", mode); 7288f4490e0SBjorn Andersson } 7298460ef38SBjorn Andersson 7308460ef38SBjorn Andersson return err; 731414c70cbSLiam Girdwood } 732414c70cbSLiam Girdwood 733414c70cbSLiam Girdwood static int suspend_set_state(struct regulator_dev *rdev, 734414c70cbSLiam Girdwood struct regulator_state *rstate) 735414c70cbSLiam Girdwood { 736414c70cbSLiam Girdwood int ret = 0; 737638f85c5SMark Brown 738638f85c5SMark Brown /* If we have no suspend mode configration don't set anything; 7398ac0e95dSAxel Lin * only warn if the driver implements set_suspend_voltage or 7408ac0e95dSAxel Lin * set_suspend_mode callback. 741638f85c5SMark Brown */ 742638f85c5SMark Brown if (!rstate->enabled && !rstate->disabled) { 7438ac0e95dSAxel Lin if (rdev->desc->ops->set_suspend_voltage || 7448ac0e95dSAxel Lin rdev->desc->ops->set_suspend_mode) 7455da84fd9SJoe Perches rdev_warn(rdev, "No configuration\n"); 746638f85c5SMark Brown return 0; 747638f85c5SMark Brown } 748638f85c5SMark Brown 749638f85c5SMark Brown if (rstate->enabled && rstate->disabled) { 7505da84fd9SJoe Perches rdev_err(rdev, "invalid configuration\n"); 751638f85c5SMark Brown return -EINVAL; 752638f85c5SMark Brown } 753638f85c5SMark Brown 7548ac0e95dSAxel Lin if (rstate->enabled && rdev->desc->ops->set_suspend_enable) 755414c70cbSLiam Girdwood ret = rdev->desc->ops->set_suspend_enable(rdev); 7568ac0e95dSAxel Lin else if (rstate->disabled && rdev->desc->ops->set_suspend_disable) 757414c70cbSLiam Girdwood ret = rdev->desc->ops->set_suspend_disable(rdev); 7588ac0e95dSAxel Lin else /* OK if set_suspend_enable or set_suspend_disable is NULL */ 7598ac0e95dSAxel Lin ret = 0; 7608ac0e95dSAxel Lin 761414c70cbSLiam Girdwood if (ret < 0) { 7625da84fd9SJoe Perches rdev_err(rdev, "failed to enabled/disable\n"); 763414c70cbSLiam Girdwood return ret; 764414c70cbSLiam Girdwood } 765414c70cbSLiam Girdwood 766414c70cbSLiam Girdwood if (rdev->desc->ops->set_suspend_voltage && rstate->uV > 0) { 767414c70cbSLiam Girdwood ret = rdev->desc->ops->set_suspend_voltage(rdev, rstate->uV); 768414c70cbSLiam Girdwood if (ret < 0) { 7695da84fd9SJoe Perches rdev_err(rdev, "failed to set voltage\n"); 770414c70cbSLiam Girdwood return ret; 771414c70cbSLiam Girdwood } 772414c70cbSLiam Girdwood } 773414c70cbSLiam Girdwood 774414c70cbSLiam Girdwood if (rdev->desc->ops->set_suspend_mode && rstate->mode > 0) { 775414c70cbSLiam Girdwood ret = rdev->desc->ops->set_suspend_mode(rdev, rstate->mode); 776414c70cbSLiam Girdwood if (ret < 0) { 7775da84fd9SJoe Perches rdev_err(rdev, "failed to set mode\n"); 778414c70cbSLiam Girdwood return ret; 779414c70cbSLiam Girdwood } 780414c70cbSLiam Girdwood } 781414c70cbSLiam Girdwood return ret; 782414c70cbSLiam Girdwood } 783414c70cbSLiam Girdwood 784414c70cbSLiam Girdwood /* locks held by caller */ 785414c70cbSLiam Girdwood static int suspend_prepare(struct regulator_dev *rdev, suspend_state_t state) 786414c70cbSLiam Girdwood { 787414c70cbSLiam Girdwood if (!rdev->constraints) 788414c70cbSLiam Girdwood return -EINVAL; 789414c70cbSLiam Girdwood 790414c70cbSLiam Girdwood switch (state) { 791414c70cbSLiam Girdwood case PM_SUSPEND_STANDBY: 792414c70cbSLiam Girdwood return suspend_set_state(rdev, 793414c70cbSLiam Girdwood &rdev->constraints->state_standby); 794414c70cbSLiam Girdwood case PM_SUSPEND_MEM: 795414c70cbSLiam Girdwood return suspend_set_state(rdev, 796414c70cbSLiam Girdwood &rdev->constraints->state_mem); 797414c70cbSLiam Girdwood case PM_SUSPEND_MAX: 798414c70cbSLiam Girdwood return suspend_set_state(rdev, 799414c70cbSLiam Girdwood &rdev->constraints->state_disk); 800414c70cbSLiam Girdwood default: 801414c70cbSLiam Girdwood return -EINVAL; 802414c70cbSLiam Girdwood } 803414c70cbSLiam Girdwood } 804414c70cbSLiam Girdwood 805414c70cbSLiam Girdwood static void print_constraints(struct regulator_dev *rdev) 806414c70cbSLiam Girdwood { 807414c70cbSLiam Girdwood struct regulation_constraints *constraints = rdev->constraints; 808a7068e39SStefan Wahren char buf[160] = ""; 8095751a99fSStefan Wahren size_t len = sizeof(buf) - 1; 8108f031b48SMark Brown int count = 0; 8118f031b48SMark Brown int ret; 812414c70cbSLiam Girdwood 8138f031b48SMark Brown if (constraints->min_uV && constraints->max_uV) { 814414c70cbSLiam Girdwood if (constraints->min_uV == constraints->max_uV) 8155751a99fSStefan Wahren count += scnprintf(buf + count, len - count, "%d mV ", 816414c70cbSLiam Girdwood constraints->min_uV / 1000); 817414c70cbSLiam Girdwood else 8185751a99fSStefan Wahren count += scnprintf(buf + count, len - count, 8195751a99fSStefan Wahren "%d <--> %d mV ", 820414c70cbSLiam Girdwood constraints->min_uV / 1000, 821414c70cbSLiam Girdwood constraints->max_uV / 1000); 8228f031b48SMark Brown } 8238f031b48SMark Brown 8248f031b48SMark Brown if (!constraints->min_uV || 8258f031b48SMark Brown constraints->min_uV != constraints->max_uV) { 8268f031b48SMark Brown ret = _regulator_get_voltage(rdev); 8278f031b48SMark Brown if (ret > 0) 8285751a99fSStefan Wahren count += scnprintf(buf + count, len - count, 8295751a99fSStefan Wahren "at %d mV ", ret / 1000); 8308f031b48SMark Brown } 8318f031b48SMark Brown 832bf5892a8SMark Brown if (constraints->uV_offset) 8335751a99fSStefan Wahren count += scnprintf(buf + count, len - count, "%dmV offset ", 834bf5892a8SMark Brown constraints->uV_offset / 1000); 835bf5892a8SMark Brown 8368f031b48SMark Brown if (constraints->min_uA && constraints->max_uA) { 837414c70cbSLiam Girdwood if (constraints->min_uA == constraints->max_uA) 8385751a99fSStefan Wahren count += scnprintf(buf + count, len - count, "%d mA ", 839414c70cbSLiam Girdwood constraints->min_uA / 1000); 840414c70cbSLiam Girdwood else 8415751a99fSStefan Wahren count += scnprintf(buf + count, len - count, 8425751a99fSStefan Wahren "%d <--> %d mA ", 843414c70cbSLiam Girdwood constraints->min_uA / 1000, 844414c70cbSLiam Girdwood constraints->max_uA / 1000); 845414c70cbSLiam Girdwood } 8468f031b48SMark Brown 8478f031b48SMark Brown if (!constraints->min_uA || 8488f031b48SMark Brown constraints->min_uA != constraints->max_uA) { 8498f031b48SMark Brown ret = _regulator_get_current_limit(rdev); 8508f031b48SMark Brown if (ret > 0) 8515751a99fSStefan Wahren count += scnprintf(buf + count, len - count, 8525751a99fSStefan Wahren "at %d mA ", ret / 1000); 8538f031b48SMark Brown } 8548f031b48SMark Brown 855414c70cbSLiam Girdwood if (constraints->valid_modes_mask & REGULATOR_MODE_FAST) 8565751a99fSStefan Wahren count += scnprintf(buf + count, len - count, "fast "); 857414c70cbSLiam Girdwood if (constraints->valid_modes_mask & REGULATOR_MODE_NORMAL) 8585751a99fSStefan Wahren count += scnprintf(buf + count, len - count, "normal "); 859414c70cbSLiam Girdwood if (constraints->valid_modes_mask & REGULATOR_MODE_IDLE) 8605751a99fSStefan Wahren count += scnprintf(buf + count, len - count, "idle "); 861414c70cbSLiam Girdwood if (constraints->valid_modes_mask & REGULATOR_MODE_STANDBY) 8625751a99fSStefan Wahren count += scnprintf(buf + count, len - count, "standby"); 863414c70cbSLiam Girdwood 864215b8b05SUwe Kleine-König if (!count) 8655751a99fSStefan Wahren scnprintf(buf, len, "no parameters"); 866215b8b05SUwe Kleine-König 867194dbaefSMark Brown rdev_dbg(rdev, "%s\n", buf); 8684a682922SMark Brown 8694a682922SMark Brown if ((constraints->min_uV != constraints->max_uV) && 8708a34e979SWEN Pingbo !regulator_ops_is_valid(rdev, REGULATOR_CHANGE_VOLTAGE)) 8714a682922SMark Brown rdev_warn(rdev, 8724a682922SMark Brown "Voltage range but no REGULATOR_CHANGE_VOLTAGE\n"); 873414c70cbSLiam Girdwood } 874414c70cbSLiam Girdwood 875e79055d6SMark Brown static int machine_constraints_voltage(struct regulator_dev *rdev, 8761083c393SMark Brown struct regulation_constraints *constraints) 877e79055d6SMark Brown { 878272e2315SGuodong Xu const struct regulator_ops *ops = rdev->desc->ops; 879af5866c9SMark Brown int ret; 880af5866c9SMark Brown 881af5866c9SMark Brown /* do we need to apply the constraint voltage */ 882af5866c9SMark Brown if (rdev->constraints->apply_uV && 883fa93fd4eSMark Brown rdev->constraints->min_uV && rdev->constraints->max_uV) { 884fa93fd4eSMark Brown int target_min, target_max; 885064d5cd1SAlban Bedel int current_uV = _regulator_get_voltage(rdev); 886064d5cd1SAlban Bedel if (current_uV < 0) { 88769d58839SNishanth Menon rdev_err(rdev, 88869d58839SNishanth Menon "failed to get the current voltage(%d)\n", 88969d58839SNishanth Menon current_uV); 890064d5cd1SAlban Bedel return current_uV; 891064d5cd1SAlban Bedel } 892fa93fd4eSMark Brown 893fa93fd4eSMark Brown /* 894fa93fd4eSMark Brown * If we're below the minimum voltage move up to the 895fa93fd4eSMark Brown * minimum voltage, if we're above the maximum voltage 896fa93fd4eSMark Brown * then move down to the maximum. 897fa93fd4eSMark Brown */ 898fa93fd4eSMark Brown target_min = current_uV; 899fa93fd4eSMark Brown target_max = current_uV; 900fa93fd4eSMark Brown 901fa93fd4eSMark Brown if (current_uV < rdev->constraints->min_uV) { 902fa93fd4eSMark Brown target_min = rdev->constraints->min_uV; 903fa93fd4eSMark Brown target_max = rdev->constraints->min_uV; 904fa93fd4eSMark Brown } 905fa93fd4eSMark Brown 906fa93fd4eSMark Brown if (current_uV > rdev->constraints->max_uV) { 907fa93fd4eSMark Brown target_min = rdev->constraints->max_uV; 908fa93fd4eSMark Brown target_max = rdev->constraints->max_uV; 909fa93fd4eSMark Brown } 910fa93fd4eSMark Brown 911fa93fd4eSMark Brown if (target_min != current_uV || target_max != current_uV) { 91245a91e8fSMark Brown rdev_info(rdev, "Bringing %duV into %d-%duV\n", 91345a91e8fSMark Brown current_uV, target_min, target_max); 914064d5cd1SAlban Bedel ret = _regulator_do_set_voltage( 915fa93fd4eSMark Brown rdev, target_min, target_max); 916af5866c9SMark Brown if (ret < 0) { 917064d5cd1SAlban Bedel rdev_err(rdev, 918fa93fd4eSMark Brown "failed to apply %d-%duV constraint(%d)\n", 919fa93fd4eSMark Brown target_min, target_max, ret); 920af5866c9SMark Brown return ret; 921af5866c9SMark Brown } 922af5866c9SMark Brown } 923064d5cd1SAlban Bedel } 924e79055d6SMark Brown 925e79055d6SMark Brown /* constrain machine-level voltage specs to fit 926e79055d6SMark Brown * the actual range supported by this regulator. 927e79055d6SMark Brown */ 928e79055d6SMark Brown if (ops->list_voltage && rdev->desc->n_voltages) { 929e79055d6SMark Brown int count = rdev->desc->n_voltages; 930e79055d6SMark Brown int i; 931e79055d6SMark Brown int min_uV = INT_MAX; 932e79055d6SMark Brown int max_uV = INT_MIN; 933e79055d6SMark Brown int cmin = constraints->min_uV; 934e79055d6SMark Brown int cmax = constraints->max_uV; 935e79055d6SMark Brown 936e79055d6SMark Brown /* it's safe to autoconfigure fixed-voltage supplies 937e79055d6SMark Brown and the constraints are used by list_voltage. */ 938e79055d6SMark Brown if (count == 1 && !cmin) { 939e79055d6SMark Brown cmin = 1; 940e79055d6SMark Brown cmax = INT_MAX; 941e79055d6SMark Brown constraints->min_uV = cmin; 942e79055d6SMark Brown constraints->max_uV = cmax; 943e79055d6SMark Brown } 944e79055d6SMark Brown 945e79055d6SMark Brown /* voltage constraints are optional */ 946e79055d6SMark Brown if ((cmin == 0) && (cmax == 0)) 947e79055d6SMark Brown return 0; 948e79055d6SMark Brown 949e79055d6SMark Brown /* else require explicit machine-level constraints */ 950e79055d6SMark Brown if (cmin <= 0 || cmax <= 0 || cmax < cmin) { 9515da84fd9SJoe Perches rdev_err(rdev, "invalid voltage constraints\n"); 952e79055d6SMark Brown return -EINVAL; 953e79055d6SMark Brown } 954e79055d6SMark Brown 955e79055d6SMark Brown /* initial: [cmin..cmax] valid, [min_uV..max_uV] not */ 956e79055d6SMark Brown for (i = 0; i < count; i++) { 957e79055d6SMark Brown int value; 958e79055d6SMark Brown 959e79055d6SMark Brown value = ops->list_voltage(rdev, i); 960e79055d6SMark Brown if (value <= 0) 961e79055d6SMark Brown continue; 962e79055d6SMark Brown 963e79055d6SMark Brown /* maybe adjust [min_uV..max_uV] */ 964e79055d6SMark Brown if (value >= cmin && value < min_uV) 965e79055d6SMark Brown min_uV = value; 966e79055d6SMark Brown if (value <= cmax && value > max_uV) 967e79055d6SMark Brown max_uV = value; 968e79055d6SMark Brown } 969e79055d6SMark Brown 970e79055d6SMark Brown /* final: [min_uV..max_uV] valid iff constraints valid */ 971e79055d6SMark Brown if (max_uV < min_uV) { 972fff15befSMark Brown rdev_err(rdev, 973fff15befSMark Brown "unsupportable voltage constraints %u-%uuV\n", 974fff15befSMark Brown min_uV, max_uV); 975e79055d6SMark Brown return -EINVAL; 976e79055d6SMark Brown } 977e79055d6SMark Brown 978e79055d6SMark Brown /* use regulator's subset of machine constraints */ 979e79055d6SMark Brown if (constraints->min_uV < min_uV) { 9805da84fd9SJoe Perches rdev_dbg(rdev, "override min_uV, %d -> %d\n", 9815da84fd9SJoe Perches constraints->min_uV, min_uV); 982e79055d6SMark Brown constraints->min_uV = min_uV; 983e79055d6SMark Brown } 984e79055d6SMark Brown if (constraints->max_uV > max_uV) { 9855da84fd9SJoe Perches rdev_dbg(rdev, "override max_uV, %d -> %d\n", 9865da84fd9SJoe Perches constraints->max_uV, max_uV); 987e79055d6SMark Brown constraints->max_uV = max_uV; 988e79055d6SMark Brown } 989e79055d6SMark Brown } 990e79055d6SMark Brown 991e79055d6SMark Brown return 0; 992e79055d6SMark Brown } 993e79055d6SMark Brown 994f8c1700dSLaxman Dewangan static int machine_constraints_current(struct regulator_dev *rdev, 995f8c1700dSLaxman Dewangan struct regulation_constraints *constraints) 996f8c1700dSLaxman Dewangan { 997272e2315SGuodong Xu const struct regulator_ops *ops = rdev->desc->ops; 998f8c1700dSLaxman Dewangan int ret; 999f8c1700dSLaxman Dewangan 1000f8c1700dSLaxman Dewangan if (!constraints->min_uA && !constraints->max_uA) 1001f8c1700dSLaxman Dewangan return 0; 1002f8c1700dSLaxman Dewangan 1003f8c1700dSLaxman Dewangan if (constraints->min_uA > constraints->max_uA) { 1004f8c1700dSLaxman Dewangan rdev_err(rdev, "Invalid current constraints\n"); 1005f8c1700dSLaxman Dewangan return -EINVAL; 1006f8c1700dSLaxman Dewangan } 1007f8c1700dSLaxman Dewangan 1008f8c1700dSLaxman Dewangan if (!ops->set_current_limit || !ops->get_current_limit) { 1009f8c1700dSLaxman Dewangan rdev_warn(rdev, "Operation of current configuration missing\n"); 1010f8c1700dSLaxman Dewangan return 0; 1011f8c1700dSLaxman Dewangan } 1012f8c1700dSLaxman Dewangan 1013f8c1700dSLaxman Dewangan /* Set regulator current in constraints range */ 1014f8c1700dSLaxman Dewangan ret = ops->set_current_limit(rdev, constraints->min_uA, 1015f8c1700dSLaxman Dewangan constraints->max_uA); 1016f8c1700dSLaxman Dewangan if (ret < 0) { 1017f8c1700dSLaxman Dewangan rdev_err(rdev, "Failed to set current constraint, %d\n", ret); 1018f8c1700dSLaxman Dewangan return ret; 1019f8c1700dSLaxman Dewangan } 1020f8c1700dSLaxman Dewangan 1021f8c1700dSLaxman Dewangan return 0; 1022f8c1700dSLaxman Dewangan } 1023f8c1700dSLaxman Dewangan 102430c21971SMarkus Pargmann static int _regulator_do_enable(struct regulator_dev *rdev); 102530c21971SMarkus Pargmann 1026a5766f11SLiam Girdwood /** 1027a5766f11SLiam Girdwood * set_machine_constraints - sets regulator constraints 102869279fb9SMark Brown * @rdev: regulator source 1029c8e7e464SMark Brown * @constraints: constraints to apply 1030a5766f11SLiam Girdwood * 1031a5766f11SLiam Girdwood * Allows platform initialisation code to define and constrain 1032a5766f11SLiam Girdwood * regulator circuits e.g. valid voltage/current ranges, etc. NOTE: 1033a5766f11SLiam Girdwood * Constraints *must* be set by platform code in order for some 1034a5766f11SLiam Girdwood * regulator operations to proceed i.e. set_voltage, set_current_limit, 1035a5766f11SLiam Girdwood * set_mode. 1036a5766f11SLiam Girdwood */ 1037a5766f11SLiam Girdwood static int set_machine_constraints(struct regulator_dev *rdev, 1038f8c12fe3SMark Brown const struct regulation_constraints *constraints) 1039a5766f11SLiam Girdwood { 1040a5766f11SLiam Girdwood int ret = 0; 1041272e2315SGuodong Xu const struct regulator_ops *ops = rdev->desc->ops; 1042e06f5b4fSMark Brown 10439a8f5e07SMark Brown if (constraints) 1044f8c12fe3SMark Brown rdev->constraints = kmemdup(constraints, sizeof(*constraints), 1045f8c12fe3SMark Brown GFP_KERNEL); 10469a8f5e07SMark Brown else 10479a8f5e07SMark Brown rdev->constraints = kzalloc(sizeof(*constraints), 10489a8f5e07SMark Brown GFP_KERNEL); 1049f8c12fe3SMark Brown if (!rdev->constraints) 1050f8c12fe3SMark Brown return -ENOMEM; 1051af5866c9SMark Brown 1052f8c12fe3SMark Brown ret = machine_constraints_voltage(rdev, rdev->constraints); 1053e79055d6SMark Brown if (ret != 0) 10546333ef46SCharles Keepax return ret; 10553e2b9abdSMark Brown 1056f8c1700dSLaxman Dewangan ret = machine_constraints_current(rdev, rdev->constraints); 1057f8c1700dSLaxman Dewangan if (ret != 0) 10586333ef46SCharles Keepax return ret; 1059f8c1700dSLaxman Dewangan 106036e4f839SStephen Boyd if (rdev->constraints->ilim_uA && ops->set_input_current_limit) { 106136e4f839SStephen Boyd ret = ops->set_input_current_limit(rdev, 106236e4f839SStephen Boyd rdev->constraints->ilim_uA); 106336e4f839SStephen Boyd if (ret < 0) { 106436e4f839SStephen Boyd rdev_err(rdev, "failed to set input limit\n"); 10656333ef46SCharles Keepax return ret; 106636e4f839SStephen Boyd } 106736e4f839SStephen Boyd } 106836e4f839SStephen Boyd 1069a5766f11SLiam Girdwood /* do we need to setup our suspend state */ 10709a8f5e07SMark Brown if (rdev->constraints->initial_state) { 1071f8c12fe3SMark Brown ret = suspend_prepare(rdev, rdev->constraints->initial_state); 1072e06f5b4fSMark Brown if (ret < 0) { 10735da84fd9SJoe Perches rdev_err(rdev, "failed to set suspend state\n"); 10746333ef46SCharles Keepax return ret; 1075e06f5b4fSMark Brown } 1076e06f5b4fSMark Brown } 1077a5766f11SLiam Girdwood 10789a8f5e07SMark Brown if (rdev->constraints->initial_mode) { 1079a308466cSMark Brown if (!ops->set_mode) { 10805da84fd9SJoe Perches rdev_err(rdev, "no set_mode operation\n"); 10816333ef46SCharles Keepax return -EINVAL; 1082a308466cSMark Brown } 1083a308466cSMark Brown 1084f8c12fe3SMark Brown ret = ops->set_mode(rdev, rdev->constraints->initial_mode); 1085a308466cSMark Brown if (ret < 0) { 10865da84fd9SJoe Perches rdev_err(rdev, "failed to set initial mode: %d\n", ret); 10876333ef46SCharles Keepax return ret; 1088a308466cSMark Brown } 1089a308466cSMark Brown } 1090a308466cSMark Brown 1091cacf90f2SMark Brown /* If the constraints say the regulator should be on at this point 1092cacf90f2SMark Brown * and we have control then make sure it is enabled. 1093cacf90f2SMark Brown */ 109430c21971SMarkus Pargmann if (rdev->constraints->always_on || rdev->constraints->boot_on) { 109530c21971SMarkus Pargmann ret = _regulator_do_enable(rdev); 109630c21971SMarkus Pargmann if (ret < 0 && ret != -EINVAL) { 10975da84fd9SJoe Perches rdev_err(rdev, "failed to enable\n"); 10986333ef46SCharles Keepax return ret; 1099e5fda26cSMark Brown } 1100e5fda26cSMark Brown } 1101e5fda26cSMark Brown 11021653ccf4SYadwinder Singh Brar if ((rdev->constraints->ramp_delay || rdev->constraints->ramp_disable) 11031653ccf4SYadwinder Singh Brar && ops->set_ramp_delay) { 11046f0b2c69SYadwinder Singh Brar ret = ops->set_ramp_delay(rdev, rdev->constraints->ramp_delay); 11056f0b2c69SYadwinder Singh Brar if (ret < 0) { 11066f0b2c69SYadwinder Singh Brar rdev_err(rdev, "failed to set ramp_delay\n"); 11076333ef46SCharles Keepax return ret; 11086f0b2c69SYadwinder Singh Brar } 11096f0b2c69SYadwinder Singh Brar } 11106f0b2c69SYadwinder Singh Brar 111123c779b9SStephen Boyd if (rdev->constraints->pull_down && ops->set_pull_down) { 111223c779b9SStephen Boyd ret = ops->set_pull_down(rdev); 111323c779b9SStephen Boyd if (ret < 0) { 111423c779b9SStephen Boyd rdev_err(rdev, "failed to set pull down\n"); 11156333ef46SCharles Keepax return ret; 111623c779b9SStephen Boyd } 111723c779b9SStephen Boyd } 111823c779b9SStephen Boyd 111957f66b78SStephen Boyd if (rdev->constraints->soft_start && ops->set_soft_start) { 112057f66b78SStephen Boyd ret = ops->set_soft_start(rdev); 112157f66b78SStephen Boyd if (ret < 0) { 112257f66b78SStephen Boyd rdev_err(rdev, "failed to set soft start\n"); 11236333ef46SCharles Keepax return ret; 112457f66b78SStephen Boyd } 112557f66b78SStephen Boyd } 112657f66b78SStephen Boyd 11273a003baeSStephen Boyd if (rdev->constraints->over_current_protection 11283a003baeSStephen Boyd && ops->set_over_current_protection) { 11293a003baeSStephen Boyd ret = ops->set_over_current_protection(rdev); 11303a003baeSStephen Boyd if (ret < 0) { 11313a003baeSStephen Boyd rdev_err(rdev, "failed to set over current protection\n"); 11326333ef46SCharles Keepax return ret; 11333a003baeSStephen Boyd } 11343a003baeSStephen Boyd } 11353a003baeSStephen Boyd 1136670666b9SLaxman Dewangan if (rdev->constraints->active_discharge && ops->set_active_discharge) { 1137670666b9SLaxman Dewangan bool ad_state = (rdev->constraints->active_discharge == 1138670666b9SLaxman Dewangan REGULATOR_ACTIVE_DISCHARGE_ENABLE) ? true : false; 1139670666b9SLaxman Dewangan 1140670666b9SLaxman Dewangan ret = ops->set_active_discharge(rdev, ad_state); 1141670666b9SLaxman Dewangan if (ret < 0) { 1142670666b9SLaxman Dewangan rdev_err(rdev, "failed to set active discharge\n"); 1143670666b9SLaxman Dewangan return ret; 1144670666b9SLaxman Dewangan } 1145670666b9SLaxman Dewangan } 1146670666b9SLaxman Dewangan 1147a5766f11SLiam Girdwood print_constraints(rdev); 11481a6958e7SAxel Lin return 0; 1149a5766f11SLiam Girdwood } 1150a5766f11SLiam Girdwood 1151a5766f11SLiam Girdwood /** 1152a5766f11SLiam Girdwood * set_supply - set regulator supply regulator 115369279fb9SMark Brown * @rdev: regulator name 115469279fb9SMark Brown * @supply_rdev: supply regulator name 1155a5766f11SLiam Girdwood * 1156a5766f11SLiam Girdwood * Called by platform initialisation code to set the supply regulator for this 1157a5766f11SLiam Girdwood * regulator. This ensures that a regulators supply will also be enabled by the 1158a5766f11SLiam Girdwood * core if it's child is enabled. 1159a5766f11SLiam Girdwood */ 1160a5766f11SLiam Girdwood static int set_supply(struct regulator_dev *rdev, 1161a5766f11SLiam Girdwood struct regulator_dev *supply_rdev) 1162a5766f11SLiam Girdwood { 1163a5766f11SLiam Girdwood int err; 1164a5766f11SLiam Girdwood 11653801b86aSMark Brown rdev_info(rdev, "supplied by %s\n", rdev_get_name(supply_rdev)); 11663801b86aSMark Brown 1167e2c09ae7SJavier Martinez Canillas if (!try_module_get(supply_rdev->owner)) 1168e2c09ae7SJavier Martinez Canillas return -ENODEV; 1169e2c09ae7SJavier Martinez Canillas 11703801b86aSMark Brown rdev->supply = create_regulator(supply_rdev, &rdev->dev, "SUPPLY"); 117132c78de8SAxel Lin if (rdev->supply == NULL) { 117232c78de8SAxel Lin err = -ENOMEM; 1173a5766f11SLiam Girdwood return err; 1174a5766f11SLiam Girdwood } 117557ad526aSLaxman Dewangan supply_rdev->open_count++; 1176a5766f11SLiam Girdwood 11773801b86aSMark Brown return 0; 11783801b86aSMark Brown } 11793801b86aSMark Brown 1180a5766f11SLiam Girdwood /** 118106c63f93SRandy Dunlap * set_consumer_device_supply - Bind a regulator to a symbolic supply 118269279fb9SMark Brown * @rdev: regulator source 118340f9244fSMark Brown * @consumer_dev_name: dev_name() string for device supply applies to 1184a5766f11SLiam Girdwood * @supply: symbolic name for supply 1185a5766f11SLiam Girdwood * 1186a5766f11SLiam Girdwood * Allows platform initialisation code to map physical regulator 1187a5766f11SLiam Girdwood * sources to symbolic names for supplies for use by devices. Devices 1188a5766f11SLiam Girdwood * should use these symbolic names to request regulators, avoiding the 1189a5766f11SLiam Girdwood * need to provide board-specific regulator names as platform data. 1190a5766f11SLiam Girdwood */ 1191a5766f11SLiam Girdwood static int set_consumer_device_supply(struct regulator_dev *rdev, 1192737f360dSMark Brown const char *consumer_dev_name, 119340f9244fSMark Brown const char *supply) 1194a5766f11SLiam Girdwood { 1195a5766f11SLiam Girdwood struct regulator_map *node; 11969ed2099eSMark Brown int has_dev; 1197a5766f11SLiam Girdwood 1198a5766f11SLiam Girdwood if (supply == NULL) 1199a5766f11SLiam Girdwood return -EINVAL; 1200a5766f11SLiam Girdwood 12019ed2099eSMark Brown if (consumer_dev_name != NULL) 12029ed2099eSMark Brown has_dev = 1; 12039ed2099eSMark Brown else 12049ed2099eSMark Brown has_dev = 0; 12059ed2099eSMark Brown 12066001e13cSDavid Brownell list_for_each_entry(node, ®ulator_map_list, list) { 120723b5cc2aSJani Nikula if (node->dev_name && consumer_dev_name) { 120823b5cc2aSJani Nikula if (strcmp(node->dev_name, consumer_dev_name) != 0) 12096001e13cSDavid Brownell continue; 121023b5cc2aSJani Nikula } else if (node->dev_name || consumer_dev_name) { 121123b5cc2aSJani Nikula continue; 121223b5cc2aSJani Nikula } 121323b5cc2aSJani Nikula 12146001e13cSDavid Brownell if (strcmp(node->supply, supply) != 0) 12156001e13cSDavid Brownell continue; 12166001e13cSDavid Brownell 1217737f360dSMark Brown pr_debug("%s: %s/%s is '%s' supply; fail %s/%s\n", 1218737f360dSMark Brown consumer_dev_name, 12196001e13cSDavid Brownell dev_name(&node->regulator->dev), 12206001e13cSDavid Brownell node->regulator->desc->name, 12216001e13cSDavid Brownell supply, 12221083c393SMark Brown dev_name(&rdev->dev), rdev_get_name(rdev)); 12236001e13cSDavid Brownell return -EBUSY; 12246001e13cSDavid Brownell } 12256001e13cSDavid Brownell 12269ed2099eSMark Brown node = kzalloc(sizeof(struct regulator_map), GFP_KERNEL); 1227a5766f11SLiam Girdwood if (node == NULL) 1228a5766f11SLiam Girdwood return -ENOMEM; 1229a5766f11SLiam Girdwood 1230a5766f11SLiam Girdwood node->regulator = rdev; 1231a5766f11SLiam Girdwood node->supply = supply; 1232a5766f11SLiam Girdwood 12339ed2099eSMark Brown if (has_dev) { 12349ed2099eSMark Brown node->dev_name = kstrdup(consumer_dev_name, GFP_KERNEL); 123540f9244fSMark Brown if (node->dev_name == NULL) { 123640f9244fSMark Brown kfree(node); 123740f9244fSMark Brown return -ENOMEM; 123840f9244fSMark Brown } 12399ed2099eSMark Brown } 124040f9244fSMark Brown 1241a5766f11SLiam Girdwood list_add(&node->list, ®ulator_map_list); 1242a5766f11SLiam Girdwood return 0; 1243a5766f11SLiam Girdwood } 1244a5766f11SLiam Girdwood 12450f1d747bSMike Rapoport static void unset_regulator_supplies(struct regulator_dev *rdev) 12460f1d747bSMike Rapoport { 12470f1d747bSMike Rapoport struct regulator_map *node, *n; 12480f1d747bSMike Rapoport 12490f1d747bSMike Rapoport list_for_each_entry_safe(node, n, ®ulator_map_list, list) { 12500f1d747bSMike Rapoport if (rdev == node->regulator) { 12510f1d747bSMike Rapoport list_del(&node->list); 125240f9244fSMark Brown kfree(node->dev_name); 12530f1d747bSMike Rapoport kfree(node); 12540f1d747bSMike Rapoport } 12550f1d747bSMike Rapoport } 12560f1d747bSMike Rapoport } 12570f1d747bSMike Rapoport 12582d80a91bSRichard Fitzgerald #ifdef CONFIG_DEBUG_FS 12592d80a91bSRichard Fitzgerald static ssize_t constraint_flags_read_file(struct file *file, 12602d80a91bSRichard Fitzgerald char __user *user_buf, 12612d80a91bSRichard Fitzgerald size_t count, loff_t *ppos) 12622d80a91bSRichard Fitzgerald { 12632d80a91bSRichard Fitzgerald const struct regulator *regulator = file->private_data; 12642d80a91bSRichard Fitzgerald const struct regulation_constraints *c = regulator->rdev->constraints; 12652d80a91bSRichard Fitzgerald char *buf; 12662d80a91bSRichard Fitzgerald ssize_t ret; 12672d80a91bSRichard Fitzgerald 12682d80a91bSRichard Fitzgerald if (!c) 12692d80a91bSRichard Fitzgerald return 0; 12702d80a91bSRichard Fitzgerald 12712d80a91bSRichard Fitzgerald buf = kmalloc(PAGE_SIZE, GFP_KERNEL); 12722d80a91bSRichard Fitzgerald if (!buf) 12732d80a91bSRichard Fitzgerald return -ENOMEM; 12742d80a91bSRichard Fitzgerald 12752d80a91bSRichard Fitzgerald ret = snprintf(buf, PAGE_SIZE, 12762d80a91bSRichard Fitzgerald "always_on: %u\n" 12772d80a91bSRichard Fitzgerald "boot_on: %u\n" 12782d80a91bSRichard Fitzgerald "apply_uV: %u\n" 12792d80a91bSRichard Fitzgerald "ramp_disable: %u\n" 12802d80a91bSRichard Fitzgerald "soft_start: %u\n" 12812d80a91bSRichard Fitzgerald "pull_down: %u\n" 12822d80a91bSRichard Fitzgerald "over_current_protection: %u\n", 12832d80a91bSRichard Fitzgerald c->always_on, 12842d80a91bSRichard Fitzgerald c->boot_on, 12852d80a91bSRichard Fitzgerald c->apply_uV, 12862d80a91bSRichard Fitzgerald c->ramp_disable, 12872d80a91bSRichard Fitzgerald c->soft_start, 12882d80a91bSRichard Fitzgerald c->pull_down, 12892d80a91bSRichard Fitzgerald c->over_current_protection); 12902d80a91bSRichard Fitzgerald 12912d80a91bSRichard Fitzgerald ret = simple_read_from_buffer(user_buf, count, ppos, buf, ret); 12922d80a91bSRichard Fitzgerald kfree(buf); 12932d80a91bSRichard Fitzgerald 12942d80a91bSRichard Fitzgerald return ret; 12952d80a91bSRichard Fitzgerald } 12962d80a91bSRichard Fitzgerald 12972d80a91bSRichard Fitzgerald #endif 12982d80a91bSRichard Fitzgerald 12992d80a91bSRichard Fitzgerald static const struct file_operations constraint_flags_fops = { 13002d80a91bSRichard Fitzgerald #ifdef CONFIG_DEBUG_FS 13012d80a91bSRichard Fitzgerald .open = simple_open, 13022d80a91bSRichard Fitzgerald .read = constraint_flags_read_file, 13032d80a91bSRichard Fitzgerald .llseek = default_llseek, 13042d80a91bSRichard Fitzgerald #endif 13052d80a91bSRichard Fitzgerald }; 13062d80a91bSRichard Fitzgerald 1307f5726ae3SMark Brown #define REG_STR_SIZE 64 1308414c70cbSLiam Girdwood 1309414c70cbSLiam Girdwood static struct regulator *create_regulator(struct regulator_dev *rdev, 1310414c70cbSLiam Girdwood struct device *dev, 1311414c70cbSLiam Girdwood const char *supply_name) 1312414c70cbSLiam Girdwood { 1313414c70cbSLiam Girdwood struct regulator *regulator; 1314414c70cbSLiam Girdwood char buf[REG_STR_SIZE]; 1315414c70cbSLiam Girdwood int err, size; 1316414c70cbSLiam Girdwood 1317414c70cbSLiam Girdwood regulator = kzalloc(sizeof(*regulator), GFP_KERNEL); 1318414c70cbSLiam Girdwood if (regulator == NULL) 1319414c70cbSLiam Girdwood return NULL; 1320414c70cbSLiam Girdwood 1321414c70cbSLiam Girdwood mutex_lock(&rdev->mutex); 1322414c70cbSLiam Girdwood regulator->rdev = rdev; 1323414c70cbSLiam Girdwood list_add(®ulator->list, &rdev->consumer_list); 1324414c70cbSLiam Girdwood 1325414c70cbSLiam Girdwood if (dev) { 1326e2c98eafSShawn Guo regulator->dev = dev; 1327e2c98eafSShawn Guo 1328222cc7b1SMark Brown /* Add a link to the device sysfs entry */ 1329414c70cbSLiam Girdwood size = scnprintf(buf, REG_STR_SIZE, "%s-%s", 1330414c70cbSLiam Girdwood dev->kobj.name, supply_name); 1331414c70cbSLiam Girdwood if (size >= REG_STR_SIZE) 1332222cc7b1SMark Brown goto overflow_err; 1333414c70cbSLiam Girdwood 1334414c70cbSLiam Girdwood regulator->supply_name = kstrdup(buf, GFP_KERNEL); 1335414c70cbSLiam Girdwood if (regulator->supply_name == NULL) 1336222cc7b1SMark Brown goto overflow_err; 1337414c70cbSLiam Girdwood 1338ff268b56SStephen Boyd err = sysfs_create_link_nowarn(&rdev->dev.kobj, &dev->kobj, 1339414c70cbSLiam Girdwood buf); 1340414c70cbSLiam Girdwood if (err) { 1341ff268b56SStephen Boyd rdev_dbg(rdev, "could not add device link %s err %d\n", 13421d7372e1SDaniel Walker dev->kobj.name, err); 1343222cc7b1SMark Brown /* non-fatal */ 1344414c70cbSLiam Girdwood } 13455de70519SMark Brown } else { 13465de70519SMark Brown regulator->supply_name = kstrdup(supply_name, GFP_KERNEL); 13475de70519SMark Brown if (regulator->supply_name == NULL) 1348222cc7b1SMark Brown goto overflow_err; 1349414c70cbSLiam Girdwood } 13505de70519SMark Brown 13515de70519SMark Brown regulator->debugfs = debugfs_create_dir(regulator->supply_name, 13525de70519SMark Brown rdev->debugfs); 135324751434SStephen Boyd if (!regulator->debugfs) { 1354ad3a942bSStephen Boyd rdev_dbg(rdev, "Failed to create debugfs directory\n"); 13555de70519SMark Brown } else { 13565de70519SMark Brown debugfs_create_u32("uA_load", 0444, regulator->debugfs, 13575de70519SMark Brown ®ulator->uA_load); 13585de70519SMark Brown debugfs_create_u32("min_uV", 0444, regulator->debugfs, 13595de70519SMark Brown ®ulator->min_uV); 13605de70519SMark Brown debugfs_create_u32("max_uV", 0444, regulator->debugfs, 13615de70519SMark Brown ®ulator->max_uV); 13622d80a91bSRichard Fitzgerald debugfs_create_file("constraint_flags", 0444, 13632d80a91bSRichard Fitzgerald regulator->debugfs, regulator, 13642d80a91bSRichard Fitzgerald &constraint_flags_fops); 13655de70519SMark Brown } 13665de70519SMark Brown 13676492bc1bSMark Brown /* 13686492bc1bSMark Brown * Check now if the regulator is an always on regulator - if 13696492bc1bSMark Brown * it is then we don't need to do nearly so much work for 13706492bc1bSMark Brown * enable/disable calls. 13716492bc1bSMark Brown */ 13728a34e979SWEN Pingbo if (!regulator_ops_is_valid(rdev, REGULATOR_CHANGE_STATUS) && 13736492bc1bSMark Brown _regulator_is_enabled(rdev)) 13746492bc1bSMark Brown regulator->always_on = true; 13756492bc1bSMark Brown 1376414c70cbSLiam Girdwood mutex_unlock(&rdev->mutex); 1377414c70cbSLiam Girdwood return regulator; 1378414c70cbSLiam Girdwood overflow_err: 1379414c70cbSLiam Girdwood list_del(®ulator->list); 1380414c70cbSLiam Girdwood kfree(regulator); 1381414c70cbSLiam Girdwood mutex_unlock(&rdev->mutex); 1382414c70cbSLiam Girdwood return NULL; 1383414c70cbSLiam Girdwood } 1384414c70cbSLiam Girdwood 138531aae2beSMark Brown static int _regulator_get_enable_time(struct regulator_dev *rdev) 138631aae2beSMark Brown { 138700c877c6SLaxman Dewangan if (rdev->constraints && rdev->constraints->enable_time) 138800c877c6SLaxman Dewangan return rdev->constraints->enable_time; 138931aae2beSMark Brown if (!rdev->desc->ops->enable_time) 139079511ed3SMark Brown return rdev->desc->enable_time; 139131aae2beSMark Brown return rdev->desc->ops->enable_time(rdev); 139231aae2beSMark Brown } 139331aae2beSMark Brown 1394a06ccd9cSCharles Keepax static struct regulator_supply_alias *regulator_find_supply_alias( 1395a06ccd9cSCharles Keepax struct device *dev, const char *supply) 1396a06ccd9cSCharles Keepax { 1397a06ccd9cSCharles Keepax struct regulator_supply_alias *map; 1398a06ccd9cSCharles Keepax 1399a06ccd9cSCharles Keepax list_for_each_entry(map, ®ulator_supply_alias_list, list) 1400a06ccd9cSCharles Keepax if (map->src_dev == dev && strcmp(map->src_supply, supply) == 0) 1401a06ccd9cSCharles Keepax return map; 1402a06ccd9cSCharles Keepax 1403a06ccd9cSCharles Keepax return NULL; 1404a06ccd9cSCharles Keepax } 1405a06ccd9cSCharles Keepax 1406a06ccd9cSCharles Keepax static void regulator_supply_alias(struct device **dev, const char **supply) 1407a06ccd9cSCharles Keepax { 1408a06ccd9cSCharles Keepax struct regulator_supply_alias *map; 1409a06ccd9cSCharles Keepax 1410a06ccd9cSCharles Keepax map = regulator_find_supply_alias(*dev, *supply); 1411a06ccd9cSCharles Keepax if (map) { 1412a06ccd9cSCharles Keepax dev_dbg(*dev, "Mapping supply %s to %s,%s\n", 1413a06ccd9cSCharles Keepax *supply, map->alias_supply, 1414a06ccd9cSCharles Keepax dev_name(map->alias_dev)); 1415a06ccd9cSCharles Keepax *dev = map->alias_dev; 1416a06ccd9cSCharles Keepax *supply = map->alias_supply; 1417a06ccd9cSCharles Keepax } 1418a06ccd9cSCharles Keepax } 1419a06ccd9cSCharles Keepax 142085f3b431STomeu Vizoso static int of_node_match(struct device *dev, const void *data) 142185f3b431STomeu Vizoso { 142285f3b431STomeu Vizoso return dev->of_node == data; 142385f3b431STomeu Vizoso } 142485f3b431STomeu Vizoso 142585f3b431STomeu Vizoso static struct regulator_dev *of_find_regulator_by_node(struct device_node *np) 142685f3b431STomeu Vizoso { 142785f3b431STomeu Vizoso struct device *dev; 142885f3b431STomeu Vizoso 142985f3b431STomeu Vizoso dev = class_find_device(®ulator_class, NULL, np, of_node_match); 143085f3b431STomeu Vizoso 143185f3b431STomeu Vizoso return dev ? dev_to_rdev(dev) : NULL; 143285f3b431STomeu Vizoso } 143385f3b431STomeu Vizoso 143485f3b431STomeu Vizoso static int regulator_match(struct device *dev, const void *data) 143585f3b431STomeu Vizoso { 143685f3b431STomeu Vizoso struct regulator_dev *r = dev_to_rdev(dev); 143785f3b431STomeu Vizoso 143885f3b431STomeu Vizoso return strcmp(rdev_get_name(r), data) == 0; 143985f3b431STomeu Vizoso } 144085f3b431STomeu Vizoso 144185f3b431STomeu Vizoso static struct regulator_dev *regulator_lookup_by_name(const char *name) 144285f3b431STomeu Vizoso { 144385f3b431STomeu Vizoso struct device *dev; 144485f3b431STomeu Vizoso 144585f3b431STomeu Vizoso dev = class_find_device(®ulator_class, NULL, name, regulator_match); 144685f3b431STomeu Vizoso 144785f3b431STomeu Vizoso return dev ? dev_to_rdev(dev) : NULL; 144885f3b431STomeu Vizoso } 144985f3b431STomeu Vizoso 145085f3b431STomeu Vizoso /** 145185f3b431STomeu Vizoso * regulator_dev_lookup - lookup a regulator device. 145285f3b431STomeu Vizoso * @dev: device for regulator "consumer". 145385f3b431STomeu Vizoso * @supply: Supply name or regulator ID. 145485f3b431STomeu Vizoso * @ret: 0 on success, -ENODEV if lookup fails permanently, -EPROBE_DEFER if 145585f3b431STomeu Vizoso * lookup could succeed in the future. 145685f3b431STomeu Vizoso * 145785f3b431STomeu Vizoso * If successful, returns a struct regulator_dev that corresponds to the name 145885f3b431STomeu Vizoso * @supply and with the embedded struct device refcount incremented by one, 145985f3b431STomeu Vizoso * or NULL on failure. The refcount must be dropped by calling put_device(). 146085f3b431STomeu Vizoso */ 146169511a45SRajendra Nayak static struct regulator_dev *regulator_dev_lookup(struct device *dev, 14626d191a5fSMark Brown const char *supply, 14636d191a5fSMark Brown int *ret) 146469511a45SRajendra Nayak { 146569511a45SRajendra Nayak struct regulator_dev *r; 146669511a45SRajendra Nayak struct device_node *node; 1467576ca436SMark Brown struct regulator_map *map; 1468576ca436SMark Brown const char *devname = NULL; 146969511a45SRajendra Nayak 1470a06ccd9cSCharles Keepax regulator_supply_alias(&dev, &supply); 1471a06ccd9cSCharles Keepax 147269511a45SRajendra Nayak /* first do a dt based lookup */ 147369511a45SRajendra Nayak if (dev && dev->of_node) { 147469511a45SRajendra Nayak node = of_get_regulator(dev, supply); 14756d191a5fSMark Brown if (node) { 147685f3b431STomeu Vizoso r = of_find_regulator_by_node(node); 147785f3b431STomeu Vizoso if (r) 147869511a45SRajendra Nayak return r; 1479317b5684SMark Brown *ret = -EPROBE_DEFER; 1480317b5684SMark Brown return NULL; 14816d191a5fSMark Brown } else { 14826d191a5fSMark Brown /* 14836d191a5fSMark Brown * If we couldn't even get the node then it's 14846d191a5fSMark Brown * not just that the device didn't register 14856d191a5fSMark Brown * yet, there's no node and we'll never 14866d191a5fSMark Brown * succeed. 14876d191a5fSMark Brown */ 14886d191a5fSMark Brown *ret = -ENODEV; 14896d191a5fSMark Brown } 149069511a45SRajendra Nayak } 149169511a45SRajendra Nayak 149269511a45SRajendra Nayak /* if not found, try doing it non-dt way */ 1493576ca436SMark Brown if (dev) 1494576ca436SMark Brown devname = dev_name(dev); 1495576ca436SMark Brown 149685f3b431STomeu Vizoso r = regulator_lookup_by_name(supply); 149785f3b431STomeu Vizoso if (r) 149869511a45SRajendra Nayak return r; 149969511a45SRajendra Nayak 150085f3b431STomeu Vizoso mutex_lock(®ulator_list_mutex); 1501576ca436SMark Brown list_for_each_entry(map, ®ulator_map_list, list) { 1502576ca436SMark Brown /* If the mapping has a device set up it must match */ 1503576ca436SMark Brown if (map->dev_name && 1504576ca436SMark Brown (!devname || strcmp(map->dev_name, devname))) 1505576ca436SMark Brown continue; 1506576ca436SMark Brown 150785f3b431STomeu Vizoso if (strcmp(map->supply, supply) == 0 && 150885f3b431STomeu Vizoso get_device(&map->regulator->dev)) { 150985f3b431STomeu Vizoso mutex_unlock(®ulator_list_mutex); 1510576ca436SMark Brown return map->regulator; 1511576ca436SMark Brown } 151285f3b431STomeu Vizoso } 151385f3b431STomeu Vizoso mutex_unlock(®ulator_list_mutex); 1514576ca436SMark Brown 151569511a45SRajendra Nayak return NULL; 151669511a45SRajendra Nayak } 151769511a45SRajendra Nayak 15186261b06dSBjorn Andersson static int regulator_resolve_supply(struct regulator_dev *rdev) 15196261b06dSBjorn Andersson { 15206261b06dSBjorn Andersson struct regulator_dev *r; 15216261b06dSBjorn Andersson struct device *dev = rdev->dev.parent; 15226261b06dSBjorn Andersson int ret; 15236261b06dSBjorn Andersson 15246261b06dSBjorn Andersson /* No supply to resovle? */ 15256261b06dSBjorn Andersson if (!rdev->supply_name) 15266261b06dSBjorn Andersson return 0; 15276261b06dSBjorn Andersson 15286261b06dSBjorn Andersson /* Supply already resolved? */ 15296261b06dSBjorn Andersson if (rdev->supply) 15306261b06dSBjorn Andersson return 0; 15316261b06dSBjorn Andersson 15326261b06dSBjorn Andersson r = regulator_dev_lookup(dev, rdev->supply_name, &ret); 153323c3f310SCharles Keepax if (!r) { 15346261b06dSBjorn Andersson if (ret == -ENODEV) { 15356261b06dSBjorn Andersson /* 15366261b06dSBjorn Andersson * No supply was specified for this regulator and 15376261b06dSBjorn Andersson * there will never be one. 15386261b06dSBjorn Andersson */ 15396261b06dSBjorn Andersson return 0; 15406261b06dSBjorn Andersson } 15416261b06dSBjorn Andersson 154206423121SMark Brown /* Did the lookup explicitly defer for us? */ 154306423121SMark Brown if (ret == -EPROBE_DEFER) 154406423121SMark Brown return ret; 154506423121SMark Brown 15469f7e25edSMark Brown if (have_full_constraints()) { 15479f7e25edSMark Brown r = dummy_regulator_rdev; 154885f3b431STomeu Vizoso get_device(&r->dev); 15499f7e25edSMark Brown } else { 15506261b06dSBjorn Andersson dev_err(dev, "Failed to resolve %s-supply for %s\n", 15516261b06dSBjorn Andersson rdev->supply_name, rdev->desc->name); 15526261b06dSBjorn Andersson return -EPROBE_DEFER; 15536261b06dSBjorn Andersson } 15549f7e25edSMark Brown } 15556261b06dSBjorn Andersson 15566261b06dSBjorn Andersson /* Recursively resolve the supply of the supply */ 15576261b06dSBjorn Andersson ret = regulator_resolve_supply(r); 155885f3b431STomeu Vizoso if (ret < 0) { 155985f3b431STomeu Vizoso put_device(&r->dev); 15606261b06dSBjorn Andersson return ret; 156185f3b431STomeu Vizoso } 15626261b06dSBjorn Andersson 15636261b06dSBjorn Andersson ret = set_supply(rdev, r); 156485f3b431STomeu Vizoso if (ret < 0) { 156585f3b431STomeu Vizoso put_device(&r->dev); 15666261b06dSBjorn Andersson return ret; 156785f3b431STomeu Vizoso } 15686261b06dSBjorn Andersson 15696261b06dSBjorn Andersson /* Cascade always-on state to supply */ 157095a293c7SJavier Martinez Canillas if (_regulator_is_enabled(rdev)) { 15716261b06dSBjorn Andersson ret = regulator_enable(rdev->supply); 157236a1f1b6SJavier Martinez Canillas if (ret < 0) { 157336a1f1b6SJavier Martinez Canillas _regulator_put(rdev->supply); 15748e5356a7SJon Hunter rdev->supply = NULL; 15756261b06dSBjorn Andersson return ret; 15766261b06dSBjorn Andersson } 157736a1f1b6SJavier Martinez Canillas } 15786261b06dSBjorn Andersson 15796261b06dSBjorn Andersson return 0; 15806261b06dSBjorn Andersson } 15816261b06dSBjorn Andersson 15825ffbd136SMark Brown /* Internal regulator request function */ 1583a8bd42a9SDmitry Torokhov struct regulator *_regulator_get(struct device *dev, const char *id, 1584a8bd42a9SDmitry Torokhov enum regulator_get_type get_type) 1585414c70cbSLiam Girdwood { 1586414c70cbSLiam Girdwood struct regulator_dev *rdev; 15877d245afaSDmitry Torokhov struct regulator *regulator; 158840f9244fSMark Brown const char *devname = NULL; 1589317b5684SMark Brown int ret; 1590414c70cbSLiam Girdwood 1591a8bd42a9SDmitry Torokhov if (get_type >= MAX_GET_TYPE) { 1592a8bd42a9SDmitry Torokhov dev_err(dev, "invalid type %d in %s\n", get_type, __func__); 1593a8bd42a9SDmitry Torokhov return ERR_PTR(-EINVAL); 1594a8bd42a9SDmitry Torokhov } 1595a8bd42a9SDmitry Torokhov 1596414c70cbSLiam Girdwood if (id == NULL) { 15975da84fd9SJoe Perches pr_err("get() with no identifier\n"); 1598043c998fSMark Brown return ERR_PTR(-EINVAL); 1599414c70cbSLiam Girdwood } 1600414c70cbSLiam Girdwood 160140f9244fSMark Brown if (dev) 160240f9244fSMark Brown devname = dev_name(dev); 160340f9244fSMark Brown 16046d191a5fSMark Brown rdev = regulator_dev_lookup(dev, id, &ret); 160569511a45SRajendra Nayak if (rdev) 160669511a45SRajendra Nayak goto found; 160769511a45SRajendra Nayak 1608ef60abbbSMark Brown regulator = ERR_PTR(ret); 1609ef60abbbSMark Brown 16101e4b545cSNishanth Menon /* 16111e4b545cSNishanth Menon * If we have return value from dev_lookup fail, we do not expect to 16121e4b545cSNishanth Menon * succeed, so, quit with appropriate error value 16131e4b545cSNishanth Menon */ 16140d25d09dSJingoo Han if (ret && ret != -ENODEV) 161585f3b431STomeu Vizoso return regulator; 16161e4b545cSNishanth Menon 161734abbd68SMark Brown if (!devname) 161834abbd68SMark Brown devname = "deviceless"; 161934abbd68SMark Brown 16204ddfebd3SMark Brown /* 16214ddfebd3SMark Brown * Assume that a regulator is physically present and enabled 16224ddfebd3SMark Brown * even if it isn't hooked up and just provide a dummy. 162334abbd68SMark Brown */ 1624a8bd42a9SDmitry Torokhov if (have_full_constraints() && get_type == NORMAL_GET) { 16255da84fd9SJoe Perches pr_warn("%s supply %s not found, using dummy regulator\n", 162634abbd68SMark Brown devname, id); 16274ddfebd3SMark Brown 162834abbd68SMark Brown rdev = dummy_regulator_rdev; 162985f3b431STomeu Vizoso get_device(&rdev->dev); 163034abbd68SMark Brown goto found; 16310781719bSHans de Goede /* Don't log an error when called from regulator_get_optional() */ 1632a8bd42a9SDmitry Torokhov } else if (!have_full_constraints() || get_type == EXCLUSIVE_GET) { 1633acc3d5ceSShuah Khan dev_warn(dev, "dummy supplies not allowed\n"); 163434abbd68SMark Brown } 163534abbd68SMark Brown 1636414c70cbSLiam Girdwood return regulator; 1637414c70cbSLiam Girdwood 1638414c70cbSLiam Girdwood found: 16395ffbd136SMark Brown if (rdev->exclusive) { 16405ffbd136SMark Brown regulator = ERR_PTR(-EPERM); 164185f3b431STomeu Vizoso put_device(&rdev->dev); 164285f3b431STomeu Vizoso return regulator; 16435ffbd136SMark Brown } 16445ffbd136SMark Brown 1645a8bd42a9SDmitry Torokhov if (get_type == EXCLUSIVE_GET && rdev->open_count) { 16465ffbd136SMark Brown regulator = ERR_PTR(-EBUSY); 164785f3b431STomeu Vizoso put_device(&rdev->dev); 164885f3b431STomeu Vizoso return regulator; 16495ffbd136SMark Brown } 16505ffbd136SMark Brown 16516261b06dSBjorn Andersson ret = regulator_resolve_supply(rdev); 16526261b06dSBjorn Andersson if (ret < 0) { 16536261b06dSBjorn Andersson regulator = ERR_PTR(ret); 165485f3b431STomeu Vizoso put_device(&rdev->dev); 165585f3b431STomeu Vizoso return regulator; 16566261b06dSBjorn Andersson } 16576261b06dSBjorn Andersson 165885f3b431STomeu Vizoso if (!try_module_get(rdev->owner)) { 16597d245afaSDmitry Torokhov regulator = ERR_PTR(-EPROBE_DEFER); 166085f3b431STomeu Vizoso put_device(&rdev->dev); 166185f3b431STomeu Vizoso return regulator; 166285f3b431STomeu Vizoso } 1663a5766f11SLiam Girdwood 1664414c70cbSLiam Girdwood regulator = create_regulator(rdev, dev, id); 1665414c70cbSLiam Girdwood if (regulator == NULL) { 1666414c70cbSLiam Girdwood regulator = ERR_PTR(-ENOMEM); 166785f3b431STomeu Vizoso put_device(&rdev->dev); 1668414c70cbSLiam Girdwood module_put(rdev->owner); 166985f3b431STomeu Vizoso return regulator; 1670414c70cbSLiam Girdwood } 1671414c70cbSLiam Girdwood 16725ffbd136SMark Brown rdev->open_count++; 1673a8bd42a9SDmitry Torokhov if (get_type == EXCLUSIVE_GET) { 16745ffbd136SMark Brown rdev->exclusive = 1; 16755ffbd136SMark Brown 16765ffbd136SMark Brown ret = _regulator_is_enabled(rdev); 16775ffbd136SMark Brown if (ret > 0) 16785ffbd136SMark Brown rdev->use_count = 1; 16795ffbd136SMark Brown else 16805ffbd136SMark Brown rdev->use_count = 0; 16815ffbd136SMark Brown } 16825ffbd136SMark Brown 1683414c70cbSLiam Girdwood return regulator; 1684414c70cbSLiam Girdwood } 16855ffbd136SMark Brown 16865ffbd136SMark Brown /** 16875ffbd136SMark Brown * regulator_get - lookup and obtain a reference to a regulator. 16885ffbd136SMark Brown * @dev: device for regulator "consumer" 16895ffbd136SMark Brown * @id: Supply name or regulator ID. 16905ffbd136SMark Brown * 16915ffbd136SMark Brown * Returns a struct regulator corresponding to the regulator producer, 16925ffbd136SMark Brown * or IS_ERR() condition containing errno. 16935ffbd136SMark Brown * 16945ffbd136SMark Brown * Use of supply names configured via regulator_set_device_supply() is 16955ffbd136SMark Brown * strongly encouraged. It is recommended that the supply name used 16965ffbd136SMark Brown * should match the name used for the supply and/or the relevant 16975ffbd136SMark Brown * device pins in the datasheet. 16985ffbd136SMark Brown */ 16995ffbd136SMark Brown struct regulator *regulator_get(struct device *dev, const char *id) 17005ffbd136SMark Brown { 1701a8bd42a9SDmitry Torokhov return _regulator_get(dev, id, NORMAL_GET); 17025ffbd136SMark Brown } 1703414c70cbSLiam Girdwood EXPORT_SYMBOL_GPL(regulator_get); 1704414c70cbSLiam Girdwood 1705070b9079SStephen Boyd /** 17065ffbd136SMark Brown * regulator_get_exclusive - obtain exclusive access to a regulator. 17075ffbd136SMark Brown * @dev: device for regulator "consumer" 17085ffbd136SMark Brown * @id: Supply name or regulator ID. 17095ffbd136SMark Brown * 17105ffbd136SMark Brown * Returns a struct regulator corresponding to the regulator producer, 17115ffbd136SMark Brown * or IS_ERR() condition containing errno. Other consumers will be 171269c3f723SStephen Boyd * unable to obtain this regulator while this reference is held and the 171369c3f723SStephen Boyd * use count for the regulator will be initialised to reflect the current 171469c3f723SStephen Boyd * state of the regulator. 17155ffbd136SMark Brown * 17165ffbd136SMark Brown * This is intended for use by consumers which cannot tolerate shared 17175ffbd136SMark Brown * use of the regulator such as those which need to force the 17185ffbd136SMark Brown * regulator off for correct operation of the hardware they are 17195ffbd136SMark Brown * controlling. 17205ffbd136SMark Brown * 17215ffbd136SMark Brown * Use of supply names configured via regulator_set_device_supply() is 17225ffbd136SMark Brown * strongly encouraged. It is recommended that the supply name used 17235ffbd136SMark Brown * should match the name used for the supply and/or the relevant 17245ffbd136SMark Brown * device pins in the datasheet. 17255ffbd136SMark Brown */ 17265ffbd136SMark Brown struct regulator *regulator_get_exclusive(struct device *dev, const char *id) 17275ffbd136SMark Brown { 1728a8bd42a9SDmitry Torokhov return _regulator_get(dev, id, EXCLUSIVE_GET); 17295ffbd136SMark Brown } 17305ffbd136SMark Brown EXPORT_SYMBOL_GPL(regulator_get_exclusive); 17315ffbd136SMark Brown 1732de1dd9fdSMark Brown /** 1733de1dd9fdSMark Brown * regulator_get_optional - obtain optional access to a regulator. 1734de1dd9fdSMark Brown * @dev: device for regulator "consumer" 1735de1dd9fdSMark Brown * @id: Supply name or regulator ID. 1736de1dd9fdSMark Brown * 1737de1dd9fdSMark Brown * Returns a struct regulator corresponding to the regulator producer, 173869c3f723SStephen Boyd * or IS_ERR() condition containing errno. 1739de1dd9fdSMark Brown * 1740de1dd9fdSMark Brown * This is intended for use by consumers for devices which can have 1741de1dd9fdSMark Brown * some supplies unconnected in normal use, such as some MMC devices. 1742de1dd9fdSMark Brown * It can allow the regulator core to provide stub supplies for other 1743de1dd9fdSMark Brown * supplies requested using normal regulator_get() calls without 1744de1dd9fdSMark Brown * disrupting the operation of drivers that can handle absent 1745de1dd9fdSMark Brown * supplies. 1746de1dd9fdSMark Brown * 1747de1dd9fdSMark Brown * Use of supply names configured via regulator_set_device_supply() is 1748de1dd9fdSMark Brown * strongly encouraged. It is recommended that the supply name used 1749de1dd9fdSMark Brown * should match the name used for the supply and/or the relevant 1750de1dd9fdSMark Brown * device pins in the datasheet. 1751de1dd9fdSMark Brown */ 1752de1dd9fdSMark Brown struct regulator *regulator_get_optional(struct device *dev, const char *id) 1753de1dd9fdSMark Brown { 1754a8bd42a9SDmitry Torokhov return _regulator_get(dev, id, OPTIONAL_GET); 1755de1dd9fdSMark Brown } 1756de1dd9fdSMark Brown EXPORT_SYMBOL_GPL(regulator_get_optional); 1757de1dd9fdSMark Brown 175883b0302dSAshay Jaiswal /* regulator_list_mutex lock held by regulator_put() */ 175923ff2f0fSCharles Keepax static void _regulator_put(struct regulator *regulator) 1760414c70cbSLiam Girdwood { 1761414c70cbSLiam Girdwood struct regulator_dev *rdev; 1762414c70cbSLiam Girdwood 176393576842SViresh Kumar if (IS_ERR_OR_NULL(regulator)) 1764414c70cbSLiam Girdwood return; 1765414c70cbSLiam Girdwood 176670cfef26SKrzysztof Kozlowski lockdep_assert_held_once(®ulator_list_mutex); 176770cfef26SKrzysztof Kozlowski 1768414c70cbSLiam Girdwood rdev = regulator->rdev; 1769414c70cbSLiam Girdwood 17705de70519SMark Brown debugfs_remove_recursive(regulator->debugfs); 17715de70519SMark Brown 1772414c70cbSLiam Girdwood /* remove any sysfs entries */ 1773e2c98eafSShawn Guo if (regulator->dev) 1774414c70cbSLiam Girdwood sysfs_remove_link(&rdev->dev.kobj, regulator->supply_name); 177583b0302dSAshay Jaiswal mutex_lock(&rdev->mutex); 1776414c70cbSLiam Girdwood list_del(®ulator->list); 1777414c70cbSLiam Girdwood 17785ffbd136SMark Brown rdev->open_count--; 17795ffbd136SMark Brown rdev->exclusive = 0; 178085f3b431STomeu Vizoso put_device(&rdev->dev); 178183b0302dSAshay Jaiswal mutex_unlock(&rdev->mutex); 17825ffbd136SMark Brown 17831768514eSMark Brown kfree(regulator->supply_name); 17841768514eSMark Brown kfree(regulator); 17851768514eSMark Brown 1786414c70cbSLiam Girdwood module_put(rdev->owner); 178723ff2f0fSCharles Keepax } 178823ff2f0fSCharles Keepax 178923ff2f0fSCharles Keepax /** 179023ff2f0fSCharles Keepax * regulator_put - "free" the regulator source 179123ff2f0fSCharles Keepax * @regulator: regulator source 179223ff2f0fSCharles Keepax * 179323ff2f0fSCharles Keepax * Note: drivers must ensure that all regulator_enable calls made on this 179423ff2f0fSCharles Keepax * regulator source are balanced by regulator_disable calls prior to calling 179523ff2f0fSCharles Keepax * this function. 179623ff2f0fSCharles Keepax */ 179723ff2f0fSCharles Keepax void regulator_put(struct regulator *regulator) 179823ff2f0fSCharles Keepax { 179923ff2f0fSCharles Keepax mutex_lock(®ulator_list_mutex); 180023ff2f0fSCharles Keepax _regulator_put(regulator); 1801414c70cbSLiam Girdwood mutex_unlock(®ulator_list_mutex); 1802414c70cbSLiam Girdwood } 1803414c70cbSLiam Girdwood EXPORT_SYMBOL_GPL(regulator_put); 1804414c70cbSLiam Girdwood 1805a06ccd9cSCharles Keepax /** 1806a06ccd9cSCharles Keepax * regulator_register_supply_alias - Provide device alias for supply lookup 1807a06ccd9cSCharles Keepax * 1808a06ccd9cSCharles Keepax * @dev: device that will be given as the regulator "consumer" 1809a06ccd9cSCharles Keepax * @id: Supply name or regulator ID 1810a06ccd9cSCharles Keepax * @alias_dev: device that should be used to lookup the supply 1811a06ccd9cSCharles Keepax * @alias_id: Supply name or regulator ID that should be used to lookup the 1812a06ccd9cSCharles Keepax * supply 1813a06ccd9cSCharles Keepax * 1814a06ccd9cSCharles Keepax * All lookups for id on dev will instead be conducted for alias_id on 1815a06ccd9cSCharles Keepax * alias_dev. 1816a06ccd9cSCharles Keepax */ 1817a06ccd9cSCharles Keepax int regulator_register_supply_alias(struct device *dev, const char *id, 1818a06ccd9cSCharles Keepax struct device *alias_dev, 1819a06ccd9cSCharles Keepax const char *alias_id) 1820a06ccd9cSCharles Keepax { 1821a06ccd9cSCharles Keepax struct regulator_supply_alias *map; 1822a06ccd9cSCharles Keepax 1823a06ccd9cSCharles Keepax map = regulator_find_supply_alias(dev, id); 1824a06ccd9cSCharles Keepax if (map) 1825a06ccd9cSCharles Keepax return -EEXIST; 1826a06ccd9cSCharles Keepax 1827a06ccd9cSCharles Keepax map = kzalloc(sizeof(struct regulator_supply_alias), GFP_KERNEL); 1828a06ccd9cSCharles Keepax if (!map) 1829a06ccd9cSCharles Keepax return -ENOMEM; 1830a06ccd9cSCharles Keepax 1831a06ccd9cSCharles Keepax map->src_dev = dev; 1832a06ccd9cSCharles Keepax map->src_supply = id; 1833a06ccd9cSCharles Keepax map->alias_dev = alias_dev; 1834a06ccd9cSCharles Keepax map->alias_supply = alias_id; 1835a06ccd9cSCharles Keepax 1836a06ccd9cSCharles Keepax list_add(&map->list, ®ulator_supply_alias_list); 1837a06ccd9cSCharles Keepax 1838a06ccd9cSCharles Keepax pr_info("Adding alias for supply %s,%s -> %s,%s\n", 1839a06ccd9cSCharles Keepax id, dev_name(dev), alias_id, dev_name(alias_dev)); 1840a06ccd9cSCharles Keepax 1841a06ccd9cSCharles Keepax return 0; 1842a06ccd9cSCharles Keepax } 1843a06ccd9cSCharles Keepax EXPORT_SYMBOL_GPL(regulator_register_supply_alias); 1844a06ccd9cSCharles Keepax 1845a06ccd9cSCharles Keepax /** 1846a06ccd9cSCharles Keepax * regulator_unregister_supply_alias - Remove device alias 1847a06ccd9cSCharles Keepax * 1848a06ccd9cSCharles Keepax * @dev: device that will be given as the regulator "consumer" 1849a06ccd9cSCharles Keepax * @id: Supply name or regulator ID 1850a06ccd9cSCharles Keepax * 1851a06ccd9cSCharles Keepax * Remove a lookup alias if one exists for id on dev. 1852a06ccd9cSCharles Keepax */ 1853a06ccd9cSCharles Keepax void regulator_unregister_supply_alias(struct device *dev, const char *id) 1854a06ccd9cSCharles Keepax { 1855a06ccd9cSCharles Keepax struct regulator_supply_alias *map; 1856a06ccd9cSCharles Keepax 1857a06ccd9cSCharles Keepax map = regulator_find_supply_alias(dev, id); 1858a06ccd9cSCharles Keepax if (map) { 1859a06ccd9cSCharles Keepax list_del(&map->list); 1860a06ccd9cSCharles Keepax kfree(map); 1861a06ccd9cSCharles Keepax } 1862a06ccd9cSCharles Keepax } 1863a06ccd9cSCharles Keepax EXPORT_SYMBOL_GPL(regulator_unregister_supply_alias); 1864a06ccd9cSCharles Keepax 1865a06ccd9cSCharles Keepax /** 1866a06ccd9cSCharles Keepax * regulator_bulk_register_supply_alias - register multiple aliases 1867a06ccd9cSCharles Keepax * 1868a06ccd9cSCharles Keepax * @dev: device that will be given as the regulator "consumer" 1869a06ccd9cSCharles Keepax * @id: List of supply names or regulator IDs 1870a06ccd9cSCharles Keepax * @alias_dev: device that should be used to lookup the supply 1871a06ccd9cSCharles Keepax * @alias_id: List of supply names or regulator IDs that should be used to 1872a06ccd9cSCharles Keepax * lookup the supply 1873a06ccd9cSCharles Keepax * @num_id: Number of aliases to register 1874a06ccd9cSCharles Keepax * 1875a06ccd9cSCharles Keepax * @return 0 on success, an errno on failure. 1876a06ccd9cSCharles Keepax * 1877a06ccd9cSCharles Keepax * This helper function allows drivers to register several supply 1878a06ccd9cSCharles Keepax * aliases in one operation. If any of the aliases cannot be 1879a06ccd9cSCharles Keepax * registered any aliases that were registered will be removed 1880a06ccd9cSCharles Keepax * before returning to the caller. 1881a06ccd9cSCharles Keepax */ 18829f8c0fe9SLee Jones int regulator_bulk_register_supply_alias(struct device *dev, 18839f8c0fe9SLee Jones const char *const *id, 1884a06ccd9cSCharles Keepax struct device *alias_dev, 18859f8c0fe9SLee Jones const char *const *alias_id, 1886a06ccd9cSCharles Keepax int num_id) 1887a06ccd9cSCharles Keepax { 1888a06ccd9cSCharles Keepax int i; 1889a06ccd9cSCharles Keepax int ret; 1890a06ccd9cSCharles Keepax 1891a06ccd9cSCharles Keepax for (i = 0; i < num_id; ++i) { 1892a06ccd9cSCharles Keepax ret = regulator_register_supply_alias(dev, id[i], alias_dev, 1893a06ccd9cSCharles Keepax alias_id[i]); 1894a06ccd9cSCharles Keepax if (ret < 0) 1895a06ccd9cSCharles Keepax goto err; 1896a06ccd9cSCharles Keepax } 1897a06ccd9cSCharles Keepax 1898a06ccd9cSCharles Keepax return 0; 1899a06ccd9cSCharles Keepax 1900a06ccd9cSCharles Keepax err: 1901a06ccd9cSCharles Keepax dev_err(dev, 1902a06ccd9cSCharles Keepax "Failed to create supply alias %s,%s -> %s,%s\n", 1903a06ccd9cSCharles Keepax id[i], dev_name(dev), alias_id[i], dev_name(alias_dev)); 1904a06ccd9cSCharles Keepax 1905a06ccd9cSCharles Keepax while (--i >= 0) 1906a06ccd9cSCharles Keepax regulator_unregister_supply_alias(dev, id[i]); 1907a06ccd9cSCharles Keepax 1908a06ccd9cSCharles Keepax return ret; 1909a06ccd9cSCharles Keepax } 1910a06ccd9cSCharles Keepax EXPORT_SYMBOL_GPL(regulator_bulk_register_supply_alias); 1911a06ccd9cSCharles Keepax 1912a06ccd9cSCharles Keepax /** 1913a06ccd9cSCharles Keepax * regulator_bulk_unregister_supply_alias - unregister multiple aliases 1914a06ccd9cSCharles Keepax * 1915a06ccd9cSCharles Keepax * @dev: device that will be given as the regulator "consumer" 1916a06ccd9cSCharles Keepax * @id: List of supply names or regulator IDs 1917a06ccd9cSCharles Keepax * @num_id: Number of aliases to unregister 1918a06ccd9cSCharles Keepax * 1919a06ccd9cSCharles Keepax * This helper function allows drivers to unregister several supply 1920a06ccd9cSCharles Keepax * aliases in one operation. 1921a06ccd9cSCharles Keepax */ 1922a06ccd9cSCharles Keepax void regulator_bulk_unregister_supply_alias(struct device *dev, 19239f8c0fe9SLee Jones const char *const *id, 1924a06ccd9cSCharles Keepax int num_id) 1925a06ccd9cSCharles Keepax { 1926a06ccd9cSCharles Keepax int i; 1927a06ccd9cSCharles Keepax 1928a06ccd9cSCharles Keepax for (i = 0; i < num_id; ++i) 1929a06ccd9cSCharles Keepax regulator_unregister_supply_alias(dev, id[i]); 1930a06ccd9cSCharles Keepax } 1931a06ccd9cSCharles Keepax EXPORT_SYMBOL_GPL(regulator_bulk_unregister_supply_alias); 1932a06ccd9cSCharles Keepax 1933a06ccd9cSCharles Keepax 1934f19b00daSKim, Milo /* Manage enable GPIO list. Same GPIO pin can be shared among regulators */ 1935f19b00daSKim, Milo static int regulator_ena_gpio_request(struct regulator_dev *rdev, 1936f19b00daSKim, Milo const struct regulator_config *config) 1937f19b00daSKim, Milo { 1938f19b00daSKim, Milo struct regulator_enable_gpio *pin; 1939778b28b4SRussell King struct gpio_desc *gpiod; 1940f19b00daSKim, Milo int ret; 1941f19b00daSKim, Milo 1942778b28b4SRussell King gpiod = gpio_to_desc(config->ena_gpio); 1943778b28b4SRussell King 1944f19b00daSKim, Milo list_for_each_entry(pin, ®ulator_ena_gpio_list, list) { 1945778b28b4SRussell King if (pin->gpiod == gpiod) { 1946f19b00daSKim, Milo rdev_dbg(rdev, "GPIO %d is already used\n", 1947f19b00daSKim, Milo config->ena_gpio); 1948f19b00daSKim, Milo goto update_ena_gpio_to_rdev; 1949f19b00daSKim, Milo } 1950f19b00daSKim, Milo } 1951f19b00daSKim, Milo 1952f19b00daSKim, Milo ret = gpio_request_one(config->ena_gpio, 1953f19b00daSKim, Milo GPIOF_DIR_OUT | config->ena_gpio_flags, 1954f19b00daSKim, Milo rdev_get_name(rdev)); 1955f19b00daSKim, Milo if (ret) 1956f19b00daSKim, Milo return ret; 1957f19b00daSKim, Milo 1958f19b00daSKim, Milo pin = kzalloc(sizeof(struct regulator_enable_gpio), GFP_KERNEL); 1959f19b00daSKim, Milo if (pin == NULL) { 1960f19b00daSKim, Milo gpio_free(config->ena_gpio); 1961f19b00daSKim, Milo return -ENOMEM; 1962f19b00daSKim, Milo } 1963f19b00daSKim, Milo 1964778b28b4SRussell King pin->gpiod = gpiod; 1965f19b00daSKim, Milo pin->ena_gpio_invert = config->ena_gpio_invert; 1966f19b00daSKim, Milo list_add(&pin->list, ®ulator_ena_gpio_list); 1967f19b00daSKim, Milo 1968f19b00daSKim, Milo update_ena_gpio_to_rdev: 1969f19b00daSKim, Milo pin->request_count++; 1970f19b00daSKim, Milo rdev->ena_pin = pin; 1971f19b00daSKim, Milo return 0; 1972f19b00daSKim, Milo } 1973f19b00daSKim, Milo 1974f19b00daSKim, Milo static void regulator_ena_gpio_free(struct regulator_dev *rdev) 1975f19b00daSKim, Milo { 1976f19b00daSKim, Milo struct regulator_enable_gpio *pin, *n; 1977f19b00daSKim, Milo 1978f19b00daSKim, Milo if (!rdev->ena_pin) 1979f19b00daSKim, Milo return; 1980f19b00daSKim, Milo 1981f19b00daSKim, Milo /* Free the GPIO only in case of no use */ 1982f19b00daSKim, Milo list_for_each_entry_safe(pin, n, ®ulator_ena_gpio_list, list) { 1983778b28b4SRussell King if (pin->gpiod == rdev->ena_pin->gpiod) { 1984f19b00daSKim, Milo if (pin->request_count <= 1) { 1985f19b00daSKim, Milo pin->request_count = 0; 1986778b28b4SRussell King gpiod_put(pin->gpiod); 1987f19b00daSKim, Milo list_del(&pin->list); 1988f19b00daSKim, Milo kfree(pin); 198960a2362fSSeung-Woo Kim rdev->ena_pin = NULL; 199060a2362fSSeung-Woo Kim return; 1991f19b00daSKim, Milo } else { 1992f19b00daSKim, Milo pin->request_count--; 1993f19b00daSKim, Milo } 1994f19b00daSKim, Milo } 1995f19b00daSKim, Milo } 1996f19b00daSKim, Milo } 1997f19b00daSKim, Milo 1998967cfb18SKim, Milo /** 199931d6eebfSRobert P. J. Day * regulator_ena_gpio_ctrl - balance enable_count of each GPIO and actual GPIO pin control 200031d6eebfSRobert P. J. Day * @rdev: regulator_dev structure 200131d6eebfSRobert P. J. Day * @enable: enable GPIO at initial use? 200231d6eebfSRobert P. J. Day * 2003967cfb18SKim, Milo * GPIO is enabled in case of initial use. (enable_count is 0) 2004967cfb18SKim, Milo * GPIO is disabled when it is not shared any more. (enable_count <= 1) 2005967cfb18SKim, Milo */ 2006967cfb18SKim, Milo static int regulator_ena_gpio_ctrl(struct regulator_dev *rdev, bool enable) 2007967cfb18SKim, Milo { 2008967cfb18SKim, Milo struct regulator_enable_gpio *pin = rdev->ena_pin; 2009967cfb18SKim, Milo 2010967cfb18SKim, Milo if (!pin) 2011967cfb18SKim, Milo return -EINVAL; 2012967cfb18SKim, Milo 2013967cfb18SKim, Milo if (enable) { 2014967cfb18SKim, Milo /* Enable GPIO at initial use */ 2015967cfb18SKim, Milo if (pin->enable_count == 0) 2016778b28b4SRussell King gpiod_set_value_cansleep(pin->gpiod, 2017967cfb18SKim, Milo !pin->ena_gpio_invert); 2018967cfb18SKim, Milo 2019967cfb18SKim, Milo pin->enable_count++; 2020967cfb18SKim, Milo } else { 2021967cfb18SKim, Milo if (pin->enable_count > 1) { 2022967cfb18SKim, Milo pin->enable_count--; 2023967cfb18SKim, Milo return 0; 2024967cfb18SKim, Milo } 2025967cfb18SKim, Milo 2026967cfb18SKim, Milo /* Disable GPIO if not used */ 2027967cfb18SKim, Milo if (pin->enable_count <= 1) { 2028778b28b4SRussell King gpiod_set_value_cansleep(pin->gpiod, 2029967cfb18SKim, Milo pin->ena_gpio_invert); 2030967cfb18SKim, Milo pin->enable_count = 0; 2031967cfb18SKim, Milo } 2032967cfb18SKim, Milo } 2033967cfb18SKim, Milo 2034967cfb18SKim, Milo return 0; 2035967cfb18SKim, Milo } 2036967cfb18SKim, Milo 203779fd1141SGuodong Xu /** 203879fd1141SGuodong Xu * _regulator_enable_delay - a delay helper function 203979fd1141SGuodong Xu * @delay: time to delay in microseconds 204079fd1141SGuodong Xu * 20415df529d4SThierry Reding * Delay for the requested amount of time as per the guidelines in: 20425df529d4SThierry Reding * 20435df529d4SThierry Reding * Documentation/timers/timers-howto.txt 20445df529d4SThierry Reding * 20455df529d4SThierry Reding * The assumption here is that regulators will never be enabled in 20465df529d4SThierry Reding * atomic context and therefore sleeping functions can be used. 20475df529d4SThierry Reding */ 204879fd1141SGuodong Xu static void _regulator_enable_delay(unsigned int delay) 204979fd1141SGuodong Xu { 20505df529d4SThierry Reding unsigned int ms = delay / 1000; 20515df529d4SThierry Reding unsigned int us = delay % 1000; 20525df529d4SThierry Reding 20535df529d4SThierry Reding if (ms > 0) { 20545df529d4SThierry Reding /* 20555df529d4SThierry Reding * For small enough values, handle super-millisecond 20565df529d4SThierry Reding * delays in the usleep_range() call below. 20575df529d4SThierry Reding */ 20585df529d4SThierry Reding if (ms < 20) 20595df529d4SThierry Reding us += ms * 1000; 20605df529d4SThierry Reding else 20615df529d4SThierry Reding msleep(ms); 20625df529d4SThierry Reding } 20635df529d4SThierry Reding 20645df529d4SThierry Reding /* 20655df529d4SThierry Reding * Give the scheduler some room to coalesce with any other 20665df529d4SThierry Reding * wakeup sources. For delays shorter than 10 us, don't even 20675df529d4SThierry Reding * bother setting up high-resolution timers and just busy- 20685df529d4SThierry Reding * loop. 20695df529d4SThierry Reding */ 20705df529d4SThierry Reding if (us >= 10) 20715df529d4SThierry Reding usleep_range(us, us + 100); 20725df529d4SThierry Reding else 20735df529d4SThierry Reding udelay(us); 20745c5659d0SMark Brown } 20755c5659d0SMark Brown 20765c5659d0SMark Brown static int _regulator_do_enable(struct regulator_dev *rdev) 20775c5659d0SMark Brown { 20785c5659d0SMark Brown int ret, delay; 20795c5659d0SMark Brown 20805c5659d0SMark Brown /* Query before enabling in case configuration dependent. */ 20815c5659d0SMark Brown ret = _regulator_get_enable_time(rdev); 20825c5659d0SMark Brown if (ret >= 0) { 20835c5659d0SMark Brown delay = ret; 20845c5659d0SMark Brown } else { 2085414c70cbSLiam Girdwood rdev_warn(rdev, "enable_time() failed: %d\n", ret); 2086414c70cbSLiam Girdwood delay = 0; 2087414c70cbSLiam Girdwood } 20885c5659d0SMark Brown 2089414c70cbSLiam Girdwood trace_regulator_enable(rdev_get_name(rdev)); 2090414c70cbSLiam Girdwood 2091871f5650SGuodong Xu if (rdev->desc->off_on_delay) { 2092871f5650SGuodong Xu /* if needed, keep a distance of off_on_delay from last time 2093871f5650SGuodong Xu * this regulator was disabled. 2094871f5650SGuodong Xu */ 2095871f5650SGuodong Xu unsigned long start_jiffy = jiffies; 2096871f5650SGuodong Xu unsigned long intended, max_delay, remaining; 2097871f5650SGuodong Xu 2098871f5650SGuodong Xu max_delay = usecs_to_jiffies(rdev->desc->off_on_delay); 2099871f5650SGuodong Xu intended = rdev->last_off_jiffy + max_delay; 2100871f5650SGuodong Xu 2101871f5650SGuodong Xu if (time_before(start_jiffy, intended)) { 2102871f5650SGuodong Xu /* calc remaining jiffies to deal with one-time 2103871f5650SGuodong Xu * timer wrapping. 2104871f5650SGuodong Xu * in case of multiple timer wrapping, either it can be 2105871f5650SGuodong Xu * detected by out-of-range remaining, or it cannot be 2106871f5650SGuodong Xu * detected and we gets a panelty of 2107871f5650SGuodong Xu * _regulator_enable_delay(). 2108871f5650SGuodong Xu */ 2109871f5650SGuodong Xu remaining = intended - start_jiffy; 2110871f5650SGuodong Xu if (remaining <= max_delay) 2111871f5650SGuodong Xu _regulator_enable_delay( 2112871f5650SGuodong Xu jiffies_to_usecs(remaining)); 2113871f5650SGuodong Xu } 2114871f5650SGuodong Xu } 2115871f5650SGuodong Xu 2116414c70cbSLiam Girdwood if (rdev->ena_pin) { 211729d62ec5SDoug Anderson if (!rdev->ena_gpio_state) { 21189a2372faSMark Brown ret = regulator_ena_gpio_ctrl(rdev, true); 2119414c70cbSLiam Girdwood if (ret < 0) 2120414c70cbSLiam Girdwood return ret; 21219a2372faSMark Brown rdev->ena_gpio_state = 1; 212229d62ec5SDoug Anderson } 21239a2372faSMark Brown } else if (rdev->desc->ops->enable) { 21249a2372faSMark Brown ret = rdev->desc->ops->enable(rdev); 21259a2372faSMark Brown if (ret < 0) 21269a2372faSMark Brown return ret; 21279a2372faSMark Brown } else { 21289a2372faSMark Brown return -EINVAL; 21295c5659d0SMark Brown } 21309a2372faSMark Brown 21319a2372faSMark Brown /* Allow the regulator to ramp; it would be useful to extend 213231aae2beSMark Brown * this for bulk operations so that the regulators can ramp 2133a7433cffSLinus Walleij * together. */ 21345da84fd9SJoe Perches trace_regulator_enable_delay(rdev_get_name(rdev)); 2135414c70cbSLiam Girdwood 213679fd1141SGuodong Xu _regulator_enable_delay(delay); 2137a7433cffSLinus Walleij 2138414c70cbSLiam Girdwood trace_regulator_enable_complete(rdev_get_name(rdev)); 2139414c70cbSLiam Girdwood 21409a2372faSMark Brown return 0; 21419a2372faSMark Brown } 21429a2372faSMark Brown 2143414c70cbSLiam Girdwood /* locks held by regulator_enable() */ 2144414c70cbSLiam Girdwood static int _regulator_enable(struct regulator_dev *rdev) 2145414c70cbSLiam Girdwood { 2146414c70cbSLiam Girdwood int ret; 2147414c70cbSLiam Girdwood 214870cfef26SKrzysztof Kozlowski lockdep_assert_held_once(&rdev->mutex); 214970cfef26SKrzysztof Kozlowski 2150414c70cbSLiam Girdwood /* check voltage and requested load before enabling */ 21518a34e979SWEN Pingbo if (regulator_ops_is_valid(rdev, REGULATOR_CHANGE_DRMS)) 2152cf7bbcdfSMark Brown drms_uA_update(rdev); 2153cf7bbcdfSMark Brown 2154414c70cbSLiam Girdwood if (rdev->use_count == 0) { 2155cf7bbcdfSMark Brown /* The regulator may on if it's not switchable or left on */ 2156414c70cbSLiam Girdwood ret = _regulator_is_enabled(rdev); 2157414c70cbSLiam Girdwood if (ret == -EINVAL || ret == 0) { 21588a34e979SWEN Pingbo if (!regulator_ops_is_valid(rdev, 21598a34e979SWEN Pingbo REGULATOR_CHANGE_STATUS)) 2160412aec61SDavid Brownell return -EPERM; 2161412aec61SDavid Brownell 2162414c70cbSLiam Girdwood ret = _regulator_do_enable(rdev); 2163412aec61SDavid Brownell if (ret < 0) 2164412aec61SDavid Brownell return ret; 2165412aec61SDavid Brownell 2166414c70cbSLiam Girdwood } else if (ret < 0) { 2167414c70cbSLiam Girdwood rdev_err(rdev, "is_enabled() failed: %d\n", ret); 2168414c70cbSLiam Girdwood return ret; 2169414c70cbSLiam Girdwood } 2170414c70cbSLiam Girdwood /* Fallthrough on positive return values - already enabled */ 2171414c70cbSLiam Girdwood } 2172414c70cbSLiam Girdwood 2173414c70cbSLiam Girdwood rdev->use_count++; 2174414c70cbSLiam Girdwood 2175cd94b505SDavid Brownell return 0; 2176cd94b505SDavid Brownell } 21771083c393SMark Brown 2178cd94b505SDavid Brownell /** 2179cd94b505SDavid Brownell * regulator_enable - enable regulator output 2180414c70cbSLiam Girdwood * @regulator: regulator source 218160ef66fcSMark Brown * 218260ef66fcSMark Brown * Request that the regulator be enabled with the regulator output at 2183414c70cbSLiam Girdwood * the predefined voltage or current value. Calls to regulator_enable() 2184414c70cbSLiam Girdwood * must be balanced with calls to regulator_disable(). 21859a2372faSMark Brown * 21869a2372faSMark Brown * NOTE: the output value can be set by other drivers, boot loader or may be 2187414c70cbSLiam Girdwood * hardwired in the regulator. 2188414c70cbSLiam Girdwood */ 2189414c70cbSLiam Girdwood int regulator_enable(struct regulator *regulator) 21901083c393SMark Brown { 2191414c70cbSLiam Girdwood struct regulator_dev *rdev = regulator->rdev; 2192414c70cbSLiam Girdwood int ret = 0; 219384b68263SMark Brown 21946492bc1bSMark Brown if (regulator->always_on) 21956492bc1bSMark Brown return 0; 21966492bc1bSMark Brown 21973801b86aSMark Brown if (rdev->supply) { 21983801b86aSMark Brown ret = regulator_enable(rdev->supply); 21993801b86aSMark Brown if (ret != 0) 22003801b86aSMark Brown return ret; 22013801b86aSMark Brown } 22023801b86aSMark Brown 2203414c70cbSLiam Girdwood mutex_lock(&rdev->mutex); 2204414c70cbSLiam Girdwood ret = _regulator_enable(rdev); 2205414c70cbSLiam Girdwood mutex_unlock(&rdev->mutex); 22063801b86aSMark Brown 2207d1685e4eSHeiko Stübner if (ret != 0 && rdev->supply) 22083801b86aSMark Brown regulator_disable(rdev->supply); 22093801b86aSMark Brown 2210414c70cbSLiam Girdwood return ret; 2211414c70cbSLiam Girdwood } 2212414c70cbSLiam Girdwood EXPORT_SYMBOL_GPL(regulator_enable); 2213414c70cbSLiam Girdwood 22145c5659d0SMark Brown static int _regulator_do_disable(struct regulator_dev *rdev) 22155c5659d0SMark Brown { 22165c5659d0SMark Brown int ret; 22175c5659d0SMark Brown 22185c5659d0SMark Brown trace_regulator_disable(rdev_get_name(rdev)); 22195c5659d0SMark Brown 2220967cfb18SKim, Milo if (rdev->ena_pin) { 222129d62ec5SDoug Anderson if (rdev->ena_gpio_state) { 2222967cfb18SKim, Milo ret = regulator_ena_gpio_ctrl(rdev, false); 2223967cfb18SKim, Milo if (ret < 0) 2224967cfb18SKim, Milo return ret; 22255c5659d0SMark Brown rdev->ena_gpio_state = 0; 222629d62ec5SDoug Anderson } 22275c5659d0SMark Brown 22285c5659d0SMark Brown } else if (rdev->desc->ops->disable) { 22295c5659d0SMark Brown ret = rdev->desc->ops->disable(rdev); 22305c5659d0SMark Brown if (ret != 0) 22315c5659d0SMark Brown return ret; 22325c5659d0SMark Brown } 22335c5659d0SMark Brown 2234871f5650SGuodong Xu /* cares about last_off_jiffy only if off_on_delay is required by 2235871f5650SGuodong Xu * device. 2236871f5650SGuodong Xu */ 2237871f5650SGuodong Xu if (rdev->desc->off_on_delay) 2238871f5650SGuodong Xu rdev->last_off_jiffy = jiffies; 2239871f5650SGuodong Xu 22405c5659d0SMark Brown trace_regulator_disable_complete(rdev_get_name(rdev)); 22415c5659d0SMark Brown 22425c5659d0SMark Brown return 0; 22435c5659d0SMark Brown } 22445c5659d0SMark Brown 2245414c70cbSLiam Girdwood /* locks held by regulator_disable() */ 22463801b86aSMark Brown static int _regulator_disable(struct regulator_dev *rdev) 2247414c70cbSLiam Girdwood { 2248414c70cbSLiam Girdwood int ret = 0; 2249414c70cbSLiam Girdwood 225070cfef26SKrzysztof Kozlowski lockdep_assert_held_once(&rdev->mutex); 225170cfef26SKrzysztof Kozlowski 2252414c70cbSLiam Girdwood if (WARN(rdev->use_count <= 0, 225343e7ee33SJoe Perches "unbalanced disables for %s\n", rdev_get_name(rdev))) 2254414c70cbSLiam Girdwood return -EIO; 2255414c70cbSLiam Girdwood 2256414c70cbSLiam Girdwood /* are we the last user and permitted to disable ? */ 2257414c70cbSLiam Girdwood if (rdev->use_count == 1 && 2258414c70cbSLiam Girdwood (rdev->constraints && !rdev->constraints->always_on)) { 2259414c70cbSLiam Girdwood 2260414c70cbSLiam Girdwood /* we are last user */ 22618a34e979SWEN Pingbo if (regulator_ops_is_valid(rdev, REGULATOR_CHANGE_STATUS)) { 2262a1c8a551SRichard Fitzgerald ret = _notifier_call_chain(rdev, 2263a1c8a551SRichard Fitzgerald REGULATOR_EVENT_PRE_DISABLE, 2264a1c8a551SRichard Fitzgerald NULL); 2265a1c8a551SRichard Fitzgerald if (ret & NOTIFY_STOP_MASK) 2266a1c8a551SRichard Fitzgerald return -EINVAL; 2267a1c8a551SRichard Fitzgerald 22685c5659d0SMark Brown ret = _regulator_do_disable(rdev); 2269414c70cbSLiam Girdwood if (ret < 0) { 22705da84fd9SJoe Perches rdev_err(rdev, "failed to disable\n"); 2271a1c8a551SRichard Fitzgerald _notifier_call_chain(rdev, 2272a1c8a551SRichard Fitzgerald REGULATOR_EVENT_ABORT_DISABLE, 2273a1c8a551SRichard Fitzgerald NULL); 2274414c70cbSLiam Girdwood return ret; 2275414c70cbSLiam Girdwood } 227666fda75fSMarkus Pargmann _notifier_call_chain(rdev, REGULATOR_EVENT_DISABLE, 227766fda75fSMarkus Pargmann NULL); 2278414c70cbSLiam Girdwood } 2279414c70cbSLiam Girdwood 2280414c70cbSLiam Girdwood rdev->use_count = 0; 2281414c70cbSLiam Girdwood } else if (rdev->use_count > 1) { 22828a34e979SWEN Pingbo if (regulator_ops_is_valid(rdev, REGULATOR_CHANGE_DRMS)) 2283414c70cbSLiam Girdwood drms_uA_update(rdev); 2284414c70cbSLiam Girdwood 2285414c70cbSLiam Girdwood rdev->use_count--; 2286414c70cbSLiam Girdwood } 22873801b86aSMark Brown 2288414c70cbSLiam Girdwood return ret; 2289414c70cbSLiam Girdwood } 2290414c70cbSLiam Girdwood 2291414c70cbSLiam Girdwood /** 2292414c70cbSLiam Girdwood * regulator_disable - disable regulator output 2293414c70cbSLiam Girdwood * @regulator: regulator source 2294414c70cbSLiam Girdwood * 2295cf7bbcdfSMark Brown * Disable the regulator output voltage or current. Calls to 2296cf7bbcdfSMark Brown * regulator_enable() must be balanced with calls to 2297cf7bbcdfSMark Brown * regulator_disable(). 229869279fb9SMark Brown * 2299414c70cbSLiam Girdwood * NOTE: this will only disable the regulator output if no other consumer 2300cf7bbcdfSMark Brown * devices have it enabled, the regulator device supports disabling and 2301cf7bbcdfSMark Brown * machine constraints permit this operation. 2302414c70cbSLiam Girdwood */ 2303414c70cbSLiam Girdwood int regulator_disable(struct regulator *regulator) 2304414c70cbSLiam Girdwood { 2305412aec61SDavid Brownell struct regulator_dev *rdev = regulator->rdev; 2306412aec61SDavid Brownell int ret = 0; 2307414c70cbSLiam Girdwood 23086492bc1bSMark Brown if (regulator->always_on) 23096492bc1bSMark Brown return 0; 23106492bc1bSMark Brown 2311412aec61SDavid Brownell mutex_lock(&rdev->mutex); 23123801b86aSMark Brown ret = _regulator_disable(rdev); 2313412aec61SDavid Brownell mutex_unlock(&rdev->mutex); 23148cbf811dSJeffrey Carlyle 23153801b86aSMark Brown if (ret == 0 && rdev->supply) 23163801b86aSMark Brown regulator_disable(rdev->supply); 23178cbf811dSJeffrey Carlyle 2318414c70cbSLiam Girdwood return ret; 2319414c70cbSLiam Girdwood } 2320414c70cbSLiam Girdwood EXPORT_SYMBOL_GPL(regulator_disable); 2321414c70cbSLiam Girdwood 2322414c70cbSLiam Girdwood /* locks held by regulator_force_disable() */ 23233801b86aSMark Brown static int _regulator_force_disable(struct regulator_dev *rdev) 2324414c70cbSLiam Girdwood { 2325414c70cbSLiam Girdwood int ret = 0; 2326414c70cbSLiam Girdwood 232770cfef26SKrzysztof Kozlowski lockdep_assert_held_once(&rdev->mutex); 232870cfef26SKrzysztof Kozlowski 2329a1c8a551SRichard Fitzgerald ret = _notifier_call_chain(rdev, REGULATOR_EVENT_FORCE_DISABLE | 2330a1c8a551SRichard Fitzgerald REGULATOR_EVENT_PRE_DISABLE, NULL); 2331a1c8a551SRichard Fitzgerald if (ret & NOTIFY_STOP_MASK) 2332a1c8a551SRichard Fitzgerald return -EINVAL; 2333a1c8a551SRichard Fitzgerald 233466fda75fSMarkus Pargmann ret = _regulator_do_disable(rdev); 2335414c70cbSLiam Girdwood if (ret < 0) { 23365da84fd9SJoe Perches rdev_err(rdev, "failed to force disable\n"); 2337a1c8a551SRichard Fitzgerald _notifier_call_chain(rdev, REGULATOR_EVENT_FORCE_DISABLE | 2338a1c8a551SRichard Fitzgerald REGULATOR_EVENT_ABORT_DISABLE, NULL); 2339414c70cbSLiam Girdwood return ret; 2340414c70cbSLiam Girdwood } 234166fda75fSMarkus Pargmann 234284b68263SMark Brown _notifier_call_chain(rdev, REGULATOR_EVENT_FORCE_DISABLE | 234384b68263SMark Brown REGULATOR_EVENT_DISABLE, NULL); 2344414c70cbSLiam Girdwood 234566fda75fSMarkus Pargmann return 0; 2346414c70cbSLiam Girdwood } 2347414c70cbSLiam Girdwood 2348414c70cbSLiam Girdwood /** 2349414c70cbSLiam Girdwood * regulator_force_disable - force disable regulator output 2350414c70cbSLiam Girdwood * @regulator: regulator source 2351414c70cbSLiam Girdwood * 2352414c70cbSLiam Girdwood * Forcibly disable the regulator output voltage or current. 2353414c70cbSLiam Girdwood * NOTE: this *will* disable the regulator output even if other consumer 2354414c70cbSLiam Girdwood * devices have it enabled. This should be used for situations when device 2355414c70cbSLiam Girdwood * damage will likely occur if the regulator is not disabled (e.g. over temp). 2356414c70cbSLiam Girdwood */ 2357414c70cbSLiam Girdwood int regulator_force_disable(struct regulator *regulator) 2358414c70cbSLiam Girdwood { 235982d15839SMark Brown struct regulator_dev *rdev = regulator->rdev; 2360414c70cbSLiam Girdwood int ret; 2361414c70cbSLiam Girdwood 236282d15839SMark Brown mutex_lock(&rdev->mutex); 2363414c70cbSLiam Girdwood regulator->uA_load = 0; 23643801b86aSMark Brown ret = _regulator_force_disable(regulator->rdev); 236582d15839SMark Brown mutex_unlock(&rdev->mutex); 23668cbf811dSJeffrey Carlyle 23673801b86aSMark Brown if (rdev->supply) 23683801b86aSMark Brown while (rdev->open_count--) 23693801b86aSMark Brown regulator_disable(rdev->supply); 23708cbf811dSJeffrey Carlyle 2371414c70cbSLiam Girdwood return ret; 2372414c70cbSLiam Girdwood } 2373414c70cbSLiam Girdwood EXPORT_SYMBOL_GPL(regulator_force_disable); 2374414c70cbSLiam Girdwood 2375da07ecd9SMark Brown static void regulator_disable_work(struct work_struct *work) 2376da07ecd9SMark Brown { 2377da07ecd9SMark Brown struct regulator_dev *rdev = container_of(work, struct regulator_dev, 2378da07ecd9SMark Brown disable_work.work); 2379da07ecd9SMark Brown int count, i, ret; 2380da07ecd9SMark Brown 2381da07ecd9SMark Brown mutex_lock(&rdev->mutex); 2382da07ecd9SMark Brown 2383da07ecd9SMark Brown BUG_ON(!rdev->deferred_disables); 2384da07ecd9SMark Brown 2385da07ecd9SMark Brown count = rdev->deferred_disables; 2386da07ecd9SMark Brown rdev->deferred_disables = 0; 2387da07ecd9SMark Brown 2388da07ecd9SMark Brown for (i = 0; i < count; i++) { 2389da07ecd9SMark Brown ret = _regulator_disable(rdev); 2390da07ecd9SMark Brown if (ret != 0) 2391da07ecd9SMark Brown rdev_err(rdev, "Deferred disable failed: %d\n", ret); 2392da07ecd9SMark Brown } 2393da07ecd9SMark Brown 2394da07ecd9SMark Brown mutex_unlock(&rdev->mutex); 2395da07ecd9SMark Brown 2396da07ecd9SMark Brown if (rdev->supply) { 2397da07ecd9SMark Brown for (i = 0; i < count; i++) { 2398da07ecd9SMark Brown ret = regulator_disable(rdev->supply); 2399da07ecd9SMark Brown if (ret != 0) { 2400da07ecd9SMark Brown rdev_err(rdev, 2401da07ecd9SMark Brown "Supply disable failed: %d\n", ret); 2402da07ecd9SMark Brown } 2403da07ecd9SMark Brown } 2404da07ecd9SMark Brown } 2405da07ecd9SMark Brown } 2406da07ecd9SMark Brown 2407da07ecd9SMark Brown /** 2408da07ecd9SMark Brown * regulator_disable_deferred - disable regulator output with delay 2409da07ecd9SMark Brown * @regulator: regulator source 2410da07ecd9SMark Brown * @ms: miliseconds until the regulator is disabled 2411da07ecd9SMark Brown * 2412da07ecd9SMark Brown * Execute regulator_disable() on the regulator after a delay. This 2413da07ecd9SMark Brown * is intended for use with devices that require some time to quiesce. 2414da07ecd9SMark Brown * 2415da07ecd9SMark Brown * NOTE: this will only disable the regulator output if no other consumer 2416da07ecd9SMark Brown * devices have it enabled, the regulator device supports disabling and 2417da07ecd9SMark Brown * machine constraints permit this operation. 2418da07ecd9SMark Brown */ 2419da07ecd9SMark Brown int regulator_disable_deferred(struct regulator *regulator, int ms) 2420da07ecd9SMark Brown { 2421da07ecd9SMark Brown struct regulator_dev *rdev = regulator->rdev; 2422da07ecd9SMark Brown 24236492bc1bSMark Brown if (regulator->always_on) 24246492bc1bSMark Brown return 0; 24256492bc1bSMark Brown 24262b5a24a0SMark Brown if (!ms) 24272b5a24a0SMark Brown return regulator_disable(regulator); 24282b5a24a0SMark Brown 2429da07ecd9SMark Brown mutex_lock(&rdev->mutex); 2430da07ecd9SMark Brown rdev->deferred_disables++; 2431da07ecd9SMark Brown mutex_unlock(&rdev->mutex); 2432da07ecd9SMark Brown 243370dc6dafSDan Carpenter queue_delayed_work(system_power_efficient_wq, &rdev->disable_work, 2434da07ecd9SMark Brown msecs_to_jiffies(ms)); 2435aa59802dSMark Brown return 0; 2436da07ecd9SMark Brown } 2437da07ecd9SMark Brown EXPORT_SYMBOL_GPL(regulator_disable_deferred); 2438da07ecd9SMark Brown 2439414c70cbSLiam Girdwood static int _regulator_is_enabled(struct regulator_dev *rdev) 2440414c70cbSLiam Girdwood { 244165f73508SMark Brown /* A GPIO control always takes precedence */ 24427b74d149SKim, Milo if (rdev->ena_pin) 244365f73508SMark Brown return rdev->ena_gpio_state; 244465f73508SMark Brown 24459a7f6a4cSMark Brown /* If we don't know then assume that the regulator is always on */ 24469332546fSMark Brown if (!rdev->desc->ops->is_enabled) 24479a7f6a4cSMark Brown return 1; 2448414c70cbSLiam Girdwood 24499332546fSMark Brown return rdev->desc->ops->is_enabled(rdev); 2450414c70cbSLiam Girdwood } 2451414c70cbSLiam Girdwood 24523a40cfc3SSascha Hauer static int _regulator_list_voltage(struct regulator *regulator, 24533a40cfc3SSascha Hauer unsigned selector, int lock) 24543a40cfc3SSascha Hauer { 24553a40cfc3SSascha Hauer struct regulator_dev *rdev = regulator->rdev; 24563a40cfc3SSascha Hauer const struct regulator_ops *ops = rdev->desc->ops; 24573a40cfc3SSascha Hauer int ret; 24583a40cfc3SSascha Hauer 24593a40cfc3SSascha Hauer if (rdev->desc->fixed_uV && rdev->desc->n_voltages == 1 && !selector) 24603a40cfc3SSascha Hauer return rdev->desc->fixed_uV; 24613a40cfc3SSascha Hauer 24623a40cfc3SSascha Hauer if (ops->list_voltage) { 24633a40cfc3SSascha Hauer if (selector >= rdev->desc->n_voltages) 24643a40cfc3SSascha Hauer return -EINVAL; 24653a40cfc3SSascha Hauer if (lock) 24663a40cfc3SSascha Hauer mutex_lock(&rdev->mutex); 24673a40cfc3SSascha Hauer ret = ops->list_voltage(rdev, selector); 24683a40cfc3SSascha Hauer if (lock) 24693a40cfc3SSascha Hauer mutex_unlock(&rdev->mutex); 24703a40cfc3SSascha Hauer } else if (rdev->supply) { 24713a40cfc3SSascha Hauer ret = _regulator_list_voltage(rdev->supply, selector, lock); 24723a40cfc3SSascha Hauer } else { 24733a40cfc3SSascha Hauer return -EINVAL; 24743a40cfc3SSascha Hauer } 24753a40cfc3SSascha Hauer 24763a40cfc3SSascha Hauer if (ret > 0) { 24773a40cfc3SSascha Hauer if (ret < rdev->constraints->min_uV) 24783a40cfc3SSascha Hauer ret = 0; 24793a40cfc3SSascha Hauer else if (ret > rdev->constraints->max_uV) 24803a40cfc3SSascha Hauer ret = 0; 24813a40cfc3SSascha Hauer } 24823a40cfc3SSascha Hauer 24833a40cfc3SSascha Hauer return ret; 24843a40cfc3SSascha Hauer } 24853a40cfc3SSascha Hauer 2486414c70cbSLiam Girdwood /** 2487414c70cbSLiam Girdwood * regulator_is_enabled - is the regulator output enabled 2488414c70cbSLiam Girdwood * @regulator: regulator source 2489414c70cbSLiam Girdwood * 2490412aec61SDavid Brownell * Returns positive if the regulator driver backing the source/client 2491412aec61SDavid Brownell * has requested that the device be enabled, zero if it hasn't, else a 2492412aec61SDavid Brownell * negative errno code. 2493412aec61SDavid Brownell * 2494412aec61SDavid Brownell * Note that the device backing this regulator handle can have multiple 2495412aec61SDavid Brownell * users, so it might be enabled even if regulator_enable() was never 2496412aec61SDavid Brownell * called for this particular source. 2497414c70cbSLiam Girdwood */ 2498414c70cbSLiam Girdwood int regulator_is_enabled(struct regulator *regulator) 2499414c70cbSLiam Girdwood { 25009332546fSMark Brown int ret; 25019332546fSMark Brown 25026492bc1bSMark Brown if (regulator->always_on) 25036492bc1bSMark Brown return 1; 25046492bc1bSMark Brown 25059332546fSMark Brown mutex_lock(®ulator->rdev->mutex); 25069332546fSMark Brown ret = _regulator_is_enabled(regulator->rdev); 25079332546fSMark Brown mutex_unlock(®ulator->rdev->mutex); 25089332546fSMark Brown 25099332546fSMark Brown return ret; 2510414c70cbSLiam Girdwood } 2511414c70cbSLiam Girdwood EXPORT_SYMBOL_GPL(regulator_is_enabled); 2512414c70cbSLiam Girdwood 2513414c70cbSLiam Girdwood /** 25144367cfdcSDavid Brownell * regulator_count_voltages - count regulator_list_voltage() selectors 25154367cfdcSDavid Brownell * @regulator: regulator source 25164367cfdcSDavid Brownell * 25174367cfdcSDavid Brownell * Returns number of selectors, or negative errno. Selectors are 25184367cfdcSDavid Brownell * numbered starting at zero, and typically correspond to bitfields 25194367cfdcSDavid Brownell * in hardware registers. 25204367cfdcSDavid Brownell */ 25214367cfdcSDavid Brownell int regulator_count_voltages(struct regulator *regulator) 25224367cfdcSDavid Brownell { 25234367cfdcSDavid Brownell struct regulator_dev *rdev = regulator->rdev; 25244367cfdcSDavid Brownell 252526988efeSJavier Martinez Canillas if (rdev->desc->n_voltages) 252626988efeSJavier Martinez Canillas return rdev->desc->n_voltages; 252726988efeSJavier Martinez Canillas 252826988efeSJavier Martinez Canillas if (!rdev->supply) 252926988efeSJavier Martinez Canillas return -EINVAL; 253026988efeSJavier Martinez Canillas 253126988efeSJavier Martinez Canillas return regulator_count_voltages(rdev->supply); 25324367cfdcSDavid Brownell } 25334367cfdcSDavid Brownell EXPORT_SYMBOL_GPL(regulator_count_voltages); 25344367cfdcSDavid Brownell 25354367cfdcSDavid Brownell /** 25364367cfdcSDavid Brownell * regulator_list_voltage - enumerate supported voltages 25374367cfdcSDavid Brownell * @regulator: regulator source 25384367cfdcSDavid Brownell * @selector: identify voltage to list 25394367cfdcSDavid Brownell * Context: can sleep 25404367cfdcSDavid Brownell * 25414367cfdcSDavid Brownell * Returns a voltage that can be passed to @regulator_set_voltage(), 254288393161SThomas Weber * zero if this selector code can't be used on this system, or a 25434367cfdcSDavid Brownell * negative errno. 25444367cfdcSDavid Brownell */ 25454367cfdcSDavid Brownell int regulator_list_voltage(struct regulator *regulator, unsigned selector) 25464367cfdcSDavid Brownell { 25473a40cfc3SSascha Hauer return _regulator_list_voltage(regulator, selector, 1); 25484367cfdcSDavid Brownell } 25494367cfdcSDavid Brownell EXPORT_SYMBOL_GPL(regulator_list_voltage); 25504367cfdcSDavid Brownell 25514367cfdcSDavid Brownell /** 255204eca28cSTuomas Tynkkynen * regulator_get_regmap - get the regulator's register map 255304eca28cSTuomas Tynkkynen * @regulator: regulator source 255404eca28cSTuomas Tynkkynen * 255504eca28cSTuomas Tynkkynen * Returns the register map for the given regulator, or an ERR_PTR value 255604eca28cSTuomas Tynkkynen * if the regulator doesn't use regmap. 255704eca28cSTuomas Tynkkynen */ 255804eca28cSTuomas Tynkkynen struct regmap *regulator_get_regmap(struct regulator *regulator) 255904eca28cSTuomas Tynkkynen { 256004eca28cSTuomas Tynkkynen struct regmap *map = regulator->rdev->regmap; 256104eca28cSTuomas Tynkkynen 256204eca28cSTuomas Tynkkynen return map ? map : ERR_PTR(-EOPNOTSUPP); 256304eca28cSTuomas Tynkkynen } 256404eca28cSTuomas Tynkkynen 256504eca28cSTuomas Tynkkynen /** 256604eca28cSTuomas Tynkkynen * regulator_get_hardware_vsel_register - get the HW voltage selector register 256704eca28cSTuomas Tynkkynen * @regulator: regulator source 256804eca28cSTuomas Tynkkynen * @vsel_reg: voltage selector register, output parameter 256904eca28cSTuomas Tynkkynen * @vsel_mask: mask for voltage selector bitfield, output parameter 257004eca28cSTuomas Tynkkynen * 257104eca28cSTuomas Tynkkynen * Returns the hardware register offset and bitmask used for setting the 257204eca28cSTuomas Tynkkynen * regulator voltage. This might be useful when configuring voltage-scaling 257304eca28cSTuomas Tynkkynen * hardware or firmware that can make I2C requests behind the kernel's back, 257404eca28cSTuomas Tynkkynen * for example. 257504eca28cSTuomas Tynkkynen * 257604eca28cSTuomas Tynkkynen * On success, the output parameters @vsel_reg and @vsel_mask are filled in 257704eca28cSTuomas Tynkkynen * and 0 is returned, otherwise a negative errno is returned. 257804eca28cSTuomas Tynkkynen */ 257904eca28cSTuomas Tynkkynen int regulator_get_hardware_vsel_register(struct regulator *regulator, 258004eca28cSTuomas Tynkkynen unsigned *vsel_reg, 258104eca28cSTuomas Tynkkynen unsigned *vsel_mask) 258204eca28cSTuomas Tynkkynen { 258304eca28cSTuomas Tynkkynen struct regulator_dev *rdev = regulator->rdev; 258439f5460dSGuodong Xu const struct regulator_ops *ops = rdev->desc->ops; 258504eca28cSTuomas Tynkkynen 258604eca28cSTuomas Tynkkynen if (ops->set_voltage_sel != regulator_set_voltage_sel_regmap) 258704eca28cSTuomas Tynkkynen return -EOPNOTSUPP; 258804eca28cSTuomas Tynkkynen 258904eca28cSTuomas Tynkkynen *vsel_reg = rdev->desc->vsel_reg; 259004eca28cSTuomas Tynkkynen *vsel_mask = rdev->desc->vsel_mask; 259104eca28cSTuomas Tynkkynen 259204eca28cSTuomas Tynkkynen return 0; 259304eca28cSTuomas Tynkkynen } 259404eca28cSTuomas Tynkkynen EXPORT_SYMBOL_GPL(regulator_get_hardware_vsel_register); 259504eca28cSTuomas Tynkkynen 259604eca28cSTuomas Tynkkynen /** 259704eca28cSTuomas Tynkkynen * regulator_list_hardware_vsel - get the HW-specific register value for a selector 259804eca28cSTuomas Tynkkynen * @regulator: regulator source 259904eca28cSTuomas Tynkkynen * @selector: identify voltage to list 260004eca28cSTuomas Tynkkynen * 260104eca28cSTuomas Tynkkynen * Converts the selector to a hardware-specific voltage selector that can be 260204eca28cSTuomas Tynkkynen * directly written to the regulator registers. The address of the voltage 260304eca28cSTuomas Tynkkynen * register can be determined by calling @regulator_get_hardware_vsel_register. 260404eca28cSTuomas Tynkkynen * 260504eca28cSTuomas Tynkkynen * On error a negative errno is returned. 260604eca28cSTuomas Tynkkynen */ 260704eca28cSTuomas Tynkkynen int regulator_list_hardware_vsel(struct regulator *regulator, 260804eca28cSTuomas Tynkkynen unsigned selector) 260904eca28cSTuomas Tynkkynen { 261004eca28cSTuomas Tynkkynen struct regulator_dev *rdev = regulator->rdev; 261139f5460dSGuodong Xu const struct regulator_ops *ops = rdev->desc->ops; 261204eca28cSTuomas Tynkkynen 261304eca28cSTuomas Tynkkynen if (selector >= rdev->desc->n_voltages) 261404eca28cSTuomas Tynkkynen return -EINVAL; 261504eca28cSTuomas Tynkkynen if (ops->set_voltage_sel != regulator_set_voltage_sel_regmap) 261604eca28cSTuomas Tynkkynen return -EOPNOTSUPP; 261704eca28cSTuomas Tynkkynen 261804eca28cSTuomas Tynkkynen return selector; 261904eca28cSTuomas Tynkkynen } 262004eca28cSTuomas Tynkkynen EXPORT_SYMBOL_GPL(regulator_list_hardware_vsel); 262104eca28cSTuomas Tynkkynen 262204eca28cSTuomas Tynkkynen /** 26232a668a8bSPaul Walmsley * regulator_get_linear_step - return the voltage step size between VSEL values 26242a668a8bSPaul Walmsley * @regulator: regulator source 26252a668a8bSPaul Walmsley * 26262a668a8bSPaul Walmsley * Returns the voltage step size between VSEL values for linear 26272a668a8bSPaul Walmsley * regulators, or return 0 if the regulator isn't a linear regulator. 26282a668a8bSPaul Walmsley */ 26292a668a8bSPaul Walmsley unsigned int regulator_get_linear_step(struct regulator *regulator) 26302a668a8bSPaul Walmsley { 26312a668a8bSPaul Walmsley struct regulator_dev *rdev = regulator->rdev; 26322a668a8bSPaul Walmsley 26332a668a8bSPaul Walmsley return rdev->desc->uV_step; 26342a668a8bSPaul Walmsley } 26352a668a8bSPaul Walmsley EXPORT_SYMBOL_GPL(regulator_get_linear_step); 26362a668a8bSPaul Walmsley 26372a668a8bSPaul Walmsley /** 2638a7a1ad90SMark Brown * regulator_is_supported_voltage - check if a voltage range can be supported 2639a7a1ad90SMark Brown * 2640a7a1ad90SMark Brown * @regulator: Regulator to check. 2641a7a1ad90SMark Brown * @min_uV: Minimum required voltage in uV. 2642a7a1ad90SMark Brown * @max_uV: Maximum required voltage in uV. 2643a7a1ad90SMark Brown * 2644a7a1ad90SMark Brown * Returns a boolean or a negative error code. 2645a7a1ad90SMark Brown */ 2646a7a1ad90SMark Brown int regulator_is_supported_voltage(struct regulator *regulator, 2647a7a1ad90SMark Brown int min_uV, int max_uV) 2648a7a1ad90SMark Brown { 2649c5f3939bSMark Brown struct regulator_dev *rdev = regulator->rdev; 2650a7a1ad90SMark Brown int i, voltages, ret; 2651a7a1ad90SMark Brown 2652c5f3939bSMark Brown /* If we can't change voltage check the current voltage */ 26538a34e979SWEN Pingbo if (!regulator_ops_is_valid(rdev, REGULATOR_CHANGE_VOLTAGE)) { 2654c5f3939bSMark Brown ret = regulator_get_voltage(regulator); 2655c5f3939bSMark Brown if (ret >= 0) 26560d25d09dSJingoo Han return min_uV <= ret && ret <= max_uV; 2657c5f3939bSMark Brown else 2658c5f3939bSMark Brown return ret; 2659c5f3939bSMark Brown } 2660c5f3939bSMark Brown 2661bd7a2b60SPawel Moll /* Any voltage within constrains range is fine? */ 2662bd7a2b60SPawel Moll if (rdev->desc->continuous_voltage_range) 2663bd7a2b60SPawel Moll return min_uV >= rdev->constraints->min_uV && 2664bd7a2b60SPawel Moll max_uV <= rdev->constraints->max_uV; 2665bd7a2b60SPawel Moll 2666a7a1ad90SMark Brown ret = regulator_count_voltages(regulator); 2667a7a1ad90SMark Brown if (ret < 0) 2668a7a1ad90SMark Brown return ret; 2669a7a1ad90SMark Brown voltages = ret; 2670a7a1ad90SMark Brown 2671a7a1ad90SMark Brown for (i = 0; i < voltages; i++) { 2672a7a1ad90SMark Brown ret = regulator_list_voltage(regulator, i); 2673a7a1ad90SMark Brown 2674a7a1ad90SMark Brown if (ret >= min_uV && ret <= max_uV) 2675a7a1ad90SMark Brown return 1; 2676a7a1ad90SMark Brown } 2677a7a1ad90SMark Brown 2678a7a1ad90SMark Brown return 0; 2679a7a1ad90SMark Brown } 2680a398eaa2SMark Brown EXPORT_SYMBOL_GPL(regulator_is_supported_voltage); 2681a7a1ad90SMark Brown 2682a204f41eSSascha Hauer static int regulator_map_voltage(struct regulator_dev *rdev, int min_uV, 2683a204f41eSSascha Hauer int max_uV) 2684a204f41eSSascha Hauer { 2685a204f41eSSascha Hauer const struct regulator_desc *desc = rdev->desc; 2686a204f41eSSascha Hauer 2687a204f41eSSascha Hauer if (desc->ops->map_voltage) 2688a204f41eSSascha Hauer return desc->ops->map_voltage(rdev, min_uV, max_uV); 2689a204f41eSSascha Hauer 2690a204f41eSSascha Hauer if (desc->ops->list_voltage == regulator_list_voltage_linear) 2691a204f41eSSascha Hauer return regulator_map_voltage_linear(rdev, min_uV, max_uV); 2692a204f41eSSascha Hauer 2693a204f41eSSascha Hauer if (desc->ops->list_voltage == regulator_list_voltage_linear_range) 2694a204f41eSSascha Hauer return regulator_map_voltage_linear_range(rdev, min_uV, max_uV); 2695a204f41eSSascha Hauer 2696a204f41eSSascha Hauer return regulator_map_voltage_iterate(rdev, min_uV, max_uV); 2697a204f41eSSascha Hauer } 2698a204f41eSSascha Hauer 26997179569aSHeiko Stübner static int _regulator_call_set_voltage(struct regulator_dev *rdev, 27007179569aSHeiko Stübner int min_uV, int max_uV, 27017179569aSHeiko Stübner unsigned *selector) 27027179569aSHeiko Stübner { 27037179569aSHeiko Stübner struct pre_voltage_change_data data; 27047179569aSHeiko Stübner int ret; 27057179569aSHeiko Stübner 27067179569aSHeiko Stübner data.old_uV = _regulator_get_voltage(rdev); 27077179569aSHeiko Stübner data.min_uV = min_uV; 27087179569aSHeiko Stübner data.max_uV = max_uV; 27097179569aSHeiko Stübner ret = _notifier_call_chain(rdev, REGULATOR_EVENT_PRE_VOLTAGE_CHANGE, 27107179569aSHeiko Stübner &data); 27117179569aSHeiko Stübner if (ret & NOTIFY_STOP_MASK) 27127179569aSHeiko Stübner return -EINVAL; 27137179569aSHeiko Stübner 27147179569aSHeiko Stübner ret = rdev->desc->ops->set_voltage(rdev, min_uV, max_uV, selector); 27157179569aSHeiko Stübner if (ret >= 0) 27167179569aSHeiko Stübner return ret; 27177179569aSHeiko Stübner 27187179569aSHeiko Stübner _notifier_call_chain(rdev, REGULATOR_EVENT_ABORT_VOLTAGE_CHANGE, 27197179569aSHeiko Stübner (void *)data.old_uV); 27207179569aSHeiko Stübner 27217179569aSHeiko Stübner return ret; 27227179569aSHeiko Stübner } 27237179569aSHeiko Stübner 27247179569aSHeiko Stübner static int _regulator_call_set_voltage_sel(struct regulator_dev *rdev, 27257179569aSHeiko Stübner int uV, unsigned selector) 27267179569aSHeiko Stübner { 27277179569aSHeiko Stübner struct pre_voltage_change_data data; 27287179569aSHeiko Stübner int ret; 27297179569aSHeiko Stübner 27307179569aSHeiko Stübner data.old_uV = _regulator_get_voltage(rdev); 27317179569aSHeiko Stübner data.min_uV = uV; 27327179569aSHeiko Stübner data.max_uV = uV; 27337179569aSHeiko Stübner ret = _notifier_call_chain(rdev, REGULATOR_EVENT_PRE_VOLTAGE_CHANGE, 27347179569aSHeiko Stübner &data); 27357179569aSHeiko Stübner if (ret & NOTIFY_STOP_MASK) 27367179569aSHeiko Stübner return -EINVAL; 27377179569aSHeiko Stübner 27387179569aSHeiko Stübner ret = rdev->desc->ops->set_voltage_sel(rdev, selector); 27397179569aSHeiko Stübner if (ret >= 0) 27407179569aSHeiko Stübner return ret; 27417179569aSHeiko Stübner 27427179569aSHeiko Stübner _notifier_call_chain(rdev, REGULATOR_EVENT_ABORT_VOLTAGE_CHANGE, 27437179569aSHeiko Stübner (void *)data.old_uV); 27447179569aSHeiko Stübner 27457179569aSHeiko Stübner return ret; 27467179569aSHeiko Stübner } 27477179569aSHeiko Stübner 274873e705bfSMatthias Kaehlcke static int _regulator_set_voltage_time(struct regulator_dev *rdev, 274973e705bfSMatthias Kaehlcke int old_uV, int new_uV) 275073e705bfSMatthias Kaehlcke { 275173e705bfSMatthias Kaehlcke unsigned int ramp_delay = 0; 275273e705bfSMatthias Kaehlcke 275373e705bfSMatthias Kaehlcke if (rdev->constraints->ramp_delay) 275473e705bfSMatthias Kaehlcke ramp_delay = rdev->constraints->ramp_delay; 275573e705bfSMatthias Kaehlcke else if (rdev->desc->ramp_delay) 275673e705bfSMatthias Kaehlcke ramp_delay = rdev->desc->ramp_delay; 275773e705bfSMatthias Kaehlcke 275873e705bfSMatthias Kaehlcke if (ramp_delay == 0) { 2759ba14fa1aSH. Nikolaus Schaller rdev_dbg(rdev, "ramp_delay not set\n"); 276073e705bfSMatthias Kaehlcke return 0; 276173e705bfSMatthias Kaehlcke } 276273e705bfSMatthias Kaehlcke 276373e705bfSMatthias Kaehlcke return DIV_ROUND_UP(abs(new_uV - old_uV), ramp_delay); 276473e705bfSMatthias Kaehlcke } 276573e705bfSMatthias Kaehlcke 276675790251SMark Brown static int _regulator_do_set_voltage(struct regulator_dev *rdev, 276775790251SMark Brown int min_uV, int max_uV) 276875790251SMark Brown { 276975790251SMark Brown int ret; 277077af1b26SLinus Walleij int delay = 0; 2771e113d792SMark Brown int best_val = 0; 277275790251SMark Brown unsigned int selector; 2773eba41a5eSAxel Lin int old_selector = -1; 277457995a48SMatthias Kaehlcke const struct regulator_ops *ops = rdev->desc->ops; 277573e705bfSMatthias Kaehlcke int old_uV = _regulator_get_voltage(rdev); 277675790251SMark Brown 277775790251SMark Brown trace_regulator_set_voltage(rdev_get_name(rdev), min_uV, max_uV); 277875790251SMark Brown 2779bf5892a8SMark Brown min_uV += rdev->constraints->uV_offset; 2780bf5892a8SMark Brown max_uV += rdev->constraints->uV_offset; 2781bf5892a8SMark Brown 278277af1b26SLinus Walleij /* 278377af1b26SLinus Walleij * If we can't obtain the old selector there is not enough 278477af1b26SLinus Walleij * info to call set_voltage_time_sel(). 278577af1b26SLinus Walleij */ 27868b7485efSAxel Lin if (_regulator_is_enabled(rdev) && 278757995a48SMatthias Kaehlcke ops->set_voltage_time_sel && ops->get_voltage_sel) { 278857995a48SMatthias Kaehlcke old_selector = ops->get_voltage_sel(rdev); 2789eba41a5eSAxel Lin if (old_selector < 0) 2790eba41a5eSAxel Lin return old_selector; 2791eba41a5eSAxel Lin } 279277af1b26SLinus Walleij 279357995a48SMatthias Kaehlcke if (ops->set_voltage) { 27947179569aSHeiko Stübner ret = _regulator_call_set_voltage(rdev, min_uV, max_uV, 279575790251SMark Brown &selector); 2796e113d792SMark Brown 2797e113d792SMark Brown if (ret >= 0) { 279857995a48SMatthias Kaehlcke if (ops->list_voltage) 279957995a48SMatthias Kaehlcke best_val = ops->list_voltage(rdev, 2800e113d792SMark Brown selector); 2801e113d792SMark Brown else 2802e113d792SMark Brown best_val = _regulator_get_voltage(rdev); 2803e113d792SMark Brown } 2804e113d792SMark Brown 280557995a48SMatthias Kaehlcke } else if (ops->set_voltage_sel) { 2806a204f41eSSascha Hauer ret = regulator_map_voltage(rdev, min_uV, max_uV); 2807e843fc46SMark Brown if (ret >= 0) { 280857995a48SMatthias Kaehlcke best_val = ops->list_voltage(rdev, ret); 2809e113d792SMark Brown if (min_uV <= best_val && max_uV >= best_val) { 2810e843fc46SMark Brown selector = ret; 2811c66a566aSAxel Lin if (old_selector == selector) 2812c66a566aSAxel Lin ret = 0; 2813c66a566aSAxel Lin else 28147179569aSHeiko Stübner ret = _regulator_call_set_voltage_sel( 28157179569aSHeiko Stübner rdev, best_val, selector); 2816e113d792SMark Brown } else { 2817e113d792SMark Brown ret = -EINVAL; 2818e113d792SMark Brown } 2819e843fc46SMark Brown } 2820e8eef82bSMark Brown } else { 2821e8eef82bSMark Brown ret = -EINVAL; 2822e8eef82bSMark Brown } 2823e8eef82bSMark Brown 282431dfe686SMatthias Kaehlcke if (ret) 282531dfe686SMatthias Kaehlcke goto out; 2826eba41a5eSAxel Lin 282773e705bfSMatthias Kaehlcke if (ops->set_voltage_time_sel) { 282873e705bfSMatthias Kaehlcke /* 282973e705bfSMatthias Kaehlcke * Call set_voltage_time_sel if successfully obtained 283073e705bfSMatthias Kaehlcke * old_selector 283173e705bfSMatthias Kaehlcke */ 283273e705bfSMatthias Kaehlcke if (old_selector >= 0 && old_selector != selector) 283373e705bfSMatthias Kaehlcke delay = ops->set_voltage_time_sel(rdev, old_selector, 283473e705bfSMatthias Kaehlcke selector); 283573e705bfSMatthias Kaehlcke } else { 283673e705bfSMatthias Kaehlcke if (old_uV != best_val) { 283773e705bfSMatthias Kaehlcke if (ops->set_voltage_time) 283873e705bfSMatthias Kaehlcke delay = ops->set_voltage_time(rdev, old_uV, 283973e705bfSMatthias Kaehlcke best_val); 284073e705bfSMatthias Kaehlcke else 284173e705bfSMatthias Kaehlcke delay = _regulator_set_voltage_time(rdev, 284273e705bfSMatthias Kaehlcke old_uV, 284373e705bfSMatthias Kaehlcke best_val); 284473e705bfSMatthias Kaehlcke } 284573e705bfSMatthias Kaehlcke } 284673e705bfSMatthias Kaehlcke 2847eba41a5eSAxel Lin if (delay < 0) { 284873e705bfSMatthias Kaehlcke rdev_warn(rdev, "failed to get delay: %d\n", delay); 2849eba41a5eSAxel Lin delay = 0; 2850e8eef82bSMark Brown } 285175790251SMark Brown 285277af1b26SLinus Walleij /* Insert any necessary delays */ 285377af1b26SLinus Walleij if (delay >= 1000) { 285477af1b26SLinus Walleij mdelay(delay / 1000); 285577af1b26SLinus Walleij udelay(delay % 1000); 285677af1b26SLinus Walleij } else if (delay) { 285777af1b26SLinus Walleij udelay(delay); 285877af1b26SLinus Walleij } 285977af1b26SLinus Walleij 286031dfe686SMatthias Kaehlcke if (best_val >= 0) { 28612f6c797fSAxel Lin unsigned long data = best_val; 28622f6c797fSAxel Lin 2863ded06a52SMark Brown _notifier_call_chain(rdev, REGULATOR_EVENT_VOLTAGE_CHANGE, 28642f6c797fSAxel Lin (void *)data); 28652f6c797fSAxel Lin } 2866ded06a52SMark Brown 286731dfe686SMatthias Kaehlcke out: 2868eba41a5eSAxel Lin trace_regulator_set_voltage_complete(rdev_get_name(rdev), best_val); 286975790251SMark Brown 287075790251SMark Brown return ret; 287175790251SMark Brown } 287275790251SMark Brown 2873a9f226bcSSascha Hauer static int regulator_set_voltage_unlocked(struct regulator *regulator, 2874a9f226bcSSascha Hauer int min_uV, int max_uV) 2875414c70cbSLiam Girdwood { 2876414c70cbSLiam Girdwood struct regulator_dev *rdev = regulator->rdev; 287795a3c23aSMark Brown int ret = 0; 287892d7a558SPaolo Pisati int old_min_uV, old_max_uV; 2879c00dc359SBjorn Andersson int current_uV; 2880fc42112cSSascha Hauer int best_supply_uV = 0; 2881fc42112cSSascha Hauer int supply_change_uV = 0; 2882414c70cbSLiam Girdwood 288395a3c23aSMark Brown /* If we're setting the same range as last time the change 288495a3c23aSMark Brown * should be a noop (some cpufreq implementations use the same 288595a3c23aSMark Brown * voltage for multiple frequencies, for example). 288695a3c23aSMark Brown */ 288795a3c23aSMark Brown if (regulator->min_uV == min_uV && regulator->max_uV == max_uV) 288895a3c23aSMark Brown goto out; 288995a3c23aSMark Brown 2890c00dc359SBjorn Andersson /* If we're trying to set a range that overlaps the current voltage, 2891d3fb9800SViresh Kumar * return successfully even though the regulator does not support 2892c00dc359SBjorn Andersson * changing the voltage. 2893c00dc359SBjorn Andersson */ 28948a34e979SWEN Pingbo if (!regulator_ops_is_valid(rdev, REGULATOR_CHANGE_VOLTAGE)) { 2895c00dc359SBjorn Andersson current_uV = _regulator_get_voltage(rdev); 2896c00dc359SBjorn Andersson if (min_uV <= current_uV && current_uV <= max_uV) { 2897c00dc359SBjorn Andersson regulator->min_uV = min_uV; 2898c00dc359SBjorn Andersson regulator->max_uV = max_uV; 2899c00dc359SBjorn Andersson goto out; 2900c00dc359SBjorn Andersson } 2901c00dc359SBjorn Andersson } 2902c00dc359SBjorn Andersson 2903414c70cbSLiam Girdwood /* sanity check */ 2904e8eef82bSMark Brown if (!rdev->desc->ops->set_voltage && 2905e8eef82bSMark Brown !rdev->desc->ops->set_voltage_sel) { 2906414c70cbSLiam Girdwood ret = -EINVAL; 2907414c70cbSLiam Girdwood goto out; 2908414c70cbSLiam Girdwood } 2909414c70cbSLiam Girdwood 2910414c70cbSLiam Girdwood /* constraints check */ 2911414c70cbSLiam Girdwood ret = regulator_check_voltage(rdev, &min_uV, &max_uV); 2912414c70cbSLiam Girdwood if (ret < 0) 2913414c70cbSLiam Girdwood goto out; 291492d7a558SPaolo Pisati 291592d7a558SPaolo Pisati /* restore original values in case of error */ 291692d7a558SPaolo Pisati old_min_uV = regulator->min_uV; 291792d7a558SPaolo Pisati old_max_uV = regulator->max_uV; 2918414c70cbSLiam Girdwood regulator->min_uV = min_uV; 2919414c70cbSLiam Girdwood regulator->max_uV = max_uV; 29203a93f2a9SMark Brown 292105fda3b1SThomas Petazzoni ret = regulator_check_consumers(rdev, &min_uV, &max_uV); 292205fda3b1SThomas Petazzoni if (ret < 0) 292392d7a558SPaolo Pisati goto out2; 292405fda3b1SThomas Petazzoni 2925fc42112cSSascha Hauer if (rdev->supply && (rdev->desc->min_dropout_uV || 2926fc42112cSSascha Hauer !rdev->desc->ops->get_voltage)) { 2927fc42112cSSascha Hauer int current_supply_uV; 2928fc42112cSSascha Hauer int selector; 2929fc42112cSSascha Hauer 2930fc42112cSSascha Hauer selector = regulator_map_voltage(rdev, min_uV, max_uV); 2931fc42112cSSascha Hauer if (selector < 0) { 2932fc42112cSSascha Hauer ret = selector; 2933fc42112cSSascha Hauer goto out2; 2934fc42112cSSascha Hauer } 2935fc42112cSSascha Hauer 2936fc42112cSSascha Hauer best_supply_uV = _regulator_list_voltage(regulator, selector, 0); 2937fc42112cSSascha Hauer if (best_supply_uV < 0) { 2938fc42112cSSascha Hauer ret = best_supply_uV; 2939fc42112cSSascha Hauer goto out2; 2940fc42112cSSascha Hauer } 2941fc42112cSSascha Hauer 2942fc42112cSSascha Hauer best_supply_uV += rdev->desc->min_dropout_uV; 2943fc42112cSSascha Hauer 2944fc42112cSSascha Hauer current_supply_uV = _regulator_get_voltage(rdev->supply->rdev); 2945fc42112cSSascha Hauer if (current_supply_uV < 0) { 2946fc42112cSSascha Hauer ret = current_supply_uV; 2947fc42112cSSascha Hauer goto out2; 2948fc42112cSSascha Hauer } 2949fc42112cSSascha Hauer 2950fc42112cSSascha Hauer supply_change_uV = best_supply_uV - current_supply_uV; 2951fc42112cSSascha Hauer } 2952fc42112cSSascha Hauer 2953fc42112cSSascha Hauer if (supply_change_uV > 0) { 2954fc42112cSSascha Hauer ret = regulator_set_voltage_unlocked(rdev->supply, 2955fc42112cSSascha Hauer best_supply_uV, INT_MAX); 2956fc42112cSSascha Hauer if (ret) { 2957fc42112cSSascha Hauer dev_err(&rdev->dev, "Failed to increase supply voltage: %d\n", 2958fc42112cSSascha Hauer ret); 2959fc42112cSSascha Hauer goto out2; 2960fc42112cSSascha Hauer } 2961fc42112cSSascha Hauer } 2962fc42112cSSascha Hauer 296375790251SMark Brown ret = _regulator_do_set_voltage(rdev, min_uV, max_uV); 296492d7a558SPaolo Pisati if (ret < 0) 296592d7a558SPaolo Pisati goto out2; 296602fa3ec0SMark Brown 2967fc42112cSSascha Hauer if (supply_change_uV < 0) { 2968fc42112cSSascha Hauer ret = regulator_set_voltage_unlocked(rdev->supply, 2969fc42112cSSascha Hauer best_supply_uV, INT_MAX); 2970fc42112cSSascha Hauer if (ret) 2971fc42112cSSascha Hauer dev_warn(&rdev->dev, "Failed to decrease supply voltage: %d\n", 2972fc42112cSSascha Hauer ret); 2973fc42112cSSascha Hauer /* No need to fail here */ 2974fc42112cSSascha Hauer ret = 0; 2975fc42112cSSascha Hauer } 2976fc42112cSSascha Hauer 2977414c70cbSLiam Girdwood out: 2978414c70cbSLiam Girdwood return ret; 297992d7a558SPaolo Pisati out2: 298092d7a558SPaolo Pisati regulator->min_uV = old_min_uV; 298192d7a558SPaolo Pisati regulator->max_uV = old_max_uV; 2982a9f226bcSSascha Hauer 2983a9f226bcSSascha Hauer return ret; 2984a9f226bcSSascha Hauer } 2985a9f226bcSSascha Hauer 2986a9f226bcSSascha Hauer /** 2987a9f226bcSSascha Hauer * regulator_set_voltage - set regulator output voltage 2988a9f226bcSSascha Hauer * @regulator: regulator source 2989a9f226bcSSascha Hauer * @min_uV: Minimum required voltage in uV 2990a9f226bcSSascha Hauer * @max_uV: Maximum acceptable voltage in uV 2991a9f226bcSSascha Hauer * 2992a9f226bcSSascha Hauer * Sets a voltage regulator to the desired output voltage. This can be set 2993a9f226bcSSascha Hauer * during any regulator state. IOW, regulator can be disabled or enabled. 2994a9f226bcSSascha Hauer * 2995a9f226bcSSascha Hauer * If the regulator is enabled then the voltage will change to the new value 2996a9f226bcSSascha Hauer * immediately otherwise if the regulator is disabled the regulator will 2997a9f226bcSSascha Hauer * output at the new voltage when enabled. 2998a9f226bcSSascha Hauer * 2999a9f226bcSSascha Hauer * NOTE: If the regulator is shared between several devices then the lowest 3000a9f226bcSSascha Hauer * request voltage that meets the system constraints will be used. 3001a9f226bcSSascha Hauer * Regulator system constraints must be set for this regulator before 3002a9f226bcSSascha Hauer * calling this function otherwise this call will fail. 3003a9f226bcSSascha Hauer */ 3004a9f226bcSSascha Hauer int regulator_set_voltage(struct regulator *regulator, int min_uV, int max_uV) 3005a9f226bcSSascha Hauer { 3006a9f226bcSSascha Hauer int ret = 0; 3007a9f226bcSSascha Hauer 3008fc42112cSSascha Hauer regulator_lock_supply(regulator->rdev); 3009a9f226bcSSascha Hauer 3010a9f226bcSSascha Hauer ret = regulator_set_voltage_unlocked(regulator, min_uV, max_uV); 3011a9f226bcSSascha Hauer 3012fc42112cSSascha Hauer regulator_unlock_supply(regulator->rdev); 3013a9f226bcSSascha Hauer 301492d7a558SPaolo Pisati return ret; 3015414c70cbSLiam Girdwood } 3016414c70cbSLiam Girdwood EXPORT_SYMBOL_GPL(regulator_set_voltage); 3017414c70cbSLiam Girdwood 3018606a2562SMark Brown /** 301988cd222bSLinus Walleij * regulator_set_voltage_time - get raise/fall time 302088cd222bSLinus Walleij * @regulator: regulator source 302188cd222bSLinus Walleij * @old_uV: starting voltage in microvolts 302288cd222bSLinus Walleij * @new_uV: target voltage in microvolts 302388cd222bSLinus Walleij * 302488cd222bSLinus Walleij * Provided with the starting and ending voltage, this function attempts to 302588cd222bSLinus Walleij * calculate the time in microseconds required to rise or fall to this new 302688cd222bSLinus Walleij * voltage. 302788cd222bSLinus Walleij */ 302888cd222bSLinus Walleij int regulator_set_voltage_time(struct regulator *regulator, 302988cd222bSLinus Walleij int old_uV, int new_uV) 303088cd222bSLinus Walleij { 303188cd222bSLinus Walleij struct regulator_dev *rdev = regulator->rdev; 3032272e2315SGuodong Xu const struct regulator_ops *ops = rdev->desc->ops; 303388cd222bSLinus Walleij int old_sel = -1; 303488cd222bSLinus Walleij int new_sel = -1; 303588cd222bSLinus Walleij int voltage; 303688cd222bSLinus Walleij int i; 303788cd222bSLinus Walleij 303873e705bfSMatthias Kaehlcke if (ops->set_voltage_time) 303973e705bfSMatthias Kaehlcke return ops->set_voltage_time(rdev, old_uV, new_uV); 304073e705bfSMatthias Kaehlcke else if (!ops->set_voltage_time_sel) 304173e705bfSMatthias Kaehlcke return _regulator_set_voltage_time(rdev, old_uV, new_uV); 304273e705bfSMatthias Kaehlcke 304388cd222bSLinus Walleij /* Currently requires operations to do this */ 304473e705bfSMatthias Kaehlcke if (!ops->list_voltage || !rdev->desc->n_voltages) 304588cd222bSLinus Walleij return -EINVAL; 304688cd222bSLinus Walleij 304788cd222bSLinus Walleij for (i = 0; i < rdev->desc->n_voltages; i++) { 304888cd222bSLinus Walleij /* We only look for exact voltage matches here */ 304988cd222bSLinus Walleij voltage = regulator_list_voltage(regulator, i); 305088cd222bSLinus Walleij if (voltage < 0) 305188cd222bSLinus Walleij return -EINVAL; 305288cd222bSLinus Walleij if (voltage == 0) 305388cd222bSLinus Walleij continue; 305488cd222bSLinus Walleij if (voltage == old_uV) 305588cd222bSLinus Walleij old_sel = i; 305688cd222bSLinus Walleij if (voltage == new_uV) 305788cd222bSLinus Walleij new_sel = i; 305888cd222bSLinus Walleij } 305988cd222bSLinus Walleij 306088cd222bSLinus Walleij if (old_sel < 0 || new_sel < 0) 306188cd222bSLinus Walleij return -EINVAL; 306288cd222bSLinus Walleij 306388cd222bSLinus Walleij return ops->set_voltage_time_sel(rdev, old_sel, new_sel); 306488cd222bSLinus Walleij } 306588cd222bSLinus Walleij EXPORT_SYMBOL_GPL(regulator_set_voltage_time); 306688cd222bSLinus Walleij 306788cd222bSLinus Walleij /** 306898a175b6SYadwinder Singh Brar * regulator_set_voltage_time_sel - get raise/fall time 3069296c6566SRandy Dunlap * @rdev: regulator source device 307098a175b6SYadwinder Singh Brar * @old_selector: selector for starting voltage 307198a175b6SYadwinder Singh Brar * @new_selector: selector for target voltage 307298a175b6SYadwinder Singh Brar * 307398a175b6SYadwinder Singh Brar * Provided with the starting and target voltage selectors, this function 307498a175b6SYadwinder Singh Brar * returns time in microseconds required to rise or fall to this new voltage 307598a175b6SYadwinder Singh Brar * 3076f11d08c3SAxel Lin * Drivers providing ramp_delay in regulation_constraints can use this as their 3077398715abSAxel Lin * set_voltage_time_sel() operation. 307898a175b6SYadwinder Singh Brar */ 307998a175b6SYadwinder Singh Brar int regulator_set_voltage_time_sel(struct regulator_dev *rdev, 308098a175b6SYadwinder Singh Brar unsigned int old_selector, 308198a175b6SYadwinder Singh Brar unsigned int new_selector) 308298a175b6SYadwinder Singh Brar { 3083f11d08c3SAxel Lin int old_volt, new_volt; 3084398715abSAxel Lin 3085f11d08c3SAxel Lin /* sanity check */ 3086f11d08c3SAxel Lin if (!rdev->desc->ops->list_voltage) 3087f11d08c3SAxel Lin return -EINVAL; 3088398715abSAxel Lin 3089f11d08c3SAxel Lin old_volt = rdev->desc->ops->list_voltage(rdev, old_selector); 3090f11d08c3SAxel Lin new_volt = rdev->desc->ops->list_voltage(rdev, new_selector); 3091f11d08c3SAxel Lin 309273e705bfSMatthias Kaehlcke if (rdev->desc->ops->set_voltage_time) 309373e705bfSMatthias Kaehlcke return rdev->desc->ops->set_voltage_time(rdev, old_volt, 309473e705bfSMatthias Kaehlcke new_volt); 309573e705bfSMatthias Kaehlcke else 309673e705bfSMatthias Kaehlcke return _regulator_set_voltage_time(rdev, old_volt, new_volt); 309798a175b6SYadwinder Singh Brar } 3098b19dbf71SMark Brown EXPORT_SYMBOL_GPL(regulator_set_voltage_time_sel); 309998a175b6SYadwinder Singh Brar 310098a175b6SYadwinder Singh Brar /** 3101606a2562SMark Brown * regulator_sync_voltage - re-apply last regulator output voltage 3102606a2562SMark Brown * @regulator: regulator source 3103606a2562SMark Brown * 3104606a2562SMark Brown * Re-apply the last configured voltage. This is intended to be used 3105606a2562SMark Brown * where some external control source the consumer is cooperating with 3106606a2562SMark Brown * has caused the configured voltage to change. 3107606a2562SMark Brown */ 3108606a2562SMark Brown int regulator_sync_voltage(struct regulator *regulator) 3109606a2562SMark Brown { 3110606a2562SMark Brown struct regulator_dev *rdev = regulator->rdev; 3111606a2562SMark Brown int ret, min_uV, max_uV; 3112606a2562SMark Brown 3113606a2562SMark Brown mutex_lock(&rdev->mutex); 3114606a2562SMark Brown 3115606a2562SMark Brown if (!rdev->desc->ops->set_voltage && 3116606a2562SMark Brown !rdev->desc->ops->set_voltage_sel) { 3117606a2562SMark Brown ret = -EINVAL; 3118606a2562SMark Brown goto out; 3119606a2562SMark Brown } 3120606a2562SMark Brown 3121606a2562SMark Brown /* This is only going to work if we've had a voltage configured. */ 3122606a2562SMark Brown if (!regulator->min_uV && !regulator->max_uV) { 3123606a2562SMark Brown ret = -EINVAL; 3124606a2562SMark Brown goto out; 3125606a2562SMark Brown } 3126606a2562SMark Brown 3127606a2562SMark Brown min_uV = regulator->min_uV; 3128606a2562SMark Brown max_uV = regulator->max_uV; 3129606a2562SMark Brown 3130606a2562SMark Brown /* This should be a paranoia check... */ 3131606a2562SMark Brown ret = regulator_check_voltage(rdev, &min_uV, &max_uV); 3132606a2562SMark Brown if (ret < 0) 3133606a2562SMark Brown goto out; 3134606a2562SMark Brown 3135606a2562SMark Brown ret = regulator_check_consumers(rdev, &min_uV, &max_uV); 3136606a2562SMark Brown if (ret < 0) 3137606a2562SMark Brown goto out; 3138606a2562SMark Brown 3139606a2562SMark Brown ret = _regulator_do_set_voltage(rdev, min_uV, max_uV); 3140606a2562SMark Brown 3141606a2562SMark Brown out: 3142606a2562SMark Brown mutex_unlock(&rdev->mutex); 3143606a2562SMark Brown return ret; 3144606a2562SMark Brown } 3145606a2562SMark Brown EXPORT_SYMBOL_GPL(regulator_sync_voltage); 3146606a2562SMark Brown 3147414c70cbSLiam Girdwood static int _regulator_get_voltage(struct regulator_dev *rdev) 3148414c70cbSLiam Girdwood { 3149bf5892a8SMark Brown int sel, ret; 3150fef95019SMark Brown bool bypassed; 3151fef95019SMark Brown 3152fef95019SMark Brown if (rdev->desc->ops->get_bypass) { 3153fef95019SMark Brown ret = rdev->desc->ops->get_bypass(rdev, &bypassed); 3154fef95019SMark Brown if (ret < 0) 3155fef95019SMark Brown return ret; 3156fef95019SMark Brown if (bypassed) { 3157fef95019SMark Brown /* if bypassed the regulator must have a supply */ 315845389c47SJon Hunter if (!rdev->supply) { 315945389c47SJon Hunter rdev_err(rdev, 316045389c47SJon Hunter "bypassed regulator has no supply!\n"); 316145389c47SJon Hunter return -EPROBE_DEFER; 316245389c47SJon Hunter } 3163fef95019SMark Brown 3164fef95019SMark Brown return _regulator_get_voltage(rdev->supply->rdev); 3165fef95019SMark Brown } 3166fef95019SMark Brown } 3167476c2d83SMark Brown 3168476c2d83SMark Brown if (rdev->desc->ops->get_voltage_sel) { 3169476c2d83SMark Brown sel = rdev->desc->ops->get_voltage_sel(rdev); 3170476c2d83SMark Brown if (sel < 0) 3171476c2d83SMark Brown return sel; 3172bf5892a8SMark Brown ret = rdev->desc->ops->list_voltage(rdev, sel); 3173cb220d16SAxel Lin } else if (rdev->desc->ops->get_voltage) { 3174bf5892a8SMark Brown ret = rdev->desc->ops->get_voltage(rdev); 3175f7df20ecSMark Brown } else if (rdev->desc->ops->list_voltage) { 3176f7df20ecSMark Brown ret = rdev->desc->ops->list_voltage(rdev, 0); 31775a523605SLaxman Dewangan } else if (rdev->desc->fixed_uV && (rdev->desc->n_voltages == 1)) { 31785a523605SLaxman Dewangan ret = rdev->desc->fixed_uV; 3179e303996eSJavier Martinez Canillas } else if (rdev->supply) { 3180d9b96d35SMark Brown ret = _regulator_get_voltage(rdev->supply->rdev); 3181cb220d16SAxel Lin } else { 3182414c70cbSLiam Girdwood return -EINVAL; 3183cb220d16SAxel Lin } 3184bf5892a8SMark Brown 3185cb220d16SAxel Lin if (ret < 0) 3186cb220d16SAxel Lin return ret; 3187bf5892a8SMark Brown return ret - rdev->constraints->uV_offset; 3188414c70cbSLiam Girdwood } 3189414c70cbSLiam Girdwood 3190414c70cbSLiam Girdwood /** 3191414c70cbSLiam Girdwood * regulator_get_voltage - get regulator output voltage 3192414c70cbSLiam Girdwood * @regulator: regulator source 3193414c70cbSLiam Girdwood * 3194414c70cbSLiam Girdwood * This returns the current regulator voltage in uV. 3195414c70cbSLiam Girdwood * 3196414c70cbSLiam Girdwood * NOTE: If the regulator is disabled it will return the voltage value. This 3197414c70cbSLiam Girdwood * function should not be used to determine regulator state. 3198414c70cbSLiam Girdwood */ 3199414c70cbSLiam Girdwood int regulator_get_voltage(struct regulator *regulator) 3200414c70cbSLiam Girdwood { 3201414c70cbSLiam Girdwood int ret; 3202414c70cbSLiam Girdwood 3203d9b96d35SMark Brown regulator_lock_supply(regulator->rdev); 3204414c70cbSLiam Girdwood 3205414c70cbSLiam Girdwood ret = _regulator_get_voltage(regulator->rdev); 3206414c70cbSLiam Girdwood 3207d9b96d35SMark Brown regulator_unlock_supply(regulator->rdev); 3208414c70cbSLiam Girdwood 3209414c70cbSLiam Girdwood return ret; 3210414c70cbSLiam Girdwood } 3211414c70cbSLiam Girdwood EXPORT_SYMBOL_GPL(regulator_get_voltage); 3212414c70cbSLiam Girdwood 3213414c70cbSLiam Girdwood /** 3214414c70cbSLiam Girdwood * regulator_set_current_limit - set regulator output current limit 3215414c70cbSLiam Girdwood * @regulator: regulator source 3216ce0d10f8SCharles Keepax * @min_uA: Minimum supported current in uA 3217414c70cbSLiam Girdwood * @max_uA: Maximum supported current in uA 3218414c70cbSLiam Girdwood * 3219414c70cbSLiam Girdwood * Sets current sink to the desired output current. This can be set during 3220414c70cbSLiam Girdwood * any regulator state. IOW, regulator can be disabled or enabled. 3221414c70cbSLiam Girdwood * 3222414c70cbSLiam Girdwood * If the regulator is enabled then the current will change to the new value 3223414c70cbSLiam Girdwood * immediately otherwise if the regulator is disabled the regulator will 3224414c70cbSLiam Girdwood * output at the new current when enabled. 3225414c70cbSLiam Girdwood * 3226414c70cbSLiam Girdwood * NOTE: Regulator system constraints must be set for this regulator before 3227414c70cbSLiam Girdwood * calling this function otherwise this call will fail. 3228414c70cbSLiam Girdwood */ 3229414c70cbSLiam Girdwood int regulator_set_current_limit(struct regulator *regulator, 3230414c70cbSLiam Girdwood int min_uA, int max_uA) 3231414c70cbSLiam Girdwood { 3232414c70cbSLiam Girdwood struct regulator_dev *rdev = regulator->rdev; 3233414c70cbSLiam Girdwood int ret; 3234414c70cbSLiam Girdwood 3235414c70cbSLiam Girdwood mutex_lock(&rdev->mutex); 3236414c70cbSLiam Girdwood 3237414c70cbSLiam Girdwood /* sanity check */ 3238414c70cbSLiam Girdwood if (!rdev->desc->ops->set_current_limit) { 3239414c70cbSLiam Girdwood ret = -EINVAL; 3240414c70cbSLiam Girdwood goto out; 3241414c70cbSLiam Girdwood } 3242414c70cbSLiam Girdwood 3243414c70cbSLiam Girdwood /* constraints check */ 3244414c70cbSLiam Girdwood ret = regulator_check_current_limit(rdev, &min_uA, &max_uA); 3245414c70cbSLiam Girdwood if (ret < 0) 3246414c70cbSLiam Girdwood goto out; 3247414c70cbSLiam Girdwood 3248414c70cbSLiam Girdwood ret = rdev->desc->ops->set_current_limit(rdev, min_uA, max_uA); 3249414c70cbSLiam Girdwood out: 3250414c70cbSLiam Girdwood mutex_unlock(&rdev->mutex); 3251414c70cbSLiam Girdwood return ret; 3252414c70cbSLiam Girdwood } 3253414c70cbSLiam Girdwood EXPORT_SYMBOL_GPL(regulator_set_current_limit); 3254414c70cbSLiam Girdwood 3255414c70cbSLiam Girdwood static int _regulator_get_current_limit(struct regulator_dev *rdev) 3256414c70cbSLiam Girdwood { 3257414c70cbSLiam Girdwood int ret; 3258414c70cbSLiam Girdwood 3259414c70cbSLiam Girdwood mutex_lock(&rdev->mutex); 3260414c70cbSLiam Girdwood 3261414c70cbSLiam Girdwood /* sanity check */ 3262414c70cbSLiam Girdwood if (!rdev->desc->ops->get_current_limit) { 3263414c70cbSLiam Girdwood ret = -EINVAL; 3264414c70cbSLiam Girdwood goto out; 3265414c70cbSLiam Girdwood } 3266414c70cbSLiam Girdwood 3267414c70cbSLiam Girdwood ret = rdev->desc->ops->get_current_limit(rdev); 3268414c70cbSLiam Girdwood out: 3269414c70cbSLiam Girdwood mutex_unlock(&rdev->mutex); 3270414c70cbSLiam Girdwood return ret; 3271414c70cbSLiam Girdwood } 3272414c70cbSLiam Girdwood 3273414c70cbSLiam Girdwood /** 3274414c70cbSLiam Girdwood * regulator_get_current_limit - get regulator output current 3275414c70cbSLiam Girdwood * @regulator: regulator source 3276414c70cbSLiam Girdwood * 3277414c70cbSLiam Girdwood * This returns the current supplied by the specified current sink in uA. 3278414c70cbSLiam Girdwood * 3279414c70cbSLiam Girdwood * NOTE: If the regulator is disabled it will return the current value. This 3280414c70cbSLiam Girdwood * function should not be used to determine regulator state. 3281414c70cbSLiam Girdwood */ 3282414c70cbSLiam Girdwood int regulator_get_current_limit(struct regulator *regulator) 3283414c70cbSLiam Girdwood { 3284414c70cbSLiam Girdwood return _regulator_get_current_limit(regulator->rdev); 3285414c70cbSLiam Girdwood } 3286414c70cbSLiam Girdwood EXPORT_SYMBOL_GPL(regulator_get_current_limit); 3287414c70cbSLiam Girdwood 3288414c70cbSLiam Girdwood /** 3289414c70cbSLiam Girdwood * regulator_set_mode - set regulator operating mode 3290414c70cbSLiam Girdwood * @regulator: regulator source 3291414c70cbSLiam Girdwood * @mode: operating mode - one of the REGULATOR_MODE constants 3292414c70cbSLiam Girdwood * 3293414c70cbSLiam Girdwood * Set regulator operating mode to increase regulator efficiency or improve 3294414c70cbSLiam Girdwood * regulation performance. 3295414c70cbSLiam Girdwood * 3296414c70cbSLiam Girdwood * NOTE: Regulator system constraints must be set for this regulator before 3297414c70cbSLiam Girdwood * calling this function otherwise this call will fail. 3298414c70cbSLiam Girdwood */ 3299414c70cbSLiam Girdwood int regulator_set_mode(struct regulator *regulator, unsigned int mode) 3300414c70cbSLiam Girdwood { 3301414c70cbSLiam Girdwood struct regulator_dev *rdev = regulator->rdev; 3302414c70cbSLiam Girdwood int ret; 3303500b4ac9SSundar R Iyer int regulator_curr_mode; 3304414c70cbSLiam Girdwood 3305414c70cbSLiam Girdwood mutex_lock(&rdev->mutex); 3306414c70cbSLiam Girdwood 3307414c70cbSLiam Girdwood /* sanity check */ 3308414c70cbSLiam Girdwood if (!rdev->desc->ops->set_mode) { 3309414c70cbSLiam Girdwood ret = -EINVAL; 3310414c70cbSLiam Girdwood goto out; 3311414c70cbSLiam Girdwood } 3312414c70cbSLiam Girdwood 3313500b4ac9SSundar R Iyer /* return if the same mode is requested */ 3314500b4ac9SSundar R Iyer if (rdev->desc->ops->get_mode) { 3315500b4ac9SSundar R Iyer regulator_curr_mode = rdev->desc->ops->get_mode(rdev); 3316500b4ac9SSundar R Iyer if (regulator_curr_mode == mode) { 3317500b4ac9SSundar R Iyer ret = 0; 3318500b4ac9SSundar R Iyer goto out; 3319500b4ac9SSundar R Iyer } 3320500b4ac9SSundar R Iyer } 3321500b4ac9SSundar R Iyer 3322414c70cbSLiam Girdwood /* constraints check */ 332322c51b47SAxel Lin ret = regulator_mode_constrain(rdev, &mode); 3324414c70cbSLiam Girdwood if (ret < 0) 3325414c70cbSLiam Girdwood goto out; 3326414c70cbSLiam Girdwood 3327414c70cbSLiam Girdwood ret = rdev->desc->ops->set_mode(rdev, mode); 3328414c70cbSLiam Girdwood out: 3329414c70cbSLiam Girdwood mutex_unlock(&rdev->mutex); 3330414c70cbSLiam Girdwood return ret; 3331414c70cbSLiam Girdwood } 3332414c70cbSLiam Girdwood EXPORT_SYMBOL_GPL(regulator_set_mode); 3333414c70cbSLiam Girdwood 3334414c70cbSLiam Girdwood static unsigned int _regulator_get_mode(struct regulator_dev *rdev) 3335414c70cbSLiam Girdwood { 3336414c70cbSLiam Girdwood int ret; 3337414c70cbSLiam Girdwood 3338414c70cbSLiam Girdwood mutex_lock(&rdev->mutex); 3339414c70cbSLiam Girdwood 3340414c70cbSLiam Girdwood /* sanity check */ 3341414c70cbSLiam Girdwood if (!rdev->desc->ops->get_mode) { 3342414c70cbSLiam Girdwood ret = -EINVAL; 3343414c70cbSLiam Girdwood goto out; 3344414c70cbSLiam Girdwood } 3345414c70cbSLiam Girdwood 3346414c70cbSLiam Girdwood ret = rdev->desc->ops->get_mode(rdev); 3347414c70cbSLiam Girdwood out: 3348414c70cbSLiam Girdwood mutex_unlock(&rdev->mutex); 3349414c70cbSLiam Girdwood return ret; 3350414c70cbSLiam Girdwood } 3351414c70cbSLiam Girdwood 3352414c70cbSLiam Girdwood /** 3353414c70cbSLiam Girdwood * regulator_get_mode - get regulator operating mode 3354414c70cbSLiam Girdwood * @regulator: regulator source 3355414c70cbSLiam Girdwood * 3356414c70cbSLiam Girdwood * Get the current regulator operating mode. 3357414c70cbSLiam Girdwood */ 3358414c70cbSLiam Girdwood unsigned int regulator_get_mode(struct regulator *regulator) 3359414c70cbSLiam Girdwood { 3360414c70cbSLiam Girdwood return _regulator_get_mode(regulator->rdev); 3361414c70cbSLiam Girdwood } 3362414c70cbSLiam Girdwood EXPORT_SYMBOL_GPL(regulator_get_mode); 3363414c70cbSLiam Girdwood 33641b5b4221SAxel Haslam static int _regulator_get_error_flags(struct regulator_dev *rdev, 33651b5b4221SAxel Haslam unsigned int *flags) 33661b5b4221SAxel Haslam { 33671b5b4221SAxel Haslam int ret; 33681b5b4221SAxel Haslam 33691b5b4221SAxel Haslam mutex_lock(&rdev->mutex); 33701b5b4221SAxel Haslam 33711b5b4221SAxel Haslam /* sanity check */ 33721b5b4221SAxel Haslam if (!rdev->desc->ops->get_error_flags) { 33731b5b4221SAxel Haslam ret = -EINVAL; 33741b5b4221SAxel Haslam goto out; 33751b5b4221SAxel Haslam } 33761b5b4221SAxel Haslam 33771b5b4221SAxel Haslam ret = rdev->desc->ops->get_error_flags(rdev, flags); 33781b5b4221SAxel Haslam out: 33791b5b4221SAxel Haslam mutex_unlock(&rdev->mutex); 33801b5b4221SAxel Haslam return ret; 33811b5b4221SAxel Haslam } 33821b5b4221SAxel Haslam 33831b5b4221SAxel Haslam /** 33841b5b4221SAxel Haslam * regulator_get_error_flags - get regulator error information 33851b5b4221SAxel Haslam * @regulator: regulator source 33861b5b4221SAxel Haslam * @flags: pointer to store error flags 33871b5b4221SAxel Haslam * 33881b5b4221SAxel Haslam * Get the current regulator error information. 33891b5b4221SAxel Haslam */ 33901b5b4221SAxel Haslam int regulator_get_error_flags(struct regulator *regulator, 33911b5b4221SAxel Haslam unsigned int *flags) 33921b5b4221SAxel Haslam { 33931b5b4221SAxel Haslam return _regulator_get_error_flags(regulator->rdev, flags); 33941b5b4221SAxel Haslam } 33951b5b4221SAxel Haslam EXPORT_SYMBOL_GPL(regulator_get_error_flags); 33961b5b4221SAxel Haslam 3397414c70cbSLiam Girdwood /** 3398e39ce48fSBjorn Andersson * regulator_set_load - set regulator load 3399414c70cbSLiam Girdwood * @regulator: regulator source 3400414c70cbSLiam Girdwood * @uA_load: load current 3401414c70cbSLiam Girdwood * 3402414c70cbSLiam Girdwood * Notifies the regulator core of a new device load. This is then used by 3403414c70cbSLiam Girdwood * DRMS (if enabled by constraints) to set the most efficient regulator 3404414c70cbSLiam Girdwood * operating mode for the new regulator loading. 3405414c70cbSLiam Girdwood * 3406414c70cbSLiam Girdwood * Consumer devices notify their supply regulator of the maximum power 3407414c70cbSLiam Girdwood * they will require (can be taken from device datasheet in the power 3408414c70cbSLiam Girdwood * consumption tables) when they change operational status and hence power 3409414c70cbSLiam Girdwood * state. Examples of operational state changes that can affect power 3410414c70cbSLiam Girdwood * consumption are :- 3411414c70cbSLiam Girdwood * 3412414c70cbSLiam Girdwood * o Device is opened / closed. 3413414c70cbSLiam Girdwood * o Device I/O is about to begin or has just finished. 3414414c70cbSLiam Girdwood * o Device is idling in between work. 3415414c70cbSLiam Girdwood * 3416414c70cbSLiam Girdwood * This information is also exported via sysfs to userspace. 3417414c70cbSLiam Girdwood * 3418414c70cbSLiam Girdwood * DRMS will sum the total requested load on the regulator and change 3419414c70cbSLiam Girdwood * to the most efficient operating mode if platform constraints allow. 3420414c70cbSLiam Girdwood * 3421e39ce48fSBjorn Andersson * On error a negative errno is returned. 3422414c70cbSLiam Girdwood */ 3423e39ce48fSBjorn Andersson int regulator_set_load(struct regulator *regulator, int uA_load) 3424414c70cbSLiam Girdwood { 3425414c70cbSLiam Girdwood struct regulator_dev *rdev = regulator->rdev; 34268460ef38SBjorn Andersson int ret; 3427d92d95b6SStephen Boyd 3428414c70cbSLiam Girdwood mutex_lock(&rdev->mutex); 3429414c70cbSLiam Girdwood regulator->uA_load = uA_load; 34308460ef38SBjorn Andersson ret = drms_uA_update(rdev); 3431414c70cbSLiam Girdwood mutex_unlock(&rdev->mutex); 34328460ef38SBjorn Andersson 3433414c70cbSLiam Girdwood return ret; 3434414c70cbSLiam Girdwood } 3435e39ce48fSBjorn Andersson EXPORT_SYMBOL_GPL(regulator_set_load); 3436414c70cbSLiam Girdwood 3437414c70cbSLiam Girdwood /** 3438f59c8f9fSMark Brown * regulator_allow_bypass - allow the regulator to go into bypass mode 3439f59c8f9fSMark Brown * 3440f59c8f9fSMark Brown * @regulator: Regulator to configure 34419345dfb8SNishanth Menon * @enable: enable or disable bypass mode 3442f59c8f9fSMark Brown * 3443f59c8f9fSMark Brown * Allow the regulator to go into bypass mode if all other consumers 3444f59c8f9fSMark Brown * for the regulator also enable bypass mode and the machine 3445f59c8f9fSMark Brown * constraints allow this. Bypass mode means that the regulator is 3446f59c8f9fSMark Brown * simply passing the input directly to the output with no regulation. 3447f59c8f9fSMark Brown */ 3448f59c8f9fSMark Brown int regulator_allow_bypass(struct regulator *regulator, bool enable) 3449f59c8f9fSMark Brown { 3450f59c8f9fSMark Brown struct regulator_dev *rdev = regulator->rdev; 3451f59c8f9fSMark Brown int ret = 0; 3452f59c8f9fSMark Brown 3453f59c8f9fSMark Brown if (!rdev->desc->ops->set_bypass) 3454f59c8f9fSMark Brown return 0; 3455f59c8f9fSMark Brown 34568a34e979SWEN Pingbo if (!regulator_ops_is_valid(rdev, REGULATOR_CHANGE_BYPASS)) 3457f59c8f9fSMark Brown return 0; 3458f59c8f9fSMark Brown 3459f59c8f9fSMark Brown mutex_lock(&rdev->mutex); 3460f59c8f9fSMark Brown 3461f59c8f9fSMark Brown if (enable && !regulator->bypass) { 3462f59c8f9fSMark Brown rdev->bypass_count++; 3463f59c8f9fSMark Brown 3464f59c8f9fSMark Brown if (rdev->bypass_count == rdev->open_count) { 3465f59c8f9fSMark Brown ret = rdev->desc->ops->set_bypass(rdev, enable); 3466f59c8f9fSMark Brown if (ret != 0) 3467f59c8f9fSMark Brown rdev->bypass_count--; 3468f59c8f9fSMark Brown } 3469f59c8f9fSMark Brown 3470f59c8f9fSMark Brown } else if (!enable && regulator->bypass) { 3471f59c8f9fSMark Brown rdev->bypass_count--; 3472f59c8f9fSMark Brown 3473f59c8f9fSMark Brown if (rdev->bypass_count != rdev->open_count) { 3474f59c8f9fSMark Brown ret = rdev->desc->ops->set_bypass(rdev, enable); 3475f59c8f9fSMark Brown if (ret != 0) 3476f59c8f9fSMark Brown rdev->bypass_count++; 3477f59c8f9fSMark Brown } 3478f59c8f9fSMark Brown } 3479f59c8f9fSMark Brown 3480f59c8f9fSMark Brown if (ret == 0) 3481f59c8f9fSMark Brown regulator->bypass = enable; 3482f59c8f9fSMark Brown 3483f59c8f9fSMark Brown mutex_unlock(&rdev->mutex); 3484f59c8f9fSMark Brown 3485f59c8f9fSMark Brown return ret; 3486f59c8f9fSMark Brown } 3487f59c8f9fSMark Brown EXPORT_SYMBOL_GPL(regulator_allow_bypass); 3488f59c8f9fSMark Brown 3489f59c8f9fSMark Brown /** 3490414c70cbSLiam Girdwood * regulator_register_notifier - register regulator event notifier 3491414c70cbSLiam Girdwood * @regulator: regulator source 349269279fb9SMark Brown * @nb: notifier block 3493414c70cbSLiam Girdwood * 3494414c70cbSLiam Girdwood * Register notifier block to receive regulator events. 3495414c70cbSLiam Girdwood */ 3496414c70cbSLiam Girdwood int regulator_register_notifier(struct regulator *regulator, 3497414c70cbSLiam Girdwood struct notifier_block *nb) 3498414c70cbSLiam Girdwood { 3499414c70cbSLiam Girdwood return blocking_notifier_chain_register(®ulator->rdev->notifier, 3500414c70cbSLiam Girdwood nb); 3501414c70cbSLiam Girdwood } 3502414c70cbSLiam Girdwood EXPORT_SYMBOL_GPL(regulator_register_notifier); 3503414c70cbSLiam Girdwood 3504414c70cbSLiam Girdwood /** 3505414c70cbSLiam Girdwood * regulator_unregister_notifier - unregister regulator event notifier 3506414c70cbSLiam Girdwood * @regulator: regulator source 350769279fb9SMark Brown * @nb: notifier block 3508414c70cbSLiam Girdwood * 3509414c70cbSLiam Girdwood * Unregister regulator event notifier block. 3510414c70cbSLiam Girdwood */ 3511414c70cbSLiam Girdwood int regulator_unregister_notifier(struct regulator *regulator, 3512414c70cbSLiam Girdwood struct notifier_block *nb) 3513414c70cbSLiam Girdwood { 3514414c70cbSLiam Girdwood return blocking_notifier_chain_unregister(®ulator->rdev->notifier, 3515414c70cbSLiam Girdwood nb); 3516414c70cbSLiam Girdwood } 3517414c70cbSLiam Girdwood EXPORT_SYMBOL_GPL(regulator_unregister_notifier); 3518414c70cbSLiam Girdwood 3519b136fb44SJonathan Cameron /* notify regulator consumers and downstream regulator consumers. 3520b136fb44SJonathan Cameron * Note mutex must be held by caller. 3521b136fb44SJonathan Cameron */ 35227179569aSHeiko Stübner static int _notifier_call_chain(struct regulator_dev *rdev, 3523414c70cbSLiam Girdwood unsigned long event, void *data) 3524414c70cbSLiam Girdwood { 3525414c70cbSLiam Girdwood /* call rdev chain first */ 35267179569aSHeiko Stübner return blocking_notifier_call_chain(&rdev->notifier, event, data); 3527414c70cbSLiam Girdwood } 3528414c70cbSLiam Girdwood 3529414c70cbSLiam Girdwood /** 3530414c70cbSLiam Girdwood * regulator_bulk_get - get multiple regulator consumers 3531414c70cbSLiam Girdwood * 3532414c70cbSLiam Girdwood * @dev: Device to supply 3533414c70cbSLiam Girdwood * @num_consumers: Number of consumers to register 3534414c70cbSLiam Girdwood * @consumers: Configuration of consumers; clients are stored here. 3535414c70cbSLiam Girdwood * 3536414c70cbSLiam Girdwood * @return 0 on success, an errno on failure. 3537414c70cbSLiam Girdwood * 3538414c70cbSLiam Girdwood * This helper function allows drivers to get several regulator 3539414c70cbSLiam Girdwood * consumers in one operation. If any of the regulators cannot be 3540414c70cbSLiam Girdwood * acquired then any regulators that were allocated will be freed 3541414c70cbSLiam Girdwood * before returning to the caller. 3542414c70cbSLiam Girdwood */ 3543414c70cbSLiam Girdwood int regulator_bulk_get(struct device *dev, int num_consumers, 3544414c70cbSLiam Girdwood struct regulator_bulk_data *consumers) 3545414c70cbSLiam Girdwood { 3546414c70cbSLiam Girdwood int i; 3547414c70cbSLiam Girdwood int ret; 3548414c70cbSLiam Girdwood 3549414c70cbSLiam Girdwood for (i = 0; i < num_consumers; i++) 3550414c70cbSLiam Girdwood consumers[i].consumer = NULL; 3551414c70cbSLiam Girdwood 3552414c70cbSLiam Girdwood for (i = 0; i < num_consumers; i++) { 3553565f9b07SBjorn Andersson consumers[i].consumer = regulator_get(dev, 3554565f9b07SBjorn Andersson consumers[i].supply); 3555414c70cbSLiam Girdwood if (IS_ERR(consumers[i].consumer)) { 3556414c70cbSLiam Girdwood ret = PTR_ERR(consumers[i].consumer); 35575b307627SMark Brown dev_err(dev, "Failed to get supply '%s': %d\n", 35585b307627SMark Brown consumers[i].supply, ret); 3559414c70cbSLiam Girdwood consumers[i].consumer = NULL; 3560414c70cbSLiam Girdwood goto err; 3561414c70cbSLiam Girdwood } 3562414c70cbSLiam Girdwood } 3563414c70cbSLiam Girdwood 3564414c70cbSLiam Girdwood return 0; 3565414c70cbSLiam Girdwood 3566414c70cbSLiam Girdwood err: 3567b29c7690SAxel Lin while (--i >= 0) 3568414c70cbSLiam Girdwood regulator_put(consumers[i].consumer); 3569414c70cbSLiam Girdwood 3570414c70cbSLiam Girdwood return ret; 3571414c70cbSLiam Girdwood } 3572414c70cbSLiam Girdwood EXPORT_SYMBOL_GPL(regulator_bulk_get); 3573414c70cbSLiam Girdwood 3574f21e0e81SMark Brown static void regulator_bulk_enable_async(void *data, async_cookie_t cookie) 3575f21e0e81SMark Brown { 3576f21e0e81SMark Brown struct regulator_bulk_data *bulk = data; 3577f21e0e81SMark Brown 3578f21e0e81SMark Brown bulk->ret = regulator_enable(bulk->consumer); 3579f21e0e81SMark Brown } 3580f21e0e81SMark Brown 3581414c70cbSLiam Girdwood /** 3582414c70cbSLiam Girdwood * regulator_bulk_enable - enable multiple regulator consumers 3583414c70cbSLiam Girdwood * 3584414c70cbSLiam Girdwood * @num_consumers: Number of consumers 3585414c70cbSLiam Girdwood * @consumers: Consumer data; clients are stored here. 3586414c70cbSLiam Girdwood * @return 0 on success, an errno on failure 3587414c70cbSLiam Girdwood * 3588414c70cbSLiam Girdwood * This convenience API allows consumers to enable multiple regulator 3589414c70cbSLiam Girdwood * clients in a single API call. If any consumers cannot be enabled 3590414c70cbSLiam Girdwood * then any others that were enabled will be disabled again prior to 3591414c70cbSLiam Girdwood * return. 3592414c70cbSLiam Girdwood */ 3593414c70cbSLiam Girdwood int regulator_bulk_enable(int num_consumers, 3594414c70cbSLiam Girdwood struct regulator_bulk_data *consumers) 3595414c70cbSLiam Girdwood { 35962955b47dSDan Williams ASYNC_DOMAIN_EXCLUSIVE(async_domain); 3597414c70cbSLiam Girdwood int i; 3598f21e0e81SMark Brown int ret = 0; 3599414c70cbSLiam Girdwood 36006492bc1bSMark Brown for (i = 0; i < num_consumers; i++) { 36016492bc1bSMark Brown if (consumers[i].consumer->always_on) 36026492bc1bSMark Brown consumers[i].ret = 0; 36036492bc1bSMark Brown else 3604f21e0e81SMark Brown async_schedule_domain(regulator_bulk_enable_async, 3605f21e0e81SMark Brown &consumers[i], &async_domain); 36066492bc1bSMark Brown } 3607f21e0e81SMark Brown 3608f21e0e81SMark Brown async_synchronize_full_domain(&async_domain); 3609f21e0e81SMark Brown 3610f21e0e81SMark Brown /* If any consumer failed we need to unwind any that succeeded */ 3611414c70cbSLiam Girdwood for (i = 0; i < num_consumers; i++) { 3612f21e0e81SMark Brown if (consumers[i].ret != 0) { 3613f21e0e81SMark Brown ret = consumers[i].ret; 3614414c70cbSLiam Girdwood goto err; 3615414c70cbSLiam Girdwood } 3616f21e0e81SMark Brown } 3617414c70cbSLiam Girdwood 3618414c70cbSLiam Girdwood return 0; 3619414c70cbSLiam Girdwood 3620414c70cbSLiam Girdwood err: 3621fbe31057SAndrzej Hajda for (i = 0; i < num_consumers; i++) { 3622fbe31057SAndrzej Hajda if (consumers[i].ret < 0) 3623fbe31057SAndrzej Hajda pr_err("Failed to enable %s: %d\n", consumers[i].supply, 3624fbe31057SAndrzej Hajda consumers[i].ret); 3625fbe31057SAndrzej Hajda else 3626414c70cbSLiam Girdwood regulator_disable(consumers[i].consumer); 3627fbe31057SAndrzej Hajda } 3628414c70cbSLiam Girdwood 3629414c70cbSLiam Girdwood return ret; 3630414c70cbSLiam Girdwood } 3631414c70cbSLiam Girdwood EXPORT_SYMBOL_GPL(regulator_bulk_enable); 3632414c70cbSLiam Girdwood 3633414c70cbSLiam Girdwood /** 3634414c70cbSLiam Girdwood * regulator_bulk_disable - disable multiple regulator consumers 3635414c70cbSLiam Girdwood * 3636414c70cbSLiam Girdwood * @num_consumers: Number of consumers 3637414c70cbSLiam Girdwood * @consumers: Consumer data; clients are stored here. 3638414c70cbSLiam Girdwood * @return 0 on success, an errno on failure 3639414c70cbSLiam Girdwood * 3640414c70cbSLiam Girdwood * This convenience API allows consumers to disable multiple regulator 364149e22632SSylwester Nawrocki * clients in a single API call. If any consumers cannot be disabled 364249e22632SSylwester Nawrocki * then any others that were disabled will be enabled again prior to 3643414c70cbSLiam Girdwood * return. 3644414c70cbSLiam Girdwood */ 3645414c70cbSLiam Girdwood int regulator_bulk_disable(int num_consumers, 3646414c70cbSLiam Girdwood struct regulator_bulk_data *consumers) 3647414c70cbSLiam Girdwood { 3648414c70cbSLiam Girdwood int i; 364901e86f49SMark Brown int ret, r; 3650414c70cbSLiam Girdwood 365149e22632SSylwester Nawrocki for (i = num_consumers - 1; i >= 0; --i) { 3652414c70cbSLiam Girdwood ret = regulator_disable(consumers[i].consumer); 3653414c70cbSLiam Girdwood if (ret != 0) 3654414c70cbSLiam Girdwood goto err; 3655414c70cbSLiam Girdwood } 3656414c70cbSLiam Girdwood 3657414c70cbSLiam Girdwood return 0; 3658414c70cbSLiam Girdwood 3659414c70cbSLiam Girdwood err: 36605da84fd9SJoe Perches pr_err("Failed to disable %s: %d\n", consumers[i].supply, ret); 366101e86f49SMark Brown for (++i; i < num_consumers; ++i) { 366201e86f49SMark Brown r = regulator_enable(consumers[i].consumer); 366301e86f49SMark Brown if (r != 0) 366401e86f49SMark Brown pr_err("Failed to reename %s: %d\n", 366501e86f49SMark Brown consumers[i].supply, r); 366601e86f49SMark Brown } 3667414c70cbSLiam Girdwood 3668414c70cbSLiam Girdwood return ret; 3669414c70cbSLiam Girdwood } 3670414c70cbSLiam Girdwood EXPORT_SYMBOL_GPL(regulator_bulk_disable); 3671414c70cbSLiam Girdwood 3672414c70cbSLiam Girdwood /** 3673e1de2f42SDonggeun Kim * regulator_bulk_force_disable - force disable multiple regulator consumers 3674e1de2f42SDonggeun Kim * 3675e1de2f42SDonggeun Kim * @num_consumers: Number of consumers 3676e1de2f42SDonggeun Kim * @consumers: Consumer data; clients are stored here. 3677e1de2f42SDonggeun Kim * @return 0 on success, an errno on failure 3678e1de2f42SDonggeun Kim * 3679e1de2f42SDonggeun Kim * This convenience API allows consumers to forcibly disable multiple regulator 3680e1de2f42SDonggeun Kim * clients in a single API call. 3681e1de2f42SDonggeun Kim * NOTE: This should be used for situations when device damage will 3682e1de2f42SDonggeun Kim * likely occur if the regulators are not disabled (e.g. over temp). 3683e1de2f42SDonggeun Kim * Although regulator_force_disable function call for some consumers can 3684e1de2f42SDonggeun Kim * return error numbers, the function is called for all consumers. 3685e1de2f42SDonggeun Kim */ 3686e1de2f42SDonggeun Kim int regulator_bulk_force_disable(int num_consumers, 3687e1de2f42SDonggeun Kim struct regulator_bulk_data *consumers) 3688e1de2f42SDonggeun Kim { 3689e1de2f42SDonggeun Kim int i; 3690e1de2f42SDonggeun Kim int ret; 3691e1de2f42SDonggeun Kim 3692e1de2f42SDonggeun Kim for (i = 0; i < num_consumers; i++) 3693e1de2f42SDonggeun Kim consumers[i].ret = 3694e1de2f42SDonggeun Kim regulator_force_disable(consumers[i].consumer); 3695e1de2f42SDonggeun Kim 3696e1de2f42SDonggeun Kim for (i = 0; i < num_consumers; i++) { 3697e1de2f42SDonggeun Kim if (consumers[i].ret != 0) { 3698e1de2f42SDonggeun Kim ret = consumers[i].ret; 3699e1de2f42SDonggeun Kim goto out; 3700e1de2f42SDonggeun Kim } 3701e1de2f42SDonggeun Kim } 3702e1de2f42SDonggeun Kim 3703e1de2f42SDonggeun Kim return 0; 3704e1de2f42SDonggeun Kim out: 3705e1de2f42SDonggeun Kim return ret; 3706e1de2f42SDonggeun Kim } 3707e1de2f42SDonggeun Kim EXPORT_SYMBOL_GPL(regulator_bulk_force_disable); 3708e1de2f42SDonggeun Kim 3709e1de2f42SDonggeun Kim /** 3710414c70cbSLiam Girdwood * regulator_bulk_free - free multiple regulator consumers 3711414c70cbSLiam Girdwood * 3712414c70cbSLiam Girdwood * @num_consumers: Number of consumers 3713414c70cbSLiam Girdwood * @consumers: Consumer data; clients are stored here. 3714414c70cbSLiam Girdwood * 3715414c70cbSLiam Girdwood * This convenience API allows consumers to free multiple regulator 3716414c70cbSLiam Girdwood * clients in a single API call. 3717414c70cbSLiam Girdwood */ 3718414c70cbSLiam Girdwood void regulator_bulk_free(int num_consumers, 3719414c70cbSLiam Girdwood struct regulator_bulk_data *consumers) 3720414c70cbSLiam Girdwood { 3721414c70cbSLiam Girdwood int i; 3722414c70cbSLiam Girdwood 3723414c70cbSLiam Girdwood for (i = 0; i < num_consumers; i++) { 3724414c70cbSLiam Girdwood regulator_put(consumers[i].consumer); 3725414c70cbSLiam Girdwood consumers[i].consumer = NULL; 3726414c70cbSLiam Girdwood } 3727414c70cbSLiam Girdwood } 3728414c70cbSLiam Girdwood EXPORT_SYMBOL_GPL(regulator_bulk_free); 3729414c70cbSLiam Girdwood 3730414c70cbSLiam Girdwood /** 3731414c70cbSLiam Girdwood * regulator_notifier_call_chain - call regulator event notifier 373269279fb9SMark Brown * @rdev: regulator source 3733414c70cbSLiam Girdwood * @event: notifier block 373469279fb9SMark Brown * @data: callback-specific data. 3735414c70cbSLiam Girdwood * 3736414c70cbSLiam Girdwood * Called by regulator drivers to notify clients a regulator event has 3737414c70cbSLiam Girdwood * occurred. We also notify regulator clients downstream. 3738b136fb44SJonathan Cameron * Note lock must be held by caller. 3739414c70cbSLiam Girdwood */ 3740414c70cbSLiam Girdwood int regulator_notifier_call_chain(struct regulator_dev *rdev, 3741414c70cbSLiam Girdwood unsigned long event, void *data) 3742414c70cbSLiam Girdwood { 374370cfef26SKrzysztof Kozlowski lockdep_assert_held_once(&rdev->mutex); 374470cfef26SKrzysztof Kozlowski 3745414c70cbSLiam Girdwood _notifier_call_chain(rdev, event, data); 3746414c70cbSLiam Girdwood return NOTIFY_DONE; 3747414c70cbSLiam Girdwood 3748414c70cbSLiam Girdwood } 3749414c70cbSLiam Girdwood EXPORT_SYMBOL_GPL(regulator_notifier_call_chain); 3750414c70cbSLiam Girdwood 3751be721979SMark Brown /** 3752be721979SMark Brown * regulator_mode_to_status - convert a regulator mode into a status 3753be721979SMark Brown * 3754be721979SMark Brown * @mode: Mode to convert 3755be721979SMark Brown * 3756be721979SMark Brown * Convert a regulator mode into a status. 3757be721979SMark Brown */ 3758be721979SMark Brown int regulator_mode_to_status(unsigned int mode) 3759be721979SMark Brown { 3760be721979SMark Brown switch (mode) { 3761be721979SMark Brown case REGULATOR_MODE_FAST: 3762be721979SMark Brown return REGULATOR_STATUS_FAST; 3763be721979SMark Brown case REGULATOR_MODE_NORMAL: 3764be721979SMark Brown return REGULATOR_STATUS_NORMAL; 3765be721979SMark Brown case REGULATOR_MODE_IDLE: 3766be721979SMark Brown return REGULATOR_STATUS_IDLE; 376703ffcf3dSKrystian Garbaciak case REGULATOR_MODE_STANDBY: 3768be721979SMark Brown return REGULATOR_STATUS_STANDBY; 3769be721979SMark Brown default: 37701beaf762SKrystian Garbaciak return REGULATOR_STATUS_UNDEFINED; 3771be721979SMark Brown } 3772be721979SMark Brown } 3773be721979SMark Brown EXPORT_SYMBOL_GPL(regulator_mode_to_status); 3774be721979SMark Brown 377539f802d6STakashi Iwai static struct attribute *regulator_dev_attrs[] = { 377639f802d6STakashi Iwai &dev_attr_name.attr, 377739f802d6STakashi Iwai &dev_attr_num_users.attr, 377839f802d6STakashi Iwai &dev_attr_type.attr, 377939f802d6STakashi Iwai &dev_attr_microvolts.attr, 378039f802d6STakashi Iwai &dev_attr_microamps.attr, 378139f802d6STakashi Iwai &dev_attr_opmode.attr, 378239f802d6STakashi Iwai &dev_attr_state.attr, 378339f802d6STakashi Iwai &dev_attr_status.attr, 378439f802d6STakashi Iwai &dev_attr_bypass.attr, 378539f802d6STakashi Iwai &dev_attr_requested_microamps.attr, 378639f802d6STakashi Iwai &dev_attr_min_microvolts.attr, 378739f802d6STakashi Iwai &dev_attr_max_microvolts.attr, 378839f802d6STakashi Iwai &dev_attr_min_microamps.attr, 378939f802d6STakashi Iwai &dev_attr_max_microamps.attr, 379039f802d6STakashi Iwai &dev_attr_suspend_standby_state.attr, 379139f802d6STakashi Iwai &dev_attr_suspend_mem_state.attr, 379239f802d6STakashi Iwai &dev_attr_suspend_disk_state.attr, 379339f802d6STakashi Iwai &dev_attr_suspend_standby_microvolts.attr, 379439f802d6STakashi Iwai &dev_attr_suspend_mem_microvolts.attr, 379539f802d6STakashi Iwai &dev_attr_suspend_disk_microvolts.attr, 379639f802d6STakashi Iwai &dev_attr_suspend_standby_mode.attr, 379739f802d6STakashi Iwai &dev_attr_suspend_mem_mode.attr, 379839f802d6STakashi Iwai &dev_attr_suspend_disk_mode.attr, 379939f802d6STakashi Iwai NULL 380039f802d6STakashi Iwai }; 380139f802d6STakashi Iwai 38027ad68e2fSDavid Brownell /* 38037ad68e2fSDavid Brownell * To avoid cluttering sysfs (and memory) with useless state, only 38047ad68e2fSDavid Brownell * create attributes that can be meaningfully displayed. 38057ad68e2fSDavid Brownell */ 380639f802d6STakashi Iwai static umode_t regulator_attr_is_visible(struct kobject *kobj, 380739f802d6STakashi Iwai struct attribute *attr, int idx) 38087ad68e2fSDavid Brownell { 380939f802d6STakashi Iwai struct device *dev = kobj_to_dev(kobj); 381083080a14SGeliang Tang struct regulator_dev *rdev = dev_to_rdev(dev); 3811272e2315SGuodong Xu const struct regulator_ops *ops = rdev->desc->ops; 381239f802d6STakashi Iwai umode_t mode = attr->mode; 381339f802d6STakashi Iwai 381439f802d6STakashi Iwai /* these three are always present */ 381539f802d6STakashi Iwai if (attr == &dev_attr_name.attr || 381639f802d6STakashi Iwai attr == &dev_attr_num_users.attr || 381739f802d6STakashi Iwai attr == &dev_attr_type.attr) 381839f802d6STakashi Iwai return mode; 38197ad68e2fSDavid Brownell 38207ad68e2fSDavid Brownell /* some attributes need specific methods to be displayed */ 382139f802d6STakashi Iwai if (attr == &dev_attr_microvolts.attr) { 38224c78899bSMark Brown if ((ops->get_voltage && ops->get_voltage(rdev) >= 0) || 3823f2889e65SMark Brown (ops->get_voltage_sel && ops->get_voltage_sel(rdev) >= 0) || 38245a523605SLaxman Dewangan (ops->list_voltage && ops->list_voltage(rdev, 0) >= 0) || 382539f802d6STakashi Iwai (rdev->desc->fixed_uV && rdev->desc->n_voltages == 1)) 382639f802d6STakashi Iwai return mode; 382739f802d6STakashi Iwai return 0; 3828f59c8f9fSMark Brown } 38297ad68e2fSDavid Brownell 383039f802d6STakashi Iwai if (attr == &dev_attr_microamps.attr) 383139f802d6STakashi Iwai return ops->get_current_limit ? mode : 0; 383239f802d6STakashi Iwai 383339f802d6STakashi Iwai if (attr == &dev_attr_opmode.attr) 383439f802d6STakashi Iwai return ops->get_mode ? mode : 0; 383539f802d6STakashi Iwai 383639f802d6STakashi Iwai if (attr == &dev_attr_state.attr) 383739f802d6STakashi Iwai return (rdev->ena_pin || ops->is_enabled) ? mode : 0; 383839f802d6STakashi Iwai 383939f802d6STakashi Iwai if (attr == &dev_attr_status.attr) 384039f802d6STakashi Iwai return ops->get_status ? mode : 0; 384139f802d6STakashi Iwai 384239f802d6STakashi Iwai if (attr == &dev_attr_bypass.attr) 384339f802d6STakashi Iwai return ops->get_bypass ? mode : 0; 384439f802d6STakashi Iwai 38457ad68e2fSDavid Brownell /* some attributes are type-specific */ 384639f802d6STakashi Iwai if (attr == &dev_attr_requested_microamps.attr) 384739f802d6STakashi Iwai return rdev->desc->type == REGULATOR_CURRENT ? mode : 0; 38487ad68e2fSDavid Brownell 38497ad68e2fSDavid Brownell /* constraints need specific supporting methods */ 385039f802d6STakashi Iwai if (attr == &dev_attr_min_microvolts.attr || 385139f802d6STakashi Iwai attr == &dev_attr_max_microvolts.attr) 385239f802d6STakashi Iwai return (ops->set_voltage || ops->set_voltage_sel) ? mode : 0; 385339f802d6STakashi Iwai 385439f802d6STakashi Iwai if (attr == &dev_attr_min_microamps.attr || 385539f802d6STakashi Iwai attr == &dev_attr_max_microamps.attr) 385639f802d6STakashi Iwai return ops->set_current_limit ? mode : 0; 385739f802d6STakashi Iwai 385839f802d6STakashi Iwai if (attr == &dev_attr_suspend_standby_state.attr || 385939f802d6STakashi Iwai attr == &dev_attr_suspend_mem_state.attr || 386039f802d6STakashi Iwai attr == &dev_attr_suspend_disk_state.attr) 386139f802d6STakashi Iwai return mode; 386239f802d6STakashi Iwai 386339f802d6STakashi Iwai if (attr == &dev_attr_suspend_standby_microvolts.attr || 386439f802d6STakashi Iwai attr == &dev_attr_suspend_mem_microvolts.attr || 386539f802d6STakashi Iwai attr == &dev_attr_suspend_disk_microvolts.attr) 386639f802d6STakashi Iwai return ops->set_suspend_voltage ? mode : 0; 386739f802d6STakashi Iwai 386839f802d6STakashi Iwai if (attr == &dev_attr_suspend_standby_mode.attr || 386939f802d6STakashi Iwai attr == &dev_attr_suspend_mem_mode.attr || 387039f802d6STakashi Iwai attr == &dev_attr_suspend_disk_mode.attr) 387139f802d6STakashi Iwai return ops->set_suspend_mode ? mode : 0; 387239f802d6STakashi Iwai 387339f802d6STakashi Iwai return mode; 38747ad68e2fSDavid Brownell } 38757ad68e2fSDavid Brownell 387639f802d6STakashi Iwai static const struct attribute_group regulator_dev_group = { 387739f802d6STakashi Iwai .attrs = regulator_dev_attrs, 387839f802d6STakashi Iwai .is_visible = regulator_attr_is_visible, 387939f802d6STakashi Iwai }; 38807ad68e2fSDavid Brownell 388139f802d6STakashi Iwai static const struct attribute_group *regulator_dev_groups[] = { 388239f802d6STakashi Iwai ®ulator_dev_group, 388339f802d6STakashi Iwai NULL 388439f802d6STakashi Iwai }; 388539f802d6STakashi Iwai 388639f802d6STakashi Iwai static void regulator_dev_release(struct device *dev) 388739f802d6STakashi Iwai { 388839f802d6STakashi Iwai struct regulator_dev *rdev = dev_get_drvdata(dev); 388929f5f486SMark Brown 389029f5f486SMark Brown kfree(rdev->constraints); 389129f5f486SMark Brown of_node_put(rdev->dev.of_node); 389239f802d6STakashi Iwai kfree(rdev); 38937ad68e2fSDavid Brownell } 38947ad68e2fSDavid Brownell 389539f802d6STakashi Iwai static struct class regulator_class = { 389639f802d6STakashi Iwai .name = "regulator", 389739f802d6STakashi Iwai .dev_release = regulator_dev_release, 389839f802d6STakashi Iwai .dev_groups = regulator_dev_groups, 389939f802d6STakashi Iwai }; 39007ad68e2fSDavid Brownell 39011130e5b3SMark Brown static void rdev_init_debugfs(struct regulator_dev *rdev) 39021130e5b3SMark Brown { 3903a9eaa813SGuenter Roeck struct device *parent = rdev->dev.parent; 3904a9eaa813SGuenter Roeck const char *rname = rdev_get_name(rdev); 3905a9eaa813SGuenter Roeck char name[NAME_MAX]; 3906a9eaa813SGuenter Roeck 3907a9eaa813SGuenter Roeck /* Avoid duplicate debugfs directory names */ 3908a9eaa813SGuenter Roeck if (parent && rname == rdev->desc->name) { 3909a9eaa813SGuenter Roeck snprintf(name, sizeof(name), "%s-%s", dev_name(parent), 3910a9eaa813SGuenter Roeck rname); 3911a9eaa813SGuenter Roeck rname = name; 3912a9eaa813SGuenter Roeck } 3913a9eaa813SGuenter Roeck 3914a9eaa813SGuenter Roeck rdev->debugfs = debugfs_create_dir(rname, debugfs_root); 391524751434SStephen Boyd if (!rdev->debugfs) { 39161130e5b3SMark Brown rdev_warn(rdev, "Failed to create debugfs directory\n"); 39171130e5b3SMark Brown return; 39181130e5b3SMark Brown } 39191130e5b3SMark Brown 39201130e5b3SMark Brown debugfs_create_u32("use_count", 0444, rdev->debugfs, 39211130e5b3SMark Brown &rdev->use_count); 39221130e5b3SMark Brown debugfs_create_u32("open_count", 0444, rdev->debugfs, 39231130e5b3SMark Brown &rdev->open_count); 3924f59c8f9fSMark Brown debugfs_create_u32("bypass_count", 0444, rdev->debugfs, 3925f59c8f9fSMark Brown &rdev->bypass_count); 39261130e5b3SMark Brown } 39271130e5b3SMark Brown 39285e3ca2b3SJavier Martinez Canillas static int regulator_register_resolve_supply(struct device *dev, void *data) 39295e3ca2b3SJavier Martinez Canillas { 39307ddede6aSJon Hunter struct regulator_dev *rdev = dev_to_rdev(dev); 39317ddede6aSJon Hunter 39327ddede6aSJon Hunter if (regulator_resolve_supply(rdev)) 39337ddede6aSJon Hunter rdev_dbg(rdev, "unable to resolve supply\n"); 39347ddede6aSJon Hunter 39357ddede6aSJon Hunter return 0; 39365e3ca2b3SJavier Martinez Canillas } 39375e3ca2b3SJavier Martinez Canillas 3938414c70cbSLiam Girdwood /** 3939414c70cbSLiam Girdwood * regulator_register - register regulator 394069279fb9SMark Brown * @regulator_desc: regulator to register 3941f47531b1SKrzysztof Kozlowski * @cfg: runtime configuration for regulator 3942414c70cbSLiam Girdwood * 3943414c70cbSLiam Girdwood * Called by regulator drivers to register a regulator. 39440384618aSAxel Lin * Returns a valid pointer to struct regulator_dev on success 39450384618aSAxel Lin * or an ERR_PTR() on error. 3946414c70cbSLiam Girdwood */ 394765f26846SMark Brown struct regulator_dev * 394865f26846SMark Brown regulator_register(const struct regulator_desc *regulator_desc, 39491b3de223SKrzysztof Kozlowski const struct regulator_config *cfg) 3950414c70cbSLiam Girdwood { 39519a8f5e07SMark Brown const struct regulation_constraints *constraints = NULL; 3952c172708dSMark Brown const struct regulator_init_data *init_data; 39531b3de223SKrzysztof Kozlowski struct regulator_config *config = NULL; 395472dca06fSAniroop Mathur static atomic_t regulator_no = ATOMIC_INIT(-1); 3955414c70cbSLiam Girdwood struct regulator_dev *rdev; 395632c8fad4SMark Brown struct device *dev; 3957a5766f11SLiam Girdwood int ret, i; 3958414c70cbSLiam Girdwood 39591b3de223SKrzysztof Kozlowski if (regulator_desc == NULL || cfg == NULL) 3960414c70cbSLiam Girdwood return ERR_PTR(-EINVAL); 3961414c70cbSLiam Girdwood 39621b3de223SKrzysztof Kozlowski dev = cfg->dev; 3963dcf70112SMark Brown WARN_ON(!dev); 396432c8fad4SMark Brown 3965414c70cbSLiam Girdwood if (regulator_desc->name == NULL || regulator_desc->ops == NULL) 3966414c70cbSLiam Girdwood return ERR_PTR(-EINVAL); 3967414c70cbSLiam Girdwood 3968cd78dfc6SDiego Liziero if (regulator_desc->type != REGULATOR_VOLTAGE && 3969cd78dfc6SDiego Liziero regulator_desc->type != REGULATOR_CURRENT) 3970414c70cbSLiam Girdwood return ERR_PTR(-EINVAL); 3971414c70cbSLiam Girdwood 3972476c2d83SMark Brown /* Only one of each should be implemented */ 3973476c2d83SMark Brown WARN_ON(regulator_desc->ops->get_voltage && 3974476c2d83SMark Brown regulator_desc->ops->get_voltage_sel); 3975e8eef82bSMark Brown WARN_ON(regulator_desc->ops->set_voltage && 3976e8eef82bSMark Brown regulator_desc->ops->set_voltage_sel); 3977476c2d83SMark Brown 3978476c2d83SMark Brown /* If we're using selectors we must implement list_voltage. */ 3979476c2d83SMark Brown if (regulator_desc->ops->get_voltage_sel && 3980476c2d83SMark Brown !regulator_desc->ops->list_voltage) { 3981476c2d83SMark Brown return ERR_PTR(-EINVAL); 3982476c2d83SMark Brown } 3983e8eef82bSMark Brown if (regulator_desc->ops->set_voltage_sel && 3984e8eef82bSMark Brown !regulator_desc->ops->list_voltage) { 3985e8eef82bSMark Brown return ERR_PTR(-EINVAL); 3986e8eef82bSMark Brown } 3987476c2d83SMark Brown 3988414c70cbSLiam Girdwood rdev = kzalloc(sizeof(struct regulator_dev), GFP_KERNEL); 3989414c70cbSLiam Girdwood if (rdev == NULL) 3990414c70cbSLiam Girdwood return ERR_PTR(-ENOMEM); 3991414c70cbSLiam Girdwood 39921b3de223SKrzysztof Kozlowski /* 39931b3de223SKrzysztof Kozlowski * Duplicate the config so the driver could override it after 39941b3de223SKrzysztof Kozlowski * parsing init data. 39951b3de223SKrzysztof Kozlowski */ 39961b3de223SKrzysztof Kozlowski config = kmemdup(cfg, sizeof(*cfg), GFP_KERNEL); 39971b3de223SKrzysztof Kozlowski if (config == NULL) { 39981b3de223SKrzysztof Kozlowski kfree(rdev); 39991b3de223SKrzysztof Kozlowski return ERR_PTR(-ENOMEM); 40001b3de223SKrzysztof Kozlowski } 40011b3de223SKrzysztof Kozlowski 4002bfa21a0dSKrzysztof Kozlowski init_data = regulator_of_get_init_data(dev, regulator_desc, config, 4003a0c7b164SMark Brown &rdev->dev.of_node); 4004a0c7b164SMark Brown if (!init_data) { 4005a0c7b164SMark Brown init_data = config->init_data; 4006a0c7b164SMark Brown rdev->dev.of_node = of_node_get(config->of_node); 4007a0c7b164SMark Brown } 4008a0c7b164SMark Brown 4009414c70cbSLiam Girdwood mutex_init(&rdev->mutex); 4010c172708dSMark Brown rdev->reg_data = config->driver_data; 4011414c70cbSLiam Girdwood rdev->owner = regulator_desc->owner; 4012414c70cbSLiam Girdwood rdev->desc = regulator_desc; 40133a4b0a07SMark Brown if (config->regmap) 401465b19ce6SMark Brown rdev->regmap = config->regmap; 401552b84dacSAnilKumar Ch else if (dev_get_regmap(dev, NULL)) 40163a4b0a07SMark Brown rdev->regmap = dev_get_regmap(dev, NULL); 401752b84dacSAnilKumar Ch else if (dev->parent) 401852b84dacSAnilKumar Ch rdev->regmap = dev_get_regmap(dev->parent, NULL); 4019414c70cbSLiam Girdwood INIT_LIST_HEAD(&rdev->consumer_list); 4020414c70cbSLiam Girdwood INIT_LIST_HEAD(&rdev->list); 4021414c70cbSLiam Girdwood BLOCKING_INIT_NOTIFIER_HEAD(&rdev->notifier); 4022da07ecd9SMark Brown INIT_DELAYED_WORK(&rdev->disable_work, regulator_disable_work); 4023414c70cbSLiam Girdwood 4024a5766f11SLiam Girdwood /* preform any regulator specific init */ 40259a8f5e07SMark Brown if (init_data && init_data->regulator_init) { 4026a5766f11SLiam Girdwood ret = init_data->regulator_init(rdev->reg_data); 40274fca9545SDavid Brownell if (ret < 0) 40284fca9545SDavid Brownell goto clean; 4029a5766f11SLiam Girdwood } 4030a5766f11SLiam Girdwood 4031daad134dSKrzysztof Adamski if ((config->ena_gpio || config->ena_gpio_initialized) && 4032daad134dSKrzysztof Adamski gpio_is_valid(config->ena_gpio)) { 403345389c47SJon Hunter mutex_lock(®ulator_list_mutex); 4034daad134dSKrzysztof Adamski ret = regulator_ena_gpio_request(rdev, config); 403545389c47SJon Hunter mutex_unlock(®ulator_list_mutex); 4036daad134dSKrzysztof Adamski if (ret != 0) { 4037daad134dSKrzysztof Adamski rdev_err(rdev, "Failed to request enable GPIO%d: %d\n", 4038daad134dSKrzysztof Adamski config->ena_gpio, ret); 403932165230SKrzysztof Adamski goto clean; 4040daad134dSKrzysztof Adamski } 4041daad134dSKrzysztof Adamski } 4042daad134dSKrzysztof Adamski 4043a5766f11SLiam Girdwood /* register with sysfs */ 4044a5766f11SLiam Girdwood rdev->dev.class = ®ulator_class; 4045a5766f11SLiam Girdwood rdev->dev.parent = dev; 404672dca06fSAniroop Mathur dev_set_name(&rdev->dev, "regulator.%lu", 404739138818SAniroop Mathur (unsigned long) atomic_inc_return(®ulator_no)); 4048a5766f11SLiam Girdwood 404974f544c1SMike Rapoport /* set regulator constraints */ 40509a8f5e07SMark Brown if (init_data) 40519a8f5e07SMark Brown constraints = &init_data->constraints; 40529a8f5e07SMark Brown 40539a8f5e07SMark Brown if (init_data && init_data->supply_regulator) 40546261b06dSBjorn Andersson rdev->supply_name = init_data->supply_regulator; 405569511a45SRajendra Nayak else if (regulator_desc->supply_name) 40566261b06dSBjorn Andersson rdev->supply_name = regulator_desc->supply_name; 405769511a45SRajendra Nayak 405845389c47SJon Hunter /* 405945389c47SJon Hunter * Attempt to resolve the regulator supply, if specified, 406045389c47SJon Hunter * but don't return an error if we fail because we will try 406145389c47SJon Hunter * to resolve it again later as more regulators are added. 406245389c47SJon Hunter */ 406345389c47SJon Hunter if (regulator_resolve_supply(rdev)) 406445389c47SJon Hunter rdev_dbg(rdev, "unable to resolve supply\n"); 406545389c47SJon Hunter 406645389c47SJon Hunter ret = set_machine_constraints(rdev, constraints); 406745389c47SJon Hunter if (ret < 0) 406845389c47SJon Hunter goto wash; 406945389c47SJon Hunter 4070a5766f11SLiam Girdwood /* add consumers devices */ 40719a8f5e07SMark Brown if (init_data) { 407245389c47SJon Hunter mutex_lock(®ulator_list_mutex); 4073a5766f11SLiam Girdwood for (i = 0; i < init_data->num_consumer_supplies; i++) { 4074a5766f11SLiam Girdwood ret = set_consumer_device_supply(rdev, 407540f9244fSMark Brown init_data->consumer_supplies[i].dev_name, 4076a5766f11SLiam Girdwood init_data->consumer_supplies[i].supply); 407723c2f041SMark Brown if (ret < 0) { 407845389c47SJon Hunter mutex_unlock(®ulator_list_mutex); 407923c2f041SMark Brown dev_err(dev, "Failed to set supply %s\n", 408023c2f041SMark Brown init_data->consumer_supplies[i].supply); 4081d4033b54SJani Nikula goto unset_supplies; 4082a5766f11SLiam Girdwood } 408323c2f041SMark Brown } 4084a2151374SJon Hunter mutex_unlock(®ulator_list_mutex); 40859a8f5e07SMark Brown } 4086a5766f11SLiam Girdwood 4087c438b9d0SJon Hunter ret = device_register(&rdev->dev); 4088c438b9d0SJon Hunter if (ret != 0) { 4089c438b9d0SJon Hunter put_device(&rdev->dev); 4090c438b9d0SJon Hunter goto unset_supplies; 4091c438b9d0SJon Hunter } 4092c438b9d0SJon Hunter 4093c438b9d0SJon Hunter dev_set_drvdata(&rdev->dev, rdev); 40941130e5b3SMark Brown rdev_init_debugfs(rdev); 40955e3ca2b3SJavier Martinez Canillas 40965e3ca2b3SJavier Martinez Canillas /* try to resolve regulators supply since a new one was registered */ 40975e3ca2b3SJavier Martinez Canillas class_for_each_device(®ulator_class, NULL, NULL, 40985e3ca2b3SJavier Martinez Canillas regulator_register_resolve_supply); 40991b3de223SKrzysztof Kozlowski kfree(config); 4100414c70cbSLiam Girdwood return rdev; 41014fca9545SDavid Brownell 4102d4033b54SJani Nikula unset_supplies: 410345389c47SJon Hunter mutex_lock(®ulator_list_mutex); 4104d4033b54SJani Nikula unset_regulator_supplies(rdev); 410545389c47SJon Hunter mutex_unlock(®ulator_list_mutex); 410632165230SKrzysztof Adamski wash: 4107469b640eSBoris Brezillon kfree(rdev->constraints); 410845389c47SJon Hunter mutex_lock(®ulator_list_mutex); 410932165230SKrzysztof Adamski regulator_ena_gpio_free(rdev); 411045389c47SJon Hunter mutex_unlock(®ulator_list_mutex); 41114fca9545SDavid Brownell clean: 41124fca9545SDavid Brownell kfree(rdev); 4113a2151374SJon Hunter kfree(config); 4114a2151374SJon Hunter return ERR_PTR(ret); 4115414c70cbSLiam Girdwood } 4116414c70cbSLiam Girdwood EXPORT_SYMBOL_GPL(regulator_register); 4117414c70cbSLiam Girdwood 4118414c70cbSLiam Girdwood /** 4119414c70cbSLiam Girdwood * regulator_unregister - unregister regulator 412069279fb9SMark Brown * @rdev: regulator to unregister 4121414c70cbSLiam Girdwood * 4122414c70cbSLiam Girdwood * Called by regulator drivers to unregister a regulator. 4123414c70cbSLiam Girdwood */ 4124414c70cbSLiam Girdwood void regulator_unregister(struct regulator_dev *rdev) 4125414c70cbSLiam Girdwood { 4126414c70cbSLiam Girdwood if (rdev == NULL) 4127414c70cbSLiam Girdwood return; 4128414c70cbSLiam Girdwood 4129891636eaSMark Brown if (rdev->supply) { 4130891636eaSMark Brown while (rdev->use_count--) 4131891636eaSMark Brown regulator_disable(rdev->supply); 4132e032b376SMark Brown regulator_put(rdev->supply); 4133891636eaSMark Brown } 4134414c70cbSLiam Girdwood mutex_lock(®ulator_list_mutex); 41351130e5b3SMark Brown debugfs_remove_recursive(rdev->debugfs); 413643829731STejun Heo flush_work(&rdev->disable_work.work); 41376bf87d17SMark Brown WARN_ON(rdev->open_count); 41380f1d747bSMike Rapoport unset_regulator_supplies(rdev); 4139414c70cbSLiam Girdwood list_del(&rdev->list); 4140f19b00daSKim, Milo regulator_ena_gpio_free(rdev); 41412c0a303aSMark Brown mutex_unlock(®ulator_list_mutex); 414258fb5cf5SLothar Waßmann device_unregister(&rdev->dev); 4143414c70cbSLiam Girdwood } 4144414c70cbSLiam Girdwood EXPORT_SYMBOL_GPL(regulator_unregister); 4145414c70cbSLiam Girdwood 414685f3b431STomeu Vizoso static int _regulator_suspend_prepare(struct device *dev, void *data) 414785f3b431STomeu Vizoso { 414885f3b431STomeu Vizoso struct regulator_dev *rdev = dev_to_rdev(dev); 414985f3b431STomeu Vizoso const suspend_state_t *state = data; 415085f3b431STomeu Vizoso int ret; 415185f3b431STomeu Vizoso 415285f3b431STomeu Vizoso mutex_lock(&rdev->mutex); 415385f3b431STomeu Vizoso ret = suspend_prepare(rdev, *state); 415485f3b431STomeu Vizoso mutex_unlock(&rdev->mutex); 415585f3b431STomeu Vizoso 415685f3b431STomeu Vizoso return ret; 415785f3b431STomeu Vizoso } 415885f3b431STomeu Vizoso 4159414c70cbSLiam Girdwood /** 4160cf7bbcdfSMark Brown * regulator_suspend_prepare - prepare regulators for system wide suspend 4161414c70cbSLiam Girdwood * @state: system suspend state 4162414c70cbSLiam Girdwood * 4163414c70cbSLiam Girdwood * Configure each regulator with it's suspend operating parameters for state. 4164414c70cbSLiam Girdwood * This will usually be called by machine suspend code prior to supending. 4165414c70cbSLiam Girdwood */ 4166414c70cbSLiam Girdwood int regulator_suspend_prepare(suspend_state_t state) 4167414c70cbSLiam Girdwood { 4168414c70cbSLiam Girdwood /* ON is handled by regulator active state */ 4169414c70cbSLiam Girdwood if (state == PM_SUSPEND_ON) 4170414c70cbSLiam Girdwood return -EINVAL; 4171414c70cbSLiam Girdwood 417285f3b431STomeu Vizoso return class_for_each_device(®ulator_class, NULL, &state, 417385f3b431STomeu Vizoso _regulator_suspend_prepare); 4174414c70cbSLiam Girdwood } 4175414c70cbSLiam Girdwood EXPORT_SYMBOL_GPL(regulator_suspend_prepare); 4176414c70cbSLiam Girdwood 417785f3b431STomeu Vizoso static int _regulator_suspend_finish(struct device *dev, void *data) 417885f3b431STomeu Vizoso { 417985f3b431STomeu Vizoso struct regulator_dev *rdev = dev_to_rdev(dev); 418085f3b431STomeu Vizoso int ret; 418185f3b431STomeu Vizoso 418285f3b431STomeu Vizoso mutex_lock(&rdev->mutex); 418385f3b431STomeu Vizoso if (rdev->use_count > 0 || rdev->constraints->always_on) { 418485f3b431STomeu Vizoso if (!_regulator_is_enabled(rdev)) { 418585f3b431STomeu Vizoso ret = _regulator_do_enable(rdev); 418685f3b431STomeu Vizoso if (ret) 418785f3b431STomeu Vizoso dev_err(dev, 418885f3b431STomeu Vizoso "Failed to resume regulator %d\n", 418985f3b431STomeu Vizoso ret); 419085f3b431STomeu Vizoso } 419185f3b431STomeu Vizoso } else { 419285f3b431STomeu Vizoso if (!have_full_constraints()) 419385f3b431STomeu Vizoso goto unlock; 419485f3b431STomeu Vizoso if (!_regulator_is_enabled(rdev)) 419585f3b431STomeu Vizoso goto unlock; 419685f3b431STomeu Vizoso 419785f3b431STomeu Vizoso ret = _regulator_do_disable(rdev); 419885f3b431STomeu Vizoso if (ret) 419985f3b431STomeu Vizoso dev_err(dev, "Failed to suspend regulator %d\n", ret); 420085f3b431STomeu Vizoso } 420185f3b431STomeu Vizoso unlock: 420285f3b431STomeu Vizoso mutex_unlock(&rdev->mutex); 420385f3b431STomeu Vizoso 420485f3b431STomeu Vizoso /* Keep processing regulators in spite of any errors */ 420585f3b431STomeu Vizoso return 0; 420685f3b431STomeu Vizoso } 420785f3b431STomeu Vizoso 4208414c70cbSLiam Girdwood /** 42097a32b589SMyungJoo Ham * regulator_suspend_finish - resume regulators from system wide suspend 42107a32b589SMyungJoo Ham * 42117a32b589SMyungJoo Ham * Turn on regulators that might be turned off by regulator_suspend_prepare 42127a32b589SMyungJoo Ham * and that should be turned on according to the regulators properties. 42137a32b589SMyungJoo Ham */ 42147a32b589SMyungJoo Ham int regulator_suspend_finish(void) 42157a32b589SMyungJoo Ham { 421685f3b431STomeu Vizoso return class_for_each_device(®ulator_class, NULL, NULL, 421785f3b431STomeu Vizoso _regulator_suspend_finish); 42187a32b589SMyungJoo Ham } 42197a32b589SMyungJoo Ham EXPORT_SYMBOL_GPL(regulator_suspend_finish); 42207a32b589SMyungJoo Ham 42217a32b589SMyungJoo Ham /** 4222ca725561SMark Brown * regulator_has_full_constraints - the system has fully specified constraints 4223ca725561SMark Brown * 4224ca725561SMark Brown * Calling this function will cause the regulator API to disable all 4225ca725561SMark Brown * regulators which have a zero use count and don't have an always_on 4226ca725561SMark Brown * constraint in a late_initcall. 4227ca725561SMark Brown * 4228ca725561SMark Brown * The intention is that this will become the default behaviour in a 4229ca725561SMark Brown * future kernel release so users are encouraged to use this facility 4230ca725561SMark Brown * now. 4231ca725561SMark Brown */ 4232ca725561SMark Brown void regulator_has_full_constraints(void) 4233ca725561SMark Brown { 4234ca725561SMark Brown has_full_constraints = 1; 4235ca725561SMark Brown } 4236ca725561SMark Brown EXPORT_SYMBOL_GPL(regulator_has_full_constraints); 4237ca725561SMark Brown 4238ca725561SMark Brown /** 4239414c70cbSLiam Girdwood * rdev_get_drvdata - get rdev regulator driver data 424069279fb9SMark Brown * @rdev: regulator 4241414c70cbSLiam Girdwood * 4242414c70cbSLiam Girdwood * Get rdev regulator driver private data. This call can be used in the 4243414c70cbSLiam Girdwood * regulator driver context. 4244414c70cbSLiam Girdwood */ 4245414c70cbSLiam Girdwood void *rdev_get_drvdata(struct regulator_dev *rdev) 4246414c70cbSLiam Girdwood { 4247414c70cbSLiam Girdwood return rdev->reg_data; 4248414c70cbSLiam Girdwood } 4249414c70cbSLiam Girdwood EXPORT_SYMBOL_GPL(rdev_get_drvdata); 4250414c70cbSLiam Girdwood 4251414c70cbSLiam Girdwood /** 4252414c70cbSLiam Girdwood * regulator_get_drvdata - get regulator driver data 4253414c70cbSLiam Girdwood * @regulator: regulator 4254414c70cbSLiam Girdwood * 4255414c70cbSLiam Girdwood * Get regulator driver private data. This call can be used in the consumer 4256414c70cbSLiam Girdwood * driver context when non API regulator specific functions need to be called. 4257414c70cbSLiam Girdwood */ 4258414c70cbSLiam Girdwood void *regulator_get_drvdata(struct regulator *regulator) 4259414c70cbSLiam Girdwood { 4260414c70cbSLiam Girdwood return regulator->rdev->reg_data; 4261414c70cbSLiam Girdwood } 4262414c70cbSLiam Girdwood EXPORT_SYMBOL_GPL(regulator_get_drvdata); 4263414c70cbSLiam Girdwood 4264414c70cbSLiam Girdwood /** 4265414c70cbSLiam Girdwood * regulator_set_drvdata - set regulator driver data 4266414c70cbSLiam Girdwood * @regulator: regulator 4267414c70cbSLiam Girdwood * @data: data 4268414c70cbSLiam Girdwood */ 4269414c70cbSLiam Girdwood void regulator_set_drvdata(struct regulator *regulator, void *data) 4270414c70cbSLiam Girdwood { 4271414c70cbSLiam Girdwood regulator->rdev->reg_data = data; 4272414c70cbSLiam Girdwood } 4273414c70cbSLiam Girdwood EXPORT_SYMBOL_GPL(regulator_set_drvdata); 4274414c70cbSLiam Girdwood 4275414c70cbSLiam Girdwood /** 4276414c70cbSLiam Girdwood * regulator_get_id - get regulator ID 427769279fb9SMark Brown * @rdev: regulator 4278414c70cbSLiam Girdwood */ 4279414c70cbSLiam Girdwood int rdev_get_id(struct regulator_dev *rdev) 4280414c70cbSLiam Girdwood { 4281414c70cbSLiam Girdwood return rdev->desc->id; 4282414c70cbSLiam Girdwood } 4283414c70cbSLiam Girdwood EXPORT_SYMBOL_GPL(rdev_get_id); 4284414c70cbSLiam Girdwood 4285a5766f11SLiam Girdwood struct device *rdev_get_dev(struct regulator_dev *rdev) 4286a5766f11SLiam Girdwood { 4287a5766f11SLiam Girdwood return &rdev->dev; 4288a5766f11SLiam Girdwood } 4289a5766f11SLiam Girdwood EXPORT_SYMBOL_GPL(rdev_get_dev); 4290a5766f11SLiam Girdwood 4291a5766f11SLiam Girdwood void *regulator_get_init_drvdata(struct regulator_init_data *reg_init_data) 4292a5766f11SLiam Girdwood { 4293a5766f11SLiam Girdwood return reg_init_data->driver_data; 4294a5766f11SLiam Girdwood } 4295a5766f11SLiam Girdwood EXPORT_SYMBOL_GPL(regulator_get_init_drvdata); 4296a5766f11SLiam Girdwood 4297ba55a974SMark Brown #ifdef CONFIG_DEBUG_FS 4298ba55a974SMark Brown static ssize_t supply_map_read_file(struct file *file, char __user *user_buf, 4299ba55a974SMark Brown size_t count, loff_t *ppos) 4300ba55a974SMark Brown { 4301ba55a974SMark Brown char *buf = kmalloc(PAGE_SIZE, GFP_KERNEL); 4302ba55a974SMark Brown ssize_t len, ret = 0; 4303ba55a974SMark Brown struct regulator_map *map; 4304ba55a974SMark Brown 4305ba55a974SMark Brown if (!buf) 4306ba55a974SMark Brown return -ENOMEM; 4307ba55a974SMark Brown 4308ba55a974SMark Brown list_for_each_entry(map, ®ulator_map_list, list) { 4309ba55a974SMark Brown len = snprintf(buf + ret, PAGE_SIZE - ret, 4310ba55a974SMark Brown "%s -> %s.%s\n", 4311ba55a974SMark Brown rdev_get_name(map->regulator), map->dev_name, 4312ba55a974SMark Brown map->supply); 4313ba55a974SMark Brown if (len >= 0) 4314ba55a974SMark Brown ret += len; 4315ba55a974SMark Brown if (ret > PAGE_SIZE) { 4316ba55a974SMark Brown ret = PAGE_SIZE; 4317ba55a974SMark Brown break; 4318ba55a974SMark Brown } 4319ba55a974SMark Brown } 4320ba55a974SMark Brown 4321ba55a974SMark Brown ret = simple_read_from_buffer(user_buf, count, ppos, buf, ret); 4322ba55a974SMark Brown 4323ba55a974SMark Brown kfree(buf); 4324ba55a974SMark Brown 4325ba55a974SMark Brown return ret; 4326ba55a974SMark Brown } 432724751434SStephen Boyd #endif 4328ba55a974SMark Brown 4329ba55a974SMark Brown static const struct file_operations supply_map_fops = { 433024751434SStephen Boyd #ifdef CONFIG_DEBUG_FS 4331ba55a974SMark Brown .read = supply_map_read_file, 4332ba55a974SMark Brown .llseek = default_llseek, 4333ba55a974SMark Brown #endif 433424751434SStephen Boyd }; 4335ba55a974SMark Brown 43367c225ec9SHeiko Stübner #ifdef CONFIG_DEBUG_FS 433785f3b431STomeu Vizoso struct summary_data { 433885f3b431STomeu Vizoso struct seq_file *s; 433985f3b431STomeu Vizoso struct regulator_dev *parent; 434085f3b431STomeu Vizoso int level; 434185f3b431STomeu Vizoso }; 434285f3b431STomeu Vizoso 434385f3b431STomeu Vizoso static void regulator_summary_show_subtree(struct seq_file *s, 434485f3b431STomeu Vizoso struct regulator_dev *rdev, 434585f3b431STomeu Vizoso int level); 434685f3b431STomeu Vizoso 434785f3b431STomeu Vizoso static int regulator_summary_show_children(struct device *dev, void *data) 434885f3b431STomeu Vizoso { 434985f3b431STomeu Vizoso struct regulator_dev *rdev = dev_to_rdev(dev); 435085f3b431STomeu Vizoso struct summary_data *summary_data = data; 435185f3b431STomeu Vizoso 435285f3b431STomeu Vizoso if (rdev->supply && rdev->supply->rdev == summary_data->parent) 435385f3b431STomeu Vizoso regulator_summary_show_subtree(summary_data->s, rdev, 435485f3b431STomeu Vizoso summary_data->level + 1); 435585f3b431STomeu Vizoso 435685f3b431STomeu Vizoso return 0; 435785f3b431STomeu Vizoso } 435885f3b431STomeu Vizoso 43597c225ec9SHeiko Stübner static void regulator_summary_show_subtree(struct seq_file *s, 43607c225ec9SHeiko Stübner struct regulator_dev *rdev, 43617c225ec9SHeiko Stübner int level) 43627c225ec9SHeiko Stübner { 43637c225ec9SHeiko Stübner struct regulation_constraints *c; 43647c225ec9SHeiko Stübner struct regulator *consumer; 436585f3b431STomeu Vizoso struct summary_data summary_data; 43667c225ec9SHeiko Stübner 43677c225ec9SHeiko Stübner if (!rdev) 43687c225ec9SHeiko Stübner return; 43697c225ec9SHeiko Stübner 43707c225ec9SHeiko Stübner seq_printf(s, "%*s%-*s %3d %4d %6d ", 43717c225ec9SHeiko Stübner level * 3 + 1, "", 43727c225ec9SHeiko Stübner 30 - level * 3, rdev_get_name(rdev), 43737c225ec9SHeiko Stübner rdev->use_count, rdev->open_count, rdev->bypass_count); 43747c225ec9SHeiko Stübner 437523296099SHeiko Stübner seq_printf(s, "%5dmV ", _regulator_get_voltage(rdev) / 1000); 437623296099SHeiko Stübner seq_printf(s, "%5dmA ", _regulator_get_current_limit(rdev) / 1000); 43777c225ec9SHeiko Stübner 43787c225ec9SHeiko Stübner c = rdev->constraints; 43797c225ec9SHeiko Stübner if (c) { 43807c225ec9SHeiko Stübner switch (rdev->desc->type) { 43817c225ec9SHeiko Stübner case REGULATOR_VOLTAGE: 43827c225ec9SHeiko Stübner seq_printf(s, "%5dmV %5dmV ", 43837c225ec9SHeiko Stübner c->min_uV / 1000, c->max_uV / 1000); 43847c225ec9SHeiko Stübner break; 43857c225ec9SHeiko Stübner case REGULATOR_CURRENT: 43867c225ec9SHeiko Stübner seq_printf(s, "%5dmA %5dmA ", 43877c225ec9SHeiko Stübner c->min_uA / 1000, c->max_uA / 1000); 43887c225ec9SHeiko Stübner break; 43897c225ec9SHeiko Stübner } 43907c225ec9SHeiko Stübner } 43917c225ec9SHeiko Stübner 43927c225ec9SHeiko Stübner seq_puts(s, "\n"); 43937c225ec9SHeiko Stübner 43947c225ec9SHeiko Stübner list_for_each_entry(consumer, &rdev->consumer_list, list) { 43957c225ec9SHeiko Stübner if (consumer->dev->class == ®ulator_class) 43967c225ec9SHeiko Stübner continue; 43977c225ec9SHeiko Stübner 43987c225ec9SHeiko Stübner seq_printf(s, "%*s%-*s ", 43997c225ec9SHeiko Stübner (level + 1) * 3 + 1, "", 44007c225ec9SHeiko Stübner 30 - (level + 1) * 3, dev_name(consumer->dev)); 44017c225ec9SHeiko Stübner 44027c225ec9SHeiko Stübner switch (rdev->desc->type) { 44037c225ec9SHeiko Stübner case REGULATOR_VOLTAGE: 440423296099SHeiko Stübner seq_printf(s, "%37dmV %5dmV", 44057c225ec9SHeiko Stübner consumer->min_uV / 1000, 44067c225ec9SHeiko Stübner consumer->max_uV / 1000); 44077c225ec9SHeiko Stübner break; 44087c225ec9SHeiko Stübner case REGULATOR_CURRENT: 44097c225ec9SHeiko Stübner break; 44107c225ec9SHeiko Stübner } 44117c225ec9SHeiko Stübner 44127c225ec9SHeiko Stübner seq_puts(s, "\n"); 44137c225ec9SHeiko Stübner } 44147c225ec9SHeiko Stübner 441585f3b431STomeu Vizoso summary_data.s = s; 441685f3b431STomeu Vizoso summary_data.level = level; 441785f3b431STomeu Vizoso summary_data.parent = rdev; 44187c225ec9SHeiko Stübner 441985f3b431STomeu Vizoso class_for_each_device(®ulator_class, NULL, &summary_data, 442085f3b431STomeu Vizoso regulator_summary_show_children); 44217c225ec9SHeiko Stübner } 442285f3b431STomeu Vizoso 442385f3b431STomeu Vizoso static int regulator_summary_show_roots(struct device *dev, void *data) 442485f3b431STomeu Vizoso { 442585f3b431STomeu Vizoso struct regulator_dev *rdev = dev_to_rdev(dev); 442685f3b431STomeu Vizoso struct seq_file *s = data; 442785f3b431STomeu Vizoso 442885f3b431STomeu Vizoso if (!rdev->supply) 442985f3b431STomeu Vizoso regulator_summary_show_subtree(s, rdev, 0); 443085f3b431STomeu Vizoso 443185f3b431STomeu Vizoso return 0; 44327c225ec9SHeiko Stübner } 44337c225ec9SHeiko Stübner 44347c225ec9SHeiko Stübner static int regulator_summary_show(struct seq_file *s, void *data) 44357c225ec9SHeiko Stübner { 443623296099SHeiko Stübner seq_puts(s, " regulator use open bypass voltage current min max\n"); 443723296099SHeiko Stübner seq_puts(s, "-------------------------------------------------------------------------------\n"); 44387c225ec9SHeiko Stübner 443985f3b431STomeu Vizoso class_for_each_device(®ulator_class, NULL, s, 444085f3b431STomeu Vizoso regulator_summary_show_roots); 44417c225ec9SHeiko Stübner 44427c225ec9SHeiko Stübner return 0; 44437c225ec9SHeiko Stübner } 44447c225ec9SHeiko Stübner 44457c225ec9SHeiko Stübner static int regulator_summary_open(struct inode *inode, struct file *file) 44467c225ec9SHeiko Stübner { 44477c225ec9SHeiko Stübner return single_open(file, regulator_summary_show, inode->i_private); 44487c225ec9SHeiko Stübner } 44497c225ec9SHeiko Stübner #endif 44507c225ec9SHeiko Stübner 44517c225ec9SHeiko Stübner static const struct file_operations regulator_summary_fops = { 44527c225ec9SHeiko Stübner #ifdef CONFIG_DEBUG_FS 44537c225ec9SHeiko Stübner .open = regulator_summary_open, 44547c225ec9SHeiko Stübner .read = seq_read, 44557c225ec9SHeiko Stübner .llseek = seq_lseek, 44567c225ec9SHeiko Stübner .release = single_release, 44577c225ec9SHeiko Stübner #endif 44587c225ec9SHeiko Stübner }; 44597c225ec9SHeiko Stübner 4460414c70cbSLiam Girdwood static int __init regulator_init(void) 4461414c70cbSLiam Girdwood { 446234abbd68SMark Brown int ret; 446334abbd68SMark Brown 446434abbd68SMark Brown ret = class_register(®ulator_class); 446534abbd68SMark Brown 44661130e5b3SMark Brown debugfs_root = debugfs_create_dir("regulator", NULL); 446724751434SStephen Boyd if (!debugfs_root) 44681130e5b3SMark Brown pr_warn("regulator: Failed to create debugfs directory\n"); 4469ba55a974SMark Brown 4470f4d562c6SMark Brown debugfs_create_file("supply_map", 0444, debugfs_root, NULL, 4471f4d562c6SMark Brown &supply_map_fops); 44721130e5b3SMark Brown 44737c225ec9SHeiko Stübner debugfs_create_file("regulator_summary", 0444, debugfs_root, 447485f3b431STomeu Vizoso NULL, ®ulator_summary_fops); 44757c225ec9SHeiko Stübner 447634abbd68SMark Brown regulator_dummy_init(); 447734abbd68SMark Brown 447834abbd68SMark Brown return ret; 4479414c70cbSLiam Girdwood } 4480414c70cbSLiam Girdwood 4481414c70cbSLiam Girdwood /* init early to allow our consumers to complete system booting */ 4482414c70cbSLiam Girdwood core_initcall(regulator_init); 4483ca725561SMark Brown 4484609ca5f3SMark Brown static int __init regulator_late_cleanup(struct device *dev, void *data) 4485ca725561SMark Brown { 4486609ca5f3SMark Brown struct regulator_dev *rdev = dev_to_rdev(dev); 4487609ca5f3SMark Brown const struct regulator_ops *ops = rdev->desc->ops; 4488609ca5f3SMark Brown struct regulation_constraints *c = rdev->constraints; 4489ca725561SMark Brown int enabled, ret; 4490ca725561SMark Brown 449166fda75fSMarkus Pargmann if (c && c->always_on) 4492609ca5f3SMark Brown return 0; 4493ca725561SMark Brown 44948a34e979SWEN Pingbo if (!regulator_ops_is_valid(rdev, REGULATOR_CHANGE_STATUS)) 4495609ca5f3SMark Brown return 0; 4496e9535834SMark Brown 4497ca725561SMark Brown mutex_lock(&rdev->mutex); 4498ca725561SMark Brown 4499ca725561SMark Brown if (rdev->use_count) 4500ca725561SMark Brown goto unlock; 4501ca725561SMark Brown 4502ca725561SMark Brown /* If we can't read the status assume it's on. */ 4503ca725561SMark Brown if (ops->is_enabled) 4504ca725561SMark Brown enabled = ops->is_enabled(rdev); 4505ca725561SMark Brown else 4506ca725561SMark Brown enabled = 1; 4507ca725561SMark Brown 4508ca725561SMark Brown if (!enabled) 4509ca725561SMark Brown goto unlock; 4510ca725561SMark Brown 451187b28417SMark Brown if (have_full_constraints()) { 4512609ca5f3SMark Brown /* We log since this may kill the system if it goes 4513609ca5f3SMark Brown * wrong. */ 45145da84fd9SJoe Perches rdev_info(rdev, "disabling\n"); 451566fda75fSMarkus Pargmann ret = _regulator_do_disable(rdev); 45160d25d09dSJingoo Han if (ret != 0) 45175da84fd9SJoe Perches rdev_err(rdev, "couldn't disable: %d\n", ret); 4518ca725561SMark Brown } else { 4519ca725561SMark Brown /* The intention is that in future we will 4520ca725561SMark Brown * assume that full constraints are provided 4521ca725561SMark Brown * so warn even if we aren't going to do 4522ca725561SMark Brown * anything here. 4523ca725561SMark Brown */ 45245da84fd9SJoe Perches rdev_warn(rdev, "incomplete constraints, leaving on\n"); 4525ca725561SMark Brown } 4526ca725561SMark Brown 4527ca725561SMark Brown unlock: 4528ca725561SMark Brown mutex_unlock(&rdev->mutex); 4529609ca5f3SMark Brown 4530609ca5f3SMark Brown return 0; 4531ca725561SMark Brown } 4532ca725561SMark Brown 4533609ca5f3SMark Brown static int __init regulator_init_complete(void) 4534609ca5f3SMark Brown { 4535609ca5f3SMark Brown /* 4536609ca5f3SMark Brown * Since DT doesn't provide an idiomatic mechanism for 4537609ca5f3SMark Brown * enabling full constraints and since it's much more natural 4538609ca5f3SMark Brown * with DT to provide them just assume that a DT enabled 4539609ca5f3SMark Brown * system has full constraints. 4540609ca5f3SMark Brown */ 4541609ca5f3SMark Brown if (of_have_populated_dt()) 4542609ca5f3SMark Brown has_full_constraints = true; 4543609ca5f3SMark Brown 4544609ca5f3SMark Brown /* If we have a full configuration then disable any regulators 4545609ca5f3SMark Brown * we have permission to change the status for and which are 4546609ca5f3SMark Brown * not in use or always_on. This is effectively the default 4547609ca5f3SMark Brown * for DT and ACPI as they have full constraints. 4548609ca5f3SMark Brown */ 4549609ca5f3SMark Brown class_for_each_device(®ulator_class, NULL, NULL, 4550609ca5f3SMark Brown regulator_late_cleanup); 4551ca725561SMark Brown 4552ca725561SMark Brown return 0; 4553ca725561SMark Brown } 4554fd482a3eSSaravana Kannan late_initcall_sync(regulator_init_complete); 4555