xref: /openbmc/linux/drivers/mfd/sec-irq.c (revision d2999e1b)
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/s5m8763.h>
24 #include <linux/mfd/samsung/s5m8767.h>
25 
26 static const struct regmap_irq s2mps11_irqs[] = {
27 	[S2MPS11_IRQ_PWRONF] = {
28 		.reg_offset = 0,
29 		.mask = S2MPS11_IRQ_PWRONF_MASK,
30 	},
31 	[S2MPS11_IRQ_PWRONR] = {
32 		.reg_offset = 0,
33 		.mask = S2MPS11_IRQ_PWRONR_MASK,
34 	},
35 	[S2MPS11_IRQ_JIGONBF] = {
36 		.reg_offset = 0,
37 		.mask = S2MPS11_IRQ_JIGONBF_MASK,
38 	},
39 	[S2MPS11_IRQ_JIGONBR] = {
40 		.reg_offset = 0,
41 		.mask = S2MPS11_IRQ_JIGONBR_MASK,
42 	},
43 	[S2MPS11_IRQ_ACOKBF] = {
44 		.reg_offset = 0,
45 		.mask = S2MPS11_IRQ_ACOKBF_MASK,
46 	},
47 	[S2MPS11_IRQ_ACOKBR] = {
48 		.reg_offset = 0,
49 		.mask = S2MPS11_IRQ_ACOKBR_MASK,
50 	},
51 	[S2MPS11_IRQ_PWRON1S] = {
52 		.reg_offset = 0,
53 		.mask = S2MPS11_IRQ_PWRON1S_MASK,
54 	},
55 	[S2MPS11_IRQ_MRB] = {
56 		.reg_offset = 0,
57 		.mask = S2MPS11_IRQ_MRB_MASK,
58 	},
59 	[S2MPS11_IRQ_RTC60S] = {
60 		.reg_offset = 1,
61 		.mask = S2MPS11_IRQ_RTC60S_MASK,
62 	},
63 	[S2MPS11_IRQ_RTCA0] = {
64 		.reg_offset = 1,
65 		.mask = S2MPS11_IRQ_RTCA0_MASK,
66 	},
67 	[S2MPS11_IRQ_RTCA1] = {
68 		.reg_offset = 1,
69 		.mask = S2MPS11_IRQ_RTCA1_MASK,
70 	},
71 	[S2MPS11_IRQ_SMPL] = {
72 		.reg_offset = 1,
73 		.mask = S2MPS11_IRQ_SMPL_MASK,
74 	},
75 	[S2MPS11_IRQ_RTC1S] = {
76 		.reg_offset = 1,
77 		.mask = S2MPS11_IRQ_RTC1S_MASK,
78 	},
79 	[S2MPS11_IRQ_WTSR] = {
80 		.reg_offset = 1,
81 		.mask = S2MPS11_IRQ_WTSR_MASK,
82 	},
83 	[S2MPS11_IRQ_INT120C] = {
84 		.reg_offset = 2,
85 		.mask = S2MPS11_IRQ_INT120C_MASK,
86 	},
87 	[S2MPS11_IRQ_INT140C] = {
88 		.reg_offset = 2,
89 		.mask = S2MPS11_IRQ_INT140C_MASK,
90 	},
91 };
92 
93 static const struct regmap_irq s2mps14_irqs[] = {
94 	[S2MPS14_IRQ_PWRONF] = {
95 		.reg_offset = 0,
96 		.mask = S2MPS11_IRQ_PWRONF_MASK,
97 	},
98 	[S2MPS14_IRQ_PWRONR] = {
99 		.reg_offset = 0,
100 		.mask = S2MPS11_IRQ_PWRONR_MASK,
101 	},
102 	[S2MPS14_IRQ_JIGONBF] = {
103 		.reg_offset = 0,
104 		.mask = S2MPS11_IRQ_JIGONBF_MASK,
105 	},
106 	[S2MPS14_IRQ_JIGONBR] = {
107 		.reg_offset = 0,
108 		.mask = S2MPS11_IRQ_JIGONBR_MASK,
109 	},
110 	[S2MPS14_IRQ_ACOKBF] = {
111 		.reg_offset = 0,
112 		.mask = S2MPS11_IRQ_ACOKBF_MASK,
113 	},
114 	[S2MPS14_IRQ_ACOKBR] = {
115 		.reg_offset = 0,
116 		.mask = S2MPS11_IRQ_ACOKBR_MASK,
117 	},
118 	[S2MPS14_IRQ_PWRON1S] = {
119 		.reg_offset = 0,
120 		.mask = S2MPS11_IRQ_PWRON1S_MASK,
121 	},
122 	[S2MPS14_IRQ_MRB] = {
123 		.reg_offset = 0,
124 		.mask = S2MPS11_IRQ_MRB_MASK,
125 	},
126 	[S2MPS14_IRQ_RTC60S] = {
127 		.reg_offset = 1,
128 		.mask = S2MPS11_IRQ_RTC60S_MASK,
129 	},
130 	[S2MPS14_IRQ_RTCA1] = {
131 		.reg_offset = 1,
132 		.mask = S2MPS11_IRQ_RTCA1_MASK,
133 	},
134 	[S2MPS14_IRQ_RTCA0] = {
135 		.reg_offset = 1,
136 		.mask = S2MPS11_IRQ_RTCA0_MASK,
137 	},
138 	[S2MPS14_IRQ_SMPL] = {
139 		.reg_offset = 1,
140 		.mask = S2MPS11_IRQ_SMPL_MASK,
141 	},
142 	[S2MPS14_IRQ_RTC1S] = {
143 		.reg_offset = 1,
144 		.mask = S2MPS11_IRQ_RTC1S_MASK,
145 	},
146 	[S2MPS14_IRQ_WTSR] = {
147 		.reg_offset = 1,
148 		.mask = S2MPS11_IRQ_WTSR_MASK,
149 	},
150 	[S2MPS14_IRQ_INT120C] = {
151 		.reg_offset = 2,
152 		.mask = S2MPS11_IRQ_INT120C_MASK,
153 	},
154 	[S2MPS14_IRQ_INT140C] = {
155 		.reg_offset = 2,
156 		.mask = S2MPS11_IRQ_INT140C_MASK,
157 	},
158 	[S2MPS14_IRQ_TSD] = {
159 		.reg_offset = 2,
160 		.mask = S2MPS14_IRQ_TSD_MASK,
161 	},
162 };
163 
164 static const struct regmap_irq s5m8767_irqs[] = {
165 	[S5M8767_IRQ_PWRR] = {
166 		.reg_offset = 0,
167 		.mask = S5M8767_IRQ_PWRR_MASK,
168 	},
169 	[S5M8767_IRQ_PWRF] = {
170 		.reg_offset = 0,
171 		.mask = S5M8767_IRQ_PWRF_MASK,
172 	},
173 	[S5M8767_IRQ_PWR1S] = {
174 		.reg_offset = 0,
175 		.mask = S5M8767_IRQ_PWR1S_MASK,
176 	},
177 	[S5M8767_IRQ_JIGR] = {
178 		.reg_offset = 0,
179 		.mask = S5M8767_IRQ_JIGR_MASK,
180 	},
181 	[S5M8767_IRQ_JIGF] = {
182 		.reg_offset = 0,
183 		.mask = S5M8767_IRQ_JIGF_MASK,
184 	},
185 	[S5M8767_IRQ_LOWBAT2] = {
186 		.reg_offset = 0,
187 		.mask = S5M8767_IRQ_LOWBAT2_MASK,
188 	},
189 	[S5M8767_IRQ_LOWBAT1] = {
190 		.reg_offset = 0,
191 		.mask = S5M8767_IRQ_LOWBAT1_MASK,
192 	},
193 	[S5M8767_IRQ_MRB] = {
194 		.reg_offset = 1,
195 		.mask = S5M8767_IRQ_MRB_MASK,
196 	},
197 	[S5M8767_IRQ_DVSOK2] = {
198 		.reg_offset = 1,
199 		.mask = S5M8767_IRQ_DVSOK2_MASK,
200 	},
201 	[S5M8767_IRQ_DVSOK3] = {
202 		.reg_offset = 1,
203 		.mask = S5M8767_IRQ_DVSOK3_MASK,
204 	},
205 	[S5M8767_IRQ_DVSOK4] = {
206 		.reg_offset = 1,
207 		.mask = S5M8767_IRQ_DVSOK4_MASK,
208 	},
209 	[S5M8767_IRQ_RTC60S] = {
210 		.reg_offset = 2,
211 		.mask = S5M8767_IRQ_RTC60S_MASK,
212 	},
213 	[S5M8767_IRQ_RTCA1] = {
214 		.reg_offset = 2,
215 		.mask = S5M8767_IRQ_RTCA1_MASK,
216 	},
217 	[S5M8767_IRQ_RTCA2] = {
218 		.reg_offset = 2,
219 		.mask = S5M8767_IRQ_RTCA2_MASK,
220 	},
221 	[S5M8767_IRQ_SMPL] = {
222 		.reg_offset = 2,
223 		.mask = S5M8767_IRQ_SMPL_MASK,
224 	},
225 	[S5M8767_IRQ_RTC1S] = {
226 		.reg_offset = 2,
227 		.mask = S5M8767_IRQ_RTC1S_MASK,
228 	},
229 	[S5M8767_IRQ_WTSR] = {
230 		.reg_offset = 2,
231 		.mask = S5M8767_IRQ_WTSR_MASK,
232 	},
233 };
234 
235 static const struct regmap_irq s5m8763_irqs[] = {
236 	[S5M8763_IRQ_DCINF] = {
237 		.reg_offset = 0,
238 		.mask = S5M8763_IRQ_DCINF_MASK,
239 	},
240 	[S5M8763_IRQ_DCINR] = {
241 		.reg_offset = 0,
242 		.mask = S5M8763_IRQ_DCINR_MASK,
243 	},
244 	[S5M8763_IRQ_JIGF] = {
245 		.reg_offset = 0,
246 		.mask = S5M8763_IRQ_JIGF_MASK,
247 	},
248 	[S5M8763_IRQ_JIGR] = {
249 		.reg_offset = 0,
250 		.mask = S5M8763_IRQ_JIGR_MASK,
251 	},
252 	[S5M8763_IRQ_PWRONF] = {
253 		.reg_offset = 0,
254 		.mask = S5M8763_IRQ_PWRONF_MASK,
255 	},
256 	[S5M8763_IRQ_PWRONR] = {
257 		.reg_offset = 0,
258 		.mask = S5M8763_IRQ_PWRONR_MASK,
259 	},
260 	[S5M8763_IRQ_WTSREVNT] = {
261 		.reg_offset = 1,
262 		.mask = S5M8763_IRQ_WTSREVNT_MASK,
263 	},
264 	[S5M8763_IRQ_SMPLEVNT] = {
265 		.reg_offset = 1,
266 		.mask = S5M8763_IRQ_SMPLEVNT_MASK,
267 	},
268 	[S5M8763_IRQ_ALARM1] = {
269 		.reg_offset = 1,
270 		.mask = S5M8763_IRQ_ALARM1_MASK,
271 	},
272 	[S5M8763_IRQ_ALARM0] = {
273 		.reg_offset = 1,
274 		.mask = S5M8763_IRQ_ALARM0_MASK,
275 	},
276 	[S5M8763_IRQ_ONKEY1S] = {
277 		.reg_offset = 2,
278 		.mask = S5M8763_IRQ_ONKEY1S_MASK,
279 	},
280 	[S5M8763_IRQ_TOPOFFR] = {
281 		.reg_offset = 2,
282 		.mask = S5M8763_IRQ_TOPOFFR_MASK,
283 	},
284 	[S5M8763_IRQ_DCINOVPR] = {
285 		.reg_offset = 2,
286 		.mask = S5M8763_IRQ_DCINOVPR_MASK,
287 	},
288 	[S5M8763_IRQ_CHGRSTF] = {
289 		.reg_offset = 2,
290 		.mask = S5M8763_IRQ_CHGRSTF_MASK,
291 	},
292 	[S5M8763_IRQ_DONER] = {
293 		.reg_offset = 2,
294 		.mask = S5M8763_IRQ_DONER_MASK,
295 	},
296 	[S5M8763_IRQ_CHGFAULT] = {
297 		.reg_offset = 2,
298 		.mask = S5M8763_IRQ_CHGFAULT_MASK,
299 	},
300 	[S5M8763_IRQ_LOBAT1] = {
301 		.reg_offset = 3,
302 		.mask = S5M8763_IRQ_LOBAT1_MASK,
303 	},
304 	[S5M8763_IRQ_LOBAT2] = {
305 		.reg_offset = 3,
306 		.mask = S5M8763_IRQ_LOBAT2_MASK,
307 	},
308 };
309 
310 static const struct regmap_irq_chip s2mps11_irq_chip = {
311 	.name = "s2mps11",
312 	.irqs = s2mps11_irqs,
313 	.num_irqs = ARRAY_SIZE(s2mps11_irqs),
314 	.num_regs = 3,
315 	.status_base = S2MPS11_REG_INT1,
316 	.mask_base = S2MPS11_REG_INT1M,
317 	.ack_base = S2MPS11_REG_INT1,
318 };
319 
320 static const struct regmap_irq_chip s2mps14_irq_chip = {
321 	.name = "s2mps14",
322 	.irqs = s2mps14_irqs,
323 	.num_irqs = ARRAY_SIZE(s2mps14_irqs),
324 	.num_regs = 3,
325 	.status_base = S2MPS14_REG_INT1,
326 	.mask_base = S2MPS14_REG_INT1M,
327 	.ack_base = S2MPS14_REG_INT1,
328 };
329 
330 static const struct regmap_irq_chip s5m8767_irq_chip = {
331 	.name = "s5m8767",
332 	.irqs = s5m8767_irqs,
333 	.num_irqs = ARRAY_SIZE(s5m8767_irqs),
334 	.num_regs = 3,
335 	.status_base = S5M8767_REG_INT1,
336 	.mask_base = S5M8767_REG_INT1M,
337 	.ack_base = S5M8767_REG_INT1,
338 };
339 
340 static const struct regmap_irq_chip s5m8763_irq_chip = {
341 	.name = "s5m8763",
342 	.irqs = s5m8763_irqs,
343 	.num_irqs = ARRAY_SIZE(s5m8763_irqs),
344 	.num_regs = 4,
345 	.status_base = S5M8763_REG_IRQ1,
346 	.mask_base = S5M8763_REG_IRQM1,
347 	.ack_base = S5M8763_REG_IRQ1,
348 };
349 
350 int sec_irq_init(struct sec_pmic_dev *sec_pmic)
351 {
352 	int ret = 0;
353 	int type = sec_pmic->device_type;
354 
355 	if (!sec_pmic->irq) {
356 		dev_warn(sec_pmic->dev,
357 			 "No interrupt specified, no interrupts\n");
358 		sec_pmic->irq_base = 0;
359 		return 0;
360 	}
361 
362 	switch (type) {
363 	case S5M8763X:
364 		ret = regmap_add_irq_chip(sec_pmic->regmap_pmic, sec_pmic->irq,
365 				  IRQF_TRIGGER_FALLING | IRQF_ONESHOT,
366 				  sec_pmic->irq_base, &s5m8763_irq_chip,
367 				  &sec_pmic->irq_data);
368 		break;
369 	case S5M8767X:
370 		ret = regmap_add_irq_chip(sec_pmic->regmap_pmic, sec_pmic->irq,
371 				  IRQF_TRIGGER_FALLING | IRQF_ONESHOT,
372 				  sec_pmic->irq_base, &s5m8767_irq_chip,
373 				  &sec_pmic->irq_data);
374 		break;
375 	case S2MPS11X:
376 		ret = regmap_add_irq_chip(sec_pmic->regmap_pmic, sec_pmic->irq,
377 				  IRQF_TRIGGER_FALLING | IRQF_ONESHOT,
378 				  sec_pmic->irq_base, &s2mps11_irq_chip,
379 				  &sec_pmic->irq_data);
380 		break;
381 	case S2MPS14X:
382 		ret = regmap_add_irq_chip(sec_pmic->regmap_pmic, sec_pmic->irq,
383 				  IRQF_TRIGGER_FALLING | IRQF_ONESHOT,
384 				  sec_pmic->irq_base, &s2mps14_irq_chip,
385 				  &sec_pmic->irq_data);
386 		break;
387 	default:
388 		dev_err(sec_pmic->dev, "Unknown device type %lu\n",
389 			sec_pmic->device_type);
390 		return -EINVAL;
391 	}
392 
393 	if (ret != 0) {
394 		dev_err(sec_pmic->dev, "Failed to register IRQ chip: %d\n", ret);
395 		return ret;
396 	}
397 
398 	return 0;
399 }
400 
401 void sec_irq_exit(struct sec_pmic_dev *sec_pmic)
402 {
403 	regmap_del_irq_chip(sec_pmic->irq, sec_pmic->irq_data);
404 }
405