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/s2mpu05.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 s2mpu05_irqs[] = {
230 REGMAP_IRQ_REG(S2MPU05_IRQ_PWRONF, 0, S2MPU05_IRQ_PWRONF_MASK),
231 REGMAP_IRQ_REG(S2MPU05_IRQ_PWRONR, 0, S2MPU05_IRQ_PWRONR_MASK),
232 REGMAP_IRQ_REG(S2MPU05_IRQ_JIGONBF, 0, S2MPU05_IRQ_JIGONBF_MASK),
233 REGMAP_IRQ_REG(S2MPU05_IRQ_JIGONBR, 0, S2MPU05_IRQ_JIGONBR_MASK),
234 REGMAP_IRQ_REG(S2MPU05_IRQ_ACOKF, 0, S2MPU05_IRQ_ACOKF_MASK),
235 REGMAP_IRQ_REG(S2MPU05_IRQ_ACOKR, 0, S2MPU05_IRQ_ACOKR_MASK),
236 REGMAP_IRQ_REG(S2MPU05_IRQ_PWRON1S, 0, S2MPU05_IRQ_PWRON1S_MASK),
237 REGMAP_IRQ_REG(S2MPU05_IRQ_MRB, 0, S2MPU05_IRQ_MRB_MASK),
238 REGMAP_IRQ_REG(S2MPU05_IRQ_RTC60S, 1, S2MPU05_IRQ_RTC60S_MASK),
239 REGMAP_IRQ_REG(S2MPU05_IRQ_RTCA1, 1, S2MPU05_IRQ_RTCA1_MASK),
240 REGMAP_IRQ_REG(S2MPU05_IRQ_RTCA0, 1, S2MPU05_IRQ_RTCA0_MASK),
241 REGMAP_IRQ_REG(S2MPU05_IRQ_SMPL, 1, S2MPU05_IRQ_SMPL_MASK),
242 REGMAP_IRQ_REG(S2MPU05_IRQ_RTC1S, 1, S2MPU05_IRQ_RTC1S_MASK),
243 REGMAP_IRQ_REG(S2MPU05_IRQ_WTSR, 1, S2MPU05_IRQ_WTSR_MASK),
244 REGMAP_IRQ_REG(S2MPU05_IRQ_INT120C, 2, S2MPU05_IRQ_INT120C_MASK),
245 REGMAP_IRQ_REG(S2MPU05_IRQ_INT140C, 2, S2MPU05_IRQ_INT140C_MASK),
246 REGMAP_IRQ_REG(S2MPU05_IRQ_TSD, 2, S2MPU05_IRQ_TSD_MASK),
247 };
248
249 static const struct regmap_irq s5m8767_irqs[] = {
250 [S5M8767_IRQ_PWRR] = {
251 .reg_offset = 0,
252 .mask = S5M8767_IRQ_PWRR_MASK,
253 },
254 [S5M8767_IRQ_PWRF] = {
255 .reg_offset = 0,
256 .mask = S5M8767_IRQ_PWRF_MASK,
257 },
258 [S5M8767_IRQ_PWR1S] = {
259 .reg_offset = 0,
260 .mask = S5M8767_IRQ_PWR1S_MASK,
261 },
262 [S5M8767_IRQ_JIGR] = {
263 .reg_offset = 0,
264 .mask = S5M8767_IRQ_JIGR_MASK,
265 },
266 [S5M8767_IRQ_JIGF] = {
267 .reg_offset = 0,
268 .mask = S5M8767_IRQ_JIGF_MASK,
269 },
270 [S5M8767_IRQ_LOWBAT2] = {
271 .reg_offset = 0,
272 .mask = S5M8767_IRQ_LOWBAT2_MASK,
273 },
274 [S5M8767_IRQ_LOWBAT1] = {
275 .reg_offset = 0,
276 .mask = S5M8767_IRQ_LOWBAT1_MASK,
277 },
278 [S5M8767_IRQ_MRB] = {
279 .reg_offset = 1,
280 .mask = S5M8767_IRQ_MRB_MASK,
281 },
282 [S5M8767_IRQ_DVSOK2] = {
283 .reg_offset = 1,
284 .mask = S5M8767_IRQ_DVSOK2_MASK,
285 },
286 [S5M8767_IRQ_DVSOK3] = {
287 .reg_offset = 1,
288 .mask = S5M8767_IRQ_DVSOK3_MASK,
289 },
290 [S5M8767_IRQ_DVSOK4] = {
291 .reg_offset = 1,
292 .mask = S5M8767_IRQ_DVSOK4_MASK,
293 },
294 [S5M8767_IRQ_RTC60S] = {
295 .reg_offset = 2,
296 .mask = S5M8767_IRQ_RTC60S_MASK,
297 },
298 [S5M8767_IRQ_RTCA1] = {
299 .reg_offset = 2,
300 .mask = S5M8767_IRQ_RTCA1_MASK,
301 },
302 [S5M8767_IRQ_RTCA2] = {
303 .reg_offset = 2,
304 .mask = S5M8767_IRQ_RTCA2_MASK,
305 },
306 [S5M8767_IRQ_SMPL] = {
307 .reg_offset = 2,
308 .mask = S5M8767_IRQ_SMPL_MASK,
309 },
310 [S5M8767_IRQ_RTC1S] = {
311 .reg_offset = 2,
312 .mask = S5M8767_IRQ_RTC1S_MASK,
313 },
314 [S5M8767_IRQ_WTSR] = {
315 .reg_offset = 2,
316 .mask = S5M8767_IRQ_WTSR_MASK,
317 },
318 };
319
320 static const struct regmap_irq_chip s2mps11_irq_chip = {
321 .name = "s2mps11",
322 .irqs = s2mps11_irqs,
323 .num_irqs = ARRAY_SIZE(s2mps11_irqs),
324 .num_regs = 3,
325 .status_base = S2MPS11_REG_INT1,
326 .mask_base = S2MPS11_REG_INT1M,
327 .ack_base = S2MPS11_REG_INT1,
328 };
329
330 #define S2MPS1X_IRQ_CHIP_COMMON_DATA \
331 .irqs = s2mps14_irqs, \
332 .num_irqs = ARRAY_SIZE(s2mps14_irqs), \
333 .num_regs = 3, \
334 .status_base = S2MPS14_REG_INT1, \
335 .mask_base = S2MPS14_REG_INT1M, \
336 .ack_base = S2MPS14_REG_INT1 \
337
338 static const struct regmap_irq_chip s2mps13_irq_chip = {
339 .name = "s2mps13",
340 S2MPS1X_IRQ_CHIP_COMMON_DATA,
341 };
342
343 static const struct regmap_irq_chip s2mps14_irq_chip = {
344 .name = "s2mps14",
345 S2MPS1X_IRQ_CHIP_COMMON_DATA,
346 };
347
348 static const struct regmap_irq_chip s2mps15_irq_chip = {
349 .name = "s2mps15",
350 S2MPS1X_IRQ_CHIP_COMMON_DATA,
351 };
352
353 static const struct regmap_irq_chip s2mpu02_irq_chip = {
354 .name = "s2mpu02",
355 .irqs = s2mpu02_irqs,
356 .num_irqs = ARRAY_SIZE(s2mpu02_irqs),
357 .num_regs = 3,
358 .status_base = S2MPU02_REG_INT1,
359 .mask_base = S2MPU02_REG_INT1M,
360 .ack_base = S2MPU02_REG_INT1,
361 };
362
363 static const struct regmap_irq_chip s2mpu05_irq_chip = {
364 .name = "s2mpu05",
365 .irqs = s2mpu05_irqs,
366 .num_irqs = ARRAY_SIZE(s2mpu05_irqs),
367 .num_regs = 3,
368 .status_base = S2MPU05_REG_INT1,
369 .mask_base = S2MPU05_REG_INT1M,
370 .ack_base = S2MPU05_REG_INT1,
371 };
372
373 static const struct regmap_irq_chip s5m8767_irq_chip = {
374 .name = "s5m8767",
375 .irqs = s5m8767_irqs,
376 .num_irqs = ARRAY_SIZE(s5m8767_irqs),
377 .num_regs = 3,
378 .status_base = S5M8767_REG_INT1,
379 .mask_base = S5M8767_REG_INT1M,
380 .ack_base = S5M8767_REG_INT1,
381 };
382
sec_irq_init(struct sec_pmic_dev * sec_pmic)383 int sec_irq_init(struct sec_pmic_dev *sec_pmic)
384 {
385 int ret = 0;
386 int type = sec_pmic->device_type;
387 const struct regmap_irq_chip *sec_irq_chip;
388
389 if (!sec_pmic->irq) {
390 dev_warn(sec_pmic->dev,
391 "No interrupt specified, no interrupts\n");
392 return 0;
393 }
394
395 switch (type) {
396 case S5M8767X:
397 sec_irq_chip = &s5m8767_irq_chip;
398 break;
399 case S2MPA01:
400 sec_irq_chip = &s2mps14_irq_chip;
401 break;
402 case S2MPS11X:
403 sec_irq_chip = &s2mps11_irq_chip;
404 break;
405 case S2MPS13X:
406 sec_irq_chip = &s2mps13_irq_chip;
407 break;
408 case S2MPS14X:
409 sec_irq_chip = &s2mps14_irq_chip;
410 break;
411 case S2MPS15X:
412 sec_irq_chip = &s2mps15_irq_chip;
413 break;
414 case S2MPU02:
415 sec_irq_chip = &s2mpu02_irq_chip;
416 break;
417 case S2MPU05:
418 sec_irq_chip = &s2mpu05_irq_chip;
419 break;
420 default:
421 dev_err(sec_pmic->dev, "Unknown device type %lu\n",
422 sec_pmic->device_type);
423 return -EINVAL;
424 }
425
426 ret = devm_regmap_add_irq_chip(sec_pmic->dev, sec_pmic->regmap_pmic,
427 sec_pmic->irq, IRQF_ONESHOT,
428 0, sec_irq_chip, &sec_pmic->irq_data);
429 if (ret != 0) {
430 dev_err(sec_pmic->dev, "Failed to register IRQ chip: %d\n", ret);
431 return ret;
432 }
433
434 /*
435 * The rtc-s5m driver requests S2MPS14_IRQ_RTCA0 also for S2MPS11
436 * so the interrupt number must be consistent.
437 */
438 BUILD_BUG_ON(((enum s2mps14_irq)S2MPS11_IRQ_RTCA0) != S2MPS14_IRQ_RTCA0);
439
440 return 0;
441 }
442 EXPORT_SYMBOL_GPL(sec_irq_init);
443
444 MODULE_AUTHOR("Sangbeom Kim <sbkim73@samsung.com>");
445 MODULE_AUTHOR("Chanwoo Choi <cw00.choi@samsung.com>");
446 MODULE_AUTHOR("Krzysztof Kozlowski <krzk@kernel.org>");
447 MODULE_DESCRIPTION("Interrupt support for the S5M MFD");
448 MODULE_LICENSE("GPL");
449