From f5eebc792559d33ddf973f640f7570d042e3bbe8 Mon Sep 17 00:00:00 2001 From: Olliver Schinagl Date: Wed, 21 Nov 2018 20:05:28 +0200 Subject: power: axp209: Define the chip version mask Use a define for the chip version mask on the axp209. Signed-off-by: Olliver Schinagl Signed-off-by: Priit Laes Acked-by: Maxime Ripard --- drivers/power/axp209.c | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) (limited to 'drivers/power/axp209.c') diff --git a/drivers/power/axp209.c b/drivers/power/axp209.c index 6de5ec68258..e13c762a810 100644 --- a/drivers/power/axp209.c +++ b/drivers/power/axp209.c @@ -153,10 +153,7 @@ int axp_init(void) if (rc) return rc; - /* Low 4 bits is chip version */ - ver &= 0x0f; - - if (ver != 0x1) + if ((ver & AXP209_CHIP_VERSION_MASK) != 0x1) return -EINVAL; /* Mask all interrupts */ -- cgit v1.2.3 From 3f7d76a7ed92e75ff30c7e6287eca71f09da0bcf Mon Sep 17 00:00:00 2001 From: Olliver Schinagl Date: Wed, 21 Nov 2018 20:05:29 +0200 Subject: power: axp209: Reduce magic values by adding defines for LDO[234] The AXP209 has a few 'magisc-ish' values that are better served with clear defines. Signed-off-by: Olliver Schinagl Signed-off-by: Priit Laes Acked-by: Maxime Ripard --- drivers/power/axp209.c | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) (limited to 'drivers/power/axp209.c') diff --git a/drivers/power/axp209.c b/drivers/power/axp209.c index e13c762a810..819b168a84b 100644 --- a/drivers/power/axp209.c +++ b/drivers/power/axp209.c @@ -81,8 +81,7 @@ int axp_set_aldo2(unsigned int mvolt) if (rc) return rc; - /* LDO2 configuration is in upper 4 bits */ - reg = (reg & 0x0f) | (cfg << 4); + reg |= AXP209_LDO24_LDO2_SET(reg, cfg); rc = pmic_bus_write(AXP209_LDO24_VOLTAGE, reg); if (rc) return rc; @@ -99,10 +98,12 @@ int axp_set_aldo3(unsigned int mvolt) return pmic_bus_clrbits(AXP209_OUTPUT_CTRL, AXP209_OUTPUT_CTRL_LDO3); - if (mvolt == -1) - cfg = 0x80; /* determined by LDO3IN pin */ - else + if (mvolt == -1) { + cfg = AXP209_LDO3_VOLTAGE_FROM_LDO3IN; + } else { cfg = axp209_mvolt_to_cfg(mvolt, 700, 3500, 25); + cfg = AXP209_LDO3_VOLTAGE_SET(cfg); + } rc = pmic_bus_write(AXP209_LDO3_VOLTAGE, cfg); if (rc) @@ -131,8 +132,7 @@ int axp_set_aldo4(unsigned int mvolt) if (rc) return rc; - /* LDO4 configuration is in lower 4 bits */ - reg = (reg & 0xf0) | (cfg << 0); + reg |= AXP209_LDO24_LDO4_SET(reg, cfg); rc = pmic_bus_write(AXP209_LDO24_VOLTAGE, reg); if (rc) return rc; -- cgit v1.2.3 From 61436d502b33854ddf33797670d4e25c0d79d540 Mon Sep 17 00:00:00 2001 From: Olliver Schinagl Date: Wed, 21 Nov 2018 20:05:30 +0200 Subject: power: axp209: Add support for voltage rate control on LDO3 The AXP209 LDO3 regulator supports voltage rate control, or can set a slew rate. This allows for the power to gradually rise up to the desired voltage, instead of spiking up as fast as possible. Reason to have this can be to reduce the inrush currents for example. There are 3 slopes to choose from, the default, 'none' is a voltage rise of 0.0167 V/uS, a 1.6 mV/uS and a 0.8 mV/uS voltage rise. In ideal world (where vendors follow the recommended design guidelines) this setting should not be enabled by default. Unless of course AXP209 crashes instead of reporting overcurrent condition as it normally should do in this case. Signed-off-by: Olliver Schinagl Signed-off-by: Priit Laes Acked-by: Maxime Ripard --- drivers/power/axp209.c | 24 ++++++++++++++++++++++++ 1 file changed, 24 insertions(+) (limited to 'drivers/power/axp209.c') diff --git a/drivers/power/axp209.c b/drivers/power/axp209.c index 819b168a84b..cf138fc7227 100644 --- a/drivers/power/axp209.c +++ b/drivers/power/axp209.c @@ -9,6 +9,16 @@ #include #include +#ifdef CONFIG_AXP_ALDO3_VOLT_SLOPE_08 +# define AXP209_VRC_SLOPE AXP209_VRC_LDO3_800uV_uS +#endif +#ifdef CONFIG_AXP_ALDO3_VOLT_SLOPE_16 +# define AXP209_VRC_SLOPE AXP209_VRC_LDO3_1600uV_uS +#endif +#if defined CONFIG_AXP_ALDO3_VOLT_SLOPE_NONE || !defined AXP209_VRC_SLOPE +# define AXP209_VRC_SLOPE 0x00 +#endif + static u8 axp209_mvolt_to_cfg(int mvolt, int min, int max, int div) { if (mvolt < min) @@ -98,6 +108,20 @@ int axp_set_aldo3(unsigned int mvolt) return pmic_bus_clrbits(AXP209_OUTPUT_CTRL, AXP209_OUTPUT_CTRL_LDO3); + /* + * Some boards have trouble reaching the target voltage without causing + * great inrush currents. To prevent this, boards can enable a certain + * slope to ramp up voltage. Note, this only works when changing an + * already active power rail. When toggling power on, the AXP ramps up + * steeply at 0.0167 V/uS. + */ + rc = pmic_bus_read(AXP209_VRC_DCDC2_LDO3, &cfg); + cfg = AXP209_VRC_LDO3_SLOPE_SET(cfg, AXP209_VRC_SLOPE); + rc |= pmic_bus_write(AXP209_VRC_DCDC2_LDO3, cfg); + + if (rc) + return rc; + if (mvolt == -1) { cfg = AXP209_LDO3_VOLTAGE_FROM_LDO3IN; } else { -- cgit v1.2.3 From ef52605ebeb4fa2a97454ab225db6514519427fb Mon Sep 17 00:00:00 2001 From: Olliver Schinagl Date: Wed, 21 Nov 2018 20:05:31 +0200 Subject: power: axp209: Limit inrush current for broken boards Some boards feature a capacitance on LDO3's output that is too large, causing inrush currents which as a result, shut down the AXP209. This has been reported before, without knowing the actual cause. A fix appeared to be done with commit 0e6e34ac8dbb ("sunxi: Olimex A20 boards: Enable LDO3 and LDO4 regulators"). The description there is a bit misleading, the kernel does not hang during AXP209 initialization, the PMIC shuts down, causing voltages to drop and thus the whole system freezes. While the AXP209 does have the ability to ramp up the voltage slowly, to reduce these inrush currents, the voltage rate control (VRC) however is not applicable when switching on the LDO3 output. Only when going from an enabled lower voltage setting, to a higher voltage setting is the VRC in effect. To work around this problem, we set LDO3 to the lowest possible setting of 0.7 V if it was not yet enabled, and then let the VRC (if enabled) do its thing. It should be noted, that for some undocumented reason, there is a short delay needed between setting the LDO3 voltage register and enabling the power. One would expect that this delay ought to be just after enabling the output power at 0.7 V, but this did not work. Signed-off-by: Olliver Schinagl Signed-off-by: Priit Laes Acked-by: Maxime Ripard --- drivers/power/axp209.c | 23 +++++++++++++++++++++++ 1 file changed, 23 insertions(+) (limited to 'drivers/power/axp209.c') diff --git a/drivers/power/axp209.c b/drivers/power/axp209.c index cf138fc7227..67b420910c9 100644 --- a/drivers/power/axp209.c +++ b/drivers/power/axp209.c @@ -122,6 +122,29 @@ int axp_set_aldo3(unsigned int mvolt) if (rc) return rc; +#ifdef CONFIG_AXP_ALDO3_INRUSH_QUIRK + /* + * On some boards, LDO3 has a too big capacitor installed. When + * turning on LDO3, this causes the AXP209 to shutdown on + * voltages over 1.9 volt. As a workaround, we enable LDO3 + * first with the lowest possible voltage. If this still causes + * high inrush currents, the voltage slope should be increased. + */ + rc = pmic_bus_read(AXP209_OUTPUT_CTRL, &cfg); + if (rc) + return rc; + + if (!(cfg & AXP209_OUTPUT_CTRL_LDO3)) { + rc = pmic_bus_write(AXP209_LDO3_VOLTAGE, 0x0); /* 0.7 Volt */ + mdelay(1); + rc |= pmic_bus_setbits(AXP209_OUTPUT_CTRL, + AXP209_OUTPUT_CTRL_LDO3); + + if (rc) + return rc; + } +#endif + if (mvolt == -1) { cfg = AXP209_LDO3_VOLTAGE_FROM_LDO3IN; } else { -- cgit v1.2.3