[PATCH v2 07/16] LoongArch: lib: General routines
Simon Glass
sjg at chromium.org
Thu Jul 2 12:28:08 CEST 2026
Hi Yao,
On 2026-07-01T11:17:53, Yao Zi <me at ziyao.cc> wrote:
> LoongArch: lib: General routines
>
> Add some common library routines for the architecture.
>
> Signed-off-by: Jiaxun Yang <jiaxun.yang at flygoat.com>
> Signed-off-by: Yao Zi <me at ziyao.cc>
>
> arch/loongarch/include/asm/cache.h | 10 ++
> arch/loongarch/include/asm/global_data.h | 7 +
> arch/loongarch/lib/Makefile | 7 +
> arch/loongarch/lib/asm-offsets.c | 66 ++++++++++
> arch/loongarch/lib/boot.c | 14 ++
> arch/loongarch/lib/cache.c | 213 +++++++++++++++++++++++++++++++
> arch/loongarch/lib/reset.c | 14 ++
> arch/loongarch/lib/setjmp.S | 52 ++++++++
> 8 files changed, 383 insertions(+)
> Add some common library routines for the architecture.
Please expand the commit message: list what the routines are
(cache maintenance, setjmp/longjmp, asm-offsets, do_go_exec,
do_reset) and note that cache handling probes the hierarchy via
CPUCFG.
> diff --git a/arch/loongarch/lib/cache.c b/arch/loongarch/lib/cache.c
> @@ -0,0 +1,213 @@
> +static inline void flush_cache_line_index(unsigned int index,
> + unsigned long addr)
> +{
> +#define do_flush(index) \
> + case index: \
> + cache_op(FIELD_PREP(CACHE_OP, CACHE_INDEX_INVWB) | \
> + FIELD_PREP(CACHE_INDEX, index), \
> + index); \
> + break;
> +
> + switch (index) {
> + do_flush(0);
> + do_flush(1);
> + do_flush(2);
> + do_flush(3);
> + do_flush(4);
> + do_flush(5);
> + }
> +
> +#undef do_flush
> +}
addr is silently dropped. Inside do_flush() the token index
resolves to the macro parameter (0..5, the cache identifier), so
cache_op() always gets the small constant as its address operand.
The way/set offset that flush_dcache_level_all() computes never
reaches the CACOP instruction, so this hammers way 0 / set 0 of
the selected cache repeatedly instead of walking it. Please pass
addr through (rename the macro parameter to avoid the shadow), and
confirm with a real by-index flush test.
> diff --git a/arch/loongarch/lib/cache.c b/arch/loongarch/lib/cache.c
> @@ -0,0 +1,213 @@
> +void probe_caches(void)
> +{
> + unsigned int level = 0, index = 0;
> + u32 cfg = read_cpucfg(LOONGARCH_CPUCFG16);
> +
> + if (cfg & CPUCFG16_L1_IUPRE) {
> + if (cfg & CPUCFG16_L1_IUUNIFY) {
> + gd->arch.dcache_index[level] = index;
> + populate_dcache_properties(cfg, level++,
> + LOONGARCH_CPUCFG17);
> + }
> +
> + index++;
> + }
> +
> + if (cfg & CPUCFG16_L1_DPRE) {
> + gd->arch.dcache_index[level] = index++;
> + populate_dcache_properties(cfg, level++, LOONGARCH_CPUCFG18);
> + }
> +
> + cfg >>= 3;
> +
> + for (; level < 3; level++) {
Please use CACHE_MAX_LEVEL rather than the bare 3.
populate_dcache_properties() also sets dcache_inclusive from cfg
whenever level != 0, but on the L1D path cfg is still CPUCFG16 -
the L1 inclusive bit describes L1I vs L1D, not L1D vs L2, so this
looks incorrect. Please double-check.
> diff --git a/arch/loongarch/include/asm/cache.h b/arch/loongarch/include/asm/cache.h
> @@ -15,6 +18,13 @@ void cache_flush(void);
> +#define CACHE_MAX_LEVEL 3
> +#define CACHE_MAX_INDEX 6
A short comment on what these two bounds represent (max dcache
levels tracked vs. max hardware cache-id encoded in CACOP) would
help - they are easy to confuse.
> diff --git a/arch/loongarch/lib/setjmp.S b/arch/loongarch/lib/setjmp.S
> @@ -0,0 +1,52 @@
> +ENTRY(setjmp)
> + LONG_S s0, a0, 0
> + LONG_S s1, a0, (1 * LONGSIZE)
Stray space after LONG_S here (and in longjmp). Please clean up.
Regards,
Simon
More information about the U-Boot
mailing list