Statistics
| Branch: | Revision:

root / hw / etraxfs_pic.c @ e7b43f7e

History | View | Annotate | Download (4.6 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 ddde095c Gerd Hoffmann
    void *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 ddde095c Gerd Hoffmann
        /* hack alert: ptr property */
75 ddde095c Gerd Hoffmann
        *(uint32_t*)(fs->interrupt_vector) = vector;
76 fd6dc90b Edgar E. Iglesias
    }
77 fd6dc90b Edgar E. Iglesias
    qemu_set_irq(fs->parent_irq, !!vector);
78 e62b5b13 edgar_igl
}
79 e62b5b13 edgar_igl
80 c227f099 Anthony Liguori
static uint32_t pic_readl (void *opaque, target_phys_addr_t addr)
81 e62b5b13 edgar_igl
{
82 fd6dc90b Edgar E. Iglesias
    struct etrax_pic *fs = opaque;
83 979d98ca Edgar E. Iglesias
    uint32_t rval;
84 e62b5b13 edgar_igl
85 979d98ca Edgar E. Iglesias
    rval = fs->regs[addr >> 2];
86 979d98ca Edgar E. Iglesias
    D(printf("%s %x=%x\n", __func__, addr, rval));
87 979d98ca Edgar E. Iglesias
    return rval;
88 e62b5b13 edgar_igl
}
89 e62b5b13 edgar_igl
90 e62b5b13 edgar_igl
static void
91 c227f099 Anthony Liguori
pic_writel (void *opaque, target_phys_addr_t addr, uint32_t value)
92 e62b5b13 edgar_igl
{
93 fd6dc90b Edgar E. Iglesias
    struct etrax_pic *fs = opaque;
94 979d98ca Edgar E. Iglesias
    D(printf("%s addr=%x val=%x\n", __func__, addr, value));
95 8d13fcc0 Edgar E. Iglesias
96 979d98ca Edgar E. Iglesias
    if (addr == R_RW_MASK) {
97 979d98ca Edgar E. Iglesias
        fs->regs[R_RW_MASK] = value;
98 979d98ca Edgar E. Iglesias
        pic_update(fs);
99 979d98ca Edgar E. Iglesias
    }
100 e62b5b13 edgar_igl
}
101 e62b5b13 edgar_igl
102 d60efc6b Blue Swirl
static CPUReadMemoryFunc * const pic_read[] = {
103 979d98ca Edgar E. Iglesias
    NULL, NULL,
104 979d98ca Edgar E. Iglesias
    &pic_readl,
105 e62b5b13 edgar_igl
};
106 e62b5b13 edgar_igl
107 d60efc6b Blue Swirl
static CPUWriteMemoryFunc * const pic_write[] = {
108 979d98ca Edgar E. Iglesias
    NULL, NULL,
109 979d98ca Edgar E. Iglesias
    &pic_writel,
110 e62b5b13 edgar_igl
};
111 e62b5b13 edgar_igl
112 5ef98b47 edgar_igl
static void nmi_handler(void *opaque, int irq, int level)
113 979d98ca Edgar E. Iglesias
{   
114 fd6dc90b Edgar E. Iglesias
    struct etrax_pic *fs = (void *)opaque;
115 979d98ca Edgar E. Iglesias
    uint32_t mask;
116 979d98ca Edgar E. Iglesias
117 979d98ca Edgar E. Iglesias
    mask = 1 << irq;
118 979d98ca Edgar E. Iglesias
    if (level)
119 979d98ca Edgar E. Iglesias
        fs->regs[R_R_NMI] |= mask;
120 979d98ca Edgar E. Iglesias
    else
121 979d98ca Edgar E. Iglesias
        fs->regs[R_R_NMI] &= ~mask;
122 979d98ca Edgar E. Iglesias
123 fd6dc90b Edgar E. Iglesias
    qemu_set_irq(fs->parent_nmi, !!fs->regs[R_R_NMI]);
124 5ef98b47 edgar_igl
}
125 5ef98b47 edgar_igl
126 73cfd29f Edgar E. Iglesias
static void irq_handler(void *opaque, int irq, int level)
127 979d98ca Edgar E. Iglesias
{   
128 fd6dc90b Edgar E. Iglesias
    struct etrax_pic *fs = (void *)opaque;
129 73cfd29f Edgar E. Iglesias
130 979d98ca Edgar E. Iglesias
    if (irq >= 30)
131 979d98ca Edgar E. Iglesias
        return nmi_handler(opaque, irq, level);
132 73cfd29f Edgar E. Iglesias
133 979d98ca Edgar E. Iglesias
    irq -= 1;
134 979d98ca Edgar E. Iglesias
    fs->regs[R_R_VECT] &= ~(1 << irq);
135 979d98ca Edgar E. Iglesias
    fs->regs[R_R_VECT] |= (!!level << irq);
136 979d98ca Edgar E. Iglesias
    pic_update(fs);
137 5ef98b47 edgar_igl
}
138 5ef98b47 edgar_igl
139 81a322d4 Gerd Hoffmann
static int etraxfs_pic_init(SysBusDevice *dev)
140 e62b5b13 edgar_igl
{
141 fd6dc90b Edgar E. Iglesias
    struct etrax_pic *s = FROM_SYSBUS(typeof (*s), dev);
142 979d98ca Edgar E. Iglesias
    int intr_vect_regs;
143 e62b5b13 edgar_igl
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 1eed09cb Avi Kivity
    intr_vect_regs = cpu_register_io_memory(pic_read, pic_write, s);
149 fd6dc90b Edgar E. Iglesias
    sysbus_init_mmio(dev, R_MAX * 4, intr_vect_regs);
150 81a322d4 Gerd Hoffmann
    return 0;
151 e62b5b13 edgar_igl
}
152 fd6dc90b Edgar E. Iglesias
153 ee6847d1 Gerd Hoffmann
static SysBusDeviceInfo etraxfs_pic_info = {
154 ee6847d1 Gerd Hoffmann
    .init = etraxfs_pic_init,
155 ee6847d1 Gerd Hoffmann
    .qdev.name  = "etraxfs,pic",
156 ee6847d1 Gerd Hoffmann
    .qdev.size  = sizeof(struct etrax_pic),
157 ee6847d1 Gerd Hoffmann
    .qdev.props = (Property[]) {
158 ddde095c Gerd Hoffmann
        DEFINE_PROP_PTR("interrupt_vector", struct etrax_pic, interrupt_vector),
159 ddde095c Gerd Hoffmann
        DEFINE_PROP_END_OF_LIST(),
160 ee6847d1 Gerd Hoffmann
    }
161 ee6847d1 Gerd Hoffmann
};
162 ee6847d1 Gerd Hoffmann
163 fd6dc90b Edgar E. Iglesias
static void etraxfs_pic_register(void)
164 fd6dc90b Edgar E. Iglesias
{
165 ee6847d1 Gerd Hoffmann
    sysbus_register_withprop(&etraxfs_pic_info);
166 fd6dc90b Edgar E. Iglesias
}
167 fd6dc90b Edgar E. Iglesias
168 fd6dc90b Edgar E. Iglesias
device_init(etraxfs_pic_register)