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 */ 15835ffbd136SMark Brown static struct regulator *_regulator_get(struct device *dev, const char *id, 15844ddfebd3SMark Brown bool exclusive, bool allow_dummy) 1585414c70cbSLiam Girdwood { 1586414c70cbSLiam Girdwood struct regulator_dev *rdev; 158704bf3011SMark Brown struct regulator *regulator = ERR_PTR(-EPROBE_DEFER); 158840f9244fSMark Brown const char *devname = NULL; 1589317b5684SMark Brown int ret; 1590414c70cbSLiam Girdwood 1591414c70cbSLiam Girdwood if (id == NULL) { 15925da84fd9SJoe Perches pr_err("get() with no identifier\n"); 1593043c998fSMark Brown return ERR_PTR(-EINVAL); 1594414c70cbSLiam Girdwood } 1595414c70cbSLiam Girdwood 159640f9244fSMark Brown if (dev) 159740f9244fSMark Brown devname = dev_name(dev); 159840f9244fSMark Brown 1599317b5684SMark Brown if (have_full_constraints()) 1600317b5684SMark Brown ret = -ENODEV; 1601317b5684SMark Brown else 1602317b5684SMark Brown ret = -EPROBE_DEFER; 1603317b5684SMark 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 */ 162487b28417SMark Brown if (have_full_constraints() && allow_dummy) { 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() */ 16320781719bSHans de Goede } else if (!have_full_constraints() || exclusive) { 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 16455ffbd136SMark Brown if (exclusive && 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)) { 165985f3b431STomeu Vizoso put_device(&rdev->dev); 166085f3b431STomeu Vizoso return regulator; 166185f3b431STomeu Vizoso } 1662a5766f11SLiam Girdwood 1663414c70cbSLiam Girdwood regulator = create_regulator(rdev, dev, id); 1664414c70cbSLiam Girdwood if (regulator == NULL) { 1665414c70cbSLiam Girdwood regulator = ERR_PTR(-ENOMEM); 166685f3b431STomeu Vizoso put_device(&rdev->dev); 1667414c70cbSLiam Girdwood module_put(rdev->owner); 166885f3b431STomeu Vizoso return regulator; 1669414c70cbSLiam Girdwood } 1670414c70cbSLiam Girdwood 16715ffbd136SMark Brown rdev->open_count++; 16725ffbd136SMark Brown if (exclusive) { 16735ffbd136SMark Brown rdev->exclusive = 1; 16745ffbd136SMark Brown 16755ffbd136SMark Brown ret = _regulator_is_enabled(rdev); 16765ffbd136SMark Brown if (ret > 0) 16775ffbd136SMark Brown rdev->use_count = 1; 16785ffbd136SMark Brown else 16795ffbd136SMark Brown rdev->use_count = 0; 16805ffbd136SMark Brown } 16815ffbd136SMark Brown 1682414c70cbSLiam Girdwood return regulator; 1683414c70cbSLiam Girdwood } 16845ffbd136SMark Brown 16855ffbd136SMark Brown /** 16865ffbd136SMark Brown * regulator_get - lookup and obtain a reference to a regulator. 16875ffbd136SMark Brown * @dev: device for regulator "consumer" 16885ffbd136SMark Brown * @id: Supply name or regulator ID. 16895ffbd136SMark Brown * 16905ffbd136SMark Brown * Returns a struct regulator corresponding to the regulator producer, 16915ffbd136SMark Brown * or IS_ERR() condition containing errno. 16925ffbd136SMark Brown * 16935ffbd136SMark Brown * Use of supply names configured via regulator_set_device_supply() is 16945ffbd136SMark Brown * strongly encouraged. It is recommended that the supply name used 16955ffbd136SMark Brown * should match the name used for the supply and/or the relevant 16965ffbd136SMark Brown * device pins in the datasheet. 16975ffbd136SMark Brown */ 16985ffbd136SMark Brown struct regulator *regulator_get(struct device *dev, const char *id) 16995ffbd136SMark Brown { 17004ddfebd3SMark Brown return _regulator_get(dev, id, false, true); 17015ffbd136SMark Brown } 1702414c70cbSLiam Girdwood EXPORT_SYMBOL_GPL(regulator_get); 1703414c70cbSLiam Girdwood 1704070b9079SStephen Boyd /** 17055ffbd136SMark Brown * regulator_get_exclusive - obtain exclusive access to a regulator. 17065ffbd136SMark Brown * @dev: device for regulator "consumer" 17075ffbd136SMark Brown * @id: Supply name or regulator ID. 17085ffbd136SMark Brown * 17095ffbd136SMark Brown * Returns a struct regulator corresponding to the regulator producer, 17105ffbd136SMark Brown * or IS_ERR() condition containing errno. Other consumers will be 171169c3f723SStephen Boyd * unable to obtain this regulator while this reference is held and the 171269c3f723SStephen Boyd * use count for the regulator will be initialised to reflect the current 171369c3f723SStephen Boyd * state of the regulator. 17145ffbd136SMark Brown * 17155ffbd136SMark Brown * This is intended for use by consumers which cannot tolerate shared 17165ffbd136SMark Brown * use of the regulator such as those which need to force the 17175ffbd136SMark Brown * regulator off for correct operation of the hardware they are 17185ffbd136SMark Brown * controlling. 17195ffbd136SMark Brown * 17205ffbd136SMark Brown * Use of supply names configured via regulator_set_device_supply() is 17215ffbd136SMark Brown * strongly encouraged. It is recommended that the supply name used 17225ffbd136SMark Brown * should match the name used for the supply and/or the relevant 17235ffbd136SMark Brown * device pins in the datasheet. 17245ffbd136SMark Brown */ 17255ffbd136SMark Brown struct regulator *regulator_get_exclusive(struct device *dev, const char *id) 17265ffbd136SMark Brown { 17274ddfebd3SMark Brown return _regulator_get(dev, id, true, false); 17285ffbd136SMark Brown } 17295ffbd136SMark Brown EXPORT_SYMBOL_GPL(regulator_get_exclusive); 17305ffbd136SMark Brown 1731de1dd9fdSMark Brown /** 1732de1dd9fdSMark Brown * regulator_get_optional - obtain optional access to a regulator. 1733de1dd9fdSMark Brown * @dev: device for regulator "consumer" 1734de1dd9fdSMark Brown * @id: Supply name or regulator ID. 1735de1dd9fdSMark Brown * 1736de1dd9fdSMark Brown * Returns a struct regulator corresponding to the regulator producer, 173769c3f723SStephen Boyd * or IS_ERR() condition containing errno. 1738de1dd9fdSMark Brown * 1739de1dd9fdSMark Brown * This is intended for use by consumers for devices which can have 1740de1dd9fdSMark Brown * some supplies unconnected in normal use, such as some MMC devices. 1741de1dd9fdSMark Brown * It can allow the regulator core to provide stub supplies for other 1742de1dd9fdSMark Brown * supplies requested using normal regulator_get() calls without 1743de1dd9fdSMark Brown * disrupting the operation of drivers that can handle absent 1744de1dd9fdSMark Brown * supplies. 1745de1dd9fdSMark Brown * 1746de1dd9fdSMark Brown * Use of supply names configured via regulator_set_device_supply() is 1747de1dd9fdSMark Brown * strongly encouraged. It is recommended that the supply name used 1748de1dd9fdSMark Brown * should match the name used for the supply and/or the relevant 1749de1dd9fdSMark Brown * device pins in the datasheet. 1750de1dd9fdSMark Brown */ 1751de1dd9fdSMark Brown struct regulator *regulator_get_optional(struct device *dev, const char *id) 1752de1dd9fdSMark Brown { 17534ddfebd3SMark Brown return _regulator_get(dev, id, false, false); 1754de1dd9fdSMark Brown } 1755de1dd9fdSMark Brown EXPORT_SYMBOL_GPL(regulator_get_optional); 1756de1dd9fdSMark Brown 175783b0302dSAshay Jaiswal /* regulator_list_mutex lock held by regulator_put() */ 175823ff2f0fSCharles Keepax static void _regulator_put(struct regulator *regulator) 1759414c70cbSLiam Girdwood { 1760414c70cbSLiam Girdwood struct regulator_dev *rdev; 1761414c70cbSLiam Girdwood 176293576842SViresh Kumar if (IS_ERR_OR_NULL(regulator)) 1763414c70cbSLiam Girdwood return; 1764414c70cbSLiam Girdwood 176570cfef26SKrzysztof Kozlowski lockdep_assert_held_once(®ulator_list_mutex); 176670cfef26SKrzysztof Kozlowski 1767414c70cbSLiam Girdwood rdev = regulator->rdev; 1768414c70cbSLiam Girdwood 17695de70519SMark Brown debugfs_remove_recursive(regulator->debugfs); 17705de70519SMark Brown 1771414c70cbSLiam Girdwood /* remove any sysfs entries */ 1772e2c98eafSShawn Guo if (regulator->dev) 1773414c70cbSLiam Girdwood sysfs_remove_link(&rdev->dev.kobj, regulator->supply_name); 177483b0302dSAshay Jaiswal mutex_lock(&rdev->mutex); 1775414c70cbSLiam Girdwood list_del(®ulator->list); 1776414c70cbSLiam Girdwood 17775ffbd136SMark Brown rdev->open_count--; 17785ffbd136SMark Brown rdev->exclusive = 0; 177985f3b431STomeu Vizoso put_device(&rdev->dev); 178083b0302dSAshay Jaiswal mutex_unlock(&rdev->mutex); 17815ffbd136SMark Brown 17821768514eSMark Brown kfree(regulator->supply_name); 17831768514eSMark Brown kfree(regulator); 17841768514eSMark Brown 1785414c70cbSLiam Girdwood module_put(rdev->owner); 178623ff2f0fSCharles Keepax } 178723ff2f0fSCharles Keepax 178823ff2f0fSCharles Keepax /** 178923ff2f0fSCharles Keepax * regulator_put - "free" the regulator source 179023ff2f0fSCharles Keepax * @regulator: regulator source 179123ff2f0fSCharles Keepax * 179223ff2f0fSCharles Keepax * Note: drivers must ensure that all regulator_enable calls made on this 179323ff2f0fSCharles Keepax * regulator source are balanced by regulator_disable calls prior to calling 179423ff2f0fSCharles Keepax * this function. 179523ff2f0fSCharles Keepax */ 179623ff2f0fSCharles Keepax void regulator_put(struct regulator *regulator) 179723ff2f0fSCharles Keepax { 179823ff2f0fSCharles Keepax mutex_lock(®ulator_list_mutex); 179923ff2f0fSCharles Keepax _regulator_put(regulator); 1800414c70cbSLiam Girdwood mutex_unlock(®ulator_list_mutex); 1801414c70cbSLiam Girdwood } 1802414c70cbSLiam Girdwood EXPORT_SYMBOL_GPL(regulator_put); 1803414c70cbSLiam Girdwood 1804a06ccd9cSCharles Keepax /** 1805a06ccd9cSCharles Keepax * regulator_register_supply_alias - Provide device alias for supply lookup 1806a06ccd9cSCharles Keepax * 1807a06ccd9cSCharles Keepax * @dev: device that will be given as the regulator "consumer" 1808a06ccd9cSCharles Keepax * @id: Supply name or regulator ID 1809a06ccd9cSCharles Keepax * @alias_dev: device that should be used to lookup the supply 1810a06ccd9cSCharles Keepax * @alias_id: Supply name or regulator ID that should be used to lookup the 1811a06ccd9cSCharles Keepax * supply 1812a06ccd9cSCharles Keepax * 1813a06ccd9cSCharles Keepax * All lookups for id on dev will instead be conducted for alias_id on 1814a06ccd9cSCharles Keepax * alias_dev. 1815a06ccd9cSCharles Keepax */ 1816a06ccd9cSCharles Keepax int regulator_register_supply_alias(struct device *dev, const char *id, 1817a06ccd9cSCharles Keepax struct device *alias_dev, 1818a06ccd9cSCharles Keepax const char *alias_id) 1819a06ccd9cSCharles Keepax { 1820a06ccd9cSCharles Keepax struct regulator_supply_alias *map; 1821a06ccd9cSCharles Keepax 1822a06ccd9cSCharles Keepax map = regulator_find_supply_alias(dev, id); 1823a06ccd9cSCharles Keepax if (map) 1824a06ccd9cSCharles Keepax return -EEXIST; 1825a06ccd9cSCharles Keepax 1826a06ccd9cSCharles Keepax map = kzalloc(sizeof(struct regulator_supply_alias), GFP_KERNEL); 1827a06ccd9cSCharles Keepax if (!map) 1828a06ccd9cSCharles Keepax return -ENOMEM; 1829a06ccd9cSCharles Keepax 1830a06ccd9cSCharles Keepax map->src_dev = dev; 1831a06ccd9cSCharles Keepax map->src_supply = id; 1832a06ccd9cSCharles Keepax map->alias_dev = alias_dev; 1833a06ccd9cSCharles Keepax map->alias_supply = alias_id; 1834a06ccd9cSCharles Keepax 1835a06ccd9cSCharles Keepax list_add(&map->list, ®ulator_supply_alias_list); 1836a06ccd9cSCharles Keepax 1837a06ccd9cSCharles Keepax pr_info("Adding alias for supply %s,%s -> %s,%s\n", 1838a06ccd9cSCharles Keepax id, dev_name(dev), alias_id, dev_name(alias_dev)); 1839a06ccd9cSCharles Keepax 1840a06ccd9cSCharles Keepax return 0; 1841a06ccd9cSCharles Keepax } 1842a06ccd9cSCharles Keepax EXPORT_SYMBOL_GPL(regulator_register_supply_alias); 1843a06ccd9cSCharles Keepax 1844a06ccd9cSCharles Keepax /** 1845a06ccd9cSCharles Keepax * regulator_unregister_supply_alias - Remove device alias 1846a06ccd9cSCharles Keepax * 1847a06ccd9cSCharles Keepax * @dev: device that will be given as the regulator "consumer" 1848a06ccd9cSCharles Keepax * @id: Supply name or regulator ID 1849a06ccd9cSCharles Keepax * 1850a06ccd9cSCharles Keepax * Remove a lookup alias if one exists for id on dev. 1851a06ccd9cSCharles Keepax */ 1852a06ccd9cSCharles Keepax void regulator_unregister_supply_alias(struct device *dev, const char *id) 1853a06ccd9cSCharles Keepax { 1854a06ccd9cSCharles Keepax struct regulator_supply_alias *map; 1855a06ccd9cSCharles Keepax 1856a06ccd9cSCharles Keepax map = regulator_find_supply_alias(dev, id); 1857a06ccd9cSCharles Keepax if (map) { 1858a06ccd9cSCharles Keepax list_del(&map->list); 1859a06ccd9cSCharles Keepax kfree(map); 1860a06ccd9cSCharles Keepax } 1861a06ccd9cSCharles Keepax } 1862a06ccd9cSCharles Keepax EXPORT_SYMBOL_GPL(regulator_unregister_supply_alias); 1863a06ccd9cSCharles Keepax 1864a06ccd9cSCharles Keepax /** 1865a06ccd9cSCharles Keepax * regulator_bulk_register_supply_alias - register multiple aliases 1866a06ccd9cSCharles Keepax * 1867a06ccd9cSCharles Keepax * @dev: device that will be given as the regulator "consumer" 1868a06ccd9cSCharles Keepax * @id: List of supply names or regulator IDs 1869a06ccd9cSCharles Keepax * @alias_dev: device that should be used to lookup the supply 1870a06ccd9cSCharles Keepax * @alias_id: List of supply names or regulator IDs that should be used to 1871a06ccd9cSCharles Keepax * lookup the supply 1872a06ccd9cSCharles Keepax * @num_id: Number of aliases to register 1873a06ccd9cSCharles Keepax * 1874a06ccd9cSCharles Keepax * @return 0 on success, an errno on failure. 1875a06ccd9cSCharles Keepax * 1876a06ccd9cSCharles Keepax * This helper function allows drivers to register several supply 1877a06ccd9cSCharles Keepax * aliases in one operation. If any of the aliases cannot be 1878a06ccd9cSCharles Keepax * registered any aliases that were registered will be removed 1879a06ccd9cSCharles Keepax * before returning to the caller. 1880a06ccd9cSCharles Keepax */ 18819f8c0fe9SLee Jones int regulator_bulk_register_supply_alias(struct device *dev, 18829f8c0fe9SLee Jones const char *const *id, 1883a06ccd9cSCharles Keepax struct device *alias_dev, 18849f8c0fe9SLee Jones const char *const *alias_id, 1885a06ccd9cSCharles Keepax int num_id) 1886a06ccd9cSCharles Keepax { 1887a06ccd9cSCharles Keepax int i; 1888a06ccd9cSCharles Keepax int ret; 1889a06ccd9cSCharles Keepax 1890a06ccd9cSCharles Keepax for (i = 0; i < num_id; ++i) { 1891a06ccd9cSCharles Keepax ret = regulator_register_supply_alias(dev, id[i], alias_dev, 1892a06ccd9cSCharles Keepax alias_id[i]); 1893a06ccd9cSCharles Keepax if (ret < 0) 1894a06ccd9cSCharles Keepax goto err; 1895a06ccd9cSCharles Keepax } 1896a06ccd9cSCharles Keepax 1897a06ccd9cSCharles Keepax return 0; 1898a06ccd9cSCharles Keepax 1899a06ccd9cSCharles Keepax err: 1900a06ccd9cSCharles Keepax dev_err(dev, 1901a06ccd9cSCharles Keepax "Failed to create supply alias %s,%s -> %s,%s\n", 1902a06ccd9cSCharles Keepax id[i], dev_name(dev), alias_id[i], dev_name(alias_dev)); 1903a06ccd9cSCharles Keepax 1904a06ccd9cSCharles Keepax while (--i >= 0) 1905a06ccd9cSCharles Keepax regulator_unregister_supply_alias(dev, id[i]); 1906a06ccd9cSCharles Keepax 1907a06ccd9cSCharles Keepax return ret; 1908a06ccd9cSCharles Keepax } 1909a06ccd9cSCharles Keepax EXPORT_SYMBOL_GPL(regulator_bulk_register_supply_alias); 1910a06ccd9cSCharles Keepax 1911a06ccd9cSCharles Keepax /** 1912a06ccd9cSCharles Keepax * regulator_bulk_unregister_supply_alias - unregister multiple aliases 1913a06ccd9cSCharles Keepax * 1914a06ccd9cSCharles Keepax * @dev: device that will be given as the regulator "consumer" 1915a06ccd9cSCharles Keepax * @id: List of supply names or regulator IDs 1916a06ccd9cSCharles Keepax * @num_id: Number of aliases to unregister 1917a06ccd9cSCharles Keepax * 1918a06ccd9cSCharles Keepax * This helper function allows drivers to unregister several supply 1919a06ccd9cSCharles Keepax * aliases in one operation. 1920a06ccd9cSCharles Keepax */ 1921a06ccd9cSCharles Keepax void regulator_bulk_unregister_supply_alias(struct device *dev, 19229f8c0fe9SLee Jones const char *const *id, 1923a06ccd9cSCharles Keepax int num_id) 1924a06ccd9cSCharles Keepax { 1925a06ccd9cSCharles Keepax int i; 1926a06ccd9cSCharles Keepax 1927a06ccd9cSCharles Keepax for (i = 0; i < num_id; ++i) 1928a06ccd9cSCharles Keepax regulator_unregister_supply_alias(dev, id[i]); 1929a06ccd9cSCharles Keepax } 1930a06ccd9cSCharles Keepax EXPORT_SYMBOL_GPL(regulator_bulk_unregister_supply_alias); 1931a06ccd9cSCharles Keepax 1932a06ccd9cSCharles Keepax 1933f19b00daSKim, Milo /* Manage enable GPIO list. Same GPIO pin can be shared among regulators */ 1934f19b00daSKim, Milo static int regulator_ena_gpio_request(struct regulator_dev *rdev, 1935f19b00daSKim, Milo const struct regulator_config *config) 1936f19b00daSKim, Milo { 1937f19b00daSKim, Milo struct regulator_enable_gpio *pin; 1938778b28b4SRussell King struct gpio_desc *gpiod; 1939f19b00daSKim, Milo int ret; 1940f19b00daSKim, Milo 1941778b28b4SRussell King gpiod = gpio_to_desc(config->ena_gpio); 1942778b28b4SRussell King 1943f19b00daSKim, Milo list_for_each_entry(pin, ®ulator_ena_gpio_list, list) { 1944778b28b4SRussell King if (pin->gpiod == gpiod) { 1945f19b00daSKim, Milo rdev_dbg(rdev, "GPIO %d is already used\n", 1946f19b00daSKim, Milo config->ena_gpio); 1947f19b00daSKim, Milo goto update_ena_gpio_to_rdev; 1948f19b00daSKim, Milo } 1949f19b00daSKim, Milo } 1950f19b00daSKim, Milo 1951f19b00daSKim, Milo ret = gpio_request_one(config->ena_gpio, 1952f19b00daSKim, Milo GPIOF_DIR_OUT | config->ena_gpio_flags, 1953f19b00daSKim, Milo rdev_get_name(rdev)); 1954f19b00daSKim, Milo if (ret) 1955f19b00daSKim, Milo return ret; 1956f19b00daSKim, Milo 1957f19b00daSKim, Milo pin = kzalloc(sizeof(struct regulator_enable_gpio), GFP_KERNEL); 1958f19b00daSKim, Milo if (pin == NULL) { 1959f19b00daSKim, Milo gpio_free(config->ena_gpio); 1960f19b00daSKim, Milo return -ENOMEM; 1961f19b00daSKim, Milo } 1962f19b00daSKim, Milo 1963778b28b4SRussell King pin->gpiod = gpiod; 1964f19b00daSKim, Milo pin->ena_gpio_invert = config->ena_gpio_invert; 1965f19b00daSKim, Milo list_add(&pin->list, ®ulator_ena_gpio_list); 1966f19b00daSKim, Milo 1967f19b00daSKim, Milo update_ena_gpio_to_rdev: 1968f19b00daSKim, Milo pin->request_count++; 1969f19b00daSKim, Milo rdev->ena_pin = pin; 1970f19b00daSKim, Milo return 0; 1971f19b00daSKim, Milo } 1972f19b00daSKim, Milo 1973f19b00daSKim, Milo static void regulator_ena_gpio_free(struct regulator_dev *rdev) 1974f19b00daSKim, Milo { 1975f19b00daSKim, Milo struct regulator_enable_gpio *pin, *n; 1976f19b00daSKim, Milo 1977f19b00daSKim, Milo if (!rdev->ena_pin) 1978f19b00daSKim, Milo return; 1979f19b00daSKim, Milo 1980f19b00daSKim, Milo /* Free the GPIO only in case of no use */ 1981f19b00daSKim, Milo list_for_each_entry_safe(pin, n, ®ulator_ena_gpio_list, list) { 1982778b28b4SRussell King if (pin->gpiod == rdev->ena_pin->gpiod) { 1983f19b00daSKim, Milo if (pin->request_count <= 1) { 1984f19b00daSKim, Milo pin->request_count = 0; 1985778b28b4SRussell King gpiod_put(pin->gpiod); 1986f19b00daSKim, Milo list_del(&pin->list); 1987f19b00daSKim, Milo kfree(pin); 198860a2362fSSeung-Woo Kim rdev->ena_pin = NULL; 198960a2362fSSeung-Woo Kim return; 1990f19b00daSKim, Milo } else { 1991f19b00daSKim, Milo pin->request_count--; 1992f19b00daSKim, Milo } 1993f19b00daSKim, Milo } 1994f19b00daSKim, Milo } 1995f19b00daSKim, Milo } 1996f19b00daSKim, Milo 1997967cfb18SKim, Milo /** 199831d6eebfSRobert P. J. Day * regulator_ena_gpio_ctrl - balance enable_count of each GPIO and actual GPIO pin control 199931d6eebfSRobert P. J. Day * @rdev: regulator_dev structure 200031d6eebfSRobert P. J. Day * @enable: enable GPIO at initial use? 200131d6eebfSRobert P. J. Day * 2002967cfb18SKim, Milo * GPIO is enabled in case of initial use. (enable_count is 0) 2003967cfb18SKim, Milo * GPIO is disabled when it is not shared any more. (enable_count <= 1) 2004967cfb18SKim, Milo */ 2005967cfb18SKim, Milo static int regulator_ena_gpio_ctrl(struct regulator_dev *rdev, bool enable) 2006967cfb18SKim, Milo { 2007967cfb18SKim, Milo struct regulator_enable_gpio *pin = rdev->ena_pin; 2008967cfb18SKim, Milo 2009967cfb18SKim, Milo if (!pin) 2010967cfb18SKim, Milo return -EINVAL; 2011967cfb18SKim, Milo 2012967cfb18SKim, Milo if (enable) { 2013967cfb18SKim, Milo /* Enable GPIO at initial use */ 2014967cfb18SKim, Milo if (pin->enable_count == 0) 2015778b28b4SRussell King gpiod_set_value_cansleep(pin->gpiod, 2016967cfb18SKim, Milo !pin->ena_gpio_invert); 2017967cfb18SKim, Milo 2018967cfb18SKim, Milo pin->enable_count++; 2019967cfb18SKim, Milo } else { 2020967cfb18SKim, Milo if (pin->enable_count > 1) { 2021967cfb18SKim, Milo pin->enable_count--; 2022967cfb18SKim, Milo return 0; 2023967cfb18SKim, Milo } 2024967cfb18SKim, Milo 2025967cfb18SKim, Milo /* Disable GPIO if not used */ 2026967cfb18SKim, Milo if (pin->enable_count <= 1) { 2027778b28b4SRussell King gpiod_set_value_cansleep(pin->gpiod, 2028967cfb18SKim, Milo pin->ena_gpio_invert); 2029967cfb18SKim, Milo pin->enable_count = 0; 2030967cfb18SKim, Milo } 2031967cfb18SKim, Milo } 2032967cfb18SKim, Milo 2033967cfb18SKim, Milo return 0; 2034967cfb18SKim, Milo } 2035967cfb18SKim, Milo 203679fd1141SGuodong Xu /** 203779fd1141SGuodong Xu * _regulator_enable_delay - a delay helper function 203879fd1141SGuodong Xu * @delay: time to delay in microseconds 203979fd1141SGuodong Xu * 20405df529d4SThierry Reding * Delay for the requested amount of time as per the guidelines in: 20415df529d4SThierry Reding * 20425df529d4SThierry Reding * Documentation/timers/timers-howto.txt 20435df529d4SThierry Reding * 20445df529d4SThierry Reding * The assumption here is that regulators will never be enabled in 20455df529d4SThierry Reding * atomic context and therefore sleeping functions can be used. 20465df529d4SThierry Reding */ 204779fd1141SGuodong Xu static void _regulator_enable_delay(unsigned int delay) 204879fd1141SGuodong Xu { 20495df529d4SThierry Reding unsigned int ms = delay / 1000; 20505df529d4SThierry Reding unsigned int us = delay % 1000; 20515df529d4SThierry Reding 20525df529d4SThierry Reding if (ms > 0) { 20535df529d4SThierry Reding /* 20545df529d4SThierry Reding * For small enough values, handle super-millisecond 20555df529d4SThierry Reding * delays in the usleep_range() call below. 20565df529d4SThierry Reding */ 20575df529d4SThierry Reding if (ms < 20) 20585df529d4SThierry Reding us += ms * 1000; 20595df529d4SThierry Reding else 20605df529d4SThierry Reding msleep(ms); 20615df529d4SThierry Reding } 20625df529d4SThierry Reding 20635df529d4SThierry Reding /* 20645df529d4SThierry Reding * Give the scheduler some room to coalesce with any other 20655df529d4SThierry Reding * wakeup sources. For delays shorter than 10 us, don't even 20665df529d4SThierry Reding * bother setting up high-resolution timers and just busy- 20675df529d4SThierry Reding * loop. 20685df529d4SThierry Reding */ 20695df529d4SThierry Reding if (us >= 10) 20705df529d4SThierry Reding usleep_range(us, us + 100); 20715df529d4SThierry Reding else 20725df529d4SThierry Reding udelay(us); 20735c5659d0SMark Brown } 20745c5659d0SMark Brown 20755c5659d0SMark Brown static int _regulator_do_enable(struct regulator_dev *rdev) 20765c5659d0SMark Brown { 20775c5659d0SMark Brown int ret, delay; 20785c5659d0SMark Brown 20795c5659d0SMark Brown /* Query before enabling in case configuration dependent. */ 20805c5659d0SMark Brown ret = _regulator_get_enable_time(rdev); 20815c5659d0SMark Brown if (ret >= 0) { 20825c5659d0SMark Brown delay = ret; 20835c5659d0SMark Brown } else { 2084414c70cbSLiam Girdwood rdev_warn(rdev, "enable_time() failed: %d\n", ret); 2085414c70cbSLiam Girdwood delay = 0; 2086414c70cbSLiam Girdwood } 20875c5659d0SMark Brown 2088414c70cbSLiam Girdwood trace_regulator_enable(rdev_get_name(rdev)); 2089414c70cbSLiam Girdwood 2090871f5650SGuodong Xu if (rdev->desc->off_on_delay) { 2091871f5650SGuodong Xu /* if needed, keep a distance of off_on_delay from last time 2092871f5650SGuodong Xu * this regulator was disabled. 2093871f5650SGuodong Xu */ 2094871f5650SGuodong Xu unsigned long start_jiffy = jiffies; 2095871f5650SGuodong Xu unsigned long intended, max_delay, remaining; 2096871f5650SGuodong Xu 2097871f5650SGuodong Xu max_delay = usecs_to_jiffies(rdev->desc->off_on_delay); 2098871f5650SGuodong Xu intended = rdev->last_off_jiffy + max_delay; 2099871f5650SGuodong Xu 2100871f5650SGuodong Xu if (time_before(start_jiffy, intended)) { 2101871f5650SGuodong Xu /* calc remaining jiffies to deal with one-time 2102871f5650SGuodong Xu * timer wrapping. 2103871f5650SGuodong Xu * in case of multiple timer wrapping, either it can be 2104871f5650SGuodong Xu * detected by out-of-range remaining, or it cannot be 2105871f5650SGuodong Xu * detected and we gets a panelty of 2106871f5650SGuodong Xu * _regulator_enable_delay(). 2107871f5650SGuodong Xu */ 2108871f5650SGuodong Xu remaining = intended - start_jiffy; 2109871f5650SGuodong Xu if (remaining <= max_delay) 2110871f5650SGuodong Xu _regulator_enable_delay( 2111871f5650SGuodong Xu jiffies_to_usecs(remaining)); 2112871f5650SGuodong Xu } 2113871f5650SGuodong Xu } 2114871f5650SGuodong Xu 2115414c70cbSLiam Girdwood if (rdev->ena_pin) { 211629d62ec5SDoug Anderson if (!rdev->ena_gpio_state) { 21179a2372faSMark Brown ret = regulator_ena_gpio_ctrl(rdev, true); 2118414c70cbSLiam Girdwood if (ret < 0) 2119414c70cbSLiam Girdwood return ret; 21209a2372faSMark Brown rdev->ena_gpio_state = 1; 212129d62ec5SDoug Anderson } 21229a2372faSMark Brown } else if (rdev->desc->ops->enable) { 21239a2372faSMark Brown ret = rdev->desc->ops->enable(rdev); 21249a2372faSMark Brown if (ret < 0) 21259a2372faSMark Brown return ret; 21269a2372faSMark Brown } else { 21279a2372faSMark Brown return -EINVAL; 21285c5659d0SMark Brown } 21299a2372faSMark Brown 21309a2372faSMark Brown /* Allow the regulator to ramp; it would be useful to extend 213131aae2beSMark Brown * this for bulk operations so that the regulators can ramp 2132a7433cffSLinus Walleij * together. */ 21335da84fd9SJoe Perches trace_regulator_enable_delay(rdev_get_name(rdev)); 2134414c70cbSLiam Girdwood 213579fd1141SGuodong Xu _regulator_enable_delay(delay); 2136a7433cffSLinus Walleij 2137414c70cbSLiam Girdwood trace_regulator_enable_complete(rdev_get_name(rdev)); 2138414c70cbSLiam Girdwood 21399a2372faSMark Brown return 0; 21409a2372faSMark Brown } 21419a2372faSMark Brown 2142414c70cbSLiam Girdwood /* locks held by regulator_enable() */ 2143414c70cbSLiam Girdwood static int _regulator_enable(struct regulator_dev *rdev) 2144414c70cbSLiam Girdwood { 2145414c70cbSLiam Girdwood int ret; 2146414c70cbSLiam Girdwood 214770cfef26SKrzysztof Kozlowski lockdep_assert_held_once(&rdev->mutex); 214870cfef26SKrzysztof Kozlowski 2149414c70cbSLiam Girdwood /* check voltage and requested load before enabling */ 21508a34e979SWEN Pingbo if (regulator_ops_is_valid(rdev, REGULATOR_CHANGE_DRMS)) 2151cf7bbcdfSMark Brown drms_uA_update(rdev); 2152cf7bbcdfSMark Brown 2153414c70cbSLiam Girdwood if (rdev->use_count == 0) { 2154cf7bbcdfSMark Brown /* The regulator may on if it's not switchable or left on */ 2155414c70cbSLiam Girdwood ret = _regulator_is_enabled(rdev); 2156414c70cbSLiam Girdwood if (ret == -EINVAL || ret == 0) { 21578a34e979SWEN Pingbo if (!regulator_ops_is_valid(rdev, 21588a34e979SWEN Pingbo REGULATOR_CHANGE_STATUS)) 2159412aec61SDavid Brownell return -EPERM; 2160412aec61SDavid Brownell 2161414c70cbSLiam Girdwood ret = _regulator_do_enable(rdev); 2162412aec61SDavid Brownell if (ret < 0) 2163412aec61SDavid Brownell return ret; 2164412aec61SDavid Brownell 2165414c70cbSLiam Girdwood } else if (ret < 0) { 2166414c70cbSLiam Girdwood rdev_err(rdev, "is_enabled() failed: %d\n", ret); 2167414c70cbSLiam Girdwood return ret; 2168414c70cbSLiam Girdwood } 2169414c70cbSLiam Girdwood /* Fallthrough on positive return values - already enabled */ 2170414c70cbSLiam Girdwood } 2171414c70cbSLiam Girdwood 2172414c70cbSLiam Girdwood rdev->use_count++; 2173414c70cbSLiam Girdwood 2174cd94b505SDavid Brownell return 0; 2175cd94b505SDavid Brownell } 21761083c393SMark Brown 2177cd94b505SDavid Brownell /** 2178cd94b505SDavid Brownell * regulator_enable - enable regulator output 2179414c70cbSLiam Girdwood * @regulator: regulator source 218060ef66fcSMark Brown * 218160ef66fcSMark Brown * Request that the regulator be enabled with the regulator output at 2182414c70cbSLiam Girdwood * the predefined voltage or current value. Calls to regulator_enable() 2183414c70cbSLiam Girdwood * must be balanced with calls to regulator_disable(). 21849a2372faSMark Brown * 21859a2372faSMark Brown * NOTE: the output value can be set by other drivers, boot loader or may be 2186414c70cbSLiam Girdwood * hardwired in the regulator. 2187414c70cbSLiam Girdwood */ 2188414c70cbSLiam Girdwood int regulator_enable(struct regulator *regulator) 21891083c393SMark Brown { 2190414c70cbSLiam Girdwood struct regulator_dev *rdev = regulator->rdev; 2191414c70cbSLiam Girdwood int ret = 0; 219284b68263SMark Brown 21936492bc1bSMark Brown if (regulator->always_on) 21946492bc1bSMark Brown return 0; 21956492bc1bSMark Brown 21963801b86aSMark Brown if (rdev->supply) { 21973801b86aSMark Brown ret = regulator_enable(rdev->supply); 21983801b86aSMark Brown if (ret != 0) 21993801b86aSMark Brown return ret; 22003801b86aSMark Brown } 22013801b86aSMark Brown 2202414c70cbSLiam Girdwood mutex_lock(&rdev->mutex); 2203414c70cbSLiam Girdwood ret = _regulator_enable(rdev); 2204414c70cbSLiam Girdwood mutex_unlock(&rdev->mutex); 22053801b86aSMark Brown 2206d1685e4eSHeiko Stübner if (ret != 0 && rdev->supply) 22073801b86aSMark Brown regulator_disable(rdev->supply); 22083801b86aSMark Brown 2209414c70cbSLiam Girdwood return ret; 2210414c70cbSLiam Girdwood } 2211414c70cbSLiam Girdwood EXPORT_SYMBOL_GPL(regulator_enable); 2212414c70cbSLiam Girdwood 22135c5659d0SMark Brown static int _regulator_do_disable(struct regulator_dev *rdev) 22145c5659d0SMark Brown { 22155c5659d0SMark Brown int ret; 22165c5659d0SMark Brown 22175c5659d0SMark Brown trace_regulator_disable(rdev_get_name(rdev)); 22185c5659d0SMark Brown 2219967cfb18SKim, Milo if (rdev->ena_pin) { 222029d62ec5SDoug Anderson if (rdev->ena_gpio_state) { 2221967cfb18SKim, Milo ret = regulator_ena_gpio_ctrl(rdev, false); 2222967cfb18SKim, Milo if (ret < 0) 2223967cfb18SKim, Milo return ret; 22245c5659d0SMark Brown rdev->ena_gpio_state = 0; 222529d62ec5SDoug Anderson } 22265c5659d0SMark Brown 22275c5659d0SMark Brown } else if (rdev->desc->ops->disable) { 22285c5659d0SMark Brown ret = rdev->desc->ops->disable(rdev); 22295c5659d0SMark Brown if (ret != 0) 22305c5659d0SMark Brown return ret; 22315c5659d0SMark Brown } 22325c5659d0SMark Brown 2233871f5650SGuodong Xu /* cares about last_off_jiffy only if off_on_delay is required by 2234871f5650SGuodong Xu * device. 2235871f5650SGuodong Xu */ 2236871f5650SGuodong Xu if (rdev->desc->off_on_delay) 2237871f5650SGuodong Xu rdev->last_off_jiffy = jiffies; 2238871f5650SGuodong Xu 22395c5659d0SMark Brown trace_regulator_disable_complete(rdev_get_name(rdev)); 22405c5659d0SMark Brown 22415c5659d0SMark Brown return 0; 22425c5659d0SMark Brown } 22435c5659d0SMark Brown 2244414c70cbSLiam Girdwood /* locks held by regulator_disable() */ 22453801b86aSMark Brown static int _regulator_disable(struct regulator_dev *rdev) 2246414c70cbSLiam Girdwood { 2247414c70cbSLiam Girdwood int ret = 0; 2248414c70cbSLiam Girdwood 224970cfef26SKrzysztof Kozlowski lockdep_assert_held_once(&rdev->mutex); 225070cfef26SKrzysztof Kozlowski 2251414c70cbSLiam Girdwood if (WARN(rdev->use_count <= 0, 225243e7ee33SJoe Perches "unbalanced disables for %s\n", rdev_get_name(rdev))) 2253414c70cbSLiam Girdwood return -EIO; 2254414c70cbSLiam Girdwood 2255414c70cbSLiam Girdwood /* are we the last user and permitted to disable ? */ 2256414c70cbSLiam Girdwood if (rdev->use_count == 1 && 2257414c70cbSLiam Girdwood (rdev->constraints && !rdev->constraints->always_on)) { 2258414c70cbSLiam Girdwood 2259414c70cbSLiam Girdwood /* we are last user */ 22608a34e979SWEN Pingbo if (regulator_ops_is_valid(rdev, REGULATOR_CHANGE_STATUS)) { 2261a1c8a551SRichard Fitzgerald ret = _notifier_call_chain(rdev, 2262a1c8a551SRichard Fitzgerald REGULATOR_EVENT_PRE_DISABLE, 2263a1c8a551SRichard Fitzgerald NULL); 2264a1c8a551SRichard Fitzgerald if (ret & NOTIFY_STOP_MASK) 2265a1c8a551SRichard Fitzgerald return -EINVAL; 2266a1c8a551SRichard Fitzgerald 22675c5659d0SMark Brown ret = _regulator_do_disable(rdev); 2268414c70cbSLiam Girdwood if (ret < 0) { 22695da84fd9SJoe Perches rdev_err(rdev, "failed to disable\n"); 2270a1c8a551SRichard Fitzgerald _notifier_call_chain(rdev, 2271a1c8a551SRichard Fitzgerald REGULATOR_EVENT_ABORT_DISABLE, 2272a1c8a551SRichard Fitzgerald NULL); 2273414c70cbSLiam Girdwood return ret; 2274414c70cbSLiam Girdwood } 227566fda75fSMarkus Pargmann _notifier_call_chain(rdev, REGULATOR_EVENT_DISABLE, 227666fda75fSMarkus Pargmann NULL); 2277414c70cbSLiam Girdwood } 2278414c70cbSLiam Girdwood 2279414c70cbSLiam Girdwood rdev->use_count = 0; 2280414c70cbSLiam Girdwood } else if (rdev->use_count > 1) { 22818a34e979SWEN Pingbo if (regulator_ops_is_valid(rdev, REGULATOR_CHANGE_DRMS)) 2282414c70cbSLiam Girdwood drms_uA_update(rdev); 2283414c70cbSLiam Girdwood 2284414c70cbSLiam Girdwood rdev->use_count--; 2285414c70cbSLiam Girdwood } 22863801b86aSMark Brown 2287414c70cbSLiam Girdwood return ret; 2288414c70cbSLiam Girdwood } 2289414c70cbSLiam Girdwood 2290414c70cbSLiam Girdwood /** 2291414c70cbSLiam Girdwood * regulator_disable - disable regulator output 2292414c70cbSLiam Girdwood * @regulator: regulator source 2293414c70cbSLiam Girdwood * 2294cf7bbcdfSMark Brown * Disable the regulator output voltage or current. Calls to 2295cf7bbcdfSMark Brown * regulator_enable() must be balanced with calls to 2296cf7bbcdfSMark Brown * regulator_disable(). 229769279fb9SMark Brown * 2298414c70cbSLiam Girdwood * NOTE: this will only disable the regulator output if no other consumer 2299cf7bbcdfSMark Brown * devices have it enabled, the regulator device supports disabling and 2300cf7bbcdfSMark Brown * machine constraints permit this operation. 2301414c70cbSLiam Girdwood */ 2302414c70cbSLiam Girdwood int regulator_disable(struct regulator *regulator) 2303414c70cbSLiam Girdwood { 2304412aec61SDavid Brownell struct regulator_dev *rdev = regulator->rdev; 2305412aec61SDavid Brownell int ret = 0; 2306414c70cbSLiam Girdwood 23076492bc1bSMark Brown if (regulator->always_on) 23086492bc1bSMark Brown return 0; 23096492bc1bSMark Brown 2310412aec61SDavid Brownell mutex_lock(&rdev->mutex); 23113801b86aSMark Brown ret = _regulator_disable(rdev); 2312412aec61SDavid Brownell mutex_unlock(&rdev->mutex); 23138cbf811dSJeffrey Carlyle 23143801b86aSMark Brown if (ret == 0 && rdev->supply) 23153801b86aSMark Brown regulator_disable(rdev->supply); 23168cbf811dSJeffrey Carlyle 2317414c70cbSLiam Girdwood return ret; 2318414c70cbSLiam Girdwood } 2319414c70cbSLiam Girdwood EXPORT_SYMBOL_GPL(regulator_disable); 2320414c70cbSLiam Girdwood 2321414c70cbSLiam Girdwood /* locks held by regulator_force_disable() */ 23223801b86aSMark Brown static int _regulator_force_disable(struct regulator_dev *rdev) 2323414c70cbSLiam Girdwood { 2324414c70cbSLiam Girdwood int ret = 0; 2325414c70cbSLiam Girdwood 232670cfef26SKrzysztof Kozlowski lockdep_assert_held_once(&rdev->mutex); 232770cfef26SKrzysztof Kozlowski 2328a1c8a551SRichard Fitzgerald ret = _notifier_call_chain(rdev, REGULATOR_EVENT_FORCE_DISABLE | 2329a1c8a551SRichard Fitzgerald REGULATOR_EVENT_PRE_DISABLE, NULL); 2330a1c8a551SRichard Fitzgerald if (ret & NOTIFY_STOP_MASK) 2331a1c8a551SRichard Fitzgerald return -EINVAL; 2332a1c8a551SRichard Fitzgerald 233366fda75fSMarkus Pargmann ret = _regulator_do_disable(rdev); 2334414c70cbSLiam Girdwood if (ret < 0) { 23355da84fd9SJoe Perches rdev_err(rdev, "failed to force disable\n"); 2336a1c8a551SRichard Fitzgerald _notifier_call_chain(rdev, REGULATOR_EVENT_FORCE_DISABLE | 2337a1c8a551SRichard Fitzgerald REGULATOR_EVENT_ABORT_DISABLE, NULL); 2338414c70cbSLiam Girdwood return ret; 2339414c70cbSLiam Girdwood } 234066fda75fSMarkus Pargmann 234184b68263SMark Brown _notifier_call_chain(rdev, REGULATOR_EVENT_FORCE_DISABLE | 234284b68263SMark Brown REGULATOR_EVENT_DISABLE, NULL); 2343414c70cbSLiam Girdwood 234466fda75fSMarkus Pargmann return 0; 2345414c70cbSLiam Girdwood } 2346414c70cbSLiam Girdwood 2347414c70cbSLiam Girdwood /** 2348414c70cbSLiam Girdwood * regulator_force_disable - force disable regulator output 2349414c70cbSLiam Girdwood * @regulator: regulator source 2350414c70cbSLiam Girdwood * 2351414c70cbSLiam Girdwood * Forcibly disable the regulator output voltage or current. 2352414c70cbSLiam Girdwood * NOTE: this *will* disable the regulator output even if other consumer 2353414c70cbSLiam Girdwood * devices have it enabled. This should be used for situations when device 2354414c70cbSLiam Girdwood * damage will likely occur if the regulator is not disabled (e.g. over temp). 2355414c70cbSLiam Girdwood */ 2356414c70cbSLiam Girdwood int regulator_force_disable(struct regulator *regulator) 2357414c70cbSLiam Girdwood { 235882d15839SMark Brown struct regulator_dev *rdev = regulator->rdev; 2359414c70cbSLiam Girdwood int ret; 2360414c70cbSLiam Girdwood 236182d15839SMark Brown mutex_lock(&rdev->mutex); 2362414c70cbSLiam Girdwood regulator->uA_load = 0; 23633801b86aSMark Brown ret = _regulator_force_disable(regulator->rdev); 236482d15839SMark Brown mutex_unlock(&rdev->mutex); 23658cbf811dSJeffrey Carlyle 23663801b86aSMark Brown if (rdev->supply) 23673801b86aSMark Brown while (rdev->open_count--) 23683801b86aSMark Brown regulator_disable(rdev->supply); 23698cbf811dSJeffrey Carlyle 2370414c70cbSLiam Girdwood return ret; 2371414c70cbSLiam Girdwood } 2372414c70cbSLiam Girdwood EXPORT_SYMBOL_GPL(regulator_force_disable); 2373414c70cbSLiam Girdwood 2374da07ecd9SMark Brown static void regulator_disable_work(struct work_struct *work) 2375da07ecd9SMark Brown { 2376da07ecd9SMark Brown struct regulator_dev *rdev = container_of(work, struct regulator_dev, 2377da07ecd9SMark Brown disable_work.work); 2378da07ecd9SMark Brown int count, i, ret; 2379da07ecd9SMark Brown 2380da07ecd9SMark Brown mutex_lock(&rdev->mutex); 2381da07ecd9SMark Brown 2382da07ecd9SMark Brown BUG_ON(!rdev->deferred_disables); 2383da07ecd9SMark Brown 2384da07ecd9SMark Brown count = rdev->deferred_disables; 2385da07ecd9SMark Brown rdev->deferred_disables = 0; 2386da07ecd9SMark Brown 2387da07ecd9SMark Brown for (i = 0; i < count; i++) { 2388da07ecd9SMark Brown ret = _regulator_disable(rdev); 2389da07ecd9SMark Brown if (ret != 0) 2390da07ecd9SMark Brown rdev_err(rdev, "Deferred disable failed: %d\n", ret); 2391da07ecd9SMark Brown } 2392da07ecd9SMark Brown 2393da07ecd9SMark Brown mutex_unlock(&rdev->mutex); 2394da07ecd9SMark Brown 2395da07ecd9SMark Brown if (rdev->supply) { 2396da07ecd9SMark Brown for (i = 0; i < count; i++) { 2397da07ecd9SMark Brown ret = regulator_disable(rdev->supply); 2398da07ecd9SMark Brown if (ret != 0) { 2399da07ecd9SMark Brown rdev_err(rdev, 2400da07ecd9SMark Brown "Supply disable failed: %d\n", ret); 2401da07ecd9SMark Brown } 2402da07ecd9SMark Brown } 2403da07ecd9SMark Brown } 2404da07ecd9SMark Brown } 2405da07ecd9SMark Brown 2406da07ecd9SMark Brown /** 2407da07ecd9SMark Brown * regulator_disable_deferred - disable regulator output with delay 2408da07ecd9SMark Brown * @regulator: regulator source 2409da07ecd9SMark Brown * @ms: miliseconds until the regulator is disabled 2410da07ecd9SMark Brown * 2411da07ecd9SMark Brown * Execute regulator_disable() on the regulator after a delay. This 2412da07ecd9SMark Brown * is intended for use with devices that require some time to quiesce. 2413da07ecd9SMark Brown * 2414da07ecd9SMark Brown * NOTE: this will only disable the regulator output if no other consumer 2415da07ecd9SMark Brown * devices have it enabled, the regulator device supports disabling and 2416da07ecd9SMark Brown * machine constraints permit this operation. 2417da07ecd9SMark Brown */ 2418da07ecd9SMark Brown int regulator_disable_deferred(struct regulator *regulator, int ms) 2419da07ecd9SMark Brown { 2420da07ecd9SMark Brown struct regulator_dev *rdev = regulator->rdev; 2421da07ecd9SMark Brown 24226492bc1bSMark Brown if (regulator->always_on) 24236492bc1bSMark Brown return 0; 24246492bc1bSMark Brown 24252b5a24a0SMark Brown if (!ms) 24262b5a24a0SMark Brown return regulator_disable(regulator); 24272b5a24a0SMark Brown 2428da07ecd9SMark Brown mutex_lock(&rdev->mutex); 2429da07ecd9SMark Brown rdev->deferred_disables++; 2430da07ecd9SMark Brown mutex_unlock(&rdev->mutex); 2431da07ecd9SMark Brown 243270dc6dafSDan Carpenter queue_delayed_work(system_power_efficient_wq, &rdev->disable_work, 2433da07ecd9SMark Brown msecs_to_jiffies(ms)); 2434aa59802dSMark Brown return 0; 2435da07ecd9SMark Brown } 2436da07ecd9SMark Brown EXPORT_SYMBOL_GPL(regulator_disable_deferred); 2437da07ecd9SMark Brown 2438414c70cbSLiam Girdwood static int _regulator_is_enabled(struct regulator_dev *rdev) 2439414c70cbSLiam Girdwood { 244065f73508SMark Brown /* A GPIO control always takes precedence */ 24417b74d149SKim, Milo if (rdev->ena_pin) 244265f73508SMark Brown return rdev->ena_gpio_state; 244365f73508SMark Brown 24449a7f6a4cSMark Brown /* If we don't know then assume that the regulator is always on */ 24459332546fSMark Brown if (!rdev->desc->ops->is_enabled) 24469a7f6a4cSMark Brown return 1; 2447414c70cbSLiam Girdwood 24489332546fSMark Brown return rdev->desc->ops->is_enabled(rdev); 2449414c70cbSLiam Girdwood } 2450414c70cbSLiam Girdwood 24513a40cfc3SSascha Hauer static int _regulator_list_voltage(struct regulator *regulator, 24523a40cfc3SSascha Hauer unsigned selector, int lock) 24533a40cfc3SSascha Hauer { 24543a40cfc3SSascha Hauer struct regulator_dev *rdev = regulator->rdev; 24553a40cfc3SSascha Hauer const struct regulator_ops *ops = rdev->desc->ops; 24563a40cfc3SSascha Hauer int ret; 24573a40cfc3SSascha Hauer 24583a40cfc3SSascha Hauer if (rdev->desc->fixed_uV && rdev->desc->n_voltages == 1 && !selector) 24593a40cfc3SSascha Hauer return rdev->desc->fixed_uV; 24603a40cfc3SSascha Hauer 24613a40cfc3SSascha Hauer if (ops->list_voltage) { 24623a40cfc3SSascha Hauer if (selector >= rdev->desc->n_voltages) 24633a40cfc3SSascha Hauer return -EINVAL; 24643a40cfc3SSascha Hauer if (lock) 24653a40cfc3SSascha Hauer mutex_lock(&rdev->mutex); 24663a40cfc3SSascha Hauer ret = ops->list_voltage(rdev, selector); 24673a40cfc3SSascha Hauer if (lock) 24683a40cfc3SSascha Hauer mutex_unlock(&rdev->mutex); 24693a40cfc3SSascha Hauer } else if (rdev->supply) { 24703a40cfc3SSascha Hauer ret = _regulator_list_voltage(rdev->supply, selector, lock); 24713a40cfc3SSascha Hauer } else { 24723a40cfc3SSascha Hauer return -EINVAL; 24733a40cfc3SSascha Hauer } 24743a40cfc3SSascha Hauer 24753a40cfc3SSascha Hauer if (ret > 0) { 24763a40cfc3SSascha Hauer if (ret < rdev->constraints->min_uV) 24773a40cfc3SSascha Hauer ret = 0; 24783a40cfc3SSascha Hauer else if (ret > rdev->constraints->max_uV) 24793a40cfc3SSascha Hauer ret = 0; 24803a40cfc3SSascha Hauer } 24813a40cfc3SSascha Hauer 24823a40cfc3SSascha Hauer return ret; 24833a40cfc3SSascha Hauer } 24843a40cfc3SSascha Hauer 2485414c70cbSLiam Girdwood /** 2486414c70cbSLiam Girdwood * regulator_is_enabled - is the regulator output enabled 2487414c70cbSLiam Girdwood * @regulator: regulator source 2488414c70cbSLiam Girdwood * 2489412aec61SDavid Brownell * Returns positive if the regulator driver backing the source/client 2490412aec61SDavid Brownell * has requested that the device be enabled, zero if it hasn't, else a 2491412aec61SDavid Brownell * negative errno code. 2492412aec61SDavid Brownell * 2493412aec61SDavid Brownell * Note that the device backing this regulator handle can have multiple 2494412aec61SDavid Brownell * users, so it might be enabled even if regulator_enable() was never 2495412aec61SDavid Brownell * called for this particular source. 2496414c70cbSLiam Girdwood */ 2497414c70cbSLiam Girdwood int regulator_is_enabled(struct regulator *regulator) 2498414c70cbSLiam Girdwood { 24999332546fSMark Brown int ret; 25009332546fSMark Brown 25016492bc1bSMark Brown if (regulator->always_on) 25026492bc1bSMark Brown return 1; 25036492bc1bSMark Brown 25049332546fSMark Brown mutex_lock(®ulator->rdev->mutex); 25059332546fSMark Brown ret = _regulator_is_enabled(regulator->rdev); 25069332546fSMark Brown mutex_unlock(®ulator->rdev->mutex); 25079332546fSMark Brown 25089332546fSMark Brown return ret; 2509414c70cbSLiam Girdwood } 2510414c70cbSLiam Girdwood EXPORT_SYMBOL_GPL(regulator_is_enabled); 2511414c70cbSLiam Girdwood 2512414c70cbSLiam Girdwood /** 25134367cfdcSDavid Brownell * regulator_count_voltages - count regulator_list_voltage() selectors 25144367cfdcSDavid Brownell * @regulator: regulator source 25154367cfdcSDavid Brownell * 25164367cfdcSDavid Brownell * Returns number of selectors, or negative errno. Selectors are 25174367cfdcSDavid Brownell * numbered starting at zero, and typically correspond to bitfields 25184367cfdcSDavid Brownell * in hardware registers. 25194367cfdcSDavid Brownell */ 25204367cfdcSDavid Brownell int regulator_count_voltages(struct regulator *regulator) 25214367cfdcSDavid Brownell { 25224367cfdcSDavid Brownell struct regulator_dev *rdev = regulator->rdev; 25234367cfdcSDavid Brownell 252426988efeSJavier Martinez Canillas if (rdev->desc->n_voltages) 252526988efeSJavier Martinez Canillas return rdev->desc->n_voltages; 252626988efeSJavier Martinez Canillas 252726988efeSJavier Martinez Canillas if (!rdev->supply) 252826988efeSJavier Martinez Canillas return -EINVAL; 252926988efeSJavier Martinez Canillas 253026988efeSJavier Martinez Canillas return regulator_count_voltages(rdev->supply); 25314367cfdcSDavid Brownell } 25324367cfdcSDavid Brownell EXPORT_SYMBOL_GPL(regulator_count_voltages); 25334367cfdcSDavid Brownell 25344367cfdcSDavid Brownell /** 25354367cfdcSDavid Brownell * regulator_list_voltage - enumerate supported voltages 25364367cfdcSDavid Brownell * @regulator: regulator source 25374367cfdcSDavid Brownell * @selector: identify voltage to list 25384367cfdcSDavid Brownell * Context: can sleep 25394367cfdcSDavid Brownell * 25404367cfdcSDavid Brownell * Returns a voltage that can be passed to @regulator_set_voltage(), 254188393161SThomas Weber * zero if this selector code can't be used on this system, or a 25424367cfdcSDavid Brownell * negative errno. 25434367cfdcSDavid Brownell */ 25444367cfdcSDavid Brownell int regulator_list_voltage(struct regulator *regulator, unsigned selector) 25454367cfdcSDavid Brownell { 25463a40cfc3SSascha Hauer return _regulator_list_voltage(regulator, selector, 1); 25474367cfdcSDavid Brownell } 25484367cfdcSDavid Brownell EXPORT_SYMBOL_GPL(regulator_list_voltage); 25494367cfdcSDavid Brownell 25504367cfdcSDavid Brownell /** 255104eca28cSTuomas Tynkkynen * regulator_get_regmap - get the regulator's register map 255204eca28cSTuomas Tynkkynen * @regulator: regulator source 255304eca28cSTuomas Tynkkynen * 255404eca28cSTuomas Tynkkynen * Returns the register map for the given regulator, or an ERR_PTR value 255504eca28cSTuomas Tynkkynen * if the regulator doesn't use regmap. 255604eca28cSTuomas Tynkkynen */ 255704eca28cSTuomas Tynkkynen struct regmap *regulator_get_regmap(struct regulator *regulator) 255804eca28cSTuomas Tynkkynen { 255904eca28cSTuomas Tynkkynen struct regmap *map = regulator->rdev->regmap; 256004eca28cSTuomas Tynkkynen 256104eca28cSTuomas Tynkkynen return map ? map : ERR_PTR(-EOPNOTSUPP); 256204eca28cSTuomas Tynkkynen } 256304eca28cSTuomas Tynkkynen 256404eca28cSTuomas Tynkkynen /** 256504eca28cSTuomas Tynkkynen * regulator_get_hardware_vsel_register - get the HW voltage selector register 256604eca28cSTuomas Tynkkynen * @regulator: regulator source 256704eca28cSTuomas Tynkkynen * @vsel_reg: voltage selector register, output parameter 256804eca28cSTuomas Tynkkynen * @vsel_mask: mask for voltage selector bitfield, output parameter 256904eca28cSTuomas Tynkkynen * 257004eca28cSTuomas Tynkkynen * Returns the hardware register offset and bitmask used for setting the 257104eca28cSTuomas Tynkkynen * regulator voltage. This might be useful when configuring voltage-scaling 257204eca28cSTuomas Tynkkynen * hardware or firmware that can make I2C requests behind the kernel's back, 257304eca28cSTuomas Tynkkynen * for example. 257404eca28cSTuomas Tynkkynen * 257504eca28cSTuomas Tynkkynen * On success, the output parameters @vsel_reg and @vsel_mask are filled in 257604eca28cSTuomas Tynkkynen * and 0 is returned, otherwise a negative errno is returned. 257704eca28cSTuomas Tynkkynen */ 257804eca28cSTuomas Tynkkynen int regulator_get_hardware_vsel_register(struct regulator *regulator, 257904eca28cSTuomas Tynkkynen unsigned *vsel_reg, 258004eca28cSTuomas Tynkkynen unsigned *vsel_mask) 258104eca28cSTuomas Tynkkynen { 258204eca28cSTuomas Tynkkynen struct regulator_dev *rdev = regulator->rdev; 258339f5460dSGuodong Xu const struct regulator_ops *ops = rdev->desc->ops; 258404eca28cSTuomas Tynkkynen 258504eca28cSTuomas Tynkkynen if (ops->set_voltage_sel != regulator_set_voltage_sel_regmap) 258604eca28cSTuomas Tynkkynen return -EOPNOTSUPP; 258704eca28cSTuomas Tynkkynen 258804eca28cSTuomas Tynkkynen *vsel_reg = rdev->desc->vsel_reg; 258904eca28cSTuomas Tynkkynen *vsel_mask = rdev->desc->vsel_mask; 259004eca28cSTuomas Tynkkynen 259104eca28cSTuomas Tynkkynen return 0; 259204eca28cSTuomas Tynkkynen } 259304eca28cSTuomas Tynkkynen EXPORT_SYMBOL_GPL(regulator_get_hardware_vsel_register); 259404eca28cSTuomas Tynkkynen 259504eca28cSTuomas Tynkkynen /** 259604eca28cSTuomas Tynkkynen * regulator_list_hardware_vsel - get the HW-specific register value for a selector 259704eca28cSTuomas Tynkkynen * @regulator: regulator source 259804eca28cSTuomas Tynkkynen * @selector: identify voltage to list 259904eca28cSTuomas Tynkkynen * 260004eca28cSTuomas Tynkkynen * Converts the selector to a hardware-specific voltage selector that can be 260104eca28cSTuomas Tynkkynen * directly written to the regulator registers. The address of the voltage 260204eca28cSTuomas Tynkkynen * register can be determined by calling @regulator_get_hardware_vsel_register. 260304eca28cSTuomas Tynkkynen * 260404eca28cSTuomas Tynkkynen * On error a negative errno is returned. 260504eca28cSTuomas Tynkkynen */ 260604eca28cSTuomas Tynkkynen int regulator_list_hardware_vsel(struct regulator *regulator, 260704eca28cSTuomas Tynkkynen unsigned selector) 260804eca28cSTuomas Tynkkynen { 260904eca28cSTuomas Tynkkynen struct regulator_dev *rdev = regulator->rdev; 261039f5460dSGuodong Xu const struct regulator_ops *ops = rdev->desc->ops; 261104eca28cSTuomas Tynkkynen 261204eca28cSTuomas Tynkkynen if (selector >= rdev->desc->n_voltages) 261304eca28cSTuomas Tynkkynen return -EINVAL; 261404eca28cSTuomas Tynkkynen if (ops->set_voltage_sel != regulator_set_voltage_sel_regmap) 261504eca28cSTuomas Tynkkynen return -EOPNOTSUPP; 261604eca28cSTuomas Tynkkynen 261704eca28cSTuomas Tynkkynen return selector; 261804eca28cSTuomas Tynkkynen } 261904eca28cSTuomas Tynkkynen EXPORT_SYMBOL_GPL(regulator_list_hardware_vsel); 262004eca28cSTuomas Tynkkynen 262104eca28cSTuomas Tynkkynen /** 26222a668a8bSPaul Walmsley * regulator_get_linear_step - return the voltage step size between VSEL values 26232a668a8bSPaul Walmsley * @regulator: regulator source 26242a668a8bSPaul Walmsley * 26252a668a8bSPaul Walmsley * Returns the voltage step size between VSEL values for linear 26262a668a8bSPaul Walmsley * regulators, or return 0 if the regulator isn't a linear regulator. 26272a668a8bSPaul Walmsley */ 26282a668a8bSPaul Walmsley unsigned int regulator_get_linear_step(struct regulator *regulator) 26292a668a8bSPaul Walmsley { 26302a668a8bSPaul Walmsley struct regulator_dev *rdev = regulator->rdev; 26312a668a8bSPaul Walmsley 26322a668a8bSPaul Walmsley return rdev->desc->uV_step; 26332a668a8bSPaul Walmsley } 26342a668a8bSPaul Walmsley EXPORT_SYMBOL_GPL(regulator_get_linear_step); 26352a668a8bSPaul Walmsley 26362a668a8bSPaul Walmsley /** 2637a7a1ad90SMark Brown * regulator_is_supported_voltage - check if a voltage range can be supported 2638a7a1ad90SMark Brown * 2639a7a1ad90SMark Brown * @regulator: Regulator to check. 2640a7a1ad90SMark Brown * @min_uV: Minimum required voltage in uV. 2641a7a1ad90SMark Brown * @max_uV: Maximum required voltage in uV. 2642a7a1ad90SMark Brown * 2643a7a1ad90SMark Brown * Returns a boolean or a negative error code. 2644a7a1ad90SMark Brown */ 2645a7a1ad90SMark Brown int regulator_is_supported_voltage(struct regulator *regulator, 2646a7a1ad90SMark Brown int min_uV, int max_uV) 2647a7a1ad90SMark Brown { 2648c5f3939bSMark Brown struct regulator_dev *rdev = regulator->rdev; 2649a7a1ad90SMark Brown int i, voltages, ret; 2650a7a1ad90SMark Brown 2651c5f3939bSMark Brown /* If we can't change voltage check the current voltage */ 26528a34e979SWEN Pingbo if (!regulator_ops_is_valid(rdev, REGULATOR_CHANGE_VOLTAGE)) { 2653c5f3939bSMark Brown ret = regulator_get_voltage(regulator); 2654c5f3939bSMark Brown if (ret >= 0) 26550d25d09dSJingoo Han return min_uV <= ret && ret <= max_uV; 2656c5f3939bSMark Brown else 2657c5f3939bSMark Brown return ret; 2658c5f3939bSMark Brown } 2659c5f3939bSMark Brown 2660bd7a2b60SPawel Moll /* Any voltage within constrains range is fine? */ 2661bd7a2b60SPawel Moll if (rdev->desc->continuous_voltage_range) 2662bd7a2b60SPawel Moll return min_uV >= rdev->constraints->min_uV && 2663bd7a2b60SPawel Moll max_uV <= rdev->constraints->max_uV; 2664bd7a2b60SPawel Moll 2665a7a1ad90SMark Brown ret = regulator_count_voltages(regulator); 2666a7a1ad90SMark Brown if (ret < 0) 2667a7a1ad90SMark Brown return ret; 2668a7a1ad90SMark Brown voltages = ret; 2669a7a1ad90SMark Brown 2670a7a1ad90SMark Brown for (i = 0; i < voltages; i++) { 2671a7a1ad90SMark Brown ret = regulator_list_voltage(regulator, i); 2672a7a1ad90SMark Brown 2673a7a1ad90SMark Brown if (ret >= min_uV && ret <= max_uV) 2674a7a1ad90SMark Brown return 1; 2675a7a1ad90SMark Brown } 2676a7a1ad90SMark Brown 2677a7a1ad90SMark Brown return 0; 2678a7a1ad90SMark Brown } 2679a398eaa2SMark Brown EXPORT_SYMBOL_GPL(regulator_is_supported_voltage); 2680a7a1ad90SMark Brown 2681a204f41eSSascha Hauer static int regulator_map_voltage(struct regulator_dev *rdev, int min_uV, 2682a204f41eSSascha Hauer int max_uV) 2683a204f41eSSascha Hauer { 2684a204f41eSSascha Hauer const struct regulator_desc *desc = rdev->desc; 2685a204f41eSSascha Hauer 2686a204f41eSSascha Hauer if (desc->ops->map_voltage) 2687a204f41eSSascha Hauer return desc->ops->map_voltage(rdev, min_uV, max_uV); 2688a204f41eSSascha Hauer 2689a204f41eSSascha Hauer if (desc->ops->list_voltage == regulator_list_voltage_linear) 2690a204f41eSSascha Hauer return regulator_map_voltage_linear(rdev, min_uV, max_uV); 2691a204f41eSSascha Hauer 2692a204f41eSSascha Hauer if (desc->ops->list_voltage == regulator_list_voltage_linear_range) 2693a204f41eSSascha Hauer return regulator_map_voltage_linear_range(rdev, min_uV, max_uV); 2694a204f41eSSascha Hauer 2695a204f41eSSascha Hauer return regulator_map_voltage_iterate(rdev, min_uV, max_uV); 2696a204f41eSSascha Hauer } 2697a204f41eSSascha Hauer 26987179569aSHeiko Stübner static int _regulator_call_set_voltage(struct regulator_dev *rdev, 26997179569aSHeiko Stübner int min_uV, int max_uV, 27007179569aSHeiko Stübner unsigned *selector) 27017179569aSHeiko Stübner { 27027179569aSHeiko Stübner struct pre_voltage_change_data data; 27037179569aSHeiko Stübner int ret; 27047179569aSHeiko Stübner 27057179569aSHeiko Stübner data.old_uV = _regulator_get_voltage(rdev); 27067179569aSHeiko Stübner data.min_uV = min_uV; 27077179569aSHeiko Stübner data.max_uV = max_uV; 27087179569aSHeiko Stübner ret = _notifier_call_chain(rdev, REGULATOR_EVENT_PRE_VOLTAGE_CHANGE, 27097179569aSHeiko Stübner &data); 27107179569aSHeiko Stübner if (ret & NOTIFY_STOP_MASK) 27117179569aSHeiko Stübner return -EINVAL; 27127179569aSHeiko Stübner 27137179569aSHeiko Stübner ret = rdev->desc->ops->set_voltage(rdev, min_uV, max_uV, selector); 27147179569aSHeiko Stübner if (ret >= 0) 27157179569aSHeiko Stübner return ret; 27167179569aSHeiko Stübner 27177179569aSHeiko Stübner _notifier_call_chain(rdev, REGULATOR_EVENT_ABORT_VOLTAGE_CHANGE, 27187179569aSHeiko Stübner (void *)data.old_uV); 27197179569aSHeiko Stübner 27207179569aSHeiko Stübner return ret; 27217179569aSHeiko Stübner } 27227179569aSHeiko Stübner 27237179569aSHeiko Stübner static int _regulator_call_set_voltage_sel(struct regulator_dev *rdev, 27247179569aSHeiko Stübner int uV, unsigned selector) 27257179569aSHeiko Stübner { 27267179569aSHeiko Stübner struct pre_voltage_change_data data; 27277179569aSHeiko Stübner int ret; 27287179569aSHeiko Stübner 27297179569aSHeiko Stübner data.old_uV = _regulator_get_voltage(rdev); 27307179569aSHeiko Stübner data.min_uV = uV; 27317179569aSHeiko Stübner data.max_uV = uV; 27327179569aSHeiko Stübner ret = _notifier_call_chain(rdev, REGULATOR_EVENT_PRE_VOLTAGE_CHANGE, 27337179569aSHeiko Stübner &data); 27347179569aSHeiko Stübner if (ret & NOTIFY_STOP_MASK) 27357179569aSHeiko Stübner return -EINVAL; 27367179569aSHeiko Stübner 27377179569aSHeiko Stübner ret = rdev->desc->ops->set_voltage_sel(rdev, selector); 27387179569aSHeiko Stübner if (ret >= 0) 27397179569aSHeiko Stübner return ret; 27407179569aSHeiko Stübner 27417179569aSHeiko Stübner _notifier_call_chain(rdev, REGULATOR_EVENT_ABORT_VOLTAGE_CHANGE, 27427179569aSHeiko Stübner (void *)data.old_uV); 27437179569aSHeiko Stübner 27447179569aSHeiko Stübner return ret; 27457179569aSHeiko Stübner } 27467179569aSHeiko Stübner 274773e705bfSMatthias Kaehlcke static int _regulator_set_voltage_time(struct regulator_dev *rdev, 274873e705bfSMatthias Kaehlcke int old_uV, int new_uV) 274973e705bfSMatthias Kaehlcke { 275073e705bfSMatthias Kaehlcke unsigned int ramp_delay = 0; 275173e705bfSMatthias Kaehlcke 275273e705bfSMatthias Kaehlcke if (rdev->constraints->ramp_delay) 275373e705bfSMatthias Kaehlcke ramp_delay = rdev->constraints->ramp_delay; 275473e705bfSMatthias Kaehlcke else if (rdev->desc->ramp_delay) 275573e705bfSMatthias Kaehlcke ramp_delay = rdev->desc->ramp_delay; 275673e705bfSMatthias Kaehlcke 275773e705bfSMatthias Kaehlcke if (ramp_delay == 0) { 275873e705bfSMatthias Kaehlcke rdev_warn(rdev, "ramp_delay not set\n"); 275973e705bfSMatthias Kaehlcke return 0; 276073e705bfSMatthias Kaehlcke } 276173e705bfSMatthias Kaehlcke 276273e705bfSMatthias Kaehlcke return DIV_ROUND_UP(abs(new_uV - old_uV), ramp_delay); 276373e705bfSMatthias Kaehlcke } 276473e705bfSMatthias Kaehlcke 276575790251SMark Brown static int _regulator_do_set_voltage(struct regulator_dev *rdev, 276675790251SMark Brown int min_uV, int max_uV) 276775790251SMark Brown { 276875790251SMark Brown int ret; 276977af1b26SLinus Walleij int delay = 0; 2770e113d792SMark Brown int best_val = 0; 277175790251SMark Brown unsigned int selector; 2772eba41a5eSAxel Lin int old_selector = -1; 277357995a48SMatthias Kaehlcke const struct regulator_ops *ops = rdev->desc->ops; 277473e705bfSMatthias Kaehlcke int old_uV = _regulator_get_voltage(rdev); 277575790251SMark Brown 277675790251SMark Brown trace_regulator_set_voltage(rdev_get_name(rdev), min_uV, max_uV); 277775790251SMark Brown 2778bf5892a8SMark Brown min_uV += rdev->constraints->uV_offset; 2779bf5892a8SMark Brown max_uV += rdev->constraints->uV_offset; 2780bf5892a8SMark Brown 278177af1b26SLinus Walleij /* 278277af1b26SLinus Walleij * If we can't obtain the old selector there is not enough 278377af1b26SLinus Walleij * info to call set_voltage_time_sel(). 278477af1b26SLinus Walleij */ 27858b7485efSAxel Lin if (_regulator_is_enabled(rdev) && 278657995a48SMatthias Kaehlcke ops->set_voltage_time_sel && ops->get_voltage_sel) { 278757995a48SMatthias Kaehlcke old_selector = ops->get_voltage_sel(rdev); 2788eba41a5eSAxel Lin if (old_selector < 0) 2789eba41a5eSAxel Lin return old_selector; 2790eba41a5eSAxel Lin } 279177af1b26SLinus Walleij 279257995a48SMatthias Kaehlcke if (ops->set_voltage) { 27937179569aSHeiko Stübner ret = _regulator_call_set_voltage(rdev, min_uV, max_uV, 279475790251SMark Brown &selector); 2795e113d792SMark Brown 2796e113d792SMark Brown if (ret >= 0) { 279757995a48SMatthias Kaehlcke if (ops->list_voltage) 279857995a48SMatthias Kaehlcke best_val = ops->list_voltage(rdev, 2799e113d792SMark Brown selector); 2800e113d792SMark Brown else 2801e113d792SMark Brown best_val = _regulator_get_voltage(rdev); 2802e113d792SMark Brown } 2803e113d792SMark Brown 280457995a48SMatthias Kaehlcke } else if (ops->set_voltage_sel) { 2805a204f41eSSascha Hauer ret = regulator_map_voltage(rdev, min_uV, max_uV); 2806e843fc46SMark Brown if (ret >= 0) { 280757995a48SMatthias Kaehlcke best_val = ops->list_voltage(rdev, ret); 2808e113d792SMark Brown if (min_uV <= best_val && max_uV >= best_val) { 2809e843fc46SMark Brown selector = ret; 2810c66a566aSAxel Lin if (old_selector == selector) 2811c66a566aSAxel Lin ret = 0; 2812c66a566aSAxel Lin else 28137179569aSHeiko Stübner ret = _regulator_call_set_voltage_sel( 28147179569aSHeiko Stübner rdev, best_val, selector); 2815e113d792SMark Brown } else { 2816e113d792SMark Brown ret = -EINVAL; 2817e113d792SMark Brown } 2818e843fc46SMark Brown } 2819e8eef82bSMark Brown } else { 2820e8eef82bSMark Brown ret = -EINVAL; 2821e8eef82bSMark Brown } 2822e8eef82bSMark Brown 282331dfe686SMatthias Kaehlcke if (ret) 282431dfe686SMatthias Kaehlcke goto out; 2825eba41a5eSAxel Lin 282673e705bfSMatthias Kaehlcke if (ops->set_voltage_time_sel) { 282773e705bfSMatthias Kaehlcke /* 282873e705bfSMatthias Kaehlcke * Call set_voltage_time_sel if successfully obtained 282973e705bfSMatthias Kaehlcke * old_selector 283073e705bfSMatthias Kaehlcke */ 283173e705bfSMatthias Kaehlcke if (old_selector >= 0 && old_selector != selector) 283273e705bfSMatthias Kaehlcke delay = ops->set_voltage_time_sel(rdev, old_selector, 283373e705bfSMatthias Kaehlcke selector); 283473e705bfSMatthias Kaehlcke } else { 283573e705bfSMatthias Kaehlcke if (old_uV != best_val) { 283673e705bfSMatthias Kaehlcke if (ops->set_voltage_time) 283773e705bfSMatthias Kaehlcke delay = ops->set_voltage_time(rdev, old_uV, 283873e705bfSMatthias Kaehlcke best_val); 283973e705bfSMatthias Kaehlcke else 284073e705bfSMatthias Kaehlcke delay = _regulator_set_voltage_time(rdev, 284173e705bfSMatthias Kaehlcke old_uV, 284273e705bfSMatthias Kaehlcke best_val); 284373e705bfSMatthias Kaehlcke } 284473e705bfSMatthias Kaehlcke } 284573e705bfSMatthias Kaehlcke 2846eba41a5eSAxel Lin if (delay < 0) { 284773e705bfSMatthias Kaehlcke rdev_warn(rdev, "failed to get delay: %d\n", delay); 2848eba41a5eSAxel Lin delay = 0; 2849e8eef82bSMark Brown } 285075790251SMark Brown 285177af1b26SLinus Walleij /* Insert any necessary delays */ 285277af1b26SLinus Walleij if (delay >= 1000) { 285377af1b26SLinus Walleij mdelay(delay / 1000); 285477af1b26SLinus Walleij udelay(delay % 1000); 285577af1b26SLinus Walleij } else if (delay) { 285677af1b26SLinus Walleij udelay(delay); 285777af1b26SLinus Walleij } 285877af1b26SLinus Walleij 285931dfe686SMatthias Kaehlcke if (best_val >= 0) { 28602f6c797fSAxel Lin unsigned long data = best_val; 28612f6c797fSAxel Lin 2862ded06a52SMark Brown _notifier_call_chain(rdev, REGULATOR_EVENT_VOLTAGE_CHANGE, 28632f6c797fSAxel Lin (void *)data); 28642f6c797fSAxel Lin } 2865ded06a52SMark Brown 286631dfe686SMatthias Kaehlcke out: 2867eba41a5eSAxel Lin trace_regulator_set_voltage_complete(rdev_get_name(rdev), best_val); 286875790251SMark Brown 286975790251SMark Brown return ret; 287075790251SMark Brown } 287175790251SMark Brown 2872a9f226bcSSascha Hauer static int regulator_set_voltage_unlocked(struct regulator *regulator, 2873a9f226bcSSascha Hauer int min_uV, int max_uV) 2874414c70cbSLiam Girdwood { 2875414c70cbSLiam Girdwood struct regulator_dev *rdev = regulator->rdev; 287695a3c23aSMark Brown int ret = 0; 287792d7a558SPaolo Pisati int old_min_uV, old_max_uV; 2878c00dc359SBjorn Andersson int current_uV; 2879fc42112cSSascha Hauer int best_supply_uV = 0; 2880fc42112cSSascha Hauer int supply_change_uV = 0; 2881414c70cbSLiam Girdwood 288295a3c23aSMark Brown /* If we're setting the same range as last time the change 288395a3c23aSMark Brown * should be a noop (some cpufreq implementations use the same 288495a3c23aSMark Brown * voltage for multiple frequencies, for example). 288595a3c23aSMark Brown */ 288695a3c23aSMark Brown if (regulator->min_uV == min_uV && regulator->max_uV == max_uV) 288795a3c23aSMark Brown goto out; 288895a3c23aSMark Brown 2889c00dc359SBjorn Andersson /* If we're trying to set a range that overlaps the current voltage, 2890d3fb9800SViresh Kumar * return successfully even though the regulator does not support 2891c00dc359SBjorn Andersson * changing the voltage. 2892c00dc359SBjorn Andersson */ 28938a34e979SWEN Pingbo if (!regulator_ops_is_valid(rdev, REGULATOR_CHANGE_VOLTAGE)) { 2894c00dc359SBjorn Andersson current_uV = _regulator_get_voltage(rdev); 2895c00dc359SBjorn Andersson if (min_uV <= current_uV && current_uV <= max_uV) { 2896c00dc359SBjorn Andersson regulator->min_uV = min_uV; 2897c00dc359SBjorn Andersson regulator->max_uV = max_uV; 2898c00dc359SBjorn Andersson goto out; 2899c00dc359SBjorn Andersson } 2900c00dc359SBjorn Andersson } 2901c00dc359SBjorn Andersson 2902414c70cbSLiam Girdwood /* sanity check */ 2903e8eef82bSMark Brown if (!rdev->desc->ops->set_voltage && 2904e8eef82bSMark Brown !rdev->desc->ops->set_voltage_sel) { 2905414c70cbSLiam Girdwood ret = -EINVAL; 2906414c70cbSLiam Girdwood goto out; 2907414c70cbSLiam Girdwood } 2908414c70cbSLiam Girdwood 2909414c70cbSLiam Girdwood /* constraints check */ 2910414c70cbSLiam Girdwood ret = regulator_check_voltage(rdev, &min_uV, &max_uV); 2911414c70cbSLiam Girdwood if (ret < 0) 2912414c70cbSLiam Girdwood goto out; 291392d7a558SPaolo Pisati 291492d7a558SPaolo Pisati /* restore original values in case of error */ 291592d7a558SPaolo Pisati old_min_uV = regulator->min_uV; 291692d7a558SPaolo Pisati old_max_uV = regulator->max_uV; 2917414c70cbSLiam Girdwood regulator->min_uV = min_uV; 2918414c70cbSLiam Girdwood regulator->max_uV = max_uV; 29193a93f2a9SMark Brown 292005fda3b1SThomas Petazzoni ret = regulator_check_consumers(rdev, &min_uV, &max_uV); 292105fda3b1SThomas Petazzoni if (ret < 0) 292292d7a558SPaolo Pisati goto out2; 292305fda3b1SThomas Petazzoni 2924fc42112cSSascha Hauer if (rdev->supply && (rdev->desc->min_dropout_uV || 2925fc42112cSSascha Hauer !rdev->desc->ops->get_voltage)) { 2926fc42112cSSascha Hauer int current_supply_uV; 2927fc42112cSSascha Hauer int selector; 2928fc42112cSSascha Hauer 2929fc42112cSSascha Hauer selector = regulator_map_voltage(rdev, min_uV, max_uV); 2930fc42112cSSascha Hauer if (selector < 0) { 2931fc42112cSSascha Hauer ret = selector; 2932fc42112cSSascha Hauer goto out2; 2933fc42112cSSascha Hauer } 2934fc42112cSSascha Hauer 2935fc42112cSSascha Hauer best_supply_uV = _regulator_list_voltage(regulator, selector, 0); 2936fc42112cSSascha Hauer if (best_supply_uV < 0) { 2937fc42112cSSascha Hauer ret = best_supply_uV; 2938fc42112cSSascha Hauer goto out2; 2939fc42112cSSascha Hauer } 2940fc42112cSSascha Hauer 2941fc42112cSSascha Hauer best_supply_uV += rdev->desc->min_dropout_uV; 2942fc42112cSSascha Hauer 2943fc42112cSSascha Hauer current_supply_uV = _regulator_get_voltage(rdev->supply->rdev); 2944fc42112cSSascha Hauer if (current_supply_uV < 0) { 2945fc42112cSSascha Hauer ret = current_supply_uV; 2946fc42112cSSascha Hauer goto out2; 2947fc42112cSSascha Hauer } 2948fc42112cSSascha Hauer 2949fc42112cSSascha Hauer supply_change_uV = best_supply_uV - current_supply_uV; 2950fc42112cSSascha Hauer } 2951fc42112cSSascha Hauer 2952fc42112cSSascha Hauer if (supply_change_uV > 0) { 2953fc42112cSSascha Hauer ret = regulator_set_voltage_unlocked(rdev->supply, 2954fc42112cSSascha Hauer best_supply_uV, INT_MAX); 2955fc42112cSSascha Hauer if (ret) { 2956fc42112cSSascha Hauer dev_err(&rdev->dev, "Failed to increase supply voltage: %d\n", 2957fc42112cSSascha Hauer ret); 2958fc42112cSSascha Hauer goto out2; 2959fc42112cSSascha Hauer } 2960fc42112cSSascha Hauer } 2961fc42112cSSascha Hauer 296275790251SMark Brown ret = _regulator_do_set_voltage(rdev, min_uV, max_uV); 296392d7a558SPaolo Pisati if (ret < 0) 296492d7a558SPaolo Pisati goto out2; 296502fa3ec0SMark Brown 2966fc42112cSSascha Hauer if (supply_change_uV < 0) { 2967fc42112cSSascha Hauer ret = regulator_set_voltage_unlocked(rdev->supply, 2968fc42112cSSascha Hauer best_supply_uV, INT_MAX); 2969fc42112cSSascha Hauer if (ret) 2970fc42112cSSascha Hauer dev_warn(&rdev->dev, "Failed to decrease supply voltage: %d\n", 2971fc42112cSSascha Hauer ret); 2972fc42112cSSascha Hauer /* No need to fail here */ 2973fc42112cSSascha Hauer ret = 0; 2974fc42112cSSascha Hauer } 2975fc42112cSSascha Hauer 2976414c70cbSLiam Girdwood out: 2977414c70cbSLiam Girdwood return ret; 297892d7a558SPaolo Pisati out2: 297992d7a558SPaolo Pisati regulator->min_uV = old_min_uV; 298092d7a558SPaolo Pisati regulator->max_uV = old_max_uV; 2981a9f226bcSSascha Hauer 2982a9f226bcSSascha Hauer return ret; 2983a9f226bcSSascha Hauer } 2984a9f226bcSSascha Hauer 2985a9f226bcSSascha Hauer /** 2986a9f226bcSSascha Hauer * regulator_set_voltage - set regulator output voltage 2987a9f226bcSSascha Hauer * @regulator: regulator source 2988a9f226bcSSascha Hauer * @min_uV: Minimum required voltage in uV 2989a9f226bcSSascha Hauer * @max_uV: Maximum acceptable voltage in uV 2990a9f226bcSSascha Hauer * 2991a9f226bcSSascha Hauer * Sets a voltage regulator to the desired output voltage. This can be set 2992a9f226bcSSascha Hauer * during any regulator state. IOW, regulator can be disabled or enabled. 2993a9f226bcSSascha Hauer * 2994a9f226bcSSascha Hauer * If the regulator is enabled then the voltage will change to the new value 2995a9f226bcSSascha Hauer * immediately otherwise if the regulator is disabled the regulator will 2996a9f226bcSSascha Hauer * output at the new voltage when enabled. 2997a9f226bcSSascha Hauer * 2998a9f226bcSSascha Hauer * NOTE: If the regulator is shared between several devices then the lowest 2999a9f226bcSSascha Hauer * request voltage that meets the system constraints will be used. 3000a9f226bcSSascha Hauer * Regulator system constraints must be set for this regulator before 3001a9f226bcSSascha Hauer * calling this function otherwise this call will fail. 3002a9f226bcSSascha Hauer */ 3003a9f226bcSSascha Hauer int regulator_set_voltage(struct regulator *regulator, int min_uV, int max_uV) 3004a9f226bcSSascha Hauer { 3005a9f226bcSSascha Hauer int ret = 0; 3006a9f226bcSSascha Hauer 3007fc42112cSSascha Hauer regulator_lock_supply(regulator->rdev); 3008a9f226bcSSascha Hauer 3009a9f226bcSSascha Hauer ret = regulator_set_voltage_unlocked(regulator, min_uV, max_uV); 3010a9f226bcSSascha Hauer 3011fc42112cSSascha Hauer regulator_unlock_supply(regulator->rdev); 3012a9f226bcSSascha Hauer 301392d7a558SPaolo Pisati return ret; 3014414c70cbSLiam Girdwood } 3015414c70cbSLiam Girdwood EXPORT_SYMBOL_GPL(regulator_set_voltage); 3016414c70cbSLiam Girdwood 3017606a2562SMark Brown /** 301888cd222bSLinus Walleij * regulator_set_voltage_time - get raise/fall time 301988cd222bSLinus Walleij * @regulator: regulator source 302088cd222bSLinus Walleij * @old_uV: starting voltage in microvolts 302188cd222bSLinus Walleij * @new_uV: target voltage in microvolts 302288cd222bSLinus Walleij * 302388cd222bSLinus Walleij * Provided with the starting and ending voltage, this function attempts to 302488cd222bSLinus Walleij * calculate the time in microseconds required to rise or fall to this new 302588cd222bSLinus Walleij * voltage. 302688cd222bSLinus Walleij */ 302788cd222bSLinus Walleij int regulator_set_voltage_time(struct regulator *regulator, 302888cd222bSLinus Walleij int old_uV, int new_uV) 302988cd222bSLinus Walleij { 303088cd222bSLinus Walleij struct regulator_dev *rdev = regulator->rdev; 3031272e2315SGuodong Xu const struct regulator_ops *ops = rdev->desc->ops; 303288cd222bSLinus Walleij int old_sel = -1; 303388cd222bSLinus Walleij int new_sel = -1; 303488cd222bSLinus Walleij int voltage; 303588cd222bSLinus Walleij int i; 303688cd222bSLinus Walleij 303773e705bfSMatthias Kaehlcke if (ops->set_voltage_time) 303873e705bfSMatthias Kaehlcke return ops->set_voltage_time(rdev, old_uV, new_uV); 303973e705bfSMatthias Kaehlcke else if (!ops->set_voltage_time_sel) 304073e705bfSMatthias Kaehlcke return _regulator_set_voltage_time(rdev, old_uV, new_uV); 304173e705bfSMatthias Kaehlcke 304288cd222bSLinus Walleij /* Currently requires operations to do this */ 304373e705bfSMatthias Kaehlcke if (!ops->list_voltage || !rdev->desc->n_voltages) 304488cd222bSLinus Walleij return -EINVAL; 304588cd222bSLinus Walleij 304688cd222bSLinus Walleij for (i = 0; i < rdev->desc->n_voltages; i++) { 304788cd222bSLinus Walleij /* We only look for exact voltage matches here */ 304888cd222bSLinus Walleij voltage = regulator_list_voltage(regulator, i); 304988cd222bSLinus Walleij if (voltage < 0) 305088cd222bSLinus Walleij return -EINVAL; 305188cd222bSLinus Walleij if (voltage == 0) 305288cd222bSLinus Walleij continue; 305388cd222bSLinus Walleij if (voltage == old_uV) 305488cd222bSLinus Walleij old_sel = i; 305588cd222bSLinus Walleij if (voltage == new_uV) 305688cd222bSLinus Walleij new_sel = i; 305788cd222bSLinus Walleij } 305888cd222bSLinus Walleij 305988cd222bSLinus Walleij if (old_sel < 0 || new_sel < 0) 306088cd222bSLinus Walleij return -EINVAL; 306188cd222bSLinus Walleij 306288cd222bSLinus Walleij return ops->set_voltage_time_sel(rdev, old_sel, new_sel); 306388cd222bSLinus Walleij } 306488cd222bSLinus Walleij EXPORT_SYMBOL_GPL(regulator_set_voltage_time); 306588cd222bSLinus Walleij 306688cd222bSLinus Walleij /** 306798a175b6SYadwinder Singh Brar * regulator_set_voltage_time_sel - get raise/fall time 3068296c6566SRandy Dunlap * @rdev: regulator source device 306998a175b6SYadwinder Singh Brar * @old_selector: selector for starting voltage 307098a175b6SYadwinder Singh Brar * @new_selector: selector for target voltage 307198a175b6SYadwinder Singh Brar * 307298a175b6SYadwinder Singh Brar * Provided with the starting and target voltage selectors, this function 307398a175b6SYadwinder Singh Brar * returns time in microseconds required to rise or fall to this new voltage 307498a175b6SYadwinder Singh Brar * 3075f11d08c3SAxel Lin * Drivers providing ramp_delay in regulation_constraints can use this as their 3076398715abSAxel Lin * set_voltage_time_sel() operation. 307798a175b6SYadwinder Singh Brar */ 307898a175b6SYadwinder Singh Brar int regulator_set_voltage_time_sel(struct regulator_dev *rdev, 307998a175b6SYadwinder Singh Brar unsigned int old_selector, 308098a175b6SYadwinder Singh Brar unsigned int new_selector) 308198a175b6SYadwinder Singh Brar { 3082f11d08c3SAxel Lin int old_volt, new_volt; 3083398715abSAxel Lin 3084f11d08c3SAxel Lin /* sanity check */ 3085f11d08c3SAxel Lin if (!rdev->desc->ops->list_voltage) 3086f11d08c3SAxel Lin return -EINVAL; 3087398715abSAxel Lin 3088f11d08c3SAxel Lin old_volt = rdev->desc->ops->list_voltage(rdev, old_selector); 3089f11d08c3SAxel Lin new_volt = rdev->desc->ops->list_voltage(rdev, new_selector); 3090f11d08c3SAxel Lin 309173e705bfSMatthias Kaehlcke if (rdev->desc->ops->set_voltage_time) 309273e705bfSMatthias Kaehlcke return rdev->desc->ops->set_voltage_time(rdev, old_volt, 309373e705bfSMatthias Kaehlcke new_volt); 309473e705bfSMatthias Kaehlcke else 309573e705bfSMatthias Kaehlcke return _regulator_set_voltage_time(rdev, old_volt, new_volt); 309698a175b6SYadwinder Singh Brar } 3097b19dbf71SMark Brown EXPORT_SYMBOL_GPL(regulator_set_voltage_time_sel); 309898a175b6SYadwinder Singh Brar 309998a175b6SYadwinder Singh Brar /** 3100606a2562SMark Brown * regulator_sync_voltage - re-apply last regulator output voltage 3101606a2562SMark Brown * @regulator: regulator source 3102606a2562SMark Brown * 3103606a2562SMark Brown * Re-apply the last configured voltage. This is intended to be used 3104606a2562SMark Brown * where some external control source the consumer is cooperating with 3105606a2562SMark Brown * has caused the configured voltage to change. 3106606a2562SMark Brown */ 3107606a2562SMark Brown int regulator_sync_voltage(struct regulator *regulator) 3108606a2562SMark Brown { 3109606a2562SMark Brown struct regulator_dev *rdev = regulator->rdev; 3110606a2562SMark Brown int ret, min_uV, max_uV; 3111606a2562SMark Brown 3112606a2562SMark Brown mutex_lock(&rdev->mutex); 3113606a2562SMark Brown 3114606a2562SMark Brown if (!rdev->desc->ops->set_voltage && 3115606a2562SMark Brown !rdev->desc->ops->set_voltage_sel) { 3116606a2562SMark Brown ret = -EINVAL; 3117606a2562SMark Brown goto out; 3118606a2562SMark Brown } 3119606a2562SMark Brown 3120606a2562SMark Brown /* This is only going to work if we've had a voltage configured. */ 3121606a2562SMark Brown if (!regulator->min_uV && !regulator->max_uV) { 3122606a2562SMark Brown ret = -EINVAL; 3123606a2562SMark Brown goto out; 3124606a2562SMark Brown } 3125606a2562SMark Brown 3126606a2562SMark Brown min_uV = regulator->min_uV; 3127606a2562SMark Brown max_uV = regulator->max_uV; 3128606a2562SMark Brown 3129606a2562SMark Brown /* This should be a paranoia check... */ 3130606a2562SMark Brown ret = regulator_check_voltage(rdev, &min_uV, &max_uV); 3131606a2562SMark Brown if (ret < 0) 3132606a2562SMark Brown goto out; 3133606a2562SMark Brown 3134606a2562SMark Brown ret = regulator_check_consumers(rdev, &min_uV, &max_uV); 3135606a2562SMark Brown if (ret < 0) 3136606a2562SMark Brown goto out; 3137606a2562SMark Brown 3138606a2562SMark Brown ret = _regulator_do_set_voltage(rdev, min_uV, max_uV); 3139606a2562SMark Brown 3140606a2562SMark Brown out: 3141606a2562SMark Brown mutex_unlock(&rdev->mutex); 3142606a2562SMark Brown return ret; 3143606a2562SMark Brown } 3144606a2562SMark Brown EXPORT_SYMBOL_GPL(regulator_sync_voltage); 3145606a2562SMark Brown 3146414c70cbSLiam Girdwood static int _regulator_get_voltage(struct regulator_dev *rdev) 3147414c70cbSLiam Girdwood { 3148bf5892a8SMark Brown int sel, ret; 3149fef95019SMark Brown bool bypassed; 3150fef95019SMark Brown 3151fef95019SMark Brown if (rdev->desc->ops->get_bypass) { 3152fef95019SMark Brown ret = rdev->desc->ops->get_bypass(rdev, &bypassed); 3153fef95019SMark Brown if (ret < 0) 3154fef95019SMark Brown return ret; 3155fef95019SMark Brown if (bypassed) { 3156fef95019SMark Brown /* if bypassed the regulator must have a supply */ 315745389c47SJon Hunter if (!rdev->supply) { 315845389c47SJon Hunter rdev_err(rdev, 315945389c47SJon Hunter "bypassed regulator has no supply!\n"); 316045389c47SJon Hunter return -EPROBE_DEFER; 316145389c47SJon Hunter } 3162fef95019SMark Brown 3163fef95019SMark Brown return _regulator_get_voltage(rdev->supply->rdev); 3164fef95019SMark Brown } 3165fef95019SMark Brown } 3166476c2d83SMark Brown 3167476c2d83SMark Brown if (rdev->desc->ops->get_voltage_sel) { 3168476c2d83SMark Brown sel = rdev->desc->ops->get_voltage_sel(rdev); 3169476c2d83SMark Brown if (sel < 0) 3170476c2d83SMark Brown return sel; 3171bf5892a8SMark Brown ret = rdev->desc->ops->list_voltage(rdev, sel); 3172cb220d16SAxel Lin } else if (rdev->desc->ops->get_voltage) { 3173bf5892a8SMark Brown ret = rdev->desc->ops->get_voltage(rdev); 3174f7df20ecSMark Brown } else if (rdev->desc->ops->list_voltage) { 3175f7df20ecSMark Brown ret = rdev->desc->ops->list_voltage(rdev, 0); 31765a523605SLaxman Dewangan } else if (rdev->desc->fixed_uV && (rdev->desc->n_voltages == 1)) { 31775a523605SLaxman Dewangan ret = rdev->desc->fixed_uV; 3178e303996eSJavier Martinez Canillas } else if (rdev->supply) { 3179d9b96d35SMark Brown ret = _regulator_get_voltage(rdev->supply->rdev); 3180cb220d16SAxel Lin } else { 3181414c70cbSLiam Girdwood return -EINVAL; 3182cb220d16SAxel Lin } 3183bf5892a8SMark Brown 3184cb220d16SAxel Lin if (ret < 0) 3185cb220d16SAxel Lin return ret; 3186bf5892a8SMark Brown return ret - rdev->constraints->uV_offset; 3187414c70cbSLiam Girdwood } 3188414c70cbSLiam Girdwood 3189414c70cbSLiam Girdwood /** 3190414c70cbSLiam Girdwood * regulator_get_voltage - get regulator output voltage 3191414c70cbSLiam Girdwood * @regulator: regulator source 3192414c70cbSLiam Girdwood * 3193414c70cbSLiam Girdwood * This returns the current regulator voltage in uV. 3194414c70cbSLiam Girdwood * 3195414c70cbSLiam Girdwood * NOTE: If the regulator is disabled it will return the voltage value. This 3196414c70cbSLiam Girdwood * function should not be used to determine regulator state. 3197414c70cbSLiam Girdwood */ 3198414c70cbSLiam Girdwood int regulator_get_voltage(struct regulator *regulator) 3199414c70cbSLiam Girdwood { 3200414c70cbSLiam Girdwood int ret; 3201414c70cbSLiam Girdwood 3202d9b96d35SMark Brown regulator_lock_supply(regulator->rdev); 3203414c70cbSLiam Girdwood 3204414c70cbSLiam Girdwood ret = _regulator_get_voltage(regulator->rdev); 3205414c70cbSLiam Girdwood 3206d9b96d35SMark Brown regulator_unlock_supply(regulator->rdev); 3207414c70cbSLiam Girdwood 3208414c70cbSLiam Girdwood return ret; 3209414c70cbSLiam Girdwood } 3210414c70cbSLiam Girdwood EXPORT_SYMBOL_GPL(regulator_get_voltage); 3211414c70cbSLiam Girdwood 3212414c70cbSLiam Girdwood /** 3213414c70cbSLiam Girdwood * regulator_set_current_limit - set regulator output current limit 3214414c70cbSLiam Girdwood * @regulator: regulator source 3215ce0d10f8SCharles Keepax * @min_uA: Minimum supported current in uA 3216414c70cbSLiam Girdwood * @max_uA: Maximum supported current in uA 3217414c70cbSLiam Girdwood * 3218414c70cbSLiam Girdwood * Sets current sink to the desired output current. This can be set during 3219414c70cbSLiam Girdwood * any regulator state. IOW, regulator can be disabled or enabled. 3220414c70cbSLiam Girdwood * 3221414c70cbSLiam Girdwood * If the regulator is enabled then the current will change to the new value 3222414c70cbSLiam Girdwood * immediately otherwise if the regulator is disabled the regulator will 3223414c70cbSLiam Girdwood * output at the new current when enabled. 3224414c70cbSLiam Girdwood * 3225414c70cbSLiam Girdwood * NOTE: Regulator system constraints must be set for this regulator before 3226414c70cbSLiam Girdwood * calling this function otherwise this call will fail. 3227414c70cbSLiam Girdwood */ 3228414c70cbSLiam Girdwood int regulator_set_current_limit(struct regulator *regulator, 3229414c70cbSLiam Girdwood int min_uA, int max_uA) 3230414c70cbSLiam Girdwood { 3231414c70cbSLiam Girdwood struct regulator_dev *rdev = regulator->rdev; 3232414c70cbSLiam Girdwood int ret; 3233414c70cbSLiam Girdwood 3234414c70cbSLiam Girdwood mutex_lock(&rdev->mutex); 3235414c70cbSLiam Girdwood 3236414c70cbSLiam Girdwood /* sanity check */ 3237414c70cbSLiam Girdwood if (!rdev->desc->ops->set_current_limit) { 3238414c70cbSLiam Girdwood ret = -EINVAL; 3239414c70cbSLiam Girdwood goto out; 3240414c70cbSLiam Girdwood } 3241414c70cbSLiam Girdwood 3242414c70cbSLiam Girdwood /* constraints check */ 3243414c70cbSLiam Girdwood ret = regulator_check_current_limit(rdev, &min_uA, &max_uA); 3244414c70cbSLiam Girdwood if (ret < 0) 3245414c70cbSLiam Girdwood goto out; 3246414c70cbSLiam Girdwood 3247414c70cbSLiam Girdwood ret = rdev->desc->ops->set_current_limit(rdev, min_uA, max_uA); 3248414c70cbSLiam Girdwood out: 3249414c70cbSLiam Girdwood mutex_unlock(&rdev->mutex); 3250414c70cbSLiam Girdwood return ret; 3251414c70cbSLiam Girdwood } 3252414c70cbSLiam Girdwood EXPORT_SYMBOL_GPL(regulator_set_current_limit); 3253414c70cbSLiam Girdwood 3254414c70cbSLiam Girdwood static int _regulator_get_current_limit(struct regulator_dev *rdev) 3255414c70cbSLiam Girdwood { 3256414c70cbSLiam Girdwood int ret; 3257414c70cbSLiam Girdwood 3258414c70cbSLiam Girdwood mutex_lock(&rdev->mutex); 3259414c70cbSLiam Girdwood 3260414c70cbSLiam Girdwood /* sanity check */ 3261414c70cbSLiam Girdwood if (!rdev->desc->ops->get_current_limit) { 3262414c70cbSLiam Girdwood ret = -EINVAL; 3263414c70cbSLiam Girdwood goto out; 3264414c70cbSLiam Girdwood } 3265414c70cbSLiam Girdwood 3266414c70cbSLiam Girdwood ret = rdev->desc->ops->get_current_limit(rdev); 3267414c70cbSLiam Girdwood out: 3268414c70cbSLiam Girdwood mutex_unlock(&rdev->mutex); 3269414c70cbSLiam Girdwood return ret; 3270414c70cbSLiam Girdwood } 3271414c70cbSLiam Girdwood 3272414c70cbSLiam Girdwood /** 3273414c70cbSLiam Girdwood * regulator_get_current_limit - get regulator output current 3274414c70cbSLiam Girdwood * @regulator: regulator source 3275414c70cbSLiam Girdwood * 3276414c70cbSLiam Girdwood * This returns the current supplied by the specified current sink in uA. 3277414c70cbSLiam Girdwood * 3278414c70cbSLiam Girdwood * NOTE: If the regulator is disabled it will return the current value. This 3279414c70cbSLiam Girdwood * function should not be used to determine regulator state. 3280414c70cbSLiam Girdwood */ 3281414c70cbSLiam Girdwood int regulator_get_current_limit(struct regulator *regulator) 3282414c70cbSLiam Girdwood { 3283414c70cbSLiam Girdwood return _regulator_get_current_limit(regulator->rdev); 3284414c70cbSLiam Girdwood } 3285414c70cbSLiam Girdwood EXPORT_SYMBOL_GPL(regulator_get_current_limit); 3286414c70cbSLiam Girdwood 3287414c70cbSLiam Girdwood /** 3288414c70cbSLiam Girdwood * regulator_set_mode - set regulator operating mode 3289414c70cbSLiam Girdwood * @regulator: regulator source 3290414c70cbSLiam Girdwood * @mode: operating mode - one of the REGULATOR_MODE constants 3291414c70cbSLiam Girdwood * 3292414c70cbSLiam Girdwood * Set regulator operating mode to increase regulator efficiency or improve 3293414c70cbSLiam Girdwood * regulation performance. 3294414c70cbSLiam Girdwood * 3295414c70cbSLiam Girdwood * NOTE: Regulator system constraints must be set for this regulator before 3296414c70cbSLiam Girdwood * calling this function otherwise this call will fail. 3297414c70cbSLiam Girdwood */ 3298414c70cbSLiam Girdwood int regulator_set_mode(struct regulator *regulator, unsigned int mode) 3299414c70cbSLiam Girdwood { 3300414c70cbSLiam Girdwood struct regulator_dev *rdev = regulator->rdev; 3301414c70cbSLiam Girdwood int ret; 3302500b4ac9SSundar R Iyer int regulator_curr_mode; 3303414c70cbSLiam Girdwood 3304414c70cbSLiam Girdwood mutex_lock(&rdev->mutex); 3305414c70cbSLiam Girdwood 3306414c70cbSLiam Girdwood /* sanity check */ 3307414c70cbSLiam Girdwood if (!rdev->desc->ops->set_mode) { 3308414c70cbSLiam Girdwood ret = -EINVAL; 3309414c70cbSLiam Girdwood goto out; 3310414c70cbSLiam Girdwood } 3311414c70cbSLiam Girdwood 3312500b4ac9SSundar R Iyer /* return if the same mode is requested */ 3313500b4ac9SSundar R Iyer if (rdev->desc->ops->get_mode) { 3314500b4ac9SSundar R Iyer regulator_curr_mode = rdev->desc->ops->get_mode(rdev); 3315500b4ac9SSundar R Iyer if (regulator_curr_mode == mode) { 3316500b4ac9SSundar R Iyer ret = 0; 3317500b4ac9SSundar R Iyer goto out; 3318500b4ac9SSundar R Iyer } 3319500b4ac9SSundar R Iyer } 3320500b4ac9SSundar R Iyer 3321414c70cbSLiam Girdwood /* constraints check */ 332222c51b47SAxel Lin ret = regulator_mode_constrain(rdev, &mode); 3323414c70cbSLiam Girdwood if (ret < 0) 3324414c70cbSLiam Girdwood goto out; 3325414c70cbSLiam Girdwood 3326414c70cbSLiam Girdwood ret = rdev->desc->ops->set_mode(rdev, mode); 3327414c70cbSLiam Girdwood out: 3328414c70cbSLiam Girdwood mutex_unlock(&rdev->mutex); 3329414c70cbSLiam Girdwood return ret; 3330414c70cbSLiam Girdwood } 3331414c70cbSLiam Girdwood EXPORT_SYMBOL_GPL(regulator_set_mode); 3332414c70cbSLiam Girdwood 3333414c70cbSLiam Girdwood static unsigned int _regulator_get_mode(struct regulator_dev *rdev) 3334414c70cbSLiam Girdwood { 3335414c70cbSLiam Girdwood int ret; 3336414c70cbSLiam Girdwood 3337414c70cbSLiam Girdwood mutex_lock(&rdev->mutex); 3338414c70cbSLiam Girdwood 3339414c70cbSLiam Girdwood /* sanity check */ 3340414c70cbSLiam Girdwood if (!rdev->desc->ops->get_mode) { 3341414c70cbSLiam Girdwood ret = -EINVAL; 3342414c70cbSLiam Girdwood goto out; 3343414c70cbSLiam Girdwood } 3344414c70cbSLiam Girdwood 3345414c70cbSLiam Girdwood ret = rdev->desc->ops->get_mode(rdev); 3346414c70cbSLiam Girdwood out: 3347414c70cbSLiam Girdwood mutex_unlock(&rdev->mutex); 3348414c70cbSLiam Girdwood return ret; 3349414c70cbSLiam Girdwood } 3350414c70cbSLiam Girdwood 3351414c70cbSLiam Girdwood /** 3352414c70cbSLiam Girdwood * regulator_get_mode - get regulator operating mode 3353414c70cbSLiam Girdwood * @regulator: regulator source 3354414c70cbSLiam Girdwood * 3355414c70cbSLiam Girdwood * Get the current regulator operating mode. 3356414c70cbSLiam Girdwood */ 3357414c70cbSLiam Girdwood unsigned int regulator_get_mode(struct regulator *regulator) 3358414c70cbSLiam Girdwood { 3359414c70cbSLiam Girdwood return _regulator_get_mode(regulator->rdev); 3360414c70cbSLiam Girdwood } 3361414c70cbSLiam Girdwood EXPORT_SYMBOL_GPL(regulator_get_mode); 3362414c70cbSLiam Girdwood 3363414c70cbSLiam Girdwood /** 3364e39ce48fSBjorn Andersson * regulator_set_load - set regulator load 3365414c70cbSLiam Girdwood * @regulator: regulator source 3366414c70cbSLiam Girdwood * @uA_load: load current 3367414c70cbSLiam Girdwood * 3368414c70cbSLiam Girdwood * Notifies the regulator core of a new device load. This is then used by 3369414c70cbSLiam Girdwood * DRMS (if enabled by constraints) to set the most efficient regulator 3370414c70cbSLiam Girdwood * operating mode for the new regulator loading. 3371414c70cbSLiam Girdwood * 3372414c70cbSLiam Girdwood * Consumer devices notify their supply regulator of the maximum power 3373414c70cbSLiam Girdwood * they will require (can be taken from device datasheet in the power 3374414c70cbSLiam Girdwood * consumption tables) when they change operational status and hence power 3375414c70cbSLiam Girdwood * state. Examples of operational state changes that can affect power 3376414c70cbSLiam Girdwood * consumption are :- 3377414c70cbSLiam Girdwood * 3378414c70cbSLiam Girdwood * o Device is opened / closed. 3379414c70cbSLiam Girdwood * o Device I/O is about to begin or has just finished. 3380414c70cbSLiam Girdwood * o Device is idling in between work. 3381414c70cbSLiam Girdwood * 3382414c70cbSLiam Girdwood * This information is also exported via sysfs to userspace. 3383414c70cbSLiam Girdwood * 3384414c70cbSLiam Girdwood * DRMS will sum the total requested load on the regulator and change 3385414c70cbSLiam Girdwood * to the most efficient operating mode if platform constraints allow. 3386414c70cbSLiam Girdwood * 3387e39ce48fSBjorn Andersson * On error a negative errno is returned. 3388414c70cbSLiam Girdwood */ 3389e39ce48fSBjorn Andersson int regulator_set_load(struct regulator *regulator, int uA_load) 3390414c70cbSLiam Girdwood { 3391414c70cbSLiam Girdwood struct regulator_dev *rdev = regulator->rdev; 33928460ef38SBjorn Andersson int ret; 3393d92d95b6SStephen Boyd 3394414c70cbSLiam Girdwood mutex_lock(&rdev->mutex); 3395414c70cbSLiam Girdwood regulator->uA_load = uA_load; 33968460ef38SBjorn Andersson ret = drms_uA_update(rdev); 3397414c70cbSLiam Girdwood mutex_unlock(&rdev->mutex); 33988460ef38SBjorn Andersson 3399414c70cbSLiam Girdwood return ret; 3400414c70cbSLiam Girdwood } 3401e39ce48fSBjorn Andersson EXPORT_SYMBOL_GPL(regulator_set_load); 3402414c70cbSLiam Girdwood 3403414c70cbSLiam Girdwood /** 3404f59c8f9fSMark Brown * regulator_allow_bypass - allow the regulator to go into bypass mode 3405f59c8f9fSMark Brown * 3406f59c8f9fSMark Brown * @regulator: Regulator to configure 34079345dfb8SNishanth Menon * @enable: enable or disable bypass mode 3408f59c8f9fSMark Brown * 3409f59c8f9fSMark Brown * Allow the regulator to go into bypass mode if all other consumers 3410f59c8f9fSMark Brown * for the regulator also enable bypass mode and the machine 3411f59c8f9fSMark Brown * constraints allow this. Bypass mode means that the regulator is 3412f59c8f9fSMark Brown * simply passing the input directly to the output with no regulation. 3413f59c8f9fSMark Brown */ 3414f59c8f9fSMark Brown int regulator_allow_bypass(struct regulator *regulator, bool enable) 3415f59c8f9fSMark Brown { 3416f59c8f9fSMark Brown struct regulator_dev *rdev = regulator->rdev; 3417f59c8f9fSMark Brown int ret = 0; 3418f59c8f9fSMark Brown 3419f59c8f9fSMark Brown if (!rdev->desc->ops->set_bypass) 3420f59c8f9fSMark Brown return 0; 3421f59c8f9fSMark Brown 34228a34e979SWEN Pingbo if (!regulator_ops_is_valid(rdev, REGULATOR_CHANGE_BYPASS)) 3423f59c8f9fSMark Brown return 0; 3424f59c8f9fSMark Brown 3425f59c8f9fSMark Brown mutex_lock(&rdev->mutex); 3426f59c8f9fSMark Brown 3427f59c8f9fSMark Brown if (enable && !regulator->bypass) { 3428f59c8f9fSMark Brown rdev->bypass_count++; 3429f59c8f9fSMark Brown 3430f59c8f9fSMark Brown if (rdev->bypass_count == rdev->open_count) { 3431f59c8f9fSMark Brown ret = rdev->desc->ops->set_bypass(rdev, enable); 3432f59c8f9fSMark Brown if (ret != 0) 3433f59c8f9fSMark Brown rdev->bypass_count--; 3434f59c8f9fSMark Brown } 3435f59c8f9fSMark Brown 3436f59c8f9fSMark Brown } else if (!enable && regulator->bypass) { 3437f59c8f9fSMark Brown rdev->bypass_count--; 3438f59c8f9fSMark Brown 3439f59c8f9fSMark Brown if (rdev->bypass_count != rdev->open_count) { 3440f59c8f9fSMark Brown ret = rdev->desc->ops->set_bypass(rdev, enable); 3441f59c8f9fSMark Brown if (ret != 0) 3442f59c8f9fSMark Brown rdev->bypass_count++; 3443f59c8f9fSMark Brown } 3444f59c8f9fSMark Brown } 3445f59c8f9fSMark Brown 3446f59c8f9fSMark Brown if (ret == 0) 3447f59c8f9fSMark Brown regulator->bypass = enable; 3448f59c8f9fSMark Brown 3449f59c8f9fSMark Brown mutex_unlock(&rdev->mutex); 3450f59c8f9fSMark Brown 3451f59c8f9fSMark Brown return ret; 3452f59c8f9fSMark Brown } 3453f59c8f9fSMark Brown EXPORT_SYMBOL_GPL(regulator_allow_bypass); 3454f59c8f9fSMark Brown 3455f59c8f9fSMark Brown /** 3456414c70cbSLiam Girdwood * regulator_register_notifier - register regulator event notifier 3457414c70cbSLiam Girdwood * @regulator: regulator source 345869279fb9SMark Brown * @nb: notifier block 3459414c70cbSLiam Girdwood * 3460414c70cbSLiam Girdwood * Register notifier block to receive regulator events. 3461414c70cbSLiam Girdwood */ 3462414c70cbSLiam Girdwood int regulator_register_notifier(struct regulator *regulator, 3463414c70cbSLiam Girdwood struct notifier_block *nb) 3464414c70cbSLiam Girdwood { 3465414c70cbSLiam Girdwood return blocking_notifier_chain_register(®ulator->rdev->notifier, 3466414c70cbSLiam Girdwood nb); 3467414c70cbSLiam Girdwood } 3468414c70cbSLiam Girdwood EXPORT_SYMBOL_GPL(regulator_register_notifier); 3469414c70cbSLiam Girdwood 3470414c70cbSLiam Girdwood /** 3471414c70cbSLiam Girdwood * regulator_unregister_notifier - unregister regulator event notifier 3472414c70cbSLiam Girdwood * @regulator: regulator source 347369279fb9SMark Brown * @nb: notifier block 3474414c70cbSLiam Girdwood * 3475414c70cbSLiam Girdwood * Unregister regulator event notifier block. 3476414c70cbSLiam Girdwood */ 3477414c70cbSLiam Girdwood int regulator_unregister_notifier(struct regulator *regulator, 3478414c70cbSLiam Girdwood struct notifier_block *nb) 3479414c70cbSLiam Girdwood { 3480414c70cbSLiam Girdwood return blocking_notifier_chain_unregister(®ulator->rdev->notifier, 3481414c70cbSLiam Girdwood nb); 3482414c70cbSLiam Girdwood } 3483414c70cbSLiam Girdwood EXPORT_SYMBOL_GPL(regulator_unregister_notifier); 3484414c70cbSLiam Girdwood 3485b136fb44SJonathan Cameron /* notify regulator consumers and downstream regulator consumers. 3486b136fb44SJonathan Cameron * Note mutex must be held by caller. 3487b136fb44SJonathan Cameron */ 34887179569aSHeiko Stübner static int _notifier_call_chain(struct regulator_dev *rdev, 3489414c70cbSLiam Girdwood unsigned long event, void *data) 3490414c70cbSLiam Girdwood { 3491414c70cbSLiam Girdwood /* call rdev chain first */ 34927179569aSHeiko Stübner return blocking_notifier_call_chain(&rdev->notifier, event, data); 3493414c70cbSLiam Girdwood } 3494414c70cbSLiam Girdwood 3495414c70cbSLiam Girdwood /** 3496414c70cbSLiam Girdwood * regulator_bulk_get - get multiple regulator consumers 3497414c70cbSLiam Girdwood * 3498414c70cbSLiam Girdwood * @dev: Device to supply 3499414c70cbSLiam Girdwood * @num_consumers: Number of consumers to register 3500414c70cbSLiam Girdwood * @consumers: Configuration of consumers; clients are stored here. 3501414c70cbSLiam Girdwood * 3502414c70cbSLiam Girdwood * @return 0 on success, an errno on failure. 3503414c70cbSLiam Girdwood * 3504414c70cbSLiam Girdwood * This helper function allows drivers to get several regulator 3505414c70cbSLiam Girdwood * consumers in one operation. If any of the regulators cannot be 3506414c70cbSLiam Girdwood * acquired then any regulators that were allocated will be freed 3507414c70cbSLiam Girdwood * before returning to the caller. 3508414c70cbSLiam Girdwood */ 3509414c70cbSLiam Girdwood int regulator_bulk_get(struct device *dev, int num_consumers, 3510414c70cbSLiam Girdwood struct regulator_bulk_data *consumers) 3511414c70cbSLiam Girdwood { 3512414c70cbSLiam Girdwood int i; 3513414c70cbSLiam Girdwood int ret; 3514414c70cbSLiam Girdwood 3515414c70cbSLiam Girdwood for (i = 0; i < num_consumers; i++) 3516414c70cbSLiam Girdwood consumers[i].consumer = NULL; 3517414c70cbSLiam Girdwood 3518414c70cbSLiam Girdwood for (i = 0; i < num_consumers; i++) { 3519565f9b07SBjorn Andersson consumers[i].consumer = regulator_get(dev, 3520565f9b07SBjorn Andersson consumers[i].supply); 3521414c70cbSLiam Girdwood if (IS_ERR(consumers[i].consumer)) { 3522414c70cbSLiam Girdwood ret = PTR_ERR(consumers[i].consumer); 35235b307627SMark Brown dev_err(dev, "Failed to get supply '%s': %d\n", 35245b307627SMark Brown consumers[i].supply, ret); 3525414c70cbSLiam Girdwood consumers[i].consumer = NULL; 3526414c70cbSLiam Girdwood goto err; 3527414c70cbSLiam Girdwood } 3528414c70cbSLiam Girdwood } 3529414c70cbSLiam Girdwood 3530414c70cbSLiam Girdwood return 0; 3531414c70cbSLiam Girdwood 3532414c70cbSLiam Girdwood err: 3533b29c7690SAxel Lin while (--i >= 0) 3534414c70cbSLiam Girdwood regulator_put(consumers[i].consumer); 3535414c70cbSLiam Girdwood 3536414c70cbSLiam Girdwood return ret; 3537414c70cbSLiam Girdwood } 3538414c70cbSLiam Girdwood EXPORT_SYMBOL_GPL(regulator_bulk_get); 3539414c70cbSLiam Girdwood 3540f21e0e81SMark Brown static void regulator_bulk_enable_async(void *data, async_cookie_t cookie) 3541f21e0e81SMark Brown { 3542f21e0e81SMark Brown struct regulator_bulk_data *bulk = data; 3543f21e0e81SMark Brown 3544f21e0e81SMark Brown bulk->ret = regulator_enable(bulk->consumer); 3545f21e0e81SMark Brown } 3546f21e0e81SMark Brown 3547414c70cbSLiam Girdwood /** 3548414c70cbSLiam Girdwood * regulator_bulk_enable - enable multiple regulator consumers 3549414c70cbSLiam Girdwood * 3550414c70cbSLiam Girdwood * @num_consumers: Number of consumers 3551414c70cbSLiam Girdwood * @consumers: Consumer data; clients are stored here. 3552414c70cbSLiam Girdwood * @return 0 on success, an errno on failure 3553414c70cbSLiam Girdwood * 3554414c70cbSLiam Girdwood * This convenience API allows consumers to enable multiple regulator 3555414c70cbSLiam Girdwood * clients in a single API call. If any consumers cannot be enabled 3556414c70cbSLiam Girdwood * then any others that were enabled will be disabled again prior to 3557414c70cbSLiam Girdwood * return. 3558414c70cbSLiam Girdwood */ 3559414c70cbSLiam Girdwood int regulator_bulk_enable(int num_consumers, 3560414c70cbSLiam Girdwood struct regulator_bulk_data *consumers) 3561414c70cbSLiam Girdwood { 35622955b47dSDan Williams ASYNC_DOMAIN_EXCLUSIVE(async_domain); 3563414c70cbSLiam Girdwood int i; 3564f21e0e81SMark Brown int ret = 0; 3565414c70cbSLiam Girdwood 35666492bc1bSMark Brown for (i = 0; i < num_consumers; i++) { 35676492bc1bSMark Brown if (consumers[i].consumer->always_on) 35686492bc1bSMark Brown consumers[i].ret = 0; 35696492bc1bSMark Brown else 3570f21e0e81SMark Brown async_schedule_domain(regulator_bulk_enable_async, 3571f21e0e81SMark Brown &consumers[i], &async_domain); 35726492bc1bSMark Brown } 3573f21e0e81SMark Brown 3574f21e0e81SMark Brown async_synchronize_full_domain(&async_domain); 3575f21e0e81SMark Brown 3576f21e0e81SMark Brown /* If any consumer failed we need to unwind any that succeeded */ 3577414c70cbSLiam Girdwood for (i = 0; i < num_consumers; i++) { 3578f21e0e81SMark Brown if (consumers[i].ret != 0) { 3579f21e0e81SMark Brown ret = consumers[i].ret; 3580414c70cbSLiam Girdwood goto err; 3581414c70cbSLiam Girdwood } 3582f21e0e81SMark Brown } 3583414c70cbSLiam Girdwood 3584414c70cbSLiam Girdwood return 0; 3585414c70cbSLiam Girdwood 3586414c70cbSLiam Girdwood err: 3587fbe31057SAndrzej Hajda for (i = 0; i < num_consumers; i++) { 3588fbe31057SAndrzej Hajda if (consumers[i].ret < 0) 3589fbe31057SAndrzej Hajda pr_err("Failed to enable %s: %d\n", consumers[i].supply, 3590fbe31057SAndrzej Hajda consumers[i].ret); 3591fbe31057SAndrzej Hajda else 3592414c70cbSLiam Girdwood regulator_disable(consumers[i].consumer); 3593fbe31057SAndrzej Hajda } 3594414c70cbSLiam Girdwood 3595414c70cbSLiam Girdwood return ret; 3596414c70cbSLiam Girdwood } 3597414c70cbSLiam Girdwood EXPORT_SYMBOL_GPL(regulator_bulk_enable); 3598414c70cbSLiam Girdwood 3599414c70cbSLiam Girdwood /** 3600414c70cbSLiam Girdwood * regulator_bulk_disable - disable multiple regulator consumers 3601414c70cbSLiam Girdwood * 3602414c70cbSLiam Girdwood * @num_consumers: Number of consumers 3603414c70cbSLiam Girdwood * @consumers: Consumer data; clients are stored here. 3604414c70cbSLiam Girdwood * @return 0 on success, an errno on failure 3605414c70cbSLiam Girdwood * 3606414c70cbSLiam Girdwood * This convenience API allows consumers to disable multiple regulator 360749e22632SSylwester Nawrocki * clients in a single API call. If any consumers cannot be disabled 360849e22632SSylwester Nawrocki * then any others that were disabled will be enabled again prior to 3609414c70cbSLiam Girdwood * return. 3610414c70cbSLiam Girdwood */ 3611414c70cbSLiam Girdwood int regulator_bulk_disable(int num_consumers, 3612414c70cbSLiam Girdwood struct regulator_bulk_data *consumers) 3613414c70cbSLiam Girdwood { 3614414c70cbSLiam Girdwood int i; 361501e86f49SMark Brown int ret, r; 3616414c70cbSLiam Girdwood 361749e22632SSylwester Nawrocki for (i = num_consumers - 1; i >= 0; --i) { 3618414c70cbSLiam Girdwood ret = regulator_disable(consumers[i].consumer); 3619414c70cbSLiam Girdwood if (ret != 0) 3620414c70cbSLiam Girdwood goto err; 3621414c70cbSLiam Girdwood } 3622414c70cbSLiam Girdwood 3623414c70cbSLiam Girdwood return 0; 3624414c70cbSLiam Girdwood 3625414c70cbSLiam Girdwood err: 36265da84fd9SJoe Perches pr_err("Failed to disable %s: %d\n", consumers[i].supply, ret); 362701e86f49SMark Brown for (++i; i < num_consumers; ++i) { 362801e86f49SMark Brown r = regulator_enable(consumers[i].consumer); 362901e86f49SMark Brown if (r != 0) 363001e86f49SMark Brown pr_err("Failed to reename %s: %d\n", 363101e86f49SMark Brown consumers[i].supply, r); 363201e86f49SMark Brown } 3633414c70cbSLiam Girdwood 3634414c70cbSLiam Girdwood return ret; 3635414c70cbSLiam Girdwood } 3636414c70cbSLiam Girdwood EXPORT_SYMBOL_GPL(regulator_bulk_disable); 3637414c70cbSLiam Girdwood 3638414c70cbSLiam Girdwood /** 3639e1de2f42SDonggeun Kim * regulator_bulk_force_disable - force disable multiple regulator consumers 3640e1de2f42SDonggeun Kim * 3641e1de2f42SDonggeun Kim * @num_consumers: Number of consumers 3642e1de2f42SDonggeun Kim * @consumers: Consumer data; clients are stored here. 3643e1de2f42SDonggeun Kim * @return 0 on success, an errno on failure 3644e1de2f42SDonggeun Kim * 3645e1de2f42SDonggeun Kim * This convenience API allows consumers to forcibly disable multiple regulator 3646e1de2f42SDonggeun Kim * clients in a single API call. 3647e1de2f42SDonggeun Kim * NOTE: This should be used for situations when device damage will 3648e1de2f42SDonggeun Kim * likely occur if the regulators are not disabled (e.g. over temp). 3649e1de2f42SDonggeun Kim * Although regulator_force_disable function call for some consumers can 3650e1de2f42SDonggeun Kim * return error numbers, the function is called for all consumers. 3651e1de2f42SDonggeun Kim */ 3652e1de2f42SDonggeun Kim int regulator_bulk_force_disable(int num_consumers, 3653e1de2f42SDonggeun Kim struct regulator_bulk_data *consumers) 3654e1de2f42SDonggeun Kim { 3655e1de2f42SDonggeun Kim int i; 3656e1de2f42SDonggeun Kim int ret; 3657e1de2f42SDonggeun Kim 3658e1de2f42SDonggeun Kim for (i = 0; i < num_consumers; i++) 3659e1de2f42SDonggeun Kim consumers[i].ret = 3660e1de2f42SDonggeun Kim regulator_force_disable(consumers[i].consumer); 3661e1de2f42SDonggeun Kim 3662e1de2f42SDonggeun Kim for (i = 0; i < num_consumers; i++) { 3663e1de2f42SDonggeun Kim if (consumers[i].ret != 0) { 3664e1de2f42SDonggeun Kim ret = consumers[i].ret; 3665e1de2f42SDonggeun Kim goto out; 3666e1de2f42SDonggeun Kim } 3667e1de2f42SDonggeun Kim } 3668e1de2f42SDonggeun Kim 3669e1de2f42SDonggeun Kim return 0; 3670e1de2f42SDonggeun Kim out: 3671e1de2f42SDonggeun Kim return ret; 3672e1de2f42SDonggeun Kim } 3673e1de2f42SDonggeun Kim EXPORT_SYMBOL_GPL(regulator_bulk_force_disable); 3674e1de2f42SDonggeun Kim 3675e1de2f42SDonggeun Kim /** 3676414c70cbSLiam Girdwood * regulator_bulk_free - free multiple regulator consumers 3677414c70cbSLiam Girdwood * 3678414c70cbSLiam Girdwood * @num_consumers: Number of consumers 3679414c70cbSLiam Girdwood * @consumers: Consumer data; clients are stored here. 3680414c70cbSLiam Girdwood * 3681414c70cbSLiam Girdwood * This convenience API allows consumers to free multiple regulator 3682414c70cbSLiam Girdwood * clients in a single API call. 3683414c70cbSLiam Girdwood */ 3684414c70cbSLiam Girdwood void regulator_bulk_free(int num_consumers, 3685414c70cbSLiam Girdwood struct regulator_bulk_data *consumers) 3686414c70cbSLiam Girdwood { 3687414c70cbSLiam Girdwood int i; 3688414c70cbSLiam Girdwood 3689414c70cbSLiam Girdwood for (i = 0; i < num_consumers; i++) { 3690414c70cbSLiam Girdwood regulator_put(consumers[i].consumer); 3691414c70cbSLiam Girdwood consumers[i].consumer = NULL; 3692414c70cbSLiam Girdwood } 3693414c70cbSLiam Girdwood } 3694414c70cbSLiam Girdwood EXPORT_SYMBOL_GPL(regulator_bulk_free); 3695414c70cbSLiam Girdwood 3696414c70cbSLiam Girdwood /** 3697414c70cbSLiam Girdwood * regulator_notifier_call_chain - call regulator event notifier 369869279fb9SMark Brown * @rdev: regulator source 3699414c70cbSLiam Girdwood * @event: notifier block 370069279fb9SMark Brown * @data: callback-specific data. 3701414c70cbSLiam Girdwood * 3702414c70cbSLiam Girdwood * Called by regulator drivers to notify clients a regulator event has 3703414c70cbSLiam Girdwood * occurred. We also notify regulator clients downstream. 3704b136fb44SJonathan Cameron * Note lock must be held by caller. 3705414c70cbSLiam Girdwood */ 3706414c70cbSLiam Girdwood int regulator_notifier_call_chain(struct regulator_dev *rdev, 3707414c70cbSLiam Girdwood unsigned long event, void *data) 3708414c70cbSLiam Girdwood { 370970cfef26SKrzysztof Kozlowski lockdep_assert_held_once(&rdev->mutex); 371070cfef26SKrzysztof Kozlowski 3711414c70cbSLiam Girdwood _notifier_call_chain(rdev, event, data); 3712414c70cbSLiam Girdwood return NOTIFY_DONE; 3713414c70cbSLiam Girdwood 3714414c70cbSLiam Girdwood } 3715414c70cbSLiam Girdwood EXPORT_SYMBOL_GPL(regulator_notifier_call_chain); 3716414c70cbSLiam Girdwood 3717be721979SMark Brown /** 3718be721979SMark Brown * regulator_mode_to_status - convert a regulator mode into a status 3719be721979SMark Brown * 3720be721979SMark Brown * @mode: Mode to convert 3721be721979SMark Brown * 3722be721979SMark Brown * Convert a regulator mode into a status. 3723be721979SMark Brown */ 3724be721979SMark Brown int regulator_mode_to_status(unsigned int mode) 3725be721979SMark Brown { 3726be721979SMark Brown switch (mode) { 3727be721979SMark Brown case REGULATOR_MODE_FAST: 3728be721979SMark Brown return REGULATOR_STATUS_FAST; 3729be721979SMark Brown case REGULATOR_MODE_NORMAL: 3730be721979SMark Brown return REGULATOR_STATUS_NORMAL; 3731be721979SMark Brown case REGULATOR_MODE_IDLE: 3732be721979SMark Brown return REGULATOR_STATUS_IDLE; 373303ffcf3dSKrystian Garbaciak case REGULATOR_MODE_STANDBY: 3734be721979SMark Brown return REGULATOR_STATUS_STANDBY; 3735be721979SMark Brown default: 37361beaf762SKrystian Garbaciak return REGULATOR_STATUS_UNDEFINED; 3737be721979SMark Brown } 3738be721979SMark Brown } 3739be721979SMark Brown EXPORT_SYMBOL_GPL(regulator_mode_to_status); 3740be721979SMark Brown 374139f802d6STakashi Iwai static struct attribute *regulator_dev_attrs[] = { 374239f802d6STakashi Iwai &dev_attr_name.attr, 374339f802d6STakashi Iwai &dev_attr_num_users.attr, 374439f802d6STakashi Iwai &dev_attr_type.attr, 374539f802d6STakashi Iwai &dev_attr_microvolts.attr, 374639f802d6STakashi Iwai &dev_attr_microamps.attr, 374739f802d6STakashi Iwai &dev_attr_opmode.attr, 374839f802d6STakashi Iwai &dev_attr_state.attr, 374939f802d6STakashi Iwai &dev_attr_status.attr, 375039f802d6STakashi Iwai &dev_attr_bypass.attr, 375139f802d6STakashi Iwai &dev_attr_requested_microamps.attr, 375239f802d6STakashi Iwai &dev_attr_min_microvolts.attr, 375339f802d6STakashi Iwai &dev_attr_max_microvolts.attr, 375439f802d6STakashi Iwai &dev_attr_min_microamps.attr, 375539f802d6STakashi Iwai &dev_attr_max_microamps.attr, 375639f802d6STakashi Iwai &dev_attr_suspend_standby_state.attr, 375739f802d6STakashi Iwai &dev_attr_suspend_mem_state.attr, 375839f802d6STakashi Iwai &dev_attr_suspend_disk_state.attr, 375939f802d6STakashi Iwai &dev_attr_suspend_standby_microvolts.attr, 376039f802d6STakashi Iwai &dev_attr_suspend_mem_microvolts.attr, 376139f802d6STakashi Iwai &dev_attr_suspend_disk_microvolts.attr, 376239f802d6STakashi Iwai &dev_attr_suspend_standby_mode.attr, 376339f802d6STakashi Iwai &dev_attr_suspend_mem_mode.attr, 376439f802d6STakashi Iwai &dev_attr_suspend_disk_mode.attr, 376539f802d6STakashi Iwai NULL 376639f802d6STakashi Iwai }; 376739f802d6STakashi Iwai 37687ad68e2fSDavid Brownell /* 37697ad68e2fSDavid Brownell * To avoid cluttering sysfs (and memory) with useless state, only 37707ad68e2fSDavid Brownell * create attributes that can be meaningfully displayed. 37717ad68e2fSDavid Brownell */ 377239f802d6STakashi Iwai static umode_t regulator_attr_is_visible(struct kobject *kobj, 377339f802d6STakashi Iwai struct attribute *attr, int idx) 37747ad68e2fSDavid Brownell { 377539f802d6STakashi Iwai struct device *dev = kobj_to_dev(kobj); 377683080a14SGeliang Tang struct regulator_dev *rdev = dev_to_rdev(dev); 3777272e2315SGuodong Xu const struct regulator_ops *ops = rdev->desc->ops; 377839f802d6STakashi Iwai umode_t mode = attr->mode; 377939f802d6STakashi Iwai 378039f802d6STakashi Iwai /* these three are always present */ 378139f802d6STakashi Iwai if (attr == &dev_attr_name.attr || 378239f802d6STakashi Iwai attr == &dev_attr_num_users.attr || 378339f802d6STakashi Iwai attr == &dev_attr_type.attr) 378439f802d6STakashi Iwai return mode; 37857ad68e2fSDavid Brownell 37867ad68e2fSDavid Brownell /* some attributes need specific methods to be displayed */ 378739f802d6STakashi Iwai if (attr == &dev_attr_microvolts.attr) { 37884c78899bSMark Brown if ((ops->get_voltage && ops->get_voltage(rdev) >= 0) || 3789f2889e65SMark Brown (ops->get_voltage_sel && ops->get_voltage_sel(rdev) >= 0) || 37905a523605SLaxman Dewangan (ops->list_voltage && ops->list_voltage(rdev, 0) >= 0) || 379139f802d6STakashi Iwai (rdev->desc->fixed_uV && rdev->desc->n_voltages == 1)) 379239f802d6STakashi Iwai return mode; 379339f802d6STakashi Iwai return 0; 3794f59c8f9fSMark Brown } 37957ad68e2fSDavid Brownell 379639f802d6STakashi Iwai if (attr == &dev_attr_microamps.attr) 379739f802d6STakashi Iwai return ops->get_current_limit ? mode : 0; 379839f802d6STakashi Iwai 379939f802d6STakashi Iwai if (attr == &dev_attr_opmode.attr) 380039f802d6STakashi Iwai return ops->get_mode ? mode : 0; 380139f802d6STakashi Iwai 380239f802d6STakashi Iwai if (attr == &dev_attr_state.attr) 380339f802d6STakashi Iwai return (rdev->ena_pin || ops->is_enabled) ? mode : 0; 380439f802d6STakashi Iwai 380539f802d6STakashi Iwai if (attr == &dev_attr_status.attr) 380639f802d6STakashi Iwai return ops->get_status ? mode : 0; 380739f802d6STakashi Iwai 380839f802d6STakashi Iwai if (attr == &dev_attr_bypass.attr) 380939f802d6STakashi Iwai return ops->get_bypass ? mode : 0; 381039f802d6STakashi Iwai 38117ad68e2fSDavid Brownell /* some attributes are type-specific */ 381239f802d6STakashi Iwai if (attr == &dev_attr_requested_microamps.attr) 381339f802d6STakashi Iwai return rdev->desc->type == REGULATOR_CURRENT ? mode : 0; 38147ad68e2fSDavid Brownell 38157ad68e2fSDavid Brownell /* constraints need specific supporting methods */ 381639f802d6STakashi Iwai if (attr == &dev_attr_min_microvolts.attr || 381739f802d6STakashi Iwai attr == &dev_attr_max_microvolts.attr) 381839f802d6STakashi Iwai return (ops->set_voltage || ops->set_voltage_sel) ? mode : 0; 381939f802d6STakashi Iwai 382039f802d6STakashi Iwai if (attr == &dev_attr_min_microamps.attr || 382139f802d6STakashi Iwai attr == &dev_attr_max_microamps.attr) 382239f802d6STakashi Iwai return ops->set_current_limit ? mode : 0; 382339f802d6STakashi Iwai 382439f802d6STakashi Iwai if (attr == &dev_attr_suspend_standby_state.attr || 382539f802d6STakashi Iwai attr == &dev_attr_suspend_mem_state.attr || 382639f802d6STakashi Iwai attr == &dev_attr_suspend_disk_state.attr) 382739f802d6STakashi Iwai return mode; 382839f802d6STakashi Iwai 382939f802d6STakashi Iwai if (attr == &dev_attr_suspend_standby_microvolts.attr || 383039f802d6STakashi Iwai attr == &dev_attr_suspend_mem_microvolts.attr || 383139f802d6STakashi Iwai attr == &dev_attr_suspend_disk_microvolts.attr) 383239f802d6STakashi Iwai return ops->set_suspend_voltage ? mode : 0; 383339f802d6STakashi Iwai 383439f802d6STakashi Iwai if (attr == &dev_attr_suspend_standby_mode.attr || 383539f802d6STakashi Iwai attr == &dev_attr_suspend_mem_mode.attr || 383639f802d6STakashi Iwai attr == &dev_attr_suspend_disk_mode.attr) 383739f802d6STakashi Iwai return ops->set_suspend_mode ? mode : 0; 383839f802d6STakashi Iwai 383939f802d6STakashi Iwai return mode; 38407ad68e2fSDavid Brownell } 38417ad68e2fSDavid Brownell 384239f802d6STakashi Iwai static const struct attribute_group regulator_dev_group = { 384339f802d6STakashi Iwai .attrs = regulator_dev_attrs, 384439f802d6STakashi Iwai .is_visible = regulator_attr_is_visible, 384539f802d6STakashi Iwai }; 38467ad68e2fSDavid Brownell 384739f802d6STakashi Iwai static const struct attribute_group *regulator_dev_groups[] = { 384839f802d6STakashi Iwai ®ulator_dev_group, 384939f802d6STakashi Iwai NULL 385039f802d6STakashi Iwai }; 385139f802d6STakashi Iwai 385239f802d6STakashi Iwai static void regulator_dev_release(struct device *dev) 385339f802d6STakashi Iwai { 385439f802d6STakashi Iwai struct regulator_dev *rdev = dev_get_drvdata(dev); 385529f5f486SMark Brown 385629f5f486SMark Brown kfree(rdev->constraints); 385729f5f486SMark Brown of_node_put(rdev->dev.of_node); 385839f802d6STakashi Iwai kfree(rdev); 38597ad68e2fSDavid Brownell } 38607ad68e2fSDavid Brownell 386139f802d6STakashi Iwai static struct class regulator_class = { 386239f802d6STakashi Iwai .name = "regulator", 386339f802d6STakashi Iwai .dev_release = regulator_dev_release, 386439f802d6STakashi Iwai .dev_groups = regulator_dev_groups, 386539f802d6STakashi Iwai }; 38667ad68e2fSDavid Brownell 38671130e5b3SMark Brown static void rdev_init_debugfs(struct regulator_dev *rdev) 38681130e5b3SMark Brown { 3869a9eaa813SGuenter Roeck struct device *parent = rdev->dev.parent; 3870a9eaa813SGuenter Roeck const char *rname = rdev_get_name(rdev); 3871a9eaa813SGuenter Roeck char name[NAME_MAX]; 3872a9eaa813SGuenter Roeck 3873a9eaa813SGuenter Roeck /* Avoid duplicate debugfs directory names */ 3874a9eaa813SGuenter Roeck if (parent && rname == rdev->desc->name) { 3875a9eaa813SGuenter Roeck snprintf(name, sizeof(name), "%s-%s", dev_name(parent), 3876a9eaa813SGuenter Roeck rname); 3877a9eaa813SGuenter Roeck rname = name; 3878a9eaa813SGuenter Roeck } 3879a9eaa813SGuenter Roeck 3880a9eaa813SGuenter Roeck rdev->debugfs = debugfs_create_dir(rname, debugfs_root); 388124751434SStephen Boyd if (!rdev->debugfs) { 38821130e5b3SMark Brown rdev_warn(rdev, "Failed to create debugfs directory\n"); 38831130e5b3SMark Brown return; 38841130e5b3SMark Brown } 38851130e5b3SMark Brown 38861130e5b3SMark Brown debugfs_create_u32("use_count", 0444, rdev->debugfs, 38871130e5b3SMark Brown &rdev->use_count); 38881130e5b3SMark Brown debugfs_create_u32("open_count", 0444, rdev->debugfs, 38891130e5b3SMark Brown &rdev->open_count); 3890f59c8f9fSMark Brown debugfs_create_u32("bypass_count", 0444, rdev->debugfs, 3891f59c8f9fSMark Brown &rdev->bypass_count); 38921130e5b3SMark Brown } 38931130e5b3SMark Brown 38945e3ca2b3SJavier Martinez Canillas static int regulator_register_resolve_supply(struct device *dev, void *data) 38955e3ca2b3SJavier Martinez Canillas { 38967ddede6aSJon Hunter struct regulator_dev *rdev = dev_to_rdev(dev); 38977ddede6aSJon Hunter 38987ddede6aSJon Hunter if (regulator_resolve_supply(rdev)) 38997ddede6aSJon Hunter rdev_dbg(rdev, "unable to resolve supply\n"); 39007ddede6aSJon Hunter 39017ddede6aSJon Hunter return 0; 39025e3ca2b3SJavier Martinez Canillas } 39035e3ca2b3SJavier Martinez Canillas 3904414c70cbSLiam Girdwood /** 3905414c70cbSLiam Girdwood * regulator_register - register regulator 390669279fb9SMark Brown * @regulator_desc: regulator to register 3907f47531b1SKrzysztof Kozlowski * @cfg: runtime configuration for regulator 3908414c70cbSLiam Girdwood * 3909414c70cbSLiam Girdwood * Called by regulator drivers to register a regulator. 39100384618aSAxel Lin * Returns a valid pointer to struct regulator_dev on success 39110384618aSAxel Lin * or an ERR_PTR() on error. 3912414c70cbSLiam Girdwood */ 391365f26846SMark Brown struct regulator_dev * 391465f26846SMark Brown regulator_register(const struct regulator_desc *regulator_desc, 39151b3de223SKrzysztof Kozlowski const struct regulator_config *cfg) 3916414c70cbSLiam Girdwood { 39179a8f5e07SMark Brown const struct regulation_constraints *constraints = NULL; 3918c172708dSMark Brown const struct regulator_init_data *init_data; 39191b3de223SKrzysztof Kozlowski struct regulator_config *config = NULL; 392072dca06fSAniroop Mathur static atomic_t regulator_no = ATOMIC_INIT(-1); 3921414c70cbSLiam Girdwood struct regulator_dev *rdev; 392232c8fad4SMark Brown struct device *dev; 3923a5766f11SLiam Girdwood int ret, i; 3924414c70cbSLiam Girdwood 39251b3de223SKrzysztof Kozlowski if (regulator_desc == NULL || cfg == NULL) 3926414c70cbSLiam Girdwood return ERR_PTR(-EINVAL); 3927414c70cbSLiam Girdwood 39281b3de223SKrzysztof Kozlowski dev = cfg->dev; 3929dcf70112SMark Brown WARN_ON(!dev); 393032c8fad4SMark Brown 3931414c70cbSLiam Girdwood if (regulator_desc->name == NULL || regulator_desc->ops == NULL) 3932414c70cbSLiam Girdwood return ERR_PTR(-EINVAL); 3933414c70cbSLiam Girdwood 3934cd78dfc6SDiego Liziero if (regulator_desc->type != REGULATOR_VOLTAGE && 3935cd78dfc6SDiego Liziero regulator_desc->type != REGULATOR_CURRENT) 3936414c70cbSLiam Girdwood return ERR_PTR(-EINVAL); 3937414c70cbSLiam Girdwood 3938476c2d83SMark Brown /* Only one of each should be implemented */ 3939476c2d83SMark Brown WARN_ON(regulator_desc->ops->get_voltage && 3940476c2d83SMark Brown regulator_desc->ops->get_voltage_sel); 3941e8eef82bSMark Brown WARN_ON(regulator_desc->ops->set_voltage && 3942e8eef82bSMark Brown regulator_desc->ops->set_voltage_sel); 3943476c2d83SMark Brown 3944476c2d83SMark Brown /* If we're using selectors we must implement list_voltage. */ 3945476c2d83SMark Brown if (regulator_desc->ops->get_voltage_sel && 3946476c2d83SMark Brown !regulator_desc->ops->list_voltage) { 3947476c2d83SMark Brown return ERR_PTR(-EINVAL); 3948476c2d83SMark Brown } 3949e8eef82bSMark Brown if (regulator_desc->ops->set_voltage_sel && 3950e8eef82bSMark Brown !regulator_desc->ops->list_voltage) { 3951e8eef82bSMark Brown return ERR_PTR(-EINVAL); 3952e8eef82bSMark Brown } 3953476c2d83SMark Brown 3954414c70cbSLiam Girdwood rdev = kzalloc(sizeof(struct regulator_dev), GFP_KERNEL); 3955414c70cbSLiam Girdwood if (rdev == NULL) 3956414c70cbSLiam Girdwood return ERR_PTR(-ENOMEM); 3957414c70cbSLiam Girdwood 39581b3de223SKrzysztof Kozlowski /* 39591b3de223SKrzysztof Kozlowski * Duplicate the config so the driver could override it after 39601b3de223SKrzysztof Kozlowski * parsing init data. 39611b3de223SKrzysztof Kozlowski */ 39621b3de223SKrzysztof Kozlowski config = kmemdup(cfg, sizeof(*cfg), GFP_KERNEL); 39631b3de223SKrzysztof Kozlowski if (config == NULL) { 39641b3de223SKrzysztof Kozlowski kfree(rdev); 39651b3de223SKrzysztof Kozlowski return ERR_PTR(-ENOMEM); 39661b3de223SKrzysztof Kozlowski } 39671b3de223SKrzysztof Kozlowski 3968bfa21a0dSKrzysztof Kozlowski init_data = regulator_of_get_init_data(dev, regulator_desc, config, 3969a0c7b164SMark Brown &rdev->dev.of_node); 3970a0c7b164SMark Brown if (!init_data) { 3971a0c7b164SMark Brown init_data = config->init_data; 3972a0c7b164SMark Brown rdev->dev.of_node = of_node_get(config->of_node); 3973a0c7b164SMark Brown } 3974a0c7b164SMark Brown 3975414c70cbSLiam Girdwood mutex_init(&rdev->mutex); 3976c172708dSMark Brown rdev->reg_data = config->driver_data; 3977414c70cbSLiam Girdwood rdev->owner = regulator_desc->owner; 3978414c70cbSLiam Girdwood rdev->desc = regulator_desc; 39793a4b0a07SMark Brown if (config->regmap) 398065b19ce6SMark Brown rdev->regmap = config->regmap; 398152b84dacSAnilKumar Ch else if (dev_get_regmap(dev, NULL)) 39823a4b0a07SMark Brown rdev->regmap = dev_get_regmap(dev, NULL); 398352b84dacSAnilKumar Ch else if (dev->parent) 398452b84dacSAnilKumar Ch rdev->regmap = dev_get_regmap(dev->parent, NULL); 3985414c70cbSLiam Girdwood INIT_LIST_HEAD(&rdev->consumer_list); 3986414c70cbSLiam Girdwood INIT_LIST_HEAD(&rdev->list); 3987414c70cbSLiam Girdwood BLOCKING_INIT_NOTIFIER_HEAD(&rdev->notifier); 3988da07ecd9SMark Brown INIT_DELAYED_WORK(&rdev->disable_work, regulator_disable_work); 3989414c70cbSLiam Girdwood 3990a5766f11SLiam Girdwood /* preform any regulator specific init */ 39919a8f5e07SMark Brown if (init_data && init_data->regulator_init) { 3992a5766f11SLiam Girdwood ret = init_data->regulator_init(rdev->reg_data); 39934fca9545SDavid Brownell if (ret < 0) 39944fca9545SDavid Brownell goto clean; 3995a5766f11SLiam Girdwood } 3996a5766f11SLiam Girdwood 3997daad134dSKrzysztof Adamski if ((config->ena_gpio || config->ena_gpio_initialized) && 3998daad134dSKrzysztof Adamski gpio_is_valid(config->ena_gpio)) { 399945389c47SJon Hunter mutex_lock(®ulator_list_mutex); 4000daad134dSKrzysztof Adamski ret = regulator_ena_gpio_request(rdev, config); 400145389c47SJon Hunter mutex_unlock(®ulator_list_mutex); 4002daad134dSKrzysztof Adamski if (ret != 0) { 4003daad134dSKrzysztof Adamski rdev_err(rdev, "Failed to request enable GPIO%d: %d\n", 4004daad134dSKrzysztof Adamski config->ena_gpio, ret); 400532165230SKrzysztof Adamski goto clean; 4006daad134dSKrzysztof Adamski } 4007daad134dSKrzysztof Adamski } 4008daad134dSKrzysztof Adamski 4009a5766f11SLiam Girdwood /* register with sysfs */ 4010a5766f11SLiam Girdwood rdev->dev.class = ®ulator_class; 4011a5766f11SLiam Girdwood rdev->dev.parent = dev; 401272dca06fSAniroop Mathur dev_set_name(&rdev->dev, "regulator.%lu", 401339138818SAniroop Mathur (unsigned long) atomic_inc_return(®ulator_no)); 4014a5766f11SLiam Girdwood 401574f544c1SMike Rapoport /* set regulator constraints */ 40169a8f5e07SMark Brown if (init_data) 40179a8f5e07SMark Brown constraints = &init_data->constraints; 40189a8f5e07SMark Brown 40199a8f5e07SMark Brown if (init_data && init_data->supply_regulator) 40206261b06dSBjorn Andersson rdev->supply_name = init_data->supply_regulator; 402169511a45SRajendra Nayak else if (regulator_desc->supply_name) 40226261b06dSBjorn Andersson rdev->supply_name = regulator_desc->supply_name; 402369511a45SRajendra Nayak 402445389c47SJon Hunter /* 402545389c47SJon Hunter * Attempt to resolve the regulator supply, if specified, 402645389c47SJon Hunter * but don't return an error if we fail because we will try 402745389c47SJon Hunter * to resolve it again later as more regulators are added. 402845389c47SJon Hunter */ 402945389c47SJon Hunter if (regulator_resolve_supply(rdev)) 403045389c47SJon Hunter rdev_dbg(rdev, "unable to resolve supply\n"); 403145389c47SJon Hunter 403245389c47SJon Hunter ret = set_machine_constraints(rdev, constraints); 403345389c47SJon Hunter if (ret < 0) 403445389c47SJon Hunter goto wash; 403545389c47SJon Hunter 4036a5766f11SLiam Girdwood /* add consumers devices */ 40379a8f5e07SMark Brown if (init_data) { 403845389c47SJon Hunter mutex_lock(®ulator_list_mutex); 4039a5766f11SLiam Girdwood for (i = 0; i < init_data->num_consumer_supplies; i++) { 4040a5766f11SLiam Girdwood ret = set_consumer_device_supply(rdev, 404140f9244fSMark Brown init_data->consumer_supplies[i].dev_name, 4042a5766f11SLiam Girdwood init_data->consumer_supplies[i].supply); 404323c2f041SMark Brown if (ret < 0) { 404445389c47SJon Hunter mutex_unlock(®ulator_list_mutex); 404523c2f041SMark Brown dev_err(dev, "Failed to set supply %s\n", 404623c2f041SMark Brown init_data->consumer_supplies[i].supply); 4047d4033b54SJani Nikula goto unset_supplies; 4048a5766f11SLiam Girdwood } 404923c2f041SMark Brown } 4050a2151374SJon Hunter mutex_unlock(®ulator_list_mutex); 40519a8f5e07SMark Brown } 4052a5766f11SLiam Girdwood 4053c438b9d0SJon Hunter ret = device_register(&rdev->dev); 4054c438b9d0SJon Hunter if (ret != 0) { 4055c438b9d0SJon Hunter put_device(&rdev->dev); 4056c438b9d0SJon Hunter goto unset_supplies; 4057c438b9d0SJon Hunter } 4058c438b9d0SJon Hunter 4059c438b9d0SJon Hunter dev_set_drvdata(&rdev->dev, rdev); 40601130e5b3SMark Brown rdev_init_debugfs(rdev); 40615e3ca2b3SJavier Martinez Canillas 40625e3ca2b3SJavier Martinez Canillas /* try to resolve regulators supply since a new one was registered */ 40635e3ca2b3SJavier Martinez Canillas class_for_each_device(®ulator_class, NULL, NULL, 40645e3ca2b3SJavier Martinez Canillas regulator_register_resolve_supply); 40651b3de223SKrzysztof Kozlowski kfree(config); 4066414c70cbSLiam Girdwood return rdev; 40674fca9545SDavid Brownell 4068d4033b54SJani Nikula unset_supplies: 406945389c47SJon Hunter mutex_lock(®ulator_list_mutex); 4070d4033b54SJani Nikula unset_regulator_supplies(rdev); 407145389c47SJon Hunter mutex_unlock(®ulator_list_mutex); 407232165230SKrzysztof Adamski wash: 4073469b640eSBoris Brezillon kfree(rdev->constraints); 407445389c47SJon Hunter mutex_lock(®ulator_list_mutex); 407532165230SKrzysztof Adamski regulator_ena_gpio_free(rdev); 407645389c47SJon Hunter mutex_unlock(®ulator_list_mutex); 40774fca9545SDavid Brownell clean: 40784fca9545SDavid Brownell kfree(rdev); 4079a2151374SJon Hunter kfree(config); 4080a2151374SJon Hunter return ERR_PTR(ret); 4081414c70cbSLiam Girdwood } 4082414c70cbSLiam Girdwood EXPORT_SYMBOL_GPL(regulator_register); 4083414c70cbSLiam Girdwood 4084414c70cbSLiam Girdwood /** 4085414c70cbSLiam Girdwood * regulator_unregister - unregister regulator 408669279fb9SMark Brown * @rdev: regulator to unregister 4087414c70cbSLiam Girdwood * 4088414c70cbSLiam Girdwood * Called by regulator drivers to unregister a regulator. 4089414c70cbSLiam Girdwood */ 4090414c70cbSLiam Girdwood void regulator_unregister(struct regulator_dev *rdev) 4091414c70cbSLiam Girdwood { 4092414c70cbSLiam Girdwood if (rdev == NULL) 4093414c70cbSLiam Girdwood return; 4094414c70cbSLiam Girdwood 4095891636eaSMark Brown if (rdev->supply) { 4096891636eaSMark Brown while (rdev->use_count--) 4097891636eaSMark Brown regulator_disable(rdev->supply); 4098e032b376SMark Brown regulator_put(rdev->supply); 4099891636eaSMark Brown } 4100414c70cbSLiam Girdwood mutex_lock(®ulator_list_mutex); 41011130e5b3SMark Brown debugfs_remove_recursive(rdev->debugfs); 410243829731STejun Heo flush_work(&rdev->disable_work.work); 41036bf87d17SMark Brown WARN_ON(rdev->open_count); 41040f1d747bSMike Rapoport unset_regulator_supplies(rdev); 4105414c70cbSLiam Girdwood list_del(&rdev->list); 4106f19b00daSKim, Milo regulator_ena_gpio_free(rdev); 41072c0a303aSMark Brown mutex_unlock(®ulator_list_mutex); 410858fb5cf5SLothar Waßmann device_unregister(&rdev->dev); 4109414c70cbSLiam Girdwood } 4110414c70cbSLiam Girdwood EXPORT_SYMBOL_GPL(regulator_unregister); 4111414c70cbSLiam Girdwood 411285f3b431STomeu Vizoso static int _regulator_suspend_prepare(struct device *dev, void *data) 411385f3b431STomeu Vizoso { 411485f3b431STomeu Vizoso struct regulator_dev *rdev = dev_to_rdev(dev); 411585f3b431STomeu Vizoso const suspend_state_t *state = data; 411685f3b431STomeu Vizoso int ret; 411785f3b431STomeu Vizoso 411885f3b431STomeu Vizoso mutex_lock(&rdev->mutex); 411985f3b431STomeu Vizoso ret = suspend_prepare(rdev, *state); 412085f3b431STomeu Vizoso mutex_unlock(&rdev->mutex); 412185f3b431STomeu Vizoso 412285f3b431STomeu Vizoso return ret; 412385f3b431STomeu Vizoso } 412485f3b431STomeu Vizoso 4125414c70cbSLiam Girdwood /** 4126cf7bbcdfSMark Brown * regulator_suspend_prepare - prepare regulators for system wide suspend 4127414c70cbSLiam Girdwood * @state: system suspend state 4128414c70cbSLiam Girdwood * 4129414c70cbSLiam Girdwood * Configure each regulator with it's suspend operating parameters for state. 4130414c70cbSLiam Girdwood * This will usually be called by machine suspend code prior to supending. 4131414c70cbSLiam Girdwood */ 4132414c70cbSLiam Girdwood int regulator_suspend_prepare(suspend_state_t state) 4133414c70cbSLiam Girdwood { 4134414c70cbSLiam Girdwood /* ON is handled by regulator active state */ 4135414c70cbSLiam Girdwood if (state == PM_SUSPEND_ON) 4136414c70cbSLiam Girdwood return -EINVAL; 4137414c70cbSLiam Girdwood 413885f3b431STomeu Vizoso return class_for_each_device(®ulator_class, NULL, &state, 413985f3b431STomeu Vizoso _regulator_suspend_prepare); 4140414c70cbSLiam Girdwood } 4141414c70cbSLiam Girdwood EXPORT_SYMBOL_GPL(regulator_suspend_prepare); 4142414c70cbSLiam Girdwood 414385f3b431STomeu Vizoso static int _regulator_suspend_finish(struct device *dev, void *data) 414485f3b431STomeu Vizoso { 414585f3b431STomeu Vizoso struct regulator_dev *rdev = dev_to_rdev(dev); 414685f3b431STomeu Vizoso int ret; 414785f3b431STomeu Vizoso 414885f3b431STomeu Vizoso mutex_lock(&rdev->mutex); 414985f3b431STomeu Vizoso if (rdev->use_count > 0 || rdev->constraints->always_on) { 415085f3b431STomeu Vizoso if (!_regulator_is_enabled(rdev)) { 415185f3b431STomeu Vizoso ret = _regulator_do_enable(rdev); 415285f3b431STomeu Vizoso if (ret) 415385f3b431STomeu Vizoso dev_err(dev, 415485f3b431STomeu Vizoso "Failed to resume regulator %d\n", 415585f3b431STomeu Vizoso ret); 415685f3b431STomeu Vizoso } 415785f3b431STomeu Vizoso } else { 415885f3b431STomeu Vizoso if (!have_full_constraints()) 415985f3b431STomeu Vizoso goto unlock; 416085f3b431STomeu Vizoso if (!_regulator_is_enabled(rdev)) 416185f3b431STomeu Vizoso goto unlock; 416285f3b431STomeu Vizoso 416385f3b431STomeu Vizoso ret = _regulator_do_disable(rdev); 416485f3b431STomeu Vizoso if (ret) 416585f3b431STomeu Vizoso dev_err(dev, "Failed to suspend regulator %d\n", ret); 416685f3b431STomeu Vizoso } 416785f3b431STomeu Vizoso unlock: 416885f3b431STomeu Vizoso mutex_unlock(&rdev->mutex); 416985f3b431STomeu Vizoso 417085f3b431STomeu Vizoso /* Keep processing regulators in spite of any errors */ 417185f3b431STomeu Vizoso return 0; 417285f3b431STomeu Vizoso } 417385f3b431STomeu Vizoso 4174414c70cbSLiam Girdwood /** 41757a32b589SMyungJoo Ham * regulator_suspend_finish - resume regulators from system wide suspend 41767a32b589SMyungJoo Ham * 41777a32b589SMyungJoo Ham * Turn on regulators that might be turned off by regulator_suspend_prepare 41787a32b589SMyungJoo Ham * and that should be turned on according to the regulators properties. 41797a32b589SMyungJoo Ham */ 41807a32b589SMyungJoo Ham int regulator_suspend_finish(void) 41817a32b589SMyungJoo Ham { 418285f3b431STomeu Vizoso return class_for_each_device(®ulator_class, NULL, NULL, 418385f3b431STomeu Vizoso _regulator_suspend_finish); 41847a32b589SMyungJoo Ham } 41857a32b589SMyungJoo Ham EXPORT_SYMBOL_GPL(regulator_suspend_finish); 41867a32b589SMyungJoo Ham 41877a32b589SMyungJoo Ham /** 4188ca725561SMark Brown * regulator_has_full_constraints - the system has fully specified constraints 4189ca725561SMark Brown * 4190ca725561SMark Brown * Calling this function will cause the regulator API to disable all 4191ca725561SMark Brown * regulators which have a zero use count and don't have an always_on 4192ca725561SMark Brown * constraint in a late_initcall. 4193ca725561SMark Brown * 4194ca725561SMark Brown * The intention is that this will become the default behaviour in a 4195ca725561SMark Brown * future kernel release so users are encouraged to use this facility 4196ca725561SMark Brown * now. 4197ca725561SMark Brown */ 4198ca725561SMark Brown void regulator_has_full_constraints(void) 4199ca725561SMark Brown { 4200ca725561SMark Brown has_full_constraints = 1; 4201ca725561SMark Brown } 4202ca725561SMark Brown EXPORT_SYMBOL_GPL(regulator_has_full_constraints); 4203ca725561SMark Brown 4204ca725561SMark Brown /** 4205414c70cbSLiam Girdwood * rdev_get_drvdata - get rdev regulator driver data 420669279fb9SMark Brown * @rdev: regulator 4207414c70cbSLiam Girdwood * 4208414c70cbSLiam Girdwood * Get rdev regulator driver private data. This call can be used in the 4209414c70cbSLiam Girdwood * regulator driver context. 4210414c70cbSLiam Girdwood */ 4211414c70cbSLiam Girdwood void *rdev_get_drvdata(struct regulator_dev *rdev) 4212414c70cbSLiam Girdwood { 4213414c70cbSLiam Girdwood return rdev->reg_data; 4214414c70cbSLiam Girdwood } 4215414c70cbSLiam Girdwood EXPORT_SYMBOL_GPL(rdev_get_drvdata); 4216414c70cbSLiam Girdwood 4217414c70cbSLiam Girdwood /** 4218414c70cbSLiam Girdwood * regulator_get_drvdata - get regulator driver data 4219414c70cbSLiam Girdwood * @regulator: regulator 4220414c70cbSLiam Girdwood * 4221414c70cbSLiam Girdwood * Get regulator driver private data. This call can be used in the consumer 4222414c70cbSLiam Girdwood * driver context when non API regulator specific functions need to be called. 4223414c70cbSLiam Girdwood */ 4224414c70cbSLiam Girdwood void *regulator_get_drvdata(struct regulator *regulator) 4225414c70cbSLiam Girdwood { 4226414c70cbSLiam Girdwood return regulator->rdev->reg_data; 4227414c70cbSLiam Girdwood } 4228414c70cbSLiam Girdwood EXPORT_SYMBOL_GPL(regulator_get_drvdata); 4229414c70cbSLiam Girdwood 4230414c70cbSLiam Girdwood /** 4231414c70cbSLiam Girdwood * regulator_set_drvdata - set regulator driver data 4232414c70cbSLiam Girdwood * @regulator: regulator 4233414c70cbSLiam Girdwood * @data: data 4234414c70cbSLiam Girdwood */ 4235414c70cbSLiam Girdwood void regulator_set_drvdata(struct regulator *regulator, void *data) 4236414c70cbSLiam Girdwood { 4237414c70cbSLiam Girdwood regulator->rdev->reg_data = data; 4238414c70cbSLiam Girdwood } 4239414c70cbSLiam Girdwood EXPORT_SYMBOL_GPL(regulator_set_drvdata); 4240414c70cbSLiam Girdwood 4241414c70cbSLiam Girdwood /** 4242414c70cbSLiam Girdwood * regulator_get_id - get regulator ID 424369279fb9SMark Brown * @rdev: regulator 4244414c70cbSLiam Girdwood */ 4245414c70cbSLiam Girdwood int rdev_get_id(struct regulator_dev *rdev) 4246414c70cbSLiam Girdwood { 4247414c70cbSLiam Girdwood return rdev->desc->id; 4248414c70cbSLiam Girdwood } 4249414c70cbSLiam Girdwood EXPORT_SYMBOL_GPL(rdev_get_id); 4250414c70cbSLiam Girdwood 4251a5766f11SLiam Girdwood struct device *rdev_get_dev(struct regulator_dev *rdev) 4252a5766f11SLiam Girdwood { 4253a5766f11SLiam Girdwood return &rdev->dev; 4254a5766f11SLiam Girdwood } 4255a5766f11SLiam Girdwood EXPORT_SYMBOL_GPL(rdev_get_dev); 4256a5766f11SLiam Girdwood 4257a5766f11SLiam Girdwood void *regulator_get_init_drvdata(struct regulator_init_data *reg_init_data) 4258a5766f11SLiam Girdwood { 4259a5766f11SLiam Girdwood return reg_init_data->driver_data; 4260a5766f11SLiam Girdwood } 4261a5766f11SLiam Girdwood EXPORT_SYMBOL_GPL(regulator_get_init_drvdata); 4262a5766f11SLiam Girdwood 4263ba55a974SMark Brown #ifdef CONFIG_DEBUG_FS 4264ba55a974SMark Brown static ssize_t supply_map_read_file(struct file *file, char __user *user_buf, 4265ba55a974SMark Brown size_t count, loff_t *ppos) 4266ba55a974SMark Brown { 4267ba55a974SMark Brown char *buf = kmalloc(PAGE_SIZE, GFP_KERNEL); 4268ba55a974SMark Brown ssize_t len, ret = 0; 4269ba55a974SMark Brown struct regulator_map *map; 4270ba55a974SMark Brown 4271ba55a974SMark Brown if (!buf) 4272ba55a974SMark Brown return -ENOMEM; 4273ba55a974SMark Brown 4274ba55a974SMark Brown list_for_each_entry(map, ®ulator_map_list, list) { 4275ba55a974SMark Brown len = snprintf(buf + ret, PAGE_SIZE - ret, 4276ba55a974SMark Brown "%s -> %s.%s\n", 4277ba55a974SMark Brown rdev_get_name(map->regulator), map->dev_name, 4278ba55a974SMark Brown map->supply); 4279ba55a974SMark Brown if (len >= 0) 4280ba55a974SMark Brown ret += len; 4281ba55a974SMark Brown if (ret > PAGE_SIZE) { 4282ba55a974SMark Brown ret = PAGE_SIZE; 4283ba55a974SMark Brown break; 4284ba55a974SMark Brown } 4285ba55a974SMark Brown } 4286ba55a974SMark Brown 4287ba55a974SMark Brown ret = simple_read_from_buffer(user_buf, count, ppos, buf, ret); 4288ba55a974SMark Brown 4289ba55a974SMark Brown kfree(buf); 4290ba55a974SMark Brown 4291ba55a974SMark Brown return ret; 4292ba55a974SMark Brown } 429324751434SStephen Boyd #endif 4294ba55a974SMark Brown 4295ba55a974SMark Brown static const struct file_operations supply_map_fops = { 429624751434SStephen Boyd #ifdef CONFIG_DEBUG_FS 4297ba55a974SMark Brown .read = supply_map_read_file, 4298ba55a974SMark Brown .llseek = default_llseek, 4299ba55a974SMark Brown #endif 430024751434SStephen Boyd }; 4301ba55a974SMark Brown 43027c225ec9SHeiko Stübner #ifdef CONFIG_DEBUG_FS 430385f3b431STomeu Vizoso struct summary_data { 430485f3b431STomeu Vizoso struct seq_file *s; 430585f3b431STomeu Vizoso struct regulator_dev *parent; 430685f3b431STomeu Vizoso int level; 430785f3b431STomeu Vizoso }; 430885f3b431STomeu Vizoso 430985f3b431STomeu Vizoso static void regulator_summary_show_subtree(struct seq_file *s, 431085f3b431STomeu Vizoso struct regulator_dev *rdev, 431185f3b431STomeu Vizoso int level); 431285f3b431STomeu Vizoso 431385f3b431STomeu Vizoso static int regulator_summary_show_children(struct device *dev, void *data) 431485f3b431STomeu Vizoso { 431585f3b431STomeu Vizoso struct regulator_dev *rdev = dev_to_rdev(dev); 431685f3b431STomeu Vizoso struct summary_data *summary_data = data; 431785f3b431STomeu Vizoso 431885f3b431STomeu Vizoso if (rdev->supply && rdev->supply->rdev == summary_data->parent) 431985f3b431STomeu Vizoso regulator_summary_show_subtree(summary_data->s, rdev, 432085f3b431STomeu Vizoso summary_data->level + 1); 432185f3b431STomeu Vizoso 432285f3b431STomeu Vizoso return 0; 432385f3b431STomeu Vizoso } 432485f3b431STomeu Vizoso 43257c225ec9SHeiko Stübner static void regulator_summary_show_subtree(struct seq_file *s, 43267c225ec9SHeiko Stübner struct regulator_dev *rdev, 43277c225ec9SHeiko Stübner int level) 43287c225ec9SHeiko Stübner { 43297c225ec9SHeiko Stübner struct regulation_constraints *c; 43307c225ec9SHeiko Stübner struct regulator *consumer; 433185f3b431STomeu Vizoso struct summary_data summary_data; 43327c225ec9SHeiko Stübner 43337c225ec9SHeiko Stübner if (!rdev) 43347c225ec9SHeiko Stübner return; 43357c225ec9SHeiko Stübner 43367c225ec9SHeiko Stübner seq_printf(s, "%*s%-*s %3d %4d %6d ", 43377c225ec9SHeiko Stübner level * 3 + 1, "", 43387c225ec9SHeiko Stübner 30 - level * 3, rdev_get_name(rdev), 43397c225ec9SHeiko Stübner rdev->use_count, rdev->open_count, rdev->bypass_count); 43407c225ec9SHeiko Stübner 434123296099SHeiko Stübner seq_printf(s, "%5dmV ", _regulator_get_voltage(rdev) / 1000); 434223296099SHeiko Stübner seq_printf(s, "%5dmA ", _regulator_get_current_limit(rdev) / 1000); 43437c225ec9SHeiko Stübner 43447c225ec9SHeiko Stübner c = rdev->constraints; 43457c225ec9SHeiko Stübner if (c) { 43467c225ec9SHeiko Stübner switch (rdev->desc->type) { 43477c225ec9SHeiko Stübner case REGULATOR_VOLTAGE: 43487c225ec9SHeiko Stübner seq_printf(s, "%5dmV %5dmV ", 43497c225ec9SHeiko Stübner c->min_uV / 1000, c->max_uV / 1000); 43507c225ec9SHeiko Stübner break; 43517c225ec9SHeiko Stübner case REGULATOR_CURRENT: 43527c225ec9SHeiko Stübner seq_printf(s, "%5dmA %5dmA ", 43537c225ec9SHeiko Stübner c->min_uA / 1000, c->max_uA / 1000); 43547c225ec9SHeiko Stübner break; 43557c225ec9SHeiko Stübner } 43567c225ec9SHeiko Stübner } 43577c225ec9SHeiko Stübner 43587c225ec9SHeiko Stübner seq_puts(s, "\n"); 43597c225ec9SHeiko Stübner 43607c225ec9SHeiko Stübner list_for_each_entry(consumer, &rdev->consumer_list, list) { 43617c225ec9SHeiko Stübner if (consumer->dev->class == ®ulator_class) 43627c225ec9SHeiko Stübner continue; 43637c225ec9SHeiko Stübner 43647c225ec9SHeiko Stübner seq_printf(s, "%*s%-*s ", 43657c225ec9SHeiko Stübner (level + 1) * 3 + 1, "", 43667c225ec9SHeiko Stübner 30 - (level + 1) * 3, dev_name(consumer->dev)); 43677c225ec9SHeiko Stübner 43687c225ec9SHeiko Stübner switch (rdev->desc->type) { 43697c225ec9SHeiko Stübner case REGULATOR_VOLTAGE: 437023296099SHeiko Stübner seq_printf(s, "%37dmV %5dmV", 43717c225ec9SHeiko Stübner consumer->min_uV / 1000, 43727c225ec9SHeiko Stübner consumer->max_uV / 1000); 43737c225ec9SHeiko Stübner break; 43747c225ec9SHeiko Stübner case REGULATOR_CURRENT: 43757c225ec9SHeiko Stübner break; 43767c225ec9SHeiko Stübner } 43777c225ec9SHeiko Stübner 43787c225ec9SHeiko Stübner seq_puts(s, "\n"); 43797c225ec9SHeiko Stübner } 43807c225ec9SHeiko Stübner 438185f3b431STomeu Vizoso summary_data.s = s; 438285f3b431STomeu Vizoso summary_data.level = level; 438385f3b431STomeu Vizoso summary_data.parent = rdev; 43847c225ec9SHeiko Stübner 438585f3b431STomeu Vizoso class_for_each_device(®ulator_class, NULL, &summary_data, 438685f3b431STomeu Vizoso regulator_summary_show_children); 43877c225ec9SHeiko Stübner } 438885f3b431STomeu Vizoso 438985f3b431STomeu Vizoso static int regulator_summary_show_roots(struct device *dev, void *data) 439085f3b431STomeu Vizoso { 439185f3b431STomeu Vizoso struct regulator_dev *rdev = dev_to_rdev(dev); 439285f3b431STomeu Vizoso struct seq_file *s = data; 439385f3b431STomeu Vizoso 439485f3b431STomeu Vizoso if (!rdev->supply) 439585f3b431STomeu Vizoso regulator_summary_show_subtree(s, rdev, 0); 439685f3b431STomeu Vizoso 439785f3b431STomeu Vizoso return 0; 43987c225ec9SHeiko Stübner } 43997c225ec9SHeiko Stübner 44007c225ec9SHeiko Stübner static int regulator_summary_show(struct seq_file *s, void *data) 44017c225ec9SHeiko Stübner { 440223296099SHeiko Stübner seq_puts(s, " regulator use open bypass voltage current min max\n"); 440323296099SHeiko Stübner seq_puts(s, "-------------------------------------------------------------------------------\n"); 44047c225ec9SHeiko Stübner 440585f3b431STomeu Vizoso class_for_each_device(®ulator_class, NULL, s, 440685f3b431STomeu Vizoso regulator_summary_show_roots); 44077c225ec9SHeiko Stübner 44087c225ec9SHeiko Stübner return 0; 44097c225ec9SHeiko Stübner } 44107c225ec9SHeiko Stübner 44117c225ec9SHeiko Stübner static int regulator_summary_open(struct inode *inode, struct file *file) 44127c225ec9SHeiko Stübner { 44137c225ec9SHeiko Stübner return single_open(file, regulator_summary_show, inode->i_private); 44147c225ec9SHeiko Stübner } 44157c225ec9SHeiko Stübner #endif 44167c225ec9SHeiko Stübner 44177c225ec9SHeiko Stübner static const struct file_operations regulator_summary_fops = { 44187c225ec9SHeiko Stübner #ifdef CONFIG_DEBUG_FS 44197c225ec9SHeiko Stübner .open = regulator_summary_open, 44207c225ec9SHeiko Stübner .read = seq_read, 44217c225ec9SHeiko Stübner .llseek = seq_lseek, 44227c225ec9SHeiko Stübner .release = single_release, 44237c225ec9SHeiko Stübner #endif 44247c225ec9SHeiko Stübner }; 44257c225ec9SHeiko Stübner 4426414c70cbSLiam Girdwood static int __init regulator_init(void) 4427414c70cbSLiam Girdwood { 442834abbd68SMark Brown int ret; 442934abbd68SMark Brown 443034abbd68SMark Brown ret = class_register(®ulator_class); 443134abbd68SMark Brown 44321130e5b3SMark Brown debugfs_root = debugfs_create_dir("regulator", NULL); 443324751434SStephen Boyd if (!debugfs_root) 44341130e5b3SMark Brown pr_warn("regulator: Failed to create debugfs directory\n"); 4435ba55a974SMark Brown 4436f4d562c6SMark Brown debugfs_create_file("supply_map", 0444, debugfs_root, NULL, 4437f4d562c6SMark Brown &supply_map_fops); 44381130e5b3SMark Brown 44397c225ec9SHeiko Stübner debugfs_create_file("regulator_summary", 0444, debugfs_root, 444085f3b431STomeu Vizoso NULL, ®ulator_summary_fops); 44417c225ec9SHeiko Stübner 444234abbd68SMark Brown regulator_dummy_init(); 444334abbd68SMark Brown 444434abbd68SMark Brown return ret; 4445414c70cbSLiam Girdwood } 4446414c70cbSLiam Girdwood 4447414c70cbSLiam Girdwood /* init early to allow our consumers to complete system booting */ 4448414c70cbSLiam Girdwood core_initcall(regulator_init); 4449ca725561SMark Brown 4450609ca5f3SMark Brown static int __init regulator_late_cleanup(struct device *dev, void *data) 4451ca725561SMark Brown { 4452609ca5f3SMark Brown struct regulator_dev *rdev = dev_to_rdev(dev); 4453609ca5f3SMark Brown const struct regulator_ops *ops = rdev->desc->ops; 4454609ca5f3SMark Brown struct regulation_constraints *c = rdev->constraints; 4455ca725561SMark Brown int enabled, ret; 4456ca725561SMark Brown 445766fda75fSMarkus Pargmann if (c && c->always_on) 4458609ca5f3SMark Brown return 0; 4459ca725561SMark Brown 44608a34e979SWEN Pingbo if (!regulator_ops_is_valid(rdev, REGULATOR_CHANGE_STATUS)) 4461609ca5f3SMark Brown return 0; 4462e9535834SMark Brown 4463ca725561SMark Brown mutex_lock(&rdev->mutex); 4464ca725561SMark Brown 4465ca725561SMark Brown if (rdev->use_count) 4466ca725561SMark Brown goto unlock; 4467ca725561SMark Brown 4468ca725561SMark Brown /* If we can't read the status assume it's on. */ 4469ca725561SMark Brown if (ops->is_enabled) 4470ca725561SMark Brown enabled = ops->is_enabled(rdev); 4471ca725561SMark Brown else 4472ca725561SMark Brown enabled = 1; 4473ca725561SMark Brown 4474ca725561SMark Brown if (!enabled) 4475ca725561SMark Brown goto unlock; 4476ca725561SMark Brown 447787b28417SMark Brown if (have_full_constraints()) { 4478609ca5f3SMark Brown /* We log since this may kill the system if it goes 4479609ca5f3SMark Brown * wrong. */ 44805da84fd9SJoe Perches rdev_info(rdev, "disabling\n"); 448166fda75fSMarkus Pargmann ret = _regulator_do_disable(rdev); 44820d25d09dSJingoo Han if (ret != 0) 44835da84fd9SJoe Perches rdev_err(rdev, "couldn't disable: %d\n", ret); 4484ca725561SMark Brown } else { 4485ca725561SMark Brown /* The intention is that in future we will 4486ca725561SMark Brown * assume that full constraints are provided 4487ca725561SMark Brown * so warn even if we aren't going to do 4488ca725561SMark Brown * anything here. 4489ca725561SMark Brown */ 44905da84fd9SJoe Perches rdev_warn(rdev, "incomplete constraints, leaving on\n"); 4491ca725561SMark Brown } 4492ca725561SMark Brown 4493ca725561SMark Brown unlock: 4494ca725561SMark Brown mutex_unlock(&rdev->mutex); 4495609ca5f3SMark Brown 4496609ca5f3SMark Brown return 0; 4497ca725561SMark Brown } 4498ca725561SMark Brown 4499609ca5f3SMark Brown static int __init regulator_init_complete(void) 4500609ca5f3SMark Brown { 4501609ca5f3SMark Brown /* 4502609ca5f3SMark Brown * Since DT doesn't provide an idiomatic mechanism for 4503609ca5f3SMark Brown * enabling full constraints and since it's much more natural 4504609ca5f3SMark Brown * with DT to provide them just assume that a DT enabled 4505609ca5f3SMark Brown * system has full constraints. 4506609ca5f3SMark Brown */ 4507609ca5f3SMark Brown if (of_have_populated_dt()) 4508609ca5f3SMark Brown has_full_constraints = true; 4509609ca5f3SMark Brown 4510609ca5f3SMark Brown /* If we have a full configuration then disable any regulators 4511609ca5f3SMark Brown * we have permission to change the status for and which are 4512609ca5f3SMark Brown * not in use or always_on. This is effectively the default 4513609ca5f3SMark Brown * for DT and ACPI as they have full constraints. 4514609ca5f3SMark Brown */ 4515609ca5f3SMark Brown class_for_each_device(®ulator_class, NULL, NULL, 4516609ca5f3SMark Brown regulator_late_cleanup); 4517ca725561SMark Brown 4518ca725561SMark Brown return 0; 4519ca725561SMark Brown } 4520fd482a3eSSaravana Kannan late_initcall_sync(regulator_init_complete); 4521