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/s5m8767.h> |
18 | |
19 | static const struct regmap_irq s2mps11_irqs[] = { |
20 | [S2MPS11_IRQ_PWRONF] = { |
21 | .reg_offset = 0, |
22 | .mask = S2MPS11_IRQ_PWRONF_MASK, |
23 | }, |
24 | [S2MPS11_IRQ_PWRONR] = { |
25 | .reg_offset = 0, |
26 | .mask = S2MPS11_IRQ_PWRONR_MASK, |
27 | }, |
28 | [S2MPS11_IRQ_JIGONBF] = { |
29 | .reg_offset = 0, |
30 | .mask = S2MPS11_IRQ_JIGONBF_MASK, |
31 | }, |
32 | [S2MPS11_IRQ_JIGONBR] = { |
33 | .reg_offset = 0, |
34 | .mask = S2MPS11_IRQ_JIGONBR_MASK, |
35 | }, |
36 | [S2MPS11_IRQ_ACOKBF] = { |
37 | .reg_offset = 0, |
38 | .mask = S2MPS11_IRQ_ACOKBF_MASK, |
39 | }, |
40 | [S2MPS11_IRQ_ACOKBR] = { |
41 | .reg_offset = 0, |
42 | .mask = S2MPS11_IRQ_ACOKBR_MASK, |
43 | }, |
44 | [S2MPS11_IRQ_PWRON1S] = { |
45 | .reg_offset = 0, |
46 | .mask = S2MPS11_IRQ_PWRON1S_MASK, |
47 | }, |
48 | [S2MPS11_IRQ_MRB] = { |
49 | .reg_offset = 0, |
50 | .mask = S2MPS11_IRQ_MRB_MASK, |
51 | }, |
52 | [S2MPS11_IRQ_RTC60S] = { |
53 | .reg_offset = 1, |
54 | .mask = S2MPS11_IRQ_RTC60S_MASK, |
55 | }, |
56 | [S2MPS11_IRQ_RTCA1] = { |
57 | .reg_offset = 1, |
58 | .mask = S2MPS11_IRQ_RTCA1_MASK, |
59 | }, |
60 | [S2MPS11_IRQ_RTCA0] = { |
61 | .reg_offset = 1, |
62 | .mask = S2MPS11_IRQ_RTCA0_MASK, |
63 | }, |
64 | [S2MPS11_IRQ_SMPL] = { |
65 | .reg_offset = 1, |
66 | .mask = S2MPS11_IRQ_SMPL_MASK, |
67 | }, |
68 | [S2MPS11_IRQ_RTC1S] = { |
69 | .reg_offset = 1, |
70 | .mask = S2MPS11_IRQ_RTC1S_MASK, |
71 | }, |
72 | [S2MPS11_IRQ_WTSR] = { |
73 | .reg_offset = 1, |
74 | .mask = S2MPS11_IRQ_WTSR_MASK, |
75 | }, |
76 | [S2MPS11_IRQ_INT120C] = { |
77 | .reg_offset = 2, |
78 | .mask = S2MPS11_IRQ_INT120C_MASK, |
79 | }, |
80 | [S2MPS11_IRQ_INT140C] = { |
81 | .reg_offset = 2, |
82 | .mask = S2MPS11_IRQ_INT140C_MASK, |
83 | }, |
84 | }; |
85 | |
86 | static const struct regmap_irq s2mps14_irqs[] = { |
87 | [S2MPS14_IRQ_PWRONF] = { |
88 | .reg_offset = 0, |
89 | .mask = S2MPS11_IRQ_PWRONF_MASK, |
90 | }, |
91 | [S2MPS14_IRQ_PWRONR] = { |
92 | .reg_offset = 0, |
93 | .mask = S2MPS11_IRQ_PWRONR_MASK, |
94 | }, |
95 | [S2MPS14_IRQ_JIGONBF] = { |
96 | .reg_offset = 0, |
97 | .mask = S2MPS11_IRQ_JIGONBF_MASK, |
98 | }, |
99 | [S2MPS14_IRQ_JIGONBR] = { |
100 | .reg_offset = 0, |
101 | .mask = S2MPS11_IRQ_JIGONBR_MASK, |
102 | }, |
103 | [S2MPS14_IRQ_ACOKBF] = { |
104 | .reg_offset = 0, |
105 | .mask = S2MPS11_IRQ_ACOKBF_MASK, |
106 | }, |
107 | [S2MPS14_IRQ_ACOKBR] = { |
108 | .reg_offset = 0, |
109 | .mask = S2MPS11_IRQ_ACOKBR_MASK, |
110 | }, |
111 | [S2MPS14_IRQ_PWRON1S] = { |
112 | .reg_offset = 0, |
113 | .mask = S2MPS11_IRQ_PWRON1S_MASK, |
114 | }, |
115 | [S2MPS14_IRQ_MRB] = { |
116 | .reg_offset = 0, |
117 | .mask = S2MPS11_IRQ_MRB_MASK, |
118 | }, |
119 | [S2MPS14_IRQ_RTC60S] = { |
120 | .reg_offset = 1, |
121 | .mask = S2MPS11_IRQ_RTC60S_MASK, |
122 | }, |
123 | [S2MPS14_IRQ_RTCA1] = { |
124 | .reg_offset = 1, |
125 | .mask = S2MPS11_IRQ_RTCA1_MASK, |
126 | }, |
127 | [S2MPS14_IRQ_RTCA0] = { |
128 | .reg_offset = 1, |
129 | .mask = S2MPS11_IRQ_RTCA0_MASK, |
130 | }, |
131 | [S2MPS14_IRQ_SMPL] = { |
132 | .reg_offset = 1, |
133 | .mask = S2MPS11_IRQ_SMPL_MASK, |
134 | }, |
135 | [S2MPS14_IRQ_RTC1S] = { |
136 | .reg_offset = 1, |
137 | .mask = S2MPS11_IRQ_RTC1S_MASK, |
138 | }, |
139 | [S2MPS14_IRQ_WTSR] = { |
140 | .reg_offset = 1, |
141 | .mask = S2MPS11_IRQ_WTSR_MASK, |
142 | }, |
143 | [S2MPS14_IRQ_INT120C] = { |
144 | .reg_offset = 2, |
145 | .mask = S2MPS11_IRQ_INT120C_MASK, |
146 | }, |
147 | [S2MPS14_IRQ_INT140C] = { |
148 | .reg_offset = 2, |
149 | .mask = S2MPS11_IRQ_INT140C_MASK, |
150 | }, |
151 | [S2MPS14_IRQ_TSD] = { |
152 | .reg_offset = 2, |
153 | .mask = S2MPS14_IRQ_TSD_MASK, |
154 | }, |
155 | }; |
156 | |
157 | static const struct regmap_irq s2mpu02_irqs[] = { |
158 | [S2MPU02_IRQ_PWRONF] = { |
159 | .reg_offset = 0, |
160 | .mask = S2MPS11_IRQ_PWRONF_MASK, |
161 | }, |
162 | [S2MPU02_IRQ_PWRONR] = { |
163 | .reg_offset = 0, |
164 | .mask = S2MPS11_IRQ_PWRONR_MASK, |
165 | }, |
166 | [S2MPU02_IRQ_JIGONBF] = { |
167 | .reg_offset = 0, |
168 | .mask = S2MPS11_IRQ_JIGONBF_MASK, |
169 | }, |
170 | [S2MPU02_IRQ_JIGONBR] = { |
171 | .reg_offset = 0, |
172 | .mask = S2MPS11_IRQ_JIGONBR_MASK, |
173 | }, |
174 | [S2MPU02_IRQ_ACOKBF] = { |
175 | .reg_offset = 0, |
176 | .mask = S2MPS11_IRQ_ACOKBF_MASK, |
177 | }, |
178 | [S2MPU02_IRQ_ACOKBR] = { |
179 | .reg_offset = 0, |
180 | .mask = S2MPS11_IRQ_ACOKBR_MASK, |
181 | }, |
182 | [S2MPU02_IRQ_PWRON1S] = { |
183 | .reg_offset = 0, |
184 | .mask = S2MPS11_IRQ_PWRON1S_MASK, |
185 | }, |
186 | [S2MPU02_IRQ_MRB] = { |
187 | .reg_offset = 0, |
188 | .mask = S2MPS11_IRQ_MRB_MASK, |
189 | }, |
190 | [S2MPU02_IRQ_RTC60S] = { |
191 | .reg_offset = 1, |
192 | .mask = S2MPS11_IRQ_RTC60S_MASK, |
193 | }, |
194 | [S2MPU02_IRQ_RTCA1] = { |
195 | .reg_offset = 1, |
196 | .mask = S2MPS11_IRQ_RTCA1_MASK, |
197 | }, |
198 | [S2MPU02_IRQ_RTCA0] = { |
199 | .reg_offset = 1, |
200 | .mask = S2MPS11_IRQ_RTCA0_MASK, |
201 | }, |
202 | [S2MPU02_IRQ_SMPL] = { |
203 | .reg_offset = 1, |
204 | .mask = S2MPS11_IRQ_SMPL_MASK, |
205 | }, |
206 | [S2MPU02_IRQ_RTC1S] = { |
207 | .reg_offset = 1, |
208 | .mask = S2MPS11_IRQ_RTC1S_MASK, |
209 | }, |
210 | [S2MPU02_IRQ_WTSR] = { |
211 | .reg_offset = 1, |
212 | .mask = S2MPS11_IRQ_WTSR_MASK, |
213 | }, |
214 | [S2MPU02_IRQ_INT120C] = { |
215 | .reg_offset = 2, |
216 | .mask = S2MPS11_IRQ_INT120C_MASK, |
217 | }, |
218 | [S2MPU02_IRQ_INT140C] = { |
219 | .reg_offset = 2, |
220 | .mask = S2MPS11_IRQ_INT140C_MASK, |
221 | }, |
222 | [S2MPU02_IRQ_TSD] = { |
223 | .reg_offset = 2, |
224 | .mask = S2MPS14_IRQ_TSD_MASK, |
225 | }, |
226 | }; |
227 | |
228 | static const struct regmap_irq s5m8767_irqs[] = { |
229 | [S5M8767_IRQ_PWRR] = { |
230 | .reg_offset = 0, |
231 | .mask = S5M8767_IRQ_PWRR_MASK, |
232 | }, |
233 | [S5M8767_IRQ_PWRF] = { |
234 | .reg_offset = 0, |
235 | .mask = S5M8767_IRQ_PWRF_MASK, |
236 | }, |
237 | [S5M8767_IRQ_PWR1S] = { |
238 | .reg_offset = 0, |
239 | .mask = S5M8767_IRQ_PWR1S_MASK, |
240 | }, |
241 | [S5M8767_IRQ_JIGR] = { |
242 | .reg_offset = 0, |
243 | .mask = S5M8767_IRQ_JIGR_MASK, |
244 | }, |
245 | [S5M8767_IRQ_JIGF] = { |
246 | .reg_offset = 0, |
247 | .mask = S5M8767_IRQ_JIGF_MASK, |
248 | }, |
249 | [S5M8767_IRQ_LOWBAT2] = { |
250 | .reg_offset = 0, |
251 | .mask = S5M8767_IRQ_LOWBAT2_MASK, |
252 | }, |
253 | [S5M8767_IRQ_LOWBAT1] = { |
254 | .reg_offset = 0, |
255 | .mask = S5M8767_IRQ_LOWBAT1_MASK, |
256 | }, |
257 | [S5M8767_IRQ_MRB] = { |
258 | .reg_offset = 1, |
259 | .mask = S5M8767_IRQ_MRB_MASK, |
260 | }, |
261 | [S5M8767_IRQ_DVSOK2] = { |
262 | .reg_offset = 1, |
263 | .mask = S5M8767_IRQ_DVSOK2_MASK, |
264 | }, |
265 | [S5M8767_IRQ_DVSOK3] = { |
266 | .reg_offset = 1, |
267 | .mask = S5M8767_IRQ_DVSOK3_MASK, |
268 | }, |
269 | [S5M8767_IRQ_DVSOK4] = { |
270 | .reg_offset = 1, |
271 | .mask = S5M8767_IRQ_DVSOK4_MASK, |
272 | }, |
273 | [S5M8767_IRQ_RTC60S] = { |
274 | .reg_offset = 2, |
275 | .mask = S5M8767_IRQ_RTC60S_MASK, |
276 | }, |
277 | [S5M8767_IRQ_RTCA1] = { |
278 | .reg_offset = 2, |
279 | .mask = S5M8767_IRQ_RTCA1_MASK, |
280 | }, |
281 | [S5M8767_IRQ_RTCA2] = { |
282 | .reg_offset = 2, |
283 | .mask = S5M8767_IRQ_RTCA2_MASK, |
284 | }, |
285 | [S5M8767_IRQ_SMPL] = { |
286 | .reg_offset = 2, |
287 | .mask = S5M8767_IRQ_SMPL_MASK, |
288 | }, |
289 | [S5M8767_IRQ_RTC1S] = { |
290 | .reg_offset = 2, |
291 | .mask = S5M8767_IRQ_RTC1S_MASK, |
292 | }, |
293 | [S5M8767_IRQ_WTSR] = { |
294 | .reg_offset = 2, |
295 | .mask = S5M8767_IRQ_WTSR_MASK, |
296 | }, |
297 | }; |
298 | |
299 | static const struct regmap_irq_chip s2mps11_irq_chip = { |
300 | .name = "s2mps11" , |
301 | .irqs = s2mps11_irqs, |
302 | .num_irqs = ARRAY_SIZE(s2mps11_irqs), |
303 | .num_regs = 3, |
304 | .status_base = S2MPS11_REG_INT1, |
305 | .mask_base = S2MPS11_REG_INT1M, |
306 | .ack_base = S2MPS11_REG_INT1, |
307 | }; |
308 | |
309 | #define S2MPS1X_IRQ_CHIP_COMMON_DATA \ |
310 | .irqs = s2mps14_irqs, \ |
311 | .num_irqs = ARRAY_SIZE(s2mps14_irqs), \ |
312 | .num_regs = 3, \ |
313 | .status_base = S2MPS14_REG_INT1, \ |
314 | .mask_base = S2MPS14_REG_INT1M, \ |
315 | .ack_base = S2MPS14_REG_INT1 \ |
316 | |
317 | static const struct regmap_irq_chip s2mps13_irq_chip = { |
318 | .name = "s2mps13" , |
319 | S2MPS1X_IRQ_CHIP_COMMON_DATA, |
320 | }; |
321 | |
322 | static const struct regmap_irq_chip s2mps14_irq_chip = { |
323 | .name = "s2mps14" , |
324 | S2MPS1X_IRQ_CHIP_COMMON_DATA, |
325 | }; |
326 | |
327 | static const struct regmap_irq_chip s2mps15_irq_chip = { |
328 | .name = "s2mps15" , |
329 | S2MPS1X_IRQ_CHIP_COMMON_DATA, |
330 | }; |
331 | |
332 | static const struct regmap_irq_chip s2mpu02_irq_chip = { |
333 | .name = "s2mpu02" , |
334 | .irqs = s2mpu02_irqs, |
335 | .num_irqs = ARRAY_SIZE(s2mpu02_irqs), |
336 | .num_regs = 3, |
337 | .status_base = S2MPU02_REG_INT1, |
338 | .mask_base = S2MPU02_REG_INT1M, |
339 | .ack_base = S2MPU02_REG_INT1, |
340 | }; |
341 | |
342 | static const struct regmap_irq_chip s5m8767_irq_chip = { |
343 | .name = "s5m8767" , |
344 | .irqs = s5m8767_irqs, |
345 | .num_irqs = ARRAY_SIZE(s5m8767_irqs), |
346 | .num_regs = 3, |
347 | .status_base = S5M8767_REG_INT1, |
348 | .mask_base = S5M8767_REG_INT1M, |
349 | .ack_base = S5M8767_REG_INT1, |
350 | }; |
351 | |
352 | int sec_irq_init(struct sec_pmic_dev *sec_pmic) |
353 | { |
354 | int ret = 0; |
355 | int type = sec_pmic->device_type; |
356 | const struct regmap_irq_chip *sec_irq_chip; |
357 | |
358 | if (!sec_pmic->irq) { |
359 | dev_warn(sec_pmic->dev, |
360 | "No interrupt specified, no interrupts\n" ); |
361 | return 0; |
362 | } |
363 | |
364 | switch (type) { |
365 | case S5M8767X: |
366 | sec_irq_chip = &s5m8767_irq_chip; |
367 | break; |
368 | case S2MPA01: |
369 | sec_irq_chip = &s2mps14_irq_chip; |
370 | break; |
371 | case S2MPS11X: |
372 | sec_irq_chip = &s2mps11_irq_chip; |
373 | break; |
374 | case S2MPS13X: |
375 | sec_irq_chip = &s2mps13_irq_chip; |
376 | break; |
377 | case S2MPS14X: |
378 | sec_irq_chip = &s2mps14_irq_chip; |
379 | break; |
380 | case S2MPS15X: |
381 | sec_irq_chip = &s2mps15_irq_chip; |
382 | break; |
383 | case S2MPU02: |
384 | sec_irq_chip = &s2mpu02_irq_chip; |
385 | break; |
386 | default: |
387 | dev_err(sec_pmic->dev, "Unknown device type %lu\n" , |
388 | sec_pmic->device_type); |
389 | return -EINVAL; |
390 | } |
391 | |
392 | ret = devm_regmap_add_irq_chip(dev: sec_pmic->dev, map: sec_pmic->regmap_pmic, |
393 | irq: sec_pmic->irq, IRQF_ONESHOT, |
394 | irq_base: 0, chip: sec_irq_chip, data: &sec_pmic->irq_data); |
395 | if (ret != 0) { |
396 | dev_err(sec_pmic->dev, "Failed to register IRQ chip: %d\n" , ret); |
397 | return ret; |
398 | } |
399 | |
400 | /* |
401 | * The rtc-s5m driver requests S2MPS14_IRQ_RTCA0 also for S2MPS11 |
402 | * so the interrupt number must be consistent. |
403 | */ |
404 | BUILD_BUG_ON(((enum s2mps14_irq)S2MPS11_IRQ_RTCA0) != S2MPS14_IRQ_RTCA0); |
405 | |
406 | return 0; |
407 | } |
408 | EXPORT_SYMBOL_GPL(sec_irq_init); |
409 | |
410 | MODULE_AUTHOR("Sangbeom Kim <sbkim73@samsung.com>" ); |
411 | MODULE_AUTHOR("Chanwoo Choi <cw00.choi@samsung.com>" ); |
412 | MODULE_AUTHOR("Krzysztof Kozlowski <krzk@kernel.org>" ); |
413 | MODULE_DESCRIPTION("Interrupt support for the S5M MFD" ); |
414 | MODULE_LICENSE("GPL" ); |
415 | |