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 
sec_irq_init(struct sec_pmic_dev * sec_pmic)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(sec_pmic->dev, sec_pmic->regmap_pmic,
393 				       sec_pmic->irq, IRQF_ONESHOT,
394 				       0, sec_irq_chip, &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