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