1 | // SPDX-License-Identifier: GPL-2.0-only |
2 | /* |
3 | * MFD core driver for the X-Powers' Power Management ICs |
4 | * |
5 | * AXP20x typically comprises an adaptive USB-Compatible PWM charger, BUCK DC-DC |
6 | * converters, LDOs, multiple 12-bit ADCs of voltage, current and temperature |
7 | * as well as configurable GPIOs. |
8 | * |
9 | * This file contains the interface independent core functions. |
10 | * |
11 | * Copyright (C) 2014 Carlo Caione |
12 | * |
13 | * Author: Carlo Caione <carlo@caione.org> |
14 | */ |
15 | |
16 | #include <linux/acpi.h> |
17 | #include <linux/bitops.h> |
18 | #include <linux/delay.h> |
19 | #include <linux/err.h> |
20 | #include <linux/interrupt.h> |
21 | #include <linux/kernel.h> |
22 | #include <linux/mfd/axp20x.h> |
23 | #include <linux/mfd/core.h> |
24 | #include <linux/module.h> |
25 | #include <linux/of.h> |
26 | #include <linux/property.h> |
27 | #include <linux/reboot.h> |
28 | #include <linux/regmap.h> |
29 | #include <linux/regulator/consumer.h> |
30 | |
31 | #define AXP20X_OFF BIT(7) |
32 | |
33 | #define AXP806_REG_ADDR_EXT_ADDR_MASTER_MODE 0 |
34 | #define AXP806_REG_ADDR_EXT_ADDR_SLAVE_MODE BIT(4) |
35 | |
36 | static const char * const axp20x_model_names[] = { |
37 | "AXP152" , |
38 | "AXP192" , |
39 | "AXP202" , |
40 | "AXP209" , |
41 | "AXP221" , |
42 | "AXP223" , |
43 | "AXP288" , |
44 | "AXP313a" , |
45 | "AXP803" , |
46 | "AXP806" , |
47 | "AXP809" , |
48 | "AXP813" , |
49 | "AXP15060" , |
50 | }; |
51 | |
52 | static const struct regmap_range axp152_writeable_ranges[] = { |
53 | regmap_reg_range(AXP152_LDO3456_DC1234_CTRL, AXP152_IRQ3_STATE), |
54 | regmap_reg_range(AXP152_DCDC_MODE, AXP152_PWM1_DUTY_CYCLE), |
55 | }; |
56 | |
57 | static const struct regmap_range axp152_volatile_ranges[] = { |
58 | regmap_reg_range(AXP152_PWR_OP_MODE, AXP152_PWR_OP_MODE), |
59 | regmap_reg_range(AXP152_IRQ1_EN, AXP152_IRQ3_STATE), |
60 | regmap_reg_range(AXP152_GPIO_INPUT, AXP152_GPIO_INPUT), |
61 | }; |
62 | |
63 | static const struct regmap_access_table axp152_writeable_table = { |
64 | .yes_ranges = axp152_writeable_ranges, |
65 | .n_yes_ranges = ARRAY_SIZE(axp152_writeable_ranges), |
66 | }; |
67 | |
68 | static const struct regmap_access_table axp152_volatile_table = { |
69 | .yes_ranges = axp152_volatile_ranges, |
70 | .n_yes_ranges = ARRAY_SIZE(axp152_volatile_ranges), |
71 | }; |
72 | |
73 | static const struct regmap_range axp20x_writeable_ranges[] = { |
74 | regmap_reg_range(AXP20X_DATACACHE(0), AXP20X_IRQ5_STATE), |
75 | regmap_reg_range(AXP20X_CHRG_CTRL1, AXP20X_CHRG_CTRL2), |
76 | regmap_reg_range(AXP20X_DCDC_MODE, AXP20X_FG_RES), |
77 | regmap_reg_range(AXP20X_RDC_H, AXP20X_OCV(AXP20X_OCV_MAX)), |
78 | }; |
79 | |
80 | static const struct regmap_range axp20x_volatile_ranges[] = { |
81 | regmap_reg_range(AXP20X_PWR_INPUT_STATUS, AXP20X_USB_OTG_STATUS), |
82 | regmap_reg_range(AXP20X_CHRG_CTRL1, AXP20X_CHRG_CTRL2), |
83 | regmap_reg_range(AXP20X_IRQ1_EN, AXP20X_IRQ5_STATE), |
84 | regmap_reg_range(AXP20X_ACIN_V_ADC_H, AXP20X_IPSOUT_V_HIGH_L), |
85 | regmap_reg_range(AXP20X_GPIO20_SS, AXP20X_GPIO3_CTRL), |
86 | regmap_reg_range(AXP20X_FG_RES, AXP20X_RDC_L), |
87 | }; |
88 | |
89 | static const struct regmap_access_table axp20x_writeable_table = { |
90 | .yes_ranges = axp20x_writeable_ranges, |
91 | .n_yes_ranges = ARRAY_SIZE(axp20x_writeable_ranges), |
92 | }; |
93 | |
94 | static const struct regmap_access_table axp20x_volatile_table = { |
95 | .yes_ranges = axp20x_volatile_ranges, |
96 | .n_yes_ranges = ARRAY_SIZE(axp20x_volatile_ranges), |
97 | }; |
98 | |
99 | static const struct regmap_range axp192_writeable_ranges[] = { |
100 | regmap_reg_range(AXP192_DATACACHE(0), AXP192_DATACACHE(5)), |
101 | regmap_reg_range(AXP192_PWR_OUT_CTRL, AXP192_IRQ5_STATE), |
102 | regmap_reg_range(AXP20X_DCDC_MODE, AXP192_N_RSTO_CTRL), |
103 | regmap_reg_range(AXP20X_CC_CTRL, AXP20X_CC_CTRL), |
104 | }; |
105 | |
106 | static const struct regmap_range axp192_volatile_ranges[] = { |
107 | regmap_reg_range(AXP20X_PWR_INPUT_STATUS, AXP192_USB_OTG_STATUS), |
108 | regmap_reg_range(AXP192_IRQ1_STATE, AXP192_IRQ4_STATE), |
109 | regmap_reg_range(AXP192_IRQ5_STATE, AXP192_IRQ5_STATE), |
110 | regmap_reg_range(AXP20X_ACIN_V_ADC_H, AXP20X_IPSOUT_V_HIGH_L), |
111 | regmap_reg_range(AXP20X_TIMER_CTRL, AXP20X_TIMER_CTRL), |
112 | regmap_reg_range(AXP192_GPIO2_0_STATE, AXP192_GPIO2_0_STATE), |
113 | regmap_reg_range(AXP192_GPIO4_3_STATE, AXP192_GPIO4_3_STATE), |
114 | regmap_reg_range(AXP192_N_RSTO_CTRL, AXP192_N_RSTO_CTRL), |
115 | regmap_reg_range(AXP20X_CHRG_CC_31_24, AXP20X_CC_CTRL), |
116 | }; |
117 | |
118 | static const struct regmap_access_table axp192_writeable_table = { |
119 | .yes_ranges = axp192_writeable_ranges, |
120 | .n_yes_ranges = ARRAY_SIZE(axp192_writeable_ranges), |
121 | }; |
122 | |
123 | static const struct regmap_access_table axp192_volatile_table = { |
124 | .yes_ranges = axp192_volatile_ranges, |
125 | .n_yes_ranges = ARRAY_SIZE(axp192_volatile_ranges), |
126 | }; |
127 | |
128 | /* AXP22x ranges are shared with the AXP809, as they cover the same range */ |
129 | static const struct regmap_range axp22x_writeable_ranges[] = { |
130 | regmap_reg_range(AXP20X_DATACACHE(0), AXP20X_IRQ5_STATE), |
131 | regmap_reg_range(AXP20X_CHRG_CTRL1, AXP22X_CHRG_CTRL3), |
132 | regmap_reg_range(AXP20X_DCDC_MODE, AXP22X_BATLOW_THRES1), |
133 | }; |
134 | |
135 | static const struct regmap_range axp22x_volatile_ranges[] = { |
136 | regmap_reg_range(AXP20X_PWR_INPUT_STATUS, AXP20X_PWR_OP_MODE), |
137 | regmap_reg_range(AXP20X_IRQ1_EN, AXP20X_IRQ5_STATE), |
138 | regmap_reg_range(AXP22X_GPIO_STATE, AXP22X_GPIO_STATE), |
139 | regmap_reg_range(AXP22X_PMIC_TEMP_H, AXP20X_IPSOUT_V_HIGH_L), |
140 | regmap_reg_range(AXP20X_FG_RES, AXP20X_FG_RES), |
141 | }; |
142 | |
143 | static const struct regmap_access_table axp22x_writeable_table = { |
144 | .yes_ranges = axp22x_writeable_ranges, |
145 | .n_yes_ranges = ARRAY_SIZE(axp22x_writeable_ranges), |
146 | }; |
147 | |
148 | static const struct regmap_access_table axp22x_volatile_table = { |
149 | .yes_ranges = axp22x_volatile_ranges, |
150 | .n_yes_ranges = ARRAY_SIZE(axp22x_volatile_ranges), |
151 | }; |
152 | |
153 | /* AXP288 ranges are shared with the AXP803, as they cover the same range */ |
154 | static const struct regmap_range axp288_writeable_ranges[] = { |
155 | regmap_reg_range(AXP288_POWER_REASON, AXP288_POWER_REASON), |
156 | regmap_reg_range(AXP20X_DATACACHE(0), AXP20X_IRQ6_STATE), |
157 | regmap_reg_range(AXP20X_DCDC_MODE, AXP288_FG_TUNE5), |
158 | }; |
159 | |
160 | static const struct regmap_range axp288_volatile_ranges[] = { |
161 | regmap_reg_range(AXP20X_PWR_INPUT_STATUS, AXP288_POWER_REASON), |
162 | regmap_reg_range(AXP22X_PWR_OUT_CTRL1, AXP22X_ALDO3_V_OUT), |
163 | regmap_reg_range(AXP288_BC_GLOBAL, AXP288_BC_GLOBAL), |
164 | regmap_reg_range(AXP288_BC_DET_STAT, AXP20X_VBUS_IPSOUT_MGMT), |
165 | regmap_reg_range(AXP20X_CHRG_BAK_CTRL, AXP20X_CHRG_BAK_CTRL), |
166 | regmap_reg_range(AXP20X_IRQ1_EN, AXP20X_IPSOUT_V_HIGH_L), |
167 | regmap_reg_range(AXP20X_TIMER_CTRL, AXP20X_TIMER_CTRL), |
168 | regmap_reg_range(AXP20X_GPIO1_CTRL, AXP22X_GPIO_STATE), |
169 | regmap_reg_range(AXP288_RT_BATT_V_H, AXP288_RT_BATT_V_L), |
170 | regmap_reg_range(AXP20X_FG_RES, AXP288_FG_CC_CAP_REG), |
171 | }; |
172 | |
173 | static const struct regmap_access_table axp288_writeable_table = { |
174 | .yes_ranges = axp288_writeable_ranges, |
175 | .n_yes_ranges = ARRAY_SIZE(axp288_writeable_ranges), |
176 | }; |
177 | |
178 | static const struct regmap_access_table axp288_volatile_table = { |
179 | .yes_ranges = axp288_volatile_ranges, |
180 | .n_yes_ranges = ARRAY_SIZE(axp288_volatile_ranges), |
181 | }; |
182 | |
183 | static const struct regmap_range axp806_writeable_ranges[] = { |
184 | regmap_reg_range(AXP20X_DATACACHE(0), AXP20X_DATACACHE(3)), |
185 | regmap_reg_range(AXP806_PWR_OUT_CTRL1, AXP806_CLDO3_V_CTRL), |
186 | regmap_reg_range(AXP20X_IRQ1_EN, AXP20X_IRQ2_EN), |
187 | regmap_reg_range(AXP20X_IRQ1_STATE, AXP20X_IRQ2_STATE), |
188 | regmap_reg_range(AXP806_REG_ADDR_EXT, AXP806_REG_ADDR_EXT), |
189 | }; |
190 | |
191 | static const struct regmap_range axp313a_writeable_ranges[] = { |
192 | regmap_reg_range(AXP313A_ON_INDICATE, AXP313A_IRQ_STATE), |
193 | }; |
194 | |
195 | static const struct regmap_range axp313a_volatile_ranges[] = { |
196 | regmap_reg_range(AXP313A_SHUTDOWN_CTRL, AXP313A_SHUTDOWN_CTRL), |
197 | regmap_reg_range(AXP313A_IRQ_STATE, AXP313A_IRQ_STATE), |
198 | }; |
199 | |
200 | static const struct regmap_access_table axp313a_writeable_table = { |
201 | .yes_ranges = axp313a_writeable_ranges, |
202 | .n_yes_ranges = ARRAY_SIZE(axp313a_writeable_ranges), |
203 | }; |
204 | |
205 | static const struct regmap_access_table axp313a_volatile_table = { |
206 | .yes_ranges = axp313a_volatile_ranges, |
207 | .n_yes_ranges = ARRAY_SIZE(axp313a_volatile_ranges), |
208 | }; |
209 | |
210 | static const struct regmap_range axp806_volatile_ranges[] = { |
211 | regmap_reg_range(AXP20X_IRQ1_STATE, AXP20X_IRQ2_STATE), |
212 | }; |
213 | |
214 | static const struct regmap_access_table axp806_writeable_table = { |
215 | .yes_ranges = axp806_writeable_ranges, |
216 | .n_yes_ranges = ARRAY_SIZE(axp806_writeable_ranges), |
217 | }; |
218 | |
219 | static const struct regmap_access_table axp806_volatile_table = { |
220 | .yes_ranges = axp806_volatile_ranges, |
221 | .n_yes_ranges = ARRAY_SIZE(axp806_volatile_ranges), |
222 | }; |
223 | |
224 | static const struct regmap_range axp15060_writeable_ranges[] = { |
225 | regmap_reg_range(AXP15060_PWR_OUT_CTRL1, AXP15060_DCDC_MODE_CTRL2), |
226 | regmap_reg_range(AXP15060_OUTPUT_MONITOR_DISCHARGE, AXP15060_CPUSLDO_V_CTRL), |
227 | regmap_reg_range(AXP15060_PWR_WAKEUP_CTRL, AXP15060_PWR_DISABLE_DOWN_SEQ), |
228 | regmap_reg_range(AXP15060_PEK_KEY, AXP15060_PEK_KEY), |
229 | regmap_reg_range(AXP15060_IRQ1_EN, AXP15060_IRQ2_EN), |
230 | regmap_reg_range(AXP15060_IRQ1_STATE, AXP15060_IRQ2_STATE), |
231 | }; |
232 | |
233 | static const struct regmap_range axp15060_volatile_ranges[] = { |
234 | regmap_reg_range(AXP15060_STARTUP_SRC, AXP15060_STARTUP_SRC), |
235 | regmap_reg_range(AXP15060_PWR_WAKEUP_CTRL, AXP15060_PWR_DISABLE_DOWN_SEQ), |
236 | regmap_reg_range(AXP15060_IRQ1_STATE, AXP15060_IRQ2_STATE), |
237 | }; |
238 | |
239 | static const struct regmap_access_table axp15060_writeable_table = { |
240 | .yes_ranges = axp15060_writeable_ranges, |
241 | .n_yes_ranges = ARRAY_SIZE(axp15060_writeable_ranges), |
242 | }; |
243 | |
244 | static const struct regmap_access_table axp15060_volatile_table = { |
245 | .yes_ranges = axp15060_volatile_ranges, |
246 | .n_yes_ranges = ARRAY_SIZE(axp15060_volatile_ranges), |
247 | }; |
248 | |
249 | static const struct resource axp152_pek_resources[] = { |
250 | DEFINE_RES_IRQ_NAMED(AXP152_IRQ_PEK_RIS_EDGE, "PEK_DBR" ), |
251 | DEFINE_RES_IRQ_NAMED(AXP152_IRQ_PEK_FAL_EDGE, "PEK_DBF" ), |
252 | }; |
253 | |
254 | static const struct resource axp192_ac_power_supply_resources[] = { |
255 | DEFINE_RES_IRQ_NAMED(AXP192_IRQ_ACIN_PLUGIN, "ACIN_PLUGIN" ), |
256 | DEFINE_RES_IRQ_NAMED(AXP192_IRQ_ACIN_REMOVAL, "ACIN_REMOVAL" ), |
257 | DEFINE_RES_IRQ_NAMED(AXP192_IRQ_ACIN_OVER_V, "ACIN_OVER_V" ), |
258 | }; |
259 | |
260 | static const struct resource axp192_usb_power_supply_resources[] = { |
261 | DEFINE_RES_IRQ_NAMED(AXP192_IRQ_VBUS_PLUGIN, "VBUS_PLUGIN" ), |
262 | DEFINE_RES_IRQ_NAMED(AXP192_IRQ_VBUS_REMOVAL, "VBUS_REMOVAL" ), |
263 | DEFINE_RES_IRQ_NAMED(AXP192_IRQ_VBUS_VALID, "VBUS_VALID" ), |
264 | DEFINE_RES_IRQ_NAMED(AXP192_IRQ_VBUS_NOT_VALID, "VBUS_NOT_VALID" ), |
265 | }; |
266 | |
267 | static const struct resource axp20x_ac_power_supply_resources[] = { |
268 | DEFINE_RES_IRQ_NAMED(AXP20X_IRQ_ACIN_PLUGIN, "ACIN_PLUGIN" ), |
269 | DEFINE_RES_IRQ_NAMED(AXP20X_IRQ_ACIN_REMOVAL, "ACIN_REMOVAL" ), |
270 | DEFINE_RES_IRQ_NAMED(AXP20X_IRQ_ACIN_OVER_V, "ACIN_OVER_V" ), |
271 | }; |
272 | |
273 | static const struct resource axp20x_pek_resources[] = { |
274 | DEFINE_RES_IRQ_NAMED(AXP20X_IRQ_PEK_RIS_EDGE, "PEK_DBR" ), |
275 | DEFINE_RES_IRQ_NAMED(AXP20X_IRQ_PEK_FAL_EDGE, "PEK_DBF" ), |
276 | }; |
277 | |
278 | static const struct resource axp20x_usb_power_supply_resources[] = { |
279 | DEFINE_RES_IRQ_NAMED(AXP20X_IRQ_VBUS_PLUGIN, "VBUS_PLUGIN" ), |
280 | DEFINE_RES_IRQ_NAMED(AXP20X_IRQ_VBUS_REMOVAL, "VBUS_REMOVAL" ), |
281 | DEFINE_RES_IRQ_NAMED(AXP20X_IRQ_VBUS_VALID, "VBUS_VALID" ), |
282 | DEFINE_RES_IRQ_NAMED(AXP20X_IRQ_VBUS_NOT_VALID, "VBUS_NOT_VALID" ), |
283 | }; |
284 | |
285 | static const struct resource axp22x_usb_power_supply_resources[] = { |
286 | DEFINE_RES_IRQ_NAMED(AXP22X_IRQ_VBUS_PLUGIN, "VBUS_PLUGIN" ), |
287 | DEFINE_RES_IRQ_NAMED(AXP22X_IRQ_VBUS_REMOVAL, "VBUS_REMOVAL" ), |
288 | }; |
289 | |
290 | /* AXP803 and AXP813/AXP818 share the same interrupts */ |
291 | static const struct resource axp803_usb_power_supply_resources[] = { |
292 | DEFINE_RES_IRQ_NAMED(AXP803_IRQ_VBUS_PLUGIN, "VBUS_PLUGIN" ), |
293 | DEFINE_RES_IRQ_NAMED(AXP803_IRQ_VBUS_REMOVAL, "VBUS_REMOVAL" ), |
294 | }; |
295 | |
296 | static const struct resource axp22x_pek_resources[] = { |
297 | DEFINE_RES_IRQ_NAMED(AXP22X_IRQ_PEK_RIS_EDGE, "PEK_DBR" ), |
298 | DEFINE_RES_IRQ_NAMED(AXP22X_IRQ_PEK_FAL_EDGE, "PEK_DBF" ), |
299 | }; |
300 | |
301 | static const struct resource axp288_power_button_resources[] = { |
302 | DEFINE_RES_IRQ_NAMED(AXP288_IRQ_POKP, "PEK_DBR" ), |
303 | DEFINE_RES_IRQ_NAMED(AXP288_IRQ_POKN, "PEK_DBF" ), |
304 | }; |
305 | |
306 | static const struct resource axp288_fuel_gauge_resources[] = { |
307 | DEFINE_RES_IRQ(AXP288_IRQ_QWBTU), |
308 | DEFINE_RES_IRQ(AXP288_IRQ_WBTU), |
309 | DEFINE_RES_IRQ(AXP288_IRQ_QWBTO), |
310 | DEFINE_RES_IRQ(AXP288_IRQ_WBTO), |
311 | DEFINE_RES_IRQ(AXP288_IRQ_WL2), |
312 | DEFINE_RES_IRQ(AXP288_IRQ_WL1), |
313 | }; |
314 | |
315 | static const struct resource axp313a_pek_resources[] = { |
316 | DEFINE_RES_IRQ_NAMED(AXP313A_IRQ_PEK_RIS_EDGE, "PEK_DBR" ), |
317 | DEFINE_RES_IRQ_NAMED(AXP313A_IRQ_PEK_FAL_EDGE, "PEK_DBF" ), |
318 | }; |
319 | |
320 | static const struct resource axp803_pek_resources[] = { |
321 | DEFINE_RES_IRQ_NAMED(AXP803_IRQ_PEK_RIS_EDGE, "PEK_DBR" ), |
322 | DEFINE_RES_IRQ_NAMED(AXP803_IRQ_PEK_FAL_EDGE, "PEK_DBF" ), |
323 | }; |
324 | |
325 | static const struct resource axp806_pek_resources[] = { |
326 | DEFINE_RES_IRQ_NAMED(AXP806_IRQ_POK_RISE, "PEK_DBR" ), |
327 | DEFINE_RES_IRQ_NAMED(AXP806_IRQ_POK_FALL, "PEK_DBF" ), |
328 | }; |
329 | |
330 | static const struct resource axp809_pek_resources[] = { |
331 | DEFINE_RES_IRQ_NAMED(AXP809_IRQ_PEK_RIS_EDGE, "PEK_DBR" ), |
332 | DEFINE_RES_IRQ_NAMED(AXP809_IRQ_PEK_FAL_EDGE, "PEK_DBF" ), |
333 | }; |
334 | |
335 | static const struct resource axp15060_pek_resources[] = { |
336 | DEFINE_RES_IRQ_NAMED(AXP15060_IRQ_PEK_RIS_EDGE, "PEK_DBR" ), |
337 | DEFINE_RES_IRQ_NAMED(AXP15060_IRQ_PEK_FAL_EDGE, "PEK_DBF" ), |
338 | }; |
339 | |
340 | static const struct regmap_config axp152_regmap_config = { |
341 | .reg_bits = 8, |
342 | .val_bits = 8, |
343 | .wr_table = &axp152_writeable_table, |
344 | .volatile_table = &axp152_volatile_table, |
345 | .max_register = AXP152_PWM1_DUTY_CYCLE, |
346 | .cache_type = REGCACHE_MAPLE, |
347 | }; |
348 | |
349 | static const struct regmap_config axp192_regmap_config = { |
350 | .reg_bits = 8, |
351 | .val_bits = 8, |
352 | .wr_table = &axp192_writeable_table, |
353 | .volatile_table = &axp192_volatile_table, |
354 | .max_register = AXP20X_CC_CTRL, |
355 | .cache_type = REGCACHE_RBTREE, |
356 | }; |
357 | |
358 | static const struct regmap_config axp20x_regmap_config = { |
359 | .reg_bits = 8, |
360 | .val_bits = 8, |
361 | .wr_table = &axp20x_writeable_table, |
362 | .volatile_table = &axp20x_volatile_table, |
363 | .max_register = AXP20X_OCV(AXP20X_OCV_MAX), |
364 | .cache_type = REGCACHE_MAPLE, |
365 | }; |
366 | |
367 | static const struct regmap_config axp22x_regmap_config = { |
368 | .reg_bits = 8, |
369 | .val_bits = 8, |
370 | .wr_table = &axp22x_writeable_table, |
371 | .volatile_table = &axp22x_volatile_table, |
372 | .max_register = AXP22X_BATLOW_THRES1, |
373 | .cache_type = REGCACHE_MAPLE, |
374 | }; |
375 | |
376 | static const struct regmap_config axp288_regmap_config = { |
377 | .reg_bits = 8, |
378 | .val_bits = 8, |
379 | .wr_table = &axp288_writeable_table, |
380 | .volatile_table = &axp288_volatile_table, |
381 | .max_register = AXP288_FG_TUNE5, |
382 | .cache_type = REGCACHE_MAPLE, |
383 | }; |
384 | |
385 | static const struct regmap_config axp313a_regmap_config = { |
386 | .reg_bits = 8, |
387 | .val_bits = 8, |
388 | .wr_table = &axp313a_writeable_table, |
389 | .volatile_table = &axp313a_volatile_table, |
390 | .max_register = AXP313A_IRQ_STATE, |
391 | .cache_type = REGCACHE_RBTREE, |
392 | }; |
393 | |
394 | static const struct regmap_config axp806_regmap_config = { |
395 | .reg_bits = 8, |
396 | .val_bits = 8, |
397 | .wr_table = &axp806_writeable_table, |
398 | .volatile_table = &axp806_volatile_table, |
399 | .max_register = AXP806_REG_ADDR_EXT, |
400 | .cache_type = REGCACHE_MAPLE, |
401 | }; |
402 | |
403 | static const struct regmap_config axp15060_regmap_config = { |
404 | .reg_bits = 8, |
405 | .val_bits = 8, |
406 | .wr_table = &axp15060_writeable_table, |
407 | .volatile_table = &axp15060_volatile_table, |
408 | .max_register = AXP15060_IRQ2_STATE, |
409 | .cache_type = REGCACHE_MAPLE, |
410 | }; |
411 | |
412 | #define INIT_REGMAP_IRQ(_variant, _irq, _off, _mask) \ |
413 | [_variant##_IRQ_##_irq] = { .reg_offset = (_off), .mask = BIT(_mask) } |
414 | |
415 | static const struct regmap_irq axp152_regmap_irqs[] = { |
416 | INIT_REGMAP_IRQ(AXP152, LDO0IN_CONNECT, 0, 6), |
417 | INIT_REGMAP_IRQ(AXP152, LDO0IN_REMOVAL, 0, 5), |
418 | INIT_REGMAP_IRQ(AXP152, ALDO0IN_CONNECT, 0, 3), |
419 | INIT_REGMAP_IRQ(AXP152, ALDO0IN_REMOVAL, 0, 2), |
420 | INIT_REGMAP_IRQ(AXP152, DCDC1_V_LOW, 1, 5), |
421 | INIT_REGMAP_IRQ(AXP152, DCDC2_V_LOW, 1, 4), |
422 | INIT_REGMAP_IRQ(AXP152, DCDC3_V_LOW, 1, 3), |
423 | INIT_REGMAP_IRQ(AXP152, DCDC4_V_LOW, 1, 2), |
424 | INIT_REGMAP_IRQ(AXP152, PEK_SHORT, 1, 1), |
425 | INIT_REGMAP_IRQ(AXP152, PEK_LONG, 1, 0), |
426 | INIT_REGMAP_IRQ(AXP152, TIMER, 2, 7), |
427 | INIT_REGMAP_IRQ(AXP152, PEK_RIS_EDGE, 2, 6), |
428 | INIT_REGMAP_IRQ(AXP152, PEK_FAL_EDGE, 2, 5), |
429 | INIT_REGMAP_IRQ(AXP152, GPIO3_INPUT, 2, 3), |
430 | INIT_REGMAP_IRQ(AXP152, GPIO2_INPUT, 2, 2), |
431 | INIT_REGMAP_IRQ(AXP152, GPIO1_INPUT, 2, 1), |
432 | INIT_REGMAP_IRQ(AXP152, GPIO0_INPUT, 2, 0), |
433 | }; |
434 | |
435 | static const struct regmap_irq axp192_regmap_irqs[] = { |
436 | INIT_REGMAP_IRQ(AXP192, ACIN_OVER_V, 0, 7), |
437 | INIT_REGMAP_IRQ(AXP192, ACIN_PLUGIN, 0, 6), |
438 | INIT_REGMAP_IRQ(AXP192, ACIN_REMOVAL, 0, 5), |
439 | INIT_REGMAP_IRQ(AXP192, VBUS_OVER_V, 0, 4), |
440 | INIT_REGMAP_IRQ(AXP192, VBUS_PLUGIN, 0, 3), |
441 | INIT_REGMAP_IRQ(AXP192, VBUS_REMOVAL, 0, 2), |
442 | INIT_REGMAP_IRQ(AXP192, VBUS_V_LOW, 0, 1), |
443 | INIT_REGMAP_IRQ(AXP192, BATT_PLUGIN, 1, 7), |
444 | INIT_REGMAP_IRQ(AXP192, BATT_REMOVAL, 1, 6), |
445 | INIT_REGMAP_IRQ(AXP192, BATT_ENT_ACT_MODE, 1, 5), |
446 | INIT_REGMAP_IRQ(AXP192, BATT_EXIT_ACT_MODE, 1, 4), |
447 | INIT_REGMAP_IRQ(AXP192, CHARG, 1, 3), |
448 | INIT_REGMAP_IRQ(AXP192, CHARG_DONE, 1, 2), |
449 | INIT_REGMAP_IRQ(AXP192, BATT_TEMP_HIGH, 1, 1), |
450 | INIT_REGMAP_IRQ(AXP192, BATT_TEMP_LOW, 1, 0), |
451 | INIT_REGMAP_IRQ(AXP192, DIE_TEMP_HIGH, 2, 7), |
452 | INIT_REGMAP_IRQ(AXP192, CHARG_I_LOW, 2, 6), |
453 | INIT_REGMAP_IRQ(AXP192, DCDC1_V_LONG, 2, 5), |
454 | INIT_REGMAP_IRQ(AXP192, DCDC2_V_LONG, 2, 4), |
455 | INIT_REGMAP_IRQ(AXP192, DCDC3_V_LONG, 2, 3), |
456 | INIT_REGMAP_IRQ(AXP192, PEK_SHORT, 2, 1), |
457 | INIT_REGMAP_IRQ(AXP192, PEK_LONG, 2, 0), |
458 | INIT_REGMAP_IRQ(AXP192, N_OE_PWR_ON, 3, 7), |
459 | INIT_REGMAP_IRQ(AXP192, N_OE_PWR_OFF, 3, 6), |
460 | INIT_REGMAP_IRQ(AXP192, VBUS_VALID, 3, 5), |
461 | INIT_REGMAP_IRQ(AXP192, VBUS_NOT_VALID, 3, 4), |
462 | INIT_REGMAP_IRQ(AXP192, VBUS_SESS_VALID, 3, 3), |
463 | INIT_REGMAP_IRQ(AXP192, VBUS_SESS_END, 3, 2), |
464 | INIT_REGMAP_IRQ(AXP192, LOW_PWR_LVL, 3, 0), |
465 | INIT_REGMAP_IRQ(AXP192, TIMER, 4, 7), |
466 | INIT_REGMAP_IRQ(AXP192, GPIO2_INPUT, 4, 2), |
467 | INIT_REGMAP_IRQ(AXP192, GPIO1_INPUT, 4, 1), |
468 | INIT_REGMAP_IRQ(AXP192, GPIO0_INPUT, 4, 0), |
469 | }; |
470 | |
471 | static const struct regmap_irq axp20x_regmap_irqs[] = { |
472 | INIT_REGMAP_IRQ(AXP20X, ACIN_OVER_V, 0, 7), |
473 | INIT_REGMAP_IRQ(AXP20X, ACIN_PLUGIN, 0, 6), |
474 | INIT_REGMAP_IRQ(AXP20X, ACIN_REMOVAL, 0, 5), |
475 | INIT_REGMAP_IRQ(AXP20X, VBUS_OVER_V, 0, 4), |
476 | INIT_REGMAP_IRQ(AXP20X, VBUS_PLUGIN, 0, 3), |
477 | INIT_REGMAP_IRQ(AXP20X, VBUS_REMOVAL, 0, 2), |
478 | INIT_REGMAP_IRQ(AXP20X, VBUS_V_LOW, 0, 1), |
479 | INIT_REGMAP_IRQ(AXP20X, BATT_PLUGIN, 1, 7), |
480 | INIT_REGMAP_IRQ(AXP20X, BATT_REMOVAL, 1, 6), |
481 | INIT_REGMAP_IRQ(AXP20X, BATT_ENT_ACT_MODE, 1, 5), |
482 | INIT_REGMAP_IRQ(AXP20X, BATT_EXIT_ACT_MODE, 1, 4), |
483 | INIT_REGMAP_IRQ(AXP20X, CHARG, 1, 3), |
484 | INIT_REGMAP_IRQ(AXP20X, CHARG_DONE, 1, 2), |
485 | INIT_REGMAP_IRQ(AXP20X, BATT_TEMP_HIGH, 1, 1), |
486 | INIT_REGMAP_IRQ(AXP20X, BATT_TEMP_LOW, 1, 0), |
487 | INIT_REGMAP_IRQ(AXP20X, DIE_TEMP_HIGH, 2, 7), |
488 | INIT_REGMAP_IRQ(AXP20X, CHARG_I_LOW, 2, 6), |
489 | INIT_REGMAP_IRQ(AXP20X, DCDC1_V_LONG, 2, 5), |
490 | INIT_REGMAP_IRQ(AXP20X, DCDC2_V_LONG, 2, 4), |
491 | INIT_REGMAP_IRQ(AXP20X, DCDC3_V_LONG, 2, 3), |
492 | INIT_REGMAP_IRQ(AXP20X, PEK_SHORT, 2, 1), |
493 | INIT_REGMAP_IRQ(AXP20X, PEK_LONG, 2, 0), |
494 | INIT_REGMAP_IRQ(AXP20X, N_OE_PWR_ON, 3, 7), |
495 | INIT_REGMAP_IRQ(AXP20X, N_OE_PWR_OFF, 3, 6), |
496 | INIT_REGMAP_IRQ(AXP20X, VBUS_VALID, 3, 5), |
497 | INIT_REGMAP_IRQ(AXP20X, VBUS_NOT_VALID, 3, 4), |
498 | INIT_REGMAP_IRQ(AXP20X, VBUS_SESS_VALID, 3, 3), |
499 | INIT_REGMAP_IRQ(AXP20X, VBUS_SESS_END, 3, 2), |
500 | INIT_REGMAP_IRQ(AXP20X, LOW_PWR_LVL1, 3, 1), |
501 | INIT_REGMAP_IRQ(AXP20X, LOW_PWR_LVL2, 3, 0), |
502 | INIT_REGMAP_IRQ(AXP20X, TIMER, 4, 7), |
503 | INIT_REGMAP_IRQ(AXP20X, PEK_RIS_EDGE, 4, 6), |
504 | INIT_REGMAP_IRQ(AXP20X, PEK_FAL_EDGE, 4, 5), |
505 | INIT_REGMAP_IRQ(AXP20X, GPIO3_INPUT, 4, 3), |
506 | INIT_REGMAP_IRQ(AXP20X, GPIO2_INPUT, 4, 2), |
507 | INIT_REGMAP_IRQ(AXP20X, GPIO1_INPUT, 4, 1), |
508 | INIT_REGMAP_IRQ(AXP20X, GPIO0_INPUT, 4, 0), |
509 | }; |
510 | |
511 | static const struct regmap_irq axp22x_regmap_irqs[] = { |
512 | INIT_REGMAP_IRQ(AXP22X, ACIN_OVER_V, 0, 7), |
513 | INIT_REGMAP_IRQ(AXP22X, ACIN_PLUGIN, 0, 6), |
514 | INIT_REGMAP_IRQ(AXP22X, ACIN_REMOVAL, 0, 5), |
515 | INIT_REGMAP_IRQ(AXP22X, VBUS_OVER_V, 0, 4), |
516 | INIT_REGMAP_IRQ(AXP22X, VBUS_PLUGIN, 0, 3), |
517 | INIT_REGMAP_IRQ(AXP22X, VBUS_REMOVAL, 0, 2), |
518 | INIT_REGMAP_IRQ(AXP22X, VBUS_V_LOW, 0, 1), |
519 | INIT_REGMAP_IRQ(AXP22X, BATT_PLUGIN, 1, 7), |
520 | INIT_REGMAP_IRQ(AXP22X, BATT_REMOVAL, 1, 6), |
521 | INIT_REGMAP_IRQ(AXP22X, BATT_ENT_ACT_MODE, 1, 5), |
522 | INIT_REGMAP_IRQ(AXP22X, BATT_EXIT_ACT_MODE, 1, 4), |
523 | INIT_REGMAP_IRQ(AXP22X, CHARG, 1, 3), |
524 | INIT_REGMAP_IRQ(AXP22X, CHARG_DONE, 1, 2), |
525 | INIT_REGMAP_IRQ(AXP22X, BATT_TEMP_HIGH, 1, 1), |
526 | INIT_REGMAP_IRQ(AXP22X, BATT_TEMP_LOW, 1, 0), |
527 | INIT_REGMAP_IRQ(AXP22X, DIE_TEMP_HIGH, 2, 7), |
528 | INIT_REGMAP_IRQ(AXP22X, PEK_SHORT, 2, 1), |
529 | INIT_REGMAP_IRQ(AXP22X, PEK_LONG, 2, 0), |
530 | INIT_REGMAP_IRQ(AXP22X, LOW_PWR_LVL1, 3, 1), |
531 | INIT_REGMAP_IRQ(AXP22X, LOW_PWR_LVL2, 3, 0), |
532 | INIT_REGMAP_IRQ(AXP22X, TIMER, 4, 7), |
533 | INIT_REGMAP_IRQ(AXP22X, PEK_RIS_EDGE, 4, 6), |
534 | INIT_REGMAP_IRQ(AXP22X, PEK_FAL_EDGE, 4, 5), |
535 | INIT_REGMAP_IRQ(AXP22X, GPIO1_INPUT, 4, 1), |
536 | INIT_REGMAP_IRQ(AXP22X, GPIO0_INPUT, 4, 0), |
537 | }; |
538 | |
539 | /* some IRQs are compatible with axp20x models */ |
540 | static const struct regmap_irq axp288_regmap_irqs[] = { |
541 | INIT_REGMAP_IRQ(AXP288, VBUS_FALL, 0, 2), |
542 | INIT_REGMAP_IRQ(AXP288, VBUS_RISE, 0, 3), |
543 | INIT_REGMAP_IRQ(AXP288, OV, 0, 4), |
544 | INIT_REGMAP_IRQ(AXP288, FALLING_ALT, 0, 5), |
545 | INIT_REGMAP_IRQ(AXP288, RISING_ALT, 0, 6), |
546 | INIT_REGMAP_IRQ(AXP288, OV_ALT, 0, 7), |
547 | |
548 | INIT_REGMAP_IRQ(AXP288, DONE, 1, 2), |
549 | INIT_REGMAP_IRQ(AXP288, CHARGING, 1, 3), |
550 | INIT_REGMAP_IRQ(AXP288, SAFE_QUIT, 1, 4), |
551 | INIT_REGMAP_IRQ(AXP288, SAFE_ENTER, 1, 5), |
552 | INIT_REGMAP_IRQ(AXP288, ABSENT, 1, 6), |
553 | INIT_REGMAP_IRQ(AXP288, APPEND, 1, 7), |
554 | |
555 | INIT_REGMAP_IRQ(AXP288, QWBTU, 2, 0), |
556 | INIT_REGMAP_IRQ(AXP288, WBTU, 2, 1), |
557 | INIT_REGMAP_IRQ(AXP288, QWBTO, 2, 2), |
558 | INIT_REGMAP_IRQ(AXP288, WBTO, 2, 3), |
559 | INIT_REGMAP_IRQ(AXP288, QCBTU, 2, 4), |
560 | INIT_REGMAP_IRQ(AXP288, CBTU, 2, 5), |
561 | INIT_REGMAP_IRQ(AXP288, QCBTO, 2, 6), |
562 | INIT_REGMAP_IRQ(AXP288, CBTO, 2, 7), |
563 | |
564 | INIT_REGMAP_IRQ(AXP288, WL2, 3, 0), |
565 | INIT_REGMAP_IRQ(AXP288, WL1, 3, 1), |
566 | INIT_REGMAP_IRQ(AXP288, GPADC, 3, 2), |
567 | INIT_REGMAP_IRQ(AXP288, OT, 3, 7), |
568 | |
569 | INIT_REGMAP_IRQ(AXP288, GPIO0, 4, 0), |
570 | INIT_REGMAP_IRQ(AXP288, GPIO1, 4, 1), |
571 | INIT_REGMAP_IRQ(AXP288, POKO, 4, 2), |
572 | INIT_REGMAP_IRQ(AXP288, POKL, 4, 3), |
573 | INIT_REGMAP_IRQ(AXP288, POKS, 4, 4), |
574 | INIT_REGMAP_IRQ(AXP288, POKN, 4, 5), |
575 | INIT_REGMAP_IRQ(AXP288, POKP, 4, 6), |
576 | INIT_REGMAP_IRQ(AXP288, TIMER, 4, 7), |
577 | |
578 | INIT_REGMAP_IRQ(AXP288, MV_CHNG, 5, 0), |
579 | INIT_REGMAP_IRQ(AXP288, BC_USB_CHNG, 5, 1), |
580 | }; |
581 | |
582 | static const struct regmap_irq axp313a_regmap_irqs[] = { |
583 | INIT_REGMAP_IRQ(AXP313A, PEK_RIS_EDGE, 0, 7), |
584 | INIT_REGMAP_IRQ(AXP313A, PEK_FAL_EDGE, 0, 6), |
585 | INIT_REGMAP_IRQ(AXP313A, PEK_SHORT, 0, 5), |
586 | INIT_REGMAP_IRQ(AXP313A, PEK_LONG, 0, 4), |
587 | INIT_REGMAP_IRQ(AXP313A, DCDC3_V_LOW, 0, 3), |
588 | INIT_REGMAP_IRQ(AXP313A, DCDC2_V_LOW, 0, 2), |
589 | INIT_REGMAP_IRQ(AXP313A, DIE_TEMP_HIGH, 0, 0), |
590 | }; |
591 | |
592 | static const struct regmap_irq axp803_regmap_irqs[] = { |
593 | INIT_REGMAP_IRQ(AXP803, ACIN_OVER_V, 0, 7), |
594 | INIT_REGMAP_IRQ(AXP803, ACIN_PLUGIN, 0, 6), |
595 | INIT_REGMAP_IRQ(AXP803, ACIN_REMOVAL, 0, 5), |
596 | INIT_REGMAP_IRQ(AXP803, VBUS_OVER_V, 0, 4), |
597 | INIT_REGMAP_IRQ(AXP803, VBUS_PLUGIN, 0, 3), |
598 | INIT_REGMAP_IRQ(AXP803, VBUS_REMOVAL, 0, 2), |
599 | INIT_REGMAP_IRQ(AXP803, BATT_PLUGIN, 1, 7), |
600 | INIT_REGMAP_IRQ(AXP803, BATT_REMOVAL, 1, 6), |
601 | INIT_REGMAP_IRQ(AXP803, BATT_ENT_ACT_MODE, 1, 5), |
602 | INIT_REGMAP_IRQ(AXP803, BATT_EXIT_ACT_MODE, 1, 4), |
603 | INIT_REGMAP_IRQ(AXP803, CHARG, 1, 3), |
604 | INIT_REGMAP_IRQ(AXP803, CHARG_DONE, 1, 2), |
605 | INIT_REGMAP_IRQ(AXP803, BATT_CHG_TEMP_HIGH, 2, 7), |
606 | INIT_REGMAP_IRQ(AXP803, BATT_CHG_TEMP_HIGH_END, 2, 6), |
607 | INIT_REGMAP_IRQ(AXP803, BATT_CHG_TEMP_LOW, 2, 5), |
608 | INIT_REGMAP_IRQ(AXP803, BATT_CHG_TEMP_LOW_END, 2, 4), |
609 | INIT_REGMAP_IRQ(AXP803, BATT_ACT_TEMP_HIGH, 2, 3), |
610 | INIT_REGMAP_IRQ(AXP803, BATT_ACT_TEMP_HIGH_END, 2, 2), |
611 | INIT_REGMAP_IRQ(AXP803, BATT_ACT_TEMP_LOW, 2, 1), |
612 | INIT_REGMAP_IRQ(AXP803, BATT_ACT_TEMP_LOW_END, 2, 0), |
613 | INIT_REGMAP_IRQ(AXP803, DIE_TEMP_HIGH, 3, 7), |
614 | INIT_REGMAP_IRQ(AXP803, GPADC, 3, 2), |
615 | INIT_REGMAP_IRQ(AXP803, LOW_PWR_LVL1, 3, 1), |
616 | INIT_REGMAP_IRQ(AXP803, LOW_PWR_LVL2, 3, 0), |
617 | INIT_REGMAP_IRQ(AXP803, TIMER, 4, 7), |
618 | INIT_REGMAP_IRQ(AXP803, PEK_RIS_EDGE, 4, 6), |
619 | INIT_REGMAP_IRQ(AXP803, PEK_FAL_EDGE, 4, 5), |
620 | INIT_REGMAP_IRQ(AXP803, PEK_SHORT, 4, 4), |
621 | INIT_REGMAP_IRQ(AXP803, PEK_LONG, 4, 3), |
622 | INIT_REGMAP_IRQ(AXP803, PEK_OVER_OFF, 4, 2), |
623 | INIT_REGMAP_IRQ(AXP803, GPIO1_INPUT, 4, 1), |
624 | INIT_REGMAP_IRQ(AXP803, GPIO0_INPUT, 4, 0), |
625 | INIT_REGMAP_IRQ(AXP803, BC_USB_CHNG, 5, 1), |
626 | INIT_REGMAP_IRQ(AXP803, MV_CHNG, 5, 0), |
627 | }; |
628 | |
629 | static const struct regmap_irq axp806_regmap_irqs[] = { |
630 | INIT_REGMAP_IRQ(AXP806, DIE_TEMP_HIGH_LV1, 0, 0), |
631 | INIT_REGMAP_IRQ(AXP806, DIE_TEMP_HIGH_LV2, 0, 1), |
632 | INIT_REGMAP_IRQ(AXP806, DCDCA_V_LOW, 0, 3), |
633 | INIT_REGMAP_IRQ(AXP806, DCDCB_V_LOW, 0, 4), |
634 | INIT_REGMAP_IRQ(AXP806, DCDCC_V_LOW, 0, 5), |
635 | INIT_REGMAP_IRQ(AXP806, DCDCD_V_LOW, 0, 6), |
636 | INIT_REGMAP_IRQ(AXP806, DCDCE_V_LOW, 0, 7), |
637 | INIT_REGMAP_IRQ(AXP806, POK_LONG, 1, 0), |
638 | INIT_REGMAP_IRQ(AXP806, POK_SHORT, 1, 1), |
639 | INIT_REGMAP_IRQ(AXP806, WAKEUP, 1, 4), |
640 | INIT_REGMAP_IRQ(AXP806, POK_FALL, 1, 5), |
641 | INIT_REGMAP_IRQ(AXP806, POK_RISE, 1, 6), |
642 | }; |
643 | |
644 | static const struct regmap_irq axp809_regmap_irqs[] = { |
645 | INIT_REGMAP_IRQ(AXP809, ACIN_OVER_V, 0, 7), |
646 | INIT_REGMAP_IRQ(AXP809, ACIN_PLUGIN, 0, 6), |
647 | INIT_REGMAP_IRQ(AXP809, ACIN_REMOVAL, 0, 5), |
648 | INIT_REGMAP_IRQ(AXP809, VBUS_OVER_V, 0, 4), |
649 | INIT_REGMAP_IRQ(AXP809, VBUS_PLUGIN, 0, 3), |
650 | INIT_REGMAP_IRQ(AXP809, VBUS_REMOVAL, 0, 2), |
651 | INIT_REGMAP_IRQ(AXP809, VBUS_V_LOW, 0, 1), |
652 | INIT_REGMAP_IRQ(AXP809, BATT_PLUGIN, 1, 7), |
653 | INIT_REGMAP_IRQ(AXP809, BATT_REMOVAL, 1, 6), |
654 | INIT_REGMAP_IRQ(AXP809, BATT_ENT_ACT_MODE, 1, 5), |
655 | INIT_REGMAP_IRQ(AXP809, BATT_EXIT_ACT_MODE, 1, 4), |
656 | INIT_REGMAP_IRQ(AXP809, CHARG, 1, 3), |
657 | INIT_REGMAP_IRQ(AXP809, CHARG_DONE, 1, 2), |
658 | INIT_REGMAP_IRQ(AXP809, BATT_CHG_TEMP_HIGH, 2, 7), |
659 | INIT_REGMAP_IRQ(AXP809, BATT_CHG_TEMP_HIGH_END, 2, 6), |
660 | INIT_REGMAP_IRQ(AXP809, BATT_CHG_TEMP_LOW, 2, 5), |
661 | INIT_REGMAP_IRQ(AXP809, BATT_CHG_TEMP_LOW_END, 2, 4), |
662 | INIT_REGMAP_IRQ(AXP809, BATT_ACT_TEMP_HIGH, 2, 3), |
663 | INIT_REGMAP_IRQ(AXP809, BATT_ACT_TEMP_HIGH_END, 2, 2), |
664 | INIT_REGMAP_IRQ(AXP809, BATT_ACT_TEMP_LOW, 2, 1), |
665 | INIT_REGMAP_IRQ(AXP809, BATT_ACT_TEMP_LOW_END, 2, 0), |
666 | INIT_REGMAP_IRQ(AXP809, DIE_TEMP_HIGH, 3, 7), |
667 | INIT_REGMAP_IRQ(AXP809, LOW_PWR_LVL1, 3, 1), |
668 | INIT_REGMAP_IRQ(AXP809, LOW_PWR_LVL2, 3, 0), |
669 | INIT_REGMAP_IRQ(AXP809, TIMER, 4, 7), |
670 | INIT_REGMAP_IRQ(AXP809, PEK_RIS_EDGE, 4, 6), |
671 | INIT_REGMAP_IRQ(AXP809, PEK_FAL_EDGE, 4, 5), |
672 | INIT_REGMAP_IRQ(AXP809, PEK_SHORT, 4, 4), |
673 | INIT_REGMAP_IRQ(AXP809, PEK_LONG, 4, 3), |
674 | INIT_REGMAP_IRQ(AXP809, PEK_OVER_OFF, 4, 2), |
675 | INIT_REGMAP_IRQ(AXP809, GPIO1_INPUT, 4, 1), |
676 | INIT_REGMAP_IRQ(AXP809, GPIO0_INPUT, 4, 0), |
677 | }; |
678 | |
679 | static const struct regmap_irq axp15060_regmap_irqs[] = { |
680 | INIT_REGMAP_IRQ(AXP15060, DIE_TEMP_HIGH_LV1, 0, 0), |
681 | INIT_REGMAP_IRQ(AXP15060, DIE_TEMP_HIGH_LV2, 0, 1), |
682 | INIT_REGMAP_IRQ(AXP15060, DCDC1_V_LOW, 0, 2), |
683 | INIT_REGMAP_IRQ(AXP15060, DCDC2_V_LOW, 0, 3), |
684 | INIT_REGMAP_IRQ(AXP15060, DCDC3_V_LOW, 0, 4), |
685 | INIT_REGMAP_IRQ(AXP15060, DCDC4_V_LOW, 0, 5), |
686 | INIT_REGMAP_IRQ(AXP15060, DCDC5_V_LOW, 0, 6), |
687 | INIT_REGMAP_IRQ(AXP15060, DCDC6_V_LOW, 0, 7), |
688 | INIT_REGMAP_IRQ(AXP15060, PEK_LONG, 1, 0), |
689 | INIT_REGMAP_IRQ(AXP15060, PEK_SHORT, 1, 1), |
690 | INIT_REGMAP_IRQ(AXP15060, GPIO1_INPUT, 1, 2), |
691 | INIT_REGMAP_IRQ(AXP15060, PEK_FAL_EDGE, 1, 3), |
692 | INIT_REGMAP_IRQ(AXP15060, PEK_RIS_EDGE, 1, 4), |
693 | INIT_REGMAP_IRQ(AXP15060, GPIO2_INPUT, 1, 5), |
694 | }; |
695 | |
696 | static const struct regmap_irq_chip axp152_regmap_irq_chip = { |
697 | .name = "axp152_irq_chip" , |
698 | .status_base = AXP152_IRQ1_STATE, |
699 | .ack_base = AXP152_IRQ1_STATE, |
700 | .unmask_base = AXP152_IRQ1_EN, |
701 | .init_ack_masked = true, |
702 | .irqs = axp152_regmap_irqs, |
703 | .num_irqs = ARRAY_SIZE(axp152_regmap_irqs), |
704 | .num_regs = 3, |
705 | }; |
706 | |
707 | static unsigned int axp192_get_irq_reg(struct regmap_irq_chip_data *data, |
708 | unsigned int base, int index) |
709 | { |
710 | /* linear mapping for IRQ1 to IRQ4 */ |
711 | if (index < 4) |
712 | return base + index; |
713 | |
714 | /* handle IRQ5 separately */ |
715 | if (base == AXP192_IRQ1_EN) |
716 | return AXP192_IRQ5_EN; |
717 | |
718 | return AXP192_IRQ5_STATE; |
719 | } |
720 | |
721 | static const struct regmap_irq_chip axp192_regmap_irq_chip = { |
722 | .name = "axp192_irq_chip" , |
723 | .status_base = AXP192_IRQ1_STATE, |
724 | .ack_base = AXP192_IRQ1_STATE, |
725 | .unmask_base = AXP192_IRQ1_EN, |
726 | .init_ack_masked = true, |
727 | .irqs = axp192_regmap_irqs, |
728 | .num_irqs = ARRAY_SIZE(axp192_regmap_irqs), |
729 | .num_regs = 5, |
730 | .get_irq_reg = axp192_get_irq_reg, |
731 | }; |
732 | |
733 | static const struct regmap_irq_chip axp20x_regmap_irq_chip = { |
734 | .name = "axp20x_irq_chip" , |
735 | .status_base = AXP20X_IRQ1_STATE, |
736 | .ack_base = AXP20X_IRQ1_STATE, |
737 | .unmask_base = AXP20X_IRQ1_EN, |
738 | .init_ack_masked = true, |
739 | .irqs = axp20x_regmap_irqs, |
740 | .num_irqs = ARRAY_SIZE(axp20x_regmap_irqs), |
741 | .num_regs = 5, |
742 | |
743 | }; |
744 | |
745 | static const struct regmap_irq_chip axp22x_regmap_irq_chip = { |
746 | .name = "axp22x_irq_chip" , |
747 | .status_base = AXP20X_IRQ1_STATE, |
748 | .ack_base = AXP20X_IRQ1_STATE, |
749 | .unmask_base = AXP20X_IRQ1_EN, |
750 | .init_ack_masked = true, |
751 | .irqs = axp22x_regmap_irqs, |
752 | .num_irqs = ARRAY_SIZE(axp22x_regmap_irqs), |
753 | .num_regs = 5, |
754 | }; |
755 | |
756 | static const struct regmap_irq_chip axp288_regmap_irq_chip = { |
757 | .name = "axp288_irq_chip" , |
758 | .status_base = AXP20X_IRQ1_STATE, |
759 | .ack_base = AXP20X_IRQ1_STATE, |
760 | .unmask_base = AXP20X_IRQ1_EN, |
761 | .init_ack_masked = true, |
762 | .irqs = axp288_regmap_irqs, |
763 | .num_irqs = ARRAY_SIZE(axp288_regmap_irqs), |
764 | .num_regs = 6, |
765 | |
766 | }; |
767 | |
768 | static const struct regmap_irq_chip axp313a_regmap_irq_chip = { |
769 | .name = "axp313a_irq_chip" , |
770 | .status_base = AXP313A_IRQ_STATE, |
771 | .ack_base = AXP313A_IRQ_STATE, |
772 | .unmask_base = AXP313A_IRQ_EN, |
773 | .init_ack_masked = true, |
774 | .irqs = axp313a_regmap_irqs, |
775 | .num_irqs = ARRAY_SIZE(axp313a_regmap_irqs), |
776 | .num_regs = 1, |
777 | }; |
778 | |
779 | static const struct regmap_irq_chip axp803_regmap_irq_chip = { |
780 | .name = "axp803" , |
781 | .status_base = AXP20X_IRQ1_STATE, |
782 | .ack_base = AXP20X_IRQ1_STATE, |
783 | .unmask_base = AXP20X_IRQ1_EN, |
784 | .init_ack_masked = true, |
785 | .irqs = axp803_regmap_irqs, |
786 | .num_irqs = ARRAY_SIZE(axp803_regmap_irqs), |
787 | .num_regs = 6, |
788 | }; |
789 | |
790 | static const struct regmap_irq_chip axp806_regmap_irq_chip = { |
791 | .name = "axp806" , |
792 | .status_base = AXP20X_IRQ1_STATE, |
793 | .ack_base = AXP20X_IRQ1_STATE, |
794 | .unmask_base = AXP20X_IRQ1_EN, |
795 | .init_ack_masked = true, |
796 | .irqs = axp806_regmap_irqs, |
797 | .num_irqs = ARRAY_SIZE(axp806_regmap_irqs), |
798 | .num_regs = 2, |
799 | }; |
800 | |
801 | static const struct regmap_irq_chip axp809_regmap_irq_chip = { |
802 | .name = "axp809" , |
803 | .status_base = AXP20X_IRQ1_STATE, |
804 | .ack_base = AXP20X_IRQ1_STATE, |
805 | .unmask_base = AXP20X_IRQ1_EN, |
806 | .init_ack_masked = true, |
807 | .irqs = axp809_regmap_irqs, |
808 | .num_irqs = ARRAY_SIZE(axp809_regmap_irqs), |
809 | .num_regs = 5, |
810 | }; |
811 | |
812 | static const struct regmap_irq_chip axp15060_regmap_irq_chip = { |
813 | .name = "axp15060" , |
814 | .status_base = AXP15060_IRQ1_STATE, |
815 | .ack_base = AXP15060_IRQ1_STATE, |
816 | .unmask_base = AXP15060_IRQ1_EN, |
817 | .init_ack_masked = true, |
818 | .irqs = axp15060_regmap_irqs, |
819 | .num_irqs = ARRAY_SIZE(axp15060_regmap_irqs), |
820 | .num_regs = 2, |
821 | }; |
822 | |
823 | static const struct mfd_cell axp192_cells[] = { |
824 | { |
825 | .name = "axp192-adc" , |
826 | .of_compatible = "x-powers,axp192-adc" , |
827 | }, { |
828 | .name = "axp20x-battery-power-supply" , |
829 | .of_compatible = "x-powers,axp192-battery-power-supply" , |
830 | }, { |
831 | .name = "axp20x-ac-power-supply" , |
832 | .of_compatible = "x-powers,axp202-ac-power-supply" , |
833 | .num_resources = ARRAY_SIZE(axp192_ac_power_supply_resources), |
834 | .resources = axp192_ac_power_supply_resources, |
835 | }, { |
836 | .name = "axp20x-usb-power-supply" , |
837 | .of_compatible = "x-powers,axp192-usb-power-supply" , |
838 | .num_resources = ARRAY_SIZE(axp192_usb_power_supply_resources), |
839 | .resources = axp192_usb_power_supply_resources, |
840 | }, |
841 | { .name = "axp20x-regulator" }, |
842 | }; |
843 | |
844 | static const struct mfd_cell axp20x_cells[] = { |
845 | { |
846 | .name = "axp20x-gpio" , |
847 | .of_compatible = "x-powers,axp209-gpio" , |
848 | }, { |
849 | .name = "axp20x-pek" , |
850 | .num_resources = ARRAY_SIZE(axp20x_pek_resources), |
851 | .resources = axp20x_pek_resources, |
852 | }, { |
853 | .name = "axp20x-regulator" , |
854 | }, { |
855 | .name = "axp20x-adc" , |
856 | .of_compatible = "x-powers,axp209-adc" , |
857 | }, { |
858 | .name = "axp20x-battery-power-supply" , |
859 | .of_compatible = "x-powers,axp209-battery-power-supply" , |
860 | }, { |
861 | .name = "axp20x-ac-power-supply" , |
862 | .of_compatible = "x-powers,axp202-ac-power-supply" , |
863 | .num_resources = ARRAY_SIZE(axp20x_ac_power_supply_resources), |
864 | .resources = axp20x_ac_power_supply_resources, |
865 | }, { |
866 | .name = "axp20x-usb-power-supply" , |
867 | .of_compatible = "x-powers,axp202-usb-power-supply" , |
868 | .num_resources = ARRAY_SIZE(axp20x_usb_power_supply_resources), |
869 | .resources = axp20x_usb_power_supply_resources, |
870 | }, |
871 | }; |
872 | |
873 | static const struct mfd_cell axp221_cells[] = { |
874 | { |
875 | .name = "axp20x-gpio" , |
876 | .of_compatible = "x-powers,axp221-gpio" , |
877 | }, { |
878 | .name = "axp221-pek" , |
879 | .num_resources = ARRAY_SIZE(axp22x_pek_resources), |
880 | .resources = axp22x_pek_resources, |
881 | }, { |
882 | .name = "axp20x-regulator" , |
883 | }, { |
884 | .name = "axp22x-adc" , |
885 | .of_compatible = "x-powers,axp221-adc" , |
886 | }, { |
887 | .name = "axp20x-ac-power-supply" , |
888 | .of_compatible = "x-powers,axp221-ac-power-supply" , |
889 | .num_resources = ARRAY_SIZE(axp20x_ac_power_supply_resources), |
890 | .resources = axp20x_ac_power_supply_resources, |
891 | }, { |
892 | .name = "axp20x-battery-power-supply" , |
893 | .of_compatible = "x-powers,axp221-battery-power-supply" , |
894 | }, { |
895 | .name = "axp20x-usb-power-supply" , |
896 | .of_compatible = "x-powers,axp221-usb-power-supply" , |
897 | .num_resources = ARRAY_SIZE(axp22x_usb_power_supply_resources), |
898 | .resources = axp22x_usb_power_supply_resources, |
899 | }, |
900 | }; |
901 | |
902 | static const struct mfd_cell axp223_cells[] = { |
903 | { |
904 | .name = "axp20x-gpio" , |
905 | .of_compatible = "x-powers,axp221-gpio" , |
906 | }, { |
907 | .name = "axp221-pek" , |
908 | .num_resources = ARRAY_SIZE(axp22x_pek_resources), |
909 | .resources = axp22x_pek_resources, |
910 | }, { |
911 | .name = "axp22x-adc" , |
912 | .of_compatible = "x-powers,axp221-adc" , |
913 | }, { |
914 | .name = "axp20x-battery-power-supply" , |
915 | .of_compatible = "x-powers,axp221-battery-power-supply" , |
916 | }, { |
917 | .name = "axp20x-regulator" , |
918 | }, { |
919 | .name = "axp20x-ac-power-supply" , |
920 | .of_compatible = "x-powers,axp221-ac-power-supply" , |
921 | .num_resources = ARRAY_SIZE(axp20x_ac_power_supply_resources), |
922 | .resources = axp20x_ac_power_supply_resources, |
923 | }, { |
924 | .name = "axp20x-usb-power-supply" , |
925 | .of_compatible = "x-powers,axp223-usb-power-supply" , |
926 | .num_resources = ARRAY_SIZE(axp22x_usb_power_supply_resources), |
927 | .resources = axp22x_usb_power_supply_resources, |
928 | }, |
929 | }; |
930 | |
931 | static const struct mfd_cell axp152_cells[] = { |
932 | { |
933 | .name = "axp20x-pek" , |
934 | .num_resources = ARRAY_SIZE(axp152_pek_resources), |
935 | .resources = axp152_pek_resources, |
936 | }, |
937 | }; |
938 | |
939 | static struct mfd_cell axp313a_cells[] = { |
940 | MFD_CELL_NAME("axp20x-regulator" ), |
941 | MFD_CELL_RES("axp313a-pek" , axp313a_pek_resources), |
942 | }; |
943 | |
944 | static const struct resource axp288_adc_resources[] = { |
945 | DEFINE_RES_IRQ_NAMED(AXP288_IRQ_GPADC, "GPADC" ), |
946 | }; |
947 | |
948 | static const struct resource axp288_extcon_resources[] = { |
949 | DEFINE_RES_IRQ(AXP288_IRQ_VBUS_FALL), |
950 | DEFINE_RES_IRQ(AXP288_IRQ_VBUS_RISE), |
951 | DEFINE_RES_IRQ(AXP288_IRQ_MV_CHNG), |
952 | DEFINE_RES_IRQ(AXP288_IRQ_BC_USB_CHNG), |
953 | }; |
954 | |
955 | static const struct resource axp288_charger_resources[] = { |
956 | DEFINE_RES_IRQ(AXP288_IRQ_OV), |
957 | DEFINE_RES_IRQ(AXP288_IRQ_DONE), |
958 | DEFINE_RES_IRQ(AXP288_IRQ_CHARGING), |
959 | DEFINE_RES_IRQ(AXP288_IRQ_SAFE_QUIT), |
960 | DEFINE_RES_IRQ(AXP288_IRQ_SAFE_ENTER), |
961 | DEFINE_RES_IRQ(AXP288_IRQ_QCBTU), |
962 | DEFINE_RES_IRQ(AXP288_IRQ_CBTU), |
963 | DEFINE_RES_IRQ(AXP288_IRQ_QCBTO), |
964 | DEFINE_RES_IRQ(AXP288_IRQ_CBTO), |
965 | }; |
966 | |
967 | static const char * const axp288_fuel_gauge_suppliers[] = { "axp288_charger" }; |
968 | |
969 | static const struct property_entry axp288_fuel_gauge_properties[] = { |
970 | PROPERTY_ENTRY_STRING_ARRAY("supplied-from" , axp288_fuel_gauge_suppliers), |
971 | { } |
972 | }; |
973 | |
974 | static const struct software_node axp288_fuel_gauge_sw_node = { |
975 | .name = "axp288_fuel_gauge" , |
976 | .properties = axp288_fuel_gauge_properties, |
977 | }; |
978 | |
979 | static const struct mfd_cell axp288_cells[] = { |
980 | { |
981 | .name = "axp288_adc" , |
982 | .num_resources = ARRAY_SIZE(axp288_adc_resources), |
983 | .resources = axp288_adc_resources, |
984 | }, { |
985 | .name = "axp288_extcon" , |
986 | .num_resources = ARRAY_SIZE(axp288_extcon_resources), |
987 | .resources = axp288_extcon_resources, |
988 | }, { |
989 | .name = "axp288_charger" , |
990 | .num_resources = ARRAY_SIZE(axp288_charger_resources), |
991 | .resources = axp288_charger_resources, |
992 | }, { |
993 | .name = "axp288_fuel_gauge" , |
994 | .num_resources = ARRAY_SIZE(axp288_fuel_gauge_resources), |
995 | .resources = axp288_fuel_gauge_resources, |
996 | .swnode = &axp288_fuel_gauge_sw_node, |
997 | }, { |
998 | .name = "axp221-pek" , |
999 | .num_resources = ARRAY_SIZE(axp288_power_button_resources), |
1000 | .resources = axp288_power_button_resources, |
1001 | }, { |
1002 | .name = "axp288_pmic_acpi" , |
1003 | }, |
1004 | }; |
1005 | |
1006 | static const struct mfd_cell axp803_cells[] = { |
1007 | { |
1008 | .name = "axp221-pek" , |
1009 | .num_resources = ARRAY_SIZE(axp803_pek_resources), |
1010 | .resources = axp803_pek_resources, |
1011 | }, { |
1012 | .name = "axp20x-gpio" , |
1013 | .of_compatible = "x-powers,axp813-gpio" , |
1014 | }, { |
1015 | .name = "axp813-adc" , |
1016 | .of_compatible = "x-powers,axp813-adc" , |
1017 | }, { |
1018 | .name = "axp20x-battery-power-supply" , |
1019 | .of_compatible = "x-powers,axp813-battery-power-supply" , |
1020 | }, { |
1021 | .name = "axp20x-ac-power-supply" , |
1022 | .of_compatible = "x-powers,axp813-ac-power-supply" , |
1023 | .num_resources = ARRAY_SIZE(axp20x_ac_power_supply_resources), |
1024 | .resources = axp20x_ac_power_supply_resources, |
1025 | }, { |
1026 | .name = "axp20x-usb-power-supply" , |
1027 | .num_resources = ARRAY_SIZE(axp803_usb_power_supply_resources), |
1028 | .resources = axp803_usb_power_supply_resources, |
1029 | .of_compatible = "x-powers,axp813-usb-power-supply" , |
1030 | }, |
1031 | { .name = "axp20x-regulator" }, |
1032 | }; |
1033 | |
1034 | static const struct mfd_cell axp806_self_working_cells[] = { |
1035 | { |
1036 | .name = "axp221-pek" , |
1037 | .num_resources = ARRAY_SIZE(axp806_pek_resources), |
1038 | .resources = axp806_pek_resources, |
1039 | }, |
1040 | { .name = "axp20x-regulator" }, |
1041 | }; |
1042 | |
1043 | static const struct mfd_cell axp806_cells[] = { |
1044 | { |
1045 | .id = 2, |
1046 | .name = "axp20x-regulator" , |
1047 | }, |
1048 | }; |
1049 | |
1050 | static const struct mfd_cell axp809_cells[] = { |
1051 | { |
1052 | .name = "axp20x-gpio" , |
1053 | .of_compatible = "x-powers,axp221-gpio" , |
1054 | }, { |
1055 | .name = "axp221-pek" , |
1056 | .num_resources = ARRAY_SIZE(axp809_pek_resources), |
1057 | .resources = axp809_pek_resources, |
1058 | }, { |
1059 | .id = 1, |
1060 | .name = "axp20x-regulator" , |
1061 | }, |
1062 | }; |
1063 | |
1064 | static const struct mfd_cell axp813_cells[] = { |
1065 | { |
1066 | .name = "axp221-pek" , |
1067 | .num_resources = ARRAY_SIZE(axp803_pek_resources), |
1068 | .resources = axp803_pek_resources, |
1069 | }, { |
1070 | .name = "axp20x-regulator" , |
1071 | }, { |
1072 | .name = "axp20x-gpio" , |
1073 | .of_compatible = "x-powers,axp813-gpio" , |
1074 | }, { |
1075 | .name = "axp813-adc" , |
1076 | .of_compatible = "x-powers,axp813-adc" , |
1077 | }, { |
1078 | .name = "axp20x-battery-power-supply" , |
1079 | .of_compatible = "x-powers,axp813-battery-power-supply" , |
1080 | }, { |
1081 | .name = "axp20x-ac-power-supply" , |
1082 | .of_compatible = "x-powers,axp813-ac-power-supply" , |
1083 | .num_resources = ARRAY_SIZE(axp20x_ac_power_supply_resources), |
1084 | .resources = axp20x_ac_power_supply_resources, |
1085 | }, { |
1086 | .name = "axp20x-usb-power-supply" , |
1087 | .num_resources = ARRAY_SIZE(axp803_usb_power_supply_resources), |
1088 | .resources = axp803_usb_power_supply_resources, |
1089 | .of_compatible = "x-powers,axp813-usb-power-supply" , |
1090 | }, |
1091 | }; |
1092 | |
1093 | static const struct mfd_cell axp15060_cells[] = { |
1094 | { |
1095 | .name = "axp221-pek" , |
1096 | .num_resources = ARRAY_SIZE(axp15060_pek_resources), |
1097 | .resources = axp15060_pek_resources, |
1098 | }, { |
1099 | .name = "axp20x-regulator" , |
1100 | }, |
1101 | }; |
1102 | |
1103 | /* For boards that don't have IRQ line connected to SOC. */ |
1104 | static const struct mfd_cell axp_regulator_only_cells[] = { |
1105 | { |
1106 | .name = "axp20x-regulator" , |
1107 | }, |
1108 | }; |
1109 | |
1110 | static int axp20x_power_off(struct sys_off_data *data) |
1111 | { |
1112 | struct axp20x_dev *axp20x = data->cb_data; |
1113 | unsigned int shutdown_reg; |
1114 | |
1115 | switch (axp20x->variant) { |
1116 | case AXP313A_ID: |
1117 | shutdown_reg = AXP313A_SHUTDOWN_CTRL; |
1118 | break; |
1119 | default: |
1120 | shutdown_reg = AXP20X_OFF_CTRL; |
1121 | break; |
1122 | } |
1123 | |
1124 | regmap_write(map: axp20x->regmap, reg: shutdown_reg, AXP20X_OFF); |
1125 | |
1126 | /* Give capacitors etc. time to drain to avoid kernel panic msg. */ |
1127 | mdelay(500); |
1128 | |
1129 | return NOTIFY_DONE; |
1130 | } |
1131 | |
1132 | int axp20x_match_device(struct axp20x_dev *axp20x) |
1133 | { |
1134 | struct device *dev = axp20x->dev; |
1135 | const struct mfd_cell *cells_no_irq = NULL; |
1136 | int nr_cells_no_irq = 0; |
1137 | |
1138 | axp20x->variant = (long)device_get_match_data(dev); |
1139 | switch (axp20x->variant) { |
1140 | case AXP152_ID: |
1141 | axp20x->nr_cells = ARRAY_SIZE(axp152_cells); |
1142 | axp20x->cells = axp152_cells; |
1143 | axp20x->regmap_cfg = &axp152_regmap_config; |
1144 | axp20x->regmap_irq_chip = &axp152_regmap_irq_chip; |
1145 | break; |
1146 | case AXP192_ID: |
1147 | axp20x->nr_cells = ARRAY_SIZE(axp192_cells); |
1148 | axp20x->cells = axp192_cells; |
1149 | axp20x->regmap_cfg = &axp192_regmap_config; |
1150 | axp20x->regmap_irq_chip = &axp192_regmap_irq_chip; |
1151 | break; |
1152 | case AXP202_ID: |
1153 | case AXP209_ID: |
1154 | axp20x->nr_cells = ARRAY_SIZE(axp20x_cells); |
1155 | axp20x->cells = axp20x_cells; |
1156 | axp20x->regmap_cfg = &axp20x_regmap_config; |
1157 | axp20x->regmap_irq_chip = &axp20x_regmap_irq_chip; |
1158 | break; |
1159 | case AXP221_ID: |
1160 | axp20x->nr_cells = ARRAY_SIZE(axp221_cells); |
1161 | axp20x->cells = axp221_cells; |
1162 | axp20x->regmap_cfg = &axp22x_regmap_config; |
1163 | axp20x->regmap_irq_chip = &axp22x_regmap_irq_chip; |
1164 | break; |
1165 | case AXP223_ID: |
1166 | axp20x->nr_cells = ARRAY_SIZE(axp223_cells); |
1167 | axp20x->cells = axp223_cells; |
1168 | axp20x->regmap_cfg = &axp22x_regmap_config; |
1169 | axp20x->regmap_irq_chip = &axp22x_regmap_irq_chip; |
1170 | break; |
1171 | case AXP288_ID: |
1172 | axp20x->cells = axp288_cells; |
1173 | axp20x->nr_cells = ARRAY_SIZE(axp288_cells); |
1174 | axp20x->regmap_cfg = &axp288_regmap_config; |
1175 | axp20x->regmap_irq_chip = &axp288_regmap_irq_chip; |
1176 | axp20x->irq_flags = IRQF_TRIGGER_LOW; |
1177 | break; |
1178 | case AXP313A_ID: |
1179 | axp20x->nr_cells = ARRAY_SIZE(axp313a_cells); |
1180 | axp20x->cells = axp313a_cells; |
1181 | axp20x->regmap_cfg = &axp313a_regmap_config; |
1182 | axp20x->regmap_irq_chip = &axp313a_regmap_irq_chip; |
1183 | break; |
1184 | case AXP803_ID: |
1185 | axp20x->nr_cells = ARRAY_SIZE(axp803_cells); |
1186 | axp20x->cells = axp803_cells; |
1187 | axp20x->regmap_cfg = &axp288_regmap_config; |
1188 | axp20x->regmap_irq_chip = &axp803_regmap_irq_chip; |
1189 | break; |
1190 | case AXP806_ID: |
1191 | /* |
1192 | * Don't register the power key part if in slave mode or |
1193 | * if there is no interrupt line. |
1194 | */ |
1195 | if (of_property_read_bool(np: axp20x->dev->of_node, |
1196 | propname: "x-powers,self-working-mode" )) { |
1197 | axp20x->nr_cells = ARRAY_SIZE(axp806_self_working_cells); |
1198 | axp20x->cells = axp806_self_working_cells; |
1199 | } else { |
1200 | axp20x->nr_cells = ARRAY_SIZE(axp806_cells); |
1201 | axp20x->cells = axp806_cells; |
1202 | } |
1203 | nr_cells_no_irq = ARRAY_SIZE(axp806_cells); |
1204 | cells_no_irq = axp806_cells; |
1205 | axp20x->regmap_cfg = &axp806_regmap_config; |
1206 | axp20x->regmap_irq_chip = &axp806_regmap_irq_chip; |
1207 | break; |
1208 | case AXP809_ID: |
1209 | axp20x->nr_cells = ARRAY_SIZE(axp809_cells); |
1210 | axp20x->cells = axp809_cells; |
1211 | axp20x->regmap_cfg = &axp22x_regmap_config; |
1212 | axp20x->regmap_irq_chip = &axp809_regmap_irq_chip; |
1213 | break; |
1214 | case AXP813_ID: |
1215 | axp20x->nr_cells = ARRAY_SIZE(axp813_cells); |
1216 | axp20x->cells = axp813_cells; |
1217 | axp20x->regmap_cfg = &axp288_regmap_config; |
1218 | /* |
1219 | * The IRQ table given in the datasheet is incorrect. |
1220 | * In IRQ enable/status registers 1, there are separate |
1221 | * IRQs for ACIN and VBUS, instead of bits [7:5] being |
1222 | * the same as bits [4:2]. So it shares the same IRQs |
1223 | * as the AXP803, rather than the AXP288. |
1224 | */ |
1225 | axp20x->regmap_irq_chip = &axp803_regmap_irq_chip; |
1226 | break; |
1227 | case AXP15060_ID: |
1228 | axp20x->nr_cells = ARRAY_SIZE(axp15060_cells); |
1229 | axp20x->cells = axp15060_cells; |
1230 | axp20x->regmap_cfg = &axp15060_regmap_config; |
1231 | axp20x->regmap_irq_chip = &axp15060_regmap_irq_chip; |
1232 | break; |
1233 | default: |
1234 | dev_err(dev, "unsupported AXP20X ID %lu\n" , axp20x->variant); |
1235 | return -EINVAL; |
1236 | } |
1237 | |
1238 | /* |
1239 | * Use an alternative cell array when no interrupt line is connected, |
1240 | * since IRQs are required by some drivers. |
1241 | * The default is the safe "regulator-only", as this works fine without |
1242 | * an interrupt specified. |
1243 | */ |
1244 | if (axp20x->irq <= 0) { |
1245 | if (cells_no_irq) { |
1246 | axp20x->nr_cells = nr_cells_no_irq; |
1247 | axp20x->cells = cells_no_irq; |
1248 | } else { |
1249 | axp20x->nr_cells = ARRAY_SIZE(axp_regulator_only_cells); |
1250 | axp20x->cells = axp_regulator_only_cells; |
1251 | } |
1252 | } |
1253 | |
1254 | dev_info(dev, "AXP20x variant %s found\n" , |
1255 | axp20x_model_names[axp20x->variant]); |
1256 | |
1257 | return 0; |
1258 | } |
1259 | EXPORT_SYMBOL(axp20x_match_device); |
1260 | |
1261 | int axp20x_device_probe(struct axp20x_dev *axp20x) |
1262 | { |
1263 | int ret; |
1264 | |
1265 | /* |
1266 | * The AXP806 supports either master/standalone or slave mode. |
1267 | * Slave mode allows sharing the serial bus, even with multiple |
1268 | * AXP806 which all have the same hardware address. |
1269 | * |
1270 | * This is done with extra "serial interface address extension", |
1271 | * or AXP806_BUS_ADDR_EXT, and "register address extension", or |
1272 | * AXP806_REG_ADDR_EXT, registers. The former is read-only, with |
1273 | * 1 bit customizable at the factory, and 1 bit depending on the |
1274 | * state of an external pin. The latter is writable. The device |
1275 | * will only respond to operations to its other registers when |
1276 | * the these device addressing bits (in the upper 4 bits of the |
1277 | * registers) match. |
1278 | * |
1279 | * By default we support an AXP806 chained to an AXP809 in slave |
1280 | * mode. Boards which use an AXP806 in master mode can set the |
1281 | * property "x-powers,master-mode" to override the default. |
1282 | */ |
1283 | if (axp20x->variant == AXP806_ID) { |
1284 | if (of_property_read_bool(np: axp20x->dev->of_node, |
1285 | propname: "x-powers,master-mode" ) || |
1286 | of_property_read_bool(np: axp20x->dev->of_node, |
1287 | propname: "x-powers,self-working-mode" )) |
1288 | regmap_write(map: axp20x->regmap, AXP806_REG_ADDR_EXT, |
1289 | AXP806_REG_ADDR_EXT_ADDR_MASTER_MODE); |
1290 | else |
1291 | regmap_write(map: axp20x->regmap, AXP806_REG_ADDR_EXT, |
1292 | AXP806_REG_ADDR_EXT_ADDR_SLAVE_MODE); |
1293 | } |
1294 | |
1295 | /* Only if there is an interrupt line connected towards the CPU. */ |
1296 | if (axp20x->irq > 0) { |
1297 | ret = regmap_add_irq_chip(map: axp20x->regmap, irq: axp20x->irq, |
1298 | IRQF_ONESHOT | IRQF_SHARED | axp20x->irq_flags, |
1299 | irq_base: -1, chip: axp20x->regmap_irq_chip, |
1300 | data: &axp20x->regmap_irqc); |
1301 | if (ret) { |
1302 | dev_err(axp20x->dev, "failed to add irq chip: %d\n" , |
1303 | ret); |
1304 | return ret; |
1305 | } |
1306 | } |
1307 | |
1308 | ret = mfd_add_devices(parent: axp20x->dev, id: -1, cells: axp20x->cells, |
1309 | n_devs: axp20x->nr_cells, NULL, irq_base: 0, NULL); |
1310 | |
1311 | if (ret) { |
1312 | dev_err(axp20x->dev, "failed to add MFD devices: %d\n" , ret); |
1313 | regmap_del_irq_chip(irq: axp20x->irq, data: axp20x->regmap_irqc); |
1314 | return ret; |
1315 | } |
1316 | |
1317 | if (axp20x->variant != AXP288_ID) |
1318 | devm_register_sys_off_handler(dev: axp20x->dev, |
1319 | mode: SYS_OFF_MODE_POWER_OFF, |
1320 | SYS_OFF_PRIO_DEFAULT, |
1321 | callback: axp20x_power_off, cb_data: axp20x); |
1322 | |
1323 | dev_info(axp20x->dev, "AXP20X driver loaded\n" ); |
1324 | |
1325 | return 0; |
1326 | } |
1327 | EXPORT_SYMBOL(axp20x_device_probe); |
1328 | |
1329 | void axp20x_device_remove(struct axp20x_dev *axp20x) |
1330 | { |
1331 | mfd_remove_devices(parent: axp20x->dev); |
1332 | regmap_del_irq_chip(irq: axp20x->irq, data: axp20x->regmap_irqc); |
1333 | } |
1334 | EXPORT_SYMBOL(axp20x_device_remove); |
1335 | |
1336 | MODULE_DESCRIPTION("PMIC MFD core driver for AXP20X" ); |
1337 | MODULE_AUTHOR("Carlo Caione <carlo@caione.org>" ); |
1338 | MODULE_LICENSE("GPL" ); |
1339 | |