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.
22
#include <ccan/str/str.h>
28
#define PACA_MAX_THREADS 4
30
static unsigned int paca_index(const struct HDIF_common_hdr *paca)
32
void *start = get_hdif(&spira.ntuples.paca, PACA_HDIF_SIG);
33
return ((void *)paca - start)
34
/ be32_to_cpu(spira.ntuples.paca.alloc_len);
37
static struct dt_node *add_cpu_node(struct dt_node *cpus,
38
const struct HDIF_common_hdr *paca,
39
const struct sppaca_cpu_id *id,
42
const struct sppaca_cpu_timebase *timebase;
43
const struct sppaca_cpu_cache *cache;
44
const struct sppaca_cpu_attr *attr;
46
u32 no, size, ve_flags, l2_phandle, chip_id;
48
/* We use the process_interrupt_line as the res id */
49
no = be32_to_cpu(id->process_interrupt_line);
51
ve_flags = be32_to_cpu(id->verify_exists_flags);
52
printf("CPU[%i]: PIR=%i RES=%i %s %s(%u threads)\n",
53
paca_index(paca), be32_to_cpu(id->pir), no,
54
ve_flags & CPU_ID_PACA_RESERVED
55
? "**RESERVED**" : cpu_state(ve_flags),
56
ve_flags & CPU_ID_SECONDARY_THREAD
58
(be32_to_cpu(id->pir) == boot_cpu->pir ? "[boot] " : ""),
59
((ve_flags & CPU_ID_NUM_SECONDARY_THREAD_MASK)
60
>> CPU_ID_NUM_SECONDARY_THREAD_SHIFT) + 1);
62
timebase = HDIF_get_idata(paca, SPPACA_IDATA_TIMEBASE, &size);
63
if (!timebase || size < sizeof(*timebase)) {
64
prerror("CPU[%i]: bad timebase size %u @ %p\n",
65
paca_index(paca), size, timebase);
69
cache = HDIF_get_idata(paca, SPPACA_IDATA_CACHE_SIZE, &size);
70
if (!cache || size < sizeof(*cache)) {
71
prerror("CPU[%i]: bad cache size %u @ %p\n",
72
paca_index(paca), size, cache);
76
cpu = add_core_common(cpus, cache, timebase, no, okay);
79
attr = HDIF_get_idata(paca, SPPACA_IDATA_CPU_ATTR, &size);
81
add_core_attr(cpu, be32_to_cpu(attr->attr));
84
l2_phandle = add_core_cache_info(cpus, cache, no, okay);
85
dt_add_property_cells(cpu, "l2-cache", l2_phandle);
87
/* We append the secondary cpus in __cpu_parse */
88
dt_add_property_cells(cpu, "ibm,ppc-interrupt-server#s", no);
90
dt_add_property_cells(cpu, DT_PRIVATE "hw_proc_id",
91
be32_to_cpu(id->hardware_proc_id));
92
dt_add_property_cells(cpu, "ibm,pir", be32_to_cpu(id->pir));
94
chip_id = pcid_to_chip_id(be32_to_cpu(id->processor_chip_id));
95
dt_add_property_cells(cpu, "ibm,chip-id", chip_id);
100
static struct dt_node *find_cpu_by_hardware_proc_id(struct dt_node *root,
105
dt_for_each_node(root, i) {
106
const struct dt_property *prop;
108
if (!dt_has_node_property(i, "device_type", "cpu"))
111
prop = dt_find_property(i, DT_PRIVATE "hw_proc_id");
115
if (be32_to_cpu(*(be32 *)prop->prop) == hw_proc_id)
121
/* Note that numbers are small. */
122
static void add_be32_sorted(__be32 arr[], __be32 new, unsigned num)
126
/* Walk until we find where we belong (insertion sort). */
127
for (i = 0; i < num; i++) {
128
if (be32_to_cpu(new) < be32_to_cpu(arr[i])) {
137
static void add_icps(void)
141
u64 reg[PACA_MAX_THREADS * 2];
144
dt_for_each_node(dt_root, cpu) {
145
u32 irange[2], size, pir;
146
const struct dt_property *intsrv;
147
const struct HDIF_common_hdr *paca;
149
unsigned int num_threads;
152
if (!dt_has_node_property(cpu, "device_type", "cpu"))
155
intsrv = dt_find_property(cpu, "ibm,ppc-interrupt-server#s");
156
pir = dt_prop_get_u32(cpu, "ibm,pir");
158
/* Get ibase address */
159
paca = get_hdif(&spira.ntuples.paca, PACA_HDIF_SIG);
160
for_each_paca(paca) {
161
const struct sppaca_cpu_id *id;
162
id = HDIF_get_idata(paca, SPPACA_IDATA_CPU_ID, &size);
164
if (!CHECK_SPPTR(id))
167
if (pir != be32_to_cpu(id->pir))
169
ibase = cleanup_addr(be64_to_cpu(id->ibase));
176
num_threads = intsrv->len / sizeof(u32);
177
assert(num_threads <= PACA_MAX_THREADS);
179
icp = dt_new_addr(dt_root, "interrupt-controller", ibase);
183
dt_add_property_strings(icp, "compatible",
187
irange[0] = dt_property_get_cell(intsrv, 0); /* Index */
188
irange[1] = num_threads; /* num servers */
189
dt_add_property(icp, "ibm,interrupt-server-ranges",
190
irange, sizeof(irange));
191
dt_add_property(icp, "interrupt-controller", NULL, 0);
192
dt_add_property_cells(icp, "#address-cells", 0);
193
dt_add_property_string(icp, "device_type",
194
"PowerPC-External-Interrupt-Presentation");
195
for (i = 0; i < num_threads*2; i += 2) {
197
/* One page is enough for a handful of regs. */
201
dt_add_property(icp, "reg", reg, sizeof(reg));
205
static bool __paca_parse(void)
207
const struct HDIF_common_hdr *paca;
208
struct dt_node *cpus;
210
paca = get_hdif(&spira.ntuples.paca, PACA_HDIF_SIG);
212
prerror("Invalid PACA (PCIA = %p)\n",
213
ntuple_addr(&spira.ntuples.pcia));
217
if (be32_to_cpu(spira.ntuples.paca.act_len) < sizeof(*paca)) {
218
prerror("PACA: invalid size %u\n",
219
be32_to_cpu(spira.ntuples.paca.act_len));
223
cpus = dt_new(dt_root, "cpus");
224
dt_add_property_cells(cpus, "#address-cells", 1);
225
dt_add_property_cells(cpus, "#size-cells", 0);
227
for_each_paca(paca) {
228
const struct sppaca_cpu_id *id;
232
id = HDIF_get_idata(paca, SPPACA_IDATA_CPU_ID, &size);
234
/* The ID structure on Blade314 is only 0x54 long. We can
235
* cope with it as we don't use all the additional fields.
236
* The minimum size we support is 0x40
238
if (!id || size < SPIRA_CPU_ID_MIN_SIZE) {
239
prerror("CPU[%i]: bad id size %u @ %p\n",
240
paca_index(paca), size, id);
244
ve_flags = be32_to_cpu(id->verify_exists_flags);
245
switch ((ve_flags&CPU_ID_VERIFY_MASK) >> CPU_ID_VERIFY_SHIFT) {
246
case CPU_ID_VERIFY_USABLE_NO_FAILURES:
247
case CPU_ID_VERIFY_USABLE_FAILURES:
254
printf("CPU[%i]: PIR=%i RES=%i %s\n",
255
paca_index(paca), be32_to_cpu(id->pir),
256
be32_to_cpu(id->process_interrupt_line),
257
okay ? "OK" : "UNAVAILABLE");
259
/* Secondary threads don't get their own node. */
260
if (ve_flags & CPU_ID_SECONDARY_THREAD)
263
if (!add_cpu_node(cpus, paca, id, okay))
267
/* Now account for secondaries. */
268
for_each_paca(paca) {
269
const struct dt_property *prop;
270
const struct sppaca_cpu_id *id;
271
u32 size, state, num, ve_flags;
275
id = HDIF_get_idata(paca, 2, &size);
276
if (!CHECK_SPPTR(id))
279
ve_flags = be32_to_cpu(id->verify_exists_flags);
280
state = (ve_flags & CPU_ID_VERIFY_MASK) >> CPU_ID_VERIFY_SHIFT;
282
case CPU_ID_VERIFY_USABLE_NO_FAILURES:
283
case CPU_ID_VERIFY_USABLE_FAILURES:
289
/* Only interested in secondary threads. */
290
if (!(ve_flags & CPU_ID_SECONDARY_THREAD))
293
cpu = find_cpu_by_hardware_proc_id(cpus,
294
be32_to_cpu(id->hardware_proc_id));
296
prerror("CPU[%i]: could not find primary hwid %i\n",
298
be32_to_cpu(id->hardware_proc_id));
303
prop = dt_find_property(cpu, "ibm,ppc-interrupt-server#s");
305
prerror("CPU[%i]: could not find mapping information\n",
309
num = prop->len / sizeof(u32);
310
new_prop = malloc((num + 1) * sizeof(u32));
312
prerror("Property allocation length %zu failed\n",
313
(num + 1) * sizeof(u32));
316
memcpy(new_prop, prop->prop, prop->len);
317
add_be32_sorted(new_prop, id->process_interrupt_line, num);
318
dt_del_property(cpu, (struct dt_property *)prop);
319
dt_add_property(cpu, "ibm,ppc-interrupt-server#s",
320
new_prop, (num + 1) * sizeof(__be32));
331
if (!__paca_parse()) {
332
prerror("CPU: Initial CPU parsing failed\n");