aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--hw/xive.c56
-rw-r--r--include/xive.h7
2 files changed, 55 insertions, 8 deletions
diff --git a/hw/xive.c b/hw/xive.c
index d69390e..fe4915b 100644
--- a/hw/xive.c
+++ b/hw/xive.c
@@ -353,6 +353,10 @@ struct xive {
uint32_t chip_id;
uint32_t block_id;
struct dt_node *x_node;
+ int rev;
+#define XIVE_REV_UNKNOWN 0 /* Unknown version */
+#define XIVE_REV_1 1 /* P9 (Nimbus) DD1.x */
+#define XIVE_REV_2 2 /* P9 (Nimbus) DD2.x or Cumulus */
uint64_t xscom_base;
@@ -488,6 +492,7 @@ static struct dt_node *xive_dt_node;
static uint32_t xive_block_to_chip[XIVE_MAX_CHIPS];
static uint32_t xive_block_count;
+#ifdef USE_BLOCK_GROUP_MODE
static uint32_t xive_chip_to_block(uint32_t chip_id)
{
struct proc_chip *c = get_chip(chip_id);
@@ -496,6 +501,7 @@ static uint32_t xive_chip_to_block(uint32_t chip_id)
assert(c->xive);
return c->xive->block_id;
}
+#endif
/* Conversion between GIRQ and block/index.
*
@@ -1678,20 +1684,37 @@ static bool xive_config_init(struct xive *x)
val = xive_regr(x, VC_GLOBAL_CONFIG);
val |= VC_GCONF_INDIRECT;
xive_regw(x, VC_GLOBAL_CONFIG, val);
+#endif
/* Enable indirect mode in PC config */
val = xive_regr(x, PC_GLOBAL_CONFIG);
+#ifdef USE_INDIRECT
val |= PC_GCONF_INDIRECT;
- xive_regw(x, PC_GLOBAL_CONFIG, val);
#endif
+ val |= PC_GCONF_CHIPID_OVR;
+ val = SETFIELD(PC_GCONF_CHIPID, val, x->block_id);
+ xive_regw(x, PC_GLOBAL_CONFIG, val);
+ xive_dbg(x, "PC_GLOBAL_CONFIG=%016llx\n", val);
val = xive_regr(x, PC_TCTXT_CFG);
#ifdef USE_BLOCK_GROUP_MODE
val |= PC_TCTXT_CFG_BLKGRP_EN | PC_TCTXT_CFG_HARD_CHIPID_BLK;
#endif
val |= PC_TCTXT_CHIPID_OVERRIDE;
+ val |= PC_TCTXT_CFG_TARGET_EN;
val = SETFIELD(PC_TCTXT_CHIPID, val, x->block_id);
xive_regw(x, PC_TCTXT_CFG, val);
+ xive_dbg(x, "PC_TCTXT_CFG=%016llx\n", val);
+
+ /* Subsequent inits are DD2 only */
+ if (x->rev < XIVE_REV_2)
+ return true;
+
+ /* Enable StoreEOI */
+ val = xive_regr(x, VC_SBC_CONFIG);
+ val |= VC_SBC_CONF_CPLX_CIST | VC_SBC_CONF_CIST_BOTH;
+ val |= VC_SBC_CONF_NO_UPD_PRF;
+ xive_regw(x, VC_SBC_CONFIG, val);
return true;
}
@@ -2562,7 +2585,7 @@ void __xive_source_eoi(struct irq_source *is, uint32_t isn)
/* If the XIVE supports the new "store EOI facility, use it */
if (s->flags & XIVE_SRC_STORE_EOI)
- out_be64(mmio_base, 0);
+ out_be64(mmio_base + 0x400, 0);
else {
uint64_t offset;
@@ -2682,6 +2705,7 @@ void xive_register_ipi_source(uint32_t base, uint32_t count, void *data,
struct xive *x = xive_from_isn(base);
uint32_t base_idx = GIRQ_TO_IDX(base);
void *mmio_base;
+ uint32_t flags = XIVE_SRC_EOI_PAGE1 | XIVE_SRC_TRIGGER_PAGE;
assert(x);
assert(base >= x->int_base && (base + count) <= x->int_ipi_top);
@@ -2689,19 +2713,23 @@ void xive_register_ipi_source(uint32_t base, uint32_t count, void *data,
s = malloc(sizeof(struct xive_src));
assert(s);
+ /* Store EOI supported on DD2.0 */
+ if (x->rev >= XIVE_REV_2)
+ flags |= XIVE_SRC_STORE_EOI;
+
/* Callbacks assume the MMIO base corresponds to the first
* interrupt of that source structure so adjust it
*/
mmio_base = x->esb_mmio + (1ul << IPI_ESB_SHIFT) * base_idx;
__xive_register_source(x, s, base, count, IPI_ESB_SHIFT, mmio_base,
- XIVE_SRC_EOI_PAGE1 | XIVE_SRC_TRIGGER_PAGE,
- false, data, ops);
+ flags, false, data, ops);
}
static struct xive *init_one_xive(struct dt_node *np)
{
struct xive *x;
struct proc_chip *chip;
+ uint32_t flags;
x = zalloc(sizeof(struct xive));
assert(x);
@@ -2717,7 +2745,18 @@ static struct xive *init_one_xive(struct dt_node *np)
chip = get_chip(x->chip_id);
assert(chip);
- xive_dbg(x, "Initializing, block ID %d...\n", x->block_id);
+
+ x->rev = XIVE_REV_UNKNOWN;
+ if (chip->type == PROC_CHIP_P9_NIMBUS) {
+ if ((chip->ec_level & 0xf0) == 0x10)
+ x->rev = XIVE_REV_1;
+ else if ((chip->ec_level & 0xf0) == 0x20)
+ x->rev = XIVE_REV_2;
+ } else if (chip->type == PROC_CHIP_P9_CUMULUS)
+ x->rev = XIVE_REV_2;
+
+ xive_dbg(x, "Initializing rev %d block ID %d...\n",
+ x->rev, x->block_id);
chip->xive = x;
#ifdef USE_INDIRECT
@@ -2781,11 +2820,12 @@ static struct xive *init_one_xive(struct dt_node *np)
goto fail;
/* Register built-in source controllers (aka IPIs) */
+ flags = XIVE_SRC_EOI_PAGE1 | XIVE_SRC_TRIGGER_PAGE;
+ if (x->rev >= XIVE_REV_2)
+ flags |= XIVE_SRC_STORE_EOI;
__xive_register_source(x, &x->ipis, x->int_base,
x->int_hw_bot - x->int_base, IPI_ESB_SHIFT,
- x->esb_mmio,
- XIVE_SRC_EOI_PAGE1 | XIVE_SRC_TRIGGER_PAGE,
- true, NULL, NULL);
+ x->esb_mmio, flags, true, NULL, NULL);
/* Register escalation sources */
__xive_register_source(x, &x->esc_irqs,
diff --git a/include/xive.h b/include/xive.h
index d2ef1d9..bddb99c 100644
--- a/include/xive.h
+++ b/include/xive.h
@@ -74,6 +74,7 @@
#define X_PC_TCTXT_CFG 0x100
#define PC_TCTXT_CFG 0x400
#define PC_TCTXT_CFG_BLKGRP_EN PPC_BIT(0)
+#define PC_TCTXT_CFG_TARGET_EN PPC_BIT(1)
#define PC_TCTXT_CFG_HARD_CHIPID_BLK PPC_BIT(8)
#define PC_TCTXT_CHIPID_OVERRIDE PPC_BIT(9)
#define PC_TCTXT_CHIPID PPC_BITMASK(12,15)
@@ -102,6 +103,8 @@
#define X_PC_GLOBAL_CONFIG 0x110
#define PC_GLOBAL_CONFIG 0x480
#define PC_GCONF_INDIRECT PPC_BIT(32)
+#define PC_GCONF_CHIPID_OVR PPC_BIT(40)
+#define PC_GCONF_CHIPID PPC_BITMASK(44,47)
#define X_PC_VSD_TABLE_ADDR 0x111
#define PC_VSD_TABLE_ADDR 0x488
#define X_PC_VSD_TABLE_DATA 0x112
@@ -225,6 +228,10 @@
#define VC_SBC_CACHE_SCRUB_TRIG 0xa10
#define VC_SBC_CACHE_SCRUB_MASK 0xa18
#define VC_SBC_CONFIG 0xa20
+#define X_VC_SBC_CONFIG 0x234
+#define VC_SBC_CONF_CPLX_CIST PPC_BIT(44)
+#define VC_SBC_CONF_CIST_BOTH PPC_BIT(45)
+#define VC_SBC_CONF_NO_UPD_PRF PPC_BIT(59)
/* VC1 register offsets */