Commit 28c37c9c authored by Mark Brown's avatar Mark Brown

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

parents d8dfad38 720c0273
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;
};
...
};
};
/*
* 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");
...@@ -64,15 +64,21 @@ config REGULATOR_USERSPACE_CONSUMER ...@@ -64,15 +64,21 @@ config REGULATOR_USERSPACE_CONSUMER
If unsure, say no. If unsure, say no.
config REGULATOR_GPIO config REGULATOR_88PM800
tristate "GPIO regulator support" tristate "Marvell 88PM800 Power regulators"
depends on GPIOLIB depends on MFD_88PM800
help help
This driver provides support for regulators that can be This driver supports Marvell 88PM800 voltage regulator chips.
controlled via gpios. It delivers digitally programmable output,
It is capable of supporting current and voltage regulators the voltage is programmed via I2C interface.
and the platform has to provide a mapping of GPIO-states It's suitable to support PXA988 chips to control VCC_MAIN and
to target volts/amps. 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 config REGULATOR_AD5398
tristate "Analog Devices AD5398/AD5821 regulators" tristate "Analog Devices AD5398/AD5821 regulators"
...@@ -81,6 +87,14 @@ config REGULATOR_AD5398 ...@@ -81,6 +87,14 @@ config REGULATOR_AD5398
This driver supports AD5398 and AD5821 current regulator chips. This driver supports AD5398 and AD5821 current regulator chips.
If building into module, its name is ad5398.ko. 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 config REGULATOR_AAT2870
tristate "AnalogicTech AAT2870 Regulators" tristate "AnalogicTech AAT2870 Regulators"
depends on MFD_AAT2870_CORE depends on MFD_AAT2870_CORE
...@@ -88,6 +102,22 @@ config REGULATOR_AAT2870 ...@@ -88,6 +102,22 @@ config REGULATOR_AAT2870
If you have a AnalogicTech AAT2870 say Y to enable the If you have a AnalogicTech AAT2870 say Y to enable the
regulator driver. 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 config REGULATOR_ARIZONA
tristate "Wolfson Arizona class devices" tristate "Wolfson Arizona class devices"
depends on MFD_ARIZONA depends on MFD_ARIZONA
...@@ -96,6 +126,13 @@ config REGULATOR_ARIZONA ...@@ -96,6 +126,13 @@ config REGULATOR_ARIZONA
Support for the regulators found on Wolfson Arizona class Support for the regulators found on Wolfson Arizona class
devices. 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 config REGULATOR_DA903X
tristate "Dialog Semiconductor DA9030/DA9034 regulators" tristate "Dialog Semiconductor DA9030/DA9034 regulators"
depends on PMIC_DA903X depends on PMIC_DA903X
...@@ -120,6 +157,17 @@ config REGULATOR_DA9055 ...@@ -120,6 +157,17 @@ config REGULATOR_DA9055
This driver can also be built as a module. If so, the module This driver can also be built as a module. If so, the module
will be called da9055-regulator. 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 config REGULATOR_FAN53555
tristate "Fairchild FAN53555 Regulator" tristate "Fairchild FAN53555 Regulator"
depends on I2C depends on I2C
...@@ -131,44 +179,57 @@ config REGULATOR_FAN53555 ...@@ -131,44 +179,57 @@ config REGULATOR_FAN53555
input voltage supply of 2.5V to 5.5V. The output voltage is input voltage supply of 2.5V to 5.5V. The output voltage is
programmed through an I2C interface. programmed through an I2C interface.
config REGULATOR_ANATOP config REGULATOR_GPIO
tristate "Freescale i.MX on-chip ANATOP LDO regulators" tristate "GPIO regulator support"
depends on MFD_SYSCON depends on GPIOLIB
help help
Say y here to support Freescale i.MX on-chip ANATOP LDOs This driver provides support for regulators that can be
regulators. It is recommended that this option be controlled via gpios.
enabled on i.MX6 platform. 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_MC13XXX_CORE config REGULATOR_ISL6271A
tristate tristate "Intersil ISL6271A Power regulator"
depends on I2C
help
This driver supports ISL6271A voltage regulator chip.
config REGULATOR_MC13783 config REGULATOR_LP3971
tristate "Freescale MC13783 regulator driver" tristate "National Semiconductors LP3971 PMIC regulator driver"
depends on MFD_MC13783 depends on I2C
select REGULATOR_MC13XXX_CORE
help help
Say y here to support the regulators found on the Freescale MC13783 Say Y here to support the voltage regulators and convertors
PMIC. on National Semiconductors LP3971 PMIC
config REGULATOR_MC13892 config REGULATOR_LP3972
tristate "Freescale MC13892 regulator driver" tristate "National Semiconductors LP3972 PMIC regulator driver"
depends on MFD_MC13XXX depends on I2C
select REGULATOR_MC13XXX_CORE
help help
Say y here to support the regulators found on the Freescale MC13892 Say Y here to support the voltage regulators and convertors
PMIC. on National Semiconductors LP3972 PMIC
config REGULATOR_ISL6271A config REGULATOR_LP872X
tristate "Intersil ISL6271A Power regulator" 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 depends on I2C
select REGMAP_I2C
help help
This driver supports ISL6271A voltage regulator chip. 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_88PM8607 config REGULATOR_LP8788
bool "Marvell 88PM8607 Power regulators" bool "TI LP8788 Power Regulators"
depends on MFD_88PM860X=y depends on MFD_LP8788
help help
This driver supports 88PM8607 voltage regulator chips. This driver supports LP8788 voltage regulator chip.
config REGULATOR_MAX1586 config REGULATOR_MAX1586
tristate "Maxim 1586/1587 voltage regulator" tristate "Maxim 1586/1587 voltage regulator"
...@@ -259,48 +320,43 @@ config REGULATOR_MAX77693 ...@@ -259,48 +320,43 @@ config REGULATOR_MAX77693
and one current regulator 'CHARGER'. This is suitable for and one current regulator 'CHARGER'. This is suitable for
Exynos-4x12 chips. Exynos-4x12 chips.
config REGULATOR_PCAP config REGULATOR_MC13XXX_CORE
tristate "Motorola PCAP2 regulator driver" tristate
depends on EZX_PCAP
help
This driver provides support for the voltage regulators of the
PCAP2 PMIC.
config REGULATOR_LP3971 config REGULATOR_MC13783
tristate "National Semiconductors LP3971 PMIC regulator driver" tristate "Freescale MC13783 regulator driver"
depends on I2C depends on MFD_MC13783
select REGULATOR_MC13XXX_CORE
help help
Say Y here to support the voltage regulators and convertors Say y here to support the regulators found on the Freescale MC13783
on National Semiconductors LP3971 PMIC PMIC.
config REGULATOR_LP3972 config REGULATOR_MC13892
tristate "National Semiconductors LP3972 PMIC regulator driver" tristate "Freescale MC13892 regulator driver"
depends on I2C depends on MFD_MC13XXX
select REGULATOR_MC13XXX_CORE
help help
Say Y here to support the voltage regulators and convertors Say y here to support the regulators found on the Freescale MC13892
on National Semiconductors LP3972 PMIC PMIC.
config REGULATOR_LP872X config REGULATOR_PALMAS
bool "TI/National Semiconductor LP8720/LP8725 voltage regulators" tristate "TI Palmas PMIC Regulators"
depends on I2C=y depends on MFD_PALMAS
select REGMAP_I2C
help help
This driver supports LP8720/LP8725 PMIC 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.
config REGULATOR_LP8755 The regulators available on Palmas series chips vary depending
tristate "TI LP8755 High Performance PMU driver" on the muxing. This is handled automatically in the driver by
depends on I2C reading the mux info from OTP.
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 config REGULATOR_PCAP
bool "TI LP8788 Power Regulators" tristate "Motorola PCAP2 regulator driver"
depends on MFD_LP8788 depends on EZX_PCAP
help help
This driver supports LP8788 voltage regulator chip. This driver provides support for the voltage regulators of the
PCAP2 PMIC.
config REGULATOR_PCF50633 config REGULATOR_PCF50633
tristate "NXP PCF50633 regulator driver" tristate "NXP PCF50633 regulator driver"
...@@ -335,44 +391,15 @@ config REGULATOR_S5M8767 ...@@ -335,44 +391,15 @@ config REGULATOR_S5M8767
via I2C bus. S5M8767A have 9 Bucks and 28 LDOs output and via I2C bus. S5M8767A have 9 Bucks and 28 LDOs output and
supports DVS mode with 8bits of output voltage control. supports DVS mode with 8bits of output voltage control.
config REGULATOR_AB3100 config REGULATOR_TI_ABB
tristate "ST-Ericsson AB3100 Regulator functions" bool "TI Adaptive Body Bias on-chip LDO"
depends on AB3100_CORE depends on ARCH_OMAP
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_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 help
If you wish to control the regulators on the Palmas series of Select this option to support Texas Instruments' on-chip Adaptive Body
chips say Y here. This will enable support for all the software Bias (ABB) LDO regulators. It is recommended that this option be
controllable SMPS/LDO regulators. enabled on required TI SoC. Certain Operating Performance Points
on TI SoCs may be unstable without enabling this as it provides
The regulators available on Palmas series chips vary depending device specific optimized bias to allow/optimize functionality.
on the muxing. This is handled automatically in the driver by
reading the mux info from OTP.
config REGULATOR_TPS51632 config REGULATOR_TPS51632
tristate "TI TPS51632 Power Regulator" tristate "TI TPS51632 Power Regulator"
...@@ -481,16 +508,6 @@ config REGULATOR_TWL4030 ...@@ -481,16 +508,6 @@ config REGULATOR_TWL4030
This driver supports the voltage regulators provided by This driver supports the voltage regulators provided by
this family of companion chips. 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 config REGULATOR_VEXPRESS
tristate "Versatile Express regulators" tristate "Versatile Express regulators"
depends on VEXPRESS_CONFIG depends on VEXPRESS_CONFIG
...@@ -526,12 +543,5 @@ config REGULATOR_WM8994 ...@@ -526,12 +543,5 @@ config REGULATOR_WM8994
This driver provides support for the voltage regulators on the This driver provides support for the voltage regulators on the
WM8994 CODEC. 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 endif
...@@ -9,6 +9,7 @@ obj-$(CONFIG_REGULATOR_FIXED_VOLTAGE) += fixed.o ...@@ -9,6 +9,7 @@ obj-$(CONFIG_REGULATOR_FIXED_VOLTAGE) += fixed.o
obj-$(CONFIG_REGULATOR_VIRTUAL_CONSUMER) += virtual.o obj-$(CONFIG_REGULATOR_VIRTUAL_CONSUMER) += virtual.o
obj-$(CONFIG_REGULATOR_USERSPACE_CONSUMER) += userspace-consumer.o obj-$(CONFIG_REGULATOR_USERSPACE_CONSUMER) += userspace-consumer.o
obj-$(CONFIG_REGULATOR_88PM800) += 88pm800.o
obj-$(CONFIG_REGULATOR_88PM8607) += 88pm8607.o obj-$(CONFIG_REGULATOR_88PM8607) += 88pm8607.o
obj-$(CONFIG_REGULATOR_AAT2870) += aat2870-regulator.o obj-$(CONFIG_REGULATOR_AAT2870) += aat2870-regulator.o
obj-$(CONFIG_REGULATOR_AB3100) += ab3100.o obj-$(CONFIG_REGULATOR_AB3100) += ab3100.o
...@@ -52,6 +53,7 @@ obj-$(CONFIG_REGULATOR_PCF50633) += pcf50633-regulator.o ...@@ -52,6 +53,7 @@ obj-$(CONFIG_REGULATOR_PCF50633) += pcf50633-regulator.o
obj-$(CONFIG_REGULATOR_RC5T583) += rc5t583-regulator.o obj-$(CONFIG_REGULATOR_RC5T583) += rc5t583-regulator.o
obj-$(CONFIG_REGULATOR_S2MPS11) += s2mps11.o obj-$(CONFIG_REGULATOR_S2MPS11) += s2mps11.o
obj-$(CONFIG_REGULATOR_S5M8767) += s5m8767.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_TPS6105X) += tps6105x-regulator.o
obj-$(CONFIG_REGULATOR_TPS62360) += tps62360-regulator.o obj-$(CONFIG_REGULATOR_TPS62360) += tps62360-regulator.o
obj-$(CONFIG_REGULATOR_TPS65023) += tps65023-regulator.o obj-$(CONFIG_REGULATOR_TPS65023) += tps65023-regulator.o
...@@ -64,7 +66,6 @@ obj-$(CONFIG_REGULATOR_TPS65910) += tps65910-regulator.o ...@@ -64,7 +66,6 @@ obj-$(CONFIG_REGULATOR_TPS65910) += tps65910-regulator.o
obj-$(CONFIG_REGULATOR_TPS65912) += tps65912-regulator.o obj-$(CONFIG_REGULATOR_TPS65912) += tps65912-regulator.o
obj-$(CONFIG_REGULATOR_TPS80031) += tps80031-regulator.o obj-$(CONFIG_REGULATOR_TPS80031) += tps80031-regulator.o
obj-$(CONFIG_REGULATOR_TWL4030) += twl-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_VEXPRESS) += vexpress.o
obj-$(CONFIG_REGULATOR_WM831X) += wm831x-dcdc.o obj-$(CONFIG_REGULATOR_WM831X) += wm831x-dcdc.o
obj-$(CONFIG_REGULATOR_WM831X) += wm831x-isink.o obj-$(CONFIG_REGULATOR_WM831X) += wm831x-isink.o
......
...@@ -2078,6 +2078,43 @@ int regulator_list_voltage_linear(struct regulator_dev *rdev, ...@@ -2078,6 +2078,43 @@ int regulator_list_voltage_linear(struct regulator_dev *rdev,
} }
EXPORT_SYMBOL_GPL(regulator_list_voltage_linear); 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 * regulator_list_voltage_table - List voltages with table based mapping
* *
...@@ -2368,6 +2405,64 @@ int regulator_map_voltage_linear(struct regulator_dev *rdev, ...@@ -2368,6 +2405,64 @@ int regulator_map_voltage_linear(struct regulator_dev *rdev,
} }
EXPORT_SYMBOL_GPL(regulator_map_voltage_linear); 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, static int _regulator_do_set_voltage(struct regulator_dev *rdev,
int min_uV, int max_uV) int min_uV, int max_uV)
{ {
......
...@@ -62,41 +62,12 @@ static irqreturn_t wm831x_ldo_uv_irq(int irq, void *data) ...@@ -62,41 +62,12 @@ static irqreturn_t wm831x_ldo_uv_irq(int irq, void *data)
* General purpose LDOs * General purpose LDOs
*/ */
#define WM831X_GP_LDO_SELECTOR_LOW 0xe static const struct regulator_linear_range wm831x_gp_ldo_ranges[] = {
#define WM831X_GP_LDO_MAX_SELECTOR 0x1f { .min_uV = 900000, .max_uV = 1650000, .min_sel = 0, .max_sel = 14,
.uV_step = 50000 },
static int wm831x_gp_ldo_list_voltage(struct regulator_dev *rdev, { .min_uV = 1700000, .max_uV = 3300000, .min_sel = 15, .max_sel = 31,
unsigned int selector) .uV_step = 100000 },
{ };
/* 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 int wm831x_gp_ldo_set_suspend_voltage(struct regulator_dev *rdev, static int wm831x_gp_ldo_set_suspend_voltage(struct regulator_dev *rdev,
int uV) int uV)
...@@ -105,7 +76,7 @@ static int wm831x_gp_ldo_set_suspend_voltage(struct regulator_dev *rdev, ...@@ -105,7 +76,7 @@ static int wm831x_gp_ldo_set_suspend_voltage(struct regulator_dev *rdev,
struct wm831x *wm831x = ldo->wm831x; struct wm831x *wm831x = ldo->wm831x;
int sel, reg = ldo->base + WM831X_LDO_SLEEP_CONTROL; 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) if (sel < 0)
return sel; return sel;
...@@ -230,8 +201,8 @@ static unsigned int wm831x_gp_ldo_get_optimum_mode(struct regulator_dev *rdev, ...@@ -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 = { static struct regulator_ops wm831x_gp_ldo_ops = {
.list_voltage = wm831x_gp_ldo_list_voltage, .list_voltage = regulator_list_voltage_linear_range,
.map_voltage = wm831x_gp_ldo_map_voltage, .map_voltage = regulator_map_voltage_linear_range,
.get_voltage_sel = regulator_get_voltage_sel_regmap, .get_voltage_sel = regulator_get_voltage_sel_regmap,
.set_voltage_sel = regulator_set_voltage_sel_regmap, .set_voltage_sel = regulator_set_voltage_sel_regmap,
.set_suspend_voltage = wm831x_gp_ldo_set_suspend_voltage, .set_suspend_voltage = wm831x_gp_ldo_set_suspend_voltage,
...@@ -290,7 +261,7 @@ static int wm831x_gp_ldo_probe(struct platform_device *pdev) ...@@ -290,7 +261,7 @@ static int wm831x_gp_ldo_probe(struct platform_device *pdev)
ldo->desc.id = id; ldo->desc.id = id;
ldo->desc.type = REGULATOR_VOLTAGE; 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.ops = &wm831x_gp_ldo_ops;
ldo->desc.owner = THIS_MODULE; ldo->desc.owner = THIS_MODULE;
ldo->desc.vsel_reg = ldo->base + WM831X_LDO_ON_CONTROL; ldo->desc.vsel_reg = ldo->base + WM831X_LDO_ON_CONTROL;
...@@ -299,6 +270,8 @@ static int wm831x_gp_ldo_probe(struct platform_device *pdev) ...@@ -299,6 +270,8 @@ static int wm831x_gp_ldo_probe(struct platform_device *pdev)
ldo->desc.enable_mask = 1 << id; ldo->desc.enable_mask = 1 << id;
ldo->desc.bypass_reg = ldo->base; ldo->desc.bypass_reg = ldo->base;
ldo->desc.bypass_mask = WM831X_LDO1_SWI; 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; config.dev = pdev->dev.parent;
if (pdata) if (pdata)
...@@ -358,43 +331,12 @@ static struct platform_driver wm831x_gp_ldo_driver = { ...@@ -358,43 +331,12 @@ static struct platform_driver wm831x_gp_ldo_driver = {
* Analogue LDOs * Analogue LDOs
*/ */
static const struct regulator_linear_range wm831x_aldo_ranges[] = {
#define WM831X_ALDO_SELECTOR_LOW 0xc { .min_uV = 1000000, .max_uV = 1650000, .min_sel = 0, .max_sel = 12,
#define WM831X_ALDO_MAX_SELECTOR 0x1f .uV_step = 50000 },
{ .min_uV = 1700000, .max_uV = 3500000, .min_sel = 13, .max_sel = 31,
static int wm831x_aldo_list_voltage(struct regulator_dev *rdev, .uV_step = 100000 },
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 int wm831x_aldo_set_suspend_voltage(struct regulator_dev *rdev, static int wm831x_aldo_set_suspend_voltage(struct regulator_dev *rdev,
int uV) int uV)
...@@ -403,7 +345,7 @@ static int wm831x_aldo_set_suspend_voltage(struct regulator_dev *rdev, ...@@ -403,7 +345,7 @@ static int wm831x_aldo_set_suspend_voltage(struct regulator_dev *rdev,
struct wm831x *wm831x = ldo->wm831x; struct wm831x *wm831x = ldo->wm831x;
int sel, reg = ldo->base + WM831X_LDO_SLEEP_CONTROL; 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) if (sel < 0)
return sel; return sel;
...@@ -486,8 +428,8 @@ static int wm831x_aldo_get_status(struct regulator_dev *rdev) ...@@ -486,8 +428,8 @@ static int wm831x_aldo_get_status(struct regulator_dev *rdev)
} }
static struct regulator_ops wm831x_aldo_ops = { static struct regulator_ops wm831x_aldo_ops = {
.list_voltage = wm831x_aldo_list_voltage, .list_voltage = regulator_list_voltage_linear_range,
.map_voltage = wm831x_aldo_map_voltage, .map_voltage = regulator_map_voltage_linear_range,
.get_voltage_sel = regulator_get_voltage_sel_regmap, .get_voltage_sel = regulator_get_voltage_sel_regmap,
.set_voltage_sel = regulator_set_voltage_sel_regmap, .set_voltage_sel = regulator_set_voltage_sel_regmap,
.set_suspend_voltage = wm831x_aldo_set_suspend_voltage, .set_suspend_voltage = wm831x_aldo_set_suspend_voltage,
...@@ -545,7 +487,9 @@ static int wm831x_aldo_probe(struct platform_device *pdev) ...@@ -545,7 +487,9 @@ static int wm831x_aldo_probe(struct platform_device *pdev)
ldo->desc.id = id; ldo->desc.id = id;
ldo->desc.type = REGULATOR_VOLTAGE; 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.ops = &wm831x_aldo_ops;
ldo->desc.owner = THIS_MODULE; ldo->desc.owner = THIS_MODULE;
ldo->desc.vsel_reg = ldo->base + WM831X_LDO_ON_CONTROL; ldo->desc.vsel_reg = ldo->base + WM831X_LDO_ON_CONTROL;
......
...@@ -542,41 +542,12 @@ static int wm8350_dcdc_set_suspend_mode(struct regulator_dev *rdev, ...@@ -542,41 +542,12 @@ static int wm8350_dcdc_set_suspend_mode(struct regulator_dev *rdev,
return 0; return 0;
} }
static int wm8350_ldo_list_voltage(struct regulator_dev *rdev, static const struct regulator_linear_range wm8350_ldo_ranges[] = {
unsigned selector) { .min_uV = 900000, .max_uV = 1750000, .min_sel = 0, .max_sel = 15,
{ .uV_step = 50000 },
if (selector > WM8350_LDO1_VSEL_MASK) { .min_uV = 1800000, .max_uV = 3300000, .min_sel = 16, .max_sel = 31,
return -EINVAL; .uV_step = 100000 },
};
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 int wm8350_ldo_set_suspend_voltage(struct regulator_dev *rdev, int uV) 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) ...@@ -603,7 +574,7 @@ static int wm8350_ldo_set_suspend_voltage(struct regulator_dev *rdev, int uV)
return -EINVAL; return -EINVAL;
} }
sel = wm8350_ldo_map_voltage(rdev, uV, uV); sel = regulator_map_voltage_linear_range(rdev, uV, uV);
if (sel < 0) if (sel < 0)
return -EINVAL; return -EINVAL;
...@@ -998,10 +969,10 @@ static struct regulator_ops wm8350_dcdc2_5_ops = { ...@@ -998,10 +969,10 @@ static struct regulator_ops wm8350_dcdc2_5_ops = {
}; };
static struct regulator_ops wm8350_ldo_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, .set_voltage_sel = regulator_set_voltage_sel_regmap,
.get_voltage_sel = regulator_get_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, .enable = regulator_enable_regmap,
.disable = regulator_disable_regmap, .disable = regulator_disable_regmap,
.is_enabled = regulator_is_enabled_regmap, .is_enabled = regulator_is_enabled_regmap,
...@@ -1108,6 +1079,8 @@ static const struct regulator_desc wm8350_reg[NUM_WM8350_REGULATORS] = { ...@@ -1108,6 +1079,8 @@ static const struct regulator_desc wm8350_reg[NUM_WM8350_REGULATORS] = {
.irq = WM8350_IRQ_UV_LDO1, .irq = WM8350_IRQ_UV_LDO1,
.type = REGULATOR_VOLTAGE, .type = REGULATOR_VOLTAGE,
.n_voltages = WM8350_LDO1_VSEL_MASK + 1, .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_reg = WM8350_LDO1_CONTROL,
.vsel_mask = WM8350_LDO1_VSEL_MASK, .vsel_mask = WM8350_LDO1_VSEL_MASK,
.enable_reg = WM8350_DCDC_LDO_REQUESTED, .enable_reg = WM8350_DCDC_LDO_REQUESTED,
...@@ -1121,6 +1094,8 @@ static const struct regulator_desc wm8350_reg[NUM_WM8350_REGULATORS] = { ...@@ -1121,6 +1094,8 @@ static const struct regulator_desc wm8350_reg[NUM_WM8350_REGULATORS] = {
.irq = WM8350_IRQ_UV_LDO2, .irq = WM8350_IRQ_UV_LDO2,
.type = REGULATOR_VOLTAGE, .type = REGULATOR_VOLTAGE,
.n_voltages = WM8350_LDO2_VSEL_MASK + 1, .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_reg = WM8350_LDO2_CONTROL,
.vsel_mask = WM8350_LDO2_VSEL_MASK, .vsel_mask = WM8350_LDO2_VSEL_MASK,
.enable_reg = WM8350_DCDC_LDO_REQUESTED, .enable_reg = WM8350_DCDC_LDO_REQUESTED,
...@@ -1134,6 +1109,8 @@ static const struct regulator_desc wm8350_reg[NUM_WM8350_REGULATORS] = { ...@@ -1134,6 +1109,8 @@ static const struct regulator_desc wm8350_reg[NUM_WM8350_REGULATORS] = {
.irq = WM8350_IRQ_UV_LDO3, .irq = WM8350_IRQ_UV_LDO3,
.type = REGULATOR_VOLTAGE, .type = REGULATOR_VOLTAGE,
.n_voltages = WM8350_LDO3_VSEL_MASK + 1, .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_reg = WM8350_LDO3_CONTROL,
.vsel_mask = WM8350_LDO3_VSEL_MASK, .vsel_mask = WM8350_LDO3_VSEL_MASK,
.enable_reg = WM8350_DCDC_LDO_REQUESTED, .enable_reg = WM8350_DCDC_LDO_REQUESTED,
...@@ -1147,6 +1124,8 @@ static const struct regulator_desc wm8350_reg[NUM_WM8350_REGULATORS] = { ...@@ -1147,6 +1124,8 @@ static const struct regulator_desc wm8350_reg[NUM_WM8350_REGULATORS] = {
.irq = WM8350_IRQ_UV_LDO4, .irq = WM8350_IRQ_UV_LDO4,
.type = REGULATOR_VOLTAGE, .type = REGULATOR_VOLTAGE,
.n_voltages = WM8350_LDO4_VSEL_MASK + 1, .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_reg = WM8350_LDO4_CONTROL,
.vsel_mask = WM8350_LDO4_VSEL_MASK, .vsel_mask = WM8350_LDO4_VSEL_MASK,
.enable_reg = WM8350_DCDC_LDO_REQUESTED, .enable_reg = WM8350_DCDC_LDO_REQUESTED,
......
...@@ -19,47 +19,21 @@ ...@@ -19,47 +19,21 @@
#include <linux/regulator/driver.h> #include <linux/regulator/driver.h>
#include <linux/mfd/wm8400-private.h> #include <linux/mfd/wm8400-private.h>
static int wm8400_ldo_list_voltage(struct regulator_dev *dev, static const struct regulator_linear_range wm8400_ldo_ranges[] = {
unsigned selector) { .min_uV = 900000, .max_uV = 1600000, .min_sel = 0, .max_sel = 14,
{ .uV_step = 50000 },
if (selector > WM8400_LDO1_VSEL_MASK) { .min_uV = 1700000, .max_uV = 3300000, .min_sel = 15, .max_sel = 31,
return -EINVAL; .uV_step = 100000 },
};
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 struct regulator_ops wm8400_ldo_ops = { static struct regulator_ops wm8400_ldo_ops = {
.is_enabled = regulator_is_enabled_regmap, .is_enabled = regulator_is_enabled_regmap,
.enable = regulator_enable_regmap, .enable = regulator_enable_regmap,
.disable = regulator_disable_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, .get_voltage_sel = regulator_get_voltage_sel_regmap,
.set_voltage_sel = regulator_set_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) static unsigned int wm8400_dcdc_get_mode(struct regulator_dev *dev)
...@@ -155,6 +129,8 @@ static struct regulator_desc regulators[] = { ...@@ -155,6 +129,8 @@ static struct regulator_desc regulators[] = {
.enable_reg = WM8400_LDO1_CONTROL, .enable_reg = WM8400_LDO1_CONTROL,
.enable_mask = WM8400_LDO1_ENA, .enable_mask = WM8400_LDO1_ENA,
.n_voltages = WM8400_LDO1_VSEL_MASK + 1, .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_reg = WM8400_LDO1_CONTROL,
.vsel_mask = WM8400_LDO1_VSEL_MASK, .vsel_mask = WM8400_LDO1_VSEL_MASK,
.type = REGULATOR_VOLTAGE, .type = REGULATOR_VOLTAGE,
...@@ -167,6 +143,8 @@ static struct regulator_desc regulators[] = { ...@@ -167,6 +143,8 @@ static struct regulator_desc regulators[] = {
.enable_reg = WM8400_LDO2_CONTROL, .enable_reg = WM8400_LDO2_CONTROL,
.enable_mask = WM8400_LDO2_ENA, .enable_mask = WM8400_LDO2_ENA,
.n_voltages = WM8400_LDO2_VSEL_MASK + 1, .n_voltages = WM8400_LDO2_VSEL_MASK + 1,
.linear_ranges = wm8400_ldo_ranges,
.n_linear_ranges = ARRAY_SIZE(wm8400_ldo_ranges),
.type = REGULATOR_VOLTAGE, .type = REGULATOR_VOLTAGE,
.vsel_reg = WM8400_LDO2_CONTROL, .vsel_reg = WM8400_LDO2_CONTROL,
.vsel_mask = WM8400_LDO2_VSEL_MASK, .vsel_mask = WM8400_LDO2_VSEL_MASK,
...@@ -179,6 +157,8 @@ static struct regulator_desc regulators[] = { ...@@ -179,6 +157,8 @@ static struct regulator_desc regulators[] = {
.enable_reg = WM8400_LDO3_CONTROL, .enable_reg = WM8400_LDO3_CONTROL,
.enable_mask = WM8400_LDO3_ENA, .enable_mask = WM8400_LDO3_ENA,
.n_voltages = WM8400_LDO3_VSEL_MASK + 1, .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_reg = WM8400_LDO3_CONTROL,
.vsel_mask = WM8400_LDO3_VSEL_MASK, .vsel_mask = WM8400_LDO3_VSEL_MASK,
.type = REGULATOR_VOLTAGE, .type = REGULATOR_VOLTAGE,
...@@ -191,6 +171,8 @@ static struct regulator_desc regulators[] = { ...@@ -191,6 +171,8 @@ static struct regulator_desc regulators[] = {
.enable_reg = WM8400_LDO4_CONTROL, .enable_reg = WM8400_LDO4_CONTROL,
.enable_mask = WM8400_LDO4_ENA, .enable_mask = WM8400_LDO4_ENA,
.n_voltages = WM8400_LDO4_VSEL_MASK + 1, .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_reg = WM8400_LDO4_CONTROL,
.vsel_mask = WM8400_LDO4_VSEL_MASK, .vsel_mask = WM8400_LDO4_VSEL_MASK,
.type = REGULATOR_VOLTAGE, .type = REGULATOR_VOLTAGE,
......
...@@ -39,6 +39,24 @@ enum regulator_status { ...@@ -39,6 +39,24 @@ enum regulator_status {
REGULATOR_STATUS_UNDEFINED, 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. * struct regulator_ops - regulator operations.
* *
...@@ -223,6 +241,9 @@ struct regulator_desc { ...@@ -223,6 +241,9 @@ struct regulator_desc {
unsigned int linear_min_sel; unsigned int linear_min_sel;
unsigned int ramp_delay; unsigned int ramp_delay;
const struct regulator_linear_range *linear_ranges;
int n_linear_ranges;
const unsigned int *volt_table; const unsigned int *volt_table;
unsigned int vsel_reg; unsigned int vsel_reg;
...@@ -326,10 +347,14 @@ int regulator_mode_to_status(unsigned int); ...@@ -326,10 +347,14 @@ int regulator_mode_to_status(unsigned int);
int regulator_list_voltage_linear(struct regulator_dev *rdev, int regulator_list_voltage_linear(struct regulator_dev *rdev,
unsigned int selector); 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, int regulator_list_voltage_table(struct regulator_dev *rdev,
unsigned int selector); unsigned int selector);
int regulator_map_voltage_linear(struct regulator_dev *rdev, int regulator_map_voltage_linear(struct regulator_dev *rdev,
int min_uV, int max_uV); 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 regulator_map_voltage_iterate(struct regulator_dev *rdev,
int min_uV, int max_uV); int min_uV, int max_uV);
int regulator_map_voltage_ascend(struct regulator_dev *rdev, int regulator_map_voltage_ascend(struct regulator_dev *rdev,
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment