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