2 * SCOM support for A2 platforms
4 * Copyright 2007-2011 Benjamin Herrenschmidt, David Gibson,
5 * Michael Ellerman, IBM Corp.
7 * This program is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU General Public License
9 * as published by the Free Software Foundation; either version
10 * 2 of the License, or (at your option) any later version.
13 #include <linux/cpumask.h>
16 #include <linux/spinlock.h>
17 #include <linux/types.h>
19 #include <asm/cputhreads.h>
20 #include <asm/reg_a2.h>
26 #define SCOM_RAMC 0x2a /* Ram Command */
27 #define SCOM_RAMC_TGT1_EXT 0x80000000
28 #define SCOM_RAMC_SRC1_EXT 0x40000000
29 #define SCOM_RAMC_SRC2_EXT 0x20000000
30 #define SCOM_RAMC_SRC3_EXT 0x10000000
31 #define SCOM_RAMC_ENABLE 0x00080000
32 #define SCOM_RAMC_THREADSEL 0x00060000
33 #define SCOM_RAMC_EXECUTE 0x00010000
34 #define SCOM_RAMC_MSR_OVERRIDE 0x00008000
35 #define SCOM_RAMC_MSR_PR 0x00004000
36 #define SCOM_RAMC_MSR_GS 0x00002000
37 #define SCOM_RAMC_FORCE 0x00001000
38 #define SCOM_RAMC_FLUSH 0x00000800
39 #define SCOM_RAMC_INTERRUPT 0x00000004
40 #define SCOM_RAMC_ERROR 0x00000002
41 #define SCOM_RAMC_DONE 0x00000001
42 #define SCOM_RAMI 0x29 /* Ram Instruction */
43 #define SCOM_RAMIC 0x28 /* Ram Instruction and Command */
44 #define SCOM_RAMIC_INSN 0xffffffff00000000
45 #define SCOM_RAMD 0x2d /* Ram Data */
46 #define SCOM_RAMDH 0x2e /* Ram Data High */
47 #define SCOM_RAMDL 0x2f /* Ram Data Low */
48 #define SCOM_PCCR0 0x33 /* PC Configuration Register 0 */
49 #define SCOM_PCCR0_ENABLE_DEBUG 0x80000000
50 #define SCOM_PCCR0_ENABLE_RAM 0x40000000
51 #define SCOM_THRCTL 0x30 /* Thread Control and Status */
52 #define SCOM_THRCTL_T0_STOP 0x80000000
53 #define SCOM_THRCTL_T1_STOP 0x40000000
54 #define SCOM_THRCTL_T2_STOP 0x20000000
55 #define SCOM_THRCTL_T3_STOP 0x10000000
56 #define SCOM_THRCTL_T0_STEP 0x08000000
57 #define SCOM_THRCTL_T1_STEP 0x04000000
58 #define SCOM_THRCTL_T2_STEP 0x02000000
59 #define SCOM_THRCTL_T3_STEP 0x01000000
60 #define SCOM_THRCTL_T0_RUN 0x00800000
61 #define SCOM_THRCTL_T1_RUN 0x00400000
62 #define SCOM_THRCTL_T2_RUN 0x00200000
63 #define SCOM_THRCTL_T3_RUN 0x00100000
64 #define SCOM_THRCTL_T0_PM 0x00080000
65 #define SCOM_THRCTL_T1_PM 0x00040000
66 #define SCOM_THRCTL_T2_PM 0x00020000
67 #define SCOM_THRCTL_T3_PM 0x00010000
68 #define SCOM_THRCTL_T0_UDE 0x00008000
69 #define SCOM_THRCTL_T1_UDE 0x00004000
70 #define SCOM_THRCTL_T2_UDE 0x00002000
71 #define SCOM_THRCTL_T3_UDE 0x00001000
72 #define SCOM_THRCTL_ASYNC_DIS 0x00000800
73 #define SCOM_THRCTL_TB_DIS 0x00000400
74 #define SCOM_THRCTL_DEC_DIS 0x00000200
75 #define SCOM_THRCTL_AND 0x31 /* Thread Control and Status */
76 #define SCOM_THRCTL_OR 0x32 /* Thread Control and Status */
79 static DEFINE_PER_CPU(scom_map_t
, scom_ptrs
);
81 static scom_map_t
get_scom(int cpu
, struct device_node
*np
, int *first_thread
)
83 scom_map_t scom
= per_cpu(scom_ptrs
, cpu
);
86 if (scom_map_ok(scom
)) {
93 scom
= scom_map_device(np
, 0);
95 for (tcpu
= cpu_first_thread_sibling(cpu
);
96 tcpu
<= cpu_last_thread_sibling(cpu
); tcpu
++)
97 per_cpu(scom_ptrs
, tcpu
) = scom
;
99 /* Hack: for the boot core, this will actually get called on
100 * the second thread up, not the first so our test above will
101 * set first_thread incorrectly. */
102 if (cpu_first_thread_sibling(cpu
) == 0)
108 static int a2_scom_ram(scom_map_t scom
, int thread
, u32 insn
, int extmask
)
113 cmd
= ((u64
)insn
<< 32) | (((u64
)extmask
& 0xf) << 28)
114 | ((u64
)thread
<< 17) | SCOM_RAMC_ENABLE
| SCOM_RAMC_EXECUTE
;
115 mask
= SCOM_RAMC_DONE
| SCOM_RAMC_INTERRUPT
| SCOM_RAMC_ERROR
;
117 scom_write(scom
, SCOM_RAMIC
, cmd
);
119 while (!((val
= scom_read(scom
, SCOM_RAMC
)) & mask
)) {
120 pr_devel("Waiting on RAMC = 0x%llx\n", val
);
122 pr_err("RAMC timeout on instruction 0x%08x, thread %d\n",
128 if (val
& SCOM_RAMC_INTERRUPT
) {
129 pr_err("RAMC interrupt on instruction 0x%08x, thread %d\n",
131 return -SCOM_RAMC_INTERRUPT
;
134 if (val
& SCOM_RAMC_ERROR
) {
135 pr_err("RAMC error on instruction 0x%08x, thread %d\n",
137 return -SCOM_RAMC_ERROR
;
143 static int a2_scom_getgpr(scom_map_t scom
, int thread
, int gpr
, int alt
,
149 u32 insn
= 0x7c000378 | (gpr
<< 21) | (gpr
<< 16) | (gpr
<< 11);
150 rc
= a2_scom_ram(scom
, thread
, insn
, alt
? 0xf : 0x0);
154 *out_gpr
= scom_read(scom
, SCOM_RAMD
);
159 static int a2_scom_getspr(scom_map_t scom
, int thread
, int spr
, u64
*out_spr
)
161 int rc
, sprhi
, sprlo
;
166 insn
= 0x7c2002a6 | (sprlo
<< 16) | (sprhi
<< 11); /* mfspr r1,spr */
169 insn
= 0x7c2000a6; /* mfmsr r1 */
171 rc
= a2_scom_ram(scom
, thread
, insn
, 0xf);
174 return a2_scom_getgpr(scom
, thread
, 1, 1, out_spr
);
177 static int a2_scom_setgpr(scom_map_t scom
, int thread
, int gpr
,
180 u32 lis
= 0x3c000000 | (gpr
<< 21);
181 u32 li
= 0x38000000 | (gpr
<< 21);
182 u32 oris
= 0x64000000 | (gpr
<< 21) | (gpr
<< 16);
183 u32 ori
= 0x60000000 | (gpr
<< 21) | (gpr
<< 16);
184 u32 rldicr32
= 0x780007c6 | (gpr
<< 21) | (gpr
<< 16);
185 u32 highest
= val
>> 48;
186 u32 higher
= (val
>> 32) & 0xffff;
187 u32 high
= (val
>> 16) & 0xffff;
188 u32 low
= val
& 0xffff;
189 int lext
= alt
? 0x8 : 0x0;
190 int oext
= alt
? 0xf : 0x0;
194 rc
|= a2_scom_ram(scom
, thread
, lis
| highest
, lext
);
198 rc
|= a2_scom_ram(scom
, thread
, oris
| higher
, oext
);
200 rc
|= a2_scom_ram(scom
, thread
, li
| higher
, lext
);
203 if (highest
|| higher
)
204 rc
|= a2_scom_ram(scom
, thread
, rldicr32
, oext
);
207 if (highest
|| higher
)
208 rc
|= a2_scom_ram(scom
, thread
, oris
| high
, oext
);
210 rc
|= a2_scom_ram(scom
, thread
, lis
| high
, lext
);
213 if (highest
|| higher
|| high
)
214 rc
|= a2_scom_ram(scom
, thread
, ori
| low
, oext
);
216 rc
|= a2_scom_ram(scom
, thread
, li
| low
, lext
);
221 static int a2_scom_setspr(scom_map_t scom
, int thread
, int spr
, u64 val
)
223 int sprhi
= spr
>> 5;
224 int sprlo
= spr
& 0x1f;
226 u32 insn
= 0x7c2003a6 | (sprlo
<< 16) | (sprhi
<< 11);
229 insn
= 0x7c200124; /* mtmsr r1 */
231 if (a2_scom_setgpr(scom
, thread
, 1, 1, val
))
234 return a2_scom_ram(scom
, thread
, insn
, 0xf);
237 static int a2_scom_initial_tlb(scom_map_t scom
, int thread
)
239 extern u32 a2_tlbinit_code_start
[], a2_tlbinit_code_end
[];
240 extern u32 a2_tlbinit_after_iprot_flush
[];
241 extern u32 a2_tlbinit_after_linear_map
[];
242 u32 assoc
, entries
, i
;
247 /* Invalidate all entries (including iprot) */
249 rc
= a2_scom_getspr(scom
, thread
, SPRN_TLB0CFG
, &tlbcfg
);
252 entries
= tlbcfg
& TLBnCFG_N_ENTRY
;
253 assoc
= (tlbcfg
& TLBnCFG_ASSOC
) >> 24;
256 /* Set MMUCR2 to enable 4K, 64K, 1M, 16M and 1G pages */
257 a2_scom_setspr(scom
, thread
, SPRN_MMUCR2
, 0x000a7531);
258 /* Set MMUCR3 to write all thids bit to the TLB */
259 a2_scom_setspr(scom
, thread
, SPRN_MMUCR3
, 0x0000000f);
261 /* Set MAS1 for 1G page size, and MAS2 to our initial EPN */
262 a2_scom_setspr(scom
, thread
, SPRN_MAS1
, MAS1_TSIZE(BOOK3E_PAGESZ_1GB
));
263 a2_scom_setspr(scom
, thread
, SPRN_MAS2
, epn
);
264 for (i
= 0; i
< entries
; i
++) {
266 a2_scom_setspr(scom
, thread
, SPRN_MAS0
, MAS0_ESEL(i
% assoc
));
269 rc
= a2_scom_ram(scom
, thread
, 0x7c0007a4, 0);
273 /* Next entry is new address? */
274 if((i
+ 1) % assoc
== 0) {
276 a2_scom_setspr(scom
, thread
, SPRN_MAS2
, epn
);
280 /* Setup args for linear mapping */
281 rc
= a2_scom_setgpr(scom
, thread
, 3, 0, MAS0_TLBSEL(0));
286 for (p
= a2_tlbinit_code_start
; p
< a2_tlbinit_after_linear_map
; p
++) {
287 rc
= a2_scom_ram(scom
, thread
, *p
, 0);
293 * For the boot thread, between the linear mapping and the debug
294 * mappings there is a loop to flush iprot mappings. Ramming doesn't do
295 * branches, but the secondary threads don't need to be nearly as smart
296 * (i.e. we don't need to worry about invalidating the mapping we're
300 /* Debug mappings. Expects r11 = MAS0 from linear map (set above) */
301 for (p
= a2_tlbinit_after_iprot_flush
; p
< a2_tlbinit_code_end
; p
++) {
302 rc
= a2_scom_ram(scom
, thread
, *p
, 0);
309 pr_err("Setting up initial TLB failed, err %d\n", rc
);
311 if (rc
== -SCOM_RAMC_INTERRUPT
) {
312 /* Interrupt, dump some status */
314 u64 iar
, srr0
, srr1
, esr
, mas0
, mas1
, mas2
, mas7_3
, mas8
, ccr2
;
315 rc
[0] = a2_scom_getspr(scom
, thread
, SPRN_IAR
, &iar
);
316 rc
[1] = a2_scom_getspr(scom
, thread
, SPRN_SRR0
, &srr0
);
317 rc
[2] = a2_scom_getspr(scom
, thread
, SPRN_SRR1
, &srr1
);
318 rc
[3] = a2_scom_getspr(scom
, thread
, SPRN_ESR
, &esr
);
319 rc
[4] = a2_scom_getspr(scom
, thread
, SPRN_MAS0
, &mas0
);
320 rc
[5] = a2_scom_getspr(scom
, thread
, SPRN_MAS1
, &mas1
);
321 rc
[6] = a2_scom_getspr(scom
, thread
, SPRN_MAS2
, &mas2
);
322 rc
[7] = a2_scom_getspr(scom
, thread
, SPRN_MAS7_MAS3
, &mas7_3
);
323 rc
[8] = a2_scom_getspr(scom
, thread
, SPRN_MAS8
, &mas8
);
324 rc
[9] = a2_scom_getspr(scom
, thread
, SPRN_A2_CCR2
, &ccr2
);
325 pr_err(" -> retreived IAR =0x%llx (err %d)\n", iar
, rc
[0]);
326 pr_err(" retreived SRR0=0x%llx (err %d)\n", srr0
, rc
[1]);
327 pr_err(" retreived SRR1=0x%llx (err %d)\n", srr1
, rc
[2]);
328 pr_err(" retreived ESR =0x%llx (err %d)\n", esr
, rc
[3]);
329 pr_err(" retreived MAS0=0x%llx (err %d)\n", mas0
, rc
[4]);
330 pr_err(" retreived MAS1=0x%llx (err %d)\n", mas1
, rc
[5]);
331 pr_err(" retreived MAS2=0x%llx (err %d)\n", mas2
, rc
[6]);
332 pr_err(" retreived MS73=0x%llx (err %d)\n", mas7_3
, rc
[7]);
333 pr_err(" retreived MAS8=0x%llx (err %d)\n", mas8
, rc
[8]);
334 pr_err(" retreived CCR2=0x%llx (err %d)\n", ccr2
, rc
[9]);
340 int a2_scom_startup_cpu(unsigned int lcpu
, int thr_idx
, struct device_node
*np
)
342 u64 init_iar
, init_msr
, init_ccr2
;
343 unsigned long start_here
;
348 scom
= get_scom(lcpu
, np
, &core_setup
);
350 printk(KERN_ERR
"Couldn't map SCOM for CPU%d\n", lcpu
);
354 pr_devel("Bringing up CPU%d using SCOM...\n", lcpu
);
356 pccr0
= scom_read(scom
, SCOM_PCCR0
);
357 scom_write(scom
, SCOM_PCCR0
, pccr0
| SCOM_PCCR0_ENABLE_DEBUG
|
358 SCOM_PCCR0_ENABLE_RAM
);
360 /* Stop the thead with THRCTL. If we are setting up the TLB we stop all
361 * threads. We also disable asynchronous interrupts while RAMing.
364 scom_write(scom
, SCOM_THRCTL_OR
,
365 SCOM_THRCTL_T0_STOP
|
366 SCOM_THRCTL_T1_STOP
|
367 SCOM_THRCTL_T2_STOP
|
368 SCOM_THRCTL_T3_STOP
|
369 SCOM_THRCTL_ASYNC_DIS
);
371 scom_write(scom
, SCOM_THRCTL_OR
, SCOM_THRCTL_T0_STOP
>> thr_idx
);
373 /* Flush its pipeline just in case */
374 scom_write(scom
, SCOM_RAMC
, ((u64
)thr_idx
<< 17) |
375 SCOM_RAMC_FLUSH
| SCOM_RAMC_ENABLE
);
377 a2_scom_getspr(scom
, thr_idx
, SPRN_IAR
, &init_iar
);
378 a2_scom_getspr(scom
, thr_idx
, 0x0ff0, &init_msr
);
379 a2_scom_getspr(scom
, thr_idx
, SPRN_A2_CCR2
, &init_ccr2
);
381 /* Set MSR to MSR_CM (0x0ff0 is magic value for MSR_CM) */
382 rc
= a2_scom_setspr(scom
, thr_idx
, 0x0ff0, MSR_CM
);
384 pr_err("Failed to set MSR ! err %d\n", rc
);
388 /* RAM in an sync/isync for the sake of it */
389 a2_scom_ram(scom
, thr_idx
, 0x7c0004ac, 0);
390 a2_scom_ram(scom
, thr_idx
, 0x4c00012c, 0);
393 pr_devel("CPU%d is first thread in core, initializing TLB...\n",
395 rc
= a2_scom_initial_tlb(scom
, thr_idx
);
400 start_here
= *(unsigned long *)(core_setup
? generic_secondary_smp_init
401 : generic_secondary_thread_init
);
402 pr_devel("CPU%d entry point at 0x%lx...\n", lcpu
, start_here
);
404 rc
|= a2_scom_setspr(scom
, thr_idx
, SPRN_IAR
, start_here
);
405 rc
|= a2_scom_setgpr(scom
, thr_idx
, 3, 0,
406 get_hard_smp_processor_id(lcpu
));
408 * Tell book3e_secondary_core_init not to set up the TLB, we've
411 rc
|= a2_scom_setgpr(scom
, thr_idx
, 4, 0, 1);
413 rc
|= a2_scom_setspr(scom
, thr_idx
, SPRN_TENS
, 0x1 << thr_idx
);
415 scom_write(scom
, SCOM_RAMC
, 0);
416 scom_write(scom
, SCOM_THRCTL_AND
, ~(SCOM_THRCTL_T0_STOP
>> thr_idx
));
417 scom_write(scom
, SCOM_PCCR0
, pccr0
);
419 pr_devel(" SCOM initialization %s\n", rc
? "failed" : "succeeded");
421 pr_err("Old IAR=0x%08llx MSR=0x%08llx CCR2=0x%08llx\n",
422 init_iar
, init_msr
, init_ccr2
);