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>
UBSan detected undefined behavior in sbi_hart.c and sbi_fwft.c (in
the case of sbi_fwft.c, the bug comes from a macro call defined at
sbi_ecall_interface.h) caused by shifting a signed integer into the
sign bit (1 << 31)
This can be fixed by using the 1UL literal, ensuring defined arithmetic.
Please let me know if there’s any other most suitable solution for
this bug.
Signed-off-by: Marcos Oduardo <marcos.oduardo@gmail.com>
Reviewed-by: Anup Patel <anup@brainfault.org>
Link: https://lore.kernel.org/r/20260223001202.284612-1-marcos.oduardo@gmail.com
Signed-off-by: Anup Patel <anup@brainfault.org>
In sbi_domain.h, when checking if a memory region is a subset of
another, an undefined behavior arithmetic operation was caught
when sanitizing with UBSan (shift exponent __riscv_xlen).
This patch adds a check to handle the case where the region order
is __riscv_xlen, avoiding the illegal shift and ensuring the operation
remains defined.
Please let me know if there’s any other most suitable solution for
this bug.
Signed-off-by: Marcos Oduardo <marcos.oduardo@gmail.com>
Reviewed-by: Anup Patel <anup@brainfault.org>
Link: https://lore.kernel.org/r/20260222235219.276432-1-marcos.oduardo@gmail.com
Signed-off-by: Anup Patel <anup@brainfault.org>
SBI code arranges domain PMP regions in a way that last entry is
all-inclusive "0..~0 RWX" and the rest of entries are not programmed.
This causes a problem for the eyeq7h.
CPU can issue speculative prefetches to non-existent addresses. If this
access goes to the system NOC, it is mis-interpreted as an access
violation and error is reported, forcing system reset.
To prevent such a speculative transaction to leave a CPU cluster,
block it using PMP, by restricting memory region to physically present
memory. To achieve this, on early init:
- update flags for the last all-inclusive "0..~0 RWX" entry to be
inaccessible MMIO. MMIO serves to set up PMA attributes to uncached
non-prefetchable, preventing transactions to reach system NOC
- add an all-permissive entry matching DRAM.
Resulting memory regions:
Domain0 Region00 : 0x0000000800100000-0x000000080013ffff M: (F,R,X) S/U: ()
Domain0 Region01 : 0x0000000800100000-0x00000008001fffff M: (F,R,W) S/U: ()
Domain0 Region02 : 0x0000000048700000-0x000000004870ffff M: (I,R,W) S/U: ()
Domain0 Region03 : 0x0000000067480000-0x000000006748ffff M: (I,R,W) S/U: ()
Domain0 Region04 : 0x0000000067500000-0x000000006750ffff M: (I,R,W) S/U: ()
Domain0 Region05 : 0x0000000048740000-0x000000004875ffff M: (I,R,W) S/U: ()
Domain0 Region06 : 0x00000000674c0000-0x00000000674dffff M: (I,R,W) S/U: ()
Domain0 Region07 : 0x0000000067540000-0x000000006755ffff M: (I,R,W) S/U: ()
Domain0 Region08 : 0x0000000000000000-0x000000007fffffff M: (I,R,W) S/U: (R,W)
Domain0 Region09 : 0x0000000800000000-0x00000008ffffffff M: () S/U: (R,W,X)
Domain0 Region10 : 0x0000001000000000-0x0000001fffffffff M: (I) S/U: (R,W)
Domain0 Region11 : 0x0000000000000000-0xffffffffffffffff M: (I) S/U: ()
Here Region09 covers DRAM, region 11 set to non-accessible
uncached no-prefetch for the entire address range
Signed-off-by: Vladimir Kondratiev <vladimir.kondratiev@mobileye.com>
Reviewed-by: Anup Patel <anup@brainfault.org>
Link: https://lore.kernel.org/r/20260223-for-upstream-eyeq7h-v3-21-621d004d1a21@mobileye.com
Signed-off-by: Anup Patel <anup@brainfault.org>
CPU clusters 1 and 2 cannot access NCORE registers through AUX ports.
AUX ports of clusters 1 and 2 are connected to NCORE through east port.
East port has no access to NCORE registers address space.
Re-route NCORE registers range to MEM port by re-configuring MMIO
regions in the GCR. REsulting map is as below. Mind a gap between
regions [1] and [2]; this gap covering NCORE registers now routed
to the default MEM port
Cluster 0: 4 MMIO regions
[0] : 0x0000000000000000-0x000000001fff0000 AUX0 UC|UCA
[1] : 0x0000000020000000-0x00000000677f0000 AUX0 ANY
[2] : 0x0000000080000000-0x0000001fffff0000 AUX0 UC|UCA
[3] : --disabled--
Cluster 1: 4 MMIO regions
[0] : 0x0000000000000000-0x000000001fff0000 AUX0 UC|UCA
[1] : 0x0000000020000000-0x00000000677f0000 AUX0 ANY
[2] : 0x0000000080000000-0x0000001fffff0000 AUX0 UC|UCA
[3] : --disabled--
Cluster 2: 4 MMIO regions
[0] : 0x0000000000000000-0x000000001fff0000 AUX0 UC|UCA
[1] : 0x0000000020000000-0x00000000677f0000 AUX0 ANY
[2] : 0x0000000080000000-0x0000001fffff0000 AUX0 UC|UCA
[3] : --disabled--
Signed-off-by: Vladimir Kondratiev <vladimir.kondratiev@mobileye.com>
Reviewed-by: Anup Patel <anup@brainfault.org>
Link: https://lore.kernel.org/r/20260223-for-upstream-eyeq7h-v3-19-621d004d1a21@mobileye.com
Signed-off-by: Anup Patel <anup@brainfault.org>
Modify the coherence manager register accessors to use the global variable
p8700_cm_info instead of the statically declared GLOBAL_CM_BASE array.
Also use p8700_cm_info to get the number of coherence managers and their
base addresses in mips_p8700_early_init() and mips_p8700_nascent_init().
Clean up the hard-coded values in mips/board.h, access to the coherence
manager is now fully based on information provided by platform compatible
from the device tree.
Signed-off-by: Benoît Monin <benoit.monin@bootlin.com>
Signed-off-by: Vladimir Kondratiev <vladimir.kondratiev@mobileye.com>
Reviewed-by: Anup Patel <anup@brainfault.org>
Link: https://lore.kernel.org/r/20260223-for-upstream-eyeq7h-v3-9-621d004d1a21@mobileye.com
Signed-off-by: Anup Patel <anup@brainfault.org>
Introduce a structure p8700_cm_info holding the number of coherence
managers and their base addresses found in a particular SoC.
Declare a global pointer to the structure that is set in
mips_p8700_platform_init(), based on the match data of the platform
compatible.
For the match data of the MIPS P8700, a single coherence manager with
a base address of 0x16100000 is declared, identical to what is found
in mips/board.h.
For now, access to the coherence manager register is still based on
the hard-coded values defined in mips/board.h.
Signed-off-by: Benoît Monin <benoit.monin@bootlin.com>
Signed-off-by: Vladimir Kondratiev <vladimir.kondratiev@mobileye.com>
Reviewed-by: Anup Patel <anup@brainfault.org>
Link: https://lore.kernel.org/r/20260223-for-upstream-eyeq7h-v3-8-621d004d1a21@mobileye.com
Signed-off-by: Anup Patel <anup@brainfault.org>
In the multi-cluster system each cluster has its own CM (Coherency Manager).
Every CM has its "global" memory address where it is accessible from
any bus master.
Initially, all CMs accessible from the local cluster using same "local"
address. Transactions by local address are not routed through system bus
and thus are faster.
Remap CM in every cluster to the local address matching its global address.
Then, every CM is always accessed using same address, but when transaction
initiated from the local cluster it is routed internally.
This removes need for 2 PMP regions covering local address access.
CM accessor functions simplified because there's no need to detect whether
transaction is local or global
Access timer always in cluster 0
Signed-off-by: Vladimir Kondratiev <vladimir.kondratiev@mobileye.com>
Reviewed-by: Anup Patel <anup@brainfault.org>
Link: https://lore.kernel.org/r/20260223-for-upstream-eyeq7h-v3-7-621d004d1a21@mobileye.com
Signed-off-by: Anup Patel <anup@brainfault.org>
Currently, when we attempt to read the upper 32 bits of a firmware
counter on RV64 or higher, we just set `sbiret.value` to 0 without
validating the counter index. The SBI specification requires us to set
`sbiret.error` to `SBI_ERR_INVALID_PARAM` if the counter index points to
a hardware counter or an invalid counter. Add a validation check to
ensure compliance with the specification on RV64 or higher.
Fixes: 51951d9e9a ("lib: sbi_pmu: Implement sbi_pmu_counter_fw_read_hi")
Signed-off-by: James Raphael Tiovalen <jamestiotio@gmail.com>
Reviewed-by: Anup Patel <anup@brainfault.org>
Link: https://lore.kernel.org/r/20260125090643.190748-1-jamestiotio@gmail.com
Signed-off-by: Anup Patel <anup@brainfault.org>
Currently, we immediately return the result of `fw_counter_start` if the
event code is 0xFFFF. However, this skips setting the bit in the
`fw_counters_started` bitmap even if the platform-specific call
succeeds. Restore the original behavior of returning early only on an
error so that we still set the bit in the bitmap. This prevents multiple
starts of the same FW counter. This also aligns the expectations of
`pmu_ctr_start_fw` with `pmu_ctr_stop_fw` since we cannot assume that
the platform-specific functions to start and stop FW counters will
modify the bitmap state.
Fixes: 57d3aa3b0d ("lib: sbi_pmu: Introduce fw_counter_write_value API")
Signed-off-by: James Raphael Tiovalen <jamestiotio@gmail.com>
Reviewed-by: Anup Patel <anup@brainfault.org>
Link: https://lore.kernel.org/r/20260116165304.180441-1-jamestiotio@gmail.com
Signed-off-by: Anup Patel <anup@brainfault.org>
Implement a system-wide suspend driver for the Andes AE350 platform.
This driver supports Andes-specific deep sleep (suspend to RAM) and
light sleep (suspend to standby) functionalities via the ATCSMU.
The major differences between deep sleep and light sleep are:
- Power Domain and Resume Path: Deep sleep powers down the core domain.
Consequently, harts waking from deep sleep resume from the reset
vector. Light sleep utilizes clock gating to the core domain; harts
maintain state and resume execution at the instruction immediately
following the WFI instruction.
- Primary Hart Wakeup: In both modes, the primary hart is woken by
UART or RTC alarm interrupts. In deep sleep, the primary hart is
additionally responsible for re-enabling the Last Level Cache (LLC)
and restoring Andes-specific CSRs.
- Secondary Hart Wakeup: In light sleep, secondary harts are woken
by an IPI sent from the primary hart. In deep sleep, they are
woken by an ATCSMU hardware wake-up command. Furthermore,
secondary harts must restore Andes-specific CSRs when returning
from deep sleep.
Signed-off-by: Ben Zong-You Xie <ben717@andestech.com>
Signed-off-by: Leo Yu-Chi Liang <ycliang@andestech.com>
Link: https://lore.kernel.org/r/20251229071914.1451587-6-ben717@andestech.com
Signed-off-by: Anup Patel <anup@brainfault.org>
Refactor ATCSMU (System Management Unit) support by moving it from a
system utility into a dedicated FDT-based HSM driver.
Key changes include:
- Moving the functions in lib/utils/sys/atcsmu.c into the new HSM driver
- Moving hart start and stop operations on AE350 platform into the new
HSM driver
- Converting the assembly-based functions in sleep.S to C code for the
readability
- Updating the ATCWDT200 driver
Signed-off-by: Ben Zong-You Xie <ben717@andestech.com>
Signed-off-by: Leo Yu-Chi Liang <ycliang@andestech.com>
Link: https://lore.kernel.org/r/20251229071914.1451587-2-ben717@andestech.com
Signed-off-by: Anup Patel <anup@brainfault.org>
The "RISC-V C API" [1] defines architecture extension test macros
says naming rule for the test macros is __riscv_<ext_name>, where
<ext_name> is all lower-case.
Three extensions dealing with atomics implementation are:
"zaamo" consists of AMO instructions,
"zalrsc" - LR/SC,
"a" extension means both "zaamo" and "zalrsc"
Built-in test macros are __riscv_a, __riscv_zaamo and __riscv_zalrsc.
Alternative to the __riscv_a macro name, __riscv_atomic, is deprecated.
Use correct test macro __riscv_zaamo for the AMO variant of atomics.
It used to be __riscv_atomic that is both deprecated and incorrect
because it tests for the "a" extension; i.e. both "zaamo" and "zalrsc"
If ISA enables only zaamo but not zalrsc, code as it was would not compile.
Older toolchains may have neither __riscv_zaamo nor __riscv_zalrsc, so
query __riscv_atomic - it should be treated as both __riscv_zaamo and
__riscv_zalrsc, in all present cases __riscv_zaamo is more favorable
so take is as alternative for __riscv_zaamo
[1] https://github.com/riscv-non-isa/riscv-c-api-doc
Signed-off-by: Vladimir Kondratiev <vladimir.kondratiev@mobileye.com>
Reviewed-by: Anup Patel <anup@brainfault.org>
Link: https://lore.kernel.org/r/20251228073321.1533844-1-vladimir.kondratiev@mobileye.com
Signed-off-by: Anup Patel <anup@brainfault.org>