1 /* 2 * QEMU PowerPC PowerNV (POWER8) PHB3 model 3 * 4 * Copyright (c) 2014-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_phb3_regs.h" 16 #include "hw/pci-host/pnv_phb3.h" 17 #include "hw/ppc/pnv.h" 18 #include "hw/ppc/pnv_xscom.h" 19 #include "hw/pci/pci_bridge.h" 20 #include "hw/pci/pci_bus.h" 21 22 #include <libfdt.h> 23 24 #define phb3_pbcq_error(pbcq, fmt, ...) \ 25 qemu_log_mask(LOG_GUEST_ERROR, "phb3_pbcq[%d:%d]: " fmt "\n", \ 26 (pbcq)->phb->chip_id, (pbcq)->phb->phb_id, ## __VA_ARGS__) 27 28 static uint64_t pnv_pbcq_nest_xscom_read(void *opaque, hwaddr addr, 29 unsigned size) 30 { 31 PnvPBCQState *pbcq = PNV_PBCQ(opaque); 32 uint32_t offset = addr >> 3; 33 34 return pbcq->nest_regs[offset]; 35 } 36 37 static uint64_t pnv_pbcq_pci_xscom_read(void *opaque, hwaddr addr, 38 unsigned size) 39 { 40 PnvPBCQState *pbcq = PNV_PBCQ(opaque); 41 uint32_t offset = addr >> 3; 42 43 return pbcq->pci_regs[offset]; 44 } 45 46 static uint64_t pnv_pbcq_spci_xscom_read(void *opaque, hwaddr addr, 47 unsigned size) 48 { 49 PnvPBCQState *pbcq = PNV_PBCQ(opaque); 50 uint32_t offset = addr >> 3; 51 52 if (offset == PBCQ_SPCI_ASB_DATA) { 53 return pnv_phb3_reg_read(pbcq->phb, 54 pbcq->spci_regs[PBCQ_SPCI_ASB_ADDR], 8); 55 } 56 return pbcq->spci_regs[offset]; 57 } 58 59 static void pnv_pbcq_update_map(PnvPBCQState *pbcq) 60 { 61 uint64_t bar_en = pbcq->nest_regs[PBCQ_NEST_BAR_EN]; 62 uint64_t bar, mask, size; 63 64 /* 65 * NOTE: This will really not work well if those are remapped 66 * after the PHB has created its sub regions. We could do better 67 * if we had a way to resize regions but we don't really care 68 * that much in practice as the stuff below really only happens 69 * once early during boot 70 */ 71 72 /* Handle unmaps */ 73 if (memory_region_is_mapped(&pbcq->mmbar0) && 74 !(bar_en & PBCQ_NEST_BAR_EN_MMIO0)) { 75 memory_region_del_subregion(get_system_memory(), &pbcq->mmbar0); 76 } 77 if (memory_region_is_mapped(&pbcq->mmbar1) && 78 !(bar_en & PBCQ_NEST_BAR_EN_MMIO1)) { 79 memory_region_del_subregion(get_system_memory(), &pbcq->mmbar1); 80 } 81 if (memory_region_is_mapped(&pbcq->phbbar) && 82 !(bar_en & PBCQ_NEST_BAR_EN_PHB)) { 83 memory_region_del_subregion(get_system_memory(), &pbcq->phbbar); 84 } 85 86 /* Update PHB */ 87 pnv_phb3_update_regions(pbcq->phb); 88 89 /* Handle maps */ 90 if (!memory_region_is_mapped(&pbcq->mmbar0) && 91 (bar_en & PBCQ_NEST_BAR_EN_MMIO0)) { 92 bar = pbcq->nest_regs[PBCQ_NEST_MMIO_BAR0] >> 14; 93 mask = pbcq->nest_regs[PBCQ_NEST_MMIO_MASK0]; 94 size = ((~mask) >> 14) + 1; 95 memory_region_init(&pbcq->mmbar0, OBJECT(pbcq), "pbcq-mmio0", size); 96 memory_region_add_subregion(get_system_memory(), bar, &pbcq->mmbar0); 97 pbcq->mmio0_base = bar; 98 pbcq->mmio0_size = size; 99 } 100 if (!memory_region_is_mapped(&pbcq->mmbar1) && 101 (bar_en & PBCQ_NEST_BAR_EN_MMIO1)) { 102 bar = pbcq->nest_regs[PBCQ_NEST_MMIO_BAR1] >> 14; 103 mask = pbcq->nest_regs[PBCQ_NEST_MMIO_MASK1]; 104 size = ((~mask) >> 14) + 1; 105 memory_region_init(&pbcq->mmbar1, OBJECT(pbcq), "pbcq-mmio1", size); 106 memory_region_add_subregion(get_system_memory(), bar, &pbcq->mmbar1); 107 pbcq->mmio1_base = bar; 108 pbcq->mmio1_size = size; 109 } 110 if (!memory_region_is_mapped(&pbcq->phbbar) 111 && (bar_en & PBCQ_NEST_BAR_EN_PHB)) { 112 bar = pbcq->nest_regs[PBCQ_NEST_PHB_BAR] >> 14; 113 size = 0x1000; 114 memory_region_init(&pbcq->phbbar, OBJECT(pbcq), "pbcq-phb", size); 115 memory_region_add_subregion(get_system_memory(), bar, &pbcq->phbbar); 116 } 117 118 /* Update PHB */ 119 pnv_phb3_update_regions(pbcq->phb); 120 } 121 122 static void pnv_pbcq_nest_xscom_write(void *opaque, hwaddr addr, 123 uint64_t val, unsigned size) 124 { 125 PnvPBCQState *pbcq = PNV_PBCQ(opaque); 126 uint32_t reg = addr >> 3; 127 128 switch (reg) { 129 case PBCQ_NEST_MMIO_BAR0: 130 case PBCQ_NEST_MMIO_BAR1: 131 case PBCQ_NEST_MMIO_MASK0: 132 case PBCQ_NEST_MMIO_MASK1: 133 if (pbcq->nest_regs[PBCQ_NEST_BAR_EN] & 134 (PBCQ_NEST_BAR_EN_MMIO0 | 135 PBCQ_NEST_BAR_EN_MMIO1)) { 136 phb3_pbcq_error(pbcq, "Changing enabled BAR unsupported"); 137 } 138 pbcq->nest_regs[reg] = val & 0xffffffffc0000000ull; 139 break; 140 case PBCQ_NEST_PHB_BAR: 141 if (pbcq->nest_regs[PBCQ_NEST_BAR_EN] & PBCQ_NEST_BAR_EN_PHB) { 142 phb3_pbcq_error(pbcq, "Changing enabled BAR unsupported"); 143 } 144 pbcq->nest_regs[reg] = val & 0xfffffffffc000000ull; 145 break; 146 case PBCQ_NEST_BAR_EN: 147 pbcq->nest_regs[reg] = val & 0xf800000000000000ull; 148 pnv_pbcq_update_map(pbcq); 149 pnv_phb3_remap_irqs(pbcq->phb); 150 break; 151 case PBCQ_NEST_IRSN_COMPARE: 152 case PBCQ_NEST_IRSN_MASK: 153 pbcq->nest_regs[reg] = val & PBCQ_NEST_IRSN_COMP; 154 pnv_phb3_remap_irqs(pbcq->phb); 155 break; 156 case PBCQ_NEST_LSI_SRC_ID: 157 pbcq->nest_regs[reg] = val & PBCQ_NEST_LSI_SRC; 158 pnv_phb3_remap_irqs(pbcq->phb); 159 break; 160 default: 161 phb3_pbcq_error(pbcq, "%s @0x%"HWADDR_PRIx"=%"PRIx64, __func__, 162 addr, val); 163 } 164 } 165 166 static void pnv_pbcq_pci_xscom_write(void *opaque, hwaddr addr, 167 uint64_t val, unsigned size) 168 { 169 PnvPBCQState *pbcq = PNV_PBCQ(opaque); 170 uint32_t reg = addr >> 3; 171 172 switch (reg) { 173 case PBCQ_PCI_BAR2: 174 pbcq->pci_regs[reg] = val & 0xfffffffffc000000ull; 175 pnv_pbcq_update_map(pbcq); 176 break; 177 default: 178 phb3_pbcq_error(pbcq, "%s @0x%"HWADDR_PRIx"=%"PRIx64, __func__, 179 addr, val); 180 } 181 } 182 183 static void pnv_pbcq_spci_xscom_write(void *opaque, hwaddr addr, 184 uint64_t val, unsigned size) 185 { 186 PnvPBCQState *pbcq = PNV_PBCQ(opaque); 187 uint32_t reg = addr >> 3; 188 189 switch (reg) { 190 case PBCQ_SPCI_ASB_ADDR: 191 pbcq->spci_regs[reg] = val & 0xfff; 192 break; 193 case PBCQ_SPCI_ASB_STATUS: 194 pbcq->spci_regs[reg] &= ~val; 195 break; 196 case PBCQ_SPCI_ASB_DATA: 197 pnv_phb3_reg_write(pbcq->phb, pbcq->spci_regs[PBCQ_SPCI_ASB_ADDR], 198 val, 8); 199 break; 200 case PBCQ_SPCI_AIB_CAPP_EN: 201 case PBCQ_SPCI_CAPP_SEC_TMR: 202 break; 203 default: 204 phb3_pbcq_error(pbcq, "%s @0x%"HWADDR_PRIx"=%"PRIx64, __func__, 205 addr, val); 206 } 207 } 208 209 static const MemoryRegionOps pnv_pbcq_nest_xscom_ops = { 210 .read = pnv_pbcq_nest_xscom_read, 211 .write = pnv_pbcq_nest_xscom_write, 212 .valid.min_access_size = 8, 213 .valid.max_access_size = 8, 214 .impl.min_access_size = 8, 215 .impl.max_access_size = 8, 216 .endianness = DEVICE_BIG_ENDIAN, 217 }; 218 219 static const MemoryRegionOps pnv_pbcq_pci_xscom_ops = { 220 .read = pnv_pbcq_pci_xscom_read, 221 .write = pnv_pbcq_pci_xscom_write, 222 .valid.min_access_size = 8, 223 .valid.max_access_size = 8, 224 .impl.min_access_size = 8, 225 .impl.max_access_size = 8, 226 .endianness = DEVICE_BIG_ENDIAN, 227 }; 228 229 static const MemoryRegionOps pnv_pbcq_spci_xscom_ops = { 230 .read = pnv_pbcq_spci_xscom_read, 231 .write = pnv_pbcq_spci_xscom_write, 232 .valid.min_access_size = 8, 233 .valid.max_access_size = 8, 234 .impl.min_access_size = 8, 235 .impl.max_access_size = 8, 236 .endianness = DEVICE_BIG_ENDIAN, 237 }; 238 239 static void pnv_pbcq_default_bars(PnvPBCQState *pbcq) 240 { 241 uint64_t mm0, mm1, reg; 242 PnvPHB3 *phb = pbcq->phb; 243 244 mm0 = 0x3d00000000000ull + 0x4000000000ull * phb->chip_id + 245 0x1000000000ull * phb->phb_id; 246 mm1 = 0x3ff8000000000ull + 0x0200000000ull * phb->chip_id + 247 0x0080000000ull * phb->phb_id; 248 reg = 0x3fffe40000000ull + 0x0000400000ull * phb->chip_id + 249 0x0000100000ull * phb->phb_id; 250 251 pbcq->nest_regs[PBCQ_NEST_MMIO_BAR0] = mm0 << 14; 252 pbcq->nest_regs[PBCQ_NEST_MMIO_BAR1] = mm1 << 14; 253 pbcq->nest_regs[PBCQ_NEST_PHB_BAR] = reg << 14; 254 pbcq->nest_regs[PBCQ_NEST_MMIO_MASK0] = 0x3fff000000000ull << 14; 255 pbcq->nest_regs[PBCQ_NEST_MMIO_MASK1] = 0x3ffff80000000ull << 14; 256 pbcq->pci_regs[PBCQ_PCI_BAR2] = reg << 14; 257 } 258 259 static void pnv_pbcq_realize(DeviceState *dev, Error **errp) 260 { 261 PnvPBCQState *pbcq = PNV_PBCQ(dev); 262 PnvPHB3 *phb; 263 char name[32]; 264 265 assert(pbcq->phb); 266 phb = pbcq->phb; 267 268 /* TODO: Fix OPAL to do that: establish default BAR values */ 269 pnv_pbcq_default_bars(pbcq); 270 271 /* Initialize the XSCOM region for the PBCQ registers */ 272 snprintf(name, sizeof(name), "xscom-pbcq-nest-%d.%d", 273 phb->chip_id, phb->phb_id); 274 pnv_xscom_region_init(&pbcq->xscom_nest_regs, OBJECT(dev), 275 &pnv_pbcq_nest_xscom_ops, pbcq, name, 276 PNV_XSCOM_PBCQ_NEST_SIZE); 277 snprintf(name, sizeof(name), "xscom-pbcq-pci-%d.%d", 278 phb->chip_id, phb->phb_id); 279 pnv_xscom_region_init(&pbcq->xscom_pci_regs, OBJECT(dev), 280 &pnv_pbcq_pci_xscom_ops, pbcq, name, 281 PNV_XSCOM_PBCQ_PCI_SIZE); 282 snprintf(name, sizeof(name), "xscom-pbcq-spci-%d.%d", 283 phb->chip_id, phb->phb_id); 284 pnv_xscom_region_init(&pbcq->xscom_spci_regs, OBJECT(dev), 285 &pnv_pbcq_spci_xscom_ops, pbcq, name, 286 PNV_XSCOM_PBCQ_SPCI_SIZE); 287 288 /* Populate the XSCOM address space. */ 289 pnv_xscom_add_subregion(phb->chip, 290 PNV_XSCOM_PBCQ_NEST_BASE + 0x400 * phb->phb_id, 291 &pbcq->xscom_nest_regs); 292 pnv_xscom_add_subregion(phb->chip, 293 PNV_XSCOM_PBCQ_PCI_BASE + 0x400 * phb->phb_id, 294 &pbcq->xscom_pci_regs); 295 pnv_xscom_add_subregion(phb->chip, 296 PNV_XSCOM_PBCQ_SPCI_BASE + 0x040 * phb->phb_id, 297 &pbcq->xscom_spci_regs); 298 } 299 300 static int pnv_pbcq_dt_xscom(PnvXScomInterface *dev, void *fdt, 301 int xscom_offset) 302 { 303 const char compat[] = "ibm,power8-pbcq"; 304 PnvPHB3 *phb = PNV_PBCQ(dev)->phb; 305 char *name; 306 int offset; 307 uint32_t lpc_pcba = PNV_XSCOM_PBCQ_NEST_BASE + 0x400 * phb->phb_id; 308 uint32_t reg[] = { 309 cpu_to_be32(lpc_pcba), 310 cpu_to_be32(PNV_XSCOM_PBCQ_NEST_SIZE), 311 cpu_to_be32(PNV_XSCOM_PBCQ_PCI_BASE + 0x400 * phb->phb_id), 312 cpu_to_be32(PNV_XSCOM_PBCQ_PCI_SIZE), 313 cpu_to_be32(PNV_XSCOM_PBCQ_SPCI_BASE + 0x040 * phb->phb_id), 314 cpu_to_be32(PNV_XSCOM_PBCQ_SPCI_SIZE) 315 }; 316 317 name = g_strdup_printf("pbcq@%x", lpc_pcba); 318 offset = fdt_add_subnode(fdt, xscom_offset, name); 319 _FDT(offset); 320 g_free(name); 321 322 _FDT((fdt_setprop(fdt, offset, "reg", reg, sizeof(reg)))); 323 324 _FDT((fdt_setprop_cell(fdt, offset, "ibm,phb-index", phb->phb_id))); 325 _FDT((fdt_setprop_cell(fdt, offset, "ibm,chip-id", phb->chip_id))); 326 _FDT((fdt_setprop(fdt, offset, "compatible", compat, 327 sizeof(compat)))); 328 return 0; 329 } 330 331 static void phb3_pbcq_instance_init(Object *obj) 332 { 333 PnvPBCQState *pbcq = PNV_PBCQ(obj); 334 335 object_property_add_link(obj, "phb", TYPE_PNV_PHB3, 336 (Object **)&pbcq->phb, 337 object_property_allow_set_link, 338 OBJ_PROP_LINK_STRONG); 339 } 340 341 static void pnv_pbcq_class_init(ObjectClass *klass, void *data) 342 { 343 DeviceClass *dc = DEVICE_CLASS(klass); 344 PnvXScomInterfaceClass *xdc = PNV_XSCOM_INTERFACE_CLASS(klass); 345 346 xdc->dt_xscom = pnv_pbcq_dt_xscom; 347 348 dc->realize = pnv_pbcq_realize; 349 dc->user_creatable = false; 350 } 351 352 static const TypeInfo pnv_pbcq_type_info = { 353 .name = TYPE_PNV_PBCQ, 354 .parent = TYPE_DEVICE, 355 .instance_size = sizeof(PnvPBCQState), 356 .instance_init = phb3_pbcq_instance_init, 357 .class_init = pnv_pbcq_class_init, 358 .interfaces = (InterfaceInfo[]) { 359 { TYPE_PNV_XSCOM_INTERFACE }, 360 { } 361 } 362 }; 363 364 static void pnv_pbcq_register_types(void) 365 { 366 type_register_static(&pnv_pbcq_type_info); 367 } 368 369 type_init(pnv_pbcq_register_types) 370