1
/* Copyright 2013-2014 IBM Corp.
3
* Licensed under the Apache License, Version 2.0 (the "License");
4
* you may not use this file except in compliance with the License.
5
* You may obtain a copy of the License at
7
* http://www.apache.org/licenses/LICENSE-2.0
9
* Unless required by applicable law or agreed to in writing, software
10
* distributed under the License is distributed on an "AS IS" BASIS,
11
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
13
* See the License for the specific language governing permissions and
14
* limitations under the License.
19
#include <ccan/str/str.h>
24
struct dt_node * add_core_common(struct dt_node *cpus,
25
const struct sppcia_cpu_cache *cache,
26
const struct sppaca_cpu_timebase *tb,
27
uint32_t int_server, bool okay)
33
const uint8_t pa_features[] = {
34
6, 0, 0xf6, 0x3f, 0xc7, 0x00, 0x80, 0xc0 };
36
prlog(PR_INFO, " Cache: I=%u D=%u/%u/%u/%u\n",
37
be32_to_cpu(cache->icache_size_kb),
38
be32_to_cpu(cache->l1_dcache_size_kb),
39
be32_to_cpu(cache->l2_dcache_size_kb),
40
be32_to_cpu(cache->l3_dcache_size_kb),
41
be32_to_cpu(cache->l35_dcache_size_kb));
43
/* Use the boot CPU PVR to make up a CPU name in the device-tree
44
* since the HDAT doesn't seem to tell....
46
version = mfspr(SPR_PVR);
47
switch(PVR_TYPE(version)) {
49
name = "PowerPC,POWER7";
52
name = "PowerPC,POWER7+";
57
name = "PowerPC,POWER8";
60
name = "PowerPC,POWER9";
63
name = "PowerPC,Unknown";
66
cpu = dt_new_addr(cpus, name, int_server);
68
dt_add_property_string(cpu, "device_type", "cpu");
69
dt_add_property_string(cpu, "status", okay ? "okay" : "bad");
70
dt_add_property_cells(cpu, "reg", int_server);
71
dt_add_property_cells(cpu, "cpu-version", version);
72
dt_add_property(cpu, "64-bit", NULL, 0);
73
dt_add_property(cpu, "32-64-bridge", NULL, 0);
74
dt_add_property(cpu, "graphics", NULL, 0);
75
dt_add_property(cpu, "general-purpose", NULL, 0);
76
dt_add_property_cells(cpu, "ibm,processor-segment-sizes",
77
0x1c, 0x28, 0xffffffff, 0xffffffff);
78
dt_add_property_cells(cpu, "ibm,processor-page-sizes",
79
0xc, 0x10, 0x18, 0x22);
81
/* Page size encodings appear to be the same for P7 and P8 */
82
dt_add_property_cells(cpu, "ibm,segment-page-sizes",
83
0x0c, 0x000, 3, 0x0c, 0x0000, /* 4K seg 4k pages */
84
0x10, 0x0007, /* 4K seg 64k pages */
85
0x18, 0x0038, /* 4K seg 16M pages */
86
0x10, 0x110, 2, 0x10, 0x0001, /* 64K seg 64k pages */
87
0x18, 0x0008, /* 64K seg 16M pages */
88
0x18, 0x100, 1, 0x18, 0x0000, /* 16M seg 16M pages */
89
0x22, 0x120, 1, 0x22, 0x0003); /* 16G seg 16G pages */
91
dt_add_property(cpu, "ibm,pa-features",
92
pa_features, sizeof(pa_features));
93
dt_add_property_cells(cpu, "ibm,slb-size", 0x20);
95
dt_add_property_cells(cpu, "ibm,vmx", 0x2);
96
dt_add_property_cells(cpu, "ibm,dfp", 0x2);
97
dt_add_property_cells(cpu, "ibm,purr", 0x1);
98
dt_add_property_cells(cpu, "ibm,spurr", 0x1);
101
* Do not create "clock-frequency" if the frequency doesn't
102
* fit in a single cell
104
freq = ((uint64_t)be32_to_cpu(tb->actual_clock_speed)) * 1000000ul;
105
if (freq <= 0xfffffffful)
106
dt_add_property_cells(cpu, "clock-frequency", freq);
107
dt_add_property_cells(cpu, "ibm,extended-clock-frequency",
108
hi32(freq), lo32(freq));
110
/* FIXME: Hardcoding is bad. */
111
dt_add_property_cells(cpu, "timebase-frequency", 512000000);
112
dt_add_property_cells(cpu, "ibm,extended-timebase-frequency",
115
dt_add_property_cells(cpu, "reservation-granule-size",
116
be32_to_cpu(cache->reservation_size));
118
dt_add_property_cells(cpu, "d-tlb-size",
119
be32_to_cpu(cache->dtlb_entries));
120
dt_add_property_cells(cpu, "i-tlb-size",
121
be32_to_cpu(cache->itlb_entries));
122
/* Assume unified TLB */
123
dt_add_property_cells(cpu, "tlb-size",
124
be32_to_cpu(cache->dtlb_entries));
125
dt_add_property_cells(cpu, "d-tlb-sets",
126
be32_to_cpu(cache->dtlb_assoc_sets));
127
dt_add_property_cells(cpu, "i-tlb-sets",
128
be32_to_cpu(cache->itlb_assoc_sets));
129
dt_add_property_cells(cpu, "tlb-sets",
130
be32_to_cpu(cache->dtlb_assoc_sets));
132
dt_add_property_cells(cpu, "d-cache-block-size",
133
be32_to_cpu(cache->dcache_block_size));
134
dt_add_property_cells(cpu, "i-cache-block-size",
135
be32_to_cpu(cache->icache_block_size));
136
dt_add_property_cells(cpu, "d-cache-size",
137
be32_to_cpu(cache->l1_dcache_size_kb)*1024);
138
dt_add_property_cells(cpu, "i-cache-size",
139
be32_to_cpu(cache->icache_size_kb)*1024);
140
dt_add_property_cells(cpu, "i-cache-sets",
141
be32_to_cpu(cache->icache_assoc_sets));
142
dt_add_property_cells(cpu, "d-cache-sets",
143
be32_to_cpu(cache->dcache_assoc_sets));
145
if (cache->icache_line_size != cache->icache_block_size)
146
dt_add_property_cells(cpu, "i-cache-line-size",
147
be32_to_cpu(cache->icache_line_size));
148
if (cache->l1_dcache_line_size != cache->dcache_block_size)
149
dt_add_property_cells(cpu, "d-cache-line-size",
150
be32_to_cpu(cache->l1_dcache_line_size));
154
void add_core_attr(struct dt_node *cpu, uint32_t attr)
156
if (attr & CPU_ATTR_UNIFIED_PL1)
157
dt_add_property(cpu, "cache-unified", NULL, 0);
158
if (attr & CPU_ATTR_SPLIT_TLB)
159
dt_add_property(cpu, "tlb-split", NULL, 0);
160
if (attr & CPU_ATTR_TLBIA)
161
dt_add_property(cpu, "tlbia", NULL, 0);
162
if (attr & CPU_ATTR_PERF_MONITOR)
163
dt_add_property_cells(cpu, "performance-monitor", 0, 1);
164
if (attr & CPU_ATTR_EXTERN_CONT)
165
dt_add_property(cpu, "external-control", NULL, 0);
168
static struct dt_node *create_cache_node(struct dt_node *cpus,
169
const struct sppcia_cpu_cache *cache,
170
const char *name, uint32_t unit_addr,
173
struct dt_node *node;
175
node = dt_new_addr(cpus, name, unit_addr);
178
dt_add_property_string(node, "device_type", "cache");
179
dt_add_property_cells(node, "reg", unit_addr);
180
dt_add_property_string(node, "status", okay ? "okay" : "bad");
181
dt_add_property(node, "cache-unified", NULL, 0);
183
/* Assume cache associavitity sets is same for L2, L3 and L3.5 */
184
dt_add_property_cells(node, "d-cache-sets",
185
be32_to_cpu(cache->l2_cache_assoc_sets));
186
dt_add_property_cells(node, "i-cache-sets",
187
be32_to_cpu(cache->l2_cache_assoc_sets));
192
static struct dt_node *l35_cache_node(struct dt_node *cpus,
193
const struct sppcia_cpu_cache *cache,
194
uint32_t unit_addr, int okay)
196
struct dt_node *node;
198
node = create_cache_node(cpus, cache, "l35-cache", unit_addr, okay);
200
dt_add_property_cells(node, "d-cache-size",
201
be32_to_cpu(cache->l35_dcache_size_kb) * 1024);
202
dt_add_property_cells(node, "i-cache-size",
203
be32_to_cpu(cache->l35_dcache_size_kb) * 1024);
205
if (cache->icache_line_size != cache->icache_block_size)
206
dt_add_property_cells(node, "i-cache-line-size",
207
be32_to_cpu(cache->icache_line_size));
208
if (cache->l35_cache_line_size != cache->dcache_block_size)
209
dt_add_property_cells(node, "d-cache-line-size",
210
be32_to_cpu(cache->l35_cache_line_size));
215
static struct dt_node *l3_cache_node(struct dt_node *cpus,
216
const struct sppcia_cpu_cache *cache,
217
uint32_t unit_addr, int okay)
219
struct dt_node *node;
221
node = create_cache_node(cpus, cache, "l3-cache", unit_addr, okay);
223
dt_add_property_cells(node, "d-cache-size",
224
be32_to_cpu(cache->l3_dcache_size_kb) * 1024);
225
dt_add_property_cells(node, "i-cache-size",
226
be32_to_cpu(cache->l3_dcache_size_kb) * 1024);
228
if (cache->icache_line_size != cache->icache_block_size)
229
dt_add_property_cells(node, "i-cache-line-size",
230
be32_to_cpu(cache->icache_line_size));
231
if (cache->l3_line_size != cache->dcache_block_size)
232
dt_add_property_cells(node, "d-cache-line-size",
233
be32_to_cpu(cache->l3_line_size));
238
static struct dt_node *l2_cache_node(struct dt_node *cpus,
239
const struct sppcia_cpu_cache *cache,
240
uint32_t unit_addr, int okay)
242
struct dt_node *node;
244
node = create_cache_node(cpus, cache, "l2-cache", unit_addr, okay);
246
dt_add_property_cells(node, "d-cache-size",
247
be32_to_cpu(cache->l2_dcache_size_kb) * 1024);
248
dt_add_property_cells(node, "i-cache-size",
249
be32_to_cpu(cache->l2_dcache_size_kb) * 1024);
251
if (cache->icache_line_size != cache->icache_block_size)
252
dt_add_property_cells(node, "i-cache-line-size",
253
be32_to_cpu(cache->icache_line_size));
254
if (cache->l2_line_size != cache->dcache_block_size)
255
dt_add_property_cells(node, "d-cache-line-size",
256
be32_to_cpu(cache->l2_line_size));
261
uint32_t add_core_cache_info(struct dt_node *cpus,
262
const struct sppcia_cpu_cache *cache,
263
uint32_t int_server, int okay)
265
struct dt_node *l2_node, *l3_node, *l35_node;
268
/* Use Processor Interrupt Line to genarate cache unit address */
269
unit_addr = 0x20 << 24 | int_server;
270
l2_node = l2_cache_node(cpus, cache, unit_addr, okay);
272
unit_addr = 0x30 << 24 | int_server;
273
l3_node = l3_cache_node(cpus, cache, unit_addr, okay);
274
/* Represents the next level of cache in the memory hierarchy */
275
dt_add_property_cells(l2_node, "l2-cache", l3_node->phandle);
277
if (be32_to_cpu(cache->l35_dcache_size_kb)) {
278
unit_addr = 0x35 << 24 | int_server;
279
l35_node = l35_cache_node(cpus, cache, unit_addr, okay);
280
dt_add_property_cells(l3_node, "l2-cache", l35_node->phandle);
283
return l2_node->phandle;