[PATCH v2 11/13] lib: utils/irqchip: Add APLIC initialization library
Anup Patel
anup at brainfault.org
Tue Feb 15 07:24:39 PST 2022
On Sat, Feb 12, 2022 at 6:02 AM Atish Patra <atishp at atishpatra.org> wrote:
>
> On Wed, Feb 9, 2022 at 7:05 AM Anup Patel <apatel at 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 at wdc.com>
> > Signed-off-by: Anup Patel <apatel at 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 at 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 at 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 at rivosinc.com>
Applied this patch to the riscv/opensbi repo.
Regards,
Anup
>
> --
> Regards,
> Atish
More information about the opensbi
mailing list