xref: /linux/arch/openrisc/kernel/cacheinfo.c (revision ec0c2d5359e2f288d75d98465829d31c6d26da47)
1 // SPDX-License-Identifier: GPL-2.0-or-later
2 /*
3  * OpenRISC cacheinfo support
4  *
5  * Based on work done for MIPS and LoongArch. All original copyrights
6  * apply as per the original source declaration.
7  *
8  * OpenRISC implementation:
9  * Copyright (C) 2025 Sahil Siddiq <sahilcdq@proton.me>
10  */
11 
12 #include <linux/cacheinfo.h>
13 #include <asm/cpuinfo.h>
14 #include <asm/spr.h>
15 #include <asm/spr_defs.h>
16 
ci_leaf_init(struct cacheinfo * this_leaf,enum cache_type type,unsigned int level,struct cache_desc * cache,int cpu)17 static inline void ci_leaf_init(struct cacheinfo *this_leaf, enum cache_type type,
18 				unsigned int level, struct cache_desc *cache, int cpu)
19 {
20 	this_leaf->type = type;
21 	this_leaf->level = level;
22 	this_leaf->coherency_line_size = cache->block_size;
23 	this_leaf->number_of_sets = cache->sets;
24 	this_leaf->ways_of_associativity = cache->ways;
25 	this_leaf->size = cache->size;
26 	cpumask_set_cpu(cpu, &this_leaf->shared_cpu_map);
27 }
28 
init_cache_level(unsigned int cpu)29 int init_cache_level(unsigned int cpu)
30 {
31 	struct cpuinfo_or1k *cpuinfo = &cpuinfo_or1k[smp_processor_id()];
32 	struct cpu_cacheinfo *this_cpu_ci = get_cpu_cacheinfo(cpu);
33 	int leaves = 0, levels = 0;
34 	unsigned long upr = mfspr(SPR_UPR);
35 	unsigned long iccfgr, dccfgr;
36 
37 	if (!(upr & SPR_UPR_UP)) {
38 		printk(KERN_INFO
39 		       "-- no UPR register... unable to detect configuration\n");
40 		return -ENOENT;
41 	}
42 
43 	if (cpu_cache_is_present(SPR_UPR_DCP)) {
44 		dccfgr = mfspr(SPR_DCCFGR);
45 		cpuinfo->dcache.ways = 1 << (dccfgr & SPR_DCCFGR_NCW);
46 		cpuinfo->dcache.sets = 1 << ((dccfgr & SPR_DCCFGR_NCS) >> 3);
47 		cpuinfo->dcache.block_size = 16 << ((dccfgr & SPR_DCCFGR_CBS) >> 7);
48 		cpuinfo->dcache.size =
49 		    cpuinfo->dcache.sets * cpuinfo->dcache.ways * cpuinfo->dcache.block_size;
50 		leaves += 1;
51 		printk(KERN_INFO
52 		       "-- dcache: %d bytes total, %d bytes/line, %d set(s), %d way(s)\n",
53 		       cpuinfo->dcache.size, cpuinfo->dcache.block_size,
54 		       cpuinfo->dcache.sets, cpuinfo->dcache.ways);
55 	} else
56 		printk(KERN_INFO "-- dcache disabled\n");
57 
58 	if (cpu_cache_is_present(SPR_UPR_ICP)) {
59 		iccfgr = mfspr(SPR_ICCFGR);
60 		cpuinfo->icache.ways = 1 << (iccfgr & SPR_ICCFGR_NCW);
61 		cpuinfo->icache.sets = 1 << ((iccfgr & SPR_ICCFGR_NCS) >> 3);
62 		cpuinfo->icache.block_size = 16 << ((iccfgr & SPR_ICCFGR_CBS) >> 7);
63 		cpuinfo->icache.size =
64 		    cpuinfo->icache.sets * cpuinfo->icache.ways * cpuinfo->icache.block_size;
65 		leaves += 1;
66 		printk(KERN_INFO
67 		       "-- icache: %d bytes total, %d bytes/line, %d set(s), %d way(s)\n",
68 		       cpuinfo->icache.size, cpuinfo->icache.block_size,
69 		       cpuinfo->icache.sets, cpuinfo->icache.ways);
70 	} else
71 		printk(KERN_INFO "-- icache disabled\n");
72 
73 	if (!leaves)
74 		return -ENOENT;
75 
76 	levels = 1;
77 
78 	this_cpu_ci->num_leaves = leaves;
79 	this_cpu_ci->num_levels = levels;
80 
81 	return 0;
82 }
83 
populate_cache_leaves(unsigned int cpu)84 int populate_cache_leaves(unsigned int cpu)
85 {
86 	struct cpuinfo_or1k *cpuinfo = &cpuinfo_or1k[smp_processor_id()];
87 	struct cpu_cacheinfo *this_cpu_ci = get_cpu_cacheinfo(cpu);
88 	struct cacheinfo *this_leaf = this_cpu_ci->info_list;
89 	int level = 1;
90 
91 	if (cpu_cache_is_present(SPR_UPR_DCP)) {
92 		ci_leaf_init(this_leaf, CACHE_TYPE_DATA, level, &cpuinfo->dcache, cpu);
93 		this_leaf->attributes = ((mfspr(SPR_DCCFGR) & SPR_DCCFGR_CWS) >> 8) ?
94 					CACHE_WRITE_BACK : CACHE_WRITE_THROUGH;
95 		this_leaf++;
96 	}
97 
98 	if (cpu_cache_is_present(SPR_UPR_ICP))
99 		ci_leaf_init(this_leaf, CACHE_TYPE_INST, level, &cpuinfo->icache, cpu);
100 
101 	this_cpu_ci->cpu_map_populated = true;
102 
103 	return 0;
104 }
105