1 From 307ba9e4d8fb0608566aacf88ab8cded5e20e005 Mon Sep 17 00:00:00 2001
2 From: John Crispin <blogic@openwrt.org>
3 Date: Thu, 29 Sep 2011 20:31:54 +0200
4 Subject: [PATCH 60/70] MIPS: lantiq: cache split
7 arch/mips/Kconfig | 22 ++++++
8 arch/mips/kernel/vpe.c | 66 ++++++++++++++++++
9 arch/mips/mm/c-r4k.c | 172 ++++++++++++++++++++++++++++++++++++++++++++++++
10 3 files changed, 260 insertions(+), 0 deletions(-)
12 diff --git a/arch/mips/Kconfig b/arch/mips/Kconfig
13 index 902aedb..12ee3df 100644
14 --- a/arch/mips/Kconfig
15 +++ b/arch/mips/Kconfig
16 @@ -1904,6 +1904,28 @@ config IFX_VPE_EXT
18 IFX included extensions in APRP
20 +config IFX_VPE_CACHE_SPLIT
21 + bool "IFX Cache Split Ways"
22 + depends on IFX_VPE_EXT
24 + IFX extension for reserving (splitting) cache ways among VPEs. You must
25 + give kernel command line arguments vpe_icache_shared=0 or
26 + vpe_dcache_shared=0 to enable splitting of icache or dcache
27 + respectively. Then you can specify which cache ways should be
28 + assigned to which VPE. There are total 8 cache ways, 4 each
29 + for dcache and icache: dcache_way0, dcache_way1,dcache_way2,
30 + dcache_way3 and icache_way0,icache_way1, icache_way2,icache_way3.
32 + For example, if you specify vpe_icache_shared=0 and icache_way2=1,
33 + then the 3rd icache way will be assigned to VPE0 and denied in VPE1.
35 + For icache, software is required to make at least one cache way available
36 + for a VPE at all times i.e., one can't assign all the icache ways to one
39 + By default, vpe_dcache_shared and vpe_icache_shared are set to 1
40 + (i.e., both icache and dcache are shared among VPEs)
43 bool "34K Performance counters"
44 depends on MIPS_MT && PROC_FS
45 diff --git a/arch/mips/kernel/vpe.c b/arch/mips/kernel/vpe.c
46 index e338ba5..0511d11 100644
47 --- a/arch/mips/kernel/vpe.c
48 +++ b/arch/mips/kernel/vpe.c
49 @@ -127,6 +127,13 @@ __setup("vpe1_wdog_timeout=", wdog_timeout);
50 EXPORT_SYMBOL(vpe1_wdog_timeout);
54 +#ifdef CONFIG_IFX_VPE_CACHE_SPLIT /* Code for splitting the cache ways among VPEs. */
55 +extern int vpe_icache_shared,vpe_dcache_shared;
56 +extern int icache_way0,icache_way1,icache_way2,icache_way3;
57 +extern int dcache_way0,dcache_way1,dcache_way2,dcache_way3;
60 /* grab the likely amount of memory we will need. */
61 #ifdef CONFIG_MIPS_VPE_LOADER_TOM
62 #define P_SIZE (2 * 1024 * 1024)
63 @@ -865,6 +872,65 @@ static int vpe_run(struct vpe * v)
65 write_vpe_c0_vpeconf0(read_vpe_c0_vpeconf0() | VPECONF0_VPA);
67 +#ifdef CONFIG_IFX_VPE_CACHE_SPLIT
68 + if ( (!vpe_icache_shared) || (!vpe_dcache_shared) ) {
70 + /* PCP bit must be 1 to split the cache */
71 + if(read_c0_mvpconf0() & MVPCONF0_PCP) {
73 + if ( !vpe_icache_shared ){
74 + write_vpe_c0_vpeconf0((read_vpe_c0_vpeconf0()) & ~VPECONF0_ICS);
77 + * If any cache way is 1, then that way is denied
78 + * in VPE1. Otherwise assign that way to VPE1.
81 + write_vpe_c0_vpeopt(read_vpe_c0_vpeopt() | VPEOPT_IWX0 );
83 + write_vpe_c0_vpeopt(read_vpe_c0_vpeopt() & ~VPEOPT_IWX0 );
85 + write_vpe_c0_vpeopt(read_vpe_c0_vpeopt() | VPEOPT_IWX1 );
87 + write_vpe_c0_vpeopt(read_vpe_c0_vpeopt() & ~VPEOPT_IWX1 );
89 + write_vpe_c0_vpeopt(read_vpe_c0_vpeopt() | VPEOPT_IWX2 );
91 + write_vpe_c0_vpeopt(read_vpe_c0_vpeopt() & ~VPEOPT_IWX2 );
93 + write_vpe_c0_vpeopt(read_vpe_c0_vpeopt() | VPEOPT_IWX3 );
95 + write_vpe_c0_vpeopt(read_vpe_c0_vpeopt() & ~VPEOPT_IWX3 );
98 + if ( !vpe_dcache_shared ) {
99 + write_vpe_c0_vpeconf0((read_vpe_c0_vpeconf0()) & ~VPECONF0_DCS);
102 + * If any cache way is 1, then that way is denied
103 + * in VPE1. Otherwise assign that way to VPE1.
106 + write_vpe_c0_vpeopt(read_vpe_c0_vpeopt() | VPEOPT_DWX0 );
108 + write_vpe_c0_vpeopt(read_vpe_c0_vpeopt() & ~VPEOPT_DWX0 );
110 + write_vpe_c0_vpeopt(read_vpe_c0_vpeopt() | VPEOPT_DWX1 );
112 + write_vpe_c0_vpeopt(read_vpe_c0_vpeopt() & ~VPEOPT_DWX1 );
114 + write_vpe_c0_vpeopt(read_vpe_c0_vpeopt() | VPEOPT_DWX2 );
116 + write_vpe_c0_vpeopt(read_vpe_c0_vpeopt() & ~VPEOPT_DWX2 );
118 + write_vpe_c0_vpeopt(read_vpe_c0_vpeopt() | VPEOPT_DWX3 );
120 + write_vpe_c0_vpeopt(read_vpe_c0_vpeopt() & ~VPEOPT_DWX3 );
124 +#endif /* endif CONFIG_IFX_VPE_CACHE_SPLIT */
126 /* clear out any left overs from a previous program */
127 write_vpe_c0_status(0);
128 write_vpe_c0_cause(0);
129 diff --git a/arch/mips/mm/c-r4k.c b/arch/mips/mm/c-r4k.c
130 index a79fe9a..94cb24f 100644
131 --- a/arch/mips/mm/c-r4k.c
132 +++ b/arch/mips/mm/c-r4k.c
133 @@ -1383,6 +1383,106 @@ static int __init setcoherentio(char *str)
134 __setup("coherentio", setcoherentio);
137 +#ifdef CONFIG_IFX_VPE_CACHE_SPLIT /* Code for splitting the cache ways among VPEs. */
139 +#include <asm/mipsmtregs.h>
142 + * By default, vpe_icache_shared and vpe_dcache_shared
143 + * values are 1 i.e., both icache and dcache are shared
147 +int vpe_icache_shared = 1;
148 +static int __init vpe_icache_shared_val(char *str)
150 + get_option(&str, &vpe_icache_shared);
153 +__setup("vpe_icache_shared=", vpe_icache_shared_val);
154 +EXPORT_SYMBOL(vpe_icache_shared);
156 +int vpe_dcache_shared = 1;
157 +static int __init vpe_dcache_shared_val(char *str)
159 + get_option(&str, &vpe_dcache_shared);
162 +__setup("vpe_dcache_shared=", vpe_dcache_shared_val);
163 +EXPORT_SYMBOL(vpe_dcache_shared);
166 + * Software is required to make atleast one icache
167 + * way available for a VPE at all times i.e., one
168 + * can't assign all the icache ways to one VPE.
171 +int icache_way0 = 0;
172 +static int __init icache_way0_val(char *str)
174 + get_option(&str, &icache_way0);
177 +__setup("icache_way0=", icache_way0_val);
179 +int icache_way1 = 0;
180 +static int __init icache_way1_val(char *str)
182 + get_option(&str, &icache_way1);
185 +__setup("icache_way1=", icache_way1_val);
187 +int icache_way2 = 0;
188 +static int __init icache_way2_val(char *str)
190 + get_option(&str, &icache_way2);
193 +__setup("icache_way2=", icache_way2_val);
195 +int icache_way3 = 0;
196 +static int __init icache_way3_val(char *str)
198 + get_option(&str, &icache_way3);
201 +__setup("icache_way3=", icache_way3_val);
203 +int dcache_way0 = 0;
204 +static int __init dcache_way0_val(char *str)
206 + get_option(&str, &dcache_way0);
209 +__setup("dcache_way0=", dcache_way0_val);
211 +int dcache_way1 = 0;
212 +static int __init dcache_way1_val(char *str)
214 + get_option(&str, &dcache_way1);
217 +__setup("dcache_way1=", dcache_way1_val);
219 +int dcache_way2 = 0;
220 +static int __init dcache_way2_val(char *str)
222 + get_option(&str, &dcache_way2);
225 +__setup("dcache_way2=", dcache_way2_val);
227 +int dcache_way3 = 0;
228 +static int __init dcache_way3_val(char *str)
230 + get_option(&str, &dcache_way3);
233 +__setup("dcache_way3=", dcache_way3_val);
235 +#endif /* endif CONFIG_IFX_VPE_CACHE_SPLIT */
237 void __cpuinit r4k_cache_init(void)
239 extern void build_clear_page(void);
240 @@ -1402,6 +1502,78 @@ void __cpuinit r4k_cache_init(void)
244 +#ifdef CONFIG_IFX_VPE_CACHE_SPLIT
246 + * We split the cache ways appropriately among the VPEs
247 + * based on cache ways values we received as command line
250 + if ( (!vpe_icache_shared) || (!vpe_dcache_shared) ){
252 + /* PCP bit must be 1 to split the cache */
253 + if(read_c0_mvpconf0() & MVPCONF0_PCP) {
255 + /* Set CPA bit which enables us to modify VPEOpt register */
256 + write_c0_mvpcontrol((read_c0_mvpcontrol()) | MVPCONTROL_CPA);
258 + if ( !vpe_icache_shared ){
259 + write_c0_vpeconf0((read_c0_vpeconf0()) & ~VPECONF0_ICS);
261 + * If any cache way is 1, then that way is denied
262 + * in VPE0. Otherwise assign that way to VPE0.
264 + printk(KERN_DEBUG "icache is split\n");
265 + printk(KERN_DEBUG "icache_way0=%d icache_way1=%d icache_way2=%d icache_way3=%d\n",
266 + icache_way0, icache_way1,icache_way2, icache_way3);
268 + write_c0_vpeopt(read_c0_vpeopt() | VPEOPT_IWX0 );
270 + write_c0_vpeopt(read_c0_vpeopt() & ~VPEOPT_IWX0 );
272 + write_c0_vpeopt(read_c0_vpeopt() | VPEOPT_IWX1 );
274 + write_c0_vpeopt(read_c0_vpeopt() & ~VPEOPT_IWX1 );
276 + write_c0_vpeopt(read_c0_vpeopt() | VPEOPT_IWX2 );
278 + write_c0_vpeopt(read_c0_vpeopt() & ~VPEOPT_IWX2 );
280 + write_c0_vpeopt(read_c0_vpeopt() | VPEOPT_IWX3 );
282 + write_c0_vpeopt(read_c0_vpeopt() & ~VPEOPT_IWX3 );
285 + if ( !vpe_dcache_shared ) {
287 + * If any cache way is 1, then that way is denied
288 + * in VPE0. Otherwise assign that way to VPE0.
290 + printk(KERN_DEBUG "dcache is split\n");
291 + printk(KERN_DEBUG "dcache_way0=%d dcache_way1=%d dcache_way2=%d dcache_way3=%d\n",
292 + dcache_way0, dcache_way1, dcache_way2, dcache_way3);
293 + write_c0_vpeconf0((read_c0_vpeconf0()) & ~VPECONF0_DCS);
295 + write_c0_vpeopt(read_c0_vpeopt() | VPEOPT_DWX0 );
297 + write_c0_vpeopt(read_c0_vpeopt() & ~VPEOPT_DWX0 );
299 + write_c0_vpeopt(read_c0_vpeopt() | VPEOPT_DWX1 );
301 + write_c0_vpeopt(read_c0_vpeopt() & ~VPEOPT_DWX1 );
303 + write_c0_vpeopt(read_c0_vpeopt() | VPEOPT_DWX2 );
305 + write_c0_vpeopt(read_c0_vpeopt() & ~VPEOPT_DWX2 );
307 + write_c0_vpeopt(read_c0_vpeopt() | VPEOPT_DWX3 );
309 + write_c0_vpeopt(read_c0_vpeopt() & ~VPEOPT_DWX3 );
314 +#endif /* endif CONFIG_IFX_VPE_CACHE_SPLIT */