c271c7cf37fd120b8d23d78624d45e5e5b3013b5
[fw/openocd] / src / target / armv4_5_cache.c
1 /* SPDX-License-Identifier: GPL-2.0-or-later */
2
3 /***************************************************************************
4  *   Copyright (C) 2005 by Dominic Rath                                    *
5  *   Dominic.Rath@gmx.de                                                   *
6  ***************************************************************************/
7
8 #ifdef HAVE_CONFIG_H
9 #include "config.h"
10 #endif
11
12 #include "armv4_5_cache.h"
13 #include <helper/log.h>
14
15 int armv4_5_identify_cache(uint32_t cache_type_reg, struct armv4_5_cache_common *cache)
16 {
17         int size, assoc, M, len, multiplier;
18
19         cache->ctype = (cache_type_reg & 0x1e000000U) >> 25;
20         cache->separate = (cache_type_reg & 0x01000000U) >> 24;
21
22         size = (cache_type_reg & 0x1c0000) >> 18;
23         assoc = (cache_type_reg & 0x38000) >> 15;
24         M = (cache_type_reg & 0x4000) >> 14;
25         len = (cache_type_reg & 0x3000) >> 12;
26         multiplier = 2 + M;
27
28         if ((assoc != 0) || (M != 1)) /* assoc 0 and M 1 means cache absent */ {
29                 /* cache is present */
30                 cache->d_u_size.linelen = 1 << (len + 3);
31                 cache->d_u_size.associativity = multiplier << (assoc - 1);
32                 cache->d_u_size.nsets = 1 << (size + 6 - assoc - len);
33                 cache->d_u_size.cachesize = multiplier << (size + 8);
34         } else {
35                 /* cache is absent */
36                 cache->d_u_size.linelen = -1;
37                 cache->d_u_size.associativity = -1;
38                 cache->d_u_size.nsets = -1;
39                 cache->d_u_size.cachesize = -1;
40         }
41
42         if (cache->separate) {
43                 size = (cache_type_reg & 0x1c0) >> 6;
44                 assoc = (cache_type_reg & 0x38) >> 3;
45                 M = (cache_type_reg & 0x4) >> 2;
46                 len = (cache_type_reg & 0x3);
47                 multiplier = 2 + M;
48
49                 if ((assoc != 0) || (M != 1)) /* assoc 0 and M 1 means cache absent */ {
50                         /* cache is present */
51                         cache->i_size.linelen = 1 << (len + 3);
52                         cache->i_size.associativity = multiplier << (assoc - 1);
53                         cache->i_size.nsets = 1 << (size + 6 - assoc - len);
54                         cache->i_size.cachesize = multiplier << (size + 8);
55                 } else {
56                         /* cache is absent */
57                         cache->i_size.linelen = -1;
58                         cache->i_size.associativity = -1;
59                         cache->i_size.nsets = -1;
60                         cache->i_size.cachesize = -1;
61                 }
62         } else
63                 cache->i_size = cache->d_u_size;
64
65         return ERROR_OK;
66 }
67
68 int armv4_5_handle_cache_info_command(struct command_invocation *cmd, struct armv4_5_cache_common *armv4_5_cache)
69 {
70         if (armv4_5_cache->ctype == -1) {
71                 command_print(cmd, "cache not yet identified");
72                 return ERROR_OK;
73         }
74
75         command_print(cmd, "cache type: 0x%1.1x, %s", armv4_5_cache->ctype,
76                 (armv4_5_cache->separate) ? "separate caches" : "unified cache");
77
78         command_print(cmd, "D-Cache: linelen %i, associativity %i, nsets %i, cachesize 0x%x",
79                 armv4_5_cache->d_u_size.linelen,
80                 armv4_5_cache->d_u_size.associativity,
81                 armv4_5_cache->d_u_size.nsets,
82                 armv4_5_cache->d_u_size.cachesize);
83
84         command_print(cmd, "I-Cache: linelen %i, associativity %i, nsets %i, cachesize 0x%x",
85                 armv4_5_cache->i_size.linelen,
86                 armv4_5_cache->i_size.associativity,
87                 armv4_5_cache->i_size.nsets,
88                 armv4_5_cache->i_size.cachesize);
89
90         return ERROR_OK;
91 }