1e029bb00SHelge Deller /* 2e029bb00SHelge Deller * HP-PARISC Astro/Pluto/Ike/REO system bus adapter (SBA) 3e029bb00SHelge Deller * with Elroy PCI bus (LBA) adapter emulation 4e029bb00SHelge Deller * Found in C3000 and similar machines 5e029bb00SHelge Deller * 6e029bb00SHelge Deller * (C) 2023 by Helge Deller <deller@gmx.de> 7e029bb00SHelge Deller * 8e029bb00SHelge Deller * This work is licensed under the GNU GPL license version 2 or later. 9e029bb00SHelge Deller * 10e029bb00SHelge Deller * Chip documentation is available at: 11e029bb00SHelge Deller * https://parisc.wiki.kernel.org/index.php/Technical_Documentation 12e029bb00SHelge Deller * 13e029bb00SHelge Deller * TODO: 14e029bb00SHelge Deller * - All user-added devices are currently attached to the first 15e029bb00SHelge Deller * Elroy (PCI bus) only for now. To fix this additional work in 16e029bb00SHelge Deller * SeaBIOS and this driver is needed. See "user_creatable" flag below. 17e029bb00SHelge Deller * - GMMIO (Greater than 4 GB MMIO) register 18e029bb00SHelge Deller */ 19e029bb00SHelge Deller 20e029bb00SHelge Deller #define TYPE_ASTRO_IOMMU_MEMORY_REGION "astro-iommu-memory-region" 21e029bb00SHelge Deller 22fd842b2fSHelge Deller #define F_EXTEND(addr) ((addr) | MAKE_64BIT_MASK(32, 32)) 23fd842b2fSHelge Deller 24e029bb00SHelge Deller #include "qemu/osdep.h" 25e029bb00SHelge Deller #include "qemu/module.h" 26e029bb00SHelge Deller #include "qemu/units.h" 27e029bb00SHelge Deller #include "qapi/error.h" 28e029bb00SHelge Deller #include "hw/irq.h" 29e029bb00SHelge Deller #include "hw/pci/pci_device.h" 30e029bb00SHelge Deller #include "hw/pci/pci_bus.h" 31e029bb00SHelge Deller #include "hw/qdev-properties.h" 32e029bb00SHelge Deller #include "hw/pci-host/astro.h" 33e029bb00SHelge Deller #include "hw/hppa/hppa_hardware.h" 34e029bb00SHelge Deller #include "migration/vmstate.h" 358066102dSHelge Deller #include "target/hppa/cpu.h" 36e029bb00SHelge Deller #include "trace.h" 37e029bb00SHelge Deller #include "qom/object.h" 38e029bb00SHelge Deller 39e029bb00SHelge Deller /* 40e029bb00SHelge Deller * Helper functions 41e029bb00SHelge Deller */ 42e029bb00SHelge Deller 43e029bb00SHelge Deller static uint64_t mask_32bit_val(hwaddr addr, unsigned size, uint64_t val) 44e029bb00SHelge Deller { 45e029bb00SHelge Deller if (size == 8) { 46e029bb00SHelge Deller return val; 47e029bb00SHelge Deller } 48e029bb00SHelge Deller if (addr & 4) { 49e029bb00SHelge Deller val >>= 32; 50e029bb00SHelge Deller } else { 51e029bb00SHelge Deller val = (uint32_t) val; 52e029bb00SHelge Deller } 53e029bb00SHelge Deller return val; 54e029bb00SHelge Deller } 55e029bb00SHelge Deller 56e029bb00SHelge Deller static void put_val_in_int64(uint64_t *p, hwaddr addr, unsigned size, 57e029bb00SHelge Deller uint64_t val) 58e029bb00SHelge Deller { 59e029bb00SHelge Deller if (size == 8) { 60e029bb00SHelge Deller *p = val; 61e029bb00SHelge Deller } else if (size == 4) { 62e029bb00SHelge Deller if (addr & 4) { 63e029bb00SHelge Deller *p = ((*p << 32) >> 32) | (val << 32); 64e029bb00SHelge Deller } else { 65e029bb00SHelge Deller *p = ((*p >> 32) << 32) | (uint32_t) val; 66e029bb00SHelge Deller } 67e029bb00SHelge Deller } 68e029bb00SHelge Deller } 69e029bb00SHelge Deller 70e029bb00SHelge Deller static void put_val_in_arrary(uint64_t *array, hwaddr start_addr, 71e029bb00SHelge Deller hwaddr addr, unsigned size, uint64_t val) 72e029bb00SHelge Deller { 73e029bb00SHelge Deller int index; 74e029bb00SHelge Deller 75e029bb00SHelge Deller index = (addr - start_addr) / 8; 76e029bb00SHelge Deller put_val_in_int64(&array[index], addr, size, val); 77e029bb00SHelge Deller } 78e029bb00SHelge Deller 79e029bb00SHelge Deller 80e029bb00SHelge Deller /* 81e029bb00SHelge Deller * The Elroy PCI host bridge. We have at least 4 of those under Astro. 82e029bb00SHelge Deller */ 83e029bb00SHelge Deller 84e029bb00SHelge Deller static MemTxResult elroy_chip_read_with_attrs(void *opaque, hwaddr addr, 85e029bb00SHelge Deller uint64_t *data, unsigned size, 86e029bb00SHelge Deller MemTxAttrs attrs) 87e029bb00SHelge Deller { 88e029bb00SHelge Deller MemTxResult ret = MEMTX_OK; 89e029bb00SHelge Deller ElroyState *s = opaque; 90e029bb00SHelge Deller uint64_t val = -1; 91e029bb00SHelge Deller int index; 92e029bb00SHelge Deller 93e029bb00SHelge Deller switch ((addr >> 3) << 3) { 94e029bb00SHelge Deller case 0x0008: 95e029bb00SHelge Deller val = 0x6000005; /* func_class */ 96e029bb00SHelge Deller break; 97e029bb00SHelge Deller case 0x0058: 98e029bb00SHelge Deller /* 99e029bb00SHelge Deller * Scratch register, but firmware initializes it with the 100e029bb00SHelge Deller * PCI BUS number and Linux/HP-UX uses it then. 101e029bb00SHelge Deller */ 102e029bb00SHelge Deller val = s->pci_bus_num; 103e029bb00SHelge Deller /* Upper byte holds the end of this bus number */ 104e029bb00SHelge Deller val |= s->pci_bus_num << 8; 105e029bb00SHelge Deller break; 106e029bb00SHelge Deller case 0x0080: 107e029bb00SHelge Deller val = s->arb_mask; /* set ARB mask */ 108e029bb00SHelge Deller break; 109e029bb00SHelge Deller case 0x0108: 110e029bb00SHelge Deller val = s->status_control; 111e029bb00SHelge Deller break; 112e029bb00SHelge Deller case 0x200 ... 0x250 - 1: /* LMMIO, GMMIO, WLMMIO, WGMMIO, ... */ 113e029bb00SHelge Deller index = (addr - 0x200) / 8; 114e029bb00SHelge Deller val = s->mmio_base[index]; 115e029bb00SHelge Deller break; 116e029bb00SHelge Deller case 0x0680: 117e029bb00SHelge Deller val = s->error_config; 118e029bb00SHelge Deller break; 119e029bb00SHelge Deller case 0x0688: 120e029bb00SHelge Deller val = 0; /* ERROR_STATUS */ 121e029bb00SHelge Deller break; 122e029bb00SHelge Deller case 0x0800: /* IOSAPIC_REG_SELECT */ 123e029bb00SHelge Deller val = s->iosapic_reg_select; 124e029bb00SHelge Deller break; 125e029bb00SHelge Deller case 0x0808: 126e029bb00SHelge Deller val = UINT64_MAX; /* XXX: tbc. */ 127e029bb00SHelge Deller g_assert_not_reached(); 128e029bb00SHelge Deller break; 129e029bb00SHelge Deller case 0x0810: /* IOSAPIC_REG_WINDOW */ 130e029bb00SHelge Deller switch (s->iosapic_reg_select) { 131e029bb00SHelge Deller case 0x01: /* IOSAPIC_REG_VERSION */ 132e029bb00SHelge Deller val = (32 << 16) | 1; /* upper 16bit holds max entries */ 133e029bb00SHelge Deller break; 134e029bb00SHelge Deller default: 135e029bb00SHelge Deller if (s->iosapic_reg_select < ARRAY_SIZE(s->iosapic_reg)) { 136e029bb00SHelge Deller val = s->iosapic_reg[s->iosapic_reg_select]; 137e029bb00SHelge Deller } else { 138e029bb00SHelge Deller trace_iosapic_reg_read(s->iosapic_reg_select, size, val); 139e029bb00SHelge Deller g_assert_not_reached(); 140e029bb00SHelge Deller } 141e029bb00SHelge Deller } 142e029bb00SHelge Deller trace_iosapic_reg_read(s->iosapic_reg_select, size, val); 143e029bb00SHelge Deller break; 144e029bb00SHelge Deller default: 145e029bb00SHelge Deller trace_elroy_read(addr, size, val); 146e029bb00SHelge Deller g_assert_not_reached(); 147e029bb00SHelge Deller } 148e029bb00SHelge Deller trace_elroy_read(addr, size, val); 149e029bb00SHelge Deller 150e029bb00SHelge Deller /* for 32-bit accesses mask return value */ 151e029bb00SHelge Deller val = mask_32bit_val(addr, size, val); 152e029bb00SHelge Deller 153e029bb00SHelge Deller trace_astro_chip_read(addr, size, val); 154e029bb00SHelge Deller *data = val; 155e029bb00SHelge Deller return ret; 156e029bb00SHelge Deller } 157e029bb00SHelge Deller 158e029bb00SHelge Deller 159e029bb00SHelge Deller static MemTxResult elroy_chip_write_with_attrs(void *opaque, hwaddr addr, 160e029bb00SHelge Deller uint64_t val, unsigned size, 161e029bb00SHelge Deller MemTxAttrs attrs) 162e029bb00SHelge Deller { 163e029bb00SHelge Deller ElroyState *s = opaque; 164e029bb00SHelge Deller int i; 165e029bb00SHelge Deller 166e029bb00SHelge Deller trace_elroy_write(addr, size, val); 167e029bb00SHelge Deller 168e029bb00SHelge Deller switch ((addr >> 3) << 3) { 169*ad701980SHelge Deller case 0x000: /* PCI_ID & PCI_COMMAND_STATUS_REG */ 170*ad701980SHelge Deller break; 171e029bb00SHelge Deller case 0x080: 172e029bb00SHelge Deller put_val_in_int64(&s->arb_mask, addr, size, val); 173e029bb00SHelge Deller break; 174e029bb00SHelge Deller case 0x0108: 175e029bb00SHelge Deller put_val_in_int64(&s->status_control, addr, size, val); 176e029bb00SHelge Deller break; 177e029bb00SHelge Deller case 0x200 ... 0x250 - 1: /* LMMIO, GMMIO, WLMMIO, WGMMIO, ... */ 178e029bb00SHelge Deller put_val_in_arrary(s->mmio_base, 0x200, addr, size, val); 179e029bb00SHelge Deller break; 180*ad701980SHelge Deller case 0x300: /* ibase */ 181*ad701980SHelge Deller case 0x308: /* imask */ 182*ad701980SHelge Deller break; 183e029bb00SHelge Deller case 0x0680: 184e029bb00SHelge Deller put_val_in_int64(&s->error_config, addr, size, val); 185e029bb00SHelge Deller break; 186e029bb00SHelge Deller case 0x0800: /* IOSAPIC_REG_SELECT */ 187e029bb00SHelge Deller s->iosapic_reg_select = val; 188e029bb00SHelge Deller break; 189e029bb00SHelge Deller case 0x0810: /* IOSAPIC_REG_WINDOW */ 190e029bb00SHelge Deller trace_iosapic_reg_write(s->iosapic_reg_select, size, val); 191e029bb00SHelge Deller if (s->iosapic_reg_select < ARRAY_SIZE(s->iosapic_reg)) { 192e029bb00SHelge Deller s->iosapic_reg[s->iosapic_reg_select] = val; 193e029bb00SHelge Deller } else { 194e029bb00SHelge Deller g_assert_not_reached(); 195e029bb00SHelge Deller } 196e029bb00SHelge Deller break; 197e029bb00SHelge Deller case 0x0840: /* IOSAPIC_REG_EOI */ 198e029bb00SHelge Deller val = le64_to_cpu(val); 199e029bb00SHelge Deller val &= 63; 200e029bb00SHelge Deller for (i = 0; i < ELROY_IRQS; i++) { 201e029bb00SHelge Deller if ((s->iosapic_reg[0x10 + 2 * i] & 63) == val) { 202e029bb00SHelge Deller s->ilr &= ~(1ull << i); 203e029bb00SHelge Deller } 204e029bb00SHelge Deller } 205e029bb00SHelge Deller break; 206e029bb00SHelge Deller default: 207e029bb00SHelge Deller g_assert_not_reached(); 208e029bb00SHelge Deller } 209e029bb00SHelge Deller return MEMTX_OK; 210e029bb00SHelge Deller } 211e029bb00SHelge Deller 212e029bb00SHelge Deller static const MemoryRegionOps elroy_chip_ops = { 213e029bb00SHelge Deller .read_with_attrs = elroy_chip_read_with_attrs, 214e029bb00SHelge Deller .write_with_attrs = elroy_chip_write_with_attrs, 215e029bb00SHelge Deller .endianness = DEVICE_LITTLE_ENDIAN, 216e029bb00SHelge Deller .valid = { 217e029bb00SHelge Deller .min_access_size = 4, 218e029bb00SHelge Deller .max_access_size = 8, 219e029bb00SHelge Deller }, 220e029bb00SHelge Deller .impl = { 221e029bb00SHelge Deller .min_access_size = 4, 222e029bb00SHelge Deller .max_access_size = 8, 223e029bb00SHelge Deller }, 224e029bb00SHelge Deller }; 225e029bb00SHelge Deller 226e029bb00SHelge Deller 227e029bb00SHelge Deller /* Unlike pci_config_data_le_ops, no check of high bit set in config_reg. */ 228e029bb00SHelge Deller 229e029bb00SHelge Deller static uint64_t elroy_config_data_read(void *opaque, hwaddr addr, unsigned len) 230e029bb00SHelge Deller { 231e029bb00SHelge Deller uint64_t val; 232e029bb00SHelge Deller 233e029bb00SHelge Deller PCIHostState *s = opaque; 234e029bb00SHelge Deller val = pci_data_read(s->bus, s->config_reg | (addr & 3), len); 235e029bb00SHelge Deller trace_elroy_pci_config_data_read(s->config_reg | (addr & 3), len, val); 236e029bb00SHelge Deller return val; 237e029bb00SHelge Deller } 238e029bb00SHelge Deller 239e029bb00SHelge Deller static void elroy_config_data_write(void *opaque, hwaddr addr, 240e029bb00SHelge Deller uint64_t val, unsigned len) 241e029bb00SHelge Deller { 242e029bb00SHelge Deller PCIHostState *s = opaque; 243e029bb00SHelge Deller pci_data_write(s->bus, s->config_reg | (addr & 3), val, len); 244e029bb00SHelge Deller trace_elroy_pci_config_data_write(s->config_reg | (addr & 3), len, val); 245e029bb00SHelge Deller } 246e029bb00SHelge Deller 247e029bb00SHelge Deller static const MemoryRegionOps elroy_config_data_ops = { 248e029bb00SHelge Deller .read = elroy_config_data_read, 249e029bb00SHelge Deller .write = elroy_config_data_write, 250e029bb00SHelge Deller .endianness = DEVICE_LITTLE_ENDIAN, 251e029bb00SHelge Deller }; 252e029bb00SHelge Deller 253e029bb00SHelge Deller static uint64_t elroy_config_addr_read(void *opaque, hwaddr addr, unsigned len) 254e029bb00SHelge Deller { 255e029bb00SHelge Deller ElroyState *s = opaque; 256e029bb00SHelge Deller return s->config_reg_elroy; 257e029bb00SHelge Deller } 258e029bb00SHelge Deller 259e029bb00SHelge Deller static void elroy_config_addr_write(void *opaque, hwaddr addr, 260e029bb00SHelge Deller uint64_t val, unsigned len) 261e029bb00SHelge Deller { 262e029bb00SHelge Deller PCIHostState *s = opaque; 263e029bb00SHelge Deller ElroyState *es = opaque; 264e029bb00SHelge Deller es->config_reg_elroy = val; /* keep a copy of original value */ 265e029bb00SHelge Deller s->config_reg = val; 266e029bb00SHelge Deller } 267e029bb00SHelge Deller 268e029bb00SHelge Deller static const MemoryRegionOps elroy_config_addr_ops = { 269e029bb00SHelge Deller .read = elroy_config_addr_read, 270e029bb00SHelge Deller .write = elroy_config_addr_write, 271e029bb00SHelge Deller .valid.min_access_size = 4, 272e029bb00SHelge Deller .valid.max_access_size = 8, 273e029bb00SHelge Deller .endianness = DEVICE_LITTLE_ENDIAN, 274e029bb00SHelge Deller }; 275e029bb00SHelge Deller 276e029bb00SHelge Deller 277e029bb00SHelge Deller /* Handle PCI-to-system address translation. */ 278e029bb00SHelge Deller static IOMMUTLBEntry astro_translate_iommu(IOMMUMemoryRegion *iommu, 279e029bb00SHelge Deller hwaddr addr, 280e029bb00SHelge Deller IOMMUAccessFlags flag, 281e029bb00SHelge Deller int iommu_idx) 282e029bb00SHelge Deller { 283e029bb00SHelge Deller AstroState *s = container_of(iommu, AstroState, iommu); 2848066102dSHelge Deller hwaddr pdir_ptr, index, ibase; 285e029bb00SHelge Deller hwaddr addr_mask = 0xfff; /* 4k translation */ 286e029bb00SHelge Deller uint64_t entry; 287e029bb00SHelge Deller 288e029bb00SHelge Deller #define IOVP_SHIFT 12 /* equals PAGE_SHIFT */ 289e029bb00SHelge Deller #define PDIR_INDEX(iovp) ((iovp) >> IOVP_SHIFT) 290e029bb00SHelge Deller #define SBA_PDIR_VALID_BIT 0x8000000000000000ULL 291e029bb00SHelge Deller 2928066102dSHelge Deller addr &= ~addr_mask; 2938066102dSHelge Deller 2948066102dSHelge Deller /* 2958066102dSHelge Deller * Default translation: "32-bit PCI Addressing on 40-bit Runway". 2968066102dSHelge Deller * For addresses in the 32-bit memory address range ... and then 2978066102dSHelge Deller * language which not-coincidentally matches the PSW.W=0 mapping. 2988066102dSHelge Deller */ 2998066102dSHelge Deller if (addr <= UINT32_MAX) { 3008066102dSHelge Deller entry = hppa_abs_to_phys_pa2_w0(addr); 3018066102dSHelge Deller } else { 3028066102dSHelge Deller entry = addr; 3038066102dSHelge Deller } 3048066102dSHelge Deller 305e029bb00SHelge Deller /* "range enable" flag cleared? */ 306e029bb00SHelge Deller if ((s->tlb_ibase & 1) == 0) { 3078066102dSHelge Deller goto skip; 308e029bb00SHelge Deller } 309e029bb00SHelge Deller 310e029bb00SHelge Deller ibase = s->tlb_ibase & ~1ULL; 3118066102dSHelge Deller if ((addr & s->tlb_imask) != ibase) { 312e029bb00SHelge Deller /* do not translate this one! */ 3138066102dSHelge Deller goto skip; 314e029bb00SHelge Deller } 3158066102dSHelge Deller 3168066102dSHelge Deller index = PDIR_INDEX(addr); 317e029bb00SHelge Deller pdir_ptr = s->tlb_pdir_base + index * sizeof(entry); 318e029bb00SHelge Deller entry = ldq_le_phys(&address_space_memory, pdir_ptr); 3198066102dSHelge Deller 320e029bb00SHelge Deller if (!(entry & SBA_PDIR_VALID_BIT)) { /* I/O PDIR entry valid ? */ 3218066102dSHelge Deller /* failure */ 3228066102dSHelge Deller return (IOMMUTLBEntry) { .perm = IOMMU_NONE }; 323e029bb00SHelge Deller } 3248066102dSHelge Deller 325e029bb00SHelge Deller entry &= ~SBA_PDIR_VALID_BIT; 326e029bb00SHelge Deller entry >>= IOVP_SHIFT; 327e029bb00SHelge Deller entry <<= 12; 328e029bb00SHelge Deller 3298066102dSHelge Deller skip: 3308066102dSHelge Deller return (IOMMUTLBEntry) { 3318066102dSHelge Deller .target_as = &address_space_memory, 3328066102dSHelge Deller .iova = addr, 3338066102dSHelge Deller .translated_addr = entry, 3348066102dSHelge Deller .addr_mask = addr_mask, 3358066102dSHelge Deller .perm = IOMMU_RW, 3368066102dSHelge Deller }; 337e029bb00SHelge Deller } 338e029bb00SHelge Deller 339e029bb00SHelge Deller static AddressSpace *elroy_pcihost_set_iommu(PCIBus *bus, void *opaque, 340e029bb00SHelge Deller int devfn) 341e029bb00SHelge Deller { 342e029bb00SHelge Deller ElroyState *s = opaque; 343e029bb00SHelge Deller return &s->astro->iommu_as; 344e029bb00SHelge Deller } 345e029bb00SHelge Deller 346ba7d12ebSYi Liu static const PCIIOMMUOps elroy_pcihost_iommu_ops = { 347ba7d12ebSYi Liu .get_address_space = elroy_pcihost_set_iommu, 348ba7d12ebSYi Liu }; 349ba7d12ebSYi Liu 350e029bb00SHelge Deller /* 351e029bb00SHelge Deller * Encoding in IOSAPIC: 352e029bb00SHelge Deller * base_addr == 0xfffa0000, we want to get 0xa0ff0000. 353e029bb00SHelge Deller * eid 0x0ff00000 -> 0x00ff0000 354e029bb00SHelge Deller * id 0x000ff000 -> 0xff000000 355e029bb00SHelge Deller */ 356e029bb00SHelge Deller #define SWIZZLE_HPA(a) \ 357e029bb00SHelge Deller ((((a) & 0x0ff00000) >> 4) | (((a) & 0x000ff000) << 12)) 358e029bb00SHelge Deller #define UNSWIZZLE_HPA(a) \ 359e029bb00SHelge Deller (((((a) << 4) & 0x0ff00000) | (((a) >> 12) & 0x000ff000) | 0xf0000000)) 360e029bb00SHelge Deller 361e029bb00SHelge Deller /* bits in the "low" I/O Sapic IRdT entry */ 362e029bb00SHelge Deller #define IOSAPIC_IRDT_DISABLE 0x10000 /* if bit is set, mask this irq */ 363e029bb00SHelge Deller #define IOSAPIC_IRDT_PO_LOW 0x02000 364e029bb00SHelge Deller #define IOSAPIC_IRDT_LEVEL_TRIG 0x08000 365e029bb00SHelge Deller #define IOSAPIC_IRDT_MODE_LPRI 0x00100 366e029bb00SHelge Deller 367e029bb00SHelge Deller #define CPU_IRQ_OFFSET 2 368e029bb00SHelge Deller 369e029bb00SHelge Deller static void elroy_set_irq(void *opaque, int irq, int level) 370e029bb00SHelge Deller { 371e029bb00SHelge Deller ElroyState *s = opaque; 372e029bb00SHelge Deller uint32_t bit; 373e029bb00SHelge Deller uint32_t old_ilr = s->ilr; 374e029bb00SHelge Deller hwaddr cpu_hpa; 375e029bb00SHelge Deller uint32_t val; 376e029bb00SHelge Deller 377e029bb00SHelge Deller val = s->iosapic_reg[0x10 + 2 * irq]; 378e029bb00SHelge Deller cpu_hpa = s->iosapic_reg[0x11 + 2 * irq]; 379e029bb00SHelge Deller /* low nibble of val has value to write into CPU irq reg */ 380e029bb00SHelge Deller bit = 1u << (val & (ELROY_IRQS - 1)); 381e029bb00SHelge Deller cpu_hpa = UNSWIZZLE_HPA(cpu_hpa); 382e029bb00SHelge Deller 383e029bb00SHelge Deller if (level && (!(val & IOSAPIC_IRDT_DISABLE)) && cpu_hpa) { 384e029bb00SHelge Deller uint32_t ena = bit & ~old_ilr; 385e029bb00SHelge Deller s->ilr = old_ilr | bit; 386e029bb00SHelge Deller if (ena != 0) { 38764bf0967SHelge Deller stl_be_phys(&address_space_memory, F_EXTEND(cpu_hpa), val & 63); 388e029bb00SHelge Deller } 389e029bb00SHelge Deller } else { 390e029bb00SHelge Deller s->ilr = old_ilr & ~bit; 391e029bb00SHelge Deller } 392e029bb00SHelge Deller } 393e029bb00SHelge Deller 394e029bb00SHelge Deller static int elroy_pci_map_irq(PCIDevice *d, int irq_num) 395e029bb00SHelge Deller { 396e029bb00SHelge Deller int slot = PCI_SLOT(d->devfn); 397e029bb00SHelge Deller 398e029bb00SHelge Deller assert(irq_num >= 0 && irq_num < ELROY_IRQS); 399e029bb00SHelge Deller return slot & (ELROY_IRQS - 1); 400e029bb00SHelge Deller } 401e029bb00SHelge Deller 402e029bb00SHelge Deller static void elroy_reset(DeviceState *dev) 403e029bb00SHelge Deller { 404e029bb00SHelge Deller ElroyState *s = ELROY_PCI_HOST_BRIDGE(dev); 405e029bb00SHelge Deller int irq; 406e029bb00SHelge Deller 407e029bb00SHelge Deller /* 408e029bb00SHelge Deller * Make sure to disable interrupts at reboot, otherwise the Linux kernel 409e029bb00SHelge Deller * serial8250_config_port() in drivers/tty/serial/8250/8250_port.c 410e029bb00SHelge Deller * will hang during autoconfig(). 411e029bb00SHelge Deller */ 412e029bb00SHelge Deller s->ilr = 0; 413e029bb00SHelge Deller for (irq = 0; irq < ELROY_IRQS; irq++) { 414e029bb00SHelge Deller s->iosapic_reg[0x10 + 2 * irq] = IOSAPIC_IRDT_PO_LOW | 415e029bb00SHelge Deller IOSAPIC_IRDT_LEVEL_TRIG | (irq + CPU_IRQ_OFFSET) | 416e029bb00SHelge Deller IOSAPIC_IRDT_DISABLE; 417e029bb00SHelge Deller s->iosapic_reg[0x11 + 2 * irq] = SWIZZLE_HPA(CPU_HPA); 418e029bb00SHelge Deller } 419e029bb00SHelge Deller } 420e029bb00SHelge Deller 421e029bb00SHelge Deller static void elroy_pcihost_init(Object *obj) 422e029bb00SHelge Deller { 423e029bb00SHelge Deller ElroyState *s = ELROY_PCI_HOST_BRIDGE(obj); 424e029bb00SHelge Deller PCIHostState *phb = PCI_HOST_BRIDGE(obj); 425e029bb00SHelge Deller SysBusDevice *sbd = SYS_BUS_DEVICE(obj); 426e029bb00SHelge Deller 427e029bb00SHelge Deller /* Elroy config access from CPU. */ 428e029bb00SHelge Deller memory_region_init_io(&s->this_mem, OBJECT(s), &elroy_chip_ops, 429e029bb00SHelge Deller s, "elroy", 0x2000); 430e029bb00SHelge Deller 431e029bb00SHelge Deller /* Elroy PCI config. */ 432e029bb00SHelge Deller memory_region_init_io(&phb->conf_mem, OBJECT(phb), 433e029bb00SHelge Deller &elroy_config_addr_ops, DEVICE(s), 434e029bb00SHelge Deller "pci-conf-idx", 8); 435e029bb00SHelge Deller memory_region_init_io(&phb->data_mem, OBJECT(phb), 436e029bb00SHelge Deller &elroy_config_data_ops, DEVICE(s), 437e029bb00SHelge Deller "pci-conf-data", 8); 438e029bb00SHelge Deller memory_region_add_subregion(&s->this_mem, 0x40, 439e029bb00SHelge Deller &phb->conf_mem); 440e029bb00SHelge Deller memory_region_add_subregion(&s->this_mem, 0x48, 441e029bb00SHelge Deller &phb->data_mem); 442e029bb00SHelge Deller 443e029bb00SHelge Deller /* Elroy PCI bus memory. */ 444e029bb00SHelge Deller memory_region_init(&s->pci_mmio, OBJECT(s), "pci-mmio", UINT64_MAX); 445e029bb00SHelge Deller memory_region_init_io(&s->pci_io, OBJECT(s), &unassigned_io_ops, obj, 446e029bb00SHelge Deller "pci-isa-mmio", 447e029bb00SHelge Deller ((uint32_t) IOS_DIST_BASE_SIZE) / ROPES_PER_IOC); 448e029bb00SHelge Deller 449e029bb00SHelge Deller phb->bus = pci_register_root_bus(DEVICE(s), "pci", 450e029bb00SHelge Deller elroy_set_irq, elroy_pci_map_irq, s, 451e029bb00SHelge Deller &s->pci_mmio, &s->pci_io, 452e029bb00SHelge Deller PCI_DEVFN(0, 0), ELROY_IRQS, TYPE_PCI_BUS); 453e029bb00SHelge Deller 454e029bb00SHelge Deller sysbus_init_mmio(sbd, &s->this_mem); 455e029bb00SHelge Deller 456e029bb00SHelge Deller qdev_init_gpio_in(DEVICE(obj), elroy_set_irq, ELROY_IRQS); 457e029bb00SHelge Deller } 458e029bb00SHelge Deller 459e029bb00SHelge Deller static Property elroy_pcihost_properties[] = { 460e029bb00SHelge Deller DEFINE_PROP_END_OF_LIST(), 461e029bb00SHelge Deller }; 462e029bb00SHelge Deller 463e029bb00SHelge Deller static const VMStateDescription vmstate_elroy = { 464e029bb00SHelge Deller .name = "Elroy", 465e029bb00SHelge Deller .version_id = 1, 466e029bb00SHelge Deller .minimum_version_id = 1, 467e029bb00SHelge Deller .fields = (VMStateField[]) { 468e029bb00SHelge Deller VMSTATE_UINT64(hpa, ElroyState), 469e029bb00SHelge Deller VMSTATE_UINT32(pci_bus_num, ElroyState), 470e029bb00SHelge Deller VMSTATE_UINT64(config_address, ElroyState), 471e029bb00SHelge Deller VMSTATE_UINT64(config_reg_elroy, ElroyState), 472e029bb00SHelge Deller VMSTATE_UINT64(status_control, ElroyState), 473e029bb00SHelge Deller VMSTATE_UINT64(arb_mask, ElroyState), 474e029bb00SHelge Deller VMSTATE_UINT64_ARRAY(mmio_base, ElroyState, (0x0250 - 0x200) / 8), 475e029bb00SHelge Deller VMSTATE_UINT64(error_config, ElroyState), 476e029bb00SHelge Deller VMSTATE_UINT32(iosapic_reg_select, ElroyState), 477e029bb00SHelge Deller VMSTATE_UINT64_ARRAY(iosapic_reg, ElroyState, 0x20), 478e029bb00SHelge Deller VMSTATE_UINT32(ilr, ElroyState), 479e029bb00SHelge Deller VMSTATE_END_OF_LIST() 480e029bb00SHelge Deller } 481e029bb00SHelge Deller }; 482e029bb00SHelge Deller 483e029bb00SHelge Deller static void elroy_pcihost_class_init(ObjectClass *klass, void *data) 484e029bb00SHelge Deller { 485e029bb00SHelge Deller DeviceClass *dc = DEVICE_CLASS(klass); 486e029bb00SHelge Deller 487e029bb00SHelge Deller dc->reset = elroy_reset; 488e029bb00SHelge Deller device_class_set_props(dc, elroy_pcihost_properties); 489e029bb00SHelge Deller dc->vmsd = &vmstate_elroy; 490e029bb00SHelge Deller dc->user_creatable = false; 491e029bb00SHelge Deller } 492e029bb00SHelge Deller 493e029bb00SHelge Deller static const TypeInfo elroy_pcihost_info = { 494e029bb00SHelge Deller .name = TYPE_ELROY_PCI_HOST_BRIDGE, 495e029bb00SHelge Deller .parent = TYPE_PCI_HOST_BRIDGE, 496e029bb00SHelge Deller .instance_init = elroy_pcihost_init, 497e029bb00SHelge Deller .instance_size = sizeof(ElroyState), 498e029bb00SHelge Deller .class_init = elroy_pcihost_class_init, 499e029bb00SHelge Deller }; 500e029bb00SHelge Deller 501e029bb00SHelge Deller static void elroy_register_types(void) 502e029bb00SHelge Deller { 503e029bb00SHelge Deller type_register_static(&elroy_pcihost_info); 504e029bb00SHelge Deller } 505e029bb00SHelge Deller 506e029bb00SHelge Deller type_init(elroy_register_types) 507e029bb00SHelge Deller 508e029bb00SHelge Deller 509e029bb00SHelge Deller static ElroyState *elroy_init(int num) 510e029bb00SHelge Deller { 511e029bb00SHelge Deller DeviceState *dev; 512e029bb00SHelge Deller 513e029bb00SHelge Deller dev = qdev_new(TYPE_ELROY_PCI_HOST_BRIDGE); 514e029bb00SHelge Deller dev->id = g_strdup_printf("elroy%d", num); 515e029bb00SHelge Deller sysbus_realize_and_unref(SYS_BUS_DEVICE(dev), &error_fatal); 516e029bb00SHelge Deller 517e029bb00SHelge Deller return ELROY_PCI_HOST_BRIDGE(dev); 518e029bb00SHelge Deller } 519e029bb00SHelge Deller 520e029bb00SHelge Deller /* 521e029bb00SHelge Deller * Astro Runway chip. 522e029bb00SHelge Deller */ 523e029bb00SHelge Deller 524e029bb00SHelge Deller static MemTxResult astro_chip_read_with_attrs(void *opaque, hwaddr addr, 525e029bb00SHelge Deller uint64_t *data, unsigned size, 526e029bb00SHelge Deller MemTxAttrs attrs) 527e029bb00SHelge Deller { 528e029bb00SHelge Deller AstroState *s = opaque; 529e029bb00SHelge Deller MemTxResult ret = MEMTX_OK; 530e029bb00SHelge Deller uint64_t val = -1; 531e029bb00SHelge Deller int index; 532e029bb00SHelge Deller 533e029bb00SHelge Deller switch ((addr >> 3) << 3) { 534e029bb00SHelge Deller /* R2I registers */ 535e029bb00SHelge Deller case 0x0000: /* ID */ 536e029bb00SHelge Deller val = (0x01 << 3) | 0x01ULL; 537e029bb00SHelge Deller break; 538e029bb00SHelge Deller case 0x0008: /* IOC_CTRL */ 539e029bb00SHelge Deller val = s->ioc_ctrl; 540e029bb00SHelge Deller break; 541e029bb00SHelge Deller case 0x0010: /* TOC_CLIENT_ID */ 542e029bb00SHelge Deller break; 543e029bb00SHelge Deller case 0x0030: /* HP-UX 10.20 and 11.11 reads it. No idea. */ 544e029bb00SHelge Deller val = -1; 545e029bb00SHelge Deller break; 546*ad701980SHelge Deller case 0x0078: /* NetBSD reads 0x78 ? */ 547*ad701980SHelge Deller val = -1; 548*ad701980SHelge Deller break; 549e029bb00SHelge Deller case 0x0300 ... 0x03d8: /* LMMIO_DIRECT0_BASE... */ 550e029bb00SHelge Deller index = (addr - 0x300) / 8; 551e029bb00SHelge Deller val = s->ioc_ranges[index]; 552e029bb00SHelge Deller break; 553e029bb00SHelge Deller case 0x10200: 554e029bb00SHelge Deller val = 0; 555e029bb00SHelge Deller break; 556e029bb00SHelge Deller case 0x10220: 557e029bb00SHelge Deller case 0x10230: /* HP-UX 11.11 reads it. No idea. */ 558e029bb00SHelge Deller val = -1; 559e029bb00SHelge Deller break; 560e029bb00SHelge Deller case 0x22108: /* IOC STATUS_CONTROL */ 561e029bb00SHelge Deller val = s->ioc_status_ctrl; 562e029bb00SHelge Deller break; 563e029bb00SHelge Deller case 0x20200 ... 0x20240 - 1: /* IOC Rope0_Control ... */ 564e029bb00SHelge Deller index = (addr - 0x20200) / 8; 565e029bb00SHelge Deller val = s->ioc_rope_control[index]; 566e029bb00SHelge Deller break; 567e029bb00SHelge Deller case 0x20040: /* IOC Rope config */ 568e029bb00SHelge Deller val = s->ioc_rope_config; 569e029bb00SHelge Deller break; 570e029bb00SHelge Deller case 0x20050: /* IOC Rope debug */ 571e029bb00SHelge Deller val = 0; 572e029bb00SHelge Deller break; 573e029bb00SHelge Deller case 0x20108: /* IOC STATUS_CONTROL */ 574e029bb00SHelge Deller val = s->ioc_status_control; 575e029bb00SHelge Deller break; 576e029bb00SHelge Deller case 0x20310: /* IOC_PCOM */ 577e029bb00SHelge Deller val = s->tlb_pcom; 578e029bb00SHelge Deller /* TODO: flush iommu */ 579e029bb00SHelge Deller break; 580e029bb00SHelge Deller case 0x20400: 581e029bb00SHelge Deller val = s->ioc_flush_control; 582e029bb00SHelge Deller break; 583e029bb00SHelge Deller /* empty placeholders for non-existent elroys */ 584e029bb00SHelge Deller #define EMPTY_PORT(x) case x: case x+8: val = 0; break; \ 585e029bb00SHelge Deller case x+40: case x+48: val = UINT64_MAX; break; 586e029bb00SHelge Deller EMPTY_PORT(0x30000) 587e029bb00SHelge Deller EMPTY_PORT(0x32000) 588e029bb00SHelge Deller EMPTY_PORT(0x34000) 589e029bb00SHelge Deller EMPTY_PORT(0x36000) 590e029bb00SHelge Deller EMPTY_PORT(0x38000) 591e029bb00SHelge Deller EMPTY_PORT(0x3a000) 592e029bb00SHelge Deller EMPTY_PORT(0x3c000) 593e029bb00SHelge Deller EMPTY_PORT(0x3e000) 594e029bb00SHelge Deller #undef EMPTY_PORT 595e029bb00SHelge Deller 596e029bb00SHelge Deller default: 597e029bb00SHelge Deller trace_astro_chip_read(addr, size, val); 598e029bb00SHelge Deller g_assert_not_reached(); 599e029bb00SHelge Deller } 600e029bb00SHelge Deller 601e029bb00SHelge Deller /* for 32-bit accesses mask return value */ 602e029bb00SHelge Deller val = mask_32bit_val(addr, size, val); 603e029bb00SHelge Deller 604e029bb00SHelge Deller trace_astro_chip_read(addr, size, val); 605e029bb00SHelge Deller *data = val; 606e029bb00SHelge Deller return ret; 607e029bb00SHelge Deller } 608e029bb00SHelge Deller 609e029bb00SHelge Deller static MemTxResult astro_chip_write_with_attrs(void *opaque, hwaddr addr, 610e029bb00SHelge Deller uint64_t val, unsigned size, 611e029bb00SHelge Deller MemTxAttrs attrs) 612e029bb00SHelge Deller { 613e029bb00SHelge Deller AstroState *s = opaque; 614e029bb00SHelge Deller 615e029bb00SHelge Deller trace_astro_chip_write(addr, size, val); 616e029bb00SHelge Deller 617e029bb00SHelge Deller switch ((addr >> 3) << 3) { 618e029bb00SHelge Deller case 0x0000: /* ID */ 619e029bb00SHelge Deller break; 620e029bb00SHelge Deller case 0x0008: /* IOC_CTRL */ 621e029bb00SHelge Deller val &= 0x0ffffff; 622e029bb00SHelge Deller put_val_in_int64(&s->ioc_ctrl, addr, size, val); 623e029bb00SHelge Deller break; 624e029bb00SHelge Deller case 0x0010: /* TOC_CLIENT_ID */ 625e029bb00SHelge Deller break; 626e029bb00SHelge Deller case 0x0030: /* HP-UX 10.20 and 11.11 reads it. No idea. */ 627e029bb00SHelge Deller break; 628e029bb00SHelge Deller case 0x0300 ... 0x03d8 - 1: /* LMMIO_DIRECT0_BASE... */ 629e029bb00SHelge Deller put_val_in_arrary(s->ioc_ranges, 0x300, addr, size, val); 630e029bb00SHelge Deller break; 631e029bb00SHelge Deller case 0x10200: 632e029bb00SHelge Deller case 0x10220: 633e029bb00SHelge Deller case 0x10230: /* HP-UX 11.11 reads it. No idea. */ 634e029bb00SHelge Deller break; 635e029bb00SHelge Deller case 0x20200 ... 0x20240 - 1: /* IOC Rope0_Control ... */ 636e029bb00SHelge Deller put_val_in_arrary(s->ioc_rope_control, 0x20200, addr, size, val); 637e029bb00SHelge Deller break; 638e029bb00SHelge Deller case 0x20040: /* IOC Rope config */ 639*ad701980SHelge Deller case 0x22040: 640e029bb00SHelge Deller put_val_in_int64(&s->ioc_rope_config, addr, size, val); 641e029bb00SHelge Deller break; 642e029bb00SHelge Deller case 0x20300: 643*ad701980SHelge Deller case 0x22300: 644e029bb00SHelge Deller put_val_in_int64(&s->tlb_ibase, addr, size, val); 645e029bb00SHelge Deller break; 646e029bb00SHelge Deller case 0x20308: 647*ad701980SHelge Deller case 0x22308: 648e029bb00SHelge Deller put_val_in_int64(&s->tlb_imask, addr, size, val); 649e029bb00SHelge Deller break; 650e029bb00SHelge Deller case 0x20310: 651*ad701980SHelge Deller case 0x22310: 652e029bb00SHelge Deller put_val_in_int64(&s->tlb_pcom, addr, size, val); 653e029bb00SHelge Deller /* TODO: flush iommu */ 654e029bb00SHelge Deller break; 655e029bb00SHelge Deller case 0x20318: 656*ad701980SHelge Deller case 0x22318: 657e029bb00SHelge Deller put_val_in_int64(&s->tlb_tcnfg, addr, size, val); 658e029bb00SHelge Deller break; 659e029bb00SHelge Deller case 0x20320: 660*ad701980SHelge Deller case 0x22320: 661e029bb00SHelge Deller put_val_in_int64(&s->tlb_pdir_base, addr, size, val); 662e029bb00SHelge Deller break; 663*ad701980SHelge Deller case 0x22000: /* func_id */ 664*ad701980SHelge Deller break; 665*ad701980SHelge Deller case 0x22008: /* func_class */ 666*ad701980SHelge Deller break; 667*ad701980SHelge Deller case 0x22050: /* rope_debug */ 668*ad701980SHelge Deller break; 669*ad701980SHelge Deller case 0x22108: /* IOC STATUS_CONTROL */ 670*ad701980SHelge Deller put_val_in_int64(&s->ioc_status_ctrl, addr, size, val); 671*ad701980SHelge Deller break; 672e029bb00SHelge Deller /* 673e029bb00SHelge Deller * empty placeholders for non-existent elroys, e.g. 674e029bb00SHelge Deller * func_class, pci config & data 675e029bb00SHelge Deller */ 676e029bb00SHelge Deller #define EMPTY_PORT(x) case x: case x+8: case x+0x40: case x+0x48: 677e029bb00SHelge Deller EMPTY_PORT(0x30000) 678e029bb00SHelge Deller EMPTY_PORT(0x32000) 679e029bb00SHelge Deller EMPTY_PORT(0x34000) 680e029bb00SHelge Deller EMPTY_PORT(0x36000) 681e029bb00SHelge Deller EMPTY_PORT(0x38000) 682e029bb00SHelge Deller EMPTY_PORT(0x3a000) 683e029bb00SHelge Deller EMPTY_PORT(0x3c000) 684e029bb00SHelge Deller EMPTY_PORT(0x3e000) 685e029bb00SHelge Deller break; 686e029bb00SHelge Deller #undef EMPTY_PORT 687e029bb00SHelge Deller 688e029bb00SHelge Deller default: 689e029bb00SHelge Deller /* Controlled by astro_chip_mem_valid above. */ 690e029bb00SHelge Deller trace_astro_chip_write(addr, size, val); 691e029bb00SHelge Deller g_assert_not_reached(); 692e029bb00SHelge Deller } 693e029bb00SHelge Deller return MEMTX_OK; 694e029bb00SHelge Deller } 695e029bb00SHelge Deller 696e029bb00SHelge Deller static const MemoryRegionOps astro_chip_ops = { 697e029bb00SHelge Deller .read_with_attrs = astro_chip_read_with_attrs, 698e029bb00SHelge Deller .write_with_attrs = astro_chip_write_with_attrs, 699e029bb00SHelge Deller .endianness = DEVICE_LITTLE_ENDIAN, 700e029bb00SHelge Deller .valid = { 701e029bb00SHelge Deller .min_access_size = 4, 702e029bb00SHelge Deller .max_access_size = 8, 703e029bb00SHelge Deller }, 704e029bb00SHelge Deller .impl = { 705e029bb00SHelge Deller .min_access_size = 4, 706e029bb00SHelge Deller .max_access_size = 8, 707e029bb00SHelge Deller }, 708e029bb00SHelge Deller }; 709e029bb00SHelge Deller 710e029bb00SHelge Deller static const VMStateDescription vmstate_astro = { 711e029bb00SHelge Deller .name = "Astro", 712e029bb00SHelge Deller .version_id = 1, 713e029bb00SHelge Deller .minimum_version_id = 1, 714e029bb00SHelge Deller .fields = (VMStateField[]) { 715e029bb00SHelge Deller VMSTATE_UINT64(ioc_ctrl, AstroState), 716e029bb00SHelge Deller VMSTATE_UINT64(ioc_status_ctrl, AstroState), 717e029bb00SHelge Deller VMSTATE_UINT64_ARRAY(ioc_ranges, AstroState, (0x03d8 - 0x300) / 8), 718e029bb00SHelge Deller VMSTATE_UINT64(ioc_rope_config, AstroState), 719e029bb00SHelge Deller VMSTATE_UINT64(ioc_status_control, AstroState), 720e029bb00SHelge Deller VMSTATE_UINT64(ioc_flush_control, AstroState), 721e029bb00SHelge Deller VMSTATE_UINT64_ARRAY(ioc_rope_control, AstroState, 8), 722e029bb00SHelge Deller VMSTATE_UINT64(tlb_ibase, AstroState), 723e029bb00SHelge Deller VMSTATE_UINT64(tlb_imask, AstroState), 724e029bb00SHelge Deller VMSTATE_UINT64(tlb_pcom, AstroState), 725e029bb00SHelge Deller VMSTATE_UINT64(tlb_tcnfg, AstroState), 726e029bb00SHelge Deller VMSTATE_UINT64(tlb_pdir_base, AstroState), 727e029bb00SHelge Deller VMSTATE_END_OF_LIST() 728e029bb00SHelge Deller } 729e029bb00SHelge Deller }; 730e029bb00SHelge Deller 731e029bb00SHelge Deller static void astro_reset(DeviceState *dev) 732e029bb00SHelge Deller { 733e029bb00SHelge Deller AstroState *s = ASTRO_CHIP(dev); 734e029bb00SHelge Deller int i; 735e029bb00SHelge Deller 736e029bb00SHelge Deller s->ioc_ctrl = 0x29cf; 737e029bb00SHelge Deller s->ioc_rope_config = 0xc5f; 738e029bb00SHelge Deller s->ioc_flush_control = 0xb03; 739e029bb00SHelge Deller s->ioc_status_control = 0; 740e029bb00SHelge Deller memset(&s->ioc_rope_control, 0, sizeof(s->ioc_rope_control)); 741e029bb00SHelge Deller 742e029bb00SHelge Deller /* 743e029bb00SHelge Deller * The SBA BASE/MASK registers control CPU -> IO routing. 744e029bb00SHelge Deller * The LBA BASE/MASK registers control IO -> System routing (in Elroy) 745e029bb00SHelge Deller */ 746e029bb00SHelge Deller memset(&s->ioc_ranges, 0, sizeof(s->ioc_ranges)); 747e029bb00SHelge Deller s->ioc_ranges[(0x360 - 0x300) / 8] = LMMIO_DIST_BASE_ADDR | 0x01; /* LMMIO_DIST_BASE (SBA) */ 748e029bb00SHelge Deller s->ioc_ranges[(0x368 - 0x300) / 8] = 0xfc000000; /* LMMIO_DIST_MASK */ 749e029bb00SHelge Deller s->ioc_ranges[(0x370 - 0x300) / 8] = 0; /* LMMIO_DIST_ROUTE */ 750e029bb00SHelge Deller s->ioc_ranges[(0x390 - 0x300) / 8] = IOS_DIST_BASE_ADDR | 0x01; /* IOS_DIST_BASE */ 751e029bb00SHelge Deller s->ioc_ranges[(0x398 - 0x300) / 8] = 0xffffff0000; /* IOS_DIST_MASK */ 752e029bb00SHelge Deller s->ioc_ranges[(0x3a0 - 0x300) / 8] = 0x3400000000000000ULL; /* IOS_DIST_ROUTE */ 753e029bb00SHelge Deller s->ioc_ranges[(0x3c0 - 0x300) / 8] = 0xfffee00000; /* IOS_DIRECT_BASE */ 754e029bb00SHelge Deller s->ioc_ranges[(0x3c8 - 0x300) / 8] = 0xffffff0000; /* IOS_DIRECT_MASK */ 755e029bb00SHelge Deller s->ioc_ranges[(0x3d0 - 0x300) / 8] = 0x0; /* IOS_DIRECT_ROUTE */ 756e029bb00SHelge Deller 757e029bb00SHelge Deller s->tlb_ibase = 0; 758e029bb00SHelge Deller s->tlb_imask = 0; 759e029bb00SHelge Deller s->tlb_pcom = 0; 760e029bb00SHelge Deller s->tlb_tcnfg = 0; 761e029bb00SHelge Deller s->tlb_pdir_base = 0; 762e029bb00SHelge Deller 763e029bb00SHelge Deller for (i = 0; i < ELROY_NUM; i++) { 764e029bb00SHelge Deller elroy_reset(DEVICE(s->elroy[i])); 765e029bb00SHelge Deller } 766e029bb00SHelge Deller } 767e029bb00SHelge Deller 768e029bb00SHelge Deller static void astro_init(Object *obj) 769e029bb00SHelge Deller { 770e029bb00SHelge Deller } 771e029bb00SHelge Deller 772e029bb00SHelge Deller static void astro_realize(DeviceState *obj, Error **errp) 773e029bb00SHelge Deller { 774e029bb00SHelge Deller AstroState *s = ASTRO_CHIP(obj); 775e029bb00SHelge Deller SysBusDevice *sbd = SYS_BUS_DEVICE(obj); 776e029bb00SHelge Deller int i; 777e029bb00SHelge Deller 778e029bb00SHelge Deller memory_region_init_io(&s->this_mem, OBJECT(s), &astro_chip_ops, 779e029bb00SHelge Deller s, "astro", 0x40000); 780e029bb00SHelge Deller sysbus_init_mmio(sbd, &s->this_mem); 781e029bb00SHelge Deller 782e029bb00SHelge Deller /* Host memory as seen from Elroys PCI side, via the IOMMU. */ 783e029bb00SHelge Deller memory_region_init_iommu(&s->iommu, sizeof(s->iommu), 784e029bb00SHelge Deller TYPE_ASTRO_IOMMU_MEMORY_REGION, OBJECT(s), 785e029bb00SHelge Deller "iommu-astro", UINT64_MAX); 786e029bb00SHelge Deller address_space_init(&s->iommu_as, MEMORY_REGION(&s->iommu), 787e029bb00SHelge Deller "bm-pci"); 788e029bb00SHelge Deller 789e029bb00SHelge Deller /* Create Elroys (PCI host bus chips). */ 790e029bb00SHelge Deller for (i = 0; i < ELROY_NUM; i++) { 791e029bb00SHelge Deller static const int elroy_hpa_offsets[ELROY_NUM] = { 792e029bb00SHelge Deller 0x30000, 0x32000, 0x38000, 0x3c000 }; 793e029bb00SHelge Deller static const char elroy_rope_nr[ELROY_NUM] = { 794e029bb00SHelge Deller 0, 1, 4, 6 }; /* busnum path, e.g. [10:6] */ 795e029bb00SHelge Deller int addr_offset; 796e029bb00SHelge Deller ElroyState *elroy; 797e029bb00SHelge Deller hwaddr map_addr; 798e029bb00SHelge Deller uint64_t map_size; 799e029bb00SHelge Deller int rope; 800e029bb00SHelge Deller 801e029bb00SHelge Deller addr_offset = elroy_hpa_offsets[i]; 802e029bb00SHelge Deller rope = elroy_rope_nr[i]; 803e029bb00SHelge Deller 804e029bb00SHelge Deller elroy = elroy_init(i); 805e029bb00SHelge Deller s->elroy[i] = elroy; 806e029bb00SHelge Deller elroy->hpa = ASTRO_HPA + addr_offset; 807e029bb00SHelge Deller elroy->pci_bus_num = i; 808e029bb00SHelge Deller elroy->astro = s; 809e029bb00SHelge Deller 810e029bb00SHelge Deller /* 811e029bb00SHelge Deller * NOTE: we only allow PCI devices on first Elroy for now. 812e029bb00SHelge Deller * SeaBIOS will not find devices on the other busses. 813e029bb00SHelge Deller */ 814e029bb00SHelge Deller if (i > 0) { 815e029bb00SHelge Deller qbus_mark_full(&PCI_HOST_BRIDGE(elroy)->bus->qbus); 816e029bb00SHelge Deller } 817e029bb00SHelge Deller 818e029bb00SHelge Deller /* map elroy config addresses into Astro space */ 819e029bb00SHelge Deller memory_region_add_subregion(&s->this_mem, addr_offset, 820e029bb00SHelge Deller &elroy->this_mem); 821e029bb00SHelge Deller 822e029bb00SHelge Deller /* LMMIO */ 823e029bb00SHelge Deller elroy->mmio_base[(0x0200 - 0x200) / 8] = 0xf0000001; 824e029bb00SHelge Deller elroy->mmio_base[(0x0208 - 0x200) / 8] = 0xf8000000; 825e029bb00SHelge Deller /* GMMIO */ 826e029bb00SHelge Deller elroy->mmio_base[(0x0210 - 0x200) / 8] = 0x000000f800000001; 827e029bb00SHelge Deller elroy->mmio_base[(0x0218 - 0x200) / 8] = 0x000000ff80000000; 828e029bb00SHelge Deller /* WLMMIO */ 829e029bb00SHelge Deller elroy->mmio_base[(0x0220 - 0x200) / 8] = 0xf0000001; 830e029bb00SHelge Deller elroy->mmio_base[(0x0228 - 0x200) / 8] = 0xf0000000; 831e029bb00SHelge Deller /* WGMMIO */ 832e029bb00SHelge Deller elroy->mmio_base[(0x0230 - 0x200) / 8] = 0x000000f800000001; 833e029bb00SHelge Deller elroy->mmio_base[(0x0238 - 0x200) / 8] = 0x000000fc00000000; 834e029bb00SHelge Deller /* IOS_BASE */ 835e029bb00SHelge Deller map_size = IOS_DIST_BASE_SIZE / ROPES_PER_IOC; 836e029bb00SHelge Deller elroy->mmio_base[(0x0240 - 0x200) / 8] = rope * map_size | 0x01; 837e029bb00SHelge Deller elroy->mmio_base[(0x0248 - 0x200) / 8] = 0x0000e000; 838e029bb00SHelge Deller 839e029bb00SHelge Deller /* map elroys mmio */ 840e029bb00SHelge Deller map_size = LMMIO_DIST_BASE_SIZE / ROPES_PER_IOC; 841fd842b2fSHelge Deller map_addr = F_EXTEND(LMMIO_DIST_BASE_ADDR + rope * map_size); 842e029bb00SHelge Deller memory_region_init_alias(&elroy->pci_mmio_alias, OBJECT(elroy), 843e029bb00SHelge Deller "pci-mmio-alias", 844fd842b2fSHelge Deller &elroy->pci_mmio, (uint32_t) map_addr, map_size); 845e029bb00SHelge Deller memory_region_add_subregion(get_system_memory(), map_addr, 846e029bb00SHelge Deller &elroy->pci_mmio_alias); 847e029bb00SHelge Deller 848fd842b2fSHelge Deller /* map elroys io */ 849e029bb00SHelge Deller map_size = IOS_DIST_BASE_SIZE / ROPES_PER_IOC; 850fd842b2fSHelge Deller map_addr = F_EXTEND(IOS_DIST_BASE_ADDR + rope * map_size); 851e029bb00SHelge Deller memory_region_add_subregion(get_system_memory(), map_addr, 852e029bb00SHelge Deller &elroy->pci_io); 853e029bb00SHelge Deller 854e029bb00SHelge Deller /* Host memory as seen from the PCI side, via the IOMMU. */ 855ba7d12ebSYi Liu pci_setup_iommu(PCI_HOST_BRIDGE(elroy)->bus, &elroy_pcihost_iommu_ops, 856e029bb00SHelge Deller elroy); 857e029bb00SHelge Deller } 858e029bb00SHelge Deller } 859e029bb00SHelge Deller 860e029bb00SHelge Deller static void astro_class_init(ObjectClass *klass, void *data) 861e029bb00SHelge Deller { 862e029bb00SHelge Deller DeviceClass *dc = DEVICE_CLASS(klass); 863e029bb00SHelge Deller 864e029bb00SHelge Deller dc->reset = astro_reset; 865e029bb00SHelge Deller dc->vmsd = &vmstate_astro; 866e029bb00SHelge Deller dc->realize = astro_realize; 867e029bb00SHelge Deller /* 868e029bb00SHelge Deller * astro with elroys are hard part of the newer PA2.0 machines and can not 869e029bb00SHelge Deller * be created without that hardware 870e029bb00SHelge Deller */ 871e029bb00SHelge Deller dc->user_creatable = false; 872e029bb00SHelge Deller } 873e029bb00SHelge Deller 874e029bb00SHelge Deller static const TypeInfo astro_chip_info = { 875e029bb00SHelge Deller .name = TYPE_ASTRO_CHIP, 876e029bb00SHelge Deller .parent = TYPE_SYS_BUS_DEVICE, 877e029bb00SHelge Deller .instance_init = astro_init, 878e029bb00SHelge Deller .instance_size = sizeof(AstroState), 879e029bb00SHelge Deller .class_init = astro_class_init, 880e029bb00SHelge Deller }; 881e029bb00SHelge Deller 882e029bb00SHelge Deller static void astro_iommu_memory_region_class_init(ObjectClass *klass, 883e029bb00SHelge Deller void *data) 884e029bb00SHelge Deller { 885e029bb00SHelge Deller IOMMUMemoryRegionClass *imrc = IOMMU_MEMORY_REGION_CLASS(klass); 886e029bb00SHelge Deller 887e029bb00SHelge Deller imrc->translate = astro_translate_iommu; 888e029bb00SHelge Deller } 889e029bb00SHelge Deller 890e029bb00SHelge Deller static const TypeInfo astro_iommu_memory_region_info = { 891e029bb00SHelge Deller .parent = TYPE_IOMMU_MEMORY_REGION, 892e029bb00SHelge Deller .name = TYPE_ASTRO_IOMMU_MEMORY_REGION, 893e029bb00SHelge Deller .class_init = astro_iommu_memory_region_class_init, 894e029bb00SHelge Deller }; 895e029bb00SHelge Deller 896e029bb00SHelge Deller 897e029bb00SHelge Deller static void astro_register_types(void) 898e029bb00SHelge Deller { 899e029bb00SHelge Deller type_register_static(&astro_chip_info); 900e029bb00SHelge Deller type_register_static(&astro_iommu_memory_region_info); 901e029bb00SHelge Deller } 902e029bb00SHelge Deller 903e029bb00SHelge Deller type_init(astro_register_types) 904