Statistics
| Branch: | Revision:

root / hw / etraxfs_pic.c @ 6693665a

History | View | Annotate | Download (4.3 kB)

1 e62b5b13 edgar_igl
/*
2 e62b5b13 edgar_igl
 * QEMU ETRAX Interrupt Controller.
3 e62b5b13 edgar_igl
 *
4 e62b5b13 edgar_igl
 * Copyright (c) 2008 Edgar E. Iglesias, Axis Communications AB.
5 e62b5b13 edgar_igl
 *
6 e62b5b13 edgar_igl
 * Permission is hereby granted, free of charge, to any person obtaining a copy
7 e62b5b13 edgar_igl
 * of this software and associated documentation files (the "Software"), to deal
8 e62b5b13 edgar_igl
 * in the Software without restriction, including without limitation the rights
9 e62b5b13 edgar_igl
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10 e62b5b13 edgar_igl
 * copies of the Software, and to permit persons to whom the Software is
11 e62b5b13 edgar_igl
 * furnished to do so, subject to the following conditions:
12 e62b5b13 edgar_igl
 *
13 e62b5b13 edgar_igl
 * The above copyright notice and this permission notice shall be included in
14 e62b5b13 edgar_igl
 * all copies or substantial portions of the Software.
15 e62b5b13 edgar_igl
 *
16 e62b5b13 edgar_igl
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 e62b5b13 edgar_igl
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 e62b5b13 edgar_igl
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
19 e62b5b13 edgar_igl
 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 e62b5b13 edgar_igl
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21 e62b5b13 edgar_igl
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
22 e62b5b13 edgar_igl
 * THE SOFTWARE.
23 e62b5b13 edgar_igl
 */
24 e62b5b13 edgar_igl
25 fd6dc90b Edgar E. Iglesias
#include "sysbus.h"
26 e62b5b13 edgar_igl
#include "hw.h"
27 1ad2134f Paul Brook
//#include "pc.h"
28 1ad2134f Paul Brook
//#include "etraxfs.h"
29 e62b5b13 edgar_igl
30 e62b5b13 edgar_igl
#define D(x)
31 e62b5b13 edgar_igl
32 979d98ca Edgar E. Iglesias
#define R_RW_MASK   0
33 979d98ca Edgar E. Iglesias
#define R_R_VECT    1
34 979d98ca Edgar E. Iglesias
#define R_R_MASKED_VECT 2
35 979d98ca Edgar E. Iglesias
#define R_R_NMI     3
36 979d98ca Edgar E. Iglesias
#define R_R_GURU    4
37 979d98ca Edgar E. Iglesias
#define R_MAX       5
38 8d13fcc0 Edgar E. Iglesias
39 fd6dc90b Edgar E. Iglesias
struct etrax_pic
40 e62b5b13 edgar_igl
{
41 fd6dc90b Edgar E. Iglesias
    SysBusDevice busdev;
42 fd6dc90b Edgar E. Iglesias
    uint32_t *interrupt_vector;
43 fd6dc90b Edgar E. Iglesias
    qemu_irq parent_irq;
44 fd6dc90b Edgar E. Iglesias
    qemu_irq parent_nmi;
45 979d98ca Edgar E. Iglesias
    uint32_t regs[R_MAX];
46 e62b5b13 edgar_igl
};
47 e62b5b13 edgar_igl
48 fd6dc90b Edgar E. Iglesias
static void pic_update(struct etrax_pic *fs)
49 979d98ca Edgar E. Iglesias
{   
50 979d98ca Edgar E. Iglesias
    uint32_t vector = 0;
51 979d98ca Edgar E. Iglesias
    int i;
52 979d98ca Edgar E. Iglesias
53 979d98ca Edgar E. Iglesias
    fs->regs[R_R_MASKED_VECT] = fs->regs[R_R_VECT] & fs->regs[R_RW_MASK];
54 979d98ca Edgar E. Iglesias
55 979d98ca Edgar E. Iglesias
    /* The ETRAX interrupt controller signals interrupts to teh core
56 979d98ca Edgar E. Iglesias
       through an interrupt request wire and an irq vector bus. If 
57 979d98ca Edgar E. Iglesias
       multiple interrupts are simultaneously active it chooses vector 
58 979d98ca Edgar E. Iglesias
       0x30 and lets the sw choose the priorities.  */
59 979d98ca Edgar E. Iglesias
    if (fs->regs[R_R_MASKED_VECT]) {
60 979d98ca Edgar E. Iglesias
        uint32_t mv = fs->regs[R_R_MASKED_VECT];
61 979d98ca Edgar E. Iglesias
        for (i = 0; i < 31; i++) {
62 979d98ca Edgar E. Iglesias
            if (mv & 1) {
63 979d98ca Edgar E. Iglesias
                vector = 0x31 + i;
64 979d98ca Edgar E. Iglesias
                /* Check for multiple interrupts.  */
65 979d98ca Edgar E. Iglesias
                if (mv > 1)
66 979d98ca Edgar E. Iglesias
                    vector = 0x30;
67 979d98ca Edgar E. Iglesias
                break;
68 979d98ca Edgar E. Iglesias
            }
69 979d98ca Edgar E. Iglesias
            mv >>= 1;
70 979d98ca Edgar E. Iglesias
        }
71 979d98ca Edgar E. Iglesias
    }
72 fd6dc90b Edgar E. Iglesias
73 fd6dc90b Edgar E. Iglesias
    if (fs->interrupt_vector) {
74 fd6dc90b Edgar E. Iglesias
        *fs->interrupt_vector = vector;
75 fd6dc90b Edgar E. Iglesias
    }
76 fd6dc90b Edgar E. Iglesias
    qemu_set_irq(fs->parent_irq, !!vector);
77 e62b5b13 edgar_igl
}
78 e62b5b13 edgar_igl
79 e62b5b13 edgar_igl
static uint32_t pic_readl (void *opaque, target_phys_addr_t addr)
80 e62b5b13 edgar_igl
{
81 fd6dc90b Edgar E. Iglesias
    struct etrax_pic *fs = opaque;
82 979d98ca Edgar E. Iglesias
    uint32_t rval;
83 e62b5b13 edgar_igl
84 979d98ca Edgar E. Iglesias
    rval = fs->regs[addr >> 2];
85 979d98ca Edgar E. Iglesias
    D(printf("%s %x=%x\n", __func__, addr, rval));
86 979d98ca Edgar E. Iglesias
    return rval;
87 e62b5b13 edgar_igl
}
88 e62b5b13 edgar_igl
89 e62b5b13 edgar_igl
static void
90 e62b5b13 edgar_igl
pic_writel (void *opaque, target_phys_addr_t addr, uint32_t value)
91 e62b5b13 edgar_igl
{
92 fd6dc90b Edgar E. Iglesias
    struct etrax_pic *fs = opaque;
93 979d98ca Edgar E. Iglesias
    D(printf("%s addr=%x val=%x\n", __func__, addr, value));
94 8d13fcc0 Edgar E. Iglesias
95 979d98ca Edgar E. Iglesias
    if (addr == R_RW_MASK) {
96 979d98ca Edgar E. Iglesias
        fs->regs[R_RW_MASK] = value;
97 979d98ca Edgar E. Iglesias
        pic_update(fs);
98 979d98ca Edgar E. Iglesias
    }
99 e62b5b13 edgar_igl
}
100 e62b5b13 edgar_igl
101 e62b5b13 edgar_igl
static CPUReadMemoryFunc *pic_read[] = {
102 979d98ca Edgar E. Iglesias
    NULL, NULL,
103 979d98ca Edgar E. Iglesias
    &pic_readl,
104 e62b5b13 edgar_igl
};
105 e62b5b13 edgar_igl
106 e62b5b13 edgar_igl
static CPUWriteMemoryFunc *pic_write[] = {
107 979d98ca Edgar E. Iglesias
    NULL, NULL,
108 979d98ca Edgar E. Iglesias
    &pic_writel,
109 e62b5b13 edgar_igl
};
110 e62b5b13 edgar_igl
111 5ef98b47 edgar_igl
static void nmi_handler(void *opaque, int irq, int level)
112 979d98ca Edgar E. Iglesias
{   
113 fd6dc90b Edgar E. Iglesias
    struct etrax_pic *fs = (void *)opaque;
114 979d98ca Edgar E. Iglesias
    uint32_t mask;
115 979d98ca Edgar E. Iglesias
116 979d98ca Edgar E. Iglesias
    mask = 1 << irq;
117 979d98ca Edgar E. Iglesias
    if (level)
118 979d98ca Edgar E. Iglesias
        fs->regs[R_R_NMI] |= mask;
119 979d98ca Edgar E. Iglesias
    else
120 979d98ca Edgar E. Iglesias
        fs->regs[R_R_NMI] &= ~mask;
121 979d98ca Edgar E. Iglesias
122 fd6dc90b Edgar E. Iglesias
    qemu_set_irq(fs->parent_nmi, !!fs->regs[R_R_NMI]);
123 5ef98b47 edgar_igl
}
124 5ef98b47 edgar_igl
125 73cfd29f Edgar E. Iglesias
static void irq_handler(void *opaque, int irq, int level)
126 979d98ca Edgar E. Iglesias
{   
127 fd6dc90b Edgar E. Iglesias
    struct etrax_pic *fs = (void *)opaque;
128 73cfd29f Edgar E. Iglesias
129 979d98ca Edgar E. Iglesias
    if (irq >= 30)
130 979d98ca Edgar E. Iglesias
        return nmi_handler(opaque, irq, level);
131 73cfd29f Edgar E. Iglesias
132 979d98ca Edgar E. Iglesias
    irq -= 1;
133 979d98ca Edgar E. Iglesias
    fs->regs[R_R_VECT] &= ~(1 << irq);
134 979d98ca Edgar E. Iglesias
    fs->regs[R_R_VECT] |= (!!level << irq);
135 979d98ca Edgar E. Iglesias
    pic_update(fs);
136 5ef98b47 edgar_igl
}
137 5ef98b47 edgar_igl
138 fd6dc90b Edgar E. Iglesias
static void etraxfs_pic_init(SysBusDevice *dev)
139 e62b5b13 edgar_igl
{
140 fd6dc90b Edgar E. Iglesias
    struct etrax_pic *s = FROM_SYSBUS(typeof (*s), dev);
141 979d98ca Edgar E. Iglesias
    int intr_vect_regs;
142 e62b5b13 edgar_igl
143 fd6dc90b Edgar E. Iglesias
    s->interrupt_vector = qdev_get_prop_ptr(&dev->qdev, "interrupt_vector");
144 067a3ddc Paul Brook
    qdev_init_gpio_in(&dev->qdev, irq_handler, 32);
145 fd6dc90b Edgar E. Iglesias
    sysbus_init_irq(dev, &s->parent_irq);
146 fd6dc90b Edgar E. Iglesias
    sysbus_init_irq(dev, &s->parent_nmi);
147 e62b5b13 edgar_igl
148 fd6dc90b Edgar E. Iglesias
    intr_vect_regs = cpu_register_io_memory(0, pic_read, pic_write, s);
149 fd6dc90b Edgar E. Iglesias
    sysbus_init_mmio(dev, R_MAX * 4, intr_vect_regs);
150 e62b5b13 edgar_igl
}
151 fd6dc90b Edgar E. Iglesias
152 fd6dc90b Edgar E. Iglesias
static void etraxfs_pic_register(void)
153 fd6dc90b Edgar E. Iglesias
{
154 fd6dc90b Edgar E. Iglesias
    sysbus_register_dev("etraxfs,pic", sizeof (struct etrax_pic),
155 fd6dc90b Edgar E. Iglesias
                        etraxfs_pic_init);
156 fd6dc90b Edgar E. Iglesias
}
157 fd6dc90b Edgar E. Iglesias
158 fd6dc90b Edgar E. Iglesias
device_init(etraxfs_pic_register)