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) 10603e2b9abdSMark Brown goto out; 10613e2b9abdSMark Brown 1062f8c1700dSLaxman Dewangan ret = machine_constraints_current(rdev, rdev->constraints); 1063f8c1700dSLaxman Dewangan if (ret != 0) 1064f8c1700dSLaxman Dewangan goto out; 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"); 107136e4f839SStephen Boyd goto out; 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"); 1080e06f5b4fSMark Brown goto out; 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"); 1087a308466cSMark Brown ret = -EINVAL; 1088a308466cSMark Brown goto out; 1089a308466cSMark Brown } 1090a308466cSMark Brown 1091f8c12fe3SMark Brown ret = ops->set_mode(rdev, rdev->constraints->initial_mode); 1092a308466cSMark Brown if (ret < 0) { 10935da84fd9SJoe Perches rdev_err(rdev, "failed to set initial mode: %d\n", ret); 1094a308466cSMark Brown goto out; 1095a308466cSMark Brown } 1096a308466cSMark Brown } 1097a308466cSMark Brown 1098cacf90f2SMark Brown /* If the constraints say the regulator should be on at this point 1099cacf90f2SMark Brown * and we have control then make sure it is enabled. 1100cacf90f2SMark Brown */ 110130c21971SMarkus Pargmann if (rdev->constraints->always_on || rdev->constraints->boot_on) { 110230c21971SMarkus Pargmann ret = _regulator_do_enable(rdev); 110330c21971SMarkus Pargmann if (ret < 0 && ret != -EINVAL) { 11045da84fd9SJoe Perches rdev_err(rdev, "failed to enable\n"); 1105e5fda26cSMark Brown goto out; 1106e5fda26cSMark Brown } 1107e5fda26cSMark Brown } 1108e5fda26cSMark Brown 11091653ccf4SYadwinder Singh Brar if ((rdev->constraints->ramp_delay || rdev->constraints->ramp_disable) 11101653ccf4SYadwinder Singh Brar && ops->set_ramp_delay) { 11116f0b2c69SYadwinder Singh Brar ret = ops->set_ramp_delay(rdev, rdev->constraints->ramp_delay); 11126f0b2c69SYadwinder Singh Brar if (ret < 0) { 11136f0b2c69SYadwinder Singh Brar rdev_err(rdev, "failed to set ramp_delay\n"); 11146f0b2c69SYadwinder Singh Brar goto out; 11156f0b2c69SYadwinder Singh Brar } 11166f0b2c69SYadwinder Singh Brar } 11176f0b2c69SYadwinder Singh Brar 111823c779b9SStephen Boyd if (rdev->constraints->pull_down && ops->set_pull_down) { 111923c779b9SStephen Boyd ret = ops->set_pull_down(rdev); 112023c779b9SStephen Boyd if (ret < 0) { 112123c779b9SStephen Boyd rdev_err(rdev, "failed to set pull down\n"); 112223c779b9SStephen Boyd goto out; 112323c779b9SStephen Boyd } 112423c779b9SStephen Boyd } 112523c779b9SStephen Boyd 112657f66b78SStephen Boyd if (rdev->constraints->soft_start && ops->set_soft_start) { 112757f66b78SStephen Boyd ret = ops->set_soft_start(rdev); 112857f66b78SStephen Boyd if (ret < 0) { 112957f66b78SStephen Boyd rdev_err(rdev, "failed to set soft start\n"); 113057f66b78SStephen Boyd goto out; 113157f66b78SStephen Boyd } 113257f66b78SStephen Boyd } 113357f66b78SStephen Boyd 11343a003baeSStephen Boyd if (rdev->constraints->over_current_protection 11353a003baeSStephen Boyd && ops->set_over_current_protection) { 11363a003baeSStephen Boyd ret = ops->set_over_current_protection(rdev); 11373a003baeSStephen Boyd if (ret < 0) { 11383a003baeSStephen Boyd rdev_err(rdev, "failed to set over current protection\n"); 11393a003baeSStephen Boyd goto out; 11403a003baeSStephen Boyd } 11413a003baeSStephen Boyd } 11423a003baeSStephen Boyd 1143670666b9SLaxman Dewangan if (rdev->constraints->active_discharge && ops->set_active_discharge) { 1144670666b9SLaxman Dewangan bool ad_state = (rdev->constraints->active_discharge == 1145670666b9SLaxman Dewangan REGULATOR_ACTIVE_DISCHARGE_ENABLE) ? true : false; 1146670666b9SLaxman Dewangan 1147670666b9SLaxman Dewangan ret = ops->set_active_discharge(rdev, ad_state); 1148670666b9SLaxman Dewangan if (ret < 0) { 1149670666b9SLaxman Dewangan rdev_err(rdev, "failed to set active discharge\n"); 1150670666b9SLaxman Dewangan return ret; 1151670666b9SLaxman Dewangan } 1152670666b9SLaxman Dewangan } 1153670666b9SLaxman Dewangan 1154909f7ee0SLaxman Dewangan if (rdev->constraints->active_discharge && ops->set_active_discharge) { 1155909f7ee0SLaxman Dewangan bool ad_state = (rdev->constraints->active_discharge == 1156909f7ee0SLaxman Dewangan REGULATOR_ACTIVE_DISCHARGE_ENABLE) ? true : false; 1157909f7ee0SLaxman Dewangan 1158909f7ee0SLaxman Dewangan ret = ops->set_active_discharge(rdev, ad_state); 1159909f7ee0SLaxman Dewangan if (ret < 0) { 1160909f7ee0SLaxman Dewangan rdev_err(rdev, "failed to set active discharge\n"); 1161909f7ee0SLaxman Dewangan return ret; 1162909f7ee0SLaxman Dewangan } 1163909f7ee0SLaxman Dewangan } 1164909f7ee0SLaxman Dewangan 1165a5766f11SLiam Girdwood print_constraints(rdev); 11661a6958e7SAxel Lin return 0; 1167a5766f11SLiam Girdwood out: 11681a6958e7SAxel Lin kfree(rdev->constraints); 11691a6958e7SAxel Lin rdev->constraints = NULL; 1170a5766f11SLiam Girdwood return ret; 1171a5766f11SLiam Girdwood } 1172a5766f11SLiam Girdwood 1173a5766f11SLiam Girdwood /** 1174a5766f11SLiam Girdwood * set_supply - set regulator supply regulator 117569279fb9SMark Brown * @rdev: regulator name 117669279fb9SMark Brown * @supply_rdev: supply regulator name 1177a5766f11SLiam Girdwood * 1178a5766f11SLiam Girdwood * Called by platform initialisation code to set the supply regulator for this 1179a5766f11SLiam Girdwood * regulator. This ensures that a regulators supply will also be enabled by the 1180a5766f11SLiam Girdwood * core if it's child is enabled. 1181a5766f11SLiam Girdwood */ 1182a5766f11SLiam Girdwood static int set_supply(struct regulator_dev *rdev, 1183a5766f11SLiam Girdwood struct regulator_dev *supply_rdev) 1184a5766f11SLiam Girdwood { 1185a5766f11SLiam Girdwood int err; 1186a5766f11SLiam Girdwood 11873801b86aSMark Brown rdev_info(rdev, "supplied by %s\n", rdev_get_name(supply_rdev)); 11883801b86aSMark Brown 1189e2c09ae7SJavier Martinez Canillas if (!try_module_get(supply_rdev->owner)) 1190e2c09ae7SJavier Martinez Canillas return -ENODEV; 1191e2c09ae7SJavier Martinez Canillas 11923801b86aSMark Brown rdev->supply = create_regulator(supply_rdev, &rdev->dev, "SUPPLY"); 119332c78de8SAxel Lin if (rdev->supply == NULL) { 119432c78de8SAxel Lin err = -ENOMEM; 1195a5766f11SLiam Girdwood return err; 1196a5766f11SLiam Girdwood } 119757ad526aSLaxman Dewangan supply_rdev->open_count++; 1198a5766f11SLiam Girdwood 11993801b86aSMark Brown return 0; 12003801b86aSMark Brown } 12013801b86aSMark Brown 1202a5766f11SLiam Girdwood /** 120306c63f93SRandy Dunlap * set_consumer_device_supply - Bind a regulator to a symbolic supply 120469279fb9SMark Brown * @rdev: regulator source 120540f9244fSMark Brown * @consumer_dev_name: dev_name() string for device supply applies to 1206a5766f11SLiam Girdwood * @supply: symbolic name for supply 1207a5766f11SLiam Girdwood * 1208a5766f11SLiam Girdwood * Allows platform initialisation code to map physical regulator 1209a5766f11SLiam Girdwood * sources to symbolic names for supplies for use by devices. Devices 1210a5766f11SLiam Girdwood * should use these symbolic names to request regulators, avoiding the 1211a5766f11SLiam Girdwood * need to provide board-specific regulator names as platform data. 1212a5766f11SLiam Girdwood */ 1213a5766f11SLiam Girdwood static int set_consumer_device_supply(struct regulator_dev *rdev, 1214737f360dSMark Brown const char *consumer_dev_name, 121540f9244fSMark Brown const char *supply) 1216a5766f11SLiam Girdwood { 1217a5766f11SLiam Girdwood struct regulator_map *node; 12189ed2099eSMark Brown int has_dev; 1219a5766f11SLiam Girdwood 1220a5766f11SLiam Girdwood if (supply == NULL) 1221a5766f11SLiam Girdwood return -EINVAL; 1222a5766f11SLiam Girdwood 12239ed2099eSMark Brown if (consumer_dev_name != NULL) 12249ed2099eSMark Brown has_dev = 1; 12259ed2099eSMark Brown else 12269ed2099eSMark Brown has_dev = 0; 12279ed2099eSMark Brown 12286001e13cSDavid Brownell list_for_each_entry(node, ®ulator_map_list, list) { 122923b5cc2aSJani Nikula if (node->dev_name && consumer_dev_name) { 123023b5cc2aSJani Nikula if (strcmp(node->dev_name, consumer_dev_name) != 0) 12316001e13cSDavid Brownell continue; 123223b5cc2aSJani Nikula } else if (node->dev_name || consumer_dev_name) { 123323b5cc2aSJani Nikula continue; 123423b5cc2aSJani Nikula } 123523b5cc2aSJani Nikula 12366001e13cSDavid Brownell if (strcmp(node->supply, supply) != 0) 12376001e13cSDavid Brownell continue; 12386001e13cSDavid Brownell 1239737f360dSMark Brown pr_debug("%s: %s/%s is '%s' supply; fail %s/%s\n", 1240737f360dSMark Brown consumer_dev_name, 12416001e13cSDavid Brownell dev_name(&node->regulator->dev), 12426001e13cSDavid Brownell node->regulator->desc->name, 12436001e13cSDavid Brownell supply, 12441083c393SMark Brown dev_name(&rdev->dev), rdev_get_name(rdev)); 12456001e13cSDavid Brownell return -EBUSY; 12466001e13cSDavid Brownell } 12476001e13cSDavid Brownell 12489ed2099eSMark Brown node = kzalloc(sizeof(struct regulator_map), GFP_KERNEL); 1249a5766f11SLiam Girdwood if (node == NULL) 1250a5766f11SLiam Girdwood return -ENOMEM; 1251a5766f11SLiam Girdwood 1252a5766f11SLiam Girdwood node->regulator = rdev; 1253a5766f11SLiam Girdwood node->supply = supply; 1254a5766f11SLiam Girdwood 12559ed2099eSMark Brown if (has_dev) { 12569ed2099eSMark Brown node->dev_name = kstrdup(consumer_dev_name, GFP_KERNEL); 125740f9244fSMark Brown if (node->dev_name == NULL) { 125840f9244fSMark Brown kfree(node); 125940f9244fSMark Brown return -ENOMEM; 126040f9244fSMark Brown } 12619ed2099eSMark Brown } 126240f9244fSMark Brown 1263a5766f11SLiam Girdwood list_add(&node->list, ®ulator_map_list); 1264a5766f11SLiam Girdwood return 0; 1265a5766f11SLiam Girdwood } 1266a5766f11SLiam Girdwood 12670f1d747bSMike Rapoport static void unset_regulator_supplies(struct regulator_dev *rdev) 12680f1d747bSMike Rapoport { 12690f1d747bSMike Rapoport struct regulator_map *node, *n; 12700f1d747bSMike Rapoport 12710f1d747bSMike Rapoport list_for_each_entry_safe(node, n, ®ulator_map_list, list) { 12720f1d747bSMike Rapoport if (rdev == node->regulator) { 12730f1d747bSMike Rapoport list_del(&node->list); 127440f9244fSMark Brown kfree(node->dev_name); 12750f1d747bSMike Rapoport kfree(node); 12760f1d747bSMike Rapoport } 12770f1d747bSMike Rapoport } 12780f1d747bSMike Rapoport } 12790f1d747bSMike Rapoport 1280f5726ae3SMark Brown #define REG_STR_SIZE 64 1281414c70cbSLiam Girdwood 1282414c70cbSLiam Girdwood static struct regulator *create_regulator(struct regulator_dev *rdev, 1283414c70cbSLiam Girdwood struct device *dev, 1284414c70cbSLiam Girdwood const char *supply_name) 1285414c70cbSLiam Girdwood { 1286414c70cbSLiam Girdwood struct regulator *regulator; 1287414c70cbSLiam Girdwood char buf[REG_STR_SIZE]; 1288414c70cbSLiam Girdwood int err, size; 1289414c70cbSLiam Girdwood 1290414c70cbSLiam Girdwood regulator = kzalloc(sizeof(*regulator), GFP_KERNEL); 1291414c70cbSLiam Girdwood if (regulator == NULL) 1292414c70cbSLiam Girdwood return NULL; 1293414c70cbSLiam Girdwood 1294414c70cbSLiam Girdwood mutex_lock(&rdev->mutex); 1295414c70cbSLiam Girdwood regulator->rdev = rdev; 1296414c70cbSLiam Girdwood list_add(®ulator->list, &rdev->consumer_list); 1297414c70cbSLiam Girdwood 1298414c70cbSLiam Girdwood if (dev) { 1299e2c98eafSShawn Guo regulator->dev = dev; 1300e2c98eafSShawn Guo 1301222cc7b1SMark Brown /* Add a link to the device sysfs entry */ 1302414c70cbSLiam Girdwood size = scnprintf(buf, REG_STR_SIZE, "%s-%s", 1303414c70cbSLiam Girdwood dev->kobj.name, supply_name); 1304414c70cbSLiam Girdwood if (size >= REG_STR_SIZE) 1305222cc7b1SMark Brown goto overflow_err; 1306414c70cbSLiam Girdwood 1307414c70cbSLiam Girdwood regulator->supply_name = kstrdup(buf, GFP_KERNEL); 1308414c70cbSLiam Girdwood if (regulator->supply_name == NULL) 1309222cc7b1SMark Brown goto overflow_err; 1310414c70cbSLiam Girdwood 1311ff268b56SStephen Boyd err = sysfs_create_link_nowarn(&rdev->dev.kobj, &dev->kobj, 1312414c70cbSLiam Girdwood buf); 1313414c70cbSLiam Girdwood if (err) { 1314ff268b56SStephen Boyd rdev_dbg(rdev, "could not add device link %s err %d\n", 13151d7372e1SDaniel Walker dev->kobj.name, err); 1316222cc7b1SMark Brown /* non-fatal */ 1317414c70cbSLiam Girdwood } 13185de70519SMark Brown } else { 13195de70519SMark Brown regulator->supply_name = kstrdup(supply_name, GFP_KERNEL); 13205de70519SMark Brown if (regulator->supply_name == NULL) 1321222cc7b1SMark Brown goto overflow_err; 1322414c70cbSLiam Girdwood } 13235de70519SMark Brown 13245de70519SMark Brown regulator->debugfs = debugfs_create_dir(regulator->supply_name, 13255de70519SMark Brown rdev->debugfs); 132624751434SStephen Boyd if (!regulator->debugfs) { 1327ad3a942bSStephen Boyd rdev_dbg(rdev, "Failed to create debugfs directory\n"); 13285de70519SMark Brown } else { 13295de70519SMark Brown debugfs_create_u32("uA_load", 0444, regulator->debugfs, 13305de70519SMark Brown ®ulator->uA_load); 13315de70519SMark Brown debugfs_create_u32("min_uV", 0444, regulator->debugfs, 13325de70519SMark Brown ®ulator->min_uV); 13335de70519SMark Brown debugfs_create_u32("max_uV", 0444, regulator->debugfs, 13345de70519SMark Brown ®ulator->max_uV); 13355de70519SMark Brown } 13365de70519SMark Brown 13376492bc1bSMark Brown /* 13386492bc1bSMark Brown * Check now if the regulator is an always on regulator - if 13396492bc1bSMark Brown * it is then we don't need to do nearly so much work for 13406492bc1bSMark Brown * enable/disable calls. 13416492bc1bSMark Brown */ 13426492bc1bSMark Brown if (!_regulator_can_change_status(rdev) && 13436492bc1bSMark Brown _regulator_is_enabled(rdev)) 13446492bc1bSMark Brown regulator->always_on = true; 13456492bc1bSMark Brown 1346414c70cbSLiam Girdwood mutex_unlock(&rdev->mutex); 1347414c70cbSLiam Girdwood return regulator; 1348414c70cbSLiam Girdwood overflow_err: 1349414c70cbSLiam Girdwood list_del(®ulator->list); 1350414c70cbSLiam Girdwood kfree(regulator); 1351414c70cbSLiam Girdwood mutex_unlock(&rdev->mutex); 1352414c70cbSLiam Girdwood return NULL; 1353414c70cbSLiam Girdwood } 1354414c70cbSLiam Girdwood 135531aae2beSMark Brown static int _regulator_get_enable_time(struct regulator_dev *rdev) 135631aae2beSMark Brown { 135700c877c6SLaxman Dewangan if (rdev->constraints && rdev->constraints->enable_time) 135800c877c6SLaxman Dewangan return rdev->constraints->enable_time; 135931aae2beSMark Brown if (!rdev->desc->ops->enable_time) 136079511ed3SMark Brown return rdev->desc->enable_time; 136131aae2beSMark Brown return rdev->desc->ops->enable_time(rdev); 136231aae2beSMark Brown } 136331aae2beSMark Brown 1364a06ccd9cSCharles Keepax static struct regulator_supply_alias *regulator_find_supply_alias( 1365a06ccd9cSCharles Keepax struct device *dev, const char *supply) 1366a06ccd9cSCharles Keepax { 1367a06ccd9cSCharles Keepax struct regulator_supply_alias *map; 1368a06ccd9cSCharles Keepax 1369a06ccd9cSCharles Keepax list_for_each_entry(map, ®ulator_supply_alias_list, list) 1370a06ccd9cSCharles Keepax if (map->src_dev == dev && strcmp(map->src_supply, supply) == 0) 1371a06ccd9cSCharles Keepax return map; 1372a06ccd9cSCharles Keepax 1373a06ccd9cSCharles Keepax return NULL; 1374a06ccd9cSCharles Keepax } 1375a06ccd9cSCharles Keepax 1376a06ccd9cSCharles Keepax static void regulator_supply_alias(struct device **dev, const char **supply) 1377a06ccd9cSCharles Keepax { 1378a06ccd9cSCharles Keepax struct regulator_supply_alias *map; 1379a06ccd9cSCharles Keepax 1380a06ccd9cSCharles Keepax map = regulator_find_supply_alias(*dev, *supply); 1381a06ccd9cSCharles Keepax if (map) { 1382a06ccd9cSCharles Keepax dev_dbg(*dev, "Mapping supply %s to %s,%s\n", 1383a06ccd9cSCharles Keepax *supply, map->alias_supply, 1384a06ccd9cSCharles Keepax dev_name(map->alias_dev)); 1385a06ccd9cSCharles Keepax *dev = map->alias_dev; 1386a06ccd9cSCharles Keepax *supply = map->alias_supply; 1387a06ccd9cSCharles Keepax } 1388a06ccd9cSCharles Keepax } 1389a06ccd9cSCharles Keepax 139085f3b431STomeu Vizoso static int of_node_match(struct device *dev, const void *data) 139185f3b431STomeu Vizoso { 139285f3b431STomeu Vizoso return dev->of_node == data; 139385f3b431STomeu Vizoso } 139485f3b431STomeu Vizoso 139585f3b431STomeu Vizoso static struct regulator_dev *of_find_regulator_by_node(struct device_node *np) 139685f3b431STomeu Vizoso { 139785f3b431STomeu Vizoso struct device *dev; 139885f3b431STomeu Vizoso 139985f3b431STomeu Vizoso dev = class_find_device(®ulator_class, NULL, np, of_node_match); 140085f3b431STomeu Vizoso 140185f3b431STomeu Vizoso return dev ? dev_to_rdev(dev) : NULL; 140285f3b431STomeu Vizoso } 140385f3b431STomeu Vizoso 140485f3b431STomeu Vizoso static int regulator_match(struct device *dev, const void *data) 140585f3b431STomeu Vizoso { 140685f3b431STomeu Vizoso struct regulator_dev *r = dev_to_rdev(dev); 140785f3b431STomeu Vizoso 140885f3b431STomeu Vizoso return strcmp(rdev_get_name(r), data) == 0; 140985f3b431STomeu Vizoso } 141085f3b431STomeu Vizoso 141185f3b431STomeu Vizoso static struct regulator_dev *regulator_lookup_by_name(const char *name) 141285f3b431STomeu Vizoso { 141385f3b431STomeu Vizoso struct device *dev; 141485f3b431STomeu Vizoso 141585f3b431STomeu Vizoso dev = class_find_device(®ulator_class, NULL, name, regulator_match); 141685f3b431STomeu Vizoso 141785f3b431STomeu Vizoso return dev ? dev_to_rdev(dev) : NULL; 141885f3b431STomeu Vizoso } 141985f3b431STomeu Vizoso 142085f3b431STomeu Vizoso /** 142185f3b431STomeu Vizoso * regulator_dev_lookup - lookup a regulator device. 142285f3b431STomeu Vizoso * @dev: device for regulator "consumer". 142385f3b431STomeu Vizoso * @supply: Supply name or regulator ID. 142485f3b431STomeu Vizoso * @ret: 0 on success, -ENODEV if lookup fails permanently, -EPROBE_DEFER if 142585f3b431STomeu Vizoso * lookup could succeed in the future. 142685f3b431STomeu Vizoso * 142785f3b431STomeu Vizoso * If successful, returns a struct regulator_dev that corresponds to the name 142885f3b431STomeu Vizoso * @supply and with the embedded struct device refcount incremented by one, 142985f3b431STomeu Vizoso * or NULL on failure. The refcount must be dropped by calling put_device(). 143085f3b431STomeu Vizoso */ 143169511a45SRajendra Nayak static struct regulator_dev *regulator_dev_lookup(struct device *dev, 14326d191a5fSMark Brown const char *supply, 14336d191a5fSMark Brown int *ret) 143469511a45SRajendra Nayak { 143569511a45SRajendra Nayak struct regulator_dev *r; 143669511a45SRajendra Nayak struct device_node *node; 1437576ca436SMark Brown struct regulator_map *map; 1438576ca436SMark Brown const char *devname = NULL; 143969511a45SRajendra Nayak 1440a06ccd9cSCharles Keepax regulator_supply_alias(&dev, &supply); 1441a06ccd9cSCharles Keepax 144269511a45SRajendra Nayak /* first do a dt based lookup */ 144369511a45SRajendra Nayak if (dev && dev->of_node) { 144469511a45SRajendra Nayak node = of_get_regulator(dev, supply); 14456d191a5fSMark Brown if (node) { 144685f3b431STomeu Vizoso r = of_find_regulator_by_node(node); 144785f3b431STomeu Vizoso if (r) 144869511a45SRajendra Nayak return r; 1449317b5684SMark Brown *ret = -EPROBE_DEFER; 1450317b5684SMark Brown return NULL; 14516d191a5fSMark Brown } else { 14526d191a5fSMark Brown /* 14536d191a5fSMark Brown * If we couldn't even get the node then it's 14546d191a5fSMark Brown * not just that the device didn't register 14556d191a5fSMark Brown * yet, there's no node and we'll never 14566d191a5fSMark Brown * succeed. 14576d191a5fSMark Brown */ 14586d191a5fSMark Brown *ret = -ENODEV; 14596d191a5fSMark Brown } 146069511a45SRajendra Nayak } 146169511a45SRajendra Nayak 146269511a45SRajendra Nayak /* if not found, try doing it non-dt way */ 1463576ca436SMark Brown if (dev) 1464576ca436SMark Brown devname = dev_name(dev); 1465576ca436SMark Brown 146685f3b431STomeu Vizoso r = regulator_lookup_by_name(supply); 146785f3b431STomeu Vizoso if (r) 146869511a45SRajendra Nayak return r; 146969511a45SRajendra Nayak 147085f3b431STomeu Vizoso mutex_lock(®ulator_list_mutex); 1471576ca436SMark Brown list_for_each_entry(map, ®ulator_map_list, list) { 1472576ca436SMark Brown /* If the mapping has a device set up it must match */ 1473576ca436SMark Brown if (map->dev_name && 1474576ca436SMark Brown (!devname || strcmp(map->dev_name, devname))) 1475576ca436SMark Brown continue; 1476576ca436SMark Brown 147785f3b431STomeu Vizoso if (strcmp(map->supply, supply) == 0 && 147885f3b431STomeu Vizoso get_device(&map->regulator->dev)) { 147985f3b431STomeu Vizoso mutex_unlock(®ulator_list_mutex); 1480576ca436SMark Brown return map->regulator; 1481576ca436SMark Brown } 148285f3b431STomeu Vizoso } 148385f3b431STomeu Vizoso mutex_unlock(®ulator_list_mutex); 1484576ca436SMark Brown 148569511a45SRajendra Nayak return NULL; 148669511a45SRajendra Nayak } 148769511a45SRajendra Nayak 14886261b06dSBjorn Andersson static int regulator_resolve_supply(struct regulator_dev *rdev) 14896261b06dSBjorn Andersson { 14906261b06dSBjorn Andersson struct regulator_dev *r; 14916261b06dSBjorn Andersson struct device *dev = rdev->dev.parent; 14926261b06dSBjorn Andersson int ret; 14936261b06dSBjorn Andersson 14946261b06dSBjorn Andersson /* No supply to resovle? */ 14956261b06dSBjorn Andersson if (!rdev->supply_name) 14966261b06dSBjorn Andersson return 0; 14976261b06dSBjorn Andersson 14986261b06dSBjorn Andersson /* Supply already resolved? */ 14996261b06dSBjorn Andersson if (rdev->supply) 15006261b06dSBjorn Andersson return 0; 15016261b06dSBjorn Andersson 15026261b06dSBjorn Andersson r = regulator_dev_lookup(dev, rdev->supply_name, &ret); 150323c3f310SCharles Keepax if (!r) { 15046261b06dSBjorn Andersson if (ret == -ENODEV) { 15056261b06dSBjorn Andersson /* 15066261b06dSBjorn Andersson * No supply was specified for this regulator and 15076261b06dSBjorn Andersson * there will never be one. 15086261b06dSBjorn Andersson */ 15096261b06dSBjorn Andersson return 0; 15106261b06dSBjorn Andersson } 15116261b06dSBjorn Andersson 151206423121SMark Brown /* Did the lookup explicitly defer for us? */ 151306423121SMark Brown if (ret == -EPROBE_DEFER) 151406423121SMark Brown return ret; 151506423121SMark Brown 15169f7e25edSMark Brown if (have_full_constraints()) { 15179f7e25edSMark Brown r = dummy_regulator_rdev; 151885f3b431STomeu Vizoso get_device(&r->dev); 15199f7e25edSMark Brown } else { 15206261b06dSBjorn Andersson dev_err(dev, "Failed to resolve %s-supply for %s\n", 15216261b06dSBjorn Andersson rdev->supply_name, rdev->desc->name); 15226261b06dSBjorn Andersson return -EPROBE_DEFER; 15236261b06dSBjorn Andersson } 15249f7e25edSMark Brown } 15256261b06dSBjorn Andersson 15266261b06dSBjorn Andersson /* Recursively resolve the supply of the supply */ 15276261b06dSBjorn Andersson ret = regulator_resolve_supply(r); 152885f3b431STomeu Vizoso if (ret < 0) { 152985f3b431STomeu Vizoso put_device(&r->dev); 15306261b06dSBjorn Andersson return ret; 153185f3b431STomeu Vizoso } 15326261b06dSBjorn Andersson 15336261b06dSBjorn Andersson ret = set_supply(rdev, r); 153485f3b431STomeu Vizoso if (ret < 0) { 153585f3b431STomeu Vizoso put_device(&r->dev); 15366261b06dSBjorn Andersson return ret; 153785f3b431STomeu Vizoso } 15386261b06dSBjorn Andersson 15396261b06dSBjorn Andersson /* Cascade always-on state to supply */ 15409f8df6adSSudip Mukherjee if (_regulator_is_enabled(rdev) && rdev->supply) { 15416261b06dSBjorn Andersson ret = regulator_enable(rdev->supply); 154236a1f1b6SJavier Martinez Canillas if (ret < 0) { 154336a1f1b6SJavier Martinez Canillas _regulator_put(rdev->supply); 15446261b06dSBjorn Andersson return ret; 15456261b06dSBjorn Andersson } 154636a1f1b6SJavier Martinez Canillas } 15476261b06dSBjorn Andersson 15486261b06dSBjorn Andersson return 0; 15496261b06dSBjorn Andersson } 15506261b06dSBjorn Andersson 15515ffbd136SMark Brown /* Internal regulator request function */ 15525ffbd136SMark Brown static struct regulator *_regulator_get(struct device *dev, const char *id, 15534ddfebd3SMark Brown bool exclusive, bool allow_dummy) 1554414c70cbSLiam Girdwood { 1555414c70cbSLiam Girdwood struct regulator_dev *rdev; 155604bf3011SMark Brown struct regulator *regulator = ERR_PTR(-EPROBE_DEFER); 155740f9244fSMark Brown const char *devname = NULL; 1558317b5684SMark Brown int ret; 1559414c70cbSLiam Girdwood 1560414c70cbSLiam Girdwood if (id == NULL) { 15615da84fd9SJoe Perches pr_err("get() with no identifier\n"); 1562043c998fSMark Brown return ERR_PTR(-EINVAL); 1563414c70cbSLiam Girdwood } 1564414c70cbSLiam Girdwood 156540f9244fSMark Brown if (dev) 156640f9244fSMark Brown devname = dev_name(dev); 156740f9244fSMark Brown 1568317b5684SMark Brown if (have_full_constraints()) 1569317b5684SMark Brown ret = -ENODEV; 1570317b5684SMark Brown else 1571317b5684SMark Brown ret = -EPROBE_DEFER; 1572317b5684SMark Brown 15736d191a5fSMark Brown rdev = regulator_dev_lookup(dev, id, &ret); 157469511a45SRajendra Nayak if (rdev) 157569511a45SRajendra Nayak goto found; 157669511a45SRajendra Nayak 1577ef60abbbSMark Brown regulator = ERR_PTR(ret); 1578ef60abbbSMark Brown 15791e4b545cSNishanth Menon /* 15801e4b545cSNishanth Menon * If we have return value from dev_lookup fail, we do not expect to 15811e4b545cSNishanth Menon * succeed, so, quit with appropriate error value 15821e4b545cSNishanth Menon */ 15830d25d09dSJingoo Han if (ret && ret != -ENODEV) 158485f3b431STomeu Vizoso return regulator; 15851e4b545cSNishanth Menon 158634abbd68SMark Brown if (!devname) 158734abbd68SMark Brown devname = "deviceless"; 158834abbd68SMark Brown 15894ddfebd3SMark Brown /* 15904ddfebd3SMark Brown * Assume that a regulator is physically present and enabled 15914ddfebd3SMark Brown * even if it isn't hooked up and just provide a dummy. 159234abbd68SMark Brown */ 159387b28417SMark Brown if (have_full_constraints() && allow_dummy) { 15945da84fd9SJoe Perches pr_warn("%s supply %s not found, using dummy regulator\n", 159534abbd68SMark Brown devname, id); 15964ddfebd3SMark Brown 159734abbd68SMark Brown rdev = dummy_regulator_rdev; 159885f3b431STomeu Vizoso get_device(&rdev->dev); 159934abbd68SMark Brown goto found; 16000781719bSHans de Goede /* Don't log an error when called from regulator_get_optional() */ 16010781719bSHans de Goede } else if (!have_full_constraints() || exclusive) { 1602acc3d5ceSShuah Khan dev_warn(dev, "dummy supplies not allowed\n"); 160334abbd68SMark Brown } 160434abbd68SMark Brown 1605414c70cbSLiam Girdwood return regulator; 1606414c70cbSLiam Girdwood 1607414c70cbSLiam Girdwood found: 16085ffbd136SMark Brown if (rdev->exclusive) { 16095ffbd136SMark Brown regulator = ERR_PTR(-EPERM); 161085f3b431STomeu Vizoso put_device(&rdev->dev); 161185f3b431STomeu Vizoso return regulator; 16125ffbd136SMark Brown } 16135ffbd136SMark Brown 16145ffbd136SMark Brown if (exclusive && rdev->open_count) { 16155ffbd136SMark Brown regulator = ERR_PTR(-EBUSY); 161685f3b431STomeu Vizoso put_device(&rdev->dev); 161785f3b431STomeu Vizoso return regulator; 16185ffbd136SMark Brown } 16195ffbd136SMark Brown 16206261b06dSBjorn Andersson ret = regulator_resolve_supply(rdev); 16216261b06dSBjorn Andersson if (ret < 0) { 16226261b06dSBjorn Andersson regulator = ERR_PTR(ret); 162385f3b431STomeu Vizoso put_device(&rdev->dev); 162485f3b431STomeu Vizoso return regulator; 16256261b06dSBjorn Andersson } 16266261b06dSBjorn Andersson 162785f3b431STomeu Vizoso if (!try_module_get(rdev->owner)) { 162885f3b431STomeu Vizoso put_device(&rdev->dev); 162985f3b431STomeu Vizoso return regulator; 163085f3b431STomeu Vizoso } 1631a5766f11SLiam Girdwood 1632414c70cbSLiam Girdwood regulator = create_regulator(rdev, dev, id); 1633414c70cbSLiam Girdwood if (regulator == NULL) { 1634414c70cbSLiam Girdwood regulator = ERR_PTR(-ENOMEM); 163585f3b431STomeu Vizoso put_device(&rdev->dev); 1636414c70cbSLiam Girdwood module_put(rdev->owner); 163785f3b431STomeu Vizoso return regulator; 1638414c70cbSLiam Girdwood } 1639414c70cbSLiam Girdwood 16405ffbd136SMark Brown rdev->open_count++; 16415ffbd136SMark Brown if (exclusive) { 16425ffbd136SMark Brown rdev->exclusive = 1; 16435ffbd136SMark Brown 16445ffbd136SMark Brown ret = _regulator_is_enabled(rdev); 16455ffbd136SMark Brown if (ret > 0) 16465ffbd136SMark Brown rdev->use_count = 1; 16475ffbd136SMark Brown else 16485ffbd136SMark Brown rdev->use_count = 0; 16495ffbd136SMark Brown } 16505ffbd136SMark Brown 1651414c70cbSLiam Girdwood return regulator; 1652414c70cbSLiam Girdwood } 16535ffbd136SMark Brown 16545ffbd136SMark Brown /** 16555ffbd136SMark Brown * regulator_get - lookup and obtain a reference to a regulator. 16565ffbd136SMark Brown * @dev: device for regulator "consumer" 16575ffbd136SMark Brown * @id: Supply name or regulator ID. 16585ffbd136SMark Brown * 16595ffbd136SMark Brown * Returns a struct regulator corresponding to the regulator producer, 16605ffbd136SMark Brown * or IS_ERR() condition containing errno. 16615ffbd136SMark Brown * 16625ffbd136SMark Brown * Use of supply names configured via regulator_set_device_supply() is 16635ffbd136SMark Brown * strongly encouraged. It is recommended that the supply name used 16645ffbd136SMark Brown * should match the name used for the supply and/or the relevant 16655ffbd136SMark Brown * device pins in the datasheet. 16665ffbd136SMark Brown */ 16675ffbd136SMark Brown struct regulator *regulator_get(struct device *dev, const char *id) 16685ffbd136SMark Brown { 16694ddfebd3SMark Brown return _regulator_get(dev, id, false, true); 16705ffbd136SMark Brown } 1671414c70cbSLiam Girdwood EXPORT_SYMBOL_GPL(regulator_get); 1672414c70cbSLiam Girdwood 1673070b9079SStephen Boyd /** 16745ffbd136SMark Brown * regulator_get_exclusive - obtain exclusive access to a regulator. 16755ffbd136SMark Brown * @dev: device for regulator "consumer" 16765ffbd136SMark Brown * @id: Supply name or regulator ID. 16775ffbd136SMark Brown * 16785ffbd136SMark Brown * Returns a struct regulator corresponding to the regulator producer, 16795ffbd136SMark Brown * or IS_ERR() condition containing errno. Other consumers will be 168069c3f723SStephen Boyd * unable to obtain this regulator while this reference is held and the 168169c3f723SStephen Boyd * use count for the regulator will be initialised to reflect the current 168269c3f723SStephen Boyd * state of the regulator. 16835ffbd136SMark Brown * 16845ffbd136SMark Brown * This is intended for use by consumers which cannot tolerate shared 16855ffbd136SMark Brown * use of the regulator such as those which need to force the 16865ffbd136SMark Brown * regulator off for correct operation of the hardware they are 16875ffbd136SMark Brown * controlling. 16885ffbd136SMark Brown * 16895ffbd136SMark Brown * Use of supply names configured via regulator_set_device_supply() is 16905ffbd136SMark Brown * strongly encouraged. It is recommended that the supply name used 16915ffbd136SMark Brown * should match the name used for the supply and/or the relevant 16925ffbd136SMark Brown * device pins in the datasheet. 16935ffbd136SMark Brown */ 16945ffbd136SMark Brown struct regulator *regulator_get_exclusive(struct device *dev, const char *id) 16955ffbd136SMark Brown { 16964ddfebd3SMark Brown return _regulator_get(dev, id, true, false); 16975ffbd136SMark Brown } 16985ffbd136SMark Brown EXPORT_SYMBOL_GPL(regulator_get_exclusive); 16995ffbd136SMark Brown 1700de1dd9fdSMark Brown /** 1701de1dd9fdSMark Brown * regulator_get_optional - obtain optional access to a regulator. 1702de1dd9fdSMark Brown * @dev: device for regulator "consumer" 1703de1dd9fdSMark Brown * @id: Supply name or regulator ID. 1704de1dd9fdSMark Brown * 1705de1dd9fdSMark Brown * Returns a struct regulator corresponding to the regulator producer, 170669c3f723SStephen Boyd * or IS_ERR() condition containing errno. 1707de1dd9fdSMark Brown * 1708de1dd9fdSMark Brown * This is intended for use by consumers for devices which can have 1709de1dd9fdSMark Brown * some supplies unconnected in normal use, such as some MMC devices. 1710de1dd9fdSMark Brown * It can allow the regulator core to provide stub supplies for other 1711de1dd9fdSMark Brown * supplies requested using normal regulator_get() calls without 1712de1dd9fdSMark Brown * disrupting the operation of drivers that can handle absent 1713de1dd9fdSMark Brown * supplies. 1714de1dd9fdSMark Brown * 1715de1dd9fdSMark Brown * Use of supply names configured via regulator_set_device_supply() is 1716de1dd9fdSMark Brown * strongly encouraged. It is recommended that the supply name used 1717de1dd9fdSMark Brown * should match the name used for the supply and/or the relevant 1718de1dd9fdSMark Brown * device pins in the datasheet. 1719de1dd9fdSMark Brown */ 1720de1dd9fdSMark Brown struct regulator *regulator_get_optional(struct device *dev, const char *id) 1721de1dd9fdSMark Brown { 17224ddfebd3SMark Brown return _regulator_get(dev, id, false, false); 1723de1dd9fdSMark Brown } 1724de1dd9fdSMark Brown EXPORT_SYMBOL_GPL(regulator_get_optional); 1725de1dd9fdSMark Brown 172683b0302dSAshay Jaiswal /* regulator_list_mutex lock held by regulator_put() */ 172723ff2f0fSCharles Keepax static void _regulator_put(struct regulator *regulator) 1728414c70cbSLiam Girdwood { 1729414c70cbSLiam Girdwood struct regulator_dev *rdev; 1730414c70cbSLiam Girdwood 173193576842SViresh Kumar if (IS_ERR_OR_NULL(regulator)) 1732414c70cbSLiam Girdwood return; 1733414c70cbSLiam Girdwood 173470cfef26SKrzysztof Kozlowski lockdep_assert_held_once(®ulator_list_mutex); 173570cfef26SKrzysztof Kozlowski 1736414c70cbSLiam Girdwood rdev = regulator->rdev; 1737414c70cbSLiam Girdwood 17385de70519SMark Brown debugfs_remove_recursive(regulator->debugfs); 17395de70519SMark Brown 1740414c70cbSLiam Girdwood /* remove any sysfs entries */ 1741e2c98eafSShawn Guo if (regulator->dev) 1742414c70cbSLiam Girdwood sysfs_remove_link(&rdev->dev.kobj, regulator->supply_name); 174383b0302dSAshay Jaiswal mutex_lock(&rdev->mutex); 1744414c70cbSLiam Girdwood list_del(®ulator->list); 1745414c70cbSLiam Girdwood 17465ffbd136SMark Brown rdev->open_count--; 17475ffbd136SMark Brown rdev->exclusive = 0; 174885f3b431STomeu Vizoso put_device(&rdev->dev); 174983b0302dSAshay Jaiswal mutex_unlock(&rdev->mutex); 17505ffbd136SMark Brown 17511768514eSMark Brown kfree(regulator->supply_name); 17521768514eSMark Brown kfree(regulator); 17531768514eSMark Brown 1754414c70cbSLiam Girdwood module_put(rdev->owner); 175523ff2f0fSCharles Keepax } 175623ff2f0fSCharles Keepax 175723ff2f0fSCharles Keepax /** 175823ff2f0fSCharles Keepax * regulator_put - "free" the regulator source 175923ff2f0fSCharles Keepax * @regulator: regulator source 176023ff2f0fSCharles Keepax * 176123ff2f0fSCharles Keepax * Note: drivers must ensure that all regulator_enable calls made on this 176223ff2f0fSCharles Keepax * regulator source are balanced by regulator_disable calls prior to calling 176323ff2f0fSCharles Keepax * this function. 176423ff2f0fSCharles Keepax */ 176523ff2f0fSCharles Keepax void regulator_put(struct regulator *regulator) 176623ff2f0fSCharles Keepax { 176723ff2f0fSCharles Keepax mutex_lock(®ulator_list_mutex); 176823ff2f0fSCharles Keepax _regulator_put(regulator); 1769414c70cbSLiam Girdwood mutex_unlock(®ulator_list_mutex); 1770414c70cbSLiam Girdwood } 1771414c70cbSLiam Girdwood EXPORT_SYMBOL_GPL(regulator_put); 1772414c70cbSLiam Girdwood 1773a06ccd9cSCharles Keepax /** 1774a06ccd9cSCharles Keepax * regulator_register_supply_alias - Provide device alias for supply lookup 1775a06ccd9cSCharles Keepax * 1776a06ccd9cSCharles Keepax * @dev: device that will be given as the regulator "consumer" 1777a06ccd9cSCharles Keepax * @id: Supply name or regulator ID 1778a06ccd9cSCharles Keepax * @alias_dev: device that should be used to lookup the supply 1779a06ccd9cSCharles Keepax * @alias_id: Supply name or regulator ID that should be used to lookup the 1780a06ccd9cSCharles Keepax * supply 1781a06ccd9cSCharles Keepax * 1782a06ccd9cSCharles Keepax * All lookups for id on dev will instead be conducted for alias_id on 1783a06ccd9cSCharles Keepax * alias_dev. 1784a06ccd9cSCharles Keepax */ 1785a06ccd9cSCharles Keepax int regulator_register_supply_alias(struct device *dev, const char *id, 1786a06ccd9cSCharles Keepax struct device *alias_dev, 1787a06ccd9cSCharles Keepax const char *alias_id) 1788a06ccd9cSCharles Keepax { 1789a06ccd9cSCharles Keepax struct regulator_supply_alias *map; 1790a06ccd9cSCharles Keepax 1791a06ccd9cSCharles Keepax map = regulator_find_supply_alias(dev, id); 1792a06ccd9cSCharles Keepax if (map) 1793a06ccd9cSCharles Keepax return -EEXIST; 1794a06ccd9cSCharles Keepax 1795a06ccd9cSCharles Keepax map = kzalloc(sizeof(struct regulator_supply_alias), GFP_KERNEL); 1796a06ccd9cSCharles Keepax if (!map) 1797a06ccd9cSCharles Keepax return -ENOMEM; 1798a06ccd9cSCharles Keepax 1799a06ccd9cSCharles Keepax map->src_dev = dev; 1800a06ccd9cSCharles Keepax map->src_supply = id; 1801a06ccd9cSCharles Keepax map->alias_dev = alias_dev; 1802a06ccd9cSCharles Keepax map->alias_supply = alias_id; 1803a06ccd9cSCharles Keepax 1804a06ccd9cSCharles Keepax list_add(&map->list, ®ulator_supply_alias_list); 1805a06ccd9cSCharles Keepax 1806a06ccd9cSCharles Keepax pr_info("Adding alias for supply %s,%s -> %s,%s\n", 1807a06ccd9cSCharles Keepax id, dev_name(dev), alias_id, dev_name(alias_dev)); 1808a06ccd9cSCharles Keepax 1809a06ccd9cSCharles Keepax return 0; 1810a06ccd9cSCharles Keepax } 1811a06ccd9cSCharles Keepax EXPORT_SYMBOL_GPL(regulator_register_supply_alias); 1812a06ccd9cSCharles Keepax 1813a06ccd9cSCharles Keepax /** 1814a06ccd9cSCharles Keepax * regulator_unregister_supply_alias - Remove device alias 1815a06ccd9cSCharles Keepax * 1816a06ccd9cSCharles Keepax * @dev: device that will be given as the regulator "consumer" 1817a06ccd9cSCharles Keepax * @id: Supply name or regulator ID 1818a06ccd9cSCharles Keepax * 1819a06ccd9cSCharles Keepax * Remove a lookup alias if one exists for id on dev. 1820a06ccd9cSCharles Keepax */ 1821a06ccd9cSCharles Keepax void regulator_unregister_supply_alias(struct device *dev, const char *id) 1822a06ccd9cSCharles Keepax { 1823a06ccd9cSCharles Keepax struct regulator_supply_alias *map; 1824a06ccd9cSCharles Keepax 1825a06ccd9cSCharles Keepax map = regulator_find_supply_alias(dev, id); 1826a06ccd9cSCharles Keepax if (map) { 1827a06ccd9cSCharles Keepax list_del(&map->list); 1828a06ccd9cSCharles Keepax kfree(map); 1829a06ccd9cSCharles Keepax } 1830a06ccd9cSCharles Keepax } 1831a06ccd9cSCharles Keepax EXPORT_SYMBOL_GPL(regulator_unregister_supply_alias); 1832a06ccd9cSCharles Keepax 1833a06ccd9cSCharles Keepax /** 1834a06ccd9cSCharles Keepax * regulator_bulk_register_supply_alias - register multiple aliases 1835a06ccd9cSCharles Keepax * 1836a06ccd9cSCharles Keepax * @dev: device that will be given as the regulator "consumer" 1837a06ccd9cSCharles Keepax * @id: List of supply names or regulator IDs 1838a06ccd9cSCharles Keepax * @alias_dev: device that should be used to lookup the supply 1839a06ccd9cSCharles Keepax * @alias_id: List of supply names or regulator IDs that should be used to 1840a06ccd9cSCharles Keepax * lookup the supply 1841a06ccd9cSCharles Keepax * @num_id: Number of aliases to register 1842a06ccd9cSCharles Keepax * 1843a06ccd9cSCharles Keepax * @return 0 on success, an errno on failure. 1844a06ccd9cSCharles Keepax * 1845a06ccd9cSCharles Keepax * This helper function allows drivers to register several supply 1846a06ccd9cSCharles Keepax * aliases in one operation. If any of the aliases cannot be 1847a06ccd9cSCharles Keepax * registered any aliases that were registered will be removed 1848a06ccd9cSCharles Keepax * before returning to the caller. 1849a06ccd9cSCharles Keepax */ 18509f8c0fe9SLee Jones int regulator_bulk_register_supply_alias(struct device *dev, 18519f8c0fe9SLee Jones const char *const *id, 1852a06ccd9cSCharles Keepax struct device *alias_dev, 18539f8c0fe9SLee Jones const char *const *alias_id, 1854a06ccd9cSCharles Keepax int num_id) 1855a06ccd9cSCharles Keepax { 1856a06ccd9cSCharles Keepax int i; 1857a06ccd9cSCharles Keepax int ret; 1858a06ccd9cSCharles Keepax 1859a06ccd9cSCharles Keepax for (i = 0; i < num_id; ++i) { 1860a06ccd9cSCharles Keepax ret = regulator_register_supply_alias(dev, id[i], alias_dev, 1861a06ccd9cSCharles Keepax alias_id[i]); 1862a06ccd9cSCharles Keepax if (ret < 0) 1863a06ccd9cSCharles Keepax goto err; 1864a06ccd9cSCharles Keepax } 1865a06ccd9cSCharles Keepax 1866a06ccd9cSCharles Keepax return 0; 1867a06ccd9cSCharles Keepax 1868a06ccd9cSCharles Keepax err: 1869a06ccd9cSCharles Keepax dev_err(dev, 1870a06ccd9cSCharles Keepax "Failed to create supply alias %s,%s -> %s,%s\n", 1871a06ccd9cSCharles Keepax id[i], dev_name(dev), alias_id[i], dev_name(alias_dev)); 1872a06ccd9cSCharles Keepax 1873a06ccd9cSCharles Keepax while (--i >= 0) 1874a06ccd9cSCharles Keepax regulator_unregister_supply_alias(dev, id[i]); 1875a06ccd9cSCharles Keepax 1876a06ccd9cSCharles Keepax return ret; 1877a06ccd9cSCharles Keepax } 1878a06ccd9cSCharles Keepax EXPORT_SYMBOL_GPL(regulator_bulk_register_supply_alias); 1879a06ccd9cSCharles Keepax 1880a06ccd9cSCharles Keepax /** 1881a06ccd9cSCharles Keepax * regulator_bulk_unregister_supply_alias - unregister multiple aliases 1882a06ccd9cSCharles Keepax * 1883a06ccd9cSCharles Keepax * @dev: device that will be given as the regulator "consumer" 1884a06ccd9cSCharles Keepax * @id: List of supply names or regulator IDs 1885a06ccd9cSCharles Keepax * @num_id: Number of aliases to unregister 1886a06ccd9cSCharles Keepax * 1887a06ccd9cSCharles Keepax * This helper function allows drivers to unregister several supply 1888a06ccd9cSCharles Keepax * aliases in one operation. 1889a06ccd9cSCharles Keepax */ 1890a06ccd9cSCharles Keepax void regulator_bulk_unregister_supply_alias(struct device *dev, 18919f8c0fe9SLee Jones const char *const *id, 1892a06ccd9cSCharles Keepax int num_id) 1893a06ccd9cSCharles Keepax { 1894a06ccd9cSCharles Keepax int i; 1895a06ccd9cSCharles Keepax 1896a06ccd9cSCharles Keepax for (i = 0; i < num_id; ++i) 1897a06ccd9cSCharles Keepax regulator_unregister_supply_alias(dev, id[i]); 1898a06ccd9cSCharles Keepax } 1899a06ccd9cSCharles Keepax EXPORT_SYMBOL_GPL(regulator_bulk_unregister_supply_alias); 1900a06ccd9cSCharles Keepax 1901a06ccd9cSCharles Keepax 1902f19b00daSKim, Milo /* Manage enable GPIO list. Same GPIO pin can be shared among regulators */ 1903f19b00daSKim, Milo static int regulator_ena_gpio_request(struct regulator_dev *rdev, 1904f19b00daSKim, Milo const struct regulator_config *config) 1905f19b00daSKim, Milo { 1906f19b00daSKim, Milo struct regulator_enable_gpio *pin; 1907778b28b4SRussell King struct gpio_desc *gpiod; 1908f19b00daSKim, Milo int ret; 1909f19b00daSKim, Milo 1910778b28b4SRussell King gpiod = gpio_to_desc(config->ena_gpio); 1911778b28b4SRussell King 1912f19b00daSKim, Milo list_for_each_entry(pin, ®ulator_ena_gpio_list, list) { 1913778b28b4SRussell King if (pin->gpiod == gpiod) { 1914f19b00daSKim, Milo rdev_dbg(rdev, "GPIO %d is already used\n", 1915f19b00daSKim, Milo config->ena_gpio); 1916f19b00daSKim, Milo goto update_ena_gpio_to_rdev; 1917f19b00daSKim, Milo } 1918f19b00daSKim, Milo } 1919f19b00daSKim, Milo 1920f19b00daSKim, Milo ret = gpio_request_one(config->ena_gpio, 1921f19b00daSKim, Milo GPIOF_DIR_OUT | config->ena_gpio_flags, 1922f19b00daSKim, Milo rdev_get_name(rdev)); 1923f19b00daSKim, Milo if (ret) 1924f19b00daSKim, Milo return ret; 1925f19b00daSKim, Milo 1926f19b00daSKim, Milo pin = kzalloc(sizeof(struct regulator_enable_gpio), GFP_KERNEL); 1927f19b00daSKim, Milo if (pin == NULL) { 1928f19b00daSKim, Milo gpio_free(config->ena_gpio); 1929f19b00daSKim, Milo return -ENOMEM; 1930f19b00daSKim, Milo } 1931f19b00daSKim, Milo 1932778b28b4SRussell King pin->gpiod = gpiod; 1933f19b00daSKim, Milo pin->ena_gpio_invert = config->ena_gpio_invert; 1934f19b00daSKim, Milo list_add(&pin->list, ®ulator_ena_gpio_list); 1935f19b00daSKim, Milo 1936f19b00daSKim, Milo update_ena_gpio_to_rdev: 1937f19b00daSKim, Milo pin->request_count++; 1938f19b00daSKim, Milo rdev->ena_pin = pin; 1939f19b00daSKim, Milo return 0; 1940f19b00daSKim, Milo } 1941f19b00daSKim, Milo 1942f19b00daSKim, Milo static void regulator_ena_gpio_free(struct regulator_dev *rdev) 1943f19b00daSKim, Milo { 1944f19b00daSKim, Milo struct regulator_enable_gpio *pin, *n; 1945f19b00daSKim, Milo 1946f19b00daSKim, Milo if (!rdev->ena_pin) 1947f19b00daSKim, Milo return; 1948f19b00daSKim, Milo 1949f19b00daSKim, Milo /* Free the GPIO only in case of no use */ 1950f19b00daSKim, Milo list_for_each_entry_safe(pin, n, ®ulator_ena_gpio_list, list) { 1951778b28b4SRussell King if (pin->gpiod == rdev->ena_pin->gpiod) { 1952f19b00daSKim, Milo if (pin->request_count <= 1) { 1953f19b00daSKim, Milo pin->request_count = 0; 1954778b28b4SRussell King gpiod_put(pin->gpiod); 1955f19b00daSKim, Milo list_del(&pin->list); 1956f19b00daSKim, Milo kfree(pin); 195760a2362fSSeung-Woo Kim rdev->ena_pin = NULL; 195860a2362fSSeung-Woo Kim return; 1959f19b00daSKim, Milo } else { 1960f19b00daSKim, Milo pin->request_count--; 1961f19b00daSKim, Milo } 1962f19b00daSKim, Milo } 1963f19b00daSKim, Milo } 1964f19b00daSKim, Milo } 1965f19b00daSKim, Milo 1966967cfb18SKim, Milo /** 196731d6eebfSRobert P. J. Day * regulator_ena_gpio_ctrl - balance enable_count of each GPIO and actual GPIO pin control 196831d6eebfSRobert P. J. Day * @rdev: regulator_dev structure 196931d6eebfSRobert P. J. Day * @enable: enable GPIO at initial use? 197031d6eebfSRobert P. J. Day * 1971967cfb18SKim, Milo * GPIO is enabled in case of initial use. (enable_count is 0) 1972967cfb18SKim, Milo * GPIO is disabled when it is not shared any more. (enable_count <= 1) 1973967cfb18SKim, Milo */ 1974967cfb18SKim, Milo static int regulator_ena_gpio_ctrl(struct regulator_dev *rdev, bool enable) 1975967cfb18SKim, Milo { 1976967cfb18SKim, Milo struct regulator_enable_gpio *pin = rdev->ena_pin; 1977967cfb18SKim, Milo 1978967cfb18SKim, Milo if (!pin) 1979967cfb18SKim, Milo return -EINVAL; 1980967cfb18SKim, Milo 1981967cfb18SKim, Milo if (enable) { 1982967cfb18SKim, Milo /* Enable GPIO at initial use */ 1983967cfb18SKim, Milo if (pin->enable_count == 0) 1984778b28b4SRussell King gpiod_set_value_cansleep(pin->gpiod, 1985967cfb18SKim, Milo !pin->ena_gpio_invert); 1986967cfb18SKim, Milo 1987967cfb18SKim, Milo pin->enable_count++; 1988967cfb18SKim, Milo } else { 1989967cfb18SKim, Milo if (pin->enable_count > 1) { 1990967cfb18SKim, Milo pin->enable_count--; 1991967cfb18SKim, Milo return 0; 1992967cfb18SKim, Milo } 1993967cfb18SKim, Milo 1994967cfb18SKim, Milo /* Disable GPIO if not used */ 1995967cfb18SKim, Milo if (pin->enable_count <= 1) { 1996778b28b4SRussell King gpiod_set_value_cansleep(pin->gpiod, 1997967cfb18SKim, Milo pin->ena_gpio_invert); 1998967cfb18SKim, Milo pin->enable_count = 0; 1999967cfb18SKim, Milo } 2000967cfb18SKim, Milo } 2001967cfb18SKim, Milo 2002967cfb18SKim, Milo return 0; 2003967cfb18SKim, Milo } 2004967cfb18SKim, Milo 200579fd1141SGuodong Xu /** 200679fd1141SGuodong Xu * _regulator_enable_delay - a delay helper function 200779fd1141SGuodong Xu * @delay: time to delay in microseconds 200879fd1141SGuodong Xu * 20095df529d4SThierry Reding * Delay for the requested amount of time as per the guidelines in: 20105df529d4SThierry Reding * 20115df529d4SThierry Reding * Documentation/timers/timers-howto.txt 20125df529d4SThierry Reding * 20135df529d4SThierry Reding * The assumption here is that regulators will never be enabled in 20145df529d4SThierry Reding * atomic context and therefore sleeping functions can be used. 20155df529d4SThierry Reding */ 201679fd1141SGuodong Xu static void _regulator_enable_delay(unsigned int delay) 201779fd1141SGuodong Xu { 20185df529d4SThierry Reding unsigned int ms = delay / 1000; 20195df529d4SThierry Reding unsigned int us = delay % 1000; 20205df529d4SThierry Reding 20215df529d4SThierry Reding if (ms > 0) { 20225df529d4SThierry Reding /* 20235df529d4SThierry Reding * For small enough values, handle super-millisecond 20245df529d4SThierry Reding * delays in the usleep_range() call below. 20255df529d4SThierry Reding */ 20265df529d4SThierry Reding if (ms < 20) 20275df529d4SThierry Reding us += ms * 1000; 20285df529d4SThierry Reding else 20295df529d4SThierry Reding msleep(ms); 20305df529d4SThierry Reding } 20315df529d4SThierry Reding 20325df529d4SThierry Reding /* 20335df529d4SThierry Reding * Give the scheduler some room to coalesce with any other 20345df529d4SThierry Reding * wakeup sources. For delays shorter than 10 us, don't even 20355df529d4SThierry Reding * bother setting up high-resolution timers and just busy- 20365df529d4SThierry Reding * loop. 20375df529d4SThierry Reding */ 20385df529d4SThierry Reding if (us >= 10) 20395df529d4SThierry Reding usleep_range(us, us + 100); 20405df529d4SThierry Reding else 20415df529d4SThierry Reding udelay(us); 20425c5659d0SMark Brown } 20435c5659d0SMark Brown 20445c5659d0SMark Brown static int _regulator_do_enable(struct regulator_dev *rdev) 20455c5659d0SMark Brown { 20465c5659d0SMark Brown int ret, delay; 20475c5659d0SMark Brown 20485c5659d0SMark Brown /* Query before enabling in case configuration dependent. */ 20495c5659d0SMark Brown ret = _regulator_get_enable_time(rdev); 20505c5659d0SMark Brown if (ret >= 0) { 20515c5659d0SMark Brown delay = ret; 20525c5659d0SMark Brown } else { 2053414c70cbSLiam Girdwood rdev_warn(rdev, "enable_time() failed: %d\n", ret); 2054414c70cbSLiam Girdwood delay = 0; 2055414c70cbSLiam Girdwood } 20565c5659d0SMark Brown 2057414c70cbSLiam Girdwood trace_regulator_enable(rdev_get_name(rdev)); 2058414c70cbSLiam Girdwood 2059871f5650SGuodong Xu if (rdev->desc->off_on_delay) { 2060871f5650SGuodong Xu /* if needed, keep a distance of off_on_delay from last time 2061871f5650SGuodong Xu * this regulator was disabled. 2062871f5650SGuodong Xu */ 2063871f5650SGuodong Xu unsigned long start_jiffy = jiffies; 2064871f5650SGuodong Xu unsigned long intended, max_delay, remaining; 2065871f5650SGuodong Xu 2066871f5650SGuodong Xu max_delay = usecs_to_jiffies(rdev->desc->off_on_delay); 2067871f5650SGuodong Xu intended = rdev->last_off_jiffy + max_delay; 2068871f5650SGuodong Xu 2069871f5650SGuodong Xu if (time_before(start_jiffy, intended)) { 2070871f5650SGuodong Xu /* calc remaining jiffies to deal with one-time 2071871f5650SGuodong Xu * timer wrapping. 2072871f5650SGuodong Xu * in case of multiple timer wrapping, either it can be 2073871f5650SGuodong Xu * detected by out-of-range remaining, or it cannot be 2074871f5650SGuodong Xu * detected and we gets a panelty of 2075871f5650SGuodong Xu * _regulator_enable_delay(). 2076871f5650SGuodong Xu */ 2077871f5650SGuodong Xu remaining = intended - start_jiffy; 2078871f5650SGuodong Xu if (remaining <= max_delay) 2079871f5650SGuodong Xu _regulator_enable_delay( 2080871f5650SGuodong Xu jiffies_to_usecs(remaining)); 2081871f5650SGuodong Xu } 2082871f5650SGuodong Xu } 2083871f5650SGuodong Xu 2084414c70cbSLiam Girdwood if (rdev->ena_pin) { 208529d62ec5SDoug Anderson if (!rdev->ena_gpio_state) { 20869a2372faSMark Brown ret = regulator_ena_gpio_ctrl(rdev, true); 2087414c70cbSLiam Girdwood if (ret < 0) 2088414c70cbSLiam Girdwood return ret; 20899a2372faSMark Brown rdev->ena_gpio_state = 1; 209029d62ec5SDoug Anderson } 20919a2372faSMark Brown } else if (rdev->desc->ops->enable) { 20929a2372faSMark Brown ret = rdev->desc->ops->enable(rdev); 20939a2372faSMark Brown if (ret < 0) 20949a2372faSMark Brown return ret; 20959a2372faSMark Brown } else { 20969a2372faSMark Brown return -EINVAL; 20975c5659d0SMark Brown } 20989a2372faSMark Brown 20999a2372faSMark Brown /* Allow the regulator to ramp; it would be useful to extend 210031aae2beSMark Brown * this for bulk operations so that the regulators can ramp 2101a7433cffSLinus Walleij * together. */ 21025da84fd9SJoe Perches trace_regulator_enable_delay(rdev_get_name(rdev)); 2103414c70cbSLiam Girdwood 210479fd1141SGuodong Xu _regulator_enable_delay(delay); 2105a7433cffSLinus Walleij 2106414c70cbSLiam Girdwood trace_regulator_enable_complete(rdev_get_name(rdev)); 2107414c70cbSLiam Girdwood 21089a2372faSMark Brown return 0; 21099a2372faSMark Brown } 21109a2372faSMark Brown 2111414c70cbSLiam Girdwood /* locks held by regulator_enable() */ 2112414c70cbSLiam Girdwood static int _regulator_enable(struct regulator_dev *rdev) 2113414c70cbSLiam Girdwood { 2114414c70cbSLiam Girdwood int ret; 2115414c70cbSLiam Girdwood 211670cfef26SKrzysztof Kozlowski lockdep_assert_held_once(&rdev->mutex); 211770cfef26SKrzysztof Kozlowski 2118414c70cbSLiam Girdwood /* check voltage and requested load before enabling */ 2119cf7bbcdfSMark Brown if (rdev->constraints && 2120cf7bbcdfSMark Brown (rdev->constraints->valid_ops_mask & REGULATOR_CHANGE_DRMS)) 2121cf7bbcdfSMark Brown drms_uA_update(rdev); 2122cf7bbcdfSMark Brown 2123414c70cbSLiam Girdwood if (rdev->use_count == 0) { 2124cf7bbcdfSMark Brown /* The regulator may on if it's not switchable or left on */ 2125414c70cbSLiam Girdwood ret = _regulator_is_enabled(rdev); 2126414c70cbSLiam Girdwood if (ret == -EINVAL || ret == 0) { 2127414c70cbSLiam Girdwood if (!_regulator_can_change_status(rdev)) 2128412aec61SDavid Brownell return -EPERM; 2129412aec61SDavid Brownell 2130414c70cbSLiam Girdwood ret = _regulator_do_enable(rdev); 2131412aec61SDavid Brownell if (ret < 0) 2132412aec61SDavid Brownell return ret; 2133412aec61SDavid Brownell 2134414c70cbSLiam Girdwood } else if (ret < 0) { 2135414c70cbSLiam Girdwood rdev_err(rdev, "is_enabled() failed: %d\n", ret); 2136414c70cbSLiam Girdwood return ret; 2137414c70cbSLiam Girdwood } 2138414c70cbSLiam Girdwood /* Fallthrough on positive return values - already enabled */ 2139414c70cbSLiam Girdwood } 2140414c70cbSLiam Girdwood 2141414c70cbSLiam Girdwood rdev->use_count++; 2142414c70cbSLiam Girdwood 2143cd94b505SDavid Brownell return 0; 2144cd94b505SDavid Brownell } 21451083c393SMark Brown 2146cd94b505SDavid Brownell /** 2147cd94b505SDavid Brownell * regulator_enable - enable regulator output 2148414c70cbSLiam Girdwood * @regulator: regulator source 214960ef66fcSMark Brown * 215060ef66fcSMark Brown * Request that the regulator be enabled with the regulator output at 2151414c70cbSLiam Girdwood * the predefined voltage or current value. Calls to regulator_enable() 2152414c70cbSLiam Girdwood * must be balanced with calls to regulator_disable(). 21539a2372faSMark Brown * 21549a2372faSMark Brown * NOTE: the output value can be set by other drivers, boot loader or may be 2155414c70cbSLiam Girdwood * hardwired in the regulator. 2156414c70cbSLiam Girdwood */ 2157414c70cbSLiam Girdwood int regulator_enable(struct regulator *regulator) 21581083c393SMark Brown { 2159414c70cbSLiam Girdwood struct regulator_dev *rdev = regulator->rdev; 2160414c70cbSLiam Girdwood int ret = 0; 216184b68263SMark Brown 21626492bc1bSMark Brown if (regulator->always_on) 21636492bc1bSMark Brown return 0; 21646492bc1bSMark Brown 21653801b86aSMark Brown if (rdev->supply) { 21663801b86aSMark Brown ret = regulator_enable(rdev->supply); 21673801b86aSMark Brown if (ret != 0) 21683801b86aSMark Brown return ret; 21693801b86aSMark Brown } 21703801b86aSMark Brown 2171414c70cbSLiam Girdwood mutex_lock(&rdev->mutex); 2172414c70cbSLiam Girdwood ret = _regulator_enable(rdev); 2173414c70cbSLiam Girdwood mutex_unlock(&rdev->mutex); 21743801b86aSMark Brown 2175d1685e4eSHeiko Stübner if (ret != 0 && rdev->supply) 21763801b86aSMark Brown regulator_disable(rdev->supply); 21773801b86aSMark Brown 2178414c70cbSLiam Girdwood return ret; 2179414c70cbSLiam Girdwood } 2180414c70cbSLiam Girdwood EXPORT_SYMBOL_GPL(regulator_enable); 2181414c70cbSLiam Girdwood 21825c5659d0SMark Brown static int _regulator_do_disable(struct regulator_dev *rdev) 21835c5659d0SMark Brown { 21845c5659d0SMark Brown int ret; 21855c5659d0SMark Brown 21865c5659d0SMark Brown trace_regulator_disable(rdev_get_name(rdev)); 21875c5659d0SMark Brown 2188967cfb18SKim, Milo if (rdev->ena_pin) { 218929d62ec5SDoug Anderson if (rdev->ena_gpio_state) { 2190967cfb18SKim, Milo ret = regulator_ena_gpio_ctrl(rdev, false); 2191967cfb18SKim, Milo if (ret < 0) 2192967cfb18SKim, Milo return ret; 21935c5659d0SMark Brown rdev->ena_gpio_state = 0; 219429d62ec5SDoug Anderson } 21955c5659d0SMark Brown 21965c5659d0SMark Brown } else if (rdev->desc->ops->disable) { 21975c5659d0SMark Brown ret = rdev->desc->ops->disable(rdev); 21985c5659d0SMark Brown if (ret != 0) 21995c5659d0SMark Brown return ret; 22005c5659d0SMark Brown } 22015c5659d0SMark Brown 2202871f5650SGuodong Xu /* cares about last_off_jiffy only if off_on_delay is required by 2203871f5650SGuodong Xu * device. 2204871f5650SGuodong Xu */ 2205871f5650SGuodong Xu if (rdev->desc->off_on_delay) 2206871f5650SGuodong Xu rdev->last_off_jiffy = jiffies; 2207871f5650SGuodong Xu 22085c5659d0SMark Brown trace_regulator_disable_complete(rdev_get_name(rdev)); 22095c5659d0SMark Brown 22105c5659d0SMark Brown return 0; 22115c5659d0SMark Brown } 22125c5659d0SMark Brown 2213414c70cbSLiam Girdwood /* locks held by regulator_disable() */ 22143801b86aSMark Brown static int _regulator_disable(struct regulator_dev *rdev) 2215414c70cbSLiam Girdwood { 2216414c70cbSLiam Girdwood int ret = 0; 2217414c70cbSLiam Girdwood 221870cfef26SKrzysztof Kozlowski lockdep_assert_held_once(&rdev->mutex); 221970cfef26SKrzysztof Kozlowski 2220414c70cbSLiam Girdwood if (WARN(rdev->use_count <= 0, 222143e7ee33SJoe Perches "unbalanced disables for %s\n", rdev_get_name(rdev))) 2222414c70cbSLiam Girdwood return -EIO; 2223414c70cbSLiam Girdwood 2224414c70cbSLiam Girdwood /* are we the last user and permitted to disable ? */ 2225414c70cbSLiam Girdwood if (rdev->use_count == 1 && 2226414c70cbSLiam Girdwood (rdev->constraints && !rdev->constraints->always_on)) { 2227414c70cbSLiam Girdwood 2228414c70cbSLiam Girdwood /* we are last user */ 22295c5659d0SMark Brown if (_regulator_can_change_status(rdev)) { 2230a1c8a551SRichard Fitzgerald ret = _notifier_call_chain(rdev, 2231a1c8a551SRichard Fitzgerald REGULATOR_EVENT_PRE_DISABLE, 2232a1c8a551SRichard Fitzgerald NULL); 2233a1c8a551SRichard Fitzgerald if (ret & NOTIFY_STOP_MASK) 2234a1c8a551SRichard Fitzgerald return -EINVAL; 2235a1c8a551SRichard Fitzgerald 22365c5659d0SMark Brown ret = _regulator_do_disable(rdev); 2237414c70cbSLiam Girdwood if (ret < 0) { 22385da84fd9SJoe Perches rdev_err(rdev, "failed to disable\n"); 2239a1c8a551SRichard Fitzgerald _notifier_call_chain(rdev, 2240a1c8a551SRichard Fitzgerald REGULATOR_EVENT_ABORT_DISABLE, 2241a1c8a551SRichard Fitzgerald NULL); 2242414c70cbSLiam Girdwood return ret; 2243414c70cbSLiam Girdwood } 224466fda75fSMarkus Pargmann _notifier_call_chain(rdev, REGULATOR_EVENT_DISABLE, 224566fda75fSMarkus Pargmann NULL); 2246414c70cbSLiam Girdwood } 2247414c70cbSLiam Girdwood 2248414c70cbSLiam Girdwood rdev->use_count = 0; 2249414c70cbSLiam Girdwood } else if (rdev->use_count > 1) { 2250414c70cbSLiam Girdwood 2251414c70cbSLiam Girdwood if (rdev->constraints && 2252414c70cbSLiam Girdwood (rdev->constraints->valid_ops_mask & 2253414c70cbSLiam Girdwood REGULATOR_CHANGE_DRMS)) 2254414c70cbSLiam Girdwood drms_uA_update(rdev); 2255414c70cbSLiam Girdwood 2256414c70cbSLiam Girdwood rdev->use_count--; 2257414c70cbSLiam Girdwood } 22583801b86aSMark Brown 2259414c70cbSLiam Girdwood return ret; 2260414c70cbSLiam Girdwood } 2261414c70cbSLiam Girdwood 2262414c70cbSLiam Girdwood /** 2263414c70cbSLiam Girdwood * regulator_disable - disable regulator output 2264414c70cbSLiam Girdwood * @regulator: regulator source 2265414c70cbSLiam Girdwood * 2266cf7bbcdfSMark Brown * Disable the regulator output voltage or current. Calls to 2267cf7bbcdfSMark Brown * regulator_enable() must be balanced with calls to 2268cf7bbcdfSMark Brown * regulator_disable(). 226969279fb9SMark Brown * 2270414c70cbSLiam Girdwood * NOTE: this will only disable the regulator output if no other consumer 2271cf7bbcdfSMark Brown * devices have it enabled, the regulator device supports disabling and 2272cf7bbcdfSMark Brown * machine constraints permit this operation. 2273414c70cbSLiam Girdwood */ 2274414c70cbSLiam Girdwood int regulator_disable(struct regulator *regulator) 2275414c70cbSLiam Girdwood { 2276412aec61SDavid Brownell struct regulator_dev *rdev = regulator->rdev; 2277412aec61SDavid Brownell int ret = 0; 2278414c70cbSLiam Girdwood 22796492bc1bSMark Brown if (regulator->always_on) 22806492bc1bSMark Brown return 0; 22816492bc1bSMark Brown 2282412aec61SDavid Brownell mutex_lock(&rdev->mutex); 22833801b86aSMark Brown ret = _regulator_disable(rdev); 2284412aec61SDavid Brownell mutex_unlock(&rdev->mutex); 22858cbf811dSJeffrey Carlyle 22863801b86aSMark Brown if (ret == 0 && rdev->supply) 22873801b86aSMark Brown regulator_disable(rdev->supply); 22888cbf811dSJeffrey Carlyle 2289414c70cbSLiam Girdwood return ret; 2290414c70cbSLiam Girdwood } 2291414c70cbSLiam Girdwood EXPORT_SYMBOL_GPL(regulator_disable); 2292414c70cbSLiam Girdwood 2293414c70cbSLiam Girdwood /* locks held by regulator_force_disable() */ 22943801b86aSMark Brown static int _regulator_force_disable(struct regulator_dev *rdev) 2295414c70cbSLiam Girdwood { 2296414c70cbSLiam Girdwood int ret = 0; 2297414c70cbSLiam Girdwood 229870cfef26SKrzysztof Kozlowski lockdep_assert_held_once(&rdev->mutex); 229970cfef26SKrzysztof Kozlowski 2300a1c8a551SRichard Fitzgerald ret = _notifier_call_chain(rdev, REGULATOR_EVENT_FORCE_DISABLE | 2301a1c8a551SRichard Fitzgerald REGULATOR_EVENT_PRE_DISABLE, NULL); 2302a1c8a551SRichard Fitzgerald if (ret & NOTIFY_STOP_MASK) 2303a1c8a551SRichard Fitzgerald return -EINVAL; 2304a1c8a551SRichard Fitzgerald 230566fda75fSMarkus Pargmann ret = _regulator_do_disable(rdev); 2306414c70cbSLiam Girdwood if (ret < 0) { 23075da84fd9SJoe Perches rdev_err(rdev, "failed to force disable\n"); 2308a1c8a551SRichard Fitzgerald _notifier_call_chain(rdev, REGULATOR_EVENT_FORCE_DISABLE | 2309a1c8a551SRichard Fitzgerald REGULATOR_EVENT_ABORT_DISABLE, NULL); 2310414c70cbSLiam Girdwood return ret; 2311414c70cbSLiam Girdwood } 231266fda75fSMarkus Pargmann 231384b68263SMark Brown _notifier_call_chain(rdev, REGULATOR_EVENT_FORCE_DISABLE | 231484b68263SMark Brown REGULATOR_EVENT_DISABLE, NULL); 2315414c70cbSLiam Girdwood 231666fda75fSMarkus Pargmann return 0; 2317414c70cbSLiam Girdwood } 2318414c70cbSLiam Girdwood 2319414c70cbSLiam Girdwood /** 2320414c70cbSLiam Girdwood * regulator_force_disable - force disable regulator output 2321414c70cbSLiam Girdwood * @regulator: regulator source 2322414c70cbSLiam Girdwood * 2323414c70cbSLiam Girdwood * Forcibly disable the regulator output voltage or current. 2324414c70cbSLiam Girdwood * NOTE: this *will* disable the regulator output even if other consumer 2325414c70cbSLiam Girdwood * devices have it enabled. This should be used for situations when device 2326414c70cbSLiam Girdwood * damage will likely occur if the regulator is not disabled (e.g. over temp). 2327414c70cbSLiam Girdwood */ 2328414c70cbSLiam Girdwood int regulator_force_disable(struct regulator *regulator) 2329414c70cbSLiam Girdwood { 233082d15839SMark Brown struct regulator_dev *rdev = regulator->rdev; 2331414c70cbSLiam Girdwood int ret; 2332414c70cbSLiam Girdwood 233382d15839SMark Brown mutex_lock(&rdev->mutex); 2334414c70cbSLiam Girdwood regulator->uA_load = 0; 23353801b86aSMark Brown ret = _regulator_force_disable(regulator->rdev); 233682d15839SMark Brown mutex_unlock(&rdev->mutex); 23378cbf811dSJeffrey Carlyle 23383801b86aSMark Brown if (rdev->supply) 23393801b86aSMark Brown while (rdev->open_count--) 23403801b86aSMark Brown regulator_disable(rdev->supply); 23418cbf811dSJeffrey Carlyle 2342414c70cbSLiam Girdwood return ret; 2343414c70cbSLiam Girdwood } 2344414c70cbSLiam Girdwood EXPORT_SYMBOL_GPL(regulator_force_disable); 2345414c70cbSLiam Girdwood 2346da07ecd9SMark Brown static void regulator_disable_work(struct work_struct *work) 2347da07ecd9SMark Brown { 2348da07ecd9SMark Brown struct regulator_dev *rdev = container_of(work, struct regulator_dev, 2349da07ecd9SMark Brown disable_work.work); 2350da07ecd9SMark Brown int count, i, ret; 2351da07ecd9SMark Brown 2352da07ecd9SMark Brown mutex_lock(&rdev->mutex); 2353da07ecd9SMark Brown 2354da07ecd9SMark Brown BUG_ON(!rdev->deferred_disables); 2355da07ecd9SMark Brown 2356da07ecd9SMark Brown count = rdev->deferred_disables; 2357da07ecd9SMark Brown rdev->deferred_disables = 0; 2358da07ecd9SMark Brown 2359da07ecd9SMark Brown for (i = 0; i < count; i++) { 2360da07ecd9SMark Brown ret = _regulator_disable(rdev); 2361da07ecd9SMark Brown if (ret != 0) 2362da07ecd9SMark Brown rdev_err(rdev, "Deferred disable failed: %d\n", ret); 2363da07ecd9SMark Brown } 2364da07ecd9SMark Brown 2365da07ecd9SMark Brown mutex_unlock(&rdev->mutex); 2366da07ecd9SMark Brown 2367da07ecd9SMark Brown if (rdev->supply) { 2368da07ecd9SMark Brown for (i = 0; i < count; i++) { 2369da07ecd9SMark Brown ret = regulator_disable(rdev->supply); 2370da07ecd9SMark Brown if (ret != 0) { 2371da07ecd9SMark Brown rdev_err(rdev, 2372da07ecd9SMark Brown "Supply disable failed: %d\n", ret); 2373da07ecd9SMark Brown } 2374da07ecd9SMark Brown } 2375da07ecd9SMark Brown } 2376da07ecd9SMark Brown } 2377da07ecd9SMark Brown 2378da07ecd9SMark Brown /** 2379da07ecd9SMark Brown * regulator_disable_deferred - disable regulator output with delay 2380da07ecd9SMark Brown * @regulator: regulator source 2381da07ecd9SMark Brown * @ms: miliseconds until the regulator is disabled 2382da07ecd9SMark Brown * 2383da07ecd9SMark Brown * Execute regulator_disable() on the regulator after a delay. This 2384da07ecd9SMark Brown * is intended for use with devices that require some time to quiesce. 2385da07ecd9SMark Brown * 2386da07ecd9SMark Brown * NOTE: this will only disable the regulator output if no other consumer 2387da07ecd9SMark Brown * devices have it enabled, the regulator device supports disabling and 2388da07ecd9SMark Brown * machine constraints permit this operation. 2389da07ecd9SMark Brown */ 2390da07ecd9SMark Brown int regulator_disable_deferred(struct regulator *regulator, int ms) 2391da07ecd9SMark Brown { 2392da07ecd9SMark Brown struct regulator_dev *rdev = regulator->rdev; 2393da07ecd9SMark Brown 23946492bc1bSMark Brown if (regulator->always_on) 23956492bc1bSMark Brown return 0; 23966492bc1bSMark Brown 23972b5a24a0SMark Brown if (!ms) 23982b5a24a0SMark Brown return regulator_disable(regulator); 23992b5a24a0SMark Brown 2400da07ecd9SMark Brown mutex_lock(&rdev->mutex); 2401da07ecd9SMark Brown rdev->deferred_disables++; 2402da07ecd9SMark Brown mutex_unlock(&rdev->mutex); 2403da07ecd9SMark Brown 240470dc6dafSDan Carpenter queue_delayed_work(system_power_efficient_wq, &rdev->disable_work, 2405da07ecd9SMark Brown msecs_to_jiffies(ms)); 2406aa59802dSMark Brown return 0; 2407da07ecd9SMark Brown } 2408da07ecd9SMark Brown EXPORT_SYMBOL_GPL(regulator_disable_deferred); 2409da07ecd9SMark Brown 2410414c70cbSLiam Girdwood static int _regulator_is_enabled(struct regulator_dev *rdev) 2411414c70cbSLiam Girdwood { 241265f73508SMark Brown /* A GPIO control always takes precedence */ 24137b74d149SKim, Milo if (rdev->ena_pin) 241465f73508SMark Brown return rdev->ena_gpio_state; 241565f73508SMark Brown 24169a7f6a4cSMark Brown /* If we don't know then assume that the regulator is always on */ 24179332546fSMark Brown if (!rdev->desc->ops->is_enabled) 24189a7f6a4cSMark Brown return 1; 2419414c70cbSLiam Girdwood 24209332546fSMark Brown return rdev->desc->ops->is_enabled(rdev); 2421414c70cbSLiam Girdwood } 2422414c70cbSLiam Girdwood 24233a40cfc3SSascha Hauer static int _regulator_list_voltage(struct regulator *regulator, 24243a40cfc3SSascha Hauer unsigned selector, int lock) 24253a40cfc3SSascha Hauer { 24263a40cfc3SSascha Hauer struct regulator_dev *rdev = regulator->rdev; 24273a40cfc3SSascha Hauer const struct regulator_ops *ops = rdev->desc->ops; 24283a40cfc3SSascha Hauer int ret; 24293a40cfc3SSascha Hauer 24303a40cfc3SSascha Hauer if (rdev->desc->fixed_uV && rdev->desc->n_voltages == 1 && !selector) 24313a40cfc3SSascha Hauer return rdev->desc->fixed_uV; 24323a40cfc3SSascha Hauer 24333a40cfc3SSascha Hauer if (ops->list_voltage) { 24343a40cfc3SSascha Hauer if (selector >= rdev->desc->n_voltages) 24353a40cfc3SSascha Hauer return -EINVAL; 24363a40cfc3SSascha Hauer if (lock) 24373a40cfc3SSascha Hauer mutex_lock(&rdev->mutex); 24383a40cfc3SSascha Hauer ret = ops->list_voltage(rdev, selector); 24393a40cfc3SSascha Hauer if (lock) 24403a40cfc3SSascha Hauer mutex_unlock(&rdev->mutex); 24413a40cfc3SSascha Hauer } else if (rdev->supply) { 24423a40cfc3SSascha Hauer ret = _regulator_list_voltage(rdev->supply, selector, lock); 24433a40cfc3SSascha Hauer } else { 24443a40cfc3SSascha Hauer return -EINVAL; 24453a40cfc3SSascha Hauer } 24463a40cfc3SSascha Hauer 24473a40cfc3SSascha Hauer if (ret > 0) { 24483a40cfc3SSascha Hauer if (ret < rdev->constraints->min_uV) 24493a40cfc3SSascha Hauer ret = 0; 24503a40cfc3SSascha Hauer else if (ret > rdev->constraints->max_uV) 24513a40cfc3SSascha Hauer ret = 0; 24523a40cfc3SSascha Hauer } 24533a40cfc3SSascha Hauer 24543a40cfc3SSascha Hauer return ret; 24553a40cfc3SSascha Hauer } 24563a40cfc3SSascha Hauer 2457414c70cbSLiam Girdwood /** 2458414c70cbSLiam Girdwood * regulator_is_enabled - is the regulator output enabled 2459414c70cbSLiam Girdwood * @regulator: regulator source 2460414c70cbSLiam Girdwood * 2461412aec61SDavid Brownell * Returns positive if the regulator driver backing the source/client 2462412aec61SDavid Brownell * has requested that the device be enabled, zero if it hasn't, else a 2463412aec61SDavid Brownell * negative errno code. 2464412aec61SDavid Brownell * 2465412aec61SDavid Brownell * Note that the device backing this regulator handle can have multiple 2466412aec61SDavid Brownell * users, so it might be enabled even if regulator_enable() was never 2467412aec61SDavid Brownell * called for this particular source. 2468414c70cbSLiam Girdwood */ 2469414c70cbSLiam Girdwood int regulator_is_enabled(struct regulator *regulator) 2470414c70cbSLiam Girdwood { 24719332546fSMark Brown int ret; 24729332546fSMark Brown 24736492bc1bSMark Brown if (regulator->always_on) 24746492bc1bSMark Brown return 1; 24756492bc1bSMark Brown 24769332546fSMark Brown mutex_lock(®ulator->rdev->mutex); 24779332546fSMark Brown ret = _regulator_is_enabled(regulator->rdev); 24789332546fSMark Brown mutex_unlock(®ulator->rdev->mutex); 24799332546fSMark Brown 24809332546fSMark Brown return ret; 2481414c70cbSLiam Girdwood } 2482414c70cbSLiam Girdwood EXPORT_SYMBOL_GPL(regulator_is_enabled); 2483414c70cbSLiam Girdwood 2484414c70cbSLiam Girdwood /** 2485d1e7de30SMarek Szyprowski * regulator_can_change_voltage - check if regulator can change voltage 2486d1e7de30SMarek Szyprowski * @regulator: regulator source 2487d1e7de30SMarek Szyprowski * 2488d1e7de30SMarek Szyprowski * Returns positive if the regulator driver backing the source/client 2489e227867fSMasanari Iida * can change its voltage, false otherwise. Useful for detecting fixed 2490d1e7de30SMarek Szyprowski * or dummy regulators and disabling voltage change logic in the client 2491d1e7de30SMarek Szyprowski * driver. 2492d1e7de30SMarek Szyprowski */ 2493d1e7de30SMarek Szyprowski int regulator_can_change_voltage(struct regulator *regulator) 2494d1e7de30SMarek Szyprowski { 2495d1e7de30SMarek Szyprowski struct regulator_dev *rdev = regulator->rdev; 2496d1e7de30SMarek Szyprowski 2497d1e7de30SMarek Szyprowski if (rdev->constraints && 249819280e40SAxel Lin (rdev->constraints->valid_ops_mask & REGULATOR_CHANGE_VOLTAGE)) { 249919280e40SAxel Lin if (rdev->desc->n_voltages - rdev->desc->linear_min_sel > 1) 2500d1e7de30SMarek Szyprowski return 1; 2501d1e7de30SMarek Szyprowski 250219280e40SAxel Lin if (rdev->desc->continuous_voltage_range && 250319280e40SAxel Lin rdev->constraints->min_uV && rdev->constraints->max_uV && 250419280e40SAxel Lin rdev->constraints->min_uV != rdev->constraints->max_uV) 250519280e40SAxel Lin return 1; 250619280e40SAxel Lin } 250719280e40SAxel Lin 2508d1e7de30SMarek Szyprowski return 0; 2509d1e7de30SMarek Szyprowski } 2510d1e7de30SMarek Szyprowski EXPORT_SYMBOL_GPL(regulator_can_change_voltage); 2511d1e7de30SMarek Szyprowski 2512d1e7de30SMarek Szyprowski /** 25134367cfdcSDavid Brownell * regulator_count_voltages - count regulator_list_voltage() selectors 25144367cfdcSDavid Brownell * @regulator: regulator source 25154367cfdcSDavid Brownell * 25164367cfdcSDavid Brownell * Returns number of selectors, or negative errno. Selectors are 25174367cfdcSDavid Brownell * numbered starting at zero, and typically correspond to bitfields 25184367cfdcSDavid Brownell * in hardware registers. 25194367cfdcSDavid Brownell */ 25204367cfdcSDavid Brownell int regulator_count_voltages(struct regulator *regulator) 25214367cfdcSDavid Brownell { 25224367cfdcSDavid Brownell struct regulator_dev *rdev = regulator->rdev; 25234367cfdcSDavid Brownell 252426988efeSJavier Martinez Canillas if (rdev->desc->n_voltages) 252526988efeSJavier Martinez Canillas return rdev->desc->n_voltages; 252626988efeSJavier Martinez Canillas 252726988efeSJavier Martinez Canillas if (!rdev->supply) 252826988efeSJavier Martinez Canillas return -EINVAL; 252926988efeSJavier Martinez Canillas 253026988efeSJavier Martinez Canillas return regulator_count_voltages(rdev->supply); 25314367cfdcSDavid Brownell } 25324367cfdcSDavid Brownell EXPORT_SYMBOL_GPL(regulator_count_voltages); 25334367cfdcSDavid Brownell 25344367cfdcSDavid Brownell /** 25354367cfdcSDavid Brownell * regulator_list_voltage - enumerate supported voltages 25364367cfdcSDavid Brownell * @regulator: regulator source 25374367cfdcSDavid Brownell * @selector: identify voltage to list 25384367cfdcSDavid Brownell * Context: can sleep 25394367cfdcSDavid Brownell * 25404367cfdcSDavid Brownell * Returns a voltage that can be passed to @regulator_set_voltage(), 254188393161SThomas Weber * zero if this selector code can't be used on this system, or a 25424367cfdcSDavid Brownell * negative errno. 25434367cfdcSDavid Brownell */ 25444367cfdcSDavid Brownell int regulator_list_voltage(struct regulator *regulator, unsigned selector) 25454367cfdcSDavid Brownell { 25463a40cfc3SSascha Hauer return _regulator_list_voltage(regulator, selector, 1); 25474367cfdcSDavid Brownell } 25484367cfdcSDavid Brownell EXPORT_SYMBOL_GPL(regulator_list_voltage); 25494367cfdcSDavid Brownell 25504367cfdcSDavid Brownell /** 255104eca28cSTuomas Tynkkynen * regulator_get_regmap - get the regulator's register map 255204eca28cSTuomas Tynkkynen * @regulator: regulator source 255304eca28cSTuomas Tynkkynen * 255404eca28cSTuomas Tynkkynen * Returns the register map for the given regulator, or an ERR_PTR value 255504eca28cSTuomas Tynkkynen * if the regulator doesn't use regmap. 255604eca28cSTuomas Tynkkynen */ 255704eca28cSTuomas Tynkkynen struct regmap *regulator_get_regmap(struct regulator *regulator) 255804eca28cSTuomas Tynkkynen { 255904eca28cSTuomas Tynkkynen struct regmap *map = regulator->rdev->regmap; 256004eca28cSTuomas Tynkkynen 256104eca28cSTuomas Tynkkynen return map ? map : ERR_PTR(-EOPNOTSUPP); 256204eca28cSTuomas Tynkkynen } 256304eca28cSTuomas Tynkkynen 256404eca28cSTuomas Tynkkynen /** 256504eca28cSTuomas Tynkkynen * regulator_get_hardware_vsel_register - get the HW voltage selector register 256604eca28cSTuomas Tynkkynen * @regulator: regulator source 256704eca28cSTuomas Tynkkynen * @vsel_reg: voltage selector register, output parameter 256804eca28cSTuomas Tynkkynen * @vsel_mask: mask for voltage selector bitfield, output parameter 256904eca28cSTuomas Tynkkynen * 257004eca28cSTuomas Tynkkynen * Returns the hardware register offset and bitmask used for setting the 257104eca28cSTuomas Tynkkynen * regulator voltage. This might be useful when configuring voltage-scaling 257204eca28cSTuomas Tynkkynen * hardware or firmware that can make I2C requests behind the kernel's back, 257304eca28cSTuomas Tynkkynen * for example. 257404eca28cSTuomas Tynkkynen * 257504eca28cSTuomas Tynkkynen * On success, the output parameters @vsel_reg and @vsel_mask are filled in 257604eca28cSTuomas Tynkkynen * and 0 is returned, otherwise a negative errno is returned. 257704eca28cSTuomas Tynkkynen */ 257804eca28cSTuomas Tynkkynen int regulator_get_hardware_vsel_register(struct regulator *regulator, 257904eca28cSTuomas Tynkkynen unsigned *vsel_reg, 258004eca28cSTuomas Tynkkynen unsigned *vsel_mask) 258104eca28cSTuomas Tynkkynen { 258204eca28cSTuomas Tynkkynen struct regulator_dev *rdev = regulator->rdev; 258339f5460dSGuodong Xu const struct regulator_ops *ops = rdev->desc->ops; 258404eca28cSTuomas Tynkkynen 258504eca28cSTuomas Tynkkynen if (ops->set_voltage_sel != regulator_set_voltage_sel_regmap) 258604eca28cSTuomas Tynkkynen return -EOPNOTSUPP; 258704eca28cSTuomas Tynkkynen 258804eca28cSTuomas Tynkkynen *vsel_reg = rdev->desc->vsel_reg; 258904eca28cSTuomas Tynkkynen *vsel_mask = rdev->desc->vsel_mask; 259004eca28cSTuomas Tynkkynen 259104eca28cSTuomas Tynkkynen return 0; 259204eca28cSTuomas Tynkkynen } 259304eca28cSTuomas Tynkkynen EXPORT_SYMBOL_GPL(regulator_get_hardware_vsel_register); 259404eca28cSTuomas Tynkkynen 259504eca28cSTuomas Tynkkynen /** 259604eca28cSTuomas Tynkkynen * regulator_list_hardware_vsel - get the HW-specific register value for a selector 259704eca28cSTuomas Tynkkynen * @regulator: regulator source 259804eca28cSTuomas Tynkkynen * @selector: identify voltage to list 259904eca28cSTuomas Tynkkynen * 260004eca28cSTuomas Tynkkynen * Converts the selector to a hardware-specific voltage selector that can be 260104eca28cSTuomas Tynkkynen * directly written to the regulator registers. The address of the voltage 260204eca28cSTuomas Tynkkynen * register can be determined by calling @regulator_get_hardware_vsel_register. 260304eca28cSTuomas Tynkkynen * 260404eca28cSTuomas Tynkkynen * On error a negative errno is returned. 260504eca28cSTuomas Tynkkynen */ 260604eca28cSTuomas Tynkkynen int regulator_list_hardware_vsel(struct regulator *regulator, 260704eca28cSTuomas Tynkkynen unsigned selector) 260804eca28cSTuomas Tynkkynen { 260904eca28cSTuomas Tynkkynen struct regulator_dev *rdev = regulator->rdev; 261039f5460dSGuodong Xu const struct regulator_ops *ops = rdev->desc->ops; 261104eca28cSTuomas Tynkkynen 261204eca28cSTuomas Tynkkynen if (selector >= rdev->desc->n_voltages) 261304eca28cSTuomas Tynkkynen return -EINVAL; 261404eca28cSTuomas Tynkkynen if (ops->set_voltage_sel != regulator_set_voltage_sel_regmap) 261504eca28cSTuomas Tynkkynen return -EOPNOTSUPP; 261604eca28cSTuomas Tynkkynen 261704eca28cSTuomas Tynkkynen return selector; 261804eca28cSTuomas Tynkkynen } 261904eca28cSTuomas Tynkkynen EXPORT_SYMBOL_GPL(regulator_list_hardware_vsel); 262004eca28cSTuomas Tynkkynen 262104eca28cSTuomas Tynkkynen /** 26222a668a8bSPaul Walmsley * regulator_get_linear_step - return the voltage step size between VSEL values 26232a668a8bSPaul Walmsley * @regulator: regulator source 26242a668a8bSPaul Walmsley * 26252a668a8bSPaul Walmsley * Returns the voltage step size between VSEL values for linear 26262a668a8bSPaul Walmsley * regulators, or return 0 if the regulator isn't a linear regulator. 26272a668a8bSPaul Walmsley */ 26282a668a8bSPaul Walmsley unsigned int regulator_get_linear_step(struct regulator *regulator) 26292a668a8bSPaul Walmsley { 26302a668a8bSPaul Walmsley struct regulator_dev *rdev = regulator->rdev; 26312a668a8bSPaul Walmsley 26322a668a8bSPaul Walmsley return rdev->desc->uV_step; 26332a668a8bSPaul Walmsley } 26342a668a8bSPaul Walmsley EXPORT_SYMBOL_GPL(regulator_get_linear_step); 26352a668a8bSPaul Walmsley 26362a668a8bSPaul Walmsley /** 2637a7a1ad90SMark Brown * regulator_is_supported_voltage - check if a voltage range can be supported 2638a7a1ad90SMark Brown * 2639a7a1ad90SMark Brown * @regulator: Regulator to check. 2640a7a1ad90SMark Brown * @min_uV: Minimum required voltage in uV. 2641a7a1ad90SMark Brown * @max_uV: Maximum required voltage in uV. 2642a7a1ad90SMark Brown * 2643a7a1ad90SMark Brown * Returns a boolean or a negative error code. 2644a7a1ad90SMark Brown */ 2645a7a1ad90SMark Brown int regulator_is_supported_voltage(struct regulator *regulator, 2646a7a1ad90SMark Brown int min_uV, int max_uV) 2647a7a1ad90SMark Brown { 2648c5f3939bSMark Brown struct regulator_dev *rdev = regulator->rdev; 2649a7a1ad90SMark Brown int i, voltages, ret; 2650a7a1ad90SMark Brown 2651c5f3939bSMark Brown /* If we can't change voltage check the current voltage */ 2652c5f3939bSMark Brown if (!(rdev->constraints->valid_ops_mask & REGULATOR_CHANGE_VOLTAGE)) { 2653c5f3939bSMark Brown ret = regulator_get_voltage(regulator); 2654c5f3939bSMark Brown if (ret >= 0) 26550d25d09dSJingoo Han return min_uV <= ret && ret <= max_uV; 2656c5f3939bSMark Brown else 2657c5f3939bSMark Brown return ret; 2658c5f3939bSMark Brown } 2659c5f3939bSMark Brown 2660bd7a2b60SPawel Moll /* Any voltage within constrains range is fine? */ 2661bd7a2b60SPawel Moll if (rdev->desc->continuous_voltage_range) 2662bd7a2b60SPawel Moll return min_uV >= rdev->constraints->min_uV && 2663bd7a2b60SPawel Moll max_uV <= rdev->constraints->max_uV; 2664bd7a2b60SPawel Moll 2665a7a1ad90SMark Brown ret = regulator_count_voltages(regulator); 2666a7a1ad90SMark Brown if (ret < 0) 2667a7a1ad90SMark Brown return ret; 2668a7a1ad90SMark Brown voltages = ret; 2669a7a1ad90SMark Brown 2670a7a1ad90SMark Brown for (i = 0; i < voltages; i++) { 2671a7a1ad90SMark Brown ret = regulator_list_voltage(regulator, i); 2672a7a1ad90SMark Brown 2673a7a1ad90SMark Brown if (ret >= min_uV && ret <= max_uV) 2674a7a1ad90SMark Brown return 1; 2675a7a1ad90SMark Brown } 2676a7a1ad90SMark Brown 2677a7a1ad90SMark Brown return 0; 2678a7a1ad90SMark Brown } 2679a398eaa2SMark Brown EXPORT_SYMBOL_GPL(regulator_is_supported_voltage); 2680a7a1ad90SMark Brown 2681a204f41eSSascha Hauer static int regulator_map_voltage(struct regulator_dev *rdev, int min_uV, 2682a204f41eSSascha Hauer int max_uV) 2683a204f41eSSascha Hauer { 2684a204f41eSSascha Hauer const struct regulator_desc *desc = rdev->desc; 2685a204f41eSSascha Hauer 2686a204f41eSSascha Hauer if (desc->ops->map_voltage) 2687a204f41eSSascha Hauer return desc->ops->map_voltage(rdev, min_uV, max_uV); 2688a204f41eSSascha Hauer 2689a204f41eSSascha Hauer if (desc->ops->list_voltage == regulator_list_voltage_linear) 2690a204f41eSSascha Hauer return regulator_map_voltage_linear(rdev, min_uV, max_uV); 2691a204f41eSSascha Hauer 2692a204f41eSSascha Hauer if (desc->ops->list_voltage == regulator_list_voltage_linear_range) 2693a204f41eSSascha Hauer return regulator_map_voltage_linear_range(rdev, min_uV, max_uV); 2694a204f41eSSascha Hauer 2695a204f41eSSascha Hauer return regulator_map_voltage_iterate(rdev, min_uV, max_uV); 2696a204f41eSSascha Hauer } 2697a204f41eSSascha Hauer 26987179569aSHeiko Stübner static int _regulator_call_set_voltage(struct regulator_dev *rdev, 26997179569aSHeiko Stübner int min_uV, int max_uV, 27007179569aSHeiko Stübner unsigned *selector) 27017179569aSHeiko Stübner { 27027179569aSHeiko Stübner struct pre_voltage_change_data data; 27037179569aSHeiko Stübner int ret; 27047179569aSHeiko Stübner 27057179569aSHeiko Stübner data.old_uV = _regulator_get_voltage(rdev); 27067179569aSHeiko Stübner data.min_uV = min_uV; 27077179569aSHeiko Stübner data.max_uV = max_uV; 27087179569aSHeiko Stübner ret = _notifier_call_chain(rdev, REGULATOR_EVENT_PRE_VOLTAGE_CHANGE, 27097179569aSHeiko Stübner &data); 27107179569aSHeiko Stübner if (ret & NOTIFY_STOP_MASK) 27117179569aSHeiko Stübner return -EINVAL; 27127179569aSHeiko Stübner 27137179569aSHeiko Stübner ret = rdev->desc->ops->set_voltage(rdev, min_uV, max_uV, selector); 27147179569aSHeiko Stübner if (ret >= 0) 27157179569aSHeiko Stübner return ret; 27167179569aSHeiko Stübner 27177179569aSHeiko Stübner _notifier_call_chain(rdev, REGULATOR_EVENT_ABORT_VOLTAGE_CHANGE, 27187179569aSHeiko Stübner (void *)data.old_uV); 27197179569aSHeiko Stübner 27207179569aSHeiko Stübner return ret; 27217179569aSHeiko Stübner } 27227179569aSHeiko Stübner 27237179569aSHeiko Stübner static int _regulator_call_set_voltage_sel(struct regulator_dev *rdev, 27247179569aSHeiko Stübner int uV, unsigned selector) 27257179569aSHeiko Stübner { 27267179569aSHeiko Stübner struct pre_voltage_change_data data; 27277179569aSHeiko Stübner int ret; 27287179569aSHeiko Stübner 27297179569aSHeiko Stübner data.old_uV = _regulator_get_voltage(rdev); 27307179569aSHeiko Stübner data.min_uV = uV; 27317179569aSHeiko Stübner data.max_uV = uV; 27327179569aSHeiko Stübner ret = _notifier_call_chain(rdev, REGULATOR_EVENT_PRE_VOLTAGE_CHANGE, 27337179569aSHeiko Stübner &data); 27347179569aSHeiko Stübner if (ret & NOTIFY_STOP_MASK) 27357179569aSHeiko Stübner return -EINVAL; 27367179569aSHeiko Stübner 27377179569aSHeiko Stübner ret = rdev->desc->ops->set_voltage_sel(rdev, selector); 27387179569aSHeiko Stübner if (ret >= 0) 27397179569aSHeiko Stübner return ret; 27407179569aSHeiko Stübner 27417179569aSHeiko Stübner _notifier_call_chain(rdev, REGULATOR_EVENT_ABORT_VOLTAGE_CHANGE, 27427179569aSHeiko Stübner (void *)data.old_uV); 27437179569aSHeiko Stübner 27447179569aSHeiko Stübner return ret; 27457179569aSHeiko Stübner } 27467179569aSHeiko Stübner 274775790251SMark Brown static int _regulator_do_set_voltage(struct regulator_dev *rdev, 274875790251SMark Brown int min_uV, int max_uV) 274975790251SMark Brown { 275075790251SMark Brown int ret; 275177af1b26SLinus Walleij int delay = 0; 2752e113d792SMark Brown int best_val = 0; 275375790251SMark Brown unsigned int selector; 2754eba41a5eSAxel Lin int old_selector = -1; 275575790251SMark Brown 275675790251SMark Brown trace_regulator_set_voltage(rdev_get_name(rdev), min_uV, max_uV); 275775790251SMark Brown 2758bf5892a8SMark Brown min_uV += rdev->constraints->uV_offset; 2759bf5892a8SMark Brown max_uV += rdev->constraints->uV_offset; 2760bf5892a8SMark Brown 276177af1b26SLinus Walleij /* 276277af1b26SLinus Walleij * If we can't obtain the old selector there is not enough 276377af1b26SLinus Walleij * info to call set_voltage_time_sel(). 276477af1b26SLinus Walleij */ 27658b7485efSAxel Lin if (_regulator_is_enabled(rdev) && 27668b7485efSAxel Lin rdev->desc->ops->set_voltage_time_sel && 276777af1b26SLinus Walleij rdev->desc->ops->get_voltage_sel) { 2768eba41a5eSAxel Lin old_selector = rdev->desc->ops->get_voltage_sel(rdev); 2769eba41a5eSAxel Lin if (old_selector < 0) 2770eba41a5eSAxel Lin return old_selector; 2771eba41a5eSAxel Lin } 277277af1b26SLinus Walleij 277375790251SMark Brown if (rdev->desc->ops->set_voltage) { 27747179569aSHeiko Stübner ret = _regulator_call_set_voltage(rdev, min_uV, max_uV, 277575790251SMark Brown &selector); 2776e113d792SMark Brown 2777e113d792SMark Brown if (ret >= 0) { 2778e113d792SMark Brown if (rdev->desc->ops->list_voltage) 2779e113d792SMark Brown best_val = rdev->desc->ops->list_voltage(rdev, 2780e113d792SMark Brown selector); 2781e113d792SMark Brown else 2782e113d792SMark Brown best_val = _regulator_get_voltage(rdev); 2783e113d792SMark Brown } 2784e113d792SMark Brown 2785e8eef82bSMark Brown } else if (rdev->desc->ops->set_voltage_sel) { 2786a204f41eSSascha Hauer ret = regulator_map_voltage(rdev, min_uV, max_uV); 2787e843fc46SMark Brown if (ret >= 0) { 2788e113d792SMark Brown best_val = rdev->desc->ops->list_voltage(rdev, ret); 2789e113d792SMark Brown if (min_uV <= best_val && max_uV >= best_val) { 2790e843fc46SMark Brown selector = ret; 2791c66a566aSAxel Lin if (old_selector == selector) 2792c66a566aSAxel Lin ret = 0; 2793c66a566aSAxel Lin else 27947179569aSHeiko Stübner ret = _regulator_call_set_voltage_sel( 27957179569aSHeiko Stübner rdev, best_val, selector); 2796e113d792SMark Brown } else { 2797e113d792SMark Brown ret = -EINVAL; 2798e113d792SMark Brown } 2799e843fc46SMark Brown } 2800e8eef82bSMark Brown } else { 2801e8eef82bSMark Brown ret = -EINVAL; 2802e8eef82bSMark Brown } 2803e8eef82bSMark Brown 2804eba41a5eSAxel Lin /* Call set_voltage_time_sel if successfully obtained old_selector */ 28055b175952SYadwinder Singh Brar if (ret == 0 && !rdev->constraints->ramp_disable && old_selector >= 0 28065b175952SYadwinder Singh Brar && old_selector != selector) { 2807eba41a5eSAxel Lin 2808eba41a5eSAxel Lin delay = rdev->desc->ops->set_voltage_time_sel(rdev, 2809eba41a5eSAxel Lin old_selector, selector); 2810eba41a5eSAxel Lin if (delay < 0) { 2811eba41a5eSAxel Lin rdev_warn(rdev, "set_voltage_time_sel() failed: %d\n", 2812eba41a5eSAxel Lin delay); 2813eba41a5eSAxel Lin delay = 0; 2814e8eef82bSMark Brown } 281575790251SMark Brown 281677af1b26SLinus Walleij /* Insert any necessary delays */ 281777af1b26SLinus Walleij if (delay >= 1000) { 281877af1b26SLinus Walleij mdelay(delay / 1000); 281977af1b26SLinus Walleij udelay(delay % 1000); 282077af1b26SLinus Walleij } else if (delay) { 282177af1b26SLinus Walleij udelay(delay); 282277af1b26SLinus Walleij } 28238b96de31SPhilip Rakity } 282477af1b26SLinus Walleij 28252f6c797fSAxel Lin if (ret == 0 && best_val >= 0) { 28262f6c797fSAxel Lin unsigned long data = best_val; 28272f6c797fSAxel Lin 2828ded06a52SMark Brown _notifier_call_chain(rdev, REGULATOR_EVENT_VOLTAGE_CHANGE, 28292f6c797fSAxel Lin (void *)data); 28302f6c797fSAxel Lin } 2831ded06a52SMark Brown 2832eba41a5eSAxel Lin trace_regulator_set_voltage_complete(rdev_get_name(rdev), best_val); 283375790251SMark Brown 283475790251SMark Brown return ret; 283575790251SMark Brown } 283675790251SMark Brown 2837a9f226bcSSascha Hauer static int regulator_set_voltage_unlocked(struct regulator *regulator, 2838a9f226bcSSascha Hauer int min_uV, int max_uV) 2839414c70cbSLiam Girdwood { 2840414c70cbSLiam Girdwood struct regulator_dev *rdev = regulator->rdev; 284195a3c23aSMark Brown int ret = 0; 284292d7a558SPaolo Pisati int old_min_uV, old_max_uV; 2843c00dc359SBjorn Andersson int current_uV; 2844fc42112cSSascha Hauer int best_supply_uV = 0; 2845fc42112cSSascha Hauer int supply_change_uV = 0; 2846414c70cbSLiam Girdwood 284795a3c23aSMark Brown /* If we're setting the same range as last time the change 284895a3c23aSMark Brown * should be a noop (some cpufreq implementations use the same 284995a3c23aSMark Brown * voltage for multiple frequencies, for example). 285095a3c23aSMark Brown */ 285195a3c23aSMark Brown if (regulator->min_uV == min_uV && regulator->max_uV == max_uV) 285295a3c23aSMark Brown goto out; 285395a3c23aSMark Brown 2854c00dc359SBjorn Andersson /* If we're trying to set a range that overlaps the current voltage, 2855d3fb9800SViresh Kumar * return successfully even though the regulator does not support 2856c00dc359SBjorn Andersson * changing the voltage. 2857c00dc359SBjorn Andersson */ 2858c00dc359SBjorn Andersson if (!(rdev->constraints->valid_ops_mask & REGULATOR_CHANGE_VOLTAGE)) { 2859c00dc359SBjorn Andersson current_uV = _regulator_get_voltage(rdev); 2860c00dc359SBjorn Andersson if (min_uV <= current_uV && current_uV <= max_uV) { 2861c00dc359SBjorn Andersson regulator->min_uV = min_uV; 2862c00dc359SBjorn Andersson regulator->max_uV = max_uV; 2863c00dc359SBjorn Andersson goto out; 2864c00dc359SBjorn Andersson } 2865c00dc359SBjorn Andersson } 2866c00dc359SBjorn Andersson 2867414c70cbSLiam Girdwood /* sanity check */ 2868e8eef82bSMark Brown if (!rdev->desc->ops->set_voltage && 2869e8eef82bSMark Brown !rdev->desc->ops->set_voltage_sel) { 2870414c70cbSLiam Girdwood ret = -EINVAL; 2871414c70cbSLiam Girdwood goto out; 2872414c70cbSLiam Girdwood } 2873414c70cbSLiam Girdwood 2874414c70cbSLiam Girdwood /* constraints check */ 2875414c70cbSLiam Girdwood ret = regulator_check_voltage(rdev, &min_uV, &max_uV); 2876414c70cbSLiam Girdwood if (ret < 0) 2877414c70cbSLiam Girdwood goto out; 287892d7a558SPaolo Pisati 287992d7a558SPaolo Pisati /* restore original values in case of error */ 288092d7a558SPaolo Pisati old_min_uV = regulator->min_uV; 288192d7a558SPaolo Pisati old_max_uV = regulator->max_uV; 2882414c70cbSLiam Girdwood regulator->min_uV = min_uV; 2883414c70cbSLiam Girdwood regulator->max_uV = max_uV; 28843a93f2a9SMark Brown 288505fda3b1SThomas Petazzoni ret = regulator_check_consumers(rdev, &min_uV, &max_uV); 288605fda3b1SThomas Petazzoni if (ret < 0) 288792d7a558SPaolo Pisati goto out2; 288805fda3b1SThomas Petazzoni 2889fc42112cSSascha Hauer if (rdev->supply && (rdev->desc->min_dropout_uV || 2890fc42112cSSascha Hauer !rdev->desc->ops->get_voltage)) { 2891fc42112cSSascha Hauer int current_supply_uV; 2892fc42112cSSascha Hauer int selector; 2893fc42112cSSascha Hauer 2894fc42112cSSascha Hauer selector = regulator_map_voltage(rdev, min_uV, max_uV); 2895fc42112cSSascha Hauer if (selector < 0) { 2896fc42112cSSascha Hauer ret = selector; 2897fc42112cSSascha Hauer goto out2; 2898fc42112cSSascha Hauer } 2899fc42112cSSascha Hauer 2900fc42112cSSascha Hauer best_supply_uV = _regulator_list_voltage(regulator, selector, 0); 2901fc42112cSSascha Hauer if (best_supply_uV < 0) { 2902fc42112cSSascha Hauer ret = best_supply_uV; 2903fc42112cSSascha Hauer goto out2; 2904fc42112cSSascha Hauer } 2905fc42112cSSascha Hauer 2906fc42112cSSascha Hauer best_supply_uV += rdev->desc->min_dropout_uV; 2907fc42112cSSascha Hauer 2908fc42112cSSascha Hauer current_supply_uV = _regulator_get_voltage(rdev->supply->rdev); 2909fc42112cSSascha Hauer if (current_supply_uV < 0) { 2910fc42112cSSascha Hauer ret = current_supply_uV; 2911fc42112cSSascha Hauer goto out2; 2912fc42112cSSascha Hauer } 2913fc42112cSSascha Hauer 2914fc42112cSSascha Hauer supply_change_uV = best_supply_uV - current_supply_uV; 2915fc42112cSSascha Hauer } 2916fc42112cSSascha Hauer 2917fc42112cSSascha Hauer if (supply_change_uV > 0) { 2918fc42112cSSascha Hauer ret = regulator_set_voltage_unlocked(rdev->supply, 2919fc42112cSSascha Hauer best_supply_uV, INT_MAX); 2920fc42112cSSascha Hauer if (ret) { 2921fc42112cSSascha Hauer dev_err(&rdev->dev, "Failed to increase supply voltage: %d\n", 2922fc42112cSSascha Hauer ret); 2923fc42112cSSascha Hauer goto out2; 2924fc42112cSSascha Hauer } 2925fc42112cSSascha Hauer } 2926fc42112cSSascha Hauer 292775790251SMark Brown ret = _regulator_do_set_voltage(rdev, min_uV, max_uV); 292892d7a558SPaolo Pisati if (ret < 0) 292992d7a558SPaolo Pisati goto out2; 293002fa3ec0SMark Brown 2931fc42112cSSascha Hauer if (supply_change_uV < 0) { 2932fc42112cSSascha Hauer ret = regulator_set_voltage_unlocked(rdev->supply, 2933fc42112cSSascha Hauer best_supply_uV, INT_MAX); 2934fc42112cSSascha Hauer if (ret) 2935fc42112cSSascha Hauer dev_warn(&rdev->dev, "Failed to decrease supply voltage: %d\n", 2936fc42112cSSascha Hauer ret); 2937fc42112cSSascha Hauer /* No need to fail here */ 2938fc42112cSSascha Hauer ret = 0; 2939fc42112cSSascha Hauer } 2940fc42112cSSascha Hauer 2941414c70cbSLiam Girdwood out: 2942414c70cbSLiam Girdwood return ret; 294392d7a558SPaolo Pisati out2: 294492d7a558SPaolo Pisati regulator->min_uV = old_min_uV; 294592d7a558SPaolo Pisati regulator->max_uV = old_max_uV; 2946a9f226bcSSascha Hauer 2947a9f226bcSSascha Hauer return ret; 2948a9f226bcSSascha Hauer } 2949a9f226bcSSascha Hauer 2950a9f226bcSSascha Hauer /** 2951a9f226bcSSascha Hauer * regulator_set_voltage - set regulator output voltage 2952a9f226bcSSascha Hauer * @regulator: regulator source 2953a9f226bcSSascha Hauer * @min_uV: Minimum required voltage in uV 2954a9f226bcSSascha Hauer * @max_uV: Maximum acceptable voltage in uV 2955a9f226bcSSascha Hauer * 2956a9f226bcSSascha Hauer * Sets a voltage regulator to the desired output voltage. This can be set 2957a9f226bcSSascha Hauer * during any regulator state. IOW, regulator can be disabled or enabled. 2958a9f226bcSSascha Hauer * 2959a9f226bcSSascha Hauer * If the regulator is enabled then the voltage will change to the new value 2960a9f226bcSSascha Hauer * immediately otherwise if the regulator is disabled the regulator will 2961a9f226bcSSascha Hauer * output at the new voltage when enabled. 2962a9f226bcSSascha Hauer * 2963a9f226bcSSascha Hauer * NOTE: If the regulator is shared between several devices then the lowest 2964a9f226bcSSascha Hauer * request voltage that meets the system constraints will be used. 2965a9f226bcSSascha Hauer * Regulator system constraints must be set for this regulator before 2966a9f226bcSSascha Hauer * calling this function otherwise this call will fail. 2967a9f226bcSSascha Hauer */ 2968a9f226bcSSascha Hauer int regulator_set_voltage(struct regulator *regulator, int min_uV, int max_uV) 2969a9f226bcSSascha Hauer { 2970a9f226bcSSascha Hauer int ret = 0; 2971a9f226bcSSascha Hauer 2972fc42112cSSascha Hauer regulator_lock_supply(regulator->rdev); 2973a9f226bcSSascha Hauer 2974a9f226bcSSascha Hauer ret = regulator_set_voltage_unlocked(regulator, min_uV, max_uV); 2975a9f226bcSSascha Hauer 2976fc42112cSSascha Hauer regulator_unlock_supply(regulator->rdev); 2977a9f226bcSSascha Hauer 297892d7a558SPaolo Pisati return ret; 2979414c70cbSLiam Girdwood } 2980414c70cbSLiam Girdwood EXPORT_SYMBOL_GPL(regulator_set_voltage); 2981414c70cbSLiam Girdwood 2982606a2562SMark Brown /** 298388cd222bSLinus Walleij * regulator_set_voltage_time - get raise/fall time 298488cd222bSLinus Walleij * @regulator: regulator source 298588cd222bSLinus Walleij * @old_uV: starting voltage in microvolts 298688cd222bSLinus Walleij * @new_uV: target voltage in microvolts 298788cd222bSLinus Walleij * 298888cd222bSLinus Walleij * Provided with the starting and ending voltage, this function attempts to 298988cd222bSLinus Walleij * calculate the time in microseconds required to rise or fall to this new 299088cd222bSLinus Walleij * voltage. 299188cd222bSLinus Walleij */ 299288cd222bSLinus Walleij int regulator_set_voltage_time(struct regulator *regulator, 299388cd222bSLinus Walleij int old_uV, int new_uV) 299488cd222bSLinus Walleij { 299588cd222bSLinus Walleij struct regulator_dev *rdev = regulator->rdev; 2996272e2315SGuodong Xu const struct regulator_ops *ops = rdev->desc->ops; 299788cd222bSLinus Walleij int old_sel = -1; 299888cd222bSLinus Walleij int new_sel = -1; 299988cd222bSLinus Walleij int voltage; 300088cd222bSLinus Walleij int i; 300188cd222bSLinus Walleij 300288cd222bSLinus Walleij /* Currently requires operations to do this */ 300388cd222bSLinus Walleij if (!ops->list_voltage || !ops->set_voltage_time_sel 300488cd222bSLinus Walleij || !rdev->desc->n_voltages) 300588cd222bSLinus Walleij return -EINVAL; 300688cd222bSLinus Walleij 300788cd222bSLinus Walleij for (i = 0; i < rdev->desc->n_voltages; i++) { 300888cd222bSLinus Walleij /* We only look for exact voltage matches here */ 300988cd222bSLinus Walleij voltage = regulator_list_voltage(regulator, i); 301088cd222bSLinus Walleij if (voltage < 0) 301188cd222bSLinus Walleij return -EINVAL; 301288cd222bSLinus Walleij if (voltage == 0) 301388cd222bSLinus Walleij continue; 301488cd222bSLinus Walleij if (voltage == old_uV) 301588cd222bSLinus Walleij old_sel = i; 301688cd222bSLinus Walleij if (voltage == new_uV) 301788cd222bSLinus Walleij new_sel = i; 301888cd222bSLinus Walleij } 301988cd222bSLinus Walleij 302088cd222bSLinus Walleij if (old_sel < 0 || new_sel < 0) 302188cd222bSLinus Walleij return -EINVAL; 302288cd222bSLinus Walleij 302388cd222bSLinus Walleij return ops->set_voltage_time_sel(rdev, old_sel, new_sel); 302488cd222bSLinus Walleij } 302588cd222bSLinus Walleij EXPORT_SYMBOL_GPL(regulator_set_voltage_time); 302688cd222bSLinus Walleij 302788cd222bSLinus Walleij /** 302898a175b6SYadwinder Singh Brar * regulator_set_voltage_time_sel - get raise/fall time 3029296c6566SRandy Dunlap * @rdev: regulator source device 303098a175b6SYadwinder Singh Brar * @old_selector: selector for starting voltage 303198a175b6SYadwinder Singh Brar * @new_selector: selector for target voltage 303298a175b6SYadwinder Singh Brar * 303398a175b6SYadwinder Singh Brar * Provided with the starting and target voltage selectors, this function 303498a175b6SYadwinder Singh Brar * returns time in microseconds required to rise or fall to this new voltage 303598a175b6SYadwinder Singh Brar * 3036f11d08c3SAxel Lin * Drivers providing ramp_delay in regulation_constraints can use this as their 3037398715abSAxel Lin * set_voltage_time_sel() operation. 303898a175b6SYadwinder Singh Brar */ 303998a175b6SYadwinder Singh Brar int regulator_set_voltage_time_sel(struct regulator_dev *rdev, 304098a175b6SYadwinder Singh Brar unsigned int old_selector, 304198a175b6SYadwinder Singh Brar unsigned int new_selector) 304298a175b6SYadwinder Singh Brar { 3043398715abSAxel Lin unsigned int ramp_delay = 0; 3044f11d08c3SAxel Lin int old_volt, new_volt; 3045398715abSAxel Lin 30466f0b2c69SYadwinder Singh Brar if (rdev->constraints->ramp_delay) 3047398715abSAxel Lin ramp_delay = rdev->constraints->ramp_delay; 3048398715abSAxel Lin else if (rdev->desc->ramp_delay) 3049398715abSAxel Lin ramp_delay = rdev->desc->ramp_delay; 3050398715abSAxel Lin 3051398715abSAxel Lin if (ramp_delay == 0) { 30526f0b2c69SYadwinder Singh Brar rdev_warn(rdev, "ramp_delay not set\n"); 3053398715abSAxel Lin return 0; 30546f0b2c69SYadwinder Singh Brar } 3055398715abSAxel Lin 3056f11d08c3SAxel Lin /* sanity check */ 3057f11d08c3SAxel Lin if (!rdev->desc->ops->list_voltage) 3058f11d08c3SAxel Lin return -EINVAL; 3059398715abSAxel Lin 3060f11d08c3SAxel Lin old_volt = rdev->desc->ops->list_voltage(rdev, old_selector); 3061f11d08c3SAxel Lin new_volt = rdev->desc->ops->list_voltage(rdev, new_selector); 3062f11d08c3SAxel Lin 3063f11d08c3SAxel Lin return DIV_ROUND_UP(abs(new_volt - old_volt), ramp_delay); 306498a175b6SYadwinder Singh Brar } 3065b19dbf71SMark Brown EXPORT_SYMBOL_GPL(regulator_set_voltage_time_sel); 306698a175b6SYadwinder Singh Brar 306798a175b6SYadwinder Singh Brar /** 3068606a2562SMark Brown * regulator_sync_voltage - re-apply last regulator output voltage 3069606a2562SMark Brown * @regulator: regulator source 3070606a2562SMark Brown * 3071606a2562SMark Brown * Re-apply the last configured voltage. This is intended to be used 3072606a2562SMark Brown * where some external control source the consumer is cooperating with 3073606a2562SMark Brown * has caused the configured voltage to change. 3074606a2562SMark Brown */ 3075606a2562SMark Brown int regulator_sync_voltage(struct regulator *regulator) 3076606a2562SMark Brown { 3077606a2562SMark Brown struct regulator_dev *rdev = regulator->rdev; 3078606a2562SMark Brown int ret, min_uV, max_uV; 3079606a2562SMark Brown 3080606a2562SMark Brown mutex_lock(&rdev->mutex); 3081606a2562SMark Brown 3082606a2562SMark Brown if (!rdev->desc->ops->set_voltage && 3083606a2562SMark Brown !rdev->desc->ops->set_voltage_sel) { 3084606a2562SMark Brown ret = -EINVAL; 3085606a2562SMark Brown goto out; 3086606a2562SMark Brown } 3087606a2562SMark Brown 3088606a2562SMark Brown /* This is only going to work if we've had a voltage configured. */ 3089606a2562SMark Brown if (!regulator->min_uV && !regulator->max_uV) { 3090606a2562SMark Brown ret = -EINVAL; 3091606a2562SMark Brown goto out; 3092606a2562SMark Brown } 3093606a2562SMark Brown 3094606a2562SMark Brown min_uV = regulator->min_uV; 3095606a2562SMark Brown max_uV = regulator->max_uV; 3096606a2562SMark Brown 3097606a2562SMark Brown /* This should be a paranoia check... */ 3098606a2562SMark Brown ret = regulator_check_voltage(rdev, &min_uV, &max_uV); 3099606a2562SMark Brown if (ret < 0) 3100606a2562SMark Brown goto out; 3101606a2562SMark Brown 3102606a2562SMark Brown ret = regulator_check_consumers(rdev, &min_uV, &max_uV); 3103606a2562SMark Brown if (ret < 0) 3104606a2562SMark Brown goto out; 3105606a2562SMark Brown 3106606a2562SMark Brown ret = _regulator_do_set_voltage(rdev, min_uV, max_uV); 3107606a2562SMark Brown 3108606a2562SMark Brown out: 3109606a2562SMark Brown mutex_unlock(&rdev->mutex); 3110606a2562SMark Brown return ret; 3111606a2562SMark Brown } 3112606a2562SMark Brown EXPORT_SYMBOL_GPL(regulator_sync_voltage); 3113606a2562SMark Brown 3114414c70cbSLiam Girdwood static int _regulator_get_voltage(struct regulator_dev *rdev) 3115414c70cbSLiam Girdwood { 3116bf5892a8SMark Brown int sel, ret; 3117476c2d83SMark Brown 3118476c2d83SMark Brown if (rdev->desc->ops->get_voltage_sel) { 3119476c2d83SMark Brown sel = rdev->desc->ops->get_voltage_sel(rdev); 3120476c2d83SMark Brown if (sel < 0) 3121476c2d83SMark Brown return sel; 3122bf5892a8SMark Brown ret = rdev->desc->ops->list_voltage(rdev, sel); 3123cb220d16SAxel Lin } else if (rdev->desc->ops->get_voltage) { 3124bf5892a8SMark Brown ret = rdev->desc->ops->get_voltage(rdev); 3125f7df20ecSMark Brown } else if (rdev->desc->ops->list_voltage) { 3126f7df20ecSMark Brown ret = rdev->desc->ops->list_voltage(rdev, 0); 31275a523605SLaxman Dewangan } else if (rdev->desc->fixed_uV && (rdev->desc->n_voltages == 1)) { 31285a523605SLaxman Dewangan ret = rdev->desc->fixed_uV; 3129e303996eSJavier Martinez Canillas } else if (rdev->supply) { 3130d9b96d35SMark Brown ret = _regulator_get_voltage(rdev->supply->rdev); 3131cb220d16SAxel Lin } else { 3132414c70cbSLiam Girdwood return -EINVAL; 3133cb220d16SAxel Lin } 3134bf5892a8SMark Brown 3135cb220d16SAxel Lin if (ret < 0) 3136cb220d16SAxel Lin return ret; 3137bf5892a8SMark Brown return ret - rdev->constraints->uV_offset; 3138414c70cbSLiam Girdwood } 3139414c70cbSLiam Girdwood 3140414c70cbSLiam Girdwood /** 3141414c70cbSLiam Girdwood * regulator_get_voltage - get regulator output voltage 3142414c70cbSLiam Girdwood * @regulator: regulator source 3143414c70cbSLiam Girdwood * 3144414c70cbSLiam Girdwood * This returns the current regulator voltage in uV. 3145414c70cbSLiam Girdwood * 3146414c70cbSLiam Girdwood * NOTE: If the regulator is disabled it will return the voltage value. This 3147414c70cbSLiam Girdwood * function should not be used to determine regulator state. 3148414c70cbSLiam Girdwood */ 3149414c70cbSLiam Girdwood int regulator_get_voltage(struct regulator *regulator) 3150414c70cbSLiam Girdwood { 3151414c70cbSLiam Girdwood int ret; 3152414c70cbSLiam Girdwood 3153d9b96d35SMark Brown regulator_lock_supply(regulator->rdev); 3154414c70cbSLiam Girdwood 3155414c70cbSLiam Girdwood ret = _regulator_get_voltage(regulator->rdev); 3156414c70cbSLiam Girdwood 3157d9b96d35SMark Brown regulator_unlock_supply(regulator->rdev); 3158414c70cbSLiam Girdwood 3159414c70cbSLiam Girdwood return ret; 3160414c70cbSLiam Girdwood } 3161414c70cbSLiam Girdwood EXPORT_SYMBOL_GPL(regulator_get_voltage); 3162414c70cbSLiam Girdwood 3163414c70cbSLiam Girdwood /** 3164414c70cbSLiam Girdwood * regulator_set_current_limit - set regulator output current limit 3165414c70cbSLiam Girdwood * @regulator: regulator source 3166ce0d10f8SCharles Keepax * @min_uA: Minimum supported current in uA 3167414c70cbSLiam Girdwood * @max_uA: Maximum supported current in uA 3168414c70cbSLiam Girdwood * 3169414c70cbSLiam Girdwood * Sets current sink to the desired output current. This can be set during 3170414c70cbSLiam Girdwood * any regulator state. IOW, regulator can be disabled or enabled. 3171414c70cbSLiam Girdwood * 3172414c70cbSLiam Girdwood * If the regulator is enabled then the current will change to the new value 3173414c70cbSLiam Girdwood * immediately otherwise if the regulator is disabled the regulator will 3174414c70cbSLiam Girdwood * output at the new current when enabled. 3175414c70cbSLiam Girdwood * 3176414c70cbSLiam Girdwood * NOTE: Regulator system constraints must be set for this regulator before 3177414c70cbSLiam Girdwood * calling this function otherwise this call will fail. 3178414c70cbSLiam Girdwood */ 3179414c70cbSLiam Girdwood int regulator_set_current_limit(struct regulator *regulator, 3180414c70cbSLiam Girdwood int min_uA, int max_uA) 3181414c70cbSLiam Girdwood { 3182414c70cbSLiam Girdwood struct regulator_dev *rdev = regulator->rdev; 3183414c70cbSLiam Girdwood int ret; 3184414c70cbSLiam Girdwood 3185414c70cbSLiam Girdwood mutex_lock(&rdev->mutex); 3186414c70cbSLiam Girdwood 3187414c70cbSLiam Girdwood /* sanity check */ 3188414c70cbSLiam Girdwood if (!rdev->desc->ops->set_current_limit) { 3189414c70cbSLiam Girdwood ret = -EINVAL; 3190414c70cbSLiam Girdwood goto out; 3191414c70cbSLiam Girdwood } 3192414c70cbSLiam Girdwood 3193414c70cbSLiam Girdwood /* constraints check */ 3194414c70cbSLiam Girdwood ret = regulator_check_current_limit(rdev, &min_uA, &max_uA); 3195414c70cbSLiam Girdwood if (ret < 0) 3196414c70cbSLiam Girdwood goto out; 3197414c70cbSLiam Girdwood 3198414c70cbSLiam Girdwood ret = rdev->desc->ops->set_current_limit(rdev, min_uA, max_uA); 3199414c70cbSLiam Girdwood out: 3200414c70cbSLiam Girdwood mutex_unlock(&rdev->mutex); 3201414c70cbSLiam Girdwood return ret; 3202414c70cbSLiam Girdwood } 3203414c70cbSLiam Girdwood EXPORT_SYMBOL_GPL(regulator_set_current_limit); 3204414c70cbSLiam Girdwood 3205414c70cbSLiam Girdwood static int _regulator_get_current_limit(struct regulator_dev *rdev) 3206414c70cbSLiam Girdwood { 3207414c70cbSLiam Girdwood int ret; 3208414c70cbSLiam Girdwood 3209414c70cbSLiam Girdwood mutex_lock(&rdev->mutex); 3210414c70cbSLiam Girdwood 3211414c70cbSLiam Girdwood /* sanity check */ 3212414c70cbSLiam Girdwood if (!rdev->desc->ops->get_current_limit) { 3213414c70cbSLiam Girdwood ret = -EINVAL; 3214414c70cbSLiam Girdwood goto out; 3215414c70cbSLiam Girdwood } 3216414c70cbSLiam Girdwood 3217414c70cbSLiam Girdwood ret = rdev->desc->ops->get_current_limit(rdev); 3218414c70cbSLiam Girdwood out: 3219414c70cbSLiam Girdwood mutex_unlock(&rdev->mutex); 3220414c70cbSLiam Girdwood return ret; 3221414c70cbSLiam Girdwood } 3222414c70cbSLiam Girdwood 3223414c70cbSLiam Girdwood /** 3224414c70cbSLiam Girdwood * regulator_get_current_limit - get regulator output current 3225414c70cbSLiam Girdwood * @regulator: regulator source 3226414c70cbSLiam Girdwood * 3227414c70cbSLiam Girdwood * This returns the current supplied by the specified current sink in uA. 3228414c70cbSLiam Girdwood * 3229414c70cbSLiam Girdwood * NOTE: If the regulator is disabled it will return the current value. This 3230414c70cbSLiam Girdwood * function should not be used to determine regulator state. 3231414c70cbSLiam Girdwood */ 3232414c70cbSLiam Girdwood int regulator_get_current_limit(struct regulator *regulator) 3233414c70cbSLiam Girdwood { 3234414c70cbSLiam Girdwood return _regulator_get_current_limit(regulator->rdev); 3235414c70cbSLiam Girdwood } 3236414c70cbSLiam Girdwood EXPORT_SYMBOL_GPL(regulator_get_current_limit); 3237414c70cbSLiam Girdwood 3238414c70cbSLiam Girdwood /** 3239414c70cbSLiam Girdwood * regulator_set_mode - set regulator operating mode 3240414c70cbSLiam Girdwood * @regulator: regulator source 3241414c70cbSLiam Girdwood * @mode: operating mode - one of the REGULATOR_MODE constants 3242414c70cbSLiam Girdwood * 3243414c70cbSLiam Girdwood * Set regulator operating mode to increase regulator efficiency or improve 3244414c70cbSLiam Girdwood * regulation performance. 3245414c70cbSLiam Girdwood * 3246414c70cbSLiam Girdwood * NOTE: Regulator system constraints must be set for this regulator before 3247414c70cbSLiam Girdwood * calling this function otherwise this call will fail. 3248414c70cbSLiam Girdwood */ 3249414c70cbSLiam Girdwood int regulator_set_mode(struct regulator *regulator, unsigned int mode) 3250414c70cbSLiam Girdwood { 3251414c70cbSLiam Girdwood struct regulator_dev *rdev = regulator->rdev; 3252414c70cbSLiam Girdwood int ret; 3253500b4ac9SSundar R Iyer int regulator_curr_mode; 3254414c70cbSLiam Girdwood 3255414c70cbSLiam Girdwood mutex_lock(&rdev->mutex); 3256414c70cbSLiam Girdwood 3257414c70cbSLiam Girdwood /* sanity check */ 3258414c70cbSLiam Girdwood if (!rdev->desc->ops->set_mode) { 3259414c70cbSLiam Girdwood ret = -EINVAL; 3260414c70cbSLiam Girdwood goto out; 3261414c70cbSLiam Girdwood } 3262414c70cbSLiam Girdwood 3263500b4ac9SSundar R Iyer /* return if the same mode is requested */ 3264500b4ac9SSundar R Iyer if (rdev->desc->ops->get_mode) { 3265500b4ac9SSundar R Iyer regulator_curr_mode = rdev->desc->ops->get_mode(rdev); 3266500b4ac9SSundar R Iyer if (regulator_curr_mode == mode) { 3267500b4ac9SSundar R Iyer ret = 0; 3268500b4ac9SSundar R Iyer goto out; 3269500b4ac9SSundar R Iyer } 3270500b4ac9SSundar R Iyer } 3271500b4ac9SSundar R Iyer 3272414c70cbSLiam Girdwood /* constraints check */ 327322c51b47SAxel Lin ret = regulator_mode_constrain(rdev, &mode); 3274414c70cbSLiam Girdwood if (ret < 0) 3275414c70cbSLiam Girdwood goto out; 3276414c70cbSLiam Girdwood 3277414c70cbSLiam Girdwood ret = rdev->desc->ops->set_mode(rdev, mode); 3278414c70cbSLiam Girdwood out: 3279414c70cbSLiam Girdwood mutex_unlock(&rdev->mutex); 3280414c70cbSLiam Girdwood return ret; 3281414c70cbSLiam Girdwood } 3282414c70cbSLiam Girdwood EXPORT_SYMBOL_GPL(regulator_set_mode); 3283414c70cbSLiam Girdwood 3284414c70cbSLiam Girdwood static unsigned int _regulator_get_mode(struct regulator_dev *rdev) 3285414c70cbSLiam Girdwood { 3286414c70cbSLiam Girdwood int ret; 3287414c70cbSLiam Girdwood 3288414c70cbSLiam Girdwood mutex_lock(&rdev->mutex); 3289414c70cbSLiam Girdwood 3290414c70cbSLiam Girdwood /* sanity check */ 3291414c70cbSLiam Girdwood if (!rdev->desc->ops->get_mode) { 3292414c70cbSLiam Girdwood ret = -EINVAL; 3293414c70cbSLiam Girdwood goto out; 3294414c70cbSLiam Girdwood } 3295414c70cbSLiam Girdwood 3296414c70cbSLiam Girdwood ret = rdev->desc->ops->get_mode(rdev); 3297414c70cbSLiam Girdwood out: 3298414c70cbSLiam Girdwood mutex_unlock(&rdev->mutex); 3299414c70cbSLiam Girdwood return ret; 3300414c70cbSLiam Girdwood } 3301414c70cbSLiam Girdwood 3302414c70cbSLiam Girdwood /** 3303414c70cbSLiam Girdwood * regulator_get_mode - get regulator operating mode 3304414c70cbSLiam Girdwood * @regulator: regulator source 3305414c70cbSLiam Girdwood * 3306414c70cbSLiam Girdwood * Get the current regulator operating mode. 3307414c70cbSLiam Girdwood */ 3308414c70cbSLiam Girdwood unsigned int regulator_get_mode(struct regulator *regulator) 3309414c70cbSLiam Girdwood { 3310414c70cbSLiam Girdwood return _regulator_get_mode(regulator->rdev); 3311414c70cbSLiam Girdwood } 3312414c70cbSLiam Girdwood EXPORT_SYMBOL_GPL(regulator_get_mode); 3313414c70cbSLiam Girdwood 3314414c70cbSLiam Girdwood /** 3315e39ce48fSBjorn Andersson * regulator_set_load - set regulator load 3316414c70cbSLiam Girdwood * @regulator: regulator source 3317414c70cbSLiam Girdwood * @uA_load: load current 3318414c70cbSLiam Girdwood * 3319414c70cbSLiam Girdwood * Notifies the regulator core of a new device load. This is then used by 3320414c70cbSLiam Girdwood * DRMS (if enabled by constraints) to set the most efficient regulator 3321414c70cbSLiam Girdwood * operating mode for the new regulator loading. 3322414c70cbSLiam Girdwood * 3323414c70cbSLiam Girdwood * Consumer devices notify their supply regulator of the maximum power 3324414c70cbSLiam Girdwood * they will require (can be taken from device datasheet in the power 3325414c70cbSLiam Girdwood * consumption tables) when they change operational status and hence power 3326414c70cbSLiam Girdwood * state. Examples of operational state changes that can affect power 3327414c70cbSLiam Girdwood * consumption are :- 3328414c70cbSLiam Girdwood * 3329414c70cbSLiam Girdwood * o Device is opened / closed. 3330414c70cbSLiam Girdwood * o Device I/O is about to begin or has just finished. 3331414c70cbSLiam Girdwood * o Device is idling in between work. 3332414c70cbSLiam Girdwood * 3333414c70cbSLiam Girdwood * This information is also exported via sysfs to userspace. 3334414c70cbSLiam Girdwood * 3335414c70cbSLiam Girdwood * DRMS will sum the total requested load on the regulator and change 3336414c70cbSLiam Girdwood * to the most efficient operating mode if platform constraints allow. 3337414c70cbSLiam Girdwood * 3338e39ce48fSBjorn Andersson * On error a negative errno is returned. 3339414c70cbSLiam Girdwood */ 3340e39ce48fSBjorn Andersson int regulator_set_load(struct regulator *regulator, int uA_load) 3341414c70cbSLiam Girdwood { 3342414c70cbSLiam Girdwood struct regulator_dev *rdev = regulator->rdev; 33438460ef38SBjorn Andersson int ret; 3344d92d95b6SStephen Boyd 3345414c70cbSLiam Girdwood mutex_lock(&rdev->mutex); 3346414c70cbSLiam Girdwood regulator->uA_load = uA_load; 33478460ef38SBjorn Andersson ret = drms_uA_update(rdev); 3348414c70cbSLiam Girdwood mutex_unlock(&rdev->mutex); 33498460ef38SBjorn Andersson 3350414c70cbSLiam Girdwood return ret; 3351414c70cbSLiam Girdwood } 3352e39ce48fSBjorn Andersson EXPORT_SYMBOL_GPL(regulator_set_load); 3353414c70cbSLiam Girdwood 3354414c70cbSLiam Girdwood /** 3355f59c8f9fSMark Brown * regulator_allow_bypass - allow the regulator to go into bypass mode 3356f59c8f9fSMark Brown * 3357f59c8f9fSMark Brown * @regulator: Regulator to configure 33589345dfb8SNishanth Menon * @enable: enable or disable bypass mode 3359f59c8f9fSMark Brown * 3360f59c8f9fSMark Brown * Allow the regulator to go into bypass mode if all other consumers 3361f59c8f9fSMark Brown * for the regulator also enable bypass mode and the machine 3362f59c8f9fSMark Brown * constraints allow this. Bypass mode means that the regulator is 3363f59c8f9fSMark Brown * simply passing the input directly to the output with no regulation. 3364f59c8f9fSMark Brown */ 3365f59c8f9fSMark Brown int regulator_allow_bypass(struct regulator *regulator, bool enable) 3366f59c8f9fSMark Brown { 3367f59c8f9fSMark Brown struct regulator_dev *rdev = regulator->rdev; 3368f59c8f9fSMark Brown int ret = 0; 3369f59c8f9fSMark Brown 3370f59c8f9fSMark Brown if (!rdev->desc->ops->set_bypass) 3371f59c8f9fSMark Brown return 0; 3372f59c8f9fSMark Brown 3373f59c8f9fSMark Brown if (rdev->constraints && 3374f59c8f9fSMark Brown !(rdev->constraints->valid_ops_mask & REGULATOR_CHANGE_BYPASS)) 3375f59c8f9fSMark Brown return 0; 3376f59c8f9fSMark Brown 3377f59c8f9fSMark Brown mutex_lock(&rdev->mutex); 3378f59c8f9fSMark Brown 3379f59c8f9fSMark Brown if (enable && !regulator->bypass) { 3380f59c8f9fSMark Brown rdev->bypass_count++; 3381f59c8f9fSMark Brown 3382f59c8f9fSMark Brown if (rdev->bypass_count == rdev->open_count) { 3383f59c8f9fSMark Brown ret = rdev->desc->ops->set_bypass(rdev, enable); 3384f59c8f9fSMark Brown if (ret != 0) 3385f59c8f9fSMark Brown rdev->bypass_count--; 3386f59c8f9fSMark Brown } 3387f59c8f9fSMark Brown 3388f59c8f9fSMark Brown } else if (!enable && regulator->bypass) { 3389f59c8f9fSMark Brown rdev->bypass_count--; 3390f59c8f9fSMark Brown 3391f59c8f9fSMark Brown if (rdev->bypass_count != rdev->open_count) { 3392f59c8f9fSMark Brown ret = rdev->desc->ops->set_bypass(rdev, enable); 3393f59c8f9fSMark Brown if (ret != 0) 3394f59c8f9fSMark Brown rdev->bypass_count++; 3395f59c8f9fSMark Brown } 3396f59c8f9fSMark Brown } 3397f59c8f9fSMark Brown 3398f59c8f9fSMark Brown if (ret == 0) 3399f59c8f9fSMark Brown regulator->bypass = enable; 3400f59c8f9fSMark Brown 3401f59c8f9fSMark Brown mutex_unlock(&rdev->mutex); 3402f59c8f9fSMark Brown 3403f59c8f9fSMark Brown return ret; 3404f59c8f9fSMark Brown } 3405f59c8f9fSMark Brown EXPORT_SYMBOL_GPL(regulator_allow_bypass); 3406f59c8f9fSMark Brown 3407f59c8f9fSMark Brown /** 3408414c70cbSLiam Girdwood * regulator_register_notifier - register regulator event notifier 3409414c70cbSLiam Girdwood * @regulator: regulator source 341069279fb9SMark Brown * @nb: notifier block 3411414c70cbSLiam Girdwood * 3412414c70cbSLiam Girdwood * Register notifier block to receive regulator events. 3413414c70cbSLiam Girdwood */ 3414414c70cbSLiam Girdwood int regulator_register_notifier(struct regulator *regulator, 3415414c70cbSLiam Girdwood struct notifier_block *nb) 3416414c70cbSLiam Girdwood { 3417414c70cbSLiam Girdwood return blocking_notifier_chain_register(®ulator->rdev->notifier, 3418414c70cbSLiam Girdwood nb); 3419414c70cbSLiam Girdwood } 3420414c70cbSLiam Girdwood EXPORT_SYMBOL_GPL(regulator_register_notifier); 3421414c70cbSLiam Girdwood 3422414c70cbSLiam Girdwood /** 3423414c70cbSLiam Girdwood * regulator_unregister_notifier - unregister regulator event notifier 3424414c70cbSLiam Girdwood * @regulator: regulator source 342569279fb9SMark Brown * @nb: notifier block 3426414c70cbSLiam Girdwood * 3427414c70cbSLiam Girdwood * Unregister regulator event notifier block. 3428414c70cbSLiam Girdwood */ 3429414c70cbSLiam Girdwood int regulator_unregister_notifier(struct regulator *regulator, 3430414c70cbSLiam Girdwood struct notifier_block *nb) 3431414c70cbSLiam Girdwood { 3432414c70cbSLiam Girdwood return blocking_notifier_chain_unregister(®ulator->rdev->notifier, 3433414c70cbSLiam Girdwood nb); 3434414c70cbSLiam Girdwood } 3435414c70cbSLiam Girdwood EXPORT_SYMBOL_GPL(regulator_unregister_notifier); 3436414c70cbSLiam Girdwood 3437b136fb44SJonathan Cameron /* notify regulator consumers and downstream regulator consumers. 3438b136fb44SJonathan Cameron * Note mutex must be held by caller. 3439b136fb44SJonathan Cameron */ 34407179569aSHeiko Stübner static int _notifier_call_chain(struct regulator_dev *rdev, 3441414c70cbSLiam Girdwood unsigned long event, void *data) 3442414c70cbSLiam Girdwood { 3443414c70cbSLiam Girdwood /* call rdev chain first */ 34447179569aSHeiko Stübner return blocking_notifier_call_chain(&rdev->notifier, event, data); 3445414c70cbSLiam Girdwood } 3446414c70cbSLiam Girdwood 3447414c70cbSLiam Girdwood /** 3448414c70cbSLiam Girdwood * regulator_bulk_get - get multiple regulator consumers 3449414c70cbSLiam Girdwood * 3450414c70cbSLiam Girdwood * @dev: Device to supply 3451414c70cbSLiam Girdwood * @num_consumers: Number of consumers to register 3452414c70cbSLiam Girdwood * @consumers: Configuration of consumers; clients are stored here. 3453414c70cbSLiam Girdwood * 3454414c70cbSLiam Girdwood * @return 0 on success, an errno on failure. 3455414c70cbSLiam Girdwood * 3456414c70cbSLiam Girdwood * This helper function allows drivers to get several regulator 3457414c70cbSLiam Girdwood * consumers in one operation. If any of the regulators cannot be 3458414c70cbSLiam Girdwood * acquired then any regulators that were allocated will be freed 3459414c70cbSLiam Girdwood * before returning to the caller. 3460414c70cbSLiam Girdwood */ 3461414c70cbSLiam Girdwood int regulator_bulk_get(struct device *dev, int num_consumers, 3462414c70cbSLiam Girdwood struct regulator_bulk_data *consumers) 3463414c70cbSLiam Girdwood { 3464414c70cbSLiam Girdwood int i; 3465414c70cbSLiam Girdwood int ret; 3466414c70cbSLiam Girdwood 3467414c70cbSLiam Girdwood for (i = 0; i < num_consumers; i++) 3468414c70cbSLiam Girdwood consumers[i].consumer = NULL; 3469414c70cbSLiam Girdwood 3470414c70cbSLiam Girdwood for (i = 0; i < num_consumers; i++) { 34713ff3f518SBjorn Andersson consumers[i].consumer = _regulator_get(dev, 34723ff3f518SBjorn Andersson consumers[i].supply, 34733ff3f518SBjorn Andersson false, 34743ff3f518SBjorn Andersson !consumers[i].optional); 3475414c70cbSLiam Girdwood if (IS_ERR(consumers[i].consumer)) { 3476414c70cbSLiam Girdwood ret = PTR_ERR(consumers[i].consumer); 34775b307627SMark Brown dev_err(dev, "Failed to get supply '%s': %d\n", 34785b307627SMark Brown consumers[i].supply, ret); 3479414c70cbSLiam Girdwood consumers[i].consumer = NULL; 3480414c70cbSLiam Girdwood goto err; 3481414c70cbSLiam Girdwood } 3482414c70cbSLiam Girdwood } 3483414c70cbSLiam Girdwood 3484414c70cbSLiam Girdwood return 0; 3485414c70cbSLiam Girdwood 3486414c70cbSLiam Girdwood err: 3487b29c7690SAxel Lin while (--i >= 0) 3488414c70cbSLiam Girdwood regulator_put(consumers[i].consumer); 3489414c70cbSLiam Girdwood 3490414c70cbSLiam Girdwood return ret; 3491414c70cbSLiam Girdwood } 3492414c70cbSLiam Girdwood EXPORT_SYMBOL_GPL(regulator_bulk_get); 3493414c70cbSLiam Girdwood 3494f21e0e81SMark Brown static void regulator_bulk_enable_async(void *data, async_cookie_t cookie) 3495f21e0e81SMark Brown { 3496f21e0e81SMark Brown struct regulator_bulk_data *bulk = data; 3497f21e0e81SMark Brown 3498f21e0e81SMark Brown bulk->ret = regulator_enable(bulk->consumer); 3499f21e0e81SMark Brown } 3500f21e0e81SMark Brown 3501414c70cbSLiam Girdwood /** 3502414c70cbSLiam Girdwood * regulator_bulk_enable - enable multiple regulator consumers 3503414c70cbSLiam Girdwood * 3504414c70cbSLiam Girdwood * @num_consumers: Number of consumers 3505414c70cbSLiam Girdwood * @consumers: Consumer data; clients are stored here. 3506414c70cbSLiam Girdwood * @return 0 on success, an errno on failure 3507414c70cbSLiam Girdwood * 3508414c70cbSLiam Girdwood * This convenience API allows consumers to enable multiple regulator 3509414c70cbSLiam Girdwood * clients in a single API call. If any consumers cannot be enabled 3510414c70cbSLiam Girdwood * then any others that were enabled will be disabled again prior to 3511414c70cbSLiam Girdwood * return. 3512414c70cbSLiam Girdwood */ 3513414c70cbSLiam Girdwood int regulator_bulk_enable(int num_consumers, 3514414c70cbSLiam Girdwood struct regulator_bulk_data *consumers) 3515414c70cbSLiam Girdwood { 35162955b47dSDan Williams ASYNC_DOMAIN_EXCLUSIVE(async_domain); 3517414c70cbSLiam Girdwood int i; 3518f21e0e81SMark Brown int ret = 0; 3519414c70cbSLiam Girdwood 35206492bc1bSMark Brown for (i = 0; i < num_consumers; i++) { 35216492bc1bSMark Brown if (consumers[i].consumer->always_on) 35226492bc1bSMark Brown consumers[i].ret = 0; 35236492bc1bSMark Brown else 3524f21e0e81SMark Brown async_schedule_domain(regulator_bulk_enable_async, 3525f21e0e81SMark Brown &consumers[i], &async_domain); 35266492bc1bSMark Brown } 3527f21e0e81SMark Brown 3528f21e0e81SMark Brown async_synchronize_full_domain(&async_domain); 3529f21e0e81SMark Brown 3530f21e0e81SMark Brown /* If any consumer failed we need to unwind any that succeeded */ 3531414c70cbSLiam Girdwood for (i = 0; i < num_consumers; i++) { 3532f21e0e81SMark Brown if (consumers[i].ret != 0) { 3533f21e0e81SMark Brown ret = consumers[i].ret; 3534414c70cbSLiam Girdwood goto err; 3535414c70cbSLiam Girdwood } 3536f21e0e81SMark Brown } 3537414c70cbSLiam Girdwood 3538414c70cbSLiam Girdwood return 0; 3539414c70cbSLiam Girdwood 3540414c70cbSLiam Girdwood err: 3541fbe31057SAndrzej Hajda for (i = 0; i < num_consumers; i++) { 3542fbe31057SAndrzej Hajda if (consumers[i].ret < 0) 3543fbe31057SAndrzej Hajda pr_err("Failed to enable %s: %d\n", consumers[i].supply, 3544fbe31057SAndrzej Hajda consumers[i].ret); 3545fbe31057SAndrzej Hajda else 3546414c70cbSLiam Girdwood regulator_disable(consumers[i].consumer); 3547fbe31057SAndrzej Hajda } 3548414c70cbSLiam Girdwood 3549414c70cbSLiam Girdwood return ret; 3550414c70cbSLiam Girdwood } 3551414c70cbSLiam Girdwood EXPORT_SYMBOL_GPL(regulator_bulk_enable); 3552414c70cbSLiam Girdwood 3553414c70cbSLiam Girdwood /** 3554414c70cbSLiam Girdwood * regulator_bulk_disable - disable multiple regulator consumers 3555414c70cbSLiam Girdwood * 3556414c70cbSLiam Girdwood * @num_consumers: Number of consumers 3557414c70cbSLiam Girdwood * @consumers: Consumer data; clients are stored here. 3558414c70cbSLiam Girdwood * @return 0 on success, an errno on failure 3559414c70cbSLiam Girdwood * 3560414c70cbSLiam Girdwood * This convenience API allows consumers to disable multiple regulator 356149e22632SSylwester Nawrocki * clients in a single API call. If any consumers cannot be disabled 356249e22632SSylwester Nawrocki * then any others that were disabled will be enabled again prior to 3563414c70cbSLiam Girdwood * return. 3564414c70cbSLiam Girdwood */ 3565414c70cbSLiam Girdwood int regulator_bulk_disable(int num_consumers, 3566414c70cbSLiam Girdwood struct regulator_bulk_data *consumers) 3567414c70cbSLiam Girdwood { 3568414c70cbSLiam Girdwood int i; 356901e86f49SMark Brown int ret, r; 3570414c70cbSLiam Girdwood 357149e22632SSylwester Nawrocki for (i = num_consumers - 1; i >= 0; --i) { 3572414c70cbSLiam Girdwood ret = regulator_disable(consumers[i].consumer); 3573414c70cbSLiam Girdwood if (ret != 0) 3574414c70cbSLiam Girdwood goto err; 3575414c70cbSLiam Girdwood } 3576414c70cbSLiam Girdwood 3577414c70cbSLiam Girdwood return 0; 3578414c70cbSLiam Girdwood 3579414c70cbSLiam Girdwood err: 35805da84fd9SJoe Perches pr_err("Failed to disable %s: %d\n", consumers[i].supply, ret); 358101e86f49SMark Brown for (++i; i < num_consumers; ++i) { 358201e86f49SMark Brown r = regulator_enable(consumers[i].consumer); 358301e86f49SMark Brown if (r != 0) 358401e86f49SMark Brown pr_err("Failed to reename %s: %d\n", 358501e86f49SMark Brown consumers[i].supply, r); 358601e86f49SMark Brown } 3587414c70cbSLiam Girdwood 3588414c70cbSLiam Girdwood return ret; 3589414c70cbSLiam Girdwood } 3590414c70cbSLiam Girdwood EXPORT_SYMBOL_GPL(regulator_bulk_disable); 3591414c70cbSLiam Girdwood 3592414c70cbSLiam Girdwood /** 3593e1de2f42SDonggeun Kim * regulator_bulk_force_disable - force disable multiple regulator consumers 3594e1de2f42SDonggeun Kim * 3595e1de2f42SDonggeun Kim * @num_consumers: Number of consumers 3596e1de2f42SDonggeun Kim * @consumers: Consumer data; clients are stored here. 3597e1de2f42SDonggeun Kim * @return 0 on success, an errno on failure 3598e1de2f42SDonggeun Kim * 3599e1de2f42SDonggeun Kim * This convenience API allows consumers to forcibly disable multiple regulator 3600e1de2f42SDonggeun Kim * clients in a single API call. 3601e1de2f42SDonggeun Kim * NOTE: This should be used for situations when device damage will 3602e1de2f42SDonggeun Kim * likely occur if the regulators are not disabled (e.g. over temp). 3603e1de2f42SDonggeun Kim * Although regulator_force_disable function call for some consumers can 3604e1de2f42SDonggeun Kim * return error numbers, the function is called for all consumers. 3605e1de2f42SDonggeun Kim */ 3606e1de2f42SDonggeun Kim int regulator_bulk_force_disable(int num_consumers, 3607e1de2f42SDonggeun Kim struct regulator_bulk_data *consumers) 3608e1de2f42SDonggeun Kim { 3609e1de2f42SDonggeun Kim int i; 3610e1de2f42SDonggeun Kim int ret; 3611e1de2f42SDonggeun Kim 3612e1de2f42SDonggeun Kim for (i = 0; i < num_consumers; i++) 3613e1de2f42SDonggeun Kim consumers[i].ret = 3614e1de2f42SDonggeun Kim regulator_force_disable(consumers[i].consumer); 3615e1de2f42SDonggeun Kim 3616e1de2f42SDonggeun Kim for (i = 0; i < num_consumers; i++) { 3617e1de2f42SDonggeun Kim if (consumers[i].ret != 0) { 3618e1de2f42SDonggeun Kim ret = consumers[i].ret; 3619e1de2f42SDonggeun Kim goto out; 3620e1de2f42SDonggeun Kim } 3621e1de2f42SDonggeun Kim } 3622e1de2f42SDonggeun Kim 3623e1de2f42SDonggeun Kim return 0; 3624e1de2f42SDonggeun Kim out: 3625e1de2f42SDonggeun Kim return ret; 3626e1de2f42SDonggeun Kim } 3627e1de2f42SDonggeun Kim EXPORT_SYMBOL_GPL(regulator_bulk_force_disable); 3628e1de2f42SDonggeun Kim 3629e1de2f42SDonggeun Kim /** 3630414c70cbSLiam Girdwood * regulator_bulk_free - free multiple regulator consumers 3631414c70cbSLiam Girdwood * 3632414c70cbSLiam Girdwood * @num_consumers: Number of consumers 3633414c70cbSLiam Girdwood * @consumers: Consumer data; clients are stored here. 3634414c70cbSLiam Girdwood * 3635414c70cbSLiam Girdwood * This convenience API allows consumers to free multiple regulator 3636414c70cbSLiam Girdwood * clients in a single API call. 3637414c70cbSLiam Girdwood */ 3638414c70cbSLiam Girdwood void regulator_bulk_free(int num_consumers, 3639414c70cbSLiam Girdwood struct regulator_bulk_data *consumers) 3640414c70cbSLiam Girdwood { 3641414c70cbSLiam Girdwood int i; 3642414c70cbSLiam Girdwood 3643414c70cbSLiam Girdwood for (i = 0; i < num_consumers; i++) { 3644414c70cbSLiam Girdwood regulator_put(consumers[i].consumer); 3645414c70cbSLiam Girdwood consumers[i].consumer = NULL; 3646414c70cbSLiam Girdwood } 3647414c70cbSLiam Girdwood } 3648414c70cbSLiam Girdwood EXPORT_SYMBOL_GPL(regulator_bulk_free); 3649414c70cbSLiam Girdwood 3650414c70cbSLiam Girdwood /** 3651414c70cbSLiam Girdwood * regulator_notifier_call_chain - call regulator event notifier 365269279fb9SMark Brown * @rdev: regulator source 3653414c70cbSLiam Girdwood * @event: notifier block 365469279fb9SMark Brown * @data: callback-specific data. 3655414c70cbSLiam Girdwood * 3656414c70cbSLiam Girdwood * Called by regulator drivers to notify clients a regulator event has 3657414c70cbSLiam Girdwood * occurred. We also notify regulator clients downstream. 3658b136fb44SJonathan Cameron * Note lock must be held by caller. 3659414c70cbSLiam Girdwood */ 3660414c70cbSLiam Girdwood int regulator_notifier_call_chain(struct regulator_dev *rdev, 3661414c70cbSLiam Girdwood unsigned long event, void *data) 3662414c70cbSLiam Girdwood { 366370cfef26SKrzysztof Kozlowski lockdep_assert_held_once(&rdev->mutex); 366470cfef26SKrzysztof Kozlowski 3665414c70cbSLiam Girdwood _notifier_call_chain(rdev, event, data); 3666414c70cbSLiam Girdwood return NOTIFY_DONE; 3667414c70cbSLiam Girdwood 3668414c70cbSLiam Girdwood } 3669414c70cbSLiam Girdwood EXPORT_SYMBOL_GPL(regulator_notifier_call_chain); 3670414c70cbSLiam Girdwood 3671be721979SMark Brown /** 3672be721979SMark Brown * regulator_mode_to_status - convert a regulator mode into a status 3673be721979SMark Brown * 3674be721979SMark Brown * @mode: Mode to convert 3675be721979SMark Brown * 3676be721979SMark Brown * Convert a regulator mode into a status. 3677be721979SMark Brown */ 3678be721979SMark Brown int regulator_mode_to_status(unsigned int mode) 3679be721979SMark Brown { 3680be721979SMark Brown switch (mode) { 3681be721979SMark Brown case REGULATOR_MODE_FAST: 3682be721979SMark Brown return REGULATOR_STATUS_FAST; 3683be721979SMark Brown case REGULATOR_MODE_NORMAL: 3684be721979SMark Brown return REGULATOR_STATUS_NORMAL; 3685be721979SMark Brown case REGULATOR_MODE_IDLE: 3686be721979SMark Brown return REGULATOR_STATUS_IDLE; 368703ffcf3dSKrystian Garbaciak case REGULATOR_MODE_STANDBY: 3688be721979SMark Brown return REGULATOR_STATUS_STANDBY; 3689be721979SMark Brown default: 36901beaf762SKrystian Garbaciak return REGULATOR_STATUS_UNDEFINED; 3691be721979SMark Brown } 3692be721979SMark Brown } 3693be721979SMark Brown EXPORT_SYMBOL_GPL(regulator_mode_to_status); 3694be721979SMark Brown 369539f802d6STakashi Iwai static struct attribute *regulator_dev_attrs[] = { 369639f802d6STakashi Iwai &dev_attr_name.attr, 369739f802d6STakashi Iwai &dev_attr_num_users.attr, 369839f802d6STakashi Iwai &dev_attr_type.attr, 369939f802d6STakashi Iwai &dev_attr_microvolts.attr, 370039f802d6STakashi Iwai &dev_attr_microamps.attr, 370139f802d6STakashi Iwai &dev_attr_opmode.attr, 370239f802d6STakashi Iwai &dev_attr_state.attr, 370339f802d6STakashi Iwai &dev_attr_status.attr, 370439f802d6STakashi Iwai &dev_attr_bypass.attr, 370539f802d6STakashi Iwai &dev_attr_requested_microamps.attr, 370639f802d6STakashi Iwai &dev_attr_min_microvolts.attr, 370739f802d6STakashi Iwai &dev_attr_max_microvolts.attr, 370839f802d6STakashi Iwai &dev_attr_min_microamps.attr, 370939f802d6STakashi Iwai &dev_attr_max_microamps.attr, 371039f802d6STakashi Iwai &dev_attr_suspend_standby_state.attr, 371139f802d6STakashi Iwai &dev_attr_suspend_mem_state.attr, 371239f802d6STakashi Iwai &dev_attr_suspend_disk_state.attr, 371339f802d6STakashi Iwai &dev_attr_suspend_standby_microvolts.attr, 371439f802d6STakashi Iwai &dev_attr_suspend_mem_microvolts.attr, 371539f802d6STakashi Iwai &dev_attr_suspend_disk_microvolts.attr, 371639f802d6STakashi Iwai &dev_attr_suspend_standby_mode.attr, 371739f802d6STakashi Iwai &dev_attr_suspend_mem_mode.attr, 371839f802d6STakashi Iwai &dev_attr_suspend_disk_mode.attr, 371939f802d6STakashi Iwai NULL 372039f802d6STakashi Iwai }; 372139f802d6STakashi Iwai 37227ad68e2fSDavid Brownell /* 37237ad68e2fSDavid Brownell * To avoid cluttering sysfs (and memory) with useless state, only 37247ad68e2fSDavid Brownell * create attributes that can be meaningfully displayed. 37257ad68e2fSDavid Brownell */ 372639f802d6STakashi Iwai static umode_t regulator_attr_is_visible(struct kobject *kobj, 372739f802d6STakashi Iwai struct attribute *attr, int idx) 37287ad68e2fSDavid Brownell { 372939f802d6STakashi Iwai struct device *dev = kobj_to_dev(kobj); 373083080a14SGeliang Tang struct regulator_dev *rdev = dev_to_rdev(dev); 3731272e2315SGuodong Xu const struct regulator_ops *ops = rdev->desc->ops; 373239f802d6STakashi Iwai umode_t mode = attr->mode; 373339f802d6STakashi Iwai 373439f802d6STakashi Iwai /* these three are always present */ 373539f802d6STakashi Iwai if (attr == &dev_attr_name.attr || 373639f802d6STakashi Iwai attr == &dev_attr_num_users.attr || 373739f802d6STakashi Iwai attr == &dev_attr_type.attr) 373839f802d6STakashi Iwai return mode; 37397ad68e2fSDavid Brownell 37407ad68e2fSDavid Brownell /* some attributes need specific methods to be displayed */ 374139f802d6STakashi Iwai if (attr == &dev_attr_microvolts.attr) { 37424c78899bSMark Brown if ((ops->get_voltage && ops->get_voltage(rdev) >= 0) || 3743f2889e65SMark Brown (ops->get_voltage_sel && ops->get_voltage_sel(rdev) >= 0) || 37445a523605SLaxman Dewangan (ops->list_voltage && ops->list_voltage(rdev, 0) >= 0) || 374539f802d6STakashi Iwai (rdev->desc->fixed_uV && rdev->desc->n_voltages == 1)) 374639f802d6STakashi Iwai return mode; 374739f802d6STakashi Iwai return 0; 3748f59c8f9fSMark Brown } 37497ad68e2fSDavid Brownell 375039f802d6STakashi Iwai if (attr == &dev_attr_microamps.attr) 375139f802d6STakashi Iwai return ops->get_current_limit ? mode : 0; 375239f802d6STakashi Iwai 375339f802d6STakashi Iwai if (attr == &dev_attr_opmode.attr) 375439f802d6STakashi Iwai return ops->get_mode ? mode : 0; 375539f802d6STakashi Iwai 375639f802d6STakashi Iwai if (attr == &dev_attr_state.attr) 375739f802d6STakashi Iwai return (rdev->ena_pin || ops->is_enabled) ? mode : 0; 375839f802d6STakashi Iwai 375939f802d6STakashi Iwai if (attr == &dev_attr_status.attr) 376039f802d6STakashi Iwai return ops->get_status ? mode : 0; 376139f802d6STakashi Iwai 376239f802d6STakashi Iwai if (attr == &dev_attr_bypass.attr) 376339f802d6STakashi Iwai return ops->get_bypass ? mode : 0; 376439f802d6STakashi Iwai 37657ad68e2fSDavid Brownell /* some attributes are type-specific */ 376639f802d6STakashi Iwai if (attr == &dev_attr_requested_microamps.attr) 376739f802d6STakashi Iwai return rdev->desc->type == REGULATOR_CURRENT ? mode : 0; 37687ad68e2fSDavid Brownell 37697ad68e2fSDavid Brownell /* constraints need specific supporting methods */ 377039f802d6STakashi Iwai if (attr == &dev_attr_min_microvolts.attr || 377139f802d6STakashi Iwai attr == &dev_attr_max_microvolts.attr) 377239f802d6STakashi Iwai return (ops->set_voltage || ops->set_voltage_sel) ? mode : 0; 377339f802d6STakashi Iwai 377439f802d6STakashi Iwai if (attr == &dev_attr_min_microamps.attr || 377539f802d6STakashi Iwai attr == &dev_attr_max_microamps.attr) 377639f802d6STakashi Iwai return ops->set_current_limit ? mode : 0; 377739f802d6STakashi Iwai 377839f802d6STakashi Iwai if (attr == &dev_attr_suspend_standby_state.attr || 377939f802d6STakashi Iwai attr == &dev_attr_suspend_mem_state.attr || 378039f802d6STakashi Iwai attr == &dev_attr_suspend_disk_state.attr) 378139f802d6STakashi Iwai return mode; 378239f802d6STakashi Iwai 378339f802d6STakashi Iwai if (attr == &dev_attr_suspend_standby_microvolts.attr || 378439f802d6STakashi Iwai attr == &dev_attr_suspend_mem_microvolts.attr || 378539f802d6STakashi Iwai attr == &dev_attr_suspend_disk_microvolts.attr) 378639f802d6STakashi Iwai return ops->set_suspend_voltage ? mode : 0; 378739f802d6STakashi Iwai 378839f802d6STakashi Iwai if (attr == &dev_attr_suspend_standby_mode.attr || 378939f802d6STakashi Iwai attr == &dev_attr_suspend_mem_mode.attr || 379039f802d6STakashi Iwai attr == &dev_attr_suspend_disk_mode.attr) 379139f802d6STakashi Iwai return ops->set_suspend_mode ? mode : 0; 379239f802d6STakashi Iwai 379339f802d6STakashi Iwai return mode; 37947ad68e2fSDavid Brownell } 37957ad68e2fSDavid Brownell 379639f802d6STakashi Iwai static const struct attribute_group regulator_dev_group = { 379739f802d6STakashi Iwai .attrs = regulator_dev_attrs, 379839f802d6STakashi Iwai .is_visible = regulator_attr_is_visible, 379939f802d6STakashi Iwai }; 38007ad68e2fSDavid Brownell 380139f802d6STakashi Iwai static const struct attribute_group *regulator_dev_groups[] = { 380239f802d6STakashi Iwai ®ulator_dev_group, 380339f802d6STakashi Iwai NULL 380439f802d6STakashi Iwai }; 380539f802d6STakashi Iwai 380639f802d6STakashi Iwai static void regulator_dev_release(struct device *dev) 380739f802d6STakashi Iwai { 380839f802d6STakashi Iwai struct regulator_dev *rdev = dev_get_drvdata(dev); 380929f5f486SMark Brown 381029f5f486SMark Brown kfree(rdev->constraints); 381129f5f486SMark Brown of_node_put(rdev->dev.of_node); 381239f802d6STakashi Iwai kfree(rdev); 38137ad68e2fSDavid Brownell } 38147ad68e2fSDavid Brownell 381539f802d6STakashi Iwai static struct class regulator_class = { 381639f802d6STakashi Iwai .name = "regulator", 381739f802d6STakashi Iwai .dev_release = regulator_dev_release, 381839f802d6STakashi Iwai .dev_groups = regulator_dev_groups, 381939f802d6STakashi Iwai }; 38207ad68e2fSDavid Brownell 38211130e5b3SMark Brown static void rdev_init_debugfs(struct regulator_dev *rdev) 38221130e5b3SMark Brown { 3823a9eaa813SGuenter Roeck struct device *parent = rdev->dev.parent; 3824a9eaa813SGuenter Roeck const char *rname = rdev_get_name(rdev); 3825a9eaa813SGuenter Roeck char name[NAME_MAX]; 3826a9eaa813SGuenter Roeck 3827a9eaa813SGuenter Roeck /* Avoid duplicate debugfs directory names */ 3828a9eaa813SGuenter Roeck if (parent && rname == rdev->desc->name) { 3829a9eaa813SGuenter Roeck snprintf(name, sizeof(name), "%s-%s", dev_name(parent), 3830a9eaa813SGuenter Roeck rname); 3831a9eaa813SGuenter Roeck rname = name; 3832a9eaa813SGuenter Roeck } 3833a9eaa813SGuenter Roeck 3834a9eaa813SGuenter Roeck rdev->debugfs = debugfs_create_dir(rname, debugfs_root); 383524751434SStephen Boyd if (!rdev->debugfs) { 38361130e5b3SMark Brown rdev_warn(rdev, "Failed to create debugfs directory\n"); 38371130e5b3SMark Brown return; 38381130e5b3SMark Brown } 38391130e5b3SMark Brown 38401130e5b3SMark Brown debugfs_create_u32("use_count", 0444, rdev->debugfs, 38411130e5b3SMark Brown &rdev->use_count); 38421130e5b3SMark Brown debugfs_create_u32("open_count", 0444, rdev->debugfs, 38431130e5b3SMark Brown &rdev->open_count); 3844f59c8f9fSMark Brown debugfs_create_u32("bypass_count", 0444, rdev->debugfs, 3845f59c8f9fSMark Brown &rdev->bypass_count); 38461130e5b3SMark Brown } 38471130e5b3SMark Brown 3848414c70cbSLiam Girdwood /** 3849414c70cbSLiam Girdwood * regulator_register - register regulator 385069279fb9SMark Brown * @regulator_desc: regulator to register 3851f47531b1SKrzysztof Kozlowski * @cfg: runtime configuration for regulator 3852414c70cbSLiam Girdwood * 3853414c70cbSLiam Girdwood * Called by regulator drivers to register a regulator. 38540384618aSAxel Lin * Returns a valid pointer to struct regulator_dev on success 38550384618aSAxel Lin * or an ERR_PTR() on error. 3856414c70cbSLiam Girdwood */ 385765f26846SMark Brown struct regulator_dev * 385865f26846SMark Brown regulator_register(const struct regulator_desc *regulator_desc, 38591b3de223SKrzysztof Kozlowski const struct regulator_config *cfg) 3860414c70cbSLiam Girdwood { 38619a8f5e07SMark Brown const struct regulation_constraints *constraints = NULL; 3862c172708dSMark Brown const struct regulator_init_data *init_data; 38631b3de223SKrzysztof Kozlowski struct regulator_config *config = NULL; 386472dca06fSAniroop Mathur static atomic_t regulator_no = ATOMIC_INIT(-1); 3865414c70cbSLiam Girdwood struct regulator_dev *rdev; 386632c8fad4SMark Brown struct device *dev; 3867a5766f11SLiam Girdwood int ret, i; 3868414c70cbSLiam Girdwood 38691b3de223SKrzysztof Kozlowski if (regulator_desc == NULL || cfg == NULL) 3870414c70cbSLiam Girdwood return ERR_PTR(-EINVAL); 3871414c70cbSLiam Girdwood 38721b3de223SKrzysztof Kozlowski dev = cfg->dev; 3873dcf70112SMark Brown WARN_ON(!dev); 387432c8fad4SMark Brown 3875414c70cbSLiam Girdwood if (regulator_desc->name == NULL || regulator_desc->ops == NULL) 3876414c70cbSLiam Girdwood return ERR_PTR(-EINVAL); 3877414c70cbSLiam Girdwood 3878cd78dfc6SDiego Liziero if (regulator_desc->type != REGULATOR_VOLTAGE && 3879cd78dfc6SDiego Liziero regulator_desc->type != REGULATOR_CURRENT) 3880414c70cbSLiam Girdwood return ERR_PTR(-EINVAL); 3881414c70cbSLiam Girdwood 3882476c2d83SMark Brown /* Only one of each should be implemented */ 3883476c2d83SMark Brown WARN_ON(regulator_desc->ops->get_voltage && 3884476c2d83SMark Brown regulator_desc->ops->get_voltage_sel); 3885e8eef82bSMark Brown WARN_ON(regulator_desc->ops->set_voltage && 3886e8eef82bSMark Brown regulator_desc->ops->set_voltage_sel); 3887476c2d83SMark Brown 3888476c2d83SMark Brown /* If we're using selectors we must implement list_voltage. */ 3889476c2d83SMark Brown if (regulator_desc->ops->get_voltage_sel && 3890476c2d83SMark Brown !regulator_desc->ops->list_voltage) { 3891476c2d83SMark Brown return ERR_PTR(-EINVAL); 3892476c2d83SMark Brown } 3893e8eef82bSMark Brown if (regulator_desc->ops->set_voltage_sel && 3894e8eef82bSMark Brown !regulator_desc->ops->list_voltage) { 3895e8eef82bSMark Brown return ERR_PTR(-EINVAL); 3896e8eef82bSMark Brown } 3897476c2d83SMark Brown 3898414c70cbSLiam Girdwood rdev = kzalloc(sizeof(struct regulator_dev), GFP_KERNEL); 3899414c70cbSLiam Girdwood if (rdev == NULL) 3900414c70cbSLiam Girdwood return ERR_PTR(-ENOMEM); 3901414c70cbSLiam Girdwood 39021b3de223SKrzysztof Kozlowski /* 39031b3de223SKrzysztof Kozlowski * Duplicate the config so the driver could override it after 39041b3de223SKrzysztof Kozlowski * parsing init data. 39051b3de223SKrzysztof Kozlowski */ 39061b3de223SKrzysztof Kozlowski config = kmemdup(cfg, sizeof(*cfg), GFP_KERNEL); 39071b3de223SKrzysztof Kozlowski if (config == NULL) { 39081b3de223SKrzysztof Kozlowski kfree(rdev); 39091b3de223SKrzysztof Kozlowski return ERR_PTR(-ENOMEM); 39101b3de223SKrzysztof Kozlowski } 39111b3de223SKrzysztof Kozlowski 3912bfa21a0dSKrzysztof Kozlowski init_data = regulator_of_get_init_data(dev, regulator_desc, config, 3913a0c7b164SMark Brown &rdev->dev.of_node); 3914a0c7b164SMark Brown if (!init_data) { 3915a0c7b164SMark Brown init_data = config->init_data; 3916a0c7b164SMark Brown rdev->dev.of_node = of_node_get(config->of_node); 3917a0c7b164SMark Brown } 3918a0c7b164SMark Brown 3919414c70cbSLiam Girdwood mutex_lock(®ulator_list_mutex); 3920414c70cbSLiam Girdwood 3921414c70cbSLiam Girdwood mutex_init(&rdev->mutex); 3922c172708dSMark Brown rdev->reg_data = config->driver_data; 3923414c70cbSLiam Girdwood rdev->owner = regulator_desc->owner; 3924414c70cbSLiam Girdwood rdev->desc = regulator_desc; 39253a4b0a07SMark Brown if (config->regmap) 392665b19ce6SMark Brown rdev->regmap = config->regmap; 392752b84dacSAnilKumar Ch else if (dev_get_regmap(dev, NULL)) 39283a4b0a07SMark Brown rdev->regmap = dev_get_regmap(dev, NULL); 392952b84dacSAnilKumar Ch else if (dev->parent) 393052b84dacSAnilKumar Ch rdev->regmap = dev_get_regmap(dev->parent, NULL); 3931414c70cbSLiam Girdwood INIT_LIST_HEAD(&rdev->consumer_list); 3932414c70cbSLiam Girdwood INIT_LIST_HEAD(&rdev->list); 3933414c70cbSLiam Girdwood BLOCKING_INIT_NOTIFIER_HEAD(&rdev->notifier); 3934da07ecd9SMark Brown INIT_DELAYED_WORK(&rdev->disable_work, regulator_disable_work); 3935414c70cbSLiam Girdwood 3936a5766f11SLiam Girdwood /* preform any regulator specific init */ 39379a8f5e07SMark Brown if (init_data && init_data->regulator_init) { 3938a5766f11SLiam Girdwood ret = init_data->regulator_init(rdev->reg_data); 39394fca9545SDavid Brownell if (ret < 0) 39404fca9545SDavid Brownell goto clean; 3941a5766f11SLiam Girdwood } 3942a5766f11SLiam Girdwood 3943a5766f11SLiam Girdwood /* register with sysfs */ 3944a5766f11SLiam Girdwood rdev->dev.class = ®ulator_class; 3945a5766f11SLiam Girdwood rdev->dev.parent = dev; 394672dca06fSAniroop Mathur dev_set_name(&rdev->dev, "regulator.%lu", 394739138818SAniroop Mathur (unsigned long) atomic_inc_return(®ulator_no)); 3948a5766f11SLiam Girdwood ret = device_register(&rdev->dev); 3949ad7725cbSVasiliy Kulikov if (ret != 0) { 3950ad7725cbSVasiliy Kulikov put_device(&rdev->dev); 39514fca9545SDavid Brownell goto clean; 3952ad7725cbSVasiliy Kulikov } 3953a5766f11SLiam Girdwood 3954a5766f11SLiam Girdwood dev_set_drvdata(&rdev->dev, rdev); 3955a5766f11SLiam Girdwood 395676f439dfSMarkus Pargmann if ((config->ena_gpio || config->ena_gpio_initialized) && 395776f439dfSMarkus Pargmann gpio_is_valid(config->ena_gpio)) { 3958f19b00daSKim, Milo ret = regulator_ena_gpio_request(rdev, config); 395965f73508SMark Brown if (ret != 0) { 396065f73508SMark Brown rdev_err(rdev, "Failed to request enable GPIO%d: %d\n", 396165f73508SMark Brown config->ena_gpio, ret); 3962b2da55d9SAndrew Lunn goto wash; 396365f73508SMark Brown } 396465f73508SMark Brown } 396565f73508SMark Brown 396674f544c1SMike Rapoport /* set regulator constraints */ 39679a8f5e07SMark Brown if (init_data) 39689a8f5e07SMark Brown constraints = &init_data->constraints; 39699a8f5e07SMark Brown 39709a8f5e07SMark Brown ret = set_machine_constraints(rdev, constraints); 397174f544c1SMike Rapoport if (ret < 0) 397274f544c1SMike Rapoport goto scrub; 397374f544c1SMike Rapoport 39749a8f5e07SMark Brown if (init_data && init_data->supply_regulator) 39756261b06dSBjorn Andersson rdev->supply_name = init_data->supply_regulator; 397669511a45SRajendra Nayak else if (regulator_desc->supply_name) 39776261b06dSBjorn Andersson rdev->supply_name = regulator_desc->supply_name; 397869511a45SRajendra Nayak 3979a5766f11SLiam Girdwood /* add consumers devices */ 39809a8f5e07SMark Brown if (init_data) { 3981a5766f11SLiam Girdwood for (i = 0; i < init_data->num_consumer_supplies; i++) { 3982a5766f11SLiam Girdwood ret = set_consumer_device_supply(rdev, 398340f9244fSMark Brown init_data->consumer_supplies[i].dev_name, 3984a5766f11SLiam Girdwood init_data->consumer_supplies[i].supply); 398523c2f041SMark Brown if (ret < 0) { 398623c2f041SMark Brown dev_err(dev, "Failed to set supply %s\n", 398723c2f041SMark Brown init_data->consumer_supplies[i].supply); 3988d4033b54SJani Nikula goto unset_supplies; 3989a5766f11SLiam Girdwood } 399023c2f041SMark Brown } 39919a8f5e07SMark Brown } 3992a5766f11SLiam Girdwood 39931130e5b3SMark Brown rdev_init_debugfs(rdev); 3994a5766f11SLiam Girdwood out: 3995414c70cbSLiam Girdwood mutex_unlock(®ulator_list_mutex); 39961b3de223SKrzysztof Kozlowski kfree(config); 3997414c70cbSLiam Girdwood return rdev; 39984fca9545SDavid Brownell 3999d4033b54SJani Nikula unset_supplies: 4000d4033b54SJani Nikula unset_regulator_supplies(rdev); 4001d4033b54SJani Nikula 40024fca9545SDavid Brownell scrub: 4003f19b00daSKim, Milo regulator_ena_gpio_free(rdev); 40041a6958e7SAxel Lin kfree(rdev->constraints); 4005b2da55d9SAndrew Lunn wash: 40064fca9545SDavid Brownell device_unregister(&rdev->dev); 400753032dafSPaul Walmsley /* device core frees rdev */ 400853032dafSPaul Walmsley rdev = ERR_PTR(ret); 400953032dafSPaul Walmsley goto out; 401053032dafSPaul Walmsley 40114fca9545SDavid Brownell clean: 40124fca9545SDavid Brownell kfree(rdev); 40134fca9545SDavid Brownell rdev = ERR_PTR(ret); 40144fca9545SDavid Brownell goto out; 4015414c70cbSLiam Girdwood } 4016414c70cbSLiam Girdwood EXPORT_SYMBOL_GPL(regulator_register); 4017414c70cbSLiam Girdwood 4018414c70cbSLiam Girdwood /** 4019414c70cbSLiam Girdwood * regulator_unregister - unregister regulator 402069279fb9SMark Brown * @rdev: regulator to unregister 4021414c70cbSLiam Girdwood * 4022414c70cbSLiam Girdwood * Called by regulator drivers to unregister a regulator. 4023414c70cbSLiam Girdwood */ 4024414c70cbSLiam Girdwood void regulator_unregister(struct regulator_dev *rdev) 4025414c70cbSLiam Girdwood { 4026414c70cbSLiam Girdwood if (rdev == NULL) 4027414c70cbSLiam Girdwood return; 4028414c70cbSLiam Girdwood 4029891636eaSMark Brown if (rdev->supply) { 4030891636eaSMark Brown while (rdev->use_count--) 4031891636eaSMark Brown regulator_disable(rdev->supply); 4032e032b376SMark Brown regulator_put(rdev->supply); 4033891636eaSMark Brown } 4034414c70cbSLiam Girdwood mutex_lock(®ulator_list_mutex); 40351130e5b3SMark Brown debugfs_remove_recursive(rdev->debugfs); 403643829731STejun Heo flush_work(&rdev->disable_work.work); 40376bf87d17SMark Brown WARN_ON(rdev->open_count); 40380f1d747bSMike Rapoport unset_regulator_supplies(rdev); 4039414c70cbSLiam Girdwood list_del(&rdev->list); 40407cd71c3bSMark Brown mutex_unlock(®ulator_list_mutex); 4041f19b00daSKim, Milo regulator_ena_gpio_free(rdev); 404258fb5cf5SLothar Waßmann device_unregister(&rdev->dev); 4043414c70cbSLiam Girdwood } 4044414c70cbSLiam Girdwood EXPORT_SYMBOL_GPL(regulator_unregister); 4045414c70cbSLiam Girdwood 404685f3b431STomeu Vizoso static int _regulator_suspend_prepare(struct device *dev, void *data) 404785f3b431STomeu Vizoso { 404885f3b431STomeu Vizoso struct regulator_dev *rdev = dev_to_rdev(dev); 404985f3b431STomeu Vizoso const suspend_state_t *state = data; 405085f3b431STomeu Vizoso int ret; 405185f3b431STomeu Vizoso 405285f3b431STomeu Vizoso mutex_lock(&rdev->mutex); 405385f3b431STomeu Vizoso ret = suspend_prepare(rdev, *state); 405485f3b431STomeu Vizoso mutex_unlock(&rdev->mutex); 405585f3b431STomeu Vizoso 405685f3b431STomeu Vizoso return ret; 405785f3b431STomeu Vizoso } 405885f3b431STomeu Vizoso 4059414c70cbSLiam Girdwood /** 4060cf7bbcdfSMark Brown * regulator_suspend_prepare - prepare regulators for system wide suspend 4061414c70cbSLiam Girdwood * @state: system suspend state 4062414c70cbSLiam Girdwood * 4063414c70cbSLiam Girdwood * Configure each regulator with it's suspend operating parameters for state. 4064414c70cbSLiam Girdwood * This will usually be called by machine suspend code prior to supending. 4065414c70cbSLiam Girdwood */ 4066414c70cbSLiam Girdwood int regulator_suspend_prepare(suspend_state_t state) 4067414c70cbSLiam Girdwood { 4068414c70cbSLiam Girdwood /* ON is handled by regulator active state */ 4069414c70cbSLiam Girdwood if (state == PM_SUSPEND_ON) 4070414c70cbSLiam Girdwood return -EINVAL; 4071414c70cbSLiam Girdwood 407285f3b431STomeu Vizoso return class_for_each_device(®ulator_class, NULL, &state, 407385f3b431STomeu Vizoso _regulator_suspend_prepare); 4074414c70cbSLiam Girdwood } 4075414c70cbSLiam Girdwood EXPORT_SYMBOL_GPL(regulator_suspend_prepare); 4076414c70cbSLiam Girdwood 407785f3b431STomeu Vizoso static int _regulator_suspend_finish(struct device *dev, void *data) 407885f3b431STomeu Vizoso { 407985f3b431STomeu Vizoso struct regulator_dev *rdev = dev_to_rdev(dev); 408085f3b431STomeu Vizoso int ret; 408185f3b431STomeu Vizoso 408285f3b431STomeu Vizoso mutex_lock(&rdev->mutex); 408385f3b431STomeu Vizoso if (rdev->use_count > 0 || rdev->constraints->always_on) { 408485f3b431STomeu Vizoso if (!_regulator_is_enabled(rdev)) { 408585f3b431STomeu Vizoso ret = _regulator_do_enable(rdev); 408685f3b431STomeu Vizoso if (ret) 408785f3b431STomeu Vizoso dev_err(dev, 408885f3b431STomeu Vizoso "Failed to resume regulator %d\n", 408985f3b431STomeu Vizoso ret); 409085f3b431STomeu Vizoso } 409185f3b431STomeu Vizoso } else { 409285f3b431STomeu Vizoso if (!have_full_constraints()) 409385f3b431STomeu Vizoso goto unlock; 409485f3b431STomeu Vizoso if (!_regulator_is_enabled(rdev)) 409585f3b431STomeu Vizoso goto unlock; 409685f3b431STomeu Vizoso 409785f3b431STomeu Vizoso ret = _regulator_do_disable(rdev); 409885f3b431STomeu Vizoso if (ret) 409985f3b431STomeu Vizoso dev_err(dev, "Failed to suspend regulator %d\n", ret); 410085f3b431STomeu Vizoso } 410185f3b431STomeu Vizoso unlock: 410285f3b431STomeu Vizoso mutex_unlock(&rdev->mutex); 410385f3b431STomeu Vizoso 410485f3b431STomeu Vizoso /* Keep processing regulators in spite of any errors */ 410585f3b431STomeu Vizoso return 0; 410685f3b431STomeu Vizoso } 410785f3b431STomeu Vizoso 4108414c70cbSLiam Girdwood /** 41097a32b589SMyungJoo Ham * regulator_suspend_finish - resume regulators from system wide suspend 41107a32b589SMyungJoo Ham * 41117a32b589SMyungJoo Ham * Turn on regulators that might be turned off by regulator_suspend_prepare 41127a32b589SMyungJoo Ham * and that should be turned on according to the regulators properties. 41137a32b589SMyungJoo Ham */ 41147a32b589SMyungJoo Ham int regulator_suspend_finish(void) 41157a32b589SMyungJoo Ham { 411685f3b431STomeu Vizoso return class_for_each_device(®ulator_class, NULL, NULL, 411785f3b431STomeu Vizoso _regulator_suspend_finish); 41187a32b589SMyungJoo Ham } 41197a32b589SMyungJoo Ham EXPORT_SYMBOL_GPL(regulator_suspend_finish); 41207a32b589SMyungJoo Ham 41217a32b589SMyungJoo Ham /** 4122ca725561SMark Brown * regulator_has_full_constraints - the system has fully specified constraints 4123ca725561SMark Brown * 4124ca725561SMark Brown * Calling this function will cause the regulator API to disable all 4125ca725561SMark Brown * regulators which have a zero use count and don't have an always_on 4126ca725561SMark Brown * constraint in a late_initcall. 4127ca725561SMark Brown * 4128ca725561SMark Brown * The intention is that this will become the default behaviour in a 4129ca725561SMark Brown * future kernel release so users are encouraged to use this facility 4130ca725561SMark Brown * now. 4131ca725561SMark Brown */ 4132ca725561SMark Brown void regulator_has_full_constraints(void) 4133ca725561SMark Brown { 4134ca725561SMark Brown has_full_constraints = 1; 4135ca725561SMark Brown } 4136ca725561SMark Brown EXPORT_SYMBOL_GPL(regulator_has_full_constraints); 4137ca725561SMark Brown 4138ca725561SMark Brown /** 4139414c70cbSLiam Girdwood * rdev_get_drvdata - get rdev regulator driver data 414069279fb9SMark Brown * @rdev: regulator 4141414c70cbSLiam Girdwood * 4142414c70cbSLiam Girdwood * Get rdev regulator driver private data. This call can be used in the 4143414c70cbSLiam Girdwood * regulator driver context. 4144414c70cbSLiam Girdwood */ 4145414c70cbSLiam Girdwood void *rdev_get_drvdata(struct regulator_dev *rdev) 4146414c70cbSLiam Girdwood { 4147414c70cbSLiam Girdwood return rdev->reg_data; 4148414c70cbSLiam Girdwood } 4149414c70cbSLiam Girdwood EXPORT_SYMBOL_GPL(rdev_get_drvdata); 4150414c70cbSLiam Girdwood 4151414c70cbSLiam Girdwood /** 4152414c70cbSLiam Girdwood * regulator_get_drvdata - get regulator driver data 4153414c70cbSLiam Girdwood * @regulator: regulator 4154414c70cbSLiam Girdwood * 4155414c70cbSLiam Girdwood * Get regulator driver private data. This call can be used in the consumer 4156414c70cbSLiam Girdwood * driver context when non API regulator specific functions need to be called. 4157414c70cbSLiam Girdwood */ 4158414c70cbSLiam Girdwood void *regulator_get_drvdata(struct regulator *regulator) 4159414c70cbSLiam Girdwood { 4160414c70cbSLiam Girdwood return regulator->rdev->reg_data; 4161414c70cbSLiam Girdwood } 4162414c70cbSLiam Girdwood EXPORT_SYMBOL_GPL(regulator_get_drvdata); 4163414c70cbSLiam Girdwood 4164414c70cbSLiam Girdwood /** 4165414c70cbSLiam Girdwood * regulator_set_drvdata - set regulator driver data 4166414c70cbSLiam Girdwood * @regulator: regulator 4167414c70cbSLiam Girdwood * @data: data 4168414c70cbSLiam Girdwood */ 4169414c70cbSLiam Girdwood void regulator_set_drvdata(struct regulator *regulator, void *data) 4170414c70cbSLiam Girdwood { 4171414c70cbSLiam Girdwood regulator->rdev->reg_data = data; 4172414c70cbSLiam Girdwood } 4173414c70cbSLiam Girdwood EXPORT_SYMBOL_GPL(regulator_set_drvdata); 4174414c70cbSLiam Girdwood 4175414c70cbSLiam Girdwood /** 4176414c70cbSLiam Girdwood * regulator_get_id - get regulator ID 417769279fb9SMark Brown * @rdev: regulator 4178414c70cbSLiam Girdwood */ 4179414c70cbSLiam Girdwood int rdev_get_id(struct regulator_dev *rdev) 4180414c70cbSLiam Girdwood { 4181414c70cbSLiam Girdwood return rdev->desc->id; 4182414c70cbSLiam Girdwood } 4183414c70cbSLiam Girdwood EXPORT_SYMBOL_GPL(rdev_get_id); 4184414c70cbSLiam Girdwood 4185a5766f11SLiam Girdwood struct device *rdev_get_dev(struct regulator_dev *rdev) 4186a5766f11SLiam Girdwood { 4187a5766f11SLiam Girdwood return &rdev->dev; 4188a5766f11SLiam Girdwood } 4189a5766f11SLiam Girdwood EXPORT_SYMBOL_GPL(rdev_get_dev); 4190a5766f11SLiam Girdwood 4191a5766f11SLiam Girdwood void *regulator_get_init_drvdata(struct regulator_init_data *reg_init_data) 4192a5766f11SLiam Girdwood { 4193a5766f11SLiam Girdwood return reg_init_data->driver_data; 4194a5766f11SLiam Girdwood } 4195a5766f11SLiam Girdwood EXPORT_SYMBOL_GPL(regulator_get_init_drvdata); 4196a5766f11SLiam Girdwood 4197ba55a974SMark Brown #ifdef CONFIG_DEBUG_FS 4198ba55a974SMark Brown static ssize_t supply_map_read_file(struct file *file, char __user *user_buf, 4199ba55a974SMark Brown size_t count, loff_t *ppos) 4200ba55a974SMark Brown { 4201ba55a974SMark Brown char *buf = kmalloc(PAGE_SIZE, GFP_KERNEL); 4202ba55a974SMark Brown ssize_t len, ret = 0; 4203ba55a974SMark Brown struct regulator_map *map; 4204ba55a974SMark Brown 4205ba55a974SMark Brown if (!buf) 4206ba55a974SMark Brown return -ENOMEM; 4207ba55a974SMark Brown 4208ba55a974SMark Brown list_for_each_entry(map, ®ulator_map_list, list) { 4209ba55a974SMark Brown len = snprintf(buf + ret, PAGE_SIZE - ret, 4210ba55a974SMark Brown "%s -> %s.%s\n", 4211ba55a974SMark Brown rdev_get_name(map->regulator), map->dev_name, 4212ba55a974SMark Brown map->supply); 4213ba55a974SMark Brown if (len >= 0) 4214ba55a974SMark Brown ret += len; 4215ba55a974SMark Brown if (ret > PAGE_SIZE) { 4216ba55a974SMark Brown ret = PAGE_SIZE; 4217ba55a974SMark Brown break; 4218ba55a974SMark Brown } 4219ba55a974SMark Brown } 4220ba55a974SMark Brown 4221ba55a974SMark Brown ret = simple_read_from_buffer(user_buf, count, ppos, buf, ret); 4222ba55a974SMark Brown 4223ba55a974SMark Brown kfree(buf); 4224ba55a974SMark Brown 4225ba55a974SMark Brown return ret; 4226ba55a974SMark Brown } 422724751434SStephen Boyd #endif 4228ba55a974SMark Brown 4229ba55a974SMark Brown static const struct file_operations supply_map_fops = { 423024751434SStephen Boyd #ifdef CONFIG_DEBUG_FS 4231ba55a974SMark Brown .read = supply_map_read_file, 4232ba55a974SMark Brown .llseek = default_llseek, 4233ba55a974SMark Brown #endif 423424751434SStephen Boyd }; 4235ba55a974SMark Brown 42367c225ec9SHeiko Stübner #ifdef CONFIG_DEBUG_FS 423785f3b431STomeu Vizoso struct summary_data { 423885f3b431STomeu Vizoso struct seq_file *s; 423985f3b431STomeu Vizoso struct regulator_dev *parent; 424085f3b431STomeu Vizoso int level; 424185f3b431STomeu Vizoso }; 424285f3b431STomeu Vizoso 424385f3b431STomeu Vizoso static void regulator_summary_show_subtree(struct seq_file *s, 424485f3b431STomeu Vizoso struct regulator_dev *rdev, 424585f3b431STomeu Vizoso int level); 424685f3b431STomeu Vizoso 424785f3b431STomeu Vizoso static int regulator_summary_show_children(struct device *dev, void *data) 424885f3b431STomeu Vizoso { 424985f3b431STomeu Vizoso struct regulator_dev *rdev = dev_to_rdev(dev); 425085f3b431STomeu Vizoso struct summary_data *summary_data = data; 425185f3b431STomeu Vizoso 425285f3b431STomeu Vizoso if (rdev->supply && rdev->supply->rdev == summary_data->parent) 425385f3b431STomeu Vizoso regulator_summary_show_subtree(summary_data->s, rdev, 425485f3b431STomeu Vizoso summary_data->level + 1); 425585f3b431STomeu Vizoso 425685f3b431STomeu Vizoso return 0; 425785f3b431STomeu Vizoso } 425885f3b431STomeu Vizoso 42597c225ec9SHeiko Stübner static void regulator_summary_show_subtree(struct seq_file *s, 42607c225ec9SHeiko Stübner struct regulator_dev *rdev, 42617c225ec9SHeiko Stübner int level) 42627c225ec9SHeiko Stübner { 42637c225ec9SHeiko Stübner struct regulation_constraints *c; 42647c225ec9SHeiko Stübner struct regulator *consumer; 426585f3b431STomeu Vizoso struct summary_data summary_data; 42667c225ec9SHeiko Stübner 42677c225ec9SHeiko Stübner if (!rdev) 42687c225ec9SHeiko Stübner return; 42697c225ec9SHeiko Stübner 42707c225ec9SHeiko Stübner seq_printf(s, "%*s%-*s %3d %4d %6d ", 42717c225ec9SHeiko Stübner level * 3 + 1, "", 42727c225ec9SHeiko Stübner 30 - level * 3, rdev_get_name(rdev), 42737c225ec9SHeiko Stübner rdev->use_count, rdev->open_count, rdev->bypass_count); 42747c225ec9SHeiko Stübner 427523296099SHeiko Stübner seq_printf(s, "%5dmV ", _regulator_get_voltage(rdev) / 1000); 427623296099SHeiko Stübner seq_printf(s, "%5dmA ", _regulator_get_current_limit(rdev) / 1000); 42777c225ec9SHeiko Stübner 42787c225ec9SHeiko Stübner c = rdev->constraints; 42797c225ec9SHeiko Stübner if (c) { 42807c225ec9SHeiko Stübner switch (rdev->desc->type) { 42817c225ec9SHeiko Stübner case REGULATOR_VOLTAGE: 42827c225ec9SHeiko Stübner seq_printf(s, "%5dmV %5dmV ", 42837c225ec9SHeiko Stübner c->min_uV / 1000, c->max_uV / 1000); 42847c225ec9SHeiko Stübner break; 42857c225ec9SHeiko Stübner case REGULATOR_CURRENT: 42867c225ec9SHeiko Stübner seq_printf(s, "%5dmA %5dmA ", 42877c225ec9SHeiko Stübner c->min_uA / 1000, c->max_uA / 1000); 42887c225ec9SHeiko Stübner break; 42897c225ec9SHeiko Stübner } 42907c225ec9SHeiko Stübner } 42917c225ec9SHeiko Stübner 42927c225ec9SHeiko Stübner seq_puts(s, "\n"); 42937c225ec9SHeiko Stübner 42947c225ec9SHeiko Stübner list_for_each_entry(consumer, &rdev->consumer_list, list) { 42957c225ec9SHeiko Stübner if (consumer->dev->class == ®ulator_class) 42967c225ec9SHeiko Stübner continue; 42977c225ec9SHeiko Stübner 42987c225ec9SHeiko Stübner seq_printf(s, "%*s%-*s ", 42997c225ec9SHeiko Stübner (level + 1) * 3 + 1, "", 43007c225ec9SHeiko Stübner 30 - (level + 1) * 3, dev_name(consumer->dev)); 43017c225ec9SHeiko Stübner 43027c225ec9SHeiko Stübner switch (rdev->desc->type) { 43037c225ec9SHeiko Stübner case REGULATOR_VOLTAGE: 430423296099SHeiko Stübner seq_printf(s, "%37dmV %5dmV", 43057c225ec9SHeiko Stübner consumer->min_uV / 1000, 43067c225ec9SHeiko Stübner consumer->max_uV / 1000); 43077c225ec9SHeiko Stübner break; 43087c225ec9SHeiko Stübner case REGULATOR_CURRENT: 43097c225ec9SHeiko Stübner break; 43107c225ec9SHeiko Stübner } 43117c225ec9SHeiko Stübner 43127c225ec9SHeiko Stübner seq_puts(s, "\n"); 43137c225ec9SHeiko Stübner } 43147c225ec9SHeiko Stübner 431585f3b431STomeu Vizoso summary_data.s = s; 431685f3b431STomeu Vizoso summary_data.level = level; 431785f3b431STomeu Vizoso summary_data.parent = rdev; 43187c225ec9SHeiko Stübner 431985f3b431STomeu Vizoso class_for_each_device(®ulator_class, NULL, &summary_data, 432085f3b431STomeu Vizoso regulator_summary_show_children); 43217c225ec9SHeiko Stübner } 432285f3b431STomeu Vizoso 432385f3b431STomeu Vizoso static int regulator_summary_show_roots(struct device *dev, void *data) 432485f3b431STomeu Vizoso { 432585f3b431STomeu Vizoso struct regulator_dev *rdev = dev_to_rdev(dev); 432685f3b431STomeu Vizoso struct seq_file *s = data; 432785f3b431STomeu Vizoso 432885f3b431STomeu Vizoso if (!rdev->supply) 432985f3b431STomeu Vizoso regulator_summary_show_subtree(s, rdev, 0); 433085f3b431STomeu Vizoso 433185f3b431STomeu Vizoso return 0; 43327c225ec9SHeiko Stübner } 43337c225ec9SHeiko Stübner 43347c225ec9SHeiko Stübner static int regulator_summary_show(struct seq_file *s, void *data) 43357c225ec9SHeiko Stübner { 433623296099SHeiko Stübner seq_puts(s, " regulator use open bypass voltage current min max\n"); 433723296099SHeiko Stübner seq_puts(s, "-------------------------------------------------------------------------------\n"); 43387c225ec9SHeiko Stübner 433985f3b431STomeu Vizoso class_for_each_device(®ulator_class, NULL, s, 434085f3b431STomeu Vizoso regulator_summary_show_roots); 43417c225ec9SHeiko Stübner 43427c225ec9SHeiko Stübner return 0; 43437c225ec9SHeiko Stübner } 43447c225ec9SHeiko Stübner 43457c225ec9SHeiko Stübner static int regulator_summary_open(struct inode *inode, struct file *file) 43467c225ec9SHeiko Stübner { 43477c225ec9SHeiko Stübner return single_open(file, regulator_summary_show, inode->i_private); 43487c225ec9SHeiko Stübner } 43497c225ec9SHeiko Stübner #endif 43507c225ec9SHeiko Stübner 43517c225ec9SHeiko Stübner static const struct file_operations regulator_summary_fops = { 43527c225ec9SHeiko Stübner #ifdef CONFIG_DEBUG_FS 43537c225ec9SHeiko Stübner .open = regulator_summary_open, 43547c225ec9SHeiko Stübner .read = seq_read, 43557c225ec9SHeiko Stübner .llseek = seq_lseek, 43567c225ec9SHeiko Stübner .release = single_release, 43577c225ec9SHeiko Stübner #endif 43587c225ec9SHeiko Stübner }; 43597c225ec9SHeiko Stübner 4360414c70cbSLiam Girdwood static int __init regulator_init(void) 4361414c70cbSLiam Girdwood { 436234abbd68SMark Brown int ret; 436334abbd68SMark Brown 436434abbd68SMark Brown ret = class_register(®ulator_class); 436534abbd68SMark Brown 43661130e5b3SMark Brown debugfs_root = debugfs_create_dir("regulator", NULL); 436724751434SStephen Boyd if (!debugfs_root) 43681130e5b3SMark Brown pr_warn("regulator: Failed to create debugfs directory\n"); 4369ba55a974SMark Brown 4370f4d562c6SMark Brown debugfs_create_file("supply_map", 0444, debugfs_root, NULL, 4371f4d562c6SMark Brown &supply_map_fops); 43721130e5b3SMark Brown 43737c225ec9SHeiko Stübner debugfs_create_file("regulator_summary", 0444, debugfs_root, 437485f3b431STomeu Vizoso NULL, ®ulator_summary_fops); 43757c225ec9SHeiko Stübner 437634abbd68SMark Brown regulator_dummy_init(); 437734abbd68SMark Brown 437834abbd68SMark Brown return ret; 4379414c70cbSLiam Girdwood } 4380414c70cbSLiam Girdwood 4381414c70cbSLiam Girdwood /* init early to allow our consumers to complete system booting */ 4382414c70cbSLiam Girdwood core_initcall(regulator_init); 4383ca725561SMark Brown 4384609ca5f3SMark Brown static int __init regulator_late_cleanup(struct device *dev, void *data) 4385ca725561SMark Brown { 4386609ca5f3SMark Brown struct regulator_dev *rdev = dev_to_rdev(dev); 4387609ca5f3SMark Brown const struct regulator_ops *ops = rdev->desc->ops; 4388609ca5f3SMark Brown struct regulation_constraints *c = rdev->constraints; 4389ca725561SMark Brown int enabled, ret; 4390ca725561SMark Brown 439166fda75fSMarkus Pargmann if (c && c->always_on) 4392609ca5f3SMark Brown return 0; 4393ca725561SMark Brown 4394e9535834SMark Brown if (c && !(c->valid_ops_mask & REGULATOR_CHANGE_STATUS)) 4395609ca5f3SMark Brown return 0; 4396e9535834SMark Brown 4397ca725561SMark Brown mutex_lock(&rdev->mutex); 4398ca725561SMark Brown 4399ca725561SMark Brown if (rdev->use_count) 4400ca725561SMark Brown goto unlock; 4401ca725561SMark Brown 4402ca725561SMark Brown /* If we can't read the status assume it's on. */ 4403ca725561SMark Brown if (ops->is_enabled) 4404ca725561SMark Brown enabled = ops->is_enabled(rdev); 4405ca725561SMark Brown else 4406ca725561SMark Brown enabled = 1; 4407ca725561SMark Brown 4408ca725561SMark Brown if (!enabled) 4409ca725561SMark Brown goto unlock; 4410ca725561SMark Brown 441187b28417SMark Brown if (have_full_constraints()) { 4412609ca5f3SMark Brown /* We log since this may kill the system if it goes 4413609ca5f3SMark Brown * wrong. */ 44145da84fd9SJoe Perches rdev_info(rdev, "disabling\n"); 441566fda75fSMarkus Pargmann ret = _regulator_do_disable(rdev); 44160d25d09dSJingoo Han if (ret != 0) 44175da84fd9SJoe Perches rdev_err(rdev, "couldn't disable: %d\n", ret); 4418ca725561SMark Brown } else { 4419ca725561SMark Brown /* The intention is that in future we will 4420ca725561SMark Brown * assume that full constraints are provided 4421ca725561SMark Brown * so warn even if we aren't going to do 4422ca725561SMark Brown * anything here. 4423ca725561SMark Brown */ 44245da84fd9SJoe Perches rdev_warn(rdev, "incomplete constraints, leaving on\n"); 4425ca725561SMark Brown } 4426ca725561SMark Brown 4427ca725561SMark Brown unlock: 4428ca725561SMark Brown mutex_unlock(&rdev->mutex); 4429609ca5f3SMark Brown 4430609ca5f3SMark Brown return 0; 4431ca725561SMark Brown } 4432ca725561SMark Brown 4433609ca5f3SMark Brown static int __init regulator_init_complete(void) 4434609ca5f3SMark Brown { 4435609ca5f3SMark Brown /* 4436609ca5f3SMark Brown * Since DT doesn't provide an idiomatic mechanism for 4437609ca5f3SMark Brown * enabling full constraints and since it's much more natural 4438609ca5f3SMark Brown * with DT to provide them just assume that a DT enabled 4439609ca5f3SMark Brown * system has full constraints. 4440609ca5f3SMark Brown */ 4441609ca5f3SMark Brown if (of_have_populated_dt()) 4442609ca5f3SMark Brown has_full_constraints = true; 4443609ca5f3SMark Brown 4444609ca5f3SMark Brown /* If we have a full configuration then disable any regulators 4445609ca5f3SMark Brown * we have permission to change the status for and which are 4446609ca5f3SMark Brown * not in use or always_on. This is effectively the default 4447609ca5f3SMark Brown * for DT and ACPI as they have full constraints. 4448609ca5f3SMark Brown */ 4449609ca5f3SMark Brown class_for_each_device(®ulator_class, NULL, NULL, 4450609ca5f3SMark Brown regulator_late_cleanup); 4451ca725561SMark Brown 4452ca725561SMark Brown return 0; 4453ca725561SMark Brown } 4454fd482a3eSSaravana Kannan late_initcall_sync(regulator_init_complete); 4455