* [PATCH v2 01/13] include: sbi: Add AIA related CSR defines
2022-02-09 15:04 [PATCH v2 00/13] OpenSBI RISC-V AIA Support Anup Patel
@ 2022-02-09 15:04 ` Anup Patel
2022-02-15 15:14 ` Anup Patel
2022-02-09 15:04 ` [PATCH v2 02/13] lib: sbi: Detect AIA CSRs at boot-time Anup Patel
` (11 subsequent siblings)
12 siblings, 1 reply; 36+ messages in thread
From: Anup Patel @ 2022-02-09 15:04 UTC (permalink / raw)
To: opensbi
The RISC-V AIA specification improves handling of per-HART local
interrupts in a backward compatible manner. This patch adds defines
for the new RISC-V AIA CSRs.
Signed-off-by: Anup Patel <anup.patel@wdc.com>
Signed-off-by: Anup Patel <apatel@ventanamicro.com>
Reviewed-by: Atish Patra <atishp@rivosinc.com>
---
include/sbi/riscv_encoding.h | 76 ++++++++++++++++++++++++++++++++++++
1 file changed, 76 insertions(+)
diff --git a/include/sbi/riscv_encoding.h b/include/sbi/riscv_encoding.h
index ac8590d..574d1c3 100644
--- a/include/sbi/riscv_encoding.h
+++ b/include/sbi/riscv_encoding.h
@@ -173,6 +173,10 @@
#define HGATP_MODE_SHIFT HGATP32_MODE_SHIFT
#endif
+#define TOPI_IID_SHIFT 16
+#define TOPI_IID_MASK 0xfff
+#define TOPI_IPRIO_MASK 0xff
+
#if __riscv_xlen == 64
#define MHPMEVENT_OF (_UL(1) << 63)
#define MHPMEVENT_MINH (_UL(1) << 62)
@@ -304,6 +308,24 @@
/* Supervisor Protection and Translation */
#define CSR_SATP 0x180
+/* Supervisor-Level Window to Indirectly Accessed Registers (AIA) */
+#define CSR_SISELECT 0x150
+#define CSR_SIREG 0x151
+
+/* Supervisor-Level Interrupts (AIA) */
+#define CSR_STOPI 0xdb0
+
+/* Supervisor-Level IMSIC Interface (AIA) */
+#define CSR_SSETEIPNUM 0x158
+#define CSR_SCLREIPNUM 0x159
+#define CSR_SSETEIENUM 0x15a
+#define CSR_SCLREIENUM 0x15b
+#define CSR_STOPEI 0x15c
+
+/* Supervisor-Level High-Half CSRs (AIA) */
+#define CSR_SIEH 0x114
+#define CSR_SIPH 0x154
+
/* ===== Hypervisor-level CSRs ===== */
/* Hypervisor Trap Setup (H-extension) */
@@ -339,6 +361,35 @@
#define CSR_VSIP 0x244
#define CSR_VSATP 0x280
+/* Virtual Interrupts and Interrupt Priorities (H-extension with AIA) */
+#define CSR_HVIEN 0x608
+#define CSR_HVICTL 0x609
+#define CSR_HVIPRIO1 0x646
+#define CSR_HVIPRIO2 0x647
+
+/* VS-Level Window to Indirectly Accessed Registers (H-extension with AIA) */
+#define CSR_VSISELECT 0x250
+#define CSR_VSIREG 0x251
+
+/* VS-Level Interrupts (H-extension with AIA) */
+#define CSR_VSTOPI 0xeb0
+
+/* VS-Level IMSIC Interface (H-extension with AIA) */
+#define CSR_VSSETEIPNUM 0x258
+#define CSR_VSCLREIPNUM 0x259
+#define CSR_VSSETEIENUM 0x25a
+#define CSR_VSCLREIENUM 0x25b
+#define CSR_VSTOPEI 0x25c
+
+/* Hypervisor and VS-Level High-Half CSRs (H-extension with AIA) */
+#define CSR_HIDELEGH 0x613
+#define CSR_HVIENH 0x618
+#define CSR_HVIPH 0x655
+#define CSR_HVIPRIO1H 0x656
+#define CSR_HVIPRIO2H 0x657
+#define CSR_VSIEH 0x214
+#define CSR_VSIPH 0x254
+
/* ===== Machine-level CSRs ===== */
/* Machine Information Registers */
@@ -590,6 +641,31 @@
#define CSR_DSCRATCH0 0x7b2
#define CSR_DSCRATCH1 0x7b3
+/* Machine-Level Window to Indirectly Accessed Registers (AIA) */
+#define CSR_MISELECT 0x350
+#define CSR_MIREG 0x351
+
+/* Machine-Level Interrupts (AIA) */
+#define CSR_MTOPI 0xfb0
+
+/* Machine-Level IMSIC Interface (AIA) */
+#define CSR_MSETEIPNUM 0x358
+#define CSR_MCLREIPNUM 0x359
+#define CSR_MSETEIENUM 0x35a
+#define CSR_MCLREIENUM 0x35b
+#define CSR_MTOPEI 0x35c
+
+/* Virtual Interrupts for Supervisor Level (AIA) */
+#define CSR_MVIEN 0x308
+#define CSR_MVIP 0x309
+
+/* Machine-Level High-Half CSRs (AIA) */
+#define CSR_MIDELEGH 0x313
+#define CSR_MIEH 0x314
+#define CSR_MVIENH 0x318
+#define CSR_MVIPH 0x319
+#define CSR_MIPH 0x354
+
/* ===== Trap/Exception Causes ===== */
#define CAUSE_MISALIGNED_FETCH 0x0
--
2.25.1
^ permalink raw reply related [flat|nested] 36+ messages in thread* [PATCH v2 01/13] include: sbi: Add AIA related CSR defines
2022-02-09 15:04 ` [PATCH v2 01/13] include: sbi: Add AIA related CSR defines Anup Patel
@ 2022-02-15 15:14 ` Anup Patel
0 siblings, 0 replies; 36+ messages in thread
From: Anup Patel @ 2022-02-15 15:14 UTC (permalink / raw)
To: opensbi
On Wed, Feb 9, 2022 at 8:35 PM Anup Patel <apatel@ventanamicro.com> wrote:
>
> The RISC-V AIA specification improves handling of per-HART local
> interrupts in a backward compatible manner. This patch adds defines
> for the new RISC-V AIA CSRs.
>
> Signed-off-by: Anup Patel <anup.patel@wdc.com>
> Signed-off-by: Anup Patel <apatel@ventanamicro.com>
> Reviewed-by: Atish Patra <atishp@rivosinc.com>
Applied this patch to the riscv/opensbi repo.
Regards,
Anup
> ---
> include/sbi/riscv_encoding.h | 76 ++++++++++++++++++++++++++++++++++++
> 1 file changed, 76 insertions(+)
>
> diff --git a/include/sbi/riscv_encoding.h b/include/sbi/riscv_encoding.h
> index ac8590d..574d1c3 100644
> --- a/include/sbi/riscv_encoding.h
> +++ b/include/sbi/riscv_encoding.h
> @@ -173,6 +173,10 @@
> #define HGATP_MODE_SHIFT HGATP32_MODE_SHIFT
> #endif
>
> +#define TOPI_IID_SHIFT 16
> +#define TOPI_IID_MASK 0xfff
> +#define TOPI_IPRIO_MASK 0xff
> +
> #if __riscv_xlen == 64
> #define MHPMEVENT_OF (_UL(1) << 63)
> #define MHPMEVENT_MINH (_UL(1) << 62)
> @@ -304,6 +308,24 @@
> /* Supervisor Protection and Translation */
> #define CSR_SATP 0x180
>
> +/* Supervisor-Level Window to Indirectly Accessed Registers (AIA) */
> +#define CSR_SISELECT 0x150
> +#define CSR_SIREG 0x151
> +
> +/* Supervisor-Level Interrupts (AIA) */
> +#define CSR_STOPI 0xdb0
> +
> +/* Supervisor-Level IMSIC Interface (AIA) */
> +#define CSR_SSETEIPNUM 0x158
> +#define CSR_SCLREIPNUM 0x159
> +#define CSR_SSETEIENUM 0x15a
> +#define CSR_SCLREIENUM 0x15b
> +#define CSR_STOPEI 0x15c
> +
> +/* Supervisor-Level High-Half CSRs (AIA) */
> +#define CSR_SIEH 0x114
> +#define CSR_SIPH 0x154
> +
> /* ===== Hypervisor-level CSRs ===== */
>
> /* Hypervisor Trap Setup (H-extension) */
> @@ -339,6 +361,35 @@
> #define CSR_VSIP 0x244
> #define CSR_VSATP 0x280
>
> +/* Virtual Interrupts and Interrupt Priorities (H-extension with AIA) */
> +#define CSR_HVIEN 0x608
> +#define CSR_HVICTL 0x609
> +#define CSR_HVIPRIO1 0x646
> +#define CSR_HVIPRIO2 0x647
> +
> +/* VS-Level Window to Indirectly Accessed Registers (H-extension with AIA) */
> +#define CSR_VSISELECT 0x250
> +#define CSR_VSIREG 0x251
> +
> +/* VS-Level Interrupts (H-extension with AIA) */
> +#define CSR_VSTOPI 0xeb0
> +
> +/* VS-Level IMSIC Interface (H-extension with AIA) */
> +#define CSR_VSSETEIPNUM 0x258
> +#define CSR_VSCLREIPNUM 0x259
> +#define CSR_VSSETEIENUM 0x25a
> +#define CSR_VSCLREIENUM 0x25b
> +#define CSR_VSTOPEI 0x25c
> +
> +/* Hypervisor and VS-Level High-Half CSRs (H-extension with AIA) */
> +#define CSR_HIDELEGH 0x613
> +#define CSR_HVIENH 0x618
> +#define CSR_HVIPH 0x655
> +#define CSR_HVIPRIO1H 0x656
> +#define CSR_HVIPRIO2H 0x657
> +#define CSR_VSIEH 0x214
> +#define CSR_VSIPH 0x254
> +
> /* ===== Machine-level CSRs ===== */
>
> /* Machine Information Registers */
> @@ -590,6 +641,31 @@
> #define CSR_DSCRATCH0 0x7b2
> #define CSR_DSCRATCH1 0x7b3
>
> +/* Machine-Level Window to Indirectly Accessed Registers (AIA) */
> +#define CSR_MISELECT 0x350
> +#define CSR_MIREG 0x351
> +
> +/* Machine-Level Interrupts (AIA) */
> +#define CSR_MTOPI 0xfb0
> +
> +/* Machine-Level IMSIC Interface (AIA) */
> +#define CSR_MSETEIPNUM 0x358
> +#define CSR_MCLREIPNUM 0x359
> +#define CSR_MSETEIENUM 0x35a
> +#define CSR_MCLREIENUM 0x35b
> +#define CSR_MTOPEI 0x35c
> +
> +/* Virtual Interrupts for Supervisor Level (AIA) */
> +#define CSR_MVIEN 0x308
> +#define CSR_MVIP 0x309
> +
> +/* Machine-Level High-Half CSRs (AIA) */
> +#define CSR_MIDELEGH 0x313
> +#define CSR_MIEH 0x314
> +#define CSR_MVIENH 0x318
> +#define CSR_MVIPH 0x319
> +#define CSR_MIPH 0x354
> +
> /* ===== Trap/Exception Causes ===== */
>
> #define CAUSE_MISALIGNED_FETCH 0x0
> --
> 2.25.1
>
^ permalink raw reply [flat|nested] 36+ messages in thread
* [PATCH v2 02/13] lib: sbi: Detect AIA CSRs at boot-time
2022-02-09 15:04 [PATCH v2 00/13] OpenSBI RISC-V AIA Support Anup Patel
2022-02-09 15:04 ` [PATCH v2 01/13] include: sbi: Add AIA related CSR defines Anup Patel
@ 2022-02-09 15:04 ` Anup Patel
2022-02-09 16:33 ` Atish Patra
2022-02-09 15:04 ` [PATCH v2 03/13] lib: sbi: Use AIA CSRs for local interrupts when available Anup Patel
` (10 subsequent siblings)
12 siblings, 1 reply; 36+ messages in thread
From: Anup Patel @ 2022-02-09 15:04 UTC (permalink / raw)
To: opensbi
We extend HART feature detection to discover AIA CSRs at boot-time.
Signed-off-by: Anup Patel <anup.patel@wdc.com>
Signed-off-by: Anup Patel <apatel@ventanamicro.com>
---
include/sbi/sbi_hart.h | 4 +++-
lib/sbi/sbi_hart.c | 11 +++++++++++
2 files changed, 14 insertions(+), 1 deletion(-)
diff --git a/include/sbi/sbi_hart.h b/include/sbi/sbi_hart.h
index d2db9d6..a83b45b 100644
--- a/include/sbi/sbi_hart.h
+++ b/include/sbi/sbi_hart.h
@@ -24,9 +24,11 @@ enum sbi_hart_features {
SBI_HART_HAS_SSCOFPMF = (1 << 3),
/** HART has timer csr implementation in hardware */
SBI_HART_HAS_TIME = (1 << 4),
+ /** HART has AIA local interrupt CSRs */
+ SBI_HART_HAS_AIA = (1 << 5),
/** Last index of Hart features*/
- SBI_HART_HAS_LAST_FEATURE = SBI_HART_HAS_TIME,
+ SBI_HART_HAS_LAST_FEATURE = SBI_HART_HAS_AIA,
};
struct sbi_scratch;
diff --git a/lib/sbi/sbi_hart.c b/lib/sbi/sbi_hart.c
index 36908b1..e028540 100644
--- a/lib/sbi/sbi_hart.c
+++ b/lib/sbi/sbi_hart.c
@@ -301,6 +301,9 @@ static inline char *sbi_hart_feature_id2string(unsigned long feature)
case SBI_HART_HAS_TIME:
fstr = "time";
break;
+ case SBI_HART_HAS_AIA:
+ fstr = "aia";
+ break;
default:
break;
}
@@ -524,6 +527,14 @@ __mhpm_skip:
csr_read_allowed(CSR_TIME, (unsigned long)&trap);
if (!trap.cause)
hfeatures->features |= SBI_HART_HAS_TIME;
+
+ /* Detect if hart has AIA local interrupt CSRs */
+ csr_read_allowed(CSR_MTOPI, (unsigned long)&trap);
+ if (trap.cause)
+ goto __aia_skip;
+ hfeatures->features |= SBI_HART_HAS_AIA;
+__aia_skip:
+ return;
}
int sbi_hart_reinit(struct sbi_scratch *scratch)
--
2.25.1
^ permalink raw reply related [flat|nested] 36+ messages in thread* [PATCH v2 02/13] lib: sbi: Detect AIA CSRs at boot-time
2022-02-09 15:04 ` [PATCH v2 02/13] lib: sbi: Detect AIA CSRs at boot-time Anup Patel
@ 2022-02-09 16:33 ` Atish Patra
2022-02-15 15:14 ` Anup Patel
0 siblings, 1 reply; 36+ messages in thread
From: Atish Patra @ 2022-02-09 16:33 UTC (permalink / raw)
To: opensbi
On Wed, Feb 9, 2022 at 7:05 AM Anup Patel <apatel@ventanamicro.com> wrote:
>
> We extend HART feature detection to discover AIA CSRs at boot-time.
>
> Signed-off-by: Anup Patel <anup.patel@wdc.com>
> Signed-off-by: Anup Patel <apatel@ventanamicro.com>
> ---
> include/sbi/sbi_hart.h | 4 +++-
> lib/sbi/sbi_hart.c | 11 +++++++++++
> 2 files changed, 14 insertions(+), 1 deletion(-)
>
> diff --git a/include/sbi/sbi_hart.h b/include/sbi/sbi_hart.h
> index d2db9d6..a83b45b 100644
> --- a/include/sbi/sbi_hart.h
> +++ b/include/sbi/sbi_hart.h
> @@ -24,9 +24,11 @@ enum sbi_hart_features {
> SBI_HART_HAS_SSCOFPMF = (1 << 3),
> /** HART has timer csr implementation in hardware */
> SBI_HART_HAS_TIME = (1 << 4),
> + /** HART has AIA local interrupt CSRs */
> + SBI_HART_HAS_AIA = (1 << 5),
>
> /** Last index of Hart features*/
> - SBI_HART_HAS_LAST_FEATURE = SBI_HART_HAS_TIME,
> + SBI_HART_HAS_LAST_FEATURE = SBI_HART_HAS_AIA,
> };
>
> struct sbi_scratch;
> diff --git a/lib/sbi/sbi_hart.c b/lib/sbi/sbi_hart.c
> index 36908b1..e028540 100644
> --- a/lib/sbi/sbi_hart.c
> +++ b/lib/sbi/sbi_hart.c
> @@ -301,6 +301,9 @@ static inline char *sbi_hart_feature_id2string(unsigned long feature)
> case SBI_HART_HAS_TIME:
> fstr = "time";
> break;
> + case SBI_HART_HAS_AIA:
> + fstr = "aia";
> + break;
> default:
> break;
> }
> @@ -524,6 +527,14 @@ __mhpm_skip:
> csr_read_allowed(CSR_TIME, (unsigned long)&trap);
> if (!trap.cause)
> hfeatures->features |= SBI_HART_HAS_TIME;
> +
> + /* Detect if hart has AIA local interrupt CSRs */
> + csr_read_allowed(CSR_MTOPI, (unsigned long)&trap);
> + if (trap.cause)
> + goto __aia_skip;
> + hfeatures->features |= SBI_HART_HAS_AIA;
> +__aia_skip:
> + return;
> }
>
> int sbi_hart_reinit(struct sbi_scratch *scratch)
> --
> 2.25.1
>
Reviewed-by: Atish Patra <atishp@rivosinc.com>
--
Regards,
Atish
^ permalink raw reply [flat|nested] 36+ messages in thread* [PATCH v2 02/13] lib: sbi: Detect AIA CSRs at boot-time
2022-02-09 16:33 ` Atish Patra
@ 2022-02-15 15:14 ` Anup Patel
0 siblings, 0 replies; 36+ messages in thread
From: Anup Patel @ 2022-02-15 15:14 UTC (permalink / raw)
To: opensbi
On Wed, Feb 9, 2022 at 10:04 PM Atish Patra <atishp@atishpatra.org> wrote:
>
> On Wed, Feb 9, 2022 at 7:05 AM Anup Patel <apatel@ventanamicro.com> wrote:
> >
> > We extend HART feature detection to discover AIA CSRs at boot-time.
> >
> > Signed-off-by: Anup Patel <anup.patel@wdc.com>
> > Signed-off-by: Anup Patel <apatel@ventanamicro.com>
> > ---
> > include/sbi/sbi_hart.h | 4 +++-
> > lib/sbi/sbi_hart.c | 11 +++++++++++
> > 2 files changed, 14 insertions(+), 1 deletion(-)
> >
> > diff --git a/include/sbi/sbi_hart.h b/include/sbi/sbi_hart.h
> > index d2db9d6..a83b45b 100644
> > --- a/include/sbi/sbi_hart.h
> > +++ b/include/sbi/sbi_hart.h
> > @@ -24,9 +24,11 @@ enum sbi_hart_features {
> > SBI_HART_HAS_SSCOFPMF = (1 << 3),
> > /** HART has timer csr implementation in hardware */
> > SBI_HART_HAS_TIME = (1 << 4),
> > + /** HART has AIA local interrupt CSRs */
> > + SBI_HART_HAS_AIA = (1 << 5),
> >
> > /** Last index of Hart features*/
> > - SBI_HART_HAS_LAST_FEATURE = SBI_HART_HAS_TIME,
> > + SBI_HART_HAS_LAST_FEATURE = SBI_HART_HAS_AIA,
> > };
> >
> > struct sbi_scratch;
> > diff --git a/lib/sbi/sbi_hart.c b/lib/sbi/sbi_hart.c
> > index 36908b1..e028540 100644
> > --- a/lib/sbi/sbi_hart.c
> > +++ b/lib/sbi/sbi_hart.c
> > @@ -301,6 +301,9 @@ static inline char *sbi_hart_feature_id2string(unsigned long feature)
> > case SBI_HART_HAS_TIME:
> > fstr = "time";
> > break;
> > + case SBI_HART_HAS_AIA:
> > + fstr = "aia";
> > + break;
> > default:
> > break;
> > }
> > @@ -524,6 +527,14 @@ __mhpm_skip:
> > csr_read_allowed(CSR_TIME, (unsigned long)&trap);
> > if (!trap.cause)
> > hfeatures->features |= SBI_HART_HAS_TIME;
> > +
> > + /* Detect if hart has AIA local interrupt CSRs */
> > + csr_read_allowed(CSR_MTOPI, (unsigned long)&trap);
> > + if (trap.cause)
> > + goto __aia_skip;
> > + hfeatures->features |= SBI_HART_HAS_AIA;
> > +__aia_skip:
> > + return;
> > }
> >
> > int sbi_hart_reinit(struct sbi_scratch *scratch)
> > --
> > 2.25.1
> >
>
> Reviewed-by: Atish Patra <atishp@rivosinc.com>
Applied this patch to the riscv/opensbi repo.
Regards,
Anup
>
>
> --
> Regards,
> Atish
^ permalink raw reply [flat|nested] 36+ messages in thread
* [PATCH v2 03/13] lib: sbi: Use AIA CSRs for local interrupts when available
2022-02-09 15:04 [PATCH v2 00/13] OpenSBI RISC-V AIA Support Anup Patel
2022-02-09 15:04 ` [PATCH v2 01/13] include: sbi: Add AIA related CSR defines Anup Patel
2022-02-09 15:04 ` [PATCH v2 02/13] lib: sbi: Detect AIA CSRs at boot-time Anup Patel
@ 2022-02-09 15:04 ` Anup Patel
2022-02-09 16:41 ` Atish Patra
2022-02-09 15:04 ` [PATCH v2 04/13] lib: sbi: Add sbi_trap_set_external_irqfn() API Anup Patel
` (9 subsequent siblings)
12 siblings, 1 reply; 36+ messages in thread
From: Anup Patel @ 2022-02-09 15:04 UTC (permalink / raw)
To: opensbi
We should use AIA CSRs to process local interrupts whenever AIA
is available.
Signed-off-by: Anup Patel <anup.patel@wdc.com>
Signed-off-by: Anup Patel <apatel@ventanamicro.com>
---
lib/sbi/sbi_trap.c | 57 +++++++++++++++++++++++++++++++++++++---------
1 file changed, 46 insertions(+), 11 deletions(-)
diff --git a/lib/sbi/sbi_trap.c b/lib/sbi/sbi_trap.c
index 8d20e04..bc8961f 100644
--- a/lib/sbi/sbi_trap.c
+++ b/lib/sbi/sbi_trap.c
@@ -195,6 +195,44 @@ int sbi_trap_redirect(struct sbi_trap_regs *regs,
return 0;
}
+static int sbi_trap_nonaia_irq(struct sbi_trap_regs *regs, ulong mcause)
+{
+ mcause &= ~(1UL << (__riscv_xlen - 1));
+ switch (mcause) {
+ case IRQ_M_TIMER:
+ sbi_timer_process();
+ break;
+ case IRQ_M_SOFT:
+ sbi_ipi_process();
+ break;
+ default:
+ return SBI_ENOENT;
+ };
+
+ return 0;
+}
+
+static int sbi_trap_aia_irq(struct sbi_trap_regs *regs, ulong mcause)
+{
+ unsigned long mtopi;
+
+ while ((mtopi = csr_read(CSR_MTOPI))) {
+ mtopi = mtopi >> TOPI_IID_SHIFT;
+ switch (mtopi) {
+ case IRQ_M_TIMER:
+ sbi_timer_process();
+ break;
+ case IRQ_M_SOFT:
+ sbi_ipi_process();
+ break;
+ default:
+ return SBI_ENOENT;
+ }
+ }
+
+ return 0;
+}
+
/**
* Handle trap/interrupt
*
@@ -225,18 +263,15 @@ struct sbi_trap_regs *sbi_trap_handler(struct sbi_trap_regs *regs)
}
if (mcause & (1UL << (__riscv_xlen - 1))) {
- mcause &= ~(1UL << (__riscv_xlen - 1));
- switch (mcause) {
- case IRQ_M_TIMER:
- sbi_timer_process();
- break;
- case IRQ_M_SOFT:
- sbi_ipi_process();
- break;
- default:
- msg = "unhandled external interrupt";
+ if (sbi_hart_has_feature(sbi_scratch_thishart_ptr(),
+ SBI_HART_HAS_AIA))
+ rc = sbi_trap_aia_irq(regs, mcause);
+ else
+ rc = sbi_trap_nonaia_irq(regs, mcause);
+ if (rc) {
+ msg = "unhandled local interrupt";
goto trap_error;
- };
+ }
return regs;
}
--
2.25.1
^ permalink raw reply related [flat|nested] 36+ messages in thread* [PATCH v2 03/13] lib: sbi: Use AIA CSRs for local interrupts when available
2022-02-09 15:04 ` [PATCH v2 03/13] lib: sbi: Use AIA CSRs for local interrupts when available Anup Patel
@ 2022-02-09 16:41 ` Atish Patra
2022-02-15 15:15 ` Anup Patel
0 siblings, 1 reply; 36+ messages in thread
From: Atish Patra @ 2022-02-09 16:41 UTC (permalink / raw)
To: opensbi
On Wed, Feb 9, 2022 at 7:05 AM Anup Patel <apatel@ventanamicro.com> wrote:
>
> We should use AIA CSRs to process local interrupts whenever AIA
> is available.
>
> Signed-off-by: Anup Patel <anup.patel@wdc.com>
> Signed-off-by: Anup Patel <apatel@ventanamicro.com>
> ---
> lib/sbi/sbi_trap.c | 57 +++++++++++++++++++++++++++++++++++++---------
> 1 file changed, 46 insertions(+), 11 deletions(-)
>
> diff --git a/lib/sbi/sbi_trap.c b/lib/sbi/sbi_trap.c
> index 8d20e04..bc8961f 100644
> --- a/lib/sbi/sbi_trap.c
> +++ b/lib/sbi/sbi_trap.c
> @@ -195,6 +195,44 @@ int sbi_trap_redirect(struct sbi_trap_regs *regs,
> return 0;
> }
>
> +static int sbi_trap_nonaia_irq(struct sbi_trap_regs *regs, ulong mcause)
> +{
> + mcause &= ~(1UL << (__riscv_xlen - 1));
> + switch (mcause) {
> + case IRQ_M_TIMER:
> + sbi_timer_process();
> + break;
> + case IRQ_M_SOFT:
> + sbi_ipi_process();
> + break;
> + default:
> + return SBI_ENOENT;
> + };
> +
> + return 0;
> +}
> +
> +static int sbi_trap_aia_irq(struct sbi_trap_regs *regs, ulong mcause)
> +{
> + unsigned long mtopi;
> +
> + while ((mtopi = csr_read(CSR_MTOPI))) {
> + mtopi = mtopi >> TOPI_IID_SHIFT;
> + switch (mtopi) {
> + case IRQ_M_TIMER:
> + sbi_timer_process();
> + break;
> + case IRQ_M_SOFT:
> + sbi_ipi_process();
> + break;
> + default:
> + return SBI_ENOENT;
> + }
> + }
> +
> + return 0;
> +}
> +
> /**
> * Handle trap/interrupt
> *
> @@ -225,18 +263,15 @@ struct sbi_trap_regs *sbi_trap_handler(struct sbi_trap_regs *regs)
> }
>
> if (mcause & (1UL << (__riscv_xlen - 1))) {
> - mcause &= ~(1UL << (__riscv_xlen - 1));
> - switch (mcause) {
> - case IRQ_M_TIMER:
> - sbi_timer_process();
> - break;
> - case IRQ_M_SOFT:
> - sbi_ipi_process();
> - break;
> - default:
> - msg = "unhandled external interrupt";
> + if (sbi_hart_has_feature(sbi_scratch_thishart_ptr(),
> + SBI_HART_HAS_AIA))
> + rc = sbi_trap_aia_irq(regs, mcause);
> + else
> + rc = sbi_trap_nonaia_irq(regs, mcause);
> + if (rc) {
> + msg = "unhandled local interrupt";
> goto trap_error;
> - };
> + }
> return regs;
> }
>
> --
> 2.25.1
>
Reviewed-by: Atish Patra <atishp@rivosinc.com>
--
Regards,
Atish
^ permalink raw reply [flat|nested] 36+ messages in thread* [PATCH v2 03/13] lib: sbi: Use AIA CSRs for local interrupts when available
2022-02-09 16:41 ` Atish Patra
@ 2022-02-15 15:15 ` Anup Patel
0 siblings, 0 replies; 36+ messages in thread
From: Anup Patel @ 2022-02-15 15:15 UTC (permalink / raw)
To: opensbi
On Wed, Feb 9, 2022 at 10:11 PM Atish Patra <atishp@atishpatra.org> wrote:
>
> On Wed, Feb 9, 2022 at 7:05 AM Anup Patel <apatel@ventanamicro.com> wrote:
> >
> > We should use AIA CSRs to process local interrupts whenever AIA
> > is available.
> >
> > Signed-off-by: Anup Patel <anup.patel@wdc.com>
> > Signed-off-by: Anup Patel <apatel@ventanamicro.com>
> > ---
> > lib/sbi/sbi_trap.c | 57 +++++++++++++++++++++++++++++++++++++---------
> > 1 file changed, 46 insertions(+), 11 deletions(-)
> >
> > diff --git a/lib/sbi/sbi_trap.c b/lib/sbi/sbi_trap.c
> > index 8d20e04..bc8961f 100644
> > --- a/lib/sbi/sbi_trap.c
> > +++ b/lib/sbi/sbi_trap.c
> > @@ -195,6 +195,44 @@ int sbi_trap_redirect(struct sbi_trap_regs *regs,
> > return 0;
> > }
> >
> > +static int sbi_trap_nonaia_irq(struct sbi_trap_regs *regs, ulong mcause)
> > +{
> > + mcause &= ~(1UL << (__riscv_xlen - 1));
> > + switch (mcause) {
> > + case IRQ_M_TIMER:
> > + sbi_timer_process();
> > + break;
> > + case IRQ_M_SOFT:
> > + sbi_ipi_process();
> > + break;
> > + default:
> > + return SBI_ENOENT;
> > + };
> > +
> > + return 0;
> > +}
> > +
> > +static int sbi_trap_aia_irq(struct sbi_trap_regs *regs, ulong mcause)
> > +{
> > + unsigned long mtopi;
> > +
> > + while ((mtopi = csr_read(CSR_MTOPI))) {
> > + mtopi = mtopi >> TOPI_IID_SHIFT;
> > + switch (mtopi) {
> > + case IRQ_M_TIMER:
> > + sbi_timer_process();
> > + break;
> > + case IRQ_M_SOFT:
> > + sbi_ipi_process();
> > + break;
> > + default:
> > + return SBI_ENOENT;
> > + }
> > + }
> > +
> > + return 0;
> > +}
> > +
> > /**
> > * Handle trap/interrupt
> > *
> > @@ -225,18 +263,15 @@ struct sbi_trap_regs *sbi_trap_handler(struct sbi_trap_regs *regs)
> > }
> >
> > if (mcause & (1UL << (__riscv_xlen - 1))) {
> > - mcause &= ~(1UL << (__riscv_xlen - 1));
> > - switch (mcause) {
> > - case IRQ_M_TIMER:
> > - sbi_timer_process();
> > - break;
> > - case IRQ_M_SOFT:
> > - sbi_ipi_process();
> > - break;
> > - default:
> > - msg = "unhandled external interrupt";
> > + if (sbi_hart_has_feature(sbi_scratch_thishart_ptr(),
> > + SBI_HART_HAS_AIA))
> > + rc = sbi_trap_aia_irq(regs, mcause);
> > + else
> > + rc = sbi_trap_nonaia_irq(regs, mcause);
> > + if (rc) {
> > + msg = "unhandled local interrupt";
> > goto trap_error;
> > - };
> > + }
> > return regs;
> > }
> >
> > --
> > 2.25.1
> >
>
> Reviewed-by: Atish Patra <atishp@rivosinc.com>
Applied this patch to the riscv/opensbi repo.
Regards,
Anup
>
> --
> Regards,
> Atish
^ permalink raw reply [flat|nested] 36+ messages in thread
* [PATCH v2 04/13] lib: sbi: Add sbi_trap_set_external_irqfn() API
2022-02-09 15:04 [PATCH v2 00/13] OpenSBI RISC-V AIA Support Anup Patel
` (2 preceding siblings ...)
2022-02-09 15:04 ` [PATCH v2 03/13] lib: sbi: Use AIA CSRs for local interrupts when available Anup Patel
@ 2022-02-09 15:04 ` Anup Patel
2022-02-15 15:15 ` Anup Patel
2022-02-09 15:04 ` [PATCH v2 05/13] lib: utils/irqchip: Allow multiple FDT irqchip drivers Anup Patel
` (8 subsequent siblings)
12 siblings, 1 reply; 36+ messages in thread
From: Anup Patel @ 2022-02-09 15:04 UTC (permalink / raw)
To: opensbi
This patch adds sbi_trap_set_external_irqfn() API which can be used by
OpenSBI platform code to set a callback function for external interrupts.
The RISC-V AIA IMSIC driver will use this API to implement inter-processor
interrupts on-top-of MSIs.
Signed-off-by: Anup Patel <anup.patel@wdc.com>
Signed-off-by: Anup Patel <apatel@ventanamicro.com>
Reviewed-by: Atish Patra <atishp@rivosinc.com>
---
include/sbi/sbi_trap.h | 2 ++
lib/sbi/sbi_trap.c | 29 +++++++++++++++++++++++++++++
2 files changed, 31 insertions(+)
diff --git a/include/sbi/sbi_trap.h b/include/sbi/sbi_trap.h
index d205056..4f611fa 100644
--- a/include/sbi/sbi_trap.h
+++ b/include/sbi/sbi_trap.h
@@ -205,6 +205,8 @@ struct sbi_trap_info {
int sbi_trap_redirect(struct sbi_trap_regs *regs,
struct sbi_trap_info *trap);
+void sbi_trap_set_external_irqfn(int (*fn)(struct sbi_trap_regs *regs));
+
struct sbi_trap_regs *sbi_trap_handler(struct sbi_trap_regs *regs);
void __noreturn sbi_trap_exit(const struct sbi_trap_regs *regs);
diff --git a/lib/sbi/sbi_trap.c b/lib/sbi/sbi_trap.c
index bc8961f..faab90a 100644
--- a/lib/sbi/sbi_trap.c
+++ b/lib/sbi/sbi_trap.c
@@ -195,6 +195,27 @@ int sbi_trap_redirect(struct sbi_trap_regs *regs,
return 0;
}
+static int default_irqfn(struct sbi_trap_regs *regs)
+{
+ return SBI_ENODEV;
+}
+
+static int (*ext_irqfn)(struct sbi_trap_regs *regs) = default_irqfn;
+
+/**
+ * Set external irq handler function
+ *
+ * This function is called by OpenSBI platform code to set a handler for
+ * external interrupts
+ *
+ * @param fn function pointer for handling external irqs
+ */
+void sbi_trap_set_external_irqfn(int (*fn)(struct sbi_trap_regs *regs))
+{
+ if (fn)
+ ext_irqfn = fn;
+}
+
static int sbi_trap_nonaia_irq(struct sbi_trap_regs *regs, ulong mcause)
{
mcause &= ~(1UL << (__riscv_xlen - 1));
@@ -205,6 +226,8 @@ static int sbi_trap_nonaia_irq(struct sbi_trap_regs *regs, ulong mcause)
case IRQ_M_SOFT:
sbi_ipi_process();
break;
+ case IRQ_M_EXT:
+ return ext_irqfn(regs);
default:
return SBI_ENOENT;
};
@@ -214,6 +237,7 @@ static int sbi_trap_nonaia_irq(struct sbi_trap_regs *regs, ulong mcause)
static int sbi_trap_aia_irq(struct sbi_trap_regs *regs, ulong mcause)
{
+ int rc;
unsigned long mtopi;
while ((mtopi = csr_read(CSR_MTOPI))) {
@@ -225,6 +249,11 @@ static int sbi_trap_aia_irq(struct sbi_trap_regs *regs, ulong mcause)
case IRQ_M_SOFT:
sbi_ipi_process();
break;
+ case IRQ_M_EXT:
+ rc = ext_irqfn(regs);
+ if (rc)
+ return rc;
+ break;
default:
return SBI_ENOENT;
}
--
2.25.1
^ permalink raw reply related [flat|nested] 36+ messages in thread* [PATCH v2 04/13] lib: sbi: Add sbi_trap_set_external_irqfn() API
2022-02-09 15:04 ` [PATCH v2 04/13] lib: sbi: Add sbi_trap_set_external_irqfn() API Anup Patel
@ 2022-02-15 15:15 ` Anup Patel
0 siblings, 0 replies; 36+ messages in thread
From: Anup Patel @ 2022-02-15 15:15 UTC (permalink / raw)
To: opensbi
On Wed, Feb 9, 2022 at 8:35 PM Anup Patel <apatel@ventanamicro.com> wrote:
>
> This patch adds sbi_trap_set_external_irqfn() API which can be used by
> OpenSBI platform code to set a callback function for external interrupts.
> The RISC-V AIA IMSIC driver will use this API to implement inter-processor
> interrupts on-top-of MSIs.
>
> Signed-off-by: Anup Patel <anup.patel@wdc.com>
> Signed-off-by: Anup Patel <apatel@ventanamicro.com>
> Reviewed-by: Atish Patra <atishp@rivosinc.com>
Applied this patch to the riscv/opensbi repo.
Regards,
Anup
> ---
> include/sbi/sbi_trap.h | 2 ++
> lib/sbi/sbi_trap.c | 29 +++++++++++++++++++++++++++++
> 2 files changed, 31 insertions(+)
>
> diff --git a/include/sbi/sbi_trap.h b/include/sbi/sbi_trap.h
> index d205056..4f611fa 100644
> --- a/include/sbi/sbi_trap.h
> +++ b/include/sbi/sbi_trap.h
> @@ -205,6 +205,8 @@ struct sbi_trap_info {
> int sbi_trap_redirect(struct sbi_trap_regs *regs,
> struct sbi_trap_info *trap);
>
> +void sbi_trap_set_external_irqfn(int (*fn)(struct sbi_trap_regs *regs));
> +
> struct sbi_trap_regs *sbi_trap_handler(struct sbi_trap_regs *regs);
>
> void __noreturn sbi_trap_exit(const struct sbi_trap_regs *regs);
> diff --git a/lib/sbi/sbi_trap.c b/lib/sbi/sbi_trap.c
> index bc8961f..faab90a 100644
> --- a/lib/sbi/sbi_trap.c
> +++ b/lib/sbi/sbi_trap.c
> @@ -195,6 +195,27 @@ int sbi_trap_redirect(struct sbi_trap_regs *regs,
> return 0;
> }
>
> +static int default_irqfn(struct sbi_trap_regs *regs)
> +{
> + return SBI_ENODEV;
> +}
> +
> +static int (*ext_irqfn)(struct sbi_trap_regs *regs) = default_irqfn;
> +
> +/**
> + * Set external irq handler function
> + *
> + * This function is called by OpenSBI platform code to set a handler for
> + * external interrupts
> + *
> + * @param fn function pointer for handling external irqs
> + */
> +void sbi_trap_set_external_irqfn(int (*fn)(struct sbi_trap_regs *regs))
> +{
> + if (fn)
> + ext_irqfn = fn;
> +}
> +
> static int sbi_trap_nonaia_irq(struct sbi_trap_regs *regs, ulong mcause)
> {
> mcause &= ~(1UL << (__riscv_xlen - 1));
> @@ -205,6 +226,8 @@ static int sbi_trap_nonaia_irq(struct sbi_trap_regs *regs, ulong mcause)
> case IRQ_M_SOFT:
> sbi_ipi_process();
> break;
> + case IRQ_M_EXT:
> + return ext_irqfn(regs);
> default:
> return SBI_ENOENT;
> };
> @@ -214,6 +237,7 @@ static int sbi_trap_nonaia_irq(struct sbi_trap_regs *regs, ulong mcause)
>
> static int sbi_trap_aia_irq(struct sbi_trap_regs *regs, ulong mcause)
> {
> + int rc;
> unsigned long mtopi;
>
> while ((mtopi = csr_read(CSR_MTOPI))) {
> @@ -225,6 +249,11 @@ static int sbi_trap_aia_irq(struct sbi_trap_regs *regs, ulong mcause)
> case IRQ_M_SOFT:
> sbi_ipi_process();
> break;
> + case IRQ_M_EXT:
> + rc = ext_irqfn(regs);
> + if (rc)
> + return rc;
> + break;
> default:
> return SBI_ENOENT;
> }
> --
> 2.25.1
>
^ permalink raw reply [flat|nested] 36+ messages in thread
* [PATCH v2 05/13] lib: utils/irqchip: Allow multiple FDT irqchip drivers
2022-02-09 15:04 [PATCH v2 00/13] OpenSBI RISC-V AIA Support Anup Patel
` (3 preceding siblings ...)
2022-02-09 15:04 ` [PATCH v2 04/13] lib: sbi: Add sbi_trap_set_external_irqfn() API Anup Patel
@ 2022-02-09 15:04 ` Anup Patel
2022-02-15 15:16 ` Anup Patel
2022-02-09 15:04 ` [PATCH v2 06/13] include: sbi: Introduce nascent_init() platform callback Anup Patel
` (7 subsequent siblings)
12 siblings, 1 reply; 36+ messages in thread
From: Anup Patel @ 2022-02-09 15:04 UTC (permalink / raw)
To: opensbi
We can have multiple FDT irqchip drivers to be probed when a RISC-V
system has different types of interrupt controller in a hierarchy.
This will be certainly the case when a RISC-V system has both
RISC-V AIA IMSIC and RISC-V AIA APLIC implemented.
We extend simple FDT irqchip framework to allow multiple FDT
irqchip drivers to be used for same RISC-V platform.
Signed-off-by: Anup Patel <anup.patel@wdc.com>
Signed-off-by: Anup Patel <apatel@ventanamicro.com>
Reviewed-by: Atish Patra <atishp@rivosinc.com>
---
lib/utils/irqchip/fdt_irqchip.c | 37 ++++++++++++++++++++++++++-------
1 file changed, 30 insertions(+), 7 deletions(-)
diff --git a/lib/utils/irqchip/fdt_irqchip.c b/lib/utils/irqchip/fdt_irqchip.c
index 8dda661..bf6969a 100644
--- a/lib/utils/irqchip/fdt_irqchip.c
+++ b/lib/utils/irqchip/fdt_irqchip.c
@@ -18,23 +18,40 @@ static struct fdt_irqchip *irqchip_drivers[] = {
&fdt_irqchip_plic
};
-static struct fdt_irqchip *current_driver = NULL;
+#define FDT_IRQCHIP_MAX_DRIVERS 8
+
+static struct fdt_irqchip *current_drivers[FDT_IRQCHIP_MAX_DRIVERS] = {0};
+static int current_drivers_count;
void fdt_irqchip_exit(void)
{
- if (current_driver && current_driver->exit)
- current_driver->exit();
+ int i;
+
+ for (i = 0; i < current_drivers_count; i++) {
+ if (!current_drivers[i] || !current_drivers[i]->exit)
+ continue;
+ current_drivers[i]->exit();
+ }
}
static int fdt_irqchip_warm_init(void)
{
- if (current_driver && current_driver->warm_init)
- return current_driver->warm_init();
+ int i, rc;
+
+ for (i = 0; i < current_drivers_count; i++) {
+ if (!current_drivers[i] || !current_drivers[i]->warm_init)
+ continue;
+ rc = current_drivers[i]->warm_init();
+ if (rc)
+ return rc;
+ }
+
return 0;
}
static int fdt_irqchip_cold_init(void)
{
+ bool drv_added;
int pos, noff, rc;
struct fdt_irqchip *drv;
const struct fdt_match *match;
@@ -44,6 +61,7 @@ static int fdt_irqchip_cold_init(void)
drv = irqchip_drivers[pos];
noff = -1;
+ drv_added = false;
while ((noff = fdt_find_match(fdt, noff,
drv->match_table, &match)) >= 0) {
if (drv->cold_init) {
@@ -53,10 +71,15 @@ static int fdt_irqchip_cold_init(void)
if (rc)
return rc;
}
- current_driver = drv;
+
+ if (drv_added)
+ continue;
+
+ current_drivers[current_drivers_count++] = drv;
+ drv_added = true;
}
- if (current_driver)
+ if (FDT_IRQCHIP_MAX_DRIVERS <= current_drivers_count)
break;
}
--
2.25.1
^ permalink raw reply related [flat|nested] 36+ messages in thread* [PATCH v2 05/13] lib: utils/irqchip: Allow multiple FDT irqchip drivers
2022-02-09 15:04 ` [PATCH v2 05/13] lib: utils/irqchip: Allow multiple FDT irqchip drivers Anup Patel
@ 2022-02-15 15:16 ` Anup Patel
0 siblings, 0 replies; 36+ messages in thread
From: Anup Patel @ 2022-02-15 15:16 UTC (permalink / raw)
To: opensbi
On Wed, Feb 9, 2022 at 8:35 PM Anup Patel <apatel@ventanamicro.com> wrote:
>
> We can have multiple FDT irqchip drivers to be probed when a RISC-V
> system has different types of interrupt controller in a hierarchy.
>
> This will be certainly the case when a RISC-V system has both
> RISC-V AIA IMSIC and RISC-V AIA APLIC implemented.
>
> We extend simple FDT irqchip framework to allow multiple FDT
> irqchip drivers to be used for same RISC-V platform.
>
> Signed-off-by: Anup Patel <anup.patel@wdc.com>
> Signed-off-by: Anup Patel <apatel@ventanamicro.com>
> Reviewed-by: Atish Patra <atishp@rivosinc.com>
Applied this patch to the riscv/opensbi repo.
Regards,
Anup
> ---
> lib/utils/irqchip/fdt_irqchip.c | 37 ++++++++++++++++++++++++++-------
> 1 file changed, 30 insertions(+), 7 deletions(-)
>
> diff --git a/lib/utils/irqchip/fdt_irqchip.c b/lib/utils/irqchip/fdt_irqchip.c
> index 8dda661..bf6969a 100644
> --- a/lib/utils/irqchip/fdt_irqchip.c
> +++ b/lib/utils/irqchip/fdt_irqchip.c
> @@ -18,23 +18,40 @@ static struct fdt_irqchip *irqchip_drivers[] = {
> &fdt_irqchip_plic
> };
>
> -static struct fdt_irqchip *current_driver = NULL;
> +#define FDT_IRQCHIP_MAX_DRIVERS 8
> +
> +static struct fdt_irqchip *current_drivers[FDT_IRQCHIP_MAX_DRIVERS] = {0};
> +static int current_drivers_count;
>
> void fdt_irqchip_exit(void)
> {
> - if (current_driver && current_driver->exit)
> - current_driver->exit();
> + int i;
> +
> + for (i = 0; i < current_drivers_count; i++) {
> + if (!current_drivers[i] || !current_drivers[i]->exit)
> + continue;
> + current_drivers[i]->exit();
> + }
> }
>
> static int fdt_irqchip_warm_init(void)
> {
> - if (current_driver && current_driver->warm_init)
> - return current_driver->warm_init();
> + int i, rc;
> +
> + for (i = 0; i < current_drivers_count; i++) {
> + if (!current_drivers[i] || !current_drivers[i]->warm_init)
> + continue;
> + rc = current_drivers[i]->warm_init();
> + if (rc)
> + return rc;
> + }
> +
> return 0;
> }
>
> static int fdt_irqchip_cold_init(void)
> {
> + bool drv_added;
> int pos, noff, rc;
> struct fdt_irqchip *drv;
> const struct fdt_match *match;
> @@ -44,6 +61,7 @@ static int fdt_irqchip_cold_init(void)
> drv = irqchip_drivers[pos];
>
> noff = -1;
> + drv_added = false;
> while ((noff = fdt_find_match(fdt, noff,
> drv->match_table, &match)) >= 0) {
> if (drv->cold_init) {
> @@ -53,10 +71,15 @@ static int fdt_irqchip_cold_init(void)
> if (rc)
> return rc;
> }
> - current_driver = drv;
> +
> + if (drv_added)
> + continue;
> +
> + current_drivers[current_drivers_count++] = drv;
> + drv_added = true;
> }
>
> - if (current_driver)
> + if (FDT_IRQCHIP_MAX_DRIVERS <= current_drivers_count)
> break;
> }
>
> --
> 2.25.1
>
^ permalink raw reply [flat|nested] 36+ messages in thread
* [PATCH v2 06/13] include: sbi: Introduce nascent_init() platform callback
2022-02-09 15:04 [PATCH v2 00/13] OpenSBI RISC-V AIA Support Anup Patel
` (4 preceding siblings ...)
2022-02-09 15:04 ` [PATCH v2 05/13] lib: utils/irqchip: Allow multiple FDT irqchip drivers Anup Patel
@ 2022-02-09 15:04 ` Anup Patel
2022-02-15 15:16 ` Anup Patel
2022-02-09 15:04 ` [PATCH v2 07/13] lib: sbi: Enable mie.MEIE bit for IPIs based on external interrupts Anup Patel
` (6 subsequent siblings)
12 siblings, 1 reply; 36+ messages in thread
From: Anup Patel @ 2022-02-09 15:04 UTC (permalink / raw)
To: opensbi
We introduce nascent_init() platform callback which will allow
platforms to do very early initialization of platform specific
per-HART CSRs and per-HART devices.
Signed-off-by: Anup Patel <anup.patel@wdc.com>
Signed-off-by: Anup Patel <apatel@ventanamicro.com>
Reviewed-by: Atish Patra <atishp@rivosinc.com>
---
include/sbi/sbi_platform.h | 20 ++++++++++++++++++++
lib/sbi/sbi_init.c | 8 ++++++++
2 files changed, 28 insertions(+)
diff --git a/include/sbi/sbi_platform.h b/include/sbi/sbi_platform.h
index 4d192f2..0b5ae4b 100644
--- a/include/sbi/sbi_platform.h
+++ b/include/sbi/sbi_platform.h
@@ -64,6 +64,9 @@ enum sbi_platform_features {
/** Platform functions */
struct sbi_platform_operations {
+ /* Platform nascent initialization */
+ int (*nascent_init)(void);
+
/** Platform early initialization */
int (*early_init)(bool cold_boot);
/** Platform final initialization */
@@ -299,6 +302,23 @@ static inline bool sbi_platform_hart_invalid(const struct sbi_platform *plat,
return FALSE;
}
+/**
+ * Nascent (very early) initialization for current HART
+ *
+ * NOTE: This function can be used to do very early initialization of
+ * platform specific per-HART CSRs and devices.
+ *
+ * @param plat pointer to struct sbi_platform
+ *
+ * @return 0 on success and negative error code on failure
+ */
+static inline int sbi_platform_nascent_init(const struct sbi_platform *plat)
+{
+ if (plat && sbi_platform_ops(plat)->nascent_init)
+ return sbi_platform_ops(plat)->nascent_init();
+ return 0;
+}
+
/**
* Early initialization for current HART
*
diff --git a/lib/sbi/sbi_init.c b/lib/sbi/sbi_init.c
index 83043c5..27d03a7 100644
--- a/lib/sbi/sbi_init.c
+++ b/lib/sbi/sbi_init.c
@@ -494,6 +494,14 @@ void __noreturn sbi_init(struct sbi_scratch *scratch)
if (next_mode_supported && atomic_xchg(&coldboot_lottery, 1) == 0)
coldboot = TRUE;
+ /*
+ * Do platform specific nascent (very early) initialization so
+ * that platform can initialize platform specific per-HART CSRs
+ * or per-HART devices.
+ */
+ if (sbi_platform_nascent_init(plat))
+ sbi_hart_hang();
+
if (coldboot)
init_coldboot(scratch, hartid);
else
--
2.25.1
^ permalink raw reply related [flat|nested] 36+ messages in thread* [PATCH v2 06/13] include: sbi: Introduce nascent_init() platform callback
2022-02-09 15:04 ` [PATCH v2 06/13] include: sbi: Introduce nascent_init() platform callback Anup Patel
@ 2022-02-15 15:16 ` Anup Patel
0 siblings, 0 replies; 36+ messages in thread
From: Anup Patel @ 2022-02-15 15:16 UTC (permalink / raw)
To: opensbi
On Wed, Feb 9, 2022 at 8:35 PM Anup Patel <apatel@ventanamicro.com> wrote:
>
> We introduce nascent_init() platform callback which will allow
> platforms to do very early initialization of platform specific
> per-HART CSRs and per-HART devices.
>
> Signed-off-by: Anup Patel <anup.patel@wdc.com>
> Signed-off-by: Anup Patel <apatel@ventanamicro.com>
> Reviewed-by: Atish Patra <atishp@rivosinc.com>
Applied this patch to the riscv/opensbi repo.
Regards,
Anup
> ---
> include/sbi/sbi_platform.h | 20 ++++++++++++++++++++
> lib/sbi/sbi_init.c | 8 ++++++++
> 2 files changed, 28 insertions(+)
>
> diff --git a/include/sbi/sbi_platform.h b/include/sbi/sbi_platform.h
> index 4d192f2..0b5ae4b 100644
> --- a/include/sbi/sbi_platform.h
> +++ b/include/sbi/sbi_platform.h
> @@ -64,6 +64,9 @@ enum sbi_platform_features {
>
> /** Platform functions */
> struct sbi_platform_operations {
> + /* Platform nascent initialization */
> + int (*nascent_init)(void);
> +
> /** Platform early initialization */
> int (*early_init)(bool cold_boot);
> /** Platform final initialization */
> @@ -299,6 +302,23 @@ static inline bool sbi_platform_hart_invalid(const struct sbi_platform *plat,
> return FALSE;
> }
>
> +/**
> + * Nascent (very early) initialization for current HART
> + *
> + * NOTE: This function can be used to do very early initialization of
> + * platform specific per-HART CSRs and devices.
> + *
> + * @param plat pointer to struct sbi_platform
> + *
> + * @return 0 on success and negative error code on failure
> + */
> +static inline int sbi_platform_nascent_init(const struct sbi_platform *plat)
> +{
> + if (plat && sbi_platform_ops(plat)->nascent_init)
> + return sbi_platform_ops(plat)->nascent_init();
> + return 0;
> +}
> +
> /**
> * Early initialization for current HART
> *
> diff --git a/lib/sbi/sbi_init.c b/lib/sbi/sbi_init.c
> index 83043c5..27d03a7 100644
> --- a/lib/sbi/sbi_init.c
> +++ b/lib/sbi/sbi_init.c
> @@ -494,6 +494,14 @@ void __noreturn sbi_init(struct sbi_scratch *scratch)
> if (next_mode_supported && atomic_xchg(&coldboot_lottery, 1) == 0)
> coldboot = TRUE;
>
> + /*
> + * Do platform specific nascent (very early) initialization so
> + * that platform can initialize platform specific per-HART CSRs
> + * or per-HART devices.
> + */
> + if (sbi_platform_nascent_init(plat))
> + sbi_hart_hang();
> +
> if (coldboot)
> init_coldboot(scratch, hartid);
> else
> --
> 2.25.1
>
^ permalink raw reply [flat|nested] 36+ messages in thread
* [PATCH v2 07/13] lib: sbi: Enable mie.MEIE bit for IPIs based on external interrupts.
2022-02-09 15:04 [PATCH v2 00/13] OpenSBI RISC-V AIA Support Anup Patel
` (5 preceding siblings ...)
2022-02-09 15:04 ` [PATCH v2 06/13] include: sbi: Introduce nascent_init() platform callback Anup Patel
@ 2022-02-09 15:04 ` Anup Patel
2022-02-09 16:31 ` Atish Patra
2022-02-09 15:04 ` [PATCH v2 08/13] lib: utils/irqchip: Add IMSIC library Anup Patel
` (5 subsequent siblings)
12 siblings, 1 reply; 36+ messages in thread
From: Anup Patel @ 2022-02-09 15:04 UTC (permalink / raw)
To: opensbi
We can have IPIs based on external interrupts provided by devices
such as AIA IMSIC so we should enable mie.MEIE bit at appropriate
places in generic library.
Signed-off-by: Anup Patel <anup@brainfault.org>
Signed-off-by: Anup Patel <apatel@ventanamicro.com>
---
lib/sbi/sbi_hsm.c | 4 ++--
lib/sbi/sbi_init.c | 9 ++++++---
2 files changed, 8 insertions(+), 5 deletions(-)
diff --git a/lib/sbi/sbi_hsm.c b/lib/sbi/sbi_hsm.c
index ecd2e45..c4d2c6d 100644
--- a/lib/sbi/sbi_hsm.c
+++ b/lib/sbi/sbi_hsm.c
@@ -113,8 +113,8 @@ static void sbi_hsm_hart_wait(struct sbi_scratch *scratch, u32 hartid)
/* Save MIE CSR */
saved_mie = csr_read(CSR_MIE);
- /* Set MSIE bit to receive IPI */
- csr_set(CSR_MIE, MIP_MSIP);
+ /* Set MSIE and MEIE bits to receive IPI */
+ csr_set(CSR_MIE, MIP_MSIP | MIP_MEIP);
/* Wait for hart_add call*/
while (atomic_read(&hdata->state) != SBI_HSM_STATE_START_PENDING) {
diff --git a/lib/sbi/sbi_init.c b/lib/sbi/sbi_init.c
index 27d03a7..6876eb2 100644
--- a/lib/sbi/sbi_init.c
+++ b/lib/sbi/sbi_init.c
@@ -165,8 +165,8 @@ static void wait_for_coldboot(struct sbi_scratch *scratch, u32 hartid)
/* Save MIE CSR */
saved_mie = csr_read(CSR_MIE);
- /* Set MSIE bit to receive IPI */
- csr_set(CSR_MIE, MIP_MSIP);
+ /* Set MSIE and MEIE bits to receive IPI */
+ csr_set(CSR_MIE, MIP_MSIP | MIP_MEIP);
/* Acquire coldboot lock */
spin_lock(&coldboot_lock);
@@ -182,7 +182,7 @@ static void wait_for_coldboot(struct sbi_scratch *scratch, u32 hartid)
do {
wfi();
cmip = csr_read(CSR_MIP);
- } while (!(cmip & MIP_MSIP));
+ } while (!(cmip & (MIP_MSIP | MIP_MEIP)));
};
/* Acquire coldboot lock */
@@ -276,6 +276,7 @@ static void __noreturn init_coldboot(struct sbi_scratch *scratch, u32 hartid)
__func__, rc);
sbi_hart_hang();
}
+ csr_set(CSR_MIE, MIP_MEIP);
rc = sbi_ipi_init(scratch, TRUE);
if (rc) {
@@ -376,6 +377,7 @@ static void init_warm_startup(struct sbi_scratch *scratch, u32 hartid)
rc = sbi_platform_irqchip_init(plat, FALSE);
if (rc)
sbi_hart_hang();
+ csr_set(CSR_MIE, MIP_MEIP);
rc = sbi_ipi_init(scratch, FALSE);
if (rc)
@@ -550,6 +552,7 @@ void __noreturn sbi_exit(struct sbi_scratch *scratch)
sbi_ipi_exit(scratch);
+ csr_clear(CSR_MIE, MIP_MEIP);
sbi_platform_irqchip_exit(plat);
sbi_platform_final_exit(plat);
--
2.25.1
^ permalink raw reply related [flat|nested] 36+ messages in thread* [PATCH v2 07/13] lib: sbi: Enable mie.MEIE bit for IPIs based on external interrupts.
2022-02-09 15:04 ` [PATCH v2 07/13] lib: sbi: Enable mie.MEIE bit for IPIs based on external interrupts Anup Patel
@ 2022-02-09 16:31 ` Atish Patra
2022-02-15 15:19 ` Anup Patel
0 siblings, 1 reply; 36+ messages in thread
From: Atish Patra @ 2022-02-09 16:31 UTC (permalink / raw)
To: opensbi
On Wed, Feb 9, 2022 at 7:05 AM Anup Patel <apatel@ventanamicro.com> wrote:
>
> We can have IPIs based on external interrupts provided by devices
> such as AIA IMSIC so we should enable mie.MEIE bit at appropriate
> places in generic library.
>
> Signed-off-by: Anup Patel <anup@brainfault.org>
> Signed-off-by: Anup Patel <apatel@ventanamicro.com>
> ---
> lib/sbi/sbi_hsm.c | 4 ++--
> lib/sbi/sbi_init.c | 9 ++++++---
> 2 files changed, 8 insertions(+), 5 deletions(-)
>
> diff --git a/lib/sbi/sbi_hsm.c b/lib/sbi/sbi_hsm.c
> index ecd2e45..c4d2c6d 100644
> --- a/lib/sbi/sbi_hsm.c
> +++ b/lib/sbi/sbi_hsm.c
> @@ -113,8 +113,8 @@ static void sbi_hsm_hart_wait(struct sbi_scratch *scratch, u32 hartid)
> /* Save MIE CSR */
> saved_mie = csr_read(CSR_MIE);
>
> - /* Set MSIE bit to receive IPI */
> - csr_set(CSR_MIE, MIP_MSIP);
> + /* Set MSIE and MEIE bits to receive IPI */
> + csr_set(CSR_MIE, MIP_MSIP | MIP_MEIP);
>
> /* Wait for hart_add call*/
> while (atomic_read(&hdata->state) != SBI_HSM_STATE_START_PENDING) {
> diff --git a/lib/sbi/sbi_init.c b/lib/sbi/sbi_init.c
> index 27d03a7..6876eb2 100644
> --- a/lib/sbi/sbi_init.c
> +++ b/lib/sbi/sbi_init.c
> @@ -165,8 +165,8 @@ static void wait_for_coldboot(struct sbi_scratch *scratch, u32 hartid)
> /* Save MIE CSR */
> saved_mie = csr_read(CSR_MIE);
>
> - /* Set MSIE bit to receive IPI */
> - csr_set(CSR_MIE, MIP_MSIP);
> + /* Set MSIE and MEIE bits to receive IPI */
> + csr_set(CSR_MIE, MIP_MSIP | MIP_MEIP);
>
> /* Acquire coldboot lock */
> spin_lock(&coldboot_lock);
> @@ -182,7 +182,7 @@ static void wait_for_coldboot(struct sbi_scratch *scratch, u32 hartid)
> do {
> wfi();
> cmip = csr_read(CSR_MIP);
> - } while (!(cmip & MIP_MSIP));
> + } while (!(cmip & (MIP_MSIP | MIP_MEIP)));
> };
>
> /* Acquire coldboot lock */
> @@ -276,6 +276,7 @@ static void __noreturn init_coldboot(struct sbi_scratch *scratch, u32 hartid)
> __func__, rc);
> sbi_hart_hang();
> }
> + csr_set(CSR_MIE, MIP_MEIP);
>
> rc = sbi_ipi_init(scratch, TRUE);
> if (rc) {
> @@ -376,6 +377,7 @@ static void init_warm_startup(struct sbi_scratch *scratch, u32 hartid)
> rc = sbi_platform_irqchip_init(plat, FALSE);
> if (rc)
> sbi_hart_hang();
> + csr_set(CSR_MIE, MIP_MEIP);
>
> rc = sbi_ipi_init(scratch, FALSE);
> if (rc)
> @@ -550,6 +552,7 @@ void __noreturn sbi_exit(struct sbi_scratch *scratch)
>
> sbi_ipi_exit(scratch);
>
> + csr_clear(CSR_MIE, MIP_MEIP);
> sbi_platform_irqchip_exit(plat);
>
> sbi_platform_final_exit(plat);
> --
> 2.25.1
>
Reviewed-by: Atish Patra <atishp@rivosinc.com>
--
Regards,
Atish
^ permalink raw reply [flat|nested] 36+ messages in thread* [PATCH v2 07/13] lib: sbi: Enable mie.MEIE bit for IPIs based on external interrupts.
2022-02-09 16:31 ` Atish Patra
@ 2022-02-15 15:19 ` Anup Patel
0 siblings, 0 replies; 36+ messages in thread
From: Anup Patel @ 2022-02-15 15:19 UTC (permalink / raw)
To: opensbi
On Wed, Feb 9, 2022 at 10:02 PM Atish Patra <atishp@atishpatra.org> wrote:
>
> On Wed, Feb 9, 2022 at 7:05 AM Anup Patel <apatel@ventanamicro.com> wrote:
> >
> > We can have IPIs based on external interrupts provided by devices
> > such as AIA IMSIC so we should enable mie.MEIE bit at appropriate
> > places in generic library.
> >
> > Signed-off-by: Anup Patel <anup@brainfault.org>
> > Signed-off-by: Anup Patel <apatel@ventanamicro.com>
> > ---
> > lib/sbi/sbi_hsm.c | 4 ++--
> > lib/sbi/sbi_init.c | 9 ++++++---
> > 2 files changed, 8 insertions(+), 5 deletions(-)
> >
> > diff --git a/lib/sbi/sbi_hsm.c b/lib/sbi/sbi_hsm.c
> > index ecd2e45..c4d2c6d 100644
> > --- a/lib/sbi/sbi_hsm.c
> > +++ b/lib/sbi/sbi_hsm.c
> > @@ -113,8 +113,8 @@ static void sbi_hsm_hart_wait(struct sbi_scratch *scratch, u32 hartid)
> > /* Save MIE CSR */
> > saved_mie = csr_read(CSR_MIE);
> >
> > - /* Set MSIE bit to receive IPI */
> > - csr_set(CSR_MIE, MIP_MSIP);
> > + /* Set MSIE and MEIE bits to receive IPI */
> > + csr_set(CSR_MIE, MIP_MSIP | MIP_MEIP);
> >
> > /* Wait for hart_add call*/
> > while (atomic_read(&hdata->state) != SBI_HSM_STATE_START_PENDING) {
> > diff --git a/lib/sbi/sbi_init.c b/lib/sbi/sbi_init.c
> > index 27d03a7..6876eb2 100644
> > --- a/lib/sbi/sbi_init.c
> > +++ b/lib/sbi/sbi_init.c
> > @@ -165,8 +165,8 @@ static void wait_for_coldboot(struct sbi_scratch *scratch, u32 hartid)
> > /* Save MIE CSR */
> > saved_mie = csr_read(CSR_MIE);
> >
> > - /* Set MSIE bit to receive IPI */
> > - csr_set(CSR_MIE, MIP_MSIP);
> > + /* Set MSIE and MEIE bits to receive IPI */
> > + csr_set(CSR_MIE, MIP_MSIP | MIP_MEIP);
> >
> > /* Acquire coldboot lock */
> > spin_lock(&coldboot_lock);
> > @@ -182,7 +182,7 @@ static void wait_for_coldboot(struct sbi_scratch *scratch, u32 hartid)
> > do {
> > wfi();
> > cmip = csr_read(CSR_MIP);
> > - } while (!(cmip & MIP_MSIP));
> > + } while (!(cmip & (MIP_MSIP | MIP_MEIP)));
> > };
> >
> > /* Acquire coldboot lock */
> > @@ -276,6 +276,7 @@ static void __noreturn init_coldboot(struct sbi_scratch *scratch, u32 hartid)
> > __func__, rc);
> > sbi_hart_hang();
> > }
> > + csr_set(CSR_MIE, MIP_MEIP);
> >
> > rc = sbi_ipi_init(scratch, TRUE);
> > if (rc) {
> > @@ -376,6 +377,7 @@ static void init_warm_startup(struct sbi_scratch *scratch, u32 hartid)
> > rc = sbi_platform_irqchip_init(plat, FALSE);
> > if (rc)
> > sbi_hart_hang();
> > + csr_set(CSR_MIE, MIP_MEIP);
> >
> > rc = sbi_ipi_init(scratch, FALSE);
> > if (rc)
> > @@ -550,6 +552,7 @@ void __noreturn sbi_exit(struct sbi_scratch *scratch)
> >
> > sbi_ipi_exit(scratch);
> >
> > + csr_clear(CSR_MIE, MIP_MEIP);
> > sbi_platform_irqchip_exit(plat);
> >
> > sbi_platform_final_exit(plat);
> > --
> > 2.25.1
> >
>
> Reviewed-by: Atish Patra <atishp@rivosinc.com>
Applied this patch to the riscv/opensbi repo.
Regards,
Anup
>
> --
> Regards,
> Atish
^ permalink raw reply [flat|nested] 36+ messages in thread
* [PATCH v2 08/13] lib: utils/irqchip: Add IMSIC library
2022-02-09 15:04 [PATCH v2 00/13] OpenSBI RISC-V AIA Support Anup Patel
` (6 preceding siblings ...)
2022-02-09 15:04 ` [PATCH v2 07/13] lib: sbi: Enable mie.MEIE bit for IPIs based on external interrupts Anup Patel
@ 2022-02-09 15:04 ` Anup Patel
2022-02-12 9:09 ` Atish Patra
2022-02-09 15:04 ` [PATCH v2 09/13] lib: utils/irqchip: Add FDT based driver for IMSIC Anup Patel
` (4 subsequent siblings)
12 siblings, 1 reply; 36+ messages in thread
From: Anup Patel @ 2022-02-09 15:04 UTC (permalink / raw)
To: opensbi
We add simple IMSIC library which is independent of hardware description
format (FDT or ACPI). This IMSIC library can be used by custom OpenSBI
platform support to setup IMSIC for external interrupts.
Signed-off-by: Anup Patel <anup.patel@wdc.com>
Signed-off-by: Anup Patel <apatel@ventanamicro.com>
---
include/sbi_utils/irqchip/imsic.h | 50 ++++++
lib/utils/irqchip/imsic.c | 287 ++++++++++++++++++++++++++++++
lib/utils/irqchip/objects.mk | 1 +
3 files changed, 338 insertions(+)
create mode 100644 include/sbi_utils/irqchip/imsic.h
create mode 100644 lib/utils/irqchip/imsic.c
diff --git a/include/sbi_utils/irqchip/imsic.h b/include/sbi_utils/irqchip/imsic.h
new file mode 100644
index 0000000..cffcb5a
--- /dev/null
+++ b/include/sbi_utils/irqchip/imsic.h
@@ -0,0 +1,50 @@
+/*
+ * SPDX-License-Identifier: BSD-2-Clause
+ *
+ * Copyright (c) 2021 Western Digital Corporation or its affiliates.
+ * Copyright (c) 2022 Ventana Micro Systems Inc.
+ *
+ * Authors:
+ * Anup Patel <anup.patel@wdc.com>
+ */
+
+#ifndef __IRQCHIP_IMSIC_H__
+#define __IRQCHIP_IMSIC_H__
+
+#include <sbi/sbi_types.h>
+
+#define IMSIC_MMIO_PAGE_SHIFT 12
+#define IMSIC_MMIO_PAGE_SZ (1UL << IMSIC_MMIO_PAGE_SHIFT)
+
+#define IMSIC_MAX_REGS 16
+
+struct imsic_regs {
+ unsigned long addr;
+ unsigned long size;
+};
+
+struct imsic_data {
+ bool targets_mmode;
+ u32 guest_index_bits;
+ u32 hart_index_bits;
+ u32 group_index_bits;
+ u32 group_index_shift;
+ unsigned long num_ids;
+ struct imsic_regs regs[IMSIC_MAX_REGS];
+};
+
+int imsic_map_hartid_to_data(u32 hartid, struct imsic_data *imsic, int file);
+
+struct imsic_data *imsic_get_data(u32 hartid);
+
+int imsic_get_target_file(u32 hartid);
+
+void imsic_local_irqchip_init(void);
+
+int imsic_warm_irqchip_init(void);
+
+int imsic_data_check(struct imsic_data *imsic);
+
+int imsic_cold_irqchip_init(struct imsic_data *imsic);
+
+#endif
diff --git a/lib/utils/irqchip/imsic.c b/lib/utils/irqchip/imsic.c
new file mode 100644
index 0000000..123d01f
--- /dev/null
+++ b/lib/utils/irqchip/imsic.c
@@ -0,0 +1,287 @@
+/*
+ * SPDX-License-Identifier: BSD-2-Clause
+ *
+ * Copyright (c) 2021 Western Digital Corporation or its affiliates.
+ * Copyright (c) 2022 Ventana Micro Systems Inc.
+ *
+ * Authors:
+ * Anup Patel <anup.patel@wdc.com>
+ */
+
+#include <sbi/riscv_asm.h>
+#include <sbi/riscv_io.h>
+#include <sbi/riscv_encoding.h>
+#include <sbi/sbi_console.h>
+#include <sbi/sbi_domain.h>
+#include <sbi/sbi_hartmask.h>
+#include <sbi/sbi_ipi.h>
+#include <sbi/sbi_error.h>
+#include <sbi/sbi_trap.h>
+#include <sbi_utils/irqchip/imsic.h>
+
+#define IMSIC_MMIO_PAGE_LE 0x00
+#define IMSIC_MMIO_PAGE_BE 0x04
+
+#define IMSIC_MIN_ID 63
+#define IMSIC_MAX_ID 2047
+
+#define IMSIC_EIDELIVERY 0x70
+
+#define IMSIC_EITHRESHOLD 0x72
+
+#define IMSIC_TOPEI 0x76
+#define IMSIC_TOPEI_ID_SHIFT 16
+#define IMSIC_TOPEI_ID_MASK 0x7ff
+#define IMSIC_TOPEI_PRIO_MASK 0x7ff
+
+#define IMSIC_EIP0 0x80
+
+#define IMSIC_EIP63 0xbf
+
+#define IMSIC_EIE0 0xc0
+
+#define IMSIC_EIE63 0xff
+
+#define IMSIC_DISABLE_EIDELIVERY 0
+#define IMSIC_ENABLE_EIDELIVERY 1
+#define IMSIC_DISABLE_EITHRESHOLD 1
+#define IMSIC_ENABLE_EITHRESHOLD 0
+
+#define IMSIC_IPI_ID 1
+
+#define imsic_csr_write(__c, __v) \
+do { \
+ csr_write(CSR_MISELECT, __c); \
+ csr_write(CSR_MIREG, __v); \
+} while (0)
+
+#define imsic_csr_read(__c) \
+({ \
+ unsigned long __v; \
+ csr_write(CSR_MISELECT, __c); \
+ __v = csr_read(CSR_MIREG); \
+ __v; \
+})
+
+static struct imsic_data *imsic_hartid2data[SBI_HARTMASK_MAX_BITS];
+static int imsic_hartid2file[SBI_HARTMASK_MAX_BITS];
+
+int imsic_map_hartid_to_data(u32 hartid, struct imsic_data *imsic, int file)
+{
+ if (!imsic || !imsic->targets_mmode ||
+ (SBI_HARTMASK_MAX_BITS <= hartid))
+ return SBI_EINVAL;
+
+ imsic_hartid2data[hartid] = imsic;
+ imsic_hartid2file[hartid] = file;
+ return 0;
+}
+
+struct imsic_data *imsic_get_data(u32 hartid)
+{
+ if (SBI_HARTMASK_MAX_BITS <= hartid)
+ return NULL;
+ return imsic_hartid2data[hartid];
+}
+
+int imsic_get_target_file(u32 hartid)
+{
+ if ((SBI_HARTMASK_MAX_BITS <= hartid) ||
+ !imsic_hartid2data[hartid])
+ return SBI_ENOENT;
+ return imsic_hartid2file[hartid];
+}
+
+static int imsic_external_irqfn(struct sbi_trap_regs *regs)
+{
+ ulong mirq;
+
+ while ((mirq = csr_swap(CSR_MTOPEI, 0))) {
+ mirq = (mirq >> IMSIC_TOPEI_ID_SHIFT);
+
+ switch (mirq) {
+ case IMSIC_IPI_ID:
+ sbi_ipi_process();
+ break;
+ default:
+ sbi_printf("%s: unhandled IRQ%d\n",
+ __func__, (u32)mirq);
+ break;
+ }
+ }
+
+ return 0;
+}
+
+static void imsic_ipi_send(u32 target_hart)
+{
+ unsigned long reloff;
+ struct imsic_regs *regs;
+ struct imsic_data *data = imsic_hartid2data[target_hart];
+ int file = imsic_hartid2file[target_hart];
+
+ if (!data || !data->targets_mmode)
+ return;
+
+ regs = &data->regs[0];
+ reloff = file * (1UL << data->guest_index_bits) * IMSIC_MMIO_PAGE_SZ;
+ while (regs->size && (regs->size <= reloff)) {
+ reloff -= regs->size;
+ regs++;
+ }
+
+ if (regs->size && (reloff < regs->size))
+ writel(IMSIC_IPI_ID,
+ (void *)(regs->addr + reloff + IMSIC_MMIO_PAGE_LE));
+}
+
+static struct sbi_ipi_device imsic_ipi_device = {
+ .name = "aia-imsic",
+ .ipi_send = imsic_ipi_send
+};
+
+void imsic_local_irqchip_init(void)
+{
+ /*
+ * This function is expected to be called from:
+ * 1) nascent_init() platform callback which is called
+ * very early on each HART in boot-up path and and
+ * HSM resume path.
+ * 2) irqchip_init() platform callback which is called
+ * in boot-up path.
+ */
+
+ /* Setup threshold to allow all enabled interrupts */
+ imsic_csr_write(IMSIC_EITHRESHOLD, IMSIC_ENABLE_EITHRESHOLD);
+
+ /* Enable interrupt delivery */
+ imsic_csr_write(IMSIC_EIDELIVERY, IMSIC_ENABLE_EIDELIVERY);
+
+ /* Enable IPI */
+ csr_write(CSR_MSETEIENUM, IMSIC_IPI_ID);
+}
+
+int imsic_warm_irqchip_init(void)
+{
+ unsigned long i;
+ struct imsic_data *imsic = imsic_hartid2data[current_hartid()];
+
+ /* Sanity checks */
+ if (!imsic || !imsic->targets_mmode)
+ return SBI_EINVAL;
+
+ /* Disable all interrupts */
+ for (i = 1; i <= imsic->num_ids; i++)
+ csr_write(CSR_MCLREIENUM, i);
+
+ /* Clear IPI */
+ csr_write(CSR_MCLREIPNUM, IMSIC_IPI_ID);
+
+ /* Local IMSIC initialization */
+ imsic_local_irqchip_init();
+
+ return 0;
+}
+
+int imsic_data_check(struct imsic_data *imsic)
+{
+ u32 i, tmp;
+ unsigned long base_addr, addr, mask;
+
+ /* Sanity checks */
+ if (!imsic ||
+ (imsic->num_ids < IMSIC_MIN_ID) ||
+ (IMSIC_MAX_ID < imsic->num_ids))
+ return SBI_EINVAL;
+
+ tmp = BITS_PER_LONG - IMSIC_MMIO_PAGE_SHIFT;
+ if (tmp < imsic->guest_index_bits)
+ return SBI_EINVAL;
+
+ tmp = BITS_PER_LONG - IMSIC_MMIO_PAGE_SHIFT -
+ imsic->guest_index_bits;
+ if (tmp < imsic->hart_index_bits)
+ return SBI_EINVAL;
+
+ tmp = BITS_PER_LONG - IMSIC_MMIO_PAGE_SHIFT -
+ imsic->guest_index_bits - imsic->hart_index_bits;
+ if (tmp < imsic->group_index_bits)
+ return SBI_EINVAL;
+
+ tmp = IMSIC_MMIO_PAGE_SHIFT + imsic->guest_index_bits +
+ imsic->hart_index_bits;
+ if (imsic->group_index_shift < tmp)
+ return SBI_EINVAL;
+ tmp = imsic->group_index_bits + imsic->group_index_shift - 1;
+ if (tmp >= BITS_PER_LONG)
+ return SBI_EINVAL;
+
+ /*
+ * Number of interrupt identities should be 1 less than
+ * multiple of 63
+ */
+ if ((imsic->num_ids & IMSIC_MIN_ID) != IMSIC_MIN_ID)
+ return SBI_EINVAL;
+
+ /* We should have at least one regset */
+ if (!imsic->regs[0].size)
+ return SBI_EINVAL;
+
+ /* Match patter of each regset */
+ base_addr = imsic->regs[0].addr;
+ base_addr &= ~((1UL << (imsic->guest_index_bits +
+ imsic->hart_index_bits +
+ IMSIC_MMIO_PAGE_SHIFT)) - 1);
+ base_addr &= ~(((1UL << imsic->group_index_bits) - 1) <<
+ imsic->group_index_shift);
+ for (i = 0; i < IMSIC_MAX_REGS && imsic->regs[i].size; i++) {
+ mask = (1UL << imsic->guest_index_bits) * IMSIC_MMIO_PAGE_SZ;
+ mask -= 1UL;
+ if (imsic->regs[i].size & mask)
+ return SBI_EINVAL;
+
+ addr = imsic->regs[i].addr;
+ addr &= ~((1UL << (imsic->guest_index_bits +
+ imsic->hart_index_bits +
+ IMSIC_MMIO_PAGE_SHIFT)) - 1);
+ addr &= ~(((1UL << imsic->group_index_bits) - 1) <<
+ imsic->group_index_shift);
+ if (base_addr != addr)
+ return SBI_EINVAL;
+ }
+
+ return 0;
+}
+
+int imsic_cold_irqchip_init(struct imsic_data *imsic)
+{
+ int i, rc;
+ struct sbi_domain_memregion reg;
+
+ /* Sanity checks */
+ rc = imsic_data_check(imsic);
+ if (rc)
+ return rc;
+
+ /* We only initialize M-mode IMSIC */
+ if (!imsic->targets_mmode)
+ return SBI_EINVAL;
+
+ /* Setup external interrupt function for IMSIC */
+ sbi_trap_set_external_irqfn(imsic_external_irqfn);
+
+ /* Add IMSIC regions to the root domain */
+ for (i = 0; i < IMSIC_MAX_REGS && imsic->regs[i].size; i++) {
+ sbi_domain_memregion_init(imsic->regs[i].addr,
+ imsic->regs[i].size,
+ SBI_DOMAIN_MEMREGION_MMIO, ®);
+ rc = sbi_domain_root_add_memregion(®);
+ if (rc)
+ return rc;
+ }
+
+ /* Register IPI device */
+ sbi_ipi_set_device(&imsic_ipi_device);
+
+ return 0;
+}
diff --git a/lib/utils/irqchip/objects.mk b/lib/utils/irqchip/objects.mk
index 934f706..76a3c94 100644
--- a/lib/utils/irqchip/objects.mk
+++ b/lib/utils/irqchip/objects.mk
@@ -9,4 +9,5 @@
libsbiutils-objs-y += irqchip/fdt_irqchip.o
libsbiutils-objs-y += irqchip/fdt_irqchip_plic.o
+libsbiutils-objs-y += irqchip/imsic.o
libsbiutils-objs-y += irqchip/plic.o
--
2.25.1
^ permalink raw reply related [flat|nested] 36+ messages in thread* [PATCH v2 08/13] lib: utils/irqchip: Add IMSIC library
2022-02-09 15:04 ` [PATCH v2 08/13] lib: utils/irqchip: Add IMSIC library Anup Patel
@ 2022-02-12 9:09 ` Atish Patra
2022-02-15 15:19 ` Anup Patel
0 siblings, 1 reply; 36+ messages in thread
From: Atish Patra @ 2022-02-12 9:09 UTC (permalink / raw)
To: opensbi
On Wed, Feb 9, 2022 at 7:05 AM Anup Patel <apatel@ventanamicro.com> wrote:
>
> We add simple IMSIC library which is independent of hardware description
> format (FDT or ACPI). This IMSIC library can be used by custom OpenSBI
> platform support to setup IMSIC for external interrupts.
>
> Signed-off-by: Anup Patel <anup.patel@wdc.com>
> Signed-off-by: Anup Patel <apatel@ventanamicro.com>
> ---
> include/sbi_utils/irqchip/imsic.h | 50 ++++++
> lib/utils/irqchip/imsic.c | 287 ++++++++++++++++++++++++++++++
> lib/utils/irqchip/objects.mk | 1 +
> 3 files changed, 338 insertions(+)
> create mode 100644 include/sbi_utils/irqchip/imsic.h
> create mode 100644 lib/utils/irqchip/imsic.c
>
> diff --git a/include/sbi_utils/irqchip/imsic.h b/include/sbi_utils/irqchip/imsic.h
> new file mode 100644
> index 0000000..cffcb5a
> --- /dev/null
> +++ b/include/sbi_utils/irqchip/imsic.h
> @@ -0,0 +1,50 @@
> +/*
> + * SPDX-License-Identifier: BSD-2-Clause
> + *
> + * Copyright (c) 2021 Western Digital Corporation or its affiliates.
> + * Copyright (c) 2022 Ventana Micro Systems Inc.
> + *
> + * Authors:
> + * Anup Patel <anup.patel@wdc.com>
> + */
> +
> +#ifndef __IRQCHIP_IMSIC_H__
> +#define __IRQCHIP_IMSIC_H__
> +
> +#include <sbi/sbi_types.h>
> +
> +#define IMSIC_MMIO_PAGE_SHIFT 12
> +#define IMSIC_MMIO_PAGE_SZ (1UL << IMSIC_MMIO_PAGE_SHIFT)
> +
> +#define IMSIC_MAX_REGS 16
> +
> +struct imsic_regs {
> + unsigned long addr;
> + unsigned long size;
> +};
> +
> +struct imsic_data {
> + bool targets_mmode;
> + u32 guest_index_bits;
> + u32 hart_index_bits;
> + u32 group_index_bits;
> + u32 group_index_shift;
> + unsigned long num_ids;
> + struct imsic_regs regs[IMSIC_MAX_REGS];
> +};
> +
> +int imsic_map_hartid_to_data(u32 hartid, struct imsic_data *imsic, int file);
> +
> +struct imsic_data *imsic_get_data(u32 hartid);
> +
> +int imsic_get_target_file(u32 hartid);
> +
> +void imsic_local_irqchip_init(void);
> +
> +int imsic_warm_irqchip_init(void);
> +
> +int imsic_data_check(struct imsic_data *imsic);
> +
> +int imsic_cold_irqchip_init(struct imsic_data *imsic);
> +
> +#endif
> diff --git a/lib/utils/irqchip/imsic.c b/lib/utils/irqchip/imsic.c
> new file mode 100644
> index 0000000..123d01f
> --- /dev/null
> +++ b/lib/utils/irqchip/imsic.c
> @@ -0,0 +1,287 @@
> +/*
> + * SPDX-License-Identifier: BSD-2-Clause
> + *
> + * Copyright (c) 2021 Western Digital Corporation or its affiliates.
> + * Copyright (c) 2022 Ventana Micro Systems Inc.
> + *
> + * Authors:
> + * Anup Patel <anup.patel@wdc.com>
> + */
> +
> +#include <sbi/riscv_asm.h>
> +#include <sbi/riscv_io.h>
> +#include <sbi/riscv_encoding.h>
> +#include <sbi/sbi_console.h>
> +#include <sbi/sbi_domain.h>
> +#include <sbi/sbi_hartmask.h>
> +#include <sbi/sbi_ipi.h>
> +#include <sbi/sbi_error.h>
> +#include <sbi/sbi_trap.h>
> +#include <sbi_utils/irqchip/imsic.h>
> +
> +#define IMSIC_MMIO_PAGE_LE 0x00
> +#define IMSIC_MMIO_PAGE_BE 0x04
> +
> +#define IMSIC_MIN_ID 63
> +#define IMSIC_MAX_ID 2047
> +
> +#define IMSIC_EIDELIVERY 0x70
> +
> +#define IMSIC_EITHRESHOLD 0x72
> +
> +#define IMSIC_TOPEI 0x76
> +#define IMSIC_TOPEI_ID_SHIFT 16
> +#define IMSIC_TOPEI_ID_MASK 0x7ff
> +#define IMSIC_TOPEI_PRIO_MASK 0x7ff
> +
> +#define IMSIC_EIP0 0x80
> +
> +#define IMSIC_EIP63 0xbf
> +
> +#define IMSIC_EIE0 0xc0
> +
> +#define IMSIC_EIE63 0xff
> +
> +#define IMSIC_DISABLE_EIDELIVERY 0
> +#define IMSIC_ENABLE_EIDELIVERY 1
> +#define IMSIC_DISABLE_EITHRESHOLD 1
> +#define IMSIC_ENABLE_EITHRESHOLD 0
> +
> +#define IMSIC_IPI_ID 1
> +
> +#define imsic_csr_write(__c, __v) \
> +do { \
> + csr_write(CSR_MISELECT, __c); \
> + csr_write(CSR_MIREG, __v); \
> +} while (0)
> +
> +#define imsic_csr_read(__c) \
> +({ \
> + unsigned long __v; \
> + csr_write(CSR_MISELECT, __c); \
> + __v = csr_read(CSR_MIREG); \
> + __v; \
> +})
> +
> +static struct imsic_data *imsic_hartid2data[SBI_HARTMASK_MAX_BITS];
> +static int imsic_hartid2file[SBI_HARTMASK_MAX_BITS];
> +
> +int imsic_map_hartid_to_data(u32 hartid, struct imsic_data *imsic, int file)
> +{
> + if (!imsic || !imsic->targets_mmode ||
> + (SBI_HARTMASK_MAX_BITS <= hartid))
> + return SBI_EINVAL;
> +
> + imsic_hartid2data[hartid] = imsic;
> + imsic_hartid2file[hartid] = file;
> + return 0;
> +}
> +
> +struct imsic_data *imsic_get_data(u32 hartid)
> +{
> + if (SBI_HARTMASK_MAX_BITS <= hartid)
> + return NULL;
> + return imsic_hartid2data[hartid];
> +}
> +
> +int imsic_get_target_file(u32 hartid)
> +{
> + if ((SBI_HARTMASK_MAX_BITS <= hartid) ||
> + !imsic_hartid2data[hartid])
> + return SBI_ENOENT;
> + return imsic_hartid2file[hartid];
> +}
> +
> +static int imsic_external_irqfn(struct sbi_trap_regs *regs)
> +{
> + ulong mirq;
> +
> + while ((mirq = csr_swap(CSR_MTOPEI, 0))) {
> + mirq = (mirq >> IMSIC_TOPEI_ID_SHIFT);
> +
> + switch (mirq) {
> + case IMSIC_IPI_ID:
> + sbi_ipi_process();
> + break;
> + default:
> + sbi_printf("%s: unhandled IRQ%d\n",
> + __func__, (u32)mirq);
> + break;
> + }
> + }
> +
> + return 0;
> +}
> +
> +static void imsic_ipi_send(u32 target_hart)
> +{
> + unsigned long reloff;
> + struct imsic_regs *regs;
> + struct imsic_data *data = imsic_hartid2data[target_hart];
> + int file = imsic_hartid2file[target_hart];
> +
> + if (!data || !data->targets_mmode)
> + return;
> +
> + regs = &data->regs[0];
> + reloff = file * (1UL << data->guest_index_bits) * IMSIC_MMIO_PAGE_SZ;
> + while (regs->size && (regs->size <= reloff)) {
> + reloff -= regs->size;
> + regs++;
> + }
> +
> + if (regs->size && (reloff < regs->size))
> + writel(IMSIC_IPI_ID,
> + (void *)(regs->addr + reloff + IMSIC_MMIO_PAGE_LE));
> +}
> +
> +static struct sbi_ipi_device imsic_ipi_device = {
> + .name = "aia-imsic",
> + .ipi_send = imsic_ipi_send
> +};
> +
> +void imsic_local_irqchip_init(void)
> +{
> + /*
> + * This function is expected to be called from:
> + * 1) nascent_init() platform callback which is called
> + * very early on each HART in boot-up path and and
> + * HSM resume path.
> + * 2) irqchip_init() platform callback which is called
> + * in boot-up path.
> + */
> +
> + /* Setup threshold to allow all enabled interrupts */
> + imsic_csr_write(IMSIC_EITHRESHOLD, IMSIC_ENABLE_EITHRESHOLD);
> +
> + /* Enable interrupt delivery */
> + imsic_csr_write(IMSIC_EIDELIVERY, IMSIC_ENABLE_EIDELIVERY);
> +
> + /* Enable IPI */
> + csr_write(CSR_MSETEIENUM, IMSIC_IPI_ID);
> +}
> +
> +int imsic_warm_irqchip_init(void)
> +{
> + unsigned long i;
> + struct imsic_data *imsic = imsic_hartid2data[current_hartid()];
> +
> + /* Sanity checks */
> + if (!imsic || !imsic->targets_mmode)
> + return SBI_EINVAL;
> +
> + /* Disable all interrupts */
> + for (i = 1; i <= imsic->num_ids; i++)
> + csr_write(CSR_MCLREIENUM, i);
> +
> + /* Clear IPI */
> + csr_write(CSR_MCLREIPNUM, IMSIC_IPI_ID);
> +
> + /* Local IMSIC initialization */
> + imsic_local_irqchip_init();
> +
> + return 0;
> +}
> +
> +int imsic_data_check(struct imsic_data *imsic)
> +{
> + u32 i, tmp;
> + unsigned long base_addr, addr, mask;
> +
> + /* Sanity checks */
> + if (!imsic ||
> + (imsic->num_ids < IMSIC_MIN_ID) ||
> + (IMSIC_MAX_ID < imsic->num_ids))
> + return SBI_EINVAL;
> +
> + tmp = BITS_PER_LONG - IMSIC_MMIO_PAGE_SHIFT;
> + if (tmp < imsic->guest_index_bits)
> + return SBI_EINVAL;
> +
> + tmp = BITS_PER_LONG - IMSIC_MMIO_PAGE_SHIFT -
> + imsic->guest_index_bits;
> + if (tmp < imsic->hart_index_bits)
> + return SBI_EINVAL;
> +
> + tmp = BITS_PER_LONG - IMSIC_MMIO_PAGE_SHIFT -
> + imsic->guest_index_bits - imsic->hart_index_bits;
> + if (tmp < imsic->group_index_bits)
> + return SBI_EINVAL;
> +
> + tmp = IMSIC_MMIO_PAGE_SHIFT + imsic->guest_index_bits +
> + imsic->hart_index_bits;
> + if (imsic->group_index_shift < tmp)
> + return SBI_EINVAL;
> + tmp = imsic->group_index_bits + imsic->group_index_shift - 1;
> + if (tmp >= BITS_PER_LONG)
> + return SBI_EINVAL;
> +
> + /*
> + * Number of interrupt identities should be 1 less than
> + * multiple of 63
> + */
> + if ((imsic->num_ids & IMSIC_MIN_ID) != IMSIC_MIN_ID)
> + return SBI_EINVAL;
> +
> + /* We should have at least one regset */
> + if (!imsic->regs[0].size)
> + return SBI_EINVAL;
> +
> + /* Match patter of each regset */
> + base_addr = imsic->regs[0].addr;
> + base_addr &= ~((1UL << (imsic->guest_index_bits +
> + imsic->hart_index_bits +
> + IMSIC_MMIO_PAGE_SHIFT)) - 1);
> + base_addr &= ~(((1UL << imsic->group_index_bits) - 1) <<
> + imsic->group_index_shift);
> + for (i = 0; i < IMSIC_MAX_REGS && imsic->regs[i].size; i++) {
> + mask = (1UL << imsic->guest_index_bits) * IMSIC_MMIO_PAGE_SZ;
> + mask -= 1UL;
> + if (imsic->regs[i].size & mask)
> + return SBI_EINVAL;
> +
> + addr = imsic->regs[i].addr;
> + addr &= ~((1UL << (imsic->guest_index_bits +
> + imsic->hart_index_bits +
> + IMSIC_MMIO_PAGE_SHIFT)) - 1);
> + addr &= ~(((1UL << imsic->group_index_bits) - 1) <<
> + imsic->group_index_shift);
> + if (base_addr != addr)
> + return SBI_EINVAL;
> + }
> +
> + return 0;
> +}
> +
> +int imsic_cold_irqchip_init(struct imsic_data *imsic)
> +{
> + int i, rc;
> + struct sbi_domain_memregion reg;
> +
> + /* Sanity checks */
> + rc = imsic_data_check(imsic);
> + if (rc)
> + return rc;
> +
> + /* We only initialize M-mode IMSIC */
> + if (!imsic->targets_mmode)
> + return SBI_EINVAL;
> +
> + /* Setup external interrupt function for IMSIC */
> + sbi_trap_set_external_irqfn(imsic_external_irqfn);
> +
> + /* Add IMSIC regions to the root domain */
> + for (i = 0; i < IMSIC_MAX_REGS && imsic->regs[i].size; i++) {
> + sbi_domain_memregion_init(imsic->regs[i].addr,
> + imsic->regs[i].size,
> + SBI_DOMAIN_MEMREGION_MMIO, ®);
> + rc = sbi_domain_root_add_memregion(®);
> + if (rc)
> + return rc;
> + }
> +
> + /* Register IPI device */
> + sbi_ipi_set_device(&imsic_ipi_device);
> +
> + return 0;
> +}
> diff --git a/lib/utils/irqchip/objects.mk b/lib/utils/irqchip/objects.mk
> index 934f706..76a3c94 100644
> --- a/lib/utils/irqchip/objects.mk
> +++ b/lib/utils/irqchip/objects.mk
> @@ -9,4 +9,5 @@
>
> libsbiutils-objs-y += irqchip/fdt_irqchip.o
> libsbiutils-objs-y += irqchip/fdt_irqchip_plic.o
> +libsbiutils-objs-y += irqchip/imsic.o
> libsbiutils-objs-y += irqchip/plic.o
> --
> 2.25.1
>
Reviewed-by: Atish Patra <atishp@rivosinc.com>
--
Regards,
Atish
^ permalink raw reply [flat|nested] 36+ messages in thread* [PATCH v2 08/13] lib: utils/irqchip: Add IMSIC library
2022-02-12 9:09 ` Atish Patra
@ 2022-02-15 15:19 ` Anup Patel
0 siblings, 0 replies; 36+ messages in thread
From: Anup Patel @ 2022-02-15 15:19 UTC (permalink / raw)
To: opensbi
On Sat, Feb 12, 2022 at 2:39 PM Atish Patra <atishp@atishpatra.org> wrote:
>
> On Wed, Feb 9, 2022 at 7:05 AM Anup Patel <apatel@ventanamicro.com> wrote:
> >
> > We add simple IMSIC library which is independent of hardware description
> > format (FDT or ACPI). This IMSIC library can be used by custom OpenSBI
> > platform support to setup IMSIC for external interrupts.
> >
> > Signed-off-by: Anup Patel <anup.patel@wdc.com>
> > Signed-off-by: Anup Patel <apatel@ventanamicro.com>
> > ---
> > include/sbi_utils/irqchip/imsic.h | 50 ++++++
> > lib/utils/irqchip/imsic.c | 287 ++++++++++++++++++++++++++++++
> > lib/utils/irqchip/objects.mk | 1 +
> > 3 files changed, 338 insertions(+)
> > create mode 100644 include/sbi_utils/irqchip/imsic.h
> > create mode 100644 lib/utils/irqchip/imsic.c
> >
> > diff --git a/include/sbi_utils/irqchip/imsic.h b/include/sbi_utils/irqchip/imsic.h
> > new file mode 100644
> > index 0000000..cffcb5a
> > --- /dev/null
> > +++ b/include/sbi_utils/irqchip/imsic.h
> > @@ -0,0 +1,50 @@
> > +/*
> > + * SPDX-License-Identifier: BSD-2-Clause
> > + *
> > + * Copyright (c) 2021 Western Digital Corporation or its affiliates.
> > + * Copyright (c) 2022 Ventana Micro Systems Inc.
> > + *
> > + * Authors:
> > + * Anup Patel <anup.patel@wdc.com>
> > + */
> > +
> > +#ifndef __IRQCHIP_IMSIC_H__
> > +#define __IRQCHIP_IMSIC_H__
> > +
> > +#include <sbi/sbi_types.h>
> > +
> > +#define IMSIC_MMIO_PAGE_SHIFT 12
> > +#define IMSIC_MMIO_PAGE_SZ (1UL << IMSIC_MMIO_PAGE_SHIFT)
> > +
> > +#define IMSIC_MAX_REGS 16
> > +
> > +struct imsic_regs {
> > + unsigned long addr;
> > + unsigned long size;
> > +};
> > +
> > +struct imsic_data {
> > + bool targets_mmode;
> > + u32 guest_index_bits;
> > + u32 hart_index_bits;
> > + u32 group_index_bits;
> > + u32 group_index_shift;
> > + unsigned long num_ids;
> > + struct imsic_regs regs[IMSIC_MAX_REGS];
> > +};
> > +
> > +int imsic_map_hartid_to_data(u32 hartid, struct imsic_data *imsic, int file);
> > +
> > +struct imsic_data *imsic_get_data(u32 hartid);
> > +
> > +int imsic_get_target_file(u32 hartid);
> > +
> > +void imsic_local_irqchip_init(void);
> > +
> > +int imsic_warm_irqchip_init(void);
> > +
> > +int imsic_data_check(struct imsic_data *imsic);
> > +
> > +int imsic_cold_irqchip_init(struct imsic_data *imsic);
> > +
> > +#endif
> > diff --git a/lib/utils/irqchip/imsic.c b/lib/utils/irqchip/imsic.c
> > new file mode 100644
> > index 0000000..123d01f
> > --- /dev/null
> > +++ b/lib/utils/irqchip/imsic.c
> > @@ -0,0 +1,287 @@
> > +/*
> > + * SPDX-License-Identifier: BSD-2-Clause
> > + *
> > + * Copyright (c) 2021 Western Digital Corporation or its affiliates.
> > + * Copyright (c) 2022 Ventana Micro Systems Inc.
> > + *
> > + * Authors:
> > + * Anup Patel <anup.patel@wdc.com>
> > + */
> > +
> > +#include <sbi/riscv_asm.h>
> > +#include <sbi/riscv_io.h>
> > +#include <sbi/riscv_encoding.h>
> > +#include <sbi/sbi_console.h>
> > +#include <sbi/sbi_domain.h>
> > +#include <sbi/sbi_hartmask.h>
> > +#include <sbi/sbi_ipi.h>
> > +#include <sbi/sbi_error.h>
> > +#include <sbi/sbi_trap.h>
> > +#include <sbi_utils/irqchip/imsic.h>
> > +
> > +#define IMSIC_MMIO_PAGE_LE 0x00
> > +#define IMSIC_MMIO_PAGE_BE 0x04
> > +
> > +#define IMSIC_MIN_ID 63
> > +#define IMSIC_MAX_ID 2047
> > +
> > +#define IMSIC_EIDELIVERY 0x70
> > +
> > +#define IMSIC_EITHRESHOLD 0x72
> > +
> > +#define IMSIC_TOPEI 0x76
> > +#define IMSIC_TOPEI_ID_SHIFT 16
> > +#define IMSIC_TOPEI_ID_MASK 0x7ff
> > +#define IMSIC_TOPEI_PRIO_MASK 0x7ff
> > +
> > +#define IMSIC_EIP0 0x80
> > +
> > +#define IMSIC_EIP63 0xbf
> > +
> > +#define IMSIC_EIE0 0xc0
> > +
> > +#define IMSIC_EIE63 0xff
> > +
> > +#define IMSIC_DISABLE_EIDELIVERY 0
> > +#define IMSIC_ENABLE_EIDELIVERY 1
> > +#define IMSIC_DISABLE_EITHRESHOLD 1
> > +#define IMSIC_ENABLE_EITHRESHOLD 0
> > +
> > +#define IMSIC_IPI_ID 1
> > +
> > +#define imsic_csr_write(__c, __v) \
> > +do { \
> > + csr_write(CSR_MISELECT, __c); \
> > + csr_write(CSR_MIREG, __v); \
> > +} while (0)
> > +
> > +#define imsic_csr_read(__c) \
> > +({ \
> > + unsigned long __v; \
> > + csr_write(CSR_MISELECT, __c); \
> > + __v = csr_read(CSR_MIREG); \
> > + __v; \
> > +})
> > +
> > +static struct imsic_data *imsic_hartid2data[SBI_HARTMASK_MAX_BITS];
> > +static int imsic_hartid2file[SBI_HARTMASK_MAX_BITS];
> > +
> > +int imsic_map_hartid_to_data(u32 hartid, struct imsic_data *imsic, int file)
> > +{
> > + if (!imsic || !imsic->targets_mmode ||
> > + (SBI_HARTMASK_MAX_BITS <= hartid))
> > + return SBI_EINVAL;
> > +
> > + imsic_hartid2data[hartid] = imsic;
> > + imsic_hartid2file[hartid] = file;
> > + return 0;
> > +}
> > +
> > +struct imsic_data *imsic_get_data(u32 hartid)
> > +{
> > + if (SBI_HARTMASK_MAX_BITS <= hartid)
> > + return NULL;
> > + return imsic_hartid2data[hartid];
> > +}
> > +
> > +int imsic_get_target_file(u32 hartid)
> > +{
> > + if ((SBI_HARTMASK_MAX_BITS <= hartid) ||
> > + !imsic_hartid2data[hartid])
> > + return SBI_ENOENT;
> > + return imsic_hartid2file[hartid];
> > +}
> > +
> > +static int imsic_external_irqfn(struct sbi_trap_regs *regs)
> > +{
> > + ulong mirq;
> > +
> > + while ((mirq = csr_swap(CSR_MTOPEI, 0))) {
> > + mirq = (mirq >> IMSIC_TOPEI_ID_SHIFT);
> > +
> > + switch (mirq) {
> > + case IMSIC_IPI_ID:
> > + sbi_ipi_process();
> > + break;
> > + default:
> > + sbi_printf("%s: unhandled IRQ%d\n",
> > + __func__, (u32)mirq);
> > + break;
> > + }
> > + }
> > +
> > + return 0;
> > +}
> > +
> > +static void imsic_ipi_send(u32 target_hart)
> > +{
> > + unsigned long reloff;
> > + struct imsic_regs *regs;
> > + struct imsic_data *data = imsic_hartid2data[target_hart];
> > + int file = imsic_hartid2file[target_hart];
> > +
> > + if (!data || !data->targets_mmode)
> > + return;
> > +
> > + regs = &data->regs[0];
> > + reloff = file * (1UL << data->guest_index_bits) * IMSIC_MMIO_PAGE_SZ;
> > + while (regs->size && (regs->size <= reloff)) {
> > + reloff -= regs->size;
> > + regs++;
> > + }
> > +
> > + if (regs->size && (reloff < regs->size))
> > + writel(IMSIC_IPI_ID,
> > + (void *)(regs->addr + reloff + IMSIC_MMIO_PAGE_LE));
> > +}
> > +
> > +static struct sbi_ipi_device imsic_ipi_device = {
> > + .name = "aia-imsic",
> > + .ipi_send = imsic_ipi_send
> > +};
> > +
> > +void imsic_local_irqchip_init(void)
> > +{
> > + /*
> > + * This function is expected to be called from:
> > + * 1) nascent_init() platform callback which is called
> > + * very early on each HART in boot-up path and and
> > + * HSM resume path.
> > + * 2) irqchip_init() platform callback which is called
> > + * in boot-up path.
> > + */
> > +
> > + /* Setup threshold to allow all enabled interrupts */
> > + imsic_csr_write(IMSIC_EITHRESHOLD, IMSIC_ENABLE_EITHRESHOLD);
> > +
> > + /* Enable interrupt delivery */
> > + imsic_csr_write(IMSIC_EIDELIVERY, IMSIC_ENABLE_EIDELIVERY);
> > +
> > + /* Enable IPI */
> > + csr_write(CSR_MSETEIENUM, IMSIC_IPI_ID);
> > +}
> > +
> > +int imsic_warm_irqchip_init(void)
> > +{
> > + unsigned long i;
> > + struct imsic_data *imsic = imsic_hartid2data[current_hartid()];
> > +
> > + /* Sanity checks */
> > + if (!imsic || !imsic->targets_mmode)
> > + return SBI_EINVAL;
> > +
> > + /* Disable all interrupts */
> > + for (i = 1; i <= imsic->num_ids; i++)
> > + csr_write(CSR_MCLREIENUM, i);
> > +
> > + /* Clear IPI */
> > + csr_write(CSR_MCLREIPNUM, IMSIC_IPI_ID);
> > +
> > + /* Local IMSIC initialization */
> > + imsic_local_irqchip_init();
> > +
> > + return 0;
> > +}
> > +
> > +int imsic_data_check(struct imsic_data *imsic)
> > +{
> > + u32 i, tmp;
> > + unsigned long base_addr, addr, mask;
> > +
> > + /* Sanity checks */
> > + if (!imsic ||
> > + (imsic->num_ids < IMSIC_MIN_ID) ||
> > + (IMSIC_MAX_ID < imsic->num_ids))
> > + return SBI_EINVAL;
> > +
> > + tmp = BITS_PER_LONG - IMSIC_MMIO_PAGE_SHIFT;
> > + if (tmp < imsic->guest_index_bits)
> > + return SBI_EINVAL;
> > +
> > + tmp = BITS_PER_LONG - IMSIC_MMIO_PAGE_SHIFT -
> > + imsic->guest_index_bits;
> > + if (tmp < imsic->hart_index_bits)
> > + return SBI_EINVAL;
> > +
> > + tmp = BITS_PER_LONG - IMSIC_MMIO_PAGE_SHIFT -
> > + imsic->guest_index_bits - imsic->hart_index_bits;
> > + if (tmp < imsic->group_index_bits)
> > + return SBI_EINVAL;
> > +
> > + tmp = IMSIC_MMIO_PAGE_SHIFT + imsic->guest_index_bits +
> > + imsic->hart_index_bits;
> > + if (imsic->group_index_shift < tmp)
> > + return SBI_EINVAL;
> > + tmp = imsic->group_index_bits + imsic->group_index_shift - 1;
> > + if (tmp >= BITS_PER_LONG)
> > + return SBI_EINVAL;
> > +
> > + /*
> > + * Number of interrupt identities should be 1 less than
> > + * multiple of 63
> > + */
> > + if ((imsic->num_ids & IMSIC_MIN_ID) != IMSIC_MIN_ID)
> > + return SBI_EINVAL;
> > +
> > + /* We should have at least one regset */
> > + if (!imsic->regs[0].size)
> > + return SBI_EINVAL;
> > +
> > + /* Match patter of each regset */
> > + base_addr = imsic->regs[0].addr;
> > + base_addr &= ~((1UL << (imsic->guest_index_bits +
> > + imsic->hart_index_bits +
> > + IMSIC_MMIO_PAGE_SHIFT)) - 1);
> > + base_addr &= ~(((1UL << imsic->group_index_bits) - 1) <<
> > + imsic->group_index_shift);
> > + for (i = 0; i < IMSIC_MAX_REGS && imsic->regs[i].size; i++) {
> > + mask = (1UL << imsic->guest_index_bits) * IMSIC_MMIO_PAGE_SZ;
> > + mask -= 1UL;
> > + if (imsic->regs[i].size & mask)
> > + return SBI_EINVAL;
> > +
> > + addr = imsic->regs[i].addr;
> > + addr &= ~((1UL << (imsic->guest_index_bits +
> > + imsic->hart_index_bits +
> > + IMSIC_MMIO_PAGE_SHIFT)) - 1);
> > + addr &= ~(((1UL << imsic->group_index_bits) - 1) <<
> > + imsic->group_index_shift);
> > + if (base_addr != addr)
> > + return SBI_EINVAL;
> > + }
> > +
> > + return 0;
> > +}
> > +
> > +int imsic_cold_irqchip_init(struct imsic_data *imsic)
> > +{
> > + int i, rc;
> > + struct sbi_domain_memregion reg;
> > +
> > + /* Sanity checks */
> > + rc = imsic_data_check(imsic);
> > + if (rc)
> > + return rc;
> > +
> > + /* We only initialize M-mode IMSIC */
> > + if (!imsic->targets_mmode)
> > + return SBI_EINVAL;
> > +
> > + /* Setup external interrupt function for IMSIC */
> > + sbi_trap_set_external_irqfn(imsic_external_irqfn);
> > +
> > + /* Add IMSIC regions to the root domain */
> > + for (i = 0; i < IMSIC_MAX_REGS && imsic->regs[i].size; i++) {
> > + sbi_domain_memregion_init(imsic->regs[i].addr,
> > + imsic->regs[i].size,
> > + SBI_DOMAIN_MEMREGION_MMIO, ®);
> > + rc = sbi_domain_root_add_memregion(®);
> > + if (rc)
> > + return rc;
> > + }
> > +
> > + /* Register IPI device */
> > + sbi_ipi_set_device(&imsic_ipi_device);
> > +
> > + return 0;
> > +}
> > diff --git a/lib/utils/irqchip/objects.mk b/lib/utils/irqchip/objects.mk
> > index 934f706..76a3c94 100644
> > --- a/lib/utils/irqchip/objects.mk
> > +++ b/lib/utils/irqchip/objects.mk
> > @@ -9,4 +9,5 @@
> >
> > libsbiutils-objs-y += irqchip/fdt_irqchip.o
> > libsbiutils-objs-y += irqchip/fdt_irqchip_plic.o
> > +libsbiutils-objs-y += irqchip/imsic.o
> > libsbiutils-objs-y += irqchip/plic.o
> > --
> > 2.25.1
> >
>
>
> Reviewed-by: Atish Patra <atishp@rivosinc.com>
Applied this patch to the riscv/opensbi repo.
Regards,
Anup
>
> --
> Regards,
> Atish
^ permalink raw reply [flat|nested] 36+ messages in thread
* [PATCH v2 09/13] lib: utils/irqchip: Add FDT based driver for IMSIC
2022-02-09 15:04 [PATCH v2 00/13] OpenSBI RISC-V AIA Support Anup Patel
` (7 preceding siblings ...)
2022-02-09 15:04 ` [PATCH v2 08/13] lib: utils/irqchip: Add IMSIC library Anup Patel
@ 2022-02-09 15:04 ` Anup Patel
2022-02-12 0:54 ` Atish Patra
2022-02-09 15:04 ` [PATCH v2 10/13] lib: utils: Disable appropriate IMSIC DT nodes in fdt_fixups() Anup Patel
` (3 subsequent siblings)
12 siblings, 1 reply; 36+ messages in thread
From: Anup Patel @ 2022-02-09 15:04 UTC (permalink / raw)
To: opensbi
We add simple FDT irqchip driver for IMSIC so that generic platform
(and other FDT based platforms) can utilize common IMIC library.
Signed-off-by: Anup Patel <anup.patel@wdc.com>
Signed-off-by: Anup Patel <apatel@ventanamicro.com>
---
include/sbi_utils/fdt/fdt_helper.h | 6 ++
lib/utils/fdt/fdt_helper.c | 103 +++++++++++++++++++++++++
lib/utils/irqchip/fdt_irqchip.c | 2 +
lib/utils/irqchip/fdt_irqchip_imsic.c | 106 ++++++++++++++++++++++++++
lib/utils/irqchip/objects.mk | 1 +
platform/generic/platform.c | 12 +++
6 files changed, 230 insertions(+)
create mode 100644 lib/utils/irqchip/fdt_irqchip_imsic.c
diff --git a/include/sbi_utils/fdt/fdt_helper.h b/include/sbi_utils/fdt/fdt_helper.h
index 24fee7a..4c8d29e 100644
--- a/include/sbi_utils/fdt/fdt_helper.h
+++ b/include/sbi_utils/fdt/fdt_helper.h
@@ -68,6 +68,12 @@ int fdt_parse_uart8250_node(void *fdt, int nodeoffset,
int fdt_parse_uart8250(void *fdt, struct platform_uart_data *uart,
const char *compatible);
+struct imsic_data;
+
+bool fdt_check_imsic_mlevel(void *fdt);
+
+int fdt_parse_imsic_node(void *fdt, int nodeoff, struct imsic_data *imsic);
+
struct plic_data;
int fdt_parse_plic_node(void *fdt, int nodeoffset, struct plic_data *plic);
diff --git a/lib/utils/fdt/fdt_helper.c b/lib/utils/fdt/fdt_helper.c
index 5bf4021..e179b79 100644
--- a/lib/utils/fdt/fdt_helper.c
+++ b/lib/utils/fdt/fdt_helper.c
@@ -13,6 +13,7 @@
#include <sbi/sbi_platform.h>
#include <sbi/sbi_scratch.h>
#include <sbi_utils/fdt/fdt_helper.h>
+#include <sbi_utils/irqchip/imsic.h>
#include <sbi_utils/irqchip/plic.h>
#define DEFAULT_UART_FREQ 0
@@ -465,6 +466,108 @@ int fdt_parse_uart8250(void *fdt, struct platform_uart_data *uart,
return fdt_parse_uart8250_node(fdt, nodeoffset, uart);
}
+bool fdt_check_imsic_mlevel(void *fdt)
+{
+ const fdt32_t *val;
+ int i, len, noff = 0;
+
+ if (!fdt)
+ return false;
+
+ while ((noff = fdt_node_offset_by_compatible(fdt, noff,
+ "riscv,imsics")) >= 0) {
+ val = fdt_getprop(fdt, noff, "interrupts-extended", &len);
+ if (val && len > sizeof(fdt32_t)) {
+ len = len / sizeof(fdt32_t);
+ for (i = 0; i < len; i += 2) {
+ if (fdt32_to_cpu(val[i + 1]) == IRQ_M_EXT)
+ return true;
+ }
+ }
+ }
+
+ return false;
+}
+
+int fdt_parse_imsic_node(void *fdt, int nodeoff, struct imsic_data *imsic)
+{
+ const fdt32_t *val;
+ struct imsic_regs *regs;
+ uint64_t reg_addr, reg_size;
+ int i, rc, len, nr_parent_irqs;
+
+ if (nodeoff < 0 || !imsic || !fdt)
+ return SBI_ENODEV;
+
+ imsic->targets_mmode = false;
+ val = fdt_getprop(fdt, nodeoff, "interrupts-extended", &len);
+ if (val && len > sizeof(fdt32_t)) {
+ len = len / sizeof(fdt32_t);
+ nr_parent_irqs = len / 2;
+ for (i = 0; i < len; i += 2) {
+ if (fdt32_to_cpu(val[i + 1]) == IRQ_M_EXT) {
+ imsic->targets_mmode = true;
+ break;
+ }
+ }
+ } else
+ return SBI_EINVAL;
+
+ val = fdt_getprop(fdt, nodeoff, "riscv,guest-index-bits", &len);
+ if (val && len > 0)
+ imsic->guest_index_bits = fdt32_to_cpu(*val);
+ else
+ imsic->guest_index_bits = 0;
+
+ val = fdt_getprop(fdt, nodeoff, "riscv,hart-index-bits", &len);
+ if (val && len > 0) {
+ imsic->hart_index_bits = fdt32_to_cpu(*val);
+ } else {
+ imsic->hart_index_bits = sbi_fls(nr_parent_irqs);
+ if ((1UL << imsic->hart_index_bits) < nr_parent_irqs)
+ imsic->hart_index_bits++;
+ }
+
+ val = fdt_getprop(fdt, nodeoff, "riscv,group-index-bits", &len);
+ if (val && len > 0)
+ imsic->group_index_bits = fdt32_to_cpu(*val);
+ else
+ imsic->group_index_bits = 0;
+
+ val = fdt_getprop(fdt, nodeoff, "riscv,group-index-shift", &len);
+ if (val && len > 0)
+ imsic->group_index_shift = fdt32_to_cpu(*val);
+ else
+ imsic->group_index_shift = 2 * IMSIC_MMIO_PAGE_SHIFT;
+
+ val = fdt_getprop(fdt, nodeoff, "riscv,num-ids", &len);
+ if (val && len > 0)
+ imsic->num_ids = fdt32_to_cpu(*val);
+ else
+ return SBI_EINVAL;
+
+ for (i = 0; i < IMSIC_MAX_REGS; i++) {
+ regs = &imsic->regs[i];
+ regs->addr = 0;
+ regs->size = 0;
+ }
+
+ for (i = 0; i < (IMSIC_MAX_REGS - 1); i++) {
+ regs = &imsic->regs[i];
+
+ rc = fdt_get_node_addr_size(fdt, nodeoff, i,
+ ®_addr, ®_size);
+ if (rc < 0 || !reg_addr || !reg_size)
+ break;
+ regs->addr = reg_addr;
+ regs->size = reg_size;
+ };
+ if (!imsic->regs[0].size)
+ return SBI_EINVAL;
+
+ return 0;
+}
+
int fdt_parse_plic_node(void *fdt, int nodeoffset, struct plic_data *plic)
{
int len, rc;
diff --git a/lib/utils/irqchip/fdt_irqchip.c b/lib/utils/irqchip/fdt_irqchip.c
index bf6969a..cf64a2e 100644
--- a/lib/utils/irqchip/fdt_irqchip.c
+++ b/lib/utils/irqchip/fdt_irqchip.c
@@ -12,9 +12,11 @@
#include <sbi_utils/fdt/fdt_helper.h>
#include <sbi_utils/irqchip/fdt_irqchip.h>
+extern struct fdt_irqchip fdt_irqchip_imsic;
extern struct fdt_irqchip fdt_irqchip_plic;
static struct fdt_irqchip *irqchip_drivers[] = {
+ &fdt_irqchip_imsic,
&fdt_irqchip_plic
};
diff --git a/lib/utils/irqchip/fdt_irqchip_imsic.c b/lib/utils/irqchip/fdt_irqchip_imsic.c
new file mode 100644
index 0000000..b6962be
--- /dev/null
+++ b/lib/utils/irqchip/fdt_irqchip_imsic.c
@@ -0,0 +1,106 @@
+/*
+ * SPDX-License-Identifier: BSD-2-Clause
+ *
+ * Copyright (c) 2021 Western Digital Corporation or its affiliates.
+ * Copyright (c) 2022 Ventana Micro Systems Inc.
+ *
+ * Authors:
+ * Anup Patel <anup.patel@wdc.com>
+ */
+
+#include <libfdt.h>
+#include <sbi/riscv_asm.h>
+#include <sbi/sbi_error.h>
+#include <sbi/sbi_hartmask.h>
+#include <sbi_utils/fdt/fdt_helper.h>
+#include <sbi_utils/irqchip/fdt_irqchip.h>
+#include <sbi_utils/irqchip/imsic.h>
+
+#define IMSIC_MAX_NR 16
+
+static unsigned long imsic_count = 0;
+static struct imsic_data imsic[IMSIC_MAX_NR];
+
+static int irqchip_imsic_update_hartid_table(void *fdt, int nodeoff,
+ struct imsic_data *id)
+{
+ const fdt32_t *val;
+ u32 phandle, hwirq, hartid;
+ int i, err, count, cpu_offset, cpu_intc_offset;
+
+ val = fdt_getprop(fdt, nodeoff, "interrupts-extended", &count);
+ if (!val || count < sizeof(fdt32_t))
+ return SBI_EINVAL;
+ count = count / sizeof(fdt32_t);
+
+ for (i = 0; i < count; i += 2) {
+ phandle = fdt32_to_cpu(val[i]);
+ hwirq = fdt32_to_cpu(val[i + 1]);
+
+ cpu_intc_offset = fdt_node_offset_by_phandle(fdt, phandle);
+ if (cpu_intc_offset < 0)
+ continue;
+
+ cpu_offset = fdt_parent_offset(fdt, cpu_intc_offset);
+ if (cpu_intc_offset < 0)
+ continue;
+
+ err = fdt_parse_hart_id(fdt, cpu_offset, &hartid);
+ if (err)
+ return SBI_EINVAL;
+ if (SBI_HARTMASK_MAX_BITS <= hartid)
+ return SBI_EINVAL;
+
+ switch (hwirq) {
+ case IRQ_M_EXT:
+ err = imsic_map_hartid_to_data(hartid, id, i / 2);
+ if (err)
+ return err;
+ break;
+ default:
+ break;
+ }
+ }
+
+ return 0;
+}
+
+static int irqchip_imsic_cold_init(void *fdt, int nodeoff,
+ const struct fdt_match *match)
+{
+ int rc;
+ struct imsic_data *id;
+
+ if (IMSIC_MAX_NR <= imsic_count)
+ return SBI_ENOSPC;
+ id = &imsic[imsic_count];
+
+ rc = fdt_parse_imsic_node(fdt, nodeoff, id);
+ if (rc)
+ return rc;
+ if (!id->targets_mmode)
+ return 0;
+
+ rc = irqchip_imsic_update_hartid_table(fdt, nodeoff, id);
+ if (rc)
+ return rc;
+
+ rc = imsic_cold_irqchip_init(id);
+ if (rc)
+ return rc;
+
+ imsic_count++;
+
+ return 0;
+}
+
+static const struct fdt_match irqchip_imsic_match[] = {
+ { .compatible = "riscv,imsics" },
+ { },
+};
+
+struct fdt_irqchip fdt_irqchip_imsic = {
+ .match_table = irqchip_imsic_match,
+ .cold_init = irqchip_imsic_cold_init,
+ .warm_init = imsic_warm_irqchip_init,
+};
diff --git a/lib/utils/irqchip/objects.mk b/lib/utils/irqchip/objects.mk
index 76a3c94..ae6f255 100644
--- a/lib/utils/irqchip/objects.mk
+++ b/lib/utils/irqchip/objects.mk
@@ -8,6 +8,7 @@
#
libsbiutils-objs-y += irqchip/fdt_irqchip.o
+libsbiutils-objs-y += irqchip/fdt_irqchip_imsic.o
libsbiutils-objs-y += irqchip/fdt_irqchip_plic.o
libsbiutils-objs-y += irqchip/imsic.o
libsbiutils-objs-y += irqchip/plic.o
diff --git a/platform/generic/platform.c b/platform/generic/platform.c
index bc6e761..8a4fb70 100644
--- a/platform/generic/platform.c
+++ b/platform/generic/platform.c
@@ -18,6 +18,7 @@
#include <sbi_utils/fdt/fdt_helper.h>
#include <sbi_utils/fdt/fdt_pmu.h>
#include <sbi_utils/irqchip/fdt_irqchip.h>
+#include <sbi_utils/irqchip/imsic.h>
#include <sbi_utils/serial/fdt_serial.h>
#include <sbi_utils/timer/fdt_timer.h>
#include <sbi_utils/ipi/fdt_ipi.h>
@@ -56,6 +57,7 @@ static void fw_platform_lookup_special(void *fdt, int root_offset)
}
extern struct sbi_platform platform;
+static bool platform_has_mlevel_imsic = false;
static u32 generic_hart_index2id[SBI_HARTMASK_MAX_BITS] = { 0 };
/*
@@ -110,6 +112,8 @@ unsigned long fw_platform_init(unsigned long arg0, unsigned long arg1,
platform.hart_count = hart_count;
+ platform_has_mlevel_imsic = fdt_check_imsic_mlevel(fdt);
+
/* Return original FDT pointer */
return arg1;
@@ -118,6 +122,13 @@ fail:
wfi();
}
+static int generic_nascent_init(void)
+{
+ if (platform_has_mlevel_imsic)
+ imsic_local_irqchip_init();
+ return 0;
+}
+
static int generic_early_init(bool cold_boot)
{
if (!generic_plat || !generic_plat->early_init)
@@ -210,6 +221,7 @@ static uint64_t generic_pmu_xlate_to_mhpmevent(uint32_t event_idx,
}
const struct sbi_platform_operations platform_ops = {
+ .nascent_init = generic_nascent_init,
.early_init = generic_early_init,
.final_init = generic_final_init,
.early_exit = generic_early_exit,
--
2.25.1
^ permalink raw reply related [flat|nested] 36+ messages in thread* [PATCH v2 09/13] lib: utils/irqchip: Add FDT based driver for IMSIC
2022-02-09 15:04 ` [PATCH v2 09/13] lib: utils/irqchip: Add FDT based driver for IMSIC Anup Patel
@ 2022-02-12 0:54 ` Atish Patra
2022-02-15 14:57 ` Anup Patel
2022-02-15 15:20 ` Anup Patel
0 siblings, 2 replies; 36+ messages in thread
From: Atish Patra @ 2022-02-12 0:54 UTC (permalink / raw)
To: opensbi
On Wed, Feb 9, 2022 at 7:05 AM Anup Patel <apatel@ventanamicro.com> wrote:
>
> We add simple FDT irqchip driver for IMSIC so that generic platform
> (and other FDT based platforms) can utilize common IMIC library.
>
> Signed-off-by: Anup Patel <anup.patel@wdc.com>
> Signed-off-by: Anup Patel <apatel@ventanamicro.com>
> ---
> include/sbi_utils/fdt/fdt_helper.h | 6 ++
> lib/utils/fdt/fdt_helper.c | 103 +++++++++++++++++++++++++
> lib/utils/irqchip/fdt_irqchip.c | 2 +
> lib/utils/irqchip/fdt_irqchip_imsic.c | 106 ++++++++++++++++++++++++++
> lib/utils/irqchip/objects.mk | 1 +
> platform/generic/platform.c | 12 +++
> 6 files changed, 230 insertions(+)
> create mode 100644 lib/utils/irqchip/fdt_irqchip_imsic.c
>
> diff --git a/include/sbi_utils/fdt/fdt_helper.h b/include/sbi_utils/fdt/fdt_helper.h
> index 24fee7a..4c8d29e 100644
> --- a/include/sbi_utils/fdt/fdt_helper.h
> +++ b/include/sbi_utils/fdt/fdt_helper.h
> @@ -68,6 +68,12 @@ int fdt_parse_uart8250_node(void *fdt, int nodeoffset,
> int fdt_parse_uart8250(void *fdt, struct platform_uart_data *uart,
> const char *compatible);
>
> +struct imsic_data;
> +
> +bool fdt_check_imsic_mlevel(void *fdt);
> +
> +int fdt_parse_imsic_node(void *fdt, int nodeoff, struct imsic_data *imsic);
> +
> struct plic_data;
>
> int fdt_parse_plic_node(void *fdt, int nodeoffset, struct plic_data *plic);
> diff --git a/lib/utils/fdt/fdt_helper.c b/lib/utils/fdt/fdt_helper.c
> index 5bf4021..e179b79 100644
> --- a/lib/utils/fdt/fdt_helper.c
> +++ b/lib/utils/fdt/fdt_helper.c
> @@ -13,6 +13,7 @@
> #include <sbi/sbi_platform.h>
> #include <sbi/sbi_scratch.h>
> #include <sbi_utils/fdt/fdt_helper.h>
> +#include <sbi_utils/irqchip/imsic.h>
> #include <sbi_utils/irqchip/plic.h>
>
> #define DEFAULT_UART_FREQ 0
> @@ -465,6 +466,108 @@ int fdt_parse_uart8250(void *fdt, struct platform_uart_data *uart,
> return fdt_parse_uart8250_node(fdt, nodeoffset, uart);
> }
>
> +bool fdt_check_imsic_mlevel(void *fdt)
> +{
> + const fdt32_t *val;
> + int i, len, noff = 0;
> +
> + if (!fdt)
> + return false;
> +
> + while ((noff = fdt_node_offset_by_compatible(fdt, noff,
> + "riscv,imsics")) >= 0) {
> + val = fdt_getprop(fdt, noff, "interrupts-extended", &len);
> + if (val && len > sizeof(fdt32_t)) {
> + len = len / sizeof(fdt32_t);
> + for (i = 0; i < len; i += 2) {
> + if (fdt32_to_cpu(val[i + 1]) == IRQ_M_EXT)
> + return true;
> + }
> + }
> + }
> +
> + return false;
> +}
> +
> +int fdt_parse_imsic_node(void *fdt, int nodeoff, struct imsic_data *imsic)
> +{
> + const fdt32_t *val;
> + struct imsic_regs *regs;
> + uint64_t reg_addr, reg_size;
> + int i, rc, len, nr_parent_irqs;
> +
> + if (nodeoff < 0 || !imsic || !fdt)
> + return SBI_ENODEV;
> +
> + imsic->targets_mmode = false;
> + val = fdt_getprop(fdt, nodeoff, "interrupts-extended", &len);
> + if (val && len > sizeof(fdt32_t)) {
> + len = len / sizeof(fdt32_t);
> + nr_parent_irqs = len / 2;
> + for (i = 0; i < len; i += 2) {
> + if (fdt32_to_cpu(val[i + 1]) == IRQ_M_EXT) {
> + imsic->targets_mmode = true;
> + break;
> + }
> + }
> + } else
> + return SBI_EINVAL;
> +
> + val = fdt_getprop(fdt, nodeoff, "riscv,guest-index-bits", &len);
> + if (val && len > 0)
> + imsic->guest_index_bits = fdt32_to_cpu(*val);
> + else
> + imsic->guest_index_bits = 0;
> +
> + val = fdt_getprop(fdt, nodeoff, "riscv,hart-index-bits", &len);
> + if (val && len > 0) {
> + imsic->hart_index_bits = fdt32_to_cpu(*val);
> + } else {
> + imsic->hart_index_bits = sbi_fls(nr_parent_irqs);
> + if ((1UL << imsic->hart_index_bits) < nr_parent_irqs)
> + imsic->hart_index_bits++;
> + }
> +
> + val = fdt_getprop(fdt, nodeoff, "riscv,group-index-bits", &len);
> + if (val && len > 0)
> + imsic->group_index_bits = fdt32_to_cpu(*val);
> + else
> + imsic->group_index_bits = 0;
> +
> + val = fdt_getprop(fdt, nodeoff, "riscv,group-index-shift", &len);
> + if (val && len > 0)
> + imsic->group_index_shift = fdt32_to_cpu(*val);
> + else
> + imsic->group_index_shift = 2 * IMSIC_MMIO_PAGE_SHIFT;
> +
> + val = fdt_getprop(fdt, nodeoff, "riscv,num-ids", &len);
> + if (val && len > 0)
> + imsic->num_ids = fdt32_to_cpu(*val);
> + else
> + return SBI_EINVAL;
> +
> + for (i = 0; i < IMSIC_MAX_REGS; i++) {
> + regs = &imsic->regs[i];
> + regs->addr = 0;
> + regs->size = 0;
> + }
> +
> + for (i = 0; i < (IMSIC_MAX_REGS - 1); i++) {
> + regs = &imsic->regs[i];
> +
> + rc = fdt_get_node_addr_size(fdt, nodeoff, i,
> + ®_addr, ®_size);
> + if (rc < 0 || !reg_addr || !reg_size)
> + break;
> + regs->addr = reg_addr;
> + regs->size = reg_size;
> + };
> + if (!imsic->regs[0].size)
> + return SBI_EINVAL;
> +
> + return 0;
> +}
> +
> int fdt_parse_plic_node(void *fdt, int nodeoffset, struct plic_data *plic)
> {
> int len, rc;
> diff --git a/lib/utils/irqchip/fdt_irqchip.c b/lib/utils/irqchip/fdt_irqchip.c
> index bf6969a..cf64a2e 100644
> --- a/lib/utils/irqchip/fdt_irqchip.c
> +++ b/lib/utils/irqchip/fdt_irqchip.c
> @@ -12,9 +12,11 @@
> #include <sbi_utils/fdt/fdt_helper.h>
> #include <sbi_utils/irqchip/fdt_irqchip.h>
>
> +extern struct fdt_irqchip fdt_irqchip_imsic;
> extern struct fdt_irqchip fdt_irqchip_plic;
>
> static struct fdt_irqchip *irqchip_drivers[] = {
> + &fdt_irqchip_imsic,
> &fdt_irqchip_plic
> };
>
> diff --git a/lib/utils/irqchip/fdt_irqchip_imsic.c b/lib/utils/irqchip/fdt_irqchip_imsic.c
> new file mode 100644
> index 0000000..b6962be
> --- /dev/null
> +++ b/lib/utils/irqchip/fdt_irqchip_imsic.c
> @@ -0,0 +1,106 @@
> +/*
> + * SPDX-License-Identifier: BSD-2-Clause
> + *
> + * Copyright (c) 2021 Western Digital Corporation or its affiliates.
> + * Copyright (c) 2022 Ventana Micro Systems Inc.
> + *
> + * Authors:
> + * Anup Patel <anup.patel@wdc.com>
> + */
> +
> +#include <libfdt.h>
> +#include <sbi/riscv_asm.h>
> +#include <sbi/sbi_error.h>
> +#include <sbi/sbi_hartmask.h>
> +#include <sbi_utils/fdt/fdt_helper.h>
> +#include <sbi_utils/irqchip/fdt_irqchip.h>
> +#include <sbi_utils/irqchip/imsic.h>
> +
> +#define IMSIC_MAX_NR 16
> +
> +static unsigned long imsic_count = 0;
> +static struct imsic_data imsic[IMSIC_MAX_NR];
> +
> +static int irqchip_imsic_update_hartid_table(void *fdt, int nodeoff,
> + struct imsic_data *id)
> +{
> + const fdt32_t *val;
> + u32 phandle, hwirq, hartid;
> + int i, err, count, cpu_offset, cpu_intc_offset;
> +
> + val = fdt_getprop(fdt, nodeoff, "interrupts-extended", &count);
> + if (!val || count < sizeof(fdt32_t))
> + return SBI_EINVAL;
> + count = count / sizeof(fdt32_t);
> +
> + for (i = 0; i < count; i += 2) {
> + phandle = fdt32_to_cpu(val[i]);
> + hwirq = fdt32_to_cpu(val[i + 1]);
> +
> + cpu_intc_offset = fdt_node_offset_by_phandle(fdt, phandle);
> + if (cpu_intc_offset < 0)
> + continue;
> +
> + cpu_offset = fdt_parent_offset(fdt, cpu_intc_offset);
> + if (cpu_intc_offset < 0)
> + continue;
> +
> + err = fdt_parse_hart_id(fdt, cpu_offset, &hartid);
> + if (err)
> + return SBI_EINVAL;
> + if (SBI_HARTMASK_MAX_BITS <= hartid)
> + return SBI_EINVAL;
> +
> + switch (hwirq) {
> + case IRQ_M_EXT:
> + err = imsic_map_hartid_to_data(hartid, id, i / 2);
> + if (err)
> + return err;
> + break;
> + default:
> + break;
> + }
> + }
> +
> + return 0;
> +}
> +
> +static int irqchip_imsic_cold_init(void *fdt, int nodeoff,
> + const struct fdt_match *match)
> +{
> + int rc;
> + struct imsic_data *id;
> +
> + if (IMSIC_MAX_NR <= imsic_count)
> + return SBI_ENOSPC;
> + id = &imsic[imsic_count];
> +
> + rc = fdt_parse_imsic_node(fdt, nodeoff, id);
> + if (rc)
> + return rc;
> + if (!id->targets_mmode)
> + return 0;
> +
> + rc = irqchip_imsic_update_hartid_table(fdt, nodeoff, id);
> + if (rc)
> + return rc;
> +
> + rc = imsic_cold_irqchip_init(id);
> + if (rc)
> + return rc;
> +
> + imsic_count++;
> +
> + return 0;
> +}
> +
> +static const struct fdt_match irqchip_imsic_match[] = {
> + { .compatible = "riscv,imsics" },
> + { },
> +};
> +
> +struct fdt_irqchip fdt_irqchip_imsic = {
> + .match_table = irqchip_imsic_match,
> + .cold_init = irqchip_imsic_cold_init,
> + .warm_init = imsic_warm_irqchip_init,
> +};
> diff --git a/lib/utils/irqchip/objects.mk b/lib/utils/irqchip/objects.mk
> index 76a3c94..ae6f255 100644
> --- a/lib/utils/irqchip/objects.mk
> +++ b/lib/utils/irqchip/objects.mk
> @@ -8,6 +8,7 @@
> #
>
> libsbiutils-objs-y += irqchip/fdt_irqchip.o
> +libsbiutils-objs-y += irqchip/fdt_irqchip_imsic.o
> libsbiutils-objs-y += irqchip/fdt_irqchip_plic.o
> libsbiutils-objs-y += irqchip/imsic.o
> libsbiutils-objs-y += irqchip/plic.o
> diff --git a/platform/generic/platform.c b/platform/generic/platform.c
> index bc6e761..8a4fb70 100644
> --- a/platform/generic/platform.c
> +++ b/platform/generic/platform.c
> @@ -18,6 +18,7 @@
> #include <sbi_utils/fdt/fdt_helper.h>
> #include <sbi_utils/fdt/fdt_pmu.h>
> #include <sbi_utils/irqchip/fdt_irqchip.h>
> +#include <sbi_utils/irqchip/imsic.h>
> #include <sbi_utils/serial/fdt_serial.h>
> #include <sbi_utils/timer/fdt_timer.h>
> #include <sbi_utils/ipi/fdt_ipi.h>
> @@ -56,6 +57,7 @@ static void fw_platform_lookup_special(void *fdt, int root_offset)
> }
>
> extern struct sbi_platform platform;
> +static bool platform_has_mlevel_imsic = false;
> static u32 generic_hart_index2id[SBI_HARTMASK_MAX_BITS] = { 0 };
>
> /*
> @@ -110,6 +112,8 @@ unsigned long fw_platform_init(unsigned long arg0, unsigned long arg1,
>
> platform.hart_count = hart_count;
>
> + platform_has_mlevel_imsic = fdt_check_imsic_mlevel(fdt);
> +
> /* Return original FDT pointer */
> return arg1;
>
> @@ -118,6 +122,13 @@ fail:
> wfi();
> }
>
> +static int generic_nascent_init(void)
> +{
> + if (platform_has_mlevel_imsic)
> + imsic_local_irqchip_init();
> + return 0;
> +}
> +
> static int generic_early_init(bool cold_boot)
> {
> if (!generic_plat || !generic_plat->early_init)
> @@ -210,6 +221,7 @@ static uint64_t generic_pmu_xlate_to_mhpmevent(uint32_t event_idx,
> }
>
> const struct sbi_platform_operations platform_ops = {
> + .nascent_init = generic_nascent_init,
> .early_init = generic_early_init,
> .final_init = generic_final_init,
> .early_exit = generic_early_exit,
> --
> 2.25.1
>
LGTM. Just a suggestion:
I find it bit difficult to follow the code without the dt-bindings
[1]. The DT bindings may also change
in future based on feedback from the kernel/device tree mailing list.
It may take some time to freeze
the AIA spec as well.
Should we keep the DT binding in OpenSBI as well so it is easier to
follow the code without referring
the DT binding in your tree.
We can remove the DT binding once it is merged to upstream Linux to
avoid duplication.
[1] https://github.com/avpatel/linux/commit/059542fbcf644a42b135600ef3dd36d88e11f831
Reviewed-by: Atish Patra <atishp@rivosinc.com>
--
Regards,
Atish
^ permalink raw reply [flat|nested] 36+ messages in thread* [PATCH v2 09/13] lib: utils/irqchip: Add FDT based driver for IMSIC
2022-02-12 0:54 ` Atish Patra
@ 2022-02-15 14:57 ` Anup Patel
2022-02-15 15:20 ` Anup Patel
1 sibling, 0 replies; 36+ messages in thread
From: Anup Patel @ 2022-02-15 14:57 UTC (permalink / raw)
To: opensbi
On Sat, Feb 12, 2022 at 6:25 AM Atish Patra <atishp@atishpatra.org> wrote:
>
> On Wed, Feb 9, 2022 at 7:05 AM Anup Patel <apatel@ventanamicro.com> wrote:
> >
> > We add simple FDT irqchip driver for IMSIC so that generic platform
> > (and other FDT based platforms) can utilize common IMIC library.
> >
> > Signed-off-by: Anup Patel <anup.patel@wdc.com>
> > Signed-off-by: Anup Patel <apatel@ventanamicro.com>
> > ---
> > include/sbi_utils/fdt/fdt_helper.h | 6 ++
> > lib/utils/fdt/fdt_helper.c | 103 +++++++++++++++++++++++++
> > lib/utils/irqchip/fdt_irqchip.c | 2 +
> > lib/utils/irqchip/fdt_irqchip_imsic.c | 106 ++++++++++++++++++++++++++
> > lib/utils/irqchip/objects.mk | 1 +
> > platform/generic/platform.c | 12 +++
> > 6 files changed, 230 insertions(+)
> > create mode 100644 lib/utils/irqchip/fdt_irqchip_imsic.c
> >
> > diff --git a/include/sbi_utils/fdt/fdt_helper.h b/include/sbi_utils/fdt/fdt_helper.h
> > index 24fee7a..4c8d29e 100644
> > --- a/include/sbi_utils/fdt/fdt_helper.h
> > +++ b/include/sbi_utils/fdt/fdt_helper.h
> > @@ -68,6 +68,12 @@ int fdt_parse_uart8250_node(void *fdt, int nodeoffset,
> > int fdt_parse_uart8250(void *fdt, struct platform_uart_data *uart,
> > const char *compatible);
> >
> > +struct imsic_data;
> > +
> > +bool fdt_check_imsic_mlevel(void *fdt);
> > +
> > +int fdt_parse_imsic_node(void *fdt, int nodeoff, struct imsic_data *imsic);
> > +
> > struct plic_data;
> >
> > int fdt_parse_plic_node(void *fdt, int nodeoffset, struct plic_data *plic);
> > diff --git a/lib/utils/fdt/fdt_helper.c b/lib/utils/fdt/fdt_helper.c
> > index 5bf4021..e179b79 100644
> > --- a/lib/utils/fdt/fdt_helper.c
> > +++ b/lib/utils/fdt/fdt_helper.c
> > @@ -13,6 +13,7 @@
> > #include <sbi/sbi_platform.h>
> > #include <sbi/sbi_scratch.h>
> > #include <sbi_utils/fdt/fdt_helper.h>
> > +#include <sbi_utils/irqchip/imsic.h>
> > #include <sbi_utils/irqchip/plic.h>
> >
> > #define DEFAULT_UART_FREQ 0
> > @@ -465,6 +466,108 @@ int fdt_parse_uart8250(void *fdt, struct platform_uart_data *uart,
> > return fdt_parse_uart8250_node(fdt, nodeoffset, uart);
> > }
> >
> > +bool fdt_check_imsic_mlevel(void *fdt)
> > +{
> > + const fdt32_t *val;
> > + int i, len, noff = 0;
> > +
> > + if (!fdt)
> > + return false;
> > +
> > + while ((noff = fdt_node_offset_by_compatible(fdt, noff,
> > + "riscv,imsics")) >= 0) {
> > + val = fdt_getprop(fdt, noff, "interrupts-extended", &len);
> > + if (val && len > sizeof(fdt32_t)) {
> > + len = len / sizeof(fdt32_t);
> > + for (i = 0; i < len; i += 2) {
> > + if (fdt32_to_cpu(val[i + 1]) == IRQ_M_EXT)
> > + return true;
> > + }
> > + }
> > + }
> > +
> > + return false;
> > +}
> > +
> > +int fdt_parse_imsic_node(void *fdt, int nodeoff, struct imsic_data *imsic)
> > +{
> > + const fdt32_t *val;
> > + struct imsic_regs *regs;
> > + uint64_t reg_addr, reg_size;
> > + int i, rc, len, nr_parent_irqs;
> > +
> > + if (nodeoff < 0 || !imsic || !fdt)
> > + return SBI_ENODEV;
> > +
> > + imsic->targets_mmode = false;
> > + val = fdt_getprop(fdt, nodeoff, "interrupts-extended", &len);
> > + if (val && len > sizeof(fdt32_t)) {
> > + len = len / sizeof(fdt32_t);
> > + nr_parent_irqs = len / 2;
> > + for (i = 0; i < len; i += 2) {
> > + if (fdt32_to_cpu(val[i + 1]) == IRQ_M_EXT) {
> > + imsic->targets_mmode = true;
> > + break;
> > + }
> > + }
> > + } else
> > + return SBI_EINVAL;
> > +
> > + val = fdt_getprop(fdt, nodeoff, "riscv,guest-index-bits", &len);
> > + if (val && len > 0)
> > + imsic->guest_index_bits = fdt32_to_cpu(*val);
> > + else
> > + imsic->guest_index_bits = 0;
> > +
> > + val = fdt_getprop(fdt, nodeoff, "riscv,hart-index-bits", &len);
> > + if (val && len > 0) {
> > + imsic->hart_index_bits = fdt32_to_cpu(*val);
> > + } else {
> > + imsic->hart_index_bits = sbi_fls(nr_parent_irqs);
> > + if ((1UL << imsic->hart_index_bits) < nr_parent_irqs)
> > + imsic->hart_index_bits++;
> > + }
> > +
> > + val = fdt_getprop(fdt, nodeoff, "riscv,group-index-bits", &len);
> > + if (val && len > 0)
> > + imsic->group_index_bits = fdt32_to_cpu(*val);
> > + else
> > + imsic->group_index_bits = 0;
> > +
> > + val = fdt_getprop(fdt, nodeoff, "riscv,group-index-shift", &len);
> > + if (val && len > 0)
> > + imsic->group_index_shift = fdt32_to_cpu(*val);
> > + else
> > + imsic->group_index_shift = 2 * IMSIC_MMIO_PAGE_SHIFT;
> > +
> > + val = fdt_getprop(fdt, nodeoff, "riscv,num-ids", &len);
> > + if (val && len > 0)
> > + imsic->num_ids = fdt32_to_cpu(*val);
> > + else
> > + return SBI_EINVAL;
> > +
> > + for (i = 0; i < IMSIC_MAX_REGS; i++) {
> > + regs = &imsic->regs[i];
> > + regs->addr = 0;
> > + regs->size = 0;
> > + }
> > +
> > + for (i = 0; i < (IMSIC_MAX_REGS - 1); i++) {
> > + regs = &imsic->regs[i];
> > +
> > + rc = fdt_get_node_addr_size(fdt, nodeoff, i,
> > + ®_addr, ®_size);
> > + if (rc < 0 || !reg_addr || !reg_size)
> > + break;
> > + regs->addr = reg_addr;
> > + regs->size = reg_size;
> > + };
> > + if (!imsic->regs[0].size)
> > + return SBI_EINVAL;
> > +
> > + return 0;
> > +}
> > +
> > int fdt_parse_plic_node(void *fdt, int nodeoffset, struct plic_data *plic)
> > {
> > int len, rc;
> > diff --git a/lib/utils/irqchip/fdt_irqchip.c b/lib/utils/irqchip/fdt_irqchip.c
> > index bf6969a..cf64a2e 100644
> > --- a/lib/utils/irqchip/fdt_irqchip.c
> > +++ b/lib/utils/irqchip/fdt_irqchip.c
> > @@ -12,9 +12,11 @@
> > #include <sbi_utils/fdt/fdt_helper.h>
> > #include <sbi_utils/irqchip/fdt_irqchip.h>
> >
> > +extern struct fdt_irqchip fdt_irqchip_imsic;
> > extern struct fdt_irqchip fdt_irqchip_plic;
> >
> > static struct fdt_irqchip *irqchip_drivers[] = {
> > + &fdt_irqchip_imsic,
> > &fdt_irqchip_plic
> > };
> >
> > diff --git a/lib/utils/irqchip/fdt_irqchip_imsic.c b/lib/utils/irqchip/fdt_irqchip_imsic.c
> > new file mode 100644
> > index 0000000..b6962be
> > --- /dev/null
> > +++ b/lib/utils/irqchip/fdt_irqchip_imsic.c
> > @@ -0,0 +1,106 @@
> > +/*
> > + * SPDX-License-Identifier: BSD-2-Clause
> > + *
> > + * Copyright (c) 2021 Western Digital Corporation or its affiliates.
> > + * Copyright (c) 2022 Ventana Micro Systems Inc.
> > + *
> > + * Authors:
> > + * Anup Patel <anup.patel@wdc.com>
> > + */
> > +
> > +#include <libfdt.h>
> > +#include <sbi/riscv_asm.h>
> > +#include <sbi/sbi_error.h>
> > +#include <sbi/sbi_hartmask.h>
> > +#include <sbi_utils/fdt/fdt_helper.h>
> > +#include <sbi_utils/irqchip/fdt_irqchip.h>
> > +#include <sbi_utils/irqchip/imsic.h>
> > +
> > +#define IMSIC_MAX_NR 16
> > +
> > +static unsigned long imsic_count = 0;
> > +static struct imsic_data imsic[IMSIC_MAX_NR];
> > +
> > +static int irqchip_imsic_update_hartid_table(void *fdt, int nodeoff,
> > + struct imsic_data *id)
> > +{
> > + const fdt32_t *val;
> > + u32 phandle, hwirq, hartid;
> > + int i, err, count, cpu_offset, cpu_intc_offset;
> > +
> > + val = fdt_getprop(fdt, nodeoff, "interrupts-extended", &count);
> > + if (!val || count < sizeof(fdt32_t))
> > + return SBI_EINVAL;
> > + count = count / sizeof(fdt32_t);
> > +
> > + for (i = 0; i < count; i += 2) {
> > + phandle = fdt32_to_cpu(val[i]);
> > + hwirq = fdt32_to_cpu(val[i + 1]);
> > +
> > + cpu_intc_offset = fdt_node_offset_by_phandle(fdt, phandle);
> > + if (cpu_intc_offset < 0)
> > + continue;
> > +
> > + cpu_offset = fdt_parent_offset(fdt, cpu_intc_offset);
> > + if (cpu_intc_offset < 0)
> > + continue;
> > +
> > + err = fdt_parse_hart_id(fdt, cpu_offset, &hartid);
> > + if (err)
> > + return SBI_EINVAL;
> > + if (SBI_HARTMASK_MAX_BITS <= hartid)
> > + return SBI_EINVAL;
> > +
> > + switch (hwirq) {
> > + case IRQ_M_EXT:
> > + err = imsic_map_hartid_to_data(hartid, id, i / 2);
> > + if (err)
> > + return err;
> > + break;
> > + default:
> > + break;
> > + }
> > + }
> > +
> > + return 0;
> > +}
> > +
> > +static int irqchip_imsic_cold_init(void *fdt, int nodeoff,
> > + const struct fdt_match *match)
> > +{
> > + int rc;
> > + struct imsic_data *id;
> > +
> > + if (IMSIC_MAX_NR <= imsic_count)
> > + return SBI_ENOSPC;
> > + id = &imsic[imsic_count];
> > +
> > + rc = fdt_parse_imsic_node(fdt, nodeoff, id);
> > + if (rc)
> > + return rc;
> > + if (!id->targets_mmode)
> > + return 0;
> > +
> > + rc = irqchip_imsic_update_hartid_table(fdt, nodeoff, id);
> > + if (rc)
> > + return rc;
> > +
> > + rc = imsic_cold_irqchip_init(id);
> > + if (rc)
> > + return rc;
> > +
> > + imsic_count++;
> > +
> > + return 0;
> > +}
> > +
> > +static const struct fdt_match irqchip_imsic_match[] = {
> > + { .compatible = "riscv,imsics" },
> > + { },
> > +};
> > +
> > +struct fdt_irqchip fdt_irqchip_imsic = {
> > + .match_table = irqchip_imsic_match,
> > + .cold_init = irqchip_imsic_cold_init,
> > + .warm_init = imsic_warm_irqchip_init,
> > +};
> > diff --git a/lib/utils/irqchip/objects.mk b/lib/utils/irqchip/objects.mk
> > index 76a3c94..ae6f255 100644
> > --- a/lib/utils/irqchip/objects.mk
> > +++ b/lib/utils/irqchip/objects.mk
> > @@ -8,6 +8,7 @@
> > #
> >
> > libsbiutils-objs-y += irqchip/fdt_irqchip.o
> > +libsbiutils-objs-y += irqchip/fdt_irqchip_imsic.o
> > libsbiutils-objs-y += irqchip/fdt_irqchip_plic.o
> > libsbiutils-objs-y += irqchip/imsic.o
> > libsbiutils-objs-y += irqchip/plic.o
> > diff --git a/platform/generic/platform.c b/platform/generic/platform.c
> > index bc6e761..8a4fb70 100644
> > --- a/platform/generic/platform.c
> > +++ b/platform/generic/platform.c
> > @@ -18,6 +18,7 @@
> > #include <sbi_utils/fdt/fdt_helper.h>
> > #include <sbi_utils/fdt/fdt_pmu.h>
> > #include <sbi_utils/irqchip/fdt_irqchip.h>
> > +#include <sbi_utils/irqchip/imsic.h>
> > #include <sbi_utils/serial/fdt_serial.h>
> > #include <sbi_utils/timer/fdt_timer.h>
> > #include <sbi_utils/ipi/fdt_ipi.h>
> > @@ -56,6 +57,7 @@ static void fw_platform_lookup_special(void *fdt, int root_offset)
> > }
> >
> > extern struct sbi_platform platform;
> > +static bool platform_has_mlevel_imsic = false;
> > static u32 generic_hart_index2id[SBI_HARTMASK_MAX_BITS] = { 0 };
> >
> > /*
> > @@ -110,6 +112,8 @@ unsigned long fw_platform_init(unsigned long arg0, unsigned long arg1,
> >
> > platform.hart_count = hart_count;
> >
> > + platform_has_mlevel_imsic = fdt_check_imsic_mlevel(fdt);
> > +
> > /* Return original FDT pointer */
> > return arg1;
> >
> > @@ -118,6 +122,13 @@ fail:
> > wfi();
> > }
> >
> > +static int generic_nascent_init(void)
> > +{
> > + if (platform_has_mlevel_imsic)
> > + imsic_local_irqchip_init();
> > + return 0;
> > +}
> > +
> > static int generic_early_init(bool cold_boot)
> > {
> > if (!generic_plat || !generic_plat->early_init)
> > @@ -210,6 +221,7 @@ static uint64_t generic_pmu_xlate_to_mhpmevent(uint32_t event_idx,
> > }
> >
> > const struct sbi_platform_operations platform_ops = {
> > + .nascent_init = generic_nascent_init,
> > .early_init = generic_early_init,
> > .final_init = generic_final_init,
> > .early_exit = generic_early_exit,
> > --
> > 2.25.1
> >
>
> LGTM. Just a suggestion:
>
> I find it bit difficult to follow the code without the dt-bindings
> [1]. The DT bindings may also change
> in future based on feedback from the kernel/device tree mailing list.
> It may take some time to freeze
> the AIA spec as well.
>
> Should we keep the DT binding in OpenSBI as well so it is easier to
> follow the code without referring
> the DT binding in your tree.
>
> We can remove the DT binding once it is merged to upstream Linux to
> avoid duplication.
>
> [1] https://github.com/avpatel/linux/commit/059542fbcf644a42b135600ef3dd36d88e11f831
We generally add DT bindings to OpenSBI sources only when these
bindings are to be used only by OpenSBI (e.g. OpenSBI domain or
SBI PMU).
I will be sending out RFC PATCH for Linux AIA support so we will
always a patches on LKML to refer for AIA DT bindings.
Regards,
Anup
>
>
> Reviewed-by: Atish Patra <atishp@rivosinc.com>
>
>
> --
> Regards,
> Atish
^ permalink raw reply [flat|nested] 36+ messages in thread* [PATCH v2 09/13] lib: utils/irqchip: Add FDT based driver for IMSIC
2022-02-12 0:54 ` Atish Patra
2022-02-15 14:57 ` Anup Patel
@ 2022-02-15 15:20 ` Anup Patel
1 sibling, 0 replies; 36+ messages in thread
From: Anup Patel @ 2022-02-15 15:20 UTC (permalink / raw)
To: opensbi
On Sat, Feb 12, 2022 at 6:25 AM Atish Patra <atishp@atishpatra.org> wrote:
>
> On Wed, Feb 9, 2022 at 7:05 AM Anup Patel <apatel@ventanamicro.com> wrote:
> >
> > We add simple FDT irqchip driver for IMSIC so that generic platform
> > (and other FDT based platforms) can utilize common IMIC library.
> >
> > Signed-off-by: Anup Patel <anup.patel@wdc.com>
> > Signed-off-by: Anup Patel <apatel@ventanamicro.com>
> > ---
> > include/sbi_utils/fdt/fdt_helper.h | 6 ++
> > lib/utils/fdt/fdt_helper.c | 103 +++++++++++++++++++++++++
> > lib/utils/irqchip/fdt_irqchip.c | 2 +
> > lib/utils/irqchip/fdt_irqchip_imsic.c | 106 ++++++++++++++++++++++++++
> > lib/utils/irqchip/objects.mk | 1 +
> > platform/generic/platform.c | 12 +++
> > 6 files changed, 230 insertions(+)
> > create mode 100644 lib/utils/irqchip/fdt_irqchip_imsic.c
> >
> > diff --git a/include/sbi_utils/fdt/fdt_helper.h b/include/sbi_utils/fdt/fdt_helper.h
> > index 24fee7a..4c8d29e 100644
> > --- a/include/sbi_utils/fdt/fdt_helper.h
> > +++ b/include/sbi_utils/fdt/fdt_helper.h
> > @@ -68,6 +68,12 @@ int fdt_parse_uart8250_node(void *fdt, int nodeoffset,
> > int fdt_parse_uart8250(void *fdt, struct platform_uart_data *uart,
> > const char *compatible);
> >
> > +struct imsic_data;
> > +
> > +bool fdt_check_imsic_mlevel(void *fdt);
> > +
> > +int fdt_parse_imsic_node(void *fdt, int nodeoff, struct imsic_data *imsic);
> > +
> > struct plic_data;
> >
> > int fdt_parse_plic_node(void *fdt, int nodeoffset, struct plic_data *plic);
> > diff --git a/lib/utils/fdt/fdt_helper.c b/lib/utils/fdt/fdt_helper.c
> > index 5bf4021..e179b79 100644
> > --- a/lib/utils/fdt/fdt_helper.c
> > +++ b/lib/utils/fdt/fdt_helper.c
> > @@ -13,6 +13,7 @@
> > #include <sbi/sbi_platform.h>
> > #include <sbi/sbi_scratch.h>
> > #include <sbi_utils/fdt/fdt_helper.h>
> > +#include <sbi_utils/irqchip/imsic.h>
> > #include <sbi_utils/irqchip/plic.h>
> >
> > #define DEFAULT_UART_FREQ 0
> > @@ -465,6 +466,108 @@ int fdt_parse_uart8250(void *fdt, struct platform_uart_data *uart,
> > return fdt_parse_uart8250_node(fdt, nodeoffset, uart);
> > }
> >
> > +bool fdt_check_imsic_mlevel(void *fdt)
> > +{
> > + const fdt32_t *val;
> > + int i, len, noff = 0;
> > +
> > + if (!fdt)
> > + return false;
> > +
> > + while ((noff = fdt_node_offset_by_compatible(fdt, noff,
> > + "riscv,imsics")) >= 0) {
> > + val = fdt_getprop(fdt, noff, "interrupts-extended", &len);
> > + if (val && len > sizeof(fdt32_t)) {
> > + len = len / sizeof(fdt32_t);
> > + for (i = 0; i < len; i += 2) {
> > + if (fdt32_to_cpu(val[i + 1]) == IRQ_M_EXT)
> > + return true;
> > + }
> > + }
> > + }
> > +
> > + return false;
> > +}
> > +
> > +int fdt_parse_imsic_node(void *fdt, int nodeoff, struct imsic_data *imsic)
> > +{
> > + const fdt32_t *val;
> > + struct imsic_regs *regs;
> > + uint64_t reg_addr, reg_size;
> > + int i, rc, len, nr_parent_irqs;
> > +
> > + if (nodeoff < 0 || !imsic || !fdt)
> > + return SBI_ENODEV;
> > +
> > + imsic->targets_mmode = false;
> > + val = fdt_getprop(fdt, nodeoff, "interrupts-extended", &len);
> > + if (val && len > sizeof(fdt32_t)) {
> > + len = len / sizeof(fdt32_t);
> > + nr_parent_irqs = len / 2;
> > + for (i = 0; i < len; i += 2) {
> > + if (fdt32_to_cpu(val[i + 1]) == IRQ_M_EXT) {
> > + imsic->targets_mmode = true;
> > + break;
> > + }
> > + }
> > + } else
> > + return SBI_EINVAL;
> > +
> > + val = fdt_getprop(fdt, nodeoff, "riscv,guest-index-bits", &len);
> > + if (val && len > 0)
> > + imsic->guest_index_bits = fdt32_to_cpu(*val);
> > + else
> > + imsic->guest_index_bits = 0;
> > +
> > + val = fdt_getprop(fdt, nodeoff, "riscv,hart-index-bits", &len);
> > + if (val && len > 0) {
> > + imsic->hart_index_bits = fdt32_to_cpu(*val);
> > + } else {
> > + imsic->hart_index_bits = sbi_fls(nr_parent_irqs);
> > + if ((1UL << imsic->hart_index_bits) < nr_parent_irqs)
> > + imsic->hart_index_bits++;
> > + }
> > +
> > + val = fdt_getprop(fdt, nodeoff, "riscv,group-index-bits", &len);
> > + if (val && len > 0)
> > + imsic->group_index_bits = fdt32_to_cpu(*val);
> > + else
> > + imsic->group_index_bits = 0;
> > +
> > + val = fdt_getprop(fdt, nodeoff, "riscv,group-index-shift", &len);
> > + if (val && len > 0)
> > + imsic->group_index_shift = fdt32_to_cpu(*val);
> > + else
> > + imsic->group_index_shift = 2 * IMSIC_MMIO_PAGE_SHIFT;
> > +
> > + val = fdt_getprop(fdt, nodeoff, "riscv,num-ids", &len);
> > + if (val && len > 0)
> > + imsic->num_ids = fdt32_to_cpu(*val);
> > + else
> > + return SBI_EINVAL;
> > +
> > + for (i = 0; i < IMSIC_MAX_REGS; i++) {
> > + regs = &imsic->regs[i];
> > + regs->addr = 0;
> > + regs->size = 0;
> > + }
> > +
> > + for (i = 0; i < (IMSIC_MAX_REGS - 1); i++) {
> > + regs = &imsic->regs[i];
> > +
> > + rc = fdt_get_node_addr_size(fdt, nodeoff, i,
> > + ®_addr, ®_size);
> > + if (rc < 0 || !reg_addr || !reg_size)
> > + break;
> > + regs->addr = reg_addr;
> > + regs->size = reg_size;
> > + };
> > + if (!imsic->regs[0].size)
> > + return SBI_EINVAL;
> > +
> > + return 0;
> > +}
> > +
> > int fdt_parse_plic_node(void *fdt, int nodeoffset, struct plic_data *plic)
> > {
> > int len, rc;
> > diff --git a/lib/utils/irqchip/fdt_irqchip.c b/lib/utils/irqchip/fdt_irqchip.c
> > index bf6969a..cf64a2e 100644
> > --- a/lib/utils/irqchip/fdt_irqchip.c
> > +++ b/lib/utils/irqchip/fdt_irqchip.c
> > @@ -12,9 +12,11 @@
> > #include <sbi_utils/fdt/fdt_helper.h>
> > #include <sbi_utils/irqchip/fdt_irqchip.h>
> >
> > +extern struct fdt_irqchip fdt_irqchip_imsic;
> > extern struct fdt_irqchip fdt_irqchip_plic;
> >
> > static struct fdt_irqchip *irqchip_drivers[] = {
> > + &fdt_irqchip_imsic,
> > &fdt_irqchip_plic
> > };
> >
> > diff --git a/lib/utils/irqchip/fdt_irqchip_imsic.c b/lib/utils/irqchip/fdt_irqchip_imsic.c
> > new file mode 100644
> > index 0000000..b6962be
> > --- /dev/null
> > +++ b/lib/utils/irqchip/fdt_irqchip_imsic.c
> > @@ -0,0 +1,106 @@
> > +/*
> > + * SPDX-License-Identifier: BSD-2-Clause
> > + *
> > + * Copyright (c) 2021 Western Digital Corporation or its affiliates.
> > + * Copyright (c) 2022 Ventana Micro Systems Inc.
> > + *
> > + * Authors:
> > + * Anup Patel <anup.patel@wdc.com>
> > + */
> > +
> > +#include <libfdt.h>
> > +#include <sbi/riscv_asm.h>
> > +#include <sbi/sbi_error.h>
> > +#include <sbi/sbi_hartmask.h>
> > +#include <sbi_utils/fdt/fdt_helper.h>
> > +#include <sbi_utils/irqchip/fdt_irqchip.h>
> > +#include <sbi_utils/irqchip/imsic.h>
> > +
> > +#define IMSIC_MAX_NR 16
> > +
> > +static unsigned long imsic_count = 0;
> > +static struct imsic_data imsic[IMSIC_MAX_NR];
> > +
> > +static int irqchip_imsic_update_hartid_table(void *fdt, int nodeoff,
> > + struct imsic_data *id)
> > +{
> > + const fdt32_t *val;
> > + u32 phandle, hwirq, hartid;
> > + int i, err, count, cpu_offset, cpu_intc_offset;
> > +
> > + val = fdt_getprop(fdt, nodeoff, "interrupts-extended", &count);
> > + if (!val || count < sizeof(fdt32_t))
> > + return SBI_EINVAL;
> > + count = count / sizeof(fdt32_t);
> > +
> > + for (i = 0; i < count; i += 2) {
> > + phandle = fdt32_to_cpu(val[i]);
> > + hwirq = fdt32_to_cpu(val[i + 1]);
> > +
> > + cpu_intc_offset = fdt_node_offset_by_phandle(fdt, phandle);
> > + if (cpu_intc_offset < 0)
> > + continue;
> > +
> > + cpu_offset = fdt_parent_offset(fdt, cpu_intc_offset);
> > + if (cpu_intc_offset < 0)
> > + continue;
> > +
> > + err = fdt_parse_hart_id(fdt, cpu_offset, &hartid);
> > + if (err)
> > + return SBI_EINVAL;
> > + if (SBI_HARTMASK_MAX_BITS <= hartid)
> > + return SBI_EINVAL;
> > +
> > + switch (hwirq) {
> > + case IRQ_M_EXT:
> > + err = imsic_map_hartid_to_data(hartid, id, i / 2);
> > + if (err)
> > + return err;
> > + break;
> > + default:
> > + break;
> > + }
> > + }
> > +
> > + return 0;
> > +}
> > +
> > +static int irqchip_imsic_cold_init(void *fdt, int nodeoff,
> > + const struct fdt_match *match)
> > +{
> > + int rc;
> > + struct imsic_data *id;
> > +
> > + if (IMSIC_MAX_NR <= imsic_count)
> > + return SBI_ENOSPC;
> > + id = &imsic[imsic_count];
> > +
> > + rc = fdt_parse_imsic_node(fdt, nodeoff, id);
> > + if (rc)
> > + return rc;
> > + if (!id->targets_mmode)
> > + return 0;
> > +
> > + rc = irqchip_imsic_update_hartid_table(fdt, nodeoff, id);
> > + if (rc)
> > + return rc;
> > +
> > + rc = imsic_cold_irqchip_init(id);
> > + if (rc)
> > + return rc;
> > +
> > + imsic_count++;
> > +
> > + return 0;
> > +}
> > +
> > +static const struct fdt_match irqchip_imsic_match[] = {
> > + { .compatible = "riscv,imsics" },
> > + { },
> > +};
> > +
> > +struct fdt_irqchip fdt_irqchip_imsic = {
> > + .match_table = irqchip_imsic_match,
> > + .cold_init = irqchip_imsic_cold_init,
> > + .warm_init = imsic_warm_irqchip_init,
> > +};
> > diff --git a/lib/utils/irqchip/objects.mk b/lib/utils/irqchip/objects.mk
> > index 76a3c94..ae6f255 100644
> > --- a/lib/utils/irqchip/objects.mk
> > +++ b/lib/utils/irqchip/objects.mk
> > @@ -8,6 +8,7 @@
> > #
> >
> > libsbiutils-objs-y += irqchip/fdt_irqchip.o
> > +libsbiutils-objs-y += irqchip/fdt_irqchip_imsic.o
> > libsbiutils-objs-y += irqchip/fdt_irqchip_plic.o
> > libsbiutils-objs-y += irqchip/imsic.o
> > libsbiutils-objs-y += irqchip/plic.o
> > diff --git a/platform/generic/platform.c b/platform/generic/platform.c
> > index bc6e761..8a4fb70 100644
> > --- a/platform/generic/platform.c
> > +++ b/platform/generic/platform.c
> > @@ -18,6 +18,7 @@
> > #include <sbi_utils/fdt/fdt_helper.h>
> > #include <sbi_utils/fdt/fdt_pmu.h>
> > #include <sbi_utils/irqchip/fdt_irqchip.h>
> > +#include <sbi_utils/irqchip/imsic.h>
> > #include <sbi_utils/serial/fdt_serial.h>
> > #include <sbi_utils/timer/fdt_timer.h>
> > #include <sbi_utils/ipi/fdt_ipi.h>
> > @@ -56,6 +57,7 @@ static void fw_platform_lookup_special(void *fdt, int root_offset)
> > }
> >
> > extern struct sbi_platform platform;
> > +static bool platform_has_mlevel_imsic = false;
> > static u32 generic_hart_index2id[SBI_HARTMASK_MAX_BITS] = { 0 };
> >
> > /*
> > @@ -110,6 +112,8 @@ unsigned long fw_platform_init(unsigned long arg0, unsigned long arg1,
> >
> > platform.hart_count = hart_count;
> >
> > + platform_has_mlevel_imsic = fdt_check_imsic_mlevel(fdt);
> > +
> > /* Return original FDT pointer */
> > return arg1;
> >
> > @@ -118,6 +122,13 @@ fail:
> > wfi();
> > }
> >
> > +static int generic_nascent_init(void)
> > +{
> > + if (platform_has_mlevel_imsic)
> > + imsic_local_irqchip_init();
> > + return 0;
> > +}
> > +
> > static int generic_early_init(bool cold_boot)
> > {
> > if (!generic_plat || !generic_plat->early_init)
> > @@ -210,6 +221,7 @@ static uint64_t generic_pmu_xlate_to_mhpmevent(uint32_t event_idx,
> > }
> >
> > const struct sbi_platform_operations platform_ops = {
> > + .nascent_init = generic_nascent_init,
> > .early_init = generic_early_init,
> > .final_init = generic_final_init,
> > .early_exit = generic_early_exit,
> > --
> > 2.25.1
> >
>
> LGTM. Just a suggestion:
>
> I find it bit difficult to follow the code without the dt-bindings
> [1]. The DT bindings may also change
> in future based on feedback from the kernel/device tree mailing list.
> It may take some time to freeze
> the AIA spec as well.
>
> Should we keep the DT binding in OpenSBI as well so it is easier to
> follow the code without referring
> the DT binding in your tree.
>
> We can remove the DT binding once it is merged to upstream Linux to
> avoid duplication.
>
> [1] https://github.com/avpatel/linux/commit/059542fbcf644a42b135600ef3dd36d88e11f831
>
>
> Reviewed-by: Atish Patra <atishp@rivosinc.com>
Applied this patch to the riscv/opensbi repo.
Regards,
Anup
>
>
> --
> Regards,
> Atish
^ permalink raw reply [flat|nested] 36+ messages in thread
* [PATCH v2 10/13] lib: utils: Disable appropriate IMSIC DT nodes in fdt_fixups()
2022-02-09 15:04 [PATCH v2 00/13] OpenSBI RISC-V AIA Support Anup Patel
` (8 preceding siblings ...)
2022-02-09 15:04 ` [PATCH v2 09/13] lib: utils/irqchip: Add FDT based driver for IMSIC Anup Patel
@ 2022-02-09 15:04 ` Anup Patel
2022-02-15 15:20 ` Anup Patel
2022-02-09 15:04 ` [PATCH v2 11/13] lib: utils/irqchip: Add APLIC initialization library Anup Patel
` (2 subsequent siblings)
12 siblings, 1 reply; 36+ messages in thread
From: Anup Patel @ 2022-02-09 15:04 UTC (permalink / raw)
To: opensbi
We should disable IMSIC DT nodes in fdt_fixups() which are not
accessible to the next booting stage based on currently assigned
domain.
Signed-off-by: Anup Patel <anup.patel@wdc.com>
Signed-off-by: Anup Patel <apatel@ventanamicro.com>
Reviewed-by: Atish Patra <atishp@rivosinc.com>
---
include/sbi_utils/fdt/fdt_fixup.h | 17 ++++++++++++++--
lib/utils/fdt/fdt_fixup.c | 32 +++++++++++++++++++++++++++++--
2 files changed, 45 insertions(+), 4 deletions(-)
diff --git a/include/sbi_utils/fdt/fdt_fixup.h b/include/sbi_utils/fdt/fdt_fixup.h
index c38e5d9..77575bb 100644
--- a/include/sbi_utils/fdt/fdt_fixup.h
+++ b/include/sbi_utils/fdt/fdt_fixup.h
@@ -21,6 +21,18 @@
*/
void fdt_cpu_fixup(void *fdt);
+/**
+ * Fix up the IMSIC nodes in the device tree
+ *
+ * This routine disables IMSIC nodes which are not accessible to the next
+ * booting stage based on currently assigned domain.
+ *
+ * It is recommended that platform codes call this helper in their final_init()
+ *
+ * @param fdt: device tree blob
+ */
+void fdt_imsic_fixup(void *fdt);
+
/**
* Fix up the PLIC node in the device tree
*
@@ -64,8 +76,9 @@ int fdt_reserved_memory_nomap_fixup(void *fdt);
* General device tree fix-up
*
* This routine do all required device tree fix-ups for a typical platform.
- * It fixes up the PLIC node and the reserved memory node in the device tree
- * by calling the corresponding helper routines to accomplish the task.
+ * It fixes up the PLIC node, IMSIC nodes, and the reserved memory node in
+ * the device tree by calling the corresponding helper routines to accomplish
+ * the task.
*
* It is recommended that platform codes call this helper in their final_init()
*
diff --git a/lib/utils/fdt/fdt_fixup.c b/lib/utils/fdt/fdt_fixup.c
index ac01ba3..c2460b8 100644
--- a/lib/utils/fdt/fdt_fixup.c
+++ b/lib/utils/fdt/fdt_fixup.c
@@ -52,6 +52,34 @@ void fdt_cpu_fixup(void *fdt)
}
}
+static void fdt_domain_based_fixup_one(void *fdt, int nodeoff)
+{
+ int rc;
+ uint64_t reg_addr, reg_size;
+ struct sbi_domain *dom = sbi_domain_thishart_ptr();
+
+ rc = fdt_get_node_addr_size(fdt, nodeoff, 0, ®_addr, ®_size);
+ if (rc < 0 || !reg_addr || !reg_size)
+ return;
+
+ if (!sbi_domain_check_addr(dom, reg_addr, dom->next_mode,
+ SBI_DOMAIN_READ | SBI_DOMAIN_WRITE)) {
+ rc = fdt_open_into(fdt, fdt, fdt_totalsize(fdt) + 32);
+ if (rc < 0)
+ return;
+ fdt_setprop_string(fdt, nodeoff, "status", "disabled");
+ }
+}
+
+void fdt_imsic_fixup(void *fdt)
+{
+ int noff = 0;
+
+ while ((noff = fdt_node_offset_by_compatible(fdt, noff,
+ "riscv,imsics")) >= 0)
+ fdt_domain_based_fixup_one(fdt, noff);
+}
+
void fdt_plic_fixup(void *fdt)
{
u32 *cells;
@@ -261,10 +289,10 @@ int fdt_reserved_memory_nomap_fixup(void *fdt)
void fdt_fixups(void *fdt)
{
+ fdt_imsic_fixup(fdt);
+
fdt_plic_fixup(fdt);
fdt_reserved_memory_fixup(fdt);
fdt_pmu_fixup(fdt);
}
-
-
--
2.25.1
^ permalink raw reply related [flat|nested] 36+ messages in thread* [PATCH v2 10/13] lib: utils: Disable appropriate IMSIC DT nodes in fdt_fixups()
2022-02-09 15:04 ` [PATCH v2 10/13] lib: utils: Disable appropriate IMSIC DT nodes in fdt_fixups() Anup Patel
@ 2022-02-15 15:20 ` Anup Patel
0 siblings, 0 replies; 36+ messages in thread
From: Anup Patel @ 2022-02-15 15:20 UTC (permalink / raw)
To: opensbi
On Wed, Feb 9, 2022 at 8:35 PM Anup Patel <apatel@ventanamicro.com> wrote:
>
> We should disable IMSIC DT nodes in fdt_fixups() which are not
> accessible to the next booting stage based on currently assigned
> domain.
>
> Signed-off-by: Anup Patel <anup.patel@wdc.com>
> Signed-off-by: Anup Patel <apatel@ventanamicro.com>
> Reviewed-by: Atish Patra <atishp@rivosinc.com>
Applied this patch to the riscv/opensbi repo.
Regards,
Anup
> ---
> include/sbi_utils/fdt/fdt_fixup.h | 17 ++++++++++++++--
> lib/utils/fdt/fdt_fixup.c | 32 +++++++++++++++++++++++++++++--
> 2 files changed, 45 insertions(+), 4 deletions(-)
>
> diff --git a/include/sbi_utils/fdt/fdt_fixup.h b/include/sbi_utils/fdt/fdt_fixup.h
> index c38e5d9..77575bb 100644
> --- a/include/sbi_utils/fdt/fdt_fixup.h
> +++ b/include/sbi_utils/fdt/fdt_fixup.h
> @@ -21,6 +21,18 @@
> */
> void fdt_cpu_fixup(void *fdt);
>
> +/**
> + * Fix up the IMSIC nodes in the device tree
> + *
> + * This routine disables IMSIC nodes which are not accessible to the next
> + * booting stage based on currently assigned domain.
> + *
> + * It is recommended that platform codes call this helper in their final_init()
> + *
> + * @param fdt: device tree blob
> + */
> +void fdt_imsic_fixup(void *fdt);
> +
> /**
> * Fix up the PLIC node in the device tree
> *
> @@ -64,8 +76,9 @@ int fdt_reserved_memory_nomap_fixup(void *fdt);
> * General device tree fix-up
> *
> * This routine do all required device tree fix-ups for a typical platform.
> - * It fixes up the PLIC node and the reserved memory node in the device tree
> - * by calling the corresponding helper routines to accomplish the task.
> + * It fixes up the PLIC node, IMSIC nodes, and the reserved memory node in
> + * the device tree by calling the corresponding helper routines to accomplish
> + * the task.
> *
> * It is recommended that platform codes call this helper in their final_init()
> *
> diff --git a/lib/utils/fdt/fdt_fixup.c b/lib/utils/fdt/fdt_fixup.c
> index ac01ba3..c2460b8 100644
> --- a/lib/utils/fdt/fdt_fixup.c
> +++ b/lib/utils/fdt/fdt_fixup.c
> @@ -52,6 +52,34 @@ void fdt_cpu_fixup(void *fdt)
> }
> }
>
> +static void fdt_domain_based_fixup_one(void *fdt, int nodeoff)
> +{
> + int rc;
> + uint64_t reg_addr, reg_size;
> + struct sbi_domain *dom = sbi_domain_thishart_ptr();
> +
> + rc = fdt_get_node_addr_size(fdt, nodeoff, 0, ®_addr, ®_size);
> + if (rc < 0 || !reg_addr || !reg_size)
> + return;
> +
> + if (!sbi_domain_check_addr(dom, reg_addr, dom->next_mode,
> + SBI_DOMAIN_READ | SBI_DOMAIN_WRITE)) {
> + rc = fdt_open_into(fdt, fdt, fdt_totalsize(fdt) + 32);
> + if (rc < 0)
> + return;
> + fdt_setprop_string(fdt, nodeoff, "status", "disabled");
> + }
> +}
> +
> +void fdt_imsic_fixup(void *fdt)
> +{
> + int noff = 0;
> +
> + while ((noff = fdt_node_offset_by_compatible(fdt, noff,
> + "riscv,imsics")) >= 0)
> + fdt_domain_based_fixup_one(fdt, noff);
> +}
> +
> void fdt_plic_fixup(void *fdt)
> {
> u32 *cells;
> @@ -261,10 +289,10 @@ int fdt_reserved_memory_nomap_fixup(void *fdt)
>
> void fdt_fixups(void *fdt)
> {
> + fdt_imsic_fixup(fdt);
> +
> fdt_plic_fixup(fdt);
>
> fdt_reserved_memory_fixup(fdt);
> fdt_pmu_fixup(fdt);
> }
> -
> -
> --
> 2.25.1
>
^ permalink raw reply [flat|nested] 36+ messages in thread
* [PATCH v2 11/13] lib: utils/irqchip: Add APLIC initialization library
2022-02-09 15:04 [PATCH v2 00/13] OpenSBI RISC-V AIA Support Anup Patel
` (9 preceding siblings ...)
2022-02-09 15:04 ` [PATCH v2 10/13] lib: utils: Disable appropriate IMSIC DT nodes in fdt_fixups() Anup Patel
@ 2022-02-09 15:04 ` Anup Patel
2022-02-12 0:32 ` Atish Patra
2022-02-09 15:04 ` [PATCH v2 12/13] lib: utils/irqchip: Add FDT based driver for APLIC Anup Patel
2022-02-09 15:04 ` [PATCH v2 13/13] lib: utils: Disable appropriate APLIC DT nodes in fdt_fixups() Anup Patel
12 siblings, 1 reply; 36+ messages in thread
From: Anup Patel @ 2022-02-09 15:04 UTC (permalink / raw)
To: opensbi
We add simple APLIC initialization library which is independent of
hardware description format (FDT or ACPI). This APLIC initialization
library can be used by custom OpenSBI platform support to setup
APLIC domains.
Signed-off-by: Anup Patel <anup.patel@wdc.com>
Signed-off-by: Anup Patel <apatel@ventanamicro.com>
---
include/sbi_utils/irqchip/aplic.h | 47 +++++
lib/utils/irqchip/aplic.c | 279 ++++++++++++++++++++++++++++++
lib/utils/irqchip/objects.mk | 1 +
3 files changed, 327 insertions(+)
create mode 100644 include/sbi_utils/irqchip/aplic.h
create mode 100644 lib/utils/irqchip/aplic.c
diff --git a/include/sbi_utils/irqchip/aplic.h b/include/sbi_utils/irqchip/aplic.h
new file mode 100644
index 0000000..82682e8
--- /dev/null
+++ b/include/sbi_utils/irqchip/aplic.h
@@ -0,0 +1,47 @@
+/*
+ * SPDX-License-Identifier: BSD-2-Clause
+ *
+ * Copyright (c) 2021 Western Digital Corporation or its affiliates.
+ * Copyright (c) 2022 Ventana Micro Systems Inc.
+ *
+ * Authors:
+ * Anup Patel <anup.patel@wdc.com>
+ */
+
+#ifndef __IRQCHIP_APLIC_H__
+#define __IRQCHIP_APLIC_H__
+
+#include <sbi/sbi_types.h>
+
+#define APLIC_MAX_DELEGATE 16
+
+struct aplic_msicfg_data {
+ unsigned long lhxs;
+ unsigned long lhxw;
+ unsigned long hhxs;
+ unsigned long hhxw;
+ unsigned long base_addr;
+};
+
+struct aplic_delegate_data {
+ u32 first_irq;
+ u32 last_irq;
+ u32 child_index;
+};
+
+struct aplic_data {
+ unsigned long addr;
+ unsigned long size;
+ unsigned long num_idc;
+ unsigned long num_source;
+ bool targets_mmode;
+ bool has_msicfg_mmode;
+ struct aplic_msicfg_data msicfg_mmode;
+ bool has_msicfg_smode;
+ struct aplic_msicfg_data msicfg_smode;
+ struct aplic_delegate_data delegate[APLIC_MAX_DELEGATE];
+};
+
+int aplic_cold_irqchip_init(struct aplic_data *aplic);
+
+#endif
diff --git a/lib/utils/irqchip/aplic.c b/lib/utils/irqchip/aplic.c
new file mode 100644
index 0000000..0a8469b
--- /dev/null
+++ b/lib/utils/irqchip/aplic.c
@@ -0,0 +1,279 @@
+/*
+ * SPDX-License-Identifier: BSD-2-Clause
+ *
+ * Copyright (c) 2021 Western Digital Corporation or its affiliates.
+ * Copyright (c) 2022 Ventana Micro Systems Inc.
+ *
+ * Authors:
+ * Anup Patel <anup.patel@wdc.com>
+ */
+
+#include <sbi/riscv_io.h>
+#include <sbi/sbi_console.h>
+#include <sbi/sbi_domain.h>
+#include <sbi/sbi_error.h>
+#include <sbi_utils/irqchip/aplic.h>
+
+#define APLIC_MAX_IDC (1UL << 14)
+#define APLIC_MAX_SOURCE 1024
+
+#define APLIC_DOMAINCFG 0x0000
+#define APLIC_DOMAINCFG_IE (1 << 8)
+#define APLIC_DOMAINCFG_DM (1 << 2)
+#define APLIC_DOMAINCFG_BE (1 << 0)
+
+#define APLIC_SOURCECFG_BASE 0x0004
+#define APLIC_SOURCECFG_D (1 << 10)
+#define APLIC_SOURCECFG_CHILDIDX_MASK 0x000003ff
+#define APLIC_SOURCECFG_SM_MASK 0x00000007
+#define APLIC_SOURCECFG_SM_INACTIVE 0x0
+#define APLIC_SOURCECFG_SM_DETACH 0x1
+#define APLIC_SOURCECFG_SM_EDGE_RISE 0x4
+#define APLIC_SOURCECFG_SM_EDGE_FALL 0x5
+#define APLIC_SOURCECFG_SM_LEVEL_HIGH 0x6
+#define APLIC_SOURCECFG_SM_LEVEL_LOW 0x7
+
+#define APLIC_MMSICFGADDR 0x1bc0
+#define APLIC_MMSICFGADDRH 0x1bc4
+#define APLIC_SMSICFGADDR 0x1bc8
+#define APLIC_SMSICFGADDRH 0x1bcc
+
+#define APLIC_xMSICFGADDRH_L (1UL << 31)
+#define APLIC_xMSICFGADDRH_HHXS_MASK 0x1f
+#define APLIC_xMSICFGADDRH_HHXS_SHIFT 24
+#define APLIC_xMSICFGADDRH_LHXS_MASK 0x7
+#define APLIC_xMSICFGADDRH_LHXS_SHIFT 20
+#define APLIC_xMSICFGADDRH_HHXW_MASK 0x7
+#define APLIC_xMSICFGADDRH_HHXW_SHIFT 16
+#define APLIC_xMSICFGADDRH_LHXW_MASK 0xf
+#define APLIC_xMSICFGADDRH_LHXW_SHIFT 12
+#define APLIC_xMSICFGADDRH_BAPPN_MASK 0xfff
+
+#define APLIC_xMSICFGADDR_PPN_SHIFT 12
+
+#define APLIC_xMSICFGADDR_PPN_HART(__lhxs) \
+ ((1UL << (__lhxs)) - 1)
+
+#define APLIC_xMSICFGADDR_PPN_LHX_MASK(__lhxw) \
+ ((1UL << (__lhxw)) - 1)
+#define APLIC_xMSICFGADDR_PPN_LHX_SHIFT(__lhxs) \
+ ((__lhxs))
+#define APLIC_xMSICFGADDR_PPN_LHX(__lhxw, __lhxs) \
+ (APLIC_xMSICFGADDR_PPN_LHX_MASK(__lhxw) << \
+ APLIC_xMSICFGADDR_PPN_LHX_SHIFT(__lhxs))
+
+#define APLIC_xMSICFGADDR_PPN_HHX_MASK(__hhxw) \
+ ((1UL << (__hhxw)) - 1)
+#define APLIC_xMSICFGADDR_PPN_HHX_SHIFT(__hhxs) \
+ ((__hhxs) + APLIC_xMSICFGADDR_PPN_SHIFT)
+#define APLIC_xMSICFGADDR_PPN_HHX(__hhxw, __hhxs) \
+ (APLIC_xMSICFGADDR_PPN_HHX_MASK(__hhxw) << \
+ APLIC_xMSICFGADDR_PPN_HHX_SHIFT(__hhxs))
+
+#define APLIC_SETIP_BASE 0x1c00
+#define APLIC_SETIPNUM 0x1cdc
+
+#define APLIC_CLRIP_BASE 0x1d00
+#define APLIC_CLRIPNUM 0x1ddc
+
+#define APLIC_SETIE_BASE 0x1e00
+#define APLIC_SETIENUM 0x1edc
+
+#define APLIC_CLRIE_BASE 0x1f00
+#define APLIC_CLRIENUM 0x1fdc
+
+#define APLIC_SETIPNUM_LE 0x2000
+#define APLIC_SETIPNUM_BE 0x2004
+
+#define APLIC_TARGET_BASE 0x3004
+#define APLIC_TARGET_HART_IDX_SHIFT 18
+#define APLIC_TARGET_HART_IDX_MASK 0x3fff
+#define APLIC_TARGET_GUEST_IDX_SHIFT 12
+#define APLIC_TARGET_GUEST_IDX_MASK 0x3f
+#define APLIC_TARGET_IPRIO_MASK 0xff
+#define APLIC_TARGET_EIID_MASK 0x7ff
+
+#define APLIC_IDC_BASE 0x4000
+#define APLIC_IDC_SIZE 32
+
+#define APLIC_IDC_IDELIVERY 0x00
+
+#define APLIC_IDC_IFORCE 0x04
+
+#define APLIC_IDC_ITHRESHOLD 0x08
+
+#define APLIC_IDC_TOPI 0x18
+#define APLIC_IDC_TOPI_ID_SHIFT 16
+#define APLIC_IDC_TOPI_ID_MASK 0x3ff
+#define APLIC_IDC_TOPI_PRIO_MASK 0xff
+
+#define APLIC_IDC_CLAIMI 0x1c
+
+#define APLIC_DEFAULT_PRIORITY 1
+#define APLIC_DISABLE_IDELIVERY 0
+#define APLIC_ENABLE_IDELIVERY 1
+#define APLIC_DISABLE_ITHRESHOLD 1
+#define APLIC_ENABLE_ITHRESHOLD 0
+
+static void aplic_writel_msicfg(struct aplic_msicfg_data *msicfg,
+ void *msicfgaddr, void *msicfgaddrH)
+{
+ u32 val;
+ unsigned long base_ppn;
+
+ /* Check if MSI config is already locked */
+ if (readl(msicfgaddrH) & APLIC_xMSICFGADDRH_L)
+ return;
+
+ /* Compute the MSI base PPN */
+ base_ppn = msicfg->base_addr >> APLIC_xMSICFGADDR_PPN_SHIFT;
+ base_ppn &= ~APLIC_xMSICFGADDR_PPN_HART(msicfg->lhxs);
+ base_ppn &= ~APLIC_xMSICFGADDR_PPN_LHX(msicfg->lhxw, msicfg->lhxs);
+ base_ppn &= ~APLIC_xMSICFGADDR_PPN_HHX(msicfg->hhxw, msicfg->hhxs);
+
+ /* Write the lower MSI config register */
+ writel((u32)base_ppn, msicfgaddr);
+
+ /* Write the upper MSI config register */
+ val = (((u64)base_ppn) >> 32) &
+ APLIC_xMSICFGADDRH_BAPPN_MASK;
+ val |= (msicfg->lhxw & APLIC_xMSICFGADDRH_LHXW_MASK)
+ << APLIC_xMSICFGADDRH_LHXW_SHIFT;
+ val |= (msicfg->hhxw & APLIC_xMSICFGADDRH_HHXW_MASK)
+ << APLIC_xMSICFGADDRH_HHXW_SHIFT;
+ val |= (msicfg->lhxs & APLIC_xMSICFGADDRH_LHXS_MASK)
+ << APLIC_xMSICFGADDRH_LHXS_SHIFT;
+ val |= (msicfg->hhxs & APLIC_xMSICFGADDRH_HHXS_MASK)
+ << APLIC_xMSICFGADDRH_HHXS_SHIFT;
+ writel(val, msicfgaddrH);
+}
+
+static int aplic_check_msicfg(struct aplic_msicfg_data *msicfg)
+{
+ if (APLIC_xMSICFGADDRH_LHXS_MASK < msicfg->lhxs)
+ return SBI_EINVAL;
+
+ if (APLIC_xMSICFGADDRH_LHXW_MASK < msicfg->lhxw)
+ return SBI_EINVAL;
+
+ if (APLIC_xMSICFGADDRH_HHXS_MASK < msicfg->hhxs)
+ return SBI_EINVAL;
+
+ if (APLIC_xMSICFGADDRH_HHXW_MASK < msicfg->hhxw)
+ return SBI_EINVAL;
+
+ return 0;
+}
+
+int aplic_cold_irqchip_init(struct aplic_data *aplic)
+{
+ int rc;
+ u32 i, j, tmp;
+ struct sbi_domain_memregion reg;
+ struct aplic_delegate_data *deleg;
+ u32 first_deleg_irq, last_deleg_irq;
+
+ /* Sanity checks */
+ if (!aplic ||
+ !aplic->num_source || APLIC_MAX_SOURCE <= aplic->num_source ||
+ APLIC_MAX_IDC <= aplic->num_idc)
+ return SBI_EINVAL;
+ if (aplic->targets_mmode && aplic->has_msicfg_mmode) {
+ rc = aplic_check_msicfg(&aplic->msicfg_mmode);
+ if (rc)
+ return rc;
+ }
+ if (aplic->targets_mmode && aplic->has_msicfg_smode) {
+ rc = aplic_check_msicfg(&aplic->msicfg_smode);
+ if (rc)
+ return rc;
+ }
+
+ /* Set domain configuration to 0 */
+ writel(0, (void *)(aplic->addr + APLIC_DOMAINCFG));
+
+ /* Disable all interrupts */
+ for (i = 0; i <= aplic->num_source; i++)
+ writel(-1U, (void *)(aplic->addr + APLIC_CLRIE_BASE +
+ (i / 32) * sizeof(u32)));
+
+ /* Set interrupt type and priority for all interrupts */
+ for (i = 1; i <= aplic->num_source; i++) {
+ /* Set IRQ source configuration to 0 */
+ writel(0, (void *)(aplic->addr + APLIC_SOURCECFG_BASE +
+ (i - 1) * sizeof(u32)));
+ /* Set IRQ target hart index and priority to 1 */
+ writel(APLIC_DEFAULT_PRIORITY, (void *)(aplic->addr +
+ APLIC_TARGET_BASE +
+ (i - 1) * sizeof(u32)));
+ }
+
+ /* Configure IRQ delegation */
+ first_deleg_irq = -1U;
+ last_deleg_irq = 0;
+ for (i = 0; i < APLIC_MAX_DELEGATE; i++) {
+ deleg = &aplic->delegate[i];
+ if (!deleg->first_irq || !deleg->last_irq)
+ continue;
+ if (aplic->num_source < deleg->first_irq ||
+ aplic->num_source < deleg->last_irq)
+ continue;
+ if (APLIC_SOURCECFG_CHILDIDX_MASK < deleg->child_index)
+ continue;
+ if (deleg->first_irq > deleg->last_irq) {
+ tmp = deleg->first_irq;
+ deleg->first_irq = deleg->last_irq;
+ deleg->last_irq = tmp;
+ }
+ if (deleg->first_irq < first_deleg_irq)
+ first_deleg_irq = deleg->first_irq;
+ if (last_deleg_irq < deleg->last_irq)
+ last_deleg_irq = deleg->last_irq;
+ for (j = deleg->first_irq; j <= deleg->last_irq; j++)
+ writel(APLIC_SOURCECFG_D | deleg->child_index,
+ (void *)(aplic->addr + APLIC_SOURCECFG_BASE +
+ (j - 1) * sizeof(u32)));
+ }
+
+ /* Default initialization of IDC structures */
+ for (i = 0; i < aplic->num_idc; i++) {
+ writel(0, (void *)(aplic->addr + APLIC_IDC_BASE +
+ i * APLIC_IDC_SIZE + APLIC_IDC_IDELIVERY));
+ writel(0, (void *)(aplic->addr + APLIC_IDC_BASE +
+ i * APLIC_IDC_SIZE + APLIC_IDC_IFORCE));
+ writel(APLIC_DISABLE_ITHRESHOLD, (void *)(aplic->addr +
+ APLIC_IDC_BASE +
+ (i * APLIC_IDC_SIZE) +
+ APLIC_IDC_ITHRESHOLD));
+ }
+
+ /* MSI configuration */
+ if (aplic->targets_mmode && aplic->has_msicfg_mmode) {
+ aplic_writel_msicfg(&aplic->msicfg_mmode,
+ (void *)(aplic->addr + APLIC_MMSICFGADDR),
+ (void *)(aplic->addr + APLIC_MMSICFGADDRH));
+ }
+ if (aplic->targets_mmode && aplic->has_msicfg_smode) {
+ aplic_writel_msicfg(&aplic->msicfg_smode,
+ (void *)(aplic->addr + APLIC_SMSICFGADDR),
+ (void *)(aplic->addr + APLIC_SMSICFGADDRH));
+ }
+
+ /*
+ * Add APLIC region to the root domain if:
+ * 1) It targets M-mode of any HART directly or via MSIs
+ * 2) All interrupts are delegated to some child APLIC
+ */
+ if (aplic->targets_mmode ||
+ ((first_deleg_irq < last_deleg_irq) &&
+ (last_deleg_irq == aplic->num_source) &&
+ (first_deleg_irq == 1))) {
+ sbi_domain_memregion_init(aplic->addr, aplic->size,
+ SBI_DOMAIN_MEMREGION_MMIO, ®);
+ rc = sbi_domain_root_add_memregion(®);
+ if (rc)
+ return rc;
+ }
+
+ return 0;
+}
diff --git a/lib/utils/irqchip/objects.mk b/lib/utils/irqchip/objects.mk
index ae6f255..b2b3f79 100644
--- a/lib/utils/irqchip/objects.mk
+++ b/lib/utils/irqchip/objects.mk
@@ -10,5 +10,6 @@
libsbiutils-objs-y += irqchip/fdt_irqchip.o
libsbiutils-objs-y += irqchip/fdt_irqchip_imsic.o
libsbiutils-objs-y += irqchip/fdt_irqchip_plic.o
+libsbiutils-objs-y += irqchip/aplic.o
libsbiutils-objs-y += irqchip/imsic.o
libsbiutils-objs-y += irqchip/plic.o
--
2.25.1
^ permalink raw reply related [flat|nested] 36+ messages in thread* [PATCH v2 11/13] lib: utils/irqchip: Add APLIC initialization library
2022-02-09 15:04 ` [PATCH v2 11/13] lib: utils/irqchip: Add APLIC initialization library Anup Patel
@ 2022-02-12 0:32 ` Atish Patra
2022-02-15 15:24 ` Anup Patel
0 siblings, 1 reply; 36+ messages in thread
From: Atish Patra @ 2022-02-12 0:32 UTC (permalink / raw)
To: opensbi
On Wed, Feb 9, 2022 at 7:05 AM Anup Patel <apatel@ventanamicro.com> wrote:
>
> We add simple APLIC initialization library which is independent of
> hardware description format (FDT or ACPI). This APLIC initialization
> library can be used by custom OpenSBI platform support to setup
> APLIC domains.
>
> Signed-off-by: Anup Patel <anup.patel@wdc.com>
> Signed-off-by: Anup Patel <apatel@ventanamicro.com>
> ---
> include/sbi_utils/irqchip/aplic.h | 47 +++++
> lib/utils/irqchip/aplic.c | 279 ++++++++++++++++++++++++++++++
> lib/utils/irqchip/objects.mk | 1 +
> 3 files changed, 327 insertions(+)
> create mode 100644 include/sbi_utils/irqchip/aplic.h
> create mode 100644 lib/utils/irqchip/aplic.c
>
> diff --git a/include/sbi_utils/irqchip/aplic.h b/include/sbi_utils/irqchip/aplic.h
> new file mode 100644
> index 0000000..82682e8
> --- /dev/null
> +++ b/include/sbi_utils/irqchip/aplic.h
> @@ -0,0 +1,47 @@
> +/*
> + * SPDX-License-Identifier: BSD-2-Clause
> + *
> + * Copyright (c) 2021 Western Digital Corporation or its affiliates.
> + * Copyright (c) 2022 Ventana Micro Systems Inc.
> + *
> + * Authors:
> + * Anup Patel <anup.patel@wdc.com>
> + */
> +
> +#ifndef __IRQCHIP_APLIC_H__
> +#define __IRQCHIP_APLIC_H__
> +
> +#include <sbi/sbi_types.h>
> +
> +#define APLIC_MAX_DELEGATE 16
> +
> +struct aplic_msicfg_data {
> + unsigned long lhxs;
> + unsigned long lhxw;
> + unsigned long hhxs;
> + unsigned long hhxw;
> + unsigned long base_addr;
> +};
> +
> +struct aplic_delegate_data {
> + u32 first_irq;
> + u32 last_irq;
> + u32 child_index;
> +};
> +
> +struct aplic_data {
> + unsigned long addr;
> + unsigned long size;
> + unsigned long num_idc;
> + unsigned long num_source;
> + bool targets_mmode;
> + bool has_msicfg_mmode;
> + struct aplic_msicfg_data msicfg_mmode;
> + bool has_msicfg_smode;
> + struct aplic_msicfg_data msicfg_smode;
> + struct aplic_delegate_data delegate[APLIC_MAX_DELEGATE];
> +};
> +
> +int aplic_cold_irqchip_init(struct aplic_data *aplic);
> +
> +#endif
> diff --git a/lib/utils/irqchip/aplic.c b/lib/utils/irqchip/aplic.c
> new file mode 100644
> index 0000000..0a8469b
> --- /dev/null
> +++ b/lib/utils/irqchip/aplic.c
> @@ -0,0 +1,279 @@
> +/*
> + * SPDX-License-Identifier: BSD-2-Clause
> + *
> + * Copyright (c) 2021 Western Digital Corporation or its affiliates.
> + * Copyright (c) 2022 Ventana Micro Systems Inc.
> + *
> + * Authors:
> + * Anup Patel <anup.patel@wdc.com>
> + */
> +
> +#include <sbi/riscv_io.h>
> +#include <sbi/sbi_console.h>
> +#include <sbi/sbi_domain.h>
> +#include <sbi/sbi_error.h>
> +#include <sbi_utils/irqchip/aplic.h>
> +
> +#define APLIC_MAX_IDC (1UL << 14)
> +#define APLIC_MAX_SOURCE 1024
> +
> +#define APLIC_DOMAINCFG 0x0000
> +#define APLIC_DOMAINCFG_IE (1 << 8)
> +#define APLIC_DOMAINCFG_DM (1 << 2)
> +#define APLIC_DOMAINCFG_BE (1 << 0)
> +
> +#define APLIC_SOURCECFG_BASE 0x0004
> +#define APLIC_SOURCECFG_D (1 << 10)
> +#define APLIC_SOURCECFG_CHILDIDX_MASK 0x000003ff
> +#define APLIC_SOURCECFG_SM_MASK 0x00000007
> +#define APLIC_SOURCECFG_SM_INACTIVE 0x0
> +#define APLIC_SOURCECFG_SM_DETACH 0x1
> +#define APLIC_SOURCECFG_SM_EDGE_RISE 0x4
> +#define APLIC_SOURCECFG_SM_EDGE_FALL 0x5
> +#define APLIC_SOURCECFG_SM_LEVEL_HIGH 0x6
> +#define APLIC_SOURCECFG_SM_LEVEL_LOW 0x7
> +
> +#define APLIC_MMSICFGADDR 0x1bc0
> +#define APLIC_MMSICFGADDRH 0x1bc4
> +#define APLIC_SMSICFGADDR 0x1bc8
> +#define APLIC_SMSICFGADDRH 0x1bcc
> +
> +#define APLIC_xMSICFGADDRH_L (1UL << 31)
> +#define APLIC_xMSICFGADDRH_HHXS_MASK 0x1f
> +#define APLIC_xMSICFGADDRH_HHXS_SHIFT 24
> +#define APLIC_xMSICFGADDRH_LHXS_MASK 0x7
> +#define APLIC_xMSICFGADDRH_LHXS_SHIFT 20
> +#define APLIC_xMSICFGADDRH_HHXW_MASK 0x7
> +#define APLIC_xMSICFGADDRH_HHXW_SHIFT 16
> +#define APLIC_xMSICFGADDRH_LHXW_MASK 0xf
> +#define APLIC_xMSICFGADDRH_LHXW_SHIFT 12
> +#define APLIC_xMSICFGADDRH_BAPPN_MASK 0xfff
> +
> +#define APLIC_xMSICFGADDR_PPN_SHIFT 12
> +
> +#define APLIC_xMSICFGADDR_PPN_HART(__lhxs) \
> + ((1UL << (__lhxs)) - 1)
> +
> +#define APLIC_xMSICFGADDR_PPN_LHX_MASK(__lhxw) \
> + ((1UL << (__lhxw)) - 1)
> +#define APLIC_xMSICFGADDR_PPN_LHX_SHIFT(__lhxs) \
> + ((__lhxs))
> +#define APLIC_xMSICFGADDR_PPN_LHX(__lhxw, __lhxs) \
> + (APLIC_xMSICFGADDR_PPN_LHX_MASK(__lhxw) << \
> + APLIC_xMSICFGADDR_PPN_LHX_SHIFT(__lhxs))
> +
> +#define APLIC_xMSICFGADDR_PPN_HHX_MASK(__hhxw) \
> + ((1UL << (__hhxw)) - 1)
> +#define APLIC_xMSICFGADDR_PPN_HHX_SHIFT(__hhxs) \
> + ((__hhxs) + APLIC_xMSICFGADDR_PPN_SHIFT)
> +#define APLIC_xMSICFGADDR_PPN_HHX(__hhxw, __hhxs) \
> + (APLIC_xMSICFGADDR_PPN_HHX_MASK(__hhxw) << \
> + APLIC_xMSICFGADDR_PPN_HHX_SHIFT(__hhxs))
> +
> +#define APLIC_SETIP_BASE 0x1c00
> +#define APLIC_SETIPNUM 0x1cdc
> +
> +#define APLIC_CLRIP_BASE 0x1d00
> +#define APLIC_CLRIPNUM 0x1ddc
> +
> +#define APLIC_SETIE_BASE 0x1e00
> +#define APLIC_SETIENUM 0x1edc
> +
> +#define APLIC_CLRIE_BASE 0x1f00
> +#define APLIC_CLRIENUM 0x1fdc
> +
> +#define APLIC_SETIPNUM_LE 0x2000
> +#define APLIC_SETIPNUM_BE 0x2004
> +
> +#define APLIC_TARGET_BASE 0x3004
> +#define APLIC_TARGET_HART_IDX_SHIFT 18
> +#define APLIC_TARGET_HART_IDX_MASK 0x3fff
> +#define APLIC_TARGET_GUEST_IDX_SHIFT 12
> +#define APLIC_TARGET_GUEST_IDX_MASK 0x3f
> +#define APLIC_TARGET_IPRIO_MASK 0xff
> +#define APLIC_TARGET_EIID_MASK 0x7ff
> +
> +#define APLIC_IDC_BASE 0x4000
> +#define APLIC_IDC_SIZE 32
> +
> +#define APLIC_IDC_IDELIVERY 0x00
> +
> +#define APLIC_IDC_IFORCE 0x04
> +
> +#define APLIC_IDC_ITHRESHOLD 0x08
> +
> +#define APLIC_IDC_TOPI 0x18
> +#define APLIC_IDC_TOPI_ID_SHIFT 16
> +#define APLIC_IDC_TOPI_ID_MASK 0x3ff
> +#define APLIC_IDC_TOPI_PRIO_MASK 0xff
> +
> +#define APLIC_IDC_CLAIMI 0x1c
> +
> +#define APLIC_DEFAULT_PRIORITY 1
> +#define APLIC_DISABLE_IDELIVERY 0
> +#define APLIC_ENABLE_IDELIVERY 1
> +#define APLIC_DISABLE_ITHRESHOLD 1
> +#define APLIC_ENABLE_ITHRESHOLD 0
> +
> +static void aplic_writel_msicfg(struct aplic_msicfg_data *msicfg,
> + void *msicfgaddr, void *msicfgaddrH)
> +{
> + u32 val;
> + unsigned long base_ppn;
> +
> + /* Check if MSI config is already locked */
> + if (readl(msicfgaddrH) & APLIC_xMSICFGADDRH_L)
> + return;
> +
> + /* Compute the MSI base PPN */
> + base_ppn = msicfg->base_addr >> APLIC_xMSICFGADDR_PPN_SHIFT;
> + base_ppn &= ~APLIC_xMSICFGADDR_PPN_HART(msicfg->lhxs);
> + base_ppn &= ~APLIC_xMSICFGADDR_PPN_LHX(msicfg->lhxw, msicfg->lhxs);
> + base_ppn &= ~APLIC_xMSICFGADDR_PPN_HHX(msicfg->hhxw, msicfg->hhxs);
> +
> + /* Write the lower MSI config register */
> + writel((u32)base_ppn, msicfgaddr);
> +
> + /* Write the upper MSI config register */
> + val = (((u64)base_ppn) >> 32) &
> + APLIC_xMSICFGADDRH_BAPPN_MASK;
> + val |= (msicfg->lhxw & APLIC_xMSICFGADDRH_LHXW_MASK)
> + << APLIC_xMSICFGADDRH_LHXW_SHIFT;
> + val |= (msicfg->hhxw & APLIC_xMSICFGADDRH_HHXW_MASK)
> + << APLIC_xMSICFGADDRH_HHXW_SHIFT;
> + val |= (msicfg->lhxs & APLIC_xMSICFGADDRH_LHXS_MASK)
> + << APLIC_xMSICFGADDRH_LHXS_SHIFT;
> + val |= (msicfg->hhxs & APLIC_xMSICFGADDRH_HHXS_MASK)
> + << APLIC_xMSICFGADDRH_HHXS_SHIFT;
> + writel(val, msicfgaddrH);
> +}
> +
> +static int aplic_check_msicfg(struct aplic_msicfg_data *msicfg)
> +{
> + if (APLIC_xMSICFGADDRH_LHXS_MASK < msicfg->lhxs)
> + return SBI_EINVAL;
> +
> + if (APLIC_xMSICFGADDRH_LHXW_MASK < msicfg->lhxw)
> + return SBI_EINVAL;
> +
> + if (APLIC_xMSICFGADDRH_HHXS_MASK < msicfg->hhxs)
> + return SBI_EINVAL;
> +
> + if (APLIC_xMSICFGADDRH_HHXW_MASK < msicfg->hhxw)
> + return SBI_EINVAL;
> +
> + return 0;
> +}
> +
> +int aplic_cold_irqchip_init(struct aplic_data *aplic)
> +{
> + int rc;
> + u32 i, j, tmp;
> + struct sbi_domain_memregion reg;
> + struct aplic_delegate_data *deleg;
> + u32 first_deleg_irq, last_deleg_irq;
> +
> + /* Sanity checks */
> + if (!aplic ||
> + !aplic->num_source || APLIC_MAX_SOURCE <= aplic->num_source ||
> + APLIC_MAX_IDC <= aplic->num_idc)
> + return SBI_EINVAL;
> + if (aplic->targets_mmode && aplic->has_msicfg_mmode) {
> + rc = aplic_check_msicfg(&aplic->msicfg_mmode);
> + if (rc)
> + return rc;
> + }
> + if (aplic->targets_mmode && aplic->has_msicfg_smode) {
> + rc = aplic_check_msicfg(&aplic->msicfg_smode);
> + if (rc)
> + return rc;
> + }
> +
> + /* Set domain configuration to 0 */
> + writel(0, (void *)(aplic->addr + APLIC_DOMAINCFG));
> +
> + /* Disable all interrupts */
> + for (i = 0; i <= aplic->num_source; i++)
> + writel(-1U, (void *)(aplic->addr + APLIC_CLRIE_BASE +
> + (i / 32) * sizeof(u32)));
> +
> + /* Set interrupt type and priority for all interrupts */
> + for (i = 1; i <= aplic->num_source; i++) {
> + /* Set IRQ source configuration to 0 */
> + writel(0, (void *)(aplic->addr + APLIC_SOURCECFG_BASE +
> + (i - 1) * sizeof(u32)));
> + /* Set IRQ target hart index and priority to 1 */
> + writel(APLIC_DEFAULT_PRIORITY, (void *)(aplic->addr +
> + APLIC_TARGET_BASE +
> + (i - 1) * sizeof(u32)));
> + }
> +
> + /* Configure IRQ delegation */
> + first_deleg_irq = -1U;
> + last_deleg_irq = 0;
> + for (i = 0; i < APLIC_MAX_DELEGATE; i++) {
> + deleg = &aplic->delegate[i];
> + if (!deleg->first_irq || !deleg->last_irq)
> + continue;
> + if (aplic->num_source < deleg->first_irq ||
> + aplic->num_source < deleg->last_irq)
> + continue;
> + if (APLIC_SOURCECFG_CHILDIDX_MASK < deleg->child_index)
> + continue;
> + if (deleg->first_irq > deleg->last_irq) {
> + tmp = deleg->first_irq;
> + deleg->first_irq = deleg->last_irq;
> + deleg->last_irq = tmp;
> + }
> + if (deleg->first_irq < first_deleg_irq)
> + first_deleg_irq = deleg->first_irq;
> + if (last_deleg_irq < deleg->last_irq)
> + last_deleg_irq = deleg->last_irq;
> + for (j = deleg->first_irq; j <= deleg->last_irq; j++)
> + writel(APLIC_SOURCECFG_D | deleg->child_index,
> + (void *)(aplic->addr + APLIC_SOURCECFG_BASE +
> + (j - 1) * sizeof(u32)));
> + }
> +
> + /* Default initialization of IDC structures */
> + for (i = 0; i < aplic->num_idc; i++) {
> + writel(0, (void *)(aplic->addr + APLIC_IDC_BASE +
> + i * APLIC_IDC_SIZE + APLIC_IDC_IDELIVERY));
> + writel(0, (void *)(aplic->addr + APLIC_IDC_BASE +
> + i * APLIC_IDC_SIZE + APLIC_IDC_IFORCE));
> + writel(APLIC_DISABLE_ITHRESHOLD, (void *)(aplic->addr +
> + APLIC_IDC_BASE +
> + (i * APLIC_IDC_SIZE) +
> + APLIC_IDC_ITHRESHOLD));
> + }
> +
> + /* MSI configuration */
> + if (aplic->targets_mmode && aplic->has_msicfg_mmode) {
> + aplic_writel_msicfg(&aplic->msicfg_mmode,
> + (void *)(aplic->addr + APLIC_MMSICFGADDR),
> + (void *)(aplic->addr + APLIC_MMSICFGADDRH));
> + }
> + if (aplic->targets_mmode && aplic->has_msicfg_smode) {
> + aplic_writel_msicfg(&aplic->msicfg_smode,
> + (void *)(aplic->addr + APLIC_SMSICFGADDR),
> + (void *)(aplic->addr + APLIC_SMSICFGADDRH));
> + }
> +
> + /*
> + * Add APLIC region to the root domain if:
> + * 1) It targets M-mode of any HART directly or via MSIs
> + * 2) All interrupts are delegated to some child APLIC
> + */
> + if (aplic->targets_mmode ||
> + ((first_deleg_irq < last_deleg_irq) &&
> + (last_deleg_irq == aplic->num_source) &&
> + (first_deleg_irq == 1))) {
> + sbi_domain_memregion_init(aplic->addr, aplic->size,
> + SBI_DOMAIN_MEMREGION_MMIO, ®);
> + rc = sbi_domain_root_add_memregion(®);
> + if (rc)
> + return rc;
> + }
> +
> + return 0;
> +}
> diff --git a/lib/utils/irqchip/objects.mk b/lib/utils/irqchip/objects.mk
> index ae6f255..b2b3f79 100644
> --- a/lib/utils/irqchip/objects.mk
> +++ b/lib/utils/irqchip/objects.mk
> @@ -10,5 +10,6 @@
> libsbiutils-objs-y += irqchip/fdt_irqchip.o
> libsbiutils-objs-y += irqchip/fdt_irqchip_imsic.o
> libsbiutils-objs-y += irqchip/fdt_irqchip_plic.o
> +libsbiutils-objs-y += irqchip/aplic.o
> libsbiutils-objs-y += irqchip/imsic.o
> libsbiutils-objs-y += irqchip/plic.o
> --
> 2.25.1
>
LGTM.
Reviewed-by: Atish Patra <atishp@rivosinc.com>
--
Regards,
Atish
^ permalink raw reply [flat|nested] 36+ messages in thread* [PATCH v2 11/13] lib: utils/irqchip: Add APLIC initialization library
2022-02-12 0:32 ` Atish Patra
@ 2022-02-15 15:24 ` Anup Patel
0 siblings, 0 replies; 36+ messages in thread
From: Anup Patel @ 2022-02-15 15:24 UTC (permalink / raw)
To: opensbi
On Sat, Feb 12, 2022 at 6:02 AM Atish Patra <atishp@atishpatra.org> wrote:
>
> On Wed, Feb 9, 2022 at 7:05 AM Anup Patel <apatel@ventanamicro.com> wrote:
> >
> > We add simple APLIC initialization library which is independent of
> > hardware description format (FDT or ACPI). This APLIC initialization
> > library can be used by custom OpenSBI platform support to setup
> > APLIC domains.
> >
> > Signed-off-by: Anup Patel <anup.patel@wdc.com>
> > Signed-off-by: Anup Patel <apatel@ventanamicro.com>
> > ---
> > include/sbi_utils/irqchip/aplic.h | 47 +++++
> > lib/utils/irqchip/aplic.c | 279 ++++++++++++++++++++++++++++++
> > lib/utils/irqchip/objects.mk | 1 +
> > 3 files changed, 327 insertions(+)
> > create mode 100644 include/sbi_utils/irqchip/aplic.h
> > create mode 100644 lib/utils/irqchip/aplic.c
> >
> > diff --git a/include/sbi_utils/irqchip/aplic.h b/include/sbi_utils/irqchip/aplic.h
> > new file mode 100644
> > index 0000000..82682e8
> > --- /dev/null
> > +++ b/include/sbi_utils/irqchip/aplic.h
> > @@ -0,0 +1,47 @@
> > +/*
> > + * SPDX-License-Identifier: BSD-2-Clause
> > + *
> > + * Copyright (c) 2021 Western Digital Corporation or its affiliates.
> > + * Copyright (c) 2022 Ventana Micro Systems Inc.
> > + *
> > + * Authors:
> > + * Anup Patel <anup.patel@wdc.com>
> > + */
> > +
> > +#ifndef __IRQCHIP_APLIC_H__
> > +#define __IRQCHIP_APLIC_H__
> > +
> > +#include <sbi/sbi_types.h>
> > +
> > +#define APLIC_MAX_DELEGATE 16
> > +
> > +struct aplic_msicfg_data {
> > + unsigned long lhxs;
> > + unsigned long lhxw;
> > + unsigned long hhxs;
> > + unsigned long hhxw;
> > + unsigned long base_addr;
> > +};
> > +
> > +struct aplic_delegate_data {
> > + u32 first_irq;
> > + u32 last_irq;
> > + u32 child_index;
> > +};
> > +
> > +struct aplic_data {
> > + unsigned long addr;
> > + unsigned long size;
> > + unsigned long num_idc;
> > + unsigned long num_source;
> > + bool targets_mmode;
> > + bool has_msicfg_mmode;
> > + struct aplic_msicfg_data msicfg_mmode;
> > + bool has_msicfg_smode;
> > + struct aplic_msicfg_data msicfg_smode;
> > + struct aplic_delegate_data delegate[APLIC_MAX_DELEGATE];
> > +};
> > +
> > +int aplic_cold_irqchip_init(struct aplic_data *aplic);
> > +
> > +#endif
> > diff --git a/lib/utils/irqchip/aplic.c b/lib/utils/irqchip/aplic.c
> > new file mode 100644
> > index 0000000..0a8469b
> > --- /dev/null
> > +++ b/lib/utils/irqchip/aplic.c
> > @@ -0,0 +1,279 @@
> > +/*
> > + * SPDX-License-Identifier: BSD-2-Clause
> > + *
> > + * Copyright (c) 2021 Western Digital Corporation or its affiliates.
> > + * Copyright (c) 2022 Ventana Micro Systems Inc.
> > + *
> > + * Authors:
> > + * Anup Patel <anup.patel@wdc.com>
> > + */
> > +
> > +#include <sbi/riscv_io.h>
> > +#include <sbi/sbi_console.h>
> > +#include <sbi/sbi_domain.h>
> > +#include <sbi/sbi_error.h>
> > +#include <sbi_utils/irqchip/aplic.h>
> > +
> > +#define APLIC_MAX_IDC (1UL << 14)
> > +#define APLIC_MAX_SOURCE 1024
> > +
> > +#define APLIC_DOMAINCFG 0x0000
> > +#define APLIC_DOMAINCFG_IE (1 << 8)
> > +#define APLIC_DOMAINCFG_DM (1 << 2)
> > +#define APLIC_DOMAINCFG_BE (1 << 0)
> > +
> > +#define APLIC_SOURCECFG_BASE 0x0004
> > +#define APLIC_SOURCECFG_D (1 << 10)
> > +#define APLIC_SOURCECFG_CHILDIDX_MASK 0x000003ff
> > +#define APLIC_SOURCECFG_SM_MASK 0x00000007
> > +#define APLIC_SOURCECFG_SM_INACTIVE 0x0
> > +#define APLIC_SOURCECFG_SM_DETACH 0x1
> > +#define APLIC_SOURCECFG_SM_EDGE_RISE 0x4
> > +#define APLIC_SOURCECFG_SM_EDGE_FALL 0x5
> > +#define APLIC_SOURCECFG_SM_LEVEL_HIGH 0x6
> > +#define APLIC_SOURCECFG_SM_LEVEL_LOW 0x7
> > +
> > +#define APLIC_MMSICFGADDR 0x1bc0
> > +#define APLIC_MMSICFGADDRH 0x1bc4
> > +#define APLIC_SMSICFGADDR 0x1bc8
> > +#define APLIC_SMSICFGADDRH 0x1bcc
> > +
> > +#define APLIC_xMSICFGADDRH_L (1UL << 31)
> > +#define APLIC_xMSICFGADDRH_HHXS_MASK 0x1f
> > +#define APLIC_xMSICFGADDRH_HHXS_SHIFT 24
> > +#define APLIC_xMSICFGADDRH_LHXS_MASK 0x7
> > +#define APLIC_xMSICFGADDRH_LHXS_SHIFT 20
> > +#define APLIC_xMSICFGADDRH_HHXW_MASK 0x7
> > +#define APLIC_xMSICFGADDRH_HHXW_SHIFT 16
> > +#define APLIC_xMSICFGADDRH_LHXW_MASK 0xf
> > +#define APLIC_xMSICFGADDRH_LHXW_SHIFT 12
> > +#define APLIC_xMSICFGADDRH_BAPPN_MASK 0xfff
> > +
> > +#define APLIC_xMSICFGADDR_PPN_SHIFT 12
> > +
> > +#define APLIC_xMSICFGADDR_PPN_HART(__lhxs) \
> > + ((1UL << (__lhxs)) - 1)
> > +
> > +#define APLIC_xMSICFGADDR_PPN_LHX_MASK(__lhxw) \
> > + ((1UL << (__lhxw)) - 1)
> > +#define APLIC_xMSICFGADDR_PPN_LHX_SHIFT(__lhxs) \
> > + ((__lhxs))
> > +#define APLIC_xMSICFGADDR_PPN_LHX(__lhxw, __lhxs) \
> > + (APLIC_xMSICFGADDR_PPN_LHX_MASK(__lhxw) << \
> > + APLIC_xMSICFGADDR_PPN_LHX_SHIFT(__lhxs))
> > +
> > +#define APLIC_xMSICFGADDR_PPN_HHX_MASK(__hhxw) \
> > + ((1UL << (__hhxw)) - 1)
> > +#define APLIC_xMSICFGADDR_PPN_HHX_SHIFT(__hhxs) \
> > + ((__hhxs) + APLIC_xMSICFGADDR_PPN_SHIFT)
> > +#define APLIC_xMSICFGADDR_PPN_HHX(__hhxw, __hhxs) \
> > + (APLIC_xMSICFGADDR_PPN_HHX_MASK(__hhxw) << \
> > + APLIC_xMSICFGADDR_PPN_HHX_SHIFT(__hhxs))
> > +
> > +#define APLIC_SETIP_BASE 0x1c00
> > +#define APLIC_SETIPNUM 0x1cdc
> > +
> > +#define APLIC_CLRIP_BASE 0x1d00
> > +#define APLIC_CLRIPNUM 0x1ddc
> > +
> > +#define APLIC_SETIE_BASE 0x1e00
> > +#define APLIC_SETIENUM 0x1edc
> > +
> > +#define APLIC_CLRIE_BASE 0x1f00
> > +#define APLIC_CLRIENUM 0x1fdc
> > +
> > +#define APLIC_SETIPNUM_LE 0x2000
> > +#define APLIC_SETIPNUM_BE 0x2004
> > +
> > +#define APLIC_TARGET_BASE 0x3004
> > +#define APLIC_TARGET_HART_IDX_SHIFT 18
> > +#define APLIC_TARGET_HART_IDX_MASK 0x3fff
> > +#define APLIC_TARGET_GUEST_IDX_SHIFT 12
> > +#define APLIC_TARGET_GUEST_IDX_MASK 0x3f
> > +#define APLIC_TARGET_IPRIO_MASK 0xff
> > +#define APLIC_TARGET_EIID_MASK 0x7ff
> > +
> > +#define APLIC_IDC_BASE 0x4000
> > +#define APLIC_IDC_SIZE 32
> > +
> > +#define APLIC_IDC_IDELIVERY 0x00
> > +
> > +#define APLIC_IDC_IFORCE 0x04
> > +
> > +#define APLIC_IDC_ITHRESHOLD 0x08
> > +
> > +#define APLIC_IDC_TOPI 0x18
> > +#define APLIC_IDC_TOPI_ID_SHIFT 16
> > +#define APLIC_IDC_TOPI_ID_MASK 0x3ff
> > +#define APLIC_IDC_TOPI_PRIO_MASK 0xff
> > +
> > +#define APLIC_IDC_CLAIMI 0x1c
> > +
> > +#define APLIC_DEFAULT_PRIORITY 1
> > +#define APLIC_DISABLE_IDELIVERY 0
> > +#define APLIC_ENABLE_IDELIVERY 1
> > +#define APLIC_DISABLE_ITHRESHOLD 1
> > +#define APLIC_ENABLE_ITHRESHOLD 0
> > +
> > +static void aplic_writel_msicfg(struct aplic_msicfg_data *msicfg,
> > + void *msicfgaddr, void *msicfgaddrH)
> > +{
> > + u32 val;
> > + unsigned long base_ppn;
> > +
> > + /* Check if MSI config is already locked */
> > + if (readl(msicfgaddrH) & APLIC_xMSICFGADDRH_L)
> > + return;
> > +
> > + /* Compute the MSI base PPN */
> > + base_ppn = msicfg->base_addr >> APLIC_xMSICFGADDR_PPN_SHIFT;
> > + base_ppn &= ~APLIC_xMSICFGADDR_PPN_HART(msicfg->lhxs);
> > + base_ppn &= ~APLIC_xMSICFGADDR_PPN_LHX(msicfg->lhxw, msicfg->lhxs);
> > + base_ppn &= ~APLIC_xMSICFGADDR_PPN_HHX(msicfg->hhxw, msicfg->hhxs);
> > +
> > + /* Write the lower MSI config register */
> > + writel((u32)base_ppn, msicfgaddr);
> > +
> > + /* Write the upper MSI config register */
> > + val = (((u64)base_ppn) >> 32) &
> > + APLIC_xMSICFGADDRH_BAPPN_MASK;
> > + val |= (msicfg->lhxw & APLIC_xMSICFGADDRH_LHXW_MASK)
> > + << APLIC_xMSICFGADDRH_LHXW_SHIFT;
> > + val |= (msicfg->hhxw & APLIC_xMSICFGADDRH_HHXW_MASK)
> > + << APLIC_xMSICFGADDRH_HHXW_SHIFT;
> > + val |= (msicfg->lhxs & APLIC_xMSICFGADDRH_LHXS_MASK)
> > + << APLIC_xMSICFGADDRH_LHXS_SHIFT;
> > + val |= (msicfg->hhxs & APLIC_xMSICFGADDRH_HHXS_MASK)
> > + << APLIC_xMSICFGADDRH_HHXS_SHIFT;
> > + writel(val, msicfgaddrH);
> > +}
> > +
> > +static int aplic_check_msicfg(struct aplic_msicfg_data *msicfg)
> > +{
> > + if (APLIC_xMSICFGADDRH_LHXS_MASK < msicfg->lhxs)
> > + return SBI_EINVAL;
> > +
> > + if (APLIC_xMSICFGADDRH_LHXW_MASK < msicfg->lhxw)
> > + return SBI_EINVAL;
> > +
> > + if (APLIC_xMSICFGADDRH_HHXS_MASK < msicfg->hhxs)
> > + return SBI_EINVAL;
> > +
> > + if (APLIC_xMSICFGADDRH_HHXW_MASK < msicfg->hhxw)
> > + return SBI_EINVAL;
> > +
> > + return 0;
> > +}
> > +
> > +int aplic_cold_irqchip_init(struct aplic_data *aplic)
> > +{
> > + int rc;
> > + u32 i, j, tmp;
> > + struct sbi_domain_memregion reg;
> > + struct aplic_delegate_data *deleg;
> > + u32 first_deleg_irq, last_deleg_irq;
> > +
> > + /* Sanity checks */
> > + if (!aplic ||
> > + !aplic->num_source || APLIC_MAX_SOURCE <= aplic->num_source ||
> > + APLIC_MAX_IDC <= aplic->num_idc)
> > + return SBI_EINVAL;
> > + if (aplic->targets_mmode && aplic->has_msicfg_mmode) {
> > + rc = aplic_check_msicfg(&aplic->msicfg_mmode);
> > + if (rc)
> > + return rc;
> > + }
> > + if (aplic->targets_mmode && aplic->has_msicfg_smode) {
> > + rc = aplic_check_msicfg(&aplic->msicfg_smode);
> > + if (rc)
> > + return rc;
> > + }
> > +
> > + /* Set domain configuration to 0 */
> > + writel(0, (void *)(aplic->addr + APLIC_DOMAINCFG));
> > +
> > + /* Disable all interrupts */
> > + for (i = 0; i <= aplic->num_source; i++)
> > + writel(-1U, (void *)(aplic->addr + APLIC_CLRIE_BASE +
> > + (i / 32) * sizeof(u32)));
> > +
> > + /* Set interrupt type and priority for all interrupts */
> > + for (i = 1; i <= aplic->num_source; i++) {
> > + /* Set IRQ source configuration to 0 */
> > + writel(0, (void *)(aplic->addr + APLIC_SOURCECFG_BASE +
> > + (i - 1) * sizeof(u32)));
> > + /* Set IRQ target hart index and priority to 1 */
> > + writel(APLIC_DEFAULT_PRIORITY, (void *)(aplic->addr +
> > + APLIC_TARGET_BASE +
> > + (i - 1) * sizeof(u32)));
> > + }
> > +
> > + /* Configure IRQ delegation */
> > + first_deleg_irq = -1U;
> > + last_deleg_irq = 0;
> > + for (i = 0; i < APLIC_MAX_DELEGATE; i++) {
> > + deleg = &aplic->delegate[i];
> > + if (!deleg->first_irq || !deleg->last_irq)
> > + continue;
> > + if (aplic->num_source < deleg->first_irq ||
> > + aplic->num_source < deleg->last_irq)
> > + continue;
> > + if (APLIC_SOURCECFG_CHILDIDX_MASK < deleg->child_index)
> > + continue;
> > + if (deleg->first_irq > deleg->last_irq) {
> > + tmp = deleg->first_irq;
> > + deleg->first_irq = deleg->last_irq;
> > + deleg->last_irq = tmp;
> > + }
> > + if (deleg->first_irq < first_deleg_irq)
> > + first_deleg_irq = deleg->first_irq;
> > + if (last_deleg_irq < deleg->last_irq)
> > + last_deleg_irq = deleg->last_irq;
> > + for (j = deleg->first_irq; j <= deleg->last_irq; j++)
> > + writel(APLIC_SOURCECFG_D | deleg->child_index,
> > + (void *)(aplic->addr + APLIC_SOURCECFG_BASE +
> > + (j - 1) * sizeof(u32)));
> > + }
> > +
> > + /* Default initialization of IDC structures */
> > + for (i = 0; i < aplic->num_idc; i++) {
> > + writel(0, (void *)(aplic->addr + APLIC_IDC_BASE +
> > + i * APLIC_IDC_SIZE + APLIC_IDC_IDELIVERY));
> > + writel(0, (void *)(aplic->addr + APLIC_IDC_BASE +
> > + i * APLIC_IDC_SIZE + APLIC_IDC_IFORCE));
> > + writel(APLIC_DISABLE_ITHRESHOLD, (void *)(aplic->addr +
> > + APLIC_IDC_BASE +
> > + (i * APLIC_IDC_SIZE) +
> > + APLIC_IDC_ITHRESHOLD));
> > + }
> > +
> > + /* MSI configuration */
> > + if (aplic->targets_mmode && aplic->has_msicfg_mmode) {
> > + aplic_writel_msicfg(&aplic->msicfg_mmode,
> > + (void *)(aplic->addr + APLIC_MMSICFGADDR),
> > + (void *)(aplic->addr + APLIC_MMSICFGADDRH));
> > + }
> > + if (aplic->targets_mmode && aplic->has_msicfg_smode) {
> > + aplic_writel_msicfg(&aplic->msicfg_smode,
> > + (void *)(aplic->addr + APLIC_SMSICFGADDR),
> > + (void *)(aplic->addr + APLIC_SMSICFGADDRH));
> > + }
> > +
> > + /*
> > + * Add APLIC region to the root domain if:
> > + * 1) It targets M-mode of any HART directly or via MSIs
> > + * 2) All interrupts are delegated to some child APLIC
> > + */
> > + if (aplic->targets_mmode ||
> > + ((first_deleg_irq < last_deleg_irq) &&
> > + (last_deleg_irq == aplic->num_source) &&
> > + (first_deleg_irq == 1))) {
> > + sbi_domain_memregion_init(aplic->addr, aplic->size,
> > + SBI_DOMAIN_MEMREGION_MMIO, ®);
> > + rc = sbi_domain_root_add_memregion(®);
> > + if (rc)
> > + return rc;
> > + }
> > +
> > + return 0;
> > +}
> > diff --git a/lib/utils/irqchip/objects.mk b/lib/utils/irqchip/objects.mk
> > index ae6f255..b2b3f79 100644
> > --- a/lib/utils/irqchip/objects.mk
> > +++ b/lib/utils/irqchip/objects.mk
> > @@ -10,5 +10,6 @@
> > libsbiutils-objs-y += irqchip/fdt_irqchip.o
> > libsbiutils-objs-y += irqchip/fdt_irqchip_imsic.o
> > libsbiutils-objs-y += irqchip/fdt_irqchip_plic.o
> > +libsbiutils-objs-y += irqchip/aplic.o
> > libsbiutils-objs-y += irqchip/imsic.o
> > libsbiutils-objs-y += irqchip/plic.o
> > --
> > 2.25.1
> >
>
> LGTM.
>
>
> Reviewed-by: Atish Patra <atishp@rivosinc.com>
Applied this patch to the riscv/opensbi repo.
Regards,
Anup
>
> --
> Regards,
> Atish
^ permalink raw reply [flat|nested] 36+ messages in thread
* [PATCH v2 12/13] lib: utils/irqchip: Add FDT based driver for APLIC
2022-02-09 15:04 [PATCH v2 00/13] OpenSBI RISC-V AIA Support Anup Patel
` (10 preceding siblings ...)
2022-02-09 15:04 ` [PATCH v2 11/13] lib: utils/irqchip: Add APLIC initialization library Anup Patel
@ 2022-02-09 15:04 ` Anup Patel
2022-02-12 0:56 ` Atish Patra
2022-02-09 15:04 ` [PATCH v2 13/13] lib: utils: Disable appropriate APLIC DT nodes in fdt_fixups() Anup Patel
12 siblings, 1 reply; 36+ messages in thread
From: Anup Patel @ 2022-02-09 15:04 UTC (permalink / raw)
To: opensbi
We add simple FDT irqchip driver for APLIC so that generic platform (and
other FDT based platforms) can utilize common APLIC initialization library.
Signed-off-by: Anup Patel <anup.patel@wdc.com>
Signed-off-by: Anup Patel <apatel@ventanamicro.com>
---
include/sbi_utils/fdt/fdt_helper.h | 4 +
lib/utils/fdt/fdt_helper.c | 159 ++++++++++++++++++++++++++
lib/utils/irqchip/fdt_irqchip.c | 2 +
lib/utils/irqchip/fdt_irqchip_aplic.c | 56 +++++++++
lib/utils/irqchip/objects.mk | 1 +
5 files changed, 222 insertions(+)
create mode 100644 lib/utils/irqchip/fdt_irqchip_aplic.c
diff --git a/include/sbi_utils/fdt/fdt_helper.h b/include/sbi_utils/fdt/fdt_helper.h
index 4c8d29e..1232b26 100644
--- a/include/sbi_utils/fdt/fdt_helper.h
+++ b/include/sbi_utils/fdt/fdt_helper.h
@@ -68,6 +68,10 @@ int fdt_parse_uart8250_node(void *fdt, int nodeoffset,
int fdt_parse_uart8250(void *fdt, struct platform_uart_data *uart,
const char *compatible);
+struct aplic_data;
+
+int fdt_parse_aplic_node(void *fdt, int nodeoff, struct aplic_data *aplic);
+
struct imsic_data;
bool fdt_check_imsic_mlevel(void *fdt);
diff --git a/lib/utils/fdt/fdt_helper.c b/lib/utils/fdt/fdt_helper.c
index e179b79..3a306cb 100644
--- a/lib/utils/fdt/fdt_helper.c
+++ b/lib/utils/fdt/fdt_helper.c
@@ -13,6 +13,7 @@
#include <sbi/sbi_platform.h>
#include <sbi/sbi_scratch.h>
#include <sbi_utils/fdt/fdt_helper.h>
+#include <sbi_utils/irqchip/aplic.h>
#include <sbi_utils/irqchip/imsic.h>
#include <sbi_utils/irqchip/plic.h>
@@ -466,6 +467,164 @@ int fdt_parse_uart8250(void *fdt, struct platform_uart_data *uart,
return fdt_parse_uart8250_node(fdt, nodeoffset, uart);
}
+int fdt_parse_aplic_node(void *fdt, int nodeoff, struct aplic_data *aplic)
+{
+ bool child_found;
+ const fdt32_t *val;
+ const fdt32_t *del;
+ struct imsic_data imsic;
+ int i, j, d, dcnt, len, noff, rc;
+ uint64_t reg_addr, reg_size;
+ struct aplic_delegate_data *deleg;
+
+ if (nodeoff < 0 || !aplic || !fdt)
+ return SBI_ENODEV;
+ memset(aplic, 0, sizeof(*aplic));
+
+ rc = fdt_get_node_addr_size(fdt, nodeoff, 0, ®_addr, ®_size);
+ if (rc < 0 || !reg_addr || !reg_size)
+ return SBI_ENODEV;
+ aplic->addr = reg_addr;
+ aplic->size = reg_size;
+
+ val = fdt_getprop(fdt, nodeoff, "riscv,num-sources", &len);
+ if (len > 0)
+ aplic->num_source = fdt32_to_cpu(*val);
+
+ val = fdt_getprop(fdt, nodeoff, "interrupts-extended", &len);
+ if (val && len > sizeof(fdt32_t)) {
+ len = len / sizeof(fdt32_t);
+ for (i = 0; i < len; i += 2) {
+ if (fdt32_to_cpu(val[i + 1]) == IRQ_M_EXT) {
+ aplic->targets_mmode = true;
+ break;
+ }
+ }
+ aplic->num_idc = len / 2;
+ goto aplic_msi_parent_done;
+ }
+
+ val = fdt_getprop(fdt, nodeoff, "msi-parent", &len);
+ if (val && len >= sizeof(fdt32_t)) {
+ noff = fdt_node_offset_by_phandle(fdt, fdt32_to_cpu(*val));
+ if (noff < 0)
+ return noff;
+
+ rc = fdt_parse_imsic_node(fdt, noff, &imsic);
+ if (rc)
+ return rc;
+
+ rc = imsic_data_check(&imsic);
+ if (rc)
+ return rc;
+
+ aplic->targets_mmode = imsic.targets_mmode;
+
+ if (imsic.targets_mmode) {
+ aplic->has_msicfg_mmode = true;
+ aplic->msicfg_mmode.lhxs = imsic.guest_index_bits;
+ aplic->msicfg_mmode.lhxw = imsic.hart_index_bits;
+ aplic->msicfg_mmode.hhxw = imsic.group_index_bits;
+ aplic->msicfg_mmode.hhxs = imsic.group_index_shift;
+ if (aplic->msicfg_mmode.hhxs <
+ (2 * IMSIC_MMIO_PAGE_SHIFT))
+ return SBI_EINVAL;
+ aplic->msicfg_mmode.hhxs -= 24;
+ aplic->msicfg_mmode.base_addr = imsic.regs[0].addr;
+ } else {
+ goto aplic_msi_parent_done;
+ }
+
+ val = fdt_getprop(fdt, nodeoff, "riscv,children", &len);
+ if (!val || len < sizeof(fdt32_t))
+ goto aplic_msi_parent_done;
+
+ noff = fdt_node_offset_by_phandle(fdt, fdt32_to_cpu(*val));
+ if (noff < 0)
+ return noff;
+
+ val = fdt_getprop(fdt, noff, "msi-parent", &len);
+ if (!val || len < sizeof(fdt32_t))
+ goto aplic_msi_parent_done;
+
+ noff = fdt_node_offset_by_phandle(fdt, fdt32_to_cpu(*val));
+ if (noff < 0)
+ return noff;
+
+ rc = fdt_parse_imsic_node(fdt, noff, &imsic);
+ if (rc)
+ return rc;
+
+ rc = imsic_data_check(&imsic);
+ if (rc)
+ return rc;
+
+ if (!imsic.targets_mmode) {
+ aplic->has_msicfg_smode = true;
+ aplic->msicfg_smode.lhxs = imsic.guest_index_bits;
+ aplic->msicfg_smode.lhxw = imsic.hart_index_bits;
+ aplic->msicfg_smode.hhxw = imsic.group_index_bits;
+ aplic->msicfg_smode.hhxs = imsic.group_index_shift;
+ if (aplic->msicfg_smode.hhxs <
+ (2 * IMSIC_MMIO_PAGE_SHIFT))
+ return SBI_EINVAL;
+ aplic->msicfg_smode.hhxs -= 24;
+ aplic->msicfg_smode.base_addr = imsic.regs[0].addr;
+ }
+ }
+aplic_msi_parent_done:
+
+ for (d = 0; d < APLIC_MAX_DELEGATE; d++) {
+ deleg = &aplic->delegate[d];
+ deleg->first_irq = 0;
+ deleg->last_irq = 0;
+ deleg->child_index = 0;
+ }
+
+ del = fdt_getprop(fdt, nodeoff, "riscv,delegate", &len);
+ if (!del || len < (3 * sizeof(fdt32_t)))
+ goto skip_delegate_parse;
+ d = 0;
+ dcnt = len / sizeof(fdt32_t);
+ for (i = 0; i < dcnt; i += 3) {
+ if (d >= APLIC_MAX_DELEGATE)
+ break;
+ deleg = &aplic->delegate[d];
+
+ deleg->first_irq = fdt32_to_cpu(del[i + 1]);
+ deleg->last_irq = fdt32_to_cpu(del[i + 2]);
+ deleg->child_index = 0;
+
+ child_found = false;
+ val = fdt_getprop(fdt, nodeoff, "riscv,children", &len);
+ if (!val || len < sizeof(fdt32_t)) {
+ deleg->first_irq = 0;
+ deleg->last_irq = 0;
+ deleg->child_index = 0;
+ continue;
+ }
+ len = len / sizeof(fdt32_t);
+ for (j = 0; j < len; j++) {
+ if (del[i] != val[j])
+ continue;
+ deleg->child_index = j;
+ child_found = true;
+ break;
+ }
+
+ if (child_found) {
+ d++;
+ } else {
+ deleg->first_irq = 0;
+ deleg->last_irq = 0;
+ deleg->child_index = 0;
+ }
+ }
+skip_delegate_parse:
+
+ return 0;
+}
+
bool fdt_check_imsic_mlevel(void *fdt)
{
const fdt32_t *val;
diff --git a/lib/utils/irqchip/fdt_irqchip.c b/lib/utils/irqchip/fdt_irqchip.c
index cf64a2e..6007755 100644
--- a/lib/utils/irqchip/fdt_irqchip.c
+++ b/lib/utils/irqchip/fdt_irqchip.c
@@ -12,10 +12,12 @@
#include <sbi_utils/fdt/fdt_helper.h>
#include <sbi_utils/irqchip/fdt_irqchip.h>
+extern struct fdt_irqchip fdt_irqchip_aplic;
extern struct fdt_irqchip fdt_irqchip_imsic;
extern struct fdt_irqchip fdt_irqchip_plic;
static struct fdt_irqchip *irqchip_drivers[] = {
+ &fdt_irqchip_aplic,
&fdt_irqchip_imsic,
&fdt_irqchip_plic
};
diff --git a/lib/utils/irqchip/fdt_irqchip_aplic.c b/lib/utils/irqchip/fdt_irqchip_aplic.c
new file mode 100644
index 0000000..965f023
--- /dev/null
+++ b/lib/utils/irqchip/fdt_irqchip_aplic.c
@@ -0,0 +1,56 @@
+/*
+ * SPDX-License-Identifier: BSD-2-Clause
+ *
+ * Copyright (c) 2021 Western Digital Corporation or its affiliates.
+ * Copyright (c) 2022 Ventana Micro Systems Inc.
+ *
+ * Authors:
+ * Anup Patel <anup.patel@wdc.com>
+ */
+
+#include <libfdt.h>
+#include <sbi/riscv_asm.h>
+#include <sbi/sbi_error.h>
+#include <sbi_utils/fdt/fdt_helper.h>
+#include <sbi_utils/irqchip/fdt_irqchip.h>
+#include <sbi_utils/irqchip/aplic.h>
+
+#define APLIC_MAX_NR 16
+
+static unsigned long aplic_count = 0;
+static struct aplic_data aplic[APLIC_MAX_NR];
+
+static int irqchip_aplic_warm_init(void)
+{
+ /* Nothing to do here. */
+ return 0;
+}
+
+static int irqchip_aplic_cold_init(void *fdt, int nodeoff,
+ const struct fdt_match *match)
+{
+ int rc;
+ struct aplic_data *pd;
+
+ if (APLIC_MAX_NR <= aplic_count)
+ return SBI_ENOSPC;
+ pd = &aplic[aplic_count++];
+
+ rc = fdt_parse_aplic_node(fdt, nodeoff, pd);
+ if (rc)
+ return rc;
+
+ return aplic_cold_irqchip_init(pd);
+}
+
+static const struct fdt_match irqchip_aplic_match[] = {
+ { .compatible = "riscv,aplic" },
+ { },
+};
+
+struct fdt_irqchip fdt_irqchip_aplic = {
+ .match_table = irqchip_aplic_match,
+ .cold_init = irqchip_aplic_cold_init,
+ .warm_init = irqchip_aplic_warm_init,
+ .exit = NULL,
+};
diff --git a/lib/utils/irqchip/objects.mk b/lib/utils/irqchip/objects.mk
index b2b3f79..fad4344 100644
--- a/lib/utils/irqchip/objects.mk
+++ b/lib/utils/irqchip/objects.mk
@@ -8,6 +8,7 @@
#
libsbiutils-objs-y += irqchip/fdt_irqchip.o
+libsbiutils-objs-y += irqchip/fdt_irqchip_aplic.o
libsbiutils-objs-y += irqchip/fdt_irqchip_imsic.o
libsbiutils-objs-y += irqchip/fdt_irqchip_plic.o
libsbiutils-objs-y += irqchip/aplic.o
--
2.25.1
^ permalink raw reply related [flat|nested] 36+ messages in thread* [PATCH v2 12/13] lib: utils/irqchip: Add FDT based driver for APLIC
2022-02-09 15:04 ` [PATCH v2 12/13] lib: utils/irqchip: Add FDT based driver for APLIC Anup Patel
@ 2022-02-12 0:56 ` Atish Patra
2022-02-15 14:57 ` Anup Patel
2022-02-15 15:25 ` Anup Patel
0 siblings, 2 replies; 36+ messages in thread
From: Atish Patra @ 2022-02-12 0:56 UTC (permalink / raw)
To: opensbi
On Wed, Feb 9, 2022 at 7:06 AM Anup Patel <apatel@ventanamicro.com> wrote:
>
> We add simple FDT irqchip driver for APLIC so that generic platform (and
> other FDT based platforms) can utilize common APLIC initialization library.
>
> Signed-off-by: Anup Patel <anup.patel@wdc.com>
> Signed-off-by: Anup Patel <apatel@ventanamicro.com>
> ---
> include/sbi_utils/fdt/fdt_helper.h | 4 +
> lib/utils/fdt/fdt_helper.c | 159 ++++++++++++++++++++++++++
> lib/utils/irqchip/fdt_irqchip.c | 2 +
> lib/utils/irqchip/fdt_irqchip_aplic.c | 56 +++++++++
> lib/utils/irqchip/objects.mk | 1 +
> 5 files changed, 222 insertions(+)
> create mode 100644 lib/utils/irqchip/fdt_irqchip_aplic.c
>
> diff --git a/include/sbi_utils/fdt/fdt_helper.h b/include/sbi_utils/fdt/fdt_helper.h
> index 4c8d29e..1232b26 100644
> --- a/include/sbi_utils/fdt/fdt_helper.h
> +++ b/include/sbi_utils/fdt/fdt_helper.h
> @@ -68,6 +68,10 @@ int fdt_parse_uart8250_node(void *fdt, int nodeoffset,
> int fdt_parse_uart8250(void *fdt, struct platform_uart_data *uart,
> const char *compatible);
>
> +struct aplic_data;
> +
> +int fdt_parse_aplic_node(void *fdt, int nodeoff, struct aplic_data *aplic);
> +
> struct imsic_data;
>
> bool fdt_check_imsic_mlevel(void *fdt);
> diff --git a/lib/utils/fdt/fdt_helper.c b/lib/utils/fdt/fdt_helper.c
> index e179b79..3a306cb 100644
> --- a/lib/utils/fdt/fdt_helper.c
> +++ b/lib/utils/fdt/fdt_helper.c
> @@ -13,6 +13,7 @@
> #include <sbi/sbi_platform.h>
> #include <sbi/sbi_scratch.h>
> #include <sbi_utils/fdt/fdt_helper.h>
> +#include <sbi_utils/irqchip/aplic.h>
> #include <sbi_utils/irqchip/imsic.h>
> #include <sbi_utils/irqchip/plic.h>
>
> @@ -466,6 +467,164 @@ int fdt_parse_uart8250(void *fdt, struct platform_uart_data *uart,
> return fdt_parse_uart8250_node(fdt, nodeoffset, uart);
> }
>
> +int fdt_parse_aplic_node(void *fdt, int nodeoff, struct aplic_data *aplic)
> +{
> + bool child_found;
> + const fdt32_t *val;
> + const fdt32_t *del;
> + struct imsic_data imsic;
> + int i, j, d, dcnt, len, noff, rc;
> + uint64_t reg_addr, reg_size;
> + struct aplic_delegate_data *deleg;
> +
> + if (nodeoff < 0 || !aplic || !fdt)
> + return SBI_ENODEV;
> + memset(aplic, 0, sizeof(*aplic));
> +
> + rc = fdt_get_node_addr_size(fdt, nodeoff, 0, ®_addr, ®_size);
> + if (rc < 0 || !reg_addr || !reg_size)
> + return SBI_ENODEV;
> + aplic->addr = reg_addr;
> + aplic->size = reg_size;
> +
> + val = fdt_getprop(fdt, nodeoff, "riscv,num-sources", &len);
> + if (len > 0)
> + aplic->num_source = fdt32_to_cpu(*val);
> +
> + val = fdt_getprop(fdt, nodeoff, "interrupts-extended", &len);
> + if (val && len > sizeof(fdt32_t)) {
> + len = len / sizeof(fdt32_t);
> + for (i = 0; i < len; i += 2) {
> + if (fdt32_to_cpu(val[i + 1]) == IRQ_M_EXT) {
> + aplic->targets_mmode = true;
> + break;
> + }
> + }
> + aplic->num_idc = len / 2;
> + goto aplic_msi_parent_done;
> + }
> +
> + val = fdt_getprop(fdt, nodeoff, "msi-parent", &len);
> + if (val && len >= sizeof(fdt32_t)) {
> + noff = fdt_node_offset_by_phandle(fdt, fdt32_to_cpu(*val));
> + if (noff < 0)
> + return noff;
> +
> + rc = fdt_parse_imsic_node(fdt, noff, &imsic);
> + if (rc)
> + return rc;
> +
> + rc = imsic_data_check(&imsic);
> + if (rc)
> + return rc;
> +
> + aplic->targets_mmode = imsic.targets_mmode;
> +
> + if (imsic.targets_mmode) {
> + aplic->has_msicfg_mmode = true;
> + aplic->msicfg_mmode.lhxs = imsic.guest_index_bits;
> + aplic->msicfg_mmode.lhxw = imsic.hart_index_bits;
> + aplic->msicfg_mmode.hhxw = imsic.group_index_bits;
> + aplic->msicfg_mmode.hhxs = imsic.group_index_shift;
> + if (aplic->msicfg_mmode.hhxs <
> + (2 * IMSIC_MMIO_PAGE_SHIFT))
> + return SBI_EINVAL;
> + aplic->msicfg_mmode.hhxs -= 24;
> + aplic->msicfg_mmode.base_addr = imsic.regs[0].addr;
> + } else {
> + goto aplic_msi_parent_done;
> + }
> +
> + val = fdt_getprop(fdt, nodeoff, "riscv,children", &len);
> + if (!val || len < sizeof(fdt32_t))
> + goto aplic_msi_parent_done;
> +
> + noff = fdt_node_offset_by_phandle(fdt, fdt32_to_cpu(*val));
> + if (noff < 0)
> + return noff;
> +
> + val = fdt_getprop(fdt, noff, "msi-parent", &len);
> + if (!val || len < sizeof(fdt32_t))
> + goto aplic_msi_parent_done;
> +
> + noff = fdt_node_offset_by_phandle(fdt, fdt32_to_cpu(*val));
> + if (noff < 0)
> + return noff;
> +
> + rc = fdt_parse_imsic_node(fdt, noff, &imsic);
> + if (rc)
> + return rc;
> +
> + rc = imsic_data_check(&imsic);
> + if (rc)
> + return rc;
> +
> + if (!imsic.targets_mmode) {
> + aplic->has_msicfg_smode = true;
> + aplic->msicfg_smode.lhxs = imsic.guest_index_bits;
> + aplic->msicfg_smode.lhxw = imsic.hart_index_bits;
> + aplic->msicfg_smode.hhxw = imsic.group_index_bits;
> + aplic->msicfg_smode.hhxs = imsic.group_index_shift;
> + if (aplic->msicfg_smode.hhxs <
> + (2 * IMSIC_MMIO_PAGE_SHIFT))
> + return SBI_EINVAL;
> + aplic->msicfg_smode.hhxs -= 24;
> + aplic->msicfg_smode.base_addr = imsic.regs[0].addr;
> + }
> + }
> +aplic_msi_parent_done:
> +
> + for (d = 0; d < APLIC_MAX_DELEGATE; d++) {
> + deleg = &aplic->delegate[d];
> + deleg->first_irq = 0;
> + deleg->last_irq = 0;
> + deleg->child_index = 0;
> + }
> +
> + del = fdt_getprop(fdt, nodeoff, "riscv,delegate", &len);
> + if (!del || len < (3 * sizeof(fdt32_t)))
> + goto skip_delegate_parse;
> + d = 0;
> + dcnt = len / sizeof(fdt32_t);
> + for (i = 0; i < dcnt; i += 3) {
> + if (d >= APLIC_MAX_DELEGATE)
> + break;
> + deleg = &aplic->delegate[d];
> +
> + deleg->first_irq = fdt32_to_cpu(del[i + 1]);
> + deleg->last_irq = fdt32_to_cpu(del[i + 2]);
> + deleg->child_index = 0;
> +
> + child_found = false;
> + val = fdt_getprop(fdt, nodeoff, "riscv,children", &len);
> + if (!val || len < sizeof(fdt32_t)) {
> + deleg->first_irq = 0;
> + deleg->last_irq = 0;
> + deleg->child_index = 0;
> + continue;
> + }
> + len = len / sizeof(fdt32_t);
> + for (j = 0; j < len; j++) {
> + if (del[i] != val[j])
> + continue;
> + deleg->child_index = j;
> + child_found = true;
> + break;
> + }
> +
> + if (child_found) {
> + d++;
> + } else {
> + deleg->first_irq = 0;
> + deleg->last_irq = 0;
> + deleg->child_index = 0;
> + }
> + }
> +skip_delegate_parse:
> +
> + return 0;
> +}
> +
> bool fdt_check_imsic_mlevel(void *fdt)
> {
> const fdt32_t *val;
> diff --git a/lib/utils/irqchip/fdt_irqchip.c b/lib/utils/irqchip/fdt_irqchip.c
> index cf64a2e..6007755 100644
> --- a/lib/utils/irqchip/fdt_irqchip.c
> +++ b/lib/utils/irqchip/fdt_irqchip.c
> @@ -12,10 +12,12 @@
> #include <sbi_utils/fdt/fdt_helper.h>
> #include <sbi_utils/irqchip/fdt_irqchip.h>
>
> +extern struct fdt_irqchip fdt_irqchip_aplic;
> extern struct fdt_irqchip fdt_irqchip_imsic;
> extern struct fdt_irqchip fdt_irqchip_plic;
>
> static struct fdt_irqchip *irqchip_drivers[] = {
> + &fdt_irqchip_aplic,
> &fdt_irqchip_imsic,
> &fdt_irqchip_plic
> };
> diff --git a/lib/utils/irqchip/fdt_irqchip_aplic.c b/lib/utils/irqchip/fdt_irqchip_aplic.c
> new file mode 100644
> index 0000000..965f023
> --- /dev/null
> +++ b/lib/utils/irqchip/fdt_irqchip_aplic.c
> @@ -0,0 +1,56 @@
> +/*
> + * SPDX-License-Identifier: BSD-2-Clause
> + *
> + * Copyright (c) 2021 Western Digital Corporation or its affiliates.
> + * Copyright (c) 2022 Ventana Micro Systems Inc.
> + *
> + * Authors:
> + * Anup Patel <anup.patel@wdc.com>
> + */
> +
> +#include <libfdt.h>
> +#include <sbi/riscv_asm.h>
> +#include <sbi/sbi_error.h>
> +#include <sbi_utils/fdt/fdt_helper.h>
> +#include <sbi_utils/irqchip/fdt_irqchip.h>
> +#include <sbi_utils/irqchip/aplic.h>
> +
> +#define APLIC_MAX_NR 16
> +
> +static unsigned long aplic_count = 0;
> +static struct aplic_data aplic[APLIC_MAX_NR];
> +
> +static int irqchip_aplic_warm_init(void)
> +{
> + /* Nothing to do here. */
> + return 0;
> +}
> +
> +static int irqchip_aplic_cold_init(void *fdt, int nodeoff,
> + const struct fdt_match *match)
> +{
> + int rc;
> + struct aplic_data *pd;
> +
> + if (APLIC_MAX_NR <= aplic_count)
> + return SBI_ENOSPC;
> + pd = &aplic[aplic_count++];
> +
> + rc = fdt_parse_aplic_node(fdt, nodeoff, pd);
> + if (rc)
> + return rc;
> +
> + return aplic_cold_irqchip_init(pd);
> +}
> +
> +static const struct fdt_match irqchip_aplic_match[] = {
> + { .compatible = "riscv,aplic" },
> + { },
> +};
> +
> +struct fdt_irqchip fdt_irqchip_aplic = {
> + .match_table = irqchip_aplic_match,
> + .cold_init = irqchip_aplic_cold_init,
> + .warm_init = irqchip_aplic_warm_init,
> + .exit = NULL,
> +};
> diff --git a/lib/utils/irqchip/objects.mk b/lib/utils/irqchip/objects.mk
> index b2b3f79..fad4344 100644
> --- a/lib/utils/irqchip/objects.mk
> +++ b/lib/utils/irqchip/objects.mk
> @@ -8,6 +8,7 @@
> #
>
> libsbiutils-objs-y += irqchip/fdt_irqchip.o
> +libsbiutils-objs-y += irqchip/fdt_irqchip_aplic.o
> libsbiutils-objs-y += irqchip/fdt_irqchip_imsic.o
> libsbiutils-objs-y += irqchip/fdt_irqchip_plic.o
> libsbiutils-objs-y += irqchip/aplic.o
> --
> 2.25.1
>
Same comment as the FDT based IMSIC driver. Other than that,
Reviewed-by: Atish Patra <atishp@rivosinc.com>
--
Regards,
Atish
^ permalink raw reply [flat|nested] 36+ messages in thread* [PATCH v2 12/13] lib: utils/irqchip: Add FDT based driver for APLIC
2022-02-12 0:56 ` Atish Patra
@ 2022-02-15 14:57 ` Anup Patel
2022-02-15 15:25 ` Anup Patel
1 sibling, 0 replies; 36+ messages in thread
From: Anup Patel @ 2022-02-15 14:57 UTC (permalink / raw)
To: opensbi
On Sat, Feb 12, 2022 at 6:26 AM Atish Patra <atishp@atishpatra.org> wrote:
>
> On Wed, Feb 9, 2022 at 7:06 AM Anup Patel <apatel@ventanamicro.com> wrote:
> >
> > We add simple FDT irqchip driver for APLIC so that generic platform (and
> > other FDT based platforms) can utilize common APLIC initialization library.
> >
> > Signed-off-by: Anup Patel <anup.patel@wdc.com>
> > Signed-off-by: Anup Patel <apatel@ventanamicro.com>
> > ---
> > include/sbi_utils/fdt/fdt_helper.h | 4 +
> > lib/utils/fdt/fdt_helper.c | 159 ++++++++++++++++++++++++++
> > lib/utils/irqchip/fdt_irqchip.c | 2 +
> > lib/utils/irqchip/fdt_irqchip_aplic.c | 56 +++++++++
> > lib/utils/irqchip/objects.mk | 1 +
> > 5 files changed, 222 insertions(+)
> > create mode 100644 lib/utils/irqchip/fdt_irqchip_aplic.c
> >
> > diff --git a/include/sbi_utils/fdt/fdt_helper.h b/include/sbi_utils/fdt/fdt_helper.h
> > index 4c8d29e..1232b26 100644
> > --- a/include/sbi_utils/fdt/fdt_helper.h
> > +++ b/include/sbi_utils/fdt/fdt_helper.h
> > @@ -68,6 +68,10 @@ int fdt_parse_uart8250_node(void *fdt, int nodeoffset,
> > int fdt_parse_uart8250(void *fdt, struct platform_uart_data *uart,
> > const char *compatible);
> >
> > +struct aplic_data;
> > +
> > +int fdt_parse_aplic_node(void *fdt, int nodeoff, struct aplic_data *aplic);
> > +
> > struct imsic_data;
> >
> > bool fdt_check_imsic_mlevel(void *fdt);
> > diff --git a/lib/utils/fdt/fdt_helper.c b/lib/utils/fdt/fdt_helper.c
> > index e179b79..3a306cb 100644
> > --- a/lib/utils/fdt/fdt_helper.c
> > +++ b/lib/utils/fdt/fdt_helper.c
> > @@ -13,6 +13,7 @@
> > #include <sbi/sbi_platform.h>
> > #include <sbi/sbi_scratch.h>
> > #include <sbi_utils/fdt/fdt_helper.h>
> > +#include <sbi_utils/irqchip/aplic.h>
> > #include <sbi_utils/irqchip/imsic.h>
> > #include <sbi_utils/irqchip/plic.h>
> >
> > @@ -466,6 +467,164 @@ int fdt_parse_uart8250(void *fdt, struct platform_uart_data *uart,
> > return fdt_parse_uart8250_node(fdt, nodeoffset, uart);
> > }
> >
> > +int fdt_parse_aplic_node(void *fdt, int nodeoff, struct aplic_data *aplic)
> > +{
> > + bool child_found;
> > + const fdt32_t *val;
> > + const fdt32_t *del;
> > + struct imsic_data imsic;
> > + int i, j, d, dcnt, len, noff, rc;
> > + uint64_t reg_addr, reg_size;
> > + struct aplic_delegate_data *deleg;
> > +
> > + if (nodeoff < 0 || !aplic || !fdt)
> > + return SBI_ENODEV;
> > + memset(aplic, 0, sizeof(*aplic));
> > +
> > + rc = fdt_get_node_addr_size(fdt, nodeoff, 0, ®_addr, ®_size);
> > + if (rc < 0 || !reg_addr || !reg_size)
> > + return SBI_ENODEV;
> > + aplic->addr = reg_addr;
> > + aplic->size = reg_size;
> > +
> > + val = fdt_getprop(fdt, nodeoff, "riscv,num-sources", &len);
> > + if (len > 0)
> > + aplic->num_source = fdt32_to_cpu(*val);
> > +
> > + val = fdt_getprop(fdt, nodeoff, "interrupts-extended", &len);
> > + if (val && len > sizeof(fdt32_t)) {
> > + len = len / sizeof(fdt32_t);
> > + for (i = 0; i < len; i += 2) {
> > + if (fdt32_to_cpu(val[i + 1]) == IRQ_M_EXT) {
> > + aplic->targets_mmode = true;
> > + break;
> > + }
> > + }
> > + aplic->num_idc = len / 2;
> > + goto aplic_msi_parent_done;
> > + }
> > +
> > + val = fdt_getprop(fdt, nodeoff, "msi-parent", &len);
> > + if (val && len >= sizeof(fdt32_t)) {
> > + noff = fdt_node_offset_by_phandle(fdt, fdt32_to_cpu(*val));
> > + if (noff < 0)
> > + return noff;
> > +
> > + rc = fdt_parse_imsic_node(fdt, noff, &imsic);
> > + if (rc)
> > + return rc;
> > +
> > + rc = imsic_data_check(&imsic);
> > + if (rc)
> > + return rc;
> > +
> > + aplic->targets_mmode = imsic.targets_mmode;
> > +
> > + if (imsic.targets_mmode) {
> > + aplic->has_msicfg_mmode = true;
> > + aplic->msicfg_mmode.lhxs = imsic.guest_index_bits;
> > + aplic->msicfg_mmode.lhxw = imsic.hart_index_bits;
> > + aplic->msicfg_mmode.hhxw = imsic.group_index_bits;
> > + aplic->msicfg_mmode.hhxs = imsic.group_index_shift;
> > + if (aplic->msicfg_mmode.hhxs <
> > + (2 * IMSIC_MMIO_PAGE_SHIFT))
> > + return SBI_EINVAL;
> > + aplic->msicfg_mmode.hhxs -= 24;
> > + aplic->msicfg_mmode.base_addr = imsic.regs[0].addr;
> > + } else {
> > + goto aplic_msi_parent_done;
> > + }
> > +
> > + val = fdt_getprop(fdt, nodeoff, "riscv,children", &len);
> > + if (!val || len < sizeof(fdt32_t))
> > + goto aplic_msi_parent_done;
> > +
> > + noff = fdt_node_offset_by_phandle(fdt, fdt32_to_cpu(*val));
> > + if (noff < 0)
> > + return noff;
> > +
> > + val = fdt_getprop(fdt, noff, "msi-parent", &len);
> > + if (!val || len < sizeof(fdt32_t))
> > + goto aplic_msi_parent_done;
> > +
> > + noff = fdt_node_offset_by_phandle(fdt, fdt32_to_cpu(*val));
> > + if (noff < 0)
> > + return noff;
> > +
> > + rc = fdt_parse_imsic_node(fdt, noff, &imsic);
> > + if (rc)
> > + return rc;
> > +
> > + rc = imsic_data_check(&imsic);
> > + if (rc)
> > + return rc;
> > +
> > + if (!imsic.targets_mmode) {
> > + aplic->has_msicfg_smode = true;
> > + aplic->msicfg_smode.lhxs = imsic.guest_index_bits;
> > + aplic->msicfg_smode.lhxw = imsic.hart_index_bits;
> > + aplic->msicfg_smode.hhxw = imsic.group_index_bits;
> > + aplic->msicfg_smode.hhxs = imsic.group_index_shift;
> > + if (aplic->msicfg_smode.hhxs <
> > + (2 * IMSIC_MMIO_PAGE_SHIFT))
> > + return SBI_EINVAL;
> > + aplic->msicfg_smode.hhxs -= 24;
> > + aplic->msicfg_smode.base_addr = imsic.regs[0].addr;
> > + }
> > + }
> > +aplic_msi_parent_done:
> > +
> > + for (d = 0; d < APLIC_MAX_DELEGATE; d++) {
> > + deleg = &aplic->delegate[d];
> > + deleg->first_irq = 0;
> > + deleg->last_irq = 0;
> > + deleg->child_index = 0;
> > + }
> > +
> > + del = fdt_getprop(fdt, nodeoff, "riscv,delegate", &len);
> > + if (!del || len < (3 * sizeof(fdt32_t)))
> > + goto skip_delegate_parse;
> > + d = 0;
> > + dcnt = len / sizeof(fdt32_t);
> > + for (i = 0; i < dcnt; i += 3) {
> > + if (d >= APLIC_MAX_DELEGATE)
> > + break;
> > + deleg = &aplic->delegate[d];
> > +
> > + deleg->first_irq = fdt32_to_cpu(del[i + 1]);
> > + deleg->last_irq = fdt32_to_cpu(del[i + 2]);
> > + deleg->child_index = 0;
> > +
> > + child_found = false;
> > + val = fdt_getprop(fdt, nodeoff, "riscv,children", &len);
> > + if (!val || len < sizeof(fdt32_t)) {
> > + deleg->first_irq = 0;
> > + deleg->last_irq = 0;
> > + deleg->child_index = 0;
> > + continue;
> > + }
> > + len = len / sizeof(fdt32_t);
> > + for (j = 0; j < len; j++) {
> > + if (del[i] != val[j])
> > + continue;
> > + deleg->child_index = j;
> > + child_found = true;
> > + break;
> > + }
> > +
> > + if (child_found) {
> > + d++;
> > + } else {
> > + deleg->first_irq = 0;
> > + deleg->last_irq = 0;
> > + deleg->child_index = 0;
> > + }
> > + }
> > +skip_delegate_parse:
> > +
> > + return 0;
> > +}
> > +
> > bool fdt_check_imsic_mlevel(void *fdt)
> > {
> > const fdt32_t *val;
> > diff --git a/lib/utils/irqchip/fdt_irqchip.c b/lib/utils/irqchip/fdt_irqchip.c
> > index cf64a2e..6007755 100644
> > --- a/lib/utils/irqchip/fdt_irqchip.c
> > +++ b/lib/utils/irqchip/fdt_irqchip.c
> > @@ -12,10 +12,12 @@
> > #include <sbi_utils/fdt/fdt_helper.h>
> > #include <sbi_utils/irqchip/fdt_irqchip.h>
> >
> > +extern struct fdt_irqchip fdt_irqchip_aplic;
> > extern struct fdt_irqchip fdt_irqchip_imsic;
> > extern struct fdt_irqchip fdt_irqchip_plic;
> >
> > static struct fdt_irqchip *irqchip_drivers[] = {
> > + &fdt_irqchip_aplic,
> > &fdt_irqchip_imsic,
> > &fdt_irqchip_plic
> > };
> > diff --git a/lib/utils/irqchip/fdt_irqchip_aplic.c b/lib/utils/irqchip/fdt_irqchip_aplic.c
> > new file mode 100644
> > index 0000000..965f023
> > --- /dev/null
> > +++ b/lib/utils/irqchip/fdt_irqchip_aplic.c
> > @@ -0,0 +1,56 @@
> > +/*
> > + * SPDX-License-Identifier: BSD-2-Clause
> > + *
> > + * Copyright (c) 2021 Western Digital Corporation or its affiliates.
> > + * Copyright (c) 2022 Ventana Micro Systems Inc.
> > + *
> > + * Authors:
> > + * Anup Patel <anup.patel@wdc.com>
> > + */
> > +
> > +#include <libfdt.h>
> > +#include <sbi/riscv_asm.h>
> > +#include <sbi/sbi_error.h>
> > +#include <sbi_utils/fdt/fdt_helper.h>
> > +#include <sbi_utils/irqchip/fdt_irqchip.h>
> > +#include <sbi_utils/irqchip/aplic.h>
> > +
> > +#define APLIC_MAX_NR 16
> > +
> > +static unsigned long aplic_count = 0;
> > +static struct aplic_data aplic[APLIC_MAX_NR];
> > +
> > +static int irqchip_aplic_warm_init(void)
> > +{
> > + /* Nothing to do here. */
> > + return 0;
> > +}
> > +
> > +static int irqchip_aplic_cold_init(void *fdt, int nodeoff,
> > + const struct fdt_match *match)
> > +{
> > + int rc;
> > + struct aplic_data *pd;
> > +
> > + if (APLIC_MAX_NR <= aplic_count)
> > + return SBI_ENOSPC;
> > + pd = &aplic[aplic_count++];
> > +
> > + rc = fdt_parse_aplic_node(fdt, nodeoff, pd);
> > + if (rc)
> > + return rc;
> > +
> > + return aplic_cold_irqchip_init(pd);
> > +}
> > +
> > +static const struct fdt_match irqchip_aplic_match[] = {
> > + { .compatible = "riscv,aplic" },
> > + { },
> > +};
> > +
> > +struct fdt_irqchip fdt_irqchip_aplic = {
> > + .match_table = irqchip_aplic_match,
> > + .cold_init = irqchip_aplic_cold_init,
> > + .warm_init = irqchip_aplic_warm_init,
> > + .exit = NULL,
> > +};
> > diff --git a/lib/utils/irqchip/objects.mk b/lib/utils/irqchip/objects.mk
> > index b2b3f79..fad4344 100644
> > --- a/lib/utils/irqchip/objects.mk
> > +++ b/lib/utils/irqchip/objects.mk
> > @@ -8,6 +8,7 @@
> > #
> >
> > libsbiutils-objs-y += irqchip/fdt_irqchip.o
> > +libsbiutils-objs-y += irqchip/fdt_irqchip_aplic.o
> > libsbiutils-objs-y += irqchip/fdt_irqchip_imsic.o
> > libsbiutils-objs-y += irqchip/fdt_irqchip_plic.o
> > libsbiutils-objs-y += irqchip/aplic.o
> > --
> > 2.25.1
> >
>
> Same comment as the FDT based IMSIC driver. Other than that,
Same response as PATCH9.
>
> Reviewed-by: Atish Patra <atishp@rivosinc.com>
>
>
> --
> Regards,
> Atish
Regards,
Anup
^ permalink raw reply [flat|nested] 36+ messages in thread* [PATCH v2 12/13] lib: utils/irqchip: Add FDT based driver for APLIC
2022-02-12 0:56 ` Atish Patra
2022-02-15 14:57 ` Anup Patel
@ 2022-02-15 15:25 ` Anup Patel
1 sibling, 0 replies; 36+ messages in thread
From: Anup Patel @ 2022-02-15 15:25 UTC (permalink / raw)
To: opensbi
On Sat, Feb 12, 2022 at 6:26 AM Atish Patra <atishp@atishpatra.org> wrote:
>
> On Wed, Feb 9, 2022 at 7:06 AM Anup Patel <apatel@ventanamicro.com> wrote:
> >
> > We add simple FDT irqchip driver for APLIC so that generic platform (and
> > other FDT based platforms) can utilize common APLIC initialization library.
> >
> > Signed-off-by: Anup Patel <anup.patel@wdc.com>
> > Signed-off-by: Anup Patel <apatel@ventanamicro.com>
> > ---
> > include/sbi_utils/fdt/fdt_helper.h | 4 +
> > lib/utils/fdt/fdt_helper.c | 159 ++++++++++++++++++++++++++
> > lib/utils/irqchip/fdt_irqchip.c | 2 +
> > lib/utils/irqchip/fdt_irqchip_aplic.c | 56 +++++++++
> > lib/utils/irqchip/objects.mk | 1 +
> > 5 files changed, 222 insertions(+)
> > create mode 100644 lib/utils/irqchip/fdt_irqchip_aplic.c
> >
> > diff --git a/include/sbi_utils/fdt/fdt_helper.h b/include/sbi_utils/fdt/fdt_helper.h
> > index 4c8d29e..1232b26 100644
> > --- a/include/sbi_utils/fdt/fdt_helper.h
> > +++ b/include/sbi_utils/fdt/fdt_helper.h
> > @@ -68,6 +68,10 @@ int fdt_parse_uart8250_node(void *fdt, int nodeoffset,
> > int fdt_parse_uart8250(void *fdt, struct platform_uart_data *uart,
> > const char *compatible);
> >
> > +struct aplic_data;
> > +
> > +int fdt_parse_aplic_node(void *fdt, int nodeoff, struct aplic_data *aplic);
> > +
> > struct imsic_data;
> >
> > bool fdt_check_imsic_mlevel(void *fdt);
> > diff --git a/lib/utils/fdt/fdt_helper.c b/lib/utils/fdt/fdt_helper.c
> > index e179b79..3a306cb 100644
> > --- a/lib/utils/fdt/fdt_helper.c
> > +++ b/lib/utils/fdt/fdt_helper.c
> > @@ -13,6 +13,7 @@
> > #include <sbi/sbi_platform.h>
> > #include <sbi/sbi_scratch.h>
> > #include <sbi_utils/fdt/fdt_helper.h>
> > +#include <sbi_utils/irqchip/aplic.h>
> > #include <sbi_utils/irqchip/imsic.h>
> > #include <sbi_utils/irqchip/plic.h>
> >
> > @@ -466,6 +467,164 @@ int fdt_parse_uart8250(void *fdt, struct platform_uart_data *uart,
> > return fdt_parse_uart8250_node(fdt, nodeoffset, uart);
> > }
> >
> > +int fdt_parse_aplic_node(void *fdt, int nodeoff, struct aplic_data *aplic)
> > +{
> > + bool child_found;
> > + const fdt32_t *val;
> > + const fdt32_t *del;
> > + struct imsic_data imsic;
> > + int i, j, d, dcnt, len, noff, rc;
> > + uint64_t reg_addr, reg_size;
> > + struct aplic_delegate_data *deleg;
> > +
> > + if (nodeoff < 0 || !aplic || !fdt)
> > + return SBI_ENODEV;
> > + memset(aplic, 0, sizeof(*aplic));
> > +
> > + rc = fdt_get_node_addr_size(fdt, nodeoff, 0, ®_addr, ®_size);
> > + if (rc < 0 || !reg_addr || !reg_size)
> > + return SBI_ENODEV;
> > + aplic->addr = reg_addr;
> > + aplic->size = reg_size;
> > +
> > + val = fdt_getprop(fdt, nodeoff, "riscv,num-sources", &len);
> > + if (len > 0)
> > + aplic->num_source = fdt32_to_cpu(*val);
> > +
> > + val = fdt_getprop(fdt, nodeoff, "interrupts-extended", &len);
> > + if (val && len > sizeof(fdt32_t)) {
> > + len = len / sizeof(fdt32_t);
> > + for (i = 0; i < len; i += 2) {
> > + if (fdt32_to_cpu(val[i + 1]) == IRQ_M_EXT) {
> > + aplic->targets_mmode = true;
> > + break;
> > + }
> > + }
> > + aplic->num_idc = len / 2;
> > + goto aplic_msi_parent_done;
> > + }
> > +
> > + val = fdt_getprop(fdt, nodeoff, "msi-parent", &len);
> > + if (val && len >= sizeof(fdt32_t)) {
> > + noff = fdt_node_offset_by_phandle(fdt, fdt32_to_cpu(*val));
> > + if (noff < 0)
> > + return noff;
> > +
> > + rc = fdt_parse_imsic_node(fdt, noff, &imsic);
> > + if (rc)
> > + return rc;
> > +
> > + rc = imsic_data_check(&imsic);
> > + if (rc)
> > + return rc;
> > +
> > + aplic->targets_mmode = imsic.targets_mmode;
> > +
> > + if (imsic.targets_mmode) {
> > + aplic->has_msicfg_mmode = true;
> > + aplic->msicfg_mmode.lhxs = imsic.guest_index_bits;
> > + aplic->msicfg_mmode.lhxw = imsic.hart_index_bits;
> > + aplic->msicfg_mmode.hhxw = imsic.group_index_bits;
> > + aplic->msicfg_mmode.hhxs = imsic.group_index_shift;
> > + if (aplic->msicfg_mmode.hhxs <
> > + (2 * IMSIC_MMIO_PAGE_SHIFT))
> > + return SBI_EINVAL;
> > + aplic->msicfg_mmode.hhxs -= 24;
> > + aplic->msicfg_mmode.base_addr = imsic.regs[0].addr;
> > + } else {
> > + goto aplic_msi_parent_done;
> > + }
> > +
> > + val = fdt_getprop(fdt, nodeoff, "riscv,children", &len);
> > + if (!val || len < sizeof(fdt32_t))
> > + goto aplic_msi_parent_done;
> > +
> > + noff = fdt_node_offset_by_phandle(fdt, fdt32_to_cpu(*val));
> > + if (noff < 0)
> > + return noff;
> > +
> > + val = fdt_getprop(fdt, noff, "msi-parent", &len);
> > + if (!val || len < sizeof(fdt32_t))
> > + goto aplic_msi_parent_done;
> > +
> > + noff = fdt_node_offset_by_phandle(fdt, fdt32_to_cpu(*val));
> > + if (noff < 0)
> > + return noff;
> > +
> > + rc = fdt_parse_imsic_node(fdt, noff, &imsic);
> > + if (rc)
> > + return rc;
> > +
> > + rc = imsic_data_check(&imsic);
> > + if (rc)
> > + return rc;
> > +
> > + if (!imsic.targets_mmode) {
> > + aplic->has_msicfg_smode = true;
> > + aplic->msicfg_smode.lhxs = imsic.guest_index_bits;
> > + aplic->msicfg_smode.lhxw = imsic.hart_index_bits;
> > + aplic->msicfg_smode.hhxw = imsic.group_index_bits;
> > + aplic->msicfg_smode.hhxs = imsic.group_index_shift;
> > + if (aplic->msicfg_smode.hhxs <
> > + (2 * IMSIC_MMIO_PAGE_SHIFT))
> > + return SBI_EINVAL;
> > + aplic->msicfg_smode.hhxs -= 24;
> > + aplic->msicfg_smode.base_addr = imsic.regs[0].addr;
> > + }
> > + }
> > +aplic_msi_parent_done:
> > +
> > + for (d = 0; d < APLIC_MAX_DELEGATE; d++) {
> > + deleg = &aplic->delegate[d];
> > + deleg->first_irq = 0;
> > + deleg->last_irq = 0;
> > + deleg->child_index = 0;
> > + }
> > +
> > + del = fdt_getprop(fdt, nodeoff, "riscv,delegate", &len);
> > + if (!del || len < (3 * sizeof(fdt32_t)))
> > + goto skip_delegate_parse;
> > + d = 0;
> > + dcnt = len / sizeof(fdt32_t);
> > + for (i = 0; i < dcnt; i += 3) {
> > + if (d >= APLIC_MAX_DELEGATE)
> > + break;
> > + deleg = &aplic->delegate[d];
> > +
> > + deleg->first_irq = fdt32_to_cpu(del[i + 1]);
> > + deleg->last_irq = fdt32_to_cpu(del[i + 2]);
> > + deleg->child_index = 0;
> > +
> > + child_found = false;
> > + val = fdt_getprop(fdt, nodeoff, "riscv,children", &len);
> > + if (!val || len < sizeof(fdt32_t)) {
> > + deleg->first_irq = 0;
> > + deleg->last_irq = 0;
> > + deleg->child_index = 0;
> > + continue;
> > + }
> > + len = len / sizeof(fdt32_t);
> > + for (j = 0; j < len; j++) {
> > + if (del[i] != val[j])
> > + continue;
> > + deleg->child_index = j;
> > + child_found = true;
> > + break;
> > + }
> > +
> > + if (child_found) {
> > + d++;
> > + } else {
> > + deleg->first_irq = 0;
> > + deleg->last_irq = 0;
> > + deleg->child_index = 0;
> > + }
> > + }
> > +skip_delegate_parse:
> > +
> > + return 0;
> > +}
> > +
> > bool fdt_check_imsic_mlevel(void *fdt)
> > {
> > const fdt32_t *val;
> > diff --git a/lib/utils/irqchip/fdt_irqchip.c b/lib/utils/irqchip/fdt_irqchip.c
> > index cf64a2e..6007755 100644
> > --- a/lib/utils/irqchip/fdt_irqchip.c
> > +++ b/lib/utils/irqchip/fdt_irqchip.c
> > @@ -12,10 +12,12 @@
> > #include <sbi_utils/fdt/fdt_helper.h>
> > #include <sbi_utils/irqchip/fdt_irqchip.h>
> >
> > +extern struct fdt_irqchip fdt_irqchip_aplic;
> > extern struct fdt_irqchip fdt_irqchip_imsic;
> > extern struct fdt_irqchip fdt_irqchip_plic;
> >
> > static struct fdt_irqchip *irqchip_drivers[] = {
> > + &fdt_irqchip_aplic,
> > &fdt_irqchip_imsic,
> > &fdt_irqchip_plic
> > };
> > diff --git a/lib/utils/irqchip/fdt_irqchip_aplic.c b/lib/utils/irqchip/fdt_irqchip_aplic.c
> > new file mode 100644
> > index 0000000..965f023
> > --- /dev/null
> > +++ b/lib/utils/irqchip/fdt_irqchip_aplic.c
> > @@ -0,0 +1,56 @@
> > +/*
> > + * SPDX-License-Identifier: BSD-2-Clause
> > + *
> > + * Copyright (c) 2021 Western Digital Corporation or its affiliates.
> > + * Copyright (c) 2022 Ventana Micro Systems Inc.
> > + *
> > + * Authors:
> > + * Anup Patel <anup.patel@wdc.com>
> > + */
> > +
> > +#include <libfdt.h>
> > +#include <sbi/riscv_asm.h>
> > +#include <sbi/sbi_error.h>
> > +#include <sbi_utils/fdt/fdt_helper.h>
> > +#include <sbi_utils/irqchip/fdt_irqchip.h>
> > +#include <sbi_utils/irqchip/aplic.h>
> > +
> > +#define APLIC_MAX_NR 16
> > +
> > +static unsigned long aplic_count = 0;
> > +static struct aplic_data aplic[APLIC_MAX_NR];
> > +
> > +static int irqchip_aplic_warm_init(void)
> > +{
> > + /* Nothing to do here. */
> > + return 0;
> > +}
> > +
> > +static int irqchip_aplic_cold_init(void *fdt, int nodeoff,
> > + const struct fdt_match *match)
> > +{
> > + int rc;
> > + struct aplic_data *pd;
> > +
> > + if (APLIC_MAX_NR <= aplic_count)
> > + return SBI_ENOSPC;
> > + pd = &aplic[aplic_count++];
> > +
> > + rc = fdt_parse_aplic_node(fdt, nodeoff, pd);
> > + if (rc)
> > + return rc;
> > +
> > + return aplic_cold_irqchip_init(pd);
> > +}
> > +
> > +static const struct fdt_match irqchip_aplic_match[] = {
> > + { .compatible = "riscv,aplic" },
> > + { },
> > +};
> > +
> > +struct fdt_irqchip fdt_irqchip_aplic = {
> > + .match_table = irqchip_aplic_match,
> > + .cold_init = irqchip_aplic_cold_init,
> > + .warm_init = irqchip_aplic_warm_init,
> > + .exit = NULL,
> > +};
> > diff --git a/lib/utils/irqchip/objects.mk b/lib/utils/irqchip/objects.mk
> > index b2b3f79..fad4344 100644
> > --- a/lib/utils/irqchip/objects.mk
> > +++ b/lib/utils/irqchip/objects.mk
> > @@ -8,6 +8,7 @@
> > #
> >
> > libsbiutils-objs-y += irqchip/fdt_irqchip.o
> > +libsbiutils-objs-y += irqchip/fdt_irqchip_aplic.o
> > libsbiutils-objs-y += irqchip/fdt_irqchip_imsic.o
> > libsbiutils-objs-y += irqchip/fdt_irqchip_plic.o
> > libsbiutils-objs-y += irqchip/aplic.o
> > --
> > 2.25.1
> >
>
> Same comment as the FDT based IMSIC driver. Other than that,
>
> Reviewed-by: Atish Patra <atishp@rivosinc.com>
Applied this patch to the riscv/opensbi repo.
Regards,
Anup
>
>
> --
> Regards,
> Atish
^ permalink raw reply [flat|nested] 36+ messages in thread
* [PATCH v2 13/13] lib: utils: Disable appropriate APLIC DT nodes in fdt_fixups()
2022-02-09 15:04 [PATCH v2 00/13] OpenSBI RISC-V AIA Support Anup Patel
` (11 preceding siblings ...)
2022-02-09 15:04 ` [PATCH v2 12/13] lib: utils/irqchip: Add FDT based driver for APLIC Anup Patel
@ 2022-02-09 15:04 ` Anup Patel
2022-02-15 15:25 ` Anup Patel
12 siblings, 1 reply; 36+ messages in thread
From: Anup Patel @ 2022-02-09 15:04 UTC (permalink / raw)
To: opensbi
We should disable APLIC DT nodes in fdt_fixups() which are not
accessible to the next booting stage based on currently assigned
domain.
Signed-off-by: Anup Patel <anup.patel@wdc.com>
Signed-off-by: Anup Patel <apatel@ventanamicro.com>
Reviewed-by: Atish Patra <atishp@rivosinc.com>
---
include/sbi_utils/fdt/fdt_fixup.h | 18 +++++++++++++++---
lib/utils/fdt/fdt_fixup.c | 11 +++++++++++
2 files changed, 26 insertions(+), 3 deletions(-)
diff --git a/include/sbi_utils/fdt/fdt_fixup.h b/include/sbi_utils/fdt/fdt_fixup.h
index 77575bb..fb076ba 100644
--- a/include/sbi_utils/fdt/fdt_fixup.h
+++ b/include/sbi_utils/fdt/fdt_fixup.h
@@ -21,6 +21,18 @@
*/
void fdt_cpu_fixup(void *fdt);
+/**
+ * Fix up the APLIC nodes in the device tree
+ *
+ * This routine disables APLIC nodes which are not accessible to the next
+ * booting stage based on currently assigned domain.
+ *
+ * It is recommended that platform codes call this helper in their final_init()
+ *
+ * @param fdt: device tree blob
+ */
+void fdt_aplic_fixup(void *fdt);
+
/**
* Fix up the IMSIC nodes in the device tree
*
@@ -76,9 +88,9 @@ int fdt_reserved_memory_nomap_fixup(void *fdt);
* General device tree fix-up
*
* This routine do all required device tree fix-ups for a typical platform.
- * It fixes up the PLIC node, IMSIC nodes, and the reserved memory node in
- * the device tree by calling the corresponding helper routines to accomplish
- * the task.
+ * It fixes up the PLIC node, IMSIC nodes, APLIC nodes, and the reserved
+ * memory node in the device tree by calling the corresponding helper
+ * routines to accomplish the task.
*
* It is recommended that platform codes call this helper in their final_init()
*
diff --git a/lib/utils/fdt/fdt_fixup.c b/lib/utils/fdt/fdt_fixup.c
index c2460b8..a80bd82 100644
--- a/lib/utils/fdt/fdt_fixup.c
+++ b/lib/utils/fdt/fdt_fixup.c
@@ -71,6 +71,15 @@ static void fdt_domain_based_fixup_one(void *fdt, int nodeoff)
}
}
+void fdt_aplic_fixup(void *fdt)
+{
+ int noff = 0;
+
+ while ((noff = fdt_node_offset_by_compatible(fdt, noff,
+ "riscv,aplic")) >= 0)
+ fdt_domain_based_fixup_one(fdt, noff);
+}
+
void fdt_imsic_fixup(void *fdt)
{
int noff = 0;
@@ -289,6 +298,8 @@ int fdt_reserved_memory_nomap_fixup(void *fdt)
void fdt_fixups(void *fdt)
{
+ fdt_aplic_fixup(fdt);
+
fdt_imsic_fixup(fdt);
fdt_plic_fixup(fdt);
--
2.25.1
^ permalink raw reply related [flat|nested] 36+ messages in thread* [PATCH v2 13/13] lib: utils: Disable appropriate APLIC DT nodes in fdt_fixups()
2022-02-09 15:04 ` [PATCH v2 13/13] lib: utils: Disable appropriate APLIC DT nodes in fdt_fixups() Anup Patel
@ 2022-02-15 15:25 ` Anup Patel
0 siblings, 0 replies; 36+ messages in thread
From: Anup Patel @ 2022-02-15 15:25 UTC (permalink / raw)
To: opensbi
On Wed, Feb 9, 2022 at 8:36 PM Anup Patel <apatel@ventanamicro.com> wrote:
>
> We should disable APLIC DT nodes in fdt_fixups() which are not
> accessible to the next booting stage based on currently assigned
> domain.
>
> Signed-off-by: Anup Patel <anup.patel@wdc.com>
> Signed-off-by: Anup Patel <apatel@ventanamicro.com>
> Reviewed-by: Atish Patra <atishp@rivosinc.com>
Applied this patch to the riscv/opensbi repo.
Regards,
Anup
> ---
> include/sbi_utils/fdt/fdt_fixup.h | 18 +++++++++++++++---
> lib/utils/fdt/fdt_fixup.c | 11 +++++++++++
> 2 files changed, 26 insertions(+), 3 deletions(-)
>
> diff --git a/include/sbi_utils/fdt/fdt_fixup.h b/include/sbi_utils/fdt/fdt_fixup.h
> index 77575bb..fb076ba 100644
> --- a/include/sbi_utils/fdt/fdt_fixup.h
> +++ b/include/sbi_utils/fdt/fdt_fixup.h
> @@ -21,6 +21,18 @@
> */
> void fdt_cpu_fixup(void *fdt);
>
> +/**
> + * Fix up the APLIC nodes in the device tree
> + *
> + * This routine disables APLIC nodes which are not accessible to the next
> + * booting stage based on currently assigned domain.
> + *
> + * It is recommended that platform codes call this helper in their final_init()
> + *
> + * @param fdt: device tree blob
> + */
> +void fdt_aplic_fixup(void *fdt);
> +
> /**
> * Fix up the IMSIC nodes in the device tree
> *
> @@ -76,9 +88,9 @@ int fdt_reserved_memory_nomap_fixup(void *fdt);
> * General device tree fix-up
> *
> * This routine do all required device tree fix-ups for a typical platform.
> - * It fixes up the PLIC node, IMSIC nodes, and the reserved memory node in
> - * the device tree by calling the corresponding helper routines to accomplish
> - * the task.
> + * It fixes up the PLIC node, IMSIC nodes, APLIC nodes, and the reserved
> + * memory node in the device tree by calling the corresponding helper
> + * routines to accomplish the task.
> *
> * It is recommended that platform codes call this helper in their final_init()
> *
> diff --git a/lib/utils/fdt/fdt_fixup.c b/lib/utils/fdt/fdt_fixup.c
> index c2460b8..a80bd82 100644
> --- a/lib/utils/fdt/fdt_fixup.c
> +++ b/lib/utils/fdt/fdt_fixup.c
> @@ -71,6 +71,15 @@ static void fdt_domain_based_fixup_one(void *fdt, int nodeoff)
> }
> }
>
> +void fdt_aplic_fixup(void *fdt)
> +{
> + int noff = 0;
> +
> + while ((noff = fdt_node_offset_by_compatible(fdt, noff,
> + "riscv,aplic")) >= 0)
> + fdt_domain_based_fixup_one(fdt, noff);
> +}
> +
> void fdt_imsic_fixup(void *fdt)
> {
> int noff = 0;
> @@ -289,6 +298,8 @@ int fdt_reserved_memory_nomap_fixup(void *fdt)
>
> void fdt_fixups(void *fdt)
> {
> + fdt_aplic_fixup(fdt);
> +
> fdt_imsic_fixup(fdt);
>
> fdt_plic_fixup(fdt);
> --
> 2.25.1
>
^ permalink raw reply [flat|nested] 36+ messages in thread