diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2009-01-08 14:51:11 -0800 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2009-01-08 14:51:11 -0800 |
commit | 022992ee59e90fef719493c09988884be157fb73 (patch) | |
tree | f532c33454d9fc3a7fb2cf488b25f69a93d00bc6 | |
parent | 5fbbf5f648a9c4ef99276854f05b2255d1b004d3 (diff) | |
parent | 0ba4887c6329043d6cee5b5b477cfe50c2b57674 (diff) | |
download | linux-022992ee59e90fef719493c09988884be157fb73.tar.bz2 |
Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/lrg/voltage-2.6
* 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/lrg/voltage-2.6:
regulator: fix kernel-doc warnings
regulator: catch some registration errors
regulator: Add basic DocBook manual
regulator: Fix some kerneldoc rendering issues
regulator: Add missing kerneldoc
regulator: Clean up kerneldoc warnings
regulator: Remove extraneous kerneldoc annotations
regulator: init/link earlier
regulator: move set_machine_constraints after regulator device initialization
regulator: da903x: make da903x_is_enabled return 0 or 1
regulator: da903x: add '\n' to error messages
regulator: sysfs attribute reduction (v2)
regulator: code shrink (v2)
regulator: improved mode error checks
regulator: enable/disable refcounting
regulator: struct device - replace bus_id with dev_name(), dev_set_name()
-rw-r--r-- | Documentation/ABI/testing/sysfs-class-regulator | 136 | ||||
-rw-r--r-- | Documentation/DocBook/Makefile | 2 | ||||
-rw-r--r-- | Documentation/DocBook/regulator.tmpl | 304 | ||||
-rw-r--r-- | drivers/Makefile | 4 | ||||
-rw-r--r-- | drivers/regulator/core.c | 474 | ||||
-rw-r--r-- | drivers/regulator/da903x.c | 12 | ||||
-rw-r--r-- | include/linux/regulator/consumer.h | 8 | ||||
-rw-r--r-- | include/linux/regulator/driver.h | 37 | ||||
-rw-r--r-- | include/linux/regulator/machine.h | 41 |
9 files changed, 746 insertions, 272 deletions
diff --git a/Documentation/ABI/testing/sysfs-class-regulator b/Documentation/ABI/testing/sysfs-class-regulator index 3731f6f29bcb..873ef1fc1569 100644 --- a/Documentation/ABI/testing/sysfs-class-regulator +++ b/Documentation/ABI/testing/sysfs-class-regulator @@ -3,8 +3,9 @@ Date: April 2008 KernelVersion: 2.6.26 Contact: Liam Girdwood <lrg@slimlogic.co.uk> Description: - Each regulator directory will contain a field called - state. This holds the regulator output state. + Some regulator directories will contain a field called + state. This reports the regulator enable status, for + regulators which can report that value. This will be one of the following strings: @@ -18,7 +19,8 @@ Description: 'disabled' means the regulator output is OFF and is not supplying power to the system.. - 'unknown' means software cannot determine the state. + 'unknown' means software cannot determine the state, or + the reported state is invalid. NOTE: this field can be used in conjunction with microvolts and microamps to determine regulator output levels. @@ -53,9 +55,10 @@ Date: April 2008 KernelVersion: 2.6.26 Contact: Liam Girdwood <lrg@slimlogic.co.uk> Description: - Each regulator directory will contain a field called + Some regulator directories will contain a field called microvolts. This holds the regulator output voltage setting - measured in microvolts (i.e. E-6 Volts). + measured in microvolts (i.e. E-6 Volts), for regulators + which can report that voltage. NOTE: This value should not be used to determine the regulator output voltage level as this value is the same regardless of @@ -67,9 +70,10 @@ Date: April 2008 KernelVersion: 2.6.26 Contact: Liam Girdwood <lrg@slimlogic.co.uk> Description: - Each regulator directory will contain a field called + Some regulator directories will contain a field called microamps. This holds the regulator output current limit - setting measured in microamps (i.e. E-6 Amps). + setting measured in microamps (i.e. E-6 Amps), for regulators + which can report that current. NOTE: This value should not be used to determine the regulator output current level as this value is the same regardless of @@ -81,8 +85,9 @@ Date: April 2008 KernelVersion: 2.6.26 Contact: Liam Girdwood <lrg@slimlogic.co.uk> Description: - Each regulator directory will contain a field called - opmode. This holds the regulator operating mode setting. + Some regulator directories will contain a field called + opmode. This holds the current regulator operating mode, + for regulators which can report it. The opmode value can be one of the following strings: @@ -92,7 +97,7 @@ Description: 'standby' 'unknown' - The modes are described in include/linux/regulator/regulator.h + The modes are described in include/linux/regulator/consumer.h NOTE: This value should not be used to determine the regulator output operating mode as this value is the same regardless of @@ -104,9 +109,10 @@ Date: April 2008 KernelVersion: 2.6.26 Contact: Liam Girdwood <lrg@slimlogic.co.uk> Description: - Each regulator directory will contain a field called + Some regulator directories will contain a field called min_microvolts. This holds the minimum safe working regulator - output voltage setting for this domain measured in microvolts. + output voltage setting for this domain measured in microvolts, + for regulators which support voltage constraints. NOTE: this will return the string 'constraint not defined' if the power domain has no min microvolts constraint defined by @@ -118,9 +124,10 @@ Date: April 2008 KernelVersion: 2.6.26 Contact: Liam Girdwood <lrg@slimlogic.co.uk> Description: - Each regulator directory will contain a field called + Some regulator directories will contain a field called max_microvolts. This holds the maximum safe working regulator - output voltage setting for this domain measured in microvolts. + output voltage setting for this domain measured in microvolts, + for regulators which support voltage constraints. NOTE: this will return the string 'constraint not defined' if the power domain has no max microvolts constraint defined by @@ -132,10 +139,10 @@ Date: April 2008 KernelVersion: 2.6.26 Contact: Liam Girdwood <lrg@slimlogic.co.uk> Description: - Each regulator directory will contain a field called + Some regulator directories will contain a field called min_microamps. This holds the minimum safe working regulator output current limit setting for this domain measured in - microamps. + microamps, for regulators which support current constraints. NOTE: this will return the string 'constraint not defined' if the power domain has no min microamps constraint defined by @@ -147,10 +154,10 @@ Date: April 2008 KernelVersion: 2.6.26 Contact: Liam Girdwood <lrg@slimlogic.co.uk> Description: - Each regulator directory will contain a field called + Some regulator directories will contain a field called max_microamps. This holds the maximum safe working regulator output current limit setting for this domain measured in - microamps. + microamps, for regulators which support current constraints. NOTE: this will return the string 'constraint not defined' if the power domain has no max microamps constraint defined by @@ -185,7 +192,7 @@ Date: April 2008 KernelVersion: 2.6.26 Contact: Liam Girdwood <lrg@slimlogic.co.uk> Description: - Each regulator directory will contain a field called + Some regulator directories will contain a field called requested_microamps. This holds the total requested load current in microamps for this regulator from all its consumer devices. @@ -204,125 +211,102 @@ Date: May 2008 KernelVersion: 2.6.26 Contact: Liam Girdwood <lrg@slimlogic.co.uk> Description: - Each regulator directory will contain a field called + Some regulator directories will contain a field called suspend_mem_microvolts. This holds the regulator output voltage setting for this domain measured in microvolts when - the system is suspended to memory. - - NOTE: this will return the string 'not defined' if - the power domain has no suspend to memory voltage defined by - platform code. + the system is suspended to memory, for voltage regulators + implementing suspend voltage configuration constraints. What: /sys/class/regulator/.../suspend_disk_microvolts Date: May 2008 KernelVersion: 2.6.26 Contact: Liam Girdwood <lrg@slimlogic.co.uk> Description: - Each regulator directory will contain a field called + Some regulator directories will contain a field called suspend_disk_microvolts. This holds the regulator output voltage setting for this domain measured in microvolts when - the system is suspended to disk. - - NOTE: this will return the string 'not defined' if - the power domain has no suspend to disk voltage defined by - platform code. + the system is suspended to disk, for voltage regulators + implementing suspend voltage configuration constraints. What: /sys/class/regulator/.../suspend_standby_microvolts Date: May 2008 KernelVersion: 2.6.26 Contact: Liam Girdwood <lrg@slimlogic.co.uk> Description: - Each regulator directory will contain a field called + Some regulator directories will contain a field called suspend_standby_microvolts. This holds the regulator output voltage setting for this domain measured in microvolts when - the system is suspended to standby. - - NOTE: this will return the string 'not defined' if - the power domain has no suspend to standby voltage defined by - platform code. + the system is suspended to standby, for voltage regulators + implementing suspend voltage configuration constraints. What: /sys/class/regulator/.../suspend_mem_mode Date: May 2008 KernelVersion: 2.6.26 Contact: Liam Girdwood <lrg@slimlogic.co.uk> Description: - Each regulator directory will contain a field called + Some regulator directories will contain a field called suspend_mem_mode. This holds the regulator operating mode setting for this domain when the system is suspended to - memory. - - NOTE: this will return the string 'not defined' if - the power domain has no suspend to memory mode defined by - platform code. + memory, for regulators implementing suspend mode + configuration constraints. What: /sys/class/regulator/.../suspend_disk_mode Date: May 2008 KernelVersion: 2.6.26 Contact: Liam Girdwood <lrg@slimlogic.co.uk> Description: - Each regulator directory will contain a field called + Some regulator directories will contain a field called suspend_disk_mode. This holds the regulator operating mode - setting for this domain when the system is suspended to disk. - - NOTE: this will return the string 'not defined' if - the power domain has no suspend to disk mode defined by - platform code. + setting for this domain when the system is suspended to disk, + for regulators implementing suspend mode configuration + constraints. What: /sys/class/regulator/.../suspend_standby_mode Date: May 2008 KernelVersion: 2.6.26 Contact: Liam Girdwood <lrg@slimlogic.co.uk> Description: - Each regulator directory will contain a field called + Some regulator directories will contain a field called suspend_standby_mode. This holds the regulator operating mode setting for this domain when the system is suspended to - standby. - - NOTE: this will return the string 'not defined' if - the power domain has no suspend to standby mode defined by - platform code. + standby, for regulators implementing suspend mode + configuration constraints. What: /sys/class/regulator/.../suspend_mem_state Date: May 2008 KernelVersion: 2.6.26 Contact: Liam Girdwood <lrg@slimlogic.co.uk> Description: - Each regulator directory will contain a field called + Some regulator directories will contain a field called suspend_mem_state. This holds the regulator operating state - when suspended to memory. - - This will be one of the following strings: + when suspended to memory, for regulators implementing suspend + configuration constraints. - 'enabled' - 'disabled' - 'not defined' + This will be one of the same strings reported by + the "state" attribute. What: /sys/class/regulator/.../suspend_disk_state Date: May 2008 KernelVersion: 2.6.26 Contact: Liam Girdwood <lrg@slimlogic.co.uk> Description: - Each regulator directory will contain a field called + Some regulator directories will contain a field called suspend_disk_state. This holds the regulator operating state - when suspended to disk. - - This will be one of the following strings: + when suspended to disk, for regulators implementing + suspend configuration constraints. - 'enabled' - 'disabled' - 'not defined' + This will be one of the same strings reported by + the "state" attribute. What: /sys/class/regulator/.../suspend_standby_state Date: May 2008 KernelVersion: 2.6.26 Contact: Liam Girdwood <lrg@slimlogic.co.uk> Description: - Each regulator directory will contain a field called + Some regulator directories will contain a field called suspend_standby_state. This holds the regulator operating - state when suspended to standby. - - This will be one of the following strings: + state when suspended to standby, for regulators implementing + suspend configuration constraints. - 'enabled' - 'disabled' - 'not defined' + This will be one of the same strings reported by + the "state" attribute. diff --git a/Documentation/DocBook/Makefile b/Documentation/DocBook/Makefile index 0a08126d3094..dc3154e49279 100644 --- a/Documentation/DocBook/Makefile +++ b/Documentation/DocBook/Makefile @@ -12,7 +12,7 @@ DOCBOOKS := z8530book.xml mcabook.xml \ kernel-api.xml filesystems.xml lsm.xml usb.xml kgdb.xml \ gadget.xml libata.xml mtdnand.xml librs.xml rapidio.xml \ genericirq.xml s390-drivers.xml uio-howto.xml scsi.xml \ - mac80211.xml debugobjects.xml sh.xml + mac80211.xml debugobjects.xml sh.xml regulator.xml ### # The build process is as follows (targets): diff --git a/Documentation/DocBook/regulator.tmpl b/Documentation/DocBook/regulator.tmpl new file mode 100644 index 000000000000..53f4f8d3b810 --- /dev/null +++ b/Documentation/DocBook/regulator.tmpl @@ -0,0 +1,304 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!DOCTYPE book PUBLIC "-//OASIS//DTD DocBook XML V4.1.2//EN" + "http://www.oasis-open.org/docbook/xml/4.1.2/docbookx.dtd" []> + +<book id="regulator-api"> + <bookinfo> + <title>Voltage and current regulator API</title> + + <authorgroup> + <author> + <firstname>Liam</firstname> + <surname>Girdwood</surname> + <affiliation> + <address> + <email>lrg@slimlogic.co.uk</email> + </address> + </affiliation> + </author> + <author> + <firstname>Mark</firstname> + <surname>Brown</surname> + <affiliation> + <orgname>Wolfson Microelectronics</orgname> + <address> + <email>broonie@opensource.wolfsonmicro.com</email> + </address> + </affiliation> + </author> + </authorgroup> + + <copyright> + <year>2007-2008</year> + <holder>Wolfson Microelectronics</holder> + </copyright> + <copyright> + <year>2008</year> + <holder>Liam Girdwood</holder> + </copyright> + + <legalnotice> + <para> + This documentation is free software; you can redistribute + it and/or modify it under the terms of the GNU General Public + License version 2 as published by the Free Software Foundation. + </para> + + <para> + This program is distributed in the hope that it will be + useful, but WITHOUT ANY WARRANTY; without even the implied + warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + See the GNU General Public License for more details. + </para> + + <para> + You should have received a copy of the GNU General Public + License along with this program; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, + MA 02111-1307 USA + </para> + + <para> + For more details see the file COPYING in the source + distribution of Linux. + </para> + </legalnotice> + </bookinfo> + +<toc></toc> + + <chapter id="intro"> + <title>Introduction</title> + <para> + This framework is designed to provide a standard kernel + interface to control voltage and current regulators. + </para> + <para> + The intention is to allow systems to dynamically control + regulator power output in order to save power and prolong + battery life. This applies to both voltage regulators (where + voltage output is controllable) and current sinks (where current + limit is controllable). + </para> + <para> + Note that additional (and currently more complete) documentation + is available in the Linux kernel source under + <filename>Documentation/power/regulator</filename>. + </para> + + <sect1 id="glossary"> + <title>Glossary</title> + <para> + The regulator API uses a number of terms which may not be + familiar: + </para> + <glossary> + + <glossentry> + <glossterm>Regulator</glossterm> + <glossdef> + <para> + Electronic device that supplies power to other devices. Most + regulators can enable and disable their output and some can also + control their output voltage or current. + </para> + </glossdef> + </glossentry> + + <glossentry> + <glossterm>Consumer</glossterm> + <glossdef> + <para> + Electronic device which consumes power provided by a regulator. + These may either be static, requiring only a fixed supply, or + dynamic, requiring active management of the regulator at + runtime. + </para> + </glossdef> + </glossentry> + + <glossentry> + <glossterm>Power Domain</glossterm> + <glossdef> + <para> + The electronic circuit supplied by a given regulator, including + the regulator and all consumer devices. The configuration of + the regulator is shared between all the components in the + circuit. + </para> + </glossdef> + </glossentry> + + <glossentry> + <glossterm>Power Management Integrated Circuit</glossterm> + <acronym>PMIC</acronym> + <glossdef> + <para> + An IC which contains numerous regulators and often also other + subsystems. In an embedded system the primary PMIC is often + equivalent to a combination of the PSU and southbridge in a + desktop system. + </para> + </glossdef> + </glossentry> + </glossary> + </sect1> + </chapter> + + <chapter id="consumer"> + <title>Consumer driver interface</title> + <para> + This offers a similar API to the kernel clock framework. + Consumer drivers use <link + linkend='API-regulator-get'>get</link> and <link + linkend='API-regulator-put'>put</link> operations to acquire and + release regulators. Functions are + provided to <link linkend='API-regulator-enable'>enable</link> + and <link linkend='API-regulator-disable'>disable</link> the + reguator and to get and set the runtime parameters of the + regulator. + </para> + <para> + When requesting regulators consumers use symbolic names for their + supplies, such as "Vcc", which are mapped into actual regulator + devices by the machine interface. + </para> + <para> + A stub version of this API is provided when the regulator + framework is not in use in order to minimise the need to use + ifdefs. + </para> + + <sect1 id="consumer-enable"> + <title>Enabling and disabling</title> + <para> + The regulator API provides reference counted enabling and + disabling of regulators. Consumer devices use the <function><link + linkend='API-regulator-enable'>regulator_enable</link></function> + and <function><link + linkend='API-regulator-disable'>regulator_disable</link> + </function> functions to enable and disable regulators. Calls + to the two functions must be balanced. + </para> + <para> + Note that since multiple consumers may be using a regulator and + machine constraints may not allow the regulator to be disabled + there is no guarantee that calling + <function>regulator_disable</function> will actually cause the + supply provided by the regulator to be disabled. Consumer + drivers should assume that the regulator may be enabled at all + times. + </para> + </sect1> + + <sect1 id="consumer-config"> + <title>Configuration</title> + <para> + Some consumer devices may need to be able to dynamically + configure their supplies. For example, MMC drivers may need to + select the correct operating voltage for their cards. This may + be done while the regulator is enabled or disabled. + </para> + <para> + The <function><link + linkend='API-regulator-set-voltage'>regulator_set_voltage</link> + </function> and <function><link + linkend='API-regulator-set-current-limit' + >regulator_set_current_limit</link> + </function> functions provide the primary interface for this. + Both take ranges of voltages and currents, supporting drivers + that do not require a specific value (eg, CPU frequency scaling + normally permits the CPU to use a wider range of supply + voltages at lower frequencies but does not require that the + supply voltage be lowered). Where an exact value is required + both minimum and maximum values should be identical. + </para> + </sect1> + + <sect1 id="consumer-callback"> + <title>Callbacks</title> + <para> + Callbacks may also be <link + linkend='API-regulator-register-notifier'>registered</link> + for events such as regulation failures. + </para> + </sect1> + </chapter> + + <chapter id="driver"> + <title>Regulator driver interface</title> + <para> + Drivers for regulator chips <link + linkend='API-regulator-register'>register</link> the regulators + with the regulator core, providing operations structures to the + core. A <link + linkend='API-regulator-notifier-call-chain'>notifier</link> interface + allows error conditions to be reported to the core. + </para> + <para> + Registration should be triggered by explicit setup done by the + platform, supplying a <link + linkend='API-struct-regulator-init-data'>struct + regulator_init_data</link> for the regulator containing + <link linkend='machine-constraint'>constraint</link> and + <link linkend='machine-supply'>supply</link> information. + </para> + </chapter> + + <chapter id="machine"> + <title>Machine interface</title> + <para> + This interface provides a way to define how regulators are + connected to consumers on a given system and what the valid + operating parameters are for the system. + </para> + + <sect1 id="machine-supply"> + <title>Supplies</title> + <para> + Regulator supplies are specified using <link + linkend='API-struct-regulator-consumer-supply'>struct + regulator_consumer_supply</link>. This is done at + <link linkend='driver'>driver registration + time</link> as part of the machine constraints. + </para> + </sect1> + + <sect1 id="machine-constraint"> + <title>Constraints</title> + <para> + As well as definining the connections the machine interface + also provides constraints definining the operations that + clients are allowed to perform and the parameters that may be + set. This is required since generally regulator devices will + offer more flexibility than it is safe to use on a given + system, for example supporting higher supply voltages than the + consumers are rated for. + </para> + <para> + This is done at <link linkend='driver'>driver + registration time</link> by providing a <link + linkend='API-struct-regulation-constraints'>struct + regulation_constraints</link>. + </para> + <para> + The constraints may also specify an initial configuration for the + regulator in the constraints, which is particularly useful for + use with static consumers. + </para> + </sect1> + </chapter> + + <chapter id="api"> + <title>API reference</title> + <para> + Due to limitations of the kernel documentation framework and the + existing layout of the source code the entire regulator API is + documented here. + </para> +!Iinclude/linux/regulator/consumer.h +!Iinclude/linux/regulator/machine.h +!Iinclude/linux/regulator/driver.h +!Edrivers/regulator/core.c + </chapter> +</book> diff --git a/drivers/Makefile b/drivers/Makefile index e121b66ef082..6326f4dbbdab 100644 --- a/drivers/Makefile +++ b/drivers/Makefile @@ -18,6 +18,9 @@ obj-$(CONFIG_ARM_AMBA) += amba/ obj-$(CONFIG_XEN) += xen/ +# regulators early, since some subsystems rely on them to initialize +obj-$(CONFIG_REGULATOR) += regulator/ + # char/ comes before serial/ etc so that the VT console is the boot-time # default. obj-y += char/ @@ -101,5 +104,4 @@ obj-$(CONFIG_PPC_PS3) += ps3/ obj-$(CONFIG_OF) += of/ obj-$(CONFIG_SSB) += ssb/ obj-$(CONFIG_VIRTIO) += virtio/ -obj-$(CONFIG_REGULATOR) += regulator/ obj-$(CONFIG_STAGING) += staging/ diff --git a/drivers/regulator/core.c b/drivers/regulator/core.c index 02a774424e8d..f511a406fcaa 100644 --- a/drivers/regulator/core.c +++ b/drivers/regulator/core.c @@ -29,7 +29,7 @@ static DEFINE_MUTEX(regulator_list_mutex); static LIST_HEAD(regulator_list); static LIST_HEAD(regulator_map_list); -/** +/* * struct regulator_dev * * Voltage / Current regulator class device. One for each regulator. @@ -56,7 +56,7 @@ struct regulator_dev { void *reg_data; /* regulator_dev data */ }; -/** +/* * struct regulator_map * * Used to provide symbolic supply names to devices. @@ -79,7 +79,7 @@ struct regulator { int uA_load; int min_uV; int max_uV; - int enabled; /* client has called enabled */ + int enabled; /* count of client enables */ char *supply_name; struct device_attribute dev_attr; struct regulator_dev *rdev; @@ -174,6 +174,16 @@ static int regulator_check_current_limit(struct regulator_dev *rdev, /* operating mode constraint check */ static int regulator_check_mode(struct regulator_dev *rdev, int mode) { + switch (mode) { + case REGULATOR_MODE_FAST: + case REGULATOR_MODE_NORMAL: + case REGULATOR_MODE_IDLE: + case REGULATOR_MODE_STANDBY: + break; + default: + return -EINVAL; + } + if (!rdev->constraints) { printk(KERN_ERR "%s: no constraints for %s\n", __func__, rdev->desc->name); @@ -232,6 +242,7 @@ static ssize_t regulator_uV_show(struct device *dev, return ret; } +static DEVICE_ATTR(microvolts, 0444, regulator_uV_show, NULL); static ssize_t regulator_uA_show(struct device *dev, struct device_attribute *attr, char *buf) @@ -240,6 +251,7 @@ static ssize_t regulator_uA_show(struct device *dev, return sprintf(buf, "%d\n", _regulator_get_current_limit(rdev)); } +static DEVICE_ATTR(microamps, 0444, regulator_uA_show, NULL); static ssize_t regulator_name_show(struct device *dev, struct device_attribute *attr, char *buf) @@ -257,12 +269,8 @@ static ssize_t regulator_name_show(struct device *dev, return sprintf(buf, "%s\n", name); } -static ssize_t regulator_opmode_show(struct device *dev, - struct device_attribute *attr, char *buf) +static ssize_t regulator_print_opmode(char *buf, int mode) { - struct regulator_dev *rdev = dev_get_drvdata(dev); - int mode = _regulator_get_mode(rdev); - switch (mode) { case REGULATOR_MODE_FAST: return sprintf(buf, "fast\n"); @@ -276,12 +284,17 @@ static ssize_t regulator_opmode_show(struct device *dev, return sprintf(buf, "unknown\n"); } -static ssize_t regulator_state_show(struct device *dev, - struct device_attribute *attr, char *buf) +static ssize_t regulator_opmode_show(struct device *dev, + struct device_attribute *attr, char *buf) { struct regulator_dev *rdev = dev_get_drvdata(dev); - int state = _regulator_is_enabled(rdev); + return regulator_print_opmode(buf, _regulator_get_mode(rdev)); +} +static DEVICE_ATTR(opmode, 0444, regulator_opmode_show, NULL); + +static ssize_t regulator_print_state(char *buf, int state) +{ if (state > 0) return sprintf(buf, "enabled\n"); else if (state == 0) @@ -290,6 +303,15 @@ static ssize_t regulator_state_show(struct device *dev, return sprintf(buf, "unknown\n"); } +static ssize_t regulator_state_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + struct regulator_dev *rdev = dev_get_drvdata(dev); + + return regulator_print_state(buf, _regulator_is_enabled(rdev)); +} +static DEVICE_ATTR(state, 0444, regulator_state_show, NULL); + static ssize_t regulator_min_uA_show(struct device *dev, struct device_attribute *attr, char *buf) { @@ -300,6 +322,7 @@ static ssize_t regulator_min_uA_show(struct device *dev, return sprintf(buf, "%d\n", rdev->constraints->min_uA); } +static DEVICE_ATTR(min_microamps, 0444, regulator_min_uA_show, NULL); static ssize_t regulator_max_uA_show(struct device *dev, struct device_attribute *attr, char *buf) @@ -311,6 +334,7 @@ static ssize_t regulator_max_uA_show(struct device *dev, return sprintf(buf, "%d\n", rdev->constraints->max_uA); } +static DEVICE_ATTR(max_microamps, 0444, regulator_max_uA_show, NULL); static ssize_t regulator_min_uV_show(struct device *dev, struct device_attribute *attr, char *buf) @@ -322,6 +346,7 @@ static ssize_t regulator_min_uV_show(struct device *dev, return sprintf(buf, "%d\n", rdev->constraints->min_uV); } +static DEVICE_ATTR(min_microvolts, 0444, regulator_min_uV_show, NULL); static ssize_t regulator_max_uV_show(struct device *dev, struct device_attribute *attr, char *buf) @@ -333,6 +358,7 @@ static ssize_t regulator_max_uV_show(struct device *dev, return sprintf(buf, "%d\n", rdev->constraints->max_uV); } +static DEVICE_ATTR(max_microvolts, 0444, regulator_max_uV_show, NULL); static ssize_t regulator_total_uA_show(struct device *dev, struct device_attribute *attr, char *buf) @@ -347,6 +373,7 @@ static ssize_t regulator_total_uA_show(struct device *dev, mutex_unlock(&rdev->mutex); return sprintf(buf, "%d\n", uA); } +static DEVICE_ATTR(requested_microamps, 0444, regulator_total_uA_show, NULL); static ssize_t regulator_num_users_show(struct device *dev, struct device_attribute *attr, char *buf) @@ -374,153 +401,106 @@ static ssize_t regulator_suspend_mem_uV_show(struct device *dev, { struct regulator_dev *rdev = dev_get_drvdata(dev); - if (!rdev->constraints) - return sprintf(buf, "not defined\n"); return sprintf(buf, "%d\n", rdev->constraints->state_mem.uV); } +static DEVICE_ATTR(suspend_mem_microvolts, 0444, + regulator_suspend_mem_uV_show, NULL); static ssize_t regulator_suspend_disk_uV_show(struct device *dev, struct device_attribute *attr, char *buf) { struct regulator_dev *rdev = dev_get_drvdata(dev); - if (!rdev->constraints) - return sprintf(buf, "not defined\n"); return sprintf(buf, "%d\n", rdev->constraints->state_disk.uV); } +static DEVICE_ATTR(suspend_disk_microvolts, 0444, + regulator_suspend_disk_uV_show, NULL); static ssize_t regulator_suspend_standby_uV_show(struct device *dev, struct device_attribute *attr, char *buf) { struct regulator_dev *rdev = dev_get_drvdata(dev); - if (!rdev->constraints) - return sprintf(buf, "not defined\n"); return sprintf(buf, "%d\n", rdev->constraints->state_standby.uV); } - -static ssize_t suspend_opmode_show(struct regulator_dev *rdev, - unsigned int mode, char *buf) -{ - switch (mode) { - case REGULATOR_MODE_FAST: - return sprintf(buf, "fast\n"); - case REGULATOR_MODE_NORMAL: - return sprintf(buf, "normal\n"); - case REGULATOR_MODE_IDLE: - return sprintf(buf, "idle\n"); - case REGULATOR_MODE_STANDBY: - return sprintf(buf, "standby\n"); - } - return sprintf(buf, "unknown\n"); -} +static DEVICE_ATTR(suspend_standby_microvolts, 0444, + regulator_suspend_standby_uV_show, NULL); static ssize_t regulator_suspend_mem_mode_show(struct device *dev, struct device_attribute *attr, char *buf) { struct regulator_dev *rdev = dev_get_drvdata(dev); - if (!rdev->constraints) - return sprintf(buf, "not defined\n"); - return suspend_opmode_show(rdev, - rdev->constraints->state_mem.mode, buf); + return regulator_print_opmode(buf, + rdev->constraints->state_mem.mode); } +static DEVICE_ATTR(suspend_mem_mode, 0444, + regulator_suspend_mem_mode_show, NULL); static ssize_t regulator_suspend_disk_mode_show(struct device *dev, struct device_attribute *attr, char *buf) { struct regulator_dev *rdev = dev_get_drvdata(dev); - if (!rdev->constraints) - return sprintf(buf, "not defined\n"); - return suspend_opmode_show(rdev, - rdev->constraints->state_disk.mode, buf); + return regulator_print_opmode(buf, + rdev->constraints->state_disk.mode); } +static DEVICE_ATTR(suspend_disk_mode, 0444, + regulator_suspend_disk_mode_show, NULL); static ssize_t regulator_suspend_standby_mode_show(struct device *dev, struct device_attribute *attr, char *buf) { struct regulator_dev *rdev = dev_get_drvdata(dev); - if (!rdev->constraints) - return sprintf(buf, "not defined\n"); - return suspend_opmode_show(rdev, - rdev->constraints->state_standby.mode, buf); + return regulator_print_opmode(buf, + rdev->constraints->state_standby.mode); } +static DEVICE_ATTR(suspend_standby_mode, 0444, + regulator_suspend_standby_mode_show, NULL); static ssize_t regulator_suspend_mem_state_show(struct device *dev, struct device_attribute *attr, char *buf) { struct regulator_dev *rdev = dev_get_drvdata(dev); - if (!rdev->constraints) - return sprintf(buf, "not defined\n"); - - if (rdev->constraints->state_mem.enabled) - return sprintf(buf, "enabled\n"); - else - return sprintf(buf, "disabled\n"); + return regulator_print_state(buf, + rdev->constraints->state_mem.enabled); } +static DEVICE_ATTR(suspend_mem_state, 0444, + regulator_suspend_mem_state_show, NULL); static ssize_t regulator_suspend_disk_state_show(struct device *dev, struct device_attribute *attr, char *buf) { struct regulator_dev *rdev = dev_get_drvdata(dev); - if (!rdev->constraints) - return sprintf(buf, "not defined\n"); - - if (rdev->constraints->state_disk.enabled) - return sprintf(buf, "enabled\n"); - else - return sprintf(buf, "disabled\n"); + return regulator_print_state(buf, + rdev->constraints->state_disk.enabled); } +static DEVICE_ATTR(suspend_disk_state, 0444, + regulator_suspend_disk_state_show, NULL); static ssize_t regulator_suspend_standby_state_show(struct device *dev, struct device_attribute *attr, char *buf) { struct regulator_dev *rdev = dev_get_drvdata(dev); - if (!rdev->constraints) - return sprintf(buf, "not defined\n"); - - if (rdev->constraints->state_standby.enabled) - return sprintf(buf, "enabled\n"); - else - return sprintf(buf, "disabled\n"); + return regulator_print_state(buf, + rdev->constraints->state_standby.enabled); } +static DEVICE_ATTR(suspend_standby_state, 0444, + regulator_suspend_standby_state_show, NULL); + +/* + * These are the only attributes are present for all regulators. + * Other attributes are a function of regulator functionality. + */ static struct device_attribute regulator_dev_attrs[] = { __ATTR(name, 0444, regulator_name_show, NULL), - __ATTR(microvolts, 0444, regulator_uV_show, NULL), - __ATTR(microamps, 0444, regulator_uA_show, NULL), - __ATTR(opmode, 0444, regulator_opmode_show, NULL), - __ATTR(state, 0444, regulator_state_show, NULL), - __ATTR(min_microvolts, 0444, regulator_min_uV_show, NULL), - __ATTR(min_microamps, 0444, regulator_min_uA_show, NULL), - __ATTR(max_microvolts, 0444, regulator_max_uV_show, NULL), - __ATTR(max_microamps, 0444, regulator_max_uA_show, NULL), - __ATTR(requested_microamps, 0444, regulator_total_uA_show, NULL), __ATTR(num_users, 0444, regulator_num_users_show, NULL), __ATTR(type, 0444, regulator_type_show, NULL), - __ATTR(suspend_mem_microvolts, 0444, - regulator_suspend_mem_uV_show, NULL), - __ATTR(suspend_disk_microvolts, 0444, - regulator_suspend_disk_uV_show, NULL), - __ATTR(suspend_standby_microvolts, 0444, - regulator_suspend_standby_uV_show, NULL), - __ATTR(suspend_mem_mode, 0444, - regulator_suspend_mem_mode_show, NULL), - __ATTR(suspend_disk_mode, 0444, - regulator_suspend_disk_mode_show, NULL), - __ATTR(suspend_standby_mode, 0444, - regulator_suspend_standby_mode_show, NULL), - __ATTR(suspend_mem_state, 0444, - regulator_suspend_mem_state_show, NULL), - __ATTR(suspend_disk_state, 0444, - regulator_suspend_disk_state_show, NULL), - __ATTR(suspend_standby_state, 0444, - regulator_suspend_standby_state_show, NULL), __ATTR_NULL, }; @@ -675,7 +655,8 @@ static void print_constraints(struct regulator_dev *rdev) /** * set_machine_constraints - sets regulator constraints - * @regulator: regulator source + * @rdev: regulator source + * @constraints: constraints to apply * * Allows platform initialisation code to define and constrain * regulator circuits e.g. valid voltage/current ranges, etc. NOTE: @@ -750,8 +731,8 @@ out: /** * set_supply - set regulator supply regulator - * @regulator: regulator name - * @supply: supply regulator name + * @rdev: regulator name + * @supply_rdev: supply regulator name * * Called by platform initialisation code to set the supply regulator for this * regulator. This ensures that a regulators supply will also be enabled by the @@ -778,9 +759,9 @@ out: /** * set_consumer_device_supply: Bind a regulator to a symbolic supply - * @regulator: regulator source - * @dev: device the supply applies to - * @supply: symbolic name for supply + * @rdev: regulator source + * @consumer_dev: device the supply applies to + * @supply: symbolic name for supply * * Allows platform initialisation code to map physical regulator * sources to symbolic names for supplies for use by devices. Devices @@ -795,6 +776,20 @@ static int set_consumer_device_supply(struct regulator_dev *rdev, if (supply == NULL) return -EINVAL; + list_for_each_entry(node, ®ulator_map_list, list) { + if (consumer_dev != node->dev) + continue; + if (strcmp(node->supply, supply) != 0) + continue; + + dev_dbg(consumer_dev, "%s/%s is '%s' supply; fail %s/%s\n", + dev_name(&node->regulator->dev), + node->regulator->desc->name, + supply, + dev_name(&rdev->dev), rdev->desc->name); + return -EBUSY; + } + node = kmalloc(sizeof(struct regulator_map), GFP_KERNEL); if (node == NULL) return -ENOMEM; @@ -963,16 +958,13 @@ void regulator_put(struct regulator *regulator) if (regulator == NULL || IS_ERR(regulator)) return; - if (regulator->enabled) { - printk(KERN_WARNING "Releasing supply %s while enabled\n", - regulator->supply_name); - WARN_ON(regulator->enabled); - regulator_disable(regulator); - } - mutex_lock(®ulator_list_mutex); rdev = regulator->rdev; + if (WARN(regulator->enabled, "Releasing supply %s while enabled\n", + regulator->supply_name)) + _regulator_disable(rdev); + /* remove any sysfs entries */ if (regulator->dev) { sysfs_remove_link(&rdev->dev.kobj, regulator->supply_name); @@ -1034,29 +1026,26 @@ static int _regulator_enable(struct regulator_dev *rdev) * regulator_enable - enable regulator output * @regulator: regulator source * - * Enable the regulator output at the predefined voltage or current value. + * Request that the regulator be enabled with the regulator output at + * the predefined voltage or current value. Calls to regulator_enable() + * must be balanced with calls to regulator_disable(). + * * NOTE: the output value can be set by other drivers, boot loader or may be * hardwired in the regulator. - * NOTE: calls to regulator_enable() must be balanced with calls to - * regulator_disable(). */ int regulator_enable(struct regulator *regulator) { - int ret; - - if (regulator->enabled) { - printk(KERN_CRIT "Regulator %s already enabled\n", - regulator->supply_name); - WARN_ON(regulator->enabled); - return 0; - } + struct regulator_dev *rdev = regulator->rdev; + int ret = 0; - mutex_lock(®ulator->rdev->mutex); - regulator->enabled = 1; - ret = _regulator_enable(regulator->rdev); - if (ret != 0) - regulator->enabled = 0; - mutex_unlock(®ulator->rdev->mutex); + mutex_lock(&rdev->mutex); + if (regulator->enabled == 0) + ret = _regulator_enable(rdev); + else if (regulator->enabled < 0) + ret = -EIO; + if (ret == 0) + regulator->enabled++; + mutex_unlock(&rdev->mutex); return ret; } EXPORT_SYMBOL_GPL(regulator_enable); @@ -1100,27 +1089,31 @@ static int _regulator_disable(struct regulator_dev *rdev) * regulator_disable - disable regulator output * @regulator: regulator source * - * Disable the regulator output voltage or current. - * NOTE: this will only disable the regulator output if no other consumer - * devices have it enabled. - * NOTE: calls to regulator_enable() must be balanced with calls to + * Disable the regulator output voltage or current. Calls to + * regulator_enable() must be balanced with calls to * regulator_disable(). + * + * NOTE: this will only disable the regulator output if no other consumer + * devices have it enabled, the regulator device supports disabling and + * machine constraints permit this operation. */ int regulator_disable(struct regulator *regulator) { - int ret; - - if (!regulator->enabled) { - printk(KERN_ERR "%s: not in use by this consumer\n", - __func__); - return 0; - } + struct regulator_dev *rdev = regulator->rdev; + int ret = 0; - mutex_lock(®ulator->rdev->mutex); - regulator->enabled = 0; - regulator->uA_load = 0; - ret = _regulator_disable(regulator->rdev); - mutex_unlock(®ulator->rdev->mutex); + mutex_lock(&rdev->mutex); + if (regulator->enabled == 1) { + ret = _regulator_disable(rdev); + if (ret == 0) + regulator->uA_load = 0; + } else if (WARN(regulator->enabled <= 0, + "unbalanced disables for supply %s\n", + regulator->supply_name)) + ret = -EIO; + if (ret == 0) + regulator->enabled--; + mutex_unlock(&rdev->mutex); return ret; } EXPORT_SYMBOL_GPL(regulator_disable); @@ -1196,7 +1189,13 @@ out: * regulator_is_enabled - is the regulator output enabled * @regulator: regulator source * - * Returns zero for disabled otherwise return number of enable requests. + * Returns positive if the regulator driver backing the source/client + * has requested that the device be enabled, zero if it hasn't, else a + * negative errno code. + * + * Note that the device backing this regulator handle can have multiple + * users, so it might be enabled even if regulator_enable() was never + * called for this particular source. */ int regulator_is_enabled(struct regulator *regulator) { @@ -1219,7 +1218,7 @@ EXPORT_SYMBOL_GPL(regulator_is_enabled); * * NOTE: If the regulator is shared between several devices then the lowest * request voltage that meets the system constraints will be used. - * NOTE: Regulator system constraints must be set for this regulator before + * Regulator system constraints must be set for this regulator before * calling this function otherwise this call will fail. */ int regulator_set_voltage(struct regulator *regulator, int min_uV, int max_uV) @@ -1493,7 +1492,8 @@ int regulator_set_optimum_mode(struct regulator *regulator, int uA_load) mode = rdev->desc->ops->get_optimum_mode(rdev, input_uV, output_uV, total_uA_load); - if (ret <= 0) { + ret = regulator_check_mode(rdev, mode); + if (ret < 0) { printk(KERN_ERR "%s: failed to get optimum mode for %s @" " %d uA %d -> %d uV\n", __func__, rdev->desc->name, total_uA_load, input_uV, output_uV); @@ -1501,7 +1501,7 @@ int regulator_set_optimum_mode(struct regulator *regulator, int uA_load) } ret = rdev->desc->ops->set_mode(rdev, mode); - if (ret <= 0) { + if (ret < 0) { printk(KERN_ERR "%s: failed to set optimum mode %x for %s\n", __func__, mode, rdev->desc->name); goto out; @@ -1516,7 +1516,7 @@ EXPORT_SYMBOL_GPL(regulator_set_optimum_mode); /** * regulator_register_notifier - register regulator event notifier * @regulator: regulator source - * @notifier_block: notifier block + * @nb: notifier block * * Register notifier block to receive regulator events. */ @@ -1531,7 +1531,7 @@ EXPORT_SYMBOL_GPL(regulator_register_notifier); /** * regulator_unregister_notifier - unregister regulator event notifier * @regulator: regulator source - * @notifier_block: notifier block + * @nb: notifier block * * Unregister regulator event notifier block. */ @@ -1697,9 +1697,9 @@ EXPORT_SYMBOL_GPL(regulator_bulk_free); /** * regulator_notifier_call_chain - call regulator event notifier - * @regulator: regulator source + * @rdev: regulator source * @event: notifier block - * @data: + * @data: callback-specific data. * * Called by regulator drivers to notify clients a regulator event has * occurred. We also notify regulator clients downstream. @@ -1713,10 +1713,122 @@ int regulator_notifier_call_chain(struct regulator_dev *rdev, } EXPORT_SYMBOL_GPL(regulator_notifier_call_chain); +/* + * To avoid cluttering sysfs (and memory) with useless state, only + * create attributes that can be meaningfully displayed. + */ +static int add_regulator_attributes(struct regulator_dev *rdev) +{ + struct device *dev = &rdev->dev; + struct regulator_ops *ops = rdev->desc->ops; + int status = 0; + + /* some attributes need specific methods to be displayed */ + if (ops->get_voltage) { + status = device_create_file(dev, &dev_attr_microvolts); + if (status < 0) + return status; + } + if (ops->get_current_limit) { + status = device_create_file(dev, &dev_attr_microamps); + if (status < 0) + return status; + } + if (ops->get_mode) { + status = device_create_file(dev, &dev_attr_opmode); + if (status < 0) + return status; + } + if (ops->is_enabled) { + status = device_create_file(dev, &dev_attr_state); + if (status < 0) + return status; + } + + /* some attributes are type-specific */ + if (rdev->desc->type == REGULATOR_CURRENT) { + status = device_create_file(dev, &dev_attr_requested_microamps); + if (status < 0) + return status; + } + + /* all the other attributes exist to support constraints; + * don't show them if there are no constraints, or if the + * relevant supporting methods are missing. + */ + if (!rdev->constraints) + return status; + + /* constraints need specific supporting methods */ + if (ops->set_voltage) { + status = device_create_file(dev, &dev_attr_min_microvolts); + if (status < 0) + return status; + status = device_create_file(dev, &dev_attr_max_microvolts); + if (status < 0) + return status; + } + if (ops->set_current_limit) { + status = device_create_file(dev, &dev_attr_min_microamps); + if (status < 0) + return status; + status = device_create_file(dev, &dev_attr_max_microamps); + if (status < 0) + return status; + } + + /* suspend mode constraints need multiple supporting methods */ + if (!(ops->set_suspend_enable && ops->set_suspend_disable)) + return status; + + status = device_create_file(dev, &dev_attr_suspend_standby_state); + if (status < 0) + return status; + status = device_create_file(dev, &dev_attr_suspend_mem_state); + if (status < 0) + return status; + status = device_create_file(dev, &dev_attr_suspend_disk_state); + if (status < 0) + return status; + + if (ops->set_suspend_voltage) { + status = device_create_file(dev, + &dev_attr_suspend_standby_microvolts); + if (status < 0) + return status; + status = device_create_file(dev, + &dev_attr_suspend_mem_microvolts); + if (status < 0) + return status; + status = device_create_file(dev, + &dev_attr_suspend_disk_microvolts); + if (status < 0) + return status; + } + + if (ops->set_suspend_mode) { + status = device_create_file(dev, + &dev_attr_suspend_standby_mode); + if (status < 0) + return status; + status = device_create_file(dev, + &dev_attr_suspend_mem_mode); + if (status < 0) + return status; + status = device_create_file(dev, + &dev_attr_suspend_disk_mode); + if (status < 0) + return status; + } + + return status; +} + /** * regulator_register - register regulator - * @regulator: regulator source - * @reg_data: private regulator data + * @regulator_desc: regulator to register + * @dev: struct device for the regulator + * @driver_data: private regulator data * * Called by regulator drivers to register a regulator. * Returns 0 on success. @@ -1761,45 +1873,37 @@ struct regulator_dev *regulator_register(struct regulator_desc *regulator_desc, /* preform any regulator specific init */ if (init_data->regulator_init) { ret = init_data->regulator_init(rdev->reg_data); - if (ret < 0) { - kfree(rdev); - rdev = ERR_PTR(ret); - goto out; - } - } - - /* set regulator constraints */ - ret = set_machine_constraints(rdev, &init_data->constraints); - if (ret < 0) { - kfree(rdev); - rdev = ERR_PTR(ret); - goto out; + if (ret < 0) + goto clean; } /* register with sysfs */ rdev->dev.class = ®ulator_class; rdev->dev.parent = dev; - snprintf(rdev->dev.bus_id, sizeof(rdev->dev.bus_id), - "regulator.%d", atomic_inc_return(®ulator_no) - 1); + dev_set_name(&rdev->dev, "regulator.%d", + atomic_inc_return(®ulator_no) - 1); ret = device_register(&rdev->dev); - if (ret != 0) { - kfree(rdev); - rdev = ERR_PTR(ret); - goto out; - } + if (ret != 0) + goto clean; dev_set_drvdata(&rdev->dev, rdev); + /* set regulator constraints */ + ret = set_machine_constraints(rdev, &init_data->constraints); + if (ret < 0) + goto scrub; + + /* add attributes supported by this regulator */ + ret = add_regulator_attributes(rdev); + if (ret < 0) + goto scrub; + /* set supply regulator if it exists */ if (init_data->supply_regulator_dev) { ret = set_supply(rdev, dev_get_drvdata(init_data->supply_regulator_dev)); - if (ret < 0) { - device_unregister(&rdev->dev); - kfree(rdev); - rdev = ERR_PTR(ret); - goto out; - } + if (ret < 0) + goto scrub; } /* add consumers devices */ @@ -1811,10 +1915,7 @@ struct regulator_dev *regulator_register(struct regulator_desc *regulator_desc, for (--i; i >= 0; i--) unset_consumer_device_supply(rdev, init_data->consumer_supplies[i].dev); - device_unregister(&rdev->dev); - kfree(rdev); - rdev = ERR_PTR(ret); - goto out; + goto scrub; } } @@ -1822,12 +1923,19 @@ struct regulator_dev *regulator_register(struct regulator_desc *regulator_desc, out: mutex_unlock(®ulator_list_mutex); return rdev; + +scrub: + device_unregister(&rdev->dev); +clean: + kfree(rdev); + rdev = ERR_PTR(ret); + goto out; } EXPORT_SYMBOL_GPL(regulator_register); /** * regulator_unregister - unregister regulator - * @regulator: regulator source + * @rdev: regulator to unregister * * Called by regulator drivers to unregister a regulator. */ @@ -1846,7 +1954,7 @@ void regulator_unregister(struct regulator_dev *rdev) EXPORT_SYMBOL_GPL(regulator_unregister); /** - * regulator_suspend_prepare: prepare regulators for system wide suspend + * regulator_suspend_prepare - prepare regulators for system wide suspend * @state: system suspend state * * Configure each regulator with it's suspend operating parameters for state. @@ -1882,7 +1990,7 @@ EXPORT_SYMBOL_GPL(regulator_suspend_prepare); /** * rdev_get_drvdata - get rdev regulator driver data - * @regulator: regulator + * @rdev: regulator * * Get rdev regulator driver private data. This call can be used in the * regulator driver context. @@ -1919,7 +2027,7 @@ EXPORT_SYMBOL_GPL(regulator_set_drvdata); /** * regulator_get_id - get regulator ID - * @regulator: regulator + * @rdev: regulator */ int rdev_get_id(struct regulator_dev *rdev) { diff --git a/drivers/regulator/da903x.c b/drivers/regulator/da903x.c index 773b29cec8be..fe77730a7edb 100644 --- a/drivers/regulator/da903x.c +++ b/drivers/regulator/da903x.c @@ -102,7 +102,7 @@ static int da903x_set_ldo_voltage(struct regulator_dev *rdev, uint8_t val, mask; if (check_range(info, min_uV, max_uV)) { - pr_err("invalid voltage range (%d, %d) uV", min_uV, max_uV); + pr_err("invalid voltage range (%d, %d) uV\n", min_uV, max_uV); return -EINVAL; } @@ -159,7 +159,7 @@ static int da903x_is_enabled(struct regulator_dev *rdev) if (ret) return ret; - return reg_val & (1 << info->enable_bit); + return !!(reg_val & (1 << info->enable_bit)); } /* DA9030 specific operations */ @@ -172,7 +172,7 @@ static int da9030_set_ldo1_15_voltage(struct regulator_dev *rdev, int ret; if (check_range(info, min_uV, max_uV)) { - pr_err("invalid voltage range (%d, %d) uV", min_uV, max_uV); + pr_err("invalid voltage range (%d, %d) uV\n", min_uV, max_uV); return -EINVAL; } @@ -199,7 +199,7 @@ static int da9030_set_ldo14_voltage(struct regulator_dev *rdev, int thresh; if (check_range(info, min_uV, max_uV)) { - pr_err("invalid voltage range (%d, %d) uV", min_uV, max_uV); + pr_err("invalid voltage range (%d, %d) uV\n", min_uV, max_uV); return -EINVAL; } @@ -248,7 +248,7 @@ static int da9034_set_dvc_voltage(struct regulator_dev *rdev, int ret; if (check_range(info, min_uV, max_uV)) { - pr_err("invalid voltage range (%d, %d) uV", min_uV, max_uV); + pr_err("invalid voltage range (%d, %d) uV\n", min_uV, max_uV); return -EINVAL; } @@ -273,7 +273,7 @@ static int da9034_set_ldo12_voltage(struct regulator_dev *rdev, uint8_t val, mask; if (check_range(info, min_uV, max_uV)) { - pr_err("invalid voltage range (%d, %d) uV", min_uV, max_uV); + pr_err("invalid voltage range (%d, %d) uV\n", min_uV, max_uV); return -EINVAL; } diff --git a/include/linux/regulator/consumer.h b/include/linux/regulator/consumer.h index afdc4558bb94..801bf77ff4e2 100644 --- a/include/linux/regulator/consumer.h +++ b/include/linux/regulator/consumer.h @@ -104,10 +104,10 @@ struct regulator; /** * struct regulator_bulk_data - Data used for bulk regulator operations. * - * @supply The name of the supply. Initialised by the user before - * using the bulk regulator APIs. - * @consumer The regulator consumer for the supply. This will be managed - * by the bulk API. + * @supply: The name of the supply. Initialised by the user before + * using the bulk regulator APIs. + * @consumer: The regulator consumer for the supply. This will be managed + * by the bulk API. * * The regulator APIs provide a series of regulator_bulk_() API calls as * a convenience to consumers which require multiple supplies. This diff --git a/include/linux/regulator/driver.h b/include/linux/regulator/driver.h index e37d80561985..2dae05705f13 100644 --- a/include/linux/regulator/driver.h +++ b/include/linux/regulator/driver.h @@ -24,7 +24,33 @@ struct regulator_init_data; /** * struct regulator_ops - regulator operations. * - * This struct describes regulator operations. + * This struct describes regulator operations which can be implemented by + * regulator chip drivers. + * + * @enable: Enable the regulator. + * @disable: Disable the regulator. + * @is_enabled: Return 1 if the regulator is enabled, 0 otherwise. + * + * @set_voltage: Set the voltage for the regulator within the range specified. + * The driver should select the voltage closest to min_uV. + * @get_voltage: Return the currently configured voltage for the regulator. + * + * @set_current_limit: Configure a limit for a current-limited regulator. + * @get_current_limit: Get the limit for a current-limited regulator. + * + * @set_mode: Set the operating mode for the regulator. + * @get_mode: Get the current operating mode for the regulator. + * @get_optimum_mode: Get the most efficient operating mode for the regulator + * when running with the specified parameters. + * + * @set_suspend_voltage: Set the voltage for the regulator when the system + * is suspended. + * @set_suspend_enable: Mark the regulator as enabled when the system is + * suspended. + * @set_suspend_disable: Mark the regulator as disabled when the system is + * suspended. + * @set_suspend_mode: Set the operating mode for the regulator when the + * system is suspended. */ struct regulator_ops { @@ -75,6 +101,15 @@ enum regulator_type { /** * struct regulator_desc - Regulator descriptor * + * Each regulator registered with the core is described with a structure of + * this type. + * + * @name: Identifying name for the regulator. + * @id: Numerical identifier for the regulator. + * @ops: Regulator operations table. + * @irq: Interrupt number for the regulator. + * @type: Indicates if the regulator is a voltage or current regulator. + * @owner: Module providing the regulator, used for refcounting. */ struct regulator_desc { const char *name; diff --git a/include/linux/regulator/machine.h b/include/linux/regulator/machine.h index c6d69331a81e..3794773b23d2 100644 --- a/include/linux/regulator/machine.h +++ b/include/linux/regulator/machine.h @@ -44,6 +44,10 @@ struct regulator; * struct regulator_state - regulator state during low power syatem states * * This describes a regulators state during a system wide low power state. + * + * @uV: Operating voltage during suspend. + * @mode: Operating mode during suspend. + * @enabled: Enabled during suspend. */ struct regulator_state { int uV; /* suspend voltage */ @@ -55,6 +59,30 @@ struct regulator_state { * struct regulation_constraints - regulator operating constraints. * * This struct describes regulator and board/machine specific constraints. + * + * @name: Descriptive name for the constraints, used for display purposes. + * + * @min_uV: Smallest voltage consumers may set. + * @max_uV: Largest voltage consumers may set. + * + * @min_uA: Smallest consumers consumers may set. + * @max_uA: Largest current consumers may set. + * + * @valid_modes_mask: Mask of modes which may be configured by consumers. + * @valid_ops_mask: Operations which may be performed by consumers. + * + * @always_on: Set if the regulator should never be disabled. + * @boot_on: Set if the regulator is enabled when the system is initially + * started. + * @apply_uV: Apply the voltage constraint when initialising. + * + * @input_uV: Input voltage for regulator when supplied by another regulator. + * + * @state_disk: State for regulator when system is suspended in disk mode. + * @state_mem: State for regulator when system is suspended in mem mode. + * @state_standby: State for regulator when system is suspended in standby + * mode. + * @initial_state: Suspend state to set by default. */ struct regulation_constraints { @@ -93,6 +121,9 @@ struct regulation_constraints { * struct regulator_consumer_supply - supply -> device mapping * * This maps a supply name to a device. + * + * @dev: Device structure for the consumer. + * @supply: Name for the supply. */ struct regulator_consumer_supply { struct device *dev; /* consumer */ @@ -103,6 +134,16 @@ struct regulator_consumer_supply { * struct regulator_init_data - regulator platform initialisation data. * * Initialisation constraints, our supply and consumers supplies. + * + * @supply_regulator_dev: Parent regulator (if any). + * + * @constraints: Constraints. These must be specified for the regulator to + * be usable. + * @num_consumer_supplies: Number of consumer device supplies. + * @consumer_supplies: Consumer device supply configuration. + * + * @regulator_init: Callback invoked when the regulator has been registered. + * @driver_data: Data passed to regulator_init. */ struct regulator_init_data { struct device *supply_regulator_dev; /* or NULL for LINE */ |