xref: /linux/drivers/mfd/da9063-irq.c (revision 23c48a124b469cee2eb0c75e6d22d366d1caa118)
1 // SPDX-License-Identifier: GPL-2.0+
2 /* Interrupt support for Dialog DA9063
3  *
4  * Copyright 2012 Dialog Semiconductor Ltd.
5  * Copyright 2013 Philipp Zabel, Pengutronix
6  *
7  * Author: Michal Hajduk, Dialog Semiconductor
8  */
9 
10 #include <linux/kernel.h>
11 #include <linux/module.h>
12 #include <linux/irq.h>
13 #include <linux/mfd/core.h>
14 #include <linux/interrupt.h>
15 #include <linux/regmap.h>
16 #include <linux/mfd/da9063/core.h>
17 
18 #define	DA9063_REG_EVENT_A_OFFSET	0
19 #define	DA9063_REG_EVENT_B_OFFSET	1
20 #define	DA9063_REG_EVENT_C_OFFSET	2
21 #define	DA9063_REG_EVENT_D_OFFSET	3
22 
23 static const struct regmap_irq da9063_irqs[] = {
24 	/* DA9063 event A register */
25 	REGMAP_IRQ_REG(DA9063_IRQ_ONKEY,
26 		       DA9063_REG_EVENT_A_OFFSET, DA9063_M_ONKEY),
27 	REGMAP_IRQ_REG(DA9063_IRQ_ALARM,
28 		       DA9063_REG_EVENT_A_OFFSET, DA9063_M_ALARM),
29 	REGMAP_IRQ_REG(DA9063_IRQ_TICK,
30 		       DA9063_REG_EVENT_A_OFFSET, DA9063_M_TICK),
31 	REGMAP_IRQ_REG(DA9063_IRQ_ADC_RDY,
32 		       DA9063_REG_EVENT_A_OFFSET, DA9063_M_ADC_RDY),
33 	REGMAP_IRQ_REG(DA9063_IRQ_SEQ_RDY,
34 		       DA9063_REG_EVENT_A_OFFSET, DA9063_M_SEQ_RDY),
35 	/* DA9063 event B register */
36 	REGMAP_IRQ_REG(DA9063_IRQ_WAKE,
37 		       DA9063_REG_EVENT_B_OFFSET, DA9063_M_WAKE),
38 	REGMAP_IRQ_REG(DA9063_IRQ_TEMP,
39 		       DA9063_REG_EVENT_B_OFFSET, DA9063_M_TEMP),
40 	REGMAP_IRQ_REG(DA9063_IRQ_COMP_1V2,
41 		       DA9063_REG_EVENT_B_OFFSET, DA9063_M_COMP_1V2),
42 	REGMAP_IRQ_REG(DA9063_IRQ_LDO_LIM,
43 		       DA9063_REG_EVENT_B_OFFSET, DA9063_M_LDO_LIM),
44 	REGMAP_IRQ_REG(DA9063_IRQ_REG_UVOV,
45 		       DA9063_REG_EVENT_B_OFFSET, DA9063_M_UVOV),
46 	REGMAP_IRQ_REG(DA9063_IRQ_DVC_RDY,
47 		       DA9063_REG_EVENT_B_OFFSET, DA9063_M_DVC_RDY),
48 	REGMAP_IRQ_REG(DA9063_IRQ_VDD_MON,
49 		       DA9063_REG_EVENT_B_OFFSET, DA9063_M_VDD_MON),
50 	REGMAP_IRQ_REG(DA9063_IRQ_WARN,
51 		       DA9063_REG_EVENT_B_OFFSET, DA9063_M_VDD_WARN),
52 	/* DA9063 event C register */
53 	REGMAP_IRQ_REG(DA9063_IRQ_GPI0,
54 		       DA9063_REG_EVENT_C_OFFSET, DA9063_M_GPI0),
55 	REGMAP_IRQ_REG(DA9063_IRQ_GPI1,
56 		       DA9063_REG_EVENT_C_OFFSET, DA9063_M_GPI1),
57 	REGMAP_IRQ_REG(DA9063_IRQ_GPI2,
58 		       DA9063_REG_EVENT_C_OFFSET, DA9063_M_GPI2),
59 	REGMAP_IRQ_REG(DA9063_IRQ_GPI3,
60 		       DA9063_REG_EVENT_C_OFFSET, DA9063_M_GPI3),
61 	REGMAP_IRQ_REG(DA9063_IRQ_GPI4,
62 		       DA9063_REG_EVENT_C_OFFSET, DA9063_M_GPI4),
63 	REGMAP_IRQ_REG(DA9063_IRQ_GPI5,
64 		       DA9063_REG_EVENT_C_OFFSET, DA9063_M_GPI5),
65 	REGMAP_IRQ_REG(DA9063_IRQ_GPI6,
66 		       DA9063_REG_EVENT_C_OFFSET, DA9063_M_GPI6),
67 	REGMAP_IRQ_REG(DA9063_IRQ_GPI7,
68 		       DA9063_REG_EVENT_C_OFFSET, DA9063_M_GPI7),
69 	/* DA9063 event D register */
70 	REGMAP_IRQ_REG(DA9063_IRQ_GPI8,
71 		       DA9063_REG_EVENT_D_OFFSET, DA9063_M_GPI8),
72 	REGMAP_IRQ_REG(DA9063_IRQ_GPI9,
73 		       DA9063_REG_EVENT_D_OFFSET, DA9063_M_GPI9),
74 	REGMAP_IRQ_REG(DA9063_IRQ_GPI10,
75 		       DA9063_REG_EVENT_D_OFFSET, DA9063_M_GPI10),
76 	REGMAP_IRQ_REG(DA9063_IRQ_GPI11,
77 		       DA9063_REG_EVENT_D_OFFSET, DA9063_M_GPI11),
78 	REGMAP_IRQ_REG(DA9063_IRQ_GPI12,
79 		       DA9063_REG_EVENT_D_OFFSET, DA9063_M_GPI12),
80 	REGMAP_IRQ_REG(DA9063_IRQ_GPI13,
81 		       DA9063_REG_EVENT_D_OFFSET, DA9063_M_GPI13),
82 	REGMAP_IRQ_REG(DA9063_IRQ_GPI14,
83 		       DA9063_REG_EVENT_D_OFFSET, DA9063_M_GPI14),
84 	REGMAP_IRQ_REG(DA9063_IRQ_GPI15,
85 		       DA9063_REG_EVENT_D_OFFSET, DA9063_M_GPI15),
86 };
87 
88 static const struct regmap_irq_chip da9063_irq_chip = {
89 	.name = "da9063-irq",
90 	.irqs = da9063_irqs,
91 	.num_irqs = ARRAY_SIZE(da9063_irqs),
92 	.num_regs = 4,
93 	.status_base = DA9063_REG_EVENT_A,
94 	.mask_base = DA9063_REG_IRQ_MASK_A,
95 	.ack_base = DA9063_REG_EVENT_A,
96 	.init_ack_masked = true,
97 };
98 
99 static const struct regmap_irq da9063l_irqs[] = {
100 	/* DA9063 event A register */
101 	REGMAP_IRQ_REG(DA9063_IRQ_ONKEY,
102 		       DA9063_REG_EVENT_A_OFFSET, DA9063_M_ONKEY),
103 	REGMAP_IRQ_REG(DA9063_IRQ_ADC_RDY,
104 		       DA9063_REG_EVENT_A_OFFSET, DA9063_M_ADC_RDY),
105 	REGMAP_IRQ_REG(DA9063_IRQ_SEQ_RDY,
106 		       DA9063_REG_EVENT_A_OFFSET, DA9063_M_SEQ_RDY),
107 	/* DA9063 event B register */
108 	REGMAP_IRQ_REG(DA9063_IRQ_WAKE,
109 		       DA9063_REG_EVENT_B_OFFSET, DA9063_M_WAKE),
110 	REGMAP_IRQ_REG(DA9063_IRQ_TEMP,
111 		       DA9063_REG_EVENT_B_OFFSET, DA9063_M_TEMP),
112 	REGMAP_IRQ_REG(DA9063_IRQ_COMP_1V2,
113 		       DA9063_REG_EVENT_B_OFFSET, DA9063_M_COMP_1V2),
114 	REGMAP_IRQ_REG(DA9063_IRQ_LDO_LIM,
115 		       DA9063_REG_EVENT_B_OFFSET, DA9063_M_LDO_LIM),
116 	REGMAP_IRQ_REG(DA9063_IRQ_REG_UVOV,
117 		       DA9063_REG_EVENT_B_OFFSET, DA9063_M_UVOV),
118 	REGMAP_IRQ_REG(DA9063_IRQ_DVC_RDY,
119 		       DA9063_REG_EVENT_B_OFFSET, DA9063_M_DVC_RDY),
120 	REGMAP_IRQ_REG(DA9063_IRQ_VDD_MON,
121 		       DA9063_REG_EVENT_B_OFFSET, DA9063_M_VDD_MON),
122 	REGMAP_IRQ_REG(DA9063_IRQ_WARN,
123 		       DA9063_REG_EVENT_B_OFFSET, DA9063_M_VDD_WARN),
124 	/* DA9063 event C register */
125 	REGMAP_IRQ_REG(DA9063_IRQ_GPI0,
126 		       DA9063_REG_EVENT_C_OFFSET, DA9063_M_GPI0),
127 	REGMAP_IRQ_REG(DA9063_IRQ_GPI1,
128 		       DA9063_REG_EVENT_C_OFFSET, DA9063_M_GPI1),
129 	REGMAP_IRQ_REG(DA9063_IRQ_GPI2,
130 		       DA9063_REG_EVENT_C_OFFSET, DA9063_M_GPI2),
131 	REGMAP_IRQ_REG(DA9063_IRQ_GPI3,
132 		       DA9063_REG_EVENT_C_OFFSET, DA9063_M_GPI3),
133 	REGMAP_IRQ_REG(DA9063_IRQ_GPI4,
134 		       DA9063_REG_EVENT_C_OFFSET, DA9063_M_GPI4),
135 	REGMAP_IRQ_REG(DA9063_IRQ_GPI5,
136 		       DA9063_REG_EVENT_C_OFFSET, DA9063_M_GPI5),
137 	REGMAP_IRQ_REG(DA9063_IRQ_GPI6,
138 		       DA9063_REG_EVENT_C_OFFSET, DA9063_M_GPI6),
139 	REGMAP_IRQ_REG(DA9063_IRQ_GPI7,
140 		       DA9063_REG_EVENT_C_OFFSET, DA9063_M_GPI7),
141 	/* DA9063 event D register */
142 	REGMAP_IRQ_REG(DA9063_IRQ_GPI8,
143 		       DA9063_REG_EVENT_D_OFFSET, DA9063_M_GPI8),
144 	REGMAP_IRQ_REG(DA9063_IRQ_GPI9,
145 		       DA9063_REG_EVENT_D_OFFSET, DA9063_M_GPI9),
146 	REGMAP_IRQ_REG(DA9063_IRQ_GPI10,
147 		       DA9063_REG_EVENT_D_OFFSET, DA9063_M_GPI10),
148 	REGMAP_IRQ_REG(DA9063_IRQ_GPI11,
149 		       DA9063_REG_EVENT_D_OFFSET, DA9063_M_GPI11),
150 	REGMAP_IRQ_REG(DA9063_IRQ_GPI12,
151 		       DA9063_REG_EVENT_D_OFFSET, DA9063_M_GPI12),
152 	REGMAP_IRQ_REG(DA9063_IRQ_GPI13,
153 		       DA9063_REG_EVENT_D_OFFSET, DA9063_M_GPI13),
154 	REGMAP_IRQ_REG(DA9063_IRQ_GPI14,
155 		       DA9063_REG_EVENT_D_OFFSET, DA9063_M_GPI14),
156 	REGMAP_IRQ_REG(DA9063_IRQ_GPI15,
157 		       DA9063_REG_EVENT_D_OFFSET, DA9063_M_GPI15),
158 };
159 
160 static const struct regmap_irq_chip da9063l_irq_chip = {
161 	.name = "da9063l-irq",
162 	.irqs = da9063l_irqs,
163 	.num_irqs = ARRAY_SIZE(da9063l_irqs),
164 	.num_regs = 4,
165 	.status_base = DA9063_REG_EVENT_A,
166 	.mask_base = DA9063_REG_IRQ_MASK_A,
167 	.ack_base = DA9063_REG_EVENT_A,
168 	.init_ack_masked = true,
169 };
170 
171 int da9063_irq_init(struct da9063 *da9063)
172 {
173 	const struct regmap_irq_chip *irq_chip;
174 	int ret;
175 
176 	if (!da9063->chip_irq) {
177 		dev_err(da9063->dev, "No IRQ configured\n");
178 		return -EINVAL;
179 	}
180 
181 	if (da9063->type == PMIC_TYPE_DA9063)
182 		irq_chip = &da9063_irq_chip;
183 	else
184 		irq_chip = &da9063l_irq_chip;
185 
186 	ret = devm_regmap_add_irq_chip(da9063->dev, da9063->regmap,
187 			da9063->chip_irq,
188 			IRQF_TRIGGER_LOW | IRQF_ONESHOT | IRQF_SHARED,
189 			da9063->irq_base, irq_chip, &da9063->regmap_irq);
190 	if (ret) {
191 		dev_err(da9063->dev, "Failed to reguest IRQ %d: %d\n",
192 				da9063->chip_irq, ret);
193 		return ret;
194 	}
195 
196 	return 0;
197 }
198