mfd: axp20x: Add support for AXP717 PMIC
authorAndre Przywara <andre.przywara@arm.com>
Sun, 10 Mar 2024 01:02:10 +0000 (01:02 +0000)
committerLee Jones <lee@kernel.org>
Thu, 28 Mar 2024 09:50:59 +0000 (09:50 +0000)
The AXP717a is a PMIC chip produced by X-Powers, it can be connected to
an I2C or RSB bus.

It's a rather complete PMIC, with many regulators, interrupts, an ADC and
battery charging functionality. It also offer USB type-C CC pin
handling.

Describe the regmap and the MFD bits, along with the registers exposed
via I2C or RSB. This covers the regulator, interrupts and power key
devices for now.
Advertise the device using the new compatible string.

Signed-off-by: Andre Przywara <andre.przywara@arm.com>
Acked-by: Jernej Skrabec <jernej.skrabec@gmail.com>
Tested-by: Ryan Walklin <ryan@testtoast.com>
Link: https://lore.kernel.org/r/20240310010211.28653-4-andre.przywara@arm.com
Signed-off-by: Lee Jones <lee@kernel.org>
drivers/mfd/axp20x-i2c.c
drivers/mfd/axp20x-rsb.c
drivers/mfd/axp20x.c
include/linux/mfd/axp20x.h

index 68d3560cfe4a0ec8076d42723daa53a200713fb4..b8e7ac89f6976f40fbb845b557caf664fa722466 100644 (file)
@@ -65,6 +65,7 @@ static const struct of_device_id axp20x_i2c_of_match[] = {
        { .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,axp717", .data = (void *)AXP717_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 },
@@ -81,6 +82,7 @@ static const struct i2c_device_id axp20x_i2c_id[] = {
        { "axp221", 0 },
        { "axp223", 0 },
        { "axp313a", 0 },
+       { "axp717", 0 },
        { "axp803", 0 },
        { "axp806", 0 },
        { "axp15060", 0 },
index 214bc0d84d44cc369f5bdfb2c5b61773d15440fa..059656f2a1bd698c3a7f463cc34463fdec15caf8 100644 (file)
@@ -58,6 +58,7 @@ static void axp20x_rsb_remove(struct sunxi_rsb_device *rdev)
 
 static const struct of_device_id axp20x_rsb_of_match[] = {
        { .compatible = "x-powers,axp223", .data = (void *)AXP223_ID },
+       { .compatible = "x-powers,axp717", .data = (void *)AXP717_ID },
        { .compatible = "x-powers,axp803", .data = (void *)AXP803_ID },
        { .compatible = "x-powers,axp806", .data = (void *)AXP806_ID },
        { .compatible = "x-powers,axp809", .data = (void *)AXP809_ID },
index d8daa593ebd5397710e44534212862d5c9dee709..48ce6ea693cea339ce1cfc340ec85c6dec1beccd 100644 (file)
@@ -42,6 +42,7 @@ static const char * const axp20x_model_names[] = {
        "AXP223",
        "AXP288",
        "AXP313a",
+       "AXP717",
        "AXP803",
        "AXP806",
        "AXP809",
@@ -207,6 +208,25 @@ static const struct regmap_access_table axp313a_volatile_table = {
        .n_yes_ranges = ARRAY_SIZE(axp313a_volatile_ranges),
 };
 
+static const struct regmap_range axp717_writeable_ranges[] = {
+       regmap_reg_range(AXP717_IRQ0_EN, AXP717_IRQ4_EN),
+       regmap_reg_range(AXP717_DCDC_OUTPUT_CONTROL, AXP717_CPUSLDO_CONTROL),
+};
+
+static const struct regmap_range axp717_volatile_ranges[] = {
+       regmap_reg_range(AXP717_IRQ0_STATE, AXP717_IRQ4_STATE),
+};
+
+static const struct regmap_access_table axp717_writeable_table = {
+       .yes_ranges = axp717_writeable_ranges,
+       .n_yes_ranges = ARRAY_SIZE(axp717_writeable_ranges),
+};
+
+static const struct regmap_access_table axp717_volatile_table = {
+       .yes_ranges = axp717_volatile_ranges,
+       .n_yes_ranges = ARRAY_SIZE(axp717_volatile_ranges),
+};
+
 static const struct regmap_range axp806_volatile_ranges[] = {
        regmap_reg_range(AXP20X_IRQ1_STATE, AXP20X_IRQ2_STATE),
 };
@@ -317,6 +337,11 @@ static const struct resource axp313a_pek_resources[] = {
        DEFINE_RES_IRQ_NAMED(AXP313A_IRQ_PEK_FAL_EDGE, "PEK_DBF"),
 };
 
+static const struct resource axp717_pek_resources[] = {
+       DEFINE_RES_IRQ_NAMED(AXP717_IRQ_PEK_RIS_EDGE, "PEK_DBR"),
+       DEFINE_RES_IRQ_NAMED(AXP717_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"),
@@ -391,6 +416,15 @@ static const struct regmap_config axp313a_regmap_config = {
        .cache_type = REGCACHE_MAPLE,
 };
 
+static const struct regmap_config axp717_regmap_config = {
+       .reg_bits = 8,
+       .val_bits = 8,
+       .wr_table = &axp717_writeable_table,
+       .volatile_table = &axp717_volatile_table,
+       .max_register = AXP717_CPUSLDO_CONTROL,
+       .cache_type = REGCACHE_RBTREE,
+};
+
 static const struct regmap_config axp806_regmap_config = {
        .reg_bits       = 8,
        .val_bits       = 8,
@@ -589,6 +623,40 @@ static const struct regmap_irq axp313a_regmap_irqs[] = {
        INIT_REGMAP_IRQ(AXP313A, DIE_TEMP_HIGH,         0, 0),
 };
 
+static const struct regmap_irq axp717_regmap_irqs[] = {
+       INIT_REGMAP_IRQ(AXP717, SOC_DROP_LVL2,          0, 7),
+       INIT_REGMAP_IRQ(AXP717, SOC_DROP_LVL1,          0, 6),
+       INIT_REGMAP_IRQ(AXP717, GAUGE_NEW_SOC,          0, 4),
+       INIT_REGMAP_IRQ(AXP717, BOOST_OVER_V,           0, 2),
+       INIT_REGMAP_IRQ(AXP717, VBUS_OVER_V,            0, 1),
+       INIT_REGMAP_IRQ(AXP717, VBUS_FAULT,             0, 0),
+       INIT_REGMAP_IRQ(AXP717, VBUS_PLUGIN,            1, 7),
+       INIT_REGMAP_IRQ(AXP717, VBUS_REMOVAL,           1, 6),
+       INIT_REGMAP_IRQ(AXP717, BATT_PLUGIN,            1, 5),
+       INIT_REGMAP_IRQ(AXP717, BATT_REMOVAL,           1, 4),
+       INIT_REGMAP_IRQ(AXP717, PEK_SHORT,              1, 3),
+       INIT_REGMAP_IRQ(AXP717, PEK_LONG,               1, 2),
+       INIT_REGMAP_IRQ(AXP717, PEK_FAL_EDGE,           1, 1),
+       INIT_REGMAP_IRQ(AXP717, PEK_RIS_EDGE,           1, 0),
+       INIT_REGMAP_IRQ(AXP717, WDOG_EXPIRE,            2, 7),
+       INIT_REGMAP_IRQ(AXP717, LDO_OVER_CURR,          2, 6),
+       INIT_REGMAP_IRQ(AXP717, BATT_OVER_CURR,         2, 5),
+       INIT_REGMAP_IRQ(AXP717, CHARG_DONE,             2, 4),
+       INIT_REGMAP_IRQ(AXP717, CHARG,                  2, 3),
+       INIT_REGMAP_IRQ(AXP717, DIE_TEMP_HIGH,          2, 2),
+       INIT_REGMAP_IRQ(AXP717, CHARG_TIMER,            2, 1),
+       INIT_REGMAP_IRQ(AXP717, BATT_OVER_V,            2, 0),
+       INIT_REGMAP_IRQ(AXP717, BC_USB_DONE,            3, 7),
+       INIT_REGMAP_IRQ(AXP717, BC_USB_CHNG,            3, 6),
+       INIT_REGMAP_IRQ(AXP717, BATT_QUIT_TEMP_HIGH,    3, 4),
+       INIT_REGMAP_IRQ(AXP717, BATT_CHG_TEMP_HIGH,     3, 3),
+       INIT_REGMAP_IRQ(AXP717, BATT_CHG_TEMP_LOW,      3, 2),
+       INIT_REGMAP_IRQ(AXP717, BATT_ACT_TEMP_HIGH,     3, 1),
+       INIT_REGMAP_IRQ(AXP717, BATT_ACT_TEMP_LOW,      3, 0),
+       INIT_REGMAP_IRQ(AXP717, TYPEC_REMOVE,           4, 6),
+       INIT_REGMAP_IRQ(AXP717, TYPEC_PLUGIN,           4, 5),
+};
+
 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),
@@ -776,6 +844,17 @@ static const struct regmap_irq_chip axp313a_regmap_irq_chip = {
        .num_regs               = 1,
 };
 
+static const struct regmap_irq_chip axp717_regmap_irq_chip = {
+       .name                   = "axp717_irq_chip",
+       .status_base            = AXP717_IRQ0_STATE,
+       .ack_base               = AXP717_IRQ0_STATE,
+       .unmask_base            = AXP717_IRQ0_EN,
+       .init_ack_masked        = true,
+       .irqs                   = axp717_regmap_irqs,
+       .num_irqs               = ARRAY_SIZE(axp717_regmap_irqs),
+       .num_regs               = 5,
+};
+
 static const struct regmap_irq_chip axp803_regmap_irq_chip = {
        .name                   = "axp803",
        .status_base            = AXP20X_IRQ1_STATE,
@@ -941,6 +1020,11 @@ static struct mfd_cell axp313a_cells[] = {
        MFD_CELL_RES("axp313a-pek", axp313a_pek_resources),
 };
 
+static struct mfd_cell axp717_cells[] = {
+       MFD_CELL_NAME("axp20x-regulator"),
+       MFD_CELL_RES("axp20x-pek", axp717_pek_resources),
+};
+
 static const struct resource axp288_adc_resources[] = {
        DEFINE_RES_IRQ_NAMED(AXP288_IRQ_GPADC, "GPADC"),
 };
@@ -1181,6 +1265,12 @@ int axp20x_match_device(struct axp20x_dev *axp20x)
                axp20x->regmap_cfg = &axp313a_regmap_config;
                axp20x->regmap_irq_chip = &axp313a_regmap_irq_chip;
                break;
+       case AXP717_ID:
+               axp20x->nr_cells = ARRAY_SIZE(axp717_cells);
+               axp20x->cells = axp717_cells;
+               axp20x->regmap_cfg = &axp717_regmap_config;
+               axp20x->regmap_irq_chip = &axp717_regmap_irq_chip;
+               break;
        case AXP803_ID:
                axp20x->nr_cells = ARRAY_SIZE(axp803_cells);
                axp20x->cells = axp803_cells;
index 9b2b7ac2107f44d1dd0565d6aeb492119d80e18a..fd7a41a69526f8fbf6a87282867d353967fb08d9 100644 (file)
@@ -19,6 +19,7 @@ enum axp20x_variants {
        AXP223_ID,
        AXP288_ID,
        AXP313A_ID,
+       AXP717_ID,
        AXP803_ID,
        AXP806_ID,
        AXP809_ID,
@@ -113,6 +114,38 @@ enum axp20x_variants {
 #define AXP313A_IRQ_EN                 0x20
 #define AXP313A_IRQ_STATE              0x21
 
+#define AXP717_ON_INDICATE             0x00
+#define AXP717_IRQ0_EN                 0x40
+#define AXP717_IRQ1_EN                 0x41
+#define AXP717_IRQ2_EN                 0x42
+#define AXP717_IRQ3_EN                 0x43
+#define AXP717_IRQ4_EN                 0x44
+#define AXP717_IRQ0_STATE              0x48
+#define AXP717_IRQ1_STATE              0x49
+#define AXP717_IRQ2_STATE              0x4a
+#define AXP717_IRQ3_STATE              0x4b
+#define AXP717_IRQ4_STATE              0x4c
+#define AXP717_DCDC_OUTPUT_CONTROL     0x80
+#define AXP717_DCDC1_CONTROL           0x83
+#define AXP717_DCDC2_CONTROL           0x84
+#define AXP717_DCDC3_CONTROL           0x85
+#define AXP717_DCDC4_CONTROL           0x86
+#define AXP717_LDO0_OUTPUT_CONTROL     0x90
+#define AXP717_LDO1_OUTPUT_CONTROL     0x91
+#define AXP717_ALDO1_CONTROL           0x93
+#define AXP717_ALDO2_CONTROL           0x94
+#define AXP717_ALDO3_CONTROL           0x95
+#define AXP717_ALDO4_CONTROL           0x96
+#define AXP717_BLDO1_CONTROL           0x97
+#define AXP717_BLDO2_CONTROL           0x98
+#define AXP717_BLDO3_CONTROL           0x99
+#define AXP717_BLDO4_CONTROL           0x9a
+#define AXP717_CLDO1_CONTROL           0x9b
+#define AXP717_CLDO2_CONTROL           0x9c
+#define AXP717_CLDO3_CONTROL           0x9d
+#define AXP717_CLDO4_CONTROL           0x9e
+#define AXP717_CPUSLDO_CONTROL         0x9f
+
 #define AXP806_STARTUP_SRC             0x00
 #define AXP806_CHIP_ID                 0x03
 #define AXP806_PWR_OUT_CTRL1           0x10
@@ -732,6 +765,40 @@ enum axp313a_irqs {
        AXP313A_IRQ_PEK_RIS_EDGE,
 };
 
+enum axp717_irqs {
+       AXP717_IRQ_VBUS_FAULT,
+       AXP717_IRQ_VBUS_OVER_V,
+       AXP717_IRQ_BOOST_OVER_V,
+       AXP717_IRQ_GAUGE_NEW_SOC = 4,
+       AXP717_IRQ_SOC_DROP_LVL1 = 6,
+       AXP717_IRQ_SOC_DROP_LVL2,
+       AXP717_IRQ_PEK_RIS_EDGE,
+       AXP717_IRQ_PEK_FAL_EDGE,
+       AXP717_IRQ_PEK_LONG,
+       AXP717_IRQ_PEK_SHORT,
+       AXP717_IRQ_BATT_REMOVAL,
+       AXP717_IRQ_BATT_PLUGIN,
+       AXP717_IRQ_VBUS_REMOVAL,
+       AXP717_IRQ_VBUS_PLUGIN,
+       AXP717_IRQ_BATT_OVER_V,
+       AXP717_IRQ_CHARG_TIMER,
+       AXP717_IRQ_DIE_TEMP_HIGH,
+       AXP717_IRQ_CHARG,
+       AXP717_IRQ_CHARG_DONE,
+       AXP717_IRQ_BATT_OVER_CURR,
+       AXP717_IRQ_LDO_OVER_CURR,
+       AXP717_IRQ_WDOG_EXPIRE,
+       AXP717_IRQ_BATT_ACT_TEMP_LOW,
+       AXP717_IRQ_BATT_ACT_TEMP_HIGH,
+       AXP717_IRQ_BATT_CHG_TEMP_LOW,
+       AXP717_IRQ_BATT_CHG_TEMP_HIGH,
+       AXP717_IRQ_BATT_QUIT_TEMP_HIGH,
+       AXP717_IRQ_BC_USB_CHNG = 30,
+       AXP717_IRQ_BC_USB_DONE,
+       AXP717_IRQ_TYPEC_PLUGIN = 37,
+       AXP717_IRQ_TYPEC_REMOVE,
+};
+
 enum axp803_irqs {
        AXP803_IRQ_ACIN_OVER_V = 1,
        AXP803_IRQ_ACIN_PLUGIN,