[PATCH v2 11/13] lib: utils/irqchip: Add APLIC initialization library

Atish Patra atishp at atishpatra.org
Fri Feb 11 16:32:19 PST 2022


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, &reg);
> +               rc = sbi_domain_root_add_memregion(&reg);
> +               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>

--
Regards,
Atish



More information about the opensbi mailing list