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 = pec->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 void pnv_pec_realize(DeviceState *dev, Error **errp) 378 { 379 PnvPhb4PecState *pec = PNV_PHB4_PEC(dev); 380 Error *local_err = NULL; 381 char name[64]; 382 int i; 383 384 assert(pec->system_memory); 385 386 /* Create stacks */ 387 for (i = 0; i < pec->num_stacks; i++) { 388 PnvPhb4PecStack *stack = &pec->stacks[i]; 389 Object *stk_obj = OBJECT(stack); 390 391 object_property_set_int(stk_obj, i, "stack-no", &error_abort); 392 object_property_set_link(stk_obj, OBJECT(pec), "pec", &error_abort); 393 if (!qdev_realize(DEVICE(stk_obj), NULL, &local_err)) { 394 error_propagate(errp, local_err); 395 return; 396 } 397 } 398 for (; i < PHB4_PEC_MAX_STACKS; i++) { 399 object_unparent(OBJECT(&pec->stacks[i])); 400 } 401 402 /* Initialize the XSCOM regions for the PEC registers */ 403 snprintf(name, sizeof(name), "xscom-pec-%d.%d-nest", pec->chip_id, 404 pec->index); 405 pnv_xscom_region_init(&pec->nest_regs_mr, OBJECT(dev), 406 &pnv_pec_nest_xscom_ops, pec, name, 407 PHB4_PEC_NEST_REGS_COUNT); 408 409 snprintf(name, sizeof(name), "xscom-pec-%d.%d-pci", pec->chip_id, 410 pec->index); 411 pnv_xscom_region_init(&pec->pci_regs_mr, OBJECT(dev), 412 &pnv_pec_pci_xscom_ops, pec, name, 413 PHB4_PEC_PCI_REGS_COUNT); 414 } 415 416 static int pnv_pec_dt_xscom(PnvXScomInterface *dev, void *fdt, 417 int xscom_offset) 418 { 419 PnvPhb4PecState *pec = PNV_PHB4_PEC(dev); 420 PnvPhb4PecClass *pecc = PNV_PHB4_PEC_GET_CLASS(dev); 421 uint32_t nbase = pecc->xscom_nest_base(pec); 422 uint32_t pbase = pecc->xscom_pci_base(pec); 423 int offset, i; 424 char *name; 425 uint32_t reg[] = { 426 cpu_to_be32(nbase), 427 cpu_to_be32(pecc->xscom_nest_size), 428 cpu_to_be32(pbase), 429 cpu_to_be32(pecc->xscom_pci_size), 430 }; 431 432 name = g_strdup_printf("pbcq@%x", nbase); 433 offset = fdt_add_subnode(fdt, xscom_offset, name); 434 _FDT(offset); 435 g_free(name); 436 437 _FDT((fdt_setprop(fdt, offset, "reg", reg, sizeof(reg)))); 438 439 _FDT((fdt_setprop_cell(fdt, offset, "ibm,pec-index", pec->index))); 440 _FDT((fdt_setprop_cell(fdt, offset, "#address-cells", 1))); 441 _FDT((fdt_setprop_cell(fdt, offset, "#size-cells", 0))); 442 _FDT((fdt_setprop(fdt, offset, "compatible", pecc->compat, 443 pecc->compat_size))); 444 445 for (i = 0; i < pec->num_stacks; i++) { 446 PnvPhb4PecStack *stack = &pec->stacks[i]; 447 PnvPHB4 *phb = &stack->phb; 448 int stk_offset; 449 450 name = g_strdup_printf("stack@%x", i); 451 stk_offset = fdt_add_subnode(fdt, offset, name); 452 _FDT(stk_offset); 453 g_free(name); 454 _FDT((fdt_setprop(fdt, stk_offset, "compatible", pecc->stk_compat, 455 pecc->stk_compat_size))); 456 _FDT((fdt_setprop_cell(fdt, stk_offset, "reg", i))); 457 _FDT((fdt_setprop_cell(fdt, stk_offset, "ibm,phb-index", phb->phb_id))); 458 } 459 460 return 0; 461 } 462 463 static Property pnv_pec_properties[] = { 464 DEFINE_PROP_UINT32("index", PnvPhb4PecState, index, 0), 465 DEFINE_PROP_UINT32("num-stacks", PnvPhb4PecState, num_stacks, 0), 466 DEFINE_PROP_UINT32("chip-id", PnvPhb4PecState, chip_id, 0), 467 DEFINE_PROP_LINK("system-memory", PnvPhb4PecState, system_memory, 468 TYPE_MEMORY_REGION, MemoryRegion *), 469 DEFINE_PROP_END_OF_LIST(), 470 }; 471 472 static uint32_t pnv_pec_xscom_pci_base(PnvPhb4PecState *pec) 473 { 474 return PNV9_XSCOM_PEC_PCI_BASE + 0x1000000 * pec->index; 475 } 476 477 static uint32_t pnv_pec_xscom_nest_base(PnvPhb4PecState *pec) 478 { 479 return PNV9_XSCOM_PEC_NEST_BASE + 0x400 * pec->index; 480 } 481 482 static void pnv_pec_class_init(ObjectClass *klass, void *data) 483 { 484 DeviceClass *dc = DEVICE_CLASS(klass); 485 PnvXScomInterfaceClass *xdc = PNV_XSCOM_INTERFACE_CLASS(klass); 486 PnvPhb4PecClass *pecc = PNV_PHB4_PEC_CLASS(klass); 487 static const char compat[] = "ibm,power9-pbcq"; 488 static const char stk_compat[] = "ibm,power9-phb-stack"; 489 490 xdc->dt_xscom = pnv_pec_dt_xscom; 491 492 dc->realize = pnv_pec_realize; 493 device_class_set_props(dc, pnv_pec_properties); 494 dc->user_creatable = false; 495 496 pecc->xscom_nest_base = pnv_pec_xscom_nest_base; 497 pecc->xscom_pci_base = pnv_pec_xscom_pci_base; 498 pecc->xscom_nest_size = PNV9_XSCOM_PEC_NEST_SIZE; 499 pecc->xscom_pci_size = PNV9_XSCOM_PEC_PCI_SIZE; 500 pecc->compat = compat; 501 pecc->compat_size = sizeof(compat); 502 pecc->stk_compat = stk_compat; 503 pecc->stk_compat_size = sizeof(stk_compat); 504 } 505 506 static const TypeInfo pnv_pec_type_info = { 507 .name = TYPE_PNV_PHB4_PEC, 508 .parent = TYPE_DEVICE, 509 .instance_size = sizeof(PnvPhb4PecState), 510 .instance_init = pnv_pec_instance_init, 511 .class_init = pnv_pec_class_init, 512 .class_size = sizeof(PnvPhb4PecClass), 513 .interfaces = (InterfaceInfo[]) { 514 { TYPE_PNV_XSCOM_INTERFACE }, 515 { } 516 } 517 }; 518 519 static void pnv_pec_stk_instance_init(Object *obj) 520 { 521 PnvPhb4PecStack *stack = PNV_PHB4_PEC_STACK(obj); 522 523 object_initialize_child(obj, "phb", &stack->phb, TYPE_PNV_PHB4); 524 } 525 526 static void pnv_pec_stk_realize(DeviceState *dev, Error **errp) 527 { 528 PnvPhb4PecStack *stack = PNV_PHB4_PEC_STACK(dev); 529 PnvPhb4PecState *pec = stack->pec; 530 char name[64]; 531 532 assert(pec); 533 534 /* Initialize the XSCOM regions for the stack registers */ 535 snprintf(name, sizeof(name), "xscom-pec-%d.%d-nest-stack-%d", 536 pec->chip_id, pec->index, stack->stack_no); 537 pnv_xscom_region_init(&stack->nest_regs_mr, OBJECT(stack), 538 &pnv_pec_stk_nest_xscom_ops, stack, name, 539 PHB4_PEC_NEST_STK_REGS_COUNT); 540 541 snprintf(name, sizeof(name), "xscom-pec-%d.%d-pci-stack-%d", 542 pec->chip_id, pec->index, stack->stack_no); 543 pnv_xscom_region_init(&stack->pci_regs_mr, OBJECT(stack), 544 &pnv_pec_stk_pci_xscom_ops, stack, name, 545 PHB4_PEC_PCI_STK_REGS_COUNT); 546 547 /* PHB pass-through */ 548 snprintf(name, sizeof(name), "xscom-pec-%d.%d-pci-stack-%d-phb", 549 pec->chip_id, pec->index, stack->stack_no); 550 pnv_xscom_region_init(&stack->phb_regs_mr, OBJECT(&stack->phb), 551 &pnv_phb4_xscom_ops, &stack->phb, name, 0x40); 552 553 /* 554 * Let the machine/chip realize the PHB object to customize more 555 * easily some fields 556 */ 557 } 558 559 static Property pnv_pec_stk_properties[] = { 560 DEFINE_PROP_UINT32("stack-no", PnvPhb4PecStack, stack_no, 0), 561 DEFINE_PROP_LINK("pec", PnvPhb4PecStack, pec, TYPE_PNV_PHB4_PEC, 562 PnvPhb4PecState *), 563 DEFINE_PROP_END_OF_LIST(), 564 }; 565 566 static void pnv_pec_stk_class_init(ObjectClass *klass, void *data) 567 { 568 DeviceClass *dc = DEVICE_CLASS(klass); 569 570 device_class_set_props(dc, pnv_pec_stk_properties); 571 dc->realize = pnv_pec_stk_realize; 572 dc->user_creatable = false; 573 574 /* TODO: reset regs ? */ 575 } 576 577 static const TypeInfo pnv_pec_stk_type_info = { 578 .name = TYPE_PNV_PHB4_PEC_STACK, 579 .parent = TYPE_DEVICE, 580 .instance_size = sizeof(PnvPhb4PecStack), 581 .instance_init = pnv_pec_stk_instance_init, 582 .class_init = pnv_pec_stk_class_init, 583 .interfaces = (InterfaceInfo[]) { 584 { TYPE_PNV_XSCOM_INTERFACE }, 585 { } 586 } 587 }; 588 589 static void pnv_pec_register_types(void) 590 { 591 type_register_static(&pnv_pec_type_info); 592 type_register_static(&pnv_pec_stk_type_info); 593 } 594 595 type_init(pnv_pec_register_types); 596