generic: 6.1: backport AXP PMIC support
[openwrt/openwrt.git] / target / linux / generic / backport-6.1 / 883-v6.4-mfd-axp20x-Add-support-for-AXP15060-PMIC.patch
1 From e0f8ad2a705367518b5c56bf9d6da89681467c02 Mon Sep 17 00:00:00 2001
2 From: Shengyu Qu <wiagn233@outlook.com>
3 Date: Fri, 21 Apr 2023 23:08:15 +0800
4 Subject: [PATCH] mfd: axp20x: Add support for AXP15060 PMIC
5
6 The AXP15060 is a PMIC chip produced by X-Powers, and could be connected
7 via an I2C bus.
8
9 Describe the regmap and the MFD bits, along with the registers exposed
10 via I2C. Eventually advertise the device using a new compatible string
11 and add support for power off the system.
12
13 The driver would disable PEK function if IRQ is not configured in device
14 tree, since some boards (For example, Starfive Visionfive 2) didn't
15 connect IRQ line of PMIC to SOC.
16
17 GPIO function isn't enabled in this commit, since its configuration
18 operation is different from any existing AXP PMICs and needs
19 logic modification on existing driver. GPIO support might come in later
20 patches.
21
22 Signed-off-by: Shengyu Qu <wiagn233@outlook.com>
23 Reviewed-by: Krzysztof Kozlowski <krzysztof.kozlowski@linaro.org>
24 Signed-off-by: Lee Jones <lee@kernel.org>
25 Link: https://lore.kernel.org/r/TY3P286MB261162D57695AC8164ED50E298609@TY3P286MB2611.JPNP286.PROD.OUTLOOK.COM
26 ---
27 drivers/mfd/axp20x-i2c.c | 2 +
28 drivers/mfd/axp20x.c | 107 +++++++++++++++++++++++++++++++++++++
29 include/linux/mfd/axp20x.h | 85 +++++++++++++++++++++++++++++
30 3 files changed, 194 insertions(+)
31
32 --- a/drivers/mfd/axp20x-i2c.c
33 +++ b/drivers/mfd/axp20x-i2c.c
34 @@ -66,6 +66,7 @@ static const struct of_device_id axp20x_
35 { .compatible = "x-powers,axp223", .data = (void *)AXP223_ID },
36 { .compatible = "x-powers,axp803", .data = (void *)AXP803_ID },
37 { .compatible = "x-powers,axp806", .data = (void *)AXP806_ID },
38 + { .compatible = "x-powers,axp15060", .data = (void *)AXP15060_ID },
39 { },
40 };
41 MODULE_DEVICE_TABLE(of, axp20x_i2c_of_match);
42 @@ -79,6 +80,7 @@ static const struct i2c_device_id axp20x
43 { "axp223", 0 },
44 { "axp803", 0 },
45 { "axp806", 0 },
46 + { "axp15060", 0 },
47 { },
48 };
49 MODULE_DEVICE_TABLE(i2c, axp20x_i2c_id);
50 --- a/drivers/mfd/axp20x.c
51 +++ b/drivers/mfd/axp20x.c
52 @@ -43,6 +43,7 @@ static const char * const axp20x_model_n
53 "AXP806",
54 "AXP809",
55 "AXP813",
56 + "AXP15060",
57 };
58
59 static const struct regmap_range axp152_writeable_ranges[] = {
60 @@ -169,6 +170,31 @@ static const struct regmap_access_table
61 .n_yes_ranges = ARRAY_SIZE(axp806_volatile_ranges),
62 };
63
64 +static const struct regmap_range axp15060_writeable_ranges[] = {
65 + regmap_reg_range(AXP15060_PWR_OUT_CTRL1, AXP15060_DCDC_MODE_CTRL2),
66 + regmap_reg_range(AXP15060_OUTPUT_MONITOR_DISCHARGE, AXP15060_CPUSLDO_V_CTRL),
67 + regmap_reg_range(AXP15060_PWR_WAKEUP_CTRL, AXP15060_PWR_DISABLE_DOWN_SEQ),
68 + regmap_reg_range(AXP15060_PEK_KEY, AXP15060_PEK_KEY),
69 + regmap_reg_range(AXP15060_IRQ1_EN, AXP15060_IRQ2_EN),
70 + regmap_reg_range(AXP15060_IRQ1_STATE, AXP15060_IRQ2_STATE),
71 +};
72 +
73 +static const struct regmap_range axp15060_volatile_ranges[] = {
74 + regmap_reg_range(AXP15060_STARTUP_SRC, AXP15060_STARTUP_SRC),
75 + regmap_reg_range(AXP15060_PWR_WAKEUP_CTRL, AXP15060_PWR_DISABLE_DOWN_SEQ),
76 + regmap_reg_range(AXP15060_IRQ1_STATE, AXP15060_IRQ2_STATE),
77 +};
78 +
79 +static const struct regmap_access_table axp15060_writeable_table = {
80 + .yes_ranges = axp15060_writeable_ranges,
81 + .n_yes_ranges = ARRAY_SIZE(axp15060_writeable_ranges),
82 +};
83 +
84 +static const struct regmap_access_table axp15060_volatile_table = {
85 + .yes_ranges = axp15060_volatile_ranges,
86 + .n_yes_ranges = ARRAY_SIZE(axp15060_volatile_ranges),
87 +};
88 +
89 static const struct resource axp152_pek_resources[] = {
90 DEFINE_RES_IRQ_NAMED(AXP152_IRQ_PEK_RIS_EDGE, "PEK_DBR"),
91 DEFINE_RES_IRQ_NAMED(AXP152_IRQ_PEK_FAL_EDGE, "PEK_DBF"),
92 @@ -237,6 +263,11 @@ static const struct resource axp809_pek_
93 DEFINE_RES_IRQ_NAMED(AXP809_IRQ_PEK_FAL_EDGE, "PEK_DBF"),
94 };
95
96 +static const struct resource axp15060_pek_resources[] = {
97 + DEFINE_RES_IRQ_NAMED(AXP15060_IRQ_PEK_RIS_EDGE, "PEK_DBR"),
98 + DEFINE_RES_IRQ_NAMED(AXP15060_IRQ_PEK_FAL_EDGE, "PEK_DBF"),
99 +};
100 +
101 static const struct regmap_config axp152_regmap_config = {
102 .reg_bits = 8,
103 .val_bits = 8,
104 @@ -282,6 +313,15 @@ static const struct regmap_config axp806
105 .cache_type = REGCACHE_RBTREE,
106 };
107
108 +static const struct regmap_config axp15060_regmap_config = {
109 + .reg_bits = 8,
110 + .val_bits = 8,
111 + .wr_table = &axp15060_writeable_table,
112 + .volatile_table = &axp15060_volatile_table,
113 + .max_register = AXP15060_IRQ2_STATE,
114 + .cache_type = REGCACHE_RBTREE,
115 +};
116 +
117 #define INIT_REGMAP_IRQ(_variant, _irq, _off, _mask) \
118 [_variant##_IRQ_##_irq] = { .reg_offset = (_off), .mask = BIT(_mask) }
119
120 @@ -503,6 +543,23 @@ static const struct regmap_irq axp809_re
121 INIT_REGMAP_IRQ(AXP809, GPIO0_INPUT, 4, 0),
122 };
123
124 +static const struct regmap_irq axp15060_regmap_irqs[] = {
125 + INIT_REGMAP_IRQ(AXP15060, DIE_TEMP_HIGH_LV1, 0, 0),
126 + INIT_REGMAP_IRQ(AXP15060, DIE_TEMP_HIGH_LV2, 0, 1),
127 + INIT_REGMAP_IRQ(AXP15060, DCDC1_V_LOW, 0, 2),
128 + INIT_REGMAP_IRQ(AXP15060, DCDC2_V_LOW, 0, 3),
129 + INIT_REGMAP_IRQ(AXP15060, DCDC3_V_LOW, 0, 4),
130 + INIT_REGMAP_IRQ(AXP15060, DCDC4_V_LOW, 0, 5),
131 + INIT_REGMAP_IRQ(AXP15060, DCDC5_V_LOW, 0, 6),
132 + INIT_REGMAP_IRQ(AXP15060, DCDC6_V_LOW, 0, 7),
133 + INIT_REGMAP_IRQ(AXP15060, PEK_LONG, 1, 0),
134 + INIT_REGMAP_IRQ(AXP15060, PEK_SHORT, 1, 1),
135 + INIT_REGMAP_IRQ(AXP15060, GPIO1_INPUT, 1, 2),
136 + INIT_REGMAP_IRQ(AXP15060, PEK_FAL_EDGE, 1, 3),
137 + INIT_REGMAP_IRQ(AXP15060, PEK_RIS_EDGE, 1, 4),
138 + INIT_REGMAP_IRQ(AXP15060, GPIO2_INPUT, 1, 5),
139 +};
140 +
141 static const struct regmap_irq_chip axp152_regmap_irq_chip = {
142 .name = "axp152_irq_chip",
143 .status_base = AXP152_IRQ1_STATE,
144 @@ -589,6 +646,17 @@ static const struct regmap_irq_chip axp8
145 .num_regs = 5,
146 };
147
148 +static const struct regmap_irq_chip axp15060_regmap_irq_chip = {
149 + .name = "axp15060",
150 + .status_base = AXP15060_IRQ1_STATE,
151 + .ack_base = AXP15060_IRQ1_STATE,
152 + .unmask_base = AXP15060_IRQ1_EN,
153 + .init_ack_masked = true,
154 + .irqs = axp15060_regmap_irqs,
155 + .num_irqs = ARRAY_SIZE(axp15060_regmap_irqs),
156 + .num_regs = 2,
157 +};
158 +
159 static const struct mfd_cell axp20x_cells[] = {
160 {
161 .name = "axp20x-gpio",
162 @@ -833,6 +901,23 @@ static const struct mfd_cell axp813_cell
163 },
164 };
165
166 +static const struct mfd_cell axp15060_cells[] = {
167 + {
168 + .name = "axp221-pek",
169 + .num_resources = ARRAY_SIZE(axp15060_pek_resources),
170 + .resources = axp15060_pek_resources,
171 + }, {
172 + .name = "axp20x-regulator",
173 + },
174 +};
175 +
176 +/* For boards that don't have IRQ line connected to SOC. */
177 +static const struct mfd_cell axp_regulator_only_cells[] = {
178 + {
179 + .name = "axp20x-regulator",
180 + },
181 +};
182 +
183 static int axp20x_power_off(struct sys_off_data *data)
184 {
185 struct axp20x_dev *axp20x = data->cb_data;
186 @@ -942,6 +1027,28 @@ int axp20x_match_device(struct axp20x_de
187 */
188 axp20x->regmap_irq_chip = &axp803_regmap_irq_chip;
189 break;
190 + case AXP15060_ID:
191 + /*
192 + * Don't register the power key part if there is no interrupt
193 + * line.
194 + *
195 + * Since most use cases of AXP PMICs are Allwinner SOCs, board
196 + * designers follow Allwinner's reference design and connects
197 + * IRQ line to SOC, there's no need for those variants to deal
198 + * with cases that IRQ isn't connected. However, AXP15660 is
199 + * used by some other vendors' SOCs that didn't connect IRQ
200 + * line, we need to deal with this case.
201 + */
202 + if (axp20x->irq > 0) {
203 + axp20x->nr_cells = ARRAY_SIZE(axp15060_cells);
204 + axp20x->cells = axp15060_cells;
205 + } else {
206 + axp20x->nr_cells = ARRAY_SIZE(axp_regulator_only_cells);
207 + axp20x->cells = axp_regulator_only_cells;
208 + }
209 + axp20x->regmap_cfg = &axp15060_regmap_config;
210 + axp20x->regmap_irq_chip = &axp15060_regmap_irq_chip;
211 + break;
212 default:
213 dev_err(dev, "unsupported AXP20X ID %lu\n", axp20x->variant);
214 return -EINVAL;
215 --- a/include/linux/mfd/axp20x.h
216 +++ b/include/linux/mfd/axp20x.h
217 @@ -21,6 +21,7 @@ enum axp20x_variants {
218 AXP806_ID,
219 AXP809_ID,
220 AXP813_ID,
221 + AXP15060_ID,
222 NR_AXP20X_VARIANTS,
223 };
224
225 @@ -131,6 +132,39 @@ enum axp20x_variants {
226 /* Other DCDC regulator control registers are the same as AXP803 */
227 #define AXP813_DCDC7_V_OUT 0x26
228
229 +#define AXP15060_STARTUP_SRC 0x00
230 +#define AXP15060_PWR_OUT_CTRL1 0x10
231 +#define AXP15060_PWR_OUT_CTRL2 0x11
232 +#define AXP15060_PWR_OUT_CTRL3 0x12
233 +#define AXP15060_DCDC1_V_CTRL 0x13
234 +#define AXP15060_DCDC2_V_CTRL 0x14
235 +#define AXP15060_DCDC3_V_CTRL 0x15
236 +#define AXP15060_DCDC4_V_CTRL 0x16
237 +#define AXP15060_DCDC5_V_CTRL 0x17
238 +#define AXP15060_DCDC6_V_CTRL 0x18
239 +#define AXP15060_ALDO1_V_CTRL 0x19
240 +#define AXP15060_DCDC_MODE_CTRL1 0x1a
241 +#define AXP15060_DCDC_MODE_CTRL2 0x1b
242 +#define AXP15060_OUTPUT_MONITOR_DISCHARGE 0x1e
243 +#define AXP15060_IRQ_PWROK_VOFF 0x1f
244 +#define AXP15060_ALDO2_V_CTRL 0x20
245 +#define AXP15060_ALDO3_V_CTRL 0x21
246 +#define AXP15060_ALDO4_V_CTRL 0x22
247 +#define AXP15060_ALDO5_V_CTRL 0x23
248 +#define AXP15060_BLDO1_V_CTRL 0x24
249 +#define AXP15060_BLDO2_V_CTRL 0x25
250 +#define AXP15060_BLDO3_V_CTRL 0x26
251 +#define AXP15060_BLDO4_V_CTRL 0x27
252 +#define AXP15060_BLDO5_V_CTRL 0x28
253 +#define AXP15060_CLDO1_V_CTRL 0x29
254 +#define AXP15060_CLDO2_V_CTRL 0x2a
255 +#define AXP15060_CLDO3_V_CTRL 0x2b
256 +#define AXP15060_CLDO4_V_CTRL 0x2d
257 +#define AXP15060_CPUSLDO_V_CTRL 0x2e
258 +#define AXP15060_PWR_WAKEUP_CTRL 0x31
259 +#define AXP15060_PWR_DISABLE_DOWN_SEQ 0x32
260 +#define AXP15060_PEK_KEY 0x36
261 +
262 /* Interrupt */
263 #define AXP152_IRQ1_EN 0x40
264 #define AXP152_IRQ2_EN 0x41
265 @@ -152,6 +186,11 @@ enum axp20x_variants {
266 #define AXP20X_IRQ5_STATE 0x4c
267 #define AXP20X_IRQ6_STATE 0x4d
268
269 +#define AXP15060_IRQ1_EN 0x40
270 +#define AXP15060_IRQ2_EN 0x41
271 +#define AXP15060_IRQ1_STATE 0x48
272 +#define AXP15060_IRQ2_STATE 0x49
273 +
274 /* ADC */
275 #define AXP20X_ACIN_V_ADC_H 0x56
276 #define AXP20X_ACIN_V_ADC_L 0x57
277 @@ -222,6 +261,8 @@ enum axp20x_variants {
278 #define AXP22X_GPIO_STATE 0x94
279 #define AXP22X_GPIO_PULL_DOWN 0x95
280
281 +#define AXP15060_CLDO4_GPIO2_MODESET 0x2c
282 +
283 /* Battery */
284 #define AXP20X_CHRG_CC_31_24 0xb0
285 #define AXP20X_CHRG_CC_23_16 0xb1
286 @@ -419,6 +460,33 @@ enum {
287 AXP813_REG_ID_MAX,
288 };
289
290 +enum {
291 + AXP15060_DCDC1 = 0,
292 + AXP15060_DCDC2,
293 + AXP15060_DCDC3,
294 + AXP15060_DCDC4,
295 + AXP15060_DCDC5,
296 + AXP15060_DCDC6,
297 + AXP15060_ALDO1,
298 + AXP15060_ALDO2,
299 + AXP15060_ALDO3,
300 + AXP15060_ALDO4,
301 + AXP15060_ALDO5,
302 + AXP15060_BLDO1,
303 + AXP15060_BLDO2,
304 + AXP15060_BLDO3,
305 + AXP15060_BLDO4,
306 + AXP15060_BLDO5,
307 + AXP15060_CLDO1,
308 + AXP15060_CLDO2,
309 + AXP15060_CLDO3,
310 + AXP15060_CLDO4,
311 + AXP15060_CPUSLDO,
312 + AXP15060_SW,
313 + AXP15060_RTC_LDO,
314 + AXP15060_REG_ID_MAX,
315 +};
316 +
317 /* IRQs */
318 enum {
319 AXP152_IRQ_LDO0IN_CONNECT = 1,
320 @@ -637,6 +705,23 @@ enum axp809_irqs {
321 AXP809_IRQ_GPIO0_INPUT,
322 };
323
324 +enum axp15060_irqs {
325 + AXP15060_IRQ_DIE_TEMP_HIGH_LV1 = 1,
326 + AXP15060_IRQ_DIE_TEMP_HIGH_LV2,
327 + AXP15060_IRQ_DCDC1_V_LOW,
328 + AXP15060_IRQ_DCDC2_V_LOW,
329 + AXP15060_IRQ_DCDC3_V_LOW,
330 + AXP15060_IRQ_DCDC4_V_LOW,
331 + AXP15060_IRQ_DCDC5_V_LOW,
332 + AXP15060_IRQ_DCDC6_V_LOW,
333 + AXP15060_IRQ_PEK_LONG,
334 + AXP15060_IRQ_PEK_SHORT,
335 + AXP15060_IRQ_GPIO1_INPUT,
336 + AXP15060_IRQ_PEK_FAL_EDGE,
337 + AXP15060_IRQ_PEK_RIS_EDGE,
338 + AXP15060_IRQ_GPIO2_INPUT,
339 +};
340 +
341 struct axp20x_dev {
342 struct device *dev;
343 int irq;