Linux-libre 5.3.12-gnu
[librecmc/linux-libre.git] / arch / mips / emma / markeins / irq.c
1 // SPDX-License-Identifier: GPL-2.0-or-later
2 /*
3  *  Copyright (C) NEC Electronics Corporation 2004-2006
4  *
5  *  This file is based on the arch/mips/ddb5xxx/ddb5477/irq.c
6  *
7  *      Copyright 2001 MontaVista Software Inc.
8  */
9 #include <linux/init.h>
10 #include <linux/interrupt.h>
11 #include <linux/irq.h>
12 #include <linux/types.h>
13 #include <linux/ptrace.h>
14 #include <linux/delay.h>
15
16 #include <asm/irq_cpu.h>
17 #include <asm/mipsregs.h>
18 #include <asm/addrspace.h>
19 #include <asm/bootinfo.h>
20
21 #include <asm/emma/emma2rh.h>
22
23 static void emma2rh_irq_enable(struct irq_data *d)
24 {
25         unsigned int irq = d->irq - EMMA2RH_IRQ_BASE;
26         u32 reg_value, reg_bitmask, reg_index;
27
28         reg_index = EMMA2RH_BHIF_INT_EN_0 +
29                     (EMMA2RH_BHIF_INT_EN_1 - EMMA2RH_BHIF_INT_EN_0) * (irq / 32);
30         reg_value = emma2rh_in32(reg_index);
31         reg_bitmask = 0x1 << (irq % 32);
32         emma2rh_out32(reg_index, reg_value | reg_bitmask);
33 }
34
35 static void emma2rh_irq_disable(struct irq_data *d)
36 {
37         unsigned int irq = d->irq - EMMA2RH_IRQ_BASE;
38         u32 reg_value, reg_bitmask, reg_index;
39
40         reg_index = EMMA2RH_BHIF_INT_EN_0 +
41                     (EMMA2RH_BHIF_INT_EN_1 - EMMA2RH_BHIF_INT_EN_0) * (irq / 32);
42         reg_value = emma2rh_in32(reg_index);
43         reg_bitmask = 0x1 << (irq % 32);
44         emma2rh_out32(reg_index, reg_value & ~reg_bitmask);
45 }
46
47 struct irq_chip emma2rh_irq_controller = {
48         .name = "emma2rh_irq",
49         .irq_mask = emma2rh_irq_disable,
50         .irq_unmask = emma2rh_irq_enable,
51 };
52
53 void emma2rh_irq_init(void)
54 {
55         u32 i;
56
57         for (i = 0; i < NUM_EMMA2RH_IRQ; i++)
58                 irq_set_chip_and_handler_name(EMMA2RH_IRQ_BASE + i,
59                                               &emma2rh_irq_controller,
60                                               handle_level_irq, "level");
61 }
62
63 static void emma2rh_sw_irq_enable(struct irq_data *d)
64 {
65         unsigned int irq = d->irq - EMMA2RH_SW_IRQ_BASE;
66         u32 reg;
67
68         reg = emma2rh_in32(EMMA2RH_BHIF_SW_INT_EN);
69         reg |= 1 << irq;
70         emma2rh_out32(EMMA2RH_BHIF_SW_INT_EN, reg);
71 }
72
73 static void emma2rh_sw_irq_disable(struct irq_data *d)
74 {
75         unsigned int irq = d->irq - EMMA2RH_SW_IRQ_BASE;
76         u32 reg;
77
78         reg = emma2rh_in32(EMMA2RH_BHIF_SW_INT_EN);
79         reg &= ~(1 << irq);
80         emma2rh_out32(EMMA2RH_BHIF_SW_INT_EN, reg);
81 }
82
83 struct irq_chip emma2rh_sw_irq_controller = {
84         .name = "emma2rh_sw_irq",
85         .irq_mask = emma2rh_sw_irq_disable,
86         .irq_unmask = emma2rh_sw_irq_enable,
87 };
88
89 void emma2rh_sw_irq_init(void)
90 {
91         u32 i;
92
93         for (i = 0; i < NUM_EMMA2RH_IRQ_SW; i++)
94                 irq_set_chip_and_handler_name(EMMA2RH_SW_IRQ_BASE + i,
95                                               &emma2rh_sw_irq_controller,
96                                               handle_level_irq, "level");
97 }
98
99 static void emma2rh_gpio_irq_enable(struct irq_data *d)
100 {
101         unsigned int irq = d->irq - EMMA2RH_GPIO_IRQ_BASE;
102         u32 reg;
103
104         reg = emma2rh_in32(EMMA2RH_GPIO_INT_MASK);
105         reg |= 1 << irq;
106         emma2rh_out32(EMMA2RH_GPIO_INT_MASK, reg);
107 }
108
109 static void emma2rh_gpio_irq_disable(struct irq_data *d)
110 {
111         unsigned int irq = d->irq - EMMA2RH_GPIO_IRQ_BASE;
112         u32 reg;
113
114         reg = emma2rh_in32(EMMA2RH_GPIO_INT_MASK);
115         reg &= ~(1 << irq);
116         emma2rh_out32(EMMA2RH_GPIO_INT_MASK, reg);
117 }
118
119 static void emma2rh_gpio_irq_ack(struct irq_data *d)
120 {
121         unsigned int irq = d->irq - EMMA2RH_GPIO_IRQ_BASE;
122
123         emma2rh_out32(EMMA2RH_GPIO_INT_ST, ~(1 << irq));
124 }
125
126 static void emma2rh_gpio_irq_mask_ack(struct irq_data *d)
127 {
128         unsigned int irq = d->irq - EMMA2RH_GPIO_IRQ_BASE;
129         u32 reg;
130
131         emma2rh_out32(EMMA2RH_GPIO_INT_ST, ~(1 << irq));
132
133         reg = emma2rh_in32(EMMA2RH_GPIO_INT_MASK);
134         reg &= ~(1 << irq);
135         emma2rh_out32(EMMA2RH_GPIO_INT_MASK, reg);
136 }
137
138 struct irq_chip emma2rh_gpio_irq_controller = {
139         .name = "emma2rh_gpio_irq",
140         .irq_ack = emma2rh_gpio_irq_ack,
141         .irq_mask = emma2rh_gpio_irq_disable,
142         .irq_mask_ack = emma2rh_gpio_irq_mask_ack,
143         .irq_unmask = emma2rh_gpio_irq_enable,
144 };
145
146 void emma2rh_gpio_irq_init(void)
147 {
148         u32 i;
149
150         for (i = 0; i < NUM_EMMA2RH_IRQ_GPIO; i++)
151                 irq_set_chip_and_handler_name(EMMA2RH_GPIO_IRQ_BASE + i,
152                                               &emma2rh_gpio_irq_controller,
153                                               handle_edge_irq, "edge");
154 }
155
156 static struct irqaction irq_cascade = {
157            .handler = no_action,
158            .flags = IRQF_NO_THREAD,
159            .name = "cascade",
160            .dev_id = NULL,
161            .next = NULL,
162 };
163
164 /*
165  * the first level int-handler will jump here if it is a emma2rh irq
166  */
167 void emma2rh_irq_dispatch(void)
168 {
169         u32 intStatus;
170         u32 bitmask;
171         u32 i;
172
173         intStatus = emma2rh_in32(EMMA2RH_BHIF_INT_ST_0) &
174                     emma2rh_in32(EMMA2RH_BHIF_INT_EN_0);
175
176 #ifdef EMMA2RH_SW_CASCADE
177         if (intStatus & (1UL << EMMA2RH_SW_CASCADE)) {
178                 u32 swIntStatus;
179                 swIntStatus = emma2rh_in32(EMMA2RH_BHIF_SW_INT)
180                     & emma2rh_in32(EMMA2RH_BHIF_SW_INT_EN);
181                 for (i = 0, bitmask = 1; i < 32; i++, bitmask <<= 1) {
182                         if (swIntStatus & bitmask) {
183                                 do_IRQ(EMMA2RH_SW_IRQ_BASE + i);
184                                 return;
185                         }
186                 }
187         }
188         /* Skip S/W interrupt */
189         intStatus &= ~(1UL << EMMA2RH_SW_CASCADE);
190 #endif
191
192         for (i = 0, bitmask = 1; i < 32; i++, bitmask <<= 1) {
193                 if (intStatus & bitmask) {
194                         do_IRQ(EMMA2RH_IRQ_BASE + i);
195                         return;
196                 }
197         }
198
199         intStatus = emma2rh_in32(EMMA2RH_BHIF_INT_ST_1) &
200                     emma2rh_in32(EMMA2RH_BHIF_INT_EN_1);
201
202 #ifdef EMMA2RH_GPIO_CASCADE
203         if (intStatus & (1UL << (EMMA2RH_GPIO_CASCADE % 32))) {
204                 u32 gpioIntStatus;
205                 gpioIntStatus = emma2rh_in32(EMMA2RH_GPIO_INT_ST)
206                     & emma2rh_in32(EMMA2RH_GPIO_INT_MASK);
207                 for (i = 0, bitmask = 1; i < 32; i++, bitmask <<= 1) {
208                         if (gpioIntStatus & bitmask) {
209                                 do_IRQ(EMMA2RH_GPIO_IRQ_BASE + i);
210                                 return;
211                         }
212                 }
213         }
214         /* Skip GPIO interrupt */
215         intStatus &= ~(1UL << (EMMA2RH_GPIO_CASCADE % 32));
216 #endif
217
218         for (i = 32, bitmask = 1; i < 64; i++, bitmask <<= 1) {
219                 if (intStatus & bitmask) {
220                         do_IRQ(EMMA2RH_IRQ_BASE + i);
221                         return;
222                 }
223         }
224
225         intStatus = emma2rh_in32(EMMA2RH_BHIF_INT_ST_2) &
226                     emma2rh_in32(EMMA2RH_BHIF_INT_EN_2);
227
228         for (i = 64, bitmask = 1; i < 96; i++, bitmask <<= 1) {
229                 if (intStatus & bitmask) {
230                         do_IRQ(EMMA2RH_IRQ_BASE + i);
231                         return;
232                 }
233         }
234 }
235
236 void __init arch_init_irq(void)
237 {
238         u32 reg;
239
240         /* by default, interrupts are disabled. */
241         emma2rh_out32(EMMA2RH_BHIF_INT_EN_0, 0);
242         emma2rh_out32(EMMA2RH_BHIF_INT_EN_1, 0);
243         emma2rh_out32(EMMA2RH_BHIF_INT_EN_2, 0);
244         emma2rh_out32(EMMA2RH_BHIF_INT1_EN_0, 0);
245         emma2rh_out32(EMMA2RH_BHIF_INT1_EN_1, 0);
246         emma2rh_out32(EMMA2RH_BHIF_INT1_EN_2, 0);
247         emma2rh_out32(EMMA2RH_BHIF_SW_INT_EN, 0);
248
249         clear_c0_status(0xff00);
250         set_c0_status(0x0400);
251
252 #define GPIO_PCI (0xf<<15)
253         /* setup GPIO interrupt for PCI interface */
254         /* direction input */
255         reg = emma2rh_in32(EMMA2RH_GPIO_DIR);
256         emma2rh_out32(EMMA2RH_GPIO_DIR, reg & ~GPIO_PCI);
257         /* disable interrupt */
258         reg = emma2rh_in32(EMMA2RH_GPIO_INT_MASK);
259         emma2rh_out32(EMMA2RH_GPIO_INT_MASK, reg & ~GPIO_PCI);
260         /* level triggerd */
261         reg = emma2rh_in32(EMMA2RH_GPIO_INT_MODE);
262         emma2rh_out32(EMMA2RH_GPIO_INT_MODE, reg | GPIO_PCI);
263         reg = emma2rh_in32(EMMA2RH_GPIO_INT_CND_A);
264         emma2rh_out32(EMMA2RH_GPIO_INT_CND_A, reg & (~GPIO_PCI));
265         /* interrupt clear */
266         emma2rh_out32(EMMA2RH_GPIO_INT_ST, ~GPIO_PCI);
267
268         /* init all controllers */
269         emma2rh_irq_init();
270         emma2rh_sw_irq_init();
271         emma2rh_gpio_irq_init();
272         mips_cpu_irq_init();
273
274         /* setup cascade interrupts */
275         setup_irq(EMMA2RH_IRQ_BASE + EMMA2RH_SW_CASCADE, &irq_cascade);
276         setup_irq(EMMA2RH_IRQ_BASE + EMMA2RH_GPIO_CASCADE, &irq_cascade);
277         setup_irq(MIPS_CPU_IRQ_BASE + 2, &irq_cascade);
278 }
279
280 asmlinkage void plat_irq_dispatch(void)
281 {
282         unsigned int pending = read_c0_status() & read_c0_cause() & ST0_IM;
283
284         if (pending & STATUSF_IP7)
285                 do_IRQ(MIPS_CPU_IRQ_BASE + 7);
286         else if (pending & STATUSF_IP2)
287                 emma2rh_irq_dispatch();
288         else if (pending & STATUSF_IP1)
289                 do_IRQ(MIPS_CPU_IRQ_BASE + 1);
290         else if (pending & STATUSF_IP0)
291                 do_IRQ(MIPS_CPU_IRQ_BASE + 0);
292         else
293                 spurious_interrupt();
294 }