aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSangbeom Kim <sbkim73@samsung.com>2012-07-11 08:08:11 -0400
committerSamuel Ortiz <sameo@linux.intel.com>2012-07-16 08:31:59 -0400
commit6445b84abf91549d8568fb5d9155447e6dba86cc (patch)
tree07b8341d4360f80630146cb21c171d6e518202d9
parent9b6d1343068d87f06c8dabf6628a30ea38082eb0 (diff)
mfd: Add s2mps11 irq driver
This patch support irq handling driver for s2mps11. As this patch use regmap_irq, s5m8767 and s5m8763 are modified with regmap_irq. Signed-off-by: Sangbeom Kim <sbkim73@samsung.com> Signed-off-by: Samuel Ortiz <sameo@linux.intel.com>
-rw-r--r--drivers/mfd/Kconfig1
-rw-r--r--drivers/mfd/sec-irq.c477
-rw-r--r--include/linux/mfd/samsung/core.h2
-rw-r--r--include/linux/mfd/samsung/irq.h42
4 files changed, 193 insertions, 329 deletions
diff --git a/drivers/mfd/Kconfig b/drivers/mfd/Kconfig
index bad68f82772a..3c263a57b760 100644
--- a/drivers/mfd/Kconfig
+++ b/drivers/mfd/Kconfig
@@ -513,6 +513,7 @@ config MFD_SEC_CORE
513 depends on I2C=y && GENERIC_HARDIRQS 513 depends on I2C=y && GENERIC_HARDIRQS
514 select MFD_CORE 514 select MFD_CORE
515 select REGMAP_I2C 515 select REGMAP_I2C
516 select REGMAP_IRQ
516 help 517 help
517 Support for the Samsung Electronics MFD series. 518 Support for the Samsung Electronics MFD series.
518 This driver provides common support for accessing the device, 519 This driver provides common support for accessing the device,
diff --git a/drivers/mfd/sec-irq.c b/drivers/mfd/sec-irq.c
index da5ec5b2ecce..c901fa50fea1 100644
--- a/drivers/mfd/sec-irq.c
+++ b/drivers/mfd/sec-irq.c
@@ -14,351 +14,260 @@
14#include <linux/device.h> 14#include <linux/device.h>
15#include <linux/interrupt.h> 15#include <linux/interrupt.h>
16#include <linux/irq.h> 16#include <linux/irq.h>
17#include <linux/regmap.h>
18
17#include <linux/mfd/samsung/core.h> 19#include <linux/mfd/samsung/core.h>
18#include <linux/mfd/samsung/irq.h> 20#include <linux/mfd/samsung/irq.h>
21#include <linux/mfd/samsung/s2mps11.h>
19#include <linux/mfd/samsung/s5m8763.h> 22#include <linux/mfd/samsung/s5m8763.h>
20#include <linux/mfd/samsung/s5m8767.h> 23#include <linux/mfd/samsung/s5m8767.h>
21 24
22struct sec_irq_data { 25static struct regmap_irq s2mps11_irqs[] = {
23 int reg; 26 [S2MPS11_IRQ_PWRONF] = {
24 int mask; 27 .reg_offset = 1,
28 .mask = S2MPS11_IRQ_PWRONF_MASK,
29 },
30 [S2MPS11_IRQ_PWRONR] = {
31 .reg_offset = 1,
32 .mask = S2MPS11_IRQ_PWRONR_MASK,
33 },
34 [S2MPS11_IRQ_JIGONBF] = {
35 .reg_offset = 1,
36 .mask = S2MPS11_IRQ_JIGONBF_MASK,
37 },
38 [S2MPS11_IRQ_JIGONBR] = {
39 .reg_offset = 1,
40 .mask = S2MPS11_IRQ_JIGONBR_MASK,
41 },
42 [S2MPS11_IRQ_ACOKBF] = {
43 .reg_offset = 1,
44 .mask = S2MPS11_IRQ_ACOKBF_MASK,
45 },
46 [S2MPS11_IRQ_ACOKBR] = {
47 .reg_offset = 1,
48 .mask = S2MPS11_IRQ_ACOKBR_MASK,
49 },
50 [S2MPS11_IRQ_PWRON1S] = {
51 .reg_offset = 1,
52 .mask = S2MPS11_IRQ_PWRON1S_MASK,
53 },
54 [S2MPS11_IRQ_MRB] = {
55 .reg_offset = 1,
56 .mask = S2MPS11_IRQ_MRB_MASK,
57 },
58 [S2MPS11_IRQ_RTC60S] = {
59 .reg_offset = 2,
60 .mask = S2MPS11_IRQ_RTC60S_MASK,
61 },
62 [S2MPS11_IRQ_RTCA1] = {
63 .reg_offset = 2,
64 .mask = S2MPS11_IRQ_RTCA1_MASK,
65 },
66 [S2MPS11_IRQ_RTCA2] = {
67 .reg_offset = 2,
68 .mask = S2MPS11_IRQ_RTCA2_MASK,
69 },
70 [S2MPS11_IRQ_SMPL] = {
71 .reg_offset = 2,
72 .mask = S2MPS11_IRQ_SMPL_MASK,
73 },
74 [S2MPS11_IRQ_RTC1S] = {
75 .reg_offset = 2,
76 .mask = S2MPS11_IRQ_RTC1S_MASK,
77 },
78 [S2MPS11_IRQ_WTSR] = {
79 .reg_offset = 2,
80 .mask = S2MPS11_IRQ_WTSR_MASK,
81 },
82 [S2MPS11_IRQ_INT120C] = {
83 .reg_offset = 3,
84 .mask = S2MPS11_IRQ_INT120C_MASK,
85 },
86 [S2MPS11_IRQ_INT140C] = {
87 .reg_offset = 3,
88 .mask = S2MPS11_IRQ_INT140C_MASK,
89 },
25}; 90};
26 91
27static struct sec_irq_data s5m8767_irqs[] = { 92
93static struct regmap_irq s5m8767_irqs[] = {
28 [S5M8767_IRQ_PWRR] = { 94 [S5M8767_IRQ_PWRR] = {
29 .reg = 1, 95 .reg_offset = 1,
30 .mask = S5M8767_IRQ_PWRR_MASK, 96 .mask = S5M8767_IRQ_PWRR_MASK,
31 }, 97 },
32 [S5M8767_IRQ_PWRF] = { 98 [S5M8767_IRQ_PWRF] = {
33 .reg = 1, 99 .reg_offset = 1,
34 .mask = S5M8767_IRQ_PWRF_MASK, 100 .mask = S5M8767_IRQ_PWRF_MASK,
35 }, 101 },
36 [S5M8767_IRQ_PWR1S] = { 102 [S5M8767_IRQ_PWR1S] = {
37 .reg = 1, 103 .reg_offset = 1,
38 .mask = S5M8767_IRQ_PWR1S_MASK, 104 .mask = S5M8767_IRQ_PWR1S_MASK,
39 }, 105 },
40 [S5M8767_IRQ_JIGR] = { 106 [S5M8767_IRQ_JIGR] = {
41 .reg = 1, 107 .reg_offset = 1,
42 .mask = S5M8767_IRQ_JIGR_MASK, 108 .mask = S5M8767_IRQ_JIGR_MASK,
43 }, 109 },
44 [S5M8767_IRQ_JIGF] = { 110 [S5M8767_IRQ_JIGF] = {
45 .reg = 1, 111 .reg_offset = 1,
46 .mask = S5M8767_IRQ_JIGF_MASK, 112 .mask = S5M8767_IRQ_JIGF_MASK,
47 }, 113 },
48 [S5M8767_IRQ_LOWBAT2] = { 114 [S5M8767_IRQ_LOWBAT2] = {
49 .reg = 1, 115 .reg_offset = 1,
50 .mask = S5M8767_IRQ_LOWBAT2_MASK, 116 .mask = S5M8767_IRQ_LOWBAT2_MASK,
51 }, 117 },
52 [S5M8767_IRQ_LOWBAT1] = { 118 [S5M8767_IRQ_LOWBAT1] = {
53 .reg = 1, 119 .reg_offset = 1,
54 .mask = S5M8767_IRQ_LOWBAT1_MASK, 120 .mask = S5M8767_IRQ_LOWBAT1_MASK,
55 }, 121 },
56 [S5M8767_IRQ_MRB] = { 122 [S5M8767_IRQ_MRB] = {
57 .reg = 2, 123 .reg_offset = 2,
58 .mask = S5M8767_IRQ_MRB_MASK, 124 .mask = S5M8767_IRQ_MRB_MASK,
59 }, 125 },
60 [S5M8767_IRQ_DVSOK2] = { 126 [S5M8767_IRQ_DVSOK2] = {
61 .reg = 2, 127 .reg_offset = 2,
62 .mask = S5M8767_IRQ_DVSOK2_MASK, 128 .mask = S5M8767_IRQ_DVSOK2_MASK,
63 }, 129 },
64 [S5M8767_IRQ_DVSOK3] = { 130 [S5M8767_IRQ_DVSOK3] = {
65 .reg = 2, 131 .reg_offset = 2,
66 .mask = S5M8767_IRQ_DVSOK3_MASK, 132 .mask = S5M8767_IRQ_DVSOK3_MASK,
67 }, 133 },
68 [S5M8767_IRQ_DVSOK4] = { 134 [S5M8767_IRQ_DVSOK4] = {
69 .reg = 2, 135 .reg_offset = 2,
70 .mask = S5M8767_IRQ_DVSOK4_MASK, 136 .mask = S5M8767_IRQ_DVSOK4_MASK,
71 }, 137 },
72 [S5M8767_IRQ_RTC60S] = { 138 [S5M8767_IRQ_RTC60S] = {
73 .reg = 3, 139 .reg_offset = 3,
74 .mask = S5M8767_IRQ_RTC60S_MASK, 140 .mask = S5M8767_IRQ_RTC60S_MASK,
75 }, 141 },
76 [S5M8767_IRQ_RTCA1] = { 142 [S5M8767_IRQ_RTCA1] = {
77 .reg = 3, 143 .reg_offset = 3,
78 .mask = S5M8767_IRQ_RTCA1_MASK, 144 .mask = S5M8767_IRQ_RTCA1_MASK,
79 }, 145 },
80 [S5M8767_IRQ_RTCA2] = { 146 [S5M8767_IRQ_RTCA2] = {
81 .reg = 3, 147 .reg_offset = 3,
82 .mask = S5M8767_IRQ_RTCA2_MASK, 148 .mask = S5M8767_IRQ_RTCA2_MASK,
83 }, 149 },
84 [S5M8767_IRQ_SMPL] = { 150 [S5M8767_IRQ_SMPL] = {
85 .reg = 3, 151 .reg_offset = 3,
86 .mask = S5M8767_IRQ_SMPL_MASK, 152 .mask = S5M8767_IRQ_SMPL_MASK,
87 }, 153 },
88 [S5M8767_IRQ_RTC1S] = { 154 [S5M8767_IRQ_RTC1S] = {
89 .reg = 3, 155 .reg_offset = 3,
90 .mask = S5M8767_IRQ_RTC1S_MASK, 156 .mask = S5M8767_IRQ_RTC1S_MASK,
91 }, 157 },
92 [S5M8767_IRQ_WTSR] = { 158 [S5M8767_IRQ_WTSR] = {
93 .reg = 3, 159 .reg_offset = 3,
94 .mask = S5M8767_IRQ_WTSR_MASK, 160 .mask = S5M8767_IRQ_WTSR_MASK,
95 }, 161 },
96}; 162};
97 163
98static struct sec_irq_data s5m8763_irqs[] = { 164static struct regmap_irq s5m8763_irqs[] = {
99 [S5M8763_IRQ_DCINF] = { 165 [S5M8763_IRQ_DCINF] = {
100 .reg = 1, 166 .reg_offset = 1,
101 .mask = S5M8763_IRQ_DCINF_MASK, 167 .mask = S5M8763_IRQ_DCINF_MASK,
102 }, 168 },
103 [S5M8763_IRQ_DCINR] = { 169 [S5M8763_IRQ_DCINR] = {
104 .reg = 1, 170 .reg_offset = 1,
105 .mask = S5M8763_IRQ_DCINR_MASK, 171 .mask = S5M8763_IRQ_DCINR_MASK,
106 }, 172 },
107 [S5M8763_IRQ_JIGF] = { 173 [S5M8763_IRQ_JIGF] = {
108 .reg = 1, 174 .reg_offset = 1,
109 .mask = S5M8763_IRQ_JIGF_MASK, 175 .mask = S5M8763_IRQ_JIGF_MASK,
110 }, 176 },
111 [S5M8763_IRQ_JIGR] = { 177 [S5M8763_IRQ_JIGR] = {
112 .reg = 1, 178 .reg_offset = 1,
113 .mask = S5M8763_IRQ_JIGR_MASK, 179 .mask = S5M8763_IRQ_JIGR_MASK,
114 }, 180 },
115 [S5M8763_IRQ_PWRONF] = { 181 [S5M8763_IRQ_PWRONF] = {
116 .reg = 1, 182 .reg_offset = 1,
117 .mask = S5M8763_IRQ_PWRONF_MASK, 183 .mask = S5M8763_IRQ_PWRONF_MASK,
118 }, 184 },
119 [S5M8763_IRQ_PWRONR] = { 185 [S5M8763_IRQ_PWRONR] = {
120 .reg = 1, 186 .reg_offset = 1,
121 .mask = S5M8763_IRQ_PWRONR_MASK, 187 .mask = S5M8763_IRQ_PWRONR_MASK,
122 }, 188 },
123 [S5M8763_IRQ_WTSREVNT] = { 189 [S5M8763_IRQ_WTSREVNT] = {
124 .reg = 2, 190 .reg_offset = 2,
125 .mask = S5M8763_IRQ_WTSREVNT_MASK, 191 .mask = S5M8763_IRQ_WTSREVNT_MASK,
126 }, 192 },
127 [S5M8763_IRQ_SMPLEVNT] = { 193 [S5M8763_IRQ_SMPLEVNT] = {
128 .reg = 2, 194 .reg_offset = 2,
129 .mask = S5M8763_IRQ_SMPLEVNT_MASK, 195 .mask = S5M8763_IRQ_SMPLEVNT_MASK,
130 }, 196 },
131 [S5M8763_IRQ_ALARM1] = { 197 [S5M8763_IRQ_ALARM1] = {
132 .reg = 2, 198 .reg_offset = 2,
133 .mask = S5M8763_IRQ_ALARM1_MASK, 199 .mask = S5M8763_IRQ_ALARM1_MASK,
134 }, 200 },
135 [S5M8763_IRQ_ALARM0] = { 201 [S5M8763_IRQ_ALARM0] = {
136 .reg = 2, 202 .reg_offset = 2,
137 .mask = S5M8763_IRQ_ALARM0_MASK, 203 .mask = S5M8763_IRQ_ALARM0_MASK,
138 }, 204 },
139 [S5M8763_IRQ_ONKEY1S] = { 205 [S5M8763_IRQ_ONKEY1S] = {
140 .reg = 3, 206 .reg_offset = 3,
141 .mask = S5M8763_IRQ_ONKEY1S_MASK, 207 .mask = S5M8763_IRQ_ONKEY1S_MASK,
142 }, 208 },
143 [S5M8763_IRQ_TOPOFFR] = { 209 [S5M8763_IRQ_TOPOFFR] = {
144 .reg = 3, 210 .reg_offset = 3,
145 .mask = S5M8763_IRQ_TOPOFFR_MASK, 211 .mask = S5M8763_IRQ_TOPOFFR_MASK,
146 }, 212 },
147 [S5M8763_IRQ_DCINOVPR] = { 213 [S5M8763_IRQ_DCINOVPR] = {
148 .reg = 3, 214 .reg_offset = 3,
149 .mask = S5M8763_IRQ_DCINOVPR_MASK, 215 .mask = S5M8763_IRQ_DCINOVPR_MASK,
150 }, 216 },
151 [S5M8763_IRQ_CHGRSTF] = { 217 [S5M8763_IRQ_CHGRSTF] = {
152 .reg = 3, 218 .reg_offset = 3,
153 .mask = S5M8763_IRQ_CHGRSTF_MASK, 219 .mask = S5M8763_IRQ_CHGRSTF_MASK,
154 }, 220 },
155 [S5M8763_IRQ_DONER] = { 221 [S5M8763_IRQ_DONER] = {
156 .reg = 3, 222 .reg_offset = 3,
157 .mask = S5M8763_IRQ_DONER_MASK, 223 .mask = S5M8763_IRQ_DONER_MASK,
158 }, 224 },
159 [S5M8763_IRQ_CHGFAULT] = { 225 [S5M8763_IRQ_CHGFAULT] = {
160 .reg = 3, 226 .reg_offset = 3,
161 .mask = S5M8763_IRQ_CHGFAULT_MASK, 227 .mask = S5M8763_IRQ_CHGFAULT_MASK,
162 }, 228 },
163 [S5M8763_IRQ_LOBAT1] = { 229 [S5M8763_IRQ_LOBAT1] = {
164 .reg = 4, 230 .reg_offset = 4,
165 .mask = S5M8763_IRQ_LOBAT1_MASK, 231 .mask = S5M8763_IRQ_LOBAT1_MASK,
166 }, 232 },
167 [S5M8763_IRQ_LOBAT2] = { 233 [S5M8763_IRQ_LOBAT2] = {
168 .reg = 4, 234 .reg_offset = 4,
169 .mask = S5M8763_IRQ_LOBAT2_MASK, 235 .mask = S5M8763_IRQ_LOBAT2_MASK,
170 }, 236 },
171}; 237};
172 238
173static inline struct sec_irq_data * 239static struct regmap_irq_chip s2mps11_irq_chip = {
174irq_to_s5m8767_irq(struct sec_pmic_dev *sec_pmic, int irq) 240 .name = "s2mps11",
175{ 241 .irqs = s2mps11_irqs,
176 return &s5m8767_irqs[irq - sec_pmic->irq_base]; 242 .num_irqs = ARRAY_SIZE(s2mps11_irqs),
177} 243 .num_regs = 3,
178 244 .status_base = S2MPS11_REG_INT1,
179static void s5m8767_irq_lock(struct irq_data *data) 245 .mask_base = S2MPS11_REG_INT1M,
180{ 246 .ack_base = S2MPS11_REG_INT1,
181 struct sec_pmic_dev *sec_pmic = irq_data_get_irq_chip_data(data); 247};
182
183 mutex_lock(&sec_pmic->irqlock);
184}
185
186static void s5m8767_irq_sync_unlock(struct irq_data *data)
187{
188 struct sec_pmic_dev *sec_pmic = irq_data_get_irq_chip_data(data);
189 int i;
190
191 for (i = 0; i < ARRAY_SIZE(sec_pmic->irq_masks_cur); i++) {
192 if (sec_pmic->irq_masks_cur[i] != sec_pmic->irq_masks_cache[i]) {
193 sec_pmic->irq_masks_cache[i] = sec_pmic->irq_masks_cur[i];
194 sec_reg_write(sec_pmic, S5M8767_REG_INT1M + i,
195 sec_pmic->irq_masks_cur[i]);
196 }
197 }
198
199 mutex_unlock(&sec_pmic->irqlock);
200}
201
202static void s5m8767_irq_unmask(struct irq_data *data)
203{
204 struct sec_pmic_dev *sec_pmic = irq_data_get_irq_chip_data(data);
205 struct sec_irq_data *irq_data = irq_to_s5m8767_irq(sec_pmic,
206 data->irq);
207
208 sec_pmic->irq_masks_cur[irq_data->reg - 1] &= ~irq_data->mask;
209}
210
211static void s5m8767_irq_mask(struct irq_data *data)
212{
213 struct sec_pmic_dev *sec_pmic = irq_data_get_irq_chip_data(data);
214 struct sec_irq_data *irq_data = irq_to_s5m8767_irq(sec_pmic,
215 data->irq);
216
217 sec_pmic->irq_masks_cur[irq_data->reg - 1] |= irq_data->mask;
218}
219 248
220static struct irq_chip s5m8767_irq_chip = { 249static struct regmap_irq_chip s5m8767_irq_chip = {
221 .name = "s5m8767", 250 .name = "s5m8767",
222 .irq_bus_lock = s5m8767_irq_lock, 251 .irqs = s5m8767_irqs,
223 .irq_bus_sync_unlock = s5m8767_irq_sync_unlock, 252 .num_irqs = ARRAY_SIZE(s5m8767_irqs),
224 .irq_mask = s5m8767_irq_mask, 253 .num_regs = 3,
225 .irq_unmask = s5m8767_irq_unmask, 254 .status_base = S5M8767_REG_INT1,
255 .mask_base = S5M8767_REG_INT1M,
256 .ack_base = S5M8767_REG_INT1,
226}; 257};
227 258
228static inline struct sec_irq_data * 259static struct regmap_irq_chip s5m8763_irq_chip = {
229irq_to_s5m8763_irq(struct sec_pmic_dev *sec_pmic, int irq)
230{
231 return &s5m8763_irqs[irq - sec_pmic->irq_base];
232}
233
234static void s5m8763_irq_lock(struct irq_data *data)
235{
236 struct sec_pmic_dev *sec_pmic = irq_data_get_irq_chip_data(data);
237
238 mutex_lock(&sec_pmic->irqlock);
239}
240
241static void s5m8763_irq_sync_unlock(struct irq_data *data)
242{
243 struct sec_pmic_dev *sec_pmic = irq_data_get_irq_chip_data(data);
244 int i;
245
246 for (i = 0; i < ARRAY_SIZE(sec_pmic->irq_masks_cur); i++) {
247 if (sec_pmic->irq_masks_cur[i] != sec_pmic->irq_masks_cache[i]) {
248 sec_pmic->irq_masks_cache[i] = sec_pmic->irq_masks_cur[i];
249 sec_reg_write(sec_pmic, S5M8763_REG_IRQM1 + i,
250 sec_pmic->irq_masks_cur[i]);
251 }
252 }
253
254 mutex_unlock(&sec_pmic->irqlock);
255}
256
257static void s5m8763_irq_unmask(struct irq_data *data)
258{
259 struct sec_pmic_dev *sec_pmic = irq_data_get_irq_chip_data(data);
260 struct sec_irq_data *irq_data = irq_to_s5m8763_irq(sec_pmic,
261 data->irq);
262
263 sec_pmic->irq_masks_cur[irq_data->reg - 1] &= ~irq_data->mask;
264}
265
266static void s5m8763_irq_mask(struct irq_data *data)
267{
268 struct sec_pmic_dev *sec_pmic = irq_data_get_irq_chip_data(data);
269 struct sec_irq_data *irq_data = irq_to_s5m8763_irq(sec_pmic,
270 data->irq);
271
272 sec_pmic->irq_masks_cur[irq_data->reg - 1] |= irq_data->mask;
273}
274
275static struct irq_chip s5m8763_irq_chip = {
276 .name = "s5m8763", 260 .name = "s5m8763",
277 .irq_bus_lock = s5m8763_irq_lock, 261 .irqs = s5m8763_irqs,
278 .irq_bus_sync_unlock = s5m8763_irq_sync_unlock, 262 .num_irqs = ARRAY_SIZE(s5m8763_irqs),
279 .irq_mask = s5m8763_irq_mask, 263 .num_regs = 4,
280 .irq_unmask = s5m8763_irq_unmask, 264 .status_base = S5M8763_REG_IRQ1,
265 .mask_base = S5M8763_REG_IRQM1,
266 .ack_base = S5M8763_REG_IRQ1,
281}; 267};
282 268
283
284static irqreturn_t s5m8767_irq_thread(int irq, void *data)
285{
286 struct sec_pmic_dev *sec_pmic = data;
287 u8 irq_reg[NUM_IRQ_REGS-1];
288 int ret;
289 int i;
290
291
292 ret = sec_bulk_read(sec_pmic, S5M8767_REG_INT1,
293 NUM_IRQ_REGS - 1, irq_reg);
294 if (ret < 0) {
295 dev_err(sec_pmic->dev, "Failed to read interrupt register: %d\n",
296 ret);
297 return IRQ_NONE;
298 }
299
300 for (i = 0; i < NUM_IRQ_REGS - 1; i++)
301 irq_reg[i] &= ~sec_pmic->irq_masks_cur[i];
302
303 for (i = 0; i < S5M8767_IRQ_NR; i++) {
304 if (irq_reg[s5m8767_irqs[i].reg - 1] & s5m8767_irqs[i].mask)
305 handle_nested_irq(sec_pmic->irq_base + i);
306 }
307
308 return IRQ_HANDLED;
309}
310
311static irqreturn_t s5m8763_irq_thread(int irq, void *data)
312{
313 struct sec_pmic_dev *sec_pmic = data;
314 u8 irq_reg[NUM_IRQ_REGS];
315 int ret;
316 int i;
317
318 ret = sec_bulk_read(sec_pmic, S5M8763_REG_IRQ1,
319 NUM_IRQ_REGS, irq_reg);
320 if (ret < 0) {
321 dev_err(sec_pmic->dev, "Failed to read interrupt register: %d\n",
322 ret);
323 return IRQ_NONE;
324 }
325
326 for (i = 0; i < NUM_IRQ_REGS; i++)
327 irq_reg[i] &= ~sec_pmic->irq_masks_cur[i];
328
329 for (i = 0; i < S5M8763_IRQ_NR; i++) {
330 if (irq_reg[s5m8763_irqs[i].reg - 1] & s5m8763_irqs[i].mask)
331 handle_nested_irq(sec_pmic->irq_base + i);
332 }
333
334 return IRQ_HANDLED;
335}
336
337int sec_irq_resume(struct sec_pmic_dev *sec_pmic)
338{
339 if (sec_pmic->irq && sec_pmic->irq_base) {
340 switch (sec_pmic->device_type) {
341 case S5M8763X:
342 s5m8763_irq_thread(sec_pmic->irq_base, sec_pmic);
343 break;
344 case S5M8767X:
345 s5m8767_irq_thread(sec_pmic->irq_base, sec_pmic);
346 break;
347 default:
348 dev_err(sec_pmic->dev,
349 "Unknown device type %d\n",
350 sec_pmic->device_type);
351 return -EINVAL;
352
353 }
354 }
355 return 0;
356}
357
358int sec_irq_init(struct sec_pmic_dev *sec_pmic) 269int sec_irq_init(struct sec_pmic_dev *sec_pmic)
359{ 270{
360 int i;
361 int cur_irq;
362 int ret = 0; 271 int ret = 0;
363 int type = sec_pmic->device_type; 272 int type = sec_pmic->device_type;
364 273
@@ -369,119 +278,33 @@ int sec_irq_init(struct sec_pmic_dev *sec_pmic)
369 return 0; 278 return 0;
370 } 279 }
371 280
372 if (!sec_pmic->irq_base) {
373 dev_err(sec_pmic->dev,
374 "No interrupt base specified, no interrupts\n");
375 return 0;
376 }
377
378 mutex_init(&sec_pmic->irqlock);
379
380 switch (type) { 281 switch (type) {
381 case S5M8763X: 282 case S5M8763X:
382 for (i = 0; i < NUM_IRQ_REGS; i++) { 283 ret = regmap_add_irq_chip(sec_pmic->regmap, sec_pmic->irq,
383 sec_pmic->irq_masks_cur[i] = 0xff; 284 IRQF_TRIGGER_FALLING | IRQF_ONESHOT,
384 sec_pmic->irq_masks_cache[i] = 0xff; 285 sec_pmic->irq_base, &s5m8763_irq_chip,
385 sec_reg_write(sec_pmic, S5M8763_REG_IRQM1 + i, 286 &sec_pmic->irq_data);
386 0xff);
387 }
388
389 sec_reg_write(sec_pmic, S5M8763_REG_STATUSM1, 0xff);
390 sec_reg_write(sec_pmic, S5M8763_REG_STATUSM2, 0xff);
391
392 for (i = 0; i < S5M8763_IRQ_NR; i++) {
393 cur_irq = i + sec_pmic->irq_base;
394 irq_set_chip_data(cur_irq, sec_pmic);
395 irq_set_chip_and_handler(cur_irq, &s5m8763_irq_chip,
396 handle_edge_irq);
397 irq_set_nested_thread(cur_irq, 1);
398#ifdef CONFIG_ARM
399 set_irq_flags(cur_irq, IRQF_VALID);
400#else
401 irq_set_noprobe(cur_irq);
402#endif
403 }
404
405 ret = request_threaded_irq(sec_pmic->irq, NULL,
406 s5m8763_irq_thread,
407 IRQF_TRIGGER_FALLING | IRQF_ONESHOT,
408 "sec-pmic-irq", sec_pmic);
409 if (ret) {
410 dev_err(sec_pmic->dev, "Failed to request IRQ %d: %d\n",
411 sec_pmic->irq, ret);
412 return ret;
413 }
414 break; 287 break;
415 case S5M8767X: 288 case S5M8767X:
416 for (i = 0; i < NUM_IRQ_REGS - 1; i++) { 289 ret = regmap_add_irq_chip(sec_pmic->regmap, sec_pmic->irq,
417 sec_pmic->irq_masks_cur[i] = 0xff; 290 IRQF_TRIGGER_FALLING | IRQF_ONESHOT,
418 sec_pmic->irq_masks_cache[i] = 0xff; 291 sec_pmic->irq_base, &s5m8767_irq_chip,
419 sec_reg_write(sec_pmic, S5M8767_REG_INT1M + i, 292 &sec_pmic->irq_data);
420 0xff);
421 }
422 for (i = 0; i < S5M8767_IRQ_NR; i++) {
423 cur_irq = i + sec_pmic->irq_base;
424 irq_set_chip_data(cur_irq, sec_pmic);
425 if (ret) {
426 dev_err(sec_pmic->dev,
427 "Failed to irq_set_chip_data %d: %d\n",
428 sec_pmic->irq, ret);
429 return ret;
430 }
431
432 irq_set_chip_and_handler(cur_irq, &s5m8767_irq_chip,
433 handle_edge_irq);
434 irq_set_nested_thread(cur_irq, 1);
435#ifdef CONFIG_ARM
436 set_irq_flags(cur_irq, IRQF_VALID);
437#else
438 irq_set_noprobe(cur_irq);
439#endif
440 }
441
442 ret = request_threaded_irq(sec_pmic->irq, NULL,
443 s5m8767_irq_thread,
444 IRQF_TRIGGER_FALLING | IRQF_ONESHOT,
445 "sec-pmic-irq", sec_pmic);
446 if (ret) {
447 dev_err(sec_pmic->dev, "Failed to request IRQ %d: %d\n",
448 sec_pmic->irq, ret);
449 return ret;
450 }
451 break; 293 break;
452 default: 294 case S2MPS11X:
453 dev_err(sec_pmic->dev, 295 ret = regmap_add_irq_chip(sec_pmic->regmap, sec_pmic->irq,
454 "Unknown device type %d\n", sec_pmic->device_type); 296 IRQF_TRIGGER_FALLING | IRQF_ONESHOT,
455 return -EINVAL; 297 sec_pmic->irq_base, &s2mps11_irq_chip,
456 } 298 &sec_pmic->irq_data);
457
458 if (!sec_pmic->ono)
459 return 0;
460
461 switch (type) {
462 case S5M8763X:
463 ret = request_threaded_irq(sec_pmic->ono, NULL,
464 s5m8763_irq_thread,
465 IRQF_TRIGGER_FALLING |
466 IRQF_TRIGGER_RISING |
467 IRQF_ONESHOT, "sec_pmic-ono",
468 sec_pmic);
469 break;
470 case S5M8767X:
471 ret = request_threaded_irq(sec_pmic->ono, NULL,
472 s5m8767_irq_thread,
473 IRQF_TRIGGER_FALLING |
474 IRQF_TRIGGER_RISING |
475 IRQF_ONESHOT, "sec_pmic-ono", sec_pmic);
476 break; 299 break;
477 default: 300 default:
478 ret = -EINVAL; 301 dev_err(sec_pmic->dev, "Unknown device type %d\n",
479 break; 302 sec_pmic->device_type);
303 return -EINVAL;
480 } 304 }
481 305
482 if (ret) { 306 if (ret != 0) {
483 dev_err(sec_pmic->dev, "Failed to request IRQ %d: %d\n", 307 dev_err(sec_pmic->dev, "Failed to register IRQ chip: %d\n", ret);
484 sec_pmic->ono, ret);
485 return ret; 308 return ret;
486 } 309 }
487 310
@@ -490,9 +313,5 @@ int sec_irq_init(struct sec_pmic_dev *sec_pmic)
490 313
491void sec_irq_exit(struct sec_pmic_dev *sec_pmic) 314void sec_irq_exit(struct sec_pmic_dev *sec_pmic)
492{ 315{
493 if (sec_pmic->ono) 316 regmap_del_irq_chip(sec_pmic->irq, sec_pmic->irq_data);
494 free_irq(sec_pmic->ono, sec_pmic);
495
496 if (sec_pmic->irq)
497 free_irq(sec_pmic->irq, sec_pmic);
498} 317}
diff --git a/include/linux/mfd/samsung/core.h b/include/linux/mfd/samsung/core.h
index 323e200bc82c..b50c38f8bc48 100644
--- a/include/linux/mfd/samsung/core.h
+++ b/include/linux/mfd/samsung/core.h
@@ -48,6 +48,8 @@ struct sec_pmic_dev {
48 int device_type; 48 int device_type;
49 int irq_base; 49 int irq_base;
50 int irq; 50 int irq;
51 struct regmap_irq_chip_data *irq_data;
52
51 int ono; 53 int ono;
52 u8 irq_masks_cur[NUM_IRQ_REGS]; 54 u8 irq_masks_cur[NUM_IRQ_REGS];
53 u8 irq_masks_cache[NUM_IRQ_REGS]; 55 u8 irq_masks_cache[NUM_IRQ_REGS];
diff --git a/include/linux/mfd/samsung/irq.h b/include/linux/mfd/samsung/irq.h
index 7f7a6248f707..d43b4f9e7fb2 100644
--- a/include/linux/mfd/samsung/irq.h
+++ b/include/linux/mfd/samsung/irq.h
@@ -13,6 +13,48 @@
13#ifndef __LINUX_MFD_SEC_IRQ_H 13#ifndef __LINUX_MFD_SEC_IRQ_H
14#define __LINUX_MFD_SEC_IRQ_H 14#define __LINUX_MFD_SEC_IRQ_H
15 15
16enum s2mps11_irq {
17 S2MPS11_IRQ_PWRONF,
18 S2MPS11_IRQ_PWRONR,
19 S2MPS11_IRQ_JIGONBF,
20 S2MPS11_IRQ_JIGONBR,
21 S2MPS11_IRQ_ACOKBF,
22 S2MPS11_IRQ_ACOKBR,
23 S2MPS11_IRQ_PWRON1S,
24 S2MPS11_IRQ_MRB,
25
26 S2MPS11_IRQ_RTC60S,
27 S2MPS11_IRQ_RTCA1,
28 S2MPS11_IRQ_RTCA2,
29 S2MPS11_IRQ_SMPL,
30 S2MPS11_IRQ_RTC1S,
31 S2MPS11_IRQ_WTSR,
32
33 S2MPS11_IRQ_INT120C,
34 S2MPS11_IRQ_INT140C,
35
36 S2MPS11_IRQ_NR,
37};
38
39#define S2MPS11_IRQ_PWRONF_MASK (1 << 0)
40#define S2MPS11_IRQ_PWRONR_MASK (1 << 1)
41#define S2MPS11_IRQ_JIGONBF_MASK (1 << 2)
42#define S2MPS11_IRQ_JIGONBR_MASK (1 << 3)
43#define S2MPS11_IRQ_ACOKBF_MASK (1 << 4)
44#define S2MPS11_IRQ_ACOKBR_MASK (1 << 5)
45#define S2MPS11_IRQ_PWRON1S_MASK (1 << 6)
46#define S2MPS11_IRQ_MRB_MASK (1 << 7)
47
48#define S2MPS11_IRQ_RTC60S_MASK (1 << 0)
49#define S2MPS11_IRQ_RTCA1_MASK (1 << 1)
50#define S2MPS11_IRQ_RTCA2_MASK (1 << 2)
51#define S2MPS11_IRQ_SMPL_MASK (1 << 3)
52#define S2MPS11_IRQ_RTC1S_MASK (1 << 4)
53#define S2MPS11_IRQ_WTSR_MASK (1 << 5)
54
55#define S2MPS11_IRQ_INT120C_MASK (1 << 0)
56#define S2MPS11_IRQ_INT140C_MASK (1 << 1)
57
16enum s5m8767_irq { 58enum s5m8767_irq {
17 S5M8767_IRQ_PWRR, 59 S5M8767_IRQ_PWRR,
18 S5M8767_IRQ_PWRF, 60 S5M8767_IRQ_PWRF,