4 * Copyright (c) 2011 Samsung Electronics Co., Ltd
5 * http://www.samsung.com
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.
14 #include <linux/device.h>
15 #include <linux/interrupt.h>
16 #include <linux/irq.h>
17 #include <linux/regmap.h>
18 #include <linux/mfd/s5m87xx/s5m-core.h>
25 static struct s5m_irq_data s5m8767_irqs[] = {
26 [S5M8767_IRQ_PWRR] = {
28 .mask = S5M8767_IRQ_PWRR_MASK,
30 [S5M8767_IRQ_PWRF] = {
32 .mask = S5M8767_IRQ_PWRF_MASK,
34 [S5M8767_IRQ_PWR1S] = {
36 .mask = S5M8767_IRQ_PWR1S_MASK,
38 [S5M8767_IRQ_JIGR] = {
40 .mask = S5M8767_IRQ_JIGR_MASK,
42 [S5M8767_IRQ_JIGF] = {
44 .mask = S5M8767_IRQ_JIGF_MASK,
46 [S5M8767_IRQ_LOWBAT2] = {
48 .mask = S5M8767_IRQ_LOWBAT2_MASK,
50 [S5M8767_IRQ_LOWBAT1] = {
52 .mask = S5M8767_IRQ_LOWBAT1_MASK,
56 .mask = S5M8767_IRQ_MRB_MASK,
58 [S5M8767_IRQ_DVSOK2] = {
60 .mask = S5M8767_IRQ_DVSOK2_MASK,
62 [S5M8767_IRQ_DVSOK3] = {
64 .mask = S5M8767_IRQ_DVSOK3_MASK,
66 [S5M8767_IRQ_DVSOK4] = {
68 .mask = S5M8767_IRQ_DVSOK4_MASK,
70 [S5M8767_IRQ_RTC60S] = {
72 .mask = S5M8767_IRQ_RTC60S_MASK,
74 [S5M8767_IRQ_RTCA1] = {
76 .mask = S5M8767_IRQ_RTCA1_MASK,
78 [S5M8767_IRQ_RTCA2] = {
80 .mask = S5M8767_IRQ_RTCA2_MASK,
82 [S5M8767_IRQ_SMPL] = {
84 .mask = S5M8767_IRQ_SMPL_MASK,
86 [S5M8767_IRQ_RTC1S] = {
88 .mask = S5M8767_IRQ_RTC1S_MASK,
90 [S5M8767_IRQ_WTSR] = {
92 .mask = S5M8767_IRQ_WTSR_MASK,
96 static struct s5m_irq_data s5m8763_irqs[] = {
97 [S5M8763_IRQ_DCINF] = {
99 .mask = S5M8763_IRQ_DCINF_MASK,
101 [S5M8763_IRQ_DCINR] = {
103 .mask = S5M8763_IRQ_DCINR_MASK,
105 [S5M8763_IRQ_JIGF] = {
107 .mask = S5M8763_IRQ_JIGF_MASK,
109 [S5M8763_IRQ_JIGR] = {
111 .mask = S5M8763_IRQ_JIGR_MASK,
113 [S5M8763_IRQ_PWRONF] = {
115 .mask = S5M8763_IRQ_PWRONF_MASK,
117 [S5M8763_IRQ_PWRONR] = {
119 .mask = S5M8763_IRQ_PWRONR_MASK,
121 [S5M8763_IRQ_WTSREVNT] = {
123 .mask = S5M8763_IRQ_WTSREVNT_MASK,
125 [S5M8763_IRQ_SMPLEVNT] = {
127 .mask = S5M8763_IRQ_SMPLEVNT_MASK,
129 [S5M8763_IRQ_ALARM1] = {
131 .mask = S5M8763_IRQ_ALARM1_MASK,
133 [S5M8763_IRQ_ALARM0] = {
135 .mask = S5M8763_IRQ_ALARM0_MASK,
137 [S5M8763_IRQ_ONKEY1S] = {
139 .mask = S5M8763_IRQ_ONKEY1S_MASK,
141 [S5M8763_IRQ_TOPOFFR] = {
143 .mask = S5M8763_IRQ_TOPOFFR_MASK,
145 [S5M8763_IRQ_DCINOVPR] = {
147 .mask = S5M8763_IRQ_DCINOVPR_MASK,
149 [S5M8763_IRQ_CHGRSTF] = {
151 .mask = S5M8763_IRQ_CHGRSTF_MASK,
153 [S5M8763_IRQ_DONER] = {
155 .mask = S5M8763_IRQ_DONER_MASK,
157 [S5M8763_IRQ_CHGFAULT] = {
159 .mask = S5M8763_IRQ_CHGFAULT_MASK,
161 [S5M8763_IRQ_LOBAT1] = {
163 .mask = S5M8763_IRQ_LOBAT1_MASK,
165 [S5M8763_IRQ_LOBAT2] = {
167 .mask = S5M8763_IRQ_LOBAT2_MASK,
171 static inline struct s5m_irq_data *
172 irq_to_s5m8767_irq(struct s5m87xx_dev *s5m87xx, int irq)
174 return &s5m8767_irqs[irq - s5m87xx->irq_base];
177 static void s5m8767_irq_lock(struct irq_data *data)
179 struct s5m87xx_dev *s5m87xx = irq_data_get_irq_chip_data(data);
181 mutex_lock(&s5m87xx->irqlock);
184 static void s5m8767_irq_sync_unlock(struct irq_data *data)
186 struct s5m87xx_dev *s5m87xx = irq_data_get_irq_chip_data(data);
189 for (i = 0; i < ARRAY_SIZE(s5m87xx->irq_masks_cur); i++) {
190 if (s5m87xx->irq_masks_cur[i] != s5m87xx->irq_masks_cache[i]) {
191 s5m87xx->irq_masks_cache[i] = s5m87xx->irq_masks_cur[i];
192 regmap_write(s5m87xx->pmic, S5M8767_REG_INT1M + i,
193 s5m87xx->irq_masks_cur[i]);
197 mutex_unlock(&s5m87xx->irqlock);
200 static void s5m8767_irq_unmask(struct irq_data *data)
202 struct s5m87xx_dev *s5m87xx = irq_data_get_irq_chip_data(data);
203 struct s5m_irq_data *irq_data = irq_to_s5m8767_irq(s5m87xx,
206 s5m87xx->irq_masks_cur[irq_data->reg - 1] &= ~irq_data->mask;
209 static void s5m8767_irq_mask(struct irq_data *data)
211 struct s5m87xx_dev *s5m87xx = irq_data_get_irq_chip_data(data);
212 struct s5m_irq_data *irq_data = irq_to_s5m8767_irq(s5m87xx,
215 s5m87xx->irq_masks_cur[irq_data->reg - 1] |= irq_data->mask;
218 static struct irq_chip s5m8767_irq_chip = {
220 .irq_bus_lock = s5m8767_irq_lock,
221 .irq_bus_sync_unlock = s5m8767_irq_sync_unlock,
222 .irq_mask = s5m8767_irq_mask,
223 .irq_unmask = s5m8767_irq_unmask,
226 static inline struct s5m_irq_data *
227 irq_to_s5m8763_irq(struct s5m87xx_dev *s5m87xx, int irq)
229 return &s5m8763_irqs[irq - s5m87xx->irq_base];
232 static void s5m8763_irq_lock(struct irq_data *data)
234 struct s5m87xx_dev *s5m87xx = irq_data_get_irq_chip_data(data);
236 mutex_lock(&s5m87xx->irqlock);
239 static void s5m8763_irq_sync_unlock(struct irq_data *data)
241 struct s5m87xx_dev *s5m87xx = irq_data_get_irq_chip_data(data);
244 for (i = 0; i < ARRAY_SIZE(s5m87xx->irq_masks_cur); i++) {
245 if (s5m87xx->irq_masks_cur[i] != s5m87xx->irq_masks_cache[i]) {
246 s5m87xx->irq_masks_cache[i] = s5m87xx->irq_masks_cur[i];
247 regmap_write(s5m87xx->pmic, S5M8763_REG_IRQM1 + i,
248 s5m87xx->irq_masks_cur[i]);
252 mutex_unlock(&s5m87xx->irqlock);
255 static void s5m8763_irq_unmask(struct irq_data *data)
257 struct s5m87xx_dev *s5m87xx = irq_data_get_irq_chip_data(data);
258 struct s5m_irq_data *irq_data = irq_to_s5m8763_irq(s5m87xx,
261 s5m87xx->irq_masks_cur[irq_data->reg - 1] &= ~irq_data->mask;
264 static void s5m8763_irq_mask(struct irq_data *data)
266 struct s5m87xx_dev *s5m87xx = irq_data_get_irq_chip_data(data);
267 struct s5m_irq_data *irq_data = irq_to_s5m8763_irq(s5m87xx,
270 s5m87xx->irq_masks_cur[irq_data->reg - 1] |= irq_data->mask;
273 static struct irq_chip s5m8763_irq_chip = {
275 .irq_bus_lock = s5m8763_irq_lock,
276 .irq_bus_sync_unlock = s5m8763_irq_sync_unlock,
277 .irq_mask = s5m8763_irq_mask,
278 .irq_unmask = s5m8763_irq_unmask,
282 static irqreturn_t s5m8767_irq_thread(int irq, void *data)
284 struct s5m87xx_dev *s5m87xx = data;
285 u8 irq_reg[NUM_IRQ_REGS-1];
290 ret = regmap_bulk_read(s5m87xx->pmic, S5M8767_REG_INT1,
291 irq_reg, NUM_IRQ_REGS - 1);
293 dev_err(s5m87xx->dev, "Failed to read interrupt register: %d\n",
298 for (i = 0; i < NUM_IRQ_REGS - 1; i++)
299 irq_reg[i] &= ~s5m87xx->irq_masks_cur[i];
301 for (i = 0; i < S5M8767_IRQ_NR; i++) {
302 if (irq_reg[s5m8767_irqs[i].reg - 1] & s5m8767_irqs[i].mask)
303 handle_nested_irq(s5m87xx->irq_base + i);
309 static irqreturn_t s5m8763_irq_thread(int irq, void *data)
311 struct s5m87xx_dev *s5m87xx = data;
312 u8 irq_reg[NUM_IRQ_REGS];
316 ret = regmap_bulk_read(s5m87xx->pmic, S5M8763_REG_IRQ1,
317 irq_reg, NUM_IRQ_REGS);
319 dev_err(s5m87xx->dev, "Failed to read interrupt register: %d\n",
324 for (i = 0; i < NUM_IRQ_REGS; i++)
325 irq_reg[i] &= ~s5m87xx->irq_masks_cur[i];
327 for (i = 0; i < S5M8763_IRQ_NR; i++) {
328 if (irq_reg[s5m8763_irqs[i].reg - 1] & s5m8763_irqs[i].mask)
329 handle_nested_irq(s5m87xx->irq_base + i);
335 int s5m_irq_resume(struct s5m87xx_dev *s5m87xx)
337 if (s5m87xx->irq && s5m87xx->irq_base){
338 switch (s5m87xx->device_type) {
340 s5m8763_irq_thread(s5m87xx->irq_base, s5m87xx);
343 s5m8767_irq_thread(s5m87xx->irq_base, s5m87xx);
346 dev_err(s5m87xx->dev,
347 "Unknown device type %d\n",
348 s5m87xx->device_type);
356 int s5m_irq_init(struct s5m87xx_dev *s5m87xx)
361 int type = s5m87xx->device_type;
364 dev_warn(s5m87xx->dev,
365 "No interrupt specified, no interrupts\n");
366 s5m87xx->irq_base = 0;
370 if (!s5m87xx->irq_base) {
371 dev_err(s5m87xx->dev,
372 "No interrupt base specified, no interrupts\n");
376 mutex_init(&s5m87xx->irqlock);
380 for (i = 0; i < NUM_IRQ_REGS; i++) {
381 s5m87xx->irq_masks_cur[i] = 0xff;
382 s5m87xx->irq_masks_cache[i] = 0xff;
383 regmap_write(s5m87xx->pmic, S5M8763_REG_IRQM1 + i,
387 regmap_write(s5m87xx->pmic, S5M8763_REG_STATUSM1, 0xff);
388 regmap_write(s5m87xx->pmic, S5M8763_REG_STATUSM2, 0xff);
390 for (i = 0; i < S5M8763_IRQ_NR; i++) {
391 cur_irq = i + s5m87xx->irq_base;
392 irq_set_chip_data(cur_irq, s5m87xx);
393 irq_set_chip_and_handler(cur_irq, &s5m8763_irq_chip,
395 irq_set_nested_thread(cur_irq, 1);
397 set_irq_flags(cur_irq, IRQF_VALID);
399 irq_set_noprobe(cur_irq);
403 ret = request_threaded_irq(s5m87xx->irq, NULL,
405 IRQF_TRIGGER_FALLING | IRQF_ONESHOT,
406 "s5m87xx-irq", s5m87xx);
408 dev_err(s5m87xx->dev, "Failed to request IRQ %d: %d\n",
414 for (i = 0; i < NUM_IRQ_REGS - 1; i++) {
415 s5m87xx->irq_masks_cur[i] = 0xff;
416 s5m87xx->irq_masks_cache[i] = 0xff;
417 regmap_write(s5m87xx->pmic, S5M8767_REG_INT1M + i,
420 for (i = 0; i < S5M8767_IRQ_NR; i++) {
421 cur_irq = i + s5m87xx->irq_base;
422 irq_set_chip_data(cur_irq, s5m87xx);
424 dev_err(s5m87xx->dev,
425 "Failed to irq_set_chip_data %d: %d\n",
430 irq_set_chip_and_handler(cur_irq, &s5m8767_irq_chip,
432 irq_set_nested_thread(cur_irq, 1);
434 set_irq_flags(cur_irq, IRQF_VALID);
436 irq_set_noprobe(cur_irq);
440 ret = request_threaded_irq(s5m87xx->irq, NULL,
442 IRQF_TRIGGER_FALLING | IRQF_ONESHOT,
443 "s5m87xx-irq", s5m87xx);
445 dev_err(s5m87xx->dev, "Failed to request IRQ %d: %d\n",
451 dev_err(s5m87xx->dev,
452 "Unknown device type %d\n", s5m87xx->device_type);
461 ret = request_threaded_irq(s5m87xx->ono, NULL,
463 IRQF_TRIGGER_FALLING |
464 IRQF_TRIGGER_RISING |
465 IRQF_ONESHOT, "s5m87xx-ono",
469 ret = request_threaded_irq(s5m87xx->ono, NULL,
471 IRQF_TRIGGER_FALLING |
472 IRQF_TRIGGER_RISING |
473 IRQF_ONESHOT, "s5m87xx-ono", s5m87xx);
481 dev_err(s5m87xx->dev, "Failed to request IRQ %d: %d\n",
489 void s5m_irq_exit(struct s5m87xx_dev *s5m87xx)
492 free_irq(s5m87xx->ono, s5m87xx);
495 free_irq(s5m87xx->irq, s5m87xx);