mtd: fix build with GCC 14
[openwrt/openwrt.git] / target / linux / generic / backport-6.1 / 884-v6.5-mfd-axp20x-Add-support-for-AXP313a-PMIC.patch
1 From 75c8cb2f4cb218aaf4ea68cab08d6dbc96eeae15 Mon Sep 17 00:00:00 2001
2 From: Martin Botka <martin.botka@somainline.org>
3 Date: Wed, 24 May 2023 01:00:10 +0100
4 Subject: [PATCH] mfd: axp20x: Add support for AXP313a PMIC
5
6 The AXP313a is a PMIC chip produced by X-Powers, it can be connected via
7 an I2C bus.
8 The name AXP1530 seems to appear as well, and this is what is used in
9 the BSP driver. From all we know it's the same chip, just a different
10 name. However we have only seen AXP313a chips in the wild, so go with
11 this name.
12
13 Compared to the other AXP PMICs it's a rather simple affair: just three
14 DCDC converters, three LDOs, and no battery charging support.
15
16 Describe the regmap and the MFD bits, along with the registers exposed
17 via I2C. Aside from the various regulators, also describe the power key
18 interrupts, and adjust the shutdown handler routine to use a different
19 register than the other PMICs.
20 Eventually advertise the device using the new compatible string.
21
22 Signed-off-by: Martin Botka <martin.botka@somainline.org>
23 Signed-off-by: Andre Przywara <andre.przywara@arm.com>
24 Reviewed-by: Chen-Yu Tsai <wens@csie.org>
25 Link: https://lore.kernel.org/r/20230524000012.15028-2-andre.przywara@arm.com
26 Signed-off-by: Lee Jones <lee@kernel.org>
27 ---
28 drivers/mfd/axp20x-i2c.c | 2 +
29 drivers/mfd/axp20x.c | 78 +++++++++++++++++++++++++++++++++++++-
30 include/linux/mfd/axp20x.h | 32 ++++++++++++++++
31 3 files changed, 111 insertions(+), 1 deletion(-)
32
33 --- a/drivers/mfd/axp20x-i2c.c
34 +++ b/drivers/mfd/axp20x-i2c.c
35 @@ -64,6 +64,7 @@ static const struct of_device_id axp20x_
36 { .compatible = "x-powers,axp209", .data = (void *)AXP209_ID },
37 { .compatible = "x-powers,axp221", .data = (void *)AXP221_ID },
38 { .compatible = "x-powers,axp223", .data = (void *)AXP223_ID },
39 + { .compatible = "x-powers,axp313a", .data = (void *)AXP313A_ID },
40 { .compatible = "x-powers,axp803", .data = (void *)AXP803_ID },
41 { .compatible = "x-powers,axp806", .data = (void *)AXP806_ID },
42 { .compatible = "x-powers,axp15060", .data = (void *)AXP15060_ID },
43 @@ -78,6 +79,7 @@ static const struct i2c_device_id axp20x
44 { "axp209", 0 },
45 { "axp221", 0 },
46 { "axp223", 0 },
47 + { "axp313a", 0 },
48 { "axp803", 0 },
49 { "axp806", 0 },
50 { "axp15060", 0 },
51 --- a/drivers/mfd/axp20x.c
52 +++ b/drivers/mfd/axp20x.c
53 @@ -39,6 +39,7 @@ static const char * const axp20x_model_n
54 "AXP221",
55 "AXP223",
56 "AXP288",
57 + "AXP313a",
58 "AXP803",
59 "AXP806",
60 "AXP809",
61 @@ -156,6 +157,25 @@ static const struct regmap_range axp806_
62 regmap_reg_range(AXP806_REG_ADDR_EXT, AXP806_REG_ADDR_EXT),
63 };
64
65 +static const struct regmap_range axp313a_writeable_ranges[] = {
66 + regmap_reg_range(AXP313A_ON_INDICATE, AXP313A_IRQ_STATE),
67 +};
68 +
69 +static const struct regmap_range axp313a_volatile_ranges[] = {
70 + regmap_reg_range(AXP313A_SHUTDOWN_CTRL, AXP313A_SHUTDOWN_CTRL),
71 + regmap_reg_range(AXP313A_IRQ_STATE, AXP313A_IRQ_STATE),
72 +};
73 +
74 +static const struct regmap_access_table axp313a_writeable_table = {
75 + .yes_ranges = axp313a_writeable_ranges,
76 + .n_yes_ranges = ARRAY_SIZE(axp313a_writeable_ranges),
77 +};
78 +
79 +static const struct regmap_access_table axp313a_volatile_table = {
80 + .yes_ranges = axp313a_volatile_ranges,
81 + .n_yes_ranges = ARRAY_SIZE(axp313a_volatile_ranges),
82 +};
83 +
84 static const struct regmap_range axp806_volatile_ranges[] = {
85 regmap_reg_range(AXP20X_IRQ1_STATE, AXP20X_IRQ2_STATE),
86 };
87 @@ -248,6 +268,11 @@ static const struct resource axp288_fuel
88 DEFINE_RES_IRQ(AXP288_IRQ_WL1),
89 };
90
91 +static const struct resource axp313a_pek_resources[] = {
92 + DEFINE_RES_IRQ_NAMED(AXP313A_IRQ_PEK_RIS_EDGE, "PEK_DBR"),
93 + DEFINE_RES_IRQ_NAMED(AXP313A_IRQ_PEK_FAL_EDGE, "PEK_DBF"),
94 +};
95 +
96 static const struct resource axp803_pek_resources[] = {
97 DEFINE_RES_IRQ_NAMED(AXP803_IRQ_PEK_RIS_EDGE, "PEK_DBR"),
98 DEFINE_RES_IRQ_NAMED(AXP803_IRQ_PEK_FAL_EDGE, "PEK_DBF"),
99 @@ -304,6 +329,15 @@ static const struct regmap_config axp288
100 .cache_type = REGCACHE_RBTREE,
101 };
102
103 +static const struct regmap_config axp313a_regmap_config = {
104 + .reg_bits = 8,
105 + .val_bits = 8,
106 + .wr_table = &axp313a_writeable_table,
107 + .volatile_table = &axp313a_volatile_table,
108 + .max_register = AXP313A_IRQ_STATE,
109 + .cache_type = REGCACHE_RBTREE,
110 +};
111 +
112 static const struct regmap_config axp806_regmap_config = {
113 .reg_bits = 8,
114 .val_bits = 8,
115 @@ -456,6 +490,16 @@ static const struct regmap_irq axp288_re
116 INIT_REGMAP_IRQ(AXP288, BC_USB_CHNG, 5, 1),
117 };
118
119 +static const struct regmap_irq axp313a_regmap_irqs[] = {
120 + INIT_REGMAP_IRQ(AXP313A, PEK_RIS_EDGE, 0, 7),
121 + INIT_REGMAP_IRQ(AXP313A, PEK_FAL_EDGE, 0, 6),
122 + INIT_REGMAP_IRQ(AXP313A, PEK_SHORT, 0, 5),
123 + INIT_REGMAP_IRQ(AXP313A, PEK_LONG, 0, 4),
124 + INIT_REGMAP_IRQ(AXP313A, DCDC3_V_LOW, 0, 3),
125 + INIT_REGMAP_IRQ(AXP313A, DCDC2_V_LOW, 0, 2),
126 + INIT_REGMAP_IRQ(AXP313A, DIE_TEMP_HIGH, 0, 0),
127 +};
128 +
129 static const struct regmap_irq axp803_regmap_irqs[] = {
130 INIT_REGMAP_IRQ(AXP803, ACIN_OVER_V, 0, 7),
131 INIT_REGMAP_IRQ(AXP803, ACIN_PLUGIN, 0, 6),
132 @@ -610,6 +654,17 @@ static const struct regmap_irq_chip axp2
133
134 };
135
136 +static const struct regmap_irq_chip axp313a_regmap_irq_chip = {
137 + .name = "axp313a_irq_chip",
138 + .status_base = AXP313A_IRQ_STATE,
139 + .ack_base = AXP313A_IRQ_STATE,
140 + .unmask_base = AXP313A_IRQ_EN,
141 + .init_ack_masked = true,
142 + .irqs = axp313a_regmap_irqs,
143 + .num_irqs = ARRAY_SIZE(axp313a_regmap_irqs),
144 + .num_regs = 1,
145 +};
146 +
147 static const struct regmap_irq_chip axp803_regmap_irq_chip = {
148 .name = "axp803",
149 .status_base = AXP20X_IRQ1_STATE,
150 @@ -752,6 +807,11 @@ static const struct mfd_cell axp152_cell
151 },
152 };
153
154 +static struct mfd_cell axp313a_cells[] = {
155 + MFD_CELL_NAME("axp20x-regulator"),
156 + MFD_CELL_RES("axp313a-pek", axp313a_pek_resources),
157 +};
158 +
159 static const struct resource axp288_adc_resources[] = {
160 DEFINE_RES_IRQ_NAMED(AXP288_IRQ_GPADC, "GPADC"),
161 };
162 @@ -921,8 +981,18 @@ static const struct mfd_cell axp_regulat
163 static int axp20x_power_off(struct sys_off_data *data)
164 {
165 struct axp20x_dev *axp20x = data->cb_data;
166 + unsigned int shutdown_reg;
167
168 - regmap_write(axp20x->regmap, AXP20X_OFF_CTRL, AXP20X_OFF);
169 + switch (axp20x->variant) {
170 + case AXP313A_ID:
171 + shutdown_reg = AXP313A_SHUTDOWN_CTRL;
172 + break;
173 + default:
174 + shutdown_reg = AXP20X_OFF_CTRL;
175 + break;
176 + }
177 +
178 + regmap_write(axp20x->regmap, shutdown_reg, AXP20X_OFF);
179
180 /* Give capacitors etc. time to drain to avoid kernel panic msg. */
181 mdelay(500);
182 @@ -985,6 +1055,12 @@ int axp20x_match_device(struct axp20x_de
183 axp20x->regmap_irq_chip = &axp288_regmap_irq_chip;
184 axp20x->irq_flags = IRQF_TRIGGER_LOW;
185 break;
186 + case AXP313A_ID:
187 + axp20x->nr_cells = ARRAY_SIZE(axp313a_cells);
188 + axp20x->cells = axp313a_cells;
189 + axp20x->regmap_cfg = &axp313a_regmap_config;
190 + axp20x->regmap_irq_chip = &axp313a_regmap_irq_chip;
191 + break;
192 case AXP803_ID:
193 axp20x->nr_cells = ARRAY_SIZE(axp803_cells);
194 axp20x->cells = axp803_cells;
195 --- a/include/linux/mfd/axp20x.h
196 +++ b/include/linux/mfd/axp20x.h
197 @@ -17,6 +17,7 @@ enum axp20x_variants {
198 AXP221_ID,
199 AXP223_ID,
200 AXP288_ID,
201 + AXP313A_ID,
202 AXP803_ID,
203 AXP806_ID,
204 AXP809_ID,
205 @@ -92,6 +93,17 @@ enum axp20x_variants {
206 #define AXP22X_ALDO3_V_OUT 0x2a
207 #define AXP22X_CHRG_CTRL3 0x35
208
209 +#define AXP313A_ON_INDICATE 0x00
210 +#define AXP313A_OUTPUT_CONTROL 0x10
211 +#define AXP313A_DCDC1_CONRTOL 0x13
212 +#define AXP313A_DCDC2_CONRTOL 0x14
213 +#define AXP313A_DCDC3_CONRTOL 0x15
214 +#define AXP313A_ALDO1_CONRTOL 0x16
215 +#define AXP313A_DLDO1_CONRTOL 0x17
216 +#define AXP313A_SHUTDOWN_CTRL 0x1a
217 +#define AXP313A_IRQ_EN 0x20
218 +#define AXP313A_IRQ_STATE 0x21
219 +
220 #define AXP806_STARTUP_SRC 0x00
221 #define AXP806_CHIP_ID 0x03
222 #define AXP806_PWR_OUT_CTRL1 0x10
223 @@ -364,6 +376,16 @@ enum {
224 };
225
226 enum {
227 + AXP313A_DCDC1 = 0,
228 + AXP313A_DCDC2,
229 + AXP313A_DCDC3,
230 + AXP313A_ALDO1,
231 + AXP313A_DLDO1,
232 + AXP313A_RTC_LDO,
233 + AXP313A_REG_ID_MAX,
234 +};
235 +
236 +enum {
237 AXP806_DCDCA = 0,
238 AXP806_DCDCB,
239 AXP806_DCDCC,
240 @@ -616,6 +638,16 @@ enum axp288_irqs {
241 AXP288_IRQ_BC_USB_CHNG,
242 };
243
244 +enum axp313a_irqs {
245 + AXP313A_IRQ_DIE_TEMP_HIGH,
246 + AXP313A_IRQ_DCDC2_V_LOW = 2,
247 + AXP313A_IRQ_DCDC3_V_LOW,
248 + AXP313A_IRQ_PEK_LONG,
249 + AXP313A_IRQ_PEK_SHORT,
250 + AXP313A_IRQ_PEK_FAL_EDGE,
251 + AXP313A_IRQ_PEK_RIS_EDGE,
252 +};
253 +
254 enum axp803_irqs {
255 AXP803_IRQ_ACIN_OVER_V = 1,
256 AXP803_IRQ_ACIN_PLUGIN,