mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git
synced 2025-01-09 14:43:16 +00:00
regulator: Updates for v3.8
A fairly quiet release again, a couple of relatively small new features and a bunch of driver specific work including yet more code elimination and fixes from Axel Lin. - Addidion of linear_min_sel for offsetting linear selectors in the helpers. - Support for continuous voltage ranges for regulators with extremely high resolution. - Drivers for AS3711, DA9055, MAX9873, TPS51632, TPS80031 and ARM vexpress. -----BEGIN PGP SIGNATURE----- Version: GnuPG v1.4.12 (GNU/Linux) iQIcBAABAgAGBQJQxyvhAAoJELSic+t+oim9F90P+QEQl/gNYmusoGbUmmgnybft hHmxpJXKhUSMSm7Lju3FLBhA7+gGnm1baWhOBGWMKM5iawlpHSUcognO2LRwRRiT d54RS6+J5vUR6AE/w4EEaIBPcgg6kAXpwe9Q22EAfJTPTndTjSuKu8HikKkMw89H RX964WKPfJDBrNBxfcJMWyQUR+89q3BcXk3oKWK5RTGJ+TvjvPnNd66/or5x+a7A H9xov93MMWBiS59MxUeAO7DTIOZg2p3TIPHlUFW3hoobbOe0EWdvqkpDJYW75ss9 53B/pO/wsct6yVu86zD8MGo0Uzu7NE3zZoR2q0EflPHV+A5U6DiOS+jW6hk+0v/B gUhreHiCNZ8veHzLujAuuESGeZG8W5qtavMI2em3eeIkGNogBMiAjwZqNfOWce/+ G3wVdpKhdGFXa4zmlD5yfOeXpjXb3agSP8i0hG/pVkDuok6KU/BnzTOi+m6uagdF GfJJI4fgoa0s02H/AicVMY2NOFBeQWPuyGTFA73tsUa0uhSPYlf0nZdIkmDYN3QX r8az6j0p3JRpvQEcADezdzcSGU6ulx5UljZn089kFDulIumjRM4fcbPWIeednvYg P3+CUmpE/xktPuohTg/si/KiJiUS/gIw2FHGrGp3TpcmoXFgcI9uKu/F2OGCZfGT t2ZqLsA6vn06Cvweml2/ =2d65 -----END PGP SIGNATURE----- Merge tag 'regulator-3.8' of git://git.kernel.org/pub/scm/linux/kernel/git/broonie/regulator Pull regulator updates from Mark Brown: "A fairly quiet release again, a couple of relatively small new features and a bunch of driver specific work including yet more code elimination and fixes from Axel Lin. - Addidion of linear_min_sel for offsetting linear selectors in the helpers. - Support for continuous voltage ranges for regulators with extremely high resolution. - Drivers for AS3711, DA9055, MAX9873, TPS51632, TPS80031 and ARM vexpress." Fix up trivial conflict (due to typo fix) in palmas-regulator.c * tag 'regulator-3.8' of git://git.kernel.org/pub/scm/linux/kernel/git/broonie/regulator: (80 commits) regulator: core: Fix logic to determinate if regulator can change voltage regulator: s5m8767: Fix to work even if no DVS gpio present regulator: s5m8767: Fix to read the first DVS register. regulator: s5m8767: Fix to work when platform registers less regulators regulator: gpio-regulator: gpio_set_value should use cansleep regulator: gpio-regulator: Fix logical error in for() loop regulator: anatop: Use regulator_[get|set]_voltage_sel_regmap regulator: anatop: Use linear_min_sel with linear mapping regulator: max1586: Implement get_voltage_sel callback regulator: lp8788-buck: Kill _gpio_request function regulator: tps80031: Convert tps80031_ldo_ops to linear_min_sel and list_voltage_linear regulator: lp8788-ldo: Remove val array in lp8788_config_ldo_enable_mode regulator: gpio-regulator: Add ifdef CONFIG_OF guard for regulator_gpio_of_match regulator: palmas: Convert palmas_ops_smps to regulator_[get|set]_voltage_sel_regmap regulator: palmas: Return raw register values as the selectors in [get|set]_voltage_sel regulators: add regulator_can_change_voltage() function regulator: tps51632: Ensure [base|max]_voltage_uV pdata settings are valid regulator: wm831x-dcdc: Add MODULE_ALIAS for wm831x-boostp regulator: wm831x-dcdc: Ensure selected voltage falls within requested range regulator: tps51632: Use linear_min_sel and regulator_[map|list]_voltage_linear ...
This commit is contained in:
commit
8b0cab1495
@ -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,146 @@
|
||||
* Maxim MAX8997 Voltage and Current Regulator
|
||||
|
||||
The Maxim MAX8997 is a multi-function device which includes volatage and
|
||||
current regulators, rtc, charger controller and other sub-blocks. It is
|
||||
interfaced to the host controller using a i2c interface. Each sub-block is
|
||||
addressed by the host system using different i2c slave address. This document
|
||||
describes the bindings for 'pmic' sub-block of max8997.
|
||||
|
||||
Required properties:
|
||||
- compatible: Should be "maxim,max8997-pmic".
|
||||
- reg: Specifies the i2c slave address of the pmic block. It should be 0x66.
|
||||
|
||||
- max8997,pmic-buck1-dvs-voltage: A set of 8 voltage values in micro-volt (uV)
|
||||
units for buck1 when changing voltage using gpio dvs. Refer to [1] below
|
||||
for additional information.
|
||||
|
||||
- max8997,pmic-buck2-dvs-voltage: A set of 8 voltage values in micro-volt (uV)
|
||||
units for buck2 when changing voltage using gpio dvs. Refer to [1] below
|
||||
for additional information.
|
||||
|
||||
- max8997,pmic-buck5-dvs-voltage: A set of 8 voltage values in micro-volt (uV)
|
||||
units for buck5 when changing voltage using gpio dvs. Refer to [1] below
|
||||
for additional information.
|
||||
|
||||
[1] If none of the 'max8997,pmic-buck[1/2/5]-uses-gpio-dvs' optional
|
||||
property is specified, the 'max8997,pmic-buck[1/2/5]-dvs-voltage'
|
||||
property should specify atleast one voltage level (which would be a
|
||||
safe operating voltage).
|
||||
|
||||
If either of the 'max8997,pmic-buck[1/2/5]-uses-gpio-dvs' optional
|
||||
property is specified, then all the eigth voltage values for the
|
||||
'max8997,pmic-buck[1/2/5]-dvs-voltage' should be specified.
|
||||
|
||||
Optional properties:
|
||||
- interrupt-parent: Specifies the phandle of the interrupt controller to which
|
||||
the interrupts from max8997 are delivered to.
|
||||
- interrupts: Interrupt specifiers for two interrupt sources.
|
||||
- First interrupt specifier is for 'irq1' interrupt.
|
||||
- Second interrupt specifier is for 'alert' interrupt.
|
||||
- max8997,pmic-buck1-uses-gpio-dvs: 'buck1' can be controlled by gpio dvs.
|
||||
- max8997,pmic-buck2-uses-gpio-dvs: 'buck2' can be controlled by gpio dvs.
|
||||
- max8997,pmic-buck5-uses-gpio-dvs: 'buck5' can be controlled by gpio dvs.
|
||||
|
||||
Additional properties required if either of the optional properties are used:
|
||||
- max8997,pmic-ignore-gpiodvs-side-effect: When GPIO-DVS mode is used for
|
||||
multiple bucks, changing the voltage value of one of the bucks may affect
|
||||
that of another buck, which is the side effect of the change (set_voltage).
|
||||
Use this property to ignore such side effects and change the voltage.
|
||||
|
||||
- max8997,pmic-buck125-default-dvs-idx: Default voltage setting selected from
|
||||
the possible 8 options selectable by the dvs gpios. The value of this
|
||||
property should be between 0 and 7. If not specified or if out of range, the
|
||||
default value of this property is set to 0.
|
||||
|
||||
- max8997,pmic-buck125-dvs-gpios: GPIO specifiers for three host gpio's used
|
||||
for dvs. The format of the gpio specifier depends in the gpio controller.
|
||||
|
||||
Regulators: The regulators of max8997 that have to be instantiated should be
|
||||
included in a sub-node named 'regulators'. Regulator nodes included in this
|
||||
sub-node should be of the format as listed below.
|
||||
|
||||
regulator_name {
|
||||
standard regulator bindings here
|
||||
};
|
||||
|
||||
The following are the names of the regulators that the max8997 pmic block
|
||||
supports. Note: The 'n' in LDOn and BUCKn represents the LDO or BUCK number
|
||||
as per the datasheet of max8997.
|
||||
|
||||
- LDOn
|
||||
- valid values for n are 1 to 18 and 21
|
||||
- Example: LDO0, LD01, LDO2, LDO21
|
||||
- BUCKn
|
||||
- valid values for n are 1 to 7.
|
||||
- Example: BUCK1, BUCK2, BUCK3, BUCK7
|
||||
|
||||
- ENVICHG: Battery Charging Current Monitor Output. This is a fixed
|
||||
voltage type regulator
|
||||
|
||||
- ESAFEOUT1: (ldo19)
|
||||
- ESAFEOUT2: (ld020)
|
||||
|
||||
- CHARGER_CV: main battery charger voltage control
|
||||
- CHARGER: main battery charger current control
|
||||
- CHARGER_TOPOFF: end of charge current threshold level
|
||||
|
||||
The bindings inside the regulator nodes use the standard regulator bindings
|
||||
which are documented elsewhere.
|
||||
|
||||
Example:
|
||||
|
||||
max8997_pmic@66 {
|
||||
compatible = "maxim,max8997-pmic";
|
||||
interrupt-parent = <&wakeup_eint>;
|
||||
reg = <0x66>;
|
||||
interrupts = <4 0>, <3 0>;
|
||||
|
||||
max8997,pmic-buck1-uses-gpio-dvs;
|
||||
max8997,pmic-buck2-uses-gpio-dvs;
|
||||
max8997,pmic-buck5-uses-gpio-dvs;
|
||||
|
||||
max8997,pmic-ignore-gpiodvs-side-effect;
|
||||
max8997,pmic-buck125-default-dvs-idx = <0>;
|
||||
|
||||
max8997,pmic-buck125-dvs-gpios = <&gpx0 0 1 0 0>, /* SET1 */
|
||||
<&gpx0 1 1 0 0>, /* SET2 */
|
||||
<&gpx0 2 1 0 0>; /* SET3 */
|
||||
|
||||
max8997,pmic-buck1-dvs-voltage = <1350000>, <1300000>,
|
||||
<1250000>, <1200000>,
|
||||
<1150000>, <1100000>,
|
||||
<1000000>, <950000>;
|
||||
|
||||
max8997,pmic-buck2-dvs-voltage = <1100000>, <1100000>,
|
||||
<1100000>, <1100000>,
|
||||
<1000000>, <1000000>,
|
||||
<1000000>, <1000000>;
|
||||
|
||||
max8997,pmic-buck5-dvs-voltage = <1200000>, <1200000>,
|
||||
<1200000>, <1200000>,
|
||||
<1200000>, <1200000>,
|
||||
<1200000>, <1200000>;
|
||||
|
||||
regulators {
|
||||
ldo1_reg: LDO1 {
|
||||
regulator-name = "VDD_ABB_3.3V";
|
||||
regulator-min-microvolt = <3300000>;
|
||||
regulator-max-microvolt = <3300000>;
|
||||
};
|
||||
|
||||
ldo2_reg: LDO2 {
|
||||
regulator-name = "VDD_ALIVE_1.1V";
|
||||
regulator-min-microvolt = <1100000>;
|
||||
regulator-max-microvolt = <1100000>;
|
||||
regulator-always-on;
|
||||
};
|
||||
|
||||
buck1_reg: BUCK1 {
|
||||
regulator-name = "VDD_ARM_1.2V";
|
||||
regulator-min-microvolt = <950000>;
|
||||
regulator-max-microvolt = <1350000>;
|
||||
regulator-always-on;
|
||||
regulator-boot-on;
|
||||
};
|
||||
};
|
||||
};
|
32
Documentation/devicetree/bindings/regulator/vexpress.txt
Normal file
32
Documentation/devicetree/bindings/regulator/vexpress.txt
Normal file
@ -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;
|
||||
};
|
@ -211,7 +211,6 @@ config MFD_TPS6586X
|
||||
depends on I2C=y && GENERIC_HARDIRQS
|
||||
select MFD_CORE
|
||||
select REGMAP_I2C
|
||||
depends on REGULATOR
|
||||
help
|
||||
If you say yes here you get support for the TPS6586X series of
|
||||
Power Management chips.
|
||||
|
@ -21,8 +21,10 @@
|
||||
* This driver is based on max8998.c
|
||||
*/
|
||||
|
||||
#include <linux/err.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/i2c.h>
|
||||
#include <linux/of_irq.h>
|
||||
#include <linux/interrupt.h>
|
||||
#include <linux/pm_runtime.h>
|
||||
#include <linux/module.h>
|
||||
@ -47,6 +49,13 @@ static struct mfd_cell max8997_devs[] = {
|
||||
{ .name = "max8997-led", .id = 2 },
|
||||
};
|
||||
|
||||
#ifdef CONFIG_OF
|
||||
static struct of_device_id __devinitdata max8997_pmic_dt_match[] = {
|
||||
{ .compatible = "maxim,max8997-pmic", .data = TYPE_MAX8997 },
|
||||
{},
|
||||
};
|
||||
#endif
|
||||
|
||||
int max8997_read_reg(struct i2c_client *i2c, u8 reg, u8 *dest)
|
||||
{
|
||||
struct max8997_dev *max8997 = i2c_get_clientdata(i2c);
|
||||
@ -123,6 +132,58 @@ int max8997_update_reg(struct i2c_client *i2c, u8 reg, u8 val, u8 mask)
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(max8997_update_reg);
|
||||
|
||||
#ifdef CONFIG_OF
|
||||
/*
|
||||
* Only the common platform data elements for max8997 are parsed here from the
|
||||
* device tree. Other sub-modules of max8997 such as pmic, rtc and others have
|
||||
* to parse their own platform data elements from device tree.
|
||||
*
|
||||
* The max8997 platform data structure is instantiated here and the drivers for
|
||||
* the sub-modules need not instantiate another instance while parsing their
|
||||
* platform data.
|
||||
*/
|
||||
static struct max8997_platform_data *max8997_i2c_parse_dt_pdata(
|
||||
struct device *dev)
|
||||
{
|
||||
struct max8997_platform_data *pd;
|
||||
|
||||
pd = devm_kzalloc(dev, sizeof(*pd), GFP_KERNEL);
|
||||
if (!pd) {
|
||||
dev_err(dev, "could not allocate memory for pdata\n");
|
||||
return ERR_PTR(-ENOMEM);
|
||||
}
|
||||
|
||||
pd->ono = irq_of_parse_and_map(dev->of_node, 1);
|
||||
|
||||
/*
|
||||
* ToDo: the 'wakeup' member in the platform data is more of a linux
|
||||
* specfic information. Hence, there is no binding for that yet and
|
||||
* not parsed here.
|
||||
*/
|
||||
|
||||
return pd;
|
||||
}
|
||||
#else
|
||||
static struct max8997_platform_data *max8997_i2c_parse_dt_pdata(
|
||||
struct device *dev)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
static inline int max8997_i2c_get_driver_data(struct i2c_client *i2c,
|
||||
const struct i2c_device_id *id)
|
||||
{
|
||||
#ifdef CONFIG_OF
|
||||
if (i2c->dev.of_node) {
|
||||
const struct of_device_id *match;
|
||||
match = of_match_node(max8997_pmic_dt_match, i2c->dev.of_node);
|
||||
return (int)match->data;
|
||||
}
|
||||
#endif
|
||||
return (int)id->driver_data;
|
||||
}
|
||||
|
||||
static int max8997_i2c_probe(struct i2c_client *i2c,
|
||||
const struct i2c_device_id *id)
|
||||
{
|
||||
@ -137,12 +198,21 @@ static int max8997_i2c_probe(struct i2c_client *i2c,
|
||||
i2c_set_clientdata(i2c, max8997);
|
||||
max8997->dev = &i2c->dev;
|
||||
max8997->i2c = i2c;
|
||||
max8997->type = id->driver_data;
|
||||
max8997->type = max8997_i2c_get_driver_data(i2c, id);
|
||||
max8997->irq = i2c->irq;
|
||||
|
||||
if (max8997->dev->of_node) {
|
||||
pdata = max8997_i2c_parse_dt_pdata(max8997->dev);
|
||||
if (IS_ERR(pdata)) {
|
||||
ret = PTR_ERR(pdata);
|
||||
goto err;
|
||||
}
|
||||
}
|
||||
|
||||
if (!pdata)
|
||||
goto err;
|
||||
|
||||
max8997->pdata = pdata;
|
||||
max8997->ono = pdata->ono;
|
||||
|
||||
mutex_init(&max8997->iolock);
|
||||
@ -434,6 +504,7 @@ static struct i2c_driver max8997_i2c_driver = {
|
||||
.name = "max8997",
|
||||
.owner = THIS_MODULE,
|
||||
.pm = &max8997_pm,
|
||||
.of_match_table = of_match_ptr(max8997_pmic_dt_match),
|
||||
},
|
||||
.probe = max8997_i2c_probe,
|
||||
.remove = max8997_i2c_remove,
|
||||
|
@ -24,8 +24,6 @@
|
||||
#include <linux/err.h>
|
||||
#include <linux/i2c.h>
|
||||
#include <linux/regmap.h>
|
||||
#include <linux/regulator/of_regulator.h>
|
||||
#include <linux/regulator/machine.h>
|
||||
|
||||
#include <linux/mfd/core.h>
|
||||
#include <linux/mfd/tps6586x.h>
|
||||
@ -98,6 +96,9 @@ static struct mfd_cell tps6586x_cell[] = {
|
||||
{
|
||||
.name = "tps6586x-gpio",
|
||||
},
|
||||
{
|
||||
.name = "tps6586x-pmic",
|
||||
},
|
||||
{
|
||||
.name = "tps6586x-rtc",
|
||||
},
|
||||
@ -350,80 +351,19 @@ failed:
|
||||
}
|
||||
|
||||
#ifdef CONFIG_OF
|
||||
static struct of_regulator_match tps6586x_matches[] = {
|
||||
{ .name = "sys", .driver_data = (void *)TPS6586X_ID_SYS },
|
||||
{ .name = "sm0", .driver_data = (void *)TPS6586X_ID_SM_0 },
|
||||
{ .name = "sm1", .driver_data = (void *)TPS6586X_ID_SM_1 },
|
||||
{ .name = "sm2", .driver_data = (void *)TPS6586X_ID_SM_2 },
|
||||
{ .name = "ldo0", .driver_data = (void *)TPS6586X_ID_LDO_0 },
|
||||
{ .name = "ldo1", .driver_data = (void *)TPS6586X_ID_LDO_1 },
|
||||
{ .name = "ldo2", .driver_data = (void *)TPS6586X_ID_LDO_2 },
|
||||
{ .name = "ldo3", .driver_data = (void *)TPS6586X_ID_LDO_3 },
|
||||
{ .name = "ldo4", .driver_data = (void *)TPS6586X_ID_LDO_4 },
|
||||
{ .name = "ldo5", .driver_data = (void *)TPS6586X_ID_LDO_5 },
|
||||
{ .name = "ldo6", .driver_data = (void *)TPS6586X_ID_LDO_6 },
|
||||
{ .name = "ldo7", .driver_data = (void *)TPS6586X_ID_LDO_7 },
|
||||
{ .name = "ldo8", .driver_data = (void *)TPS6586X_ID_LDO_8 },
|
||||
{ .name = "ldo9", .driver_data = (void *)TPS6586X_ID_LDO_9 },
|
||||
{ .name = "ldo_rtc", .driver_data = (void *)TPS6586X_ID_LDO_RTC },
|
||||
};
|
||||
|
||||
static struct tps6586x_platform_data *tps6586x_parse_dt(struct i2c_client *client)
|
||||
{
|
||||
const unsigned int num = ARRAY_SIZE(tps6586x_matches);
|
||||
struct device_node *np = client->dev.of_node;
|
||||
struct tps6586x_platform_data *pdata;
|
||||
struct tps6586x_subdev_info *devs;
|
||||
struct device_node *regs;
|
||||
const char *sys_rail_name = NULL;
|
||||
unsigned int count;
|
||||
unsigned int i, j;
|
||||
int err;
|
||||
|
||||
regs = of_find_node_by_name(np, "regulators");
|
||||
if (!regs)
|
||||
return NULL;
|
||||
|
||||
err = of_regulator_match(&client->dev, regs, tps6586x_matches, num);
|
||||
if (err < 0) {
|
||||
of_node_put(regs);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
of_node_put(regs);
|
||||
count = err;
|
||||
|
||||
devs = devm_kzalloc(&client->dev, count * sizeof(*devs), GFP_KERNEL);
|
||||
if (!devs)
|
||||
return NULL;
|
||||
|
||||
for (i = 0, j = 0; i < num && j < count; i++) {
|
||||
struct regulator_init_data *reg_idata;
|
||||
|
||||
if (!tps6586x_matches[i].init_data)
|
||||
continue;
|
||||
|
||||
reg_idata = tps6586x_matches[i].init_data;
|
||||
devs[j].name = "tps6586x-regulator";
|
||||
devs[j].platform_data = tps6586x_matches[i].init_data;
|
||||
devs[j].id = (int)tps6586x_matches[i].driver_data;
|
||||
if (devs[j].id == TPS6586X_ID_SYS)
|
||||
sys_rail_name = reg_idata->constraints.name;
|
||||
|
||||
if ((devs[j].id == TPS6586X_ID_LDO_5) ||
|
||||
(devs[j].id == TPS6586X_ID_LDO_RTC))
|
||||
reg_idata->supply_regulator = sys_rail_name;
|
||||
|
||||
devs[j].of_node = tps6586x_matches[i].of_node;
|
||||
j++;
|
||||
}
|
||||
|
||||
pdata = devm_kzalloc(&client->dev, sizeof(*pdata), GFP_KERNEL);
|
||||
if (!pdata)
|
||||
if (!pdata) {
|
||||
dev_err(&client->dev, "Memory allocation failed\n");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
pdata->num_subdevs = count;
|
||||
pdata->subdevs = devs;
|
||||
pdata->num_subdevs = 0;
|
||||
pdata->subdevs = NULL;
|
||||
pdata->gpio_base = -1;
|
||||
pdata->irq_base = -1;
|
||||
pdata->pm_off = of_property_read_bool(np, "ti,system-power-controller");
|
||||
|
@ -258,6 +258,7 @@ static const struct reg_default wm5102_reg_default[] = {
|
||||
{ 0x00000154, 0x0000 }, /* R340 - Rate Estimator 3 */
|
||||
{ 0x00000155, 0x0000 }, /* R341 - Rate Estimator 4 */
|
||||
{ 0x00000156, 0x0000 }, /* R342 - Rate Estimator 5 */
|
||||
{ 0x00000161, 0x0000 }, /* R353 - Dynamic Frequency Scaling 1 */
|
||||
{ 0x00000171, 0x0000 }, /* R369 - FLL1 Control 1 */
|
||||
{ 0x00000172, 0x0008 }, /* R370 - FLL1 Control 2 */
|
||||
{ 0x00000173, 0x0018 }, /* R371 - FLL1 Control 3 */
|
||||
@ -1047,6 +1048,7 @@ static bool wm5102_readable_register(struct device *dev, unsigned int reg)
|
||||
case ARIZONA_RATE_ESTIMATOR_3:
|
||||
case ARIZONA_RATE_ESTIMATOR_4:
|
||||
case ARIZONA_RATE_ESTIMATOR_5:
|
||||
case ARIZONA_DYNAMIC_FREQUENCY_SCALING_1:
|
||||
case ARIZONA_FLL1_CONTROL_1:
|
||||
case ARIZONA_FLL1_CONTROL_2:
|
||||
case ARIZONA_FLL1_CONTROL_3:
|
||||
@ -1079,6 +1081,7 @@ static bool wm5102_readable_register(struct device *dev, unsigned int reg)
|
||||
case ARIZONA_FLL2_GPIO_CLOCK:
|
||||
case ARIZONA_MIC_CHARGE_PUMP_1:
|
||||
case ARIZONA_LDO1_CONTROL_1:
|
||||
case ARIZONA_LDO1_CONTROL_2:
|
||||
case ARIZONA_LDO2_CONTROL_1:
|
||||
case ARIZONA_MIC_BIAS_CTRL_1:
|
||||
case ARIZONA_MIC_BIAS_CTRL_2:
|
||||
|
@ -394,7 +394,7 @@ static int pm8607_regulator_dt_init(struct platform_device *pdev,
|
||||
#define pm8607_regulator_dt_init(x, y, z) (-1)
|
||||
#endif
|
||||
|
||||
static int __devinit pm8607_regulator_probe(struct platform_device *pdev)
|
||||
static int pm8607_regulator_probe(struct platform_device *pdev)
|
||||
{
|
||||
struct pm860x_chip *chip = dev_get_drvdata(pdev->dev.parent);
|
||||
struct pm8607_regulator_info *info = NULL;
|
||||
@ -454,7 +454,7 @@ static int __devinit pm8607_regulator_probe(struct platform_device *pdev)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int __devexit pm8607_regulator_remove(struct platform_device *pdev)
|
||||
static int pm8607_regulator_remove(struct platform_device *pdev)
|
||||
{
|
||||
struct pm8607_regulator_info *info = platform_get_drvdata(pdev);
|
||||
|
||||
@ -481,7 +481,7 @@ static struct platform_driver pm8607_regulator_driver = {
|
||||
.owner = THIS_MODULE,
|
||||
},
|
||||
.probe = pm8607_regulator_probe,
|
||||
.remove = __devexit_p(pm8607_regulator_remove),
|
||||
.remove = pm8607_regulator_remove,
|
||||
.id_table = pm8607_regulator_driver_ids,
|
||||
};
|
||||
|
||||
|
@ -109,6 +109,16 @@ config REGULATOR_DA9052
|
||||
This driver supports the voltage regulators of DA9052-BC and
|
||||
DA9053-AA/Bx PMIC.
|
||||
|
||||
config REGULATOR_DA9055
|
||||
tristate "Dialog Semiconductor DA9055 regulators"
|
||||
depends on MFD_DA9055
|
||||
help
|
||||
Say y here to support the BUCKs and LDOs regulators found on
|
||||
Dialog Semiconductor DA9055 PMIC.
|
||||
|
||||
This driver can also be built as a module. If so, the module
|
||||
will be called da9055-regulator.
|
||||
|
||||
config REGULATOR_FAN53555
|
||||
tristate "Fairchild FAN53555 Regulator"
|
||||
depends on I2C
|
||||
@ -204,6 +214,16 @@ config REGULATOR_MAX8952
|
||||
via I2C bus. Maxim 8952 has one voltage output and supports 4 DVS
|
||||
modes ranging from 0.77V to 1.40V by 0.01V steps.
|
||||
|
||||
config REGULATOR_MAX8973
|
||||
tristate "Maxim MAX8973 voltage regulator "
|
||||
depends on I2C
|
||||
select REGMAP_I2C
|
||||
help
|
||||
The MAXIM MAX8973 high-efficiency. three phase, DC-DC step-down
|
||||
switching regulator delievers up to 9A of output current. Each
|
||||
phase operates at a 2MHz fixed frequency with a 120 deg shift
|
||||
from the adjacent phase, allowing the use of small magnetic component.
|
||||
|
||||
config REGULATOR_MAX8997
|
||||
tristate "Maxim 8997/8966 regulator"
|
||||
depends on MFD_MAX8997
|
||||
@ -335,6 +355,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 +446,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 +462,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
|
||||
@ -450,5 +497,12 @@ config REGULATOR_WM8994
|
||||
This driver provides support for the voltage regulators on the
|
||||
WM8994 CODEC.
|
||||
|
||||
config REGULATOR_AS3711
|
||||
tristate "AS3711 PMIC"
|
||||
depends on MFD_AS3711
|
||||
help
|
||||
This driver provides support for the voltage regulators on the
|
||||
AS3711 PMIC
|
||||
|
||||
endif
|
||||
|
||||
|
@ -16,8 +16,10 @@ obj-$(CONFIG_REGULATOR_AB8500) += ab8500.o
|
||||
obj-$(CONFIG_REGULATOR_AD5398) += ad5398.o
|
||||
obj-$(CONFIG_REGULATOR_ANATOP) += anatop-regulator.o
|
||||
obj-$(CONFIG_REGULATOR_ARIZONA) += arizona-micsupp.o arizona-ldo1.o
|
||||
obj-$(CONFIG_REGULATOR_AS3711) += as3711-regulator.o
|
||||
obj-$(CONFIG_REGULATOR_DA903X) += da903x.o
|
||||
obj-$(CONFIG_REGULATOR_DA9052) += da9052-regulator.o
|
||||
obj-$(CONFIG_REGULATOR_DA9055) += da9055-regulator.o
|
||||
obj-$(CONFIG_REGULATOR_DBX500_PRCMU) += dbx500-prcmu.o
|
||||
obj-$(CONFIG_REGULATOR_DB8500_PRCMU) += db8500-prcmu.o
|
||||
obj-$(CONFIG_REGULATOR_FAN53555) += fan53555.o
|
||||
@ -34,6 +36,7 @@ obj-$(CONFIG_REGULATOR_MAX8660) += max8660.o
|
||||
obj-$(CONFIG_REGULATOR_MAX8907) += max8907-regulator.o
|
||||
obj-$(CONFIG_REGULATOR_MAX8925) += max8925-regulator.o
|
||||
obj-$(CONFIG_REGULATOR_MAX8952) += max8952.o
|
||||
obj-$(CONFIG_REGULATOR_MAX8973) += max8973-regulator.o
|
||||
obj-$(CONFIG_REGULATOR_MAX8997) += max8997.o
|
||||
obj-$(CONFIG_REGULATOR_MAX8998) += max8998.o
|
||||
obj-$(CONFIG_REGULATOR_MAX77686) += max77686.o
|
||||
@ -41,6 +44,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 +60,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
|
||||
|
@ -187,7 +187,7 @@ static int aat2870_regulator_probe(struct platform_device *pdev)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int __devexit aat2870_regulator_remove(struct platform_device *pdev)
|
||||
static int aat2870_regulator_remove(struct platform_device *pdev)
|
||||
{
|
||||
struct regulator_dev *rdev = platform_get_drvdata(pdev);
|
||||
|
||||
@ -201,7 +201,7 @@ static struct platform_driver aat2870_regulator_driver = {
|
||||
.owner = THIS_MODULE,
|
||||
},
|
||||
.probe = aat2870_regulator_probe,
|
||||
.remove = __devexit_p(aat2870_regulator_remove),
|
||||
.remove = aat2870_regulator_remove,
|
||||
};
|
||||
|
||||
static int __init aat2870_regulator_init(void)
|
||||
|
@ -494,7 +494,7 @@ ab3100_regulator_desc[AB3100_NUM_REGULATORS] = {
|
||||
* for all the different regulators.
|
||||
*/
|
||||
|
||||
static int __devinit ab3100_regulators_probe(struct platform_device *pdev)
|
||||
static int ab3100_regulators_probe(struct platform_device *pdev)
|
||||
{
|
||||
struct ab3100_platform_data *plfdata = pdev->dev.platform_data;
|
||||
struct regulator_config config = { };
|
||||
@ -571,7 +571,7 @@ static int __devinit ab3100_regulators_probe(struct platform_device *pdev)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int __devexit ab3100_regulators_remove(struct platform_device *pdev)
|
||||
static int ab3100_regulators_remove(struct platform_device *pdev)
|
||||
{
|
||||
int i;
|
||||
|
||||
@ -589,7 +589,7 @@ static struct platform_driver ab3100_regulators_driver = {
|
||||
.owner = THIS_MODULE,
|
||||
},
|
||||
.probe = ab3100_regulators_probe,
|
||||
.remove = __devexit_p(ab3100_regulators_remove),
|
||||
.remove = ab3100_regulators_remove,
|
||||
};
|
||||
|
||||
static __init int ab3100_regulators_init(void)
|
||||
|
@ -641,7 +641,7 @@ static struct ab8500_reg_init ab8500_reg_init[] = {
|
||||
REG_INIT(AB8500_REGUCTRLDISCH2, 0x04, 0x44, 0x16),
|
||||
};
|
||||
|
||||
static __devinit int
|
||||
static int
|
||||
ab8500_regulator_init_registers(struct platform_device *pdev, int id, int value)
|
||||
{
|
||||
int err;
|
||||
@ -676,7 +676,7 @@ ab8500_regulator_init_registers(struct platform_device *pdev, int id, int value)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static __devinit int ab8500_regulator_register(struct platform_device *pdev,
|
||||
static int ab8500_regulator_register(struct platform_device *pdev,
|
||||
struct regulator_init_data *init_data,
|
||||
int id,
|
||||
struct device_node *np)
|
||||
@ -735,7 +735,7 @@ static struct of_regulator_match ab8500_regulator_matches[] = {
|
||||
{ .name = "ab8500_ldo_ana", .driver_data = (void *) AB8500_LDO_ANA, },
|
||||
};
|
||||
|
||||
static __devinit int
|
||||
static int
|
||||
ab8500_regulator_of_probe(struct platform_device *pdev, struct device_node *np)
|
||||
{
|
||||
int err, i;
|
||||
@ -751,7 +751,7 @@ ab8500_regulator_of_probe(struct platform_device *pdev, struct device_node *np)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static __devinit int ab8500_regulator_probe(struct platform_device *pdev)
|
||||
static int ab8500_regulator_probe(struct platform_device *pdev)
|
||||
{
|
||||
struct ab8500 *ab8500 = dev_get_drvdata(pdev->dev.parent);
|
||||
struct ab8500_platform_data *pdata;
|
||||
@ -817,7 +817,7 @@ static __devinit int ab8500_regulator_probe(struct platform_device *pdev)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static __devexit int ab8500_regulator_remove(struct platform_device *pdev)
|
||||
static int ab8500_regulator_remove(struct platform_device *pdev)
|
||||
{
|
||||
int i;
|
||||
|
||||
@ -836,7 +836,7 @@ static __devexit int ab8500_regulator_remove(struct platform_device *pdev)
|
||||
|
||||
static struct platform_driver ab8500_regulator_driver = {
|
||||
.probe = ab8500_regulator_probe,
|
||||
.remove = __devexit_p(ab8500_regulator_remove),
|
||||
.remove = ab8500_regulator_remove,
|
||||
.driver = {
|
||||
.name = "ab8500-regulator",
|
||||
.owner = THIS_MODULE,
|
||||
|
@ -211,7 +211,7 @@ static const struct i2c_device_id ad5398_id[] = {
|
||||
};
|
||||
MODULE_DEVICE_TABLE(i2c, ad5398_id);
|
||||
|
||||
static int __devinit ad5398_probe(struct i2c_client *client,
|
||||
static int ad5398_probe(struct i2c_client *client,
|
||||
const struct i2c_device_id *id)
|
||||
{
|
||||
struct regulator_init_data *init_data = client->dev.platform_data;
|
||||
@ -256,7 +256,7 @@ err:
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int __devexit ad5398_remove(struct i2c_client *client)
|
||||
static int ad5398_remove(struct i2c_client *client)
|
||||
{
|
||||
struct ad5398_chip_info *chip = i2c_get_clientdata(client);
|
||||
|
||||
@ -266,7 +266,7 @@ static int __devexit ad5398_remove(struct i2c_client *client)
|
||||
|
||||
static struct i2c_driver ad5398_driver = {
|
||||
.probe = ad5398_probe,
|
||||
.remove = __devexit_p(ad5398_remove),
|
||||
.remove = ad5398_remove,
|
||||
.driver = {
|
||||
.name = "ad5398",
|
||||
},
|
||||
|
@ -48,36 +48,21 @@ static int anatop_regmap_set_voltage_sel(struct regulator_dev *reg,
|
||||
unsigned selector)
|
||||
{
|
||||
struct anatop_regulator *anatop_reg = rdev_get_drvdata(reg);
|
||||
u32 val, mask;
|
||||
|
||||
if (!anatop_reg->control_reg)
|
||||
return -ENOTSUPP;
|
||||
|
||||
val = anatop_reg->min_bit_val + selector;
|
||||
dev_dbg(®->dev, "%s: calculated val %d\n", __func__, val);
|
||||
mask = ((1 << anatop_reg->vol_bit_width) - 1) <<
|
||||
anatop_reg->vol_bit_shift;
|
||||
val <<= anatop_reg->vol_bit_shift;
|
||||
regmap_update_bits(anatop_reg->anatop, anatop_reg->control_reg,
|
||||
mask, val);
|
||||
|
||||
return 0;
|
||||
return regulator_set_voltage_sel_regmap(reg, selector);
|
||||
}
|
||||
|
||||
static int anatop_regmap_get_voltage_sel(struct regulator_dev *reg)
|
||||
{
|
||||
struct anatop_regulator *anatop_reg = rdev_get_drvdata(reg);
|
||||
u32 val, mask;
|
||||
|
||||
if (!anatop_reg->control_reg)
|
||||
return -ENOTSUPP;
|
||||
|
||||
regmap_read(anatop_reg->anatop, anatop_reg->control_reg, &val);
|
||||
mask = ((1 << anatop_reg->vol_bit_width) - 1) <<
|
||||
anatop_reg->vol_bit_shift;
|
||||
val = (val & mask) >> anatop_reg->vol_bit_shift;
|
||||
|
||||
return val - anatop_reg->min_bit_val;
|
||||
return regulator_get_voltage_sel_regmap(reg);
|
||||
}
|
||||
|
||||
static struct regulator_ops anatop_rops = {
|
||||
@ -87,7 +72,7 @@ static struct regulator_ops anatop_rops = {
|
||||
.map_voltage = regulator_map_voltage_linear,
|
||||
};
|
||||
|
||||
static int __devinit anatop_regulator_probe(struct platform_device *pdev)
|
||||
static int anatop_regulator_probe(struct platform_device *pdev)
|
||||
{
|
||||
struct device *dev = &pdev->dev;
|
||||
struct device_node *np = dev->of_node;
|
||||
@ -158,15 +143,20 @@ static int __devinit anatop_regulator_probe(struct platform_device *pdev)
|
||||
goto anatop_probe_end;
|
||||
}
|
||||
|
||||
rdesc->n_voltages = (sreg->max_voltage - sreg->min_voltage)
|
||||
/ 25000 + 1;
|
||||
rdesc->n_voltages = (sreg->max_voltage - sreg->min_voltage) / 25000 + 1
|
||||
+ sreg->min_bit_val;
|
||||
rdesc->min_uV = sreg->min_voltage;
|
||||
rdesc->uV_step = 25000;
|
||||
rdesc->linear_min_sel = sreg->min_bit_val;
|
||||
rdesc->vsel_reg = sreg->control_reg;
|
||||
rdesc->vsel_mask = ((1 << sreg->vol_bit_width) - 1) <<
|
||||
sreg->vol_bit_shift;
|
||||
|
||||
config.dev = &pdev->dev;
|
||||
config.init_data = initdata;
|
||||
config.driver_data = sreg;
|
||||
config.of_node = pdev->dev.of_node;
|
||||
config.regmap = sreg->anatop;
|
||||
|
||||
/* register regulator */
|
||||
rdev = regulator_register(rdesc, &config);
|
||||
@ -186,7 +176,7 @@ anatop_probe_end:
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int __devexit anatop_regulator_remove(struct platform_device *pdev)
|
||||
static int anatop_regulator_remove(struct platform_device *pdev)
|
||||
{
|
||||
struct regulator_dev *rdev = platform_get_drvdata(pdev);
|
||||
struct anatop_regulator *sreg = rdev_get_drvdata(rdev);
|
||||
@ -210,7 +200,7 @@ static struct platform_driver anatop_regulator_driver = {
|
||||
.of_match_table = of_anatop_regulator_match_tbl,
|
||||
},
|
||||
.probe = anatop_regulator_probe,
|
||||
.remove = __devexit_p(anatop_regulator_remove),
|
||||
.remove = anatop_regulator_remove,
|
||||
};
|
||||
|
||||
static int __init anatop_regulator_init(void)
|
||||
|
@ -34,6 +34,108 @@ struct arizona_ldo1 {
|
||||
struct regulator_init_data init_data;
|
||||
};
|
||||
|
||||
static int arizona_ldo1_hc_list_voltage(struct regulator_dev *rdev,
|
||||
unsigned int selector)
|
||||
{
|
||||
if (selector >= rdev->desc->n_voltages)
|
||||
return -EINVAL;
|
||||
|
||||
if (selector == rdev->desc->n_voltages - 1)
|
||||
return 1800000;
|
||||
else
|
||||
return rdev->desc->min_uV + (rdev->desc->uV_step * selector);
|
||||
}
|
||||
|
||||
static int arizona_ldo1_hc_map_voltage(struct regulator_dev *rdev,
|
||||
int min_uV, int max_uV)
|
||||
{
|
||||
int sel;
|
||||
|
||||
sel = DIV_ROUND_UP(min_uV - rdev->desc->min_uV, rdev->desc->uV_step);
|
||||
if (sel >= rdev->desc->n_voltages)
|
||||
sel = rdev->desc->n_voltages - 1;
|
||||
|
||||
return sel;
|
||||
}
|
||||
|
||||
static int arizona_ldo1_hc_set_voltage_sel(struct regulator_dev *rdev,
|
||||
unsigned sel)
|
||||
{
|
||||
struct arizona_ldo1 *ldo = rdev_get_drvdata(rdev);
|
||||
struct regmap *regmap = ldo->arizona->regmap;
|
||||
unsigned int val;
|
||||
int ret;
|
||||
|
||||
if (sel == rdev->desc->n_voltages - 1)
|
||||
val = ARIZONA_LDO1_HI_PWR;
|
||||
else
|
||||
val = 0;
|
||||
|
||||
ret = regmap_update_bits(regmap, ARIZONA_LDO1_CONTROL_2,
|
||||
ARIZONA_LDO1_HI_PWR, val);
|
||||
if (ret != 0)
|
||||
return ret;
|
||||
|
||||
ret = regmap_update_bits(regmap, ARIZONA_DYNAMIC_FREQUENCY_SCALING_1,
|
||||
ARIZONA_SUBSYS_MAX_FREQ, val);
|
||||
if (ret != 0)
|
||||
return ret;
|
||||
|
||||
if (val)
|
||||
return 0;
|
||||
|
||||
val = sel << ARIZONA_LDO1_VSEL_SHIFT;
|
||||
|
||||
return regmap_update_bits(regmap, ARIZONA_LDO1_CONTROL_1,
|
||||
ARIZONA_LDO1_VSEL_MASK, val);
|
||||
}
|
||||
|
||||
static int arizona_ldo1_hc_get_voltage_sel(struct regulator_dev *rdev)
|
||||
{
|
||||
struct arizona_ldo1 *ldo = rdev_get_drvdata(rdev);
|
||||
struct regmap *regmap = ldo->arizona->regmap;
|
||||
unsigned int val;
|
||||
int ret;
|
||||
|
||||
ret = regmap_read(regmap, ARIZONA_LDO1_CONTROL_2, &val);
|
||||
if (ret != 0)
|
||||
return ret;
|
||||
|
||||
if (val & ARIZONA_LDO1_HI_PWR)
|
||||
return rdev->desc->n_voltages - 1;
|
||||
|
||||
ret = regmap_read(regmap, ARIZONA_LDO1_CONTROL_1, &val);
|
||||
if (ret != 0)
|
||||
return ret;
|
||||
|
||||
return (val & ARIZONA_LDO1_VSEL_MASK) >> ARIZONA_LDO1_VSEL_SHIFT;
|
||||
}
|
||||
|
||||
static struct regulator_ops arizona_ldo1_hc_ops = {
|
||||
.list_voltage = arizona_ldo1_hc_list_voltage,
|
||||
.map_voltage = arizona_ldo1_hc_map_voltage,
|
||||
.get_voltage_sel = arizona_ldo1_hc_get_voltage_sel,
|
||||
.set_voltage_sel = arizona_ldo1_hc_set_voltage_sel,
|
||||
.get_bypass = regulator_get_bypass_regmap,
|
||||
.set_bypass = regulator_set_bypass_regmap,
|
||||
};
|
||||
|
||||
static const struct regulator_desc arizona_ldo1_hc = {
|
||||
.name = "LDO1",
|
||||
.supply_name = "LDOVDD",
|
||||
.type = REGULATOR_VOLTAGE,
|
||||
.ops = &arizona_ldo1_hc_ops,
|
||||
|
||||
.bypass_reg = ARIZONA_LDO1_CONTROL_1,
|
||||
.bypass_mask = ARIZONA_LDO1_BYPASS,
|
||||
.min_uV = 900000,
|
||||
.uV_step = 50000,
|
||||
.n_voltages = 8,
|
||||
.enable_time = 500,
|
||||
|
||||
.owner = THIS_MODULE,
|
||||
};
|
||||
|
||||
static struct regulator_ops arizona_ldo1_ops = {
|
||||
.list_voltage = regulator_list_voltage_linear,
|
||||
.map_voltage = regulator_map_voltage_linear,
|
||||
@ -55,11 +157,22 @@ static const struct regulator_desc arizona_ldo1 = {
|
||||
.bypass_mask = ARIZONA_LDO1_BYPASS,
|
||||
.min_uV = 900000,
|
||||
.uV_step = 50000,
|
||||
.n_voltages = 6,
|
||||
.n_voltages = 7,
|
||||
.enable_time = 500,
|
||||
|
||||
.owner = THIS_MODULE,
|
||||
};
|
||||
|
||||
static const struct regulator_init_data arizona_ldo1_dvfs = {
|
||||
.constraints = {
|
||||
.min_uV = 1200000,
|
||||
.max_uV = 1800000,
|
||||
.valid_ops_mask = REGULATOR_CHANGE_STATUS |
|
||||
REGULATOR_CHANGE_VOLTAGE,
|
||||
},
|
||||
.num_consumer_supplies = 1,
|
||||
};
|
||||
|
||||
static const struct regulator_init_data arizona_ldo1_default = {
|
||||
.constraints = {
|
||||
.valid_ops_mask = REGULATOR_CHANGE_STATUS,
|
||||
@ -67,9 +180,10 @@ static const struct regulator_init_data arizona_ldo1_default = {
|
||||
.num_consumer_supplies = 1,
|
||||
};
|
||||
|
||||
static __devinit int arizona_ldo1_probe(struct platform_device *pdev)
|
||||
static int arizona_ldo1_probe(struct platform_device *pdev)
|
||||
{
|
||||
struct arizona *arizona = dev_get_drvdata(pdev->dev.parent);
|
||||
const struct regulator_desc *desc;
|
||||
struct regulator_config config = { };
|
||||
struct arizona_ldo1 *ldo1;
|
||||
int ret;
|
||||
@ -87,7 +201,17 @@ static __devinit int arizona_ldo1_probe(struct platform_device *pdev)
|
||||
* default init_data for it. This will be overridden with
|
||||
* platform data if provided.
|
||||
*/
|
||||
ldo1->init_data = arizona_ldo1_default;
|
||||
switch (arizona->type) {
|
||||
case WM5102:
|
||||
desc = &arizona_ldo1_hc;
|
||||
ldo1->init_data = arizona_ldo1_dvfs;
|
||||
break;
|
||||
default:
|
||||
desc = &arizona_ldo1;
|
||||
ldo1->init_data = arizona_ldo1_default;
|
||||
break;
|
||||
}
|
||||
|
||||
ldo1->init_data.consumer_supplies = &ldo1->supply;
|
||||
ldo1->supply.supply = "DCVDD";
|
||||
ldo1->supply.dev_name = dev_name(arizona->dev);
|
||||
@ -102,7 +226,7 @@ static __devinit int arizona_ldo1_probe(struct platform_device *pdev)
|
||||
else
|
||||
config.init_data = &ldo1->init_data;
|
||||
|
||||
ldo1->regulator = regulator_register(&arizona_ldo1, &config);
|
||||
ldo1->regulator = regulator_register(desc, &config);
|
||||
if (IS_ERR(ldo1->regulator)) {
|
||||
ret = PTR_ERR(ldo1->regulator);
|
||||
dev_err(arizona->dev, "Failed to register LDO1 supply: %d\n",
|
||||
@ -115,7 +239,7 @@ static __devinit int arizona_ldo1_probe(struct platform_device *pdev)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static __devexit int arizona_ldo1_remove(struct platform_device *pdev)
|
||||
static int arizona_ldo1_remove(struct platform_device *pdev)
|
||||
{
|
||||
struct arizona_ldo1 *ldo1 = platform_get_drvdata(pdev);
|
||||
|
||||
@ -126,7 +250,7 @@ static __devexit int arizona_ldo1_remove(struct platform_device *pdev)
|
||||
|
||||
static struct platform_driver arizona_ldo1_driver = {
|
||||
.probe = arizona_ldo1_probe,
|
||||
.remove = __devexit_p(arizona_ldo1_remove),
|
||||
.remove = arizona_ldo1_remove,
|
||||
.driver = {
|
||||
.name = "arizona-ldo1",
|
||||
.owner = THIS_MODULE,
|
||||
|
@ -101,6 +101,8 @@ static const struct regulator_desc arizona_micsupp = {
|
||||
.bypass_reg = ARIZONA_MIC_CHARGE_PUMP_1,
|
||||
.bypass_mask = ARIZONA_CPMIC_BYPASS,
|
||||
|
||||
.enable_time = 3000,
|
||||
|
||||
.owner = THIS_MODULE,
|
||||
};
|
||||
|
||||
@ -115,7 +117,7 @@ static const struct regulator_init_data arizona_micsupp_default = {
|
||||
.num_consumer_supplies = 1,
|
||||
};
|
||||
|
||||
static __devinit int arizona_micsupp_probe(struct platform_device *pdev)
|
||||
static int arizona_micsupp_probe(struct platform_device *pdev)
|
||||
{
|
||||
struct arizona *arizona = dev_get_drvdata(pdev->dev.parent);
|
||||
struct regulator_config config = { };
|
||||
@ -166,7 +168,7 @@ static __devinit int arizona_micsupp_probe(struct platform_device *pdev)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static __devexit int arizona_micsupp_remove(struct platform_device *pdev)
|
||||
static int arizona_micsupp_remove(struct platform_device *pdev)
|
||||
{
|
||||
struct arizona_micsupp *micsupp = platform_get_drvdata(pdev);
|
||||
|
||||
@ -177,7 +179,7 @@ static __devexit int arizona_micsupp_remove(struct platform_device *pdev)
|
||||
|
||||
static struct platform_driver arizona_micsupp_driver = {
|
||||
.probe = arizona_micsupp_probe,
|
||||
.remove = __devexit_p(arizona_micsupp_remove),
|
||||
.remove = arizona_micsupp_remove,
|
||||
.driver = {
|
||||
.name = "arizona-micsupp",
|
||||
.owner = THIS_MODULE,
|
||||
|
369
drivers/regulator/as3711-regulator.c
Normal file
369
drivers/regulator/as3711-regulator.c
Normal file
@ -0,0 +1,369 @@
|
||||
/*
|
||||
* AS3711 PMIC regulator driver, using DCDC Step Down and LDO supplies
|
||||
*
|
||||
* Copyright (C) 2012 Renesas Electronics Corporation
|
||||
* Author: Guennadi Liakhovetski, <g.liakhovetski@gmx.de>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the version 2 of the GNU General Public License as
|
||||
* published by the Free Software Foundation
|
||||
*/
|
||||
|
||||
#include <linux/err.h>
|
||||
#include <linux/init.h>
|
||||
#include <linux/mfd/as3711.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/regmap.h>
|
||||
#include <linux/regulator/driver.h>
|
||||
#include <linux/slab.h>
|
||||
|
||||
struct as3711_regulator_info {
|
||||
struct regulator_desc desc;
|
||||
unsigned int max_uV;
|
||||
};
|
||||
|
||||
struct as3711_regulator {
|
||||
struct as3711_regulator_info *reg_info;
|
||||
struct regulator_dev *rdev;
|
||||
};
|
||||
|
||||
static int as3711_list_voltage_sd(struct regulator_dev *rdev,
|
||||
unsigned int selector)
|
||||
{
|
||||
if (selector >= rdev->desc->n_voltages)
|
||||
return -EINVAL;
|
||||
|
||||
if (!selector)
|
||||
return 0;
|
||||
if (selector < 0x41)
|
||||
return 600000 + selector * 12500;
|
||||
if (selector < 0x71)
|
||||
return 1400000 + (selector - 0x40) * 25000;
|
||||
return 2600000 + (selector - 0x70) * 50000;
|
||||
}
|
||||
|
||||
static int as3711_list_voltage_aldo(struct regulator_dev *rdev,
|
||||
unsigned int selector)
|
||||
{
|
||||
if (selector >= rdev->desc->n_voltages)
|
||||
return -EINVAL;
|
||||
|
||||
if (selector < 0x10)
|
||||
return 1200000 + selector * 50000;
|
||||
return 1800000 + (selector - 0x10) * 100000;
|
||||
}
|
||||
|
||||
static int as3711_list_voltage_dldo(struct regulator_dev *rdev,
|
||||
unsigned int selector)
|
||||
{
|
||||
if (selector >= rdev->desc->n_voltages ||
|
||||
(selector > 0x10 && selector < 0x20))
|
||||
return -EINVAL;
|
||||
|
||||
if (selector < 0x11)
|
||||
return 900000 + selector * 50000;
|
||||
return 1750000 + (selector - 0x20) * 50000;
|
||||
}
|
||||
|
||||
static int as3711_bound_check(struct regulator_dev *rdev,
|
||||
int *min_uV, int *max_uV)
|
||||
{
|
||||
struct as3711_regulator *reg = rdev_get_drvdata(rdev);
|
||||
struct as3711_regulator_info *info = reg->reg_info;
|
||||
|
||||
dev_dbg(&rdev->dev, "%s(), %d, %d, %d\n", __func__,
|
||||
*min_uV, rdev->desc->min_uV, info->max_uV);
|
||||
|
||||
if (*max_uV < *min_uV ||
|
||||
*min_uV > info->max_uV || rdev->desc->min_uV > *max_uV)
|
||||
return -EINVAL;
|
||||
|
||||
if (rdev->desc->n_voltages == 1)
|
||||
return 0;
|
||||
|
||||
if (*max_uV > info->max_uV)
|
||||
*max_uV = info->max_uV;
|
||||
|
||||
if (*min_uV < rdev->desc->min_uV)
|
||||
*min_uV = rdev->desc->min_uV;
|
||||
|
||||
return *min_uV;
|
||||
}
|
||||
|
||||
static int as3711_sel_check(int min, int max, int bottom, int step)
|
||||
{
|
||||
int sel, voltage;
|
||||
|
||||
/* Round up min, when dividing: keeps us within the range */
|
||||
sel = DIV_ROUND_UP(min - bottom, step);
|
||||
voltage = sel * step + bottom;
|
||||
pr_debug("%s(): select %d..%d in %d+N*%d: %d\n", __func__,
|
||||
min, max, bottom, step, sel);
|
||||
if (voltage > max)
|
||||
return -EINVAL;
|
||||
|
||||
return sel;
|
||||
}
|
||||
|
||||
static int as3711_map_voltage_sd(struct regulator_dev *rdev,
|
||||
int min_uV, int max_uV)
|
||||
{
|
||||
int ret;
|
||||
|
||||
ret = as3711_bound_check(rdev, &min_uV, &max_uV);
|
||||
if (ret <= 0)
|
||||
return ret;
|
||||
|
||||
if (min_uV <= 1400000)
|
||||
return as3711_sel_check(min_uV, max_uV, 600000, 12500);
|
||||
|
||||
if (min_uV <= 2600000)
|
||||
return as3711_sel_check(min_uV, max_uV, 1400000, 25000) + 0x40;
|
||||
|
||||
return as3711_sel_check(min_uV, max_uV, 2600000, 50000) + 0x70;
|
||||
}
|
||||
|
||||
/*
|
||||
* The regulator API supports 4 modes of operataion: FAST, NORMAL, IDLE and
|
||||
* STANDBY. We map them in the following way to AS3711 SD1-4 DCDC modes:
|
||||
* FAST: sdX_fast=1
|
||||
* NORMAL: low_noise=1
|
||||
* IDLE: low_noise=0
|
||||
*/
|
||||
|
||||
static int as3711_set_mode_sd(struct regulator_dev *rdev, unsigned int mode)
|
||||
{
|
||||
unsigned int fast_bit = rdev->desc->enable_mask,
|
||||
low_noise_bit = fast_bit << 4;
|
||||
u8 val;
|
||||
|
||||
switch (mode) {
|
||||
case REGULATOR_MODE_FAST:
|
||||
val = fast_bit | low_noise_bit;
|
||||
break;
|
||||
case REGULATOR_MODE_NORMAL:
|
||||
val = low_noise_bit;
|
||||
break;
|
||||
case REGULATOR_MODE_IDLE:
|
||||
val = 0;
|
||||
break;
|
||||
default:
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
return regmap_update_bits(rdev->regmap, AS3711_SD_CONTROL_1,
|
||||
low_noise_bit | fast_bit, val);
|
||||
}
|
||||
|
||||
static unsigned int as3711_get_mode_sd(struct regulator_dev *rdev)
|
||||
{
|
||||
unsigned int fast_bit = rdev->desc->enable_mask,
|
||||
low_noise_bit = fast_bit << 4, mask = fast_bit | low_noise_bit;
|
||||
unsigned int val;
|
||||
int ret = regmap_read(rdev->regmap, AS3711_SD_CONTROL_1, &val);
|
||||
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
if ((val & mask) == mask)
|
||||
return REGULATOR_MODE_FAST;
|
||||
|
||||
if ((val & mask) == low_noise_bit)
|
||||
return REGULATOR_MODE_NORMAL;
|
||||
|
||||
if (!(val & mask))
|
||||
return REGULATOR_MODE_IDLE;
|
||||
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
static int as3711_map_voltage_aldo(struct regulator_dev *rdev,
|
||||
int min_uV, int max_uV)
|
||||
{
|
||||
int ret;
|
||||
|
||||
ret = as3711_bound_check(rdev, &min_uV, &max_uV);
|
||||
if (ret <= 0)
|
||||
return ret;
|
||||
|
||||
if (min_uV <= 1800000)
|
||||
return as3711_sel_check(min_uV, max_uV, 1200000, 50000);
|
||||
|
||||
return as3711_sel_check(min_uV, max_uV, 1800000, 100000) + 0x10;
|
||||
}
|
||||
|
||||
static int as3711_map_voltage_dldo(struct regulator_dev *rdev,
|
||||
int min_uV, int max_uV)
|
||||
{
|
||||
int ret;
|
||||
|
||||
ret = as3711_bound_check(rdev, &min_uV, &max_uV);
|
||||
if (ret <= 0)
|
||||
return ret;
|
||||
|
||||
if (min_uV <= 1700000)
|
||||
return as3711_sel_check(min_uV, max_uV, 900000, 50000);
|
||||
|
||||
return as3711_sel_check(min_uV, max_uV, 1750000, 50000) + 0x20;
|
||||
}
|
||||
|
||||
static struct regulator_ops as3711_sd_ops = {
|
||||
.is_enabled = regulator_is_enabled_regmap,
|
||||
.enable = regulator_enable_regmap,
|
||||
.disable = regulator_disable_regmap,
|
||||
.get_voltage_sel = regulator_get_voltage_sel_regmap,
|
||||
.set_voltage_sel = regulator_set_voltage_sel_regmap,
|
||||
.list_voltage = as3711_list_voltage_sd,
|
||||
.map_voltage = as3711_map_voltage_sd,
|
||||
.get_mode = as3711_get_mode_sd,
|
||||
.set_mode = as3711_set_mode_sd,
|
||||
};
|
||||
|
||||
static struct regulator_ops as3711_aldo_ops = {
|
||||
.is_enabled = regulator_is_enabled_regmap,
|
||||
.enable = regulator_enable_regmap,
|
||||
.disable = regulator_disable_regmap,
|
||||
.get_voltage_sel = regulator_get_voltage_sel_regmap,
|
||||
.set_voltage_sel = regulator_set_voltage_sel_regmap,
|
||||
.list_voltage = as3711_list_voltage_aldo,
|
||||
.map_voltage = as3711_map_voltage_aldo,
|
||||
};
|
||||
|
||||
static struct regulator_ops as3711_dldo_ops = {
|
||||
.is_enabled = regulator_is_enabled_regmap,
|
||||
.enable = regulator_enable_regmap,
|
||||
.disable = regulator_disable_regmap,
|
||||
.get_voltage_sel = regulator_get_voltage_sel_regmap,
|
||||
.set_voltage_sel = regulator_set_voltage_sel_regmap,
|
||||
.list_voltage = as3711_list_voltage_dldo,
|
||||
.map_voltage = as3711_map_voltage_dldo,
|
||||
};
|
||||
|
||||
#define AS3711_REG(_id, _en_reg, _en_bit, _vmask, _vshift, _min_uV, _max_uV, _sfx) \
|
||||
[AS3711_REGULATOR_ ## _id] = { \
|
||||
.desc = { \
|
||||
.name = "as3711-regulator-" # _id, \
|
||||
.id = AS3711_REGULATOR_ ## _id, \
|
||||
.n_voltages = (_vmask + 1), \
|
||||
.ops = &as3711_ ## _sfx ## _ops, \
|
||||
.type = REGULATOR_VOLTAGE, \
|
||||
.owner = THIS_MODULE, \
|
||||
.vsel_reg = AS3711_ ## _id ## _VOLTAGE, \
|
||||
.vsel_mask = _vmask << _vshift, \
|
||||
.enable_reg = AS3711_ ## _en_reg, \
|
||||
.enable_mask = BIT(_en_bit), \
|
||||
.min_uV = _min_uV, \
|
||||
}, \
|
||||
.max_uV = _max_uV, \
|
||||
}
|
||||
|
||||
static struct as3711_regulator_info as3711_reg_info[] = {
|
||||
AS3711_REG(SD_1, SD_CONTROL, 0, 0x7f, 0, 612500, 3350000, sd),
|
||||
AS3711_REG(SD_2, SD_CONTROL, 1, 0x7f, 0, 612500, 3350000, sd),
|
||||
AS3711_REG(SD_3, SD_CONTROL, 2, 0x7f, 0, 612500, 3350000, sd),
|
||||
AS3711_REG(SD_4, SD_CONTROL, 3, 0x7f, 0, 612500, 3350000, sd),
|
||||
AS3711_REG(LDO_1, LDO_1_VOLTAGE, 7, 0x1f, 0, 1200000, 3300000, aldo),
|
||||
AS3711_REG(LDO_2, LDO_2_VOLTAGE, 7, 0x1f, 0, 1200000, 3300000, aldo),
|
||||
AS3711_REG(LDO_3, LDO_3_VOLTAGE, 7, 0x3f, 0, 900000, 3300000, dldo),
|
||||
AS3711_REG(LDO_4, LDO_4_VOLTAGE, 7, 0x3f, 0, 900000, 3300000, dldo),
|
||||
AS3711_REG(LDO_5, LDO_5_VOLTAGE, 7, 0x3f, 0, 900000, 3300000, dldo),
|
||||
AS3711_REG(LDO_6, LDO_6_VOLTAGE, 7, 0x3f, 0, 900000, 3300000, dldo),
|
||||
AS3711_REG(LDO_7, LDO_7_VOLTAGE, 7, 0x3f, 0, 900000, 3300000, dldo),
|
||||
AS3711_REG(LDO_8, LDO_8_VOLTAGE, 7, 0x3f, 0, 900000, 3300000, dldo),
|
||||
/* StepUp output voltage depends on supplying regulator */
|
||||
};
|
||||
|
||||
#define AS3711_REGULATOR_NUM ARRAY_SIZE(as3711_reg_info)
|
||||
|
||||
static int as3711_regulator_probe(struct platform_device *pdev)
|
||||
{
|
||||
struct as3711_regulator_pdata *pdata = dev_get_platdata(&pdev->dev);
|
||||
struct as3711 *as3711 = dev_get_drvdata(pdev->dev.parent);
|
||||
struct regulator_init_data *reg_data;
|
||||
struct regulator_config config = {.dev = &pdev->dev,};
|
||||
struct as3711_regulator *reg = NULL;
|
||||
struct as3711_regulator *regs;
|
||||
struct regulator_dev *rdev;
|
||||
struct as3711_regulator_info *ri;
|
||||
int ret;
|
||||
int id;
|
||||
|
||||
if (!pdata)
|
||||
dev_dbg(&pdev->dev, "No platform data...\n");
|
||||
|
||||
regs = devm_kzalloc(&pdev->dev, AS3711_REGULATOR_NUM *
|
||||
sizeof(struct as3711_regulator), GFP_KERNEL);
|
||||
if (!regs) {
|
||||
dev_err(&pdev->dev, "Memory allocation failed exiting..\n");
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
for (id = 0, ri = as3711_reg_info; id < AS3711_REGULATOR_NUM; ++id, ri++) {
|
||||
reg_data = pdata ? pdata->init_data[id] : NULL;
|
||||
|
||||
/* No need to register if there is no regulator data */
|
||||
if (!ri->desc.name)
|
||||
continue;
|
||||
|
||||
reg = ®s[id];
|
||||
reg->reg_info = ri;
|
||||
|
||||
config.init_data = reg_data;
|
||||
config.driver_data = reg;
|
||||
config.regmap = as3711->regmap;
|
||||
|
||||
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 eregreg;
|
||||
}
|
||||
reg->rdev = rdev;
|
||||
}
|
||||
platform_set_drvdata(pdev, regs);
|
||||
return 0;
|
||||
|
||||
eregreg:
|
||||
while (--id >= 0)
|
||||
regulator_unregister(regs[id].rdev);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int as3711_regulator_remove(struct platform_device *pdev)
|
||||
{
|
||||
struct as3711_regulator *regs = platform_get_drvdata(pdev);
|
||||
int id;
|
||||
|
||||
for (id = 0; id < AS3711_REGULATOR_NUM; ++id)
|
||||
regulator_unregister(regs[id].rdev);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct platform_driver as3711_regulator_driver = {
|
||||
.driver = {
|
||||
.name = "as3711-regulator",
|
||||
.owner = THIS_MODULE,
|
||||
},
|
||||
.probe = as3711_regulator_probe,
|
||||
.remove = as3711_regulator_remove,
|
||||
};
|
||||
|
||||
static int __init as3711_regulator_init(void)
|
||||
{
|
||||
return platform_driver_register(&as3711_regulator_driver);
|
||||
}
|
||||
subsys_initcall(as3711_regulator_init);
|
||||
|
||||
static void __exit as3711_regulator_exit(void)
|
||||
{
|
||||
platform_driver_unregister(&as3711_regulator_driver);
|
||||
}
|
||||
module_exit(as3711_regulator_exit);
|
||||
|
||||
MODULE_AUTHOR("Guennadi Liakhovetski <g.liakhovetski@gmx.de>");
|
||||
MODULE_DESCRIPTION("AS3711 regulator driver");
|
||||
MODULE_ALIAS("platform:as3711-regulator");
|
||||
MODULE_LICENSE("GPL v2");
|
@ -199,8 +199,11 @@ static int regulator_check_consumers(struct regulator_dev *rdev,
|
||||
*min_uV = regulator->min_uV;
|
||||
}
|
||||
|
||||
if (*min_uV > *max_uV)
|
||||
if (*min_uV > *max_uV) {
|
||||
dev_err(regulator->dev, "Restricting voltage, %u-%uuV\n",
|
||||
regulator->min_uV, regulator->max_uV);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
@ -880,7 +883,9 @@ static int machine_constraints_voltage(struct regulator_dev *rdev,
|
||||
|
||||
/* final: [min_uV..max_uV] valid iff constraints valid */
|
||||
if (max_uV < min_uV) {
|
||||
rdev_err(rdev, "unsupportable voltage constraints\n");
|
||||
rdev_err(rdev,
|
||||
"unsupportable voltage constraints %u-%uuV\n",
|
||||
min_uV, max_uV);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
@ -1866,6 +1871,28 @@ int regulator_is_enabled(struct regulator *regulator)
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(regulator_is_enabled);
|
||||
|
||||
/**
|
||||
* regulator_can_change_voltage - check if regulator can change voltage
|
||||
* @regulator: regulator source
|
||||
*
|
||||
* Returns positive if the regulator driver backing the source/client
|
||||
* can change its voltage, false otherwise. Usefull for detecting fixed
|
||||
* or dummy regulators and disabling voltage change logic in the client
|
||||
* driver.
|
||||
*/
|
||||
int regulator_can_change_voltage(struct regulator *regulator)
|
||||
{
|
||||
struct regulator_dev *rdev = regulator->rdev;
|
||||
|
||||
if (rdev->constraints &&
|
||||
rdev->constraints->valid_ops_mask & REGULATOR_CHANGE_VOLTAGE &&
|
||||
(rdev->desc->n_voltages - rdev->desc->linear_min_sel) > 1)
|
||||
return 1;
|
||||
|
||||
return 0;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(regulator_can_change_voltage);
|
||||
|
||||
/**
|
||||
* regulator_count_voltages - count regulator_list_voltage() selectors
|
||||
* @regulator: regulator source
|
||||
@ -1897,6 +1924,10 @@ int regulator_list_voltage_linear(struct regulator_dev *rdev,
|
||||
{
|
||||
if (selector >= rdev->desc->n_voltages)
|
||||
return -EINVAL;
|
||||
if (selector < rdev->desc->linear_min_sel)
|
||||
return 0;
|
||||
|
||||
selector -= rdev->desc->linear_min_sel;
|
||||
|
||||
return rdev->desc->min_uV + (rdev->desc->uV_step * selector);
|
||||
}
|
||||
@ -1985,6 +2016,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;
|
||||
@ -2120,6 +2156,8 @@ int regulator_map_voltage_linear(struct regulator_dev *rdev,
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
ret += rdev->desc->linear_min_sel;
|
||||
|
||||
/* 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)
|
||||
|
@ -460,7 +460,7 @@ static inline struct da903x_regulator_info *find_regulator_info(int id)
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static int __devinit da903x_regulator_probe(struct platform_device *pdev)
|
||||
static int da903x_regulator_probe(struct platform_device *pdev)
|
||||
{
|
||||
struct da903x_regulator_info *ri = NULL;
|
||||
struct regulator_dev *rdev;
|
||||
@ -499,7 +499,7 @@ static int __devinit da903x_regulator_probe(struct platform_device *pdev)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int __devexit da903x_regulator_remove(struct platform_device *pdev)
|
||||
static int da903x_regulator_remove(struct platform_device *pdev)
|
||||
{
|
||||
struct regulator_dev *rdev = platform_get_drvdata(pdev);
|
||||
|
||||
@ -513,7 +513,7 @@ static struct platform_driver da903x_regulator_driver = {
|
||||
.owner = THIS_MODULE,
|
||||
},
|
||||
.probe = da903x_regulator_probe,
|
||||
.remove = __devexit_p(da903x_regulator_remove),
|
||||
.remove = da903x_regulator_remove,
|
||||
};
|
||||
|
||||
static int __init da903x_regulator_init(void)
|
||||
|
@ -129,17 +129,17 @@ static int da9052_dcdc_set_current_limit(struct regulator_dev *rdev, int min_uA,
|
||||
else if (offset == 0)
|
||||
row = 1;
|
||||
|
||||
if (min_uA > da9052_current_limits[row][DA9052_MAX_UA] ||
|
||||
max_uA < da9052_current_limits[row][DA9052_MIN_UA])
|
||||
return -EINVAL;
|
||||
|
||||
for (i = DA9052_CURRENT_RANGE - 1; i >= 0; i--) {
|
||||
if (da9052_current_limits[row][i] <= max_uA) {
|
||||
if ((min_uA <= da9052_current_limits[row][i]) &&
|
||||
(da9052_current_limits[row][i] <= max_uA)) {
|
||||
reg_val = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (i < 0)
|
||||
return -EINVAL;
|
||||
|
||||
/* Determine the even or odd position of the buck current limit
|
||||
* register field
|
||||
*/
|
||||
@ -365,7 +365,7 @@ static inline struct da9052_regulator_info *find_regulator_info(u8 chip_id,
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static int __devinit da9052_regulator_probe(struct platform_device *pdev)
|
||||
static int da9052_regulator_probe(struct platform_device *pdev)
|
||||
{
|
||||
struct regulator_config config = { };
|
||||
struct da9052_regulator *regulator;
|
||||
@ -430,7 +430,7 @@ static int __devinit da9052_regulator_probe(struct platform_device *pdev)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int __devexit da9052_regulator_remove(struct platform_device *pdev)
|
||||
static int da9052_regulator_remove(struct platform_device *pdev)
|
||||
{
|
||||
struct da9052_regulator *regulator = platform_get_drvdata(pdev);
|
||||
|
||||
@ -440,7 +440,7 @@ static int __devexit da9052_regulator_remove(struct platform_device *pdev)
|
||||
|
||||
static struct platform_driver da9052_regulator_driver = {
|
||||
.probe = da9052_regulator_probe,
|
||||
.remove = __devexit_p(da9052_regulator_remove),
|
||||
.remove = da9052_regulator_remove,
|
||||
.driver = {
|
||||
.name = "da9052-regulator",
|
||||
.owner = THIS_MODULE,
|
||||
|
641
drivers/regulator/da9055-regulator.c
Normal file
641
drivers/regulator/da9055-regulator.c
Normal file
@ -0,0 +1,641 @@
|
||||
/*
|
||||
* Regulator driver for DA9055 PMIC
|
||||
*
|
||||
* Copyright(c) 2012 Dialog Semiconductor Ltd.
|
||||
*
|
||||
* Author: David Dajun Chen <dchen@diasemi.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.
|
||||
*
|
||||
*/
|
||||
|
||||
#include <linux/module.h>
|
||||
#include <linux/init.h>
|
||||
#include <linux/err.h>
|
||||
#include <linux/gpio.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/regulator/driver.h>
|
||||
#include <linux/regulator/machine.h>
|
||||
|
||||
#include <linux/mfd/da9055/core.h>
|
||||
#include <linux/mfd/da9055/reg.h>
|
||||
#include <linux/mfd/da9055/pdata.h>
|
||||
|
||||
#define DA9055_MIN_UA 0
|
||||
#define DA9055_MAX_UA 3
|
||||
|
||||
#define DA9055_LDO_MODE_SYNC 0
|
||||
#define DA9055_LDO_MODE_SLEEP 1
|
||||
|
||||
#define DA9055_BUCK_MODE_SLEEP 1
|
||||
#define DA9055_BUCK_MODE_SYNC 2
|
||||
#define DA9055_BUCK_MODE_AUTO 3
|
||||
|
||||
/* DA9055 REGULATOR IDs */
|
||||
#define DA9055_ID_BUCK1 0
|
||||
#define DA9055_ID_BUCK2 1
|
||||
#define DA9055_ID_LDO1 2
|
||||
#define DA9055_ID_LDO2 3
|
||||
#define DA9055_ID_LDO3 4
|
||||
#define DA9055_ID_LDO4 5
|
||||
#define DA9055_ID_LDO5 6
|
||||
#define DA9055_ID_LDO6 7
|
||||
|
||||
/* DA9055 BUCK current limit */
|
||||
static const int da9055_current_limits[] = { 500000, 600000, 700000, 800000 };
|
||||
|
||||
struct da9055_conf_reg {
|
||||
int reg;
|
||||
int sel_mask;
|
||||
int en_mask;
|
||||
};
|
||||
|
||||
struct da9055_volt_reg {
|
||||
int reg_a;
|
||||
int reg_b;
|
||||
int sl_shift;
|
||||
int v_mask;
|
||||
int v_shift;
|
||||
};
|
||||
|
||||
struct da9055_mode_reg {
|
||||
int reg;
|
||||
int mask;
|
||||
int shift;
|
||||
};
|
||||
|
||||
struct da9055_regulator_info {
|
||||
struct regulator_desc reg_desc;
|
||||
struct da9055_conf_reg conf;
|
||||
struct da9055_volt_reg volt;
|
||||
struct da9055_mode_reg mode;
|
||||
};
|
||||
|
||||
struct da9055_regulator {
|
||||
struct da9055 *da9055;
|
||||
struct da9055_regulator_info *info;
|
||||
struct regulator_dev *rdev;
|
||||
enum gpio_select reg_rselect;
|
||||
};
|
||||
|
||||
static unsigned int da9055_buck_get_mode(struct regulator_dev *rdev)
|
||||
{
|
||||
struct da9055_regulator *regulator = rdev_get_drvdata(rdev);
|
||||
struct da9055_regulator_info *info = regulator->info;
|
||||
int ret, mode = 0;
|
||||
|
||||
ret = da9055_reg_read(regulator->da9055, info->mode.reg);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
switch ((ret & info->mode.mask) >> info->mode.shift) {
|
||||
case DA9055_BUCK_MODE_SYNC:
|
||||
mode = REGULATOR_MODE_FAST;
|
||||
break;
|
||||
case DA9055_BUCK_MODE_AUTO:
|
||||
mode = REGULATOR_MODE_NORMAL;
|
||||
break;
|
||||
case DA9055_BUCK_MODE_SLEEP:
|
||||
mode = REGULATOR_MODE_STANDBY;
|
||||
break;
|
||||
}
|
||||
|
||||
return mode;
|
||||
}
|
||||
|
||||
static int da9055_buck_set_mode(struct regulator_dev *rdev,
|
||||
unsigned int mode)
|
||||
{
|
||||
struct da9055_regulator *regulator = rdev_get_drvdata(rdev);
|
||||
struct da9055_regulator_info *info = regulator->info;
|
||||
int val = 0;
|
||||
|
||||
switch (mode) {
|
||||
case REGULATOR_MODE_FAST:
|
||||
val = DA9055_BUCK_MODE_SYNC << info->mode.shift;
|
||||
break;
|
||||
case REGULATOR_MODE_NORMAL:
|
||||
val = DA9055_BUCK_MODE_AUTO << info->mode.shift;
|
||||
break;
|
||||
case REGULATOR_MODE_STANDBY:
|
||||
val = DA9055_BUCK_MODE_SLEEP << info->mode.shift;
|
||||
break;
|
||||
}
|
||||
|
||||
return da9055_reg_update(regulator->da9055, info->mode.reg,
|
||||
info->mode.mask, val);
|
||||
}
|
||||
|
||||
static unsigned int da9055_ldo_get_mode(struct regulator_dev *rdev)
|
||||
{
|
||||
struct da9055_regulator *regulator = rdev_get_drvdata(rdev);
|
||||
struct da9055_regulator_info *info = regulator->info;
|
||||
int ret;
|
||||
|
||||
ret = da9055_reg_read(regulator->da9055, info->volt.reg_b);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
if (ret >> info->volt.sl_shift)
|
||||
return REGULATOR_MODE_STANDBY;
|
||||
else
|
||||
return REGULATOR_MODE_NORMAL;
|
||||
}
|
||||
|
||||
static int da9055_ldo_set_mode(struct regulator_dev *rdev, unsigned int mode)
|
||||
{
|
||||
struct da9055_regulator *regulator = rdev_get_drvdata(rdev);
|
||||
struct da9055_regulator_info *info = regulator->info;
|
||||
struct da9055_volt_reg volt = info->volt;
|
||||
int val = 0;
|
||||
|
||||
switch (mode) {
|
||||
case REGULATOR_MODE_NORMAL:
|
||||
case REGULATOR_MODE_FAST:
|
||||
val = DA9055_LDO_MODE_SYNC;
|
||||
break;
|
||||
case REGULATOR_MODE_STANDBY:
|
||||
val = DA9055_LDO_MODE_SLEEP;
|
||||
break;
|
||||
}
|
||||
|
||||
return da9055_reg_update(regulator->da9055, volt.reg_b,
|
||||
1 << volt.sl_shift,
|
||||
val << volt.sl_shift);
|
||||
}
|
||||
|
||||
static int da9055_buck_get_current_limit(struct regulator_dev *rdev)
|
||||
{
|
||||
struct da9055_regulator *regulator = rdev_get_drvdata(rdev);
|
||||
struct da9055_regulator_info *info = regulator->info;
|
||||
int ret;
|
||||
|
||||
ret = da9055_reg_read(regulator->da9055, DA9055_REG_BUCK_LIM);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
ret &= info->mode.mask;
|
||||
return da9055_current_limits[ret >> info->mode.shift];
|
||||
}
|
||||
|
||||
static int da9055_buck_set_current_limit(struct regulator_dev *rdev, int min_uA,
|
||||
int max_uA)
|
||||
{
|
||||
struct da9055_regulator *regulator = rdev_get_drvdata(rdev);
|
||||
struct da9055_regulator_info *info = regulator->info;
|
||||
int i;
|
||||
|
||||
for (i = ARRAY_SIZE(da9055_current_limits) - 1; i >= 0; i--) {
|
||||
if ((min_uA <= da9055_current_limits[i]) &&
|
||||
(da9055_current_limits[i] <= max_uA))
|
||||
return da9055_reg_update(regulator->da9055,
|
||||
DA9055_REG_BUCK_LIM,
|
||||
info->mode.mask,
|
||||
i << info->mode.shift);
|
||||
}
|
||||
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
static int da9055_regulator_get_voltage_sel(struct regulator_dev *rdev)
|
||||
{
|
||||
struct da9055_regulator *regulator = rdev_get_drvdata(rdev);
|
||||
struct da9055_regulator_info *info = regulator->info;
|
||||
struct da9055_volt_reg volt = info->volt;
|
||||
int ret, sel;
|
||||
|
||||
/*
|
||||
* There are two voltage register set A & B for voltage ramping but
|
||||
* either one of then can be active therefore we first determine
|
||||
* the active register set.
|
||||
*/
|
||||
ret = da9055_reg_read(regulator->da9055, info->conf.reg);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
ret &= info->conf.sel_mask;
|
||||
|
||||
/* Get the voltage for the active register set A/B */
|
||||
if (ret == DA9055_REGUALTOR_SET_A)
|
||||
ret = da9055_reg_read(regulator->da9055, volt.reg_a);
|
||||
else
|
||||
ret = da9055_reg_read(regulator->da9055, volt.reg_b);
|
||||
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
sel = (ret & volt.v_mask);
|
||||
return sel;
|
||||
}
|
||||
|
||||
static int da9055_regulator_set_voltage_sel(struct regulator_dev *rdev,
|
||||
unsigned int selector)
|
||||
{
|
||||
struct da9055_regulator *regulator = rdev_get_drvdata(rdev);
|
||||
struct da9055_regulator_info *info = regulator->info;
|
||||
int ret;
|
||||
|
||||
/*
|
||||
* Regulator register set A/B is not selected through GPIO therefore
|
||||
* we use default register set A for voltage ramping.
|
||||
*/
|
||||
if (regulator->reg_rselect == NO_GPIO) {
|
||||
/* Select register set A */
|
||||
ret = da9055_reg_update(regulator->da9055, info->conf.reg,
|
||||
info->conf.sel_mask, DA9055_SEL_REG_A);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
/* Set the voltage */
|
||||
return da9055_reg_update(regulator->da9055, info->volt.reg_a,
|
||||
info->volt.v_mask, selector);
|
||||
}
|
||||
|
||||
/*
|
||||
* Here regulator register set A/B is selected through GPIO.
|
||||
* Therefore we first determine the selected register set A/B and
|
||||
* then set the desired voltage for that register set A/B.
|
||||
*/
|
||||
ret = da9055_reg_read(regulator->da9055, info->conf.reg);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
ret &= info->conf.sel_mask;
|
||||
|
||||
/* Set the voltage */
|
||||
if (ret == DA9055_REGUALTOR_SET_A)
|
||||
return da9055_reg_update(regulator->da9055, info->volt.reg_a,
|
||||
info->volt.v_mask, selector);
|
||||
else
|
||||
return da9055_reg_update(regulator->da9055, info->volt.reg_b,
|
||||
info->volt.v_mask, selector);
|
||||
}
|
||||
|
||||
static int da9055_regulator_set_suspend_voltage(struct regulator_dev *rdev,
|
||||
int uV)
|
||||
{
|
||||
struct da9055_regulator *regulator = rdev_get_drvdata(rdev);
|
||||
struct da9055_regulator_info *info = regulator->info;
|
||||
int ret;
|
||||
|
||||
/* Select register set B for suspend voltage ramping. */
|
||||
if (regulator->reg_rselect == NO_GPIO) {
|
||||
ret = da9055_reg_update(regulator->da9055, info->conf.reg,
|
||||
info->conf.sel_mask, DA9055_SEL_REG_B);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
}
|
||||
|
||||
ret = regulator_map_voltage_linear(rdev, uV, uV);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
return da9055_reg_update(regulator->da9055, info->volt.reg_b,
|
||||
info->volt.v_mask, ret);
|
||||
}
|
||||
|
||||
static int da9055_suspend_enable(struct regulator_dev *rdev)
|
||||
{
|
||||
struct da9055_regulator *regulator = rdev_get_drvdata(rdev);
|
||||
struct da9055_regulator_info *info = regulator->info;
|
||||
|
||||
/* Select register set B for voltage ramping. */
|
||||
if (regulator->reg_rselect == NO_GPIO)
|
||||
return da9055_reg_update(regulator->da9055, info->conf.reg,
|
||||
info->conf.sel_mask, DA9055_SEL_REG_B);
|
||||
else
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int da9055_suspend_disable(struct regulator_dev *rdev)
|
||||
{
|
||||
struct da9055_regulator *regulator = rdev_get_drvdata(rdev);
|
||||
struct da9055_regulator_info *info = regulator->info;
|
||||
|
||||
/* Diselect register set B. */
|
||||
if (regulator->reg_rselect == NO_GPIO)
|
||||
return da9055_reg_update(regulator->da9055, info->conf.reg,
|
||||
info->conf.sel_mask, DA9055_SEL_REG_A);
|
||||
else
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct regulator_ops da9055_buck_ops = {
|
||||
.get_mode = da9055_buck_get_mode,
|
||||
.set_mode = da9055_buck_set_mode,
|
||||
|
||||
.get_current_limit = da9055_buck_get_current_limit,
|
||||
.set_current_limit = da9055_buck_set_current_limit,
|
||||
|
||||
.get_voltage_sel = da9055_regulator_get_voltage_sel,
|
||||
.set_voltage_sel = da9055_regulator_set_voltage_sel,
|
||||
.list_voltage = regulator_list_voltage_linear,
|
||||
.map_voltage = regulator_map_voltage_linear,
|
||||
.is_enabled = regulator_is_enabled_regmap,
|
||||
.enable = regulator_enable_regmap,
|
||||
.disable = regulator_disable_regmap,
|
||||
|
||||
.set_suspend_voltage = da9055_regulator_set_suspend_voltage,
|
||||
.set_suspend_enable = da9055_suspend_enable,
|
||||
.set_suspend_disable = da9055_suspend_disable,
|
||||
.set_suspend_mode = da9055_buck_set_mode,
|
||||
};
|
||||
|
||||
static struct regulator_ops da9055_ldo_ops = {
|
||||
.get_mode = da9055_ldo_get_mode,
|
||||
.set_mode = da9055_ldo_set_mode,
|
||||
|
||||
.get_voltage_sel = da9055_regulator_get_voltage_sel,
|
||||
.set_voltage_sel = da9055_regulator_set_voltage_sel,
|
||||
.list_voltage = regulator_list_voltage_linear,
|
||||
.map_voltage = regulator_map_voltage_linear,
|
||||
.is_enabled = regulator_is_enabled_regmap,
|
||||
.enable = regulator_enable_regmap,
|
||||
.disable = regulator_disable_regmap,
|
||||
|
||||
.set_suspend_voltage = da9055_regulator_set_suspend_voltage,
|
||||
.set_suspend_enable = da9055_suspend_enable,
|
||||
.set_suspend_disable = da9055_suspend_disable,
|
||||
.set_suspend_mode = da9055_ldo_set_mode,
|
||||
|
||||
};
|
||||
|
||||
#define DA9055_LDO(_id, step, min, max, vbits, voffset) \
|
||||
{\
|
||||
.reg_desc = {\
|
||||
.name = #_id,\
|
||||
.ops = &da9055_ldo_ops,\
|
||||
.type = REGULATOR_VOLTAGE,\
|
||||
.id = DA9055_ID_##_id,\
|
||||
.n_voltages = (max - min) / step + 1 + (voffset), \
|
||||
.enable_reg = DA9055_REG_BCORE_CONT + DA9055_ID_##_id, \
|
||||
.enable_mask = 1, \
|
||||
.min_uV = (min) * 1000,\
|
||||
.uV_step = (step) * 1000,\
|
||||
.linear_min_sel = (voffset),\
|
||||
.owner = THIS_MODULE,\
|
||||
},\
|
||||
.conf = {\
|
||||
.reg = DA9055_REG_BCORE_CONT + DA9055_ID_##_id, \
|
||||
.sel_mask = (1 << 4),\
|
||||
.en_mask = 1,\
|
||||
},\
|
||||
.volt = {\
|
||||
.reg_a = DA9055_REG_VBCORE_A + DA9055_ID_##_id, \
|
||||
.reg_b = DA9055_REG_VBCORE_B + DA9055_ID_##_id, \
|
||||
.sl_shift = 7,\
|
||||
.v_mask = (1 << (vbits)) - 1,\
|
||||
.v_shift = (vbits),\
|
||||
},\
|
||||
}
|
||||
|
||||
#define DA9055_BUCK(_id, step, min, max, vbits, voffset, mbits, sbits) \
|
||||
{\
|
||||
.reg_desc = {\
|
||||
.name = #_id,\
|
||||
.ops = &da9055_buck_ops,\
|
||||
.type = REGULATOR_VOLTAGE,\
|
||||
.id = DA9055_ID_##_id,\
|
||||
.n_voltages = (max - min) / step + 1 + (voffset), \
|
||||
.enable_reg = DA9055_REG_BCORE_CONT + DA9055_ID_##_id, \
|
||||
.enable_mask = 1,\
|
||||
.min_uV = (min) * 1000,\
|
||||
.uV_step = (step) * 1000,\
|
||||
.linear_min_sel = (voffset),\
|
||||
.owner = THIS_MODULE,\
|
||||
},\
|
||||
.conf = {\
|
||||
.reg = DA9055_REG_BCORE_CONT + DA9055_ID_##_id, \
|
||||
.sel_mask = (1 << 4),\
|
||||
.en_mask = 1,\
|
||||
},\
|
||||
.volt = {\
|
||||
.reg_a = DA9055_REG_VBCORE_A + DA9055_ID_##_id, \
|
||||
.reg_b = DA9055_REG_VBCORE_B + DA9055_ID_##_id, \
|
||||
.sl_shift = 7,\
|
||||
.v_mask = (1 << (vbits)) - 1,\
|
||||
.v_shift = (vbits),\
|
||||
},\
|
||||
.mode = {\
|
||||
.reg = DA9055_REG_BCORE_MODE,\
|
||||
.mask = (mbits),\
|
||||
.shift = (sbits),\
|
||||
},\
|
||||
}
|
||||
|
||||
static struct da9055_regulator_info da9055_regulator_info[] = {
|
||||
DA9055_BUCK(BUCK1, 25, 725, 2075, 6, 9, 0xc, 2),
|
||||
DA9055_BUCK(BUCK2, 25, 925, 2500, 6, 0, 3, 0),
|
||||
DA9055_LDO(LDO1, 50, 900, 3300, 6, 2),
|
||||
DA9055_LDO(LDO2, 50, 900, 3300, 6, 3),
|
||||
DA9055_LDO(LDO3, 50, 900, 3300, 6, 2),
|
||||
DA9055_LDO(LDO4, 50, 900, 3300, 6, 2),
|
||||
DA9055_LDO(LDO5, 50, 900, 2750, 6, 2),
|
||||
DA9055_LDO(LDO6, 20, 900, 3300, 7, 0),
|
||||
};
|
||||
|
||||
/*
|
||||
* Configures regulator to be controlled either through GPIO 1 or 2.
|
||||
* GPIO can control regulator state and/or select the regulator register
|
||||
* set A/B for voltage ramping.
|
||||
*/
|
||||
static __devinit int da9055_gpio_init(struct da9055_regulator *regulator,
|
||||
struct regulator_config *config,
|
||||
struct da9055_pdata *pdata, int id)
|
||||
{
|
||||
struct da9055_regulator_info *info = regulator->info;
|
||||
int ret = 0;
|
||||
|
||||
if (pdata->gpio_ren && pdata->gpio_ren[id]) {
|
||||
char name[18];
|
||||
int gpio_mux = pdata->gpio_ren[id];
|
||||
|
||||
config->ena_gpio = pdata->ena_gpio[id];
|
||||
config->ena_gpio_flags = GPIOF_OUT_INIT_HIGH;
|
||||
config->ena_gpio_invert = 1;
|
||||
|
||||
/*
|
||||
* GPI pin is muxed with regulator to control the
|
||||
* regulator state.
|
||||
*/
|
||||
sprintf(name, "DA9055 GPI %d", gpio_mux);
|
||||
ret = devm_gpio_request_one(config->dev, gpio_mux, GPIOF_DIR_IN,
|
||||
name);
|
||||
if (ret < 0)
|
||||
goto err;
|
||||
|
||||
/*
|
||||
* Let the regulator know that its state is controlled
|
||||
* through GPI.
|
||||
*/
|
||||
ret = da9055_reg_update(regulator->da9055, info->conf.reg,
|
||||
DA9055_E_GPI_MASK,
|
||||
pdata->reg_ren[id]
|
||||
<< DA9055_E_GPI_SHIFT);
|
||||
if (ret < 0)
|
||||
goto err;
|
||||
}
|
||||
|
||||
if (pdata->gpio_rsel && pdata->gpio_rsel[id]) {
|
||||
char name[18];
|
||||
int gpio_mux = pdata->gpio_rsel[id];
|
||||
|
||||
regulator->reg_rselect = pdata->reg_rsel[id];
|
||||
|
||||
/*
|
||||
* GPI pin is muxed with regulator to select the
|
||||
* regulator register set A/B for voltage ramping.
|
||||
*/
|
||||
sprintf(name, "DA9055 GPI %d", gpio_mux);
|
||||
ret = devm_gpio_request_one(config->dev, gpio_mux, GPIOF_DIR_IN,
|
||||
name);
|
||||
if (ret < 0)
|
||||
goto err;
|
||||
|
||||
/*
|
||||
* Let the regulator know that its register set A/B
|
||||
* will be selected through GPI for voltage ramping.
|
||||
*/
|
||||
ret = da9055_reg_update(regulator->da9055, info->conf.reg,
|
||||
DA9055_V_GPI_MASK,
|
||||
pdata->reg_rsel[id]
|
||||
<< DA9055_V_GPI_SHIFT);
|
||||
}
|
||||
|
||||
err:
|
||||
return ret;
|
||||
}
|
||||
|
||||
static irqreturn_t da9055_ldo5_6_oc_irq(int irq, void *data)
|
||||
{
|
||||
struct da9055_regulator *regulator = data;
|
||||
|
||||
regulator_notifier_call_chain(regulator->rdev,
|
||||
REGULATOR_EVENT_OVER_CURRENT, NULL);
|
||||
|
||||
return IRQ_HANDLED;
|
||||
}
|
||||
|
||||
static inline struct da9055_regulator_info *find_regulator_info(int id)
|
||||
{
|
||||
struct da9055_regulator_info *info;
|
||||
int i;
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(da9055_regulator_info); i++) {
|
||||
info = &da9055_regulator_info[i];
|
||||
if (info->reg_desc.id == id)
|
||||
return info;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static int __devinit da9055_regulator_probe(struct platform_device *pdev)
|
||||
{
|
||||
struct regulator_config config = { };
|
||||
struct da9055_regulator *regulator;
|
||||
struct da9055 *da9055 = dev_get_drvdata(pdev->dev.parent);
|
||||
struct da9055_pdata *pdata = da9055->dev->platform_data;
|
||||
int ret, irq;
|
||||
|
||||
if (pdata == NULL || pdata->regulators[pdev->id] == NULL)
|
||||
return -ENODEV;
|
||||
|
||||
regulator = devm_kzalloc(&pdev->dev, sizeof(struct da9055_regulator),
|
||||
GFP_KERNEL);
|
||||
if (!regulator)
|
||||
return -ENOMEM;
|
||||
|
||||
regulator->info = find_regulator_info(pdev->id);
|
||||
if (regulator->info == NULL) {
|
||||
dev_err(&pdev->dev, "invalid regulator ID specified\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
regulator->da9055 = da9055;
|
||||
config.dev = &pdev->dev;
|
||||
config.driver_data = regulator;
|
||||
config.regmap = da9055->regmap;
|
||||
|
||||
if (pdata && pdata->regulators)
|
||||
config.init_data = pdata->regulators[pdev->id];
|
||||
|
||||
ret = da9055_gpio_init(regulator, &config, pdata, pdev->id);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
regulator->rdev = regulator_register(®ulator->info->reg_desc,
|
||||
&config);
|
||||
if (IS_ERR(regulator->rdev)) {
|
||||
dev_err(&pdev->dev, "Failed to register regulator %s\n",
|
||||
regulator->info->reg_desc.name);
|
||||
ret = PTR_ERR(regulator->rdev);
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* Only LDO 5 and 6 has got the over current interrupt */
|
||||
if (pdev->id == DA9055_ID_LDO5 || pdev->id == DA9055_ID_LDO6) {
|
||||
irq = platform_get_irq_byname(pdev, "REGULATOR");
|
||||
irq = regmap_irq_get_virq(da9055->irq_data, irq);
|
||||
ret = devm_request_threaded_irq(&pdev->dev, irq, NULL,
|
||||
da9055_ldo5_6_oc_irq,
|
||||
IRQF_TRIGGER_HIGH |
|
||||
IRQF_ONESHOT |
|
||||
IRQF_PROBE_SHARED,
|
||||
pdev->name, regulator);
|
||||
if (ret != 0) {
|
||||
if (ret != -EBUSY) {
|
||||
dev_err(&pdev->dev,
|
||||
"Failed to request Regulator IRQ %d: %d\n",
|
||||
irq, ret);
|
||||
goto err_regulator;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
platform_set_drvdata(pdev, regulator);
|
||||
|
||||
return 0;
|
||||
|
||||
err_regulator:
|
||||
regulator_unregister(regulator->rdev);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int __devexit da9055_regulator_remove(struct platform_device *pdev)
|
||||
{
|
||||
struct da9055_regulator *regulator = platform_get_drvdata(pdev);
|
||||
|
||||
regulator_unregister(regulator->rdev);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct platform_driver da9055_regulator_driver = {
|
||||
.probe = da9055_regulator_probe,
|
||||
.remove = __devexit_p(da9055_regulator_remove),
|
||||
.driver = {
|
||||
.name = "da9055-regulator",
|
||||
.owner = THIS_MODULE,
|
||||
},
|
||||
};
|
||||
|
||||
static int __init da9055_regulator_init(void)
|
||||
{
|
||||
return platform_driver_register(&da9055_regulator_driver);
|
||||
}
|
||||
subsys_initcall(da9055_regulator_init);
|
||||
|
||||
static void __exit da9055_regulator_exit(void)
|
||||
{
|
||||
platform_driver_unregister(&da9055_regulator_driver);
|
||||
}
|
||||
module_exit(da9055_regulator_exit);
|
||||
|
||||
MODULE_AUTHOR("David Dajun Chen <dchen@diasemi.com>");
|
||||
MODULE_DESCRIPTION("Power Regulator driver for Dialog DA9055 PMIC");
|
||||
MODULE_LICENSE("GPL");
|
||||
MODULE_ALIAS("platform:da9055-regulator");
|
@ -412,7 +412,7 @@ dbx500_regulator_info[DB8500_NUM_REGULATORS] = {
|
||||
},
|
||||
};
|
||||
|
||||
static __devinit int db8500_regulator_register(struct platform_device *pdev,
|
||||
static int db8500_regulator_register(struct platform_device *pdev,
|
||||
struct regulator_init_data *init_data,
|
||||
int id,
|
||||
struct device_node *np)
|
||||
@ -474,7 +474,7 @@ static struct of_regulator_match db8500_regulator_matches[] = {
|
||||
{ .name = "db8500_esram34_ret", .driver_data = (void *) DB8500_REGULATOR_SWITCH_ESRAM34RET, },
|
||||
};
|
||||
|
||||
static __devinit int
|
||||
static int
|
||||
db8500_regulator_of_probe(struct platform_device *pdev,
|
||||
struct device_node *np)
|
||||
{
|
||||
@ -491,7 +491,7 @@ db8500_regulator_of_probe(struct platform_device *pdev,
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int __devinit db8500_regulator_probe(struct platform_device *pdev)
|
||||
static int db8500_regulator_probe(struct platform_device *pdev)
|
||||
{
|
||||
struct regulator_init_data *db8500_init_data =
|
||||
dev_get_platdata(&pdev->dev);
|
||||
|
@ -173,7 +173,7 @@ int __attribute__((weak)) dbx500_regulator_testcase(
|
||||
return 0;
|
||||
}
|
||||
|
||||
int __devinit
|
||||
int
|
||||
ux500_regulator_debug_init(struct platform_device *pdev,
|
||||
struct dbx500_regulator_info *regulator_info,
|
||||
int num_regulators)
|
||||
@ -230,7 +230,7 @@ exit_no_debugfs:
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
int __devexit ux500_regulator_debug_exit(void)
|
||||
int ux500_regulator_debug_exit(void)
|
||||
{
|
||||
debugfs_remove_recursive(rdebug.dir);
|
||||
kfree(rdebug.state_after_suspend);
|
||||
|
@ -37,7 +37,7 @@ static struct regulator_desc dummy_desc = {
|
||||
.ops = &dummy_ops,
|
||||
};
|
||||
|
||||
static int __devinit dummy_regulator_probe(struct platform_device *pdev)
|
||||
static int dummy_regulator_probe(struct platform_device *pdev)
|
||||
{
|
||||
struct regulator_config config = { };
|
||||
int ret;
|
||||
|
@ -230,7 +230,7 @@ static struct regmap_config fan53555_regmap_config = {
|
||||
.val_bits = 8,
|
||||
};
|
||||
|
||||
static int __devinit fan53555_regulator_probe(struct i2c_client *client,
|
||||
static int fan53555_regulator_probe(struct i2c_client *client,
|
||||
const struct i2c_device_id *id)
|
||||
{
|
||||
struct fan53555_device_info *di;
|
||||
@ -293,7 +293,7 @@ static int __devinit fan53555_regulator_probe(struct i2c_client *client,
|
||||
|
||||
}
|
||||
|
||||
static int __devexit fan53555_regulator_remove(struct i2c_client *client)
|
||||
static int fan53555_regulator_remove(struct i2c_client *client)
|
||||
{
|
||||
struct fan53555_device_info *di = i2c_get_clientdata(client);
|
||||
|
||||
@ -311,7 +311,7 @@ static struct i2c_driver fan53555_regulator_driver = {
|
||||
.name = "fan53555-regulator",
|
||||
},
|
||||
.probe = fan53555_regulator_probe,
|
||||
.remove = __devexit_p(fan53555_regulator_remove),
|
||||
.remove = fan53555_regulator_remove,
|
||||
.id_table = fan53555_id,
|
||||
};
|
||||
|
||||
|
@ -134,7 +134,7 @@ static struct regulator_ops fixed_voltage_ops = {
|
||||
.list_voltage = fixed_voltage_list_voltage,
|
||||
};
|
||||
|
||||
static int __devinit reg_fixed_voltage_probe(struct platform_device *pdev)
|
||||
static int reg_fixed_voltage_probe(struct platform_device *pdev)
|
||||
{
|
||||
struct fixed_voltage_config *config;
|
||||
struct fixed_voltage_data *drvdata;
|
||||
@ -234,7 +234,7 @@ err:
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int __devexit reg_fixed_voltage_remove(struct platform_device *pdev)
|
||||
static int reg_fixed_voltage_remove(struct platform_device *pdev)
|
||||
{
|
||||
struct fixed_voltage_data *drvdata = platform_get_drvdata(pdev);
|
||||
|
||||
@ -255,7 +255,7 @@ MODULE_DEVICE_TABLE(of, fixed_of_match);
|
||||
|
||||
static struct platform_driver regulator_fixed_voltage_driver = {
|
||||
.probe = reg_fixed_voltage_probe,
|
||||
.remove = __devexit_p(reg_fixed_voltage_remove),
|
||||
.remove = reg_fixed_voltage_remove,
|
||||
.driver = {
|
||||
.name = "reg-fixed-voltage",
|
||||
.owner = THIS_MODULE,
|
||||
|
@ -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;
|
||||
@ -79,7 +82,7 @@ static int gpio_regulator_set_voltage(struct regulator_dev *dev,
|
||||
|
||||
for (ptr = 0; ptr < data->nr_gpios; ptr++) {
|
||||
state = (target & (1 << ptr)) >> ptr;
|
||||
gpio_set_value(data->gpios[ptr].gpio, state);
|
||||
gpio_set_value_cansleep(data->gpios[ptr].gpio, state);
|
||||
}
|
||||
data->state = target;
|
||||
|
||||
@ -116,7 +119,7 @@ static int gpio_regulator_set_current_limit(struct regulator_dev *dev,
|
||||
|
||||
for (ptr = 0; ptr < data->nr_gpios; ptr++) {
|
||||
state = (target & (1 << ptr)) >> ptr;
|
||||
gpio_set_value(data->gpios[ptr].gpio, state);
|
||||
gpio_set_value_cansleep(data->gpios[ptr].gpio, state);
|
||||
}
|
||||
data->state = target;
|
||||
|
||||
@ -129,18 +132,108 @@ 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; i < 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,
|
||||
};
|
||||
|
||||
static int __devinit gpio_regulator_probe(struct platform_device *pdev)
|
||||
static int 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;
|
||||
@ -254,7 +348,7 @@ err:
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int __devexit gpio_regulator_remove(struct platform_device *pdev)
|
||||
static int gpio_regulator_remove(struct platform_device *pdev)
|
||||
{
|
||||
struct gpio_regulator_data *drvdata = platform_get_drvdata(pdev);
|
||||
|
||||
@ -270,12 +364,20 @@ static int __devexit gpio_regulator_remove(struct platform_device *pdev)
|
||||
return 0;
|
||||
}
|
||||
|
||||
#if defined(CONFIG_OF)
|
||||
static const struct of_device_id regulator_gpio_of_match[] __devinitconst = {
|
||||
{ .compatible = "regulator-gpio", },
|
||||
{},
|
||||
};
|
||||
#endif
|
||||
|
||||
static struct platform_driver gpio_regulator_driver = {
|
||||
.probe = gpio_regulator_probe,
|
||||
.remove = __devexit_p(gpio_regulator_remove),
|
||||
.remove = gpio_regulator_remove,
|
||||
.driver = {
|
||||
.name = "gpio-regulator",
|
||||
.owner = THIS_MODULE,
|
||||
.of_match_table = of_match_ptr(regulator_gpio_of_match),
|
||||
},
|
||||
};
|
||||
|
||||
|
@ -106,7 +106,7 @@ static const struct regulator_desc isl_rd[] = {
|
||||
},
|
||||
};
|
||||
|
||||
static int __devinit isl6271a_probe(struct i2c_client *i2c,
|
||||
static int isl6271a_probe(struct i2c_client *i2c,
|
||||
const struct i2c_device_id *id)
|
||||
{
|
||||
struct regulator_config config = { };
|
||||
@ -151,7 +151,7 @@ error:
|
||||
return err;
|
||||
}
|
||||
|
||||
static int __devexit isl6271a_remove(struct i2c_client *i2c)
|
||||
static int isl6271a_remove(struct i2c_client *i2c)
|
||||
{
|
||||
struct isl_pmic *pmic = i2c_get_clientdata(i2c);
|
||||
int i;
|
||||
@ -174,7 +174,7 @@ static struct i2c_driver isl6271a_i2c_driver = {
|
||||
.owner = THIS_MODULE,
|
||||
},
|
||||
.probe = isl6271a_probe,
|
||||
.remove = __devexit_p(isl6271a_remove),
|
||||
.remove = isl6271a_remove,
|
||||
.id_table = isl6271a_id,
|
||||
};
|
||||
|
||||
|
@ -386,7 +386,7 @@ static int lp3971_set_bits(struct lp3971 *lp3971, u8 reg, u16 mask, u16 val)
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int __devinit setup_regulators(struct lp3971 *lp3971,
|
||||
static int setup_regulators(struct lp3971 *lp3971,
|
||||
struct lp3971_platform_data *pdata)
|
||||
{
|
||||
int i, err;
|
||||
@ -429,7 +429,7 @@ err_nomem:
|
||||
return err;
|
||||
}
|
||||
|
||||
static int __devinit lp3971_i2c_probe(struct i2c_client *i2c,
|
||||
static int lp3971_i2c_probe(struct i2c_client *i2c,
|
||||
const struct i2c_device_id *id)
|
||||
{
|
||||
struct lp3971 *lp3971;
|
||||
@ -472,7 +472,7 @@ err_detect:
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int __devexit lp3971_i2c_remove(struct i2c_client *i2c)
|
||||
static int lp3971_i2c_remove(struct i2c_client *i2c)
|
||||
{
|
||||
struct lp3971 *lp3971 = i2c_get_clientdata(i2c);
|
||||
int i;
|
||||
@ -498,7 +498,7 @@ static struct i2c_driver lp3971_i2c_driver = {
|
||||
.owner = THIS_MODULE,
|
||||
},
|
||||
.probe = lp3971_i2c_probe,
|
||||
.remove = __devexit_p(lp3971_i2c_remove),
|
||||
.remove = lp3971_i2c_remove,
|
||||
.id_table = lp3971_i2c_id,
|
||||
};
|
||||
|
||||
|
@ -481,7 +481,7 @@ static const struct regulator_desc regulators[] = {
|
||||
},
|
||||
};
|
||||
|
||||
static int __devinit setup_regulators(struct lp3972 *lp3972,
|
||||
static int setup_regulators(struct lp3972 *lp3972,
|
||||
struct lp3972_platform_data *pdata)
|
||||
{
|
||||
int i, err;
|
||||
@ -523,7 +523,7 @@ err_nomem:
|
||||
return err;
|
||||
}
|
||||
|
||||
static int __devinit lp3972_i2c_probe(struct i2c_client *i2c,
|
||||
static int lp3972_i2c_probe(struct i2c_client *i2c,
|
||||
const struct i2c_device_id *id)
|
||||
{
|
||||
struct lp3972 *lp3972;
|
||||
@ -569,7 +569,7 @@ err_detect:
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int __devexit lp3972_i2c_remove(struct i2c_client *i2c)
|
||||
static int lp3972_i2c_remove(struct i2c_client *i2c)
|
||||
{
|
||||
struct lp3972 *lp3972 = i2c_get_clientdata(i2c);
|
||||
int i;
|
||||
@ -594,7 +594,7 @@ static struct i2c_driver lp3972_i2c_driver = {
|
||||
.owner = THIS_MODULE,
|
||||
},
|
||||
.probe = lp3972_i2c_probe,
|
||||
.remove = __devexit_p(lp3972_i2c_remove),
|
||||
.remove = lp3972_i2c_remove,
|
||||
.id_table = lp3972_i2c_id,
|
||||
};
|
||||
|
||||
|
@ -893,7 +893,7 @@ err_dev:
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int __devexit lp872x_remove(struct i2c_client *cl)
|
||||
static int lp872x_remove(struct i2c_client *cl)
|
||||
{
|
||||
struct lp872x *lp = i2c_get_clientdata(cl);
|
||||
|
||||
@ -914,7 +914,7 @@ static struct i2c_driver lp872x_driver = {
|
||||
.owner = THIS_MODULE,
|
||||
},
|
||||
.probe = lp872x_probe,
|
||||
.remove = __devexit_p(lp872x_remove),
|
||||
.remove = lp872x_remove,
|
||||
.id_table = lp872x_ids,
|
||||
};
|
||||
|
||||
|
@ -429,18 +429,6 @@ static struct regulator_desc lp8788_buck_desc[] = {
|
||||
},
|
||||
};
|
||||
|
||||
static int _gpio_request(struct lp8788_buck *buck, int gpio, char *name)
|
||||
{
|
||||
struct device *dev = buck->lp->dev;
|
||||
|
||||
if (!gpio_is_valid(gpio)) {
|
||||
dev_err(dev, "invalid gpio: %d\n", gpio);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
return devm_gpio_request_one(dev, gpio, DVS_LOW, name);
|
||||
}
|
||||
|
||||
static int lp8788_dvs_gpio_request(struct lp8788_buck *buck,
|
||||
enum lp8788_buck_id id)
|
||||
{
|
||||
@ -452,7 +440,8 @@ static int lp8788_dvs_gpio_request(struct lp8788_buck *buck,
|
||||
switch (id) {
|
||||
case BUCK1:
|
||||
gpio = pdata->buck1_dvs->gpio;
|
||||
ret = _gpio_request(buck, gpio, b1_name);
|
||||
ret = devm_gpio_request_one(buck->lp->dev, gpio, DVS_LOW,
|
||||
b1_name);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
@ -461,7 +450,8 @@ static int lp8788_dvs_gpio_request(struct lp8788_buck *buck,
|
||||
case BUCK2:
|
||||
for (i = 0 ; i < LP8788_NUM_BUCK2_DVS ; i++) {
|
||||
gpio = pdata->buck2_dvs->gpio[i];
|
||||
ret = _gpio_request(buck, gpio, b2_name[i]);
|
||||
ret = devm_gpio_request_one(buck->lp->dev, gpio,
|
||||
DVS_LOW, b2_name[i]);
|
||||
if (ret)
|
||||
return ret;
|
||||
}
|
||||
@ -504,7 +494,7 @@ set_default_dvs_mode:
|
||||
default_dvs_mode[id]);
|
||||
}
|
||||
|
||||
static __devinit int lp8788_buck_probe(struct platform_device *pdev)
|
||||
static int lp8788_buck_probe(struct platform_device *pdev)
|
||||
{
|
||||
struct lp8788 *lp = dev_get_drvdata(pdev->dev.parent);
|
||||
int id = pdev->id;
|
||||
@ -542,7 +532,7 @@ static __devinit int lp8788_buck_probe(struct platform_device *pdev)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int __devexit lp8788_buck_remove(struct platform_device *pdev)
|
||||
static int lp8788_buck_remove(struct platform_device *pdev)
|
||||
{
|
||||
struct lp8788_buck *buck = platform_get_drvdata(pdev);
|
||||
|
||||
@ -554,7 +544,7 @@ static int __devexit lp8788_buck_remove(struct platform_device *pdev)
|
||||
|
||||
static struct platform_driver lp8788_buck_driver = {
|
||||
.probe = lp8788_buck_probe,
|
||||
.remove = __devexit_p(lp8788_buck_remove),
|
||||
.remove = lp8788_buck_remove,
|
||||
.driver = {
|
||||
.name = LP8788_DEV_BUCK,
|
||||
.owner = THIS_MODULE,
|
||||
|
@ -126,7 +126,7 @@ struct lp8788_ldo {
|
||||
};
|
||||
|
||||
/* DLDO 1, 2, 3, 9 voltage table */
|
||||
const int lp8788_dldo1239_vtbl[] = {
|
||||
static const int lp8788_dldo1239_vtbl[] = {
|
||||
1800000, 1900000, 2000000, 2100000, 2200000, 2300000, 2400000, 2500000,
|
||||
2600000, 2700000, 2800000, 2900000, 3000000, 2850000, 2850000, 2850000,
|
||||
2850000, 2850000, 2850000, 2850000, 2850000, 2850000, 2850000, 2850000,
|
||||
@ -662,14 +662,6 @@ static int lp8788_config_ldo_enable_mode(struct lp8788_ldo *ldo,
|
||||
[EN_DLDO7] = LP8788_EN_SEL_DLDO7_M,
|
||||
[EN_DLDO911] = LP8788_EN_SEL_DLDO911_M,
|
||||
};
|
||||
u8 val[] = {
|
||||
[EN_ALDO1] = 0 << 5,
|
||||
[EN_ALDO234] = 0 << 4,
|
||||
[EN_ALDO5] = 0 << 3,
|
||||
[EN_ALDO7] = 0 << 2,
|
||||
[EN_DLDO7] = 0 << 1,
|
||||
[EN_DLDO911] = 0 << 0,
|
||||
};
|
||||
|
||||
switch (id) {
|
||||
case DLDO7:
|
||||
@ -708,11 +700,10 @@ static int lp8788_config_ldo_enable_mode(struct lp8788_ldo *ldo,
|
||||
return ret;
|
||||
|
||||
set_default_ldo_enable_mode:
|
||||
return lp8788_update_bits(lp, LP8788_EN_SEL, en_mask[enable_id],
|
||||
val[enable_id]);
|
||||
return lp8788_update_bits(lp, LP8788_EN_SEL, en_mask[enable_id], 0);
|
||||
}
|
||||
|
||||
static __devinit int lp8788_dldo_probe(struct platform_device *pdev)
|
||||
static int lp8788_dldo_probe(struct platform_device *pdev)
|
||||
{
|
||||
struct lp8788 *lp = dev_get_drvdata(pdev->dev.parent);
|
||||
int id = pdev->id;
|
||||
@ -749,7 +740,7 @@ static __devinit int lp8788_dldo_probe(struct platform_device *pdev)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int __devexit lp8788_dldo_remove(struct platform_device *pdev)
|
||||
static int lp8788_dldo_remove(struct platform_device *pdev)
|
||||
{
|
||||
struct lp8788_ldo *ldo = platform_get_drvdata(pdev);
|
||||
|
||||
@ -761,14 +752,14 @@ static int __devexit lp8788_dldo_remove(struct platform_device *pdev)
|
||||
|
||||
static struct platform_driver lp8788_dldo_driver = {
|
||||
.probe = lp8788_dldo_probe,
|
||||
.remove = __devexit_p(lp8788_dldo_remove),
|
||||
.remove = lp8788_dldo_remove,
|
||||
.driver = {
|
||||
.name = LP8788_DEV_DLDO,
|
||||
.owner = THIS_MODULE,
|
||||
},
|
||||
};
|
||||
|
||||
static __devinit int lp8788_aldo_probe(struct platform_device *pdev)
|
||||
static int lp8788_aldo_probe(struct platform_device *pdev)
|
||||
{
|
||||
struct lp8788 *lp = dev_get_drvdata(pdev->dev.parent);
|
||||
int id = pdev->id;
|
||||
@ -805,7 +796,7 @@ static __devinit int lp8788_aldo_probe(struct platform_device *pdev)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int __devexit lp8788_aldo_remove(struct platform_device *pdev)
|
||||
static int lp8788_aldo_remove(struct platform_device *pdev)
|
||||
{
|
||||
struct lp8788_ldo *ldo = platform_get_drvdata(pdev);
|
||||
|
||||
@ -817,7 +808,7 @@ static int __devexit lp8788_aldo_remove(struct platform_device *pdev)
|
||||
|
||||
static struct platform_driver lp8788_aldo_driver = {
|
||||
.probe = lp8788_aldo_probe,
|
||||
.remove = __devexit_p(lp8788_aldo_remove),
|
||||
.remove = lp8788_aldo_remove,
|
||||
.driver = {
|
||||
.name = LP8788_DEV_ALDO,
|
||||
.owner = THIS_MODULE,
|
||||
|
@ -44,6 +44,9 @@ struct max1586_data {
|
||||
unsigned int min_uV;
|
||||
unsigned int max_uV;
|
||||
|
||||
unsigned int v3_curr_sel;
|
||||
unsigned int v6_curr_sel;
|
||||
|
||||
struct regulator_dev *rdev[0];
|
||||
};
|
||||
|
||||
@ -63,31 +66,60 @@ static int v6_voltages_uv[] = { 1, 1800000, 2500000, 3000000 };
|
||||
* R24 and R25=100kOhm as described in the data sheet.
|
||||
* The gain is approximately: 1 + R24/R25 + R24/185.5kOhm
|
||||
*/
|
||||
static int max1586_v3_get_voltage_sel(struct regulator_dev *rdev)
|
||||
{
|
||||
struct max1586_data *max1586 = rdev_get_drvdata(rdev);
|
||||
|
||||
return max1586->v3_curr_sel;
|
||||
}
|
||||
|
||||
static int max1586_v3_set_voltage_sel(struct regulator_dev *rdev,
|
||||
unsigned selector)
|
||||
{
|
||||
struct max1586_data *max1586 = rdev_get_drvdata(rdev);
|
||||
struct i2c_client *client = max1586->client;
|
||||
int ret;
|
||||
u8 v3_prog;
|
||||
|
||||
dev_dbg(&client->dev, "changing voltage v3 to %dmv\n",
|
||||
regulator_list_voltage_linear(rdev, selector) / 1000);
|
||||
|
||||
v3_prog = I2C_V3_SELECT | (u8) selector;
|
||||
return i2c_smbus_write_byte(client, v3_prog);
|
||||
ret = i2c_smbus_write_byte(client, v3_prog);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
max1586->v3_curr_sel = selector;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int max1586_v6_get_voltage_sel(struct regulator_dev *rdev)
|
||||
{
|
||||
struct max1586_data *max1586 = rdev_get_drvdata(rdev);
|
||||
|
||||
return max1586->v6_curr_sel;
|
||||
}
|
||||
|
||||
static int max1586_v6_set_voltage_sel(struct regulator_dev *rdev,
|
||||
unsigned int selector)
|
||||
{
|
||||
struct i2c_client *client = rdev_get_drvdata(rdev);
|
||||
struct max1586_data *max1586 = rdev_get_drvdata(rdev);
|
||||
struct i2c_client *client = max1586->client;
|
||||
u8 v6_prog;
|
||||
int ret;
|
||||
|
||||
dev_dbg(&client->dev, "changing voltage v6 to %dmv\n",
|
||||
rdev->desc->volt_table[selector] / 1000);
|
||||
|
||||
v6_prog = I2C_V6_SELECT | (u8) selector;
|
||||
return i2c_smbus_write_byte(client, v6_prog);
|
||||
ret = i2c_smbus_write_byte(client, v6_prog);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
max1586->v6_curr_sel = selector;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
@ -95,12 +127,14 @@ static int max1586_v6_set_voltage_sel(struct regulator_dev *rdev,
|
||||
* the set up value.
|
||||
*/
|
||||
static struct regulator_ops max1586_v3_ops = {
|
||||
.get_voltage_sel = max1586_v3_get_voltage_sel,
|
||||
.set_voltage_sel = max1586_v3_set_voltage_sel,
|
||||
.list_voltage = regulator_list_voltage_linear,
|
||||
.map_voltage = regulator_map_voltage_linear,
|
||||
};
|
||||
|
||||
static struct regulator_ops max1586_v6_ops = {
|
||||
.get_voltage_sel = max1586_v6_get_voltage_sel,
|
||||
.set_voltage_sel = max1586_v6_set_voltage_sel,
|
||||
.list_voltage = regulator_list_voltage_table,
|
||||
};
|
||||
@ -125,7 +159,7 @@ static struct regulator_desc max1586_reg[] = {
|
||||
},
|
||||
};
|
||||
|
||||
static int __devinit max1586_pmic_probe(struct i2c_client *client,
|
||||
static int max1586_pmic_probe(struct i2c_client *client,
|
||||
const struct i2c_device_id *i2c_id)
|
||||
{
|
||||
struct regulator_dev **rdev;
|
||||
@ -148,6 +182,10 @@ static int __devinit max1586_pmic_probe(struct i2c_client *client,
|
||||
max1586->min_uV = MAX1586_V3_MIN_UV / 1000 * pdata->v3_gain / 1000;
|
||||
max1586->max_uV = MAX1586_V3_MAX_UV / 1000 * pdata->v3_gain / 1000;
|
||||
|
||||
/* Set curr_sel to default voltage on power-up */
|
||||
max1586->v3_curr_sel = 24; /* 1.3V */
|
||||
max1586->v6_curr_sel = 0;
|
||||
|
||||
rdev = max1586->rdev;
|
||||
for (i = 0; i < pdata->num_subdevs && i <= MAX1586_V6; i++) {
|
||||
id = pdata->subdevs[i].id;
|
||||
@ -188,7 +226,7 @@ err:
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int __devexit max1586_pmic_remove(struct i2c_client *client)
|
||||
static int max1586_pmic_remove(struct i2c_client *client)
|
||||
{
|
||||
struct max1586_data *max1586 = i2c_get_clientdata(client);
|
||||
int i;
|
||||
@ -207,7 +245,7 @@ MODULE_DEVICE_TABLE(i2c, max1586_id);
|
||||
|
||||
static struct i2c_driver max1586_pmic_driver = {
|
||||
.probe = max1586_pmic_probe,
|
||||
.remove = __devexit_p(max1586_pmic_remove),
|
||||
.remove = max1586_pmic_remove,
|
||||
.driver = {
|
||||
.name = "max1586",
|
||||
.owner = THIS_MODULE,
|
||||
|
@ -67,8 +67,94 @@ enum max77686_ramp_rate {
|
||||
|
||||
struct max77686_data {
|
||||
struct regulator_dev *rdev[MAX77686_REGULATORS];
|
||||
unsigned int opmode[MAX77686_REGULATORS];
|
||||
};
|
||||
|
||||
/* Some BUCKS supports Normal[ON/OFF] mode during suspend */
|
||||
static int max77686_buck_set_suspend_disable(struct regulator_dev *rdev)
|
||||
{
|
||||
unsigned int val;
|
||||
struct max77686_data *max77686 = rdev_get_drvdata(rdev);
|
||||
|
||||
if (rdev->desc->id == MAX77686_BUCK1)
|
||||
val = 0x1;
|
||||
else
|
||||
val = 0x1 << MAX77686_OPMODE_BUCK234_SHIFT;
|
||||
|
||||
max77686->opmode[rdev->desc->id] = val;
|
||||
return regmap_update_bits(rdev->regmap, rdev->desc->enable_reg,
|
||||
rdev->desc->enable_mask,
|
||||
val);
|
||||
}
|
||||
|
||||
/* Some LDOs supports [LPM/Normal]ON mode during suspend state */
|
||||
static int max77686_set_suspend_mode(struct regulator_dev *rdev,
|
||||
unsigned int mode)
|
||||
{
|
||||
struct max77686_data *max77686 = rdev_get_drvdata(rdev);
|
||||
unsigned int val;
|
||||
|
||||
/* BUCK[5-9] doesn't support this feature */
|
||||
if (rdev->desc->id >= MAX77686_BUCK5)
|
||||
return 0;
|
||||
|
||||
switch (mode) {
|
||||
case REGULATOR_MODE_IDLE: /* ON in LP Mode */
|
||||
val = 0x2 << MAX77686_OPMODE_SHIFT;
|
||||
break;
|
||||
case REGULATOR_MODE_NORMAL: /* ON in Normal Mode */
|
||||
val = 0x3 << MAX77686_OPMODE_SHIFT;
|
||||
break;
|
||||
default:
|
||||
pr_warn("%s: regulator_suspend_mode : 0x%x not supported\n",
|
||||
rdev->desc->name, mode);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
max77686->opmode[rdev->desc->id] = val;
|
||||
return regmap_update_bits(rdev->regmap, rdev->desc->enable_reg,
|
||||
rdev->desc->enable_mask,
|
||||
val);
|
||||
}
|
||||
|
||||
/* Some LDOs supports LPM-ON/OFF/Normal-ON mode during suspend state */
|
||||
static int max77686_ldo_set_suspend_mode(struct regulator_dev *rdev,
|
||||
unsigned int mode)
|
||||
{
|
||||
unsigned int val;
|
||||
struct max77686_data *max77686 = rdev_get_drvdata(rdev);
|
||||
|
||||
switch (mode) {
|
||||
case REGULATOR_MODE_STANDBY: /* switch off */
|
||||
val = 0x1 << MAX77686_OPMODE_SHIFT;
|
||||
break;
|
||||
case REGULATOR_MODE_IDLE: /* ON in LP Mode */
|
||||
val = 0x2 << MAX77686_OPMODE_SHIFT;
|
||||
break;
|
||||
case REGULATOR_MODE_NORMAL: /* ON in Normal Mode */
|
||||
val = 0x3 << MAX77686_OPMODE_SHIFT;
|
||||
break;
|
||||
default:
|
||||
pr_warn("%s: regulator_suspend_mode : 0x%x not supported\n",
|
||||
rdev->desc->name, mode);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
max77686->opmode[rdev->desc->id] = val;
|
||||
return regmap_update_bits(rdev->regmap, rdev->desc->enable_reg,
|
||||
rdev->desc->enable_mask,
|
||||
val);
|
||||
}
|
||||
|
||||
static int max77686_enable(struct regulator_dev *rdev)
|
||||
{
|
||||
struct max77686_data *max77686 = rdev_get_drvdata(rdev);
|
||||
|
||||
return regmap_update_bits(rdev->regmap, rdev->desc->enable_reg,
|
||||
rdev->desc->enable_mask,
|
||||
max77686->opmode[rdev->desc->id]);
|
||||
}
|
||||
|
||||
static int max77686_set_ramp_delay(struct regulator_dev *rdev, int ramp_delay)
|
||||
{
|
||||
unsigned int ramp_value = RAMP_RATE_NO_CTRL;
|
||||
@ -98,23 +184,49 @@ static struct regulator_ops max77686_ops = {
|
||||
.list_voltage = regulator_list_voltage_linear,
|
||||
.map_voltage = regulator_map_voltage_linear,
|
||||
.is_enabled = regulator_is_enabled_regmap,
|
||||
.enable = regulator_enable_regmap,
|
||||
.enable = max77686_enable,
|
||||
.disable = regulator_disable_regmap,
|
||||
.get_voltage_sel = regulator_get_voltage_sel_regmap,
|
||||
.set_voltage_sel = regulator_set_voltage_sel_regmap,
|
||||
.set_voltage_time_sel = regulator_set_voltage_time_sel,
|
||||
.set_suspend_mode = max77686_set_suspend_mode,
|
||||
};
|
||||
|
||||
static struct regulator_ops max77686_ldo_ops = {
|
||||
.list_voltage = regulator_list_voltage_linear,
|
||||
.map_voltage = regulator_map_voltage_linear,
|
||||
.is_enabled = regulator_is_enabled_regmap,
|
||||
.enable = max77686_enable,
|
||||
.disable = regulator_disable_regmap,
|
||||
.get_voltage_sel = regulator_get_voltage_sel_regmap,
|
||||
.set_voltage_sel = regulator_set_voltage_sel_regmap,
|
||||
.set_voltage_time_sel = regulator_set_voltage_time_sel,
|
||||
.set_suspend_mode = max77686_ldo_set_suspend_mode,
|
||||
};
|
||||
|
||||
static struct regulator_ops max77686_buck1_ops = {
|
||||
.list_voltage = regulator_list_voltage_linear,
|
||||
.map_voltage = regulator_map_voltage_linear,
|
||||
.is_enabled = regulator_is_enabled_regmap,
|
||||
.enable = max77686_enable,
|
||||
.disable = regulator_disable_regmap,
|
||||
.get_voltage_sel = regulator_get_voltage_sel_regmap,
|
||||
.set_voltage_sel = regulator_set_voltage_sel_regmap,
|
||||
.set_voltage_time_sel = regulator_set_voltage_time_sel,
|
||||
.set_suspend_disable = max77686_buck_set_suspend_disable,
|
||||
};
|
||||
|
||||
static struct regulator_ops max77686_buck_dvs_ops = {
|
||||
.list_voltage = regulator_list_voltage_linear,
|
||||
.map_voltage = regulator_map_voltage_linear,
|
||||
.is_enabled = regulator_is_enabled_regmap,
|
||||
.enable = regulator_enable_regmap,
|
||||
.enable = max77686_enable,
|
||||
.disable = regulator_disable_regmap,
|
||||
.get_voltage_sel = regulator_get_voltage_sel_regmap,
|
||||
.set_voltage_sel = regulator_set_voltage_sel_regmap,
|
||||
.set_voltage_time_sel = regulator_set_voltage_time_sel,
|
||||
.set_ramp_delay = max77686_set_ramp_delay,
|
||||
.set_suspend_disable = max77686_buck_set_suspend_disable,
|
||||
};
|
||||
|
||||
#define regulator_desc_ldo(num) { \
|
||||
@ -133,7 +245,39 @@ static struct regulator_ops max77686_buck_dvs_ops = {
|
||||
.enable_mask = MAX77686_OPMODE_MASK \
|
||||
<< MAX77686_OPMODE_SHIFT, \
|
||||
}
|
||||
#define regulator_desc_lpm_ldo(num) { \
|
||||
.name = "LDO"#num, \
|
||||
.id = MAX77686_LDO##num, \
|
||||
.ops = &max77686_ldo_ops, \
|
||||
.type = REGULATOR_VOLTAGE, \
|
||||
.owner = THIS_MODULE, \
|
||||
.min_uV = MAX77686_LDO_MINUV, \
|
||||
.uV_step = MAX77686_LDO_UVSTEP, \
|
||||
.ramp_delay = MAX77686_RAMP_DELAY, \
|
||||
.n_voltages = MAX77686_VSEL_MASK + 1, \
|
||||
.vsel_reg = MAX77686_REG_LDO1CTRL1 + num - 1, \
|
||||
.vsel_mask = MAX77686_VSEL_MASK, \
|
||||
.enable_reg = MAX77686_REG_LDO1CTRL1 + num - 1, \
|
||||
.enable_mask = MAX77686_OPMODE_MASK \
|
||||
<< MAX77686_OPMODE_SHIFT, \
|
||||
}
|
||||
#define regulator_desc_ldo_low(num) { \
|
||||
.name = "LDO"#num, \
|
||||
.id = MAX77686_LDO##num, \
|
||||
.ops = &max77686_ldo_ops, \
|
||||
.type = REGULATOR_VOLTAGE, \
|
||||
.owner = THIS_MODULE, \
|
||||
.min_uV = MAX77686_LDO_LOW_MINUV, \
|
||||
.uV_step = MAX77686_LDO_LOW_UVSTEP, \
|
||||
.ramp_delay = MAX77686_RAMP_DELAY, \
|
||||
.n_voltages = MAX77686_VSEL_MASK + 1, \
|
||||
.vsel_reg = MAX77686_REG_LDO1CTRL1 + num - 1, \
|
||||
.vsel_mask = MAX77686_VSEL_MASK, \
|
||||
.enable_reg = MAX77686_REG_LDO1CTRL1 + num - 1, \
|
||||
.enable_mask = MAX77686_OPMODE_MASK \
|
||||
<< MAX77686_OPMODE_SHIFT, \
|
||||
}
|
||||
#define regulator_desc_ldo1_low(num) { \
|
||||
.name = "LDO"#num, \
|
||||
.id = MAX77686_LDO##num, \
|
||||
.ops = &max77686_ops, \
|
||||
@ -167,7 +311,7 @@ static struct regulator_ops max77686_buck_dvs_ops = {
|
||||
#define regulator_desc_buck1(num) { \
|
||||
.name = "BUCK"#num, \
|
||||
.id = MAX77686_BUCK##num, \
|
||||
.ops = &max77686_ops, \
|
||||
.ops = &max77686_buck1_ops, \
|
||||
.type = REGULATOR_VOLTAGE, \
|
||||
.owner = THIS_MODULE, \
|
||||
.min_uV = MAX77686_BUCK_MINUV, \
|
||||
@ -197,7 +341,7 @@ static struct regulator_ops max77686_buck_dvs_ops = {
|
||||
}
|
||||
|
||||
static struct regulator_desc regulators[] = {
|
||||
regulator_desc_ldo_low(1),
|
||||
regulator_desc_ldo1_low(1),
|
||||
regulator_desc_ldo_low(2),
|
||||
regulator_desc_ldo(3),
|
||||
regulator_desc_ldo(4),
|
||||
@ -206,13 +350,13 @@ static struct regulator_desc regulators[] = {
|
||||
regulator_desc_ldo_low(7),
|
||||
regulator_desc_ldo_low(8),
|
||||
regulator_desc_ldo(9),
|
||||
regulator_desc_ldo(10),
|
||||
regulator_desc_ldo(11),
|
||||
regulator_desc_ldo(12),
|
||||
regulator_desc_lpm_ldo(10),
|
||||
regulator_desc_lpm_ldo(11),
|
||||
regulator_desc_lpm_ldo(12),
|
||||
regulator_desc_ldo(13),
|
||||
regulator_desc_ldo(14),
|
||||
regulator_desc_lpm_ldo(14),
|
||||
regulator_desc_ldo_low(15),
|
||||
regulator_desc_ldo(16),
|
||||
regulator_desc_lpm_ldo(16),
|
||||
regulator_desc_ldo(17),
|
||||
regulator_desc_ldo(18),
|
||||
regulator_desc_ldo(19),
|
||||
@ -280,7 +424,7 @@ static int max77686_pmic_dt_parse_pdata(struct max77686_dev *iodev,
|
||||
}
|
||||
#endif /* CONFIG_OF */
|
||||
|
||||
static __devinit int max77686_pmic_probe(struct platform_device *pdev)
|
||||
static int max77686_pmic_probe(struct platform_device *pdev)
|
||||
{
|
||||
struct max77686_dev *iodev = dev_get_drvdata(pdev->dev.parent);
|
||||
struct max77686_platform_data *pdata = dev_get_platdata(iodev->dev);
|
||||
@ -314,12 +458,14 @@ static __devinit int max77686_pmic_probe(struct platform_device *pdev)
|
||||
|
||||
config.dev = &pdev->dev;
|
||||
config.regmap = iodev->regmap;
|
||||
config.driver_data = max77686;
|
||||
platform_set_drvdata(pdev, max77686);
|
||||
|
||||
for (i = 0; i < MAX77686_REGULATORS; i++) {
|
||||
config.init_data = pdata->regulators[i].initdata;
|
||||
config.of_node = pdata->regulators[i].of_node;
|
||||
|
||||
max77686->opmode[i] = regulators[i].enable_mask;
|
||||
max77686->rdev[i] = regulator_register(®ulators[i], &config);
|
||||
if (IS_ERR(max77686->rdev[i])) {
|
||||
ret = PTR_ERR(max77686->rdev[i]);
|
||||
@ -337,7 +483,7 @@ err:
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int __devexit max77686_pmic_remove(struct platform_device *pdev)
|
||||
static int max77686_pmic_remove(struct platform_device *pdev)
|
||||
{
|
||||
struct max77686_data *max77686 = platform_get_drvdata(pdev);
|
||||
int i;
|
||||
@ -360,7 +506,7 @@ static struct platform_driver max77686_pmic_driver = {
|
||||
.owner = THIS_MODULE,
|
||||
},
|
||||
.probe = max77686_pmic_probe,
|
||||
.remove = __devexit_p(max77686_pmic_remove),
|
||||
.remove = max77686_pmic_remove,
|
||||
.id_table = max77686_pmic_id,
|
||||
};
|
||||
|
||||
|
@ -176,7 +176,7 @@ static struct regmap_config max8649_regmap_config = {
|
||||
.val_bits = 8,
|
||||
};
|
||||
|
||||
static int __devinit max8649_regulator_probe(struct i2c_client *client,
|
||||
static int max8649_regulator_probe(struct i2c_client *client,
|
||||
const struct i2c_device_id *id)
|
||||
{
|
||||
struct max8649_platform_data *pdata = client->dev.platform_data;
|
||||
@ -271,7 +271,7 @@ static int __devinit max8649_regulator_probe(struct i2c_client *client,
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int __devexit max8649_regulator_remove(struct i2c_client *client)
|
||||
static int max8649_regulator_remove(struct i2c_client *client)
|
||||
{
|
||||
struct max8649_regulator_info *info = i2c_get_clientdata(client);
|
||||
|
||||
@ -291,7 +291,7 @@ MODULE_DEVICE_TABLE(i2c, max8649_id);
|
||||
|
||||
static struct i2c_driver max8649_driver = {
|
||||
.probe = max8649_regulator_probe,
|
||||
.remove = __devexit_p(max8649_regulator_remove),
|
||||
.remove = max8649_regulator_remove,
|
||||
.driver = {
|
||||
.name = "max8649",
|
||||
},
|
||||
|
@ -305,7 +305,7 @@ static const struct regulator_desc max8660_reg[] = {
|
||||
},
|
||||
};
|
||||
|
||||
static int __devinit max8660_probe(struct i2c_client *client,
|
||||
static int max8660_probe(struct i2c_client *client,
|
||||
const struct i2c_device_id *i2c_id)
|
||||
{
|
||||
struct regulator_dev **rdev;
|
||||
@ -420,7 +420,7 @@ err_out:
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int __devexit max8660_remove(struct i2c_client *client)
|
||||
static int max8660_remove(struct i2c_client *client)
|
||||
{
|
||||
struct max8660 *max8660 = i2c_get_clientdata(client);
|
||||
int i;
|
||||
@ -440,7 +440,7 @@ MODULE_DEVICE_TABLE(i2c, max8660_id);
|
||||
|
||||
static struct i2c_driver max8660_driver = {
|
||||
.probe = max8660_probe,
|
||||
.remove = __devexit_p(max8660_remove),
|
||||
.remove = max8660_remove,
|
||||
.driver = {
|
||||
.name = "max8660",
|
||||
.owner = THIS_MODULE,
|
||||
|
@ -275,7 +275,7 @@ static inline struct device_node *match_of_node(int index)
|
||||
}
|
||||
#endif
|
||||
|
||||
static __devinit int max8907_regulator_probe(struct platform_device *pdev)
|
||||
static int max8907_regulator_probe(struct platform_device *pdev)
|
||||
{
|
||||
struct max8907 *max8907 = dev_get_drvdata(pdev->dev.parent);
|
||||
struct max8907_platform_data *pdata = dev_get_platdata(max8907->dev);
|
||||
@ -368,7 +368,7 @@ err_unregister_regulator:
|
||||
return ret;
|
||||
}
|
||||
|
||||
static __devexit int max8907_regulator_remove(struct platform_device *pdev)
|
||||
static int max8907_regulator_remove(struct platform_device *pdev)
|
||||
{
|
||||
struct max8907_regulator *pmic = platform_get_drvdata(pdev);
|
||||
int i;
|
||||
@ -385,7 +385,7 @@ static struct platform_driver max8907_regulator_driver = {
|
||||
.owner = THIS_MODULE,
|
||||
},
|
||||
.probe = max8907_regulator_probe,
|
||||
.remove = __devexit_p(max8907_regulator_remove),
|
||||
.remove = max8907_regulator_remove,
|
||||
};
|
||||
|
||||
static int __init max8907_regulator_init(void)
|
||||
|
@ -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,7 +244,37 @@ static struct max8925_regulator_info max8925_regulator_info[] = {
|
||||
MAX8925_LDO(20, 750, 3900, 50),
|
||||
};
|
||||
|
||||
static int __devinit max8925_regulator_probe(struct platform_device *pdev)
|
||||
#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 max8925_regulator_probe(struct platform_device *pdev)
|
||||
{
|
||||
struct max8925_chip *chip = dev_get_drvdata(pdev->dev.parent);
|
||||
struct regulator_init_data *pdata = pdev->dev.platform_data;
|
||||
@ -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",
|
||||
@ -257,7 +323,7 @@ static int __devinit max8925_regulator_probe(struct platform_device *pdev)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int __devexit max8925_regulator_remove(struct platform_device *pdev)
|
||||
static int max8925_regulator_remove(struct platform_device *pdev)
|
||||
{
|
||||
struct regulator_dev *rdev = platform_get_drvdata(pdev);
|
||||
|
||||
@ -273,7 +339,7 @@ static struct platform_driver max8925_regulator_driver = {
|
||||
.owner = THIS_MODULE,
|
||||
},
|
||||
.probe = max8925_regulator_probe,
|
||||
.remove = __devexit_p(max8925_regulator_remove),
|
||||
.remove = max8925_regulator_remove,
|
||||
};
|
||||
|
||||
static int __init max8925_regulator_init(void)
|
||||
|
@ -126,7 +126,7 @@ static const struct regulator_desc regulator = {
|
||||
.owner = THIS_MODULE,
|
||||
};
|
||||
|
||||
static int __devinit max8952_pmic_probe(struct i2c_client *client,
|
||||
static int max8952_pmic_probe(struct i2c_client *client,
|
||||
const struct i2c_device_id *i2c_id)
|
||||
{
|
||||
struct i2c_adapter *adapter = to_i2c_adapter(client->dev.parent);
|
||||
@ -247,7 +247,7 @@ static int __devinit max8952_pmic_probe(struct i2c_client *client,
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int __devexit max8952_pmic_remove(struct i2c_client *client)
|
||||
static int max8952_pmic_remove(struct i2c_client *client)
|
||||
{
|
||||
struct max8952_data *max8952 = i2c_get_clientdata(client);
|
||||
struct max8952_platform_data *pdata = max8952->pdata;
|
||||
@ -268,7 +268,7 @@ MODULE_DEVICE_TABLE(i2c, max8952_ids);
|
||||
|
||||
static struct i2c_driver max8952_pmic_driver = {
|
||||
.probe = max8952_pmic_probe,
|
||||
.remove = __devexit_p(max8952_pmic_remove),
|
||||
.remove = max8952_pmic_remove,
|
||||
.driver = {
|
||||
.name = "max8952",
|
||||
},
|
||||
|
505
drivers/regulator/max8973-regulator.c
Normal file
505
drivers/regulator/max8973-regulator.c
Normal file
@ -0,0 +1,505 @@
|
||||
/*
|
||||
* max8973-regulator.c -- Maxim max8973
|
||||
*
|
||||
* Regulator driver for MAXIM 8973 DC-DC step-down switching regulator.
|
||||
*
|
||||
* 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/kernel.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/init.h>
|
||||
#include <linux/err.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/regulator/driver.h>
|
||||
#include <linux/regulator/machine.h>
|
||||
#include <linux/regulator/max8973-regulator.h>
|
||||
#include <linux/gpio.h>
|
||||
#include <linux/i2c.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/regmap.h>
|
||||
|
||||
/* Register definitions */
|
||||
#define MAX8973_VOUT 0x0
|
||||
#define MAX8973_VOUT_DVS 0x1
|
||||
#define MAX8973_CONTROL1 0x2
|
||||
#define MAX8973_CONTROL2 0x3
|
||||
#define MAX8973_CHIPID1 0x4
|
||||
#define MAX8973_CHIPID2 0x5
|
||||
|
||||
#define MAX8973_MAX_VOUT_REG 2
|
||||
|
||||
/* MAX8973_VOUT */
|
||||
#define MAX8973_VOUT_ENABLE BIT(7)
|
||||
#define MAX8973_VOUT_MASK 0x7F
|
||||
|
||||
/* MAX8973_VOUT_DVS */
|
||||
#define MAX8973_DVS_VOUT_MASK 0x7F
|
||||
|
||||
/* MAX8973_CONTROL1 */
|
||||
#define MAX8973_SNS_ENABLE BIT(7)
|
||||
#define MAX8973_FPWM_EN_M BIT(6)
|
||||
#define MAX8973_NFSR_ENABLE BIT(5)
|
||||
#define MAX8973_AD_ENABLE BIT(4)
|
||||
#define MAX8973_BIAS_ENABLE BIT(3)
|
||||
#define MAX8973_FREQSHIFT_9PER BIT(2)
|
||||
|
||||
#define MAX8973_RAMP_12mV_PER_US 0x0
|
||||
#define MAX8973_RAMP_25mV_PER_US 0x1
|
||||
#define MAX8973_RAMP_50mV_PER_US 0x2
|
||||
#define MAX8973_RAMP_200mV_PER_US 0x3
|
||||
|
||||
/* MAX8973_CONTROL2 */
|
||||
#define MAX8973_WDTMR_ENABLE BIT(6)
|
||||
#define MAX8973_DISCH_ENBABLE BIT(5)
|
||||
#define MAX8973_FT_ENABLE BIT(4)
|
||||
|
||||
#define MAX8973_CKKADV_TRIP_DISABLE 0xC
|
||||
#define MAX8973_CKKADV_TRIP_75mV_PER_US 0x0
|
||||
#define MAX8973_CKKADV_TRIP_150mV_PER_US 0x4
|
||||
#define MAX8973_CKKADV_TRIP_75mV_PER_US_HIST_DIS 0x8
|
||||
#define MAX8973_CONTROL_CLKADV_TRIP_MASK 0x00030000
|
||||
|
||||
#define MAX8973_INDUCTOR_MIN_30_PER 0x0
|
||||
#define MAX8973_INDUCTOR_NOMINAL 0x1
|
||||
#define MAX8973_INDUCTOR_PLUS_30_PER 0x2
|
||||
#define MAX8973_INDUCTOR_PLUS_60_PER 0x3
|
||||
#define MAX8973_CONTROL_INDUCTOR_VALUE_MASK 0x00300000
|
||||
|
||||
#define MAX8973_MIN_VOLATGE 606250
|
||||
#define MAX8973_MAX_VOLATGE 1400000
|
||||
#define MAX8973_VOLATGE_STEP 6250
|
||||
#define MAX8973_BUCK_N_VOLTAGE 0x80
|
||||
|
||||
/* Maxim 8973 chip information */
|
||||
struct max8973_chip {
|
||||
struct device *dev;
|
||||
struct regulator_desc desc;
|
||||
struct regulator_dev *rdev;
|
||||
struct regmap *regmap;
|
||||
bool enable_external_control;
|
||||
int dvs_gpio;
|
||||
int lru_index[MAX8973_MAX_VOUT_REG];
|
||||
int curr_vout_val[MAX8973_MAX_VOUT_REG];
|
||||
int curr_vout_reg;
|
||||
int curr_gpio_val;
|
||||
bool valid_dvs_gpio;
|
||||
};
|
||||
|
||||
/*
|
||||
* find_voltage_set_register: Find new voltage configuration register (VOUT).
|
||||
* The finding of the new VOUT register will be based on the LRU mechanism.
|
||||
* Each VOUT register will have different voltage configured . This
|
||||
* Function will look if any of the VOUT register have requested voltage set
|
||||
* or not.
|
||||
* - If it is already there then it will make that register as most
|
||||
* recently used and return as found so that caller need not to set
|
||||
* the VOUT register but need to set the proper gpios to select this
|
||||
* VOUT register.
|
||||
* - If requested voltage is not found then it will use the least
|
||||
* recently mechanism to get new VOUT register for new configuration
|
||||
* and will return not_found so that caller need to set new VOUT
|
||||
* register and then gpios (both).
|
||||
*/
|
||||
static bool find_voltage_set_register(struct max8973_chip *tps,
|
||||
int req_vsel, int *vout_reg, int *gpio_val)
|
||||
{
|
||||
int i;
|
||||
bool found = false;
|
||||
int new_vout_reg = tps->lru_index[MAX8973_MAX_VOUT_REG - 1];
|
||||
int found_index = MAX8973_MAX_VOUT_REG - 1;
|
||||
|
||||
for (i = 0; i < MAX8973_MAX_VOUT_REG; ++i) {
|
||||
if (tps->curr_vout_val[tps->lru_index[i]] == req_vsel) {
|
||||
new_vout_reg = tps->lru_index[i];
|
||||
found_index = i;
|
||||
found = true;
|
||||
goto update_lru_index;
|
||||
}
|
||||
}
|
||||
|
||||
update_lru_index:
|
||||
for (i = found_index; i > 0; i--)
|
||||
tps->lru_index[i] = tps->lru_index[i - 1];
|
||||
|
||||
tps->lru_index[0] = new_vout_reg;
|
||||
*gpio_val = new_vout_reg;
|
||||
*vout_reg = MAX8973_VOUT + new_vout_reg;
|
||||
return found;
|
||||
}
|
||||
|
||||
static int max8973_dcdc_get_voltage_sel(struct regulator_dev *rdev)
|
||||
{
|
||||
struct max8973_chip *max = rdev_get_drvdata(rdev);
|
||||
unsigned int data;
|
||||
int ret;
|
||||
|
||||
ret = regmap_read(max->regmap, max->curr_vout_reg, &data);
|
||||
if (ret < 0) {
|
||||
dev_err(max->dev, "register %d read failed, err = %d\n",
|
||||
max->curr_vout_reg, ret);
|
||||
return ret;
|
||||
}
|
||||
return data & MAX8973_VOUT_MASK;
|
||||
}
|
||||
|
||||
static int max8973_dcdc_set_voltage_sel(struct regulator_dev *rdev,
|
||||
unsigned vsel)
|
||||
{
|
||||
struct max8973_chip *max = rdev_get_drvdata(rdev);
|
||||
int ret;
|
||||
bool found = false;
|
||||
int vout_reg = max->curr_vout_reg;
|
||||
int gpio_val = max->curr_gpio_val;
|
||||
|
||||
/*
|
||||
* If gpios are available to select the VOUT register then least
|
||||
* recently used register for new configuration.
|
||||
*/
|
||||
if (max->valid_dvs_gpio)
|
||||
found = find_voltage_set_register(max, vsel,
|
||||
&vout_reg, &gpio_val);
|
||||
|
||||
if (!found) {
|
||||
ret = regmap_update_bits(max->regmap, vout_reg,
|
||||
MAX8973_VOUT_MASK, vsel);
|
||||
if (ret < 0) {
|
||||
dev_err(max->dev, "register %d update failed, err %d\n",
|
||||
vout_reg, ret);
|
||||
return ret;
|
||||
}
|
||||
max->curr_vout_reg = vout_reg;
|
||||
max->curr_vout_val[gpio_val] = vsel;
|
||||
}
|
||||
|
||||
/* Select proper VOUT register vio gpios */
|
||||
if (max->valid_dvs_gpio) {
|
||||
gpio_set_value_cansleep(max->dvs_gpio, gpio_val & 0x1);
|
||||
max->curr_gpio_val = gpio_val;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int max8973_dcdc_set_mode(struct regulator_dev *rdev, unsigned int mode)
|
||||
{
|
||||
struct max8973_chip *max = rdev_get_drvdata(rdev);
|
||||
int ret;
|
||||
int pwm;
|
||||
|
||||
/* Enable force PWM mode in FAST mode only. */
|
||||
switch (mode) {
|
||||
case REGULATOR_MODE_FAST:
|
||||
pwm = MAX8973_FPWM_EN_M;
|
||||
break;
|
||||
|
||||
case REGULATOR_MODE_NORMAL:
|
||||
pwm = 0;
|
||||
break;
|
||||
|
||||
default:
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
ret = regmap_update_bits(max->regmap, MAX8973_CONTROL1,
|
||||
MAX8973_FPWM_EN_M, pwm);
|
||||
if (ret < 0)
|
||||
dev_err(max->dev, "register %d update failed, err %d\n",
|
||||
MAX8973_CONTROL1, ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static unsigned int max8973_dcdc_get_mode(struct regulator_dev *rdev)
|
||||
{
|
||||
struct max8973_chip *max = rdev_get_drvdata(rdev);
|
||||
unsigned int data;
|
||||
int ret;
|
||||
|
||||
ret = regmap_read(max->regmap, MAX8973_CONTROL1, &data);
|
||||
if (ret < 0) {
|
||||
dev_err(max->dev, "register %d read failed, err %d\n",
|
||||
MAX8973_CONTROL1, ret);
|
||||
return ret;
|
||||
}
|
||||
return (data & MAX8973_FPWM_EN_M) ?
|
||||
REGULATOR_MODE_FAST : REGULATOR_MODE_NORMAL;
|
||||
}
|
||||
|
||||
static struct regulator_ops max8973_dcdc_ops = {
|
||||
.get_voltage_sel = max8973_dcdc_get_voltage_sel,
|
||||
.set_voltage_sel = max8973_dcdc_set_voltage_sel,
|
||||
.list_voltage = regulator_list_voltage_linear,
|
||||
.set_mode = max8973_dcdc_set_mode,
|
||||
.get_mode = max8973_dcdc_get_mode,
|
||||
};
|
||||
|
||||
static int __devinit max8973_init_dcdc(struct max8973_chip *max,
|
||||
struct max8973_regulator_platform_data *pdata)
|
||||
{
|
||||
int ret;
|
||||
uint8_t control1 = 0;
|
||||
uint8_t control2 = 0;
|
||||
|
||||
if (pdata->control_flags & MAX8973_CONTROL_REMOTE_SENSE_ENABLE)
|
||||
control1 |= MAX8973_SNS_ENABLE;
|
||||
|
||||
if (!(pdata->control_flags & MAX8973_CONTROL_FALLING_SLEW_RATE_ENABLE))
|
||||
control1 |= MAX8973_NFSR_ENABLE;
|
||||
|
||||
if (pdata->control_flags & MAX8973_CONTROL_OUTPUT_ACTIVE_DISCH_ENABLE)
|
||||
control1 |= MAX8973_AD_ENABLE;
|
||||
|
||||
if (pdata->control_flags & MAX8973_CONTROL_BIAS_ENABLE)
|
||||
control1 |= MAX8973_BIAS_ENABLE;
|
||||
|
||||
if (pdata->control_flags & MAX8973_CONTROL_FREQ_SHIFT_9PER_ENABLE)
|
||||
control1 |= MAX8973_FREQSHIFT_9PER;
|
||||
|
||||
/* Set ramp delay */
|
||||
if (pdata->reg_init_data &&
|
||||
pdata->reg_init_data->constraints.ramp_delay) {
|
||||
if (pdata->reg_init_data->constraints.ramp_delay < 25000)
|
||||
control1 = MAX8973_RAMP_12mV_PER_US;
|
||||
else if (pdata->reg_init_data->constraints.ramp_delay < 50000)
|
||||
control1 = MAX8973_RAMP_25mV_PER_US;
|
||||
else if (pdata->reg_init_data->constraints.ramp_delay < 200000)
|
||||
control1 = MAX8973_RAMP_50mV_PER_US;
|
||||
else
|
||||
control1 = MAX8973_RAMP_200mV_PER_US;
|
||||
} else {
|
||||
control1 = MAX8973_RAMP_12mV_PER_US;
|
||||
max->desc.ramp_delay = 12500;
|
||||
}
|
||||
|
||||
if (!(pdata->control_flags & MAX8973_CONTROL_PULL_DOWN_ENABLE))
|
||||
control2 |= MAX8973_DISCH_ENBABLE;
|
||||
|
||||
/* Clock advance trip configuration */
|
||||
switch (pdata->control_flags & MAX8973_CONTROL_CLKADV_TRIP_MASK) {
|
||||
case MAX8973_CONTROL_CLKADV_TRIP_DISABLED:
|
||||
control2 |= MAX8973_CKKADV_TRIP_DISABLE;
|
||||
break;
|
||||
|
||||
case MAX8973_CONTROL_CLKADV_TRIP_75mV_PER_US:
|
||||
control2 |= MAX8973_CKKADV_TRIP_75mV_PER_US;
|
||||
break;
|
||||
|
||||
case MAX8973_CONTROL_CLKADV_TRIP_150mV_PER_US:
|
||||
control2 |= MAX8973_CKKADV_TRIP_150mV_PER_US;
|
||||
break;
|
||||
|
||||
case MAX8973_CONTROL_CLKADV_TRIP_75mV_PER_US_HIST_DIS:
|
||||
control2 |= MAX8973_CKKADV_TRIP_75mV_PER_US_HIST_DIS;
|
||||
break;
|
||||
}
|
||||
|
||||
/* Configure inductor value */
|
||||
switch (pdata->control_flags & MAX8973_CONTROL_INDUCTOR_VALUE_MASK) {
|
||||
case MAX8973_CONTROL_INDUCTOR_VALUE_NOMINAL:
|
||||
control2 |= MAX8973_INDUCTOR_NOMINAL;
|
||||
break;
|
||||
|
||||
case MAX8973_CONTROL_INDUCTOR_VALUE_MINUS_30_PER:
|
||||
control2 |= MAX8973_INDUCTOR_MIN_30_PER;
|
||||
break;
|
||||
|
||||
case MAX8973_CONTROL_INDUCTOR_VALUE_PLUS_30_PER:
|
||||
control2 |= MAX8973_INDUCTOR_PLUS_30_PER;
|
||||
break;
|
||||
|
||||
case MAX8973_CONTROL_INDUCTOR_VALUE_PLUS_60_PER:
|
||||
control2 |= MAX8973_INDUCTOR_PLUS_60_PER;
|
||||
break;
|
||||
}
|
||||
|
||||
ret = regmap_write(max->regmap, MAX8973_CONTROL1, control1);
|
||||
if (ret < 0) {
|
||||
dev_err(max->dev, "register %d write failed, err = %d",
|
||||
MAX8973_CONTROL1, ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
ret = regmap_write(max->regmap, MAX8973_CONTROL2, control2);
|
||||
if (ret < 0) {
|
||||
dev_err(max->dev, "register %d write failed, err = %d",
|
||||
MAX8973_CONTROL2, ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* If external control is enabled then disable EN bit */
|
||||
if (max->enable_external_control) {
|
||||
ret = regmap_update_bits(max->regmap, MAX8973_VOUT,
|
||||
MAX8973_VOUT_ENABLE, 0);
|
||||
if (ret < 0)
|
||||
dev_err(max->dev, "register %d update failed, err = %d",
|
||||
MAX8973_VOUT, ret);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
static const struct regmap_config max8973_regmap_config = {
|
||||
.reg_bits = 8,
|
||||
.val_bits = 8,
|
||||
.max_register = MAX8973_CHIPID2,
|
||||
.cache_type = REGCACHE_RBTREE,
|
||||
};
|
||||
|
||||
static int __devinit max8973_probe(struct i2c_client *client,
|
||||
const struct i2c_device_id *id)
|
||||
{
|
||||
struct max8973_regulator_platform_data *pdata;
|
||||
struct regulator_config config = { };
|
||||
struct regulator_dev *rdev;
|
||||
struct max8973_chip *max;
|
||||
int ret;
|
||||
|
||||
pdata = client->dev.platform_data;
|
||||
if (!pdata) {
|
||||
dev_err(&client->dev, "No Platform data");
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
max = devm_kzalloc(&client->dev, sizeof(*max), GFP_KERNEL);
|
||||
if (!max) {
|
||||
dev_err(&client->dev, "Memory allocation for max failed\n");
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
max->regmap = devm_regmap_init_i2c(client, &max8973_regmap_config);
|
||||
if (IS_ERR(max->regmap)) {
|
||||
ret = PTR_ERR(max->regmap);
|
||||
dev_err(&client->dev, "regmap init failed, err %d\n", ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
i2c_set_clientdata(client, max);
|
||||
max->dev = &client->dev;
|
||||
max->desc.name = id->name;
|
||||
max->desc.id = 0;
|
||||
max->desc.ops = &max8973_dcdc_ops;
|
||||
max->desc.type = REGULATOR_VOLTAGE;
|
||||
max->desc.owner = THIS_MODULE;
|
||||
max->desc.min_uV = MAX8973_MIN_VOLATGE;
|
||||
max->desc.uV_step = MAX8973_VOLATGE_STEP;
|
||||
max->desc.n_voltages = MAX8973_BUCK_N_VOLTAGE;
|
||||
|
||||
if (!pdata->enable_ext_control) {
|
||||
max->desc.enable_reg = MAX8973_VOUT;
|
||||
max->desc.enable_mask = MAX8973_VOUT_ENABLE;
|
||||
max8973_dcdc_ops.enable = regulator_enable_regmap;
|
||||
max8973_dcdc_ops.disable = regulator_disable_regmap;
|
||||
max8973_dcdc_ops.is_enabled = regulator_is_enabled_regmap;
|
||||
}
|
||||
|
||||
max->enable_external_control = pdata->enable_ext_control;
|
||||
max->dvs_gpio = pdata->dvs_gpio;
|
||||
max->curr_gpio_val = pdata->dvs_def_state;
|
||||
max->curr_vout_reg = MAX8973_VOUT + pdata->dvs_def_state;
|
||||
max->lru_index[0] = max->curr_vout_reg;
|
||||
max->valid_dvs_gpio = false;
|
||||
|
||||
if (gpio_is_valid(max->dvs_gpio)) {
|
||||
int gpio_flags;
|
||||
int i;
|
||||
|
||||
gpio_flags = (pdata->dvs_def_state) ?
|
||||
GPIOF_OUT_INIT_HIGH : GPIOF_OUT_INIT_LOW;
|
||||
ret = devm_gpio_request_one(&client->dev, max->dvs_gpio,
|
||||
gpio_flags, "max8973-dvs");
|
||||
if (ret) {
|
||||
dev_err(&client->dev,
|
||||
"gpio_request for gpio %d failed, err = %d\n",
|
||||
max->dvs_gpio, ret);
|
||||
return ret;
|
||||
}
|
||||
max->valid_dvs_gpio = true;
|
||||
|
||||
/*
|
||||
* Initialize the lru index with vout_reg id
|
||||
* The index 0 will be most recently used and
|
||||
* set with the max->curr_vout_reg */
|
||||
for (i = 0; i < MAX8973_MAX_VOUT_REG; ++i)
|
||||
max->lru_index[i] = i;
|
||||
max->lru_index[0] = max->curr_vout_reg;
|
||||
max->lru_index[max->curr_vout_reg] = 0;
|
||||
}
|
||||
|
||||
ret = max8973_init_dcdc(max, pdata);
|
||||
if (ret < 0) {
|
||||
dev_err(max->dev, "Max8973 Init failed, err = %d\n", ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
config.dev = &client->dev;
|
||||
config.init_data = pdata->reg_init_data;
|
||||
config.driver_data = max;
|
||||
config.of_node = client->dev.of_node;
|
||||
config.regmap = max->regmap;
|
||||
|
||||
/* Register the regulators */
|
||||
rdev = regulator_register(&max->desc, &config);
|
||||
if (IS_ERR(rdev)) {
|
||||
ret = PTR_ERR(rdev);
|
||||
dev_err(max->dev, "regulator register failed, err %d\n", ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
max->rdev = rdev;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int __devexit max8973_remove(struct i2c_client *client)
|
||||
{
|
||||
struct max8973_chip *max = i2c_get_clientdata(client);
|
||||
|
||||
regulator_unregister(max->rdev);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct i2c_device_id max8973_id[] = {
|
||||
{.name = "max8973",},
|
||||
{},
|
||||
};
|
||||
|
||||
MODULE_DEVICE_TABLE(i2c, max8973_id);
|
||||
|
||||
static struct i2c_driver max8973_i2c_driver = {
|
||||
.driver = {
|
||||
.name = "max8973",
|
||||
.owner = THIS_MODULE,
|
||||
},
|
||||
.probe = max8973_probe,
|
||||
.remove = __devexit_p(max8973_remove),
|
||||
.id_table = max8973_id,
|
||||
};
|
||||
|
||||
static int __init max8973_init(void)
|
||||
{
|
||||
return i2c_add_driver(&max8973_i2c_driver);
|
||||
}
|
||||
subsys_initcall(max8973_init);
|
||||
|
||||
static void __exit max8973_cleanup(void)
|
||||
{
|
||||
i2c_del_driver(&max8973_i2c_driver);
|
||||
}
|
||||
module_exit(max8973_cleanup);
|
||||
|
||||
MODULE_AUTHOR("Laxman Dewangan <ldewangan@nvidia.com>");
|
||||
MODULE_DESCRIPTION("MAX8973 voltage regulator driver");
|
||||
MODULE_LICENSE("GPL v2");
|
@ -24,6 +24,7 @@
|
||||
#include <linux/bug.h>
|
||||
#include <linux/err.h>
|
||||
#include <linux/gpio.h>
|
||||
#include <linux/of_gpio.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/platform_device.h>
|
||||
@ -31,6 +32,7 @@
|
||||
#include <linux/regulator/machine.h>
|
||||
#include <linux/mfd/max8997.h>
|
||||
#include <linux/mfd/max8997-private.h>
|
||||
#include <linux/regulator/of_regulator.h>
|
||||
|
||||
struct max8997_data {
|
||||
struct device *dev;
|
||||
@ -933,22 +935,163 @@ static struct regulator_desc regulators[] = {
|
||||
max8997_charger_fixedstate_ops),
|
||||
};
|
||||
|
||||
static __devinit int max8997_pmic_probe(struct platform_device *pdev)
|
||||
#ifdef CONFIG_OF
|
||||
static int max8997_pmic_dt_parse_dvs_gpio(struct max8997_dev *iodev,
|
||||
struct max8997_platform_data *pdata,
|
||||
struct device_node *pmic_np)
|
||||
{
|
||||
int i, gpio;
|
||||
|
||||
for (i = 0; i < 3; i++) {
|
||||
gpio = of_get_named_gpio(pmic_np,
|
||||
"max8997,pmic-buck125-dvs-gpios", i);
|
||||
if (!gpio_is_valid(gpio)) {
|
||||
dev_err(iodev->dev, "invalid gpio[%d]: %d\n", i, gpio);
|
||||
return -EINVAL;
|
||||
}
|
||||
pdata->buck125_gpios[i] = gpio;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int max8997_pmic_dt_parse_pdata(struct max8997_dev *iodev,
|
||||
struct max8997_platform_data *pdata)
|
||||
{
|
||||
struct device_node *pmic_np, *regulators_np, *reg_np;
|
||||
struct max8997_regulator_data *rdata;
|
||||
unsigned int i, dvs_voltage_nr = 1, ret;
|
||||
|
||||
pmic_np = iodev->dev->of_node;
|
||||
if (!pmic_np) {
|
||||
dev_err(iodev->dev, "could not find pmic sub-node\n");
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
regulators_np = of_find_node_by_name(pmic_np, "regulators");
|
||||
if (!regulators_np) {
|
||||
dev_err(iodev->dev, "could not find regulators sub-node\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
/* count the number of regulators to be supported in pmic */
|
||||
pdata->num_regulators = 0;
|
||||
for_each_child_of_node(regulators_np, reg_np)
|
||||
pdata->num_regulators++;
|
||||
|
||||
rdata = devm_kzalloc(iodev->dev, sizeof(*rdata) *
|
||||
pdata->num_regulators, GFP_KERNEL);
|
||||
if (!rdata) {
|
||||
dev_err(iodev->dev, "could not allocate memory for "
|
||||
"regulator data\n");
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
pdata->regulators = rdata;
|
||||
for_each_child_of_node(regulators_np, reg_np) {
|
||||
for (i = 0; i < ARRAY_SIZE(regulators); i++)
|
||||
if (!of_node_cmp(reg_np->name, regulators[i].name))
|
||||
break;
|
||||
|
||||
if (i == ARRAY_SIZE(regulators)) {
|
||||
dev_warn(iodev->dev, "don't know how to configure "
|
||||
"regulator %s\n", reg_np->name);
|
||||
continue;
|
||||
}
|
||||
|
||||
rdata->id = i;
|
||||
rdata->initdata = of_get_regulator_init_data(
|
||||
iodev->dev, reg_np);
|
||||
rdata->reg_node = reg_np;
|
||||
rdata++;
|
||||
}
|
||||
|
||||
if (of_get_property(pmic_np, "max8997,pmic-buck1-uses-gpio-dvs", NULL))
|
||||
pdata->buck1_gpiodvs = true;
|
||||
|
||||
if (of_get_property(pmic_np, "max8997,pmic-buck2-uses-gpio-dvs", NULL))
|
||||
pdata->buck2_gpiodvs = true;
|
||||
|
||||
if (of_get_property(pmic_np, "max8997,pmic-buck5-uses-gpio-dvs", NULL))
|
||||
pdata->buck5_gpiodvs = true;
|
||||
|
||||
if (pdata->buck1_gpiodvs || pdata->buck2_gpiodvs ||
|
||||
pdata->buck5_gpiodvs) {
|
||||
ret = max8997_pmic_dt_parse_dvs_gpio(iodev, pdata, pmic_np);
|
||||
if (ret)
|
||||
return -EINVAL;
|
||||
|
||||
if (of_property_read_u32(pmic_np,
|
||||
"max8997,pmic-buck125-default-dvs-idx",
|
||||
&pdata->buck125_default_idx)) {
|
||||
pdata->buck125_default_idx = 0;
|
||||
} else {
|
||||
if (pdata->buck125_default_idx >= 8) {
|
||||
pdata->buck125_default_idx = 0;
|
||||
dev_info(iodev->dev, "invalid value for "
|
||||
"default dvs index, using 0 instead\n");
|
||||
}
|
||||
}
|
||||
|
||||
if (of_get_property(pmic_np,
|
||||
"max8997,pmic-ignore-gpiodvs-side-effect", NULL))
|
||||
pdata->ignore_gpiodvs_side_effect = true;
|
||||
|
||||
dvs_voltage_nr = 8;
|
||||
}
|
||||
|
||||
if (of_property_read_u32_array(pmic_np,
|
||||
"max8997,pmic-buck1-dvs-voltage",
|
||||
pdata->buck1_voltage, dvs_voltage_nr)) {
|
||||
dev_err(iodev->dev, "buck1 voltages not specified\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (of_property_read_u32_array(pmic_np,
|
||||
"max8997,pmic-buck2-dvs-voltage",
|
||||
pdata->buck2_voltage, dvs_voltage_nr)) {
|
||||
dev_err(iodev->dev, "buck2 voltages not specified\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (of_property_read_u32_array(pmic_np,
|
||||
"max8997,pmic-buck5-dvs-voltage",
|
||||
pdata->buck5_voltage, dvs_voltage_nr)) {
|
||||
dev_err(iodev->dev, "buck5 voltages not specified\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
#else
|
||||
static int max8997_pmic_dt_parse_pdata(struct max8997_dev *iodev,
|
||||
struct max8997_platform_data *pdata)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
#endif /* CONFIG_OF */
|
||||
|
||||
static int max8997_pmic_probe(struct platform_device *pdev)
|
||||
{
|
||||
struct max8997_dev *iodev = dev_get_drvdata(pdev->dev.parent);
|
||||
struct max8997_platform_data *pdata = dev_get_platdata(iodev->dev);
|
||||
struct max8997_platform_data *pdata = iodev->pdata;
|
||||
struct regulator_config config = { };
|
||||
struct regulator_dev **rdev;
|
||||
struct max8997_data *max8997;
|
||||
struct i2c_client *i2c;
|
||||
int i, ret, size;
|
||||
int i, ret, size, nr_dvs;
|
||||
u8 max_buck1 = 0, max_buck2 = 0, max_buck5 = 0;
|
||||
|
||||
if (!pdata) {
|
||||
if (IS_ERR_OR_NULL(pdata)) {
|
||||
dev_err(pdev->dev.parent, "No platform init data supplied.\n");
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
if (iodev->dev->of_node) {
|
||||
ret = max8997_pmic_dt_parse_pdata(iodev, pdata);
|
||||
if (ret)
|
||||
return ret;
|
||||
}
|
||||
|
||||
max8997 = devm_kzalloc(&pdev->dev, sizeof(struct max8997_data),
|
||||
GFP_KERNEL);
|
||||
if (!max8997)
|
||||
@ -973,7 +1116,10 @@ static __devinit int max8997_pmic_probe(struct platform_device *pdev)
|
||||
memcpy(max8997->buck125_gpios, pdata->buck125_gpios, sizeof(int) * 3);
|
||||
max8997->ignore_gpiodvs_side_effect = pdata->ignore_gpiodvs_side_effect;
|
||||
|
||||
for (i = 0; i < 8; i++) {
|
||||
nr_dvs = (pdata->buck1_gpiodvs || pdata->buck2_gpiodvs ||
|
||||
pdata->buck5_gpiodvs) ? 8 : 1;
|
||||
|
||||
for (i = 0; i < nr_dvs; i++) {
|
||||
max8997->buck1_vol[i] = ret =
|
||||
max8997_get_voltage_proper_val(
|
||||
&buck1245_voltage_map_desc,
|
||||
@ -1019,6 +1165,19 @@ static __devinit int max8997_pmic_probe(struct platform_device *pdev)
|
||||
max_buck5, 0x3f);
|
||||
}
|
||||
|
||||
/* Initialize all the DVS related BUCK registers */
|
||||
for (i = 0; i < nr_dvs; i++) {
|
||||
max8997_update_reg(i2c, MAX8997_REG_BUCK1DVS1 + i,
|
||||
max8997->buck1_vol[i],
|
||||
0x3f);
|
||||
max8997_update_reg(i2c, MAX8997_REG_BUCK2DVS1 + i,
|
||||
max8997->buck2_vol[i],
|
||||
0x3f);
|
||||
max8997_update_reg(i2c, MAX8997_REG_BUCK5DVS1 + i,
|
||||
max8997->buck5_vol[i],
|
||||
0x3f);
|
||||
}
|
||||
|
||||
/*
|
||||
* If buck 1, 2, and 5 do not care DVS GPIO settings, ignore them.
|
||||
* If at least one of them cares, set gpios.
|
||||
@ -1068,19 +1227,6 @@ static __devinit int max8997_pmic_probe(struct platform_device *pdev)
|
||||
max8997_update_reg(i2c, MAX8997_REG_BUCK5CTRL, (pdata->buck5_gpiodvs) ?
|
||||
(1 << 1) : (0 << 1), 1 << 1);
|
||||
|
||||
/* Initialize all the DVS related BUCK registers */
|
||||
for (i = 0; i < 8; i++) {
|
||||
max8997_update_reg(i2c, MAX8997_REG_BUCK1DVS1 + i,
|
||||
max8997->buck1_vol[i],
|
||||
0x3f);
|
||||
max8997_update_reg(i2c, MAX8997_REG_BUCK2DVS1 + i,
|
||||
max8997->buck2_vol[i],
|
||||
0x3f);
|
||||
max8997_update_reg(i2c, MAX8997_REG_BUCK5DVS1 + i,
|
||||
max8997->buck5_vol[i],
|
||||
0x3f);
|
||||
}
|
||||
|
||||
/* Misc Settings */
|
||||
max8997->ramp_delay = 10; /* set 10mV/us, which is the default */
|
||||
max8997_write_reg(i2c, MAX8997_REG_BUCKRAMP, (0xf << 4) | 0x9);
|
||||
@ -1101,6 +1247,7 @@ static __devinit int max8997_pmic_probe(struct platform_device *pdev)
|
||||
config.dev = max8997->dev;
|
||||
config.init_data = pdata->regulators[i].initdata;
|
||||
config.driver_data = max8997;
|
||||
config.of_node = pdata->regulators[i].reg_node;
|
||||
|
||||
rdev[i] = regulator_register(®ulators[id], &config);
|
||||
if (IS_ERR(rdev[i])) {
|
||||
@ -1120,7 +1267,7 @@ err_out:
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int __devexit max8997_pmic_remove(struct platform_device *pdev)
|
||||
static int max8997_pmic_remove(struct platform_device *pdev)
|
||||
{
|
||||
struct max8997_data *max8997 = platform_get_drvdata(pdev);
|
||||
struct regulator_dev **rdev = max8997->rdev;
|
||||
@ -1143,7 +1290,7 @@ static struct platform_driver max8997_pmic_driver = {
|
||||
.owner = THIS_MODULE,
|
||||
},
|
||||
.probe = max8997_pmic_probe,
|
||||
.remove = __devexit_p(max8997_pmic_remove),
|
||||
.remove = max8997_pmic_remove,
|
||||
.id_table = max8997_pmic_id,
|
||||
};
|
||||
|
||||
|
@ -633,7 +633,7 @@ static struct regulator_desc regulators[] = {
|
||||
}
|
||||
};
|
||||
|
||||
static __devinit int max8998_pmic_probe(struct platform_device *pdev)
|
||||
static int max8998_pmic_probe(struct platform_device *pdev)
|
||||
{
|
||||
struct max8998_dev *iodev = dev_get_drvdata(pdev->dev.parent);
|
||||
struct max8998_platform_data *pdata = dev_get_platdata(iodev->dev);
|
||||
@ -818,7 +818,7 @@ err_out:
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int __devexit max8998_pmic_remove(struct platform_device *pdev)
|
||||
static int max8998_pmic_remove(struct platform_device *pdev)
|
||||
{
|
||||
struct max8998_data *max8998 = platform_get_drvdata(pdev);
|
||||
struct regulator_dev **rdev = max8998->rdev;
|
||||
@ -842,7 +842,7 @@ static struct platform_driver max8998_pmic_driver = {
|
||||
.owner = THIS_MODULE,
|
||||
},
|
||||
.probe = max8998_pmic_probe,
|
||||
.remove = __devexit_p(max8998_pmic_remove),
|
||||
.remove = max8998_pmic_remove,
|
||||
.id_table = max8998_pmic_id,
|
||||
};
|
||||
|
||||
|
@ -392,7 +392,7 @@ static struct regulator_ops mc13783_gpo_regulator_ops = {
|
||||
.set_voltage = mc13xxx_fixed_regulator_set_voltage,
|
||||
};
|
||||
|
||||
static int __devinit mc13783_regulator_probe(struct platform_device *pdev)
|
||||
static int mc13783_regulator_probe(struct platform_device *pdev)
|
||||
{
|
||||
struct mc13xxx_regulator_priv *priv;
|
||||
struct mc13xxx *mc13783 = dev_get_drvdata(pdev->dev.parent);
|
||||
@ -445,7 +445,7 @@ err:
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int __devexit mc13783_regulator_remove(struct platform_device *pdev)
|
||||
static int mc13783_regulator_remove(struct platform_device *pdev)
|
||||
{
|
||||
struct mc13xxx_regulator_priv *priv = platform_get_drvdata(pdev);
|
||||
struct mc13xxx_regulator_platform_data *pdata =
|
||||
@ -465,7 +465,7 @@ static struct platform_driver mc13783_regulator_driver = {
|
||||
.name = "mc13783-regulator",
|
||||
.owner = THIS_MODULE,
|
||||
},
|
||||
.remove = __devexit_p(mc13783_regulator_remove),
|
||||
.remove = mc13783_regulator_remove,
|
||||
.probe = mc13783_regulator_probe,
|
||||
};
|
||||
|
||||
|
@ -486,7 +486,7 @@ static unsigned int mc13892_vcam_get_mode(struct regulator_dev *rdev)
|
||||
}
|
||||
|
||||
|
||||
static int __devinit mc13892_regulator_probe(struct platform_device *pdev)
|
||||
static int mc13892_regulator_probe(struct platform_device *pdev)
|
||||
{
|
||||
struct mc13xxx_regulator_priv *priv;
|
||||
struct mc13xxx *mc13892 = dev_get_drvdata(pdev->dev.parent);
|
||||
@ -588,7 +588,7 @@ err_unlock:
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int __devexit mc13892_regulator_remove(struct platform_device *pdev)
|
||||
static int mc13892_regulator_remove(struct platform_device *pdev)
|
||||
{
|
||||
struct mc13xxx_regulator_priv *priv = platform_get_drvdata(pdev);
|
||||
int i;
|
||||
@ -606,7 +606,7 @@ static struct platform_driver mc13892_regulator_driver = {
|
||||
.name = "mc13892-regulator",
|
||||
.owner = THIS_MODULE,
|
||||
},
|
||||
.remove = __devexit_p(mc13892_regulator_remove),
|
||||
.remove = mc13892_regulator_remove,
|
||||
.probe = mc13892_regulator_probe,
|
||||
};
|
||||
|
||||
|
@ -162,7 +162,7 @@ struct regulator_ops mc13xxx_fixed_regulator_ops = {
|
||||
EXPORT_SYMBOL_GPL(mc13xxx_fixed_regulator_ops);
|
||||
|
||||
#ifdef CONFIG_OF
|
||||
int __devinit mc13xxx_get_num_regulators_dt(struct platform_device *pdev)
|
||||
int mc13xxx_get_num_regulators_dt(struct platform_device *pdev)
|
||||
{
|
||||
struct device_node *parent, *child;
|
||||
int num = 0;
|
||||
@ -179,7 +179,7 @@ int __devinit mc13xxx_get_num_regulators_dt(struct platform_device *pdev)
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(mc13xxx_get_num_regulators_dt);
|
||||
|
||||
struct mc13xxx_regulator_init_data * __devinit mc13xxx_parse_regulators_dt(
|
||||
struct mc13xxx_regulator_init_data *mc13xxx_parse_regulators_dt(
|
||||
struct platform_device *pdev, struct mc13xxx_regulator *regulators,
|
||||
int num_regulators)
|
||||
{
|
||||
|
@ -309,68 +309,22 @@ static int palmas_list_voltage_smps(struct regulator_dev *dev,
|
||||
int id = rdev_get_id(dev);
|
||||
int mult = 1;
|
||||
|
||||
if (!selector)
|
||||
return 0;
|
||||
|
||||
/* Read the multiplier set in VSEL register to return
|
||||
* the correct voltage.
|
||||
*/
|
||||
if (pmic->range[id])
|
||||
mult = 2;
|
||||
|
||||
/* Voltage is (0.49V + (selector * 0.01V)) * RANGE
|
||||
* as defined in data sheet. RANGE is either x1 or x2
|
||||
*/
|
||||
return (490000 + (selector * 10000)) * mult;
|
||||
}
|
||||
|
||||
static int palmas_get_voltage_smps_sel(struct regulator_dev *dev)
|
||||
{
|
||||
struct palmas_pmic *pmic = rdev_get_drvdata(dev);
|
||||
int id = rdev_get_id(dev);
|
||||
int selector;
|
||||
unsigned int reg;
|
||||
unsigned int addr;
|
||||
|
||||
addr = palmas_regs_info[id].vsel_addr;
|
||||
|
||||
palmas_smps_read(pmic->palmas, addr, ®);
|
||||
|
||||
selector = reg & PALMAS_SMPS12_VOLTAGE_VSEL_MASK;
|
||||
|
||||
/* Adjust selector to match list_voltage ranges */
|
||||
if ((selector > 0) && (selector < 6))
|
||||
selector = 6;
|
||||
if (!selector)
|
||||
selector = 5;
|
||||
if (selector > 121)
|
||||
selector = 121;
|
||||
selector -= 5;
|
||||
|
||||
return selector;
|
||||
}
|
||||
|
||||
static int palmas_set_voltage_smps_sel(struct regulator_dev *dev,
|
||||
unsigned selector)
|
||||
{
|
||||
struct palmas_pmic *pmic = rdev_get_drvdata(dev);
|
||||
int id = rdev_get_id(dev);
|
||||
unsigned int reg = 0;
|
||||
unsigned int addr;
|
||||
|
||||
addr = palmas_regs_info[id].vsel_addr;
|
||||
|
||||
/* Make sure we don't change the value of RANGE */
|
||||
if (pmic->range[id])
|
||||
reg |= PALMAS_SMPS12_VOLTAGE_RANGE;
|
||||
|
||||
/* Adjust the linux selector into range used in VSEL register */
|
||||
if (selector)
|
||||
reg |= selector + 5;
|
||||
|
||||
palmas_smps_write(pmic->palmas, addr, reg);
|
||||
|
||||
return 0;
|
||||
if (selector == 0)
|
||||
return 0;
|
||||
else if (selector < 6)
|
||||
return 500000 * mult;
|
||||
else
|
||||
/* Voltage is linear mapping starting from selector 6,
|
||||
* volt = (0.49V + ((selector - 5) * 0.01V)) * RANGE
|
||||
* RANGE is either x1 or x2
|
||||
*/
|
||||
return (490000 + ((selector - 5) * 10000)) * mult;
|
||||
}
|
||||
|
||||
static int palmas_map_voltage_smps(struct regulator_dev *rdev,
|
||||
@ -386,11 +340,11 @@ static int palmas_map_voltage_smps(struct regulator_dev *rdev,
|
||||
if (pmic->range[id]) { /* RANGE is x2 */
|
||||
if (min_uV < 1000000)
|
||||
min_uV = 1000000;
|
||||
ret = DIV_ROUND_UP(min_uV - 1000000, 20000) + 1;
|
||||
ret = DIV_ROUND_UP(min_uV - 1000000, 20000) + 6;
|
||||
} else { /* RANGE is x1 */
|
||||
if (min_uV < 500000)
|
||||
min_uV = 500000;
|
||||
ret = DIV_ROUND_UP(min_uV - 500000, 10000) + 1;
|
||||
ret = DIV_ROUND_UP(min_uV - 500000, 10000) + 6;
|
||||
}
|
||||
|
||||
/* Map back into a voltage to verify we're still in bounds */
|
||||
@ -407,8 +361,8 @@ static struct regulator_ops palmas_ops_smps = {
|
||||
.disable = palmas_disable_smps,
|
||||
.set_mode = palmas_set_mode_smps,
|
||||
.get_mode = palmas_get_mode_smps,
|
||||
.get_voltage_sel = palmas_get_voltage_smps_sel,
|
||||
.set_voltage_sel = palmas_set_voltage_smps_sel,
|
||||
.get_voltage_sel = regulator_get_voltage_sel_regmap,
|
||||
.set_voltage_sel = regulator_set_voltage_sel_regmap,
|
||||
.list_voltage = palmas_list_voltage_smps,
|
||||
.map_voltage = palmas_map_voltage_smps,
|
||||
};
|
||||
@ -436,44 +390,14 @@ static int palmas_is_enabled_ldo(struct regulator_dev *dev)
|
||||
return !!(reg);
|
||||
}
|
||||
|
||||
static int palmas_list_voltage_ldo(struct regulator_dev *dev,
|
||||
unsigned selector)
|
||||
{
|
||||
if (!selector)
|
||||
return 0;
|
||||
|
||||
/* voltage is 0.85V + (selector * 0.05v) */
|
||||
return 850000 + (selector * 50000);
|
||||
}
|
||||
|
||||
static int palmas_map_voltage_ldo(struct regulator_dev *rdev,
|
||||
int min_uV, int max_uV)
|
||||
{
|
||||
int ret, voltage;
|
||||
|
||||
if (min_uV == 0)
|
||||
return 0;
|
||||
|
||||
if (min_uV < 900000)
|
||||
min_uV = 900000;
|
||||
ret = DIV_ROUND_UP(min_uV - 900000, 50000) + 1;
|
||||
|
||||
/* Map back into a voltage to verify we're still in bounds */
|
||||
voltage = palmas_list_voltage_ldo(rdev, ret);
|
||||
if (voltage < min_uV || voltage > max_uV)
|
||||
return -EINVAL;
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static struct regulator_ops palmas_ops_ldo = {
|
||||
.is_enabled = palmas_is_enabled_ldo,
|
||||
.enable = regulator_enable_regmap,
|
||||
.disable = regulator_disable_regmap,
|
||||
.get_voltage_sel = regulator_get_voltage_sel_regmap,
|
||||
.set_voltage_sel = regulator_set_voltage_sel_regmap,
|
||||
.list_voltage = palmas_list_voltage_ldo,
|
||||
.map_voltage = palmas_map_voltage_ldo,
|
||||
.list_voltage = regulator_list_voltage_linear,
|
||||
.map_voltage = regulator_map_voltage_linear,
|
||||
};
|
||||
|
||||
/*
|
||||
@ -595,7 +519,7 @@ static struct of_regulator_match palmas_matches[] = {
|
||||
{ .name = "ldousb", },
|
||||
};
|
||||
|
||||
static void __devinit palmas_dt_to_pdata(struct device *dev,
|
||||
static void palmas_dt_to_pdata(struct device *dev,
|
||||
struct device_node *node,
|
||||
struct palmas_pmic_platform_data *pdata)
|
||||
{
|
||||
@ -663,7 +587,7 @@ static void __devinit palmas_dt_to_pdata(struct device *dev,
|
||||
}
|
||||
|
||||
|
||||
static __devinit int palmas_probe(struct platform_device *pdev)
|
||||
static int palmas_probe(struct platform_device *pdev)
|
||||
{
|
||||
struct palmas *palmas = dev_get_drvdata(pdev->dev.parent);
|
||||
struct palmas_pmic_platform_data *pdata = pdev->dev.platform_data;
|
||||
@ -733,6 +657,14 @@ static __devinit int palmas_probe(struct platform_device *pdev)
|
||||
continue;
|
||||
}
|
||||
|
||||
/* Initialise sleep/init values from platform data */
|
||||
if (pdata && pdata->reg_init[id]) {
|
||||
reg_init = pdata->reg_init[id];
|
||||
ret = palmas_smps_init(palmas, id, reg_init);
|
||||
if (ret)
|
||||
goto err_unregister_regulator;
|
||||
}
|
||||
|
||||
/* Register the regulators */
|
||||
pmic->desc[id].name = palmas_regs_info[id].name;
|
||||
pmic->desc[id].id = id;
|
||||
@ -753,29 +685,11 @@ static __devinit int palmas_probe(struct platform_device *pdev)
|
||||
pmic->desc[id].uV_step = 1250000;
|
||||
break;
|
||||
default:
|
||||
pmic->desc[id].ops = &palmas_ops_smps;
|
||||
pmic->desc[id].n_voltages = PALMAS_SMPS_NUM_VOLTAGES;
|
||||
}
|
||||
|
||||
pmic->desc[id].type = REGULATOR_VOLTAGE;
|
||||
pmic->desc[id].owner = THIS_MODULE;
|
||||
|
||||
/* Initialise sleep/init values from platform data */
|
||||
if (pdata) {
|
||||
reg_init = pdata->reg_init[id];
|
||||
if (reg_init) {
|
||||
ret = palmas_smps_init(palmas, id, reg_init);
|
||||
if (ret)
|
||||
goto err_unregister_regulator;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* read and store the RANGE bit for later use
|
||||
* This must be done before regulator is probed otherwise
|
||||
* we error in probe with unsupportable ranges.
|
||||
*/
|
||||
if (id != PALMAS_REG_SMPS10) {
|
||||
/*
|
||||
* Read and store the RANGE bit for later use
|
||||
* This must be done before regulator is probed,
|
||||
* otherwise we error in probe with unsupportable ranges.
|
||||
*/
|
||||
addr = palmas_regs_info[id].vsel_addr;
|
||||
|
||||
ret = palmas_smps_read(pmic->palmas, addr, ®);
|
||||
@ -783,8 +697,19 @@ static __devinit int palmas_probe(struct platform_device *pdev)
|
||||
goto err_unregister_regulator;
|
||||
if (reg & PALMAS_SMPS12_VOLTAGE_RANGE)
|
||||
pmic->range[id] = 1;
|
||||
|
||||
pmic->desc[id].ops = &palmas_ops_smps;
|
||||
pmic->desc[id].n_voltages = PALMAS_SMPS_NUM_VOLTAGES;
|
||||
pmic->desc[id].vsel_reg =
|
||||
PALMAS_BASE_TO_REG(PALMAS_SMPS_BASE,
|
||||
palmas_regs_info[id].vsel_addr);
|
||||
pmic->desc[id].vsel_mask =
|
||||
PALMAS_SMPS12_VOLTAGE_VSEL_MASK;
|
||||
}
|
||||
|
||||
pmic->desc[id].type = REGULATOR_VOLTAGE;
|
||||
pmic->desc[id].owner = THIS_MODULE;
|
||||
|
||||
if (pdata)
|
||||
config.init_data = pdata->reg_data[id];
|
||||
else
|
||||
@ -821,6 +746,9 @@ static __devinit int palmas_probe(struct platform_device *pdev)
|
||||
|
||||
pmic->desc[id].type = REGULATOR_VOLTAGE;
|
||||
pmic->desc[id].owner = THIS_MODULE;
|
||||
pmic->desc[id].min_uV = 900000;
|
||||
pmic->desc[id].uV_step = 50000;
|
||||
pmic->desc[id].linear_min_sel = 1;
|
||||
pmic->desc[id].vsel_reg = PALMAS_BASE_TO_REG(PALMAS_LDO_BASE,
|
||||
palmas_regs_info[id].vsel_addr);
|
||||
pmic->desc[id].vsel_mask = PALMAS_LDO1_VOLTAGE_VSEL_MASK;
|
||||
@ -868,7 +796,7 @@ err_unregister_regulator:
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int __devexit palmas_remove(struct platform_device *pdev)
|
||||
static int palmas_remove(struct platform_device *pdev)
|
||||
{
|
||||
struct palmas_pmic *pmic = platform_get_drvdata(pdev);
|
||||
int id;
|
||||
@ -890,7 +818,7 @@ static struct platform_driver palmas_driver = {
|
||||
.owner = THIS_MODULE,
|
||||
},
|
||||
.probe = palmas_probe,
|
||||
.remove = __devexit_p(palmas_remove),
|
||||
.remove = palmas_remove,
|
||||
};
|
||||
|
||||
static int __init palmas_init(void)
|
||||
|
@ -236,7 +236,7 @@ static const struct regulator_desc pcap_regulators[] = {
|
||||
VREG(VAUX4), VREG(VSIM), VREG(VSIM2), VREG(VVIB), VREG(SW1), VREG(SW2),
|
||||
};
|
||||
|
||||
static int __devinit pcap_regulator_probe(struct platform_device *pdev)
|
||||
static int pcap_regulator_probe(struct platform_device *pdev)
|
||||
{
|
||||
struct regulator_dev *rdev;
|
||||
void *pcap = dev_get_drvdata(pdev->dev.parent);
|
||||
@ -255,7 +255,7 @@ static int __devinit pcap_regulator_probe(struct platform_device *pdev)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int __devexit pcap_regulator_remove(struct platform_device *pdev)
|
||||
static int pcap_regulator_remove(struct platform_device *pdev)
|
||||
{
|
||||
struct regulator_dev *rdev = platform_get_drvdata(pdev);
|
||||
|
||||
@ -271,7 +271,7 @@ static struct platform_driver pcap_regulator_driver = {
|
||||
.owner = THIS_MODULE,
|
||||
},
|
||||
.probe = pcap_regulator_probe,
|
||||
.remove = __devexit_p(pcap_regulator_remove),
|
||||
.remove = pcap_regulator_remove,
|
||||
};
|
||||
|
||||
static int __init pcap_regulator_init(void)
|
||||
|
@ -24,12 +24,15 @@
|
||||
#include <linux/mfd/pcf50633/core.h>
|
||||
#include <linux/mfd/pcf50633/pmic.h>
|
||||
|
||||
#define PCF50633_REGULATOR(_name, _id, _n) \
|
||||
#define PCF50633_REGULATOR(_name, _id, _min_uV, _uV_step, _min_sel, _n) \
|
||||
{ \
|
||||
.name = _name, \
|
||||
.id = PCF50633_REGULATOR_##_id, \
|
||||
.ops = &pcf50633_regulator_ops, \
|
||||
.n_voltages = _n, \
|
||||
.min_uV = _min_uV, \
|
||||
.uV_step = _uV_step, \
|
||||
.linear_min_sel = _min_sel, \
|
||||
.type = REGULATOR_VOLTAGE, \
|
||||
.owner = THIS_MODULE, \
|
||||
.vsel_reg = PCF50633_REG_##_id##OUT, \
|
||||
@ -38,165 +41,42 @@
|
||||
.enable_mask = PCF50633_REGULATOR_ON, \
|
||||
}
|
||||
|
||||
/* Bits from voltage value */
|
||||
static u8 auto_voltage_bits(unsigned int millivolts)
|
||||
{
|
||||
if (millivolts < 1800)
|
||||
return 0x2f;
|
||||
if (millivolts > 3800)
|
||||
return 0xff;
|
||||
|
||||
millivolts -= 625;
|
||||
|
||||
return millivolts / 25;
|
||||
}
|
||||
|
||||
static u8 down_voltage_bits(unsigned int millivolts)
|
||||
{
|
||||
if (millivolts < 625)
|
||||
return 0;
|
||||
else if (millivolts > 3000)
|
||||
return 0xff;
|
||||
|
||||
millivolts -= 625;
|
||||
|
||||
return millivolts / 25;
|
||||
}
|
||||
|
||||
static u8 ldo_voltage_bits(unsigned int millivolts)
|
||||
{
|
||||
if (millivolts < 900)
|
||||
return 0;
|
||||
else if (millivolts > 3600)
|
||||
return 0x1f;
|
||||
|
||||
millivolts -= 900;
|
||||
return millivolts / 100;
|
||||
}
|
||||
|
||||
/* Obtain voltage value from bits */
|
||||
static unsigned int auto_voltage_value(u8 bits)
|
||||
{
|
||||
/* AUTOOUT: 00000000 to 00101110 are reserved.
|
||||
* Return 0 for bits in reserved range, which means this selector code
|
||||
* can't be used on this system */
|
||||
if (bits < 0x2f)
|
||||
return 0;
|
||||
|
||||
return 625 + (bits * 25);
|
||||
}
|
||||
|
||||
|
||||
static unsigned int down_voltage_value(u8 bits)
|
||||
{
|
||||
return 625 + (bits * 25);
|
||||
}
|
||||
|
||||
|
||||
static unsigned int ldo_voltage_value(u8 bits)
|
||||
{
|
||||
bits &= 0x1f;
|
||||
|
||||
return 900 + (bits * 100);
|
||||
}
|
||||
|
||||
static int pcf50633_regulator_map_voltage(struct regulator_dev *rdev,
|
||||
int min_uV, int max_uV)
|
||||
{
|
||||
struct pcf50633 *pcf;
|
||||
int regulator_id, millivolts;
|
||||
u8 volt_bits;
|
||||
|
||||
pcf = rdev_get_drvdata(rdev);
|
||||
|
||||
regulator_id = rdev_get_id(rdev);
|
||||
if (regulator_id >= PCF50633_NUM_REGULATORS)
|
||||
return -EINVAL;
|
||||
|
||||
millivolts = min_uV / 1000;
|
||||
|
||||
switch (regulator_id) {
|
||||
case PCF50633_REGULATOR_AUTO:
|
||||
volt_bits = auto_voltage_bits(millivolts);
|
||||
break;
|
||||
case PCF50633_REGULATOR_DOWN1:
|
||||
case PCF50633_REGULATOR_DOWN2:
|
||||
volt_bits = down_voltage_bits(millivolts);
|
||||
break;
|
||||
case PCF50633_REGULATOR_LDO1:
|
||||
case PCF50633_REGULATOR_LDO2:
|
||||
case PCF50633_REGULATOR_LDO3:
|
||||
case PCF50633_REGULATOR_LDO4:
|
||||
case PCF50633_REGULATOR_LDO5:
|
||||
case PCF50633_REGULATOR_LDO6:
|
||||
case PCF50633_REGULATOR_HCLDO:
|
||||
case PCF50633_REGULATOR_MEMLDO:
|
||||
volt_bits = ldo_voltage_bits(millivolts);
|
||||
break;
|
||||
default:
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
return volt_bits;
|
||||
}
|
||||
|
||||
static int pcf50633_regulator_list_voltage(struct regulator_dev *rdev,
|
||||
unsigned int index)
|
||||
{
|
||||
int regulator_id = rdev_get_id(rdev);
|
||||
|
||||
int millivolts;
|
||||
|
||||
switch (regulator_id) {
|
||||
case PCF50633_REGULATOR_AUTO:
|
||||
millivolts = auto_voltage_value(index);
|
||||
break;
|
||||
case PCF50633_REGULATOR_DOWN1:
|
||||
case PCF50633_REGULATOR_DOWN2:
|
||||
millivolts = down_voltage_value(index);
|
||||
break;
|
||||
case PCF50633_REGULATOR_LDO1:
|
||||
case PCF50633_REGULATOR_LDO2:
|
||||
case PCF50633_REGULATOR_LDO3:
|
||||
case PCF50633_REGULATOR_LDO4:
|
||||
case PCF50633_REGULATOR_LDO5:
|
||||
case PCF50633_REGULATOR_LDO6:
|
||||
case PCF50633_REGULATOR_HCLDO:
|
||||
case PCF50633_REGULATOR_MEMLDO:
|
||||
millivolts = ldo_voltage_value(index);
|
||||
break;
|
||||
default:
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
return millivolts * 1000;
|
||||
}
|
||||
|
||||
static struct regulator_ops pcf50633_regulator_ops = {
|
||||
.set_voltage_sel = regulator_set_voltage_sel_regmap,
|
||||
.get_voltage_sel = regulator_get_voltage_sel_regmap,
|
||||
.list_voltage = pcf50633_regulator_list_voltage,
|
||||
.map_voltage = pcf50633_regulator_map_voltage,
|
||||
.list_voltage = regulator_list_voltage_linear,
|
||||
.map_voltage = regulator_map_voltage_linear,
|
||||
.enable = regulator_enable_regmap,
|
||||
.disable = regulator_disable_regmap,
|
||||
.is_enabled = regulator_is_enabled_regmap,
|
||||
};
|
||||
|
||||
static const struct regulator_desc regulators[] = {
|
||||
[PCF50633_REGULATOR_AUTO] = PCF50633_REGULATOR("auto", AUTO, 128),
|
||||
[PCF50633_REGULATOR_DOWN1] = PCF50633_REGULATOR("down1", DOWN1, 96),
|
||||
[PCF50633_REGULATOR_DOWN2] = PCF50633_REGULATOR("down2", DOWN2, 96),
|
||||
[PCF50633_REGULATOR_LDO1] = PCF50633_REGULATOR("ldo1", LDO1, 28),
|
||||
[PCF50633_REGULATOR_LDO2] = PCF50633_REGULATOR("ldo2", LDO2, 28),
|
||||
[PCF50633_REGULATOR_LDO3] = PCF50633_REGULATOR("ldo3", LDO3, 28),
|
||||
[PCF50633_REGULATOR_LDO4] = PCF50633_REGULATOR("ldo4", LDO4, 28),
|
||||
[PCF50633_REGULATOR_LDO5] = PCF50633_REGULATOR("ldo5", LDO5, 28),
|
||||
[PCF50633_REGULATOR_LDO6] = PCF50633_REGULATOR("ldo6", LDO6, 28),
|
||||
[PCF50633_REGULATOR_HCLDO] = PCF50633_REGULATOR("hcldo", HCLDO, 28),
|
||||
[PCF50633_REGULATOR_MEMLDO] = PCF50633_REGULATOR("memldo", MEMLDO, 28),
|
||||
[PCF50633_REGULATOR_AUTO] =
|
||||
PCF50633_REGULATOR("auto", AUTO, 1800000, 25000, 0x2f, 128),
|
||||
[PCF50633_REGULATOR_DOWN1] =
|
||||
PCF50633_REGULATOR("down1", DOWN1, 625000, 25000, 0, 96),
|
||||
[PCF50633_REGULATOR_DOWN2] =
|
||||
PCF50633_REGULATOR("down2", DOWN2, 625000, 25000, 0, 96),
|
||||
[PCF50633_REGULATOR_LDO1] =
|
||||
PCF50633_REGULATOR("ldo1", LDO1, 900000, 100000, 0, 28),
|
||||
[PCF50633_REGULATOR_LDO2] =
|
||||
PCF50633_REGULATOR("ldo2", LDO2, 900000, 100000, 0, 28),
|
||||
[PCF50633_REGULATOR_LDO3] =
|
||||
PCF50633_REGULATOR("ldo3", LDO3, 900000, 100000, 0, 28),
|
||||
[PCF50633_REGULATOR_LDO4] =
|
||||
PCF50633_REGULATOR("ldo4", LDO4, 900000, 100000, 0, 28),
|
||||
[PCF50633_REGULATOR_LDO5] =
|
||||
PCF50633_REGULATOR("ldo5", LDO5, 900000, 100000, 0, 28),
|
||||
[PCF50633_REGULATOR_LDO6] =
|
||||
PCF50633_REGULATOR("ldo6", LDO6, 900000, 100000, 0, 28),
|
||||
[PCF50633_REGULATOR_HCLDO] =
|
||||
PCF50633_REGULATOR("hcldo", HCLDO, 900000, 100000, 0, 28),
|
||||
[PCF50633_REGULATOR_MEMLDO] =
|
||||
PCF50633_REGULATOR("memldo", MEMLDO, 900000, 100000, 0, 28),
|
||||
};
|
||||
|
||||
static int __devinit pcf50633_regulator_probe(struct platform_device *pdev)
|
||||
static int pcf50633_regulator_probe(struct platform_device *pdev)
|
||||
{
|
||||
struct regulator_dev *rdev;
|
||||
struct pcf50633 *pcf;
|
||||
@ -222,7 +102,7 @@ static int __devinit pcf50633_regulator_probe(struct platform_device *pdev)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int __devexit pcf50633_regulator_remove(struct platform_device *pdev)
|
||||
static int pcf50633_regulator_remove(struct platform_device *pdev)
|
||||
{
|
||||
struct regulator_dev *rdev = platform_get_drvdata(pdev);
|
||||
|
||||
@ -237,7 +117,7 @@ static struct platform_driver pcf50633_regulator_driver = {
|
||||
.name = "pcf50633-regltr",
|
||||
},
|
||||
.probe = pcf50633_regulator_probe,
|
||||
.remove = __devexit_p(pcf50633_regulator_remove),
|
||||
.remove = pcf50633_regulator_remove,
|
||||
};
|
||||
|
||||
static int __init pcf50633_regulator_init(void)
|
||||
|
@ -119,7 +119,7 @@ static struct rc5t583_regulator_info rc5t583_reg_info[RC5T583_REGULATOR_MAX] = {
|
||||
RC5T583_REG(LDO9, LDOEN1, 1, LDODIS1, 1, 0x7F, 900, 3400, 25000, 133),
|
||||
};
|
||||
|
||||
static int __devinit rc5t583_regulator_probe(struct platform_device *pdev)
|
||||
static int rc5t583_regulator_probe(struct platform_device *pdev)
|
||||
{
|
||||
struct rc5t583 *rc5t583 = dev_get_drvdata(pdev->dev.parent);
|
||||
struct rc5t583_platform_data *pdata = dev_get_platdata(rc5t583->dev);
|
||||
@ -198,7 +198,7 @@ clean_exit:
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int __devexit rc5t583_regulator_remove(struct platform_device *pdev)
|
||||
static int rc5t583_regulator_remove(struct platform_device *pdev)
|
||||
{
|
||||
struct rc5t583_regulator *regs = platform_get_drvdata(pdev);
|
||||
int id;
|
||||
@ -214,7 +214,7 @@ static struct platform_driver rc5t583_regulator_driver = {
|
||||
.owner = THIS_MODULE,
|
||||
},
|
||||
.probe = rc5t583_regulator_probe,
|
||||
.remove = __devexit_p(rc5t583_regulator_remove),
|
||||
.remove = rc5t583_regulator_remove,
|
||||
};
|
||||
|
||||
static int __init rc5t583_regulator_init(void)
|
||||
|
@ -231,7 +231,7 @@ static struct regulator_desc regulators[] = {
|
||||
regulator_desc_buck10,
|
||||
};
|
||||
|
||||
static __devinit int s2mps11_pmic_probe(struct platform_device *pdev)
|
||||
static int s2mps11_pmic_probe(struct platform_device *pdev)
|
||||
{
|
||||
struct sec_pmic_dev *iodev = dev_get_drvdata(pdev->dev.parent);
|
||||
struct sec_platform_data *pdata = dev_get_platdata(iodev->dev);
|
||||
@ -269,16 +269,16 @@ static __devinit int s2mps11_pmic_probe(struct platform_device *pdev)
|
||||
|
||||
if (ramp_enable) {
|
||||
if (s2mps11->buck2_ramp)
|
||||
ramp_reg |= get_ramp_delay(s2mps11->ramp_delay2) >> 6;
|
||||
ramp_reg |= get_ramp_delay(s2mps11->ramp_delay2) << 6;
|
||||
if (s2mps11->buck3_ramp || s2mps11->buck4_ramp)
|
||||
ramp_reg |= get_ramp_delay(s2mps11->ramp_delay34) >> 4;
|
||||
ramp_reg |= get_ramp_delay(s2mps11->ramp_delay34) << 4;
|
||||
sec_reg_write(iodev, S2MPS11_REG_RAMP, ramp_reg | ramp_enable);
|
||||
}
|
||||
|
||||
ramp_reg &= 0x00;
|
||||
ramp_reg |= get_ramp_delay(s2mps11->ramp_delay5) >> 6;
|
||||
ramp_reg |= get_ramp_delay(s2mps11->ramp_delay16) >> 4;
|
||||
ramp_reg |= get_ramp_delay(s2mps11->ramp_delay7810) >> 2;
|
||||
ramp_reg |= get_ramp_delay(s2mps11->ramp_delay5) << 6;
|
||||
ramp_reg |= get_ramp_delay(s2mps11->ramp_delay16) << 4;
|
||||
ramp_reg |= get_ramp_delay(s2mps11->ramp_delay7810) << 2;
|
||||
ramp_reg |= get_ramp_delay(s2mps11->ramp_delay9);
|
||||
sec_reg_write(iodev, S2MPS11_REG_RAMP_BUCK, ramp_reg);
|
||||
|
||||
@ -307,7 +307,7 @@ err:
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int __devexit s2mps11_pmic_remove(struct platform_device *pdev)
|
||||
static int s2mps11_pmic_remove(struct platform_device *pdev)
|
||||
{
|
||||
struct s2mps11_info *s2mps11 = platform_get_drvdata(pdev);
|
||||
int i;
|
||||
@ -330,7 +330,7 @@ static struct platform_driver s2mps11_pmic_driver = {
|
||||
.owner = THIS_MODULE,
|
||||
},
|
||||
.probe = s2mps11_pmic_probe,
|
||||
.remove = __devexit_p(s2mps11_pmic_remove),
|
||||
.remove = s2mps11_pmic_remove,
|
||||
.id_table = s2mps11_pmic_id,
|
||||
};
|
||||
|
||||
|
@ -168,7 +168,7 @@ static unsigned int s5m8767_opmode_reg[][4] = {
|
||||
static int s5m8767_get_register(struct regulator_dev *rdev, int *reg,
|
||||
int *enable_ctrl)
|
||||
{
|
||||
int reg_id = rdev_get_id(rdev);
|
||||
int i, reg_id = rdev_get_id(rdev);
|
||||
unsigned int mode;
|
||||
struct s5m8767_info *s5m8767 = rdev_get_drvdata(rdev);
|
||||
|
||||
@ -195,8 +195,17 @@ static int s5m8767_get_register(struct regulator_dev *rdev, int *reg,
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
mode = s5m8767->opmode[reg_id].mode;
|
||||
*enable_ctrl = s5m8767_opmode_reg[reg_id][mode] << S5M8767_ENCTRL_SHIFT;
|
||||
for (i = 0; i < s5m8767->num_regulators; i++) {
|
||||
if (s5m8767->opmode[i].id == reg_id) {
|
||||
mode = s5m8767->opmode[i].mode;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (i < s5m8767->num_regulators)
|
||||
*enable_ctrl =
|
||||
s5m8767_opmode_reg[reg_id][mode] << S5M8767_ENCTRL_SHIFT;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -263,17 +272,17 @@ static int s5m8767_get_voltage_register(struct regulator_dev *rdev, int *_reg)
|
||||
reg = S5M8767_REG_BUCK1CTRL2;
|
||||
break;
|
||||
case S5M8767_BUCK2:
|
||||
reg = S5M8767_REG_BUCK2DVS2;
|
||||
reg = S5M8767_REG_BUCK2DVS1;
|
||||
if (s5m8767->buck2_gpiodvs)
|
||||
reg += s5m8767->buck_gpioindex;
|
||||
break;
|
||||
case S5M8767_BUCK3:
|
||||
reg = S5M8767_REG_BUCK3DVS2;
|
||||
reg = S5M8767_REG_BUCK3DVS1;
|
||||
if (s5m8767->buck3_gpiodvs)
|
||||
reg += s5m8767->buck_gpioindex;
|
||||
break;
|
||||
case S5M8767_BUCK4:
|
||||
reg = S5M8767_REG_BUCK4DVS2;
|
||||
reg = S5M8767_REG_BUCK4DVS1;
|
||||
if (s5m8767->buck4_gpiodvs)
|
||||
reg += s5m8767->buck_gpioindex;
|
||||
break;
|
||||
@ -499,7 +508,7 @@ static struct regulator_desc regulators[] = {
|
||||
s5m8767_regulator_desc(BUCK9),
|
||||
};
|
||||
|
||||
static __devinit int s5m8767_pmic_probe(struct platform_device *pdev)
|
||||
static int s5m8767_pmic_probe(struct platform_device *pdev)
|
||||
{
|
||||
struct sec_pmic_dev *iodev = dev_get_drvdata(pdev->dev.parent);
|
||||
struct sec_platform_data *pdata = dev_get_platdata(iodev->dev);
|
||||
@ -547,7 +556,7 @@ static __devinit int s5m8767_pmic_probe(struct platform_device *pdev)
|
||||
rdev = s5m8767->rdev;
|
||||
s5m8767->dev = &pdev->dev;
|
||||
s5m8767->iodev = iodev;
|
||||
s5m8767->num_regulators = S5M8767_REG_MAX - 2;
|
||||
s5m8767->num_regulators = pdata->num_regulators;
|
||||
platform_set_drvdata(pdev, s5m8767);
|
||||
|
||||
s5m8767->buck_gpioindex = pdata->buck_default_idx;
|
||||
@ -617,9 +626,16 @@ static __devinit int s5m8767_pmic_probe(struct platform_device *pdev)
|
||||
}
|
||||
}
|
||||
|
||||
if (gpio_is_valid(pdata->buck_gpios[0]) &&
|
||||
gpio_is_valid(pdata->buck_gpios[1]) &&
|
||||
gpio_is_valid(pdata->buck_gpios[2])) {
|
||||
if (pdata->buck2_gpiodvs || pdata->buck3_gpiodvs ||
|
||||
pdata->buck4_gpiodvs) {
|
||||
|
||||
if (!gpio_is_valid(pdata->buck_gpios[0]) ||
|
||||
!gpio_is_valid(pdata->buck_gpios[1]) ||
|
||||
!gpio_is_valid(pdata->buck_gpios[2])) {
|
||||
dev_err(&pdev->dev, "GPIO NOT VALID\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
ret = devm_gpio_request(&pdev->dev, pdata->buck_gpios[0],
|
||||
"S5M8767 SET1");
|
||||
if (ret)
|
||||
@ -644,10 +660,6 @@ static __devinit int s5m8767_pmic_probe(struct platform_device *pdev)
|
||||
/* SET3 GPIO */
|
||||
gpio_direction_output(pdata->buck_gpios[2],
|
||||
(s5m8767->buck_gpioindex >> 0) & 0x1);
|
||||
} else {
|
||||
dev_err(&pdev->dev, "GPIO NOT VALID\n");
|
||||
ret = -EINVAL;
|
||||
return ret;
|
||||
}
|
||||
|
||||
ret = devm_gpio_request(&pdev->dev, pdata->buck_ds[0], "S5M8767 DS2");
|
||||
@ -773,7 +785,7 @@ err:
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int __devexit s5m8767_pmic_remove(struct platform_device *pdev)
|
||||
static int s5m8767_pmic_remove(struct platform_device *pdev)
|
||||
{
|
||||
struct s5m8767_info *s5m8767 = platform_get_drvdata(pdev);
|
||||
struct regulator_dev **rdev = s5m8767->rdev;
|
||||
@ -798,7 +810,7 @@ static struct platform_driver s5m8767_pmic_driver = {
|
||||
.owner = THIS_MODULE,
|
||||
},
|
||||
.probe = s5m8767_pmic_probe,
|
||||
.remove = __devexit_p(s5m8767_pmic_remove),
|
||||
.remove = s5m8767_pmic_remove,
|
||||
.id_table = s5m8767_pmic_id,
|
||||
};
|
||||
|
||||
|
342
drivers/regulator/tps51632-regulator.c
Normal file
342
drivers/regulator/tps51632-regulator.c
Normal file
@ -0,0 +1,342 @@
|
||||
/*
|
||||
* 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;
|
||||
return vsel;
|
||||
}
|
||||
|
||||
static int tps51632_dcdc_set_voltage_sel(struct regulator_dev *rdev,
|
||||
unsigned selector)
|
||||
{
|
||||
struct tps51632_chip *tps = rdev_get_drvdata(rdev);
|
||||
int ret;
|
||||
unsigned int reg = TPS51632_VOLTAGE_SELECT_REG;
|
||||
|
||||
if (tps->enable_pwm_dvfs)
|
||||
reg = TPS51632_VOLTAGE_BASE_REG;
|
||||
|
||||
if (selector > TPS51632_MAX_VSEL)
|
||||
return -EINVAL;
|
||||
|
||||
ret = regmap_write(tps->regmap, reg, selector);
|
||||
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 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 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;
|
||||
}
|
||||
|
||||
if (pdata->enable_pwm_dvfs) {
|
||||
if ((pdata->base_voltage_uV < TPS51632_MIN_VOLATGE) ||
|
||||
(pdata->base_voltage_uV > TPS51632_MAX_VOLATGE)) {
|
||||
dev_err(&client->dev, "Invalid base_voltage_uV setting\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if ((pdata->max_voltage_uV) &&
|
||||
((pdata->max_voltage_uV < TPS51632_MIN_VOLATGE) ||
|
||||
(pdata->max_voltage_uV > TPS51632_MAX_VOLATGE))) {
|
||||
dev_err(&client->dev, "Invalid max_voltage_uV setting\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.linear_min_sel = TPS51632_MIN_VSEL;
|
||||
tps->desc.n_voltages = TPS51632_MAX_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 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 = 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");
|
@ -127,7 +127,7 @@ static const struct regulator_desc tps6105x_regulator_desc = {
|
||||
/*
|
||||
* Registers the chip as a voltage regulator
|
||||
*/
|
||||
static int __devinit tps6105x_regulator_probe(struct platform_device *pdev)
|
||||
static int tps6105x_regulator_probe(struct platform_device *pdev)
|
||||
{
|
||||
struct tps6105x *tps6105x = dev_get_platdata(&pdev->dev);
|
||||
struct tps6105x_platform_data *pdata = tps6105x->pdata;
|
||||
@ -159,7 +159,7 @@ static int __devinit tps6105x_regulator_probe(struct platform_device *pdev)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int __devexit tps6105x_regulator_remove(struct platform_device *pdev)
|
||||
static int tps6105x_regulator_remove(struct platform_device *pdev)
|
||||
{
|
||||
struct tps6105x *tps6105x = dev_get_platdata(&pdev->dev);
|
||||
regulator_unregister(tps6105x->regulator);
|
||||
@ -172,7 +172,7 @@ static struct platform_driver tps6105x_regulator_driver = {
|
||||
.owner = THIS_MODULE,
|
||||
},
|
||||
.probe = tps6105x_regulator_probe,
|
||||
.remove = __devexit_p(tps6105x_regulator_remove),
|
||||
.remove = tps6105x_regulator_remove,
|
||||
};
|
||||
|
||||
static __init int tps6105x_regulator_init(void)
|
||||
|
@ -243,7 +243,7 @@ static struct regulator_ops tps62360_dcdc_ops = {
|
||||
.get_mode = tps62360_get_mode,
|
||||
};
|
||||
|
||||
static int __devinit tps62360_init_dcdc(struct tps62360_chip *tps,
|
||||
static int tps62360_init_dcdc(struct tps62360_chip *tps,
|
||||
struct tps62360_regulator_platform_data *pdata)
|
||||
{
|
||||
int ret;
|
||||
@ -339,7 +339,7 @@ static const struct of_device_id tps62360_of_match[] = {
|
||||
MODULE_DEVICE_TABLE(of, tps62360_of_match);
|
||||
#endif
|
||||
|
||||
static int __devinit tps62360_probe(struct i2c_client *client,
|
||||
static int tps62360_probe(struct i2c_client *client,
|
||||
const struct i2c_device_id *id)
|
||||
{
|
||||
struct regulator_config config = { };
|
||||
@ -490,7 +490,7 @@ static int __devinit tps62360_probe(struct i2c_client *client,
|
||||
*
|
||||
* Unregister TPS driver as an i2c client device driver
|
||||
*/
|
||||
static int __devexit tps62360_remove(struct i2c_client *client)
|
||||
static int tps62360_remove(struct i2c_client *client)
|
||||
{
|
||||
struct tps62360_chip *tps = i2c_get_clientdata(client);
|
||||
|
||||
@ -531,7 +531,7 @@ static struct i2c_driver tps62360_i2c_driver = {
|
||||
.of_match_table = of_match_ptr(tps62360_of_match),
|
||||
},
|
||||
.probe = tps62360_probe,
|
||||
.remove = __devexit_p(tps62360_remove),
|
||||
.remove = tps62360_remove,
|
||||
.shutdown = tps62360_shutdown,
|
||||
.id_table = tps62360_id,
|
||||
};
|
||||
|
@ -219,7 +219,7 @@ static struct regmap_config tps65023_regmap_config = {
|
||||
.val_bits = 8,
|
||||
};
|
||||
|
||||
static int __devinit tps_65023_probe(struct i2c_client *client,
|
||||
static int tps_65023_probe(struct i2c_client *client,
|
||||
const struct i2c_device_id *id)
|
||||
{
|
||||
const struct tps_driver_data *drv_data = (void *)id->driver_data;
|
||||
@ -319,7 +319,7 @@ static int __devinit tps_65023_probe(struct i2c_client *client,
|
||||
return error;
|
||||
}
|
||||
|
||||
static int __devexit tps_65023_remove(struct i2c_client *client)
|
||||
static int tps_65023_remove(struct i2c_client *client)
|
||||
{
|
||||
struct tps_pmic *tps = i2c_get_clientdata(client);
|
||||
int i;
|
||||
@ -446,7 +446,7 @@ static struct i2c_driver tps_65023_i2c_driver = {
|
||||
.owner = THIS_MODULE,
|
||||
},
|
||||
.probe = tps_65023_probe,
|
||||
.remove = __devexit_p(tps_65023_remove),
|
||||
.remove = tps_65023_remove,
|
||||
.id_table = tps_65023_id,
|
||||
};
|
||||
|
||||
|
@ -356,7 +356,7 @@ static struct regulator_ops tps6507x_pmic_ops = {
|
||||
.list_voltage = regulator_list_voltage_table,
|
||||
};
|
||||
|
||||
static __devinit int tps6507x_pmic_probe(struct platform_device *pdev)
|
||||
static int tps6507x_pmic_probe(struct platform_device *pdev)
|
||||
{
|
||||
struct tps6507x_dev *tps6507x_dev = dev_get_drvdata(pdev->dev.parent);
|
||||
struct tps_info *info = &tps6507x_pmic_regs[0];
|
||||
@ -439,7 +439,7 @@ fail:
|
||||
return error;
|
||||
}
|
||||
|
||||
static int __devexit tps6507x_pmic_remove(struct platform_device *pdev)
|
||||
static int tps6507x_pmic_remove(struct platform_device *pdev)
|
||||
{
|
||||
struct tps6507x_dev *tps6507x_dev = platform_get_drvdata(pdev);
|
||||
struct tps6507x_pmic *tps = tps6507x_dev->pmic;
|
||||
@ -456,7 +456,7 @@ static struct platform_driver tps6507x_pmic_driver = {
|
||||
.owner = THIS_MODULE,
|
||||
},
|
||||
.probe = tps6507x_pmic_probe,
|
||||
.remove = __devexit_p(tps6507x_pmic_remove),
|
||||
.remove = tps6507x_pmic_remove,
|
||||
};
|
||||
|
||||
static int __init tps6507x_pmic_init(void)
|
||||
|
@ -18,119 +18,240 @@
|
||||
|
||||
#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;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static int __devinit tps65090_regulator_probe(struct platform_device *pdev)
|
||||
static int 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 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 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;
|
||||
}
|
||||
}
|
||||
|
||||
static int tps65090_regulator_probe(struct platform_device *pdev)
|
||||
{
|
||||
struct tps65090 *tps65090_mfd = dev_get_drvdata(pdev->dev.parent);
|
||||
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)
|
||||
static int 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,
|
||||
.remove = __devexit_p(tps65090_regulator_remove),
|
||||
.remove = tps65090_regulator_remove,
|
||||
};
|
||||
|
||||
static int __init tps65090_regulator_init(void)
|
||||
@ -148,3 +269,4 @@ module_exit(tps65090_regulator_exit);
|
||||
MODULE_DESCRIPTION("tps65090 regulator driver");
|
||||
MODULE_AUTHOR("Venu Byravarasu <vbyravarasu@nvidia.com>");
|
||||
MODULE_LICENSE("GPL v2");
|
||||
MODULE_ALIAS("platform:tps65090-pmic");
|
||||
|
@ -332,7 +332,7 @@ static struct tps65217_board *tps65217_parse_dt(struct platform_device *pdev)
|
||||
}
|
||||
#endif
|
||||
|
||||
static int __devinit tps65217_regulator_probe(struct platform_device *pdev)
|
||||
static int tps65217_regulator_probe(struct platform_device *pdev)
|
||||
{
|
||||
struct tps65217 *tps = dev_get_drvdata(pdev->dev.parent);
|
||||
struct tps65217_board *pdata = dev_get_platdata(tps->dev);
|
||||
@ -397,7 +397,7 @@ err_unregister_regulator:
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int __devexit tps65217_regulator_remove(struct platform_device *pdev)
|
||||
static int tps65217_regulator_remove(struct platform_device *pdev)
|
||||
{
|
||||
struct tps65217 *tps = platform_get_drvdata(pdev);
|
||||
unsigned int i;
|
||||
@ -415,7 +415,7 @@ static struct platform_driver tps65217_regulator_driver = {
|
||||
.name = "tps65217-pmic",
|
||||
},
|
||||
.probe = tps65217_regulator_probe,
|
||||
.remove = __devexit_p(tps65217_regulator_remove),
|
||||
.remove = tps65217_regulator_remove,
|
||||
};
|
||||
|
||||
static int __init tps65217_regulator_init(void)
|
||||
|
@ -592,7 +592,7 @@ static int pmic_remove(struct spi_device *spi)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int __devinit pmic_probe(struct spi_device *spi)
|
||||
static int pmic_probe(struct spi_device *spi)
|
||||
{
|
||||
struct tps6524x *hw;
|
||||
struct device *dev = &spi->dev;
|
||||
@ -649,7 +649,7 @@ fail:
|
||||
|
||||
static struct spi_driver pmic_driver = {
|
||||
.probe = pmic_probe,
|
||||
.remove = __devexit_p(pmic_remove),
|
||||
.remove = pmic_remove,
|
||||
.driver = {
|
||||
.name = "tps6524x",
|
||||
.owner = THIS_MODULE,
|
||||
|
@ -17,10 +17,12 @@
|
||||
#include <linux/module.h>
|
||||
#include <linux/init.h>
|
||||
#include <linux/err.h>
|
||||
#include <linux/of.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/regulator/driver.h>
|
||||
#include <linux/regulator/machine.h>
|
||||
#include <linux/regulator/of_regulator.h>
|
||||
#include <linux/mfd/tps6586x.h>
|
||||
|
||||
/* supply control and voltage setting */
|
||||
@ -255,10 +257,10 @@ static inline int tps6586x_regulator_preinit(struct device *parent,
|
||||
1 << ri->enable_bit[1]);
|
||||
}
|
||||
|
||||
static int tps6586x_regulator_set_slew_rate(struct platform_device *pdev)
|
||||
static int tps6586x_regulator_set_slew_rate(struct platform_device *pdev,
|
||||
int id, struct regulator_init_data *p)
|
||||
{
|
||||
struct device *parent = pdev->dev.parent;
|
||||
struct regulator_init_data *p = pdev->dev.platform_data;
|
||||
struct tps6586x_settings *setting = p->driver_data;
|
||||
uint8_t reg;
|
||||
|
||||
@ -269,7 +271,7 @@ static int tps6586x_regulator_set_slew_rate(struct platform_device *pdev)
|
||||
return 0;
|
||||
|
||||
/* only SM0 and SM1 can have the slew rate settings */
|
||||
switch (pdev->id) {
|
||||
switch (id) {
|
||||
case TPS6586X_ID_SM_0:
|
||||
reg = TPS6586X_SM0SL;
|
||||
break;
|
||||
@ -298,58 +300,185 @@ static inline struct tps6586x_regulator *find_regulator_info(int id)
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static int __devinit tps6586x_regulator_probe(struct platform_device *pdev)
|
||||
#ifdef CONFIG_OF
|
||||
static struct of_regulator_match tps6586x_matches[] = {
|
||||
{ .name = "sys", .driver_data = (void *)TPS6586X_ID_SYS },
|
||||
{ .name = "sm0", .driver_data = (void *)TPS6586X_ID_SM_0 },
|
||||
{ .name = "sm1", .driver_data = (void *)TPS6586X_ID_SM_1 },
|
||||
{ .name = "sm2", .driver_data = (void *)TPS6586X_ID_SM_2 },
|
||||
{ .name = "ldo0", .driver_data = (void *)TPS6586X_ID_LDO_0 },
|
||||
{ .name = "ldo1", .driver_data = (void *)TPS6586X_ID_LDO_1 },
|
||||
{ .name = "ldo2", .driver_data = (void *)TPS6586X_ID_LDO_2 },
|
||||
{ .name = "ldo3", .driver_data = (void *)TPS6586X_ID_LDO_3 },
|
||||
{ .name = "ldo4", .driver_data = (void *)TPS6586X_ID_LDO_4 },
|
||||
{ .name = "ldo5", .driver_data = (void *)TPS6586X_ID_LDO_5 },
|
||||
{ .name = "ldo6", .driver_data = (void *)TPS6586X_ID_LDO_6 },
|
||||
{ .name = "ldo7", .driver_data = (void *)TPS6586X_ID_LDO_7 },
|
||||
{ .name = "ldo8", .driver_data = (void *)TPS6586X_ID_LDO_8 },
|
||||
{ .name = "ldo9", .driver_data = (void *)TPS6586X_ID_LDO_9 },
|
||||
{ .name = "ldo_rtc", .driver_data = (void *)TPS6586X_ID_LDO_RTC },
|
||||
};
|
||||
|
||||
static struct tps6586x_platform_data *tps6586x_parse_regulator_dt(
|
||||
struct platform_device *pdev,
|
||||
struct of_regulator_match **tps6586x_reg_matches)
|
||||
{
|
||||
const unsigned int num = ARRAY_SIZE(tps6586x_matches);
|
||||
struct device_node *np = pdev->dev.parent->of_node;
|
||||
struct device_node *regs;
|
||||
const char *sys_rail = NULL;
|
||||
unsigned int i;
|
||||
struct tps6586x_platform_data *pdata;
|
||||
int err;
|
||||
|
||||
regs = of_find_node_by_name(np, "regulators");
|
||||
if (!regs) {
|
||||
dev_err(&pdev->dev, "regulator node not found\n");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
err = of_regulator_match(&pdev->dev, regs, tps6586x_matches, num);
|
||||
if (err < 0) {
|
||||
dev_err(&pdev->dev, "Regulator match failed, e %d\n", err);
|
||||
of_node_put(regs);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
of_node_put(regs);
|
||||
|
||||
pdata = devm_kzalloc(&pdev->dev, sizeof(*pdata), GFP_KERNEL);
|
||||
if (!pdata) {
|
||||
dev_err(&pdev->dev, "Memory alloction failed\n");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
for (i = 0; i < num; i++) {
|
||||
int id;
|
||||
if (!tps6586x_matches[i].init_data)
|
||||
continue;
|
||||
|
||||
pdata->reg_init_data[i] = tps6586x_matches[i].init_data;
|
||||
id = (int)tps6586x_matches[i].driver_data;
|
||||
if (id == TPS6586X_ID_SYS)
|
||||
sys_rail = pdata->reg_init_data[i]->constraints.name;
|
||||
|
||||
if ((id == TPS6586X_ID_LDO_5) || (id == TPS6586X_ID_LDO_RTC))
|
||||
pdata->reg_init_data[i]->supply_regulator = sys_rail;
|
||||
}
|
||||
*tps6586x_reg_matches = tps6586x_matches;
|
||||
return pdata;
|
||||
}
|
||||
#else
|
||||
static struct tps6586x_platform_data *tps6586x_parse_regulator_dt(
|
||||
struct platform_device *pdev,
|
||||
struct of_regulator_match **tps6586x_reg_matches)
|
||||
{
|
||||
*tps6586x_reg_matches = NULL;
|
||||
return NULL;
|
||||
}
|
||||
#endif
|
||||
|
||||
static int tps6586x_regulator_probe(struct platform_device *pdev)
|
||||
{
|
||||
struct tps6586x_regulator *ri = NULL;
|
||||
struct regulator_config config = { };
|
||||
struct regulator_dev *rdev;
|
||||
int id = pdev->id;
|
||||
struct regulator_dev **rdev;
|
||||
struct regulator_init_data *reg_data;
|
||||
struct tps6586x_platform_data *pdata;
|
||||
struct of_regulator_match *tps6586x_reg_matches = NULL;
|
||||
int id;
|
||||
int err;
|
||||
|
||||
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");
|
||||
return -EINVAL;
|
||||
pdata = dev_get_platdata(pdev->dev.parent);
|
||||
if ((!pdata) && (pdev->dev.parent->of_node))
|
||||
pdata = tps6586x_parse_regulator_dt(pdev,
|
||||
&tps6586x_reg_matches);
|
||||
|
||||
if (!pdata) {
|
||||
dev_err(&pdev->dev, "Platform data not available, exiting\n");
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
err = tps6586x_regulator_preinit(pdev->dev.parent, ri);
|
||||
if (err)
|
||||
return err;
|
||||
rdev = devm_kzalloc(&pdev->dev, TPS6586X_ID_MAX_REGULATOR *
|
||||
sizeof(*rdev), GFP_KERNEL);
|
||||
if (!rdev) {
|
||||
dev_err(&pdev->dev, "Mmemory alloc failed\n");
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
config.dev = pdev->dev.parent;
|
||||
config.of_node = pdev->dev.of_node;
|
||||
config.init_data = pdev->dev.platform_data;
|
||||
config.driver_data = ri;
|
||||
for (id = 0; id < TPS6586X_ID_MAX_REGULATOR; ++id) {
|
||||
reg_data = pdata->reg_init_data[id];
|
||||
|
||||
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);
|
||||
ri = find_regulator_info(id);
|
||||
if (!ri) {
|
||||
dev_err(&pdev->dev, "invalid regulator ID specified\n");
|
||||
err = -EINVAL;
|
||||
goto fail;
|
||||
}
|
||||
|
||||
err = tps6586x_regulator_preinit(pdev->dev.parent, ri);
|
||||
if (err) {
|
||||
dev_err(&pdev->dev,
|
||||
"regulator %d preinit failed, e %d\n", id, err);
|
||||
goto fail;
|
||||
}
|
||||
|
||||
config.dev = pdev->dev.parent;
|
||||
config.init_data = reg_data;
|
||||
config.driver_data = ri;
|
||||
|
||||
if (tps6586x_reg_matches)
|
||||
config.of_node = tps6586x_reg_matches[id].of_node;
|
||||
|
||||
rdev[id] = regulator_register(&ri->desc, &config);
|
||||
if (IS_ERR(rdev[id])) {
|
||||
dev_err(&pdev->dev, "failed to register regulator %s\n",
|
||||
ri->desc.name);
|
||||
err = PTR_ERR(rdev[id]);
|
||||
goto fail;
|
||||
}
|
||||
|
||||
if (reg_data) {
|
||||
err = tps6586x_regulator_set_slew_rate(pdev, id,
|
||||
reg_data);
|
||||
if (err < 0) {
|
||||
dev_err(&pdev->dev,
|
||||
"Slew rate config failed, e %d\n", err);
|
||||
regulator_unregister(rdev[id]);
|
||||
goto fail;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
platform_set_drvdata(pdev, rdev);
|
||||
return 0;
|
||||
|
||||
return tps6586x_regulator_set_slew_rate(pdev);
|
||||
fail:
|
||||
while (--id >= 0)
|
||||
regulator_unregister(rdev[id]);
|
||||
return err;
|
||||
}
|
||||
|
||||
static int __devexit tps6586x_regulator_remove(struct platform_device *pdev)
|
||||
static int tps6586x_regulator_remove(struct platform_device *pdev)
|
||||
{
|
||||
struct regulator_dev *rdev = platform_get_drvdata(pdev);
|
||||
struct regulator_dev **rdev = platform_get_drvdata(pdev);
|
||||
int id = TPS6586X_ID_MAX_REGULATOR;
|
||||
|
||||
while (--id >= 0)
|
||||
regulator_unregister(rdev[id]);
|
||||
|
||||
regulator_unregister(rdev);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct platform_driver tps6586x_regulator_driver = {
|
||||
.driver = {
|
||||
.name = "tps6586x-regulator",
|
||||
.name = "tps6586x-pmic",
|
||||
.owner = THIS_MODULE,
|
||||
},
|
||||
.probe = tps6586x_regulator_probe,
|
||||
.remove = __devexit_p(tps6586x_regulator_remove),
|
||||
.remove = tps6586x_regulator_remove,
|
||||
};
|
||||
|
||||
static int __init tps6586x_regulator_init(void)
|
||||
|
@ -38,6 +38,11 @@ static const unsigned int VIO_VSEL_table[] = {
|
||||
|
||||
/* VSEL tables for TPS65910 specific LDOs and dcdc's */
|
||||
|
||||
/* supported VRTC voltages in microvolts */
|
||||
static const unsigned int VRTC_VSEL_table[] = {
|
||||
1800000,
|
||||
};
|
||||
|
||||
/* supported VDD3 voltages in microvolts */
|
||||
static const unsigned int VDD3_VSEL_table[] = {
|
||||
5000000,
|
||||
@ -95,6 +100,8 @@ static struct tps_info tps65910_regs[] = {
|
||||
{
|
||||
.name = "vrtc",
|
||||
.vin_name = "vcc7",
|
||||
.n_voltages = ARRAY_SIZE(VRTC_VSEL_table),
|
||||
.voltage_table = VRTC_VSEL_table,
|
||||
.enable_time_us = 2200,
|
||||
},
|
||||
{
|
||||
@ -1026,7 +1033,7 @@ static inline struct tps65910_board *tps65910_parse_dt_reg_data(
|
||||
}
|
||||
#endif
|
||||
|
||||
static __devinit int tps65910_probe(struct platform_device *pdev)
|
||||
static int tps65910_probe(struct platform_device *pdev)
|
||||
{
|
||||
struct tps65910 *tps65910 = dev_get_drvdata(pdev->dev.parent);
|
||||
struct regulator_config config = { };
|
||||
@ -1184,7 +1191,7 @@ err_unregister_regulator:
|
||||
return err;
|
||||
}
|
||||
|
||||
static int __devexit tps65910_remove(struct platform_device *pdev)
|
||||
static int tps65910_remove(struct platform_device *pdev)
|
||||
{
|
||||
struct tps65910_reg *pmic = platform_get_drvdata(pdev);
|
||||
int i;
|
||||
@ -1231,7 +1238,7 @@ static struct platform_driver tps65910_driver = {
|
||||
.owner = THIS_MODULE,
|
||||
},
|
||||
.probe = tps65910_probe,
|
||||
.remove = __devexit_p(tps65910_remove),
|
||||
.remove = tps65910_remove,
|
||||
.shutdown = tps65910_shutdown,
|
||||
};
|
||||
|
||||
|
@ -459,7 +459,7 @@ static struct regulator_ops tps65912_ops_ldo = {
|
||||
.list_voltage = tps65912_list_voltage,
|
||||
};
|
||||
|
||||
static __devinit int tps65912_probe(struct platform_device *pdev)
|
||||
static int tps65912_probe(struct platform_device *pdev)
|
||||
{
|
||||
struct tps65912 *tps65912 = dev_get_drvdata(pdev->dev.parent);
|
||||
struct regulator_config config = { };
|
||||
@ -525,7 +525,7 @@ err:
|
||||
return err;
|
||||
}
|
||||
|
||||
static int __devexit tps65912_remove(struct platform_device *pdev)
|
||||
static int tps65912_remove(struct platform_device *pdev)
|
||||
{
|
||||
struct tps65912_reg *tps65912_reg = platform_get_drvdata(pdev);
|
||||
int i;
|
||||
@ -541,7 +541,7 @@ static struct platform_driver tps65912_driver = {
|
||||
.owner = THIS_MODULE,
|
||||
},
|
||||
.probe = tps65912_probe,
|
||||
.remove = __devexit_p(tps65912_remove),
|
||||
.remove = tps65912_remove,
|
||||
};
|
||||
|
||||
static int __init tps65912_init(void)
|
||||
|
788
drivers/regulator/tps80031-regulator.c
Normal file
788
drivers/regulator/tps80031-regulator.c
Normal file
@ -0,0 +1,788 @@
|
||||
/*
|
||||
* tps80031-regulator.c -- TI TPS80031 regulator driver.
|
||||
*
|
||||
* Regulator driver for TI TPS80031/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_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_CTRL3, 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 = regulator_list_voltage_linear,
|
||||
.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 = {
|
||||
.list_voltage = regulator_list_voltage_linear,
|
||||
.enable = tps80031_vbus_enable,
|
||||
.disable = tps80031_vbus_disable,
|
||||
.is_enabled = tps80031_vbus_is_enabled,
|
||||
};
|
||||
|
||||
static struct regulator_ops tps80031_vbus_hw_ops = {
|
||||
.list_voltage = regulator_list_voltage_linear,
|
||||
};
|
||||
|
||||
static struct regulator_ops tps80031_ext_reg_ops = {
|
||||
.list_voltage = regulator_list_voltage_linear,
|
||||
.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, \
|
||||
.linear_min_sel = 1, \
|
||||
.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, \
|
||||
.min_uV = max_mV * 1000, \
|
||||
.n_voltages = 1, \
|
||||
.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 tps80031_regulator_probe(struct platform_device *pdev)
|
||||
{
|
||||
struct tps80031_platform_data *pdata;
|
||||
struct tps80031_regulator_platform_data *tps_pdata;
|
||||
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];
|
||||
ri = &pmic[num];
|
||||
ri->rinfo = &tps80031_rinfo[num];
|
||||
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 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 = 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/TPS80032 PMIC");
|
||||
MODULE_AUTHOR("Laxman Dewangan <ldewangan@nvidia.com>");
|
||||
MODULE_LICENSE("GPL v2");
|
@ -1116,7 +1116,7 @@ static const struct of_device_id twl_of_match[] __devinitconst = {
|
||||
};
|
||||
MODULE_DEVICE_TABLE(of, twl_of_match);
|
||||
|
||||
static int __devinit twlreg_probe(struct platform_device *pdev)
|
||||
static int twlreg_probe(struct platform_device *pdev)
|
||||
{
|
||||
int i, id;
|
||||
struct twlreg_info *info;
|
||||
@ -1241,7 +1241,7 @@ static int __devinit twlreg_probe(struct platform_device *pdev)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int __devexit twlreg_remove(struct platform_device *pdev)
|
||||
static int twlreg_remove(struct platform_device *pdev)
|
||||
{
|
||||
struct regulator_dev *rdev = platform_get_drvdata(pdev);
|
||||
struct twlreg_info *info = rdev->reg_data;
|
||||
@ -1255,7 +1255,7 @@ MODULE_ALIAS("platform:twl_reg");
|
||||
|
||||
static struct platform_driver twlreg_driver = {
|
||||
.probe = twlreg_probe,
|
||||
.remove = __devexit_p(twlreg_remove),
|
||||
.remove = twlreg_remove,
|
||||
/* NOTE: short name, to work around driver model truncation of
|
||||
* "twl_regulator.12" (and friends) to "twl_regulator.1".
|
||||
*/
|
||||
|
147
drivers/regulator/vexpress.c
Normal file
147
drivers/regulator/vexpress.c
Normal file
@ -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 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 = 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");
|
@ -285,7 +285,7 @@ static const struct attribute_group regulator_virtual_attr_group = {
|
||||
.attrs = regulator_virtual_attributes,
|
||||
};
|
||||
|
||||
static int __devinit regulator_virtual_probe(struct platform_device *pdev)
|
||||
static int regulator_virtual_probe(struct platform_device *pdev)
|
||||
{
|
||||
char *reg_id = pdev->dev.platform_data;
|
||||
struct virtual_consumer_data *drvdata;
|
||||
@ -321,7 +321,7 @@ static int __devinit regulator_virtual_probe(struct platform_device *pdev)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int __devexit regulator_virtual_remove(struct platform_device *pdev)
|
||||
static int regulator_virtual_remove(struct platform_device *pdev)
|
||||
{
|
||||
struct virtual_consumer_data *drvdata = platform_get_drvdata(pdev);
|
||||
|
||||
@ -337,7 +337,7 @@ static int __devexit regulator_virtual_remove(struct platform_device *pdev)
|
||||
|
||||
static struct platform_driver regulator_virtual_consumer_driver = {
|
||||
.probe = regulator_virtual_probe,
|
||||
.remove = __devexit_p(regulator_virtual_remove),
|
||||
.remove = regulator_virtual_remove,
|
||||
.driver = {
|
||||
.name = "reg-virt-consumer",
|
||||
.owner = THIS_MODULE,
|
||||
|
@ -223,7 +223,7 @@ static int wm831x_buckv_map_voltage(struct regulator_dev *rdev,
|
||||
if (min_uV < 600000)
|
||||
vsel = 0;
|
||||
else if (min_uV <= 1800000)
|
||||
vsel = ((min_uV - 600000) / 12500) + 8;
|
||||
vsel = DIV_ROUND_UP(min_uV - 600000, 12500) + 8;
|
||||
else
|
||||
return -EINVAL;
|
||||
|
||||
@ -290,7 +290,7 @@ static int wm831x_buckv_set_voltage_sel(struct regulator_dev *rdev,
|
||||
if (vsel > dcdc->dvs_vsel) {
|
||||
ret = wm831x_set_bits(wm831x, dvs_reg,
|
||||
WM831X_DC1_DVS_VSEL_MASK,
|
||||
dcdc->dvs_vsel);
|
||||
vsel);
|
||||
if (ret == 0)
|
||||
dcdc->dvs_vsel = vsel;
|
||||
else
|
||||
@ -387,7 +387,7 @@ static struct regulator_ops wm831x_buckv_ops = {
|
||||
* Set up DVS control. We just log errors since we can still run
|
||||
* (with reduced performance) if we fail.
|
||||
*/
|
||||
static __devinit void wm831x_buckv_dvs_init(struct wm831x_dcdc *dcdc,
|
||||
static void wm831x_buckv_dvs_init(struct wm831x_dcdc *dcdc,
|
||||
struct wm831x_buckv_pdata *pdata)
|
||||
{
|
||||
struct wm831x *wm831x = dcdc->wm831x;
|
||||
@ -448,7 +448,7 @@ static __devinit void wm831x_buckv_dvs_init(struct wm831x_dcdc *dcdc,
|
||||
}
|
||||
}
|
||||
|
||||
static __devinit int wm831x_buckv_probe(struct platform_device *pdev)
|
||||
static int wm831x_buckv_probe(struct platform_device *pdev)
|
||||
{
|
||||
struct wm831x *wm831x = dev_get_drvdata(pdev->dev.parent);
|
||||
struct wm831x_pdata *pdata = wm831x->dev->platform_data;
|
||||
@ -562,7 +562,7 @@ err:
|
||||
return ret;
|
||||
}
|
||||
|
||||
static __devexit int wm831x_buckv_remove(struct platform_device *pdev)
|
||||
static int wm831x_buckv_remove(struct platform_device *pdev)
|
||||
{
|
||||
struct wm831x_dcdc *dcdc = platform_get_drvdata(pdev);
|
||||
struct wm831x *wm831x = dcdc->wm831x;
|
||||
@ -582,7 +582,7 @@ static __devexit int wm831x_buckv_remove(struct platform_device *pdev)
|
||||
|
||||
static struct platform_driver wm831x_buckv_driver = {
|
||||
.probe = wm831x_buckv_probe,
|
||||
.remove = __devexit_p(wm831x_buckv_remove),
|
||||
.remove = wm831x_buckv_remove,
|
||||
.driver = {
|
||||
.name = "wm831x-buckv",
|
||||
.owner = THIS_MODULE,
|
||||
@ -623,7 +623,7 @@ static struct regulator_ops wm831x_buckp_ops = {
|
||||
.set_suspend_mode = wm831x_dcdc_set_suspend_mode,
|
||||
};
|
||||
|
||||
static __devinit int wm831x_buckp_probe(struct platform_device *pdev)
|
||||
static int wm831x_buckp_probe(struct platform_device *pdev)
|
||||
{
|
||||
struct wm831x *wm831x = dev_get_drvdata(pdev->dev.parent);
|
||||
struct wm831x_pdata *pdata = wm831x->dev->platform_data;
|
||||
@ -710,7 +710,7 @@ err:
|
||||
return ret;
|
||||
}
|
||||
|
||||
static __devexit int wm831x_buckp_remove(struct platform_device *pdev)
|
||||
static int wm831x_buckp_remove(struct platform_device *pdev)
|
||||
{
|
||||
struct wm831x_dcdc *dcdc = platform_get_drvdata(pdev);
|
||||
|
||||
@ -725,7 +725,7 @@ static __devexit int wm831x_buckp_remove(struct platform_device *pdev)
|
||||
|
||||
static struct platform_driver wm831x_buckp_driver = {
|
||||
.probe = wm831x_buckp_probe,
|
||||
.remove = __devexit_p(wm831x_buckp_remove),
|
||||
.remove = wm831x_buckp_remove,
|
||||
.driver = {
|
||||
.name = "wm831x-buckp",
|
||||
.owner = THIS_MODULE,
|
||||
@ -771,7 +771,7 @@ static struct regulator_ops wm831x_boostp_ops = {
|
||||
.disable = regulator_disable_regmap,
|
||||
};
|
||||
|
||||
static __devinit int wm831x_boostp_probe(struct platform_device *pdev)
|
||||
static int wm831x_boostp_probe(struct platform_device *pdev)
|
||||
{
|
||||
struct wm831x *wm831x = dev_get_drvdata(pdev->dev.parent);
|
||||
struct wm831x_pdata *pdata = wm831x->dev->platform_data;
|
||||
@ -845,7 +845,7 @@ err:
|
||||
return ret;
|
||||
}
|
||||
|
||||
static __devexit int wm831x_boostp_remove(struct platform_device *pdev)
|
||||
static int wm831x_boostp_remove(struct platform_device *pdev)
|
||||
{
|
||||
struct wm831x_dcdc *dcdc = platform_get_drvdata(pdev);
|
||||
|
||||
@ -860,7 +860,7 @@ static __devexit int wm831x_boostp_remove(struct platform_device *pdev)
|
||||
|
||||
static struct platform_driver wm831x_boostp_driver = {
|
||||
.probe = wm831x_boostp_probe,
|
||||
.remove = __devexit_p(wm831x_boostp_remove),
|
||||
.remove = wm831x_boostp_remove,
|
||||
.driver = {
|
||||
.name = "wm831x-boostp",
|
||||
.owner = THIS_MODULE,
|
||||
@ -883,7 +883,7 @@ static struct regulator_ops wm831x_epe_ops = {
|
||||
.get_status = wm831x_dcdc_get_status,
|
||||
};
|
||||
|
||||
static __devinit int wm831x_epe_probe(struct platform_device *pdev)
|
||||
static int wm831x_epe_probe(struct platform_device *pdev)
|
||||
{
|
||||
struct wm831x *wm831x = dev_get_drvdata(pdev->dev.parent);
|
||||
struct wm831x_pdata *pdata = wm831x->dev->platform_data;
|
||||
@ -936,7 +936,7 @@ err:
|
||||
return ret;
|
||||
}
|
||||
|
||||
static __devexit int wm831x_epe_remove(struct platform_device *pdev)
|
||||
static int wm831x_epe_remove(struct platform_device *pdev)
|
||||
{
|
||||
struct wm831x_dcdc *dcdc = platform_get_drvdata(pdev);
|
||||
|
||||
@ -948,7 +948,7 @@ static __devexit int wm831x_epe_remove(struct platform_device *pdev)
|
||||
|
||||
static struct platform_driver wm831x_epe_driver = {
|
||||
.probe = wm831x_epe_probe,
|
||||
.remove = __devexit_p(wm831x_epe_remove),
|
||||
.remove = wm831x_epe_remove,
|
||||
.driver = {
|
||||
.name = "wm831x-epe",
|
||||
.owner = THIS_MODULE,
|
||||
@ -993,4 +993,5 @@ MODULE_DESCRIPTION("WM831x DC-DC convertor driver");
|
||||
MODULE_LICENSE("GPL");
|
||||
MODULE_ALIAS("platform:wm831x-buckv");
|
||||
MODULE_ALIAS("platform:wm831x-buckp");
|
||||
MODULE_ALIAS("platform:wm831x-boostp");
|
||||
MODULE_ALIAS("platform:wm831x-epe");
|
||||
|
@ -148,7 +148,7 @@ static irqreturn_t wm831x_isink_irq(int irq, void *data)
|
||||
}
|
||||
|
||||
|
||||
static __devinit int wm831x_isink_probe(struct platform_device *pdev)
|
||||
static int wm831x_isink_probe(struct platform_device *pdev)
|
||||
{
|
||||
struct wm831x *wm831x = dev_get_drvdata(pdev->dev.parent);
|
||||
struct wm831x_pdata *pdata = wm831x->dev->platform_data;
|
||||
@ -221,7 +221,7 @@ err:
|
||||
return ret;
|
||||
}
|
||||
|
||||
static __devexit int wm831x_isink_remove(struct platform_device *pdev)
|
||||
static int wm831x_isink_remove(struct platform_device *pdev)
|
||||
{
|
||||
struct wm831x_isink *isink = platform_get_drvdata(pdev);
|
||||
|
||||
@ -236,7 +236,7 @@ static __devexit int wm831x_isink_remove(struct platform_device *pdev)
|
||||
|
||||
static struct platform_driver wm831x_isink_driver = {
|
||||
.probe = wm831x_isink_probe,
|
||||
.remove = __devexit_p(wm831x_isink_remove),
|
||||
.remove = wm831x_isink_remove,
|
||||
.driver = {
|
||||
.name = "wm831x-isink",
|
||||
.owner = THIS_MODULE,
|
||||
|
@ -247,7 +247,7 @@ static struct regulator_ops wm831x_gp_ldo_ops = {
|
||||
.disable = regulator_disable_regmap,
|
||||
};
|
||||
|
||||
static __devinit int wm831x_gp_ldo_probe(struct platform_device *pdev)
|
||||
static int wm831x_gp_ldo_probe(struct platform_device *pdev)
|
||||
{
|
||||
struct wm831x *wm831x = dev_get_drvdata(pdev->dev.parent);
|
||||
struct wm831x_pdata *pdata = wm831x->dev->platform_data;
|
||||
@ -334,7 +334,7 @@ err:
|
||||
return ret;
|
||||
}
|
||||
|
||||
static __devexit int wm831x_gp_ldo_remove(struct platform_device *pdev)
|
||||
static int wm831x_gp_ldo_remove(struct platform_device *pdev)
|
||||
{
|
||||
struct wm831x_ldo *ldo = platform_get_drvdata(pdev);
|
||||
|
||||
@ -349,7 +349,7 @@ static __devexit int wm831x_gp_ldo_remove(struct platform_device *pdev)
|
||||
|
||||
static struct platform_driver wm831x_gp_ldo_driver = {
|
||||
.probe = wm831x_gp_ldo_probe,
|
||||
.remove = __devexit_p(wm831x_gp_ldo_remove),
|
||||
.remove = wm831x_gp_ldo_remove,
|
||||
.driver = {
|
||||
.name = "wm831x-ldo",
|
||||
.owner = THIS_MODULE,
|
||||
@ -504,7 +504,7 @@ static struct regulator_ops wm831x_aldo_ops = {
|
||||
.disable = regulator_disable_regmap,
|
||||
};
|
||||
|
||||
static __devinit int wm831x_aldo_probe(struct platform_device *pdev)
|
||||
static int wm831x_aldo_probe(struct platform_device *pdev)
|
||||
{
|
||||
struct wm831x *wm831x = dev_get_drvdata(pdev->dev.parent);
|
||||
struct wm831x_pdata *pdata = wm831x->dev->platform_data;
|
||||
@ -590,7 +590,7 @@ err:
|
||||
return ret;
|
||||
}
|
||||
|
||||
static __devexit int wm831x_aldo_remove(struct platform_device *pdev)
|
||||
static int wm831x_aldo_remove(struct platform_device *pdev)
|
||||
{
|
||||
struct wm831x_ldo *ldo = platform_get_drvdata(pdev);
|
||||
|
||||
@ -603,7 +603,7 @@ static __devexit int wm831x_aldo_remove(struct platform_device *pdev)
|
||||
|
||||
static struct platform_driver wm831x_aldo_driver = {
|
||||
.probe = wm831x_aldo_probe,
|
||||
.remove = __devexit_p(wm831x_aldo_remove),
|
||||
.remove = wm831x_aldo_remove,
|
||||
.driver = {
|
||||
.name = "wm831x-aldo",
|
||||
.owner = THIS_MODULE,
|
||||
@ -660,7 +660,7 @@ static struct regulator_ops wm831x_alive_ldo_ops = {
|
||||
.disable = regulator_disable_regmap,
|
||||
};
|
||||
|
||||
static __devinit int wm831x_alive_ldo_probe(struct platform_device *pdev)
|
||||
static int wm831x_alive_ldo_probe(struct platform_device *pdev)
|
||||
{
|
||||
struct wm831x *wm831x = dev_get_drvdata(pdev->dev.parent);
|
||||
struct wm831x_pdata *pdata = wm831x->dev->platform_data;
|
||||
@ -737,7 +737,7 @@ err:
|
||||
return ret;
|
||||
}
|
||||
|
||||
static __devexit int wm831x_alive_ldo_remove(struct platform_device *pdev)
|
||||
static int wm831x_alive_ldo_remove(struct platform_device *pdev)
|
||||
{
|
||||
struct wm831x_ldo *ldo = platform_get_drvdata(pdev);
|
||||
|
||||
@ -748,7 +748,7 @@ static __devexit int wm831x_alive_ldo_remove(struct platform_device *pdev)
|
||||
|
||||
static struct platform_driver wm831x_alive_ldo_driver = {
|
||||
.probe = wm831x_alive_ldo_probe,
|
||||
.remove = __devexit_p(wm831x_alive_ldo_remove),
|
||||
.remove = wm831x_alive_ldo_remove,
|
||||
.driver = {
|
||||
.name = "wm831x-alive-ldo",
|
||||
.owner = THIS_MODULE,
|
||||
|
@ -226,7 +226,7 @@ static struct regulator_desc regulators[] = {
|
||||
},
|
||||
};
|
||||
|
||||
static int __devinit wm8400_regulator_probe(struct platform_device *pdev)
|
||||
static int wm8400_regulator_probe(struct platform_device *pdev)
|
||||
{
|
||||
struct wm8400 *wm8400 = container_of(pdev, struct wm8400, regulators[pdev->id]);
|
||||
struct regulator_config config = { };
|
||||
@ -246,7 +246,7 @@ static int __devinit wm8400_regulator_probe(struct platform_device *pdev)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int __devexit wm8400_regulator_remove(struct platform_device *pdev)
|
||||
static int wm8400_regulator_remove(struct platform_device *pdev)
|
||||
{
|
||||
struct regulator_dev *rdev = platform_get_drvdata(pdev);
|
||||
|
||||
@ -261,7 +261,7 @@ static struct platform_driver wm8400_regulator_driver = {
|
||||
.name = "wm8400-regulator",
|
||||
},
|
||||
.probe = wm8400_regulator_probe,
|
||||
.remove = __devexit_p(wm8400_regulator_remove),
|
||||
.remove = wm8400_regulator_remove,
|
||||
};
|
||||
|
||||
/**
|
||||
|
@ -99,7 +99,7 @@ static const struct regulator_desc wm8994_ldo_desc[] = {
|
||||
},
|
||||
};
|
||||
|
||||
static __devinit int wm8994_ldo_probe(struct platform_device *pdev)
|
||||
static int wm8994_ldo_probe(struct platform_device *pdev)
|
||||
{
|
||||
struct wm8994 *wm8994 = dev_get_drvdata(pdev->dev.parent);
|
||||
struct wm8994_pdata *pdata = wm8994->dev->platform_data;
|
||||
@ -142,7 +142,7 @@ err:
|
||||
return ret;
|
||||
}
|
||||
|
||||
static __devexit int wm8994_ldo_remove(struct platform_device *pdev)
|
||||
static int wm8994_ldo_remove(struct platform_device *pdev)
|
||||
{
|
||||
struct wm8994_ldo *ldo = platform_get_drvdata(pdev);
|
||||
|
||||
@ -155,7 +155,7 @@ static __devexit int wm8994_ldo_remove(struct platform_device *pdev)
|
||||
|
||||
static struct platform_driver wm8994_ldo_driver = {
|
||||
.probe = wm8994_ldo_probe,
|
||||
.remove = __devexit_p(wm8994_ldo_remove),
|
||||
.remove = wm8994_ldo_remove,
|
||||
.driver = {
|
||||
.name = "wm8994-ldo",
|
||||
.owner = THIS_MODULE,
|
||||
|
@ -76,6 +76,7 @@
|
||||
#define ARIZONA_RATE_ESTIMATOR_3 0x154
|
||||
#define ARIZONA_RATE_ESTIMATOR_4 0x155
|
||||
#define ARIZONA_RATE_ESTIMATOR_5 0x156
|
||||
#define ARIZONA_DYNAMIC_FREQUENCY_SCALING_1 0x161
|
||||
#define ARIZONA_FLL1_CONTROL_1 0x171
|
||||
#define ARIZONA_FLL1_CONTROL_2 0x172
|
||||
#define ARIZONA_FLL1_CONTROL_3 0x173
|
||||
@ -110,6 +111,7 @@
|
||||
#define ARIZONA_FLL2_GPIO_CLOCK 0x1AA
|
||||
#define ARIZONA_MIC_CHARGE_PUMP_1 0x200
|
||||
#define ARIZONA_LDO1_CONTROL_1 0x210
|
||||
#define ARIZONA_LDO1_CONTROL_2 0x212
|
||||
#define ARIZONA_LDO2_CONTROL_1 0x213
|
||||
#define ARIZONA_MIC_BIAS_CTRL_1 0x218
|
||||
#define ARIZONA_MIC_BIAS_CTRL_2 0x219
|
||||
@ -1573,6 +1575,13 @@
|
||||
#define ARIZONA_SAMPLE_RATE_DETECT_D_SHIFT 0 /* SAMPLE_RATE_DETECT_D - [4:0] */
|
||||
#define ARIZONA_SAMPLE_RATE_DETECT_D_WIDTH 5 /* SAMPLE_RATE_DETECT_D - [4:0] */
|
||||
|
||||
/*
|
||||
* R353 (0x161) - Dynamic Frequency Scaling 1
|
||||
*/
|
||||
#define ARIZONA_SUBSYS_MAX_FREQ 0x0001 /* SUBSYS_MAX_FREQ */
|
||||
#define ARIZONA_SUBSYS_MAX_FREQ_SHIFT 0 /* SUBSYS_MAX_FREQ */
|
||||
#define ARIZONA_SUBSYS_MAX_FREQ_WIDTH 1 /* SUBSYS_MAX_FREQ */
|
||||
|
||||
/*
|
||||
* R369 (0x171) - FLL1 Control 1
|
||||
*/
|
||||
@ -1888,6 +1897,13 @@
|
||||
#define ARIZONA_LDO1_ENA_SHIFT 0 /* LDO1_ENA */
|
||||
#define ARIZONA_LDO1_ENA_WIDTH 1 /* LDO1_ENA */
|
||||
|
||||
/*
|
||||
* R530 (0x212) - LDO1 Control 2
|
||||
*/
|
||||
#define ARIZONA_LDO1_HI_PWR 0x0001 /* LDO1_HI_PWR */
|
||||
#define ARIZONA_LDO1_HI_PWR_SHIFT 0 /* LDO1_HI_PWR */
|
||||
#define ARIZONA_LDO1_HI_PWR_WIDTH 1 /* LDO1_HI_PWR */
|
||||
|
||||
/*
|
||||
* R531 (0x213) - LDO2 Control 1
|
||||
*/
|
||||
|
@ -25,8 +25,29 @@ struct da9055_pdata {
|
||||
int gpio_base;
|
||||
|
||||
struct regulator_init_data *regulators[DA9055_MAX_REGULATORS];
|
||||
bool reset_enable; /* Enable RTC in RESET Mode */
|
||||
enum gpio_select *gpio_rsel; /* Select regulator set thru GPIO 1/2 */
|
||||
enum gpio_select *gpio_ren; /* Enable regulator thru GPIO 1/2 */
|
||||
/* Enable RTC in RESET Mode */
|
||||
bool reset_enable;
|
||||
/*
|
||||
* GPI muxed pin to control
|
||||
* regulator state A/B, 0 if not available.
|
||||
*/
|
||||
int *gpio_ren;
|
||||
/*
|
||||
* GPI muxed pin to control
|
||||
* regulator set, 0 if not available.
|
||||
*/
|
||||
int *gpio_rsel;
|
||||
/*
|
||||
* Regulator mode control bits value (GPI offset) that
|
||||
* that controls the regulator state, 0 if not available.
|
||||
*/
|
||||
enum gpio_select *reg_ren;
|
||||
/*
|
||||
* Regulator mode control bits value (GPI offset) that
|
||||
* controls the regulator set A/B, 0 if not available.
|
||||
*/
|
||||
enum gpio_select *reg_rsel;
|
||||
/* GPIOs to enable regulator, 0 if not available */
|
||||
int *ena_gpio;
|
||||
};
|
||||
#endif /* __DA9055_PDATA_H */
|
||||
|
@ -316,6 +316,7 @@ enum max8997_irq {
|
||||
#define MAX8997_NUM_GPIO 12
|
||||
struct max8997_dev {
|
||||
struct device *dev;
|
||||
struct max8997_platform_data *pdata;
|
||||
struct i2c_client *i2c; /* 0xcc / PMIC, Battery Control, and FLASH */
|
||||
struct i2c_client *rtc; /* slave addr 0x0c */
|
||||
struct i2c_client *haptic; /* slave addr 0x90 */
|
||||
|
@ -75,6 +75,7 @@ enum max8998_regulators {
|
||||
struct max8997_regulator_data {
|
||||
int id;
|
||||
struct regulator_init_data *initdata;
|
||||
struct device_node *reg_node;
|
||||
};
|
||||
|
||||
enum max8997_muic_usb_type {
|
||||
|
@ -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];
|
||||
};
|
||||
|
||||
/*
|
||||
|
@ -29,6 +29,7 @@ enum {
|
||||
TPS6586X_ID_LDO_8,
|
||||
TPS6586X_ID_LDO_9,
|
||||
TPS6586X_ID_LDO_RTC,
|
||||
TPS6586X_ID_MAX_REGULATOR,
|
||||
};
|
||||
|
||||
enum {
|
||||
@ -79,6 +80,8 @@ struct tps6586x_platform_data {
|
||||
int gpio_base;
|
||||
int irq_base;
|
||||
bool pm_off;
|
||||
|
||||
struct regulator_init_data *reg_init_data[TPS6586X_ID_MAX_REGULATOR];
|
||||
};
|
||||
|
||||
/*
|
||||
|
@ -160,6 +160,7 @@ int regulator_bulk_force_disable(int num_consumers,
|
||||
void regulator_bulk_free(int num_consumers,
|
||||
struct regulator_bulk_data *consumers);
|
||||
|
||||
int regulator_can_change_voltage(struct regulator *regulator);
|
||||
int regulator_count_voltages(struct regulator *regulator);
|
||||
int regulator_list_voltage(struct regulator *regulator, unsigned selector);
|
||||
int regulator_is_supported_voltage(struct regulator *regulator,
|
||||
@ -358,6 +359,10 @@ static inline void regulator_set_drvdata(struct regulator *regulator,
|
||||
{
|
||||
}
|
||||
|
||||
static inline int regulator_count_voltages(struct regulator *regulator)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
static inline int regulator_set_voltage_tol(struct regulator *regulator,
|
||||
@ -367,4 +372,12 @@ static inline int regulator_set_voltage_tol(struct regulator *regulator,
|
||||
new_uV - tol_uV, new_uV + tol_uV);
|
||||
}
|
||||
|
||||
static inline int regulator_is_supported_voltage_tol(struct regulator *regulator,
|
||||
int target_uV, int tol_uV)
|
||||
{
|
||||
return regulator_is_supported_voltage(regulator,
|
||||
target_uV - tol_uV,
|
||||
target_uV + tol_uV);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
@ -181,10 +181,13 @@ 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)
|
||||
* @uV_step: Voltage increase with each selector (if linear mapping)
|
||||
* @linear_min_sel: Minimal selector for starting linear mapping
|
||||
* @ramp_delay: Time to settle down after voltage change (unit: uV/us)
|
||||
* @volt_table: Voltage mapping table (if table based mapping)
|
||||
*
|
||||
@ -199,6 +202,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;
|
||||
@ -207,6 +211,7 @@ struct regulator_desc {
|
||||
|
||||
unsigned int min_uV;
|
||||
unsigned int uV_step;
|
||||
unsigned int linear_min_sel;
|
||||
unsigned int ramp_delay;
|
||||
|
||||
const unsigned int *volt_table;
|
||||
|
72
include/linux/regulator/max8973-regulator.h
Normal file
72
include/linux/regulator/max8973-regulator.h
Normal file
@ -0,0 +1,72 @@
|
||||
/*
|
||||
* max8973-regulator.h -- MAXIM 8973 regulator
|
||||
*
|
||||
* Interface for regulator driver for MAXIM 8973 DC-DC step-down
|
||||
* switching regulator.
|
||||
*
|
||||
* 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_MAX8973_H
|
||||
#define __LINUX_REGULATOR_MAX8973_H
|
||||
|
||||
/*
|
||||
* Control flags for configuration of the device.
|
||||
* Client need to pass this information with ORed
|
||||
*/
|
||||
#define MAX8973_CONTROL_REMOTE_SENSE_ENABLE 0x00000001
|
||||
#define MAX8973_CONTROL_FALLING_SLEW_RATE_ENABLE 0x00000002
|
||||
#define MAX8973_CONTROL_OUTPUT_ACTIVE_DISCH_ENABLE 0x00000004
|
||||
#define MAX8973_CONTROL_BIAS_ENABLE 0x00000008
|
||||
#define MAX8973_CONTROL_PULL_DOWN_ENABLE 0x00000010
|
||||
#define MAX8973_CONTROL_FREQ_SHIFT_9PER_ENABLE 0x00000020
|
||||
|
||||
#define MAX8973_CONTROL_CLKADV_TRIP_DISABLED 0x00000000
|
||||
#define MAX8973_CONTROL_CLKADV_TRIP_75mV_PER_US 0x00010000
|
||||
#define MAX8973_CONTROL_CLKADV_TRIP_150mV_PER_US 0x00020000
|
||||
#define MAX8973_CONTROL_CLKADV_TRIP_75mV_PER_US_HIST_DIS 0x00030000
|
||||
|
||||
#define MAX8973_CONTROL_INDUCTOR_VALUE_NOMINAL 0x00000000
|
||||
#define MAX8973_CONTROL_INDUCTOR_VALUE_MINUS_30_PER 0x00100000
|
||||
#define MAX8973_CONTROL_INDUCTOR_VALUE_PLUS_30_PER 0x00200000
|
||||
#define MAX8973_CONTROL_INDUCTOR_VALUE_PLUS_60_PER 0x00300000
|
||||
|
||||
/*
|
||||
* struct max8973_regulator_platform_data - max8973 regulator platform data.
|
||||
*
|
||||
* @reg_init_data: The regulator init data.
|
||||
* @control_flags: Control flags which are ORed value of above flags to
|
||||
* configure device.
|
||||
* @enable_ext_control: Enable the voltage enable/disable through external
|
||||
* control signal from EN input pin. If it is false then
|
||||
* voltage output will be enabled/disabled through EN bit of
|
||||
* device register.
|
||||
* @dvs_gpio: GPIO for dvs. It should be -1 if this is tied with fixed logic.
|
||||
* @dvs_def_state: Default state of dvs. 1 if it is high else 0.
|
||||
*/
|
||||
struct max8973_regulator_platform_data {
|
||||
struct regulator_init_data *reg_init_data;
|
||||
unsigned long control_flags;
|
||||
bool enable_ext_control;
|
||||
int dvs_gpio;
|
||||
unsigned dvs_def_state:1;
|
||||
};
|
||||
|
||||
#endif /* __LINUX_REGULATOR_MAX8973_H */
|
47
include/linux/regulator/tps51632-regulator.h
Normal file
47
include/linux/regulator/tps51632-regulator.h
Normal file
@ -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…
x
Reference in New Issue
Block a user