From 4af62c65cb051515d82381111eb2b43933fef996 Mon Sep 17 00:00:00 2001 From: aiamadeus <2789289348@qq.com> Date: Wed, 3 Jan 2024 23:19:31 +0800 Subject: [PATCH] generic: 6.1: backport AXP PMIC support --- ...x-Switch-to-the-sys-off-handler-API.patch} | 0 ...axp20x-Add-support-for-AXP15060-PMIC.patch | 343 ++++++++++++++++ ...axp20x-Add-support-for-AXP313a-PMIC.patch} | 28 +- ...20x-Add-support-for-AXP313a-variant.patch} | 0 ...egulator-axp20x-Add-AXP15060-support.patch | 367 +++++++++++++++++ ....5-mfd-axp20x-Add-support-for-AXP192.patch | 383 ++++++++++++++++++ 6 files changed, 1107 insertions(+), 14 deletions(-) rename target/linux/generic/backport-6.1/{850-v6.3-mfd-axp20x-Switch-to-the-sys-off-handler-API.patch => 880-v6.3-mfd-axp20x-Switch-to-the-sys-off-handler-API.patch} (100%) create mode 100644 target/linux/generic/backport-6.1/881-v6.4-mfd-axp20x-Add-support-for-AXP15060-PMIC.patch rename target/linux/generic/backport-6.1/{851-v6.5-mfd-axp20x-Add-support-for-AXP313a-PMIC.patch => 882-v6.5-mfd-axp20x-Add-support-for-AXP313a-PMIC.patch} (90%) rename target/linux/generic/backport-6.1/{852-v6.5-regulator-axp20x-Add-support-for-AXP313a-variant.patch => 883-v6.5-regulator-axp20x-Add-support-for-AXP313a-variant.patch} (100%) create mode 100644 target/linux/generic/backport-6.1/884-v6.5-regulator-axp20x-Add-AXP15060-support.patch create mode 100644 target/linux/generic/backport-6.1/885-v6.5-mfd-axp20x-Add-support-for-AXP192.patch diff --git a/target/linux/generic/backport-6.1/850-v6.3-mfd-axp20x-Switch-to-the-sys-off-handler-API.patch b/target/linux/generic/backport-6.1/880-v6.3-mfd-axp20x-Switch-to-the-sys-off-handler-API.patch similarity index 100% rename from target/linux/generic/backport-6.1/850-v6.3-mfd-axp20x-Switch-to-the-sys-off-handler-API.patch rename to target/linux/generic/backport-6.1/880-v6.3-mfd-axp20x-Switch-to-the-sys-off-handler-API.patch diff --git a/target/linux/generic/backport-6.1/881-v6.4-mfd-axp20x-Add-support-for-AXP15060-PMIC.patch b/target/linux/generic/backport-6.1/881-v6.4-mfd-axp20x-Add-support-for-AXP15060-PMIC.patch new file mode 100644 index 000000000..ec8d38a18 --- /dev/null +++ b/target/linux/generic/backport-6.1/881-v6.4-mfd-axp20x-Add-support-for-AXP15060-PMIC.patch @@ -0,0 +1,343 @@ +From e0f8ad2a705367518b5c56bf9d6da89681467c02 Mon Sep 17 00:00:00 2001 +From: Shengyu Qu +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 +Reviewed-by: Krzysztof Kozlowski +Signed-off-by: Lee Jones +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[] = { +@@ -168,6 +169,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"), +@@ -236,6 +262,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, +@@ -281,6 +312,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) } + +@@ -502,6 +542,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, +@@ -588,6 +645,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", +@@ -832,6 +900,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; +@@ -941,6 +1026,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, +@@ -632,6 +700,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/851-v6.5-mfd-axp20x-Add-support-for-AXP313a-PMIC.patch b/target/linux/generic/backport-6.1/882-v6.5-mfd-axp20x-Add-support-for-AXP313a-PMIC.patch similarity index 90% rename from target/linux/generic/backport-6.1/851-v6.5-mfd-axp20x-Add-support-for-AXP313a-PMIC.patch rename to target/linux/generic/backport-6.1/882-v6.5-mfd-axp20x-Add-support-for-AXP313a-PMIC.patch index b74283edd..9fe70c103 100644 --- a/target/linux/generic/backport-6.1/851-v6.5-mfd-axp20x-Add-support-for-AXP313a-PMIC.patch +++ b/target/linux/generic/backport-6.1/882-v6.5-mfd-axp20x-Add-support-for-AXP313a-PMIC.patch @@ -39,15 +39,15 @@ Signed-off-by: Lee Jones + { .compatible = "x-powers,axp313a", .data = (void *)AXP313A_ID }, { .compatible = "x-powers,axp803", .data = (void *)AXP803_ID }, { .compatible = "x-powers,axp806", .data = (void *)AXP806_ID }, - { }, -@@ -77,6 +78,7 @@ static const struct i2c_device_id axp20x + { .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 @@ -58,7 +58,7 @@ Signed-off-by: Lee Jones "AXP803", "AXP806", "AXP809", -@@ -154,6 +155,25 @@ static const struct regmap_range axp806_ +@@ -155,6 +156,25 @@ static const struct regmap_range axp806_ regmap_reg_range(AXP806_REG_ADDR_EXT, AXP806_REG_ADDR_EXT), }; @@ -84,7 +84,7 @@ Signed-off-by: Lee Jones static const struct regmap_range axp806_volatile_ranges[] = { regmap_reg_range(AXP20X_IRQ1_STATE, AXP20X_IRQ2_STATE), }; -@@ -221,6 +241,11 @@ static const struct resource axp288_fuel +@@ -247,6 +267,11 @@ static const struct resource axp288_fuel DEFINE_RES_IRQ(AXP288_IRQ_WL1), }; @@ -96,7 +96,7 @@ Signed-off-by: Lee Jones 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"), -@@ -272,6 +297,15 @@ static const struct regmap_config axp288 +@@ -303,6 +328,15 @@ static const struct regmap_config axp288 .cache_type = REGCACHE_RBTREE, }; @@ -112,7 +112,7 @@ Signed-off-by: Lee Jones static const struct regmap_config axp806_regmap_config = { .reg_bits = 8, .val_bits = 8, -@@ -415,6 +449,16 @@ static const struct regmap_irq axp288_re +@@ -455,6 +489,16 @@ static const struct regmap_irq axp288_re INIT_REGMAP_IRQ(AXP288, BC_USB_CHNG, 5, 1), }; @@ -129,7 +129,7 @@ Signed-off-by: Lee Jones 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), -@@ -552,6 +596,17 @@ static const struct regmap_irq_chip axp2 +@@ -609,6 +653,17 @@ static const struct regmap_irq_chip axp2 }; @@ -147,7 +147,7 @@ Signed-off-by: Lee Jones static const struct regmap_irq_chip axp803_regmap_irq_chip = { .name = "axp803", .status_base = AXP20X_IRQ1_STATE, -@@ -683,6 +738,11 @@ static const struct mfd_cell axp152_cell +@@ -751,6 +806,11 @@ static const struct mfd_cell axp152_cell }, }; @@ -159,7 +159,7 @@ Signed-off-by: Lee Jones static const struct resource axp288_adc_resources[] = { DEFINE_RES_IRQ_NAMED(AXP288_IRQ_GPADC, "GPADC"), }; -@@ -835,8 +895,18 @@ static const struct mfd_cell axp813_cell +@@ -920,8 +980,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; @@ -179,7 +179,7 @@ Signed-off-by: Lee Jones /* Give capacitors etc. time to drain to avoid kernel panic msg. */ mdelay(500); -@@ -899,6 +969,12 @@ int axp20x_match_device(struct axp20x_de +@@ -984,6 +1054,12 @@ int axp20x_match_device(struct axp20x_de axp20x->regmap_irq_chip = &axp288_regmap_irq_chip; axp20x->irq_flags = IRQF_TRIGGER_LOW; break; @@ -202,7 +202,7 @@ Signed-off-by: Lee Jones AXP803_ID, AXP806_ID, AXP809_ID, -@@ -91,6 +92,17 @@ enum axp20x_variants { +@@ -92,6 +93,17 @@ enum axp20x_variants { #define AXP22X_ALDO3_V_OUT 0x2a #define AXP22X_CHRG_CTRL3 0x35 @@ -220,7 +220,7 @@ Signed-off-by: Lee Jones #define AXP806_STARTUP_SRC 0x00 #define AXP806_CHIP_ID 0x03 #define AXP806_PWR_OUT_CTRL1 0x10 -@@ -323,6 +335,16 @@ enum { +@@ -364,6 +376,16 @@ enum { }; enum { @@ -237,7 +237,7 @@ Signed-off-by: Lee Jones AXP806_DCDCA = 0, AXP806_DCDCB, AXP806_DCDCC, -@@ -545,6 +567,16 @@ enum axp288_irqs { +@@ -613,6 +635,16 @@ enum axp288_irqs { AXP288_IRQ_BC_USB_CHNG, }; diff --git a/target/linux/generic/backport-6.1/852-v6.5-regulator-axp20x-Add-support-for-AXP313a-variant.patch b/target/linux/generic/backport-6.1/883-v6.5-regulator-axp20x-Add-support-for-AXP313a-variant.patch similarity index 100% rename from target/linux/generic/backport-6.1/852-v6.5-regulator-axp20x-Add-support-for-AXP313a-variant.patch rename to target/linux/generic/backport-6.1/883-v6.5-regulator-axp20x-Add-support-for-AXP313a-variant.patch diff --git a/target/linux/generic/backport-6.1/884-v6.5-regulator-axp20x-Add-AXP15060-support.patch b/target/linux/generic/backport-6.1/884-v6.5-regulator-axp20x-Add-AXP15060-support.patch new file mode 100644 index 000000000..6af09204a --- /dev/null +++ b/target/linux/generic/backport-6.1/884-v6.5-regulator-axp20x-Add-AXP15060-support.patch @@ -0,0 +1,367 @@ +From 9e72869d0fe12aba8cd489e485d93912b3f5c248 Mon Sep 17 00:00:00 2001 +From: Shengyu Qu +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 +Signed-off-by: Andre Przywara +Reviewed-by: Mark Brown +Tested-by: Shengyu Qu +Link: https://lore.kernel.org/r/20230524000012.15028-4-andre.przywara@arm.com +Signed-off-by: Mark Brown +--- + 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, ®); ++ ++ 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/885-v6.5-mfd-axp20x-Add-support-for-AXP192.patch b/target/linux/generic/backport-6.1/885-v6.5-mfd-axp20x-Add-support-for-AXP192.patch new file mode 100644 index 000000000..20a26db3e --- /dev/null +++ b/target/linux/generic/backport-6.1/885-v6.5-mfd-axp20x-Add-support-for-AXP192.patch @@ -0,0 +1,383 @@ +From 63eeabbc9dbddd7381409feccd9082e5ffabfe59 Mon Sep 17 00:00:00 2001 +From: Aidan MacDonald +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 +Link: https://lore.kernel.org/r/20230511092609.76183-1-aidanmacdonald.0x0@gmail.com +Signed-off-by: Lee Jones +--- + 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), +@@ -219,6 +249,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"), +@@ -301,6 +344,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, +@@ -378,6 +430,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), +@@ -615,6 +703,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, +@@ -711,6 +825,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", +@@ -1028,6 +1163,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, +@@ -530,6 +578,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,