1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30#include <linux/init.h>
31#include <linux/interrupt.h>
32#include <linux/irq.h>
33#include <linux/kthread.h>
34
35#include <linux/i2c/twl4030.h>
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57#define REG_PIH_ISR_P1 0x01
58#define REG_PIH_ISR_P2 0x02
59#define REG_PIH_SIR 0x03
60
61
62
63static int irq_line;
64
65struct sih {
66 char name[8];
67 u8 module;
68 u8 control_offset;
69 bool set_cor;
70
71 u8 bits;
72 u8 bytes_ixr;
73
74 u8 edr_offset;
75 u8 bytes_edr;
76
77
78 struct irq_data {
79 u8 isr_offset;
80 u8 imr_offset;
81 } mask[2];
82
83};
84
85#define SIH_INITIALIZER(modname, nbits) \
86 .module = TWL4030_MODULE_ ## modname, \
87 .control_offset = TWL4030_ ## modname ## _SIH_CTRL, \
88 .bits = nbits, \
89 .bytes_ixr = DIV_ROUND_UP(nbits, 8), \
90 .edr_offset = TWL4030_ ## modname ## _EDR, \
91 .bytes_edr = DIV_ROUND_UP((2*(nbits)), 8), \
92 .mask = { { \
93 .isr_offset = TWL4030_ ## modname ## _ISR1, \
94 .imr_offset = TWL4030_ ## modname ## _IMR1, \
95 }, \
96 { \
97 .isr_offset = TWL4030_ ## modname ## _ISR2, \
98 .imr_offset = TWL4030_ ## modname ## _IMR2, \
99 }, },
100
101
102#define TWL4030_INT_PWR_EDR TWL4030_INT_PWR_EDR1
103#define TWL4030_MODULE_KEYPAD_KEYP TWL4030_MODULE_KEYPAD
104#define TWL4030_MODULE_INT_PWR TWL4030_MODULE_INT
105
106
107
108
109
110static const struct sih sih_modules[6] = {
111 [0] = {
112 .name = "gpio",
113 .module = TWL4030_MODULE_GPIO,
114 .control_offset = REG_GPIO_SIH_CTRL,
115 .set_cor = true,
116 .bits = TWL4030_GPIO_MAX,
117 .bytes_ixr = 3,
118
119 .edr_offset = REG_GPIO_EDR1,
120 .bytes_edr = 5,
121 .mask = { {
122 .isr_offset = REG_GPIO_ISR1A,
123 .imr_offset = REG_GPIO_IMR1A,
124 }, {
125 .isr_offset = REG_GPIO_ISR1B,
126 .imr_offset = REG_GPIO_IMR1B,
127 }, },
128 },
129 [1] = {
130 .name = "keypad",
131 .set_cor = true,
132 SIH_INITIALIZER(KEYPAD_KEYP, 4)
133 },
134 [2] = {
135 .name = "bci",
136 .module = TWL4030_MODULE_INTERRUPTS,
137 .control_offset = TWL4030_INTERRUPTS_BCISIHCTRL,
138 .bits = 12,
139 .bytes_ixr = 2,
140 .edr_offset = TWL4030_INTERRUPTS_BCIEDR1,
141
142 .bytes_edr = 3,
143 .mask = { {
144 .isr_offset = TWL4030_INTERRUPTS_BCIISR1A,
145 .imr_offset = TWL4030_INTERRUPTS_BCIIMR1A,
146 }, {
147 .isr_offset = TWL4030_INTERRUPTS_BCIISR1B,
148 .imr_offset = TWL4030_INTERRUPTS_BCIIMR1B,
149 }, },
150 },
151 [3] = {
152 .name = "madc",
153 SIH_INITIALIZER(MADC, 4)
154 },
155 [4] = {
156
157 .name = "usb",
158 },
159 [5] = {
160 .name = "power",
161 .set_cor = true,
162 SIH_INITIALIZER(INT_PWR, 8)
163 },
164
165};
166
167#undef TWL4030_MODULE_KEYPAD_KEYP
168#undef TWL4030_MODULE_INT_PWR
169#undef TWL4030_INT_PWR_EDR
170
171
172
173static unsigned twl4030_irq_base;
174
175static struct completion irq_event;
176
177
178
179
180static int twl4030_irq_thread(void *data)
181{
182 long irq = (long)data;
183 static unsigned i2c_errors;
184 static const unsigned max_i2c_errors = 100;
185
186
187 current->flags |= PF_NOFREEZE;
188
189 while (!kthread_should_stop()) {
190 int ret;
191 int module_irq;
192 u8 pih_isr;
193
194
195 wait_for_completion_interruptible(&irq_event);
196
197 ret = twl4030_i2c_read_u8(TWL4030_MODULE_PIH, &pih_isr,
198 REG_PIH_ISR_P1);
199 if (ret) {
200 pr_warning("twl4030: I2C error %d reading PIH ISR\n",
201 ret);
202 if (++i2c_errors >= max_i2c_errors) {
203 printk(KERN_ERR "Maximum I2C error count"
204 " exceeded. Terminating %s.\n",
205 __func__);
206 break;
207 }
208 complete(&irq_event);
209 continue;
210 }
211
212
213 local_irq_disable();
214 for (module_irq = twl4030_irq_base;
215 pih_isr;
216 pih_isr >>= 1, module_irq++) {
217 if (pih_isr & 0x1) {
218 struct irq_desc *d = irq_to_desc(module_irq);
219
220 if (!d) {
221 pr_err("twl4030: Invalid SIH IRQ: %d\n",
222 module_irq);
223 return -EINVAL;
224 }
225
226
227
228
229 if (d->status & IRQ_DISABLED)
230 note_interrupt(module_irq, d,
231 IRQ_NONE);
232 else
233 d->handle_irq(module_irq, d);
234 }
235 }
236 local_irq_enable();
237
238 enable_irq(irq);
239 }
240
241 return 0;
242}
243
244
245
246
247
248
249
250
251
252
253static irqreturn_t handle_twl4030_pih(int irq, void *devid)
254{
255
256 disable_irq_nosync(irq);
257 complete(devid);
258 return IRQ_HANDLED;
259}
260
261
262
263
264
265
266
267
268
269
270
271static int twl4030_init_sih_modules(unsigned line)
272{
273 const struct sih *sih;
274 u8 buf[4];
275 int i;
276 int status;
277
278
279 if (line > 1)
280 return -EINVAL;
281
282 irq_line = line;
283
284
285 memset(buf, 0xff, sizeof buf);
286 sih = sih_modules;
287 for (i = 0; i < ARRAY_SIZE(sih_modules); i++, sih++) {
288
289
290 if (!sih->bytes_ixr)
291 continue;
292
293 status = twl4030_i2c_write(sih->module, buf,
294 sih->mask[line].imr_offset, sih->bytes_ixr);
295 if (status < 0)
296 pr_err("twl4030: err %d initializing %s %s\n",
297 status, sih->name, "IMR");
298
299
300
301
302
303
304
305
306 if (sih->set_cor) {
307 status = twl4030_i2c_write_u8(sih->module,
308 TWL4030_SIH_CTRL_COR_MASK,
309 sih->control_offset);
310 if (status < 0)
311 pr_err("twl4030: err %d initializing %s %s\n",
312 status, sih->name, "SIH_CTRL");
313 }
314 }
315
316 sih = sih_modules;
317 for (i = 0; i < ARRAY_SIZE(sih_modules); i++, sih++) {
318 u8 rxbuf[4];
319 int j;
320
321
322 if (!sih->bytes_ixr)
323 continue;
324
325
326
327
328
329
330 for (j = 0; j < 2; j++) {
331 status = twl4030_i2c_read(sih->module, rxbuf,
332 sih->mask[line].isr_offset, sih->bytes_ixr);
333 if (status < 0)
334 pr_err("twl4030: err %d initializing %s %s\n",
335 status, sih->name, "ISR");
336
337 if (!sih->set_cor)
338 status = twl4030_i2c_write(sih->module, buf,
339 sih->mask[line].isr_offset,
340 sih->bytes_ixr);
341
342
343
344 }
345 }
346
347 return 0;
348}
349
350static inline void activate_irq(int irq)
351{
352#ifdef CONFIG_ARM
353
354
355
356 set_irq_flags(irq, IRQF_VALID);
357#else
358
359 set_irq_noprobe(irq);
360#endif
361}
362
363
364
365static DEFINE_SPINLOCK(sih_agent_lock);
366
367static struct workqueue_struct *wq;
368
369struct sih_agent {
370 int irq_base;
371 const struct sih *sih;
372
373 u32 imr;
374 bool imr_change_pending;
375 struct work_struct mask_work;
376
377 u32 edge_change;
378 struct work_struct edge_work;
379};
380
381static void twl4030_sih_do_mask(struct work_struct *work)
382{
383 struct sih_agent *agent;
384 const struct sih *sih;
385 union {
386 u8 bytes[4];
387 u32 word;
388 } imr;
389 int status;
390
391 agent = container_of(work, struct sih_agent, mask_work);
392
393
394 spin_lock_irq(&sih_agent_lock);
395 if (agent->imr_change_pending) {
396 sih = agent->sih;
397
398 imr.word = cpu_to_le32(agent->imr << 8);
399 agent->imr_change_pending = false;
400 } else
401 sih = NULL;
402 spin_unlock_irq(&sih_agent_lock);
403 if (!sih)
404 return;
405
406
407 status = twl4030_i2c_write(sih->module, imr.bytes,
408 sih->mask[irq_line].imr_offset, sih->bytes_ixr);
409 if (status)
410 pr_err("twl4030: %s, %s --> %d\n", __func__,
411 "write", status);
412}
413
414static void twl4030_sih_do_edge(struct work_struct *work)
415{
416 struct sih_agent *agent;
417 const struct sih *sih;
418 u8 bytes[6];
419 u32 edge_change;
420 int status;
421
422 agent = container_of(work, struct sih_agent, edge_work);
423
424
425 spin_lock_irq(&sih_agent_lock);
426 edge_change = agent->edge_change;
427 agent->edge_change = 0;
428 sih = edge_change ? agent->sih : NULL;
429 spin_unlock_irq(&sih_agent_lock);
430 if (!sih)
431 return;
432
433
434
435
436
437
438 status = twl4030_i2c_read(sih->module, bytes + 1,
439 sih->edr_offset, sih->bytes_edr);
440 if (status) {
441 pr_err("twl4030: %s, %s --> %d\n", __func__,
442 "read", status);
443 return;
444 }
445
446
447 while (edge_change) {
448 int i = fls(edge_change) - 1;
449 struct irq_desc *d = irq_to_desc(i + agent->irq_base);
450 int byte = 1 + (i >> 2);
451 int off = (i & 0x3) * 2;
452
453 if (!d) {
454 pr_err("twl4030: Invalid IRQ: %d\n",
455 i + agent->irq_base);
456 return;
457 }
458
459 bytes[byte] &= ~(0x03 << off);
460
461 spin_lock_irq(&d->lock);
462 if (d->status & IRQ_TYPE_EDGE_RISING)
463 bytes[byte] |= BIT(off + 1);
464 if (d->status & IRQ_TYPE_EDGE_FALLING)
465 bytes[byte] |= BIT(off + 0);
466 spin_unlock_irq(&d->lock);
467
468 edge_change &= ~BIT(i);
469 }
470
471
472 status = twl4030_i2c_write(sih->module, bytes,
473 sih->edr_offset, sih->bytes_edr);
474 if (status)
475 pr_err("twl4030: %s, %s --> %d\n", __func__,
476 "write", status);
477}
478
479
480
481
482
483
484
485
486
487
488static void twl4030_sih_mask(unsigned irq)
489{
490 struct sih_agent *sih = get_irq_chip_data(irq);
491 unsigned long flags;
492
493 spin_lock_irqsave(&sih_agent_lock, flags);
494 sih->imr |= BIT(irq - sih->irq_base);
495 sih->imr_change_pending = true;
496 queue_work(wq, &sih->mask_work);
497 spin_unlock_irqrestore(&sih_agent_lock, flags);
498}
499
500static void twl4030_sih_unmask(unsigned irq)
501{
502 struct sih_agent *sih = get_irq_chip_data(irq);
503 unsigned long flags;
504
505 spin_lock_irqsave(&sih_agent_lock, flags);
506 sih->imr &= ~BIT(irq - sih->irq_base);
507 sih->imr_change_pending = true;
508 queue_work(wq, &sih->mask_work);
509 spin_unlock_irqrestore(&sih_agent_lock, flags);
510}
511
512static int twl4030_sih_set_type(unsigned irq, unsigned trigger)
513{
514 struct sih_agent *sih = get_irq_chip_data(irq);
515 struct irq_desc *desc = irq_to_desc(irq);
516 unsigned long flags;
517
518 if (!desc) {
519 pr_err("twl4030: Invalid IRQ: %d\n", irq);
520 return -EINVAL;
521 }
522
523 if (trigger & ~(IRQ_TYPE_EDGE_FALLING | IRQ_TYPE_EDGE_RISING))
524 return -EINVAL;
525
526 spin_lock_irqsave(&sih_agent_lock, flags);
527 if ((desc->status & IRQ_TYPE_SENSE_MASK) != trigger) {
528 desc->status &= ~IRQ_TYPE_SENSE_MASK;
529 desc->status |= trigger;
530 sih->edge_change |= BIT(irq - sih->irq_base);
531 queue_work(wq, &sih->edge_work);
532 }
533 spin_unlock_irqrestore(&sih_agent_lock, flags);
534 return 0;
535}
536
537static struct irq_chip twl4030_sih_irq_chip = {
538 .name = "twl4030",
539 .mask = twl4030_sih_mask,
540 .unmask = twl4030_sih_unmask,
541 .set_type = twl4030_sih_set_type,
542};
543
544
545
546static inline int sih_read_isr(const struct sih *sih)
547{
548 int status;
549 union {
550 u8 bytes[4];
551 u32 word;
552 } isr;
553
554
555
556 isr.word = 0;
557 status = twl4030_i2c_read(sih->module, isr.bytes,
558 sih->mask[irq_line].isr_offset, sih->bytes_ixr);
559
560 return (status < 0) ? status : le32_to_cpu(isr.word);
561}
562
563
564
565
566
567static void handle_twl4030_sih(unsigned irq, struct irq_desc *desc)
568{
569 struct sih_agent *agent = get_irq_data(irq);
570 const struct sih *sih = agent->sih;
571 int isr;
572
573
574 local_irq_enable();
575 isr = sih_read_isr(sih);
576 local_irq_disable();
577
578 if (isr < 0) {
579 pr_err("twl4030: %s SIH, read ISR error %d\n",
580 sih->name, isr);
581
582 return;
583 }
584
585 while (isr) {
586 irq = fls(isr);
587 irq--;
588 isr &= ~BIT(irq);
589
590 if (irq < sih->bits)
591 generic_handle_irq(agent->irq_base + irq);
592 else
593 pr_err("twl4030: %s SIH, invalid ISR bit %d\n",
594 sih->name, irq);
595 }
596}
597
598static unsigned twl4030_irq_next;
599
600
601
602
603int twl4030_sih_setup(int module)
604{
605 int sih_mod;
606 const struct sih *sih = NULL;
607 struct sih_agent *agent;
608 int i, irq;
609 int status = -EINVAL;
610 unsigned irq_base = twl4030_irq_next;
611
612
613 for (sih_mod = 0, sih = sih_modules;
614 sih_mod < ARRAY_SIZE(sih_modules);
615 sih_mod++, sih++) {
616 if (sih->module == module && sih->set_cor) {
617 if (!WARN((irq_base + sih->bits) > NR_IRQS,
618 "irq %d for %s too big\n",
619 irq_base + sih->bits,
620 sih->name))
621 status = 0;
622 break;
623 }
624 }
625 if (status < 0)
626 return status;
627
628 agent = kzalloc(sizeof *agent, GFP_KERNEL);
629 if (!agent)
630 return -ENOMEM;
631
632 status = 0;
633
634 agent->irq_base = irq_base;
635 agent->sih = sih;
636 agent->imr = ~0;
637 INIT_WORK(&agent->mask_work, twl4030_sih_do_mask);
638 INIT_WORK(&agent->edge_work, twl4030_sih_do_edge);
639
640 for (i = 0; i < sih->bits; i++) {
641 irq = irq_base + i;
642
643 set_irq_chip_and_handler(irq, &twl4030_sih_irq_chip,
644 handle_edge_irq);
645 set_irq_chip_data(irq, agent);
646 activate_irq(irq);
647 }
648
649 status = irq_base;
650 twl4030_irq_next += i;
651
652
653 irq = sih_mod + twl4030_irq_base;
654 set_irq_data(irq, agent);
655 set_irq_chained_handler(irq, handle_twl4030_sih);
656
657 pr_info("twl4030: %s (irq %d) chaining IRQs %d..%d\n", sih->name,
658 irq, irq_base, twl4030_irq_next - 1);
659
660 return status;
661}
662
663
664
665
666
667
668
669#define twl_irq_line 0
670
671int twl_init_irq(int irq_num, unsigned irq_base, unsigned irq_end)
672{
673 static struct irq_chip twl4030_irq_chip;
674
675 int status;
676 int i;
677 struct task_struct *task;
678
679
680
681
682
683 status = twl4030_init_sih_modules(twl_irq_line);
684 if (status < 0)
685 return status;
686
687 wq = create_singlethread_workqueue("twl4030-irqchip");
688 if (!wq) {
689 pr_err("twl4030: workqueue FAIL\n");
690 return -ESRCH;
691 }
692
693 twl4030_irq_base = irq_base;
694
695
696
697
698 twl4030_irq_chip = dummy_irq_chip;
699 twl4030_irq_chip.name = "twl4030";
700
701 twl4030_sih_irq_chip.ack = dummy_irq_chip.ack;
702
703 for (i = irq_base; i < irq_end; i++) {
704 set_irq_chip_and_handler(i, &twl4030_irq_chip,
705 handle_simple_irq);
706 activate_irq(i);
707 }
708 twl4030_irq_next = i;
709 pr_info("twl4030: %s (irq %d) chaining IRQs %d..%d\n", "PIH",
710 irq_num, irq_base, twl4030_irq_next - 1);
711
712
713 status = twl4030_sih_setup(TWL4030_MODULE_INT);
714 if (status < 0) {
715 pr_err("twl4030: sih_setup PWR INT --> %d\n", status);
716 goto fail;
717 }
718
719
720
721
722 init_completion(&irq_event);
723
724 status = request_irq(irq_num, handle_twl4030_pih, IRQF_DISABLED,
725 "TWL4030-PIH", &irq_event);
726 if (status < 0) {
727 pr_err("twl4030: could not claim irq%d: %d\n", irq_num, status);
728 goto fail_rqirq;
729 }
730
731 task = kthread_run(twl4030_irq_thread, (void *)irq_num, "twl4030-irq");
732 if (IS_ERR(task)) {
733 pr_err("twl4030: could not create irq %d thread!\n", irq_num);
734 status = PTR_ERR(task);
735 goto fail_kthread;
736 }
737 return status;
738fail_kthread:
739 free_irq(irq_num, &irq_event);
740fail_rqirq:
741
742fail:
743 for (i = irq_base; i < irq_end; i++)
744 set_irq_chip_and_handler(i, NULL, NULL);
745 destroy_workqueue(wq);
746 wq = NULL;
747 return status;
748}
749
750int twl_exit_irq(void)
751{
752
753 if (twl4030_irq_base) {
754 pr_err("twl4030: can't yet clean up IRQs?\n");
755 return -ENOSYS;
756 }
757 return 0;
758}
759