xref: /aosp_15_r20/external/coreboot/src/arch/riscv/ramdetect.c (revision b9411a12aaaa7e1e6a6fb7c5e057f44ee179a49c)
1 /* SPDX-License-Identifier: GPL-2.0-or-later */
2 
3 #include <arch/exception.h>
4 #include <types.h>
5 #include <console/console.h>
6 #include <device/mmio.h>
7 #include <ramdetect.h>
8 #include <arch/smp/spinlock.h>
9 #include <vm.h>
10 
11 static enum {
12 	ABORT_CHECKER_NOT_TRIGGERED,
13 	ABORT_CHECKER_TRIGGERED,
14 } abort_state = ABORT_CHECKER_NOT_TRIGGERED;
15 
16 extern void (*trap_handler)(struct trapframe *tf);
17 
get_instruction_len(uintptr_t addr)18 static int get_instruction_len(uintptr_t addr)
19 {
20 	uint16_t ins = read16p(addr);
21 
22 	/*
23 	 * 16-bit or 32-bit instructions supported
24 	 */
25 	if ((ins & 0x3) != 3) {
26 		return 2;
27 	} else if ((ins & 0x1f) != 0x1f) {
28 		return 4;
29 	}
30 
31 	die("Not a 16bit or 32bit instruction 0x%x\n", ins);
32 }
33 
ramcheck_trap_handler(struct trapframe * tf)34 static void ramcheck_trap_handler(struct trapframe *tf)
35 {
36 	abort_state = ABORT_CHECKER_TRIGGERED;
37 
38 	/*
39 	 * skip read instruction.
40 	 */
41 	int insn_size = get_instruction_len(tf->epc);
42 
43 	write_csr(mepc, read_csr(mepc) + insn_size);
44 }
45 
probe_mb(const uintptr_t dram_start,const uintptr_t size)46 int probe_mb(const uintptr_t dram_start, const uintptr_t size)
47 {
48 	uintptr_t addr = dram_start + (size * MiB) - sizeof(uint32_t);
49 	void *ptr = (void *)addr;
50 
51 	abort_state = ABORT_CHECKER_NOT_TRIGGERED;
52 	trap_handler = ramcheck_trap_handler;
53 	barrier();
54 	read32(ptr);
55 	trap_handler = default_trap_handler;
56 	barrier();
57 	printk(BIOS_DEBUG, "%lx is %s DRAM\n", dram_start + size * MiB,
58 	       abort_state == ABORT_CHECKER_NOT_TRIGGERED ? "" : "not");
59 
60 	return abort_state == ABORT_CHECKER_NOT_TRIGGERED;
61 }
62