generic: 6.1: backport AXP PMIC support
authorChukun Pan <amadeus@jmu.edu.cn>
Fri, 8 Dec 2023 15:10:21 +0000 (23:10 +0800)
committerHauke Mehrtens <hauke@hauke-m.de>
Tue, 26 Mar 2024 20:56:57 +0000 (21:56 +0100)
Backport AXP15060, AXP313a and AXP192 support.
The AXP15060 PMIC is used for starfive boards,
and the AXP313a PMIC is used for sunxi boards.
Remove conflicting patches from starfive target.

Signed-off-by: Chukun Pan <amadeus@jmu.edu.cn>
target/linux/generic/backport-6.1/880-v6.3-mfd-axp20x-Fix-order-of-pek-rise-and-fall-events.patch [new file with mode: 0644]
target/linux/generic/backport-6.1/881-v6.3-mfd-axp20x-Switch-to-the-sys-off-handler-API.patch [new file with mode: 0644]
target/linux/generic/backport-6.1/882-v6.3-mfd-axp20x-Fix-axp288-writable-ranges.patch [new file with mode: 0644]
target/linux/generic/backport-6.1/883-v6.4-mfd-axp20x-Add-support-for-AXP15060-PMIC.patch [new file with mode: 0644]
target/linux/generic/backport-6.1/884-v6.5-mfd-axp20x-Add-support-for-AXP313a-PMIC.patch [new file with mode: 0644]
target/linux/generic/backport-6.1/885-v6.5-regulator-axp20x-Add-support-for-AXP313a-variant.patch [new file with mode: 0644]
target/linux/generic/backport-6.1/886-v6.5-regulator-axp20x-Add-AXP15060-support.patch [new file with mode: 0644]
target/linux/generic/backport-6.1/887-v6.5-mfd-axp20x-Add-support-for-AXP192.patch [new file with mode: 0644]
target/linux/starfive/patches-6.1/0117-driver-mfd-axp20x-Add-support-for-AXP15060.patch [deleted file]
target/linux/starfive/patches-6.1/0118-driver-regulator-axp20x-Support-AXP15060-variant.patch [deleted file]

diff --git a/target/linux/generic/backport-6.1/880-v6.3-mfd-axp20x-Fix-order-of-pek-rise-and-fall-events.patch b/target/linux/generic/backport-6.1/880-v6.3-mfd-axp20x-Fix-order-of-pek-rise-and-fall-events.patch
new file mode 100644 (file)
index 0000000..23681ba
--- /dev/null
@@ -0,0 +1,80 @@
+From 8781ba7f45695af3ab8e8d1b55a31f527c9201a3 Mon Sep 17 00:00:00 2001
+From: Aren Moynihan <aren@peacevolution.org>
+Date: Thu, 8 Dec 2022 17:02:26 -0500
+Subject: [PATCH] mfd: axp20x: Fix order of pek rise and fall events
+
+The power button can get "stuck" if the rising edge and falling edge irq
+are read in the same pass. This can often be triggered when resuming
+from suspend if the power button is released before the kernel handles
+the interrupt.
+
+Swapping the order of the rise and fall events makes sure that the press
+event is handled first, which prevents this situation.
+
+Signed-off-by: Aren Moynihan <aren@peacevolution.org>
+Reviewed-by: Samuel Holland <samuel@sholland.org>
+Tested-by: Samuel Holland <samuel@sholland.org>
+Acked-by: Chen-Yu Tsai <wens@csie.org>
+Signed-off-by: Lee Jones <lee@kernel.org>
+Link: https://lore.kernel.org/r/20221208220225.635414-1-aren@peacevolution.org
+---
+ include/linux/mfd/axp20x.h | 15 ++++++++++-----
+ 1 file changed, 10 insertions(+), 5 deletions(-)
+
+--- a/include/linux/mfd/axp20x.h
++++ b/include/linux/mfd/axp20x.h
+@@ -432,8 +432,9 @@ enum {
+       AXP152_IRQ_PEK_SHORT,
+       AXP152_IRQ_PEK_LONG,
+       AXP152_IRQ_TIMER,
+-      AXP152_IRQ_PEK_RIS_EDGE,
++      /* out of bit order to make sure the press event is handled first */
+       AXP152_IRQ_PEK_FAL_EDGE,
++      AXP152_IRQ_PEK_RIS_EDGE,
+       AXP152_IRQ_GPIO3_INPUT,
+       AXP152_IRQ_GPIO2_INPUT,
+       AXP152_IRQ_GPIO1_INPUT,
+@@ -472,8 +473,9 @@ enum {
+       AXP20X_IRQ_LOW_PWR_LVL1,
+       AXP20X_IRQ_LOW_PWR_LVL2,
+       AXP20X_IRQ_TIMER,
+-      AXP20X_IRQ_PEK_RIS_EDGE,
++      /* out of bit order to make sure the press event is handled first */
+       AXP20X_IRQ_PEK_FAL_EDGE,
++      AXP20X_IRQ_PEK_RIS_EDGE,
+       AXP20X_IRQ_GPIO3_INPUT,
+       AXP20X_IRQ_GPIO2_INPUT,
+       AXP20X_IRQ_GPIO1_INPUT,
+@@ -502,8 +504,9 @@ enum axp22x_irqs {
+       AXP22X_IRQ_LOW_PWR_LVL1,
+       AXP22X_IRQ_LOW_PWR_LVL2,
+       AXP22X_IRQ_TIMER,
+-      AXP22X_IRQ_PEK_RIS_EDGE,
++      /* out of bit order to make sure the press event is handled first */
+       AXP22X_IRQ_PEK_FAL_EDGE,
++      AXP22X_IRQ_PEK_RIS_EDGE,
+       AXP22X_IRQ_GPIO1_INPUT,
+       AXP22X_IRQ_GPIO0_INPUT,
+ };
+@@ -571,8 +574,9 @@ enum axp803_irqs {
+       AXP803_IRQ_LOW_PWR_LVL1,
+       AXP803_IRQ_LOW_PWR_LVL2,
+       AXP803_IRQ_TIMER,
+-      AXP803_IRQ_PEK_RIS_EDGE,
++      /* out of bit order to make sure the press event is handled first */
+       AXP803_IRQ_PEK_FAL_EDGE,
++      AXP803_IRQ_PEK_RIS_EDGE,
+       AXP803_IRQ_PEK_SHORT,
+       AXP803_IRQ_PEK_LONG,
+       AXP803_IRQ_PEK_OVER_OFF,
+@@ -623,8 +627,9 @@ enum axp809_irqs {
+       AXP809_IRQ_LOW_PWR_LVL1,
+       AXP809_IRQ_LOW_PWR_LVL2,
+       AXP809_IRQ_TIMER,
+-      AXP809_IRQ_PEK_RIS_EDGE,
++      /* out of bit order to make sure the press event is handled first */
+       AXP809_IRQ_PEK_FAL_EDGE,
++      AXP809_IRQ_PEK_RIS_EDGE,
+       AXP809_IRQ_PEK_SHORT,
+       AXP809_IRQ_PEK_LONG,
+       AXP809_IRQ_PEK_OVER_OFF,
diff --git a/target/linux/generic/backport-6.1/881-v6.3-mfd-axp20x-Switch-to-the-sys-off-handler-API.patch b/target/linux/generic/backport-6.1/881-v6.3-mfd-axp20x-Switch-to-the-sys-off-handler-API.patch
new file mode 100644 (file)
index 0000000..b742276
--- /dev/null
@@ -0,0 +1,82 @@
+From 1b1305e95e85624f538ec56db9acf88e2d3d7397 Mon Sep 17 00:00:00 2001
+From: Samuel Holland <samuel@sholland.org>
+Date: Wed, 28 Dec 2022 10:27:52 -0600
+Subject: [PATCH] mfd: axp20x: Switch to the sys-off handler API
+
+This removes a layer of indirection through pm_power_off() and allows
+the PMIC handler to be used as a fallback when firmware power off fails.
+This happens on boards like the Clockwork DevTerm R-01 where OpenSBI
+does not know how to use the PMIC to power off the board.
+
+Move the check for AXP288 to avoid registering a dummy handler.
+
+Signed-off-by: Samuel Holland <samuel@sholland.org>
+[Lee: Removed superfluous new line]
+Signed-off-by: Lee Jones <lee@kernel.org>
+Link: https://lore.kernel.org/r/20221228162752.14204-1-samuel@sholland.org
+---
+ drivers/mfd/axp20x.c | 27 +++++++++++----------------
+ 1 file changed, 11 insertions(+), 16 deletions(-)
+
+--- a/drivers/mfd/axp20x.c
++++ b/drivers/mfd/axp20x.c
+@@ -23,7 +23,7 @@
+ #include <linux/mfd/core.h>
+ #include <linux/module.h>
+ #include <linux/of_device.h>
+-#include <linux/pm_runtime.h>
++#include <linux/reboot.h>
+ #include <linux/regmap.h>
+ #include <linux/regulator/consumer.h>
+@@ -832,17 +832,16 @@ static const struct mfd_cell axp813_cell
+       },
+ };
+-static struct axp20x_dev *axp20x_pm_power_off;
+-static void axp20x_power_off(void)
++static int axp20x_power_off(struct sys_off_data *data)
+ {
+-      if (axp20x_pm_power_off->variant == AXP288_ID)
+-              return;
++      struct axp20x_dev *axp20x = data->cb_data;
+-      regmap_write(axp20x_pm_power_off->regmap, AXP20X_OFF_CTRL,
+-                   AXP20X_OFF);
++      regmap_write(axp20x->regmap, AXP20X_OFF_CTRL, AXP20X_OFF);
+       /* Give capacitors etc. time to drain to avoid kernel panic msg. */
+       mdelay(500);
++
++      return NOTIFY_DONE;
+ }
+ int axp20x_match_device(struct axp20x_dev *axp20x)
+@@ -1009,10 +1008,11 @@ int axp20x_device_probe(struct axp20x_de
+               return ret;
+       }
+-      if (!pm_power_off) {
+-              axp20x_pm_power_off = axp20x;
+-              pm_power_off = axp20x_power_off;
+-      }
++      if (axp20x->variant != AXP288_ID)
++              devm_register_sys_off_handler(axp20x->dev,
++                                            SYS_OFF_MODE_POWER_OFF,
++                                            SYS_OFF_PRIO_DEFAULT,
++                                            axp20x_power_off, axp20x);
+       dev_info(axp20x->dev, "AXP20X driver loaded\n");
+@@ -1022,11 +1022,6 @@ EXPORT_SYMBOL(axp20x_device_probe);
+ void axp20x_device_remove(struct axp20x_dev *axp20x)
+ {
+-      if (axp20x == axp20x_pm_power_off) {
+-              axp20x_pm_power_off = NULL;
+-              pm_power_off = NULL;
+-      }
+-
+       mfd_remove_devices(axp20x->dev);
+       regmap_del_irq_chip(axp20x->irq, axp20x->regmap_irqc);
+ }
diff --git a/target/linux/generic/backport-6.1/882-v6.3-mfd-axp20x-Fix-axp288-writable-ranges.patch b/target/linux/generic/backport-6.1/882-v6.3-mfd-axp20x-Fix-axp288-writable-ranges.patch
new file mode 100644 (file)
index 0000000..b84815e
--- /dev/null
@@ -0,0 +1,28 @@
+From 2405fbfb384ef39e9560d76d3f6e4c90519f90aa Mon Sep 17 00:00:00 2001
+From: Hans de Goede <hdegoede@redhat.com>
+Date: Wed, 29 Mar 2023 22:55:44 +0200
+Subject: [PATCH] mfd: axp20x: Fix axp288 writable-ranges
+
+Register AXP288_POWER_REASON is writable and needs to be written
+to reset the reset- / power-on-reason bits.
+
+Add it to the axp288 writable-ranges so that the extcon-axp288
+driver can properly clear the reset- / power-on-reason bits.
+
+Signed-off-by: Hans de Goede <hdegoede@redhat.com>
+Signed-off-by: Lee Jones <lee@kernel.org>
+Link: https://lore.kernel.org/r/20230329205544.1051393-1-hdegoede@redhat.com
+---
+ drivers/mfd/axp20x.c | 1 +
+ 1 file changed, 1 insertion(+)
+
+--- a/drivers/mfd/axp20x.c
++++ b/drivers/mfd/axp20x.c
+@@ -119,6 +119,7 @@ static const struct regmap_access_table
+ /* AXP288 ranges are shared with the AXP803, as they cover the same range */
+ static const struct regmap_range axp288_writeable_ranges[] = {
++      regmap_reg_range(AXP288_POWER_REASON, AXP288_POWER_REASON),
+       regmap_reg_range(AXP20X_DATACACHE(0), AXP20X_IRQ6_STATE),
+       regmap_reg_range(AXP20X_DCDC_MODE, AXP288_FG_TUNE5),
+ };
diff --git a/target/linux/generic/backport-6.1/883-v6.4-mfd-axp20x-Add-support-for-AXP15060-PMIC.patch b/target/linux/generic/backport-6.1/883-v6.4-mfd-axp20x-Add-support-for-AXP15060-PMIC.patch
new file mode 100644 (file)
index 0000000..83ef60a
--- /dev/null
@@ -0,0 +1,343 @@
+From e0f8ad2a705367518b5c56bf9d6da89681467c02 Mon Sep 17 00:00:00 2001
+From: Shengyu Qu <wiagn233@outlook.com>
+Date: Fri, 21 Apr 2023 23:08:15 +0800
+Subject: [PATCH] mfd: axp20x: Add support for AXP15060 PMIC
+
+The AXP15060 is a PMIC chip produced by X-Powers, and could be connected
+via an I2C bus.
+
+Describe the regmap and the MFD bits, along with the registers exposed
+via I2C. Eventually advertise the device using a new compatible string
+and add support for power off the system.
+
+The driver would disable PEK function if IRQ is not configured in device
+tree, since some boards (For example, Starfive Visionfive 2) didn't
+connect IRQ line of PMIC to SOC.
+
+GPIO function isn't enabled in this commit, since its configuration
+operation is different from any existing AXP PMICs and needs
+logic modification on existing driver. GPIO support might come in later
+patches.
+
+Signed-off-by: Shengyu Qu <wiagn233@outlook.com>
+Reviewed-by: Krzysztof Kozlowski <krzysztof.kozlowski@linaro.org>
+Signed-off-by: Lee Jones <lee@kernel.org>
+Link: https://lore.kernel.org/r/TY3P286MB261162D57695AC8164ED50E298609@TY3P286MB2611.JPNP286.PROD.OUTLOOK.COM
+---
+ drivers/mfd/axp20x-i2c.c   |   2 +
+ drivers/mfd/axp20x.c       | 107 +++++++++++++++++++++++++++++++++++++
+ include/linux/mfd/axp20x.h |  85 +++++++++++++++++++++++++++++
+ 3 files changed, 194 insertions(+)
+
+--- a/drivers/mfd/axp20x-i2c.c
++++ b/drivers/mfd/axp20x-i2c.c
+@@ -66,6 +66,7 @@ static const struct of_device_id axp20x_
+       { .compatible = "x-powers,axp223", .data = (void *)AXP223_ID },
+       { .compatible = "x-powers,axp803", .data = (void *)AXP803_ID },
+       { .compatible = "x-powers,axp806", .data = (void *)AXP806_ID },
++      { .compatible = "x-powers,axp15060", .data = (void *)AXP15060_ID },
+       { },
+ };
+ MODULE_DEVICE_TABLE(of, axp20x_i2c_of_match);
+@@ -79,6 +80,7 @@ static const struct i2c_device_id axp20x
+       { "axp223", 0 },
+       { "axp803", 0 },
+       { "axp806", 0 },
++      { "axp15060", 0 },
+       { },
+ };
+ MODULE_DEVICE_TABLE(i2c, axp20x_i2c_id);
+--- a/drivers/mfd/axp20x.c
++++ b/drivers/mfd/axp20x.c
+@@ -43,6 +43,7 @@ static const char * const axp20x_model_n
+       "AXP806",
+       "AXP809",
+       "AXP813",
++      "AXP15060",
+ };
+ static const struct regmap_range axp152_writeable_ranges[] = {
+@@ -169,6 +170,31 @@ static const struct regmap_access_table
+       .n_yes_ranges   = ARRAY_SIZE(axp806_volatile_ranges),
+ };
++static const struct regmap_range axp15060_writeable_ranges[] = {
++      regmap_reg_range(AXP15060_PWR_OUT_CTRL1, AXP15060_DCDC_MODE_CTRL2),
++      regmap_reg_range(AXP15060_OUTPUT_MONITOR_DISCHARGE, AXP15060_CPUSLDO_V_CTRL),
++      regmap_reg_range(AXP15060_PWR_WAKEUP_CTRL, AXP15060_PWR_DISABLE_DOWN_SEQ),
++      regmap_reg_range(AXP15060_PEK_KEY, AXP15060_PEK_KEY),
++      regmap_reg_range(AXP15060_IRQ1_EN, AXP15060_IRQ2_EN),
++      regmap_reg_range(AXP15060_IRQ1_STATE, AXP15060_IRQ2_STATE),
++};
++
++static const struct regmap_range axp15060_volatile_ranges[] = {
++      regmap_reg_range(AXP15060_STARTUP_SRC, AXP15060_STARTUP_SRC),
++      regmap_reg_range(AXP15060_PWR_WAKEUP_CTRL, AXP15060_PWR_DISABLE_DOWN_SEQ),
++      regmap_reg_range(AXP15060_IRQ1_STATE, AXP15060_IRQ2_STATE),
++};
++
++static const struct regmap_access_table axp15060_writeable_table = {
++      .yes_ranges     = axp15060_writeable_ranges,
++      .n_yes_ranges   = ARRAY_SIZE(axp15060_writeable_ranges),
++};
++
++static const struct regmap_access_table axp15060_volatile_table = {
++      .yes_ranges     = axp15060_volatile_ranges,
++      .n_yes_ranges   = ARRAY_SIZE(axp15060_volatile_ranges),
++};
++
+ static const struct resource axp152_pek_resources[] = {
+       DEFINE_RES_IRQ_NAMED(AXP152_IRQ_PEK_RIS_EDGE, "PEK_DBR"),
+       DEFINE_RES_IRQ_NAMED(AXP152_IRQ_PEK_FAL_EDGE, "PEK_DBF"),
+@@ -237,6 +263,11 @@ static const struct resource axp809_pek_
+       DEFINE_RES_IRQ_NAMED(AXP809_IRQ_PEK_FAL_EDGE, "PEK_DBF"),
+ };
++static const struct resource axp15060_pek_resources[] = {
++      DEFINE_RES_IRQ_NAMED(AXP15060_IRQ_PEK_RIS_EDGE, "PEK_DBR"),
++      DEFINE_RES_IRQ_NAMED(AXP15060_IRQ_PEK_FAL_EDGE, "PEK_DBF"),
++};
++
+ static const struct regmap_config axp152_regmap_config = {
+       .reg_bits       = 8,
+       .val_bits       = 8,
+@@ -282,6 +313,15 @@ static const struct regmap_config axp806
+       .cache_type     = REGCACHE_RBTREE,
+ };
++static const struct regmap_config axp15060_regmap_config = {
++      .reg_bits       = 8,
++      .val_bits       = 8,
++      .wr_table       = &axp15060_writeable_table,
++      .volatile_table = &axp15060_volatile_table,
++      .max_register   = AXP15060_IRQ2_STATE,
++      .cache_type     = REGCACHE_RBTREE,
++};
++
+ #define INIT_REGMAP_IRQ(_variant, _irq, _off, _mask)                  \
+       [_variant##_IRQ_##_irq] = { .reg_offset = (_off), .mask = BIT(_mask) }
+@@ -503,6 +543,23 @@ static const struct regmap_irq axp809_re
+       INIT_REGMAP_IRQ(AXP809, GPIO0_INPUT,            4, 0),
+ };
++static const struct regmap_irq axp15060_regmap_irqs[] = {
++      INIT_REGMAP_IRQ(AXP15060, DIE_TEMP_HIGH_LV1,    0, 0),
++      INIT_REGMAP_IRQ(AXP15060, DIE_TEMP_HIGH_LV2,    0, 1),
++      INIT_REGMAP_IRQ(AXP15060, DCDC1_V_LOW,          0, 2),
++      INIT_REGMAP_IRQ(AXP15060, DCDC2_V_LOW,          0, 3),
++      INIT_REGMAP_IRQ(AXP15060, DCDC3_V_LOW,          0, 4),
++      INIT_REGMAP_IRQ(AXP15060, DCDC4_V_LOW,          0, 5),
++      INIT_REGMAP_IRQ(AXP15060, DCDC5_V_LOW,          0, 6),
++      INIT_REGMAP_IRQ(AXP15060, DCDC6_V_LOW,          0, 7),
++      INIT_REGMAP_IRQ(AXP15060, PEK_LONG,                     1, 0),
++      INIT_REGMAP_IRQ(AXP15060, PEK_SHORT,                    1, 1),
++      INIT_REGMAP_IRQ(AXP15060, GPIO1_INPUT,          1, 2),
++      INIT_REGMAP_IRQ(AXP15060, PEK_FAL_EDGE,                 1, 3),
++      INIT_REGMAP_IRQ(AXP15060, PEK_RIS_EDGE,                 1, 4),
++      INIT_REGMAP_IRQ(AXP15060, GPIO2_INPUT,          1, 5),
++};
++
+ static const struct regmap_irq_chip axp152_regmap_irq_chip = {
+       .name                   = "axp152_irq_chip",
+       .status_base            = AXP152_IRQ1_STATE,
+@@ -589,6 +646,17 @@ static const struct regmap_irq_chip axp8
+       .num_regs               = 5,
+ };
++static const struct regmap_irq_chip axp15060_regmap_irq_chip = {
++      .name                   = "axp15060",
++      .status_base            = AXP15060_IRQ1_STATE,
++      .ack_base               = AXP15060_IRQ1_STATE,
++      .unmask_base            = AXP15060_IRQ1_EN,
++      .init_ack_masked        = true,
++      .irqs                   = axp15060_regmap_irqs,
++      .num_irqs               = ARRAY_SIZE(axp15060_regmap_irqs),
++      .num_regs               = 2,
++};
++
+ static const struct mfd_cell axp20x_cells[] = {
+       {
+               .name           = "axp20x-gpio",
+@@ -833,6 +901,23 @@ static const struct mfd_cell axp813_cell
+       },
+ };
++static const struct mfd_cell axp15060_cells[] = {
++      {
++              .name           = "axp221-pek",
++              .num_resources  = ARRAY_SIZE(axp15060_pek_resources),
++              .resources      = axp15060_pek_resources,
++      }, {
++              .name           = "axp20x-regulator",
++      },
++};
++
++/* For boards that don't have IRQ line connected to SOC. */
++static const struct mfd_cell axp_regulator_only_cells[] = {
++      {
++              .name           = "axp20x-regulator",
++      },
++};
++
+ static int axp20x_power_off(struct sys_off_data *data)
+ {
+       struct axp20x_dev *axp20x = data->cb_data;
+@@ -942,6 +1027,28 @@ int axp20x_match_device(struct axp20x_de
+                */
+               axp20x->regmap_irq_chip = &axp803_regmap_irq_chip;
+               break;
++      case AXP15060_ID:
++              /*
++               * Don't register the power key part if there is no interrupt
++               * line.
++               *
++               * Since most use cases of AXP PMICs are Allwinner SOCs, board
++               * designers follow Allwinner's reference design and connects
++               * IRQ line to SOC, there's no need for those variants to deal
++               * with cases that IRQ isn't connected. However, AXP15660 is
++               * used by some other vendors' SOCs that didn't connect IRQ
++               * line, we need to deal with this case.
++               */
++              if (axp20x->irq > 0) {
++                      axp20x->nr_cells = ARRAY_SIZE(axp15060_cells);
++                      axp20x->cells = axp15060_cells;
++              } else {
++                      axp20x->nr_cells = ARRAY_SIZE(axp_regulator_only_cells);
++                      axp20x->cells = axp_regulator_only_cells;
++              }
++              axp20x->regmap_cfg = &axp15060_regmap_config;
++              axp20x->regmap_irq_chip = &axp15060_regmap_irq_chip;
++              break;
+       default:
+               dev_err(dev, "unsupported AXP20X ID %lu\n", axp20x->variant);
+               return -EINVAL;
+--- a/include/linux/mfd/axp20x.h
++++ b/include/linux/mfd/axp20x.h
+@@ -21,6 +21,7 @@ enum axp20x_variants {
+       AXP806_ID,
+       AXP809_ID,
+       AXP813_ID,
++      AXP15060_ID,
+       NR_AXP20X_VARIANTS,
+ };
+@@ -131,6 +132,39 @@ enum axp20x_variants {
+ /* Other DCDC regulator control registers are the same as AXP803 */
+ #define AXP813_DCDC7_V_OUT            0x26
++#define AXP15060_STARTUP_SRC          0x00
++#define AXP15060_PWR_OUT_CTRL1                0x10
++#define AXP15060_PWR_OUT_CTRL2                0x11
++#define AXP15060_PWR_OUT_CTRL3                0x12
++#define AXP15060_DCDC1_V_CTRL         0x13
++#define AXP15060_DCDC2_V_CTRL         0x14
++#define AXP15060_DCDC3_V_CTRL         0x15
++#define AXP15060_DCDC4_V_CTRL         0x16
++#define AXP15060_DCDC5_V_CTRL         0x17
++#define AXP15060_DCDC6_V_CTRL         0x18
++#define AXP15060_ALDO1_V_CTRL         0x19
++#define AXP15060_DCDC_MODE_CTRL1              0x1a
++#define AXP15060_DCDC_MODE_CTRL2              0x1b
++#define AXP15060_OUTPUT_MONITOR_DISCHARGE             0x1e
++#define AXP15060_IRQ_PWROK_VOFF               0x1f
++#define AXP15060_ALDO2_V_CTRL         0x20
++#define AXP15060_ALDO3_V_CTRL         0x21
++#define AXP15060_ALDO4_V_CTRL         0x22
++#define AXP15060_ALDO5_V_CTRL         0x23
++#define AXP15060_BLDO1_V_CTRL         0x24
++#define AXP15060_BLDO2_V_CTRL         0x25
++#define AXP15060_BLDO3_V_CTRL         0x26
++#define AXP15060_BLDO4_V_CTRL         0x27
++#define AXP15060_BLDO5_V_CTRL         0x28
++#define AXP15060_CLDO1_V_CTRL         0x29
++#define AXP15060_CLDO2_V_CTRL         0x2a
++#define AXP15060_CLDO3_V_CTRL         0x2b
++#define AXP15060_CLDO4_V_CTRL         0x2d
++#define AXP15060_CPUSLDO_V_CTRL               0x2e
++#define AXP15060_PWR_WAKEUP_CTRL              0x31
++#define AXP15060_PWR_DISABLE_DOWN_SEQ         0x32
++#define AXP15060_PEK_KEY              0x36
++
+ /* Interrupt */
+ #define AXP152_IRQ1_EN                        0x40
+ #define AXP152_IRQ2_EN                        0x41
+@@ -152,6 +186,11 @@ enum axp20x_variants {
+ #define AXP20X_IRQ5_STATE             0x4c
+ #define AXP20X_IRQ6_STATE             0x4d
++#define AXP15060_IRQ1_EN              0x40
++#define AXP15060_IRQ2_EN              0x41
++#define AXP15060_IRQ1_STATE           0x48
++#define AXP15060_IRQ2_STATE           0x49
++
+ /* ADC */
+ #define AXP20X_ACIN_V_ADC_H           0x56
+ #define AXP20X_ACIN_V_ADC_L           0x57
+@@ -222,6 +261,8 @@ enum axp20x_variants {
+ #define AXP22X_GPIO_STATE             0x94
+ #define AXP22X_GPIO_PULL_DOWN         0x95
++#define AXP15060_CLDO4_GPIO2_MODESET          0x2c
++
+ /* Battery */
+ #define AXP20X_CHRG_CC_31_24          0xb0
+ #define AXP20X_CHRG_CC_23_16          0xb1
+@@ -419,6 +460,33 @@ enum {
+       AXP813_REG_ID_MAX,
+ };
++enum {
++      AXP15060_DCDC1 = 0,
++      AXP15060_DCDC2,
++      AXP15060_DCDC3,
++      AXP15060_DCDC4,
++      AXP15060_DCDC5,
++      AXP15060_DCDC6,
++      AXP15060_ALDO1,
++      AXP15060_ALDO2,
++      AXP15060_ALDO3,
++      AXP15060_ALDO4,
++      AXP15060_ALDO5,
++      AXP15060_BLDO1,
++      AXP15060_BLDO2,
++      AXP15060_BLDO3,
++      AXP15060_BLDO4,
++      AXP15060_BLDO5,
++      AXP15060_CLDO1,
++      AXP15060_CLDO2,
++      AXP15060_CLDO3,
++      AXP15060_CLDO4,
++      AXP15060_CPUSLDO,
++      AXP15060_SW,
++      AXP15060_RTC_LDO,
++      AXP15060_REG_ID_MAX,
++};
++
+ /* IRQs */
+ enum {
+       AXP152_IRQ_LDO0IN_CONNECT = 1,
+@@ -637,6 +705,23 @@ enum axp809_irqs {
+       AXP809_IRQ_GPIO0_INPUT,
+ };
++enum axp15060_irqs {
++      AXP15060_IRQ_DIE_TEMP_HIGH_LV1 = 1,
++      AXP15060_IRQ_DIE_TEMP_HIGH_LV2,
++      AXP15060_IRQ_DCDC1_V_LOW,
++      AXP15060_IRQ_DCDC2_V_LOW,
++      AXP15060_IRQ_DCDC3_V_LOW,
++      AXP15060_IRQ_DCDC4_V_LOW,
++      AXP15060_IRQ_DCDC5_V_LOW,
++      AXP15060_IRQ_DCDC6_V_LOW,
++      AXP15060_IRQ_PEK_LONG,
++      AXP15060_IRQ_PEK_SHORT,
++      AXP15060_IRQ_GPIO1_INPUT,
++      AXP15060_IRQ_PEK_FAL_EDGE,
++      AXP15060_IRQ_PEK_RIS_EDGE,
++      AXP15060_IRQ_GPIO2_INPUT,
++};
++
+ struct axp20x_dev {
+       struct device                   *dev;
+       int                             irq;
diff --git a/target/linux/generic/backport-6.1/884-v6.5-mfd-axp20x-Add-support-for-AXP313a-PMIC.patch b/target/linux/generic/backport-6.1/884-v6.5-mfd-axp20x-Add-support-for-AXP313a-PMIC.patch
new file mode 100644 (file)
index 0000000..c9470ea
--- /dev/null
@@ -0,0 +1,256 @@
+From 75c8cb2f4cb218aaf4ea68cab08d6dbc96eeae15 Mon Sep 17 00:00:00 2001
+From: Martin Botka <martin.botka@somainline.org>
+Date: Wed, 24 May 2023 01:00:10 +0100
+Subject: [PATCH] mfd: axp20x: Add support for AXP313a PMIC
+
+The AXP313a is a PMIC chip produced by X-Powers, it can be connected via
+an I2C bus.
+The name AXP1530 seems to appear as well, and this is what is used in
+the BSP driver. From all we know it's the same chip, just a different
+name. However we have only seen AXP313a chips in the wild, so go with
+this name.
+
+Compared to the other AXP PMICs it's a rather simple affair: just three
+DCDC converters, three LDOs, and no battery charging support.
+
+Describe the regmap and the MFD bits, along with the registers exposed
+via I2C. Aside from the various regulators, also describe the power key
+interrupts, and adjust the shutdown handler routine to use a different
+register than the other PMICs.
+Eventually advertise the device using the new compatible string.
+
+Signed-off-by: Martin Botka <martin.botka@somainline.org>
+Signed-off-by: Andre Przywara <andre.przywara@arm.com>
+Reviewed-by: Chen-Yu Tsai <wens@csie.org>
+Link: https://lore.kernel.org/r/20230524000012.15028-2-andre.przywara@arm.com
+Signed-off-by: Lee Jones <lee@kernel.org>
+---
+ drivers/mfd/axp20x-i2c.c   |  2 +
+ drivers/mfd/axp20x.c       | 78 +++++++++++++++++++++++++++++++++++++-
+ include/linux/mfd/axp20x.h | 32 ++++++++++++++++
+ 3 files changed, 111 insertions(+), 1 deletion(-)
+
+--- a/drivers/mfd/axp20x-i2c.c
++++ b/drivers/mfd/axp20x-i2c.c
+@@ -64,6 +64,7 @@ static const struct of_device_id axp20x_
+       { .compatible = "x-powers,axp209", .data = (void *)AXP209_ID },
+       { .compatible = "x-powers,axp221", .data = (void *)AXP221_ID },
+       { .compatible = "x-powers,axp223", .data = (void *)AXP223_ID },
++      { .compatible = "x-powers,axp313a", .data = (void *)AXP313A_ID },
+       { .compatible = "x-powers,axp803", .data = (void *)AXP803_ID },
+       { .compatible = "x-powers,axp806", .data = (void *)AXP806_ID },
+       { .compatible = "x-powers,axp15060", .data = (void *)AXP15060_ID },
+@@ -78,6 +79,7 @@ static const struct i2c_device_id axp20x
+       { "axp209", 0 },
+       { "axp221", 0 },
+       { "axp223", 0 },
++      { "axp313a", 0 },
+       { "axp803", 0 },
+       { "axp806", 0 },
+       { "axp15060", 0 },
+--- a/drivers/mfd/axp20x.c
++++ b/drivers/mfd/axp20x.c
+@@ -39,6 +39,7 @@ static const char * const axp20x_model_n
+       "AXP221",
+       "AXP223",
+       "AXP288",
++      "AXP313a",
+       "AXP803",
+       "AXP806",
+       "AXP809",
+@@ -156,6 +157,25 @@ static const struct regmap_range axp806_
+       regmap_reg_range(AXP806_REG_ADDR_EXT, AXP806_REG_ADDR_EXT),
+ };
++static const struct regmap_range axp313a_writeable_ranges[] = {
++      regmap_reg_range(AXP313A_ON_INDICATE, AXP313A_IRQ_STATE),
++};
++
++static const struct regmap_range axp313a_volatile_ranges[] = {
++      regmap_reg_range(AXP313A_SHUTDOWN_CTRL, AXP313A_SHUTDOWN_CTRL),
++      regmap_reg_range(AXP313A_IRQ_STATE, AXP313A_IRQ_STATE),
++};
++
++static const struct regmap_access_table axp313a_writeable_table = {
++      .yes_ranges = axp313a_writeable_ranges,
++      .n_yes_ranges = ARRAY_SIZE(axp313a_writeable_ranges),
++};
++
++static const struct regmap_access_table axp313a_volatile_table = {
++      .yes_ranges = axp313a_volatile_ranges,
++      .n_yes_ranges = ARRAY_SIZE(axp313a_volatile_ranges),
++};
++
+ static const struct regmap_range axp806_volatile_ranges[] = {
+       regmap_reg_range(AXP20X_IRQ1_STATE, AXP20X_IRQ2_STATE),
+ };
+@@ -248,6 +268,11 @@ static const struct resource axp288_fuel
+       DEFINE_RES_IRQ(AXP288_IRQ_WL1),
+ };
++static const struct resource axp313a_pek_resources[] = {
++      DEFINE_RES_IRQ_NAMED(AXP313A_IRQ_PEK_RIS_EDGE, "PEK_DBR"),
++      DEFINE_RES_IRQ_NAMED(AXP313A_IRQ_PEK_FAL_EDGE, "PEK_DBF"),
++};
++
+ static const struct resource axp803_pek_resources[] = {
+       DEFINE_RES_IRQ_NAMED(AXP803_IRQ_PEK_RIS_EDGE, "PEK_DBR"),
+       DEFINE_RES_IRQ_NAMED(AXP803_IRQ_PEK_FAL_EDGE, "PEK_DBF"),
+@@ -304,6 +329,15 @@ static const struct regmap_config axp288
+       .cache_type     = REGCACHE_RBTREE,
+ };
++static const struct regmap_config axp313a_regmap_config = {
++      .reg_bits = 8,
++      .val_bits = 8,
++      .wr_table = &axp313a_writeable_table,
++      .volatile_table = &axp313a_volatile_table,
++      .max_register = AXP313A_IRQ_STATE,
++      .cache_type = REGCACHE_RBTREE,
++};
++
+ static const struct regmap_config axp806_regmap_config = {
+       .reg_bits       = 8,
+       .val_bits       = 8,
+@@ -456,6 +490,16 @@ static const struct regmap_irq axp288_re
+       INIT_REGMAP_IRQ(AXP288, BC_USB_CHNG,            5, 1),
+ };
++static const struct regmap_irq axp313a_regmap_irqs[] = {
++      INIT_REGMAP_IRQ(AXP313A, PEK_RIS_EDGE,          0, 7),
++      INIT_REGMAP_IRQ(AXP313A, PEK_FAL_EDGE,          0, 6),
++      INIT_REGMAP_IRQ(AXP313A, PEK_SHORT,             0, 5),
++      INIT_REGMAP_IRQ(AXP313A, PEK_LONG,              0, 4),
++      INIT_REGMAP_IRQ(AXP313A, DCDC3_V_LOW,           0, 3),
++      INIT_REGMAP_IRQ(AXP313A, DCDC2_V_LOW,           0, 2),
++      INIT_REGMAP_IRQ(AXP313A, DIE_TEMP_HIGH,         0, 0),
++};
++
+ static const struct regmap_irq axp803_regmap_irqs[] = {
+       INIT_REGMAP_IRQ(AXP803, ACIN_OVER_V,            0, 7),
+       INIT_REGMAP_IRQ(AXP803, ACIN_PLUGIN,            0, 6),
+@@ -610,6 +654,17 @@ static const struct regmap_irq_chip axp2
+ };
++static const struct regmap_irq_chip axp313a_regmap_irq_chip = {
++      .name                   = "axp313a_irq_chip",
++      .status_base            = AXP313A_IRQ_STATE,
++      .ack_base               = AXP313A_IRQ_STATE,
++      .unmask_base            = AXP313A_IRQ_EN,
++      .init_ack_masked        = true,
++      .irqs                   = axp313a_regmap_irqs,
++      .num_irqs               = ARRAY_SIZE(axp313a_regmap_irqs),
++      .num_regs               = 1,
++};
++
+ static const struct regmap_irq_chip axp803_regmap_irq_chip = {
+       .name                   = "axp803",
+       .status_base            = AXP20X_IRQ1_STATE,
+@@ -752,6 +807,11 @@ static const struct mfd_cell axp152_cell
+       },
+ };
++static struct mfd_cell axp313a_cells[] = {
++      MFD_CELL_NAME("axp20x-regulator"),
++      MFD_CELL_RES("axp313a-pek", axp313a_pek_resources),
++};
++
+ static const struct resource axp288_adc_resources[] = {
+       DEFINE_RES_IRQ_NAMED(AXP288_IRQ_GPADC, "GPADC"),
+ };
+@@ -921,8 +981,18 @@ static const struct mfd_cell axp_regulat
+ static int axp20x_power_off(struct sys_off_data *data)
+ {
+       struct axp20x_dev *axp20x = data->cb_data;
++      unsigned int shutdown_reg;
+-      regmap_write(axp20x->regmap, AXP20X_OFF_CTRL, AXP20X_OFF);
++      switch (axp20x->variant) {
++      case AXP313A_ID:
++              shutdown_reg = AXP313A_SHUTDOWN_CTRL;
++              break;
++      default:
++              shutdown_reg = AXP20X_OFF_CTRL;
++              break;
++      }
++
++      regmap_write(axp20x->regmap, shutdown_reg, AXP20X_OFF);
+       /* Give capacitors etc. time to drain to avoid kernel panic msg. */
+       mdelay(500);
+@@ -985,6 +1055,12 @@ int axp20x_match_device(struct axp20x_de
+               axp20x->regmap_irq_chip = &axp288_regmap_irq_chip;
+               axp20x->irq_flags = IRQF_TRIGGER_LOW;
+               break;
++      case AXP313A_ID:
++              axp20x->nr_cells = ARRAY_SIZE(axp313a_cells);
++              axp20x->cells = axp313a_cells;
++              axp20x->regmap_cfg = &axp313a_regmap_config;
++              axp20x->regmap_irq_chip = &axp313a_regmap_irq_chip;
++              break;
+       case AXP803_ID:
+               axp20x->nr_cells = ARRAY_SIZE(axp803_cells);
+               axp20x->cells = axp803_cells;
+--- a/include/linux/mfd/axp20x.h
++++ b/include/linux/mfd/axp20x.h
+@@ -17,6 +17,7 @@ enum axp20x_variants {
+       AXP221_ID,
+       AXP223_ID,
+       AXP288_ID,
++      AXP313A_ID,
+       AXP803_ID,
+       AXP806_ID,
+       AXP809_ID,
+@@ -92,6 +93,17 @@ enum axp20x_variants {
+ #define AXP22X_ALDO3_V_OUT            0x2a
+ #define AXP22X_CHRG_CTRL3             0x35
++#define AXP313A_ON_INDICATE           0x00
++#define AXP313A_OUTPUT_CONTROL                0x10
++#define AXP313A_DCDC1_CONRTOL         0x13
++#define AXP313A_DCDC2_CONRTOL         0x14
++#define AXP313A_DCDC3_CONRTOL         0x15
++#define AXP313A_ALDO1_CONRTOL         0x16
++#define AXP313A_DLDO1_CONRTOL         0x17
++#define AXP313A_SHUTDOWN_CTRL         0x1a
++#define AXP313A_IRQ_EN                        0x20
++#define AXP313A_IRQ_STATE             0x21
++
+ #define AXP806_STARTUP_SRC            0x00
+ #define AXP806_CHIP_ID                        0x03
+ #define AXP806_PWR_OUT_CTRL1          0x10
+@@ -364,6 +376,16 @@ enum {
+ };
+ enum {
++      AXP313A_DCDC1 = 0,
++      AXP313A_DCDC2,
++      AXP313A_DCDC3,
++      AXP313A_ALDO1,
++      AXP313A_DLDO1,
++      AXP313A_RTC_LDO,
++      AXP313A_REG_ID_MAX,
++};
++
++enum {
+       AXP806_DCDCA = 0,
+       AXP806_DCDCB,
+       AXP806_DCDCC,
+@@ -616,6 +638,16 @@ enum axp288_irqs {
+       AXP288_IRQ_BC_USB_CHNG,
+ };
++enum axp313a_irqs {
++      AXP313A_IRQ_DIE_TEMP_HIGH,
++      AXP313A_IRQ_DCDC2_V_LOW = 2,
++      AXP313A_IRQ_DCDC3_V_LOW,
++      AXP313A_IRQ_PEK_LONG,
++      AXP313A_IRQ_PEK_SHORT,
++      AXP313A_IRQ_PEK_FAL_EDGE,
++      AXP313A_IRQ_PEK_RIS_EDGE,
++};
++
+ enum axp803_irqs {
+       AXP803_IRQ_ACIN_OVER_V = 1,
+       AXP803_IRQ_ACIN_PLUGIN,
diff --git a/target/linux/generic/backport-6.1/885-v6.5-regulator-axp20x-Add-support-for-AXP313a-variant.patch b/target/linux/generic/backport-6.1/885-v6.5-regulator-axp20x-Add-support-for-AXP313a-variant.patch
new file mode 100644 (file)
index 0000000..91f1b39
--- /dev/null
@@ -0,0 +1,129 @@
+From 60fd7eb89670d2636ac3156881acbd103c6eba6a Mon Sep 17 00:00:00 2001
+From: Martin Botka <martin.botka@somainline.org>
+Date: Wed, 24 May 2023 01:00:11 +0100
+Subject: [PATCH] regulator: axp20x: Add support for AXP313a variant
+
+The AXP313a is your typical I2C controlled PMIC, although in a lighter
+fashion compared to the other X-Powers PMICs: it has only three DCDC
+rails, three LDOs, and no battery charging support.
+
+The AXP313a datasheet does not describe a register to change the DCDC
+switching frequency, and talks of it being fixed at 3 MHz. Check that
+the property allowing to change that frequency is absent from the DT,
+and bail out otherwise.
+
+The third LDO, RTCLDO, is fixed, and cannot even be turned on or off,
+programmatically. On top of that, its voltage is customisable (either
+1.8V or 3.3V), which we cannot describe easily using the existing
+regulator wrapper functions. This should be fixed properly, using
+regulator-{min,max}-microvolt in the DT, but this requires more changes
+to the code. As some other PMICs (AXP2xx, AXP803) seem to paper over the
+same problem as well, we follow suit here and pretend it's a fixed 1.8V
+regulator. A proper fix can follow later. The BSP code seems to ignore
+this regulator altogether.
+
+Describe the AXP313A's voltage settings and switch registers, how the
+voltages are encoded, and connect this to the MFD device via its
+regulator ID.
+
+Signed-off-by: Martin Botka <martin.botka@somainline.org>
+Signed-off-by: Andre Przywara <andre.przywara@arm.com>
+Reviewed-by: Chen-Yu Tsai <wens@csie.org>
+Reviewed-by: Mark Brown <broonie@kernel.org>
+Tested-by: Shengyu Qu <wiagn233@outlook.com>
+Link: https://lore.kernel.org/r/20230524000012.15028-3-andre.przywara@arm.com
+Signed-off-by: Mark Brown <broonie@kernel.org>
+---
+ drivers/regulator/axp20x-regulator.c | 60 ++++++++++++++++++++++++++++
+ 1 file changed, 60 insertions(+)
+
+--- a/drivers/regulator/axp20x-regulator.c
++++ b/drivers/regulator/axp20x-regulator.c
+@@ -134,6 +134,11 @@
+ #define AXP22X_PWR_OUT_DLDO4_MASK     BIT_MASK(6)
+ #define AXP22X_PWR_OUT_ALDO3_MASK     BIT_MASK(7)
++#define AXP313A_DCDC1_NUM_VOLTAGES    107
++#define AXP313A_DCDC23_NUM_VOLTAGES   88
++#define AXP313A_DCDC_V_OUT_MASK               GENMASK(6, 0)
++#define AXP313A_LDO_V_OUT_MASK                GENMASK(4, 0)
++
+ #define AXP803_PWR_OUT_DCDC1_MASK     BIT_MASK(0)
+ #define AXP803_PWR_OUT_DCDC2_MASK     BIT_MASK(1)
+ #define AXP803_PWR_OUT_DCDC3_MASK     BIT_MASK(2)
+@@ -638,6 +643,48 @@ static const struct regulator_desc axp22
+       .ops            = &axp20x_ops_sw,
+ };
++static const struct linear_range axp313a_dcdc1_ranges[] = {
++      REGULATOR_LINEAR_RANGE(500000,   0,  70,  10000),
++      REGULATOR_LINEAR_RANGE(1220000, 71,  87,  20000),
++      REGULATOR_LINEAR_RANGE(1600000, 88, 106, 100000),
++};
++
++static const struct linear_range axp313a_dcdc2_ranges[] = {
++      REGULATOR_LINEAR_RANGE(500000,   0, 70, 10000),
++      REGULATOR_LINEAR_RANGE(1220000, 71, 87, 20000),
++};
++
++/*
++ * This is deviating from the datasheet. The values here are taken from the
++ * BSP driver and have been confirmed by measurements.
++ */
++static const struct linear_range axp313a_dcdc3_ranges[] = {
++      REGULATOR_LINEAR_RANGE(500000,   0,  70, 10000),
++      REGULATOR_LINEAR_RANGE(1220000, 71, 102, 20000),
++};
++
++static const struct regulator_desc axp313a_regulators[] = {
++      AXP_DESC_RANGES(AXP313A, DCDC1, "dcdc1", "vin1",
++                      axp313a_dcdc1_ranges, AXP313A_DCDC1_NUM_VOLTAGES,
++                      AXP313A_DCDC1_CONRTOL, AXP313A_DCDC_V_OUT_MASK,
++                      AXP313A_OUTPUT_CONTROL, BIT(0)),
++      AXP_DESC_RANGES(AXP313A, DCDC2, "dcdc2", "vin2",
++                      axp313a_dcdc2_ranges, AXP313A_DCDC23_NUM_VOLTAGES,
++                      AXP313A_DCDC2_CONRTOL, AXP313A_DCDC_V_OUT_MASK,
++                      AXP313A_OUTPUT_CONTROL, BIT(1)),
++      AXP_DESC_RANGES(AXP313A, DCDC3, "dcdc3", "vin3",
++                      axp313a_dcdc3_ranges, AXP313A_DCDC23_NUM_VOLTAGES,
++                      AXP313A_DCDC3_CONRTOL, AXP313A_DCDC_V_OUT_MASK,
++                      AXP313A_OUTPUT_CONTROL, BIT(2)),
++      AXP_DESC(AXP313A, ALDO1, "aldo1", "vin1", 500, 3500, 100,
++               AXP313A_ALDO1_CONRTOL, AXP313A_LDO_V_OUT_MASK,
++               AXP313A_OUTPUT_CONTROL, BIT(3)),
++      AXP_DESC(AXP313A, DLDO1, "dldo1", "vin1", 500, 3500, 100,
++               AXP313A_DLDO1_CONRTOL, AXP313A_LDO_V_OUT_MASK,
++               AXP313A_OUTPUT_CONTROL, BIT(4)),
++      AXP_DESC_FIXED(AXP313A, RTC_LDO, "rtc-ldo", "vin1", 1800),
++};
++
+ /* DCDC ranges shared with AXP813 */
+ static const struct linear_range axp803_dcdc234_ranges[] = {
+       REGULATOR_LINEAR_RANGE(500000,
+@@ -1040,6 +1087,15 @@ static int axp20x_set_dcdc_freq(struct p
+               def = 3000;
+               step = 150;
+               break;
++      case AXP313A_ID:
++              /* The DCDC PWM frequency seems to be fixed to 3 MHz. */
++              if (dcdcfreq != 0) {
++                      dev_err(&pdev->dev,
++                              "DCDC frequency on AXP313a is fixed to 3 MHz.\n");
++                      return -EINVAL;
++              }
++
++              return 0;
+       default:
+               dev_err(&pdev->dev,
+                       "Setting DCDC frequency for unsupported AXP variant\n");
+@@ -1232,6 +1288,10 @@ static int axp20x_regulator_probe(struct
+               drivevbus = of_property_read_bool(pdev->dev.parent->of_node,
+                                                 "x-powers,drive-vbus-en");
+               break;
++      case AXP313A_ID:
++              regulators = axp313a_regulators;
++              nregulators = AXP313A_REG_ID_MAX;
++              break;
+       case AXP803_ID:
+               regulators = axp803_regulators;
+               nregulators = AXP803_REG_ID_MAX;
diff --git a/target/linux/generic/backport-6.1/886-v6.5-regulator-axp20x-Add-AXP15060-support.patch b/target/linux/generic/backport-6.1/886-v6.5-regulator-axp20x-Add-AXP15060-support.patch
new file mode 100644 (file)
index 0000000..6af0920
--- /dev/null
@@ -0,0 +1,367 @@
+From 9e72869d0fe12aba8cd489e485d93912b3f5c248 Mon Sep 17 00:00:00 2001
+From: Shengyu Qu <wiagn233@outlook.com>
+Date: Wed, 24 May 2023 01:00:12 +0100
+Subject: [PATCH] regulator: axp20x: Add AXP15060 support
+
+The AXP15060 is a typical I2C-controlled PMIC, seen on multiple boards
+with different default register value. Current driver is tested on
+Starfive Visionfive 2.
+
+The RTCLDO is fixed, and cannot even be turned on or off. On top of
+that, its voltage is customisable (either 1.8V or 3.3V). We pretend it's
+a fixed 1.8V regulator since other AXP driver also do like this. Also,
+BSP code ignores this regulator and it's not used according to VF2
+schematic.
+
+Describe the AXP15060's voltage settings and switch registers, how the
+voltages are encoded, and connect this to the MFD device via its
+regulator ID.
+
+Signed-off-by: Shengyu Qu <wiagn233@outlook.com>
+Signed-off-by: Andre Przywara <andre.przywara@arm.com>
+Reviewed-by: Mark Brown <broonie@kernel.org>
+Tested-by: Shengyu Qu <wiagn233@outlook.com>
+Link: https://lore.kernel.org/r/20230524000012.15028-4-andre.przywara@arm.com
+Signed-off-by: Mark Brown <broonie@kernel.org>
+---
+ drivers/regulator/axp20x-regulator.c | 232 +++++++++++++++++++++++++--
+ 1 file changed, 223 insertions(+), 9 deletions(-)
+
+--- a/drivers/regulator/axp20x-regulator.c
++++ b/drivers/regulator/axp20x-regulator.c
+@@ -275,6 +275,74 @@
+ #define AXP813_PWR_OUT_DCDC7_MASK     BIT_MASK(6)
++#define AXP15060_DCDC1_V_CTRL_MASK            GENMASK(4, 0)
++#define AXP15060_DCDC2_V_CTRL_MASK            GENMASK(6, 0)
++#define AXP15060_DCDC3_V_CTRL_MASK            GENMASK(6, 0)
++#define AXP15060_DCDC4_V_CTRL_MASK            GENMASK(6, 0)
++#define AXP15060_DCDC5_V_CTRL_MASK            GENMASK(6, 0)
++#define AXP15060_DCDC6_V_CTRL_MASK            GENMASK(4, 0)
++#define AXP15060_ALDO1_V_CTRL_MASK            GENMASK(4, 0)
++#define AXP15060_ALDO2_V_CTRL_MASK            GENMASK(4, 0)
++#define AXP15060_ALDO3_V_CTRL_MASK            GENMASK(4, 0)
++#define AXP15060_ALDO4_V_CTRL_MASK            GENMASK(4, 0)
++#define AXP15060_ALDO5_V_CTRL_MASK            GENMASK(4, 0)
++#define AXP15060_BLDO1_V_CTRL_MASK            GENMASK(4, 0)
++#define AXP15060_BLDO2_V_CTRL_MASK            GENMASK(4, 0)
++#define AXP15060_BLDO3_V_CTRL_MASK            GENMASK(4, 0)
++#define AXP15060_BLDO4_V_CTRL_MASK            GENMASK(4, 0)
++#define AXP15060_BLDO5_V_CTRL_MASK            GENMASK(4, 0)
++#define AXP15060_CLDO1_V_CTRL_MASK            GENMASK(4, 0)
++#define AXP15060_CLDO2_V_CTRL_MASK            GENMASK(4, 0)
++#define AXP15060_CLDO3_V_CTRL_MASK            GENMASK(4, 0)
++#define AXP15060_CLDO4_V_CTRL_MASK            GENMASK(5, 0)
++#define AXP15060_CPUSLDO_V_CTRL_MASK          GENMASK(3, 0)
++
++#define AXP15060_PWR_OUT_DCDC1_MASK   BIT_MASK(0)
++#define AXP15060_PWR_OUT_DCDC2_MASK   BIT_MASK(1)
++#define AXP15060_PWR_OUT_DCDC3_MASK   BIT_MASK(2)
++#define AXP15060_PWR_OUT_DCDC4_MASK   BIT_MASK(3)
++#define AXP15060_PWR_OUT_DCDC5_MASK   BIT_MASK(4)
++#define AXP15060_PWR_OUT_DCDC6_MASK   BIT_MASK(5)
++#define AXP15060_PWR_OUT_ALDO1_MASK   BIT_MASK(0)
++#define AXP15060_PWR_OUT_ALDO2_MASK   BIT_MASK(1)
++#define AXP15060_PWR_OUT_ALDO3_MASK   BIT_MASK(2)
++#define AXP15060_PWR_OUT_ALDO4_MASK   BIT_MASK(3)
++#define AXP15060_PWR_OUT_ALDO5_MASK   BIT_MASK(4)
++#define AXP15060_PWR_OUT_BLDO1_MASK   BIT_MASK(5)
++#define AXP15060_PWR_OUT_BLDO2_MASK   BIT_MASK(6)
++#define AXP15060_PWR_OUT_BLDO3_MASK   BIT_MASK(7)
++#define AXP15060_PWR_OUT_BLDO4_MASK   BIT_MASK(0)
++#define AXP15060_PWR_OUT_BLDO5_MASK   BIT_MASK(1)
++#define AXP15060_PWR_OUT_CLDO1_MASK   BIT_MASK(2)
++#define AXP15060_PWR_OUT_CLDO2_MASK   BIT_MASK(3)
++#define AXP15060_PWR_OUT_CLDO3_MASK   BIT_MASK(4)
++#define AXP15060_PWR_OUT_CLDO4_MASK   BIT_MASK(5)
++#define AXP15060_PWR_OUT_CPUSLDO_MASK BIT_MASK(6)
++#define AXP15060_PWR_OUT_SW_MASK              BIT_MASK(7)
++
++#define AXP15060_DCDC23_POLYPHASE_DUAL_MASK           BIT_MASK(6)
++#define AXP15060_DCDC46_POLYPHASE_DUAL_MASK           BIT_MASK(7)
++
++#define AXP15060_DCDC234_500mV_START  0x00
++#define AXP15060_DCDC234_500mV_STEPS  70
++#define AXP15060_DCDC234_500mV_END            \
++      (AXP15060_DCDC234_500mV_START + AXP15060_DCDC234_500mV_STEPS)
++#define AXP15060_DCDC234_1220mV_START 0x47
++#define AXP15060_DCDC234_1220mV_STEPS 16
++#define AXP15060_DCDC234_1220mV_END           \
++      (AXP15060_DCDC234_1220mV_START + AXP15060_DCDC234_1220mV_STEPS)
++#define AXP15060_DCDC234_NUM_VOLTAGES 88
++
++#define AXP15060_DCDC5_800mV_START    0x00
++#define AXP15060_DCDC5_800mV_STEPS    32
++#define AXP15060_DCDC5_800mV_END              \
++      (AXP15060_DCDC5_800mV_START + AXP15060_DCDC5_800mV_STEPS)
++#define AXP15060_DCDC5_1140mV_START   0x21
++#define AXP15060_DCDC5_1140mV_STEPS   35
++#define AXP15060_DCDC5_1140mV_END             \
++      (AXP15060_DCDC5_1140mV_START + AXP15060_DCDC5_1140mV_STEPS)
++#define AXP15060_DCDC5_NUM_VOLTAGES   69
++
+ #define AXP_DESC_IO(_family, _id, _match, _supply, _min, _max, _step, _vreg,  \
+                   _vmask, _ereg, _emask, _enable_val, _disable_val)           \
+       [_family##_##_id] = {                                                   \
+@@ -1048,6 +1116,104 @@ static const struct regulator_desc axp81
+                   AXP22X_PWR_OUT_CTRL2, AXP22X_PWR_OUT_DC1SW_MASK),
+ };
++static const struct linear_range axp15060_dcdc234_ranges[] = {
++      REGULATOR_LINEAR_RANGE(500000,
++                             AXP15060_DCDC234_500mV_START,
++                             AXP15060_DCDC234_500mV_END,
++                             10000),
++      REGULATOR_LINEAR_RANGE(1220000,
++                             AXP15060_DCDC234_1220mV_START,
++                             AXP15060_DCDC234_1220mV_END,
++                             20000),
++};
++
++static const struct linear_range axp15060_dcdc5_ranges[] = {
++      REGULATOR_LINEAR_RANGE(800000,
++                             AXP15060_DCDC5_800mV_START,
++                             AXP15060_DCDC5_800mV_END,
++                             10000),
++      REGULATOR_LINEAR_RANGE(1140000,
++                             AXP15060_DCDC5_1140mV_START,
++                             AXP15060_DCDC5_1140mV_END,
++                             20000),
++};
++
++static const struct regulator_desc axp15060_regulators[] = {
++      AXP_DESC(AXP15060, DCDC1, "dcdc1", "vin1", 1500, 3400, 100,
++               AXP15060_DCDC1_V_CTRL, AXP15060_DCDC1_V_CTRL_MASK,
++               AXP15060_PWR_OUT_CTRL1, AXP15060_PWR_OUT_DCDC1_MASK),
++      AXP_DESC_RANGES(AXP15060, DCDC2, "dcdc2", "vin2",
++                      axp15060_dcdc234_ranges, AXP15060_DCDC234_NUM_VOLTAGES,
++                      AXP15060_DCDC2_V_CTRL, AXP15060_DCDC2_V_CTRL_MASK,
++                      AXP15060_PWR_OUT_CTRL1, AXP15060_PWR_OUT_DCDC2_MASK),
++      AXP_DESC_RANGES(AXP15060, DCDC3, "dcdc3", "vin3",
++                      axp15060_dcdc234_ranges, AXP15060_DCDC234_NUM_VOLTAGES,
++                      AXP15060_DCDC3_V_CTRL, AXP15060_DCDC3_V_CTRL_MASK,
++                      AXP15060_PWR_OUT_CTRL1, AXP15060_PWR_OUT_DCDC3_MASK),
++      AXP_DESC_RANGES(AXP15060, DCDC4, "dcdc4", "vin4",
++                      axp15060_dcdc234_ranges, AXP15060_DCDC234_NUM_VOLTAGES,
++                      AXP15060_DCDC4_V_CTRL, AXP15060_DCDC4_V_CTRL_MASK,
++                      AXP15060_PWR_OUT_CTRL1, AXP15060_PWR_OUT_DCDC4_MASK),
++      AXP_DESC_RANGES(AXP15060, DCDC5, "dcdc5", "vin5",
++                      axp15060_dcdc5_ranges, AXP15060_DCDC5_NUM_VOLTAGES,
++                      AXP15060_DCDC5_V_CTRL, AXP15060_DCDC5_V_CTRL_MASK,
++                      AXP15060_PWR_OUT_CTRL1, AXP15060_PWR_OUT_DCDC5_MASK),
++      AXP_DESC(AXP15060, DCDC6, "dcdc6", "vin6", 500, 3400, 100,
++               AXP15060_DCDC6_V_CTRL, AXP15060_DCDC6_V_CTRL_MASK,
++               AXP15060_PWR_OUT_CTRL1, AXP15060_PWR_OUT_DCDC6_MASK),
++      AXP_DESC(AXP15060, ALDO1, "aldo1", "aldoin", 700, 3300, 100,
++               AXP15060_ALDO1_V_CTRL, AXP15060_ALDO1_V_CTRL_MASK,
++               AXP15060_PWR_OUT_CTRL2, AXP15060_PWR_OUT_ALDO1_MASK),
++      AXP_DESC(AXP15060, ALDO2, "aldo2", "aldoin", 700, 3300, 100,
++               AXP15060_ALDO2_V_CTRL, AXP15060_ALDO2_V_CTRL_MASK,
++               AXP15060_PWR_OUT_CTRL2, AXP15060_PWR_OUT_ALDO2_MASK),
++      AXP_DESC(AXP15060, ALDO3, "aldo3", "aldoin", 700, 3300, 100,
++               AXP15060_ALDO3_V_CTRL, AXP15060_ALDO3_V_CTRL_MASK,
++               AXP15060_PWR_OUT_CTRL2, AXP15060_PWR_OUT_ALDO3_MASK),
++      AXP_DESC(AXP15060, ALDO4, "aldo4", "aldoin", 700, 3300, 100,
++               AXP15060_ALDO4_V_CTRL, AXP15060_ALDO4_V_CTRL_MASK,
++               AXP15060_PWR_OUT_CTRL2, AXP15060_PWR_OUT_ALDO4_MASK),
++      AXP_DESC(AXP15060, ALDO5, "aldo5", "aldoin", 700, 3300, 100,
++               AXP15060_ALDO5_V_CTRL, AXP15060_ALDO5_V_CTRL_MASK,
++               AXP15060_PWR_OUT_CTRL2, AXP15060_PWR_OUT_ALDO5_MASK),
++      AXP_DESC(AXP15060, BLDO1, "bldo1", "bldoin", 700, 3300, 100,
++               AXP15060_BLDO1_V_CTRL, AXP15060_BLDO1_V_CTRL_MASK,
++               AXP15060_PWR_OUT_CTRL2, AXP15060_PWR_OUT_BLDO1_MASK),
++      AXP_DESC(AXP15060, BLDO2, "bldo2", "bldoin", 700, 3300, 100,
++               AXP15060_BLDO2_V_CTRL, AXP15060_BLDO2_V_CTRL_MASK,
++               AXP15060_PWR_OUT_CTRL2, AXP15060_PWR_OUT_BLDO2_MASK),
++      AXP_DESC(AXP15060, BLDO3, "bldo3", "bldoin", 700, 3300, 100,
++               AXP15060_BLDO3_V_CTRL, AXP15060_BLDO3_V_CTRL_MASK,
++               AXP15060_PWR_OUT_CTRL2, AXP15060_PWR_OUT_BLDO3_MASK),
++      AXP_DESC(AXP15060, BLDO4, "bldo4", "bldoin", 700, 3300, 100,
++               AXP15060_BLDO4_V_CTRL, AXP15060_BLDO4_V_CTRL_MASK,
++               AXP15060_PWR_OUT_CTRL3, AXP15060_PWR_OUT_BLDO4_MASK),
++      AXP_DESC(AXP15060, BLDO5, "bldo5", "bldoin", 700, 3300, 100,
++               AXP15060_BLDO5_V_CTRL, AXP15060_BLDO5_V_CTRL_MASK,
++               AXP15060_PWR_OUT_CTRL3, AXP15060_PWR_OUT_BLDO5_MASK),
++      AXP_DESC(AXP15060, CLDO1, "cldo1", "cldoin", 700, 3300, 100,
++               AXP15060_CLDO1_V_CTRL, AXP15060_CLDO1_V_CTRL_MASK,
++               AXP15060_PWR_OUT_CTRL3, AXP15060_PWR_OUT_CLDO1_MASK),
++      AXP_DESC(AXP15060, CLDO2, "cldo2", "cldoin", 700, 3300, 100,
++               AXP15060_CLDO2_V_CTRL, AXP15060_CLDO2_V_CTRL_MASK,
++               AXP15060_PWR_OUT_CTRL3, AXP15060_PWR_OUT_CLDO2_MASK),
++      AXP_DESC(AXP15060, CLDO3, "cldo3", "cldoin", 700, 3300, 100,
++               AXP15060_CLDO3_V_CTRL, AXP15060_CLDO3_V_CTRL_MASK,
++               AXP15060_PWR_OUT_CTRL3, AXP15060_PWR_OUT_CLDO3_MASK),
++      AXP_DESC(AXP15060, CLDO4, "cldo4", "cldoin", 700, 4200, 100,
++               AXP15060_CLDO4_V_CTRL, AXP15060_CLDO4_V_CTRL_MASK,
++               AXP15060_PWR_OUT_CTRL3, AXP15060_PWR_OUT_CLDO4_MASK),
++      /* Supply comes from DCDC5 */
++      AXP_DESC(AXP15060, CPUSLDO, "cpusldo", NULL, 700, 1400, 50,
++               AXP15060_CPUSLDO_V_CTRL, AXP15060_CPUSLDO_V_CTRL_MASK,
++               AXP15060_PWR_OUT_CTRL3, AXP15060_PWR_OUT_CPUSLDO_MASK),
++      /* Supply comes from DCDC1 */
++      AXP_DESC_SW(AXP15060, SW, "sw", NULL,
++                  AXP15060_PWR_OUT_CTRL3, AXP15060_PWR_OUT_SW_MASK),
++      /* Supply comes from ALDO1 */
++      AXP_DESC_FIXED(AXP15060, RTC_LDO, "rtc-ldo", NULL, 1800),
++};
++
+ static int axp20x_set_dcdc_freq(struct platform_device *pdev, u32 dcdcfreq)
+ {
+       struct axp20x_dev *axp20x = dev_get_drvdata(pdev->dev.parent);
+@@ -1088,10 +1254,11 @@ static int axp20x_set_dcdc_freq(struct p
+               step = 150;
+               break;
+       case AXP313A_ID:
++      case AXP15060_ID:
+               /* The DCDC PWM frequency seems to be fixed to 3 MHz. */
+               if (dcdcfreq != 0) {
+                       dev_err(&pdev->dev,
+-                              "DCDC frequency on AXP313a is fixed to 3 MHz.\n");
++                              "DCDC frequency on this PMIC is fixed to 3 MHz.\n");
+                       return -EINVAL;
+               }
+@@ -1201,6 +1368,15 @@ static int axp20x_set_dcdc_workmode(stru
+               workmode <<= id - AXP813_DCDC1;
+               break;
++      case AXP15060_ID:
++              reg = AXP15060_DCDC_MODE_CTRL2;
++              if (id < AXP15060_DCDC1 || id > AXP15060_DCDC6)
++                      return -EINVAL;
++
++              mask = AXP22X_WORKMODE_DCDCX_MASK(id - AXP15060_DCDC1);
++              workmode <<= id - AXP15060_DCDC1;
++              break;
++
+       default:
+               /* should not happen */
+               WARN_ON(1);
+@@ -1220,7 +1396,7 @@ static bool axp20x_is_polyphase_slave(st
+       /*
+        * Currently in our supported AXP variants, only AXP803, AXP806,
+-       * and AXP813 have polyphase regulators.
++       * AXP813 and AXP15060 have polyphase regulators.
+        */
+       switch (axp20x->variant) {
+       case AXP803_ID:
+@@ -1252,6 +1428,17 @@ static bool axp20x_is_polyphase_slave(st
+               }
+               break;
++      case AXP15060_ID:
++              regmap_read(axp20x->regmap, AXP15060_DCDC_MODE_CTRL1, &reg);
++
++              switch (id) {
++              case AXP15060_DCDC3:
++                      return !!(reg & AXP15060_DCDC23_POLYPHASE_DUAL_MASK);
++              case AXP15060_DCDC6:
++                      return !!(reg & AXP15060_DCDC46_POLYPHASE_DUAL_MASK);
++              }
++              break;
++
+       default:
+               return false;
+       }
+@@ -1273,6 +1460,7 @@ static int axp20x_regulator_probe(struct
+       u32 workmode;
+       const char *dcdc1_name = axp22x_regulators[AXP22X_DCDC1].name;
+       const char *dcdc5_name = axp22x_regulators[AXP22X_DCDC5].name;
++      const char *aldo1_name = axp15060_regulators[AXP15060_ALDO1].name;
+       bool drivevbus = false;
+       switch (axp20x->variant) {
+@@ -1312,6 +1500,10 @@ static int axp20x_regulator_probe(struct
+               drivevbus = of_property_read_bool(pdev->dev.parent->of_node,
+                                                 "x-powers,drive-vbus-en");
+               break;
++      case AXP15060_ID:
++              regulators = axp15060_regulators;
++              nregulators = AXP15060_REG_ID_MAX;
++              break;
+       default:
+               dev_err(&pdev->dev, "Unsupported AXP variant: %ld\n",
+                       axp20x->variant);
+@@ -1338,8 +1530,9 @@ static int axp20x_regulator_probe(struct
+                       continue;
+               /*
+-               * Regulators DC1SW and DC5LDO are connected internally,
+-               * so we have to handle their supply names separately.
++               * Regulators DC1SW, DC5LDO and RTCLDO on AXP15060 are
++               * connected internally, so we have to handle their supply
++               * names separately.
+                *
+                * We always register the regulators in proper sequence,
+                * so the supply names are correctly read. See the last
+@@ -1348,7 +1541,8 @@ static int axp20x_regulator_probe(struct
+                */
+               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) ||
++                  (regulators == axp15060_regulators && i == AXP15060_SW)) {
+                       new_desc = devm_kzalloc(&pdev->dev, sizeof(*desc),
+                                               GFP_KERNEL);
+                       if (!new_desc)
+@@ -1360,7 +1554,8 @@ static int axp20x_regulator_probe(struct
+               }
+               if ((regulators == axp22x_regulators && i == AXP22X_DC5LDO) ||
+-                  (regulators == axp809_regulators && i == AXP809_DC5LDO)) {
++                  (regulators == axp809_regulators && i == AXP809_DC5LDO) ||
++                  (regulators == axp15060_regulators && i == AXP15060_CPUSLDO)) {
+                       new_desc = devm_kzalloc(&pdev->dev, sizeof(*desc),
+                                               GFP_KERNEL);
+                       if (!new_desc)
+@@ -1371,6 +1566,18 @@ static int axp20x_regulator_probe(struct
+                       desc = new_desc;
+               }
++
++              if (regulators == axp15060_regulators && i == AXP15060_RTC_LDO) {
++                      new_desc = devm_kzalloc(&pdev->dev, sizeof(*desc),
++                                              GFP_KERNEL);
++                      if (!new_desc)
++                              return -ENOMEM;
++
++                      *new_desc = regulators[i];
++                      new_desc->supply_name = aldo1_name;
++                      desc = new_desc;
++              }
++
+               rdev = devm_regulator_register(&pdev->dev, desc, &config);
+               if (IS_ERR(rdev)) {
+                       dev_err(&pdev->dev, "Failed to register %s\n",
+@@ -1389,19 +1596,26 @@ static int axp20x_regulator_probe(struct
+               }
+               /*
+-               * Save AXP22X DCDC1 / DCDC5 regulator names for later.
++               * Save AXP22X DCDC1 / DCDC5 / AXP15060 ALDO1 regulator names for later.
+                */
+               if ((regulators == axp22x_regulators && i == AXP22X_DCDC1) ||
+-                  (regulators == axp809_regulators && i == AXP809_DCDC1))
++                  (regulators == axp809_regulators && i == AXP809_DCDC1) ||
++                  (regulators == axp15060_regulators && i == AXP15060_DCDC1))
+                       of_property_read_string(rdev->dev.of_node,
+                                               "regulator-name",
+                                               &dcdc1_name);
+               if ((regulators == axp22x_regulators && i == AXP22X_DCDC5) ||
+-                  (regulators == axp809_regulators && i == AXP809_DCDC5))
++                  (regulators == axp809_regulators && i == AXP809_DCDC5) ||
++                  (regulators == axp15060_regulators && i == AXP15060_DCDC5))
+                       of_property_read_string(rdev->dev.of_node,
+                                               "regulator-name",
+                                               &dcdc5_name);
++
++              if (regulators == axp15060_regulators && i == AXP15060_ALDO1)
++                      of_property_read_string(rdev->dev.of_node,
++                                              "regulator-name",
++                                              &aldo1_name);
+       }
+       if (drivevbus) {
diff --git a/target/linux/generic/backport-6.1/887-v6.5-mfd-axp20x-Add-support-for-AXP192.patch b/target/linux/generic/backport-6.1/887-v6.5-mfd-axp20x-Add-support-for-AXP192.patch
new file mode 100644 (file)
index 0000000..d75b4e7
--- /dev/null
@@ -0,0 +1,383 @@
+From 63eeabbc9dbddd7381409feccd9082e5ffabfe59 Mon Sep 17 00:00:00 2001
+From: Aidan MacDonald <aidanmacdonald.0x0@gmail.com>
+Date: Thu, 11 May 2023 10:26:08 +0100
+Subject: [PATCH] mfd: axp20x: Add support for AXP192
+
+The AXP192 PMIC is similar to the AXP202/AXP209, but with different
+regulators, additional GPIOs, and a different IRQ register layout.
+
+Signed-off-by: Aidan MacDonald <aidanmacdonald.0x0@gmail.com>
+Link: https://lore.kernel.org/r/20230511092609.76183-1-aidanmacdonald.0x0@gmail.com
+Signed-off-by: Lee Jones <lee@kernel.org>
+---
+ drivers/mfd/axp20x-i2c.c   |   2 +
+ drivers/mfd/axp20x.c       | 141 +++++++++++++++++++++++++++++++++++++
+ include/linux/mfd/axp20x.h |  84 ++++++++++++++++++++++
+ 3 files changed, 227 insertions(+)
+
+--- a/drivers/mfd/axp20x-i2c.c
++++ b/drivers/mfd/axp20x-i2c.c
+@@ -60,6 +60,7 @@ static void axp20x_i2c_remove(struct i2c
+ #ifdef CONFIG_OF
+ static const struct of_device_id axp20x_i2c_of_match[] = {
+       { .compatible = "x-powers,axp152", .data = (void *)AXP152_ID },
++      { .compatible = "x-powers,axp192", .data = (void *)AXP192_ID },
+       { .compatible = "x-powers,axp202", .data = (void *)AXP202_ID },
+       { .compatible = "x-powers,axp209", .data = (void *)AXP209_ID },
+       { .compatible = "x-powers,axp221", .data = (void *)AXP221_ID },
+@@ -75,6 +76,7 @@ MODULE_DEVICE_TABLE(of, axp20x_i2c_of_ma
+ static const struct i2c_device_id axp20x_i2c_id[] = {
+       { "axp152", 0 },
++      { "axp192", 0 },
+       { "axp202", 0 },
+       { "axp209", 0 },
+       { "axp221", 0 },
+--- a/drivers/mfd/axp20x.c
++++ b/drivers/mfd/axp20x.c
+@@ -34,6 +34,7 @@
+ static const char * const axp20x_model_names[] = {
+       "AXP152",
++      "AXP192",
+       "AXP202",
+       "AXP209",
+       "AXP221",
+@@ -94,6 +95,35 @@ static const struct regmap_access_table
+       .n_yes_ranges   = ARRAY_SIZE(axp20x_volatile_ranges),
+ };
++static const struct regmap_range axp192_writeable_ranges[] = {
++      regmap_reg_range(AXP192_DATACACHE(0), AXP192_DATACACHE(5)),
++      regmap_reg_range(AXP192_PWR_OUT_CTRL, AXP192_IRQ5_STATE),
++      regmap_reg_range(AXP20X_DCDC_MODE, AXP192_N_RSTO_CTRL),
++      regmap_reg_range(AXP20X_CC_CTRL, AXP20X_CC_CTRL),
++};
++
++static const struct regmap_range axp192_volatile_ranges[] = {
++      regmap_reg_range(AXP20X_PWR_INPUT_STATUS, AXP192_USB_OTG_STATUS),
++      regmap_reg_range(AXP192_IRQ1_STATE, AXP192_IRQ4_STATE),
++      regmap_reg_range(AXP192_IRQ5_STATE, AXP192_IRQ5_STATE),
++      regmap_reg_range(AXP20X_ACIN_V_ADC_H, AXP20X_IPSOUT_V_HIGH_L),
++      regmap_reg_range(AXP20X_TIMER_CTRL, AXP20X_TIMER_CTRL),
++      regmap_reg_range(AXP192_GPIO2_0_STATE, AXP192_GPIO2_0_STATE),
++      regmap_reg_range(AXP192_GPIO4_3_STATE, AXP192_GPIO4_3_STATE),
++      regmap_reg_range(AXP192_N_RSTO_CTRL, AXP192_N_RSTO_CTRL),
++      regmap_reg_range(AXP20X_CHRG_CC_31_24, AXP20X_CC_CTRL),
++};
++
++static const struct regmap_access_table axp192_writeable_table = {
++      .yes_ranges     = axp192_writeable_ranges,
++      .n_yes_ranges   = ARRAY_SIZE(axp192_writeable_ranges),
++};
++
++static const struct regmap_access_table axp192_volatile_table = {
++      .yes_ranges     = axp192_volatile_ranges,
++      .n_yes_ranges   = ARRAY_SIZE(axp192_volatile_ranges),
++};
++
+ /* AXP22x ranges are shared with the AXP809, as they cover the same range */
+ static const struct regmap_range axp22x_writeable_ranges[] = {
+       regmap_reg_range(AXP20X_DATACACHE(0), AXP20X_IRQ5_STATE),
+@@ -220,6 +250,19 @@ static const struct resource axp152_pek_
+       DEFINE_RES_IRQ_NAMED(AXP152_IRQ_PEK_FAL_EDGE, "PEK_DBF"),
+ };
++static const struct resource axp192_ac_power_supply_resources[] = {
++      DEFINE_RES_IRQ_NAMED(AXP192_IRQ_ACIN_PLUGIN, "ACIN_PLUGIN"),
++      DEFINE_RES_IRQ_NAMED(AXP192_IRQ_ACIN_REMOVAL, "ACIN_REMOVAL"),
++      DEFINE_RES_IRQ_NAMED(AXP192_IRQ_ACIN_OVER_V, "ACIN_OVER_V"),
++};
++
++static const struct resource axp192_usb_power_supply_resources[] = {
++      DEFINE_RES_IRQ_NAMED(AXP192_IRQ_VBUS_PLUGIN, "VBUS_PLUGIN"),
++      DEFINE_RES_IRQ_NAMED(AXP192_IRQ_VBUS_REMOVAL, "VBUS_REMOVAL"),
++      DEFINE_RES_IRQ_NAMED(AXP192_IRQ_VBUS_VALID, "VBUS_VALID"),
++      DEFINE_RES_IRQ_NAMED(AXP192_IRQ_VBUS_NOT_VALID, "VBUS_NOT_VALID"),
++};
++
+ static const struct resource axp20x_ac_power_supply_resources[] = {
+       DEFINE_RES_IRQ_NAMED(AXP20X_IRQ_ACIN_PLUGIN, "ACIN_PLUGIN"),
+       DEFINE_RES_IRQ_NAMED(AXP20X_IRQ_ACIN_REMOVAL, "ACIN_REMOVAL"),
+@@ -302,6 +345,15 @@ static const struct regmap_config axp152
+       .cache_type     = REGCACHE_RBTREE,
+ };
++static const struct regmap_config axp192_regmap_config = {
++      .reg_bits       = 8,
++      .val_bits       = 8,
++      .wr_table       = &axp192_writeable_table,
++      .volatile_table = &axp192_volatile_table,
++      .max_register   = AXP20X_CC_CTRL,
++      .cache_type     = REGCACHE_RBTREE,
++};
++
+ static const struct regmap_config axp20x_regmap_config = {
+       .reg_bits       = 8,
+       .val_bits       = 8,
+@@ -379,6 +431,42 @@ static const struct regmap_irq axp152_re
+       INIT_REGMAP_IRQ(AXP152, GPIO0_INPUT,            2, 0),
+ };
++static const struct regmap_irq axp192_regmap_irqs[] = {
++      INIT_REGMAP_IRQ(AXP192, ACIN_OVER_V,            0, 7),
++      INIT_REGMAP_IRQ(AXP192, ACIN_PLUGIN,            0, 6),
++      INIT_REGMAP_IRQ(AXP192, ACIN_REMOVAL,           0, 5),
++      INIT_REGMAP_IRQ(AXP192, VBUS_OVER_V,            0, 4),
++      INIT_REGMAP_IRQ(AXP192, VBUS_PLUGIN,            0, 3),
++      INIT_REGMAP_IRQ(AXP192, VBUS_REMOVAL,           0, 2),
++      INIT_REGMAP_IRQ(AXP192, VBUS_V_LOW,             0, 1),
++      INIT_REGMAP_IRQ(AXP192, BATT_PLUGIN,            1, 7),
++      INIT_REGMAP_IRQ(AXP192, BATT_REMOVAL,           1, 6),
++      INIT_REGMAP_IRQ(AXP192, BATT_ENT_ACT_MODE,      1, 5),
++      INIT_REGMAP_IRQ(AXP192, BATT_EXIT_ACT_MODE,     1, 4),
++      INIT_REGMAP_IRQ(AXP192, CHARG,                  1, 3),
++      INIT_REGMAP_IRQ(AXP192, CHARG_DONE,             1, 2),
++      INIT_REGMAP_IRQ(AXP192, BATT_TEMP_HIGH,         1, 1),
++      INIT_REGMAP_IRQ(AXP192, BATT_TEMP_LOW,          1, 0),
++      INIT_REGMAP_IRQ(AXP192, DIE_TEMP_HIGH,          2, 7),
++      INIT_REGMAP_IRQ(AXP192, CHARG_I_LOW,            2, 6),
++      INIT_REGMAP_IRQ(AXP192, DCDC1_V_LONG,           2, 5),
++      INIT_REGMAP_IRQ(AXP192, DCDC2_V_LONG,           2, 4),
++      INIT_REGMAP_IRQ(AXP192, DCDC3_V_LONG,           2, 3),
++      INIT_REGMAP_IRQ(AXP192, PEK_SHORT,              2, 1),
++      INIT_REGMAP_IRQ(AXP192, PEK_LONG,               2, 0),
++      INIT_REGMAP_IRQ(AXP192, N_OE_PWR_ON,            3, 7),
++      INIT_REGMAP_IRQ(AXP192, N_OE_PWR_OFF,           3, 6),
++      INIT_REGMAP_IRQ(AXP192, VBUS_VALID,             3, 5),
++      INIT_REGMAP_IRQ(AXP192, VBUS_NOT_VALID,         3, 4),
++      INIT_REGMAP_IRQ(AXP192, VBUS_SESS_VALID,        3, 3),
++      INIT_REGMAP_IRQ(AXP192, VBUS_SESS_END,          3, 2),
++      INIT_REGMAP_IRQ(AXP192, LOW_PWR_LVL,            3, 0),
++      INIT_REGMAP_IRQ(AXP192, TIMER,                  4, 7),
++      INIT_REGMAP_IRQ(AXP192, GPIO2_INPUT,            4, 2),
++      INIT_REGMAP_IRQ(AXP192, GPIO1_INPUT,            4, 1),
++      INIT_REGMAP_IRQ(AXP192, GPIO0_INPUT,            4, 0),
++};
++
+ static const struct regmap_irq axp20x_regmap_irqs[] = {
+       INIT_REGMAP_IRQ(AXP20X, ACIN_OVER_V,            0, 7),
+       INIT_REGMAP_IRQ(AXP20X, ACIN_PLUGIN,            0, 6),
+@@ -616,6 +704,32 @@ static const struct regmap_irq_chip axp1
+       .num_regs               = 3,
+ };
++static unsigned int axp192_get_irq_reg(struct regmap_irq_chip_data *data,
++                                     unsigned int base, int index)
++{
++      /* linear mapping for IRQ1 to IRQ4 */
++      if (index < 4)
++              return base + index;
++
++      /* handle IRQ5 separately */
++      if (base == AXP192_IRQ1_EN)
++              return AXP192_IRQ5_EN;
++
++      return AXP192_IRQ5_STATE;
++}
++
++static const struct regmap_irq_chip axp192_regmap_irq_chip = {
++      .name                   = "axp192_irq_chip",
++      .status_base            = AXP192_IRQ1_STATE,
++      .ack_base               = AXP192_IRQ1_STATE,
++      .unmask_base            = AXP192_IRQ1_EN,
++      .init_ack_masked        = true,
++      .irqs                   = axp192_regmap_irqs,
++      .num_irqs               = ARRAY_SIZE(axp192_regmap_irqs),
++      .num_regs               = 5,
++      .get_irq_reg            = axp192_get_irq_reg,
++};
++
+ static const struct regmap_irq_chip axp20x_regmap_irq_chip = {
+       .name                   = "axp20x_irq_chip",
+       .status_base            = AXP20X_IRQ1_STATE,
+@@ -712,6 +826,27 @@ static const struct regmap_irq_chip axp1
+       .num_regs               = 2,
+ };
++static const struct mfd_cell axp192_cells[] = {
++      {
++              .name           = "axp192-adc",
++              .of_compatible  = "x-powers,axp192-adc",
++      }, {
++              .name           = "axp20x-battery-power-supply",
++              .of_compatible  = "x-powers,axp192-battery-power-supply",
++      }, {
++              .name           = "axp20x-ac-power-supply",
++              .of_compatible  = "x-powers,axp202-ac-power-supply",
++              .num_resources  = ARRAY_SIZE(axp192_ac_power_supply_resources),
++              .resources      = axp192_ac_power_supply_resources,
++      }, {
++              .name           = "axp20x-usb-power-supply",
++              .of_compatible  = "x-powers,axp192-usb-power-supply",
++              .num_resources  = ARRAY_SIZE(axp192_usb_power_supply_resources),
++              .resources      = axp192_usb_power_supply_resources,
++      },
++      {       .name           = "axp20x-regulator" },
++};
++
+ static const struct mfd_cell axp20x_cells[] = {
+       {
+               .name           = "axp20x-gpio",
+@@ -1029,6 +1164,12 @@ int axp20x_match_device(struct axp20x_de
+               axp20x->regmap_cfg = &axp152_regmap_config;
+               axp20x->regmap_irq_chip = &axp152_regmap_irq_chip;
+               break;
++      case AXP192_ID:
++              axp20x->nr_cells = ARRAY_SIZE(axp192_cells);
++              axp20x->cells = axp192_cells;
++              axp20x->regmap_cfg = &axp192_regmap_config;
++              axp20x->regmap_irq_chip = &axp192_regmap_irq_chip;
++              break;
+       case AXP202_ID:
+       case AXP209_ID:
+               axp20x->nr_cells = ARRAY_SIZE(axp20x_cells);
+--- a/include/linux/mfd/axp20x.h
++++ b/include/linux/mfd/axp20x.h
+@@ -12,6 +12,7 @@
+ enum axp20x_variants {
+       AXP152_ID = 0,
++      AXP192_ID,
+       AXP202_ID,
+       AXP209_ID,
+       AXP221_ID,
+@@ -26,6 +27,7 @@ enum axp20x_variants {
+       NR_AXP20X_VARIANTS,
+ };
++#define AXP192_DATACACHE(m)           (0x06 + (m))
+ #define AXP20X_DATACACHE(m)           (0x04 + (m))
+ /* Power supply */
+@@ -47,6 +49,13 @@ enum axp20x_variants {
+ #define AXP152_DCDC_FREQ              0x37
+ #define AXP152_DCDC_MODE              0x80
++#define AXP192_USB_OTG_STATUS         0x04
++#define AXP192_PWR_OUT_CTRL           0x12
++#define AXP192_DCDC2_V_OUT            0x23
++#define AXP192_DCDC1_V_OUT            0x26
++#define AXP192_DCDC3_V_OUT            0x27
++#define AXP192_LDO2_3_V_OUT           0x28
++
+ #define AXP20X_PWR_INPUT_STATUS               0x00
+ #define AXP20X_PWR_OP_MODE            0x01
+ #define AXP20X_USB_OTG_STATUS         0x02
+@@ -185,6 +194,17 @@ enum axp20x_variants {
+ #define AXP152_IRQ2_STATE             0x49
+ #define AXP152_IRQ3_STATE             0x4a
++#define AXP192_IRQ1_EN                        0x40
++#define AXP192_IRQ2_EN                        0x41
++#define AXP192_IRQ3_EN                        0x42
++#define AXP192_IRQ4_EN                        0x43
++#define AXP192_IRQ1_STATE             0x44
++#define AXP192_IRQ2_STATE             0x45
++#define AXP192_IRQ3_STATE             0x46
++#define AXP192_IRQ4_STATE             0x47
++#define AXP192_IRQ5_EN                        0x4a
++#define AXP192_IRQ5_STATE             0x4d
++
+ #define AXP20X_IRQ1_EN                        0x40
+ #define AXP20X_IRQ2_EN                        0x41
+ #define AXP20X_IRQ3_EN                        0x42
+@@ -204,6 +224,11 @@ enum axp20x_variants {
+ #define AXP15060_IRQ2_STATE           0x49
+ /* ADC */
++#define AXP192_GPIO2_V_ADC_H          0x68
++#define AXP192_GPIO2_V_ADC_L          0x69
++#define AXP192_GPIO3_V_ADC_H          0x6a
++#define AXP192_GPIO3_V_ADC_L          0x6b
++
+ #define AXP20X_ACIN_V_ADC_H           0x56
+ #define AXP20X_ACIN_V_ADC_L           0x57
+ #define AXP20X_ACIN_I_ADC_H           0x58
+@@ -233,6 +258,8 @@ enum axp20x_variants {
+ #define AXP20X_IPSOUT_V_HIGH_L                0x7f
+ /* Power supply */
++#define AXP192_GPIO30_IN_RANGE                0x85
++
+ #define AXP20X_DCDC_MODE              0x80
+ #define AXP20X_ADC_EN1                        0x82
+ #define AXP20X_ADC_EN2                        0x83
+@@ -261,6 +288,16 @@ enum axp20x_variants {
+ #define AXP152_PWM1_FREQ_Y            0x9c
+ #define AXP152_PWM1_DUTY_CYCLE                0x9d
++#define AXP192_GPIO0_CTRL             0x90
++#define AXP192_LDO_IO0_V_OUT          0x91
++#define AXP192_GPIO1_CTRL             0x92
++#define AXP192_GPIO2_CTRL             0x93
++#define AXP192_GPIO2_0_STATE          0x94
++#define AXP192_GPIO4_3_CTRL           0x95
++#define AXP192_GPIO4_3_STATE          0x96
++#define AXP192_GPIO2_0_PULL           0x97
++#define AXP192_N_RSTO_CTRL            0x9e
++
+ #define AXP20X_GPIO0_CTRL             0x90
+ #define AXP20X_LDO5_V_OUT             0x91
+ #define AXP20X_GPIO1_CTRL             0x92
+@@ -341,6 +378,17 @@ enum axp20x_variants {
+ /* Regulators IDs */
+ enum {
++      AXP192_DCDC1 = 0,
++      AXP192_DCDC2,
++      AXP192_DCDC3,
++      AXP192_LDO1,
++      AXP192_LDO2,
++      AXP192_LDO3,
++      AXP192_LDO_IO0,
++      AXP192_REG_ID_MAX
++};
++
++enum {
+       AXP20X_LDO1 = 0,
+       AXP20X_LDO2,
+       AXP20X_LDO3,
+@@ -531,6 +579,42 @@ enum {
+       AXP152_IRQ_GPIO0_INPUT,
+ };
++enum axp192_irqs {
++      AXP192_IRQ_ACIN_OVER_V = 1,
++      AXP192_IRQ_ACIN_PLUGIN,
++      AXP192_IRQ_ACIN_REMOVAL,
++      AXP192_IRQ_VBUS_OVER_V,
++      AXP192_IRQ_VBUS_PLUGIN,
++      AXP192_IRQ_VBUS_REMOVAL,
++      AXP192_IRQ_VBUS_V_LOW,
++      AXP192_IRQ_BATT_PLUGIN,
++      AXP192_IRQ_BATT_REMOVAL,
++      AXP192_IRQ_BATT_ENT_ACT_MODE,
++      AXP192_IRQ_BATT_EXIT_ACT_MODE,
++      AXP192_IRQ_CHARG,
++      AXP192_IRQ_CHARG_DONE,
++      AXP192_IRQ_BATT_TEMP_HIGH,
++      AXP192_IRQ_BATT_TEMP_LOW,
++      AXP192_IRQ_DIE_TEMP_HIGH,
++      AXP192_IRQ_CHARG_I_LOW,
++      AXP192_IRQ_DCDC1_V_LONG,
++      AXP192_IRQ_DCDC2_V_LONG,
++      AXP192_IRQ_DCDC3_V_LONG,
++      AXP192_IRQ_PEK_SHORT = 22,
++      AXP192_IRQ_PEK_LONG,
++      AXP192_IRQ_N_OE_PWR_ON,
++      AXP192_IRQ_N_OE_PWR_OFF,
++      AXP192_IRQ_VBUS_VALID,
++      AXP192_IRQ_VBUS_NOT_VALID,
++      AXP192_IRQ_VBUS_SESS_VALID,
++      AXP192_IRQ_VBUS_SESS_END,
++      AXP192_IRQ_LOW_PWR_LVL = 31,
++      AXP192_IRQ_TIMER,
++      AXP192_IRQ_GPIO2_INPUT = 37,
++      AXP192_IRQ_GPIO1_INPUT,
++      AXP192_IRQ_GPIO0_INPUT,
++};
++
+ enum {
+       AXP20X_IRQ_ACIN_OVER_V = 1,
+       AXP20X_IRQ_ACIN_PLUGIN,
diff --git a/target/linux/starfive/patches-6.1/0117-driver-mfd-axp20x-Add-support-for-AXP15060.patch b/target/linux/starfive/patches-6.1/0117-driver-mfd-axp20x-Add-support-for-AXP15060.patch
deleted file mode 100644 (file)
index 18ad298..0000000
+++ /dev/null
@@ -1,1014 +0,0 @@
-From e62161318f2fe3e396fc31c50d210e99bec83021 Mon Sep 17 00:00:00 2001
-From: "ziv.xu" <ziv.xu@starfive.com>
-Date: Fri, 4 Aug 2023 13:53:10 +0800
-Subject: [PATCH 117/122] driver: mfd: axp20x: Add support for AXP15060
-
-axp20x add support for AXP15060
-
-Signed-off-by: ziv.xu <ziv.xu@starfive.com>
----
- drivers/mfd/axp20x-i2c.c   |   2 +
- drivers/mfd/axp20x.c       | 373 ++++++++++++++++++++++++++++++++++---
- include/linux/mfd/axp20x.h | 218 +++++++++++++++++++++-
- 3 files changed, 557 insertions(+), 36 deletions(-)
-
---- a/drivers/mfd/axp20x-i2c.c
-+++ b/drivers/mfd/axp20x-i2c.c
-@@ -66,6 +66,7 @@ static const struct of_device_id axp20x_
-       { .compatible = "x-powers,axp223", .data = (void *)AXP223_ID },
-       { .compatible = "x-powers,axp803", .data = (void *)AXP803_ID },
-       { .compatible = "x-powers,axp806", .data = (void *)AXP806_ID },
-+      { .compatible = "x-powers,axp15060", .data = (void *)AXP15060_ID },
-       { },
- };
- MODULE_DEVICE_TABLE(of, axp20x_i2c_of_match);
-@@ -79,6 +80,7 @@ static const struct i2c_device_id axp20x
-       { "axp223", 0 },
-       { "axp803", 0 },
-       { "axp806", 0 },
-+      { "axp15060", 0 },
-       { },
- };
- MODULE_DEVICE_TABLE(i2c, axp20x_i2c_id);
---- a/drivers/mfd/axp20x.c
-+++ b/drivers/mfd/axp20x.c
-@@ -23,7 +23,7 @@
- #include <linux/mfd/core.h>
- #include <linux/module.h>
- #include <linux/of_device.h>
--#include <linux/pm_runtime.h>
-+#include <linux/reboot.h>
- #include <linux/regmap.h>
- #include <linux/regulator/consumer.h>
-@@ -34,15 +34,18 @@
- static const char * const axp20x_model_names[] = {
-       "AXP152",
-+      "AXP192",
-       "AXP202",
-       "AXP209",
-       "AXP221",
-       "AXP223",
-       "AXP288",
-+      "AXP313a",
-       "AXP803",
-       "AXP806",
-       "AXP809",
-       "AXP813",
-+      "AXP15060",
- };
- static const struct regmap_range axp152_writeable_ranges[] = {
-@@ -92,6 +95,35 @@ static const struct regmap_access_table
-       .n_yes_ranges   = ARRAY_SIZE(axp20x_volatile_ranges),
- };
-+static const struct regmap_range axp192_writeable_ranges[] = {
-+      regmap_reg_range(AXP192_DATACACHE(0), AXP192_DATACACHE(5)),
-+      regmap_reg_range(AXP192_PWR_OUT_CTRL, AXP192_IRQ5_STATE),
-+      regmap_reg_range(AXP20X_DCDC_MODE, AXP192_N_RSTO_CTRL),
-+      regmap_reg_range(AXP20X_CC_CTRL, AXP20X_CC_CTRL),
-+};
-+
-+static const struct regmap_range axp192_volatile_ranges[] = {
-+      regmap_reg_range(AXP20X_PWR_INPUT_STATUS, AXP192_USB_OTG_STATUS),
-+      regmap_reg_range(AXP192_IRQ1_STATE, AXP192_IRQ4_STATE),
-+      regmap_reg_range(AXP192_IRQ5_STATE, AXP192_IRQ5_STATE),
-+      regmap_reg_range(AXP20X_ACIN_V_ADC_H, AXP20X_IPSOUT_V_HIGH_L),
-+      regmap_reg_range(AXP20X_TIMER_CTRL, AXP20X_TIMER_CTRL),
-+      regmap_reg_range(AXP192_GPIO2_0_STATE, AXP192_GPIO2_0_STATE),
-+      regmap_reg_range(AXP192_GPIO4_3_STATE, AXP192_GPIO4_3_STATE),
-+      regmap_reg_range(AXP192_N_RSTO_CTRL, AXP192_N_RSTO_CTRL),
-+      regmap_reg_range(AXP20X_CHRG_CC_31_24, AXP20X_CC_CTRL),
-+};
-+
-+static const struct regmap_access_table axp192_writeable_table = {
-+      .yes_ranges     = axp192_writeable_ranges,
-+      .n_yes_ranges   = ARRAY_SIZE(axp192_writeable_ranges),
-+};
-+
-+static const struct regmap_access_table axp192_volatile_table = {
-+      .yes_ranges     = axp192_volatile_ranges,
-+      .n_yes_ranges   = ARRAY_SIZE(axp192_volatile_ranges),
-+};
-+
- /* AXP22x ranges are shared with the AXP809, as they cover the same range */
- static const struct regmap_range axp22x_writeable_ranges[] = {
-       regmap_reg_range(AXP20X_DATACACHE(0), AXP20X_IRQ5_STATE),
-@@ -119,6 +151,7 @@ static const struct regmap_access_table
- /* AXP288 ranges are shared with the AXP803, as they cover the same range */
- static const struct regmap_range axp288_writeable_ranges[] = {
-+      regmap_reg_range(AXP288_POWER_REASON, AXP288_POWER_REASON),
-       regmap_reg_range(AXP20X_DATACACHE(0), AXP20X_IRQ6_STATE),
-       regmap_reg_range(AXP20X_DCDC_MODE, AXP288_FG_TUNE5),
- };
-@@ -154,6 +187,25 @@ static const struct regmap_range axp806_
-       regmap_reg_range(AXP806_REG_ADDR_EXT, AXP806_REG_ADDR_EXT),
- };
-+static const struct regmap_range axp313a_writeable_ranges[] = {
-+      regmap_reg_range(AXP313A_ON_INDICATE, AXP313A_IRQ_STATE),
-+};
-+
-+static const struct regmap_range axp313a_volatile_ranges[] = {
-+      regmap_reg_range(AXP313A_SHUTDOWN_CTRL, AXP313A_SHUTDOWN_CTRL),
-+      regmap_reg_range(AXP313A_IRQ_STATE, AXP313A_IRQ_STATE),
-+};
-+
-+static const struct regmap_access_table axp313a_writeable_table = {
-+      .yes_ranges = axp313a_writeable_ranges,
-+      .n_yes_ranges = ARRAY_SIZE(axp313a_writeable_ranges),
-+};
-+
-+static const struct regmap_access_table axp313a_volatile_table = {
-+      .yes_ranges = axp313a_volatile_ranges,
-+      .n_yes_ranges = ARRAY_SIZE(axp313a_volatile_ranges),
-+};
-+
- static const struct regmap_range axp806_volatile_ranges[] = {
-       regmap_reg_range(AXP20X_IRQ1_STATE, AXP20X_IRQ2_STATE),
- };
-@@ -168,11 +220,49 @@ static const struct regmap_access_table
-       .n_yes_ranges   = ARRAY_SIZE(axp806_volatile_ranges),
- };
-+static const struct regmap_range axp15060_writeable_ranges[] = {
-+      regmap_reg_range(AXP15060_PWR_OUT_CTRL1, AXP15060_DCDC_MODE_CTRL2),
-+      regmap_reg_range(AXP15060_OUTPUT_MONITOR_DISCHARGE, AXP15060_CPUSLDO_V_CTRL),
-+      regmap_reg_range(AXP15060_PWR_WAKEUP_CTRL, AXP15060_PWR_DISABLE_DOWN_SEQ),
-+      regmap_reg_range(AXP15060_PEK_KEY, AXP15060_PEK_KEY),
-+      regmap_reg_range(AXP15060_IRQ1_EN, AXP15060_IRQ2_EN),
-+      regmap_reg_range(AXP15060_IRQ1_STATE, AXP15060_IRQ2_STATE),
-+};
-+
-+static const struct regmap_range axp15060_volatile_ranges[] = {
-+      regmap_reg_range(AXP15060_STARTUP_SRC, AXP15060_STARTUP_SRC),
-+      regmap_reg_range(AXP15060_PWR_WAKEUP_CTRL, AXP15060_PWR_DISABLE_DOWN_SEQ),
-+      regmap_reg_range(AXP15060_IRQ1_STATE, AXP15060_IRQ2_STATE),
-+};
-+
-+static const struct regmap_access_table axp15060_writeable_table = {
-+      .yes_ranges     = axp15060_writeable_ranges,
-+      .n_yes_ranges   = ARRAY_SIZE(axp15060_writeable_ranges),
-+};
-+
-+static const struct regmap_access_table axp15060_volatile_table = {
-+      .yes_ranges     = axp15060_volatile_ranges,
-+      .n_yes_ranges   = ARRAY_SIZE(axp15060_volatile_ranges),
-+};
-+
- static const struct resource axp152_pek_resources[] = {
-       DEFINE_RES_IRQ_NAMED(AXP152_IRQ_PEK_RIS_EDGE, "PEK_DBR"),
-       DEFINE_RES_IRQ_NAMED(AXP152_IRQ_PEK_FAL_EDGE, "PEK_DBF"),
- };
-+static const struct resource axp192_ac_power_supply_resources[] = {
-+      DEFINE_RES_IRQ_NAMED(AXP192_IRQ_ACIN_PLUGIN, "ACIN_PLUGIN"),
-+      DEFINE_RES_IRQ_NAMED(AXP192_IRQ_ACIN_REMOVAL, "ACIN_REMOVAL"),
-+      DEFINE_RES_IRQ_NAMED(AXP192_IRQ_ACIN_OVER_V, "ACIN_OVER_V"),
-+};
-+
-+static const struct resource axp192_usb_power_supply_resources[] = {
-+      DEFINE_RES_IRQ_NAMED(AXP192_IRQ_VBUS_PLUGIN, "VBUS_PLUGIN"),
-+      DEFINE_RES_IRQ_NAMED(AXP192_IRQ_VBUS_REMOVAL, "VBUS_REMOVAL"),
-+      DEFINE_RES_IRQ_NAMED(AXP192_IRQ_VBUS_VALID, "VBUS_VALID"),
-+      DEFINE_RES_IRQ_NAMED(AXP192_IRQ_VBUS_NOT_VALID, "VBUS_NOT_VALID"),
-+};
-+
- static const struct resource axp20x_ac_power_supply_resources[] = {
-       DEFINE_RES_IRQ_NAMED(AXP20X_IRQ_ACIN_PLUGIN, "ACIN_PLUGIN"),
-       DEFINE_RES_IRQ_NAMED(AXP20X_IRQ_ACIN_REMOVAL, "ACIN_REMOVAL"),
-@@ -221,6 +311,11 @@ static const struct resource axp288_fuel
-       DEFINE_RES_IRQ(AXP288_IRQ_WL1),
- };
-+static const struct resource axp313a_pek_resources[] = {
-+      DEFINE_RES_IRQ_NAMED(AXP313A_IRQ_PEK_RIS_EDGE, "PEK_DBR"),
-+      DEFINE_RES_IRQ_NAMED(AXP313A_IRQ_PEK_FAL_EDGE, "PEK_DBF"),
-+};
-+
- static const struct resource axp803_pek_resources[] = {
-       DEFINE_RES_IRQ_NAMED(AXP803_IRQ_PEK_RIS_EDGE, "PEK_DBR"),
-       DEFINE_RES_IRQ_NAMED(AXP803_IRQ_PEK_FAL_EDGE, "PEK_DBF"),
-@@ -236,6 +331,11 @@ static const struct resource axp809_pek_
-       DEFINE_RES_IRQ_NAMED(AXP809_IRQ_PEK_FAL_EDGE, "PEK_DBF"),
- };
-+static const struct resource axp15060_pek_resources[] = {
-+      DEFINE_RES_IRQ_NAMED(AXP15060_IRQ_PEK_RIS_EDGE, "PEK_DBR"),
-+      DEFINE_RES_IRQ_NAMED(AXP15060_IRQ_PEK_FAL_EDGE, "PEK_DBF"),
-+};
-+
- static const struct regmap_config axp152_regmap_config = {
-       .reg_bits       = 8,
-       .val_bits       = 8,
-@@ -245,6 +345,15 @@ static const struct regmap_config axp152
-       .cache_type     = REGCACHE_RBTREE,
- };
-+static const struct regmap_config axp192_regmap_config = {
-+      .reg_bits       = 8,
-+      .val_bits       = 8,
-+      .wr_table       = &axp192_writeable_table,
-+      .volatile_table = &axp192_volatile_table,
-+      .max_register   = AXP20X_CC_CTRL,
-+      .cache_type     = REGCACHE_RBTREE,
-+};
-+
- static const struct regmap_config axp20x_regmap_config = {
-       .reg_bits       = 8,
-       .val_bits       = 8,
-@@ -272,6 +381,15 @@ static const struct regmap_config axp288
-       .cache_type     = REGCACHE_RBTREE,
- };
-+static const struct regmap_config axp313a_regmap_config = {
-+      .reg_bits = 8,
-+      .val_bits = 8,
-+      .wr_table = &axp313a_writeable_table,
-+      .volatile_table = &axp313a_volatile_table,
-+      .max_register = AXP313A_IRQ_STATE,
-+      .cache_type = REGCACHE_RBTREE,
-+};
-+
- static const struct regmap_config axp806_regmap_config = {
-       .reg_bits       = 8,
-       .val_bits       = 8,
-@@ -281,6 +399,15 @@ static const struct regmap_config axp806
-       .cache_type     = REGCACHE_RBTREE,
- };
-+static const struct regmap_config axp15060_regmap_config = {
-+      .reg_bits       = 8,
-+      .val_bits       = 8,
-+      .wr_table       = &axp15060_writeable_table,
-+      .volatile_table = &axp15060_volatile_table,
-+      .max_register   = AXP15060_IRQ2_STATE,
-+      .cache_type     = REGCACHE_RBTREE,
-+};
-+
- #define INIT_REGMAP_IRQ(_variant, _irq, _off, _mask)                  \
-       [_variant##_IRQ_##_irq] = { .reg_offset = (_off), .mask = BIT(_mask) }
-@@ -304,6 +431,42 @@ static const struct regmap_irq axp152_re
-       INIT_REGMAP_IRQ(AXP152, GPIO0_INPUT,            2, 0),
- };
-+static const struct regmap_irq axp192_regmap_irqs[] = {
-+      INIT_REGMAP_IRQ(AXP192, ACIN_OVER_V,            0, 7),
-+      INIT_REGMAP_IRQ(AXP192, ACIN_PLUGIN,            0, 6),
-+      INIT_REGMAP_IRQ(AXP192, ACIN_REMOVAL,           0, 5),
-+      INIT_REGMAP_IRQ(AXP192, VBUS_OVER_V,            0, 4),
-+      INIT_REGMAP_IRQ(AXP192, VBUS_PLUGIN,            0, 3),
-+      INIT_REGMAP_IRQ(AXP192, VBUS_REMOVAL,           0, 2),
-+      INIT_REGMAP_IRQ(AXP192, VBUS_V_LOW,             0, 1),
-+      INIT_REGMAP_IRQ(AXP192, BATT_PLUGIN,            1, 7),
-+      INIT_REGMAP_IRQ(AXP192, BATT_REMOVAL,           1, 6),
-+      INIT_REGMAP_IRQ(AXP192, BATT_ENT_ACT_MODE,      1, 5),
-+      INIT_REGMAP_IRQ(AXP192, BATT_EXIT_ACT_MODE,     1, 4),
-+      INIT_REGMAP_IRQ(AXP192, CHARG,                  1, 3),
-+      INIT_REGMAP_IRQ(AXP192, CHARG_DONE,             1, 2),
-+      INIT_REGMAP_IRQ(AXP192, BATT_TEMP_HIGH,         1, 1),
-+      INIT_REGMAP_IRQ(AXP192, BATT_TEMP_LOW,          1, 0),
-+      INIT_REGMAP_IRQ(AXP192, DIE_TEMP_HIGH,          2, 7),
-+      INIT_REGMAP_IRQ(AXP192, CHARG_I_LOW,            2, 6),
-+      INIT_REGMAP_IRQ(AXP192, DCDC1_V_LONG,           2, 5),
-+      INIT_REGMAP_IRQ(AXP192, DCDC2_V_LONG,           2, 4),
-+      INIT_REGMAP_IRQ(AXP192, DCDC3_V_LONG,           2, 3),
-+      INIT_REGMAP_IRQ(AXP192, PEK_SHORT,              2, 1),
-+      INIT_REGMAP_IRQ(AXP192, PEK_LONG,               2, 0),
-+      INIT_REGMAP_IRQ(AXP192, N_OE_PWR_ON,            3, 7),
-+      INIT_REGMAP_IRQ(AXP192, N_OE_PWR_OFF,           3, 6),
-+      INIT_REGMAP_IRQ(AXP192, VBUS_VALID,             3, 5),
-+      INIT_REGMAP_IRQ(AXP192, VBUS_NOT_VALID,         3, 4),
-+      INIT_REGMAP_IRQ(AXP192, VBUS_SESS_VALID,        3, 3),
-+      INIT_REGMAP_IRQ(AXP192, VBUS_SESS_END,          3, 2),
-+      INIT_REGMAP_IRQ(AXP192, LOW_PWR_LVL,            3, 0),
-+      INIT_REGMAP_IRQ(AXP192, TIMER,                  4, 7),
-+      INIT_REGMAP_IRQ(AXP192, GPIO2_INPUT,            4, 2),
-+      INIT_REGMAP_IRQ(AXP192, GPIO1_INPUT,            4, 1),
-+      INIT_REGMAP_IRQ(AXP192, GPIO0_INPUT,            4, 0),
-+};
-+
- static const struct regmap_irq axp20x_regmap_irqs[] = {
-       INIT_REGMAP_IRQ(AXP20X, ACIN_OVER_V,            0, 7),
-       INIT_REGMAP_IRQ(AXP20X, ACIN_PLUGIN,            0, 6),
-@@ -415,6 +578,16 @@ static const struct regmap_irq axp288_re
-       INIT_REGMAP_IRQ(AXP288, BC_USB_CHNG,            5, 1),
- };
-+static const struct regmap_irq axp313a_regmap_irqs[] = {
-+      INIT_REGMAP_IRQ(AXP313A, PEK_RIS_EDGE,          0, 7),
-+      INIT_REGMAP_IRQ(AXP313A, PEK_FAL_EDGE,          0, 6),
-+      INIT_REGMAP_IRQ(AXP313A, PEK_SHORT,             0, 5),
-+      INIT_REGMAP_IRQ(AXP313A, PEK_LONG,              0, 4),
-+      INIT_REGMAP_IRQ(AXP313A, DCDC3_V_LOW,           0, 3),
-+      INIT_REGMAP_IRQ(AXP313A, DCDC2_V_LOW,           0, 2),
-+      INIT_REGMAP_IRQ(AXP313A, DIE_TEMP_HIGH,         0, 0),
-+};
-+
- static const struct regmap_irq axp803_regmap_irqs[] = {
-       INIT_REGMAP_IRQ(AXP803, ACIN_OVER_V,            0, 7),
-       INIT_REGMAP_IRQ(AXP803, ACIN_PLUGIN,            0, 6),
-@@ -502,24 +675,65 @@ static const struct regmap_irq axp809_re
-       INIT_REGMAP_IRQ(AXP809, GPIO0_INPUT,            4, 0),
- };
-+static const struct regmap_irq axp15060_regmap_irqs[] = {
-+      INIT_REGMAP_IRQ(AXP15060, DIE_TEMP_HIGH_LV1,    0, 0),
-+      INIT_REGMAP_IRQ(AXP15060, DIE_TEMP_HIGH_LV2,    0, 1),
-+      INIT_REGMAP_IRQ(AXP15060, DCDC1_V_LOW,          0, 2),
-+      INIT_REGMAP_IRQ(AXP15060, DCDC2_V_LOW,          0, 3),
-+      INIT_REGMAP_IRQ(AXP15060, DCDC3_V_LOW,          0, 4),
-+      INIT_REGMAP_IRQ(AXP15060, DCDC4_V_LOW,          0, 5),
-+      INIT_REGMAP_IRQ(AXP15060, DCDC5_V_LOW,          0, 6),
-+      INIT_REGMAP_IRQ(AXP15060, DCDC6_V_LOW,          0, 7),
-+      INIT_REGMAP_IRQ(AXP15060, PEK_LONG,                     1, 0),
-+      INIT_REGMAP_IRQ(AXP15060, PEK_SHORT,                    1, 1),
-+      INIT_REGMAP_IRQ(AXP15060, GPIO1_INPUT,          1, 2),
-+      INIT_REGMAP_IRQ(AXP15060, PEK_FAL_EDGE,                 1, 3),
-+      INIT_REGMAP_IRQ(AXP15060, PEK_RIS_EDGE,                 1, 4),
-+      INIT_REGMAP_IRQ(AXP15060, GPIO2_INPUT,          1, 5),
-+};
-+
- static const struct regmap_irq_chip axp152_regmap_irq_chip = {
-       .name                   = "axp152_irq_chip",
-       .status_base            = AXP152_IRQ1_STATE,
-       .ack_base               = AXP152_IRQ1_STATE,
--      .mask_base              = AXP152_IRQ1_EN,
--      .mask_invert            = true,
-+      .unmask_base            = AXP152_IRQ1_EN,
-       .init_ack_masked        = true,
-       .irqs                   = axp152_regmap_irqs,
-       .num_irqs               = ARRAY_SIZE(axp152_regmap_irqs),
-       .num_regs               = 3,
- };
-+static unsigned int axp192_get_irq_reg(struct regmap_irq_chip_data *data,
-+                                     unsigned int base, int index)
-+{
-+      /* linear mapping for IRQ1 to IRQ4 */
-+      if (index < 4)
-+              return base + index;
-+
-+      /* handle IRQ5 separately */
-+      if (base == AXP192_IRQ1_EN)
-+              return AXP192_IRQ5_EN;
-+
-+      return AXP192_IRQ5_STATE;
-+}
-+
-+static const struct regmap_irq_chip axp192_regmap_irq_chip = {
-+      .name                   = "axp192_irq_chip",
-+      .status_base            = AXP192_IRQ1_STATE,
-+      .ack_base               = AXP192_IRQ1_STATE,
-+      .unmask_base            = AXP192_IRQ1_EN,
-+      .init_ack_masked        = true,
-+      .irqs                   = axp192_regmap_irqs,
-+      .num_irqs               = ARRAY_SIZE(axp192_regmap_irqs),
-+      .num_regs               = 5,
-+      .get_irq_reg            = axp192_get_irq_reg,
-+};
-+
- static const struct regmap_irq_chip axp20x_regmap_irq_chip = {
-       .name                   = "axp20x_irq_chip",
-       .status_base            = AXP20X_IRQ1_STATE,
-       .ack_base               = AXP20X_IRQ1_STATE,
--      .mask_base              = AXP20X_IRQ1_EN,
--      .mask_invert            = true,
-+      .unmask_base            = AXP20X_IRQ1_EN,
-       .init_ack_masked        = true,
-       .irqs                   = axp20x_regmap_irqs,
-       .num_irqs               = ARRAY_SIZE(axp20x_regmap_irqs),
-@@ -531,8 +745,7 @@ static const struct regmap_irq_chip axp2
-       .name                   = "axp22x_irq_chip",
-       .status_base            = AXP20X_IRQ1_STATE,
-       .ack_base               = AXP20X_IRQ1_STATE,
--      .mask_base              = AXP20X_IRQ1_EN,
--      .mask_invert            = true,
-+      .unmask_base            = AXP20X_IRQ1_EN,
-       .init_ack_masked        = true,
-       .irqs                   = axp22x_regmap_irqs,
-       .num_irqs               = ARRAY_SIZE(axp22x_regmap_irqs),
-@@ -543,8 +756,7 @@ static const struct regmap_irq_chip axp2
-       .name                   = "axp288_irq_chip",
-       .status_base            = AXP20X_IRQ1_STATE,
-       .ack_base               = AXP20X_IRQ1_STATE,
--      .mask_base              = AXP20X_IRQ1_EN,
--      .mask_invert            = true,
-+      .unmask_base            = AXP20X_IRQ1_EN,
-       .init_ack_masked        = true,
-       .irqs                   = axp288_regmap_irqs,
-       .num_irqs               = ARRAY_SIZE(axp288_regmap_irqs),
-@@ -552,12 +764,22 @@ static const struct regmap_irq_chip axp2
- };
-+static const struct regmap_irq_chip axp313a_regmap_irq_chip = {
-+      .name                   = "axp313a_irq_chip",
-+      .status_base            = AXP313A_IRQ_STATE,
-+      .ack_base               = AXP313A_IRQ_STATE,
-+      .unmask_base            = AXP313A_IRQ_EN,
-+      .init_ack_masked        = true,
-+      .irqs                   = axp313a_regmap_irqs,
-+      .num_irqs               = ARRAY_SIZE(axp313a_regmap_irqs),
-+      .num_regs               = 1,
-+};
-+
- static const struct regmap_irq_chip axp803_regmap_irq_chip = {
-       .name                   = "axp803",
-       .status_base            = AXP20X_IRQ1_STATE,
-       .ack_base               = AXP20X_IRQ1_STATE,
--      .mask_base              = AXP20X_IRQ1_EN,
--      .mask_invert            = true,
-+      .unmask_base            = AXP20X_IRQ1_EN,
-       .init_ack_masked        = true,
-       .irqs                   = axp803_regmap_irqs,
-       .num_irqs               = ARRAY_SIZE(axp803_regmap_irqs),
-@@ -568,8 +790,7 @@ static const struct regmap_irq_chip axp8
-       .name                   = "axp806",
-       .status_base            = AXP20X_IRQ1_STATE,
-       .ack_base               = AXP20X_IRQ1_STATE,
--      .mask_base              = AXP20X_IRQ1_EN,
--      .mask_invert            = true,
-+      .unmask_base            = AXP20X_IRQ1_EN,
-       .init_ack_masked        = true,
-       .irqs                   = axp806_regmap_irqs,
-       .num_irqs               = ARRAY_SIZE(axp806_regmap_irqs),
-@@ -580,14 +801,45 @@ static const struct regmap_irq_chip axp8
-       .name                   = "axp809",
-       .status_base            = AXP20X_IRQ1_STATE,
-       .ack_base               = AXP20X_IRQ1_STATE,
--      .mask_base              = AXP20X_IRQ1_EN,
--      .mask_invert            = true,
-+      .unmask_base            = AXP20X_IRQ1_EN,
-       .init_ack_masked        = true,
-       .irqs                   = axp809_regmap_irqs,
-       .num_irqs               = ARRAY_SIZE(axp809_regmap_irqs),
-       .num_regs               = 5,
- };
-+static const struct regmap_irq_chip axp15060_regmap_irq_chip = {
-+      .name                   = "axp15060",
-+      .status_base            = AXP15060_IRQ1_STATE,
-+      .ack_base               = AXP15060_IRQ1_STATE,
-+      .unmask_base            = AXP15060_IRQ1_EN,
-+      .init_ack_masked        = true,
-+      .irqs                   = axp15060_regmap_irqs,
-+      .num_irqs               = ARRAY_SIZE(axp15060_regmap_irqs),
-+      .num_regs               = 2,
-+};
-+
-+static const struct mfd_cell axp192_cells[] = {
-+      {
-+              .name           = "axp192-adc",
-+              .of_compatible  = "x-powers,axp192-adc",
-+      }, {
-+              .name           = "axp20x-battery-power-supply",
-+              .of_compatible  = "x-powers,axp192-battery-power-supply",
-+      }, {
-+              .name           = "axp20x-ac-power-supply",
-+              .of_compatible  = "x-powers,axp202-ac-power-supply",
-+              .num_resources  = ARRAY_SIZE(axp192_ac_power_supply_resources),
-+              .resources      = axp192_ac_power_supply_resources,
-+      }, {
-+              .name           = "axp20x-usb-power-supply",
-+              .of_compatible  = "x-powers,axp192-usb-power-supply",
-+              .num_resources  = ARRAY_SIZE(axp192_usb_power_supply_resources),
-+              .resources      = axp192_usb_power_supply_resources,
-+      },
-+      {       .name           = "axp20x-regulator" },
-+};
-+
- static const struct mfd_cell axp20x_cells[] = {
-       {
-               .name           = "axp20x-gpio",
-@@ -683,6 +935,11 @@ static const struct mfd_cell axp152_cell
-       },
- };
-+static struct mfd_cell axp313a_cells[] = {
-+      MFD_CELL_NAME("axp20x-regulator"),
-+      MFD_CELL_RES("axp313a-pek", axp313a_pek_resources),
-+};
-+
- static const struct resource axp288_adc_resources[] = {
-       DEFINE_RES_IRQ_NAMED(AXP288_IRQ_GPADC, "GPADC"),
- };
-@@ -832,17 +1089,43 @@ static const struct mfd_cell axp813_cell
-       },
- };
--static struct axp20x_dev *axp20x_pm_power_off;
--static void axp20x_power_off(void)
-+static const struct mfd_cell axp15060_cells[] = {
-+      {
-+              .name           = "axp221-pek",
-+              .num_resources  = ARRAY_SIZE(axp15060_pek_resources),
-+              .resources      = axp15060_pek_resources,
-+      }, {
-+              .name           = "axp20x-regulator",
-+      },
-+};
-+
-+/* For boards that don't have IRQ line connected to SOC. */
-+static const struct mfd_cell axp_regulator_only_cells[] = {
-+      {
-+              .name           = "axp20x-regulator",
-+      },
-+};
-+
-+static int axp20x_power_off(struct sys_off_data *data)
- {
--      if (axp20x_pm_power_off->variant == AXP288_ID)
--              return;
-+      struct axp20x_dev *axp20x = data->cb_data;
-+      unsigned int shutdown_reg;
--      regmap_write(axp20x_pm_power_off->regmap, AXP20X_OFF_CTRL,
--                   AXP20X_OFF);
-+      switch (axp20x->variant) {
-+      case AXP313A_ID:
-+              shutdown_reg = AXP313A_SHUTDOWN_CTRL;
-+              break;
-+      default:
-+              shutdown_reg = AXP20X_OFF_CTRL;
-+              break;
-+      }
-+
-+      regmap_write(axp20x->regmap, shutdown_reg, AXP20X_OFF);
-       /* Give capacitors etc. time to drain to avoid kernel panic msg. */
-       mdelay(500);
-+
-+      return NOTIFY_DONE;
- }
- int axp20x_match_device(struct axp20x_dev *axp20x)
-@@ -874,6 +1157,12 @@ int axp20x_match_device(struct axp20x_de
-               axp20x->regmap_cfg = &axp152_regmap_config;
-               axp20x->regmap_irq_chip = &axp152_regmap_irq_chip;
-               break;
-+      case AXP192_ID:
-+              axp20x->nr_cells = ARRAY_SIZE(axp192_cells);
-+              axp20x->cells = axp192_cells;
-+              axp20x->regmap_cfg = &axp192_regmap_config;
-+              axp20x->regmap_irq_chip = &axp192_regmap_irq_chip;
-+              break;
-       case AXP202_ID:
-       case AXP209_ID:
-               axp20x->nr_cells = ARRAY_SIZE(axp20x_cells);
-@@ -900,6 +1189,12 @@ int axp20x_match_device(struct axp20x_de
-               axp20x->regmap_irq_chip = &axp288_regmap_irq_chip;
-               axp20x->irq_flags = IRQF_TRIGGER_LOW;
-               break;
-+      case AXP313A_ID:
-+              axp20x->nr_cells = ARRAY_SIZE(axp313a_cells);
-+              axp20x->cells = axp313a_cells;
-+              axp20x->regmap_cfg = &axp313a_regmap_config;
-+              axp20x->regmap_irq_chip = &axp313a_regmap_irq_chip;
-+              break;
-       case AXP803_ID:
-               axp20x->nr_cells = ARRAY_SIZE(axp803_cells);
-               axp20x->cells = axp803_cells;
-@@ -942,6 +1237,28 @@ int axp20x_match_device(struct axp20x_de
-                */
-               axp20x->regmap_irq_chip = &axp803_regmap_irq_chip;
-               break;
-+      case AXP15060_ID:
-+              /*
-+               * Don't register the power key part if there is no interrupt
-+               * line.
-+               *
-+               * Since most use cases of AXP PMICs are Allwinner SOCs, board
-+               * designers follow Allwinner's reference design and connects
-+               * IRQ line to SOC, there's no need for those variants to deal
-+               * with cases that IRQ isn't connected. However, AXP15660 is
-+               * used by some other vendors' SOCs that didn't connect IRQ
-+               * line, we need to deal with this case.
-+               */
-+              if (axp20x->irq > 0) {
-+                      axp20x->nr_cells = ARRAY_SIZE(axp15060_cells);
-+                      axp20x->cells = axp15060_cells;
-+              } else {
-+                      axp20x->nr_cells = ARRAY_SIZE(axp_regulator_only_cells);
-+                      axp20x->cells = axp_regulator_only_cells;
-+              }
-+              axp20x->regmap_cfg = &axp15060_regmap_config;
-+              axp20x->regmap_irq_chip = &axp15060_regmap_irq_chip;
-+              break;
-       default:
-               dev_err(dev, "unsupported AXP20X ID %lu\n", axp20x->variant);
-               return -EINVAL;
-@@ -1009,10 +1326,11 @@ int axp20x_device_probe(struct axp20x_de
-               return ret;
-       }
--      if (!pm_power_off) {
--              axp20x_pm_power_off = axp20x;
--              pm_power_off = axp20x_power_off;
--      }
-+      if (axp20x->variant != AXP288_ID)
-+              devm_register_sys_off_handler(axp20x->dev,
-+                                            SYS_OFF_MODE_POWER_OFF,
-+                                            SYS_OFF_PRIO_DEFAULT,
-+                                            axp20x_power_off, axp20x);
-       dev_info(axp20x->dev, "AXP20X driver loaded\n");
-@@ -1022,11 +1340,6 @@ EXPORT_SYMBOL(axp20x_device_probe);
- void axp20x_device_remove(struct axp20x_dev *axp20x)
- {
--      if (axp20x == axp20x_pm_power_off) {
--              axp20x_pm_power_off = NULL;
--              pm_power_off = NULL;
--      }
--
-       mfd_remove_devices(axp20x->dev);
-       regmap_del_irq_chip(axp20x->irq, axp20x->regmap_irqc);
- }
---- a/include/linux/mfd/axp20x.h
-+++ b/include/linux/mfd/axp20x.h
-@@ -12,18 +12,22 @@
- enum axp20x_variants {
-       AXP152_ID = 0,
-+      AXP192_ID,
-       AXP202_ID,
-       AXP209_ID,
-       AXP221_ID,
-       AXP223_ID,
-       AXP288_ID,
-+      AXP313A_ID,
-       AXP803_ID,
-       AXP806_ID,
-       AXP809_ID,
-       AXP813_ID,
-+      AXP15060_ID,
-       NR_AXP20X_VARIANTS,
- };
-+#define AXP192_DATACACHE(m)           (0x06 + (m))
- #define AXP20X_DATACACHE(m)           (0x04 + (m))
- /* Power supply */
-@@ -45,6 +49,13 @@ enum axp20x_variants {
- #define AXP152_DCDC_FREQ              0x37
- #define AXP152_DCDC_MODE              0x80
-+#define AXP192_USB_OTG_STATUS         0x04
-+#define AXP192_PWR_OUT_CTRL           0x12
-+#define AXP192_DCDC2_V_OUT            0x23
-+#define AXP192_DCDC1_V_OUT            0x26
-+#define AXP192_DCDC3_V_OUT            0x27
-+#define AXP192_LDO2_3_V_OUT           0x28
-+
- #define AXP20X_PWR_INPUT_STATUS               0x00
- #define AXP20X_PWR_OP_MODE            0x01
- #define AXP20X_USB_OTG_STATUS         0x02
-@@ -91,6 +102,17 @@ enum axp20x_variants {
- #define AXP22X_ALDO3_V_OUT            0x2a
- #define AXP22X_CHRG_CTRL3             0x35
-+#define AXP313A_ON_INDICATE           0x00
-+#define AXP313A_OUTPUT_CONTROL                0x10
-+#define AXP313A_DCDC1_CONRTOL         0x13
-+#define AXP313A_DCDC2_CONRTOL         0x14
-+#define AXP313A_DCDC3_CONRTOL         0x15
-+#define AXP313A_ALDO1_CONRTOL         0x16
-+#define AXP313A_DLDO1_CONRTOL         0x17
-+#define AXP313A_SHUTDOWN_CTRL         0x1a
-+#define AXP313A_IRQ_EN                        0x20
-+#define AXP313A_IRQ_STATE             0x21
-+
- #define AXP806_STARTUP_SRC            0x00
- #define AXP806_CHIP_ID                        0x03
- #define AXP806_PWR_OUT_CTRL1          0x10
-@@ -131,6 +153,39 @@ enum axp20x_variants {
- /* Other DCDC regulator control registers are the same as AXP803 */
- #define AXP813_DCDC7_V_OUT            0x26
-+#define AXP15060_STARTUP_SRC          0x00
-+#define AXP15060_PWR_OUT_CTRL1                0x10
-+#define AXP15060_PWR_OUT_CTRL2                0x11
-+#define AXP15060_PWR_OUT_CTRL3                0x12
-+#define AXP15060_DCDC1_V_CTRL         0x13
-+#define AXP15060_DCDC2_V_CTRL         0x14
-+#define AXP15060_DCDC3_V_CTRL         0x15
-+#define AXP15060_DCDC4_V_CTRL         0x16
-+#define AXP15060_DCDC5_V_CTRL         0x17
-+#define AXP15060_DCDC6_V_CTRL         0x18
-+#define AXP15060_ALDO1_V_CTRL         0x19
-+#define AXP15060_DCDC_MODE_CTRL1              0x1a
-+#define AXP15060_DCDC_MODE_CTRL2              0x1b
-+#define AXP15060_OUTPUT_MONITOR_DISCHARGE             0x1e
-+#define AXP15060_IRQ_PWROK_VOFF               0x1f
-+#define AXP15060_ALDO2_V_CTRL         0x20
-+#define AXP15060_ALDO3_V_CTRL         0x21
-+#define AXP15060_ALDO4_V_CTRL         0x22
-+#define AXP15060_ALDO5_V_CTRL         0x23
-+#define AXP15060_BLDO1_V_CTRL         0x24
-+#define AXP15060_BLDO2_V_CTRL         0x25
-+#define AXP15060_BLDO3_V_CTRL         0x26
-+#define AXP15060_BLDO4_V_CTRL         0x27
-+#define AXP15060_BLDO5_V_CTRL         0x28
-+#define AXP15060_CLDO1_V_CTRL         0x29
-+#define AXP15060_CLDO2_V_CTRL         0x2a
-+#define AXP15060_CLDO3_V_CTRL         0x2b
-+#define AXP15060_CLDO4_V_CTRL         0x2d
-+#define AXP15060_CPUSLDO_V_CTRL               0x2e
-+#define AXP15060_PWR_WAKEUP_CTRL              0x31
-+#define AXP15060_PWR_DISABLE_DOWN_SEQ         0x32
-+#define AXP15060_PEK_KEY              0x36
-+
- /* Interrupt */
- #define AXP152_IRQ1_EN                        0x40
- #define AXP152_IRQ2_EN                        0x41
-@@ -139,6 +194,17 @@ enum axp20x_variants {
- #define AXP152_IRQ2_STATE             0x49
- #define AXP152_IRQ3_STATE             0x4a
-+#define AXP192_IRQ1_EN                        0x40
-+#define AXP192_IRQ2_EN                        0x41
-+#define AXP192_IRQ3_EN                        0x42
-+#define AXP192_IRQ4_EN                        0x43
-+#define AXP192_IRQ1_STATE             0x44
-+#define AXP192_IRQ2_STATE             0x45
-+#define AXP192_IRQ3_STATE             0x46
-+#define AXP192_IRQ4_STATE             0x47
-+#define AXP192_IRQ5_EN                        0x4a
-+#define AXP192_IRQ5_STATE             0x4d
-+
- #define AXP20X_IRQ1_EN                        0x40
- #define AXP20X_IRQ2_EN                        0x41
- #define AXP20X_IRQ3_EN                        0x42
-@@ -152,7 +218,17 @@ enum axp20x_variants {
- #define AXP20X_IRQ5_STATE             0x4c
- #define AXP20X_IRQ6_STATE             0x4d
-+#define AXP15060_IRQ1_EN              0x40
-+#define AXP15060_IRQ2_EN              0x41
-+#define AXP15060_IRQ1_STATE           0x48
-+#define AXP15060_IRQ2_STATE           0x49
-+
- /* ADC */
-+#define AXP192_GPIO2_V_ADC_H          0x68
-+#define AXP192_GPIO2_V_ADC_L          0x69
-+#define AXP192_GPIO3_V_ADC_H          0x6a
-+#define AXP192_GPIO3_V_ADC_L          0x6b
-+
- #define AXP20X_ACIN_V_ADC_H           0x56
- #define AXP20X_ACIN_V_ADC_L           0x57
- #define AXP20X_ACIN_I_ADC_H           0x58
-@@ -182,6 +258,8 @@ enum axp20x_variants {
- #define AXP20X_IPSOUT_V_HIGH_L                0x7f
- /* Power supply */
-+#define AXP192_GPIO30_IN_RANGE                0x85
-+
- #define AXP20X_DCDC_MODE              0x80
- #define AXP20X_ADC_EN1                        0x82
- #define AXP20X_ADC_EN2                        0x83
-@@ -210,6 +288,16 @@ enum axp20x_variants {
- #define AXP152_PWM1_FREQ_Y            0x9c
- #define AXP152_PWM1_DUTY_CYCLE                0x9d
-+#define AXP192_GPIO0_CTRL             0x90
-+#define AXP192_LDO_IO0_V_OUT          0x91
-+#define AXP192_GPIO1_CTRL             0x92
-+#define AXP192_GPIO2_CTRL             0x93
-+#define AXP192_GPIO2_0_STATE          0x94
-+#define AXP192_GPIO4_3_CTRL           0x95
-+#define AXP192_GPIO4_3_STATE          0x96
-+#define AXP192_GPIO2_0_PULL           0x97
-+#define AXP192_N_RSTO_CTRL            0x9e
-+
- #define AXP20X_GPIO0_CTRL             0x90
- #define AXP20X_LDO5_V_OUT             0x91
- #define AXP20X_GPIO1_CTRL             0x92
-@@ -222,6 +310,8 @@ enum axp20x_variants {
- #define AXP22X_GPIO_STATE             0x94
- #define AXP22X_GPIO_PULL_DOWN         0x95
-+#define AXP15060_CLDO4_GPIO2_MODESET          0x2c
-+
- /* Battery */
- #define AXP20X_CHRG_CC_31_24          0xb0
- #define AXP20X_CHRG_CC_23_16          0xb1
-@@ -288,6 +378,17 @@ enum axp20x_variants {
- /* Regulators IDs */
- enum {
-+      AXP192_DCDC1 = 0,
-+      AXP192_DCDC2,
-+      AXP192_DCDC3,
-+      AXP192_LDO1,
-+      AXP192_LDO2,
-+      AXP192_LDO3,
-+      AXP192_LDO_IO0,
-+      AXP192_REG_ID_MAX
-+};
-+
-+enum {
-       AXP20X_LDO1 = 0,
-       AXP20X_LDO2,
-       AXP20X_LDO3,
-@@ -323,6 +424,16 @@ enum {
- };
- enum {
-+      AXP313A_DCDC1 = 0,
-+      AXP313A_DCDC2,
-+      AXP313A_DCDC3,
-+      AXP313A_ALDO1,
-+      AXP313A_DLDO1,
-+      AXP313A_RTC_LDO,
-+      AXP313A_REG_ID_MAX,
-+};
-+
-+enum {
-       AXP806_DCDCA = 0,
-       AXP806_DCDCB,
-       AXP806_DCDCC,
-@@ -419,6 +530,33 @@ enum {
-       AXP813_REG_ID_MAX,
- };
-+enum {
-+      AXP15060_DCDC1 = 0,
-+      AXP15060_DCDC2,
-+      AXP15060_DCDC3,
-+      AXP15060_DCDC4,
-+      AXP15060_DCDC5,
-+      AXP15060_DCDC6,
-+      AXP15060_ALDO1,
-+      AXP15060_ALDO2,
-+      AXP15060_ALDO3,
-+      AXP15060_ALDO4,
-+      AXP15060_ALDO5,
-+      AXP15060_BLDO1,
-+      AXP15060_BLDO2,
-+      AXP15060_BLDO3,
-+      AXP15060_BLDO4,
-+      AXP15060_BLDO5,
-+      AXP15060_CLDO1,
-+      AXP15060_CLDO2,
-+      AXP15060_CLDO3,
-+      AXP15060_CLDO4,
-+      AXP15060_CPUSLDO,
-+      AXP15060_SW,
-+      AXP15060_RTC_LDO,
-+      AXP15060_REG_ID_MAX,
-+};
-+
- /* IRQs */
- enum {
-       AXP152_IRQ_LDO0IN_CONNECT = 1,
-@@ -432,14 +570,51 @@ enum {
-       AXP152_IRQ_PEK_SHORT,
-       AXP152_IRQ_PEK_LONG,
-       AXP152_IRQ_TIMER,
--      AXP152_IRQ_PEK_RIS_EDGE,
-+      /* out of bit order to make sure the press event is handled first */
-       AXP152_IRQ_PEK_FAL_EDGE,
-+      AXP152_IRQ_PEK_RIS_EDGE,
-       AXP152_IRQ_GPIO3_INPUT,
-       AXP152_IRQ_GPIO2_INPUT,
-       AXP152_IRQ_GPIO1_INPUT,
-       AXP152_IRQ_GPIO0_INPUT,
- };
-+enum axp192_irqs {
-+      AXP192_IRQ_ACIN_OVER_V = 1,
-+      AXP192_IRQ_ACIN_PLUGIN,
-+      AXP192_IRQ_ACIN_REMOVAL,
-+      AXP192_IRQ_VBUS_OVER_V,
-+      AXP192_IRQ_VBUS_PLUGIN,
-+      AXP192_IRQ_VBUS_REMOVAL,
-+      AXP192_IRQ_VBUS_V_LOW,
-+      AXP192_IRQ_BATT_PLUGIN,
-+      AXP192_IRQ_BATT_REMOVAL,
-+      AXP192_IRQ_BATT_ENT_ACT_MODE,
-+      AXP192_IRQ_BATT_EXIT_ACT_MODE,
-+      AXP192_IRQ_CHARG,
-+      AXP192_IRQ_CHARG_DONE,
-+      AXP192_IRQ_BATT_TEMP_HIGH,
-+      AXP192_IRQ_BATT_TEMP_LOW,
-+      AXP192_IRQ_DIE_TEMP_HIGH,
-+      AXP192_IRQ_CHARG_I_LOW,
-+      AXP192_IRQ_DCDC1_V_LONG,
-+      AXP192_IRQ_DCDC2_V_LONG,
-+      AXP192_IRQ_DCDC3_V_LONG,
-+      AXP192_IRQ_PEK_SHORT = 22,
-+      AXP192_IRQ_PEK_LONG,
-+      AXP192_IRQ_N_OE_PWR_ON,
-+      AXP192_IRQ_N_OE_PWR_OFF,
-+      AXP192_IRQ_VBUS_VALID,
-+      AXP192_IRQ_VBUS_NOT_VALID,
-+      AXP192_IRQ_VBUS_SESS_VALID,
-+      AXP192_IRQ_VBUS_SESS_END,
-+      AXP192_IRQ_LOW_PWR_LVL = 31,
-+      AXP192_IRQ_TIMER,
-+      AXP192_IRQ_GPIO2_INPUT = 37,
-+      AXP192_IRQ_GPIO1_INPUT,
-+      AXP192_IRQ_GPIO0_INPUT,
-+};
-+
- enum {
-       AXP20X_IRQ_ACIN_OVER_V = 1,
-       AXP20X_IRQ_ACIN_PLUGIN,
-@@ -472,8 +647,9 @@ enum {
-       AXP20X_IRQ_LOW_PWR_LVL1,
-       AXP20X_IRQ_LOW_PWR_LVL2,
-       AXP20X_IRQ_TIMER,
--      AXP20X_IRQ_PEK_RIS_EDGE,
-+      /* out of bit order to make sure the press event is handled first */
-       AXP20X_IRQ_PEK_FAL_EDGE,
-+      AXP20X_IRQ_PEK_RIS_EDGE,
-       AXP20X_IRQ_GPIO3_INPUT,
-       AXP20X_IRQ_GPIO2_INPUT,
-       AXP20X_IRQ_GPIO1_INPUT,
-@@ -502,8 +678,9 @@ enum axp22x_irqs {
-       AXP22X_IRQ_LOW_PWR_LVL1,
-       AXP22X_IRQ_LOW_PWR_LVL2,
-       AXP22X_IRQ_TIMER,
--      AXP22X_IRQ_PEK_RIS_EDGE,
-+      /* out of bit order to make sure the press event is handled first */
-       AXP22X_IRQ_PEK_FAL_EDGE,
-+      AXP22X_IRQ_PEK_RIS_EDGE,
-       AXP22X_IRQ_GPIO1_INPUT,
-       AXP22X_IRQ_GPIO0_INPUT,
- };
-@@ -545,6 +722,16 @@ enum axp288_irqs {
-       AXP288_IRQ_BC_USB_CHNG,
- };
-+enum axp313a_irqs {
-+      AXP313A_IRQ_DIE_TEMP_HIGH,
-+      AXP313A_IRQ_DCDC2_V_LOW = 2,
-+      AXP313A_IRQ_DCDC3_V_LOW,
-+      AXP313A_IRQ_PEK_LONG,
-+      AXP313A_IRQ_PEK_SHORT,
-+      AXP313A_IRQ_PEK_FAL_EDGE,
-+      AXP313A_IRQ_PEK_RIS_EDGE,
-+};
-+
- enum axp803_irqs {
-       AXP803_IRQ_ACIN_OVER_V = 1,
-       AXP803_IRQ_ACIN_PLUGIN,
-@@ -571,8 +758,9 @@ enum axp803_irqs {
-       AXP803_IRQ_LOW_PWR_LVL1,
-       AXP803_IRQ_LOW_PWR_LVL2,
-       AXP803_IRQ_TIMER,
--      AXP803_IRQ_PEK_RIS_EDGE,
-+      /* out of bit order to make sure the press event is handled first */
-       AXP803_IRQ_PEK_FAL_EDGE,
-+      AXP803_IRQ_PEK_RIS_EDGE,
-       AXP803_IRQ_PEK_SHORT,
-       AXP803_IRQ_PEK_LONG,
-       AXP803_IRQ_PEK_OVER_OFF,
-@@ -623,8 +811,9 @@ enum axp809_irqs {
-       AXP809_IRQ_LOW_PWR_LVL1,
-       AXP809_IRQ_LOW_PWR_LVL2,
-       AXP809_IRQ_TIMER,
--      AXP809_IRQ_PEK_RIS_EDGE,
-+      /* out of bit order to make sure the press event is handled first */
-       AXP809_IRQ_PEK_FAL_EDGE,
-+      AXP809_IRQ_PEK_RIS_EDGE,
-       AXP809_IRQ_PEK_SHORT,
-       AXP809_IRQ_PEK_LONG,
-       AXP809_IRQ_PEK_OVER_OFF,
-@@ -632,6 +821,23 @@ enum axp809_irqs {
-       AXP809_IRQ_GPIO0_INPUT,
- };
-+enum axp15060_irqs {
-+      AXP15060_IRQ_DIE_TEMP_HIGH_LV1 = 1,
-+      AXP15060_IRQ_DIE_TEMP_HIGH_LV2,
-+      AXP15060_IRQ_DCDC1_V_LOW,
-+      AXP15060_IRQ_DCDC2_V_LOW,
-+      AXP15060_IRQ_DCDC3_V_LOW,
-+      AXP15060_IRQ_DCDC4_V_LOW,
-+      AXP15060_IRQ_DCDC5_V_LOW,
-+      AXP15060_IRQ_DCDC6_V_LOW,
-+      AXP15060_IRQ_PEK_LONG,
-+      AXP15060_IRQ_PEK_SHORT,
-+      AXP15060_IRQ_GPIO1_INPUT,
-+      AXP15060_IRQ_PEK_FAL_EDGE,
-+      AXP15060_IRQ_PEK_RIS_EDGE,
-+      AXP15060_IRQ_GPIO2_INPUT,
-+};
-+
- struct axp20x_dev {
-       struct device                   *dev;
-       int                             irq;
-@@ -698,4 +904,4 @@ int axp20x_device_probe(struct axp20x_de
-  */
- void axp20x_device_remove(struct axp20x_dev *axp20x);
--#endif /* __LINUX_MFD_AXP20X_H */
-+#endif /* __LINUX_MFD_AXP20X_H */
-\ No newline at end of file
diff --git a/target/linux/starfive/patches-6.1/0118-driver-regulator-axp20x-Support-AXP15060-variant.patch b/target/linux/starfive/patches-6.1/0118-driver-regulator-axp20x-Support-AXP15060-variant.patch
deleted file mode 100644 (file)
index ccb277b..0000000
+++ /dev/null
@@ -1,434 +0,0 @@
-From 1b017f3376a5df4a2cd5a120c16723e777fc9a36 Mon Sep 17 00:00:00 2001
-From: "ziv.xu" <ziv.xu@starfive.com>
-Date: Fri, 4 Aug 2023 13:55:23 +0800
-Subject: [PATCH 118/122] driver: regulator: axp20x: Support AXP15060 variant.
-
-Add axp15060 variant support to axp20x
-
-Signed-off-by: ziv.xu <ziv.xu@starfive.com>
----
- drivers/regulator/axp20x-regulator.c | 291 ++++++++++++++++++++++++++-
- 1 file changed, 283 insertions(+), 8 deletions(-)
-
---- a/drivers/regulator/axp20x-regulator.c
-+++ b/drivers/regulator/axp20x-regulator.c
-@@ -134,6 +134,11 @@
- #define AXP22X_PWR_OUT_DLDO4_MASK     BIT_MASK(6)
- #define AXP22X_PWR_OUT_ALDO3_MASK     BIT_MASK(7)
-+#define AXP313A_DCDC1_NUM_VOLTAGES    107
-+#define AXP313A_DCDC23_NUM_VOLTAGES   88
-+#define AXP313A_DCDC_V_OUT_MASK               GENMASK(6, 0)
-+#define AXP313A_LDO_V_OUT_MASK                GENMASK(4, 0)
-+
- #define AXP803_PWR_OUT_DCDC1_MASK     BIT_MASK(0)
- #define AXP803_PWR_OUT_DCDC2_MASK     BIT_MASK(1)
- #define AXP803_PWR_OUT_DCDC3_MASK     BIT_MASK(2)
-@@ -270,6 +275,74 @@
- #define AXP813_PWR_OUT_DCDC7_MASK     BIT_MASK(6)
-+#define AXP15060_DCDC1_V_CTRL_MASK            GENMASK(4, 0)
-+#define AXP15060_DCDC2_V_CTRL_MASK            GENMASK(6, 0)
-+#define AXP15060_DCDC3_V_CTRL_MASK            GENMASK(6, 0)
-+#define AXP15060_DCDC4_V_CTRL_MASK            GENMASK(6, 0)
-+#define AXP15060_DCDC5_V_CTRL_MASK            GENMASK(6, 0)
-+#define AXP15060_DCDC6_V_CTRL_MASK            GENMASK(4, 0)
-+#define AXP15060_ALDO1_V_CTRL_MASK            GENMASK(4, 0)
-+#define AXP15060_ALDO2_V_CTRL_MASK            GENMASK(4, 0)
-+#define AXP15060_ALDO3_V_CTRL_MASK            GENMASK(4, 0)
-+#define AXP15060_ALDO4_V_CTRL_MASK            GENMASK(4, 0)
-+#define AXP15060_ALDO5_V_CTRL_MASK            GENMASK(4, 0)
-+#define AXP15060_BLDO1_V_CTRL_MASK            GENMASK(4, 0)
-+#define AXP15060_BLDO2_V_CTRL_MASK            GENMASK(4, 0)
-+#define AXP15060_BLDO3_V_CTRL_MASK            GENMASK(4, 0)
-+#define AXP15060_BLDO4_V_CTRL_MASK            GENMASK(4, 0)
-+#define AXP15060_BLDO5_V_CTRL_MASK            GENMASK(4, 0)
-+#define AXP15060_CLDO1_V_CTRL_MASK            GENMASK(4, 0)
-+#define AXP15060_CLDO2_V_CTRL_MASK            GENMASK(4, 0)
-+#define AXP15060_CLDO3_V_CTRL_MASK            GENMASK(4, 0)
-+#define AXP15060_CLDO4_V_CTRL_MASK            GENMASK(5, 0)
-+#define AXP15060_CPUSLDO_V_CTRL_MASK          GENMASK(3, 0)
-+
-+#define AXP15060_PWR_OUT_DCDC1_MASK   BIT_MASK(0)
-+#define AXP15060_PWR_OUT_DCDC2_MASK   BIT_MASK(1)
-+#define AXP15060_PWR_OUT_DCDC3_MASK   BIT_MASK(2)
-+#define AXP15060_PWR_OUT_DCDC4_MASK   BIT_MASK(3)
-+#define AXP15060_PWR_OUT_DCDC5_MASK   BIT_MASK(4)
-+#define AXP15060_PWR_OUT_DCDC6_MASK   BIT_MASK(5)
-+#define AXP15060_PWR_OUT_ALDO1_MASK   BIT_MASK(0)
-+#define AXP15060_PWR_OUT_ALDO2_MASK   BIT_MASK(1)
-+#define AXP15060_PWR_OUT_ALDO3_MASK   BIT_MASK(2)
-+#define AXP15060_PWR_OUT_ALDO4_MASK   BIT_MASK(3)
-+#define AXP15060_PWR_OUT_ALDO5_MASK   BIT_MASK(4)
-+#define AXP15060_PWR_OUT_BLDO1_MASK   BIT_MASK(5)
-+#define AXP15060_PWR_OUT_BLDO2_MASK   BIT_MASK(6)
-+#define AXP15060_PWR_OUT_BLDO3_MASK   BIT_MASK(7)
-+#define AXP15060_PWR_OUT_BLDO4_MASK   BIT_MASK(0)
-+#define AXP15060_PWR_OUT_BLDO5_MASK   BIT_MASK(1)
-+#define AXP15060_PWR_OUT_CLDO1_MASK   BIT_MASK(2)
-+#define AXP15060_PWR_OUT_CLDO2_MASK   BIT_MASK(3)
-+#define AXP15060_PWR_OUT_CLDO3_MASK   BIT_MASK(4)
-+#define AXP15060_PWR_OUT_CLDO4_MASK   BIT_MASK(5)
-+#define AXP15060_PWR_OUT_CPUSLDO_MASK BIT_MASK(6)
-+#define AXP15060_PWR_OUT_SW_MASK              BIT_MASK(7)
-+
-+#define AXP15060_DCDC23_POLYPHASE_DUAL_MASK           BIT_MASK(6)
-+#define AXP15060_DCDC46_POLYPHASE_DUAL_MASK           BIT_MASK(7)
-+
-+#define AXP15060_DCDC234_500mV_START  0x00
-+#define AXP15060_DCDC234_500mV_STEPS  70
-+#define AXP15060_DCDC234_500mV_END            \
-+      (AXP15060_DCDC234_500mV_START + AXP15060_DCDC234_500mV_STEPS)
-+#define AXP15060_DCDC234_1220mV_START 0x47
-+#define AXP15060_DCDC234_1220mV_STEPS 16
-+#define AXP15060_DCDC234_1220mV_END           \
-+      (AXP15060_DCDC234_1220mV_START + AXP15060_DCDC234_1220mV_STEPS)
-+#define AXP15060_DCDC234_NUM_VOLTAGES 88
-+
-+#define AXP15060_DCDC5_800mV_START    0x00
-+#define AXP15060_DCDC5_800mV_STEPS    32
-+#define AXP15060_DCDC5_800mV_END              \
-+      (AXP15060_DCDC5_800mV_START + AXP15060_DCDC5_800mV_STEPS)
-+#define AXP15060_DCDC5_1140mV_START   0x21
-+#define AXP15060_DCDC5_1140mV_STEPS   35
-+#define AXP15060_DCDC5_1140mV_END             \
-+      (AXP15060_DCDC5_1140mV_START + AXP15060_DCDC5_1140mV_STEPS)
-+#define AXP15060_DCDC5_NUM_VOLTAGES   69
-+
- #define AXP_DESC_IO(_family, _id, _match, _supply, _min, _max, _step, _vreg,  \
-                   _vmask, _ereg, _emask, _enable_val, _disable_val)           \
-       [_family##_##_id] = {                                                   \
-@@ -638,6 +711,48 @@ static const struct regulator_desc axp22
-       .ops            = &axp20x_ops_sw,
- };
-+static const struct linear_range axp313a_dcdc1_ranges[] = {
-+      REGULATOR_LINEAR_RANGE(500000,   0,  70,  10000),
-+      REGULATOR_LINEAR_RANGE(1220000, 71,  87,  20000),
-+      REGULATOR_LINEAR_RANGE(1600000, 88, 106, 100000),
-+};
-+
-+static const struct linear_range axp313a_dcdc2_ranges[] = {
-+      REGULATOR_LINEAR_RANGE(500000,   0, 70, 10000),
-+      REGULATOR_LINEAR_RANGE(1220000, 71, 87, 20000),
-+};
-+
-+/*
-+ * This is deviating from the datasheet. The values here are taken from the
-+ * BSP driver and have been confirmed by measurements.
-+ */
-+static const struct linear_range axp313a_dcdc3_ranges[] = {
-+      REGULATOR_LINEAR_RANGE(500000,   0,  70, 10000),
-+      REGULATOR_LINEAR_RANGE(1220000, 71, 102, 20000),
-+};
-+
-+static const struct regulator_desc axp313a_regulators[] = {
-+      AXP_DESC_RANGES(AXP313A, DCDC1, "dcdc1", "vin1",
-+                      axp313a_dcdc1_ranges, AXP313A_DCDC1_NUM_VOLTAGES,
-+                      AXP313A_DCDC1_CONRTOL, AXP313A_DCDC_V_OUT_MASK,
-+                      AXP313A_OUTPUT_CONTROL, BIT(0)),
-+      AXP_DESC_RANGES(AXP313A, DCDC2, "dcdc2", "vin2",
-+                      axp313a_dcdc2_ranges, AXP313A_DCDC23_NUM_VOLTAGES,
-+                      AXP313A_DCDC2_CONRTOL, AXP313A_DCDC_V_OUT_MASK,
-+                      AXP313A_OUTPUT_CONTROL, BIT(1)),
-+      AXP_DESC_RANGES(AXP313A, DCDC3, "dcdc3", "vin3",
-+                      axp313a_dcdc3_ranges, AXP313A_DCDC23_NUM_VOLTAGES,
-+                      AXP313A_DCDC3_CONRTOL, AXP313A_DCDC_V_OUT_MASK,
-+                      AXP313A_OUTPUT_CONTROL, BIT(2)),
-+      AXP_DESC(AXP313A, ALDO1, "aldo1", "vin1", 500, 3500, 100,
-+               AXP313A_ALDO1_CONRTOL, AXP313A_LDO_V_OUT_MASK,
-+               AXP313A_OUTPUT_CONTROL, BIT(3)),
-+      AXP_DESC(AXP313A, DLDO1, "dldo1", "vin1", 500, 3500, 100,
-+               AXP313A_DLDO1_CONRTOL, AXP313A_LDO_V_OUT_MASK,
-+               AXP313A_OUTPUT_CONTROL, BIT(4)),
-+      AXP_DESC_FIXED(AXP313A, RTC_LDO, "rtc-ldo", "vin1", 1800),
-+};
-+
- /* DCDC ranges shared with AXP813 */
- static const struct linear_range axp803_dcdc234_ranges[] = {
-       REGULATOR_LINEAR_RANGE(500000,
-@@ -1001,6 +1116,104 @@ static const struct regulator_desc axp81
-                   AXP22X_PWR_OUT_CTRL2, AXP22X_PWR_OUT_DC1SW_MASK),
- };
-+static const struct linear_range axp15060_dcdc234_ranges[] = {
-+      REGULATOR_LINEAR_RANGE(500000,
-+                             AXP15060_DCDC234_500mV_START,
-+                             AXP15060_DCDC234_500mV_END,
-+                             10000),
-+      REGULATOR_LINEAR_RANGE(1220000,
-+                             AXP15060_DCDC234_1220mV_START,
-+                             AXP15060_DCDC234_1220mV_END,
-+                             20000),
-+};
-+
-+static const struct linear_range axp15060_dcdc5_ranges[] = {
-+      REGULATOR_LINEAR_RANGE(800000,
-+                             AXP15060_DCDC5_800mV_START,
-+                             AXP15060_DCDC5_800mV_END,
-+                             10000),
-+      REGULATOR_LINEAR_RANGE(1140000,
-+                             AXP15060_DCDC5_1140mV_START,
-+                             AXP15060_DCDC5_1140mV_END,
-+                             20000),
-+};
-+
-+static const struct regulator_desc axp15060_regulators[] = {
-+      AXP_DESC(AXP15060, DCDC1, "dcdc1", "vin1", 1500, 3400, 100,
-+               AXP15060_DCDC1_V_CTRL, AXP15060_DCDC1_V_CTRL_MASK,
-+               AXP15060_PWR_OUT_CTRL1, AXP15060_PWR_OUT_DCDC1_MASK),
-+      AXP_DESC_RANGES(AXP15060, DCDC2, "dcdc2", "vin2",
-+                      axp15060_dcdc234_ranges, AXP15060_DCDC234_NUM_VOLTAGES,
-+                      AXP15060_DCDC2_V_CTRL, AXP15060_DCDC2_V_CTRL_MASK,
-+                      AXP15060_PWR_OUT_CTRL1, AXP15060_PWR_OUT_DCDC2_MASK),
-+      AXP_DESC_RANGES(AXP15060, DCDC3, "dcdc3", "vin3",
-+                      axp15060_dcdc234_ranges, AXP15060_DCDC234_NUM_VOLTAGES,
-+                      AXP15060_DCDC3_V_CTRL, AXP15060_DCDC3_V_CTRL_MASK,
-+                      AXP15060_PWR_OUT_CTRL1, AXP15060_PWR_OUT_DCDC3_MASK),
-+      AXP_DESC_RANGES(AXP15060, DCDC4, "dcdc4", "vin4",
-+                      axp15060_dcdc234_ranges, AXP15060_DCDC234_NUM_VOLTAGES,
-+                      AXP15060_DCDC4_V_CTRL, AXP15060_DCDC4_V_CTRL_MASK,
-+                      AXP15060_PWR_OUT_CTRL1, AXP15060_PWR_OUT_DCDC4_MASK),
-+      AXP_DESC_RANGES(AXP15060, DCDC5, "dcdc5", "vin5",
-+                      axp15060_dcdc5_ranges, AXP15060_DCDC5_NUM_VOLTAGES,
-+                      AXP15060_DCDC5_V_CTRL, AXP15060_DCDC5_V_CTRL_MASK,
-+                      AXP15060_PWR_OUT_CTRL1, AXP15060_PWR_OUT_DCDC5_MASK),
-+      AXP_DESC(AXP15060, DCDC6, "dcdc6", "vin6", 500, 3400, 100,
-+               AXP15060_DCDC6_V_CTRL, AXP15060_DCDC6_V_CTRL_MASK,
-+               AXP15060_PWR_OUT_CTRL1, AXP15060_PWR_OUT_DCDC6_MASK),
-+      AXP_DESC(AXP15060, ALDO1, "aldo1", "aldoin", 700, 3300, 100,
-+               AXP15060_ALDO1_V_CTRL, AXP15060_ALDO1_V_CTRL_MASK,
-+               AXP15060_PWR_OUT_CTRL2, AXP15060_PWR_OUT_ALDO1_MASK),
-+      AXP_DESC(AXP15060, ALDO2, "aldo2", "aldoin", 700, 3300, 100,
-+               AXP15060_ALDO2_V_CTRL, AXP15060_ALDO2_V_CTRL_MASK,
-+               AXP15060_PWR_OUT_CTRL2, AXP15060_PWR_OUT_ALDO2_MASK),
-+      AXP_DESC(AXP15060, ALDO3, "aldo3", "aldoin", 700, 3300, 100,
-+               AXP15060_ALDO3_V_CTRL, AXP15060_ALDO3_V_CTRL_MASK,
-+               AXP15060_PWR_OUT_CTRL2, AXP15060_PWR_OUT_ALDO3_MASK),
-+      AXP_DESC(AXP15060, ALDO4, "aldo4", "aldoin", 700, 3300, 100,
-+               AXP15060_ALDO4_V_CTRL, AXP15060_ALDO4_V_CTRL_MASK,
-+               AXP15060_PWR_OUT_CTRL2, AXP15060_PWR_OUT_ALDO4_MASK),
-+      AXP_DESC(AXP15060, ALDO5, "aldo5", "aldoin", 700, 3300, 100,
-+               AXP15060_ALDO5_V_CTRL, AXP15060_ALDO5_V_CTRL_MASK,
-+               AXP15060_PWR_OUT_CTRL2, AXP15060_PWR_OUT_ALDO5_MASK),
-+      AXP_DESC(AXP15060, BLDO1, "bldo1", "bldoin", 700, 3300, 100,
-+               AXP15060_BLDO1_V_CTRL, AXP15060_BLDO1_V_CTRL_MASK,
-+               AXP15060_PWR_OUT_CTRL2, AXP15060_PWR_OUT_BLDO1_MASK),
-+      AXP_DESC(AXP15060, BLDO2, "bldo2", "bldoin", 700, 3300, 100,
-+               AXP15060_BLDO2_V_CTRL, AXP15060_BLDO2_V_CTRL_MASK,
-+               AXP15060_PWR_OUT_CTRL2, AXP15060_PWR_OUT_BLDO2_MASK),
-+      AXP_DESC(AXP15060, BLDO3, "bldo3", "bldoin", 700, 3300, 100,
-+               AXP15060_BLDO3_V_CTRL, AXP15060_BLDO3_V_CTRL_MASK,
-+               AXP15060_PWR_OUT_CTRL2, AXP15060_PWR_OUT_BLDO3_MASK),
-+      AXP_DESC(AXP15060, BLDO4, "bldo4", "bldoin", 700, 3300, 100,
-+               AXP15060_BLDO4_V_CTRL, AXP15060_BLDO4_V_CTRL_MASK,
-+               AXP15060_PWR_OUT_CTRL3, AXP15060_PWR_OUT_BLDO4_MASK),
-+      AXP_DESC(AXP15060, BLDO5, "bldo5", "bldoin", 700, 3300, 100,
-+               AXP15060_BLDO5_V_CTRL, AXP15060_BLDO5_V_CTRL_MASK,
-+               AXP15060_PWR_OUT_CTRL3, AXP15060_PWR_OUT_BLDO5_MASK),
-+      AXP_DESC(AXP15060, CLDO1, "cldo1", "cldoin", 700, 3300, 100,
-+               AXP15060_CLDO1_V_CTRL, AXP15060_CLDO1_V_CTRL_MASK,
-+               AXP15060_PWR_OUT_CTRL3, AXP15060_PWR_OUT_CLDO1_MASK),
-+      AXP_DESC(AXP15060, CLDO2, "cldo2", "cldoin", 700, 3300, 100,
-+               AXP15060_CLDO2_V_CTRL, AXP15060_CLDO2_V_CTRL_MASK,
-+               AXP15060_PWR_OUT_CTRL3, AXP15060_PWR_OUT_CLDO2_MASK),
-+      AXP_DESC(AXP15060, CLDO3, "cldo3", "cldoin", 700, 3300, 100,
-+               AXP15060_CLDO3_V_CTRL, AXP15060_CLDO3_V_CTRL_MASK,
-+               AXP15060_PWR_OUT_CTRL3, AXP15060_PWR_OUT_CLDO3_MASK),
-+      AXP_DESC(AXP15060, CLDO4, "cldo4", "cldoin", 700, 4200, 100,
-+               AXP15060_CLDO4_V_CTRL, AXP15060_CLDO4_V_CTRL_MASK,
-+               AXP15060_PWR_OUT_CTRL3, AXP15060_PWR_OUT_CLDO4_MASK),
-+      /* Supply comes from DCDC5 */
-+      AXP_DESC(AXP15060, CPUSLDO, "cpusldo", NULL, 700, 1400, 50,
-+               AXP15060_CPUSLDO_V_CTRL, AXP15060_CPUSLDO_V_CTRL_MASK,
-+               AXP15060_PWR_OUT_CTRL3, AXP15060_PWR_OUT_CPUSLDO_MASK),
-+      /* Supply comes from DCDC1 */
-+      AXP_DESC_SW(AXP15060, SW, "sw", NULL,
-+                  AXP15060_PWR_OUT_CTRL3, AXP15060_PWR_OUT_SW_MASK),
-+      /* Supply comes from ALDO1 */
-+      AXP_DESC_FIXED(AXP15060, RTC_LDO, "rtc-ldo", NULL, 1800),
-+};
-+
- static int axp20x_set_dcdc_freq(struct platform_device *pdev, u32 dcdcfreq)
- {
-       struct axp20x_dev *axp20x = dev_get_drvdata(pdev->dev.parent);
-@@ -1040,6 +1253,16 @@ static int axp20x_set_dcdc_freq(struct p
-               def = 3000;
-               step = 150;
-               break;
-+      case AXP313A_ID:
-+      case AXP15060_ID:
-+              /* The DCDC PWM frequency seems to be fixed to 3 MHz. */
-+              if (dcdcfreq != 0) {
-+                      dev_err(&pdev->dev,
-+                              "DCDC frequency on this PMIC is fixed to 3 MHz.\n");
-+                      return -EINVAL;
-+              }
-+
-+              return 0;
-       default:
-               dev_err(&pdev->dev,
-                       "Setting DCDC frequency for unsupported AXP variant\n");
-@@ -1145,6 +1368,15 @@ static int axp20x_set_dcdc_workmode(stru
-               workmode <<= id - AXP813_DCDC1;
-               break;
-+      case AXP15060_ID:
-+              reg = AXP15060_DCDC_MODE_CTRL2;
-+              if (id < AXP15060_DCDC1 || id > AXP15060_DCDC6)
-+                      return -EINVAL;
-+
-+              mask = AXP22X_WORKMODE_DCDCX_MASK(id - AXP15060_DCDC1);
-+              workmode <<= id - AXP15060_DCDC1;
-+              break;
-+
-       default:
-               /* should not happen */
-               WARN_ON(1);
-@@ -1164,7 +1396,7 @@ static bool axp20x_is_polyphase_slave(st
-       /*
-        * Currently in our supported AXP variants, only AXP803, AXP806,
--       * and AXP813 have polyphase regulators.
-+       * AXP813 and AXP15060 have polyphase regulators.
-        */
-       switch (axp20x->variant) {
-       case AXP803_ID:
-@@ -1196,6 +1428,17 @@ static bool axp20x_is_polyphase_slave(st
-               }
-               break;
-+      case AXP15060_ID:
-+              regmap_read(axp20x->regmap, AXP15060_DCDC_MODE_CTRL1, &reg);
-+
-+              switch (id) {
-+              case AXP15060_DCDC3:
-+                      return !!(reg & AXP15060_DCDC23_POLYPHASE_DUAL_MASK);
-+              case AXP15060_DCDC6:
-+                      return !!(reg & AXP15060_DCDC46_POLYPHASE_DUAL_MASK);
-+              }
-+              break;
-+
-       default:
-               return false;
-       }
-@@ -1217,6 +1460,7 @@ static int axp20x_regulator_probe(struct
-       u32 workmode;
-       const char *dcdc1_name = axp22x_regulators[AXP22X_DCDC1].name;
-       const char *dcdc5_name = axp22x_regulators[AXP22X_DCDC5].name;
-+      const char *aldo1_name = axp15060_regulators[AXP15060_ALDO1].name;
-       bool drivevbus = false;
-       switch (axp20x->variant) {
-@@ -1232,6 +1476,10 @@ static int axp20x_regulator_probe(struct
-               drivevbus = of_property_read_bool(pdev->dev.parent->of_node,
-                                                 "x-powers,drive-vbus-en");
-               break;
-+      case AXP313A_ID:
-+              regulators = axp313a_regulators;
-+              nregulators = AXP313A_REG_ID_MAX;
-+              break;
-       case AXP803_ID:
-               regulators = axp803_regulators;
-               nregulators = AXP803_REG_ID_MAX;
-@@ -1252,6 +1500,10 @@ static int axp20x_regulator_probe(struct
-               drivevbus = of_property_read_bool(pdev->dev.parent->of_node,
-                                                 "x-powers,drive-vbus-en");
-               break;
-+      case AXP15060_ID:
-+              regulators = axp15060_regulators;
-+              nregulators = AXP15060_REG_ID_MAX;
-+              break;
-       default:
-               dev_err(&pdev->dev, "Unsupported AXP variant: %ld\n",
-                       axp20x->variant);
-@@ -1278,8 +1530,9 @@ static int axp20x_regulator_probe(struct
-                       continue;
-               /*
--               * Regulators DC1SW and DC5LDO are connected internally,
--               * so we have to handle their supply names separately.
-+               * Regulators DC1SW, DC5LDO and RTCLDO on AXP15060 are
-+               * connected internally, so we have to handle their supply
-+               * names separately.
-                *
-                * We always register the regulators in proper sequence,
-                * so the supply names are correctly read. See the last
-@@ -1288,7 +1541,8 @@ static int axp20x_regulator_probe(struct
-                */
-               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) ||
-+                  (regulators == axp15060_regulators && i == AXP15060_SW)) {
-                       new_desc = devm_kzalloc(&pdev->dev, sizeof(*desc),
-                                               GFP_KERNEL);
-                       if (!new_desc)
-@@ -1300,7 +1554,8 @@ static int axp20x_regulator_probe(struct
-               }
-               if ((regulators == axp22x_regulators && i == AXP22X_DC5LDO) ||
--                  (regulators == axp809_regulators && i == AXP809_DC5LDO)) {
-+                  (regulators == axp809_regulators && i == AXP809_DC5LDO) ||
-+                  (regulators == axp15060_regulators && i == AXP15060_CPUSLDO)) {
-                       new_desc = devm_kzalloc(&pdev->dev, sizeof(*desc),
-                                               GFP_KERNEL);
-                       if (!new_desc)
-@@ -1311,6 +1566,18 @@ static int axp20x_regulator_probe(struct
-                       desc = new_desc;
-               }
-+
-+              if (regulators == axp15060_regulators && i == AXP15060_RTC_LDO) {
-+                      new_desc = devm_kzalloc(&pdev->dev, sizeof(*desc),
-+                                              GFP_KERNEL);
-+                      if (!new_desc)
-+                              return -ENOMEM;
-+
-+                      *new_desc = regulators[i];
-+                      new_desc->supply_name = aldo1_name;
-+                      desc = new_desc;
-+              }
-+
-               rdev = devm_regulator_register(&pdev->dev, desc, &config);
-               if (IS_ERR(rdev)) {
-                       dev_err(&pdev->dev, "Failed to register %s\n",
-@@ -1329,19 +1596,26 @@ static int axp20x_regulator_probe(struct
-               }
-               /*
--               * Save AXP22X DCDC1 / DCDC5 regulator names for later.
-+               * Save AXP22X DCDC1 / DCDC5 / AXP15060 ALDO1 regulator names for later.
-                */
-               if ((regulators == axp22x_regulators && i == AXP22X_DCDC1) ||
--                  (regulators == axp809_regulators && i == AXP809_DCDC1))
-+                  (regulators == axp809_regulators && i == AXP809_DCDC1) ||
-+                  (regulators == axp15060_regulators && i == AXP15060_DCDC1))
-                       of_property_read_string(rdev->dev.of_node,
-                                               "regulator-name",
-                                               &dcdc1_name);
-               if ((regulators == axp22x_regulators && i == AXP22X_DCDC5) ||
--                  (regulators == axp809_regulators && i == AXP809_DCDC5))
-+                  (regulators == axp809_regulators && i == AXP809_DCDC5) ||
-+                  (regulators == axp15060_regulators && i == AXP15060_DCDC5))
-                       of_property_read_string(rdev->dev.of_node,
-                                               "regulator-name",
-                                               &dcdc5_name);
-+
-+              if (regulators == axp15060_regulators && i == AXP15060_ALDO1)
-+                      of_property_read_string(rdev->dev.of_node,
-+                                              "regulator-name",
-+                                              &aldo1_name);
-       }
-       if (drivevbus) {
-@@ -1364,6 +1638,7 @@ static struct platform_driver axp20x_reg
-       .probe  = axp20x_regulator_probe,
-       .driver = {
-               .name           = "axp20x-regulator",
-+              .probe_type     = PROBE_PREFER_ASYNCHRONOUS,
-       },
- };