0001
0002
0003
0004
0005
0006
0007
0008
0009 #include <linux/acpi.h>
0010 #include <linux/cacheinfo.h>
0011 #include <linux/of.h>
0012
0013 #define MAX_CACHE_LEVEL 7
0014
0015 #define CLIDR_CTYPE_SHIFT(level) (3 * (level - 1))
0016 #define CLIDR_CTYPE_MASK(level) (7 << CLIDR_CTYPE_SHIFT(level))
0017 #define CLIDR_CTYPE(clidr, level) \
0018 (((clidr) & CLIDR_CTYPE_MASK(level)) >> CLIDR_CTYPE_SHIFT(level))
0019
0020 int cache_line_size(void)
0021 {
0022 if (coherency_max_size != 0)
0023 return coherency_max_size;
0024
0025 return cache_line_size_of_cpu();
0026 }
0027 EXPORT_SYMBOL_GPL(cache_line_size);
0028
0029 static inline enum cache_type get_cache_type(int level)
0030 {
0031 u64 clidr;
0032
0033 if (level > MAX_CACHE_LEVEL)
0034 return CACHE_TYPE_NOCACHE;
0035 clidr = read_sysreg(clidr_el1);
0036 return CLIDR_CTYPE(clidr, level);
0037 }
0038
0039 static void ci_leaf_init(struct cacheinfo *this_leaf,
0040 enum cache_type type, unsigned int level)
0041 {
0042 this_leaf->level = level;
0043 this_leaf->type = type;
0044 }
0045
0046 int init_cache_level(unsigned int cpu)
0047 {
0048 unsigned int ctype, level, leaves;
0049 int fw_level;
0050 struct cpu_cacheinfo *this_cpu_ci = get_cpu_cacheinfo(cpu);
0051
0052 for (level = 1, leaves = 0; level <= MAX_CACHE_LEVEL; level++) {
0053 ctype = get_cache_type(level);
0054 if (ctype == CACHE_TYPE_NOCACHE) {
0055 level--;
0056 break;
0057 }
0058
0059 leaves += (ctype == CACHE_TYPE_SEPARATE) ? 2 : 1;
0060 }
0061
0062 if (acpi_disabled)
0063 fw_level = of_find_last_cache_level(cpu);
0064 else
0065 fw_level = acpi_find_last_cache_level(cpu);
0066
0067 if (fw_level < 0)
0068 return fw_level;
0069
0070 if (level < fw_level) {
0071
0072
0073
0074
0075
0076 leaves += (fw_level - level);
0077 level = fw_level;
0078 }
0079
0080 this_cpu_ci->num_levels = level;
0081 this_cpu_ci->num_leaves = leaves;
0082 return 0;
0083 }
0084
0085 int populate_cache_leaves(unsigned int cpu)
0086 {
0087 unsigned int level, idx;
0088 enum cache_type type;
0089 struct cpu_cacheinfo *this_cpu_ci = get_cpu_cacheinfo(cpu);
0090 struct cacheinfo *this_leaf = this_cpu_ci->info_list;
0091
0092 for (idx = 0, level = 1; level <= this_cpu_ci->num_levels &&
0093 idx < this_cpu_ci->num_leaves; idx++, level++) {
0094 type = get_cache_type(level);
0095 if (type == CACHE_TYPE_SEPARATE) {
0096 ci_leaf_init(this_leaf++, CACHE_TYPE_DATA, level);
0097 ci_leaf_init(this_leaf++, CACHE_TYPE_INST, level);
0098 } else {
0099 ci_leaf_init(this_leaf++, type, level);
0100 }
0101 }
0102 return 0;
0103 }