summaryrefslogtreecommitdiff
path: root/sys/arch
diff options
context:
space:
mode:
authorMark Kettenis <kettenis@cvs.openbsd.org>2024-01-26 16:59:48 +0000
committerMark Kettenis <kettenis@cvs.openbsd.org>2024-01-26 16:59:48 +0000
commit98e991bda26b2d7e68bda608a72895af5836b4b9 (patch)
tree380ce79e59a859e3d1a2abc72799cb4d10838e6f /sys/arch
parente13c03243afe0ed7606fa1cfd8ea86718bccbfd6 (diff)
Implement T-Head cache management operations which are needed to handle
the incoherent hardware design of SoCs like the Allwinner D1. ok miod@, jca@
Diffstat (limited to 'sys/arch')
-rw-r--r--sys/arch/riscv64/riscv64/cpu.c73
1 files changed, 72 insertions, 1 deletions
diff --git a/sys/arch/riscv64/riscv64/cpu.c b/sys/arch/riscv64/riscv64/cpu.c
index 13ae7c06072..0649c79cc01 100644
--- a/sys/arch/riscv64/riscv64/cpu.c
+++ b/sys/arch/riscv64/riscv64/cpu.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: cpu.c,v 1.17 2024/01/23 19:51:10 kettenis Exp $ */
+/* $OpenBSD: cpu.c,v 1.18 2024/01/26 16:59:47 kettenis Exp $ */
/*
* Copyright (c) 2016 Dale Rahn <drahn@dalerahn.com>
@@ -27,6 +27,7 @@
#include <uvm/uvm.h>
+#include <machine/cpufunc.h>
#include <machine/fdt.h>
#include <machine/sbi.h>
@@ -91,6 +92,12 @@ int cpu_errata_sifive_cip_1200;
void cpu_opp_init(struct cpu_info *, uint32_t);
+void thead_dcache_wbinv_range(paddr_t, psize_t);
+void thead_dcache_inv_range(paddr_t, psize_t);
+void thead_dcache_wb_range(paddr_t, psize_t);
+
+size_t thead_dcache_line_size;
+
void
cpu_identify(struct cpu_info *ci)
{
@@ -141,6 +148,13 @@ cpu_identify(struct cpu_info *ci)
/* Handle errata. */
if (mvendorid == CPU_VENDOR_SIFIVE && marchid == CPU_ARCH_U7)
cpu_errata_sifive_cip_1200 = 1;
+ if (mvendorid == CPU_VENDOR_THEAD && marchid == 0 && mimpid == 0) {
+ cpu_dcache_wbinv_range = thead_dcache_wbinv_range;
+ cpu_dcache_inv_range = thead_dcache_inv_range;
+ cpu_dcache_wb_range = thead_dcache_wb_range;
+ thead_dcache_line_size =
+ OF_getpropint(ci->ci_node, "d-cache-block-size", 64);
+ }
}
#ifdef MULTIPROCESSOR
@@ -309,6 +323,63 @@ cpu_cache_nop_range(paddr_t pa, psize_t len)
{
}
+void
+thead_dcache_wbinv_range(paddr_t pa, psize_t len)
+{
+ paddr_t end, mask;
+
+ mask = thead_dcache_line_size - 1;
+ end = (pa + len + mask) & ~mask;
+ pa &= ~mask;
+
+ while (pa != end) {
+ /* th.dcache.cipa a0 */
+ __asm volatile ("mv a0, %0; .long 0x02b5000b" :: "r"(pa)
+ : "a0", "memory");
+ pa += thead_dcache_line_size;
+ }
+ /* th.sync.s */
+ __asm volatile (".long 0x0190000b" ::: "memory");
+}
+
+void
+thead_dcache_inv_range(paddr_t pa, psize_t len)
+{
+ paddr_t end, mask;
+
+ mask = thead_dcache_line_size - 1;
+ end = (pa + len + mask) & ~mask;
+ pa &= ~mask;
+
+ while (pa != end) {
+ /* th.dcache.ipa a0 */
+ __asm volatile ("mv a0, %0; .long 0x02a5000b" :: "r"(pa)
+ : "a0", "memory");
+ pa += thead_dcache_line_size;
+ }
+ /* th.sync.s */
+ __asm volatile (".long 0x0190000b" ::: "memory");
+}
+
+void
+thead_dcache_wb_range(paddr_t pa, psize_t len)
+{
+ paddr_t end, mask;
+
+ mask = thead_dcache_line_size - 1;
+ end = (pa + len + mask) & ~mask;
+ pa &= ~mask;
+
+ while (pa != end) {
+ /* th.dcache.cpa a0 */
+ __asm volatile ("mv a0, %0; .long 0x0295000b" :: "r"(pa)
+ : "a0", "memory");
+ pa += thead_dcache_line_size;
+ }
+ /* th.sync.s */
+ __asm volatile (".long 0x0190000b" ::: "memory");
+}
+
void (*cpu_dcache_wbinv_range)(paddr_t, psize_t) = cpu_cache_nop_range;
void (*cpu_dcache_inv_range)(paddr_t, psize_t) = cpu_cache_nop_range;
void (*cpu_dcache_wb_range)(paddr_t, psize_t) = cpu_cache_nop_range;