core.c revision 89f425ed5bf3d4fd97e840296dccd75b8e0fe4c9
1414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood/* 2414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood * core.c -- Voltage/Current Regulator framework. 3414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood * 4414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood * Copyright 2007, 2008 Wolfson Microelectronics PLC. 5a5766f11cfd3a0c03450d99c8fe548c2940be884Liam Girdwood * Copyright 2008 SlimLogic Ltd. 6414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood * 7a5766f11cfd3a0c03450d99c8fe548c2940be884Liam Girdwood * Author: Liam Girdwood <lrg@slimlogic.co.uk> 8414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood * 9414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood * This program is free software; you can redistribute it and/or modify it 10414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood * under the terms of the GNU General Public License as published by the 11414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood * Free Software Foundation; either version 2 of the License, or (at your 12414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood * option) any later version. 13414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood * 14414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood */ 15414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood 161d7372e15ebd7f56a336fabe6ee31f8e692cd9cbDaniel Walker#define pr_fmt(fmt) "%s: " fmt, __func__ 17c5e28ed78274468b92522e7f1e9a5e6080559100Daniel Walker 18414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood#include <linux/kernel.h> 19414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood#include <linux/init.h> 201130e5b3ff4a7f3f54a48d46e9d0d81b47765bd8Mark Brown#include <linux/debugfs.h> 21414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood#include <linux/device.h> 225a0e3ad6af8660be21ca98a971cd00f331318c05Tejun Heo#include <linux/slab.h> 23f21e0e81d81b649ad309cedc7226f1bed72982e0Mark Brown#include <linux/async.h> 24414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood#include <linux/err.h> 25414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood#include <linux/mutex.h> 26414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood#include <linux/suspend.h> 2731aae2beeb3d601d556b6a8c39085940ad1e9f42Mark Brown#include <linux/delay.h> 28414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood#include <linux/regulator/consumer.h> 29414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood#include <linux/regulator/driver.h> 30414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood#include <linux/regulator/machine.h> 31414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood 3202fa3ec01a0df7a8ccc356d8e245a9a1423b3596Mark Brown#define CREATE_TRACE_POINTS 3302fa3ec01a0df7a8ccc356d8e245a9a1423b3596Mark Brown#include <trace/events/regulator.h> 3402fa3ec01a0df7a8ccc356d8e245a9a1423b3596Mark Brown 3534abbd68efe09765465b81dfedeee9994f13302fMark Brown#include "dummy.h" 3634abbd68efe09765465b81dfedeee9994f13302fMark Brown 377d51a0dbe51282f3ed13cadf6e7f13a974374be2Mark Brown#define rdev_crit(rdev, fmt, ...) \ 387d51a0dbe51282f3ed13cadf6e7f13a974374be2Mark Brown pr_crit("%s: " fmt, rdev_get_name(rdev), ##__VA_ARGS__) 395da84fd99bb1ab1c7cd39d0cf7c08bb63931a59aJoe Perches#define rdev_err(rdev, fmt, ...) \ 405da84fd99bb1ab1c7cd39d0cf7c08bb63931a59aJoe Perches pr_err("%s: " fmt, rdev_get_name(rdev), ##__VA_ARGS__) 415da84fd99bb1ab1c7cd39d0cf7c08bb63931a59aJoe Perches#define rdev_warn(rdev, fmt, ...) \ 425da84fd99bb1ab1c7cd39d0cf7c08bb63931a59aJoe Perches pr_warn("%s: " fmt, rdev_get_name(rdev), ##__VA_ARGS__) 435da84fd99bb1ab1c7cd39d0cf7c08bb63931a59aJoe Perches#define rdev_info(rdev, fmt, ...) \ 445da84fd99bb1ab1c7cd39d0cf7c08bb63931a59aJoe Perches pr_info("%s: " fmt, rdev_get_name(rdev), ##__VA_ARGS__) 455da84fd99bb1ab1c7cd39d0cf7c08bb63931a59aJoe Perches#define rdev_dbg(rdev, fmt, ...) \ 465da84fd99bb1ab1c7cd39d0cf7c08bb63931a59aJoe Perches pr_debug("%s: " fmt, rdev_get_name(rdev), ##__VA_ARGS__) 475da84fd99bb1ab1c7cd39d0cf7c08bb63931a59aJoe Perches 48414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwoodstatic DEFINE_MUTEX(regulator_list_mutex); 49414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwoodstatic LIST_HEAD(regulator_list); 50414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwoodstatic LIST_HEAD(regulator_map_list); 5121cf891a47ff5e7bd77fdc524a25072c447d56bbMark Brownstatic bool has_full_constraints; 52688fe99a439f7c9dfcc52fbf7cb347f140a2dc8bMark Brownstatic bool board_wants_dummy_regulator; 53414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood 541130e5b3ff4a7f3f54a48d46e9d0d81b47765bd8Mark Brown#ifdef CONFIG_DEBUG_FS 551130e5b3ff4a7f3f54a48d46e9d0d81b47765bd8Mark Brownstatic struct dentry *debugfs_root; 561130e5b3ff4a7f3f54a48d46e9d0d81b47765bd8Mark Brown#endif 571130e5b3ff4a7f3f54a48d46e9d0d81b47765bd8Mark Brown 588dc5390d4f3fd8acc73773a56fea13544e7924dcMark Brown/* 59414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood * struct regulator_map 60414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood * 61414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood * Used to provide symbolic supply names to devices. 62414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood */ 63414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwoodstruct regulator_map { 64414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood struct list_head list; 6540f9244f4da8976eeb6d5ed6313c635ba238a9d3Mark Brown const char *dev_name; /* The dev_name() for the consumer */ 66414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood const char *supply; 67a5766f11cfd3a0c03450d99c8fe548c2940be884Liam Girdwood struct regulator_dev *regulator; 68414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood}; 69414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood 70414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood/* 71414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood * struct regulator 72414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood * 73414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood * One for each consumer device. 74414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood */ 75414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwoodstruct regulator { 76414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood struct device *dev; 77414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood struct list_head list; 78414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood int uA_load; 79414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood int min_uV; 80414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood int max_uV; 81414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood char *supply_name; 82414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood struct device_attribute dev_attr; 83414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood struct regulator_dev *rdev; 845de705194e9883a39f993e2ff96028d5aab99b37Mark Brown#ifdef CONFIG_DEBUG_FS 855de705194e9883a39f993e2ff96028d5aab99b37Mark Brown struct dentry *debugfs; 865de705194e9883a39f993e2ff96028d5aab99b37Mark Brown#endif 87414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood}; 88414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood 89414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwoodstatic int _regulator_is_enabled(struct regulator_dev *rdev); 903801b86aa482d26a8ae460f67fca29e016491a86Mark Brownstatic int _regulator_disable(struct regulator_dev *rdev); 91414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwoodstatic int _regulator_get_voltage(struct regulator_dev *rdev); 92414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwoodstatic int _regulator_get_current_limit(struct regulator_dev *rdev); 93414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwoodstatic unsigned int _regulator_get_mode(struct regulator_dev *rdev); 94414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwoodstatic void _notifier_call_chain(struct regulator_dev *rdev, 95414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood unsigned long event, void *data); 96757902513019e6ee469791ff76f954b19ca8d036Mark Brownstatic int _regulator_do_set_voltage(struct regulator_dev *rdev, 97757902513019e6ee469791ff76f954b19ca8d036Mark Brown int min_uV, int max_uV); 983801b86aa482d26a8ae460f67fca29e016491a86Mark Brownstatic struct regulator *create_regulator(struct regulator_dev *rdev, 993801b86aa482d26a8ae460f67fca29e016491a86Mark Brown struct device *dev, 1003801b86aa482d26a8ae460f67fca29e016491a86Mark Brown const char *supply_name); 101414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood 1021083c39346d482b9001944d05c09191027892226Mark Brownstatic const char *rdev_get_name(struct regulator_dev *rdev) 1031083c39346d482b9001944d05c09191027892226Mark Brown{ 1041083c39346d482b9001944d05c09191027892226Mark Brown if (rdev->constraints && rdev->constraints->name) 1051083c39346d482b9001944d05c09191027892226Mark Brown return rdev->constraints->name; 1061083c39346d482b9001944d05c09191027892226Mark Brown else if (rdev->desc->name) 1071083c39346d482b9001944d05c09191027892226Mark Brown return rdev->desc->name; 1081083c39346d482b9001944d05c09191027892226Mark Brown else 1091083c39346d482b9001944d05c09191027892226Mark Brown return ""; 1101083c39346d482b9001944d05c09191027892226Mark Brown} 1111083c39346d482b9001944d05c09191027892226Mark Brown 112414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood/* gets the regulator for a given consumer device */ 113414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwoodstatic struct regulator *get_device_regulator(struct device *dev) 114414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood{ 115414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood struct regulator *regulator = NULL; 116414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood struct regulator_dev *rdev; 117414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood 118414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood mutex_lock(®ulator_list_mutex); 119414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood list_for_each_entry(rdev, ®ulator_list, list) { 120414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood mutex_lock(&rdev->mutex); 121414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood list_for_each_entry(regulator, &rdev->consumer_list, list) { 122414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood if (regulator->dev == dev) { 123414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood mutex_unlock(&rdev->mutex); 124414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood mutex_unlock(®ulator_list_mutex); 125414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood return regulator; 126414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood } 127414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood } 128414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood mutex_unlock(&rdev->mutex); 129414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood } 130414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood mutex_unlock(®ulator_list_mutex); 131414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood return NULL; 132414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood} 133414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood 134414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood/* Platform voltage constraint check */ 135414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwoodstatic int regulator_check_voltage(struct regulator_dev *rdev, 136414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood int *min_uV, int *max_uV) 137414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood{ 138414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood BUG_ON(*min_uV > *max_uV); 139414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood 140414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood if (!rdev->constraints) { 1415da84fd99bb1ab1c7cd39d0cf7c08bb63931a59aJoe Perches rdev_err(rdev, "no constraints\n"); 142414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood return -ENODEV; 143414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood } 144414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood if (!(rdev->constraints->valid_ops_mask & REGULATOR_CHANGE_VOLTAGE)) { 1455da84fd99bb1ab1c7cd39d0cf7c08bb63931a59aJoe Perches rdev_err(rdev, "operation not allowed\n"); 146414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood return -EPERM; 147414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood } 148414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood 149414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood if (*max_uV > rdev->constraints->max_uV) 150414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood *max_uV = rdev->constraints->max_uV; 151414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood if (*min_uV < rdev->constraints->min_uV) 152414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood *min_uV = rdev->constraints->min_uV; 153414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood 15489f425ed5bf3d4fd97e840296dccd75b8e0fe4c9Mark Brown if (*min_uV > *max_uV) { 15589f425ed5bf3d4fd97e840296dccd75b8e0fe4c9Mark Brown rdev_err(rdev, "unsupportable voltage range: %d-%duV\n", 15689f425ed5bf3d4fd97e840296dccd75b8e0fe4c9Mark Brown min_uV, max_uV); 157414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood return -EINVAL; 15889f425ed5bf3d4fd97e840296dccd75b8e0fe4c9Mark Brown } 159414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood 160414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood return 0; 161414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood} 162414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood 16305fda3b1abc23d832144e9497fb218870927d645Thomas Petazzoni/* Make sure we select a voltage that suits the needs of all 16405fda3b1abc23d832144e9497fb218870927d645Thomas Petazzoni * regulator consumers 16505fda3b1abc23d832144e9497fb218870927d645Thomas Petazzoni */ 16605fda3b1abc23d832144e9497fb218870927d645Thomas Petazzonistatic int regulator_check_consumers(struct regulator_dev *rdev, 16705fda3b1abc23d832144e9497fb218870927d645Thomas Petazzoni int *min_uV, int *max_uV) 16805fda3b1abc23d832144e9497fb218870927d645Thomas Petazzoni{ 16905fda3b1abc23d832144e9497fb218870927d645Thomas Petazzoni struct regulator *regulator; 17005fda3b1abc23d832144e9497fb218870927d645Thomas Petazzoni 17105fda3b1abc23d832144e9497fb218870927d645Thomas Petazzoni list_for_each_entry(regulator, &rdev->consumer_list, list) { 1724aa922c024b2a194d7b68b22a66dfcf86e7838b3Mark Brown /* 1734aa922c024b2a194d7b68b22a66dfcf86e7838b3Mark Brown * Assume consumers that didn't say anything are OK 1744aa922c024b2a194d7b68b22a66dfcf86e7838b3Mark Brown * with anything in the constraint range. 1754aa922c024b2a194d7b68b22a66dfcf86e7838b3Mark Brown */ 1764aa922c024b2a194d7b68b22a66dfcf86e7838b3Mark Brown if (!regulator->min_uV && !regulator->max_uV) 1774aa922c024b2a194d7b68b22a66dfcf86e7838b3Mark Brown continue; 1784aa922c024b2a194d7b68b22a66dfcf86e7838b3Mark Brown 17905fda3b1abc23d832144e9497fb218870927d645Thomas Petazzoni if (*max_uV > regulator->max_uV) 18005fda3b1abc23d832144e9497fb218870927d645Thomas Petazzoni *max_uV = regulator->max_uV; 18105fda3b1abc23d832144e9497fb218870927d645Thomas Petazzoni if (*min_uV < regulator->min_uV) 18205fda3b1abc23d832144e9497fb218870927d645Thomas Petazzoni *min_uV = regulator->min_uV; 18305fda3b1abc23d832144e9497fb218870927d645Thomas Petazzoni } 18405fda3b1abc23d832144e9497fb218870927d645Thomas Petazzoni 18505fda3b1abc23d832144e9497fb218870927d645Thomas Petazzoni if (*min_uV > *max_uV) 18605fda3b1abc23d832144e9497fb218870927d645Thomas Petazzoni return -EINVAL; 18705fda3b1abc23d832144e9497fb218870927d645Thomas Petazzoni 18805fda3b1abc23d832144e9497fb218870927d645Thomas Petazzoni return 0; 18905fda3b1abc23d832144e9497fb218870927d645Thomas Petazzoni} 19005fda3b1abc23d832144e9497fb218870927d645Thomas Petazzoni 191414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood/* current constraint check */ 192414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwoodstatic int regulator_check_current_limit(struct regulator_dev *rdev, 193414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood int *min_uA, int *max_uA) 194414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood{ 195414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood BUG_ON(*min_uA > *max_uA); 196414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood 197414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood if (!rdev->constraints) { 1985da84fd99bb1ab1c7cd39d0cf7c08bb63931a59aJoe Perches rdev_err(rdev, "no constraints\n"); 199414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood return -ENODEV; 200414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood } 201414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood if (!(rdev->constraints->valid_ops_mask & REGULATOR_CHANGE_CURRENT)) { 2025da84fd99bb1ab1c7cd39d0cf7c08bb63931a59aJoe Perches rdev_err(rdev, "operation not allowed\n"); 203414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood return -EPERM; 204414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood } 205414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood 206414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood if (*max_uA > rdev->constraints->max_uA) 207414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood *max_uA = rdev->constraints->max_uA; 208414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood if (*min_uA < rdev->constraints->min_uA) 209414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood *min_uA = rdev->constraints->min_uA; 210414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood 21189f425ed5bf3d4fd97e840296dccd75b8e0fe4c9Mark Brown if (*min_uA > *max_uA) { 21289f425ed5bf3d4fd97e840296dccd75b8e0fe4c9Mark Brown rdev_err(rdev, "unsupportable current range: %d-%duA\n", 21389f425ed5bf3d4fd97e840296dccd75b8e0fe4c9Mark Brown min_uA, max_uA); 214414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood return -EINVAL; 21589f425ed5bf3d4fd97e840296dccd75b8e0fe4c9Mark Brown } 216414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood 217414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood return 0; 218414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood} 219414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood 220414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood/* operating mode constraint check */ 2212c6082341d1896218ca974cc2bb6876e36fcba5cMark Brownstatic int regulator_mode_constrain(struct regulator_dev *rdev, int *mode) 222414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood{ 2232c6082341d1896218ca974cc2bb6876e36fcba5cMark Brown switch (*mode) { 224e573520b171095c106ffbbbf4f9cbed6d9bff576David Brownell case REGULATOR_MODE_FAST: 225e573520b171095c106ffbbbf4f9cbed6d9bff576David Brownell case REGULATOR_MODE_NORMAL: 226e573520b171095c106ffbbbf4f9cbed6d9bff576David Brownell case REGULATOR_MODE_IDLE: 227e573520b171095c106ffbbbf4f9cbed6d9bff576David Brownell case REGULATOR_MODE_STANDBY: 228e573520b171095c106ffbbbf4f9cbed6d9bff576David Brownell break; 229e573520b171095c106ffbbbf4f9cbed6d9bff576David Brownell default: 23089f425ed5bf3d4fd97e840296dccd75b8e0fe4c9Mark Brown rdev_err(rdev, "invalid mode %x specified\n", *mode); 231e573520b171095c106ffbbbf4f9cbed6d9bff576David Brownell return -EINVAL; 232e573520b171095c106ffbbbf4f9cbed6d9bff576David Brownell } 233e573520b171095c106ffbbbf4f9cbed6d9bff576David Brownell 234414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood if (!rdev->constraints) { 2355da84fd99bb1ab1c7cd39d0cf7c08bb63931a59aJoe Perches rdev_err(rdev, "no constraints\n"); 236414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood return -ENODEV; 237414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood } 238414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood if (!(rdev->constraints->valid_ops_mask & REGULATOR_CHANGE_MODE)) { 2395da84fd99bb1ab1c7cd39d0cf7c08bb63931a59aJoe Perches rdev_err(rdev, "operation not allowed\n"); 240414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood return -EPERM; 241414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood } 2422c6082341d1896218ca974cc2bb6876e36fcba5cMark Brown 2432c6082341d1896218ca974cc2bb6876e36fcba5cMark Brown /* The modes are bitmasks, the most power hungry modes having 2442c6082341d1896218ca974cc2bb6876e36fcba5cMark Brown * the lowest values. If the requested mode isn't supported 2452c6082341d1896218ca974cc2bb6876e36fcba5cMark Brown * try higher modes. */ 2462c6082341d1896218ca974cc2bb6876e36fcba5cMark Brown while (*mode) { 2472c6082341d1896218ca974cc2bb6876e36fcba5cMark Brown if (rdev->constraints->valid_modes_mask & *mode) 2482c6082341d1896218ca974cc2bb6876e36fcba5cMark Brown return 0; 2492c6082341d1896218ca974cc2bb6876e36fcba5cMark Brown *mode /= 2; 250414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood } 2512c6082341d1896218ca974cc2bb6876e36fcba5cMark Brown 2522c6082341d1896218ca974cc2bb6876e36fcba5cMark Brown return -EINVAL; 253414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood} 254414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood 255414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood/* dynamic regulator mode switching constraint check */ 256414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwoodstatic int regulator_check_drms(struct regulator_dev *rdev) 257414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood{ 258414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood if (!rdev->constraints) { 2595da84fd99bb1ab1c7cd39d0cf7c08bb63931a59aJoe Perches rdev_err(rdev, "no constraints\n"); 260414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood return -ENODEV; 261414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood } 262414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood if (!(rdev->constraints->valid_ops_mask & REGULATOR_CHANGE_DRMS)) { 2635da84fd99bb1ab1c7cd39d0cf7c08bb63931a59aJoe Perches rdev_err(rdev, "operation not allowed\n"); 264414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood return -EPERM; 265414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood } 266414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood return 0; 267414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood} 268414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood 269414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwoodstatic ssize_t device_requested_uA_show(struct device *dev, 270414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood struct device_attribute *attr, char *buf) 271414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood{ 272414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood struct regulator *regulator; 273414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood 274414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood regulator = get_device_regulator(dev); 275414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood if (regulator == NULL) 276414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood return 0; 277414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood 278414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood return sprintf(buf, "%d\n", regulator->uA_load); 279414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood} 280414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood 281414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwoodstatic ssize_t regulator_uV_show(struct device *dev, 282414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood struct device_attribute *attr, char *buf) 283414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood{ 284a5766f11cfd3a0c03450d99c8fe548c2940be884Liam Girdwood struct regulator_dev *rdev = dev_get_drvdata(dev); 285414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood ssize_t ret; 286414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood 287414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood mutex_lock(&rdev->mutex); 288414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood ret = sprintf(buf, "%d\n", _regulator_get_voltage(rdev)); 289414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood mutex_unlock(&rdev->mutex); 290414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood 291414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood return ret; 292414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood} 2937ad68e2f970fd84d15ad67ce3216aed05f944a9cDavid Brownellstatic DEVICE_ATTR(microvolts, 0444, regulator_uV_show, NULL); 294414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood 295414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwoodstatic ssize_t regulator_uA_show(struct device *dev, 296414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood struct device_attribute *attr, char *buf) 297414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood{ 298a5766f11cfd3a0c03450d99c8fe548c2940be884Liam Girdwood struct regulator_dev *rdev = dev_get_drvdata(dev); 299414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood 300414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood return sprintf(buf, "%d\n", _regulator_get_current_limit(rdev)); 301414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood} 3027ad68e2f970fd84d15ad67ce3216aed05f944a9cDavid Brownellstatic DEVICE_ATTR(microamps, 0444, regulator_uA_show, NULL); 303414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood 304bc558a60b58f638ee0188affb627d4894a97b1c7Mark Brownstatic ssize_t regulator_name_show(struct device *dev, 305bc558a60b58f638ee0188affb627d4894a97b1c7Mark Brown struct device_attribute *attr, char *buf) 306bc558a60b58f638ee0188affb627d4894a97b1c7Mark Brown{ 307bc558a60b58f638ee0188affb627d4894a97b1c7Mark Brown struct regulator_dev *rdev = dev_get_drvdata(dev); 308bc558a60b58f638ee0188affb627d4894a97b1c7Mark Brown 3091083c39346d482b9001944d05c09191027892226Mark Brown return sprintf(buf, "%s\n", rdev_get_name(rdev)); 310bc558a60b58f638ee0188affb627d4894a97b1c7Mark Brown} 311bc558a60b58f638ee0188affb627d4894a97b1c7Mark Brown 3124fca9545d17b99cdb2774716b034c62a70151bcdDavid Brownellstatic ssize_t regulator_print_opmode(char *buf, int mode) 313414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood{ 314414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood switch (mode) { 315414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood case REGULATOR_MODE_FAST: 316414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood return sprintf(buf, "fast\n"); 317414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood case REGULATOR_MODE_NORMAL: 318414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood return sprintf(buf, "normal\n"); 319414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood case REGULATOR_MODE_IDLE: 320414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood return sprintf(buf, "idle\n"); 321414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood case REGULATOR_MODE_STANDBY: 322414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood return sprintf(buf, "standby\n"); 323414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood } 324414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood return sprintf(buf, "unknown\n"); 325414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood} 326414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood 3274fca9545d17b99cdb2774716b034c62a70151bcdDavid Brownellstatic ssize_t regulator_opmode_show(struct device *dev, 3284fca9545d17b99cdb2774716b034c62a70151bcdDavid Brownell struct device_attribute *attr, char *buf) 329414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood{ 330a5766f11cfd3a0c03450d99c8fe548c2940be884Liam Girdwood struct regulator_dev *rdev = dev_get_drvdata(dev); 331414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood 3324fca9545d17b99cdb2774716b034c62a70151bcdDavid Brownell return regulator_print_opmode(buf, _regulator_get_mode(rdev)); 3334fca9545d17b99cdb2774716b034c62a70151bcdDavid Brownell} 3347ad68e2f970fd84d15ad67ce3216aed05f944a9cDavid Brownellstatic DEVICE_ATTR(opmode, 0444, regulator_opmode_show, NULL); 3354fca9545d17b99cdb2774716b034c62a70151bcdDavid Brownell 3364fca9545d17b99cdb2774716b034c62a70151bcdDavid Brownellstatic ssize_t regulator_print_state(char *buf, int state) 3374fca9545d17b99cdb2774716b034c62a70151bcdDavid Brownell{ 338414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood if (state > 0) 339414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood return sprintf(buf, "enabled\n"); 340414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood else if (state == 0) 341414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood return sprintf(buf, "disabled\n"); 342414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood else 343414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood return sprintf(buf, "unknown\n"); 344414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood} 345414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood 3464fca9545d17b99cdb2774716b034c62a70151bcdDavid Brownellstatic ssize_t regulator_state_show(struct device *dev, 3474fca9545d17b99cdb2774716b034c62a70151bcdDavid Brownell struct device_attribute *attr, char *buf) 3484fca9545d17b99cdb2774716b034c62a70151bcdDavid Brownell{ 3494fca9545d17b99cdb2774716b034c62a70151bcdDavid Brownell struct regulator_dev *rdev = dev_get_drvdata(dev); 3509332546fe88fa88bf6a7d9b1dce53ff5d314934eMark Brown ssize_t ret; 3519332546fe88fa88bf6a7d9b1dce53ff5d314934eMark Brown 3529332546fe88fa88bf6a7d9b1dce53ff5d314934eMark Brown mutex_lock(&rdev->mutex); 3539332546fe88fa88bf6a7d9b1dce53ff5d314934eMark Brown ret = regulator_print_state(buf, _regulator_is_enabled(rdev)); 3549332546fe88fa88bf6a7d9b1dce53ff5d314934eMark Brown mutex_unlock(&rdev->mutex); 3554fca9545d17b99cdb2774716b034c62a70151bcdDavid Brownell 3569332546fe88fa88bf6a7d9b1dce53ff5d314934eMark Brown return ret; 3574fca9545d17b99cdb2774716b034c62a70151bcdDavid Brownell} 3587ad68e2f970fd84d15ad67ce3216aed05f944a9cDavid Brownellstatic DEVICE_ATTR(state, 0444, regulator_state_show, NULL); 3594fca9545d17b99cdb2774716b034c62a70151bcdDavid Brownell 360853116a10544206b6b2cf42ebc9d78fba2668888David Brownellstatic ssize_t regulator_status_show(struct device *dev, 361853116a10544206b6b2cf42ebc9d78fba2668888David Brownell struct device_attribute *attr, char *buf) 362853116a10544206b6b2cf42ebc9d78fba2668888David Brownell{ 363853116a10544206b6b2cf42ebc9d78fba2668888David Brownell struct regulator_dev *rdev = dev_get_drvdata(dev); 364853116a10544206b6b2cf42ebc9d78fba2668888David Brownell int status; 365853116a10544206b6b2cf42ebc9d78fba2668888David Brownell char *label; 366853116a10544206b6b2cf42ebc9d78fba2668888David Brownell 367853116a10544206b6b2cf42ebc9d78fba2668888David Brownell status = rdev->desc->ops->get_status(rdev); 368853116a10544206b6b2cf42ebc9d78fba2668888David Brownell if (status < 0) 369853116a10544206b6b2cf42ebc9d78fba2668888David Brownell return status; 370853116a10544206b6b2cf42ebc9d78fba2668888David Brownell 371853116a10544206b6b2cf42ebc9d78fba2668888David Brownell switch (status) { 372853116a10544206b6b2cf42ebc9d78fba2668888David Brownell case REGULATOR_STATUS_OFF: 373853116a10544206b6b2cf42ebc9d78fba2668888David Brownell label = "off"; 374853116a10544206b6b2cf42ebc9d78fba2668888David Brownell break; 375853116a10544206b6b2cf42ebc9d78fba2668888David Brownell case REGULATOR_STATUS_ON: 376853116a10544206b6b2cf42ebc9d78fba2668888David Brownell label = "on"; 377853116a10544206b6b2cf42ebc9d78fba2668888David Brownell break; 378853116a10544206b6b2cf42ebc9d78fba2668888David Brownell case REGULATOR_STATUS_ERROR: 379853116a10544206b6b2cf42ebc9d78fba2668888David Brownell label = "error"; 380853116a10544206b6b2cf42ebc9d78fba2668888David Brownell break; 381853116a10544206b6b2cf42ebc9d78fba2668888David Brownell case REGULATOR_STATUS_FAST: 382853116a10544206b6b2cf42ebc9d78fba2668888David Brownell label = "fast"; 383853116a10544206b6b2cf42ebc9d78fba2668888David Brownell break; 384853116a10544206b6b2cf42ebc9d78fba2668888David Brownell case REGULATOR_STATUS_NORMAL: 385853116a10544206b6b2cf42ebc9d78fba2668888David Brownell label = "normal"; 386853116a10544206b6b2cf42ebc9d78fba2668888David Brownell break; 387853116a10544206b6b2cf42ebc9d78fba2668888David Brownell case REGULATOR_STATUS_IDLE: 388853116a10544206b6b2cf42ebc9d78fba2668888David Brownell label = "idle"; 389853116a10544206b6b2cf42ebc9d78fba2668888David Brownell break; 390853116a10544206b6b2cf42ebc9d78fba2668888David Brownell case REGULATOR_STATUS_STANDBY: 391853116a10544206b6b2cf42ebc9d78fba2668888David Brownell label = "standby"; 392853116a10544206b6b2cf42ebc9d78fba2668888David Brownell break; 393853116a10544206b6b2cf42ebc9d78fba2668888David Brownell default: 394853116a10544206b6b2cf42ebc9d78fba2668888David Brownell return -ERANGE; 395853116a10544206b6b2cf42ebc9d78fba2668888David Brownell } 396853116a10544206b6b2cf42ebc9d78fba2668888David Brownell 397853116a10544206b6b2cf42ebc9d78fba2668888David Brownell return sprintf(buf, "%s\n", label); 398853116a10544206b6b2cf42ebc9d78fba2668888David Brownell} 399853116a10544206b6b2cf42ebc9d78fba2668888David Brownellstatic DEVICE_ATTR(status, 0444, regulator_status_show, NULL); 400853116a10544206b6b2cf42ebc9d78fba2668888David Brownell 401414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwoodstatic ssize_t regulator_min_uA_show(struct device *dev, 402414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood struct device_attribute *attr, char *buf) 403414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood{ 404a5766f11cfd3a0c03450d99c8fe548c2940be884Liam Girdwood struct regulator_dev *rdev = dev_get_drvdata(dev); 405414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood 406414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood if (!rdev->constraints) 407414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood return sprintf(buf, "constraint not defined\n"); 408414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood 409414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood return sprintf(buf, "%d\n", rdev->constraints->min_uA); 410414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood} 4117ad68e2f970fd84d15ad67ce3216aed05f944a9cDavid Brownellstatic DEVICE_ATTR(min_microamps, 0444, regulator_min_uA_show, NULL); 412414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood 413414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwoodstatic ssize_t regulator_max_uA_show(struct device *dev, 414414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood struct device_attribute *attr, char *buf) 415414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood{ 416a5766f11cfd3a0c03450d99c8fe548c2940be884Liam Girdwood struct regulator_dev *rdev = dev_get_drvdata(dev); 417414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood 418414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood if (!rdev->constraints) 419414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood return sprintf(buf, "constraint not defined\n"); 420414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood 421414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood return sprintf(buf, "%d\n", rdev->constraints->max_uA); 422414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood} 4237ad68e2f970fd84d15ad67ce3216aed05f944a9cDavid Brownellstatic DEVICE_ATTR(max_microamps, 0444, regulator_max_uA_show, NULL); 424414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood 425414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwoodstatic ssize_t regulator_min_uV_show(struct device *dev, 426414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood struct device_attribute *attr, char *buf) 427414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood{ 428a5766f11cfd3a0c03450d99c8fe548c2940be884Liam Girdwood struct regulator_dev *rdev = dev_get_drvdata(dev); 429414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood 430414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood if (!rdev->constraints) 431414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood return sprintf(buf, "constraint not defined\n"); 432414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood 433414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood return sprintf(buf, "%d\n", rdev->constraints->min_uV); 434414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood} 4357ad68e2f970fd84d15ad67ce3216aed05f944a9cDavid Brownellstatic DEVICE_ATTR(min_microvolts, 0444, regulator_min_uV_show, NULL); 436414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood 437414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwoodstatic ssize_t regulator_max_uV_show(struct device *dev, 438414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood struct device_attribute *attr, char *buf) 439414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood{ 440a5766f11cfd3a0c03450d99c8fe548c2940be884Liam Girdwood struct regulator_dev *rdev = dev_get_drvdata(dev); 441414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood 442414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood if (!rdev->constraints) 443414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood return sprintf(buf, "constraint not defined\n"); 444414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood 445414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood return sprintf(buf, "%d\n", rdev->constraints->max_uV); 446414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood} 4477ad68e2f970fd84d15ad67ce3216aed05f944a9cDavid Brownellstatic DEVICE_ATTR(max_microvolts, 0444, regulator_max_uV_show, NULL); 448414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood 449414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwoodstatic ssize_t regulator_total_uA_show(struct device *dev, 450414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood struct device_attribute *attr, char *buf) 451414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood{ 452a5766f11cfd3a0c03450d99c8fe548c2940be884Liam Girdwood struct regulator_dev *rdev = dev_get_drvdata(dev); 453414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood struct regulator *regulator; 454414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood int uA = 0; 455414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood 456414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood mutex_lock(&rdev->mutex); 457414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood list_for_each_entry(regulator, &rdev->consumer_list, list) 458fa2984d4691c96367d6666694ecc6744135174c6Stefan Roese uA += regulator->uA_load; 459414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood mutex_unlock(&rdev->mutex); 460414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood return sprintf(buf, "%d\n", uA); 461414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood} 4627ad68e2f970fd84d15ad67ce3216aed05f944a9cDavid Brownellstatic DEVICE_ATTR(requested_microamps, 0444, regulator_total_uA_show, NULL); 463414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood 464414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwoodstatic ssize_t regulator_num_users_show(struct device *dev, 465414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood struct device_attribute *attr, char *buf) 466414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood{ 467a5766f11cfd3a0c03450d99c8fe548c2940be884Liam Girdwood struct regulator_dev *rdev = dev_get_drvdata(dev); 468414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood return sprintf(buf, "%d\n", rdev->use_count); 469414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood} 470414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood 471414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwoodstatic ssize_t regulator_type_show(struct device *dev, 472414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood struct device_attribute *attr, char *buf) 473414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood{ 474a5766f11cfd3a0c03450d99c8fe548c2940be884Liam Girdwood struct regulator_dev *rdev = dev_get_drvdata(dev); 475414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood 476414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood switch (rdev->desc->type) { 477414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood case REGULATOR_VOLTAGE: 478414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood return sprintf(buf, "voltage\n"); 479414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood case REGULATOR_CURRENT: 480414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood return sprintf(buf, "current\n"); 481414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood } 482414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood return sprintf(buf, "unknown\n"); 483414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood} 484414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood 485414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwoodstatic ssize_t regulator_suspend_mem_uV_show(struct device *dev, 486414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood struct device_attribute *attr, char *buf) 487414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood{ 488a5766f11cfd3a0c03450d99c8fe548c2940be884Liam Girdwood struct regulator_dev *rdev = dev_get_drvdata(dev); 489414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood 490414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood return sprintf(buf, "%d\n", rdev->constraints->state_mem.uV); 491414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood} 4927ad68e2f970fd84d15ad67ce3216aed05f944a9cDavid Brownellstatic DEVICE_ATTR(suspend_mem_microvolts, 0444, 4937ad68e2f970fd84d15ad67ce3216aed05f944a9cDavid Brownell regulator_suspend_mem_uV_show, NULL); 494414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood 495414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwoodstatic ssize_t regulator_suspend_disk_uV_show(struct device *dev, 496414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood struct device_attribute *attr, char *buf) 497414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood{ 498a5766f11cfd3a0c03450d99c8fe548c2940be884Liam Girdwood struct regulator_dev *rdev = dev_get_drvdata(dev); 499414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood 500414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood return sprintf(buf, "%d\n", rdev->constraints->state_disk.uV); 501414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood} 5027ad68e2f970fd84d15ad67ce3216aed05f944a9cDavid Brownellstatic DEVICE_ATTR(suspend_disk_microvolts, 0444, 5037ad68e2f970fd84d15ad67ce3216aed05f944a9cDavid Brownell regulator_suspend_disk_uV_show, NULL); 504414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood 505414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwoodstatic ssize_t regulator_suspend_standby_uV_show(struct device *dev, 506414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood struct device_attribute *attr, char *buf) 507414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood{ 508a5766f11cfd3a0c03450d99c8fe548c2940be884Liam Girdwood struct regulator_dev *rdev = dev_get_drvdata(dev); 509414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood 510414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood return sprintf(buf, "%d\n", rdev->constraints->state_standby.uV); 511414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood} 5127ad68e2f970fd84d15ad67ce3216aed05f944a9cDavid Brownellstatic DEVICE_ATTR(suspend_standby_microvolts, 0444, 5137ad68e2f970fd84d15ad67ce3216aed05f944a9cDavid Brownell regulator_suspend_standby_uV_show, NULL); 514414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood 515414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwoodstatic ssize_t regulator_suspend_mem_mode_show(struct device *dev, 516414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood struct device_attribute *attr, char *buf) 517414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood{ 518a5766f11cfd3a0c03450d99c8fe548c2940be884Liam Girdwood struct regulator_dev *rdev = dev_get_drvdata(dev); 519414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood 5204fca9545d17b99cdb2774716b034c62a70151bcdDavid Brownell return regulator_print_opmode(buf, 5214fca9545d17b99cdb2774716b034c62a70151bcdDavid Brownell rdev->constraints->state_mem.mode); 522414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood} 5237ad68e2f970fd84d15ad67ce3216aed05f944a9cDavid Brownellstatic DEVICE_ATTR(suspend_mem_mode, 0444, 5247ad68e2f970fd84d15ad67ce3216aed05f944a9cDavid Brownell regulator_suspend_mem_mode_show, NULL); 525414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood 526414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwoodstatic ssize_t regulator_suspend_disk_mode_show(struct device *dev, 527414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood struct device_attribute *attr, char *buf) 528414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood{ 529a5766f11cfd3a0c03450d99c8fe548c2940be884Liam Girdwood struct regulator_dev *rdev = dev_get_drvdata(dev); 530414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood 5314fca9545d17b99cdb2774716b034c62a70151bcdDavid Brownell return regulator_print_opmode(buf, 5324fca9545d17b99cdb2774716b034c62a70151bcdDavid Brownell rdev->constraints->state_disk.mode); 533414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood} 5347ad68e2f970fd84d15ad67ce3216aed05f944a9cDavid Brownellstatic DEVICE_ATTR(suspend_disk_mode, 0444, 5357ad68e2f970fd84d15ad67ce3216aed05f944a9cDavid Brownell regulator_suspend_disk_mode_show, NULL); 536414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood 537414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwoodstatic ssize_t regulator_suspend_standby_mode_show(struct device *dev, 538414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood struct device_attribute *attr, char *buf) 539414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood{ 540a5766f11cfd3a0c03450d99c8fe548c2940be884Liam Girdwood struct regulator_dev *rdev = dev_get_drvdata(dev); 541414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood 5424fca9545d17b99cdb2774716b034c62a70151bcdDavid Brownell return regulator_print_opmode(buf, 5434fca9545d17b99cdb2774716b034c62a70151bcdDavid Brownell rdev->constraints->state_standby.mode); 544414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood} 5457ad68e2f970fd84d15ad67ce3216aed05f944a9cDavid Brownellstatic DEVICE_ATTR(suspend_standby_mode, 0444, 5467ad68e2f970fd84d15ad67ce3216aed05f944a9cDavid Brownell regulator_suspend_standby_mode_show, NULL); 547414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood 548414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwoodstatic ssize_t regulator_suspend_mem_state_show(struct device *dev, 549414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood struct device_attribute *attr, char *buf) 550414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood{ 551a5766f11cfd3a0c03450d99c8fe548c2940be884Liam Girdwood struct regulator_dev *rdev = dev_get_drvdata(dev); 552414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood 5534fca9545d17b99cdb2774716b034c62a70151bcdDavid Brownell return regulator_print_state(buf, 5544fca9545d17b99cdb2774716b034c62a70151bcdDavid Brownell rdev->constraints->state_mem.enabled); 555414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood} 5567ad68e2f970fd84d15ad67ce3216aed05f944a9cDavid Brownellstatic DEVICE_ATTR(suspend_mem_state, 0444, 5577ad68e2f970fd84d15ad67ce3216aed05f944a9cDavid Brownell regulator_suspend_mem_state_show, NULL); 558414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood 559414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwoodstatic ssize_t regulator_suspend_disk_state_show(struct device *dev, 560414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood struct device_attribute *attr, char *buf) 561414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood{ 562a5766f11cfd3a0c03450d99c8fe548c2940be884Liam Girdwood struct regulator_dev *rdev = dev_get_drvdata(dev); 563414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood 5644fca9545d17b99cdb2774716b034c62a70151bcdDavid Brownell return regulator_print_state(buf, 5654fca9545d17b99cdb2774716b034c62a70151bcdDavid Brownell rdev->constraints->state_disk.enabled); 566414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood} 5677ad68e2f970fd84d15ad67ce3216aed05f944a9cDavid Brownellstatic DEVICE_ATTR(suspend_disk_state, 0444, 5687ad68e2f970fd84d15ad67ce3216aed05f944a9cDavid Brownell regulator_suspend_disk_state_show, NULL); 569414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood 570414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwoodstatic ssize_t regulator_suspend_standby_state_show(struct device *dev, 571414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood struct device_attribute *attr, char *buf) 572414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood{ 573a5766f11cfd3a0c03450d99c8fe548c2940be884Liam Girdwood struct regulator_dev *rdev = dev_get_drvdata(dev); 574414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood 5754fca9545d17b99cdb2774716b034c62a70151bcdDavid Brownell return regulator_print_state(buf, 5764fca9545d17b99cdb2774716b034c62a70151bcdDavid Brownell rdev->constraints->state_standby.enabled); 577414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood} 5787ad68e2f970fd84d15ad67ce3216aed05f944a9cDavid Brownellstatic DEVICE_ATTR(suspend_standby_state, 0444, 5797ad68e2f970fd84d15ad67ce3216aed05f944a9cDavid Brownell regulator_suspend_standby_state_show, NULL); 5807ad68e2f970fd84d15ad67ce3216aed05f944a9cDavid Brownell 581bc558a60b58f638ee0188affb627d4894a97b1c7Mark Brown 5827ad68e2f970fd84d15ad67ce3216aed05f944a9cDavid Brownell/* 5837ad68e2f970fd84d15ad67ce3216aed05f944a9cDavid Brownell * These are the only attributes are present for all regulators. 5847ad68e2f970fd84d15ad67ce3216aed05f944a9cDavid Brownell * Other attributes are a function of regulator functionality. 5857ad68e2f970fd84d15ad67ce3216aed05f944a9cDavid Brownell */ 586414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwoodstatic struct device_attribute regulator_dev_attrs[] = { 587bc558a60b58f638ee0188affb627d4894a97b1c7Mark Brown __ATTR(name, 0444, regulator_name_show, NULL), 588414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood __ATTR(num_users, 0444, regulator_num_users_show, NULL), 589414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood __ATTR(type, 0444, regulator_type_show, NULL), 590414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood __ATTR_NULL, 591414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood}; 592414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood 593414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwoodstatic void regulator_dev_release(struct device *dev) 594414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood{ 595a5766f11cfd3a0c03450d99c8fe548c2940be884Liam Girdwood struct regulator_dev *rdev = dev_get_drvdata(dev); 596414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood kfree(rdev); 597414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood} 598414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood 599414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwoodstatic struct class regulator_class = { 600414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood .name = "regulator", 601414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood .dev_release = regulator_dev_release, 602414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood .dev_attrs = regulator_dev_attrs, 603414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood}; 604414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood 605414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood/* Calculate the new optimum regulator operating mode based on the new total 606414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood * consumer load. All locks held by caller */ 607414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwoodstatic void drms_uA_update(struct regulator_dev *rdev) 608414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood{ 609414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood struct regulator *sibling; 610414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood int current_uA = 0, output_uV, input_uV, err; 611414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood unsigned int mode; 612414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood 613414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood err = regulator_check_drms(rdev); 614414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood if (err < 0 || !rdev->desc->ops->get_optimum_mode || 615476c2d83c7ffb2429b2a504fbdb4326fc8a9d0e8Mark Brown (!rdev->desc->ops->get_voltage && 616476c2d83c7ffb2429b2a504fbdb4326fc8a9d0e8Mark Brown !rdev->desc->ops->get_voltage_sel) || 617476c2d83c7ffb2429b2a504fbdb4326fc8a9d0e8Mark Brown !rdev->desc->ops->set_mode) 618036de8efae4b81f8e1504fab654070cecce6dfa9Dan Carpenter return; 619414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood 620414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood /* get output voltage */ 6211bf5a1f86a328122714680cd59951074b4f31e07Mark Brown output_uV = _regulator_get_voltage(rdev); 622414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood if (output_uV <= 0) 623414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood return; 624414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood 625414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood /* get input voltage */ 6261bf5a1f86a328122714680cd59951074b4f31e07Mark Brown input_uV = 0; 6271bf5a1f86a328122714680cd59951074b4f31e07Mark Brown if (rdev->supply) 6281bf5a1f86a328122714680cd59951074b4f31e07Mark Brown input_uV = _regulator_get_voltage(rdev); 6291bf5a1f86a328122714680cd59951074b4f31e07Mark Brown if (input_uV <= 0) 630414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood input_uV = rdev->constraints->input_uV; 631414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood if (input_uV <= 0) 632414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood return; 633414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood 634414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood /* calc total requested load */ 635414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood list_for_each_entry(sibling, &rdev->consumer_list, list) 636fa2984d4691c96367d6666694ecc6744135174c6Stefan Roese current_uA += sibling->uA_load; 637414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood 638414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood /* now get the optimum mode for our new total regulator load */ 639414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood mode = rdev->desc->ops->get_optimum_mode(rdev, input_uV, 640414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood output_uV, current_uA); 641414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood 642414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood /* check the new mode is allowed */ 6432c6082341d1896218ca974cc2bb6876e36fcba5cMark Brown err = regulator_mode_constrain(rdev, &mode); 644414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood if (err == 0) 645414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood rdev->desc->ops->set_mode(rdev, mode); 646414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood} 647414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood 648414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwoodstatic int suspend_set_state(struct regulator_dev *rdev, 649414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood struct regulator_state *rstate) 650414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood{ 651414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood int ret = 0; 652638f85c54f4fed0f8f1fbc23745a8f334112e892Mark Brown bool can_set_state; 653638f85c54f4fed0f8f1fbc23745a8f334112e892Mark Brown 654638f85c54f4fed0f8f1fbc23745a8f334112e892Mark Brown can_set_state = rdev->desc->ops->set_suspend_enable && 655638f85c54f4fed0f8f1fbc23745a8f334112e892Mark Brown rdev->desc->ops->set_suspend_disable; 656638f85c54f4fed0f8f1fbc23745a8f334112e892Mark Brown 657638f85c54f4fed0f8f1fbc23745a8f334112e892Mark Brown /* If we have no suspend mode configration don't set anything; 658638f85c54f4fed0f8f1fbc23745a8f334112e892Mark Brown * only warn if the driver actually makes the suspend mode 659638f85c54f4fed0f8f1fbc23745a8f334112e892Mark Brown * configurable. 660638f85c54f4fed0f8f1fbc23745a8f334112e892Mark Brown */ 661638f85c54f4fed0f8f1fbc23745a8f334112e892Mark Brown if (!rstate->enabled && !rstate->disabled) { 662638f85c54f4fed0f8f1fbc23745a8f334112e892Mark Brown if (can_set_state) 6635da84fd99bb1ab1c7cd39d0cf7c08bb63931a59aJoe Perches rdev_warn(rdev, "No configuration\n"); 664638f85c54f4fed0f8f1fbc23745a8f334112e892Mark Brown return 0; 665638f85c54f4fed0f8f1fbc23745a8f334112e892Mark Brown } 666638f85c54f4fed0f8f1fbc23745a8f334112e892Mark Brown 667638f85c54f4fed0f8f1fbc23745a8f334112e892Mark Brown if (rstate->enabled && rstate->disabled) { 6685da84fd99bb1ab1c7cd39d0cf7c08bb63931a59aJoe Perches rdev_err(rdev, "invalid configuration\n"); 669638f85c54f4fed0f8f1fbc23745a8f334112e892Mark Brown return -EINVAL; 670638f85c54f4fed0f8f1fbc23745a8f334112e892Mark Brown } 671414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood 672638f85c54f4fed0f8f1fbc23745a8f334112e892Mark Brown if (!can_set_state) { 6735da84fd99bb1ab1c7cd39d0cf7c08bb63931a59aJoe Perches rdev_err(rdev, "no way to set suspend state\n"); 674414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood return -EINVAL; 675a5766f11cfd3a0c03450d99c8fe548c2940be884Liam Girdwood } 676414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood 677414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood if (rstate->enabled) 678414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood ret = rdev->desc->ops->set_suspend_enable(rdev); 679414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood else 680414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood ret = rdev->desc->ops->set_suspend_disable(rdev); 681414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood if (ret < 0) { 6825da84fd99bb1ab1c7cd39d0cf7c08bb63931a59aJoe Perches rdev_err(rdev, "failed to enabled/disable\n"); 683414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood return ret; 684414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood } 685414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood 686414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood if (rdev->desc->ops->set_suspend_voltage && rstate->uV > 0) { 687414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood ret = rdev->desc->ops->set_suspend_voltage(rdev, rstate->uV); 688414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood if (ret < 0) { 6895da84fd99bb1ab1c7cd39d0cf7c08bb63931a59aJoe Perches rdev_err(rdev, "failed to set voltage\n"); 690414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood return ret; 691414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood } 692414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood } 693414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood 694414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood if (rdev->desc->ops->set_suspend_mode && rstate->mode > 0) { 695414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood ret = rdev->desc->ops->set_suspend_mode(rdev, rstate->mode); 696414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood if (ret < 0) { 6975da84fd99bb1ab1c7cd39d0cf7c08bb63931a59aJoe Perches rdev_err(rdev, "failed to set mode\n"); 698414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood return ret; 699414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood } 700414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood } 701414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood return ret; 702414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood} 703414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood 704414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood/* locks held by caller */ 705414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwoodstatic int suspend_prepare(struct regulator_dev *rdev, suspend_state_t state) 706414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood{ 707414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood if (!rdev->constraints) 708414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood return -EINVAL; 709414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood 710414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood switch (state) { 711414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood case PM_SUSPEND_STANDBY: 712414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood return suspend_set_state(rdev, 713414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood &rdev->constraints->state_standby); 714414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood case PM_SUSPEND_MEM: 715414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood return suspend_set_state(rdev, 716414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood &rdev->constraints->state_mem); 717414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood case PM_SUSPEND_MAX: 718414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood return suspend_set_state(rdev, 719414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood &rdev->constraints->state_disk); 720414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood default: 721414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood return -EINVAL; 722414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood } 723414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood} 724414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood 725414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwoodstatic void print_constraints(struct regulator_dev *rdev) 726414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood{ 727414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood struct regulation_constraints *constraints = rdev->constraints; 728973e9a2795b3b41d8408a0bb6f87b783c5efc88aMark Brown char buf[80] = ""; 7298f031b48cd2eab5fc3e4dffa06706372e90d63feMark Brown int count = 0; 7308f031b48cd2eab5fc3e4dffa06706372e90d63feMark Brown int ret; 731414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood 7328f031b48cd2eab5fc3e4dffa06706372e90d63feMark Brown if (constraints->min_uV && constraints->max_uV) { 733414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood if (constraints->min_uV == constraints->max_uV) 7348f031b48cd2eab5fc3e4dffa06706372e90d63feMark Brown count += sprintf(buf + count, "%d mV ", 7358f031b48cd2eab5fc3e4dffa06706372e90d63feMark Brown constraints->min_uV / 1000); 736414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood else 7378f031b48cd2eab5fc3e4dffa06706372e90d63feMark Brown count += sprintf(buf + count, "%d <--> %d mV ", 7388f031b48cd2eab5fc3e4dffa06706372e90d63feMark Brown constraints->min_uV / 1000, 7398f031b48cd2eab5fc3e4dffa06706372e90d63feMark Brown constraints->max_uV / 1000); 7408f031b48cd2eab5fc3e4dffa06706372e90d63feMark Brown } 7418f031b48cd2eab5fc3e4dffa06706372e90d63feMark Brown 7428f031b48cd2eab5fc3e4dffa06706372e90d63feMark Brown if (!constraints->min_uV || 7438f031b48cd2eab5fc3e4dffa06706372e90d63feMark Brown constraints->min_uV != constraints->max_uV) { 7448f031b48cd2eab5fc3e4dffa06706372e90d63feMark Brown ret = _regulator_get_voltage(rdev); 7458f031b48cd2eab5fc3e4dffa06706372e90d63feMark Brown if (ret > 0) 7468f031b48cd2eab5fc3e4dffa06706372e90d63feMark Brown count += sprintf(buf + count, "at %d mV ", ret / 1000); 7478f031b48cd2eab5fc3e4dffa06706372e90d63feMark Brown } 7488f031b48cd2eab5fc3e4dffa06706372e90d63feMark Brown 749bf5892a8167e4aa5a9a6d72f803fde850e0c5753Mark Brown if (constraints->uV_offset) 750bf5892a8167e4aa5a9a6d72f803fde850e0c5753Mark Brown count += sprintf(buf, "%dmV offset ", 751bf5892a8167e4aa5a9a6d72f803fde850e0c5753Mark Brown constraints->uV_offset / 1000); 752bf5892a8167e4aa5a9a6d72f803fde850e0c5753Mark Brown 7538f031b48cd2eab5fc3e4dffa06706372e90d63feMark Brown if (constraints->min_uA && constraints->max_uA) { 754414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood if (constraints->min_uA == constraints->max_uA) 7558f031b48cd2eab5fc3e4dffa06706372e90d63feMark Brown count += sprintf(buf + count, "%d mA ", 7568f031b48cd2eab5fc3e4dffa06706372e90d63feMark Brown constraints->min_uA / 1000); 757414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood else 7588f031b48cd2eab5fc3e4dffa06706372e90d63feMark Brown count += sprintf(buf + count, "%d <--> %d mA ", 7598f031b48cd2eab5fc3e4dffa06706372e90d63feMark Brown constraints->min_uA / 1000, 7608f031b48cd2eab5fc3e4dffa06706372e90d63feMark Brown constraints->max_uA / 1000); 7618f031b48cd2eab5fc3e4dffa06706372e90d63feMark Brown } 7628f031b48cd2eab5fc3e4dffa06706372e90d63feMark Brown 7638f031b48cd2eab5fc3e4dffa06706372e90d63feMark Brown if (!constraints->min_uA || 7648f031b48cd2eab5fc3e4dffa06706372e90d63feMark Brown constraints->min_uA != constraints->max_uA) { 7658f031b48cd2eab5fc3e4dffa06706372e90d63feMark Brown ret = _regulator_get_current_limit(rdev); 7668f031b48cd2eab5fc3e4dffa06706372e90d63feMark Brown if (ret > 0) 767e4a6376b3b2999d169b602a582a8819d95ff79bcCyril Chemparathy count += sprintf(buf + count, "at %d mA ", ret / 1000); 768414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood } 7698f031b48cd2eab5fc3e4dffa06706372e90d63feMark Brown 770414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood if (constraints->valid_modes_mask & REGULATOR_MODE_FAST) 771414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood count += sprintf(buf + count, "fast "); 772414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood if (constraints->valid_modes_mask & REGULATOR_MODE_NORMAL) 773414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood count += sprintf(buf + count, "normal "); 774414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood if (constraints->valid_modes_mask & REGULATOR_MODE_IDLE) 775414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood count += sprintf(buf + count, "idle "); 776414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood if (constraints->valid_modes_mask & REGULATOR_MODE_STANDBY) 777414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood count += sprintf(buf + count, "standby"); 778414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood 77913ce29f80fe3f61d3865b90244b1d1430f553e9fMark Brown rdev_info(rdev, "%s\n", buf); 780414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood} 781414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood 782e79055d62ea6ca3c36962209f4c819614972c95aMark Brownstatic int machine_constraints_voltage(struct regulator_dev *rdev, 7831083c39346d482b9001944d05c09191027892226Mark Brown struct regulation_constraints *constraints) 784a5766f11cfd3a0c03450d99c8fe548c2940be884Liam Girdwood{ 785e5fda26c7ea9430d7d953364f900bafdce2be67bMark Brown struct regulator_ops *ops = rdev->desc->ops; 786af5866c9cdc9e43ef775a14765fd8eab95c7fd20Mark Brown int ret; 787af5866c9cdc9e43ef775a14765fd8eab95c7fd20Mark Brown 788af5866c9cdc9e43ef775a14765fd8eab95c7fd20Mark Brown /* do we need to apply the constraint voltage */ 789af5866c9cdc9e43ef775a14765fd8eab95c7fd20Mark Brown if (rdev->constraints->apply_uV && 790757902513019e6ee469791ff76f954b19ca8d036Mark Brown rdev->constraints->min_uV == rdev->constraints->max_uV) { 791757902513019e6ee469791ff76f954b19ca8d036Mark Brown ret = _regulator_do_set_voltage(rdev, 792757902513019e6ee469791ff76f954b19ca8d036Mark Brown rdev->constraints->min_uV, 793757902513019e6ee469791ff76f954b19ca8d036Mark Brown rdev->constraints->max_uV); 794757902513019e6ee469791ff76f954b19ca8d036Mark Brown if (ret < 0) { 795757902513019e6ee469791ff76f954b19ca8d036Mark Brown rdev_err(rdev, "failed to apply %duV constraint\n", 796757902513019e6ee469791ff76f954b19ca8d036Mark Brown rdev->constraints->min_uV); 797757902513019e6ee469791ff76f954b19ca8d036Mark Brown rdev->constraints = NULL; 798757902513019e6ee469791ff76f954b19ca8d036Mark Brown return ret; 799757902513019e6ee469791ff76f954b19ca8d036Mark Brown } 800af5866c9cdc9e43ef775a14765fd8eab95c7fd20Mark Brown } 801e06f5b4fea243b152c79fe5d9552a852069de483Mark Brown 8024367cfdc7c657ad8a797f51b9ffd3c64b31910e7David Brownell /* constrain machine-level voltage specs to fit 8034367cfdc7c657ad8a797f51b9ffd3c64b31910e7David Brownell * the actual range supported by this regulator. 8044367cfdc7c657ad8a797f51b9ffd3c64b31910e7David Brownell */ 8054367cfdc7c657ad8a797f51b9ffd3c64b31910e7David Brownell if (ops->list_voltage && rdev->desc->n_voltages) { 8064367cfdc7c657ad8a797f51b9ffd3c64b31910e7David Brownell int count = rdev->desc->n_voltages; 8074367cfdc7c657ad8a797f51b9ffd3c64b31910e7David Brownell int i; 8084367cfdc7c657ad8a797f51b9ffd3c64b31910e7David Brownell int min_uV = INT_MAX; 8094367cfdc7c657ad8a797f51b9ffd3c64b31910e7David Brownell int max_uV = INT_MIN; 8104367cfdc7c657ad8a797f51b9ffd3c64b31910e7David Brownell int cmin = constraints->min_uV; 8114367cfdc7c657ad8a797f51b9ffd3c64b31910e7David Brownell int cmax = constraints->max_uV; 8124367cfdc7c657ad8a797f51b9ffd3c64b31910e7David Brownell 8133e59091828ed5406c879b899b4257fcef7271e2cMark Brown /* it's safe to autoconfigure fixed-voltage supplies 8143e59091828ed5406c879b899b4257fcef7271e2cMark Brown and the constraints are used by list_voltage. */ 8154367cfdc7c657ad8a797f51b9ffd3c64b31910e7David Brownell if (count == 1 && !cmin) { 8163e59091828ed5406c879b899b4257fcef7271e2cMark Brown cmin = 1; 8174367cfdc7c657ad8a797f51b9ffd3c64b31910e7David Brownell cmax = INT_MAX; 8183e59091828ed5406c879b899b4257fcef7271e2cMark Brown constraints->min_uV = cmin; 8193e59091828ed5406c879b899b4257fcef7271e2cMark Brown constraints->max_uV = cmax; 8204367cfdc7c657ad8a797f51b9ffd3c64b31910e7David Brownell } 8214367cfdc7c657ad8a797f51b9ffd3c64b31910e7David Brownell 8223e2b9abda554e9f6105996dca77cca9ef98de17aMark Brown /* voltage constraints are optional */ 8233e2b9abda554e9f6105996dca77cca9ef98de17aMark Brown if ((cmin == 0) && (cmax == 0)) 824e79055d62ea6ca3c36962209f4c819614972c95aMark Brown return 0; 8253e2b9abda554e9f6105996dca77cca9ef98de17aMark Brown 8264367cfdc7c657ad8a797f51b9ffd3c64b31910e7David Brownell /* else require explicit machine-level constraints */ 8273e2b9abda554e9f6105996dca77cca9ef98de17aMark Brown if (cmin <= 0 || cmax <= 0 || cmax < cmin) { 8285da84fd99bb1ab1c7cd39d0cf7c08bb63931a59aJoe Perches rdev_err(rdev, "invalid voltage constraints\n"); 829e79055d62ea6ca3c36962209f4c819614972c95aMark Brown return -EINVAL; 8304367cfdc7c657ad8a797f51b9ffd3c64b31910e7David Brownell } 8314367cfdc7c657ad8a797f51b9ffd3c64b31910e7David Brownell 8324367cfdc7c657ad8a797f51b9ffd3c64b31910e7David Brownell /* initial: [cmin..cmax] valid, [min_uV..max_uV] not */ 8334367cfdc7c657ad8a797f51b9ffd3c64b31910e7David Brownell for (i = 0; i < count; i++) { 8344367cfdc7c657ad8a797f51b9ffd3c64b31910e7David Brownell int value; 8354367cfdc7c657ad8a797f51b9ffd3c64b31910e7David Brownell 8364367cfdc7c657ad8a797f51b9ffd3c64b31910e7David Brownell value = ops->list_voltage(rdev, i); 8374367cfdc7c657ad8a797f51b9ffd3c64b31910e7David Brownell if (value <= 0) 8384367cfdc7c657ad8a797f51b9ffd3c64b31910e7David Brownell continue; 8394367cfdc7c657ad8a797f51b9ffd3c64b31910e7David Brownell 8404367cfdc7c657ad8a797f51b9ffd3c64b31910e7David Brownell /* maybe adjust [min_uV..max_uV] */ 8414367cfdc7c657ad8a797f51b9ffd3c64b31910e7David Brownell if (value >= cmin && value < min_uV) 8424367cfdc7c657ad8a797f51b9ffd3c64b31910e7David Brownell min_uV = value; 8434367cfdc7c657ad8a797f51b9ffd3c64b31910e7David Brownell if (value <= cmax && value > max_uV) 8444367cfdc7c657ad8a797f51b9ffd3c64b31910e7David Brownell max_uV = value; 8454367cfdc7c657ad8a797f51b9ffd3c64b31910e7David Brownell } 8464367cfdc7c657ad8a797f51b9ffd3c64b31910e7David Brownell 8474367cfdc7c657ad8a797f51b9ffd3c64b31910e7David Brownell /* final: [min_uV..max_uV] valid iff constraints valid */ 8484367cfdc7c657ad8a797f51b9ffd3c64b31910e7David Brownell if (max_uV < min_uV) { 8495da84fd99bb1ab1c7cd39d0cf7c08bb63931a59aJoe Perches rdev_err(rdev, "unsupportable voltage constraints\n"); 850e79055d62ea6ca3c36962209f4c819614972c95aMark Brown return -EINVAL; 8514367cfdc7c657ad8a797f51b9ffd3c64b31910e7David Brownell } 8524367cfdc7c657ad8a797f51b9ffd3c64b31910e7David Brownell 8534367cfdc7c657ad8a797f51b9ffd3c64b31910e7David Brownell /* use regulator's subset of machine constraints */ 8544367cfdc7c657ad8a797f51b9ffd3c64b31910e7David Brownell if (constraints->min_uV < min_uV) { 8555da84fd99bb1ab1c7cd39d0cf7c08bb63931a59aJoe Perches rdev_dbg(rdev, "override min_uV, %d -> %d\n", 8565da84fd99bb1ab1c7cd39d0cf7c08bb63931a59aJoe Perches constraints->min_uV, min_uV); 8574367cfdc7c657ad8a797f51b9ffd3c64b31910e7David Brownell constraints->min_uV = min_uV; 8584367cfdc7c657ad8a797f51b9ffd3c64b31910e7David Brownell } 8594367cfdc7c657ad8a797f51b9ffd3c64b31910e7David Brownell if (constraints->max_uV > max_uV) { 8605da84fd99bb1ab1c7cd39d0cf7c08bb63931a59aJoe Perches rdev_dbg(rdev, "override max_uV, %d -> %d\n", 8615da84fd99bb1ab1c7cd39d0cf7c08bb63931a59aJoe Perches constraints->max_uV, max_uV); 8624367cfdc7c657ad8a797f51b9ffd3c64b31910e7David Brownell constraints->max_uV = max_uV; 8634367cfdc7c657ad8a797f51b9ffd3c64b31910e7David Brownell } 8644367cfdc7c657ad8a797f51b9ffd3c64b31910e7David Brownell } 8654367cfdc7c657ad8a797f51b9ffd3c64b31910e7David Brownell 866e79055d62ea6ca3c36962209f4c819614972c95aMark Brown return 0; 867e79055d62ea6ca3c36962209f4c819614972c95aMark Brown} 868e79055d62ea6ca3c36962209f4c819614972c95aMark Brown 869e79055d62ea6ca3c36962209f4c819614972c95aMark Brown/** 870e79055d62ea6ca3c36962209f4c819614972c95aMark Brown * set_machine_constraints - sets regulator constraints 871e79055d62ea6ca3c36962209f4c819614972c95aMark Brown * @rdev: regulator source 872e79055d62ea6ca3c36962209f4c819614972c95aMark Brown * @constraints: constraints to apply 873e79055d62ea6ca3c36962209f4c819614972c95aMark Brown * 874e79055d62ea6ca3c36962209f4c819614972c95aMark Brown * Allows platform initialisation code to define and constrain 875e79055d62ea6ca3c36962209f4c819614972c95aMark Brown * regulator circuits e.g. valid voltage/current ranges, etc. NOTE: 876e79055d62ea6ca3c36962209f4c819614972c95aMark Brown * Constraints *must* be set by platform code in order for some 877e79055d62ea6ca3c36962209f4c819614972c95aMark Brown * regulator operations to proceed i.e. set_voltage, set_current_limit, 878e79055d62ea6ca3c36962209f4c819614972c95aMark Brown * set_mode. 879e79055d62ea6ca3c36962209f4c819614972c95aMark Brown */ 880e79055d62ea6ca3c36962209f4c819614972c95aMark Brownstatic int set_machine_constraints(struct regulator_dev *rdev, 881f8c12fe329c8da9f50d8b2b1183eeaa4d587e747Mark Brown const struct regulation_constraints *constraints) 882e79055d62ea6ca3c36962209f4c819614972c95aMark Brown{ 883e79055d62ea6ca3c36962209f4c819614972c95aMark Brown int ret = 0; 884e79055d62ea6ca3c36962209f4c819614972c95aMark Brown struct regulator_ops *ops = rdev->desc->ops; 885e79055d62ea6ca3c36962209f4c819614972c95aMark Brown 886f8c12fe329c8da9f50d8b2b1183eeaa4d587e747Mark Brown rdev->constraints = kmemdup(constraints, sizeof(*constraints), 887f8c12fe329c8da9f50d8b2b1183eeaa4d587e747Mark Brown GFP_KERNEL); 888f8c12fe329c8da9f50d8b2b1183eeaa4d587e747Mark Brown if (!rdev->constraints) 889f8c12fe329c8da9f50d8b2b1183eeaa4d587e747Mark Brown return -ENOMEM; 890af5866c9cdc9e43ef775a14765fd8eab95c7fd20Mark Brown 891f8c12fe329c8da9f50d8b2b1183eeaa4d587e747Mark Brown ret = machine_constraints_voltage(rdev, rdev->constraints); 892e79055d62ea6ca3c36962209f4c819614972c95aMark Brown if (ret != 0) 893e79055d62ea6ca3c36962209f4c819614972c95aMark Brown goto out; 894e79055d62ea6ca3c36962209f4c819614972c95aMark Brown 895a5766f11cfd3a0c03450d99c8fe548c2940be884Liam Girdwood /* do we need to setup our suspend state */ 896e06f5b4fea243b152c79fe5d9552a852069de483Mark Brown if (constraints->initial_state) { 897f8c12fe329c8da9f50d8b2b1183eeaa4d587e747Mark Brown ret = suspend_prepare(rdev, rdev->constraints->initial_state); 898e06f5b4fea243b152c79fe5d9552a852069de483Mark Brown if (ret < 0) { 8995da84fd99bb1ab1c7cd39d0cf7c08bb63931a59aJoe Perches rdev_err(rdev, "failed to set suspend state\n"); 900e06f5b4fea243b152c79fe5d9552a852069de483Mark Brown rdev->constraints = NULL; 901e06f5b4fea243b152c79fe5d9552a852069de483Mark Brown goto out; 902e06f5b4fea243b152c79fe5d9552a852069de483Mark Brown } 903e06f5b4fea243b152c79fe5d9552a852069de483Mark Brown } 904a5766f11cfd3a0c03450d99c8fe548c2940be884Liam Girdwood 905a308466c24b4f42bab6945026e938874d22cde50Mark Brown if (constraints->initial_mode) { 906a308466c24b4f42bab6945026e938874d22cde50Mark Brown if (!ops->set_mode) { 9075da84fd99bb1ab1c7cd39d0cf7c08bb63931a59aJoe Perches rdev_err(rdev, "no set_mode operation\n"); 908a308466c24b4f42bab6945026e938874d22cde50Mark Brown ret = -EINVAL; 909a308466c24b4f42bab6945026e938874d22cde50Mark Brown goto out; 910a308466c24b4f42bab6945026e938874d22cde50Mark Brown } 911a308466c24b4f42bab6945026e938874d22cde50Mark Brown 912f8c12fe329c8da9f50d8b2b1183eeaa4d587e747Mark Brown ret = ops->set_mode(rdev, rdev->constraints->initial_mode); 913a308466c24b4f42bab6945026e938874d22cde50Mark Brown if (ret < 0) { 9145da84fd99bb1ab1c7cd39d0cf7c08bb63931a59aJoe Perches rdev_err(rdev, "failed to set initial mode: %d\n", ret); 915a308466c24b4f42bab6945026e938874d22cde50Mark Brown goto out; 916a308466c24b4f42bab6945026e938874d22cde50Mark Brown } 917a308466c24b4f42bab6945026e938874d22cde50Mark Brown } 918a308466c24b4f42bab6945026e938874d22cde50Mark Brown 919cacf90f24e80cec9334f98e0377149f943fe9f16Mark Brown /* If the constraints say the regulator should be on at this point 920cacf90f24e80cec9334f98e0377149f943fe9f16Mark Brown * and we have control then make sure it is enabled. 921cacf90f24e80cec9334f98e0377149f943fe9f16Mark Brown */ 922f8c12fe329c8da9f50d8b2b1183eeaa4d587e747Mark Brown if ((rdev->constraints->always_on || rdev->constraints->boot_on) && 923f8c12fe329c8da9f50d8b2b1183eeaa4d587e747Mark Brown ops->enable) { 924e5fda26c7ea9430d7d953364f900bafdce2be67bMark Brown ret = ops->enable(rdev); 925e5fda26c7ea9430d7d953364f900bafdce2be67bMark Brown if (ret < 0) { 9265da84fd99bb1ab1c7cd39d0cf7c08bb63931a59aJoe Perches rdev_err(rdev, "failed to enable\n"); 927e5fda26c7ea9430d7d953364f900bafdce2be67bMark Brown rdev->constraints = NULL; 928e5fda26c7ea9430d7d953364f900bafdce2be67bMark Brown goto out; 929e5fda26c7ea9430d7d953364f900bafdce2be67bMark Brown } 930e5fda26c7ea9430d7d953364f900bafdce2be67bMark Brown } 931e5fda26c7ea9430d7d953364f900bafdce2be67bMark Brown 932a5766f11cfd3a0c03450d99c8fe548c2940be884Liam Girdwood print_constraints(rdev); 933a5766f11cfd3a0c03450d99c8fe548c2940be884Liam Girdwoodout: 934a5766f11cfd3a0c03450d99c8fe548c2940be884Liam Girdwood return ret; 935a5766f11cfd3a0c03450d99c8fe548c2940be884Liam Girdwood} 936a5766f11cfd3a0c03450d99c8fe548c2940be884Liam Girdwood 937a5766f11cfd3a0c03450d99c8fe548c2940be884Liam Girdwood/** 938a5766f11cfd3a0c03450d99c8fe548c2940be884Liam Girdwood * set_supply - set regulator supply regulator 93969279fb9a95051971ac03e558c4d46e7ba84ab3aMark Brown * @rdev: regulator name 94069279fb9a95051971ac03e558c4d46e7ba84ab3aMark Brown * @supply_rdev: supply regulator name 941a5766f11cfd3a0c03450d99c8fe548c2940be884Liam Girdwood * 942a5766f11cfd3a0c03450d99c8fe548c2940be884Liam Girdwood * Called by platform initialisation code to set the supply regulator for this 943a5766f11cfd3a0c03450d99c8fe548c2940be884Liam Girdwood * regulator. This ensures that a regulators supply will also be enabled by the 944a5766f11cfd3a0c03450d99c8fe548c2940be884Liam Girdwood * core if it's child is enabled. 945a5766f11cfd3a0c03450d99c8fe548c2940be884Liam Girdwood */ 946a5766f11cfd3a0c03450d99c8fe548c2940be884Liam Girdwoodstatic int set_supply(struct regulator_dev *rdev, 9473801b86aa482d26a8ae460f67fca29e016491a86Mark Brown struct regulator_dev *supply_rdev) 948a5766f11cfd3a0c03450d99c8fe548c2940be884Liam Girdwood{ 949a5766f11cfd3a0c03450d99c8fe548c2940be884Liam Girdwood int err; 950a5766f11cfd3a0c03450d99c8fe548c2940be884Liam Girdwood 9513801b86aa482d26a8ae460f67fca29e016491a86Mark Brown rdev_info(rdev, "supplied by %s\n", rdev_get_name(supply_rdev)); 9523801b86aa482d26a8ae460f67fca29e016491a86Mark Brown 9533801b86aa482d26a8ae460f67fca29e016491a86Mark Brown rdev->supply = create_regulator(supply_rdev, &rdev->dev, "SUPPLY"); 9543801b86aa482d26a8ae460f67fca29e016491a86Mark Brown if (IS_ERR(rdev->supply)) { 9553801b86aa482d26a8ae460f67fca29e016491a86Mark Brown err = PTR_ERR(rdev->supply); 9563801b86aa482d26a8ae460f67fca29e016491a86Mark Brown rdev->supply = NULL; 9573801b86aa482d26a8ae460f67fca29e016491a86Mark Brown return err; 958a5766f11cfd3a0c03450d99c8fe548c2940be884Liam Girdwood } 9593801b86aa482d26a8ae460f67fca29e016491a86Mark Brown 9603801b86aa482d26a8ae460f67fca29e016491a86Mark Brown return 0; 961a5766f11cfd3a0c03450d99c8fe548c2940be884Liam Girdwood} 962a5766f11cfd3a0c03450d99c8fe548c2940be884Liam Girdwood 963a5766f11cfd3a0c03450d99c8fe548c2940be884Liam Girdwood/** 96406c63f9396133f312c5a49c2285c2c8015e80934Randy Dunlap * set_consumer_device_supply - Bind a regulator to a symbolic supply 96569279fb9a95051971ac03e558c4d46e7ba84ab3aMark Brown * @rdev: regulator source 96669279fb9a95051971ac03e558c4d46e7ba84ab3aMark Brown * @consumer_dev: device the supply applies to 96740f9244f4da8976eeb6d5ed6313c635ba238a9d3Mark Brown * @consumer_dev_name: dev_name() string for device supply applies to 96869279fb9a95051971ac03e558c4d46e7ba84ab3aMark Brown * @supply: symbolic name for supply 969a5766f11cfd3a0c03450d99c8fe548c2940be884Liam Girdwood * 970a5766f11cfd3a0c03450d99c8fe548c2940be884Liam Girdwood * Allows platform initialisation code to map physical regulator 971a5766f11cfd3a0c03450d99c8fe548c2940be884Liam Girdwood * sources to symbolic names for supplies for use by devices. Devices 972a5766f11cfd3a0c03450d99c8fe548c2940be884Liam Girdwood * should use these symbolic names to request regulators, avoiding the 973a5766f11cfd3a0c03450d99c8fe548c2940be884Liam Girdwood * need to provide board-specific regulator names as platform data. 97440f9244f4da8976eeb6d5ed6313c635ba238a9d3Mark Brown * 97540f9244f4da8976eeb6d5ed6313c635ba238a9d3Mark Brown * Only one of consumer_dev and consumer_dev_name may be specified. 976a5766f11cfd3a0c03450d99c8fe548c2940be884Liam Girdwood */ 977a5766f11cfd3a0c03450d99c8fe548c2940be884Liam Girdwoodstatic int set_consumer_device_supply(struct regulator_dev *rdev, 97840f9244f4da8976eeb6d5ed6313c635ba238a9d3Mark Brown struct device *consumer_dev, const char *consumer_dev_name, 97940f9244f4da8976eeb6d5ed6313c635ba238a9d3Mark Brown const char *supply) 980a5766f11cfd3a0c03450d99c8fe548c2940be884Liam Girdwood{ 981a5766f11cfd3a0c03450d99c8fe548c2940be884Liam Girdwood struct regulator_map *node; 9829ed2099edca26d07947beb42c12bd1d6669e82bcMark Brown int has_dev; 983a5766f11cfd3a0c03450d99c8fe548c2940be884Liam Girdwood 98440f9244f4da8976eeb6d5ed6313c635ba238a9d3Mark Brown if (consumer_dev && consumer_dev_name) 98540f9244f4da8976eeb6d5ed6313c635ba238a9d3Mark Brown return -EINVAL; 98640f9244f4da8976eeb6d5ed6313c635ba238a9d3Mark Brown 98740f9244f4da8976eeb6d5ed6313c635ba238a9d3Mark Brown if (!consumer_dev_name && consumer_dev) 98840f9244f4da8976eeb6d5ed6313c635ba238a9d3Mark Brown consumer_dev_name = dev_name(consumer_dev); 98940f9244f4da8976eeb6d5ed6313c635ba238a9d3Mark Brown 990a5766f11cfd3a0c03450d99c8fe548c2940be884Liam Girdwood if (supply == NULL) 991a5766f11cfd3a0c03450d99c8fe548c2940be884Liam Girdwood return -EINVAL; 992a5766f11cfd3a0c03450d99c8fe548c2940be884Liam Girdwood 9939ed2099edca26d07947beb42c12bd1d6669e82bcMark Brown if (consumer_dev_name != NULL) 9949ed2099edca26d07947beb42c12bd1d6669e82bcMark Brown has_dev = 1; 9959ed2099edca26d07947beb42c12bd1d6669e82bcMark Brown else 9969ed2099edca26d07947beb42c12bd1d6669e82bcMark Brown has_dev = 0; 9979ed2099edca26d07947beb42c12bd1d6669e82bcMark Brown 9986001e13c5f708eb68c744a69df3c2c281156030dDavid Brownell list_for_each_entry(node, ®ulator_map_list, list) { 99923b5cc2ab6783256cf06779e1d522482b819b808Jani Nikula if (node->dev_name && consumer_dev_name) { 100023b5cc2ab6783256cf06779e1d522482b819b808Jani Nikula if (strcmp(node->dev_name, consumer_dev_name) != 0) 100123b5cc2ab6783256cf06779e1d522482b819b808Jani Nikula continue; 100223b5cc2ab6783256cf06779e1d522482b819b808Jani Nikula } else if (node->dev_name || consumer_dev_name) { 10036001e13c5f708eb68c744a69df3c2c281156030dDavid Brownell continue; 100423b5cc2ab6783256cf06779e1d522482b819b808Jani Nikula } 100523b5cc2ab6783256cf06779e1d522482b819b808Jani Nikula 10066001e13c5f708eb68c744a69df3c2c281156030dDavid Brownell if (strcmp(node->supply, supply) != 0) 10076001e13c5f708eb68c744a69df3c2c281156030dDavid Brownell continue; 10086001e13c5f708eb68c744a69df3c2c281156030dDavid Brownell 10096001e13c5f708eb68c744a69df3c2c281156030dDavid Brownell dev_dbg(consumer_dev, "%s/%s is '%s' supply; fail %s/%s\n", 10105da84fd99bb1ab1c7cd39d0cf7c08bb63931a59aJoe Perches dev_name(&node->regulator->dev), 10115da84fd99bb1ab1c7cd39d0cf7c08bb63931a59aJoe Perches node->regulator->desc->name, 10125da84fd99bb1ab1c7cd39d0cf7c08bb63931a59aJoe Perches supply, 10135da84fd99bb1ab1c7cd39d0cf7c08bb63931a59aJoe Perches dev_name(&rdev->dev), rdev_get_name(rdev)); 10146001e13c5f708eb68c744a69df3c2c281156030dDavid Brownell return -EBUSY; 10156001e13c5f708eb68c744a69df3c2c281156030dDavid Brownell } 10166001e13c5f708eb68c744a69df3c2c281156030dDavid Brownell 10179ed2099edca26d07947beb42c12bd1d6669e82bcMark Brown node = kzalloc(sizeof(struct regulator_map), GFP_KERNEL); 1018a5766f11cfd3a0c03450d99c8fe548c2940be884Liam Girdwood if (node == NULL) 1019a5766f11cfd3a0c03450d99c8fe548c2940be884Liam Girdwood return -ENOMEM; 1020a5766f11cfd3a0c03450d99c8fe548c2940be884Liam Girdwood 1021a5766f11cfd3a0c03450d99c8fe548c2940be884Liam Girdwood node->regulator = rdev; 1022a5766f11cfd3a0c03450d99c8fe548c2940be884Liam Girdwood node->supply = supply; 1023a5766f11cfd3a0c03450d99c8fe548c2940be884Liam Girdwood 10249ed2099edca26d07947beb42c12bd1d6669e82bcMark Brown if (has_dev) { 10259ed2099edca26d07947beb42c12bd1d6669e82bcMark Brown node->dev_name = kstrdup(consumer_dev_name, GFP_KERNEL); 10269ed2099edca26d07947beb42c12bd1d6669e82bcMark Brown if (node->dev_name == NULL) { 10279ed2099edca26d07947beb42c12bd1d6669e82bcMark Brown kfree(node); 10289ed2099edca26d07947beb42c12bd1d6669e82bcMark Brown return -ENOMEM; 10299ed2099edca26d07947beb42c12bd1d6669e82bcMark Brown } 103040f9244f4da8976eeb6d5ed6313c635ba238a9d3Mark Brown } 103140f9244f4da8976eeb6d5ed6313c635ba238a9d3Mark Brown 1032a5766f11cfd3a0c03450d99c8fe548c2940be884Liam Girdwood list_add(&node->list, ®ulator_map_list); 1033a5766f11cfd3a0c03450d99c8fe548c2940be884Liam Girdwood return 0; 1034a5766f11cfd3a0c03450d99c8fe548c2940be884Liam Girdwood} 1035a5766f11cfd3a0c03450d99c8fe548c2940be884Liam Girdwood 10360f1d747bfa89de4ca52dc1dffdcce35a2b8a1532Mike Rapoportstatic void unset_regulator_supplies(struct regulator_dev *rdev) 10370f1d747bfa89de4ca52dc1dffdcce35a2b8a1532Mike Rapoport{ 10380f1d747bfa89de4ca52dc1dffdcce35a2b8a1532Mike Rapoport struct regulator_map *node, *n; 10390f1d747bfa89de4ca52dc1dffdcce35a2b8a1532Mike Rapoport 10400f1d747bfa89de4ca52dc1dffdcce35a2b8a1532Mike Rapoport list_for_each_entry_safe(node, n, ®ulator_map_list, list) { 10410f1d747bfa89de4ca52dc1dffdcce35a2b8a1532Mike Rapoport if (rdev == node->regulator) { 10420f1d747bfa89de4ca52dc1dffdcce35a2b8a1532Mike Rapoport list_del(&node->list); 104340f9244f4da8976eeb6d5ed6313c635ba238a9d3Mark Brown kfree(node->dev_name); 10440f1d747bfa89de4ca52dc1dffdcce35a2b8a1532Mike Rapoport kfree(node); 10450f1d747bfa89de4ca52dc1dffdcce35a2b8a1532Mike Rapoport } 10460f1d747bfa89de4ca52dc1dffdcce35a2b8a1532Mike Rapoport } 10470f1d747bfa89de4ca52dc1dffdcce35a2b8a1532Mike Rapoport} 10480f1d747bfa89de4ca52dc1dffdcce35a2b8a1532Mike Rapoport 1049f5726ae33c382366ea1b23240d5620dcf675d81dMark Brown#define REG_STR_SIZE 64 1050414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood 1051414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwoodstatic struct regulator *create_regulator(struct regulator_dev *rdev, 1052414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood struct device *dev, 1053414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood const char *supply_name) 1054414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood{ 1055414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood struct regulator *regulator; 1056414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood char buf[REG_STR_SIZE]; 1057414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood int err, size; 1058414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood 1059414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood regulator = kzalloc(sizeof(*regulator), GFP_KERNEL); 1060414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood if (regulator == NULL) 1061414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood return NULL; 1062414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood 1063414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood mutex_lock(&rdev->mutex); 1064414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood regulator->rdev = rdev; 1065414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood list_add(®ulator->list, &rdev->consumer_list); 1066414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood 1067414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood if (dev) { 1068414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood /* create a 'requested_microamps_name' sysfs entry */ 1069e0eaedefda8e14ed3f445f382c568c5d69e4223fMark Brown size = scnprintf(buf, REG_STR_SIZE, 1070e0eaedefda8e14ed3f445f382c568c5d69e4223fMark Brown "microamps_requested_%s-%s", 1071e0eaedefda8e14ed3f445f382c568c5d69e4223fMark Brown dev_name(dev), supply_name); 1072414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood if (size >= REG_STR_SIZE) 1073414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood goto overflow_err; 1074414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood 1075414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood regulator->dev = dev; 10764f26a2abe1eed18dc6adddf2d0ae5553e51578c2Ameya Palande sysfs_attr_init(®ulator->dev_attr.attr); 1077414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood regulator->dev_attr.attr.name = kstrdup(buf, GFP_KERNEL); 1078414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood if (regulator->dev_attr.attr.name == NULL) 1079414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood goto attr_name_err; 1080414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood 1081414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood regulator->dev_attr.attr.mode = 0444; 1082414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood regulator->dev_attr.show = device_requested_uA_show; 1083414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood err = device_create_file(dev, ®ulator->dev_attr); 1084414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood if (err < 0) { 10855da84fd99bb1ab1c7cd39d0cf7c08bb63931a59aJoe Perches rdev_warn(rdev, "could not add regulator_dev requested microamps sysfs entry\n"); 1086414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood goto attr_name_err; 1087414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood } 1088414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood 1089414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood /* also add a link to the device sysfs entry */ 1090414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood size = scnprintf(buf, REG_STR_SIZE, "%s-%s", 1091414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood dev->kobj.name, supply_name); 1092414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood if (size >= REG_STR_SIZE) 1093414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood goto attr_err; 1094414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood 1095414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood regulator->supply_name = kstrdup(buf, GFP_KERNEL); 1096414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood if (regulator->supply_name == NULL) 1097414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood goto attr_err; 1098414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood 1099414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood err = sysfs_create_link(&rdev->dev.kobj, &dev->kobj, 1100414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood buf); 1101414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood if (err) { 11025da84fd99bb1ab1c7cd39d0cf7c08bb63931a59aJoe Perches rdev_warn(rdev, "could not add device link %s err %d\n", 11035da84fd99bb1ab1c7cd39d0cf7c08bb63931a59aJoe Perches dev->kobj.name, err); 1104414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood goto link_name_err; 1105414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood } 11065de705194e9883a39f993e2ff96028d5aab99b37Mark Brown } else { 11075de705194e9883a39f993e2ff96028d5aab99b37Mark Brown regulator->supply_name = kstrdup(supply_name, GFP_KERNEL); 11085de705194e9883a39f993e2ff96028d5aab99b37Mark Brown if (regulator->supply_name == NULL) 11095de705194e9883a39f993e2ff96028d5aab99b37Mark Brown goto attr_err; 11105de705194e9883a39f993e2ff96028d5aab99b37Mark Brown } 11115de705194e9883a39f993e2ff96028d5aab99b37Mark Brown 11125de705194e9883a39f993e2ff96028d5aab99b37Mark Brown#ifdef CONFIG_DEBUG_FS 11135de705194e9883a39f993e2ff96028d5aab99b37Mark Brown regulator->debugfs = debugfs_create_dir(regulator->supply_name, 11145de705194e9883a39f993e2ff96028d5aab99b37Mark Brown rdev->debugfs); 11155de705194e9883a39f993e2ff96028d5aab99b37Mark Brown if (IS_ERR_OR_NULL(regulator->debugfs)) { 11165de705194e9883a39f993e2ff96028d5aab99b37Mark Brown rdev_warn(rdev, "Failed to create debugfs directory\n"); 11175de705194e9883a39f993e2ff96028d5aab99b37Mark Brown regulator->debugfs = NULL; 11185de705194e9883a39f993e2ff96028d5aab99b37Mark Brown } else { 11195de705194e9883a39f993e2ff96028d5aab99b37Mark Brown debugfs_create_u32("uA_load", 0444, regulator->debugfs, 11205de705194e9883a39f993e2ff96028d5aab99b37Mark Brown ®ulator->uA_load); 11215de705194e9883a39f993e2ff96028d5aab99b37Mark Brown debugfs_create_u32("min_uV", 0444, regulator->debugfs, 11225de705194e9883a39f993e2ff96028d5aab99b37Mark Brown ®ulator->min_uV); 11235de705194e9883a39f993e2ff96028d5aab99b37Mark Brown debugfs_create_u32("max_uV", 0444, regulator->debugfs, 11245de705194e9883a39f993e2ff96028d5aab99b37Mark Brown ®ulator->max_uV); 1125414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood } 11265de705194e9883a39f993e2ff96028d5aab99b37Mark Brown#endif 11275de705194e9883a39f993e2ff96028d5aab99b37Mark Brown 1128414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood mutex_unlock(&rdev->mutex); 1129414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood return regulator; 1130414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwoodlink_name_err: 1131414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood kfree(regulator->supply_name); 1132414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwoodattr_err: 1133414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood device_remove_file(regulator->dev, ®ulator->dev_attr); 1134414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwoodattr_name_err: 1135414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood kfree(regulator->dev_attr.attr.name); 1136414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwoodoverflow_err: 1137414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood list_del(®ulator->list); 1138414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood kfree(regulator); 1139414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood mutex_unlock(&rdev->mutex); 1140414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood return NULL; 1141414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood} 1142414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood 114331aae2beeb3d601d556b6a8c39085940ad1e9f42Mark Brownstatic int _regulator_get_enable_time(struct regulator_dev *rdev) 114431aae2beeb3d601d556b6a8c39085940ad1e9f42Mark Brown{ 114531aae2beeb3d601d556b6a8c39085940ad1e9f42Mark Brown if (!rdev->desc->ops->enable_time) 114631aae2beeb3d601d556b6a8c39085940ad1e9f42Mark Brown return 0; 114731aae2beeb3d601d556b6a8c39085940ad1e9f42Mark Brown return rdev->desc->ops->enable_time(rdev); 114831aae2beeb3d601d556b6a8c39085940ad1e9f42Mark Brown} 114931aae2beeb3d601d556b6a8c39085940ad1e9f42Mark Brown 11505ffbd136e6c51c8d1eec7a4a0c5d2180c81aea30Mark Brown/* Internal regulator request function */ 11515ffbd136e6c51c8d1eec7a4a0c5d2180c81aea30Mark Brownstatic struct regulator *_regulator_get(struct device *dev, const char *id, 11525ffbd136e6c51c8d1eec7a4a0c5d2180c81aea30Mark Brown int exclusive) 1153414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood{ 1154414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood struct regulator_dev *rdev; 1155414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood struct regulator_map *map; 1156414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood struct regulator *regulator = ERR_PTR(-ENODEV); 115740f9244f4da8976eeb6d5ed6313c635ba238a9d3Mark Brown const char *devname = NULL; 11585ffbd136e6c51c8d1eec7a4a0c5d2180c81aea30Mark Brown int ret; 1159414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood 1160414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood if (id == NULL) { 11615da84fd99bb1ab1c7cd39d0cf7c08bb63931a59aJoe Perches pr_err("get() with no identifier\n"); 1162414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood return regulator; 1163414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood } 1164414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood 116540f9244f4da8976eeb6d5ed6313c635ba238a9d3Mark Brown if (dev) 116640f9244f4da8976eeb6d5ed6313c635ba238a9d3Mark Brown devname = dev_name(dev); 116740f9244f4da8976eeb6d5ed6313c635ba238a9d3Mark Brown 1168414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood mutex_lock(®ulator_list_mutex); 1169414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood 1170414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood list_for_each_entry(map, ®ulator_map_list, list) { 117140f9244f4da8976eeb6d5ed6313c635ba238a9d3Mark Brown /* If the mapping has a device set up it must match */ 117240f9244f4da8976eeb6d5ed6313c635ba238a9d3Mark Brown if (map->dev_name && 117340f9244f4da8976eeb6d5ed6313c635ba238a9d3Mark Brown (!devname || strcmp(map->dev_name, devname))) 117440f9244f4da8976eeb6d5ed6313c635ba238a9d3Mark Brown continue; 117540f9244f4da8976eeb6d5ed6313c635ba238a9d3Mark Brown 117640f9244f4da8976eeb6d5ed6313c635ba238a9d3Mark Brown if (strcmp(map->supply, id) == 0) { 1177a5766f11cfd3a0c03450d99c8fe548c2940be884Liam Girdwood rdev = map->regulator; 1178414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood goto found; 1179a5766f11cfd3a0c03450d99c8fe548c2940be884Liam Girdwood } 1180414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood } 118134abbd68efe09765465b81dfedeee9994f13302fMark Brown 1182688fe99a439f7c9dfcc52fbf7cb347f140a2dc8bMark Brown if (board_wants_dummy_regulator) { 1183688fe99a439f7c9dfcc52fbf7cb347f140a2dc8bMark Brown rdev = dummy_regulator_rdev; 1184688fe99a439f7c9dfcc52fbf7cb347f140a2dc8bMark Brown goto found; 1185688fe99a439f7c9dfcc52fbf7cb347f140a2dc8bMark Brown } 1186688fe99a439f7c9dfcc52fbf7cb347f140a2dc8bMark Brown 118734abbd68efe09765465b81dfedeee9994f13302fMark Brown#ifdef CONFIG_REGULATOR_DUMMY 118834abbd68efe09765465b81dfedeee9994f13302fMark Brown if (!devname) 118934abbd68efe09765465b81dfedeee9994f13302fMark Brown devname = "deviceless"; 119034abbd68efe09765465b81dfedeee9994f13302fMark Brown 119134abbd68efe09765465b81dfedeee9994f13302fMark Brown /* If the board didn't flag that it was fully constrained then 119234abbd68efe09765465b81dfedeee9994f13302fMark Brown * substitute in a dummy regulator so consumers can continue. 119334abbd68efe09765465b81dfedeee9994f13302fMark Brown */ 119434abbd68efe09765465b81dfedeee9994f13302fMark Brown if (!has_full_constraints) { 11955da84fd99bb1ab1c7cd39d0cf7c08bb63931a59aJoe Perches pr_warn("%s supply %s not found, using dummy regulator\n", 11965da84fd99bb1ab1c7cd39d0cf7c08bb63931a59aJoe Perches devname, id); 119734abbd68efe09765465b81dfedeee9994f13302fMark Brown rdev = dummy_regulator_rdev; 119834abbd68efe09765465b81dfedeee9994f13302fMark Brown goto found; 119934abbd68efe09765465b81dfedeee9994f13302fMark Brown } 120034abbd68efe09765465b81dfedeee9994f13302fMark Brown#endif 120134abbd68efe09765465b81dfedeee9994f13302fMark Brown 1202414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood mutex_unlock(®ulator_list_mutex); 1203414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood return regulator; 1204414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood 1205414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwoodfound: 12065ffbd136e6c51c8d1eec7a4a0c5d2180c81aea30Mark Brown if (rdev->exclusive) { 12075ffbd136e6c51c8d1eec7a4a0c5d2180c81aea30Mark Brown regulator = ERR_PTR(-EPERM); 12085ffbd136e6c51c8d1eec7a4a0c5d2180c81aea30Mark Brown goto out; 12095ffbd136e6c51c8d1eec7a4a0c5d2180c81aea30Mark Brown } 12105ffbd136e6c51c8d1eec7a4a0c5d2180c81aea30Mark Brown 12115ffbd136e6c51c8d1eec7a4a0c5d2180c81aea30Mark Brown if (exclusive && rdev->open_count) { 12125ffbd136e6c51c8d1eec7a4a0c5d2180c81aea30Mark Brown regulator = ERR_PTR(-EBUSY); 12135ffbd136e6c51c8d1eec7a4a0c5d2180c81aea30Mark Brown goto out; 12145ffbd136e6c51c8d1eec7a4a0c5d2180c81aea30Mark Brown } 12155ffbd136e6c51c8d1eec7a4a0c5d2180c81aea30Mark Brown 1216a5766f11cfd3a0c03450d99c8fe548c2940be884Liam Girdwood if (!try_module_get(rdev->owner)) 1217a5766f11cfd3a0c03450d99c8fe548c2940be884Liam Girdwood goto out; 1218a5766f11cfd3a0c03450d99c8fe548c2940be884Liam Girdwood 1219414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood regulator = create_regulator(rdev, dev, id); 1220414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood if (regulator == NULL) { 1221414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood regulator = ERR_PTR(-ENOMEM); 1222414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood module_put(rdev->owner); 1223414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood } 1224414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood 12255ffbd136e6c51c8d1eec7a4a0c5d2180c81aea30Mark Brown rdev->open_count++; 12265ffbd136e6c51c8d1eec7a4a0c5d2180c81aea30Mark Brown if (exclusive) { 12275ffbd136e6c51c8d1eec7a4a0c5d2180c81aea30Mark Brown rdev->exclusive = 1; 12285ffbd136e6c51c8d1eec7a4a0c5d2180c81aea30Mark Brown 12295ffbd136e6c51c8d1eec7a4a0c5d2180c81aea30Mark Brown ret = _regulator_is_enabled(rdev); 12305ffbd136e6c51c8d1eec7a4a0c5d2180c81aea30Mark Brown if (ret > 0) 12315ffbd136e6c51c8d1eec7a4a0c5d2180c81aea30Mark Brown rdev->use_count = 1; 12325ffbd136e6c51c8d1eec7a4a0c5d2180c81aea30Mark Brown else 12335ffbd136e6c51c8d1eec7a4a0c5d2180c81aea30Mark Brown rdev->use_count = 0; 12345ffbd136e6c51c8d1eec7a4a0c5d2180c81aea30Mark Brown } 12355ffbd136e6c51c8d1eec7a4a0c5d2180c81aea30Mark Brown 1236a5766f11cfd3a0c03450d99c8fe548c2940be884Liam Girdwoodout: 1237414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood mutex_unlock(®ulator_list_mutex); 12385ffbd136e6c51c8d1eec7a4a0c5d2180c81aea30Mark Brown 1239414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood return regulator; 1240414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood} 12415ffbd136e6c51c8d1eec7a4a0c5d2180c81aea30Mark Brown 12425ffbd136e6c51c8d1eec7a4a0c5d2180c81aea30Mark Brown/** 12435ffbd136e6c51c8d1eec7a4a0c5d2180c81aea30Mark Brown * regulator_get - lookup and obtain a reference to a regulator. 12445ffbd136e6c51c8d1eec7a4a0c5d2180c81aea30Mark Brown * @dev: device for regulator "consumer" 12455ffbd136e6c51c8d1eec7a4a0c5d2180c81aea30Mark Brown * @id: Supply name or regulator ID. 12465ffbd136e6c51c8d1eec7a4a0c5d2180c81aea30Mark Brown * 12475ffbd136e6c51c8d1eec7a4a0c5d2180c81aea30Mark Brown * Returns a struct regulator corresponding to the regulator producer, 12485ffbd136e6c51c8d1eec7a4a0c5d2180c81aea30Mark Brown * or IS_ERR() condition containing errno. 12495ffbd136e6c51c8d1eec7a4a0c5d2180c81aea30Mark Brown * 12505ffbd136e6c51c8d1eec7a4a0c5d2180c81aea30Mark Brown * Use of supply names configured via regulator_set_device_supply() is 12515ffbd136e6c51c8d1eec7a4a0c5d2180c81aea30Mark Brown * strongly encouraged. It is recommended that the supply name used 12525ffbd136e6c51c8d1eec7a4a0c5d2180c81aea30Mark Brown * should match the name used for the supply and/or the relevant 12535ffbd136e6c51c8d1eec7a4a0c5d2180c81aea30Mark Brown * device pins in the datasheet. 12545ffbd136e6c51c8d1eec7a4a0c5d2180c81aea30Mark Brown */ 12555ffbd136e6c51c8d1eec7a4a0c5d2180c81aea30Mark Brownstruct regulator *regulator_get(struct device *dev, const char *id) 12565ffbd136e6c51c8d1eec7a4a0c5d2180c81aea30Mark Brown{ 12575ffbd136e6c51c8d1eec7a4a0c5d2180c81aea30Mark Brown return _regulator_get(dev, id, 0); 12585ffbd136e6c51c8d1eec7a4a0c5d2180c81aea30Mark Brown} 1259414c70cb91c445ec813b61e16fe4882807e40240Liam GirdwoodEXPORT_SYMBOL_GPL(regulator_get); 1260414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood 1261414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood/** 12625ffbd136e6c51c8d1eec7a4a0c5d2180c81aea30Mark Brown * regulator_get_exclusive - obtain exclusive access to a regulator. 12635ffbd136e6c51c8d1eec7a4a0c5d2180c81aea30Mark Brown * @dev: device for regulator "consumer" 12645ffbd136e6c51c8d1eec7a4a0c5d2180c81aea30Mark Brown * @id: Supply name or regulator ID. 12655ffbd136e6c51c8d1eec7a4a0c5d2180c81aea30Mark Brown * 12665ffbd136e6c51c8d1eec7a4a0c5d2180c81aea30Mark Brown * Returns a struct regulator corresponding to the regulator producer, 12675ffbd136e6c51c8d1eec7a4a0c5d2180c81aea30Mark Brown * or IS_ERR() condition containing errno. Other consumers will be 12685ffbd136e6c51c8d1eec7a4a0c5d2180c81aea30Mark Brown * unable to obtain this reference is held and the use count for the 12695ffbd136e6c51c8d1eec7a4a0c5d2180c81aea30Mark Brown * regulator will be initialised to reflect the current state of the 12705ffbd136e6c51c8d1eec7a4a0c5d2180c81aea30Mark Brown * regulator. 12715ffbd136e6c51c8d1eec7a4a0c5d2180c81aea30Mark Brown * 12725ffbd136e6c51c8d1eec7a4a0c5d2180c81aea30Mark Brown * This is intended for use by consumers which cannot tolerate shared 12735ffbd136e6c51c8d1eec7a4a0c5d2180c81aea30Mark Brown * use of the regulator such as those which need to force the 12745ffbd136e6c51c8d1eec7a4a0c5d2180c81aea30Mark Brown * regulator off for correct operation of the hardware they are 12755ffbd136e6c51c8d1eec7a4a0c5d2180c81aea30Mark Brown * controlling. 12765ffbd136e6c51c8d1eec7a4a0c5d2180c81aea30Mark Brown * 12775ffbd136e6c51c8d1eec7a4a0c5d2180c81aea30Mark Brown * Use of supply names configured via regulator_set_device_supply() is 12785ffbd136e6c51c8d1eec7a4a0c5d2180c81aea30Mark Brown * strongly encouraged. It is recommended that the supply name used 12795ffbd136e6c51c8d1eec7a4a0c5d2180c81aea30Mark Brown * should match the name used for the supply and/or the relevant 12805ffbd136e6c51c8d1eec7a4a0c5d2180c81aea30Mark Brown * device pins in the datasheet. 12815ffbd136e6c51c8d1eec7a4a0c5d2180c81aea30Mark Brown */ 12825ffbd136e6c51c8d1eec7a4a0c5d2180c81aea30Mark Brownstruct regulator *regulator_get_exclusive(struct device *dev, const char *id) 12835ffbd136e6c51c8d1eec7a4a0c5d2180c81aea30Mark Brown{ 12845ffbd136e6c51c8d1eec7a4a0c5d2180c81aea30Mark Brown return _regulator_get(dev, id, 1); 12855ffbd136e6c51c8d1eec7a4a0c5d2180c81aea30Mark Brown} 12865ffbd136e6c51c8d1eec7a4a0c5d2180c81aea30Mark BrownEXPORT_SYMBOL_GPL(regulator_get_exclusive); 12875ffbd136e6c51c8d1eec7a4a0c5d2180c81aea30Mark Brown 12885ffbd136e6c51c8d1eec7a4a0c5d2180c81aea30Mark Brown/** 1289414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood * regulator_put - "free" the regulator source 1290414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood * @regulator: regulator source 1291414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood * 1292414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood * Note: drivers must ensure that all regulator_enable calls made on this 1293414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood * regulator source are balanced by regulator_disable calls prior to calling 1294414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood * this function. 1295414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood */ 1296414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwoodvoid regulator_put(struct regulator *regulator) 1297414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood{ 1298414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood struct regulator_dev *rdev; 1299414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood 1300414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood if (regulator == NULL || IS_ERR(regulator)) 1301414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood return; 1302414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood 1303414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood mutex_lock(®ulator_list_mutex); 1304414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood rdev = regulator->rdev; 1305414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood 13065de705194e9883a39f993e2ff96028d5aab99b37Mark Brown#ifdef CONFIG_DEBUG_FS 13075de705194e9883a39f993e2ff96028d5aab99b37Mark Brown debugfs_remove_recursive(regulator->debugfs); 13085de705194e9883a39f993e2ff96028d5aab99b37Mark Brown#endif 13095de705194e9883a39f993e2ff96028d5aab99b37Mark Brown 1310414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood /* remove any sysfs entries */ 1311414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood if (regulator->dev) { 1312414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood sysfs_remove_link(&rdev->dev.kobj, regulator->supply_name); 1313414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood device_remove_file(regulator->dev, ®ulator->dev_attr); 1314414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood kfree(regulator->dev_attr.attr.name); 1315414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood } 13165de705194e9883a39f993e2ff96028d5aab99b37Mark Brown kfree(regulator->supply_name); 1317414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood list_del(®ulator->list); 1318414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood kfree(regulator); 1319414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood 13205ffbd136e6c51c8d1eec7a4a0c5d2180c81aea30Mark Brown rdev->open_count--; 13215ffbd136e6c51c8d1eec7a4a0c5d2180c81aea30Mark Brown rdev->exclusive = 0; 13225ffbd136e6c51c8d1eec7a4a0c5d2180c81aea30Mark Brown 1323414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood module_put(rdev->owner); 1324414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood mutex_unlock(®ulator_list_mutex); 1325414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood} 1326414c70cb91c445ec813b61e16fe4882807e40240Liam GirdwoodEXPORT_SYMBOL_GPL(regulator_put); 1327414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood 13289a2372fa7a403ba327873d0208a619d781a8a150Mark Brownstatic int _regulator_can_change_status(struct regulator_dev *rdev) 13299a2372fa7a403ba327873d0208a619d781a8a150Mark Brown{ 13309a2372fa7a403ba327873d0208a619d781a8a150Mark Brown if (!rdev->constraints) 13319a2372fa7a403ba327873d0208a619d781a8a150Mark Brown return 0; 13329a2372fa7a403ba327873d0208a619d781a8a150Mark Brown 13339a2372fa7a403ba327873d0208a619d781a8a150Mark Brown if (rdev->constraints->valid_ops_mask & REGULATOR_CHANGE_STATUS) 13349a2372fa7a403ba327873d0208a619d781a8a150Mark Brown return 1; 13359a2372fa7a403ba327873d0208a619d781a8a150Mark Brown else 13369a2372fa7a403ba327873d0208a619d781a8a150Mark Brown return 0; 13379a2372fa7a403ba327873d0208a619d781a8a150Mark Brown} 13389a2372fa7a403ba327873d0208a619d781a8a150Mark Brown 1339414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood/* locks held by regulator_enable() */ 1340414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwoodstatic int _regulator_enable(struct regulator_dev *rdev) 1341414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood{ 134231aae2beeb3d601d556b6a8c39085940ad1e9f42Mark Brown int ret, delay; 1343414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood 1344414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood /* check voltage and requested load before enabling */ 13459a2372fa7a403ba327873d0208a619d781a8a150Mark Brown if (rdev->constraints && 13469a2372fa7a403ba327873d0208a619d781a8a150Mark Brown (rdev->constraints->valid_ops_mask & REGULATOR_CHANGE_DRMS)) 13479a2372fa7a403ba327873d0208a619d781a8a150Mark Brown drms_uA_update(rdev); 1348414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood 13499a2372fa7a403ba327873d0208a619d781a8a150Mark Brown if (rdev->use_count == 0) { 13509a2372fa7a403ba327873d0208a619d781a8a150Mark Brown /* The regulator may on if it's not switchable or left on */ 13519a2372fa7a403ba327873d0208a619d781a8a150Mark Brown ret = _regulator_is_enabled(rdev); 13529a2372fa7a403ba327873d0208a619d781a8a150Mark Brown if (ret == -EINVAL || ret == 0) { 13539a2372fa7a403ba327873d0208a619d781a8a150Mark Brown if (!_regulator_can_change_status(rdev)) 13549a2372fa7a403ba327873d0208a619d781a8a150Mark Brown return -EPERM; 13559a2372fa7a403ba327873d0208a619d781a8a150Mark Brown 135631aae2beeb3d601d556b6a8c39085940ad1e9f42Mark Brown if (!rdev->desc->ops->enable) 13579a2372fa7a403ba327873d0208a619d781a8a150Mark Brown return -EINVAL; 135831aae2beeb3d601d556b6a8c39085940ad1e9f42Mark Brown 135931aae2beeb3d601d556b6a8c39085940ad1e9f42Mark Brown /* Query before enabling in case configuration 136025985edcedea6396277003854657b5f3cb31a628Lucas De Marchi * dependent. */ 136131aae2beeb3d601d556b6a8c39085940ad1e9f42Mark Brown ret = _regulator_get_enable_time(rdev); 136231aae2beeb3d601d556b6a8c39085940ad1e9f42Mark Brown if (ret >= 0) { 136331aae2beeb3d601d556b6a8c39085940ad1e9f42Mark Brown delay = ret; 136431aae2beeb3d601d556b6a8c39085940ad1e9f42Mark Brown } else { 13655da84fd99bb1ab1c7cd39d0cf7c08bb63931a59aJoe Perches rdev_warn(rdev, "enable_time() failed: %d\n", 13661d7372e15ebd7f56a336fabe6ee31f8e692cd9cbDaniel Walker ret); 136731aae2beeb3d601d556b6a8c39085940ad1e9f42Mark Brown delay = 0; 13689a2372fa7a403ba327873d0208a619d781a8a150Mark Brown } 136931aae2beeb3d601d556b6a8c39085940ad1e9f42Mark Brown 137002fa3ec01a0df7a8ccc356d8e245a9a1423b3596Mark Brown trace_regulator_enable(rdev_get_name(rdev)); 137102fa3ec01a0df7a8ccc356d8e245a9a1423b3596Mark Brown 137231aae2beeb3d601d556b6a8c39085940ad1e9f42Mark Brown /* Allow the regulator to ramp; it would be useful 137331aae2beeb3d601d556b6a8c39085940ad1e9f42Mark Brown * to extend this for bulk operations so that the 137431aae2beeb3d601d556b6a8c39085940ad1e9f42Mark Brown * regulators can ramp together. */ 137531aae2beeb3d601d556b6a8c39085940ad1e9f42Mark Brown ret = rdev->desc->ops->enable(rdev); 137631aae2beeb3d601d556b6a8c39085940ad1e9f42Mark Brown if (ret < 0) 137731aae2beeb3d601d556b6a8c39085940ad1e9f42Mark Brown return ret; 137831aae2beeb3d601d556b6a8c39085940ad1e9f42Mark Brown 137902fa3ec01a0df7a8ccc356d8e245a9a1423b3596Mark Brown trace_regulator_enable_delay(rdev_get_name(rdev)); 138002fa3ec01a0df7a8ccc356d8e245a9a1423b3596Mark Brown 1381e36c1df8e18183ba2c691fe766a52c94020cdc5eAxel Lin if (delay >= 1000) { 138231aae2beeb3d601d556b6a8c39085940ad1e9f42Mark Brown mdelay(delay / 1000); 1383e36c1df8e18183ba2c691fe766a52c94020cdc5eAxel Lin udelay(delay % 1000); 1384e36c1df8e18183ba2c691fe766a52c94020cdc5eAxel Lin } else if (delay) { 138531aae2beeb3d601d556b6a8c39085940ad1e9f42Mark Brown udelay(delay); 1386e36c1df8e18183ba2c691fe766a52c94020cdc5eAxel Lin } 138731aae2beeb3d601d556b6a8c39085940ad1e9f42Mark Brown 138802fa3ec01a0df7a8ccc356d8e245a9a1423b3596Mark Brown trace_regulator_enable_complete(rdev_get_name(rdev)); 138902fa3ec01a0df7a8ccc356d8e245a9a1423b3596Mark Brown 1390a7433cff9ed8e7982de8e0f210f0325d0f3d1949Linus Walleij } else if (ret < 0) { 13915da84fd99bb1ab1c7cd39d0cf7c08bb63931a59aJoe Perches rdev_err(rdev, "is_enabled() failed: %d\n", ret); 1392414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood return ret; 1393414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood } 1394a7433cff9ed8e7982de8e0f210f0325d0f3d1949Linus Walleij /* Fallthrough on positive return values - already enabled */ 1395414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood } 1396414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood 13979a2372fa7a403ba327873d0208a619d781a8a150Mark Brown rdev->use_count++; 13989a2372fa7a403ba327873d0208a619d781a8a150Mark Brown 13999a2372fa7a403ba327873d0208a619d781a8a150Mark Brown return 0; 1400414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood} 1401414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood 1402414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood/** 1403414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood * regulator_enable - enable regulator output 1404414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood * @regulator: regulator source 1405414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood * 1406cf7bbcdf4d267eff580cb7ce6cf4fe16a940a005Mark Brown * Request that the regulator be enabled with the regulator output at 1407cf7bbcdf4d267eff580cb7ce6cf4fe16a940a005Mark Brown * the predefined voltage or current value. Calls to regulator_enable() 1408cf7bbcdf4d267eff580cb7ce6cf4fe16a940a005Mark Brown * must be balanced with calls to regulator_disable(). 1409cf7bbcdf4d267eff580cb7ce6cf4fe16a940a005Mark Brown * 1410414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood * NOTE: the output value can be set by other drivers, boot loader or may be 1411cf7bbcdf4d267eff580cb7ce6cf4fe16a940a005Mark Brown * hardwired in the regulator. 1412414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood */ 1413414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwoodint regulator_enable(struct regulator *regulator) 1414414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood{ 1415412aec610559bdb602a0a21ce149ba8ffbb6f983David Brownell struct regulator_dev *rdev = regulator->rdev; 1416412aec610559bdb602a0a21ce149ba8ffbb6f983David Brownell int ret = 0; 1417414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood 14183801b86aa482d26a8ae460f67fca29e016491a86Mark Brown if (rdev->supply) { 14193801b86aa482d26a8ae460f67fca29e016491a86Mark Brown ret = regulator_enable(rdev->supply); 14203801b86aa482d26a8ae460f67fca29e016491a86Mark Brown if (ret != 0) 14213801b86aa482d26a8ae460f67fca29e016491a86Mark Brown return ret; 14223801b86aa482d26a8ae460f67fca29e016491a86Mark Brown } 14233801b86aa482d26a8ae460f67fca29e016491a86Mark Brown 1424412aec610559bdb602a0a21ce149ba8ffbb6f983David Brownell mutex_lock(&rdev->mutex); 1425cd94b5053081963614f6ad77b9b66a7968056c84David Brownell ret = _regulator_enable(rdev); 1426412aec610559bdb602a0a21ce149ba8ffbb6f983David Brownell mutex_unlock(&rdev->mutex); 14273801b86aa482d26a8ae460f67fca29e016491a86Mark Brown 14283801b86aa482d26a8ae460f67fca29e016491a86Mark Brown if (ret != 0) 14293801b86aa482d26a8ae460f67fca29e016491a86Mark Brown regulator_disable(rdev->supply); 14303801b86aa482d26a8ae460f67fca29e016491a86Mark Brown 1431414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood return ret; 1432414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood} 1433414c70cb91c445ec813b61e16fe4882807e40240Liam GirdwoodEXPORT_SYMBOL_GPL(regulator_enable); 1434414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood 1435414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood/* locks held by regulator_disable() */ 14363801b86aa482d26a8ae460f67fca29e016491a86Mark Brownstatic int _regulator_disable(struct regulator_dev *rdev) 1437414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood{ 1438414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood int ret = 0; 1439414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood 1440cd94b5053081963614f6ad77b9b66a7968056c84David Brownell if (WARN(rdev->use_count <= 0, 144143e7ee33f2a8d20238267b789791386739247478Joe Perches "unbalanced disables for %s\n", rdev_get_name(rdev))) 1442cd94b5053081963614f6ad77b9b66a7968056c84David Brownell return -EIO; 1443cd94b5053081963614f6ad77b9b66a7968056c84David Brownell 1444414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood /* are we the last user and permitted to disable ? */ 144560ef66fcf40f0e7bc9579981aa16bd8218942a83Mark Brown if (rdev->use_count == 1 && 144660ef66fcf40f0e7bc9579981aa16bd8218942a83Mark Brown (rdev->constraints && !rdev->constraints->always_on)) { 1447414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood 1448414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood /* we are last user */ 14499a2372fa7a403ba327873d0208a619d781a8a150Mark Brown if (_regulator_can_change_status(rdev) && 14509a2372fa7a403ba327873d0208a619d781a8a150Mark Brown rdev->desc->ops->disable) { 145102fa3ec01a0df7a8ccc356d8e245a9a1423b3596Mark Brown trace_regulator_disable(rdev_get_name(rdev)); 145202fa3ec01a0df7a8ccc356d8e245a9a1423b3596Mark Brown 1453414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood ret = rdev->desc->ops->disable(rdev); 1454414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood if (ret < 0) { 14555da84fd99bb1ab1c7cd39d0cf7c08bb63931a59aJoe Perches rdev_err(rdev, "failed to disable\n"); 1456414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood return ret; 1457414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood } 145884b6826306119dc3c41ef9d7ed6c408112f63301Mark Brown 145902fa3ec01a0df7a8ccc356d8e245a9a1423b3596Mark Brown trace_regulator_disable_complete(rdev_get_name(rdev)); 146002fa3ec01a0df7a8ccc356d8e245a9a1423b3596Mark Brown 146184b6826306119dc3c41ef9d7ed6c408112f63301Mark Brown _notifier_call_chain(rdev, REGULATOR_EVENT_DISABLE, 146284b6826306119dc3c41ef9d7ed6c408112f63301Mark Brown NULL); 1463414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood } 1464414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood 1465414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood rdev->use_count = 0; 1466414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood } else if (rdev->use_count > 1) { 1467414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood 1468414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood if (rdev->constraints && 1469414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood (rdev->constraints->valid_ops_mask & 1470414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood REGULATOR_CHANGE_DRMS)) 1471414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood drms_uA_update(rdev); 1472414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood 1473414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood rdev->use_count--; 1474414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood } 14753801b86aa482d26a8ae460f67fca29e016491a86Mark Brown 1476414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood return ret; 1477414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood} 1478414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood 1479414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood/** 1480414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood * regulator_disable - disable regulator output 1481414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood * @regulator: regulator source 1482414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood * 1483cf7bbcdf4d267eff580cb7ce6cf4fe16a940a005Mark Brown * Disable the regulator output voltage or current. Calls to 1484cf7bbcdf4d267eff580cb7ce6cf4fe16a940a005Mark Brown * regulator_enable() must be balanced with calls to 1485cf7bbcdf4d267eff580cb7ce6cf4fe16a940a005Mark Brown * regulator_disable(). 148669279fb9a95051971ac03e558c4d46e7ba84ab3aMark Brown * 1487414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood * NOTE: this will only disable the regulator output if no other consumer 1488cf7bbcdf4d267eff580cb7ce6cf4fe16a940a005Mark Brown * devices have it enabled, the regulator device supports disabling and 1489cf7bbcdf4d267eff580cb7ce6cf4fe16a940a005Mark Brown * machine constraints permit this operation. 1490414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood */ 1491414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwoodint regulator_disable(struct regulator *regulator) 1492414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood{ 1493412aec610559bdb602a0a21ce149ba8ffbb6f983David Brownell struct regulator_dev *rdev = regulator->rdev; 1494412aec610559bdb602a0a21ce149ba8ffbb6f983David Brownell int ret = 0; 1495414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood 1496412aec610559bdb602a0a21ce149ba8ffbb6f983David Brownell mutex_lock(&rdev->mutex); 14973801b86aa482d26a8ae460f67fca29e016491a86Mark Brown ret = _regulator_disable(rdev); 1498412aec610559bdb602a0a21ce149ba8ffbb6f983David Brownell mutex_unlock(&rdev->mutex); 14998cbf811dfd027bde8504e541d0009c5722b98be5Jeffrey Carlyle 15003801b86aa482d26a8ae460f67fca29e016491a86Mark Brown if (ret == 0 && rdev->supply) 15013801b86aa482d26a8ae460f67fca29e016491a86Mark Brown regulator_disable(rdev->supply); 15028cbf811dfd027bde8504e541d0009c5722b98be5Jeffrey Carlyle 1503414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood return ret; 1504414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood} 1505414c70cb91c445ec813b61e16fe4882807e40240Liam GirdwoodEXPORT_SYMBOL_GPL(regulator_disable); 1506414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood 1507414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood/* locks held by regulator_force_disable() */ 15083801b86aa482d26a8ae460f67fca29e016491a86Mark Brownstatic int _regulator_force_disable(struct regulator_dev *rdev) 1509414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood{ 1510414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood int ret = 0; 1511414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood 1512414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood /* force disable */ 1513414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood if (rdev->desc->ops->disable) { 1514414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood /* ah well, who wants to live forever... */ 1515414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood ret = rdev->desc->ops->disable(rdev); 1516414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood if (ret < 0) { 15175da84fd99bb1ab1c7cd39d0cf7c08bb63931a59aJoe Perches rdev_err(rdev, "failed to force disable\n"); 1518414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood return ret; 1519414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood } 1520414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood /* notify other consumers that power has been forced off */ 152184b6826306119dc3c41ef9d7ed6c408112f63301Mark Brown _notifier_call_chain(rdev, REGULATOR_EVENT_FORCE_DISABLE | 152284b6826306119dc3c41ef9d7ed6c408112f63301Mark Brown REGULATOR_EVENT_DISABLE, NULL); 1523414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood } 1524414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood 1525414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood return ret; 1526414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood} 1527414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood 1528414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood/** 1529414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood * regulator_force_disable - force disable regulator output 1530414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood * @regulator: regulator source 1531414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood * 1532414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood * Forcibly disable the regulator output voltage or current. 1533414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood * NOTE: this *will* disable the regulator output even if other consumer 1534414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood * devices have it enabled. This should be used for situations when device 1535414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood * damage will likely occur if the regulator is not disabled (e.g. over temp). 1536414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood */ 1537414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwoodint regulator_force_disable(struct regulator *regulator) 1538414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood{ 153982d158397b6eeb464263a6ef6a739c4118a34720Mark Brown struct regulator_dev *rdev = regulator->rdev; 1540414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood int ret; 1541414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood 154282d158397b6eeb464263a6ef6a739c4118a34720Mark Brown mutex_lock(&rdev->mutex); 1543414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood regulator->uA_load = 0; 15443801b86aa482d26a8ae460f67fca29e016491a86Mark Brown ret = _regulator_force_disable(regulator->rdev); 154582d158397b6eeb464263a6ef6a739c4118a34720Mark Brown mutex_unlock(&rdev->mutex); 15468cbf811dfd027bde8504e541d0009c5722b98be5Jeffrey Carlyle 15473801b86aa482d26a8ae460f67fca29e016491a86Mark Brown if (rdev->supply) 15483801b86aa482d26a8ae460f67fca29e016491a86Mark Brown while (rdev->open_count--) 15493801b86aa482d26a8ae460f67fca29e016491a86Mark Brown regulator_disable(rdev->supply); 15508cbf811dfd027bde8504e541d0009c5722b98be5Jeffrey Carlyle 1551414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood return ret; 1552414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood} 1553414c70cb91c445ec813b61e16fe4882807e40240Liam GirdwoodEXPORT_SYMBOL_GPL(regulator_force_disable); 1554414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood 1555414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwoodstatic int _regulator_is_enabled(struct regulator_dev *rdev) 1556414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood{ 15579a7f6a4c6edc84748c6477c9df56691a0e61b8fdMark Brown /* If we don't know then assume that the regulator is always on */ 15589332546fe88fa88bf6a7d9b1dce53ff5d314934eMark Brown if (!rdev->desc->ops->is_enabled) 15599a7f6a4c6edc84748c6477c9df56691a0e61b8fdMark Brown return 1; 1560414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood 15619332546fe88fa88bf6a7d9b1dce53ff5d314934eMark Brown return rdev->desc->ops->is_enabled(rdev); 1562414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood} 1563414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood 1564414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood/** 1565414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood * regulator_is_enabled - is the regulator output enabled 1566414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood * @regulator: regulator source 1567414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood * 1568412aec610559bdb602a0a21ce149ba8ffbb6f983David Brownell * Returns positive if the regulator driver backing the source/client 1569412aec610559bdb602a0a21ce149ba8ffbb6f983David Brownell * has requested that the device be enabled, zero if it hasn't, else a 1570412aec610559bdb602a0a21ce149ba8ffbb6f983David Brownell * negative errno code. 1571412aec610559bdb602a0a21ce149ba8ffbb6f983David Brownell * 1572412aec610559bdb602a0a21ce149ba8ffbb6f983David Brownell * Note that the device backing this regulator handle can have multiple 1573412aec610559bdb602a0a21ce149ba8ffbb6f983David Brownell * users, so it might be enabled even if regulator_enable() was never 1574412aec610559bdb602a0a21ce149ba8ffbb6f983David Brownell * called for this particular source. 1575414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood */ 1576414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwoodint regulator_is_enabled(struct regulator *regulator) 1577414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood{ 15789332546fe88fa88bf6a7d9b1dce53ff5d314934eMark Brown int ret; 15799332546fe88fa88bf6a7d9b1dce53ff5d314934eMark Brown 15809332546fe88fa88bf6a7d9b1dce53ff5d314934eMark Brown mutex_lock(®ulator->rdev->mutex); 15819332546fe88fa88bf6a7d9b1dce53ff5d314934eMark Brown ret = _regulator_is_enabled(regulator->rdev); 15829332546fe88fa88bf6a7d9b1dce53ff5d314934eMark Brown mutex_unlock(®ulator->rdev->mutex); 15839332546fe88fa88bf6a7d9b1dce53ff5d314934eMark Brown 15849332546fe88fa88bf6a7d9b1dce53ff5d314934eMark Brown return ret; 1585414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood} 1586414c70cb91c445ec813b61e16fe4882807e40240Liam GirdwoodEXPORT_SYMBOL_GPL(regulator_is_enabled); 1587414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood 1588414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood/** 15894367cfdc7c657ad8a797f51b9ffd3c64b31910e7David Brownell * regulator_count_voltages - count regulator_list_voltage() selectors 15904367cfdc7c657ad8a797f51b9ffd3c64b31910e7David Brownell * @regulator: regulator source 15914367cfdc7c657ad8a797f51b9ffd3c64b31910e7David Brownell * 15924367cfdc7c657ad8a797f51b9ffd3c64b31910e7David Brownell * Returns number of selectors, or negative errno. Selectors are 15934367cfdc7c657ad8a797f51b9ffd3c64b31910e7David Brownell * numbered starting at zero, and typically correspond to bitfields 15944367cfdc7c657ad8a797f51b9ffd3c64b31910e7David Brownell * in hardware registers. 15954367cfdc7c657ad8a797f51b9ffd3c64b31910e7David Brownell */ 15964367cfdc7c657ad8a797f51b9ffd3c64b31910e7David Brownellint regulator_count_voltages(struct regulator *regulator) 15974367cfdc7c657ad8a797f51b9ffd3c64b31910e7David Brownell{ 15984367cfdc7c657ad8a797f51b9ffd3c64b31910e7David Brownell struct regulator_dev *rdev = regulator->rdev; 15994367cfdc7c657ad8a797f51b9ffd3c64b31910e7David Brownell 16004367cfdc7c657ad8a797f51b9ffd3c64b31910e7David Brownell return rdev->desc->n_voltages ? : -EINVAL; 16014367cfdc7c657ad8a797f51b9ffd3c64b31910e7David Brownell} 16024367cfdc7c657ad8a797f51b9ffd3c64b31910e7David BrownellEXPORT_SYMBOL_GPL(regulator_count_voltages); 16034367cfdc7c657ad8a797f51b9ffd3c64b31910e7David Brownell 16044367cfdc7c657ad8a797f51b9ffd3c64b31910e7David Brownell/** 16054367cfdc7c657ad8a797f51b9ffd3c64b31910e7David Brownell * regulator_list_voltage - enumerate supported voltages 16064367cfdc7c657ad8a797f51b9ffd3c64b31910e7David Brownell * @regulator: regulator source 16074367cfdc7c657ad8a797f51b9ffd3c64b31910e7David Brownell * @selector: identify voltage to list 16084367cfdc7c657ad8a797f51b9ffd3c64b31910e7David Brownell * Context: can sleep 16094367cfdc7c657ad8a797f51b9ffd3c64b31910e7David Brownell * 16104367cfdc7c657ad8a797f51b9ffd3c64b31910e7David Brownell * Returns a voltage that can be passed to @regulator_set_voltage(), 161188393161210493e317ae391696ee8ef463cb3c23Thomas Weber * zero if this selector code can't be used on this system, or a 16124367cfdc7c657ad8a797f51b9ffd3c64b31910e7David Brownell * negative errno. 16134367cfdc7c657ad8a797f51b9ffd3c64b31910e7David Brownell */ 16144367cfdc7c657ad8a797f51b9ffd3c64b31910e7David Brownellint regulator_list_voltage(struct regulator *regulator, unsigned selector) 16154367cfdc7c657ad8a797f51b9ffd3c64b31910e7David Brownell{ 16164367cfdc7c657ad8a797f51b9ffd3c64b31910e7David Brownell struct regulator_dev *rdev = regulator->rdev; 16174367cfdc7c657ad8a797f51b9ffd3c64b31910e7David Brownell struct regulator_ops *ops = rdev->desc->ops; 16184367cfdc7c657ad8a797f51b9ffd3c64b31910e7David Brownell int ret; 16194367cfdc7c657ad8a797f51b9ffd3c64b31910e7David Brownell 16204367cfdc7c657ad8a797f51b9ffd3c64b31910e7David Brownell if (!ops->list_voltage || selector >= rdev->desc->n_voltages) 16214367cfdc7c657ad8a797f51b9ffd3c64b31910e7David Brownell return -EINVAL; 16224367cfdc7c657ad8a797f51b9ffd3c64b31910e7David Brownell 16234367cfdc7c657ad8a797f51b9ffd3c64b31910e7David Brownell mutex_lock(&rdev->mutex); 16244367cfdc7c657ad8a797f51b9ffd3c64b31910e7David Brownell ret = ops->list_voltage(rdev, selector); 16254367cfdc7c657ad8a797f51b9ffd3c64b31910e7David Brownell mutex_unlock(&rdev->mutex); 16264367cfdc7c657ad8a797f51b9ffd3c64b31910e7David Brownell 16274367cfdc7c657ad8a797f51b9ffd3c64b31910e7David Brownell if (ret > 0) { 16284367cfdc7c657ad8a797f51b9ffd3c64b31910e7David Brownell if (ret < rdev->constraints->min_uV) 16294367cfdc7c657ad8a797f51b9ffd3c64b31910e7David Brownell ret = 0; 16304367cfdc7c657ad8a797f51b9ffd3c64b31910e7David Brownell else if (ret > rdev->constraints->max_uV) 16314367cfdc7c657ad8a797f51b9ffd3c64b31910e7David Brownell ret = 0; 16324367cfdc7c657ad8a797f51b9ffd3c64b31910e7David Brownell } 16334367cfdc7c657ad8a797f51b9ffd3c64b31910e7David Brownell 16344367cfdc7c657ad8a797f51b9ffd3c64b31910e7David Brownell return ret; 16354367cfdc7c657ad8a797f51b9ffd3c64b31910e7David Brownell} 16364367cfdc7c657ad8a797f51b9ffd3c64b31910e7David BrownellEXPORT_SYMBOL_GPL(regulator_list_voltage); 16374367cfdc7c657ad8a797f51b9ffd3c64b31910e7David Brownell 16384367cfdc7c657ad8a797f51b9ffd3c64b31910e7David Brownell/** 1639a7a1ad9066e0266c8a4357ba3dbaeebfb80f531dMark Brown * regulator_is_supported_voltage - check if a voltage range can be supported 1640a7a1ad9066e0266c8a4357ba3dbaeebfb80f531dMark Brown * 1641a7a1ad9066e0266c8a4357ba3dbaeebfb80f531dMark Brown * @regulator: Regulator to check. 1642a7a1ad9066e0266c8a4357ba3dbaeebfb80f531dMark Brown * @min_uV: Minimum required voltage in uV. 1643a7a1ad9066e0266c8a4357ba3dbaeebfb80f531dMark Brown * @max_uV: Maximum required voltage in uV. 1644a7a1ad9066e0266c8a4357ba3dbaeebfb80f531dMark Brown * 1645a7a1ad9066e0266c8a4357ba3dbaeebfb80f531dMark Brown * Returns a boolean or a negative error code. 1646a7a1ad9066e0266c8a4357ba3dbaeebfb80f531dMark Brown */ 1647a7a1ad9066e0266c8a4357ba3dbaeebfb80f531dMark Brownint regulator_is_supported_voltage(struct regulator *regulator, 1648a7a1ad9066e0266c8a4357ba3dbaeebfb80f531dMark Brown int min_uV, int max_uV) 1649a7a1ad9066e0266c8a4357ba3dbaeebfb80f531dMark Brown{ 1650a7a1ad9066e0266c8a4357ba3dbaeebfb80f531dMark Brown int i, voltages, ret; 1651a7a1ad9066e0266c8a4357ba3dbaeebfb80f531dMark Brown 1652a7a1ad9066e0266c8a4357ba3dbaeebfb80f531dMark Brown ret = regulator_count_voltages(regulator); 1653a7a1ad9066e0266c8a4357ba3dbaeebfb80f531dMark Brown if (ret < 0) 1654a7a1ad9066e0266c8a4357ba3dbaeebfb80f531dMark Brown return ret; 1655a7a1ad9066e0266c8a4357ba3dbaeebfb80f531dMark Brown voltages = ret; 1656a7a1ad9066e0266c8a4357ba3dbaeebfb80f531dMark Brown 1657a7a1ad9066e0266c8a4357ba3dbaeebfb80f531dMark Brown for (i = 0; i < voltages; i++) { 1658a7a1ad9066e0266c8a4357ba3dbaeebfb80f531dMark Brown ret = regulator_list_voltage(regulator, i); 1659a7a1ad9066e0266c8a4357ba3dbaeebfb80f531dMark Brown 1660a7a1ad9066e0266c8a4357ba3dbaeebfb80f531dMark Brown if (ret >= min_uV && ret <= max_uV) 1661a7a1ad9066e0266c8a4357ba3dbaeebfb80f531dMark Brown return 1; 1662a7a1ad9066e0266c8a4357ba3dbaeebfb80f531dMark Brown } 1663a7a1ad9066e0266c8a4357ba3dbaeebfb80f531dMark Brown 1664a7a1ad9066e0266c8a4357ba3dbaeebfb80f531dMark Brown return 0; 1665a7a1ad9066e0266c8a4357ba3dbaeebfb80f531dMark Brown} 1666a7a1ad9066e0266c8a4357ba3dbaeebfb80f531dMark Brown 1667757902513019e6ee469791ff76f954b19ca8d036Mark Brownstatic int _regulator_do_set_voltage(struct regulator_dev *rdev, 1668757902513019e6ee469791ff76f954b19ca8d036Mark Brown int min_uV, int max_uV) 1669757902513019e6ee469791ff76f954b19ca8d036Mark Brown{ 1670757902513019e6ee469791ff76f954b19ca8d036Mark Brown int ret; 167177af1b2641faf45788a0d480db94082ebee931dcLinus Walleij int delay = 0; 1672757902513019e6ee469791ff76f954b19ca8d036Mark Brown unsigned int selector; 1673757902513019e6ee469791ff76f954b19ca8d036Mark Brown 1674757902513019e6ee469791ff76f954b19ca8d036Mark Brown trace_regulator_set_voltage(rdev_get_name(rdev), min_uV, max_uV); 1675757902513019e6ee469791ff76f954b19ca8d036Mark Brown 1676bf5892a8167e4aa5a9a6d72f803fde850e0c5753Mark Brown min_uV += rdev->constraints->uV_offset; 1677bf5892a8167e4aa5a9a6d72f803fde850e0c5753Mark Brown max_uV += rdev->constraints->uV_offset; 1678bf5892a8167e4aa5a9a6d72f803fde850e0c5753Mark Brown 1679757902513019e6ee469791ff76f954b19ca8d036Mark Brown if (rdev->desc->ops->set_voltage) { 1680757902513019e6ee469791ff76f954b19ca8d036Mark Brown ret = rdev->desc->ops->set_voltage(rdev, min_uV, max_uV, 1681757902513019e6ee469791ff76f954b19ca8d036Mark Brown &selector); 1682757902513019e6ee469791ff76f954b19ca8d036Mark Brown 1683757902513019e6ee469791ff76f954b19ca8d036Mark Brown if (rdev->desc->ops->list_voltage) 1684757902513019e6ee469791ff76f954b19ca8d036Mark Brown selector = rdev->desc->ops->list_voltage(rdev, 1685757902513019e6ee469791ff76f954b19ca8d036Mark Brown selector); 1686757902513019e6ee469791ff76f954b19ca8d036Mark Brown else 1687757902513019e6ee469791ff76f954b19ca8d036Mark Brown selector = -1; 1688e8eef82b2c652d031bee9dff9762325672f5a1e0Mark Brown } else if (rdev->desc->ops->set_voltage_sel) { 1689e8eef82b2c652d031bee9dff9762325672f5a1e0Mark Brown int best_val = INT_MAX; 1690e8eef82b2c652d031bee9dff9762325672f5a1e0Mark Brown int i; 1691e8eef82b2c652d031bee9dff9762325672f5a1e0Mark Brown 1692e8eef82b2c652d031bee9dff9762325672f5a1e0Mark Brown selector = 0; 1693e8eef82b2c652d031bee9dff9762325672f5a1e0Mark Brown 1694e8eef82b2c652d031bee9dff9762325672f5a1e0Mark Brown /* Find the smallest voltage that falls within the specified 1695e8eef82b2c652d031bee9dff9762325672f5a1e0Mark Brown * range. 1696e8eef82b2c652d031bee9dff9762325672f5a1e0Mark Brown */ 1697e8eef82b2c652d031bee9dff9762325672f5a1e0Mark Brown for (i = 0; i < rdev->desc->n_voltages; i++) { 1698e8eef82b2c652d031bee9dff9762325672f5a1e0Mark Brown ret = rdev->desc->ops->list_voltage(rdev, i); 1699e8eef82b2c652d031bee9dff9762325672f5a1e0Mark Brown if (ret < 0) 1700e8eef82b2c652d031bee9dff9762325672f5a1e0Mark Brown continue; 1701e8eef82b2c652d031bee9dff9762325672f5a1e0Mark Brown 1702e8eef82b2c652d031bee9dff9762325672f5a1e0Mark Brown if (ret < best_val && ret >= min_uV && ret <= max_uV) { 1703e8eef82b2c652d031bee9dff9762325672f5a1e0Mark Brown best_val = ret; 1704e8eef82b2c652d031bee9dff9762325672f5a1e0Mark Brown selector = i; 1705e8eef82b2c652d031bee9dff9762325672f5a1e0Mark Brown } 1706e8eef82b2c652d031bee9dff9762325672f5a1e0Mark Brown } 1707e8eef82b2c652d031bee9dff9762325672f5a1e0Mark Brown 170877af1b2641faf45788a0d480db94082ebee931dcLinus Walleij /* 170977af1b2641faf45788a0d480db94082ebee931dcLinus Walleij * If we can't obtain the old selector there is not enough 171077af1b2641faf45788a0d480db94082ebee931dcLinus Walleij * info to call set_voltage_time_sel(). 171177af1b2641faf45788a0d480db94082ebee931dcLinus Walleij */ 171277af1b2641faf45788a0d480db94082ebee931dcLinus Walleij if (rdev->desc->ops->set_voltage_time_sel && 171377af1b2641faf45788a0d480db94082ebee931dcLinus Walleij rdev->desc->ops->get_voltage_sel) { 171477af1b2641faf45788a0d480db94082ebee931dcLinus Walleij unsigned int old_selector = 0; 171577af1b2641faf45788a0d480db94082ebee931dcLinus Walleij 171677af1b2641faf45788a0d480db94082ebee931dcLinus Walleij ret = rdev->desc->ops->get_voltage_sel(rdev); 171777af1b2641faf45788a0d480db94082ebee931dcLinus Walleij if (ret < 0) 171877af1b2641faf45788a0d480db94082ebee931dcLinus Walleij return ret; 171977af1b2641faf45788a0d480db94082ebee931dcLinus Walleij old_selector = ret; 172077af1b2641faf45788a0d480db94082ebee931dcLinus Walleij delay = rdev->desc->ops->set_voltage_time_sel(rdev, 172177af1b2641faf45788a0d480db94082ebee931dcLinus Walleij old_selector, selector); 172277af1b2641faf45788a0d480db94082ebee931dcLinus Walleij } 172377af1b2641faf45788a0d480db94082ebee931dcLinus Walleij 1724e8eef82b2c652d031bee9dff9762325672f5a1e0Mark Brown if (best_val != INT_MAX) { 1725e8eef82b2c652d031bee9dff9762325672f5a1e0Mark Brown ret = rdev->desc->ops->set_voltage_sel(rdev, selector); 1726e8eef82b2c652d031bee9dff9762325672f5a1e0Mark Brown selector = best_val; 1727e8eef82b2c652d031bee9dff9762325672f5a1e0Mark Brown } else { 1728e8eef82b2c652d031bee9dff9762325672f5a1e0Mark Brown ret = -EINVAL; 1729e8eef82b2c652d031bee9dff9762325672f5a1e0Mark Brown } 1730757902513019e6ee469791ff76f954b19ca8d036Mark Brown } else { 1731757902513019e6ee469791ff76f954b19ca8d036Mark Brown ret = -EINVAL; 1732757902513019e6ee469791ff76f954b19ca8d036Mark Brown } 1733757902513019e6ee469791ff76f954b19ca8d036Mark Brown 173477af1b2641faf45788a0d480db94082ebee931dcLinus Walleij /* Insert any necessary delays */ 173577af1b2641faf45788a0d480db94082ebee931dcLinus Walleij if (delay >= 1000) { 173677af1b2641faf45788a0d480db94082ebee931dcLinus Walleij mdelay(delay / 1000); 173777af1b2641faf45788a0d480db94082ebee931dcLinus Walleij udelay(delay % 1000); 173877af1b2641faf45788a0d480db94082ebee931dcLinus Walleij } else if (delay) { 173977af1b2641faf45788a0d480db94082ebee931dcLinus Walleij udelay(delay); 174077af1b2641faf45788a0d480db94082ebee931dcLinus Walleij } 174177af1b2641faf45788a0d480db94082ebee931dcLinus Walleij 1742ded06a5270ddd6c3c3e25d9ddcaaaa4cb8385c2fMark Brown if (ret == 0) 1743ded06a5270ddd6c3c3e25d9ddcaaaa4cb8385c2fMark Brown _notifier_call_chain(rdev, REGULATOR_EVENT_VOLTAGE_CHANGE, 1744ded06a5270ddd6c3c3e25d9ddcaaaa4cb8385c2fMark Brown NULL); 1745ded06a5270ddd6c3c3e25d9ddcaaaa4cb8385c2fMark Brown 1746757902513019e6ee469791ff76f954b19ca8d036Mark Brown trace_regulator_set_voltage_complete(rdev_get_name(rdev), selector); 1747757902513019e6ee469791ff76f954b19ca8d036Mark Brown 1748757902513019e6ee469791ff76f954b19ca8d036Mark Brown return ret; 1749757902513019e6ee469791ff76f954b19ca8d036Mark Brown} 1750757902513019e6ee469791ff76f954b19ca8d036Mark Brown 1751a7a1ad9066e0266c8a4357ba3dbaeebfb80f531dMark Brown/** 1752414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood * regulator_set_voltage - set regulator output voltage 1753414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood * @regulator: regulator source 1754414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood * @min_uV: Minimum required voltage in uV 1755414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood * @max_uV: Maximum acceptable voltage in uV 1756414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood * 1757414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood * Sets a voltage regulator to the desired output voltage. This can be set 1758414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood * during any regulator state. IOW, regulator can be disabled or enabled. 1759414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood * 1760414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood * If the regulator is enabled then the voltage will change to the new value 1761414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood * immediately otherwise if the regulator is disabled the regulator will 1762414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood * output at the new voltage when enabled. 1763414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood * 1764414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood * NOTE: If the regulator is shared between several devices then the lowest 1765414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood * request voltage that meets the system constraints will be used. 176669279fb9a95051971ac03e558c4d46e7ba84ab3aMark Brown * Regulator system constraints must be set for this regulator before 1767414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood * calling this function otherwise this call will fail. 1768414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood */ 1769414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwoodint regulator_set_voltage(struct regulator *regulator, int min_uV, int max_uV) 1770414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood{ 1771414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood struct regulator_dev *rdev = regulator->rdev; 177295a3c23ae620c1b4c499746e70f4034bdc067737Mark Brown int ret = 0; 1773414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood 1774414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood mutex_lock(&rdev->mutex); 1775414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood 177695a3c23ae620c1b4c499746e70f4034bdc067737Mark Brown /* If we're setting the same range as last time the change 177795a3c23ae620c1b4c499746e70f4034bdc067737Mark Brown * should be a noop (some cpufreq implementations use the same 177895a3c23ae620c1b4c499746e70f4034bdc067737Mark Brown * voltage for multiple frequencies, for example). 177995a3c23ae620c1b4c499746e70f4034bdc067737Mark Brown */ 178095a3c23ae620c1b4c499746e70f4034bdc067737Mark Brown if (regulator->min_uV == min_uV && regulator->max_uV == max_uV) 178195a3c23ae620c1b4c499746e70f4034bdc067737Mark Brown goto out; 178295a3c23ae620c1b4c499746e70f4034bdc067737Mark Brown 1783414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood /* sanity check */ 1784e8eef82b2c652d031bee9dff9762325672f5a1e0Mark Brown if (!rdev->desc->ops->set_voltage && 1785e8eef82b2c652d031bee9dff9762325672f5a1e0Mark Brown !rdev->desc->ops->set_voltage_sel) { 1786414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood ret = -EINVAL; 1787414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood goto out; 1788414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood } 1789414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood 1790414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood /* constraints check */ 1791414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood ret = regulator_check_voltage(rdev, &min_uV, &max_uV); 1792414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood if (ret < 0) 1793414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood goto out; 1794414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood regulator->min_uV = min_uV; 1795414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood regulator->max_uV = max_uV; 17963a93f2a9f4d8f73d74c0e552feb68a10f778a219Mark Brown 179705fda3b1abc23d832144e9497fb218870927d645Thomas Petazzoni ret = regulator_check_consumers(rdev, &min_uV, &max_uV); 179805fda3b1abc23d832144e9497fb218870927d645Thomas Petazzoni if (ret < 0) 179905fda3b1abc23d832144e9497fb218870927d645Thomas Petazzoni goto out; 180005fda3b1abc23d832144e9497fb218870927d645Thomas Petazzoni 1801757902513019e6ee469791ff76f954b19ca8d036Mark Brown ret = _regulator_do_set_voltage(rdev, min_uV, max_uV); 180202fa3ec01a0df7a8ccc356d8e245a9a1423b3596Mark Brown 1803414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwoodout: 1804414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood mutex_unlock(&rdev->mutex); 1805414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood return ret; 1806414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood} 1807414c70cb91c445ec813b61e16fe4882807e40240Liam GirdwoodEXPORT_SYMBOL_GPL(regulator_set_voltage); 1808414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood 1809606a25628187ce863b48d43ca42bc0cbe8342de9Mark Brown/** 181088cd222b259d62148ab8c82398498b1a01314476Linus Walleij * regulator_set_voltage_time - get raise/fall time 181188cd222b259d62148ab8c82398498b1a01314476Linus Walleij * @regulator: regulator source 181288cd222b259d62148ab8c82398498b1a01314476Linus Walleij * @old_uV: starting voltage in microvolts 181388cd222b259d62148ab8c82398498b1a01314476Linus Walleij * @new_uV: target voltage in microvolts 181488cd222b259d62148ab8c82398498b1a01314476Linus Walleij * 181588cd222b259d62148ab8c82398498b1a01314476Linus Walleij * Provided with the starting and ending voltage, this function attempts to 181688cd222b259d62148ab8c82398498b1a01314476Linus Walleij * calculate the time in microseconds required to rise or fall to this new 181788cd222b259d62148ab8c82398498b1a01314476Linus Walleij * voltage. 181888cd222b259d62148ab8c82398498b1a01314476Linus Walleij */ 181988cd222b259d62148ab8c82398498b1a01314476Linus Walleijint regulator_set_voltage_time(struct regulator *regulator, 182088cd222b259d62148ab8c82398498b1a01314476Linus Walleij int old_uV, int new_uV) 182188cd222b259d62148ab8c82398498b1a01314476Linus Walleij{ 182288cd222b259d62148ab8c82398498b1a01314476Linus Walleij struct regulator_dev *rdev = regulator->rdev; 182388cd222b259d62148ab8c82398498b1a01314476Linus Walleij struct regulator_ops *ops = rdev->desc->ops; 182488cd222b259d62148ab8c82398498b1a01314476Linus Walleij int old_sel = -1; 182588cd222b259d62148ab8c82398498b1a01314476Linus Walleij int new_sel = -1; 182688cd222b259d62148ab8c82398498b1a01314476Linus Walleij int voltage; 182788cd222b259d62148ab8c82398498b1a01314476Linus Walleij int i; 182888cd222b259d62148ab8c82398498b1a01314476Linus Walleij 182988cd222b259d62148ab8c82398498b1a01314476Linus Walleij /* Currently requires operations to do this */ 183088cd222b259d62148ab8c82398498b1a01314476Linus Walleij if (!ops->list_voltage || !ops->set_voltage_time_sel 183188cd222b259d62148ab8c82398498b1a01314476Linus Walleij || !rdev->desc->n_voltages) 183288cd222b259d62148ab8c82398498b1a01314476Linus Walleij return -EINVAL; 183388cd222b259d62148ab8c82398498b1a01314476Linus Walleij 183488cd222b259d62148ab8c82398498b1a01314476Linus Walleij for (i = 0; i < rdev->desc->n_voltages; i++) { 183588cd222b259d62148ab8c82398498b1a01314476Linus Walleij /* We only look for exact voltage matches here */ 183688cd222b259d62148ab8c82398498b1a01314476Linus Walleij voltage = regulator_list_voltage(regulator, i); 183788cd222b259d62148ab8c82398498b1a01314476Linus Walleij if (voltage < 0) 183888cd222b259d62148ab8c82398498b1a01314476Linus Walleij return -EINVAL; 183988cd222b259d62148ab8c82398498b1a01314476Linus Walleij if (voltage == 0) 184088cd222b259d62148ab8c82398498b1a01314476Linus Walleij continue; 184188cd222b259d62148ab8c82398498b1a01314476Linus Walleij if (voltage == old_uV) 184288cd222b259d62148ab8c82398498b1a01314476Linus Walleij old_sel = i; 184388cd222b259d62148ab8c82398498b1a01314476Linus Walleij if (voltage == new_uV) 184488cd222b259d62148ab8c82398498b1a01314476Linus Walleij new_sel = i; 184588cd222b259d62148ab8c82398498b1a01314476Linus Walleij } 184688cd222b259d62148ab8c82398498b1a01314476Linus Walleij 184788cd222b259d62148ab8c82398498b1a01314476Linus Walleij if (old_sel < 0 || new_sel < 0) 184888cd222b259d62148ab8c82398498b1a01314476Linus Walleij return -EINVAL; 184988cd222b259d62148ab8c82398498b1a01314476Linus Walleij 185088cd222b259d62148ab8c82398498b1a01314476Linus Walleij return ops->set_voltage_time_sel(rdev, old_sel, new_sel); 185188cd222b259d62148ab8c82398498b1a01314476Linus Walleij} 185288cd222b259d62148ab8c82398498b1a01314476Linus WalleijEXPORT_SYMBOL_GPL(regulator_set_voltage_time); 185388cd222b259d62148ab8c82398498b1a01314476Linus Walleij 185488cd222b259d62148ab8c82398498b1a01314476Linus Walleij/** 1855606a25628187ce863b48d43ca42bc0cbe8342de9Mark Brown * regulator_sync_voltage - re-apply last regulator output voltage 1856606a25628187ce863b48d43ca42bc0cbe8342de9Mark Brown * @regulator: regulator source 1857606a25628187ce863b48d43ca42bc0cbe8342de9Mark Brown * 1858606a25628187ce863b48d43ca42bc0cbe8342de9Mark Brown * Re-apply the last configured voltage. This is intended to be used 1859606a25628187ce863b48d43ca42bc0cbe8342de9Mark Brown * where some external control source the consumer is cooperating with 1860606a25628187ce863b48d43ca42bc0cbe8342de9Mark Brown * has caused the configured voltage to change. 1861606a25628187ce863b48d43ca42bc0cbe8342de9Mark Brown */ 1862606a25628187ce863b48d43ca42bc0cbe8342de9Mark Brownint regulator_sync_voltage(struct regulator *regulator) 1863606a25628187ce863b48d43ca42bc0cbe8342de9Mark Brown{ 1864606a25628187ce863b48d43ca42bc0cbe8342de9Mark Brown struct regulator_dev *rdev = regulator->rdev; 1865606a25628187ce863b48d43ca42bc0cbe8342de9Mark Brown int ret, min_uV, max_uV; 1866606a25628187ce863b48d43ca42bc0cbe8342de9Mark Brown 1867606a25628187ce863b48d43ca42bc0cbe8342de9Mark Brown mutex_lock(&rdev->mutex); 1868606a25628187ce863b48d43ca42bc0cbe8342de9Mark Brown 1869606a25628187ce863b48d43ca42bc0cbe8342de9Mark Brown if (!rdev->desc->ops->set_voltage && 1870606a25628187ce863b48d43ca42bc0cbe8342de9Mark Brown !rdev->desc->ops->set_voltage_sel) { 1871606a25628187ce863b48d43ca42bc0cbe8342de9Mark Brown ret = -EINVAL; 1872606a25628187ce863b48d43ca42bc0cbe8342de9Mark Brown goto out; 1873606a25628187ce863b48d43ca42bc0cbe8342de9Mark Brown } 1874606a25628187ce863b48d43ca42bc0cbe8342de9Mark Brown 1875606a25628187ce863b48d43ca42bc0cbe8342de9Mark Brown /* This is only going to work if we've had a voltage configured. */ 1876606a25628187ce863b48d43ca42bc0cbe8342de9Mark Brown if (!regulator->min_uV && !regulator->max_uV) { 1877606a25628187ce863b48d43ca42bc0cbe8342de9Mark Brown ret = -EINVAL; 1878606a25628187ce863b48d43ca42bc0cbe8342de9Mark Brown goto out; 1879606a25628187ce863b48d43ca42bc0cbe8342de9Mark Brown } 1880606a25628187ce863b48d43ca42bc0cbe8342de9Mark Brown 1881606a25628187ce863b48d43ca42bc0cbe8342de9Mark Brown min_uV = regulator->min_uV; 1882606a25628187ce863b48d43ca42bc0cbe8342de9Mark Brown max_uV = regulator->max_uV; 1883606a25628187ce863b48d43ca42bc0cbe8342de9Mark Brown 1884606a25628187ce863b48d43ca42bc0cbe8342de9Mark Brown /* This should be a paranoia check... */ 1885606a25628187ce863b48d43ca42bc0cbe8342de9Mark Brown ret = regulator_check_voltage(rdev, &min_uV, &max_uV); 1886606a25628187ce863b48d43ca42bc0cbe8342de9Mark Brown if (ret < 0) 1887606a25628187ce863b48d43ca42bc0cbe8342de9Mark Brown goto out; 1888606a25628187ce863b48d43ca42bc0cbe8342de9Mark Brown 1889606a25628187ce863b48d43ca42bc0cbe8342de9Mark Brown ret = regulator_check_consumers(rdev, &min_uV, &max_uV); 1890606a25628187ce863b48d43ca42bc0cbe8342de9Mark Brown if (ret < 0) 1891606a25628187ce863b48d43ca42bc0cbe8342de9Mark Brown goto out; 1892606a25628187ce863b48d43ca42bc0cbe8342de9Mark Brown 1893606a25628187ce863b48d43ca42bc0cbe8342de9Mark Brown ret = _regulator_do_set_voltage(rdev, min_uV, max_uV); 1894606a25628187ce863b48d43ca42bc0cbe8342de9Mark Brown 1895606a25628187ce863b48d43ca42bc0cbe8342de9Mark Brownout: 1896606a25628187ce863b48d43ca42bc0cbe8342de9Mark Brown mutex_unlock(&rdev->mutex); 1897606a25628187ce863b48d43ca42bc0cbe8342de9Mark Brown return ret; 1898606a25628187ce863b48d43ca42bc0cbe8342de9Mark Brown} 1899606a25628187ce863b48d43ca42bc0cbe8342de9Mark BrownEXPORT_SYMBOL_GPL(regulator_sync_voltage); 1900606a25628187ce863b48d43ca42bc0cbe8342de9Mark Brown 1901414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwoodstatic int _regulator_get_voltage(struct regulator_dev *rdev) 1902414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood{ 1903bf5892a8167e4aa5a9a6d72f803fde850e0c5753Mark Brown int sel, ret; 1904476c2d83c7ffb2429b2a504fbdb4326fc8a9d0e8Mark Brown 1905476c2d83c7ffb2429b2a504fbdb4326fc8a9d0e8Mark Brown if (rdev->desc->ops->get_voltage_sel) { 1906476c2d83c7ffb2429b2a504fbdb4326fc8a9d0e8Mark Brown sel = rdev->desc->ops->get_voltage_sel(rdev); 1907476c2d83c7ffb2429b2a504fbdb4326fc8a9d0e8Mark Brown if (sel < 0) 1908476c2d83c7ffb2429b2a504fbdb4326fc8a9d0e8Mark Brown return sel; 1909bf5892a8167e4aa5a9a6d72f803fde850e0c5753Mark Brown ret = rdev->desc->ops->list_voltage(rdev, sel); 1910cb220d16f91f8d5fa1450c7af17e028e8cb3f0f1Axel Lin } else if (rdev->desc->ops->get_voltage) { 1911bf5892a8167e4aa5a9a6d72f803fde850e0c5753Mark Brown ret = rdev->desc->ops->get_voltage(rdev); 1912cb220d16f91f8d5fa1450c7af17e028e8cb3f0f1Axel Lin } else { 1913414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood return -EINVAL; 1914cb220d16f91f8d5fa1450c7af17e028e8cb3f0f1Axel Lin } 1915bf5892a8167e4aa5a9a6d72f803fde850e0c5753Mark Brown 1916cb220d16f91f8d5fa1450c7af17e028e8cb3f0f1Axel Lin if (ret < 0) 1917cb220d16f91f8d5fa1450c7af17e028e8cb3f0f1Axel Lin return ret; 1918bf5892a8167e4aa5a9a6d72f803fde850e0c5753Mark Brown return ret - rdev->constraints->uV_offset; 1919414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood} 1920414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood 1921414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood/** 1922414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood * regulator_get_voltage - get regulator output voltage 1923414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood * @regulator: regulator source 1924414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood * 1925414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood * This returns the current regulator voltage in uV. 1926414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood * 1927414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood * NOTE: If the regulator is disabled it will return the voltage value. This 1928414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood * function should not be used to determine regulator state. 1929414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood */ 1930414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwoodint regulator_get_voltage(struct regulator *regulator) 1931414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood{ 1932414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood int ret; 1933414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood 1934414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood mutex_lock(®ulator->rdev->mutex); 1935414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood 1936414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood ret = _regulator_get_voltage(regulator->rdev); 1937414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood 1938414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood mutex_unlock(®ulator->rdev->mutex); 1939414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood 1940414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood return ret; 1941414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood} 1942414c70cb91c445ec813b61e16fe4882807e40240Liam GirdwoodEXPORT_SYMBOL_GPL(regulator_get_voltage); 1943414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood 1944414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood/** 1945414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood * regulator_set_current_limit - set regulator output current limit 1946414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood * @regulator: regulator source 1947414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood * @min_uA: Minimuum supported current in uA 1948414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood * @max_uA: Maximum supported current in uA 1949414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood * 1950414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood * Sets current sink to the desired output current. This can be set during 1951414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood * any regulator state. IOW, regulator can be disabled or enabled. 1952414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood * 1953414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood * If the regulator is enabled then the current will change to the new value 1954414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood * immediately otherwise if the regulator is disabled the regulator will 1955414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood * output at the new current when enabled. 1956414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood * 1957414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood * NOTE: Regulator system constraints must be set for this regulator before 1958414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood * calling this function otherwise this call will fail. 1959414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood */ 1960414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwoodint regulator_set_current_limit(struct regulator *regulator, 1961414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood int min_uA, int max_uA) 1962414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood{ 1963414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood struct regulator_dev *rdev = regulator->rdev; 1964414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood int ret; 1965414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood 1966414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood mutex_lock(&rdev->mutex); 1967414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood 1968414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood /* sanity check */ 1969414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood if (!rdev->desc->ops->set_current_limit) { 1970414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood ret = -EINVAL; 1971414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood goto out; 1972414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood } 1973414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood 1974414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood /* constraints check */ 1975414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood ret = regulator_check_current_limit(rdev, &min_uA, &max_uA); 1976414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood if (ret < 0) 1977414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood goto out; 1978414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood 1979414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood ret = rdev->desc->ops->set_current_limit(rdev, min_uA, max_uA); 1980414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwoodout: 1981414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood mutex_unlock(&rdev->mutex); 1982414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood return ret; 1983414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood} 1984414c70cb91c445ec813b61e16fe4882807e40240Liam GirdwoodEXPORT_SYMBOL_GPL(regulator_set_current_limit); 1985414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood 1986414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwoodstatic int _regulator_get_current_limit(struct regulator_dev *rdev) 1987414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood{ 1988414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood int ret; 1989414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood 1990414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood mutex_lock(&rdev->mutex); 1991414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood 1992414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood /* sanity check */ 1993414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood if (!rdev->desc->ops->get_current_limit) { 1994414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood ret = -EINVAL; 1995414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood goto out; 1996414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood } 1997414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood 1998414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood ret = rdev->desc->ops->get_current_limit(rdev); 1999414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwoodout: 2000414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood mutex_unlock(&rdev->mutex); 2001414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood return ret; 2002414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood} 2003414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood 2004414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood/** 2005414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood * regulator_get_current_limit - get regulator output current 2006414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood * @regulator: regulator source 2007414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood * 2008414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood * This returns the current supplied by the specified current sink in uA. 2009414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood * 2010414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood * NOTE: If the regulator is disabled it will return the current value. This 2011414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood * function should not be used to determine regulator state. 2012414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood */ 2013414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwoodint regulator_get_current_limit(struct regulator *regulator) 2014414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood{ 2015414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood return _regulator_get_current_limit(regulator->rdev); 2016414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood} 2017414c70cb91c445ec813b61e16fe4882807e40240Liam GirdwoodEXPORT_SYMBOL_GPL(regulator_get_current_limit); 2018414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood 2019414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood/** 2020414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood * regulator_set_mode - set regulator operating mode 2021414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood * @regulator: regulator source 2022414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood * @mode: operating mode - one of the REGULATOR_MODE constants 2023414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood * 2024414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood * Set regulator operating mode to increase regulator efficiency or improve 2025414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood * regulation performance. 2026414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood * 2027414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood * NOTE: Regulator system constraints must be set for this regulator before 2028414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood * calling this function otherwise this call will fail. 2029414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood */ 2030414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwoodint regulator_set_mode(struct regulator *regulator, unsigned int mode) 2031414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood{ 2032414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood struct regulator_dev *rdev = regulator->rdev; 2033414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood int ret; 2034500b4ac90d1103a7c302d5bb16c53f4ffc45d057Sundar R Iyer int regulator_curr_mode; 2035414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood 2036414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood mutex_lock(&rdev->mutex); 2037414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood 2038414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood /* sanity check */ 2039414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood if (!rdev->desc->ops->set_mode) { 2040414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood ret = -EINVAL; 2041414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood goto out; 2042414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood } 2043414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood 2044500b4ac90d1103a7c302d5bb16c53f4ffc45d057Sundar R Iyer /* return if the same mode is requested */ 2045500b4ac90d1103a7c302d5bb16c53f4ffc45d057Sundar R Iyer if (rdev->desc->ops->get_mode) { 2046500b4ac90d1103a7c302d5bb16c53f4ffc45d057Sundar R Iyer regulator_curr_mode = rdev->desc->ops->get_mode(rdev); 2047500b4ac90d1103a7c302d5bb16c53f4ffc45d057Sundar R Iyer if (regulator_curr_mode == mode) { 2048500b4ac90d1103a7c302d5bb16c53f4ffc45d057Sundar R Iyer ret = 0; 2049500b4ac90d1103a7c302d5bb16c53f4ffc45d057Sundar R Iyer goto out; 2050500b4ac90d1103a7c302d5bb16c53f4ffc45d057Sundar R Iyer } 2051500b4ac90d1103a7c302d5bb16c53f4ffc45d057Sundar R Iyer } 2052500b4ac90d1103a7c302d5bb16c53f4ffc45d057Sundar R Iyer 2053414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood /* constraints check */ 205422c51b47aa7cded7e4768540ebbbfddc91e31d90Axel Lin ret = regulator_mode_constrain(rdev, &mode); 2055414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood if (ret < 0) 2056414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood goto out; 2057414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood 2058414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood ret = rdev->desc->ops->set_mode(rdev, mode); 2059414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwoodout: 2060414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood mutex_unlock(&rdev->mutex); 2061414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood return ret; 2062414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood} 2063414c70cb91c445ec813b61e16fe4882807e40240Liam GirdwoodEXPORT_SYMBOL_GPL(regulator_set_mode); 2064414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood 2065414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwoodstatic unsigned int _regulator_get_mode(struct regulator_dev *rdev) 2066414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood{ 2067414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood int ret; 2068414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood 2069414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood mutex_lock(&rdev->mutex); 2070414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood 2071414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood /* sanity check */ 2072414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood if (!rdev->desc->ops->get_mode) { 2073414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood ret = -EINVAL; 2074414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood goto out; 2075414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood } 2076414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood 2077414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood ret = rdev->desc->ops->get_mode(rdev); 2078414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwoodout: 2079414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood mutex_unlock(&rdev->mutex); 2080414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood return ret; 2081414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood} 2082414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood 2083414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood/** 2084414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood * regulator_get_mode - get regulator operating mode 2085414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood * @regulator: regulator source 2086414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood * 2087414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood * Get the current regulator operating mode. 2088414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood */ 2089414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwoodunsigned int regulator_get_mode(struct regulator *regulator) 2090414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood{ 2091414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood return _regulator_get_mode(regulator->rdev); 2092414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood} 2093414c70cb91c445ec813b61e16fe4882807e40240Liam GirdwoodEXPORT_SYMBOL_GPL(regulator_get_mode); 2094414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood 2095414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood/** 2096414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood * regulator_set_optimum_mode - set regulator optimum operating mode 2097414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood * @regulator: regulator source 2098414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood * @uA_load: load current 2099414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood * 2100414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood * Notifies the regulator core of a new device load. This is then used by 2101414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood * DRMS (if enabled by constraints) to set the most efficient regulator 2102414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood * operating mode for the new regulator loading. 2103414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood * 2104414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood * Consumer devices notify their supply regulator of the maximum power 2105414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood * they will require (can be taken from device datasheet in the power 2106414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood * consumption tables) when they change operational status and hence power 2107414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood * state. Examples of operational state changes that can affect power 2108414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood * consumption are :- 2109414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood * 2110414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood * o Device is opened / closed. 2111414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood * o Device I/O is about to begin or has just finished. 2112414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood * o Device is idling in between work. 2113414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood * 2114414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood * This information is also exported via sysfs to userspace. 2115414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood * 2116414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood * DRMS will sum the total requested load on the regulator and change 2117414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood * to the most efficient operating mode if platform constraints allow. 2118414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood * 2119414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood * Returns the new regulator mode or error. 2120414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood */ 2121414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwoodint regulator_set_optimum_mode(struct regulator *regulator, int uA_load) 2122414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood{ 2123414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood struct regulator_dev *rdev = regulator->rdev; 2124414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood struct regulator *consumer; 2125414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood int ret, output_uV, input_uV, total_uA_load = 0; 2126414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood unsigned int mode; 2127414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood 2128414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood mutex_lock(&rdev->mutex); 2129414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood 2130a4b4148379ef1ad460fc1aa6bcf2cde99cd91166Mark Brown /* 2131a4b4148379ef1ad460fc1aa6bcf2cde99cd91166Mark Brown * first check to see if we can set modes at all, otherwise just 2132a4b4148379ef1ad460fc1aa6bcf2cde99cd91166Mark Brown * tell the consumer everything is OK. 2133a4b4148379ef1ad460fc1aa6bcf2cde99cd91166Mark Brown */ 2134414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood regulator->uA_load = uA_load; 2135414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood ret = regulator_check_drms(rdev); 2136a4b4148379ef1ad460fc1aa6bcf2cde99cd91166Mark Brown if (ret < 0) { 2137a4b4148379ef1ad460fc1aa6bcf2cde99cd91166Mark Brown ret = 0; 2138414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood goto out; 2139a4b4148379ef1ad460fc1aa6bcf2cde99cd91166Mark Brown } 2140414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood 2141414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood if (!rdev->desc->ops->get_optimum_mode) 2142414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood goto out; 2143414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood 2144a4b4148379ef1ad460fc1aa6bcf2cde99cd91166Mark Brown /* 2145a4b4148379ef1ad460fc1aa6bcf2cde99cd91166Mark Brown * we can actually do this so any errors are indicators of 2146a4b4148379ef1ad460fc1aa6bcf2cde99cd91166Mark Brown * potential real failure. 2147a4b4148379ef1ad460fc1aa6bcf2cde99cd91166Mark Brown */ 2148a4b4148379ef1ad460fc1aa6bcf2cde99cd91166Mark Brown ret = -EINVAL; 2149a4b4148379ef1ad460fc1aa6bcf2cde99cd91166Mark Brown 2150414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood /* get output voltage */ 21511bf5a1f86a328122714680cd59951074b4f31e07Mark Brown output_uV = _regulator_get_voltage(rdev); 2152414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood if (output_uV <= 0) { 21535da84fd99bb1ab1c7cd39d0cf7c08bb63931a59aJoe Perches rdev_err(rdev, "invalid output voltage found\n"); 2154414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood goto out; 2155414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood } 2156414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood 2157414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood /* get input voltage */ 21581bf5a1f86a328122714680cd59951074b4f31e07Mark Brown input_uV = 0; 21591bf5a1f86a328122714680cd59951074b4f31e07Mark Brown if (rdev->supply) 21603801b86aa482d26a8ae460f67fca29e016491a86Mark Brown input_uV = regulator_get_voltage(rdev->supply); 21611bf5a1f86a328122714680cd59951074b4f31e07Mark Brown if (input_uV <= 0) 2162414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood input_uV = rdev->constraints->input_uV; 2163414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood if (input_uV <= 0) { 21645da84fd99bb1ab1c7cd39d0cf7c08bb63931a59aJoe Perches rdev_err(rdev, "invalid input voltage found\n"); 2165414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood goto out; 2166414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood } 2167414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood 2168414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood /* calc total requested load for this regulator */ 2169414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood list_for_each_entry(consumer, &rdev->consumer_list, list) 2170fa2984d4691c96367d6666694ecc6744135174c6Stefan Roese total_uA_load += consumer->uA_load; 2171414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood 2172414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood mode = rdev->desc->ops->get_optimum_mode(rdev, 2173414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood input_uV, output_uV, 2174414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood total_uA_load); 21752c6082341d1896218ca974cc2bb6876e36fcba5cMark Brown ret = regulator_mode_constrain(rdev, &mode); 2176e573520b171095c106ffbbbf4f9cbed6d9bff576David Brownell if (ret < 0) { 21775da84fd99bb1ab1c7cd39d0cf7c08bb63931a59aJoe Perches rdev_err(rdev, "failed to get optimum mode @ %d uA %d -> %d uV\n", 21785da84fd99bb1ab1c7cd39d0cf7c08bb63931a59aJoe Perches total_uA_load, input_uV, output_uV); 2179414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood goto out; 2180414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood } 2181414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood 2182414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood ret = rdev->desc->ops->set_mode(rdev, mode); 2183e573520b171095c106ffbbbf4f9cbed6d9bff576David Brownell if (ret < 0) { 21845da84fd99bb1ab1c7cd39d0cf7c08bb63931a59aJoe Perches rdev_err(rdev, "failed to set optimum mode %x\n", mode); 2185414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood goto out; 2186414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood } 2187414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood ret = mode; 2188414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwoodout: 2189414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood mutex_unlock(&rdev->mutex); 2190414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood return ret; 2191414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood} 2192414c70cb91c445ec813b61e16fe4882807e40240Liam GirdwoodEXPORT_SYMBOL_GPL(regulator_set_optimum_mode); 2193414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood 2194414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood/** 2195414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood * regulator_register_notifier - register regulator event notifier 2196414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood * @regulator: regulator source 219769279fb9a95051971ac03e558c4d46e7ba84ab3aMark Brown * @nb: notifier block 2198414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood * 2199414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood * Register notifier block to receive regulator events. 2200414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood */ 2201414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwoodint regulator_register_notifier(struct regulator *regulator, 2202414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood struct notifier_block *nb) 2203414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood{ 2204414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood return blocking_notifier_chain_register(®ulator->rdev->notifier, 2205414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood nb); 2206414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood} 2207414c70cb91c445ec813b61e16fe4882807e40240Liam GirdwoodEXPORT_SYMBOL_GPL(regulator_register_notifier); 2208414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood 2209414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood/** 2210414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood * regulator_unregister_notifier - unregister regulator event notifier 2211414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood * @regulator: regulator source 221269279fb9a95051971ac03e558c4d46e7ba84ab3aMark Brown * @nb: notifier block 2213414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood * 2214414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood * Unregister regulator event notifier block. 2215414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood */ 2216414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwoodint regulator_unregister_notifier(struct regulator *regulator, 2217414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood struct notifier_block *nb) 2218414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood{ 2219414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood return blocking_notifier_chain_unregister(®ulator->rdev->notifier, 2220414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood nb); 2221414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood} 2222414c70cb91c445ec813b61e16fe4882807e40240Liam GirdwoodEXPORT_SYMBOL_GPL(regulator_unregister_notifier); 2223414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood 2224b136fb4463d13eea129bf090a8a465bba6bf0003Jonathan Cameron/* notify regulator consumers and downstream regulator consumers. 2225b136fb4463d13eea129bf090a8a465bba6bf0003Jonathan Cameron * Note mutex must be held by caller. 2226b136fb4463d13eea129bf090a8a465bba6bf0003Jonathan Cameron */ 2227414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwoodstatic void _notifier_call_chain(struct regulator_dev *rdev, 2228414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood unsigned long event, void *data) 2229414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood{ 2230414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood /* call rdev chain first */ 2231414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood blocking_notifier_call_chain(&rdev->notifier, event, NULL); 2232414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood} 2233414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood 2234414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood/** 2235414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood * regulator_bulk_get - get multiple regulator consumers 2236414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood * 2237414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood * @dev: Device to supply 2238414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood * @num_consumers: Number of consumers to register 2239414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood * @consumers: Configuration of consumers; clients are stored here. 2240414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood * 2241414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood * @return 0 on success, an errno on failure. 2242414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood * 2243414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood * This helper function allows drivers to get several regulator 2244414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood * consumers in one operation. If any of the regulators cannot be 2245414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood * acquired then any regulators that were allocated will be freed 2246414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood * before returning to the caller. 2247414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood */ 2248414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwoodint regulator_bulk_get(struct device *dev, int num_consumers, 2249414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood struct regulator_bulk_data *consumers) 2250414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood{ 2251414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood int i; 2252414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood int ret; 2253414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood 2254414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood for (i = 0; i < num_consumers; i++) 2255414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood consumers[i].consumer = NULL; 2256414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood 2257414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood for (i = 0; i < num_consumers; i++) { 2258414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood consumers[i].consumer = regulator_get(dev, 2259414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood consumers[i].supply); 2260414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood if (IS_ERR(consumers[i].consumer)) { 2261414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood ret = PTR_ERR(consumers[i].consumer); 22625b307627738f1f6cbc31fad9e28a299b5fe55602Mark Brown dev_err(dev, "Failed to get supply '%s': %d\n", 22635b307627738f1f6cbc31fad9e28a299b5fe55602Mark Brown consumers[i].supply, ret); 2264414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood consumers[i].consumer = NULL; 2265414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood goto err; 2266414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood } 2267414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood } 2268414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood 2269414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood return 0; 2270414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood 2271414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwooderr: 2272414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood for (i = 0; i < num_consumers && consumers[i].consumer; i++) 2273414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood regulator_put(consumers[i].consumer); 2274414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood 2275414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood return ret; 2276414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood} 2277414c70cb91c445ec813b61e16fe4882807e40240Liam GirdwoodEXPORT_SYMBOL_GPL(regulator_bulk_get); 2278414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood 2279f21e0e81d81b649ad309cedc7226f1bed72982e0Mark Brownstatic void regulator_bulk_enable_async(void *data, async_cookie_t cookie) 2280f21e0e81d81b649ad309cedc7226f1bed72982e0Mark Brown{ 2281f21e0e81d81b649ad309cedc7226f1bed72982e0Mark Brown struct regulator_bulk_data *bulk = data; 2282f21e0e81d81b649ad309cedc7226f1bed72982e0Mark Brown 2283f21e0e81d81b649ad309cedc7226f1bed72982e0Mark Brown bulk->ret = regulator_enable(bulk->consumer); 2284f21e0e81d81b649ad309cedc7226f1bed72982e0Mark Brown} 2285f21e0e81d81b649ad309cedc7226f1bed72982e0Mark Brown 2286414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood/** 2287414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood * regulator_bulk_enable - enable multiple regulator consumers 2288414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood * 2289414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood * @num_consumers: Number of consumers 2290414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood * @consumers: Consumer data; clients are stored here. 2291414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood * @return 0 on success, an errno on failure 2292414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood * 2293414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood * This convenience API allows consumers to enable multiple regulator 2294414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood * clients in a single API call. If any consumers cannot be enabled 2295414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood * then any others that were enabled will be disabled again prior to 2296414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood * return. 2297414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood */ 2298414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwoodint regulator_bulk_enable(int num_consumers, 2299414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood struct regulator_bulk_data *consumers) 2300414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood{ 2301f21e0e81d81b649ad309cedc7226f1bed72982e0Mark Brown LIST_HEAD(async_domain); 2302414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood int i; 2303f21e0e81d81b649ad309cedc7226f1bed72982e0Mark Brown int ret = 0; 2304414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood 2305f21e0e81d81b649ad309cedc7226f1bed72982e0Mark Brown for (i = 0; i < num_consumers; i++) 2306f21e0e81d81b649ad309cedc7226f1bed72982e0Mark Brown async_schedule_domain(regulator_bulk_enable_async, 2307f21e0e81d81b649ad309cedc7226f1bed72982e0Mark Brown &consumers[i], &async_domain); 2308f21e0e81d81b649ad309cedc7226f1bed72982e0Mark Brown 2309f21e0e81d81b649ad309cedc7226f1bed72982e0Mark Brown async_synchronize_full_domain(&async_domain); 2310f21e0e81d81b649ad309cedc7226f1bed72982e0Mark Brown 2311f21e0e81d81b649ad309cedc7226f1bed72982e0Mark Brown /* If any consumer failed we need to unwind any that succeeded */ 2312414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood for (i = 0; i < num_consumers; i++) { 2313f21e0e81d81b649ad309cedc7226f1bed72982e0Mark Brown if (consumers[i].ret != 0) { 2314f21e0e81d81b649ad309cedc7226f1bed72982e0Mark Brown ret = consumers[i].ret; 2315414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood goto err; 2316f21e0e81d81b649ad309cedc7226f1bed72982e0Mark Brown } 2317414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood } 2318414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood 2319414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood return 0; 2320414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood 2321414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwooderr: 2322f21e0e81d81b649ad309cedc7226f1bed72982e0Mark Brown for (i = 0; i < num_consumers; i++) 2323f21e0e81d81b649ad309cedc7226f1bed72982e0Mark Brown if (consumers[i].ret == 0) 2324f21e0e81d81b649ad309cedc7226f1bed72982e0Mark Brown regulator_disable(consumers[i].consumer); 2325f21e0e81d81b649ad309cedc7226f1bed72982e0Mark Brown else 2326f21e0e81d81b649ad309cedc7226f1bed72982e0Mark Brown pr_err("Failed to enable %s: %d\n", 2327f21e0e81d81b649ad309cedc7226f1bed72982e0Mark Brown consumers[i].supply, consumers[i].ret); 2328414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood 2329414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood return ret; 2330414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood} 2331414c70cb91c445ec813b61e16fe4882807e40240Liam GirdwoodEXPORT_SYMBOL_GPL(regulator_bulk_enable); 2332414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood 2333414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood/** 2334414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood * regulator_bulk_disable - disable multiple regulator consumers 2335414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood * 2336414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood * @num_consumers: Number of consumers 2337414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood * @consumers: Consumer data; clients are stored here. 2338414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood * @return 0 on success, an errno on failure 2339414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood * 2340414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood * This convenience API allows consumers to disable multiple regulator 2341414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood * clients in a single API call. If any consumers cannot be enabled 2342414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood * then any others that were disabled will be disabled again prior to 2343414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood * return. 2344414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood */ 2345414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwoodint regulator_bulk_disable(int num_consumers, 2346414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood struct regulator_bulk_data *consumers) 2347414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood{ 2348414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood int i; 2349414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood int ret; 2350414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood 2351414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood for (i = 0; i < num_consumers; i++) { 2352414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood ret = regulator_disable(consumers[i].consumer); 2353414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood if (ret != 0) 2354414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood goto err; 2355414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood } 2356414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood 2357414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood return 0; 2358414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood 2359414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwooderr: 23605da84fd99bb1ab1c7cd39d0cf7c08bb63931a59aJoe Perches pr_err("Failed to disable %s: %d\n", consumers[i].supply, ret); 2361eb143ac1b9f56ca9c6dc782d795acda1f60c5fd2Lars-Peter Clausen for (--i; i >= 0; --i) 2362414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood regulator_enable(consumers[i].consumer); 2363414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood 2364414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood return ret; 2365414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood} 2366414c70cb91c445ec813b61e16fe4882807e40240Liam GirdwoodEXPORT_SYMBOL_GPL(regulator_bulk_disable); 2367414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood 2368414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood/** 2369414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood * regulator_bulk_free - free multiple regulator consumers 2370414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood * 2371414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood * @num_consumers: Number of consumers 2372414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood * @consumers: Consumer data; clients are stored here. 2373414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood * 2374414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood * This convenience API allows consumers to free multiple regulator 2375414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood * clients in a single API call. 2376414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood */ 2377414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwoodvoid regulator_bulk_free(int num_consumers, 2378414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood struct regulator_bulk_data *consumers) 2379414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood{ 2380414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood int i; 2381414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood 2382414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood for (i = 0; i < num_consumers; i++) { 2383414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood regulator_put(consumers[i].consumer); 2384414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood consumers[i].consumer = NULL; 2385414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood } 2386414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood} 2387414c70cb91c445ec813b61e16fe4882807e40240Liam GirdwoodEXPORT_SYMBOL_GPL(regulator_bulk_free); 2388414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood 2389414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood/** 2390414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood * regulator_notifier_call_chain - call regulator event notifier 239169279fb9a95051971ac03e558c4d46e7ba84ab3aMark Brown * @rdev: regulator source 2392414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood * @event: notifier block 239369279fb9a95051971ac03e558c4d46e7ba84ab3aMark Brown * @data: callback-specific data. 2394414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood * 2395414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood * Called by regulator drivers to notify clients a regulator event has 2396414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood * occurred. We also notify regulator clients downstream. 2397b136fb4463d13eea129bf090a8a465bba6bf0003Jonathan Cameron * Note lock must be held by caller. 2398414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood */ 2399414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwoodint regulator_notifier_call_chain(struct regulator_dev *rdev, 2400414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood unsigned long event, void *data) 2401414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood{ 2402414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood _notifier_call_chain(rdev, event, data); 2403414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood return NOTIFY_DONE; 2404414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood 2405414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood} 2406414c70cb91c445ec813b61e16fe4882807e40240Liam GirdwoodEXPORT_SYMBOL_GPL(regulator_notifier_call_chain); 2407414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood 2408be721979dd6b335e4ab6f83abb5cc11c33662aa8Mark Brown/** 2409be721979dd6b335e4ab6f83abb5cc11c33662aa8Mark Brown * regulator_mode_to_status - convert a regulator mode into a status 2410be721979dd6b335e4ab6f83abb5cc11c33662aa8Mark Brown * 2411be721979dd6b335e4ab6f83abb5cc11c33662aa8Mark Brown * @mode: Mode to convert 2412be721979dd6b335e4ab6f83abb5cc11c33662aa8Mark Brown * 2413be721979dd6b335e4ab6f83abb5cc11c33662aa8Mark Brown * Convert a regulator mode into a status. 2414be721979dd6b335e4ab6f83abb5cc11c33662aa8Mark Brown */ 2415be721979dd6b335e4ab6f83abb5cc11c33662aa8Mark Brownint regulator_mode_to_status(unsigned int mode) 2416be721979dd6b335e4ab6f83abb5cc11c33662aa8Mark Brown{ 2417be721979dd6b335e4ab6f83abb5cc11c33662aa8Mark Brown switch (mode) { 2418be721979dd6b335e4ab6f83abb5cc11c33662aa8Mark Brown case REGULATOR_MODE_FAST: 2419be721979dd6b335e4ab6f83abb5cc11c33662aa8Mark Brown return REGULATOR_STATUS_FAST; 2420be721979dd6b335e4ab6f83abb5cc11c33662aa8Mark Brown case REGULATOR_MODE_NORMAL: 2421be721979dd6b335e4ab6f83abb5cc11c33662aa8Mark Brown return REGULATOR_STATUS_NORMAL; 2422be721979dd6b335e4ab6f83abb5cc11c33662aa8Mark Brown case REGULATOR_MODE_IDLE: 2423be721979dd6b335e4ab6f83abb5cc11c33662aa8Mark Brown return REGULATOR_STATUS_IDLE; 2424be721979dd6b335e4ab6f83abb5cc11c33662aa8Mark Brown case REGULATOR_STATUS_STANDBY: 2425be721979dd6b335e4ab6f83abb5cc11c33662aa8Mark Brown return REGULATOR_STATUS_STANDBY; 2426be721979dd6b335e4ab6f83abb5cc11c33662aa8Mark Brown default: 2427be721979dd6b335e4ab6f83abb5cc11c33662aa8Mark Brown return 0; 2428be721979dd6b335e4ab6f83abb5cc11c33662aa8Mark Brown } 2429be721979dd6b335e4ab6f83abb5cc11c33662aa8Mark Brown} 2430be721979dd6b335e4ab6f83abb5cc11c33662aa8Mark BrownEXPORT_SYMBOL_GPL(regulator_mode_to_status); 2431be721979dd6b335e4ab6f83abb5cc11c33662aa8Mark Brown 24327ad68e2f970fd84d15ad67ce3216aed05f944a9cDavid Brownell/* 24337ad68e2f970fd84d15ad67ce3216aed05f944a9cDavid Brownell * To avoid cluttering sysfs (and memory) with useless state, only 24347ad68e2f970fd84d15ad67ce3216aed05f944a9cDavid Brownell * create attributes that can be meaningfully displayed. 24357ad68e2f970fd84d15ad67ce3216aed05f944a9cDavid Brownell */ 24367ad68e2f970fd84d15ad67ce3216aed05f944a9cDavid Brownellstatic int add_regulator_attributes(struct regulator_dev *rdev) 24377ad68e2f970fd84d15ad67ce3216aed05f944a9cDavid Brownell{ 24387ad68e2f970fd84d15ad67ce3216aed05f944a9cDavid Brownell struct device *dev = &rdev->dev; 24397ad68e2f970fd84d15ad67ce3216aed05f944a9cDavid Brownell struct regulator_ops *ops = rdev->desc->ops; 24407ad68e2f970fd84d15ad67ce3216aed05f944a9cDavid Brownell int status = 0; 24417ad68e2f970fd84d15ad67ce3216aed05f944a9cDavid Brownell 24427ad68e2f970fd84d15ad67ce3216aed05f944a9cDavid Brownell /* some attributes need specific methods to be displayed */ 2443476c2d83c7ffb2429b2a504fbdb4326fc8a9d0e8Mark Brown if (ops->get_voltage || ops->get_voltage_sel) { 24447ad68e2f970fd84d15ad67ce3216aed05f944a9cDavid Brownell status = device_create_file(dev, &dev_attr_microvolts); 24457ad68e2f970fd84d15ad67ce3216aed05f944a9cDavid Brownell if (status < 0) 24467ad68e2f970fd84d15ad67ce3216aed05f944a9cDavid Brownell return status; 24477ad68e2f970fd84d15ad67ce3216aed05f944a9cDavid Brownell } 24487ad68e2f970fd84d15ad67ce3216aed05f944a9cDavid Brownell if (ops->get_current_limit) { 24497ad68e2f970fd84d15ad67ce3216aed05f944a9cDavid Brownell status = device_create_file(dev, &dev_attr_microamps); 24507ad68e2f970fd84d15ad67ce3216aed05f944a9cDavid Brownell if (status < 0) 24517ad68e2f970fd84d15ad67ce3216aed05f944a9cDavid Brownell return status; 24527ad68e2f970fd84d15ad67ce3216aed05f944a9cDavid Brownell } 24537ad68e2f970fd84d15ad67ce3216aed05f944a9cDavid Brownell if (ops->get_mode) { 24547ad68e2f970fd84d15ad67ce3216aed05f944a9cDavid Brownell status = device_create_file(dev, &dev_attr_opmode); 24557ad68e2f970fd84d15ad67ce3216aed05f944a9cDavid Brownell if (status < 0) 24567ad68e2f970fd84d15ad67ce3216aed05f944a9cDavid Brownell return status; 24577ad68e2f970fd84d15ad67ce3216aed05f944a9cDavid Brownell } 24587ad68e2f970fd84d15ad67ce3216aed05f944a9cDavid Brownell if (ops->is_enabled) { 24597ad68e2f970fd84d15ad67ce3216aed05f944a9cDavid Brownell status = device_create_file(dev, &dev_attr_state); 24607ad68e2f970fd84d15ad67ce3216aed05f944a9cDavid Brownell if (status < 0) 24617ad68e2f970fd84d15ad67ce3216aed05f944a9cDavid Brownell return status; 24627ad68e2f970fd84d15ad67ce3216aed05f944a9cDavid Brownell } 2463853116a10544206b6b2cf42ebc9d78fba2668888David Brownell if (ops->get_status) { 2464853116a10544206b6b2cf42ebc9d78fba2668888David Brownell status = device_create_file(dev, &dev_attr_status); 2465853116a10544206b6b2cf42ebc9d78fba2668888David Brownell if (status < 0) 2466853116a10544206b6b2cf42ebc9d78fba2668888David Brownell return status; 2467853116a10544206b6b2cf42ebc9d78fba2668888David Brownell } 24687ad68e2f970fd84d15ad67ce3216aed05f944a9cDavid Brownell 24697ad68e2f970fd84d15ad67ce3216aed05f944a9cDavid Brownell /* some attributes are type-specific */ 24707ad68e2f970fd84d15ad67ce3216aed05f944a9cDavid Brownell if (rdev->desc->type == REGULATOR_CURRENT) { 24717ad68e2f970fd84d15ad67ce3216aed05f944a9cDavid Brownell status = device_create_file(dev, &dev_attr_requested_microamps); 24727ad68e2f970fd84d15ad67ce3216aed05f944a9cDavid Brownell if (status < 0) 24737ad68e2f970fd84d15ad67ce3216aed05f944a9cDavid Brownell return status; 24747ad68e2f970fd84d15ad67ce3216aed05f944a9cDavid Brownell } 24757ad68e2f970fd84d15ad67ce3216aed05f944a9cDavid Brownell 24767ad68e2f970fd84d15ad67ce3216aed05f944a9cDavid Brownell /* all the other attributes exist to support constraints; 24777ad68e2f970fd84d15ad67ce3216aed05f944a9cDavid Brownell * don't show them if there are no constraints, or if the 24787ad68e2f970fd84d15ad67ce3216aed05f944a9cDavid Brownell * relevant supporting methods are missing. 24797ad68e2f970fd84d15ad67ce3216aed05f944a9cDavid Brownell */ 24807ad68e2f970fd84d15ad67ce3216aed05f944a9cDavid Brownell if (!rdev->constraints) 24817ad68e2f970fd84d15ad67ce3216aed05f944a9cDavid Brownell return status; 24827ad68e2f970fd84d15ad67ce3216aed05f944a9cDavid Brownell 24837ad68e2f970fd84d15ad67ce3216aed05f944a9cDavid Brownell /* constraints need specific supporting methods */ 2484e8eef82b2c652d031bee9dff9762325672f5a1e0Mark Brown if (ops->set_voltage || ops->set_voltage_sel) { 24857ad68e2f970fd84d15ad67ce3216aed05f944a9cDavid Brownell status = device_create_file(dev, &dev_attr_min_microvolts); 24867ad68e2f970fd84d15ad67ce3216aed05f944a9cDavid Brownell if (status < 0) 24877ad68e2f970fd84d15ad67ce3216aed05f944a9cDavid Brownell return status; 24887ad68e2f970fd84d15ad67ce3216aed05f944a9cDavid Brownell status = device_create_file(dev, &dev_attr_max_microvolts); 24897ad68e2f970fd84d15ad67ce3216aed05f944a9cDavid Brownell if (status < 0) 24907ad68e2f970fd84d15ad67ce3216aed05f944a9cDavid Brownell return status; 24917ad68e2f970fd84d15ad67ce3216aed05f944a9cDavid Brownell } 24927ad68e2f970fd84d15ad67ce3216aed05f944a9cDavid Brownell if (ops->set_current_limit) { 24937ad68e2f970fd84d15ad67ce3216aed05f944a9cDavid Brownell status = device_create_file(dev, &dev_attr_min_microamps); 24947ad68e2f970fd84d15ad67ce3216aed05f944a9cDavid Brownell if (status < 0) 24957ad68e2f970fd84d15ad67ce3216aed05f944a9cDavid Brownell return status; 24967ad68e2f970fd84d15ad67ce3216aed05f944a9cDavid Brownell status = device_create_file(dev, &dev_attr_max_microamps); 24977ad68e2f970fd84d15ad67ce3216aed05f944a9cDavid Brownell if (status < 0) 24987ad68e2f970fd84d15ad67ce3216aed05f944a9cDavid Brownell return status; 24997ad68e2f970fd84d15ad67ce3216aed05f944a9cDavid Brownell } 25007ad68e2f970fd84d15ad67ce3216aed05f944a9cDavid Brownell 25017ad68e2f970fd84d15ad67ce3216aed05f944a9cDavid Brownell /* suspend mode constraints need multiple supporting methods */ 25027ad68e2f970fd84d15ad67ce3216aed05f944a9cDavid Brownell if (!(ops->set_suspend_enable && ops->set_suspend_disable)) 25037ad68e2f970fd84d15ad67ce3216aed05f944a9cDavid Brownell return status; 25047ad68e2f970fd84d15ad67ce3216aed05f944a9cDavid Brownell 25057ad68e2f970fd84d15ad67ce3216aed05f944a9cDavid Brownell status = device_create_file(dev, &dev_attr_suspend_standby_state); 25067ad68e2f970fd84d15ad67ce3216aed05f944a9cDavid Brownell if (status < 0) 25077ad68e2f970fd84d15ad67ce3216aed05f944a9cDavid Brownell return status; 25087ad68e2f970fd84d15ad67ce3216aed05f944a9cDavid Brownell status = device_create_file(dev, &dev_attr_suspend_mem_state); 25097ad68e2f970fd84d15ad67ce3216aed05f944a9cDavid Brownell if (status < 0) 25107ad68e2f970fd84d15ad67ce3216aed05f944a9cDavid Brownell return status; 25117ad68e2f970fd84d15ad67ce3216aed05f944a9cDavid Brownell status = device_create_file(dev, &dev_attr_suspend_disk_state); 25127ad68e2f970fd84d15ad67ce3216aed05f944a9cDavid Brownell if (status < 0) 25137ad68e2f970fd84d15ad67ce3216aed05f944a9cDavid Brownell return status; 25147ad68e2f970fd84d15ad67ce3216aed05f944a9cDavid Brownell 25157ad68e2f970fd84d15ad67ce3216aed05f944a9cDavid Brownell if (ops->set_suspend_voltage) { 25167ad68e2f970fd84d15ad67ce3216aed05f944a9cDavid Brownell status = device_create_file(dev, 25177ad68e2f970fd84d15ad67ce3216aed05f944a9cDavid Brownell &dev_attr_suspend_standby_microvolts); 25187ad68e2f970fd84d15ad67ce3216aed05f944a9cDavid Brownell if (status < 0) 25197ad68e2f970fd84d15ad67ce3216aed05f944a9cDavid Brownell return status; 25207ad68e2f970fd84d15ad67ce3216aed05f944a9cDavid Brownell status = device_create_file(dev, 25217ad68e2f970fd84d15ad67ce3216aed05f944a9cDavid Brownell &dev_attr_suspend_mem_microvolts); 25227ad68e2f970fd84d15ad67ce3216aed05f944a9cDavid Brownell if (status < 0) 25237ad68e2f970fd84d15ad67ce3216aed05f944a9cDavid Brownell return status; 25247ad68e2f970fd84d15ad67ce3216aed05f944a9cDavid Brownell status = device_create_file(dev, 25257ad68e2f970fd84d15ad67ce3216aed05f944a9cDavid Brownell &dev_attr_suspend_disk_microvolts); 25267ad68e2f970fd84d15ad67ce3216aed05f944a9cDavid Brownell if (status < 0) 25277ad68e2f970fd84d15ad67ce3216aed05f944a9cDavid Brownell return status; 25287ad68e2f970fd84d15ad67ce3216aed05f944a9cDavid Brownell } 25297ad68e2f970fd84d15ad67ce3216aed05f944a9cDavid Brownell 25307ad68e2f970fd84d15ad67ce3216aed05f944a9cDavid Brownell if (ops->set_suspend_mode) { 25317ad68e2f970fd84d15ad67ce3216aed05f944a9cDavid Brownell status = device_create_file(dev, 25327ad68e2f970fd84d15ad67ce3216aed05f944a9cDavid Brownell &dev_attr_suspend_standby_mode); 25337ad68e2f970fd84d15ad67ce3216aed05f944a9cDavid Brownell if (status < 0) 25347ad68e2f970fd84d15ad67ce3216aed05f944a9cDavid Brownell return status; 25357ad68e2f970fd84d15ad67ce3216aed05f944a9cDavid Brownell status = device_create_file(dev, 25367ad68e2f970fd84d15ad67ce3216aed05f944a9cDavid Brownell &dev_attr_suspend_mem_mode); 25377ad68e2f970fd84d15ad67ce3216aed05f944a9cDavid Brownell if (status < 0) 25387ad68e2f970fd84d15ad67ce3216aed05f944a9cDavid Brownell return status; 25397ad68e2f970fd84d15ad67ce3216aed05f944a9cDavid Brownell status = device_create_file(dev, 25407ad68e2f970fd84d15ad67ce3216aed05f944a9cDavid Brownell &dev_attr_suspend_disk_mode); 25417ad68e2f970fd84d15ad67ce3216aed05f944a9cDavid Brownell if (status < 0) 25427ad68e2f970fd84d15ad67ce3216aed05f944a9cDavid Brownell return status; 25437ad68e2f970fd84d15ad67ce3216aed05f944a9cDavid Brownell } 25447ad68e2f970fd84d15ad67ce3216aed05f944a9cDavid Brownell 25457ad68e2f970fd84d15ad67ce3216aed05f944a9cDavid Brownell return status; 25467ad68e2f970fd84d15ad67ce3216aed05f944a9cDavid Brownell} 25477ad68e2f970fd84d15ad67ce3216aed05f944a9cDavid Brownell 25481130e5b3ff4a7f3f54a48d46e9d0d81b47765bd8Mark Brownstatic void rdev_init_debugfs(struct regulator_dev *rdev) 25491130e5b3ff4a7f3f54a48d46e9d0d81b47765bd8Mark Brown{ 25501130e5b3ff4a7f3f54a48d46e9d0d81b47765bd8Mark Brown#ifdef CONFIG_DEBUG_FS 25511130e5b3ff4a7f3f54a48d46e9d0d81b47765bd8Mark Brown rdev->debugfs = debugfs_create_dir(rdev_get_name(rdev), debugfs_root); 25521130e5b3ff4a7f3f54a48d46e9d0d81b47765bd8Mark Brown if (IS_ERR(rdev->debugfs) || !rdev->debugfs) { 25531130e5b3ff4a7f3f54a48d46e9d0d81b47765bd8Mark Brown rdev_warn(rdev, "Failed to create debugfs directory\n"); 25541130e5b3ff4a7f3f54a48d46e9d0d81b47765bd8Mark Brown rdev->debugfs = NULL; 25551130e5b3ff4a7f3f54a48d46e9d0d81b47765bd8Mark Brown return; 25561130e5b3ff4a7f3f54a48d46e9d0d81b47765bd8Mark Brown } 25571130e5b3ff4a7f3f54a48d46e9d0d81b47765bd8Mark Brown 25581130e5b3ff4a7f3f54a48d46e9d0d81b47765bd8Mark Brown debugfs_create_u32("use_count", 0444, rdev->debugfs, 25591130e5b3ff4a7f3f54a48d46e9d0d81b47765bd8Mark Brown &rdev->use_count); 25601130e5b3ff4a7f3f54a48d46e9d0d81b47765bd8Mark Brown debugfs_create_u32("open_count", 0444, rdev->debugfs, 25611130e5b3ff4a7f3f54a48d46e9d0d81b47765bd8Mark Brown &rdev->open_count); 25621130e5b3ff4a7f3f54a48d46e9d0d81b47765bd8Mark Brown#endif 25631130e5b3ff4a7f3f54a48d46e9d0d81b47765bd8Mark Brown} 25641130e5b3ff4a7f3f54a48d46e9d0d81b47765bd8Mark Brown 2565414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood/** 2566414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood * regulator_register - register regulator 256769279fb9a95051971ac03e558c4d46e7ba84ab3aMark Brown * @regulator_desc: regulator to register 256869279fb9a95051971ac03e558c4d46e7ba84ab3aMark Brown * @dev: struct device for the regulator 25690527100fd11d9710c7e153d791da78824b7b46faMark Brown * @init_data: platform provided init data, passed through by driver 257069279fb9a95051971ac03e558c4d46e7ba84ab3aMark Brown * @driver_data: private regulator data 2571414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood * 2572414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood * Called by regulator drivers to register a regulator. 2573414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood * Returns 0 on success. 2574414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood */ 2575414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwoodstruct regulator_dev *regulator_register(struct regulator_desc *regulator_desc, 2576f8c12fe329c8da9f50d8b2b1183eeaa4d587e747Mark Brown struct device *dev, const struct regulator_init_data *init_data, 25770527100fd11d9710c7e153d791da78824b7b46faMark Brown void *driver_data) 2578414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood{ 2579414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood static atomic_t regulator_no = ATOMIC_INIT(0); 2580414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood struct regulator_dev *rdev; 2581a5766f11cfd3a0c03450d99c8fe548c2940be884Liam Girdwood int ret, i; 2582414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood 2583414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood if (regulator_desc == NULL) 2584414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood return ERR_PTR(-EINVAL); 2585414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood 2586414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood if (regulator_desc->name == NULL || regulator_desc->ops == NULL) 2587414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood return ERR_PTR(-EINVAL); 2588414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood 2589cd78dfc6c6e321a310a73ef7b0df3d262704dd55Diego Liziero if (regulator_desc->type != REGULATOR_VOLTAGE && 2590cd78dfc6c6e321a310a73ef7b0df3d262704dd55Diego Liziero regulator_desc->type != REGULATOR_CURRENT) 2591414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood return ERR_PTR(-EINVAL); 2592414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood 259346fabe1edd44a8893d88d7982f88d01ccf77f0bbMark Brown if (!init_data) 259446fabe1edd44a8893d88d7982f88d01ccf77f0bbMark Brown return ERR_PTR(-EINVAL); 259546fabe1edd44a8893d88d7982f88d01ccf77f0bbMark Brown 2596476c2d83c7ffb2429b2a504fbdb4326fc8a9d0e8Mark Brown /* Only one of each should be implemented */ 2597476c2d83c7ffb2429b2a504fbdb4326fc8a9d0e8Mark Brown WARN_ON(regulator_desc->ops->get_voltage && 2598476c2d83c7ffb2429b2a504fbdb4326fc8a9d0e8Mark Brown regulator_desc->ops->get_voltage_sel); 2599e8eef82b2c652d031bee9dff9762325672f5a1e0Mark Brown WARN_ON(regulator_desc->ops->set_voltage && 2600e8eef82b2c652d031bee9dff9762325672f5a1e0Mark Brown regulator_desc->ops->set_voltage_sel); 2601476c2d83c7ffb2429b2a504fbdb4326fc8a9d0e8Mark Brown 2602476c2d83c7ffb2429b2a504fbdb4326fc8a9d0e8Mark Brown /* If we're using selectors we must implement list_voltage. */ 2603476c2d83c7ffb2429b2a504fbdb4326fc8a9d0e8Mark Brown if (regulator_desc->ops->get_voltage_sel && 2604476c2d83c7ffb2429b2a504fbdb4326fc8a9d0e8Mark Brown !regulator_desc->ops->list_voltage) { 2605476c2d83c7ffb2429b2a504fbdb4326fc8a9d0e8Mark Brown return ERR_PTR(-EINVAL); 2606476c2d83c7ffb2429b2a504fbdb4326fc8a9d0e8Mark Brown } 2607e8eef82b2c652d031bee9dff9762325672f5a1e0Mark Brown if (regulator_desc->ops->set_voltage_sel && 2608e8eef82b2c652d031bee9dff9762325672f5a1e0Mark Brown !regulator_desc->ops->list_voltage) { 2609e8eef82b2c652d031bee9dff9762325672f5a1e0Mark Brown return ERR_PTR(-EINVAL); 2610e8eef82b2c652d031bee9dff9762325672f5a1e0Mark Brown } 2611476c2d83c7ffb2429b2a504fbdb4326fc8a9d0e8Mark Brown 2612414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood rdev = kzalloc(sizeof(struct regulator_dev), GFP_KERNEL); 2613414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood if (rdev == NULL) 2614414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood return ERR_PTR(-ENOMEM); 2615414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood 2616414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood mutex_lock(®ulator_list_mutex); 2617414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood 2618414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood mutex_init(&rdev->mutex); 2619a5766f11cfd3a0c03450d99c8fe548c2940be884Liam Girdwood rdev->reg_data = driver_data; 2620414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood rdev->owner = regulator_desc->owner; 2621414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood rdev->desc = regulator_desc; 2622414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood INIT_LIST_HEAD(&rdev->consumer_list); 2623414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood INIT_LIST_HEAD(&rdev->list); 2624414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood BLOCKING_INIT_NOTIFIER_HEAD(&rdev->notifier); 2625414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood 2626a5766f11cfd3a0c03450d99c8fe548c2940be884Liam Girdwood /* preform any regulator specific init */ 2627a5766f11cfd3a0c03450d99c8fe548c2940be884Liam Girdwood if (init_data->regulator_init) { 2628a5766f11cfd3a0c03450d99c8fe548c2940be884Liam Girdwood ret = init_data->regulator_init(rdev->reg_data); 26294fca9545d17b99cdb2774716b034c62a70151bcdDavid Brownell if (ret < 0) 26304fca9545d17b99cdb2774716b034c62a70151bcdDavid Brownell goto clean; 2631a5766f11cfd3a0c03450d99c8fe548c2940be884Liam Girdwood } 2632a5766f11cfd3a0c03450d99c8fe548c2940be884Liam Girdwood 2633a5766f11cfd3a0c03450d99c8fe548c2940be884Liam Girdwood /* register with sysfs */ 2634414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood rdev->dev.class = ®ulator_class; 2635a5766f11cfd3a0c03450d99c8fe548c2940be884Liam Girdwood rdev->dev.parent = dev; 2636812460a927c1d0dc1fbdbec9aa07de1b04043d83Kay Sievers dev_set_name(&rdev->dev, "regulator.%d", 2637812460a927c1d0dc1fbdbec9aa07de1b04043d83Kay Sievers atomic_inc_return(®ulator_no) - 1); 2638a5766f11cfd3a0c03450d99c8fe548c2940be884Liam Girdwood ret = device_register(&rdev->dev); 2639ad7725cb43b8badb2fec2c2bfca07c067f2e19a7Vasiliy Kulikov if (ret != 0) { 2640ad7725cb43b8badb2fec2c2bfca07c067f2e19a7Vasiliy Kulikov put_device(&rdev->dev); 26414fca9545d17b99cdb2774716b034c62a70151bcdDavid Brownell goto clean; 2642ad7725cb43b8badb2fec2c2bfca07c067f2e19a7Vasiliy Kulikov } 2643a5766f11cfd3a0c03450d99c8fe548c2940be884Liam Girdwood 2644a5766f11cfd3a0c03450d99c8fe548c2940be884Liam Girdwood dev_set_drvdata(&rdev->dev, rdev); 2645a5766f11cfd3a0c03450d99c8fe548c2940be884Liam Girdwood 264674f544c1fc0339acf6f66ff438b8543b1f9faf10Mike Rapoport /* set regulator constraints */ 264774f544c1fc0339acf6f66ff438b8543b1f9faf10Mike Rapoport ret = set_machine_constraints(rdev, &init_data->constraints); 264874f544c1fc0339acf6f66ff438b8543b1f9faf10Mike Rapoport if (ret < 0) 264974f544c1fc0339acf6f66ff438b8543b1f9faf10Mike Rapoport goto scrub; 265074f544c1fc0339acf6f66ff438b8543b1f9faf10Mike Rapoport 26517ad68e2f970fd84d15ad67ce3216aed05f944a9cDavid Brownell /* add attributes supported by this regulator */ 26527ad68e2f970fd84d15ad67ce3216aed05f944a9cDavid Brownell ret = add_regulator_attributes(rdev); 26537ad68e2f970fd84d15ad67ce3216aed05f944a9cDavid Brownell if (ret < 0) 26547ad68e2f970fd84d15ad67ce3216aed05f944a9cDavid Brownell goto scrub; 26557ad68e2f970fd84d15ad67ce3216aed05f944a9cDavid Brownell 26560178f3e28e2166664916265c5d4922b1376b9fa1Mark Brown if (init_data->supply_regulator) { 26570178f3e28e2166664916265c5d4922b1376b9fa1Mark Brown struct regulator_dev *r; 26580178f3e28e2166664916265c5d4922b1376b9fa1Mark Brown int found = 0; 26590178f3e28e2166664916265c5d4922b1376b9fa1Mark Brown 26600178f3e28e2166664916265c5d4922b1376b9fa1Mark Brown list_for_each_entry(r, ®ulator_list, list) { 26610178f3e28e2166664916265c5d4922b1376b9fa1Mark Brown if (strcmp(rdev_get_name(r), 26620178f3e28e2166664916265c5d4922b1376b9fa1Mark Brown init_data->supply_regulator) == 0) { 26630178f3e28e2166664916265c5d4922b1376b9fa1Mark Brown found = 1; 26640178f3e28e2166664916265c5d4922b1376b9fa1Mark Brown break; 26650178f3e28e2166664916265c5d4922b1376b9fa1Mark Brown } 26660178f3e28e2166664916265c5d4922b1376b9fa1Mark Brown } 26670178f3e28e2166664916265c5d4922b1376b9fa1Mark Brown 26680178f3e28e2166664916265c5d4922b1376b9fa1Mark Brown if (!found) { 26690178f3e28e2166664916265c5d4922b1376b9fa1Mark Brown dev_err(dev, "Failed to find supply %s\n", 26700178f3e28e2166664916265c5d4922b1376b9fa1Mark Brown init_data->supply_regulator); 26717727da22e820a96ab394db2fc0ab58f7f7ecb323Axel Lin ret = -ENODEV; 26720178f3e28e2166664916265c5d4922b1376b9fa1Mark Brown goto scrub; 26730178f3e28e2166664916265c5d4922b1376b9fa1Mark Brown } 26740178f3e28e2166664916265c5d4922b1376b9fa1Mark Brown 26750178f3e28e2166664916265c5d4922b1376b9fa1Mark Brown ret = set_supply(rdev, r); 26760178f3e28e2166664916265c5d4922b1376b9fa1Mark Brown if (ret < 0) 26770178f3e28e2166664916265c5d4922b1376b9fa1Mark Brown goto scrub; 26780178f3e28e2166664916265c5d4922b1376b9fa1Mark Brown } 26790178f3e28e2166664916265c5d4922b1376b9fa1Mark Brown 2680a5766f11cfd3a0c03450d99c8fe548c2940be884Liam Girdwood /* add consumers devices */ 2681a5766f11cfd3a0c03450d99c8fe548c2940be884Liam Girdwood for (i = 0; i < init_data->num_consumer_supplies; i++) { 2682a5766f11cfd3a0c03450d99c8fe548c2940be884Liam Girdwood ret = set_consumer_device_supply(rdev, 2683a5766f11cfd3a0c03450d99c8fe548c2940be884Liam Girdwood init_data->consumer_supplies[i].dev, 268440f9244f4da8976eeb6d5ed6313c635ba238a9d3Mark Brown init_data->consumer_supplies[i].dev_name, 2685a5766f11cfd3a0c03450d99c8fe548c2940be884Liam Girdwood init_data->consumer_supplies[i].supply); 268623c2f041efa891e6ec0706dc9ad4f776a9aa8c14Mark Brown if (ret < 0) { 268723c2f041efa891e6ec0706dc9ad4f776a9aa8c14Mark Brown dev_err(dev, "Failed to set supply %s\n", 268823c2f041efa891e6ec0706dc9ad4f776a9aa8c14Mark Brown init_data->consumer_supplies[i].supply); 2689d4033b54fc91221b13e2850bf298683c0f2ff37dJani Nikula goto unset_supplies; 269023c2f041efa891e6ec0706dc9ad4f776a9aa8c14Mark Brown } 2691414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood } 2692a5766f11cfd3a0c03450d99c8fe548c2940be884Liam Girdwood 2693a5766f11cfd3a0c03450d99c8fe548c2940be884Liam Girdwood list_add(&rdev->list, ®ulator_list); 26941130e5b3ff4a7f3f54a48d46e9d0d81b47765bd8Mark Brown 26951130e5b3ff4a7f3f54a48d46e9d0d81b47765bd8Mark Brown rdev_init_debugfs(rdev); 2696a5766f11cfd3a0c03450d99c8fe548c2940be884Liam Girdwoodout: 2697414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood mutex_unlock(®ulator_list_mutex); 2698414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood return rdev; 26994fca9545d17b99cdb2774716b034c62a70151bcdDavid Brownell 2700d4033b54fc91221b13e2850bf298683c0f2ff37dJani Nikulaunset_supplies: 2701d4033b54fc91221b13e2850bf298683c0f2ff37dJani Nikula unset_regulator_supplies(rdev); 2702d4033b54fc91221b13e2850bf298683c0f2ff37dJani Nikula 27034fca9545d17b99cdb2774716b034c62a70151bcdDavid Brownellscrub: 27044fca9545d17b99cdb2774716b034c62a70151bcdDavid Brownell device_unregister(&rdev->dev); 270553032dafc6b93ac178ca2340ff8eb4ee2b3d1a92Paul Walmsley /* device core frees rdev */ 270653032dafc6b93ac178ca2340ff8eb4ee2b3d1a92Paul Walmsley rdev = ERR_PTR(ret); 270753032dafc6b93ac178ca2340ff8eb4ee2b3d1a92Paul Walmsley goto out; 270853032dafc6b93ac178ca2340ff8eb4ee2b3d1a92Paul Walmsley 27094fca9545d17b99cdb2774716b034c62a70151bcdDavid Brownellclean: 27104fca9545d17b99cdb2774716b034c62a70151bcdDavid Brownell kfree(rdev); 27114fca9545d17b99cdb2774716b034c62a70151bcdDavid Brownell rdev = ERR_PTR(ret); 27124fca9545d17b99cdb2774716b034c62a70151bcdDavid Brownell goto out; 2713414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood} 2714414c70cb91c445ec813b61e16fe4882807e40240Liam GirdwoodEXPORT_SYMBOL_GPL(regulator_register); 2715414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood 2716414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood/** 2717414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood * regulator_unregister - unregister regulator 271869279fb9a95051971ac03e558c4d46e7ba84ab3aMark Brown * @rdev: regulator to unregister 2719414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood * 2720414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood * Called by regulator drivers to unregister a regulator. 2721414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood */ 2722414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwoodvoid regulator_unregister(struct regulator_dev *rdev) 2723414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood{ 2724414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood if (rdev == NULL) 2725414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood return; 2726414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood 2727414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood mutex_lock(®ulator_list_mutex); 27281130e5b3ff4a7f3f54a48d46e9d0d81b47765bd8Mark Brown#ifdef CONFIG_DEBUG_FS 27291130e5b3ff4a7f3f54a48d46e9d0d81b47765bd8Mark Brown debugfs_remove_recursive(rdev->debugfs); 27301130e5b3ff4a7f3f54a48d46e9d0d81b47765bd8Mark Brown#endif 27316bf87d17c9f5b855e9dde7b3d6f726385b966814Mark Brown WARN_ON(rdev->open_count); 27320f1d747bfa89de4ca52dc1dffdcce35a2b8a1532Mike Rapoport unset_regulator_supplies(rdev); 2733414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood list_del(&rdev->list); 2734414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood if (rdev->supply) 27353801b86aa482d26a8ae460f67fca29e016491a86Mark Brown regulator_put(rdev->supply); 2736414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood device_unregister(&rdev->dev); 2737f8c12fe329c8da9f50d8b2b1183eeaa4d587e747Mark Brown kfree(rdev->constraints); 2738414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood mutex_unlock(®ulator_list_mutex); 2739414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood} 2740414c70cb91c445ec813b61e16fe4882807e40240Liam GirdwoodEXPORT_SYMBOL_GPL(regulator_unregister); 2741414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood 2742414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood/** 2743cf7bbcdf4d267eff580cb7ce6cf4fe16a940a005Mark Brown * regulator_suspend_prepare - prepare regulators for system wide suspend 2744414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood * @state: system suspend state 2745414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood * 2746414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood * Configure each regulator with it's suspend operating parameters for state. 2747414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood * This will usually be called by machine suspend code prior to supending. 2748414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood */ 2749414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwoodint regulator_suspend_prepare(suspend_state_t state) 2750414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood{ 2751414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood struct regulator_dev *rdev; 2752414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood int ret = 0; 2753414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood 2754414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood /* ON is handled by regulator active state */ 2755414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood if (state == PM_SUSPEND_ON) 2756414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood return -EINVAL; 2757414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood 2758414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood mutex_lock(®ulator_list_mutex); 2759414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood list_for_each_entry(rdev, ®ulator_list, list) { 2760414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood 2761414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood mutex_lock(&rdev->mutex); 2762414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood ret = suspend_prepare(rdev, state); 2763414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood mutex_unlock(&rdev->mutex); 2764414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood 2765414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood if (ret < 0) { 27665da84fd99bb1ab1c7cd39d0cf7c08bb63931a59aJoe Perches rdev_err(rdev, "failed to prepare\n"); 2767414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood goto out; 2768414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood } 2769414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood } 2770414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwoodout: 2771414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood mutex_unlock(®ulator_list_mutex); 2772414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood return ret; 2773414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood} 2774414c70cb91c445ec813b61e16fe4882807e40240Liam GirdwoodEXPORT_SYMBOL_GPL(regulator_suspend_prepare); 2775414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood 2776414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood/** 27777a32b589a9c856493bccb02db55047edc04eee7bMyungJoo Ham * regulator_suspend_finish - resume regulators from system wide suspend 27787a32b589a9c856493bccb02db55047edc04eee7bMyungJoo Ham * 27797a32b589a9c856493bccb02db55047edc04eee7bMyungJoo Ham * Turn on regulators that might be turned off by regulator_suspend_prepare 27807a32b589a9c856493bccb02db55047edc04eee7bMyungJoo Ham * and that should be turned on according to the regulators properties. 27817a32b589a9c856493bccb02db55047edc04eee7bMyungJoo Ham */ 27827a32b589a9c856493bccb02db55047edc04eee7bMyungJoo Hamint regulator_suspend_finish(void) 27837a32b589a9c856493bccb02db55047edc04eee7bMyungJoo Ham{ 27847a32b589a9c856493bccb02db55047edc04eee7bMyungJoo Ham struct regulator_dev *rdev; 27857a32b589a9c856493bccb02db55047edc04eee7bMyungJoo Ham int ret = 0, error; 27867a32b589a9c856493bccb02db55047edc04eee7bMyungJoo Ham 27877a32b589a9c856493bccb02db55047edc04eee7bMyungJoo Ham mutex_lock(®ulator_list_mutex); 27887a32b589a9c856493bccb02db55047edc04eee7bMyungJoo Ham list_for_each_entry(rdev, ®ulator_list, list) { 27897a32b589a9c856493bccb02db55047edc04eee7bMyungJoo Ham struct regulator_ops *ops = rdev->desc->ops; 27907a32b589a9c856493bccb02db55047edc04eee7bMyungJoo Ham 27917a32b589a9c856493bccb02db55047edc04eee7bMyungJoo Ham mutex_lock(&rdev->mutex); 27927a32b589a9c856493bccb02db55047edc04eee7bMyungJoo Ham if ((rdev->use_count > 0 || rdev->constraints->always_on) && 27937a32b589a9c856493bccb02db55047edc04eee7bMyungJoo Ham ops->enable) { 27947a32b589a9c856493bccb02db55047edc04eee7bMyungJoo Ham error = ops->enable(rdev); 27957a32b589a9c856493bccb02db55047edc04eee7bMyungJoo Ham if (error) 27967a32b589a9c856493bccb02db55047edc04eee7bMyungJoo Ham ret = error; 27977a32b589a9c856493bccb02db55047edc04eee7bMyungJoo Ham } else { 27987a32b589a9c856493bccb02db55047edc04eee7bMyungJoo Ham if (!has_full_constraints) 27997a32b589a9c856493bccb02db55047edc04eee7bMyungJoo Ham goto unlock; 28007a32b589a9c856493bccb02db55047edc04eee7bMyungJoo Ham if (!ops->disable) 28017a32b589a9c856493bccb02db55047edc04eee7bMyungJoo Ham goto unlock; 28027a32b589a9c856493bccb02db55047edc04eee7bMyungJoo Ham if (ops->is_enabled && !ops->is_enabled(rdev)) 28037a32b589a9c856493bccb02db55047edc04eee7bMyungJoo Ham goto unlock; 28047a32b589a9c856493bccb02db55047edc04eee7bMyungJoo Ham 28057a32b589a9c856493bccb02db55047edc04eee7bMyungJoo Ham error = ops->disable(rdev); 28067a32b589a9c856493bccb02db55047edc04eee7bMyungJoo Ham if (error) 28077a32b589a9c856493bccb02db55047edc04eee7bMyungJoo Ham ret = error; 28087a32b589a9c856493bccb02db55047edc04eee7bMyungJoo Ham } 28097a32b589a9c856493bccb02db55047edc04eee7bMyungJoo Hamunlock: 28107a32b589a9c856493bccb02db55047edc04eee7bMyungJoo Ham mutex_unlock(&rdev->mutex); 28117a32b589a9c856493bccb02db55047edc04eee7bMyungJoo Ham } 28127a32b589a9c856493bccb02db55047edc04eee7bMyungJoo Ham mutex_unlock(®ulator_list_mutex); 28137a32b589a9c856493bccb02db55047edc04eee7bMyungJoo Ham return ret; 28147a32b589a9c856493bccb02db55047edc04eee7bMyungJoo Ham} 28157a32b589a9c856493bccb02db55047edc04eee7bMyungJoo HamEXPORT_SYMBOL_GPL(regulator_suspend_finish); 28167a32b589a9c856493bccb02db55047edc04eee7bMyungJoo Ham 28177a32b589a9c856493bccb02db55047edc04eee7bMyungJoo Ham/** 2818ca7255614e0861e36480103f4a402a115803d7b5Mark Brown * regulator_has_full_constraints - the system has fully specified constraints 2819ca7255614e0861e36480103f4a402a115803d7b5Mark Brown * 2820ca7255614e0861e36480103f4a402a115803d7b5Mark Brown * Calling this function will cause the regulator API to disable all 2821ca7255614e0861e36480103f4a402a115803d7b5Mark Brown * regulators which have a zero use count and don't have an always_on 2822ca7255614e0861e36480103f4a402a115803d7b5Mark Brown * constraint in a late_initcall. 2823ca7255614e0861e36480103f4a402a115803d7b5Mark Brown * 2824ca7255614e0861e36480103f4a402a115803d7b5Mark Brown * The intention is that this will become the default behaviour in a 2825ca7255614e0861e36480103f4a402a115803d7b5Mark Brown * future kernel release so users are encouraged to use this facility 2826ca7255614e0861e36480103f4a402a115803d7b5Mark Brown * now. 2827ca7255614e0861e36480103f4a402a115803d7b5Mark Brown */ 2828ca7255614e0861e36480103f4a402a115803d7b5Mark Brownvoid regulator_has_full_constraints(void) 2829ca7255614e0861e36480103f4a402a115803d7b5Mark Brown{ 2830ca7255614e0861e36480103f4a402a115803d7b5Mark Brown has_full_constraints = 1; 2831ca7255614e0861e36480103f4a402a115803d7b5Mark Brown} 2832ca7255614e0861e36480103f4a402a115803d7b5Mark BrownEXPORT_SYMBOL_GPL(regulator_has_full_constraints); 2833ca7255614e0861e36480103f4a402a115803d7b5Mark Brown 2834ca7255614e0861e36480103f4a402a115803d7b5Mark Brown/** 2835688fe99a439f7c9dfcc52fbf7cb347f140a2dc8bMark Brown * regulator_use_dummy_regulator - Provide a dummy regulator when none is found 2836688fe99a439f7c9dfcc52fbf7cb347f140a2dc8bMark Brown * 2837688fe99a439f7c9dfcc52fbf7cb347f140a2dc8bMark Brown * Calling this function will cause the regulator API to provide a 2838688fe99a439f7c9dfcc52fbf7cb347f140a2dc8bMark Brown * dummy regulator to consumers if no physical regulator is found, 2839688fe99a439f7c9dfcc52fbf7cb347f140a2dc8bMark Brown * allowing most consumers to proceed as though a regulator were 2840688fe99a439f7c9dfcc52fbf7cb347f140a2dc8bMark Brown * configured. This allows systems such as those with software 2841688fe99a439f7c9dfcc52fbf7cb347f140a2dc8bMark Brown * controllable regulators for the CPU core only to be brought up more 2842688fe99a439f7c9dfcc52fbf7cb347f140a2dc8bMark Brown * readily. 2843688fe99a439f7c9dfcc52fbf7cb347f140a2dc8bMark Brown */ 2844688fe99a439f7c9dfcc52fbf7cb347f140a2dc8bMark Brownvoid regulator_use_dummy_regulator(void) 2845688fe99a439f7c9dfcc52fbf7cb347f140a2dc8bMark Brown{ 2846688fe99a439f7c9dfcc52fbf7cb347f140a2dc8bMark Brown board_wants_dummy_regulator = true; 2847688fe99a439f7c9dfcc52fbf7cb347f140a2dc8bMark Brown} 2848688fe99a439f7c9dfcc52fbf7cb347f140a2dc8bMark BrownEXPORT_SYMBOL_GPL(regulator_use_dummy_regulator); 2849688fe99a439f7c9dfcc52fbf7cb347f140a2dc8bMark Brown 2850688fe99a439f7c9dfcc52fbf7cb347f140a2dc8bMark Brown/** 2851414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood * rdev_get_drvdata - get rdev regulator driver data 285269279fb9a95051971ac03e558c4d46e7ba84ab3aMark Brown * @rdev: regulator 2853414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood * 2854414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood * Get rdev regulator driver private data. This call can be used in the 2855414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood * regulator driver context. 2856414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood */ 2857414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwoodvoid *rdev_get_drvdata(struct regulator_dev *rdev) 2858414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood{ 2859414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood return rdev->reg_data; 2860414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood} 2861414c70cb91c445ec813b61e16fe4882807e40240Liam GirdwoodEXPORT_SYMBOL_GPL(rdev_get_drvdata); 2862414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood 2863414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood/** 2864414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood * regulator_get_drvdata - get regulator driver data 2865414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood * @regulator: regulator 2866414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood * 2867414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood * Get regulator driver private data. This call can be used in the consumer 2868414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood * driver context when non API regulator specific functions need to be called. 2869414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood */ 2870414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwoodvoid *regulator_get_drvdata(struct regulator *regulator) 2871414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood{ 2872414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood return regulator->rdev->reg_data; 2873414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood} 2874414c70cb91c445ec813b61e16fe4882807e40240Liam GirdwoodEXPORT_SYMBOL_GPL(regulator_get_drvdata); 2875414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood 2876414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood/** 2877414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood * regulator_set_drvdata - set regulator driver data 2878414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood * @regulator: regulator 2879414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood * @data: data 2880414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood */ 2881414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwoodvoid regulator_set_drvdata(struct regulator *regulator, void *data) 2882414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood{ 2883414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood regulator->rdev->reg_data = data; 2884414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood} 2885414c70cb91c445ec813b61e16fe4882807e40240Liam GirdwoodEXPORT_SYMBOL_GPL(regulator_set_drvdata); 2886414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood 2887414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood/** 2888414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood * regulator_get_id - get regulator ID 288969279fb9a95051971ac03e558c4d46e7ba84ab3aMark Brown * @rdev: regulator 2890414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood */ 2891414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwoodint rdev_get_id(struct regulator_dev *rdev) 2892414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood{ 2893414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood return rdev->desc->id; 2894414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood} 2895414c70cb91c445ec813b61e16fe4882807e40240Liam GirdwoodEXPORT_SYMBOL_GPL(rdev_get_id); 2896414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood 2897a5766f11cfd3a0c03450d99c8fe548c2940be884Liam Girdwoodstruct device *rdev_get_dev(struct regulator_dev *rdev) 2898a5766f11cfd3a0c03450d99c8fe548c2940be884Liam Girdwood{ 2899a5766f11cfd3a0c03450d99c8fe548c2940be884Liam Girdwood return &rdev->dev; 2900a5766f11cfd3a0c03450d99c8fe548c2940be884Liam Girdwood} 2901a5766f11cfd3a0c03450d99c8fe548c2940be884Liam GirdwoodEXPORT_SYMBOL_GPL(rdev_get_dev); 2902a5766f11cfd3a0c03450d99c8fe548c2940be884Liam Girdwood 2903a5766f11cfd3a0c03450d99c8fe548c2940be884Liam Girdwoodvoid *regulator_get_init_drvdata(struct regulator_init_data *reg_init_data) 2904a5766f11cfd3a0c03450d99c8fe548c2940be884Liam Girdwood{ 2905a5766f11cfd3a0c03450d99c8fe548c2940be884Liam Girdwood return reg_init_data->driver_data; 2906a5766f11cfd3a0c03450d99c8fe548c2940be884Liam Girdwood} 2907a5766f11cfd3a0c03450d99c8fe548c2940be884Liam GirdwoodEXPORT_SYMBOL_GPL(regulator_get_init_drvdata); 2908a5766f11cfd3a0c03450d99c8fe548c2940be884Liam Girdwood 2909414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwoodstatic int __init regulator_init(void) 2910414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood{ 291134abbd68efe09765465b81dfedeee9994f13302fMark Brown int ret; 291234abbd68efe09765465b81dfedeee9994f13302fMark Brown 291334abbd68efe09765465b81dfedeee9994f13302fMark Brown ret = class_register(®ulator_class); 291434abbd68efe09765465b81dfedeee9994f13302fMark Brown 29151130e5b3ff4a7f3f54a48d46e9d0d81b47765bd8Mark Brown#ifdef CONFIG_DEBUG_FS 29161130e5b3ff4a7f3f54a48d46e9d0d81b47765bd8Mark Brown debugfs_root = debugfs_create_dir("regulator", NULL); 29171130e5b3ff4a7f3f54a48d46e9d0d81b47765bd8Mark Brown if (IS_ERR(debugfs_root) || !debugfs_root) { 29181130e5b3ff4a7f3f54a48d46e9d0d81b47765bd8Mark Brown pr_warn("regulator: Failed to create debugfs directory\n"); 29191130e5b3ff4a7f3f54a48d46e9d0d81b47765bd8Mark Brown debugfs_root = NULL; 29201130e5b3ff4a7f3f54a48d46e9d0d81b47765bd8Mark Brown } 29211130e5b3ff4a7f3f54a48d46e9d0d81b47765bd8Mark Brown#endif 29221130e5b3ff4a7f3f54a48d46e9d0d81b47765bd8Mark Brown 292334abbd68efe09765465b81dfedeee9994f13302fMark Brown regulator_dummy_init(); 292434abbd68efe09765465b81dfedeee9994f13302fMark Brown 292534abbd68efe09765465b81dfedeee9994f13302fMark Brown return ret; 2926414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood} 2927414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood 2928414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwood/* init early to allow our consumers to complete system booting */ 2929414c70cb91c445ec813b61e16fe4882807e40240Liam Girdwoodcore_initcall(regulator_init); 2930ca7255614e0861e36480103f4a402a115803d7b5Mark Brown 2931ca7255614e0861e36480103f4a402a115803d7b5Mark Brownstatic int __init regulator_init_complete(void) 2932ca7255614e0861e36480103f4a402a115803d7b5Mark Brown{ 2933ca7255614e0861e36480103f4a402a115803d7b5Mark Brown struct regulator_dev *rdev; 2934ca7255614e0861e36480103f4a402a115803d7b5Mark Brown struct regulator_ops *ops; 2935ca7255614e0861e36480103f4a402a115803d7b5Mark Brown struct regulation_constraints *c; 2936ca7255614e0861e36480103f4a402a115803d7b5Mark Brown int enabled, ret; 2937ca7255614e0861e36480103f4a402a115803d7b5Mark Brown 2938ca7255614e0861e36480103f4a402a115803d7b5Mark Brown mutex_lock(®ulator_list_mutex); 2939ca7255614e0861e36480103f4a402a115803d7b5Mark Brown 2940ca7255614e0861e36480103f4a402a115803d7b5Mark Brown /* If we have a full configuration then disable any regulators 2941ca7255614e0861e36480103f4a402a115803d7b5Mark Brown * which are not in use or always_on. This will become the 2942ca7255614e0861e36480103f4a402a115803d7b5Mark Brown * default behaviour in the future. 2943ca7255614e0861e36480103f4a402a115803d7b5Mark Brown */ 2944ca7255614e0861e36480103f4a402a115803d7b5Mark Brown list_for_each_entry(rdev, ®ulator_list, list) { 2945ca7255614e0861e36480103f4a402a115803d7b5Mark Brown ops = rdev->desc->ops; 2946ca7255614e0861e36480103f4a402a115803d7b5Mark Brown c = rdev->constraints; 2947ca7255614e0861e36480103f4a402a115803d7b5Mark Brown 2948f25e0b4fcc38d120e704c377791158c4b2a54daaMark Brown if (!ops->disable || (c && c->always_on)) 2949ca7255614e0861e36480103f4a402a115803d7b5Mark Brown continue; 2950ca7255614e0861e36480103f4a402a115803d7b5Mark Brown 2951ca7255614e0861e36480103f4a402a115803d7b5Mark Brown mutex_lock(&rdev->mutex); 2952ca7255614e0861e36480103f4a402a115803d7b5Mark Brown 2953ca7255614e0861e36480103f4a402a115803d7b5Mark Brown if (rdev->use_count) 2954ca7255614e0861e36480103f4a402a115803d7b5Mark Brown goto unlock; 2955ca7255614e0861e36480103f4a402a115803d7b5Mark Brown 2956ca7255614e0861e36480103f4a402a115803d7b5Mark Brown /* If we can't read the status assume it's on. */ 2957ca7255614e0861e36480103f4a402a115803d7b5Mark Brown if (ops->is_enabled) 2958ca7255614e0861e36480103f4a402a115803d7b5Mark Brown enabled = ops->is_enabled(rdev); 2959ca7255614e0861e36480103f4a402a115803d7b5Mark Brown else 2960ca7255614e0861e36480103f4a402a115803d7b5Mark Brown enabled = 1; 2961ca7255614e0861e36480103f4a402a115803d7b5Mark Brown 2962ca7255614e0861e36480103f4a402a115803d7b5Mark Brown if (!enabled) 2963ca7255614e0861e36480103f4a402a115803d7b5Mark Brown goto unlock; 2964ca7255614e0861e36480103f4a402a115803d7b5Mark Brown 2965ca7255614e0861e36480103f4a402a115803d7b5Mark Brown if (has_full_constraints) { 2966ca7255614e0861e36480103f4a402a115803d7b5Mark Brown /* We log since this may kill the system if it 2967ca7255614e0861e36480103f4a402a115803d7b5Mark Brown * goes wrong. */ 29685da84fd99bb1ab1c7cd39d0cf7c08bb63931a59aJoe Perches rdev_info(rdev, "disabling\n"); 2969ca7255614e0861e36480103f4a402a115803d7b5Mark Brown ret = ops->disable(rdev); 2970ca7255614e0861e36480103f4a402a115803d7b5Mark Brown if (ret != 0) { 29715da84fd99bb1ab1c7cd39d0cf7c08bb63931a59aJoe Perches rdev_err(rdev, "couldn't disable: %d\n", ret); 2972ca7255614e0861e36480103f4a402a115803d7b5Mark Brown } 2973ca7255614e0861e36480103f4a402a115803d7b5Mark Brown } else { 2974ca7255614e0861e36480103f4a402a115803d7b5Mark Brown /* The intention is that in future we will 2975ca7255614e0861e36480103f4a402a115803d7b5Mark Brown * assume that full constraints are provided 2976ca7255614e0861e36480103f4a402a115803d7b5Mark Brown * so warn even if we aren't going to do 2977ca7255614e0861e36480103f4a402a115803d7b5Mark Brown * anything here. 2978ca7255614e0861e36480103f4a402a115803d7b5Mark Brown */ 29795da84fd99bb1ab1c7cd39d0cf7c08bb63931a59aJoe Perches rdev_warn(rdev, "incomplete constraints, leaving on\n"); 2980ca7255614e0861e36480103f4a402a115803d7b5Mark Brown } 2981ca7255614e0861e36480103f4a402a115803d7b5Mark Brown 2982ca7255614e0861e36480103f4a402a115803d7b5Mark Brownunlock: 2983ca7255614e0861e36480103f4a402a115803d7b5Mark Brown mutex_unlock(&rdev->mutex); 2984ca7255614e0861e36480103f4a402a115803d7b5Mark Brown } 2985ca7255614e0861e36480103f4a402a115803d7b5Mark Brown 2986ca7255614e0861e36480103f4a402a115803d7b5Mark Brown mutex_unlock(®ulator_list_mutex); 2987ca7255614e0861e36480103f4a402a115803d7b5Mark Brown 2988ca7255614e0861e36480103f4a402a115803d7b5Mark Brown return 0; 2989ca7255614e0861e36480103f4a402a115803d7b5Mark Brown} 2990ca7255614e0861e36480103f4a402a115803d7b5Mark Brownlate_initcall(regulator_init_complete); 2991