aboutsummaryrefslogtreecommitdiffstats
path: root/arch/powerpc/kernel/cpu_setup_power.S
blob: 18b5b9cf8e3730f4608ca6ff997810d5cc47df9a (plain)
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
/*
 * This file contains low level CPU setup functions.
 *    Copyright (C) 2003 Benjamin Herrenschmidt (benh@kernel.crashing.org)
 *
 * This program is free software; you can redistribute it and/or
 * modify it under the terms of the GNU General Public License
 * as published by the Free Software Foundation; either version
 * 2 of the License, or (at your option) any later version.
 *
 */

#include <asm/processor.h>
#include <asm/page.h>
#include <asm/cputable.h>
#include <asm/ppc_asm.h>
#include <asm/asm-offsets.h>
#include <asm/cache.h>

/* Entry: r3 = crap, r4 = ptr to cputable entry
 *
 * Note that we can be called twice for pseudo-PVRs
 */
_GLOBAL(__setup_cpu_power7)
	mflr	r11
	bl	__init_hvmode_206
	mtlr	r11
	beqlr
	li	r0,0
	mtspr	SPRN_LPID,r0
	mfspr	r3,SPRN_LPCR
	bl	__init_LPCR
	bl	__init_TLB
	mtlr	r11
	blr

_GLOBAL(__restore_cpu_power7)
	mflr	r11
	mfmsr	r3
	rldicl.	r0,r3,4,63
	beqlr
	li	r0,0
	mtspr	SPRN_LPID,r0
	mfspr	r3,SPRN_LPCR
	bl	__init_LPCR
	bl	__init_TLB
	mtlr	r11
	blr

_GLOBAL(__setup_cpu_power8)
	mflr	r11
	bl	__init_FSCR
	bl	__init_PMU
	bl	__init_hvmode_206
	mtlr	r11
	beqlr
	li	r0,0
	mtspr	SPRN_LPID,r0
	mfspr	r3,SPRN_LPCR
	oris	r3, r3, LPCR_AIL_3@h
	bl	__init_LPCR
	bl	__init_HFSCR
	bl	__init_TLB
	bl	__init_PMU_HV
	mtlr	r11
	blr

_GLOBAL(__restore_cpu_power8)
	mflr	r11
	bl	__init_FSCR
	bl	__init_PMU
	mfmsr	r3
	rldicl.	r0,r3,4,63
	mtlr	r11
	beqlr
	li	r0,0
	mtspr	SPRN_LPID,r0
	mfspr   r3,SPRN_LPCR
	oris	r3, r3, LPCR_AIL_3@h
	bl	__init_LPCR
	bl	__init_HFSCR
	bl	__init_TLB
	bl	__init_PMU_HV
	mtlr	r11
	blr

__init_hvmode_206:
	/* Disable CPU_FTR_HVMODE and exit if MSR:HV is not set */
	mfmsr	r3
	rldicl.	r0,r3,4,63
	bnelr
	ld	r5,CPU_SPEC_FEATURES(r4)
	LOAD_REG_IMMEDIATE(r6,CPU_FTR_HVMODE)
	xor	r5,r5,r6
	std	r5,CPU_SPEC_FEATURES(r4)
	blr

__init_LPCR:
	/* Setup a sane LPCR:
	 *   Called with initial LPCR in R3
	 *
	 *   LPES = 0b01 (HSRR0/1 used for 0x500)
	 *   PECE = 0b111
	 *   DPFD = 4
	 *   HDICE = 0
	 *   VC = 0b100 (VPM0=1, VPM1=0, ISL=0)
	 *   VRMASD = 0b10000 (L=1, LP=00)
	 *
	 * Other bits untouched for now
	 */
	li	r5,1
	rldimi	r3,r5, LPCR_LPES_SH, 64-LPCR_LPES_SH-2
	ori	r3,r3,(LPCR_PECE0|LPCR_PECE1|LPCR_PECE2)
	li	r5,4
	rldimi	r3,r5, LPCR_DPFD_SH, 64-LPCR_DPFD_SH-3
	clrrdi	r3,r3,1		/* clear HDICE */
	li	r5,4
	rldimi	r3,r5, LPCR_VC_SH, 0
	li	r5,0x10
	rldimi	r3,r5, LPCR_VRMASD_SH, 64-LPCR_VRMASD_SH-5
	mtspr	SPRN_LPCR,r3
	isync
	blr

__init_FSCR:
	mfspr	r3,SPRN_FSCR
	ori	r3,r3,FSCR_TAR|FSCR_DSCR|FSCR_EBB
	mtspr	SPRN_FSCR,r3
	blr

__init_HFSCR:
	mfspr	r3,SPRN_HFSCR
	ori	r3,r3,HFSCR_TAR|HFSCR_TM|HFSCR_BHRB|HFSCR_PM|\
		      HFSCR_DSCR|HFSCR_VECVSX|HFSCR_FP|HFSCR_EBB
	mtspr	SPRN_HFSCR,r3
	blr

__init_TLB:
	/*
	 * Clear the TLB using the "IS 3" form of tlbiel instruction
	 * (invalidate by congruence class). P7 has 128 CCs, P8 has 512
	 * so we just always do 512
	 */
	li	r6,512
	mtctr	r6
	li	r7,0xc00	/* IS field = 0b11 */
	ptesync
2:	tlbiel	r7
	addi	r7,r7,0x1000
	bdnz	2b
	ptesync
1:	blr

__init_PMU_HV:
	li	r5,0
	mtspr	SPRN_MMCRC,r5
	mtspr	SPRN_MMCRH,r5
	blr

__init_PMU:
	li	r5,0
	mtspr	SPRN_MMCRS,r5
	mtspr	SPRN_MMCRA,r5
	mtspr	SPRN_MMCR0,r5
	mtspr	SPRN_MMCR1,r5
	mtspr	SPRN_MMCR2,r5
	blr