blob: 7fb97fb0931e54645c7cc5598450be3b349d11b3 [file] [log] [blame]
David VomLehna3a0f8c2009-08-30 17:15:11 -07001/*
2 * Portions copyright (C) 2005-2009 Scientific Atlanta
3 * Portions copyright (C) 2009 Cisco Systems, Inc.
4 *
5 * Modified from arch/mips/kernel/irq-rm7000.c:
6 * Copyright (C) 2003 Ralf Baechle
7 *
8 * This program is free software; you can redistribute it and/or modify it
9 * under the terms of the GNU General Public License as published by the
10 * Free Software Foundation; either version 2 of the License, or (at your
11 * option) any later version.
12 */
13#include <linux/init.h>
14#include <linux/interrupt.h>
15#include <linux/kernel.h>
David Howellsca4d3e672010-10-07 14:08:54 +010016#include <linux/irq.h>
David VomLehna3a0f8c2009-08-30 17:15:11 -070017
18#include <asm/irq_cpu.h>
19#include <asm/mipsregs.h>
20#include <asm/system.h>
21
22#include <asm/mach-powertv/asic_regs.h>
23
Thomas Gleixner2f8d36e2011-03-23 21:09:09 +000024static inline void unmask_asic_irq(struct irq_data *d)
David VomLehna3a0f8c2009-08-30 17:15:11 -070025{
26 unsigned long enable_bit;
Thomas Gleixner2f8d36e2011-03-23 21:09:09 +000027 unsigned int irq = d->irq;
David VomLehna3a0f8c2009-08-30 17:15:11 -070028
29 enable_bit = (1 << (irq & 0x1f));
30
31 switch (irq >> 5) {
32 case 0:
33 asic_write(asic_read(ien_int_0) | enable_bit, ien_int_0);
34 break;
35 case 1:
36 asic_write(asic_read(ien_int_1) | enable_bit, ien_int_1);
37 break;
38 case 2:
39 asic_write(asic_read(ien_int_2) | enable_bit, ien_int_2);
40 break;
41 case 3:
42 asic_write(asic_read(ien_int_3) | enable_bit, ien_int_3);
43 break;
44 default:
45 BUG();
46 }
47}
48
Thomas Gleixner2f8d36e2011-03-23 21:09:09 +000049static inline void mask_asic_irq(struct irq_data *d)
David VomLehna3a0f8c2009-08-30 17:15:11 -070050{
51 unsigned long disable_mask;
Thomas Gleixner2f8d36e2011-03-23 21:09:09 +000052 unsigned int irq = d->irq;
David VomLehna3a0f8c2009-08-30 17:15:11 -070053
54 disable_mask = ~(1 << (irq & 0x1f));
55
56 switch (irq >> 5) {
57 case 0:
58 asic_write(asic_read(ien_int_0) & disable_mask, ien_int_0);
59 break;
60 case 1:
61 asic_write(asic_read(ien_int_1) & disable_mask, ien_int_1);
62 break;
63 case 2:
64 asic_write(asic_read(ien_int_2) & disable_mask, ien_int_2);
65 break;
66 case 3:
67 asic_write(asic_read(ien_int_3) & disable_mask, ien_int_3);
68 break;
69 default:
70 BUG();
71 }
72}
73
74static struct irq_chip asic_irq_chip = {
75 .name = "ASIC Level",
Thomas Gleixner2f8d36e2011-03-23 21:09:09 +000076 .irq_mask = mask_asic_irq,
77 .irq_unmask = unmask_asic_irq,
David VomLehna3a0f8c2009-08-30 17:15:11 -070078};
79
80void __init asic_irq_init(void)
81{
82 int i;
83
84 /* set priority to 0 */
85 write_c0_status(read_c0_status() & ~(0x0000fc00));
86
87 asic_write(0, ien_int_0);
88 asic_write(0, ien_int_1);
89 asic_write(0, ien_int_2);
90 asic_write(0, ien_int_3);
91
92 asic_write(0x0fffffff, int_level_3_3);
93 asic_write(0xffffffff, int_level_3_2);
94 asic_write(0xffffffff, int_level_3_1);
95 asic_write(0xffffffff, int_level_3_0);
96 asic_write(0xffffffff, int_level_2_3);
97 asic_write(0xffffffff, int_level_2_2);
98 asic_write(0xffffffff, int_level_2_1);
99 asic_write(0xffffffff, int_level_2_0);
100 asic_write(0xffffffff, int_level_1_3);
101 asic_write(0xffffffff, int_level_1_2);
102 asic_write(0xffffffff, int_level_1_1);
103 asic_write(0xffffffff, int_level_1_0);
104 asic_write(0xffffffff, int_level_0_3);
105 asic_write(0xffffffff, int_level_0_2);
106 asic_write(0xffffffff, int_level_0_1);
107 asic_write(0xffffffff, int_level_0_0);
108
109 asic_write(0xf, int_int_scan);
110
111 /*
112 * Initialize interrupt handlers.
113 */
114 for (i = 0; i < NR_IRQS; i++)
Thomas Gleixnere4ec7982011-03-27 15:19:28 +0200115 irq_set_chip_and_handler(i, &asic_irq_chip, handle_level_irq);
David VomLehna3a0f8c2009-08-30 17:15:11 -0700116}