1 /*
2  * Copyright (c) 2021-2022 HPMicro
3  *
4  * SPDX-License-Identifier: BSD-3-Clause
5  *
6  */
7 
8 #include "hpm_l1c_drv.h"
9 #include <assert.h>
10 
11 
12 #define ASSERT_ADDR_SIZE(addr, size) do { \
13                                              assert(address % HPM_L1C_CACHELINE_SIZE == 0); \
14                                              assert(size % HPM_L1C_CACHELINE_SIZE == 0); \
15                                         } while (0)
16 
l1c_op(uint8_t opcode,uint32_t address,uint32_t size)17 static void l1c_op(uint8_t opcode, uint32_t address, uint32_t size)
18 {
19     register uint32_t i;
20     register uint32_t next_address;
21     register uint32_t tmp;
22     register uint32_t csr;
23 
24     csr = read_clear_csr(CSR_MSTATUS, CSR_MSTATUS_MIE_MASK);
25 
26 #define CCTL_VERSION (3U << 18)
27 
28     if ((read_csr(CSR_MMSC_CFG) & CCTL_VERSION)) {
29         l1c_cctl_address(address);
30         next_address = address;
31         while ((next_address < (address + size)) && (next_address >= address)) {
32             l1c_cctl_cmd(opcode);
33             next_address = l1c_cctl_get_address();
34         }
35     } else {
36         for (i = 0, tmp = 0; tmp < size; i++) {
37             l1c_cctl_address_cmd(opcode, address + i * HPM_L1C_CACHELINE_SIZE);
38             tmp += HPM_L1C_CACHELINE_SIZE;
39         }
40     }
41 
42     write_csr(CSR_MSTATUS, csr);
43 }
44 
l1c_dc_enable(void)45 void l1c_dc_enable(void)
46 {
47     if (!l1c_dc_is_enabled()) {
48         clear_csr(CSR_MCACHE_CTL, HPM_MCACHE_CTL_DC_WAROUND_MASK);
49         set_csr(CSR_MCACHE_CTL,
50 #ifdef L1C_DC_WAROUND_VALUE
51                 HPM_MCACHE_CTL_DC_WAROUND(L1C_DC_WAROUND_VALUE) |
52 #endif
53                                 HPM_MCACHE_CTL_DPREF_EN_MASK
54                               | HPM_MCACHE_CTL_DC_EN_MASK);
55     }
56 }
57 
l1c_dc_disable(void)58 void l1c_dc_disable(void)
59 {
60     if (l1c_dc_is_enabled()) {
61         clear_csr(CSR_MCACHE_CTL, HPM_MCACHE_CTL_DC_EN_MASK);
62     }
63 }
64 
l1c_ic_enable(void)65 void l1c_ic_enable(void)
66 {
67     if (!l1c_ic_is_enabled()) {
68         set_csr(CSR_MCACHE_CTL, HPM_MCACHE_CTL_IPREF_EN_MASK
69                               | HPM_MCACHE_CTL_CCTL_SUEN_MASK
70                               | HPM_MCACHE_CTL_IC_EN_MASK);
71     }
72 }
73 
l1c_ic_disable(void)74 void l1c_ic_disable(void)
75 {
76     if (l1c_ic_is_enabled()) {
77         clear_csr(CSR_MCACHE_CTL, HPM_MCACHE_CTL_IC_EN_MASK);
78     }
79 }
80 
l1c_fence_i(void)81 void l1c_fence_i(void)
82 {
83     __asm("fence.i");
84 }
85 
l1c_dc_invalidate_all(void)86 void l1c_dc_invalidate_all(void)
87 {
88     l1c_cctl_cmd(HPM_L1C_CCTL_CMD_L1D_INVAL_ALL);
89 }
90 
l1c_dc_writeback_all(void)91 void l1c_dc_writeback_all(void)
92 {
93     l1c_cctl_cmd(HPM_L1C_CCTL_CMD_L1D_WB_ALL);
94 }
95 
l1c_dc_flush_all(void)96 void l1c_dc_flush_all(void)
97 {
98     l1c_cctl_cmd(HPM_L1C_CCTL_CMD_L1D_WBINVAL_ALL);
99 }
100 
l1c_dc_fill_lock(uint32_t address,uint32_t size)101 void l1c_dc_fill_lock(uint32_t address, uint32_t size)
102 {
103     ASSERT_ADDR_SIZE(address, size);
104     l1c_op(HPM_L1C_CCTL_CMD_L1D_VA_LOCK, address, size);
105 }
106 
l1c_dc_invalidate(uint32_t address,uint32_t size)107 void l1c_dc_invalidate(uint32_t address, uint32_t size)
108 {
109     ASSERT_ADDR_SIZE(address, size);
110     l1c_op(HPM_L1C_CCTL_CMD_L1D_VA_INVAL, address, size);
111 }
112 
l1c_dc_writeback(uint32_t address,uint32_t size)113 void l1c_dc_writeback(uint32_t address, uint32_t size)
114 {
115     ASSERT_ADDR_SIZE(address, size);
116     l1c_op(HPM_L1C_CCTL_CMD_L1D_VA_WB, address, size);
117 }
118 
l1c_dc_flush(uint32_t address,uint32_t size)119 void l1c_dc_flush(uint32_t address, uint32_t size)
120 {
121     ASSERT_ADDR_SIZE(address, size);
122     l1c_op(HPM_L1C_CCTL_CMD_L1D_VA_WBINVAL, address, size);
123 }
124 
l1c_ic_invalidate(uint32_t address,uint32_t size)125 void l1c_ic_invalidate(uint32_t address, uint32_t size)
126 {
127     ASSERT_ADDR_SIZE(address, size);
128     l1c_op(HPM_L1C_CCTL_CMD_L1I_VA_INVAL, address, size);
129 }
130 
l1c_ic_fill_lock(uint32_t address,uint32_t size)131 void l1c_ic_fill_lock(uint32_t address, uint32_t size)
132 {
133     ASSERT_ADDR_SIZE(address, size);
134     l1c_op(HPM_L1C_CCTL_CMD_L1I_VA_LOCK, address, size);
135 }
136