[PATCH 08/16] LoongArch: CPU assembly routines
Jiaxun Yang
jiaxun.yang at flygoat.com
Wed May 22 17:34:51 CEST 2024
start.S for initialisation, smp_secondary routine for
a spin-table like interface for secondary cpus.
Signed-off-by: Jiaxun Yang <jiaxun.yang at 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.yang at 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.cn at 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.yang at 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.yang at 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
More information about the U-Boot
mailing list