diff options
author | Benjamin Herrenschmidt <benh@kernel.crashing.org> | 2017-06-24 14:17:06 -0500 |
---|---|---|
committer | Stewart Smith <stewart@linux.vnet.ibm.com> | 2017-06-26 14:28:58 +1000 |
commit | c890a1ff25617a628d3a83d514c8dc4bcffac797 (patch) | |
tree | 36dd66ab494b211f8d314ff7265707742ba91d65 /hw | |
parent | 8019007766da1a09b0280d37ab9e5aa4df396e7f (diff) | |
download | skiboot-c890a1ff25617a628d3a83d514c8dc4bcffac797.zip skiboot-c890a1ff25617a628d3a83d514c8dc4bcffac797.tar.gz skiboot-c890a1ff25617a628d3a83d514c8dc4bcffac797.tar.bz2 |
xive: DD2.0 updates
Add support for StoreEOI, fix StoreEOI MMIO offset in ESB page,
and other cleanups
Signed-off-by: Benjamin Herrenschmidt <benh@kernel.crashing.org>
Signed-off-by: Michael Neuling <mikey@neuling.org>
Signed-off-by: Stewart Smith <stewart@linux.vnet.ibm.com>
Diffstat (limited to 'hw')
-rw-r--r-- | hw/xive.c | 56 |
1 files changed, 48 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, |