regulator: Updates for v4.13

A quiet release for the regulator API, a series of fairly small fixes
 plus one new feature and a few new drivers:
 
  - Support for regulators with different settling times for rising and
    falling voltage changes.
  - New drivers for Allwinner AXP803, HiSilicon HI6421V530 and TI
    LP87565.
 -----BEGIN PGP SIGNATURE-----
 
 iQFHBAABCAAxFiEEreZoqmdXGLWf4p/qJNaLcl1Uh9AFAllbr7oTHGJyb29uaWVA
 a2VybmVsLm9yZwAKCRAk1otyXVSH0E90B/9q4yTZ03ztMZT+CdKq8tZOgvt9OXqx
 XMrcny2cdFm5uXSY3zXGpFwiMTMgsyt2oypQrGLYQxiH6aAvAwD1blygeaIOK77I
 uoZBAGAH4oc4LySu5lmzozCM1ao1CaiTEdsBb/yjG13pKI24aFxLPL5SZfiyzXs8
 EY2QCiAC4FkMJYEERcHb3Mk2Nhsm99Iy533gr6wgToQF4REwGVM8kIwTKftQ/8N5
 OEKycgg2r9G2zTXR6S5m/yArHzaqPdJUu6HF4DG2wmgTiNURbm87I3u1z7NAEYzj
 KoyiMn9D1OpMootUMEQo8RQPhH6n8q6OWvHcrpRbmatA7pmQ+b/lt4vr
 =9LJp
 -----END PGP SIGNATURE-----

Merge tag 'regulator-v4.13' of git://git.kernel.org/pub/scm/linux/kernel/git/broonie/regulator

Pull regulator updates from Mark Brown:
 "A quiet release for the regulator API, a series of fairly small fixes
  plus one new feature and a few new drivers:

   - Support for regulators with different settling times for rising and
     falling voltage changes.

   - New drivers for Allwinner AXP803, HiSilicon HI6421V530 and TI
     LP87565"

* tag 'regulator-v4.13' of git://git.kernel.org/pub/scm/linux/kernel/git/broonie/regulator: (21 commits)
  regulator: core: Fix size limit of supply_map
  regulator: core: Fix voltage change propagations to supply regulators
  regulator: lp87565: Fix the initial voltage range
  regulator: tps65910: wire up sleep control configuration
  regulator: hi6421v530: Describe consumed platform device
  regulator: tps65910: check TPS65910_NUM_REGS at build time
  regulator: core: Prioritise consumer mappings over regulator name
  regulator: lp87565: Fix the GPL header
  regulator: hi6421: Describe consumed platform device
  regulator: hi6421v530: add driver for hi6421v530 voltage regulator
  regulator: da9061: BUCK and LDO regulator driver
  regulator: bd9571mwv: Statize local symbols
  regulator: tps65917: Add support for SMPS12
  regulator: lp87565: Add support for lp87565 PMIC regulators
  regulator: axp20x-regulator: add support for AXP803
  regulator: lp8755: fix spelling mistake "acceess" -> "access"
  regulator: Allow for asymmetric settling times
  regulator: DT: Add properties for asymmetric settling times
  regulator: palmas: Drop unnecessary static
  MAINTAINERS: Update MAX77802 PMIC entry
  ...
This commit is contained in:
Linus Torvalds 2017-07-04 11:55:21 -07:00
commit d62eb5edf6
22 changed files with 1058 additions and 102 deletions

View File

@ -61,6 +61,10 @@ Optional properties:
There should be 9 entries here, one for each gpio. There should be 9 entries here, one for each gpio.
- ti,system-power-controller: Telling whether or not this pmic is controlling - ti,system-power-controller: Telling whether or not this pmic is controlling
the system power. the system power.
- ti,sleep-enable: Enable SLEEP state.
- ti,sleep-keep-therm: Keep thermal monitoring on in sleep state.
- ti,sleep-keep-ck32k: Keep the 32KHz clock output on in sleep state.
- ti,sleep-keep-hsclk: Keep high speed internal clock on in sleep state.
Regulator Optional properties: Regulator Optional properties:
- ti,regulator-ext-sleep-control: enable external sleep - ti,regulator-ext-sleep-control: enable external sleep

View File

@ -24,6 +24,14 @@ Optional properties:
- regulator-settling-time-us: Settling time, in microseconds, for voltage - regulator-settling-time-us: Settling time, in microseconds, for voltage
change if regulator have the constant time for any level voltage change. change if regulator have the constant time for any level voltage change.
This is useful when regulator have exponential voltage change. This is useful when regulator have exponential voltage change.
- regulator-settling-time-up-us: Settling time, in microseconds, for voltage
increase if the regulator needs a constant time to settle after voltage
increases of any level. This is useful for regulators with exponential
voltage changes.
- regulator-settling-time-down-us: Settling time, in microseconds, for voltage
decrease if the regulator needs a constant time to settle after voltage
decreases of any level. This is useful for regulators with exponential
voltage changes.
- regulator-soft-start: Enable soft start so that voltage ramps slowly - regulator-soft-start: Enable soft start so that voltage ramps slowly
- regulator-state-mem sub-root node for Suspend-to-RAM mode - regulator-state-mem sub-root node for Suspend-to-RAM mode
: suspend to memory, the device goes to sleep, but all data stored in memory, : suspend to memory, the device goes to sleep, but all data stored in memory,

View File

@ -8076,11 +8076,11 @@ S: Supported
F: drivers/power/supply/max14577_charger.c F: drivers/power/supply/max14577_charger.c
F: drivers/power/supply/max77693_charger.c F: drivers/power/supply/max77693_charger.c
MAXIM MAX77802 MULTIFUNCTION PMIC DEVICE DRIVERS MAXIM MAX77802 PMIC REGULATOR DEVICE DRIVER
M: Javier Martinez Canillas <javier@osg.samsung.com> M: Javier Martinez Canillas <javier@dowhile0.org>
L: linux-kernel@vger.kernel.org L: linux-kernel@vger.kernel.org
S: Supported S: Supported
F: drivers/*/*max77802*.c F: drivers/regulator/max77802-regulator.c
F: Documentation/devicetree/bindings/*/*max77802.txt F: Documentation/devicetree/bindings/*/*max77802.txt
F: include/dt-bindings/*/*max77802.h F: include/dt-bindings/*/*max77802.h

View File

@ -328,11 +328,7 @@ static int tps65910_sleepinit(struct tps65910 *tps65910,
goto err_sleep_init; goto err_sleep_init;
} }
/* Return if there is no sleep keepon data. */ if (pmic_pdata->slp_keepon.therm_keepon) {
if (!pmic_pdata->slp_keepon)
return 0;
if (pmic_pdata->slp_keepon->therm_keepon) {
ret = tps65910_reg_set_bits(tps65910, ret = tps65910_reg_set_bits(tps65910,
TPS65910_SLEEP_KEEP_RES_ON, TPS65910_SLEEP_KEEP_RES_ON,
SLEEP_KEEP_RES_ON_THERM_KEEPON_MASK); SLEEP_KEEP_RES_ON_THERM_KEEPON_MASK);
@ -342,7 +338,7 @@ static int tps65910_sleepinit(struct tps65910 *tps65910,
} }
} }
if (pmic_pdata->slp_keepon->clkout32k_keepon) { if (pmic_pdata->slp_keepon.clkout32k_keepon) {
ret = tps65910_reg_set_bits(tps65910, ret = tps65910_reg_set_bits(tps65910,
TPS65910_SLEEP_KEEP_RES_ON, TPS65910_SLEEP_KEEP_RES_ON,
SLEEP_KEEP_RES_ON_CLKOUT32K_KEEPON_MASK); SLEEP_KEEP_RES_ON_CLKOUT32K_KEEPON_MASK);
@ -352,7 +348,7 @@ static int tps65910_sleepinit(struct tps65910 *tps65910,
} }
} }
if (pmic_pdata->slp_keepon->i2chs_keepon) { if (pmic_pdata->slp_keepon.i2chs_keepon) {
ret = tps65910_reg_set_bits(tps65910, ret = tps65910_reg_set_bits(tps65910,
TPS65910_SLEEP_KEEP_RES_ON, TPS65910_SLEEP_KEEP_RES_ON,
SLEEP_KEEP_RES_ON_I2CHS_KEEPON_MASK); SLEEP_KEEP_RES_ON_I2CHS_KEEPON_MASK);
@ -415,6 +411,18 @@ static struct tps65910_board *tps65910_parse_dt(struct i2c_client *client,
prop = of_property_read_bool(np, "ti,en-ck32k-xtal"); prop = of_property_read_bool(np, "ti,en-ck32k-xtal");
board_info->en_ck32k_xtal = prop; board_info->en_ck32k_xtal = prop;
prop = of_property_read_bool(np, "ti,sleep-enable");
board_info->en_dev_slp = prop;
prop = of_property_read_bool(np, "ti,sleep-keep-therm");
board_info->slp_keepon.therm_keepon = prop;
prop = of_property_read_bool(np, "ti,sleep-keep-ck32k");
board_info->slp_keepon.clkout32k_keepon = prop;
prop = of_property_read_bool(np, "ti,sleep-keep-hsclk");
board_info->slp_keepon.i2chs_keepon = prop;
board_info->irq = client->irq; board_info->irq = client->irq;
board_info->irq_base = -1; board_info->irq_base = -1;
board_info->pm_off = of_property_read_bool(np, board_info->pm_off = of_property_read_bool(np,

View File

@ -214,11 +214,11 @@ config REGULATOR_DA9055
will be called da9055-regulator. will be called da9055-regulator.
config REGULATOR_DA9062 config REGULATOR_DA9062
tristate "Dialog Semiconductor DA9062 regulators" tristate "Dialog Semiconductor DA9061/62 regulators"
depends on MFD_DA9062 depends on MFD_DA9062
help help
Say y here to support the BUCKs and LDOs regulators found on Say y here to support the BUCKs and LDOs regulators found on
DA9062 PMICs. DA9061 and DA9062 PMICs.
This driver can also be built as a module. If so, the module This driver can also be built as a module. If so, the module
will be called da9062-regulator. will be called da9062-regulator.
@ -296,6 +296,16 @@ config REGULATOR_HI6421
21 general purpose LDOs, 3 dedicated LDOs, and 5 BUCKs. All 21 general purpose LDOs, 3 dedicated LDOs, and 5 BUCKs. All
of them come with support to either ECO (idle) or sleep mode. of them come with support to either ECO (idle) or sleep mode.
config REGULATOR_HI6421V530
tristate "HiSilicon Hi6421v530 PMIC voltage regulator support"
depends on MFD_HI6421_PMIC && OF
help
This driver provides support for the voltage regulators on
HiSilicon Hi6421v530 PMU / Codec IC.
Hi6421v530 is a multi-function device which, on regulator part,
provides 5 general purpose LDOs, and all of them come with support
to either ECO (idle) or sleep mode.
config REGULATOR_HI655X config REGULATOR_HI655X
tristate "Hisilicon HI655X PMIC regulators support" tristate "Hisilicon HI655X PMIC regulators support"
depends on ARCH_HISI || COMPILE_TEST depends on ARCH_HISI || COMPILE_TEST
@ -365,6 +375,14 @@ config REGULATOR_LP8755
chip contains six step-down DC/DC converters which can support chip contains six step-down DC/DC converters which can support
9 mode multiphase configuration. 9 mode multiphase configuration.
config REGULATOR_LP87565
tristate "TI LP87565 Power regulators"
depends on MFD_TI_LP87565 && OF
help
This driver supports LP87565 voltage regulator chips. LP87565
provides four step-down converters. It supports software based
voltage control for different voltage domains
config REGULATOR_LP8788 config REGULATOR_LP8788
tristate "TI LP8788 Power Regulators" tristate "TI LP8788 Power Regulators"
depends on MFD_LP8788 depends on MFD_LP8788

View File

@ -38,6 +38,7 @@ obj-$(CONFIG_REGULATOR_DB8500_PRCMU) += db8500-prcmu.o
obj-$(CONFIG_REGULATOR_FAN53555) += fan53555.o obj-$(CONFIG_REGULATOR_FAN53555) += fan53555.o
obj-$(CONFIG_REGULATOR_GPIO) += gpio-regulator.o obj-$(CONFIG_REGULATOR_GPIO) += gpio-regulator.o
obj-$(CONFIG_REGULATOR_HI6421) += hi6421-regulator.o obj-$(CONFIG_REGULATOR_HI6421) += hi6421-regulator.o
obj-$(CONFIG_REGULATOR_HI6421V530) += hi6421v530-regulator.o
obj-$(CONFIG_REGULATOR_HI655X) += hi655x-regulator.o obj-$(CONFIG_REGULATOR_HI655X) += hi655x-regulator.o
obj-$(CONFIG_REGULATOR_ISL6271A) += isl6271a-regulator.o obj-$(CONFIG_REGULATOR_ISL6271A) += isl6271a-regulator.o
obj-$(CONFIG_REGULATOR_ISL9305) += isl9305.o obj-$(CONFIG_REGULATOR_ISL9305) += isl9305.o
@ -46,6 +47,7 @@ obj-$(CONFIG_REGULATOR_LP3971) += lp3971.o
obj-$(CONFIG_REGULATOR_LP3972) += lp3972.o obj-$(CONFIG_REGULATOR_LP3972) += lp3972.o
obj-$(CONFIG_REGULATOR_LP872X) += lp872x.o obj-$(CONFIG_REGULATOR_LP872X) += lp872x.o
obj-$(CONFIG_REGULATOR_LP873X) += lp873x-regulator.o obj-$(CONFIG_REGULATOR_LP873X) += lp873x-regulator.o
obj-$(CONFIG_REGULATOR_LP87565) += lp87565-regulator.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

View File

@ -244,6 +244,82 @@ static const struct regulator_desc axp22x_drivevbus_regulator = {
.ops = &axp20x_ops_sw, .ops = &axp20x_ops_sw,
}; };
static const struct regulator_linear_range axp803_dcdc234_ranges[] = {
REGULATOR_LINEAR_RANGE(500000, 0x0, 0x46, 10000),
REGULATOR_LINEAR_RANGE(1220000, 0x47, 0x4b, 20000),
};
static const struct regulator_linear_range axp803_dcdc5_ranges[] = {
REGULATOR_LINEAR_RANGE(800000, 0x0, 0x20, 10000),
REGULATOR_LINEAR_RANGE(1140000, 0x21, 0x44, 20000),
};
static const struct regulator_linear_range axp803_dcdc6_ranges[] = {
REGULATOR_LINEAR_RANGE(600000, 0x0, 0x32, 10000),
REGULATOR_LINEAR_RANGE(1120000, 0x33, 0x47, 20000),
};
/* AXP806's CLDO2 and AXP809's DLDO1 shares the same range */
static const struct regulator_linear_range axp803_dldo2_ranges[] = {
REGULATOR_LINEAR_RANGE(700000, 0x0, 0x1a, 100000),
REGULATOR_LINEAR_RANGE(3400000, 0x1b, 0x1f, 200000),
};
static const struct regulator_desc axp803_regulators[] = {
AXP_DESC(AXP803, DCDC1, "dcdc1", "vin1", 1600, 3400, 100,
AXP803_DCDC1_V_OUT, 0x1f, AXP22X_PWR_OUT_CTRL1, BIT(0)),
AXP_DESC_RANGES(AXP803, DCDC2, "dcdc2", "vin2", axp803_dcdc234_ranges,
76, AXP803_DCDC2_V_OUT, 0x7f, AXP22X_PWR_OUT_CTRL1,
BIT(1)),
AXP_DESC_RANGES(AXP803, DCDC3, "dcdc3", "vin3", axp803_dcdc234_ranges,
76, AXP803_DCDC3_V_OUT, 0x7f, AXP22X_PWR_OUT_CTRL1,
BIT(2)),
AXP_DESC_RANGES(AXP803, DCDC4, "dcdc4", "vin4", axp803_dcdc234_ranges,
76, AXP803_DCDC4_V_OUT, 0x7f, AXP22X_PWR_OUT_CTRL1,
BIT(3)),
AXP_DESC_RANGES(AXP803, DCDC5, "dcdc5", "vin5", axp803_dcdc5_ranges,
68, AXP803_DCDC5_V_OUT, 0x7f, AXP22X_PWR_OUT_CTRL1,
BIT(4)),
AXP_DESC_RANGES(AXP803, DCDC6, "dcdc6", "vin6", axp803_dcdc6_ranges,
72, AXP803_DCDC6_V_OUT, 0x7f, AXP22X_PWR_OUT_CTRL1,
BIT(5)),
/* secondary switchable output of DCDC1 */
AXP_DESC_SW(AXP803, DC1SW, "dc1sw", NULL, AXP22X_PWR_OUT_CTRL2,
BIT(7)),
AXP_DESC(AXP803, ALDO1, "aldo1", "aldoin", 700, 3300, 100,
AXP22X_ALDO1_V_OUT, 0x1f, AXP22X_PWR_OUT_CTRL3, BIT(5)),
AXP_DESC(AXP803, ALDO2, "aldo2", "aldoin", 700, 3300, 100,
AXP22X_ALDO2_V_OUT, 0x1f, AXP22X_PWR_OUT_CTRL3, BIT(6)),
AXP_DESC(AXP803, ALDO3, "aldo3", "aldoin", 700, 3300, 100,
AXP22X_ALDO3_V_OUT, 0x1f, AXP22X_PWR_OUT_CTRL3, BIT(7)),
AXP_DESC(AXP803, DLDO1, "dldo1", "dldoin", 700, 3300, 100,
AXP22X_DLDO1_V_OUT, 0x1f, AXP22X_PWR_OUT_CTRL2, BIT(3)),
AXP_DESC_RANGES(AXP803, DLDO2, "dldo2", "dldoin", axp803_dldo2_ranges,
32, AXP22X_DLDO2_V_OUT, 0x1f, AXP22X_PWR_OUT_CTRL2,
BIT(4)),
AXP_DESC(AXP803, DLDO3, "dldo3", "dldoin", 700, 3300, 100,
AXP22X_DLDO3_V_OUT, 0x1f, AXP22X_PWR_OUT_CTRL2, BIT(5)),
AXP_DESC(AXP803, DLDO4, "dldo4", "dldoin", 700, 3300, 100,
AXP22X_DLDO4_V_OUT, 0x1f, AXP22X_PWR_OUT_CTRL2, BIT(6)),
AXP_DESC(AXP803, ELDO1, "eldo1", "eldoin", 700, 1900, 50,
AXP22X_ELDO1_V_OUT, 0x1f, AXP22X_PWR_OUT_CTRL2, BIT(0)),
AXP_DESC(AXP803, ELDO2, "eldo2", "eldoin", 700, 1900, 50,
AXP22X_ELDO2_V_OUT, 0x1f, AXP22X_PWR_OUT_CTRL2, BIT(1)),
AXP_DESC(AXP803, ELDO3, "eldo3", "eldoin", 700, 1900, 50,
AXP22X_ELDO3_V_OUT, 0x1f, AXP22X_PWR_OUT_CTRL2, BIT(2)),
AXP_DESC(AXP803, FLDO1, "fldo1", "fldoin", 700, 1450, 50,
AXP803_FLDO1_V_OUT, 0x0f, AXP22X_PWR_OUT_CTRL3, BIT(2)),
AXP_DESC(AXP803, FLDO2, "fldo2", "fldoin", 700, 1450, 50,
AXP803_FLDO2_V_OUT, 0x0f, AXP22X_PWR_OUT_CTRL3, BIT(3)),
AXP_DESC_IO(AXP803, LDO_IO0, "ldo-io0", "ips", 700, 3300, 100,
AXP22X_LDO_IO0_V_OUT, 0x1f, AXP20X_GPIO0_CTRL, 0x07,
AXP22X_IO_ENABLED, AXP22X_IO_DISABLED),
AXP_DESC_IO(AXP803, LDO_IO1, "ldo-io1", "ips", 700, 3300, 100,
AXP22X_LDO_IO1_V_OUT, 0x1f, AXP20X_GPIO1_CTRL, 0x07,
AXP22X_IO_ENABLED, AXP22X_IO_DISABLED),
AXP_DESC_FIXED(AXP803, RTC_LDO, "rtc-ldo", "ips", 3000),
};
static const struct regulator_linear_range axp806_dcdca_ranges[] = { static const struct regulator_linear_range axp806_dcdca_ranges[] = {
REGULATOR_LINEAR_RANGE(600000, 0x0, 0x32, 10000), REGULATOR_LINEAR_RANGE(600000, 0x0, 0x32, 10000),
REGULATOR_LINEAR_RANGE(1120000, 0x33, 0x47, 20000), REGULATOR_LINEAR_RANGE(1120000, 0x33, 0x47, 20000),
@ -254,11 +330,6 @@ static const struct regulator_linear_range axp806_dcdcd_ranges[] = {
REGULATOR_LINEAR_RANGE(1600000, 0x2e, 0x3f, 100000), REGULATOR_LINEAR_RANGE(1600000, 0x2e, 0x3f, 100000),
}; };
static const struct regulator_linear_range axp806_cldo2_ranges[] = {
REGULATOR_LINEAR_RANGE(700000, 0x0, 0x1a, 100000),
REGULATOR_LINEAR_RANGE(3400000, 0x1b, 0x1f, 200000),
};
static const struct regulator_desc axp806_regulators[] = { static const struct regulator_desc axp806_regulators[] = {
AXP_DESC_RANGES(AXP806, DCDCA, "dcdca", "vina", axp806_dcdca_ranges, AXP_DESC_RANGES(AXP806, DCDCA, "dcdca", "vina", axp806_dcdca_ranges,
72, AXP806_DCDCA_V_CTRL, 0x7f, AXP806_PWR_OUT_CTRL1, 72, AXP806_DCDCA_V_CTRL, 0x7f, AXP806_PWR_OUT_CTRL1,
@ -289,7 +360,7 @@ static const struct regulator_desc axp806_regulators[] = {
AXP806_BLDO4_V_CTRL, 0x0f, AXP806_PWR_OUT_CTRL2, BIT(3)), AXP806_BLDO4_V_CTRL, 0x0f, AXP806_PWR_OUT_CTRL2, BIT(3)),
AXP_DESC(AXP806, CLDO1, "cldo1", "cldoin", 700, 3300, 100, AXP_DESC(AXP806, CLDO1, "cldo1", "cldoin", 700, 3300, 100,
AXP806_CLDO1_V_CTRL, 0x1f, AXP806_PWR_OUT_CTRL2, BIT(4)), AXP806_CLDO1_V_CTRL, 0x1f, AXP806_PWR_OUT_CTRL2, BIT(4)),
AXP_DESC_RANGES(AXP806, CLDO2, "cldo2", "cldoin", axp806_cldo2_ranges, AXP_DESC_RANGES(AXP806, CLDO2, "cldo2", "cldoin", axp803_dldo2_ranges,
32, AXP806_CLDO2_V_CTRL, 0x1f, AXP806_PWR_OUT_CTRL2, 32, AXP806_CLDO2_V_CTRL, 0x1f, AXP806_PWR_OUT_CTRL2,
BIT(5)), BIT(5)),
AXP_DESC(AXP806, CLDO3, "cldo3", "cldoin", 700, 3300, 100, AXP_DESC(AXP806, CLDO3, "cldo3", "cldoin", 700, 3300, 100,
@ -326,7 +397,7 @@ static const struct regulator_desc axp809_regulators[] = {
AXP22X_ALDO2_V_OUT, 0x1f, AXP22X_PWR_OUT_CTRL1, BIT(7)), AXP22X_ALDO2_V_OUT, 0x1f, AXP22X_PWR_OUT_CTRL1, BIT(7)),
AXP_DESC(AXP809, ALDO3, "aldo3", "aldoin", 700, 3300, 100, AXP_DESC(AXP809, ALDO3, "aldo3", "aldoin", 700, 3300, 100,
AXP22X_ALDO3_V_OUT, 0x1f, AXP22X_PWR_OUT_CTRL2, BIT(5)), AXP22X_ALDO3_V_OUT, 0x1f, AXP22X_PWR_OUT_CTRL2, BIT(5)),
AXP_DESC_RANGES(AXP809, DLDO1, "dldo1", "dldoin", axp806_cldo2_ranges, AXP_DESC_RANGES(AXP809, DLDO1, "dldo1", "dldoin", axp803_dldo2_ranges,
32, AXP22X_DLDO1_V_OUT, 0x1f, AXP22X_PWR_OUT_CTRL2, 32, AXP22X_DLDO1_V_OUT, 0x1f, AXP22X_PWR_OUT_CTRL2,
BIT(3)), BIT(3)),
AXP_DESC(AXP809, DLDO2, "dldo2", "dldoin", 700, 3300, 100, AXP_DESC(AXP809, DLDO2, "dldo2", "dldoin", 700, 3300, 100,
@ -369,14 +440,21 @@ static int axp20x_set_dcdc_freq(struct platform_device *pdev, u32 dcdcfreq)
def = 1500; def = 1500;
step = 75; step = 75;
break; break;
case AXP806_ID: case AXP803_ID:
/* /*
* AXP806 DCDC work frequency setting has the same range and * AXP803 DCDC work frequency setting has the same range and
* step as AXP22X, but at a different register. * step as AXP22X, but at a different register.
* Fall through to the check below. * Fall through to the check below.
* (See include/linux/mfd/axp20x.h) * (See include/linux/mfd/axp20x.h)
*/ */
reg = AXP806_DCDC_FREQ_CTRL; reg = AXP803_DCDC_FREQ_CTRL;
case AXP806_ID:
/*
* AXP806 also have DCDC work frequency setting register at a
* different position.
*/
if (axp20x->variant == AXP806_ID)
reg = AXP806_DCDC_FREQ_CTRL;
case AXP221_ID: case AXP221_ID:
case AXP223_ID: case AXP223_ID:
case AXP809_ID: case AXP809_ID:
@ -475,6 +553,14 @@ static int axp20x_set_dcdc_workmode(struct regulator_dev *rdev, int id, u32 work
workmode <<= id - AXP22X_DCDC1; workmode <<= id - AXP22X_DCDC1;
break; break;
case AXP803_ID:
if (id < AXP803_DCDC1 || id > AXP803_DCDC6)
return -EINVAL;
mask = AXP22X_WORKMODE_DCDCX_MASK(id - AXP803_DCDC1);
workmode <<= id - AXP803_DCDC1;
break;
default: default:
/* should not happen */ /* should not happen */
WARN_ON(1); WARN_ON(1);
@ -492,20 +578,38 @@ static bool axp20x_is_polyphase_slave(struct axp20x_dev *axp20x, int id)
{ {
u32 reg = 0; u32 reg = 0;
/* Only AXP806 has poly-phase outputs */ /*
if (axp20x->variant != AXP806_ID) * Currently in our supported AXP variants, only AXP803 and AXP806
* have polyphase regulators.
*/
switch (axp20x->variant) {
case AXP803_ID:
regmap_read(axp20x->regmap, AXP803_POLYPHASE_CTRL, &reg);
switch (id) {
case AXP803_DCDC3:
return !!(reg & BIT(6));
case AXP803_DCDC6:
return !!(reg & BIT(7));
}
break;
case AXP806_ID:
regmap_read(axp20x->regmap, AXP806_DCDC_MODE_CTRL2, &reg);
switch (id) {
case AXP806_DCDCB:
return (((reg & GENMASK(7, 6)) == BIT(6)) ||
((reg & GENMASK(7, 6)) == BIT(7)));
case AXP806_DCDCC:
return ((reg & GENMASK(7, 6)) == BIT(7));
case AXP806_DCDCE:
return !!(reg & BIT(5));
}
break;
default:
return false; return false;
regmap_read(axp20x->regmap, AXP806_DCDC_MODE_CTRL2, &reg);
switch (id) {
case AXP806_DCDCB:
return (((reg & GENMASK(7, 6)) == BIT(6)) ||
((reg & GENMASK(7, 6)) == BIT(7)));
case AXP806_DCDCC:
return ((reg & GENMASK(7, 6)) == BIT(7));
case AXP806_DCDCE:
return !!(reg & BIT(5));
} }
return false; return false;
@ -540,6 +644,10 @@ static int axp20x_regulator_probe(struct platform_device *pdev)
drivevbus = of_property_read_bool(pdev->dev.parent->of_node, drivevbus = of_property_read_bool(pdev->dev.parent->of_node,
"x-powers,drive-vbus-en"); "x-powers,drive-vbus-en");
break; break;
case AXP803_ID:
regulators = axp803_regulators;
nregulators = AXP803_REG_ID_MAX;
break;
case AXP806_ID: case AXP806_ID:
regulators = axp806_regulators; regulators = axp806_regulators;
nregulators = AXP806_REG_ID_MAX; nregulators = AXP806_REG_ID_MAX;
@ -579,6 +687,7 @@ static int axp20x_regulator_probe(struct platform_device *pdev)
* name. * name.
*/ */
if ((regulators == axp22x_regulators && i == AXP22X_DC1SW) || if ((regulators == axp22x_regulators && i == AXP22X_DC1SW) ||
(regulators == axp803_regulators && i == AXP803_DC1SW) ||
(regulators == axp809_regulators && i == AXP809_DC1SW)) { (regulators == axp809_regulators && i == AXP809_DC1SW)) {
new_desc = devm_kzalloc(&pdev->dev, sizeof(*desc), new_desc = devm_kzalloc(&pdev->dev, sizeof(*desc),
GFP_KERNEL); GFP_KERNEL);

View File

@ -43,7 +43,7 @@ enum bd9571mwv_regulators { VD09, VD18, VD25, VD33, DVFS };
.linear_min_sel = _lmin, \ .linear_min_sel = _lmin, \
} }
int bd9571mwv_avs_get_moni_state(struct regulator_dev *rdev) static int bd9571mwv_avs_get_moni_state(struct regulator_dev *rdev)
{ {
unsigned int val; unsigned int val;
int ret; int ret;
@ -55,8 +55,8 @@ int bd9571mwv_avs_get_moni_state(struct regulator_dev *rdev)
return val & BD9571MWV_AVS_SET_MONI_MASK; return val & BD9571MWV_AVS_SET_MONI_MASK;
} }
int bd9571mwv_avs_set_voltage_sel_regmap(struct regulator_dev *rdev, static int bd9571mwv_avs_set_voltage_sel_regmap(struct regulator_dev *rdev,
unsigned int sel) unsigned int sel)
{ {
int ret; int ret;
@ -68,7 +68,7 @@ int bd9571mwv_avs_set_voltage_sel_regmap(struct regulator_dev *rdev,
rdev->desc->vsel_mask, sel); rdev->desc->vsel_mask, sel);
} }
int bd9571mwv_avs_get_voltage_sel_regmap(struct regulator_dev *rdev) static int bd9571mwv_avs_get_voltage_sel_regmap(struct regulator_dev *rdev)
{ {
unsigned int val; unsigned int val;
int ret; int ret;
@ -87,8 +87,8 @@ int bd9571mwv_avs_get_voltage_sel_regmap(struct regulator_dev *rdev)
return val; return val;
} }
int bd9571mwv_reg_set_voltage_sel_regmap(struct regulator_dev *rdev, static int bd9571mwv_reg_set_voltage_sel_regmap(struct regulator_dev *rdev,
unsigned int sel) unsigned int sel)
{ {
return regmap_write_bits(rdev->regmap, BD9571MWV_DVFS_SETVID, return regmap_write_bits(rdev->regmap, BD9571MWV_DVFS_SETVID,
rdev->desc->vsel_mask, sel); rdev->desc->vsel_mask, sel);

View File

@ -1462,7 +1462,7 @@ static struct regulator_dev *regulator_lookup_by_name(const char *name)
static struct regulator_dev *regulator_dev_lookup(struct device *dev, static struct regulator_dev *regulator_dev_lookup(struct device *dev,
const char *supply) const char *supply)
{ {
struct regulator_dev *r; struct regulator_dev *r = NULL;
struct device_node *node; struct device_node *node;
struct regulator_map *map; struct regulator_map *map;
const char *devname = NULL; const char *devname = NULL;
@ -1489,10 +1489,6 @@ static struct regulator_dev *regulator_dev_lookup(struct device *dev,
if (dev) if (dev)
devname = dev_name(dev); devname = dev_name(dev);
r = regulator_lookup_by_name(supply);
if (r)
return r;
mutex_lock(&regulator_list_mutex); mutex_lock(&regulator_list_mutex);
list_for_each_entry(map, &regulator_map_list, list) { list_for_each_entry(map, &regulator_map_list, list) {
/* If the mapping has a device set up it must match */ /* If the mapping has a device set up it must match */
@ -1508,6 +1504,10 @@ static struct regulator_dev *regulator_dev_lookup(struct device *dev,
} }
mutex_unlock(&regulator_list_mutex); mutex_unlock(&regulator_list_mutex);
if (r)
return r;
r = regulator_lookup_by_name(supply);
if (r) if (r)
return r; return r;
@ -2767,6 +2767,12 @@ static int _regulator_set_voltage_time(struct regulator_dev *rdev,
ramp_delay = rdev->desc->ramp_delay; ramp_delay = rdev->desc->ramp_delay;
else if (rdev->constraints->settling_time) else if (rdev->constraints->settling_time)
return rdev->constraints->settling_time; return rdev->constraints->settling_time;
else if (rdev->constraints->settling_time_up &&
(new_uV > old_uV))
return rdev->constraints->settling_time_up;
else if (rdev->constraints->settling_time_down &&
(new_uV < old_uV))
return rdev->constraints->settling_time_down;
if (ramp_delay == 0) { if (ramp_delay == 0) {
rdev_dbg(rdev, "ramp_delay not set\n"); rdev_dbg(rdev, "ramp_delay not set\n");
@ -2938,7 +2944,8 @@ static int regulator_set_voltage_unlocked(struct regulator *regulator,
if (rdev->supply && if (rdev->supply &&
regulator_ops_is_valid(rdev->supply->rdev, regulator_ops_is_valid(rdev->supply->rdev,
REGULATOR_CHANGE_VOLTAGE) && REGULATOR_CHANGE_VOLTAGE) &&
(rdev->desc->min_dropout_uV || !rdev->desc->ops->get_voltage)) { (rdev->desc->min_dropout_uV || !(rdev->desc->ops->get_voltage ||
rdev->desc->ops->get_voltage_sel))) {
int current_supply_uV; int current_supply_uV;
int selector; int selector;
@ -4311,41 +4318,31 @@ void *regulator_get_init_drvdata(struct regulator_init_data *reg_init_data)
EXPORT_SYMBOL_GPL(regulator_get_init_drvdata); EXPORT_SYMBOL_GPL(regulator_get_init_drvdata);
#ifdef CONFIG_DEBUG_FS #ifdef CONFIG_DEBUG_FS
static ssize_t supply_map_read_file(struct file *file, char __user *user_buf, static int supply_map_show(struct seq_file *sf, void *data)
size_t count, loff_t *ppos)
{ {
char *buf = kmalloc(PAGE_SIZE, GFP_KERNEL);
ssize_t len, ret = 0;
struct regulator_map *map; struct regulator_map *map;
if (!buf)
return -ENOMEM;
list_for_each_entry(map, &regulator_map_list, list) { list_for_each_entry(map, &regulator_map_list, list) {
len = snprintf(buf + ret, PAGE_SIZE - ret, seq_printf(sf, "%s -> %s.%s\n",
"%s -> %s.%s\n", rdev_get_name(map->regulator), map->dev_name,
rdev_get_name(map->regulator), map->dev_name, map->supply);
map->supply);
if (len >= 0)
ret += len;
if (ret > PAGE_SIZE) {
ret = PAGE_SIZE;
break;
}
} }
ret = simple_read_from_buffer(user_buf, count, ppos, buf, ret); return 0;
}
kfree(buf); static int supply_map_open(struct inode *inode, struct file *file)
{
return ret; return single_open(file, supply_map_show, inode->i_private);
} }
#endif #endif
static const struct file_operations supply_map_fops = { static const struct file_operations supply_map_fops = {
#ifdef CONFIG_DEBUG_FS #ifdef CONFIG_DEBUG_FS
.read = supply_map_read_file, .open = supply_map_open,
.llseek = default_llseek, .read = seq_read,
.llseek = seq_lseek,
.release = single_release,
#endif #endif
}; };

View File

@ -1,6 +1,6 @@
/* /*
* da9062-regulator.c - REGULATOR device driver for DA9062 * Regulator device driver for DA9061 and DA9062.
* Copyright (C) 2015 Dialog Semiconductor Ltd. * Copyright (C) 2015-2017 Dialog Semiconductor
* *
* This program is free software; you can redistribute it and/or * This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License * modify it under the terms of the GNU General Public License
@ -27,6 +27,17 @@
#include <linux/mfd/da9062/registers.h> #include <linux/mfd/da9062/registers.h>
/* Regulator IDs */ /* Regulator IDs */
enum {
DA9061_ID_BUCK1,
DA9061_ID_BUCK2,
DA9061_ID_BUCK3,
DA9061_ID_LDO1,
DA9061_ID_LDO2,
DA9061_ID_LDO3,
DA9061_ID_LDO4,
DA9061_MAX_REGULATORS,
};
enum { enum {
DA9062_ID_BUCK1, DA9062_ID_BUCK1,
DA9062_ID_BUCK2, DA9062_ID_BUCK2,
@ -88,15 +99,21 @@ enum {
/* Regulator operations */ /* Regulator operations */
/* Current limits array (in uA) BUCK1 and BUCK3. /* Current limits array (in uA)
Entry indexes corresponds to register values. */ * - DA9061_ID_[BUCK1|BUCK3]
* - DA9062_ID_[BUCK1|BUCK2|BUCK4]
* Entry indexes corresponds to register values.
*/
static const int da9062_buck_a_limits[] = { static const int da9062_buck_a_limits[] = {
500000, 600000, 700000, 800000, 900000, 1000000, 1100000, 1200000, 500000, 600000, 700000, 800000, 900000, 1000000, 1100000, 1200000,
1300000, 1400000, 1500000, 1600000, 1700000, 1800000, 1900000, 2000000 1300000, 1400000, 1500000, 1600000, 1700000, 1800000, 1900000, 2000000
}; };
/* Current limits array (in uA) for BUCK2. /* Current limits array (in uA)
Entry indexes corresponds to register values. */ * - DA9061_ID_BUCK2
* - DA9062_ID_BUCK3
* Entry indexes corresponds to register values.
*/
static const int da9062_buck_b_limits[] = { static const int da9062_buck_b_limits[] = {
1500000, 1600000, 1700000, 1800000, 1900000, 2000000, 2100000, 2200000, 1500000, 1600000, 1700000, 1800000, 1900000, 2000000, 2100000, 2200000,
2300000, 2400000, 2500000, 2600000, 2700000, 2800000, 2900000, 3000000 2300000, 2400000, 2500000, 2600000, 2700000, 2800000, 2900000, 3000000
@ -405,8 +422,254 @@ static const struct regulator_ops da9062_ldo_ops = {
.set_suspend_mode = da9062_ldo_set_suspend_mode, .set_suspend_mode = da9062_ldo_set_suspend_mode,
}; };
/* Regulator information */ /* DA9061 Regulator information */
static const struct da9062_regulator_info local_regulator_info[] = { static const struct da9062_regulator_info local_da9061_regulator_info[] = {
{
.desc.id = DA9061_ID_BUCK1,
.desc.name = "DA9061 BUCK1",
.desc.of_match = of_match_ptr("buck1"),
.desc.regulators_node = of_match_ptr("regulators"),
.desc.ops = &da9062_buck_ops,
.desc.min_uV = (300) * 1000,
.desc.uV_step = (10) * 1000,
.desc.n_voltages = ((1570) - (300))/(10) + 1,
.current_limits = da9062_buck_a_limits,
.n_current_limits = ARRAY_SIZE(da9062_buck_a_limits),
.desc.enable_reg = DA9062AA_BUCK1_CONT,
.desc.enable_mask = DA9062AA_BUCK1_EN_MASK,
.desc.vsel_reg = DA9062AA_VBUCK1_A,
.desc.vsel_mask = DA9062AA_VBUCK1_A_MASK,
.desc.linear_min_sel = 0,
.sleep = REG_FIELD(DA9062AA_VBUCK1_A,
__builtin_ffs((int)DA9062AA_BUCK1_SL_A_MASK) - 1,
sizeof(unsigned int) * 8 -
__builtin_clz((DA9062AA_BUCK1_SL_A_MASK)) - 1),
.suspend_sleep = REG_FIELD(DA9062AA_VBUCK1_B,
__builtin_ffs((int)DA9062AA_BUCK1_SL_B_MASK) - 1,
sizeof(unsigned int) * 8 -
__builtin_clz((DA9062AA_BUCK1_SL_B_MASK)) - 1),
.suspend_vsel_reg = DA9062AA_VBUCK1_B,
.mode = REG_FIELD(DA9062AA_BUCK1_CFG,
__builtin_ffs((int)DA9062AA_BUCK1_MODE_MASK) - 1,
sizeof(unsigned int) * 8 -
__builtin_clz((DA9062AA_BUCK1_MODE_MASK)) - 1),
.suspend = REG_FIELD(DA9062AA_DVC_1,
__builtin_ffs((int)DA9062AA_VBUCK1_SEL_MASK) - 1,
sizeof(unsigned int) * 8 -
__builtin_clz((DA9062AA_VBUCK1_SEL_MASK)) - 1),
.ilimit = REG_FIELD(DA9062AA_BUCK_ILIM_C,
__builtin_ffs((int)DA9062AA_BUCK1_ILIM_MASK) - 1,
sizeof(unsigned int) * 8 -
__builtin_clz((DA9062AA_BUCK1_ILIM_MASK)) - 1),
},
{
.desc.id = DA9061_ID_BUCK2,
.desc.name = "DA9061 BUCK2",
.desc.of_match = of_match_ptr("buck2"),
.desc.regulators_node = of_match_ptr("regulators"),
.desc.ops = &da9062_buck_ops,
.desc.min_uV = (800) * 1000,
.desc.uV_step = (20) * 1000,
.desc.n_voltages = ((3340) - (800))/(20) + 1,
.current_limits = da9062_buck_b_limits,
.n_current_limits = ARRAY_SIZE(da9062_buck_b_limits),
.desc.enable_reg = DA9062AA_BUCK3_CONT,
.desc.enable_mask = DA9062AA_BUCK3_EN_MASK,
.desc.vsel_reg = DA9062AA_VBUCK3_A,
.desc.vsel_mask = DA9062AA_VBUCK3_A_MASK,
.desc.linear_min_sel = 0,
.sleep = REG_FIELD(DA9062AA_VBUCK3_A,
__builtin_ffs((int)DA9062AA_BUCK3_SL_A_MASK) - 1,
sizeof(unsigned int) * 8 -
__builtin_clz((DA9062AA_BUCK3_SL_A_MASK)) - 1),
.suspend_sleep = REG_FIELD(DA9062AA_VBUCK3_B,
__builtin_ffs((int)DA9062AA_BUCK3_SL_B_MASK) - 1,
sizeof(unsigned int) * 8 -
__builtin_clz((DA9062AA_BUCK3_SL_B_MASK)) - 1),
.suspend_vsel_reg = DA9062AA_VBUCK3_B,
.mode = REG_FIELD(DA9062AA_BUCK3_CFG,
__builtin_ffs((int)DA9062AA_BUCK3_MODE_MASK) - 1,
sizeof(unsigned int) * 8 -
__builtin_clz((DA9062AA_BUCK3_MODE_MASK)) - 1),
.suspend = REG_FIELD(DA9062AA_DVC_1,
__builtin_ffs((int)DA9062AA_VBUCK3_SEL_MASK) - 1,
sizeof(unsigned int) * 8 -
__builtin_clz((DA9062AA_VBUCK3_SEL_MASK)) - 1),
.ilimit = REG_FIELD(DA9062AA_BUCK_ILIM_A,
__builtin_ffs((int)DA9062AA_BUCK3_ILIM_MASK) - 1,
sizeof(unsigned int) * 8 -
__builtin_clz((DA9062AA_BUCK3_ILIM_MASK)) - 1),
},
{
.desc.id = DA9061_ID_BUCK3,
.desc.name = "DA9061 BUCK3",
.desc.of_match = of_match_ptr("buck3"),
.desc.regulators_node = of_match_ptr("regulators"),
.desc.ops = &da9062_buck_ops,
.desc.min_uV = (530) * 1000,
.desc.uV_step = (10) * 1000,
.desc.n_voltages = ((1800) - (530))/(10) + 1,
.current_limits = da9062_buck_a_limits,
.n_current_limits = ARRAY_SIZE(da9062_buck_a_limits),
.desc.enable_reg = DA9062AA_BUCK4_CONT,
.desc.enable_mask = DA9062AA_BUCK4_EN_MASK,
.desc.vsel_reg = DA9062AA_VBUCK4_A,
.desc.vsel_mask = DA9062AA_VBUCK4_A_MASK,
.desc.linear_min_sel = 0,
.sleep = REG_FIELD(DA9062AA_VBUCK4_A,
__builtin_ffs((int)DA9062AA_BUCK4_SL_A_MASK) - 1,
sizeof(unsigned int) * 8 -
__builtin_clz((DA9062AA_BUCK4_SL_A_MASK)) - 1),
.suspend_sleep = REG_FIELD(DA9062AA_VBUCK4_B,
__builtin_ffs((int)DA9062AA_BUCK4_SL_B_MASK) - 1,
sizeof(unsigned int) * 8 -
__builtin_clz((DA9062AA_BUCK4_SL_B_MASK)) - 1),
.suspend_vsel_reg = DA9062AA_VBUCK4_B,
.mode = REG_FIELD(DA9062AA_BUCK4_CFG,
__builtin_ffs((int)DA9062AA_BUCK4_MODE_MASK) - 1,
sizeof(unsigned int) * 8 -
__builtin_clz((DA9062AA_BUCK4_MODE_MASK)) - 1),
.suspend = REG_FIELD(DA9062AA_DVC_1,
__builtin_ffs((int)DA9062AA_VBUCK4_SEL_MASK) - 1,
sizeof(unsigned int) * 8 -
__builtin_clz((DA9062AA_VBUCK4_SEL_MASK)) - 1),
.ilimit = REG_FIELD(DA9062AA_BUCK_ILIM_B,
__builtin_ffs((int)DA9062AA_BUCK4_ILIM_MASK) - 1,
sizeof(unsigned int) * 8 -
__builtin_clz((DA9062AA_BUCK4_ILIM_MASK)) - 1),
},
{
.desc.id = DA9061_ID_LDO1,
.desc.name = "DA9061 LDO1",
.desc.of_match = of_match_ptr("ldo1"),
.desc.regulators_node = of_match_ptr("regulators"),
.desc.ops = &da9062_ldo_ops,
.desc.min_uV = (900) * 1000,
.desc.uV_step = (50) * 1000,
.desc.n_voltages = ((3600) - (900))/(50) + 1,
.desc.enable_reg = DA9062AA_LDO1_CONT,
.desc.enable_mask = DA9062AA_LDO1_EN_MASK,
.desc.vsel_reg = DA9062AA_VLDO1_A,
.desc.vsel_mask = DA9062AA_VLDO1_A_MASK,
.desc.linear_min_sel = 0,
.sleep = REG_FIELD(DA9062AA_VLDO1_A,
__builtin_ffs((int)DA9062AA_LDO1_SL_A_MASK) - 1,
sizeof(unsigned int) * 8 -
__builtin_clz((DA9062AA_LDO1_SL_A_MASK)) - 1),
.suspend_sleep = REG_FIELD(DA9062AA_VLDO1_B,
__builtin_ffs((int)DA9062AA_LDO1_SL_B_MASK) - 1,
sizeof(unsigned int) * 8 -
__builtin_clz((DA9062AA_LDO1_SL_B_MASK)) - 1),
.suspend_vsel_reg = DA9062AA_VLDO1_B,
.suspend = REG_FIELD(DA9062AA_DVC_1,
__builtin_ffs((int)DA9062AA_VLDO1_SEL_MASK) - 1,
sizeof(unsigned int) * 8 -
__builtin_clz((DA9062AA_VLDO1_SEL_MASK)) - 1),
.oc_event = REG_FIELD(DA9062AA_STATUS_D,
__builtin_ffs((int)DA9062AA_LDO1_ILIM_MASK) - 1,
sizeof(unsigned int) * 8 -
__builtin_clz((DA9062AA_LDO1_ILIM_MASK)) - 1),
},
{
.desc.id = DA9061_ID_LDO2,
.desc.name = "DA9061 LDO2",
.desc.of_match = of_match_ptr("ldo2"),
.desc.regulators_node = of_match_ptr("regulators"),
.desc.ops = &da9062_ldo_ops,
.desc.min_uV = (900) * 1000,
.desc.uV_step = (50) * 1000,
.desc.n_voltages = ((3600) - (600))/(50) + 1,
.desc.enable_reg = DA9062AA_LDO2_CONT,
.desc.enable_mask = DA9062AA_LDO2_EN_MASK,
.desc.vsel_reg = DA9062AA_VLDO2_A,
.desc.vsel_mask = DA9062AA_VLDO2_A_MASK,
.desc.linear_min_sel = 0,
.sleep = REG_FIELD(DA9062AA_VLDO2_A,
__builtin_ffs((int)DA9062AA_LDO2_SL_A_MASK) - 1,
sizeof(unsigned int) * 8 -
__builtin_clz((DA9062AA_LDO2_SL_A_MASK)) - 1),
.suspend_sleep = REG_FIELD(DA9062AA_VLDO2_B,
__builtin_ffs((int)DA9062AA_LDO2_SL_B_MASK) - 1,
sizeof(unsigned int) * 8 -
__builtin_clz((DA9062AA_LDO2_SL_B_MASK)) - 1),
.suspend_vsel_reg = DA9062AA_VLDO2_B,
.suspend = REG_FIELD(DA9062AA_DVC_1,
__builtin_ffs((int)DA9062AA_VLDO2_SEL_MASK) - 1,
sizeof(unsigned int) * 8 -
__builtin_clz((DA9062AA_VLDO2_SEL_MASK)) - 1),
.oc_event = REG_FIELD(DA9062AA_STATUS_D,
__builtin_ffs((int)DA9062AA_LDO2_ILIM_MASK) - 1,
sizeof(unsigned int) * 8 -
__builtin_clz((DA9062AA_LDO2_ILIM_MASK)) - 1),
},
{
.desc.id = DA9061_ID_LDO3,
.desc.name = "DA9061 LDO3",
.desc.of_match = of_match_ptr("ldo3"),
.desc.regulators_node = of_match_ptr("regulators"),
.desc.ops = &da9062_ldo_ops,
.desc.min_uV = (900) * 1000,
.desc.uV_step = (50) * 1000,
.desc.n_voltages = ((3600) - (900))/(50) + 1,
.desc.enable_reg = DA9062AA_LDO3_CONT,
.desc.enable_mask = DA9062AA_LDO3_EN_MASK,
.desc.vsel_reg = DA9062AA_VLDO3_A,
.desc.vsel_mask = DA9062AA_VLDO3_A_MASK,
.desc.linear_min_sel = 0,
.sleep = REG_FIELD(DA9062AA_VLDO3_A,
__builtin_ffs((int)DA9062AA_LDO3_SL_A_MASK) - 1,
sizeof(unsigned int) * 8 -
__builtin_clz((DA9062AA_LDO3_SL_A_MASK)) - 1),
.suspend_sleep = REG_FIELD(DA9062AA_VLDO3_B,
__builtin_ffs((int)DA9062AA_LDO3_SL_B_MASK) - 1,
sizeof(unsigned int) * 8 -
__builtin_clz((DA9062AA_LDO3_SL_B_MASK)) - 1),
.suspend_vsel_reg = DA9062AA_VLDO3_B,
.suspend = REG_FIELD(DA9062AA_DVC_1,
__builtin_ffs((int)DA9062AA_VLDO3_SEL_MASK) - 1,
sizeof(unsigned int) * 8 -
__builtin_clz((DA9062AA_VLDO3_SEL_MASK)) - 1),
.oc_event = REG_FIELD(DA9062AA_STATUS_D,
__builtin_ffs((int)DA9062AA_LDO3_ILIM_MASK) - 1,
sizeof(unsigned int) * 8 -
__builtin_clz((DA9062AA_LDO3_ILIM_MASK)) - 1),
},
{
.desc.id = DA9061_ID_LDO4,
.desc.name = "DA9061 LDO4",
.desc.of_match = of_match_ptr("ldo4"),
.desc.regulators_node = of_match_ptr("regulators"),
.desc.ops = &da9062_ldo_ops,
.desc.min_uV = (900) * 1000,
.desc.uV_step = (50) * 1000,
.desc.n_voltages = ((3600) - (900))/(50) + 1,
.desc.enable_reg = DA9062AA_LDO4_CONT,
.desc.enable_mask = DA9062AA_LDO4_EN_MASK,
.desc.vsel_reg = DA9062AA_VLDO4_A,
.desc.vsel_mask = DA9062AA_VLDO4_A_MASK,
.desc.linear_min_sel = 0,
.sleep = REG_FIELD(DA9062AA_VLDO4_A,
__builtin_ffs((int)DA9062AA_LDO4_SL_A_MASK) - 1,
sizeof(unsigned int) * 8 -
__builtin_clz((DA9062AA_LDO4_SL_A_MASK)) - 1),
.suspend_sleep = REG_FIELD(DA9062AA_VLDO4_B,
__builtin_ffs((int)DA9062AA_LDO4_SL_B_MASK) - 1,
sizeof(unsigned int) * 8 -
__builtin_clz((DA9062AA_LDO4_SL_B_MASK)) - 1),
.suspend_vsel_reg = DA9062AA_VLDO4_B,
.suspend = REG_FIELD(DA9062AA_DVC_1,
__builtin_ffs((int)DA9062AA_VLDO4_SEL_MASK) - 1,
sizeof(unsigned int) * 8 -
__builtin_clz((DA9062AA_VLDO4_SEL_MASK)) - 1),
.oc_event = REG_FIELD(DA9062AA_STATUS_D,
__builtin_ffs((int)DA9062AA_LDO4_ILIM_MASK) - 1,
sizeof(unsigned int) * 8 -
__builtin_clz((DA9062AA_LDO4_ILIM_MASK)) - 1),
},
};
/* DA9062 Regulator information */
static const struct da9062_regulator_info local_da9062_regulator_info[] = {
{ {
.desc.id = DA9062_ID_BUCK1, .desc.id = DA9062_ID_BUCK1,
.desc.name = "DA9062 BUCK1", .desc.name = "DA9062 BUCK1",
@ -727,17 +990,33 @@ static int da9062_regulator_probe(struct platform_device *pdev)
struct da9062_regulators *regulators; struct da9062_regulators *regulators;
struct da9062_regulator *regl; struct da9062_regulator *regl;
struct regulator_config config = { }; struct regulator_config config = { };
const struct da9062_regulator_info *rinfo;
int irq, n, ret; int irq, n, ret;
size_t size; size_t size;
int max_regulators;
switch (chip->chip_type) {
case COMPAT_TYPE_DA9061:
max_regulators = DA9061_MAX_REGULATORS;
rinfo = local_da9061_regulator_info;
break;
case COMPAT_TYPE_DA9062:
max_regulators = DA9062_MAX_REGULATORS;
rinfo = local_da9062_regulator_info;
break;
default:
dev_err(chip->dev, "Unrecognised chip type\n");
return -ENODEV;
}
/* Allocate memory required by usable regulators */ /* Allocate memory required by usable regulators */
size = sizeof(struct da9062_regulators) + size = sizeof(struct da9062_regulators) +
DA9062_MAX_REGULATORS * sizeof(struct da9062_regulator); max_regulators * sizeof(struct da9062_regulator);
regulators = devm_kzalloc(&pdev->dev, size, GFP_KERNEL); regulators = devm_kzalloc(&pdev->dev, size, GFP_KERNEL);
if (!regulators) if (!regulators)
return -ENOMEM; return -ENOMEM;
regulators->n_regulators = DA9062_MAX_REGULATORS; regulators->n_regulators = max_regulators;
platform_set_drvdata(pdev, regulators); platform_set_drvdata(pdev, regulators);
n = 0; n = 0;
@ -745,7 +1024,7 @@ static int da9062_regulator_probe(struct platform_device *pdev)
/* Initialise regulator structure */ /* Initialise regulator structure */
regl = &regulators->regulator[n]; regl = &regulators->regulator[n];
regl->hw = chip; regl->hw = chip;
regl->info = &local_regulator_info[n]; regl->info = &rinfo[n];
regl->desc = regl->info->desc; regl->desc = regl->info->desc;
regl->desc.type = REGULATOR_VOLTAGE; regl->desc.type = REGULATOR_VOLTAGE;
regl->desc.owner = THIS_MODULE; regl->desc.owner = THIS_MODULE;
@ -836,6 +1115,6 @@ module_exit(da9062_regulator_cleanup);
/* Module information */ /* Module information */
MODULE_AUTHOR("S Twiss <stwiss.opensource@diasemi.com>"); MODULE_AUTHOR("S Twiss <stwiss.opensource@diasemi.com>");
MODULE_DESCRIPTION("REGULATOR device driver for Dialog DA9062"); MODULE_DESCRIPTION("REGULATOR device driver for Dialog DA9062 and DA9061");
MODULE_LICENSE("GPL"); MODULE_LICENSE("GPL");
MODULE_ALIAS("platform:da9062-regulators"); MODULE_ALIAS("platform:da9062-regulators");

View File

@ -621,7 +621,14 @@ static int hi6421_regulator_probe(struct platform_device *pdev)
return 0; return 0;
} }
static const struct platform_device_id hi6421_regulator_table[] = {
{ .name = "hi6421-regulator" },
{},
};
MODULE_DEVICE_TABLE(platform, hi6421_regulator_table);
static struct platform_driver hi6421_regulator_driver = { static struct platform_driver hi6421_regulator_driver = {
.id_table = hi6421_regulator_table,
.driver = { .driver = {
.name = "hi6421-regulator", .name = "hi6421-regulator",
}, },

View File

@ -0,0 +1,214 @@
/*
* Device driver for regulators in Hi6421V530 IC
*
* Copyright (c) <2017> HiSilicon Technologies Co., Ltd.
* http://www.hisilicon.com
* Copyright (c) <2017> Linaro Ltd.
* http://www.linaro.org
*
* Author: Wang Xiaoyin <hw.wangxiaoyin@hisilicon.com>
* Guodong Xu <guodong.xu@linaro.org>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*/
#include <linux/mfd/hi6421-pmic.h>
#include <linux/module.h>
#include <linux/of.h>
#include <linux/platform_device.h>
#include <linux/regmap.h>
#include <linux/regulator/driver.h>
/*
* struct hi6421v530_regulator_info - hi6421v530 regulator information
* @desc: regulator description
* @mode_mask: ECO mode bitmask of LDOs; for BUCKs, this masks sleep
* @eco_microamp: eco mode load upper limit (in uA), valid for LDOs only
*/
struct hi6421v530_regulator_info {
struct regulator_desc rdesc;
u8 mode_mask;
u32 eco_microamp;
};
/* HI6421v530 regulators */
enum hi6421v530_regulator_id {
HI6421V530_LDO3,
HI6421V530_LDO9,
HI6421V530_LDO11,
HI6421V530_LDO15,
HI6421V530_LDO16,
};
static const unsigned int ldo_3_voltages[] = {
1800000, 1825000, 1850000, 1875000,
1900000, 1925000, 1950000, 1975000,
2000000, 2025000, 2050000, 2075000,
2100000, 2125000, 2150000, 2200000,
};
static const unsigned int ldo_9_11_voltages[] = {
1750000, 1800000, 1825000, 2800000,
2850000, 2950000, 3000000, 3300000,
};
static const unsigned int ldo_15_16_voltages[] = {
1750000, 1800000, 2400000, 2600000,
2700000, 2850000, 2950000, 3000000,
};
static const struct regulator_ops hi6421v530_ldo_ops;
#define HI6421V530_LDO_ENABLE_TIME (350)
/*
* _id - LDO id name string
* v_table - voltage table
* vreg - voltage select register
* vmask - voltage select mask
* ereg - enable register
* emask - enable mask
* odelay - off/on delay time in uS
* ecomask - eco mode mask
* ecoamp - eco mode load uppler limit in uA
*/
#define HI6421V530_LDO(_ID, v_table, vreg, vmask, ereg, emask, \
odelay, ecomask, ecoamp) { \
.rdesc = { \
.name = #_ID, \
.of_match = of_match_ptr(#_ID), \
.regulators_node = of_match_ptr("regulators"), \
.ops = &hi6421v530_ldo_ops, \
.type = REGULATOR_VOLTAGE, \
.id = HI6421V530_##_ID, \
.owner = THIS_MODULE, \
.n_voltages = ARRAY_SIZE(v_table), \
.volt_table = v_table, \
.vsel_reg = HI6421_REG_TO_BUS_ADDR(vreg), \
.vsel_mask = vmask, \
.enable_reg = HI6421_REG_TO_BUS_ADDR(ereg), \
.enable_mask = emask, \
.enable_time = HI6421V530_LDO_ENABLE_TIME, \
.off_on_delay = odelay, \
}, \
.mode_mask = ecomask, \
.eco_microamp = ecoamp, \
}
/* HI6421V530 regulator information */
static struct hi6421v530_regulator_info hi6421v530_regulator_info[] = {
HI6421V530_LDO(LDO3, ldo_3_voltages, 0x061, 0xf, 0x060, 0x2,
20000, 0x6, 8000),
HI6421V530_LDO(LDO9, ldo_9_11_voltages, 0x06b, 0x7, 0x06a, 0x2,
40000, 0x6, 8000),
HI6421V530_LDO(LDO11, ldo_9_11_voltages, 0x06f, 0x7, 0x06e, 0x2,
40000, 0x6, 8000),
HI6421V530_LDO(LDO15, ldo_15_16_voltages, 0x077, 0x7, 0x076, 0x2,
40000, 0x6, 8000),
HI6421V530_LDO(LDO16, ldo_15_16_voltages, 0x079, 0x7, 0x078, 0x2,
40000, 0x6, 8000),
};
static unsigned int hi6421v530_regulator_ldo_get_mode(
struct regulator_dev *rdev)
{
struct hi6421v530_regulator_info *info;
unsigned int reg_val;
info = rdev_get_drvdata(rdev);
regmap_read(rdev->regmap, rdev->desc->enable_reg, &reg_val);
if (reg_val & (info->mode_mask))
return REGULATOR_MODE_IDLE;
return REGULATOR_MODE_NORMAL;
}
static int hi6421v530_regulator_ldo_set_mode(struct regulator_dev *rdev,
unsigned int mode)
{
struct hi6421v530_regulator_info *info;
unsigned int new_mode;
info = rdev_get_drvdata(rdev);
switch (mode) {
case REGULATOR_MODE_NORMAL:
new_mode = 0;
break;
case REGULATOR_MODE_IDLE:
new_mode = info->mode_mask;
break;
default:
return -EINVAL;
}
regmap_update_bits(rdev->regmap, rdev->desc->enable_reg,
info->mode_mask, new_mode);
return 0;
}
static const struct regulator_ops hi6421v530_ldo_ops = {
.is_enabled = regulator_is_enabled_regmap,
.enable = regulator_enable_regmap,
.disable = regulator_disable_regmap,
.list_voltage = regulator_list_voltage_table,
.map_voltage = regulator_map_voltage_ascend,
.get_voltage_sel = regulator_get_voltage_sel_regmap,
.set_voltage_sel = regulator_set_voltage_sel_regmap,
.get_mode = hi6421v530_regulator_ldo_get_mode,
.set_mode = hi6421v530_regulator_ldo_set_mode,
};
static int hi6421v530_regulator_probe(struct platform_device *pdev)
{
struct hi6421_pmic *pmic;
struct regulator_dev *rdev;
struct regulator_config config = { };
unsigned int i;
pmic = dev_get_drvdata(pdev->dev.parent);
if (!pmic) {
dev_err(&pdev->dev, "no pmic in the regulator parent node\n");
return -ENODEV;
}
for (i = 0; i < ARRAY_SIZE(hi6421v530_regulator_info); i++) {
config.dev = pdev->dev.parent;
config.regmap = pmic->regmap;
config.driver_data = &hi6421v530_regulator_info[i];
rdev = devm_regulator_register(&pdev->dev,
&hi6421v530_regulator_info[i].rdesc,
&config);
if (IS_ERR(rdev)) {
dev_err(&pdev->dev, "failed to register regulator %s\n",
hi6421v530_regulator_info[i].rdesc.name);
return PTR_ERR(rdev);
}
}
return 0;
}
static const struct platform_device_id hi6421v530_regulator_table[] = {
{ .name = "hi6421v530-regulator" },
{},
};
MODULE_DEVICE_TABLE(platform, hi6421v530_regulator_table);
static struct platform_driver hi6421v530_regulator_driver = {
.id_table = hi6421v530_regulator_table,
.driver = {
.name = "hi6421v530-regulator",
},
.probe = hi6421v530_regulator_probe,
};
module_platform_driver(hi6421v530_regulator_driver);
MODULE_AUTHOR("Wang Xiaoyin <hw.wangxiaoyin@hisilicon.com>");
MODULE_DESCRIPTION("Hi6421v530 regulator driver");
MODULE_LICENSE("GPL v2");

View File

@ -99,7 +99,7 @@ static int lp8755_buck_enable_time(struct regulator_dev *rdev)
ret = lp8755_read(pchip, 0x12 + id, &regval); ret = lp8755_read(pchip, 0x12 + id, &regval);
if (ret < 0) { if (ret < 0) {
dev_err(pchip->dev, "i2c acceess error %s\n", __func__); dev_err(pchip->dev, "i2c access error %s\n", __func__);
return ret; return ret;
} }
return (regval & 0xff) * 100; return (regval & 0xff) * 100;
@ -144,7 +144,7 @@ static int lp8755_buck_set_mode(struct regulator_dev *rdev, unsigned int mode)
goto err_i2c; goto err_i2c;
return ret; return ret;
err_i2c: err_i2c:
dev_err(pchip->dev, "i2c acceess error %s\n", __func__); dev_err(pchip->dev, "i2c access error %s\n", __func__);
return ret; return ret;
} }
@ -175,7 +175,7 @@ static unsigned int lp8755_buck_get_mode(struct regulator_dev *rdev)
return REGULATOR_MODE_NORMAL; return REGULATOR_MODE_NORMAL;
err_i2c: err_i2c:
dev_err(pchip->dev, "i2c acceess error %s\n", __func__); dev_err(pchip->dev, "i2c access error %s\n", __func__);
return 0; return 0;
} }
@ -223,7 +223,7 @@ static int lp8755_buck_set_ramp(struct regulator_dev *rdev, int ramp)
goto err_i2c; goto err_i2c;
return ret; return ret;
err_i2c: err_i2c:
dev_err(pchip->dev, "i2c acceess error %s\n", __func__); dev_err(pchip->dev, "i2c access error %s\n", __func__);
return ret; return ret;
} }
@ -295,7 +295,7 @@ static int lp8755_init_data(struct lp8755_chip *pchip)
return ret; return ret;
out_i2c_error: out_i2c_error:
dev_err(pchip->dev, "i2c acceess error %s\n", __func__); dev_err(pchip->dev, "i2c access error %s\n", __func__);
return ret; return ret;
} }
@ -404,7 +404,7 @@ static irqreturn_t lp8755_irq_handler(int irq, void *data)
return IRQ_HANDLED; return IRQ_HANDLED;
err_i2c: err_i2c:
dev_err(pchip->dev, "i2c acceess error %s\n", __func__); dev_err(pchip->dev, "i2c access error %s\n", __func__);
return IRQ_NONE; return IRQ_NONE;
} }
@ -420,7 +420,7 @@ static int lp8755_int_config(struct lp8755_chip *pchip)
ret = lp8755_read(pchip, 0x0F, &regval); ret = lp8755_read(pchip, 0x0F, &regval);
if (ret < 0) { if (ret < 0) {
dev_err(pchip->dev, "i2c acceess error %s\n", __func__); dev_err(pchip->dev, "i2c access error %s\n", __func__);
return ret; return ret;
} }

View File

@ -0,0 +1,236 @@
/*
* Regulator driver for LP87565 PMIC
*
* Copyright (C) 2017 Texas Instruments Incorporated - http://www.ti.com/
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* Free Software Foundation version 2.
*/
#include <linux/module.h>
#include <linux/platform_device.h>
#include <linux/regmap.h>
#include <linux/mfd/lp87565.h>
#define LP87565_REGULATOR(_name, _id, _of, _ops, _n, _vr, _vm, _er, _em, \
_delay, _lr, _cr) \
[_id] = { \
.desc = { \
.name = _name, \
.supply_name = _of "-in", \
.id = _id, \
.of_match = of_match_ptr(_of), \
.regulators_node = of_match_ptr("regulators"),\
.ops = &_ops, \
.n_voltages = _n, \
.type = REGULATOR_VOLTAGE, \
.owner = THIS_MODULE, \
.vsel_reg = _vr, \
.vsel_mask = _vm, \
.enable_reg = _er, \
.enable_mask = _em, \
.ramp_delay = _delay, \
.linear_ranges = _lr, \
.n_linear_ranges = ARRAY_SIZE(_lr), \
}, \
.ctrl2_reg = _cr, \
}
struct lp87565_regulator {
struct regulator_desc desc;
unsigned int ctrl2_reg;
};
static const struct lp87565_regulator regulators[];
static const struct regulator_linear_range buck0_1_2_3_ranges[] = {
REGULATOR_LINEAR_RANGE(600000, 0xA, 0x17, 10000),
REGULATOR_LINEAR_RANGE(735000, 0x18, 0x9d, 5000),
REGULATOR_LINEAR_RANGE(1420000, 0x9e, 0xff, 20000),
};
static unsigned int lp87565_buck_ramp_delay[] = {
30000, 15000, 10000, 7500, 3800, 1900, 940, 470
};
/* LP87565 BUCK current limit */
static const unsigned int lp87565_buck_uA[] = {
1500000, 2000000, 2500000, 3000000, 3500000, 4000000, 4500000, 5000000,
};
static int lp87565_buck_set_ramp_delay(struct regulator_dev *rdev,
int ramp_delay)
{
int id = rdev_get_id(rdev);
struct lp87565 *lp87565 = rdev_get_drvdata(rdev);
unsigned int reg;
int ret;
if (ramp_delay <= 470)
reg = 7;
else if (ramp_delay <= 940)
reg = 6;
else if (ramp_delay <= 1900)
reg = 5;
else if (ramp_delay <= 3800)
reg = 4;
else if (ramp_delay <= 7500)
reg = 3;
else if (ramp_delay <= 10000)
reg = 2;
else if (ramp_delay <= 15000)
reg = 1;
else
reg = 0;
ret = regmap_update_bits(lp87565->regmap, regulators[id].ctrl2_reg,
LP87565_BUCK_CTRL_2_SLEW_RATE,
reg << __ffs(LP87565_BUCK_CTRL_2_SLEW_RATE));
if (ret) {
dev_err(lp87565->dev, "SLEW RATE write failed: %d\n", ret);
return ret;
}
rdev->constraints->ramp_delay = lp87565_buck_ramp_delay[reg];
return 0;
}
static int lp87565_buck_set_current_limit(struct regulator_dev *rdev,
int min_uA, int max_uA)
{
int id = rdev_get_id(rdev);
struct lp87565 *lp87565 = rdev_get_drvdata(rdev);
int i;
for (i = ARRAY_SIZE(lp87565_buck_uA) - 1; i >= 0; i--) {
if (lp87565_buck_uA[i] >= min_uA &&
lp87565_buck_uA[i] <= max_uA)
return regmap_update_bits(lp87565->regmap,
regulators[id].ctrl2_reg,
LP87565_BUCK_CTRL_2_ILIM,
i << __ffs(LP87565_BUCK_CTRL_2_ILIM));
}
return -EINVAL;
}
static int lp87565_buck_get_current_limit(struct regulator_dev *rdev)
{
int id = rdev_get_id(rdev);
struct lp87565 *lp87565 = rdev_get_drvdata(rdev);
int ret;
unsigned int val;
ret = regmap_read(lp87565->regmap, regulators[id].ctrl2_reg, &val);
if (ret)
return ret;
val = (val & LP87565_BUCK_CTRL_2_ILIM) >>
__ffs(LP87565_BUCK_CTRL_2_ILIM);
return (val < ARRAY_SIZE(lp87565_buck_uA)) ?
lp87565_buck_uA[val] : -EINVAL;
}
/* Operations permitted on BUCK0, BUCK1 */
static struct regulator_ops lp87565_buck_ops = {
.is_enabled = regulator_is_enabled_regmap,
.enable = regulator_enable_regmap,
.disable = regulator_disable_regmap,
.get_voltage_sel = regulator_get_voltage_sel_regmap,
.set_voltage_sel = regulator_set_voltage_sel_regmap,
.list_voltage = regulator_list_voltage_linear_range,
.map_voltage = regulator_map_voltage_linear_range,
.set_voltage_time_sel = regulator_set_voltage_time_sel,
.set_ramp_delay = lp87565_buck_set_ramp_delay,
.set_current_limit = lp87565_buck_set_current_limit,
.get_current_limit = lp87565_buck_get_current_limit,
};
static const struct lp87565_regulator regulators[] = {
LP87565_REGULATOR("BUCK0", LP87565_BUCK_0, "buck0", lp87565_buck_ops,
256, LP87565_REG_BUCK0_VOUT, LP87565_BUCK_VSET,
LP87565_REG_BUCK0_CTRL_1,
LP87565_BUCK_CTRL_1_EN, 3800,
buck0_1_2_3_ranges, LP87565_REG_BUCK0_CTRL_2),
LP87565_REGULATOR("BUCK1", LP87565_BUCK_1, "buck1", lp87565_buck_ops,
256, LP87565_REG_BUCK1_VOUT, LP87565_BUCK_VSET,
LP87565_REG_BUCK1_CTRL_1,
LP87565_BUCK_CTRL_1_EN, 3800,
buck0_1_2_3_ranges, LP87565_REG_BUCK1_CTRL_2),
LP87565_REGULATOR("BUCK2", LP87565_BUCK_2, "buck2", lp87565_buck_ops,
256, LP87565_REG_BUCK2_VOUT, LP87565_BUCK_VSET,
LP87565_REG_BUCK2_CTRL_1,
LP87565_BUCK_CTRL_1_EN, 3800,
buck0_1_2_3_ranges, LP87565_REG_BUCK2_CTRL_2),
LP87565_REGULATOR("BUCK3", LP87565_BUCK_3, "buck3", lp87565_buck_ops,
256, LP87565_REG_BUCK3_VOUT, LP87565_BUCK_VSET,
LP87565_REG_BUCK3_CTRL_1,
LP87565_BUCK_CTRL_1_EN, 3800,
buck0_1_2_3_ranges, LP87565_REG_BUCK3_CTRL_2),
LP87565_REGULATOR("BUCK10", LP87565_BUCK_10, "buck10", lp87565_buck_ops,
256, LP87565_REG_BUCK0_VOUT, LP87565_BUCK_VSET,
LP87565_REG_BUCK0_CTRL_1,
LP87565_BUCK_CTRL_1_EN, 3800,
buck0_1_2_3_ranges, LP87565_REG_BUCK0_CTRL_2),
LP87565_REGULATOR("BUCK23", LP87565_BUCK_23, "buck23", lp87565_buck_ops,
256, LP87565_REG_BUCK2_VOUT, LP87565_BUCK_VSET,
LP87565_REG_BUCK2_CTRL_1,
LP87565_BUCK_CTRL_1_EN, 3800,
buck0_1_2_3_ranges, LP87565_REG_BUCK2_CTRL_2),
};
static int lp87565_regulator_probe(struct platform_device *pdev)
{
struct lp87565 *lp87565 = dev_get_drvdata(pdev->dev.parent);
struct regulator_config config = { };
struct regulator_dev *rdev;
int i, min_idx = LP87565_BUCK_1, max_idx = LP87565_BUCK_3;
platform_set_drvdata(pdev, lp87565);
config.dev = &pdev->dev;
config.dev->of_node = lp87565->dev->of_node;
config.driver_data = lp87565;
config.regmap = lp87565->regmap;
if (lp87565->dev_type == LP87565_DEVICE_TYPE_LP87565_Q1) {
min_idx = LP87565_BUCK_10;
max_idx = LP87565_BUCK_23;
}
for (i = min_idx; i <= max_idx; i++) {
rdev = devm_regulator_register(&pdev->dev, &regulators[i].desc,
&config);
if (IS_ERR(rdev)) {
dev_err(lp87565->dev, "failed to register %s regulator\n",
pdev->name);
return PTR_ERR(rdev);
}
}
return 0;
}
static const struct platform_device_id lp87565_regulator_id_table[] = {
{ "lp87565-regulator", },
{ "lp87565-q1-regulator", },
{ /* sentinel */ }
};
MODULE_DEVICE_TABLE(platform, lp87565_regulator_id_table);
static struct platform_driver lp87565_regulator_driver = {
.driver = {
.name = "lp87565-pmic",
},
.probe = lp87565_regulator_probe,
.id_table = lp87565_regulator_id_table,
};
module_platform_driver(lp87565_regulator_driver);
MODULE_AUTHOR("J Keerthy <j-keerthy@ti.com>");
MODULE_DESCRIPTION("LP87565 voltage regulator driver");
MODULE_LICENSE("GPL v2");

View File

@ -428,12 +428,9 @@ static int max8997_set_voltage_charger_cv(struct regulator_dev *rdev,
if (max_uV < 4000000 || min_uV > 4350000) if (max_uV < 4000000 || min_uV > 4350000)
return -EINVAL; return -EINVAL;
if (min_uV <= 4000000) { if (min_uV <= 4000000)
if (max_uV >= 4000000) val = 0x1;
return -EINVAL; else if (min_uV <= 4200000 && max_uV >= 4200000)
else
val = 0x1;
} else if (min_uV <= 4200000 && max_uV >= 4200000)
val = 0x0; val = 0x0;
else { else {
lb = (min_uV - 4000001) / 20000 + 2; lb = (min_uV - 4000001) / 20000 + 2;

View File

@ -90,6 +90,25 @@ static void of_get_regulation_constraints(struct device_node *np,
if (!ret) if (!ret)
constraints->settling_time = pval; constraints->settling_time = pval;
ret = of_property_read_u32(np, "regulator-settling-time-up-us", &pval);
if (!ret)
constraints->settling_time_up = pval;
if (constraints->settling_time_up && constraints->settling_time) {
pr_warn("%s: ambiguous configuration for settling time, ignoring 'regulator-settling-time-up-us'\n",
np->name);
constraints->settling_time_up = 0;
}
ret = of_property_read_u32(np, "regulator-settling-time-down-us",
&pval);
if (!ret)
constraints->settling_time_down = pval;
if (constraints->settling_time_down && constraints->settling_time) {
pr_warn("%s: ambiguous configuration for settling time, ignoring 'regulator-settling-time-down-us'\n",
np->name);
constraints->settling_time_down = 0;
}
ret = of_property_read_u32(np, "regulator-enable-ramp-delay", &pval); ret = of_property_read_u32(np, "regulator-enable-ramp-delay", &pval);
if (!ret) if (!ret)
constraints->enable_time = pval; constraints->enable_time = pval;

View File

@ -263,6 +263,13 @@ static struct palmas_regs_info tps65917_regs_info[] = {
.ctrl_addr = TPS65917_SMPS5_CTRL, .ctrl_addr = TPS65917_SMPS5_CTRL,
.sleep_id = TPS65917_EXTERNAL_REQSTR_ID_SMPS5, .sleep_id = TPS65917_EXTERNAL_REQSTR_ID_SMPS5,
}, },
{
.name = "SMPS12",
.sname = "smps1-in",
.vsel_addr = TPS65917_SMPS1_VOLTAGE,
.ctrl_addr = TPS65917_SMPS1_CTRL,
.sleep_id = TPS65917_EXTERNAL_REQSTR_ID_SMPS12,
},
{ {
.name = "LDO1", .name = "LDO1",
.sname = "ldo1-in", .sname = "ldo1-in",
@ -367,6 +374,7 @@ static struct palmas_sleep_requestor_info tps65917_sleep_req_info[] = {
EXTERNAL_REQUESTOR_TPS65917(SMPS3, 1, 2), EXTERNAL_REQUESTOR_TPS65917(SMPS3, 1, 2),
EXTERNAL_REQUESTOR_TPS65917(SMPS4, 1, 3), EXTERNAL_REQUESTOR_TPS65917(SMPS4, 1, 3),
EXTERNAL_REQUESTOR_TPS65917(SMPS5, 1, 4), EXTERNAL_REQUESTOR_TPS65917(SMPS5, 1, 4),
EXTERNAL_REQUESTOR_TPS65917(SMPS12, 1, 5),
EXTERNAL_REQUESTOR_TPS65917(LDO1, 2, 0), EXTERNAL_REQUESTOR_TPS65917(LDO1, 2, 0),
EXTERNAL_REQUESTOR_TPS65917(LDO2, 2, 1), EXTERNAL_REQUESTOR_TPS65917(LDO2, 2, 1),
EXTERNAL_REQUESTOR_TPS65917(LDO3, 2, 2), EXTERNAL_REQUESTOR_TPS65917(LDO3, 2, 2),
@ -1305,7 +1313,8 @@ static int tps65917_smps_registration(struct palmas_pmic *pmic,
*/ */
desc = &pmic->desc[id]; desc = &pmic->desc[id];
desc->n_linear_ranges = 3; desc->n_linear_ranges = 3;
if ((id == TPS65917_REG_SMPS2) && pmic->smps12) if ((id == TPS65917_REG_SMPS2 || id == TPS65917_REG_SMPS1) &&
pmic->smps12)
continue; continue;
/* Initialise sleep/init values from platform data */ /* Initialise sleep/init values from platform data */
@ -1427,6 +1436,7 @@ static struct of_regulator_match tps65917_matches[] = {
{ .name = "smps3", }, { .name = "smps3", },
{ .name = "smps4", }, { .name = "smps4", },
{ .name = "smps5", }, { .name = "smps5", },
{ .name = "smps12",},
{ .name = "ldo1", }, { .name = "ldo1", },
{ .name = "ldo2", }, { .name = "ldo2", },
{ .name = "ldo3", }, { .name = "ldo3", },
@ -1455,7 +1465,7 @@ static struct palmas_pmic_driver_data palmas_ddata = {
static struct palmas_pmic_driver_data tps65917_ddata = { static struct palmas_pmic_driver_data tps65917_ddata = {
.smps_start = TPS65917_REG_SMPS1, .smps_start = TPS65917_REG_SMPS1,
.smps_end = TPS65917_REG_SMPS5, .smps_end = TPS65917_REG_SMPS12,
.ldo_begin = TPS65917_REG_LDO1, .ldo_begin = TPS65917_REG_LDO1,
.ldo_end = TPS65917_REG_LDO5, .ldo_end = TPS65917_REG_LDO5,
.max_reg = TPS65917_NUM_REGS, .max_reg = TPS65917_NUM_REGS,
@ -1491,7 +1501,7 @@ static int palmas_dt_to_pdata(struct device *dev,
} }
for (idx = 0; idx < ddata->max_reg; idx++) { for (idx = 0; idx < ddata->max_reg; idx++) {
static struct of_regulator_match *match; struct of_regulator_match *match;
struct palmas_reg_init *rinit; struct palmas_reg_init *rinit;
struct device_node *np; struct device_node *np;
@ -1643,8 +1653,10 @@ static int palmas_regulators_probe(struct platform_device *pdev)
if (ret) if (ret)
return ret; return ret;
if (reg & PALMAS_SMPS_CTRL_SMPS12_SMPS123_EN) if (reg & PALMAS_SMPS_CTRL_SMPS12_SMPS123_EN) {
pmic->smps123 = 1; pmic->smps123 = 1;
pmic->smps12 = 1;
}
if (reg & PALMAS_SMPS_CTRL_SMPS45_SMPS457_EN) if (reg & PALMAS_SMPS_CTRL_SMPS45_SMPS457_EN)
pmic->smps457 = 1; pmic->smps457 = 1;

View File

@ -1107,6 +1107,7 @@ static int tps65910_probe(struct platform_device *pdev)
switch (tps65910_chip_id(tps65910)) { switch (tps65910_chip_id(tps65910)) {
case TPS65910: case TPS65910:
BUILD_BUG_ON(TPS65910_NUM_REGS < ARRAY_SIZE(tps65910_regs));
pmic->get_ctrl_reg = &tps65910_get_ctrl_register; pmic->get_ctrl_reg = &tps65910_get_ctrl_register;
pmic->num_regulators = ARRAY_SIZE(tps65910_regs); pmic->num_regulators = ARRAY_SIZE(tps65910_regs);
pmic->ext_sleep_control = tps65910_ext_sleep_control; pmic->ext_sleep_control = tps65910_ext_sleep_control;
@ -1119,6 +1120,7 @@ static int tps65910_probe(struct platform_device *pdev)
DCDCCTRL_DCDCCKSYNC_MASK); DCDCCTRL_DCDCCKSYNC_MASK);
break; break;
case TPS65911: case TPS65911:
BUILD_BUG_ON(TPS65910_NUM_REGS < ARRAY_SIZE(tps65911_regs));
pmic->get_ctrl_reg = &tps65911_get_ctrl_register; pmic->get_ctrl_reg = &tps65911_get_ctrl_register;
pmic->num_regulators = ARRAY_SIZE(tps65911_regs); pmic->num_regulators = ARRAY_SIZE(tps65911_regs);
pmic->ext_sleep_control = tps65911_ext_sleep_control; pmic->ext_sleep_control = tps65911_ext_sleep_control;
@ -1144,8 +1146,7 @@ static int tps65910_probe(struct platform_device *pdev)
if (!pmic->rdev) if (!pmic->rdev)
return -ENOMEM; return -ENOMEM;
for (i = 0; i < pmic->num_regulators && i < TPS65910_NUM_REGS; for (i = 0; i < pmic->num_regulators; i++, info++) {
i++, info++) {
/* Register the regulators */ /* Register the regulators */
pmic->info[i] = info; pmic->info[i] = info;

View File

@ -119,6 +119,17 @@ enum axp20x_variants {
#define AXP806_BUS_ADDR_EXT 0xfe #define AXP806_BUS_ADDR_EXT 0xfe
#define AXP806_REG_ADDR_EXT 0xff #define AXP806_REG_ADDR_EXT 0xff
#define AXP803_POLYPHASE_CTRL 0x14
#define AXP803_FLDO1_V_OUT 0x1c
#define AXP803_FLDO2_V_OUT 0x1d
#define AXP803_DCDC1_V_OUT 0x20
#define AXP803_DCDC2_V_OUT 0x21
#define AXP803_DCDC3_V_OUT 0x22
#define AXP803_DCDC4_V_OUT 0x23
#define AXP803_DCDC5_V_OUT 0x24
#define AXP803_DCDC6_V_OUT 0x25
#define AXP803_DCDC_FREQ_CTRL 0x3b
/* Interrupt */ /* Interrupt */
#define AXP152_IRQ1_EN 0x40 #define AXP152_IRQ1_EN 0x40
#define AXP152_IRQ2_EN 0x41 #define AXP152_IRQ2_EN 0x41
@ -350,6 +361,32 @@ enum {
AXP809_REG_ID_MAX, AXP809_REG_ID_MAX,
}; };
enum {
AXP803_DCDC1 = 0,
AXP803_DCDC2,
AXP803_DCDC3,
AXP803_DCDC4,
AXP803_DCDC5,
AXP803_DCDC6,
AXP803_DC1SW,
AXP803_ALDO1,
AXP803_ALDO2,
AXP803_ALDO3,
AXP803_DLDO1,
AXP803_DLDO2,
AXP803_DLDO3,
AXP803_DLDO4,
AXP803_ELDO1,
AXP803_ELDO2,
AXP803_ELDO3,
AXP803_FLDO1,
AXP803_FLDO2,
AXP803_RTC_LDO,
AXP803_LDO_IO0,
AXP803_LDO_IO1,
AXP803_REG_ID_MAX,
};
/* IRQs */ /* IRQs */
enum { enum {
AXP152_IRQ_LDO0IN_CONNECT = 1, AXP152_IRQ_LDO0IN_CONNECT = 1,

View File

@ -250,6 +250,7 @@ enum tps65917_regulators {
TPS65917_REG_SMPS3, TPS65917_REG_SMPS3,
TPS65917_REG_SMPS4, TPS65917_REG_SMPS4,
TPS65917_REG_SMPS5, TPS65917_REG_SMPS5,
TPS65917_REG_SMPS12,
/* LDO regulators */ /* LDO regulators */
TPS65917_REG_LDO1, TPS65917_REG_LDO1,
TPS65917_REG_LDO2, TPS65917_REG_LDO2,
@ -317,6 +318,7 @@ enum tps65917_external_requestor_id {
TPS65917_EXTERNAL_REQSTR_ID_SMPS3, TPS65917_EXTERNAL_REQSTR_ID_SMPS3,
TPS65917_EXTERNAL_REQSTR_ID_SMPS4, TPS65917_EXTERNAL_REQSTR_ID_SMPS4,
TPS65917_EXTERNAL_REQSTR_ID_SMPS5, TPS65917_EXTERNAL_REQSTR_ID_SMPS5,
TPS65917_EXTERNAL_REQSTR_ID_SMPS12,
TPS65917_EXTERNAL_REQSTR_ID_LDO1, TPS65917_EXTERNAL_REQSTR_ID_LDO1,
TPS65917_EXTERNAL_REQSTR_ID_LDO2, TPS65917_EXTERNAL_REQSTR_ID_LDO2,
TPS65917_EXTERNAL_REQSTR_ID_LDO3, TPS65917_EXTERNAL_REQSTR_ID_LDO3,

View File

@ -879,7 +879,7 @@ struct tps65910_board {
bool en_ck32k_xtal; bool en_ck32k_xtal;
bool en_dev_slp; bool en_dev_slp;
bool pm_off; bool pm_off;
struct tps65910_sleep_keepon_data *slp_keepon; struct tps65910_sleep_keepon_data slp_keepon;
bool en_gpio_sleep[TPS6591X_MAX_NUM_GPIO]; bool en_gpio_sleep[TPS6591X_MAX_NUM_GPIO];
unsigned long regulator_ext_sleep_control[TPS65910_NUM_REGS]; unsigned long regulator_ext_sleep_control[TPS65910_NUM_REGS];
struct regulator_init_data *tps65910_pmic_init_data[TPS65910_NUM_REGS]; struct regulator_init_data *tps65910_pmic_init_data[TPS65910_NUM_REGS];

View File

@ -110,6 +110,10 @@ struct regulator_state {
* @ramp_delay: Time to settle down after voltage change (unit: uV/us) * @ramp_delay: Time to settle down after voltage change (unit: uV/us)
* @settling_time: Time to settle down after voltage change when voltage * @settling_time: Time to settle down after voltage change when voltage
* change is non-linear (unit: microseconds). * change is non-linear (unit: microseconds).
* @settling_time_up: Time to settle down after voltage increase when voltage
* change is non-linear (unit: microseconds).
* @settling_time_down : Time to settle down after voltage decrease when
* voltage change is non-linear (unit: microseconds).
* @active_discharge: Enable/disable active discharge. The enum * @active_discharge: Enable/disable active discharge. The enum
* regulator_active_discharge values are used for * regulator_active_discharge values are used for
* initialisation. * initialisation.
@ -152,6 +156,8 @@ struct regulation_constraints {
unsigned int ramp_delay; unsigned int ramp_delay;
unsigned int settling_time; unsigned int settling_time;
unsigned int settling_time_up;
unsigned int settling_time_down;
unsigned int enable_time; unsigned int enable_time;
unsigned int active_discharge; unsigned int active_discharge;