|
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] [xen staging] xen/riscv: aplic_init() implementation
commit 028e41d1f3e24e5f52bb101d75bf77f87714b6c3
Author: Oleksii Kurochko <oleksii.kurochko@xxxxxxxxx>
AuthorDate: Thu Jul 10 13:36:42 2025 +0200
Commit: Jan Beulich <jbeulich@xxxxxxxx>
CommitDate: Thu Jul 10 13:36:42 2025 +0200
xen/riscv: aplic_init() implementation
aplic_init() function does the following few things:
- checks that IMSIC in device tree node ( by checking msi-parent property
in APLIC node ) is present as current one implmenetaion of AIA is
supported only MSI method.
- initialize IMSIC based on IMSIC device tree node
- Read value of APLIC's paddr start/end and size.
- Map aplic.regs
- Setup APLIC initial state interrupts (disable all interrupts, set
interrupt type and default priority, confgifure APLIC domaincfg) by
calling aplic_init_hw_interrutps().
aplic_init() is based on the code from [1] and [2].
Since Microchip originally developed aplic.c, an internal discussion with
them led to the decision to use the MIT license.
[1]
https://gitlab.com/xen-project/people/olkur/xen/-/commit/7cfb4bd4748ca268142497ac5c327d2766fb342d
[2]
https://gitlab.com/xen-project/people/olkur/xen/-/commit/392a531bfad39bf4656ce8128e004b241b8b3f3e
Co-developed-by: Romain Caritey <Romain.Caritey@xxxxxxxxxxxxx>
Signed-off-by: Oleksii Kurochko <oleksii.kurochko@xxxxxxxxx>
Acked-by: Jan Beulich<jbeulich@xxxxxxxx>
---
xen/arch/riscv/aplic-priv.h | 33 ++++++++++++
xen/arch/riscv/aplic.c | 103 +++++++++++++++++++++++++++++++++++++
xen/arch/riscv/include/asm/aplic.h | 64 +++++++++++++++++++++++
xen/arch/riscv/include/asm/intc.h | 3 ++
4 files changed, 203 insertions(+)
diff --git a/xen/arch/riscv/aplic-priv.h b/xen/arch/riscv/aplic-priv.h
new file mode 100644
index 0000000000..551747a8b4
--- /dev/null
+++ b/xen/arch/riscv/aplic-priv.h
@@ -0,0 +1,33 @@
+/* SPDX-License-Identifier: MIT */
+
+/*
+ * xen/arch/riscv/aplic-priv.h
+ *
+ * Private part of aplic.h header.
+ *
+ * RISC-V Advanced Platform-Level Interrupt Controller support
+ *
+ * Copyright (c) Microchip.
+ * Copyright (c) Vates.
+ */
+
+#ifndef ASM_RISCV_APLIC_PRIV_H
+#define ASM_RISCV_APLIC_PRIV_H
+
+#include <xen/types.h>
+
+#include <asm/aplic.h>
+
+struct aplic_priv {
+ /* Base physical address and size */
+ paddr_t paddr_start;
+ size_t size;
+
+ /* Registers */
+ volatile struct aplic_regs __iomem *regs;
+
+ /* IMSIC configuration */
+ const struct imsic_config *imsic_cfg;
+};
+
+#endif /* ASM_RISCV_APLIC_PRIV_H */
diff --git a/xen/arch/riscv/aplic.c b/xen/arch/riscv/aplic.c
index 10ae81f7ac..0b0101ebc1 100644
--- a/xen/arch/riscv/aplic.c
+++ b/xen/arch/riscv/aplic.c
@@ -9,19 +9,118 @@
* Copyright (c) 2024-2025 Vates
*/
+#include <xen/device_tree.h>
#include <xen/errno.h>
#include <xen/init.h>
#include <xen/irq.h>
+#include <xen/mm.h>
#include <xen/sections.h>
#include <xen/types.h>
+#include <xen/vmap.h>
+
+#include "aplic-priv.h"
#include <asm/device.h>
+#include <asm/imsic.h>
#include <asm/intc.h>
+#include <asm/riscv_encoding.h>
+
+#define APLIC_DEFAULT_PRIORITY 1
+
+static struct aplic_priv aplic;
static struct intc_info __ro_after_init aplic_info = {
.hw_version = INTC_APLIC,
};
+static void __init aplic_init_hw_interrupts(void)
+{
+ unsigned int i;
+
+ /* Disable all interrupts */
+ for ( i = 0; i < ARRAY_SIZE(aplic.regs->clrie); i++)
+ writel(~0U, &aplic.regs->clrie[i]);
+
+ /* Set interrupt type and default priority for all interrupts */
+ for ( i = 0; i < aplic_info.num_irqs; i++ )
+ {
+ writel(0, &aplic.regs->sourcecfg[i]);
+ /*
+ * Low bits of target register contains Interrupt Priority bits which
+ * can't be zero according to AIA spec.
+ * Thereby they are initialized to APLIC_DEFAULT_PRIORITY.
+ */
+ writel(APLIC_DEFAULT_PRIORITY, &aplic.regs->target[i]);
+ }
+
+ writel(APLIC_DOMAINCFG_IE | APLIC_DOMAINCFG_DM, &aplic.regs->domaincfg);
+}
+
+static int __init cf_check aplic_init(void)
+{
+ dt_phandle imsic_phandle;
+ const __be32 *prop;
+ uint64_t size, paddr;
+ const struct dt_device_node *imsic_node;
+ const struct dt_device_node *node = aplic_info.node;
+ int rc;
+
+ /* Check for associated imsic node */
+ if ( !dt_property_read_u32(node, "msi-parent", &imsic_phandle) )
+ panic("%s: IDC mode not supported\n", node->full_name);
+
+ imsic_node = dt_find_node_by_phandle(imsic_phandle);
+ if ( !imsic_node )
+ panic("%s: unable to find IMSIC node\n", node->full_name);
+
+ rc = imsic_init(imsic_node);
+ if ( rc == IRQ_M_EXT )
+ /* Machine mode imsic node, ignore this aplic node */
+ return 0;
+
+ if ( rc )
+ panic("%s: Failed to initialize IMSIC\n", node->full_name);
+
+ /* Find out number of interrupt sources */
+ if ( !dt_property_read_u32(node, "riscv,num-sources",
+ &aplic_info.num_irqs) )
+ panic("%s: failed to get number of interrupt sources\n",
+ node->full_name);
+
+ if ( aplic_info.num_irqs > ARRAY_SIZE(aplic.regs->sourcecfg) )
+ aplic_info.num_irqs = ARRAY_SIZE(aplic.regs->sourcecfg);
+
+ prop = dt_get_property(node, "reg", NULL);
+ dt_get_range(&prop, node, &paddr, &size);
+ if ( !paddr )
+ panic("%s: first MMIO resource not found\n", node->full_name);
+
+ if ( !IS_ALIGNED(paddr, KB(4)) )
+ panic("%s: paddr of memory-mapped control region should be 4Kb
aligned:%#lx\n",
+ __func__, paddr);
+
+ if ( !IS_ALIGNED(size, KB(4)) || (size < KB(16)) )
+ panic("%s: control region size must be >= 16KB and 4KB-aligned:%#lx\n",
+ __func__, size);
+
+ aplic.paddr_start = paddr;
+ aplic.size = size;
+
+ aplic.regs = ioremap(paddr, size);
+ if ( !aplic.regs )
+ panic("%s: unable to map\n", node->full_name);
+
+ /* Setup initial state APLIC interrupts */
+ aplic_init_hw_interrupts();
+
+ return 0;
+}
+
+static const struct intc_hw_operations aplic_ops = {
+ .info = &aplic_info,
+ .init = aplic_init,
+};
+
static int cf_check aplic_irq_xlate(const uint32_t *intspec,
unsigned int intsize,
unsigned int *out_hwirq,
@@ -53,8 +152,12 @@ static int __init aplic_preinit(struct dt_device_node
*node, const void *dat)
aplic_info.node = node;
+ aplic.imsic_cfg = imsic_get_config();
+
dt_irq_xlate = aplic_irq_xlate;
+ register_intc_ops(&aplic_ops);
+
return 0;
}
diff --git a/xen/arch/riscv/include/asm/aplic.h
b/xen/arch/riscv/include/asm/aplic.h
new file mode 100644
index 0000000000..1388a977e6
--- /dev/null
+++ b/xen/arch/riscv/include/asm/aplic.h
@@ -0,0 +1,64 @@
+/* SPDX-License-Identifier: MIT */
+
+/*
+ * xen/arch/riscv/asm/include/aplic.h
+ *
+ * RISC-V Advanced Platform-Level Interrupt Controller support
+ *
+ * Copyright (c) Microchip.
+ */
+
+#ifndef ASM_RISCV_APLIC_H
+#define ASM_RISCV_APLIC_H
+
+#include <xen/types.h>
+
+#include <asm/imsic.h>
+
+#define APLIC_DOMAINCFG_IE BIT(8, U)
+#define APLIC_DOMAINCFG_DM BIT(2, U)
+
+struct aplic_regs {
+ uint32_t domaincfg; /* 0x0000 */
+ uint32_t sourcecfg[1023]; /* 0x0004 */
+ uint8_t _reserved1[3008]; /* 0x1000 */
+
+ uint32_t mmsiaddrcfg; /* 0x1BC0 */
+ uint32_t mmsiaddrcfgh; /* 0x1BC4 */
+ uint32_t smsiaddrcfg; /* 0x1BC8 */
+ uint32_t smsiaddrcfgh; /* 0x1BCC */
+ uint8_t _reserved2[48]; /* 0x1BD0 */
+
+ uint32_t setip[32]; /* 0x1C00 */
+ uint8_t _reserved3[92]; /* 0x1C80 */
+
+ uint32_t setipnum; /* 0x1CDC */
+ uint8_t _reserved4[32]; /* 0x1CE0 */
+
+ uint32_t in_clrip[32]; /* 0x1D00 */
+ uint8_t _reserved5[92]; /* 0x1D80 */
+
+ uint32_t clripnum; /* 0x1DDC */
+ uint8_t _reserved6[32]; /* 0x1DE0 */
+
+ uint32_t setie[32]; /* 0x1E00 */
+ uint8_t _reserved7[92]; /* 0x1E80 */
+
+ uint32_t setienum; /* 0x1EDC */
+ uint8_t _reserved8[32]; /* 0x1EE0 */
+
+ uint32_t clrie[32]; /* 0x1F00 */
+ uint8_t _reserved9[92]; /* 0x1F80 */
+
+ uint32_t clrienum; /* 0x1FDC */
+ uint8_t _reserved10[32]; /* 0x1FF0 */
+
+ uint32_t setipnum_le; /* 0x2000 */
+ uint32_t setipnum_be; /* 0x2004 */
+ uint8_t _reserved11[4088]; /* 0x2008 */
+
+ uint32_t genmsi; /* 0x3000 */
+ uint32_t target[1023]; /* 0x3008 */
+};
+
+#endif /* ASM_RISCV_APLIC_H */
diff --git a/xen/arch/riscv/include/asm/intc.h
b/xen/arch/riscv/include/asm/intc.h
index 434c9d0781..3c4b211f58 100644
--- a/xen/arch/riscv/include/asm/intc.h
+++ b/xen/arch/riscv/include/asm/intc.h
@@ -19,6 +19,9 @@ struct irq_desc;
struct intc_info {
enum intc_version hw_version;
const struct dt_device_node *node;
+
+ /* number of irqs */
+ unsigned int num_irqs;
};
struct intc_hw_operations {
--
generated by git-patchbot for /home/xen/git/xen.git#staging
|
![]() |
Lists.xenproject.org is hosted with RackSpace, monitoring our |