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 #include "qemu/osdep.h"
23 #include "qemu/module.h"
24 #include "qemu/units.h"
25 #include "qapi/error.h"
27 #include "hw/pci/pci_device.h"
28 #include "hw/pci/pci_bus.h"
29 #include "hw/qdev-properties.h"
30 #include "hw/pci-host/astro.h"
31 #include "hw/hppa/hppa_hardware.h"
32 #include "migration/vmstate.h"
34 #include "qom/object.h"
40 static uint64_t mask_32bit_val(hwaddr addr
, unsigned size
, uint64_t val
)
53 static void put_val_in_int64(uint64_t *p
, hwaddr addr
, unsigned size
,
58 } else if (size
== 4) {
60 *p
= ((*p
<< 32) >> 32) | (val
<< 32);
62 *p
= ((*p
>> 32) << 32) | (uint32_t) val
;
67 static void put_val_in_arrary(uint64_t *array
, hwaddr start_addr
,
68 hwaddr addr
, unsigned size
, uint64_t val
)
72 index
= (addr
- start_addr
) / 8;
73 put_val_in_int64(&array
[index
], addr
, size
, val
);
78 * The Elroy PCI host bridge. We have at least 4 of those under Astro.
81 static MemTxResult
elroy_chip_read_with_attrs(void *opaque
, hwaddr addr
,
82 uint64_t *data
, unsigned size
,
85 MemTxResult ret
= MEMTX_OK
;
86 ElroyState
*s
= opaque
;
90 switch ((addr
>> 3) << 3) {
92 val
= 0x6000005; /* func_class */
96 * Scratch register, but firmware initializes it with the
97 * PCI BUS number and Linux/HP-UX uses it then.
100 /* Upper byte holds the end of this bus number */
101 val
|= s
->pci_bus_num
<< 8;
104 val
= s
->arb_mask
; /* set ARB mask */
107 val
= s
->status_control
;
109 case 0x200 ... 0x250 - 1: /* LMMIO, GMMIO, WLMMIO, WGMMIO, ... */
110 index
= (addr
- 0x200) / 8;
111 val
= s
->mmio_base
[index
];
114 val
= s
->error_config
;
117 val
= 0; /* ERROR_STATUS */
119 case 0x0800: /* IOSAPIC_REG_SELECT */
120 val
= s
->iosapic_reg_select
;
123 val
= UINT64_MAX
; /* XXX: tbc. */
124 g_assert_not_reached();
126 case 0x0810: /* IOSAPIC_REG_WINDOW */
127 switch (s
->iosapic_reg_select
) {
128 case 0x01: /* IOSAPIC_REG_VERSION */
129 val
= (32 << 16) | 1; /* upper 16bit holds max entries */
132 if (s
->iosapic_reg_select
< ARRAY_SIZE(s
->iosapic_reg
)) {
133 val
= s
->iosapic_reg
[s
->iosapic_reg_select
];
135 trace_iosapic_reg_read(s
->iosapic_reg_select
, size
, val
);
136 g_assert_not_reached();
139 trace_iosapic_reg_read(s
->iosapic_reg_select
, size
, val
);
142 trace_elroy_read(addr
, size
, val
);
143 g_assert_not_reached();
145 trace_elroy_read(addr
, size
, val
);
147 /* for 32-bit accesses mask return value */
148 val
= mask_32bit_val(addr
, size
, val
);
150 trace_astro_chip_read(addr
, size
, val
);
156 static MemTxResult
elroy_chip_write_with_attrs(void *opaque
, hwaddr addr
,
157 uint64_t val
, unsigned size
,
160 ElroyState
*s
= opaque
;
163 trace_elroy_write(addr
, size
, val
);
165 switch ((addr
>> 3) << 3) {
167 put_val_in_int64(&s
->arb_mask
, addr
, size
, val
);
170 put_val_in_int64(&s
->status_control
, addr
, size
, val
);
172 case 0x200 ... 0x250 - 1: /* LMMIO, GMMIO, WLMMIO, WGMMIO, ... */
173 put_val_in_arrary(s
->mmio_base
, 0x200, addr
, size
, val
);
176 put_val_in_int64(&s
->error_config
, addr
, size
, val
);
178 case 0x0800: /* IOSAPIC_REG_SELECT */
179 s
->iosapic_reg_select
= val
;
181 case 0x0810: /* IOSAPIC_REG_WINDOW */
182 trace_iosapic_reg_write(s
->iosapic_reg_select
, size
, val
);
183 if (s
->iosapic_reg_select
< ARRAY_SIZE(s
->iosapic_reg
)) {
184 s
->iosapic_reg
[s
->iosapic_reg_select
] = val
;
186 g_assert_not_reached();
189 case 0x0840: /* IOSAPIC_REG_EOI */
190 val
= le64_to_cpu(val
);
192 for (i
= 0; i
< ELROY_IRQS
; i
++) {
193 if ((s
->iosapic_reg
[0x10 + 2 * i
] & 63) == val
) {
194 s
->ilr
&= ~(1ull << i
);
199 g_assert_not_reached();
204 static const MemoryRegionOps elroy_chip_ops
= {
205 .read_with_attrs
= elroy_chip_read_with_attrs
,
206 .write_with_attrs
= elroy_chip_write_with_attrs
,
207 .endianness
= DEVICE_LITTLE_ENDIAN
,
209 .min_access_size
= 4,
210 .max_access_size
= 8,
213 .min_access_size
= 4,
214 .max_access_size
= 8,
219 /* Unlike pci_config_data_le_ops, no check of high bit set in config_reg. */
221 static uint64_t elroy_config_data_read(void *opaque
, hwaddr addr
, unsigned len
)
225 PCIHostState
*s
= opaque
;
226 val
= pci_data_read(s
->bus
, s
->config_reg
| (addr
& 3), len
);
227 trace_elroy_pci_config_data_read(s
->config_reg
| (addr
& 3), len
, val
);
231 static void elroy_config_data_write(void *opaque
, hwaddr addr
,
232 uint64_t val
, unsigned len
)
234 PCIHostState
*s
= opaque
;
235 pci_data_write(s
->bus
, s
->config_reg
| (addr
& 3), val
, len
);
236 trace_elroy_pci_config_data_write(s
->config_reg
| (addr
& 3), len
, val
);
239 static const MemoryRegionOps elroy_config_data_ops
= {
240 .read
= elroy_config_data_read
,
241 .write
= elroy_config_data_write
,
242 .endianness
= DEVICE_LITTLE_ENDIAN
,
245 static uint64_t elroy_config_addr_read(void *opaque
, hwaddr addr
, unsigned len
)
247 ElroyState
*s
= opaque
;
248 return s
->config_reg_elroy
;
251 static void elroy_config_addr_write(void *opaque
, hwaddr addr
,
252 uint64_t val
, unsigned len
)
254 PCIHostState
*s
= opaque
;
255 ElroyState
*es
= opaque
;
256 es
->config_reg_elroy
= val
; /* keep a copy of original value */
260 static const MemoryRegionOps elroy_config_addr_ops
= {
261 .read
= elroy_config_addr_read
,
262 .write
= elroy_config_addr_write
,
263 .valid
.min_access_size
= 4,
264 .valid
.max_access_size
= 8,
265 .endianness
= DEVICE_LITTLE_ENDIAN
,
270 * A subroutine of astro_translate_iommu that builds an IOMMUTLBEntry using the
271 * given translated address and mask.
273 static bool make_iommu_tlbe(hwaddr addr
, hwaddr taddr
, hwaddr mask
,
276 hwaddr tce_mask
= ~((1ull << 12) - 1);
277 ret
->target_as
= &address_space_memory
;
278 ret
->iova
= addr
& tce_mask
;
279 ret
->translated_addr
= taddr
& tce_mask
;
280 ret
->addr_mask
= ~tce_mask
;
281 ret
->perm
= IOMMU_RW
;
285 /* Handle PCI-to-system address translation. */
286 static IOMMUTLBEntry
astro_translate_iommu(IOMMUMemoryRegion
*iommu
,
288 IOMMUAccessFlags flag
,
291 AstroState
*s
= container_of(iommu
, AstroState
, iommu
);
292 IOMMUTLBEntry ret
= {
293 .target_as
= &address_space_memory
,
295 .translated_addr
= 0,
296 .addr_mask
= ~(hwaddr
)0,
299 hwaddr pdir_ptr
, index
, a
, ibase
;
300 hwaddr addr_mask
= 0xfff; /* 4k translation */
303 #define IOVP_SHIFT 12 /* equals PAGE_SHIFT */
304 #define PDIR_INDEX(iovp) ((iovp) >> IOVP_SHIFT)
305 #define IOVP_MASK PAGE_MASK
306 #define SBA_PDIR_VALID_BIT 0x8000000000000000ULL
308 /* "range enable" flag cleared? */
309 if ((s
->tlb_ibase
& 1) == 0) {
310 make_iommu_tlbe(addr
, addr
, addr_mask
, &ret
);
315 ibase
= s
->tlb_ibase
& ~1ULL;
316 if ((a
& s
->tlb_imask
) != ibase
) {
317 /* do not translate this one! */
318 make_iommu_tlbe(addr
, addr
, addr_mask
, &ret
);
321 index
= PDIR_INDEX(a
);
322 pdir_ptr
= s
->tlb_pdir_base
+ index
* sizeof(entry
);
323 entry
= ldq_le_phys(&address_space_memory
, pdir_ptr
);
324 if (!(entry
& SBA_PDIR_VALID_BIT
)) { /* I/O PDIR entry valid ? */
325 g_assert_not_reached();
328 entry
&= ~SBA_PDIR_VALID_BIT
;
329 entry
>>= IOVP_SHIFT
;
331 entry
|= addr
& 0xfff;
332 make_iommu_tlbe(addr
, entry
, addr_mask
, &ret
);
336 ret
= (IOMMUTLBEntry
) { .perm
= IOMMU_NONE
};
341 static AddressSpace
*elroy_pcihost_set_iommu(PCIBus
*bus
, void *opaque
,
344 ElroyState
*s
= opaque
;
345 return &s
->astro
->iommu_as
;
348 static const PCIIOMMUOps elroy_pcihost_iommu_ops
= {
349 .get_address_space
= elroy_pcihost_set_iommu
,
353 * Encoding in IOSAPIC:
354 * base_addr == 0xfffa0000, we want to get 0xa0ff0000.
355 * eid 0x0ff00000 -> 0x00ff0000
356 * id 0x000ff000 -> 0xff000000
358 #define SWIZZLE_HPA(a) \
359 ((((a) & 0x0ff00000) >> 4) | (((a) & 0x000ff000) << 12))
360 #define UNSWIZZLE_HPA(a) \
361 (((((a) << 4) & 0x0ff00000) | (((a) >> 12) & 0x000ff000) | 0xf0000000))
363 /* bits in the "low" I/O Sapic IRdT entry */
364 #define IOSAPIC_IRDT_DISABLE 0x10000 /* if bit is set, mask this irq */
365 #define IOSAPIC_IRDT_PO_LOW 0x02000
366 #define IOSAPIC_IRDT_LEVEL_TRIG 0x08000
367 #define IOSAPIC_IRDT_MODE_LPRI 0x00100
369 #define CPU_IRQ_OFFSET 2
371 static void elroy_set_irq(void *opaque
, int irq
, int level
)
373 ElroyState
*s
= opaque
;
375 uint32_t old_ilr
= s
->ilr
;
379 val
= s
->iosapic_reg
[0x10 + 2 * irq
];
380 cpu_hpa
= s
->iosapic_reg
[0x11 + 2 * irq
];
381 /* low nibble of val has value to write into CPU irq reg */
382 bit
= 1u << (val
& (ELROY_IRQS
- 1));
383 cpu_hpa
= UNSWIZZLE_HPA(cpu_hpa
);
385 if (level
&& (!(val
& IOSAPIC_IRDT_DISABLE
)) && cpu_hpa
) {
386 uint32_t ena
= bit
& ~old_ilr
;
387 s
->ilr
= old_ilr
| bit
;
389 stl_be_phys(&address_space_memory
, cpu_hpa
, val
& 63);
392 s
->ilr
= old_ilr
& ~bit
;
396 static int elroy_pci_map_irq(PCIDevice
*d
, int irq_num
)
398 int slot
= PCI_SLOT(d
->devfn
);
400 assert(irq_num
>= 0 && irq_num
< ELROY_IRQS
);
401 return slot
& (ELROY_IRQS
- 1);
404 static void elroy_reset(DeviceState
*dev
)
406 ElroyState
*s
= ELROY_PCI_HOST_BRIDGE(dev
);
410 * Make sure to disable interrupts at reboot, otherwise the Linux kernel
411 * serial8250_config_port() in drivers/tty/serial/8250/8250_port.c
412 * will hang during autoconfig().
415 for (irq
= 0; irq
< ELROY_IRQS
; irq
++) {
416 s
->iosapic_reg
[0x10 + 2 * irq
] = IOSAPIC_IRDT_PO_LOW
|
417 IOSAPIC_IRDT_LEVEL_TRIG
| (irq
+ CPU_IRQ_OFFSET
) |
418 IOSAPIC_IRDT_DISABLE
;
419 s
->iosapic_reg
[0x11 + 2 * irq
] = SWIZZLE_HPA(CPU_HPA
);
423 static void elroy_pcihost_init(Object
*obj
)
425 ElroyState
*s
= ELROY_PCI_HOST_BRIDGE(obj
);
426 PCIHostState
*phb
= PCI_HOST_BRIDGE(obj
);
427 SysBusDevice
*sbd
= SYS_BUS_DEVICE(obj
);
429 /* Elroy config access from CPU. */
430 memory_region_init_io(&s
->this_mem
, OBJECT(s
), &elroy_chip_ops
,
433 /* Elroy PCI config. */
434 memory_region_init_io(&phb
->conf_mem
, OBJECT(phb
),
435 &elroy_config_addr_ops
, DEVICE(s
),
437 memory_region_init_io(&phb
->data_mem
, OBJECT(phb
),
438 &elroy_config_data_ops
, DEVICE(s
),
440 memory_region_add_subregion(&s
->this_mem
, 0x40,
442 memory_region_add_subregion(&s
->this_mem
, 0x48,
445 /* Elroy PCI bus memory. */
446 memory_region_init(&s
->pci_mmio
, OBJECT(s
), "pci-mmio", UINT64_MAX
);
447 memory_region_init_io(&s
->pci_io
, OBJECT(s
), &unassigned_io_ops
, obj
,
449 ((uint32_t) IOS_DIST_BASE_SIZE
) / ROPES_PER_IOC
);
451 phb
->bus
= pci_register_root_bus(DEVICE(s
), "pci",
452 elroy_set_irq
, elroy_pci_map_irq
, s
,
453 &s
->pci_mmio
, &s
->pci_io
,
454 PCI_DEVFN(0, 0), ELROY_IRQS
, TYPE_PCI_BUS
);
456 sysbus_init_mmio(sbd
, &s
->this_mem
);
458 qdev_init_gpio_in(DEVICE(obj
), elroy_set_irq
, ELROY_IRQS
);
461 static Property elroy_pcihost_properties
[] = {
462 DEFINE_PROP_END_OF_LIST(),
465 static const VMStateDescription vmstate_elroy
= {
468 .minimum_version_id
= 1,
469 .fields
= (VMStateField
[]) {
470 VMSTATE_UINT64(hpa
, ElroyState
),
471 VMSTATE_UINT32(pci_bus_num
, ElroyState
),
472 VMSTATE_UINT64(config_address
, ElroyState
),
473 VMSTATE_UINT64(config_reg_elroy
, ElroyState
),
474 VMSTATE_UINT64(status_control
, ElroyState
),
475 VMSTATE_UINT64(arb_mask
, ElroyState
),
476 VMSTATE_UINT64_ARRAY(mmio_base
, ElroyState
, (0x0250 - 0x200) / 8),
477 VMSTATE_UINT64(error_config
, ElroyState
),
478 VMSTATE_UINT32(iosapic_reg_select
, ElroyState
),
479 VMSTATE_UINT64_ARRAY(iosapic_reg
, ElroyState
, 0x20),
480 VMSTATE_UINT32(ilr
, ElroyState
),
481 VMSTATE_END_OF_LIST()
485 static void elroy_pcihost_class_init(ObjectClass
*klass
, void *data
)
487 DeviceClass
*dc
= DEVICE_CLASS(klass
);
489 dc
->reset
= elroy_reset
;
490 device_class_set_props(dc
, elroy_pcihost_properties
);
491 dc
->vmsd
= &vmstate_elroy
;
492 dc
->user_creatable
= false;
495 static const TypeInfo elroy_pcihost_info
= {
496 .name
= TYPE_ELROY_PCI_HOST_BRIDGE
,
497 .parent
= TYPE_PCI_HOST_BRIDGE
,
498 .instance_init
= elroy_pcihost_init
,
499 .instance_size
= sizeof(ElroyState
),
500 .class_init
= elroy_pcihost_class_init
,
503 static void elroy_register_types(void)
505 type_register_static(&elroy_pcihost_info
);
508 type_init(elroy_register_types
)
511 static ElroyState
*elroy_init(int num
)
515 dev
= qdev_new(TYPE_ELROY_PCI_HOST_BRIDGE
);
516 dev
->id
= g_strdup_printf("elroy%d", num
);
517 sysbus_realize_and_unref(SYS_BUS_DEVICE(dev
), &error_fatal
);
519 return ELROY_PCI_HOST_BRIDGE(dev
);
526 static MemTxResult
astro_chip_read_with_attrs(void *opaque
, hwaddr addr
,
527 uint64_t *data
, unsigned size
,
530 AstroState
*s
= opaque
;
531 MemTxResult ret
= MEMTX_OK
;
535 switch ((addr
>> 3) << 3) {
537 case 0x0000: /* ID */
538 val
= (0x01 << 3) | 0x01ULL
;
540 case 0x0008: /* IOC_CTRL */
543 case 0x0010: /* TOC_CLIENT_ID */
545 case 0x0030: /* HP-UX 10.20 and 11.11 reads it. No idea. */
548 case 0x0300 ... 0x03d8: /* LMMIO_DIRECT0_BASE... */
549 index
= (addr
- 0x300) / 8;
550 val
= s
->ioc_ranges
[index
];
556 case 0x10230: /* HP-UX 11.11 reads it. No idea. */
559 case 0x22108: /* IOC STATUS_CONTROL */
560 val
= s
->ioc_status_ctrl
;
562 case 0x20200 ... 0x20240 - 1: /* IOC Rope0_Control ... */
563 index
= (addr
- 0x20200) / 8;
564 val
= s
->ioc_rope_control
[index
];
566 case 0x20040: /* IOC Rope config */
567 val
= s
->ioc_rope_config
;
569 case 0x20050: /* IOC Rope debug */
572 case 0x20108: /* IOC STATUS_CONTROL */
573 val
= s
->ioc_status_control
;
575 case 0x20310: /* IOC_PCOM */
577 /* TODO: flush iommu */
580 val
= s
->ioc_flush_control
;
582 /* empty placeholders for non-existent elroys */
583 #define EMPTY_PORT(x) case x: case x+8: val = 0; break; \
584 case x+40: case x+48: val = UINT64_MAX; break;
596 trace_astro_chip_read(addr
, size
, val
);
597 g_assert_not_reached();
600 /* for 32-bit accesses mask return value */
601 val
= mask_32bit_val(addr
, size
, val
);
603 trace_astro_chip_read(addr
, size
, val
);
608 static MemTxResult
astro_chip_write_with_attrs(void *opaque
, hwaddr addr
,
609 uint64_t val
, unsigned size
,
612 AstroState
*s
= opaque
;
614 trace_astro_chip_write(addr
, size
, val
);
616 switch ((addr
>> 3) << 3) {
617 case 0x0000: /* ID */
619 case 0x0008: /* IOC_CTRL */
621 put_val_in_int64(&s
->ioc_ctrl
, addr
, size
, val
);
623 case 0x0010: /* TOC_CLIENT_ID */
625 case 0x0030: /* HP-UX 10.20 and 11.11 reads it. No idea. */
627 case 0x0300 ... 0x03d8 - 1: /* LMMIO_DIRECT0_BASE... */
628 put_val_in_arrary(s
->ioc_ranges
, 0x300, addr
, size
, val
);
632 case 0x10230: /* HP-UX 11.11 reads it. No idea. */
634 case 0x22108: /* IOC STATUS_CONTROL */
635 put_val_in_int64(&s
->ioc_status_ctrl
, addr
, size
, val
);
637 case 0x20200 ... 0x20240 - 1: /* IOC Rope0_Control ... */
638 put_val_in_arrary(s
->ioc_rope_control
, 0x20200, addr
, size
, val
);
640 case 0x20040: /* IOC Rope config */
641 put_val_in_int64(&s
->ioc_rope_config
, addr
, size
, val
);
644 put_val_in_int64(&s
->tlb_ibase
, addr
, size
, val
);
647 put_val_in_int64(&s
->tlb_imask
, addr
, size
, val
);
650 put_val_in_int64(&s
->tlb_pcom
, addr
, size
, val
);
651 /* TODO: flush iommu */
654 put_val_in_int64(&s
->tlb_tcnfg
, addr
, size
, val
);
657 put_val_in_int64(&s
->tlb_pdir_base
, addr
, size
, val
);
660 * empty placeholders for non-existent elroys, e.g.
661 * func_class, pci config & data
663 #define EMPTY_PORT(x) case x: case x+8: case x+0x40: case x+0x48:
676 /* Controlled by astro_chip_mem_valid above. */
677 trace_astro_chip_write(addr
, size
, val
);
678 g_assert_not_reached();
683 static const MemoryRegionOps astro_chip_ops
= {
684 .read_with_attrs
= astro_chip_read_with_attrs
,
685 .write_with_attrs
= astro_chip_write_with_attrs
,
686 .endianness
= DEVICE_LITTLE_ENDIAN
,
688 .min_access_size
= 4,
689 .max_access_size
= 8,
692 .min_access_size
= 4,
693 .max_access_size
= 8,
697 static const VMStateDescription vmstate_astro
= {
700 .minimum_version_id
= 1,
701 .fields
= (VMStateField
[]) {
702 VMSTATE_UINT64(ioc_ctrl
, AstroState
),
703 VMSTATE_UINT64(ioc_status_ctrl
, AstroState
),
704 VMSTATE_UINT64_ARRAY(ioc_ranges
, AstroState
, (0x03d8 - 0x300) / 8),
705 VMSTATE_UINT64(ioc_rope_config
, AstroState
),
706 VMSTATE_UINT64(ioc_status_control
, AstroState
),
707 VMSTATE_UINT64(ioc_flush_control
, AstroState
),
708 VMSTATE_UINT64_ARRAY(ioc_rope_control
, AstroState
, 8),
709 VMSTATE_UINT64(tlb_ibase
, AstroState
),
710 VMSTATE_UINT64(tlb_imask
, AstroState
),
711 VMSTATE_UINT64(tlb_pcom
, AstroState
),
712 VMSTATE_UINT64(tlb_tcnfg
, AstroState
),
713 VMSTATE_UINT64(tlb_pdir_base
, AstroState
),
714 VMSTATE_END_OF_LIST()
718 static void astro_reset(DeviceState
*dev
)
720 AstroState
*s
= ASTRO_CHIP(dev
);
723 s
->ioc_ctrl
= 0x29cf;
724 s
->ioc_rope_config
= 0xc5f;
725 s
->ioc_flush_control
= 0xb03;
726 s
->ioc_status_control
= 0;
727 memset(&s
->ioc_rope_control
, 0, sizeof(s
->ioc_rope_control
));
730 * The SBA BASE/MASK registers control CPU -> IO routing.
731 * The LBA BASE/MASK registers control IO -> System routing (in Elroy)
733 memset(&s
->ioc_ranges
, 0, sizeof(s
->ioc_ranges
));
734 s
->ioc_ranges
[(0x360 - 0x300) / 8] = LMMIO_DIST_BASE_ADDR
| 0x01; /* LMMIO_DIST_BASE (SBA) */
735 s
->ioc_ranges
[(0x368 - 0x300) / 8] = 0xfc000000; /* LMMIO_DIST_MASK */
736 s
->ioc_ranges
[(0x370 - 0x300) / 8] = 0; /* LMMIO_DIST_ROUTE */
737 s
->ioc_ranges
[(0x390 - 0x300) / 8] = IOS_DIST_BASE_ADDR
| 0x01; /* IOS_DIST_BASE */
738 s
->ioc_ranges
[(0x398 - 0x300) / 8] = 0xffffff0000; /* IOS_DIST_MASK */
739 s
->ioc_ranges
[(0x3a0 - 0x300) / 8] = 0x3400000000000000ULL
; /* IOS_DIST_ROUTE */
740 s
->ioc_ranges
[(0x3c0 - 0x300) / 8] = 0xfffee00000; /* IOS_DIRECT_BASE */
741 s
->ioc_ranges
[(0x3c8 - 0x300) / 8] = 0xffffff0000; /* IOS_DIRECT_MASK */
742 s
->ioc_ranges
[(0x3d0 - 0x300) / 8] = 0x0; /* IOS_DIRECT_ROUTE */
748 s
->tlb_pdir_base
= 0;
750 for (i
= 0; i
< ELROY_NUM
; i
++) {
751 elroy_reset(DEVICE(s
->elroy
[i
]));
755 static void astro_init(Object
*obj
)
759 static void astro_realize(DeviceState
*obj
, Error
**errp
)
761 AstroState
*s
= ASTRO_CHIP(obj
);
762 SysBusDevice
*sbd
= SYS_BUS_DEVICE(obj
);
765 memory_region_init_io(&s
->this_mem
, OBJECT(s
), &astro_chip_ops
,
766 s
, "astro", 0x40000);
767 sysbus_init_mmio(sbd
, &s
->this_mem
);
769 /* Host memory as seen from Elroys PCI side, via the IOMMU. */
770 memory_region_init_iommu(&s
->iommu
, sizeof(s
->iommu
),
771 TYPE_ASTRO_IOMMU_MEMORY_REGION
, OBJECT(s
),
772 "iommu-astro", UINT64_MAX
);
773 address_space_init(&s
->iommu_as
, MEMORY_REGION(&s
->iommu
),
776 /* Create Elroys (PCI host bus chips). */
777 for (i
= 0; i
< ELROY_NUM
; i
++) {
778 static const int elroy_hpa_offsets
[ELROY_NUM
] = {
779 0x30000, 0x32000, 0x38000, 0x3c000 };
780 static const char elroy_rope_nr
[ELROY_NUM
] = {
781 0, 1, 4, 6 }; /* busnum path, e.g. [10:6] */
788 addr_offset
= elroy_hpa_offsets
[i
];
789 rope
= elroy_rope_nr
[i
];
791 elroy
= elroy_init(i
);
793 elroy
->hpa
= ASTRO_HPA
+ addr_offset
;
794 elroy
->pci_bus_num
= i
;
798 * NOTE: we only allow PCI devices on first Elroy for now.
799 * SeaBIOS will not find devices on the other busses.
802 qbus_mark_full(&PCI_HOST_BRIDGE(elroy
)->bus
->qbus
);
805 /* map elroy config addresses into Astro space */
806 memory_region_add_subregion(&s
->this_mem
, addr_offset
,
810 elroy
->mmio_base
[(0x0200 - 0x200) / 8] = 0xf0000001;
811 elroy
->mmio_base
[(0x0208 - 0x200) / 8] = 0xf8000000;
813 elroy
->mmio_base
[(0x0210 - 0x200) / 8] = 0x000000f800000001;
814 elroy
->mmio_base
[(0x0218 - 0x200) / 8] = 0x000000ff80000000;
816 elroy
->mmio_base
[(0x0220 - 0x200) / 8] = 0xf0000001;
817 elroy
->mmio_base
[(0x0228 - 0x200) / 8] = 0xf0000000;
819 elroy
->mmio_base
[(0x0230 - 0x200) / 8] = 0x000000f800000001;
820 elroy
->mmio_base
[(0x0238 - 0x200) / 8] = 0x000000fc00000000;
822 map_size
= IOS_DIST_BASE_SIZE
/ ROPES_PER_IOC
;
823 elroy
->mmio_base
[(0x0240 - 0x200) / 8] = rope
* map_size
| 0x01;
824 elroy
->mmio_base
[(0x0248 - 0x200) / 8] = 0x0000e000;
826 /* map elroys mmio */
827 map_size
= LMMIO_DIST_BASE_SIZE
/ ROPES_PER_IOC
;
828 map_addr
= (uint32_t) (LMMIO_DIST_BASE_ADDR
+ rope
* map_size
);
829 memory_region_init_alias(&elroy
->pci_mmio_alias
, OBJECT(elroy
),
831 &elroy
->pci_mmio
, map_addr
, map_size
);
832 memory_region_add_subregion(get_system_memory(), map_addr
,
833 &elroy
->pci_mmio_alias
);
835 map_size
= IOS_DIST_BASE_SIZE
/ ROPES_PER_IOC
;
836 map_addr
= (uint32_t) (IOS_DIST_BASE_ADDR
+ rope
* map_size
);
837 memory_region_add_subregion(get_system_memory(), map_addr
,
840 /* Host memory as seen from the PCI side, via the IOMMU. */
841 pci_setup_iommu(PCI_HOST_BRIDGE(elroy
)->bus
, &elroy_pcihost_iommu_ops
,
846 static void astro_class_init(ObjectClass
*klass
, void *data
)
848 DeviceClass
*dc
= DEVICE_CLASS(klass
);
850 dc
->reset
= astro_reset
;
851 dc
->vmsd
= &vmstate_astro
;
852 dc
->realize
= astro_realize
;
854 * astro with elroys are hard part of the newer PA2.0 machines and can not
855 * be created without that hardware
857 dc
->user_creatable
= false;
860 static const TypeInfo astro_chip_info
= {
861 .name
= TYPE_ASTRO_CHIP
,
862 .parent
= TYPE_SYS_BUS_DEVICE
,
863 .instance_init
= astro_init
,
864 .instance_size
= sizeof(AstroState
),
865 .class_init
= astro_class_init
,
868 static void astro_iommu_memory_region_class_init(ObjectClass
*klass
,
871 IOMMUMemoryRegionClass
*imrc
= IOMMU_MEMORY_REGION_CLASS(klass
);
873 imrc
->translate
= astro_translate_iommu
;
876 static const TypeInfo astro_iommu_memory_region_info
= {
877 .parent
= TYPE_IOMMU_MEMORY_REGION
,
878 .name
= TYPE_ASTRO_IOMMU_MEMORY_REGION
,
879 .class_init
= astro_iommu_memory_region_class_init
,
883 static void astro_register_types(void)
885 type_register_static(&astro_chip_info
);
886 type_register_static(&astro_iommu_memory_region_info
);
889 type_init(astro_register_types
)