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