]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - sys/arm/arm/cpufunc.c
Remove remaining fragments of code for older already ceased ARM versions.
[FreeBSD/FreeBSD.git] / sys / arm / arm / cpufunc.c
1 /*      $NetBSD: cpufunc.c,v 1.65 2003/11/05 12:53:15 scw Exp $ */
2
3 /*-
4  * SPDX-License-Identifier: BSD-4-Clause
5  *
6  * arm9 support code Copyright (C) 2001 ARM Ltd
7  * Copyright (c) 1997 Mark Brinicombe.
8  * Copyright (c) 1997 Causality Limited
9  * All rights reserved.
10  *
11  * Redistribution and use in source and binary forms, with or without
12  * modification, are permitted provided that the following conditions
13  * are met:
14  * 1. Redistributions of source code must retain the above copyright
15  *    notice, this list of conditions and the following disclaimer.
16  * 2. Redistributions in binary form must reproduce the above copyright
17  *    notice, this list of conditions and the following disclaimer in the
18  *    documentation and/or other materials provided with the distribution.
19  * 3. All advertising materials mentioning features or use of this software
20  *    must display the following acknowledgement:
21  *      This product includes software developed by Causality Limited.
22  * 4. The name of Causality Limited may not be used to endorse or promote
23  *    products derived from this software without specific prior written
24  *    permission.
25  *
26  * THIS SOFTWARE IS PROVIDED BY CAUSALITY LIMITED ``AS IS'' AND ANY EXPRESS
27  * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
28  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
29  * DISCLAIMED. IN NO EVENT SHALL CAUSALITY LIMITED BE LIABLE FOR ANY DIRECT,
30  * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
31  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
32  * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
33  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
34  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
35  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
36  * SUCH DAMAGE.
37  *
38  * RiscBSD kernel project
39  *
40  * cpufuncs.c
41  *
42  * C functions for supporting CPU / MMU / TLB specific operations.
43  *
44  * Created      : 30/01/97
45  */
46 #include <sys/cdefs.h>
47 __FBSDID("$FreeBSD$");
48
49 #include <sys/param.h>
50 #include <sys/systm.h>
51 #include <sys/lock.h>
52 #include <sys/mutex.h>
53 #include <sys/bus.h>
54 #include <machine/bus.h>
55 #include <machine/cpu.h>
56 #include <machine/disassem.h>
57
58 #include <vm/vm.h>
59 #include <vm/pmap.h>
60 #include <vm/uma.h>
61
62 #include <machine/cpufunc.h>
63
64 /* PRIMARY CACHE VARIABLES */
65 int     arm_picache_size;
66 int     arm_picache_line_size;
67 int     arm_picache_ways;
68
69 int     arm_pdcache_size;       /* and unified */
70 int     arm_pdcache_line_size;
71 int     arm_pdcache_ways;
72
73 int     arm_pcache_type;
74 int     arm_pcache_unified;
75
76 int     arm_dcache_align;
77 int     arm_dcache_align_mask;
78
79 u_int   arm_cache_level;
80 u_int   arm_cache_type[14];
81 u_int   arm_cache_loc;
82
83 #ifdef CPU_MV_PJ4B
84 static void pj4bv7_setup(void);
85 #endif
86 #if defined(CPU_ARM1176)
87 static void arm11x6_setup(void);
88 #endif
89 #if defined(CPU_CORTEXA) || defined(CPU_KRAIT)
90 static void cortexa_setup(void);
91 #endif
92
93 #ifdef CPU_MV_PJ4B
94 struct cpu_functions pj4bv7_cpufuncs = {
95         /* Cache operations */
96         .cf_l2cache_wbinv_all = (void *)cpufunc_nullop,
97         .cf_l2cache_wbinv_range = (void *)cpufunc_nullop,
98         .cf_l2cache_inv_range = (void *)cpufunc_nullop,
99         .cf_l2cache_wb_range = (void *)cpufunc_nullop,
100         .cf_l2cache_drain_writebuf = (void *)cpufunc_nullop,
101
102         /* Other functions */
103         .cf_sleep = (void *)cpufunc_nullop,
104
105         /* Soft functions */
106         .cf_setup = pj4bv7_setup
107 };
108 #endif /* CPU_MV_PJ4B */
109
110 #if defined(CPU_ARM1176)
111 struct cpu_functions arm1176_cpufuncs = {
112         /* Cache operations */
113         .cf_l2cache_wbinv_all = (void *)cpufunc_nullop,
114         .cf_l2cache_wbinv_range = (void *)cpufunc_nullop,
115         .cf_l2cache_inv_range = (void *)cpufunc_nullop,
116         .cf_l2cache_wb_range = (void *)cpufunc_nullop,
117         .cf_l2cache_drain_writebuf = (void *)cpufunc_nullop,
118
119         /* Other functions */
120         .cf_sleep = arm11x6_sleep, 
121
122         /* Soft functions */
123         .cf_setup = arm11x6_setup
124 };
125 #endif /*CPU_ARM1176 */
126
127 #if defined(CPU_CORTEXA) || defined(CPU_KRAIT)
128 struct cpu_functions cortexa_cpufuncs = {
129         /* Cache operations */
130
131         /*
132          * Note: For CPUs using the PL310 the L2 ops are filled in when the
133          * L2 cache controller is actually enabled.
134          */
135         .cf_l2cache_wbinv_all = cpufunc_nullop,
136         .cf_l2cache_wbinv_range = (void *)cpufunc_nullop,
137         .cf_l2cache_inv_range = (void *)cpufunc_nullop,
138         .cf_l2cache_wb_range = (void *)cpufunc_nullop,
139         .cf_l2cache_drain_writebuf = (void *)cpufunc_nullop,
140
141         /* Other functions */
142         .cf_sleep = armv7_cpu_sleep,
143
144         /* Soft functions */
145         .cf_setup = cortexa_setup
146 };
147 #endif /* CPU_CORTEXA || CPU_KRAIT */
148
149 /*
150  * Global constants also used by locore.s
151  */
152
153 struct cpu_functions cpufuncs;
154 u_int cputype;
155
156 static void get_cachetype_cp15(void);
157
158 /* Additional cache information local to this file.  Log2 of some of the
159    above numbers.  */
160 static int      arm_dcache_l2_nsets;
161 static int      arm_dcache_l2_assoc;
162 static int      arm_dcache_l2_linesize;
163
164 static void
165 get_cachetype_cp15(void)
166 {
167         u_int ctype, isize, dsize, cpuid;
168         u_int clevel, csize, i, sel;
169         u_int multiplier;
170         u_char type;
171
172         ctype = cp15_ctr_get();
173         cpuid = cp15_midr_get();
174         /*
175          * ...and thus spake the ARM ARM:
176          *
177          * If an <opcode2> value corresponding to an unimplemented or
178          * reserved ID register is encountered, the System Control
179          * processor returns the value of the main ID register.
180          */
181         if (ctype == cpuid)
182                 goto out;
183
184         if (CPU_CT_FORMAT(ctype) == CPU_CT_ARMV7) {
185                 __asm __volatile("mrc p15, 1, %0, c0, c0, 1"
186                     : "=r" (clevel));
187                 arm_cache_level = clevel;
188                 arm_cache_loc = CPU_CLIDR_LOC(arm_cache_level);
189                 i = 0;
190                 while ((type = (clevel & 0x7)) && i < 7) {
191                         if (type == CACHE_DCACHE || type == CACHE_UNI_CACHE ||
192                             type == CACHE_SEP_CACHE) {
193                                 sel = i << 1;
194                                 __asm __volatile("mcr p15, 2, %0, c0, c0, 0"
195                                     : : "r" (sel));
196                                 __asm __volatile("mrc p15, 1, %0, c0, c0, 0"
197                                     : "=r" (csize));
198                                 arm_cache_type[sel] = csize;
199                                 arm_dcache_align = 1 <<
200                                     (CPUV7_CT_xSIZE_LEN(csize) + 4);
201                                 arm_dcache_align_mask = arm_dcache_align - 1;
202                         }
203                         if (type == CACHE_ICACHE || type == CACHE_SEP_CACHE) {
204                                 sel = (i << 1) | 1;
205                                 __asm __volatile("mcr p15, 2, %0, c0, c0, 0"
206                                     : : "r" (sel));
207                                 __asm __volatile("mrc p15, 1, %0, c0, c0, 0"
208                                     : "=r" (csize));
209                                 arm_cache_type[sel] = csize;
210                         }
211                         i++;
212                         clevel >>= 3;
213                 }
214         } else {
215                 if ((ctype & CPU_CT_S) == 0)
216                         arm_pcache_unified = 1;
217
218                 /*
219                  * If you want to know how this code works, go read the ARM ARM.
220                  */
221
222                 arm_pcache_type = CPU_CT_CTYPE(ctype);
223
224                 if (arm_pcache_unified == 0) {
225                         isize = CPU_CT_ISIZE(ctype);
226                         multiplier = (isize & CPU_CT_xSIZE_M) ? 3 : 2;
227                         arm_picache_line_size = 1U << (CPU_CT_xSIZE_LEN(isize) + 3);
228                         if (CPU_CT_xSIZE_ASSOC(isize) == 0) {
229                                 if (isize & CPU_CT_xSIZE_M)
230                                         arm_picache_line_size = 0; /* not present */
231                                 else
232                                         arm_picache_ways = 1;
233                         } else {
234                                 arm_picache_ways = multiplier <<
235                                     (CPU_CT_xSIZE_ASSOC(isize) - 1);
236                         }
237                         arm_picache_size = multiplier << (CPU_CT_xSIZE_SIZE(isize) + 8);
238                 }
239
240                 dsize = CPU_CT_DSIZE(ctype);
241                 multiplier = (dsize & CPU_CT_xSIZE_M) ? 3 : 2;
242                 arm_pdcache_line_size = 1U << (CPU_CT_xSIZE_LEN(dsize) + 3);
243                 if (CPU_CT_xSIZE_ASSOC(dsize) == 0) {
244                         if (dsize & CPU_CT_xSIZE_M)
245                                 arm_pdcache_line_size = 0; /* not present */
246                         else
247                                 arm_pdcache_ways = 1;
248                 } else {
249                         arm_pdcache_ways = multiplier <<
250                             (CPU_CT_xSIZE_ASSOC(dsize) - 1);
251                 }
252                 arm_pdcache_size = multiplier << (CPU_CT_xSIZE_SIZE(dsize) + 8);
253
254                 arm_dcache_align = arm_pdcache_line_size;
255
256                 arm_dcache_l2_assoc = CPU_CT_xSIZE_ASSOC(dsize) + multiplier - 2;
257                 arm_dcache_l2_linesize = CPU_CT_xSIZE_LEN(dsize) + 3;
258                 arm_dcache_l2_nsets = 6 + CPU_CT_xSIZE_SIZE(dsize) -
259                     CPU_CT_xSIZE_ASSOC(dsize) - CPU_CT_xSIZE_LEN(dsize);
260
261         out:
262                 arm_dcache_align_mask = arm_dcache_align - 1;
263         }
264 }
265
266 /*
267  * Cannot panic here as we may not have a console yet ...
268  */
269
270 int
271 set_cpufuncs(void)
272 {
273         cputype = cp15_midr_get();
274         cputype &= CPU_ID_CPU_MASK;
275
276 #if defined(CPU_ARM1176)
277         if (cputype == CPU_ID_ARM1176JZS) {
278                 cpufuncs = arm1176_cpufuncs;
279                 get_cachetype_cp15();
280                 goto out;
281         }
282 #endif /* CPU_ARM1176 */
283 #if defined(CPU_CORTEXA) || defined(CPU_KRAIT)
284         switch(cputype & CPU_ID_SCHEME_MASK) {
285         case CPU_ID_CORTEXA5:
286         case CPU_ID_CORTEXA7:
287         case CPU_ID_CORTEXA8:
288         case CPU_ID_CORTEXA9:
289         case CPU_ID_CORTEXA12:
290         case CPU_ID_CORTEXA15:
291         case CPU_ID_CORTEXA53:
292         case CPU_ID_CORTEXA57:
293         case CPU_ID_CORTEXA72:
294         case CPU_ID_KRAIT300:
295                 cpufuncs = cortexa_cpufuncs;
296                 get_cachetype_cp15();
297                 goto out;
298         default:
299                 break;
300         }
301 #endif /* CPU_CORTEXA || CPU_KRAIT */
302
303 #if defined(CPU_MV_PJ4B)
304         if (cputype == CPU_ID_MV88SV581X_V7 ||
305             cputype == CPU_ID_MV88SV584X_V7 ||
306             cputype == CPU_ID_ARM_88SV581X_V7) {
307                 cpufuncs = pj4bv7_cpufuncs;
308                 get_cachetype_cp15();
309                 goto out;
310         }
311 #endif /* CPU_MV_PJ4B */
312
313         /*
314          * Bzzzz. And the answer was ...
315          */
316         panic("No support for this CPU type (%08x) in kernel", cputype);
317         return(ARCHITECTURE_NOT_PRESENT);
318 out:
319         uma_set_align(arm_dcache_align_mask);
320         return (0);
321 }
322
323 /*
324  * CPU Setup code
325  */
326
327
328 #if defined(CPU_ARM1176) \
329  || defined(CPU_MV_PJ4B) \
330  || defined(CPU_CORTEXA) || defined(CPU_KRAIT)
331 static __inline void
332 cpu_scc_setup_ccnt(void)
333 {
334 /* This is how you give userland access to the CCNT and PMCn
335  * registers.
336  * BEWARE! This gives write access also, which may not be what
337  * you want!
338  */
339 #ifdef _PMC_USER_READ_WRITE_
340         /* Set PMUSERENR[0] to allow userland access */
341         cp15_pmuserenr_set(1);
342 #endif
343 #if defined(CPU_ARM1176)
344         /* Set PMCR[2,0] to enable counters and reset CCNT */
345         cp15_pmcr_set(5);
346 #else
347         /* Set up the PMCCNTR register as a cyclecounter:
348          * Set PMINTENCLR to 0xFFFFFFFF to block interrupts
349          * Set PMCR[2,0] to enable counters and reset CCNT
350          * Set PMCNTENSET to 0x80000000 to enable CCNT */
351         cp15_pminten_clr(0xFFFFFFFF);
352         cp15_pmcr_set(5);
353         cp15_pmcnten_set(0x80000000);
354 #endif
355 }
356 #endif
357
358 #if defined(CPU_ARM1176)
359 static void
360 arm11x6_setup(void)
361 {
362         uint32_t auxctrl, auxctrl_wax;
363         uint32_t tmp, tmp2;
364         uint32_t cpuid;
365
366         cpuid = cp15_midr_get();
367
368         auxctrl = 0;
369         auxctrl_wax = ~0;
370
371         /*
372          * Enable an errata workaround
373          */
374         if ((cpuid & CPU_ID_CPU_MASK) == CPU_ID_ARM1176JZS) { /* ARM1176JZSr0 */
375                 auxctrl = ARM1176_AUXCTL_PHD;
376                 auxctrl_wax = ~ARM1176_AUXCTL_PHD;
377         }
378
379         tmp = cp15_actlr_get();
380         tmp2 = tmp;
381         tmp &= auxctrl_wax;
382         tmp |= auxctrl;
383         if (tmp != tmp2)
384                 cp15_actlr_set(tmp);
385
386         cpu_scc_setup_ccnt();
387 }
388 #endif  /* CPU_ARM1176 */
389
390 #ifdef CPU_MV_PJ4B
391 static void
392 pj4bv7_setup(void)
393 {
394
395         pj4b_config();
396         cpu_scc_setup_ccnt();
397 }
398 #endif /* CPU_MV_PJ4B */
399
400 #if defined(CPU_CORTEXA) || defined(CPU_KRAIT)
401 static void
402 cortexa_setup(void)
403 {
404
405         cpu_scc_setup_ccnt();
406 }
407 #endif  /* CPU_CORTEXA || CPU_KRAIT */