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