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