start.S for initialisation, smp_secondary routine for a spin-table like interface for secondary cpus.
Signed-off-by: Jiaxun Yang <jiaxun.y...@flygoat.com> --- arch/loongarch/cpu/Makefile | 4 + arch/loongarch/cpu/cpu.c | 28 ++++++ arch/loongarch/cpu/smp_secondary.S | 55 ++++++++++++ arch/loongarch/cpu/start.S | 169 +++++++++++++++++++++++++++++++++++++ 4 files changed, 256 insertions(+) diff --git a/arch/loongarch/cpu/Makefile b/arch/loongarch/cpu/Makefile index 3dbed94cc624..d3c38a16d057 100644 --- a/arch/loongarch/cpu/Makefile +++ b/arch/loongarch/cpu/Makefile @@ -3,3 +3,7 @@ # Copyright (C) 2024 Jiaxun yang <jiaxun.y...@flygoat.com> # +extra-y = start.o + +obj-y += cpu.o +obj-y += smp_secondary.o diff --git a/arch/loongarch/cpu/cpu.c b/arch/loongarch/cpu/cpu.c new file mode 100644 index 000000000000..87c93c0cb20e --- /dev/null +++ b/arch/loongarch/cpu/cpu.c @@ -0,0 +1,28 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Copyright (C) 2018, Bin Meng <bmeng...@gmail.com> + */ + +#include <command.h> +#include <cpu.h> +#include <cpu_func.h> +#include <dm.h> +#include <dm/lists.h> +#include <event.h> +#include <hang.h> +#include <init.h> +#include <log.h> +#include <asm/system.h> +#include <dm/uclass-internal.h> +#include <linux/bitops.h> + + +#if !CONFIG_IS_ENABLED(SYSRESET) +void reset_cpu(void) +{ + printf("resetting ...\n"); + + printf("reset not supported yet\n"); + hang(); +} +#endif diff --git a/arch/loongarch/cpu/smp_secondary.S b/arch/loongarch/cpu/smp_secondary.S new file mode 100644 index 000000000000..1d7f02babb48 --- /dev/null +++ b/arch/loongarch/cpu/smp_secondary.S @@ -0,0 +1,55 @@ +/* SPDX-License-Identifier: GPL-2.0+ */ +/* + * Loop to run on secondary cores for LoongArch CPU + * + * Copyright (C) 2024 Jiaxun Yang <jiaxun.y...@flygoat.com> + */ + +#include <linux/linkage.h> +#include <asm/asm.h> +#include <asm/loongarch.h> +#include <asm/arch/entry-init.h> + +ENTRY(secondary_core_loop) + smp_secondary_setup + + PTR_LI t0, LOONGARCH_IOCSR_MBUF0 + LONG_IOCSRWR zero, t0 + + /* Enable IPI interrupt for wakeup */ + LONG_LI t0, ECFGF_IPI + csrxchg t0, t0, LOONGARCH_CSR_ECFG + + LONG_LI t0, 0xffffffff + li.w t1, LOONGARCH_IOCSR_IPI_CLEAR + iocsrwr.w t0, t1 + li.w t1, LOONGARCH_IOCSR_IPI_EN + iocsrwr.w t0, t1 + + /* t1 for spin table */ + PTR_LI t1, LOONGARCH_IOCSR_MBUF0 + +1: + /* Query spin table */ + idle 0 + nop + iocsrrd.w t0, t1 + beqz t0, 1b + + /* CLear IPI interrupt */ + PTR_LI t1, LOONGARCH_IOCSR_IPI_STATUS + iocsrrd.w t0, t1 + PTR_LI t1, LOONGARCH_IOCSR_IPI_CLEAR + iocsrwr.w t0, t1 + + /* Mask all interrupts */ + LONG_LI t0, ECFG0_IM + csrxchg zero, t0, LOONGARCH_CSR_ECFG + + /* Jump to secondary core */ + PTR_LI t1, LOONGARCH_IOCSR_MBUF0 + LONG_IOCSRRD t0, t1 + /* If we ever return, put us back to the loop */ + la.pcrel ra, secondary_core_loop + jirl zero, t0, 0 +END(secondary_core_loop) diff --git a/arch/loongarch/cpu/start.S b/arch/loongarch/cpu/start.S new file mode 100644 index 000000000000..69d52c5d7f4a --- /dev/null +++ b/arch/loongarch/cpu/start.S @@ -0,0 +1,169 @@ +/* SPDX-License-Identifier: GPL-2.0+ */ +/* + * Startup Code for LoongArch CPU + * + * Copyright (C) 2024 Jiaxun Yang <jiaxun.y...@flygoat.com> + */ + +#include <asm-offsets.h> +#include <config.h> +#include <elf.h> +#include <system-constants.h> +#include <asm/addrspace.h> +#include <asm/asm.h> +#include <asm/loongarch.h> +#include <asm/arch/entry-init.h> + +#define BOOTCORE_ID 0 + +.section .text +.globl _start +_start: + /* Allow arch specific setup code for MCSR stuff */ + entry_setup + + /* Disable interrupt */ + LONG_LI t0, CSR_CRMD_IE + csrxchg zero, t0, LOONGARCH_CSR_CRMD + + /* Configure reset ebase */ + la.pcrel t0, exception_entry + csrwr t0, LOONGARCH_CSR_EENTRY + + /* Setup direct map window for later use */ + PTR_LI t0, CSR_DMW0_INIT + csrwr t0, LOONGARCH_CSR_DMWIN0 + PTR_LI t0, CSR_DMW1_INIT + csrwr t0, LOONGARCH_CSR_DMWIN1 + + /* Branch out for nonboot core */ + csrrd t0, LOONGARCH_CSR_CPUID + andi t0, t0, CSR_CPUID_COREID + LONG_LI t1, BOOTCORE_ID + bne t1, t0, secondary_core_loop + +/* + * Set stackpointer in internal/ex RAM to call board_init_f + */ +call_board_init_f: + PTR_LI t0, (SYS_INIT_SP_ADDR & STACK_ALIGN) + move sp, t0 /* save stack pointer */ +/* + * Now sp points to the right stack belonging to current CPU. + * It's essential before any function call, otherwise, we get data-race. + */ + +call_board_init_f_0: + /* find top of reserve space */ + PTR_LI t1, 1 + PTR_SLL t1, t1, CONFIG_STACK_SIZE_SHIFT + PTR_SUB a0, t0, t1 /* t1 -> size of all CPU stacks */ + bl board_init_f_alloc_reserve + + /* Set global pointer to u0 ($r21) */ + move u0, a0 + bl board_init_f_init_reserve + + /* Enable cache */ + bl enable_caches + +#ifdef CONFIG_DEBUG_UART + bl debug_uart_init +#endif + + move a0, zero /* a0 <-- boot_flags = 0 */ + la.pcrel t5, board_init_f + jirl ra, t5, 0 /* jump to board_init_f() */ + + move sp, s0 + +/* + * void relocate_code(addr_sp, gd, addr_moni) + * + * This "function" does not return, instead it continues in RAM + * after relocating the monitor code. + * + */ +.globl relocate_code +relocate_code: + move s2, a0 /* save addr_sp */ + move s3, a1 /* save addr of gd */ + move s4, a2 /* save addr of destination */ + +/* + *Set up the stack + */ +stack_setup: + move sp, s2 + la.pcrel t0, _start + PTR_SUB t6, s4, t0 /* t6 <- relocation offset */ + beq t0, s4, clear_bss /* skip relocation */ + + move t1, s4 /* t1 <- scratch for copy_loop */ + la.pcrel t2, __bss_start /* t2 <- source end address */ + +copy_loop: + LONG_L t5, t0, 0 + PTR_ADDI t0, t0, LONGSIZE + LONG_S t5, t1, 0 + PTR_ADDI t1, t1, LONGSIZE + blt t0, t2, copy_loop + +/* + * Update dynamic relocations after board_init_f + */ +fix_rela_dyn: + la.pcrel t1, __rel_dyn_start + la.pcrel t2, __rel_dyn_end + beq t1, t2, clear_bss + PTR_ADD t1, t1, t6 /* t1 <- rela_dyn_start in RAM */ + PTR_ADD t2, t2, t6 /* t2 <- rela_dyn_end in RAM */ + +6: + PTR_L t5, t1, PTRSIZE /* t5 <-- relocation info:type */ + PTR_LI t3, R_LARCH_RELATIVE /* reloc type R_LARCH_RELATIVE */ + bne t5, t3, 8f /* skip non-RELATIVE entries */ + PTR_L t3, t1, 0 + PTR_L t5, t1, (PTRSIZE * 2) /* t5 <-- addend */ + PTR_ADD t5, t5, t6 /* t5 <-- location to fix up in RAM */ + PTR_ADD t3, t3, t6 /* t3 <-- location to fix up in RAM */ + PTR_S t5, t3, 0 +8: + PTR_ADDI t1, t1, (PTRSIZE * 3) + blt t1, t2, 6b + + + /* Update exception entry */ + la.pcrel t0, exception_entry + PTR_ADD t0, t0, t6 + csrwr t0, LOONGARCH_CSR_EENTRY + +clear_bss: + la.pcrel t0, __bss_start /* t0 <- rel __bss_start in FLASH */ + PTR_ADD t0, t0, t6 /* t0 <- rel __bss_start in RAM */ + la.pcrel t1, __bss_end /* t1 <- rel __bss_end in FLASH */ + PTR_ADD t1, t1, t6 /* t1 <- rel __bss_end in RAM */ + +clbss_l: + LONG_S zero, t0, 0 /* clear loop... */ + PTR_ADDI t0, t0, LONGSIZE + blt t0, t1, clbss_l + + +/* + * We are done. Do not return, instead branch to second part of board + * initialization, now running from RAM. + */ +call_board_init_r: + bl invalidate_icache_all + bl flush_dcache_all + la.pcrel t0, board_init_r /* offset of board_init_r() */ + PTR_ADD t4, t0, t6 /* real address of board_init_r() */ +/* + * setup parameters for board_init_r + */ + move a0, s3 /* gd_t */ + move a1, s4 /* dest_addr */ + move s0, zero /* fp == NULL */ + jirl ra, t4, 0 /* jump to board_init_r() */ + -- 2.43.0