• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2 // Copyright (C) 2022 Beken Corporation
3  * Licensed under the Apache License, Version 2.0 (the "License");
4  * you may not use this file except in compliance with the License.
5  * You may obtain a copy of the License at
6  *
7  *     http://www.apache.org/licenses/LICENSE-2.0
8  *
9  * Unless required by applicable law or agreed to in writing, software
10  * distributed under the License is distributed on an "AS IS" BASIS,
11  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12  * See the License for the specific language governing permissions and
13  * limitations under the License.
14  */
15 
16 #include <stdio.h>
17 #include "platform.h"
18 #include <os/os.h>
19 #include <components/system.h>
20 #include "cache.h"
21 
22 /* CSR NDS_ICM_CFG */
23 #define ISET_MSK                                ((1ULL << 2) | (1ULL << 1) | (1ULL << 0))
24 #define IWAY_MSK                                ((1ULL << 5) | (1ULL << 4) | (1ULL << 3))
25 #define ISIZE_MSK                               ((1ULL << 8) | (1ULL << 7) | (1ULL << 6))
26 
27 /* CSR NDS_DCM_CFG */
28 #define DSET_MSK                                ((1ULL << 2) | (1ULL << 1) | (1ULL << 0))
29 #define DWAY_MSK                                ((1ULL << 5) | (1ULL << 4) | (1ULL << 3))
30 #define DSIZE_MSK                               ((1ULL << 8) | (1ULL << 7) | (1ULL << 6))
31 
32 /* CSR NDS_MCACHE_CTL */
33 #define DC_WARND_MSK                            (3UL << 13)
34 #define CCTL_SUEN_MSK                           (1ULL << 8)
35 
36 /* CSR NDS_MMSC_CFG */
37 #define CCTLCSR_MSK                             (1ULL << 16)
38 #define VCCTL_MSK                               ((1ULL << 18) | (1ULL << 19))
39 
40 /* AndeStar CCTL Command Machine mode */
41 /* Allow S/U mode */
42 #define CCTL_L1D_VA_INVAL                       0
43 /* Allow S/U mode */
44 #define CCTL_L1D_VA_WB                          1
45 /* Allow S/U mode */
46 #define CCTL_L1D_VA_WBINVAL                     2
47 #define CCTL_L1D_VA_LOCK                        3
48 #define CCTL_L1D_VA_UNLOCK                      4
49 #define CCTL_L1D_WBINVAL_ALL                    6
50 #define CCTL_L1D_WB_ALL                         7
51 /* Allow S/U mode */
52 #define CCTL_L1I_VA_INVAL                       8
53 #define CCTL_L1I_VA_LOCK                        11
54 #define CCTL_L1I_VA_UNLOCK                      12
55 #define CCTL_L1D_IX_INVAL                       16
56 #define CCTL_L1D_IX_WB                          17
57 #define CCTL_L1D_IX_WBINVAL                     18
58 #define CCTL_L1D_IX_RTAG                        19
59 #define CCTL_L1D_IX_RDATA                       20
60 #define CCTL_L1D_IX_WTAG                        21
61 #define CCTL_L1D_IX_WDATA                       22
62 #define CCTL_L1D_INVAL_ALL                      23
63 #define CCTL_L1I_IX_INVAL                       24
64 #define CCTL_L1I_IX_RTAG                        27
65 #define CCTL_L1I_IX_RDATA                       28
66 #define CCTL_L1I_IX_WTAG                        29
67 #define CCTL_L1I_IX_WDATA                       30
68 
69 #define USE_CCTL                                0
70 #define BUF_SIZE                                0x100
71 
72 /* SMU.SYSTEMCFG Configuration Register */
73 #define L2C_CTL_OFF                             8
74 #define L2C_CTL_MSK                             (0x1 << L2C_CTL_OFF)
75 
76 /* Configuration Register */
77 #define L2C_SIZE_OFF                            7
78 #define L2C_SIZE_MSK                            (0x1F << L2C_SIZE_OFF)
79 #define L2C_SIZE_0KB                            (0x00 << L2C_SIZE_OFF)
80 #define L2C_SIZE_128KB                          (0x01 << L2C_SIZE_OFF)
81 #define L2C_SIZE_256KB                          (0x02 << L2C_SIZE_OFF)
82 #define L2C_SIZE_512KB                          (0x04 << L2C_SIZE_OFF)
83 #define L2C_SIZE_1024KB                         (0x08 << L2C_SIZE_OFF)
84 #define L2C_SIZE_2048KB                         (0x10 << L2C_SIZE_OFF)
85 #define L2C_LINE_SIZE                           32
86 
87 /* Control Register */
88 #define L2C_ENABLE                              0x1
89 
90 /* Prefetch Threshold */
91 #define PFTHRES_OFF                             1
92 #define PFTHRES_MSK                             (0x3 << PFTHRES_OFF)
93 
94 /* Instruction Prefetch Depth */
95 #define IPFDPT_OFF                              3
96 #define IPFDPT_MSK                              (0x3 << IPFDPT_OFF)
97 #define IPFDPT_3REQ                             (0x3 << IPFDPT_OFF)
98 
99 /* Data Prefetch Depth */
100 #define DPFDPT_OFF                              5
101 #define DPFDPT_MSK                              (0x3 << DPFDPT_OFF)
102 #define DPFDPT_3REQ                             (0x3 << DPFDPT_OFF)
103 
104 /* Tag Ram output cycle */
105 #define TRAMOCTL_OFF                            8
106 #define TRAMOCTL_MSK                            (0x3 << TRAMOCTL_OFF)
107 
108 /* Tag Ram setup cycle */
109 #define TRAMICTL_OFF                            10
110 #define TRAMICTL_MSK                            (0x1 << TRAMICTL_OFF)
111 
112 /* Data Ram output cycle */
113 #define DRAMOCTL_OFF                            11
114 #define DRAMOCTL_MSK                            (0x3 << DRAMOCTL_OFF)
115 
116 /* Data Ram setup cycle */
117 #define DRAMICTL_OFF                            13
118 #define DRAMICTL_MSK                            (0x1 << DRAMICTL_OFF)
119 
120 /* CCTL Command Register */
121 #define CCTL_L2_IX_INVAL                        0x0
122 #define CCTL_L2_IX_WB                           0x1
123 #define CCTL_L2_IX_WBINVAL                      0x2
124 #define CCTL_L2_PA_INVAL                        0x8
125 #define CCTL_L2_PA_WB                           0x9
126 #define CCTL_L2_PA_WBINVAL                      0xA
127 #define CCTL_L2_TGT_WRITE                       0x10
128 #define CCTL_L2_TGT_READ                        0x11
129 #define CCTL_L2_WBINVAL_ALL                     0x12
130 
131 /* CCTL Access Line Registers */
132 #define CCTL_L2_ACC_SET_OFF                     5
133 #define CCTL_L2_ACC_SET_MSK                     (0x7FFF << CCTL_L2_ACC_SET_OFF)
134 #define CCTL_L2_ACC_WAY_OFF                     28
135 #define CCTL_L2_ACC_WAY_MSK                     (0xF << CCTL_L2_ACC_WAY_OFF)
136 #define CCTL_L2_ACC_RAMID_OFF                   26
137 #define CCTL_L2_ACC_RAMID_MSK                   (0x3 << CCTL_L2_ACC_RAMID_OFF)
138 
139 /* CCTL Status Register */
140 #define CCTL_L2_ST_IDLE                         0
141 #define CCTL_L2_ST_RUNNING                      1
142 #define CCTL_L2_ST_INVALID                      2
143 #define CCTL_ST_MASK                            0xF
144 
145 #define SRAM_CACHE_CONFIG_BASE                  0x3fff0048
146 
147 #if !CONFIG_CACHE_CUSTOM_SRAM_MAPPING
148 #if !CONFIG_CACHE_ENABLE
149 const unsigned int g_sram_addr_map[SRAM_BLOCK_COUNT] = {
150     0x30020000,
151     0x30040000,
152     0x30060000,
153     0x30000000
154 };
155 #else //#if CONFIG_CACHE_ENABLE
156 const unsigned int g_sram_addr_map[SRAM_BLOCK_COUNT] = {
157     0x38000000,
158     0x38020000,
159     0x30000000,
160     0x30020000
161 };
162 #endif //#if CONFIG_CACHE_ENABLE
163 #else  //#if !CONFIG_CACHE_CUSTOM_SRAM_MAPPING
164 extern unsigned int g_sram_addr_map[SRAM_BLOCK_COUNT];
165 #endif //#if !CONFIG_CACHE_CUSTOM_SRAM_MAPPING
166 
sram_dcache_map(void)167 void sram_dcache_map(void)
168 {
169    int i = 0;
170    unsigned int addr, data;
171 
172    for(i = 0; i < SRAM_BLOCK_COUNT; i++)
173    {
174         addr = SRAM_CACHE_CONFIG_BASE + (i * SRAM_BLOCK_COUNT);
175         data = *((volatile unsigned int *) (addr));
176         *((volatile unsigned int *) (addr)) = (g_sram_addr_map[i]) + (data & 0x03ff);
177    }
178 }
179 
show_cache_config_info(void)180 int show_cache_config_info(void)
181 {
182     unsigned int iset, iway, isize, dset, dway, dsize;
183     unsigned long icm_cfg = 0, dcm_cfg = 0;
184 
185     /* Check if support CCTL feature */
186     if (read_csr(NDS_MMSC_CFG) & CCTLCSR_MSK) {
187         os_printf("CPU supports CCTL operation\n");
188 
189         if (read_csr(NDS_MMSC_CFG) & VCCTL_MSK) {
190             os_printf("CPU supports CCTL auto-increment\n");
191         } else {
192             os_printf("CPU does NOT support CCTL auto-increment\n");
193         }
194 
195     } else {
196         os_printf("CPU supports FENCE operation\n");
197     }
198 
199     /* Enable I/D cache HW prefetcher and D-cache write-around (threshold: 4 cache lines) as default */
200     // clear_csr(NDS_MCACHE_CTL, DC_WARND_MSK);
201     // set_csr(NDS_MCACHE_CTL, (1 << 13) | (1 << 10) | (1 << 9));
202 
203     /* Get ICache ways, sets, line size */
204     icm_cfg = read_csr(NDS_MICM_CFG);
205     if ((icm_cfg & ISET_MSK) < 7) {
206         iset = (unsigned int)(1 << ((icm_cfg & ISET_MSK) + 6));
207     } else {
208         iset = 0;
209     }
210     os_printf("The L1C ICache sets = %u\n", iset);
211 
212     iway = (unsigned int)(((icm_cfg & IWAY_MSK) >> 3) + 1);
213     os_printf("The L1C ICache ways = %u\n", iway);
214 
215     if (((icm_cfg & ISIZE_MSK) >> 6) && (((icm_cfg & ISIZE_MSK) >> 6) <= 5)) {
216         isize = (unsigned int)(1 << (((icm_cfg & ISIZE_MSK) >> 6) + 2));
217     } else if (((icm_cfg & ISIZE_MSK) >> 6) >= 6) {
218         os_printf("Warning L1C i cacheline size is reserved value\n");
219         isize = 0;
220     } else {
221         isize = 0;
222     }
223 
224     os_printf("The L1C ICache line size = %u\n", isize);
225     if (isize == 0) {
226         os_printf("This CPU doesn't have L1C ICache.\n");
227         return 0;
228     } else {
229         /* Enable L1C ICache */
230         // set_csr(NDS_MCACHE_CTL, (0x1 << 0));
231     }
232 
233     /* Get DCache ways, sets, line size  */
234     dcm_cfg = read_csr(NDS_MDCM_CFG);
235     if ((dcm_cfg & DSET_MSK) < 7) {
236         dset = (unsigned int)(1 << ((dcm_cfg & DSET_MSK) + 6));
237     } else {
238         dset = 0;
239     }
240     os_printf("The L1C DCache sets = %u\n", dset);
241 
242     dway = (unsigned int)(((dcm_cfg & DWAY_MSK) >> 3) + 1);
243     os_printf("The L1C DCache ways = %u\n", dway);
244 
245     if (((dcm_cfg & DSIZE_MSK) >> 6) && (((dcm_cfg & DSIZE_MSK) >> 6) <= 5)) {
246         dsize = (unsigned int)(1 << (((dcm_cfg & DSIZE_MSK) >> 6) + 2));
247     } else if (((dcm_cfg & DSIZE_MSK) >> 6) >= 6) {
248         os_printf("Warning L1C d cacheline size is reserved value\n");
249         dsize = 0;
250     } else {
251         dsize = 0;
252     }
253 
254     os_printf("The L1C DCache line size = %u\n", dsize);
255     if (dsize == 0) {
256         os_printf("This CPU doesn't have L1C DCache.\n");
257         return 0;
258     } else {
259         /* Enable L1C DCache */
260         // set_csr(NDS_MCACHE_CTL, (0x1 << 1));
261     }
262 
263     if (read_csr(NDS_MCACHE_CTL) & 0x1) {
264         os_printf("Enable L1C I cache\n");
265     }
266 
267     if (read_csr(NDS_MCACHE_CTL) & 0x2) {
268         os_printf("Enable L1C D cache\n");
269     }
270 
271     if (!(read_csr(NDS_MCACHE_CTL) & 0x3)) {
272         os_printf("Can't enable L1C I/D cache\n");
273     }
274 
275     return 1;
276 }
277 
flush_dcache(void * va,long size)278 void flush_dcache(void *va, long size)
279 {
280     // os_printf("I/D cache flush\n");
281 
282     if(read_csr(NDS_MMSC_CFG) & CCTLCSR_MSK) {
283         unsigned int i, tmp = 0, dsize = 0;
284 
285         dsize = (unsigned int)(1 << (((read_csr(NDS_MDCM_CFG) & DSIZE_MSK) >> 6) + 2));
286 
287         /* Check whether the CPU configured with CCTL auto-incremented feature. */
288         if ((read_csr(NDS_MMSC_CFG) & VCCTL_MSK)) {
289             unsigned long final_va = (unsigned long)(va + size);
290             unsigned long next_va = (unsigned long)va;
291 
292             /* Write only once at the beginning, it will be updated by CCTL command CSR write operation */
293             write_csr(NDS_MCCTLBEGINADDR, (unsigned long)va);
294 
295             /* L1C DCache write back and invalidate */
296             while (next_va < final_va) {
297                 /* Write back and invalid one cache line each time */
298                 write_csr(NDS_MCCTLCOMMAND, CCTL_L1D_VA_WBINVAL);
299 
300                 /* Read back from BEGINADDR csr for next va */
301                 next_va = read_csr(NDS_MCCTLBEGINADDR);
302             }
303 
304         } else {
305             /* L1C DCache write back and invalidate */
306             for (i = 0; tmp < size; i++) {
307                 /* Write back and invalid one cache line each time */
308                 write_csr(NDS_MCCTLBEGINADDR, (unsigned long)(va + (i * dsize)));
309                 tmp += dsize;
310                 write_csr(NDS_MCCTLCOMMAND, CCTL_L1D_VA_WBINVAL);
311             }
312         }
313 
314     } else {
315         /* FENCE.I go data writeback w/o data invalid but instruction invalid.
316            As src code is copied to dst and go to execute dst instruction,
317            you should use FENCE.I instead of FENCE */
318         __nds__fencei();
319     }
320 }
321 
flush_all_dcache(void)322 void flush_all_dcache(void) {
323     int i = 0;
324     for(i = 0; i < SRAM_BLOCK_COUNT; i++)
325     {
326         if(g_sram_addr_map[i] & 0x08000000) {
327             flush_dcache((void *)g_sram_addr_map[i], SRAM_BLOCK_SIZE);
328         }
329     }
330 }