1 /* 2 * QEMU PowerPC PowerNV (POWER9) PHB4 model 3 * 4 * Copyright (c) 2018-2020, IBM Corporation. 5 * 6 * This code is licensed under the GPL version 2 or later. See the 7 * COPYING file in the top-level directory. 8 */ 9 #include "qemu/osdep.h" 10 #include "qapi/error.h" 11 #include "qemu-common.h" 12 #include "qemu/log.h" 13 #include "target/ppc/cpu.h" 14 #include "hw/ppc/fdt.h" 15 #include "hw/pci-host/pnv_phb4_regs.h" 16 #include "hw/pci-host/pnv_phb4.h" 17 #include "hw/ppc/pnv_xscom.h" 18 #include "hw/pci/pci_bridge.h" 19 #include "hw/pci/pci_bus.h" 20 #include "hw/ppc/pnv.h" 21 #include "hw/qdev-properties.h" 22 23 #include <libfdt.h> 24 25 #define phb_pec_error(pec, fmt, ...) \ 26 qemu_log_mask(LOG_GUEST_ERROR, "phb4_pec[%d:%d]: " fmt "\n", \ 27 (pec)->chip_id, (pec)->index, ## __VA_ARGS__) 28 29 30 static uint64_t pnv_pec_nest_xscom_read(void *opaque, hwaddr addr, 31 unsigned size) 32 { 33 PnvPhb4PecState *pec = PNV_PHB4_PEC(opaque); 34 uint32_t reg = addr >> 3; 35 36 /* TODO: add list of allowed registers and error out if not */ 37 return pec->nest_regs[reg]; 38 } 39 40 static void pnv_pec_nest_xscom_write(void *opaque, hwaddr addr, 41 uint64_t val, unsigned size) 42 { 43 PnvPhb4PecState *pec = PNV_PHB4_PEC(opaque); 44 uint32_t reg = addr >> 3; 45 46 switch (reg) { 47 case PEC_NEST_PBCQ_HW_CONFIG: 48 case PEC_NEST_DROP_PRIO_CTRL: 49 case PEC_NEST_PBCQ_ERR_INJECT: 50 case PEC_NEST_PCI_NEST_CLK_TRACE_CTL: 51 case PEC_NEST_PBCQ_PMON_CTRL: 52 case PEC_NEST_PBCQ_PBUS_ADDR_EXT: 53 case PEC_NEST_PBCQ_PRED_VEC_TIMEOUT: 54 case PEC_NEST_CAPP_CTRL: 55 case PEC_NEST_PBCQ_READ_STK_OVR: 56 case PEC_NEST_PBCQ_WRITE_STK_OVR: 57 case PEC_NEST_PBCQ_STORE_STK_OVR: 58 case PEC_NEST_PBCQ_RETRY_BKOFF_CTRL: 59 pec->nest_regs[reg] = val; 60 break; 61 default: 62 phb_pec_error(pec, "%s @0x%"HWADDR_PRIx"=%"PRIx64"\n", __func__, 63 addr, val); 64 } 65 } 66 67 static const MemoryRegionOps pnv_pec_nest_xscom_ops = { 68 .read = pnv_pec_nest_xscom_read, 69 .write = pnv_pec_nest_xscom_write, 70 .valid.min_access_size = 8, 71 .valid.max_access_size = 8, 72 .impl.min_access_size = 8, 73 .impl.max_access_size = 8, 74 .endianness = DEVICE_BIG_ENDIAN, 75 }; 76 77 static uint64_t pnv_pec_pci_xscom_read(void *opaque, hwaddr addr, 78 unsigned size) 79 { 80 PnvPhb4PecState *pec = PNV_PHB4_PEC(opaque); 81 uint32_t reg = addr >> 3; 82 83 /* TODO: add list of allowed registers and error out if not */ 84 return pec->pci_regs[reg]; 85 } 86 87 static void pnv_pec_pci_xscom_write(void *opaque, hwaddr addr, 88 uint64_t val, unsigned size) 89 { 90 PnvPhb4PecState *pec = PNV_PHB4_PEC(opaque); 91 uint32_t reg = addr >> 3; 92 93 switch (reg) { 94 case PEC_PCI_PBAIB_HW_CONFIG: 95 case PEC_PCI_PBAIB_READ_STK_OVR: 96 pec->pci_regs[reg] = val; 97 break; 98 default: 99 phb_pec_error(pec, "%s @0x%"HWADDR_PRIx"=%"PRIx64"\n", __func__, 100 addr, val); 101 } 102 } 103 104 static const MemoryRegionOps pnv_pec_pci_xscom_ops = { 105 .read = pnv_pec_pci_xscom_read, 106 .write = pnv_pec_pci_xscom_write, 107 .valid.min_access_size = 8, 108 .valid.max_access_size = 8, 109 .impl.min_access_size = 8, 110 .impl.max_access_size = 8, 111 .endianness = DEVICE_BIG_ENDIAN, 112 }; 113 114 static uint64_t pnv_pec_stk_nest_xscom_read(void *opaque, hwaddr addr, 115 unsigned size) 116 { 117 PnvPhb4PecStack *stack = PNV_PHB4_PEC_STACK(opaque); 118 uint32_t reg = addr >> 3; 119 120 /* TODO: add list of allowed registers and error out if not */ 121 return stack->nest_regs[reg]; 122 } 123 124 static void pnv_pec_stk_update_map(PnvPhb4PecStack *stack) 125 { 126 PnvPhb4PecState *pec = stack->pec; 127 MemoryRegion *sysmem = get_system_memory(); 128 uint64_t bar_en = stack->nest_regs[PEC_NEST_STK_BAR_EN]; 129 uint64_t bar, mask, size; 130 char name[64]; 131 132 /* 133 * NOTE: This will really not work well if those are remapped 134 * after the PHB has created its sub regions. We could do better 135 * if we had a way to resize regions but we don't really care 136 * that much in practice as the stuff below really only happens 137 * once early during boot 138 */ 139 140 /* Handle unmaps */ 141 if (memory_region_is_mapped(&stack->mmbar0) && 142 !(bar_en & PEC_NEST_STK_BAR_EN_MMIO0)) { 143 memory_region_del_subregion(sysmem, &stack->mmbar0); 144 } 145 if (memory_region_is_mapped(&stack->mmbar1) && 146 !(bar_en & PEC_NEST_STK_BAR_EN_MMIO1)) { 147 memory_region_del_subregion(sysmem, &stack->mmbar1); 148 } 149 if (memory_region_is_mapped(&stack->phbbar) && 150 !(bar_en & PEC_NEST_STK_BAR_EN_PHB)) { 151 memory_region_del_subregion(sysmem, &stack->phbbar); 152 } 153 if (memory_region_is_mapped(&stack->intbar) && 154 !(bar_en & PEC_NEST_STK_BAR_EN_INT)) { 155 memory_region_del_subregion(sysmem, &stack->intbar); 156 } 157 158 /* Update PHB */ 159 pnv_phb4_update_regions(stack); 160 161 /* Handle maps */ 162 if (!memory_region_is_mapped(&stack->mmbar0) && 163 (bar_en & PEC_NEST_STK_BAR_EN_MMIO0)) { 164 bar = stack->nest_regs[PEC_NEST_STK_MMIO_BAR0] >> 8; 165 mask = stack->nest_regs[PEC_NEST_STK_MMIO_BAR0_MASK]; 166 size = ((~mask) >> 8) + 1; 167 snprintf(name, sizeof(name), "pec-%d.%d-stack-%d-mmio0", 168 pec->chip_id, pec->index, stack->stack_no); 169 memory_region_init(&stack->mmbar0, OBJECT(stack), name, size); 170 memory_region_add_subregion(sysmem, bar, &stack->mmbar0); 171 stack->mmio0_base = bar; 172 stack->mmio0_size = size; 173 } 174 if (!memory_region_is_mapped(&stack->mmbar1) && 175 (bar_en & PEC_NEST_STK_BAR_EN_MMIO1)) { 176 bar = stack->nest_regs[PEC_NEST_STK_MMIO_BAR1] >> 8; 177 mask = stack->nest_regs[PEC_NEST_STK_MMIO_BAR1_MASK]; 178 size = ((~mask) >> 8) + 1; 179 snprintf(name, sizeof(name), "pec-%d.%d-stack-%d-mmio1", 180 pec->chip_id, pec->index, stack->stack_no); 181 memory_region_init(&stack->mmbar1, OBJECT(stack), name, size); 182 memory_region_add_subregion(sysmem, bar, &stack->mmbar1); 183 stack->mmio1_base = bar; 184 stack->mmio1_size = size; 185 } 186 if (!memory_region_is_mapped(&stack->phbbar) && 187 (bar_en & PEC_NEST_STK_BAR_EN_PHB)) { 188 bar = stack->nest_regs[PEC_NEST_STK_PHB_REGS_BAR] >> 8; 189 size = PNV_PHB4_NUM_REGS << 3; 190 snprintf(name, sizeof(name), "pec-%d.%d-stack-%d-phb", 191 pec->chip_id, pec->index, stack->stack_no); 192 memory_region_init(&stack->phbbar, OBJECT(stack), name, size); 193 memory_region_add_subregion(sysmem, bar, &stack->phbbar); 194 } 195 if (!memory_region_is_mapped(&stack->intbar) && 196 (bar_en & PEC_NEST_STK_BAR_EN_INT)) { 197 bar = stack->nest_regs[PEC_NEST_STK_INT_BAR] >> 8; 198 size = PNV_PHB4_MAX_INTs << 16; 199 snprintf(name, sizeof(name), "pec-%d.%d-stack-%d-int", 200 stack->pec->chip_id, stack->pec->index, stack->stack_no); 201 memory_region_init(&stack->intbar, OBJECT(stack), name, size); 202 memory_region_add_subregion(sysmem, bar, &stack->intbar); 203 } 204 205 /* Update PHB */ 206 pnv_phb4_update_regions(stack); 207 } 208 209 static void pnv_pec_stk_nest_xscom_write(void *opaque, hwaddr addr, 210 uint64_t val, unsigned size) 211 { 212 PnvPhb4PecStack *stack = PNV_PHB4_PEC_STACK(opaque); 213 PnvPhb4PecState *pec = stack->pec; 214 uint32_t reg = addr >> 3; 215 216 switch (reg) { 217 case PEC_NEST_STK_PCI_NEST_FIR: 218 stack->nest_regs[PEC_NEST_STK_PCI_NEST_FIR] = val; 219 break; 220 case PEC_NEST_STK_PCI_NEST_FIR_CLR: 221 stack->nest_regs[PEC_NEST_STK_PCI_NEST_FIR] &= val; 222 break; 223 case PEC_NEST_STK_PCI_NEST_FIR_SET: 224 stack->nest_regs[PEC_NEST_STK_PCI_NEST_FIR] |= val; 225 break; 226 case PEC_NEST_STK_PCI_NEST_FIR_MSK: 227 stack->nest_regs[PEC_NEST_STK_PCI_NEST_FIR_MSK] = val; 228 break; 229 case PEC_NEST_STK_PCI_NEST_FIR_MSKC: 230 stack->nest_regs[PEC_NEST_STK_PCI_NEST_FIR_MSK] &= val; 231 break; 232 case PEC_NEST_STK_PCI_NEST_FIR_MSKS: 233 stack->nest_regs[PEC_NEST_STK_PCI_NEST_FIR_MSK] |= val; 234 break; 235 case PEC_NEST_STK_PCI_NEST_FIR_ACT0: 236 case PEC_NEST_STK_PCI_NEST_FIR_ACT1: 237 stack->nest_regs[reg] = val; 238 break; 239 case PEC_NEST_STK_PCI_NEST_FIR_WOF: 240 stack->nest_regs[reg] = 0; 241 break; 242 case PEC_NEST_STK_ERR_REPORT_0: 243 case PEC_NEST_STK_ERR_REPORT_1: 244 case PEC_NEST_STK_PBCQ_GNRL_STATUS: 245 /* Flag error ? */ 246 break; 247 case PEC_NEST_STK_PBCQ_MODE: 248 stack->nest_regs[reg] = val & 0xff00000000000000ull; 249 break; 250 case PEC_NEST_STK_MMIO_BAR0: 251 case PEC_NEST_STK_MMIO_BAR0_MASK: 252 case PEC_NEST_STK_MMIO_BAR1: 253 case PEC_NEST_STK_MMIO_BAR1_MASK: 254 if (stack->nest_regs[PEC_NEST_STK_BAR_EN] & 255 (PEC_NEST_STK_BAR_EN_MMIO0 | 256 PEC_NEST_STK_BAR_EN_MMIO1)) { 257 phb_pec_error(pec, "Changing enabled BAR unsupported\n"); 258 } 259 stack->nest_regs[reg] = val & 0xffffffffff000000ull; 260 break; 261 case PEC_NEST_STK_PHB_REGS_BAR: 262 if (stack->nest_regs[PEC_NEST_STK_BAR_EN] & PEC_NEST_STK_BAR_EN_PHB) { 263 phb_pec_error(pec, "Changing enabled BAR unsupported\n"); 264 } 265 stack->nest_regs[reg] = val & 0xffffffffffc00000ull; 266 break; 267 case PEC_NEST_STK_INT_BAR: 268 if (stack->nest_regs[PEC_NEST_STK_BAR_EN] & PEC_NEST_STK_BAR_EN_INT) { 269 phb_pec_error(pec, "Changing enabled BAR unsupported\n"); 270 } 271 stack->nest_regs[reg] = val & 0xfffffff000000000ull; 272 break; 273 case PEC_NEST_STK_BAR_EN: 274 stack->nest_regs[reg] = val & 0xf000000000000000ull; 275 pnv_pec_stk_update_map(stack); 276 break; 277 case PEC_NEST_STK_DATA_FRZ_TYPE: 278 case PEC_NEST_STK_PBCQ_TUN_BAR: 279 /* Not used for now */ 280 stack->nest_regs[reg] = val; 281 break; 282 default: 283 qemu_log_mask(LOG_UNIMP, "phb4_pec: nest_xscom_write 0x%"HWADDR_PRIx 284 "=%"PRIx64"\n", addr, val); 285 } 286 } 287 288 static const MemoryRegionOps pnv_pec_stk_nest_xscom_ops = { 289 .read = pnv_pec_stk_nest_xscom_read, 290 .write = pnv_pec_stk_nest_xscom_write, 291 .valid.min_access_size = 8, 292 .valid.max_access_size = 8, 293 .impl.min_access_size = 8, 294 .impl.max_access_size = 8, 295 .endianness = DEVICE_BIG_ENDIAN, 296 }; 297 298 static uint64_t pnv_pec_stk_pci_xscom_read(void *opaque, hwaddr addr, 299 unsigned size) 300 { 301 PnvPhb4PecStack *stack = PNV_PHB4_PEC_STACK(opaque); 302 uint32_t reg = addr >> 3; 303 304 /* TODO: add list of allowed registers and error out if not */ 305 return stack->pci_regs[reg]; 306 } 307 308 static void pnv_pec_stk_pci_xscom_write(void *opaque, hwaddr addr, 309 uint64_t val, unsigned size) 310 { 311 PnvPhb4PecStack *stack = PNV_PHB4_PEC_STACK(opaque); 312 uint32_t reg = addr >> 3; 313 314 switch (reg) { 315 case PEC_PCI_STK_PCI_FIR: 316 stack->nest_regs[reg] = val; 317 break; 318 case PEC_PCI_STK_PCI_FIR_CLR: 319 stack->nest_regs[PEC_PCI_STK_PCI_FIR] &= val; 320 break; 321 case PEC_PCI_STK_PCI_FIR_SET: 322 stack->nest_regs[PEC_PCI_STK_PCI_FIR] |= val; 323 break; 324 case PEC_PCI_STK_PCI_FIR_MSK: 325 stack->nest_regs[reg] = val; 326 break; 327 case PEC_PCI_STK_PCI_FIR_MSKC: 328 stack->nest_regs[PEC_PCI_STK_PCI_FIR_MSK] &= val; 329 break; 330 case PEC_PCI_STK_PCI_FIR_MSKS: 331 stack->nest_regs[PEC_PCI_STK_PCI_FIR_MSK] |= val; 332 break; 333 case PEC_PCI_STK_PCI_FIR_ACT0: 334 case PEC_PCI_STK_PCI_FIR_ACT1: 335 stack->nest_regs[reg] = val; 336 break; 337 case PEC_PCI_STK_PCI_FIR_WOF: 338 stack->nest_regs[reg] = 0; 339 break; 340 case PEC_PCI_STK_ETU_RESET: 341 stack->nest_regs[reg] = val & 0x8000000000000000ull; 342 /* TODO: Implement reset */ 343 break; 344 case PEC_PCI_STK_PBAIB_ERR_REPORT: 345 break; 346 case PEC_PCI_STK_PBAIB_TX_CMD_CRED: 347 case PEC_PCI_STK_PBAIB_TX_DAT_CRED: 348 stack->nest_regs[reg] = val; 349 break; 350 default: 351 qemu_log_mask(LOG_UNIMP, "phb4_pec_stk: pci_xscom_write 0x%"HWADDR_PRIx 352 "=%"PRIx64"\n", addr, val); 353 } 354 } 355 356 static const MemoryRegionOps pnv_pec_stk_pci_xscom_ops = { 357 .read = pnv_pec_stk_pci_xscom_read, 358 .write = pnv_pec_stk_pci_xscom_write, 359 .valid.min_access_size = 8, 360 .valid.max_access_size = 8, 361 .impl.min_access_size = 8, 362 .impl.max_access_size = 8, 363 .endianness = DEVICE_BIG_ENDIAN, 364 }; 365 366 static void pnv_pec_instance_init(Object *obj) 367 { 368 PnvPhb4PecState *pec = PNV_PHB4_PEC(obj); 369 int i; 370 371 for (i = 0; i < PHB4_PEC_MAX_STACKS; i++) { 372 object_initialize_child(obj, "stack[*]", &pec->stacks[i], 373 TYPE_PNV_PHB4_PEC_STACK); 374 } 375 } 376 377 static int pnv_pec_phb_offset(PnvPhb4PecState *pec) 378 { 379 PnvPhb4PecClass *pecc = PNV_PHB4_PEC_GET_CLASS(pec); 380 int index = pec->index; 381 int offset = 0; 382 383 while (index--) { 384 offset += pecc->num_stacks[index]; 385 } 386 387 return offset; 388 } 389 390 static void pnv_pec_realize(DeviceState *dev, Error **errp) 391 { 392 PnvPhb4PecState *pec = PNV_PHB4_PEC(dev); 393 PnvPhb4PecClass *pecc = PNV_PHB4_PEC_GET_CLASS(pec); 394 char name[64]; 395 int i; 396 397 if (pec->index >= PNV_CHIP_GET_CLASS(pec->chip)->num_pecs) { 398 error_setg(errp, "invalid PEC index: %d", pec->index); 399 return; 400 } 401 402 pec->num_stacks = pecc->num_stacks[pec->index]; 403 404 /* Create stacks */ 405 for (i = 0; i < pec->num_stacks; i++) { 406 PnvPhb4PecStack *stack = &pec->stacks[i]; 407 Object *stk_obj = OBJECT(stack); 408 int phb_id = pnv_pec_phb_offset(pec) + i; 409 410 object_property_set_int(stk_obj, "stack-no", i, &error_abort); 411 object_property_set_int(stk_obj, "phb-id", phb_id, &error_abort); 412 object_property_set_link(stk_obj, "pec", OBJECT(pec), &error_abort); 413 if (!qdev_realize(DEVICE(stk_obj), NULL, errp)) { 414 return; 415 } 416 } 417 for (; i < PHB4_PEC_MAX_STACKS; i++) { 418 object_unparent(OBJECT(&pec->stacks[i])); 419 } 420 421 /* Initialize the XSCOM regions for the PEC registers */ 422 snprintf(name, sizeof(name), "xscom-pec-%d.%d-nest", pec->chip_id, 423 pec->index); 424 pnv_xscom_region_init(&pec->nest_regs_mr, OBJECT(dev), 425 &pnv_pec_nest_xscom_ops, pec, name, 426 PHB4_PEC_NEST_REGS_COUNT); 427 428 snprintf(name, sizeof(name), "xscom-pec-%d.%d-pci", pec->chip_id, 429 pec->index); 430 pnv_xscom_region_init(&pec->pci_regs_mr, OBJECT(dev), 431 &pnv_pec_pci_xscom_ops, pec, name, 432 PHB4_PEC_PCI_REGS_COUNT); 433 } 434 435 static int pnv_pec_dt_xscom(PnvXScomInterface *dev, void *fdt, 436 int xscom_offset) 437 { 438 PnvPhb4PecState *pec = PNV_PHB4_PEC(dev); 439 PnvPhb4PecClass *pecc = PNV_PHB4_PEC_GET_CLASS(dev); 440 uint32_t nbase = pecc->xscom_nest_base(pec); 441 uint32_t pbase = pecc->xscom_pci_base(pec); 442 int offset, i; 443 char *name; 444 uint32_t reg[] = { 445 cpu_to_be32(nbase), 446 cpu_to_be32(pecc->xscom_nest_size), 447 cpu_to_be32(pbase), 448 cpu_to_be32(pecc->xscom_pci_size), 449 }; 450 451 name = g_strdup_printf("pbcq@%x", nbase); 452 offset = fdt_add_subnode(fdt, xscom_offset, name); 453 _FDT(offset); 454 g_free(name); 455 456 _FDT((fdt_setprop(fdt, offset, "reg", reg, sizeof(reg)))); 457 458 _FDT((fdt_setprop_cell(fdt, offset, "ibm,pec-index", pec->index))); 459 _FDT((fdt_setprop_cell(fdt, offset, "#address-cells", 1))); 460 _FDT((fdt_setprop_cell(fdt, offset, "#size-cells", 0))); 461 _FDT((fdt_setprop(fdt, offset, "compatible", pecc->compat, 462 pecc->compat_size))); 463 464 for (i = 0; i < pec->num_stacks; i++) { 465 PnvPhb4PecStack *stack = &pec->stacks[i]; 466 PnvPHB4 *phb = &stack->phb; 467 int stk_offset; 468 469 name = g_strdup_printf("stack@%x", i); 470 stk_offset = fdt_add_subnode(fdt, offset, name); 471 _FDT(stk_offset); 472 g_free(name); 473 _FDT((fdt_setprop(fdt, stk_offset, "compatible", pecc->stk_compat, 474 pecc->stk_compat_size))); 475 _FDT((fdt_setprop_cell(fdt, stk_offset, "reg", i))); 476 _FDT((fdt_setprop_cell(fdt, stk_offset, "ibm,phb-index", phb->phb_id))); 477 } 478 479 return 0; 480 } 481 482 static Property pnv_pec_properties[] = { 483 DEFINE_PROP_UINT32("index", PnvPhb4PecState, index, 0), 484 DEFINE_PROP_UINT32("chip-id", PnvPhb4PecState, chip_id, 0), 485 DEFINE_PROP_LINK("chip", PnvPhb4PecState, chip, TYPE_PNV_CHIP, 486 PnvChip *), 487 DEFINE_PROP_END_OF_LIST(), 488 }; 489 490 static uint32_t pnv_pec_xscom_pci_base(PnvPhb4PecState *pec) 491 { 492 return PNV9_XSCOM_PEC_PCI_BASE + 0x1000000 * pec->index; 493 } 494 495 static uint32_t pnv_pec_xscom_nest_base(PnvPhb4PecState *pec) 496 { 497 return PNV9_XSCOM_PEC_NEST_BASE + 0x400 * pec->index; 498 } 499 500 /* 501 * PEC0 -> 1 stack 502 * PEC1 -> 2 stacks 503 * PEC2 -> 3 stacks 504 */ 505 static const uint32_t pnv_pec_num_stacks[] = { 1, 2, 3 }; 506 507 static void pnv_pec_class_init(ObjectClass *klass, void *data) 508 { 509 DeviceClass *dc = DEVICE_CLASS(klass); 510 PnvXScomInterfaceClass *xdc = PNV_XSCOM_INTERFACE_CLASS(klass); 511 PnvPhb4PecClass *pecc = PNV_PHB4_PEC_CLASS(klass); 512 static const char compat[] = "ibm,power9-pbcq"; 513 static const char stk_compat[] = "ibm,power9-phb-stack"; 514 515 xdc->dt_xscom = pnv_pec_dt_xscom; 516 517 dc->realize = pnv_pec_realize; 518 device_class_set_props(dc, pnv_pec_properties); 519 dc->user_creatable = false; 520 521 pecc->xscom_nest_base = pnv_pec_xscom_nest_base; 522 pecc->xscom_pci_base = pnv_pec_xscom_pci_base; 523 pecc->xscom_nest_size = PNV9_XSCOM_PEC_NEST_SIZE; 524 pecc->xscom_pci_size = PNV9_XSCOM_PEC_PCI_SIZE; 525 pecc->compat = compat; 526 pecc->compat_size = sizeof(compat); 527 pecc->stk_compat = stk_compat; 528 pecc->stk_compat_size = sizeof(stk_compat); 529 pecc->version = PNV_PHB4_VERSION; 530 pecc->device_id = PNV_PHB4_DEVICE_ID; 531 pecc->num_stacks = pnv_pec_num_stacks; 532 } 533 534 static const TypeInfo pnv_pec_type_info = { 535 .name = TYPE_PNV_PHB4_PEC, 536 .parent = TYPE_DEVICE, 537 .instance_size = sizeof(PnvPhb4PecState), 538 .instance_init = pnv_pec_instance_init, 539 .class_init = pnv_pec_class_init, 540 .class_size = sizeof(PnvPhb4PecClass), 541 .interfaces = (InterfaceInfo[]) { 542 { TYPE_PNV_XSCOM_INTERFACE }, 543 { } 544 } 545 }; 546 547 static void pnv_pec_stk_instance_init(Object *obj) 548 { 549 PnvPhb4PecStack *stack = PNV_PHB4_PEC_STACK(obj); 550 551 object_initialize_child(obj, "phb", &stack->phb, TYPE_PNV_PHB4); 552 object_property_add_alias(obj, "phb-id", OBJECT(&stack->phb), "index"); 553 } 554 555 static void pnv_pec_stk_realize(DeviceState *dev, Error **errp) 556 { 557 PnvPhb4PecStack *stack = PNV_PHB4_PEC_STACK(dev); 558 PnvPhb4PecState *pec = stack->pec; 559 PnvPhb4PecClass *pecc = PNV_PHB4_PEC_GET_CLASS(pec); 560 PnvChip *chip = pec->chip; 561 uint32_t pec_nest_base; 562 uint32_t pec_pci_base; 563 char name[64]; 564 565 assert(pec); 566 567 /* Initialize the XSCOM regions for the stack registers */ 568 snprintf(name, sizeof(name), "xscom-pec-%d.%d-nest-stack-%d", 569 pec->chip_id, pec->index, stack->stack_no); 570 pnv_xscom_region_init(&stack->nest_regs_mr, OBJECT(stack), 571 &pnv_pec_stk_nest_xscom_ops, stack, name, 572 PHB4_PEC_NEST_STK_REGS_COUNT); 573 574 snprintf(name, sizeof(name), "xscom-pec-%d.%d-pci-stack-%d", 575 pec->chip_id, pec->index, stack->stack_no); 576 pnv_xscom_region_init(&stack->pci_regs_mr, OBJECT(stack), 577 &pnv_pec_stk_pci_xscom_ops, stack, name, 578 PHB4_PEC_PCI_STK_REGS_COUNT); 579 580 /* PHB pass-through */ 581 snprintf(name, sizeof(name), "xscom-pec-%d.%d-pci-stack-%d-phb", 582 pec->chip_id, pec->index, stack->stack_no); 583 pnv_xscom_region_init(&stack->phb_regs_mr, OBJECT(&stack->phb), 584 &pnv_phb4_xscom_ops, &stack->phb, name, 0x40); 585 586 object_property_set_int(OBJECT(&stack->phb), "chip-id", pec->chip_id, 587 &error_fatal); 588 object_property_set_int(OBJECT(&stack->phb), "version", pecc->version, 589 &error_fatal); 590 object_property_set_int(OBJECT(&stack->phb), "device-id", pecc->device_id, 591 &error_fatal); 592 object_property_set_link(OBJECT(&stack->phb), "stack", OBJECT(stack), 593 &error_abort); 594 if (!sysbus_realize(SYS_BUS_DEVICE(&stack->phb), errp)) { 595 return; 596 } 597 598 pec_nest_base = pecc->xscom_nest_base(pec); 599 pec_pci_base = pecc->xscom_pci_base(pec); 600 601 /* Populate the XSCOM address space. */ 602 pnv_xscom_add_subregion(chip, 603 pec_nest_base + 0x40 * (stack->stack_no + 1), 604 &stack->nest_regs_mr); 605 pnv_xscom_add_subregion(chip, 606 pec_pci_base + 0x40 * (stack->stack_no + 1), 607 &stack->pci_regs_mr); 608 pnv_xscom_add_subregion(chip, 609 pec_pci_base + PNV9_XSCOM_PEC_PCI_STK0 + 610 0x40 * stack->stack_no, 611 &stack->phb_regs_mr); 612 } 613 614 static Property pnv_pec_stk_properties[] = { 615 DEFINE_PROP_UINT32("stack-no", PnvPhb4PecStack, stack_no, 0), 616 DEFINE_PROP_LINK("pec", PnvPhb4PecStack, pec, TYPE_PNV_PHB4_PEC, 617 PnvPhb4PecState *), 618 DEFINE_PROP_END_OF_LIST(), 619 }; 620 621 static void pnv_pec_stk_class_init(ObjectClass *klass, void *data) 622 { 623 DeviceClass *dc = DEVICE_CLASS(klass); 624 625 device_class_set_props(dc, pnv_pec_stk_properties); 626 dc->realize = pnv_pec_stk_realize; 627 dc->user_creatable = false; 628 629 /* TODO: reset regs ? */ 630 } 631 632 static const TypeInfo pnv_pec_stk_type_info = { 633 .name = TYPE_PNV_PHB4_PEC_STACK, 634 .parent = TYPE_DEVICE, 635 .instance_size = sizeof(PnvPhb4PecStack), 636 .instance_init = pnv_pec_stk_instance_init, 637 .class_init = pnv_pec_stk_class_init, 638 .interfaces = (InterfaceInfo[]) { 639 { TYPE_PNV_XSCOM_INTERFACE }, 640 { } 641 } 642 }; 643 644 static void pnv_pec_register_types(void) 645 { 646 type_register_static(&pnv_pec_type_info); 647 type_register_static(&pnv_pec_stk_type_info); 648 } 649 650 type_init(pnv_pec_register_types); 651