power: axp209: Add support for voltage rate control on LDO3
authorOlliver Schinagl <oliver@schinagl.nl>
Wed, 21 Nov 2018 18:05:30 +0000 (20:05 +0200)
committerJagan Teki <jagan@amarulasolutions.com>
Fri, 7 Dec 2018 16:54:33 +0000 (22:24 +0530)
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 <oliver@schinagl.nl>
Signed-off-by: Priit Laes <plaes@plaes.org>
Acked-by: Maxime Ripard <maxime.ripard@bootlin.com>
drivers/power/Kconfig
drivers/power/axp209.c
include/axp209.h

index 1a3852442a8b2f3d61dc3326731c6ad66fb880ad..e83036fd66082a66f44198edc1889cf492a16159 100644 (file)
@@ -197,6 +197,40 @@ config AXP_ALDO3_VOLT
        On A83T / H8 boards aldo3 is AVCC, VCC-PL, and VCC-LED, and should be
        3.0V.
 
+choice
+       prompt "axp pmic (a)ldo3 voltage rate control"
+       depends on AXP209_POWER
+       default AXP_ALDO3_VOLT_SLOPE_NONE
+       ---help---
+       The AXP can slowly ramp up voltage to reduce the inrush current when
+       changing voltages.
+       Note, this does not apply when enabling/disabling LDO3. See
+       "axp pmic (a)ldo3 inrush quirk" below to enable a slew rate to limit
+       inrush current on broken board designs.
+
+config AXP_ALDO3_VOLT_SLOPE_NONE
+       bool "No voltage slope"
+       ---help---
+       Tries to reach the next voltage setting near instantaneously. Measurements
+       indicate that this is about 0.0167 V/uS.
+
+config AXP_ALDO3_VOLT_SLOPE_16
+       bool "1.6 mV per uS"
+       ---help---
+       Increases the voltage by 1.6 mV per uS until the final voltage has
+       been reached. Note that the scaling is in 25 mV steps and thus
+       the slew rate in reality is about 25 mV/31.250 uS.
+
+config AXP_ALDO3_VOLT_SLOPE_08
+       bool "0.8 mV per uS"
+       ---help---
+       Increases the voltage by 0.8 mV per uS until the final voltage has
+       been reached. Note that the scaling is in 25 mV steps however and thus
+       the slew rate in reality is about 25 mV/15.625 uS.
+       This is the slowest supported rate.
+
+endchoice
+
 config AXP_ALDO4_VOLT
        int "axp pmic (a)ldo4 voltage"
        depends on AXP209_POWER
index 819b168a84b101866a11cf1dc9f968997fcbc0b1..cf138fc7227391c70dc6b30a0c1deb304fc4e2aa 100644 (file)
@@ -9,6 +9,16 @@
 #include <asm/arch/pmic_bus.h>
 #include <axp_pmic.h>
 
+#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 {
index dc27d65a43fff44271b50d1b6cb24ba8e738d550..f4f1b2fe56d6dbb42fca9f9945016271de7b0869 100644 (file)
@@ -10,6 +10,7 @@ enum axp209_reg {
        AXP209_CHIP_VERSION = 0x03,
        AXP209_OUTPUT_CTRL = 0x12,
        AXP209_DCDC2_VOLTAGE = 0x23,
+       AXP209_VRC_DCDC2_LDO3 = 0x25,
        AXP209_DCDC3_VOLTAGE = 0x27,
        AXP209_LDO24_VOLTAGE = 0x28,
        AXP209_LDO3_VOLTAGE = 0x29,
@@ -34,6 +35,26 @@ enum axp209_reg {
 #define AXP209_OUTPUT_CTRL_DCDC2       BIT(4)
 #define AXP209_OUTPUT_CTRL_LDO3                BIT(6)
 
+/*
+ * AXP209 datasheet contains wrong information about LDO3 VRC:
+ * - VRC is actually enabled when BIT(1) is True
+ * - VRC is actually not enabled by default (BIT(3) = 0 after reset)
+ */
+#define AXP209_VRC_LDO3_EN             BIT(3)
+#define AXP209_VRC_DCDC2_EN            BIT(2)
+#define AXP209_VRC_LDO3_800uV_uS       (BIT(1) | AXP209_VRC_LDO3_EN)
+#define AXP209_VRC_LDO3_1600uV_uS      AXP209_VRC_LDO3_EN
+#define AXP209_VRC_DCDC2_800uV_uS      (BIT(0) | AXP209_VRC_DCDC2_EN)
+#define AXP209_VRC_DCDC2_1600uV_uS     AXP209_VRC_DCDC2_EN
+#define AXP209_VRC_LDO3_MASK           0xa
+#define AXP209_VRC_DCDC2_MASK          0x5
+#define AXP209_VRC_DCDC2_SLOPE_SET(reg, cfg) \
+       (((reg) & ~AXP209_VRC_DCDC2_MASK) | \
+       ((cfg) & AXP209_VRC_DCDC2_MASK))
+#define AXP209_VRC_LDO3_SLOPE_SET(reg, cfg) \
+       (((reg) & ~AXP209_VRC_LDO3_MASK) | \
+       ((cfg) & AXP209_VRC_LDO3_MASK))
+
 #define AXP209_LDO24_LDO2_MASK         0xf0
 #define AXP209_LDO24_LDO4_MASK         0x0f
 #define AXP209_LDO24_LDO2_SET(reg, cfg)        \