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 13570a7fb80SThierry Reding static inline struct regulator_dev *rdev_get_supply(struct regulator_dev *rdev) 13670a7fb80SThierry Reding { 13770a7fb80SThierry Reding if (rdev && rdev->supply) 13870a7fb80SThierry Reding return rdev->supply->rdev; 13970a7fb80SThierry Reding 14070a7fb80SThierry Reding return NULL; 14170a7fb80SThierry Reding } 14270a7fb80SThierry Reding 14369511a45SRajendra Nayak /** 1449f01cd4aSSascha Hauer * regulator_lock_supply - lock a regulator and its supplies 1459f01cd4aSSascha Hauer * @rdev: regulator source 1469f01cd4aSSascha Hauer */ 1479f01cd4aSSascha Hauer static void regulator_lock_supply(struct regulator_dev *rdev) 1489f01cd4aSSascha Hauer { 149fa731ac7SArnd Bergmann int i; 1509f01cd4aSSascha Hauer 15170a7fb80SThierry Reding for (i = 0; rdev; rdev = rdev_get_supply(rdev), i++) 152fa731ac7SArnd Bergmann mutex_lock_nested(&rdev->mutex, i); 1539f01cd4aSSascha Hauer } 1549f01cd4aSSascha Hauer 1559f01cd4aSSascha Hauer /** 1569f01cd4aSSascha Hauer * regulator_unlock_supply - unlock a regulator and its supplies 1579f01cd4aSSascha Hauer * @rdev: regulator source 1589f01cd4aSSascha Hauer */ 1599f01cd4aSSascha Hauer static void regulator_unlock_supply(struct regulator_dev *rdev) 1609f01cd4aSSascha Hauer { 1619f01cd4aSSascha Hauer struct regulator *supply; 1629f01cd4aSSascha Hauer 1639f01cd4aSSascha Hauer while (1) { 1649f01cd4aSSascha Hauer mutex_unlock(&rdev->mutex); 1659f01cd4aSSascha Hauer supply = rdev->supply; 1669f01cd4aSSascha Hauer 1679f01cd4aSSascha Hauer if (!rdev->supply) 1689f01cd4aSSascha Hauer return; 1699f01cd4aSSascha Hauer 1709f01cd4aSSascha Hauer rdev = supply->rdev; 1719f01cd4aSSascha Hauer } 1729f01cd4aSSascha Hauer } 1739f01cd4aSSascha Hauer 1749f01cd4aSSascha Hauer /** 17569511a45SRajendra Nayak * of_get_regulator - get a regulator device node based on supply name 17669511a45SRajendra Nayak * @dev: Device pointer for the consumer (of regulator) device 17769511a45SRajendra Nayak * @supply: regulator supply name 17869511a45SRajendra Nayak * 17969511a45SRajendra Nayak * Extract the regulator device node corresponding to the supply name. 180167d41dcSMaxime Ripard * returns the device node corresponding to the regulator if found, else 18169511a45SRajendra Nayak * returns NULL. 18269511a45SRajendra Nayak */ 18369511a45SRajendra Nayak static struct device_node *of_get_regulator(struct device *dev, const char *supply) 18469511a45SRajendra Nayak { 18569511a45SRajendra Nayak struct device_node *regnode = NULL; 18669511a45SRajendra Nayak char prop_name[32]; /* 32 is max size of property name */ 18769511a45SRajendra Nayak 18869511a45SRajendra Nayak dev_dbg(dev, "Looking up %s-supply from device tree\n", supply); 18969511a45SRajendra Nayak 19069511a45SRajendra Nayak snprintf(prop_name, 32, "%s-supply", supply); 19169511a45SRajendra Nayak regnode = of_parse_phandle(dev->of_node, prop_name, 0); 19269511a45SRajendra Nayak 19369511a45SRajendra Nayak if (!regnode) { 19416fbcc3bSRajendra Nayak dev_dbg(dev, "Looking up %s property in node %s failed", 19569511a45SRajendra Nayak prop_name, dev->of_node->full_name); 19669511a45SRajendra Nayak return NULL; 19769511a45SRajendra Nayak } 19869511a45SRajendra Nayak return regnode; 19969511a45SRajendra Nayak } 20069511a45SRajendra Nayak 2016492bc1bSMark Brown static int _regulator_can_change_status(struct regulator_dev *rdev) 2026492bc1bSMark Brown { 2036492bc1bSMark Brown if (!rdev->constraints) 2046492bc1bSMark Brown return 0; 2056492bc1bSMark Brown 2066492bc1bSMark Brown if (rdev->constraints->valid_ops_mask & REGULATOR_CHANGE_STATUS) 2076492bc1bSMark Brown return 1; 2086492bc1bSMark Brown else 2096492bc1bSMark Brown return 0; 2106492bc1bSMark Brown } 2116492bc1bSMark Brown 212414c70cbSLiam Girdwood /* Platform voltage constraint check */ 213414c70cbSLiam Girdwood static int regulator_check_voltage(struct regulator_dev *rdev, 214414c70cbSLiam Girdwood int *min_uV, int *max_uV) 215414c70cbSLiam Girdwood { 216414c70cbSLiam Girdwood BUG_ON(*min_uV > *max_uV); 217414c70cbSLiam Girdwood 218414c70cbSLiam Girdwood if (!rdev->constraints) { 2195da84fd9SJoe Perches rdev_err(rdev, "no constraints\n"); 220414c70cbSLiam Girdwood return -ENODEV; 221414c70cbSLiam Girdwood } 222414c70cbSLiam Girdwood if (!(rdev->constraints->valid_ops_mask & REGULATOR_CHANGE_VOLTAGE)) { 2237ebcf26cSStephen Boyd rdev_err(rdev, "voltage operation not allowed\n"); 224414c70cbSLiam Girdwood return -EPERM; 225414c70cbSLiam Girdwood } 226414c70cbSLiam Girdwood 227414c70cbSLiam Girdwood if (*max_uV > rdev->constraints->max_uV) 228414c70cbSLiam Girdwood *max_uV = rdev->constraints->max_uV; 229414c70cbSLiam Girdwood if (*min_uV < rdev->constraints->min_uV) 230414c70cbSLiam Girdwood *min_uV = rdev->constraints->min_uV; 231414c70cbSLiam Girdwood 23289f425edSMark Brown if (*min_uV > *max_uV) { 23389f425edSMark Brown rdev_err(rdev, "unsupportable voltage range: %d-%duV\n", 23454abd335SMark Brown *min_uV, *max_uV); 235414c70cbSLiam Girdwood return -EINVAL; 23689f425edSMark Brown } 237414c70cbSLiam Girdwood 238414c70cbSLiam Girdwood return 0; 239414c70cbSLiam Girdwood } 240414c70cbSLiam Girdwood 24105fda3b1SThomas Petazzoni /* Make sure we select a voltage that suits the needs of all 24205fda3b1SThomas Petazzoni * regulator consumers 24305fda3b1SThomas Petazzoni */ 24405fda3b1SThomas Petazzoni static int regulator_check_consumers(struct regulator_dev *rdev, 24505fda3b1SThomas Petazzoni int *min_uV, int *max_uV) 24605fda3b1SThomas Petazzoni { 24705fda3b1SThomas Petazzoni struct regulator *regulator; 24805fda3b1SThomas Petazzoni 24905fda3b1SThomas Petazzoni list_for_each_entry(regulator, &rdev->consumer_list, list) { 2504aa922c0SMark Brown /* 2514aa922c0SMark Brown * Assume consumers that didn't say anything are OK 2524aa922c0SMark Brown * with anything in the constraint range. 2534aa922c0SMark Brown */ 2544aa922c0SMark Brown if (!regulator->min_uV && !regulator->max_uV) 2554aa922c0SMark Brown continue; 2564aa922c0SMark Brown 25705fda3b1SThomas Petazzoni if (*max_uV > regulator->max_uV) 25805fda3b1SThomas Petazzoni *max_uV = regulator->max_uV; 25905fda3b1SThomas Petazzoni if (*min_uV < regulator->min_uV) 26005fda3b1SThomas Petazzoni *min_uV = regulator->min_uV; 26105fda3b1SThomas Petazzoni } 26205fda3b1SThomas Petazzoni 263dd8004afSMark Brown if (*min_uV > *max_uV) { 2649c7b4e8aSRuss Dill rdev_err(rdev, "Restricting voltage, %u-%uuV\n", 2659c7b4e8aSRuss Dill *min_uV, *max_uV); 26605fda3b1SThomas Petazzoni return -EINVAL; 267dd8004afSMark Brown } 26805fda3b1SThomas Petazzoni 26905fda3b1SThomas Petazzoni return 0; 27005fda3b1SThomas Petazzoni } 27105fda3b1SThomas Petazzoni 272414c70cbSLiam Girdwood /* current constraint check */ 273414c70cbSLiam Girdwood static int regulator_check_current_limit(struct regulator_dev *rdev, 274414c70cbSLiam Girdwood int *min_uA, int *max_uA) 275414c70cbSLiam Girdwood { 276414c70cbSLiam Girdwood BUG_ON(*min_uA > *max_uA); 277414c70cbSLiam Girdwood 278414c70cbSLiam Girdwood if (!rdev->constraints) { 2795da84fd9SJoe Perches rdev_err(rdev, "no constraints\n"); 280414c70cbSLiam Girdwood return -ENODEV; 281414c70cbSLiam Girdwood } 282414c70cbSLiam Girdwood if (!(rdev->constraints->valid_ops_mask & REGULATOR_CHANGE_CURRENT)) { 2837ebcf26cSStephen Boyd rdev_err(rdev, "current operation not allowed\n"); 284414c70cbSLiam Girdwood return -EPERM; 285414c70cbSLiam Girdwood } 286414c70cbSLiam Girdwood 287414c70cbSLiam Girdwood if (*max_uA > rdev->constraints->max_uA) 288414c70cbSLiam Girdwood *max_uA = rdev->constraints->max_uA; 289414c70cbSLiam Girdwood if (*min_uA < rdev->constraints->min_uA) 290414c70cbSLiam Girdwood *min_uA = rdev->constraints->min_uA; 291414c70cbSLiam Girdwood 29289f425edSMark Brown if (*min_uA > *max_uA) { 29389f425edSMark Brown rdev_err(rdev, "unsupportable current range: %d-%duA\n", 29454abd335SMark Brown *min_uA, *max_uA); 295414c70cbSLiam Girdwood return -EINVAL; 29689f425edSMark Brown } 297414c70cbSLiam Girdwood 298414c70cbSLiam Girdwood return 0; 299414c70cbSLiam Girdwood } 300414c70cbSLiam Girdwood 301414c70cbSLiam Girdwood /* operating mode constraint check */ 3022c608234SMark Brown static int regulator_mode_constrain(struct regulator_dev *rdev, int *mode) 303414c70cbSLiam Girdwood { 3042c608234SMark Brown switch (*mode) { 305e573520bSDavid Brownell case REGULATOR_MODE_FAST: 306e573520bSDavid Brownell case REGULATOR_MODE_NORMAL: 307e573520bSDavid Brownell case REGULATOR_MODE_IDLE: 308e573520bSDavid Brownell case REGULATOR_MODE_STANDBY: 309e573520bSDavid Brownell break; 310e573520bSDavid Brownell default: 31189f425edSMark Brown rdev_err(rdev, "invalid mode %x specified\n", *mode); 312e573520bSDavid Brownell return -EINVAL; 313e573520bSDavid Brownell } 314e573520bSDavid Brownell 315414c70cbSLiam Girdwood if (!rdev->constraints) { 3165da84fd9SJoe Perches rdev_err(rdev, "no constraints\n"); 317414c70cbSLiam Girdwood return -ENODEV; 318414c70cbSLiam Girdwood } 319414c70cbSLiam Girdwood if (!(rdev->constraints->valid_ops_mask & REGULATOR_CHANGE_MODE)) { 3207ebcf26cSStephen Boyd rdev_err(rdev, "mode operation not allowed\n"); 321414c70cbSLiam Girdwood return -EPERM; 322414c70cbSLiam Girdwood } 3232c608234SMark Brown 3242c608234SMark Brown /* The modes are bitmasks, the most power hungry modes having 3252c608234SMark Brown * the lowest values. If the requested mode isn't supported 3262c608234SMark Brown * try higher modes. */ 3272c608234SMark Brown while (*mode) { 3282c608234SMark Brown if (rdev->constraints->valid_modes_mask & *mode) 329414c70cbSLiam Girdwood return 0; 3302c608234SMark Brown *mode /= 2; 3312c608234SMark Brown } 3322c608234SMark Brown 3332c608234SMark Brown return -EINVAL; 334414c70cbSLiam Girdwood } 335414c70cbSLiam Girdwood 336414c70cbSLiam Girdwood /* dynamic regulator mode switching constraint check */ 337414c70cbSLiam Girdwood static int regulator_check_drms(struct regulator_dev *rdev) 338414c70cbSLiam Girdwood { 339414c70cbSLiam Girdwood if (!rdev->constraints) { 3405da84fd9SJoe Perches rdev_err(rdev, "no constraints\n"); 341414c70cbSLiam Girdwood return -ENODEV; 342414c70cbSLiam Girdwood } 343414c70cbSLiam Girdwood if (!(rdev->constraints->valid_ops_mask & REGULATOR_CHANGE_DRMS)) { 3447ebcf26cSStephen Boyd rdev_dbg(rdev, "drms operation not allowed\n"); 345414c70cbSLiam Girdwood return -EPERM; 346414c70cbSLiam Girdwood } 347414c70cbSLiam Girdwood return 0; 348414c70cbSLiam Girdwood } 349414c70cbSLiam Girdwood 350414c70cbSLiam Girdwood static ssize_t regulator_uV_show(struct device *dev, 351414c70cbSLiam Girdwood struct device_attribute *attr, char *buf) 352414c70cbSLiam Girdwood { 353a5766f11SLiam Girdwood struct regulator_dev *rdev = dev_get_drvdata(dev); 354414c70cbSLiam Girdwood ssize_t ret; 355414c70cbSLiam Girdwood 356414c70cbSLiam Girdwood mutex_lock(&rdev->mutex); 357414c70cbSLiam Girdwood ret = sprintf(buf, "%d\n", _regulator_get_voltage(rdev)); 358414c70cbSLiam Girdwood mutex_unlock(&rdev->mutex); 359414c70cbSLiam Girdwood 360414c70cbSLiam Girdwood return ret; 361414c70cbSLiam Girdwood } 3627ad68e2fSDavid Brownell static DEVICE_ATTR(microvolts, 0444, regulator_uV_show, NULL); 363414c70cbSLiam Girdwood 364414c70cbSLiam Girdwood static ssize_t regulator_uA_show(struct device *dev, 365414c70cbSLiam Girdwood struct device_attribute *attr, char *buf) 366414c70cbSLiam Girdwood { 367a5766f11SLiam Girdwood struct regulator_dev *rdev = dev_get_drvdata(dev); 368414c70cbSLiam Girdwood 369414c70cbSLiam Girdwood return sprintf(buf, "%d\n", _regulator_get_current_limit(rdev)); 370414c70cbSLiam Girdwood } 3717ad68e2fSDavid Brownell static DEVICE_ATTR(microamps, 0444, regulator_uA_show, NULL); 372414c70cbSLiam Girdwood 373587cea27SGreg Kroah-Hartman static ssize_t name_show(struct device *dev, struct device_attribute *attr, 374587cea27SGreg Kroah-Hartman char *buf) 375bc558a60SMark Brown { 376bc558a60SMark Brown struct regulator_dev *rdev = dev_get_drvdata(dev); 377bc558a60SMark Brown 3781083c393SMark Brown return sprintf(buf, "%s\n", rdev_get_name(rdev)); 379bc558a60SMark Brown } 380587cea27SGreg Kroah-Hartman static DEVICE_ATTR_RO(name); 381bc558a60SMark Brown 3824fca9545SDavid Brownell static ssize_t regulator_print_opmode(char *buf, int mode) 383414c70cbSLiam Girdwood { 384414c70cbSLiam Girdwood switch (mode) { 385414c70cbSLiam Girdwood case REGULATOR_MODE_FAST: 386414c70cbSLiam Girdwood return sprintf(buf, "fast\n"); 387414c70cbSLiam Girdwood case REGULATOR_MODE_NORMAL: 388414c70cbSLiam Girdwood return sprintf(buf, "normal\n"); 389414c70cbSLiam Girdwood case REGULATOR_MODE_IDLE: 390414c70cbSLiam Girdwood return sprintf(buf, "idle\n"); 391414c70cbSLiam Girdwood case REGULATOR_MODE_STANDBY: 392414c70cbSLiam Girdwood return sprintf(buf, "standby\n"); 393414c70cbSLiam Girdwood } 394414c70cbSLiam Girdwood return sprintf(buf, "unknown\n"); 395414c70cbSLiam Girdwood } 396414c70cbSLiam Girdwood 3974fca9545SDavid Brownell static ssize_t regulator_opmode_show(struct device *dev, 398414c70cbSLiam Girdwood struct device_attribute *attr, char *buf) 399414c70cbSLiam Girdwood { 400a5766f11SLiam Girdwood struct regulator_dev *rdev = dev_get_drvdata(dev); 401414c70cbSLiam Girdwood 4024fca9545SDavid Brownell return regulator_print_opmode(buf, _regulator_get_mode(rdev)); 4034fca9545SDavid Brownell } 4047ad68e2fSDavid Brownell static DEVICE_ATTR(opmode, 0444, regulator_opmode_show, NULL); 4054fca9545SDavid Brownell 4064fca9545SDavid Brownell static ssize_t regulator_print_state(char *buf, int state) 4074fca9545SDavid Brownell { 408414c70cbSLiam Girdwood if (state > 0) 409414c70cbSLiam Girdwood return sprintf(buf, "enabled\n"); 410414c70cbSLiam Girdwood else if (state == 0) 411414c70cbSLiam Girdwood return sprintf(buf, "disabled\n"); 412414c70cbSLiam Girdwood else 413414c70cbSLiam Girdwood return sprintf(buf, "unknown\n"); 414414c70cbSLiam Girdwood } 415414c70cbSLiam Girdwood 4164fca9545SDavid Brownell static ssize_t regulator_state_show(struct device *dev, 4174fca9545SDavid Brownell struct device_attribute *attr, char *buf) 4184fca9545SDavid Brownell { 4194fca9545SDavid Brownell struct regulator_dev *rdev = dev_get_drvdata(dev); 4209332546fSMark Brown ssize_t ret; 4214fca9545SDavid Brownell 4229332546fSMark Brown mutex_lock(&rdev->mutex); 4239332546fSMark Brown ret = regulator_print_state(buf, _regulator_is_enabled(rdev)); 4249332546fSMark Brown mutex_unlock(&rdev->mutex); 4259332546fSMark Brown 4269332546fSMark Brown return ret; 4274fca9545SDavid Brownell } 4287ad68e2fSDavid Brownell static DEVICE_ATTR(state, 0444, regulator_state_show, NULL); 4294fca9545SDavid Brownell 430853116a1SDavid Brownell static ssize_t regulator_status_show(struct device *dev, 431853116a1SDavid Brownell struct device_attribute *attr, char *buf) 432853116a1SDavid Brownell { 433853116a1SDavid Brownell struct regulator_dev *rdev = dev_get_drvdata(dev); 434853116a1SDavid Brownell int status; 435853116a1SDavid Brownell char *label; 436853116a1SDavid Brownell 437853116a1SDavid Brownell status = rdev->desc->ops->get_status(rdev); 438853116a1SDavid Brownell if (status < 0) 439853116a1SDavid Brownell return status; 440853116a1SDavid Brownell 441853116a1SDavid Brownell switch (status) { 442853116a1SDavid Brownell case REGULATOR_STATUS_OFF: 443853116a1SDavid Brownell label = "off"; 444853116a1SDavid Brownell break; 445853116a1SDavid Brownell case REGULATOR_STATUS_ON: 446853116a1SDavid Brownell label = "on"; 447853116a1SDavid Brownell break; 448853116a1SDavid Brownell case REGULATOR_STATUS_ERROR: 449853116a1SDavid Brownell label = "error"; 450853116a1SDavid Brownell break; 451853116a1SDavid Brownell case REGULATOR_STATUS_FAST: 452853116a1SDavid Brownell label = "fast"; 453853116a1SDavid Brownell break; 454853116a1SDavid Brownell case REGULATOR_STATUS_NORMAL: 455853116a1SDavid Brownell label = "normal"; 456853116a1SDavid Brownell break; 457853116a1SDavid Brownell case REGULATOR_STATUS_IDLE: 458853116a1SDavid Brownell label = "idle"; 459853116a1SDavid Brownell break; 460853116a1SDavid Brownell case REGULATOR_STATUS_STANDBY: 461853116a1SDavid Brownell label = "standby"; 462853116a1SDavid Brownell break; 463f59c8f9fSMark Brown case REGULATOR_STATUS_BYPASS: 464f59c8f9fSMark Brown label = "bypass"; 465f59c8f9fSMark Brown break; 4661beaf762SKrystian Garbaciak case REGULATOR_STATUS_UNDEFINED: 4671beaf762SKrystian Garbaciak label = "undefined"; 4681beaf762SKrystian Garbaciak break; 469853116a1SDavid Brownell default: 470853116a1SDavid Brownell return -ERANGE; 471853116a1SDavid Brownell } 472853116a1SDavid Brownell 473853116a1SDavid Brownell return sprintf(buf, "%s\n", label); 474853116a1SDavid Brownell } 475853116a1SDavid Brownell static DEVICE_ATTR(status, 0444, regulator_status_show, NULL); 476853116a1SDavid Brownell 477414c70cbSLiam Girdwood static ssize_t regulator_min_uA_show(struct device *dev, 478414c70cbSLiam Girdwood struct device_attribute *attr, char *buf) 479414c70cbSLiam Girdwood { 480a5766f11SLiam Girdwood struct regulator_dev *rdev = dev_get_drvdata(dev); 481414c70cbSLiam Girdwood 482414c70cbSLiam Girdwood if (!rdev->constraints) 483414c70cbSLiam Girdwood return sprintf(buf, "constraint not defined\n"); 484414c70cbSLiam Girdwood 485414c70cbSLiam Girdwood return sprintf(buf, "%d\n", rdev->constraints->min_uA); 486414c70cbSLiam Girdwood } 4877ad68e2fSDavid Brownell static DEVICE_ATTR(min_microamps, 0444, regulator_min_uA_show, NULL); 488414c70cbSLiam Girdwood 489414c70cbSLiam Girdwood static ssize_t regulator_max_uA_show(struct device *dev, 490414c70cbSLiam Girdwood struct device_attribute *attr, char *buf) 491414c70cbSLiam Girdwood { 492a5766f11SLiam Girdwood struct regulator_dev *rdev = dev_get_drvdata(dev); 493414c70cbSLiam Girdwood 494414c70cbSLiam Girdwood if (!rdev->constraints) 495414c70cbSLiam Girdwood return sprintf(buf, "constraint not defined\n"); 496414c70cbSLiam Girdwood 497414c70cbSLiam Girdwood return sprintf(buf, "%d\n", rdev->constraints->max_uA); 498414c70cbSLiam Girdwood } 4997ad68e2fSDavid Brownell static DEVICE_ATTR(max_microamps, 0444, regulator_max_uA_show, NULL); 500414c70cbSLiam Girdwood 501414c70cbSLiam Girdwood static ssize_t regulator_min_uV_show(struct device *dev, 502414c70cbSLiam Girdwood struct device_attribute *attr, char *buf) 503414c70cbSLiam Girdwood { 504a5766f11SLiam Girdwood struct regulator_dev *rdev = dev_get_drvdata(dev); 505414c70cbSLiam Girdwood 506414c70cbSLiam Girdwood if (!rdev->constraints) 507414c70cbSLiam Girdwood return sprintf(buf, "constraint not defined\n"); 508414c70cbSLiam Girdwood 509414c70cbSLiam Girdwood return sprintf(buf, "%d\n", rdev->constraints->min_uV); 510414c70cbSLiam Girdwood } 5117ad68e2fSDavid Brownell static DEVICE_ATTR(min_microvolts, 0444, regulator_min_uV_show, NULL); 512414c70cbSLiam Girdwood 513414c70cbSLiam Girdwood static ssize_t regulator_max_uV_show(struct device *dev, 514414c70cbSLiam Girdwood struct device_attribute *attr, char *buf) 515414c70cbSLiam Girdwood { 516a5766f11SLiam Girdwood struct regulator_dev *rdev = dev_get_drvdata(dev); 517414c70cbSLiam Girdwood 518414c70cbSLiam Girdwood if (!rdev->constraints) 519414c70cbSLiam Girdwood return sprintf(buf, "constraint not defined\n"); 520414c70cbSLiam Girdwood 521414c70cbSLiam Girdwood return sprintf(buf, "%d\n", rdev->constraints->max_uV); 522414c70cbSLiam Girdwood } 5237ad68e2fSDavid Brownell static DEVICE_ATTR(max_microvolts, 0444, regulator_max_uV_show, NULL); 524414c70cbSLiam Girdwood 525414c70cbSLiam Girdwood static ssize_t regulator_total_uA_show(struct device *dev, 526414c70cbSLiam Girdwood struct device_attribute *attr, char *buf) 527414c70cbSLiam Girdwood { 528a5766f11SLiam Girdwood struct regulator_dev *rdev = dev_get_drvdata(dev); 529414c70cbSLiam Girdwood struct regulator *regulator; 530414c70cbSLiam Girdwood int uA = 0; 531414c70cbSLiam Girdwood 532414c70cbSLiam Girdwood mutex_lock(&rdev->mutex); 533414c70cbSLiam Girdwood list_for_each_entry(regulator, &rdev->consumer_list, list) 534414c70cbSLiam Girdwood uA += regulator->uA_load; 535414c70cbSLiam Girdwood mutex_unlock(&rdev->mutex); 536414c70cbSLiam Girdwood return sprintf(buf, "%d\n", uA); 537414c70cbSLiam Girdwood } 5387ad68e2fSDavid Brownell static DEVICE_ATTR(requested_microamps, 0444, regulator_total_uA_show, NULL); 539414c70cbSLiam Girdwood 540587cea27SGreg Kroah-Hartman static ssize_t num_users_show(struct device *dev, struct device_attribute *attr, 541587cea27SGreg Kroah-Hartman char *buf) 542414c70cbSLiam Girdwood { 543a5766f11SLiam Girdwood struct regulator_dev *rdev = dev_get_drvdata(dev); 544414c70cbSLiam Girdwood return sprintf(buf, "%d\n", rdev->use_count); 545414c70cbSLiam Girdwood } 546587cea27SGreg Kroah-Hartman static DEVICE_ATTR_RO(num_users); 547414c70cbSLiam Girdwood 548587cea27SGreg Kroah-Hartman static ssize_t type_show(struct device *dev, struct device_attribute *attr, 549587cea27SGreg Kroah-Hartman char *buf) 550414c70cbSLiam Girdwood { 551a5766f11SLiam Girdwood struct regulator_dev *rdev = dev_get_drvdata(dev); 552414c70cbSLiam Girdwood 553414c70cbSLiam Girdwood switch (rdev->desc->type) { 554414c70cbSLiam Girdwood case REGULATOR_VOLTAGE: 555414c70cbSLiam Girdwood return sprintf(buf, "voltage\n"); 556414c70cbSLiam Girdwood case REGULATOR_CURRENT: 557414c70cbSLiam Girdwood return sprintf(buf, "current\n"); 558414c70cbSLiam Girdwood } 559414c70cbSLiam Girdwood return sprintf(buf, "unknown\n"); 560414c70cbSLiam Girdwood } 561587cea27SGreg Kroah-Hartman static DEVICE_ATTR_RO(type); 562414c70cbSLiam Girdwood 563414c70cbSLiam Girdwood static ssize_t regulator_suspend_mem_uV_show(struct device *dev, 564414c70cbSLiam Girdwood struct device_attribute *attr, char *buf) 565414c70cbSLiam Girdwood { 566a5766f11SLiam Girdwood struct regulator_dev *rdev = dev_get_drvdata(dev); 567414c70cbSLiam Girdwood 568414c70cbSLiam Girdwood return sprintf(buf, "%d\n", rdev->constraints->state_mem.uV); 569414c70cbSLiam Girdwood } 5707ad68e2fSDavid Brownell static DEVICE_ATTR(suspend_mem_microvolts, 0444, 5717ad68e2fSDavid Brownell regulator_suspend_mem_uV_show, NULL); 572414c70cbSLiam Girdwood 573414c70cbSLiam Girdwood static ssize_t regulator_suspend_disk_uV_show(struct device *dev, 574414c70cbSLiam Girdwood struct device_attribute *attr, char *buf) 575414c70cbSLiam Girdwood { 576a5766f11SLiam Girdwood struct regulator_dev *rdev = dev_get_drvdata(dev); 577414c70cbSLiam Girdwood 578414c70cbSLiam Girdwood return sprintf(buf, "%d\n", rdev->constraints->state_disk.uV); 579414c70cbSLiam Girdwood } 5807ad68e2fSDavid Brownell static DEVICE_ATTR(suspend_disk_microvolts, 0444, 5817ad68e2fSDavid Brownell regulator_suspend_disk_uV_show, NULL); 582414c70cbSLiam Girdwood 583414c70cbSLiam Girdwood static ssize_t regulator_suspend_standby_uV_show(struct device *dev, 584414c70cbSLiam Girdwood struct device_attribute *attr, char *buf) 585414c70cbSLiam Girdwood { 586a5766f11SLiam Girdwood struct regulator_dev *rdev = dev_get_drvdata(dev); 587414c70cbSLiam Girdwood 588414c70cbSLiam Girdwood return sprintf(buf, "%d\n", rdev->constraints->state_standby.uV); 589414c70cbSLiam Girdwood } 5907ad68e2fSDavid Brownell static DEVICE_ATTR(suspend_standby_microvolts, 0444, 5917ad68e2fSDavid Brownell regulator_suspend_standby_uV_show, NULL); 592414c70cbSLiam Girdwood 593414c70cbSLiam Girdwood static ssize_t regulator_suspend_mem_mode_show(struct device *dev, 594414c70cbSLiam Girdwood struct device_attribute *attr, char *buf) 595414c70cbSLiam Girdwood { 596a5766f11SLiam Girdwood struct regulator_dev *rdev = dev_get_drvdata(dev); 597414c70cbSLiam Girdwood 5984fca9545SDavid Brownell return regulator_print_opmode(buf, 5994fca9545SDavid Brownell rdev->constraints->state_mem.mode); 600414c70cbSLiam Girdwood } 6017ad68e2fSDavid Brownell static DEVICE_ATTR(suspend_mem_mode, 0444, 6027ad68e2fSDavid Brownell regulator_suspend_mem_mode_show, NULL); 603414c70cbSLiam Girdwood 604414c70cbSLiam Girdwood static ssize_t regulator_suspend_disk_mode_show(struct device *dev, 605414c70cbSLiam Girdwood struct device_attribute *attr, char *buf) 606414c70cbSLiam Girdwood { 607a5766f11SLiam Girdwood struct regulator_dev *rdev = dev_get_drvdata(dev); 608414c70cbSLiam Girdwood 6094fca9545SDavid Brownell return regulator_print_opmode(buf, 6104fca9545SDavid Brownell rdev->constraints->state_disk.mode); 611414c70cbSLiam Girdwood } 6127ad68e2fSDavid Brownell static DEVICE_ATTR(suspend_disk_mode, 0444, 6137ad68e2fSDavid Brownell regulator_suspend_disk_mode_show, NULL); 614414c70cbSLiam Girdwood 615414c70cbSLiam Girdwood static ssize_t regulator_suspend_standby_mode_show(struct device *dev, 616414c70cbSLiam Girdwood struct device_attribute *attr, char *buf) 617414c70cbSLiam Girdwood { 618a5766f11SLiam Girdwood struct regulator_dev *rdev = dev_get_drvdata(dev); 619414c70cbSLiam Girdwood 6204fca9545SDavid Brownell return regulator_print_opmode(buf, 6214fca9545SDavid Brownell rdev->constraints->state_standby.mode); 622414c70cbSLiam Girdwood } 6237ad68e2fSDavid Brownell static DEVICE_ATTR(suspend_standby_mode, 0444, 6247ad68e2fSDavid Brownell regulator_suspend_standby_mode_show, NULL); 625414c70cbSLiam Girdwood 626414c70cbSLiam Girdwood static ssize_t regulator_suspend_mem_state_show(struct device *dev, 627414c70cbSLiam Girdwood struct device_attribute *attr, char *buf) 628414c70cbSLiam Girdwood { 629a5766f11SLiam Girdwood struct regulator_dev *rdev = dev_get_drvdata(dev); 630414c70cbSLiam Girdwood 6314fca9545SDavid Brownell return regulator_print_state(buf, 6324fca9545SDavid Brownell rdev->constraints->state_mem.enabled); 633414c70cbSLiam Girdwood } 6347ad68e2fSDavid Brownell static DEVICE_ATTR(suspend_mem_state, 0444, 6357ad68e2fSDavid Brownell regulator_suspend_mem_state_show, NULL); 636414c70cbSLiam Girdwood 637414c70cbSLiam Girdwood static ssize_t regulator_suspend_disk_state_show(struct device *dev, 638414c70cbSLiam Girdwood struct device_attribute *attr, char *buf) 639414c70cbSLiam Girdwood { 640a5766f11SLiam Girdwood struct regulator_dev *rdev = dev_get_drvdata(dev); 641414c70cbSLiam Girdwood 6424fca9545SDavid Brownell return regulator_print_state(buf, 6434fca9545SDavid Brownell rdev->constraints->state_disk.enabled); 644414c70cbSLiam Girdwood } 6457ad68e2fSDavid Brownell static DEVICE_ATTR(suspend_disk_state, 0444, 6467ad68e2fSDavid Brownell regulator_suspend_disk_state_show, NULL); 647414c70cbSLiam Girdwood 648414c70cbSLiam Girdwood static ssize_t regulator_suspend_standby_state_show(struct device *dev, 649414c70cbSLiam Girdwood struct device_attribute *attr, char *buf) 650414c70cbSLiam Girdwood { 651a5766f11SLiam Girdwood struct regulator_dev *rdev = dev_get_drvdata(dev); 652414c70cbSLiam Girdwood 6534fca9545SDavid Brownell return regulator_print_state(buf, 6544fca9545SDavid Brownell rdev->constraints->state_standby.enabled); 655414c70cbSLiam Girdwood } 6567ad68e2fSDavid Brownell static DEVICE_ATTR(suspend_standby_state, 0444, 6577ad68e2fSDavid Brownell regulator_suspend_standby_state_show, NULL); 658bc558a60SMark Brown 659f59c8f9fSMark Brown static ssize_t regulator_bypass_show(struct device *dev, 660f59c8f9fSMark Brown struct device_attribute *attr, char *buf) 661f59c8f9fSMark Brown { 662f59c8f9fSMark Brown struct regulator_dev *rdev = dev_get_drvdata(dev); 663f59c8f9fSMark Brown const char *report; 664f59c8f9fSMark Brown bool bypass; 665f59c8f9fSMark Brown int ret; 666f59c8f9fSMark Brown 667f59c8f9fSMark Brown ret = rdev->desc->ops->get_bypass(rdev, &bypass); 668f59c8f9fSMark Brown 669f59c8f9fSMark Brown if (ret != 0) 670f59c8f9fSMark Brown report = "unknown"; 671f59c8f9fSMark Brown else if (bypass) 672f59c8f9fSMark Brown report = "enabled"; 673f59c8f9fSMark Brown else 674f59c8f9fSMark Brown report = "disabled"; 675f59c8f9fSMark Brown 676f59c8f9fSMark Brown return sprintf(buf, "%s\n", report); 677f59c8f9fSMark Brown } 678f59c8f9fSMark Brown static DEVICE_ATTR(bypass, 0444, 679f59c8f9fSMark Brown regulator_bypass_show, NULL); 6807ad68e2fSDavid Brownell 681414c70cbSLiam Girdwood /* Calculate the new optimum regulator operating mode based on the new total 682414c70cbSLiam Girdwood * consumer load. All locks held by caller */ 6838460ef38SBjorn Andersson static int drms_uA_update(struct regulator_dev *rdev) 684414c70cbSLiam Girdwood { 685414c70cbSLiam Girdwood struct regulator *sibling; 686414c70cbSLiam Girdwood int current_uA = 0, output_uV, input_uV, err; 687414c70cbSLiam Girdwood unsigned int mode; 688414c70cbSLiam Girdwood 68970cfef26SKrzysztof Kozlowski lockdep_assert_held_once(&rdev->mutex); 69070cfef26SKrzysztof Kozlowski 6918460ef38SBjorn Andersson /* 6928460ef38SBjorn Andersson * first check to see if we can set modes at all, otherwise just 6938460ef38SBjorn Andersson * tell the consumer everything is OK. 6948460ef38SBjorn Andersson */ 695414c70cbSLiam Girdwood err = regulator_check_drms(rdev); 6968460ef38SBjorn Andersson if (err < 0) 6978460ef38SBjorn Andersson return 0; 6988460ef38SBjorn Andersson 6998f4490e0SBjorn Andersson if (!rdev->desc->ops->get_optimum_mode && 7008f4490e0SBjorn Andersson !rdev->desc->ops->set_load) 7018460ef38SBjorn Andersson return 0; 7028460ef38SBjorn Andersson 7038f4490e0SBjorn Andersson if (!rdev->desc->ops->set_mode && 7048f4490e0SBjorn Andersson !rdev->desc->ops->set_load) 7058460ef38SBjorn Andersson return -EINVAL; 706414c70cbSLiam Girdwood 707414c70cbSLiam Girdwood /* get output voltage */ 7081bf5a1f8SMark Brown output_uV = _regulator_get_voltage(rdev); 7098460ef38SBjorn Andersson if (output_uV <= 0) { 7108460ef38SBjorn Andersson rdev_err(rdev, "invalid output voltage found\n"); 7118460ef38SBjorn Andersson return -EINVAL; 7128460ef38SBjorn Andersson } 713414c70cbSLiam Girdwood 714414c70cbSLiam Girdwood /* get input voltage */ 7151bf5a1f8SMark Brown input_uV = 0; 7161bf5a1f8SMark Brown if (rdev->supply) 7173f24f5adSAxel Lin input_uV = regulator_get_voltage(rdev->supply); 7181bf5a1f8SMark Brown if (input_uV <= 0) 719414c70cbSLiam Girdwood input_uV = rdev->constraints->input_uV; 7208460ef38SBjorn Andersson if (input_uV <= 0) { 7218460ef38SBjorn Andersson rdev_err(rdev, "invalid input voltage found\n"); 7228460ef38SBjorn Andersson return -EINVAL; 7238460ef38SBjorn Andersson } 724414c70cbSLiam Girdwood 725414c70cbSLiam Girdwood /* calc total requested load */ 726414c70cbSLiam Girdwood list_for_each_entry(sibling, &rdev->consumer_list, list) 727414c70cbSLiam Girdwood current_uA += sibling->uA_load; 728414c70cbSLiam Girdwood 72922a10bcaSStephen Boyd current_uA += rdev->constraints->system_load; 73022a10bcaSStephen Boyd 7318f4490e0SBjorn Andersson if (rdev->desc->ops->set_load) { 7328f4490e0SBjorn Andersson /* set the optimum mode for our new total regulator load */ 7338f4490e0SBjorn Andersson err = rdev->desc->ops->set_load(rdev, current_uA); 7348f4490e0SBjorn Andersson if (err < 0) 7358f4490e0SBjorn Andersson rdev_err(rdev, "failed to set load %d\n", current_uA); 7368f4490e0SBjorn Andersson } else { 737414c70cbSLiam Girdwood /* now get the optimum mode for our new total regulator load */ 738414c70cbSLiam Girdwood mode = rdev->desc->ops->get_optimum_mode(rdev, input_uV, 739414c70cbSLiam Girdwood output_uV, current_uA); 740414c70cbSLiam Girdwood 741414c70cbSLiam Girdwood /* check the new mode is allowed */ 7422c608234SMark Brown err = regulator_mode_constrain(rdev, &mode); 7438460ef38SBjorn Andersson if (err < 0) { 7448460ef38SBjorn Andersson rdev_err(rdev, "failed to get optimum mode @ %d uA %d -> %d uV\n", 7458460ef38SBjorn Andersson current_uA, input_uV, output_uV); 7468460ef38SBjorn Andersson return err; 7478460ef38SBjorn Andersson } 7488460ef38SBjorn Andersson 7498460ef38SBjorn Andersson err = rdev->desc->ops->set_mode(rdev, mode); 7508460ef38SBjorn Andersson if (err < 0) 7518460ef38SBjorn Andersson rdev_err(rdev, "failed to set optimum mode %x\n", mode); 7528f4490e0SBjorn Andersson } 7538460ef38SBjorn Andersson 7548460ef38SBjorn Andersson return err; 755414c70cbSLiam Girdwood } 756414c70cbSLiam Girdwood 757414c70cbSLiam Girdwood static int suspend_set_state(struct regulator_dev *rdev, 758414c70cbSLiam Girdwood struct regulator_state *rstate) 759414c70cbSLiam Girdwood { 760414c70cbSLiam Girdwood int ret = 0; 761638f85c5SMark Brown 762638f85c5SMark Brown /* If we have no suspend mode configration don't set anything; 7638ac0e95dSAxel Lin * only warn if the driver implements set_suspend_voltage or 7648ac0e95dSAxel Lin * set_suspend_mode callback. 765638f85c5SMark Brown */ 766638f85c5SMark Brown if (!rstate->enabled && !rstate->disabled) { 7678ac0e95dSAxel Lin if (rdev->desc->ops->set_suspend_voltage || 7688ac0e95dSAxel Lin rdev->desc->ops->set_suspend_mode) 7695da84fd9SJoe Perches rdev_warn(rdev, "No configuration\n"); 770638f85c5SMark Brown return 0; 771638f85c5SMark Brown } 772638f85c5SMark Brown 773638f85c5SMark Brown if (rstate->enabled && rstate->disabled) { 7745da84fd9SJoe Perches rdev_err(rdev, "invalid configuration\n"); 775638f85c5SMark Brown return -EINVAL; 776638f85c5SMark Brown } 777638f85c5SMark Brown 7788ac0e95dSAxel Lin if (rstate->enabled && rdev->desc->ops->set_suspend_enable) 779414c70cbSLiam Girdwood ret = rdev->desc->ops->set_suspend_enable(rdev); 7808ac0e95dSAxel Lin else if (rstate->disabled && rdev->desc->ops->set_suspend_disable) 781414c70cbSLiam Girdwood ret = rdev->desc->ops->set_suspend_disable(rdev); 7828ac0e95dSAxel Lin else /* OK if set_suspend_enable or set_suspend_disable is NULL */ 7838ac0e95dSAxel Lin ret = 0; 7848ac0e95dSAxel Lin 785414c70cbSLiam Girdwood if (ret < 0) { 7865da84fd9SJoe Perches rdev_err(rdev, "failed to enabled/disable\n"); 787414c70cbSLiam Girdwood return ret; 788414c70cbSLiam Girdwood } 789414c70cbSLiam Girdwood 790414c70cbSLiam Girdwood if (rdev->desc->ops->set_suspend_voltage && rstate->uV > 0) { 791414c70cbSLiam Girdwood ret = rdev->desc->ops->set_suspend_voltage(rdev, rstate->uV); 792414c70cbSLiam Girdwood if (ret < 0) { 7935da84fd9SJoe Perches rdev_err(rdev, "failed to set voltage\n"); 794414c70cbSLiam Girdwood return ret; 795414c70cbSLiam Girdwood } 796414c70cbSLiam Girdwood } 797414c70cbSLiam Girdwood 798414c70cbSLiam Girdwood if (rdev->desc->ops->set_suspend_mode && rstate->mode > 0) { 799414c70cbSLiam Girdwood ret = rdev->desc->ops->set_suspend_mode(rdev, rstate->mode); 800414c70cbSLiam Girdwood if (ret < 0) { 8015da84fd9SJoe Perches rdev_err(rdev, "failed to set mode\n"); 802414c70cbSLiam Girdwood return ret; 803414c70cbSLiam Girdwood } 804414c70cbSLiam Girdwood } 805414c70cbSLiam Girdwood return ret; 806414c70cbSLiam Girdwood } 807414c70cbSLiam Girdwood 808414c70cbSLiam Girdwood /* locks held by caller */ 809414c70cbSLiam Girdwood static int suspend_prepare(struct regulator_dev *rdev, suspend_state_t state) 810414c70cbSLiam Girdwood { 81170cfef26SKrzysztof Kozlowski lockdep_assert_held_once(&rdev->mutex); 81270cfef26SKrzysztof Kozlowski 813414c70cbSLiam Girdwood if (!rdev->constraints) 814414c70cbSLiam Girdwood return -EINVAL; 815414c70cbSLiam Girdwood 816414c70cbSLiam Girdwood switch (state) { 817414c70cbSLiam Girdwood case PM_SUSPEND_STANDBY: 818414c70cbSLiam Girdwood return suspend_set_state(rdev, 819414c70cbSLiam Girdwood &rdev->constraints->state_standby); 820414c70cbSLiam Girdwood case PM_SUSPEND_MEM: 821414c70cbSLiam Girdwood return suspend_set_state(rdev, 822414c70cbSLiam Girdwood &rdev->constraints->state_mem); 823414c70cbSLiam Girdwood case PM_SUSPEND_MAX: 824414c70cbSLiam Girdwood return suspend_set_state(rdev, 825414c70cbSLiam Girdwood &rdev->constraints->state_disk); 826414c70cbSLiam Girdwood default: 827414c70cbSLiam Girdwood return -EINVAL; 828414c70cbSLiam Girdwood } 829414c70cbSLiam Girdwood } 830414c70cbSLiam Girdwood 831414c70cbSLiam Girdwood static void print_constraints(struct regulator_dev *rdev) 832414c70cbSLiam Girdwood { 833414c70cbSLiam Girdwood struct regulation_constraints *constraints = rdev->constraints; 834a7068e39SStefan Wahren char buf[160] = ""; 8355751a99fSStefan Wahren size_t len = sizeof(buf) - 1; 8368f031b48SMark Brown int count = 0; 8378f031b48SMark Brown int ret; 838414c70cbSLiam Girdwood 8398f031b48SMark Brown if (constraints->min_uV && constraints->max_uV) { 840414c70cbSLiam Girdwood if (constraints->min_uV == constraints->max_uV) 8415751a99fSStefan Wahren count += scnprintf(buf + count, len - count, "%d mV ", 842414c70cbSLiam Girdwood constraints->min_uV / 1000); 843414c70cbSLiam Girdwood else 8445751a99fSStefan Wahren count += scnprintf(buf + count, len - count, 8455751a99fSStefan Wahren "%d <--> %d mV ", 846414c70cbSLiam Girdwood constraints->min_uV / 1000, 847414c70cbSLiam Girdwood constraints->max_uV / 1000); 8488f031b48SMark Brown } 8498f031b48SMark Brown 8508f031b48SMark Brown if (!constraints->min_uV || 8518f031b48SMark Brown constraints->min_uV != constraints->max_uV) { 8528f031b48SMark Brown ret = _regulator_get_voltage(rdev); 8538f031b48SMark Brown if (ret > 0) 8545751a99fSStefan Wahren count += scnprintf(buf + count, len - count, 8555751a99fSStefan Wahren "at %d mV ", ret / 1000); 8568f031b48SMark Brown } 8578f031b48SMark Brown 858bf5892a8SMark Brown if (constraints->uV_offset) 8595751a99fSStefan Wahren count += scnprintf(buf + count, len - count, "%dmV offset ", 860bf5892a8SMark Brown constraints->uV_offset / 1000); 861bf5892a8SMark Brown 8628f031b48SMark Brown if (constraints->min_uA && constraints->max_uA) { 863414c70cbSLiam Girdwood if (constraints->min_uA == constraints->max_uA) 8645751a99fSStefan Wahren count += scnprintf(buf + count, len - count, "%d mA ", 865414c70cbSLiam Girdwood constraints->min_uA / 1000); 866414c70cbSLiam Girdwood else 8675751a99fSStefan Wahren count += scnprintf(buf + count, len - count, 8685751a99fSStefan Wahren "%d <--> %d mA ", 869414c70cbSLiam Girdwood constraints->min_uA / 1000, 870414c70cbSLiam Girdwood constraints->max_uA / 1000); 871414c70cbSLiam Girdwood } 8728f031b48SMark Brown 8738f031b48SMark Brown if (!constraints->min_uA || 8748f031b48SMark Brown constraints->min_uA != constraints->max_uA) { 8758f031b48SMark Brown ret = _regulator_get_current_limit(rdev); 8768f031b48SMark Brown if (ret > 0) 8775751a99fSStefan Wahren count += scnprintf(buf + count, len - count, 8785751a99fSStefan Wahren "at %d mA ", ret / 1000); 8798f031b48SMark Brown } 8808f031b48SMark Brown 881414c70cbSLiam Girdwood if (constraints->valid_modes_mask & REGULATOR_MODE_FAST) 8825751a99fSStefan Wahren count += scnprintf(buf + count, len - count, "fast "); 883414c70cbSLiam Girdwood if (constraints->valid_modes_mask & REGULATOR_MODE_NORMAL) 8845751a99fSStefan Wahren count += scnprintf(buf + count, len - count, "normal "); 885414c70cbSLiam Girdwood if (constraints->valid_modes_mask & REGULATOR_MODE_IDLE) 8865751a99fSStefan Wahren count += scnprintf(buf + count, len - count, "idle "); 887414c70cbSLiam Girdwood if (constraints->valid_modes_mask & REGULATOR_MODE_STANDBY) 8885751a99fSStefan Wahren count += scnprintf(buf + count, len - count, "standby"); 889414c70cbSLiam Girdwood 890215b8b05SUwe Kleine-König if (!count) 8915751a99fSStefan Wahren scnprintf(buf, len, "no parameters"); 892215b8b05SUwe Kleine-König 893194dbaefSMark Brown rdev_dbg(rdev, "%s\n", buf); 8944a682922SMark Brown 8954a682922SMark Brown if ((constraints->min_uV != constraints->max_uV) && 8964a682922SMark Brown !(constraints->valid_ops_mask & REGULATOR_CHANGE_VOLTAGE)) 8974a682922SMark Brown rdev_warn(rdev, 8984a682922SMark Brown "Voltage range but no REGULATOR_CHANGE_VOLTAGE\n"); 899414c70cbSLiam Girdwood } 900414c70cbSLiam Girdwood 901e79055d6SMark Brown static int machine_constraints_voltage(struct regulator_dev *rdev, 9021083c393SMark Brown struct regulation_constraints *constraints) 903e79055d6SMark Brown { 904272e2315SGuodong Xu const struct regulator_ops *ops = rdev->desc->ops; 905af5866c9SMark Brown int ret; 906af5866c9SMark Brown 907af5866c9SMark Brown /* do we need to apply the constraint voltage */ 908af5866c9SMark Brown if (rdev->constraints->apply_uV && 90975790251SMark Brown rdev->constraints->min_uV == rdev->constraints->max_uV) { 910064d5cd1SAlban Bedel int current_uV = _regulator_get_voltage(rdev); 911064d5cd1SAlban Bedel if (current_uV < 0) { 91269d58839SNishanth Menon rdev_err(rdev, 91369d58839SNishanth Menon "failed to get the current voltage(%d)\n", 91469d58839SNishanth Menon current_uV); 915064d5cd1SAlban Bedel return current_uV; 916064d5cd1SAlban Bedel } 917064d5cd1SAlban Bedel if (current_uV < rdev->constraints->min_uV || 918064d5cd1SAlban Bedel current_uV > rdev->constraints->max_uV) { 919064d5cd1SAlban Bedel ret = _regulator_do_set_voltage( 920064d5cd1SAlban Bedel rdev, rdev->constraints->min_uV, 92175790251SMark Brown rdev->constraints->max_uV); 922af5866c9SMark Brown if (ret < 0) { 923064d5cd1SAlban Bedel rdev_err(rdev, 92469d58839SNishanth Menon "failed to apply %duV constraint(%d)\n", 92569d58839SNishanth Menon rdev->constraints->min_uV, ret); 926af5866c9SMark Brown return ret; 927af5866c9SMark Brown } 928af5866c9SMark Brown } 929064d5cd1SAlban Bedel } 930e79055d6SMark Brown 931e79055d6SMark Brown /* constrain machine-level voltage specs to fit 932e79055d6SMark Brown * the actual range supported by this regulator. 933e79055d6SMark Brown */ 934e79055d6SMark Brown if (ops->list_voltage && rdev->desc->n_voltages) { 935e79055d6SMark Brown int count = rdev->desc->n_voltages; 936e79055d6SMark Brown int i; 937e79055d6SMark Brown int min_uV = INT_MAX; 938e79055d6SMark Brown int max_uV = INT_MIN; 939e79055d6SMark Brown int cmin = constraints->min_uV; 940e79055d6SMark Brown int cmax = constraints->max_uV; 941e79055d6SMark Brown 942e79055d6SMark Brown /* it's safe to autoconfigure fixed-voltage supplies 943e79055d6SMark Brown and the constraints are used by list_voltage. */ 944e79055d6SMark Brown if (count == 1 && !cmin) { 945e79055d6SMark Brown cmin = 1; 946e79055d6SMark Brown cmax = INT_MAX; 947e79055d6SMark Brown constraints->min_uV = cmin; 948e79055d6SMark Brown constraints->max_uV = cmax; 949e79055d6SMark Brown } 950e79055d6SMark Brown 951e79055d6SMark Brown /* voltage constraints are optional */ 952e79055d6SMark Brown if ((cmin == 0) && (cmax == 0)) 953e79055d6SMark Brown return 0; 954e79055d6SMark Brown 955e79055d6SMark Brown /* else require explicit machine-level constraints */ 956e79055d6SMark Brown if (cmin <= 0 || cmax <= 0 || cmax < cmin) { 9575da84fd9SJoe Perches rdev_err(rdev, "invalid voltage constraints\n"); 958e79055d6SMark Brown return -EINVAL; 959e79055d6SMark Brown } 960e79055d6SMark Brown 961e79055d6SMark Brown /* initial: [cmin..cmax] valid, [min_uV..max_uV] not */ 962e79055d6SMark Brown for (i = 0; i < count; i++) { 963e79055d6SMark Brown int value; 964e79055d6SMark Brown 965e79055d6SMark Brown value = ops->list_voltage(rdev, i); 966e79055d6SMark Brown if (value <= 0) 967e79055d6SMark Brown continue; 968e79055d6SMark Brown 969e79055d6SMark Brown /* maybe adjust [min_uV..max_uV] */ 970e79055d6SMark Brown if (value >= cmin && value < min_uV) 971e79055d6SMark Brown min_uV = value; 972e79055d6SMark Brown if (value <= cmax && value > max_uV) 973e79055d6SMark Brown max_uV = value; 974e79055d6SMark Brown } 975e79055d6SMark Brown 976e79055d6SMark Brown /* final: [min_uV..max_uV] valid iff constraints valid */ 977e79055d6SMark Brown if (max_uV < min_uV) { 978fff15befSMark Brown rdev_err(rdev, 979fff15befSMark Brown "unsupportable voltage constraints %u-%uuV\n", 980fff15befSMark Brown min_uV, max_uV); 981e79055d6SMark Brown return -EINVAL; 982e79055d6SMark Brown } 983e79055d6SMark Brown 984e79055d6SMark Brown /* use regulator's subset of machine constraints */ 985e79055d6SMark Brown if (constraints->min_uV < min_uV) { 9865da84fd9SJoe Perches rdev_dbg(rdev, "override min_uV, %d -> %d\n", 9875da84fd9SJoe Perches constraints->min_uV, min_uV); 988e79055d6SMark Brown constraints->min_uV = min_uV; 989e79055d6SMark Brown } 990e79055d6SMark Brown if (constraints->max_uV > max_uV) { 9915da84fd9SJoe Perches rdev_dbg(rdev, "override max_uV, %d -> %d\n", 9925da84fd9SJoe Perches constraints->max_uV, max_uV); 993e79055d6SMark Brown constraints->max_uV = max_uV; 994e79055d6SMark Brown } 995e79055d6SMark Brown } 996e79055d6SMark Brown 997e79055d6SMark Brown return 0; 998e79055d6SMark Brown } 999e79055d6SMark Brown 1000f8c1700dSLaxman Dewangan static int machine_constraints_current(struct regulator_dev *rdev, 1001f8c1700dSLaxman Dewangan struct regulation_constraints *constraints) 1002f8c1700dSLaxman Dewangan { 1003272e2315SGuodong Xu const struct regulator_ops *ops = rdev->desc->ops; 1004f8c1700dSLaxman Dewangan int ret; 1005f8c1700dSLaxman Dewangan 1006f8c1700dSLaxman Dewangan if (!constraints->min_uA && !constraints->max_uA) 1007f8c1700dSLaxman Dewangan return 0; 1008f8c1700dSLaxman Dewangan 1009f8c1700dSLaxman Dewangan if (constraints->min_uA > constraints->max_uA) { 1010f8c1700dSLaxman Dewangan rdev_err(rdev, "Invalid current constraints\n"); 1011f8c1700dSLaxman Dewangan return -EINVAL; 1012f8c1700dSLaxman Dewangan } 1013f8c1700dSLaxman Dewangan 1014f8c1700dSLaxman Dewangan if (!ops->set_current_limit || !ops->get_current_limit) { 1015f8c1700dSLaxman Dewangan rdev_warn(rdev, "Operation of current configuration missing\n"); 1016f8c1700dSLaxman Dewangan return 0; 1017f8c1700dSLaxman Dewangan } 1018f8c1700dSLaxman Dewangan 1019f8c1700dSLaxman Dewangan /* Set regulator current in constraints range */ 1020f8c1700dSLaxman Dewangan ret = ops->set_current_limit(rdev, constraints->min_uA, 1021f8c1700dSLaxman Dewangan constraints->max_uA); 1022f8c1700dSLaxman Dewangan if (ret < 0) { 1023f8c1700dSLaxman Dewangan rdev_err(rdev, "Failed to set current constraint, %d\n", ret); 1024f8c1700dSLaxman Dewangan return ret; 1025f8c1700dSLaxman Dewangan } 1026f8c1700dSLaxman Dewangan 1027f8c1700dSLaxman Dewangan return 0; 1028f8c1700dSLaxman Dewangan } 1029f8c1700dSLaxman Dewangan 103030c21971SMarkus Pargmann static int _regulator_do_enable(struct regulator_dev *rdev); 103130c21971SMarkus Pargmann 1032a5766f11SLiam Girdwood /** 1033a5766f11SLiam Girdwood * set_machine_constraints - sets regulator constraints 103469279fb9SMark Brown * @rdev: regulator source 1035c8e7e464SMark Brown * @constraints: constraints to apply 1036a5766f11SLiam Girdwood * 1037a5766f11SLiam Girdwood * Allows platform initialisation code to define and constrain 1038a5766f11SLiam Girdwood * regulator circuits e.g. valid voltage/current ranges, etc. NOTE: 1039a5766f11SLiam Girdwood * Constraints *must* be set by platform code in order for some 1040a5766f11SLiam Girdwood * regulator operations to proceed i.e. set_voltage, set_current_limit, 1041a5766f11SLiam Girdwood * set_mode. 1042a5766f11SLiam Girdwood */ 1043a5766f11SLiam Girdwood static int set_machine_constraints(struct regulator_dev *rdev, 1044f8c12fe3SMark Brown const struct regulation_constraints *constraints) 1045a5766f11SLiam Girdwood { 1046a5766f11SLiam Girdwood int ret = 0; 1047272e2315SGuodong Xu const struct regulator_ops *ops = rdev->desc->ops; 1048e06f5b4fSMark Brown 10499a8f5e07SMark Brown if (constraints) 1050f8c12fe3SMark Brown rdev->constraints = kmemdup(constraints, sizeof(*constraints), 1051f8c12fe3SMark Brown GFP_KERNEL); 10529a8f5e07SMark Brown else 10539a8f5e07SMark Brown rdev->constraints = kzalloc(sizeof(*constraints), 10549a8f5e07SMark Brown GFP_KERNEL); 1055f8c12fe3SMark Brown if (!rdev->constraints) 1056f8c12fe3SMark Brown return -ENOMEM; 1057af5866c9SMark Brown 1058f8c12fe3SMark Brown ret = machine_constraints_voltage(rdev, rdev->constraints); 1059e79055d6SMark Brown if (ret != 0) 10606333ef46SCharles Keepax return ret; 10613e2b9abdSMark Brown 1062f8c1700dSLaxman Dewangan ret = machine_constraints_current(rdev, rdev->constraints); 1063f8c1700dSLaxman Dewangan if (ret != 0) 10646333ef46SCharles Keepax return ret; 1065f8c1700dSLaxman Dewangan 106636e4f839SStephen Boyd if (rdev->constraints->ilim_uA && ops->set_input_current_limit) { 106736e4f839SStephen Boyd ret = ops->set_input_current_limit(rdev, 106836e4f839SStephen Boyd rdev->constraints->ilim_uA); 106936e4f839SStephen Boyd if (ret < 0) { 107036e4f839SStephen Boyd rdev_err(rdev, "failed to set input limit\n"); 10716333ef46SCharles Keepax return ret; 107236e4f839SStephen Boyd } 107336e4f839SStephen Boyd } 107436e4f839SStephen Boyd 1075a5766f11SLiam Girdwood /* do we need to setup our suspend state */ 10769a8f5e07SMark Brown if (rdev->constraints->initial_state) { 1077f8c12fe3SMark Brown ret = suspend_prepare(rdev, rdev->constraints->initial_state); 1078e06f5b4fSMark Brown if (ret < 0) { 10795da84fd9SJoe Perches rdev_err(rdev, "failed to set suspend state\n"); 10806333ef46SCharles Keepax return ret; 1081e06f5b4fSMark Brown } 1082e06f5b4fSMark Brown } 1083a5766f11SLiam Girdwood 10849a8f5e07SMark Brown if (rdev->constraints->initial_mode) { 1085a308466cSMark Brown if (!ops->set_mode) { 10865da84fd9SJoe Perches rdev_err(rdev, "no set_mode operation\n"); 10876333ef46SCharles Keepax return -EINVAL; 1088a308466cSMark Brown } 1089a308466cSMark Brown 1090f8c12fe3SMark Brown ret = ops->set_mode(rdev, rdev->constraints->initial_mode); 1091a308466cSMark Brown if (ret < 0) { 10925da84fd9SJoe Perches rdev_err(rdev, "failed to set initial mode: %d\n", ret); 10936333ef46SCharles Keepax return ret; 1094a308466cSMark Brown } 1095a308466cSMark Brown } 1096a308466cSMark Brown 1097cacf90f2SMark Brown /* If the constraints say the regulator should be on at this point 1098cacf90f2SMark Brown * and we have control then make sure it is enabled. 1099cacf90f2SMark Brown */ 110030c21971SMarkus Pargmann if (rdev->constraints->always_on || rdev->constraints->boot_on) { 110130c21971SMarkus Pargmann ret = _regulator_do_enable(rdev); 110230c21971SMarkus Pargmann if (ret < 0 && ret != -EINVAL) { 11035da84fd9SJoe Perches rdev_err(rdev, "failed to enable\n"); 11046333ef46SCharles Keepax return ret; 1105e5fda26cSMark Brown } 1106e5fda26cSMark Brown } 1107e5fda26cSMark Brown 11081653ccf4SYadwinder Singh Brar if ((rdev->constraints->ramp_delay || rdev->constraints->ramp_disable) 11091653ccf4SYadwinder Singh Brar && ops->set_ramp_delay) { 11106f0b2c69SYadwinder Singh Brar ret = ops->set_ramp_delay(rdev, rdev->constraints->ramp_delay); 11116f0b2c69SYadwinder Singh Brar if (ret < 0) { 11126f0b2c69SYadwinder Singh Brar rdev_err(rdev, "failed to set ramp_delay\n"); 11136333ef46SCharles Keepax return ret; 11146f0b2c69SYadwinder Singh Brar } 11156f0b2c69SYadwinder Singh Brar } 11166f0b2c69SYadwinder Singh Brar 111723c779b9SStephen Boyd if (rdev->constraints->pull_down && ops->set_pull_down) { 111823c779b9SStephen Boyd ret = ops->set_pull_down(rdev); 111923c779b9SStephen Boyd if (ret < 0) { 112023c779b9SStephen Boyd rdev_err(rdev, "failed to set pull down\n"); 11216333ef46SCharles Keepax return ret; 112223c779b9SStephen Boyd } 112323c779b9SStephen Boyd } 112423c779b9SStephen Boyd 112557f66b78SStephen Boyd if (rdev->constraints->soft_start && ops->set_soft_start) { 112657f66b78SStephen Boyd ret = ops->set_soft_start(rdev); 112757f66b78SStephen Boyd if (ret < 0) { 112857f66b78SStephen Boyd rdev_err(rdev, "failed to set soft start\n"); 11296333ef46SCharles Keepax return ret; 113057f66b78SStephen Boyd } 113157f66b78SStephen Boyd } 113257f66b78SStephen Boyd 11333a003baeSStephen Boyd if (rdev->constraints->over_current_protection 11343a003baeSStephen Boyd && ops->set_over_current_protection) { 11353a003baeSStephen Boyd ret = ops->set_over_current_protection(rdev); 11363a003baeSStephen Boyd if (ret < 0) { 11373a003baeSStephen Boyd rdev_err(rdev, "failed to set over current protection\n"); 11386333ef46SCharles Keepax return ret; 11393a003baeSStephen Boyd } 11403a003baeSStephen Boyd } 11413a003baeSStephen Boyd 1142670666b9SLaxman Dewangan if (rdev->constraints->active_discharge && ops->set_active_discharge) { 1143670666b9SLaxman Dewangan bool ad_state = (rdev->constraints->active_discharge == 1144670666b9SLaxman Dewangan REGULATOR_ACTIVE_DISCHARGE_ENABLE) ? true : false; 1145670666b9SLaxman Dewangan 1146670666b9SLaxman Dewangan ret = ops->set_active_discharge(rdev, ad_state); 1147670666b9SLaxman Dewangan if (ret < 0) { 1148670666b9SLaxman Dewangan rdev_err(rdev, "failed to set active discharge\n"); 1149670666b9SLaxman Dewangan return ret; 1150670666b9SLaxman Dewangan } 1151670666b9SLaxman Dewangan } 1152670666b9SLaxman Dewangan 1153909f7ee0SLaxman Dewangan if (rdev->constraints->active_discharge && ops->set_active_discharge) { 1154909f7ee0SLaxman Dewangan bool ad_state = (rdev->constraints->active_discharge == 1155909f7ee0SLaxman Dewangan REGULATOR_ACTIVE_DISCHARGE_ENABLE) ? true : false; 1156909f7ee0SLaxman Dewangan 1157909f7ee0SLaxman Dewangan ret = ops->set_active_discharge(rdev, ad_state); 1158909f7ee0SLaxman Dewangan if (ret < 0) { 1159909f7ee0SLaxman Dewangan rdev_err(rdev, "failed to set active discharge\n"); 1160909f7ee0SLaxman Dewangan return ret; 1161a5766f11SLiam Girdwood } 1162a5766f11SLiam Girdwood } 1163a5766f11SLiam Girdwood 1164a5766f11SLiam Girdwood print_constraints(rdev); 116569279fb9SMark Brown return 0; 1166a5766f11SLiam Girdwood } 1167a5766f11SLiam Girdwood 1168a5766f11SLiam Girdwood /** 1169a5766f11SLiam Girdwood * set_supply - set regulator supply regulator 117069279fb9SMark Brown * @rdev: regulator name 117169279fb9SMark Brown * @supply_rdev: supply regulator name 1172a5766f11SLiam Girdwood * 1173a5766f11SLiam Girdwood * Called by platform initialisation code to set the supply regulator for this 1174a5766f11SLiam Girdwood * regulator. This ensures that a regulators supply will also be enabled by the 1175a5766f11SLiam Girdwood * core if it's child is enabled. 1176a5766f11SLiam Girdwood */ 1177a5766f11SLiam Girdwood static int set_supply(struct regulator_dev *rdev, 1178a5766f11SLiam Girdwood struct regulator_dev *supply_rdev) 1179a5766f11SLiam Girdwood { 1180a5766f11SLiam Girdwood int err; 1181a5766f11SLiam Girdwood 11823801b86aSMark Brown rdev_info(rdev, "supplied by %s\n", rdev_get_name(supply_rdev)); 11833801b86aSMark Brown 1184e2c09ae7SJavier Martinez Canillas if (!try_module_get(supply_rdev->owner)) 1185e2c09ae7SJavier Martinez Canillas return -ENODEV; 1186e2c09ae7SJavier Martinez Canillas 11873801b86aSMark Brown rdev->supply = create_regulator(supply_rdev, &rdev->dev, "SUPPLY"); 118832c78de8SAxel Lin if (rdev->supply == NULL) { 118932c78de8SAxel Lin err = -ENOMEM; 1190a5766f11SLiam Girdwood return err; 1191a5766f11SLiam Girdwood } 119257ad526aSLaxman Dewangan supply_rdev->open_count++; 1193a5766f11SLiam Girdwood 11943801b86aSMark Brown return 0; 11953801b86aSMark Brown } 11963801b86aSMark Brown 1197a5766f11SLiam Girdwood /** 119806c63f93SRandy Dunlap * set_consumer_device_supply - Bind a regulator to a symbolic supply 119969279fb9SMark Brown * @rdev: regulator source 120040f9244fSMark Brown * @consumer_dev_name: dev_name() string for device supply applies to 1201a5766f11SLiam Girdwood * @supply: symbolic name for supply 1202a5766f11SLiam Girdwood * 1203a5766f11SLiam Girdwood * Allows platform initialisation code to map physical regulator 1204a5766f11SLiam Girdwood * sources to symbolic names for supplies for use by devices. Devices 1205a5766f11SLiam Girdwood * should use these symbolic names to request regulators, avoiding the 1206a5766f11SLiam Girdwood * need to provide board-specific regulator names as platform data. 1207a5766f11SLiam Girdwood */ 1208a5766f11SLiam Girdwood static int set_consumer_device_supply(struct regulator_dev *rdev, 1209737f360dSMark Brown const char *consumer_dev_name, 121040f9244fSMark Brown const char *supply) 1211a5766f11SLiam Girdwood { 1212a5766f11SLiam Girdwood struct regulator_map *node; 12139ed2099eSMark Brown int has_dev; 1214a5766f11SLiam Girdwood 1215a5766f11SLiam Girdwood if (supply == NULL) 1216a5766f11SLiam Girdwood return -EINVAL; 1217a5766f11SLiam Girdwood 12189ed2099eSMark Brown if (consumer_dev_name != NULL) 12199ed2099eSMark Brown has_dev = 1; 12209ed2099eSMark Brown else 12219ed2099eSMark Brown has_dev = 0; 12229ed2099eSMark Brown 12236001e13cSDavid Brownell list_for_each_entry(node, ®ulator_map_list, list) { 122423b5cc2aSJani Nikula if (node->dev_name && consumer_dev_name) { 122523b5cc2aSJani Nikula if (strcmp(node->dev_name, consumer_dev_name) != 0) 12266001e13cSDavid Brownell continue; 122723b5cc2aSJani Nikula } else if (node->dev_name || consumer_dev_name) { 122823b5cc2aSJani Nikula continue; 122923b5cc2aSJani Nikula } 123023b5cc2aSJani Nikula 12316001e13cSDavid Brownell if (strcmp(node->supply, supply) != 0) 12326001e13cSDavid Brownell continue; 12336001e13cSDavid Brownell 1234737f360dSMark Brown pr_debug("%s: %s/%s is '%s' supply; fail %s/%s\n", 1235737f360dSMark Brown consumer_dev_name, 12366001e13cSDavid Brownell dev_name(&node->regulator->dev), 12376001e13cSDavid Brownell node->regulator->desc->name, 12386001e13cSDavid Brownell supply, 12391083c393SMark Brown dev_name(&rdev->dev), rdev_get_name(rdev)); 12406001e13cSDavid Brownell return -EBUSY; 12416001e13cSDavid Brownell } 12426001e13cSDavid Brownell 12439ed2099eSMark Brown node = kzalloc(sizeof(struct regulator_map), GFP_KERNEL); 1244a5766f11SLiam Girdwood if (node == NULL) 1245a5766f11SLiam Girdwood return -ENOMEM; 1246a5766f11SLiam Girdwood 1247a5766f11SLiam Girdwood node->regulator = rdev; 1248a5766f11SLiam Girdwood node->supply = supply; 1249a5766f11SLiam Girdwood 12509ed2099eSMark Brown if (has_dev) { 12519ed2099eSMark Brown node->dev_name = kstrdup(consumer_dev_name, GFP_KERNEL); 125240f9244fSMark Brown if (node->dev_name == NULL) { 125340f9244fSMark Brown kfree(node); 125440f9244fSMark Brown return -ENOMEM; 125540f9244fSMark Brown } 12569ed2099eSMark Brown } 125740f9244fSMark Brown 1258a5766f11SLiam Girdwood list_add(&node->list, ®ulator_map_list); 1259a5766f11SLiam Girdwood return 0; 1260a5766f11SLiam Girdwood } 1261a5766f11SLiam Girdwood 12620f1d747bSMike Rapoport static void unset_regulator_supplies(struct regulator_dev *rdev) 12630f1d747bSMike Rapoport { 12640f1d747bSMike Rapoport struct regulator_map *node, *n; 12650f1d747bSMike Rapoport 12660f1d747bSMike Rapoport list_for_each_entry_safe(node, n, ®ulator_map_list, list) { 12670f1d747bSMike Rapoport if (rdev == node->regulator) { 12680f1d747bSMike Rapoport list_del(&node->list); 126940f9244fSMark Brown kfree(node->dev_name); 12700f1d747bSMike Rapoport kfree(node); 12710f1d747bSMike Rapoport } 12720f1d747bSMike Rapoport } 12730f1d747bSMike Rapoport } 12740f1d747bSMike Rapoport 1275f5726ae3SMark Brown #define REG_STR_SIZE 64 1276414c70cbSLiam Girdwood 1277414c70cbSLiam Girdwood static struct regulator *create_regulator(struct regulator_dev *rdev, 1278414c70cbSLiam Girdwood struct device *dev, 1279414c70cbSLiam Girdwood const char *supply_name) 1280414c70cbSLiam Girdwood { 1281414c70cbSLiam Girdwood struct regulator *regulator; 1282414c70cbSLiam Girdwood char buf[REG_STR_SIZE]; 1283414c70cbSLiam Girdwood int err, size; 1284414c70cbSLiam Girdwood 1285414c70cbSLiam Girdwood regulator = kzalloc(sizeof(*regulator), GFP_KERNEL); 1286414c70cbSLiam Girdwood if (regulator == NULL) 1287414c70cbSLiam Girdwood return NULL; 1288414c70cbSLiam Girdwood 1289414c70cbSLiam Girdwood mutex_lock(&rdev->mutex); 1290414c70cbSLiam Girdwood regulator->rdev = rdev; 1291414c70cbSLiam Girdwood list_add(®ulator->list, &rdev->consumer_list); 1292414c70cbSLiam Girdwood 1293414c70cbSLiam Girdwood if (dev) { 1294e2c98eafSShawn Guo regulator->dev = dev; 1295e2c98eafSShawn Guo 1296222cc7b1SMark Brown /* Add a link to the device sysfs entry */ 1297414c70cbSLiam Girdwood size = scnprintf(buf, REG_STR_SIZE, "%s-%s", 1298414c70cbSLiam Girdwood dev->kobj.name, supply_name); 1299414c70cbSLiam Girdwood if (size >= REG_STR_SIZE) 1300222cc7b1SMark Brown goto overflow_err; 1301414c70cbSLiam Girdwood 1302414c70cbSLiam Girdwood regulator->supply_name = kstrdup(buf, GFP_KERNEL); 1303414c70cbSLiam Girdwood if (regulator->supply_name == NULL) 1304222cc7b1SMark Brown goto overflow_err; 1305414c70cbSLiam Girdwood 1306ff268b56SStephen Boyd err = sysfs_create_link_nowarn(&rdev->dev.kobj, &dev->kobj, 1307414c70cbSLiam Girdwood buf); 1308414c70cbSLiam Girdwood if (err) { 1309ff268b56SStephen Boyd rdev_dbg(rdev, "could not add device link %s err %d\n", 13101d7372e1SDaniel Walker dev->kobj.name, err); 1311222cc7b1SMark Brown /* non-fatal */ 1312414c70cbSLiam Girdwood } 13135de70519SMark Brown } else { 13145de70519SMark Brown regulator->supply_name = kstrdup(supply_name, GFP_KERNEL); 13155de70519SMark Brown if (regulator->supply_name == NULL) 1316222cc7b1SMark Brown goto overflow_err; 1317414c70cbSLiam Girdwood } 13185de70519SMark Brown 13195de70519SMark Brown regulator->debugfs = debugfs_create_dir(regulator->supply_name, 13205de70519SMark Brown rdev->debugfs); 132124751434SStephen Boyd if (!regulator->debugfs) { 1322ad3a942bSStephen Boyd rdev_dbg(rdev, "Failed to create debugfs directory\n"); 13235de70519SMark Brown } else { 13245de70519SMark Brown debugfs_create_u32("uA_load", 0444, regulator->debugfs, 13255de70519SMark Brown ®ulator->uA_load); 13265de70519SMark Brown debugfs_create_u32("min_uV", 0444, regulator->debugfs, 13275de70519SMark Brown ®ulator->min_uV); 13285de70519SMark Brown debugfs_create_u32("max_uV", 0444, regulator->debugfs, 13295de70519SMark Brown ®ulator->max_uV); 13305de70519SMark Brown } 13315de70519SMark Brown 13326492bc1bSMark Brown /* 13336492bc1bSMark Brown * Check now if the regulator is an always on regulator - if 13346492bc1bSMark Brown * it is then we don't need to do nearly so much work for 13356492bc1bSMark Brown * enable/disable calls. 13366492bc1bSMark Brown */ 13376492bc1bSMark Brown if (!_regulator_can_change_status(rdev) && 13386492bc1bSMark Brown _regulator_is_enabled(rdev)) 13396492bc1bSMark Brown regulator->always_on = true; 13406492bc1bSMark Brown 1341414c70cbSLiam Girdwood mutex_unlock(&rdev->mutex); 1342414c70cbSLiam Girdwood return regulator; 1343414c70cbSLiam Girdwood overflow_err: 1344414c70cbSLiam Girdwood list_del(®ulator->list); 1345414c70cbSLiam Girdwood kfree(regulator); 1346414c70cbSLiam Girdwood mutex_unlock(&rdev->mutex); 1347414c70cbSLiam Girdwood return NULL; 1348414c70cbSLiam Girdwood } 1349414c70cbSLiam Girdwood 135031aae2beSMark Brown static int _regulator_get_enable_time(struct regulator_dev *rdev) 135131aae2beSMark Brown { 135200c877c6SLaxman Dewangan if (rdev->constraints && rdev->constraints->enable_time) 135300c877c6SLaxman Dewangan return rdev->constraints->enable_time; 135431aae2beSMark Brown if (!rdev->desc->ops->enable_time) 135579511ed3SMark Brown return rdev->desc->enable_time; 135631aae2beSMark Brown return rdev->desc->ops->enable_time(rdev); 135731aae2beSMark Brown } 135831aae2beSMark Brown 1359a06ccd9cSCharles Keepax static struct regulator_supply_alias *regulator_find_supply_alias( 1360a06ccd9cSCharles Keepax struct device *dev, const char *supply) 1361a06ccd9cSCharles Keepax { 1362a06ccd9cSCharles Keepax struct regulator_supply_alias *map; 1363a06ccd9cSCharles Keepax 1364a06ccd9cSCharles Keepax list_for_each_entry(map, ®ulator_supply_alias_list, list) 1365a06ccd9cSCharles Keepax if (map->src_dev == dev && strcmp(map->src_supply, supply) == 0) 1366a06ccd9cSCharles Keepax return map; 1367a06ccd9cSCharles Keepax 1368a06ccd9cSCharles Keepax return NULL; 1369a06ccd9cSCharles Keepax } 1370a06ccd9cSCharles Keepax 1371a06ccd9cSCharles Keepax static void regulator_supply_alias(struct device **dev, const char **supply) 1372a06ccd9cSCharles Keepax { 1373a06ccd9cSCharles Keepax struct regulator_supply_alias *map; 1374a06ccd9cSCharles Keepax 1375a06ccd9cSCharles Keepax map = regulator_find_supply_alias(*dev, *supply); 1376a06ccd9cSCharles Keepax if (map) { 1377a06ccd9cSCharles Keepax dev_dbg(*dev, "Mapping supply %s to %s,%s\n", 1378a06ccd9cSCharles Keepax *supply, map->alias_supply, 1379a06ccd9cSCharles Keepax dev_name(map->alias_dev)); 1380a06ccd9cSCharles Keepax *dev = map->alias_dev; 1381a06ccd9cSCharles Keepax *supply = map->alias_supply; 1382a06ccd9cSCharles Keepax } 1383a06ccd9cSCharles Keepax } 1384a06ccd9cSCharles Keepax 138585f3b431STomeu Vizoso static int of_node_match(struct device *dev, const void *data) 138685f3b431STomeu Vizoso { 138785f3b431STomeu Vizoso return dev->of_node == data; 138885f3b431STomeu Vizoso } 138985f3b431STomeu Vizoso 139085f3b431STomeu Vizoso static struct regulator_dev *of_find_regulator_by_node(struct device_node *np) 139185f3b431STomeu Vizoso { 139285f3b431STomeu Vizoso struct device *dev; 139385f3b431STomeu Vizoso 139485f3b431STomeu Vizoso dev = class_find_device(®ulator_class, NULL, np, of_node_match); 139585f3b431STomeu Vizoso 139685f3b431STomeu Vizoso return dev ? dev_to_rdev(dev) : NULL; 139785f3b431STomeu Vizoso } 139885f3b431STomeu Vizoso 139985f3b431STomeu Vizoso static int regulator_match(struct device *dev, const void *data) 140085f3b431STomeu Vizoso { 140185f3b431STomeu Vizoso struct regulator_dev *r = dev_to_rdev(dev); 140285f3b431STomeu Vizoso 140385f3b431STomeu Vizoso return strcmp(rdev_get_name(r), data) == 0; 140485f3b431STomeu Vizoso } 140585f3b431STomeu Vizoso 140685f3b431STomeu Vizoso static struct regulator_dev *regulator_lookup_by_name(const char *name) 140785f3b431STomeu Vizoso { 140885f3b431STomeu Vizoso struct device *dev; 140985f3b431STomeu Vizoso 141085f3b431STomeu Vizoso dev = class_find_device(®ulator_class, NULL, name, regulator_match); 141185f3b431STomeu Vizoso 141285f3b431STomeu Vizoso return dev ? dev_to_rdev(dev) : NULL; 141385f3b431STomeu Vizoso } 141485f3b431STomeu Vizoso 141585f3b431STomeu Vizoso /** 141685f3b431STomeu Vizoso * regulator_dev_lookup - lookup a regulator device. 141785f3b431STomeu Vizoso * @dev: device for regulator "consumer". 141885f3b431STomeu Vizoso * @supply: Supply name or regulator ID. 141985f3b431STomeu Vizoso * @ret: 0 on success, -ENODEV if lookup fails permanently, -EPROBE_DEFER if 142085f3b431STomeu Vizoso * lookup could succeed in the future. 142185f3b431STomeu Vizoso * 142285f3b431STomeu Vizoso * If successful, returns a struct regulator_dev that corresponds to the name 142385f3b431STomeu Vizoso * @supply and with the embedded struct device refcount incremented by one, 142485f3b431STomeu Vizoso * or NULL on failure. The refcount must be dropped by calling put_device(). 142585f3b431STomeu Vizoso */ 142669511a45SRajendra Nayak static struct regulator_dev *regulator_dev_lookup(struct device *dev, 14276d191a5fSMark Brown const char *supply, 14286d191a5fSMark Brown int *ret) 142969511a45SRajendra Nayak { 143069511a45SRajendra Nayak struct regulator_dev *r; 143169511a45SRajendra Nayak struct device_node *node; 1432576ca436SMark Brown struct regulator_map *map; 1433576ca436SMark Brown const char *devname = NULL; 143469511a45SRajendra Nayak 1435a06ccd9cSCharles Keepax regulator_supply_alias(&dev, &supply); 1436a06ccd9cSCharles Keepax 143769511a45SRajendra Nayak /* first do a dt based lookup */ 143869511a45SRajendra Nayak if (dev && dev->of_node) { 143969511a45SRajendra Nayak node = of_get_regulator(dev, supply); 14406d191a5fSMark Brown if (node) { 144185f3b431STomeu Vizoso r = of_find_regulator_by_node(node); 144285f3b431STomeu Vizoso if (r) 144369511a45SRajendra Nayak return r; 1444317b5684SMark Brown *ret = -EPROBE_DEFER; 1445317b5684SMark Brown return NULL; 14466d191a5fSMark Brown } else { 14476d191a5fSMark Brown /* 14486d191a5fSMark Brown * If we couldn't even get the node then it's 14496d191a5fSMark Brown * not just that the device didn't register 14506d191a5fSMark Brown * yet, there's no node and we'll never 14516d191a5fSMark Brown * succeed. 14526d191a5fSMark Brown */ 14536d191a5fSMark Brown *ret = -ENODEV; 14546d191a5fSMark Brown } 145569511a45SRajendra Nayak } 145669511a45SRajendra Nayak 145769511a45SRajendra Nayak /* if not found, try doing it non-dt way */ 1458576ca436SMark Brown if (dev) 1459576ca436SMark Brown devname = dev_name(dev); 1460576ca436SMark Brown 146185f3b431STomeu Vizoso r = regulator_lookup_by_name(supply); 146285f3b431STomeu Vizoso if (r) 146369511a45SRajendra Nayak return r; 146469511a45SRajendra Nayak 146585f3b431STomeu Vizoso mutex_lock(®ulator_list_mutex); 1466576ca436SMark Brown list_for_each_entry(map, ®ulator_map_list, list) { 1467576ca436SMark Brown /* If the mapping has a device set up it must match */ 1468576ca436SMark Brown if (map->dev_name && 1469576ca436SMark Brown (!devname || strcmp(map->dev_name, devname))) 1470576ca436SMark Brown continue; 1471576ca436SMark Brown 147285f3b431STomeu Vizoso if (strcmp(map->supply, supply) == 0 && 147385f3b431STomeu Vizoso get_device(&map->regulator->dev)) { 147485f3b431STomeu Vizoso mutex_unlock(®ulator_list_mutex); 1475576ca436SMark Brown return map->regulator; 1476576ca436SMark Brown } 147785f3b431STomeu Vizoso } 147885f3b431STomeu Vizoso mutex_unlock(®ulator_list_mutex); 1479576ca436SMark Brown 148069511a45SRajendra Nayak return NULL; 148169511a45SRajendra Nayak } 148269511a45SRajendra Nayak 14836261b06dSBjorn Andersson static int regulator_resolve_supply(struct regulator_dev *rdev) 14846261b06dSBjorn Andersson { 14856261b06dSBjorn Andersson struct regulator_dev *r; 14866261b06dSBjorn Andersson struct device *dev = rdev->dev.parent; 14876261b06dSBjorn Andersson int ret; 14886261b06dSBjorn Andersson 14896261b06dSBjorn Andersson /* No supply to resovle? */ 14906261b06dSBjorn Andersson if (!rdev->supply_name) 14916261b06dSBjorn Andersson return 0; 14926261b06dSBjorn Andersson 14936261b06dSBjorn Andersson /* Supply already resolved? */ 14946261b06dSBjorn Andersson if (rdev->supply) 14956261b06dSBjorn Andersson return 0; 14966261b06dSBjorn Andersson 14976261b06dSBjorn Andersson r = regulator_dev_lookup(dev, rdev->supply_name, &ret); 149823c3f310SCharles Keepax if (!r) { 14996261b06dSBjorn Andersson if (ret == -ENODEV) { 15006261b06dSBjorn Andersson /* 15016261b06dSBjorn Andersson * No supply was specified for this regulator and 15026261b06dSBjorn Andersson * there will never be one. 15036261b06dSBjorn Andersson */ 15046261b06dSBjorn Andersson return 0; 15056261b06dSBjorn Andersson } 15066261b06dSBjorn Andersson 150706423121SMark Brown /* Did the lookup explicitly defer for us? */ 150806423121SMark Brown if (ret == -EPROBE_DEFER) 150906423121SMark Brown return ret; 151006423121SMark Brown 15119f7e25edSMark Brown if (have_full_constraints()) { 15129f7e25edSMark Brown r = dummy_regulator_rdev; 151385f3b431STomeu Vizoso get_device(&r->dev); 15149f7e25edSMark Brown } else { 15156261b06dSBjorn Andersson dev_err(dev, "Failed to resolve %s-supply for %s\n", 15166261b06dSBjorn Andersson rdev->supply_name, rdev->desc->name); 15176261b06dSBjorn Andersson return -EPROBE_DEFER; 15186261b06dSBjorn Andersson } 15199f7e25edSMark Brown } 15206261b06dSBjorn Andersson 15216261b06dSBjorn Andersson /* Recursively resolve the supply of the supply */ 15226261b06dSBjorn Andersson ret = regulator_resolve_supply(r); 152385f3b431STomeu Vizoso if (ret < 0) { 152485f3b431STomeu Vizoso put_device(&r->dev); 15256261b06dSBjorn Andersson return ret; 152685f3b431STomeu Vizoso } 15276261b06dSBjorn Andersson 15286261b06dSBjorn Andersson ret = set_supply(rdev, r); 152985f3b431STomeu Vizoso if (ret < 0) { 153085f3b431STomeu Vizoso put_device(&r->dev); 15316261b06dSBjorn Andersson return ret; 153285f3b431STomeu Vizoso } 15336261b06dSBjorn Andersson 15346261b06dSBjorn Andersson /* Cascade always-on state to supply */ 153595a293c7SJavier Martinez Canillas if (_regulator_is_enabled(rdev)) { 15366261b06dSBjorn Andersson ret = regulator_enable(rdev->supply); 153736a1f1b6SJavier Martinez Canillas if (ret < 0) { 153836a1f1b6SJavier Martinez Canillas _regulator_put(rdev->supply); 15396261b06dSBjorn Andersson return ret; 15406261b06dSBjorn Andersson } 154136a1f1b6SJavier Martinez Canillas } 15426261b06dSBjorn Andersson 15436261b06dSBjorn Andersson return 0; 15446261b06dSBjorn Andersson } 15456261b06dSBjorn Andersson 15465ffbd136SMark Brown /* Internal regulator request function */ 15475ffbd136SMark Brown static struct regulator *_regulator_get(struct device *dev, const char *id, 15484ddfebd3SMark Brown bool exclusive, bool allow_dummy) 1549414c70cbSLiam Girdwood { 1550414c70cbSLiam Girdwood struct regulator_dev *rdev; 155104bf3011SMark Brown struct regulator *regulator = ERR_PTR(-EPROBE_DEFER); 155240f9244fSMark Brown const char *devname = NULL; 1553317b5684SMark Brown int ret; 1554414c70cbSLiam Girdwood 1555414c70cbSLiam Girdwood if (id == NULL) { 15565da84fd9SJoe Perches pr_err("get() with no identifier\n"); 1557043c998fSMark Brown return ERR_PTR(-EINVAL); 1558414c70cbSLiam Girdwood } 1559414c70cbSLiam Girdwood 156040f9244fSMark Brown if (dev) 156140f9244fSMark Brown devname = dev_name(dev); 156240f9244fSMark Brown 1563317b5684SMark Brown if (have_full_constraints()) 1564317b5684SMark Brown ret = -ENODEV; 1565317b5684SMark Brown else 1566317b5684SMark Brown ret = -EPROBE_DEFER; 1567317b5684SMark Brown 15686d191a5fSMark Brown rdev = regulator_dev_lookup(dev, id, &ret); 156969511a45SRajendra Nayak if (rdev) 157069511a45SRajendra Nayak goto found; 157169511a45SRajendra Nayak 1572ef60abbbSMark Brown regulator = ERR_PTR(ret); 1573ef60abbbSMark Brown 15741e4b545cSNishanth Menon /* 15751e4b545cSNishanth Menon * If we have return value from dev_lookup fail, we do not expect to 15761e4b545cSNishanth Menon * succeed, so, quit with appropriate error value 15771e4b545cSNishanth Menon */ 15780d25d09dSJingoo Han if (ret && ret != -ENODEV) 157985f3b431STomeu Vizoso return regulator; 15801e4b545cSNishanth Menon 158134abbd68SMark Brown if (!devname) 158234abbd68SMark Brown devname = "deviceless"; 158334abbd68SMark Brown 15844ddfebd3SMark Brown /* 15854ddfebd3SMark Brown * Assume that a regulator is physically present and enabled 15864ddfebd3SMark Brown * even if it isn't hooked up and just provide a dummy. 158734abbd68SMark Brown */ 158887b28417SMark Brown if (have_full_constraints() && allow_dummy) { 15895da84fd9SJoe Perches pr_warn("%s supply %s not found, using dummy regulator\n", 159034abbd68SMark Brown devname, id); 15914ddfebd3SMark Brown 159234abbd68SMark Brown rdev = dummy_regulator_rdev; 159385f3b431STomeu Vizoso get_device(&rdev->dev); 159434abbd68SMark Brown goto found; 15950781719bSHans de Goede /* Don't log an error when called from regulator_get_optional() */ 15960781719bSHans de Goede } else if (!have_full_constraints() || exclusive) { 1597acc3d5ceSShuah Khan dev_warn(dev, "dummy supplies not allowed\n"); 159834abbd68SMark Brown } 159934abbd68SMark Brown 1600414c70cbSLiam Girdwood return regulator; 1601414c70cbSLiam Girdwood 1602414c70cbSLiam Girdwood found: 16035ffbd136SMark Brown if (rdev->exclusive) { 16045ffbd136SMark Brown regulator = ERR_PTR(-EPERM); 160585f3b431STomeu Vizoso put_device(&rdev->dev); 160685f3b431STomeu Vizoso return regulator; 16075ffbd136SMark Brown } 16085ffbd136SMark Brown 16095ffbd136SMark Brown if (exclusive && rdev->open_count) { 16105ffbd136SMark Brown regulator = ERR_PTR(-EBUSY); 161185f3b431STomeu Vizoso put_device(&rdev->dev); 161285f3b431STomeu Vizoso return regulator; 16135ffbd136SMark Brown } 16145ffbd136SMark Brown 16156261b06dSBjorn Andersson ret = regulator_resolve_supply(rdev); 16166261b06dSBjorn Andersson if (ret < 0) { 16176261b06dSBjorn Andersson regulator = ERR_PTR(ret); 161885f3b431STomeu Vizoso put_device(&rdev->dev); 161985f3b431STomeu Vizoso return regulator; 16206261b06dSBjorn Andersson } 16216261b06dSBjorn Andersson 162285f3b431STomeu Vizoso if (!try_module_get(rdev->owner)) { 162385f3b431STomeu Vizoso put_device(&rdev->dev); 162485f3b431STomeu Vizoso return regulator; 162585f3b431STomeu Vizoso } 1626a5766f11SLiam Girdwood 1627414c70cbSLiam Girdwood regulator = create_regulator(rdev, dev, id); 1628414c70cbSLiam Girdwood if (regulator == NULL) { 1629414c70cbSLiam Girdwood regulator = ERR_PTR(-ENOMEM); 163085f3b431STomeu Vizoso put_device(&rdev->dev); 1631414c70cbSLiam Girdwood module_put(rdev->owner); 163285f3b431STomeu Vizoso return regulator; 1633414c70cbSLiam Girdwood } 1634414c70cbSLiam Girdwood 16355ffbd136SMark Brown rdev->open_count++; 16365ffbd136SMark Brown if (exclusive) { 16375ffbd136SMark Brown rdev->exclusive = 1; 16385ffbd136SMark Brown 16395ffbd136SMark Brown ret = _regulator_is_enabled(rdev); 16405ffbd136SMark Brown if (ret > 0) 16415ffbd136SMark Brown rdev->use_count = 1; 16425ffbd136SMark Brown else 16435ffbd136SMark Brown rdev->use_count = 0; 16445ffbd136SMark Brown } 16455ffbd136SMark Brown 1646414c70cbSLiam Girdwood return regulator; 1647414c70cbSLiam Girdwood } 16485ffbd136SMark Brown 16495ffbd136SMark Brown /** 16505ffbd136SMark Brown * regulator_get - lookup and obtain a reference to a regulator. 16515ffbd136SMark Brown * @dev: device for regulator "consumer" 16525ffbd136SMark Brown * @id: Supply name or regulator ID. 16535ffbd136SMark Brown * 16545ffbd136SMark Brown * Returns a struct regulator corresponding to the regulator producer, 16555ffbd136SMark Brown * or IS_ERR() condition containing errno. 16565ffbd136SMark Brown * 16575ffbd136SMark Brown * Use of supply names configured via regulator_set_device_supply() is 16585ffbd136SMark Brown * strongly encouraged. It is recommended that the supply name used 16595ffbd136SMark Brown * should match the name used for the supply and/or the relevant 16605ffbd136SMark Brown * device pins in the datasheet. 16615ffbd136SMark Brown */ 16625ffbd136SMark Brown struct regulator *regulator_get(struct device *dev, const char *id) 16635ffbd136SMark Brown { 16644ddfebd3SMark Brown return _regulator_get(dev, id, false, true); 16655ffbd136SMark Brown } 1666414c70cbSLiam Girdwood EXPORT_SYMBOL_GPL(regulator_get); 1667414c70cbSLiam Girdwood 1668070b9079SStephen Boyd /** 16695ffbd136SMark Brown * regulator_get_exclusive - obtain exclusive access to a regulator. 16705ffbd136SMark Brown * @dev: device for regulator "consumer" 16715ffbd136SMark Brown * @id: Supply name or regulator ID. 16725ffbd136SMark Brown * 16735ffbd136SMark Brown * Returns a struct regulator corresponding to the regulator producer, 16745ffbd136SMark Brown * or IS_ERR() condition containing errno. Other consumers will be 167569c3f723SStephen Boyd * unable to obtain this regulator while this reference is held and the 167669c3f723SStephen Boyd * use count for the regulator will be initialised to reflect the current 167769c3f723SStephen Boyd * state of the regulator. 16785ffbd136SMark Brown * 16795ffbd136SMark Brown * This is intended for use by consumers which cannot tolerate shared 16805ffbd136SMark Brown * use of the regulator such as those which need to force the 16815ffbd136SMark Brown * regulator off for correct operation of the hardware they are 16825ffbd136SMark Brown * controlling. 16835ffbd136SMark Brown * 16845ffbd136SMark Brown * Use of supply names configured via regulator_set_device_supply() is 16855ffbd136SMark Brown * strongly encouraged. It is recommended that the supply name used 16865ffbd136SMark Brown * should match the name used for the supply and/or the relevant 16875ffbd136SMark Brown * device pins in the datasheet. 16885ffbd136SMark Brown */ 16895ffbd136SMark Brown struct regulator *regulator_get_exclusive(struct device *dev, const char *id) 16905ffbd136SMark Brown { 16914ddfebd3SMark Brown return _regulator_get(dev, id, true, false); 16925ffbd136SMark Brown } 16935ffbd136SMark Brown EXPORT_SYMBOL_GPL(regulator_get_exclusive); 16945ffbd136SMark Brown 1695de1dd9fdSMark Brown /** 1696de1dd9fdSMark Brown * regulator_get_optional - obtain optional access to a regulator. 1697de1dd9fdSMark Brown * @dev: device for regulator "consumer" 1698de1dd9fdSMark Brown * @id: Supply name or regulator ID. 1699de1dd9fdSMark Brown * 1700de1dd9fdSMark Brown * Returns a struct regulator corresponding to the regulator producer, 170169c3f723SStephen Boyd * or IS_ERR() condition containing errno. 1702de1dd9fdSMark Brown * 1703de1dd9fdSMark Brown * This is intended for use by consumers for devices which can have 1704de1dd9fdSMark Brown * some supplies unconnected in normal use, such as some MMC devices. 1705de1dd9fdSMark Brown * It can allow the regulator core to provide stub supplies for other 1706de1dd9fdSMark Brown * supplies requested using normal regulator_get() calls without 1707de1dd9fdSMark Brown * disrupting the operation of drivers that can handle absent 1708de1dd9fdSMark Brown * supplies. 1709de1dd9fdSMark Brown * 1710de1dd9fdSMark Brown * Use of supply names configured via regulator_set_device_supply() is 1711de1dd9fdSMark Brown * strongly encouraged. It is recommended that the supply name used 1712de1dd9fdSMark Brown * should match the name used for the supply and/or the relevant 1713de1dd9fdSMark Brown * device pins in the datasheet. 1714de1dd9fdSMark Brown */ 1715de1dd9fdSMark Brown struct regulator *regulator_get_optional(struct device *dev, const char *id) 1716de1dd9fdSMark Brown { 17174ddfebd3SMark Brown return _regulator_get(dev, id, false, false); 1718de1dd9fdSMark Brown } 1719de1dd9fdSMark Brown EXPORT_SYMBOL_GPL(regulator_get_optional); 1720de1dd9fdSMark Brown 172183b0302dSAshay Jaiswal /* regulator_list_mutex lock held by regulator_put() */ 172223ff2f0fSCharles Keepax static void _regulator_put(struct regulator *regulator) 1723414c70cbSLiam Girdwood { 1724414c70cbSLiam Girdwood struct regulator_dev *rdev; 1725414c70cbSLiam Girdwood 172693576842SViresh Kumar if (IS_ERR_OR_NULL(regulator)) 1727414c70cbSLiam Girdwood return; 1728414c70cbSLiam Girdwood 172970cfef26SKrzysztof Kozlowski lockdep_assert_held_once(®ulator_list_mutex); 173070cfef26SKrzysztof Kozlowski 1731414c70cbSLiam Girdwood rdev = regulator->rdev; 1732414c70cbSLiam Girdwood 17335de70519SMark Brown debugfs_remove_recursive(regulator->debugfs); 17345de70519SMark Brown 1735414c70cbSLiam Girdwood /* remove any sysfs entries */ 1736e2c98eafSShawn Guo if (regulator->dev) 1737414c70cbSLiam Girdwood sysfs_remove_link(&rdev->dev.kobj, regulator->supply_name); 173883b0302dSAshay Jaiswal mutex_lock(&rdev->mutex); 1739414c70cbSLiam Girdwood list_del(®ulator->list); 1740414c70cbSLiam Girdwood 17415ffbd136SMark Brown rdev->open_count--; 17425ffbd136SMark Brown rdev->exclusive = 0; 174385f3b431STomeu Vizoso put_device(&rdev->dev); 174483b0302dSAshay Jaiswal mutex_unlock(&rdev->mutex); 17455ffbd136SMark Brown 17461768514eSMark Brown kfree(regulator->supply_name); 17471768514eSMark Brown kfree(regulator); 17481768514eSMark Brown 1749414c70cbSLiam Girdwood module_put(rdev->owner); 175023ff2f0fSCharles Keepax } 175123ff2f0fSCharles Keepax 175223ff2f0fSCharles Keepax /** 175323ff2f0fSCharles Keepax * regulator_put - "free" the regulator source 175423ff2f0fSCharles Keepax * @regulator: regulator source 175523ff2f0fSCharles Keepax * 175623ff2f0fSCharles Keepax * Note: drivers must ensure that all regulator_enable calls made on this 175723ff2f0fSCharles Keepax * regulator source are balanced by regulator_disable calls prior to calling 175823ff2f0fSCharles Keepax * this function. 175923ff2f0fSCharles Keepax */ 176023ff2f0fSCharles Keepax void regulator_put(struct regulator *regulator) 176123ff2f0fSCharles Keepax { 176223ff2f0fSCharles Keepax mutex_lock(®ulator_list_mutex); 176323ff2f0fSCharles Keepax _regulator_put(regulator); 1764414c70cbSLiam Girdwood mutex_unlock(®ulator_list_mutex); 1765414c70cbSLiam Girdwood } 1766414c70cbSLiam Girdwood EXPORT_SYMBOL_GPL(regulator_put); 1767414c70cbSLiam Girdwood 1768a06ccd9cSCharles Keepax /** 1769a06ccd9cSCharles Keepax * regulator_register_supply_alias - Provide device alias for supply lookup 1770a06ccd9cSCharles Keepax * 1771a06ccd9cSCharles Keepax * @dev: device that will be given as the regulator "consumer" 1772a06ccd9cSCharles Keepax * @id: Supply name or regulator ID 1773a06ccd9cSCharles Keepax * @alias_dev: device that should be used to lookup the supply 1774a06ccd9cSCharles Keepax * @alias_id: Supply name or regulator ID that should be used to lookup the 1775a06ccd9cSCharles Keepax * supply 1776a06ccd9cSCharles Keepax * 1777a06ccd9cSCharles Keepax * All lookups for id on dev will instead be conducted for alias_id on 1778a06ccd9cSCharles Keepax * alias_dev. 1779a06ccd9cSCharles Keepax */ 1780a06ccd9cSCharles Keepax int regulator_register_supply_alias(struct device *dev, const char *id, 1781a06ccd9cSCharles Keepax struct device *alias_dev, 1782a06ccd9cSCharles Keepax const char *alias_id) 1783a06ccd9cSCharles Keepax { 1784a06ccd9cSCharles Keepax struct regulator_supply_alias *map; 1785a06ccd9cSCharles Keepax 1786a06ccd9cSCharles Keepax map = regulator_find_supply_alias(dev, id); 1787a06ccd9cSCharles Keepax if (map) 1788a06ccd9cSCharles Keepax return -EEXIST; 1789a06ccd9cSCharles Keepax 1790a06ccd9cSCharles Keepax map = kzalloc(sizeof(struct regulator_supply_alias), GFP_KERNEL); 1791a06ccd9cSCharles Keepax if (!map) 1792a06ccd9cSCharles Keepax return -ENOMEM; 1793a06ccd9cSCharles Keepax 1794a06ccd9cSCharles Keepax map->src_dev = dev; 1795a06ccd9cSCharles Keepax map->src_supply = id; 1796a06ccd9cSCharles Keepax map->alias_dev = alias_dev; 1797a06ccd9cSCharles Keepax map->alias_supply = alias_id; 1798a06ccd9cSCharles Keepax 1799a06ccd9cSCharles Keepax list_add(&map->list, ®ulator_supply_alias_list); 1800a06ccd9cSCharles Keepax 1801a06ccd9cSCharles Keepax pr_info("Adding alias for supply %s,%s -> %s,%s\n", 1802a06ccd9cSCharles Keepax id, dev_name(dev), alias_id, dev_name(alias_dev)); 1803a06ccd9cSCharles Keepax 1804a06ccd9cSCharles Keepax return 0; 1805a06ccd9cSCharles Keepax } 1806a06ccd9cSCharles Keepax EXPORT_SYMBOL_GPL(regulator_register_supply_alias); 1807a06ccd9cSCharles Keepax 1808a06ccd9cSCharles Keepax /** 1809a06ccd9cSCharles Keepax * regulator_unregister_supply_alias - Remove device alias 1810a06ccd9cSCharles Keepax * 1811a06ccd9cSCharles Keepax * @dev: device that will be given as the regulator "consumer" 1812a06ccd9cSCharles Keepax * @id: Supply name or regulator ID 1813a06ccd9cSCharles Keepax * 1814a06ccd9cSCharles Keepax * Remove a lookup alias if one exists for id on dev. 1815a06ccd9cSCharles Keepax */ 1816a06ccd9cSCharles Keepax void regulator_unregister_supply_alias(struct device *dev, const char *id) 1817a06ccd9cSCharles Keepax { 1818a06ccd9cSCharles Keepax struct regulator_supply_alias *map; 1819a06ccd9cSCharles Keepax 1820a06ccd9cSCharles Keepax map = regulator_find_supply_alias(dev, id); 1821a06ccd9cSCharles Keepax if (map) { 1822a06ccd9cSCharles Keepax list_del(&map->list); 1823a06ccd9cSCharles Keepax kfree(map); 1824a06ccd9cSCharles Keepax } 1825a06ccd9cSCharles Keepax } 1826a06ccd9cSCharles Keepax EXPORT_SYMBOL_GPL(regulator_unregister_supply_alias); 1827a06ccd9cSCharles Keepax 1828a06ccd9cSCharles Keepax /** 1829a06ccd9cSCharles Keepax * regulator_bulk_register_supply_alias - register multiple aliases 1830a06ccd9cSCharles Keepax * 1831a06ccd9cSCharles Keepax * @dev: device that will be given as the regulator "consumer" 1832a06ccd9cSCharles Keepax * @id: List of supply names or regulator IDs 1833a06ccd9cSCharles Keepax * @alias_dev: device that should be used to lookup the supply 1834a06ccd9cSCharles Keepax * @alias_id: List of supply names or regulator IDs that should be used to 1835a06ccd9cSCharles Keepax * lookup the supply 1836a06ccd9cSCharles Keepax * @num_id: Number of aliases to register 1837a06ccd9cSCharles Keepax * 1838a06ccd9cSCharles Keepax * @return 0 on success, an errno on failure. 1839a06ccd9cSCharles Keepax * 1840a06ccd9cSCharles Keepax * This helper function allows drivers to register several supply 1841a06ccd9cSCharles Keepax * aliases in one operation. If any of the aliases cannot be 1842a06ccd9cSCharles Keepax * registered any aliases that were registered will be removed 1843a06ccd9cSCharles Keepax * before returning to the caller. 1844a06ccd9cSCharles Keepax */ 18459f8c0fe9SLee Jones int regulator_bulk_register_supply_alias(struct device *dev, 18469f8c0fe9SLee Jones const char *const *id, 1847a06ccd9cSCharles Keepax struct device *alias_dev, 18489f8c0fe9SLee Jones const char *const *alias_id, 1849a06ccd9cSCharles Keepax int num_id) 1850a06ccd9cSCharles Keepax { 1851a06ccd9cSCharles Keepax int i; 1852a06ccd9cSCharles Keepax int ret; 1853a06ccd9cSCharles Keepax 1854a06ccd9cSCharles Keepax for (i = 0; i < num_id; ++i) { 1855a06ccd9cSCharles Keepax ret = regulator_register_supply_alias(dev, id[i], alias_dev, 1856a06ccd9cSCharles Keepax alias_id[i]); 1857a06ccd9cSCharles Keepax if (ret < 0) 1858a06ccd9cSCharles Keepax goto err; 1859a06ccd9cSCharles Keepax } 1860a06ccd9cSCharles Keepax 1861a06ccd9cSCharles Keepax return 0; 1862a06ccd9cSCharles Keepax 1863a06ccd9cSCharles Keepax err: 1864a06ccd9cSCharles Keepax dev_err(dev, 1865a06ccd9cSCharles Keepax "Failed to create supply alias %s,%s -> %s,%s\n", 1866a06ccd9cSCharles Keepax id[i], dev_name(dev), alias_id[i], dev_name(alias_dev)); 1867a06ccd9cSCharles Keepax 1868a06ccd9cSCharles Keepax while (--i >= 0) 1869a06ccd9cSCharles Keepax regulator_unregister_supply_alias(dev, id[i]); 1870a06ccd9cSCharles Keepax 1871a06ccd9cSCharles Keepax return ret; 1872a06ccd9cSCharles Keepax } 1873a06ccd9cSCharles Keepax EXPORT_SYMBOL_GPL(regulator_bulk_register_supply_alias); 1874a06ccd9cSCharles Keepax 1875a06ccd9cSCharles Keepax /** 1876a06ccd9cSCharles Keepax * regulator_bulk_unregister_supply_alias - unregister multiple aliases 1877a06ccd9cSCharles Keepax * 1878a06ccd9cSCharles Keepax * @dev: device that will be given as the regulator "consumer" 1879a06ccd9cSCharles Keepax * @id: List of supply names or regulator IDs 1880a06ccd9cSCharles Keepax * @num_id: Number of aliases to unregister 1881a06ccd9cSCharles Keepax * 1882a06ccd9cSCharles Keepax * This helper function allows drivers to unregister several supply 1883a06ccd9cSCharles Keepax * aliases in one operation. 1884a06ccd9cSCharles Keepax */ 1885a06ccd9cSCharles Keepax void regulator_bulk_unregister_supply_alias(struct device *dev, 18869f8c0fe9SLee Jones const char *const *id, 1887a06ccd9cSCharles Keepax int num_id) 1888a06ccd9cSCharles Keepax { 1889a06ccd9cSCharles Keepax int i; 1890a06ccd9cSCharles Keepax 1891a06ccd9cSCharles Keepax for (i = 0; i < num_id; ++i) 1892a06ccd9cSCharles Keepax regulator_unregister_supply_alias(dev, id[i]); 1893a06ccd9cSCharles Keepax } 1894a06ccd9cSCharles Keepax EXPORT_SYMBOL_GPL(regulator_bulk_unregister_supply_alias); 1895a06ccd9cSCharles Keepax 1896a06ccd9cSCharles Keepax 1897f19b00daSKim, Milo /* Manage enable GPIO list. Same GPIO pin can be shared among regulators */ 1898f19b00daSKim, Milo static int regulator_ena_gpio_request(struct regulator_dev *rdev, 1899f19b00daSKim, Milo const struct regulator_config *config) 1900f19b00daSKim, Milo { 1901f19b00daSKim, Milo struct regulator_enable_gpio *pin; 1902778b28b4SRussell King struct gpio_desc *gpiod; 1903f19b00daSKim, Milo int ret; 1904f19b00daSKim, Milo 1905778b28b4SRussell King gpiod = gpio_to_desc(config->ena_gpio); 1906778b28b4SRussell King 1907f19b00daSKim, Milo list_for_each_entry(pin, ®ulator_ena_gpio_list, list) { 1908778b28b4SRussell King if (pin->gpiod == gpiod) { 1909f19b00daSKim, Milo rdev_dbg(rdev, "GPIO %d is already used\n", 1910f19b00daSKim, Milo config->ena_gpio); 1911f19b00daSKim, Milo goto update_ena_gpio_to_rdev; 1912f19b00daSKim, Milo } 1913f19b00daSKim, Milo } 1914f19b00daSKim, Milo 1915f19b00daSKim, Milo ret = gpio_request_one(config->ena_gpio, 1916f19b00daSKim, Milo GPIOF_DIR_OUT | config->ena_gpio_flags, 1917f19b00daSKim, Milo rdev_get_name(rdev)); 1918f19b00daSKim, Milo if (ret) 1919f19b00daSKim, Milo return ret; 1920f19b00daSKim, Milo 1921f19b00daSKim, Milo pin = kzalloc(sizeof(struct regulator_enable_gpio), GFP_KERNEL); 1922f19b00daSKim, Milo if (pin == NULL) { 1923f19b00daSKim, Milo gpio_free(config->ena_gpio); 1924f19b00daSKim, Milo return -ENOMEM; 1925f19b00daSKim, Milo } 1926f19b00daSKim, Milo 1927778b28b4SRussell King pin->gpiod = gpiod; 1928f19b00daSKim, Milo pin->ena_gpio_invert = config->ena_gpio_invert; 1929f19b00daSKim, Milo list_add(&pin->list, ®ulator_ena_gpio_list); 1930f19b00daSKim, Milo 1931f19b00daSKim, Milo update_ena_gpio_to_rdev: 1932f19b00daSKim, Milo pin->request_count++; 1933f19b00daSKim, Milo rdev->ena_pin = pin; 1934f19b00daSKim, Milo return 0; 1935f19b00daSKim, Milo } 1936f19b00daSKim, Milo 1937f19b00daSKim, Milo static void regulator_ena_gpio_free(struct regulator_dev *rdev) 1938f19b00daSKim, Milo { 1939f19b00daSKim, Milo struct regulator_enable_gpio *pin, *n; 1940f19b00daSKim, Milo 1941f19b00daSKim, Milo if (!rdev->ena_pin) 1942f19b00daSKim, Milo return; 1943f19b00daSKim, Milo 1944f19b00daSKim, Milo /* Free the GPIO only in case of no use */ 1945f19b00daSKim, Milo list_for_each_entry_safe(pin, n, ®ulator_ena_gpio_list, list) { 1946778b28b4SRussell King if (pin->gpiod == rdev->ena_pin->gpiod) { 1947f19b00daSKim, Milo if (pin->request_count <= 1) { 1948f19b00daSKim, Milo pin->request_count = 0; 1949778b28b4SRussell King gpiod_put(pin->gpiod); 1950f19b00daSKim, Milo list_del(&pin->list); 1951f19b00daSKim, Milo kfree(pin); 195260a2362fSSeung-Woo Kim rdev->ena_pin = NULL; 195360a2362fSSeung-Woo Kim return; 1954f19b00daSKim, Milo } else { 1955f19b00daSKim, Milo pin->request_count--; 1956f19b00daSKim, Milo } 1957f19b00daSKim, Milo } 1958f19b00daSKim, Milo } 1959f19b00daSKim, Milo } 1960f19b00daSKim, Milo 1961967cfb18SKim, Milo /** 196231d6eebfSRobert P. J. Day * regulator_ena_gpio_ctrl - balance enable_count of each GPIO and actual GPIO pin control 196331d6eebfSRobert P. J. Day * @rdev: regulator_dev structure 196431d6eebfSRobert P. J. Day * @enable: enable GPIO at initial use? 196531d6eebfSRobert P. J. Day * 1966967cfb18SKim, Milo * GPIO is enabled in case of initial use. (enable_count is 0) 1967967cfb18SKim, Milo * GPIO is disabled when it is not shared any more. (enable_count <= 1) 1968967cfb18SKim, Milo */ 1969967cfb18SKim, Milo static int regulator_ena_gpio_ctrl(struct regulator_dev *rdev, bool enable) 1970967cfb18SKim, Milo { 1971967cfb18SKim, Milo struct regulator_enable_gpio *pin = rdev->ena_pin; 1972967cfb18SKim, Milo 1973967cfb18SKim, Milo if (!pin) 1974967cfb18SKim, Milo return -EINVAL; 1975967cfb18SKim, Milo 1976967cfb18SKim, Milo if (enable) { 1977967cfb18SKim, Milo /* Enable GPIO at initial use */ 1978967cfb18SKim, Milo if (pin->enable_count == 0) 1979778b28b4SRussell King gpiod_set_value_cansleep(pin->gpiod, 1980967cfb18SKim, Milo !pin->ena_gpio_invert); 1981967cfb18SKim, Milo 1982967cfb18SKim, Milo pin->enable_count++; 1983967cfb18SKim, Milo } else { 1984967cfb18SKim, Milo if (pin->enable_count > 1) { 1985967cfb18SKim, Milo pin->enable_count--; 1986967cfb18SKim, Milo return 0; 1987967cfb18SKim, Milo } 1988967cfb18SKim, Milo 1989967cfb18SKim, Milo /* Disable GPIO if not used */ 1990967cfb18SKim, Milo if (pin->enable_count <= 1) { 1991778b28b4SRussell King gpiod_set_value_cansleep(pin->gpiod, 1992967cfb18SKim, Milo pin->ena_gpio_invert); 1993967cfb18SKim, Milo pin->enable_count = 0; 1994967cfb18SKim, Milo } 1995967cfb18SKim, Milo } 1996967cfb18SKim, Milo 1997967cfb18SKim, Milo return 0; 1998967cfb18SKim, Milo } 1999967cfb18SKim, Milo 200079fd1141SGuodong Xu /** 200179fd1141SGuodong Xu * _regulator_enable_delay - a delay helper function 200279fd1141SGuodong Xu * @delay: time to delay in microseconds 200379fd1141SGuodong Xu * 20045df529d4SThierry Reding * Delay for the requested amount of time as per the guidelines in: 20055df529d4SThierry Reding * 20065df529d4SThierry Reding * Documentation/timers/timers-howto.txt 20075df529d4SThierry Reding * 20085df529d4SThierry Reding * The assumption here is that regulators will never be enabled in 20095df529d4SThierry Reding * atomic context and therefore sleeping functions can be used. 20105df529d4SThierry Reding */ 201179fd1141SGuodong Xu static void _regulator_enable_delay(unsigned int delay) 201279fd1141SGuodong Xu { 20135df529d4SThierry Reding unsigned int ms = delay / 1000; 20145df529d4SThierry Reding unsigned int us = delay % 1000; 20155df529d4SThierry Reding 20165df529d4SThierry Reding if (ms > 0) { 20175df529d4SThierry Reding /* 20185df529d4SThierry Reding * For small enough values, handle super-millisecond 20195df529d4SThierry Reding * delays in the usleep_range() call below. 20205df529d4SThierry Reding */ 20215df529d4SThierry Reding if (ms < 20) 20225df529d4SThierry Reding us += ms * 1000; 20235df529d4SThierry Reding else 20245df529d4SThierry Reding msleep(ms); 20255df529d4SThierry Reding } 20265df529d4SThierry Reding 20275df529d4SThierry Reding /* 20285df529d4SThierry Reding * Give the scheduler some room to coalesce with any other 20295df529d4SThierry Reding * wakeup sources. For delays shorter than 10 us, don't even 20305df529d4SThierry Reding * bother setting up high-resolution timers and just busy- 20315df529d4SThierry Reding * loop. 20325df529d4SThierry Reding */ 20335df529d4SThierry Reding if (us >= 10) 20345df529d4SThierry Reding usleep_range(us, us + 100); 20355df529d4SThierry Reding else 20365df529d4SThierry Reding udelay(us); 20375c5659d0SMark Brown } 20385c5659d0SMark Brown 20395c5659d0SMark Brown static int _regulator_do_enable(struct regulator_dev *rdev) 20405c5659d0SMark Brown { 20415c5659d0SMark Brown int ret, delay; 20425c5659d0SMark Brown 20435c5659d0SMark Brown /* Query before enabling in case configuration dependent. */ 20445c5659d0SMark Brown ret = _regulator_get_enable_time(rdev); 20455c5659d0SMark Brown if (ret >= 0) { 20465c5659d0SMark Brown delay = ret; 20475c5659d0SMark Brown } else { 2048414c70cbSLiam Girdwood rdev_warn(rdev, "enable_time() failed: %d\n", ret); 2049414c70cbSLiam Girdwood delay = 0; 2050414c70cbSLiam Girdwood } 20515c5659d0SMark Brown 2052414c70cbSLiam Girdwood trace_regulator_enable(rdev_get_name(rdev)); 2053414c70cbSLiam Girdwood 2054871f5650SGuodong Xu if (rdev->desc->off_on_delay) { 2055871f5650SGuodong Xu /* if needed, keep a distance of off_on_delay from last time 2056871f5650SGuodong Xu * this regulator was disabled. 2057871f5650SGuodong Xu */ 2058871f5650SGuodong Xu unsigned long start_jiffy = jiffies; 2059871f5650SGuodong Xu unsigned long intended, max_delay, remaining; 2060871f5650SGuodong Xu 2061871f5650SGuodong Xu max_delay = usecs_to_jiffies(rdev->desc->off_on_delay); 2062871f5650SGuodong Xu intended = rdev->last_off_jiffy + max_delay; 2063871f5650SGuodong Xu 2064871f5650SGuodong Xu if (time_before(start_jiffy, intended)) { 2065871f5650SGuodong Xu /* calc remaining jiffies to deal with one-time 2066871f5650SGuodong Xu * timer wrapping. 2067871f5650SGuodong Xu * in case of multiple timer wrapping, either it can be 2068871f5650SGuodong Xu * detected by out-of-range remaining, or it cannot be 2069871f5650SGuodong Xu * detected and we gets a panelty of 2070871f5650SGuodong Xu * _regulator_enable_delay(). 2071871f5650SGuodong Xu */ 2072871f5650SGuodong Xu remaining = intended - start_jiffy; 2073871f5650SGuodong Xu if (remaining <= max_delay) 2074871f5650SGuodong Xu _regulator_enable_delay( 2075871f5650SGuodong Xu jiffies_to_usecs(remaining)); 2076871f5650SGuodong Xu } 2077871f5650SGuodong Xu } 2078871f5650SGuodong Xu 2079414c70cbSLiam Girdwood if (rdev->ena_pin) { 208029d62ec5SDoug Anderson if (!rdev->ena_gpio_state) { 20819a2372faSMark Brown ret = regulator_ena_gpio_ctrl(rdev, true); 2082414c70cbSLiam Girdwood if (ret < 0) 2083414c70cbSLiam Girdwood return ret; 20849a2372faSMark Brown rdev->ena_gpio_state = 1; 208529d62ec5SDoug Anderson } 20869a2372faSMark Brown } else if (rdev->desc->ops->enable) { 20879a2372faSMark Brown ret = rdev->desc->ops->enable(rdev); 20889a2372faSMark Brown if (ret < 0) 20899a2372faSMark Brown return ret; 20909a2372faSMark Brown } else { 20919a2372faSMark Brown return -EINVAL; 20925c5659d0SMark Brown } 20939a2372faSMark Brown 20949a2372faSMark Brown /* Allow the regulator to ramp; it would be useful to extend 209531aae2beSMark Brown * this for bulk operations so that the regulators can ramp 2096a7433cffSLinus Walleij * together. */ 20975da84fd9SJoe Perches trace_regulator_enable_delay(rdev_get_name(rdev)); 2098414c70cbSLiam Girdwood 209979fd1141SGuodong Xu _regulator_enable_delay(delay); 2100a7433cffSLinus Walleij 2101414c70cbSLiam Girdwood trace_regulator_enable_complete(rdev_get_name(rdev)); 2102414c70cbSLiam Girdwood 21039a2372faSMark Brown return 0; 21049a2372faSMark Brown } 21059a2372faSMark Brown 2106414c70cbSLiam Girdwood /* locks held by regulator_enable() */ 2107414c70cbSLiam Girdwood static int _regulator_enable(struct regulator_dev *rdev) 2108414c70cbSLiam Girdwood { 2109414c70cbSLiam Girdwood int ret; 2110414c70cbSLiam Girdwood 211170cfef26SKrzysztof Kozlowski lockdep_assert_held_once(&rdev->mutex); 211270cfef26SKrzysztof Kozlowski 2113414c70cbSLiam Girdwood /* check voltage and requested load before enabling */ 2114cf7bbcdfSMark Brown if (rdev->constraints && 2115cf7bbcdfSMark Brown (rdev->constraints->valid_ops_mask & REGULATOR_CHANGE_DRMS)) 2116cf7bbcdfSMark Brown drms_uA_update(rdev); 2117cf7bbcdfSMark Brown 2118414c70cbSLiam Girdwood if (rdev->use_count == 0) { 2119cf7bbcdfSMark Brown /* The regulator may on if it's not switchable or left on */ 2120414c70cbSLiam Girdwood ret = _regulator_is_enabled(rdev); 2121414c70cbSLiam Girdwood if (ret == -EINVAL || ret == 0) { 2122414c70cbSLiam Girdwood if (!_regulator_can_change_status(rdev)) 2123412aec61SDavid Brownell return -EPERM; 2124412aec61SDavid Brownell 2125414c70cbSLiam Girdwood ret = _regulator_do_enable(rdev); 2126412aec61SDavid Brownell if (ret < 0) 2127412aec61SDavid Brownell return ret; 2128412aec61SDavid Brownell 2129414c70cbSLiam Girdwood } else if (ret < 0) { 2130414c70cbSLiam Girdwood rdev_err(rdev, "is_enabled() failed: %d\n", ret); 2131414c70cbSLiam Girdwood return ret; 2132414c70cbSLiam Girdwood } 2133414c70cbSLiam Girdwood /* Fallthrough on positive return values - already enabled */ 2134414c70cbSLiam Girdwood } 2135414c70cbSLiam Girdwood 2136414c70cbSLiam Girdwood rdev->use_count++; 2137414c70cbSLiam Girdwood 2138cd94b505SDavid Brownell return 0; 2139cd94b505SDavid Brownell } 21401083c393SMark Brown 2141cd94b505SDavid Brownell /** 2142cd94b505SDavid Brownell * regulator_enable - enable regulator output 2143414c70cbSLiam Girdwood * @regulator: regulator source 214460ef66fcSMark Brown * 214560ef66fcSMark Brown * Request that the regulator be enabled with the regulator output at 2146414c70cbSLiam Girdwood * the predefined voltage or current value. Calls to regulator_enable() 2147414c70cbSLiam Girdwood * must be balanced with calls to regulator_disable(). 21489a2372faSMark Brown * 21499a2372faSMark Brown * NOTE: the output value can be set by other drivers, boot loader or may be 2150414c70cbSLiam Girdwood * hardwired in the regulator. 2151414c70cbSLiam Girdwood */ 2152414c70cbSLiam Girdwood int regulator_enable(struct regulator *regulator) 21531083c393SMark Brown { 2154414c70cbSLiam Girdwood struct regulator_dev *rdev = regulator->rdev; 2155414c70cbSLiam Girdwood int ret = 0; 215684b68263SMark Brown 21576492bc1bSMark Brown if (regulator->always_on) 21586492bc1bSMark Brown return 0; 21596492bc1bSMark Brown 21603801b86aSMark Brown if (rdev->supply) { 21613801b86aSMark Brown ret = regulator_enable(rdev->supply); 21623801b86aSMark Brown if (ret != 0) 21633801b86aSMark Brown return ret; 21643801b86aSMark Brown } 21653801b86aSMark Brown 2166414c70cbSLiam Girdwood mutex_lock(&rdev->mutex); 2167414c70cbSLiam Girdwood ret = _regulator_enable(rdev); 2168414c70cbSLiam Girdwood mutex_unlock(&rdev->mutex); 21693801b86aSMark Brown 2170d1685e4eSHeiko Stübner if (ret != 0 && rdev->supply) 21713801b86aSMark Brown regulator_disable(rdev->supply); 21723801b86aSMark Brown 2173414c70cbSLiam Girdwood return ret; 2174414c70cbSLiam Girdwood } 2175414c70cbSLiam Girdwood EXPORT_SYMBOL_GPL(regulator_enable); 2176414c70cbSLiam Girdwood 21775c5659d0SMark Brown static int _regulator_do_disable(struct regulator_dev *rdev) 21785c5659d0SMark Brown { 21795c5659d0SMark Brown int ret; 21805c5659d0SMark Brown 21815c5659d0SMark Brown trace_regulator_disable(rdev_get_name(rdev)); 21825c5659d0SMark Brown 2183967cfb18SKim, Milo if (rdev->ena_pin) { 218429d62ec5SDoug Anderson if (rdev->ena_gpio_state) { 2185967cfb18SKim, Milo ret = regulator_ena_gpio_ctrl(rdev, false); 2186967cfb18SKim, Milo if (ret < 0) 2187967cfb18SKim, Milo return ret; 21885c5659d0SMark Brown rdev->ena_gpio_state = 0; 218929d62ec5SDoug Anderson } 21905c5659d0SMark Brown 21915c5659d0SMark Brown } else if (rdev->desc->ops->disable) { 21925c5659d0SMark Brown ret = rdev->desc->ops->disable(rdev); 21935c5659d0SMark Brown if (ret != 0) 21945c5659d0SMark Brown return ret; 21955c5659d0SMark Brown } 21965c5659d0SMark Brown 2197871f5650SGuodong Xu /* cares about last_off_jiffy only if off_on_delay is required by 2198871f5650SGuodong Xu * device. 2199871f5650SGuodong Xu */ 2200871f5650SGuodong Xu if (rdev->desc->off_on_delay) 2201871f5650SGuodong Xu rdev->last_off_jiffy = jiffies; 2202871f5650SGuodong Xu 22035c5659d0SMark Brown trace_regulator_disable_complete(rdev_get_name(rdev)); 22045c5659d0SMark Brown 22055c5659d0SMark Brown return 0; 22065c5659d0SMark Brown } 22075c5659d0SMark Brown 2208414c70cbSLiam Girdwood /* locks held by regulator_disable() */ 22093801b86aSMark Brown static int _regulator_disable(struct regulator_dev *rdev) 2210414c70cbSLiam Girdwood { 2211414c70cbSLiam Girdwood int ret = 0; 2212414c70cbSLiam Girdwood 221370cfef26SKrzysztof Kozlowski lockdep_assert_held_once(&rdev->mutex); 221470cfef26SKrzysztof Kozlowski 2215414c70cbSLiam Girdwood if (WARN(rdev->use_count <= 0, 221643e7ee33SJoe Perches "unbalanced disables for %s\n", rdev_get_name(rdev))) 2217414c70cbSLiam Girdwood return -EIO; 2218414c70cbSLiam Girdwood 2219414c70cbSLiam Girdwood /* are we the last user and permitted to disable ? */ 2220414c70cbSLiam Girdwood if (rdev->use_count == 1 && 2221414c70cbSLiam Girdwood (rdev->constraints && !rdev->constraints->always_on)) { 2222414c70cbSLiam Girdwood 2223414c70cbSLiam Girdwood /* we are last user */ 22245c5659d0SMark Brown if (_regulator_can_change_status(rdev)) { 2225a1c8a551SRichard Fitzgerald ret = _notifier_call_chain(rdev, 2226a1c8a551SRichard Fitzgerald REGULATOR_EVENT_PRE_DISABLE, 2227a1c8a551SRichard Fitzgerald NULL); 2228a1c8a551SRichard Fitzgerald if (ret & NOTIFY_STOP_MASK) 2229a1c8a551SRichard Fitzgerald return -EINVAL; 2230a1c8a551SRichard Fitzgerald 22315c5659d0SMark Brown ret = _regulator_do_disable(rdev); 2232414c70cbSLiam Girdwood if (ret < 0) { 22335da84fd9SJoe Perches rdev_err(rdev, "failed to disable\n"); 2234a1c8a551SRichard Fitzgerald _notifier_call_chain(rdev, 2235a1c8a551SRichard Fitzgerald REGULATOR_EVENT_ABORT_DISABLE, 2236a1c8a551SRichard Fitzgerald NULL); 2237414c70cbSLiam Girdwood return ret; 2238414c70cbSLiam Girdwood } 223966fda75fSMarkus Pargmann _notifier_call_chain(rdev, REGULATOR_EVENT_DISABLE, 224066fda75fSMarkus Pargmann NULL); 2241414c70cbSLiam Girdwood } 2242414c70cbSLiam Girdwood 2243414c70cbSLiam Girdwood rdev->use_count = 0; 2244414c70cbSLiam Girdwood } else if (rdev->use_count > 1) { 2245414c70cbSLiam Girdwood 2246414c70cbSLiam Girdwood if (rdev->constraints && 2247414c70cbSLiam Girdwood (rdev->constraints->valid_ops_mask & 2248414c70cbSLiam Girdwood REGULATOR_CHANGE_DRMS)) 2249414c70cbSLiam Girdwood drms_uA_update(rdev); 2250414c70cbSLiam Girdwood 2251414c70cbSLiam Girdwood rdev->use_count--; 2252414c70cbSLiam Girdwood } 22533801b86aSMark Brown 2254414c70cbSLiam Girdwood return ret; 2255414c70cbSLiam Girdwood } 2256414c70cbSLiam Girdwood 2257414c70cbSLiam Girdwood /** 2258414c70cbSLiam Girdwood * regulator_disable - disable regulator output 2259414c70cbSLiam Girdwood * @regulator: regulator source 2260414c70cbSLiam Girdwood * 2261cf7bbcdfSMark Brown * Disable the regulator output voltage or current. Calls to 2262cf7bbcdfSMark Brown * regulator_enable() must be balanced with calls to 2263cf7bbcdfSMark Brown * regulator_disable(). 226469279fb9SMark Brown * 2265414c70cbSLiam Girdwood * NOTE: this will only disable the regulator output if no other consumer 2266cf7bbcdfSMark Brown * devices have it enabled, the regulator device supports disabling and 2267cf7bbcdfSMark Brown * machine constraints permit this operation. 2268414c70cbSLiam Girdwood */ 2269414c70cbSLiam Girdwood int regulator_disable(struct regulator *regulator) 2270414c70cbSLiam Girdwood { 2271412aec61SDavid Brownell struct regulator_dev *rdev = regulator->rdev; 2272412aec61SDavid Brownell int ret = 0; 2273414c70cbSLiam Girdwood 22746492bc1bSMark Brown if (regulator->always_on) 22756492bc1bSMark Brown return 0; 22766492bc1bSMark Brown 2277412aec61SDavid Brownell mutex_lock(&rdev->mutex); 22783801b86aSMark Brown ret = _regulator_disable(rdev); 2279412aec61SDavid Brownell mutex_unlock(&rdev->mutex); 22808cbf811dSJeffrey Carlyle 22813801b86aSMark Brown if (ret == 0 && rdev->supply) 22823801b86aSMark Brown regulator_disable(rdev->supply); 22838cbf811dSJeffrey Carlyle 2284414c70cbSLiam Girdwood return ret; 2285414c70cbSLiam Girdwood } 2286414c70cbSLiam Girdwood EXPORT_SYMBOL_GPL(regulator_disable); 2287414c70cbSLiam Girdwood 2288414c70cbSLiam Girdwood /* locks held by regulator_force_disable() */ 22893801b86aSMark Brown static int _regulator_force_disable(struct regulator_dev *rdev) 2290414c70cbSLiam Girdwood { 2291414c70cbSLiam Girdwood int ret = 0; 2292414c70cbSLiam Girdwood 229370cfef26SKrzysztof Kozlowski lockdep_assert_held_once(&rdev->mutex); 229470cfef26SKrzysztof Kozlowski 2295a1c8a551SRichard Fitzgerald ret = _notifier_call_chain(rdev, REGULATOR_EVENT_FORCE_DISABLE | 2296a1c8a551SRichard Fitzgerald REGULATOR_EVENT_PRE_DISABLE, NULL); 2297a1c8a551SRichard Fitzgerald if (ret & NOTIFY_STOP_MASK) 2298a1c8a551SRichard Fitzgerald return -EINVAL; 2299a1c8a551SRichard Fitzgerald 230066fda75fSMarkus Pargmann ret = _regulator_do_disable(rdev); 2301414c70cbSLiam Girdwood if (ret < 0) { 23025da84fd9SJoe Perches rdev_err(rdev, "failed to force disable\n"); 2303a1c8a551SRichard Fitzgerald _notifier_call_chain(rdev, REGULATOR_EVENT_FORCE_DISABLE | 2304a1c8a551SRichard Fitzgerald REGULATOR_EVENT_ABORT_DISABLE, NULL); 2305414c70cbSLiam Girdwood return ret; 2306414c70cbSLiam Girdwood } 230766fda75fSMarkus Pargmann 230884b68263SMark Brown _notifier_call_chain(rdev, REGULATOR_EVENT_FORCE_DISABLE | 230984b68263SMark Brown REGULATOR_EVENT_DISABLE, NULL); 2310414c70cbSLiam Girdwood 231166fda75fSMarkus Pargmann return 0; 2312414c70cbSLiam Girdwood } 2313414c70cbSLiam Girdwood 2314414c70cbSLiam Girdwood /** 2315414c70cbSLiam Girdwood * regulator_force_disable - force disable regulator output 2316414c70cbSLiam Girdwood * @regulator: regulator source 2317414c70cbSLiam Girdwood * 2318414c70cbSLiam Girdwood * Forcibly disable the regulator output voltage or current. 2319414c70cbSLiam Girdwood * NOTE: this *will* disable the regulator output even if other consumer 2320414c70cbSLiam Girdwood * devices have it enabled. This should be used for situations when device 2321414c70cbSLiam Girdwood * damage will likely occur if the regulator is not disabled (e.g. over temp). 2322414c70cbSLiam Girdwood */ 2323414c70cbSLiam Girdwood int regulator_force_disable(struct regulator *regulator) 2324414c70cbSLiam Girdwood { 232582d15839SMark Brown struct regulator_dev *rdev = regulator->rdev; 2326414c70cbSLiam Girdwood int ret; 2327414c70cbSLiam Girdwood 232882d15839SMark Brown mutex_lock(&rdev->mutex); 2329414c70cbSLiam Girdwood regulator->uA_load = 0; 23303801b86aSMark Brown ret = _regulator_force_disable(regulator->rdev); 233182d15839SMark Brown mutex_unlock(&rdev->mutex); 23328cbf811dSJeffrey Carlyle 23333801b86aSMark Brown if (rdev->supply) 23343801b86aSMark Brown while (rdev->open_count--) 23353801b86aSMark Brown regulator_disable(rdev->supply); 23368cbf811dSJeffrey Carlyle 2337414c70cbSLiam Girdwood return ret; 2338414c70cbSLiam Girdwood } 2339414c70cbSLiam Girdwood EXPORT_SYMBOL_GPL(regulator_force_disable); 2340414c70cbSLiam Girdwood 2341da07ecd9SMark Brown static void regulator_disable_work(struct work_struct *work) 2342da07ecd9SMark Brown { 2343da07ecd9SMark Brown struct regulator_dev *rdev = container_of(work, struct regulator_dev, 2344da07ecd9SMark Brown disable_work.work); 2345da07ecd9SMark Brown int count, i, ret; 2346da07ecd9SMark Brown 2347da07ecd9SMark Brown mutex_lock(&rdev->mutex); 2348da07ecd9SMark Brown 2349da07ecd9SMark Brown BUG_ON(!rdev->deferred_disables); 2350da07ecd9SMark Brown 2351da07ecd9SMark Brown count = rdev->deferred_disables; 2352da07ecd9SMark Brown rdev->deferred_disables = 0; 2353da07ecd9SMark Brown 2354da07ecd9SMark Brown for (i = 0; i < count; i++) { 2355da07ecd9SMark Brown ret = _regulator_disable(rdev); 2356da07ecd9SMark Brown if (ret != 0) 2357da07ecd9SMark Brown rdev_err(rdev, "Deferred disable failed: %d\n", ret); 2358da07ecd9SMark Brown } 2359da07ecd9SMark Brown 2360da07ecd9SMark Brown mutex_unlock(&rdev->mutex); 2361da07ecd9SMark Brown 2362da07ecd9SMark Brown if (rdev->supply) { 2363da07ecd9SMark Brown for (i = 0; i < count; i++) { 2364da07ecd9SMark Brown ret = regulator_disable(rdev->supply); 2365da07ecd9SMark Brown if (ret != 0) { 2366da07ecd9SMark Brown rdev_err(rdev, 2367da07ecd9SMark Brown "Supply disable failed: %d\n", ret); 2368da07ecd9SMark Brown } 2369da07ecd9SMark Brown } 2370da07ecd9SMark Brown } 2371da07ecd9SMark Brown } 2372da07ecd9SMark Brown 2373da07ecd9SMark Brown /** 2374da07ecd9SMark Brown * regulator_disable_deferred - disable regulator output with delay 2375da07ecd9SMark Brown * @regulator: regulator source 2376da07ecd9SMark Brown * @ms: miliseconds until the regulator is disabled 2377da07ecd9SMark Brown * 2378da07ecd9SMark Brown * Execute regulator_disable() on the regulator after a delay. This 2379da07ecd9SMark Brown * is intended for use with devices that require some time to quiesce. 2380da07ecd9SMark Brown * 2381da07ecd9SMark Brown * NOTE: this will only disable the regulator output if no other consumer 2382da07ecd9SMark Brown * devices have it enabled, the regulator device supports disabling and 2383da07ecd9SMark Brown * machine constraints permit this operation. 2384da07ecd9SMark Brown */ 2385da07ecd9SMark Brown int regulator_disable_deferred(struct regulator *regulator, int ms) 2386da07ecd9SMark Brown { 2387da07ecd9SMark Brown struct regulator_dev *rdev = regulator->rdev; 2388da07ecd9SMark Brown 23896492bc1bSMark Brown if (regulator->always_on) 23906492bc1bSMark Brown return 0; 23916492bc1bSMark Brown 23922b5a24a0SMark Brown if (!ms) 23932b5a24a0SMark Brown return regulator_disable(regulator); 23942b5a24a0SMark Brown 2395da07ecd9SMark Brown mutex_lock(&rdev->mutex); 2396da07ecd9SMark Brown rdev->deferred_disables++; 2397da07ecd9SMark Brown mutex_unlock(&rdev->mutex); 2398da07ecd9SMark Brown 239970dc6dafSDan Carpenter queue_delayed_work(system_power_efficient_wq, &rdev->disable_work, 2400da07ecd9SMark Brown msecs_to_jiffies(ms)); 2401aa59802dSMark Brown return 0; 2402da07ecd9SMark Brown } 2403da07ecd9SMark Brown EXPORT_SYMBOL_GPL(regulator_disable_deferred); 2404da07ecd9SMark Brown 2405414c70cbSLiam Girdwood static int _regulator_is_enabled(struct regulator_dev *rdev) 2406414c70cbSLiam Girdwood { 240765f73508SMark Brown /* A GPIO control always takes precedence */ 24087b74d149SKim, Milo if (rdev->ena_pin) 240965f73508SMark Brown return rdev->ena_gpio_state; 241065f73508SMark Brown 24119a7f6a4cSMark Brown /* If we don't know then assume that the regulator is always on */ 24129332546fSMark Brown if (!rdev->desc->ops->is_enabled) 24139a7f6a4cSMark Brown return 1; 2414414c70cbSLiam Girdwood 24159332546fSMark Brown return rdev->desc->ops->is_enabled(rdev); 2416414c70cbSLiam Girdwood } 2417414c70cbSLiam Girdwood 24183a40cfc3SSascha Hauer static int _regulator_list_voltage(struct regulator *regulator, 24193a40cfc3SSascha Hauer unsigned selector, int lock) 24203a40cfc3SSascha Hauer { 24213a40cfc3SSascha Hauer struct regulator_dev *rdev = regulator->rdev; 24223a40cfc3SSascha Hauer const struct regulator_ops *ops = rdev->desc->ops; 24233a40cfc3SSascha Hauer int ret; 24243a40cfc3SSascha Hauer 24253a40cfc3SSascha Hauer if (rdev->desc->fixed_uV && rdev->desc->n_voltages == 1 && !selector) 24263a40cfc3SSascha Hauer return rdev->desc->fixed_uV; 24273a40cfc3SSascha Hauer 24283a40cfc3SSascha Hauer if (ops->list_voltage) { 24293a40cfc3SSascha Hauer if (selector >= rdev->desc->n_voltages) 24303a40cfc3SSascha Hauer return -EINVAL; 24313a40cfc3SSascha Hauer if (lock) 24323a40cfc3SSascha Hauer mutex_lock(&rdev->mutex); 24333a40cfc3SSascha Hauer ret = ops->list_voltage(rdev, selector); 24343a40cfc3SSascha Hauer if (lock) 24353a40cfc3SSascha Hauer mutex_unlock(&rdev->mutex); 24363a40cfc3SSascha Hauer } else if (rdev->supply) { 24373a40cfc3SSascha Hauer ret = _regulator_list_voltage(rdev->supply, selector, lock); 24383a40cfc3SSascha Hauer } else { 24393a40cfc3SSascha Hauer return -EINVAL; 24403a40cfc3SSascha Hauer } 24413a40cfc3SSascha Hauer 24423a40cfc3SSascha Hauer if (ret > 0) { 24433a40cfc3SSascha Hauer if (ret < rdev->constraints->min_uV) 24443a40cfc3SSascha Hauer ret = 0; 24453a40cfc3SSascha Hauer else if (ret > rdev->constraints->max_uV) 24463a40cfc3SSascha Hauer ret = 0; 24473a40cfc3SSascha Hauer } 24483a40cfc3SSascha Hauer 24493a40cfc3SSascha Hauer return ret; 24503a40cfc3SSascha Hauer } 24513a40cfc3SSascha Hauer 2452414c70cbSLiam Girdwood /** 2453414c70cbSLiam Girdwood * regulator_is_enabled - is the regulator output enabled 2454414c70cbSLiam Girdwood * @regulator: regulator source 2455414c70cbSLiam Girdwood * 2456412aec61SDavid Brownell * Returns positive if the regulator driver backing the source/client 2457412aec61SDavid Brownell * has requested that the device be enabled, zero if it hasn't, else a 2458412aec61SDavid Brownell * negative errno code. 2459412aec61SDavid Brownell * 2460412aec61SDavid Brownell * Note that the device backing this regulator handle can have multiple 2461412aec61SDavid Brownell * users, so it might be enabled even if regulator_enable() was never 2462412aec61SDavid Brownell * called for this particular source. 2463414c70cbSLiam Girdwood */ 2464414c70cbSLiam Girdwood int regulator_is_enabled(struct regulator *regulator) 2465414c70cbSLiam Girdwood { 24669332546fSMark Brown int ret; 24679332546fSMark Brown 24686492bc1bSMark Brown if (regulator->always_on) 24696492bc1bSMark Brown return 1; 24706492bc1bSMark Brown 24719332546fSMark Brown mutex_lock(®ulator->rdev->mutex); 24729332546fSMark Brown ret = _regulator_is_enabled(regulator->rdev); 24739332546fSMark Brown mutex_unlock(®ulator->rdev->mutex); 24749332546fSMark Brown 24759332546fSMark Brown return ret; 2476414c70cbSLiam Girdwood } 2477414c70cbSLiam Girdwood EXPORT_SYMBOL_GPL(regulator_is_enabled); 2478414c70cbSLiam Girdwood 2479414c70cbSLiam Girdwood /** 2480d1e7de30SMarek Szyprowski * regulator_can_change_voltage - check if regulator can change voltage 2481d1e7de30SMarek Szyprowski * @regulator: regulator source 2482d1e7de30SMarek Szyprowski * 2483d1e7de30SMarek Szyprowski * Returns positive if the regulator driver backing the source/client 2484e227867fSMasanari Iida * can change its voltage, false otherwise. Useful for detecting fixed 2485d1e7de30SMarek Szyprowski * or dummy regulators and disabling voltage change logic in the client 2486d1e7de30SMarek Szyprowski * driver. 2487d1e7de30SMarek Szyprowski */ 2488d1e7de30SMarek Szyprowski int regulator_can_change_voltage(struct regulator *regulator) 2489d1e7de30SMarek Szyprowski { 2490d1e7de30SMarek Szyprowski struct regulator_dev *rdev = regulator->rdev; 2491d1e7de30SMarek Szyprowski 2492d1e7de30SMarek Szyprowski if (rdev->constraints && 249319280e40SAxel Lin (rdev->constraints->valid_ops_mask & REGULATOR_CHANGE_VOLTAGE)) { 249419280e40SAxel Lin if (rdev->desc->n_voltages - rdev->desc->linear_min_sel > 1) 2495d1e7de30SMarek Szyprowski return 1; 2496d1e7de30SMarek Szyprowski 249719280e40SAxel Lin if (rdev->desc->continuous_voltage_range && 249819280e40SAxel Lin rdev->constraints->min_uV && rdev->constraints->max_uV && 249919280e40SAxel Lin rdev->constraints->min_uV != rdev->constraints->max_uV) 250019280e40SAxel Lin return 1; 250119280e40SAxel Lin } 250219280e40SAxel Lin 2503d1e7de30SMarek Szyprowski return 0; 2504d1e7de30SMarek Szyprowski } 2505d1e7de30SMarek Szyprowski EXPORT_SYMBOL_GPL(regulator_can_change_voltage); 2506d1e7de30SMarek Szyprowski 2507d1e7de30SMarek Szyprowski /** 25084367cfdcSDavid Brownell * regulator_count_voltages - count regulator_list_voltage() selectors 25094367cfdcSDavid Brownell * @regulator: regulator source 25104367cfdcSDavid Brownell * 25114367cfdcSDavid Brownell * Returns number of selectors, or negative errno. Selectors are 25124367cfdcSDavid Brownell * numbered starting at zero, and typically correspond to bitfields 25134367cfdcSDavid Brownell * in hardware registers. 25144367cfdcSDavid Brownell */ 25154367cfdcSDavid Brownell int regulator_count_voltages(struct regulator *regulator) 25164367cfdcSDavid Brownell { 25174367cfdcSDavid Brownell struct regulator_dev *rdev = regulator->rdev; 25184367cfdcSDavid Brownell 251926988efeSJavier Martinez Canillas if (rdev->desc->n_voltages) 252026988efeSJavier Martinez Canillas return rdev->desc->n_voltages; 252126988efeSJavier Martinez Canillas 252226988efeSJavier Martinez Canillas if (!rdev->supply) 252326988efeSJavier Martinez Canillas return -EINVAL; 252426988efeSJavier Martinez Canillas 252526988efeSJavier Martinez Canillas return regulator_count_voltages(rdev->supply); 25264367cfdcSDavid Brownell } 25274367cfdcSDavid Brownell EXPORT_SYMBOL_GPL(regulator_count_voltages); 25284367cfdcSDavid Brownell 25294367cfdcSDavid Brownell /** 25304367cfdcSDavid Brownell * regulator_list_voltage - enumerate supported voltages 25314367cfdcSDavid Brownell * @regulator: regulator source 25324367cfdcSDavid Brownell * @selector: identify voltage to list 25334367cfdcSDavid Brownell * Context: can sleep 25344367cfdcSDavid Brownell * 25354367cfdcSDavid Brownell * Returns a voltage that can be passed to @regulator_set_voltage(), 253688393161SThomas Weber * zero if this selector code can't be used on this system, or a 25374367cfdcSDavid Brownell * negative errno. 25384367cfdcSDavid Brownell */ 25394367cfdcSDavid Brownell int regulator_list_voltage(struct regulator *regulator, unsigned selector) 25404367cfdcSDavid Brownell { 25413a40cfc3SSascha Hauer return _regulator_list_voltage(regulator, selector, 1); 25424367cfdcSDavid Brownell } 25434367cfdcSDavid Brownell EXPORT_SYMBOL_GPL(regulator_list_voltage); 25444367cfdcSDavid Brownell 25454367cfdcSDavid Brownell /** 254604eca28cSTuomas Tynkkynen * regulator_get_regmap - get the regulator's register map 254704eca28cSTuomas Tynkkynen * @regulator: regulator source 254804eca28cSTuomas Tynkkynen * 254904eca28cSTuomas Tynkkynen * Returns the register map for the given regulator, or an ERR_PTR value 255004eca28cSTuomas Tynkkynen * if the regulator doesn't use regmap. 255104eca28cSTuomas Tynkkynen */ 255204eca28cSTuomas Tynkkynen struct regmap *regulator_get_regmap(struct regulator *regulator) 255304eca28cSTuomas Tynkkynen { 255404eca28cSTuomas Tynkkynen struct regmap *map = regulator->rdev->regmap; 255504eca28cSTuomas Tynkkynen 255604eca28cSTuomas Tynkkynen return map ? map : ERR_PTR(-EOPNOTSUPP); 255704eca28cSTuomas Tynkkynen } 255804eca28cSTuomas Tynkkynen 255904eca28cSTuomas Tynkkynen /** 256004eca28cSTuomas Tynkkynen * regulator_get_hardware_vsel_register - get the HW voltage selector register 256104eca28cSTuomas Tynkkynen * @regulator: regulator source 256204eca28cSTuomas Tynkkynen * @vsel_reg: voltage selector register, output parameter 256304eca28cSTuomas Tynkkynen * @vsel_mask: mask for voltage selector bitfield, output parameter 256404eca28cSTuomas Tynkkynen * 256504eca28cSTuomas Tynkkynen * Returns the hardware register offset and bitmask used for setting the 256604eca28cSTuomas Tynkkynen * regulator voltage. This might be useful when configuring voltage-scaling 256704eca28cSTuomas Tynkkynen * hardware or firmware that can make I2C requests behind the kernel's back, 256804eca28cSTuomas Tynkkynen * for example. 256904eca28cSTuomas Tynkkynen * 257004eca28cSTuomas Tynkkynen * On success, the output parameters @vsel_reg and @vsel_mask are filled in 257104eca28cSTuomas Tynkkynen * and 0 is returned, otherwise a negative errno is returned. 257204eca28cSTuomas Tynkkynen */ 257304eca28cSTuomas Tynkkynen int regulator_get_hardware_vsel_register(struct regulator *regulator, 257404eca28cSTuomas Tynkkynen unsigned *vsel_reg, 257504eca28cSTuomas Tynkkynen unsigned *vsel_mask) 257604eca28cSTuomas Tynkkynen { 257704eca28cSTuomas Tynkkynen struct regulator_dev *rdev = regulator->rdev; 257839f5460dSGuodong Xu const struct regulator_ops *ops = rdev->desc->ops; 257904eca28cSTuomas Tynkkynen 258004eca28cSTuomas Tynkkynen if (ops->set_voltage_sel != regulator_set_voltage_sel_regmap) 258104eca28cSTuomas Tynkkynen return -EOPNOTSUPP; 258204eca28cSTuomas Tynkkynen 258304eca28cSTuomas Tynkkynen *vsel_reg = rdev->desc->vsel_reg; 258404eca28cSTuomas Tynkkynen *vsel_mask = rdev->desc->vsel_mask; 258504eca28cSTuomas Tynkkynen 258604eca28cSTuomas Tynkkynen return 0; 258704eca28cSTuomas Tynkkynen } 258804eca28cSTuomas Tynkkynen EXPORT_SYMBOL_GPL(regulator_get_hardware_vsel_register); 258904eca28cSTuomas Tynkkynen 259004eca28cSTuomas Tynkkynen /** 259104eca28cSTuomas Tynkkynen * regulator_list_hardware_vsel - get the HW-specific register value for a selector 259204eca28cSTuomas Tynkkynen * @regulator: regulator source 259304eca28cSTuomas Tynkkynen * @selector: identify voltage to list 259404eca28cSTuomas Tynkkynen * 259504eca28cSTuomas Tynkkynen * Converts the selector to a hardware-specific voltage selector that can be 259604eca28cSTuomas Tynkkynen * directly written to the regulator registers. The address of the voltage 259704eca28cSTuomas Tynkkynen * register can be determined by calling @regulator_get_hardware_vsel_register. 259804eca28cSTuomas Tynkkynen * 259904eca28cSTuomas Tynkkynen * On error a negative errno is returned. 260004eca28cSTuomas Tynkkynen */ 260104eca28cSTuomas Tynkkynen int regulator_list_hardware_vsel(struct regulator *regulator, 260204eca28cSTuomas Tynkkynen unsigned selector) 260304eca28cSTuomas Tynkkynen { 260404eca28cSTuomas Tynkkynen struct regulator_dev *rdev = regulator->rdev; 260539f5460dSGuodong Xu const struct regulator_ops *ops = rdev->desc->ops; 260604eca28cSTuomas Tynkkynen 260704eca28cSTuomas Tynkkynen if (selector >= rdev->desc->n_voltages) 260804eca28cSTuomas Tynkkynen return -EINVAL; 260904eca28cSTuomas Tynkkynen if (ops->set_voltage_sel != regulator_set_voltage_sel_regmap) 261004eca28cSTuomas Tynkkynen return -EOPNOTSUPP; 261104eca28cSTuomas Tynkkynen 261204eca28cSTuomas Tynkkynen return selector; 261304eca28cSTuomas Tynkkynen } 261404eca28cSTuomas Tynkkynen EXPORT_SYMBOL_GPL(regulator_list_hardware_vsel); 261504eca28cSTuomas Tynkkynen 261604eca28cSTuomas Tynkkynen /** 26172a668a8bSPaul Walmsley * regulator_get_linear_step - return the voltage step size between VSEL values 26182a668a8bSPaul Walmsley * @regulator: regulator source 26192a668a8bSPaul Walmsley * 26202a668a8bSPaul Walmsley * Returns the voltage step size between VSEL values for linear 26212a668a8bSPaul Walmsley * regulators, or return 0 if the regulator isn't a linear regulator. 26222a668a8bSPaul Walmsley */ 26232a668a8bSPaul Walmsley unsigned int regulator_get_linear_step(struct regulator *regulator) 26242a668a8bSPaul Walmsley { 26252a668a8bSPaul Walmsley struct regulator_dev *rdev = regulator->rdev; 26262a668a8bSPaul Walmsley 26272a668a8bSPaul Walmsley return rdev->desc->uV_step; 26282a668a8bSPaul Walmsley } 26292a668a8bSPaul Walmsley EXPORT_SYMBOL_GPL(regulator_get_linear_step); 26302a668a8bSPaul Walmsley 26312a668a8bSPaul Walmsley /** 2632a7a1ad90SMark Brown * regulator_is_supported_voltage - check if a voltage range can be supported 2633a7a1ad90SMark Brown * 2634a7a1ad90SMark Brown * @regulator: Regulator to check. 2635a7a1ad90SMark Brown * @min_uV: Minimum required voltage in uV. 2636a7a1ad90SMark Brown * @max_uV: Maximum required voltage in uV. 2637a7a1ad90SMark Brown * 2638a7a1ad90SMark Brown * Returns a boolean or a negative error code. 2639a7a1ad90SMark Brown */ 2640a7a1ad90SMark Brown int regulator_is_supported_voltage(struct regulator *regulator, 2641a7a1ad90SMark Brown int min_uV, int max_uV) 2642a7a1ad90SMark Brown { 2643c5f3939bSMark Brown struct regulator_dev *rdev = regulator->rdev; 2644a7a1ad90SMark Brown int i, voltages, ret; 2645a7a1ad90SMark Brown 2646c5f3939bSMark Brown /* If we can't change voltage check the current voltage */ 2647c5f3939bSMark Brown if (!(rdev->constraints->valid_ops_mask & REGULATOR_CHANGE_VOLTAGE)) { 2648c5f3939bSMark Brown ret = regulator_get_voltage(regulator); 2649c5f3939bSMark Brown if (ret >= 0) 26500d25d09dSJingoo Han return min_uV <= ret && ret <= max_uV; 2651c5f3939bSMark Brown else 2652c5f3939bSMark Brown return ret; 2653c5f3939bSMark Brown } 2654c5f3939bSMark Brown 2655bd7a2b60SPawel Moll /* Any voltage within constrains range is fine? */ 2656bd7a2b60SPawel Moll if (rdev->desc->continuous_voltage_range) 2657bd7a2b60SPawel Moll return min_uV >= rdev->constraints->min_uV && 2658bd7a2b60SPawel Moll max_uV <= rdev->constraints->max_uV; 2659bd7a2b60SPawel Moll 2660a7a1ad90SMark Brown ret = regulator_count_voltages(regulator); 2661a7a1ad90SMark Brown if (ret < 0) 2662a7a1ad90SMark Brown return ret; 2663a7a1ad90SMark Brown voltages = ret; 2664a7a1ad90SMark Brown 2665a7a1ad90SMark Brown for (i = 0; i < voltages; i++) { 2666a7a1ad90SMark Brown ret = regulator_list_voltage(regulator, i); 2667a7a1ad90SMark Brown 2668a7a1ad90SMark Brown if (ret >= min_uV && ret <= max_uV) 2669a7a1ad90SMark Brown return 1; 2670a7a1ad90SMark Brown } 2671a7a1ad90SMark Brown 2672a7a1ad90SMark Brown return 0; 2673a7a1ad90SMark Brown } 2674a398eaa2SMark Brown EXPORT_SYMBOL_GPL(regulator_is_supported_voltage); 2675a7a1ad90SMark Brown 2676a204f41eSSascha Hauer static int regulator_map_voltage(struct regulator_dev *rdev, int min_uV, 2677a204f41eSSascha Hauer int max_uV) 2678a204f41eSSascha Hauer { 2679a204f41eSSascha Hauer const struct regulator_desc *desc = rdev->desc; 2680a204f41eSSascha Hauer 2681a204f41eSSascha Hauer if (desc->ops->map_voltage) 2682a204f41eSSascha Hauer return desc->ops->map_voltage(rdev, min_uV, max_uV); 2683a204f41eSSascha Hauer 2684a204f41eSSascha Hauer if (desc->ops->list_voltage == regulator_list_voltage_linear) 2685a204f41eSSascha Hauer return regulator_map_voltage_linear(rdev, min_uV, max_uV); 2686a204f41eSSascha Hauer 2687a204f41eSSascha Hauer if (desc->ops->list_voltage == regulator_list_voltage_linear_range) 2688a204f41eSSascha Hauer return regulator_map_voltage_linear_range(rdev, min_uV, max_uV); 2689a204f41eSSascha Hauer 2690a204f41eSSascha Hauer return regulator_map_voltage_iterate(rdev, min_uV, max_uV); 2691a204f41eSSascha Hauer } 2692a204f41eSSascha Hauer 26937179569aSHeiko Stübner static int _regulator_call_set_voltage(struct regulator_dev *rdev, 26947179569aSHeiko Stübner int min_uV, int max_uV, 26957179569aSHeiko Stübner unsigned *selector) 26967179569aSHeiko Stübner { 26977179569aSHeiko Stübner struct pre_voltage_change_data data; 26987179569aSHeiko Stübner int ret; 26997179569aSHeiko Stübner 27007179569aSHeiko Stübner data.old_uV = _regulator_get_voltage(rdev); 27017179569aSHeiko Stübner data.min_uV = min_uV; 27027179569aSHeiko Stübner data.max_uV = max_uV; 27037179569aSHeiko Stübner ret = _notifier_call_chain(rdev, REGULATOR_EVENT_PRE_VOLTAGE_CHANGE, 27047179569aSHeiko Stübner &data); 27057179569aSHeiko Stübner if (ret & NOTIFY_STOP_MASK) 27067179569aSHeiko Stübner return -EINVAL; 27077179569aSHeiko Stübner 27087179569aSHeiko Stübner ret = rdev->desc->ops->set_voltage(rdev, min_uV, max_uV, selector); 27097179569aSHeiko Stübner if (ret >= 0) 27107179569aSHeiko Stübner return ret; 27117179569aSHeiko Stübner 27127179569aSHeiko Stübner _notifier_call_chain(rdev, REGULATOR_EVENT_ABORT_VOLTAGE_CHANGE, 27137179569aSHeiko Stübner (void *)data.old_uV); 27147179569aSHeiko Stübner 27157179569aSHeiko Stübner return ret; 27167179569aSHeiko Stübner } 27177179569aSHeiko Stübner 27187179569aSHeiko Stübner static int _regulator_call_set_voltage_sel(struct regulator_dev *rdev, 27197179569aSHeiko Stübner int uV, unsigned selector) 27207179569aSHeiko Stübner { 27217179569aSHeiko Stübner struct pre_voltage_change_data data; 27227179569aSHeiko Stübner int ret; 27237179569aSHeiko Stübner 27247179569aSHeiko Stübner data.old_uV = _regulator_get_voltage(rdev); 27257179569aSHeiko Stübner data.min_uV = uV; 27267179569aSHeiko Stübner data.max_uV = uV; 27277179569aSHeiko Stübner ret = _notifier_call_chain(rdev, REGULATOR_EVENT_PRE_VOLTAGE_CHANGE, 27287179569aSHeiko Stübner &data); 27297179569aSHeiko Stübner if (ret & NOTIFY_STOP_MASK) 27307179569aSHeiko Stübner return -EINVAL; 27317179569aSHeiko Stübner 27327179569aSHeiko Stübner ret = rdev->desc->ops->set_voltage_sel(rdev, selector); 27337179569aSHeiko Stübner if (ret >= 0) 27347179569aSHeiko Stübner return ret; 27357179569aSHeiko Stübner 27367179569aSHeiko Stübner _notifier_call_chain(rdev, REGULATOR_EVENT_ABORT_VOLTAGE_CHANGE, 27377179569aSHeiko Stübner (void *)data.old_uV); 27387179569aSHeiko Stübner 27397179569aSHeiko Stübner return ret; 27407179569aSHeiko Stübner } 27417179569aSHeiko Stübner 274275790251SMark Brown static int _regulator_do_set_voltage(struct regulator_dev *rdev, 274375790251SMark Brown int min_uV, int max_uV) 274475790251SMark Brown { 274575790251SMark Brown int ret; 274677af1b26SLinus Walleij int delay = 0; 2747e113d792SMark Brown int best_val = 0; 274875790251SMark Brown unsigned int selector; 2749eba41a5eSAxel Lin int old_selector = -1; 275075790251SMark Brown 275175790251SMark Brown trace_regulator_set_voltage(rdev_get_name(rdev), min_uV, max_uV); 275275790251SMark Brown 2753bf5892a8SMark Brown min_uV += rdev->constraints->uV_offset; 2754bf5892a8SMark Brown max_uV += rdev->constraints->uV_offset; 2755bf5892a8SMark Brown 275677af1b26SLinus Walleij /* 275777af1b26SLinus Walleij * If we can't obtain the old selector there is not enough 275877af1b26SLinus Walleij * info to call set_voltage_time_sel(). 275977af1b26SLinus Walleij */ 27608b7485efSAxel Lin if (_regulator_is_enabled(rdev) && 27618b7485efSAxel Lin rdev->desc->ops->set_voltage_time_sel && 276277af1b26SLinus Walleij rdev->desc->ops->get_voltage_sel) { 2763eba41a5eSAxel Lin old_selector = rdev->desc->ops->get_voltage_sel(rdev); 2764eba41a5eSAxel Lin if (old_selector < 0) 2765eba41a5eSAxel Lin return old_selector; 2766eba41a5eSAxel Lin } 276777af1b26SLinus Walleij 276875790251SMark Brown if (rdev->desc->ops->set_voltage) { 27697179569aSHeiko Stübner ret = _regulator_call_set_voltage(rdev, min_uV, max_uV, 277075790251SMark Brown &selector); 2771e113d792SMark Brown 2772e113d792SMark Brown if (ret >= 0) { 2773e113d792SMark Brown if (rdev->desc->ops->list_voltage) 2774e113d792SMark Brown best_val = rdev->desc->ops->list_voltage(rdev, 2775e113d792SMark Brown selector); 2776e113d792SMark Brown else 2777e113d792SMark Brown best_val = _regulator_get_voltage(rdev); 2778e113d792SMark Brown } 2779e113d792SMark Brown 2780e8eef82bSMark Brown } else if (rdev->desc->ops->set_voltage_sel) { 2781a204f41eSSascha Hauer ret = regulator_map_voltage(rdev, min_uV, max_uV); 2782e843fc46SMark Brown if (ret >= 0) { 2783e113d792SMark Brown best_val = rdev->desc->ops->list_voltage(rdev, ret); 2784e113d792SMark Brown if (min_uV <= best_val && max_uV >= best_val) { 2785e843fc46SMark Brown selector = ret; 2786c66a566aSAxel Lin if (old_selector == selector) 2787c66a566aSAxel Lin ret = 0; 2788c66a566aSAxel Lin else 27897179569aSHeiko Stübner ret = _regulator_call_set_voltage_sel( 27907179569aSHeiko Stübner rdev, best_val, selector); 2791e113d792SMark Brown } else { 2792e113d792SMark Brown ret = -EINVAL; 2793e113d792SMark Brown } 2794e843fc46SMark Brown } 2795e8eef82bSMark Brown } else { 2796e8eef82bSMark Brown ret = -EINVAL; 2797e8eef82bSMark Brown } 2798e8eef82bSMark Brown 2799eba41a5eSAxel Lin /* Call set_voltage_time_sel if successfully obtained old_selector */ 28005b175952SYadwinder Singh Brar if (ret == 0 && !rdev->constraints->ramp_disable && old_selector >= 0 28015b175952SYadwinder Singh Brar && old_selector != selector) { 2802eba41a5eSAxel Lin 2803eba41a5eSAxel Lin delay = rdev->desc->ops->set_voltage_time_sel(rdev, 2804eba41a5eSAxel Lin old_selector, selector); 2805eba41a5eSAxel Lin if (delay < 0) { 2806eba41a5eSAxel Lin rdev_warn(rdev, "set_voltage_time_sel() failed: %d\n", 2807eba41a5eSAxel Lin delay); 2808eba41a5eSAxel Lin delay = 0; 2809e8eef82bSMark Brown } 281075790251SMark Brown 281177af1b26SLinus Walleij /* Insert any necessary delays */ 281277af1b26SLinus Walleij if (delay >= 1000) { 281377af1b26SLinus Walleij mdelay(delay / 1000); 281477af1b26SLinus Walleij udelay(delay % 1000); 281577af1b26SLinus Walleij } else if (delay) { 281677af1b26SLinus Walleij udelay(delay); 281777af1b26SLinus Walleij } 28188b96de31SPhilip Rakity } 281977af1b26SLinus Walleij 28202f6c797fSAxel Lin if (ret == 0 && best_val >= 0) { 28212f6c797fSAxel Lin unsigned long data = best_val; 28222f6c797fSAxel Lin 2823ded06a52SMark Brown _notifier_call_chain(rdev, REGULATOR_EVENT_VOLTAGE_CHANGE, 28242f6c797fSAxel Lin (void *)data); 28252f6c797fSAxel Lin } 2826ded06a52SMark Brown 2827eba41a5eSAxel Lin trace_regulator_set_voltage_complete(rdev_get_name(rdev), best_val); 282875790251SMark Brown 282975790251SMark Brown return ret; 283075790251SMark Brown } 283175790251SMark Brown 2832a9f226bcSSascha Hauer static int regulator_set_voltage_unlocked(struct regulator *regulator, 2833a9f226bcSSascha Hauer int min_uV, int max_uV) 2834414c70cbSLiam Girdwood { 2835414c70cbSLiam Girdwood struct regulator_dev *rdev = regulator->rdev; 283695a3c23aSMark Brown int ret = 0; 283792d7a558SPaolo Pisati int old_min_uV, old_max_uV; 2838c00dc359SBjorn Andersson int current_uV; 2839fc42112cSSascha Hauer int best_supply_uV = 0; 2840fc42112cSSascha Hauer int supply_change_uV = 0; 2841414c70cbSLiam Girdwood 284295a3c23aSMark Brown /* If we're setting the same range as last time the change 284395a3c23aSMark Brown * should be a noop (some cpufreq implementations use the same 284495a3c23aSMark Brown * voltage for multiple frequencies, for example). 284595a3c23aSMark Brown */ 284695a3c23aSMark Brown if (regulator->min_uV == min_uV && regulator->max_uV == max_uV) 284795a3c23aSMark Brown goto out; 284895a3c23aSMark Brown 2849c00dc359SBjorn Andersson /* If we're trying to set a range that overlaps the current voltage, 2850d3fb9800SViresh Kumar * return successfully even though the regulator does not support 2851c00dc359SBjorn Andersson * changing the voltage. 2852c00dc359SBjorn Andersson */ 2853c00dc359SBjorn Andersson if (!(rdev->constraints->valid_ops_mask & REGULATOR_CHANGE_VOLTAGE)) { 2854c00dc359SBjorn Andersson current_uV = _regulator_get_voltage(rdev); 2855c00dc359SBjorn Andersson if (min_uV <= current_uV && current_uV <= max_uV) { 2856c00dc359SBjorn Andersson regulator->min_uV = min_uV; 2857c00dc359SBjorn Andersson regulator->max_uV = max_uV; 2858c00dc359SBjorn Andersson goto out; 2859c00dc359SBjorn Andersson } 2860c00dc359SBjorn Andersson } 2861c00dc359SBjorn Andersson 2862414c70cbSLiam Girdwood /* sanity check */ 2863e8eef82bSMark Brown if (!rdev->desc->ops->set_voltage && 2864e8eef82bSMark Brown !rdev->desc->ops->set_voltage_sel) { 2865414c70cbSLiam Girdwood ret = -EINVAL; 2866414c70cbSLiam Girdwood goto out; 2867414c70cbSLiam Girdwood } 2868414c70cbSLiam Girdwood 2869414c70cbSLiam Girdwood /* constraints check */ 2870414c70cbSLiam Girdwood ret = regulator_check_voltage(rdev, &min_uV, &max_uV); 2871414c70cbSLiam Girdwood if (ret < 0) 2872414c70cbSLiam Girdwood goto out; 287392d7a558SPaolo Pisati 287492d7a558SPaolo Pisati /* restore original values in case of error */ 287592d7a558SPaolo Pisati old_min_uV = regulator->min_uV; 287692d7a558SPaolo Pisati old_max_uV = regulator->max_uV; 2877414c70cbSLiam Girdwood regulator->min_uV = min_uV; 2878414c70cbSLiam Girdwood regulator->max_uV = max_uV; 28793a93f2a9SMark Brown 288005fda3b1SThomas Petazzoni ret = regulator_check_consumers(rdev, &min_uV, &max_uV); 288105fda3b1SThomas Petazzoni if (ret < 0) 288292d7a558SPaolo Pisati goto out2; 288305fda3b1SThomas Petazzoni 2884fc42112cSSascha Hauer if (rdev->supply && (rdev->desc->min_dropout_uV || 2885fc42112cSSascha Hauer !rdev->desc->ops->get_voltage)) { 2886fc42112cSSascha Hauer int current_supply_uV; 2887fc42112cSSascha Hauer int selector; 2888fc42112cSSascha Hauer 2889fc42112cSSascha Hauer selector = regulator_map_voltage(rdev, min_uV, max_uV); 2890fc42112cSSascha Hauer if (selector < 0) { 2891fc42112cSSascha Hauer ret = selector; 2892fc42112cSSascha Hauer goto out2; 2893fc42112cSSascha Hauer } 2894fc42112cSSascha Hauer 2895fc42112cSSascha Hauer best_supply_uV = _regulator_list_voltage(regulator, selector, 0); 2896fc42112cSSascha Hauer if (best_supply_uV < 0) { 2897fc42112cSSascha Hauer ret = best_supply_uV; 2898fc42112cSSascha Hauer goto out2; 2899fc42112cSSascha Hauer } 2900fc42112cSSascha Hauer 2901fc42112cSSascha Hauer best_supply_uV += rdev->desc->min_dropout_uV; 2902fc42112cSSascha Hauer 2903fc42112cSSascha Hauer current_supply_uV = _regulator_get_voltage(rdev->supply->rdev); 2904fc42112cSSascha Hauer if (current_supply_uV < 0) { 2905fc42112cSSascha Hauer ret = current_supply_uV; 2906fc42112cSSascha Hauer goto out2; 2907fc42112cSSascha Hauer } 2908fc42112cSSascha Hauer 2909fc42112cSSascha Hauer supply_change_uV = best_supply_uV - current_supply_uV; 2910fc42112cSSascha Hauer } 2911fc42112cSSascha Hauer 2912fc42112cSSascha Hauer if (supply_change_uV > 0) { 2913fc42112cSSascha Hauer ret = regulator_set_voltage_unlocked(rdev->supply, 2914fc42112cSSascha Hauer best_supply_uV, INT_MAX); 2915fc42112cSSascha Hauer if (ret) { 2916fc42112cSSascha Hauer dev_err(&rdev->dev, "Failed to increase supply voltage: %d\n", 2917fc42112cSSascha Hauer ret); 2918fc42112cSSascha Hauer goto out2; 2919fc42112cSSascha Hauer } 2920fc42112cSSascha Hauer } 2921fc42112cSSascha Hauer 292275790251SMark Brown ret = _regulator_do_set_voltage(rdev, min_uV, max_uV); 292392d7a558SPaolo Pisati if (ret < 0) 292492d7a558SPaolo Pisati goto out2; 292502fa3ec0SMark Brown 2926fc42112cSSascha Hauer if (supply_change_uV < 0) { 2927fc42112cSSascha Hauer ret = regulator_set_voltage_unlocked(rdev->supply, 2928fc42112cSSascha Hauer best_supply_uV, INT_MAX); 2929fc42112cSSascha Hauer if (ret) 2930fc42112cSSascha Hauer dev_warn(&rdev->dev, "Failed to decrease supply voltage: %d\n", 2931fc42112cSSascha Hauer ret); 2932fc42112cSSascha Hauer /* No need to fail here */ 2933fc42112cSSascha Hauer ret = 0; 2934fc42112cSSascha Hauer } 2935fc42112cSSascha Hauer 2936414c70cbSLiam Girdwood out: 2937414c70cbSLiam Girdwood return ret; 293892d7a558SPaolo Pisati out2: 293992d7a558SPaolo Pisati regulator->min_uV = old_min_uV; 294092d7a558SPaolo Pisati regulator->max_uV = old_max_uV; 2941a9f226bcSSascha Hauer 2942a9f226bcSSascha Hauer return ret; 2943a9f226bcSSascha Hauer } 2944a9f226bcSSascha Hauer 2945a9f226bcSSascha Hauer /** 2946a9f226bcSSascha Hauer * regulator_set_voltage - set regulator output voltage 2947a9f226bcSSascha Hauer * @regulator: regulator source 2948a9f226bcSSascha Hauer * @min_uV: Minimum required voltage in uV 2949a9f226bcSSascha Hauer * @max_uV: Maximum acceptable voltage in uV 2950a9f226bcSSascha Hauer * 2951a9f226bcSSascha Hauer * Sets a voltage regulator to the desired output voltage. This can be set 2952a9f226bcSSascha Hauer * during any regulator state. IOW, regulator can be disabled or enabled. 2953a9f226bcSSascha Hauer * 2954a9f226bcSSascha Hauer * If the regulator is enabled then the voltage will change to the new value 2955a9f226bcSSascha Hauer * immediately otherwise if the regulator is disabled the regulator will 2956a9f226bcSSascha Hauer * output at the new voltage when enabled. 2957a9f226bcSSascha Hauer * 2958a9f226bcSSascha Hauer * NOTE: If the regulator is shared between several devices then the lowest 2959a9f226bcSSascha Hauer * request voltage that meets the system constraints will be used. 2960a9f226bcSSascha Hauer * Regulator system constraints must be set for this regulator before 2961a9f226bcSSascha Hauer * calling this function otherwise this call will fail. 2962a9f226bcSSascha Hauer */ 2963a9f226bcSSascha Hauer int regulator_set_voltage(struct regulator *regulator, int min_uV, int max_uV) 2964a9f226bcSSascha Hauer { 2965a9f226bcSSascha Hauer int ret = 0; 2966a9f226bcSSascha Hauer 2967fc42112cSSascha Hauer regulator_lock_supply(regulator->rdev); 2968a9f226bcSSascha Hauer 2969a9f226bcSSascha Hauer ret = regulator_set_voltage_unlocked(regulator, min_uV, max_uV); 2970a9f226bcSSascha Hauer 2971fc42112cSSascha Hauer regulator_unlock_supply(regulator->rdev); 2972a9f226bcSSascha Hauer 297392d7a558SPaolo Pisati return ret; 2974414c70cbSLiam Girdwood } 2975414c70cbSLiam Girdwood EXPORT_SYMBOL_GPL(regulator_set_voltage); 2976414c70cbSLiam Girdwood 2977606a2562SMark Brown /** 297888cd222bSLinus Walleij * regulator_set_voltage_time - get raise/fall time 297988cd222bSLinus Walleij * @regulator: regulator source 298088cd222bSLinus Walleij * @old_uV: starting voltage in microvolts 298188cd222bSLinus Walleij * @new_uV: target voltage in microvolts 298288cd222bSLinus Walleij * 298388cd222bSLinus Walleij * Provided with the starting and ending voltage, this function attempts to 298488cd222bSLinus Walleij * calculate the time in microseconds required to rise or fall to this new 298588cd222bSLinus Walleij * voltage. 298688cd222bSLinus Walleij */ 298788cd222bSLinus Walleij int regulator_set_voltage_time(struct regulator *regulator, 298888cd222bSLinus Walleij int old_uV, int new_uV) 298988cd222bSLinus Walleij { 299088cd222bSLinus Walleij struct regulator_dev *rdev = regulator->rdev; 2991272e2315SGuodong Xu const struct regulator_ops *ops = rdev->desc->ops; 299288cd222bSLinus Walleij int old_sel = -1; 299388cd222bSLinus Walleij int new_sel = -1; 299488cd222bSLinus Walleij int voltage; 299588cd222bSLinus Walleij int i; 299688cd222bSLinus Walleij 299788cd222bSLinus Walleij /* Currently requires operations to do this */ 299888cd222bSLinus Walleij if (!ops->list_voltage || !ops->set_voltage_time_sel 299988cd222bSLinus Walleij || !rdev->desc->n_voltages) 300088cd222bSLinus Walleij return -EINVAL; 300188cd222bSLinus Walleij 300288cd222bSLinus Walleij for (i = 0; i < rdev->desc->n_voltages; i++) { 300388cd222bSLinus Walleij /* We only look for exact voltage matches here */ 300488cd222bSLinus Walleij voltage = regulator_list_voltage(regulator, i); 300588cd222bSLinus Walleij if (voltage < 0) 300688cd222bSLinus Walleij return -EINVAL; 300788cd222bSLinus Walleij if (voltage == 0) 300888cd222bSLinus Walleij continue; 300988cd222bSLinus Walleij if (voltage == old_uV) 301088cd222bSLinus Walleij old_sel = i; 301188cd222bSLinus Walleij if (voltage == new_uV) 301288cd222bSLinus Walleij new_sel = i; 301388cd222bSLinus Walleij } 301488cd222bSLinus Walleij 301588cd222bSLinus Walleij if (old_sel < 0 || new_sel < 0) 301688cd222bSLinus Walleij return -EINVAL; 301788cd222bSLinus Walleij 301888cd222bSLinus Walleij return ops->set_voltage_time_sel(rdev, old_sel, new_sel); 301988cd222bSLinus Walleij } 302088cd222bSLinus Walleij EXPORT_SYMBOL_GPL(regulator_set_voltage_time); 302188cd222bSLinus Walleij 302288cd222bSLinus Walleij /** 302398a175b6SYadwinder Singh Brar * regulator_set_voltage_time_sel - get raise/fall time 3024296c6566SRandy Dunlap * @rdev: regulator source device 302598a175b6SYadwinder Singh Brar * @old_selector: selector for starting voltage 302698a175b6SYadwinder Singh Brar * @new_selector: selector for target voltage 302798a175b6SYadwinder Singh Brar * 302898a175b6SYadwinder Singh Brar * Provided with the starting and target voltage selectors, this function 302998a175b6SYadwinder Singh Brar * returns time in microseconds required to rise or fall to this new voltage 303098a175b6SYadwinder Singh Brar * 3031f11d08c3SAxel Lin * Drivers providing ramp_delay in regulation_constraints can use this as their 3032398715abSAxel Lin * set_voltage_time_sel() operation. 303398a175b6SYadwinder Singh Brar */ 303498a175b6SYadwinder Singh Brar int regulator_set_voltage_time_sel(struct regulator_dev *rdev, 303598a175b6SYadwinder Singh Brar unsigned int old_selector, 303698a175b6SYadwinder Singh Brar unsigned int new_selector) 303798a175b6SYadwinder Singh Brar { 3038398715abSAxel Lin unsigned int ramp_delay = 0; 3039f11d08c3SAxel Lin int old_volt, new_volt; 3040398715abSAxel Lin 30416f0b2c69SYadwinder Singh Brar if (rdev->constraints->ramp_delay) 3042398715abSAxel Lin ramp_delay = rdev->constraints->ramp_delay; 3043398715abSAxel Lin else if (rdev->desc->ramp_delay) 3044398715abSAxel Lin ramp_delay = rdev->desc->ramp_delay; 3045398715abSAxel Lin 3046398715abSAxel Lin if (ramp_delay == 0) { 30476f0b2c69SYadwinder Singh Brar rdev_warn(rdev, "ramp_delay not set\n"); 3048398715abSAxel Lin return 0; 30496f0b2c69SYadwinder Singh Brar } 3050398715abSAxel Lin 3051f11d08c3SAxel Lin /* sanity check */ 3052f11d08c3SAxel Lin if (!rdev->desc->ops->list_voltage) 3053f11d08c3SAxel Lin return -EINVAL; 3054398715abSAxel Lin 3055f11d08c3SAxel Lin old_volt = rdev->desc->ops->list_voltage(rdev, old_selector); 3056f11d08c3SAxel Lin new_volt = rdev->desc->ops->list_voltage(rdev, new_selector); 3057f11d08c3SAxel Lin 3058f11d08c3SAxel Lin return DIV_ROUND_UP(abs(new_volt - old_volt), ramp_delay); 305998a175b6SYadwinder Singh Brar } 3060b19dbf71SMark Brown EXPORT_SYMBOL_GPL(regulator_set_voltage_time_sel); 306198a175b6SYadwinder Singh Brar 306298a175b6SYadwinder Singh Brar /** 3063606a2562SMark Brown * regulator_sync_voltage - re-apply last regulator output voltage 3064606a2562SMark Brown * @regulator: regulator source 3065606a2562SMark Brown * 3066606a2562SMark Brown * Re-apply the last configured voltage. This is intended to be used 3067606a2562SMark Brown * where some external control source the consumer is cooperating with 3068606a2562SMark Brown * has caused the configured voltage to change. 3069606a2562SMark Brown */ 3070606a2562SMark Brown int regulator_sync_voltage(struct regulator *regulator) 3071606a2562SMark Brown { 3072606a2562SMark Brown struct regulator_dev *rdev = regulator->rdev; 3073606a2562SMark Brown int ret, min_uV, max_uV; 3074606a2562SMark Brown 3075606a2562SMark Brown mutex_lock(&rdev->mutex); 3076606a2562SMark Brown 3077606a2562SMark Brown if (!rdev->desc->ops->set_voltage && 3078606a2562SMark Brown !rdev->desc->ops->set_voltage_sel) { 3079606a2562SMark Brown ret = -EINVAL; 3080606a2562SMark Brown goto out; 3081606a2562SMark Brown } 3082606a2562SMark Brown 3083606a2562SMark Brown /* This is only going to work if we've had a voltage configured. */ 3084606a2562SMark Brown if (!regulator->min_uV && !regulator->max_uV) { 3085606a2562SMark Brown ret = -EINVAL; 3086606a2562SMark Brown goto out; 3087606a2562SMark Brown } 3088606a2562SMark Brown 3089606a2562SMark Brown min_uV = regulator->min_uV; 3090606a2562SMark Brown max_uV = regulator->max_uV; 3091606a2562SMark Brown 3092606a2562SMark Brown /* This should be a paranoia check... */ 3093606a2562SMark Brown ret = regulator_check_voltage(rdev, &min_uV, &max_uV); 3094606a2562SMark Brown if (ret < 0) 3095606a2562SMark Brown goto out; 3096606a2562SMark Brown 3097606a2562SMark Brown ret = regulator_check_consumers(rdev, &min_uV, &max_uV); 3098606a2562SMark Brown if (ret < 0) 3099606a2562SMark Brown goto out; 3100606a2562SMark Brown 3101606a2562SMark Brown ret = _regulator_do_set_voltage(rdev, min_uV, max_uV); 3102606a2562SMark Brown 3103606a2562SMark Brown out: 3104606a2562SMark Brown mutex_unlock(&rdev->mutex); 3105606a2562SMark Brown return ret; 3106606a2562SMark Brown } 3107606a2562SMark Brown EXPORT_SYMBOL_GPL(regulator_sync_voltage); 3108606a2562SMark Brown 3109414c70cbSLiam Girdwood static int _regulator_get_voltage(struct regulator_dev *rdev) 3110414c70cbSLiam Girdwood { 3111bf5892a8SMark Brown int sel, ret; 3112476c2d83SMark Brown 3113476c2d83SMark Brown if (rdev->desc->ops->get_voltage_sel) { 3114476c2d83SMark Brown sel = rdev->desc->ops->get_voltage_sel(rdev); 3115476c2d83SMark Brown if (sel < 0) 3116476c2d83SMark Brown return sel; 3117bf5892a8SMark Brown ret = rdev->desc->ops->list_voltage(rdev, sel); 3118cb220d16SAxel Lin } else if (rdev->desc->ops->get_voltage) { 3119bf5892a8SMark Brown ret = rdev->desc->ops->get_voltage(rdev); 3120f7df20ecSMark Brown } else if (rdev->desc->ops->list_voltage) { 3121f7df20ecSMark Brown ret = rdev->desc->ops->list_voltage(rdev, 0); 31225a523605SLaxman Dewangan } else if (rdev->desc->fixed_uV && (rdev->desc->n_voltages == 1)) { 31235a523605SLaxman Dewangan ret = rdev->desc->fixed_uV; 3124e303996eSJavier Martinez Canillas } else if (rdev->supply) { 3125d9b96d35SMark Brown ret = _regulator_get_voltage(rdev->supply->rdev); 3126cb220d16SAxel Lin } else { 3127414c70cbSLiam Girdwood return -EINVAL; 3128cb220d16SAxel Lin } 3129bf5892a8SMark Brown 3130cb220d16SAxel Lin if (ret < 0) 3131cb220d16SAxel Lin return ret; 3132bf5892a8SMark Brown return ret - rdev->constraints->uV_offset; 3133414c70cbSLiam Girdwood } 3134414c70cbSLiam Girdwood 3135414c70cbSLiam Girdwood /** 3136414c70cbSLiam Girdwood * regulator_get_voltage - get regulator output voltage 3137414c70cbSLiam Girdwood * @regulator: regulator source 3138414c70cbSLiam Girdwood * 3139414c70cbSLiam Girdwood * This returns the current regulator voltage in uV. 3140414c70cbSLiam Girdwood * 3141414c70cbSLiam Girdwood * NOTE: If the regulator is disabled it will return the voltage value. This 3142414c70cbSLiam Girdwood * function should not be used to determine regulator state. 3143414c70cbSLiam Girdwood */ 3144414c70cbSLiam Girdwood int regulator_get_voltage(struct regulator *regulator) 3145414c70cbSLiam Girdwood { 3146414c70cbSLiam Girdwood int ret; 3147414c70cbSLiam Girdwood 3148d9b96d35SMark Brown regulator_lock_supply(regulator->rdev); 3149414c70cbSLiam Girdwood 3150414c70cbSLiam Girdwood ret = _regulator_get_voltage(regulator->rdev); 3151414c70cbSLiam Girdwood 3152d9b96d35SMark Brown regulator_unlock_supply(regulator->rdev); 3153414c70cbSLiam Girdwood 3154414c70cbSLiam Girdwood return ret; 3155414c70cbSLiam Girdwood } 3156414c70cbSLiam Girdwood EXPORT_SYMBOL_GPL(regulator_get_voltage); 3157414c70cbSLiam Girdwood 3158414c70cbSLiam Girdwood /** 3159414c70cbSLiam Girdwood * regulator_set_current_limit - set regulator output current limit 3160414c70cbSLiam Girdwood * @regulator: regulator source 3161ce0d10f8SCharles Keepax * @min_uA: Minimum supported current in uA 3162414c70cbSLiam Girdwood * @max_uA: Maximum supported current in uA 3163414c70cbSLiam Girdwood * 3164414c70cbSLiam Girdwood * Sets current sink to the desired output current. This can be set during 3165414c70cbSLiam Girdwood * any regulator state. IOW, regulator can be disabled or enabled. 3166414c70cbSLiam Girdwood * 3167414c70cbSLiam Girdwood * If the regulator is enabled then the current will change to the new value 3168414c70cbSLiam Girdwood * immediately otherwise if the regulator is disabled the regulator will 3169414c70cbSLiam Girdwood * output at the new current when enabled. 3170414c70cbSLiam Girdwood * 3171414c70cbSLiam Girdwood * NOTE: Regulator system constraints must be set for this regulator before 3172414c70cbSLiam Girdwood * calling this function otherwise this call will fail. 3173414c70cbSLiam Girdwood */ 3174414c70cbSLiam Girdwood int regulator_set_current_limit(struct regulator *regulator, 3175414c70cbSLiam Girdwood int min_uA, int max_uA) 3176414c70cbSLiam Girdwood { 3177414c70cbSLiam Girdwood struct regulator_dev *rdev = regulator->rdev; 3178414c70cbSLiam Girdwood int ret; 3179414c70cbSLiam Girdwood 3180414c70cbSLiam Girdwood mutex_lock(&rdev->mutex); 3181414c70cbSLiam Girdwood 3182414c70cbSLiam Girdwood /* sanity check */ 3183414c70cbSLiam Girdwood if (!rdev->desc->ops->set_current_limit) { 3184414c70cbSLiam Girdwood ret = -EINVAL; 3185414c70cbSLiam Girdwood goto out; 3186414c70cbSLiam Girdwood } 3187414c70cbSLiam Girdwood 3188414c70cbSLiam Girdwood /* constraints check */ 3189414c70cbSLiam Girdwood ret = regulator_check_current_limit(rdev, &min_uA, &max_uA); 3190414c70cbSLiam Girdwood if (ret < 0) 3191414c70cbSLiam Girdwood goto out; 3192414c70cbSLiam Girdwood 3193414c70cbSLiam Girdwood ret = rdev->desc->ops->set_current_limit(rdev, min_uA, max_uA); 3194414c70cbSLiam Girdwood out: 3195414c70cbSLiam Girdwood mutex_unlock(&rdev->mutex); 3196414c70cbSLiam Girdwood return ret; 3197414c70cbSLiam Girdwood } 3198414c70cbSLiam Girdwood EXPORT_SYMBOL_GPL(regulator_set_current_limit); 3199414c70cbSLiam Girdwood 3200414c70cbSLiam Girdwood static int _regulator_get_current_limit(struct regulator_dev *rdev) 3201414c70cbSLiam Girdwood { 3202414c70cbSLiam Girdwood int ret; 3203414c70cbSLiam Girdwood 3204414c70cbSLiam Girdwood mutex_lock(&rdev->mutex); 3205414c70cbSLiam Girdwood 3206414c70cbSLiam Girdwood /* sanity check */ 3207414c70cbSLiam Girdwood if (!rdev->desc->ops->get_current_limit) { 3208414c70cbSLiam Girdwood ret = -EINVAL; 3209414c70cbSLiam Girdwood goto out; 3210414c70cbSLiam Girdwood } 3211414c70cbSLiam Girdwood 3212414c70cbSLiam Girdwood ret = rdev->desc->ops->get_current_limit(rdev); 3213414c70cbSLiam Girdwood out: 3214414c70cbSLiam Girdwood mutex_unlock(&rdev->mutex); 3215414c70cbSLiam Girdwood return ret; 3216414c70cbSLiam Girdwood } 3217414c70cbSLiam Girdwood 3218414c70cbSLiam Girdwood /** 3219414c70cbSLiam Girdwood * regulator_get_current_limit - get regulator output current 3220414c70cbSLiam Girdwood * @regulator: regulator source 3221414c70cbSLiam Girdwood * 3222414c70cbSLiam Girdwood * This returns the current supplied by the specified current sink in uA. 3223414c70cbSLiam Girdwood * 3224414c70cbSLiam Girdwood * NOTE: If the regulator is disabled it will return the current value. This 3225414c70cbSLiam Girdwood * function should not be used to determine regulator state. 3226414c70cbSLiam Girdwood */ 3227414c70cbSLiam Girdwood int regulator_get_current_limit(struct regulator *regulator) 3228414c70cbSLiam Girdwood { 3229414c70cbSLiam Girdwood return _regulator_get_current_limit(regulator->rdev); 3230414c70cbSLiam Girdwood } 3231414c70cbSLiam Girdwood EXPORT_SYMBOL_GPL(regulator_get_current_limit); 3232414c70cbSLiam Girdwood 3233414c70cbSLiam Girdwood /** 3234414c70cbSLiam Girdwood * regulator_set_mode - set regulator operating mode 3235414c70cbSLiam Girdwood * @regulator: regulator source 3236414c70cbSLiam Girdwood * @mode: operating mode - one of the REGULATOR_MODE constants 3237414c70cbSLiam Girdwood * 3238414c70cbSLiam Girdwood * Set regulator operating mode to increase regulator efficiency or improve 3239414c70cbSLiam Girdwood * regulation performance. 3240414c70cbSLiam Girdwood * 3241414c70cbSLiam Girdwood * NOTE: Regulator system constraints must be set for this regulator before 3242414c70cbSLiam Girdwood * calling this function otherwise this call will fail. 3243414c70cbSLiam Girdwood */ 3244414c70cbSLiam Girdwood int regulator_set_mode(struct regulator *regulator, unsigned int mode) 3245414c70cbSLiam Girdwood { 3246414c70cbSLiam Girdwood struct regulator_dev *rdev = regulator->rdev; 3247414c70cbSLiam Girdwood int ret; 3248500b4ac9SSundar R Iyer int regulator_curr_mode; 3249414c70cbSLiam Girdwood 3250414c70cbSLiam Girdwood mutex_lock(&rdev->mutex); 3251414c70cbSLiam Girdwood 3252414c70cbSLiam Girdwood /* sanity check */ 3253414c70cbSLiam Girdwood if (!rdev->desc->ops->set_mode) { 3254414c70cbSLiam Girdwood ret = -EINVAL; 3255414c70cbSLiam Girdwood goto out; 3256414c70cbSLiam Girdwood } 3257414c70cbSLiam Girdwood 3258500b4ac9SSundar R Iyer /* return if the same mode is requested */ 3259500b4ac9SSundar R Iyer if (rdev->desc->ops->get_mode) { 3260500b4ac9SSundar R Iyer regulator_curr_mode = rdev->desc->ops->get_mode(rdev); 3261500b4ac9SSundar R Iyer if (regulator_curr_mode == mode) { 3262500b4ac9SSundar R Iyer ret = 0; 3263500b4ac9SSundar R Iyer goto out; 3264500b4ac9SSundar R Iyer } 3265500b4ac9SSundar R Iyer } 3266500b4ac9SSundar R Iyer 3267414c70cbSLiam Girdwood /* constraints check */ 326822c51b47SAxel Lin ret = regulator_mode_constrain(rdev, &mode); 3269414c70cbSLiam Girdwood if (ret < 0) 3270414c70cbSLiam Girdwood goto out; 3271414c70cbSLiam Girdwood 3272414c70cbSLiam Girdwood ret = rdev->desc->ops->set_mode(rdev, mode); 3273414c70cbSLiam Girdwood out: 3274414c70cbSLiam Girdwood mutex_unlock(&rdev->mutex); 3275414c70cbSLiam Girdwood return ret; 3276414c70cbSLiam Girdwood } 3277414c70cbSLiam Girdwood EXPORT_SYMBOL_GPL(regulator_set_mode); 3278414c70cbSLiam Girdwood 3279414c70cbSLiam Girdwood static unsigned int _regulator_get_mode(struct regulator_dev *rdev) 3280414c70cbSLiam Girdwood { 3281414c70cbSLiam Girdwood int ret; 3282414c70cbSLiam Girdwood 3283414c70cbSLiam Girdwood mutex_lock(&rdev->mutex); 3284414c70cbSLiam Girdwood 3285414c70cbSLiam Girdwood /* sanity check */ 3286414c70cbSLiam Girdwood if (!rdev->desc->ops->get_mode) { 3287414c70cbSLiam Girdwood ret = -EINVAL; 3288414c70cbSLiam Girdwood goto out; 3289414c70cbSLiam Girdwood } 3290414c70cbSLiam Girdwood 3291414c70cbSLiam Girdwood ret = rdev->desc->ops->get_mode(rdev); 3292414c70cbSLiam Girdwood out: 3293414c70cbSLiam Girdwood mutex_unlock(&rdev->mutex); 3294414c70cbSLiam Girdwood return ret; 3295414c70cbSLiam Girdwood } 3296414c70cbSLiam Girdwood 3297414c70cbSLiam Girdwood /** 3298414c70cbSLiam Girdwood * regulator_get_mode - get regulator operating mode 3299414c70cbSLiam Girdwood * @regulator: regulator source 3300414c70cbSLiam Girdwood * 3301414c70cbSLiam Girdwood * Get the current regulator operating mode. 3302414c70cbSLiam Girdwood */ 3303414c70cbSLiam Girdwood unsigned int regulator_get_mode(struct regulator *regulator) 3304414c70cbSLiam Girdwood { 3305414c70cbSLiam Girdwood return _regulator_get_mode(regulator->rdev); 3306414c70cbSLiam Girdwood } 3307414c70cbSLiam Girdwood EXPORT_SYMBOL_GPL(regulator_get_mode); 3308414c70cbSLiam Girdwood 3309414c70cbSLiam Girdwood /** 3310e39ce48fSBjorn Andersson * regulator_set_load - set regulator load 3311414c70cbSLiam Girdwood * @regulator: regulator source 3312414c70cbSLiam Girdwood * @uA_load: load current 3313414c70cbSLiam Girdwood * 3314414c70cbSLiam Girdwood * Notifies the regulator core of a new device load. This is then used by 3315414c70cbSLiam Girdwood * DRMS (if enabled by constraints) to set the most efficient regulator 3316414c70cbSLiam Girdwood * operating mode for the new regulator loading. 3317414c70cbSLiam Girdwood * 3318414c70cbSLiam Girdwood * Consumer devices notify their supply regulator of the maximum power 3319414c70cbSLiam Girdwood * they will require (can be taken from device datasheet in the power 3320414c70cbSLiam Girdwood * consumption tables) when they change operational status and hence power 3321414c70cbSLiam Girdwood * state. Examples of operational state changes that can affect power 3322414c70cbSLiam Girdwood * consumption are :- 3323414c70cbSLiam Girdwood * 3324414c70cbSLiam Girdwood * o Device is opened / closed. 3325414c70cbSLiam Girdwood * o Device I/O is about to begin or has just finished. 3326414c70cbSLiam Girdwood * o Device is idling in between work. 3327414c70cbSLiam Girdwood * 3328414c70cbSLiam Girdwood * This information is also exported via sysfs to userspace. 3329414c70cbSLiam Girdwood * 3330414c70cbSLiam Girdwood * DRMS will sum the total requested load on the regulator and change 3331414c70cbSLiam Girdwood * to the most efficient operating mode if platform constraints allow. 3332414c70cbSLiam Girdwood * 3333e39ce48fSBjorn Andersson * On error a negative errno is returned. 3334414c70cbSLiam Girdwood */ 3335e39ce48fSBjorn Andersson int regulator_set_load(struct regulator *regulator, int uA_load) 3336414c70cbSLiam Girdwood { 3337414c70cbSLiam Girdwood struct regulator_dev *rdev = regulator->rdev; 33388460ef38SBjorn Andersson int ret; 3339d92d95b6SStephen Boyd 3340414c70cbSLiam Girdwood mutex_lock(&rdev->mutex); 3341414c70cbSLiam Girdwood regulator->uA_load = uA_load; 33428460ef38SBjorn Andersson ret = drms_uA_update(rdev); 3343414c70cbSLiam Girdwood mutex_unlock(&rdev->mutex); 33448460ef38SBjorn Andersson 3345414c70cbSLiam Girdwood return ret; 3346414c70cbSLiam Girdwood } 3347e39ce48fSBjorn Andersson EXPORT_SYMBOL_GPL(regulator_set_load); 3348414c70cbSLiam Girdwood 3349414c70cbSLiam Girdwood /** 3350f59c8f9fSMark Brown * regulator_allow_bypass - allow the regulator to go into bypass mode 3351f59c8f9fSMark Brown * 3352f59c8f9fSMark Brown * @regulator: Regulator to configure 33539345dfb8SNishanth Menon * @enable: enable or disable bypass mode 3354f59c8f9fSMark Brown * 3355f59c8f9fSMark Brown * Allow the regulator to go into bypass mode if all other consumers 3356f59c8f9fSMark Brown * for the regulator also enable bypass mode and the machine 3357f59c8f9fSMark Brown * constraints allow this. Bypass mode means that the regulator is 3358f59c8f9fSMark Brown * simply passing the input directly to the output with no regulation. 3359f59c8f9fSMark Brown */ 3360f59c8f9fSMark Brown int regulator_allow_bypass(struct regulator *regulator, bool enable) 3361f59c8f9fSMark Brown { 3362f59c8f9fSMark Brown struct regulator_dev *rdev = regulator->rdev; 3363f59c8f9fSMark Brown int ret = 0; 3364f59c8f9fSMark Brown 3365f59c8f9fSMark Brown if (!rdev->desc->ops->set_bypass) 3366f59c8f9fSMark Brown return 0; 3367f59c8f9fSMark Brown 3368f59c8f9fSMark Brown if (rdev->constraints && 3369f59c8f9fSMark Brown !(rdev->constraints->valid_ops_mask & REGULATOR_CHANGE_BYPASS)) 3370f59c8f9fSMark Brown return 0; 3371f59c8f9fSMark Brown 3372f59c8f9fSMark Brown mutex_lock(&rdev->mutex); 3373f59c8f9fSMark Brown 3374f59c8f9fSMark Brown if (enable && !regulator->bypass) { 3375f59c8f9fSMark Brown rdev->bypass_count++; 3376f59c8f9fSMark Brown 3377f59c8f9fSMark Brown if (rdev->bypass_count == rdev->open_count) { 3378f59c8f9fSMark Brown ret = rdev->desc->ops->set_bypass(rdev, enable); 3379f59c8f9fSMark Brown if (ret != 0) 3380f59c8f9fSMark Brown rdev->bypass_count--; 3381f59c8f9fSMark Brown } 3382f59c8f9fSMark Brown 3383f59c8f9fSMark Brown } else if (!enable && regulator->bypass) { 3384f59c8f9fSMark Brown rdev->bypass_count--; 3385f59c8f9fSMark Brown 3386f59c8f9fSMark Brown if (rdev->bypass_count != rdev->open_count) { 3387f59c8f9fSMark Brown ret = rdev->desc->ops->set_bypass(rdev, enable); 3388f59c8f9fSMark Brown if (ret != 0) 3389f59c8f9fSMark Brown rdev->bypass_count++; 3390f59c8f9fSMark Brown } 3391f59c8f9fSMark Brown } 3392f59c8f9fSMark Brown 3393f59c8f9fSMark Brown if (ret == 0) 3394f59c8f9fSMark Brown regulator->bypass = enable; 3395f59c8f9fSMark Brown 3396f59c8f9fSMark Brown mutex_unlock(&rdev->mutex); 3397f59c8f9fSMark Brown 3398f59c8f9fSMark Brown return ret; 3399f59c8f9fSMark Brown } 3400f59c8f9fSMark Brown EXPORT_SYMBOL_GPL(regulator_allow_bypass); 3401f59c8f9fSMark Brown 3402f59c8f9fSMark Brown /** 3403414c70cbSLiam Girdwood * regulator_register_notifier - register regulator event notifier 3404414c70cbSLiam Girdwood * @regulator: regulator source 340569279fb9SMark Brown * @nb: notifier block 3406414c70cbSLiam Girdwood * 3407414c70cbSLiam Girdwood * Register notifier block to receive regulator events. 3408414c70cbSLiam Girdwood */ 3409414c70cbSLiam Girdwood int regulator_register_notifier(struct regulator *regulator, 3410414c70cbSLiam Girdwood struct notifier_block *nb) 3411414c70cbSLiam Girdwood { 3412414c70cbSLiam Girdwood return blocking_notifier_chain_register(®ulator->rdev->notifier, 3413414c70cbSLiam Girdwood nb); 3414414c70cbSLiam Girdwood } 3415414c70cbSLiam Girdwood EXPORT_SYMBOL_GPL(regulator_register_notifier); 3416414c70cbSLiam Girdwood 3417414c70cbSLiam Girdwood /** 3418414c70cbSLiam Girdwood * regulator_unregister_notifier - unregister regulator event notifier 3419414c70cbSLiam Girdwood * @regulator: regulator source 342069279fb9SMark Brown * @nb: notifier block 3421414c70cbSLiam Girdwood * 3422414c70cbSLiam Girdwood * Unregister regulator event notifier block. 3423414c70cbSLiam Girdwood */ 3424414c70cbSLiam Girdwood int regulator_unregister_notifier(struct regulator *regulator, 3425414c70cbSLiam Girdwood struct notifier_block *nb) 3426414c70cbSLiam Girdwood { 3427414c70cbSLiam Girdwood return blocking_notifier_chain_unregister(®ulator->rdev->notifier, 3428414c70cbSLiam Girdwood nb); 3429414c70cbSLiam Girdwood } 3430414c70cbSLiam Girdwood EXPORT_SYMBOL_GPL(regulator_unregister_notifier); 3431414c70cbSLiam Girdwood 3432b136fb44SJonathan Cameron /* notify regulator consumers and downstream regulator consumers. 3433b136fb44SJonathan Cameron * Note mutex must be held by caller. 3434b136fb44SJonathan Cameron */ 34357179569aSHeiko Stübner static int _notifier_call_chain(struct regulator_dev *rdev, 3436414c70cbSLiam Girdwood unsigned long event, void *data) 3437414c70cbSLiam Girdwood { 3438414c70cbSLiam Girdwood /* call rdev chain first */ 34397179569aSHeiko Stübner return blocking_notifier_call_chain(&rdev->notifier, event, data); 3440414c70cbSLiam Girdwood } 3441414c70cbSLiam Girdwood 3442414c70cbSLiam Girdwood /** 3443414c70cbSLiam Girdwood * regulator_bulk_get - get multiple regulator consumers 3444414c70cbSLiam Girdwood * 3445414c70cbSLiam Girdwood * @dev: Device to supply 3446414c70cbSLiam Girdwood * @num_consumers: Number of consumers to register 3447414c70cbSLiam Girdwood * @consumers: Configuration of consumers; clients are stored here. 3448414c70cbSLiam Girdwood * 3449414c70cbSLiam Girdwood * @return 0 on success, an errno on failure. 3450414c70cbSLiam Girdwood * 3451414c70cbSLiam Girdwood * This helper function allows drivers to get several regulator 3452414c70cbSLiam Girdwood * consumers in one operation. If any of the regulators cannot be 3453414c70cbSLiam Girdwood * acquired then any regulators that were allocated will be freed 3454414c70cbSLiam Girdwood * before returning to the caller. 3455414c70cbSLiam Girdwood */ 3456414c70cbSLiam Girdwood int regulator_bulk_get(struct device *dev, int num_consumers, 3457414c70cbSLiam Girdwood struct regulator_bulk_data *consumers) 3458414c70cbSLiam Girdwood { 3459414c70cbSLiam Girdwood int i; 3460414c70cbSLiam Girdwood int ret; 3461414c70cbSLiam Girdwood 3462414c70cbSLiam Girdwood for (i = 0; i < num_consumers; i++) 3463414c70cbSLiam Girdwood consumers[i].consumer = NULL; 3464414c70cbSLiam Girdwood 3465414c70cbSLiam Girdwood for (i = 0; i < num_consumers; i++) { 34663ff3f518SBjorn Andersson consumers[i].consumer = _regulator_get(dev, 34673ff3f518SBjorn Andersson consumers[i].supply, 34683ff3f518SBjorn Andersson false, 34693ff3f518SBjorn Andersson !consumers[i].optional); 3470414c70cbSLiam Girdwood if (IS_ERR(consumers[i].consumer)) { 3471414c70cbSLiam Girdwood ret = PTR_ERR(consumers[i].consumer); 34725b307627SMark Brown dev_err(dev, "Failed to get supply '%s': %d\n", 34735b307627SMark Brown consumers[i].supply, ret); 3474414c70cbSLiam Girdwood consumers[i].consumer = NULL; 3475414c70cbSLiam Girdwood goto err; 3476414c70cbSLiam Girdwood } 3477414c70cbSLiam Girdwood } 3478414c70cbSLiam Girdwood 3479414c70cbSLiam Girdwood return 0; 3480414c70cbSLiam Girdwood 3481414c70cbSLiam Girdwood err: 3482b29c7690SAxel Lin while (--i >= 0) 3483414c70cbSLiam Girdwood regulator_put(consumers[i].consumer); 3484414c70cbSLiam Girdwood 3485414c70cbSLiam Girdwood return ret; 3486414c70cbSLiam Girdwood } 3487414c70cbSLiam Girdwood EXPORT_SYMBOL_GPL(regulator_bulk_get); 3488414c70cbSLiam Girdwood 3489f21e0e81SMark Brown static void regulator_bulk_enable_async(void *data, async_cookie_t cookie) 3490f21e0e81SMark Brown { 3491f21e0e81SMark Brown struct regulator_bulk_data *bulk = data; 3492f21e0e81SMark Brown 3493f21e0e81SMark Brown bulk->ret = regulator_enable(bulk->consumer); 3494f21e0e81SMark Brown } 3495f21e0e81SMark Brown 3496414c70cbSLiam Girdwood /** 3497414c70cbSLiam Girdwood * regulator_bulk_enable - enable multiple regulator consumers 3498414c70cbSLiam Girdwood * 3499414c70cbSLiam Girdwood * @num_consumers: Number of consumers 3500414c70cbSLiam Girdwood * @consumers: Consumer data; clients are stored here. 3501414c70cbSLiam Girdwood * @return 0 on success, an errno on failure 3502414c70cbSLiam Girdwood * 3503414c70cbSLiam Girdwood * This convenience API allows consumers to enable multiple regulator 3504414c70cbSLiam Girdwood * clients in a single API call. If any consumers cannot be enabled 3505414c70cbSLiam Girdwood * then any others that were enabled will be disabled again prior to 3506414c70cbSLiam Girdwood * return. 3507414c70cbSLiam Girdwood */ 3508414c70cbSLiam Girdwood int regulator_bulk_enable(int num_consumers, 3509414c70cbSLiam Girdwood struct regulator_bulk_data *consumers) 3510414c70cbSLiam Girdwood { 35112955b47dSDan Williams ASYNC_DOMAIN_EXCLUSIVE(async_domain); 3512414c70cbSLiam Girdwood int i; 3513f21e0e81SMark Brown int ret = 0; 3514414c70cbSLiam Girdwood 35156492bc1bSMark Brown for (i = 0; i < num_consumers; i++) { 35166492bc1bSMark Brown if (consumers[i].consumer->always_on) 35176492bc1bSMark Brown consumers[i].ret = 0; 35186492bc1bSMark Brown else 3519f21e0e81SMark Brown async_schedule_domain(regulator_bulk_enable_async, 3520f21e0e81SMark Brown &consumers[i], &async_domain); 35216492bc1bSMark Brown } 3522f21e0e81SMark Brown 3523f21e0e81SMark Brown async_synchronize_full_domain(&async_domain); 3524f21e0e81SMark Brown 3525f21e0e81SMark Brown /* If any consumer failed we need to unwind any that succeeded */ 3526414c70cbSLiam Girdwood for (i = 0; i < num_consumers; i++) { 3527f21e0e81SMark Brown if (consumers[i].ret != 0) { 3528f21e0e81SMark Brown ret = consumers[i].ret; 3529414c70cbSLiam Girdwood goto err; 3530414c70cbSLiam Girdwood } 3531f21e0e81SMark Brown } 3532414c70cbSLiam Girdwood 3533414c70cbSLiam Girdwood return 0; 3534414c70cbSLiam Girdwood 3535414c70cbSLiam Girdwood err: 3536fbe31057SAndrzej Hajda for (i = 0; i < num_consumers; i++) { 3537fbe31057SAndrzej Hajda if (consumers[i].ret < 0) 3538fbe31057SAndrzej Hajda pr_err("Failed to enable %s: %d\n", consumers[i].supply, 3539fbe31057SAndrzej Hajda consumers[i].ret); 3540fbe31057SAndrzej Hajda else 3541414c70cbSLiam Girdwood regulator_disable(consumers[i].consumer); 3542fbe31057SAndrzej Hajda } 3543414c70cbSLiam Girdwood 3544414c70cbSLiam Girdwood return ret; 3545414c70cbSLiam Girdwood } 3546414c70cbSLiam Girdwood EXPORT_SYMBOL_GPL(regulator_bulk_enable); 3547414c70cbSLiam Girdwood 3548414c70cbSLiam Girdwood /** 3549414c70cbSLiam Girdwood * regulator_bulk_disable - disable multiple regulator consumers 3550414c70cbSLiam Girdwood * 3551414c70cbSLiam Girdwood * @num_consumers: Number of consumers 3552414c70cbSLiam Girdwood * @consumers: Consumer data; clients are stored here. 3553414c70cbSLiam Girdwood * @return 0 on success, an errno on failure 3554414c70cbSLiam Girdwood * 3555414c70cbSLiam Girdwood * This convenience API allows consumers to disable multiple regulator 355649e22632SSylwester Nawrocki * clients in a single API call. If any consumers cannot be disabled 355749e22632SSylwester Nawrocki * then any others that were disabled will be enabled again prior to 3558414c70cbSLiam Girdwood * return. 3559414c70cbSLiam Girdwood */ 3560414c70cbSLiam Girdwood int regulator_bulk_disable(int num_consumers, 3561414c70cbSLiam Girdwood struct regulator_bulk_data *consumers) 3562414c70cbSLiam Girdwood { 3563414c70cbSLiam Girdwood int i; 356401e86f49SMark Brown int ret, r; 3565414c70cbSLiam Girdwood 356649e22632SSylwester Nawrocki for (i = num_consumers - 1; i >= 0; --i) { 3567414c70cbSLiam Girdwood ret = regulator_disable(consumers[i].consumer); 3568414c70cbSLiam Girdwood if (ret != 0) 3569414c70cbSLiam Girdwood goto err; 3570414c70cbSLiam Girdwood } 3571414c70cbSLiam Girdwood 3572414c70cbSLiam Girdwood return 0; 3573414c70cbSLiam Girdwood 3574414c70cbSLiam Girdwood err: 35755da84fd9SJoe Perches pr_err("Failed to disable %s: %d\n", consumers[i].supply, ret); 357601e86f49SMark Brown for (++i; i < num_consumers; ++i) { 357701e86f49SMark Brown r = regulator_enable(consumers[i].consumer); 357801e86f49SMark Brown if (r != 0) 357901e86f49SMark Brown pr_err("Failed to reename %s: %d\n", 358001e86f49SMark Brown consumers[i].supply, r); 358101e86f49SMark Brown } 3582414c70cbSLiam Girdwood 3583414c70cbSLiam Girdwood return ret; 3584414c70cbSLiam Girdwood } 3585414c70cbSLiam Girdwood EXPORT_SYMBOL_GPL(regulator_bulk_disable); 3586414c70cbSLiam Girdwood 3587414c70cbSLiam Girdwood /** 3588e1de2f42SDonggeun Kim * regulator_bulk_force_disable - force disable multiple regulator consumers 3589e1de2f42SDonggeun Kim * 3590e1de2f42SDonggeun Kim * @num_consumers: Number of consumers 3591e1de2f42SDonggeun Kim * @consumers: Consumer data; clients are stored here. 3592e1de2f42SDonggeun Kim * @return 0 on success, an errno on failure 3593e1de2f42SDonggeun Kim * 3594e1de2f42SDonggeun Kim * This convenience API allows consumers to forcibly disable multiple regulator 3595e1de2f42SDonggeun Kim * clients in a single API call. 3596e1de2f42SDonggeun Kim * NOTE: This should be used for situations when device damage will 3597e1de2f42SDonggeun Kim * likely occur if the regulators are not disabled (e.g. over temp). 3598e1de2f42SDonggeun Kim * Although regulator_force_disable function call for some consumers can 3599e1de2f42SDonggeun Kim * return error numbers, the function is called for all consumers. 3600e1de2f42SDonggeun Kim */ 3601e1de2f42SDonggeun Kim int regulator_bulk_force_disable(int num_consumers, 3602e1de2f42SDonggeun Kim struct regulator_bulk_data *consumers) 3603e1de2f42SDonggeun Kim { 3604e1de2f42SDonggeun Kim int i; 3605e1de2f42SDonggeun Kim int ret; 3606e1de2f42SDonggeun Kim 3607e1de2f42SDonggeun Kim for (i = 0; i < num_consumers; i++) 3608e1de2f42SDonggeun Kim consumers[i].ret = 3609e1de2f42SDonggeun Kim regulator_force_disable(consumers[i].consumer); 3610e1de2f42SDonggeun Kim 3611e1de2f42SDonggeun Kim for (i = 0; i < num_consumers; i++) { 3612e1de2f42SDonggeun Kim if (consumers[i].ret != 0) { 3613e1de2f42SDonggeun Kim ret = consumers[i].ret; 3614e1de2f42SDonggeun Kim goto out; 3615e1de2f42SDonggeun Kim } 3616e1de2f42SDonggeun Kim } 3617e1de2f42SDonggeun Kim 3618e1de2f42SDonggeun Kim return 0; 3619e1de2f42SDonggeun Kim out: 3620e1de2f42SDonggeun Kim return ret; 3621e1de2f42SDonggeun Kim } 3622e1de2f42SDonggeun Kim EXPORT_SYMBOL_GPL(regulator_bulk_force_disable); 3623e1de2f42SDonggeun Kim 3624e1de2f42SDonggeun Kim /** 3625414c70cbSLiam Girdwood * regulator_bulk_free - free multiple regulator consumers 3626414c70cbSLiam Girdwood * 3627414c70cbSLiam Girdwood * @num_consumers: Number of consumers 3628414c70cbSLiam Girdwood * @consumers: Consumer data; clients are stored here. 3629414c70cbSLiam Girdwood * 3630414c70cbSLiam Girdwood * This convenience API allows consumers to free multiple regulator 3631414c70cbSLiam Girdwood * clients in a single API call. 3632414c70cbSLiam Girdwood */ 3633414c70cbSLiam Girdwood void regulator_bulk_free(int num_consumers, 3634414c70cbSLiam Girdwood struct regulator_bulk_data *consumers) 3635414c70cbSLiam Girdwood { 3636414c70cbSLiam Girdwood int i; 3637414c70cbSLiam Girdwood 3638414c70cbSLiam Girdwood for (i = 0; i < num_consumers; i++) { 3639414c70cbSLiam Girdwood regulator_put(consumers[i].consumer); 3640414c70cbSLiam Girdwood consumers[i].consumer = NULL; 3641414c70cbSLiam Girdwood } 3642414c70cbSLiam Girdwood } 3643414c70cbSLiam Girdwood EXPORT_SYMBOL_GPL(regulator_bulk_free); 3644414c70cbSLiam Girdwood 3645414c70cbSLiam Girdwood /** 3646414c70cbSLiam Girdwood * regulator_notifier_call_chain - call regulator event notifier 364769279fb9SMark Brown * @rdev: regulator source 3648414c70cbSLiam Girdwood * @event: notifier block 364969279fb9SMark Brown * @data: callback-specific data. 3650414c70cbSLiam Girdwood * 3651414c70cbSLiam Girdwood * Called by regulator drivers to notify clients a regulator event has 3652414c70cbSLiam Girdwood * occurred. We also notify regulator clients downstream. 3653b136fb44SJonathan Cameron * Note lock must be held by caller. 3654414c70cbSLiam Girdwood */ 3655414c70cbSLiam Girdwood int regulator_notifier_call_chain(struct regulator_dev *rdev, 3656414c70cbSLiam Girdwood unsigned long event, void *data) 3657414c70cbSLiam Girdwood { 365870cfef26SKrzysztof Kozlowski lockdep_assert_held_once(&rdev->mutex); 365970cfef26SKrzysztof Kozlowski 3660414c70cbSLiam Girdwood _notifier_call_chain(rdev, event, data); 3661414c70cbSLiam Girdwood return NOTIFY_DONE; 3662414c70cbSLiam Girdwood 3663414c70cbSLiam Girdwood } 3664414c70cbSLiam Girdwood EXPORT_SYMBOL_GPL(regulator_notifier_call_chain); 3665414c70cbSLiam Girdwood 3666be721979SMark Brown /** 3667be721979SMark Brown * regulator_mode_to_status - convert a regulator mode into a status 3668be721979SMark Brown * 3669be721979SMark Brown * @mode: Mode to convert 3670be721979SMark Brown * 3671be721979SMark Brown * Convert a regulator mode into a status. 3672be721979SMark Brown */ 3673be721979SMark Brown int regulator_mode_to_status(unsigned int mode) 3674be721979SMark Brown { 3675be721979SMark Brown switch (mode) { 3676be721979SMark Brown case REGULATOR_MODE_FAST: 3677be721979SMark Brown return REGULATOR_STATUS_FAST; 3678be721979SMark Brown case REGULATOR_MODE_NORMAL: 3679be721979SMark Brown return REGULATOR_STATUS_NORMAL; 3680be721979SMark Brown case REGULATOR_MODE_IDLE: 3681be721979SMark Brown return REGULATOR_STATUS_IDLE; 368203ffcf3dSKrystian Garbaciak case REGULATOR_MODE_STANDBY: 3683be721979SMark Brown return REGULATOR_STATUS_STANDBY; 3684be721979SMark Brown default: 36851beaf762SKrystian Garbaciak return REGULATOR_STATUS_UNDEFINED; 3686be721979SMark Brown } 3687be721979SMark Brown } 3688be721979SMark Brown EXPORT_SYMBOL_GPL(regulator_mode_to_status); 3689be721979SMark Brown 369039f802d6STakashi Iwai static struct attribute *regulator_dev_attrs[] = { 369139f802d6STakashi Iwai &dev_attr_name.attr, 369239f802d6STakashi Iwai &dev_attr_num_users.attr, 369339f802d6STakashi Iwai &dev_attr_type.attr, 369439f802d6STakashi Iwai &dev_attr_microvolts.attr, 369539f802d6STakashi Iwai &dev_attr_microamps.attr, 369639f802d6STakashi Iwai &dev_attr_opmode.attr, 369739f802d6STakashi Iwai &dev_attr_state.attr, 369839f802d6STakashi Iwai &dev_attr_status.attr, 369939f802d6STakashi Iwai &dev_attr_bypass.attr, 370039f802d6STakashi Iwai &dev_attr_requested_microamps.attr, 370139f802d6STakashi Iwai &dev_attr_min_microvolts.attr, 370239f802d6STakashi Iwai &dev_attr_max_microvolts.attr, 370339f802d6STakashi Iwai &dev_attr_min_microamps.attr, 370439f802d6STakashi Iwai &dev_attr_max_microamps.attr, 370539f802d6STakashi Iwai &dev_attr_suspend_standby_state.attr, 370639f802d6STakashi Iwai &dev_attr_suspend_mem_state.attr, 370739f802d6STakashi Iwai &dev_attr_suspend_disk_state.attr, 370839f802d6STakashi Iwai &dev_attr_suspend_standby_microvolts.attr, 370939f802d6STakashi Iwai &dev_attr_suspend_mem_microvolts.attr, 371039f802d6STakashi Iwai &dev_attr_suspend_disk_microvolts.attr, 371139f802d6STakashi Iwai &dev_attr_suspend_standby_mode.attr, 371239f802d6STakashi Iwai &dev_attr_suspend_mem_mode.attr, 371339f802d6STakashi Iwai &dev_attr_suspend_disk_mode.attr, 371439f802d6STakashi Iwai NULL 371539f802d6STakashi Iwai }; 371639f802d6STakashi Iwai 37177ad68e2fSDavid Brownell /* 37187ad68e2fSDavid Brownell * To avoid cluttering sysfs (and memory) with useless state, only 37197ad68e2fSDavid Brownell * create attributes that can be meaningfully displayed. 37207ad68e2fSDavid Brownell */ 372139f802d6STakashi Iwai static umode_t regulator_attr_is_visible(struct kobject *kobj, 372239f802d6STakashi Iwai struct attribute *attr, int idx) 37237ad68e2fSDavid Brownell { 372439f802d6STakashi Iwai struct device *dev = kobj_to_dev(kobj); 372583080a14SGeliang Tang struct regulator_dev *rdev = dev_to_rdev(dev); 3726272e2315SGuodong Xu const struct regulator_ops *ops = rdev->desc->ops; 372739f802d6STakashi Iwai umode_t mode = attr->mode; 372839f802d6STakashi Iwai 372939f802d6STakashi Iwai /* these three are always present */ 373039f802d6STakashi Iwai if (attr == &dev_attr_name.attr || 373139f802d6STakashi Iwai attr == &dev_attr_num_users.attr || 373239f802d6STakashi Iwai attr == &dev_attr_type.attr) 373339f802d6STakashi Iwai return mode; 37347ad68e2fSDavid Brownell 37357ad68e2fSDavid Brownell /* some attributes need specific methods to be displayed */ 373639f802d6STakashi Iwai if (attr == &dev_attr_microvolts.attr) { 37374c78899bSMark Brown if ((ops->get_voltage && ops->get_voltage(rdev) >= 0) || 3738f2889e65SMark Brown (ops->get_voltage_sel && ops->get_voltage_sel(rdev) >= 0) || 37395a523605SLaxman Dewangan (ops->list_voltage && ops->list_voltage(rdev, 0) >= 0) || 374039f802d6STakashi Iwai (rdev->desc->fixed_uV && rdev->desc->n_voltages == 1)) 374139f802d6STakashi Iwai return mode; 374239f802d6STakashi Iwai return 0; 3743f59c8f9fSMark Brown } 37447ad68e2fSDavid Brownell 374539f802d6STakashi Iwai if (attr == &dev_attr_microamps.attr) 374639f802d6STakashi Iwai return ops->get_current_limit ? mode : 0; 374739f802d6STakashi Iwai 374839f802d6STakashi Iwai if (attr == &dev_attr_opmode.attr) 374939f802d6STakashi Iwai return ops->get_mode ? mode : 0; 375039f802d6STakashi Iwai 375139f802d6STakashi Iwai if (attr == &dev_attr_state.attr) 375239f802d6STakashi Iwai return (rdev->ena_pin || ops->is_enabled) ? mode : 0; 375339f802d6STakashi Iwai 375439f802d6STakashi Iwai if (attr == &dev_attr_status.attr) 375539f802d6STakashi Iwai return ops->get_status ? mode : 0; 375639f802d6STakashi Iwai 375739f802d6STakashi Iwai if (attr == &dev_attr_bypass.attr) 375839f802d6STakashi Iwai return ops->get_bypass ? mode : 0; 375939f802d6STakashi Iwai 37607ad68e2fSDavid Brownell /* some attributes are type-specific */ 376139f802d6STakashi Iwai if (attr == &dev_attr_requested_microamps.attr) 376239f802d6STakashi Iwai return rdev->desc->type == REGULATOR_CURRENT ? mode : 0; 37637ad68e2fSDavid Brownell 37647ad68e2fSDavid Brownell /* constraints need specific supporting methods */ 376539f802d6STakashi Iwai if (attr == &dev_attr_min_microvolts.attr || 376639f802d6STakashi Iwai attr == &dev_attr_max_microvolts.attr) 376739f802d6STakashi Iwai return (ops->set_voltage || ops->set_voltage_sel) ? mode : 0; 376839f802d6STakashi Iwai 376939f802d6STakashi Iwai if (attr == &dev_attr_min_microamps.attr || 377039f802d6STakashi Iwai attr == &dev_attr_max_microamps.attr) 377139f802d6STakashi Iwai return ops->set_current_limit ? mode : 0; 377239f802d6STakashi Iwai 377339f802d6STakashi Iwai if (attr == &dev_attr_suspend_standby_state.attr || 377439f802d6STakashi Iwai attr == &dev_attr_suspend_mem_state.attr || 377539f802d6STakashi Iwai attr == &dev_attr_suspend_disk_state.attr) 377639f802d6STakashi Iwai return mode; 377739f802d6STakashi Iwai 377839f802d6STakashi Iwai if (attr == &dev_attr_suspend_standby_microvolts.attr || 377939f802d6STakashi Iwai attr == &dev_attr_suspend_mem_microvolts.attr || 378039f802d6STakashi Iwai attr == &dev_attr_suspend_disk_microvolts.attr) 378139f802d6STakashi Iwai return ops->set_suspend_voltage ? mode : 0; 378239f802d6STakashi Iwai 378339f802d6STakashi Iwai if (attr == &dev_attr_suspend_standby_mode.attr || 378439f802d6STakashi Iwai attr == &dev_attr_suspend_mem_mode.attr || 378539f802d6STakashi Iwai attr == &dev_attr_suspend_disk_mode.attr) 378639f802d6STakashi Iwai return ops->set_suspend_mode ? mode : 0; 378739f802d6STakashi Iwai 378839f802d6STakashi Iwai return mode; 37897ad68e2fSDavid Brownell } 37907ad68e2fSDavid Brownell 379139f802d6STakashi Iwai static const struct attribute_group regulator_dev_group = { 379239f802d6STakashi Iwai .attrs = regulator_dev_attrs, 379339f802d6STakashi Iwai .is_visible = regulator_attr_is_visible, 379439f802d6STakashi Iwai }; 37957ad68e2fSDavid Brownell 379639f802d6STakashi Iwai static const struct attribute_group *regulator_dev_groups[] = { 379739f802d6STakashi Iwai ®ulator_dev_group, 379839f802d6STakashi Iwai NULL 379939f802d6STakashi Iwai }; 380039f802d6STakashi Iwai 380139f802d6STakashi Iwai static void regulator_dev_release(struct device *dev) 380239f802d6STakashi Iwai { 380339f802d6STakashi Iwai struct regulator_dev *rdev = dev_get_drvdata(dev); 380429f5f486SMark Brown 380529f5f486SMark Brown kfree(rdev->constraints); 380629f5f486SMark Brown of_node_put(rdev->dev.of_node); 380739f802d6STakashi Iwai kfree(rdev); 38087ad68e2fSDavid Brownell } 38097ad68e2fSDavid Brownell 381039f802d6STakashi Iwai static struct class regulator_class = { 381139f802d6STakashi Iwai .name = "regulator", 381239f802d6STakashi Iwai .dev_release = regulator_dev_release, 381339f802d6STakashi Iwai .dev_groups = regulator_dev_groups, 381439f802d6STakashi Iwai }; 38157ad68e2fSDavid Brownell 38161130e5b3SMark Brown static void rdev_init_debugfs(struct regulator_dev *rdev) 38171130e5b3SMark Brown { 3818a9eaa813SGuenter Roeck struct device *parent = rdev->dev.parent; 3819a9eaa813SGuenter Roeck const char *rname = rdev_get_name(rdev); 3820a9eaa813SGuenter Roeck char name[NAME_MAX]; 3821a9eaa813SGuenter Roeck 3822a9eaa813SGuenter Roeck /* Avoid duplicate debugfs directory names */ 3823a9eaa813SGuenter Roeck if (parent && rname == rdev->desc->name) { 3824a9eaa813SGuenter Roeck snprintf(name, sizeof(name), "%s-%s", dev_name(parent), 3825a9eaa813SGuenter Roeck rname); 3826a9eaa813SGuenter Roeck rname = name; 3827a9eaa813SGuenter Roeck } 3828a9eaa813SGuenter Roeck 3829a9eaa813SGuenter Roeck rdev->debugfs = debugfs_create_dir(rname, debugfs_root); 383024751434SStephen Boyd if (!rdev->debugfs) { 38311130e5b3SMark Brown rdev_warn(rdev, "Failed to create debugfs directory\n"); 38321130e5b3SMark Brown return; 38331130e5b3SMark Brown } 38341130e5b3SMark Brown 38351130e5b3SMark Brown debugfs_create_u32("use_count", 0444, rdev->debugfs, 38361130e5b3SMark Brown &rdev->use_count); 38371130e5b3SMark Brown debugfs_create_u32("open_count", 0444, rdev->debugfs, 38381130e5b3SMark Brown &rdev->open_count); 3839f59c8f9fSMark Brown debugfs_create_u32("bypass_count", 0444, rdev->debugfs, 3840f59c8f9fSMark Brown &rdev->bypass_count); 38411130e5b3SMark Brown } 38421130e5b3SMark Brown 3843414c70cbSLiam Girdwood /** 3844414c70cbSLiam Girdwood * regulator_register - register regulator 384569279fb9SMark Brown * @regulator_desc: regulator to register 3846f47531b1SKrzysztof Kozlowski * @cfg: runtime configuration for regulator 3847414c70cbSLiam Girdwood * 3848414c70cbSLiam Girdwood * Called by regulator drivers to register a regulator. 38490384618aSAxel Lin * Returns a valid pointer to struct regulator_dev on success 38500384618aSAxel Lin * or an ERR_PTR() on error. 3851414c70cbSLiam Girdwood */ 385265f26846SMark Brown struct regulator_dev * 385365f26846SMark Brown regulator_register(const struct regulator_desc *regulator_desc, 38541b3de223SKrzysztof Kozlowski const struct regulator_config *cfg) 3855414c70cbSLiam Girdwood { 38569a8f5e07SMark Brown const struct regulation_constraints *constraints = NULL; 3857c172708dSMark Brown const struct regulator_init_data *init_data; 38581b3de223SKrzysztof Kozlowski struct regulator_config *config = NULL; 385972dca06fSAniroop Mathur static atomic_t regulator_no = ATOMIC_INIT(-1); 3860414c70cbSLiam Girdwood struct regulator_dev *rdev; 386132c8fad4SMark Brown struct device *dev; 3862a5766f11SLiam Girdwood int ret, i; 3863414c70cbSLiam Girdwood 38641b3de223SKrzysztof Kozlowski if (regulator_desc == NULL || cfg == NULL) 3865414c70cbSLiam Girdwood return ERR_PTR(-EINVAL); 3866414c70cbSLiam Girdwood 38671b3de223SKrzysztof Kozlowski dev = cfg->dev; 3868dcf70112SMark Brown WARN_ON(!dev); 386932c8fad4SMark Brown 3870414c70cbSLiam Girdwood if (regulator_desc->name == NULL || regulator_desc->ops == NULL) 3871414c70cbSLiam Girdwood return ERR_PTR(-EINVAL); 3872414c70cbSLiam Girdwood 3873cd78dfc6SDiego Liziero if (regulator_desc->type != REGULATOR_VOLTAGE && 3874cd78dfc6SDiego Liziero regulator_desc->type != REGULATOR_CURRENT) 3875414c70cbSLiam Girdwood return ERR_PTR(-EINVAL); 3876414c70cbSLiam Girdwood 3877476c2d83SMark Brown /* Only one of each should be implemented */ 3878476c2d83SMark Brown WARN_ON(regulator_desc->ops->get_voltage && 3879476c2d83SMark Brown regulator_desc->ops->get_voltage_sel); 3880e8eef82bSMark Brown WARN_ON(regulator_desc->ops->set_voltage && 3881e8eef82bSMark Brown regulator_desc->ops->set_voltage_sel); 3882476c2d83SMark Brown 3883476c2d83SMark Brown /* If we're using selectors we must implement list_voltage. */ 3884476c2d83SMark Brown if (regulator_desc->ops->get_voltage_sel && 3885476c2d83SMark Brown !regulator_desc->ops->list_voltage) { 3886476c2d83SMark Brown return ERR_PTR(-EINVAL); 3887476c2d83SMark Brown } 3888e8eef82bSMark Brown if (regulator_desc->ops->set_voltage_sel && 3889e8eef82bSMark Brown !regulator_desc->ops->list_voltage) { 3890e8eef82bSMark Brown return ERR_PTR(-EINVAL); 3891e8eef82bSMark Brown } 3892476c2d83SMark Brown 3893414c70cbSLiam Girdwood rdev = kzalloc(sizeof(struct regulator_dev), GFP_KERNEL); 3894414c70cbSLiam Girdwood if (rdev == NULL) 3895414c70cbSLiam Girdwood return ERR_PTR(-ENOMEM); 3896414c70cbSLiam Girdwood 38971b3de223SKrzysztof Kozlowski /* 38981b3de223SKrzysztof Kozlowski * Duplicate the config so the driver could override it after 38991b3de223SKrzysztof Kozlowski * parsing init data. 39001b3de223SKrzysztof Kozlowski */ 39011b3de223SKrzysztof Kozlowski config = kmemdup(cfg, sizeof(*cfg), GFP_KERNEL); 39021b3de223SKrzysztof Kozlowski if (config == NULL) { 39031b3de223SKrzysztof Kozlowski kfree(rdev); 39041b3de223SKrzysztof Kozlowski return ERR_PTR(-ENOMEM); 39051b3de223SKrzysztof Kozlowski } 39061b3de223SKrzysztof Kozlowski 3907bfa21a0dSKrzysztof Kozlowski init_data = regulator_of_get_init_data(dev, regulator_desc, config, 3908a0c7b164SMark Brown &rdev->dev.of_node); 3909a0c7b164SMark Brown if (!init_data) { 3910a0c7b164SMark Brown init_data = config->init_data; 3911a0c7b164SMark Brown rdev->dev.of_node = of_node_get(config->of_node); 3912a0c7b164SMark Brown } 3913a0c7b164SMark Brown 3914414c70cbSLiam Girdwood mutex_lock(®ulator_list_mutex); 3915414c70cbSLiam Girdwood 3916414c70cbSLiam Girdwood mutex_init(&rdev->mutex); 3917c172708dSMark Brown rdev->reg_data = config->driver_data; 3918414c70cbSLiam Girdwood rdev->owner = regulator_desc->owner; 3919414c70cbSLiam Girdwood rdev->desc = regulator_desc; 39203a4b0a07SMark Brown if (config->regmap) 392165b19ce6SMark Brown rdev->regmap = config->regmap; 392252b84dacSAnilKumar Ch else if (dev_get_regmap(dev, NULL)) 39233a4b0a07SMark Brown rdev->regmap = dev_get_regmap(dev, NULL); 392452b84dacSAnilKumar Ch else if (dev->parent) 392552b84dacSAnilKumar Ch rdev->regmap = dev_get_regmap(dev->parent, NULL); 3926414c70cbSLiam Girdwood INIT_LIST_HEAD(&rdev->consumer_list); 3927414c70cbSLiam Girdwood INIT_LIST_HEAD(&rdev->list); 3928414c70cbSLiam Girdwood BLOCKING_INIT_NOTIFIER_HEAD(&rdev->notifier); 3929da07ecd9SMark Brown INIT_DELAYED_WORK(&rdev->disable_work, regulator_disable_work); 3930414c70cbSLiam Girdwood 3931a5766f11SLiam Girdwood /* preform any regulator specific init */ 39329a8f5e07SMark Brown if (init_data && init_data->regulator_init) { 3933a5766f11SLiam Girdwood ret = init_data->regulator_init(rdev->reg_data); 39344fca9545SDavid Brownell if (ret < 0) 39354fca9545SDavid Brownell goto clean; 3936a5766f11SLiam Girdwood } 3937a5766f11SLiam Girdwood 3938daad134dSKrzysztof Adamski if ((config->ena_gpio || config->ena_gpio_initialized) && 3939daad134dSKrzysztof Adamski gpio_is_valid(config->ena_gpio)) { 3940daad134dSKrzysztof Adamski ret = regulator_ena_gpio_request(rdev, config); 3941daad134dSKrzysztof Adamski if (ret != 0) { 3942daad134dSKrzysztof Adamski rdev_err(rdev, "Failed to request enable GPIO%d: %d\n", 3943daad134dSKrzysztof Adamski config->ena_gpio, ret); 394432165230SKrzysztof Adamski goto clean; 3945daad134dSKrzysztof Adamski } 3946daad134dSKrzysztof Adamski } 3947daad134dSKrzysztof Adamski 3948a5766f11SLiam Girdwood /* register with sysfs */ 3949a5766f11SLiam Girdwood rdev->dev.class = ®ulator_class; 3950a5766f11SLiam Girdwood rdev->dev.parent = dev; 395172dca06fSAniroop Mathur dev_set_name(&rdev->dev, "regulator.%lu", 395239138818SAniroop Mathur (unsigned long) atomic_inc_return(®ulator_no)); 3953a5766f11SLiam Girdwood ret = device_register(&rdev->dev); 3954ad7725cbSVasiliy Kulikov if (ret != 0) { 3955ad7725cbSVasiliy Kulikov put_device(&rdev->dev); 395632165230SKrzysztof Adamski goto wash; 3957ad7725cbSVasiliy Kulikov } 3958a5766f11SLiam Girdwood 3959a5766f11SLiam Girdwood dev_set_drvdata(&rdev->dev, rdev); 3960a5766f11SLiam Girdwood 396174f544c1SMike Rapoport /* set regulator constraints */ 39629a8f5e07SMark Brown if (init_data) 39639a8f5e07SMark Brown constraints = &init_data->constraints; 39649a8f5e07SMark Brown 39659a8f5e07SMark Brown ret = set_machine_constraints(rdev, constraints); 396674f544c1SMike Rapoport if (ret < 0) 396774f544c1SMike Rapoport goto scrub; 396874f544c1SMike Rapoport 39699a8f5e07SMark Brown if (init_data && init_data->supply_regulator) 39706261b06dSBjorn Andersson rdev->supply_name = init_data->supply_regulator; 397169511a45SRajendra Nayak else if (regulator_desc->supply_name) 39726261b06dSBjorn Andersson rdev->supply_name = regulator_desc->supply_name; 397369511a45SRajendra Nayak 3974a5766f11SLiam Girdwood /* add consumers devices */ 39759a8f5e07SMark Brown if (init_data) { 3976a5766f11SLiam Girdwood for (i = 0; i < init_data->num_consumer_supplies; i++) { 3977a5766f11SLiam Girdwood ret = set_consumer_device_supply(rdev, 397840f9244fSMark Brown init_data->consumer_supplies[i].dev_name, 3979a5766f11SLiam Girdwood init_data->consumer_supplies[i].supply); 398023c2f041SMark Brown if (ret < 0) { 398123c2f041SMark Brown dev_err(dev, "Failed to set supply %s\n", 398223c2f041SMark Brown init_data->consumer_supplies[i].supply); 3983d4033b54SJani Nikula goto unset_supplies; 3984a5766f11SLiam Girdwood } 398523c2f041SMark Brown } 39869a8f5e07SMark Brown } 3987a5766f11SLiam Girdwood 39881130e5b3SMark Brown rdev_init_debugfs(rdev); 3989a5766f11SLiam Girdwood out: 3990414c70cbSLiam Girdwood mutex_unlock(®ulator_list_mutex); 39911b3de223SKrzysztof Kozlowski kfree(config); 3992414c70cbSLiam Girdwood return rdev; 39934fca9545SDavid Brownell 3994d4033b54SJani Nikula unset_supplies: 3995d4033b54SJani Nikula unset_regulator_supplies(rdev); 3996d4033b54SJani Nikula 39974fca9545SDavid Brownell scrub: 3998f19b00daSKim, Milo regulator_ena_gpio_free(rdev); 39994fca9545SDavid Brownell device_unregister(&rdev->dev); 400053032dafSPaul Walmsley /* device core frees rdev */ 400153032dafSPaul Walmsley rdev = ERR_PTR(ret); 400253032dafSPaul Walmsley goto out; 400353032dafSPaul Walmsley 400432165230SKrzysztof Adamski wash: 400532165230SKrzysztof Adamski regulator_ena_gpio_free(rdev); 40064fca9545SDavid Brownell clean: 40074fca9545SDavid Brownell kfree(rdev); 40084fca9545SDavid Brownell rdev = ERR_PTR(ret); 40094fca9545SDavid Brownell goto out; 4010414c70cbSLiam Girdwood } 4011414c70cbSLiam Girdwood EXPORT_SYMBOL_GPL(regulator_register); 4012414c70cbSLiam Girdwood 4013414c70cbSLiam Girdwood /** 4014414c70cbSLiam Girdwood * regulator_unregister - unregister regulator 401569279fb9SMark Brown * @rdev: regulator to unregister 4016414c70cbSLiam Girdwood * 4017414c70cbSLiam Girdwood * Called by regulator drivers to unregister a regulator. 4018414c70cbSLiam Girdwood */ 4019414c70cbSLiam Girdwood void regulator_unregister(struct regulator_dev *rdev) 4020414c70cbSLiam Girdwood { 4021414c70cbSLiam Girdwood if (rdev == NULL) 4022414c70cbSLiam Girdwood return; 4023414c70cbSLiam Girdwood 4024891636eaSMark Brown if (rdev->supply) { 4025891636eaSMark Brown while (rdev->use_count--) 4026891636eaSMark Brown regulator_disable(rdev->supply); 4027e032b376SMark Brown regulator_put(rdev->supply); 4028891636eaSMark Brown } 4029414c70cbSLiam Girdwood mutex_lock(®ulator_list_mutex); 40301130e5b3SMark Brown debugfs_remove_recursive(rdev->debugfs); 403143829731STejun Heo flush_work(&rdev->disable_work.work); 40326bf87d17SMark Brown WARN_ON(rdev->open_count); 40330f1d747bSMike Rapoport unset_regulator_supplies(rdev); 4034414c70cbSLiam Girdwood list_del(&rdev->list); 40357cd71c3bSMark Brown mutex_unlock(®ulator_list_mutex); 4036f19b00daSKim, Milo regulator_ena_gpio_free(rdev); 403758fb5cf5SLothar Waßmann device_unregister(&rdev->dev); 4038414c70cbSLiam Girdwood } 4039414c70cbSLiam Girdwood EXPORT_SYMBOL_GPL(regulator_unregister); 4040414c70cbSLiam Girdwood 404185f3b431STomeu Vizoso static int _regulator_suspend_prepare(struct device *dev, void *data) 404285f3b431STomeu Vizoso { 404385f3b431STomeu Vizoso struct regulator_dev *rdev = dev_to_rdev(dev); 404485f3b431STomeu Vizoso const suspend_state_t *state = data; 404585f3b431STomeu Vizoso int ret; 404685f3b431STomeu Vizoso 404785f3b431STomeu Vizoso mutex_lock(&rdev->mutex); 404885f3b431STomeu Vizoso ret = suspend_prepare(rdev, *state); 404985f3b431STomeu Vizoso mutex_unlock(&rdev->mutex); 405085f3b431STomeu Vizoso 405185f3b431STomeu Vizoso return ret; 405285f3b431STomeu Vizoso } 405385f3b431STomeu Vizoso 4054414c70cbSLiam Girdwood /** 4055cf7bbcdfSMark Brown * regulator_suspend_prepare - prepare regulators for system wide suspend 4056414c70cbSLiam Girdwood * @state: system suspend state 4057414c70cbSLiam Girdwood * 4058414c70cbSLiam Girdwood * Configure each regulator with it's suspend operating parameters for state. 4059414c70cbSLiam Girdwood * This will usually be called by machine suspend code prior to supending. 4060414c70cbSLiam Girdwood */ 4061414c70cbSLiam Girdwood int regulator_suspend_prepare(suspend_state_t state) 4062414c70cbSLiam Girdwood { 4063414c70cbSLiam Girdwood /* ON is handled by regulator active state */ 4064414c70cbSLiam Girdwood if (state == PM_SUSPEND_ON) 4065414c70cbSLiam Girdwood return -EINVAL; 4066414c70cbSLiam Girdwood 406785f3b431STomeu Vizoso return class_for_each_device(®ulator_class, NULL, &state, 406885f3b431STomeu Vizoso _regulator_suspend_prepare); 4069414c70cbSLiam Girdwood } 4070414c70cbSLiam Girdwood EXPORT_SYMBOL_GPL(regulator_suspend_prepare); 4071414c70cbSLiam Girdwood 407285f3b431STomeu Vizoso static int _regulator_suspend_finish(struct device *dev, void *data) 407385f3b431STomeu Vizoso { 407485f3b431STomeu Vizoso struct regulator_dev *rdev = dev_to_rdev(dev); 407585f3b431STomeu Vizoso int ret; 407685f3b431STomeu Vizoso 407785f3b431STomeu Vizoso mutex_lock(&rdev->mutex); 407885f3b431STomeu Vizoso if (rdev->use_count > 0 || rdev->constraints->always_on) { 407985f3b431STomeu Vizoso if (!_regulator_is_enabled(rdev)) { 408085f3b431STomeu Vizoso ret = _regulator_do_enable(rdev); 408185f3b431STomeu Vizoso if (ret) 408285f3b431STomeu Vizoso dev_err(dev, 408385f3b431STomeu Vizoso "Failed to resume regulator %d\n", 408485f3b431STomeu Vizoso ret); 408585f3b431STomeu Vizoso } 408685f3b431STomeu Vizoso } else { 408785f3b431STomeu Vizoso if (!have_full_constraints()) 408885f3b431STomeu Vizoso goto unlock; 408985f3b431STomeu Vizoso if (!_regulator_is_enabled(rdev)) 409085f3b431STomeu Vizoso goto unlock; 409185f3b431STomeu Vizoso 409285f3b431STomeu Vizoso ret = _regulator_do_disable(rdev); 409385f3b431STomeu Vizoso if (ret) 409485f3b431STomeu Vizoso dev_err(dev, "Failed to suspend regulator %d\n", ret); 409585f3b431STomeu Vizoso } 409685f3b431STomeu Vizoso unlock: 409785f3b431STomeu Vizoso mutex_unlock(&rdev->mutex); 409885f3b431STomeu Vizoso 409985f3b431STomeu Vizoso /* Keep processing regulators in spite of any errors */ 410085f3b431STomeu Vizoso return 0; 410185f3b431STomeu Vizoso } 410285f3b431STomeu Vizoso 4103414c70cbSLiam Girdwood /** 41047a32b589SMyungJoo Ham * regulator_suspend_finish - resume regulators from system wide suspend 41057a32b589SMyungJoo Ham * 41067a32b589SMyungJoo Ham * Turn on regulators that might be turned off by regulator_suspend_prepare 41077a32b589SMyungJoo Ham * and that should be turned on according to the regulators properties. 41087a32b589SMyungJoo Ham */ 41097a32b589SMyungJoo Ham int regulator_suspend_finish(void) 41107a32b589SMyungJoo Ham { 411185f3b431STomeu Vizoso return class_for_each_device(®ulator_class, NULL, NULL, 411285f3b431STomeu Vizoso _regulator_suspend_finish); 41137a32b589SMyungJoo Ham } 41147a32b589SMyungJoo Ham EXPORT_SYMBOL_GPL(regulator_suspend_finish); 41157a32b589SMyungJoo Ham 41167a32b589SMyungJoo Ham /** 4117ca725561SMark Brown * regulator_has_full_constraints - the system has fully specified constraints 4118ca725561SMark Brown * 4119ca725561SMark Brown * Calling this function will cause the regulator API to disable all 4120ca725561SMark Brown * regulators which have a zero use count and don't have an always_on 4121ca725561SMark Brown * constraint in a late_initcall. 4122ca725561SMark Brown * 4123ca725561SMark Brown * The intention is that this will become the default behaviour in a 4124ca725561SMark Brown * future kernel release so users are encouraged to use this facility 4125ca725561SMark Brown * now. 4126ca725561SMark Brown */ 4127ca725561SMark Brown void regulator_has_full_constraints(void) 4128ca725561SMark Brown { 4129ca725561SMark Brown has_full_constraints = 1; 4130ca725561SMark Brown } 4131ca725561SMark Brown EXPORT_SYMBOL_GPL(regulator_has_full_constraints); 4132ca725561SMark Brown 4133ca725561SMark Brown /** 4134414c70cbSLiam Girdwood * rdev_get_drvdata - get rdev regulator driver data 413569279fb9SMark Brown * @rdev: regulator 4136414c70cbSLiam Girdwood * 4137414c70cbSLiam Girdwood * Get rdev regulator driver private data. This call can be used in the 4138414c70cbSLiam Girdwood * regulator driver context. 4139414c70cbSLiam Girdwood */ 4140414c70cbSLiam Girdwood void *rdev_get_drvdata(struct regulator_dev *rdev) 4141414c70cbSLiam Girdwood { 4142414c70cbSLiam Girdwood return rdev->reg_data; 4143414c70cbSLiam Girdwood } 4144414c70cbSLiam Girdwood EXPORT_SYMBOL_GPL(rdev_get_drvdata); 4145414c70cbSLiam Girdwood 4146414c70cbSLiam Girdwood /** 4147414c70cbSLiam Girdwood * regulator_get_drvdata - get regulator driver data 4148414c70cbSLiam Girdwood * @regulator: regulator 4149414c70cbSLiam Girdwood * 4150414c70cbSLiam Girdwood * Get regulator driver private data. This call can be used in the consumer 4151414c70cbSLiam Girdwood * driver context when non API regulator specific functions need to be called. 4152414c70cbSLiam Girdwood */ 4153414c70cbSLiam Girdwood void *regulator_get_drvdata(struct regulator *regulator) 4154414c70cbSLiam Girdwood { 4155414c70cbSLiam Girdwood return regulator->rdev->reg_data; 4156414c70cbSLiam Girdwood } 4157414c70cbSLiam Girdwood EXPORT_SYMBOL_GPL(regulator_get_drvdata); 4158414c70cbSLiam Girdwood 4159414c70cbSLiam Girdwood /** 4160414c70cbSLiam Girdwood * regulator_set_drvdata - set regulator driver data 4161414c70cbSLiam Girdwood * @regulator: regulator 4162414c70cbSLiam Girdwood * @data: data 4163414c70cbSLiam Girdwood */ 4164414c70cbSLiam Girdwood void regulator_set_drvdata(struct regulator *regulator, void *data) 4165414c70cbSLiam Girdwood { 4166414c70cbSLiam Girdwood regulator->rdev->reg_data = data; 4167414c70cbSLiam Girdwood } 4168414c70cbSLiam Girdwood EXPORT_SYMBOL_GPL(regulator_set_drvdata); 4169414c70cbSLiam Girdwood 4170414c70cbSLiam Girdwood /** 4171414c70cbSLiam Girdwood * regulator_get_id - get regulator ID 417269279fb9SMark Brown * @rdev: regulator 4173414c70cbSLiam Girdwood */ 4174414c70cbSLiam Girdwood int rdev_get_id(struct regulator_dev *rdev) 4175414c70cbSLiam Girdwood { 4176414c70cbSLiam Girdwood return rdev->desc->id; 4177414c70cbSLiam Girdwood } 4178414c70cbSLiam Girdwood EXPORT_SYMBOL_GPL(rdev_get_id); 4179414c70cbSLiam Girdwood 4180a5766f11SLiam Girdwood struct device *rdev_get_dev(struct regulator_dev *rdev) 4181a5766f11SLiam Girdwood { 4182a5766f11SLiam Girdwood return &rdev->dev; 4183a5766f11SLiam Girdwood } 4184a5766f11SLiam Girdwood EXPORT_SYMBOL_GPL(rdev_get_dev); 4185a5766f11SLiam Girdwood 4186a5766f11SLiam Girdwood void *regulator_get_init_drvdata(struct regulator_init_data *reg_init_data) 4187a5766f11SLiam Girdwood { 4188a5766f11SLiam Girdwood return reg_init_data->driver_data; 4189a5766f11SLiam Girdwood } 4190a5766f11SLiam Girdwood EXPORT_SYMBOL_GPL(regulator_get_init_drvdata); 4191a5766f11SLiam Girdwood 4192ba55a974SMark Brown #ifdef CONFIG_DEBUG_FS 4193ba55a974SMark Brown static ssize_t supply_map_read_file(struct file *file, char __user *user_buf, 4194ba55a974SMark Brown size_t count, loff_t *ppos) 4195ba55a974SMark Brown { 4196ba55a974SMark Brown char *buf = kmalloc(PAGE_SIZE, GFP_KERNEL); 4197ba55a974SMark Brown ssize_t len, ret = 0; 4198ba55a974SMark Brown struct regulator_map *map; 4199ba55a974SMark Brown 4200ba55a974SMark Brown if (!buf) 4201ba55a974SMark Brown return -ENOMEM; 4202ba55a974SMark Brown 4203ba55a974SMark Brown list_for_each_entry(map, ®ulator_map_list, list) { 4204ba55a974SMark Brown len = snprintf(buf + ret, PAGE_SIZE - ret, 4205ba55a974SMark Brown "%s -> %s.%s\n", 4206ba55a974SMark Brown rdev_get_name(map->regulator), map->dev_name, 4207ba55a974SMark Brown map->supply); 4208ba55a974SMark Brown if (len >= 0) 4209ba55a974SMark Brown ret += len; 4210ba55a974SMark Brown if (ret > PAGE_SIZE) { 4211ba55a974SMark Brown ret = PAGE_SIZE; 4212ba55a974SMark Brown break; 4213ba55a974SMark Brown } 4214ba55a974SMark Brown } 4215ba55a974SMark Brown 4216ba55a974SMark Brown ret = simple_read_from_buffer(user_buf, count, ppos, buf, ret); 4217ba55a974SMark Brown 4218ba55a974SMark Brown kfree(buf); 4219ba55a974SMark Brown 4220ba55a974SMark Brown return ret; 4221ba55a974SMark Brown } 422224751434SStephen Boyd #endif 4223ba55a974SMark Brown 4224ba55a974SMark Brown static const struct file_operations supply_map_fops = { 422524751434SStephen Boyd #ifdef CONFIG_DEBUG_FS 4226ba55a974SMark Brown .read = supply_map_read_file, 4227ba55a974SMark Brown .llseek = default_llseek, 4228ba55a974SMark Brown #endif 422924751434SStephen Boyd }; 4230ba55a974SMark Brown 42317c225ec9SHeiko Stübner #ifdef CONFIG_DEBUG_FS 423285f3b431STomeu Vizoso struct summary_data { 423385f3b431STomeu Vizoso struct seq_file *s; 423485f3b431STomeu Vizoso struct regulator_dev *parent; 423585f3b431STomeu Vizoso int level; 423685f3b431STomeu Vizoso }; 423785f3b431STomeu Vizoso 423885f3b431STomeu Vizoso static void regulator_summary_show_subtree(struct seq_file *s, 423985f3b431STomeu Vizoso struct regulator_dev *rdev, 424085f3b431STomeu Vizoso int level); 424185f3b431STomeu Vizoso 424285f3b431STomeu Vizoso static int regulator_summary_show_children(struct device *dev, void *data) 424385f3b431STomeu Vizoso { 424485f3b431STomeu Vizoso struct regulator_dev *rdev = dev_to_rdev(dev); 424585f3b431STomeu Vizoso struct summary_data *summary_data = data; 424685f3b431STomeu Vizoso 424785f3b431STomeu Vizoso if (rdev->supply && rdev->supply->rdev == summary_data->parent) 424885f3b431STomeu Vizoso regulator_summary_show_subtree(summary_data->s, rdev, 424985f3b431STomeu Vizoso summary_data->level + 1); 425085f3b431STomeu Vizoso 425185f3b431STomeu Vizoso return 0; 425285f3b431STomeu Vizoso } 425385f3b431STomeu Vizoso 42547c225ec9SHeiko Stübner static void regulator_summary_show_subtree(struct seq_file *s, 42557c225ec9SHeiko Stübner struct regulator_dev *rdev, 42567c225ec9SHeiko Stübner int level) 42577c225ec9SHeiko Stübner { 42587c225ec9SHeiko Stübner struct regulation_constraints *c; 42597c225ec9SHeiko Stübner struct regulator *consumer; 426085f3b431STomeu Vizoso struct summary_data summary_data; 42617c225ec9SHeiko Stübner 42627c225ec9SHeiko Stübner if (!rdev) 42637c225ec9SHeiko Stübner return; 42647c225ec9SHeiko Stübner 42657c225ec9SHeiko Stübner seq_printf(s, "%*s%-*s %3d %4d %6d ", 42667c225ec9SHeiko Stübner level * 3 + 1, "", 42677c225ec9SHeiko Stübner 30 - level * 3, rdev_get_name(rdev), 42687c225ec9SHeiko Stübner rdev->use_count, rdev->open_count, rdev->bypass_count); 42697c225ec9SHeiko Stübner 427023296099SHeiko Stübner seq_printf(s, "%5dmV ", _regulator_get_voltage(rdev) / 1000); 427123296099SHeiko Stübner seq_printf(s, "%5dmA ", _regulator_get_current_limit(rdev) / 1000); 42727c225ec9SHeiko Stübner 42737c225ec9SHeiko Stübner c = rdev->constraints; 42747c225ec9SHeiko Stübner if (c) { 42757c225ec9SHeiko Stübner switch (rdev->desc->type) { 42767c225ec9SHeiko Stübner case REGULATOR_VOLTAGE: 42777c225ec9SHeiko Stübner seq_printf(s, "%5dmV %5dmV ", 42787c225ec9SHeiko Stübner c->min_uV / 1000, c->max_uV / 1000); 42797c225ec9SHeiko Stübner break; 42807c225ec9SHeiko Stübner case REGULATOR_CURRENT: 42817c225ec9SHeiko Stübner seq_printf(s, "%5dmA %5dmA ", 42827c225ec9SHeiko Stübner c->min_uA / 1000, c->max_uA / 1000); 42837c225ec9SHeiko Stübner break; 42847c225ec9SHeiko Stübner } 42857c225ec9SHeiko Stübner } 42867c225ec9SHeiko Stübner 42877c225ec9SHeiko Stübner seq_puts(s, "\n"); 42887c225ec9SHeiko Stübner 42897c225ec9SHeiko Stübner list_for_each_entry(consumer, &rdev->consumer_list, list) { 42907c225ec9SHeiko Stübner if (consumer->dev->class == ®ulator_class) 42917c225ec9SHeiko Stübner continue; 42927c225ec9SHeiko Stübner 42937c225ec9SHeiko Stübner seq_printf(s, "%*s%-*s ", 42947c225ec9SHeiko Stübner (level + 1) * 3 + 1, "", 42957c225ec9SHeiko Stübner 30 - (level + 1) * 3, dev_name(consumer->dev)); 42967c225ec9SHeiko Stübner 42977c225ec9SHeiko Stübner switch (rdev->desc->type) { 42987c225ec9SHeiko Stübner case REGULATOR_VOLTAGE: 429923296099SHeiko Stübner seq_printf(s, "%37dmV %5dmV", 43007c225ec9SHeiko Stübner consumer->min_uV / 1000, 43017c225ec9SHeiko Stübner consumer->max_uV / 1000); 43027c225ec9SHeiko Stübner break; 43037c225ec9SHeiko Stübner case REGULATOR_CURRENT: 43047c225ec9SHeiko Stübner break; 43057c225ec9SHeiko Stübner } 43067c225ec9SHeiko Stübner 43077c225ec9SHeiko Stübner seq_puts(s, "\n"); 43087c225ec9SHeiko Stübner } 43097c225ec9SHeiko Stübner 431085f3b431STomeu Vizoso summary_data.s = s; 431185f3b431STomeu Vizoso summary_data.level = level; 431285f3b431STomeu Vizoso summary_data.parent = rdev; 43137c225ec9SHeiko Stübner 431485f3b431STomeu Vizoso class_for_each_device(®ulator_class, NULL, &summary_data, 431585f3b431STomeu Vizoso regulator_summary_show_children); 43167c225ec9SHeiko Stübner } 431785f3b431STomeu Vizoso 431885f3b431STomeu Vizoso static int regulator_summary_show_roots(struct device *dev, void *data) 431985f3b431STomeu Vizoso { 432085f3b431STomeu Vizoso struct regulator_dev *rdev = dev_to_rdev(dev); 432185f3b431STomeu Vizoso struct seq_file *s = data; 432285f3b431STomeu Vizoso 432385f3b431STomeu Vizoso if (!rdev->supply) 432485f3b431STomeu Vizoso regulator_summary_show_subtree(s, rdev, 0); 432585f3b431STomeu Vizoso 432685f3b431STomeu Vizoso return 0; 43277c225ec9SHeiko Stübner } 43287c225ec9SHeiko Stübner 43297c225ec9SHeiko Stübner static int regulator_summary_show(struct seq_file *s, void *data) 43307c225ec9SHeiko Stübner { 433123296099SHeiko Stübner seq_puts(s, " regulator use open bypass voltage current min max\n"); 433223296099SHeiko Stübner seq_puts(s, "-------------------------------------------------------------------------------\n"); 43337c225ec9SHeiko Stübner 433485f3b431STomeu Vizoso class_for_each_device(®ulator_class, NULL, s, 433585f3b431STomeu Vizoso regulator_summary_show_roots); 43367c225ec9SHeiko Stübner 43377c225ec9SHeiko Stübner return 0; 43387c225ec9SHeiko Stübner } 43397c225ec9SHeiko Stübner 43407c225ec9SHeiko Stübner static int regulator_summary_open(struct inode *inode, struct file *file) 43417c225ec9SHeiko Stübner { 43427c225ec9SHeiko Stübner return single_open(file, regulator_summary_show, inode->i_private); 43437c225ec9SHeiko Stübner } 43447c225ec9SHeiko Stübner #endif 43457c225ec9SHeiko Stübner 43467c225ec9SHeiko Stübner static const struct file_operations regulator_summary_fops = { 43477c225ec9SHeiko Stübner #ifdef CONFIG_DEBUG_FS 43487c225ec9SHeiko Stübner .open = regulator_summary_open, 43497c225ec9SHeiko Stübner .read = seq_read, 43507c225ec9SHeiko Stübner .llseek = seq_lseek, 43517c225ec9SHeiko Stübner .release = single_release, 43527c225ec9SHeiko Stübner #endif 43537c225ec9SHeiko Stübner }; 43547c225ec9SHeiko Stübner 4355414c70cbSLiam Girdwood static int __init regulator_init(void) 4356414c70cbSLiam Girdwood { 435734abbd68SMark Brown int ret; 435834abbd68SMark Brown 435934abbd68SMark Brown ret = class_register(®ulator_class); 436034abbd68SMark Brown 43611130e5b3SMark Brown debugfs_root = debugfs_create_dir("regulator", NULL); 436224751434SStephen Boyd if (!debugfs_root) 43631130e5b3SMark Brown pr_warn("regulator: Failed to create debugfs directory\n"); 4364ba55a974SMark Brown 4365f4d562c6SMark Brown debugfs_create_file("supply_map", 0444, debugfs_root, NULL, 4366f4d562c6SMark Brown &supply_map_fops); 43671130e5b3SMark Brown 43687c225ec9SHeiko Stübner debugfs_create_file("regulator_summary", 0444, debugfs_root, 436985f3b431STomeu Vizoso NULL, ®ulator_summary_fops); 43707c225ec9SHeiko Stübner 437134abbd68SMark Brown regulator_dummy_init(); 437234abbd68SMark Brown 437334abbd68SMark Brown return ret; 4374414c70cbSLiam Girdwood } 4375414c70cbSLiam Girdwood 4376414c70cbSLiam Girdwood /* init early to allow our consumers to complete system booting */ 4377414c70cbSLiam Girdwood core_initcall(regulator_init); 4378ca725561SMark Brown 4379609ca5f3SMark Brown static int __init regulator_late_cleanup(struct device *dev, void *data) 4380ca725561SMark Brown { 4381609ca5f3SMark Brown struct regulator_dev *rdev = dev_to_rdev(dev); 4382609ca5f3SMark Brown const struct regulator_ops *ops = rdev->desc->ops; 4383609ca5f3SMark Brown struct regulation_constraints *c = rdev->constraints; 4384ca725561SMark Brown int enabled, ret; 4385ca725561SMark Brown 438666fda75fSMarkus Pargmann if (c && c->always_on) 4387609ca5f3SMark Brown return 0; 4388ca725561SMark Brown 4389e9535834SMark Brown if (c && !(c->valid_ops_mask & REGULATOR_CHANGE_STATUS)) 4390609ca5f3SMark Brown return 0; 4391e9535834SMark Brown 4392ca725561SMark Brown mutex_lock(&rdev->mutex); 4393ca725561SMark Brown 4394ca725561SMark Brown if (rdev->use_count) 4395ca725561SMark Brown goto unlock; 4396ca725561SMark Brown 4397ca725561SMark Brown /* If we can't read the status assume it's on. */ 4398ca725561SMark Brown if (ops->is_enabled) 4399ca725561SMark Brown enabled = ops->is_enabled(rdev); 4400ca725561SMark Brown else 4401ca725561SMark Brown enabled = 1; 4402ca725561SMark Brown 4403ca725561SMark Brown if (!enabled) 4404ca725561SMark Brown goto unlock; 4405ca725561SMark Brown 440687b28417SMark Brown if (have_full_constraints()) { 4407609ca5f3SMark Brown /* We log since this may kill the system if it goes 4408609ca5f3SMark Brown * wrong. */ 44095da84fd9SJoe Perches rdev_info(rdev, "disabling\n"); 441066fda75fSMarkus Pargmann ret = _regulator_do_disable(rdev); 44110d25d09dSJingoo Han if (ret != 0) 44125da84fd9SJoe Perches rdev_err(rdev, "couldn't disable: %d\n", ret); 4413ca725561SMark Brown } else { 4414ca725561SMark Brown /* The intention is that in future we will 4415ca725561SMark Brown * assume that full constraints are provided 4416ca725561SMark Brown * so warn even if we aren't going to do 4417ca725561SMark Brown * anything here. 4418ca725561SMark Brown */ 44195da84fd9SJoe Perches rdev_warn(rdev, "incomplete constraints, leaving on\n"); 4420ca725561SMark Brown } 4421ca725561SMark Brown 4422ca725561SMark Brown unlock: 4423ca725561SMark Brown mutex_unlock(&rdev->mutex); 4424609ca5f3SMark Brown 4425609ca5f3SMark Brown return 0; 4426ca725561SMark Brown } 4427ca725561SMark Brown 4428609ca5f3SMark Brown static int __init regulator_init_complete(void) 4429609ca5f3SMark Brown { 4430609ca5f3SMark Brown /* 4431609ca5f3SMark Brown * Since DT doesn't provide an idiomatic mechanism for 4432609ca5f3SMark Brown * enabling full constraints and since it's much more natural 4433609ca5f3SMark Brown * with DT to provide them just assume that a DT enabled 4434609ca5f3SMark Brown * system has full constraints. 4435609ca5f3SMark Brown */ 4436609ca5f3SMark Brown if (of_have_populated_dt()) 4437609ca5f3SMark Brown has_full_constraints = true; 4438609ca5f3SMark Brown 4439609ca5f3SMark Brown /* If we have a full configuration then disable any regulators 4440609ca5f3SMark Brown * we have permission to change the status for and which are 4441609ca5f3SMark Brown * not in use or always_on. This is effectively the default 4442609ca5f3SMark Brown * for DT and ACPI as they have full constraints. 4443609ca5f3SMark Brown */ 4444609ca5f3SMark Brown class_for_each_device(®ulator_class, NULL, NULL, 4445609ca5f3SMark Brown regulator_late_cleanup); 4446ca725561SMark Brown 4447ca725561SMark Brown return 0; 4448ca725561SMark Brown } 4449fd482a3eSSaravana Kannan late_initcall_sync(regulator_init_complete); 4450