summaryrefslogtreecommitdiff
path: root/core/riscv-rv32i/init.S
diff options
context:
space:
mode:
Diffstat (limited to 'core/riscv-rv32i/init.S')
-rw-r--r--core/riscv-rv32i/init.S394
1 files changed, 394 insertions, 0 deletions
diff --git a/core/riscv-rv32i/init.S b/core/riscv-rv32i/init.S
new file mode 100644
index 0000000000..11b1dba1f8
--- /dev/null
+++ b/core/riscv-rv32i/init.S
@@ -0,0 +1,394 @@
+/* Copyright 2019 The Chromium OS Authors. All rights reserved.
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ *
+ * RISC-V CPU initialization
+ */
+
+#include "config.h"
+
+.macro vector name
+.set \name\()_handler, unhandled_ec_irq
+.weak \name\()_handler
+j __entry_\()\name
+.pushsection .text.vectirq
+.global __entry_\()\name
+__entry_\()\name:
+ /* C routine handler */
+ j \name\()_handler
+.popsection
+.pushsection .rodata.vecthandlers
+.long \name\()_handler
+.popsection
+.endm
+
+.section .text.vecttable
+.align 2
+__startup:
+ j __reset /* reset */
+__irq:
+ j __irq_isr /* interrupts / exceptions */
+
+/*
+ * E-flash signature used to enable specific function after power-on reset.
+ * (HW mechanism)
+ * The content of 16-bytes must be the following and at offset 0x80 of binary.
+ * ----------------------------------------------------------------------------
+ * 1st 2nd 3rd 4th 5th 6th 7th 8th 9th 10th 11th 12th 13th 14th 15th 16th
+ * ----------------------------------------------------------------------------
+ * A5h A5h A5h A5h A5h A5h [host] [flag] 85h 12h 5Ah 5Ah AAh AAh 55h 55h
+ * ----------------------------------------------------------------------------
+ * [host]: A4h = enable eSPI, A5h = enable LPC
+ * [flag]:
+ * bit7: it must be 1b.
+ * bit6: it must be 0b.
+ * bit5: it must be 1b.
+ * bit4: 1b = 32.768KHz is from the internal clock generator.
+ * bit3: it must be 0b.
+ * bit2: it must be 1b.
+ * bit1: it must be 0b.
+ * bit0: it must be 0b.
+ */
+.org 0x80
+.balign 16
+.global eflash_sig
+eflash_sig:
+.byte 0xA5, 0xA5, 0xA5, 0xA5, 0xA5, 0xA5
+#ifdef CONFIG_HOSTCMD_ESPI
+.byte 0xA4 /* eSPI */
+#else
+.byte 0xA5 /* LPC */
+#endif
+.byte 0xB4 /* flag of signature */
+.byte 0x85, 0x12, 0x5A, 0x5A, 0xAA, 0xAA, 0x55, 0x55
+/* flags: internal oscillator + implicit location */
+
+.align 2
+__ec_intc:
+ vector irq_0 /* INT GROUP 0 */
+ vector irq_1 /* INT GROUP 1 */
+ vector irq_2 /* INT GROUP 2 */
+ vector irq_3 /* INT GROUP 3 */
+ vector irq_4 /* INT GROUP 4 */
+ vector irq_5 /* INT GROUP 5 */
+ vector irq_6 /* INT GROUP 6 */
+ vector irq_7 /* INT GROUP 7 */
+ vector irq_8 /* INT GROUP 8 */
+ vector irq_9 /* INT GROUP 9 */
+ vector irq_10 /* INT GROUP 10 */
+ vector irq_11 /* INT GROUP 11 */
+ vector irq_12 /* INT GROUP 12 */
+ vector irq_13 /* INT GROUP 13 */
+ vector irq_14 /* INT GROUP 14 */
+ vector irq_15 /* INT GROUP 15 */
+ vector syscall /* system call (emulate INT GROUP 16) */
+
+.align 2
+__irq_isr:
+ /* save t2 to scratch register */
+ csrw mscratch, t2
+ /* save registers (sp, ra, t0, and t1) state at exception entry */
+ la t2, excep_entry_saved_regs
+ sw sp, 0*4(t2)
+ sw ra, 1*4(t2)
+ sw t0, 2*4(t2)
+ sw t1, 3*4(t2)
+ /* store return address register */
+ la t2, ira
+ sw ra, 0(t2)
+ /* restore t2 */
+ csrr t2, mscratch
+ /* save ra, a0-7, t0-t6 (high memory address to low) */
+ sw t6, -16*4(sp)
+ sw t5, -15*4(sp)
+ sw t4, -14*4(sp)
+ sw t3, -13*4(sp)
+ sw t2, -12*4(sp)
+ sw t1, -11*4(sp)
+ sw t0, -10*4(sp)
+ sw a7, -9*4(sp)
+ sw a6, -8*4(sp)
+ sw a5, -7*4(sp)
+ sw a4, -6*4(sp)
+ sw a3, -5*4(sp)
+ sw a2, -4*4(sp)
+ sw a1, -3*4(sp)
+ /* Don't change index of ra and a0 (see task_pre_init()) */
+ sw a0, -2*4(sp)
+ sw ra, -1*4(sp)
+#ifdef CONFIG_FPU
+ /* save ft0-11, fa0-7, and fcsr. */
+ csrr t0, fcsr
+ sw t0, -37*4(sp)
+ fsw fa7, -36*4(sp)
+ fsw fa6, -35*4(sp)
+ fsw fa5, -34*4(sp)
+ fsw fa4, -33*4(sp)
+ fsw fa3, -32*4(sp)
+ fsw fa2, -31*4(sp)
+ fsw fa1, -30*4(sp)
+ fsw fa0, -29*4(sp)
+ fsw ft11, -28*4(sp)
+ fsw ft10, -27*4(sp)
+ fsw ft9, -26*4(sp)
+ fsw ft8, -25*4(sp)
+ fsw ft7, -24*4(sp)
+ fsw ft6, -23*4(sp)
+ fsw ft5, -22*4(sp)
+ fsw ft4, -21*4(sp)
+ fsw ft3, -20*4(sp)
+ fsw ft2, -19*4(sp)
+ fsw ft1, -18*4(sp)
+ fsw ft0, -17*4(sp)
+ addi sp, sp, -37*4
+#else
+ addi sp, sp, -16*4
+#endif
+ /* save sp to scratch register */
+ csrw mscratch, sp
+ /* switch to system stack if we are called from process stack */
+ la t0, stack_end
+ /* no chagne sp if sp < end of system stack */
+ bltu sp, t0, __no_adjust_sp
+ mv sp, t0
+__no_adjust_sp:
+ /* read exception cause */
+ csrr t0, mcause
+ /* isolate exception cause */
+ andi t1, t0, 0x1f
+ /* mcause = 11: external interrupt or environment call from M-mode */
+ addi t1, t1, -11
+ beqz t1, __irq_handler
+ /* branch if this is an exceptoin (the interrupt bit of mcause is 0) */
+ bgez t0, excep_handler
+ /* This interrupt is unhandled */
+ j unhandled_interrupt
+__irq_handler:
+ jal start_irq_handler
+ /* get EC interrupt group 0-15 or 16:ecall */
+ la t0, ec_int_group
+ /* get corresponding isr */
+ lw t1, 0(t0)
+ slli t1, t1, 2
+ la t0, __ec_intc
+ add t0, t0, t1
+ /* handle irq */
+ jalr t0
+ /* check whether we need to change the scheduled task */
+ la t0, need_resched
+ lw t1, 0(t0)
+ bnez t1, __switch_task
+.global __irq_exit
+__irq_exit:
+ jal end_irq_handler
+ /* restore sp from scratch register */
+ csrr sp, mscratch
+#ifdef CONFIG_FPU
+ addi sp, sp, 37*4
+ /* restore ft0-11, fa0-7, and fcsr. */
+ lw t0, -37*4(sp)
+ csrw fcsr, t0
+ flw fa7, -36*4(sp)
+ flw fa6, -35*4(sp)
+ flw fa5, -34*4(sp)
+ flw fa4, -33*4(sp)
+ flw fa3, -32*4(sp)
+ flw fa2, -31*4(sp)
+ flw fa1, -30*4(sp)
+ flw fa0, -29*4(sp)
+ flw ft11, -28*4(sp)
+ flw ft10, -27*4(sp)
+ flw ft9, -26*4(sp)
+ flw ft8, -25*4(sp)
+ flw ft7, -24*4(sp)
+ flw ft6, -23*4(sp)
+ flw ft5, -22*4(sp)
+ flw ft4, -21*4(sp)
+ flw ft3, -20*4(sp)
+ flw ft2, -19*4(sp)
+ flw ft1, -18*4(sp)
+ flw ft0, -17*4(sp)
+#else
+ addi sp, sp, 16*4
+#endif
+ /* restore ra, a0-a7, t0-t6 */
+ lw t6, -16*4(sp)
+ lw t5, -15*4(sp)
+ lw t4, -14*4(sp)
+ lw t3, -13*4(sp)
+ lw t2, -12*4(sp)
+ lw t1, -11*4(sp)
+ lw t0, -10*4(sp)
+ lw a7, -9*4(sp)
+ lw a6, -8*4(sp)
+ lw a5, -7*4(sp)
+ lw a4, -6*4(sp)
+ lw a3, -5*4(sp)
+ lw a2, -4*4(sp)
+ lw a1, -3*4(sp)
+ lw a0, -2*4(sp)
+ lw ra, -1*4(sp)
+ mret
+
+.text
+.global __reset
+__reset:
+ /* disable interrupts */
+ csrw mie, zero
+.option push
+.option norelax
+ /* GP register is used to access .data and .bss (address +/- 2048) */
+ la gp, __global_pointer$
+.option pop
+ /* Set system stack pointer. */
+ la sp, stack_end
+#ifdef CONFIG_FPU
+ li t0, 0x6000
+ csrw mstatus, t0
+ csrw fcsr, zero
+#else
+ csrw mstatus, zero
+#endif
+ /*
+ * move content of return address(ra) into t5 and then store the content
+ * into variable "ec_reset_lp" later after memory initialization.
+ */
+ mv t5, ra
+ /* Clear the link register */
+ li ra, 0
+ /* Clear the thread pointer register */
+ li tp, 0
+ /* set machine trap-handler base address */
+ la t0, __irq
+ csrw mtvec, t0
+ /* reset scratch register */
+ csrw mscratch, zero
+ /* The M-mode handles interrupt/exception */
+ csrwi mideleg, 0
+ csrwi medeleg, 0
+ /* Clear BSS */
+ la t0, __bss_start
+ la t1, __bss_end
+bss_loop:
+ sw zero, 0(t0)
+ addi t0, t0, 4
+ bltu t0, t1, bss_loop
+ /* Copy initialized data to data section */
+ la t0, __data_start
+ la t1, __data_end
+ la t2, __data_lma_start
+data_loop:
+ lw t3, 0(t2)
+ sw t3, 0(t0)
+ addi t0, t0, 4
+ addi t2, t2, 4
+ bltu t0, t1, data_loop
+ /* store the content of t5 (ra after reset) into "ec_reset_lp" */
+ la t0, ec_reset_lp
+ sw t5, 0(t0)
+ /* clear BRAM if it is not valid */
+ jal chip_bram_valid
+ /* Jump to C routine */
+ jal main
+ /* That should not return. If it does, loop forever. */
+ j .
+
+.global unhandled_ec_irq
+.global unhandled_interrupt
+unhandled_ec_irq:
+ li tp, 0xBAD1
+ j __unhandled_irq
+unhandled_interrupt:
+ li tp, 0xBAD0
+__unhandled_irq:
+ slli tp, tp, 8
+ csrr t0, mcause
+ add tp, tp, t0
+ j excep_handler /* display exception with TP 80bad[0|1]<irq> */
+
+.global excep_handler
+excep_handler:
+ /* save t2 */
+ csrw mscratch, t2
+ /* restore registers (sp, ra, t0, and t1) state */
+ la t2, excep_entry_saved_regs
+ lw sp, 0*4(t2)
+ lw ra, 1*4(t2)
+ lw t0, 2*4(t2)
+ lw t1, 3*4(t2)
+ /* restore t2 */
+ csrr t2, mscratch
+ /* save sp to scratch register */
+ csrw mscratch, sp
+ la sp, saved_regs
+ /* save sp, ra, gp, tp , a0-a7, t0-t6, and s0-s11 registers */
+ sw s11, 0*4(sp)
+ sw s10, 1*4(sp)
+ sw s9, 2*4(sp)
+ sw s8, 3*4(sp)
+ sw s7, 4*4(sp)
+ sw s6, 5*4(sp)
+ sw s5, 6*4(sp)
+ sw s4, 7*4(sp)
+ sw s3, 8*4(sp)
+ sw s2, 9*4(sp)
+ sw s1, 10*4(sp)
+ sw s0, 11*4(sp)
+ sw t6, 12*4(sp)
+ sw t5, 13*4(sp)
+ sw t4, 14*4(sp)
+ sw t3, 15*4(sp)
+ sw t2, 16*4(sp)
+ sw t1, 17*4(sp)
+ sw t0, 18*4(sp)
+ sw a7, 19*4(sp)
+ sw a6, 20*4(sp)
+ sw a5, 21*4(sp)
+ sw a4, 22*4(sp)
+ sw a3, 23*4(sp)
+ sw a2, 24*4(sp)
+ sw a1, 25*4(sp)
+ sw a0, 26*4(sp)
+ sw tp, 27*4(sp)
+ sw gp, 28*4(sp)
+ sw ra, 29*4(sp)
+ la a0, saved_regs
+ csrr sp, mscratch
+ sw sp, 30*4(a0)
+ /* put a sane stack pointer */
+ la sp, stack_end
+ /* jump to panic dump C routine */
+ jal report_panic
+ j .
+
+.align 2
+_bss_start:
+.long __bss_start
+_bss_end:
+.long __bss_end
+_data_start:
+.long __data_start
+_data_end:
+.long __data_end
+_data_lma_start:
+.long __data_lma_start
+
+/* Reserve space for system stack */
+.section .bss.system_stack
+stack_start:
+.space CONFIG_STACK_SIZE, 0
+stack_end:
+.global stack_end
+
+/* sp, ra, t0, t1 registers state at exception entry */
+.global excep_entry_saved_regs
+excep_entry_saved_regs:
+.long 0, 0, 0, 0
+
+/* registers state at exception entry */
+.global saved_regs
+saved_regs:
+.long 0, 0, 0, 0, 0, 0, 0, 0
+.long 0, 0, 0, 0, 0, 0, 0, 0
+.long 0, 0, 0, 0, 0, 0, 0, 0
+.long 0, 0, 0, 0, 0, 0, 0, 0