hc
2024-05-10 37f49e37ab4cb5d0bc4c60eb5c6d4dd57db767bb
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
/* SPDX-License-Identifier: GPL-2.0-or-later */
/*
 * This file contains low level CPU setup functions.
 * Kumar Gala <galak@kernel.crashing.org>
 * Copyright 2009 Freescale Semiconductor, Inc.
 *
 * Based on cpu_setup_6xx code by
 * Benjamin Herrenschmidt <benh@kernel.crashing.org>
 */
 
#include <asm/page.h>
#include <asm/processor.h>
#include <asm/cputable.h>
#include <asm/ppc_asm.h>
#include <asm/nohash/mmu-book3e.h>
#include <asm/asm-offsets.h>
#include <asm/mpc85xx.h>
 
_GLOBAL(__e500_icache_setup)
   mfspr    r0, SPRN_L1CSR1
   andi.    r3, r0, L1CSR1_ICE
   bnelr                /* Already enabled */
   oris    r0, r0, L1CSR1_CPE@h
   ori    r0, r0, (L1CSR1_ICFI | L1CSR1_ICLFR |  L1CSR1_ICE)
   mtspr    SPRN_L1CSR1, r0        /* Enable I-Cache */
   isync
   blr
 
_GLOBAL(__e500_dcache_setup)
   mfspr    r0, SPRN_L1CSR0
   andi.    r3, r0, L1CSR0_DCE
   bnelr                /* Already enabled */
   msync
   isync
   li    r0, 0
   mtspr    SPRN_L1CSR0, r0        /* Disable */
   msync
   isync
   li    r0, (L1CSR0_DCFI | L1CSR0_CLFC)
   mtspr    SPRN_L1CSR0, r0        /* Invalidate */
   isync
1:    mfspr    r0, SPRN_L1CSR0
   andi.    r3, r0, L1CSR0_CLFC
   bne+    1b            /* Wait for lock bits reset */
   oris    r0, r0, L1CSR0_CPE@h
   ori    r0, r0, L1CSR0_DCE
   msync
   isync
   mtspr    SPRN_L1CSR0, r0        /* Enable */
   isync
   blr
 
/*
 * FIXME - we haven't yet done testing to determine a reasonable default
 * value for PW20_WAIT_IDLE_BIT.
 */
#define PW20_WAIT_IDLE_BIT        50 /* 1ms, TB frequency is 41.66MHZ */
_GLOBAL(setup_pw20_idle)
   mfspr    r3, SPRN_PWRMGTCR0
 
   /* Set PW20_WAIT bit, enable pw20 state*/
   ori    r3, r3, PWRMGTCR0_PW20_WAIT
   li    r11, PW20_WAIT_IDLE_BIT
 
   /* Set Automatic PW20 Core Idle Count */
   rlwimi    r3, r11, PWRMGTCR0_PW20_ENT_SHIFT, PWRMGTCR0_PW20_ENT
 
   mtspr    SPRN_PWRMGTCR0, r3
 
   blr
 
/*
 * FIXME - we haven't yet done testing to determine a reasonable default
 * value for AV_WAIT_IDLE_BIT.
 */
#define AV_WAIT_IDLE_BIT        50 /* 1ms, TB frequency is 41.66MHZ */
_GLOBAL(setup_altivec_idle)
   mfspr    r3, SPRN_PWRMGTCR0
 
   /* Enable Altivec Idle */
   oris    r3, r3, PWRMGTCR0_AV_IDLE_PD_EN@h
   li    r11, AV_WAIT_IDLE_BIT
 
   /* Set Automatic AltiVec Idle Count */
   rlwimi    r3, r11, PWRMGTCR0_AV_IDLE_CNT_SHIFT, PWRMGTCR0_AV_IDLE_CNT
 
   mtspr    SPRN_PWRMGTCR0, r3
 
   blr
 
#ifdef CONFIG_PPC_E500MC
_GLOBAL(__setup_cpu_e6500)
   mflr    r6
#ifdef CONFIG_PPC64
   bl    setup_altivec_ivors
   /* Touch IVOR42 only if the CPU supports E.HV category */
   mfspr    r10,SPRN_MMUCFG
   rlwinm.    r10,r10,0,MMUCFG_LPIDSIZE
   beq    1f
   bl    setup_lrat_ivor
1:
#endif
   bl    setup_pw20_idle
   bl    setup_altivec_idle
   bl    __setup_cpu_e5500
   mtlr    r6
   blr
#endif /* CONFIG_PPC_E500MC */
 
#ifdef CONFIG_PPC32
#ifdef CONFIG_E200
_GLOBAL(__setup_cpu_e200)
   /* enable dedicated debug exception handling resources (Debug APU) */
   mfspr    r3,SPRN_HID0
   ori    r3,r3,HID0_DAPUEN@l
   mtspr    SPRN_HID0,r3
   b    __setup_e200_ivors
#endif /* CONFIG_E200 */
 
#ifdef CONFIG_E500
#ifndef CONFIG_PPC_E500MC
_GLOBAL(__setup_cpu_e500v1)
_GLOBAL(__setup_cpu_e500v2)
   mflr    r4
   bl    __e500_icache_setup
   bl    __e500_dcache_setup
   bl    __setup_e500_ivors
#if defined(CONFIG_FSL_RIO) || defined(CONFIG_FSL_PCI)
   /* Ensure that RFXE is set */
   mfspr    r3,SPRN_HID1
   oris    r3,r3,HID1_RFXE@h
   mtspr    SPRN_HID1,r3
#endif
   mtlr    r4
   blr
#else /* CONFIG_PPC_E500MC */
_GLOBAL(__setup_cpu_e500mc)
_GLOBAL(__setup_cpu_e5500)
   mflr    r5
   bl    __e500_icache_setup
   bl    __e500_dcache_setup
   bl    __setup_e500mc_ivors
   /*
    * We only want to touch IVOR38-41 if we're running on hardware
    * that supports category E.HV.  The architectural way to determine
    * this is MMUCFG[LPIDSIZE].
    */
   mfspr    r3, SPRN_MMUCFG
   rlwinm.    r3, r3, 0, MMUCFG_LPIDSIZE
   beq    1f
   bl    __setup_ehv_ivors
   b    2f
1:
   lwz    r3, CPU_SPEC_FEATURES(r4)
   /* We need this check as cpu_setup is also called for
    * the secondary cores. So, if we have already cleared
    * the feature on the primary core, avoid doing it on the
    * secondary core.
    */
   andi.    r6, r3, CPU_FTR_EMB_HV
   beq    2f
   rlwinm    r3, r3, 0, ~CPU_FTR_EMB_HV
   stw    r3, CPU_SPEC_FEATURES(r4)
2:
   mtlr    r5
   blr
#endif /* CONFIG_PPC_E500MC */
#endif /* CONFIG_E500 */
#endif /* CONFIG_PPC32 */
 
#ifdef CONFIG_PPC_BOOK3E_64
_GLOBAL(__restore_cpu_e6500)
   mflr    r5
   bl    setup_altivec_ivors
   /* Touch IVOR42 only if the CPU supports E.HV category */
   mfspr    r10,SPRN_MMUCFG
   rlwinm.    r10,r10,0,MMUCFG_LPIDSIZE
   beq    1f
   bl    setup_lrat_ivor
1:
   bl    setup_pw20_idle
   bl    setup_altivec_idle
   bl    __restore_cpu_e5500
   mtlr    r5
   blr
 
_GLOBAL(__restore_cpu_e5500)
   mflr    r4
   bl    __e500_icache_setup
   bl    __e500_dcache_setup
   bl    __setup_base_ivors
   bl    setup_perfmon_ivor
   bl    setup_doorbell_ivors
   /*
    * We only want to touch IVOR38-41 if we're running on hardware
    * that supports category E.HV.  The architectural way to determine
    * this is MMUCFG[LPIDSIZE].
    */
   mfspr    r10,SPRN_MMUCFG
   rlwinm.    r10,r10,0,MMUCFG_LPIDSIZE
   beq    1f
   bl    setup_ehv_ivors
1:
   mtlr    r4
   blr
 
_GLOBAL(__setup_cpu_e5500)
   mflr    r5
   bl    __e500_icache_setup
   bl    __e500_dcache_setup
   bl    __setup_base_ivors
   bl    setup_perfmon_ivor
   bl    setup_doorbell_ivors
   /*
    * We only want to touch IVOR38-41 if we're running on hardware
    * that supports category E.HV.  The architectural way to determine
    * this is MMUCFG[LPIDSIZE].
    */
   mfspr    r10,SPRN_MMUCFG
   rlwinm.    r10,r10,0,MMUCFG_LPIDSIZE
   beq    1f
   bl    setup_ehv_ivors
   b    2f
1:
   ld    r10,CPU_SPEC_FEATURES(r4)
   LOAD_REG_IMMEDIATE(r9,CPU_FTR_EMB_HV)
   andc    r10,r10,r9
   std    r10,CPU_SPEC_FEATURES(r4)
2:
   mtlr    r5
   blr
#endif
 
/* flush L1 data cache, it can apply to e500v2, e500mc and e5500 */
_GLOBAL(flush_dcache_L1)
   mfmsr    r10
   wrteei    0
 
   mfspr    r3,SPRN_L1CFG0
   rlwinm    r5,r3,9,3    /* Extract cache block size */
   twlgti    r5,1        /* Only 32 and 64 byte cache blocks
                * are currently defined.
                */
   li    r4,32
   subfic    r6,r5,2        /* r6 = log2(1KiB / cache block size) -
                *      log2(number of ways)
                */
   slw    r5,r4,r5    /* r5 = cache block size */
 
   rlwinm    r7,r3,0,0xff    /* Extract number of KiB in the cache */
   mulli    r7,r7,13    /* An 8-way cache will require 13
                * loads per set.
                */
   slw    r7,r7,r6
 
   /* save off HID0 and set DCFA */
   mfspr    r8,SPRN_HID0
   ori    r9,r8,HID0_DCFA@l
   mtspr    SPRN_HID0,r9
   isync
 
   LOAD_REG_IMMEDIATE(r6, KERNELBASE)
   mr    r4, r6
   mtctr    r7
 
1:    lwz    r3,0(r4)    /* Load... */
   add    r4,r4,r5
   bdnz    1b
 
   msync
   mr    r4, r6
   mtctr    r7
 
1:    dcbf    0,r4        /* ...and flush. */
   add    r4,r4,r5
   bdnz    1b
 
   /* restore HID0 */
   mtspr    SPRN_HID0,r8
   isync
 
   wrtee r10
 
   blr
 
has_L2_cache:
   /* skip L2 cache on P2040/P2040E as they have no L2 cache */
   mfspr    r3, SPRN_SVR
   /* shift right by 8 bits and clear E bit of SVR */
   rlwinm    r4, r3, 24, ~0x800
 
   lis    r3, SVR_P2040@h
   ori    r3, r3, SVR_P2040@l
   cmpw    r4, r3
   beq    1f
 
   li    r3, 1
   blr
1:
   li    r3, 0
   blr
 
/* flush backside L2 cache */
flush_backside_L2_cache:
   mflr    r10
   bl    has_L2_cache
   mtlr    r10
   cmpwi    r3, 0
   beq    2f
 
   /* Flush the L2 cache */
   mfspr    r3, SPRN_L2CSR0
   ori    r3, r3, L2CSR0_L2FL@l
   msync
   isync
   mtspr    SPRN_L2CSR0,r3
   isync
 
   /* check if it is complete */
1:    mfspr    r3,SPRN_L2CSR0
   andi.    r3, r3, L2CSR0_L2FL@l
   bne    1b
2:
   blr
 
_GLOBAL(cpu_down_flush_e500v2)
   mflr r0
   bl    flush_dcache_L1
   mtlr r0
   blr
 
_GLOBAL(cpu_down_flush_e500mc)
_GLOBAL(cpu_down_flush_e5500)
   mflr r0
   bl    flush_dcache_L1
   bl    flush_backside_L2_cache
   mtlr r0
   blr
 
/* L1 Data Cache of e6500 contains no modified data, no flush is required */
_GLOBAL(cpu_down_flush_e6500)
   blr