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