aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--hw/npu2-common.c102
-rw-r--r--hw/npu2.c100
2 files changed, 102 insertions, 100 deletions
diff --git a/hw/npu2-common.c b/hw/npu2-common.c
index 3d0b636..b0d55f5 100644
--- a/hw/npu2-common.c
+++ b/hw/npu2-common.c
@@ -22,6 +22,12 @@
#include <bitutils.h>
#include <nvram.h>
#include <i2c.h>
+#include <interrupts.h>
+#include <xive.h>
+
+#define NPU2_IRQ_BASE_SHIFT 13
+#define NPU2_N_DL_IRQS 23
+#define NPU2_N_DL_IRQS_ALIGN 64
/*
* We use the indirect method because it uses the same addresses as
@@ -97,6 +103,99 @@ void npu2_write_mask_4b(struct npu2 *p, uint64_t reg, uint32_t val, uint32_t mas
(uint64_t)new_val << 32);
}
+static uint64_t npu2_ipi_attributes(struct irq_source *is __unused, uint32_t isn __unused)
+{
+ struct npu2 *p = is->data;
+ uint32_t idx = isn - p->base_lsi;
+
+ if (idx == 18)
+ /* TCE Interrupt - used to detect a frozen PE */
+ return IRQ_ATTR_TARGET_OPAL | IRQ_ATTR_TARGET_RARE | IRQ_ATTR_TYPE_MSI;
+ else
+ return IRQ_ATTR_TARGET_LINUX;
+}
+
+static char *npu2_ipi_name(struct irq_source *is, uint32_t isn)
+{
+ struct npu2 *p = is->data;
+ uint32_t idx = isn - p->base_lsi;
+ const char *name;
+
+ switch (idx) {
+ case 0: name = "NDL 0 Stall Event (brick 0)"; break;
+ case 1: name = "NDL 0 No-Stall Event (brick 0)"; break;
+ case 2: name = "NDL 1 Stall Event (brick 1)"; break;
+ case 3: name = "NDL 1 No-Stall Event (brick 1)"; break;
+ case 4: name = "NDL 2 Stall Event (brick 2)"; break;
+ case 5: name = "NDL 2 No-Stall Event (brick 2)"; break;
+ case 6: name = "NDL 5 Stall Event (brick 3)"; break;
+ case 7: name = "NDL 5 No-Stall Event (brick 3)"; break;
+ case 8: name = "NDL 4 Stall Event (brick 4)"; break;
+ case 9: name = "NDL 4 No-Stall Event (brick 4)"; break;
+ case 10: name = "NDL 3 Stall Event (brick 5)"; break;
+ case 11: name = "NDL 3 No-Stall Event (brick 5)"; break;
+ case 12: name = "NTL 0 Event"; break;
+ case 13: name = "NTL 1 Event"; break;
+ case 14: name = "NTL 2 Event"; break;
+ case 15: name = "NTL 3 Event"; break;
+ case 16: name = "NTL 4 Event"; break;
+ case 17: name = "NTL 5 Event"; break;
+ case 18: name = "TCE Event"; break;
+ case 19: name = "ATS Event"; break;
+ case 20: name = "CQ Event"; break;
+ case 21: name = "MISC Event"; break;
+ case 22: name = "NMMU Local Xstop"; break;
+ default: name = "Unknown";
+ }
+ return strdup(name);
+}
+
+static void npu2_err_interrupt(struct irq_source *is, uint32_t isn)
+{
+ struct npu2 *p = is->data;
+ uint32_t idx = isn - p->base_lsi;
+
+ if (idx != 18) {
+ prerror("OPAL received unknown NPU2 interrupt %d\n", idx);
+ return;
+ }
+
+ opal_update_pending_evt(OPAL_EVENT_PCI_ERROR,
+ OPAL_EVENT_PCI_ERROR);
+}
+
+static const struct irq_source_ops npu2_ipi_ops = {
+ .interrupt = npu2_err_interrupt,
+ .attributes = npu2_ipi_attributes,
+ .name = npu2_ipi_name,
+};
+
+static void setup_irqs(struct npu2 *p)
+{
+ uint64_t reg, val;
+ void *tp;
+
+ p->base_lsi = xive_alloc_ipi_irqs(p->chip_id, NPU2_N_DL_IRQS, NPU2_N_DL_IRQS_ALIGN);
+ if (p->base_lsi == XIVE_IRQ_ERROR) {
+ prlog(PR_ERR, "NPU: Failed to allocate interrupt sources, IRQs for NDL No-stall events will not be available.\n");
+ return;
+ }
+ xive_register_ipi_source(p->base_lsi, NPU2_N_DL_IRQS, p, &npu2_ipi_ops);
+
+ /* Set IPI configuration */
+ reg = NPU2_REG_OFFSET(NPU2_STACK_MISC, NPU2_BLOCK_MISC, NPU2_MISC_CFG);
+ val = npu2_read(p, reg);
+ val = SETFIELD(NPU2_MISC_CFG_IPI_PS, val, NPU2_MISC_CFG_IPI_PS_64K);
+ val = SETFIELD(NPU2_MISC_CFG_IPI_OS, val, NPU2_MISC_CFG_IPI_OS_AIX);
+ npu2_write(p, reg, val);
+
+ /* Set IRQ base */
+ reg = NPU2_REG_OFFSET(NPU2_STACK_MISC, NPU2_BLOCK_MISC, NPU2_MISC_IRQ_BASE);
+ tp = xive_get_trigger_port(p->base_lsi);
+ val = ((uint64_t)tp) << NPU2_IRQ_BASE_SHIFT;
+ npu2_write(p, reg, val);
+}
+
static bool _i2c_presence_detect(struct npu2_dev *dev)
{
uint8_t state, data;
@@ -277,6 +376,9 @@ static void setup_devices(struct npu2 *npu)
}
if (nvlink_detected)
+ setup_irqs(npu);
+
+ if (nvlink_detected)
npu2_nvlink_init_npu(npu);
else if (ocapi_detected)
npu2_opencapi_init_npu(npu);
diff --git a/hw/npu2.c b/hw/npu2.c
index 4ecc913..d532c4d 100644
--- a/hw/npu2.c
+++ b/hw/npu2.c
@@ -20,7 +20,6 @@
#include <pci.h>
#include <pci-slot.h>
#include <pci-virt.h>
-#include <interrupts.h>
#include <opal.h>
#include <opal-api.h>
#include <cpu.h>
@@ -35,14 +34,9 @@
#include <chip.h>
#include <phys-map.h>
#include <nvram.h>
-#include <xive.h>
#include <xscom-p9-regs.h>
#include <phb4.h>
-#define NPU2_IRQ_BASE_SHIFT 13
-#define NPU2_N_DL_IRQS 23
-#define NPU2_N_DL_IRQS_ALIGN 64
-
#define VENDOR_CAP_START 0x80
#define VENDOR_CAP_END 0x90
#define VENDOR_CAP_LEN 0x10
@@ -1922,99 +1916,6 @@ static void npu2_add_phb_properties(struct npu2 *p)
hi32(mm_size), lo32(mm_size));
}
-static uint64_t npu2_ipi_attributes(struct irq_source *is __unused, uint32_t isn __unused)
-{
- struct npu2 *p = is->data;
- uint32_t idx = isn - p->base_lsi;
-
- if (idx == 18)
- /* TCE Interrupt - used to detect a frozen PE */
- return IRQ_ATTR_TARGET_OPAL | IRQ_ATTR_TARGET_RARE | IRQ_ATTR_TYPE_MSI;
- else
- return IRQ_ATTR_TARGET_LINUX;
-}
-
-static char *npu2_ipi_name(struct irq_source *is, uint32_t isn)
-{
- struct npu2 *p = is->data;
- uint32_t idx = isn - p->base_lsi;
- const char *name;
-
- switch (idx) {
- case 0: name = "NDL 0 Stall Event (brick 0)"; break;
- case 1: name = "NDL 0 No-Stall Event (brick 0)"; break;
- case 2: name = "NDL 1 Stall Event (brick 1)"; break;
- case 3: name = "NDL 1 No-Stall Event (brick 1)"; break;
- case 4: name = "NDL 2 Stall Event (brick 2)"; break;
- case 5: name = "NDL 2 No-Stall Event (brick 2)"; break;
- case 6: name = "NDL 5 Stall Event (brick 3)"; break;
- case 7: name = "NDL 5 No-Stall Event (brick 3)"; break;
- case 8: name = "NDL 4 Stall Event (brick 4)"; break;
- case 9: name = "NDL 4 No-Stall Event (brick 4)"; break;
- case 10: name = "NDL 3 Stall Event (brick 5)"; break;
- case 11: name = "NDL 3 No-Stall Event (brick 5)"; break;
- case 12: name = "NTL 0 Event"; break;
- case 13: name = "NTL 1 Event"; break;
- case 14: name = "NTL 2 Event"; break;
- case 15: name = "NTL 3 Event"; break;
- case 16: name = "NTL 4 Event"; break;
- case 17: name = "NTL 5 Event"; break;
- case 18: name = "TCE Event"; break;
- case 19: name = "ATS Event"; break;
- case 20: name = "CQ Event"; break;
- case 21: name = "MISC Event"; break;
- case 22: name = "NMMU Local Xstop"; break;
- default: name = "Unknown";
- }
- return strdup(name);
-}
-
-static void npu2_err_interrupt(struct irq_source *is, uint32_t isn)
-{
- struct npu2 *p = is->data;
- uint32_t idx = isn - p->base_lsi;
-
- if (idx != 18) {
- prerror("OPAL received unknown NPU2 interrupt %d\n", idx);
- return;
- }
-
- opal_update_pending_evt(OPAL_EVENT_PCI_ERROR,
- OPAL_EVENT_PCI_ERROR);
-}
-
-static const struct irq_source_ops npu2_ipi_ops = {
- .interrupt = npu2_err_interrupt,
- .attributes = npu2_ipi_attributes,
- .name = npu2_ipi_name,
-};
-
-static void npu2_setup_irqs(struct npu2 *p)
-{
- uint64_t reg, val;
- void *tp;
-
- p->base_lsi = xive_alloc_ipi_irqs(p->chip_id, NPU2_N_DL_IRQS, NPU2_N_DL_IRQS_ALIGN);
- if (p->base_lsi == XIVE_IRQ_ERROR) {
- prlog(PR_ERR, "NPU: Failed to allocate interrupt sources, IRQs for NDL No-stall events will not be available.\n");
- return;
- }
- xive_register_ipi_source(p->base_lsi, NPU2_N_DL_IRQS, p, &npu2_ipi_ops );
-
- /* Set IPI configuration */
- reg = NPU2_REG_OFFSET(NPU2_STACK_MISC, NPU2_BLOCK_MISC, NPU2_MISC_CFG);
- val = npu2_read(p, reg);
- val = SETFIELD(NPU2_MISC_CFG_IPI_PS, val, NPU2_MISC_CFG_IPI_PS_64K);
- val = SETFIELD(NPU2_MISC_CFG_IPI_OS, val, NPU2_MISC_CFG_IPI_OS_AIX);
- npu2_write(p, reg, val);
-
- /* Set IRQ base */
- reg = NPU2_REG_OFFSET(NPU2_STACK_MISC, NPU2_BLOCK_MISC, NPU2_MISC_IRQ_BASE);
- tp = xive_get_trigger_port(p->base_lsi);
- val = ((uint64_t)tp) << NPU2_IRQ_BASE_SHIFT;
- npu2_write(p, reg, val);
-}
-
void npu2_nvlink_create_phb(struct npu2 *npu, struct dt_node *dn)
{
struct pci_slot *slot;
@@ -2028,7 +1929,6 @@ void npu2_nvlink_create_phb(struct npu2 *npu, struct dt_node *dn)
list_head_init(&npu->phb_nvlink.devices);
list_head_init(&npu->phb_nvlink.virt_devices);
- npu2_setup_irqs(npu);
npu2_populate_devices(npu, dn);
npu2_add_interrupt_map(npu, dn);
npu2_add_phb_properties(npu);