prep: Fix NIP reset value
[qemu/agraf.git] / hw / pci-host / apb.c
blobe0996556e581fb2f0a5ea63928b1727937925b7c
1 /*
2 * QEMU Ultrasparc APB PCI host
4 * Copyright (c) 2006 Fabrice Bellard
5 * Copyright (c) 2012,2013 Artyom Tarasenko
7 * Permission is hereby granted, free of charge, to any person obtaining a copy
8 * of this software and associated documentation files (the "Software"), to deal
9 * in the Software without restriction, including without limitation the rights
10 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
11 * copies of the Software, and to permit persons to whom the Software is
12 * furnished to do so, subject to the following conditions:
14 * The above copyright notice and this permission notice shall be included in
15 * all copies or substantial portions of the Software.
17 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
20 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
22 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
23 * THE SOFTWARE.
26 /* XXX This file and most of its contents are somewhat misnamed. The
27 Ultrasparc PCI host is called the PCI Bus Module (PBM). The APB is
28 the secondary PCI bridge. */
30 #include "hw/sysbus.h"
31 #include "hw/pci/pci.h"
32 #include "hw/pci/pci_host.h"
33 #include "hw/pci/pci_bridge.h"
34 #include "hw/pci/pci_bus.h"
35 #include "hw/pci-host/apb.h"
36 #include "sysemu/sysemu.h"
37 #include "exec/address-spaces.h"
39 /* debug APB */
40 //#define DEBUG_APB
42 #ifdef DEBUG_APB
43 #define APB_DPRINTF(fmt, ...) \
44 do { printf("APB: " fmt , ## __VA_ARGS__); } while (0)
45 #else
46 #define APB_DPRINTF(fmt, ...)
47 #endif
50 * Chipset docs:
51 * PBM: "UltraSPARC IIi User's Manual",
52 * http://www.sun.com/processors/manuals/805-0087.pdf
54 * APB: "Advanced PCI Bridge (APB) User's Manual",
55 * http://www.sun.com/processors/manuals/805-1251.pdf
58 #define PBM_PCI_IMR_MASK 0x7fffffff
59 #define PBM_PCI_IMR_ENABLED 0x80000000
61 #define POR (1 << 31)
62 #define SOFT_POR (1 << 30)
63 #define SOFT_XIR (1 << 29)
64 #define BTN_POR (1 << 28)
65 #define BTN_XIR (1 << 27)
66 #define RESET_MASK 0xf8000000
67 #define RESET_WCMASK 0x98000000
68 #define RESET_WMASK 0x60000000
70 #define MAX_IVEC 0x40
71 #define NO_IRQ_REQUEST (MAX_IVEC + 1)
73 typedef struct APBState {
74 SysBusDevice busdev;
75 PCIBus *bus;
76 MemoryRegion apb_config;
77 MemoryRegion pci_config;
78 MemoryRegion pci_mmio;
79 MemoryRegion pci_ioport;
80 uint64_t pci_irq_in;
81 uint32_t iommu[4];
82 uint32_t pci_control[16];
83 uint32_t pci_irq_map[8];
84 uint32_t obio_irq_map[32];
85 qemu_irq *pbm_irqs;
86 qemu_irq *ivec_irqs;
87 unsigned int irq_request;
88 uint32_t reset_control;
89 unsigned int nr_resets;
90 } APBState;
92 static inline void pbm_set_request(APBState *s, unsigned int irq_num)
94 APB_DPRINTF("%s: request irq %d\n", __func__, irq_num);
96 s->irq_request = irq_num;
97 qemu_set_irq(s->ivec_irqs[irq_num], 1);
100 static inline void pbm_check_irqs(APBState *s)
103 unsigned int i;
105 /* Previous request is not acknowledged, resubmit */
106 if (s->irq_request != NO_IRQ_REQUEST) {
107 pbm_set_request(s, s->irq_request);
108 return;
110 /* no request pending */
111 if (s->pci_irq_in == 0ULL) {
112 return;
114 for (i = 0; i < 32; i++) {
115 if (s->pci_irq_in & (1ULL << i)) {
116 if (s->pci_irq_map[i >> 2] & PBM_PCI_IMR_ENABLED) {
117 pbm_set_request(s, i);
118 return;
122 for (i = 32; i < 64; i++) {
123 if (s->pci_irq_in & (1ULL << i)) {
124 if (s->obio_irq_map[i - 32] & PBM_PCI_IMR_ENABLED) {
125 pbm_set_request(s, i);
126 break;
132 static inline void pbm_clear_request(APBState *s, unsigned int irq_num)
134 APB_DPRINTF("%s: clear request irq %d\n", __func__, irq_num);
135 qemu_set_irq(s->ivec_irqs[irq_num], 0);
136 s->irq_request = NO_IRQ_REQUEST;
139 static void apb_config_writel (void *opaque, hwaddr addr,
140 uint64_t val, unsigned size)
142 APBState *s = opaque;
144 APB_DPRINTF("%s: addr " TARGET_FMT_plx " val %" PRIx64 "\n", __func__, addr, val);
146 switch (addr & 0xffff) {
147 case 0x30 ... 0x4f: /* DMA error registers */
148 /* XXX: not implemented yet */
149 break;
150 case 0x200 ... 0x20b: /* IOMMU */
151 s->iommu[(addr & 0xf) >> 2] = val;
152 break;
153 case 0x20c ... 0x3ff: /* IOMMU flush */
154 break;
155 case 0xc00 ... 0xc3f: /* PCI interrupt control */
156 if (addr & 4) {
157 unsigned int ino = (addr & 0x3f) >> 3;
158 s->pci_irq_map[ino] &= PBM_PCI_IMR_MASK;
159 s->pci_irq_map[ino] |= val & ~PBM_PCI_IMR_MASK;
160 if ((s->irq_request == ino) && !(val & ~PBM_PCI_IMR_MASK)) {
161 pbm_clear_request(s, ino);
163 pbm_check_irqs(s);
165 break;
166 case 0x1000 ... 0x1080: /* OBIO interrupt control */
167 if (addr & 4) {
168 unsigned int ino = ((addr & 0xff) >> 3);
169 s->obio_irq_map[ino] &= PBM_PCI_IMR_MASK;
170 s->obio_irq_map[ino] |= val & ~PBM_PCI_IMR_MASK;
171 if ((s->irq_request == (ino | 0x20))
172 && !(val & ~PBM_PCI_IMR_MASK)) {
173 pbm_clear_request(s, ino | 0x20);
175 pbm_check_irqs(s);
177 break;
178 case 0x1400 ... 0x14ff: /* PCI interrupt clear */
179 if (addr & 4) {
180 unsigned int ino = (addr & 0xff) >> 5;
181 if ((s->irq_request / 4) == ino) {
182 pbm_clear_request(s, s->irq_request);
183 pbm_check_irqs(s);
186 break;
187 case 0x1800 ... 0x1860: /* OBIO interrupt clear */
188 if (addr & 4) {
189 unsigned int ino = ((addr & 0xff) >> 3) | 0x20;
190 if (s->irq_request == ino) {
191 pbm_clear_request(s, ino);
192 pbm_check_irqs(s);
195 break;
196 case 0x2000 ... 0x202f: /* PCI control */
197 s->pci_control[(addr & 0x3f) >> 2] = val;
198 break;
199 case 0xf020 ... 0xf027: /* Reset control */
200 if (addr & 4) {
201 val &= RESET_MASK;
202 s->reset_control &= ~(val & RESET_WCMASK);
203 s->reset_control |= val & RESET_WMASK;
204 if (val & SOFT_POR) {
205 s->nr_resets = 0;
206 qemu_system_reset_request();
207 } else if (val & SOFT_XIR) {
208 qemu_system_reset_request();
211 break;
212 case 0x5000 ... 0x51cf: /* PIO/DMA diagnostics */
213 case 0xa400 ... 0xa67f: /* IOMMU diagnostics */
214 case 0xa800 ... 0xa80f: /* Interrupt diagnostics */
215 case 0xf000 ... 0xf01f: /* FFB config, memory control */
216 /* we don't care */
217 default:
218 break;
222 static uint64_t apb_config_readl (void *opaque,
223 hwaddr addr, unsigned size)
225 APBState *s = opaque;
226 uint32_t val;
228 switch (addr & 0xffff) {
229 case 0x30 ... 0x4f: /* DMA error registers */
230 val = 0;
231 /* XXX: not implemented yet */
232 break;
233 case 0x200 ... 0x20b: /* IOMMU */
234 val = s->iommu[(addr & 0xf) >> 2];
235 break;
236 case 0x20c ... 0x3ff: /* IOMMU flush */
237 val = 0;
238 break;
239 case 0xc00 ... 0xc3f: /* PCI interrupt control */
240 if (addr & 4) {
241 val = s->pci_irq_map[(addr & 0x3f) >> 3];
242 } else {
243 val = 0;
245 break;
246 case 0x1000 ... 0x1080: /* OBIO interrupt control */
247 if (addr & 4) {
248 val = s->obio_irq_map[(addr & 0xff) >> 3];
249 } else {
250 val = 0;
252 break;
253 case 0x2000 ... 0x202f: /* PCI control */
254 val = s->pci_control[(addr & 0x3f) >> 2];
255 break;
256 case 0xf020 ... 0xf027: /* Reset control */
257 if (addr & 4) {
258 val = s->reset_control;
259 } else {
260 val = 0;
262 break;
263 case 0x5000 ... 0x51cf: /* PIO/DMA diagnostics */
264 case 0xa400 ... 0xa67f: /* IOMMU diagnostics */
265 case 0xa800 ... 0xa80f: /* Interrupt diagnostics */
266 case 0xf000 ... 0xf01f: /* FFB config, memory control */
267 /* we don't care */
268 default:
269 val = 0;
270 break;
272 APB_DPRINTF("%s: addr " TARGET_FMT_plx " -> %x\n", __func__, addr, val);
274 return val;
277 static const MemoryRegionOps apb_config_ops = {
278 .read = apb_config_readl,
279 .write = apb_config_writel,
280 .endianness = DEVICE_NATIVE_ENDIAN,
283 static void apb_pci_config_write(void *opaque, hwaddr addr,
284 uint64_t val, unsigned size)
286 APBState *s = opaque;
288 val = qemu_bswap_len(val, size);
289 APB_DPRINTF("%s: addr " TARGET_FMT_plx " val %" PRIx64 "\n", __func__, addr, val);
290 pci_data_write(s->bus, addr, val, size);
293 static uint64_t apb_pci_config_read(void *opaque, hwaddr addr,
294 unsigned size)
296 uint32_t ret;
297 APBState *s = opaque;
299 ret = pci_data_read(s->bus, addr, size);
300 ret = qemu_bswap_len(ret, size);
301 APB_DPRINTF("%s: addr " TARGET_FMT_plx " -> %x\n", __func__, addr, ret);
302 return ret;
305 static void pci_apb_iowriteb (void *opaque, hwaddr addr,
306 uint32_t val)
308 cpu_outb(addr & IOPORTS_MASK, val);
311 static void pci_apb_iowritew (void *opaque, hwaddr addr,
312 uint32_t val)
314 cpu_outw(addr & IOPORTS_MASK, bswap16(val));
317 static void pci_apb_iowritel (void *opaque, hwaddr addr,
318 uint32_t val)
320 cpu_outl(addr & IOPORTS_MASK, bswap32(val));
323 static uint32_t pci_apb_ioreadb (void *opaque, hwaddr addr)
325 uint32_t val;
327 val = cpu_inb(addr & IOPORTS_MASK);
328 return val;
331 static uint32_t pci_apb_ioreadw (void *opaque, hwaddr addr)
333 uint32_t val;
335 val = bswap16(cpu_inw(addr & IOPORTS_MASK));
336 return val;
339 static uint32_t pci_apb_ioreadl (void *opaque, hwaddr addr)
341 uint32_t val;
343 val = bswap32(cpu_inl(addr & IOPORTS_MASK));
344 return val;
347 static const MemoryRegionOps pci_ioport_ops = {
348 .old_mmio = {
349 .read = { pci_apb_ioreadb, pci_apb_ioreadw, pci_apb_ioreadl },
350 .write = { pci_apb_iowriteb, pci_apb_iowritew, pci_apb_iowritel, },
352 .endianness = DEVICE_NATIVE_ENDIAN,
355 /* The APB host has an IRQ line for each IRQ line of each slot. */
356 static int pci_apb_map_irq(PCIDevice *pci_dev, int irq_num)
358 return ((pci_dev->devfn & 0x18) >> 1) + irq_num;
361 static int pci_pbm_map_irq(PCIDevice *pci_dev, int irq_num)
363 int bus_offset;
364 if (pci_dev->devfn & 1)
365 bus_offset = 16;
366 else
367 bus_offset = 0;
368 return (bus_offset + (PCI_SLOT(pci_dev->devfn) << 2) + irq_num) & 0x1f;
371 static void pci_apb_set_irq(void *opaque, int irq_num, int level)
373 APBState *s = opaque;
375 APB_DPRINTF("%s: set irq_in %d level %d\n", __func__, irq_num, level);
376 /* PCI IRQ map onto the first 32 INO. */
377 if (irq_num < 32) {
378 if (level) {
379 s->pci_irq_in |= 1ULL << irq_num;
380 if (s->pci_irq_map[irq_num >> 2] & PBM_PCI_IMR_ENABLED) {
381 pbm_set_request(s, irq_num);
383 } else {
384 s->pci_irq_in &= ~(1ULL << irq_num);
386 } else {
387 /* OBIO IRQ map onto the next 32 INO. */
388 if (level) {
389 APB_DPRINTF("%s: set irq %d level %d\n", __func__, irq_num, level);
390 s->pci_irq_in |= 1ULL << irq_num;
391 if ((s->irq_request == NO_IRQ_REQUEST)
392 && (s->obio_irq_map[irq_num - 32] & PBM_PCI_IMR_ENABLED)) {
393 pbm_set_request(s, irq_num);
395 } else {
396 s->pci_irq_in &= ~(1ULL << irq_num);
401 static int apb_pci_bridge_initfn(PCIDevice *dev)
403 int rc;
405 rc = pci_bridge_initfn(dev, TYPE_PCI_BUS);
406 if (rc < 0) {
407 return rc;
411 * command register:
412 * According to PCI bridge spec, after reset
413 * bus master bit is off
414 * memory space enable bit is off
415 * According to manual (805-1251.pdf).
416 * the reset value should be zero unless the boot pin is tied high
417 * (which is true) and thus it should be PCI_COMMAND_MEMORY.
419 pci_set_word(dev->config + PCI_COMMAND,
420 PCI_COMMAND_MEMORY);
421 pci_set_word(dev->config + PCI_STATUS,
422 PCI_STATUS_FAST_BACK | PCI_STATUS_66MHZ |
423 PCI_STATUS_DEVSEL_MEDIUM);
424 return 0;
427 PCIBus *pci_apb_init(hwaddr special_base,
428 hwaddr mem_base,
429 qemu_irq *ivec_irqs, PCIBus **bus2, PCIBus **bus3,
430 qemu_irq **pbm_irqs)
432 DeviceState *dev;
433 SysBusDevice *s;
434 APBState *d;
435 PCIDevice *pci_dev;
436 PCIBridge *br;
438 /* Ultrasparc PBM main bus */
439 dev = qdev_create(NULL, "pbm");
440 qdev_init_nofail(dev);
441 s = SYS_BUS_DEVICE(dev);
442 /* apb_config */
443 sysbus_mmio_map(s, 0, special_base);
444 /* PCI configuration space */
445 sysbus_mmio_map(s, 1, special_base + 0x1000000ULL);
446 /* pci_ioport */
447 sysbus_mmio_map(s, 2, special_base + 0x2000000ULL);
448 d = FROM_SYSBUS(APBState, s);
450 memory_region_init(&d->pci_mmio, "pci-mmio", 0x100000000ULL);
451 memory_region_add_subregion(get_system_memory(), mem_base, &d->pci_mmio);
453 d->bus = pci_register_bus(&d->busdev.qdev, "pci",
454 pci_apb_set_irq, pci_pbm_map_irq, d,
455 &d->pci_mmio,
456 get_system_io(),
457 0, 32, TYPE_PCI_BUS);
459 *pbm_irqs = d->pbm_irqs;
460 d->ivec_irqs = ivec_irqs;
462 pci_create_simple(d->bus, 0, "pbm-pci");
464 /* APB secondary busses */
465 pci_dev = pci_create_multifunction(d->bus, PCI_DEVFN(1, 0), true,
466 "pbm-bridge");
467 br = DO_UPCAST(PCIBridge, dev, pci_dev);
468 pci_bridge_map_irq(br, "Advanced PCI Bus secondary bridge 1",
469 pci_apb_map_irq);
470 qdev_init_nofail(&pci_dev->qdev);
471 *bus2 = pci_bridge_get_sec_bus(br);
473 pci_dev = pci_create_multifunction(d->bus, PCI_DEVFN(1, 1), true,
474 "pbm-bridge");
475 br = DO_UPCAST(PCIBridge, dev, pci_dev);
476 pci_bridge_map_irq(br, "Advanced PCI Bus secondary bridge 2",
477 pci_apb_map_irq);
478 qdev_init_nofail(&pci_dev->qdev);
479 *bus3 = pci_bridge_get_sec_bus(br);
481 return d->bus;
484 static void pci_pbm_reset(DeviceState *d)
486 unsigned int i;
487 APBState *s = container_of(d, APBState, busdev.qdev);
489 for (i = 0; i < 8; i++) {
490 s->pci_irq_map[i] &= PBM_PCI_IMR_MASK;
492 for (i = 0; i < 32; i++) {
493 s->obio_irq_map[i] &= PBM_PCI_IMR_MASK;
496 s->irq_request = NO_IRQ_REQUEST;
497 s->pci_irq_in = 0ULL;
499 if (s->nr_resets++ == 0) {
500 /* Power on reset */
501 s->reset_control = POR;
505 static const MemoryRegionOps pci_config_ops = {
506 .read = apb_pci_config_read,
507 .write = apb_pci_config_write,
508 .endianness = DEVICE_NATIVE_ENDIAN,
511 static int pci_pbm_init_device(SysBusDevice *dev)
513 APBState *s;
514 unsigned int i;
516 s = FROM_SYSBUS(APBState, dev);
517 for (i = 0; i < 8; i++) {
518 s->pci_irq_map[i] = (0x1f << 6) | (i << 2);
520 for (i = 0; i < 32; i++) {
521 s->obio_irq_map[i] = ((0x1f << 6) | 0x20) + i;
523 s->pbm_irqs = qemu_allocate_irqs(pci_apb_set_irq, s, MAX_IVEC);
524 s->irq_request = NO_IRQ_REQUEST;
525 s->pci_irq_in = 0ULL;
527 /* apb_config */
528 memory_region_init_io(&s->apb_config, &apb_config_ops, s, "apb-config",
529 0x10000);
530 /* at region 0 */
531 sysbus_init_mmio(dev, &s->apb_config);
533 memory_region_init_io(&s->pci_config, &pci_config_ops, s, "apb-pci-config",
534 0x1000000);
535 /* at region 1 */
536 sysbus_init_mmio(dev, &s->pci_config);
538 /* pci_ioport */
539 memory_region_init_io(&s->pci_ioport, &pci_ioport_ops, s,
540 "apb-pci-ioport", 0x10000);
541 /* at region 2 */
542 sysbus_init_mmio(dev, &s->pci_ioport);
544 return 0;
547 static int pbm_pci_host_init(PCIDevice *d)
549 pci_set_word(d->config + PCI_COMMAND,
550 PCI_COMMAND_MEMORY | PCI_COMMAND_MASTER);
551 pci_set_word(d->config + PCI_STATUS,
552 PCI_STATUS_FAST_BACK | PCI_STATUS_66MHZ |
553 PCI_STATUS_DEVSEL_MEDIUM);
554 return 0;
557 static void pbm_pci_host_class_init(ObjectClass *klass, void *data)
559 PCIDeviceClass *k = PCI_DEVICE_CLASS(klass);
561 k->init = pbm_pci_host_init;
562 k->vendor_id = PCI_VENDOR_ID_SUN;
563 k->device_id = PCI_DEVICE_ID_SUN_SABRE;
564 k->class_id = PCI_CLASS_BRIDGE_HOST;
567 static const TypeInfo pbm_pci_host_info = {
568 .name = "pbm-pci",
569 .parent = TYPE_PCI_DEVICE,
570 .instance_size = sizeof(PCIDevice),
571 .class_init = pbm_pci_host_class_init,
574 static void pbm_host_class_init(ObjectClass *klass, void *data)
576 DeviceClass *dc = DEVICE_CLASS(klass);
577 SysBusDeviceClass *k = SYS_BUS_DEVICE_CLASS(klass);
579 k->init = pci_pbm_init_device;
580 dc->reset = pci_pbm_reset;
583 static const TypeInfo pbm_host_info = {
584 .name = "pbm",
585 .parent = TYPE_SYS_BUS_DEVICE,
586 .instance_size = sizeof(APBState),
587 .class_init = pbm_host_class_init,
590 static void pbm_pci_bridge_class_init(ObjectClass *klass, void *data)
592 DeviceClass *dc = DEVICE_CLASS(klass);
593 PCIDeviceClass *k = PCI_DEVICE_CLASS(klass);
595 k->init = apb_pci_bridge_initfn;
596 k->exit = pci_bridge_exitfn;
597 k->vendor_id = PCI_VENDOR_ID_SUN;
598 k->device_id = PCI_DEVICE_ID_SUN_SIMBA;
599 k->revision = 0x11;
600 k->config_write = pci_bridge_write_config;
601 k->is_bridge = 1;
602 dc->reset = pci_bridge_reset;
603 dc->vmsd = &vmstate_pci_device;
606 static const TypeInfo pbm_pci_bridge_info = {
607 .name = "pbm-bridge",
608 .parent = TYPE_PCI_DEVICE,
609 .instance_size = sizeof(PCIBridge),
610 .class_init = pbm_pci_bridge_class_init,
613 static void pbm_register_types(void)
615 type_register_static(&pbm_host_info);
616 type_register_static(&pbm_pci_host_info);
617 type_register_static(&pbm_pci_bridge_info);
620 type_init(pbm_register_types)