blob: e184d5e20594614e65c20b516f021954a4fe2347 [file] [log] [blame]
Tom Rini10e47792018-05-06 17:58:06 -04001// SPDX-License-Identifier: GPL-2.0+
Rick Chen6eedd922017-12-26 13:55:49 +08002/*
3 * Copyright (C) 2017 Andes Technology Corporation
4 * Rick Chen, Andes Technology Corporation <rick@andestech.com>
Rick Chen6eedd922017-12-26 13:55:49 +08005 */
6
Simon Glass1d91ba72019-11-14 12:57:37 -07007#include <cpu_func.h>
Mayuresh Chitalec3abcaa2024-08-23 09:41:26 +00008#include <dm.h>
9#include <asm/insn-def.h>
10#include <linux/const.h>
11
12#define CBO_INVAL(base) \
13 INSN_I(OPCODE_MISC_MEM, FUNC3(2), __RD(0), \
14 RS1(base), SIMM12(0))
15#define CBO_CLEAN(base) \
16 INSN_I(OPCODE_MISC_MEM, FUNC3(2), __RD(0), \
17 RS1(base), SIMM12(1))
18#define CBO_FLUSH(base) \
19 INSN_I(OPCODE_MISC_MEM, FUNC3(2), __RD(0), \
20 RS1(base), SIMM12(2))
21enum {
22 CBO_CLEAN,
23 CBO_FLUSH,
24 CBO_INVAL
25} riscv_cbo_ops;
26static int zicbom_block_size;
27
28static inline void do_cbo_clean(unsigned long base)
29{
30 asm volatile ("add a0, %0, zero\n" CBO_CLEAN(%0) ::
31 "r"(base) : "memory");
32}
33
34static inline void do_cbo_flush(unsigned long base)
35{
36 asm volatile ("add a0, %0, zero\n" CBO_FLUSH(%0) ::
37 "r"(base) : "memory");
38}
39
40static inline void do_cbo_inval(unsigned long base)
41{
42 asm volatile ("add a0, %0, zero\n" CBO_INVAL(%0) ::
43 "r"(base) : "memory");
44}
45
46static void cbo_op(int op_type, unsigned long start,
47 unsigned long end)
48{
49 unsigned long op_size = end - start, size = 0;
50 void (*fn)(unsigned long base);
51
52 switch (op_type) {
53 case CBO_CLEAN:
54 fn = do_cbo_clean;
55 break;
56 case CBO_FLUSH:
57 fn = do_cbo_flush;
58 break;
59 case CBO_INVAL:
60 fn = do_cbo_inval;
61 break;
62 }
63 start &= ~(UL(zicbom_block_size - 1));
64 while (size < op_size) {
65 fn(start + size);
66 size += zicbom_block_size;
67 }
68}
69
70void cbo_flush(unsigned long start, unsigned long end)
71{
72 if (zicbom_block_size)
73 cbo_op(CBO_FLUSH, start, end);
74}
75
76void cbo_inval(unsigned long start, unsigned long end)
77{
78 if (zicbom_block_size)
79 cbo_op(CBO_INVAL, start, end);
80}
81
82static int riscv_zicbom_init(void)
83{
84 struct udevice *dev;
85
86 if (!CONFIG_IS_ENABLED(RISCV_ISA_ZICBOM) || zicbom_block_size)
87 return 1;
88
89 uclass_first_device(UCLASS_CPU, &dev);
90 if (!dev) {
91 log_debug("Failed to get cpu device!\n");
92 return 0;
93 }
94
95 if (dev_read_u32(dev, "riscv,cbom-block-size", &zicbom_block_size))
96 log_debug("riscv,cbom-block-size DT property not present\n");
97
98 return zicbom_block_size;
99}
Rick Chen6eedd922017-12-26 13:55:49 +0800100
Rick Chen842d5802018-11-07 09:34:06 +0800101void invalidate_icache_all(void)
102{
103 asm volatile ("fence.i" ::: "memory");
104}
105
Lukas Auer6280e322019-01-04 01:37:29 +0100106__weak void flush_dcache_all(void)
Rick Chen842d5802018-11-07 09:34:06 +0800107{
Rick Chen842d5802018-11-07 09:34:06 +0800108}
Lukas Auer6280e322019-01-04 01:37:29 +0100109
110__weak void flush_dcache_range(unsigned long start, unsigned long end)
Rick Chen6eedd922017-12-26 13:55:49 +0800111{
Mayuresh Chitalec3abcaa2024-08-23 09:41:26 +0000112 cbo_flush(start, end);
Rick Chen6eedd922017-12-26 13:55:49 +0800113}
114
Samuel Hollandac1c3d02023-10-31 00:37:20 -0500115__weak void invalidate_icache_range(unsigned long start, unsigned long end)
Rick Chen6eedd922017-12-26 13:55:49 +0800116{
Lukas Auer76562282018-11-22 11:26:23 +0100117 /*
118 * RISC-V does not have an instruction for invalidating parts of the
119 * instruction cache. Invalidate all of it instead.
120 */
121 invalidate_icache_all();
122}
123
Lukas Auer6280e322019-01-04 01:37:29 +0100124__weak void invalidate_dcache_range(unsigned long start, unsigned long end)
Lukas Auer76562282018-11-22 11:26:23 +0100125{
Mayuresh Chitalec3abcaa2024-08-23 09:41:26 +0000126 cbo_inval(start, end);
Rick Chen6eedd922017-12-26 13:55:49 +0800127}
128
Rick Chen842d5802018-11-07 09:34:06 +0800129void cache_flush(void)
Rick Chen6eedd922017-12-26 13:55:49 +0800130{
Rick Chen842d5802018-11-07 09:34:06 +0800131 invalidate_icache_all();
132 flush_dcache_all();
Rick Chen6eedd922017-12-26 13:55:49 +0800133}
134
135void flush_cache(unsigned long addr, unsigned long size)
136{
Lukas Auer09dfc3c2019-01-04 01:37:30 +0100137 invalidate_icache_range(addr, addr + size);
138 flush_dcache_range(addr, addr + size);
Rick Chen6eedd922017-12-26 13:55:49 +0800139}
140
Rick Chen842d5802018-11-07 09:34:06 +0800141__weak void icache_enable(void)
Rick Chen6eedd922017-12-26 13:55:49 +0800142{
143}
144
Rick Chen842d5802018-11-07 09:34:06 +0800145__weak void icache_disable(void)
Rick Chen6eedd922017-12-26 13:55:49 +0800146{
147}
148
Rick Chen842d5802018-11-07 09:34:06 +0800149__weak int icache_status(void)
Rick Chen6eedd922017-12-26 13:55:49 +0800150{
151 return 0;
152}
153
Rick Chen842d5802018-11-07 09:34:06 +0800154__weak void dcache_enable(void)
Rick Chen6eedd922017-12-26 13:55:49 +0800155{
156}
157
Rick Chen842d5802018-11-07 09:34:06 +0800158__weak void dcache_disable(void)
Rick Chen6eedd922017-12-26 13:55:49 +0800159{
160}
161
Rick Chen842d5802018-11-07 09:34:06 +0800162__weak int dcache_status(void)
Rick Chen6eedd922017-12-26 13:55:49 +0800163{
164 return 0;
165}
Zong Lia33070c2021-09-01 15:01:40 +0800166
167__weak void enable_caches(void)
168{
Mayuresh Chitalec3abcaa2024-08-23 09:41:26 +0000169 if (!riscv_zicbom_init())
170 log_info("Zicbom not initialized.\n");
Zong Lia33070c2021-09-01 15:01:40 +0800171}