aboutsummaryrefslogtreecommitdiff
path: root/core/interrupts.c
diff options
context:
space:
mode:
authorAlistair Popple <alistair@popple.id.au>2015-09-15 11:20:05 +1000
committerStewart Smith <stewart@linux.vnet.ibm.com>2015-10-08 14:17:00 +1100
commitb4315f5520cb99312e139d55289a012af14ad042 (patch)
treee009d4fd14cda6c4ed00ac2dc32bcdb7d305b297 /core/interrupts.c
parentdc3d17ac940fe1e0b2723a31d171ab47fd68fd47 (diff)
downloadskiboot-b4315f5520cb99312e139d55289a012af14ad042.zip
skiboot-b4315f5520cb99312e139d55289a012af14ad042.tar.gz
skiboot-b4315f5520cb99312e139d55289a012af14ad042.tar.bz2
interrupts: Convert P8 IRQ assignment to functions
Interrupts on P8 are currently hard-coded using macros in include/interrupts.h. The new P8NVL processor has an extra PHB meaning it supports 4 PHBs in total which leads to the following assert fail when booting P8NVL based systems: [6614913194,3] register IRQ source overlap ! [6620562844,3] new: 2000..27f7 old: 2000..27f7 [6870377440,0] Assert fail: core/interrupts.c:67:0 This patch converts the existing macros to function calls so that different platforms can support extra PHBs at the expense of a reduced maximum number of chips. Signed-off-by: Alistair Popple <alistair@popple.id.au> Signed-off-by: Stewart Smith <stewart@linux.vnet.ibm.com>
Diffstat (limited to 'core/interrupts.c')
-rw-r--r--core/interrupts.c86
1 files changed, 85 insertions, 1 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;