Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

mfd: axp20x: Add support for AXP717 PMIC

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>

authored by

Andre Przywara and committed by
Lee Jones
b5bfc8ab 3bfe7fe6

+160
+2
drivers/mfd/axp20x-i2c.c
··· 65 65 { .compatible = "x-powers,axp221", .data = (void *)AXP221_ID }, 66 66 { .compatible = "x-powers,axp223", .data = (void *)AXP223_ID }, 67 67 { .compatible = "x-powers,axp313a", .data = (void *)AXP313A_ID }, 68 + { .compatible = "x-powers,axp717", .data = (void *)AXP717_ID }, 68 69 { .compatible = "x-powers,axp803", .data = (void *)AXP803_ID }, 69 70 { .compatible = "x-powers,axp806", .data = (void *)AXP806_ID }, 70 71 { .compatible = "x-powers,axp15060", .data = (void *)AXP15060_ID }, ··· 82 81 { "axp221", 0 }, 83 82 { "axp223", 0 }, 84 83 { "axp313a", 0 }, 84 + { "axp717", 0 }, 85 85 { "axp803", 0 }, 86 86 { "axp806", 0 }, 87 87 { "axp15060", 0 },
+1
drivers/mfd/axp20x-rsb.c
··· 58 58 59 59 static const struct of_device_id axp20x_rsb_of_match[] = { 60 60 { .compatible = "x-powers,axp223", .data = (void *)AXP223_ID }, 61 + { .compatible = "x-powers,axp717", .data = (void *)AXP717_ID }, 61 62 { .compatible = "x-powers,axp803", .data = (void *)AXP803_ID }, 62 63 { .compatible = "x-powers,axp806", .data = (void *)AXP806_ID }, 63 64 { .compatible = "x-powers,axp809", .data = (void *)AXP809_ID },
+90
drivers/mfd/axp20x.c
··· 42 42 "AXP223", 43 43 "AXP288", 44 44 "AXP313a", 45 + "AXP717", 45 46 "AXP803", 46 47 "AXP806", 47 48 "AXP809", ··· 208 207 .n_yes_ranges = ARRAY_SIZE(axp313a_volatile_ranges), 209 208 }; 210 209 210 + static const struct regmap_range axp717_writeable_ranges[] = { 211 + regmap_reg_range(AXP717_IRQ0_EN, AXP717_IRQ4_EN), 212 + regmap_reg_range(AXP717_DCDC_OUTPUT_CONTROL, AXP717_CPUSLDO_CONTROL), 213 + }; 214 + 215 + static const struct regmap_range axp717_volatile_ranges[] = { 216 + regmap_reg_range(AXP717_IRQ0_STATE, AXP717_IRQ4_STATE), 217 + }; 218 + 219 + static const struct regmap_access_table axp717_writeable_table = { 220 + .yes_ranges = axp717_writeable_ranges, 221 + .n_yes_ranges = ARRAY_SIZE(axp717_writeable_ranges), 222 + }; 223 + 224 + static const struct regmap_access_table axp717_volatile_table = { 225 + .yes_ranges = axp717_volatile_ranges, 226 + .n_yes_ranges = ARRAY_SIZE(axp717_volatile_ranges), 227 + }; 228 + 211 229 static const struct regmap_range axp806_volatile_ranges[] = { 212 230 regmap_reg_range(AXP20X_IRQ1_STATE, AXP20X_IRQ2_STATE), 213 231 }; ··· 337 317 DEFINE_RES_IRQ_NAMED(AXP313A_IRQ_PEK_FAL_EDGE, "PEK_DBF"), 338 318 }; 339 319 320 + static const struct resource axp717_pek_resources[] = { 321 + DEFINE_RES_IRQ_NAMED(AXP717_IRQ_PEK_RIS_EDGE, "PEK_DBR"), 322 + DEFINE_RES_IRQ_NAMED(AXP717_IRQ_PEK_FAL_EDGE, "PEK_DBF"), 323 + }; 324 + 340 325 static const struct resource axp803_pek_resources[] = { 341 326 DEFINE_RES_IRQ_NAMED(AXP803_IRQ_PEK_RIS_EDGE, "PEK_DBR"), 342 327 DEFINE_RES_IRQ_NAMED(AXP803_IRQ_PEK_FAL_EDGE, "PEK_DBF"), ··· 414 389 .volatile_table = &axp313a_volatile_table, 415 390 .max_register = AXP313A_IRQ_STATE, 416 391 .cache_type = REGCACHE_MAPLE, 392 + }; 393 + 394 + static const struct regmap_config axp717_regmap_config = { 395 + .reg_bits = 8, 396 + .val_bits = 8, 397 + .wr_table = &axp717_writeable_table, 398 + .volatile_table = &axp717_volatile_table, 399 + .max_register = AXP717_CPUSLDO_CONTROL, 400 + .cache_type = REGCACHE_RBTREE, 417 401 }; 418 402 419 403 static const struct regmap_config axp806_regmap_config = { ··· 623 589 INIT_REGMAP_IRQ(AXP313A, DIE_TEMP_HIGH, 0, 0), 624 590 }; 625 591 592 + static const struct regmap_irq axp717_regmap_irqs[] = { 593 + INIT_REGMAP_IRQ(AXP717, SOC_DROP_LVL2, 0, 7), 594 + INIT_REGMAP_IRQ(AXP717, SOC_DROP_LVL1, 0, 6), 595 + INIT_REGMAP_IRQ(AXP717, GAUGE_NEW_SOC, 0, 4), 596 + INIT_REGMAP_IRQ(AXP717, BOOST_OVER_V, 0, 2), 597 + INIT_REGMAP_IRQ(AXP717, VBUS_OVER_V, 0, 1), 598 + INIT_REGMAP_IRQ(AXP717, VBUS_FAULT, 0, 0), 599 + INIT_REGMAP_IRQ(AXP717, VBUS_PLUGIN, 1, 7), 600 + INIT_REGMAP_IRQ(AXP717, VBUS_REMOVAL, 1, 6), 601 + INIT_REGMAP_IRQ(AXP717, BATT_PLUGIN, 1, 5), 602 + INIT_REGMAP_IRQ(AXP717, BATT_REMOVAL, 1, 4), 603 + INIT_REGMAP_IRQ(AXP717, PEK_SHORT, 1, 3), 604 + INIT_REGMAP_IRQ(AXP717, PEK_LONG, 1, 2), 605 + INIT_REGMAP_IRQ(AXP717, PEK_FAL_EDGE, 1, 1), 606 + INIT_REGMAP_IRQ(AXP717, PEK_RIS_EDGE, 1, 0), 607 + INIT_REGMAP_IRQ(AXP717, WDOG_EXPIRE, 2, 7), 608 + INIT_REGMAP_IRQ(AXP717, LDO_OVER_CURR, 2, 6), 609 + INIT_REGMAP_IRQ(AXP717, BATT_OVER_CURR, 2, 5), 610 + INIT_REGMAP_IRQ(AXP717, CHARG_DONE, 2, 4), 611 + INIT_REGMAP_IRQ(AXP717, CHARG, 2, 3), 612 + INIT_REGMAP_IRQ(AXP717, DIE_TEMP_HIGH, 2, 2), 613 + INIT_REGMAP_IRQ(AXP717, CHARG_TIMER, 2, 1), 614 + INIT_REGMAP_IRQ(AXP717, BATT_OVER_V, 2, 0), 615 + INIT_REGMAP_IRQ(AXP717, BC_USB_DONE, 3, 7), 616 + INIT_REGMAP_IRQ(AXP717, BC_USB_CHNG, 3, 6), 617 + INIT_REGMAP_IRQ(AXP717, BATT_QUIT_TEMP_HIGH, 3, 4), 618 + INIT_REGMAP_IRQ(AXP717, BATT_CHG_TEMP_HIGH, 3, 3), 619 + INIT_REGMAP_IRQ(AXP717, BATT_CHG_TEMP_LOW, 3, 2), 620 + INIT_REGMAP_IRQ(AXP717, BATT_ACT_TEMP_HIGH, 3, 1), 621 + INIT_REGMAP_IRQ(AXP717, BATT_ACT_TEMP_LOW, 3, 0), 622 + INIT_REGMAP_IRQ(AXP717, TYPEC_REMOVE, 4, 6), 623 + INIT_REGMAP_IRQ(AXP717, TYPEC_PLUGIN, 4, 5), 624 + }; 625 + 626 626 static const struct regmap_irq axp803_regmap_irqs[] = { 627 627 INIT_REGMAP_IRQ(AXP803, ACIN_OVER_V, 0, 7), 628 628 INIT_REGMAP_IRQ(AXP803, ACIN_PLUGIN, 0, 6), ··· 844 776 .num_regs = 1, 845 777 }; 846 778 779 + static const struct regmap_irq_chip axp717_regmap_irq_chip = { 780 + .name = "axp717_irq_chip", 781 + .status_base = AXP717_IRQ0_STATE, 782 + .ack_base = AXP717_IRQ0_STATE, 783 + .unmask_base = AXP717_IRQ0_EN, 784 + .init_ack_masked = true, 785 + .irqs = axp717_regmap_irqs, 786 + .num_irqs = ARRAY_SIZE(axp717_regmap_irqs), 787 + .num_regs = 5, 788 + }; 789 + 847 790 static const struct regmap_irq_chip axp803_regmap_irq_chip = { 848 791 .name = "axp803", 849 792 .status_base = AXP20X_IRQ1_STATE, ··· 1018 939 static struct mfd_cell axp313a_cells[] = { 1019 940 MFD_CELL_NAME("axp20x-regulator"), 1020 941 MFD_CELL_RES("axp313a-pek", axp313a_pek_resources), 942 + }; 943 + 944 + static struct mfd_cell axp717_cells[] = { 945 + MFD_CELL_NAME("axp20x-regulator"), 946 + MFD_CELL_RES("axp20x-pek", axp717_pek_resources), 1021 947 }; 1022 948 1023 949 static const struct resource axp288_adc_resources[] = { ··· 1264 1180 axp20x->cells = axp313a_cells; 1265 1181 axp20x->regmap_cfg = &axp313a_regmap_config; 1266 1182 axp20x->regmap_irq_chip = &axp313a_regmap_irq_chip; 1183 + break; 1184 + case AXP717_ID: 1185 + axp20x->nr_cells = ARRAY_SIZE(axp717_cells); 1186 + axp20x->cells = axp717_cells; 1187 + axp20x->regmap_cfg = &axp717_regmap_config; 1188 + axp20x->regmap_irq_chip = &axp717_regmap_irq_chip; 1267 1189 break; 1268 1190 case AXP803_ID: 1269 1191 axp20x->nr_cells = ARRAY_SIZE(axp803_cells);
+67
include/linux/mfd/axp20x.h
··· 19 19 AXP223_ID, 20 20 AXP288_ID, 21 21 AXP313A_ID, 22 + AXP717_ID, 22 23 AXP803_ID, 23 24 AXP806_ID, 24 25 AXP809_ID, ··· 113 112 #define AXP313A_SHUTDOWN_CTRL 0x1a 114 113 #define AXP313A_IRQ_EN 0x20 115 114 #define AXP313A_IRQ_STATE 0x21 115 + 116 + #define AXP717_ON_INDICATE 0x00 117 + #define AXP717_IRQ0_EN 0x40 118 + #define AXP717_IRQ1_EN 0x41 119 + #define AXP717_IRQ2_EN 0x42 120 + #define AXP717_IRQ3_EN 0x43 121 + #define AXP717_IRQ4_EN 0x44 122 + #define AXP717_IRQ0_STATE 0x48 123 + #define AXP717_IRQ1_STATE 0x49 124 + #define AXP717_IRQ2_STATE 0x4a 125 + #define AXP717_IRQ3_STATE 0x4b 126 + #define AXP717_IRQ4_STATE 0x4c 127 + #define AXP717_DCDC_OUTPUT_CONTROL 0x80 128 + #define AXP717_DCDC1_CONTROL 0x83 129 + #define AXP717_DCDC2_CONTROL 0x84 130 + #define AXP717_DCDC3_CONTROL 0x85 131 + #define AXP717_DCDC4_CONTROL 0x86 132 + #define AXP717_LDO0_OUTPUT_CONTROL 0x90 133 + #define AXP717_LDO1_OUTPUT_CONTROL 0x91 134 + #define AXP717_ALDO1_CONTROL 0x93 135 + #define AXP717_ALDO2_CONTROL 0x94 136 + #define AXP717_ALDO3_CONTROL 0x95 137 + #define AXP717_ALDO4_CONTROL 0x96 138 + #define AXP717_BLDO1_CONTROL 0x97 139 + #define AXP717_BLDO2_CONTROL 0x98 140 + #define AXP717_BLDO3_CONTROL 0x99 141 + #define AXP717_BLDO4_CONTROL 0x9a 142 + #define AXP717_CLDO1_CONTROL 0x9b 143 + #define AXP717_CLDO2_CONTROL 0x9c 144 + #define AXP717_CLDO3_CONTROL 0x9d 145 + #define AXP717_CLDO4_CONTROL 0x9e 146 + #define AXP717_CPUSLDO_CONTROL 0x9f 116 147 117 148 #define AXP806_STARTUP_SRC 0x00 118 149 #define AXP806_CHIP_ID 0x03 ··· 763 730 AXP313A_IRQ_PEK_SHORT, 764 731 AXP313A_IRQ_PEK_FAL_EDGE, 765 732 AXP313A_IRQ_PEK_RIS_EDGE, 733 + }; 734 + 735 + enum axp717_irqs { 736 + AXP717_IRQ_VBUS_FAULT, 737 + AXP717_IRQ_VBUS_OVER_V, 738 + AXP717_IRQ_BOOST_OVER_V, 739 + AXP717_IRQ_GAUGE_NEW_SOC = 4, 740 + AXP717_IRQ_SOC_DROP_LVL1 = 6, 741 + AXP717_IRQ_SOC_DROP_LVL2, 742 + AXP717_IRQ_PEK_RIS_EDGE, 743 + AXP717_IRQ_PEK_FAL_EDGE, 744 + AXP717_IRQ_PEK_LONG, 745 + AXP717_IRQ_PEK_SHORT, 746 + AXP717_IRQ_BATT_REMOVAL, 747 + AXP717_IRQ_BATT_PLUGIN, 748 + AXP717_IRQ_VBUS_REMOVAL, 749 + AXP717_IRQ_VBUS_PLUGIN, 750 + AXP717_IRQ_BATT_OVER_V, 751 + AXP717_IRQ_CHARG_TIMER, 752 + AXP717_IRQ_DIE_TEMP_HIGH, 753 + AXP717_IRQ_CHARG, 754 + AXP717_IRQ_CHARG_DONE, 755 + AXP717_IRQ_BATT_OVER_CURR, 756 + AXP717_IRQ_LDO_OVER_CURR, 757 + AXP717_IRQ_WDOG_EXPIRE, 758 + AXP717_IRQ_BATT_ACT_TEMP_LOW, 759 + AXP717_IRQ_BATT_ACT_TEMP_HIGH, 760 + AXP717_IRQ_BATT_CHG_TEMP_LOW, 761 + AXP717_IRQ_BATT_CHG_TEMP_HIGH, 762 + AXP717_IRQ_BATT_QUIT_TEMP_HIGH, 763 + AXP717_IRQ_BC_USB_CHNG = 30, 764 + AXP717_IRQ_BC_USB_DONE, 765 + AXP717_IRQ_TYPEC_PLUGIN = 37, 766 + AXP717_IRQ_TYPEC_REMOVE, 766 767 }; 767 768 768 769 enum axp803_irqs {