2 * HP-PARISC Astro/Pluto/Ike/REO system bus adapter (SBA)
3 * with Elroy PCI bus (LBA) adapter emulation
4 * Found in C3000 and similar machines
6 * (C) 2023 by Helge Deller <deller@gmx.de>
8 * This work is licensed under the GNU GPL license version 2 or later.
10 * Chip documentation is available at:
11 * https://parisc.wiki.kernel.org/index.php/Technical_Documentation
14 * - All user-added devices are currently attached to the first
15 * Elroy (PCI bus) only for now. To fix this additional work in
16 * SeaBIOS and this driver is needed. See "user_creatable" flag below.
17 * - GMMIO (Greater than 4 GB MMIO) register
20 #define TYPE_ASTRO_IOMMU_MEMORY_REGION "astro-iommu-memory-region"
22 #define F_EXTEND(addr) ((addr) | MAKE_64BIT_MASK(32, 32))
24 #include "qemu/osdep.h"
25 #include "qemu/module.h"
26 #include "qemu/units.h"
27 #include "qapi/error.h"
29 #include "hw/pci/pci_device.h"
30 #include "hw/pci/pci_bus.h"
31 #include "hw/qdev-properties.h"
32 #include "hw/pci-host/astro.h"
33 #include "hw/hppa/hppa_hardware.h"
34 #include "migration/vmstate.h"
36 #include "qom/object.h"
42 static uint64_t mask_32bit_val(hwaddr addr, unsigned size, uint64_t val)
55 static void put_val_in_int64(uint64_t *p, hwaddr addr, unsigned size,
60 } else if (size == 4) {
62 *p = ((*p << 32) >> 32) | (val << 32);
64 *p = ((*p >> 32) << 32) | (uint32_t) val;
69 static void put_val_in_arrary(uint64_t *array, hwaddr start_addr,
70 hwaddr addr, unsigned size, uint64_t val)
74 index = (addr - start_addr) / 8;
75 put_val_in_int64(&array[index], addr, size, val);
80 * The Elroy PCI host bridge. We have at least 4 of those under Astro.
83 static MemTxResult elroy_chip_read_with_attrs(void *opaque, hwaddr addr,
84 uint64_t *data, unsigned size,
87 MemTxResult ret = MEMTX_OK;
88 ElroyState *s = opaque;
92 switch ((addr >> 3) << 3) {
94 val = 0x6000005; /* func_class */
98 * Scratch register, but firmware initializes it with the
99 * PCI BUS number and Linux/HP-UX uses it then.
101 val = s->pci_bus_num;
102 /* Upper byte holds the end of this bus number */
103 val |= s->pci_bus_num << 8;
106 val = s->arb_mask; /* set ARB mask */
109 val = s->status_control;
111 case 0x200 ... 0x250 - 1: /* LMMIO, GMMIO, WLMMIO, WGMMIO, ... */
112 index = (addr - 0x200) / 8;
113 val = s->mmio_base[index];
116 val = s->error_config;
119 val = 0; /* ERROR_STATUS */
121 case 0x0800: /* IOSAPIC_REG_SELECT */
122 val = s->iosapic_reg_select;
125 val = UINT64_MAX; /* XXX: tbc. */
126 g_assert_not_reached();
128 case 0x0810: /* IOSAPIC_REG_WINDOW */
129 switch (s->iosapic_reg_select) {
130 case 0x01: /* IOSAPIC_REG_VERSION */
131 val = (32 << 16) | 1; /* upper 16bit holds max entries */
134 if (s->iosapic_reg_select < ARRAY_SIZE(s->iosapic_reg)) {
135 val = s->iosapic_reg[s->iosapic_reg_select];
137 trace_iosapic_reg_read(s->iosapic_reg_select, size, val);
138 g_assert_not_reached();
141 trace_iosapic_reg_read(s->iosapic_reg_select, size, val);
144 trace_elroy_read(addr, size, val);
145 g_assert_not_reached();
147 trace_elroy_read(addr, size, val);
149 /* for 32-bit accesses mask return value */
150 val = mask_32bit_val(addr, size, val);
152 trace_astro_chip_read(addr, size, val);
158 static MemTxResult elroy_chip_write_with_attrs(void *opaque, hwaddr addr,
159 uint64_t val, unsigned size,
162 ElroyState *s = opaque;
165 trace_elroy_write(addr, size, val);
167 switch ((addr >> 3) << 3) {
169 put_val_in_int64(&s->arb_mask, addr, size, val);
172 put_val_in_int64(&s->status_control, addr, size, val);
174 case 0x200 ... 0x250 - 1: /* LMMIO, GMMIO, WLMMIO, WGMMIO, ... */
175 put_val_in_arrary(s->mmio_base, 0x200, addr, size, val);
178 put_val_in_int64(&s->error_config, addr, size, val);
180 case 0x0800: /* IOSAPIC_REG_SELECT */
181 s->iosapic_reg_select = val;
183 case 0x0810: /* IOSAPIC_REG_WINDOW */
184 trace_iosapic_reg_write(s->iosapic_reg_select, size, val);
185 if (s->iosapic_reg_select < ARRAY_SIZE(s->iosapic_reg)) {
186 s->iosapic_reg[s->iosapic_reg_select] = val;
188 g_assert_not_reached();
191 case 0x0840: /* IOSAPIC_REG_EOI */
192 val = le64_to_cpu(val);
194 for (i = 0; i < ELROY_IRQS; i++) {
195 if ((s->iosapic_reg[0x10 + 2 * i] & 63) == val) {
196 s->ilr &= ~(1ull << i);
201 g_assert_not_reached();
206 static const MemoryRegionOps elroy_chip_ops = {
207 .read_with_attrs = elroy_chip_read_with_attrs,
208 .write_with_attrs = elroy_chip_write_with_attrs,
209 .endianness = DEVICE_LITTLE_ENDIAN,
211 .min_access_size = 4,
212 .max_access_size = 8,
215 .min_access_size = 4,
216 .max_access_size = 8,
221 /* Unlike pci_config_data_le_ops, no check of high bit set in config_reg. */
223 static uint64_t elroy_config_data_read(void *opaque, hwaddr addr, unsigned len)
227 PCIHostState *s = opaque;
228 val = pci_data_read(s->bus, s->config_reg | (addr & 3), len);
229 trace_elroy_pci_config_data_read(s->config_reg | (addr & 3), len, val);
233 static void elroy_config_data_write(void *opaque, hwaddr addr,
234 uint64_t val, unsigned len)
236 PCIHostState *s = opaque;
237 pci_data_write(s->bus, s->config_reg | (addr & 3), val, len);
238 trace_elroy_pci_config_data_write(s->config_reg | (addr & 3), len, val);
241 static const MemoryRegionOps elroy_config_data_ops = {
242 .read = elroy_config_data_read,
243 .write = elroy_config_data_write,
244 .endianness = DEVICE_LITTLE_ENDIAN,
247 static uint64_t elroy_config_addr_read(void *opaque, hwaddr addr, unsigned len)
249 ElroyState *s = opaque;
250 return s->config_reg_elroy;
253 static void elroy_config_addr_write(void *opaque, hwaddr addr,
254 uint64_t val, unsigned len)
256 PCIHostState *s = opaque;
257 ElroyState *es = opaque;
258 es->config_reg_elroy = val; /* keep a copy of original value */
262 static const MemoryRegionOps elroy_config_addr_ops = {
263 .read = elroy_config_addr_read,
264 .write = elroy_config_addr_write,
265 .valid.min_access_size = 4,
266 .valid.max_access_size = 8,
267 .endianness = DEVICE_LITTLE_ENDIAN,
272 * A subroutine of astro_translate_iommu that builds an IOMMUTLBEntry using the
273 * given translated address and mask.
275 static bool make_iommu_tlbe(hwaddr addr, hwaddr taddr, hwaddr mask,
278 hwaddr tce_mask = ~((1ull << 12) - 1);
279 ret->target_as = &address_space_memory;
280 ret->iova = addr & tce_mask;
281 ret->translated_addr = taddr & tce_mask;
282 ret->addr_mask = ~tce_mask;
283 ret->perm = IOMMU_RW;
287 /* Handle PCI-to-system address translation. */
288 static IOMMUTLBEntry astro_translate_iommu(IOMMUMemoryRegion *iommu,
290 IOMMUAccessFlags flag,
293 AstroState *s = container_of(iommu, AstroState, iommu);
294 IOMMUTLBEntry ret = {
295 .target_as = &address_space_memory,
297 .translated_addr = 0,
298 .addr_mask = ~(hwaddr)0,
301 hwaddr pdir_ptr, index, a, ibase;
302 hwaddr addr_mask = 0xfff; /* 4k translation */
305 #define IOVP_SHIFT 12 /* equals PAGE_SHIFT */
306 #define PDIR_INDEX(iovp) ((iovp) >> IOVP_SHIFT)
307 #define IOVP_MASK PAGE_MASK
308 #define SBA_PDIR_VALID_BIT 0x8000000000000000ULL
310 /* "range enable" flag cleared? */
311 if ((s->tlb_ibase & 1) == 0) {
312 make_iommu_tlbe(addr, addr, addr_mask, &ret);
317 ibase = s->tlb_ibase & ~1ULL;
318 if ((a & s->tlb_imask) != ibase) {
319 /* do not translate this one! */
320 make_iommu_tlbe(addr, addr, addr_mask, &ret);
323 index = PDIR_INDEX(a);
324 pdir_ptr = s->tlb_pdir_base + index * sizeof(entry);
325 entry = ldq_le_phys(&address_space_memory, pdir_ptr);
326 if (!(entry & SBA_PDIR_VALID_BIT)) { /* I/O PDIR entry valid ? */
327 g_assert_not_reached();
330 entry &= ~SBA_PDIR_VALID_BIT;
331 entry >>= IOVP_SHIFT;
333 entry |= addr & 0xfff;
334 make_iommu_tlbe(addr, entry, addr_mask, &ret);
338 ret = (IOMMUTLBEntry) { .perm = IOMMU_NONE };
343 static AddressSpace *elroy_pcihost_set_iommu(PCIBus *bus, void *opaque,
346 ElroyState *s = opaque;
347 return &s->astro->iommu_as;
351 * Encoding in IOSAPIC:
352 * base_addr == 0xfffa0000, we want to get 0xa0ff0000.
353 * eid 0x0ff00000 -> 0x00ff0000
354 * id 0x000ff000 -> 0xff000000
356 #define SWIZZLE_HPA(a) \
357 ((((a) & 0x0ff00000) >> 4) | (((a) & 0x000ff000) << 12))
358 #define UNSWIZZLE_HPA(a) \
359 (((((a) << 4) & 0x0ff00000) | (((a) >> 12) & 0x000ff000) | 0xf0000000))
361 /* bits in the "low" I/O Sapic IRdT entry */
362 #define IOSAPIC_IRDT_DISABLE 0x10000 /* if bit is set, mask this irq */
363 #define IOSAPIC_IRDT_PO_LOW 0x02000
364 #define IOSAPIC_IRDT_LEVEL_TRIG 0x08000
365 #define IOSAPIC_IRDT_MODE_LPRI 0x00100
367 #define CPU_IRQ_OFFSET 2
369 static void elroy_set_irq(void *opaque, int irq, int level)
371 ElroyState *s = opaque;
373 uint32_t old_ilr = s->ilr;
377 val = s->iosapic_reg[0x10 + 2 * irq];
378 cpu_hpa = s->iosapic_reg[0x11 + 2 * irq];
379 /* low nibble of val has value to write into CPU irq reg */
380 bit = 1u << (val & (ELROY_IRQS - 1));
381 cpu_hpa = UNSWIZZLE_HPA(cpu_hpa);
383 if (level && (!(val & IOSAPIC_IRDT_DISABLE)) && cpu_hpa) {
384 uint32_t ena = bit & ~old_ilr;
385 s->ilr = old_ilr | bit;
387 stl_be_phys(&address_space_memory, cpu_hpa, val & 63);
390 s->ilr = old_ilr & ~bit;
394 static int elroy_pci_map_irq(PCIDevice *d, int irq_num)
396 int slot = PCI_SLOT(d->devfn);
398 assert(irq_num >= 0 && irq_num < ELROY_IRQS);
399 return slot & (ELROY_IRQS - 1);
402 static void elroy_reset(DeviceState *dev)
404 ElroyState *s = ELROY_PCI_HOST_BRIDGE(dev);
408 * Make sure to disable interrupts at reboot, otherwise the Linux kernel
409 * serial8250_config_port() in drivers/tty/serial/8250/8250_port.c
410 * will hang during autoconfig().
413 for (irq = 0; irq < ELROY_IRQS; irq++) {
414 s->iosapic_reg[0x10 + 2 * irq] = IOSAPIC_IRDT_PO_LOW |
415 IOSAPIC_IRDT_LEVEL_TRIG | (irq + CPU_IRQ_OFFSET) |
416 IOSAPIC_IRDT_DISABLE;
417 s->iosapic_reg[0x11 + 2 * irq] = SWIZZLE_HPA(CPU_HPA);
421 static void elroy_pcihost_init(Object *obj)
423 ElroyState *s = ELROY_PCI_HOST_BRIDGE(obj);
424 PCIHostState *phb = PCI_HOST_BRIDGE(obj);
425 SysBusDevice *sbd = SYS_BUS_DEVICE(obj);
427 /* Elroy config access from CPU. */
428 memory_region_init_io(&s->this_mem, OBJECT(s), &elroy_chip_ops,
431 /* Elroy PCI config. */
432 memory_region_init_io(&phb->conf_mem, OBJECT(phb),
433 &elroy_config_addr_ops, DEVICE(s),
435 memory_region_init_io(&phb->data_mem, OBJECT(phb),
436 &elroy_config_data_ops, DEVICE(s),
438 memory_region_add_subregion(&s->this_mem, 0x40,
440 memory_region_add_subregion(&s->this_mem, 0x48,
443 /* Elroy PCI bus memory. */
444 memory_region_init(&s->pci_mmio, OBJECT(s), "pci-mmio", UINT64_MAX);
445 memory_region_init_io(&s->pci_io, OBJECT(s), &unassigned_io_ops, obj,
447 ((uint32_t) IOS_DIST_BASE_SIZE) / ROPES_PER_IOC);
449 phb->bus = pci_register_root_bus(DEVICE(s), "pci",
450 elroy_set_irq, elroy_pci_map_irq, s,
451 &s->pci_mmio, &s->pci_io,
452 PCI_DEVFN(0, 0), ELROY_IRQS, TYPE_PCI_BUS);
454 sysbus_init_mmio(sbd, &s->this_mem);
456 qdev_init_gpio_in(DEVICE(obj), elroy_set_irq, ELROY_IRQS);
459 static Property elroy_pcihost_properties[] = {
460 DEFINE_PROP_END_OF_LIST(),
463 static const VMStateDescription vmstate_elroy = {
466 .minimum_version_id = 1,
467 .fields = (VMStateField[]) {
468 VMSTATE_UINT64(hpa, ElroyState),
469 VMSTATE_UINT32(pci_bus_num, ElroyState),
470 VMSTATE_UINT64(config_address, ElroyState),
471 VMSTATE_UINT64(config_reg_elroy, ElroyState),
472 VMSTATE_UINT64(status_control, ElroyState),
473 VMSTATE_UINT64(arb_mask, ElroyState),
474 VMSTATE_UINT64_ARRAY(mmio_base, ElroyState, (0x0250 - 0x200) / 8),
475 VMSTATE_UINT64(error_config, ElroyState),
476 VMSTATE_UINT32(iosapic_reg_select, ElroyState),
477 VMSTATE_UINT64_ARRAY(iosapic_reg, ElroyState, 0x20),
478 VMSTATE_UINT32(ilr, ElroyState),
479 VMSTATE_END_OF_LIST()
483 static void elroy_pcihost_class_init(ObjectClass *klass, void *data)
485 DeviceClass *dc = DEVICE_CLASS(klass);
487 dc->reset = elroy_reset;
488 device_class_set_props(dc, elroy_pcihost_properties);
489 dc->vmsd = &vmstate_elroy;
490 dc->user_creatable = false;
493 static const TypeInfo elroy_pcihost_info = {
494 .name = TYPE_ELROY_PCI_HOST_BRIDGE,
495 .parent = TYPE_PCI_HOST_BRIDGE,
496 .instance_init = elroy_pcihost_init,
497 .instance_size = sizeof(ElroyState),
498 .class_init = elroy_pcihost_class_init,
501 static void elroy_register_types(void)
503 type_register_static(&elroy_pcihost_info);
506 type_init(elroy_register_types)
509 static ElroyState *elroy_init(int num)
513 dev = qdev_new(TYPE_ELROY_PCI_HOST_BRIDGE);
514 dev->id = g_strdup_printf("elroy%d", num);
515 sysbus_realize_and_unref(SYS_BUS_DEVICE(dev), &error_fatal);
517 return ELROY_PCI_HOST_BRIDGE(dev);
524 static MemTxResult astro_chip_read_with_attrs(void *opaque, hwaddr addr,
525 uint64_t *data, unsigned size,
528 AstroState *s = opaque;
529 MemTxResult ret = MEMTX_OK;
533 switch ((addr >> 3) << 3) {
535 case 0x0000: /* ID */
536 val = (0x01 << 3) | 0x01ULL;
538 case 0x0008: /* IOC_CTRL */
541 case 0x0010: /* TOC_CLIENT_ID */
543 case 0x0030: /* HP-UX 10.20 and 11.11 reads it. No idea. */
546 case 0x0300 ... 0x03d8: /* LMMIO_DIRECT0_BASE... */
547 index = (addr - 0x300) / 8;
548 val = s->ioc_ranges[index];
554 case 0x10230: /* HP-UX 11.11 reads it. No idea. */
557 case 0x22108: /* IOC STATUS_CONTROL */
558 val = s->ioc_status_ctrl;
560 case 0x20200 ... 0x20240 - 1: /* IOC Rope0_Control ... */
561 index = (addr - 0x20200) / 8;
562 val = s->ioc_rope_control[index];
564 case 0x20040: /* IOC Rope config */
565 val = s->ioc_rope_config;
567 case 0x20050: /* IOC Rope debug */
570 case 0x20108: /* IOC STATUS_CONTROL */
571 val = s->ioc_status_control;
573 case 0x20310: /* IOC_PCOM */
575 /* TODO: flush iommu */
578 val = s->ioc_flush_control;
580 /* empty placeholders for non-existent elroys */
581 #define EMPTY_PORT(x) case x: case x+8: val = 0; break; \
582 case x+40: case x+48: val = UINT64_MAX; break;
594 trace_astro_chip_read(addr, size, val);
595 g_assert_not_reached();
598 /* for 32-bit accesses mask return value */
599 val = mask_32bit_val(addr, size, val);
601 trace_astro_chip_read(addr, size, val);
606 static MemTxResult astro_chip_write_with_attrs(void *opaque, hwaddr addr,
607 uint64_t val, unsigned size,
610 AstroState *s = opaque;
612 trace_astro_chip_write(addr, size, val);
614 switch ((addr >> 3) << 3) {
615 case 0x0000: /* ID */
617 case 0x0008: /* IOC_CTRL */
619 put_val_in_int64(&s->ioc_ctrl, addr, size, val);
621 case 0x0010: /* TOC_CLIENT_ID */
623 case 0x0030: /* HP-UX 10.20 and 11.11 reads it. No idea. */
625 case 0x0300 ... 0x03d8 - 1: /* LMMIO_DIRECT0_BASE... */
626 put_val_in_arrary(s->ioc_ranges, 0x300, addr, size, val);
630 case 0x10230: /* HP-UX 11.11 reads it. No idea. */
632 case 0x22108: /* IOC STATUS_CONTROL */
633 put_val_in_int64(&s->ioc_status_ctrl, addr, size, val);
635 case 0x20200 ... 0x20240 - 1: /* IOC Rope0_Control ... */
636 put_val_in_arrary(s->ioc_rope_control, 0x20200, addr, size, val);
638 case 0x20040: /* IOC Rope config */
639 put_val_in_int64(&s->ioc_rope_config, addr, size, val);
642 put_val_in_int64(&s->tlb_ibase, addr, size, val);
645 put_val_in_int64(&s->tlb_imask, addr, size, val);
648 put_val_in_int64(&s->tlb_pcom, addr, size, val);
649 /* TODO: flush iommu */
652 put_val_in_int64(&s->tlb_tcnfg, addr, size, val);
655 put_val_in_int64(&s->tlb_pdir_base, addr, size, val);
658 * empty placeholders for non-existent elroys, e.g.
659 * func_class, pci config & data
661 #define EMPTY_PORT(x) case x: case x+8: case x+0x40: case x+0x48:
674 /* Controlled by astro_chip_mem_valid above. */
675 trace_astro_chip_write(addr, size, val);
676 g_assert_not_reached();
681 static const MemoryRegionOps astro_chip_ops = {
682 .read_with_attrs = astro_chip_read_with_attrs,
683 .write_with_attrs = astro_chip_write_with_attrs,
684 .endianness = DEVICE_LITTLE_ENDIAN,
686 .min_access_size = 4,
687 .max_access_size = 8,
690 .min_access_size = 4,
691 .max_access_size = 8,
695 static const VMStateDescription vmstate_astro = {
698 .minimum_version_id = 1,
699 .fields = (VMStateField[]) {
700 VMSTATE_UINT64(ioc_ctrl, AstroState),
701 VMSTATE_UINT64(ioc_status_ctrl, AstroState),
702 VMSTATE_UINT64_ARRAY(ioc_ranges, AstroState, (0x03d8 - 0x300) / 8),
703 VMSTATE_UINT64(ioc_rope_config, AstroState),
704 VMSTATE_UINT64(ioc_status_control, AstroState),
705 VMSTATE_UINT64(ioc_flush_control, AstroState),
706 VMSTATE_UINT64_ARRAY(ioc_rope_control, AstroState, 8),
707 VMSTATE_UINT64(tlb_ibase, AstroState),
708 VMSTATE_UINT64(tlb_imask, AstroState),
709 VMSTATE_UINT64(tlb_pcom, AstroState),
710 VMSTATE_UINT64(tlb_tcnfg, AstroState),
711 VMSTATE_UINT64(tlb_pdir_base, AstroState),
712 VMSTATE_END_OF_LIST()
716 static void astro_reset(DeviceState *dev)
718 AstroState *s = ASTRO_CHIP(dev);
721 s->ioc_ctrl = 0x29cf;
722 s->ioc_rope_config = 0xc5f;
723 s->ioc_flush_control = 0xb03;
724 s->ioc_status_control = 0;
725 memset(&s->ioc_rope_control, 0, sizeof(s->ioc_rope_control));
728 * The SBA BASE/MASK registers control CPU -> IO routing.
729 * The LBA BASE/MASK registers control IO -> System routing (in Elroy)
731 memset(&s->ioc_ranges, 0, sizeof(s->ioc_ranges));
732 s->ioc_ranges[(0x360 - 0x300) / 8] = LMMIO_DIST_BASE_ADDR | 0x01; /* LMMIO_DIST_BASE (SBA) */
733 s->ioc_ranges[(0x368 - 0x300) / 8] = 0xfc000000; /* LMMIO_DIST_MASK */
734 s->ioc_ranges[(0x370 - 0x300) / 8] = 0; /* LMMIO_DIST_ROUTE */
735 s->ioc_ranges[(0x390 - 0x300) / 8] = IOS_DIST_BASE_ADDR | 0x01; /* IOS_DIST_BASE */
736 s->ioc_ranges[(0x398 - 0x300) / 8] = 0xffffff0000; /* IOS_DIST_MASK */
737 s->ioc_ranges[(0x3a0 - 0x300) / 8] = 0x3400000000000000ULL; /* IOS_DIST_ROUTE */
738 s->ioc_ranges[(0x3c0 - 0x300) / 8] = 0xfffee00000; /* IOS_DIRECT_BASE */
739 s->ioc_ranges[(0x3c8 - 0x300) / 8] = 0xffffff0000; /* IOS_DIRECT_MASK */
740 s->ioc_ranges[(0x3d0 - 0x300) / 8] = 0x0; /* IOS_DIRECT_ROUTE */
746 s->tlb_pdir_base = 0;
748 for (i = 0; i < ELROY_NUM; i++) {
749 elroy_reset(DEVICE(s->elroy[i]));
753 static void astro_init(Object *obj)
757 static void astro_realize(DeviceState *obj, Error **errp)
759 AstroState *s = ASTRO_CHIP(obj);
760 SysBusDevice *sbd = SYS_BUS_DEVICE(obj);
763 memory_region_init_io(&s->this_mem, OBJECT(s), &astro_chip_ops,
764 s, "astro", 0x40000);
765 sysbus_init_mmio(sbd, &s->this_mem);
767 /* Host memory as seen from Elroys PCI side, via the IOMMU. */
768 memory_region_init_iommu(&s->iommu, sizeof(s->iommu),
769 TYPE_ASTRO_IOMMU_MEMORY_REGION, OBJECT(s),
770 "iommu-astro", UINT64_MAX);
771 address_space_init(&s->iommu_as, MEMORY_REGION(&s->iommu),
774 /* Create Elroys (PCI host bus chips). */
775 for (i = 0; i < ELROY_NUM; i++) {
776 static const int elroy_hpa_offsets[ELROY_NUM] = {
777 0x30000, 0x32000, 0x38000, 0x3c000 };
778 static const char elroy_rope_nr[ELROY_NUM] = {
779 0, 1, 4, 6 }; /* busnum path, e.g. [10:6] */
786 addr_offset = elroy_hpa_offsets[i];
787 rope = elroy_rope_nr[i];
789 elroy = elroy_init(i);
791 elroy->hpa = ASTRO_HPA + addr_offset;
792 elroy->pci_bus_num = i;
796 * NOTE: we only allow PCI devices on first Elroy for now.
797 * SeaBIOS will not find devices on the other busses.
800 qbus_mark_full(&PCI_HOST_BRIDGE(elroy)->bus->qbus);
803 /* map elroy config addresses into Astro space */
804 memory_region_add_subregion(&s->this_mem, addr_offset,
808 elroy->mmio_base[(0x0200 - 0x200) / 8] = 0xf0000001;
809 elroy->mmio_base[(0x0208 - 0x200) / 8] = 0xf8000000;
811 elroy->mmio_base[(0x0210 - 0x200) / 8] = 0x000000f800000001;
812 elroy->mmio_base[(0x0218 - 0x200) / 8] = 0x000000ff80000000;
814 elroy->mmio_base[(0x0220 - 0x200) / 8] = 0xf0000001;
815 elroy->mmio_base[(0x0228 - 0x200) / 8] = 0xf0000000;
817 elroy->mmio_base[(0x0230 - 0x200) / 8] = 0x000000f800000001;
818 elroy->mmio_base[(0x0238 - 0x200) / 8] = 0x000000fc00000000;
820 map_size = IOS_DIST_BASE_SIZE / ROPES_PER_IOC;
821 elroy->mmio_base[(0x0240 - 0x200) / 8] = rope * map_size | 0x01;
822 elroy->mmio_base[(0x0248 - 0x200) / 8] = 0x0000e000;
824 /* map elroys mmio */
825 map_size = LMMIO_DIST_BASE_SIZE / ROPES_PER_IOC;
826 map_addr = F_EXTEND(LMMIO_DIST_BASE_ADDR + rope * map_size);
827 memory_region_init_alias(&elroy->pci_mmio_alias, OBJECT(elroy),
829 &elroy->pci_mmio, (uint32_t) map_addr, map_size);
830 memory_region_add_subregion(get_system_memory(), map_addr,
831 &elroy->pci_mmio_alias);
834 map_size = IOS_DIST_BASE_SIZE / ROPES_PER_IOC;
835 map_addr = F_EXTEND(IOS_DIST_BASE_ADDR + rope * map_size);
836 memory_region_add_subregion(get_system_memory(), map_addr,
839 /* Host memory as seen from the PCI side, via the IOMMU. */
840 pci_setup_iommu(PCI_HOST_BRIDGE(elroy)->bus, elroy_pcihost_set_iommu,
845 static void astro_class_init(ObjectClass *klass, void *data)
847 DeviceClass *dc = DEVICE_CLASS(klass);
849 dc->reset = astro_reset;
850 dc->vmsd = &vmstate_astro;
851 dc->realize = astro_realize;
853 * astro with elroys are hard part of the newer PA2.0 machines and can not
854 * be created without that hardware
856 dc->user_creatable = false;
859 static const TypeInfo astro_chip_info = {
860 .name = TYPE_ASTRO_CHIP,
861 .parent = TYPE_SYS_BUS_DEVICE,
862 .instance_init = astro_init,
863 .instance_size = sizeof(AstroState),
864 .class_init = astro_class_init,
867 static void astro_iommu_memory_region_class_init(ObjectClass *klass,
870 IOMMUMemoryRegionClass *imrc = IOMMU_MEMORY_REGION_CLASS(klass);
872 imrc->translate = astro_translate_iommu;
875 static const TypeInfo astro_iommu_memory_region_info = {
876 .parent = TYPE_IOMMU_MEMORY_REGION,
877 .name = TYPE_ASTRO_IOMMU_MEMORY_REGION,
878 .class_init = astro_iommu_memory_region_class_init,
882 static void astro_register_types(void)
884 type_register_static(&astro_chip_info);
885 type_register_static(&astro_iommu_memory_region_info);
888 type_init(astro_register_types)