Statistics
| Branch: | Revision:

root / hw / xilinx_intc.c @ e685b4eb

History | View | Annotate | Download (4.6 kB)

1 17628bc6 Edgar E. Iglesias
/*
2 17628bc6 Edgar E. Iglesias
 * QEMU Xilinx OPB Interrupt Controller.
3 17628bc6 Edgar E. Iglesias
 *
4 17628bc6 Edgar E. Iglesias
 * Copyright (c) 2009 Edgar E. Iglesias.
5 17628bc6 Edgar E. Iglesias
 *
6 17628bc6 Edgar E. Iglesias
 * Permission is hereby granted, free of charge, to any person obtaining a copy
7 17628bc6 Edgar E. Iglesias
 * of this software and associated documentation files (the "Software"), to deal
8 17628bc6 Edgar E. Iglesias
 * in the Software without restriction, including without limitation the rights
9 17628bc6 Edgar E. Iglesias
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10 17628bc6 Edgar E. Iglesias
 * copies of the Software, and to permit persons to whom the Software is
11 17628bc6 Edgar E. Iglesias
 * furnished to do so, subject to the following conditions:
12 17628bc6 Edgar E. Iglesias
 *
13 17628bc6 Edgar E. Iglesias
 * The above copyright notice and this permission notice shall be included in
14 17628bc6 Edgar E. Iglesias
 * all copies or substantial portions of the Software.
15 17628bc6 Edgar E. Iglesias
 *
16 17628bc6 Edgar E. Iglesias
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 17628bc6 Edgar E. Iglesias
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 17628bc6 Edgar E. Iglesias
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
19 17628bc6 Edgar E. Iglesias
 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 17628bc6 Edgar E. Iglesias
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21 17628bc6 Edgar E. Iglesias
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
22 17628bc6 Edgar E. Iglesias
 * THE SOFTWARE.
23 17628bc6 Edgar E. Iglesias
 */
24 17628bc6 Edgar E. Iglesias
25 17628bc6 Edgar E. Iglesias
#include "sysbus.h"
26 17628bc6 Edgar E. Iglesias
#include "hw.h"
27 17628bc6 Edgar E. Iglesias
28 17628bc6 Edgar E. Iglesias
#define D(x)
29 17628bc6 Edgar E. Iglesias
30 17628bc6 Edgar E. Iglesias
#define R_ISR       0
31 17628bc6 Edgar E. Iglesias
#define R_IPR       1
32 17628bc6 Edgar E. Iglesias
#define R_IER       2
33 17628bc6 Edgar E. Iglesias
#define R_IAR       3
34 17628bc6 Edgar E. Iglesias
#define R_SIE       4
35 17628bc6 Edgar E. Iglesias
#define R_CIE       5
36 17628bc6 Edgar E. Iglesias
#define R_IVR       6
37 17628bc6 Edgar E. Iglesias
#define R_MER       7
38 17628bc6 Edgar E. Iglesias
#define R_MAX       8
39 17628bc6 Edgar E. Iglesias
40 17628bc6 Edgar E. Iglesias
struct xlx_pic
41 17628bc6 Edgar E. Iglesias
{
42 17628bc6 Edgar E. Iglesias
    SysBusDevice busdev;
43 17628bc6 Edgar E. Iglesias
    qemu_irq parent_irq;
44 17628bc6 Edgar E. Iglesias
45 17628bc6 Edgar E. Iglesias
    /* Configuration reg chosen at synthesis-time. QEMU populates
46 17628bc6 Edgar E. Iglesias
       the bits at board-setup.  */
47 17628bc6 Edgar E. Iglesias
    uint32_t c_kind_of_intr;
48 17628bc6 Edgar E. Iglesias
49 17628bc6 Edgar E. Iglesias
    /* Runtime control registers.  */
50 17628bc6 Edgar E. Iglesias
    uint32_t regs[R_MAX];
51 17628bc6 Edgar E. Iglesias
};
52 17628bc6 Edgar E. Iglesias
53 17628bc6 Edgar E. Iglesias
static void update_irq(struct xlx_pic *p)
54 17628bc6 Edgar E. Iglesias
{
55 17628bc6 Edgar E. Iglesias
    uint32_t i;
56 17628bc6 Edgar E. Iglesias
    /* Update the pending register.  */
57 17628bc6 Edgar E. Iglesias
    p->regs[R_IPR] = p->regs[R_ISR] & p->regs[R_IER];
58 17628bc6 Edgar E. Iglesias
59 17628bc6 Edgar E. Iglesias
    /* Update the vector register.  */
60 17628bc6 Edgar E. Iglesias
    for (i = 0; i < 32; i++) {
61 17628bc6 Edgar E. Iglesias
        if (p->regs[R_IPR] & (1 << i))
62 17628bc6 Edgar E. Iglesias
            break;
63 17628bc6 Edgar E. Iglesias
    }
64 17628bc6 Edgar E. Iglesias
    if (i == 32)
65 17628bc6 Edgar E. Iglesias
        i = ~0;
66 17628bc6 Edgar E. Iglesias
67 17628bc6 Edgar E. Iglesias
    p->regs[R_IVR] = i;
68 17628bc6 Edgar E. Iglesias
    if ((p->regs[R_MER] & 1) && p->regs[R_IPR]) {
69 17628bc6 Edgar E. Iglesias
        qemu_irq_raise(p->parent_irq);
70 17628bc6 Edgar E. Iglesias
    } else {
71 17628bc6 Edgar E. Iglesias
        qemu_irq_lower(p->parent_irq);
72 17628bc6 Edgar E. Iglesias
    }
73 17628bc6 Edgar E. Iglesias
}
74 17628bc6 Edgar E. Iglesias
75 c227f099 Anthony Liguori
static uint32_t pic_readl (void *opaque, target_phys_addr_t addr)
76 17628bc6 Edgar E. Iglesias
{
77 17628bc6 Edgar E. Iglesias
    struct xlx_pic *p = opaque;
78 17628bc6 Edgar E. Iglesias
    uint32_t r = 0;
79 17628bc6 Edgar E. Iglesias
80 17628bc6 Edgar E. Iglesias
    addr >>= 2;
81 17628bc6 Edgar E. Iglesias
    switch (addr)
82 17628bc6 Edgar E. Iglesias
    {
83 17628bc6 Edgar E. Iglesias
        default:
84 17628bc6 Edgar E. Iglesias
            if (addr < ARRAY_SIZE(p->regs))
85 17628bc6 Edgar E. Iglesias
                r = p->regs[addr];
86 17628bc6 Edgar E. Iglesias
            break;
87 17628bc6 Edgar E. Iglesias
88 17628bc6 Edgar E. Iglesias
    }
89 17628bc6 Edgar E. Iglesias
    D(printf("%s %x=%x\n", __func__, addr * 4, r));
90 17628bc6 Edgar E. Iglesias
    return r;
91 17628bc6 Edgar E. Iglesias
}
92 17628bc6 Edgar E. Iglesias
93 17628bc6 Edgar E. Iglesias
static void
94 c227f099 Anthony Liguori
pic_writel (void *opaque, target_phys_addr_t addr, uint32_t value)
95 17628bc6 Edgar E. Iglesias
{
96 17628bc6 Edgar E. Iglesias
    struct xlx_pic *p = opaque;
97 17628bc6 Edgar E. Iglesias
98 17628bc6 Edgar E. Iglesias
    addr >>= 2;
99 17628bc6 Edgar E. Iglesias
    D(qemu_log("%s addr=%x val=%x\n", __func__, addr * 4, value));
100 17628bc6 Edgar E. Iglesias
    switch (addr) 
101 17628bc6 Edgar E. Iglesias
    {
102 17628bc6 Edgar E. Iglesias
        case R_IAR:
103 17628bc6 Edgar E. Iglesias
            p->regs[R_ISR] &= ~value; /* ACK.  */
104 17628bc6 Edgar E. Iglesias
            break;
105 17628bc6 Edgar E. Iglesias
        case R_SIE:
106 17628bc6 Edgar E. Iglesias
            p->regs[R_IER] |= value;  /* Atomic set ie.  */
107 17628bc6 Edgar E. Iglesias
            break;
108 17628bc6 Edgar E. Iglesias
        case R_CIE:
109 17628bc6 Edgar E. Iglesias
            p->regs[R_IER] &= ~value; /* Atomic clear ie.  */
110 17628bc6 Edgar E. Iglesias
            break;
111 17628bc6 Edgar E. Iglesias
        default:
112 17628bc6 Edgar E. Iglesias
            if (addr < ARRAY_SIZE(p->regs))
113 17628bc6 Edgar E. Iglesias
                p->regs[addr] = value;
114 17628bc6 Edgar E. Iglesias
            break;
115 17628bc6 Edgar E. Iglesias
    }
116 17628bc6 Edgar E. Iglesias
    update_irq(p);
117 17628bc6 Edgar E. Iglesias
}
118 17628bc6 Edgar E. Iglesias
119 d60efc6b Blue Swirl
static CPUReadMemoryFunc * const pic_read[] = {
120 17628bc6 Edgar E. Iglesias
    NULL, NULL,
121 17628bc6 Edgar E. Iglesias
    &pic_readl,
122 17628bc6 Edgar E. Iglesias
};
123 17628bc6 Edgar E. Iglesias
124 d60efc6b Blue Swirl
static CPUWriteMemoryFunc * const pic_write[] = {
125 17628bc6 Edgar E. Iglesias
    NULL, NULL,
126 17628bc6 Edgar E. Iglesias
    &pic_writel,
127 17628bc6 Edgar E. Iglesias
};
128 17628bc6 Edgar E. Iglesias
129 17628bc6 Edgar E. Iglesias
static void irq_handler(void *opaque, int irq, int level)
130 17628bc6 Edgar E. Iglesias
{
131 17628bc6 Edgar E. Iglesias
    struct xlx_pic *p = opaque;
132 17628bc6 Edgar E. Iglesias
133 17628bc6 Edgar E. Iglesias
    if (!(p->regs[R_MER] & 2)) {
134 17628bc6 Edgar E. Iglesias
        qemu_irq_lower(p->parent_irq);
135 17628bc6 Edgar E. Iglesias
        return;
136 17628bc6 Edgar E. Iglesias
    }
137 17628bc6 Edgar E. Iglesias
138 17628bc6 Edgar E. Iglesias
    /* Update source flops. Don't clear unless level triggered.
139 17628bc6 Edgar E. Iglesias
       Edge triggered interrupts only go away when explicitely acked to
140 17628bc6 Edgar E. Iglesias
       the interrupt controller.  */
141 17628bc6 Edgar E. Iglesias
    if (!(p->c_kind_of_intr & (1 << irq)) || level) {
142 17628bc6 Edgar E. Iglesias
        p->regs[R_ISR] &= ~(1 << irq);
143 17628bc6 Edgar E. Iglesias
        p->regs[R_ISR] |= (level << irq);
144 17628bc6 Edgar E. Iglesias
    }
145 17628bc6 Edgar E. Iglesias
    update_irq(p);
146 17628bc6 Edgar E. Iglesias
}
147 17628bc6 Edgar E. Iglesias
148 81a322d4 Gerd Hoffmann
static int xilinx_intc_init(SysBusDevice *dev)
149 17628bc6 Edgar E. Iglesias
{
150 17628bc6 Edgar E. Iglesias
    struct xlx_pic *p = FROM_SYSBUS(typeof (*p), dev);
151 17628bc6 Edgar E. Iglesias
    int pic_regs;
152 17628bc6 Edgar E. Iglesias
153 17628bc6 Edgar E. Iglesias
    qdev_init_gpio_in(&dev->qdev, irq_handler, 32);
154 17628bc6 Edgar E. Iglesias
    sysbus_init_irq(dev, &p->parent_irq);
155 17628bc6 Edgar E. Iglesias
156 1eed09cb Avi Kivity
    pic_regs = cpu_register_io_memory(pic_read, pic_write, p);
157 17628bc6 Edgar E. Iglesias
    sysbus_init_mmio(dev, R_MAX * 4, pic_regs);
158 81a322d4 Gerd Hoffmann
    return 0;
159 17628bc6 Edgar E. Iglesias
}
160 17628bc6 Edgar E. Iglesias
161 ee6847d1 Gerd Hoffmann
static SysBusDeviceInfo xilinx_intc_info = {
162 ee6847d1 Gerd Hoffmann
    .init = xilinx_intc_init,
163 ee6847d1 Gerd Hoffmann
    .qdev.name  = "xilinx,intc",
164 ee6847d1 Gerd Hoffmann
    .qdev.size  = sizeof(struct xlx_pic),
165 ee6847d1 Gerd Hoffmann
    .qdev.props = (Property[]) {
166 8017dc26 Gerd Hoffmann
        DEFINE_PROP_UINT32("kind-of-intr", struct xlx_pic, c_kind_of_intr, 0),
167 8017dc26 Gerd Hoffmann
        DEFINE_PROP_END_OF_LIST(),
168 ee6847d1 Gerd Hoffmann
    }
169 ee6847d1 Gerd Hoffmann
};
170 ee6847d1 Gerd Hoffmann
171 17628bc6 Edgar E. Iglesias
static void xilinx_intc_register(void)
172 17628bc6 Edgar E. Iglesias
{
173 ee6847d1 Gerd Hoffmann
    sysbus_register_withprop(&xilinx_intc_info);
174 17628bc6 Edgar E. Iglesias
}
175 17628bc6 Edgar E. Iglesias
176 17628bc6 Edgar E. Iglesias
device_init(xilinx_intc_register)