xref: /openbmc/linux/drivers/mfd/axp20x.c (revision 82003e04)
1 /*
2  * MFD core driver for the X-Powers' Power Management ICs
3  *
4  * AXP20x typically comprises an adaptive USB-Compatible PWM charger, BUCK DC-DC
5  * converters, LDOs, multiple 12-bit ADCs of voltage, current and temperature
6  * as well as configurable GPIOs.
7  *
8  * This file contains the interface independent core functions.
9  *
10  * Copyright (C) 2014 Carlo Caione
11  *
12  * Author: Carlo Caione <carlo@caione.org>
13  *
14  * This program is free software; you can redistribute it and/or modify
15  * it under the terms of the GNU General Public License version 2 as
16  * published by the Free Software Foundation.
17  */
18 
19 #include <linux/err.h>
20 #include <linux/delay.h>
21 #include <linux/interrupt.h>
22 #include <linux/kernel.h>
23 #include <linux/module.h>
24 #include <linux/pm_runtime.h>
25 #include <linux/regmap.h>
26 #include <linux/regulator/consumer.h>
27 #include <linux/mfd/axp20x.h>
28 #include <linux/mfd/core.h>
29 #include <linux/of_device.h>
30 #include <linux/acpi.h>
31 
32 #define AXP20X_OFF	0x80
33 
34 static const char * const axp20x_model_names[] = {
35 	"AXP152",
36 	"AXP202",
37 	"AXP209",
38 	"AXP221",
39 	"AXP223",
40 	"AXP288",
41 	"AXP806",
42 	"AXP809",
43 };
44 
45 static const struct regmap_range axp152_writeable_ranges[] = {
46 	regmap_reg_range(AXP152_LDO3456_DC1234_CTRL, AXP152_IRQ3_STATE),
47 	regmap_reg_range(AXP152_DCDC_MODE, AXP152_PWM1_DUTY_CYCLE),
48 };
49 
50 static const struct regmap_range axp152_volatile_ranges[] = {
51 	regmap_reg_range(AXP152_PWR_OP_MODE, AXP152_PWR_OP_MODE),
52 	regmap_reg_range(AXP152_IRQ1_EN, AXP152_IRQ3_STATE),
53 	regmap_reg_range(AXP152_GPIO_INPUT, AXP152_GPIO_INPUT),
54 };
55 
56 static const struct regmap_access_table axp152_writeable_table = {
57 	.yes_ranges	= axp152_writeable_ranges,
58 	.n_yes_ranges	= ARRAY_SIZE(axp152_writeable_ranges),
59 };
60 
61 static const struct regmap_access_table axp152_volatile_table = {
62 	.yes_ranges	= axp152_volatile_ranges,
63 	.n_yes_ranges	= ARRAY_SIZE(axp152_volatile_ranges),
64 };
65 
66 static const struct regmap_range axp20x_writeable_ranges[] = {
67 	regmap_reg_range(AXP20X_DATACACHE(0), AXP20X_IRQ5_STATE),
68 	regmap_reg_range(AXP20X_DCDC_MODE, AXP20X_FG_RES),
69 	regmap_reg_range(AXP20X_RDC_H, AXP20X_OCV(AXP20X_OCV_MAX)),
70 };
71 
72 static const struct regmap_range axp20x_volatile_ranges[] = {
73 	regmap_reg_range(AXP20X_PWR_INPUT_STATUS, AXP20X_USB_OTG_STATUS),
74 	regmap_reg_range(AXP20X_CHRG_CTRL1, AXP20X_CHRG_CTRL2),
75 	regmap_reg_range(AXP20X_IRQ1_EN, AXP20X_IRQ5_STATE),
76 	regmap_reg_range(AXP20X_ACIN_V_ADC_H, AXP20X_IPSOUT_V_HIGH_L),
77 	regmap_reg_range(AXP20X_GPIO20_SS, AXP20X_GPIO3_CTRL),
78 	regmap_reg_range(AXP20X_FG_RES, AXP20X_RDC_L),
79 };
80 
81 static const struct regmap_access_table axp20x_writeable_table = {
82 	.yes_ranges	= axp20x_writeable_ranges,
83 	.n_yes_ranges	= ARRAY_SIZE(axp20x_writeable_ranges),
84 };
85 
86 static const struct regmap_access_table axp20x_volatile_table = {
87 	.yes_ranges	= axp20x_volatile_ranges,
88 	.n_yes_ranges	= ARRAY_SIZE(axp20x_volatile_ranges),
89 };
90 
91 /* AXP22x ranges are shared with the AXP809, as they cover the same range */
92 static const struct regmap_range axp22x_writeable_ranges[] = {
93 	regmap_reg_range(AXP20X_DATACACHE(0), AXP20X_IRQ5_STATE),
94 	regmap_reg_range(AXP20X_DCDC_MODE, AXP22X_BATLOW_THRES1),
95 };
96 
97 static const struct regmap_range axp22x_volatile_ranges[] = {
98 	regmap_reg_range(AXP20X_PWR_INPUT_STATUS, AXP20X_PWR_OP_MODE),
99 	regmap_reg_range(AXP20X_IRQ1_EN, AXP20X_IRQ5_STATE),
100 	regmap_reg_range(AXP22X_GPIO_STATE, AXP22X_GPIO_STATE),
101 	regmap_reg_range(AXP20X_FG_RES, AXP20X_FG_RES),
102 };
103 
104 static const struct regmap_access_table axp22x_writeable_table = {
105 	.yes_ranges	= axp22x_writeable_ranges,
106 	.n_yes_ranges	= ARRAY_SIZE(axp22x_writeable_ranges),
107 };
108 
109 static const struct regmap_access_table axp22x_volatile_table = {
110 	.yes_ranges	= axp22x_volatile_ranges,
111 	.n_yes_ranges	= ARRAY_SIZE(axp22x_volatile_ranges),
112 };
113 
114 static const struct regmap_range axp288_writeable_ranges[] = {
115 	regmap_reg_range(AXP20X_DATACACHE(0), AXP20X_IRQ6_STATE),
116 	regmap_reg_range(AXP20X_DCDC_MODE, AXP288_FG_TUNE5),
117 };
118 
119 static const struct regmap_range axp288_volatile_ranges[] = {
120 	regmap_reg_range(AXP20X_IRQ1_EN, AXP20X_IPSOUT_V_HIGH_L),
121 };
122 
123 static const struct regmap_access_table axp288_writeable_table = {
124 	.yes_ranges	= axp288_writeable_ranges,
125 	.n_yes_ranges	= ARRAY_SIZE(axp288_writeable_ranges),
126 };
127 
128 static const struct regmap_access_table axp288_volatile_table = {
129 	.yes_ranges	= axp288_volatile_ranges,
130 	.n_yes_ranges	= ARRAY_SIZE(axp288_volatile_ranges),
131 };
132 
133 static const struct regmap_range axp806_writeable_ranges[] = {
134 	regmap_reg_range(AXP20X_DATACACHE(0), AXP20X_DATACACHE(3)),
135 	regmap_reg_range(AXP806_PWR_OUT_CTRL1, AXP806_CLDO3_V_CTRL),
136 	regmap_reg_range(AXP20X_IRQ1_EN, AXP20X_IRQ2_EN),
137 	regmap_reg_range(AXP20X_IRQ1_STATE, AXP20X_IRQ2_STATE),
138 };
139 
140 static const struct regmap_range axp806_volatile_ranges[] = {
141 	regmap_reg_range(AXP20X_IRQ1_STATE, AXP20X_IRQ2_STATE),
142 };
143 
144 static const struct regmap_access_table axp806_writeable_table = {
145 	.yes_ranges	= axp806_writeable_ranges,
146 	.n_yes_ranges	= ARRAY_SIZE(axp806_writeable_ranges),
147 };
148 
149 static const struct regmap_access_table axp806_volatile_table = {
150 	.yes_ranges	= axp806_volatile_ranges,
151 	.n_yes_ranges	= ARRAY_SIZE(axp806_volatile_ranges),
152 };
153 
154 static struct resource axp152_pek_resources[] = {
155 	DEFINE_RES_IRQ_NAMED(AXP152_IRQ_PEK_RIS_EDGE, "PEK_DBR"),
156 	DEFINE_RES_IRQ_NAMED(AXP152_IRQ_PEK_FAL_EDGE, "PEK_DBF"),
157 };
158 
159 static struct resource axp20x_ac_power_supply_resources[] = {
160 	DEFINE_RES_IRQ_NAMED(AXP20X_IRQ_ACIN_PLUGIN, "ACIN_PLUGIN"),
161 	DEFINE_RES_IRQ_NAMED(AXP20X_IRQ_ACIN_REMOVAL, "ACIN_REMOVAL"),
162 	DEFINE_RES_IRQ_NAMED(AXP20X_IRQ_ACIN_OVER_V, "ACIN_OVER_V"),
163 };
164 
165 static struct resource axp20x_pek_resources[] = {
166 	{
167 		.name	= "PEK_DBR",
168 		.start	= AXP20X_IRQ_PEK_RIS_EDGE,
169 		.end	= AXP20X_IRQ_PEK_RIS_EDGE,
170 		.flags	= IORESOURCE_IRQ,
171 	}, {
172 		.name	= "PEK_DBF",
173 		.start	= AXP20X_IRQ_PEK_FAL_EDGE,
174 		.end	= AXP20X_IRQ_PEK_FAL_EDGE,
175 		.flags	= IORESOURCE_IRQ,
176 	},
177 };
178 
179 static struct resource axp20x_usb_power_supply_resources[] = {
180 	DEFINE_RES_IRQ_NAMED(AXP20X_IRQ_VBUS_PLUGIN, "VBUS_PLUGIN"),
181 	DEFINE_RES_IRQ_NAMED(AXP20X_IRQ_VBUS_REMOVAL, "VBUS_REMOVAL"),
182 	DEFINE_RES_IRQ_NAMED(AXP20X_IRQ_VBUS_VALID, "VBUS_VALID"),
183 	DEFINE_RES_IRQ_NAMED(AXP20X_IRQ_VBUS_NOT_VALID, "VBUS_NOT_VALID"),
184 };
185 
186 static struct resource axp22x_usb_power_supply_resources[] = {
187 	DEFINE_RES_IRQ_NAMED(AXP22X_IRQ_VBUS_PLUGIN, "VBUS_PLUGIN"),
188 	DEFINE_RES_IRQ_NAMED(AXP22X_IRQ_VBUS_REMOVAL, "VBUS_REMOVAL"),
189 };
190 
191 static struct resource axp22x_pek_resources[] = {
192 	{
193 		.name   = "PEK_DBR",
194 		.start  = AXP22X_IRQ_PEK_RIS_EDGE,
195 		.end    = AXP22X_IRQ_PEK_RIS_EDGE,
196 		.flags  = IORESOURCE_IRQ,
197 	}, {
198 		.name   = "PEK_DBF",
199 		.start  = AXP22X_IRQ_PEK_FAL_EDGE,
200 		.end    = AXP22X_IRQ_PEK_FAL_EDGE,
201 		.flags  = IORESOURCE_IRQ,
202 	},
203 };
204 
205 static struct resource axp288_power_button_resources[] = {
206 	{
207 		.name	= "PEK_DBR",
208 		.start	= AXP288_IRQ_POKN,
209 		.end	= AXP288_IRQ_POKN,
210 		.flags	= IORESOURCE_IRQ,
211 	},
212 	{
213 		.name	= "PEK_DBF",
214 		.start	= AXP288_IRQ_POKP,
215 		.end	= AXP288_IRQ_POKP,
216 		.flags	= IORESOURCE_IRQ,
217 	},
218 };
219 
220 static struct resource axp288_fuel_gauge_resources[] = {
221 	{
222 		.start = AXP288_IRQ_QWBTU,
223 		.end   = AXP288_IRQ_QWBTU,
224 		.flags = IORESOURCE_IRQ,
225 	},
226 	{
227 		.start = AXP288_IRQ_WBTU,
228 		.end   = AXP288_IRQ_WBTU,
229 		.flags = IORESOURCE_IRQ,
230 	},
231 	{
232 		.start = AXP288_IRQ_QWBTO,
233 		.end   = AXP288_IRQ_QWBTO,
234 		.flags = IORESOURCE_IRQ,
235 	},
236 	{
237 		.start = AXP288_IRQ_WBTO,
238 		.end   = AXP288_IRQ_WBTO,
239 		.flags = IORESOURCE_IRQ,
240 	},
241 	{
242 		.start = AXP288_IRQ_WL2,
243 		.end   = AXP288_IRQ_WL2,
244 		.flags = IORESOURCE_IRQ,
245 	},
246 	{
247 		.start = AXP288_IRQ_WL1,
248 		.end   = AXP288_IRQ_WL1,
249 		.flags = IORESOURCE_IRQ,
250 	},
251 };
252 
253 static struct resource axp809_pek_resources[] = {
254 	{
255 		.name   = "PEK_DBR",
256 		.start  = AXP809_IRQ_PEK_RIS_EDGE,
257 		.end    = AXP809_IRQ_PEK_RIS_EDGE,
258 		.flags  = IORESOURCE_IRQ,
259 	}, {
260 		.name   = "PEK_DBF",
261 		.start  = AXP809_IRQ_PEK_FAL_EDGE,
262 		.end    = AXP809_IRQ_PEK_FAL_EDGE,
263 		.flags  = IORESOURCE_IRQ,
264 	},
265 };
266 
267 static const struct regmap_config axp152_regmap_config = {
268 	.reg_bits	= 8,
269 	.val_bits	= 8,
270 	.wr_table	= &axp152_writeable_table,
271 	.volatile_table	= &axp152_volatile_table,
272 	.max_register	= AXP152_PWM1_DUTY_CYCLE,
273 	.cache_type	= REGCACHE_RBTREE,
274 };
275 
276 static const struct regmap_config axp20x_regmap_config = {
277 	.reg_bits	= 8,
278 	.val_bits	= 8,
279 	.wr_table	= &axp20x_writeable_table,
280 	.volatile_table	= &axp20x_volatile_table,
281 	.max_register	= AXP20X_OCV(AXP20X_OCV_MAX),
282 	.cache_type	= REGCACHE_RBTREE,
283 };
284 
285 static const struct regmap_config axp22x_regmap_config = {
286 	.reg_bits	= 8,
287 	.val_bits	= 8,
288 	.wr_table	= &axp22x_writeable_table,
289 	.volatile_table	= &axp22x_volatile_table,
290 	.max_register	= AXP22X_BATLOW_THRES1,
291 	.cache_type	= REGCACHE_RBTREE,
292 };
293 
294 static const struct regmap_config axp288_regmap_config = {
295 	.reg_bits	= 8,
296 	.val_bits	= 8,
297 	.wr_table	= &axp288_writeable_table,
298 	.volatile_table	= &axp288_volatile_table,
299 	.max_register	= AXP288_FG_TUNE5,
300 	.cache_type	= REGCACHE_RBTREE,
301 };
302 
303 static const struct regmap_config axp806_regmap_config = {
304 	.reg_bits	= 8,
305 	.val_bits	= 8,
306 	.wr_table	= &axp806_writeable_table,
307 	.volatile_table	= &axp806_volatile_table,
308 	.max_register	= AXP806_VREF_TEMP_WARN_L,
309 	.cache_type	= REGCACHE_RBTREE,
310 };
311 
312 #define INIT_REGMAP_IRQ(_variant, _irq, _off, _mask)			\
313 	[_variant##_IRQ_##_irq] = { .reg_offset = (_off), .mask = BIT(_mask) }
314 
315 static const struct regmap_irq axp152_regmap_irqs[] = {
316 	INIT_REGMAP_IRQ(AXP152, LDO0IN_CONNECT,		0, 6),
317 	INIT_REGMAP_IRQ(AXP152, LDO0IN_REMOVAL,		0, 5),
318 	INIT_REGMAP_IRQ(AXP152, ALDO0IN_CONNECT,	0, 3),
319 	INIT_REGMAP_IRQ(AXP152, ALDO0IN_REMOVAL,	0, 2),
320 	INIT_REGMAP_IRQ(AXP152, DCDC1_V_LOW,		1, 5),
321 	INIT_REGMAP_IRQ(AXP152, DCDC2_V_LOW,		1, 4),
322 	INIT_REGMAP_IRQ(AXP152, DCDC3_V_LOW,		1, 3),
323 	INIT_REGMAP_IRQ(AXP152, DCDC4_V_LOW,		1, 2),
324 	INIT_REGMAP_IRQ(AXP152, PEK_SHORT,		1, 1),
325 	INIT_REGMAP_IRQ(AXP152, PEK_LONG,		1, 0),
326 	INIT_REGMAP_IRQ(AXP152, TIMER,			2, 7),
327 	INIT_REGMAP_IRQ(AXP152, PEK_RIS_EDGE,		2, 6),
328 	INIT_REGMAP_IRQ(AXP152, PEK_FAL_EDGE,		2, 5),
329 	INIT_REGMAP_IRQ(AXP152, GPIO3_INPUT,		2, 3),
330 	INIT_REGMAP_IRQ(AXP152, GPIO2_INPUT,		2, 2),
331 	INIT_REGMAP_IRQ(AXP152, GPIO1_INPUT,		2, 1),
332 	INIT_REGMAP_IRQ(AXP152, GPIO0_INPUT,		2, 0),
333 };
334 
335 static const struct regmap_irq axp20x_regmap_irqs[] = {
336 	INIT_REGMAP_IRQ(AXP20X, ACIN_OVER_V,		0, 7),
337 	INIT_REGMAP_IRQ(AXP20X, ACIN_PLUGIN,		0, 6),
338 	INIT_REGMAP_IRQ(AXP20X, ACIN_REMOVAL,	        0, 5),
339 	INIT_REGMAP_IRQ(AXP20X, VBUS_OVER_V,		0, 4),
340 	INIT_REGMAP_IRQ(AXP20X, VBUS_PLUGIN,		0, 3),
341 	INIT_REGMAP_IRQ(AXP20X, VBUS_REMOVAL,	        0, 2),
342 	INIT_REGMAP_IRQ(AXP20X, VBUS_V_LOW,		0, 1),
343 	INIT_REGMAP_IRQ(AXP20X, BATT_PLUGIN,		1, 7),
344 	INIT_REGMAP_IRQ(AXP20X, BATT_REMOVAL,	        1, 6),
345 	INIT_REGMAP_IRQ(AXP20X, BATT_ENT_ACT_MODE,	1, 5),
346 	INIT_REGMAP_IRQ(AXP20X, BATT_EXIT_ACT_MODE,	1, 4),
347 	INIT_REGMAP_IRQ(AXP20X, CHARG,		        1, 3),
348 	INIT_REGMAP_IRQ(AXP20X, CHARG_DONE,		1, 2),
349 	INIT_REGMAP_IRQ(AXP20X, BATT_TEMP_HIGH,	        1, 1),
350 	INIT_REGMAP_IRQ(AXP20X, BATT_TEMP_LOW,	        1, 0),
351 	INIT_REGMAP_IRQ(AXP20X, DIE_TEMP_HIGH,	        2, 7),
352 	INIT_REGMAP_IRQ(AXP20X, CHARG_I_LOW,		2, 6),
353 	INIT_REGMAP_IRQ(AXP20X, DCDC1_V_LONG,	        2, 5),
354 	INIT_REGMAP_IRQ(AXP20X, DCDC2_V_LONG,	        2, 4),
355 	INIT_REGMAP_IRQ(AXP20X, DCDC3_V_LONG,	        2, 3),
356 	INIT_REGMAP_IRQ(AXP20X, PEK_SHORT,		2, 1),
357 	INIT_REGMAP_IRQ(AXP20X, PEK_LONG,		2, 0),
358 	INIT_REGMAP_IRQ(AXP20X, N_OE_PWR_ON,		3, 7),
359 	INIT_REGMAP_IRQ(AXP20X, N_OE_PWR_OFF,	        3, 6),
360 	INIT_REGMAP_IRQ(AXP20X, VBUS_VALID,		3, 5),
361 	INIT_REGMAP_IRQ(AXP20X, VBUS_NOT_VALID,	        3, 4),
362 	INIT_REGMAP_IRQ(AXP20X, VBUS_SESS_VALID,	3, 3),
363 	INIT_REGMAP_IRQ(AXP20X, VBUS_SESS_END,	        3, 2),
364 	INIT_REGMAP_IRQ(AXP20X, LOW_PWR_LVL1,	        3, 1),
365 	INIT_REGMAP_IRQ(AXP20X, LOW_PWR_LVL2,	        3, 0),
366 	INIT_REGMAP_IRQ(AXP20X, TIMER,		        4, 7),
367 	INIT_REGMAP_IRQ(AXP20X, PEK_RIS_EDGE,	        4, 6),
368 	INIT_REGMAP_IRQ(AXP20X, PEK_FAL_EDGE,	        4, 5),
369 	INIT_REGMAP_IRQ(AXP20X, GPIO3_INPUT,		4, 3),
370 	INIT_REGMAP_IRQ(AXP20X, GPIO2_INPUT,		4, 2),
371 	INIT_REGMAP_IRQ(AXP20X, GPIO1_INPUT,		4, 1),
372 	INIT_REGMAP_IRQ(AXP20X, GPIO0_INPUT,		4, 0),
373 };
374 
375 static const struct regmap_irq axp22x_regmap_irqs[] = {
376 	INIT_REGMAP_IRQ(AXP22X, ACIN_OVER_V,		0, 7),
377 	INIT_REGMAP_IRQ(AXP22X, ACIN_PLUGIN,		0, 6),
378 	INIT_REGMAP_IRQ(AXP22X, ACIN_REMOVAL,	        0, 5),
379 	INIT_REGMAP_IRQ(AXP22X, VBUS_OVER_V,		0, 4),
380 	INIT_REGMAP_IRQ(AXP22X, VBUS_PLUGIN,		0, 3),
381 	INIT_REGMAP_IRQ(AXP22X, VBUS_REMOVAL,	        0, 2),
382 	INIT_REGMAP_IRQ(AXP22X, VBUS_V_LOW,		0, 1),
383 	INIT_REGMAP_IRQ(AXP22X, BATT_PLUGIN,		1, 7),
384 	INIT_REGMAP_IRQ(AXP22X, BATT_REMOVAL,	        1, 6),
385 	INIT_REGMAP_IRQ(AXP22X, BATT_ENT_ACT_MODE,	1, 5),
386 	INIT_REGMAP_IRQ(AXP22X, BATT_EXIT_ACT_MODE,	1, 4),
387 	INIT_REGMAP_IRQ(AXP22X, CHARG,		        1, 3),
388 	INIT_REGMAP_IRQ(AXP22X, CHARG_DONE,		1, 2),
389 	INIT_REGMAP_IRQ(AXP22X, BATT_TEMP_HIGH,	        1, 1),
390 	INIT_REGMAP_IRQ(AXP22X, BATT_TEMP_LOW,	        1, 0),
391 	INIT_REGMAP_IRQ(AXP22X, DIE_TEMP_HIGH,	        2, 7),
392 	INIT_REGMAP_IRQ(AXP22X, PEK_SHORT,		2, 1),
393 	INIT_REGMAP_IRQ(AXP22X, PEK_LONG,		2, 0),
394 	INIT_REGMAP_IRQ(AXP22X, LOW_PWR_LVL1,	        3, 1),
395 	INIT_REGMAP_IRQ(AXP22X, LOW_PWR_LVL2,	        3, 0),
396 	INIT_REGMAP_IRQ(AXP22X, TIMER,		        4, 7),
397 	INIT_REGMAP_IRQ(AXP22X, PEK_RIS_EDGE,	        4, 6),
398 	INIT_REGMAP_IRQ(AXP22X, PEK_FAL_EDGE,	        4, 5),
399 	INIT_REGMAP_IRQ(AXP22X, GPIO1_INPUT,		4, 1),
400 	INIT_REGMAP_IRQ(AXP22X, GPIO0_INPUT,		4, 0),
401 };
402 
403 /* some IRQs are compatible with axp20x models */
404 static const struct regmap_irq axp288_regmap_irqs[] = {
405 	INIT_REGMAP_IRQ(AXP288, VBUS_FALL,              0, 2),
406 	INIT_REGMAP_IRQ(AXP288, VBUS_RISE,              0, 3),
407 	INIT_REGMAP_IRQ(AXP288, OV,                     0, 4),
408 
409 	INIT_REGMAP_IRQ(AXP288, DONE,                   1, 2),
410 	INIT_REGMAP_IRQ(AXP288, CHARGING,               1, 3),
411 	INIT_REGMAP_IRQ(AXP288, SAFE_QUIT,              1, 4),
412 	INIT_REGMAP_IRQ(AXP288, SAFE_ENTER,             1, 5),
413 	INIT_REGMAP_IRQ(AXP288, ABSENT,                 1, 6),
414 	INIT_REGMAP_IRQ(AXP288, APPEND,                 1, 7),
415 
416 	INIT_REGMAP_IRQ(AXP288, QWBTU,                  2, 0),
417 	INIT_REGMAP_IRQ(AXP288, WBTU,                   2, 1),
418 	INIT_REGMAP_IRQ(AXP288, QWBTO,                  2, 2),
419 	INIT_REGMAP_IRQ(AXP288, WBTO,                   2, 3),
420 	INIT_REGMAP_IRQ(AXP288, QCBTU,                  2, 4),
421 	INIT_REGMAP_IRQ(AXP288, CBTU,                   2, 5),
422 	INIT_REGMAP_IRQ(AXP288, QCBTO,                  2, 6),
423 	INIT_REGMAP_IRQ(AXP288, CBTO,                   2, 7),
424 
425 	INIT_REGMAP_IRQ(AXP288, WL2,                    3, 0),
426 	INIT_REGMAP_IRQ(AXP288, WL1,                    3, 1),
427 	INIT_REGMAP_IRQ(AXP288, GPADC,                  3, 2),
428 	INIT_REGMAP_IRQ(AXP288, OT,                     3, 7),
429 
430 	INIT_REGMAP_IRQ(AXP288, GPIO0,                  4, 0),
431 	INIT_REGMAP_IRQ(AXP288, GPIO1,                  4, 1),
432 	INIT_REGMAP_IRQ(AXP288, POKO,                   4, 2),
433 	INIT_REGMAP_IRQ(AXP288, POKL,                   4, 3),
434 	INIT_REGMAP_IRQ(AXP288, POKS,                   4, 4),
435 	INIT_REGMAP_IRQ(AXP288, POKN,                   4, 5),
436 	INIT_REGMAP_IRQ(AXP288, POKP,                   4, 6),
437 	INIT_REGMAP_IRQ(AXP288, TIMER,                  4, 7),
438 
439 	INIT_REGMAP_IRQ(AXP288, MV_CHNG,                5, 0),
440 	INIT_REGMAP_IRQ(AXP288, BC_USB_CHNG,            5, 1),
441 };
442 
443 static const struct regmap_irq axp806_regmap_irqs[] = {
444 	INIT_REGMAP_IRQ(AXP806, DIE_TEMP_HIGH_LV1,	0, 0),
445 	INIT_REGMAP_IRQ(AXP806, DIE_TEMP_HIGH_LV2,	0, 1),
446 	INIT_REGMAP_IRQ(AXP806, DCDCA_V_LOW,		0, 3),
447 	INIT_REGMAP_IRQ(AXP806, DCDCB_V_LOW,		0, 4),
448 	INIT_REGMAP_IRQ(AXP806, DCDCC_V_LOW,		0, 5),
449 	INIT_REGMAP_IRQ(AXP806, DCDCD_V_LOW,		0, 6),
450 	INIT_REGMAP_IRQ(AXP806, DCDCE_V_LOW,		0, 7),
451 	INIT_REGMAP_IRQ(AXP806, PWROK_LONG,		1, 0),
452 	INIT_REGMAP_IRQ(AXP806, PWROK_SHORT,		1, 1),
453 	INIT_REGMAP_IRQ(AXP806, WAKEUP,			1, 4),
454 	INIT_REGMAP_IRQ(AXP806, PWROK_FALL,		1, 5),
455 	INIT_REGMAP_IRQ(AXP806, PWROK_RISE,		1, 6),
456 };
457 
458 static const struct regmap_irq axp809_regmap_irqs[] = {
459 	INIT_REGMAP_IRQ(AXP809, ACIN_OVER_V,		0, 7),
460 	INIT_REGMAP_IRQ(AXP809, ACIN_PLUGIN,		0, 6),
461 	INIT_REGMAP_IRQ(AXP809, ACIN_REMOVAL,	        0, 5),
462 	INIT_REGMAP_IRQ(AXP809, VBUS_OVER_V,		0, 4),
463 	INIT_REGMAP_IRQ(AXP809, VBUS_PLUGIN,		0, 3),
464 	INIT_REGMAP_IRQ(AXP809, VBUS_REMOVAL,	        0, 2),
465 	INIT_REGMAP_IRQ(AXP809, VBUS_V_LOW,		0, 1),
466 	INIT_REGMAP_IRQ(AXP809, BATT_PLUGIN,		1, 7),
467 	INIT_REGMAP_IRQ(AXP809, BATT_REMOVAL,	        1, 6),
468 	INIT_REGMAP_IRQ(AXP809, BATT_ENT_ACT_MODE,	1, 5),
469 	INIT_REGMAP_IRQ(AXP809, BATT_EXIT_ACT_MODE,	1, 4),
470 	INIT_REGMAP_IRQ(AXP809, CHARG,		        1, 3),
471 	INIT_REGMAP_IRQ(AXP809, CHARG_DONE,		1, 2),
472 	INIT_REGMAP_IRQ(AXP809, BATT_CHG_TEMP_HIGH,	2, 7),
473 	INIT_REGMAP_IRQ(AXP809, BATT_CHG_TEMP_HIGH_END,	2, 6),
474 	INIT_REGMAP_IRQ(AXP809, BATT_CHG_TEMP_LOW,	2, 5),
475 	INIT_REGMAP_IRQ(AXP809, BATT_CHG_TEMP_LOW_END,	2, 4),
476 	INIT_REGMAP_IRQ(AXP809, BATT_ACT_TEMP_HIGH,	2, 3),
477 	INIT_REGMAP_IRQ(AXP809, BATT_ACT_TEMP_HIGH_END,	2, 2),
478 	INIT_REGMAP_IRQ(AXP809, BATT_ACT_TEMP_LOW,	2, 1),
479 	INIT_REGMAP_IRQ(AXP809, BATT_ACT_TEMP_LOW_END,	2, 0),
480 	INIT_REGMAP_IRQ(AXP809, DIE_TEMP_HIGH,	        3, 7),
481 	INIT_REGMAP_IRQ(AXP809, LOW_PWR_LVL1,	        3, 1),
482 	INIT_REGMAP_IRQ(AXP809, LOW_PWR_LVL2,	        3, 0),
483 	INIT_REGMAP_IRQ(AXP809, TIMER,		        4, 7),
484 	INIT_REGMAP_IRQ(AXP809, PEK_RIS_EDGE,	        4, 6),
485 	INIT_REGMAP_IRQ(AXP809, PEK_FAL_EDGE,	        4, 5),
486 	INIT_REGMAP_IRQ(AXP809, PEK_SHORT,		4, 4),
487 	INIT_REGMAP_IRQ(AXP809, PEK_LONG,		4, 3),
488 	INIT_REGMAP_IRQ(AXP809, PEK_OVER_OFF,		4, 2),
489 	INIT_REGMAP_IRQ(AXP809, GPIO1_INPUT,		4, 1),
490 	INIT_REGMAP_IRQ(AXP809, GPIO0_INPUT,		4, 0),
491 };
492 
493 static const struct regmap_irq_chip axp152_regmap_irq_chip = {
494 	.name			= "axp152_irq_chip",
495 	.status_base		= AXP152_IRQ1_STATE,
496 	.ack_base		= AXP152_IRQ1_STATE,
497 	.mask_base		= AXP152_IRQ1_EN,
498 	.mask_invert		= true,
499 	.init_ack_masked	= true,
500 	.irqs			= axp152_regmap_irqs,
501 	.num_irqs		= ARRAY_SIZE(axp152_regmap_irqs),
502 	.num_regs		= 3,
503 };
504 
505 static const struct regmap_irq_chip axp20x_regmap_irq_chip = {
506 	.name			= "axp20x_irq_chip",
507 	.status_base		= AXP20X_IRQ1_STATE,
508 	.ack_base		= AXP20X_IRQ1_STATE,
509 	.mask_base		= AXP20X_IRQ1_EN,
510 	.mask_invert		= true,
511 	.init_ack_masked	= true,
512 	.irqs			= axp20x_regmap_irqs,
513 	.num_irqs		= ARRAY_SIZE(axp20x_regmap_irqs),
514 	.num_regs		= 5,
515 
516 };
517 
518 static const struct regmap_irq_chip axp22x_regmap_irq_chip = {
519 	.name			= "axp22x_irq_chip",
520 	.status_base		= AXP20X_IRQ1_STATE,
521 	.ack_base		= AXP20X_IRQ1_STATE,
522 	.mask_base		= AXP20X_IRQ1_EN,
523 	.mask_invert		= true,
524 	.init_ack_masked	= true,
525 	.irqs			= axp22x_regmap_irqs,
526 	.num_irqs		= ARRAY_SIZE(axp22x_regmap_irqs),
527 	.num_regs		= 5,
528 };
529 
530 static const struct regmap_irq_chip axp288_regmap_irq_chip = {
531 	.name			= "axp288_irq_chip",
532 	.status_base		= AXP20X_IRQ1_STATE,
533 	.ack_base		= AXP20X_IRQ1_STATE,
534 	.mask_base		= AXP20X_IRQ1_EN,
535 	.mask_invert		= true,
536 	.init_ack_masked	= true,
537 	.irqs			= axp288_regmap_irqs,
538 	.num_irqs		= ARRAY_SIZE(axp288_regmap_irqs),
539 	.num_regs		= 6,
540 
541 };
542 
543 static const struct regmap_irq_chip axp806_regmap_irq_chip = {
544 	.name			= "axp806",
545 	.status_base		= AXP20X_IRQ1_STATE,
546 	.ack_base		= AXP20X_IRQ1_STATE,
547 	.mask_base		= AXP20X_IRQ1_EN,
548 	.mask_invert		= true,
549 	.init_ack_masked	= true,
550 	.irqs			= axp806_regmap_irqs,
551 	.num_irqs		= ARRAY_SIZE(axp806_regmap_irqs),
552 	.num_regs		= 2,
553 };
554 
555 static const struct regmap_irq_chip axp809_regmap_irq_chip = {
556 	.name			= "axp809",
557 	.status_base		= AXP20X_IRQ1_STATE,
558 	.ack_base		= AXP20X_IRQ1_STATE,
559 	.mask_base		= AXP20X_IRQ1_EN,
560 	.mask_invert		= true,
561 	.init_ack_masked	= true,
562 	.irqs			= axp809_regmap_irqs,
563 	.num_irqs		= ARRAY_SIZE(axp809_regmap_irqs),
564 	.num_regs		= 5,
565 };
566 
567 static struct mfd_cell axp20x_cells[] = {
568 	{
569 		.name		= "axp20x-gpio",
570 		.of_compatible	= "x-powers,axp209-gpio",
571 	}, {
572 		.name		= "axp20x-pek",
573 		.num_resources	= ARRAY_SIZE(axp20x_pek_resources),
574 		.resources	= axp20x_pek_resources,
575 	}, {
576 		.name		= "axp20x-regulator",
577 	}, {
578 		.name		= "axp20x-ac-power-supply",
579 		.of_compatible	= "x-powers,axp202-ac-power-supply",
580 		.num_resources	= ARRAY_SIZE(axp20x_ac_power_supply_resources),
581 		.resources	= axp20x_ac_power_supply_resources,
582 	}, {
583 		.name		= "axp20x-usb-power-supply",
584 		.of_compatible	= "x-powers,axp202-usb-power-supply",
585 		.num_resources	= ARRAY_SIZE(axp20x_usb_power_supply_resources),
586 		.resources	= axp20x_usb_power_supply_resources,
587 	},
588 };
589 
590 static struct mfd_cell axp22x_cells[] = {
591 	{
592 		.name			= "axp20x-pek",
593 		.num_resources		= ARRAY_SIZE(axp22x_pek_resources),
594 		.resources		= axp22x_pek_resources,
595 	}, {
596 		.name			= "axp20x-regulator",
597 	}, {
598 		.name		= "axp20x-usb-power-supply",
599 		.of_compatible	= "x-powers,axp221-usb-power-supply",
600 		.num_resources	= ARRAY_SIZE(axp22x_usb_power_supply_resources),
601 		.resources	= axp22x_usb_power_supply_resources,
602 	},
603 };
604 
605 static struct mfd_cell axp152_cells[] = {
606 	{
607 		.name			= "axp20x-pek",
608 		.num_resources		= ARRAY_SIZE(axp152_pek_resources),
609 		.resources		= axp152_pek_resources,
610 	},
611 };
612 
613 static struct resource axp288_adc_resources[] = {
614 	{
615 		.name  = "GPADC",
616 		.start = AXP288_IRQ_GPADC,
617 		.end   = AXP288_IRQ_GPADC,
618 		.flags = IORESOURCE_IRQ,
619 	},
620 };
621 
622 static struct resource axp288_extcon_resources[] = {
623 	{
624 		.start = AXP288_IRQ_VBUS_FALL,
625 		.end   = AXP288_IRQ_VBUS_FALL,
626 		.flags = IORESOURCE_IRQ,
627 	},
628 	{
629 		.start = AXP288_IRQ_VBUS_RISE,
630 		.end   = AXP288_IRQ_VBUS_RISE,
631 		.flags = IORESOURCE_IRQ,
632 	},
633 	{
634 		.start = AXP288_IRQ_MV_CHNG,
635 		.end   = AXP288_IRQ_MV_CHNG,
636 		.flags = IORESOURCE_IRQ,
637 	},
638 	{
639 		.start = AXP288_IRQ_BC_USB_CHNG,
640 		.end   = AXP288_IRQ_BC_USB_CHNG,
641 		.flags = IORESOURCE_IRQ,
642 	},
643 };
644 
645 static struct resource axp288_charger_resources[] = {
646 	{
647 		.start = AXP288_IRQ_OV,
648 		.end   = AXP288_IRQ_OV,
649 		.flags = IORESOURCE_IRQ,
650 	},
651 	{
652 		.start = AXP288_IRQ_DONE,
653 		.end   = AXP288_IRQ_DONE,
654 		.flags = IORESOURCE_IRQ,
655 	},
656 	{
657 		.start = AXP288_IRQ_CHARGING,
658 		.end   = AXP288_IRQ_CHARGING,
659 		.flags = IORESOURCE_IRQ,
660 	},
661 	{
662 		.start = AXP288_IRQ_SAFE_QUIT,
663 		.end   = AXP288_IRQ_SAFE_QUIT,
664 		.flags = IORESOURCE_IRQ,
665 	},
666 	{
667 		.start = AXP288_IRQ_SAFE_ENTER,
668 		.end   = AXP288_IRQ_SAFE_ENTER,
669 		.flags = IORESOURCE_IRQ,
670 	},
671 	{
672 		.start = AXP288_IRQ_QCBTU,
673 		.end   = AXP288_IRQ_QCBTU,
674 		.flags = IORESOURCE_IRQ,
675 	},
676 	{
677 		.start = AXP288_IRQ_CBTU,
678 		.end   = AXP288_IRQ_CBTU,
679 		.flags = IORESOURCE_IRQ,
680 	},
681 	{
682 		.start = AXP288_IRQ_QCBTO,
683 		.end   = AXP288_IRQ_QCBTO,
684 		.flags = IORESOURCE_IRQ,
685 	},
686 	{
687 		.start = AXP288_IRQ_CBTO,
688 		.end   = AXP288_IRQ_CBTO,
689 		.flags = IORESOURCE_IRQ,
690 	},
691 };
692 
693 static struct mfd_cell axp288_cells[] = {
694 	{
695 		.name = "axp288_adc",
696 		.num_resources = ARRAY_SIZE(axp288_adc_resources),
697 		.resources = axp288_adc_resources,
698 	},
699 	{
700 		.name = "axp288_extcon",
701 		.num_resources = ARRAY_SIZE(axp288_extcon_resources),
702 		.resources = axp288_extcon_resources,
703 	},
704 	{
705 		.name = "axp288_charger",
706 		.num_resources = ARRAY_SIZE(axp288_charger_resources),
707 		.resources = axp288_charger_resources,
708 	},
709 	{
710 		.name = "axp288_fuel_gauge",
711 		.num_resources = ARRAY_SIZE(axp288_fuel_gauge_resources),
712 		.resources = axp288_fuel_gauge_resources,
713 	},
714 	{
715 		.name = "axp20x-pek",
716 		.num_resources = ARRAY_SIZE(axp288_power_button_resources),
717 		.resources = axp288_power_button_resources,
718 	},
719 	{
720 		.name = "axp288_pmic_acpi",
721 	},
722 };
723 
724 static struct mfd_cell axp806_cells[] = {
725 	{
726 		.id			= 2,
727 		.name			= "axp20x-regulator",
728 	},
729 };
730 
731 static struct mfd_cell axp809_cells[] = {
732 	{
733 		.name			= "axp20x-pek",
734 		.num_resources		= ARRAY_SIZE(axp809_pek_resources),
735 		.resources		= axp809_pek_resources,
736 	}, {
737 		.id			= 1,
738 		.name			= "axp20x-regulator",
739 	},
740 };
741 
742 static struct axp20x_dev *axp20x_pm_power_off;
743 static void axp20x_power_off(void)
744 {
745 	if (axp20x_pm_power_off->variant == AXP288_ID)
746 		return;
747 
748 	regmap_write(axp20x_pm_power_off->regmap, AXP20X_OFF_CTRL,
749 		     AXP20X_OFF);
750 
751 	/* Give capacitors etc. time to drain to avoid kernel panic msg. */
752 	msleep(500);
753 }
754 
755 int axp20x_match_device(struct axp20x_dev *axp20x)
756 {
757 	struct device *dev = axp20x->dev;
758 	const struct acpi_device_id *acpi_id;
759 	const struct of_device_id *of_id;
760 
761 	if (dev->of_node) {
762 		of_id = of_match_device(dev->driver->of_match_table, dev);
763 		if (!of_id) {
764 			dev_err(dev, "Unable to match OF ID\n");
765 			return -ENODEV;
766 		}
767 		axp20x->variant = (long)of_id->data;
768 	} else {
769 		acpi_id = acpi_match_device(dev->driver->acpi_match_table, dev);
770 		if (!acpi_id || !acpi_id->driver_data) {
771 			dev_err(dev, "Unable to match ACPI ID and data\n");
772 			return -ENODEV;
773 		}
774 		axp20x->variant = (long)acpi_id->driver_data;
775 	}
776 
777 	switch (axp20x->variant) {
778 	case AXP152_ID:
779 		axp20x->nr_cells = ARRAY_SIZE(axp152_cells);
780 		axp20x->cells = axp152_cells;
781 		axp20x->regmap_cfg = &axp152_regmap_config;
782 		axp20x->regmap_irq_chip = &axp152_regmap_irq_chip;
783 		break;
784 	case AXP202_ID:
785 	case AXP209_ID:
786 		axp20x->nr_cells = ARRAY_SIZE(axp20x_cells);
787 		axp20x->cells = axp20x_cells;
788 		axp20x->regmap_cfg = &axp20x_regmap_config;
789 		axp20x->regmap_irq_chip = &axp20x_regmap_irq_chip;
790 		break;
791 	case AXP221_ID:
792 	case AXP223_ID:
793 		axp20x->nr_cells = ARRAY_SIZE(axp22x_cells);
794 		axp20x->cells = axp22x_cells;
795 		axp20x->regmap_cfg = &axp22x_regmap_config;
796 		axp20x->regmap_irq_chip = &axp22x_regmap_irq_chip;
797 		break;
798 	case AXP288_ID:
799 		axp20x->cells = axp288_cells;
800 		axp20x->nr_cells = ARRAY_SIZE(axp288_cells);
801 		axp20x->regmap_cfg = &axp288_regmap_config;
802 		axp20x->regmap_irq_chip = &axp288_regmap_irq_chip;
803 		break;
804 	case AXP806_ID:
805 		axp20x->nr_cells = ARRAY_SIZE(axp806_cells);
806 		axp20x->cells = axp806_cells;
807 		axp20x->regmap_cfg = &axp806_regmap_config;
808 		axp20x->regmap_irq_chip = &axp806_regmap_irq_chip;
809 		break;
810 	case AXP809_ID:
811 		axp20x->nr_cells = ARRAY_SIZE(axp809_cells);
812 		axp20x->cells = axp809_cells;
813 		axp20x->regmap_cfg = &axp22x_regmap_config;
814 		axp20x->regmap_irq_chip = &axp809_regmap_irq_chip;
815 		break;
816 	default:
817 		dev_err(dev, "unsupported AXP20X ID %lu\n", axp20x->variant);
818 		return -EINVAL;
819 	}
820 	dev_info(dev, "AXP20x variant %s found\n",
821 		 axp20x_model_names[axp20x->variant]);
822 
823 	return 0;
824 }
825 EXPORT_SYMBOL(axp20x_match_device);
826 
827 int axp20x_device_probe(struct axp20x_dev *axp20x)
828 {
829 	int ret;
830 
831 	ret = regmap_add_irq_chip(axp20x->regmap, axp20x->irq,
832 				  IRQF_ONESHOT | IRQF_SHARED, -1,
833 				  axp20x->regmap_irq_chip,
834 				  &axp20x->regmap_irqc);
835 	if (ret) {
836 		dev_err(axp20x->dev, "failed to add irq chip: %d\n", ret);
837 		return ret;
838 	}
839 
840 	ret = mfd_add_devices(axp20x->dev, -1, axp20x->cells,
841 			      axp20x->nr_cells, NULL, 0, NULL);
842 
843 	if (ret) {
844 		dev_err(axp20x->dev, "failed to add MFD devices: %d\n", ret);
845 		regmap_del_irq_chip(axp20x->irq, axp20x->regmap_irqc);
846 		return ret;
847 	}
848 
849 	if (!pm_power_off) {
850 		axp20x_pm_power_off = axp20x;
851 		pm_power_off = axp20x_power_off;
852 	}
853 
854 	dev_info(axp20x->dev, "AXP20X driver loaded\n");
855 
856 	return 0;
857 }
858 EXPORT_SYMBOL(axp20x_device_probe);
859 
860 int axp20x_device_remove(struct axp20x_dev *axp20x)
861 {
862 	if (axp20x == axp20x_pm_power_off) {
863 		axp20x_pm_power_off = NULL;
864 		pm_power_off = NULL;
865 	}
866 
867 	mfd_remove_devices(axp20x->dev);
868 	regmap_del_irq_chip(axp20x->irq, axp20x->regmap_irqc);
869 
870 	return 0;
871 }
872 EXPORT_SYMBOL(axp20x_device_remove);
873 
874 MODULE_DESCRIPTION("PMIC MFD core driver for AXP20X");
875 MODULE_AUTHOR("Carlo Caione <carlo@caione.org>");
876 MODULE_LICENSE("GPL");
877