Merge remote-tracking branch 'regulator/topic/88pm800' into regulator-next

This commit is contained in:
Mark Brown 2013-09-01 13:50:04 +01:00
commit 28c37c9ce8
9 changed files with 737 additions and 280 deletions

View file

@ -0,0 +1,38 @@
Marvell 88PM800 regulator
Required properties:
- compatible: "marvell,88pm800"
- reg: I2C slave address
- regulators: A node that houses a sub-node for each regulator within the
device. Each sub-node is identified using the node's name (or the deprecated
regulator-compatible property if present), with valid values listed below.
The content of each sub-node is defined by the standard binding for
regulators; see regulator.txt.
The valid names for regulators are:
buck1, buck2, buck3, buck4, buck5, ldo1, ldo2, ldo3, ldo4, ldo5, ldo6, ldo7,
ldo8, ldo9, ldo10, ldo11, ldo12, ldo13, ldo14, ldo15, ldo16, ldo17, ldo18, ldo19
Example:
pmic: 88pm800@31 {
compatible = "marvell,88pm800";
reg = <0x31>;
regulators {
buck1 {
regulator-min-microvolt = <600000>;
regulator-max-microvolt = <3950000>;
regulator-boot-on;
regulator-always-on;
};
ldo1 {
regulator-min-microvolt = <600000>;
regulator-max-microvolt = <15000000>;
regulator-boot-on;
regulator-always-on;
};
...
};
};

383
drivers/regulator/88pm800.c Normal file
View file

@ -0,0 +1,383 @@
/*
* Regulators driver for Marvell 88PM800
*
* Copyright (C) 2012 Marvell International Ltd.
* Joseph(Yossi) Hanin <yhanin@marvell.com>
* Yi Zhang <yizhang@marvell.com>
*
* This program 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.
*/
#include <linux/module.h>
#include <linux/moduleparam.h>
#include <linux/init.h>
#include <linux/err.h>
#include <linux/regmap.h>
#include <linux/regulator/driver.h>
#include <linux/regulator/machine.h>
#include <linux/mfd/88pm80x.h>
#include <linux/delay.h>
#include <linux/io.h>
#include <linux/of.h>
#include <linux/regulator/of_regulator.h>
/* LDO1 with DVC[0..3] */
#define PM800_LDO1_VOUT (0x08) /* VOUT1 */
#define PM800_LDO1_VOUT_2 (0x09)
#define PM800_LDO1_VOUT_3 (0x0A)
#define PM800_LDO2_VOUT (0x0B)
#define PM800_LDO3_VOUT (0x0C)
#define PM800_LDO4_VOUT (0x0D)
#define PM800_LDO5_VOUT (0x0E)
#define PM800_LDO6_VOUT (0x0F)
#define PM800_LDO7_VOUT (0x10)
#define PM800_LDO8_VOUT (0x11)
#define PM800_LDO9_VOUT (0x12)
#define PM800_LDO10_VOUT (0x13)
#define PM800_LDO11_VOUT (0x14)
#define PM800_LDO12_VOUT (0x15)
#define PM800_LDO13_VOUT (0x16)
#define PM800_LDO14_VOUT (0x17)
#define PM800_LDO15_VOUT (0x18)
#define PM800_LDO16_VOUT (0x19)
#define PM800_LDO17_VOUT (0x1A)
#define PM800_LDO18_VOUT (0x1B)
#define PM800_LDO19_VOUT (0x1C)
/* BUCK1 with DVC[0..3] */
#define PM800_BUCK1 (0x3C)
#define PM800_BUCK1_1 (0x3D)
#define PM800_BUCK1_2 (0x3E)
#define PM800_BUCK1_3 (0x3F)
#define PM800_BUCK2 (0x40)
#define PM800_BUCK3 (0x41)
#define PM800_BUCK3 (0x41)
#define PM800_BUCK4 (0x42)
#define PM800_BUCK4_1 (0x43)
#define PM800_BUCK4_2 (0x44)
#define PM800_BUCK4_3 (0x45)
#define PM800_BUCK5 (0x46)
#define PM800_BUCK_ENA (0x50)
#define PM800_LDO_ENA1_1 (0x51)
#define PM800_LDO_ENA1_2 (0x52)
#define PM800_LDO_ENA1_3 (0x53)
#define PM800_LDO_ENA2_1 (0x56)
#define PM800_LDO_ENA2_2 (0x57)
#define PM800_LDO_ENA2_3 (0x58)
#define PM800_BUCK1_MISC1 (0x78)
#define PM800_BUCK3_MISC1 (0x7E)
#define PM800_BUCK4_MISC1 (0x81)
#define PM800_BUCK5_MISC1 (0x84)
struct pm800_regulator_info {
struct regulator_desc desc;
int max_ua;
};
struct pm800_regulators {
struct regulator_dev *regulators[PM800_ID_RG_MAX];
struct pm80x_chip *chip;
struct regmap *map;
};
/*
* vreg - the buck regs string.
* ereg - the string for the enable register.
* ebit - the bit number in the enable register.
* amax - the current
* Buck has 2 kinds of voltage steps. It is easy to find voltage by ranges,
* not the constant voltage table.
* n_volt - Number of available selectors
*/
#define PM800_BUCK(vreg, ereg, ebit, amax, volt_ranges, n_volt) \
{ \
.desc = { \
.name = #vreg, \
.ops = &pm800_volt_range_ops, \
.type = REGULATOR_VOLTAGE, \
.id = PM800_ID_##vreg, \
.owner = THIS_MODULE, \
.n_voltages = n_volt, \
.linear_ranges = volt_ranges, \
.n_linear_ranges = ARRAY_SIZE(volt_ranges), \
.vsel_reg = PM800_##vreg, \
.vsel_mask = 0x7f, \
.enable_reg = PM800_##ereg, \
.enable_mask = 1 << (ebit), \
}, \
.max_ua = (amax), \
}
/*
* vreg - the LDO regs string
* ereg - the string for the enable register.
* ebit - the bit number in the enable register.
* amax - the current
* volt_table - the LDO voltage table
* For all the LDOes, there are too many ranges. Using volt_table will be
* simpler and faster.
*/
#define PM800_LDO(vreg, ereg, ebit, amax, ldo_volt_table) \
{ \
.desc = { \
.name = #vreg, \
.ops = &pm800_volt_table_ops, \
.type = REGULATOR_VOLTAGE, \
.id = PM800_ID_##vreg, \
.owner = THIS_MODULE, \
.n_voltages = ARRAY_SIZE(ldo_volt_table), \
.vsel_reg = PM800_##vreg##_VOUT, \
.vsel_mask = 0x1f, \
.enable_reg = PM800_##ereg, \
.enable_mask = 1 << (ebit), \
.volt_table = ldo_volt_table, \
}, \
.max_ua = (amax), \
}
/* Ranges are sorted in ascending order. */
static const struct regulator_linear_range buck1_volt_range[] = {
{ .min_uV = 600000, .max_uV = 1587500, .min_sel = 0, .max_sel = 0x4f,
.uV_step = 12500 },
{ .min_uV = 1600000, .max_uV = 1800000, .min_sel = 0x50,
.max_sel = 0x54, .uV_step = 50000 },
};
/* BUCK 2~5 have same ranges. */
static const struct regulator_linear_range buck2_5_volt_range[] = {
{ .min_uV = 600000, .max_uV = 1587500, .min_sel = 0, .max_sel = 0x4f,
.uV_step = 12500 },
{ .min_uV = 1600000, .max_uV = 3300000, .min_sel = 0x50,
.max_sel = 0x72, .uV_step = 50000 },
};
static const unsigned int ldo1_volt_table[] = {
600000, 650000, 700000, 750000, 800000, 850000, 900000, 950000,
1000000, 1050000, 1100000, 1150000, 1200000, 1300000, 1400000, 1500000,
};
static const unsigned int ldo2_volt_table[] = {
1700000, 1800000, 1900000, 2000000, 2100000, 2500000, 2700000, 2800000,
};
/* LDO 3~17 have same voltage table. */
static const unsigned int ldo3_17_volt_table[] = {
1200000, 1250000, 1700000, 1800000, 1850000, 1900000, 2500000, 2600000,
2700000, 2750000, 2800000, 2850000, 2900000, 3000000, 3100000, 3300000,
};
/* LDO 18~19 have same voltage table. */
static const unsigned int ldo18_19_volt_table[] = {
1700000, 1800000, 1900000, 2500000, 2800000, 2900000, 3100000, 3300000,
};
static int pm800_get_current_limit(struct regulator_dev *rdev)
{
struct pm800_regulator_info *info = rdev_get_drvdata(rdev);
return info->max_ua;
}
static struct regulator_ops pm800_volt_range_ops = {
.list_voltage = regulator_list_voltage_linear_range,
.map_voltage = regulator_map_voltage_linear_range,
.set_voltage_sel = regulator_set_voltage_sel_regmap,
.get_voltage_sel = regulator_get_voltage_sel_regmap,
.enable = regulator_enable_regmap,
.disable = regulator_disable_regmap,
.is_enabled = regulator_is_enabled_regmap,
.get_current_limit = pm800_get_current_limit,
};
static struct regulator_ops pm800_volt_table_ops = {
.list_voltage = regulator_list_voltage_table,
.map_voltage = regulator_map_voltage_iterate,
.set_voltage_sel = regulator_set_voltage_sel_regmap,
.get_voltage_sel = regulator_get_voltage_sel_regmap,
.enable = regulator_enable_regmap,
.disable = regulator_disable_regmap,
.is_enabled = regulator_is_enabled_regmap,
.get_current_limit = pm800_get_current_limit,
};
/* The array is indexed by id(PM800_ID_XXX) */
static struct pm800_regulator_info pm800_regulator_info[] = {
PM800_BUCK(BUCK1, BUCK_ENA, 0, 3000000, buck1_volt_range, 0x55),
PM800_BUCK(BUCK2, BUCK_ENA, 1, 1200000, buck2_5_volt_range, 0x73),
PM800_BUCK(BUCK3, BUCK_ENA, 2, 1200000, buck2_5_volt_range, 0x73),
PM800_BUCK(BUCK4, BUCK_ENA, 3, 1200000, buck2_5_volt_range, 0x73),
PM800_BUCK(BUCK5, BUCK_ENA, 4, 1200000, buck2_5_volt_range, 0x73),
PM800_LDO(LDO1, LDO_ENA1_1, 0, 200000, ldo1_volt_table),
PM800_LDO(LDO2, LDO_ENA1_1, 1, 10000, ldo2_volt_table),
PM800_LDO(LDO3, LDO_ENA1_1, 2, 300000, ldo3_17_volt_table),
PM800_LDO(LDO4, LDO_ENA1_1, 3, 300000, ldo3_17_volt_table),
PM800_LDO(LDO5, LDO_ENA1_1, 4, 300000, ldo3_17_volt_table),
PM800_LDO(LDO6, LDO_ENA1_1, 5, 300000, ldo3_17_volt_table),
PM800_LDO(LDO7, LDO_ENA1_1, 6, 300000, ldo3_17_volt_table),
PM800_LDO(LDO8, LDO_ENA1_1, 7, 300000, ldo3_17_volt_table),
PM800_LDO(LDO9, LDO_ENA1_2, 0, 300000, ldo3_17_volt_table),
PM800_LDO(LDO10, LDO_ENA1_2, 1, 300000, ldo3_17_volt_table),
PM800_LDO(LDO11, LDO_ENA1_2, 2, 300000, ldo3_17_volt_table),
PM800_LDO(LDO12, LDO_ENA1_2, 3, 300000, ldo3_17_volt_table),
PM800_LDO(LDO13, LDO_ENA1_2, 4, 300000, ldo3_17_volt_table),
PM800_LDO(LDO14, LDO_ENA1_2, 5, 300000, ldo3_17_volt_table),
PM800_LDO(LDO15, LDO_ENA1_2, 6, 300000, ldo3_17_volt_table),
PM800_LDO(LDO16, LDO_ENA1_2, 7, 300000, ldo3_17_volt_table),
PM800_LDO(LDO17, LDO_ENA1_3, 0, 300000, ldo3_17_volt_table),
PM800_LDO(LDO18, LDO_ENA1_3, 1, 200000, ldo18_19_volt_table),
PM800_LDO(LDO19, LDO_ENA1_3, 2, 200000, ldo18_19_volt_table),
};
#define PM800_REGULATOR_OF_MATCH(_name, _id) \
[PM800_ID_##_id] = { \
.name = #_name, \
.driver_data = &pm800_regulator_info[PM800_ID_##_id], \
}
static struct of_regulator_match pm800_regulator_matches[] = {
PM800_REGULATOR_OF_MATCH(buck1, BUCK1),
PM800_REGULATOR_OF_MATCH(buck2, BUCK2),
PM800_REGULATOR_OF_MATCH(buck3, BUCK3),
PM800_REGULATOR_OF_MATCH(buck4, BUCK4),
PM800_REGULATOR_OF_MATCH(buck5, BUCK5),
PM800_REGULATOR_OF_MATCH(ldo1, LDO1),
PM800_REGULATOR_OF_MATCH(ldo2, LDO2),
PM800_REGULATOR_OF_MATCH(ldo3, LDO3),
PM800_REGULATOR_OF_MATCH(ldo4, LDO4),
PM800_REGULATOR_OF_MATCH(ldo5, LDO5),
PM800_REGULATOR_OF_MATCH(ldo6, LDO6),
PM800_REGULATOR_OF_MATCH(ldo7, LDO7),
PM800_REGULATOR_OF_MATCH(ldo8, LDO8),
PM800_REGULATOR_OF_MATCH(ldo9, LDO9),
PM800_REGULATOR_OF_MATCH(ldo10, LDO10),
PM800_REGULATOR_OF_MATCH(ldo11, LDO11),
PM800_REGULATOR_OF_MATCH(ldo12, LDO12),
PM800_REGULATOR_OF_MATCH(ldo13, LDO13),
PM800_REGULATOR_OF_MATCH(ldo14, LDO14),
PM800_REGULATOR_OF_MATCH(ldo15, LDO15),
PM800_REGULATOR_OF_MATCH(ldo16, LDO16),
PM800_REGULATOR_OF_MATCH(ldo17, LDO17),
PM800_REGULATOR_OF_MATCH(ldo18, LDO18),
PM800_REGULATOR_OF_MATCH(ldo19, LDO19),
};
static int pm800_regulator_dt_init(struct platform_device *pdev)
{
struct device_node *np = pdev->dev.of_node;
int ret;
ret = of_regulator_match(&pdev->dev, np,
pm800_regulator_matches,
ARRAY_SIZE(pm800_regulator_matches));
if (ret < 0)
return ret;
return 0;
}
static int pm800_regulator_probe(struct platform_device *pdev)
{
struct pm80x_chip *chip = dev_get_drvdata(pdev->dev.parent);
struct pm80x_platform_data *pdata = pdev->dev.parent->platform_data;
struct pm800_regulators *pm800_data;
struct pm800_regulator_info *info;
struct regulator_config config = { };
struct regulator_init_data *init_data;
int i, ret;
if (!pdata || pdata->num_regulators == 0) {
if (IS_ENABLED(CONFIG_OF)) {
ret = pm800_regulator_dt_init(pdev);
if (ret)
return ret;
} else {
return -ENODEV;
}
} else if (pdata->num_regulators) {
unsigned int count = 0;
/* Check whether num_regulator is valid. */
for (i = 0; i < ARRAY_SIZE(pdata->regulators); i++) {
if (pdata->regulators[i])
count++;
}
if (count != pdata->num_regulators)
return -EINVAL;
} else {
return -EINVAL;
}
pm800_data = devm_kzalloc(&pdev->dev, sizeof(*pm800_data),
GFP_KERNEL);
if (!pm800_data) {
dev_err(&pdev->dev, "Failed to allocate pm800_regualtors");
return -ENOMEM;
}
pm800_data->map = chip->subchip->regmap_power;
pm800_data->chip = chip;
platform_set_drvdata(pdev, pm800_data);
for (i = 0; i < PM800_ID_RG_MAX; i++) {
if (!pdata || pdata->num_regulators == 0)
init_data = pm800_regulator_matches[i].init_data;
else
init_data = pdata->regulators[i];
if (!init_data)
continue;
info = pm800_regulator_matches[i].driver_data;
config.dev = &pdev->dev;
config.init_data = init_data;
config.driver_data = info;
config.regmap = pm800_data->map;
config.of_node = pm800_regulator_matches[i].of_node;
pm800_data->regulators[i] =
regulator_register(&info->desc, &config);
if (IS_ERR(pm800_data->regulators[i])) {
ret = PTR_ERR(pm800_data->regulators[i]);
dev_err(&pdev->dev, "Failed to register %s\n",
info->desc.name);
while (--i >= 0)
regulator_unregister(pm800_data->regulators[i]);
return ret;
}
}
return 0;
}
static int pm800_regulator_remove(struct platform_device *pdev)
{
struct pm800_regulators *pm800_data = platform_get_drvdata(pdev);
int i;
for (i = 0; i < PM800_ID_RG_MAX; i++)
regulator_unregister(pm800_data->regulators[i]);
return 0;
}
static struct platform_driver pm800_regulator_driver = {
.driver = {
.name = "88pm80x-regulator",
.owner = THIS_MODULE,
},
.probe = pm800_regulator_probe,
.remove = pm800_regulator_remove,
};
module_platform_driver(pm800_regulator_driver);
MODULE_LICENSE("GPL");
MODULE_AUTHOR("Joseph(Yossi) Hanin <yhanin@marvell.com>");
MODULE_DESCRIPTION("Regulator Driver for Marvell 88PM800 PMIC");
MODULE_ALIAS("platform:88pm800-regulator");

View file

@ -64,15 +64,21 @@ config REGULATOR_USERSPACE_CONSUMER
If unsure, say no.
config REGULATOR_GPIO
tristate "GPIO regulator support"
depends on GPIOLIB
config REGULATOR_88PM800
tristate "Marvell 88PM800 Power regulators"
depends on MFD_88PM800
help
This driver provides support for regulators that can be
controlled via gpios.
It is capable of supporting current and voltage regulators
and the platform has to provide a mapping of GPIO-states
to target volts/amps.
This driver supports Marvell 88PM800 voltage regulator chips.
It delivers digitally programmable output,
the voltage is programmed via I2C interface.
It's suitable to support PXA988 chips to control VCC_MAIN and
various voltages.
config REGULATOR_88PM8607
bool "Marvell 88PM8607 Power regulators"
depends on MFD_88PM860X=y
help
This driver supports 88PM8607 voltage regulator chips.
config REGULATOR_AD5398
tristate "Analog Devices AD5398/AD5821 regulators"
@ -81,6 +87,14 @@ config REGULATOR_AD5398
This driver supports AD5398 and AD5821 current regulator chips.
If building into module, its name is ad5398.ko.
config REGULATOR_ANATOP
tristate "Freescale i.MX on-chip ANATOP LDO regulators"
depends on MFD_SYSCON
help
Say y here to support Freescale i.MX on-chip ANATOP LDOs
regulators. It is recommended that this option be
enabled on i.MX6 platform.
config REGULATOR_AAT2870
tristate "AnalogicTech AAT2870 Regulators"
depends on MFD_AAT2870_CORE
@ -88,6 +102,22 @@ config REGULATOR_AAT2870
If you have a AnalogicTech AAT2870 say Y to enable the
regulator driver.
config REGULATOR_AB3100
tristate "ST-Ericsson AB3100 Regulator functions"
depends on AB3100_CORE
default y if AB3100_CORE
help
These regulators correspond to functionality in the
AB3100 analog baseband dealing with power regulators
for the system.
config REGULATOR_AB8500
bool "ST-Ericsson AB8500 Power Regulators"
depends on AB8500_CORE
help
This driver supports the regulators found on the ST-Ericsson mixed
signal AB8500 PMIC
config REGULATOR_ARIZONA
tristate "Wolfson Arizona class devices"
depends on MFD_ARIZONA
@ -96,6 +126,13 @@ config REGULATOR_ARIZONA
Support for the regulators found on Wolfson Arizona class
devices.
config REGULATOR_AS3711
tristate "AS3711 PMIC"
depends on MFD_AS3711
help
This driver provides support for the voltage regulators on the
AS3711 PMIC
config REGULATOR_DA903X
tristate "Dialog Semiconductor DA9030/DA9034 regulators"
depends on PMIC_DA903X
@ -120,6 +157,17 @@ config REGULATOR_DA9055
This driver can also be built as a module. If so, the module
will be called da9055-regulator.
config REGULATOR_DBX500_PRCMU
bool
config REGULATOR_DB8500_PRCMU
bool "ST-Ericsson DB8500 Voltage Domain Regulators"
depends on MFD_DB8500_PRCMU
select REGULATOR_DBX500_PRCMU
help
This driver supports the voltage domain regulators controlled by the
DB8500 PRCMU
config REGULATOR_FAN53555
tristate "Fairchild FAN53555 Regulator"
depends on I2C
@ -131,32 +179,15 @@ config REGULATOR_FAN53555
input voltage supply of 2.5V to 5.5V. The output voltage is
programmed through an I2C interface.
config REGULATOR_ANATOP
tristate "Freescale i.MX on-chip ANATOP LDO regulators"
depends on MFD_SYSCON
config REGULATOR_GPIO
tristate "GPIO regulator support"
depends on GPIOLIB
help
Say y here to support Freescale i.MX on-chip ANATOP LDOs
regulators. It is recommended that this option be
enabled on i.MX6 platform.
config REGULATOR_MC13XXX_CORE
tristate
config REGULATOR_MC13783
tristate "Freescale MC13783 regulator driver"
depends on MFD_MC13783
select REGULATOR_MC13XXX_CORE
help
Say y here to support the regulators found on the Freescale MC13783
PMIC.
config REGULATOR_MC13892
tristate "Freescale MC13892 regulator driver"
depends on MFD_MC13XXX
select REGULATOR_MC13XXX_CORE
help
Say y here to support the regulators found on the Freescale MC13892
PMIC.
This driver provides support for regulators that can be
controlled via gpios.
It is capable of supporting current and voltage regulators
and the platform has to provide a mapping of GPIO-states
to target volts/amps.
config REGULATOR_ISL6271A
tristate "Intersil ISL6271A Power regulator"
@ -164,11 +195,41 @@ config REGULATOR_ISL6271A
help
This driver supports ISL6271A voltage regulator chip.
config REGULATOR_88PM8607
bool "Marvell 88PM8607 Power regulators"
depends on MFD_88PM860X=y
config REGULATOR_LP3971
tristate "National Semiconductors LP3971 PMIC regulator driver"
depends on I2C
help
This driver supports 88PM8607 voltage regulator chips.
Say Y here to support the voltage regulators and convertors
on National Semiconductors LP3971 PMIC
config REGULATOR_LP3972
tristate "National Semiconductors LP3972 PMIC regulator driver"
depends on I2C
help
Say Y here to support the voltage regulators and convertors
on National Semiconductors LP3972 PMIC
config REGULATOR_LP872X
bool "TI/National Semiconductor LP8720/LP8725 voltage regulators"
depends on I2C=y
select REGMAP_I2C
help
This driver supports LP8720/LP8725 PMIC
config REGULATOR_LP8755
tristate "TI LP8755 High Performance PMU driver"
depends on I2C
select REGMAP_I2C
help
This driver supports LP8755 High Performance PMU driver. This
chip contains six step-down DC/DC converters which can support
9 mode multiphase configuration.
config REGULATOR_LP8788
bool "TI LP8788 Power Regulators"
depends on MFD_LP8788
help
This driver supports LP8788 voltage regulator chip.
config REGULATOR_MAX1586
tristate "Maxim 1586/1587 voltage regulator"
@ -259,6 +320,37 @@ config REGULATOR_MAX77693
and one current regulator 'CHARGER'. This is suitable for
Exynos-4x12 chips.
config REGULATOR_MC13XXX_CORE
tristate
config REGULATOR_MC13783
tristate "Freescale MC13783 regulator driver"
depends on MFD_MC13783
select REGULATOR_MC13XXX_CORE
help
Say y here to support the regulators found on the Freescale MC13783
PMIC.
config REGULATOR_MC13892
tristate "Freescale MC13892 regulator driver"
depends on MFD_MC13XXX
select REGULATOR_MC13XXX_CORE
help
Say y here to support the regulators found on the Freescale MC13892
PMIC.
config REGULATOR_PALMAS
tristate "TI Palmas PMIC Regulators"
depends on MFD_PALMAS
help
If you wish to control the regulators on the Palmas series of
chips say Y here. This will enable support for all the software
controllable SMPS/LDO regulators.
The regulators available on Palmas series chips vary depending
on the muxing. This is handled automatically in the driver by
reading the mux info from OTP.
config REGULATOR_PCAP
tristate "Motorola PCAP2 regulator driver"
depends on EZX_PCAP
@ -266,42 +358,6 @@ config REGULATOR_PCAP
This driver provides support for the voltage regulators of the
PCAP2 PMIC.
config REGULATOR_LP3971
tristate "National Semiconductors LP3971 PMIC regulator driver"
depends on I2C
help
Say Y here to support the voltage regulators and convertors
on National Semiconductors LP3971 PMIC
config REGULATOR_LP3972
tristate "National Semiconductors LP3972 PMIC regulator driver"
depends on I2C
help
Say Y here to support the voltage regulators and convertors
on National Semiconductors LP3972 PMIC
config REGULATOR_LP872X
bool "TI/National Semiconductor LP8720/LP8725 voltage regulators"
depends on I2C=y
select REGMAP_I2C
help
This driver supports LP8720/LP8725 PMIC
config REGULATOR_LP8755
tristate "TI LP8755 High Performance PMU driver"
depends on I2C
select REGMAP_I2C
help
This driver supports LP8755 High Performance PMU driver. This
chip contains six step-down DC/DC converters which can support
9 mode multiphase configuration.
config REGULATOR_LP8788
bool "TI LP8788 Power Regulators"
depends on MFD_LP8788
help
This driver supports LP8788 voltage regulator chip.
config REGULATOR_PCF50633
tristate "NXP PCF50633 regulator driver"
depends on MFD_PCF50633
@ -335,44 +391,15 @@ config REGULATOR_S5M8767
via I2C bus. S5M8767A have 9 Bucks and 28 LDOs output and
supports DVS mode with 8bits of output voltage control.
config REGULATOR_AB3100
tristate "ST-Ericsson AB3100 Regulator functions"
depends on AB3100_CORE
default y if AB3100_CORE
config REGULATOR_TI_ABB
bool "TI Adaptive Body Bias on-chip LDO"
depends on ARCH_OMAP
help
These regulators correspond to functionality in the
AB3100 analog baseband dealing with power regulators
for the system.
config REGULATOR_AB8500
bool "ST-Ericsson AB8500 Power Regulators"
depends on AB8500_CORE
help
This driver supports the regulators found on the ST-Ericsson mixed
signal AB8500 PMIC
config REGULATOR_DBX500_PRCMU
bool
config REGULATOR_DB8500_PRCMU
bool "ST-Ericsson DB8500 Voltage Domain Regulators"
depends on MFD_DB8500_PRCMU
select REGULATOR_DBX500_PRCMU
help
This driver supports the voltage domain regulators controlled by the
DB8500 PRCMU
config REGULATOR_PALMAS
tristate "TI Palmas PMIC Regulators"
depends on MFD_PALMAS
help
If you wish to control the regulators on the Palmas series of
chips say Y here. This will enable support for all the software
controllable SMPS/LDO regulators.
The regulators available on Palmas series chips vary depending
on the muxing. This is handled automatically in the driver by
reading the mux info from OTP.
Select this option to support Texas Instruments' on-chip Adaptive Body
Bias (ABB) LDO regulators. It is recommended that this option be
enabled on required TI SoC. Certain Operating Performance Points
on TI SoCs may be unstable without enabling this as it provides
device specific optimized bias to allow/optimize functionality.
config REGULATOR_TPS51632
tristate "TI TPS51632 Power Regulator"
@ -481,16 +508,6 @@ config REGULATOR_TWL4030
This driver supports the voltage regulators provided by
this family of companion chips.
config REGULATOR_TI_ABB
bool "TI Adaptive Body Bias on-chip LDO"
depends on ARCH_OMAP
help
Select this option to support Texas Instruments' on-chip Adaptive Body
Bias (ABB) LDO regulators. It is recommended that this option be
enabled on required TI SoC. Certain Operating Performance Points
on TI SoCs may be unstable without enabling this as it provides
device specific optimized bias to allow/optimize functionality.
config REGULATOR_VEXPRESS
tristate "Versatile Express regulators"
depends on VEXPRESS_CONFIG
@ -526,12 +543,5 @@ config REGULATOR_WM8994
This driver provides support for the voltage regulators on the
WM8994 CODEC.
config REGULATOR_AS3711
tristate "AS3711 PMIC"
depends on MFD_AS3711
help
This driver provides support for the voltage regulators on the
AS3711 PMIC
endif

View file

@ -9,6 +9,7 @@ obj-$(CONFIG_REGULATOR_FIXED_VOLTAGE) += fixed.o
obj-$(CONFIG_REGULATOR_VIRTUAL_CONSUMER) += virtual.o
obj-$(CONFIG_REGULATOR_USERSPACE_CONSUMER) += userspace-consumer.o
obj-$(CONFIG_REGULATOR_88PM800) += 88pm800.o
obj-$(CONFIG_REGULATOR_88PM8607) += 88pm8607.o
obj-$(CONFIG_REGULATOR_AAT2870) += aat2870-regulator.o
obj-$(CONFIG_REGULATOR_AB3100) += ab3100.o
@ -52,6 +53,7 @@ obj-$(CONFIG_REGULATOR_PCF50633) += pcf50633-regulator.o
obj-$(CONFIG_REGULATOR_RC5T583) += rc5t583-regulator.o
obj-$(CONFIG_REGULATOR_S2MPS11) += s2mps11.o
obj-$(CONFIG_REGULATOR_S5M8767) += s5m8767.o
obj-$(CONFIG_REGULATOR_TI_ABB) += ti-abb-regulator.o
obj-$(CONFIG_REGULATOR_TPS6105X) += tps6105x-regulator.o
obj-$(CONFIG_REGULATOR_TPS62360) += tps62360-regulator.o
obj-$(CONFIG_REGULATOR_TPS65023) += tps65023-regulator.o
@ -64,7 +66,6 @@ obj-$(CONFIG_REGULATOR_TPS65910) += tps65910-regulator.o
obj-$(CONFIG_REGULATOR_TPS65912) += tps65912-regulator.o
obj-$(CONFIG_REGULATOR_TPS80031) += tps80031-regulator.o
obj-$(CONFIG_REGULATOR_TWL4030) += twl-regulator.o
obj-$(CONFIG_REGULATOR_TI_ABB) += ti-abb-regulator.o
obj-$(CONFIG_REGULATOR_VEXPRESS) += vexpress.o
obj-$(CONFIG_REGULATOR_WM831X) += wm831x-dcdc.o
obj-$(CONFIG_REGULATOR_WM831X) += wm831x-isink.o

View file

@ -2078,6 +2078,43 @@ int regulator_list_voltage_linear(struct regulator_dev *rdev,
}
EXPORT_SYMBOL_GPL(regulator_list_voltage_linear);
/**
* regulator_list_voltage_linear_range - List voltages for linear ranges
*
* @rdev: Regulator device
* @selector: Selector to convert into a voltage
*
* Regulators with a series of simple linear mappings between voltages
* and selectors can set linear_ranges in the regulator descriptor and
* then use this function as their list_voltage() operation,
*/
int regulator_list_voltage_linear_range(struct regulator_dev *rdev,
unsigned int selector)
{
const struct regulator_linear_range *range;
int i;
if (!rdev->desc->n_linear_ranges) {
BUG_ON(!rdev->desc->n_linear_ranges);
return -EINVAL;
}
for (i = 0; i < rdev->desc->n_linear_ranges; i++) {
range = &rdev->desc->linear_ranges[i];
if (!(selector >= range->min_sel &&
selector <= range->max_sel))
continue;
selector -= range->min_sel;
return range->min_uV + (range->uV_step * selector);
}
return -EINVAL;
}
EXPORT_SYMBOL_GPL(regulator_list_voltage_linear_range);
/**
* regulator_list_voltage_table - List voltages with table based mapping
*
@ -2368,6 +2405,64 @@ int regulator_map_voltage_linear(struct regulator_dev *rdev,
}
EXPORT_SYMBOL_GPL(regulator_map_voltage_linear);
/**
* regulator_map_voltage_linear - map_voltage() for multiple linear ranges
*
* @rdev: Regulator to operate on
* @min_uV: Lower bound for voltage
* @max_uV: Upper bound for voltage
*
* Drivers providing linear_ranges in their descriptor can use this as
* their map_voltage() callback.
*/
int regulator_map_voltage_linear_range(struct regulator_dev *rdev,
int min_uV, int max_uV)
{
const struct regulator_linear_range *range;
int ret = -EINVAL;
int voltage, i;
if (!rdev->desc->n_linear_ranges) {
BUG_ON(!rdev->desc->n_linear_ranges);
return -EINVAL;
}
for (i = 0; i < rdev->desc->n_linear_ranges; i++) {
range = &rdev->desc->linear_ranges[i];
if (!(min_uV <= range->max_uV && max_uV >= range->min_uV))
continue;
if (min_uV <= range->min_uV)
min_uV = range->min_uV;
/* range->uV_step == 0 means fixed voltage range */
if (range->uV_step == 0) {
ret = 0;
} else {
ret = DIV_ROUND_UP(min_uV - range->min_uV,
range->uV_step);
if (ret < 0)
return ret;
}
ret += range->min_sel;
break;
}
if (i == rdev->desc->n_linear_ranges)
return -EINVAL;
/* Map back into a voltage to verify we're still in bounds */
voltage = rdev->desc->ops->list_voltage(rdev, ret);
if (voltage < min_uV || voltage > max_uV)
return -EINVAL;
return ret;
}
EXPORT_SYMBOL_GPL(regulator_map_voltage_linear_range);
static int _regulator_do_set_voltage(struct regulator_dev *rdev,
int min_uV, int max_uV)
{

View file

@ -62,41 +62,12 @@ static irqreturn_t wm831x_ldo_uv_irq(int irq, void *data)
* General purpose LDOs
*/
#define WM831X_GP_LDO_SELECTOR_LOW 0xe
#define WM831X_GP_LDO_MAX_SELECTOR 0x1f
static int wm831x_gp_ldo_list_voltage(struct regulator_dev *rdev,
unsigned int selector)
{
/* 0.9-1.6V in 50mV steps */
if (selector <= WM831X_GP_LDO_SELECTOR_LOW)
return 900000 + (selector * 50000);
/* 1.7-3.3V in 100mV steps */
if (selector <= WM831X_GP_LDO_MAX_SELECTOR)
return 1600000 + ((selector - WM831X_GP_LDO_SELECTOR_LOW)
* 100000);
return -EINVAL;
}
static int wm831x_gp_ldo_map_voltage(struct regulator_dev *rdev,
int min_uV, int max_uV)
{
int volt, vsel;
if (min_uV < 900000)
vsel = 0;
else if (min_uV < 1700000)
vsel = ((min_uV - 900000) / 50000);
else
vsel = ((min_uV - 1700000) / 100000)
+ WM831X_GP_LDO_SELECTOR_LOW + 1;
volt = wm831x_gp_ldo_list_voltage(rdev, vsel);
if (volt < min_uV || volt > max_uV)
return -EINVAL;
return vsel;
}
static const struct regulator_linear_range wm831x_gp_ldo_ranges[] = {
{ .min_uV = 900000, .max_uV = 1650000, .min_sel = 0, .max_sel = 14,
.uV_step = 50000 },
{ .min_uV = 1700000, .max_uV = 3300000, .min_sel = 15, .max_sel = 31,
.uV_step = 100000 },
};
static int wm831x_gp_ldo_set_suspend_voltage(struct regulator_dev *rdev,
int uV)
@ -105,7 +76,7 @@ static int wm831x_gp_ldo_set_suspend_voltage(struct regulator_dev *rdev,
struct wm831x *wm831x = ldo->wm831x;
int sel, reg = ldo->base + WM831X_LDO_SLEEP_CONTROL;
sel = wm831x_gp_ldo_map_voltage(rdev, uV, uV);
sel = regulator_map_voltage_linear_range(rdev, uV, uV);
if (sel < 0)
return sel;
@ -230,8 +201,8 @@ static unsigned int wm831x_gp_ldo_get_optimum_mode(struct regulator_dev *rdev,
static struct regulator_ops wm831x_gp_ldo_ops = {
.list_voltage = wm831x_gp_ldo_list_voltage,
.map_voltage = wm831x_gp_ldo_map_voltage,
.list_voltage = regulator_list_voltage_linear_range,
.map_voltage = regulator_map_voltage_linear_range,
.get_voltage_sel = regulator_get_voltage_sel_regmap,
.set_voltage_sel = regulator_set_voltage_sel_regmap,
.set_suspend_voltage = wm831x_gp_ldo_set_suspend_voltage,
@ -290,7 +261,7 @@ static int wm831x_gp_ldo_probe(struct platform_device *pdev)
ldo->desc.id = id;
ldo->desc.type = REGULATOR_VOLTAGE;
ldo->desc.n_voltages = WM831X_GP_LDO_MAX_SELECTOR + 1;
ldo->desc.n_voltages = 32;
ldo->desc.ops = &wm831x_gp_ldo_ops;
ldo->desc.owner = THIS_MODULE;
ldo->desc.vsel_reg = ldo->base + WM831X_LDO_ON_CONTROL;
@ -299,6 +270,8 @@ static int wm831x_gp_ldo_probe(struct platform_device *pdev)
ldo->desc.enable_mask = 1 << id;
ldo->desc.bypass_reg = ldo->base;
ldo->desc.bypass_mask = WM831X_LDO1_SWI;
ldo->desc.linear_ranges = wm831x_gp_ldo_ranges;
ldo->desc.n_linear_ranges = ARRAY_SIZE(wm831x_gp_ldo_ranges);
config.dev = pdev->dev.parent;
if (pdata)
@ -358,43 +331,12 @@ static struct platform_driver wm831x_gp_ldo_driver = {
* Analogue LDOs
*/
#define WM831X_ALDO_SELECTOR_LOW 0xc
#define WM831X_ALDO_MAX_SELECTOR 0x1f
static int wm831x_aldo_list_voltage(struct regulator_dev *rdev,
unsigned int selector)
{
/* 1-1.6V in 50mV steps */
if (selector <= WM831X_ALDO_SELECTOR_LOW)
return 1000000 + (selector * 50000);
/* 1.7-3.5V in 100mV steps */
if (selector <= WM831X_ALDO_MAX_SELECTOR)
return 1600000 + ((selector - WM831X_ALDO_SELECTOR_LOW)
* 100000);
return -EINVAL;
}
static int wm831x_aldo_map_voltage(struct regulator_dev *rdev,
int min_uV, int max_uV)
{
int volt, vsel;
if (min_uV < 1000000)
vsel = 0;
else if (min_uV < 1700000)
vsel = ((min_uV - 1000000) / 50000);
else
vsel = ((min_uV - 1700000) / 100000)
+ WM831X_ALDO_SELECTOR_LOW + 1;
volt = wm831x_aldo_list_voltage(rdev, vsel);
if (volt < min_uV || volt > max_uV)
return -EINVAL;
return vsel;
}
static const struct regulator_linear_range wm831x_aldo_ranges[] = {
{ .min_uV = 1000000, .max_uV = 1650000, .min_sel = 0, .max_sel = 12,
.uV_step = 50000 },
{ .min_uV = 1700000, .max_uV = 3500000, .min_sel = 13, .max_sel = 31,
.uV_step = 100000 },
};
static int wm831x_aldo_set_suspend_voltage(struct regulator_dev *rdev,
int uV)
@ -403,7 +345,7 @@ static int wm831x_aldo_set_suspend_voltage(struct regulator_dev *rdev,
struct wm831x *wm831x = ldo->wm831x;
int sel, reg = ldo->base + WM831X_LDO_SLEEP_CONTROL;
sel = wm831x_aldo_map_voltage(rdev, uV, uV);
sel = regulator_map_voltage_linear_range(rdev, uV, uV);
if (sel < 0)
return sel;
@ -486,8 +428,8 @@ static int wm831x_aldo_get_status(struct regulator_dev *rdev)
}
static struct regulator_ops wm831x_aldo_ops = {
.list_voltage = wm831x_aldo_list_voltage,
.map_voltage = wm831x_aldo_map_voltage,
.list_voltage = regulator_list_voltage_linear_range,
.map_voltage = regulator_map_voltage_linear_range,
.get_voltage_sel = regulator_get_voltage_sel_regmap,
.set_voltage_sel = regulator_set_voltage_sel_regmap,
.set_suspend_voltage = wm831x_aldo_set_suspend_voltage,
@ -545,7 +487,9 @@ static int wm831x_aldo_probe(struct platform_device *pdev)
ldo->desc.id = id;
ldo->desc.type = REGULATOR_VOLTAGE;
ldo->desc.n_voltages = WM831X_ALDO_MAX_SELECTOR + 1;
ldo->desc.n_voltages = 32;
ldo->desc.linear_ranges = wm831x_aldo_ranges;
ldo->desc.n_linear_ranges = ARRAY_SIZE(wm831x_aldo_ranges);
ldo->desc.ops = &wm831x_aldo_ops;
ldo->desc.owner = THIS_MODULE;
ldo->desc.vsel_reg = ldo->base + WM831X_LDO_ON_CONTROL;

View file

@ -542,41 +542,12 @@ static int wm8350_dcdc_set_suspend_mode(struct regulator_dev *rdev,
return 0;
}
static int wm8350_ldo_list_voltage(struct regulator_dev *rdev,
unsigned selector)
{
if (selector > WM8350_LDO1_VSEL_MASK)
return -EINVAL;
if (selector < 16)
return (selector * 50000) + 900000;
else
return ((selector - 16) * 100000) + 1800000;
}
static int wm8350_ldo_map_voltage(struct regulator_dev *rdev, int min_uV,
int max_uV)
{
int volt, sel;
int min_mV = min_uV / 1000;
int max_mV = max_uV / 1000;
if (min_mV < 900 || min_mV > 3300)
return -EINVAL;
if (max_mV < 900 || max_mV > 3300)
return -EINVAL;
if (min_mV < 1800) /* step size is 50mV < 1800mV */
sel = DIV_ROUND_UP(min_uV - 900, 50);
else /* step size is 100mV > 1800mV */
sel = DIV_ROUND_UP(min_uV - 1800, 100) + 16;
volt = wm8350_ldo_list_voltage(rdev, sel);
if (volt < min_uV || volt > max_uV)
return -EINVAL;
return sel;
}
static const struct regulator_linear_range wm8350_ldo_ranges[] = {
{ .min_uV = 900000, .max_uV = 1750000, .min_sel = 0, .max_sel = 15,
.uV_step = 50000 },
{ .min_uV = 1800000, .max_uV = 3300000, .min_sel = 16, .max_sel = 31,
.uV_step = 100000 },
};
static int wm8350_ldo_set_suspend_voltage(struct regulator_dev *rdev, int uV)
{
@ -603,7 +574,7 @@ static int wm8350_ldo_set_suspend_voltage(struct regulator_dev *rdev, int uV)
return -EINVAL;
}
sel = wm8350_ldo_map_voltage(rdev, uV, uV);
sel = regulator_map_voltage_linear_range(rdev, uV, uV);
if (sel < 0)
return -EINVAL;
@ -998,10 +969,10 @@ static struct regulator_ops wm8350_dcdc2_5_ops = {
};
static struct regulator_ops wm8350_ldo_ops = {
.map_voltage = wm8350_ldo_map_voltage,
.map_voltage = regulator_map_voltage_linear_range,
.set_voltage_sel = regulator_set_voltage_sel_regmap,
.get_voltage_sel = regulator_get_voltage_sel_regmap,
.list_voltage = wm8350_ldo_list_voltage,
.list_voltage = regulator_list_voltage_linear_range,
.enable = regulator_enable_regmap,
.disable = regulator_disable_regmap,
.is_enabled = regulator_is_enabled_regmap,
@ -1108,6 +1079,8 @@ static const struct regulator_desc wm8350_reg[NUM_WM8350_REGULATORS] = {
.irq = WM8350_IRQ_UV_LDO1,
.type = REGULATOR_VOLTAGE,
.n_voltages = WM8350_LDO1_VSEL_MASK + 1,
.linear_ranges = wm8350_ldo_ranges,
.n_linear_ranges = ARRAY_SIZE(wm8350_ldo_ranges),
.vsel_reg = WM8350_LDO1_CONTROL,
.vsel_mask = WM8350_LDO1_VSEL_MASK,
.enable_reg = WM8350_DCDC_LDO_REQUESTED,
@ -1121,6 +1094,8 @@ static const struct regulator_desc wm8350_reg[NUM_WM8350_REGULATORS] = {
.irq = WM8350_IRQ_UV_LDO2,
.type = REGULATOR_VOLTAGE,
.n_voltages = WM8350_LDO2_VSEL_MASK + 1,
.linear_ranges = wm8350_ldo_ranges,
.n_linear_ranges = ARRAY_SIZE(wm8350_ldo_ranges),
.vsel_reg = WM8350_LDO2_CONTROL,
.vsel_mask = WM8350_LDO2_VSEL_MASK,
.enable_reg = WM8350_DCDC_LDO_REQUESTED,
@ -1134,6 +1109,8 @@ static const struct regulator_desc wm8350_reg[NUM_WM8350_REGULATORS] = {
.irq = WM8350_IRQ_UV_LDO3,
.type = REGULATOR_VOLTAGE,
.n_voltages = WM8350_LDO3_VSEL_MASK + 1,
.linear_ranges = wm8350_ldo_ranges,
.n_linear_ranges = ARRAY_SIZE(wm8350_ldo_ranges),
.vsel_reg = WM8350_LDO3_CONTROL,
.vsel_mask = WM8350_LDO3_VSEL_MASK,
.enable_reg = WM8350_DCDC_LDO_REQUESTED,
@ -1147,6 +1124,8 @@ static const struct regulator_desc wm8350_reg[NUM_WM8350_REGULATORS] = {
.irq = WM8350_IRQ_UV_LDO4,
.type = REGULATOR_VOLTAGE,
.n_voltages = WM8350_LDO4_VSEL_MASK + 1,
.linear_ranges = wm8350_ldo_ranges,
.n_linear_ranges = ARRAY_SIZE(wm8350_ldo_ranges),
.vsel_reg = WM8350_LDO4_CONTROL,
.vsel_mask = WM8350_LDO4_VSEL_MASK,
.enable_reg = WM8350_DCDC_LDO_REQUESTED,

View file

@ -19,47 +19,21 @@
#include <linux/regulator/driver.h>
#include <linux/mfd/wm8400-private.h>
static int wm8400_ldo_list_voltage(struct regulator_dev *dev,
unsigned selector)
{
if (selector > WM8400_LDO1_VSEL_MASK)
return -EINVAL;
if (selector < 15)
return 900000 + (selector * 50000);
else
return 1700000 + ((selector - 15) * 100000);
}
static int wm8400_ldo_map_voltage(struct regulator_dev *dev,
int min_uV, int max_uV)
{
u16 val;
int volt;
if (min_uV < 900000 || min_uV > 3300000)
return -EINVAL;
if (min_uV < 1700000) /* Steps of 50mV from 900mV; */
val = DIV_ROUND_UP(min_uV - 900000, 50000);
else /* Steps of 100mV from 1700mV */
val = DIV_ROUND_UP(min_uV - 1700000, 100000) + 15;
volt = wm8400_ldo_list_voltage(dev, val);
if (volt < min_uV || volt > max_uV)
return -EINVAL;
return val;
}
static const struct regulator_linear_range wm8400_ldo_ranges[] = {
{ .min_uV = 900000, .max_uV = 1600000, .min_sel = 0, .max_sel = 14,
.uV_step = 50000 },
{ .min_uV = 1700000, .max_uV = 3300000, .min_sel = 15, .max_sel = 31,
.uV_step = 100000 },
};
static struct regulator_ops wm8400_ldo_ops = {
.is_enabled = regulator_is_enabled_regmap,
.enable = regulator_enable_regmap,
.disable = regulator_disable_regmap,
.list_voltage = wm8400_ldo_list_voltage,
.list_voltage = regulator_list_voltage_linear_range,
.get_voltage_sel = regulator_get_voltage_sel_regmap,
.set_voltage_sel = regulator_set_voltage_sel_regmap,
.map_voltage = wm8400_ldo_map_voltage,
.map_voltage = regulator_map_voltage_linear_range,
};
static unsigned int wm8400_dcdc_get_mode(struct regulator_dev *dev)
@ -155,6 +129,8 @@ static struct regulator_desc regulators[] = {
.enable_reg = WM8400_LDO1_CONTROL,
.enable_mask = WM8400_LDO1_ENA,
.n_voltages = WM8400_LDO1_VSEL_MASK + 1,
.linear_ranges = wm8400_ldo_ranges,
.n_linear_ranges = ARRAY_SIZE(wm8400_ldo_ranges),
.vsel_reg = WM8400_LDO1_CONTROL,
.vsel_mask = WM8400_LDO1_VSEL_MASK,
.type = REGULATOR_VOLTAGE,
@ -167,6 +143,8 @@ static struct regulator_desc regulators[] = {
.enable_reg = WM8400_LDO2_CONTROL,
.enable_mask = WM8400_LDO2_ENA,
.n_voltages = WM8400_LDO2_VSEL_MASK + 1,
.linear_ranges = wm8400_ldo_ranges,
.n_linear_ranges = ARRAY_SIZE(wm8400_ldo_ranges),
.type = REGULATOR_VOLTAGE,
.vsel_reg = WM8400_LDO2_CONTROL,
.vsel_mask = WM8400_LDO2_VSEL_MASK,
@ -179,6 +157,8 @@ static struct regulator_desc regulators[] = {
.enable_reg = WM8400_LDO3_CONTROL,
.enable_mask = WM8400_LDO3_ENA,
.n_voltages = WM8400_LDO3_VSEL_MASK + 1,
.linear_ranges = wm8400_ldo_ranges,
.n_linear_ranges = ARRAY_SIZE(wm8400_ldo_ranges),
.vsel_reg = WM8400_LDO3_CONTROL,
.vsel_mask = WM8400_LDO3_VSEL_MASK,
.type = REGULATOR_VOLTAGE,
@ -191,6 +171,8 @@ static struct regulator_desc regulators[] = {
.enable_reg = WM8400_LDO4_CONTROL,
.enable_mask = WM8400_LDO4_ENA,
.n_voltages = WM8400_LDO4_VSEL_MASK + 1,
.linear_ranges = wm8400_ldo_ranges,
.n_linear_ranges = ARRAY_SIZE(wm8400_ldo_ranges),
.vsel_reg = WM8400_LDO4_CONTROL,
.vsel_mask = WM8400_LDO4_VSEL_MASK,
.type = REGULATOR_VOLTAGE,

View file

@ -39,6 +39,24 @@ enum regulator_status {
REGULATOR_STATUS_UNDEFINED,
};
/**
* Specify a range of voltages for regulator_map_linar_range() and
* regulator_list_linear_range().
*
* @min_uV: Lowest voltage in range
* @max_uV: Highest voltage in range
* @min_sel: Lowest selector for range
* @max_sel: Highest selector for range
* @uV_step: Step size
*/
struct regulator_linear_range {
unsigned int min_uV;
unsigned int max_uV;
unsigned int min_sel;
unsigned int max_sel;
unsigned int uV_step;
};
/**
* struct regulator_ops - regulator operations.
*
@ -223,6 +241,9 @@ struct regulator_desc {
unsigned int linear_min_sel;
unsigned int ramp_delay;
const struct regulator_linear_range *linear_ranges;
int n_linear_ranges;
const unsigned int *volt_table;
unsigned int vsel_reg;
@ -326,10 +347,14 @@ int regulator_mode_to_status(unsigned int);
int regulator_list_voltage_linear(struct regulator_dev *rdev,
unsigned int selector);
int regulator_list_voltage_linear_range(struct regulator_dev *rdev,
unsigned int selector);
int regulator_list_voltage_table(struct regulator_dev *rdev,
unsigned int selector);
int regulator_map_voltage_linear(struct regulator_dev *rdev,
int min_uV, int max_uV);
int regulator_map_voltage_linear_range(struct regulator_dev *rdev,
int min_uV, int max_uV);
int regulator_map_voltage_iterate(struct regulator_dev *rdev,
int min_uV, int max_uV);
int regulator_map_voltage_ascend(struct regulator_dev *rdev,