diff options
-rw-r--r-- | hw/xive.c | 56 | ||||
-rw-r--r-- | include/xive.h | 7 |
2 files changed, 55 insertions, 8 deletions
@@ -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 */ |