diff options
-rw-r--r-- | core/interrupts.c | 86 | ||||
-rw-r--r-- | hw/phb3.c | 18 | ||||
-rw-r--r-- | include/interrupts.h | 42 | ||||
-rw-r--r-- | include/phb3.h | 4 |
4 files changed, 120 insertions, 30 deletions
diff --git a/core/interrupts.c b/core/interrupts.c index 32f43ef..6ed2e9a 100644 --- a/core/interrupts.c +++ b/core/interrupts.c @@ -15,6 +15,7 @@ */ #include <skiboot.h> +#include <chip.h> #include <cpu.h> #include <fsp.h> #include <interrupts.h> @@ -121,7 +122,7 @@ uint32_t get_psi_interrupt(uint32_t chip_id) irq |= P7_PSI_IRQ_BUID << 4; break; case proc_gen_p8: - irq = P8_CHIP_IRQ_BLOCK_BASE(chip_id, P8_IRQ_BLOCK_MISC); + irq = p8_chip_irq_block_base(chip_id, P8_IRQ_BLOCK_MISC); irq += P8_IRQ_MISC_PSI_BASE; break; default: @@ -253,6 +254,89 @@ void icp_kick_cpu(struct cpu_thread *cpu) out_8(icp + ICP_MFRR, 0); } +/* Returns the number of chip ID bits used for interrupt numbers */ +static uint32_t p8_chip_id_bits(uint32_t chip) +{ + struct proc_chip *proc_chip = get_chip(chip); + + assert(proc_chip); + switch (proc_chip->type) { + case PROC_CHIP_P8_MURANO: + case PROC_CHIP_P8_VENICE: + return 6; + break; + + case PROC_CHIP_P8_NAPLES: + return 5; + break; + + default: + /* This shouldn't be called on non-P8 based systems */ + assert(0); + return 0; + break; + } +} + +/* The chip id mask is the upper p8_chip_id_bits of the irq number */ +static uint32_t chip_id_mask(uint32_t chip) +{ + uint32_t chip_id_bits = p8_chip_id_bits(chip); + uint32_t chip_id_mask; + + chip_id_mask = ((1 << chip_id_bits) - 1); + chip_id_mask <<= P8_IRQ_BITS - chip_id_bits; + return chip_id_mask; +} + +/* The block mask is what remains of the 19 bit irq number after + * removing the upper 5 or 6 bits for the chip# and the lower 11 bits + * for the number of bits per block. */ +static uint32_t block_mask(uint32_t chip) +{ + uint32_t chip_id_bits = p8_chip_id_bits(chip); + uint32_t irq_block_mask; + + irq_block_mask = P8_IRQ_BITS - chip_id_bits - P8_IVE_BITS; + irq_block_mask = ((1 << irq_block_mask) - 1) << P8_IVE_BITS; + return irq_block_mask; +} + +uint32_t p8_chip_irq_block_base(uint32_t chip, uint32_t block) +{ + uint32_t irq; + + assert(chip < (1 << p8_chip_id_bits(chip))); + irq = SETFIELD(chip_id_mask(chip), 0, chip); + irq = SETFIELD(block_mask(chip), irq, block); + + return irq; +} + +uint32_t p8_chip_irq_phb_base(uint32_t chip, uint32_t phb) +{ + assert(chip < (1 << p8_chip_id_bits(chip))); + + return p8_chip_irq_block_base(chip, phb + P8_IRQ_BLOCK_PHB_BASE); +} + +uint32_t p8_irq_to_chip(uint32_t irq) +{ + /* This assumes we only have one type of cpu in a system, + * which should be ok. */ + return GETFIELD(chip_id_mask(this_cpu()->chip_id), irq); +} + +uint32_t p8_irq_to_block(uint32_t irq) +{ + return GETFIELD(block_mask(this_cpu()->chip_id), irq); +} + +uint32_t p8_irq_to_phb(uint32_t irq) +{ + return p8_irq_to_block(irq) - P8_IRQ_BLOCK_PHB_BASE; +} + static struct irq_source *irq_find_source(uint32_t isn) { struct irq_source *is; @@ -1550,8 +1550,8 @@ static int64_t phb3_msi_get_xive(void *data, uint32_t chip, index, irq; uint64_t ive; - chip = P8_IRQ_TO_CHIP(isn); - index = P8_IRQ_TO_PHB(isn); + chip = p8_irq_to_chip(isn); + index = p8_irq_to_phb(isn); irq = PHB3_IRQ_NUM(isn); if (chip != p->chip_id || @@ -1580,8 +1580,8 @@ static int64_t phb3_msi_set_xive(void *data, uint64_t *cache, ive_num, data64, m_server, m_prio; uint32_t *ive; - chip = P8_IRQ_TO_CHIP(isn); - index = P8_IRQ_TO_PHB(isn); + chip = p8_irq_to_chip(isn); + index = p8_irq_to_phb(isn); ive_num = PHB3_IRQ_NUM(isn); if (p->state == PHB3_STATE_BROKEN || !p->tbl_rtt) @@ -1642,8 +1642,8 @@ static int64_t phb3_lsi_get_xive(void *data, uint32_t chip, index, irq; uint64_t lxive; - chip = P8_IRQ_TO_CHIP(isn); - index = P8_IRQ_TO_PHB(isn); + chip = p8_irq_to_chip(isn); + index = p8_irq_to_phb(isn); irq = PHB3_IRQ_NUM(isn); if (chip != p->chip_id || @@ -1668,8 +1668,8 @@ static int64_t phb3_lsi_set_xive(void *data, uint32_t chip, index, irq, entry; uint64_t lxive; - chip = P8_IRQ_TO_CHIP(isn); - index = P8_IRQ_TO_PHB(isn); + chip = p8_irq_to_chip(isn); + index = p8_irq_to_phb(isn); irq = PHB3_IRQ_NUM(isn); if (p->state == PHB3_STATE_BROKEN) @@ -4479,7 +4479,7 @@ static void phb3_probe_pbcq(struct dt_node *pbcq) /* Set the interrupt routing stuff, 8 relevant bits in mask * (11 bits per PHB) */ - val = P8_CHIP_IRQ_PHB_BASE(gcid, pno); + val = p8_chip_irq_phb_base(gcid, pno); val = (val << 45); xscom_write(gcid, pe_xscom + 0x1a, val); xscom_write(gcid, pe_xscom + 0x1b, 0xff00000000000000ul); diff --git a/include/interrupts.h b/include/interrupts.h index 9239b86..d144dcd 100644 --- a/include/interrupts.h +++ b/include/interrupts.h @@ -152,19 +152,26 @@ * are naturally power-of-two aligned * * Our P8 Interrupt map consits thus of dividing the chip space - * into 4 "blocks" of 2048 interrupts. Block 0 is for random chip + * into "blocks" of 2048 interrupts. Block 0 is for random chip * interrupt sources (NX, PSI, OCC, ...) and keeps sources 0..15 - * clear to avoid conflits with IPIs etc.... Block 1..3 are assigned - * to PHB 0..2 respectively. + * clear to avoid conflits with IPIs etc.... Block 1..n are assigned + * to PHB 0..n respectively. The number of blocks is determined by the + * number of bits assigned to chips. * * That gives us an interrupt number made of: - * 18 13 12 11 10 0 + * 18 n+1 n 11 10 0 * | | | | | | * +--------------------+------+-----------------------------+ * | Chip# | PHB# | IVE# | * +--------------------+------+-----------------------------+ * - * We can thus support a max of 2^6 = 64 chips + * Where n = 18 - p8_chip_id_bits + * + * For P8 we have 6 bits for Chip# as defined by p8_chip_id_bits. We + * therefore support a max of 2^6 = 64 chips. + * + * For P8NVL we have an extra PHB and so we assign 5 bits for Chip# + * and therefore support a max of 32 chips. * * Each PHB supports 2K interrupt sources, which is shared by * LSI and MSI. With default configuration, MSI would use range @@ -174,21 +181,20 @@ * */ -#define P8_CHIP_IRQ_BASE(chip) ((chip) << 13) -#define P8_CHIP_IRQ_BLOCK_BASE(chip, block) (P8_CHIP_IRQ_BASE(chip) \ - | ((block) << 11)) -#define P8_IRQ_BLOCK_MISC 0 -#define P8_IRQ_BLOCK_PHB0 1 -#define P8_IRQ_BLOCK_PHB1 2 -#define P8_IRQ_BLOCK_PHB2 3 +uint32_t p8_chip_irq_block_base(uint32_t chip, uint32_t block); +uint32_t p8_chip_irq_phb_base(uint32_t chip, uint32_t phb); +uint32_t p8_irq_to_chip(uint32_t irq); +uint32_t p8_irq_to_block(uint32_t irq); +uint32_t p8_irq_to_phb(uint32_t irq); -#define P8_CHIP_IRQ_PHB_BASE(chip, phb) (P8_CHIP_IRQ_BLOCK_BASE(chip,\ - (phb) + P8_IRQ_BLOCK_PHB0)) +/* Total number of bits in the P8 interrupt space */ +#define P8_IRQ_BITS 19 -#define P8_IRQ_TO_CHIP(irq) (((irq) >> 13) & 0x3f) -#define P8_IRQ_TO_BLOCK(irq) (((irq) >> 11) & 0x03) -#define P8_IRQ_TO_PHB(irq) (P8_IRQ_TO_BLOCK(irq) - \ - P8_IRQ_BLOCK_PHB0) +/* Number of bits per block */ +#define P8_IVE_BITS 11 + +#define P8_IRQ_BLOCK_MISC 0 +#define P8_IRQ_BLOCK_PHB_BASE 1 /* Assignment of the "MISC" block: * ------------------------------- diff --git a/include/phb3.h b/include/phb3.h index b2aae15..44ac52b 100644 --- a/include/phb3.h +++ b/include/phb3.h @@ -52,9 +52,9 @@ #define PHB3_LSI_IRQ_COUNT 8 #define PHB3_LSI_IRQ_MAX (PHB3_LSI_IRQ_MIN+PHB3_LSI_IRQ_COUNT-1) -#define PHB3_MSI_IRQ_BASE(chip, phb) (P8_CHIP_IRQ_PHB_BASE(chip, phb) | \ +#define PHB3_MSI_IRQ_BASE(chip, phb) (p8_chip_irq_phb_base(chip, phb) | \ PHB3_MSI_IRQ_MIN) -#define PHB3_LSI_IRQ_BASE(chip, phb) (P8_CHIP_IRQ_PHB_BASE(chip, phb) | \ +#define PHB3_LSI_IRQ_BASE(chip, phb) (p8_chip_irq_phb_base(chip, phb) | \ PHB3_LSI_IRQ_MIN) #define PHB3_IRQ_NUM(irq) (irq & 0x7FF) |