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
27static 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_RTCA1] = {
65		.reg_offset = 1,
66		.mask = S2MPS11_IRQ_RTCA1_MASK,
67	},
68	[S2MPS11_IRQ_RTCA0] = {
69		.reg_offset = 1,
70		.mask = S2MPS11_IRQ_RTCA0_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
94static 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
165static 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
236static 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
307static 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
382static 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#define S2MPS1X_IRQ_CHIP_COMMON_DATA		\
393	.irqs = s2mps14_irqs,			\
394	.num_irqs = ARRAY_SIZE(s2mps14_irqs),	\
395	.num_regs = 3,				\
396	.status_base = S2MPS14_REG_INT1,	\
397	.mask_base = S2MPS14_REG_INT1M,		\
398	.ack_base = S2MPS14_REG_INT1		\
399
400static const struct regmap_irq_chip s2mps13_irq_chip = {
401	.name = "s2mps13",
402	S2MPS1X_IRQ_CHIP_COMMON_DATA,
403};
404
405static const struct regmap_irq_chip s2mps14_irq_chip = {
406	.name = "s2mps14",
407	S2MPS1X_IRQ_CHIP_COMMON_DATA,
408};
409
410static const struct regmap_irq_chip s2mpu02_irq_chip = {
411	.name = "s2mpu02",
412	.irqs = s2mpu02_irqs,
413	.num_irqs = ARRAY_SIZE(s2mpu02_irqs),
414	.num_regs = 3,
415	.status_base = S2MPU02_REG_INT1,
416	.mask_base = S2MPU02_REG_INT1M,
417	.ack_base = S2MPU02_REG_INT1,
418};
419
420static const struct regmap_irq_chip s5m8767_irq_chip = {
421	.name = "s5m8767",
422	.irqs = s5m8767_irqs,
423	.num_irqs = ARRAY_SIZE(s5m8767_irqs),
424	.num_regs = 3,
425	.status_base = S5M8767_REG_INT1,
426	.mask_base = S5M8767_REG_INT1M,
427	.ack_base = S5M8767_REG_INT1,
428};
429
430static const struct regmap_irq_chip s5m8763_irq_chip = {
431	.name = "s5m8763",
432	.irqs = s5m8763_irqs,
433	.num_irqs = ARRAY_SIZE(s5m8763_irqs),
434	.num_regs = 4,
435	.status_base = S5M8763_REG_IRQ1,
436	.mask_base = S5M8763_REG_IRQM1,
437	.ack_base = S5M8763_REG_IRQ1,
438};
439
440int sec_irq_init(struct sec_pmic_dev *sec_pmic)
441{
442	int ret = 0;
443	int type = sec_pmic->device_type;
444	const struct regmap_irq_chip *sec_irq_chip;
445
446	if (!sec_pmic->irq) {
447		dev_warn(sec_pmic->dev,
448			 "No interrupt specified, no interrupts\n");
449		sec_pmic->irq_base = 0;
450		return 0;
451	}
452
453	switch (type) {
454	case S5M8763X:
455		sec_irq_chip = &s5m8763_irq_chip;
456		break;
457	case S5M8767X:
458		sec_irq_chip = &s5m8767_irq_chip;
459		break;
460	case S2MPS11X:
461		sec_irq_chip = &s2mps11_irq_chip;
462		break;
463	case S2MPS13X:
464		sec_irq_chip = &s2mps13_irq_chip;
465		break;
466	case S2MPS14X:
467		sec_irq_chip = &s2mps14_irq_chip;
468		break;
469	case S2MPU02:
470		sec_irq_chip = &s2mpu02_irq_chip;
471		break;
472	default:
473		dev_err(sec_pmic->dev, "Unknown device type %lu\n",
474			sec_pmic->device_type);
475		return -EINVAL;
476	}
477
478	ret = regmap_add_irq_chip(sec_pmic->regmap_pmic, sec_pmic->irq,
479			  IRQF_TRIGGER_FALLING | IRQF_ONESHOT,
480			  sec_pmic->irq_base, sec_irq_chip,
481			  &sec_pmic->irq_data);
482	if (ret != 0) {
483		dev_err(sec_pmic->dev, "Failed to register IRQ chip: %d\n", ret);
484		return ret;
485	}
486
487	/*
488	 * The rtc-s5m driver requests S2MPS14_IRQ_RTCA0 also for S2MPS11
489	 * so the interrupt number must be consistent.
490	 */
491	BUILD_BUG_ON(((enum s2mps14_irq)S2MPS11_IRQ_RTCA0) != S2MPS14_IRQ_RTCA0);
492
493	return 0;
494}
495
496void sec_irq_exit(struct sec_pmic_dev *sec_pmic)
497{
498	regmap_del_irq_chip(sec_pmic->irq, sec_pmic->irq_data);
499}
500