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