xref: /openbmc/linux/drivers/mfd/sec-irq.c (revision 275876e2)
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_RTCA0] = {
65 		.reg_offset = 1,
66 		.mask = S2MPS11_IRQ_RTCA0_MASK,
67 	},
68 	[S2MPS11_IRQ_RTCA1] = {
69 		.reg_offset = 1,
70 		.mask = S2MPS11_IRQ_RTCA1_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 static const struct regmap_irq_chip s2mps14_irq_chip = {
393 	.name = "s2mps14",
394 	.irqs = s2mps14_irqs,
395 	.num_irqs = ARRAY_SIZE(s2mps14_irqs),
396 	.num_regs = 3,
397 	.status_base = S2MPS14_REG_INT1,
398 	.mask_base = S2MPS14_REG_INT1M,
399 	.ack_base = S2MPS14_REG_INT1,
400 };
401 
402 static const struct regmap_irq_chip s2mpu02_irq_chip = {
403 	.name = "s2mpu02",
404 	.irqs = s2mpu02_irqs,
405 	.num_irqs = ARRAY_SIZE(s2mpu02_irqs),
406 	.num_regs = 3,
407 	.status_base = S2MPU02_REG_INT1,
408 	.mask_base = S2MPU02_REG_INT1M,
409 	.ack_base = S2MPU02_REG_INT1,
410 };
411 
412 static const struct regmap_irq_chip s5m8767_irq_chip = {
413 	.name = "s5m8767",
414 	.irqs = s5m8767_irqs,
415 	.num_irqs = ARRAY_SIZE(s5m8767_irqs),
416 	.num_regs = 3,
417 	.status_base = S5M8767_REG_INT1,
418 	.mask_base = S5M8767_REG_INT1M,
419 	.ack_base = S5M8767_REG_INT1,
420 };
421 
422 static const struct regmap_irq_chip s5m8763_irq_chip = {
423 	.name = "s5m8763",
424 	.irqs = s5m8763_irqs,
425 	.num_irqs = ARRAY_SIZE(s5m8763_irqs),
426 	.num_regs = 4,
427 	.status_base = S5M8763_REG_IRQ1,
428 	.mask_base = S5M8763_REG_IRQM1,
429 	.ack_base = S5M8763_REG_IRQ1,
430 };
431 
432 int sec_irq_init(struct sec_pmic_dev *sec_pmic)
433 {
434 	int ret = 0;
435 	int type = sec_pmic->device_type;
436 	const struct regmap_irq_chip *sec_irq_chip;
437 
438 	if (!sec_pmic->irq) {
439 		dev_warn(sec_pmic->dev,
440 			 "No interrupt specified, no interrupts\n");
441 		sec_pmic->irq_base = 0;
442 		return 0;
443 	}
444 
445 	switch (type) {
446 	case S5M8763X:
447 		sec_irq_chip = &s5m8763_irq_chip;
448 		break;
449 	case S5M8767X:
450 		sec_irq_chip = &s5m8767_irq_chip;
451 		break;
452 	case S2MPS11X:
453 		sec_irq_chip = &s2mps11_irq_chip;
454 		break;
455 	case S2MPS14X:
456 		sec_irq_chip = &s2mps14_irq_chip;
457 		break;
458 	case S2MPU02:
459 		sec_irq_chip = &s2mpu02_irq_chip;
460 		break;
461 	default:
462 		dev_err(sec_pmic->dev, "Unknown device type %lu\n",
463 			sec_pmic->device_type);
464 		return -EINVAL;
465 	}
466 
467 	ret = regmap_add_irq_chip(sec_pmic->regmap_pmic, sec_pmic->irq,
468 			  IRQF_TRIGGER_FALLING | IRQF_ONESHOT,
469 			  sec_pmic->irq_base, sec_irq_chip,
470 			  &sec_pmic->irq_data);
471 	if (ret != 0) {
472 		dev_err(sec_pmic->dev, "Failed to register IRQ chip: %d\n", ret);
473 		return ret;
474 	}
475 
476 	return 0;
477 }
478 
479 void sec_irq_exit(struct sec_pmic_dev *sec_pmic)
480 {
481 	regmap_del_irq_chip(sec_pmic->irq, sec_pmic->irq_data);
482 }
483