Merge branches 'topic/tps51632', 'topic/tps80031', 'topic/vexpress', 'topic/max8925', 'topic/gpio' and 'topic/tps65090' of git://git.kernel.org/pub/scm/linux/kernel/git/broonie/regulator into regulator-hotplug
This commit is contained in:
commit
f86221d2b9
|
@ -0,0 +1,37 @@
|
|||
GPIO controlled regulators
|
||||
|
||||
Required properties:
|
||||
- compatible : Must be "regulator-gpio".
|
||||
- states : Selection of available voltages and GPIO configs.
|
||||
if there are no states, then use a fixed regulator
|
||||
|
||||
Optional properties:
|
||||
- enable-gpio : GPIO to use to enable/disable the regulator.
|
||||
- gpios : GPIO group used to control voltage.
|
||||
- startup-delay-us : Startup time in microseconds.
|
||||
- enable-active-high : Polarity of GPIO is active high (default is low).
|
||||
|
||||
Any property defined as part of the core regulator binding defined in
|
||||
regulator.txt can also be used.
|
||||
|
||||
Example:
|
||||
|
||||
mmciv: gpio-regulator {
|
||||
compatible = "regulator-gpio";
|
||||
|
||||
regulator-name = "mmci-gpio-supply";
|
||||
regulator-min-microvolt = <1800000>;
|
||||
regulator-max-microvolt = <2600000>;
|
||||
regulator-boot-on;
|
||||
|
||||
enable-gpio = <&gpio0 23 0x4>;
|
||||
gpios = <&gpio0 24 0x4
|
||||
&gpio0 25 0x4>;
|
||||
states = <1800000 0x3
|
||||
2200000 0x2
|
||||
2600000 0x1
|
||||
2900000 0x0>;
|
||||
|
||||
startup-delay-us = <100000>;
|
||||
enable-active-high;
|
||||
};
|
|
@ -0,0 +1,40 @@
|
|||
Max8925 Voltage regulators
|
||||
|
||||
Required nodes:
|
||||
-nodes:
|
||||
- SDV1 for SDV SDV1
|
||||
- SDV2 for SDV SDV2
|
||||
- SDV3 for SDV SDV3
|
||||
- LDO1 for LDO LDO1
|
||||
- LDO2 for LDO LDO2
|
||||
- LDO3 for LDO LDO3
|
||||
- LDO4 for LDO LDO4
|
||||
- LDO5 for LDO LDO5
|
||||
- LDO6 for LDO LDO6
|
||||
- LDO7 for LDO LDO7
|
||||
- LDO8 for LDO LDO8
|
||||
- LDO9 for LDO LDO9
|
||||
- LDO10 for LDO LDO10
|
||||
- LDO11 for LDO LDO11
|
||||
- LDO12 for LDO LDO12
|
||||
- LDO13 for LDO LDO13
|
||||
- LDO14 for LDO LDO14
|
||||
- LDO15 for LDO LDO15
|
||||
- LDO16 for LDO LDO16
|
||||
- LDO17 for LDO LDO17
|
||||
- LDO18 for LDO LDO18
|
||||
- LDO19 for LDO LDO19
|
||||
- LDO20 for LDO LDO20
|
||||
|
||||
Optional properties:
|
||||
- Any optional property defined in bindings/regulator/regulator.txt
|
||||
|
||||
Example:
|
||||
|
||||
SDV1 {
|
||||
regulator-min-microvolt = <637500>;
|
||||
regulator-max-microvolt = <1425000>;
|
||||
regulator-boot-on;
|
||||
regulator-always-on;
|
||||
};
|
||||
|
|
@ -0,0 +1,32 @@
|
|||
Versatile Express voltage regulators
|
||||
------------------------------------
|
||||
|
||||
Requires node properties:
|
||||
- "compatible" value: "arm,vexpress-volt"
|
||||
- "arm,vexpress-sysreg,func" when controlled via vexpress-sysreg
|
||||
(see Documentation/devicetree/bindings/arm/vexpress-sysreg.txt
|
||||
for more details)
|
||||
|
||||
Required regulator properties:
|
||||
- "regulator-name"
|
||||
- "regulator-always-on"
|
||||
|
||||
Optional regulator properties:
|
||||
- "regulator-min-microvolt"
|
||||
- "regulator-max-microvolt"
|
||||
|
||||
See Documentation/devicetree/bindings/regulator/regulator.txt
|
||||
for more details about the regulator properties.
|
||||
|
||||
When no "regulator-[min|max]-microvolt" properties are defined,
|
||||
the device is treated as fixed (or rather "read-only") regulator.
|
||||
|
||||
Example:
|
||||
volt@0 {
|
||||
compatible = "arm,vexpress-volt";
|
||||
arm,vexpress-sysreg,func = <2 0>;
|
||||
regulator-name = "Cores";
|
||||
regulator-min-microvolt = <800000>;
|
||||
regulator-max-microvolt = <1050000>;
|
||||
regulator-always-on;
|
||||
};
|
|
@ -335,6 +335,17 @@ config REGULATOR_PALMAS
|
|||
on the muxing. This is handled automatically in the driver by
|
||||
reading the mux info from OTP.
|
||||
|
||||
config REGULATOR_TPS51632
|
||||
tristate "TI TPS51632 Power Regulator"
|
||||
depends on I2C
|
||||
select REGMAP_I2C
|
||||
help
|
||||
This driver supports TPS51632 voltage regulator chip.
|
||||
The TPS51632 is 3-2-1 Phase D-Cap+ Step Down Driverless Controller
|
||||
with Serial VID control and DVFS.
|
||||
The voltage output can be configure through I2C interface or PWM
|
||||
interface.
|
||||
|
||||
config REGULATOR_TPS6105X
|
||||
tristate "TI TPS6105X Power regulators"
|
||||
depends on TPS6105X
|
||||
|
@ -415,6 +426,15 @@ config REGULATOR_TPS65912
|
|||
help
|
||||
This driver supports TPS65912 voltage regulator chip.
|
||||
|
||||
config REGULATOR_TPS80031
|
||||
tristate "TI TPS80031/TPS80032 power regualtor driver"
|
||||
depends on MFD_TPS80031
|
||||
help
|
||||
TPS80031/ TPS80032 Fully Integrated Power Management with Power
|
||||
Path and Battery Charger. It has 5 configurable step-down
|
||||
converters, 11 general purpose LDOs, VBUS generator and digital
|
||||
output to control regulators.
|
||||
|
||||
config REGULATOR_TWL4030
|
||||
bool "TI TWL4030/TWL5030/TWL6030/TPS659x0 PMIC"
|
||||
depends on TWL4030_CORE
|
||||
|
@ -422,6 +442,13 @@ config REGULATOR_TWL4030
|
|||
This driver supports the voltage regulators provided by
|
||||
this family of companion chips.
|
||||
|
||||
config REGULATOR_VEXPRESS
|
||||
tristate "Versatile Express regulators"
|
||||
depends on VEXPRESS_CONFIG
|
||||
help
|
||||
This driver provides support for voltage regulators available
|
||||
on the ARM Ltd's Versatile Express platform.
|
||||
|
||||
config REGULATOR_WM831X
|
||||
tristate "Wolfson Microelectronics WM831x PMIC regulators"
|
||||
depends on MFD_WM831X
|
||||
|
|
|
@ -41,6 +41,7 @@ obj-$(CONFIG_REGULATOR_MC13783) += mc13783-regulator.o
|
|||
obj-$(CONFIG_REGULATOR_MC13892) += mc13892-regulator.o
|
||||
obj-$(CONFIG_REGULATOR_MC13XXX_CORE) += mc13xxx-regulator-core.o
|
||||
obj-$(CONFIG_REGULATOR_PALMAS) += palmas-regulator.o
|
||||
obj-$(CONFIG_REGULATOR_TPS51632) += tps51632-regulator.o
|
||||
obj-$(CONFIG_REGULATOR_PCAP) += pcap-regulator.o
|
||||
obj-$(CONFIG_REGULATOR_PCF50633) += pcf50633-regulator.o
|
||||
obj-$(CONFIG_REGULATOR_RC5T583) += rc5t583-regulator.o
|
||||
|
@ -56,7 +57,9 @@ obj-$(CONFIG_REGULATOR_TPS6524X) += tps6524x-regulator.o
|
|||
obj-$(CONFIG_REGULATOR_TPS6586X) += tps6586x-regulator.o
|
||||
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_VEXPRESS) += vexpress.o
|
||||
obj-$(CONFIG_REGULATOR_WM831X) += wm831x-dcdc.o
|
||||
obj-$(CONFIG_REGULATOR_WM831X) += wm831x-isink.o
|
||||
obj-$(CONFIG_REGULATOR_WM831X) += wm831x-ldo.o
|
||||
|
|
|
@ -1985,6 +1985,11 @@ int regulator_is_supported_voltage(struct regulator *regulator,
|
|||
return ret;
|
||||
}
|
||||
|
||||
/* Any voltage within constrains range is fine? */
|
||||
if (rdev->desc->continuous_voltage_range)
|
||||
return min_uV >= rdev->constraints->min_uV &&
|
||||
max_uV <= rdev->constraints->max_uV;
|
||||
|
||||
ret = regulator_count_voltages(regulator);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
|
|
@ -28,9 +28,12 @@
|
|||
#include <linux/platform_device.h>
|
||||
#include <linux/regulator/driver.h>
|
||||
#include <linux/regulator/machine.h>
|
||||
#include <linux/regulator/of_regulator.h>
|
||||
#include <linux/regulator/gpio-regulator.h>
|
||||
#include <linux/gpio.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/of.h>
|
||||
#include <linux/of_gpio.h>
|
||||
|
||||
struct gpio_regulator_data {
|
||||
struct regulator_desc desc;
|
||||
|
@ -129,6 +132,89 @@ static struct regulator_ops gpio_regulator_voltage_ops = {
|
|||
.list_voltage = gpio_regulator_list_voltage,
|
||||
};
|
||||
|
||||
struct gpio_regulator_config *
|
||||
of_get_gpio_regulator_config(struct device *dev, struct device_node *np)
|
||||
{
|
||||
struct gpio_regulator_config *config;
|
||||
struct property *prop;
|
||||
const char *regtype;
|
||||
int proplen, gpio, i;
|
||||
|
||||
config = devm_kzalloc(dev,
|
||||
sizeof(struct gpio_regulator_config),
|
||||
GFP_KERNEL);
|
||||
if (!config)
|
||||
return ERR_PTR(-ENOMEM);
|
||||
|
||||
config->init_data = of_get_regulator_init_data(dev, np);
|
||||
if (!config->init_data)
|
||||
return ERR_PTR(-EINVAL);
|
||||
|
||||
config->supply_name = config->init_data->constraints.name;
|
||||
|
||||
if (of_property_read_bool(np, "enable-active-high"))
|
||||
config->enable_high = true;
|
||||
|
||||
if (of_property_read_bool(np, "enable-at-boot"))
|
||||
config->enabled_at_boot = true;
|
||||
|
||||
of_property_read_u32(np, "startup-delay-us", &config->startup_delay);
|
||||
|
||||
config->enable_gpio = of_get_named_gpio(np, "enable-gpio", 0);
|
||||
|
||||
/* Fetch GPIOs. */
|
||||
for (i = 0; ; i++)
|
||||
if (of_get_named_gpio(np, "gpios", i) < 0)
|
||||
break;
|
||||
config->nr_gpios = i;
|
||||
|
||||
config->gpios = devm_kzalloc(dev,
|
||||
sizeof(struct gpio) * config->nr_gpios,
|
||||
GFP_KERNEL);
|
||||
if (!config->gpios)
|
||||
return ERR_PTR(-ENOMEM);
|
||||
|
||||
for (i = 0; config->nr_gpios; i++) {
|
||||
gpio = of_get_named_gpio(np, "gpios", i);
|
||||
if (gpio < 0)
|
||||
break;
|
||||
config->gpios[i].gpio = gpio;
|
||||
}
|
||||
|
||||
/* Fetch states. */
|
||||
prop = of_find_property(np, "states", NULL);
|
||||
if (!prop) {
|
||||
dev_err(dev, "No 'states' property found\n");
|
||||
return ERR_PTR(-EINVAL);
|
||||
}
|
||||
|
||||
proplen = prop->length / sizeof(int);
|
||||
|
||||
config->states = devm_kzalloc(dev,
|
||||
sizeof(struct gpio_regulator_state)
|
||||
* (proplen / 2),
|
||||
GFP_KERNEL);
|
||||
if (!config->states)
|
||||
return ERR_PTR(-ENOMEM);
|
||||
|
||||
for (i = 0; i < proplen / 2; i++) {
|
||||
config->states[i].value =
|
||||
be32_to_cpup((int *)prop->value + (i * 2));
|
||||
config->states[i].gpios =
|
||||
be32_to_cpup((int *)prop->value + (i * 2 + 1));
|
||||
}
|
||||
config->nr_states = i;
|
||||
|
||||
of_property_read_string(np, "regulator-type", ®type);
|
||||
|
||||
if (!strncmp("voltage", regtype, 7))
|
||||
config->type = REGULATOR_VOLTAGE;
|
||||
else if (!strncmp("current", regtype, 7))
|
||||
config->type = REGULATOR_CURRENT;
|
||||
|
||||
return config;
|
||||
}
|
||||
|
||||
static struct regulator_ops gpio_regulator_current_ops = {
|
||||
.get_current_limit = gpio_regulator_get_value,
|
||||
.set_current_limit = gpio_regulator_set_current_limit,
|
||||
|
@ -137,10 +223,17 @@ static struct regulator_ops gpio_regulator_current_ops = {
|
|||
static int __devinit gpio_regulator_probe(struct platform_device *pdev)
|
||||
{
|
||||
struct gpio_regulator_config *config = pdev->dev.platform_data;
|
||||
struct device_node *np = pdev->dev.of_node;
|
||||
struct gpio_regulator_data *drvdata;
|
||||
struct regulator_config cfg = { };
|
||||
int ptr, ret, state;
|
||||
|
||||
if (np) {
|
||||
config = of_get_gpio_regulator_config(&pdev->dev, np);
|
||||
if (IS_ERR(config))
|
||||
return PTR_ERR(config);
|
||||
}
|
||||
|
||||
drvdata = devm_kzalloc(&pdev->dev, sizeof(struct gpio_regulator_data),
|
||||
GFP_KERNEL);
|
||||
if (drvdata == NULL) {
|
||||
|
@ -215,6 +308,7 @@ static int __devinit gpio_regulator_probe(struct platform_device *pdev)
|
|||
cfg.dev = &pdev->dev;
|
||||
cfg.init_data = config->init_data;
|
||||
cfg.driver_data = drvdata;
|
||||
cfg.of_node = np;
|
||||
|
||||
if (config->enable_gpio >= 0)
|
||||
cfg.ena_gpio = config->enable_gpio;
|
||||
|
@ -270,12 +364,18 @@ static int __devexit gpio_regulator_remove(struct platform_device *pdev)
|
|||
return 0;
|
||||
}
|
||||
|
||||
static const struct of_device_id regulator_gpio_of_match[] __devinitconst = {
|
||||
{ .compatible = "regulator-gpio", },
|
||||
{},
|
||||
};
|
||||
|
||||
static struct platform_driver gpio_regulator_driver = {
|
||||
.probe = gpio_regulator_probe,
|
||||
.remove = __devexit_p(gpio_regulator_remove),
|
||||
.driver = {
|
||||
.name = "gpio-regulator",
|
||||
.owner = THIS_MODULE,
|
||||
.of_match_table = regulator_gpio_of_match,
|
||||
},
|
||||
};
|
||||
|
||||
|
|
|
@ -17,6 +17,8 @@
|
|||
#include <linux/regulator/driver.h>
|
||||
#include <linux/regulator/machine.h>
|
||||
#include <linux/mfd/max8925.h>
|
||||
#include <linux/of.h>
|
||||
#include <linux/regulator/of_regulator.h>
|
||||
|
||||
#define SD1_DVM_VMIN 850000
|
||||
#define SD1_DVM_VMAX 1000000
|
||||
|
@ -187,6 +189,34 @@ static struct regulator_ops max8925_regulator_ldo_ops = {
|
|||
.enable_reg = MAX8925_LDOCTL##_id, \
|
||||
}
|
||||
|
||||
#ifdef CONFIG_OF
|
||||
static struct of_regulator_match max8925_regulator_matches[] = {
|
||||
{ .name = "SDV1",},
|
||||
{ .name = "SDV2",},
|
||||
{ .name = "SDV3",},
|
||||
{ .name = "LDO1",},
|
||||
{ .name = "LDO2",},
|
||||
{ .name = "LDO3",},
|
||||
{ .name = "LDO4",},
|
||||
{ .name = "LDO5",},
|
||||
{ .name = "LDO6",},
|
||||
{ .name = "LDO7",},
|
||||
{ .name = "LDO8",},
|
||||
{ .name = "LDO9",},
|
||||
{ .name = "LDO10",},
|
||||
{ .name = "LDO11",},
|
||||
{ .name = "LDO12",},
|
||||
{ .name = "LDO13",},
|
||||
{ .name = "LDO14",},
|
||||
{ .name = "LDO15",},
|
||||
{ .name = "LDO16",},
|
||||
{ .name = "LDO17",},
|
||||
{ .name = "LDO18",},
|
||||
{ .name = "LDO19",},
|
||||
{ .name = "LDO20",},
|
||||
};
|
||||
#endif
|
||||
|
||||
static struct max8925_regulator_info max8925_regulator_info[] = {
|
||||
MAX8925_SDV(1, 637.5, 1425, 12.5),
|
||||
MAX8925_SDV(2, 650, 2225, 25),
|
||||
|
@ -214,6 +244,36 @@ static struct max8925_regulator_info max8925_regulator_info[] = {
|
|||
MAX8925_LDO(20, 750, 3900, 50),
|
||||
};
|
||||
|
||||
#ifdef CONFIG_OF
|
||||
static int max8925_regulator_dt_init(struct platform_device *pdev,
|
||||
struct max8925_regulator_info *info,
|
||||
struct regulator_config *config,
|
||||
int ridx)
|
||||
{
|
||||
struct device_node *nproot, *np;
|
||||
int rcount;
|
||||
nproot = pdev->dev.parent->of_node;
|
||||
if (!nproot)
|
||||
return -ENODEV;
|
||||
np = of_find_node_by_name(nproot, "regulators");
|
||||
if (!np) {
|
||||
dev_err(&pdev->dev, "failed to find regulators node\n");
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
rcount = of_regulator_match(&pdev->dev, np,
|
||||
&max8925_regulator_matches[ridx], 1);
|
||||
if (rcount < 0)
|
||||
return -ENODEV;
|
||||
config->init_data = max8925_regulator_matches[ridx].init_data;
|
||||
config->of_node = max8925_regulator_matches[ridx].of_node;
|
||||
|
||||
return 0;
|
||||
}
|
||||
#else
|
||||
#define max8925_regulator_dt_init(w, x, y, z) (-1)
|
||||
#endif
|
||||
|
||||
static int __devinit max8925_regulator_probe(struct platform_device *pdev)
|
||||
{
|
||||
struct max8925_chip *chip = dev_get_drvdata(pdev->dev.parent);
|
||||
|
@ -222,7 +282,7 @@ static int __devinit max8925_regulator_probe(struct platform_device *pdev)
|
|||
struct max8925_regulator_info *ri;
|
||||
struct resource *res;
|
||||
struct regulator_dev *rdev;
|
||||
int i;
|
||||
int i, regulator_idx;
|
||||
|
||||
res = platform_get_resource(pdev, IORESOURCE_REG, 0);
|
||||
if (!res) {
|
||||
|
@ -231,9 +291,12 @@ static int __devinit max8925_regulator_probe(struct platform_device *pdev)
|
|||
}
|
||||
for (i = 0; i < ARRAY_SIZE(max8925_regulator_info); i++) {
|
||||
ri = &max8925_regulator_info[i];
|
||||
if (ri->vol_reg == res->start)
|
||||
if (ri->vol_reg == res->start) {
|
||||
regulator_idx = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (i == ARRAY_SIZE(max8925_regulator_info)) {
|
||||
dev_err(&pdev->dev, "Failed to find regulator %llu\n",
|
||||
(unsigned long long)res->start);
|
||||
|
@ -243,9 +306,12 @@ static int __devinit max8925_regulator_probe(struct platform_device *pdev)
|
|||
ri->chip = chip;
|
||||
|
||||
config.dev = &pdev->dev;
|
||||
config.init_data = pdata;
|
||||
config.driver_data = ri;
|
||||
|
||||
if (max8925_regulator_dt_init(pdev, ri, &config, regulator_idx))
|
||||
if (pdata)
|
||||
config.init_data = pdata;
|
||||
|
||||
rdev = regulator_register(&ri->desc, &config);
|
||||
if (IS_ERR(rdev)) {
|
||||
dev_err(&pdev->dev, "failed to register regulator %s\n",
|
||||
|
|
|
@ -0,0 +1,332 @@
|
|||
/*
|
||||
* tps51632-regulator.c -- TI TPS51632
|
||||
*
|
||||
* Regulator driver for TPS51632 3-2-1 Phase D-Cap Step Down Driverless
|
||||
* Controller with serial VID control and DVFS.
|
||||
*
|
||||
* Copyright (c) 2012, NVIDIA Corporation.
|
||||
*
|
||||
* Author: Laxman Dewangan <ldewangan@nvidia.com>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License as
|
||||
* published by the Free Software Foundation version 2.
|
||||
*
|
||||
* This program is distributed "as is" WITHOUT ANY WARRANTY of any kind,
|
||||
* whether express or implied; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* General Public License for more details.
|
||||
*
|
||||
* 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
|
||||
*/
|
||||
|
||||
#include <linux/err.h>
|
||||
#include <linux/i2c.h>
|
||||
#include <linux/init.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/regmap.h>
|
||||
#include <linux/regulator/driver.h>
|
||||
#include <linux/regulator/machine.h>
|
||||
#include <linux/regulator/tps51632-regulator.h>
|
||||
#include <linux/slab.h>
|
||||
|
||||
/* Register definitions */
|
||||
#define TPS51632_VOLTAGE_SELECT_REG 0x0
|
||||
#define TPS51632_VOLTAGE_BASE_REG 0x1
|
||||
#define TPS51632_OFFSET_REG 0x2
|
||||
#define TPS51632_IMON_REG 0x3
|
||||
#define TPS51632_VMAX_REG 0x4
|
||||
#define TPS51632_DVFS_CONTROL_REG 0x5
|
||||
#define TPS51632_POWER_STATE_REG 0x6
|
||||
#define TPS51632_SLEW_REGS 0x7
|
||||
#define TPS51632_FAULT_REG 0x14
|
||||
|
||||
#define TPS51632_MAX_REG 0x15
|
||||
|
||||
#define TPS51632_VOUT_MASK 0x7F
|
||||
#define TPS51632_VOUT_OFFSET_MASK 0x1F
|
||||
#define TPS51632_VMAX_MASK 0x7F
|
||||
#define TPS51632_VMAX_LOCK 0x80
|
||||
|
||||
/* TPS51632_DVFS_CONTROL_REG */
|
||||
#define TPS51632_DVFS_PWMEN 0x1
|
||||
#define TPS51632_DVFS_STEP_20 0x2
|
||||
#define TPS51632_DVFS_VMAX_PG 0x4
|
||||
#define TPS51632_DVFS_PWMRST 0x8
|
||||
#define TPS51632_DVFS_OCA_EN 0x10
|
||||
#define TPS51632_DVFS_FCCM 0x20
|
||||
|
||||
/* TPS51632_POWER_STATE_REG */
|
||||
#define TPS51632_POWER_STATE_MASK 0x03
|
||||
#define TPS51632_POWER_STATE_MULTI_PHASE_CCM 0x0
|
||||
#define TPS51632_POWER_STATE_SINGLE_PHASE_CCM 0x1
|
||||
#define TPS51632_POWER_STATE_SINGLE_PHASE_DCM 0x2
|
||||
|
||||
#define TPS51632_MIN_VOLATGE 500000
|
||||
#define TPS51632_MAX_VOLATGE 1520000
|
||||
#define TPS51632_VOLATGE_STEP_10mV 10000
|
||||
#define TPS51632_VOLATGE_STEP_20mV 20000
|
||||
#define TPS51632_MAX_VSEL 0x7F
|
||||
#define TPS51632_MIN_VSEL 0x19
|
||||
#define TPS51632_DEFAULT_RAMP_DELAY 6000
|
||||
#define TPS51632_VOLT_VSEL(uV) \
|
||||
(DIV_ROUND_UP(uV - TPS51632_MIN_VOLATGE, \
|
||||
TPS51632_VOLATGE_STEP_10mV) + \
|
||||
TPS51632_MIN_VSEL)
|
||||
|
||||
/* TPS51632 chip information */
|
||||
struct tps51632_chip {
|
||||
struct device *dev;
|
||||
struct regulator_desc desc;
|
||||
struct regulator_dev *rdev;
|
||||
struct regmap *regmap;
|
||||
bool enable_pwm_dvfs;
|
||||
};
|
||||
|
||||
static int tps51632_dcdc_get_voltage_sel(struct regulator_dev *rdev)
|
||||
{
|
||||
struct tps51632_chip *tps = rdev_get_drvdata(rdev);
|
||||
unsigned int data;
|
||||
int ret;
|
||||
unsigned int reg = TPS51632_VOLTAGE_SELECT_REG;
|
||||
int vsel;
|
||||
|
||||
if (tps->enable_pwm_dvfs)
|
||||
reg = TPS51632_VOLTAGE_BASE_REG;
|
||||
|
||||
ret = regmap_read(tps->regmap, reg, &data);
|
||||
if (ret < 0) {
|
||||
dev_err(tps->dev, "reg read failed, err %d\n", ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
vsel = data & TPS51632_VOUT_MASK;
|
||||
|
||||
if (vsel < TPS51632_MIN_VSEL)
|
||||
return 0;
|
||||
else
|
||||
return vsel - TPS51632_MIN_VSEL;
|
||||
}
|
||||
|
||||
static int tps51632_dcdc_set_voltage_sel(struct regulator_dev *rdev,
|
||||
unsigned selector)
|
||||
{
|
||||
struct tps51632_chip *tps = rdev_get_drvdata(rdev);
|
||||
int vsel;
|
||||
int ret;
|
||||
unsigned int reg = TPS51632_VOLTAGE_SELECT_REG;
|
||||
|
||||
if (tps->enable_pwm_dvfs)
|
||||
reg = TPS51632_VOLTAGE_BASE_REG;
|
||||
|
||||
vsel = selector + TPS51632_MIN_VSEL;
|
||||
if (vsel > TPS51632_MAX_VSEL)
|
||||
return -EINVAL;
|
||||
|
||||
ret = regmap_write(tps->regmap, TPS51632_VOLTAGE_SELECT_REG, vsel);
|
||||
if (ret < 0)
|
||||
dev_err(tps->dev, "reg write failed, err %d\n", ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int tps51632_dcdc_set_ramp_delay(struct regulator_dev *rdev,
|
||||
int ramp_delay)
|
||||
{
|
||||
struct tps51632_chip *tps = rdev_get_drvdata(rdev);
|
||||
int bit = ramp_delay/6000;
|
||||
int ret;
|
||||
|
||||
if (bit)
|
||||
bit--;
|
||||
ret = regmap_write(tps->regmap, TPS51632_SLEW_REGS, BIT(bit));
|
||||
if (ret < 0)
|
||||
dev_err(tps->dev, "SLEW reg write failed, err %d\n", ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static struct regulator_ops tps51632_dcdc_ops = {
|
||||
.get_voltage_sel = tps51632_dcdc_get_voltage_sel,
|
||||
.set_voltage_sel = tps51632_dcdc_set_voltage_sel,
|
||||
.list_voltage = regulator_list_voltage_linear,
|
||||
.set_voltage_time_sel = regulator_set_voltage_time_sel,
|
||||
.set_ramp_delay = tps51632_dcdc_set_ramp_delay,
|
||||
};
|
||||
|
||||
static int __devinit tps51632_init_dcdc(struct tps51632_chip *tps,
|
||||
struct tps51632_regulator_platform_data *pdata)
|
||||
{
|
||||
int ret;
|
||||
uint8_t control = 0;
|
||||
int vsel;
|
||||
|
||||
if (!pdata->enable_pwm_dvfs)
|
||||
goto skip_pwm_config;
|
||||
|
||||
control |= TPS51632_DVFS_PWMEN;
|
||||
tps->enable_pwm_dvfs = pdata->enable_pwm_dvfs;
|
||||
vsel = TPS51632_VOLT_VSEL(pdata->base_voltage_uV);
|
||||
ret = regmap_write(tps->regmap, TPS51632_VOLTAGE_BASE_REG, vsel);
|
||||
if (ret < 0) {
|
||||
dev_err(tps->dev, "BASE reg write failed, err %d\n", ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
if (pdata->dvfs_step_20mV)
|
||||
control |= TPS51632_DVFS_STEP_20;
|
||||
|
||||
if (pdata->max_voltage_uV) {
|
||||
unsigned int vmax;
|
||||
/**
|
||||
* TPS51632 hw behavior: VMAX register can be write only
|
||||
* once as it get locked after first write. The lock get
|
||||
* reset only when device is power-reset.
|
||||
* Write register only when lock bit is not enabled.
|
||||
*/
|
||||
ret = regmap_read(tps->regmap, TPS51632_VMAX_REG, &vmax);
|
||||
if (ret < 0) {
|
||||
dev_err(tps->dev, "VMAX read failed, err %d\n", ret);
|
||||
return ret;
|
||||
}
|
||||
if (!(vmax & TPS51632_VMAX_LOCK)) {
|
||||
vsel = TPS51632_VOLT_VSEL(pdata->max_voltage_uV);
|
||||
ret = regmap_write(tps->regmap, TPS51632_VMAX_REG,
|
||||
vsel);
|
||||
if (ret < 0) {
|
||||
dev_err(tps->dev,
|
||||
"VMAX write failed, err %d\n", ret);
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
skip_pwm_config:
|
||||
ret = regmap_write(tps->regmap, TPS51632_DVFS_CONTROL_REG, control);
|
||||
if (ret < 0)
|
||||
dev_err(tps->dev, "DVFS reg write failed, err %d\n", ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static bool rd_wr_reg(struct device *dev, unsigned int reg)
|
||||
{
|
||||
if ((reg >= 0x8) && (reg <= 0x10))
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
static const struct regmap_config tps51632_regmap_config = {
|
||||
.reg_bits = 8,
|
||||
.val_bits = 8,
|
||||
.writeable_reg = rd_wr_reg,
|
||||
.readable_reg = rd_wr_reg,
|
||||
.max_register = TPS51632_MAX_REG - 1,
|
||||
.cache_type = REGCACHE_RBTREE,
|
||||
};
|
||||
|
||||
static int __devinit tps51632_probe(struct i2c_client *client,
|
||||
const struct i2c_device_id *id)
|
||||
{
|
||||
struct tps51632_regulator_platform_data *pdata;
|
||||
struct regulator_dev *rdev;
|
||||
struct tps51632_chip *tps;
|
||||
int ret;
|
||||
struct regulator_config config = { };
|
||||
|
||||
pdata = client->dev.platform_data;
|
||||
if (!pdata) {
|
||||
dev_err(&client->dev, "No Platform data\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
tps = devm_kzalloc(&client->dev, sizeof(*tps), GFP_KERNEL);
|
||||
if (!tps) {
|
||||
dev_err(&client->dev, "Memory allocation failed\n");
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
tps->dev = &client->dev;
|
||||
tps->desc.name = id->name;
|
||||
tps->desc.id = 0;
|
||||
tps->desc.ramp_delay = TPS51632_DEFAULT_RAMP_DELAY;
|
||||
tps->desc.min_uV = TPS51632_MIN_VOLATGE;
|
||||
tps->desc.uV_step = TPS51632_VOLATGE_STEP_10mV;
|
||||
tps->desc.n_voltages = (TPS51632_MAX_VSEL - TPS51632_MIN_VSEL) + 1;
|
||||
tps->desc.ops = &tps51632_dcdc_ops;
|
||||
tps->desc.type = REGULATOR_VOLTAGE;
|
||||
tps->desc.owner = THIS_MODULE;
|
||||
|
||||
tps->regmap = devm_regmap_init_i2c(client, &tps51632_regmap_config);
|
||||
if (IS_ERR(tps->regmap)) {
|
||||
ret = PTR_ERR(tps->regmap);
|
||||
dev_err(&client->dev, "regmap init failed, err %d\n", ret);
|
||||
return ret;
|
||||
}
|
||||
i2c_set_clientdata(client, tps);
|
||||
|
||||
ret = tps51632_init_dcdc(tps, pdata);
|
||||
if (ret < 0) {
|
||||
dev_err(tps->dev, "Init failed, err = %d\n", ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* Register the regulators */
|
||||
config.dev = &client->dev;
|
||||
config.init_data = pdata->reg_init_data;
|
||||
config.driver_data = tps;
|
||||
config.regmap = tps->regmap;
|
||||
config.of_node = client->dev.of_node;
|
||||
|
||||
rdev = regulator_register(&tps->desc, &config);
|
||||
if (IS_ERR(rdev)) {
|
||||
dev_err(tps->dev, "regulator register failed\n");
|
||||
return PTR_ERR(rdev);
|
||||
}
|
||||
|
||||
tps->rdev = rdev;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int __devexit tps51632_remove(struct i2c_client *client)
|
||||
{
|
||||
struct tps51632_chip *tps = i2c_get_clientdata(client);
|
||||
|
||||
regulator_unregister(tps->rdev);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct i2c_device_id tps51632_id[] = {
|
||||
{.name = "tps51632",},
|
||||
{},
|
||||
};
|
||||
|
||||
MODULE_DEVICE_TABLE(i2c, tps51632_id);
|
||||
|
||||
static struct i2c_driver tps51632_i2c_driver = {
|
||||
.driver = {
|
||||
.name = "tps51632",
|
||||
.owner = THIS_MODULE,
|
||||
},
|
||||
.probe = tps51632_probe,
|
||||
.remove = __devexit_p(tps51632_remove),
|
||||
.id_table = tps51632_id,
|
||||
};
|
||||
|
||||
static int __init tps51632_init(void)
|
||||
{
|
||||
return i2c_add_driver(&tps51632_i2c_driver);
|
||||
}
|
||||
subsys_initcall(tps51632_init);
|
||||
|
||||
static void __exit tps51632_cleanup(void)
|
||||
{
|
||||
i2c_del_driver(&tps51632_i2c_driver);
|
||||
}
|
||||
module_exit(tps51632_cleanup);
|
||||
|
||||
MODULE_AUTHOR("Laxman Dewangan <ldewangan@nvidia.com>");
|
||||
MODULE_DESCRIPTION("TPS51632 voltage regulator driver");
|
||||
MODULE_LICENSE("GPL v2");
|
|
@ -18,67 +18,124 @@
|
|||
|
||||
#include <linux/module.h>
|
||||
#include <linux/init.h>
|
||||
#include <linux/gpio.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/err.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/regulator/driver.h>
|
||||
#include <linux/regulator/machine.h>
|
||||
#include <linux/mfd/tps65090.h>
|
||||
#include <linux/regulator/tps65090-regulator.h>
|
||||
|
||||
struct tps65090_regulator {
|
||||
int id;
|
||||
/* used by regulator core */
|
||||
struct regulator_desc desc;
|
||||
|
||||
/* Device */
|
||||
struct device *dev;
|
||||
struct regulator_desc *desc;
|
||||
struct regulator_dev *rdev;
|
||||
};
|
||||
|
||||
static struct regulator_ops tps65090_ops = {
|
||||
.enable = regulator_enable_regmap,
|
||||
.disable = regulator_disable_regmap,
|
||||
.is_enabled = regulator_is_enabled_regmap,
|
||||
static struct regulator_ops tps65090_ext_control_ops = {
|
||||
};
|
||||
|
||||
#define tps65090_REG(_id) \
|
||||
static struct regulator_ops tps65090_reg_contol_ops = {
|
||||
.enable = regulator_enable_regmap,
|
||||
.disable = regulator_disable_regmap,
|
||||
.is_enabled = regulator_is_enabled_regmap,
|
||||
};
|
||||
|
||||
static struct regulator_ops tps65090_ldo_ops = {
|
||||
};
|
||||
|
||||
#define tps65090_REG_DESC(_id, _sname, _en_reg, _ops) \
|
||||
{ \
|
||||
.id = TPS65090_ID_##_id, \
|
||||
.desc = { \
|
||||
.name = tps65090_rails(_id), \
|
||||
.id = TPS65090_ID_##_id, \
|
||||
.ops = &tps65090_ops, \
|
||||
.type = REGULATOR_VOLTAGE, \
|
||||
.owner = THIS_MODULE, \
|
||||
.enable_reg = (TPS65090_ID_##_id) + 12, \
|
||||
.enable_mask = BIT(0), \
|
||||
}, \
|
||||
.name = "TPS65090_RAILS"#_id, \
|
||||
.supply_name = _sname, \
|
||||
.id = TPS65090_REGULATOR_##_id, \
|
||||
.ops = &_ops, \
|
||||
.enable_reg = _en_reg, \
|
||||
.enable_mask = BIT(0), \
|
||||
.type = REGULATOR_VOLTAGE, \
|
||||
.owner = THIS_MODULE, \
|
||||
}
|
||||
|
||||
static struct tps65090_regulator TPS65090_regulator[] = {
|
||||
tps65090_REG(DCDC1),
|
||||
tps65090_REG(DCDC2),
|
||||
tps65090_REG(DCDC3),
|
||||
tps65090_REG(FET1),
|
||||
tps65090_REG(FET2),
|
||||
tps65090_REG(FET3),
|
||||
tps65090_REG(FET4),
|
||||
tps65090_REG(FET5),
|
||||
tps65090_REG(FET6),
|
||||
tps65090_REG(FET7),
|
||||
static struct regulator_desc tps65090_regulator_desc[] = {
|
||||
tps65090_REG_DESC(DCDC1, "vsys1", 0x0C, tps65090_reg_contol_ops),
|
||||
tps65090_REG_DESC(DCDC2, "vsys2", 0x0D, tps65090_reg_contol_ops),
|
||||
tps65090_REG_DESC(DCDC3, "vsys3", 0x0E, tps65090_reg_contol_ops),
|
||||
tps65090_REG_DESC(FET1, "infet1", 0x0F, tps65090_reg_contol_ops),
|
||||
tps65090_REG_DESC(FET2, "infet2", 0x10, tps65090_reg_contol_ops),
|
||||
tps65090_REG_DESC(FET3, "infet3", 0x11, tps65090_reg_contol_ops),
|
||||
tps65090_REG_DESC(FET4, "infet4", 0x12, tps65090_reg_contol_ops),
|
||||
tps65090_REG_DESC(FET5, "infet5", 0x13, tps65090_reg_contol_ops),
|
||||
tps65090_REG_DESC(FET6, "infet6", 0x14, tps65090_reg_contol_ops),
|
||||
tps65090_REG_DESC(FET7, "infet7", 0x15, tps65090_reg_contol_ops),
|
||||
tps65090_REG_DESC(LDO1, "vsys_l1", 0, tps65090_ldo_ops),
|
||||
tps65090_REG_DESC(LDO2, "vsys_l2", 0, tps65090_ldo_ops),
|
||||
};
|
||||
|
||||
static inline struct tps65090_regulator *find_regulator_info(int id)
|
||||
static inline bool is_dcdc(int id)
|
||||
{
|
||||
struct tps65090_regulator *ri;
|
||||
int i;
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(TPS65090_regulator); i++) {
|
||||
ri = &TPS65090_regulator[i];
|
||||
if (ri->desc.id == id)
|
||||
return ri;
|
||||
switch (id) {
|
||||
case TPS65090_REGULATOR_DCDC1:
|
||||
case TPS65090_REGULATOR_DCDC2:
|
||||
case TPS65090_REGULATOR_DCDC3:
|
||||
return true;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
static int __devinit tps65090_config_ext_control(
|
||||
struct tps65090_regulator *ri, bool enable)
|
||||
{
|
||||
int ret;
|
||||
struct device *parent = ri->dev->parent;
|
||||
unsigned int reg_en_reg = ri->desc->enable_reg;
|
||||
|
||||
if (enable)
|
||||
ret = tps65090_set_bits(parent, reg_en_reg, 1);
|
||||
else
|
||||
ret = tps65090_clr_bits(parent, reg_en_reg, 1);
|
||||
if (ret < 0)
|
||||
dev_err(ri->dev, "Error in updating reg 0x%x\n", reg_en_reg);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int __devinit tps65090_regulator_disable_ext_control(
|
||||
struct tps65090_regulator *ri,
|
||||
struct tps65090_regulator_plat_data *tps_pdata)
|
||||
{
|
||||
int ret = 0;
|
||||
struct device *parent = ri->dev->parent;
|
||||
unsigned int reg_en_reg = ri->desc->enable_reg;
|
||||
|
||||
/*
|
||||
* First enable output for internal control if require.
|
||||
* And then disable external control.
|
||||
*/
|
||||
if (tps_pdata->reg_init_data->constraints.always_on ||
|
||||
tps_pdata->reg_init_data->constraints.boot_on) {
|
||||
ret = tps65090_set_bits(parent, reg_en_reg, 0);
|
||||
if (ret < 0) {
|
||||
dev_err(ri->dev, "Error in set reg 0x%x\n", reg_en_reg);
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
return tps65090_config_ext_control(ri, false);
|
||||
}
|
||||
|
||||
static void __devinit tps65090_configure_regulator_config(
|
||||
struct tps65090_regulator_plat_data *tps_pdata,
|
||||
struct regulator_config *config)
|
||||
{
|
||||
if (gpio_is_valid(tps_pdata->gpio)) {
|
||||
int gpio_flag = GPIOF_OUT_INIT_LOW;
|
||||
|
||||
if (tps_pdata->reg_init_data->constraints.always_on ||
|
||||
tps_pdata->reg_init_data->constraints.boot_on)
|
||||
gpio_flag = GPIOF_OUT_INIT_HIGH;
|
||||
|
||||
config->ena_gpio = tps_pdata->gpio;
|
||||
config->ena_gpio_flags = gpio_flag;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static int __devinit tps65090_regulator_probe(struct platform_device *pdev)
|
||||
|
@ -87,46 +144,110 @@ static int __devinit tps65090_regulator_probe(struct platform_device *pdev)
|
|||
struct tps65090_regulator *ri = NULL;
|
||||
struct regulator_config config = { };
|
||||
struct regulator_dev *rdev;
|
||||
struct tps65090_regulator_platform_data *tps_pdata;
|
||||
int id = pdev->id;
|
||||
struct tps65090_regulator_plat_data *tps_pdata;
|
||||
struct tps65090_regulator *pmic;
|
||||
struct tps65090_platform_data *tps65090_pdata;
|
||||
int num;
|
||||
int ret;
|
||||
|
||||
dev_dbg(&pdev->dev, "Probing regulator %d\n", id);
|
||||
dev_dbg(&pdev->dev, "Probing regulator\n");
|
||||
|
||||
ri = find_regulator_info(id);
|
||||
if (ri == NULL) {
|
||||
dev_err(&pdev->dev, "invalid regulator ID specified\n");
|
||||
tps65090_pdata = dev_get_platdata(pdev->dev.parent);
|
||||
if (!tps65090_pdata) {
|
||||
dev_err(&pdev->dev, "Platform data missing\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
tps_pdata = pdev->dev.platform_data;
|
||||
ri->dev = &pdev->dev;
|
||||
|
||||
config.dev = &pdev->dev;
|
||||
config.init_data = &tps_pdata->regulator;
|
||||
config.driver_data = ri;
|
||||
config.regmap = tps65090_mfd->rmap;
|
||||
|
||||
rdev = regulator_register(&ri->desc, &config);
|
||||
if (IS_ERR(rdev)) {
|
||||
dev_err(&pdev->dev, "failed to register regulator %s\n",
|
||||
ri->desc.name);
|
||||
return PTR_ERR(rdev);
|
||||
pmic = devm_kzalloc(&pdev->dev, TPS65090_REGULATOR_MAX * sizeof(*pmic),
|
||||
GFP_KERNEL);
|
||||
if (!pmic) {
|
||||
dev_err(&pdev->dev, "mem alloc for pmic failed\n");
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
platform_set_drvdata(pdev, rdev);
|
||||
for (num = 0; num < TPS65090_REGULATOR_MAX; num++) {
|
||||
tps_pdata = tps65090_pdata->reg_pdata[num];
|
||||
|
||||
ri = &pmic[num];
|
||||
ri->dev = &pdev->dev;
|
||||
ri->desc = &tps65090_regulator_desc[num];
|
||||
|
||||
/*
|
||||
* TPS5090 DCDC support the control from external digital input.
|
||||
* Configure it as per platform data.
|
||||
*/
|
||||
if (tps_pdata && is_dcdc(num) && tps_pdata->reg_init_data) {
|
||||
if (tps_pdata->enable_ext_control) {
|
||||
tps65090_configure_regulator_config(
|
||||
tps_pdata, &config);
|
||||
ri->desc->ops = &tps65090_ext_control_ops;
|
||||
} else {
|
||||
ret = tps65090_regulator_disable_ext_control(
|
||||
ri, tps_pdata);
|
||||
if (ret < 0) {
|
||||
dev_err(&pdev->dev,
|
||||
"failed disable ext control\n");
|
||||
goto scrub;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
config.dev = &pdev->dev;
|
||||
config.driver_data = ri;
|
||||
config.regmap = tps65090_mfd->rmap;
|
||||
if (tps_pdata)
|
||||
config.init_data = tps_pdata->reg_init_data;
|
||||
else
|
||||
config.init_data = NULL;
|
||||
|
||||
rdev = regulator_register(ri->desc, &config);
|
||||
if (IS_ERR(rdev)) {
|
||||
dev_err(&pdev->dev, "failed to register regulator %s\n",
|
||||
ri->desc->name);
|
||||
ret = PTR_ERR(rdev);
|
||||
goto scrub;
|
||||
}
|
||||
ri->rdev = rdev;
|
||||
|
||||
/* Enable external control if it is require */
|
||||
if (tps_pdata && is_dcdc(num) && tps_pdata->reg_init_data &&
|
||||
tps_pdata->enable_ext_control) {
|
||||
ret = tps65090_config_ext_control(ri, true);
|
||||
if (ret < 0) {
|
||||
/* Increment num to get unregister rdev */
|
||||
num++;
|
||||
goto scrub;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
platform_set_drvdata(pdev, pmic);
|
||||
return 0;
|
||||
|
||||
scrub:
|
||||
while (--num >= 0) {
|
||||
ri = &pmic[num];
|
||||
regulator_unregister(ri->rdev);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int __devexit tps65090_regulator_remove(struct platform_device *pdev)
|
||||
{
|
||||
struct regulator_dev *rdev = platform_get_drvdata(pdev);
|
||||
struct tps65090_regulator *pmic = platform_get_drvdata(pdev);
|
||||
struct tps65090_regulator *ri;
|
||||
int num;
|
||||
|
||||
regulator_unregister(rdev);
|
||||
for (num = 0; num < TPS65090_REGULATOR_MAX; ++num) {
|
||||
ri = &pmic[num];
|
||||
regulator_unregister(ri->rdev);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct platform_driver tps65090_regulator_driver = {
|
||||
.driver = {
|
||||
.name = "tps65090-regulator",
|
||||
.name = "tps65090-pmic",
|
||||
.owner = THIS_MODULE,
|
||||
},
|
||||
.probe = tps65090_regulator_probe,
|
||||
|
|
|
@ -0,0 +1,793 @@
|
|||
/*
|
||||
* tps80031-regulator.c -- TI TPS80031 regulator driver.
|
||||
*
|
||||
* Regulator driver for TITPS80031/TPS80032 Fully Integrated Power
|
||||
* Management with Power Path and Battery Charger.
|
||||
*
|
||||
* Copyright (c) 2012, NVIDIA Corporation.
|
||||
*
|
||||
* Author: Laxman Dewangan <ldewangan@nvidia.com>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License as
|
||||
* published by the Free Software Foundation version 2.
|
||||
*
|
||||
* This program is distributed "as is" WITHOUT ANY WARRANTY of any kind,
|
||||
* whether express or implied; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* General Public License for more details.
|
||||
*
|
||||
* 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
|
||||
*/
|
||||
|
||||
#include <linux/delay.h>
|
||||
#include <linux/err.h>
|
||||
#include <linux/init.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/mfd/tps80031.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/regulator/driver.h>
|
||||
#include <linux/regulator/machine.h>
|
||||
#include <linux/slab.h>
|
||||
|
||||
/* Flags for DCDC Voltage reading */
|
||||
#define DCDC_OFFSET_EN BIT(0)
|
||||
#define DCDC_EXTENDED_EN BIT(1)
|
||||
#define TRACK_MODE_ENABLE BIT(2)
|
||||
|
||||
#define SMPS_MULTOFFSET_VIO BIT(1)
|
||||
#define SMPS_MULTOFFSET_SMPS1 BIT(3)
|
||||
#define SMPS_MULTOFFSET_SMPS2 BIT(4)
|
||||
#define SMPS_MULTOFFSET_SMPS3 BIT(6)
|
||||
#define SMPS_MULTOFFSET_SMPS4 BIT(0)
|
||||
|
||||
#define SMPS_CMD_MASK 0xC0
|
||||
#define SMPS_VSEL_MASK 0x3F
|
||||
#define LDO_VSEL_MASK 0x1F
|
||||
#define LDO_TRACK_VSEL_MASK 0x3F
|
||||
|
||||
#define MISC2_LDOUSB_IN_VSYS BIT(4)
|
||||
#define MISC2_LDOUSB_IN_PMID BIT(3)
|
||||
#define MISC2_LDOUSB_IN_MASK 0x18
|
||||
|
||||
#define MISC2_LDO3_SEL_VIB_VAL BIT(0)
|
||||
#define MISC2_LDO3_SEL_VIB_MASK 0x1
|
||||
|
||||
#define BOOST_HW_PWR_EN BIT(5)
|
||||
#define BOOST_HW_PWR_EN_MASK BIT(5)
|
||||
|
||||
#define OPA_MODE_EN BIT(6)
|
||||
#define OPA_MODE_EN_MASK BIT(6)
|
||||
|
||||
#define USB_VBUS_CTRL_SET 0x04
|
||||
#define USB_VBUS_CTRL_CLR 0x05
|
||||
#define VBUS_DISCHRG 0x20
|
||||
|
||||
struct tps80031_regulator_info {
|
||||
/* Regulator register address.*/
|
||||
u8 trans_reg;
|
||||
u8 state_reg;
|
||||
u8 force_reg;
|
||||
u8 volt_reg;
|
||||
u8 volt_id;
|
||||
|
||||
/*Power request bits */
|
||||
int preq_bit;
|
||||
|
||||
/* used by regulator core */
|
||||
struct regulator_desc desc;
|
||||
|
||||
};
|
||||
|
||||
struct tps80031_regulator {
|
||||
struct device *dev;
|
||||
struct regulator_dev *rdev;
|
||||
struct tps80031_regulator_info *rinfo;
|
||||
|
||||
u8 device_flags;
|
||||
unsigned int config_flags;
|
||||
unsigned int ext_ctrl_flag;
|
||||
};
|
||||
|
||||
static inline struct device *to_tps80031_dev(struct regulator_dev *rdev)
|
||||
{
|
||||
return rdev_get_dev(rdev)->parent->parent;
|
||||
}
|
||||
|
||||
static int tps80031_reg_is_enabled(struct regulator_dev *rdev)
|
||||
{
|
||||
struct tps80031_regulator *ri = rdev_get_drvdata(rdev);
|
||||
struct device *parent = to_tps80031_dev(rdev);
|
||||
u8 reg_val;
|
||||
int ret;
|
||||
|
||||
if (ri->ext_ctrl_flag & TPS80031_EXT_PWR_REQ)
|
||||
return true;
|
||||
|
||||
ret = tps80031_read(parent, TPS80031_SLAVE_ID1, ri->rinfo->state_reg,
|
||||
®_val);
|
||||
if (ret < 0) {
|
||||
dev_err(&rdev->dev, "Reg 0x%02x read failed, err = %d\n",
|
||||
ri->rinfo->state_reg, ret);
|
||||
return ret;
|
||||
}
|
||||
return ((reg_val & TPS80031_STATE_MASK) == TPS80031_STATE_ON);
|
||||
}
|
||||
|
||||
static int tps80031_reg_enable(struct regulator_dev *rdev)
|
||||
{
|
||||
struct tps80031_regulator *ri = rdev_get_drvdata(rdev);
|
||||
struct device *parent = to_tps80031_dev(rdev);
|
||||
int ret;
|
||||
|
||||
if (ri->ext_ctrl_flag & TPS80031_EXT_PWR_REQ)
|
||||
return 0;
|
||||
|
||||
ret = tps80031_update(parent, TPS80031_SLAVE_ID1, ri->rinfo->state_reg,
|
||||
TPS80031_STATE_ON, TPS80031_STATE_MASK);
|
||||
if (ret < 0) {
|
||||
dev_err(&rdev->dev, "Reg 0x%02x update failed, err = %d\n",
|
||||
ri->rinfo->state_reg, ret);
|
||||
return ret;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int tps80031_reg_disable(struct regulator_dev *rdev)
|
||||
{
|
||||
struct tps80031_regulator *ri = rdev_get_drvdata(rdev);
|
||||
struct device *parent = to_tps80031_dev(rdev);
|
||||
int ret;
|
||||
|
||||
if (ri->ext_ctrl_flag & TPS80031_EXT_PWR_REQ)
|
||||
return 0;
|
||||
|
||||
ret = tps80031_update(parent, TPS80031_SLAVE_ID1, ri->rinfo->state_reg,
|
||||
TPS80031_STATE_OFF, TPS80031_STATE_MASK);
|
||||
if (ret < 0)
|
||||
dev_err(&rdev->dev, "Reg 0x%02x update failed, err = %d\n",
|
||||
ri->rinfo->state_reg, ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* DCDC voltages for the selector of 58 to 63 */
|
||||
static int tps80031_dcdc_voltages[4][5] = {
|
||||
{ 1350, 1500, 1800, 1900, 2100},
|
||||
{ 1350, 1500, 1800, 1900, 2100},
|
||||
{ 2084, 2315, 2778, 2932, 3241},
|
||||
{ 4167, 2315, 2778, 2932, 3241},
|
||||
};
|
||||
|
||||
static int tps80031_dcdc_list_voltage(struct regulator_dev *rdev, unsigned sel)
|
||||
{
|
||||
struct tps80031_regulator *ri = rdev_get_drvdata(rdev);
|
||||
int volt_index = ri->device_flags & 0x3;
|
||||
|
||||
if (sel == 0)
|
||||
return 0;
|
||||
else if (sel < 58)
|
||||
return regulator_list_voltage_linear(rdev, sel - 1);
|
||||
else
|
||||
return tps80031_dcdc_voltages[volt_index][sel - 58] * 1000;
|
||||
}
|
||||
|
||||
static int tps80031_dcdc_set_voltage_sel(struct regulator_dev *rdev,
|
||||
unsigned vsel)
|
||||
{
|
||||
struct tps80031_regulator *ri = rdev_get_drvdata(rdev);
|
||||
struct device *parent = to_tps80031_dev(rdev);
|
||||
int ret;
|
||||
u8 reg_val;
|
||||
|
||||
if (ri->rinfo->force_reg) {
|
||||
ret = tps80031_read(parent, ri->rinfo->volt_id,
|
||||
ri->rinfo->force_reg, ®_val);
|
||||
if (ret < 0) {
|
||||
dev_err(ri->dev, "reg 0x%02x read failed, e = %d\n",
|
||||
ri->rinfo->force_reg, ret);
|
||||
return ret;
|
||||
}
|
||||
if (!(reg_val & SMPS_CMD_MASK)) {
|
||||
ret = tps80031_update(parent, ri->rinfo->volt_id,
|
||||
ri->rinfo->force_reg, vsel, SMPS_VSEL_MASK);
|
||||
if (ret < 0)
|
||||
dev_err(ri->dev,
|
||||
"reg 0x%02x update failed, e = %d\n",
|
||||
ri->rinfo->force_reg, ret);
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
ret = tps80031_update(parent, ri->rinfo->volt_id,
|
||||
ri->rinfo->volt_reg, vsel, SMPS_VSEL_MASK);
|
||||
if (ret < 0)
|
||||
dev_err(ri->dev, "reg 0x%02x update failed, e = %d\n",
|
||||
ri->rinfo->volt_reg, ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int tps80031_dcdc_get_voltage_sel(struct regulator_dev *rdev)
|
||||
{
|
||||
struct tps80031_regulator *ri = rdev_get_drvdata(rdev);
|
||||
struct device *parent = to_tps80031_dev(rdev);
|
||||
uint8_t vsel = 0;
|
||||
int ret;
|
||||
|
||||
if (ri->rinfo->force_reg) {
|
||||
ret = tps80031_read(parent, ri->rinfo->volt_id,
|
||||
ri->rinfo->force_reg, &vsel);
|
||||
if (ret < 0) {
|
||||
dev_err(ri->dev, "reg 0x%02x read failed, e = %d\n",
|
||||
ri->rinfo->force_reg, ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
if (!(vsel & SMPS_CMD_MASK))
|
||||
return vsel & SMPS_VSEL_MASK;
|
||||
}
|
||||
ret = tps80031_read(parent, ri->rinfo->volt_id,
|
||||
ri->rinfo->volt_reg, &vsel);
|
||||
if (ret < 0) {
|
||||
dev_err(ri->dev, "reg 0x%02x read failed, e = %d\n",
|
||||
ri->rinfo->volt_reg, ret);
|
||||
return ret;
|
||||
}
|
||||
return vsel & SMPS_VSEL_MASK;
|
||||
}
|
||||
|
||||
static int tps80031_ldo_set_voltage_sel(struct regulator_dev *rdev,
|
||||
unsigned sel)
|
||||
{
|
||||
struct tps80031_regulator *ri = rdev_get_drvdata(rdev);
|
||||
struct device *parent = to_tps80031_dev(rdev);
|
||||
int ret;
|
||||
|
||||
/* Check for valid setting for TPS80031 or TPS80032-ES1.0 */
|
||||
if ((ri->rinfo->desc.id == TPS80031_REGULATOR_LDO2) &&
|
||||
(ri->device_flags & TRACK_MODE_ENABLE)) {
|
||||
unsigned nvsel = (sel) & 0x1F;
|
||||
if (((tps80031_get_chip_info(parent) == TPS80031) ||
|
||||
((tps80031_get_chip_info(parent) == TPS80032) &&
|
||||
(tps80031_get_pmu_version(parent) == 0x0))) &&
|
||||
((nvsel == 0x0) || (nvsel >= 0x19 && nvsel <= 0x1F))) {
|
||||
dev_err(ri->dev,
|
||||
"Invalid sel %d in track mode LDO2\n",
|
||||
nvsel);
|
||||
return -EINVAL;
|
||||
}
|
||||
}
|
||||
|
||||
ret = tps80031_write(parent, ri->rinfo->volt_id,
|
||||
ri->rinfo->volt_reg, sel);
|
||||
if (ret < 0)
|
||||
dev_err(ri->dev, "Error in writing reg 0x%02x, e = %d\n",
|
||||
ri->rinfo->volt_reg, ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int tps80031_ldo_get_voltage_sel(struct regulator_dev *rdev)
|
||||
{
|
||||
struct tps80031_regulator *ri = rdev_get_drvdata(rdev);
|
||||
struct device *parent = to_tps80031_dev(rdev);
|
||||
uint8_t vsel;
|
||||
int ret;
|
||||
|
||||
ret = tps80031_read(parent, ri->rinfo->volt_id,
|
||||
ri->rinfo->volt_reg, &vsel);
|
||||
if (ret < 0) {
|
||||
dev_err(ri->dev, "Error in writing the Voltage register\n");
|
||||
return ret;
|
||||
}
|
||||
return vsel & rdev->desc->vsel_mask;
|
||||
}
|
||||
|
||||
static int tps80031_ldo_list_voltage(struct regulator_dev *rdev, unsigned sel)
|
||||
{
|
||||
if (sel == 0)
|
||||
return 0;
|
||||
else
|
||||
return regulator_list_voltage_linear(rdev, sel - 1);
|
||||
}
|
||||
|
||||
static int tps80031_vbus_is_enabled(struct regulator_dev *rdev)
|
||||
{
|
||||
struct tps80031_regulator *ri = rdev_get_drvdata(rdev);
|
||||
struct device *parent = to_tps80031_dev(rdev);
|
||||
int ret = -EIO;
|
||||
uint8_t ctrl1 = 0;
|
||||
uint8_t ctrl3 = 0;
|
||||
|
||||
ret = tps80031_read(parent, TPS80031_SLAVE_ID2,
|
||||
TPS80031_CHARGERUSB_CTRL1, &ctrl1);
|
||||
if (ret < 0) {
|
||||
dev_err(ri->dev, "reg 0x%02x read failed, e = %d\n",
|
||||
TPS80031_CHARGERUSB_CTRL1, ret);
|
||||
return ret;
|
||||
}
|
||||
ret = tps80031_read(parent, TPS80031_SLAVE_ID2,
|
||||
TPS80031_CHARGERUSB_CTRL3, &ctrl3);
|
||||
if (ret < 0) {
|
||||
dev_err(ri->dev, "reg 0x%02x read failed, e = %d\n",
|
||||
TPS80031_CHARGERUSB_CTRL1, ret);
|
||||
return ret;
|
||||
}
|
||||
if ((ctrl1 & OPA_MODE_EN) && (ctrl3 & BOOST_HW_PWR_EN))
|
||||
return 1;
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int tps80031_vbus_enable(struct regulator_dev *rdev)
|
||||
{
|
||||
struct tps80031_regulator *ri = rdev_get_drvdata(rdev);
|
||||
struct device *parent = to_tps80031_dev(rdev);
|
||||
int ret;
|
||||
|
||||
ret = tps80031_set_bits(parent, TPS80031_SLAVE_ID2,
|
||||
TPS80031_CHARGERUSB_CTRL1, OPA_MODE_EN);
|
||||
if (ret < 0) {
|
||||
dev_err(ri->dev, "reg 0x%02x read failed, e = %d\n",
|
||||
TPS80031_CHARGERUSB_CTRL1, ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
ret = tps80031_set_bits(parent, TPS80031_SLAVE_ID2,
|
||||
TPS80031_CHARGERUSB_CTRL3, BOOST_HW_PWR_EN);
|
||||
if (ret < 0) {
|
||||
dev_err(ri->dev, "reg 0x%02x read failed, e = %d\n",
|
||||
TPS80031_CHARGERUSB_CTRL3, ret);
|
||||
return ret;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int tps80031_vbus_disable(struct regulator_dev *rdev)
|
||||
{
|
||||
struct tps80031_regulator *ri = rdev_get_drvdata(rdev);
|
||||
struct device *parent = to_tps80031_dev(rdev);
|
||||
int ret = 0;
|
||||
|
||||
if (ri->config_flags & TPS80031_VBUS_DISCHRG_EN_PDN) {
|
||||
ret = tps80031_write(parent, TPS80031_SLAVE_ID2,
|
||||
USB_VBUS_CTRL_SET, VBUS_DISCHRG);
|
||||
if (ret < 0) {
|
||||
dev_err(ri->dev, "reg 0x%02x write failed, e = %d\n",
|
||||
USB_VBUS_CTRL_SET, ret);
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
|
||||
ret = tps80031_clr_bits(parent, TPS80031_SLAVE_ID2,
|
||||
TPS80031_CHARGERUSB_CTRL1, OPA_MODE_EN);
|
||||
if (ret < 0) {
|
||||
dev_err(ri->dev, "reg 0x%02x clearbit failed, e = %d\n",
|
||||
TPS80031_CHARGERUSB_CTRL1, ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
ret = tps80031_clr_bits(parent, TPS80031_SLAVE_ID2,
|
||||
TPS80031_CHARGERUSB_CTRL3, BOOST_HW_PWR_EN);
|
||||
if (ret < 0) {
|
||||
dev_err(ri->dev, "reg 0x%02x clearbit failed, e = %d\n",
|
||||
TPS80031_CHARGERUSB_CTRL3, ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
mdelay(DIV_ROUND_UP(ri->rinfo->desc.enable_time, 1000));
|
||||
if (ri->config_flags & TPS80031_VBUS_DISCHRG_EN_PDN) {
|
||||
ret = tps80031_write(parent, TPS80031_SLAVE_ID2,
|
||||
USB_VBUS_CTRL_CLR, VBUS_DISCHRG);
|
||||
if (ret < 0) {
|
||||
dev_err(ri->dev, "reg 0x%02x write failed, e = %d\n",
|
||||
USB_VBUS_CTRL_CLR, ret);
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
static struct regulator_ops tps80031_dcdc_ops = {
|
||||
.list_voltage = tps80031_dcdc_list_voltage,
|
||||
.set_voltage_sel = tps80031_dcdc_set_voltage_sel,
|
||||
.get_voltage_sel = tps80031_dcdc_get_voltage_sel,
|
||||
.enable = tps80031_reg_enable,
|
||||
.disable = tps80031_reg_disable,
|
||||
.is_enabled = tps80031_reg_is_enabled,
|
||||
};
|
||||
|
||||
static struct regulator_ops tps80031_ldo_ops = {
|
||||
.list_voltage = tps80031_ldo_list_voltage,
|
||||
.set_voltage_sel = tps80031_ldo_set_voltage_sel,
|
||||
.get_voltage_sel = tps80031_ldo_get_voltage_sel,
|
||||
.enable = tps80031_reg_enable,
|
||||
.disable = tps80031_reg_disable,
|
||||
.is_enabled = tps80031_reg_is_enabled,
|
||||
};
|
||||
|
||||
static struct regulator_ops tps80031_vbus_sw_ops = {
|
||||
.enable = tps80031_vbus_enable,
|
||||
.disable = tps80031_vbus_disable,
|
||||
.is_enabled = tps80031_vbus_is_enabled,
|
||||
};
|
||||
|
||||
static struct regulator_ops tps80031_vbus_hw_ops = {
|
||||
};
|
||||
|
||||
static struct regulator_ops tps80031_ext_reg_ops = {
|
||||
.enable = tps80031_reg_enable,
|
||||
.disable = tps80031_reg_disable,
|
||||
.is_enabled = tps80031_reg_is_enabled,
|
||||
};
|
||||
|
||||
/* Non-exiting default definition for some register */
|
||||
#define TPS80031_SMPS3_CFG_FORCE 0
|
||||
#define TPS80031_SMPS4_CFG_FORCE 0
|
||||
|
||||
#define TPS80031_VBUS_CFG_TRANS 0
|
||||
#define TPS80031_VBUS_CFG_STATE 0
|
||||
|
||||
#define TPS80031_REG_SMPS(_id, _volt_id, _pbit) \
|
||||
{ \
|
||||
.trans_reg = TPS80031_##_id##_CFG_TRANS, \
|
||||
.state_reg = TPS80031_##_id##_CFG_STATE, \
|
||||
.force_reg = TPS80031_##_id##_CFG_FORCE, \
|
||||
.volt_reg = TPS80031_##_id##_CFG_VOLTAGE, \
|
||||
.volt_id = TPS80031_SLAVE_##_volt_id, \
|
||||
.preq_bit = _pbit, \
|
||||
.desc = { \
|
||||
.name = "tps80031_"#_id, \
|
||||
.id = TPS80031_REGULATOR_##_id, \
|
||||
.n_voltages = 63, \
|
||||
.ops = &tps80031_dcdc_ops, \
|
||||
.type = REGULATOR_VOLTAGE, \
|
||||
.owner = THIS_MODULE, \
|
||||
.enable_time = 500, \
|
||||
}, \
|
||||
}
|
||||
|
||||
#define TPS80031_REG_LDO(_id, _preq_bit) \
|
||||
{ \
|
||||
.trans_reg = TPS80031_##_id##_CFG_TRANS, \
|
||||
.state_reg = TPS80031_##_id##_CFG_STATE, \
|
||||
.volt_reg = TPS80031_##_id##_CFG_VOLTAGE, \
|
||||
.volt_id = TPS80031_SLAVE_ID1, \
|
||||
.preq_bit = _preq_bit, \
|
||||
.desc = { \
|
||||
.owner = THIS_MODULE, \
|
||||
.name = "tps80031_"#_id, \
|
||||
.id = TPS80031_REGULATOR_##_id, \
|
||||
.ops = &tps80031_ldo_ops, \
|
||||
.type = REGULATOR_VOLTAGE, \
|
||||
.min_uV = 1000000, \
|
||||
.uV_step = 100000, \
|
||||
.n_voltages = 25, \
|
||||
.vsel_mask = LDO_VSEL_MASK, \
|
||||
.enable_time = 500, \
|
||||
}, \
|
||||
}
|
||||
|
||||
#define TPS80031_REG_FIXED(_id, max_mV, _ops, _delay, _pbit) \
|
||||
{ \
|
||||
.trans_reg = TPS80031_##_id##_CFG_TRANS, \
|
||||
.state_reg = TPS80031_##_id##_CFG_STATE, \
|
||||
.volt_id = TPS80031_SLAVE_ID1, \
|
||||
.preq_bit = _pbit, \
|
||||
.desc = { \
|
||||
.name = "tps80031_"#_id, \
|
||||
.id = TPS80031_REGULATOR_##_id, \
|
||||
.n_voltages = 2, \
|
||||
.ops = &_ops, \
|
||||
.type = REGULATOR_VOLTAGE, \
|
||||
.owner = THIS_MODULE, \
|
||||
.enable_time = _delay, \
|
||||
}, \
|
||||
}
|
||||
|
||||
static struct tps80031_regulator_info tps80031_rinfo[TPS80031_REGULATOR_MAX] = {
|
||||
TPS80031_REG_SMPS(VIO, ID0, 4),
|
||||
TPS80031_REG_SMPS(SMPS1, ID0, 0),
|
||||
TPS80031_REG_SMPS(SMPS2, ID0, 1),
|
||||
TPS80031_REG_SMPS(SMPS3, ID1, 2),
|
||||
TPS80031_REG_SMPS(SMPS4, ID1, 3),
|
||||
TPS80031_REG_LDO(VANA, -1),
|
||||
TPS80031_REG_LDO(LDO1, 8),
|
||||
TPS80031_REG_LDO(LDO2, 9),
|
||||
TPS80031_REG_LDO(LDO3, 10),
|
||||
TPS80031_REG_LDO(LDO4, 11),
|
||||
TPS80031_REG_LDO(LDO5, 12),
|
||||
TPS80031_REG_LDO(LDO6, 13),
|
||||
TPS80031_REG_LDO(LDO7, 14),
|
||||
TPS80031_REG_LDO(LDOLN, 15),
|
||||
TPS80031_REG_LDO(LDOUSB, 5),
|
||||
TPS80031_REG_FIXED(VBUS, 5000, tps80031_vbus_hw_ops, 100000, -1),
|
||||
TPS80031_REG_FIXED(REGEN1, 3300, tps80031_ext_reg_ops, 0, 16),
|
||||
TPS80031_REG_FIXED(REGEN2, 3300, tps80031_ext_reg_ops, 0, 17),
|
||||
TPS80031_REG_FIXED(SYSEN, 3300, tps80031_ext_reg_ops, 0, 18),
|
||||
};
|
||||
|
||||
static int tps80031_power_req_config(struct device *parent,
|
||||
struct tps80031_regulator *ri,
|
||||
struct tps80031_regulator_platform_data *tps80031_pdata)
|
||||
{
|
||||
int ret = 0;
|
||||
|
||||
if (ri->rinfo->preq_bit < 0)
|
||||
goto skip_pwr_req_config;
|
||||
|
||||
ret = tps80031_ext_power_req_config(parent, ri->ext_ctrl_flag,
|
||||
ri->rinfo->preq_bit, ri->rinfo->state_reg,
|
||||
ri->rinfo->trans_reg);
|
||||
if (ret < 0) {
|
||||
dev_err(ri->dev, "ext powerreq config failed, err = %d\n", ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
skip_pwr_req_config:
|
||||
if (tps80031_pdata->ext_ctrl_flag & TPS80031_PWR_ON_ON_SLEEP) {
|
||||
ret = tps80031_update(parent, TPS80031_SLAVE_ID1,
|
||||
ri->rinfo->trans_reg, TPS80031_TRANS_SLEEP_ON,
|
||||
TPS80031_TRANS_SLEEP_MASK);
|
||||
if (ret < 0) {
|
||||
dev_err(ri->dev, "Reg 0x%02x update failed, e %d\n",
|
||||
ri->rinfo->trans_reg, ret);
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int tps80031_regulator_config(struct device *parent,
|
||||
struct tps80031_regulator *ri,
|
||||
struct tps80031_regulator_platform_data *tps80031_pdata)
|
||||
{
|
||||
int ret = 0;
|
||||
|
||||
switch (ri->rinfo->desc.id) {
|
||||
case TPS80031_REGULATOR_LDOUSB:
|
||||
if (ri->config_flags & (TPS80031_USBLDO_INPUT_VSYS |
|
||||
TPS80031_USBLDO_INPUT_PMID)) {
|
||||
unsigned val = 0;
|
||||
if (ri->config_flags & TPS80031_USBLDO_INPUT_VSYS)
|
||||
val = MISC2_LDOUSB_IN_VSYS;
|
||||
else
|
||||
val = MISC2_LDOUSB_IN_PMID;
|
||||
|
||||
ret = tps80031_update(parent, TPS80031_SLAVE_ID1,
|
||||
TPS80031_MISC2, val,
|
||||
MISC2_LDOUSB_IN_MASK);
|
||||
if (ret < 0) {
|
||||
dev_err(ri->dev,
|
||||
"LDOUSB config failed, e= %d\n", ret);
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case TPS80031_REGULATOR_LDO3:
|
||||
if (ri->config_flags & TPS80031_LDO3_OUTPUT_VIB) {
|
||||
ret = tps80031_update(parent, TPS80031_SLAVE_ID1,
|
||||
TPS80031_MISC2, MISC2_LDO3_SEL_VIB_VAL,
|
||||
MISC2_LDO3_SEL_VIB_MASK);
|
||||
if (ret < 0) {
|
||||
dev_err(ri->dev,
|
||||
"LDO3 config failed, e = %d\n", ret);
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case TPS80031_REGULATOR_VBUS:
|
||||
/* Provide SW control Ops if VBUS is SW control */
|
||||
if (!(ri->config_flags & TPS80031_VBUS_SW_ONLY))
|
||||
ri->rinfo->desc.ops = &tps80031_vbus_sw_ops;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
/* Configure Active state to ON, SLEEP to OFF and OFF_state to OFF */
|
||||
ret = tps80031_update(parent, TPS80031_SLAVE_ID1, ri->rinfo->trans_reg,
|
||||
TPS80031_TRANS_ACTIVE_ON | TPS80031_TRANS_SLEEP_OFF |
|
||||
TPS80031_TRANS_OFF_OFF, TPS80031_TRANS_ACTIVE_MASK |
|
||||
TPS80031_TRANS_SLEEP_MASK | TPS80031_TRANS_OFF_MASK);
|
||||
if (ret < 0) {
|
||||
dev_err(ri->dev, "trans reg update failed, e %d\n", ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int check_smps_mode_mult(struct device *parent,
|
||||
struct tps80031_regulator *ri)
|
||||
{
|
||||
int mult_offset;
|
||||
int ret;
|
||||
u8 smps_offset;
|
||||
u8 smps_mult;
|
||||
|
||||
ret = tps80031_read(parent, TPS80031_SLAVE_ID1,
|
||||
TPS80031_SMPS_OFFSET, &smps_offset);
|
||||
if (ret < 0) {
|
||||
dev_err(parent, "Error in reading smps offset register\n");
|
||||
return ret;
|
||||
}
|
||||
|
||||
ret = tps80031_read(parent, TPS80031_SLAVE_ID1,
|
||||
TPS80031_SMPS_MULT, &smps_mult);
|
||||
if (ret < 0) {
|
||||
dev_err(parent, "Error in reading smps mult register\n");
|
||||
return ret;
|
||||
}
|
||||
|
||||
switch (ri->rinfo->desc.id) {
|
||||
case TPS80031_REGULATOR_VIO:
|
||||
mult_offset = SMPS_MULTOFFSET_VIO;
|
||||
break;
|
||||
case TPS80031_REGULATOR_SMPS1:
|
||||
mult_offset = SMPS_MULTOFFSET_SMPS1;
|
||||
break;
|
||||
case TPS80031_REGULATOR_SMPS2:
|
||||
mult_offset = SMPS_MULTOFFSET_SMPS2;
|
||||
break;
|
||||
case TPS80031_REGULATOR_SMPS3:
|
||||
mult_offset = SMPS_MULTOFFSET_SMPS3;
|
||||
break;
|
||||
case TPS80031_REGULATOR_SMPS4:
|
||||
mult_offset = SMPS_MULTOFFSET_SMPS4;
|
||||
break;
|
||||
case TPS80031_REGULATOR_LDO2:
|
||||
ri->device_flags = smps_mult & BIT(5) ? TRACK_MODE_ENABLE : 0;
|
||||
/* TRACK mode the ldo2 varies from 600mV to 1300mV */
|
||||
if (ri->device_flags & TRACK_MODE_ENABLE) {
|
||||
ri->rinfo->desc.min_uV = 600000;
|
||||
ri->rinfo->desc.uV_step = 12500;
|
||||
ri->rinfo->desc.n_voltages = 57;
|
||||
ri->rinfo->desc.vsel_mask = LDO_TRACK_VSEL_MASK;
|
||||
}
|
||||
return 0;
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
|
||||
ri->device_flags = (smps_offset & mult_offset) ? DCDC_OFFSET_EN : 0;
|
||||
ri->device_flags |= (smps_mult & mult_offset) ? DCDC_EXTENDED_EN : 0;
|
||||
switch (ri->device_flags) {
|
||||
case 0:
|
||||
ri->rinfo->desc.min_uV = 607700;
|
||||
ri->rinfo->desc.uV_step = 12660;
|
||||
break;
|
||||
case DCDC_OFFSET_EN:
|
||||
ri->rinfo->desc.min_uV = 700000;
|
||||
ri->rinfo->desc.uV_step = 12500;
|
||||
break;
|
||||
case DCDC_EXTENDED_EN:
|
||||
ri->rinfo->desc.min_uV = 1852000;
|
||||
ri->rinfo->desc.uV_step = 38600;
|
||||
break;
|
||||
case DCDC_OFFSET_EN | DCDC_EXTENDED_EN:
|
||||
ri->rinfo->desc.min_uV = 2161000;
|
||||
ri->rinfo->desc.uV_step = 38600;
|
||||
break;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int __devinit tps80031_regulator_probe(struct platform_device *pdev)
|
||||
{
|
||||
struct tps80031_platform_data *pdata;
|
||||
struct tps80031_regulator_platform_data *tps_pdata;
|
||||
struct tps80031_regulator_info *rinfo;
|
||||
struct tps80031_regulator *ri;
|
||||
struct tps80031_regulator *pmic;
|
||||
struct regulator_dev *rdev;
|
||||
struct regulator_config config = { };
|
||||
int ret;
|
||||
int num;
|
||||
|
||||
pdata = dev_get_platdata(pdev->dev.parent);
|
||||
|
||||
if (!pdata) {
|
||||
dev_err(&pdev->dev, "No platform data\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
pmic = devm_kzalloc(&pdev->dev,
|
||||
TPS80031_REGULATOR_MAX * sizeof(*pmic), GFP_KERNEL);
|
||||
if (!pmic) {
|
||||
dev_err(&pdev->dev, "mem alloc for pmic failed\n");
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
for (num = 0; num < TPS80031_REGULATOR_MAX; ++num) {
|
||||
tps_pdata = pdata->regulator_pdata[num];
|
||||
rinfo = &tps80031_rinfo[num];
|
||||
ri = &pmic[num];
|
||||
ri->rinfo = rinfo;
|
||||
ri->dev = &pdev->dev;
|
||||
|
||||
check_smps_mode_mult(pdev->dev.parent, ri);
|
||||
config.dev = &pdev->dev;
|
||||
config.init_data = NULL;
|
||||
config.driver_data = ri;
|
||||
if (tps_pdata) {
|
||||
config.init_data = tps_pdata->reg_init_data;
|
||||
ri->config_flags = tps_pdata->config_flags;
|
||||
ri->ext_ctrl_flag = tps_pdata->ext_ctrl_flag;
|
||||
ret = tps80031_regulator_config(pdev->dev.parent,
|
||||
ri, tps_pdata);
|
||||
if (ret < 0) {
|
||||
dev_err(&pdev->dev,
|
||||
"regulator config failed, e %d\n", ret);
|
||||
goto fail;
|
||||
}
|
||||
|
||||
ret = tps80031_power_req_config(pdev->dev.parent,
|
||||
ri, tps_pdata);
|
||||
if (ret < 0) {
|
||||
dev_err(&pdev->dev,
|
||||
"pwr_req config failed, err %d\n", ret);
|
||||
goto fail;
|
||||
}
|
||||
}
|
||||
rdev = regulator_register(&ri->rinfo->desc, &config);
|
||||
if (IS_ERR_OR_NULL(rdev)) {
|
||||
dev_err(&pdev->dev,
|
||||
"register regulator failed %s\n",
|
||||
ri->rinfo->desc.name);
|
||||
ret = PTR_ERR(rdev);
|
||||
goto fail;
|
||||
}
|
||||
ri->rdev = rdev;
|
||||
}
|
||||
|
||||
platform_set_drvdata(pdev, pmic);
|
||||
return 0;
|
||||
fail:
|
||||
while (--num >= 0) {
|
||||
ri = &pmic[num];
|
||||
regulator_unregister(ri->rdev);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int __devexit tps80031_regulator_remove(struct platform_device *pdev)
|
||||
{
|
||||
struct tps80031_regulator *pmic = platform_get_drvdata(pdev);
|
||||
struct tps80031_regulator *ri = NULL;
|
||||
int num;
|
||||
|
||||
for (num = 0; num < TPS80031_REGULATOR_MAX; ++num) {
|
||||
ri = &pmic[num];
|
||||
regulator_unregister(ri->rdev);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct platform_driver tps80031_regulator_driver = {
|
||||
.driver = {
|
||||
.name = "tps80031-pmic",
|
||||
.owner = THIS_MODULE,
|
||||
},
|
||||
.probe = tps80031_regulator_probe,
|
||||
.remove = __devexit_p(tps80031_regulator_remove),
|
||||
};
|
||||
|
||||
static int __init tps80031_regulator_init(void)
|
||||
{
|
||||
return platform_driver_register(&tps80031_regulator_driver);
|
||||
}
|
||||
subsys_initcall(tps80031_regulator_init);
|
||||
|
||||
static void __exit tps80031_regulator_exit(void)
|
||||
{
|
||||
platform_driver_unregister(&tps80031_regulator_driver);
|
||||
}
|
||||
module_exit(tps80031_regulator_exit);
|
||||
|
||||
MODULE_ALIAS("platform:tps80031-regulator");
|
||||
MODULE_DESCRIPTION("Regulator Driver for TI TPS80031 PMIC");
|
||||
MODULE_AUTHOR("Laxman Dewangan <ldewangan@nvidia.com>");
|
||||
MODULE_LICENSE("GPL v2");
|
|
@ -0,0 +1,147 @@
|
|||
/*
|
||||
* 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.
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
* Copyright (C) 2012 ARM Limited
|
||||
*/
|
||||
|
||||
#define DRVNAME "vexpress-regulator"
|
||||
#define pr_fmt(fmt) DRVNAME ": " fmt
|
||||
|
||||
#include <linux/device.h>
|
||||
#include <linux/err.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/of_device.h>
|
||||
#include <linux/regulator/driver.h>
|
||||
#include <linux/regulator/machine.h>
|
||||
#include <linux/regulator/of_regulator.h>
|
||||
#include <linux/vexpress.h>
|
||||
|
||||
struct vexpress_regulator {
|
||||
struct regulator_desc desc;
|
||||
struct regulator_dev *regdev;
|
||||
struct vexpress_config_func *func;
|
||||
};
|
||||
|
||||
static int vexpress_regulator_get_voltage(struct regulator_dev *regdev)
|
||||
{
|
||||
struct vexpress_regulator *reg = rdev_get_drvdata(regdev);
|
||||
u32 uV;
|
||||
int err = vexpress_config_read(reg->func, 0, &uV);
|
||||
|
||||
return err ? err : uV;
|
||||
}
|
||||
|
||||
static int vexpress_regulator_set_voltage(struct regulator_dev *regdev,
|
||||
int min_uV, int max_uV, unsigned *selector)
|
||||
{
|
||||
struct vexpress_regulator *reg = rdev_get_drvdata(regdev);
|
||||
|
||||
return vexpress_config_write(reg->func, 0, min_uV);
|
||||
}
|
||||
|
||||
static struct regulator_ops vexpress_regulator_ops_ro = {
|
||||
.get_voltage = vexpress_regulator_get_voltage,
|
||||
};
|
||||
|
||||
static struct regulator_ops vexpress_regulator_ops = {
|
||||
.get_voltage = vexpress_regulator_get_voltage,
|
||||
.set_voltage = vexpress_regulator_set_voltage,
|
||||
};
|
||||
|
||||
static int vexpress_regulator_probe(struct platform_device *pdev)
|
||||
{
|
||||
int err;
|
||||
struct vexpress_regulator *reg;
|
||||
struct regulator_init_data *init_data;
|
||||
struct regulator_config config = { };
|
||||
|
||||
reg = devm_kzalloc(&pdev->dev, sizeof(*reg), GFP_KERNEL);
|
||||
if (!reg) {
|
||||
err = -ENOMEM;
|
||||
goto error_kzalloc;
|
||||
}
|
||||
|
||||
reg->func = vexpress_config_func_get_by_dev(&pdev->dev);
|
||||
if (!reg->func) {
|
||||
err = -ENXIO;
|
||||
goto error_get_func;
|
||||
}
|
||||
|
||||
reg->desc.name = dev_name(&pdev->dev);
|
||||
reg->desc.type = REGULATOR_VOLTAGE;
|
||||
reg->desc.owner = THIS_MODULE;
|
||||
reg->desc.continuous_voltage_range = true;
|
||||
|
||||
init_data = of_get_regulator_init_data(&pdev->dev, pdev->dev.of_node);
|
||||
if (!init_data) {
|
||||
err = -EINVAL;
|
||||
goto error_get_regulator_init_data;
|
||||
}
|
||||
|
||||
init_data->constraints.apply_uV = 0;
|
||||
if (init_data->constraints.min_uV && init_data->constraints.max_uV)
|
||||
reg->desc.ops = &vexpress_regulator_ops;
|
||||
else
|
||||
reg->desc.ops = &vexpress_regulator_ops_ro;
|
||||
|
||||
config.dev = &pdev->dev;
|
||||
config.init_data = init_data;
|
||||
config.driver_data = reg;
|
||||
config.of_node = pdev->dev.of_node;
|
||||
|
||||
reg->regdev = regulator_register(®->desc, &config);
|
||||
if (IS_ERR(reg->regdev)) {
|
||||
err = PTR_ERR(reg->regdev);
|
||||
goto error_regulator_register;
|
||||
}
|
||||
|
||||
platform_set_drvdata(pdev, reg);
|
||||
|
||||
return 0;
|
||||
|
||||
error_regulator_register:
|
||||
error_get_regulator_init_data:
|
||||
vexpress_config_func_put(reg->func);
|
||||
error_get_func:
|
||||
error_kzalloc:
|
||||
return err;
|
||||
}
|
||||
|
||||
static int __devexit vexpress_regulator_remove(struct platform_device *pdev)
|
||||
{
|
||||
struct vexpress_regulator *reg = platform_get_drvdata(pdev);
|
||||
|
||||
vexpress_config_func_put(reg->func);
|
||||
regulator_unregister(reg->regdev);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct of_device_id vexpress_regulator_of_match[] = {
|
||||
{ .compatible = "arm,vexpress-volt", },
|
||||
{ }
|
||||
};
|
||||
|
||||
static struct platform_driver vexpress_regulator_driver = {
|
||||
.probe = vexpress_regulator_probe,
|
||||
.remove = __devexit_p(vexpress_regulator_remove),
|
||||
.driver = {
|
||||
.name = DRVNAME,
|
||||
.owner = THIS_MODULE,
|
||||
.of_match_table = vexpress_regulator_of_match,
|
||||
},
|
||||
};
|
||||
|
||||
module_platform_driver(vexpress_regulator_driver);
|
||||
|
||||
MODULE_AUTHOR("Pawel Moll <pawel.moll@arm.com>");
|
||||
MODULE_DESCRIPTION("Versatile Express regulator");
|
||||
MODULE_LICENSE("GPL");
|
||||
MODULE_ALIAS("platform:vexpress-regulator");
|
|
@ -24,6 +24,25 @@
|
|||
|
||||
#include <linux/irq.h>
|
||||
|
||||
/* TPS65090 Regulator ID */
|
||||
enum {
|
||||
TPS65090_REGULATOR_DCDC1,
|
||||
TPS65090_REGULATOR_DCDC2,
|
||||
TPS65090_REGULATOR_DCDC3,
|
||||
TPS65090_REGULATOR_FET1,
|
||||
TPS65090_REGULATOR_FET2,
|
||||
TPS65090_REGULATOR_FET3,
|
||||
TPS65090_REGULATOR_FET4,
|
||||
TPS65090_REGULATOR_FET5,
|
||||
TPS65090_REGULATOR_FET6,
|
||||
TPS65090_REGULATOR_FET7,
|
||||
TPS65090_REGULATOR_LDO1,
|
||||
TPS65090_REGULATOR_LDO2,
|
||||
|
||||
/* Last entry for maximum ID */
|
||||
TPS65090_REGULATOR_MAX,
|
||||
};
|
||||
|
||||
struct tps65090 {
|
||||
struct mutex lock;
|
||||
struct device *dev;
|
||||
|
@ -41,10 +60,26 @@ struct tps65090_subdev_info {
|
|||
void *platform_data;
|
||||
};
|
||||
|
||||
/*
|
||||
* struct tps65090_regulator_plat_data
|
||||
*
|
||||
* @reg_init_data: The regulator init data.
|
||||
* @enable_ext_control: Enable extrenal control or not. Only available for
|
||||
* DCDC1, DCDC2 and DCDC3.
|
||||
* @gpio: Gpio number if external control is enabled and controlled through
|
||||
* gpio.
|
||||
*/
|
||||
struct tps65090_regulator_plat_data {
|
||||
struct regulator_init_data *reg_init_data;
|
||||
bool enable_ext_control;
|
||||
int gpio;
|
||||
};
|
||||
|
||||
struct tps65090_platform_data {
|
||||
int irq_base;
|
||||
int num_subdevs;
|
||||
struct tps65090_subdev_info *subdevs;
|
||||
struct tps65090_regulator_plat_data *reg_pdata[TPS65090_REGULATOR_MAX];
|
||||
};
|
||||
|
||||
/*
|
||||
|
|
|
@ -181,6 +181,8 @@ enum regulator_type {
|
|||
* @type: Indicates if the regulator is a voltage or current regulator.
|
||||
* @owner: Module providing the regulator, used for refcounting.
|
||||
*
|
||||
* @continuous_voltage_range: Indicates if the regulator can set any
|
||||
* voltage within constrains range.
|
||||
* @n_voltages: Number of selectors available for ops.list_voltage().
|
||||
*
|
||||
* @min_uV: Voltage given by the lowest selector (if linear mapping)
|
||||
|
@ -199,6 +201,7 @@ struct regulator_desc {
|
|||
const char *name;
|
||||
const char *supply_name;
|
||||
int id;
|
||||
bool continuous_voltage_range;
|
||||
unsigned n_voltages;
|
||||
struct regulator_ops *ops;
|
||||
int irq;
|
||||
|
|
|
@ -0,0 +1,47 @@
|
|||
/*
|
||||
* tps51632-regulator.h -- TPS51632 regulator
|
||||
*
|
||||
* Interface for regulator driver for TPS51632 3-2-1 Phase D-Cap Step Down
|
||||
* Driverless Controller with serial VID control and DVFS.
|
||||
*
|
||||
* Copyright (C) 2012 NVIDIA Corporation
|
||||
|
||||
* Author: Laxman Dewangan <ldewangan@nvidia.com>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
* 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.,
|
||||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef __LINUX_REGULATOR_TPS51632_H
|
||||
#define __LINUX_REGULATOR_TPS51632_H
|
||||
|
||||
/*
|
||||
* struct tps51632_regulator_platform_data - tps51632 regulator platform data.
|
||||
*
|
||||
* @reg_init_data: The regulator init data.
|
||||
* @enable_pwm_dvfs: Enable PWM DVFS or not.
|
||||
* @dvfs_step_20mV: Step for DVFS is 20mV or 10mV.
|
||||
* @max_voltage_uV: Maximum possible voltage in PWM-DVFS mode.
|
||||
* @base_voltage_uV: Base voltage when PWM-DVFS enabled.
|
||||
*/
|
||||
struct tps51632_regulator_platform_data {
|
||||
struct regulator_init_data *reg_init_data;
|
||||
bool enable_pwm_dvfs;
|
||||
bool dvfs_step_20mV;
|
||||
int max_voltage_uV;
|
||||
int base_voltage_uV;
|
||||
};
|
||||
|
||||
#endif /* __LINUX_REGULATOR_TPS51632_H */
|
|
@ -1,50 +0,0 @@
|
|||
/*
|
||||
* Regulator driver interface for TI TPS65090 PMIC family
|
||||
*
|
||||
* Copyright (c) 2012, NVIDIA CORPORATION. All rights reserved.
|
||||
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms and conditions of the GNU General Public License,
|
||||
* version 2, as published by the Free Software Foundation.
|
||||
|
||||
* This program is distributed in the hope 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.
|
||||
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef __REGULATOR_TPS65090_H
|
||||
#define __REGULATOR_TPS65090_H
|
||||
|
||||
#include <linux/regulator/machine.h>
|
||||
|
||||
#define tps65090_rails(_name) "tps65090_"#_name
|
||||
|
||||
enum {
|
||||
TPS65090_ID_DCDC1,
|
||||
TPS65090_ID_DCDC2,
|
||||
TPS65090_ID_DCDC3,
|
||||
TPS65090_ID_FET1,
|
||||
TPS65090_ID_FET2,
|
||||
TPS65090_ID_FET3,
|
||||
TPS65090_ID_FET4,
|
||||
TPS65090_ID_FET5,
|
||||
TPS65090_ID_FET6,
|
||||
TPS65090_ID_FET7,
|
||||
};
|
||||
|
||||
/*
|
||||
* struct tps65090_regulator_platform_data
|
||||
*
|
||||
* @regulator: The regulator init data.
|
||||
* @slew_rate_uV_per_us: Slew rate microvolt per microsec.
|
||||
*/
|
||||
|
||||
struct tps65090_regulator_platform_data {
|
||||
struct regulator_init_data regulator;
|
||||
};
|
||||
|
||||
#endif /* __REGULATOR_TPS65090_H */
|
Loading…
Reference in New Issue