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(dev: da9063->dev, map: da9063->regmap, |
187 | irq: da9063->chip_irq, |
188 | IRQF_TRIGGER_LOW | IRQF_ONESHOT | IRQF_SHARED, |
189 | irq_base: da9063->irq_base, chip: irq_chip, data: &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 | |