|
|
1.1 root 1: /*
2: * QEMU ETRAX Interrupt Controller.
3: *
4: * Copyright (c) 2008 Edgar E. Iglesias, Axis Communications AB.
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:
1.1.1.2 root 25: #include "sysbus.h"
1.1 root 26: #include "hw.h"
1.1.1.2 root 27: //#include "pc.h"
28: //#include "etraxfs.h"
1.1 root 29:
30: #define D(x)
31:
1.1.1.2 root 32: #define R_RW_MASK 0
33: #define R_R_VECT 1
34: #define R_R_MASKED_VECT 2
35: #define R_R_NMI 3
36: #define R_R_GURU 4
37: #define R_MAX 5
38:
39: struct etrax_pic
40: {
41: SysBusDevice busdev;
1.1.1.5 root 42: MemoryRegion mmio;
1.1.1.3 root 43: void *interrupt_vector;
1.1.1.2 root 44: qemu_irq parent_irq;
45: qemu_irq parent_nmi;
46: uint32_t regs[R_MAX];
1.1 root 47: };
48:
1.1.1.2 root 49: static void pic_update(struct etrax_pic *fs)
50: {
51: uint32_t vector = 0;
52: int i;
53:
54: fs->regs[R_R_MASKED_VECT] = fs->regs[R_R_VECT] & fs->regs[R_RW_MASK];
55:
1.1.1.6 ! root 56: /* The ETRAX interrupt controller signals interrupts to the core
1.1.1.2 root 57: through an interrupt request wire and an irq vector bus. If
58: multiple interrupts are simultaneously active it chooses vector
59: 0x30 and lets the sw choose the priorities. */
60: if (fs->regs[R_R_MASKED_VECT]) {
61: uint32_t mv = fs->regs[R_R_MASKED_VECT];
62: for (i = 0; i < 31; i++) {
63: if (mv & 1) {
64: vector = 0x31 + i;
65: /* Check for multiple interrupts. */
66: if (mv > 1)
67: vector = 0x30;
68: break;
69: }
70: mv >>= 1;
71: }
72: }
73:
74: if (fs->interrupt_vector) {
1.1.1.3 root 75: /* hack alert: ptr property */
76: *(uint32_t*)(fs->interrupt_vector) = vector;
1.1.1.2 root 77: }
78: qemu_set_irq(fs->parent_irq, !!vector);
1.1 root 79: }
80:
1.1.1.5 root 81: static uint64_t
82: pic_read(void *opaque, target_phys_addr_t addr, unsigned int size)
1.1 root 83: {
1.1.1.2 root 84: struct etrax_pic *fs = opaque;
85: uint32_t rval;
1.1 root 86:
1.1.1.2 root 87: rval = fs->regs[addr >> 2];
88: D(printf("%s %x=%x\n", __func__, addr, rval));
89: return rval;
1.1 root 90: }
91:
1.1.1.5 root 92: static void pic_write(void *opaque, target_phys_addr_t addr,
93: uint64_t value, unsigned int size)
1.1 root 94: {
1.1.1.2 root 95: struct etrax_pic *fs = opaque;
96: D(printf("%s addr=%x val=%x\n", __func__, addr, value));
97:
98: if (addr == R_RW_MASK) {
99: fs->regs[R_RW_MASK] = value;
100: pic_update(fs);
101: }
1.1 root 102: }
103:
1.1.1.5 root 104: static const MemoryRegionOps pic_ops = {
105: .read = pic_read,
106: .write = pic_write,
107: .endianness = DEVICE_NATIVE_ENDIAN,
108: .valid = {
109: .min_access_size = 4,
110: .max_access_size = 4
111: }
1.1 root 112: };
113:
1.1.1.2 root 114: static void nmi_handler(void *opaque, int irq, int level)
115: {
116: struct etrax_pic *fs = (void *)opaque;
117: uint32_t mask;
118:
119: mask = 1 << irq;
120: if (level)
121: fs->regs[R_R_NMI] |= mask;
122: else
123: fs->regs[R_R_NMI] &= ~mask;
1.1 root 124:
1.1.1.2 root 125: qemu_set_irq(fs->parent_nmi, !!fs->regs[R_R_NMI]);
1.1 root 126: }
127:
128: static void irq_handler(void *opaque, int irq, int level)
1.1.1.2 root 129: {
130: struct etrax_pic *fs = (void *)opaque;
1.1 root 131:
1.1.1.2 root 132: if (irq >= 30)
133: return nmi_handler(opaque, irq, level);
1.1 root 134:
1.1.1.2 root 135: irq -= 1;
136: fs->regs[R_R_VECT] &= ~(1 << irq);
137: fs->regs[R_R_VECT] |= (!!level << irq);
138: pic_update(fs);
139: }
140:
1.1.1.3 root 141: static int etraxfs_pic_init(SysBusDevice *dev)
1.1.1.2 root 142: {
143: struct etrax_pic *s = FROM_SYSBUS(typeof (*s), dev);
144:
145: qdev_init_gpio_in(&dev->qdev, irq_handler, 32);
146: sysbus_init_irq(dev, &s->parent_irq);
147: sysbus_init_irq(dev, &s->parent_nmi);
148:
1.1.1.5 root 149: memory_region_init_io(&s->mmio, &pic_ops, s, "etraxfs-pic", R_MAX * 4);
1.1.1.6 ! root 150: sysbus_init_mmio(dev, &s->mmio);
1.1.1.3 root 151: return 0;
1.1.1.2 root 152: }
153:
1.1.1.6 ! root 154: static Property etraxfs_pic_properties[] = {
! 155: DEFINE_PROP_PTR("interrupt_vector", struct etrax_pic, interrupt_vector),
! 156: DEFINE_PROP_END_OF_LIST(),
! 157: };
! 158:
! 159: static void etraxfs_pic_class_init(ObjectClass *klass, void *data)
! 160: {
! 161: DeviceClass *dc = DEVICE_CLASS(klass);
! 162: SysBusDeviceClass *k = SYS_BUS_DEVICE_CLASS(klass);
! 163:
! 164: k->init = etraxfs_pic_init;
! 165: dc->props = etraxfs_pic_properties;
! 166: }
! 167:
! 168: static TypeInfo etraxfs_pic_info = {
! 169: .name = "etraxfs,pic",
! 170: .parent = TYPE_SYS_BUS_DEVICE,
! 171: .instance_size = sizeof(struct etrax_pic),
! 172: .class_init = etraxfs_pic_class_init,
1.1.1.2 root 173: };
1.1 root 174:
1.1.1.6 ! root 175: static void etraxfs_pic_register_types(void)
1.1 root 176: {
1.1.1.6 ! root 177: type_register_static(&etraxfs_pic_info);
1.1 root 178: }
1.1.1.2 root 179:
1.1.1.6 ! root 180: type_init(etraxfs_pic_register_types)
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.