19ae1329eSCédric Le Goater /* 29ae1329eSCédric Le Goater * QEMU PowerPC PowerNV (POWER8) PHB3 model 39ae1329eSCédric Le Goater * 49ae1329eSCédric Le Goater * Copyright (c) 2014-2020, IBM Corporation. 59ae1329eSCédric Le Goater * 69ae1329eSCédric Le Goater * This code is licensed under the GPL version 2 or later. See the 79ae1329eSCédric Le Goater * COPYING file in the top-level directory. 89ae1329eSCédric Le Goater */ 99ae1329eSCédric Le Goater #include "qemu/osdep.h" 109ae1329eSCédric Le Goater #include "qapi/error.h" 119ae1329eSCédric Le Goater #include "qemu-common.h" 129ae1329eSCédric Le Goater #include "qemu/log.h" 139ae1329eSCédric Le Goater #include "target/ppc/cpu.h" 149ae1329eSCédric Le Goater #include "hw/ppc/fdt.h" 159ae1329eSCédric Le Goater #include "hw/pci-host/pnv_phb3_regs.h" 169ae1329eSCédric Le Goater #include "hw/pci-host/pnv_phb3.h" 179ae1329eSCédric Le Goater #include "hw/ppc/pnv.h" 189ae1329eSCédric Le Goater #include "hw/ppc/pnv_xscom.h" 199ae1329eSCédric Le Goater #include "hw/pci/pci_bridge.h" 209ae1329eSCédric Le Goater #include "hw/pci/pci_bus.h" 219ae1329eSCédric Le Goater 229ae1329eSCédric Le Goater #include <libfdt.h> 239ae1329eSCédric Le Goater 249ae1329eSCédric Le Goater #define phb3_pbcq_error(pbcq, fmt, ...) \ 259ae1329eSCédric Le Goater qemu_log_mask(LOG_GUEST_ERROR, "phb3_pbcq[%d:%d]: " fmt "\n", \ 269ae1329eSCédric Le Goater (pbcq)->phb->chip_id, (pbcq)->phb->phb_id, ## __VA_ARGS__) 279ae1329eSCédric Le Goater 289ae1329eSCédric Le Goater static uint64_t pnv_pbcq_nest_xscom_read(void *opaque, hwaddr addr, 299ae1329eSCédric Le Goater unsigned size) 309ae1329eSCédric Le Goater { 319ae1329eSCédric Le Goater PnvPBCQState *pbcq = PNV_PBCQ(opaque); 329ae1329eSCédric Le Goater uint32_t offset = addr >> 3; 339ae1329eSCédric Le Goater 349ae1329eSCédric Le Goater return pbcq->nest_regs[offset]; 359ae1329eSCédric Le Goater } 369ae1329eSCédric Le Goater 379ae1329eSCédric Le Goater static uint64_t pnv_pbcq_pci_xscom_read(void *opaque, hwaddr addr, 389ae1329eSCédric Le Goater unsigned size) 399ae1329eSCédric Le Goater { 409ae1329eSCédric Le Goater PnvPBCQState *pbcq = PNV_PBCQ(opaque); 419ae1329eSCédric Le Goater uint32_t offset = addr >> 3; 429ae1329eSCédric Le Goater 439ae1329eSCédric Le Goater return pbcq->pci_regs[offset]; 449ae1329eSCédric Le Goater } 459ae1329eSCédric Le Goater 469ae1329eSCédric Le Goater static uint64_t pnv_pbcq_spci_xscom_read(void *opaque, hwaddr addr, 479ae1329eSCédric Le Goater unsigned size) 489ae1329eSCédric Le Goater { 499ae1329eSCédric Le Goater PnvPBCQState *pbcq = PNV_PBCQ(opaque); 509ae1329eSCédric Le Goater uint32_t offset = addr >> 3; 519ae1329eSCédric Le Goater 529ae1329eSCédric Le Goater if (offset == PBCQ_SPCI_ASB_DATA) { 539ae1329eSCédric Le Goater return pnv_phb3_reg_read(pbcq->phb, 549ae1329eSCédric Le Goater pbcq->spci_regs[PBCQ_SPCI_ASB_ADDR], 8); 559ae1329eSCédric Le Goater } 569ae1329eSCédric Le Goater return pbcq->spci_regs[offset]; 579ae1329eSCédric Le Goater } 589ae1329eSCédric Le Goater 599ae1329eSCédric Le Goater static void pnv_pbcq_update_map(PnvPBCQState *pbcq) 609ae1329eSCédric Le Goater { 619ae1329eSCédric Le Goater uint64_t bar_en = pbcq->nest_regs[PBCQ_NEST_BAR_EN]; 629ae1329eSCédric Le Goater uint64_t bar, mask, size; 639ae1329eSCédric Le Goater 649ae1329eSCédric Le Goater /* 659ae1329eSCédric Le Goater * NOTE: This will really not work well if those are remapped 669ae1329eSCédric Le Goater * after the PHB has created its sub regions. We could do better 679ae1329eSCédric Le Goater * if we had a way to resize regions but we don't really care 689ae1329eSCédric Le Goater * that much in practice as the stuff below really only happens 699ae1329eSCédric Le Goater * once early during boot 709ae1329eSCédric Le Goater */ 719ae1329eSCédric Le Goater 729ae1329eSCédric Le Goater /* Handle unmaps */ 739ae1329eSCédric Le Goater if (memory_region_is_mapped(&pbcq->mmbar0) && 749ae1329eSCédric Le Goater !(bar_en & PBCQ_NEST_BAR_EN_MMIO0)) { 759ae1329eSCédric Le Goater memory_region_del_subregion(get_system_memory(), &pbcq->mmbar0); 769ae1329eSCédric Le Goater } 779ae1329eSCédric Le Goater if (memory_region_is_mapped(&pbcq->mmbar1) && 789ae1329eSCédric Le Goater !(bar_en & PBCQ_NEST_BAR_EN_MMIO1)) { 799ae1329eSCédric Le Goater memory_region_del_subregion(get_system_memory(), &pbcq->mmbar1); 809ae1329eSCédric Le Goater } 819ae1329eSCédric Le Goater if (memory_region_is_mapped(&pbcq->phbbar) && 829ae1329eSCédric Le Goater !(bar_en & PBCQ_NEST_BAR_EN_PHB)) { 839ae1329eSCédric Le Goater memory_region_del_subregion(get_system_memory(), &pbcq->phbbar); 849ae1329eSCédric Le Goater } 859ae1329eSCédric Le Goater 869ae1329eSCédric Le Goater /* Update PHB */ 879ae1329eSCédric Le Goater pnv_phb3_update_regions(pbcq->phb); 889ae1329eSCédric Le Goater 899ae1329eSCédric Le Goater /* Handle maps */ 909ae1329eSCédric Le Goater if (!memory_region_is_mapped(&pbcq->mmbar0) && 919ae1329eSCédric Le Goater (bar_en & PBCQ_NEST_BAR_EN_MMIO0)) { 929ae1329eSCédric Le Goater bar = pbcq->nest_regs[PBCQ_NEST_MMIO_BAR0] >> 14; 939ae1329eSCédric Le Goater mask = pbcq->nest_regs[PBCQ_NEST_MMIO_MASK0]; 949ae1329eSCédric Le Goater size = ((~mask) >> 14) + 1; 959ae1329eSCédric Le Goater memory_region_init(&pbcq->mmbar0, OBJECT(pbcq), "pbcq-mmio0", size); 969ae1329eSCédric Le Goater memory_region_add_subregion(get_system_memory(), bar, &pbcq->mmbar0); 979ae1329eSCédric Le Goater pbcq->mmio0_base = bar; 989ae1329eSCédric Le Goater pbcq->mmio0_size = size; 999ae1329eSCédric Le Goater } 1009ae1329eSCédric Le Goater if (!memory_region_is_mapped(&pbcq->mmbar1) && 1019ae1329eSCédric Le Goater (bar_en & PBCQ_NEST_BAR_EN_MMIO1)) { 1029ae1329eSCédric Le Goater bar = pbcq->nest_regs[PBCQ_NEST_MMIO_BAR1] >> 14; 1039ae1329eSCédric Le Goater mask = pbcq->nest_regs[PBCQ_NEST_MMIO_MASK1]; 1049ae1329eSCédric Le Goater size = ((~mask) >> 14) + 1; 1059ae1329eSCédric Le Goater memory_region_init(&pbcq->mmbar1, OBJECT(pbcq), "pbcq-mmio1", size); 1069ae1329eSCédric Le Goater memory_region_add_subregion(get_system_memory(), bar, &pbcq->mmbar1); 1079ae1329eSCédric Le Goater pbcq->mmio1_base = bar; 1089ae1329eSCédric Le Goater pbcq->mmio1_size = size; 1099ae1329eSCédric Le Goater } 1109ae1329eSCédric Le Goater if (!memory_region_is_mapped(&pbcq->phbbar) 1119ae1329eSCédric Le Goater && (bar_en & PBCQ_NEST_BAR_EN_PHB)) { 1129ae1329eSCédric Le Goater bar = pbcq->nest_regs[PBCQ_NEST_PHB_BAR] >> 14; 1139ae1329eSCédric Le Goater size = 0x1000; 1149ae1329eSCédric Le Goater memory_region_init(&pbcq->phbbar, OBJECT(pbcq), "pbcq-phb", size); 1159ae1329eSCédric Le Goater memory_region_add_subregion(get_system_memory(), bar, &pbcq->phbbar); 1169ae1329eSCédric Le Goater } 1179ae1329eSCédric Le Goater 1189ae1329eSCédric Le Goater /* Update PHB */ 1199ae1329eSCédric Le Goater pnv_phb3_update_regions(pbcq->phb); 1209ae1329eSCédric Le Goater } 1219ae1329eSCédric Le Goater 1229ae1329eSCédric Le Goater static void pnv_pbcq_nest_xscom_write(void *opaque, hwaddr addr, 1239ae1329eSCédric Le Goater uint64_t val, unsigned size) 1249ae1329eSCédric Le Goater { 1259ae1329eSCédric Le Goater PnvPBCQState *pbcq = PNV_PBCQ(opaque); 1269ae1329eSCédric Le Goater uint32_t reg = addr >> 3; 1279ae1329eSCédric Le Goater 1289ae1329eSCédric Le Goater switch (reg) { 1299ae1329eSCédric Le Goater case PBCQ_NEST_MMIO_BAR0: 1309ae1329eSCédric Le Goater case PBCQ_NEST_MMIO_BAR1: 1319ae1329eSCédric Le Goater case PBCQ_NEST_MMIO_MASK0: 1329ae1329eSCédric Le Goater case PBCQ_NEST_MMIO_MASK1: 1339ae1329eSCédric Le Goater if (pbcq->nest_regs[PBCQ_NEST_BAR_EN] & 1349ae1329eSCédric Le Goater (PBCQ_NEST_BAR_EN_MMIO0 | 1359ae1329eSCédric Le Goater PBCQ_NEST_BAR_EN_MMIO1)) { 1369ae1329eSCédric Le Goater phb3_pbcq_error(pbcq, "Changing enabled BAR unsupported"); 1379ae1329eSCédric Le Goater } 1389ae1329eSCédric Le Goater pbcq->nest_regs[reg] = val & 0xffffffffc0000000ull; 1399ae1329eSCédric Le Goater break; 1409ae1329eSCédric Le Goater case PBCQ_NEST_PHB_BAR: 1419ae1329eSCédric Le Goater if (pbcq->nest_regs[PBCQ_NEST_BAR_EN] & PBCQ_NEST_BAR_EN_PHB) { 1429ae1329eSCédric Le Goater phb3_pbcq_error(pbcq, "Changing enabled BAR unsupported"); 1439ae1329eSCédric Le Goater } 1449ae1329eSCédric Le Goater pbcq->nest_regs[reg] = val & 0xfffffffffc000000ull; 1459ae1329eSCédric Le Goater break; 1469ae1329eSCédric Le Goater case PBCQ_NEST_BAR_EN: 1479ae1329eSCédric Le Goater pbcq->nest_regs[reg] = val & 0xf800000000000000ull; 1489ae1329eSCédric Le Goater pnv_pbcq_update_map(pbcq); 1499ae1329eSCédric Le Goater pnv_phb3_remap_irqs(pbcq->phb); 1509ae1329eSCédric Le Goater break; 1519ae1329eSCédric Le Goater case PBCQ_NEST_IRSN_COMPARE: 1529ae1329eSCédric Le Goater case PBCQ_NEST_IRSN_MASK: 1539ae1329eSCédric Le Goater pbcq->nest_regs[reg] = val & PBCQ_NEST_IRSN_COMP; 1549ae1329eSCédric Le Goater pnv_phb3_remap_irqs(pbcq->phb); 1559ae1329eSCédric Le Goater break; 1569ae1329eSCédric Le Goater case PBCQ_NEST_LSI_SRC_ID: 1579ae1329eSCédric Le Goater pbcq->nest_regs[reg] = val & PBCQ_NEST_LSI_SRC; 1589ae1329eSCédric Le Goater pnv_phb3_remap_irqs(pbcq->phb); 1599ae1329eSCédric Le Goater break; 1609ae1329eSCédric Le Goater default: 1619ae1329eSCédric Le Goater phb3_pbcq_error(pbcq, "%s @0x%"HWADDR_PRIx"=%"PRIx64, __func__, 1629ae1329eSCédric Le Goater addr, val); 1639ae1329eSCédric Le Goater } 1649ae1329eSCédric Le Goater } 1659ae1329eSCédric Le Goater 1669ae1329eSCédric Le Goater static void pnv_pbcq_pci_xscom_write(void *opaque, hwaddr addr, 1679ae1329eSCédric Le Goater uint64_t val, unsigned size) 1689ae1329eSCédric Le Goater { 1699ae1329eSCédric Le Goater PnvPBCQState *pbcq = PNV_PBCQ(opaque); 1709ae1329eSCédric Le Goater uint32_t reg = addr >> 3; 1719ae1329eSCédric Le Goater 1729ae1329eSCédric Le Goater switch (reg) { 1739ae1329eSCédric Le Goater case PBCQ_PCI_BAR2: 1749ae1329eSCédric Le Goater pbcq->pci_regs[reg] = val & 0xfffffffffc000000ull; 1759ae1329eSCédric Le Goater pnv_pbcq_update_map(pbcq); 176*e8ead7d5SGreg Kurz break; 1779ae1329eSCédric Le Goater default: 1789ae1329eSCédric Le Goater phb3_pbcq_error(pbcq, "%s @0x%"HWADDR_PRIx"=%"PRIx64, __func__, 1799ae1329eSCédric Le Goater addr, val); 1809ae1329eSCédric Le Goater } 1819ae1329eSCédric Le Goater } 1829ae1329eSCédric Le Goater 1839ae1329eSCédric Le Goater static void pnv_pbcq_spci_xscom_write(void *opaque, hwaddr addr, 1849ae1329eSCédric Le Goater uint64_t val, unsigned size) 1859ae1329eSCédric Le Goater { 1869ae1329eSCédric Le Goater PnvPBCQState *pbcq = PNV_PBCQ(opaque); 1879ae1329eSCédric Le Goater uint32_t reg = addr >> 3; 1889ae1329eSCédric Le Goater 1899ae1329eSCédric Le Goater switch (reg) { 1909ae1329eSCédric Le Goater case PBCQ_SPCI_ASB_ADDR: 1919ae1329eSCédric Le Goater pbcq->spci_regs[reg] = val & 0xfff; 1929ae1329eSCédric Le Goater break; 1939ae1329eSCédric Le Goater case PBCQ_SPCI_ASB_STATUS: 1949ae1329eSCédric Le Goater pbcq->spci_regs[reg] &= ~val; 1959ae1329eSCédric Le Goater break; 1969ae1329eSCédric Le Goater case PBCQ_SPCI_ASB_DATA: 1979ae1329eSCédric Le Goater pnv_phb3_reg_write(pbcq->phb, pbcq->spci_regs[PBCQ_SPCI_ASB_ADDR], 1989ae1329eSCédric Le Goater val, 8); 1999ae1329eSCédric Le Goater break; 2009ae1329eSCédric Le Goater case PBCQ_SPCI_AIB_CAPP_EN: 2019ae1329eSCédric Le Goater case PBCQ_SPCI_CAPP_SEC_TMR: 2029ae1329eSCédric Le Goater break; 2039ae1329eSCédric Le Goater default: 2049ae1329eSCédric Le Goater phb3_pbcq_error(pbcq, "%s @0x%"HWADDR_PRIx"=%"PRIx64, __func__, 2059ae1329eSCédric Le Goater addr, val); 2069ae1329eSCédric Le Goater } 2079ae1329eSCédric Le Goater } 2089ae1329eSCédric Le Goater 2099ae1329eSCédric Le Goater static const MemoryRegionOps pnv_pbcq_nest_xscom_ops = { 2109ae1329eSCédric Le Goater .read = pnv_pbcq_nest_xscom_read, 2119ae1329eSCédric Le Goater .write = pnv_pbcq_nest_xscom_write, 2129ae1329eSCédric Le Goater .valid.min_access_size = 8, 2139ae1329eSCédric Le Goater .valid.max_access_size = 8, 2149ae1329eSCédric Le Goater .impl.min_access_size = 8, 2159ae1329eSCédric Le Goater .impl.max_access_size = 8, 2169ae1329eSCédric Le Goater .endianness = DEVICE_BIG_ENDIAN, 2179ae1329eSCédric Le Goater }; 2189ae1329eSCédric Le Goater 2199ae1329eSCédric Le Goater static const MemoryRegionOps pnv_pbcq_pci_xscom_ops = { 2209ae1329eSCédric Le Goater .read = pnv_pbcq_pci_xscom_read, 2219ae1329eSCédric Le Goater .write = pnv_pbcq_pci_xscom_write, 2229ae1329eSCédric Le Goater .valid.min_access_size = 8, 2239ae1329eSCédric Le Goater .valid.max_access_size = 8, 2249ae1329eSCédric Le Goater .impl.min_access_size = 8, 2259ae1329eSCédric Le Goater .impl.max_access_size = 8, 2269ae1329eSCédric Le Goater .endianness = DEVICE_BIG_ENDIAN, 2279ae1329eSCédric Le Goater }; 2289ae1329eSCédric Le Goater 2299ae1329eSCédric Le Goater static const MemoryRegionOps pnv_pbcq_spci_xscom_ops = { 2309ae1329eSCédric Le Goater .read = pnv_pbcq_spci_xscom_read, 2319ae1329eSCédric Le Goater .write = pnv_pbcq_spci_xscom_write, 2329ae1329eSCédric Le Goater .valid.min_access_size = 8, 2339ae1329eSCédric Le Goater .valid.max_access_size = 8, 2349ae1329eSCédric Le Goater .impl.min_access_size = 8, 2359ae1329eSCédric Le Goater .impl.max_access_size = 8, 2369ae1329eSCédric Le Goater .endianness = DEVICE_BIG_ENDIAN, 2379ae1329eSCédric Le Goater }; 2389ae1329eSCédric Le Goater 2399ae1329eSCédric Le Goater static void pnv_pbcq_default_bars(PnvPBCQState *pbcq) 2409ae1329eSCédric Le Goater { 2419ae1329eSCédric Le Goater uint64_t mm0, mm1, reg; 2429ae1329eSCédric Le Goater PnvPHB3 *phb = pbcq->phb; 2439ae1329eSCédric Le Goater 2449ae1329eSCédric Le Goater mm0 = 0x3d00000000000ull + 0x4000000000ull * phb->chip_id + 2459ae1329eSCédric Le Goater 0x1000000000ull * phb->phb_id; 2469ae1329eSCédric Le Goater mm1 = 0x3ff8000000000ull + 0x0200000000ull * phb->chip_id + 2479ae1329eSCédric Le Goater 0x0080000000ull * phb->phb_id; 2489ae1329eSCédric Le Goater reg = 0x3fffe40000000ull + 0x0000400000ull * phb->chip_id + 2499ae1329eSCédric Le Goater 0x0000100000ull * phb->phb_id; 2509ae1329eSCédric Le Goater 2519ae1329eSCédric Le Goater pbcq->nest_regs[PBCQ_NEST_MMIO_BAR0] = mm0 << 14; 2529ae1329eSCédric Le Goater pbcq->nest_regs[PBCQ_NEST_MMIO_BAR1] = mm1 << 14; 2539ae1329eSCédric Le Goater pbcq->nest_regs[PBCQ_NEST_PHB_BAR] = reg << 14; 2549ae1329eSCédric Le Goater pbcq->nest_regs[PBCQ_NEST_MMIO_MASK0] = 0x3fff000000000ull << 14; 2559ae1329eSCédric Le Goater pbcq->nest_regs[PBCQ_NEST_MMIO_MASK1] = 0x3ffff80000000ull << 14; 2569ae1329eSCédric Le Goater pbcq->pci_regs[PBCQ_PCI_BAR2] = reg << 14; 2579ae1329eSCédric Le Goater } 2589ae1329eSCédric Le Goater 2599ae1329eSCédric Le Goater static void pnv_pbcq_realize(DeviceState *dev, Error **errp) 2609ae1329eSCédric Le Goater { 2619ae1329eSCédric Le Goater PnvPBCQState *pbcq = PNV_PBCQ(dev); 2629ae1329eSCédric Le Goater PnvPHB3 *phb; 2639ae1329eSCédric Le Goater char name[32]; 2649ae1329eSCédric Le Goater 2659ae1329eSCédric Le Goater assert(pbcq->phb); 2669ae1329eSCédric Le Goater phb = pbcq->phb; 2679ae1329eSCédric Le Goater 2689ae1329eSCédric Le Goater /* TODO: Fix OPAL to do that: establish default BAR values */ 2699ae1329eSCédric Le Goater pnv_pbcq_default_bars(pbcq); 2709ae1329eSCédric Le Goater 2719ae1329eSCédric Le Goater /* Initialize the XSCOM region for the PBCQ registers */ 2729ae1329eSCédric Le Goater snprintf(name, sizeof(name), "xscom-pbcq-nest-%d.%d", 2739ae1329eSCédric Le Goater phb->chip_id, phb->phb_id); 2749ae1329eSCédric Le Goater pnv_xscom_region_init(&pbcq->xscom_nest_regs, OBJECT(dev), 2759ae1329eSCédric Le Goater &pnv_pbcq_nest_xscom_ops, pbcq, name, 2769ae1329eSCédric Le Goater PNV_XSCOM_PBCQ_NEST_SIZE); 2779ae1329eSCédric Le Goater snprintf(name, sizeof(name), "xscom-pbcq-pci-%d.%d", 2789ae1329eSCédric Le Goater phb->chip_id, phb->phb_id); 2799ae1329eSCédric Le Goater pnv_xscom_region_init(&pbcq->xscom_pci_regs, OBJECT(dev), 2809ae1329eSCédric Le Goater &pnv_pbcq_pci_xscom_ops, pbcq, name, 2819ae1329eSCédric Le Goater PNV_XSCOM_PBCQ_PCI_SIZE); 2829ae1329eSCédric Le Goater snprintf(name, sizeof(name), "xscom-pbcq-spci-%d.%d", 2839ae1329eSCédric Le Goater phb->chip_id, phb->phb_id); 2849ae1329eSCédric Le Goater pnv_xscom_region_init(&pbcq->xscom_spci_regs, OBJECT(dev), 2859ae1329eSCédric Le Goater &pnv_pbcq_spci_xscom_ops, pbcq, name, 2869ae1329eSCédric Le Goater PNV_XSCOM_PBCQ_SPCI_SIZE); 2879ae1329eSCédric Le Goater } 2889ae1329eSCédric Le Goater 2899ae1329eSCédric Le Goater static int pnv_pbcq_dt_xscom(PnvXScomInterface *dev, void *fdt, 2909ae1329eSCédric Le Goater int xscom_offset) 2919ae1329eSCédric Le Goater { 2929ae1329eSCédric Le Goater const char compat[] = "ibm,power8-pbcq"; 2939ae1329eSCédric Le Goater PnvPHB3 *phb = PNV_PBCQ(dev)->phb; 2949ae1329eSCédric Le Goater char *name; 2959ae1329eSCédric Le Goater int offset; 2969ae1329eSCédric Le Goater uint32_t lpc_pcba = PNV_XSCOM_PBCQ_NEST_BASE + 0x400 * phb->phb_id; 2979ae1329eSCédric Le Goater uint32_t reg[] = { 2989ae1329eSCédric Le Goater cpu_to_be32(lpc_pcba), 2999ae1329eSCédric Le Goater cpu_to_be32(PNV_XSCOM_PBCQ_NEST_SIZE), 3009ae1329eSCédric Le Goater cpu_to_be32(PNV_XSCOM_PBCQ_PCI_BASE + 0x400 * phb->phb_id), 3019ae1329eSCédric Le Goater cpu_to_be32(PNV_XSCOM_PBCQ_PCI_SIZE), 3029ae1329eSCédric Le Goater cpu_to_be32(PNV_XSCOM_PBCQ_SPCI_BASE + 0x040 * phb->phb_id), 3039ae1329eSCédric Le Goater cpu_to_be32(PNV_XSCOM_PBCQ_SPCI_SIZE) 3049ae1329eSCédric Le Goater }; 3059ae1329eSCédric Le Goater 3069ae1329eSCédric Le Goater name = g_strdup_printf("pbcq@%x", lpc_pcba); 3079ae1329eSCédric Le Goater offset = fdt_add_subnode(fdt, xscom_offset, name); 3089ae1329eSCédric Le Goater _FDT(offset); 3099ae1329eSCédric Le Goater g_free(name); 3109ae1329eSCédric Le Goater 3119ae1329eSCédric Le Goater _FDT((fdt_setprop(fdt, offset, "reg", reg, sizeof(reg)))); 3129ae1329eSCédric Le Goater 3139ae1329eSCédric Le Goater _FDT((fdt_setprop_cell(fdt, offset, "ibm,phb-index", phb->phb_id))); 3149ae1329eSCédric Le Goater _FDT((fdt_setprop_cell(fdt, offset, "ibm,chip-id", phb->chip_id))); 3159ae1329eSCédric Le Goater _FDT((fdt_setprop(fdt, offset, "compatible", compat, 3169ae1329eSCédric Le Goater sizeof(compat)))); 3179ae1329eSCédric Le Goater return 0; 3189ae1329eSCédric Le Goater } 3199ae1329eSCédric Le Goater 3209ae1329eSCédric Le Goater static void phb3_pbcq_instance_init(Object *obj) 3219ae1329eSCédric Le Goater { 3229ae1329eSCédric Le Goater PnvPBCQState *pbcq = PNV_PBCQ(obj); 3239ae1329eSCédric Le Goater 3249ae1329eSCédric Le Goater object_property_add_link(obj, "phb", TYPE_PNV_PHB3, 3259ae1329eSCédric Le Goater (Object **)&pbcq->phb, 3269ae1329eSCédric Le Goater object_property_allow_set_link, 3279ae1329eSCédric Le Goater OBJ_PROP_LINK_STRONG, 3289ae1329eSCédric Le Goater &error_abort); 3299ae1329eSCédric Le Goater } 3309ae1329eSCédric Le Goater 3319ae1329eSCédric Le Goater static void pnv_pbcq_class_init(ObjectClass *klass, void *data) 3329ae1329eSCédric Le Goater { 3339ae1329eSCédric Le Goater DeviceClass *dc = DEVICE_CLASS(klass); 3349ae1329eSCédric Le Goater PnvXScomInterfaceClass *xdc = PNV_XSCOM_INTERFACE_CLASS(klass); 3359ae1329eSCédric Le Goater 3369ae1329eSCédric Le Goater xdc->dt_xscom = pnv_pbcq_dt_xscom; 3379ae1329eSCédric Le Goater 3389ae1329eSCédric Le Goater dc->realize = pnv_pbcq_realize; 33923a782ebSCédric Le Goater dc->user_creatable = false; 3409ae1329eSCédric Le Goater } 3419ae1329eSCédric Le Goater 3429ae1329eSCédric Le Goater static const TypeInfo pnv_pbcq_type_info = { 3439ae1329eSCédric Le Goater .name = TYPE_PNV_PBCQ, 3449ae1329eSCédric Le Goater .parent = TYPE_DEVICE, 3459ae1329eSCédric Le Goater .instance_size = sizeof(PnvPBCQState), 3469ae1329eSCédric Le Goater .instance_init = phb3_pbcq_instance_init, 3479ae1329eSCédric Le Goater .class_init = pnv_pbcq_class_init, 3489ae1329eSCédric Le Goater .interfaces = (InterfaceInfo[]) { 3499ae1329eSCédric Le Goater { TYPE_PNV_XSCOM_INTERFACE }, 3509ae1329eSCédric Le Goater { } 3519ae1329eSCédric Le Goater } 3529ae1329eSCédric Le Goater }; 3539ae1329eSCédric Le Goater 3549ae1329eSCédric Le Goater static void pnv_pbcq_register_types(void) 3559ae1329eSCédric Le Goater { 3569ae1329eSCédric Le Goater type_register_static(&pnv_pbcq_type_info); 3579ae1329eSCédric Le Goater } 3589ae1329eSCédric Le Goater 3599ae1329eSCédric Le Goater type_init(pnv_pbcq_register_types) 360