xref: /linux/drivers/mfd/sec-irq.c (revision 3f0a50f345f78183f6e9b39c2f45ca5dcaa511ca)
1 // SPDX-License-Identifier: GPL-2.0+
2 //
3 // Copyright (c) 2011-2014 Samsung Electronics Co., Ltd
4 //              http://www.samsung.com
5 
6 #include <linux/device.h>
7 #include <linux/interrupt.h>
8 #include <linux/irq.h>
9 #include <linux/module.h>
10 #include <linux/regmap.h>
11 
12 #include <linux/mfd/samsung/core.h>
13 #include <linux/mfd/samsung/irq.h>
14 #include <linux/mfd/samsung/s2mps11.h>
15 #include <linux/mfd/samsung/s2mps14.h>
16 #include <linux/mfd/samsung/s2mpu02.h>
17 #include <linux/mfd/samsung/s5m8763.h>
18 #include <linux/mfd/samsung/s5m8767.h>
19 
20 static const struct regmap_irq s2mps11_irqs[] = {
21 	[S2MPS11_IRQ_PWRONF] = {
22 		.reg_offset = 0,
23 		.mask = S2MPS11_IRQ_PWRONF_MASK,
24 	},
25 	[S2MPS11_IRQ_PWRONR] = {
26 		.reg_offset = 0,
27 		.mask = S2MPS11_IRQ_PWRONR_MASK,
28 	},
29 	[S2MPS11_IRQ_JIGONBF] = {
30 		.reg_offset = 0,
31 		.mask = S2MPS11_IRQ_JIGONBF_MASK,
32 	},
33 	[S2MPS11_IRQ_JIGONBR] = {
34 		.reg_offset = 0,
35 		.mask = S2MPS11_IRQ_JIGONBR_MASK,
36 	},
37 	[S2MPS11_IRQ_ACOKBF] = {
38 		.reg_offset = 0,
39 		.mask = S2MPS11_IRQ_ACOKBF_MASK,
40 	},
41 	[S2MPS11_IRQ_ACOKBR] = {
42 		.reg_offset = 0,
43 		.mask = S2MPS11_IRQ_ACOKBR_MASK,
44 	},
45 	[S2MPS11_IRQ_PWRON1S] = {
46 		.reg_offset = 0,
47 		.mask = S2MPS11_IRQ_PWRON1S_MASK,
48 	},
49 	[S2MPS11_IRQ_MRB] = {
50 		.reg_offset = 0,
51 		.mask = S2MPS11_IRQ_MRB_MASK,
52 	},
53 	[S2MPS11_IRQ_RTC60S] = {
54 		.reg_offset = 1,
55 		.mask = S2MPS11_IRQ_RTC60S_MASK,
56 	},
57 	[S2MPS11_IRQ_RTCA1] = {
58 		.reg_offset = 1,
59 		.mask = S2MPS11_IRQ_RTCA1_MASK,
60 	},
61 	[S2MPS11_IRQ_RTCA0] = {
62 		.reg_offset = 1,
63 		.mask = S2MPS11_IRQ_RTCA0_MASK,
64 	},
65 	[S2MPS11_IRQ_SMPL] = {
66 		.reg_offset = 1,
67 		.mask = S2MPS11_IRQ_SMPL_MASK,
68 	},
69 	[S2MPS11_IRQ_RTC1S] = {
70 		.reg_offset = 1,
71 		.mask = S2MPS11_IRQ_RTC1S_MASK,
72 	},
73 	[S2MPS11_IRQ_WTSR] = {
74 		.reg_offset = 1,
75 		.mask = S2MPS11_IRQ_WTSR_MASK,
76 	},
77 	[S2MPS11_IRQ_INT120C] = {
78 		.reg_offset = 2,
79 		.mask = S2MPS11_IRQ_INT120C_MASK,
80 	},
81 	[S2MPS11_IRQ_INT140C] = {
82 		.reg_offset = 2,
83 		.mask = S2MPS11_IRQ_INT140C_MASK,
84 	},
85 };
86 
87 static const struct regmap_irq s2mps14_irqs[] = {
88 	[S2MPS14_IRQ_PWRONF] = {
89 		.reg_offset = 0,
90 		.mask = S2MPS11_IRQ_PWRONF_MASK,
91 	},
92 	[S2MPS14_IRQ_PWRONR] = {
93 		.reg_offset = 0,
94 		.mask = S2MPS11_IRQ_PWRONR_MASK,
95 	},
96 	[S2MPS14_IRQ_JIGONBF] = {
97 		.reg_offset = 0,
98 		.mask = S2MPS11_IRQ_JIGONBF_MASK,
99 	},
100 	[S2MPS14_IRQ_JIGONBR] = {
101 		.reg_offset = 0,
102 		.mask = S2MPS11_IRQ_JIGONBR_MASK,
103 	},
104 	[S2MPS14_IRQ_ACOKBF] = {
105 		.reg_offset = 0,
106 		.mask = S2MPS11_IRQ_ACOKBF_MASK,
107 	},
108 	[S2MPS14_IRQ_ACOKBR] = {
109 		.reg_offset = 0,
110 		.mask = S2MPS11_IRQ_ACOKBR_MASK,
111 	},
112 	[S2MPS14_IRQ_PWRON1S] = {
113 		.reg_offset = 0,
114 		.mask = S2MPS11_IRQ_PWRON1S_MASK,
115 	},
116 	[S2MPS14_IRQ_MRB] = {
117 		.reg_offset = 0,
118 		.mask = S2MPS11_IRQ_MRB_MASK,
119 	},
120 	[S2MPS14_IRQ_RTC60S] = {
121 		.reg_offset = 1,
122 		.mask = S2MPS11_IRQ_RTC60S_MASK,
123 	},
124 	[S2MPS14_IRQ_RTCA1] = {
125 		.reg_offset = 1,
126 		.mask = S2MPS11_IRQ_RTCA1_MASK,
127 	},
128 	[S2MPS14_IRQ_RTCA0] = {
129 		.reg_offset = 1,
130 		.mask = S2MPS11_IRQ_RTCA0_MASK,
131 	},
132 	[S2MPS14_IRQ_SMPL] = {
133 		.reg_offset = 1,
134 		.mask = S2MPS11_IRQ_SMPL_MASK,
135 	},
136 	[S2MPS14_IRQ_RTC1S] = {
137 		.reg_offset = 1,
138 		.mask = S2MPS11_IRQ_RTC1S_MASK,
139 	},
140 	[S2MPS14_IRQ_WTSR] = {
141 		.reg_offset = 1,
142 		.mask = S2MPS11_IRQ_WTSR_MASK,
143 	},
144 	[S2MPS14_IRQ_INT120C] = {
145 		.reg_offset = 2,
146 		.mask = S2MPS11_IRQ_INT120C_MASK,
147 	},
148 	[S2MPS14_IRQ_INT140C] = {
149 		.reg_offset = 2,
150 		.mask = S2MPS11_IRQ_INT140C_MASK,
151 	},
152 	[S2MPS14_IRQ_TSD] = {
153 		.reg_offset = 2,
154 		.mask = S2MPS14_IRQ_TSD_MASK,
155 	},
156 };
157 
158 static const struct regmap_irq s2mpu02_irqs[] = {
159 	[S2MPU02_IRQ_PWRONF] = {
160 		.reg_offset = 0,
161 		.mask = S2MPS11_IRQ_PWRONF_MASK,
162 	},
163 	[S2MPU02_IRQ_PWRONR] = {
164 		.reg_offset = 0,
165 		.mask = S2MPS11_IRQ_PWRONR_MASK,
166 	},
167 	[S2MPU02_IRQ_JIGONBF] = {
168 		.reg_offset = 0,
169 		.mask = S2MPS11_IRQ_JIGONBF_MASK,
170 	},
171 	[S2MPU02_IRQ_JIGONBR] = {
172 		.reg_offset = 0,
173 		.mask = S2MPS11_IRQ_JIGONBR_MASK,
174 	},
175 	[S2MPU02_IRQ_ACOKBF] = {
176 		.reg_offset = 0,
177 		.mask = S2MPS11_IRQ_ACOKBF_MASK,
178 	},
179 	[S2MPU02_IRQ_ACOKBR] = {
180 		.reg_offset = 0,
181 		.mask = S2MPS11_IRQ_ACOKBR_MASK,
182 	},
183 	[S2MPU02_IRQ_PWRON1S] = {
184 		.reg_offset = 0,
185 		.mask = S2MPS11_IRQ_PWRON1S_MASK,
186 	},
187 	[S2MPU02_IRQ_MRB] = {
188 		.reg_offset = 0,
189 		.mask = S2MPS11_IRQ_MRB_MASK,
190 	},
191 	[S2MPU02_IRQ_RTC60S] = {
192 		.reg_offset = 1,
193 		.mask = S2MPS11_IRQ_RTC60S_MASK,
194 	},
195 	[S2MPU02_IRQ_RTCA1] = {
196 		.reg_offset = 1,
197 		.mask = S2MPS11_IRQ_RTCA1_MASK,
198 	},
199 	[S2MPU02_IRQ_RTCA0] = {
200 		.reg_offset = 1,
201 		.mask = S2MPS11_IRQ_RTCA0_MASK,
202 	},
203 	[S2MPU02_IRQ_SMPL] = {
204 		.reg_offset = 1,
205 		.mask = S2MPS11_IRQ_SMPL_MASK,
206 	},
207 	[S2MPU02_IRQ_RTC1S] = {
208 		.reg_offset = 1,
209 		.mask = S2MPS11_IRQ_RTC1S_MASK,
210 	},
211 	[S2MPU02_IRQ_WTSR] = {
212 		.reg_offset = 1,
213 		.mask = S2MPS11_IRQ_WTSR_MASK,
214 	},
215 	[S2MPU02_IRQ_INT120C] = {
216 		.reg_offset = 2,
217 		.mask = S2MPS11_IRQ_INT120C_MASK,
218 	},
219 	[S2MPU02_IRQ_INT140C] = {
220 		.reg_offset = 2,
221 		.mask = S2MPS11_IRQ_INT140C_MASK,
222 	},
223 	[S2MPU02_IRQ_TSD] = {
224 		.reg_offset = 2,
225 		.mask = S2MPS14_IRQ_TSD_MASK,
226 	},
227 };
228 
229 static const struct regmap_irq s5m8767_irqs[] = {
230 	[S5M8767_IRQ_PWRR] = {
231 		.reg_offset = 0,
232 		.mask = S5M8767_IRQ_PWRR_MASK,
233 	},
234 	[S5M8767_IRQ_PWRF] = {
235 		.reg_offset = 0,
236 		.mask = S5M8767_IRQ_PWRF_MASK,
237 	},
238 	[S5M8767_IRQ_PWR1S] = {
239 		.reg_offset = 0,
240 		.mask = S5M8767_IRQ_PWR1S_MASK,
241 	},
242 	[S5M8767_IRQ_JIGR] = {
243 		.reg_offset = 0,
244 		.mask = S5M8767_IRQ_JIGR_MASK,
245 	},
246 	[S5M8767_IRQ_JIGF] = {
247 		.reg_offset = 0,
248 		.mask = S5M8767_IRQ_JIGF_MASK,
249 	},
250 	[S5M8767_IRQ_LOWBAT2] = {
251 		.reg_offset = 0,
252 		.mask = S5M8767_IRQ_LOWBAT2_MASK,
253 	},
254 	[S5M8767_IRQ_LOWBAT1] = {
255 		.reg_offset = 0,
256 		.mask = S5M8767_IRQ_LOWBAT1_MASK,
257 	},
258 	[S5M8767_IRQ_MRB] = {
259 		.reg_offset = 1,
260 		.mask = S5M8767_IRQ_MRB_MASK,
261 	},
262 	[S5M8767_IRQ_DVSOK2] = {
263 		.reg_offset = 1,
264 		.mask = S5M8767_IRQ_DVSOK2_MASK,
265 	},
266 	[S5M8767_IRQ_DVSOK3] = {
267 		.reg_offset = 1,
268 		.mask = S5M8767_IRQ_DVSOK3_MASK,
269 	},
270 	[S5M8767_IRQ_DVSOK4] = {
271 		.reg_offset = 1,
272 		.mask = S5M8767_IRQ_DVSOK4_MASK,
273 	},
274 	[S5M8767_IRQ_RTC60S] = {
275 		.reg_offset = 2,
276 		.mask = S5M8767_IRQ_RTC60S_MASK,
277 	},
278 	[S5M8767_IRQ_RTCA1] = {
279 		.reg_offset = 2,
280 		.mask = S5M8767_IRQ_RTCA1_MASK,
281 	},
282 	[S5M8767_IRQ_RTCA2] = {
283 		.reg_offset = 2,
284 		.mask = S5M8767_IRQ_RTCA2_MASK,
285 	},
286 	[S5M8767_IRQ_SMPL] = {
287 		.reg_offset = 2,
288 		.mask = S5M8767_IRQ_SMPL_MASK,
289 	},
290 	[S5M8767_IRQ_RTC1S] = {
291 		.reg_offset = 2,
292 		.mask = S5M8767_IRQ_RTC1S_MASK,
293 	},
294 	[S5M8767_IRQ_WTSR] = {
295 		.reg_offset = 2,
296 		.mask = S5M8767_IRQ_WTSR_MASK,
297 	},
298 };
299 
300 static const struct regmap_irq s5m8763_irqs[] = {
301 	[S5M8763_IRQ_DCINF] = {
302 		.reg_offset = 0,
303 		.mask = S5M8763_IRQ_DCINF_MASK,
304 	},
305 	[S5M8763_IRQ_DCINR] = {
306 		.reg_offset = 0,
307 		.mask = S5M8763_IRQ_DCINR_MASK,
308 	},
309 	[S5M8763_IRQ_JIGF] = {
310 		.reg_offset = 0,
311 		.mask = S5M8763_IRQ_JIGF_MASK,
312 	},
313 	[S5M8763_IRQ_JIGR] = {
314 		.reg_offset = 0,
315 		.mask = S5M8763_IRQ_JIGR_MASK,
316 	},
317 	[S5M8763_IRQ_PWRONF] = {
318 		.reg_offset = 0,
319 		.mask = S5M8763_IRQ_PWRONF_MASK,
320 	},
321 	[S5M8763_IRQ_PWRONR] = {
322 		.reg_offset = 0,
323 		.mask = S5M8763_IRQ_PWRONR_MASK,
324 	},
325 	[S5M8763_IRQ_WTSREVNT] = {
326 		.reg_offset = 1,
327 		.mask = S5M8763_IRQ_WTSREVNT_MASK,
328 	},
329 	[S5M8763_IRQ_SMPLEVNT] = {
330 		.reg_offset = 1,
331 		.mask = S5M8763_IRQ_SMPLEVNT_MASK,
332 	},
333 	[S5M8763_IRQ_ALARM1] = {
334 		.reg_offset = 1,
335 		.mask = S5M8763_IRQ_ALARM1_MASK,
336 	},
337 	[S5M8763_IRQ_ALARM0] = {
338 		.reg_offset = 1,
339 		.mask = S5M8763_IRQ_ALARM0_MASK,
340 	},
341 	[S5M8763_IRQ_ONKEY1S] = {
342 		.reg_offset = 2,
343 		.mask = S5M8763_IRQ_ONKEY1S_MASK,
344 	},
345 	[S5M8763_IRQ_TOPOFFR] = {
346 		.reg_offset = 2,
347 		.mask = S5M8763_IRQ_TOPOFFR_MASK,
348 	},
349 	[S5M8763_IRQ_DCINOVPR] = {
350 		.reg_offset = 2,
351 		.mask = S5M8763_IRQ_DCINOVPR_MASK,
352 	},
353 	[S5M8763_IRQ_CHGRSTF] = {
354 		.reg_offset = 2,
355 		.mask = S5M8763_IRQ_CHGRSTF_MASK,
356 	},
357 	[S5M8763_IRQ_DONER] = {
358 		.reg_offset = 2,
359 		.mask = S5M8763_IRQ_DONER_MASK,
360 	},
361 	[S5M8763_IRQ_CHGFAULT] = {
362 		.reg_offset = 2,
363 		.mask = S5M8763_IRQ_CHGFAULT_MASK,
364 	},
365 	[S5M8763_IRQ_LOBAT1] = {
366 		.reg_offset = 3,
367 		.mask = S5M8763_IRQ_LOBAT1_MASK,
368 	},
369 	[S5M8763_IRQ_LOBAT2] = {
370 		.reg_offset = 3,
371 		.mask = S5M8763_IRQ_LOBAT2_MASK,
372 	},
373 };
374 
375 static const struct regmap_irq_chip s2mps11_irq_chip = {
376 	.name = "s2mps11",
377 	.irqs = s2mps11_irqs,
378 	.num_irqs = ARRAY_SIZE(s2mps11_irqs),
379 	.num_regs = 3,
380 	.status_base = S2MPS11_REG_INT1,
381 	.mask_base = S2MPS11_REG_INT1M,
382 	.ack_base = S2MPS11_REG_INT1,
383 };
384 
385 #define S2MPS1X_IRQ_CHIP_COMMON_DATA		\
386 	.irqs = s2mps14_irqs,			\
387 	.num_irqs = ARRAY_SIZE(s2mps14_irqs),	\
388 	.num_regs = 3,				\
389 	.status_base = S2MPS14_REG_INT1,	\
390 	.mask_base = S2MPS14_REG_INT1M,		\
391 	.ack_base = S2MPS14_REG_INT1		\
392 
393 static const struct regmap_irq_chip s2mps13_irq_chip = {
394 	.name = "s2mps13",
395 	S2MPS1X_IRQ_CHIP_COMMON_DATA,
396 };
397 
398 static const struct regmap_irq_chip s2mps14_irq_chip = {
399 	.name = "s2mps14",
400 	S2MPS1X_IRQ_CHIP_COMMON_DATA,
401 };
402 
403 static const struct regmap_irq_chip s2mps15_irq_chip = {
404 	.name = "s2mps15",
405 	S2MPS1X_IRQ_CHIP_COMMON_DATA,
406 };
407 
408 static const struct regmap_irq_chip s2mpu02_irq_chip = {
409 	.name = "s2mpu02",
410 	.irqs = s2mpu02_irqs,
411 	.num_irqs = ARRAY_SIZE(s2mpu02_irqs),
412 	.num_regs = 3,
413 	.status_base = S2MPU02_REG_INT1,
414 	.mask_base = S2MPU02_REG_INT1M,
415 	.ack_base = S2MPU02_REG_INT1,
416 };
417 
418 static const struct regmap_irq_chip s5m8767_irq_chip = {
419 	.name = "s5m8767",
420 	.irqs = s5m8767_irqs,
421 	.num_irqs = ARRAY_SIZE(s5m8767_irqs),
422 	.num_regs = 3,
423 	.status_base = S5M8767_REG_INT1,
424 	.mask_base = S5M8767_REG_INT1M,
425 	.ack_base = S5M8767_REG_INT1,
426 };
427 
428 static const struct regmap_irq_chip s5m8763_irq_chip = {
429 	.name = "s5m8763",
430 	.irqs = s5m8763_irqs,
431 	.num_irqs = ARRAY_SIZE(s5m8763_irqs),
432 	.num_regs = 4,
433 	.status_base = S5M8763_REG_IRQ1,
434 	.mask_base = S5M8763_REG_IRQM1,
435 	.ack_base = S5M8763_REG_IRQ1,
436 };
437 
438 int sec_irq_init(struct sec_pmic_dev *sec_pmic)
439 {
440 	int ret = 0;
441 	int type = sec_pmic->device_type;
442 	const struct regmap_irq_chip *sec_irq_chip;
443 
444 	if (!sec_pmic->irq) {
445 		dev_warn(sec_pmic->dev,
446 			 "No interrupt specified, no interrupts\n");
447 		return 0;
448 	}
449 
450 	switch (type) {
451 	case S5M8763X:
452 		sec_irq_chip = &s5m8763_irq_chip;
453 		break;
454 	case S5M8767X:
455 		sec_irq_chip = &s5m8767_irq_chip;
456 		break;
457 	case S2MPA01:
458 		sec_irq_chip = &s2mps14_irq_chip;
459 		break;
460 	case S2MPS11X:
461 		sec_irq_chip = &s2mps11_irq_chip;
462 		break;
463 	case S2MPS13X:
464 		sec_irq_chip = &s2mps13_irq_chip;
465 		break;
466 	case S2MPS14X:
467 		sec_irq_chip = &s2mps14_irq_chip;
468 		break;
469 	case S2MPS15X:
470 		sec_irq_chip = &s2mps15_irq_chip;
471 		break;
472 	case S2MPU02:
473 		sec_irq_chip = &s2mpu02_irq_chip;
474 		break;
475 	default:
476 		dev_err(sec_pmic->dev, "Unknown device type %lu\n",
477 			sec_pmic->device_type);
478 		return -EINVAL;
479 	}
480 
481 	ret = devm_regmap_add_irq_chip(sec_pmic->dev, sec_pmic->regmap_pmic,
482 				       sec_pmic->irq, IRQF_ONESHOT,
483 				       0, sec_irq_chip, &sec_pmic->irq_data);
484 	if (ret != 0) {
485 		dev_err(sec_pmic->dev, "Failed to register IRQ chip: %d\n", ret);
486 		return ret;
487 	}
488 
489 	/*
490 	 * The rtc-s5m driver requests S2MPS14_IRQ_RTCA0 also for S2MPS11
491 	 * so the interrupt number must be consistent.
492 	 */
493 	BUILD_BUG_ON(((enum s2mps14_irq)S2MPS11_IRQ_RTCA0) != S2MPS14_IRQ_RTCA0);
494 
495 	return 0;
496 }
497 EXPORT_SYMBOL_GPL(sec_irq_init);
498 
499 MODULE_AUTHOR("Sangbeom Kim <sbkim73@samsung.com>");
500 MODULE_AUTHOR("Chanwoo Choi <cw00.choi@samsung.com>");
501 MODULE_AUTHOR("Krzysztof Kozlowski <krzk@kernel.org>");
502 MODULE_DESCRIPTION("Interrupt support for the S5M MFD");
503 MODULE_LICENSE("GPL");
504