Commit ed59c8f9 authored by Mark Brown's avatar Mark Brown

Merge tag 'regulator-v3.15' into regulator-linus

regulator: Updates for v3.15

This release has lots and lots of small cleanups and fixes in the
regulator subsystem, mainly cleaning up some bad patterns that got
duplicated in DT code, but otherwise very little of note outside
of the scope of the relevant drivers:

 - Support for configuration of the initial state for gpio regulators
   with multi-voltage support.
 - Support for calling regulator_set_voltage() on fixed regulators.
 - New drivers for Broadcom BCM590xx, Freescale pfuze200, Samsung S2MPA01 &
   S2MPS11/4, some PWM controlled regulators found on some ST boards and
   TI TPS65218.

# gpg: Signature made Mon 31 Mar 2014 12:29:14 BST using RSA key ID 7EA229BD
# gpg: Good signature from "Mark Brown <broonie@sirena.org.uk>"
# gpg:                 aka "Mark Brown <broonie@debian.org>"
# gpg:                 aka "Mark Brown <broonie@kernel.org>"
# gpg:                 aka "Mark Brown <broonie@tardis.ed.ac.uk>"
# gpg:                 aka "Mark Brown <broonie@linaro.org>"
# gpg:                 aka "Mark Brown <Mark.Brown@linaro.org>"
parents 455c6fdb 5481b348
* Samsung S2MPA01 Voltage and Current Regulator
The Samsung S2MPA01 is a multi-function device which includes high
efficiency buck converters including Dual-Phase buck converter, various LDOs,
and an RTC. It is interfaced to the host controller using an I2C interface.
Each sub-block is addressed by the host system using different I2C slave
addresses.
Required properties:
- compatible: Should be "samsung,s2mpa01-pmic".
- reg: Specifies the I2C slave address of the PMIC block. It should be 0x66.
Optional properties:
- interrupt-parent: Specifies the phandle of the interrupt controller to which
the interrupts from s2mpa01 are delivered to.
- interrupts: An interrupt specifier for the sole interrupt generated by the
device.
Optional nodes:
- regulators: The regulators of s2mpa01 that have to be instantiated should be
included in a sub-node named 'regulators'. Regulator nodes and constraints
included in this sub-node use the standard regulator bindings which are
documented elsewhere.
Properties for BUCK regulator nodes:
- regulator-ramp-delay: ramp delay in uV/us. May be 6250, 12500
(default), 25000, or 50000. May be 0 for disabling the ramp delay on
BUCK{1,2,3,4}.
In the absence of the regulator-ramp-delay property, the default ramp
delay will be used.
NOTE: Some BUCKs share the ramp rate setting i.e. same ramp value will be set
for a particular group of BUCKs. So provide same regulator-ramp-delay=<value>.
The following BUCKs share ramp settings:
* 1 and 6
* 2 and 4
* 8, 9, and 10
The following are the names of the regulators that the s2mpa01 PMIC block
supports. Note: The 'n' in LDOn and BUCKn represents the LDO or BUCK number
as per the datasheet of s2mpa01.
- LDOn
- valid values for n are 1 to 26
- Example: LDO1, LD02, LDO26
- BUCKn
- valid values for n are 1 to 10.
- Example: BUCK1, BUCK2, BUCK9
Example:
s2mpa01_pmic@66 {
compatible = "samsung,s2mpa01-pmic";
reg = <0x66>;
regulators {
ldo1_reg: LDO1 {
regulator-name = "VDD_ALIVE";
regulator-min-microvolt = <1000000>;
regulator-max-microvolt = <1000000>;
};
ldo2_reg: LDO2 {
regulator-name = "VDDQ_MMC2";
regulator-min-microvolt = <2800000>;
regulator-max-microvolt = <2800000>;
regulator-always-on;
};
buck1_reg: BUCK1 {
regulator-name = "vdd_mif";
regulator-min-microvolt = <950000>;
regulator-max-microvolt = <1350000>;
regulator-always-on;
regulator-boot-on;
};
buck2_reg: BUCK2 {
regulator-name = "vdd_arm";
regulator-min-microvolt = <950000>;
regulator-max-microvolt = <1350000>;
regulator-always-on;
regulator-boot-on;
regulator-ramp-delay = <50000>;
};
};
};
* Samsung S2MPS11 Voltage and Current Regulator * Samsung S2MPS11 and S2MPS14 Voltage and Current Regulator
The Samsung S2MPS11 is a multi-function device which includes voltage and The Samsung S2MPS11 is a multi-function device which includes voltage and
current regulators, RTC, charger controller and other sub-blocks. It is current regulators, RTC, charger controller and other sub-blocks. It is
...@@ -7,7 +7,7 @@ interfaced to the host controller using an I2C interface. Each sub-block is ...@@ -7,7 +7,7 @@ interfaced to the host controller using an I2C interface. Each sub-block is
addressed by the host system using different I2C slave addresses. addressed by the host system using different I2C slave addresses.
Required properties: Required properties:
- compatible: Should be "samsung,s2mps11-pmic". - compatible: Should be "samsung,s2mps11-pmic" or "samsung,s2mps14-pmic".
- reg: Specifies the I2C slave address of the pmic block. It should be 0x66. - reg: Specifies the I2C slave address of the pmic block. It should be 0x66.
Optional properties: Optional properties:
...@@ -59,10 +59,14 @@ supports. Note: The 'n' in LDOn and BUCKn represents the LDO or BUCK number ...@@ -59,10 +59,14 @@ supports. Note: The 'n' in LDOn and BUCKn represents the LDO or BUCK number
as per the datasheet of s2mps11. as per the datasheet of s2mps11.
- LDOn - LDOn
- valid values for n are 1 to 38 - valid values for n are:
- S2MPS11: 1 to 38
- S2MPS14: 1 to 25
- Example: LDO1, LD02, LDO28 - Example: LDO1, LD02, LDO28
- BUCKn - BUCKn
- valid values for n are 1 to 10. - valid values for n are:
- S2MPS11: 1 to 10
- S2MPS14: 1 to 5
- Example: BUCK1, BUCK2, BUCK9 - Example: BUCK1, BUCK2, BUCK9
Example: Example:
......
...@@ -11,7 +11,7 @@ Required properties: ...@@ -11,7 +11,7 @@ Required properties:
- #interrupt-cells: the number of cells to describe an IRQ, this should be 2. - #interrupt-cells: the number of cells to describe an IRQ, this should be 2.
The first cell is the IRQ number. The first cell is the IRQ number.
The second cell is the flags, encoded as the trigger masks from The second cell is the flags, encoded as the trigger masks from
Documentation/devicetree/bindings/interrupts.txt Documentation/devicetree/bindings/interrupt-controller/interrupts.txt
- regulators: This is the list of child nodes that specify the regulator - regulators: This is the list of child nodes that specify the regulator
initialization data for defined regulators. Not all regulators for the given initialization data for defined regulators. Not all regulators for the given
device need to be present. The definition for each of these nodes is defined device need to be present. The definition for each of these nodes is defined
......
...@@ -8,8 +8,12 @@ Required properties: ...@@ -8,8 +8,12 @@ Required properties:
Optional properties: Optional properties:
- enable-gpio : GPIO to use to enable/disable the regulator. - enable-gpio : GPIO to use to enable/disable the regulator.
- gpios : GPIO group used to control voltage. - gpios : GPIO group used to control voltage.
- gpios-states : gpios pin's initial states array. 0: LOW, 1: HIGH.
defualt is LOW if nothing is specified.
- startup-delay-us : Startup time in microseconds. - startup-delay-us : Startup time in microseconds.
- enable-active-high : Polarity of GPIO is active high (default is low). - enable-active-high : Polarity of GPIO is active high (default is low).
- regulator-type : Specifies what is being regulated, must be either
"voltage" or "current", defaults to current.
Any property defined as part of the core regulator binding defined in Any property defined as part of the core regulator binding defined in
regulator.txt can also be used. regulator.txt can also be used.
......
PFUZE100 family of regulators PFUZE100 family of regulators
Required properties: Required properties:
- compatible: "fsl,pfuze100" - compatible: "fsl,pfuze100" or "fsl,pfuze200"
- reg: I2C slave address - reg: I2C slave address
Required child node: Required child node:
...@@ -10,11 +10,14 @@ Required child node: ...@@ -10,11 +10,14 @@ Required child node:
Documentation/devicetree/bindings/regulator/regulator.txt. Documentation/devicetree/bindings/regulator/regulator.txt.
The valid names for regulators are: The valid names for regulators are:
--PFUZE100
sw1ab,sw1c,sw2,sw3a,sw3b,sw4,swbst,vsnvs,vrefddr,vgen1~vgen6 sw1ab,sw1c,sw2,sw3a,sw3b,sw4,swbst,vsnvs,vrefddr,vgen1~vgen6
--PFUZE200
sw1ab,sw2,sw3a,sw3b,swbst,vsnvs,vrefddr,vgen1~vgen6
Each regulator is defined using the standard binding for regulators. Each regulator is defined using the standard binding for regulators.
Example: Example 1: PFUZE100
pmic: pfuze100@08 { pmic: pfuze100@08 {
compatible = "fsl,pfuze100"; compatible = "fsl,pfuze100";
...@@ -113,3 +116,92 @@ Example: ...@@ -113,3 +116,92 @@ Example:
}; };
}; };
}; };
Example 2: PFUZE200
pmic: pfuze200@08 {
compatible = "fsl,pfuze200";
reg = <0x08>;
regulators {
sw1a_reg: sw1ab {
regulator-min-microvolt = <300000>;
regulator-max-microvolt = <1875000>;
regulator-boot-on;
regulator-always-on;
regulator-ramp-delay = <6250>;
};
sw2_reg: sw2 {
regulator-min-microvolt = <800000>;
regulator-max-microvolt = <3300000>;
regulator-boot-on;
regulator-always-on;
};
sw3a_reg: sw3a {
regulator-min-microvolt = <400000>;
regulator-max-microvolt = <1975000>;
regulator-boot-on;
regulator-always-on;
};
sw3b_reg: sw3b {
regulator-min-microvolt = <400000>;
regulator-max-microvolt = <1975000>;
regulator-boot-on;
regulator-always-on;
};
swbst_reg: swbst {
regulator-min-microvolt = <5000000>;
regulator-max-microvolt = <5150000>;
};
snvs_reg: vsnvs {
regulator-min-microvolt = <1000000>;
regulator-max-microvolt = <3000000>;
regulator-boot-on;
regulator-always-on;
};
vref_reg: vrefddr {
regulator-boot-on;
regulator-always-on;
};
vgen1_reg: vgen1 {
regulator-min-microvolt = <800000>;
regulator-max-microvolt = <1550000>;
};
vgen2_reg: vgen2 {
regulator-min-microvolt = <800000>;
regulator-max-microvolt = <1550000>;
};
vgen3_reg: vgen3 {
regulator-min-microvolt = <1800000>;
regulator-max-microvolt = <3300000>;
};
vgen4_reg: vgen4 {
regulator-min-microvolt = <1800000>;
regulator-max-microvolt = <3300000>;
regulator-always-on;
};
vgen5_reg: vgen5 {
regulator-min-microvolt = <1800000>;
regulator-max-microvolt = <3300000>;
regulator-always-on;
};
vgen6_reg: vgen6 {
regulator-min-microvolt = <1800000>;
regulator-max-microvolt = <3300000>;
regulator-always-on;
};
};
};
...@@ -69,13 +69,16 @@ sub-node should be of the format as listed below. ...@@ -69,13 +69,16 @@ sub-node should be of the format as listed below.
}; };
}; };
The above regulator entries are defined in regulator bindings documentation The above regulator entries are defined in regulator bindings documentation
except op_mode description. except these properties:
- op_mode: describes the different operating modes of the LDO's with - op_mode: describes the different operating modes of the LDO's with
power mode change in SOC. The different possible values are, power mode change in SOC. The different possible values are,
0 - always off mode 0 - always off mode
1 - on in normal mode 1 - on in normal mode
2 - low power mode 2 - low power mode
3 - suspend mode 3 - suspend mode
- s5m8767,pmic-ext-control-gpios: (optional) GPIO specifier for one
GPIO controlling this regulator (enable/disable); This is
valid only for buck9.
The following are the names of the regulators that the s5m8767 pmic block The following are the names of the regulators that the s5m8767 pmic block
supports. Note: The 'n' in LDOn and BUCKn represents the LDO or BUCK number supports. Note: The 'n' in LDOn and BUCKn represents the LDO or BUCK number
...@@ -148,5 +151,13 @@ Example: ...@@ -148,5 +151,13 @@ Example:
regulator-always-on; regulator-always-on;
regulator-boot-on; regulator-boot-on;
}; };
vemmc_reg: BUCK9 {
regulator-name = "VMEM_VDD_2.8V";
regulator-min-microvolt = <2800000>;
regulator-max-microvolt = <2800000>;
op_mode = <3>; /* Standby Mode */
s5m8767,pmic-ext-control-gpios = <&gpk0 2 0>;
};
}; };
}; };
...@@ -4,10 +4,14 @@ Required Properties: ...@@ -4,10 +4,14 @@ Required Properties:
- compatible: Should be one of: - compatible: Should be one of:
- "ti,abb-v1" for older SoCs like OMAP3 - "ti,abb-v1" for older SoCs like OMAP3
- "ti,abb-v2" for newer SoCs like OMAP4, OMAP5 - "ti,abb-v2" for newer SoCs like OMAP4, OMAP5
- "ti,abb-v3" for a generic definition where setup and control registers are
provided (example: DRA7)
- reg: Address and length of the register set for the device. It contains - reg: Address and length of the register set for the device. It contains
the information of registers in the same order as described by reg-names the information of registers in the same order as described by reg-names
- reg-names: Should contain the reg names - reg-names: Should contain the reg names
- "base-address" - contains base address of ABB module - "base-address" - contains base address of ABB module (ti,abb-v1,ti,abb-v2)
- "control-address" - contains control register address of ABB module (ti,abb-v3)
- "setup-address" - contains setup register address of ABB module (ti,abb-v3)
- "int-address" - contains address of interrupt register for ABB module - "int-address" - contains address of interrupt register for ABB module
(also see Optional properties) (also see Optional properties)
- #address-cell: should be 0 - #address-cell: should be 0
......
...@@ -790,6 +790,32 @@ void * devm_kmalloc(struct device *dev, size_t size, gfp_t gfp) ...@@ -790,6 +790,32 @@ void * devm_kmalloc(struct device *dev, size_t size, gfp_t gfp)
} }
EXPORT_SYMBOL_GPL(devm_kmalloc); EXPORT_SYMBOL_GPL(devm_kmalloc);
/**
* devm_kstrdup - Allocate resource managed space and
* copy an existing string into that.
* @dev: Device to allocate memory for
* @s: the string to duplicate
* @gfp: the GFP mask used in the devm_kmalloc() call when
* allocating memory
* RETURNS:
* Pointer to allocated string on success, NULL on failure.
*/
char *devm_kstrdup(struct device *dev, const char *s, gfp_t gfp)
{
size_t size;
char *buf;
if (!s)
return NULL;
size = strlen(s) + 1;
buf = devm_kmalloc(dev, size, gfp);
if (buf)
memcpy(buf, s, size);
return buf;
}
EXPORT_SYMBOL_GPL(devm_kstrdup);
/** /**
* devm_kfree - Resource-managed kfree * devm_kfree - Resource-managed kfree
* @dev: Device this memory belongs to * @dev: Device this memory belongs to
......
...@@ -26,7 +26,9 @@ ...@@ -26,7 +26,9 @@
#include <linux/mfd/samsung/core.h> #include <linux/mfd/samsung/core.h>
#include <linux/mfd/samsung/irq.h> #include <linux/mfd/samsung/irq.h>
#include <linux/mfd/samsung/rtc.h> #include <linux/mfd/samsung/rtc.h>
#include <linux/mfd/samsung/s2mpa01.h>
#include <linux/mfd/samsung/s2mps11.h> #include <linux/mfd/samsung/s2mps11.h>
#include <linux/mfd/samsung/s2mps14.h>
#include <linux/mfd/samsung/s5m8763.h> #include <linux/mfd/samsung/s5m8763.h>
#include <linux/mfd/samsung/s5m8767.h> #include <linux/mfd/samsung/s5m8767.h>
#include <linux/regmap.h> #include <linux/regmap.h>
...@@ -69,18 +71,53 @@ static const struct mfd_cell s2mps11_devs[] = { ...@@ -69,18 +71,53 @@ static const struct mfd_cell s2mps11_devs[] = {
} }
}; };
static const struct mfd_cell s2mps14_devs[] = {
{
.name = "s2mps14-pmic",
}, {
.name = "s2mps14-rtc",
}, {
.name = "s2mps14-clk",
}
};
static const struct mfd_cell s2mpa01_devs[] = {
{
.name = "s2mpa01-pmic",
},
};
#ifdef CONFIG_OF #ifdef CONFIG_OF
static struct of_device_id sec_dt_match[] = { static struct of_device_id sec_dt_match[] = {
{ .compatible = "samsung,s5m8767-pmic", { .compatible = "samsung,s5m8767-pmic",
.data = (void *)S5M8767X, .data = (void *)S5M8767X,
}, }, {
{ .compatible = "samsung,s2mps11-pmic", .compatible = "samsung,s2mps11-pmic",
.data = (void *)S2MPS11X, .data = (void *)S2MPS11X,
}, {
.compatible = "samsung,s2mps14-pmic",
.data = (void *)S2MPS14X,
}, {
.compatible = "samsung,s2mpa01-pmic",
.data = (void *)S2MPA01,
}, {
/* Sentinel */
}, },
{},
}; };
#endif #endif
static bool s2mpa01_volatile(struct device *dev, unsigned int reg)
{
switch (reg) {
case S2MPA01_REG_INT1M:
case S2MPA01_REG_INT2M:
case S2MPA01_REG_INT3M:
return false;
default:
return true;
}
}
static bool s2mps11_volatile(struct device *dev, unsigned int reg) static bool s2mps11_volatile(struct device *dev, unsigned int reg)
{ {
switch (reg) { switch (reg) {
...@@ -111,6 +148,15 @@ static const struct regmap_config sec_regmap_config = { ...@@ -111,6 +148,15 @@ static const struct regmap_config sec_regmap_config = {
.val_bits = 8, .val_bits = 8,
}; };
static const struct regmap_config s2mpa01_regmap_config = {
.reg_bits = 8,
.val_bits = 8,
.max_register = S2MPA01_REG_LDO_OVCB4,
.volatile_reg = s2mpa01_volatile,
.cache_type = REGCACHE_FLAT,
};
static const struct regmap_config s2mps11_regmap_config = { static const struct regmap_config s2mps11_regmap_config = {
.reg_bits = 8, .reg_bits = 8,
.val_bits = 8, .val_bits = 8,
...@@ -120,6 +166,15 @@ static const struct regmap_config s2mps11_regmap_config = { ...@@ -120,6 +166,15 @@ static const struct regmap_config s2mps11_regmap_config = {
.cache_type = REGCACHE_FLAT, .cache_type = REGCACHE_FLAT,
}; };
static const struct regmap_config s2mps14_regmap_config = {
.reg_bits = 8,
.val_bits = 8,
.max_register = S2MPS14_REG_LDODSCH3,
.volatile_reg = s2mps11_volatile,
.cache_type = REGCACHE_FLAT,
};
static const struct regmap_config s5m8763_regmap_config = { static const struct regmap_config s5m8763_regmap_config = {
.reg_bits = 8, .reg_bits = 8,
.val_bits = 8, .val_bits = 8,
...@@ -138,9 +193,18 @@ static const struct regmap_config s5m8767_regmap_config = { ...@@ -138,9 +193,18 @@ static const struct regmap_config s5m8767_regmap_config = {
.cache_type = REGCACHE_FLAT, .cache_type = REGCACHE_FLAT,
}; };
static const struct regmap_config sec_rtc_regmap_config = { static const struct regmap_config s5m_rtc_regmap_config = {
.reg_bits = 8,
.val_bits = 8,
.max_register = SEC_RTC_REG_MAX,
};
static const struct regmap_config s2mps14_rtc_regmap_config = {
.reg_bits = 8, .reg_bits = 8,
.val_bits = 8, .val_bits = 8,
.max_register = S2MPS_RTC_REG_MAX,
}; };
#ifdef CONFIG_OF #ifdef CONFIG_OF
...@@ -180,24 +244,24 @@ static struct sec_platform_data *sec_pmic_i2c_parse_dt_pdata( ...@@ -180,24 +244,24 @@ static struct sec_platform_data *sec_pmic_i2c_parse_dt_pdata(
} }
#endif #endif
static inline int sec_i2c_get_driver_data(struct i2c_client *i2c, static inline unsigned long sec_i2c_get_driver_data(struct i2c_client *i2c,
const struct i2c_device_id *id) const struct i2c_device_id *id)
{ {
#ifdef CONFIG_OF #ifdef CONFIG_OF
if (i2c->dev.of_node) { if (i2c->dev.of_node) {
const struct of_device_id *match; const struct of_device_id *match;
match = of_match_node(sec_dt_match, i2c->dev.of_node); match = of_match_node(sec_dt_match, i2c->dev.of_node);
return (int)match->data; return (unsigned long)match->data;
} }
#endif #endif
return (int)id->driver_data; return id->driver_data;
} }
static int sec_pmic_probe(struct i2c_client *i2c, static int sec_pmic_probe(struct i2c_client *i2c,
const struct i2c_device_id *id) const struct i2c_device_id *id)
{ {
struct sec_platform_data *pdata = dev_get_platdata(&i2c->dev); struct sec_platform_data *pdata = dev_get_platdata(&i2c->dev);
const struct regmap_config *regmap; const struct regmap_config *regmap, *regmap_rtc;
struct sec_pmic_dev *sec_pmic; struct sec_pmic_dev *sec_pmic;
int ret; int ret;
...@@ -229,17 +293,34 @@ static int sec_pmic_probe(struct i2c_client *i2c, ...@@ -229,17 +293,34 @@ static int sec_pmic_probe(struct i2c_client *i2c,
} }
switch (sec_pmic->device_type) { switch (sec_pmic->device_type) {
case S2MPA01:
regmap = &s2mpa01_regmap_config;
break;
case S2MPS11X: case S2MPS11X:
regmap = &s2mps11_regmap_config; regmap = &s2mps11_regmap_config;
/*
* The rtc-s5m driver does not support S2MPS11 and there
* is no mfd_cell for S2MPS11 RTC device.
* However we must pass something to devm_regmap_init_i2c()
* so use S5M-like regmap config even though it wouldn't work.
*/
regmap_rtc = &s5m_rtc_regmap_config;
break;
case S2MPS14X:
regmap = &s2mps14_regmap_config;
regmap_rtc = &s2mps14_rtc_regmap_config;
break; break;
case S5M8763X: case S5M8763X:
regmap = &s5m8763_regmap_config; regmap = &s5m8763_regmap_config;
regmap_rtc = &s5m_rtc_regmap_config;
break; break;
case S5M8767X: case S5M8767X:
regmap = &s5m8767_regmap_config; regmap = &s5m8767_regmap_config;
regmap_rtc = &s5m_rtc_regmap_config;
break; break;
default: default:
regmap = &sec_regmap_config; regmap = &sec_regmap_config;
regmap_rtc = &s5m_rtc_regmap_config;
break; break;
} }
...@@ -252,10 +333,13 @@ static int sec_pmic_probe(struct i2c_client *i2c, ...@@ -252,10 +333,13 @@ static int sec_pmic_probe(struct i2c_client *i2c,
} }
sec_pmic->rtc = i2c_new_dummy(i2c->adapter, RTC_I2C_ADDR); sec_pmic->rtc = i2c_new_dummy(i2c->adapter, RTC_I2C_ADDR);
if (!sec_pmic->rtc) {
dev_err(&i2c->dev, "Failed to allocate I2C for RTC\n");
return -ENODEV;
}
i2c_set_clientdata(sec_pmic->rtc, sec_pmic); i2c_set_clientdata(sec_pmic->rtc, sec_pmic);
sec_pmic->regmap_rtc = devm_regmap_init_i2c(sec_pmic->rtc, sec_pmic->regmap_rtc = devm_regmap_init_i2c(sec_pmic->rtc, regmap_rtc);
&sec_rtc_regmap_config);
if (IS_ERR(sec_pmic->regmap_rtc)) { if (IS_ERR(sec_pmic->regmap_rtc)) {
ret = PTR_ERR(sec_pmic->regmap_rtc); ret = PTR_ERR(sec_pmic->regmap_rtc);
dev_err(&i2c->dev, "Failed to allocate RTC register map: %d\n", dev_err(&i2c->dev, "Failed to allocate RTC register map: %d\n",
...@@ -283,10 +367,18 @@ static int sec_pmic_probe(struct i2c_client *i2c, ...@@ -283,10 +367,18 @@ static int sec_pmic_probe(struct i2c_client *i2c,
ret = mfd_add_devices(sec_pmic->dev, -1, s5m8767_devs, ret = mfd_add_devices(sec_pmic->dev, -1, s5m8767_devs,
ARRAY_SIZE(s5m8767_devs), NULL, 0, NULL); ARRAY_SIZE(s5m8767_devs), NULL, 0, NULL);
break; break;
case S2MPA01:
ret = mfd_add_devices(sec_pmic->dev, -1, s2mpa01_devs,
ARRAY_SIZE(s2mpa01_devs), NULL, 0, NULL);
break;
case S2MPS11X: case S2MPS11X:
ret = mfd_add_devices(sec_pmic->dev, -1, s2mps11_devs, ret = mfd_add_devices(sec_pmic->dev, -1, s2mps11_devs,
ARRAY_SIZE(s2mps11_devs), NULL, 0, NULL); ARRAY_SIZE(s2mps11_devs), NULL, 0, NULL);
break; break;
case S2MPS14X:
ret = mfd_add_devices(sec_pmic->dev, -1, s2mps14_devs,
ARRAY_SIZE(s2mps14_devs), NULL, 0, NULL);
break;
default: default:
/* If this happens the probe function is problem */ /* If this happens the probe function is problem */
BUG(); BUG();
......
/* /*
* sec-irq.c * sec-irq.c
* *
* Copyright (c) 2011 Samsung Electronics Co., Ltd * Copyright (c) 2011-2014 Samsung Electronics Co., Ltd
* http://www.samsung.com * http://www.samsung.com
* *
* This program is free software; you can redistribute it and/or modify it * This program is free software; you can redistribute it and/or modify it
...@@ -19,6 +19,7 @@ ...@@ -19,6 +19,7 @@
#include <linux/mfd/samsung/core.h> #include <linux/mfd/samsung/core.h>
#include <linux/mfd/samsung/irq.h> #include <linux/mfd/samsung/irq.h>
#include <linux/mfd/samsung/s2mps11.h> #include <linux/mfd/samsung/s2mps11.h>
#include <linux/mfd/samsung/s2mps14.h>
#include <linux/mfd/samsung/s5m8763.h> #include <linux/mfd/samsung/s5m8763.h>
#include <linux/mfd/samsung/s5m8767.h> #include <linux/mfd/samsung/s5m8767.h>
...@@ -59,13 +60,13 @@ static const struct regmap_irq s2mps11_irqs[] = { ...@@ -59,13 +60,13 @@ static const struct regmap_irq s2mps11_irqs[] = {
.reg_offset = 1, .reg_offset = 1,
.mask = S2MPS11_IRQ_RTC60S_MASK, .mask = S2MPS11_IRQ_RTC60S_MASK,
}, },
[S2MPS11_IRQ_RTCA1] = { [S2MPS11_IRQ_RTCA0] = {
.reg_offset = 1, .reg_offset = 1,
.mask = S2MPS11_IRQ_RTCA1_MASK, .mask = S2MPS11_IRQ_RTCA0_MASK,
}, },
[S2MPS11_IRQ_RTCA2] = { [S2MPS11_IRQ_RTCA1] = {
.reg_offset = 1, .reg_offset = 1,
.mask = S2MPS11_IRQ_RTCA2_MASK, .mask = S2MPS11_IRQ_RTCA1_MASK,
}, },
[S2MPS11_IRQ_SMPL] = { [S2MPS11_IRQ_SMPL] = {
.reg_offset = 1, .reg_offset = 1,
...@@ -89,6 +90,76 @@ static const struct regmap_irq s2mps11_irqs[] = { ...@@ -89,6 +90,76 @@ static const struct regmap_irq s2mps11_irqs[] = {
}, },
}; };
static const struct regmap_irq s2mps14_irqs[] = {
[S2MPS14_IRQ_PWRONF] = {
.reg_offset = 0,
.mask = S2MPS11_IRQ_PWRONF_MASK,
},
[S2MPS14_IRQ_PWRONR] = {
.reg_offset = 0,
.mask = S2MPS11_IRQ_PWRONR_MASK,
},
[S2MPS14_IRQ_JIGONBF] = {
.reg_offset = 0,
.mask = S2MPS11_IRQ_JIGONBF_MASK,
},
[S2MPS14_IRQ_JIGONBR] = {
.reg_offset = 0,
.mask = S2MPS11_IRQ_JIGONBR_MASK,
},
[S2MPS14_IRQ_ACOKBF] = {
.reg_offset = 0,
.mask = S2MPS11_IRQ_ACOKBF_MASK,
},
[S2MPS14_IRQ_ACOKBR] = {
.reg_offset = 0,
.mask = S2MPS11_IRQ_ACOKBR_MASK,
},
[S2MPS14_IRQ_PWRON1S] = {
.reg_offset = 0,
.mask = S2MPS11_IRQ_PWRON1S_MASK,
},
[S2MPS14_IRQ_MRB] = {
.reg_offset = 0,
.mask = S2MPS11_IRQ_MRB_MASK,
},
[S2MPS14_IRQ_RTC60S] = {
.reg_offset = 1,
.mask = S2MPS11_IRQ_RTC60S_MASK,
},
[S2MPS14_IRQ_RTCA1] = {
.reg_offset = 1,
.mask = S2MPS11_IRQ_RTCA1_MASK,
},
[S2MPS14_IRQ_RTCA0] = {
.reg_offset = 1,
.mask = S2MPS11_IRQ_RTCA0_MASK,
},
[S2MPS14_IRQ_SMPL] = {
.reg_offset = 1,
.mask = S2MPS11_IRQ_SMPL_MASK,
},
[S2MPS14_IRQ_RTC1S] = {
.reg_offset = 1,
.mask = S2MPS11_IRQ_RTC1S_MASK,
},
[S2MPS14_IRQ_WTSR] = {
.reg_offset = 1,
.mask = S2MPS11_IRQ_WTSR_MASK,
},
[S2MPS14_IRQ_INT120C] = {
.reg_offset = 2,
.mask = S2MPS11_IRQ_INT120C_MASK,
},
[S2MPS14_IRQ_INT140C] = {
.reg_offset = 2,
.mask = S2MPS11_IRQ_INT140C_MASK,
},
[S2MPS14_IRQ_TSD] = {
.reg_offset = 2,
.mask = S2MPS14_IRQ_TSD_MASK,
},
};
static const struct regmap_irq s5m8767_irqs[] = { static const struct regmap_irq s5m8767_irqs[] = {
[S5M8767_IRQ_PWRR] = { [S5M8767_IRQ_PWRR] = {
...@@ -246,6 +317,16 @@ static const struct regmap_irq_chip s2mps11_irq_chip = { ...@@ -246,6 +317,16 @@ static const struct regmap_irq_chip s2mps11_irq_chip = {
.ack_base = S2MPS11_REG_INT1, .ack_base = S2MPS11_REG_INT1,
}; };
static const struct regmap_irq_chip s2mps14_irq_chip = {
.name = "s2mps14",
.irqs = s2mps14_irqs,
.num_irqs = ARRAY_SIZE(s2mps14_irqs),
.num_regs = 3,
.status_base = S2MPS14_REG_INT1,
.mask_base = S2MPS14_REG_INT1M,
.ack_base = S2MPS14_REG_INT1,
};
static const struct regmap_irq_chip s5m8767_irq_chip = { static const struct regmap_irq_chip s5m8767_irq_chip = {
.name = "s5m8767", .name = "s5m8767",
.irqs = s5m8767_irqs, .irqs = s5m8767_irqs,
...@@ -297,6 +378,12 @@ int sec_irq_init(struct sec_pmic_dev *sec_pmic) ...@@ -297,6 +378,12 @@ int sec_irq_init(struct sec_pmic_dev *sec_pmic)
sec_pmic->irq_base, &s2mps11_irq_chip, sec_pmic->irq_base, &s2mps11_irq_chip,
&sec_pmic->irq_data); &sec_pmic->irq_data);
break; break;
case S2MPS14X:
ret = regmap_add_irq_chip(sec_pmic->regmap_pmic, sec_pmic->irq,
IRQF_TRIGGER_FALLING | IRQF_ONESHOT,
sec_pmic->irq_base, &s2mps14_irq_chip,
&sec_pmic->irq_data);
break;
default: default:
dev_err(sec_pmic->dev, "Unknown device type %d\n", dev_err(sec_pmic->dev, "Unknown device type %d\n",
sec_pmic->device_type); sec_pmic->device_type);
......
...@@ -903,6 +903,38 @@ struct device_node *of_find_node_by_phandle(phandle handle) ...@@ -903,6 +903,38 @@ struct device_node *of_find_node_by_phandle(phandle handle)
} }
EXPORT_SYMBOL(of_find_node_by_phandle); EXPORT_SYMBOL(of_find_node_by_phandle);
/**
* of_property_count_elems_of_size - Count the number of elements in a property
*
* @np: device node from which the property value is to be read.
* @propname: name of the property to be searched.
* @elem_size: size of the individual element
*
* Search for a property in a device node and count the number of elements of
* size elem_size in it. Returns number of elements on sucess, -EINVAL if the
* property does not exist or its length does not match a multiple of elem_size
* and -ENODATA if the property does not have a value.
*/
int of_property_count_elems_of_size(const struct device_node *np,
const char *propname, int elem_size)
{
struct property *prop = of_find_property(np, propname, NULL);
if (!prop)
return -EINVAL;
if (!prop->value)
return -ENODATA;
if (prop->length % elem_size != 0) {
pr_err("size of %s in node %s is not a multiple of %d\n",
propname, np->full_name, elem_size);
return -EINVAL;
}
return prop->length / elem_size;
}
EXPORT_SYMBOL_GPL(of_property_count_elems_of_size);
/** /**
* of_find_property_value_of_size * of_find_property_value_of_size
* *
......
...@@ -310,10 +310,8 @@ static int pm800_regulator_probe(struct platform_device *pdev) ...@@ -310,10 +310,8 @@ static int pm800_regulator_probe(struct platform_device *pdev)
pm800_data = devm_kzalloc(&pdev->dev, sizeof(*pm800_data), pm800_data = devm_kzalloc(&pdev->dev, sizeof(*pm800_data),
GFP_KERNEL); GFP_KERNEL);
if (!pm800_data) { if (!pm800_data)
dev_err(&pdev->dev, "Failed to allocate pm800_regualtors");
return -ENOMEM; return -ENOMEM;
}
pm800_data->map = chip->subchip->regmap_power; pm800_data->map = chip->subchip->regmap_power;
pm800_data->chip = chip; pm800_data->chip = chip;
......
...@@ -322,7 +322,7 @@ static int pm8607_regulator_dt_init(struct platform_device *pdev, ...@@ -322,7 +322,7 @@ static int pm8607_regulator_dt_init(struct platform_device *pdev,
nproot = of_node_get(pdev->dev.parent->of_node); nproot = of_node_get(pdev->dev.parent->of_node);
if (!nproot) if (!nproot)
return -ENODEV; return -ENODEV;
nproot = of_find_node_by_name(nproot, "regulators"); nproot = of_get_child_by_name(nproot, "regulators");
if (!nproot) { if (!nproot) {
dev_err(&pdev->dev, "failed to find regulators node\n"); dev_err(&pdev->dev, "failed to find regulators node\n");
return -ENODEV; return -ENODEV;
......
...@@ -139,6 +139,14 @@ config REGULATOR_AS3722 ...@@ -139,6 +139,14 @@ config REGULATOR_AS3722
AS3722 PMIC. This will enable support for all the software AS3722 PMIC. This will enable support for all the software
controllable DCDC/LDO regulators. controllable DCDC/LDO regulators.
config REGULATOR_BCM590XX
tristate "Broadcom BCM590xx PMU Regulators"
depends on MFD_BCM590XX
help
This driver provides support for the voltage regulators on the
BCM590xx PMUs. This will enable support for the software
controllable LDO/Switching regulators.
config REGULATOR_DA903X config REGULATOR_DA903X
tristate "Dialog Semiconductor DA9030/DA9034 regulators" tristate "Dialog Semiconductor DA9030/DA9034 regulators"
depends on PMIC_DA903X depends on PMIC_DA903X
...@@ -399,12 +407,12 @@ config REGULATOR_PCF50633 ...@@ -399,12 +407,12 @@ config REGULATOR_PCF50633
on PCF50633 on PCF50633
config REGULATOR_PFUZE100 config REGULATOR_PFUZE100
tristate "Freescale PFUZE100 regulator driver" tristate "Freescale PFUZE100/PFUZE200 regulator driver"
depends on I2C depends on I2C
select REGMAP_I2C select REGMAP_I2C
help help
Say y here to support the regulators found on the Freescale PFUZE100 Say y here to support the regulators found on the Freescale
PMIC. PFUZE100/PFUZE200 PMIC.
config REGULATOR_RC5T583 config REGULATOR_RC5T583
tristate "RICOH RC5T583 Power regulators" tristate "RICOH RC5T583 Power regulators"
...@@ -416,13 +424,21 @@ config REGULATOR_RC5T583 ...@@ -416,13 +424,21 @@ config REGULATOR_RC5T583
through regulator interface. The device supports multiple DCDC/LDO through regulator interface. The device supports multiple DCDC/LDO
outputs which can be controlled by i2c communication. outputs which can be controlled by i2c communication.
config REGULATOR_S2MPA01
tristate "Samsung S2MPA01 voltage regulator"
depends on MFD_SEC_CORE
help
This driver controls Samsung S2MPA01 voltage output regulator
via I2C bus. S2MPA01 has 10 Bucks and 26 LDO outputs.
config REGULATOR_S2MPS11 config REGULATOR_S2MPS11
tristate "Samsung S2MPS11 voltage regulator" tristate "Samsung S2MPS11/S2MPS14 voltage regulator"
depends on MFD_SEC_CORE depends on MFD_SEC_CORE
help help
This driver supports a Samsung S2MPS11 voltage output regulator This driver supports a Samsung S2MPS11/S2MPS14 voltage output
via I2C bus. S2MPS11 is comprised of high efficient Buck converters regulator via I2C bus. The chip is comprised of high efficient Buck
including Dual-Phase Buck converter, Buck-Boost converter, various LDOs. converters including Dual-Phase Buck converter, Buck-Boost converter,
various LDOs.
config REGULATOR_S5M8767 config REGULATOR_S5M8767
tristate "Samsung S5M8767A voltage regulator" tristate "Samsung S5M8767A voltage regulator"
...@@ -432,6 +448,12 @@ config REGULATOR_S5M8767 ...@@ -432,6 +448,12 @@ config REGULATOR_S5M8767
via I2C bus. S5M8767A have 9 Bucks and 28 LDOs output and via I2C bus. S5M8767A have 9 Bucks and 28 LDOs output and
supports DVS mode with 8bits of output voltage control. supports DVS mode with 8bits of output voltage control.
config REGULATOR_ST_PWM
tristate "STMicroelectronics PWM voltage regulator"
depends on ARCH_STI
help
This driver supports ST's PWM controlled voltage regulators.
config REGULATOR_TI_ABB config REGULATOR_TI_ABB
tristate "TI Adaptive Body Bias on-chip LDO" tristate "TI Adaptive Body Bias on-chip LDO"
depends on ARCH_OMAP depends on ARCH_OMAP
...@@ -513,6 +535,15 @@ config REGULATOR_TPS65217 ...@@ -513,6 +535,15 @@ config REGULATOR_TPS65217
voltage regulators. It supports software based voltage control voltage regulators. It supports software based voltage control
for different voltage domains for different voltage domains
config REGULATOR_TPS65218
tristate "TI TPS65218 Power regulators"
depends on MFD_TPS65218 && OF
help
This driver supports TPS65218 voltage regulator chips. TPS65218
provides six step-down converters and one general-purpose LDO
voltage regulators. It supports software based voltage control
for different voltage domains
config REGULATOR_TPS6524X config REGULATOR_TPS6524X
tristate "TI TPS6524X Power regulators" tristate "TI TPS6524X Power regulators"
depends on SPI depends on SPI
......
...@@ -20,6 +20,7 @@ obj-$(CONFIG_REGULATOR_ANATOP) += anatop-regulator.o ...@@ -20,6 +20,7 @@ obj-$(CONFIG_REGULATOR_ANATOP) += anatop-regulator.o
obj-$(CONFIG_REGULATOR_ARIZONA) += arizona-micsupp.o arizona-ldo1.o obj-$(CONFIG_REGULATOR_ARIZONA) += arizona-micsupp.o arizona-ldo1.o
obj-$(CONFIG_REGULATOR_AS3711) += as3711-regulator.o obj-$(CONFIG_REGULATOR_AS3711) += as3711-regulator.o
obj-$(CONFIG_REGULATOR_AS3722) += as3722-regulator.o obj-$(CONFIG_REGULATOR_AS3722) += as3722-regulator.o
obj-$(CONFIG_REGULATOR_BCM590XX) += bcm590xx-regulator.o
obj-$(CONFIG_REGULATOR_DA903X) += da903x.o obj-$(CONFIG_REGULATOR_DA903X) += da903x.o
obj-$(CONFIG_REGULATOR_DA9052) += da9052-regulator.o obj-$(CONFIG_REGULATOR_DA9052) += da9052-regulator.o
obj-$(CONFIG_REGULATOR_DA9055) += da9055-regulator.o obj-$(CONFIG_REGULATOR_DA9055) += da9055-regulator.o
...@@ -57,8 +58,10 @@ obj-$(CONFIG_REGULATOR_TPS51632) += tps51632-regulator.o ...@@ -57,8 +58,10 @@ obj-$(CONFIG_REGULATOR_TPS51632) += tps51632-regulator.o
obj-$(CONFIG_REGULATOR_PCAP) += pcap-regulator.o obj-$(CONFIG_REGULATOR_PCAP) += pcap-regulator.o
obj-$(CONFIG_REGULATOR_PCF50633) += pcf50633-regulator.o obj-$(CONFIG_REGULATOR_PCF50633) += pcf50633-regulator.o
obj-$(CONFIG_REGULATOR_RC5T583) += rc5t583-regulator.o obj-$(CONFIG_REGULATOR_RC5T583) += rc5t583-regulator.o
obj-$(CONFIG_REGULATOR_S2MPA01) += s2mpa01.o
obj-$(CONFIG_REGULATOR_S2MPS11) += s2mps11.o obj-$(CONFIG_REGULATOR_S2MPS11) += s2mps11.o
obj-$(CONFIG_REGULATOR_S5M8767) += s5m8767.o obj-$(CONFIG_REGULATOR_S5M8767) += s5m8767.o
obj-$(CONFIG_REGULATOR_ST_PWM) += st-pwm.o
obj-$(CONFIG_REGULATOR_STW481X_VMMC) += stw481x-vmmc.o obj-$(CONFIG_REGULATOR_STW481X_VMMC) += stw481x-vmmc.o
obj-$(CONFIG_REGULATOR_TI_ABB) += ti-abb-regulator.o obj-$(CONFIG_REGULATOR_TI_ABB) += ti-abb-regulator.o
obj-$(CONFIG_REGULATOR_TPS6105X) += tps6105x-regulator.o obj-$(CONFIG_REGULATOR_TPS6105X) += tps6105x-regulator.o
...@@ -67,6 +70,7 @@ obj-$(CONFIG_REGULATOR_TPS65023) += tps65023-regulator.o ...@@ -67,6 +70,7 @@ obj-$(CONFIG_REGULATOR_TPS65023) += tps65023-regulator.o
obj-$(CONFIG_REGULATOR_TPS6507X) += tps6507x-regulator.o obj-$(CONFIG_REGULATOR_TPS6507X) += tps6507x-regulator.o
obj-$(CONFIG_REGULATOR_TPS65090) += tps65090-regulator.o obj-$(CONFIG_REGULATOR_TPS65090) += tps65090-regulator.o
obj-$(CONFIG_REGULATOR_TPS65217) += tps65217-regulator.o obj-$(CONFIG_REGULATOR_TPS65217) += tps65217-regulator.o
obj-$(CONFIG_REGULATOR_TPS65218) += tps65218-regulator.o
obj-$(CONFIG_REGULATOR_TPS6524X) += tps6524x-regulator.o obj-$(CONFIG_REGULATOR_TPS6524X) += tps6524x-regulator.o
obj-$(CONFIG_REGULATOR_TPS6586X) += tps6586x-regulator.o obj-$(CONFIG_REGULATOR_TPS6586X) += tps6586x-regulator.o
obj-$(CONFIG_REGULATOR_TPS65910) += tps65910-regulator.o obj-$(CONFIG_REGULATOR_TPS65910) += tps65910-regulator.o
......
...@@ -99,6 +99,7 @@ static int aat2870_ldo_is_enabled(struct regulator_dev *rdev) ...@@ -99,6 +99,7 @@ static int aat2870_ldo_is_enabled(struct regulator_dev *rdev)
static struct regulator_ops aat2870_ldo_ops = { static struct regulator_ops aat2870_ldo_ops = {
.list_voltage = regulator_list_voltage_table, .list_voltage = regulator_list_voltage_table,
.map_voltage = regulator_map_voltage_ascend,
.set_voltage_sel = aat2870_ldo_set_voltage_sel, .set_voltage_sel = aat2870_ldo_set_voltage_sel,
.get_voltage_sel = aat2870_ldo_get_voltage_sel, .get_voltage_sel = aat2870_ldo_get_voltage_sel,
.enable = aat2870_ldo_enable, .enable = aat2870_ldo_enable,
......
...@@ -62,7 +62,6 @@ ...@@ -62,7 +62,6 @@
#define ACT8865_VOLTAGE_NUM 64 #define ACT8865_VOLTAGE_NUM 64
struct act8865 { struct act8865 {
struct regulator_dev *rdev[ACT8865_REG_NUM];
struct regmap *regmap; struct regmap *regmap;
}; };
...@@ -213,7 +212,7 @@ static int act8865_pdata_from_dt(struct device *dev, ...@@ -213,7 +212,7 @@ static int act8865_pdata_from_dt(struct device *dev,
struct device_node *np; struct device_node *np;
struct act8865_regulator_data *regulator; struct act8865_regulator_data *regulator;
np = of_find_node_by_name(dev->of_node, "regulators"); np = of_get_child_by_name(dev->of_node, "regulators");
if (!np) { if (!np) {
dev_err(dev, "missing 'regulators' subnode in DT\n"); dev_err(dev, "missing 'regulators' subnode in DT\n");
return -EINVAL; return -EINVAL;
...@@ -221,17 +220,15 @@ static int act8865_pdata_from_dt(struct device *dev, ...@@ -221,17 +220,15 @@ static int act8865_pdata_from_dt(struct device *dev,
matched = of_regulator_match(dev, np, matched = of_regulator_match(dev, np,
act8865_matches, ARRAY_SIZE(act8865_matches)); act8865_matches, ARRAY_SIZE(act8865_matches));
of_node_put(np);
if (matched <= 0) if (matched <= 0)
return matched; return matched;
pdata->regulators = devm_kzalloc(dev, pdata->regulators = devm_kzalloc(dev,
sizeof(struct act8865_regulator_data) * sizeof(struct act8865_regulator_data) *
ARRAY_SIZE(act8865_matches), GFP_KERNEL); ARRAY_SIZE(act8865_matches), GFP_KERNEL);
if (!pdata->regulators) { if (!pdata->regulators)
dev_err(dev, "%s: failed to allocate act8865 registor\n",
__func__);
return -ENOMEM; return -ENOMEM;
}
pdata->num_regulators = matched; pdata->num_regulators = matched;
regulator = pdata->regulators; regulator = pdata->regulators;
...@@ -258,7 +255,7 @@ static inline int act8865_pdata_from_dt(struct device *dev, ...@@ -258,7 +255,7 @@ static inline int act8865_pdata_from_dt(struct device *dev,
static int act8865_pmic_probe(struct i2c_client *client, static int act8865_pmic_probe(struct i2c_client *client,
const struct i2c_device_id *i2c_id) const struct i2c_device_id *i2c_id)
{ {
struct regulator_dev **rdev; struct regulator_dev *rdev;
struct device *dev = &client->dev; struct device *dev = &client->dev;
struct act8865_platform_data *pdata = dev_get_platdata(dev); struct act8865_platform_data *pdata = dev_get_platdata(dev);
struct regulator_config config = { }; struct regulator_config config = { };
...@@ -292,8 +289,6 @@ static int act8865_pmic_probe(struct i2c_client *client, ...@@ -292,8 +289,6 @@ static int act8865_pmic_probe(struct i2c_client *client,
if (!act8865) if (!act8865)
return -ENOMEM; return -ENOMEM;
rdev = act8865->rdev;
act8865->regmap = devm_regmap_init_i2c(client, &act8865_regmap_config); act8865->regmap = devm_regmap_init_i2c(client, &act8865_regmap_config);
if (IS_ERR(act8865->regmap)) { if (IS_ERR(act8865->regmap)) {
error = PTR_ERR(act8865->regmap); error = PTR_ERR(act8865->regmap);
...@@ -313,12 +308,12 @@ static int act8865_pmic_probe(struct i2c_client *client, ...@@ -313,12 +308,12 @@ static int act8865_pmic_probe(struct i2c_client *client,
config.driver_data = act8865; config.driver_data = act8865;
config.regmap = act8865->regmap; config.regmap = act8865->regmap;
rdev[i] = devm_regulator_register(&client->dev, rdev = devm_regulator_register(&client->dev, &act8865_reg[i],
&act8865_reg[i], &config); &config);
if (IS_ERR(rdev[i])) { if (IS_ERR(rdev)) {
dev_err(dev, "failed to register %s\n", dev_err(dev, "failed to register %s\n",
act8865_reg[id].name); act8865_reg[id].name);
return PTR_ERR(rdev[i]); return PTR_ERR(rdev);
} }
} }
......
...@@ -34,6 +34,9 @@ ...@@ -34,6 +34,9 @@
#define LDO_RAMP_UP_UNIT_IN_CYCLES 64 /* 64 cycles per step */ #define LDO_RAMP_UP_UNIT_IN_CYCLES 64 /* 64 cycles per step */
#define LDO_RAMP_UP_FREQ_IN_MHZ 24 /* cycle based on 24M OSC */ #define LDO_RAMP_UP_FREQ_IN_MHZ 24 /* cycle based on 24M OSC */
#define LDO_POWER_GATE 0x00
#define LDO_FET_FULL_ON 0x1f
struct anatop_regulator { struct anatop_regulator {
const char *name; const char *name;
u32 control_reg; u32 control_reg;
...@@ -48,19 +51,10 @@ struct anatop_regulator { ...@@ -48,19 +51,10 @@ struct anatop_regulator {
int max_voltage; int max_voltage;
struct regulator_desc rdesc; struct regulator_desc rdesc;
struct regulator_init_data *initdata; struct regulator_init_data *initdata;
bool bypass;
int sel;
}; };
static int anatop_regmap_set_voltage_sel(struct regulator_dev *reg,
unsigned selector)
{
struct anatop_regulator *anatop_reg = rdev_get_drvdata(reg);
if (!anatop_reg->control_reg)
return -ENOTSUPP;
return regulator_set_voltage_sel_regmap(reg, selector);
}
static int anatop_regmap_set_voltage_time_sel(struct regulator_dev *reg, static int anatop_regmap_set_voltage_time_sel(struct regulator_dev *reg,
unsigned int old_sel, unsigned int old_sel,
unsigned int new_sel) unsigned int new_sel)
...@@ -87,22 +81,99 @@ static int anatop_regmap_set_voltage_time_sel(struct regulator_dev *reg, ...@@ -87,22 +81,99 @@ static int anatop_regmap_set_voltage_time_sel(struct regulator_dev *reg,
return ret; return ret;
} }
static int anatop_regmap_get_voltage_sel(struct regulator_dev *reg) static int anatop_regmap_enable(struct regulator_dev *reg)
{
struct anatop_regulator *anatop_reg = rdev_get_drvdata(reg);
int sel;
sel = anatop_reg->bypass ? LDO_FET_FULL_ON : anatop_reg->sel;
return regulator_set_voltage_sel_regmap(reg, sel);
}
static int anatop_regmap_disable(struct regulator_dev *reg)
{
return regulator_set_voltage_sel_regmap(reg, LDO_POWER_GATE);
}
static int anatop_regmap_is_enabled(struct regulator_dev *reg)
{
return regulator_get_voltage_sel_regmap(reg) != LDO_POWER_GATE;
}
static int anatop_regmap_core_set_voltage_sel(struct regulator_dev *reg,
unsigned selector)
{
struct anatop_regulator *anatop_reg = rdev_get_drvdata(reg);
int ret;
if (anatop_reg->bypass || !anatop_regmap_is_enabled(reg)) {
anatop_reg->sel = selector;
return 0;
}
ret = regulator_set_voltage_sel_regmap(reg, selector);
if (!ret)
anatop_reg->sel = selector;
return ret;
}
static int anatop_regmap_core_get_voltage_sel(struct regulator_dev *reg)
{ {
struct anatop_regulator *anatop_reg = rdev_get_drvdata(reg); struct anatop_regulator *anatop_reg = rdev_get_drvdata(reg);
if (!anatop_reg->control_reg) if (anatop_reg->bypass || !anatop_regmap_is_enabled(reg))
return -ENOTSUPP; return anatop_reg->sel;
return regulator_get_voltage_sel_regmap(reg); return regulator_get_voltage_sel_regmap(reg);
} }
static int anatop_regmap_get_bypass(struct regulator_dev *reg, bool *enable)
{
struct anatop_regulator *anatop_reg = rdev_get_drvdata(reg);
int sel;
sel = regulator_get_voltage_sel_regmap(reg);
if (sel == LDO_FET_FULL_ON)
WARN_ON(!anatop_reg->bypass);
else if (sel != LDO_POWER_GATE)
WARN_ON(anatop_reg->bypass);
*enable = anatop_reg->bypass;
return 0;
}
static int anatop_regmap_set_bypass(struct regulator_dev *reg, bool enable)
{
struct anatop_regulator *anatop_reg = rdev_get_drvdata(reg);
int sel;
if (enable == anatop_reg->bypass)
return 0;
sel = enable ? LDO_FET_FULL_ON : anatop_reg->sel;
anatop_reg->bypass = enable;
return regulator_set_voltage_sel_regmap(reg, sel);
}
static struct regulator_ops anatop_rops = { static struct regulator_ops anatop_rops = {
.set_voltage_sel = anatop_regmap_set_voltage_sel, .set_voltage_sel = regulator_set_voltage_sel_regmap,
.get_voltage_sel = regulator_get_voltage_sel_regmap,
.list_voltage = regulator_list_voltage_linear,
.map_voltage = regulator_map_voltage_linear,
};
static struct regulator_ops anatop_core_rops = {
.enable = anatop_regmap_enable,
.disable = anatop_regmap_disable,
.is_enabled = anatop_regmap_is_enabled,
.set_voltage_sel = anatop_regmap_core_set_voltage_sel,
.set_voltage_time_sel = anatop_regmap_set_voltage_time_sel, .set_voltage_time_sel = anatop_regmap_set_voltage_time_sel,
.get_voltage_sel = anatop_regmap_get_voltage_sel, .get_voltage_sel = anatop_regmap_core_get_voltage_sel,
.list_voltage = regulator_list_voltage_linear, .list_voltage = regulator_list_voltage_linear,
.map_voltage = regulator_map_voltage_linear, .map_voltage = regulator_map_voltage_linear,
.get_bypass = anatop_regmap_get_bypass,
.set_bypass = anatop_regmap_set_bypass,
}; };
static int anatop_regulator_probe(struct platform_device *pdev) static int anatop_regulator_probe(struct platform_device *pdev)
...@@ -116,6 +187,7 @@ static int anatop_regulator_probe(struct platform_device *pdev) ...@@ -116,6 +187,7 @@ static int anatop_regulator_probe(struct platform_device *pdev)
struct regulator_init_data *initdata; struct regulator_init_data *initdata;
struct regulator_config config = { }; struct regulator_config config = { };
int ret = 0; int ret = 0;
u32 val;
initdata = of_get_regulator_init_data(dev, np); initdata = of_get_regulator_init_data(dev, np);
sreg = devm_kzalloc(dev, sizeof(*sreg), GFP_KERNEL); sreg = devm_kzalloc(dev, sizeof(*sreg), GFP_KERNEL);
...@@ -125,7 +197,6 @@ static int anatop_regulator_probe(struct platform_device *pdev) ...@@ -125,7 +197,6 @@ static int anatop_regulator_probe(struct platform_device *pdev)
sreg->name = of_get_property(np, "regulator-name", NULL); sreg->name = of_get_property(np, "regulator-name", NULL);
rdesc = &sreg->rdesc; rdesc = &sreg->rdesc;
rdesc->name = sreg->name; rdesc->name = sreg->name;
rdesc->ops = &anatop_rops;
rdesc->type = REGULATOR_VOLTAGE; rdesc->type = REGULATOR_VOLTAGE;
rdesc->owner = THIS_MODULE; rdesc->owner = THIS_MODULE;
...@@ -197,6 +268,25 @@ static int anatop_regulator_probe(struct platform_device *pdev) ...@@ -197,6 +268,25 @@ static int anatop_regulator_probe(struct platform_device *pdev)
config.of_node = pdev->dev.of_node; config.of_node = pdev->dev.of_node;
config.regmap = sreg->anatop; config.regmap = sreg->anatop;
/* Only core regulators have the ramp up delay configuration. */
if (sreg->control_reg && sreg->delay_bit_width) {
rdesc->ops = &anatop_core_rops;
ret = regmap_read(config.regmap, rdesc->vsel_reg, &val);
if (ret) {
dev_err(dev, "failed to read initial state\n");
return ret;
}
sreg->sel = (val & rdesc->vsel_mask) >> sreg->vol_bit_shift;
if (sreg->sel == LDO_FET_FULL_ON) {
sreg->sel = 0;
sreg->bypass = true;
}
} else {
rdesc->ops = &anatop_rops;
}
/* register regulator */ /* register regulator */
rdev = devm_regulator_register(dev, rdesc, &config); rdev = devm_regulator_register(dev, rdesc, &config);
if (IS_ERR(rdev)) { if (IS_ERR(rdev)) {
......
...@@ -153,11 +153,9 @@ static const struct regulator_desc arizona_ldo1 = { ...@@ -153,11 +153,9 @@ static const struct regulator_desc arizona_ldo1 = {
.vsel_reg = ARIZONA_LDO1_CONTROL_1, .vsel_reg = ARIZONA_LDO1_CONTROL_1,
.vsel_mask = ARIZONA_LDO1_VSEL_MASK, .vsel_mask = ARIZONA_LDO1_VSEL_MASK,
.bypass_reg = ARIZONA_LDO1_CONTROL_1,
.bypass_mask = ARIZONA_LDO1_BYPASS,
.min_uV = 900000, .min_uV = 900000,
.uV_step = 50000, .uV_step = 25000,
.n_voltages = 7, .n_voltages = 13,
.enable_time = 500, .enable_time = 500,
.owner = THIS_MODULE, .owner = THIS_MODULE,
...@@ -189,10 +187,8 @@ static int arizona_ldo1_probe(struct platform_device *pdev) ...@@ -189,10 +187,8 @@ static int arizona_ldo1_probe(struct platform_device *pdev)
int ret; int ret;
ldo1 = devm_kzalloc(&pdev->dev, sizeof(*ldo1), GFP_KERNEL); ldo1 = devm_kzalloc(&pdev->dev, sizeof(*ldo1), GFP_KERNEL);
if (ldo1 == NULL) { if (!ldo1)
dev_err(&pdev->dev, "Unable to allocate private data\n");
return -ENOMEM; return -ENOMEM;
}
ldo1->arizona = arizona; ldo1->arizona = arizona;
...@@ -203,6 +199,7 @@ static int arizona_ldo1_probe(struct platform_device *pdev) ...@@ -203,6 +199,7 @@ static int arizona_ldo1_probe(struct platform_device *pdev)
*/ */
switch (arizona->type) { switch (arizona->type) {
case WM5102: case WM5102:
case WM8997:
desc = &arizona_ldo1_hc; desc = &arizona_ldo1_hc;
ldo1->init_data = arizona_ldo1_dvfs; ldo1->init_data = arizona_ldo1_dvfs;
break; break;
......
...@@ -204,10 +204,8 @@ static int arizona_micsupp_probe(struct platform_device *pdev) ...@@ -204,10 +204,8 @@ static int arizona_micsupp_probe(struct platform_device *pdev)
int ret; int ret;
micsupp = devm_kzalloc(&pdev->dev, sizeof(*micsupp), GFP_KERNEL); micsupp = devm_kzalloc(&pdev->dev, sizeof(*micsupp), GFP_KERNEL);
if (micsupp == NULL) { if (!micsupp)
dev_err(&pdev->dev, "Unable to allocate private data\n");
return -ENOMEM; return -ENOMEM;
}
micsupp->arizona = arizona; micsupp->arizona = arizona;
INIT_WORK(&micsupp->check_cp_work, arizona_micsupp_check_cp); INIT_WORK(&micsupp->check_cp_work, arizona_micsupp_check_cp);
......
...@@ -191,7 +191,7 @@ static int as3711_regulator_parse_dt(struct device *dev, ...@@ -191,7 +191,7 @@ static int as3711_regulator_parse_dt(struct device *dev,
{ {
struct as3711_regulator_pdata *pdata = dev_get_platdata(dev); struct as3711_regulator_pdata *pdata = dev_get_platdata(dev);
struct device_node *regulators = struct device_node *regulators =
of_find_node_by_name(dev->parent->of_node, "regulators"); of_get_child_by_name(dev->parent->of_node, "regulators");
struct of_regulator_match *match; struct of_regulator_match *match;
int ret, i; int ret, i;
...@@ -221,7 +221,6 @@ static int as3711_regulator_probe(struct platform_device *pdev) ...@@ -221,7 +221,6 @@ static int as3711_regulator_probe(struct platform_device *pdev)
{ {
struct as3711_regulator_pdata *pdata = dev_get_platdata(&pdev->dev); struct as3711_regulator_pdata *pdata = dev_get_platdata(&pdev->dev);
struct as3711 *as3711 = dev_get_drvdata(pdev->dev.parent); struct as3711 *as3711 = dev_get_drvdata(pdev->dev.parent);
struct regulator_init_data *reg_data;
struct regulator_config config = {.dev = &pdev->dev,}; struct regulator_config config = {.dev = &pdev->dev,};
struct as3711_regulator *reg = NULL; struct as3711_regulator *reg = NULL;
struct as3711_regulator *regs; struct as3711_regulator *regs;
...@@ -246,22 +245,14 @@ static int as3711_regulator_probe(struct platform_device *pdev) ...@@ -246,22 +245,14 @@ static int as3711_regulator_probe(struct platform_device *pdev)
regs = devm_kzalloc(&pdev->dev, AS3711_REGULATOR_NUM * regs = devm_kzalloc(&pdev->dev, AS3711_REGULATOR_NUM *
sizeof(struct as3711_regulator), GFP_KERNEL); sizeof(struct as3711_regulator), GFP_KERNEL);
if (!regs) { if (!regs)
dev_err(&pdev->dev, "Memory allocation failed exiting..\n");
return -ENOMEM; return -ENOMEM;
}
for (id = 0, ri = as3711_reg_info; id < AS3711_REGULATOR_NUM; ++id, ri++) { for (id = 0, ri = as3711_reg_info; id < AS3711_REGULATOR_NUM; ++id, ri++) {
reg_data = pdata->init_data[id];
/* No need to register if there is no regulator data */
if (!reg_data)
continue;
reg = &regs[id]; reg = &regs[id];
reg->reg_info = ri; reg->reg_info = ri;
config.init_data = reg_data; config.init_data = pdata->init_data[id];
config.driver_data = reg; config.driver_data = reg;
config.regmap = as3711->regmap; config.regmap = as3711->regmap;
config.of_node = of_node[id]; config.of_node = of_node[id];
......
...@@ -719,6 +719,7 @@ static int as3722_get_regulator_dt_data(struct platform_device *pdev, ...@@ -719,6 +719,7 @@ static int as3722_get_regulator_dt_data(struct platform_device *pdev,
ret = of_regulator_match(&pdev->dev, np, as3722_regulator_matches, ret = of_regulator_match(&pdev->dev, np, as3722_regulator_matches,
ARRAY_SIZE(as3722_regulator_matches)); ARRAY_SIZE(as3722_regulator_matches));
of_node_put(np);
if (ret < 0) { if (ret < 0) {
dev_err(&pdev->dev, "Parsing of regulator node failed: %d\n", dev_err(&pdev->dev, "Parsing of regulator node failed: %d\n",
ret); ret);
......
This diff is collapsed.
...@@ -2399,6 +2399,7 @@ int regulator_set_voltage(struct regulator *regulator, int min_uV, int max_uV) ...@@ -2399,6 +2399,7 @@ int regulator_set_voltage(struct regulator *regulator, int min_uV, int max_uV)
struct regulator_dev *rdev = regulator->rdev; struct regulator_dev *rdev = regulator->rdev;
int ret = 0; int ret = 0;
int old_min_uV, old_max_uV; int old_min_uV, old_max_uV;
int current_uV;
mutex_lock(&rdev->mutex); mutex_lock(&rdev->mutex);
...@@ -2409,6 +2410,19 @@ int regulator_set_voltage(struct regulator *regulator, int min_uV, int max_uV) ...@@ -2409,6 +2410,19 @@ int regulator_set_voltage(struct regulator *regulator, int min_uV, int max_uV)
if (regulator->min_uV == min_uV && regulator->max_uV == max_uV) if (regulator->min_uV == min_uV && regulator->max_uV == max_uV)
goto out; goto out;
/* If we're trying to set a range that overlaps the current voltage,
* return succesfully even though the regulator does not support
* changing the voltage.
*/
if (!(rdev->constraints->valid_ops_mask & REGULATOR_CHANGE_VOLTAGE)) {
current_uV = _regulator_get_voltage(rdev);
if (min_uV <= current_uV && current_uV <= max_uV) {
regulator->min_uV = min_uV;
regulator->max_uV = max_uV;
goto out;
}
}
/* sanity check */ /* sanity check */
if (!rdev->desc->ops->set_voltage && if (!rdev->desc->ops->set_voltage &&
!rdev->desc->ops->set_voltage_sel) { !rdev->desc->ops->set_voltage_sel) {
......
...@@ -240,6 +240,31 @@ static int da9052_regulator_set_voltage_sel(struct regulator_dev *rdev, ...@@ -240,6 +240,31 @@ static int da9052_regulator_set_voltage_sel(struct regulator_dev *rdev,
return ret; return ret;
} }
static int da9052_regulator_set_voltage_time_sel(struct regulator_dev *rdev,
unsigned int old_sel,
unsigned int new_sel)
{
struct da9052_regulator *regulator = rdev_get_drvdata(rdev);
struct da9052_regulator_info *info = regulator->info;
int id = rdev_get_id(rdev);
int ret = 0;
/* The DVC controlled LDOs and DCDCs ramp with 6.25mV/µs after enabling
* the activate bit.
*/
switch (id) {
case DA9052_ID_BUCK1:
case DA9052_ID_BUCK2:
case DA9052_ID_BUCK3:
case DA9052_ID_LDO2:
case DA9052_ID_LDO3:
ret = (new_sel - old_sel) * info->step_uV / 6250;
break;
}
return ret;
}
static struct regulator_ops da9052_dcdc_ops = { static struct regulator_ops da9052_dcdc_ops = {
.get_current_limit = da9052_dcdc_get_current_limit, .get_current_limit = da9052_dcdc_get_current_limit,
.set_current_limit = da9052_dcdc_set_current_limit, .set_current_limit = da9052_dcdc_set_current_limit,
...@@ -248,6 +273,7 @@ static struct regulator_ops da9052_dcdc_ops = { ...@@ -248,6 +273,7 @@ static struct regulator_ops da9052_dcdc_ops = {
.map_voltage = da9052_map_voltage, .map_voltage = da9052_map_voltage,
.get_voltage_sel = regulator_get_voltage_sel_regmap, .get_voltage_sel = regulator_get_voltage_sel_regmap,
.set_voltage_sel = da9052_regulator_set_voltage_sel, .set_voltage_sel = da9052_regulator_set_voltage_sel,
.set_voltage_time_sel = da9052_regulator_set_voltage_time_sel,
.is_enabled = regulator_is_enabled_regmap, .is_enabled = regulator_is_enabled_regmap,
.enable = regulator_enable_regmap, .enable = regulator_enable_regmap,
.disable = regulator_disable_regmap, .disable = regulator_disable_regmap,
...@@ -258,6 +284,7 @@ static struct regulator_ops da9052_ldo_ops = { ...@@ -258,6 +284,7 @@ static struct regulator_ops da9052_ldo_ops = {
.map_voltage = da9052_map_voltage, .map_voltage = da9052_map_voltage,
.get_voltage_sel = regulator_get_voltage_sel_regmap, .get_voltage_sel = regulator_get_voltage_sel_regmap,
.set_voltage_sel = da9052_regulator_set_voltage_sel, .set_voltage_sel = da9052_regulator_set_voltage_sel,
.set_voltage_time_sel = da9052_regulator_set_voltage_time_sel,
.is_enabled = regulator_is_enabled_regmap, .is_enabled = regulator_is_enabled_regmap,
.enable = regulator_enable_regmap, .enable = regulator_enable_regmap,
.disable = regulator_disable_regmap, .disable = regulator_disable_regmap,
...@@ -401,7 +428,7 @@ static int da9052_regulator_probe(struct platform_device *pdev) ...@@ -401,7 +428,7 @@ static int da9052_regulator_probe(struct platform_device *pdev)
if (!nproot) if (!nproot)
return -ENODEV; return -ENODEV;
nproot = of_find_node_by_name(nproot, "regulators"); nproot = of_get_child_by_name(nproot, "regulators");
if (!nproot) if (!nproot)
return -ENODEV; return -ENODEV;
......
...@@ -19,6 +19,8 @@ ...@@ -19,6 +19,8 @@
#include <linux/platform_device.h> #include <linux/platform_device.h>
#include <linux/regulator/driver.h> #include <linux/regulator/driver.h>
#include <linux/regulator/machine.h> #include <linux/regulator/machine.h>
#include <linux/of.h>
#include <linux/regulator/of_regulator.h>
#include <linux/mfd/da9055/core.h> #include <linux/mfd/da9055/core.h>
#include <linux/mfd/da9055/reg.h> #include <linux/mfd/da9055/reg.h>
...@@ -446,6 +448,9 @@ static int da9055_gpio_init(struct da9055_regulator *regulator, ...@@ -446,6 +448,9 @@ static int da9055_gpio_init(struct da9055_regulator *regulator,
struct da9055_regulator_info *info = regulator->info; struct da9055_regulator_info *info = regulator->info;
int ret = 0; int ret = 0;
if (!pdata)
return 0;
if (pdata->gpio_ren && pdata->gpio_ren[id]) { if (pdata->gpio_ren && pdata->gpio_ren[id]) {
char name[18]; char name[18];
int gpio_mux = pdata->gpio_ren[id]; int gpio_mux = pdata->gpio_ren[id];
...@@ -530,6 +535,59 @@ static inline struct da9055_regulator_info *find_regulator_info(int id) ...@@ -530,6 +535,59 @@ static inline struct da9055_regulator_info *find_regulator_info(int id)
return NULL; return NULL;
} }
#ifdef CONFIG_OF
static struct of_regulator_match da9055_reg_matches[] = {
{ .name = "BUCK1", },
{ .name = "BUCK2", },
{ .name = "LDO1", },
{ .name = "LDO2", },
{ .name = "LDO3", },
{ .name = "LDO4", },
{ .name = "LDO5", },
{ .name = "LDO6", },
};
static int da9055_regulator_dt_init(struct platform_device *pdev,
struct da9055_regulator *regulator,
struct regulator_config *config,
int regid)
{
struct device_node *nproot, *np;
int ret;
nproot = of_node_get(pdev->dev.parent->of_node);
if (!nproot)
return -ENODEV;
np = of_get_child_by_name(nproot, "regulators");
if (!np)
return -ENODEV;
ret = of_regulator_match(&pdev->dev, np, &da9055_reg_matches[regid], 1);
of_node_put(nproot);
if (ret < 0) {
dev_err(&pdev->dev, "Error matching regulator: %d\n", ret);
return ret;
}
config->init_data = da9055_reg_matches[regid].init_data;
config->of_node = da9055_reg_matches[regid].of_node;
if (!config->of_node)
return -ENODEV;
return 0;
}
#else
static inline int da9055_regulator_dt_init(struct platform_device *pdev,
struct da9055_regulator *regulator,
struct regulator_config *config,
int regid)
{
return -ENODEV;
}
#endif /* CONFIG_OF */
static int da9055_regulator_probe(struct platform_device *pdev) static int da9055_regulator_probe(struct platform_device *pdev)
{ {
struct regulator_config config = { }; struct regulator_config config = { };
...@@ -538,9 +596,6 @@ static int da9055_regulator_probe(struct platform_device *pdev) ...@@ -538,9 +596,6 @@ static int da9055_regulator_probe(struct platform_device *pdev)
struct da9055_pdata *pdata = dev_get_platdata(da9055->dev); struct da9055_pdata *pdata = dev_get_platdata(da9055->dev);
int ret, irq; int ret, irq;
if (pdata == NULL || pdata->regulators[pdev->id] == NULL)
return -ENODEV;
regulator = devm_kzalloc(&pdev->dev, sizeof(struct da9055_regulator), regulator = devm_kzalloc(&pdev->dev, sizeof(struct da9055_regulator),
GFP_KERNEL); GFP_KERNEL);
if (!regulator) if (!regulator)
...@@ -557,8 +612,14 @@ static int da9055_regulator_probe(struct platform_device *pdev) ...@@ -557,8 +612,14 @@ static int da9055_regulator_probe(struct platform_device *pdev)
config.driver_data = regulator; config.driver_data = regulator;
config.regmap = da9055->regmap; config.regmap = da9055->regmap;
if (pdata && pdata->regulators) if (pdata && pdata->regulators) {
config.init_data = pdata->regulators[pdev->id]; config.init_data = pdata->regulators[pdev->id];
} else {
ret = da9055_regulator_dt_init(pdev, regulator, &config,
pdev->id);
if (ret < 0)
return ret;
}
ret = da9055_gpio_init(regulator, &config, pdata, pdev->id); ret = da9055_gpio_init(regulator, &config, pdata, pdev->id);
if (ret < 0) if (ret < 0)
......
...@@ -365,7 +365,7 @@ static int da9063_set_suspend_voltage(struct regulator_dev *rdev, int uV) ...@@ -365,7 +365,7 @@ static int da9063_set_suspend_voltage(struct regulator_dev *rdev, int uV)
sel = regulator_map_voltage_linear(rdev, uV, uV); sel = regulator_map_voltage_linear(rdev, uV, uV);
if (sel < 0) if (sel < 0)
return -EINVAL; return sel;
sel <<= ffs(rdev->desc->vsel_mask) - 1; sel <<= ffs(rdev->desc->vsel_mask) - 1;
...@@ -666,7 +666,7 @@ static struct da9063_regulators_pdata *da9063_parse_regulators_dt( ...@@ -666,7 +666,7 @@ static struct da9063_regulators_pdata *da9063_parse_regulators_dt(
struct device_node *node; struct device_node *node;
int i, n, num; int i, n, num;
node = of_find_node_by_name(pdev->dev.parent->of_node, "regulators"); node = of_get_child_by_name(pdev->dev.parent->of_node, "regulators");
if (!node) { if (!node) {
dev_err(&pdev->dev, "Regulators device node not found\n"); dev_err(&pdev->dev, "Regulators device node not found\n");
return ERR_PTR(-ENODEV); return ERR_PTR(-ENODEV);
...@@ -674,6 +674,7 @@ static struct da9063_regulators_pdata *da9063_parse_regulators_dt( ...@@ -674,6 +674,7 @@ static struct da9063_regulators_pdata *da9063_parse_regulators_dt(
num = of_regulator_match(&pdev->dev, node, da9063_matches, num = of_regulator_match(&pdev->dev, node, da9063_matches,
ARRAY_SIZE(da9063_matches)); ARRAY_SIZE(da9063_matches));
of_node_put(node);
if (num < 0) { if (num < 0) {
dev_err(&pdev->dev, "Failed to match regulators\n"); dev_err(&pdev->dev, "Failed to match regulators\n");
return ERR_PTR(-EINVAL); return ERR_PTR(-EINVAL);
...@@ -710,7 +711,7 @@ static struct da9063_regulators_pdata *da9063_parse_regulators_dt( ...@@ -710,7 +711,7 @@ static struct da9063_regulators_pdata *da9063_parse_regulators_dt(
struct platform_device *pdev, struct platform_device *pdev,
struct of_regulator_match **da9063_reg_matches) struct of_regulator_match **da9063_reg_matches)
{ {
da9063_reg_matches = NULL; *da9063_reg_matches = NULL;
return ERR_PTR(-ENODEV); return ERR_PTR(-ENODEV);
} }
#endif #endif
...@@ -756,7 +757,7 @@ static int da9063_regulator_probe(struct platform_device *pdev) ...@@ -756,7 +757,7 @@ static int da9063_regulator_probe(struct platform_device *pdev)
if (ret < 0) { if (ret < 0) {
dev_err(&pdev->dev, dev_err(&pdev->dev,
"Error while reading BUCKs configuration\n"); "Error while reading BUCKs configuration\n");
return -EIO; return ret;
} }
bcores_merged = val & DA9063_BCORE_MERGE; bcores_merged = val & DA9063_BCORE_MERGE;
bmem_bio_merged = val & DA9063_BUCK_MERGE; bmem_bio_merged = val & DA9063_BUCK_MERGE;
...@@ -775,10 +776,8 @@ static int da9063_regulator_probe(struct platform_device *pdev) ...@@ -775,10 +776,8 @@ static int da9063_regulator_probe(struct platform_device *pdev)
size = sizeof(struct da9063_regulators) + size = sizeof(struct da9063_regulators) +
n_regulators * sizeof(struct da9063_regulator); n_regulators * sizeof(struct da9063_regulator);
regulators = devm_kzalloc(&pdev->dev, size, GFP_KERNEL); regulators = devm_kzalloc(&pdev->dev, size, GFP_KERNEL);
if (!regulators) { if (!regulators)
dev_err(&pdev->dev, "No memory for regulators\n");
return -ENOMEM; return -ENOMEM;
}
regulators->n_regulators = n_regulators; regulators->n_regulators = n_regulators;
platform_set_drvdata(pdev, regulators); platform_set_drvdata(pdev, regulators);
......
...@@ -134,11 +134,8 @@ static int da9210_i2c_probe(struct i2c_client *i2c, ...@@ -134,11 +134,8 @@ static int da9210_i2c_probe(struct i2c_client *i2c,
int error; int error;
chip = devm_kzalloc(&i2c->dev, sizeof(struct da9210), GFP_KERNEL); chip = devm_kzalloc(&i2c->dev, sizeof(struct da9210), GFP_KERNEL);
if (NULL == chip) { if (!chip)
dev_err(&i2c->dev,
"Cannot kzalloc memory for regulator structure\n");
return -ENOMEM; return -ENOMEM;
}
chip->regmap = devm_regmap_init_i2c(i2c, &da9210_regmap_config); chip->regmap = devm_regmap_init_i2c(i2c, &da9210_regmap_config);
if (IS_ERR(chip->regmap)) { if (IS_ERR(chip->regmap)) {
......
...@@ -263,6 +263,8 @@ dbx500_regulator_info[DB8500_NUM_REGULATORS] = { ...@@ -263,6 +263,8 @@ dbx500_regulator_info[DB8500_NUM_REGULATORS] = {
.ops = &db8500_regulator_ops, .ops = &db8500_regulator_ops,
.type = REGULATOR_VOLTAGE, .type = REGULATOR_VOLTAGE,
.owner = THIS_MODULE, .owner = THIS_MODULE,
.fixed_uV = 1800000,
.n_voltages = 1,
}, },
.exclude_from_power_state = true, .exclude_from_power_state = true,
}, },
......
...@@ -78,6 +78,7 @@ static struct ux500_regulator_debug { ...@@ -78,6 +78,7 @@ static struct ux500_regulator_debug {
void ux500_regulator_suspend_debug(void) void ux500_regulator_suspend_debug(void)
{ {
int i; int i;
for (i = 0; i < rdebug.num_regulators; i++) for (i = 0; i < rdebug.num_regulators; i++)
rdebug.state_before_suspend[i] = rdebug.state_before_suspend[i] =
rdebug.regulator_array[i].is_enabled; rdebug.regulator_array[i].is_enabled;
...@@ -86,6 +87,7 @@ void ux500_regulator_suspend_debug(void) ...@@ -86,6 +87,7 @@ void ux500_regulator_suspend_debug(void)
void ux500_regulator_resume_debug(void) void ux500_regulator_resume_debug(void)
{ {
int i; int i;
for (i = 0; i < rdebug.num_regulators; i++) for (i = 0; i < rdebug.num_regulators; i++)
rdebug.state_after_suspend[i] = rdebug.state_after_suspend[i] =
rdebug.regulator_array[i].is_enabled; rdebug.regulator_array[i].is_enabled;
...@@ -127,9 +129,9 @@ static int ux500_regulator_status_print(struct seq_file *s, void *p) ...@@ -127,9 +129,9 @@ static int ux500_regulator_status_print(struct seq_file *s, void *p)
int i; int i;
/* print dump header */ /* print dump header */
err = seq_printf(s, "ux500-regulator status:\n"); err = seq_puts(s, "ux500-regulator status:\n");
if (err < 0) if (err < 0)
dev_err(dev, "seq_printf overflow\n"); dev_err(dev, "seq_puts overflow\n");
err = seq_printf(s, "%31s : %8s : %8s\n", "current", err = seq_printf(s, "%31s : %8s : %8s\n", "current",
"before", "after"); "before", "after");
...@@ -202,18 +204,12 @@ ux500_regulator_debug_init(struct platform_device *pdev, ...@@ -202,18 +204,12 @@ ux500_regulator_debug_init(struct platform_device *pdev,
rdebug.num_regulators = num_regulators; rdebug.num_regulators = num_regulators;
rdebug.state_before_suspend = kzalloc(num_regulators, GFP_KERNEL); rdebug.state_before_suspend = kzalloc(num_regulators, GFP_KERNEL);
if (!rdebug.state_before_suspend) { if (!rdebug.state_before_suspend)
dev_err(&pdev->dev,
"could not allocate memory for saving state\n");
goto exit_destroy_power_state; goto exit_destroy_power_state;
}
rdebug.state_after_suspend = kzalloc(num_regulators, GFP_KERNEL); rdebug.state_after_suspend = kzalloc(num_regulators, GFP_KERNEL);
if (!rdebug.state_after_suspend) { if (!rdebug.state_after_suspend)
dev_err(&pdev->dev,
"could not allocate memory for saving state\n");
goto exit_free; goto exit_free;
}
dbx500_regulator_testcase(regulator_info, num_regulators); dbx500_regulator_testcase(regulator_info, num_regulators);
return 0; return 0;
......
...@@ -25,7 +25,11 @@ ...@@ -25,7 +25,11 @@
struct regulator_dev *dummy_regulator_rdev; struct regulator_dev *dummy_regulator_rdev;
static struct regulator_init_data dummy_initdata; static struct regulator_init_data dummy_initdata = {
.constraints = {
.always_on = 1,
},
};
static struct regulator_ops dummy_ops; static struct regulator_ops dummy_ops;
......
...@@ -90,11 +90,11 @@ static int fan53555_set_suspend_voltage(struct regulator_dev *rdev, int uV) ...@@ -90,11 +90,11 @@ static int fan53555_set_suspend_voltage(struct regulator_dev *rdev, int uV)
return 0; return 0;
ret = regulator_map_voltage_linear(rdev, uV, uV); ret = regulator_map_voltage_linear(rdev, uV, uV);
if (ret < 0) if (ret < 0)
return -EINVAL; return ret;
ret = regmap_update_bits(di->regmap, di->sleep_reg, ret = regmap_update_bits(di->regmap, di->sleep_reg,
VSEL_NSEL_MASK, ret); VSEL_NSEL_MASK, ret);
if (ret < 0) if (ret < 0)
return -EINVAL; return ret;
/* Cache the sleep voltage setting. /* Cache the sleep voltage setting.
* Might not be the real voltage which is rounded */ * Might not be the real voltage which is rounded */
di->sleep_vol_cache = uV; di->sleep_vol_cache = uV;
...@@ -244,10 +244,9 @@ static int fan53555_regulator_probe(struct i2c_client *client, ...@@ -244,10 +244,9 @@ static int fan53555_regulator_probe(struct i2c_client *client,
di = devm_kzalloc(&client->dev, sizeof(struct fan53555_device_info), di = devm_kzalloc(&client->dev, sizeof(struct fan53555_device_info),
GFP_KERNEL); GFP_KERNEL);
if (!di) { if (!di)
dev_err(&client->dev, "Failed to allocate device info data!\n");
return -ENOMEM; return -ENOMEM;
}
di->regmap = devm_regmap_init_i2c(client, &fan53555_regmap_config); di->regmap = devm_regmap_init_i2c(client, &fan53555_regmap_config);
if (IS_ERR(di->regmap)) { if (IS_ERR(di->regmap)) {
dev_err(&client->dev, "Failed to allocate regmap!\n"); dev_err(&client->dev, "Failed to allocate regmap!\n");
...@@ -260,14 +259,14 @@ static int fan53555_regulator_probe(struct i2c_client *client, ...@@ -260,14 +259,14 @@ static int fan53555_regulator_probe(struct i2c_client *client,
ret = regmap_read(di->regmap, FAN53555_ID1, &val); ret = regmap_read(di->regmap, FAN53555_ID1, &val);
if (ret < 0) { if (ret < 0) {
dev_err(&client->dev, "Failed to get chip ID!\n"); dev_err(&client->dev, "Failed to get chip ID!\n");
return -ENODEV; return ret;
} }
di->chip_id = val & DIE_ID; di->chip_id = val & DIE_ID;
/* Get chip revision */ /* Get chip revision */
ret = regmap_read(di->regmap, FAN53555_ID2, &val); ret = regmap_read(di->regmap, FAN53555_ID2, &val);
if (ret < 0) { if (ret < 0) {
dev_err(&client->dev, "Failed to get chip Rev!\n"); dev_err(&client->dev, "Failed to get chip Rev!\n");
return -ENODEV; return ret;
} }
di->chip_rev = val & DIE_REV; di->chip_rev = val & DIE_REV;
dev_info(&client->dev, "FAN53555 Option[%d] Rev[%d] Detected!\n", dev_info(&client->dev, "FAN53555 Option[%d] Rev[%d] Detected!\n",
......
...@@ -130,17 +130,15 @@ static int reg_fixed_voltage_probe(struct platform_device *pdev) ...@@ -130,17 +130,15 @@ static int reg_fixed_voltage_probe(struct platform_device *pdev)
drvdata = devm_kzalloc(&pdev->dev, sizeof(struct fixed_voltage_data), drvdata = devm_kzalloc(&pdev->dev, sizeof(struct fixed_voltage_data),
GFP_KERNEL); GFP_KERNEL);
if (drvdata == NULL) { if (!drvdata)
dev_err(&pdev->dev, "Failed to allocate device data\n"); return -ENOMEM;
ret = -ENOMEM;
goto err;
}
drvdata->desc.name = kstrdup(config->supply_name, GFP_KERNEL); drvdata->desc.name = devm_kstrdup(&pdev->dev,
config->supply_name,
GFP_KERNEL);
if (drvdata->desc.name == NULL) { if (drvdata->desc.name == NULL) {
dev_err(&pdev->dev, "Failed to allocate supply name\n"); dev_err(&pdev->dev, "Failed to allocate supply name\n");
ret = -ENOMEM; return -ENOMEM;
goto err;
} }
drvdata->desc.type = REGULATOR_VOLTAGE; drvdata->desc.type = REGULATOR_VOLTAGE;
drvdata->desc.owner = THIS_MODULE; drvdata->desc.owner = THIS_MODULE;
...@@ -149,13 +147,13 @@ static int reg_fixed_voltage_probe(struct platform_device *pdev) ...@@ -149,13 +147,13 @@ static int reg_fixed_voltage_probe(struct platform_device *pdev)
drvdata->desc.enable_time = config->startup_delay; drvdata->desc.enable_time = config->startup_delay;
if (config->input_supply) { if (config->input_supply) {
drvdata->desc.supply_name = kstrdup(config->input_supply, drvdata->desc.supply_name = devm_kstrdup(&pdev->dev,
config->input_supply,
GFP_KERNEL); GFP_KERNEL);
if (!drvdata->desc.supply_name) { if (!drvdata->desc.supply_name) {
dev_err(&pdev->dev, dev_err(&pdev->dev,
"Failed to allocate input supply\n"); "Failed to allocate input supply\n");
ret = -ENOMEM; return -ENOMEM;
goto err_name;
} }
} }
...@@ -186,11 +184,12 @@ static int reg_fixed_voltage_probe(struct platform_device *pdev) ...@@ -186,11 +184,12 @@ static int reg_fixed_voltage_probe(struct platform_device *pdev)
cfg.driver_data = drvdata; cfg.driver_data = drvdata;
cfg.of_node = pdev->dev.of_node; cfg.of_node = pdev->dev.of_node;
drvdata->dev = regulator_register(&drvdata->desc, &cfg); drvdata->dev = devm_regulator_register(&pdev->dev, &drvdata->desc,
&cfg);
if (IS_ERR(drvdata->dev)) { if (IS_ERR(drvdata->dev)) {
ret = PTR_ERR(drvdata->dev); ret = PTR_ERR(drvdata->dev);
dev_err(&pdev->dev, "Failed to register regulator: %d\n", ret); dev_err(&pdev->dev, "Failed to register regulator: %d\n", ret);
goto err_input; return ret;
} }
platform_set_drvdata(pdev, drvdata); platform_set_drvdata(pdev, drvdata);
...@@ -199,24 +198,6 @@ static int reg_fixed_voltage_probe(struct platform_device *pdev) ...@@ -199,24 +198,6 @@ static int reg_fixed_voltage_probe(struct platform_device *pdev)
drvdata->desc.fixed_uV); drvdata->desc.fixed_uV);
return 0; return 0;
err_input:
kfree(drvdata->desc.supply_name);
err_name:
kfree(drvdata->desc.name);
err:
return ret;
}
static int reg_fixed_voltage_remove(struct platform_device *pdev)
{
struct fixed_voltage_data *drvdata = platform_get_drvdata(pdev);
regulator_unregister(drvdata->dev);
kfree(drvdata->desc.supply_name);
kfree(drvdata->desc.name);
return 0;
} }
#if defined(CONFIG_OF) #if defined(CONFIG_OF)
...@@ -229,7 +210,6 @@ MODULE_DEVICE_TABLE(of, fixed_of_match); ...@@ -229,7 +210,6 @@ MODULE_DEVICE_TABLE(of, fixed_of_match);
static struct platform_driver regulator_fixed_voltage_driver = { static struct platform_driver regulator_fixed_voltage_driver = {
.probe = reg_fixed_voltage_probe, .probe = reg_fixed_voltage_probe,
.remove = reg_fixed_voltage_remove,
.driver = { .driver = {
.name = "reg-fixed-voltage", .name = "reg-fixed-voltage",
.owner = THIS_MODULE, .owner = THIS_MODULE,
......
...@@ -136,7 +136,6 @@ static struct gpio_regulator_config * ...@@ -136,7 +136,6 @@ static struct gpio_regulator_config *
of_get_gpio_regulator_config(struct device *dev, struct device_node *np) of_get_gpio_regulator_config(struct device *dev, struct device_node *np)
{ {
struct gpio_regulator_config *config; struct gpio_regulator_config *config;
struct property *prop;
const char *regtype; const char *regtype;
int proplen, gpio, i; int proplen, gpio, i;
int ret; int ret;
...@@ -172,22 +171,35 @@ of_get_gpio_regulator_config(struct device *dev, struct device_node *np) ...@@ -172,22 +171,35 @@ of_get_gpio_regulator_config(struct device *dev, struct device_node *np)
if (!config->gpios) if (!config->gpios)
return ERR_PTR(-ENOMEM); return ERR_PTR(-ENOMEM);
proplen = of_property_count_u32_elems(np, "gpios-states");
/* optional property */
if (proplen < 0)
proplen = 0;
if (proplen > 0 && proplen != config->nr_gpios) {
dev_warn(dev, "gpios <-> gpios-states mismatch\n");
proplen = 0;
}
for (i = 0; i < config->nr_gpios; i++) { for (i = 0; i < config->nr_gpios; i++) {
gpio = of_get_named_gpio(np, "gpios", i); gpio = of_get_named_gpio(np, "gpios", i);
if (gpio < 0) if (gpio < 0)
break; break;
config->gpios[i].gpio = gpio; config->gpios[i].gpio = gpio;
if (proplen > 0) {
of_property_read_u32_index(np, "gpios-states", i, &ret);
if (ret)
config->gpios[i].flags = GPIOF_OUT_INIT_HIGH;
}
} }
/* Fetch states. */ /* Fetch states. */
prop = of_find_property(np, "states", NULL); proplen = of_property_count_u32_elems(np, "states");
if (!prop) { if (proplen < 0) {
dev_err(dev, "No 'states' property found\n"); dev_err(dev, "No 'states' property found\n");
return ERR_PTR(-EINVAL); return ERR_PTR(-EINVAL);
} }
proplen = prop->length / sizeof(int);
config->states = devm_kzalloc(dev, config->states = devm_kzalloc(dev,
sizeof(struct gpio_regulator_state) sizeof(struct gpio_regulator_state)
* (proplen / 2), * (proplen / 2),
...@@ -196,10 +208,10 @@ of_get_gpio_regulator_config(struct device *dev, struct device_node *np) ...@@ -196,10 +208,10 @@ of_get_gpio_regulator_config(struct device *dev, struct device_node *np)
return ERR_PTR(-ENOMEM); return ERR_PTR(-ENOMEM);
for (i = 0; i < proplen / 2; i++) { for (i = 0; i < proplen / 2; i++) {
config->states[i].value = of_property_read_u32_index(np, "states", i * 2,
be32_to_cpup((int *)prop->value + (i * 2)); &config->states[i].value);
config->states[i].gpios = of_property_read_u32_index(np, "states", i * 2 + 1,
be32_to_cpup((int *)prop->value + (i * 2 + 1)); &config->states[i].gpios);
} }
config->nr_states = i; config->nr_states = i;
...@@ -239,10 +251,8 @@ static int gpio_regulator_probe(struct platform_device *pdev) ...@@ -239,10 +251,8 @@ static int gpio_regulator_probe(struct platform_device *pdev)
drvdata = devm_kzalloc(&pdev->dev, sizeof(struct gpio_regulator_data), drvdata = devm_kzalloc(&pdev->dev, sizeof(struct gpio_regulator_data),
GFP_KERNEL); GFP_KERNEL);
if (drvdata == NULL) { if (drvdata == NULL)
dev_err(&pdev->dev, "Failed to allocate device data\n");
return -ENOMEM; return -ENOMEM;
}
drvdata->desc.name = kstrdup(config->supply_name, GFP_KERNEL); drvdata->desc.name = kstrdup(config->supply_name, GFP_KERNEL);
if (drvdata->desc.name == NULL) { if (drvdata->desc.name == NULL) {
......
...@@ -37,10 +37,17 @@ int regulator_is_enabled_regmap(struct regulator_dev *rdev) ...@@ -37,10 +37,17 @@ int regulator_is_enabled_regmap(struct regulator_dev *rdev)
if (ret != 0) if (ret != 0)
return ret; return ret;
if (rdev->desc->enable_is_inverted) val &= rdev->desc->enable_mask;
return (val & rdev->desc->enable_mask) == 0;
else if (rdev->desc->enable_is_inverted) {
return (val & rdev->desc->enable_mask) != 0; if (rdev->desc->enable_val)
return val != rdev->desc->enable_val;
return val == 0;
} else {
if (rdev->desc->enable_val)
return val == rdev->desc->enable_val;
return val != 0;
}
} }
EXPORT_SYMBOL_GPL(regulator_is_enabled_regmap); EXPORT_SYMBOL_GPL(regulator_is_enabled_regmap);
...@@ -57,10 +64,13 @@ int regulator_enable_regmap(struct regulator_dev *rdev) ...@@ -57,10 +64,13 @@ int regulator_enable_regmap(struct regulator_dev *rdev)
{ {
unsigned int val; unsigned int val;
if (rdev->desc->enable_is_inverted) if (rdev->desc->enable_is_inverted) {
val = 0; val = rdev->desc->disable_val;
else } else {
val = rdev->desc->enable_val;
if (!val)
val = rdev->desc->enable_mask; val = rdev->desc->enable_mask;
}
return regmap_update_bits(rdev->regmap, rdev->desc->enable_reg, return regmap_update_bits(rdev->regmap, rdev->desc->enable_reg,
rdev->desc->enable_mask, val); rdev->desc->enable_mask, val);
...@@ -80,10 +90,13 @@ int regulator_disable_regmap(struct regulator_dev *rdev) ...@@ -80,10 +90,13 @@ int regulator_disable_regmap(struct regulator_dev *rdev)
{ {
unsigned int val; unsigned int val;
if (rdev->desc->enable_is_inverted) if (rdev->desc->enable_is_inverted) {
val = rdev->desc->enable_val;
if (!val)
val = rdev->desc->enable_mask; val = rdev->desc->enable_mask;
else } else {
val = 0; val = rdev->desc->disable_val;
}
return regmap_update_bits(rdev->regmap, rdev->desc->enable_reg, return regmap_update_bits(rdev->regmap, rdev->desc->enable_reg,
rdev->desc->enable_mask, val); rdev->desc->enable_mask, val);
...@@ -419,10 +432,13 @@ int regulator_set_bypass_regmap(struct regulator_dev *rdev, bool enable) ...@@ -419,10 +432,13 @@ int regulator_set_bypass_regmap(struct regulator_dev *rdev, bool enable)
{ {
unsigned int val; unsigned int val;
if (enable) if (enable) {
val = rdev->desc->bypass_val_on;
if (!val)
val = rdev->desc->bypass_mask; val = rdev->desc->bypass_mask;
else } else {
val = 0; val = rdev->desc->bypass_val_off;
}
return regmap_update_bits(rdev->regmap, rdev->desc->bypass_reg, return regmap_update_bits(rdev->regmap, rdev->desc->bypass_reg,
rdev->desc->bypass_mask, val); rdev->desc->bypass_mask, val);
......
...@@ -327,7 +327,7 @@ static int lp3971_i2c_read(struct i2c_client *i2c, char reg, int count, ...@@ -327,7 +327,7 @@ static int lp3971_i2c_read(struct i2c_client *i2c, char reg, int count,
return -EIO; return -EIO;
ret = i2c_smbus_read_byte_data(i2c, reg); ret = i2c_smbus_read_byte_data(i2c, reg);
if (ret < 0) if (ret < 0)
return -EIO; return ret;
*dest = ret; *dest = ret;
return 0; return 0;
......
...@@ -211,7 +211,7 @@ static int lp872x_get_timestep_usec(struct lp872x *lp) ...@@ -211,7 +211,7 @@ static int lp872x_get_timestep_usec(struct lp872x *lp)
ret = lp872x_read_byte(lp, LP872X_GENERAL_CFG, &val); ret = lp872x_read_byte(lp, LP872X_GENERAL_CFG, &val);
if (ret) if (ret)
return -EINVAL; return ret;
val = (val & mask) >> shift; val = (val & mask) >> shift;
if (val >= size) if (val >= size)
...@@ -229,7 +229,7 @@ static int lp872x_regulator_enable_time(struct regulator_dev *rdev) ...@@ -229,7 +229,7 @@ static int lp872x_regulator_enable_time(struct regulator_dev *rdev)
u8 addr, val; u8 addr, val;
if (time_step_us < 0) if (time_step_us < 0)
return -EINVAL; return time_step_us;
switch (rid) { switch (rid) {
case LP8720_ID_LDO1 ... LP8720_ID_BUCK: case LP8720_ID_LDO1 ... LP8720_ID_BUCK:
......
/* /*
* max14577.c - Regulator driver for the Maxim 14577 * max14577.c - Regulator driver for the Maxim 14577
* *
* Copyright (C) 2013 Samsung Electronics * Copyright (C) 2013,2014 Samsung Electronics
* Krzysztof Kozlowski <k.kozlowski@samsung.com> * Krzysztof Kozlowski <k.kozlowski@samsung.com>
* *
* This program is free software; you can redistribute it and/or modify * This program is free software; you can redistribute it and/or modify
...@@ -22,12 +22,6 @@ ...@@ -22,12 +22,6 @@
#include <linux/mfd/max14577-private.h> #include <linux/mfd/max14577-private.h>
#include <linux/regulator/of_regulator.h> #include <linux/regulator/of_regulator.h>
struct max14577_regulator {
struct device *dev;
struct max14577 *max14577;
struct regulator_dev **regulators;
};
static int max14577_reg_is_enabled(struct regulator_dev *rdev) static int max14577_reg_is_enabled(struct regulator_dev *rdev)
{ {
int rid = rdev_get_id(rdev); int rid = rdev_get_id(rdev);
......
...@@ -46,8 +46,6 @@ struct max1586_data { ...@@ -46,8 +46,6 @@ struct max1586_data {
unsigned int v3_curr_sel; unsigned int v3_curr_sel;
unsigned int v6_curr_sel; unsigned int v6_curr_sel;
struct regulator_dev *rdev[0];
}; };
/* /*
...@@ -162,14 +160,12 @@ static struct regulator_desc max1586_reg[] = { ...@@ -162,14 +160,12 @@ static struct regulator_desc max1586_reg[] = {
static int max1586_pmic_probe(struct i2c_client *client, static int max1586_pmic_probe(struct i2c_client *client,
const struct i2c_device_id *i2c_id) const struct i2c_device_id *i2c_id)
{ {
struct regulator_dev **rdev;
struct max1586_platform_data *pdata = dev_get_platdata(&client->dev); struct max1586_platform_data *pdata = dev_get_platdata(&client->dev);
struct regulator_config config = { }; struct regulator_config config = { };
struct max1586_data *max1586; struct max1586_data *max1586;
int i, id; int i, id;
max1586 = devm_kzalloc(&client->dev, sizeof(struct max1586_data) + max1586 = devm_kzalloc(&client->dev, sizeof(struct max1586_data),
sizeof(struct regulator_dev *) * (MAX1586_V6 + 1),
GFP_KERNEL); GFP_KERNEL);
if (!max1586) if (!max1586)
return -ENOMEM; return -ENOMEM;
...@@ -186,8 +182,9 @@ static int max1586_pmic_probe(struct i2c_client *client, ...@@ -186,8 +182,9 @@ static int max1586_pmic_probe(struct i2c_client *client,
max1586->v3_curr_sel = 24; /* 1.3V */ max1586->v3_curr_sel = 24; /* 1.3V */
max1586->v6_curr_sel = 0; max1586->v6_curr_sel = 0;
rdev = max1586->rdev;
for (i = 0; i < pdata->num_subdevs && i <= MAX1586_V6; i++) { for (i = 0; i < pdata->num_subdevs && i <= MAX1586_V6; i++) {
struct regulator_dev *rdev;
id = pdata->subdevs[i].id; id = pdata->subdevs[i].id;
if (!pdata->subdevs[i].platform_data) if (!pdata->subdevs[i].platform_data)
continue; continue;
...@@ -207,12 +204,12 @@ static int max1586_pmic_probe(struct i2c_client *client, ...@@ -207,12 +204,12 @@ static int max1586_pmic_probe(struct i2c_client *client,
config.init_data = pdata->subdevs[i].platform_data; config.init_data = pdata->subdevs[i].platform_data;
config.driver_data = max1586; config.driver_data = max1586;
rdev[i] = devm_regulator_register(&client->dev, rdev = devm_regulator_register(&client->dev,
&max1586_reg[id], &config); &max1586_reg[id], &config);
if (IS_ERR(rdev[i])) { if (IS_ERR(rdev)) {
dev_err(&client->dev, "failed to register %s\n", dev_err(&client->dev, "failed to register %s\n",
max1586_reg[id].name); max1586_reg[id].name);
return PTR_ERR(rdev[i]); return PTR_ERR(rdev);
} }
} }
......
...@@ -65,7 +65,6 @@ enum max77686_ramp_rate { ...@@ -65,7 +65,6 @@ enum max77686_ramp_rate {
}; };
struct max77686_data { struct max77686_data {
struct regulator_dev *rdev[MAX77686_REGULATORS];
unsigned int opmode[MAX77686_REGULATORS]; unsigned int opmode[MAX77686_REGULATORS];
}; };
...@@ -400,7 +399,7 @@ static int max77686_pmic_dt_parse_pdata(struct platform_device *pdev, ...@@ -400,7 +399,7 @@ static int max77686_pmic_dt_parse_pdata(struct platform_device *pdev,
unsigned int i; unsigned int i;
pmic_np = iodev->dev->of_node; pmic_np = iodev->dev->of_node;
regulators_np = of_find_node_by_name(pmic_np, "voltage-regulators"); regulators_np = of_get_child_by_name(pmic_np, "voltage-regulators");
if (!regulators_np) { if (!regulators_np) {
dev_err(&pdev->dev, "could not find regulators sub-node\n"); dev_err(&pdev->dev, "could not find regulators sub-node\n");
return -EINVAL; return -EINVAL;
...@@ -410,8 +409,7 @@ static int max77686_pmic_dt_parse_pdata(struct platform_device *pdev, ...@@ -410,8 +409,7 @@ static int max77686_pmic_dt_parse_pdata(struct platform_device *pdev,
rdata = devm_kzalloc(&pdev->dev, sizeof(*rdata) * rdata = devm_kzalloc(&pdev->dev, sizeof(*rdata) *
pdata->num_regulators, GFP_KERNEL); pdata->num_regulators, GFP_KERNEL);
if (!rdata) { if (!rdata) {
dev_err(&pdev->dev, of_node_put(regulators_np);
"could not allocate memory for regulator data\n");
return -ENOMEM; return -ENOMEM;
} }
...@@ -425,6 +423,7 @@ static int max77686_pmic_dt_parse_pdata(struct platform_device *pdev, ...@@ -425,6 +423,7 @@ static int max77686_pmic_dt_parse_pdata(struct platform_device *pdev,
} }
pdata->regulators = rdata; pdata->regulators = rdata;
of_node_put(regulators_np);
return 0; return 0;
} }
...@@ -474,16 +473,18 @@ static int max77686_pmic_probe(struct platform_device *pdev) ...@@ -474,16 +473,18 @@ static int max77686_pmic_probe(struct platform_device *pdev)
platform_set_drvdata(pdev, max77686); platform_set_drvdata(pdev, max77686);
for (i = 0; i < MAX77686_REGULATORS; i++) { for (i = 0; i < MAX77686_REGULATORS; i++) {
struct regulator_dev *rdev;
config.init_data = pdata->regulators[i].initdata; config.init_data = pdata->regulators[i].initdata;
config.of_node = pdata->regulators[i].of_node; config.of_node = pdata->regulators[i].of_node;
max77686->opmode[i] = regulators[i].enable_mask; max77686->opmode[i] = regulators[i].enable_mask;
max77686->rdev[i] = devm_regulator_register(&pdev->dev, rdev = devm_regulator_register(&pdev->dev,
&regulators[i], &config); &regulators[i], &config);
if (IS_ERR(max77686->rdev[i])) { if (IS_ERR(rdev)) {
dev_err(&pdev->dev, dev_err(&pdev->dev,
"regulator init failed for %d\n", i); "regulator init failed for %d\n", i);
return PTR_ERR(max77686->rdev[i]); return PTR_ERR(rdev);
} }
} }
......
...@@ -34,13 +34,6 @@ ...@@ -34,13 +34,6 @@
#define CHGIN_ILIM_STEP_20mA 20000 #define CHGIN_ILIM_STEP_20mA 20000
struct max77693_pmic_dev {
struct device *dev;
struct max77693_dev *iodev;
int num_regulators;
struct regulator_dev **rdev;
};
/* CHARGER regulator ops */ /* CHARGER regulator ops */
/* CHARGER regulator uses two bits for enabling */ /* CHARGER regulator uses two bits for enabling */
static int max77693_chg_is_enabled(struct regulator_dev *rdev) static int max77693_chg_is_enabled(struct regulator_dev *rdev)
...@@ -170,19 +163,22 @@ static int max77693_pmic_dt_parse_rdata(struct device *dev, ...@@ -170,19 +163,22 @@ static int max77693_pmic_dt_parse_rdata(struct device *dev,
struct max77693_regulator_data *tmp; struct max77693_regulator_data *tmp;
int i, matched = 0; int i, matched = 0;
np = of_find_node_by_name(dev->parent->of_node, "regulators"); np = of_get_child_by_name(dev->parent->of_node, "regulators");
if (!np) if (!np)
return -EINVAL; return -EINVAL;
rmatch = devm_kzalloc(dev, rmatch = devm_kzalloc(dev,
sizeof(*rmatch) * ARRAY_SIZE(regulators), GFP_KERNEL); sizeof(*rmatch) * ARRAY_SIZE(regulators), GFP_KERNEL);
if (!rmatch) if (!rmatch) {
of_node_put(np);
return -ENOMEM; return -ENOMEM;
}
for (i = 0; i < ARRAY_SIZE(regulators); i++) for (i = 0; i < ARRAY_SIZE(regulators); i++)
rmatch[i].name = regulators[i].name; rmatch[i].name = regulators[i].name;
matched = of_regulator_match(dev, np, rmatch, ARRAY_SIZE(regulators)); matched = of_regulator_match(dev, np, rmatch, ARRAY_SIZE(regulators));
of_node_put(np);
if (matched <= 0) if (matched <= 0)
return matched; return matched;
*rdata = devm_kzalloc(dev, sizeof(**rdata) * matched, GFP_KERNEL); *rdata = devm_kzalloc(dev, sizeof(**rdata) * matched, GFP_KERNEL);
...@@ -229,7 +225,6 @@ static int max77693_pmic_init_rdata(struct device *dev, ...@@ -229,7 +225,6 @@ static int max77693_pmic_init_rdata(struct device *dev,
static int max77693_pmic_probe(struct platform_device *pdev) static int max77693_pmic_probe(struct platform_device *pdev)
{ {
struct max77693_dev *iodev = dev_get_drvdata(pdev->dev.parent); struct max77693_dev *iodev = dev_get_drvdata(pdev->dev.parent);
struct max77693_pmic_dev *max77693_pmic;
struct max77693_regulator_data *rdata = NULL; struct max77693_regulator_data *rdata = NULL;
int num_rdata, i; int num_rdata, i;
struct regulator_config config; struct regulator_config config;
...@@ -240,39 +235,22 @@ static int max77693_pmic_probe(struct platform_device *pdev) ...@@ -240,39 +235,22 @@ static int max77693_pmic_probe(struct platform_device *pdev)
return -ENODEV; return -ENODEV;
} }
max77693_pmic = devm_kzalloc(&pdev->dev,
sizeof(struct max77693_pmic_dev),
GFP_KERNEL);
if (!max77693_pmic)
return -ENOMEM;
max77693_pmic->rdev = devm_kzalloc(&pdev->dev,
sizeof(struct regulator_dev *) * num_rdata,
GFP_KERNEL);
if (!max77693_pmic->rdev)
return -ENOMEM;
max77693_pmic->dev = &pdev->dev;
max77693_pmic->iodev = iodev;
max77693_pmic->num_regulators = num_rdata;
config.dev = &pdev->dev; config.dev = &pdev->dev;
config.regmap = iodev->regmap; config.regmap = iodev->regmap;
config.driver_data = max77693_pmic;
platform_set_drvdata(pdev, max77693_pmic);
for (i = 0; i < max77693_pmic->num_regulators; i++) { for (i = 0; i < num_rdata; i++) {
int id = rdata[i].id; int id = rdata[i].id;
struct regulator_dev *rdev;
config.init_data = rdata[i].initdata; config.init_data = rdata[i].initdata;
config.of_node = rdata[i].of_node; config.of_node = rdata[i].of_node;
max77693_pmic->rdev[i] = devm_regulator_register(&pdev->dev, rdev = devm_regulator_register(&pdev->dev,
&regulators[id], &config); &regulators[id], &config);
if (IS_ERR(max77693_pmic->rdev[i])) { if (IS_ERR(rdev)) {
dev_err(max77693_pmic->dev, dev_err(&pdev->dev,
"Failed to initialize regulator-%d\n", id); "Failed to initialize regulator-%d\n", id);
return PTR_ERR(max77693_pmic->rdev[i]); return PTR_ERR(rdev);
} }
} }
......
...@@ -49,7 +49,6 @@ ...@@ -49,7 +49,6 @@
#define MAX8649_RAMP_DOWN (1 << 1) #define MAX8649_RAMP_DOWN (1 << 1)
struct max8649_regulator_info { struct max8649_regulator_info {
struct regulator_dev *regulator;
struct device *dev; struct device *dev;
struct regmap *regmap; struct regmap *regmap;
...@@ -154,6 +153,7 @@ static int max8649_regulator_probe(struct i2c_client *client, ...@@ -154,6 +153,7 @@ static int max8649_regulator_probe(struct i2c_client *client,
{ {
struct max8649_platform_data *pdata = dev_get_platdata(&client->dev); struct max8649_platform_data *pdata = dev_get_platdata(&client->dev);
struct max8649_regulator_info *info = NULL; struct max8649_regulator_info *info = NULL;
struct regulator_dev *regulator;
struct regulator_config config = { }; struct regulator_config config = { };
unsigned int val; unsigned int val;
unsigned char data; unsigned char data;
...@@ -234,12 +234,12 @@ static int max8649_regulator_probe(struct i2c_client *client, ...@@ -234,12 +234,12 @@ static int max8649_regulator_probe(struct i2c_client *client,
config.driver_data = info; config.driver_data = info;
config.regmap = info->regmap; config.regmap = info->regmap;
info->regulator = devm_regulator_register(&client->dev, &dcdc_desc, regulator = devm_regulator_register(&client->dev, &dcdc_desc,
&config); &config);
if (IS_ERR(info->regulator)) { if (IS_ERR(regulator)) {
dev_err(info->dev, "failed to register regulator %s\n", dev_err(info->dev, "failed to register regulator %s\n",
dcdc_desc.name); dcdc_desc.name);
return PTR_ERR(info->regulator); return PTR_ERR(regulator);
} }
return 0; return 0;
......
...@@ -81,16 +81,17 @@ enum { ...@@ -81,16 +81,17 @@ enum {
struct max8660 { struct max8660 {
struct i2c_client *client; struct i2c_client *client;
u8 shadow_regs[MAX8660_N_REGS]; /* as chip is write only */ u8 shadow_regs[MAX8660_N_REGS]; /* as chip is write only */
struct regulator_dev *rdev[];
}; };
static int max8660_write(struct max8660 *max8660, u8 reg, u8 mask, u8 val) static int max8660_write(struct max8660 *max8660, u8 reg, u8 mask, u8 val)
{ {
static const u8 max8660_addresses[MAX8660_N_REGS] = static const u8 max8660_addresses[MAX8660_N_REGS] = {
{ 0x10, 0x12, 0x20, 0x23, 0x24, 0x29, 0x2a, 0x32, 0x33, 0x39, 0x80 }; 0x10, 0x12, 0x20, 0x23, 0x24, 0x29, 0x2a, 0x32, 0x33, 0x39, 0x80
};
int ret; int ret;
u8 reg_val = (max8660->shadow_regs[reg] & mask) | val; u8 reg_val = (max8660->shadow_regs[reg] & mask) | val;
dev_vdbg(&max8660->client->dev, "Writing reg %02x with %02x\n", dev_vdbg(&max8660->client->dev, "Writing reg %02x with %02x\n",
max8660_addresses[reg], reg_val); max8660_addresses[reg], reg_val);
...@@ -112,6 +113,7 @@ static int max8660_dcdc_is_enabled(struct regulator_dev *rdev) ...@@ -112,6 +113,7 @@ static int max8660_dcdc_is_enabled(struct regulator_dev *rdev)
struct max8660 *max8660 = rdev_get_drvdata(rdev); struct max8660 *max8660 = rdev_get_drvdata(rdev);
u8 val = max8660->shadow_regs[MAX8660_OVER1]; u8 val = max8660->shadow_regs[MAX8660_OVER1];
u8 mask = (rdev_get_id(rdev) == MAX8660_V3) ? 1 : 4; u8 mask = (rdev_get_id(rdev) == MAX8660_V3) ? 1 : 4;
return !!(val & mask); return !!(val & mask);
} }
...@@ -119,6 +121,7 @@ static int max8660_dcdc_enable(struct regulator_dev *rdev) ...@@ -119,6 +121,7 @@ static int max8660_dcdc_enable(struct regulator_dev *rdev)
{ {
struct max8660 *max8660 = rdev_get_drvdata(rdev); struct max8660 *max8660 = rdev_get_drvdata(rdev);
u8 bit = (rdev_get_id(rdev) == MAX8660_V3) ? 1 : 4; u8 bit = (rdev_get_id(rdev) == MAX8660_V3) ? 1 : 4;
return max8660_write(max8660, MAX8660_OVER1, 0xff, bit); return max8660_write(max8660, MAX8660_OVER1, 0xff, bit);
} }
...@@ -126,15 +129,16 @@ static int max8660_dcdc_disable(struct regulator_dev *rdev) ...@@ -126,15 +129,16 @@ static int max8660_dcdc_disable(struct regulator_dev *rdev)
{ {
struct max8660 *max8660 = rdev_get_drvdata(rdev); struct max8660 *max8660 = rdev_get_drvdata(rdev);
u8 mask = (rdev_get_id(rdev) == MAX8660_V3) ? ~1 : ~4; u8 mask = (rdev_get_id(rdev) == MAX8660_V3) ? ~1 : ~4;
return max8660_write(max8660, MAX8660_OVER1, mask, 0); return max8660_write(max8660, MAX8660_OVER1, mask, 0);
} }
static int max8660_dcdc_get_voltage_sel(struct regulator_dev *rdev) static int max8660_dcdc_get_voltage_sel(struct regulator_dev *rdev)
{ {
struct max8660 *max8660 = rdev_get_drvdata(rdev); struct max8660 *max8660 = rdev_get_drvdata(rdev);
u8 reg = (rdev_get_id(rdev) == MAX8660_V3) ? MAX8660_ADTV2 : MAX8660_SDTV2; u8 reg = (rdev_get_id(rdev) == MAX8660_V3) ? MAX8660_ADTV2 : MAX8660_SDTV2;
u8 selector = max8660->shadow_regs[reg]; u8 selector = max8660->shadow_regs[reg];
return selector; return selector;
} }
...@@ -207,6 +211,7 @@ static int max8660_ldo67_is_enabled(struct regulator_dev *rdev) ...@@ -207,6 +211,7 @@ static int max8660_ldo67_is_enabled(struct regulator_dev *rdev)
struct max8660 *max8660 = rdev_get_drvdata(rdev); struct max8660 *max8660 = rdev_get_drvdata(rdev);
u8 val = max8660->shadow_regs[MAX8660_OVER2]; u8 val = max8660->shadow_regs[MAX8660_OVER2];
u8 mask = (rdev_get_id(rdev) == MAX8660_V6) ? 2 : 4; u8 mask = (rdev_get_id(rdev) == MAX8660_V6) ? 2 : 4;
return !!(val & mask); return !!(val & mask);
} }
...@@ -214,6 +219,7 @@ static int max8660_ldo67_enable(struct regulator_dev *rdev) ...@@ -214,6 +219,7 @@ static int max8660_ldo67_enable(struct regulator_dev *rdev)
{ {
struct max8660 *max8660 = rdev_get_drvdata(rdev); struct max8660 *max8660 = rdev_get_drvdata(rdev);
u8 bit = (rdev_get_id(rdev) == MAX8660_V6) ? 2 : 4; u8 bit = (rdev_get_id(rdev) == MAX8660_V6) ? 2 : 4;
return max8660_write(max8660, MAX8660_OVER2, 0xff, bit); return max8660_write(max8660, MAX8660_OVER2, 0xff, bit);
} }
...@@ -221,15 +227,16 @@ static int max8660_ldo67_disable(struct regulator_dev *rdev) ...@@ -221,15 +227,16 @@ static int max8660_ldo67_disable(struct regulator_dev *rdev)
{ {
struct max8660 *max8660 = rdev_get_drvdata(rdev); struct max8660 *max8660 = rdev_get_drvdata(rdev);
u8 mask = (rdev_get_id(rdev) == MAX8660_V6) ? ~2 : ~4; u8 mask = (rdev_get_id(rdev) == MAX8660_V6) ? ~2 : ~4;
return max8660_write(max8660, MAX8660_OVER2, mask, 0); return max8660_write(max8660, MAX8660_OVER2, mask, 0);
} }
static int max8660_ldo67_get_voltage_sel(struct regulator_dev *rdev) static int max8660_ldo67_get_voltage_sel(struct regulator_dev *rdev)
{ {
struct max8660 *max8660 = rdev_get_drvdata(rdev); struct max8660 *max8660 = rdev_get_drvdata(rdev);
u8 shift = (rdev_get_id(rdev) == MAX8660_V6) ? 0 : 4; u8 shift = (rdev_get_id(rdev) == MAX8660_V6) ? 0 : 4;
u8 selector = (max8660->shadow_regs[MAX8660_L12VCR] >> shift) & 0xf; u8 selector = (max8660->shadow_regs[MAX8660_L12VCR] >> shift) & 0xf;
return selector; return selector;
} }
...@@ -330,7 +337,7 @@ static int max8660_pdata_from_dt(struct device *dev, ...@@ -330,7 +337,7 @@ static int max8660_pdata_from_dt(struct device *dev,
struct max8660_subdev_data *sub; struct max8660_subdev_data *sub;
struct of_regulator_match rmatch[ARRAY_SIZE(max8660_reg)]; struct of_regulator_match rmatch[ARRAY_SIZE(max8660_reg)];
np = of_find_node_by_name(dev->of_node, "regulators"); np = of_get_child_by_name(dev->of_node, "regulators");
if (!np) { if (!np) {
dev_err(dev, "missing 'regulators' subnode in DT\n"); dev_err(dev, "missing 'regulators' subnode in DT\n");
return -EINVAL; return -EINVAL;
...@@ -340,6 +347,7 @@ static int max8660_pdata_from_dt(struct device *dev, ...@@ -340,6 +347,7 @@ static int max8660_pdata_from_dt(struct device *dev,
rmatch[i].name = max8660_reg[i].name; rmatch[i].name = max8660_reg[i].name;
matched = of_regulator_match(dev, np, rmatch, ARRAY_SIZE(rmatch)); matched = of_regulator_match(dev, np, rmatch, ARRAY_SIZE(rmatch));
of_node_put(np);
if (matched <= 0) if (matched <= 0)
return matched; return matched;
...@@ -373,7 +381,6 @@ static inline int max8660_pdata_from_dt(struct device *dev, ...@@ -373,7 +381,6 @@ static inline int max8660_pdata_from_dt(struct device *dev,
static int max8660_probe(struct i2c_client *client, static int max8660_probe(struct i2c_client *client,
const struct i2c_device_id *i2c_id) const struct i2c_device_id *i2c_id)
{ {
struct regulator_dev **rdev;
struct device *dev = &client->dev; struct device *dev = &client->dev;
struct max8660_platform_data *pdata = dev_get_platdata(dev); struct max8660_platform_data *pdata = dev_get_platdata(dev);
struct regulator_config config = { }; struct regulator_config config = { };
...@@ -406,14 +413,11 @@ static int max8660_probe(struct i2c_client *client, ...@@ -406,14 +413,11 @@ static int max8660_probe(struct i2c_client *client,
return -EINVAL; return -EINVAL;
} }
max8660 = devm_kzalloc(dev, sizeof(struct max8660) + max8660 = devm_kzalloc(dev, sizeof(struct max8660), GFP_KERNEL);
sizeof(struct regulator_dev *) * MAX8660_V_END,
GFP_KERNEL);
if (!max8660) if (!max8660)
return -ENOMEM; return -ENOMEM;
max8660->client = client; max8660->client = client;
rdev = max8660->rdev;
if (pdata->en34_is_high) { if (pdata->en34_is_high) {
/* Simulate always on */ /* Simulate always on */
...@@ -481,6 +485,7 @@ static int max8660_probe(struct i2c_client *client, ...@@ -481,6 +485,7 @@ static int max8660_probe(struct i2c_client *client,
/* Finally register devices */ /* Finally register devices */
for (i = 0; i < pdata->num_subdevs; i++) { for (i = 0; i < pdata->num_subdevs; i++) {
struct regulator_dev *rdev;
id = pdata->subdevs[i].id; id = pdata->subdevs[i].id;
...@@ -489,13 +494,13 @@ static int max8660_probe(struct i2c_client *client, ...@@ -489,13 +494,13 @@ static int max8660_probe(struct i2c_client *client,
config.of_node = of_node[i]; config.of_node = of_node[i];
config.driver_data = max8660; config.driver_data = max8660;
rdev[i] = devm_regulator_register(&client->dev, rdev = devm_regulator_register(&client->dev,
&max8660_reg[id], &config); &max8660_reg[id], &config);
if (IS_ERR(rdev[i])) { if (IS_ERR(rdev)) {
ret = PTR_ERR(rdev[i]); ret = PTR_ERR(rdev);
dev_err(&client->dev, "failed to register %s\n", dev_err(&client->dev, "failed to register %s\n",
max8660_reg[id].name); max8660_reg[id].name);
return PTR_ERR(rdev[i]); return PTR_ERR(rdev);
} }
} }
......
...@@ -34,7 +34,6 @@ ...@@ -34,7 +34,6 @@
struct max8907_regulator { struct max8907_regulator {
struct regulator_desc desc[MAX8907_NUM_REGULATORS]; struct regulator_desc desc[MAX8907_NUM_REGULATORS];
struct regulator_dev *rdev[MAX8907_NUM_REGULATORS];
}; };
#define REG_MBATT() \ #define REG_MBATT() \
...@@ -231,7 +230,7 @@ static int max8907_regulator_parse_dt(struct platform_device *pdev) ...@@ -231,7 +230,7 @@ static int max8907_regulator_parse_dt(struct platform_device *pdev)
if (!np) if (!np)
return 0; return 0;
regulators = of_find_node_by_name(np, "regulators"); regulators = of_get_child_by_name(np, "regulators");
if (!regulators) { if (!regulators) {
dev_err(&pdev->dev, "regulators node not found\n"); dev_err(&pdev->dev, "regulators node not found\n");
return -EINVAL; return -EINVAL;
...@@ -292,10 +291,9 @@ static int max8907_regulator_probe(struct platform_device *pdev) ...@@ -292,10 +291,9 @@ static int max8907_regulator_probe(struct platform_device *pdev)
return ret; return ret;
pmic = devm_kzalloc(&pdev->dev, sizeof(*pmic), GFP_KERNEL); pmic = devm_kzalloc(&pdev->dev, sizeof(*pmic), GFP_KERNEL);
if (!pmic) { if (!pmic)
dev_err(&pdev->dev, "Failed to alloc pmic\n");
return -ENOMEM; return -ENOMEM;
}
platform_set_drvdata(pdev, pmic); platform_set_drvdata(pdev, pmic);
memcpy(pmic->desc, max8907_regulators, sizeof(pmic->desc)); memcpy(pmic->desc, max8907_regulators, sizeof(pmic->desc));
...@@ -311,6 +309,8 @@ static int max8907_regulator_probe(struct platform_device *pdev) ...@@ -311,6 +309,8 @@ static int max8907_regulator_probe(struct platform_device *pdev)
} }
for (i = 0; i < MAX8907_NUM_REGULATORS; i++) { for (i = 0; i < MAX8907_NUM_REGULATORS; i++) {
struct regulator_dev *rdev;
config.dev = pdev->dev.parent; config.dev = pdev->dev.parent;
if (pdata) if (pdata)
idata = pdata->init_data[i]; idata = pdata->init_data[i];
...@@ -350,13 +350,13 @@ static int max8907_regulator_probe(struct platform_device *pdev) ...@@ -350,13 +350,13 @@ static int max8907_regulator_probe(struct platform_device *pdev)
pmic->desc[i].ops = &max8907_out5v_hwctl_ops; pmic->desc[i].ops = &max8907_out5v_hwctl_ops;
} }
pmic->rdev[i] = devm_regulator_register(&pdev->dev, rdev = devm_regulator_register(&pdev->dev,
&pmic->desc[i], &config); &pmic->desc[i], &config);
if (IS_ERR(pmic->rdev[i])) { if (IS_ERR(rdev)) {
dev_err(&pdev->dev, dev_err(&pdev->dev,
"failed to register %s regulator\n", "failed to register %s regulator\n",
pmic->desc[i].name); pmic->desc[i].name);
return PTR_ERR(pmic->rdev[i]); return PTR_ERR(rdev);
} }
} }
......
...@@ -36,9 +36,7 @@ ...@@ -36,9 +36,7 @@
struct max8925_regulator_info { struct max8925_regulator_info {
struct regulator_desc desc; struct regulator_desc desc;
struct regulator_dev *regulator;
struct i2c_client *i2c; struct i2c_client *i2c;
struct max8925_chip *chip;
int vol_reg; int vol_reg;
int enable_reg; int enable_reg;
...@@ -251,10 +249,11 @@ static int max8925_regulator_dt_init(struct platform_device *pdev, ...@@ -251,10 +249,11 @@ static int max8925_regulator_dt_init(struct platform_device *pdev,
{ {
struct device_node *nproot, *np; struct device_node *nproot, *np;
int rcount; int rcount;
nproot = of_node_get(pdev->dev.parent->of_node); nproot = of_node_get(pdev->dev.parent->of_node);
if (!nproot) if (!nproot)
return -ENODEV; return -ENODEV;
np = of_find_node_by_name(nproot, "regulators"); np = of_get_child_by_name(nproot, "regulators");
if (!np) { if (!np) {
dev_err(&pdev->dev, "failed to find regulators node\n"); dev_err(&pdev->dev, "failed to find regulators node\n");
return -ENODEV; return -ENODEV;
...@@ -264,7 +263,7 @@ static int max8925_regulator_dt_init(struct platform_device *pdev, ...@@ -264,7 +263,7 @@ static int max8925_regulator_dt_init(struct platform_device *pdev,
&max8925_regulator_matches[ridx], 1); &max8925_regulator_matches[ridx], 1);
of_node_put(np); of_node_put(np);
if (rcount < 0) if (rcount < 0)
return -ENODEV; return rcount;
config->init_data = max8925_regulator_matches[ridx].init_data; config->init_data = max8925_regulator_matches[ridx].init_data;
config->of_node = max8925_regulator_matches[ridx].of_node; config->of_node = max8925_regulator_matches[ridx].of_node;
...@@ -303,7 +302,6 @@ static int max8925_regulator_probe(struct platform_device *pdev) ...@@ -303,7 +302,6 @@ static int max8925_regulator_probe(struct platform_device *pdev)
return -EINVAL; return -EINVAL;
} }
ri->i2c = chip->i2c; ri->i2c = chip->i2c;
ri->chip = chip;
config.dev = &pdev->dev; config.dev = &pdev->dev;
config.driver_data = ri; config.driver_data = ri;
......
...@@ -48,9 +48,7 @@ enum { ...@@ -48,9 +48,7 @@ enum {
struct max8952_data { struct max8952_data {
struct i2c_client *client; struct i2c_client *client;
struct device *dev;
struct max8952_platform_data *pdata; struct max8952_platform_data *pdata;
struct regulator_dev *rdev;
bool vid0; bool vid0;
bool vid1; bool vid1;
...@@ -59,6 +57,7 @@ struct max8952_data { ...@@ -59,6 +57,7 @@ struct max8952_data {
static int max8952_read_reg(struct max8952_data *max8952, u8 reg) static int max8952_read_reg(struct max8952_data *max8952, u8 reg)
{ {
int ret = i2c_smbus_read_byte_data(max8952->client, reg); int ret = i2c_smbus_read_byte_data(max8952->client, reg);
if (ret > 0) if (ret > 0)
ret &= 0xff; ret &= 0xff;
...@@ -144,10 +143,8 @@ static struct max8952_platform_data *max8952_parse_dt(struct device *dev) ...@@ -144,10 +143,8 @@ static struct max8952_platform_data *max8952_parse_dt(struct device *dev)
int i; int i;
pd = devm_kzalloc(dev, sizeof(*pd), GFP_KERNEL); pd = devm_kzalloc(dev, sizeof(*pd), GFP_KERNEL);
if (!pd) { if (!pd)
dev_err(dev, "Failed to allocate platform data\n");
return NULL; return NULL;
}
pd->gpio_vid0 = of_get_named_gpio(np, "max8952,vid-gpios", 0); pd->gpio_vid0 = of_get_named_gpio(np, "max8952,vid-gpios", 0);
pd->gpio_vid1 = of_get_named_gpio(np, "max8952,vid-gpios", 1); pd->gpio_vid1 = of_get_named_gpio(np, "max8952,vid-gpios", 1);
...@@ -199,6 +196,7 @@ static int max8952_pmic_probe(struct i2c_client *client, ...@@ -199,6 +196,7 @@ static int max8952_pmic_probe(struct i2c_client *client,
struct max8952_platform_data *pdata = dev_get_platdata(&client->dev); struct max8952_platform_data *pdata = dev_get_platdata(&client->dev);
struct regulator_config config = { }; struct regulator_config config = { };
struct max8952_data *max8952; struct max8952_data *max8952;
struct regulator_dev *rdev;
int ret = 0, err = 0; int ret = 0, err = 0;
...@@ -219,10 +217,9 @@ static int max8952_pmic_probe(struct i2c_client *client, ...@@ -219,10 +217,9 @@ static int max8952_pmic_probe(struct i2c_client *client,
return -ENOMEM; return -ENOMEM;
max8952->client = client; max8952->client = client;
max8952->dev = &client->dev;
max8952->pdata = pdata; max8952->pdata = pdata;
config.dev = max8952->dev; config.dev = &client->dev;
config.init_data = pdata->reg_data; config.init_data = pdata->reg_data;
config.driver_data = max8952; config.driver_data = max8952;
config.of_node = client->dev.of_node; config.of_node = client->dev.of_node;
...@@ -231,11 +228,11 @@ static int max8952_pmic_probe(struct i2c_client *client, ...@@ -231,11 +228,11 @@ static int max8952_pmic_probe(struct i2c_client *client,
if (pdata->reg_data->constraints.boot_on) if (pdata->reg_data->constraints.boot_on)
config.ena_gpio_flags |= GPIOF_OUT_INIT_HIGH; config.ena_gpio_flags |= GPIOF_OUT_INIT_HIGH;
max8952->rdev = regulator_register(&regulator, &config); rdev = devm_regulator_register(&client->dev, &regulator, &config);
if (IS_ERR(max8952->rdev)) { if (IS_ERR(rdev)) {
ret = PTR_ERR(max8952->rdev); ret = PTR_ERR(rdev);
dev_err(max8952->dev, "regulator init failed (%d)\n", ret); dev_err(&client->dev, "regulator init failed (%d)\n", ret);
return ret; return ret;
} }
...@@ -263,7 +260,7 @@ static int max8952_pmic_probe(struct i2c_client *client, ...@@ -263,7 +260,7 @@ static int max8952_pmic_probe(struct i2c_client *client,
err = 3; err = 3;
if (err) { if (err) {
dev_warn(max8952->dev, "VID0/1 gpio invalid: " dev_warn(&client->dev, "VID0/1 gpio invalid: "
"DVS not available.\n"); "DVS not available.\n");
max8952->vid0 = 0; max8952->vid0 = 0;
max8952->vid1 = 0; max8952->vid1 = 0;
...@@ -274,7 +271,7 @@ static int max8952_pmic_probe(struct i2c_client *client, ...@@ -274,7 +271,7 @@ static int max8952_pmic_probe(struct i2c_client *client,
/* Disable Pulldown of EN only */ /* Disable Pulldown of EN only */
max8952_write_reg(max8952, MAX8952_REG_CONTROL, 0x60); max8952_write_reg(max8952, MAX8952_REG_CONTROL, 0x60);
dev_err(max8952->dev, "DVS modes disabled because VID0 and VID1" dev_err(&client->dev, "DVS modes disabled because VID0 and VID1"
" do not have proper controls.\n"); " do not have proper controls.\n");
} else { } else {
/* /*
...@@ -321,9 +318,6 @@ static int max8952_pmic_remove(struct i2c_client *client) ...@@ -321,9 +318,6 @@ static int max8952_pmic_remove(struct i2c_client *client)
{ {
struct max8952_data *max8952 = i2c_get_clientdata(client); struct max8952_data *max8952 = i2c_get_clientdata(client);
struct max8952_platform_data *pdata = max8952->pdata; struct max8952_platform_data *pdata = max8952->pdata;
struct regulator_dev *rdev = max8952->rdev;
regulator_unregister(rdev);
gpio_free(pdata->gpio_vid0); gpio_free(pdata->gpio_vid0);
gpio_free(pdata->gpio_vid1); gpio_free(pdata->gpio_vid1);
......
...@@ -93,7 +93,6 @@ ...@@ -93,7 +93,6 @@
struct max8973_chip { struct max8973_chip {
struct device *dev; struct device *dev;
struct regulator_desc desc; struct regulator_desc desc;
struct regulator_dev *rdev;
struct regmap *regmap; struct regmap *regmap;
bool enable_external_control; bool enable_external_control;
int dvs_gpio; int dvs_gpio;
...@@ -379,10 +378,8 @@ static int max8973_probe(struct i2c_client *client, ...@@ -379,10 +378,8 @@ static int max8973_probe(struct i2c_client *client,
} }
max = devm_kzalloc(&client->dev, sizeof(*max), GFP_KERNEL); max = devm_kzalloc(&client->dev, sizeof(*max), GFP_KERNEL);
if (!max) { if (!max)
dev_err(&client->dev, "Memory allocation for max failed\n");
return -ENOMEM; return -ENOMEM;
}
max->regmap = devm_regmap_init_i2c(client, &max8973_regmap_config); max->regmap = devm_regmap_init_i2c(client, &max8973_regmap_config);
if (IS_ERR(max->regmap)) { if (IS_ERR(max->regmap)) {
...@@ -474,7 +471,6 @@ static int max8973_probe(struct i2c_client *client, ...@@ -474,7 +471,6 @@ static int max8973_probe(struct i2c_client *client,
return ret; return ret;
} }
max->rdev = rdev;
return 0; return 0;
} }
......
...@@ -38,7 +38,6 @@ struct max8997_data { ...@@ -38,7 +38,6 @@ struct max8997_data {
struct device *dev; struct device *dev;
struct max8997_dev *iodev; struct max8997_dev *iodev;
int num_regulators; int num_regulators;
struct regulator_dev **rdev;
int ramp_delay; /* in mV/us */ int ramp_delay; /* in mV/us */
bool buck1_gpiodvs; bool buck1_gpiodvs;
...@@ -924,7 +923,7 @@ static int max8997_pmic_dt_parse_pdata(struct platform_device *pdev, ...@@ -924,7 +923,7 @@ static int max8997_pmic_dt_parse_pdata(struct platform_device *pdev,
return -ENODEV; return -ENODEV;
} }
regulators_np = of_find_node_by_name(pmic_np, "regulators"); regulators_np = of_get_child_by_name(pmic_np, "regulators");
if (!regulators_np) { if (!regulators_np) {
dev_err(&pdev->dev, "could not find regulators sub-node\n"); dev_err(&pdev->dev, "could not find regulators sub-node\n");
return -EINVAL; return -EINVAL;
...@@ -937,7 +936,6 @@ static int max8997_pmic_dt_parse_pdata(struct platform_device *pdev, ...@@ -937,7 +936,6 @@ static int max8997_pmic_dt_parse_pdata(struct platform_device *pdev,
pdata->num_regulators, GFP_KERNEL); pdata->num_regulators, GFP_KERNEL);
if (!rdata) { if (!rdata) {
of_node_put(regulators_np); of_node_put(regulators_np);
dev_err(&pdev->dev, "could not allocate memory for regulator data\n");
return -ENOMEM; return -ENOMEM;
} }
...@@ -1030,10 +1028,10 @@ static int max8997_pmic_probe(struct platform_device *pdev) ...@@ -1030,10 +1028,10 @@ static int max8997_pmic_probe(struct platform_device *pdev)
struct max8997_dev *iodev = dev_get_drvdata(pdev->dev.parent); struct max8997_dev *iodev = dev_get_drvdata(pdev->dev.parent);
struct max8997_platform_data *pdata = iodev->pdata; struct max8997_platform_data *pdata = iodev->pdata;
struct regulator_config config = { }; struct regulator_config config = { };
struct regulator_dev **rdev; struct regulator_dev *rdev;
struct max8997_data *max8997; struct max8997_data *max8997;
struct i2c_client *i2c; struct i2c_client *i2c;
int i, ret, size, nr_dvs; int i, ret, nr_dvs;
u8 max_buck1 = 0, max_buck2 = 0, max_buck5 = 0; u8 max_buck1 = 0, max_buck2 = 0, max_buck5 = 0;
if (!pdata) { if (!pdata) {
...@@ -1052,12 +1050,6 @@ static int max8997_pmic_probe(struct platform_device *pdev) ...@@ -1052,12 +1050,6 @@ static int max8997_pmic_probe(struct platform_device *pdev)
if (!max8997) if (!max8997)
return -ENOMEM; return -ENOMEM;
size = sizeof(struct regulator_dev *) * pdata->num_regulators;
max8997->rdev = devm_kzalloc(&pdev->dev, size, GFP_KERNEL);
if (!max8997->rdev)
return -ENOMEM;
rdev = max8997->rdev;
max8997->dev = &pdev->dev; max8997->dev = &pdev->dev;
max8997->iodev = iodev; max8997->iodev = iodev;
max8997->num_regulators = pdata->num_regulators; max8997->num_regulators = pdata->num_regulators;
...@@ -1205,12 +1197,12 @@ static int max8997_pmic_probe(struct platform_device *pdev) ...@@ -1205,12 +1197,12 @@ static int max8997_pmic_probe(struct platform_device *pdev)
config.driver_data = max8997; config.driver_data = max8997;
config.of_node = pdata->regulators[i].reg_node; config.of_node = pdata->regulators[i].reg_node;
rdev[i] = devm_regulator_register(&pdev->dev, &regulators[id], rdev = devm_regulator_register(&pdev->dev, &regulators[id],
&config); &config);
if (IS_ERR(rdev[i])) { if (IS_ERR(rdev)) {
dev_err(max8997->dev, "regulator init failed for %d\n", dev_err(max8997->dev, "regulator init failed for %d\n",
id); id);
return PTR_ERR(rdev[i]); return PTR_ERR(rdev);
} }
} }
......
...@@ -40,7 +40,6 @@ struct max8998_data { ...@@ -40,7 +40,6 @@ struct max8998_data {
struct device *dev; struct device *dev;
struct max8998_dev *iodev; struct max8998_dev *iodev;
int num_regulators; int num_regulators;
struct regulator_dev **rdev;
u8 buck1_vol[4]; /* voltages for selection */ u8 buck1_vol[4]; /* voltages for selection */
u8 buck2_vol[2]; u8 buck2_vol[2];
unsigned int buck1_idx; /* index to last changed voltage */ unsigned int buck1_idx; /* index to last changed voltage */
...@@ -674,8 +673,10 @@ static int max8998_pmic_dt_parse_pdata(struct max8998_dev *iodev, ...@@ -674,8 +673,10 @@ static int max8998_pmic_dt_parse_pdata(struct max8998_dev *iodev,
rdata = devm_kzalloc(iodev->dev, sizeof(*rdata) * rdata = devm_kzalloc(iodev->dev, sizeof(*rdata) *
pdata->num_regulators, GFP_KERNEL); pdata->num_regulators, GFP_KERNEL);
if (!rdata) if (!rdata) {
of_node_put(regulators_np);
return -ENOMEM; return -ENOMEM;
}
pdata->regulators = rdata; pdata->regulators = rdata;
for (i = 0; i < ARRAY_SIZE(regulators); ++i) { for (i = 0; i < ARRAY_SIZE(regulators); ++i) {
...@@ -692,6 +693,9 @@ static int max8998_pmic_dt_parse_pdata(struct max8998_dev *iodev, ...@@ -692,6 +693,9 @@ static int max8998_pmic_dt_parse_pdata(struct max8998_dev *iodev,
} }
pdata->num_regulators = rdata - pdata->regulators; pdata->num_regulators = rdata - pdata->regulators;
of_node_put(reg_np);
of_node_put(regulators_np);
ret = max8998_pmic_dt_parse_dvs_gpio(iodev, pdata, pmic_np); ret = max8998_pmic_dt_parse_dvs_gpio(iodev, pdata, pmic_np);
if (ret) if (ret)
return -EINVAL; return -EINVAL;
...@@ -741,10 +745,10 @@ static int max8998_pmic_probe(struct platform_device *pdev) ...@@ -741,10 +745,10 @@ static int max8998_pmic_probe(struct platform_device *pdev)
struct max8998_dev *iodev = dev_get_drvdata(pdev->dev.parent); struct max8998_dev *iodev = dev_get_drvdata(pdev->dev.parent);
struct max8998_platform_data *pdata = iodev->pdata; struct max8998_platform_data *pdata = iodev->pdata;
struct regulator_config config = { }; struct regulator_config config = { };
struct regulator_dev **rdev; struct regulator_dev *rdev;
struct max8998_data *max8998; struct max8998_data *max8998;
struct i2c_client *i2c; struct i2c_client *i2c;
int i, ret, size; int i, ret;
unsigned int v; unsigned int v;
if (!pdata) { if (!pdata) {
...@@ -763,12 +767,6 @@ static int max8998_pmic_probe(struct platform_device *pdev) ...@@ -763,12 +767,6 @@ static int max8998_pmic_probe(struct platform_device *pdev)
if (!max8998) if (!max8998)
return -ENOMEM; return -ENOMEM;
size = sizeof(struct regulator_dev *) * pdata->num_regulators;
max8998->rdev = devm_kzalloc(&pdev->dev, size, GFP_KERNEL);
if (!max8998->rdev)
return -ENOMEM;
rdev = max8998->rdev;
max8998->dev = &pdev->dev; max8998->dev = &pdev->dev;
max8998->iodev = iodev; max8998->iodev = iodev;
max8998->num_regulators = pdata->num_regulators; max8998->num_regulators = pdata->num_regulators;
...@@ -872,13 +870,12 @@ static int max8998_pmic_probe(struct platform_device *pdev) ...@@ -872,13 +870,12 @@ static int max8998_pmic_probe(struct platform_device *pdev)
config.init_data = pdata->regulators[i].initdata; config.init_data = pdata->regulators[i].initdata;
config.driver_data = max8998; config.driver_data = max8998;
rdev[i] = devm_regulator_register(&pdev->dev, rdev = devm_regulator_register(&pdev->dev, &regulators[index],
&regulators[index], &config); &config);
if (IS_ERR(rdev[i])) { if (IS_ERR(rdev)) {
ret = PTR_ERR(rdev[i]); ret = PTR_ERR(rdev);
dev_err(max8998->dev, "regulator %s init failed (%d)\n", dev_err(max8998->dev, "regulator %s init failed (%d)\n",
regulators[index].name, ret); regulators[index].name, ret);
rdev[i] = NULL;
return ret; return ret;
} }
} }
......
...@@ -167,8 +167,10 @@ int mc13xxx_get_num_regulators_dt(struct platform_device *pdev) ...@@ -167,8 +167,10 @@ int mc13xxx_get_num_regulators_dt(struct platform_device *pdev)
struct device_node *parent; struct device_node *parent;
int num; int num;
of_node_get(pdev->dev.parent->of_node); if (!pdev->dev.parent->of_node)
parent = of_find_node_by_name(pdev->dev.parent->of_node, "regulators"); return -ENODEV;
parent = of_get_child_by_name(pdev->dev.parent->of_node, "regulators");
if (!parent) if (!parent)
return -ENODEV; return -ENODEV;
...@@ -187,8 +189,10 @@ struct mc13xxx_regulator_init_data *mc13xxx_parse_regulators_dt( ...@@ -187,8 +189,10 @@ struct mc13xxx_regulator_init_data *mc13xxx_parse_regulators_dt(
struct device_node *parent, *child; struct device_node *parent, *child;
int i, parsed = 0; int i, parsed = 0;
of_node_get(pdev->dev.parent->of_node); if (!pdev->dev.parent->of_node)
parent = of_find_node_by_name(pdev->dev.parent->of_node, "regulators"); return NULL;
parent = of_get_child_by_name(pdev->dev.parent->of_node, "regulators");
if (!parent) if (!parent)
return NULL; return NULL;
......
This diff is collapsed.
...@@ -119,7 +119,6 @@ static int rc5t583_regulator_probe(struct platform_device *pdev) ...@@ -119,7 +119,6 @@ static int rc5t583_regulator_probe(struct platform_device *pdev)
{ {
struct rc5t583 *rc5t583 = dev_get_drvdata(pdev->dev.parent); struct rc5t583 *rc5t583 = dev_get_drvdata(pdev->dev.parent);
struct rc5t583_platform_data *pdata = dev_get_platdata(rc5t583->dev); struct rc5t583_platform_data *pdata = dev_get_platdata(rc5t583->dev);
struct regulator_init_data *reg_data;
struct regulator_config config = { }; struct regulator_config config = { };
struct rc5t583_regulator *reg = NULL; struct rc5t583_regulator *reg = NULL;
struct rc5t583_regulator *regs; struct rc5t583_regulator *regs;
...@@ -135,19 +134,11 @@ static int rc5t583_regulator_probe(struct platform_device *pdev) ...@@ -135,19 +134,11 @@ static int rc5t583_regulator_probe(struct platform_device *pdev)
regs = devm_kzalloc(&pdev->dev, RC5T583_REGULATOR_MAX * regs = devm_kzalloc(&pdev->dev, RC5T583_REGULATOR_MAX *
sizeof(struct rc5t583_regulator), GFP_KERNEL); sizeof(struct rc5t583_regulator), GFP_KERNEL);
if (!regs) { if (!regs)
dev_err(&pdev->dev, "Memory allocation failed exiting..\n");
return -ENOMEM; return -ENOMEM;
}
for (id = 0; id < RC5T583_REGULATOR_MAX; ++id) { for (id = 0; id < RC5T583_REGULATOR_MAX; ++id) {
reg_data = pdata->reg_init_data[id];
/* No need to register if there is no regulator data */
if (!reg_data)
continue;
reg = &regs[id]; reg = &regs[id];
ri = &rc5t583_reg_info[id]; ri = &rc5t583_reg_info[id];
reg->reg_info = ri; reg->reg_info = ri;
...@@ -169,7 +160,7 @@ static int rc5t583_regulator_probe(struct platform_device *pdev) ...@@ -169,7 +160,7 @@ static int rc5t583_regulator_probe(struct platform_device *pdev)
skip_ext_pwr_config: skip_ext_pwr_config:
config.dev = &pdev->dev; config.dev = &pdev->dev;
config.init_data = reg_data; config.init_data = pdata->reg_init_data[id];
config.driver_data = reg; config.driver_data = reg;
config.regmap = rc5t583->regmap; config.regmap = rc5t583->regmap;
......
This diff is collapsed.
This diff is collapsed.
...@@ -11,11 +11,8 @@ ...@@ -11,11 +11,8 @@
* *
*/ */
#include <linux/bug.h>
#include <linux/err.h> #include <linux/err.h>
#include <linux/gpio.h>
#include <linux/of_gpio.h> #include <linux/of_gpio.h>
#include <linux/slab.h>
#include <linux/module.h> #include <linux/module.h>
#include <linux/platform_device.h> #include <linux/platform_device.h>
#include <linux/regulator/driver.h> #include <linux/regulator/driver.h>
...@@ -170,12 +167,11 @@ static unsigned int s5m8767_opmode_reg[][4] = { ...@@ -170,12 +167,11 @@ static unsigned int s5m8767_opmode_reg[][4] = {
{0x0, 0x3, 0x1, 0x1}, /* BUCK9 */ {0x0, 0x3, 0x1, 0x1}, /* BUCK9 */
}; };
static int s5m8767_get_register(struct regulator_dev *rdev, int *reg, static int s5m8767_get_register(struct s5m8767_info *s5m8767, int reg_id,
int *enable_ctrl) int *reg, int *enable_ctrl)
{ {
int i, reg_id = rdev_get_id(rdev); int i;
unsigned int mode; unsigned int mode;
struct s5m8767_info *s5m8767 = rdev_get_drvdata(rdev);
switch (reg_id) { switch (reg_id) {
case S5M8767_LDO1 ... S5M8767_LDO2: case S5M8767_LDO1 ... S5M8767_LDO2:
...@@ -214,53 +210,6 @@ static int s5m8767_get_register(struct regulator_dev *rdev, int *reg, ...@@ -214,53 +210,6 @@ static int s5m8767_get_register(struct regulator_dev *rdev, int *reg,
return 0; return 0;
} }
static int s5m8767_reg_is_enabled(struct regulator_dev *rdev)
{
struct s5m8767_info *s5m8767 = rdev_get_drvdata(rdev);
int ret, reg;
int enable_ctrl;
unsigned int val;
ret = s5m8767_get_register(rdev, &reg, &enable_ctrl);
if (ret == -EINVAL)
return 1;
else if (ret)
return ret;
ret = regmap_read(s5m8767->iodev->regmap_pmic, reg, &val);
if (ret)
return ret;
return (val & S5M8767_ENCTRL_MASK) == enable_ctrl;
}
static int s5m8767_reg_enable(struct regulator_dev *rdev)
{
struct s5m8767_info *s5m8767 = rdev_get_drvdata(rdev);
int ret, reg;
int enable_ctrl;
ret = s5m8767_get_register(rdev, &reg, &enable_ctrl);
if (ret)
return ret;
return regmap_update_bits(s5m8767->iodev->regmap_pmic, reg,
S5M8767_ENCTRL_MASK, enable_ctrl);
}
static int s5m8767_reg_disable(struct regulator_dev *rdev)
{
struct s5m8767_info *s5m8767 = rdev_get_drvdata(rdev);
int ret, reg, enable_ctrl;
ret = s5m8767_get_register(rdev, &reg, &enable_ctrl);
if (ret)
return ret;
return regmap_update_bits(s5m8767->iodev->regmap_pmic, reg,
S5M8767_ENCTRL_MASK, ~S5M8767_ENCTRL_MASK);
}
static int s5m8767_get_vsel_reg(int reg_id, struct s5m8767_info *s5m8767) static int s5m8767_get_vsel_reg(int reg_id, struct s5m8767_info *s5m8767)
{ {
int reg; int reg;
...@@ -410,9 +359,9 @@ static int s5m8767_set_voltage_time_sel(struct regulator_dev *rdev, ...@@ -410,9 +359,9 @@ static int s5m8767_set_voltage_time_sel(struct regulator_dev *rdev,
static struct regulator_ops s5m8767_ops = { static struct regulator_ops s5m8767_ops = {
.list_voltage = regulator_list_voltage_linear, .list_voltage = regulator_list_voltage_linear,
.is_enabled = s5m8767_reg_is_enabled, .is_enabled = regulator_is_enabled_regmap,
.enable = s5m8767_reg_enable, .enable = regulator_enable_regmap,
.disable = s5m8767_reg_disable, .disable = regulator_disable_regmap,
.get_voltage_sel = regulator_get_voltage_sel_regmap, .get_voltage_sel = regulator_get_voltage_sel_regmap,
.set_voltage_sel = s5m8767_set_voltage_sel, .set_voltage_sel = s5m8767_set_voltage_sel,
.set_voltage_time_sel = s5m8767_set_voltage_time_sel, .set_voltage_time_sel = s5m8767_set_voltage_time_sel,
...@@ -420,9 +369,9 @@ static struct regulator_ops s5m8767_ops = { ...@@ -420,9 +369,9 @@ static struct regulator_ops s5m8767_ops = {
static struct regulator_ops s5m8767_buck78_ops = { static struct regulator_ops s5m8767_buck78_ops = {
.list_voltage = regulator_list_voltage_linear, .list_voltage = regulator_list_voltage_linear,
.is_enabled = s5m8767_reg_is_enabled, .is_enabled = regulator_is_enabled_regmap,
.enable = s5m8767_reg_enable, .enable = regulator_enable_regmap,
.disable = s5m8767_reg_disable, .disable = regulator_disable_regmap,
.get_voltage_sel = regulator_get_voltage_sel_regmap, .get_voltage_sel = regulator_get_voltage_sel_regmap,
.set_voltage_sel = regulator_set_voltage_sel_regmap, .set_voltage_sel = regulator_set_voltage_sel_regmap,
}; };
...@@ -483,6 +432,66 @@ static struct regulator_desc regulators[] = { ...@@ -483,6 +432,66 @@ static struct regulator_desc regulators[] = {
s5m8767_regulator_desc(BUCK9), s5m8767_regulator_desc(BUCK9),
}; };
/*
* Enable GPIO control over BUCK9 in regulator_config for that regulator.
*/
static void s5m8767_regulator_config_ext_control(struct s5m8767_info *s5m8767,
struct sec_regulator_data *rdata,
struct regulator_config *config)
{
int i, mode = 0;
if (rdata->id != S5M8767_BUCK9)
return;
/* Check if opmode for regulator matches S5M8767_ENCTRL_USE_GPIO */
for (i = 0; i < s5m8767->num_regulators; i++) {
const struct sec_opmode_data *opmode = &s5m8767->opmode[i];
if (opmode->id == rdata->id) {
mode = s5m8767_opmode_reg[rdata->id][opmode->mode];
break;
}
}
if (mode != S5M8767_ENCTRL_USE_GPIO) {
dev_warn(s5m8767->dev,
"ext-control for %s: mismatched op_mode (%x), ignoring\n",
rdata->reg_node->name, mode);
return;
}
if (!gpio_is_valid(rdata->ext_control_gpio)) {
dev_warn(s5m8767->dev,
"ext-control for %s: GPIO not valid, ignoring\n",
rdata->reg_node->name);
return;
}
config->ena_gpio = rdata->ext_control_gpio;
config->ena_gpio_flags = GPIOF_OUT_INIT_HIGH;
}
/*
* Turn on GPIO control over BUCK9.
*/
static int s5m8767_enable_ext_control(struct s5m8767_info *s5m8767,
struct regulator_dev *rdev)
{
int id = rdev_get_id(rdev);
int ret, reg, enable_ctrl;
if (id != S5M8767_BUCK9)
return -EINVAL;
ret = s5m8767_get_register(s5m8767, id, &reg, &enable_ctrl);
if (ret)
return ret;
return regmap_update_bits(s5m8767->iodev->regmap_pmic,
reg, S5M8767_ENCTRL_MASK,
S5M8767_ENCTRL_USE_GPIO << S5M8767_ENCTRL_SHIFT);
}
#ifdef CONFIG_OF #ifdef CONFIG_OF
static int s5m8767_pmic_dt_parse_dvs_gpio(struct sec_pmic_dev *iodev, static int s5m8767_pmic_dt_parse_dvs_gpio(struct sec_pmic_dev *iodev,
struct sec_platform_data *pdata, struct sec_platform_data *pdata,
...@@ -520,6 +529,16 @@ static int s5m8767_pmic_dt_parse_ds_gpio(struct sec_pmic_dev *iodev, ...@@ -520,6 +529,16 @@ static int s5m8767_pmic_dt_parse_ds_gpio(struct sec_pmic_dev *iodev,
return 0; return 0;
} }
static void s5m8767_pmic_dt_parse_ext_control_gpio(struct sec_pmic_dev *iodev,
struct sec_regulator_data *rdata,
struct device_node *reg_np)
{
rdata->ext_control_gpio = of_get_named_gpio(reg_np,
"s5m8767,pmic-ext-control-gpios", 0);
if (!gpio_is_valid(rdata->ext_control_gpio))
rdata->ext_control_gpio = 0;
}
static int s5m8767_pmic_dt_parse_pdata(struct platform_device *pdev, static int s5m8767_pmic_dt_parse_pdata(struct platform_device *pdev,
struct sec_platform_data *pdata) struct sec_platform_data *pdata)
{ {
...@@ -546,19 +565,13 @@ static int s5m8767_pmic_dt_parse_pdata(struct platform_device *pdev, ...@@ -546,19 +565,13 @@ static int s5m8767_pmic_dt_parse_pdata(struct platform_device *pdev,
rdata = devm_kzalloc(&pdev->dev, sizeof(*rdata) * rdata = devm_kzalloc(&pdev->dev, sizeof(*rdata) *
pdata->num_regulators, GFP_KERNEL); pdata->num_regulators, GFP_KERNEL);
if (!rdata) { if (!rdata)
dev_err(iodev->dev,
"could not allocate memory for regulator data\n");
return -ENOMEM; return -ENOMEM;
}
rmode = devm_kzalloc(&pdev->dev, sizeof(*rmode) * rmode = devm_kzalloc(&pdev->dev, sizeof(*rmode) *
pdata->num_regulators, GFP_KERNEL); pdata->num_regulators, GFP_KERNEL);
if (!rmode) { if (!rmode)
dev_err(iodev->dev,
"could not allocate memory for regulator mode\n");
return -ENOMEM; return -ENOMEM;
}
pdata->regulators = rdata; pdata->regulators = rdata;
pdata->opmode = rmode; pdata->opmode = rmode;
...@@ -574,6 +587,8 @@ static int s5m8767_pmic_dt_parse_pdata(struct platform_device *pdev, ...@@ -574,6 +587,8 @@ static int s5m8767_pmic_dt_parse_pdata(struct platform_device *pdev,
continue; continue;
} }
s5m8767_pmic_dt_parse_ext_control_gpio(iodev, rdata, reg_np);
rdata->id = i; rdata->id = i;
rdata->initdata = of_get_regulator_init_data( rdata->initdata = of_get_regulator_init_data(
&pdev->dev, reg_np); &pdev->dev, reg_np);
...@@ -922,6 +937,7 @@ static int s5m8767_pmic_probe(struct platform_device *pdev) ...@@ -922,6 +937,7 @@ static int s5m8767_pmic_probe(struct platform_device *pdev)
for (i = 0; i < pdata->num_regulators; i++) { for (i = 0; i < pdata->num_regulators; i++) {
const struct sec_voltage_desc *desc; const struct sec_voltage_desc *desc;
int id = pdata->regulators[i].id; int id = pdata->regulators[i].id;
int enable_reg, enable_val;
desc = reg_voltage_map[id]; desc = reg_voltage_map[id];
if (desc) { if (desc) {
...@@ -935,6 +951,12 @@ static int s5m8767_pmic_probe(struct platform_device *pdev) ...@@ -935,6 +951,12 @@ static int s5m8767_pmic_probe(struct platform_device *pdev)
regulators[id].vsel_mask = 0x3f; regulators[id].vsel_mask = 0x3f;
else else
regulators[id].vsel_mask = 0xff; regulators[id].vsel_mask = 0xff;
s5m8767_get_register(s5m8767, id, &enable_reg,
&enable_val);
regulators[id].enable_reg = enable_reg;
regulators[id].enable_mask = S5M8767_ENCTRL_MASK;
regulators[id].enable_val = enable_val;
} }
config.dev = s5m8767->dev; config.dev = s5m8767->dev;
...@@ -942,6 +964,9 @@ static int s5m8767_pmic_probe(struct platform_device *pdev) ...@@ -942,6 +964,9 @@ static int s5m8767_pmic_probe(struct platform_device *pdev)
config.driver_data = s5m8767; config.driver_data = s5m8767;
config.regmap = iodev->regmap_pmic; config.regmap = iodev->regmap_pmic;
config.of_node = pdata->regulators[i].reg_node; config.of_node = pdata->regulators[i].reg_node;
if (pdata->regulators[i].ext_control_gpio)
s5m8767_regulator_config_ext_control(s5m8767,
&pdata->regulators[i], &config);
rdev[i] = devm_regulator_register(&pdev->dev, &regulators[id], rdev[i] = devm_regulator_register(&pdev->dev, &regulators[id],
&config); &config);
...@@ -951,6 +976,16 @@ static int s5m8767_pmic_probe(struct platform_device *pdev) ...@@ -951,6 +976,16 @@ static int s5m8767_pmic_probe(struct platform_device *pdev)
id); id);
return ret; return ret;
} }
if (pdata->regulators[i].ext_control_gpio) {
ret = s5m8767_enable_ext_control(s5m8767, rdev[i]);
if (ret < 0) {
dev_err(s5m8767->dev,
"failed to enable gpio control over %s: %d\n",
rdev[i]->desc->name, ret);
return ret;
}
}
} }
return 0; return 0;
......
/*
* Regulator driver for ST's PWM Regulators
*
* Copyright (C) 2014 - STMicroelectronics Inc.
*
* Author: Lee Jones <lee.jones@linaro.org>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*/
#include <linux/module.h>
#include <linux/init.h>
#include <linux/err.h>
#include <linux/regulator/driver.h>
#include <linux/regulator/machine.h>
#include <linux/regulator/of_regulator.h>
#include <linux/of.h>
#include <linux/of_device.h>
#include <linux/pwm.h>
#define ST_PWM_REG_PERIOD 8448
struct st_pwm_regulator_pdata {
const struct regulator_desc *desc;
struct st_pwm_voltages *duty_cycle_table;
};
struct st_pwm_regulator_data {
const struct st_pwm_regulator_pdata *pdata;
struct pwm_device *pwm;
bool enabled;
int state;
};
struct st_pwm_voltages {
unsigned int uV;
unsigned int dutycycle;
};
static int st_pwm_regulator_get_voltage_sel(struct regulator_dev *dev)
{
struct st_pwm_regulator_data *drvdata = rdev_get_drvdata(dev);
return drvdata->state;
}
static int st_pwm_regulator_set_voltage_sel(struct regulator_dev *dev,
unsigned selector)
{
struct st_pwm_regulator_data *drvdata = rdev_get_drvdata(dev);
int dutycycle;
int ret;
dutycycle = (ST_PWM_REG_PERIOD / 100) *
drvdata->pdata->duty_cycle_table[selector].dutycycle;
ret = pwm_config(drvdata->pwm, dutycycle, ST_PWM_REG_PERIOD);
if (ret) {
dev_err(&dev->dev, "Failed to configure PWM\n");
return ret;
}
drvdata->state = selector;
if (!drvdata->enabled) {
ret = pwm_enable(drvdata->pwm);
if (ret) {
dev_err(&dev->dev, "Failed to enable PWM\n");
return ret;
}
drvdata->enabled = true;
}
return 0;
}
static int st_pwm_regulator_list_voltage(struct regulator_dev *dev,
unsigned selector)
{
struct st_pwm_regulator_data *drvdata = rdev_get_drvdata(dev);
if (selector >= dev->desc->n_voltages)
return -EINVAL;
return drvdata->pdata->duty_cycle_table[selector].uV;
}
static struct regulator_ops st_pwm_regulator_voltage_ops = {
.set_voltage_sel = st_pwm_regulator_set_voltage_sel,
.get_voltage_sel = st_pwm_regulator_get_voltage_sel,
.list_voltage = st_pwm_regulator_list_voltage,
.map_voltage = regulator_map_voltage_iterate,
};
static struct st_pwm_voltages b2105_duty_cycle_table[] = {
{ .uV = 1114000, .dutycycle = 0, },
{ .uV = 1095000, .dutycycle = 10, },
{ .uV = 1076000, .dutycycle = 20, },
{ .uV = 1056000, .dutycycle = 30, },
{ .uV = 1036000, .dutycycle = 40, },
{ .uV = 1016000, .dutycycle = 50, },
/* WARNING: Values above 50% duty-cycle cause boot failures. */
};
static const struct regulator_desc b2105_desc = {
.name = "b2105-pwm-regulator",
.ops = &st_pwm_regulator_voltage_ops,
.type = REGULATOR_VOLTAGE,
.owner = THIS_MODULE,
.n_voltages = ARRAY_SIZE(b2105_duty_cycle_table),
.supply_name = "pwm",
};
static const struct st_pwm_regulator_pdata b2105_info = {
.desc = &b2105_desc,
.duty_cycle_table = b2105_duty_cycle_table,
};
static struct of_device_id st_pwm_of_match[] = {
{ .compatible = "st,b2105-pwm-regulator", .data = &b2105_info, },
{ },
};
MODULE_DEVICE_TABLE(of, st_pwm_of_match);
static int st_pwm_regulator_probe(struct platform_device *pdev)
{
struct st_pwm_regulator_data *drvdata;
struct regulator_dev *regulator;
struct regulator_config config = { };
struct device_node *np = pdev->dev.of_node;
const struct of_device_id *of_match;
if (!np) {
dev_err(&pdev->dev, "Device Tree node missing\n");
return -EINVAL;
}
drvdata = devm_kzalloc(&pdev->dev, sizeof(*drvdata), GFP_KERNEL);
if (!drvdata)
return -ENOMEM;
of_match = of_match_device(st_pwm_of_match, &pdev->dev);
if (!of_match) {
dev_err(&pdev->dev, "failed to match of device\n");
return -ENODEV;
}
drvdata->pdata = of_match->data;
config.init_data = of_get_regulator_init_data(&pdev->dev, np);
if (!config.init_data)
return -ENOMEM;
config.of_node = np;
config.dev = &pdev->dev;
config.driver_data = drvdata;
drvdata->pwm = devm_pwm_get(&pdev->dev, NULL);
if (IS_ERR(drvdata->pwm)) {
dev_err(&pdev->dev, "Failed to get PWM\n");
return PTR_ERR(drvdata->pwm);
}
regulator = devm_regulator_register(&pdev->dev,
drvdata->pdata->desc, &config);
if (IS_ERR(regulator)) {
dev_err(&pdev->dev, "Failed to register regulator %s\n",
drvdata->pdata->desc->name);
return PTR_ERR(regulator);
}
return 0;
}
static struct platform_driver st_pwm_regulator_driver = {
.driver = {
.name = "st-pwm-regulator",
.owner = THIS_MODULE,
.of_match_table = of_match_ptr(st_pwm_of_match),
},
.probe = st_pwm_regulator_probe,
};
module_platform_driver(st_pwm_regulator_driver);
MODULE_LICENSE("GPL");
MODULE_AUTHOR("Lee Jones <lee.jones@linaro.org>");
MODULE_DESCRIPTION("ST PWM Regulator Driver");
MODULE_ALIAS("platform:st_pwm-regulator");
...@@ -54,8 +54,8 @@ struct ti_abb_info { ...@@ -54,8 +54,8 @@ struct ti_abb_info {
/** /**
* struct ti_abb_reg - Register description for ABB block * struct ti_abb_reg - Register description for ABB block
* @setup_reg: setup register offset from base * @setup_off: setup register offset from base
* @control_reg: control register offset from base * @control_off: control register offset from base
* @sr2_wtcnt_value_mask: setup register- sr2_wtcnt_value mask * @sr2_wtcnt_value_mask: setup register- sr2_wtcnt_value mask
* @fbb_sel_mask: setup register- FBB sel mask * @fbb_sel_mask: setup register- FBB sel mask
* @rbb_sel_mask: setup register- RBB sel mask * @rbb_sel_mask: setup register- RBB sel mask
...@@ -64,8 +64,8 @@ struct ti_abb_info { ...@@ -64,8 +64,8 @@ struct ti_abb_info {
* @opp_sel_mask: control register - mask for mode to operate * @opp_sel_mask: control register - mask for mode to operate
*/ */
struct ti_abb_reg { struct ti_abb_reg {
u32 setup_reg; u32 setup_off;
u32 control_reg; u32 control_off;
/* Setup register fields */ /* Setup register fields */
u32 sr2_wtcnt_value_mask; u32 sr2_wtcnt_value_mask;
...@@ -83,6 +83,8 @@ struct ti_abb_reg { ...@@ -83,6 +83,8 @@ struct ti_abb_reg {
* @rdesc: regulator descriptor * @rdesc: regulator descriptor
* @clk: clock(usually sysclk) supplying ABB block * @clk: clock(usually sysclk) supplying ABB block
* @base: base address of ABB block * @base: base address of ABB block
* @setup_reg: setup register of ABB block
* @control_reg: control register of ABB block
* @int_base: interrupt register base address * @int_base: interrupt register base address
* @efuse_base: (optional) efuse base address for ABB modes * @efuse_base: (optional) efuse base address for ABB modes
* @ldo_base: (optional) LDOVBB vset override base address * @ldo_base: (optional) LDOVBB vset override base address
...@@ -99,6 +101,8 @@ struct ti_abb { ...@@ -99,6 +101,8 @@ struct ti_abb {
struct regulator_desc rdesc; struct regulator_desc rdesc;
struct clk *clk; struct clk *clk;
void __iomem *base; void __iomem *base;
void __iomem *setup_reg;
void __iomem *control_reg;
void __iomem *int_base; void __iomem *int_base;
void __iomem *efuse_base; void __iomem *efuse_base;
void __iomem *ldo_base; void __iomem *ldo_base;
...@@ -118,20 +122,18 @@ struct ti_abb { ...@@ -118,20 +122,18 @@ struct ti_abb {
* ti_abb_rmw() - handy wrapper to set specific register bits * ti_abb_rmw() - handy wrapper to set specific register bits
* @mask: mask for register field * @mask: mask for register field
* @value: value shifted to mask location and written * @value: value shifted to mask location and written
* @offset: offset of register * @reg: register address
* @base: base address
* *
* Return: final register value (may be unused) * Return: final register value (may be unused)
*/ */
static inline u32 ti_abb_rmw(u32 mask, u32 value, u32 offset, static inline u32 ti_abb_rmw(u32 mask, u32 value, void __iomem *reg)
void __iomem *base)
{ {
u32 val; u32 val;
val = readl(base + offset); val = readl(reg);
val &= ~mask; val &= ~mask;
val |= (value << __ffs(mask)) & mask; val |= (value << __ffs(mask)) & mask;
writel(val, base + offset); writel(val, reg);
return val; return val;
} }
...@@ -263,21 +265,19 @@ static int ti_abb_set_opp(struct regulator_dev *rdev, struct ti_abb *abb, ...@@ -263,21 +265,19 @@ static int ti_abb_set_opp(struct regulator_dev *rdev, struct ti_abb *abb,
if (ret) if (ret)
goto out; goto out;
ti_abb_rmw(regs->fbb_sel_mask | regs->rbb_sel_mask, 0, regs->setup_reg, ti_abb_rmw(regs->fbb_sel_mask | regs->rbb_sel_mask, 0, abb->setup_reg);
abb->base);
switch (info->opp_sel) { switch (info->opp_sel) {
case TI_ABB_SLOW_OPP: case TI_ABB_SLOW_OPP:
ti_abb_rmw(regs->rbb_sel_mask, 1, regs->setup_reg, abb->base); ti_abb_rmw(regs->rbb_sel_mask, 1, abb->setup_reg);
break; break;
case TI_ABB_FAST_OPP: case TI_ABB_FAST_OPP:
ti_abb_rmw(regs->fbb_sel_mask, 1, regs->setup_reg, abb->base); ti_abb_rmw(regs->fbb_sel_mask, 1, abb->setup_reg);
break; break;
} }
/* program next state of ABB ldo */ /* program next state of ABB ldo */
ti_abb_rmw(regs->opp_sel_mask, info->opp_sel, regs->control_reg, ti_abb_rmw(regs->opp_sel_mask, info->opp_sel, abb->control_reg);
abb->base);
/* /*
* program LDO VBB vset override if needed for !bypass mode * program LDO VBB vset override if needed for !bypass mode
...@@ -288,7 +288,7 @@ static int ti_abb_set_opp(struct regulator_dev *rdev, struct ti_abb *abb, ...@@ -288,7 +288,7 @@ static int ti_abb_set_opp(struct regulator_dev *rdev, struct ti_abb *abb,
ti_abb_program_ldovbb(dev, abb, info); ti_abb_program_ldovbb(dev, abb, info);
/* Initiate ABB ldo change */ /* Initiate ABB ldo change */
ti_abb_rmw(regs->opp_change_mask, 1, regs->control_reg, abb->base); ti_abb_rmw(regs->opp_change_mask, 1, abb->control_reg);
/* Wait for ABB LDO to complete transition to new Bias setting */ /* Wait for ABB LDO to complete transition to new Bias setting */
ret = ti_abb_wait_txdone(dev, abb); ret = ti_abb_wait_txdone(dev, abb);
...@@ -490,8 +490,7 @@ static int ti_abb_init_timings(struct device *dev, struct ti_abb *abb) ...@@ -490,8 +490,7 @@ static int ti_abb_init_timings(struct device *dev, struct ti_abb *abb)
dev_dbg(dev, "%s: Clk_rate=%ld, sr2_cnt=0x%08x\n", __func__, dev_dbg(dev, "%s: Clk_rate=%ld, sr2_cnt=0x%08x\n", __func__,
clk_get_rate(abb->clk), sr2_wt_cnt_val); clk_get_rate(abb->clk), sr2_wt_cnt_val);
ti_abb_rmw(regs->sr2_wtcnt_value_mask, sr2_wt_cnt_val, regs->setup_reg, ti_abb_rmw(regs->sr2_wtcnt_value_mask, sr2_wt_cnt_val, abb->setup_reg);
abb->base);
return 0; return 0;
} }
...@@ -508,32 +507,24 @@ static int ti_abb_init_table(struct device *dev, struct ti_abb *abb, ...@@ -508,32 +507,24 @@ static int ti_abb_init_table(struct device *dev, struct ti_abb *abb,
struct regulator_init_data *rinit_data) struct regulator_init_data *rinit_data)
{ {
struct ti_abb_info *info; struct ti_abb_info *info;
const struct property *prop;
const __be32 *abb_info;
const u32 num_values = 6; const u32 num_values = 6;
char *pname = "ti,abb_info"; char *pname = "ti,abb_info";
u32 num_entries, i; u32 i;
unsigned int *volt_table; unsigned int *volt_table;
int min_uV = INT_MAX, max_uV = 0; int num_entries, min_uV = INT_MAX, max_uV = 0;
struct regulation_constraints *c = &rinit_data->constraints; struct regulation_constraints *c = &rinit_data->constraints;
prop = of_find_property(dev->of_node, pname, NULL);
if (!prop) {
dev_err(dev, "No '%s' property?\n", pname);
return -ENODEV;
}
if (!prop->value) {
dev_err(dev, "Empty '%s' property?\n", pname);
return -ENODATA;
}
/* /*
* Each abb_info is a set of n-tuple, where n is num_values, consisting * Each abb_info is a set of n-tuple, where n is num_values, consisting
* of voltage and a set of detection logic for ABB information for that * of voltage and a set of detection logic for ABB information for that
* voltage to apply. * voltage to apply.
*/ */
num_entries = prop->length / sizeof(u32); num_entries = of_property_count_u32_elems(dev->of_node, pname);
if (num_entries < 0) {
dev_err(dev, "No '%s' property?\n", pname);
return num_entries;
}
if (!num_entries || (num_entries % num_values)) { if (!num_entries || (num_entries % num_values)) {
dev_err(dev, "All '%s' list entries need %d vals\n", pname, dev_err(dev, "All '%s' list entries need %d vals\n", pname,
num_values); num_values);
...@@ -542,38 +533,38 @@ static int ti_abb_init_table(struct device *dev, struct ti_abb *abb, ...@@ -542,38 +533,38 @@ static int ti_abb_init_table(struct device *dev, struct ti_abb *abb,
num_entries /= num_values; num_entries /= num_values;
info = devm_kzalloc(dev, sizeof(*info) * num_entries, GFP_KERNEL); info = devm_kzalloc(dev, sizeof(*info) * num_entries, GFP_KERNEL);
if (!info) { if (!info)
dev_err(dev, "Can't allocate info table for '%s' property\n",
pname);
return -ENOMEM; return -ENOMEM;
}
abb->info = info; abb->info = info;
volt_table = devm_kzalloc(dev, sizeof(unsigned int) * num_entries, volt_table = devm_kzalloc(dev, sizeof(unsigned int) * num_entries,
GFP_KERNEL); GFP_KERNEL);
if (!volt_table) { if (!volt_table)
dev_err(dev, "Can't allocate voltage table for '%s' property\n",
pname);
return -ENOMEM; return -ENOMEM;
}
abb->rdesc.n_voltages = num_entries; abb->rdesc.n_voltages = num_entries;
abb->rdesc.volt_table = volt_table; abb->rdesc.volt_table = volt_table;
/* We do not know where the OPP voltage is at the moment */ /* We do not know where the OPP voltage is at the moment */
abb->current_info_idx = -EINVAL; abb->current_info_idx = -EINVAL;
abb_info = prop->value;
for (i = 0; i < num_entries; i++, info++, volt_table++) { for (i = 0; i < num_entries; i++, info++, volt_table++) {
u32 efuse_offset, rbb_mask, fbb_mask, vset_mask; u32 efuse_offset, rbb_mask, fbb_mask, vset_mask;
u32 efuse_val; u32 efuse_val;
/* NOTE: num_values should equal to entries picked up here */ /* NOTE: num_values should equal to entries picked up here */
*volt_table = be32_to_cpup(abb_info++); of_property_read_u32_index(dev->of_node, pname, i * num_values,
info->opp_sel = be32_to_cpup(abb_info++); volt_table);
efuse_offset = be32_to_cpup(abb_info++); of_property_read_u32_index(dev->of_node, pname,
rbb_mask = be32_to_cpup(abb_info++); i * num_values + 1, &info->opp_sel);
fbb_mask = be32_to_cpup(abb_info++); of_property_read_u32_index(dev->of_node, pname,
vset_mask = be32_to_cpup(abb_info++); i * num_values + 2, &efuse_offset);
of_property_read_u32_index(dev->of_node, pname,
i * num_values + 3, &rbb_mask);
of_property_read_u32_index(dev->of_node, pname,
i * num_values + 4, &fbb_mask);
of_property_read_u32_index(dev->of_node, pname,
i * num_values + 5, &vset_mask);
dev_dbg(dev, dev_dbg(dev,
"[%d]v=%d ABB=%d ef=0x%x rbb=0x%x fbb=0x%x vset=0x%x\n", "[%d]v=%d ABB=%d ef=0x%x rbb=0x%x fbb=0x%x vset=0x%x\n",
...@@ -648,8 +639,8 @@ static struct regulator_ops ti_abb_reg_ops = { ...@@ -648,8 +639,8 @@ static struct regulator_ops ti_abb_reg_ops = {
/* Default ABB block offsets, IF this changes in future, create new one */ /* Default ABB block offsets, IF this changes in future, create new one */
static const struct ti_abb_reg abb_regs_v1 = { static const struct ti_abb_reg abb_regs_v1 = {
/* WARNING: registers are wrongly documented in TRM */ /* WARNING: registers are wrongly documented in TRM */
.setup_reg = 0x04, .setup_off = 0x04,
.control_reg = 0x00, .control_off = 0x00,
.sr2_wtcnt_value_mask = (0xff << 8), .sr2_wtcnt_value_mask = (0xff << 8),
.fbb_sel_mask = (0x01 << 2), .fbb_sel_mask = (0x01 << 2),
...@@ -661,8 +652,8 @@ static const struct ti_abb_reg abb_regs_v1 = { ...@@ -661,8 +652,8 @@ static const struct ti_abb_reg abb_regs_v1 = {
}; };
static const struct ti_abb_reg abb_regs_v2 = { static const struct ti_abb_reg abb_regs_v2 = {
.setup_reg = 0x00, .setup_off = 0x00,
.control_reg = 0x04, .control_off = 0x04,
.sr2_wtcnt_value_mask = (0xff << 8), .sr2_wtcnt_value_mask = (0xff << 8),
.fbb_sel_mask = (0x01 << 2), .fbb_sel_mask = (0x01 << 2),
...@@ -673,9 +664,20 @@ static const struct ti_abb_reg abb_regs_v2 = { ...@@ -673,9 +664,20 @@ static const struct ti_abb_reg abb_regs_v2 = {
.opp_sel_mask = (0x03 << 0), .opp_sel_mask = (0x03 << 0),
}; };
static const struct ti_abb_reg abb_regs_generic = {
.sr2_wtcnt_value_mask = (0xff << 8),
.fbb_sel_mask = (0x01 << 2),
.rbb_sel_mask = (0x01 << 1),
.sr2_en_mask = (0x01 << 0),
.opp_change_mask = (0x01 << 2),
.opp_sel_mask = (0x03 << 0),
};
static const struct of_device_id ti_abb_of_match[] = { static const struct of_device_id ti_abb_of_match[] = {
{.compatible = "ti,abb-v1", .data = &abb_regs_v1}, {.compatible = "ti,abb-v1", .data = &abb_regs_v1},
{.compatible = "ti,abb-v2", .data = &abb_regs_v2}, {.compatible = "ti,abb-v2", .data = &abb_regs_v2},
{.compatible = "ti,abb-v3", .data = &abb_regs_generic},
{ }, { },
}; };
...@@ -722,12 +724,30 @@ static int ti_abb_probe(struct platform_device *pdev) ...@@ -722,12 +724,30 @@ static int ti_abb_probe(struct platform_device *pdev)
abb->regs = match->data; abb->regs = match->data;
/* Map ABB resources */ /* Map ABB resources */
if (abb->regs->setup_off || abb->regs->control_off) {
pname = "base-address"; pname = "base-address";
res = platform_get_resource_byname(pdev, IORESOURCE_MEM, pname); res = platform_get_resource_byname(pdev, IORESOURCE_MEM, pname);
abb->base = devm_ioremap_resource(dev, res); abb->base = devm_ioremap_resource(dev, res);
if (IS_ERR(abb->base)) if (IS_ERR(abb->base))
return PTR_ERR(abb->base); return PTR_ERR(abb->base);
abb->setup_reg = abb->base + abb->regs->setup_off;
abb->control_reg = abb->base + abb->regs->control_off;
} else {
pname = "control-address";
res = platform_get_resource_byname(pdev, IORESOURCE_MEM, pname);
abb->control_reg = devm_ioremap_resource(dev, res);
if (IS_ERR(abb->control_reg))
return PTR_ERR(abb->control_reg);
pname = "setup-address";
res = platform_get_resource_byname(pdev, IORESOURCE_MEM, pname);
abb->setup_reg = devm_ioremap_resource(dev, res);
if (IS_ERR(abb->setup_reg))
return PTR_ERR(abb->setup_reg);
}
pname = "int-address"; pname = "int-address";
res = platform_get_resource_byname(pdev, IORESOURCE_MEM, pname); res = platform_get_resource_byname(pdev, IORESOURCE_MEM, pname);
if (!res) { if (!res) {
...@@ -860,7 +880,7 @@ static int ti_abb_probe(struct platform_device *pdev) ...@@ -860,7 +880,7 @@ static int ti_abb_probe(struct platform_device *pdev)
platform_set_drvdata(pdev, rdev); platform_set_drvdata(pdev, rdev);
/* Enable the ldo if not already done by bootloader */ /* Enable the ldo if not already done by bootloader */
ti_abb_rmw(abb->regs->sr2_en_mask, 1, abb->regs->setup_reg, abb->base); ti_abb_rmw(abb->regs->sr2_en_mask, 1, abb->setup_reg);
return 0; return 0;
} }
......
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
...@@ -165,10 +165,8 @@ static int wm831x_isink_probe(struct platform_device *pdev) ...@@ -165,10 +165,8 @@ static int wm831x_isink_probe(struct platform_device *pdev)
isink = devm_kzalloc(&pdev->dev, sizeof(struct wm831x_isink), isink = devm_kzalloc(&pdev->dev, sizeof(struct wm831x_isink),
GFP_KERNEL); GFP_KERNEL);
if (isink == NULL) { if (!isink)
dev_err(&pdev->dev, "Unable to allocate private data\n");
return -ENOMEM; return -ENOMEM;
}
isink->wm831x = wm831x; isink->wm831x = wm831x;
......
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment