Statistics
| Branch: | Revision:

root / hw / etraxfs_pic.c @ 37952117

History | View | Annotate | Download (4.9 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 5dd25f36 Edgar E. Iglesias
    MemoryRegion mmio;
43 ddde095c Gerd Hoffmann
    void *interrupt_vector;
44 fd6dc90b Edgar E. Iglesias
    qemu_irq parent_irq;
45 fd6dc90b Edgar E. Iglesias
    qemu_irq parent_nmi;
46 979d98ca Edgar E. Iglesias
    uint32_t regs[R_MAX];
47 e62b5b13 edgar_igl
};
48 e62b5b13 edgar_igl
49 fd6dc90b Edgar E. Iglesias
static void pic_update(struct etrax_pic *fs)
50 979d98ca Edgar E. Iglesias
{   
51 979d98ca Edgar E. Iglesias
    uint32_t vector = 0;
52 979d98ca Edgar E. Iglesias
    int i;
53 979d98ca Edgar E. Iglesias
54 979d98ca Edgar E. Iglesias
    fs->regs[R_R_MASKED_VECT] = fs->regs[R_R_VECT] & fs->regs[R_RW_MASK];
55 979d98ca Edgar E. Iglesias
56 66a0a2cb Dong Xu Wang
    /* The ETRAX interrupt controller signals interrupts to the core
57 979d98ca Edgar E. Iglesias
       through an interrupt request wire and an irq vector bus. If 
58 979d98ca Edgar E. Iglesias
       multiple interrupts are simultaneously active it chooses vector 
59 979d98ca Edgar E. Iglesias
       0x30 and lets the sw choose the priorities.  */
60 979d98ca Edgar E. Iglesias
    if (fs->regs[R_R_MASKED_VECT]) {
61 979d98ca Edgar E. Iglesias
        uint32_t mv = fs->regs[R_R_MASKED_VECT];
62 979d98ca Edgar E. Iglesias
        for (i = 0; i < 31; i++) {
63 979d98ca Edgar E. Iglesias
            if (mv & 1) {
64 979d98ca Edgar E. Iglesias
                vector = 0x31 + i;
65 979d98ca Edgar E. Iglesias
                /* Check for multiple interrupts.  */
66 979d98ca Edgar E. Iglesias
                if (mv > 1)
67 979d98ca Edgar E. Iglesias
                    vector = 0x30;
68 979d98ca Edgar E. Iglesias
                break;
69 979d98ca Edgar E. Iglesias
            }
70 979d98ca Edgar E. Iglesias
            mv >>= 1;
71 979d98ca Edgar E. Iglesias
        }
72 979d98ca Edgar E. Iglesias
    }
73 fd6dc90b Edgar E. Iglesias
74 fd6dc90b Edgar E. Iglesias
    if (fs->interrupt_vector) {
75 ddde095c Gerd Hoffmann
        /* hack alert: ptr property */
76 ddde095c Gerd Hoffmann
        *(uint32_t*)(fs->interrupt_vector) = vector;
77 fd6dc90b Edgar E. Iglesias
    }
78 fd6dc90b Edgar E. Iglesias
    qemu_set_irq(fs->parent_irq, !!vector);
79 e62b5b13 edgar_igl
}
80 e62b5b13 edgar_igl
81 5dd25f36 Edgar E. Iglesias
static uint64_t
82 5dd25f36 Edgar E. Iglesias
pic_read(void *opaque, target_phys_addr_t addr, unsigned int size)
83 e62b5b13 edgar_igl
{
84 fd6dc90b Edgar E. Iglesias
    struct etrax_pic *fs = opaque;
85 979d98ca Edgar E. Iglesias
    uint32_t rval;
86 e62b5b13 edgar_igl
87 979d98ca Edgar E. Iglesias
    rval = fs->regs[addr >> 2];
88 979d98ca Edgar E. Iglesias
    D(printf("%s %x=%x\n", __func__, addr, rval));
89 979d98ca Edgar E. Iglesias
    return rval;
90 e62b5b13 edgar_igl
}
91 e62b5b13 edgar_igl
92 5dd25f36 Edgar E. Iglesias
static void pic_write(void *opaque, target_phys_addr_t addr,
93 5dd25f36 Edgar E. Iglesias
                      uint64_t value, unsigned int size)
94 e62b5b13 edgar_igl
{
95 fd6dc90b Edgar E. Iglesias
    struct etrax_pic *fs = opaque;
96 979d98ca Edgar E. Iglesias
    D(printf("%s addr=%x val=%x\n", __func__, addr, value));
97 8d13fcc0 Edgar E. Iglesias
98 979d98ca Edgar E. Iglesias
    if (addr == R_RW_MASK) {
99 979d98ca Edgar E. Iglesias
        fs->regs[R_RW_MASK] = value;
100 979d98ca Edgar E. Iglesias
        pic_update(fs);
101 979d98ca Edgar E. Iglesias
    }
102 e62b5b13 edgar_igl
}
103 e62b5b13 edgar_igl
104 5dd25f36 Edgar E. Iglesias
static const MemoryRegionOps pic_ops = {
105 5dd25f36 Edgar E. Iglesias
    .read = pic_read,
106 5dd25f36 Edgar E. Iglesias
    .write = pic_write,
107 5dd25f36 Edgar E. Iglesias
    .endianness = DEVICE_NATIVE_ENDIAN,
108 5dd25f36 Edgar E. Iglesias
    .valid = {
109 5dd25f36 Edgar E. Iglesias
        .min_access_size = 4,
110 5dd25f36 Edgar E. Iglesias
        .max_access_size = 4
111 5dd25f36 Edgar E. Iglesias
    }
112 e62b5b13 edgar_igl
};
113 e62b5b13 edgar_igl
114 5ef98b47 edgar_igl
static void nmi_handler(void *opaque, int irq, int level)
115 979d98ca Edgar E. Iglesias
{   
116 fd6dc90b Edgar E. Iglesias
    struct etrax_pic *fs = (void *)opaque;
117 979d98ca Edgar E. Iglesias
    uint32_t mask;
118 979d98ca Edgar E. Iglesias
119 979d98ca Edgar E. Iglesias
    mask = 1 << irq;
120 979d98ca Edgar E. Iglesias
    if (level)
121 979d98ca Edgar E. Iglesias
        fs->regs[R_R_NMI] |= mask;
122 979d98ca Edgar E. Iglesias
    else
123 979d98ca Edgar E. Iglesias
        fs->regs[R_R_NMI] &= ~mask;
124 979d98ca Edgar E. Iglesias
125 fd6dc90b Edgar E. Iglesias
    qemu_set_irq(fs->parent_nmi, !!fs->regs[R_R_NMI]);
126 5ef98b47 edgar_igl
}
127 5ef98b47 edgar_igl
128 73cfd29f Edgar E. Iglesias
static void irq_handler(void *opaque, int irq, int level)
129 979d98ca Edgar E. Iglesias
{   
130 fd6dc90b Edgar E. Iglesias
    struct etrax_pic *fs = (void *)opaque;
131 73cfd29f Edgar E. Iglesias
132 979d98ca Edgar E. Iglesias
    if (irq >= 30)
133 979d98ca Edgar E. Iglesias
        return nmi_handler(opaque, irq, level);
134 73cfd29f Edgar E. Iglesias
135 979d98ca Edgar E. Iglesias
    irq -= 1;
136 979d98ca Edgar E. Iglesias
    fs->regs[R_R_VECT] &= ~(1 << irq);
137 979d98ca Edgar E. Iglesias
    fs->regs[R_R_VECT] |= (!!level << irq);
138 979d98ca Edgar E. Iglesias
    pic_update(fs);
139 5ef98b47 edgar_igl
}
140 5ef98b47 edgar_igl
141 81a322d4 Gerd Hoffmann
static int etraxfs_pic_init(SysBusDevice *dev)
142 e62b5b13 edgar_igl
{
143 fd6dc90b Edgar E. Iglesias
    struct etrax_pic *s = FROM_SYSBUS(typeof (*s), dev);
144 e62b5b13 edgar_igl
145 067a3ddc Paul Brook
    qdev_init_gpio_in(&dev->qdev, irq_handler, 32);
146 fd6dc90b Edgar E. Iglesias
    sysbus_init_irq(dev, &s->parent_irq);
147 fd6dc90b Edgar E. Iglesias
    sysbus_init_irq(dev, &s->parent_nmi);
148 e62b5b13 edgar_igl
149 5dd25f36 Edgar E. Iglesias
    memory_region_init_io(&s->mmio, &pic_ops, s, "etraxfs-pic", R_MAX * 4);
150 750ecd44 Avi Kivity
    sysbus_init_mmio(dev, &s->mmio);
151 81a322d4 Gerd Hoffmann
    return 0;
152 e62b5b13 edgar_igl
}
153 fd6dc90b Edgar E. Iglesias
154 999e12bb Anthony Liguori
static Property etraxfs_pic_properties[] = {
155 999e12bb Anthony Liguori
    DEFINE_PROP_PTR("interrupt_vector", struct etrax_pic, interrupt_vector),
156 999e12bb Anthony Liguori
    DEFINE_PROP_END_OF_LIST(),
157 999e12bb Anthony Liguori
};
158 999e12bb Anthony Liguori
159 999e12bb Anthony Liguori
static void etraxfs_pic_class_init(ObjectClass *klass, void *data)
160 999e12bb Anthony Liguori
{
161 39bffca2 Anthony Liguori
    DeviceClass *dc = DEVICE_CLASS(klass);
162 999e12bb Anthony Liguori
    SysBusDeviceClass *k = SYS_BUS_DEVICE_CLASS(klass);
163 999e12bb Anthony Liguori
164 999e12bb Anthony Liguori
    k->init = etraxfs_pic_init;
165 39bffca2 Anthony Liguori
    dc->props = etraxfs_pic_properties;
166 999e12bb Anthony Liguori
}
167 999e12bb Anthony Liguori
168 39bffca2 Anthony Liguori
static TypeInfo etraxfs_pic_info = {
169 39bffca2 Anthony Liguori
    .name          = "etraxfs,pic",
170 39bffca2 Anthony Liguori
    .parent        = TYPE_SYS_BUS_DEVICE,
171 39bffca2 Anthony Liguori
    .instance_size = sizeof(struct etrax_pic),
172 39bffca2 Anthony Liguori
    .class_init    = etraxfs_pic_class_init,
173 ee6847d1 Gerd Hoffmann
};
174 ee6847d1 Gerd Hoffmann
175 83f7d43a Andreas Färber
static void etraxfs_pic_register_types(void)
176 fd6dc90b Edgar E. Iglesias
{
177 39bffca2 Anthony Liguori
    type_register_static(&etraxfs_pic_info);
178 fd6dc90b Edgar E. Iglesias
}
179 fd6dc90b Edgar E. Iglesias
180 83f7d43a Andreas Färber
type_init(etraxfs_pic_register_types)