Add parent_unique_id fields to struct aplic_data for
IMSIC parent linking in MSI mode. Store parent IMSIC unique_id
during FDT parsing of the APLIC node.
Add aplic_is_msi_mode() complementing aplic_is_direct_mode() to
consolidate delivery mode detection. Add APLIC_TARGET_EIID() macro
for packing the EIID field into the TARGET register.
Add parent_unique_id and parent_irq_map fields to struct aplic_data.
parent_unique_id identifies the upstream IMSIC irqchip device resolved
via sbi_irqchip_find_device() during hwirq_setup. parent_irq_map is
a per-source array allocated at cold init time to track the EIID
assigned by the IMSIC for each APLIC source.
Restore aplic_writel_msicfg() and re-introduce MSI address register
programming in aplic_init(), gated on aplic_is_msi_mode(). Set the
DOMAINCFG_DM bit to switch the hardware to MSI delivery mode when
no IDC structures are present.
Add aplic_program_msi_target() to pack hart_index, guest_index, and
EIID into the APLIC_TARGET register. Add aplic_write_msi() as the
sbi_irqchip write_msi callback that extracts EIID and hart_index from
the MSI message and calls aplic_program_msi_target(). Add
aplic_msi_callback() as the MSI receive callback that dispatches to
sbi_irqchip_process_hwirq() on the APLIC chip.
Extend aplic_hwirq_setup() with an MSI path that resolves the parent
IMSIC chip by parent_unique_id, registers an MSI route via
sbi_irqchip_register_msi(), and stores the allocated EIID in
parent_irq_map for the source being configured.
Extend aplic_hwirq_set_affinity() with an MSI path that delegates
affinity reprogramming to the parent IMSIC chip via
sbi_irqchip_set_affinity() using the stored parent_irq_map entry.
Guard warm_init, process_hwirqs, and hwirq_eoi with early returns in
MSI mode as interrupt delivery and acknowledgement are handled by the
IMSIC in that configuration.
Signed-off-by: Oza Pawandeep <pawandeep.oza@oss.qualcomm.com>
Reviewed-by: Anup Patel <anup@brainfault.org>
Link: https://lore.kernel.org/r/20260721214833.687361-3-pawandeep.oza@oss.qualcomm.com
Signed-off-by: Anup Patel <anup@brainfault.org>
When called with first == NULL, sbi_irqchip_find_device_by_caps() should
scan the device list from the start. Instead it always returns NULL: "found"
starts false and only flips true when an entry equals "first", but no entry
ever equals NULL, so every entry hits "else continue" and nothing is checked.
This breaks MSI detection in sbi_mpxy, which calls it with first == NULL:
ms->msi_avail = !!sbi_irqchip_find_device_by_caps(SBI_IRQCHIP_CAPS_MSI, NULL);
msi_avail is therefore always false, so mpxy_write_std_attr() silently drops
the MSI attributes (MSI_ADDR_LO/HI, MSI_DATA, MSI_CONTROL) while still
returning success, and MSI-based MPXY notifications are never delivered.
Initialize "found" from "first" so a NULL "first" scans from the beginning,
and always continue in the pre-match branch so a non-NULL "first" resumes
after the given device.
Fixes: 8570b93844 ("lib: sbi_irqchip: Allow irqchip drivers advertise capabilities")
Signed-off-by: David E. Garcia Porras <david.garcia@aheadcomputing.com>
Reviewed-by: Anup Patel <anup@brainfault.org>
Link: https://lore.kernel.org/r/20260701181334.969877-1-david.garcia@aheadcomputing.com
Signed-off-by: Anup Patel <anup@brainfault.org>
It is possible to have platform where an irqchip device targets
a subset of harts and there are multiple irqchip devices to cover
all harts.
To support this scenario:
1) Add target_harts hartmask to struct sbi_irqchip_device which
represents the set of harts targetted by the irqchip device
2) Call warm_init() and process_hwirqs() callbacks of an irqchip
device on a hart only if irqchip device targets that particular
hart
Signed-off-by: Anup Patel <anup.patel@oss.qualcomm.com>
Link: https://lore.kernel.org/r/20260213055342.3124872-6-anup.patel@oss.qualcomm.com
Signed-off-by: Anup Patel <anup@brainfault.org>
In addition to saving some code size, this moves the decision about
setting the top-level external interrupt handler to the irqchip core,
not the specific driver, which would be needed to support chained
interrupt handlers.
Signed-off-by: Samuel Holland <samuel.holland@sifive.com>
Reviewed-by: Anup Patel <anup@brainfault.org>
Now that driver lifecycle is managed from within the SBI irqchip core,
platforms need only to initialize the driver once during cold init.
Remove the remaining platform hooks that are no longer used.
Signed-off-by: Samuel Holland <samuel.holland@sifive.com>
Reviewed-by: Anup Patel <anup@brainfault.org>
Currently, each platform keeps track of which irqchip driver is in use
and calls its warm init function. Since the generic platform may use
multiple irqchip drivers, it has logic to track an array of drivers.
The code is simplified and made common across platforms by treating warm
init and exit as properties of the driver, not the platform. Then the
platform's only role is to select and prepare a driver during cold boot.
For now, only add a .warm_init hook, since none of the existing drivers
need an .exit hook. It could be added in the future if needed.
Signed-off-by: Samuel Holland <samuel.holland@sifive.com>
Reviewed-by: Anup Patel <anup@brainfault.org>
Have the SBI irqchip core keep track of registered irqchip devices. This
is useful for any callbacks the irqchip driver may have, such as for
warm initialization, the external interrupt handler function, and any
future support for handling external interrupts (beyond IPIs) in M-mode.
This improves on the tracking done in fdt_irqchip.c, as it tracks device
instances, not just drivers, so callbacks can target a specific device.
Signed-off-by: Samuel Holland <samuel.holland@sifive.com>
Reviewed-by: Anup Patel <anup@brainfault.org>
Currently, the external interrupt handling is scattered between
sbi_init and sbi_trap. This patch moves all external interrupt
handling into a simple framework called sbi_irqchip.
Signed-off-by: Anup Patel <apatel@ventanamicro.com>
Reviewed-by: Xiang W <wxjstz@126.com>
Reviewed-by: Atish Patra <atishp@rivosinc.com>