Sparc32: move intbit_to_level table back to slavio_intctl.c
[qemu] / hw / slavio_intctl.c
1 /*
2  * QEMU Sparc SLAVIO interrupt controller emulation
3  *
4  * Copyright (c) 2003-2005 Fabrice Bellard
5  *
6  * Permission is hereby granted, free of charge, to any person obtaining a copy
7  * of this software and associated documentation files (the "Software"), to deal
8  * in the Software without restriction, including without limitation the rights
9  * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10  * copies of the Software, and to permit persons to whom the Software is
11  * furnished to do so, subject to the following conditions:
12  *
13  * The above copyright notice and this permission notice shall be included in
14  * all copies or substantial portions of the Software.
15  *
16  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
19  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
22  * THE SOFTWARE.
23  */
24
25 #include "sun4m.h"
26 #include "monitor.h"
27 #include "sysbus.h"
28
29 //#define DEBUG_IRQ_COUNT
30 //#define DEBUG_IRQ
31
32 #ifdef DEBUG_IRQ
33 #define DPRINTF(fmt, ...)                                       \
34     do { printf("IRQ: " fmt , ## __VA_ARGS__); } while (0)
35 #else
36 #define DPRINTF(fmt, ...)
37 #endif
38
39 /*
40  * Registers of interrupt controller in sun4m.
41  *
42  * This is the interrupt controller part of chip STP2001 (Slave I/O), also
43  * produced as NCR89C105. See
44  * http://www.ibiblio.org/pub/historic-linux/early-ports/Sparc/NCR/NCR89C105.txt
45  *
46  * There is a system master controller and one for each cpu.
47  *
48  */
49
50 #define MAX_CPUS 16
51 #define MAX_PILS 16
52
53 struct SLAVIO_INTCTLState;
54
55 typedef struct SLAVIO_CPUINTCTLState {
56     uint32_t intreg_pending;
57     struct SLAVIO_INTCTLState *master;
58     uint32_t cpu;
59 } SLAVIO_CPUINTCTLState;
60
61 typedef struct SLAVIO_INTCTLState {
62     SysBusDevice busdev;
63     uint32_t intregm_pending;
64     uint32_t intregm_disabled;
65     uint32_t target_cpu;
66 #ifdef DEBUG_IRQ_COUNT
67     uint64_t irq_count[32];
68 #endif
69     qemu_irq cpu_irqs[MAX_CPUS][MAX_PILS];
70     uint32_t cputimer_lbit, cputimer_mbit;
71     uint32_t cputimer_bit;
72     uint32_t pil_out[MAX_CPUS];
73     SLAVIO_CPUINTCTLState slaves[MAX_CPUS];
74 } SLAVIO_INTCTLState;
75
76 #define INTCTL_MAXADDR 0xf
77 #define INTCTL_SIZE (INTCTL_MAXADDR + 1)
78 #define INTCTLM_SIZE 0x14
79 #define MASTER_IRQ_MASK ~0x0fa2007f
80 #define MASTER_DISABLE 0x80000000
81 #define CPU_SOFTIRQ_MASK 0xfffe0000
82 #define CPU_IRQ_INT15_IN 0x0004000
83 #define CPU_IRQ_INT15_MASK 0x80000000
84
85 static void slavio_check_interrupts(SLAVIO_INTCTLState *s, int set_irqs);
86
87 // per-cpu interrupt controller
88 static uint32_t slavio_intctl_mem_readl(void *opaque, target_phys_addr_t addr)
89 {
90     SLAVIO_CPUINTCTLState *s = opaque;
91     uint32_t saddr, ret;
92
93     saddr = addr >> 2;
94     switch (saddr) {
95     case 0:
96         ret = s->intreg_pending;
97         break;
98     default:
99         ret = 0;
100         break;
101     }
102     DPRINTF("read cpu %d reg 0x" TARGET_FMT_plx " = %x\n", s->cpu, addr, ret);
103
104     return ret;
105 }
106
107 static void slavio_intctl_mem_writel(void *opaque, target_phys_addr_t addr,
108                                      uint32_t val)
109 {
110     SLAVIO_CPUINTCTLState *s = opaque;
111     uint32_t saddr;
112
113     saddr = addr >> 2;
114     DPRINTF("write cpu %d reg 0x" TARGET_FMT_plx " = %x\n", s->cpu, addr, val);
115     switch (saddr) {
116     case 1: // clear pending softints
117         if (val & CPU_IRQ_INT15_IN)
118             val |= CPU_IRQ_INT15_MASK;
119         val &= CPU_SOFTIRQ_MASK;
120         s->intreg_pending &= ~val;
121         slavio_check_interrupts(s->master, 1);
122         DPRINTF("Cleared cpu %d irq mask %x, curmask %x\n", s->cpu, val,
123                 s->intreg_pending);
124         break;
125     case 2: // set softint
126         val &= CPU_SOFTIRQ_MASK;
127         s->intreg_pending |= val;
128         slavio_check_interrupts(s->master, 1);
129         DPRINTF("Set cpu %d irq mask %x, curmask %x\n", s->cpu, val,
130                 s->intreg_pending);
131         break;
132     default:
133         break;
134     }
135 }
136
137 static CPUReadMemoryFunc *slavio_intctl_mem_read[3] = {
138     NULL,
139     NULL,
140     slavio_intctl_mem_readl,
141 };
142
143 static CPUWriteMemoryFunc *slavio_intctl_mem_write[3] = {
144     NULL,
145     NULL,
146     slavio_intctl_mem_writel,
147 };
148
149 // master system interrupt controller
150 static uint32_t slavio_intctlm_mem_readl(void *opaque, target_phys_addr_t addr)
151 {
152     SLAVIO_INTCTLState *s = opaque;
153     uint32_t saddr, ret;
154
155     saddr = addr >> 2;
156     switch (saddr) {
157     case 0:
158         ret = s->intregm_pending & ~MASTER_DISABLE;
159         break;
160     case 1:
161         ret = s->intregm_disabled & MASTER_IRQ_MASK;
162         break;
163     case 4:
164         ret = s->target_cpu;
165         break;
166     default:
167         ret = 0;
168         break;
169     }
170     DPRINTF("read system reg 0x" TARGET_FMT_plx " = %x\n", addr, ret);
171
172     return ret;
173 }
174
175 static void slavio_intctlm_mem_writel(void *opaque, target_phys_addr_t addr,
176                                       uint32_t val)
177 {
178     SLAVIO_INTCTLState *s = opaque;
179     uint32_t saddr;
180
181     saddr = addr >> 2;
182     DPRINTF("write system reg 0x" TARGET_FMT_plx " = %x\n", addr, val);
183     switch (saddr) {
184     case 2: // clear (enable)
185         // Force clear unused bits
186         val &= MASTER_IRQ_MASK;
187         s->intregm_disabled &= ~val;
188         DPRINTF("Enabled master irq mask %x, curmask %x\n", val,
189                 s->intregm_disabled);
190         slavio_check_interrupts(s, 1);
191         break;
192     case 3: // set (disable, clear pending)
193         // Force clear unused bits
194         val &= MASTER_IRQ_MASK;
195         s->intregm_disabled |= val;
196         s->intregm_pending &= ~val;
197         slavio_check_interrupts(s, 1);
198         DPRINTF("Disabled master irq mask %x, curmask %x\n", val,
199                 s->intregm_disabled);
200         break;
201     case 4:
202         s->target_cpu = val & (MAX_CPUS - 1);
203         slavio_check_interrupts(s, 1);
204         DPRINTF("Set master irq cpu %d\n", s->target_cpu);
205         break;
206     default:
207         break;
208     }
209 }
210
211 static CPUReadMemoryFunc *slavio_intctlm_mem_read[3] = {
212     NULL,
213     NULL,
214     slavio_intctlm_mem_readl,
215 };
216
217 static CPUWriteMemoryFunc *slavio_intctlm_mem_write[3] = {
218     NULL,
219     NULL,
220     slavio_intctlm_mem_writel,
221 };
222
223 void slavio_pic_info(Monitor *mon, void *opaque)
224 {
225     SLAVIO_INTCTLState *s = opaque;
226     int i;
227
228     for (i = 0; i < MAX_CPUS; i++) {
229         monitor_printf(mon, "per-cpu %d: pending 0x%08x\n", i,
230                        s->slaves[i].intreg_pending);
231     }
232     monitor_printf(mon, "master: pending 0x%08x, disabled 0x%08x\n",
233                    s->intregm_pending, s->intregm_disabled);
234 }
235
236 void slavio_irq_info(Monitor *mon, void *opaque)
237 {
238 #ifndef DEBUG_IRQ_COUNT
239     monitor_printf(mon, "irq statistic code not compiled.\n");
240 #else
241     SLAVIO_INTCTLState *s = opaque;
242     int i;
243     int64_t count;
244
245     monitor_printf(mon, "IRQ statistics:\n");
246     for (i = 0; i < 32; i++) {
247         count = s->irq_count[i];
248         if (count > 0)
249             monitor_printf(mon, "%2d: %" PRId64 "\n", i, count);
250     }
251 #endif
252 }
253
254 static const uint32_t intbit_to_level[] = {
255     2, 3, 5, 7, 9, 11, 0, 14,   3, 5, 7, 9, 11, 13, 12, 12,
256     6, 0, 4, 10, 8, 0, 11, 0,   0, 0, 0, 0, 15, 0, 15, 0,
257 };
258
259 static void slavio_check_interrupts(SLAVIO_INTCTLState *s, int set_irqs)
260 {
261     uint32_t pending = s->intregm_pending, pil_pending;
262     unsigned int i, j;
263
264     pending &= ~s->intregm_disabled;
265
266     DPRINTF("pending %x disabled %x\n", pending, s->intregm_disabled);
267     for (i = 0; i < MAX_CPUS; i++) {
268         pil_pending = 0;
269         if (pending && !(s->intregm_disabled & MASTER_DISABLE) &&
270             (i == s->target_cpu)) {
271             for (j = 0; j < 32; j++) {
272                 if (pending & (1 << j))
273                     pil_pending |= 1 << intbit_to_level[j];
274             }
275         }
276         pil_pending |= (s->slaves[i].intreg_pending & CPU_SOFTIRQ_MASK) >> 16;
277
278         if (set_irqs) {
279             for (j = 0; j < MAX_PILS; j++) {
280                 if (pil_pending & (1 << j)) {
281                     if (!(s->pil_out[i] & (1 << j))) {
282                         qemu_irq_raise(s->cpu_irqs[i][j]);
283                     }
284                 } else {
285                     if (s->pil_out[i] & (1 << j)) {
286                         qemu_irq_lower(s->cpu_irqs[i][j]);
287                     }
288                 }
289             }
290         }
291         s->pil_out[i] = pil_pending;
292     }
293 }
294
295 /*
296  * "irq" here is the bit number in the system interrupt register to
297  * separate serial and keyboard interrupts sharing a level.
298  */
299 static void slavio_set_irq(void *opaque, int irq, int level)
300 {
301     SLAVIO_INTCTLState *s = opaque;
302     uint32_t mask = 1 << irq;
303     uint32_t pil = intbit_to_level[irq];
304
305     DPRINTF("Set cpu %d irq %d -> pil %d level %d\n", s->target_cpu, irq, pil,
306             level);
307     if (pil > 0) {
308         if (level) {
309 #ifdef DEBUG_IRQ_COUNT
310             s->irq_count[pil]++;
311 #endif
312             s->intregm_pending |= mask;
313             s->slaves[s->target_cpu].intreg_pending |= 1 << pil;
314         } else {
315             s->intregm_pending &= ~mask;
316             s->slaves[s->target_cpu].intreg_pending &= ~(1 << pil);
317         }
318         slavio_check_interrupts(s, 1);
319     }
320 }
321
322 static void slavio_set_timer_irq_cpu(void *opaque, int cpu, int level)
323 {
324     SLAVIO_INTCTLState *s = opaque;
325
326     DPRINTF("Set cpu %d local timer level %d\n", cpu, level);
327
328     if (level) {
329         s->intregm_pending |= s->cputimer_mbit;
330         s->slaves[cpu].intreg_pending |= s->cputimer_lbit;
331     } else {
332         s->intregm_pending &= ~s->cputimer_mbit;
333         s->slaves[cpu].intreg_pending &= ~s->cputimer_lbit;
334     }
335
336     slavio_check_interrupts(s, 1);
337 }
338
339 static void slavio_set_irq_all(void *opaque, int irq, int level)
340 {
341     if (irq < 32) {
342         slavio_set_irq(opaque, irq, level);
343     } else {
344         slavio_set_timer_irq_cpu(opaque, irq - 32, level);
345     }
346 }
347
348 static void slavio_intctl_save(QEMUFile *f, void *opaque)
349 {
350     SLAVIO_INTCTLState *s = opaque;
351     int i;
352
353     for (i = 0; i < MAX_CPUS; i++) {
354         qemu_put_be32s(f, &s->slaves[i].intreg_pending);
355     }
356     qemu_put_be32s(f, &s->intregm_pending);
357     qemu_put_be32s(f, &s->intregm_disabled);
358     qemu_put_be32s(f, &s->target_cpu);
359 }
360
361 static int slavio_intctl_load(QEMUFile *f, void *opaque, int version_id)
362 {
363     SLAVIO_INTCTLState *s = opaque;
364     int i;
365
366     if (version_id != 1)
367         return -EINVAL;
368
369     for (i = 0; i < MAX_CPUS; i++) {
370         qemu_get_be32s(f, &s->slaves[i].intreg_pending);
371     }
372     qemu_get_be32s(f, &s->intregm_pending);
373     qemu_get_be32s(f, &s->intregm_disabled);
374     qemu_get_be32s(f, &s->target_cpu);
375     slavio_check_interrupts(s, 0);
376     return 0;
377 }
378
379 static void slavio_intctl_reset(void *opaque)
380 {
381     SLAVIO_INTCTLState *s = opaque;
382     int i;
383
384     for (i = 0; i < MAX_CPUS; i++) {
385         s->slaves[i].intreg_pending = 0;
386     }
387     s->intregm_disabled = ~MASTER_IRQ_MASK;
388     s->intregm_pending = 0;
389     s->target_cpu = 0;
390     slavio_check_interrupts(s, 0);
391 }
392
393 static void slavio_intctl_init1(SysBusDevice *dev)
394 {
395     SLAVIO_INTCTLState *s = FROM_SYSBUS(SLAVIO_INTCTLState, dev);
396     int io_memory;
397     unsigned int i, j;
398
399     qdev_init_gpio_in(&dev->qdev, slavio_set_irq_all, 32 + MAX_CPUS);
400     io_memory = cpu_register_io_memory(slavio_intctlm_mem_read,
401                                        slavio_intctlm_mem_write, s);
402     sysbus_init_mmio(dev, INTCTLM_SIZE, io_memory);
403     s->cputimer_mbit = 1 << s->cputimer_bit;
404     s->cputimer_lbit = 1 << intbit_to_level[s->cputimer_bit];
405
406     for (i = 0; i < MAX_CPUS; i++) {
407         for (j = 0; j < MAX_PILS; j++) {
408             sysbus_init_irq(dev, &s->cpu_irqs[i][j]);
409         }
410         io_memory = cpu_register_io_memory(slavio_intctl_mem_read,
411                                            slavio_intctl_mem_write,
412                                            &s->slaves[i]);
413         sysbus_init_mmio(dev, INTCTL_SIZE, io_memory);
414         s->slaves[i].cpu = i;
415         s->slaves[i].master = s;
416     }
417     register_savevm("slavio_intctl", -1, 1, slavio_intctl_save,
418                     slavio_intctl_load, s);
419     qemu_register_reset(slavio_intctl_reset, s);
420     slavio_intctl_reset(s);
421 }
422
423 static SysBusDeviceInfo slavio_intctl_info = {
424     .init = slavio_intctl_init1,
425     .qdev.name  = "slavio_intctl",
426     .qdev.size  = sizeof(SLAVIO_INTCTLState),
427     .qdev.props = (Property[]) {
428         {
429             .name = "cputimer_bit",
430             .info = &qdev_prop_uint32,
431             .offset = offsetof(SLAVIO_INTCTLState, cputimer_bit),
432         },
433         {/* end of property list */}
434     }
435 };
436
437 static void slavio_intctl_register_devices(void)
438 {
439     sysbus_register_withprop(&slavio_intctl_info);
440 }
441
442 device_init(slavio_intctl_register_devices)