Commit 312c76f1 authored by Linus Torvalds's avatar Linus Torvalds

Merge tag 'regulator-v3.16' of...

Merge tag 'regulator-v3.16' of git://git.kernel.org/pub/scm/linux/kernel/git/broonie/regulator into next

Pull regulator updates from Mark Brown:
 "The bulk of the changes for this release are a few new drivers however
  there are a couple of noticable core changes and the usual stream of
  cleanups and fixes:

   - move disable of unused regulators later in init so it comes after
     deferred probe has iterated making startup smoother.
   - fixes to reference counting of the DT nodes for constraints from
     Charles Keepax.  This has little practical impact since all real
     users of the regulator bindings use FDT which doesn't need the
     reference counting.
   - lots of cleanups, especially to the Samsung drivers.
   - support for Linear Technologies LTC3589, Texas Instruments
     TPS658640 and X-Powers AXP20x"

* tag 'regulator-v3.16' of git://git.kernel.org/pub/scm/linux/kernel/git/broonie/regulator: (64 commits)
  regulator: pbias: remove unnecessary OOM messages
  regulator: max8649: remove unnecessary OOM messages
  regulator: core: Fix the init of DT defined fixed regulators
  regulator: core: Disable unused regulators after deferred probing is done
  regulator: Don't disable unused regulators we don't have permission for
  regulator: axp20x: Use regulator_map_voltage_ascend for LDO4
  regulator: use of_property_read_{bool|u32}()
  regulator: Fix regulator_get_{optional,exclusive}() documentation
  regulators: Add definition of regulator_set_voltage_time() for !CONFIG_REGULATOR
  regulator: arizona-ldo1: add missing #include
  regulator: pfuze100: Support enable/disable for fixed regulator
  regulator: ltc3589: Remove ltc3589_list_voltage_fixed function
  regulator: ltc3589: Fix module dependency
  regulator: tps6586x: Remove unused to_tps6586x_dev() function
  regulator: tps65218: Convert to use regulator_set_voltage_time_sel
  regulator: tps6586x: Add support for the TPS658640
  regulator: tps6586x: Prepare supporting fixed regulators
  regulator: pfuze100: Don't allocate an invalid gpio
  regulator: pfuze100: Support SWB enable/disable
  regulator: fixed: use of_property_read_{bool|u32}()
  ...
parents e13cccfd 978371cb
...@@ -19,7 +19,9 @@ Optional child nodes: ...@@ -19,7 +19,9 @@ Optional child nodes:
The valid regulator node names for BCM59056 are: The valid regulator node names for BCM59056 are:
rfldo, camldo1, camldo2, simldo1, simldo2, sdldo, sdxldo, rfldo, camldo1, camldo2, simldo1, simldo2, sdldo, sdxldo,
mmcldo1, mmcldo2, audldo, micldo, usbldo, vibldo, mmcldo1, mmcldo2, audldo, micldo, usbldo, vibldo,
csr, iosr1, iosr2, msr, sdsr1, sdsr2, vsr csr, iosr1, iosr2, msr, sdsr1, sdsr2, vsr,
gpldo1, gpldo2, gpldo3, gpldo4, gpldo5, gpldo6,
vbus
Example: Example:
pmu: bcm59056@8 { pmu: bcm59056@8 {
......
...@@ -56,6 +56,20 @@ for a particular group of BUCKs. So provide same regulator-ramp-delay<value>. ...@@ -56,6 +56,20 @@ for a particular group of BUCKs. So provide same regulator-ramp-delay<value>.
Grouping of BUCKs sharing ramp rate setting is as follow : BUCK[1, 6], Grouping of BUCKs sharing ramp rate setting is as follow : BUCK[1, 6],
BUCK[3, 4], and BUCK[7, 8, 10] BUCK[3, 4], and BUCK[7, 8, 10]
On S2MPS14 the LDO10, LDO11 and LDO12 can be configured to external control
over GPIO. To turn this feature on this property must be added to the regulator
sub-node:
- samsung,ext-control-gpios: GPIO specifier for one GPIO
controlling this regulator (enable/disable);
Example:
LDO12 {
regulator-name = "V_EMMC_2.8V";
regulator-min-microvolt = <2800000>;
regulator-max-microvolt = <2800000>;
samsung,ext-control-gpios = <&gpk0 2 0>;
};
The regulator constraints inside the regulator nodes use the standard regulator The regulator constraints inside the regulator nodes use the standard regulator
bindings which are documented elsewhere. bindings which are documented elsewhere.
......
Linear Technology LTC3589, LTC3589-1, and LTC3589-2 8-output regulators
Required properties:
- compatible: "lltc,ltc3589", "lltc,ltc3589-1" or "lltc,ltc3589-2"
- reg: I2C slave address
Required child node:
- regulators: Contains eight regulator child nodes sw1, sw2, sw3, bb-out,
ldo1, ldo2, ldo3, and ldo4, specifying the initialization data as
documented in Documentation/devicetree/bindings/regulator/regulator.txt.
Each regulator is defined using the standard binding for regulators. The
nodes for sw1, sw2, sw3, bb-out, ldo1, and ldo2 additionally need to specify
the resistor values of their external feedback voltage dividers:
Required properties (not on ldo3, ldo4):
- lltc,fb-voltage-divider: An array of two integers containing the resistor
values R1 and R2 of the feedback voltage divider in ohms.
Regulators sw1, sw2, sw3, and ldo2 can regulate the feedback reference from
0.3625 V to 0.75 V in 12.5 mV steps. The output voltage thus ranges between
0.3625 * (1 + R1/R2) V and 0.75 * (1 + R1/R2) V. Regulators bb-out and ldo1
have a fixed 0.8 V reference and thus output 0.8 * (1 + R1/R2) V. The ldo3
regulator is fixed to 1.8 V on LTC3589 and to 2.8 V on LTC3589-1,2. The ldo4
regulator can output between 1.8 V and 3.3 V on LTC3589 and between 1.2 V
and 3.2 V on LTC3589-1,2 in four steps. The ldo1 standby regulator can not
be disabled and thus should have the regulator-always-on property set.
Example:
ltc3589: pmic@34 {
compatible = "lltc,ltc3589-1";
reg = <0x34>;
regulators {
sw1_reg: sw1 {
regulator-min-microvolt = <591930>;
regulator-max-microvolt = <1224671>;
lltc,fb-voltage-divider = <100000 158000>;
regulator-ramp-delay = <7000>;
regulator-boot-on;
regulator-always-on;
};
sw2_reg: sw2 {
regulator-min-microvolt = <704123>;
regulator-max-microvolt = <1456803>;
lltc,fb-voltage-divider = <180000 191000>;
regulator-ramp-delay = <7000>;
regulator-boot-on;
regulator-always-on;
};
sw3_reg: sw3 {
regulator-min-microvolt = <1341250>;
regulator-max-microvolt = <2775000>;
lltc,fb-voltage-divider = <270000 100000>;
regulator-ramp-delay = <7000>;
regulator-boot-on;
regulator-always-on;
};
bb_out_reg: bb-out {
regulator-min-microvolt = <3387341>;
regulator-max-microvolt = <3387341>;
lltc,fb-voltage-divider = <511000 158000>;
regulator-boot-on;
regulator-always-on;
};
ldo1_reg: ldo1 {
regulator-min-microvolt = <1306329>;
regulator-max-microvolt = <1306329>;
lltc,fb-voltage-divider = <100000 158000>;
regulator-boot-on;
regulator-always-on;
};
ldo2_reg: ldo2 {
regulator-min-microvolt = <704123>;
regulator-max-microvolt = <1456806>;
lltc,fb-voltage-divider = <180000 191000>;
regulator-ramp-delay = <7000>;
regulator-boot-on;
regulator-always-on;
};
ldo3_reg: ldo3 {
regulator-min-microvolt = <2800000>;
regulator-max-microvolt = <2800000>;
regulator-boot-on;
};
ldo4_reg: ldo4 {
regulator-min-microvolt = <1200000>;
regulator-max-microvolt = <3200000>;
};
};
};
...@@ -21,6 +21,10 @@ Optional properties: ...@@ -21,6 +21,10 @@ Optional properties:
number should be provided. If it is externally controlled and no GPIO number should be provided. If it is externally controlled and no GPIO
entry then driver will just configure this rails as external control entry then driver will just configure this rails as external control
and will not provide any enable/disable APIs. and will not provide any enable/disable APIs.
- ti,overcurrent-wait: This is applicable to FET registers, which have a
poorly defined "overcurrent wait" field. If this property is present it
should be between 0 - 3. If this property isn't present we won't touch the
"overcurrent wait" field and we'll leave it to the BIOS/EC to deal with.
Each regulator is defined using the standard binding for regulators. Each regulator is defined using the standard binding for regulators.
......
...@@ -74,6 +74,7 @@ lantiq Lantiq Semiconductor ...@@ -74,6 +74,7 @@ lantiq Lantiq Semiconductor
lg LG Corporation lg LG Corporation
linux Linux-specific binding linux Linux-specific binding
lsi LSI Corp. (LSI Logic) lsi LSI Corp. (LSI Logic)
lltc Linear Technology Corporation
marvell Marvell Technology Group Ltd. marvell Marvell Technology Group Ltd.
maxim Maxim Integrated Products maxim Maxim Integrated Products
microchip Microchip Technology Inc. microchip Microchip Technology Inc.
......
...@@ -508,19 +508,31 @@ int arizona_of_get_type(struct device *dev) ...@@ -508,19 +508,31 @@ int arizona_of_get_type(struct device *dev)
} }
EXPORT_SYMBOL_GPL(arizona_of_get_type); EXPORT_SYMBOL_GPL(arizona_of_get_type);
int arizona_of_get_named_gpio(struct arizona *arizona, const char *prop,
bool mandatory)
{
int gpio;
gpio = of_get_named_gpio(arizona->dev->of_node, prop, 0);
if (gpio < 0) {
if (mandatory)
dev_err(arizona->dev,
"Mandatory DT gpio %s missing/malformed: %d\n",
prop, gpio);
gpio = 0;
}
return gpio;
}
EXPORT_SYMBOL_GPL(arizona_of_get_named_gpio);
static int arizona_of_get_core_pdata(struct arizona *arizona) static int arizona_of_get_core_pdata(struct arizona *arizona)
{ {
struct arizona_pdata *pdata = &arizona->pdata;
int ret, i; int ret, i;
arizona->pdata.reset = of_get_named_gpio(arizona->dev->of_node, pdata->reset = arizona_of_get_named_gpio(arizona, "wlf,reset", true);
"wlf,reset", 0);
if (arizona->pdata.reset < 0)
arizona->pdata.reset = 0;
arizona->pdata.ldoena = of_get_named_gpio(arizona->dev->of_node,
"wlf,ldoena", 0);
if (arizona->pdata.ldoena < 0)
arizona->pdata.ldoena = 0;
ret = of_property_read_u32_array(arizona->dev->of_node, ret = of_property_read_u32_array(arizona->dev->of_node,
"wlf,gpio-defaults", "wlf,gpio-defaults",
...@@ -652,6 +664,9 @@ int arizona_dev_init(struct arizona *arizona) ...@@ -652,6 +664,9 @@ int arizona_dev_init(struct arizona *arizona)
return -EINVAL; return -EINVAL;
} }
/* Mark DCVDD as external, LDO1 driver will clear if internal */
arizona->external_dcvdd = true;
ret = mfd_add_devices(arizona->dev, -1, early_devs, ret = mfd_add_devices(arizona->dev, -1, early_devs,
ARRAY_SIZE(early_devs), NULL, 0, NULL); ARRAY_SIZE(early_devs), NULL, 0, NULL);
if (ret != 0) { if (ret != 0) {
...@@ -851,14 +866,6 @@ int arizona_dev_init(struct arizona *arizona) ...@@ -851,14 +866,6 @@ int arizona_dev_init(struct arizona *arizona)
arizona->pdata.gpio_defaults[i]); arizona->pdata.gpio_defaults[i]);
} }
/*
* LDO1 can only be used to supply DCVDD so if it has no
* consumers then DCVDD is supplied externally.
*/
if (arizona->pdata.ldo1 &&
arizona->pdata.ldo1->num_consumer_supplies == 0)
arizona->external_dcvdd = true;
pm_runtime_set_autosuspend_delay(arizona->dev, 100); pm_runtime_set_autosuspend_delay(arizona->dev, 100);
pm_runtime_use_autosuspend(arizona->dev); pm_runtime_use_autosuspend(arizona->dev);
pm_runtime_enable(arizona->dev); pm_runtime_enable(arizona->dev);
......
...@@ -28,39 +28,71 @@ static const struct mfd_cell bcm590xx_devs[] = { ...@@ -28,39 +28,71 @@ static const struct mfd_cell bcm590xx_devs[] = {
}, },
}; };
static const struct regmap_config bcm590xx_regmap_config = { static const struct regmap_config bcm590xx_regmap_config_pri = {
.reg_bits = 8, .reg_bits = 8,
.val_bits = 8, .val_bits = 8,
.max_register = BCM590XX_MAX_REGISTER, .max_register = BCM590XX_MAX_REGISTER_PRI,
.cache_type = REGCACHE_RBTREE, .cache_type = REGCACHE_RBTREE,
}; };
static int bcm590xx_i2c_probe(struct i2c_client *i2c, static const struct regmap_config bcm590xx_regmap_config_sec = {
.reg_bits = 8,
.val_bits = 8,
.max_register = BCM590XX_MAX_REGISTER_SEC,
.cache_type = REGCACHE_RBTREE,
};
static int bcm590xx_i2c_probe(struct i2c_client *i2c_pri,
const struct i2c_device_id *id) const struct i2c_device_id *id)
{ {
struct bcm590xx *bcm590xx; struct bcm590xx *bcm590xx;
int ret; int ret;
bcm590xx = devm_kzalloc(&i2c->dev, sizeof(*bcm590xx), GFP_KERNEL); bcm590xx = devm_kzalloc(&i2c_pri->dev, sizeof(*bcm590xx), GFP_KERNEL);
if (!bcm590xx) if (!bcm590xx)
return -ENOMEM; return -ENOMEM;
i2c_set_clientdata(i2c, bcm590xx); i2c_set_clientdata(i2c_pri, bcm590xx);
bcm590xx->dev = &i2c->dev; bcm590xx->dev = &i2c_pri->dev;
bcm590xx->i2c_client = i2c; bcm590xx->i2c_pri = i2c_pri;
bcm590xx->regmap = devm_regmap_init_i2c(i2c, &bcm590xx_regmap_config); bcm590xx->regmap_pri = devm_regmap_init_i2c(i2c_pri,
if (IS_ERR(bcm590xx->regmap)) { &bcm590xx_regmap_config_pri);
ret = PTR_ERR(bcm590xx->regmap); if (IS_ERR(bcm590xx->regmap_pri)) {
dev_err(&i2c->dev, "regmap initialization failed: %d\n", ret); ret = PTR_ERR(bcm590xx->regmap_pri);
dev_err(&i2c_pri->dev, "primary regmap init failed: %d\n", ret);
return ret; return ret;
} }
ret = mfd_add_devices(&i2c->dev, -1, bcm590xx_devs, /* Secondary I2C slave address is the base address with A(2) asserted */
bcm590xx->i2c_sec = i2c_new_dummy(i2c_pri->adapter,
i2c_pri->addr | BIT(2));
if (IS_ERR_OR_NULL(bcm590xx->i2c_sec)) {
dev_err(&i2c_pri->dev, "failed to add secondary I2C device\n");
return -ENODEV;
}
i2c_set_clientdata(bcm590xx->i2c_sec, bcm590xx);
bcm590xx->regmap_sec = devm_regmap_init_i2c(bcm590xx->i2c_sec,
&bcm590xx_regmap_config_sec);
if (IS_ERR(bcm590xx->regmap_sec)) {
ret = PTR_ERR(bcm590xx->regmap_sec);
dev_err(&bcm590xx->i2c_sec->dev,
"secondary regmap init failed: %d\n", ret);
goto err;
}
ret = mfd_add_devices(&i2c_pri->dev, -1, bcm590xx_devs,
ARRAY_SIZE(bcm590xx_devs), NULL, 0, NULL); ARRAY_SIZE(bcm590xx_devs), NULL, 0, NULL);
if (ret < 0) if (ret < 0) {
dev_err(&i2c->dev, "failed to add sub-devices: %d\n", ret); dev_err(&i2c_pri->dev, "failed to add sub-devices: %d\n", ret);
goto err;
}
return 0;
err:
i2c_unregister_device(bcm590xx->i2c_sec);
return ret; return ret;
} }
......
...@@ -32,14 +32,6 @@ ...@@ -32,14 +32,6 @@
#define NUM_INT_REG 2 #define NUM_INT_REG 2
#define TOTAL_NUM_REG 0x18 #define TOTAL_NUM_REG 0x18
/* interrupt status registers */
#define TPS65090_INT_STS 0x0
#define TPS65090_INT_STS2 0x1
/* interrupt mask registers */
#define TPS65090_INT_MSK 0x2
#define TPS65090_INT_MSK2 0x3
#define TPS65090_INT1_MASK_VAC_STATUS_CHANGE 1 #define TPS65090_INT1_MASK_VAC_STATUS_CHANGE 1
#define TPS65090_INT1_MASK_VSYS_STATUS_CHANGE 2 #define TPS65090_INT1_MASK_VSYS_STATUS_CHANGE 2
#define TPS65090_INT1_MASK_BAT_STATUS_CHANGE 3 #define TPS65090_INT1_MASK_BAT_STATUS_CHANGE 3
...@@ -64,11 +56,16 @@ static struct resource charger_resources[] = { ...@@ -64,11 +56,16 @@ static struct resource charger_resources[] = {
} }
}; };
static const struct mfd_cell tps65090s[] = { enum tps65090_cells {
{ PMIC = 0,
CHARGER = 1,
};
static struct mfd_cell tps65090s[] = {
[PMIC] = {
.name = "tps65090-pmic", .name = "tps65090-pmic",
}, },
{ [CHARGER] = {
.name = "tps65090-charger", .name = "tps65090-charger",
.num_resources = ARRAY_SIZE(charger_resources), .num_resources = ARRAY_SIZE(charger_resources),
.resources = &charger_resources[0], .resources = &charger_resources[0],
...@@ -139,17 +136,26 @@ static struct regmap_irq_chip tps65090_irq_chip = { ...@@ -139,17 +136,26 @@ static struct regmap_irq_chip tps65090_irq_chip = {
.irqs = tps65090_irqs, .irqs = tps65090_irqs,
.num_irqs = ARRAY_SIZE(tps65090_irqs), .num_irqs = ARRAY_SIZE(tps65090_irqs),
.num_regs = NUM_INT_REG, .num_regs = NUM_INT_REG,
.status_base = TPS65090_INT_STS, .status_base = TPS65090_REG_INTR_STS,
.mask_base = TPS65090_INT_MSK, .mask_base = TPS65090_REG_INTR_MASK,
.mask_invert = true, .mask_invert = true,
}; };
static bool is_volatile_reg(struct device *dev, unsigned int reg) static bool is_volatile_reg(struct device *dev, unsigned int reg)
{ {
if ((reg == TPS65090_INT_STS) || (reg == TPS65090_INT_STS2)) /* Nearly all registers have status bits mixed in, except a few */
return true; switch (reg) {
else case TPS65090_REG_INTR_MASK:
case TPS65090_REG_INTR_MASK2:
case TPS65090_REG_CG_CTRL0:
case TPS65090_REG_CG_CTRL1:
case TPS65090_REG_CG_CTRL2:
case TPS65090_REG_CG_CTRL3:
case TPS65090_REG_CG_CTRL4:
case TPS65090_REG_CG_CTRL5:
return false; return false;
}
return true;
} }
static const struct regmap_config tps65090_regmap_config = { static const struct regmap_config tps65090_regmap_config = {
...@@ -211,6 +217,9 @@ static int tps65090_i2c_probe(struct i2c_client *client, ...@@ -211,6 +217,9 @@ static int tps65090_i2c_probe(struct i2c_client *client,
"IRQ init failed with err: %d\n", ret); "IRQ init failed with err: %d\n", ret);
return ret; return ret;
} }
} else {
/* Don't tell children they have an IRQ that'll never fire */
tps65090s[CHARGER].num_resources = 0;
} }
ret = mfd_add_devices(tps65090->dev, -1, tps65090s, ret = mfd_add_devices(tps65090->dev, -1, tps65090s,
......
...@@ -495,6 +495,10 @@ static void tps6586x_print_version(struct i2c_client *client, int version) ...@@ -495,6 +495,10 @@ static void tps6586x_print_version(struct i2c_client *client, int version)
case TPS658623: case TPS658623:
name = "TPS658623"; name = "TPS658623";
break; break;
case TPS658640:
case TPS658640v2:
name = "TPS658640";
break;
case TPS658643: case TPS658643:
name = "TPS658643"; name = "TPS658643";
break; break;
......
...@@ -28,17 +28,6 @@ ...@@ -28,17 +28,6 @@
#include <linux/mfd/tps65090.h> #include <linux/mfd/tps65090.h>
#define TPS65090_REG_INTR_STS 0x00
#define TPS65090_REG_INTR_MASK 0x02
#define TPS65090_REG_CG_CTRL0 0x04
#define TPS65090_REG_CG_CTRL1 0x05
#define TPS65090_REG_CG_CTRL2 0x06
#define TPS65090_REG_CG_CTRL3 0x07
#define TPS65090_REG_CG_CTRL4 0x08
#define TPS65090_REG_CG_CTRL5 0x09
#define TPS65090_REG_CG_STATUS1 0x0a
#define TPS65090_REG_CG_STATUS2 0x0b
#define TPS65090_CHARGER_ENABLE BIT(0) #define TPS65090_CHARGER_ENABLE BIT(0)
#define TPS65090_VACG BIT(1) #define TPS65090_VACG BIT(1)
#define TPS65090_NOITERM BIT(5) #define TPS65090_NOITERM BIT(5)
......
...@@ -139,6 +139,13 @@ config REGULATOR_AS3722 ...@@ -139,6 +139,13 @@ 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_AXP20X
tristate "X-POWERS AXP20X PMIC Regulators"
depends on MFD_AXP20X
help
This driver provides support for the voltage regulators on the
AXP20X PMIC.
config REGULATOR_BCM590XX config REGULATOR_BCM590XX
tristate "Broadcom BCM590xx PMU Regulators" tristate "Broadcom BCM590xx PMU Regulators"
depends on MFD_BCM590XX depends on MFD_BCM590XX
...@@ -265,6 +272,14 @@ config REGULATOR_LP8788 ...@@ -265,6 +272,14 @@ config REGULATOR_LP8788
help help
This driver supports LP8788 voltage regulator chip. This driver supports LP8788 voltage regulator chip.
config REGULATOR_LTC3589
tristate "LTC3589 8-output voltage regulator"
depends on I2C
select REGMAP_I2C
help
This enables support for the LTC3589, LTC3589-1, and LTC3589-2
8-output regulators controlled via I2C.
config REGULATOR_MAX14577 config REGULATOR_MAX14577
tristate "Maxim 14577/77836 regulator" tristate "Maxim 14577/77836 regulator"
depends on MFD_MAX14577 depends on MFD_MAX14577
......
...@@ -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_AXP20X) += axp20x-regulator.o
obj-$(CONFIG_REGULATOR_BCM590XX) += bcm590xx-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
...@@ -37,6 +38,7 @@ obj-$(CONFIG_REGULATOR_LP872X) += lp872x.o ...@@ -37,6 +38,7 @@ obj-$(CONFIG_REGULATOR_LP872X) += lp872x.o
obj-$(CONFIG_REGULATOR_LP8788) += lp8788-buck.o obj-$(CONFIG_REGULATOR_LP8788) += lp8788-buck.o
obj-$(CONFIG_REGULATOR_LP8788) += lp8788-ldo.o obj-$(CONFIG_REGULATOR_LP8788) += lp8788-ldo.o
obj-$(CONFIG_REGULATOR_LP8755) += lp8755.o obj-$(CONFIG_REGULATOR_LP8755) += lp8755.o
obj-$(CONFIG_REGULATOR_LTC3589) += ltc3589.o
obj-$(CONFIG_REGULATOR_MAX14577) += max14577.o obj-$(CONFIG_REGULATOR_MAX14577) += max14577.o
obj-$(CONFIG_REGULATOR_MAX1586) += max1586.o obj-$(CONFIG_REGULATOR_MAX1586) += max1586.o
obj-$(CONFIG_REGULATOR_MAX8649) += max8649.o obj-$(CONFIG_REGULATOR_MAX8649) += max8649.o
......
...@@ -300,7 +300,7 @@ static int anatop_regulator_probe(struct platform_device *pdev) ...@@ -300,7 +300,7 @@ static int anatop_regulator_probe(struct platform_device *pdev)
return 0; return 0;
} }
static struct of_device_id of_anatop_regulator_match_tbl[] = { static const struct of_device_id of_anatop_regulator_match_tbl[] = {
{ .compatible = "fsl,anatop-regulator", }, { .compatible = "fsl,anatop-regulator", },
{ /* end */ } { /* end */ }
}; };
......
...@@ -16,9 +16,11 @@ ...@@ -16,9 +16,11 @@
#include <linux/init.h> #include <linux/init.h>
#include <linux/bitops.h> #include <linux/bitops.h>
#include <linux/err.h> #include <linux/err.h>
#include <linux/of.h>
#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/regulator/of_regulator.h>
#include <linux/gpio.h> #include <linux/gpio.h>
#include <linux/slab.h> #include <linux/slab.h>
...@@ -178,6 +180,42 @@ static const struct regulator_init_data arizona_ldo1_default = { ...@@ -178,6 +180,42 @@ static const struct regulator_init_data arizona_ldo1_default = {
.num_consumer_supplies = 1, .num_consumer_supplies = 1,
}; };
static int arizona_ldo1_of_get_pdata(struct arizona *arizona,
struct regulator_config *config)
{
struct arizona_pdata *pdata = &arizona->pdata;
struct arizona_ldo1 *ldo1 = config->driver_data;
struct device_node *init_node, *dcvdd_node;
struct regulator_init_data *init_data;
pdata->ldoena = arizona_of_get_named_gpio(arizona, "wlf,ldoena", true);
init_node = of_get_child_by_name(arizona->dev->of_node, "ldo1");
dcvdd_node = of_parse_phandle(arizona->dev->of_node, "DCVDD-supply", 0);
if (init_node) {
config->of_node = init_node;
init_data = of_get_regulator_init_data(arizona->dev, init_node);
if (init_data) {
init_data->consumer_supplies = &ldo1->supply;
init_data->num_consumer_supplies = 1;
if (dcvdd_node && dcvdd_node != init_node)
arizona->external_dcvdd = true;
pdata->ldo1 = init_data;
}
} else if (dcvdd_node) {
arizona->external_dcvdd = true;
}
of_node_put(dcvdd_node);
return 0;
}
static int arizona_ldo1_probe(struct platform_device *pdev) static int arizona_ldo1_probe(struct platform_device *pdev)
{ {
struct arizona *arizona = dev_get_drvdata(pdev->dev.parent); struct arizona *arizona = dev_get_drvdata(pdev->dev.parent);
...@@ -186,6 +224,8 @@ static int arizona_ldo1_probe(struct platform_device *pdev) ...@@ -186,6 +224,8 @@ static int arizona_ldo1_probe(struct platform_device *pdev)
struct arizona_ldo1 *ldo1; struct arizona_ldo1 *ldo1;
int ret; int ret;
arizona->external_dcvdd = false;
ldo1 = devm_kzalloc(&pdev->dev, sizeof(*ldo1), GFP_KERNEL); ldo1 = devm_kzalloc(&pdev->dev, sizeof(*ldo1), GFP_KERNEL);
if (!ldo1) if (!ldo1)
return -ENOMEM; return -ENOMEM;
...@@ -216,6 +256,15 @@ static int arizona_ldo1_probe(struct platform_device *pdev) ...@@ -216,6 +256,15 @@ static int arizona_ldo1_probe(struct platform_device *pdev)
config.dev = arizona->dev; config.dev = arizona->dev;
config.driver_data = ldo1; config.driver_data = ldo1;
config.regmap = arizona->regmap; config.regmap = arizona->regmap;
if (IS_ENABLED(CONFIG_OF)) {
if (!dev_get_platdata(arizona->dev)) {
ret = arizona_ldo1_of_get_pdata(arizona, &config);
if (ret < 0)
return ret;
}
}
config.ena_gpio = arizona->pdata.ldoena; config.ena_gpio = arizona->pdata.ldoena;
if (arizona->pdata.ldo1) if (arizona->pdata.ldo1)
...@@ -223,6 +272,13 @@ static int arizona_ldo1_probe(struct platform_device *pdev) ...@@ -223,6 +272,13 @@ static int arizona_ldo1_probe(struct platform_device *pdev)
else else
config.init_data = &ldo1->init_data; config.init_data = &ldo1->init_data;
/*
* LDO1 can only be used to supply DCVDD so if it has no
* consumers then DCVDD is supplied externally.
*/
if (config.init_data->num_consumer_supplies == 0)
arizona->external_dcvdd = true;
ldo1->regulator = devm_regulator_register(&pdev->dev, desc, &config); ldo1->regulator = devm_regulator_register(&pdev->dev, desc, &config);
if (IS_ERR(ldo1->regulator)) { if (IS_ERR(ldo1->regulator)) {
ret = PTR_ERR(ldo1->regulator); ret = PTR_ERR(ldo1->regulator);
...@@ -231,6 +287,8 @@ static int arizona_ldo1_probe(struct platform_device *pdev) ...@@ -231,6 +287,8 @@ static int arizona_ldo1_probe(struct platform_device *pdev)
return ret; return ret;
} }
of_node_put(config.of_node);
platform_set_drvdata(pdev, ldo1); platform_set_drvdata(pdev, ldo1);
return 0; return 0;
......
...@@ -16,9 +16,11 @@ ...@@ -16,9 +16,11 @@
#include <linux/init.h> #include <linux/init.h>
#include <linux/bitops.h> #include <linux/bitops.h>
#include <linux/err.h> #include <linux/err.h>
#include <linux/of.h>
#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/regulator/of_regulator.h>
#include <linux/gpio.h> #include <linux/gpio.h>
#include <linux/slab.h> #include <linux/slab.h>
#include <linux/workqueue.h> #include <linux/workqueue.h>
...@@ -195,6 +197,32 @@ static const struct regulator_init_data arizona_micsupp_ext_default = { ...@@ -195,6 +197,32 @@ static const struct regulator_init_data arizona_micsupp_ext_default = {
.num_consumer_supplies = 1, .num_consumer_supplies = 1,
}; };
static int arizona_micsupp_of_get_pdata(struct arizona *arizona,
struct regulator_config *config)
{
struct arizona_pdata *pdata = &arizona->pdata;
struct arizona_micsupp *micsupp = config->driver_data;
struct device_node *np;
struct regulator_init_data *init_data;
np = of_get_child_by_name(arizona->dev->of_node, "micvdd");
if (np) {
config->of_node = np;
init_data = of_get_regulator_init_data(arizona->dev, np);
if (init_data) {
init_data->consumer_supplies = &micsupp->supply;
init_data->num_consumer_supplies = 1;
pdata->micvdd = init_data;
}
}
return 0;
}
static int arizona_micsupp_probe(struct platform_device *pdev) static int arizona_micsupp_probe(struct platform_device *pdev)
{ {
struct arizona *arizona = dev_get_drvdata(pdev->dev.parent); struct arizona *arizona = dev_get_drvdata(pdev->dev.parent);
...@@ -234,6 +262,14 @@ static int arizona_micsupp_probe(struct platform_device *pdev) ...@@ -234,6 +262,14 @@ static int arizona_micsupp_probe(struct platform_device *pdev)
config.driver_data = micsupp; config.driver_data = micsupp;
config.regmap = arizona->regmap; config.regmap = arizona->regmap;
if (IS_ENABLED(CONFIG_OF)) {
if (!dev_get_platdata(arizona->dev)) {
ret = arizona_micsupp_of_get_pdata(arizona, &config);
if (ret < 0)
return ret;
}
}
if (arizona->pdata.micvdd) if (arizona->pdata.micvdd)
config.init_data = arizona->pdata.micvdd; config.init_data = arizona->pdata.micvdd;
else else
...@@ -253,6 +289,8 @@ static int arizona_micsupp_probe(struct platform_device *pdev) ...@@ -253,6 +289,8 @@ static int arizona_micsupp_probe(struct platform_device *pdev)
return ret; return ret;
} }
of_node_put(config.of_node);
platform_set_drvdata(pdev, micsupp); platform_set_drvdata(pdev, micsupp);
return 0; return 0;
......
/*
* AXP20x regulators driver.
*
* Copyright (C) 2013 Carlo Caione <carlo@caione.org>
*
* This file is subject to the terms and conditions of the GNU General
* Public License. See the file "COPYING" in the main directory of this
* archive for more details.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*/
#include <linux/err.h>
#include <linux/init.h>
#include <linux/module.h>
#include <linux/of.h>
#include <linux/of_device.h>
#include <linux/platform_device.h>
#include <linux/regmap.h>
#include <linux/mfd/axp20x.h>
#include <linux/regulator/driver.h>
#include <linux/regulator/of_regulator.h>
#define AXP20X_IO_ENABLED 0x03
#define AXP20X_IO_DISABLED 0x07
#define AXP20X_WORKMODE_DCDC2_MASK BIT(2)
#define AXP20X_WORKMODE_DCDC3_MASK BIT(1)
#define AXP20X_FREQ_DCDC_MASK 0x0f
#define AXP20X_DESC_IO(_id, _supply, _min, _max, _step, _vreg, _vmask, _ereg, \
_emask, _enable_val, _disable_val) \
[AXP20X_##_id] = { \
.name = #_id, \
.supply_name = (_supply), \
.type = REGULATOR_VOLTAGE, \
.id = AXP20X_##_id, \
.n_voltages = (((_max) - (_min)) / (_step) + 1), \
.owner = THIS_MODULE, \
.min_uV = (_min) * 1000, \
.uV_step = (_step) * 1000, \
.vsel_reg = (_vreg), \
.vsel_mask = (_vmask), \
.enable_reg = (_ereg), \
.enable_mask = (_emask), \
.enable_val = (_enable_val), \
.disable_val = (_disable_val), \
.ops = &axp20x_ops, \
}
#define AXP20X_DESC(_id, _supply, _min, _max, _step, _vreg, _vmask, _ereg, \
_emask) \
[AXP20X_##_id] = { \
.name = #_id, \
.supply_name = (_supply), \
.type = REGULATOR_VOLTAGE, \
.id = AXP20X_##_id, \
.n_voltages = (((_max) - (_min)) / (_step) + 1), \
.owner = THIS_MODULE, \
.min_uV = (_min) * 1000, \
.uV_step = (_step) * 1000, \
.vsel_reg = (_vreg), \
.vsel_mask = (_vmask), \
.enable_reg = (_ereg), \
.enable_mask = (_emask), \
.ops = &axp20x_ops, \
}
#define AXP20X_DESC_FIXED(_id, _supply, _volt) \
[AXP20X_##_id] = { \
.name = #_id, \
.supply_name = (_supply), \
.type = REGULATOR_VOLTAGE, \
.id = AXP20X_##_id, \
.n_voltages = 1, \
.owner = THIS_MODULE, \
.min_uV = (_volt) * 1000, \
.ops = &axp20x_ops_fixed \
}
#define AXP20X_DESC_TABLE(_id, _supply, _table, _vreg, _vmask, _ereg, _emask) \
[AXP20X_##_id] = { \
.name = #_id, \
.supply_name = (_supply), \
.type = REGULATOR_VOLTAGE, \
.id = AXP20X_##_id, \
.n_voltages = ARRAY_SIZE(_table), \
.owner = THIS_MODULE, \
.vsel_reg = (_vreg), \
.vsel_mask = (_vmask), \
.enable_reg = (_ereg), \
.enable_mask = (_emask), \
.volt_table = (_table), \
.ops = &axp20x_ops_table, \
}
static const int axp20x_ldo4_data[] = { 1250000, 1300000, 1400000, 1500000, 1600000,
1700000, 1800000, 1900000, 2000000, 2500000,
2700000, 2800000, 3000000, 3100000, 3200000,
3300000 };
static struct regulator_ops axp20x_ops_fixed = {
.list_voltage = regulator_list_voltage_linear,
};
static struct regulator_ops axp20x_ops_table = {
.set_voltage_sel = regulator_set_voltage_sel_regmap,
.get_voltage_sel = regulator_get_voltage_sel_regmap,
.list_voltage = regulator_list_voltage_table,
.map_voltage = regulator_map_voltage_ascend,
.enable = regulator_enable_regmap,
.disable = regulator_disable_regmap,
.is_enabled = regulator_is_enabled_regmap,
};
static struct regulator_ops axp20x_ops = {
.set_voltage_sel = regulator_set_voltage_sel_regmap,
.get_voltage_sel = regulator_get_voltage_sel_regmap,
.list_voltage = regulator_list_voltage_linear,
.enable = regulator_enable_regmap,
.disable = regulator_disable_regmap,
.is_enabled = regulator_is_enabled_regmap,
};
static const struct regulator_desc axp20x_regulators[] = {
AXP20X_DESC(DCDC2, "vin2", 700, 2275, 25, AXP20X_DCDC2_V_OUT, 0x3f,
AXP20X_PWR_OUT_CTRL, 0x10),
AXP20X_DESC(DCDC3, "vin3", 700, 3500, 25, AXP20X_DCDC3_V_OUT, 0x7f,
AXP20X_PWR_OUT_CTRL, 0x02),
AXP20X_DESC_FIXED(LDO1, "acin", 1300),
AXP20X_DESC(LDO2, "ldo24in", 1800, 3300, 100, AXP20X_LDO24_V_OUT, 0xf0,
AXP20X_PWR_OUT_CTRL, 0x04),
AXP20X_DESC(LDO3, "ldo3in", 700, 3500, 25, AXP20X_LDO3_V_OUT, 0x7f,
AXP20X_PWR_OUT_CTRL, 0x40),
AXP20X_DESC_TABLE(LDO4, "ldo24in", axp20x_ldo4_data, AXP20X_LDO24_V_OUT, 0x0f,
AXP20X_PWR_OUT_CTRL, 0x08),
AXP20X_DESC_IO(LDO5, "ldo5in", 1800, 3300, 100, AXP20X_LDO5_V_OUT, 0xf0,
AXP20X_GPIO0_CTRL, 0x07, AXP20X_IO_ENABLED,
AXP20X_IO_DISABLED),
};
#define AXP_MATCH(_name, _id) \
[AXP20X_##_id] = { \
.name = #_name, \
.driver_data = (void *) &axp20x_regulators[AXP20X_##_id], \
}
static struct of_regulator_match axp20x_matches[] = {
AXP_MATCH(dcdc2, DCDC2),
AXP_MATCH(dcdc3, DCDC3),
AXP_MATCH(ldo1, LDO1),
AXP_MATCH(ldo2, LDO2),
AXP_MATCH(ldo3, LDO3),
AXP_MATCH(ldo4, LDO4),
AXP_MATCH(ldo5, LDO5),
};
static int axp20x_set_dcdc_freq(struct platform_device *pdev, u32 dcdcfreq)
{
struct axp20x_dev *axp20x = dev_get_drvdata(pdev->dev.parent);
if (dcdcfreq < 750) {
dcdcfreq = 750;
dev_warn(&pdev->dev, "DCDC frequency too low. Set to 750kHz\n");
}
if (dcdcfreq > 1875) {
dcdcfreq = 1875;
dev_warn(&pdev->dev, "DCDC frequency too high. Set to 1875kHz\n");
}
dcdcfreq = (dcdcfreq - 750) / 75;
return regmap_update_bits(axp20x->regmap, AXP20X_DCDC_FREQ,
AXP20X_FREQ_DCDC_MASK, dcdcfreq);
}
static int axp20x_regulator_parse_dt(struct platform_device *pdev)
{
struct device_node *np, *regulators;
int ret;
u32 dcdcfreq;
np = of_node_get(pdev->dev.parent->of_node);
if (!np)
return 0;
regulators = of_get_child_by_name(np, "regulators");
if (!regulators) {
dev_warn(&pdev->dev, "regulators node not found\n");
} else {
ret = of_regulator_match(&pdev->dev, regulators, axp20x_matches,
ARRAY_SIZE(axp20x_matches));
if (ret < 0) {
dev_err(&pdev->dev, "Error parsing regulator init data: %d\n", ret);
return ret;
}
dcdcfreq = 1500;
of_property_read_u32(regulators, "x-powers,dcdc-freq", &dcdcfreq);
ret = axp20x_set_dcdc_freq(pdev, dcdcfreq);
if (ret < 0) {
dev_err(&pdev->dev, "Error setting dcdc frequency: %d\n", ret);
return ret;
}
of_node_put(regulators);
}
return 0;
}
static int axp20x_set_dcdc_workmode(struct regulator_dev *rdev, int id, u32 workmode)
{
unsigned int mask = AXP20X_WORKMODE_DCDC2_MASK;
if ((id != AXP20X_DCDC2) && (id != AXP20X_DCDC3))
return -EINVAL;
if (id == AXP20X_DCDC3)
mask = AXP20X_WORKMODE_DCDC3_MASK;
workmode <<= ffs(mask) - 1;
return regmap_update_bits(rdev->regmap, AXP20X_DCDC_MODE, mask, workmode);
}
static int axp20x_regulator_probe(struct platform_device *pdev)
{
struct regulator_dev *rdev;
struct axp20x_dev *axp20x = dev_get_drvdata(pdev->dev.parent);
struct regulator_config config = { };
struct regulator_init_data *init_data;
int ret, i;
u32 workmode;
ret = axp20x_regulator_parse_dt(pdev);
if (ret)
return ret;
for (i = 0; i < AXP20X_REG_ID_MAX; i++) {
init_data = axp20x_matches[i].init_data;
config.dev = &pdev->dev;
config.init_data = init_data;
config.regmap = axp20x->regmap;
config.of_node = axp20x_matches[i].of_node;
rdev = devm_regulator_register(&pdev->dev, &axp20x_regulators[i],
&config);
if (IS_ERR(rdev)) {
dev_err(&pdev->dev, "Failed to register %s\n",
axp20x_regulators[i].name);
return PTR_ERR(rdev);
}
ret = of_property_read_u32(axp20x_matches[i].of_node, "x-powers,dcdc-workmode",
&workmode);
if (!ret) {
if (axp20x_set_dcdc_workmode(rdev, i, workmode))
dev_err(&pdev->dev, "Failed to set workmode on %s\n",
axp20x_regulators[i].name);
}
}
return 0;
}
static struct platform_driver axp20x_regulator_driver = {
.probe = axp20x_regulator_probe,
.driver = {
.name = "axp20x-regulator",
.owner = THIS_MODULE,
},
};
module_platform_driver(axp20x_regulator_driver);
MODULE_LICENSE("GPL v2");
MODULE_AUTHOR("Carlo Caione <carlo@caione.org>");
MODULE_DESCRIPTION("Regulator Driver for AXP20X PMIC");
...@@ -22,7 +22,7 @@ ...@@ -22,7 +22,7 @@
#include <linux/regulator/of_regulator.h> #include <linux/regulator/of_regulator.h>
#include <linux/slab.h> #include <linux/slab.h>
/* Register defs */ /* I2C slave 0 registers */
#define BCM590XX_RFLDOPMCTRL1 0x60 #define BCM590XX_RFLDOPMCTRL1 0x60
#define BCM590XX_IOSR1PMCTRL1 0x7a #define BCM590XX_IOSR1PMCTRL1 0x7a
#define BCM590XX_IOSR2PMCTRL1 0x7c #define BCM590XX_IOSR2PMCTRL1 0x7c
...@@ -31,13 +31,34 @@ ...@@ -31,13 +31,34 @@
#define BCM590XX_SDSR2PMCTRL1 0x86 #define BCM590XX_SDSR2PMCTRL1 0x86
#define BCM590XX_MSRPMCTRL1 0x8a #define BCM590XX_MSRPMCTRL1 0x8a
#define BCM590XX_VSRPMCTRL1 0x8e #define BCM590XX_VSRPMCTRL1 0x8e
#define BCM590XX_REG_ENABLE BIT(7)
#define BCM590XX_RFLDOCTRL 0x96 #define BCM590XX_RFLDOCTRL 0x96
#define BCM590XX_CSRVOUT1 0xc0 #define BCM590XX_CSRVOUT1 0xc0
/* I2C slave 1 registers */
#define BCM590XX_GPLDO5PMCTRL1 0x16
#define BCM590XX_GPLDO6PMCTRL1 0x18
#define BCM590XX_GPLDO1CTRL 0x1a
#define BCM590XX_GPLDO2CTRL 0x1b
#define BCM590XX_GPLDO3CTRL 0x1c
#define BCM590XX_GPLDO4CTRL 0x1d
#define BCM590XX_GPLDO5CTRL 0x1e
#define BCM590XX_GPLDO6CTRL 0x1f
#define BCM590XX_OTG_CTRL 0x40
#define BCM590XX_GPLDO1PMCTRL1 0x57
#define BCM590XX_GPLDO2PMCTRL1 0x59
#define BCM590XX_GPLDO3PMCTRL1 0x5b
#define BCM590XX_GPLDO4PMCTRL1 0x5d
#define BCM590XX_REG_ENABLE BIT(7)
#define BCM590XX_VBUS_ENABLE BIT(2)
#define BCM590XX_LDO_VSEL_MASK GENMASK(5, 3) #define BCM590XX_LDO_VSEL_MASK GENMASK(5, 3)
#define BCM590XX_SR_VSEL_MASK GENMASK(5, 0) #define BCM590XX_SR_VSEL_MASK GENMASK(5, 0)
/*
* RFLDO to VSR regulators are
* accessed via I2C slave 0
*/
/* LDO regulator IDs */ /* LDO regulator IDs */
#define BCM590XX_REG_RFLDO 0 #define BCM590XX_REG_RFLDO 0
#define BCM590XX_REG_CAMLDO1 1 #define BCM590XX_REG_CAMLDO1 1
...@@ -62,9 +83,25 @@ ...@@ -62,9 +83,25 @@
#define BCM590XX_REG_SDSR2 18 #define BCM590XX_REG_SDSR2 18
#define BCM590XX_REG_VSR 19 #define BCM590XX_REG_VSR 19
#define BCM590XX_NUM_REGS 20 /*
* GPLDO1 to VBUS regulators are
* accessed via I2C slave 1
*/
#define BCM590XX_REG_GPLDO1 20
#define BCM590XX_REG_GPLDO2 21
#define BCM590XX_REG_GPLDO3 22
#define BCM590XX_REG_GPLDO4 23
#define BCM590XX_REG_GPLDO5 24
#define BCM590XX_REG_GPLDO6 25
#define BCM590XX_REG_VBUS 26
#define BCM590XX_NUM_REGS 27
#define BCM590XX_REG_IS_LDO(n) (n < BCM590XX_REG_CSR) #define BCM590XX_REG_IS_LDO(n) (n < BCM590XX_REG_CSR)
#define BCM590XX_REG_IS_GPLDO(n) \
((n > BCM590XX_REG_VSR) && (n < BCM590XX_REG_VBUS))
#define BCM590XX_REG_IS_VBUS(n) (n == BCM590XX_REG_VBUS)
struct bcm590xx_board { struct bcm590xx_board {
struct regulator_init_data *bcm590xx_pmu_init_data[BCM590XX_NUM_REGS]; struct regulator_init_data *bcm590xx_pmu_init_data[BCM590XX_NUM_REGS];
...@@ -149,6 +186,12 @@ static struct bcm590xx_info bcm590xx_regs[] = { ...@@ -149,6 +186,12 @@ static struct bcm590xx_info bcm590xx_regs[] = {
BCM590XX_REG_RANGES(sdsr1, dcdc_sdsr1_ranges), BCM590XX_REG_RANGES(sdsr1, dcdc_sdsr1_ranges),
BCM590XX_REG_RANGES(sdsr2, dcdc_iosr1_ranges), BCM590XX_REG_RANGES(sdsr2, dcdc_iosr1_ranges),
BCM590XX_REG_RANGES(vsr, dcdc_iosr1_ranges), BCM590XX_REG_RANGES(vsr, dcdc_iosr1_ranges),
BCM590XX_REG_TABLE(gpldo1, ldo_a_table),
BCM590XX_REG_TABLE(gpldo2, ldo_a_table),
BCM590XX_REG_TABLE(gpldo3, ldo_a_table),
BCM590XX_REG_TABLE(gpldo4, ldo_a_table),
BCM590XX_REG_TABLE(gpldo5, ldo_a_table),
BCM590XX_REG_TABLE(gpldo6, ldo_a_table),
}; };
struct bcm590xx_reg { struct bcm590xx_reg {
...@@ -161,6 +204,8 @@ static int bcm590xx_get_vsel_register(int id) ...@@ -161,6 +204,8 @@ static int bcm590xx_get_vsel_register(int id)
{ {
if (BCM590XX_REG_IS_LDO(id)) if (BCM590XX_REG_IS_LDO(id))
return BCM590XX_RFLDOCTRL + id; return BCM590XX_RFLDOCTRL + id;
else if (BCM590XX_REG_IS_GPLDO(id))
return BCM590XX_GPLDO1CTRL + id;
else else
return BCM590XX_CSRVOUT1 + (id - BCM590XX_REG_CSR) * 3; return BCM590XX_CSRVOUT1 + (id - BCM590XX_REG_CSR) * 3;
} }
...@@ -171,6 +216,8 @@ static int bcm590xx_get_enable_register(int id) ...@@ -171,6 +216,8 @@ static int bcm590xx_get_enable_register(int id)
if (BCM590XX_REG_IS_LDO(id)) if (BCM590XX_REG_IS_LDO(id))
reg = BCM590XX_RFLDOPMCTRL1 + id * 2; reg = BCM590XX_RFLDOPMCTRL1 + id * 2;
else if (BCM590XX_REG_IS_GPLDO(id))
reg = BCM590XX_GPLDO1PMCTRL1 + id * 2;
else else
switch (id) { switch (id) {
case BCM590XX_REG_CSR: case BCM590XX_REG_CSR:
...@@ -191,8 +238,11 @@ static int bcm590xx_get_enable_register(int id) ...@@ -191,8 +238,11 @@ static int bcm590xx_get_enable_register(int id)
case BCM590XX_REG_SDSR2: case BCM590XX_REG_SDSR2:
reg = BCM590XX_SDSR2PMCTRL1; reg = BCM590XX_SDSR2PMCTRL1;
break; break;
case BCM590XX_REG_VBUS:
reg = BCM590XX_OTG_CTRL;
}; };
return reg; return reg;
} }
...@@ -216,6 +266,12 @@ static struct regulator_ops bcm590xx_ops_dcdc = { ...@@ -216,6 +266,12 @@ static struct regulator_ops bcm590xx_ops_dcdc = {
.map_voltage = regulator_map_voltage_linear_range, .map_voltage = regulator_map_voltage_linear_range,
}; };
static struct regulator_ops bcm590xx_ops_vbus = {
.is_enabled = regulator_is_enabled_regmap,
.enable = regulator_enable_regmap,
.disable = regulator_disable_regmap,
};
#define BCM590XX_MATCH(_name, _id) \ #define BCM590XX_MATCH(_name, _id) \
{ \ { \
.name = #_name, \ .name = #_name, \
...@@ -243,6 +299,13 @@ static struct of_regulator_match bcm590xx_matches[] = { ...@@ -243,6 +299,13 @@ static struct of_regulator_match bcm590xx_matches[] = {
BCM590XX_MATCH(sdsr1, SDSR1), BCM590XX_MATCH(sdsr1, SDSR1),
BCM590XX_MATCH(sdsr2, SDSR2), BCM590XX_MATCH(sdsr2, SDSR2),
BCM590XX_MATCH(vsr, VSR), BCM590XX_MATCH(vsr, VSR),
BCM590XX_MATCH(gpldo1, GPLDO1),
BCM590XX_MATCH(gpldo2, GPLDO2),
BCM590XX_MATCH(gpldo3, GPLDO3),
BCM590XX_MATCH(gpldo4, GPLDO4),
BCM590XX_MATCH(gpldo5, GPLDO5),
BCM590XX_MATCH(gpldo6, GPLDO6),
BCM590XX_MATCH(vbus, VBUS),
}; };
static struct bcm590xx_board *bcm590xx_parse_dt_reg_data( static struct bcm590xx_board *bcm590xx_parse_dt_reg_data(
...@@ -353,17 +416,23 @@ static int bcm590xx_probe(struct platform_device *pdev) ...@@ -353,17 +416,23 @@ static int bcm590xx_probe(struct platform_device *pdev)
pmu->desc[i].linear_ranges = info->linear_ranges; pmu->desc[i].linear_ranges = info->linear_ranges;
pmu->desc[i].n_linear_ranges = info->n_linear_ranges; pmu->desc[i].n_linear_ranges = info->n_linear_ranges;
if (BCM590XX_REG_IS_LDO(i)) { if ((BCM590XX_REG_IS_LDO(i)) || (BCM590XX_REG_IS_GPLDO(i))) {
pmu->desc[i].ops = &bcm590xx_ops_ldo; pmu->desc[i].ops = &bcm590xx_ops_ldo;
pmu->desc[i].vsel_mask = BCM590XX_LDO_VSEL_MASK; pmu->desc[i].vsel_mask = BCM590XX_LDO_VSEL_MASK;
} else { } else if (BCM590XX_REG_IS_VBUS(i))
pmu->desc[i].ops = &bcm590xx_ops_vbus;
else {
pmu->desc[i].ops = &bcm590xx_ops_dcdc; pmu->desc[i].ops = &bcm590xx_ops_dcdc;
pmu->desc[i].vsel_mask = BCM590XX_SR_VSEL_MASK; pmu->desc[i].vsel_mask = BCM590XX_SR_VSEL_MASK;
} }
pmu->desc[i].vsel_reg = bcm590xx_get_vsel_register(i); if (BCM590XX_REG_IS_VBUS(i))
pmu->desc[i].enable_is_inverted = true; pmu->desc[i].enable_mask = BCM590XX_VBUS_ENABLE;
pmu->desc[i].enable_mask = BCM590XX_REG_ENABLE; else {
pmu->desc[i].vsel_reg = bcm590xx_get_vsel_register(i);
pmu->desc[i].enable_is_inverted = true;
pmu->desc[i].enable_mask = BCM590XX_REG_ENABLE;
}
pmu->desc[i].enable_reg = bcm590xx_get_enable_register(i); pmu->desc[i].enable_reg = bcm590xx_get_enable_register(i);
pmu->desc[i].type = REGULATOR_VOLTAGE; pmu->desc[i].type = REGULATOR_VOLTAGE;
pmu->desc[i].owner = THIS_MODULE; pmu->desc[i].owner = THIS_MODULE;
...@@ -371,7 +440,10 @@ static int bcm590xx_probe(struct platform_device *pdev) ...@@ -371,7 +440,10 @@ static int bcm590xx_probe(struct platform_device *pdev)
config.dev = bcm590xx->dev; config.dev = bcm590xx->dev;
config.init_data = reg_data; config.init_data = reg_data;
config.driver_data = pmu; config.driver_data = pmu;
config.regmap = bcm590xx->regmap; if (BCM590XX_REG_IS_GPLDO(i) || BCM590XX_REG_IS_VBUS(i))
config.regmap = bcm590xx->regmap_sec;
else
config.regmap = bcm590xx->regmap_pri;
if (bcm590xx_reg_matches) if (bcm590xx_reg_matches)
config.of_node = bcm590xx_reg_matches[i].of_node; config.of_node = bcm590xx_reg_matches[i].of_node;
......
...@@ -844,13 +844,22 @@ static int machine_constraints_voltage(struct regulator_dev *rdev, ...@@ -844,13 +844,22 @@ static int machine_constraints_voltage(struct regulator_dev *rdev,
/* do we need to apply the constraint voltage */ /* do we need to apply the constraint voltage */
if (rdev->constraints->apply_uV && if (rdev->constraints->apply_uV &&
rdev->constraints->min_uV == rdev->constraints->max_uV) { rdev->constraints->min_uV == rdev->constraints->max_uV) {
ret = _regulator_do_set_voltage(rdev, int current_uV = _regulator_get_voltage(rdev);
rdev->constraints->min_uV, if (current_uV < 0) {
rdev->constraints->max_uV); rdev_err(rdev, "failed to get the current voltage\n");
if (ret < 0) { return current_uV;
rdev_err(rdev, "failed to apply %duV constraint\n", }
rdev->constraints->min_uV); if (current_uV < rdev->constraints->min_uV ||
return ret; current_uV > rdev->constraints->max_uV) {
ret = _regulator_do_set_voltage(
rdev, rdev->constraints->min_uV,
rdev->constraints->max_uV);
if (ret < 0) {
rdev_err(rdev,
"failed to apply %duV constraint\n",
rdev->constraints->min_uV);
return ret;
}
} }
} }
...@@ -1430,9 +1439,9 @@ EXPORT_SYMBOL_GPL(regulator_get); ...@@ -1430,9 +1439,9 @@ EXPORT_SYMBOL_GPL(regulator_get);
* *
* Returns a struct regulator corresponding to the regulator producer, * Returns a struct regulator corresponding to the regulator producer,
* or IS_ERR() condition containing errno. Other consumers will be * or IS_ERR() condition containing errno. Other consumers will be
* unable to obtain this reference is held and the use count for the * unable to obtain this regulator while this reference is held and the
* regulator will be initialised to reflect the current state of the * use count for the regulator will be initialised to reflect the current
* regulator. * state of the regulator.
* *
* This is intended for use by consumers which cannot tolerate shared * This is intended for use by consumers which cannot tolerate shared
* use of the regulator such as those which need to force the * use of the regulator such as those which need to force the
...@@ -1456,10 +1465,7 @@ EXPORT_SYMBOL_GPL(regulator_get_exclusive); ...@@ -1456,10 +1465,7 @@ EXPORT_SYMBOL_GPL(regulator_get_exclusive);
* @id: Supply name or regulator ID. * @id: Supply name or regulator ID.
* *
* Returns a struct regulator corresponding to the regulator producer, * Returns a struct regulator corresponding to the regulator producer,
* or IS_ERR() condition containing errno. Other consumers will be * or IS_ERR() condition containing errno.
* unable to obtain this reference is held and the use count for the
* regulator will be initialised to reflect the current state of the
* regulator.
* *
* This is intended for use by consumers for devices which can have * This is intended for use by consumers for devices which can have
* some supplies unconnected in normal use, such as some MMC devices. * some supplies unconnected in normal use, such as some MMC devices.
...@@ -1597,9 +1603,10 @@ EXPORT_SYMBOL_GPL(regulator_unregister_supply_alias); ...@@ -1597,9 +1603,10 @@ EXPORT_SYMBOL_GPL(regulator_unregister_supply_alias);
* registered any aliases that were registered will be removed * registered any aliases that were registered will be removed
* before returning to the caller. * before returning to the caller.
*/ */
int regulator_bulk_register_supply_alias(struct device *dev, const char **id, int regulator_bulk_register_supply_alias(struct device *dev,
const char *const *id,
struct device *alias_dev, struct device *alias_dev,
const char **alias_id, const char *const *alias_id,
int num_id) int num_id)
{ {
int i; int i;
...@@ -1637,7 +1644,7 @@ EXPORT_SYMBOL_GPL(regulator_bulk_register_supply_alias); ...@@ -1637,7 +1644,7 @@ EXPORT_SYMBOL_GPL(regulator_bulk_register_supply_alias);
* aliases in one operation. * aliases in one operation.
*/ */
void regulator_bulk_unregister_supply_alias(struct device *dev, void regulator_bulk_unregister_supply_alias(struct device *dev,
const char **id, const char *const *id,
int num_id) int num_id)
{ {
int i; int i;
...@@ -2321,6 +2328,10 @@ static int _regulator_do_set_voltage(struct regulator_dev *rdev, ...@@ -2321,6 +2328,10 @@ static int _regulator_do_set_voltage(struct regulator_dev *rdev,
regulator_list_voltage_linear) regulator_list_voltage_linear)
ret = regulator_map_voltage_linear(rdev, ret = regulator_map_voltage_linear(rdev,
min_uV, max_uV); min_uV, max_uV);
else if (rdev->desc->ops->list_voltage ==
regulator_list_voltage_linear_range)
ret = regulator_map_voltage_linear_range(rdev,
min_uV, max_uV);
else else
ret = regulator_map_voltage_iterate(rdev, ret = regulator_map_voltage_iterate(rdev,
min_uV, max_uV); min_uV, max_uV);
...@@ -3447,7 +3458,7 @@ regulator_register(const struct regulator_desc *regulator_desc, ...@@ -3447,7 +3458,7 @@ regulator_register(const struct regulator_desc *regulator_desc,
/* register with sysfs */ /* register with sysfs */
rdev->dev.class = &regulator_class; rdev->dev.class = &regulator_class;
rdev->dev.of_node = config->of_node; rdev->dev.of_node = of_node_get(config->of_node);
rdev->dev.parent = dev; rdev->dev.parent = dev;
dev_set_name(&rdev->dev, "regulator.%d", dev_set_name(&rdev->dev, "regulator.%d",
atomic_inc_return(&regulator_no) - 1); atomic_inc_return(&regulator_no) - 1);
...@@ -3589,6 +3600,7 @@ void regulator_unregister(struct regulator_dev *rdev) ...@@ -3589,6 +3600,7 @@ void regulator_unregister(struct regulator_dev *rdev)
list_del(&rdev->list); list_del(&rdev->list);
kfree(rdev->constraints); kfree(rdev->constraints);
regulator_ena_gpio_free(rdev); regulator_ena_gpio_free(rdev);
of_node_put(rdev->dev.of_node);
device_unregister(&rdev->dev); device_unregister(&rdev->dev);
mutex_unlock(&regulator_list_mutex); mutex_unlock(&regulator_list_mutex);
} }
...@@ -3819,8 +3831,9 @@ static int __init regulator_init_complete(void) ...@@ -3819,8 +3831,9 @@ static int __init regulator_init_complete(void)
mutex_lock(&regulator_list_mutex); mutex_lock(&regulator_list_mutex);
/* If we have a full configuration then disable any regulators /* If we have a full configuration then disable any regulators
* which are not in use or always_on. This will become the * we have permission to change the status for and which are
* default behaviour in the future. * not in use or always_on. This is effectively the default
* for DT and ACPI as they have full constraints.
*/ */
list_for_each_entry(rdev, &regulator_list, list) { list_for_each_entry(rdev, &regulator_list, list) {
ops = rdev->desc->ops; ops = rdev->desc->ops;
...@@ -3829,6 +3842,9 @@ static int __init regulator_init_complete(void) ...@@ -3829,6 +3842,9 @@ static int __init regulator_init_complete(void)
if (c && c->always_on) if (c && c->always_on)
continue; continue;
if (c && !(c->valid_ops_mask & REGULATOR_CHANGE_STATUS))
continue;
mutex_lock(&rdev->mutex); mutex_lock(&rdev->mutex);
if (rdev->use_count) if (rdev->use_count)
...@@ -3867,4 +3883,4 @@ static int __init regulator_init_complete(void) ...@@ -3867,4 +3883,4 @@ static int __init regulator_init_complete(void)
return 0; return 0;
} }
late_initcall(regulator_init_complete); late_initcall_sync(regulator_init_complete);
...@@ -360,9 +360,9 @@ EXPORT_SYMBOL_GPL(devm_regulator_unregister_supply_alias); ...@@ -360,9 +360,9 @@ EXPORT_SYMBOL_GPL(devm_regulator_unregister_supply_alias);
* will be removed before returning to the caller. * will be removed before returning to the caller.
*/ */
int devm_regulator_bulk_register_supply_alias(struct device *dev, int devm_regulator_bulk_register_supply_alias(struct device *dev,
const char **id, const char *const *id,
struct device *alias_dev, struct device *alias_dev,
const char **alias_id, const char *const *alias_id,
int num_id) int num_id)
{ {
int i; int i;
...@@ -404,7 +404,7 @@ EXPORT_SYMBOL_GPL(devm_regulator_bulk_register_supply_alias); ...@@ -404,7 +404,7 @@ EXPORT_SYMBOL_GPL(devm_regulator_bulk_register_supply_alias);
* will ensure that the resource is freed. * will ensure that the resource is freed.
*/ */
void devm_regulator_bulk_unregister_supply_alias(struct device *dev, void devm_regulator_bulk_unregister_supply_alias(struct device *dev,
const char **id, const char *const *id,
int num_id) int num_id)
{ {
int i; int i;
......
...@@ -50,7 +50,6 @@ of_get_fixed_voltage_config(struct device *dev) ...@@ -50,7 +50,6 @@ of_get_fixed_voltage_config(struct device *dev)
{ {
struct fixed_voltage_config *config; struct fixed_voltage_config *config;
struct device_node *np = dev->of_node; struct device_node *np = dev->of_node;
const __be32 *delay;
struct regulator_init_data *init_data; struct regulator_init_data *init_data;
config = devm_kzalloc(dev, sizeof(struct fixed_voltage_config), config = devm_kzalloc(dev, sizeof(struct fixed_voltage_config),
...@@ -91,15 +90,11 @@ of_get_fixed_voltage_config(struct device *dev) ...@@ -91,15 +90,11 @@ of_get_fixed_voltage_config(struct device *dev)
if ((config->gpio == -ENODEV) || (config->gpio == -EPROBE_DEFER)) if ((config->gpio == -ENODEV) || (config->gpio == -EPROBE_DEFER))
return ERR_PTR(-EPROBE_DEFER); return ERR_PTR(-EPROBE_DEFER);
delay = of_get_property(np, "startup-delay-us", NULL); of_property_read_u32(np, "startup-delay-us", &config->startup_delay);
if (delay)
config->startup_delay = be32_to_cpu(*delay);
if (of_find_property(np, "enable-active-high", NULL)) config->enable_high = of_property_read_bool(np, "enable-active-high");
config->enable_high = true; config->gpio_is_open_drain = of_property_read_bool(np,
"gpio-open-drain");
if (of_find_property(np, "gpio-open-drain", NULL))
config->gpio_is_open_drain = true;
if (of_find_property(np, "vin-supply", NULL)) if (of_find_property(np, "vin-supply", NULL))
config->input_supply = "vin"; config->input_supply = "vin";
......
This diff is collapsed.
...@@ -161,10 +161,8 @@ static int max8649_regulator_probe(struct i2c_client *client, ...@@ -161,10 +161,8 @@ static int max8649_regulator_probe(struct i2c_client *client,
info = devm_kzalloc(&client->dev, sizeof(struct max8649_regulator_info), info = devm_kzalloc(&client->dev, sizeof(struct max8649_regulator_info),
GFP_KERNEL); GFP_KERNEL);
if (!info) { if (!info)
dev_err(&client->dev, "No enough memory\n");
return -ENOMEM; return -ENOMEM;
}
info->regmap = devm_regmap_init_i2c(client, &max8649_regmap_config); info->regmap = devm_regmap_init_i2c(client, &max8649_regmap_config);
if (IS_ERR(info->regmap)) { if (IS_ERR(info->regmap)) {
......
...@@ -129,7 +129,7 @@ static const struct regulator_desc regulator = { ...@@ -129,7 +129,7 @@ static const struct regulator_desc regulator = {
}; };
#ifdef CONFIG_OF #ifdef CONFIG_OF
static struct of_device_id max8952_dt_match[] = { static const struct of_device_id max8952_dt_match[] = {
{ .compatible = "maxim,max8952" }, { .compatible = "maxim,max8952" },
{}, {},
}; };
......
...@@ -19,9 +19,7 @@ ...@@ -19,9 +19,7 @@
static void of_get_regulation_constraints(struct device_node *np, static void of_get_regulation_constraints(struct device_node *np,
struct regulator_init_data **init_data) struct regulator_init_data **init_data)
{ {
const __be32 *min_uV, *max_uV, *uV_offset; const __be32 *min_uV, *max_uV;
const __be32 *min_uA, *max_uA, *ramp_delay;
struct property *prop;
struct regulation_constraints *constraints = &(*init_data)->constraints; struct regulation_constraints *constraints = &(*init_data)->constraints;
int ret; int ret;
u32 pval; u32 pval;
...@@ -42,36 +40,29 @@ static void of_get_regulation_constraints(struct device_node *np, ...@@ -42,36 +40,29 @@ static void of_get_regulation_constraints(struct device_node *np,
if (min_uV && max_uV && constraints->min_uV == constraints->max_uV) if (min_uV && max_uV && constraints->min_uV == constraints->max_uV)
constraints->apply_uV = true; constraints->apply_uV = true;
uV_offset = of_get_property(np, "regulator-microvolt-offset", NULL); if (!of_property_read_u32(np, "regulator-microvolt-offset", &pval))
if (uV_offset) constraints->uV_offset = pval;
constraints->uV_offset = be32_to_cpu(*uV_offset); if (!of_property_read_u32(np, "regulator-min-microamp", &pval))
min_uA = of_get_property(np, "regulator-min-microamp", NULL); constraints->min_uA = pval;
if (min_uA) if (!of_property_read_u32(np, "regulator-max-microamp", &pval))
constraints->min_uA = be32_to_cpu(*min_uA); constraints->max_uA = pval;
max_uA = of_get_property(np, "regulator-max-microamp", NULL);
if (max_uA)
constraints->max_uA = be32_to_cpu(*max_uA);
/* Current change possible? */ /* Current change possible? */
if (constraints->min_uA != constraints->max_uA) if (constraints->min_uA != constraints->max_uA)
constraints->valid_ops_mask |= REGULATOR_CHANGE_CURRENT; constraints->valid_ops_mask |= REGULATOR_CHANGE_CURRENT;
if (of_find_property(np, "regulator-boot-on", NULL)) constraints->boot_on = of_property_read_bool(np, "regulator-boot-on");
constraints->boot_on = true; constraints->always_on = of_property_read_bool(np, "regulator-always-on");
if (!constraints->always_on) /* status change should be possible. */
if (of_find_property(np, "regulator-always-on", NULL))
constraints->always_on = true;
else /* status change should be possible if not always on. */
constraints->valid_ops_mask |= REGULATOR_CHANGE_STATUS; constraints->valid_ops_mask |= REGULATOR_CHANGE_STATUS;
if (of_property_read_bool(np, "regulator-allow-bypass")) if (of_property_read_bool(np, "regulator-allow-bypass"))
constraints->valid_ops_mask |= REGULATOR_CHANGE_BYPASS; constraints->valid_ops_mask |= REGULATOR_CHANGE_BYPASS;
prop = of_find_property(np, "regulator-ramp-delay", NULL); ret = of_property_read_u32(np, "regulator-ramp-delay", &pval);
if (prop && prop->value) { if (!ret) {
ramp_delay = prop->value; if (pval)
if (*ramp_delay) constraints->ramp_delay = pval;
constraints->ramp_delay = be32_to_cpu(*ramp_delay);
else else
constraints->ramp_disable = true; constraints->ramp_disable = true;
} }
...@@ -106,6 +97,20 @@ struct regulator_init_data *of_get_regulator_init_data(struct device *dev, ...@@ -106,6 +97,20 @@ struct regulator_init_data *of_get_regulator_init_data(struct device *dev,
} }
EXPORT_SYMBOL_GPL(of_get_regulator_init_data); EXPORT_SYMBOL_GPL(of_get_regulator_init_data);
struct devm_of_regulator_matches {
struct of_regulator_match *matches;
unsigned int num_matches;
};
static void devm_of_regulator_put_matches(struct device *dev, void *res)
{
struct devm_of_regulator_matches *devm_matches = res;
int i;
for (i = 0; i < devm_matches->num_matches; i++)
of_node_put(devm_matches->matches[i].of_node);
}
/** /**
* of_regulator_match - extract multiple regulator init data from device tree. * of_regulator_match - extract multiple regulator init data from device tree.
* @dev: device requesting the data * @dev: device requesting the data
...@@ -119,7 +124,8 @@ EXPORT_SYMBOL_GPL(of_get_regulator_init_data); ...@@ -119,7 +124,8 @@ EXPORT_SYMBOL_GPL(of_get_regulator_init_data);
* regulator. The data parsed from a child node will be matched to a regulator * regulator. The data parsed from a child node will be matched to a regulator
* based on either the deprecated property regulator-compatible if present, * based on either the deprecated property regulator-compatible if present,
* or otherwise the child node's name. Note that the match table is modified * or otherwise the child node's name. Note that the match table is modified
* in place. * in place and an additional of_node reference is taken for each matched
* regulator.
* *
* Returns the number of matches found or a negative error code on failure. * Returns the number of matches found or a negative error code on failure.
*/ */
...@@ -131,10 +137,22 @@ int of_regulator_match(struct device *dev, struct device_node *node, ...@@ -131,10 +137,22 @@ int of_regulator_match(struct device *dev, struct device_node *node,
unsigned int i; unsigned int i;
const char *name; const char *name;
struct device_node *child; struct device_node *child;
struct devm_of_regulator_matches *devm_matches;
if (!dev || !node) if (!dev || !node)
return -EINVAL; return -EINVAL;
devm_matches = devres_alloc(devm_of_regulator_put_matches,
sizeof(struct devm_of_regulator_matches),
GFP_KERNEL);
if (!devm_matches)
return -ENOMEM;
devm_matches->matches = matches;
devm_matches->num_matches = num_matches;
devres_add(dev, devm_matches);
for (i = 0; i < num_matches; i++) { for (i = 0; i < num_matches; i++) {
struct of_regulator_match *match = &matches[i]; struct of_regulator_match *match = &matches[i];
match->init_data = NULL; match->init_data = NULL;
...@@ -162,7 +180,7 @@ int of_regulator_match(struct device *dev, struct device_node *node, ...@@ -162,7 +180,7 @@ int of_regulator_match(struct device *dev, struct device_node *node,
child->name); child->name);
return -EINVAL; return -EINVAL;
} }
match->of_node = child; match->of_node = of_node_get(child);
count++; count++;
break; break;
} }
......
...@@ -36,6 +36,18 @@ struct regs_info { ...@@ -36,6 +36,18 @@ struct regs_info {
int sleep_id; int sleep_id;
}; };
static const struct regulator_linear_range smps_low_ranges[] = {
REGULATOR_LINEAR_RANGE(500000, 0x1, 0x6, 0),
REGULATOR_LINEAR_RANGE(510000, 0x7, 0x79, 10000),
REGULATOR_LINEAR_RANGE(1650000, 0x7A, 0x7f, 0),
};
static const struct regulator_linear_range smps_high_ranges[] = {
REGULATOR_LINEAR_RANGE(1000000, 0x1, 0x6, 0),
REGULATOR_LINEAR_RANGE(1020000, 0x7, 0x79, 20000),
REGULATOR_LINEAR_RANGE(3300000, 0x7A, 0x7f, 0),
};
static const struct regs_info palmas_regs_info[] = { static const struct regs_info palmas_regs_info[] = {
{ {
.name = "SMPS12", .name = "SMPS12",
...@@ -280,54 +292,6 @@ static int palmas_ldo_write(struct palmas *palmas, unsigned int reg, ...@@ -280,54 +292,6 @@ static int palmas_ldo_write(struct palmas *palmas, unsigned int reg,
return regmap_write(palmas->regmap[REGULATOR_SLAVE], addr, value); return regmap_write(palmas->regmap[REGULATOR_SLAVE], addr, value);
} }
static int palmas_is_enabled_smps(struct regulator_dev *dev)
{
struct palmas_pmic *pmic = rdev_get_drvdata(dev);
int id = rdev_get_id(dev);
unsigned int reg;
palmas_smps_read(pmic->palmas, palmas_regs_info[id].ctrl_addr, &reg);
reg &= PALMAS_SMPS12_CTRL_STATUS_MASK;
reg >>= PALMAS_SMPS12_CTRL_STATUS_SHIFT;
return !!(reg);
}
static int palmas_enable_smps(struct regulator_dev *dev)
{
struct palmas_pmic *pmic = rdev_get_drvdata(dev);
int id = rdev_get_id(dev);
unsigned int reg;
palmas_smps_read(pmic->palmas, palmas_regs_info[id].ctrl_addr, &reg);
reg &= ~PALMAS_SMPS12_CTRL_MODE_ACTIVE_MASK;
if (pmic->current_reg_mode[id])
reg |= pmic->current_reg_mode[id];
else
reg |= SMPS_CTRL_MODE_ON;
palmas_smps_write(pmic->palmas, palmas_regs_info[id].ctrl_addr, reg);
return 0;
}
static int palmas_disable_smps(struct regulator_dev *dev)
{
struct palmas_pmic *pmic = rdev_get_drvdata(dev);
int id = rdev_get_id(dev);
unsigned int reg;
palmas_smps_read(pmic->palmas, palmas_regs_info[id].ctrl_addr, &reg);
reg &= ~PALMAS_SMPS12_CTRL_MODE_ACTIVE_MASK;
palmas_smps_write(pmic->palmas, palmas_regs_info[id].ctrl_addr, reg);
return 0;
}
static int palmas_set_mode_smps(struct regulator_dev *dev, unsigned int mode) static int palmas_set_mode_smps(struct regulator_dev *dev, unsigned int mode)
{ {
struct palmas_pmic *pmic = rdev_get_drvdata(dev); struct palmas_pmic *pmic = rdev_get_drvdata(dev);
...@@ -382,81 +346,6 @@ static unsigned int palmas_get_mode_smps(struct regulator_dev *dev) ...@@ -382,81 +346,6 @@ static unsigned int palmas_get_mode_smps(struct regulator_dev *dev)
return 0; return 0;
} }
static int palmas_list_voltage_smps(struct regulator_dev *dev,
unsigned selector)
{
struct palmas_pmic *pmic = rdev_get_drvdata(dev);
int id = rdev_get_id(dev);
int mult = 1;
/* Read the multiplier set in VSEL register to return
* the correct voltage.
*/
if (pmic->range[id])
mult = 2;
if (selector == 0)
return 0;
else if (selector < 6)
return 500000 * mult;
else
/* Voltage is linear mapping starting from selector 6,
* volt = (0.49V + ((selector - 5) * 0.01V)) * RANGE
* RANGE is either x1 or x2
*/
return (490000 + ((selector - 5) * 10000)) * mult;
}
static int palmas_map_voltage_smps(struct regulator_dev *rdev,
int min_uV, int max_uV)
{
struct palmas_pmic *pmic = rdev_get_drvdata(rdev);
int id = rdev_get_id(rdev);
int ret, voltage;
if (min_uV == 0)
return 0;
if (pmic->range[id]) { /* RANGE is x2 */
if (min_uV < 1000000)
min_uV = 1000000;
ret = DIV_ROUND_UP(min_uV - 1000000, 20000) + 6;
} else { /* RANGE is x1 */
if (min_uV < 500000)
min_uV = 500000;
ret = DIV_ROUND_UP(min_uV - 500000, 10000) + 6;
}
/* Map back into a voltage to verify we're still in bounds */
voltage = palmas_list_voltage_smps(rdev, ret);
if (voltage < min_uV || voltage > max_uV)
return -EINVAL;
return ret;
}
static int palma_smps_set_voltage_smps_time_sel(struct regulator_dev *rdev,
unsigned int old_selector, unsigned int new_selector)
{
struct palmas_pmic *pmic = rdev_get_drvdata(rdev);
int id = rdev_get_id(rdev);
int old_uv, new_uv;
unsigned int ramp_delay = pmic->ramp_delay[id];
if (!ramp_delay)
return 0;
old_uv = palmas_list_voltage_smps(rdev, old_selector);
if (old_uv < 0)
return old_uv;
new_uv = palmas_list_voltage_smps(rdev, new_selector);
if (new_uv < 0)
return new_uv;
return DIV_ROUND_UP(abs(old_uv - new_uv), ramp_delay);
}
static int palmas_smps_set_ramp_delay(struct regulator_dev *rdev, static int palmas_smps_set_ramp_delay(struct regulator_dev *rdev,
int ramp_delay) int ramp_delay)
{ {
...@@ -493,16 +382,16 @@ static int palmas_smps_set_ramp_delay(struct regulator_dev *rdev, ...@@ -493,16 +382,16 @@ static int palmas_smps_set_ramp_delay(struct regulator_dev *rdev,
} }
static struct regulator_ops palmas_ops_smps = { static struct regulator_ops palmas_ops_smps = {
.is_enabled = palmas_is_enabled_smps, .is_enabled = regulator_is_enabled_regmap,
.enable = palmas_enable_smps, .enable = regulator_enable_regmap,
.disable = palmas_disable_smps, .disable = regulator_disable_regmap,
.set_mode = palmas_set_mode_smps, .set_mode = palmas_set_mode_smps,
.get_mode = palmas_get_mode_smps, .get_mode = palmas_get_mode_smps,
.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,
.list_voltage = palmas_list_voltage_smps, .list_voltage = regulator_list_voltage_linear_range,
.map_voltage = palmas_map_voltage_smps, .map_voltage = regulator_map_voltage_linear_range,
.set_voltage_time_sel = palma_smps_set_voltage_smps_time_sel, .set_voltage_time_sel = regulator_set_voltage_time_sel,
.set_ramp_delay = palmas_smps_set_ramp_delay, .set_ramp_delay = palmas_smps_set_ramp_delay,
}; };
...@@ -511,9 +400,9 @@ static struct regulator_ops palmas_ops_ext_control_smps = { ...@@ -511,9 +400,9 @@ static struct regulator_ops palmas_ops_ext_control_smps = {
.get_mode = palmas_get_mode_smps, .get_mode = palmas_get_mode_smps,
.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,
.list_voltage = palmas_list_voltage_smps, .list_voltage = regulator_list_voltage_linear_range,
.map_voltage = palmas_map_voltage_smps, .map_voltage = regulator_map_voltage_linear_range,
.set_voltage_time_sel = palma_smps_set_voltage_smps_time_sel, .set_voltage_time_sel = regulator_set_voltage_time_sel,
.set_ramp_delay = palmas_smps_set_ramp_delay, .set_ramp_delay = palmas_smps_set_ramp_delay,
}; };
...@@ -1042,12 +931,17 @@ static int palmas_regulators_probe(struct platform_device *pdev) ...@@ -1042,12 +931,17 @@ static int palmas_regulators_probe(struct platform_device *pdev)
* ranges. Read the current smps mode for later use. * ranges. Read the current smps mode for later use.
*/ */
addr = palmas_regs_info[id].vsel_addr; addr = palmas_regs_info[id].vsel_addr;
pmic->desc[id].n_linear_ranges = 3;
ret = palmas_smps_read(pmic->palmas, addr, &reg); ret = palmas_smps_read(pmic->palmas, addr, &reg);
if (ret) if (ret)
return ret; return ret;
if (reg & PALMAS_SMPS12_VOLTAGE_RANGE) if (reg & PALMAS_SMPS12_VOLTAGE_RANGE)
pmic->range[id] = 1; pmic->range[id] = 1;
if (pmic->range[id])
pmic->desc[id].linear_ranges = smps_high_ranges;
else
pmic->desc[id].linear_ranges = smps_low_ranges;
if (reg_init && reg_init->roof_floor) if (reg_init && reg_init->roof_floor)
pmic->desc[id].ops = pmic->desc[id].ops =
...@@ -1199,7 +1093,7 @@ static int palmas_regulators_probe(struct platform_device *pdev) ...@@ -1199,7 +1093,7 @@ static int palmas_regulators_probe(struct platform_device *pdev)
return 0; return 0;
} }
static struct of_device_id of_palmas_match_tbl[] = { static const struct of_device_id of_palmas_match_tbl[] = {
{ .compatible = "ti,palmas-pmic", }, { .compatible = "ti,palmas-pmic", },
{ .compatible = "ti,twl6035-pmic", }, { .compatible = "ti,twl6035-pmic", },
{ .compatible = "ti,twl6036-pmic", }, { .compatible = "ti,twl6036-pmic", },
......
...@@ -49,33 +49,13 @@ static const unsigned int pbias_volt_table[] = { ...@@ -49,33 +49,13 @@ static const unsigned int pbias_volt_table[] = {
3000000 3000000
}; };
static int pbias_regulator_enable(struct regulator_dev *rdev)
{
struct pbias_regulator_data *data = rdev_get_drvdata(rdev);
const struct pbias_reg_info *info = data->info;
return regmap_update_bits(data->syscon, rdev->desc->enable_reg,
info->enable_mask, info->enable);
}
static int pbias_regulator_is_enable(struct regulator_dev *rdev)
{
struct pbias_regulator_data *data = rdev_get_drvdata(rdev);
const struct pbias_reg_info *info = data->info;
int value;
regmap_read(data->syscon, rdev->desc->enable_reg, &value);
return (value & info->enable_mask) == info->enable;
}
static struct regulator_ops pbias_regulator_voltage_ops = { static struct regulator_ops pbias_regulator_voltage_ops = {
.list_voltage = regulator_list_voltage_table, .list_voltage = regulator_list_voltage_table,
.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,
.enable = pbias_regulator_enable, .enable = regulator_enable_regmap,
.disable = regulator_disable_regmap, .disable = regulator_disable_regmap,
.is_enabled = pbias_regulator_is_enable, .is_enabled = regulator_is_enabled_regmap,
}; };
static const struct pbias_reg_info pbias_mmc_omap2430 = { static const struct pbias_reg_info pbias_mmc_omap2430 = {
...@@ -142,10 +122,8 @@ static int pbias_regulator_probe(struct platform_device *pdev) ...@@ -142,10 +122,8 @@ static int pbias_regulator_probe(struct platform_device *pdev)
drvdata = devm_kzalloc(&pdev->dev, sizeof(struct pbias_regulator_data) drvdata = devm_kzalloc(&pdev->dev, sizeof(struct pbias_regulator_data)
* count, GFP_KERNEL); * count, GFP_KERNEL);
if (drvdata == NULL) { if (!drvdata)
dev_err(&pdev->dev, "Failed to allocate device data\n");
return -ENOMEM; return -ENOMEM;
}
syscon = syscon_regmap_lookup_by_phandle(np, "syscon"); syscon = syscon_regmap_lookup_by_phandle(np, "syscon");
if (IS_ERR(syscon)) if (IS_ERR(syscon))
...@@ -180,6 +158,7 @@ static int pbias_regulator_probe(struct platform_device *pdev) ...@@ -180,6 +158,7 @@ static int pbias_regulator_probe(struct platform_device *pdev)
drvdata[data_idx].desc.vsel_mask = info->vmode; drvdata[data_idx].desc.vsel_mask = info->vmode;
drvdata[data_idx].desc.enable_reg = res->start; drvdata[data_idx].desc.enable_reg = res->start;
drvdata[data_idx].desc.enable_mask = info->enable_mask; drvdata[data_idx].desc.enable_mask = info->enable_mask;
drvdata[data_idx].desc.enable_val = info->enable;
cfg.init_data = pbias_matches[idx].init_data; cfg.init_data = pbias_matches[idx].init_data;
cfg.driver_data = &drvdata[data_idx]; cfg.driver_data = &drvdata[data_idx];
......
...@@ -125,6 +125,9 @@ static struct regulator_ops pfuze100_ldo_regulator_ops = { ...@@ -125,6 +125,9 @@ static struct regulator_ops pfuze100_ldo_regulator_ops = {
}; };
static struct regulator_ops pfuze100_fixed_regulator_ops = { static struct regulator_ops pfuze100_fixed_regulator_ops = {
.enable = regulator_enable_regmap,
.disable = regulator_disable_regmap,
.is_enabled = regulator_is_enabled_regmap,
.list_voltage = regulator_list_voltage_linear, .list_voltage = regulator_list_voltage_linear,
}; };
...@@ -137,6 +140,8 @@ static struct regulator_ops pfuze100_sw_regulator_ops = { ...@@ -137,6 +140,8 @@ static struct regulator_ops pfuze100_sw_regulator_ops = {
}; };
static struct regulator_ops pfuze100_swb_regulator_ops = { static struct regulator_ops pfuze100_swb_regulator_ops = {
.enable = regulator_enable_regmap,
.disable = regulator_disable_regmap,
.list_voltage = regulator_list_voltage_table, .list_voltage = regulator_list_voltage_table,
.map_voltage = regulator_map_voltage_ascend, .map_voltage = regulator_map_voltage_ascend,
.set_voltage_sel = regulator_set_voltage_sel_regmap, .set_voltage_sel = regulator_set_voltage_sel_regmap,
...@@ -189,6 +194,8 @@ static struct regulator_ops pfuze100_swb_regulator_ops = { ...@@ -189,6 +194,8 @@ static struct regulator_ops pfuze100_swb_regulator_ops = {
.volt_table = voltages, \ .volt_table = voltages, \
.vsel_reg = (base), \ .vsel_reg = (base), \
.vsel_mask = (mask), \ .vsel_mask = (mask), \
.enable_reg = (base), \
.enable_mask = 0x48, \
}, \ }, \
} }
...@@ -502,6 +509,7 @@ static int pfuze100_regulator_probe(struct i2c_client *client, ...@@ -502,6 +509,7 @@ static int pfuze100_regulator_probe(struct i2c_client *client,
config.init_data = init_data; config.init_data = init_data;
config.driver_data = pfuze_chip; config.driver_data = pfuze_chip;
config.of_node = match_of_node(i); config.of_node = match_of_node(i);
config.ena_gpio = -EINVAL;
pfuze_chip->regulators[i] = pfuze_chip->regulators[i] =
devm_regulator_register(&client->dev, desc, &config); devm_regulator_register(&client->dev, desc, &config);
......
...@@ -61,7 +61,7 @@ static int s2mpa01_regulator_set_voltage_time_sel(struct regulator_dev *rdev, ...@@ -61,7 +61,7 @@ static int s2mpa01_regulator_set_voltage_time_sel(struct regulator_dev *rdev,
unsigned int ramp_delay = 0; unsigned int ramp_delay = 0;
int old_volt, new_volt; int old_volt, new_volt;
switch (rdev->desc->id) { switch (rdev_get_id(rdev)) {
case S2MPA01_BUCK2: case S2MPA01_BUCK2:
case S2MPA01_BUCK4: case S2MPA01_BUCK4:
ramp_delay = s2mpa01->ramp_delay24; ramp_delay = s2mpa01->ramp_delay24;
...@@ -102,7 +102,7 @@ static int s2mpa01_set_ramp_delay(struct regulator_dev *rdev, int ramp_delay) ...@@ -102,7 +102,7 @@ static int s2mpa01_set_ramp_delay(struct regulator_dev *rdev, int ramp_delay)
unsigned int ramp_enable = 1, enable_shift = 0; unsigned int ramp_enable = 1, enable_shift = 0;
int ret; int ret;
switch (rdev->desc->id) { switch (rdev_get_id(rdev)) {
case S2MPA01_BUCK1: case S2MPA01_BUCK1:
enable_shift = S2MPA01_BUCK1_RAMP_EN_SHIFT; enable_shift = S2MPA01_BUCK1_RAMP_EN_SHIFT;
if (!ramp_delay) { if (!ramp_delay) {
...@@ -116,7 +116,6 @@ static int s2mpa01_set_ramp_delay(struct regulator_dev *rdev, int ramp_delay) ...@@ -116,7 +116,6 @@ static int s2mpa01_set_ramp_delay(struct regulator_dev *rdev, int ramp_delay)
ramp_delay = s2mpa01->ramp_delay16; ramp_delay = s2mpa01->ramp_delay16;
ramp_shift = S2MPA01_BUCK16_RAMP_SHIFT; ramp_shift = S2MPA01_BUCK16_RAMP_SHIFT;
ramp_reg = S2MPA01_REG_RAMP1;
break; break;
case S2MPA01_BUCK2: case S2MPA01_BUCK2:
enable_shift = S2MPA01_BUCK2_RAMP_EN_SHIFT; enable_shift = S2MPA01_BUCK2_RAMP_EN_SHIFT;
...@@ -192,11 +191,15 @@ static int s2mpa01_set_ramp_delay(struct regulator_dev *rdev, int ramp_delay) ...@@ -192,11 +191,15 @@ static int s2mpa01_set_ramp_delay(struct regulator_dev *rdev, int ramp_delay)
if (!ramp_enable) if (!ramp_enable)
goto ramp_disable; goto ramp_disable;
ret = regmap_update_bits(rdev->regmap, S2MPA01_REG_RAMP1, /* Ramp delay can be enabled/disabled only for buck[1234] */
1 << enable_shift, 1 << enable_shift); if (rdev_get_id(rdev) >= S2MPA01_BUCK1 &&
if (ret) { rdev_get_id(rdev) <= S2MPA01_BUCK4) {
dev_err(&rdev->dev, "failed to enable ramp rate\n"); ret = regmap_update_bits(rdev->regmap, S2MPA01_REG_RAMP1,
return ret; 1 << enable_shift, 1 << enable_shift);
if (ret) {
dev_err(&rdev->dev, "failed to enable ramp rate\n");
return ret;
}
} }
ramp_val = get_ramp_delay(ramp_delay); ramp_val = get_ramp_delay(ramp_delay);
......
...@@ -27,6 +27,7 @@ ...@@ -27,6 +27,7 @@
#include <linux/regulator/driver.h> #include <linux/regulator/driver.h>
#include <linux/regulator/machine.h> #include <linux/regulator/machine.h>
#include <linux/regulator/of_regulator.h> #include <linux/regulator/of_regulator.h>
#include <linux/of_gpio.h>
#include <linux/mfd/samsung/core.h> #include <linux/mfd/samsung/core.h>
#include <linux/mfd/samsung/s2mps11.h> #include <linux/mfd/samsung/s2mps11.h>
#include <linux/mfd/samsung/s2mps14.h> #include <linux/mfd/samsung/s2mps14.h>
...@@ -44,6 +45,8 @@ struct s2mps11_info { ...@@ -44,6 +45,8 @@ struct s2mps11_info {
* was enabled. * was enabled.
*/ */
unsigned int s2mps14_suspend_state:30; unsigned int s2mps14_suspend_state:30;
/* Array of size rdev_num with GPIO-s for external sleep control */
int *ext_control_gpio;
}; };
static int get_ramp_delay(int ramp_delay) static int get_ramp_delay(int ramp_delay)
...@@ -202,11 +205,16 @@ static int s2mps11_set_ramp_delay(struct regulator_dev *rdev, int ramp_delay) ...@@ -202,11 +205,16 @@ static int s2mps11_set_ramp_delay(struct regulator_dev *rdev, int ramp_delay)
if (!ramp_enable) if (!ramp_enable)
goto ramp_disable; goto ramp_disable;
ret = regmap_update_bits(rdev->regmap, S2MPS11_REG_RAMP, /* Ramp delay can be enabled/disabled only for buck[2346] */
1 << enable_shift, 1 << enable_shift); if ((rdev_get_id(rdev) >= S2MPS11_BUCK2 &&
if (ret) { rdev_get_id(rdev) <= S2MPS11_BUCK4) ||
dev_err(&rdev->dev, "failed to enable ramp rate\n"); rdev_get_id(rdev) == S2MPS11_BUCK6) {
return ret; ret = regmap_update_bits(rdev->regmap, S2MPS11_REG_RAMP,
1 << enable_shift, 1 << enable_shift);
if (ret) {
dev_err(&rdev->dev, "failed to enable ramp rate\n");
return ret;
}
} }
ramp_val = get_ramp_delay(ramp_delay); ramp_val = get_ramp_delay(ramp_delay);
...@@ -409,6 +417,8 @@ static int s2mps14_regulator_enable(struct regulator_dev *rdev) ...@@ -409,6 +417,8 @@ static int s2mps14_regulator_enable(struct regulator_dev *rdev)
if (s2mps11->s2mps14_suspend_state & (1 << rdev_get_id(rdev))) if (s2mps11->s2mps14_suspend_state & (1 << rdev_get_id(rdev)))
val = S2MPS14_ENABLE_SUSPEND; val = S2MPS14_ENABLE_SUSPEND;
else if (gpio_is_valid(s2mps11->ext_control_gpio[rdev_get_id(rdev)]))
val = S2MPS14_ENABLE_EXT_CONTROL;
else else
val = rdev->desc->enable_mask; val = rdev->desc->enable_mask;
...@@ -565,12 +575,61 @@ static const struct regulator_desc s2mps14_regulators[] = { ...@@ -565,12 +575,61 @@ static const struct regulator_desc s2mps14_regulators[] = {
regulator_desc_s2mps14_buck1235(5), regulator_desc_s2mps14_buck1235(5),
}; };
static int s2mps14_pmic_enable_ext_control(struct s2mps11_info *s2mps11,
struct regulator_dev *rdev)
{
return regmap_update_bits(rdev->regmap, rdev->desc->enable_reg,
rdev->desc->enable_mask, S2MPS14_ENABLE_EXT_CONTROL);
}
static void s2mps14_pmic_dt_parse_ext_control_gpio(struct platform_device *pdev,
struct of_regulator_match *rdata, struct s2mps11_info *s2mps11)
{
int *gpio = s2mps11->ext_control_gpio;
unsigned int i;
unsigned int valid_regulators[3] = { S2MPS14_LDO10, S2MPS14_LDO11,
S2MPS14_LDO12 };
for (i = 0; i < ARRAY_SIZE(valid_regulators); i++) {
unsigned int reg = valid_regulators[i];
if (!rdata[reg].init_data || !rdata[reg].of_node)
continue;
gpio[reg] = of_get_named_gpio(rdata[reg].of_node,
"samsung,ext-control-gpios", 0);
if (gpio_is_valid(gpio[reg]))
dev_dbg(&pdev->dev, "Using GPIO %d for ext-control over %d/%s\n",
gpio[reg], reg, rdata[reg].name);
}
}
static int s2mps11_pmic_dt_parse(struct platform_device *pdev,
struct of_regulator_match *rdata, struct s2mps11_info *s2mps11,
enum sec_device_type dev_type)
{
struct device_node *reg_np;
reg_np = of_get_child_by_name(pdev->dev.parent->of_node, "regulators");
if (!reg_np) {
dev_err(&pdev->dev, "could not find regulators sub-node\n");
return -EINVAL;
}
of_regulator_match(&pdev->dev, reg_np, rdata, s2mps11->rdev_num);
if (dev_type == S2MPS14X)
s2mps14_pmic_dt_parse_ext_control_gpio(pdev, rdata, s2mps11);
of_node_put(reg_np);
return 0;
}
static int s2mps11_pmic_probe(struct platform_device *pdev) static int s2mps11_pmic_probe(struct platform_device *pdev)
{ {
struct sec_pmic_dev *iodev = dev_get_drvdata(pdev->dev.parent); struct sec_pmic_dev *iodev = dev_get_drvdata(pdev->dev.parent);
struct sec_platform_data *pdata = iodev->pdata; struct sec_platform_data *pdata = NULL;
struct of_regulator_match *rdata = NULL; struct of_regulator_match *rdata = NULL;
struct device_node *reg_np = NULL;
struct regulator_config config = { }; struct regulator_config config = { };
struct s2mps11_info *s2mps11; struct s2mps11_info *s2mps11;
int i, ret = 0; int i, ret = 0;
...@@ -597,8 +656,21 @@ static int s2mps11_pmic_probe(struct platform_device *pdev) ...@@ -597,8 +656,21 @@ static int s2mps11_pmic_probe(struct platform_device *pdev)
return -EINVAL; return -EINVAL;
}; };
s2mps11->ext_control_gpio = devm_kzalloc(&pdev->dev,
sizeof(*s2mps11->ext_control_gpio) * s2mps11->rdev_num,
GFP_KERNEL);
if (!s2mps11->ext_control_gpio)
return -ENOMEM;
/*
* 0 is a valid GPIO so initialize all GPIO-s to negative value
* to indicate that external control won't be used for this regulator.
*/
for (i = 0; i < s2mps11->rdev_num; i++)
s2mps11->ext_control_gpio[i] = -EINVAL;
if (!iodev->dev->of_node) { if (!iodev->dev->of_node) {
if (pdata) { if (iodev->pdata) {
pdata = iodev->pdata;
goto common_reg; goto common_reg;
} else { } else {
dev_err(pdev->dev.parent, dev_err(pdev->dev.parent,
...@@ -614,15 +686,9 @@ static int s2mps11_pmic_probe(struct platform_device *pdev) ...@@ -614,15 +686,9 @@ static int s2mps11_pmic_probe(struct platform_device *pdev)
for (i = 0; i < s2mps11->rdev_num; i++) for (i = 0; i < s2mps11->rdev_num; i++)
rdata[i].name = regulators[i].name; rdata[i].name = regulators[i].name;
reg_np = of_get_child_by_name(iodev->dev->of_node, "regulators"); ret = s2mps11_pmic_dt_parse(pdev, rdata, s2mps11, dev_type);
if (!reg_np) { if (ret)
dev_err(&pdev->dev, "could not find regulators sub-node\n");
ret = -EINVAL;
goto out; goto out;
}
of_regulator_match(&pdev->dev, reg_np, rdata, s2mps11->rdev_num);
of_node_put(reg_np);
common_reg: common_reg:
platform_set_drvdata(pdev, s2mps11); platform_set_drvdata(pdev, s2mps11);
...@@ -630,16 +696,18 @@ static int s2mps11_pmic_probe(struct platform_device *pdev) ...@@ -630,16 +696,18 @@ static int s2mps11_pmic_probe(struct platform_device *pdev)
config.dev = &pdev->dev; config.dev = &pdev->dev;
config.regmap = iodev->regmap_pmic; config.regmap = iodev->regmap_pmic;
config.driver_data = s2mps11; config.driver_data = s2mps11;
config.ena_gpio_flags = GPIOF_OUT_INIT_HIGH;
for (i = 0; i < s2mps11->rdev_num; i++) { for (i = 0; i < s2mps11->rdev_num; i++) {
struct regulator_dev *regulator; struct regulator_dev *regulator;
if (!reg_np) { if (pdata) {
config.init_data = pdata->regulators[i].initdata; config.init_data = pdata->regulators[i].initdata;
config.of_node = pdata->regulators[i].reg_node; config.of_node = pdata->regulators[i].reg_node;
} else { } else {
config.init_data = rdata[i].init_data; config.init_data = rdata[i].init_data;
config.of_node = rdata[i].of_node; config.of_node = rdata[i].of_node;
} }
config.ena_gpio = s2mps11->ext_control_gpio[i];
regulator = devm_regulator_register(&pdev->dev, regulator = devm_regulator_register(&pdev->dev,
&regulators[i], &config); &regulators[i], &config);
...@@ -649,6 +717,17 @@ static int s2mps11_pmic_probe(struct platform_device *pdev) ...@@ -649,6 +717,17 @@ static int s2mps11_pmic_probe(struct platform_device *pdev)
i); i);
goto out; goto out;
} }
if (gpio_is_valid(s2mps11->ext_control_gpio[i])) {
ret = s2mps14_pmic_enable_ext_control(s2mps11,
regulator);
if (ret < 0) {
dev_err(&pdev->dev,
"failed to enable GPIO control over %s: %d\n",
regulator->desc->name, ret);
goto out;
}
}
} }
out: out:
......
...@@ -28,7 +28,6 @@ struct s5m8767_info { ...@@ -28,7 +28,6 @@ struct s5m8767_info {
struct device *dev; struct device *dev;
struct sec_pmic_dev *iodev; struct sec_pmic_dev *iodev;
int num_regulators; int num_regulators;
struct regulator_dev **rdev;
struct sec_opmode_data *opmode; struct sec_opmode_data *opmode;
int ramp_delay; int ramp_delay;
...@@ -529,16 +528,6 @@ static int s5m8767_pmic_dt_parse_ds_gpio(struct sec_pmic_dev *iodev, ...@@ -529,16 +528,6 @@ 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)
{ {
...@@ -587,7 +576,8 @@ static int s5m8767_pmic_dt_parse_pdata(struct platform_device *pdev, ...@@ -587,7 +576,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->ext_control_gpio = of_get_named_gpio(reg_np,
"s5m8767,pmic-ext-control-gpios", 0);
rdata->id = i; rdata->id = i;
rdata->initdata = of_get_regulator_init_data( rdata->initdata = of_get_regulator_init_data(
...@@ -695,7 +685,6 @@ static int s5m8767_pmic_probe(struct platform_device *pdev) ...@@ -695,7 +685,6 @@ static int s5m8767_pmic_probe(struct platform_device *pdev)
struct sec_pmic_dev *iodev = dev_get_drvdata(pdev->dev.parent); struct sec_pmic_dev *iodev = dev_get_drvdata(pdev->dev.parent);
struct sec_platform_data *pdata = iodev->pdata; struct sec_platform_data *pdata = iodev->pdata;
struct regulator_config config = { }; struct regulator_config config = { };
struct regulator_dev **rdev;
struct s5m8767_info *s5m8767; struct s5m8767_info *s5m8767;
int i, ret, size, buck_init; int i, ret, size, buck_init;
...@@ -737,11 +726,7 @@ static int s5m8767_pmic_probe(struct platform_device *pdev) ...@@ -737,11 +726,7 @@ static int s5m8767_pmic_probe(struct platform_device *pdev)
return -ENOMEM; return -ENOMEM;
size = sizeof(struct regulator_dev *) * (S5M8767_REG_MAX - 2); size = sizeof(struct regulator_dev *) * (S5M8767_REG_MAX - 2);
s5m8767->rdev = devm_kzalloc(&pdev->dev, size, GFP_KERNEL);
if (!s5m8767->rdev)
return -ENOMEM;
rdev = s5m8767->rdev;
s5m8767->dev = &pdev->dev; s5m8767->dev = &pdev->dev;
s5m8767->iodev = iodev; s5m8767->iodev = iodev;
s5m8767->num_regulators = pdata->num_regulators; s5m8767->num_regulators = pdata->num_regulators;
...@@ -938,6 +923,7 @@ static int s5m8767_pmic_probe(struct platform_device *pdev) ...@@ -938,6 +923,7 @@ static int s5m8767_pmic_probe(struct platform_device *pdev)
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; int enable_reg, enable_val;
struct regulator_dev *rdev;
desc = reg_voltage_map[id]; desc = reg_voltage_map[id];
if (desc) { if (desc) {
...@@ -964,26 +950,27 @@ static int s5m8767_pmic_probe(struct platform_device *pdev) ...@@ -964,26 +950,27 @@ 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;
config.ena_gpio = config.ena_gpio_flags = 0; config.ena_gpio = -EINVAL;
if (pdata->regulators[i].ext_control_gpio) config.ena_gpio_flags = 0;
if (gpio_is_valid(pdata->regulators[i].ext_control_gpio))
s5m8767_regulator_config_ext_control(s5m8767, s5m8767_regulator_config_ext_control(s5m8767,
&pdata->regulators[i], &config); &pdata->regulators[i], &config);
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)) {
ret = PTR_ERR(rdev[i]); ret = PTR_ERR(rdev);
dev_err(s5m8767->dev, "regulator init failed for %d\n", dev_err(s5m8767->dev, "regulator init failed for %d\n",
id); id);
return ret; return ret;
} }
if (pdata->regulators[i].ext_control_gpio) { if (gpio_is_valid(pdata->regulators[i].ext_control_gpio)) {
ret = s5m8767_enable_ext_control(s5m8767, rdev[i]); ret = s5m8767_enable_ext_control(s5m8767, rdev);
if (ret < 0) { if (ret < 0) {
dev_err(s5m8767->dev, dev_err(s5m8767->dev,
"failed to enable gpio control over %s: %d\n", "failed to enable gpio control over %s: %d\n",
rdev[i]->desc->name, ret); rdev->desc->name, ret);
return ret; return ret;
} }
} }
......
...@@ -118,7 +118,7 @@ static const struct st_pwm_regulator_pdata b2105_info = { ...@@ -118,7 +118,7 @@ static const struct st_pwm_regulator_pdata b2105_info = {
.duty_cycle_table = b2105_duty_cycle_table, .duty_cycle_table = b2105_duty_cycle_table,
}; };
static struct of_device_id st_pwm_of_match[] = { static const struct of_device_id st_pwm_of_match[] = {
{ .compatible = "st,b2105-pwm-regulator", .data = &b2105_info, }, { .compatible = "st,b2105-pwm-regulator", .data = &b2105_info, },
{ }, { },
}; };
......
...@@ -17,6 +17,7 @@ ...@@ -17,6 +17,7 @@
*/ */
#include <linux/module.h> #include <linux/module.h>
#include <linux/delay.h>
#include <linux/init.h> #include <linux/init.h>
#include <linux/gpio.h> #include <linux/gpio.h>
#include <linux/of_gpio.h> #include <linux/of_gpio.h>
...@@ -28,49 +29,216 @@ ...@@ -28,49 +29,216 @@
#include <linux/regulator/of_regulator.h> #include <linux/regulator/of_regulator.h>
#include <linux/mfd/tps65090.h> #include <linux/mfd/tps65090.h>
#define MAX_CTRL_READ_TRIES 5
#define MAX_FET_ENABLE_TRIES 1000
#define CTRL_EN_BIT 0 /* Regulator enable bit, active high */
#define CTRL_WT_BIT 2 /* Regulator wait time 0 bit */
#define CTRL_PG_BIT 4 /* Regulator power good bit, 1=good */
#define CTRL_TO_BIT 7 /* Regulator timeout bit, 1=wait */
#define MAX_OVERCURRENT_WAIT 3 /* Overcurrent wait must be <= this */
/**
* struct tps65090_regulator - Per-regulator data for a tps65090 regulator
*
* @dev: Pointer to our device.
* @desc: The struct regulator_desc for the regulator.
* @rdev: The struct regulator_dev for the regulator.
* @overcurrent_wait_valid: True if overcurrent_wait is valid.
* @overcurrent_wait: For FETs, the value to put in the WTFET bitfield.
*/
struct tps65090_regulator { struct tps65090_regulator {
struct device *dev; struct device *dev;
struct regulator_desc *desc; struct regulator_desc *desc;
struct regulator_dev *rdev; struct regulator_dev *rdev;
bool overcurrent_wait_valid;
int overcurrent_wait;
}; };
static struct regulator_ops tps65090_ext_control_ops = { static struct regulator_ops tps65090_ext_control_ops = {
}; };
static struct regulator_ops tps65090_reg_contol_ops = { /**
* tps65090_reg_set_overcurrent_wait - Setup overcurrent wait
*
* This will set the overcurrent wait time based on what's in the regulator
* info.
*
* @ri: Overall regulator data
* @rdev: Regulator device
*
* Return: 0 if no error, non-zero if there was an error writing the register.
*/
static int tps65090_reg_set_overcurrent_wait(struct tps65090_regulator *ri,
struct regulator_dev *rdev)
{
int ret;
ret = regmap_update_bits(rdev->regmap, rdev->desc->enable_reg,
MAX_OVERCURRENT_WAIT << CTRL_WT_BIT,
ri->overcurrent_wait << CTRL_WT_BIT);
if (ret) {
dev_err(&rdev->dev, "Error updating overcurrent wait %#x\n",
rdev->desc->enable_reg);
}
return ret;
}
/**
* tps65090_try_enable_fet - Try to enable a FET
*
* @rdev: Regulator device
*
* Return: 0 if ok, -ENOTRECOVERABLE if the FET power good bit did not get
* set, or some other -ve value if another error occurred (e.g. i2c error)
*/
static int tps65090_try_enable_fet(struct regulator_dev *rdev)
{
unsigned int control;
int ret, i;
ret = regmap_update_bits(rdev->regmap, rdev->desc->enable_reg,
rdev->desc->enable_mask,
rdev->desc->enable_mask);
if (ret < 0) {
dev_err(&rdev->dev, "Error in updating reg %#x\n",
rdev->desc->enable_reg);
return ret;
}
for (i = 0; i < MAX_CTRL_READ_TRIES; i++) {
ret = regmap_read(rdev->regmap, rdev->desc->enable_reg,
&control);
if (ret < 0)
return ret;
if (!(control & BIT(CTRL_TO_BIT)))
break;
usleep_range(1000, 1500);
}
if (!(control & BIT(CTRL_PG_BIT)))
return -ENOTRECOVERABLE;
return 0;
}
/**
* tps65090_fet_enable - Enable a FET, trying a few times if it fails
*
* Some versions of the tps65090 have issues when turning on the FETs.
* This function goes through several steps to ensure the best chance of the
* FET going on. Specifically:
* - We'll make sure that we bump the "overcurrent wait" to the maximum, which
* increases the chances that we'll turn on properly.
* - We'll retry turning the FET on multiple times (turning off in between).
*
* @rdev: Regulator device
*
* Return: 0 if ok, non-zero if it fails.
*/
static int tps65090_fet_enable(struct regulator_dev *rdev)
{
int ret, tries;
/*
* Try enabling multiple times until we succeed since sometimes the
* first try times out.
*/
tries = 0;
while (true) {
ret = tps65090_try_enable_fet(rdev);
if (!ret)
break;
if (ret != -ENOTRECOVERABLE || tries == MAX_FET_ENABLE_TRIES)
goto err;
/* Try turning the FET off (and then on again) */
ret = regmap_update_bits(rdev->regmap, rdev->desc->enable_reg,
rdev->desc->enable_mask, 0);
if (ret)
goto err;
tries++;
}
if (tries)
dev_warn(&rdev->dev, "reg %#x enable ok after %d tries\n",
rdev->desc->enable_reg, tries);
return 0;
err:
dev_warn(&rdev->dev, "reg %#x enable failed\n", rdev->desc->enable_reg);
WARN_ON(1);
return ret;
}
static struct regulator_ops tps65090_reg_control_ops = {
.enable = regulator_enable_regmap, .enable = regulator_enable_regmap,
.disable = regulator_disable_regmap, .disable = regulator_disable_regmap,
.is_enabled = regulator_is_enabled_regmap, .is_enabled = regulator_is_enabled_regmap,
}; };
static struct regulator_ops tps65090_fet_control_ops = {
.enable = tps65090_fet_enable,
.disable = regulator_disable_regmap,
.is_enabled = regulator_is_enabled_regmap,
};
static struct regulator_ops tps65090_ldo_ops = { static struct regulator_ops tps65090_ldo_ops = {
}; };
#define tps65090_REG_DESC(_id, _sname, _en_reg, _ops) \ #define tps65090_REG_DESC(_id, _sname, _en_reg, _en_bits, _ops) \
{ \ { \
.name = "TPS65090_RAILS"#_id, \ .name = "TPS65090_RAILS"#_id, \
.supply_name = _sname, \ .supply_name = _sname, \
.id = TPS65090_REGULATOR_##_id, \ .id = TPS65090_REGULATOR_##_id, \
.ops = &_ops, \ .ops = &_ops, \
.enable_reg = _en_reg, \ .enable_reg = _en_reg, \
.enable_mask = BIT(0), \ .enable_val = _en_bits, \
.enable_mask = _en_bits, \
.type = REGULATOR_VOLTAGE, \ .type = REGULATOR_VOLTAGE, \
.owner = THIS_MODULE, \ .owner = THIS_MODULE, \
} }
static struct regulator_desc tps65090_regulator_desc[] = { static struct regulator_desc tps65090_regulator_desc[] = {
tps65090_REG_DESC(DCDC1, "vsys1", 0x0C, tps65090_reg_contol_ops), tps65090_REG_DESC(DCDC1, "vsys1", 0x0C, BIT(CTRL_EN_BIT),
tps65090_REG_DESC(DCDC2, "vsys2", 0x0D, tps65090_reg_contol_ops), tps65090_reg_control_ops),
tps65090_REG_DESC(DCDC3, "vsys3", 0x0E, tps65090_reg_contol_ops), tps65090_REG_DESC(DCDC2, "vsys2", 0x0D, BIT(CTRL_EN_BIT),
tps65090_REG_DESC(FET1, "infet1", 0x0F, tps65090_reg_contol_ops), tps65090_reg_control_ops),
tps65090_REG_DESC(FET2, "infet2", 0x10, tps65090_reg_contol_ops), tps65090_REG_DESC(DCDC3, "vsys3", 0x0E, BIT(CTRL_EN_BIT),
tps65090_REG_DESC(FET3, "infet3", 0x11, tps65090_reg_contol_ops), tps65090_reg_control_ops),
tps65090_REG_DESC(FET4, "infet4", 0x12, tps65090_reg_contol_ops),
tps65090_REG_DESC(FET5, "infet5", 0x13, tps65090_reg_contol_ops), tps65090_REG_DESC(FET1, "infet1", 0x0F,
tps65090_REG_DESC(FET6, "infet6", 0x14, tps65090_reg_contol_ops), BIT(CTRL_EN_BIT) | BIT(CTRL_PG_BIT),
tps65090_REG_DESC(FET7, "infet7", 0x15, tps65090_reg_contol_ops), tps65090_fet_control_ops),
tps65090_REG_DESC(LDO1, "vsys-l1", 0, tps65090_ldo_ops), tps65090_REG_DESC(FET2, "infet2", 0x10,
tps65090_REG_DESC(LDO2, "vsys-l2", 0, tps65090_ldo_ops), BIT(CTRL_EN_BIT) | BIT(CTRL_PG_BIT),
tps65090_fet_control_ops),
tps65090_REG_DESC(FET3, "infet3", 0x11,
BIT(CTRL_EN_BIT) | BIT(CTRL_PG_BIT),
tps65090_fet_control_ops),
tps65090_REG_DESC(FET4, "infet4", 0x12,
BIT(CTRL_EN_BIT) | BIT(CTRL_PG_BIT),
tps65090_fet_control_ops),
tps65090_REG_DESC(FET5, "infet5", 0x13,
BIT(CTRL_EN_BIT) | BIT(CTRL_PG_BIT),
tps65090_fet_control_ops),
tps65090_REG_DESC(FET6, "infet6", 0x14,
BIT(CTRL_EN_BIT) | BIT(CTRL_PG_BIT),
tps65090_fet_control_ops),
tps65090_REG_DESC(FET7, "infet7", 0x15,
BIT(CTRL_EN_BIT) | BIT(CTRL_PG_BIT),
tps65090_fet_control_ops),
tps65090_REG_DESC(LDO1, "vsys-l1", 0, 0,
tps65090_ldo_ops),
tps65090_REG_DESC(LDO2, "vsys-l2", 0, 0,
tps65090_ldo_ops),
}; };
static inline bool is_dcdc(int id) static inline bool is_dcdc(int id)
...@@ -209,6 +377,11 @@ static struct tps65090_platform_data *tps65090_parse_dt_reg_data( ...@@ -209,6 +377,11 @@ static struct tps65090_platform_data *tps65090_parse_dt_reg_data(
rpdata->gpio = of_get_named_gpio(np, rpdata->gpio = of_get_named_gpio(np,
"dcdc-ext-control-gpios", 0); "dcdc-ext-control-gpios", 0);
if (of_property_read_u32(tps65090_matches[idx].of_node,
"ti,overcurrent-wait",
&rpdata->overcurrent_wait) == 0)
rpdata->overcurrent_wait_valid = true;
tps65090_pdata->reg_pdata[idx] = rpdata; tps65090_pdata->reg_pdata[idx] = rpdata;
} }
return tps65090_pdata; return tps65090_pdata;
...@@ -258,6 +431,11 @@ static int tps65090_regulator_probe(struct platform_device *pdev) ...@@ -258,6 +431,11 @@ static int tps65090_regulator_probe(struct platform_device *pdev)
ri = &pmic[num]; ri = &pmic[num];
ri->dev = &pdev->dev; ri->dev = &pdev->dev;
ri->desc = &tps65090_regulator_desc[num]; ri->desc = &tps65090_regulator_desc[num];
if (tps_pdata) {
ri->overcurrent_wait_valid =
tps_pdata->overcurrent_wait_valid;
ri->overcurrent_wait = tps_pdata->overcurrent_wait;
}
/* /*
* TPS5090 DCDC support the control from external digital input. * TPS5090 DCDC support the control from external digital input.
...@@ -299,6 +477,12 @@ static int tps65090_regulator_probe(struct platform_device *pdev) ...@@ -299,6 +477,12 @@ static int tps65090_regulator_probe(struct platform_device *pdev)
} }
ri->rdev = rdev; ri->rdev = rdev;
if (ri->overcurrent_wait_valid) {
ret = tps65090_reg_set_overcurrent_wait(ri, rdev);
if (ret < 0)
return ret;
}
/* Enable external control if it is require */ /* Enable external control if it is require */
if (tps_pdata && is_dcdc(num) && tps_pdata->reg_init_data && if (tps_pdata && is_dcdc(num) && tps_pdata->reg_init_data &&
tps_pdata->enable_ext_control) { tps_pdata->enable_ext_control) {
......
...@@ -134,6 +134,7 @@ static struct regulator_ops tps65217_pmic_ldo1_ops = { ...@@ -134,6 +134,7 @@ static struct regulator_ops tps65217_pmic_ldo1_ops = {
.get_voltage_sel = regulator_get_voltage_sel_regmap, .get_voltage_sel = regulator_get_voltage_sel_regmap,
.set_voltage_sel = tps65217_pmic_set_voltage_sel, .set_voltage_sel = tps65217_pmic_set_voltage_sel,
.list_voltage = regulator_list_voltage_table, .list_voltage = regulator_list_voltage_table,
.map_voltage = regulator_map_voltage_ascend,
}; };
static const struct regulator_desc regulators[] = { static const struct regulator_desc regulators[] = {
...@@ -257,9 +258,6 @@ static int tps65217_regulator_probe(struct platform_device *pdev) ...@@ -257,9 +258,6 @@ static int tps65217_regulator_probe(struct platform_device *pdev)
pdev->name); pdev->name);
return PTR_ERR(rdev); return PTR_ERR(rdev);
} }
/* Save regulator for cleanup */
tps->rdev[i] = rdev;
} }
return 0; return 0;
} }
......
...@@ -27,12 +27,10 @@ ...@@ -27,12 +27,10 @@
#include <linux/regulator/machine.h> #include <linux/regulator/machine.h>
#include <linux/mfd/tps65218.h> #include <linux/mfd/tps65218.h>
static unsigned int tps65218_ramp_delay = 4000;
enum tps65218_regulators { DCDC1, DCDC2, DCDC3, DCDC4, DCDC5, DCDC6, LDO1 }; enum tps65218_regulators { DCDC1, DCDC2, DCDC3, DCDC4, DCDC5, DCDC6, LDO1 };
#define TPS65218_REGULATOR(_name, _id, _ops, _n, _vr, _vm, _er, _em, _t, \ #define TPS65218_REGULATOR(_name, _id, _ops, _n, _vr, _vm, _er, _em, _t, \
_lr, _nlr) \ _lr, _nlr, _delay) \
{ \ { \
.name = _name, \ .name = _name, \
.id = _id, \ .id = _id, \
...@@ -47,6 +45,7 @@ enum tps65218_regulators { DCDC1, DCDC2, DCDC3, DCDC4, DCDC5, DCDC6, LDO1 }; ...@@ -47,6 +45,7 @@ enum tps65218_regulators { DCDC1, DCDC2, DCDC3, DCDC4, DCDC5, DCDC6, LDO1 };
.volt_table = _t, \ .volt_table = _t, \
.linear_ranges = _lr, \ .linear_ranges = _lr, \
.n_linear_ranges = _nlr, \ .n_linear_ranges = _nlr, \
.ramp_delay = _delay, \
} \ } \
#define TPS65218_INFO(_id, _nm, _min, _max) \ #define TPS65218_INFO(_id, _nm, _min, _max) \
...@@ -152,22 +151,6 @@ static int tps65218_pmic_disable(struct regulator_dev *dev) ...@@ -152,22 +151,6 @@ static int tps65218_pmic_disable(struct regulator_dev *dev)
dev->desc->enable_mask, TPS65218_PROTECT_L1); dev->desc->enable_mask, TPS65218_PROTECT_L1);
} }
static int tps65218_set_voltage_time_sel(struct regulator_dev *rdev,
unsigned int old_selector, unsigned int new_selector)
{
int old_uv, new_uv;
old_uv = regulator_list_voltage_linear_range(rdev, old_selector);
if (old_uv < 0)
return old_uv;
new_uv = regulator_list_voltage_linear_range(rdev, new_selector);
if (new_uv < 0)
return new_uv;
return DIV_ROUND_UP(abs(old_uv - new_uv), tps65218_ramp_delay);
}
/* Operations permitted on DCDC1, DCDC2 */ /* Operations permitted on DCDC1, DCDC2 */
static struct regulator_ops tps65218_dcdc12_ops = { static struct regulator_ops tps65218_dcdc12_ops = {
.is_enabled = regulator_is_enabled_regmap, .is_enabled = regulator_is_enabled_regmap,
...@@ -177,7 +160,7 @@ static struct regulator_ops tps65218_dcdc12_ops = { ...@@ -177,7 +160,7 @@ static struct regulator_ops tps65218_dcdc12_ops = {
.set_voltage_sel = tps65218_pmic_set_voltage_sel, .set_voltage_sel = tps65218_pmic_set_voltage_sel,
.list_voltage = regulator_list_voltage_linear_range, .list_voltage = regulator_list_voltage_linear_range,
.map_voltage = regulator_map_voltage_linear_range, .map_voltage = regulator_map_voltage_linear_range,
.set_voltage_time_sel = tps65218_set_voltage_time_sel, .set_voltage_time_sel = regulator_set_voltage_time_sel,
}; };
/* Operations permitted on DCDC3, DCDC4 and LDO1 */ /* Operations permitted on DCDC3, DCDC4 and LDO1 */
...@@ -203,33 +186,33 @@ static const struct regulator_desc regulators[] = { ...@@ -203,33 +186,33 @@ static const struct regulator_desc regulators[] = {
TPS65218_REG_CONTROL_DCDC1, TPS65218_REG_CONTROL_DCDC1,
TPS65218_CONTROL_DCDC1_MASK, TPS65218_CONTROL_DCDC1_MASK,
TPS65218_REG_ENABLE1, TPS65218_ENABLE1_DC1_EN, NULL, TPS65218_REG_ENABLE1, TPS65218_ENABLE1_DC1_EN, NULL,
dcdc1_dcdc2_ranges, 2), dcdc1_dcdc2_ranges, 2, 4000),
TPS65218_REGULATOR("DCDC2", TPS65218_DCDC_2, tps65218_dcdc12_ops, 64, TPS65218_REGULATOR("DCDC2", TPS65218_DCDC_2, tps65218_dcdc12_ops, 64,
TPS65218_REG_CONTROL_DCDC2, TPS65218_REG_CONTROL_DCDC2,
TPS65218_CONTROL_DCDC2_MASK, TPS65218_CONTROL_DCDC2_MASK,
TPS65218_REG_ENABLE1, TPS65218_ENABLE1_DC2_EN, NULL, TPS65218_REG_ENABLE1, TPS65218_ENABLE1_DC2_EN, NULL,
dcdc1_dcdc2_ranges, 2), dcdc1_dcdc2_ranges, 2, 4000),
TPS65218_REGULATOR("DCDC3", TPS65218_DCDC_3, tps65218_ldo1_dcdc34_ops, TPS65218_REGULATOR("DCDC3", TPS65218_DCDC_3, tps65218_ldo1_dcdc34_ops,
64, TPS65218_REG_CONTROL_DCDC3, 64, TPS65218_REG_CONTROL_DCDC3,
TPS65218_CONTROL_DCDC3_MASK, TPS65218_REG_ENABLE1, TPS65218_CONTROL_DCDC3_MASK, TPS65218_REG_ENABLE1,
TPS65218_ENABLE1_DC3_EN, NULL, TPS65218_ENABLE1_DC3_EN, NULL,
ldo1_dcdc3_ranges, 2), ldo1_dcdc3_ranges, 2, 0),
TPS65218_REGULATOR("DCDC4", TPS65218_DCDC_4, tps65218_ldo1_dcdc34_ops, TPS65218_REGULATOR("DCDC4", TPS65218_DCDC_4, tps65218_ldo1_dcdc34_ops,
53, TPS65218_REG_CONTROL_DCDC4, 53, TPS65218_REG_CONTROL_DCDC4,
TPS65218_CONTROL_DCDC4_MASK, TPS65218_CONTROL_DCDC4_MASK,
TPS65218_REG_ENABLE1, TPS65218_ENABLE1_DC4_EN, NULL, TPS65218_REG_ENABLE1, TPS65218_ENABLE1_DC4_EN, NULL,
dcdc4_ranges, 2), dcdc4_ranges, 2, 0),
TPS65218_REGULATOR("DCDC5", TPS65218_DCDC_5, tps65218_dcdc56_pmic_ops, TPS65218_REGULATOR("DCDC5", TPS65218_DCDC_5, tps65218_dcdc56_pmic_ops,
1, -1, -1, TPS65218_REG_ENABLE1, 1, -1, -1, TPS65218_REG_ENABLE1,
TPS65218_ENABLE1_DC5_EN, NULL, NULL, 0), TPS65218_ENABLE1_DC5_EN, NULL, NULL, 0, 0),
TPS65218_REGULATOR("DCDC6", TPS65218_DCDC_6, tps65218_dcdc56_pmic_ops, TPS65218_REGULATOR("DCDC6", TPS65218_DCDC_6, tps65218_dcdc56_pmic_ops,
1, -1, -1, TPS65218_REG_ENABLE1, 1, -1, -1, TPS65218_REG_ENABLE1,
TPS65218_ENABLE1_DC6_EN, NULL, NULL, 0), TPS65218_ENABLE1_DC6_EN, NULL, NULL, 0, 0),
TPS65218_REGULATOR("LDO1", TPS65218_LDO_1, tps65218_ldo1_dcdc34_ops, 64, TPS65218_REGULATOR("LDO1", TPS65218_LDO_1, tps65218_ldo1_dcdc34_ops, 64,
TPS65218_REG_CONTROL_DCDC4, TPS65218_REG_CONTROL_DCDC4,
TPS65218_CONTROL_LDO1_MASK, TPS65218_REG_ENABLE2, TPS65218_CONTROL_LDO1_MASK, TPS65218_REG_ENABLE2,
TPS65218_ENABLE2_LDO1_EN, NULL, ldo1_dcdc3_ranges, TPS65218_ENABLE2_LDO1_EN, NULL, ldo1_dcdc3_ranges,
2), 2, 0),
}; };
static int tps65218_regulator_probe(struct platform_device *pdev) static int tps65218_regulator_probe(struct platform_device *pdev)
......
...@@ -63,12 +63,7 @@ struct tps6586x_regulator { ...@@ -63,12 +63,7 @@ struct tps6586x_regulator {
int enable_reg[2]; int enable_reg[2];
}; };
static inline struct device *to_tps6586x_dev(struct regulator_dev *rdev) static struct regulator_ops tps6586x_rw_regulator_ops = {
{
return rdev_get_dev(rdev)->parent;
}
static struct regulator_ops tps6586x_regulator_ops = {
.list_voltage = regulator_list_voltage_table, .list_voltage = regulator_list_voltage_table,
.map_voltage = regulator_map_voltage_ascend, .map_voltage = regulator_map_voltage_ascend,
.get_voltage_sel = regulator_get_voltage_sel_regmap, .get_voltage_sel = regulator_get_voltage_sel_regmap,
...@@ -79,6 +74,16 @@ static struct regulator_ops tps6586x_regulator_ops = { ...@@ -79,6 +74,16 @@ static struct regulator_ops tps6586x_regulator_ops = {
.disable = regulator_disable_regmap, .disable = regulator_disable_regmap,
}; };
static struct regulator_ops tps6586x_ro_regulator_ops = {
.list_voltage = regulator_list_voltage_table,
.map_voltage = regulator_map_voltage_ascend,
.get_voltage_sel = regulator_get_voltage_sel_regmap,
.is_enabled = regulator_is_enabled_regmap,
.enable = regulator_enable_regmap,
.disable = regulator_disable_regmap,
};
static struct regulator_ops tps6586x_sys_regulator_ops = { static struct regulator_ops tps6586x_sys_regulator_ops = {
}; };
...@@ -106,6 +111,13 @@ static const unsigned int tps6586x_sm2_voltages[] = { ...@@ -106,6 +111,13 @@ static const unsigned int tps6586x_sm2_voltages[] = {
4200000, 4250000, 4300000, 4350000, 4400000, 4450000, 4500000, 4550000, 4200000, 4250000, 4300000, 4350000, 4400000, 4450000, 4500000, 4550000,
}; };
static int tps658640_sm2_voltages[] = {
2150000, 2200000, 2250000, 2300000, 2350000, 2400000, 2450000, 2500000,
2550000, 2600000, 2650000, 2700000, 2750000, 2800000, 2850000, 2900000,
2950000, 3000000, 3050000, 3100000, 3150000, 3200000, 3250000, 3300000,
3350000, 3400000, 3450000, 3500000, 3550000, 3600000, 3650000, 3700000,
};
static const unsigned int tps658643_sm2_voltages[] = { static const unsigned int tps658643_sm2_voltages[] = {
1025000, 1050000, 1075000, 1100000, 1125000, 1150000, 1175000, 1200000, 1025000, 1050000, 1075000, 1100000, 1125000, 1150000, 1175000, 1200000,
1225000, 1250000, 1275000, 1300000, 1325000, 1350000, 1375000, 1400000, 1225000, 1250000, 1275000, 1300000, 1325000, 1350000, 1375000, 1400000,
...@@ -120,12 +132,16 @@ static const unsigned int tps6586x_dvm_voltages[] = { ...@@ -120,12 +132,16 @@ static const unsigned int tps6586x_dvm_voltages[] = {
1325000, 1350000, 1375000, 1400000, 1425000, 1450000, 1475000, 1500000, 1325000, 1350000, 1375000, 1400000, 1425000, 1450000, 1475000, 1500000,
}; };
#define TPS6586X_REGULATOR(_id, _pin_name, vdata, vreg, shift, nbits, \ static int tps658640_rtc_voltages[] = {
2500000, 2850000, 3100000, 3300000,
};
#define TPS6586X_REGULATOR(_id, _ops, _pin_name, vdata, vreg, shift, nbits, \
ereg0, ebit0, ereg1, ebit1, goreg, gobit) \ ereg0, ebit0, ereg1, ebit1, goreg, gobit) \
.desc = { \ .desc = { \
.supply_name = _pin_name, \ .supply_name = _pin_name, \
.name = "REG-" #_id, \ .name = "REG-" #_id, \
.ops = &tps6586x_regulator_ops, \ .ops = &tps6586x_## _ops ## _regulator_ops, \
.type = REGULATOR_VOLTAGE, \ .type = REGULATOR_VOLTAGE, \
.id = TPS6586X_ID_##_id, \ .id = TPS6586X_ID_##_id, \
.n_voltages = ARRAY_SIZE(vdata##_voltages), \ .n_voltages = ARRAY_SIZE(vdata##_voltages), \
...@@ -146,14 +162,21 @@ static const unsigned int tps6586x_dvm_voltages[] = { ...@@ -146,14 +162,21 @@ static const unsigned int tps6586x_dvm_voltages[] = {
#define TPS6586X_LDO(_id, _pname, vdata, vreg, shift, nbits, \ #define TPS6586X_LDO(_id, _pname, vdata, vreg, shift, nbits, \
ereg0, ebit0, ereg1, ebit1) \ ereg0, ebit0, ereg1, ebit1) \
{ \ { \
TPS6586X_REGULATOR(_id, _pname, vdata, vreg, shift, nbits, \ TPS6586X_REGULATOR(_id, rw, _pname, vdata, vreg, shift, nbits, \
ereg0, ebit0, ereg1, ebit1, 0, 0) \
}
#define TPS6586X_FIXED_LDO(_id, _pname, vdata, vreg, shift, nbits, \
ereg0, ebit0, ereg1, ebit1) \
{ \
TPS6586X_REGULATOR(_id, ro, _pname, vdata, vreg, shift, nbits, \
ereg0, ebit0, ereg1, ebit1, 0, 0) \ ereg0, ebit0, ereg1, ebit1, 0, 0) \
} }
#define TPS6586X_DVM(_id, _pname, vdata, vreg, shift, nbits, \ #define TPS6586X_DVM(_id, _pname, vdata, vreg, shift, nbits, \
ereg0, ebit0, ereg1, ebit1, goreg, gobit) \ ereg0, ebit0, ereg1, ebit1, goreg, gobit) \
{ \ { \
TPS6586X_REGULATOR(_id, _pname, vdata, vreg, shift, nbits, \ TPS6586X_REGULATOR(_id, rw, _pname, vdata, vreg, shift, nbits, \
ereg0, ebit0, ereg1, ebit1, goreg, gobit) \ ereg0, ebit0, ereg1, ebit1, goreg, gobit) \
} }
...@@ -207,6 +230,26 @@ static struct tps6586x_regulator tps658623_regulator[] = { ...@@ -207,6 +230,26 @@ static struct tps6586x_regulator tps658623_regulator[] = {
END, 7), END, 7),
}; };
static struct tps6586x_regulator tps658640_regulator[] = {
TPS6586X_LDO(LDO_3, "vinldo23", tps6586x_ldo0, SUPPLYV4, 0, 3,
ENC, 2, END, 2),
TPS6586X_LDO(LDO_5, "REG-SYS", tps6586x_ldo0, SUPPLYV6, 0, 3,
ENE, 6, ENE, 6),
TPS6586X_LDO(LDO_6, "vinldo678", tps6586x_ldo0, SUPPLYV3, 0, 3,
ENC, 4, END, 4),
TPS6586X_LDO(LDO_7, "vinldo678", tps6586x_ldo0, SUPPLYV3, 3, 3,
ENC, 5, END, 5),
TPS6586X_LDO(LDO_8, "vinldo678", tps6586x_ldo0, SUPPLYV2, 5, 3,
ENC, 6, END, 6),
TPS6586X_LDO(LDO_9, "vinldo9", tps6586x_ldo0, SUPPLYV6, 3, 3,
ENE, 7, ENE, 7),
TPS6586X_LDO(SM_2, "vin-sm2", tps658640_sm2, SUPPLYV2, 0, 5,
ENC, 7, END, 7),
TPS6586X_FIXED_LDO(LDO_RTC, "REG-SYS", tps658640_rtc, SUPPLYV4, 3, 2,
V4, 7, V4, 7),
};
static struct tps6586x_regulator tps658643_regulator[] = { static struct tps6586x_regulator tps658643_regulator[] = {
TPS6586X_LDO(SM_2, "vin-sm2", tps658643_sm2, SUPPLYV2, 0, 5, ENC, 7, TPS6586X_LDO(SM_2, "vin-sm2", tps658643_sm2, SUPPLYV2, 0, 5, ENC, 7,
END, 7), END, 7),
...@@ -295,6 +338,11 @@ static struct tps6586x_regulator *find_regulator_info(int id, int version) ...@@ -295,6 +338,11 @@ static struct tps6586x_regulator *find_regulator_info(int id, int version)
table = tps658623_regulator; table = tps658623_regulator;
num = ARRAY_SIZE(tps658623_regulator); num = ARRAY_SIZE(tps658623_regulator);
break; break;
case TPS658640:
case TPS658640v2:
table = tps658640_regulator;
num = ARRAY_SIZE(tps658640_regulator);
break;
case TPS658643: case TPS658643:
table = tps658643_regulator; table = tps658643_regulator;
num = ARRAY_SIZE(tps658643_regulator); num = ARRAY_SIZE(tps658643_regulator);
......
...@@ -98,7 +98,7 @@ static int vexpress_regulator_probe(struct platform_device *pdev) ...@@ -98,7 +98,7 @@ static int vexpress_regulator_probe(struct platform_device *pdev)
return 0; return 0;
} }
static struct of_device_id vexpress_regulator_of_match[] = { static const struct of_device_id vexpress_regulator_of_match[] = {
{ .compatible = "arm,vexpress-volt", }, { .compatible = "arm,vexpress-volt", },
{ } { }
}; };
......
...@@ -124,4 +124,7 @@ int wm5102_patch(struct arizona *arizona); ...@@ -124,4 +124,7 @@ int wm5102_patch(struct arizona *arizona);
int wm5110_patch(struct arizona *arizona); int wm5110_patch(struct arizona *arizona);
int wm8997_patch(struct arizona *arizona); int wm8997_patch(struct arizona *arizona);
extern int arizona_of_get_named_gpio(struct arizona *arizona, const char *prop,
bool mandatory);
#endif #endif
...@@ -19,12 +19,15 @@ ...@@ -19,12 +19,15 @@
#include <linux/regmap.h> #include <linux/regmap.h>
/* max register address */ /* max register address */
#define BCM590XX_MAX_REGISTER 0xe7 #define BCM590XX_MAX_REGISTER_PRI 0xe7
#define BCM590XX_MAX_REGISTER_SEC 0xf0
struct bcm590xx { struct bcm590xx {
struct device *dev; struct device *dev;
struct i2c_client *i2c_client; struct i2c_client *i2c_pri;
struct regmap *regmap; struct i2c_client *i2c_sec;
struct regmap *regmap_pri;
struct regmap *regmap_sec;
unsigned int id; unsigned int id;
}; };
......
...@@ -63,7 +63,7 @@ struct mfd_cell { ...@@ -63,7 +63,7 @@ struct mfd_cell {
/* A list of regulator supplies that should be mapped to the MFD /* A list of regulator supplies that should be mapped to the MFD
* device rather than the child device when requested * device rather than the child device when requested
*/ */
const char **parent_supplies; const char * const *parent_supplies;
int num_parent_supplies; int num_parent_supplies;
}; };
......
...@@ -148,6 +148,8 @@ enum s2mps14_regulators { ...@@ -148,6 +148,8 @@ enum s2mps14_regulators {
#define S2MPS14_ENABLE_SHIFT 6 #define S2MPS14_ENABLE_SHIFT 6
/* On/Off controlled by PWREN */ /* On/Off controlled by PWREN */
#define S2MPS14_ENABLE_SUSPEND (0x01 << S2MPS14_ENABLE_SHIFT) #define S2MPS14_ENABLE_SUSPEND (0x01 << S2MPS14_ENABLE_SHIFT)
/* On/Off controlled by LDO10EN or EMMCEN */
#define S2MPS14_ENABLE_EXT_CONTROL (0x00 << S2MPS14_ENABLE_SHIFT)
#define S2MPS14_LDO_N_VOLTAGES (S2MPS14_LDO_VSEL_MASK + 1) #define S2MPS14_LDO_N_VOLTAGES (S2MPS14_LDO_VSEL_MASK + 1)
#define S2MPS14_BUCK_N_VOLTAGES (S2MPS14_BUCK_VSEL_MASK + 1) #define S2MPS14_BUCK_N_VOLTAGES (S2MPS14_BUCK_VSEL_MASK + 1)
......
...@@ -64,6 +64,20 @@ enum { ...@@ -64,6 +64,20 @@ enum {
TPS65090_REGULATOR_MAX, TPS65090_REGULATOR_MAX,
}; };
/* Register addresses */
#define TPS65090_REG_INTR_STS 0x00
#define TPS65090_REG_INTR_STS2 0x01
#define TPS65090_REG_INTR_MASK 0x02
#define TPS65090_REG_INTR_MASK2 0x03
#define TPS65090_REG_CG_CTRL0 0x04
#define TPS65090_REG_CG_CTRL1 0x05
#define TPS65090_REG_CG_CTRL2 0x06
#define TPS65090_REG_CG_CTRL3 0x07
#define TPS65090_REG_CG_CTRL4 0x08
#define TPS65090_REG_CG_CTRL5 0x09
#define TPS65090_REG_CG_STATUS1 0x0a
#define TPS65090_REG_CG_STATUS2 0x0b
struct tps65090 { struct tps65090 {
struct device *dev; struct device *dev;
struct regmap *rmap; struct regmap *rmap;
...@@ -78,11 +92,16 @@ struct tps65090 { ...@@ -78,11 +92,16 @@ struct tps65090 {
* DCDC1, DCDC2 and DCDC3. * DCDC1, DCDC2 and DCDC3.
* @gpio: Gpio number if external control is enabled and controlled through * @gpio: Gpio number if external control is enabled and controlled through
* gpio. * gpio.
* @overcurrent_wait_valid: True if the overcurrent_wait should be applied.
* @overcurrent_wait: Value to set as the overcurrent wait time. This is the
* actual bitfield value, not a time in ms (valid value are 0 - 3).
*/ */
struct tps65090_regulator_plat_data { struct tps65090_regulator_plat_data {
struct regulator_init_data *reg_init_data; struct regulator_init_data *reg_init_data;
bool enable_ext_control; bool enable_ext_control;
int gpio; int gpio;
bool overcurrent_wait_valid;
int overcurrent_wait;
}; };
struct tps65090_platform_data { struct tps65090_platform_data {
......
...@@ -254,7 +254,6 @@ struct tps65217 { ...@@ -254,7 +254,6 @@ struct tps65217 {
struct tps65217_board *pdata; struct tps65217_board *pdata;
unsigned long id; unsigned long id;
struct regulator_desc desc[TPS65217_NUM_REGULATOR]; struct regulator_desc desc[TPS65217_NUM_REGULATOR];
struct regulator_dev *rdev[TPS65217_NUM_REGULATOR];
struct regmap *regmap; struct regmap *regmap;
}; };
......
...@@ -17,6 +17,8 @@ ...@@ -17,6 +17,8 @@
#define TPS658621A 0x15 #define TPS658621A 0x15
#define TPS658621CD 0x2c #define TPS658621CD 0x2c
#define TPS658623 0x1b #define TPS658623 0x1b
#define TPS658640 0x01
#define TPS658640v2 0x02
#define TPS658643 0x03 #define TPS658643 0x03
enum { enum {
......
...@@ -151,11 +151,13 @@ int regulator_register_supply_alias(struct device *dev, const char *id, ...@@ -151,11 +151,13 @@ int regulator_register_supply_alias(struct device *dev, const char *id,
const char *alias_id); const char *alias_id);
void regulator_unregister_supply_alias(struct device *dev, const char *id); void regulator_unregister_supply_alias(struct device *dev, const char *id);
int regulator_bulk_register_supply_alias(struct device *dev, const char **id, int regulator_bulk_register_supply_alias(struct device *dev,
const char *const *id,
struct device *alias_dev, struct device *alias_dev,
const char **alias_id, int num_id); const char *const *alias_id,
int num_id);
void regulator_bulk_unregister_supply_alias(struct device *dev, void regulator_bulk_unregister_supply_alias(struct device *dev,
const char **id, int num_id); const char * const *id, int num_id);
int devm_regulator_register_supply_alias(struct device *dev, const char *id, int devm_regulator_register_supply_alias(struct device *dev, const char *id,
struct device *alias_dev, struct device *alias_dev,
...@@ -164,12 +166,12 @@ void devm_regulator_unregister_supply_alias(struct device *dev, ...@@ -164,12 +166,12 @@ void devm_regulator_unregister_supply_alias(struct device *dev,
const char *id); const char *id);
int devm_regulator_bulk_register_supply_alias(struct device *dev, int devm_regulator_bulk_register_supply_alias(struct device *dev,
const char **id, const char *const *id,
struct device *alias_dev, struct device *alias_dev,
const char **alias_id, const char *const *alias_id,
int num_id); int num_id);
void devm_regulator_bulk_unregister_supply_alias(struct device *dev, void devm_regulator_bulk_unregister_supply_alias(struct device *dev,
const char **id, const char *const *id,
int num_id); int num_id);
/* regulator output control and status */ /* regulator output control and status */
...@@ -290,17 +292,17 @@ static inline void regulator_unregister_supply_alias(struct device *dev, ...@@ -290,17 +292,17 @@ static inline void regulator_unregister_supply_alias(struct device *dev,
} }
static inline int regulator_bulk_register_supply_alias(struct device *dev, static inline int regulator_bulk_register_supply_alias(struct device *dev,
const char **id, const char *const *id,
struct device *alias_dev, struct device *alias_dev,
const char **alias_id, const char * const *alias_id,
int num_id) int num_id)
{ {
return 0; return 0;
} }
static inline void regulator_bulk_unregister_supply_alias(struct device *dev, static inline void regulator_bulk_unregister_supply_alias(struct device *dev,
const char **id, const char * const *id,
int num_id) int num_id)
{ {
} }
...@@ -317,15 +319,17 @@ static inline void devm_regulator_unregister_supply_alias(struct device *dev, ...@@ -317,15 +319,17 @@ static inline void devm_regulator_unregister_supply_alias(struct device *dev,
{ {
} }
static inline int devm_regulator_bulk_register_supply_alias( static inline int devm_regulator_bulk_register_supply_alias(struct device *dev,
struct device *dev, const char **id, struct device *alias_dev, const char *const *id,
const char **alias_id, int num_id) struct device *alias_dev,
const char *const *alias_id,
int num_id)
{ {
return 0; return 0;
} }
static inline void devm_regulator_bulk_unregister_supply_alias( static inline void devm_regulator_bulk_unregister_supply_alias(
struct device *dev, const char **id, int num_id) struct device *dev, const char *const *id, int num_id)
{ {
} }
...@@ -397,6 +401,12 @@ static inline int regulator_set_voltage(struct regulator *regulator, ...@@ -397,6 +401,12 @@ static inline int regulator_set_voltage(struct regulator *regulator,
return 0; return 0;
} }
static inline int regulator_set_voltage_time(struct regulator *regulator,
int old_uV, int new_uV)
{
return 0;
}
static inline int regulator_get_voltage(struct regulator *regulator) static inline int regulator_get_voltage(struct regulator *regulator)
{ {
return -EINVAL; return -EINVAL;
......
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