blob: 1af453a61991515c922e695d0aafee76b29cb991 [file] [log] [blame]
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001/*
2 * Procedures for interfacing to Open Firmware.
3 *
4 * Paul Mackerras August 1996.
5 * Copyright (C) 1996-2005 Paul Mackerras.
6 *
7 * Adapted for 64bit PowerPC by Dave Engebretsen and Peter Bergner.
8 * {engebret|bergner}@us.ibm.com
9 *
10 * This program is free software; you can redistribute it and/or
11 * modify it under the terms of the GNU General Public License
12 * as published by the Free Software Foundation; either version
13 * 2 of the License, or (at your option) any later version.
14 */
15
16#undef DEBUG_PROM
17
Daniel Axtens054f3672017-07-12 14:36:04 -070018/* we cannot use FORTIFY as it brings in new symbols */
19#define __NO_FORTIFY
20
Paul Mackerras9b6b5632005-10-06 12:06:20 +100021#include <stdarg.h>
Paul Mackerras9b6b5632005-10-06 12:06:20 +100022#include <linux/kernel.h>
23#include <linux/string.h>
24#include <linux/init.h>
25#include <linux/threads.h>
26#include <linux/spinlock.h>
27#include <linux/types.h>
28#include <linux/pci.h>
29#include <linux/proc_fs.h>
Paul Mackerras9b6b5632005-10-06 12:06:20 +100030#include <linux/delay.h>
31#include <linux/initrd.h>
32#include <linux/bitops.h>
33#include <asm/prom.h>
34#include <asm/rtas.h>
35#include <asm/page.h>
36#include <asm/processor.h>
37#include <asm/irq.h>
38#include <asm/io.h>
39#include <asm/smp.h>
Paul Mackerras9b6b5632005-10-06 12:06:20 +100040#include <asm/mmu.h>
41#include <asm/pgtable.h>
Paul Mackerras9b6b5632005-10-06 12:06:20 +100042#include <asm/iommu.h>
Paul Mackerras9b6b5632005-10-06 12:06:20 +100043#include <asm/btext.h>
44#include <asm/sections.h>
45#include <asm/machdep.h>
Benjamin Herrenschmidt27f44882011-09-19 18:27:58 +000046#include <asm/opal.h>
Daniel Axtens0545d542016-09-06 15:32:43 +100047#include <asm/asm-prototypes.h>
Paul Mackerras9b6b5632005-10-06 12:06:20 +100048
Paul Mackerras9b6b5632005-10-06 12:06:20 +100049#include <linux/linux_logo.h>
Paul Mackerras9b6b5632005-10-06 12:06:20 +100050
51/*
Paul Mackerras9b6b5632005-10-06 12:06:20 +100052 * Eventually bump that one up
53 */
54#define DEVTREE_CHUNK_SIZE 0x100000
55
56/*
57 * This is the size of the local memory reserve map that gets copied
58 * into the boot params passed to the kernel. That size is totally
59 * flexible as the kernel just reads the list until it encounters an
60 * entry with size 0, so it can be changed without breaking binary
61 * compatibility
62 */
63#define MEM_RESERVE_MAP_SIZE 8
64
65/*
66 * prom_init() is called very early on, before the kernel text
67 * and data have been mapped to KERNELBASE. At this point the code
68 * is running at whatever address it has been loaded at.
69 * On ppc32 we compile with -mrelocatable, which means that references
70 * to extern and static variables get relocated automatically.
Anton Blanchard5ac47f72012-11-26 17:39:03 +000071 * ppc64 objects are always relocatable, we just need to relocate the
72 * TOC.
Paul Mackerras9b6b5632005-10-06 12:06:20 +100073 *
74 * Because OF may have mapped I/O devices into the area starting at
75 * KERNELBASE, particularly on CHRP machines, we can't safely call
76 * OF once the kernel has been mapped to KERNELBASE. Therefore all
77 * OF calls must be done within prom_init().
78 *
79 * ADDR is used in calls to call_prom. The 4th and following
80 * arguments to call_prom should be 32-bit values.
81 * On ppc64, 64 bit values are truncated to 32 bits (and
82 * fortunately don't get interpreted as two arguments).
83 */
Anton Blanchard5ac47f72012-11-26 17:39:03 +000084#define ADDR(x) (u32)(unsigned long)(x)
85
Paul Mackerras9b6b5632005-10-06 12:06:20 +100086#ifdef CONFIG_PPC64
Paul Mackerrasa23414b2005-11-10 12:00:55 +110087#define OF_WORKAROUNDS 0
Paul Mackerras9b6b5632005-10-06 12:06:20 +100088#else
Paul Mackerrasa23414b2005-11-10 12:00:55 +110089#define OF_WORKAROUNDS of_workarounds
90int of_workarounds;
Paul Mackerras9b6b5632005-10-06 12:06:20 +100091#endif
92
Paul Mackerrasa23414b2005-11-10 12:00:55 +110093#define OF_WA_CLAIM 1 /* do phys/virt claim separately, then map */
94#define OF_WA_LONGTRAIL 2 /* work around longtrail bugs */
95
Paul Mackerras9b6b5632005-10-06 12:06:20 +100096#define PROM_BUG() do { \
97 prom_printf("kernel BUG at %s line 0x%x!\n", \
Anton Blanchard5827d412012-11-26 17:40:03 +000098 __FILE__, __LINE__); \
Paul Mackerras9b6b5632005-10-06 12:06:20 +100099 __asm__ __volatile__(".long " BUG_ILLEGAL_INSTR); \
100} while (0)
101
102#ifdef DEBUG_PROM
103#define prom_debug(x...) prom_printf(x)
104#else
Mathieu Malaterre85aa4b92018-04-23 21:36:38 +0200105#define prom_debug(x...) do { } while (0)
Paul Mackerras9b6b5632005-10-06 12:06:20 +1000106#endif
107
Paul Mackerras9b6b5632005-10-06 12:06:20 +1000108
109typedef u32 prom_arg_t;
110
111struct prom_args {
Benjamin Herrenschmidt493adff2013-08-07 02:01:38 +1000112 __be32 service;
113 __be32 nargs;
114 __be32 nret;
115 __be32 args[10];
Paul Mackerras9b6b5632005-10-06 12:06:20 +1000116};
117
118struct prom_t {
119 ihandle root;
Paul Mackerrasa23414b2005-11-10 12:00:55 +1100120 phandle chosen;
Paul Mackerras9b6b5632005-10-06 12:06:20 +1000121 int cpu;
122 ihandle stdout;
Paul Mackerrasa575b802005-10-23 17:23:21 +1000123 ihandle mmumap;
Paul Mackerrasa23414b2005-11-10 12:00:55 +1100124 ihandle memory;
Paul Mackerras9b6b5632005-10-06 12:06:20 +1000125};
126
127struct mem_map_entry {
Benjamin Herrenschmidt493adff2013-08-07 02:01:38 +1000128 __be64 base;
129 __be64 size;
Paul Mackerras9b6b5632005-10-06 12:06:20 +1000130};
131
Benjamin Herrenschmidt493adff2013-08-07 02:01:38 +1000132typedef __be32 cell_t;
Paul Mackerras9b6b5632005-10-06 12:06:20 +1000133
Benjamin Herrenschmidt6e35d5d2011-09-19 18:28:01 +0000134extern void __start(unsigned long r3, unsigned long r4, unsigned long r5,
135 unsigned long r6, unsigned long r7, unsigned long r8,
136 unsigned long r9);
Paul Mackerras9b6b5632005-10-06 12:06:20 +1000137
138#ifdef CONFIG_PPC64
Paul Mackerrasc49888202005-10-26 21:52:53 +1000139extern int enter_prom(struct prom_args *args, unsigned long entry);
Paul Mackerras9b6b5632005-10-06 12:06:20 +1000140#else
Paul Mackerrasc49888202005-10-26 21:52:53 +1000141static inline int enter_prom(struct prom_args *args, unsigned long entry)
Paul Mackerras9b6b5632005-10-06 12:06:20 +1000142{
Paul Mackerrasc49888202005-10-26 21:52:53 +1000143 return ((int (*)(struct prom_args *))entry)(args);
Paul Mackerras9b6b5632005-10-06 12:06:20 +1000144}
145#endif
146
147extern void copy_and_flush(unsigned long dest, unsigned long src,
148 unsigned long size, unsigned long offset);
149
150/* prom structure */
151static struct prom_t __initdata prom;
152
153static unsigned long prom_entry __initdata;
154
155#define PROM_SCRATCH_SIZE 256
156
157static char __initdata of_stdout_device[256];
158static char __initdata prom_scratch[PROM_SCRATCH_SIZE];
159
160static unsigned long __initdata dt_header_start;
161static unsigned long __initdata dt_struct_start, dt_struct_end;
162static unsigned long __initdata dt_string_start, dt_string_end;
163
164static unsigned long __initdata prom_initrd_start, prom_initrd_end;
165
166#ifdef CONFIG_PPC64
Jeremy Kerr165785e2006-11-11 17:25:18 +1100167static int __initdata prom_iommu_force_on;
168static int __initdata prom_iommu_off;
Paul Mackerras9b6b5632005-10-06 12:06:20 +1000169static unsigned long __initdata prom_tce_alloc_start;
170static unsigned long __initdata prom_tce_alloc_end;
171#endif
172
Aneesh Kumar K.V7a22d632018-03-30 17:39:02 +0530173static bool prom_radix_disable __initdata = !IS_ENABLED(CONFIG_PPC_RADIX_MMU_DEFAULT);
Suraj Jitindar Singh014d02c2017-02-28 17:03:48 +1100174
175struct platform_support {
176 bool hash_mmu;
177 bool radix_mmu;
178 bool radix_gtse;
Cédric Le Goaterac5e5a52017-08-30 21:46:16 +0200179 bool xive;
Suraj Jitindar Singh014d02c2017-02-28 17:03:48 +1100180};
181
Benjamin Herrenschmidte8222502006-03-28 23:15:54 +1100182/* Platforms codes are now obsolete in the kernel. Now only used within this
183 * file and ultimately gone too. Feel free to change them if you need, they
184 * are not shared with anything outside of this file anymore
185 */
186#define PLATFORM_PSERIES 0x0100
187#define PLATFORM_PSERIES_LPAR 0x0101
188#define PLATFORM_LPAR 0x0001
189#define PLATFORM_POWERMAC 0x0400
190#define PLATFORM_GENERIC 0x0500
Benjamin Herrenschmidt27f44882011-09-19 18:27:58 +0000191#define PLATFORM_OPAL 0x0600
Benjamin Herrenschmidte8222502006-03-28 23:15:54 +1100192
Paul Mackerras9b6b5632005-10-06 12:06:20 +1000193static int __initdata of_platform;
194
195static char __initdata prom_cmd_line[COMMAND_LINE_SIZE];
196
Benjamin Krillcf687872009-07-27 22:02:39 +0000197static unsigned long __initdata prom_memory_limit;
198
Paul Mackerras9b6b5632005-10-06 12:06:20 +1000199static unsigned long __initdata alloc_top;
200static unsigned long __initdata alloc_top_high;
201static unsigned long __initdata alloc_bottom;
202static unsigned long __initdata rmo_top;
203static unsigned long __initdata ram_top;
204
205static struct mem_map_entry __initdata mem_reserve_map[MEM_RESERVE_MAP_SIZE];
206static int __initdata mem_reserve_cnt;
207
208static cell_t __initdata regbuf[1024];
209
Benjamin Herrenschmidtdbe78b42013-09-25 14:02:50 +1000210static bool rtas_has_query_cpu_stopped;
211
Paul Mackerras9b6b5632005-10-06 12:06:20 +1000212
Paul Mackerras9b6b5632005-10-06 12:06:20 +1000213/*
214 * Error results ... some OF calls will return "-1" on error, some
215 * will return 0, some will return either. To simplify, here are
216 * macros to use with any ihandle or phandle return value to check if
217 * it is valid
218 */
219
220#define PROM_ERROR (-1u)
221#define PHANDLE_VALID(p) ((p) != 0 && (p) != PROM_ERROR)
222#define IHANDLE_VALID(i) ((i) != 0 && (i) != PROM_ERROR)
223
224
225/* This is the one and *ONLY* place where we actually call open
226 * firmware.
227 */
228
229static int __init call_prom(const char *service, int nargs, int nret, ...)
230{
231 int i;
232 struct prom_args args;
233 va_list list;
234
Benjamin Herrenschmidt493adff2013-08-07 02:01:38 +1000235 args.service = cpu_to_be32(ADDR(service));
236 args.nargs = cpu_to_be32(nargs);
237 args.nret = cpu_to_be32(nret);
Paul Mackerras9b6b5632005-10-06 12:06:20 +1000238
239 va_start(list, nret);
240 for (i = 0; i < nargs; i++)
Benjamin Herrenschmidt493adff2013-08-07 02:01:38 +1000241 args.args[i] = cpu_to_be32(va_arg(list, prom_arg_t));
Paul Mackerras9b6b5632005-10-06 12:06:20 +1000242 va_end(list);
243
244 for (i = 0; i < nret; i++)
245 args.args[nargs+i] = 0;
246
Anton Blanchard5827d412012-11-26 17:40:03 +0000247 if (enter_prom(&args, prom_entry) < 0)
Paul Mackerrasc49888202005-10-26 21:52:53 +1000248 return PROM_ERROR;
Paul Mackerras9b6b5632005-10-06 12:06:20 +1000249
Benjamin Herrenschmidt493adff2013-08-07 02:01:38 +1000250 return (nret > 0) ? be32_to_cpu(args.args[nargs]) : 0;
Paul Mackerras9b6b5632005-10-06 12:06:20 +1000251}
252
253static int __init call_prom_ret(const char *service, int nargs, int nret,
254 prom_arg_t *rets, ...)
255{
256 int i;
257 struct prom_args args;
258 va_list list;
259
Benjamin Herrenschmidt493adff2013-08-07 02:01:38 +1000260 args.service = cpu_to_be32(ADDR(service));
261 args.nargs = cpu_to_be32(nargs);
262 args.nret = cpu_to_be32(nret);
Paul Mackerras9b6b5632005-10-06 12:06:20 +1000263
264 va_start(list, rets);
265 for (i = 0; i < nargs; i++)
Benjamin Herrenschmidt493adff2013-08-07 02:01:38 +1000266 args.args[i] = cpu_to_be32(va_arg(list, prom_arg_t));
Paul Mackerras9b6b5632005-10-06 12:06:20 +1000267 va_end(list);
268
269 for (i = 0; i < nret; i++)
Olaf Heringed1189b72005-11-29 14:04:05 +0100270 args.args[nargs+i] = 0;
Paul Mackerras9b6b5632005-10-06 12:06:20 +1000271
Anton Blanchard5827d412012-11-26 17:40:03 +0000272 if (enter_prom(&args, prom_entry) < 0)
Paul Mackerrasc49888202005-10-26 21:52:53 +1000273 return PROM_ERROR;
Paul Mackerras9b6b5632005-10-06 12:06:20 +1000274
275 if (rets != NULL)
276 for (i = 1; i < nret; ++i)
Benjamin Herrenschmidt493adff2013-08-07 02:01:38 +1000277 rets[i-1] = be32_to_cpu(args.args[nargs+i]);
Paul Mackerras9b6b5632005-10-06 12:06:20 +1000278
Benjamin Herrenschmidt493adff2013-08-07 02:01:38 +1000279 return (nret > 0) ? be32_to_cpu(args.args[nargs]) : 0;
Paul Mackerras9b6b5632005-10-06 12:06:20 +1000280}
281
282
Paul Mackerras9b6b5632005-10-06 12:06:20 +1000283static void __init prom_print(const char *msg)
284{
285 const char *p, *q;
Paul Mackerras9b6b5632005-10-06 12:06:20 +1000286
Anton Blanchard5827d412012-11-26 17:40:03 +0000287 if (prom.stdout == 0)
Paul Mackerras9b6b5632005-10-06 12:06:20 +1000288 return;
289
290 for (p = msg; *p != 0; p = q) {
291 for (q = p; *q != 0 && *q != '\n'; ++q)
292 ;
293 if (q > p)
Anton Blanchard5827d412012-11-26 17:40:03 +0000294 call_prom("write", 3, 1, prom.stdout, p, q - p);
Paul Mackerras9b6b5632005-10-06 12:06:20 +1000295 if (*q == 0)
296 break;
297 ++q;
Anton Blanchard5827d412012-11-26 17:40:03 +0000298 call_prom("write", 3, 1, prom.stdout, ADDR("\r\n"), 2);
Paul Mackerras9b6b5632005-10-06 12:06:20 +1000299 }
300}
301
302
Mathieu Malaterre8af1da42018-05-29 21:20:01 +0200303/*
304 * Both prom_print_hex & prom_print_dec takes an unsigned long as input so that
305 * we do not need __udivdi3 or __umoddi3 on 32bits.
306 */
Paul Mackerras9b6b5632005-10-06 12:06:20 +1000307static void __init prom_print_hex(unsigned long val)
308{
309 int i, nibbles = sizeof(val)*2;
310 char buf[sizeof(val)*2+1];
Paul Mackerras9b6b5632005-10-06 12:06:20 +1000311
312 for (i = nibbles-1; i >= 0; i--) {
313 buf[i] = (val & 0xf) + '0';
314 if (buf[i] > '9')
315 buf[i] += ('a'-'0'-10);
316 val >>= 4;
317 }
318 buf[nibbles] = '\0';
Anton Blanchard5827d412012-11-26 17:40:03 +0000319 call_prom("write", 3, 1, prom.stdout, buf, nibbles);
Paul Mackerras9b6b5632005-10-06 12:06:20 +1000320}
321
Michael Neuling2c48a7d2010-07-27 18:26:21 +0000322/* max number of decimal digits in an unsigned long */
323#define UL_DIGITS 21
324static void __init prom_print_dec(unsigned long val)
325{
326 int i, size;
327 char buf[UL_DIGITS+1];
Michael Neuling2c48a7d2010-07-27 18:26:21 +0000328
329 for (i = UL_DIGITS-1; i >= 0; i--) {
330 buf[i] = (val % 10) + '0';
331 val = val/10;
332 if (val == 0)
333 break;
334 }
335 /* shift stuff down */
336 size = UL_DIGITS - i;
Anton Blanchard5827d412012-11-26 17:40:03 +0000337 call_prom("write", 3, 1, prom.stdout, buf+i, size);
Michael Neuling2c48a7d2010-07-27 18:26:21 +0000338}
Paul Mackerras9b6b5632005-10-06 12:06:20 +1000339
Mathieu Malaterreeae5f702018-04-06 22:12:19 +0200340__printf(1, 2)
Paul Mackerras9b6b5632005-10-06 12:06:20 +1000341static void __init prom_printf(const char *format, ...)
342{
343 const char *p, *q, *s;
344 va_list args;
345 unsigned long v;
Benjamin Herrenschmidtaf277142011-04-06 10:51:17 +1000346 long vs;
Mathieu Malaterre8af1da42018-05-29 21:20:01 +0200347 int n = 0;
Paul Mackerras9b6b5632005-10-06 12:06:20 +1000348
349 va_start(args, format);
Paul Mackerras9b6b5632005-10-06 12:06:20 +1000350 for (p = format; *p != 0; p = q) {
351 for (q = p; *q != 0 && *q != '\n' && *q != '%'; ++q)
352 ;
353 if (q > p)
Anton Blanchard5827d412012-11-26 17:40:03 +0000354 call_prom("write", 3, 1, prom.stdout, p, q - p);
Paul Mackerras9b6b5632005-10-06 12:06:20 +1000355 if (*q == 0)
356 break;
357 if (*q == '\n') {
358 ++q;
Anton Blanchard5827d412012-11-26 17:40:03 +0000359 call_prom("write", 3, 1, prom.stdout,
Paul Mackerras9b6b5632005-10-06 12:06:20 +1000360 ADDR("\r\n"), 2);
361 continue;
362 }
363 ++q;
364 if (*q == 0)
365 break;
Mathieu Malaterre8af1da42018-05-29 21:20:01 +0200366 while (*q == 'l') {
367 ++q;
368 ++n;
369 }
Paul Mackerras9b6b5632005-10-06 12:06:20 +1000370 switch (*q) {
371 case 's':
372 ++q;
373 s = va_arg(args, const char *);
374 prom_print(s);
375 break;
376 case 'x':
377 ++q;
Mathieu Malaterre8af1da42018-05-29 21:20:01 +0200378 switch (n) {
379 case 0:
380 v = va_arg(args, unsigned int);
381 break;
382 case 1:
383 v = va_arg(args, unsigned long);
384 break;
385 case 2:
386 default:
387 v = va_arg(args, unsigned long long);
388 break;
389 }
Paul Mackerras9b6b5632005-10-06 12:06:20 +1000390 prom_print_hex(v);
391 break;
Mathieu Malaterre8af1da42018-05-29 21:20:01 +0200392 case 'u':
393 ++q;
394 switch (n) {
395 case 0:
396 v = va_arg(args, unsigned int);
397 break;
398 case 1:
399 v = va_arg(args, unsigned long);
400 break;
401 case 2:
402 default:
403 v = va_arg(args, unsigned long long);
404 break;
405 }
406 prom_print_dec(v);
407 break;
Benjamin Herrenschmidtaf277142011-04-06 10:51:17 +1000408 case 'd':
409 ++q;
Mathieu Malaterre8af1da42018-05-29 21:20:01 +0200410 switch (n) {
411 case 0:
412 vs = va_arg(args, int);
413 break;
414 case 1:
415 vs = va_arg(args, long);
416 break;
417 case 2:
418 default:
419 vs = va_arg(args, long long);
420 break;
421 }
Benjamin Herrenschmidtaf277142011-04-06 10:51:17 +1000422 if (vs < 0) {
Anton Blanchard5827d412012-11-26 17:40:03 +0000423 prom_print("-");
Benjamin Herrenschmidtaf277142011-04-06 10:51:17 +1000424 vs = -vs;
425 }
426 prom_print_dec(vs);
427 break;
Paul Mackerras9b6b5632005-10-06 12:06:20 +1000428 }
429 }
Daniel Axtens1b855e12015-12-17 19:41:00 +1100430 va_end(args);
Paul Mackerras9b6b5632005-10-06 12:06:20 +1000431}
432
433
Paul Mackerrasa575b802005-10-23 17:23:21 +1000434static unsigned int __init prom_claim(unsigned long virt, unsigned long size,
435 unsigned long align)
436{
Paul Mackerrasa575b802005-10-23 17:23:21 +1000437
Paul Mackerrasa23414b2005-11-10 12:00:55 +1100438 if (align == 0 && (OF_WORKAROUNDS & OF_WA_CLAIM)) {
439 /*
440 * Old OF requires we claim physical and virtual separately
441 * and then map explicitly (assuming virtual mode)
442 */
443 int ret;
444 prom_arg_t result;
445
446 ret = call_prom_ret("call-method", 5, 2, &result,
Anton Blanchard5827d412012-11-26 17:40:03 +0000447 ADDR("claim"), prom.memory,
Paul Mackerrasa23414b2005-11-10 12:00:55 +1100448 align, size, virt);
449 if (ret != 0 || result == -1)
450 return -1;
451 ret = call_prom_ret("call-method", 5, 2, &result,
Anton Blanchard5827d412012-11-26 17:40:03 +0000452 ADDR("claim"), prom.mmumap,
Paul Mackerrasa23414b2005-11-10 12:00:55 +1100453 align, size, virt);
454 if (ret != 0) {
455 call_prom("call-method", 4, 1, ADDR("release"),
Anton Blanchard5827d412012-11-26 17:40:03 +0000456 prom.memory, size, virt);
Paul Mackerrasa23414b2005-11-10 12:00:55 +1100457 return -1;
458 }
459 /* the 0x12 is M (coherence) + PP == read/write */
Paul Mackerrasa575b802005-10-23 17:23:21 +1000460 call_prom("call-method", 6, 1,
Anton Blanchard5827d412012-11-26 17:40:03 +0000461 ADDR("map"), prom.mmumap, 0x12, size, virt, virt);
Paul Mackerrasa23414b2005-11-10 12:00:55 +1100462 return virt;
463 }
464 return call_prom("claim", 3, 1, (prom_arg_t)virt, (prom_arg_t)size,
465 (prom_arg_t)align);
Paul Mackerrasa575b802005-10-23 17:23:21 +1000466}
467
Paul Mackerras9b6b5632005-10-06 12:06:20 +1000468static void __init __attribute__((noreturn)) prom_panic(const char *reason)
469{
Paul Mackerras9b6b5632005-10-06 12:06:20 +1000470 prom_print(reason);
Olaf Heringadd60ef2006-03-23 22:03:57 +0100471 /* Do not call exit because it clears the screen on pmac
472 * it also causes some sort of double-fault on early pmacs */
Anton Blanchard5827d412012-11-26 17:40:03 +0000473 if (of_platform == PLATFORM_POWERMAC)
Olaf Heringadd60ef2006-03-23 22:03:57 +0100474 asm("trap\n");
475
Stephen Rothwell1d9a4732012-03-21 18:23:27 +0000476 /* ToDo: should put up an SRC here on pSeries */
Paul Mackerras9b6b5632005-10-06 12:06:20 +1000477 call_prom("exit", 0, 0);
478
479 for (;;) /* should never get here */
480 ;
481}
482
483
484static int __init prom_next_node(phandle *nodep)
485{
486 phandle node;
487
488 if ((node = *nodep) != 0
489 && (*nodep = call_prom("child", 1, 1, node)) != 0)
490 return 1;
491 if ((*nodep = call_prom("peer", 1, 1, node)) != 0)
492 return 1;
493 for (;;) {
494 if ((node = call_prom("parent", 1, 1, node)) == 0)
495 return 0;
496 if ((*nodep = call_prom("peer", 1, 1, node)) != 0)
497 return 1;
498 }
499}
500
Tobias Klauser60d862e2016-11-17 17:20:24 +0100501static inline int prom_getprop(phandle node, const char *pname,
Paul Mackerras9b6b5632005-10-06 12:06:20 +1000502 void *value, size_t valuelen)
503{
504 return call_prom("getprop", 4, 1, node, ADDR(pname),
505 (u32)(unsigned long) value, (u32) valuelen);
506}
507
Tobias Klauser60d862e2016-11-17 17:20:24 +0100508static inline int prom_getproplen(phandle node, const char *pname)
Paul Mackerras9b6b5632005-10-06 12:06:20 +1000509{
510 return call_prom("getproplen", 2, 1, node, ADDR(pname));
511}
512
Paul Mackerrasa23414b2005-11-10 12:00:55 +1100513static void add_string(char **str, const char *q)
Paul Mackerras9b6b5632005-10-06 12:06:20 +1000514{
Paul Mackerrasa23414b2005-11-10 12:00:55 +1100515 char *p = *str;
516
517 while (*q)
518 *p++ = *q++;
519 *p++ = ' ';
520 *str = p;
521}
522
523static char *tohex(unsigned int x)
524{
525 static char digits[] = "0123456789abcdef";
526 static char result[9];
527 int i;
528
529 result[8] = 0;
530 i = 8;
531 do {
532 --i;
533 result[i] = digits[x & 0xf];
534 x >>= 4;
535 } while (x != 0 && i > 0);
536 return &result[i];
537}
538
539static int __init prom_setprop(phandle node, const char *nodename,
540 const char *pname, void *value, size_t valuelen)
541{
542 char cmd[256], *p;
543
544 if (!(OF_WORKAROUNDS & OF_WA_LONGTRAIL))
545 return call_prom("setprop", 4, 1, node, ADDR(pname),
546 (u32)(unsigned long) value, (u32) valuelen);
547
548 /* gah... setprop doesn't work on longtrail, have to use interpret */
549 p = cmd;
550 add_string(&p, "dev");
551 add_string(&p, nodename);
552 add_string(&p, tohex((u32)(unsigned long) value));
553 add_string(&p, tohex(valuelen));
554 add_string(&p, tohex(ADDR(pname)));
Anton Blanchard5827d412012-11-26 17:40:03 +0000555 add_string(&p, tohex(strlen(pname)));
Paul Mackerrasa23414b2005-11-10 12:00:55 +1100556 add_string(&p, "property");
557 *p = 0;
558 return call_prom("interpret", 1, 1, (u32)(unsigned long) cmd);
Paul Mackerras9b6b5632005-10-06 12:06:20 +1000559}
560
Anton Blanchard5827d412012-11-26 17:40:03 +0000561/* We can't use the standard versions because of relocation headaches. */
Benjamin Krillcf687872009-07-27 22:02:39 +0000562#define isxdigit(c) (('0' <= (c) && (c) <= '9') \
563 || ('a' <= (c) && (c) <= 'f') \
564 || ('A' <= (c) && (c) <= 'F'))
565
566#define isdigit(c) ('0' <= (c) && (c) <= '9')
567#define islower(c) ('a' <= (c) && (c) <= 'z')
568#define toupper(c) (islower(c) ? ((c) - 'a' + 'A') : (c))
569
Benjamin Herrenschmidt493adff2013-08-07 02:01:38 +1000570static unsigned long prom_strtoul(const char *cp, const char **endp)
Benjamin Krillcf687872009-07-27 22:02:39 +0000571{
572 unsigned long result = 0, base = 10, value;
573
574 if (*cp == '0') {
575 base = 8;
576 cp++;
577 if (toupper(*cp) == 'X') {
578 cp++;
579 base = 16;
580 }
581 }
582
583 while (isxdigit(*cp) &&
584 (value = isdigit(*cp) ? *cp - '0' : toupper(*cp) - 'A' + 10) < base) {
585 result = result * base + value;
586 cp++;
587 }
588
589 if (endp)
590 *endp = cp;
591
592 return result;
593}
594
Benjamin Herrenschmidt493adff2013-08-07 02:01:38 +1000595static unsigned long prom_memparse(const char *ptr, const char **retptr)
Benjamin Krillcf687872009-07-27 22:02:39 +0000596{
597 unsigned long ret = prom_strtoul(ptr, retptr);
598 int shift = 0;
599
600 /*
601 * We can't use a switch here because GCC *may* generate a
602 * jump table which won't work, because we're not running at
603 * the address we're linked at.
604 */
605 if ('G' == **retptr || 'g' == **retptr)
606 shift = 30;
607
608 if ('M' == **retptr || 'm' == **retptr)
609 shift = 20;
610
611 if ('K' == **retptr || 'k' == **retptr)
612 shift = 10;
613
614 if (shift) {
615 ret <<= shift;
616 (*retptr)++;
617 }
618
619 return ret;
620}
621
Paul Mackerras9b6b5632005-10-06 12:06:20 +1000622/*
623 * Early parsing of the command line passed to the kernel, used for
624 * "mem=x" and the options that affect the iommu
625 */
626static void __init early_cmdline_parse(void)
627{
Benjamin Herrenschmidtcc5d0182005-12-13 18:01:21 +1100628 const char *opt;
Benjamin Krillcf687872009-07-27 22:02:39 +0000629
Benjamin Herrenschmidtcc5d0182005-12-13 18:01:21 +1100630 char *p;
Mathieu Malaterreeab00a22018-04-04 22:08:35 +0200631 int l __maybe_unused = 0;
Paul Mackerras9b6b5632005-10-06 12:06:20 +1000632
Anton Blanchard5827d412012-11-26 17:40:03 +0000633 prom_cmd_line[0] = 0;
634 p = prom_cmd_line;
635 if ((long)prom.chosen > 0)
636 l = prom_getprop(prom.chosen, "bootargs", p, COMMAND_LINE_SIZE-1);
Paul Mackerras9b6b5632005-10-06 12:06:20 +1000637#ifdef CONFIG_CMDLINE
Amos Waterland0e4aa9c2006-06-12 23:45:02 -0400638 if (l <= 0 || p[0] == '\0') /* dbl check */
Anton Blanchard5827d412012-11-26 17:40:03 +0000639 strlcpy(prom_cmd_line,
640 CONFIG_CMDLINE, sizeof(prom_cmd_line));
Paul Mackerras9b6b5632005-10-06 12:06:20 +1000641#endif /* CONFIG_CMDLINE */
Anton Blanchard5827d412012-11-26 17:40:03 +0000642 prom_printf("command line: %s\n", prom_cmd_line);
Paul Mackerras9b6b5632005-10-06 12:06:20 +1000643
644#ifdef CONFIG_PPC64
Anton Blanchard5827d412012-11-26 17:40:03 +0000645 opt = strstr(prom_cmd_line, "iommu=");
Paul Mackerras9b6b5632005-10-06 12:06:20 +1000646 if (opt) {
647 prom_printf("iommu opt is: %s\n", opt);
648 opt += 6;
649 while (*opt && *opt == ' ')
650 opt++;
Anton Blanchard5827d412012-11-26 17:40:03 +0000651 if (!strncmp(opt, "off", 3))
652 prom_iommu_off = 1;
653 else if (!strncmp(opt, "force", 5))
654 prom_iommu_force_on = 1;
Paul Mackerras9b6b5632005-10-06 12:06:20 +1000655 }
656#endif
Anton Blanchard5827d412012-11-26 17:40:03 +0000657 opt = strstr(prom_cmd_line, "mem=");
Benjamin Krillcf687872009-07-27 22:02:39 +0000658 if (opt) {
659 opt += 4;
Anton Blanchard5827d412012-11-26 17:40:03 +0000660 prom_memory_limit = prom_memparse(opt, (const char **)&opt);
Benjamin Krillcf687872009-07-27 22:02:39 +0000661#ifdef CONFIG_PPC64
662 /* Align to 16 MB == size of ppc64 large page */
Anton Blanchard5827d412012-11-26 17:40:03 +0000663 prom_memory_limit = ALIGN(prom_memory_limit, 0x1000000);
Benjamin Krillcf687872009-07-27 22:02:39 +0000664#endif
665 }
Suraj Jitindar Singh014d02c2017-02-28 17:03:48 +1100666
667 opt = strstr(prom_cmd_line, "disable_radix");
668 if (opt) {
Aneesh Kumar K.V7a22d632018-03-30 17:39:02 +0530669 opt += 13;
670 if (*opt && *opt == '=') {
671 bool val;
672
673 if (kstrtobool(++opt, &val))
674 prom_radix_disable = false;
675 else
676 prom_radix_disable = val;
677 } else
678 prom_radix_disable = true;
Suraj Jitindar Singh014d02c2017-02-28 17:03:48 +1100679 }
Aneesh Kumar K.V7a22d632018-03-30 17:39:02 +0530680 if (prom_radix_disable)
681 prom_debug("Radix disabled from cmdline\n");
Paul Mackerras9b6b5632005-10-06 12:06:20 +1000682}
683
Benjamin Herrenschmidt27f44882011-09-19 18:27:58 +0000684#if defined(CONFIG_PPC_PSERIES) || defined(CONFIG_PPC_POWERNV)
Paul Mackerras9b6b5632005-10-06 12:06:20 +1000685/*
Nathan Fontenot530b5e12013-04-24 05:53:10 +0000686 * The architecture vector has an array of PVR mask/value pairs,
687 * followed by # option vectors - 1, followed by the option vectors.
688 *
689 * See prom.h for the definition of the bits specified in the
690 * architecture vector.
Paul Mackerrasf709bfa2006-04-28 16:28:35 +1000691 */
Paul Mackerrasf709bfa2006-04-28 16:28:35 +1000692
Michael Ellermane8a4fd02014-08-29 17:01:43 +1000693/* Firmware expects the value to be n - 1, where n is the # of vectors */
694#define NUM_VECTORS(n) ((n) - 1)
695
696/*
697 * Firmware expects 1 + n - 2, where n is the length of the option vector in
698 * bytes. The 1 accounts for the length byte itself, the - 2 .. ?
699 */
700#define VECTOR_LENGTH(n) (1 + (n) - 2)
701
Michael Ellermand03d1d62016-11-18 23:15:41 +1100702struct option_vector1 {
703 u8 byte1;
704 u8 arch_versions;
Paul Mackerrascc3d2942017-01-30 21:21:36 +1100705 u8 arch_versions3;
Michael Ellermand03d1d62016-11-18 23:15:41 +1100706} __packed;
707
708struct option_vector2 {
709 u8 byte1;
710 __be16 reserved;
711 __be32 real_base;
712 __be32 real_size;
713 __be32 virt_base;
714 __be32 virt_size;
715 __be32 load_base;
716 __be32 min_rma;
717 __be32 min_load;
718 u8 min_rma_percent;
719 u8 max_pft_size;
720} __packed;
721
722struct option_vector3 {
723 u8 byte1;
724 u8 byte2;
725} __packed;
726
727struct option_vector4 {
728 u8 byte1;
729 u8 min_vp_cap;
730} __packed;
731
732struct option_vector5 {
733 u8 byte1;
734 u8 byte2;
735 u8 byte3;
736 u8 cmo;
737 u8 associativity;
738 u8 bin_opts;
739 u8 micro_checkpoint;
740 u8 reserved0;
741 __be32 max_cpus;
742 __be16 papr_level;
743 __be16 reserved1;
744 u8 platform_facilities;
745 u8 reserved2;
746 __be16 reserved3;
747 u8 subprocessors;
Paul Mackerrascc3d2942017-01-30 21:21:36 +1100748 u8 byte22;
749 u8 intarch;
750 u8 mmu;
Suraj Jitindar Singh014d02c2017-02-28 17:03:48 +1100751 u8 hash_ext;
752 u8 radix_ext;
Michael Ellermand03d1d62016-11-18 23:15:41 +1100753} __packed;
754
755struct option_vector6 {
756 u8 reserved;
757 u8 secondary_pteg;
758 u8 os_name;
759} __packed;
760
Michael Ellerman76ffb572016-11-18 23:15:42 +1100761struct ibm_arch_vec {
Paul Mackerrascc3d2942017-01-30 21:21:36 +1100762 struct { u32 mask, val; } pvrs[12];
Michael Ellerman76ffb572016-11-18 23:15:42 +1100763
764 u8 num_vectors;
765
766 u8 vec1_len;
767 struct option_vector1 vec1;
768
769 u8 vec2_len;
770 struct option_vector2 vec2;
771
772 u8 vec3_len;
773 struct option_vector3 vec3;
774
775 u8 vec4_len;
776 struct option_vector4 vec4;
777
778 u8 vec5_len;
779 struct option_vector5 vec5;
780
781 u8 vec6_len;
782 struct option_vector6 vec6;
783} __packed;
784
785struct ibm_arch_vec __cacheline_aligned ibm_architecture_vec = {
786 .pvrs = {
787 {
788 .mask = cpu_to_be32(0xfffe0000), /* POWER5/POWER5+ */
789 .val = cpu_to_be32(0x003a0000),
790 },
791 {
792 .mask = cpu_to_be32(0xffff0000), /* POWER6 */
793 .val = cpu_to_be32(0x003e0000),
794 },
795 {
796 .mask = cpu_to_be32(0xffff0000), /* POWER7 */
797 .val = cpu_to_be32(0x003f0000),
798 },
799 {
800 .mask = cpu_to_be32(0xffff0000), /* POWER8E */
801 .val = cpu_to_be32(0x004b0000),
802 },
803 {
804 .mask = cpu_to_be32(0xffff0000), /* POWER8NVL */
805 .val = cpu_to_be32(0x004c0000),
806 },
807 {
808 .mask = cpu_to_be32(0xffff0000), /* POWER8 */
809 .val = cpu_to_be32(0x004d0000),
810 },
811 {
Paul Mackerrascc3d2942017-01-30 21:21:36 +1100812 .mask = cpu_to_be32(0xffff0000), /* POWER9 */
813 .val = cpu_to_be32(0x004e0000),
814 },
815 {
816 .mask = cpu_to_be32(0xffffffff), /* all 3.00-compliant */
817 .val = cpu_to_be32(0x0f000005),
818 },
819 {
Michael Ellerman76ffb572016-11-18 23:15:42 +1100820 .mask = cpu_to_be32(0xffffffff), /* all 2.07-compliant */
821 .val = cpu_to_be32(0x0f000004),
822 },
823 {
824 .mask = cpu_to_be32(0xffffffff), /* all 2.06-compliant */
825 .val = cpu_to_be32(0x0f000003),
826 },
827 {
828 .mask = cpu_to_be32(0xffffffff), /* all 2.05-compliant */
829 .val = cpu_to_be32(0x0f000002),
830 },
831 {
832 .mask = cpu_to_be32(0xfffffffe), /* all 2.04-compliant and earlier */
833 .val = cpu_to_be32(0x0f000001),
834 },
835 },
836
837 .num_vectors = NUM_VECTORS(6),
838
839 .vec1_len = VECTOR_LENGTH(sizeof(struct option_vector1)),
840 .vec1 = {
841 .byte1 = 0,
842 .arch_versions = OV1_PPC_2_00 | OV1_PPC_2_01 | OV1_PPC_2_02 | OV1_PPC_2_03 |
843 OV1_PPC_2_04 | OV1_PPC_2_05 | OV1_PPC_2_06 | OV1_PPC_2_07,
Paul Mackerrascc3d2942017-01-30 21:21:36 +1100844 .arch_versions3 = OV1_PPC_3_00,
Michael Ellerman76ffb572016-11-18 23:15:42 +1100845 },
846
847 .vec2_len = VECTOR_LENGTH(sizeof(struct option_vector2)),
848 /* option vector 2: Open Firmware options supported */
849 .vec2 = {
850 .byte1 = OV2_REAL_MODE,
851 .reserved = 0,
852 .real_base = cpu_to_be32(0xffffffff),
853 .real_size = cpu_to_be32(0xffffffff),
854 .virt_base = cpu_to_be32(0xffffffff),
855 .virt_size = cpu_to_be32(0xffffffff),
856 .load_base = cpu_to_be32(0xffffffff),
Sukadev Bhattiprolu687da8f2017-03-27 19:43:14 -0400857 .min_rma = cpu_to_be32(512), /* 512MB min RMA */
Michael Ellerman76ffb572016-11-18 23:15:42 +1100858 .min_load = cpu_to_be32(0xffffffff), /* full client load */
859 .min_rma_percent = 0, /* min RMA percentage of total RAM */
860 .max_pft_size = 48, /* max log_2(hash table size) */
861 },
862
863 .vec3_len = VECTOR_LENGTH(sizeof(struct option_vector3)),
864 /* option vector 3: processor options supported */
865 .vec3 = {
866 .byte1 = 0, /* don't ignore, don't halt */
867 .byte2 = OV3_FP | OV3_VMX | OV3_DFP,
868 },
869
870 .vec4_len = VECTOR_LENGTH(sizeof(struct option_vector4)),
871 /* option vector 4: IBM PAPR implementation */
872 .vec4 = {
873 .byte1 = 0, /* don't halt */
874 .min_vp_cap = OV4_MIN_ENT_CAP, /* minimum VP entitled capacity */
875 },
876
877 .vec5_len = VECTOR_LENGTH(sizeof(struct option_vector5)),
878 /* option vector 5: PAPR/OF options */
879 .vec5 = {
880 .byte1 = 0, /* don't ignore, don't halt */
881 .byte2 = OV5_FEAT(OV5_LPAR) | OV5_FEAT(OV5_SPLPAR) | OV5_FEAT(OV5_LARGE_PAGES) |
882 OV5_FEAT(OV5_DRCONF_MEMORY) | OV5_FEAT(OV5_DONATE_DEDICATE_CPU) |
883#ifdef CONFIG_PCI_MSI
884 /* PCIe/MSI support. Without MSI full PCIe is not supported */
885 OV5_FEAT(OV5_MSI),
886#else
887 0,
888#endif
889 .byte3 = 0,
890 .cmo =
891#ifdef CONFIG_PPC_SMLPAR
892 OV5_FEAT(OV5_CMO) | OV5_FEAT(OV5_XCMO),
893#else
894 0,
895#endif
896 .associativity = OV5_FEAT(OV5_TYPE1_AFFINITY) | OV5_FEAT(OV5_PRRN),
Michael Roth3dbbaf22017-02-20 19:12:18 -0600897 .bin_opts = OV5_FEAT(OV5_RESIZE_HPT) | OV5_FEAT(OV5_HP_EVT),
Michael Ellerman76ffb572016-11-18 23:15:42 +1100898 .micro_checkpoint = 0,
899 .reserved0 = 0,
900 .max_cpus = cpu_to_be32(NR_CPUS), /* number of cores supported */
901 .papr_level = 0,
902 .reserved1 = 0,
903 .platform_facilities = OV5_FEAT(OV5_PFO_HW_RNG) | OV5_FEAT(OV5_PFO_HW_ENCR) | OV5_FEAT(OV5_PFO_HW_842),
904 .reserved2 = 0,
905 .reserved3 = 0,
906 .subprocessors = 1,
Nathan Fontenot0c38ed62017-12-01 10:48:03 -0600907 .byte22 = OV5_FEAT(OV5_DRMEM_V2),
Paul Mackerrascc3d2942017-01-30 21:21:36 +1100908 .intarch = 0,
Suraj Jitindar Singh014d02c2017-02-28 17:03:48 +1100909 .mmu = 0,
910 .hash_ext = 0,
911 .radix_ext = 0,
Michael Ellerman76ffb572016-11-18 23:15:42 +1100912 },
913
914 /* option vector 6: IBM PAPR hints */
915 .vec6_len = VECTOR_LENGTH(sizeof(struct option_vector6)),
916 .vec6 = {
917 .reserved = 0,
918 .secondary_pteg = 0,
919 .os_name = OV6_LINUX,
920 },
921};
922
Benjamin Herrenschmidt493adff2013-08-07 02:01:38 +1000923/* Old method - ELF header with PT_NOTE sections only works on BE */
924#ifdef __BIG_ENDIAN__
Paul Mackerras9b6b5632005-10-06 12:06:20 +1000925static struct fake_elf {
926 Elf32_Ehdr elfhdr;
927 Elf32_Phdr phdr[2];
928 struct chrpnote {
929 u32 namesz;
930 u32 descsz;
931 u32 type;
932 char name[8]; /* "PowerPC" */
933 struct chrpdesc {
934 u32 real_mode;
935 u32 real_base;
936 u32 real_size;
937 u32 virt_base;
938 u32 virt_size;
939 u32 load_base;
940 } chrpdesc;
941 } chrpnote;
942 struct rpanote {
943 u32 namesz;
944 u32 descsz;
945 u32 type;
946 char name[24]; /* "IBM,RPA-Client-Config" */
947 struct rpadesc {
948 u32 lpar_affinity;
949 u32 min_rmo_size;
950 u32 min_rmo_percent;
951 u32 max_pft_size;
952 u32 splpar;
953 u32 min_load;
954 u32 new_mem_def;
955 u32 ignore_me;
956 } rpadesc;
957 } rpanote;
Paul Mackerras5663a122008-10-31 22:27:17 +1100958} fake_elf = {
Paul Mackerras9b6b5632005-10-06 12:06:20 +1000959 .elfhdr = {
960 .e_ident = { 0x7f, 'E', 'L', 'F',
961 ELFCLASS32, ELFDATA2MSB, EV_CURRENT },
962 .e_type = ET_EXEC, /* yeah right */
963 .e_machine = EM_PPC,
964 .e_version = EV_CURRENT,
965 .e_phoff = offsetof(struct fake_elf, phdr),
966 .e_phentsize = sizeof(Elf32_Phdr),
967 .e_phnum = 2
968 },
969 .phdr = {
970 [0] = {
971 .p_type = PT_NOTE,
972 .p_offset = offsetof(struct fake_elf, chrpnote),
973 .p_filesz = sizeof(struct chrpnote)
974 }, [1] = {
975 .p_type = PT_NOTE,
976 .p_offset = offsetof(struct fake_elf, rpanote),
977 .p_filesz = sizeof(struct rpanote)
978 }
979 },
980 .chrpnote = {
981 .namesz = sizeof("PowerPC"),
982 .descsz = sizeof(struct chrpdesc),
983 .type = 0x1275,
984 .name = "PowerPC",
985 .chrpdesc = {
986 .real_mode = ~0U, /* ~0 means "don't care" */
987 .real_base = ~0U,
988 .real_size = ~0U,
989 .virt_base = ~0U,
990 .virt_size = ~0U,
991 .load_base = ~0U
992 },
993 },
994 .rpanote = {
995 .namesz = sizeof("IBM,RPA-Client-Config"),
996 .descsz = sizeof(struct rpadesc),
997 .type = 0x12759999,
998 .name = "IBM,RPA-Client-Config",
999 .rpadesc = {
Paul Mackerras5663a122008-10-31 22:27:17 +11001000 .lpar_affinity = 0,
1001 .min_rmo_size = 64, /* in megabytes */
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001002 .min_rmo_percent = 0,
Paul Mackerras5663a122008-10-31 22:27:17 +11001003 .max_pft_size = 48, /* 2^48 bytes max PFT size */
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001004 .splpar = 1,
1005 .min_load = ~0U,
Paul Mackerras5663a122008-10-31 22:27:17 +11001006 .new_mem_def = 0
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001007 }
1008 }
1009};
Benjamin Herrenschmidt493adff2013-08-07 02:01:38 +10001010#endif /* __BIG_ENDIAN__ */
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001011
Benjamin Herrenschmidtefec9592010-02-04 14:33:54 +11001012static int __init prom_count_smt_threads(void)
1013{
1014 phandle node;
1015 char type[64];
1016 unsigned int plen;
1017
1018 /* Pick up th first CPU node we can find */
1019 for (node = 0; prom_next_node(&node); ) {
1020 type[0] = 0;
1021 prom_getprop(node, "device_type", type, sizeof(type));
1022
Anton Blanchard5827d412012-11-26 17:40:03 +00001023 if (strcmp(type, "cpu"))
Benjamin Herrenschmidtefec9592010-02-04 14:33:54 +11001024 continue;
1025 /*
1026 * There is an entry for each smt thread, each entry being
1027 * 4 bytes long. All cpus should have the same number of
1028 * smt threads, so return after finding the first.
1029 */
1030 plen = prom_getproplen(node, "ibm,ppc-interrupt-server#s");
1031 if (plen == PROM_ERROR)
1032 break;
1033 plen >>= 2;
Michael Neuling2c48a7d2010-07-27 18:26:21 +00001034 prom_debug("Found %lu smt threads per core\n", (unsigned long)plen);
Benjamin Herrenschmidtefec9592010-02-04 14:33:54 +11001035
1036 /* Sanity check */
1037 if (plen < 1 || plen > 64) {
Michael Neuling2c48a7d2010-07-27 18:26:21 +00001038 prom_printf("Threads per core %lu out of bounds, assuming 1\n",
Benjamin Herrenschmidtefec9592010-02-04 14:33:54 +11001039 (unsigned long)plen);
1040 return 1;
1041 }
1042 return plen;
1043 }
1044 prom_debug("No threads found, assuming 1 per core\n");
1045
1046 return 1;
1047
1048}
1049
Suraj Jitindar Singh014d02c2017-02-28 17:03:48 +11001050static void __init prom_parse_mmu_model(u8 val,
1051 struct platform_support *support)
1052{
1053 switch (val) {
1054 case OV5_FEAT(OV5_MMU_DYNAMIC):
1055 case OV5_FEAT(OV5_MMU_EITHER): /* Either Available */
1056 prom_debug("MMU - either supported\n");
1057 support->radix_mmu = !prom_radix_disable;
1058 support->hash_mmu = true;
1059 break;
1060 case OV5_FEAT(OV5_MMU_RADIX): /* Only Radix */
1061 prom_debug("MMU - radix only\n");
1062 if (prom_radix_disable) {
1063 /*
1064 * If we __have__ to do radix, we're better off ignoring
1065 * the command line rather than not booting.
1066 */
1067 prom_printf("WARNING: Ignoring cmdline option disable_radix\n");
1068 }
1069 support->radix_mmu = true;
1070 break;
1071 case OV5_FEAT(OV5_MMU_HASH):
1072 prom_debug("MMU - hash only\n");
1073 support->hash_mmu = true;
1074 break;
1075 default:
1076 prom_debug("Unknown mmu support option: 0x%x\n", val);
1077 break;
1078 }
1079}
1080
Cédric Le Goaterac5e5a52017-08-30 21:46:16 +02001081static void __init prom_parse_xive_model(u8 val,
1082 struct platform_support *support)
1083{
1084 switch (val) {
1085 case OV5_FEAT(OV5_XIVE_EITHER): /* Either Available */
1086 prom_debug("XIVE - either mode supported\n");
1087 support->xive = true;
1088 break;
1089 case OV5_FEAT(OV5_XIVE_EXPLOIT): /* Only Exploitation mode */
1090 prom_debug("XIVE - exploitation mode supported\n");
1091 support->xive = true;
1092 break;
1093 case OV5_FEAT(OV5_XIVE_LEGACY): /* Only Legacy mode */
1094 prom_debug("XIVE - legacy mode supported\n");
1095 break;
1096 default:
1097 prom_debug("Unknown xive support option: 0x%x\n", val);
1098 break;
1099 }
1100}
1101
Suraj Jitindar Singh014d02c2017-02-28 17:03:48 +11001102static void __init prom_parse_platform_support(u8 index, u8 val,
1103 struct platform_support *support)
1104{
1105 switch (index) {
1106 case OV5_INDX(OV5_MMU_SUPPORT): /* MMU Model */
1107 prom_parse_mmu_model(val & OV5_FEAT(OV5_MMU_SUPPORT), support);
1108 break;
1109 case OV5_INDX(OV5_RADIX_GTSE): /* Radix Extensions */
1110 if (val & OV5_FEAT(OV5_RADIX_GTSE)) {
1111 prom_debug("Radix - GTSE supported\n");
1112 support->radix_gtse = true;
1113 }
1114 break;
Cédric Le Goaterac5e5a52017-08-30 21:46:16 +02001115 case OV5_INDX(OV5_XIVE_SUPPORT): /* Interrupt mode */
1116 prom_parse_xive_model(val & OV5_FEAT(OV5_XIVE_SUPPORT),
1117 support);
1118 break;
Suraj Jitindar Singh014d02c2017-02-28 17:03:48 +11001119 }
1120}
1121
1122static void __init prom_check_platform_support(void)
1123{
1124 struct platform_support supported = {
1125 .hash_mmu = false,
1126 .radix_mmu = false,
Cédric Le Goaterac5e5a52017-08-30 21:46:16 +02001127 .radix_gtse = false,
1128 .xive = false
Suraj Jitindar Singh014d02c2017-02-28 17:03:48 +11001129 };
1130 int prop_len = prom_getproplen(prom.chosen,
1131 "ibm,arch-vec-5-platform-support");
1132 if (prop_len > 1) {
1133 int i;
Suraj Jitindar Singhab912392018-09-05 12:09:50 +10001134 u8 vec[8];
Suraj Jitindar Singh014d02c2017-02-28 17:03:48 +11001135 prom_debug("Found ibm,arch-vec-5-platform-support, len: %d\n",
1136 prop_len);
Suraj Jitindar Singhab912392018-09-05 12:09:50 +10001137 if (prop_len > sizeof(vec))
1138 prom_printf("WARNING: ibm,arch-vec-5-platform-support longer than expected (len: %d)\n",
1139 prop_len);
Suraj Jitindar Singh014d02c2017-02-28 17:03:48 +11001140 prom_getprop(prom.chosen, "ibm,arch-vec-5-platform-support",
1141 &vec, sizeof(vec));
Suraj Jitindar Singhab912392018-09-05 12:09:50 +10001142 for (i = 0; i < sizeof(vec); i += 2) {
Suraj Jitindar Singh014d02c2017-02-28 17:03:48 +11001143 prom_debug("%d: index = 0x%x val = 0x%x\n", i / 2
1144 , vec[i]
1145 , vec[i + 1]);
1146 prom_parse_platform_support(vec[i], vec[i + 1],
1147 &supported);
1148 }
1149 }
1150
Alexey Kardashevskiy79b46862018-01-09 16:45:20 +11001151 if (supported.radix_mmu && supported.radix_gtse &&
1152 IS_ENABLED(CONFIG_PPC_RADIX_MMU)) {
Suraj Jitindar Singh014d02c2017-02-28 17:03:48 +11001153 /* Radix preferred - but we require GTSE for now */
1154 prom_debug("Asking for radix with GTSE\n");
1155 ibm_architecture_vec.vec5.mmu = OV5_FEAT(OV5_MMU_RADIX);
1156 ibm_architecture_vec.vec5.radix_ext = OV5_FEAT(OV5_RADIX_GTSE);
1157 } else if (supported.hash_mmu) {
1158 /* Default to hash mmu (if we can) */
1159 prom_debug("Asking for hash\n");
1160 ibm_architecture_vec.vec5.mmu = OV5_FEAT(OV5_MMU_HASH);
1161 } else {
1162 /* We're probably on a legacy hypervisor */
1163 prom_debug("Assuming legacy hash support\n");
1164 }
Cédric Le Goaterac5e5a52017-08-30 21:46:16 +02001165
1166 if (supported.xive) {
1167 prom_debug("Asking for XIVE\n");
1168 ibm_architecture_vec.vec5.intarch = OV5_FEAT(OV5_XIVE_EXPLOIT);
1169 }
Suraj Jitindar Singh014d02c2017-02-28 17:03:48 +11001170}
Benjamin Herrenschmidtefec9592010-02-04 14:33:54 +11001171
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001172static void __init prom_send_capabilities(void)
1173{
Benjamin Herrenschmidt493adff2013-08-07 02:01:38 +10001174 ihandle root;
Paul Mackerrasf709bfa2006-04-28 16:28:35 +10001175 prom_arg_t ret;
Laurent Dufourdbd0c5d2013-09-17 11:52:48 +02001176 u32 cores;
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001177
Suraj Jitindar Singh014d02c2017-02-28 17:03:48 +11001178 /* Check ibm,arch-vec-5-platform-support and fixup vec5 if required */
1179 prom_check_platform_support();
1180
Paul Mackerrasf709bfa2006-04-28 16:28:35 +10001181 root = call_prom("open", 1, 1, ADDR("/"));
1182 if (root != 0) {
Benjamin Herrenschmidtefec9592010-02-04 14:33:54 +11001183 /* We need to tell the FW about the number of cores we support.
1184 *
1185 * To do that, we count the number of threads on the first core
1186 * (we assume this is the same for all cores) and use it to
1187 * divide NR_CPUS.
1188 */
Laurent Dufourdbd0c5d2013-09-17 11:52:48 +02001189
Michael Ellerman76ffb572016-11-18 23:15:42 +11001190 cores = DIV_ROUND_UP(NR_CPUS, prom_count_smt_threads());
Mathieu Malaterreeae5f702018-04-06 22:12:19 +02001191 prom_printf("Max number of cores passed to firmware: %u (NR_CPUS = %d)\n",
Michael Ellerman76ffb572016-11-18 23:15:42 +11001192 cores, NR_CPUS);
1193
1194 ibm_architecture_vec.vec5.max_cpus = cpu_to_be32(cores);
Benjamin Herrenschmidtefec9592010-02-04 14:33:54 +11001195
Paul Mackerrasf709bfa2006-04-28 16:28:35 +10001196 /* try calling the ibm,client-architecture-support method */
Anton Blanchard049d0492009-09-21 20:47:39 +00001197 prom_printf("Calling ibm,client-architecture-support...");
Paul Mackerrasf709bfa2006-04-28 16:28:35 +10001198 if (call_prom_ret("call-method", 3, 2, &ret,
1199 ADDR("ibm,client-architecture-support"),
Benjamin Herrenschmidt33b74972006-06-07 12:01:32 +10001200 root,
Michael Ellerman76ffb572016-11-18 23:15:42 +11001201 ADDR(&ibm_architecture_vec)) == 0) {
Paul Mackerrasf709bfa2006-04-28 16:28:35 +10001202 /* the call exists... */
1203 if (ret)
Anton Blanchard4da727a2009-03-31 20:06:14 +00001204 prom_printf("\nWARNING: ibm,client-architecture"
Paul Mackerrasf709bfa2006-04-28 16:28:35 +10001205 "-support call FAILED!\n");
1206 call_prom("close", 1, 0, root);
Anton Blanchard4da727a2009-03-31 20:06:14 +00001207 prom_printf(" done\n");
Paul Mackerrasf709bfa2006-04-28 16:28:35 +10001208 return;
1209 }
1210 call_prom("close", 1, 0, root);
Anton Blanchard049d0492009-09-21 20:47:39 +00001211 prom_printf(" not implemented\n");
Paul Mackerrasf709bfa2006-04-28 16:28:35 +10001212 }
1213
Benjamin Herrenschmidt493adff2013-08-07 02:01:38 +10001214#ifdef __BIG_ENDIAN__
1215 {
1216 ihandle elfloader;
1217
1218 /* no ibm,client-architecture-support call, try the old way */
1219 elfloader = call_prom("open", 1, 1,
1220 ADDR("/packages/elf-loader"));
1221 if (elfloader == 0) {
1222 prom_printf("couldn't open /packages/elf-loader\n");
1223 return;
1224 }
1225 call_prom("call-method", 3, 1, ADDR("process-elf-header"),
1226 elfloader, ADDR(&fake_elf));
1227 call_prom("close", 1, 0, elfloader);
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001228 }
Benjamin Herrenschmidt493adff2013-08-07 02:01:38 +10001229#endif /* __BIG_ENDIAN__ */
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001230}
Benjamin Herrenschmidt493adff2013-08-07 02:01:38 +10001231#endif /* #if defined(CONFIG_PPC_PSERIES) || defined(CONFIG_PPC_POWERNV) */
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001232
1233/*
1234 * Memory allocation strategy... our layout is normally:
1235 *
1236 * at 14Mb or more we have vmlinux, then a gap and initrd. In some
1237 * rare cases, initrd might end up being before the kernel though.
1238 * We assume this won't override the final kernel at 0, we have no
1239 * provision to handle that in this version, but it should hopefully
1240 * never happen.
1241 *
1242 * alloc_top is set to the top of RMO, eventually shrink down if the
1243 * TCEs overlap
1244 *
1245 * alloc_bottom is set to the top of kernel/initrd
1246 *
1247 * from there, allocations are done this way : rtas is allocated
1248 * topmost, and the device-tree is allocated from the bottom. We try
1249 * to grow the device-tree allocation as we progress. If we can't,
1250 * then we fail, we don't currently have a facility to restart
1251 * elsewhere, but that shouldn't be necessary.
1252 *
1253 * Note that calls to reserve_mem have to be done explicitly, memory
1254 * allocated with either alloc_up or alloc_down isn't automatically
1255 * reserved.
1256 */
1257
1258
1259/*
1260 * Allocates memory in the RMO upward from the kernel/initrd
1261 *
1262 * When align is 0, this is a special case, it means to allocate in place
1263 * at the current location of alloc_bottom or fail (that is basically
1264 * extending the previous allocation). Used for the device-tree flattening
1265 */
1266static unsigned long __init alloc_up(unsigned long size, unsigned long align)
1267{
Anton Blanchard5827d412012-11-26 17:40:03 +00001268 unsigned long base = alloc_bottom;
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001269 unsigned long addr = 0;
1270
Paul Mackerrasc49888202005-10-26 21:52:53 +10001271 if (align)
1272 base = _ALIGN_UP(base, align);
Mathieu Malaterreeae5f702018-04-06 22:12:19 +02001273 prom_debug("%s(%lx, %lx)\n", __func__, size, align);
Anton Blanchard5827d412012-11-26 17:40:03 +00001274 if (ram_top == 0)
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001275 prom_panic("alloc_up() called with mem not initialized\n");
1276
1277 if (align)
Anton Blanchard5827d412012-11-26 17:40:03 +00001278 base = _ALIGN_UP(alloc_bottom, align);
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001279 else
Anton Blanchard5827d412012-11-26 17:40:03 +00001280 base = alloc_bottom;
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001281
Anton Blanchard5827d412012-11-26 17:40:03 +00001282 for(; (base + size) <= alloc_top;
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001283 base = _ALIGN_UP(base + 0x100000, align)) {
Mathieu Malaterreeae5f702018-04-06 22:12:19 +02001284 prom_debug(" trying: 0x%lx\n\r", base);
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001285 addr = (unsigned long)prom_claim(base, size, 0);
Paul Mackerrasc49888202005-10-26 21:52:53 +10001286 if (addr != PROM_ERROR && addr != 0)
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001287 break;
1288 addr = 0;
1289 if (align == 0)
1290 break;
1291 }
1292 if (addr == 0)
1293 return 0;
Anton Blanchard5827d412012-11-26 17:40:03 +00001294 alloc_bottom = addr + size;
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001295
Mathieu Malaterreeae5f702018-04-06 22:12:19 +02001296 prom_debug(" -> %lx\n", addr);
1297 prom_debug(" alloc_bottom : %lx\n", alloc_bottom);
1298 prom_debug(" alloc_top : %lx\n", alloc_top);
1299 prom_debug(" alloc_top_hi : %lx\n", alloc_top_high);
1300 prom_debug(" rmo_top : %lx\n", rmo_top);
1301 prom_debug(" ram_top : %lx\n", ram_top);
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001302
1303 return addr;
1304}
1305
1306/*
1307 * Allocates memory downward, either from top of RMO, or if highmem
1308 * is set, from the top of RAM. Note that this one doesn't handle
1309 * failures. It does claim memory if highmem is not set.
1310 */
1311static unsigned long __init alloc_down(unsigned long size, unsigned long align,
1312 int highmem)
1313{
1314 unsigned long base, addr = 0;
1315
Mathieu Malaterreeae5f702018-04-06 22:12:19 +02001316 prom_debug("%s(%lx, %lx, %s)\n", __func__, size, align,
Anton Blanchard5827d412012-11-26 17:40:03 +00001317 highmem ? "(high)" : "(low)");
1318 if (ram_top == 0)
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001319 prom_panic("alloc_down() called with mem not initialized\n");
1320
1321 if (highmem) {
1322 /* Carve out storage for the TCE table. */
Anton Blanchard5827d412012-11-26 17:40:03 +00001323 addr = _ALIGN_DOWN(alloc_top_high - size, align);
1324 if (addr <= alloc_bottom)
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001325 return 0;
1326 /* Will we bump into the RMO ? If yes, check out that we
1327 * didn't overlap existing allocations there, if we did,
1328 * we are dead, we must be the first in town !
1329 */
Anton Blanchard5827d412012-11-26 17:40:03 +00001330 if (addr < rmo_top) {
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001331 /* Good, we are first */
Anton Blanchard5827d412012-11-26 17:40:03 +00001332 if (alloc_top == rmo_top)
1333 alloc_top = rmo_top = addr;
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001334 else
1335 return 0;
1336 }
Anton Blanchard5827d412012-11-26 17:40:03 +00001337 alloc_top_high = addr;
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001338 goto bail;
1339 }
1340
Anton Blanchard5827d412012-11-26 17:40:03 +00001341 base = _ALIGN_DOWN(alloc_top - size, align);
1342 for (; base > alloc_bottom;
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001343 base = _ALIGN_DOWN(base - 0x100000, align)) {
Mathieu Malaterreeae5f702018-04-06 22:12:19 +02001344 prom_debug(" trying: 0x%lx\n\r", base);
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001345 addr = (unsigned long)prom_claim(base, size, 0);
Paul Mackerrasc49888202005-10-26 21:52:53 +10001346 if (addr != PROM_ERROR && addr != 0)
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001347 break;
1348 addr = 0;
1349 }
1350 if (addr == 0)
1351 return 0;
Anton Blanchard5827d412012-11-26 17:40:03 +00001352 alloc_top = addr;
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001353
1354 bail:
Mathieu Malaterreeae5f702018-04-06 22:12:19 +02001355 prom_debug(" -> %lx\n", addr);
1356 prom_debug(" alloc_bottom : %lx\n", alloc_bottom);
1357 prom_debug(" alloc_top : %lx\n", alloc_top);
1358 prom_debug(" alloc_top_hi : %lx\n", alloc_top_high);
1359 prom_debug(" rmo_top : %lx\n", rmo_top);
1360 prom_debug(" ram_top : %lx\n", ram_top);
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001361
1362 return addr;
1363}
1364
1365/*
1366 * Parse a "reg" cell
1367 */
1368static unsigned long __init prom_next_cell(int s, cell_t **cellp)
1369{
1370 cell_t *p = *cellp;
1371 unsigned long r = 0;
1372
1373 /* Ignore more than 2 cells */
1374 while (s > sizeof(unsigned long) / 4) {
1375 p++;
1376 s--;
1377 }
Benjamin Herrenschmidt493adff2013-08-07 02:01:38 +10001378 r = be32_to_cpu(*p++);
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001379#ifdef CONFIG_PPC64
Paul Mackerras35499c02005-10-22 16:02:39 +10001380 if (s > 1) {
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001381 r <<= 32;
Benjamin Herrenschmidt493adff2013-08-07 02:01:38 +10001382 r |= be32_to_cpu(*(p++));
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001383 }
1384#endif
1385 *cellp = p;
1386 return r;
1387}
1388
1389/*
1390 * Very dumb function for adding to the memory reserve list, but
1391 * we don't need anything smarter at this point
1392 *
1393 * XXX Eventually check for collisions. They should NEVER happen.
1394 * If problems seem to show up, it would be a good start to track
1395 * them down.
1396 */
Michael Ellerman0108d3f2007-05-07 15:58:28 +10001397static void __init reserve_mem(u64 base, u64 size)
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001398{
Kumar Galacbbcf342006-01-11 17:57:13 -06001399 u64 top = base + size;
Anton Blanchard5827d412012-11-26 17:40:03 +00001400 unsigned long cnt = mem_reserve_cnt;
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001401
1402 if (size == 0)
1403 return;
1404
1405 /* We need to always keep one empty entry so that we
1406 * have our terminator with "size" set to 0 since we are
1407 * dumb and just copy this entire array to the boot params
1408 */
1409 base = _ALIGN_DOWN(base, PAGE_SIZE);
1410 top = _ALIGN_UP(top, PAGE_SIZE);
1411 size = top - base;
1412
1413 if (cnt >= (MEM_RESERVE_MAP_SIZE - 1))
1414 prom_panic("Memory reserve map exhausted !\n");
Benjamin Herrenschmidt493adff2013-08-07 02:01:38 +10001415 mem_reserve_map[cnt].base = cpu_to_be64(base);
1416 mem_reserve_map[cnt].size = cpu_to_be64(size);
Anton Blanchard5827d412012-11-26 17:40:03 +00001417 mem_reserve_cnt = cnt + 1;
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001418}
1419
1420/*
Adrian Bunkb3c2ffd2006-06-30 18:20:44 +02001421 * Initialize memory allocation mechanism, parse "memory" nodes and
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001422 * obtain that way the top of memory and RMO to setup out local allocator
1423 */
1424static void __init prom_init_mem(void)
1425{
1426 phandle node;
Mathieu Malaterreeab00a22018-04-04 22:08:35 +02001427#ifdef DEBUG_PROM
1428 char *path;
1429#endif
1430 char type[64];
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001431 unsigned int plen;
1432 cell_t *p, *endp;
Benjamin Herrenschmidt493adff2013-08-07 02:01:38 +10001433 __be32 val;
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001434 u32 rac, rsc;
1435
1436 /*
1437 * We iterate the memory nodes to find
1438 * 1) top of RMO (first node)
1439 * 2) top of memory
1440 */
Benjamin Herrenschmidt493adff2013-08-07 02:01:38 +10001441 val = cpu_to_be32(2);
1442 prom_getprop(prom.root, "#address-cells", &val, sizeof(val));
1443 rac = be32_to_cpu(val);
1444 val = cpu_to_be32(1);
1445 prom_getprop(prom.root, "#size-cells", &val, sizeof(rsc));
1446 rsc = be32_to_cpu(val);
1447 prom_debug("root_addr_cells: %x\n", rac);
1448 prom_debug("root_size_cells: %x\n", rsc);
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001449
1450 prom_debug("scanning memory:\n");
Mathieu Malaterreeab00a22018-04-04 22:08:35 +02001451#ifdef DEBUG_PROM
Anton Blanchard5827d412012-11-26 17:40:03 +00001452 path = prom_scratch;
Mathieu Malaterreeab00a22018-04-04 22:08:35 +02001453#endif
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001454
1455 for (node = 0; prom_next_node(&node); ) {
1456 type[0] = 0;
1457 prom_getprop(node, "device_type", type, sizeof(type));
1458
Paul Mackerrasc49888202005-10-26 21:52:53 +10001459 if (type[0] == 0) {
1460 /*
1461 * CHRP Longtrail machines have no device_type
1462 * on the memory node, so check the name instead...
1463 */
1464 prom_getprop(node, "name", type, sizeof(type));
1465 }
Anton Blanchard5827d412012-11-26 17:40:03 +00001466 if (strcmp(type, "memory"))
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001467 continue;
Paul Mackerrasc49888202005-10-26 21:52:53 +10001468
Anton Blanchard5827d412012-11-26 17:40:03 +00001469 plen = prom_getprop(node, "reg", regbuf, sizeof(regbuf));
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001470 if (plen > sizeof(regbuf)) {
1471 prom_printf("memory node too large for buffer !\n");
1472 plen = sizeof(regbuf);
1473 }
Anton Blanchard5827d412012-11-26 17:40:03 +00001474 p = regbuf;
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001475 endp = p + (plen / sizeof(cell_t));
1476
1477#ifdef DEBUG_PROM
1478 memset(path, 0, PROM_SCRATCH_SIZE);
1479 call_prom("package-to-path", 3, 1, node, path, PROM_SCRATCH_SIZE-1);
1480 prom_debug(" node %s :\n", path);
1481#endif /* DEBUG_PROM */
1482
1483 while ((endp - p) >= (rac + rsc)) {
1484 unsigned long base, size;
1485
1486 base = prom_next_cell(rac, &p);
1487 size = prom_next_cell(rsc, &p);
1488
1489 if (size == 0)
1490 continue;
Mathieu Malaterreeae5f702018-04-06 22:12:19 +02001491 prom_debug(" %lx %lx\n", base, size);
Anton Blanchard5827d412012-11-26 17:40:03 +00001492 if (base == 0 && (of_platform & PLATFORM_LPAR))
1493 rmo_top = size;
1494 if ((base + size) > ram_top)
1495 ram_top = base + size;
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001496 }
1497 }
1498
Anton Blanchard5827d412012-11-26 17:40:03 +00001499 alloc_bottom = PAGE_ALIGN((unsigned long)&_end + 0x4000);
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001500
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001501 /*
Benjamin Krillcf687872009-07-27 22:02:39 +00001502 * If prom_memory_limit is set we reduce the upper limits *except* for
1503 * alloc_top_high. This must be the real top of RAM so we can put
1504 * TCE's up there.
1505 */
1506
Anton Blanchard5827d412012-11-26 17:40:03 +00001507 alloc_top_high = ram_top;
Benjamin Krillcf687872009-07-27 22:02:39 +00001508
Anton Blanchard5827d412012-11-26 17:40:03 +00001509 if (prom_memory_limit) {
1510 if (prom_memory_limit <= alloc_bottom) {
Mathieu Malaterreeae5f702018-04-06 22:12:19 +02001511 prom_printf("Ignoring mem=%lx <= alloc_bottom.\n",
1512 prom_memory_limit);
Anton Blanchard5827d412012-11-26 17:40:03 +00001513 prom_memory_limit = 0;
1514 } else if (prom_memory_limit >= ram_top) {
Mathieu Malaterreeae5f702018-04-06 22:12:19 +02001515 prom_printf("Ignoring mem=%lx >= ram_top.\n",
1516 prom_memory_limit);
Anton Blanchard5827d412012-11-26 17:40:03 +00001517 prom_memory_limit = 0;
Benjamin Krillcf687872009-07-27 22:02:39 +00001518 } else {
Anton Blanchard5827d412012-11-26 17:40:03 +00001519 ram_top = prom_memory_limit;
1520 rmo_top = min(rmo_top, prom_memory_limit);
Benjamin Krillcf687872009-07-27 22:02:39 +00001521 }
1522 }
1523
1524 /*
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001525 * Setup our top alloc point, that is top of RMO or top of
1526 * segment 0 when running non-LPAR.
1527 * Some RS64 machines have buggy firmware where claims up at
1528 * 1GB fail. Cap at 768MB as a workaround.
1529 * Since 768MB is plenty of room, and we need to cap to something
1530 * reasonable on 32-bit, cap at 768MB on all machines.
1531 */
Anton Blanchard5827d412012-11-26 17:40:03 +00001532 if (!rmo_top)
1533 rmo_top = ram_top;
1534 rmo_top = min(0x30000000ul, rmo_top);
1535 alloc_top = rmo_top;
1536 alloc_top_high = ram_top;
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001537
Paul Mackerras64968f62011-12-13 17:54:13 +00001538 /*
1539 * Check if we have an initrd after the kernel but still inside
1540 * the RMO. If we do move our bottom point to after it.
1541 */
Anton Blanchard5827d412012-11-26 17:40:03 +00001542 if (prom_initrd_start &&
1543 prom_initrd_start < rmo_top &&
1544 prom_initrd_end > alloc_bottom)
1545 alloc_bottom = PAGE_ALIGN(prom_initrd_end);
Paul Mackerras64968f62011-12-13 17:54:13 +00001546
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001547 prom_printf("memory layout at init:\n");
Mathieu Malaterreeae5f702018-04-06 22:12:19 +02001548 prom_printf(" memory_limit : %lx (16 MB aligned)\n",
1549 prom_memory_limit);
1550 prom_printf(" alloc_bottom : %lx\n", alloc_bottom);
1551 prom_printf(" alloc_top : %lx\n", alloc_top);
1552 prom_printf(" alloc_top_hi : %lx\n", alloc_top_high);
1553 prom_printf(" rmo_top : %lx\n", rmo_top);
1554 prom_printf(" ram_top : %lx\n", ram_top);
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001555}
1556
Benjamin Herrenschmidt27f44882011-09-19 18:27:58 +00001557static void __init prom_close_stdin(void)
1558{
Benjamin Herrenschmidt493adff2013-08-07 02:01:38 +10001559 __be32 val;
1560 ihandle stdin;
Benjamin Herrenschmidt27f44882011-09-19 18:27:58 +00001561
Benjamin Herrenschmidt493adff2013-08-07 02:01:38 +10001562 if (prom_getprop(prom.chosen, "stdin", &val, sizeof(val)) > 0) {
1563 stdin = be32_to_cpu(val);
1564 call_prom("close", 1, 0, stdin);
1565 }
Benjamin Herrenschmidt27f44882011-09-19 18:27:58 +00001566}
1567
1568#ifdef CONFIG_PPC_POWERNV
1569
Benjamin Herrenschmidt6e35d5d2011-09-19 18:28:01 +00001570#ifdef CONFIG_PPC_EARLY_DEBUG_OPAL
1571static u64 __initdata prom_opal_base;
1572static u64 __initdata prom_opal_entry;
1573#endif
1574
Benjamin Herrenschmidt6e35d5d2011-09-19 18:28:01 +00001575/*
1576 * Allocate room for and instantiate OPAL
1577 */
1578static void __init prom_instantiate_opal(void)
1579{
1580 phandle opal_node;
1581 ihandle opal_inst;
1582 u64 base, entry;
1583 u64 size = 0, align = 0x10000;
Benjamin Herrenschmidt493adff2013-08-07 02:01:38 +10001584 __be64 val64;
Benjamin Herrenschmidt6e35d5d2011-09-19 18:28:01 +00001585 u32 rets[2];
1586
1587 prom_debug("prom_instantiate_opal: start...\n");
1588
1589 opal_node = call_prom("finddevice", 1, 1, ADDR("/ibm,opal"));
1590 prom_debug("opal_node: %x\n", opal_node);
1591 if (!PHANDLE_VALID(opal_node))
1592 return;
1593
Benjamin Herrenschmidt493adff2013-08-07 02:01:38 +10001594 val64 = 0;
1595 prom_getprop(opal_node, "opal-runtime-size", &val64, sizeof(val64));
1596 size = be64_to_cpu(val64);
Benjamin Herrenschmidt6e35d5d2011-09-19 18:28:01 +00001597 if (size == 0)
1598 return;
Benjamin Herrenschmidt493adff2013-08-07 02:01:38 +10001599 val64 = 0;
1600 prom_getprop(opal_node, "opal-runtime-alignment", &val64,sizeof(val64));
1601 align = be64_to_cpu(val64);
Benjamin Herrenschmidt6e35d5d2011-09-19 18:28:01 +00001602
1603 base = alloc_down(size, align, 0);
1604 if (base == 0) {
1605 prom_printf("OPAL allocation failed !\n");
1606 return;
1607 }
1608
1609 opal_inst = call_prom("open", 1, 1, ADDR("/ibm,opal"));
1610 if (!IHANDLE_VALID(opal_inst)) {
1611 prom_printf("opening opal package failed (%x)\n", opal_inst);
1612 return;
1613 }
1614
Mathieu Malaterreeae5f702018-04-06 22:12:19 +02001615 prom_printf("instantiating opal at 0x%llx...", base);
Benjamin Herrenschmidt6e35d5d2011-09-19 18:28:01 +00001616
1617 if (call_prom_ret("call-method", 4, 3, rets,
1618 ADDR("load-opal-runtime"),
1619 opal_inst,
1620 base >> 32, base & 0xffffffff) != 0
1621 || (rets[0] == 0 && rets[1] == 0)) {
1622 prom_printf(" failed\n");
1623 return;
1624 }
1625 entry = (((u64)rets[0]) << 32) | rets[1];
1626
1627 prom_printf(" done\n");
1628
1629 reserve_mem(base, size);
1630
Mathieu Malaterreeae5f702018-04-06 22:12:19 +02001631 prom_debug("opal base = 0x%llx\n", base);
1632 prom_debug("opal align = 0x%llx\n", align);
1633 prom_debug("opal entry = 0x%llx\n", entry);
1634 prom_debug("opal size = 0x%llx\n", size);
Benjamin Herrenschmidt6e35d5d2011-09-19 18:28:01 +00001635
1636 prom_setprop(opal_node, "/ibm,opal", "opal-base-address",
1637 &base, sizeof(base));
1638 prom_setprop(opal_node, "/ibm,opal", "opal-entry-address",
1639 &entry, sizeof(entry));
1640
1641#ifdef CONFIG_PPC_EARLY_DEBUG_OPAL
Anton Blanchard5827d412012-11-26 17:40:03 +00001642 prom_opal_base = base;
1643 prom_opal_entry = entry;
Benjamin Herrenschmidt6e35d5d2011-09-19 18:28:01 +00001644#endif
1645 prom_debug("prom_instantiate_opal: end...\n");
1646}
1647
Benjamin Herrenschmidt27f44882011-09-19 18:27:58 +00001648#endif /* CONFIG_PPC_POWERNV */
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001649
1650/*
1651 * Allocate room for and instantiate RTAS
1652 */
1653static void __init prom_instantiate_rtas(void)
1654{
1655 phandle rtas_node;
1656 ihandle rtas_inst;
1657 u32 base, entry = 0;
Benjamin Herrenschmidt493adff2013-08-07 02:01:38 +10001658 __be32 val;
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001659 u32 size = 0;
1660
1661 prom_debug("prom_instantiate_rtas: start...\n");
1662
1663 rtas_node = call_prom("finddevice", 1, 1, ADDR("/rtas"));
1664 prom_debug("rtas_node: %x\n", rtas_node);
1665 if (!PHANDLE_VALID(rtas_node))
1666 return;
1667
Benjamin Herrenschmidt493adff2013-08-07 02:01:38 +10001668 val = 0;
1669 prom_getprop(rtas_node, "rtas-size", &val, sizeof(size));
1670 size = be32_to_cpu(val);
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001671 if (size == 0)
1672 return;
1673
1674 base = alloc_down(size, PAGE_SIZE, 0);
Anton Blanchard6d1e2c62011-11-14 12:55:47 +00001675 if (base == 0)
1676 prom_panic("Could not allocate memory for RTAS\n");
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001677
1678 rtas_inst = call_prom("open", 1, 1, ADDR("/rtas"));
1679 if (!IHANDLE_VALID(rtas_inst)) {
Paul Mackerrasa23414b2005-11-10 12:00:55 +11001680 prom_printf("opening rtas package failed (%x)\n", rtas_inst);
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001681 return;
1682 }
1683
Anton Blanchard1f8737a2009-03-31 20:06:15 +00001684 prom_printf("instantiating rtas at 0x%x...", base);
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001685
1686 if (call_prom_ret("call-method", 3, 2, &entry,
1687 ADDR("instantiate-rtas"),
Paul Mackerrasa23414b2005-11-10 12:00:55 +11001688 rtas_inst, base) != 0
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001689 || entry == 0) {
1690 prom_printf(" failed\n");
1691 return;
1692 }
1693 prom_printf(" done\n");
1694
1695 reserve_mem(base, size);
1696
Benjamin Herrenschmidt493adff2013-08-07 02:01:38 +10001697 val = cpu_to_be32(base);
Paul Mackerrasa23414b2005-11-10 12:00:55 +11001698 prom_setprop(rtas_node, "/rtas", "linux,rtas-base",
Benjamin Herrenschmidt493adff2013-08-07 02:01:38 +10001699 &val, sizeof(val));
1700 val = cpu_to_be32(entry);
Paul Mackerrasa23414b2005-11-10 12:00:55 +11001701 prom_setprop(rtas_node, "/rtas", "linux,rtas-entry",
Benjamin Herrenschmidt493adff2013-08-07 02:01:38 +10001702 &val, sizeof(val));
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001703
Benjamin Herrenschmidtdbe78b42013-09-25 14:02:50 +10001704 /* Check if it supports "query-cpu-stopped-state" */
1705 if (prom_getprop(rtas_node, "query-cpu-stopped-state",
1706 &val, sizeof(val)) != PROM_ERROR)
1707 rtas_has_query_cpu_stopped = true;
1708
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001709 prom_debug("rtas base = 0x%x\n", base);
1710 prom_debug("rtas entry = 0x%x\n", entry);
Mathieu Malaterreeae5f702018-04-06 22:12:19 +02001711 prom_debug("rtas size = 0x%x\n", size);
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001712
1713 prom_debug("prom_instantiate_rtas: end...\n");
1714}
1715
1716#ifdef CONFIG_PPC64
1717/*
Ashley Lai4a727422012-08-14 18:34:57 -05001718 * Allocate room for and instantiate Stored Measurement Log (SML)
1719 */
1720static void __init prom_instantiate_sml(void)
1721{
1722 phandle ibmvtpm_node;
1723 ihandle ibmvtpm_inst;
Hon Ching \(Vicky\) Lob4ed0462015-10-07 20:11:53 -04001724 u32 entry = 0, size = 0, succ = 0;
Ashley Lai4a727422012-08-14 18:34:57 -05001725 u64 base;
Hon Ching \(Vicky\) Lob4ed0462015-10-07 20:11:53 -04001726 __be32 val;
Ashley Lai4a727422012-08-14 18:34:57 -05001727
1728 prom_debug("prom_instantiate_sml: start...\n");
1729
Hon Ching \(Vicky\) Lo2f82e982015-10-07 20:11:52 -04001730 ibmvtpm_node = call_prom("finddevice", 1, 1, ADDR("/vdevice/vtpm"));
Ashley Lai4a727422012-08-14 18:34:57 -05001731 prom_debug("ibmvtpm_node: %x\n", ibmvtpm_node);
1732 if (!PHANDLE_VALID(ibmvtpm_node))
1733 return;
1734
Hon Ching \(Vicky\) Lo2f82e982015-10-07 20:11:52 -04001735 ibmvtpm_inst = call_prom("open", 1, 1, ADDR("/vdevice/vtpm"));
Ashley Lai4a727422012-08-14 18:34:57 -05001736 if (!IHANDLE_VALID(ibmvtpm_inst)) {
1737 prom_printf("opening vtpm package failed (%x)\n", ibmvtpm_inst);
1738 return;
1739 }
1740
Hon Ching \(Vicky\) Lob4ed0462015-10-07 20:11:53 -04001741 if (prom_getprop(ibmvtpm_node, "ibm,sml-efi-reformat-supported",
1742 &val, sizeof(val)) != PROM_ERROR) {
1743 if (call_prom_ret("call-method", 2, 2, &succ,
1744 ADDR("reformat-sml-to-efi-alignment"),
1745 ibmvtpm_inst) != 0 || succ == 0) {
1746 prom_printf("Reformat SML to EFI alignment failed\n");
1747 return;
1748 }
Hon Ching \(Vicky\) Lob4ed0462015-10-07 20:11:53 -04001749
Hon Ching \(Vicky\) Lo9e5d4af2015-10-07 20:11:54 -04001750 if (call_prom_ret("call-method", 2, 2, &size,
1751 ADDR("sml-get-allocated-size"),
1752 ibmvtpm_inst) != 0 || size == 0) {
1753 prom_printf("SML get allocated size failed\n");
1754 return;
1755 }
1756 } else {
1757 if (call_prom_ret("call-method", 2, 2, &size,
1758 ADDR("sml-get-handover-size"),
1759 ibmvtpm_inst) != 0 || size == 0) {
1760 prom_printf("SML get handover size failed\n");
1761 return;
1762 }
Ashley Lai4a727422012-08-14 18:34:57 -05001763 }
1764
1765 base = alloc_down(size, PAGE_SIZE, 0);
1766 if (base == 0)
1767 prom_panic("Could not allocate memory for sml\n");
1768
Mathieu Malaterreeae5f702018-04-06 22:12:19 +02001769 prom_printf("instantiating sml at 0x%llx...", base);
Ashley Lai4a727422012-08-14 18:34:57 -05001770
Hon Ching \(Vicky\) Lo9e5d4af2015-10-07 20:11:54 -04001771 memset((void *)base, 0, size);
1772
Ashley Lai4a727422012-08-14 18:34:57 -05001773 if (call_prom_ret("call-method", 4, 2, &entry,
1774 ADDR("sml-handover"),
1775 ibmvtpm_inst, size, base) != 0 || entry == 0) {
1776 prom_printf("SML handover failed\n");
1777 return;
1778 }
1779 prom_printf(" done\n");
1780
1781 reserve_mem(base, size);
1782
Hon Ching \(Vicky\) Lo2f82e982015-10-07 20:11:52 -04001783 prom_setprop(ibmvtpm_node, "/vdevice/vtpm", "linux,sml-base",
Ashley Lai4a727422012-08-14 18:34:57 -05001784 &base, sizeof(base));
Hon Ching \(Vicky\) Lo2f82e982015-10-07 20:11:52 -04001785 prom_setprop(ibmvtpm_node, "/vdevice/vtpm", "linux,sml-size",
Ashley Lai4a727422012-08-14 18:34:57 -05001786 &size, sizeof(size));
1787
Mathieu Malaterreeae5f702018-04-06 22:12:19 +02001788 prom_debug("sml base = 0x%llx\n", base);
1789 prom_debug("sml size = 0x%x\n", size);
Ashley Lai4a727422012-08-14 18:34:57 -05001790
1791 prom_debug("prom_instantiate_sml: end...\n");
1792}
1793
1794/*
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001795 * Allocate room for and initialize TCE tables
1796 */
Benjamin Herrenschmidt493adff2013-08-07 02:01:38 +10001797#ifdef __BIG_ENDIAN__
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001798static void __init prom_initialize_tce_table(void)
1799{
1800 phandle node;
1801 ihandle phb_node;
1802 char compatible[64], type[64], model[64];
Anton Blanchard5827d412012-11-26 17:40:03 +00001803 char *path = prom_scratch;
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001804 u64 base, align;
1805 u32 minalign, minsize;
1806 u64 tce_entry, *tce_entryp;
1807 u64 local_alloc_top, local_alloc_bottom;
1808 u64 i;
1809
Anton Blanchard5827d412012-11-26 17:40:03 +00001810 if (prom_iommu_off)
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001811 return;
1812
1813 prom_debug("starting prom_initialize_tce_table\n");
1814
1815 /* Cache current top of allocs so we reserve a single block */
Anton Blanchard5827d412012-11-26 17:40:03 +00001816 local_alloc_top = alloc_top_high;
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001817 local_alloc_bottom = local_alloc_top;
1818
1819 /* Search all nodes looking for PHBs. */
1820 for (node = 0; prom_next_node(&node); ) {
1821 compatible[0] = 0;
1822 type[0] = 0;
1823 model[0] = 0;
1824 prom_getprop(node, "compatible",
1825 compatible, sizeof(compatible));
1826 prom_getprop(node, "device_type", type, sizeof(type));
1827 prom_getprop(node, "model", model, sizeof(model));
1828
Anton Blanchard5827d412012-11-26 17:40:03 +00001829 if ((type[0] == 0) || (strstr(type, "pci") == NULL))
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001830 continue;
1831
Linas Vepstase788ff12007-09-07 03:45:21 +10001832 /* Keep the old logic intact to avoid regression. */
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001833 if (compatible[0] != 0) {
Anton Blanchard5827d412012-11-26 17:40:03 +00001834 if ((strstr(compatible, "python") == NULL) &&
1835 (strstr(compatible, "Speedwagon") == NULL) &&
1836 (strstr(compatible, "Winnipeg") == NULL))
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001837 continue;
1838 } else if (model[0] != 0) {
Anton Blanchard5827d412012-11-26 17:40:03 +00001839 if ((strstr(model, "ython") == NULL) &&
1840 (strstr(model, "peedwagon") == NULL) &&
1841 (strstr(model, "innipeg") == NULL))
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001842 continue;
1843 }
1844
1845 if (prom_getprop(node, "tce-table-minalign", &minalign,
1846 sizeof(minalign)) == PROM_ERROR)
1847 minalign = 0;
1848 if (prom_getprop(node, "tce-table-minsize", &minsize,
1849 sizeof(minsize)) == PROM_ERROR)
1850 minsize = 4UL << 20;
1851
1852 /*
1853 * Even though we read what OF wants, we just set the table
1854 * size to 4 MB. This is enough to map 2GB of PCI DMA space.
1855 * By doing this, we avoid the pitfalls of trying to DMA to
1856 * MMIO space and the DMA alias hole.
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001857 */
Nicholas Piggin471d7ff2018-02-21 05:08:29 +10001858 minsize = 4UL << 20;
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001859
1860 /* Align to the greater of the align or size */
1861 align = max(minalign, minsize);
1862 base = alloc_down(minsize, align, 1);
1863 if (base == 0)
1864 prom_panic("ERROR, cannot find space for TCE table.\n");
1865 if (base < local_alloc_bottom)
1866 local_alloc_bottom = base;
1867
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001868 /* It seems OF doesn't null-terminate the path :-( */
Li Zefanaca71ef2007-11-05 13:21:56 +11001869 memset(path, 0, PROM_SCRATCH_SIZE);
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001870 /* Call OF to setup the TCE hardware */
1871 if (call_prom("package-to-path", 3, 1, node,
1872 path, PROM_SCRATCH_SIZE-1) == PROM_ERROR) {
1873 prom_printf("package-to-path failed\n");
1874 }
1875
Paul Mackerrasa23414b2005-11-10 12:00:55 +11001876 /* Save away the TCE table attributes for later use. */
1877 prom_setprop(node, path, "linux,tce-base", &base, sizeof(base));
1878 prom_setprop(node, path, "linux,tce-size", &minsize, sizeof(minsize));
1879
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001880 prom_debug("TCE table: %s\n", path);
1881 prom_debug("\tnode = 0x%x\n", node);
Mathieu Malaterreeae5f702018-04-06 22:12:19 +02001882 prom_debug("\tbase = 0x%llx\n", base);
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001883 prom_debug("\tsize = 0x%x\n", minsize);
1884
1885 /* Initialize the table to have a one-to-one mapping
1886 * over the allocated size.
1887 */
Ingo Molnar2b931fb2009-01-06 13:56:52 +00001888 tce_entryp = (u64 *)base;
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001889 for (i = 0; i < (minsize >> 3) ;tce_entryp++, i++) {
1890 tce_entry = (i << PAGE_SHIFT);
1891 tce_entry |= 0x3;
1892 *tce_entryp = tce_entry;
1893 }
1894
1895 prom_printf("opening PHB %s", path);
1896 phb_node = call_prom("open", 1, 1, path);
1897 if (phb_node == 0)
1898 prom_printf("... failed\n");
1899 else
1900 prom_printf("... done\n");
1901
1902 call_prom("call-method", 6, 0, ADDR("set-64-bit-addressing"),
1903 phb_node, -1, minsize,
1904 (u32) base, (u32) (base >> 32));
1905 call_prom("close", 1, 0, phb_node);
1906 }
1907
1908 reserve_mem(local_alloc_bottom, local_alloc_top - local_alloc_bottom);
1909
Michael Ellerman2babf5c2006-05-17 18:00:46 +10001910 /* These are only really needed if there is a memory limit in
1911 * effect, but we don't know so export them always. */
Anton Blanchard5827d412012-11-26 17:40:03 +00001912 prom_tce_alloc_start = local_alloc_bottom;
1913 prom_tce_alloc_end = local_alloc_top;
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001914
1915 /* Flag the first invalid entry */
1916 prom_debug("ending prom_initialize_tce_table\n");
1917}
Benjamin Herrenschmidt493adff2013-08-07 02:01:38 +10001918#endif /* __BIG_ENDIAN__ */
1919#endif /* CONFIG_PPC64 */
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001920
1921/*
1922 * With CHRP SMP we need to use the OF to start the other processors.
1923 * We can't wait until smp_boot_cpus (the OF is trashed by then)
1924 * so we have to put the processors into a holding pattern controlled
1925 * by the kernel (not OF) before we destroy the OF.
1926 *
1927 * This uses a chunk of low memory, puts some holding pattern
1928 * code there and sends the other processors off to there until
1929 * smp_boot_cpus tells them to do something. The holding pattern
1930 * checks that address until its cpu # is there, when it is that
1931 * cpu jumps to __secondary_start(). smp_boot_cpus() takes care
1932 * of setting those values.
1933 *
1934 * We also use physical address 0x4 here to tell when a cpu
1935 * is in its holding pattern code.
1936 *
1937 * -- Cort
1938 */
Paul Mackerrasbbd0abd2005-10-26 21:45:56 +10001939/*
1940 * We want to reference the copy of __secondary_hold_* in the
1941 * 0 - 0x100 address range
1942 */
1943#define LOW_ADDR(x) (((unsigned long) &(x)) & 0xff)
1944
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001945static void __init prom_hold_cpus(void)
1946{
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001947 unsigned long i;
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001948 phandle node;
1949 char type[64];
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001950 unsigned long *spinloop
Paul Mackerrasbbd0abd2005-10-26 21:45:56 +10001951 = (void *) LOW_ADDR(__secondary_hold_spinloop);
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001952 unsigned long *acknowledge
Paul Mackerrasbbd0abd2005-10-26 21:45:56 +10001953 = (void *) LOW_ADDR(__secondary_hold_acknowledge);
Paul Mackerrasbbd0abd2005-10-26 21:45:56 +10001954 unsigned long secondary_hold = LOW_ADDR(__secondary_hold);
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001955
Benjamin Herrenschmidtdbe78b42013-09-25 14:02:50 +10001956 /*
1957 * On pseries, if RTAS supports "query-cpu-stopped-state",
1958 * we skip this stage, the CPUs will be started by the
1959 * kernel using RTAS.
1960 */
1961 if ((of_platform == PLATFORM_PSERIES ||
1962 of_platform == PLATFORM_PSERIES_LPAR) &&
1963 rtas_has_query_cpu_stopped) {
1964 prom_printf("prom_hold_cpus: skipped\n");
1965 return;
1966 }
1967
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001968 prom_debug("prom_hold_cpus: start...\n");
Mathieu Malaterreeae5f702018-04-06 22:12:19 +02001969 prom_debug(" 1) spinloop = 0x%lx\n", (unsigned long)spinloop);
1970 prom_debug(" 1) *spinloop = 0x%lx\n", *spinloop);
1971 prom_debug(" 1) acknowledge = 0x%lx\n",
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001972 (unsigned long)acknowledge);
Mathieu Malaterreeae5f702018-04-06 22:12:19 +02001973 prom_debug(" 1) *acknowledge = 0x%lx\n", *acknowledge);
1974 prom_debug(" 1) secondary_hold = 0x%lx\n", secondary_hold);
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001975
1976 /* Set the common spinloop variable, so all of the secondary cpus
1977 * will block when they are awakened from their OF spinloop.
1978 * This must occur for both SMP and non SMP kernels, since OF will
1979 * be trashed when we move the kernel.
1980 */
1981 *spinloop = 0;
1982
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001983 /* look for cpus */
1984 for (node = 0; prom_next_node(&node); ) {
Benjamin Herrenschmidt493adff2013-08-07 02:01:38 +10001985 unsigned int cpu_no;
1986 __be32 reg;
1987
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001988 type[0] = 0;
1989 prom_getprop(node, "device_type", type, sizeof(type));
Anton Blanchard5827d412012-11-26 17:40:03 +00001990 if (strcmp(type, "cpu") != 0)
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001991 continue;
1992
1993 /* Skip non-configured cpus. */
1994 if (prom_getprop(node, "status", type, sizeof(type)) > 0)
Anton Blanchard5827d412012-11-26 17:40:03 +00001995 if (strcmp(type, "okay") != 0)
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001996 continue;
1997
Benjamin Herrenschmidt493adff2013-08-07 02:01:38 +10001998 reg = cpu_to_be32(-1); /* make sparse happy */
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001999 prom_getprop(node, "reg", &reg, sizeof(reg));
Benjamin Herrenschmidt493adff2013-08-07 02:01:38 +10002000 cpu_no = be32_to_cpu(reg);
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002001
Mathieu Malaterreeae5f702018-04-06 22:12:19 +02002002 prom_debug("cpu hw idx = %u\n", cpu_no);
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002003
2004 /* Init the acknowledge var which will be reset by
2005 * the secondary cpu when it awakens from its OF
2006 * spinloop.
2007 */
2008 *acknowledge = (unsigned long)-1;
2009
Benjamin Herrenschmidt493adff2013-08-07 02:01:38 +10002010 if (cpu_no != prom.cpu) {
Benjamin Herrenschmidt27f44882011-09-19 18:27:58 +00002011 /* Primary Thread of non-boot cpu or any thread */
Mathieu Malaterreeae5f702018-04-06 22:12:19 +02002012 prom_printf("starting cpu hw idx %u... ", cpu_no);
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002013 call_prom("start-cpu", 3, 0, node,
Benjamin Herrenschmidt493adff2013-08-07 02:01:38 +10002014 secondary_hold, cpu_no);
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002015
Paul Mackerrasbbd0abd2005-10-26 21:45:56 +10002016 for (i = 0; (i < 100000000) &&
2017 (*acknowledge == ((unsigned long)-1)); i++ )
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002018 mb();
2019
Benjamin Herrenschmidt493adff2013-08-07 02:01:38 +10002020 if (*acknowledge == cpu_no)
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002021 prom_printf("done\n");
Paul Mackerrasbbd0abd2005-10-26 21:45:56 +10002022 else
Mathieu Malaterreeae5f702018-04-06 22:12:19 +02002023 prom_printf("failed: %lx\n", *acknowledge);
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002024 }
2025#ifdef CONFIG_SMP
2026 else
Mathieu Malaterreeae5f702018-04-06 22:12:19 +02002027 prom_printf("boot cpu hw idx %u\n", cpu_no);
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002028#endif /* CONFIG_SMP */
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002029 }
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002030
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002031 prom_debug("prom_hold_cpus: end...\n");
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002032}
2033
2034
2035static void __init prom_init_client_services(unsigned long pp)
2036{
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002037 /* Get a handle to the prom entry point before anything else */
Anton Blanchard5827d412012-11-26 17:40:03 +00002038 prom_entry = pp;
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002039
2040 /* get a handle for the stdout device */
Anton Blanchard5827d412012-11-26 17:40:03 +00002041 prom.chosen = call_prom("finddevice", 1, 1, ADDR("/chosen"));
2042 if (!PHANDLE_VALID(prom.chosen))
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002043 prom_panic("cannot find chosen"); /* msg won't be printed :( */
2044
2045 /* get device tree root */
Anton Blanchard5827d412012-11-26 17:40:03 +00002046 prom.root = call_prom("finddevice", 1, 1, ADDR("/"));
2047 if (!PHANDLE_VALID(prom.root))
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002048 prom_panic("cannot find device tree root"); /* msg won't be printed :( */
Paul Mackerrasa575b802005-10-23 17:23:21 +10002049
Anton Blanchard5827d412012-11-26 17:40:03 +00002050 prom.mmumap = 0;
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002051}
2052
Paul Mackerrasa575b802005-10-23 17:23:21 +10002053#ifdef CONFIG_PPC32
2054/*
2055 * For really old powermacs, we need to map things we claim.
2056 * For that, we need the ihandle of the mmu.
Paul Mackerrasa23414b2005-11-10 12:00:55 +11002057 * Also, on the longtrail, we need to work around other bugs.
Paul Mackerrasa575b802005-10-23 17:23:21 +10002058 */
2059static void __init prom_find_mmu(void)
2060{
Paul Mackerrasa575b802005-10-23 17:23:21 +10002061 phandle oprom;
2062 char version[64];
2063
2064 oprom = call_prom("finddevice", 1, 1, ADDR("/openprom"));
2065 if (!PHANDLE_VALID(oprom))
2066 return;
2067 if (prom_getprop(oprom, "model", version, sizeof(version)) <= 0)
2068 return;
2069 version[sizeof(version) - 1] = 0;
Paul Mackerrasa575b802005-10-23 17:23:21 +10002070 /* XXX might need to add other versions here */
Paul Mackerrasa23414b2005-11-10 12:00:55 +11002071 if (strcmp(version, "Open Firmware, 1.0.5") == 0)
2072 of_workarounds = OF_WA_CLAIM;
2073 else if (strncmp(version, "FirmWorks,3.", 12) == 0) {
2074 of_workarounds = OF_WA_CLAIM | OF_WA_LONGTRAIL;
2075 call_prom("interpret", 1, 1, "dev /memory 0 to allow-reclaim");
2076 } else
Paul Mackerrasa575b802005-10-23 17:23:21 +10002077 return;
Anton Blanchard5827d412012-11-26 17:40:03 +00002078 prom.memory = call_prom("open", 1, 1, ADDR("/memory"));
2079 prom_getprop(prom.chosen, "mmu", &prom.mmumap,
2080 sizeof(prom.mmumap));
Benjamin Herrenschmidt493adff2013-08-07 02:01:38 +10002081 prom.mmumap = be32_to_cpu(prom.mmumap);
Anton Blanchard5827d412012-11-26 17:40:03 +00002082 if (!IHANDLE_VALID(prom.memory) || !IHANDLE_VALID(prom.mmumap))
Paul Mackerrasa23414b2005-11-10 12:00:55 +11002083 of_workarounds &= ~OF_WA_CLAIM; /* hmmm */
Paul Mackerrasa575b802005-10-23 17:23:21 +10002084}
2085#else
2086#define prom_find_mmu()
2087#endif
2088
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002089static void __init prom_init_stdout(void)
2090{
Anton Blanchard5827d412012-11-26 17:40:03 +00002091 char *path = of_stdout_device;
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002092 char type[16];
Benjamin Herrenschmidt493adff2013-08-07 02:01:38 +10002093 phandle stdout_node;
2094 __be32 val;
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002095
Anton Blanchard5827d412012-11-26 17:40:03 +00002096 if (prom_getprop(prom.chosen, "stdout", &val, sizeof(val)) <= 0)
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002097 prom_panic("cannot find stdout");
2098
Benjamin Herrenschmidt493adff2013-08-07 02:01:38 +10002099 prom.stdout = be32_to_cpu(val);
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002100
2101 /* Get the full OF pathname of the stdout device */
2102 memset(path, 0, 256);
Anton Blanchard5827d412012-11-26 17:40:03 +00002103 call_prom("instance-to-path", 3, 1, prom.stdout, path, 255);
Anton Blanchard5827d412012-11-26 17:40:03 +00002104 prom_printf("OF stdout device is: %s\n", of_stdout_device);
2105 prom_setprop(prom.chosen, "/chosen", "linux,stdout-path",
Paul Mackerrasa23414b2005-11-10 12:00:55 +11002106 path, strlen(path) + 1);
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002107
Benjamin Herrenschmidt10348f52014-01-13 09:49:17 +11002108 /* instance-to-package fails on PA-Semi */
2109 stdout_node = call_prom("instance-to-package", 1, 1, prom.stdout);
2110 if (stdout_node != PROM_ERROR) {
2111 val = cpu_to_be32(stdout_node);
Benjamin Herrenschmidt10348f52014-01-13 09:49:17 +11002112
2113 /* If it's a display, note it */
2114 memset(type, 0, sizeof(type));
2115 prom_getprop(stdout_node, "device_type", type, sizeof(type));
2116 if (strcmp(type, "display") == 0)
2117 prom_setprop(stdout_node, path, "linux,boot-display", NULL, 0);
2118 }
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002119}
2120
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002121static int __init prom_find_machine_type(void)
2122{
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002123 char compat[256];
2124 int len, i = 0;
Benjamin Herrenschmidt21fe3302005-11-07 16:41:59 +11002125#ifdef CONFIG_PPC64
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002126 phandle rtas;
Benjamin Herrenschmidte8222502006-03-28 23:15:54 +11002127 int x;
Benjamin Herrenschmidt21fe3302005-11-07 16:41:59 +11002128#endif
Benjamin Herrenschmidte8222502006-03-28 23:15:54 +11002129
Benjamin Herrenschmidt6e35d5d2011-09-19 18:28:01 +00002130 /* Look for a PowerMac or a Cell */
Anton Blanchard5827d412012-11-26 17:40:03 +00002131 len = prom_getprop(prom.root, "compatible",
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002132 compat, sizeof(compat)-1);
2133 if (len > 0) {
2134 compat[len] = 0;
2135 while (i < len) {
2136 char *p = &compat[i];
2137 int sl = strlen(p);
2138 if (sl == 0)
2139 break;
Anton Blanchard5827d412012-11-26 17:40:03 +00002140 if (strstr(p, "Power Macintosh") ||
2141 strstr(p, "MacRISC"))
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002142 return PLATFORM_POWERMAC;
Arnd Bergmann133dda12006-06-07 12:04:18 +10002143#ifdef CONFIG_PPC64
2144 /* We must make sure we don't detect the IBM Cell
2145 * blades as pSeries due to some firmware issues,
2146 * so we do it here.
2147 */
Anton Blanchard5827d412012-11-26 17:40:03 +00002148 if (strstr(p, "IBM,CBEA") ||
2149 strstr(p, "IBM,CPBW-1.0"))
Arnd Bergmann133dda12006-06-07 12:04:18 +10002150 return PLATFORM_GENERIC;
2151#endif /* CONFIG_PPC64 */
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002152 i += sl + 1;
2153 }
2154 }
2155#ifdef CONFIG_PPC64
Benjamin Herrenschmidt6e35d5d2011-09-19 18:28:01 +00002156 /* Try to detect OPAL */
2157 if (PHANDLE_VALID(call_prom("finddevice", 1, 1, ADDR("/ibm,opal"))))
2158 return PLATFORM_OPAL;
2159
2160 /* Try to figure out if it's an IBM pSeries or any other
Benjamin Herrenschmidte8222502006-03-28 23:15:54 +11002161 * PAPR compliant platform. We assume it is if :
2162 * - /device_type is "chrp" (please, do NOT use that for future
2163 * non-IBM designs !
2164 * - it has /rtas
2165 */
Anton Blanchard5827d412012-11-26 17:40:03 +00002166 len = prom_getprop(prom.root, "device_type",
Benjamin Herrenschmidte8222502006-03-28 23:15:54 +11002167 compat, sizeof(compat)-1);
2168 if (len <= 0)
2169 return PLATFORM_GENERIC;
Anton Blanchard5827d412012-11-26 17:40:03 +00002170 if (strcmp(compat, "chrp"))
Benjamin Herrenschmidte8222502006-03-28 23:15:54 +11002171 return PLATFORM_GENERIC;
2172
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002173 /* Default to pSeries. We need to know if we are running LPAR */
2174 rtas = call_prom("finddevice", 1, 1, ADDR("/rtas"));
Benjamin Herrenschmidte8222502006-03-28 23:15:54 +11002175 if (!PHANDLE_VALID(rtas))
2176 return PLATFORM_GENERIC;
2177 x = prom_getproplen(rtas, "ibm,hypertas-functions");
2178 if (x != PROM_ERROR) {
Anton Blanchard4da727a2009-03-31 20:06:14 +00002179 prom_debug("Hypertas detected, assuming LPAR !\n");
Benjamin Herrenschmidte8222502006-03-28 23:15:54 +11002180 return PLATFORM_PSERIES_LPAR;
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002181 }
2182 return PLATFORM_PSERIES;
2183#else
Benjamin Herrenschmidte8222502006-03-28 23:15:54 +11002184 return PLATFORM_GENERIC;
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002185#endif
2186}
2187
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002188static int __init prom_set_color(ihandle ih, int i, int r, int g, int b)
2189{
2190 return call_prom("call-method", 6, 1, ADDR("color!"), ih, i, b, g, r);
2191}
2192
2193/*
2194 * If we have a display that we don't know how to drive,
2195 * we will want to try to execute OF's open method for it
2196 * later. However, OF will probably fall over if we do that
2197 * we've taken over the MMU.
2198 * So we check whether we will need to open the display,
2199 * and if so, open it now.
2200 */
2201static void __init prom_check_displays(void)
2202{
2203 char type[16], *path;
2204 phandle node;
2205 ihandle ih;
2206 int i;
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002207
2208 static unsigned char default_colors[] = {
2209 0x00, 0x00, 0x00,
2210 0x00, 0x00, 0xaa,
2211 0x00, 0xaa, 0x00,
2212 0x00, 0xaa, 0xaa,
2213 0xaa, 0x00, 0x00,
2214 0xaa, 0x00, 0xaa,
2215 0xaa, 0xaa, 0x00,
2216 0xaa, 0xaa, 0xaa,
2217 0x55, 0x55, 0x55,
2218 0x55, 0x55, 0xff,
2219 0x55, 0xff, 0x55,
2220 0x55, 0xff, 0xff,
2221 0xff, 0x55, 0x55,
2222 0xff, 0x55, 0xff,
2223 0xff, 0xff, 0x55,
2224 0xff, 0xff, 0xff
2225 };
2226 const unsigned char *clut;
2227
Anton Blanchard4da727a2009-03-31 20:06:14 +00002228 prom_debug("Looking for displays\n");
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002229 for (node = 0; prom_next_node(&node); ) {
2230 memset(type, 0, sizeof(type));
2231 prom_getprop(node, "device_type", type, sizeof(type));
Anton Blanchard5827d412012-11-26 17:40:03 +00002232 if (strcmp(type, "display") != 0)
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002233 continue;
2234
2235 /* It seems OF doesn't null-terminate the path :-( */
Anton Blanchard5827d412012-11-26 17:40:03 +00002236 path = prom_scratch;
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002237 memset(path, 0, PROM_SCRATCH_SIZE);
2238
2239 /*
2240 * leave some room at the end of the path for appending extra
2241 * arguments
2242 */
2243 if (call_prom("package-to-path", 3, 1, node, path,
2244 PROM_SCRATCH_SIZE-10) == PROM_ERROR)
2245 continue;
Anton Blanchard1f8737a2009-03-31 20:06:15 +00002246 prom_printf("found display : %s, opening... ", path);
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002247
2248 ih = call_prom("open", 1, 1, path);
2249 if (ih == 0) {
2250 prom_printf("failed\n");
2251 continue;
2252 }
2253
2254 /* Success */
2255 prom_printf("done\n");
Paul Mackerrasa23414b2005-11-10 12:00:55 +11002256 prom_setprop(node, path, "linux,opened", NULL, 0);
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002257
2258 /* Setup a usable color table when the appropriate
2259 * method is available. Should update this to set-colors */
Anton Blanchard5827d412012-11-26 17:40:03 +00002260 clut = default_colors;
Benjamin Herrenschmidt3f536382011-12-14 13:55:11 +00002261 for (i = 0; i < 16; i++, clut += 3)
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002262 if (prom_set_color(ih, i, clut[0], clut[1],
2263 clut[2]) != 0)
2264 break;
2265
2266#ifdef CONFIG_LOGO_LINUX_CLUT224
Anton Blanchard5827d412012-11-26 17:40:03 +00002267 clut = PTRRELOC(logo_linux_clut224.clut);
2268 for (i = 0; i < logo_linux_clut224.clutsize; i++, clut += 3)
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002269 if (prom_set_color(ih, i + 32, clut[0], clut[1],
2270 clut[2]) != 0)
2271 break;
2272#endif /* CONFIG_LOGO_LINUX_CLUT224 */
Benjamin Herrenschmidt7191b612013-07-25 12:12:32 +10002273
2274#ifdef CONFIG_PPC_EARLY_DEBUG_BOOTX
2275 if (prom_getprop(node, "linux,boot-display", NULL, 0) !=
2276 PROM_ERROR) {
2277 u32 width, height, pitch, addr;
2278
2279 prom_printf("Setting btext !\n");
2280 prom_getprop(node, "width", &width, 4);
2281 prom_getprop(node, "height", &height, 4);
2282 prom_getprop(node, "linebytes", &pitch, 4);
2283 prom_getprop(node, "address", &addr, 4);
2284 prom_printf("W=%d H=%d LB=%d addr=0x%x\n",
2285 width, height, pitch, addr);
2286 btext_setup_display(width, height, 8, pitch, addr);
2287 }
2288#endif /* CONFIG_PPC_EARLY_DEBUG_BOOTX */
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002289 }
2290}
2291
2292
2293/* Return (relocated) pointer to this much memory: moves initrd if reqd. */
2294static void __init *make_room(unsigned long *mem_start, unsigned long *mem_end,
2295 unsigned long needed, unsigned long align)
2296{
2297 void *ret;
2298
2299 *mem_start = _ALIGN(*mem_start, align);
2300 while ((*mem_start + needed) > *mem_end) {
2301 unsigned long room, chunk;
2302
Mathieu Malaterreeae5f702018-04-06 22:12:19 +02002303 prom_debug("Chunk exhausted, claiming more at %lx...\n",
Anton Blanchard5827d412012-11-26 17:40:03 +00002304 alloc_bottom);
2305 room = alloc_top - alloc_bottom;
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002306 if (room > DEVTREE_CHUNK_SIZE)
2307 room = DEVTREE_CHUNK_SIZE;
2308 if (room < PAGE_SIZE)
Anton Blanchardfbafd722011-07-25 20:47:51 +00002309 prom_panic("No memory for flatten_device_tree "
2310 "(no room)\n");
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002311 chunk = alloc_up(room, 0);
2312 if (chunk == 0)
Anton Blanchardfbafd722011-07-25 20:47:51 +00002313 prom_panic("No memory for flatten_device_tree "
2314 "(claim failed)\n");
Anton Blanchard966728d2011-07-25 20:47:07 +00002315 *mem_end = chunk + room;
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002316 }
2317
2318 ret = (void *)*mem_start;
2319 *mem_start += needed;
2320
2321 return ret;
2322}
2323
Benjamin Herrenschmidt493adff2013-08-07 02:01:38 +10002324#define dt_push_token(token, mem_start, mem_end) do { \
2325 void *room = make_room(mem_start, mem_end, 4, 4); \
2326 *(__be32 *)room = cpu_to_be32(token); \
2327 } while(0)
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002328
2329static unsigned long __init dt_find_string(char *str)
2330{
2331 char *s, *os;
2332
Anton Blanchard5827d412012-11-26 17:40:03 +00002333 s = os = (char *)dt_string_start;
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002334 s += 4;
Anton Blanchard5827d412012-11-26 17:40:03 +00002335 while (s < (char *)dt_string_end) {
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002336 if (strcmp(s, str) == 0)
2337 return s - os;
2338 s += strlen(s) + 1;
2339 }
2340 return 0;
2341}
2342
2343/*
2344 * The Open Firmware 1275 specification states properties must be 31 bytes or
2345 * less, however not all firmwares obey this. Make it 64 bytes to be safe.
2346 */
2347#define MAX_PROPERTY_NAME 64
2348
2349static void __init scan_dt_build_strings(phandle node,
2350 unsigned long *mem_start,
2351 unsigned long *mem_end)
2352{
2353 char *prev_name, *namep, *sstart;
2354 unsigned long soff;
2355 phandle child;
2356
Anton Blanchard5827d412012-11-26 17:40:03 +00002357 sstart = (char *)dt_string_start;
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002358
2359 /* get and store all property names */
Anton Blanchard5827d412012-11-26 17:40:03 +00002360 prev_name = "";
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002361 for (;;) {
2362 /* 64 is max len of name including nul. */
2363 namep = make_room(mem_start, mem_end, MAX_PROPERTY_NAME, 1);
2364 if (call_prom("nextprop", 3, 1, node, prev_name, namep) != 1) {
2365 /* No more nodes: unwind alloc */
2366 *mem_start = (unsigned long)namep;
2367 break;
2368 }
2369
2370 /* skip "name" */
Anton Blanchard5827d412012-11-26 17:40:03 +00002371 if (strcmp(namep, "name") == 0) {
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002372 *mem_start = (unsigned long)namep;
Anton Blanchard5827d412012-11-26 17:40:03 +00002373 prev_name = "name";
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002374 continue;
2375 }
2376 /* get/create string entry */
2377 soff = dt_find_string(namep);
2378 if (soff != 0) {
2379 *mem_start = (unsigned long)namep;
2380 namep = sstart + soff;
2381 } else {
2382 /* Trim off some if we can */
2383 *mem_start = (unsigned long)namep + strlen(namep) + 1;
Anton Blanchard5827d412012-11-26 17:40:03 +00002384 dt_string_end = *mem_start;
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002385 }
2386 prev_name = namep;
2387 }
2388
2389 /* do all our children */
2390 child = call_prom("child", 1, 1, node);
2391 while (child != 0) {
2392 scan_dt_build_strings(child, mem_start, mem_end);
2393 child = call_prom("peer", 1, 1, child);
2394 }
2395}
2396
2397static void __init scan_dt_build_struct(phandle node, unsigned long *mem_start,
2398 unsigned long *mem_end)
2399{
2400 phandle child;
2401 char *namep, *prev_name, *sstart, *p, *ep, *lp, *path;
2402 unsigned long soff;
2403 unsigned char *valp;
2404 static char pname[MAX_PROPERTY_NAME];
Benjamin Herrenschmidt6e35d5d2011-09-19 18:28:01 +00002405 int l, room, has_phandle = 0;
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002406
2407 dt_push_token(OF_DT_BEGIN_NODE, mem_start, mem_end);
2408
2409 /* get the node's full name */
2410 namep = (char *)*mem_start;
Paul Mackerrasc49888202005-10-26 21:52:53 +10002411 room = *mem_end - *mem_start;
2412 if (room > 255)
2413 room = 255;
2414 l = call_prom("package-to-path", 3, 1, node, namep, room);
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002415 if (l >= 0) {
2416 /* Didn't fit? Get more room. */
Paul Mackerrasc49888202005-10-26 21:52:53 +10002417 if (l >= room) {
2418 if (l >= *mem_end - *mem_start)
2419 namep = make_room(mem_start, mem_end, l+1, 1);
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002420 call_prom("package-to-path", 3, 1, node, namep, l);
2421 }
2422 namep[l] = '\0';
2423
2424 /* Fixup an Apple bug where they have bogus \0 chars in the
Paul Mackerrasa575b802005-10-23 17:23:21 +10002425 * middle of the path in some properties, and extract
2426 * the unit name (everything after the last '/').
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002427 */
Paul Mackerrasa575b802005-10-23 17:23:21 +10002428 for (lp = p = namep, ep = namep + l; p < ep; p++) {
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002429 if (*p == '/')
Paul Mackerrasa575b802005-10-23 17:23:21 +10002430 lp = namep;
2431 else if (*p != 0)
2432 *lp++ = *p;
2433 }
2434 *lp = 0;
2435 *mem_start = _ALIGN((unsigned long)lp + 1, 4);
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002436 }
2437
2438 /* get it again for debugging */
Anton Blanchard5827d412012-11-26 17:40:03 +00002439 path = prom_scratch;
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002440 memset(path, 0, PROM_SCRATCH_SIZE);
2441 call_prom("package-to-path", 3, 1, node, path, PROM_SCRATCH_SIZE-1);
2442
2443 /* get and store all properties */
Anton Blanchard5827d412012-11-26 17:40:03 +00002444 prev_name = "";
2445 sstart = (char *)dt_string_start;
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002446 for (;;) {
2447 if (call_prom("nextprop", 3, 1, node, prev_name,
Anton Blanchard5827d412012-11-26 17:40:03 +00002448 pname) != 1)
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002449 break;
2450
2451 /* skip "name" */
Anton Blanchard5827d412012-11-26 17:40:03 +00002452 if (strcmp(pname, "name") == 0) {
2453 prev_name = "name";
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002454 continue;
2455 }
2456
2457 /* find string offset */
Anton Blanchard5827d412012-11-26 17:40:03 +00002458 soff = dt_find_string(pname);
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002459 if (soff == 0) {
2460 prom_printf("WARNING: Can't find string index for"
Anton Blanchard5827d412012-11-26 17:40:03 +00002461 " <%s>, node %s\n", pname, path);
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002462 break;
2463 }
2464 prev_name = sstart + soff;
2465
2466 /* get length */
Anton Blanchard5827d412012-11-26 17:40:03 +00002467 l = call_prom("getproplen", 2, 1, node, pname);
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002468
2469 /* sanity checks */
2470 if (l == PROM_ERROR)
2471 continue;
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002472
2473 /* push property head */
2474 dt_push_token(OF_DT_PROP, mem_start, mem_end);
2475 dt_push_token(l, mem_start, mem_end);
2476 dt_push_token(soff, mem_start, mem_end);
2477
2478 /* push property content */
2479 valp = make_room(mem_start, mem_end, l, 4);
Anton Blanchard5827d412012-11-26 17:40:03 +00002480 call_prom("getprop", 4, 1, node, pname, valp, l);
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002481 *mem_start = _ALIGN(*mem_start, 4);
Benjamin Herrenschmidt6e35d5d2011-09-19 18:28:01 +00002482
Anton Blanchard5827d412012-11-26 17:40:03 +00002483 if (!strcmp(pname, "phandle"))
Benjamin Herrenschmidt6e35d5d2011-09-19 18:28:01 +00002484 has_phandle = 1;
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002485 }
2486
Benjamin Herrenschmidt6e35d5d2011-09-19 18:28:01 +00002487 /* Add a "linux,phandle" property if no "phandle" property already
2488 * existed (can happen with OPAL)
2489 */
2490 if (!has_phandle) {
Anton Blanchard5827d412012-11-26 17:40:03 +00002491 soff = dt_find_string("linux,phandle");
Benjamin Herrenschmidt6e35d5d2011-09-19 18:28:01 +00002492 if (soff == 0)
2493 prom_printf("WARNING: Can't find string index for"
2494 " <linux-phandle> node %s\n", path);
2495 else {
2496 dt_push_token(OF_DT_PROP, mem_start, mem_end);
2497 dt_push_token(4, mem_start, mem_end);
2498 dt_push_token(soff, mem_start, mem_end);
2499 valp = make_room(mem_start, mem_end, 4, 4);
Benjamin Herrenschmidt493adff2013-08-07 02:01:38 +10002500 *(__be32 *)valp = cpu_to_be32(node);
Benjamin Herrenschmidt6e35d5d2011-09-19 18:28:01 +00002501 }
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002502 }
2503
2504 /* do all our children */
2505 child = call_prom("child", 1, 1, node);
2506 while (child != 0) {
2507 scan_dt_build_struct(child, mem_start, mem_end);
2508 child = call_prom("peer", 1, 1, child);
2509 }
2510
2511 dt_push_token(OF_DT_END_NODE, mem_start, mem_end);
2512}
2513
2514static void __init flatten_device_tree(void)
2515{
2516 phandle root;
2517 unsigned long mem_start, mem_end, room;
2518 struct boot_param_header *hdr;
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002519 char *namep;
2520 u64 *rsvmap;
2521
2522 /*
2523 * Check how much room we have between alloc top & bottom (+/- a
Anton Blanchardfbafd722011-07-25 20:47:51 +00002524 * few pages), crop to 1MB, as this is our "chunk" size
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002525 */
Anton Blanchard5827d412012-11-26 17:40:03 +00002526 room = alloc_top - alloc_bottom - 0x4000;
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002527 if (room > DEVTREE_CHUNK_SIZE)
2528 room = DEVTREE_CHUNK_SIZE;
Mathieu Malaterreeae5f702018-04-06 22:12:19 +02002529 prom_debug("starting device tree allocs at %lx\n", alloc_bottom);
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002530
2531 /* Now try to claim that */
2532 mem_start = (unsigned long)alloc_up(room, PAGE_SIZE);
2533 if (mem_start == 0)
2534 prom_panic("Can't allocate initial device-tree chunk\n");
Anton Blanchard966728d2011-07-25 20:47:07 +00002535 mem_end = mem_start + room;
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002536
2537 /* Get root of tree */
2538 root = call_prom("peer", 1, 1, (phandle)0);
2539 if (root == (phandle)0)
2540 prom_panic ("couldn't get device tree root\n");
2541
2542 /* Build header and make room for mem rsv map */
2543 mem_start = _ALIGN(mem_start, 4);
2544 hdr = make_room(&mem_start, &mem_end,
2545 sizeof(struct boot_param_header), 4);
Anton Blanchard5827d412012-11-26 17:40:03 +00002546 dt_header_start = (unsigned long)hdr;
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002547 rsvmap = make_room(&mem_start, &mem_end, sizeof(mem_reserve_map), 8);
2548
2549 /* Start of strings */
2550 mem_start = PAGE_ALIGN(mem_start);
Anton Blanchard5827d412012-11-26 17:40:03 +00002551 dt_string_start = mem_start;
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002552 mem_start += 4; /* hole */
2553
2554 /* Add "linux,phandle" in there, we'll need it */
2555 namep = make_room(&mem_start, &mem_end, 16, 1);
Anton Blanchard5827d412012-11-26 17:40:03 +00002556 strcpy(namep, "linux,phandle");
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002557 mem_start = (unsigned long)namep + strlen(namep) + 1;
2558
2559 /* Build string array */
2560 prom_printf("Building dt strings...\n");
2561 scan_dt_build_strings(root, &mem_start, &mem_end);
Anton Blanchard5827d412012-11-26 17:40:03 +00002562 dt_string_end = mem_start;
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002563
2564 /* Build structure */
2565 mem_start = PAGE_ALIGN(mem_start);
Anton Blanchard5827d412012-11-26 17:40:03 +00002566 dt_struct_start = mem_start;
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002567 prom_printf("Building dt structure...\n");
2568 scan_dt_build_struct(root, &mem_start, &mem_end);
2569 dt_push_token(OF_DT_END, &mem_start, &mem_end);
Anton Blanchard5827d412012-11-26 17:40:03 +00002570 dt_struct_end = PAGE_ALIGN(mem_start);
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002571
2572 /* Finish header */
Benjamin Herrenschmidt493adff2013-08-07 02:01:38 +10002573 hdr->boot_cpuid_phys = cpu_to_be32(prom.cpu);
2574 hdr->magic = cpu_to_be32(OF_DT_HEADER);
2575 hdr->totalsize = cpu_to_be32(dt_struct_end - dt_header_start);
2576 hdr->off_dt_struct = cpu_to_be32(dt_struct_start - dt_header_start);
2577 hdr->off_dt_strings = cpu_to_be32(dt_string_start - dt_header_start);
2578 hdr->dt_strings_size = cpu_to_be32(dt_string_end - dt_string_start);
2579 hdr->off_mem_rsvmap = cpu_to_be32(((unsigned long)rsvmap) - dt_header_start);
2580 hdr->version = cpu_to_be32(OF_DT_VERSION);
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002581 /* Version 16 is not backward compatible */
Benjamin Herrenschmidt493adff2013-08-07 02:01:38 +10002582 hdr->last_comp_version = cpu_to_be32(0x10);
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002583
Jimi Xenidis4d1f3f22006-05-18 17:03:05 -05002584 /* Copy the reserve map in */
Anton Blanchard5827d412012-11-26 17:40:03 +00002585 memcpy(rsvmap, mem_reserve_map, sizeof(mem_reserve_map));
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002586
2587#ifdef DEBUG_PROM
2588 {
2589 int i;
2590 prom_printf("reserved memory map:\n");
Anton Blanchard5827d412012-11-26 17:40:03 +00002591 for (i = 0; i < mem_reserve_cnt; i++)
Mathieu Malaterreeae5f702018-04-06 22:12:19 +02002592 prom_printf(" %llx - %llx\n",
Benjamin Herrenschmidt493adff2013-08-07 02:01:38 +10002593 be64_to_cpu(mem_reserve_map[i].base),
2594 be64_to_cpu(mem_reserve_map[i].size));
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002595 }
2596#endif
Jimi Xenidis4d1f3f22006-05-18 17:03:05 -05002597 /* Bump mem_reserve_cnt to cause further reservations to fail
2598 * since it's too late.
2599 */
Anton Blanchard5827d412012-11-26 17:40:03 +00002600 mem_reserve_cnt = MEM_RESERVE_MAP_SIZE;
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002601
Mathieu Malaterreeae5f702018-04-06 22:12:19 +02002602 prom_printf("Device tree strings 0x%lx -> 0x%lx\n",
Anton Blanchard5827d412012-11-26 17:40:03 +00002603 dt_string_start, dt_string_end);
Mathieu Malaterreeae5f702018-04-06 22:12:19 +02002604 prom_printf("Device tree struct 0x%lx -> 0x%lx\n",
Anton Blanchard5827d412012-11-26 17:40:03 +00002605 dt_struct_start, dt_struct_end);
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002606}
2607
Hollis Blanchard54f4ee12006-05-25 16:36:53 -05002608#ifdef CONFIG_PPC_MAPLE
2609/* PIBS Version 1.05.0000 04/26/2005 has an incorrect /ht/isa/ranges property.
2610 * The values are bad, and it doesn't even have the right number of cells. */
2611static void __init fixup_device_tree_maple(void)
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002612{
Hollis Blanchard54f4ee12006-05-25 16:36:53 -05002613 phandle isa;
Benjamin Herrenschmidt980a6512006-07-03 17:22:05 +10002614 u32 rloc = 0x01002000; /* IO space; PCI device = 4 */
Hollis Blanchard54f4ee12006-05-25 16:36:53 -05002615 u32 isa_ranges[6];
Benjamin Herrenschmidt980a6512006-07-03 17:22:05 +10002616 char *name;
Hollis Blanchard54f4ee12006-05-25 16:36:53 -05002617
Benjamin Herrenschmidt980a6512006-07-03 17:22:05 +10002618 name = "/ht@0/isa@4";
2619 isa = call_prom("finddevice", 1, 1, ADDR(name));
2620 if (!PHANDLE_VALID(isa)) {
2621 name = "/ht@0/isa@6";
2622 isa = call_prom("finddevice", 1, 1, ADDR(name));
2623 rloc = 0x01003000; /* IO space; PCI device = 6 */
2624 }
Hollis Blanchard54f4ee12006-05-25 16:36:53 -05002625 if (!PHANDLE_VALID(isa))
2626 return;
2627
Benjamin Herrenschmidt980a6512006-07-03 17:22:05 +10002628 if (prom_getproplen(isa, "ranges") != 12)
2629 return;
Hollis Blanchard54f4ee12006-05-25 16:36:53 -05002630 if (prom_getprop(isa, "ranges", isa_ranges, sizeof(isa_ranges))
2631 == PROM_ERROR)
2632 return;
2633
2634 if (isa_ranges[0] != 0x1 ||
2635 isa_ranges[1] != 0xf4000000 ||
2636 isa_ranges[2] != 0x00010000)
2637 return;
2638
Benjamin Herrenschmidt980a6512006-07-03 17:22:05 +10002639 prom_printf("Fixing up bogus ISA range on Maple/Apache...\n");
Hollis Blanchard54f4ee12006-05-25 16:36:53 -05002640
2641 isa_ranges[0] = 0x1;
2642 isa_ranges[1] = 0x0;
Benjamin Herrenschmidt980a6512006-07-03 17:22:05 +10002643 isa_ranges[2] = rloc;
Hollis Blanchard54f4ee12006-05-25 16:36:53 -05002644 isa_ranges[3] = 0x0;
2645 isa_ranges[4] = 0x0;
2646 isa_ranges[5] = 0x00010000;
Benjamin Herrenschmidt980a6512006-07-03 17:22:05 +10002647 prom_setprop(isa, name, "ranges",
Hollis Blanchard54f4ee12006-05-25 16:36:53 -05002648 isa_ranges, sizeof(isa_ranges));
2649}
Harry Ciao8f101a052009-06-17 16:28:00 -07002650
2651#define CPC925_MC_START 0xf8000000
2652#define CPC925_MC_LENGTH 0x1000000
2653/* The values for memory-controller don't have right number of cells */
2654static void __init fixup_device_tree_maple_memory_controller(void)
2655{
2656 phandle mc;
2657 u32 mc_reg[4];
2658 char *name = "/hostbridge@f8000000";
Harry Ciao8f101a052009-06-17 16:28:00 -07002659 u32 ac, sc;
2660
2661 mc = call_prom("finddevice", 1, 1, ADDR(name));
2662 if (!PHANDLE_VALID(mc))
2663 return;
2664
2665 if (prom_getproplen(mc, "reg") != 8)
2666 return;
2667
Anton Blanchard5827d412012-11-26 17:40:03 +00002668 prom_getprop(prom.root, "#address-cells", &ac, sizeof(ac));
2669 prom_getprop(prom.root, "#size-cells", &sc, sizeof(sc));
Harry Ciao8f101a052009-06-17 16:28:00 -07002670 if ((ac != 2) || (sc != 2))
2671 return;
2672
2673 if (prom_getprop(mc, "reg", mc_reg, sizeof(mc_reg)) == PROM_ERROR)
2674 return;
2675
2676 if (mc_reg[0] != CPC925_MC_START || mc_reg[1] != CPC925_MC_LENGTH)
2677 return;
2678
2679 prom_printf("Fixing up bogus hostbridge on Maple...\n");
2680
2681 mc_reg[0] = 0x0;
2682 mc_reg[1] = CPC925_MC_START;
2683 mc_reg[2] = 0x0;
2684 mc_reg[3] = CPC925_MC_LENGTH;
2685 prom_setprop(mc, name, "reg", mc_reg, sizeof(mc_reg));
2686}
Hollis Blanchard54f4ee12006-05-25 16:36:53 -05002687#else
2688#define fixup_device_tree_maple()
Harry Ciao8f101a052009-06-17 16:28:00 -07002689#define fixup_device_tree_maple_memory_controller()
Hollis Blanchard54f4ee12006-05-25 16:36:53 -05002690#endif
2691
Benjamin Herrenschmidte8c0acf2006-07-04 14:06:29 +10002692#ifdef CONFIG_PPC_CHRP
Olaf Heringe4805922007-04-04 18:20:04 +02002693/*
2694 * Pegasos and BriQ lacks the "ranges" property in the isa node
2695 * Pegasos needs decimal IRQ 14/15, not hexadecimal
Olaf Hering556ecf92007-08-18 04:27:17 +10002696 * Pegasos has the IDE configured in legacy mode, but advertised as native
Olaf Heringe4805922007-04-04 18:20:04 +02002697 */
Benjamin Herrenschmidte8c0acf2006-07-04 14:06:29 +10002698static void __init fixup_device_tree_chrp(void)
2699{
Olaf Heringe4805922007-04-04 18:20:04 +02002700 phandle ph;
2701 u32 prop[6];
Benjamin Herrenschmidt26c50322006-07-04 14:16:28 +10002702 u32 rloc = 0x01006000; /* IO space; PCI device = 12 */
Benjamin Herrenschmidte8c0acf2006-07-04 14:06:29 +10002703 char *name;
2704 int rc;
2705
2706 name = "/pci@80000000/isa@c";
Olaf Heringe4805922007-04-04 18:20:04 +02002707 ph = call_prom("finddevice", 1, 1, ADDR(name));
2708 if (!PHANDLE_VALID(ph)) {
Benjamin Herrenschmidt26c50322006-07-04 14:16:28 +10002709 name = "/pci@ff500000/isa@6";
Olaf Heringe4805922007-04-04 18:20:04 +02002710 ph = call_prom("finddevice", 1, 1, ADDR(name));
Benjamin Herrenschmidt26c50322006-07-04 14:16:28 +10002711 rloc = 0x01003000; /* IO space; PCI device = 6 */
2712 }
Olaf Heringe4805922007-04-04 18:20:04 +02002713 if (PHANDLE_VALID(ph)) {
2714 rc = prom_getproplen(ph, "ranges");
2715 if (rc == 0 || rc == PROM_ERROR) {
2716 prom_printf("Fixing up missing ISA range on Pegasos...\n");
Benjamin Herrenschmidte8c0acf2006-07-04 14:06:29 +10002717
Olaf Heringe4805922007-04-04 18:20:04 +02002718 prop[0] = 0x1;
2719 prop[1] = 0x0;
2720 prop[2] = rloc;
2721 prop[3] = 0x0;
2722 prop[4] = 0x0;
2723 prop[5] = 0x00010000;
2724 prom_setprop(ph, name, "ranges", prop, sizeof(prop));
2725 }
2726 }
Benjamin Herrenschmidte8c0acf2006-07-04 14:06:29 +10002727
Olaf Heringe4805922007-04-04 18:20:04 +02002728 name = "/pci@80000000/ide@C,1";
2729 ph = call_prom("finddevice", 1, 1, ADDR(name));
2730 if (PHANDLE_VALID(ph)) {
2731 prom_printf("Fixing up IDE interrupt on Pegasos...\n");
2732 prop[0] = 14;
2733 prop[1] = 0x0;
Olaf Hering556ecf92007-08-18 04:27:17 +10002734 prom_setprop(ph, name, "interrupts", prop, 2*sizeof(u32));
2735 prom_printf("Fixing up IDE class-code on Pegasos...\n");
2736 rc = prom_getprop(ph, "class-code", prop, sizeof(u32));
2737 if (rc == sizeof(u32)) {
2738 prop[0] &= ~0x5;
2739 prom_setprop(ph, name, "class-code", prop, sizeof(u32));
2740 }
Olaf Heringe4805922007-04-04 18:20:04 +02002741 }
Benjamin Herrenschmidte8c0acf2006-07-04 14:06:29 +10002742}
2743#else
2744#define fixup_device_tree_chrp()
2745#endif
2746
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002747#if defined(CONFIG_PPC64) && defined(CONFIG_PPC_PMAC)
Hollis Blanchard54f4ee12006-05-25 16:36:53 -05002748static void __init fixup_device_tree_pmac(void)
2749{
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002750 phandle u3, i2c, mpic;
2751 u32 u3_rev;
2752 u32 interrupts[2];
2753 u32 parent;
2754
2755 /* Some G5s have a missing interrupt definition, fix it up here */
2756 u3 = call_prom("finddevice", 1, 1, ADDR("/u3@0,f8000000"));
2757 if (!PHANDLE_VALID(u3))
2758 return;
2759 i2c = call_prom("finddevice", 1, 1, ADDR("/u3@0,f8000000/i2c@f8001000"));
2760 if (!PHANDLE_VALID(i2c))
2761 return;
2762 mpic = call_prom("finddevice", 1, 1, ADDR("/u3@0,f8000000/mpic@f8040000"));
2763 if (!PHANDLE_VALID(mpic))
2764 return;
2765
2766 /* check if proper rev of u3 */
2767 if (prom_getprop(u3, "device-rev", &u3_rev, sizeof(u3_rev))
2768 == PROM_ERROR)
2769 return;
Benjamin Herrenschmidt7d496972005-11-07 14:36:21 +11002770 if (u3_rev < 0x35 || u3_rev > 0x39)
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002771 return;
2772 /* does it need fixup ? */
2773 if (prom_getproplen(i2c, "interrupts") > 0)
2774 return;
2775
2776 prom_printf("fixing up bogus interrupts for u3 i2c...\n");
2777
2778 /* interrupt on this revision of u3 is number 0 and level */
2779 interrupts[0] = 0;
2780 interrupts[1] = 1;
Paul Mackerrasa23414b2005-11-10 12:00:55 +11002781 prom_setprop(i2c, "/u3@0,f8000000/i2c@f8001000", "interrupts",
2782 &interrupts, sizeof(interrupts));
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002783 parent = (u32)mpic;
Paul Mackerrasa23414b2005-11-10 12:00:55 +11002784 prom_setprop(i2c, "/u3@0,f8000000/i2c@f8001000", "interrupt-parent",
2785 &parent, sizeof(parent));
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002786}
Hollis Blanchard54f4ee12006-05-25 16:36:53 -05002787#else
2788#define fixup_device_tree_pmac()
2789#endif
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002790
Sylvain Munaut88fd2a92007-02-12 23:13:20 +01002791#ifdef CONFIG_PPC_EFIKA
Grant Likely94d2dde2008-01-24 22:25:32 -07002792/*
2793 * The MPC5200 FEC driver requires an phy-handle property to tell it how
2794 * to talk to the phy. If the phy-handle property is missing, then this
2795 * function is called to add the appropriate nodes and link it to the
2796 * ethernet node.
2797 */
2798static void __init fixup_device_tree_efika_add_phy(void)
Sylvain Munaut88fd2a92007-02-12 23:13:20 +01002799{
Sylvain Munaut88fd2a92007-02-12 23:13:20 +01002800 u32 node;
2801 char prop[64];
Grant Likely94d2dde2008-01-24 22:25:32 -07002802 int rv;
Sylvain Munaut88fd2a92007-02-12 23:13:20 +01002803
Grant Likely94d2dde2008-01-24 22:25:32 -07002804 /* Check if /builtin/ethernet exists - bail if it doesn't */
2805 node = call_prom("finddevice", 1, 1, ADDR("/builtin/ethernet"));
Sylvain Munaut88fd2a92007-02-12 23:13:20 +01002806 if (!PHANDLE_VALID(node))
2807 return;
2808
Grant Likely94d2dde2008-01-24 22:25:32 -07002809 /* Check if the phy-handle property exists - bail if it does */
2810 rv = prom_getprop(node, "phy-handle", prop, sizeof(prop));
2811 if (!rv)
Sylvain Munaut88fd2a92007-02-12 23:13:20 +01002812 return;
2813
Grant Likely94d2dde2008-01-24 22:25:32 -07002814 /*
2815 * At this point the ethernet device doesn't have a phy described.
2816 * Now we need to add the missing phy node and linkage
2817 */
Sylvain Munaut88fd2a92007-02-12 23:13:20 +01002818
Grant Likely94d2dde2008-01-24 22:25:32 -07002819 /* Check for an MDIO bus node - if missing then create one */
Olaf Hering6f4347c2008-01-10 01:06:08 +11002820 node = call_prom("finddevice", 1, 1, ADDR("/builtin/mdio"));
2821 if (!PHANDLE_VALID(node)) {
2822 prom_printf("Adding Ethernet MDIO node\n");
2823 call_prom("interpret", 1, 1,
2824 " s\" /builtin\" find-device"
2825 " new-device"
2826 " 1 encode-int s\" #address-cells\" property"
2827 " 0 encode-int s\" #size-cells\" property"
Grant Likely94d2dde2008-01-24 22:25:32 -07002828 " s\" mdio\" device-name"
2829 " s\" fsl,mpc5200b-mdio\" encode-string"
Olaf Hering6f4347c2008-01-10 01:06:08 +11002830 " s\" compatible\" property"
2831 " 0xf0003000 0x400 reg"
2832 " 0x2 encode-int"
2833 " 0x5 encode-int encode+"
2834 " 0x3 encode-int encode+"
2835 " s\" interrupts\" property"
2836 " finish-device");
2837 };
2838
Grant Likely94d2dde2008-01-24 22:25:32 -07002839 /* Check for a PHY device node - if missing then create one and
2840 * give it's phandle to the ethernet node */
2841 node = call_prom("finddevice", 1, 1,
2842 ADDR("/builtin/mdio/ethernet-phy"));
Olaf Hering6f4347c2008-01-10 01:06:08 +11002843 if (!PHANDLE_VALID(node)) {
2844 prom_printf("Adding Ethernet PHY node\n");
2845 call_prom("interpret", 1, 1,
2846 " s\" /builtin/mdio\" find-device"
2847 " new-device"
2848 " s\" ethernet-phy\" device-name"
2849 " 0x10 encode-int s\" reg\" property"
2850 " my-self"
2851 " ihandle>phandle"
2852 " finish-device"
2853 " s\" /builtin/ethernet\" find-device"
2854 " encode-int"
2855 " s\" phy-handle\" property"
2856 " device-end");
2857 }
Grant Likely94d2dde2008-01-24 22:25:32 -07002858}
Olaf Hering6f4347c2008-01-10 01:06:08 +11002859
Grant Likely94d2dde2008-01-24 22:25:32 -07002860static void __init fixup_device_tree_efika(void)
2861{
2862 int sound_irq[3] = { 2, 2, 0 };
2863 int bcomm_irq[3*16] = { 3,0,0, 3,1,0, 3,2,0, 3,3,0,
2864 3,4,0, 3,5,0, 3,6,0, 3,7,0,
2865 3,8,0, 3,9,0, 3,10,0, 3,11,0,
2866 3,12,0, 3,13,0, 3,14,0, 3,15,0 };
2867 u32 node;
2868 char prop[64];
2869 int rv, len;
2870
2871 /* Check if we're really running on a EFIKA */
2872 node = call_prom("finddevice", 1, 1, ADDR("/"));
2873 if (!PHANDLE_VALID(node))
2874 return;
2875
2876 rv = prom_getprop(node, "model", prop, sizeof(prop));
2877 if (rv == PROM_ERROR)
2878 return;
2879 if (strcmp(prop, "EFIKA5K2"))
2880 return;
2881
2882 prom_printf("Applying EFIKA device tree fixups\n");
2883
2884 /* Claiming to be 'chrp' is death */
2885 node = call_prom("finddevice", 1, 1, ADDR("/"));
2886 rv = prom_getprop(node, "device_type", prop, sizeof(prop));
2887 if (rv != PROM_ERROR && (strcmp(prop, "chrp") == 0))
2888 prom_setprop(node, "/", "device_type", "efika", sizeof("efika"));
2889
David Woodhouse7f4392c2008-04-14 02:52:38 +10002890 /* CODEGEN,description is exposed in /proc/cpuinfo so
2891 fix that too */
2892 rv = prom_getprop(node, "CODEGEN,description", prop, sizeof(prop));
2893 if (rv != PROM_ERROR && (strstr(prop, "CHRP")))
2894 prom_setprop(node, "/", "CODEGEN,description",
2895 "Efika 5200B PowerPC System",
2896 sizeof("Efika 5200B PowerPC System"));
2897
Grant Likely94d2dde2008-01-24 22:25:32 -07002898 /* Fixup bestcomm interrupts property */
2899 node = call_prom("finddevice", 1, 1, ADDR("/builtin/bestcomm"));
2900 if (PHANDLE_VALID(node)) {
2901 len = prom_getproplen(node, "interrupts");
2902 if (len == 12) {
2903 prom_printf("Fixing bestcomm interrupts property\n");
2904 prom_setprop(node, "/builtin/bestcom", "interrupts",
2905 bcomm_irq, sizeof(bcomm_irq));
2906 }
2907 }
2908
2909 /* Fixup sound interrupts property */
2910 node = call_prom("finddevice", 1, 1, ADDR("/builtin/sound"));
2911 if (PHANDLE_VALID(node)) {
2912 rv = prom_getprop(node, "interrupts", prop, sizeof(prop));
2913 if (rv == PROM_ERROR) {
2914 prom_printf("Adding sound interrupts property\n");
2915 prom_setprop(node, "/builtin/sound", "interrupts",
2916 sound_irq, sizeof(sound_irq));
2917 }
2918 }
2919
2920 /* Make sure ethernet phy-handle property exists */
2921 fixup_device_tree_efika_add_phy();
Sylvain Munaut88fd2a92007-02-12 23:13:20 +01002922}
2923#else
2924#define fixup_device_tree_efika()
2925#endif
2926
Darren Stevens50246782016-08-31 13:24:40 +01002927#ifdef CONFIG_PPC_PASEMI_NEMO
2928/*
2929 * CFE supplied on Nemo is broken in several ways, biggest
2930 * problem is that it reassigns ISA interrupts to unused mpic ints.
2931 * Add an interrupt-controller property for the io-bridge to use
2932 * and correct the ints so we can attach them to an irq_domain
2933 */
2934static void __init fixup_device_tree_pasemi(void)
2935{
2936 u32 interrupts[2], parent, rval, val = 0;
2937 char *name, *pci_name;
2938 phandle iob, node;
2939
2940 /* Find the root pci node */
2941 name = "/pxp@0,e0000000";
2942 iob = call_prom("finddevice", 1, 1, ADDR(name));
2943 if (!PHANDLE_VALID(iob))
2944 return;
2945
2946 /* check if interrupt-controller node set yet */
2947 if (prom_getproplen(iob, "interrupt-controller") !=PROM_ERROR)
2948 return;
2949
2950 prom_printf("adding interrupt-controller property for SB600...\n");
2951
2952 prom_setprop(iob, name, "interrupt-controller", &val, 0);
2953
2954 pci_name = "/pxp@0,e0000000/pci@11";
2955 node = call_prom("finddevice", 1, 1, ADDR(pci_name));
2956 parent = ADDR(iob);
2957
2958 for( ; prom_next_node(&node); ) {
2959 /* scan each node for one with an interrupt */
2960 if (!PHANDLE_VALID(node))
2961 continue;
2962
2963 rval = prom_getproplen(node, "interrupts");
2964 if (rval == 0 || rval == PROM_ERROR)
2965 continue;
2966
2967 prom_getprop(node, "interrupts", &interrupts, sizeof(interrupts));
2968 if ((interrupts[0] < 212) || (interrupts[0] > 222))
2969 continue;
2970
2971 /* found a node, update both interrupts and interrupt-parent */
2972 if ((interrupts[0] >= 212) && (interrupts[0] <= 215))
2973 interrupts[0] -= 203;
2974 if ((interrupts[0] >= 216) && (interrupts[0] <= 220))
2975 interrupts[0] -= 213;
2976 if (interrupts[0] == 221)
2977 interrupts[0] = 14;
2978 if (interrupts[0] == 222)
2979 interrupts[0] = 8;
2980
2981 prom_setprop(node, pci_name, "interrupts", interrupts,
2982 sizeof(interrupts));
2983 prom_setprop(node, pci_name, "interrupt-parent", &parent,
2984 sizeof(parent));
2985 }
Darren Stevens687e16b2016-08-31 13:24:45 +01002986
2987 /*
2988 * The io-bridge has device_type set to 'io-bridge' change it to 'isa'
2989 * so that generic isa-bridge code can add the SB600 and its on-board
2990 * peripherals.
2991 */
2992 name = "/pxp@0,e0000000/io-bridge@0";
2993 iob = call_prom("finddevice", 1, 1, ADDR(name));
2994 if (!PHANDLE_VALID(iob))
2995 return;
2996
2997 /* device_type is already set, just change it. */
2998
2999 prom_printf("Changing device_type of SB600 node...\n");
3000
3001 prom_setprop(iob, name, "device_type", "isa", sizeof("isa"));
Darren Stevens50246782016-08-31 13:24:40 +01003002}
3003#else /* !CONFIG_PPC_PASEMI_NEMO */
3004static inline void fixup_device_tree_pasemi(void) { }
3005#endif
3006
Hollis Blanchard54f4ee12006-05-25 16:36:53 -05003007static void __init fixup_device_tree(void)
3008{
3009 fixup_device_tree_maple();
Harry Ciao8f101a052009-06-17 16:28:00 -07003010 fixup_device_tree_maple_memory_controller();
Benjamin Herrenschmidte8c0acf2006-07-04 14:06:29 +10003011 fixup_device_tree_chrp();
Hollis Blanchard54f4ee12006-05-25 16:36:53 -05003012 fixup_device_tree_pmac();
Sylvain Munaut88fd2a92007-02-12 23:13:20 +01003013 fixup_device_tree_efika();
Darren Stevens50246782016-08-31 13:24:40 +01003014 fixup_device_tree_pasemi();
Hollis Blanchard54f4ee12006-05-25 16:36:53 -05003015}
Paul Mackerras9b6b5632005-10-06 12:06:20 +10003016
3017static void __init prom_find_boot_cpu(void)
3018{
Benjamin Herrenschmidt493adff2013-08-07 02:01:38 +10003019 __be32 rval;
Paul Mackerras9b6b5632005-10-06 12:06:20 +10003020 ihandle prom_cpu;
3021 phandle cpu_pkg;
3022
Benjamin Herrenschmidt493adff2013-08-07 02:01:38 +10003023 rval = 0;
3024 if (prom_getprop(prom.chosen, "cpu", &rval, sizeof(rval)) <= 0)
Paul Mackerrasa575b802005-10-23 17:23:21 +10003025 return;
Benjamin Herrenschmidt493adff2013-08-07 02:01:38 +10003026 prom_cpu = be32_to_cpu(rval);
Paul Mackerras9b6b5632005-10-06 12:06:20 +10003027
3028 cpu_pkg = call_prom("instance-to-package", 1, 1, prom_cpu);
3029
Darren Stevensaf2b7fa2017-01-23 19:42:54 +00003030 if (!PHANDLE_VALID(cpu_pkg))
3031 return;
3032
Benjamin Herrenschmidt493adff2013-08-07 02:01:38 +10003033 prom_getprop(cpu_pkg, "reg", &rval, sizeof(rval));
3034 prom.cpu = be32_to_cpu(rval);
Paul Mackerras9b6b5632005-10-06 12:06:20 +10003035
Mathieu Malaterreeae5f702018-04-06 22:12:19 +02003036 prom_debug("Booting CPU hw index = %d\n", prom.cpu);
Paul Mackerras9b6b5632005-10-06 12:06:20 +10003037}
3038
3039static void __init prom_check_initrd(unsigned long r3, unsigned long r4)
3040{
3041#ifdef CONFIG_BLK_DEV_INITRD
Paul Mackerras9b6b5632005-10-06 12:06:20 +10003042 if (r3 && r4 && r4 != 0xdeadbeef) {
Benjamin Herrenschmidt493adff2013-08-07 02:01:38 +10003043 __be64 val;
Paul Mackerras9b6b5632005-10-06 12:06:20 +10003044
Anton Blanchard5827d412012-11-26 17:40:03 +00003045 prom_initrd_start = is_kernel_addr(r3) ? __pa(r3) : r3;
3046 prom_initrd_end = prom_initrd_start + r4;
Paul Mackerras9b6b5632005-10-06 12:06:20 +10003047
Benjamin Herrenschmidt493adff2013-08-07 02:01:38 +10003048 val = cpu_to_be64(prom_initrd_start);
Anton Blanchard5827d412012-11-26 17:40:03 +00003049 prom_setprop(prom.chosen, "/chosen", "linux,initrd-start",
Paul Mackerrasa23414b2005-11-10 12:00:55 +11003050 &val, sizeof(val));
Benjamin Herrenschmidt493adff2013-08-07 02:01:38 +10003051 val = cpu_to_be64(prom_initrd_end);
Anton Blanchard5827d412012-11-26 17:40:03 +00003052 prom_setprop(prom.chosen, "/chosen", "linux,initrd-end",
Paul Mackerrasa23414b2005-11-10 12:00:55 +11003053 &val, sizeof(val));
Paul Mackerras9b6b5632005-10-06 12:06:20 +10003054
Anton Blanchard5827d412012-11-26 17:40:03 +00003055 reserve_mem(prom_initrd_start,
3056 prom_initrd_end - prom_initrd_start);
Paul Mackerras9b6b5632005-10-06 12:06:20 +10003057
Mathieu Malaterreeae5f702018-04-06 22:12:19 +02003058 prom_debug("initrd_start=0x%lx\n", prom_initrd_start);
3059 prom_debug("initrd_end=0x%lx\n", prom_initrd_end);
Paul Mackerras9b6b5632005-10-06 12:06:20 +10003060 }
3061#endif /* CONFIG_BLK_DEV_INITRD */
3062}
3063
Anton Blanchard5ac47f72012-11-26 17:39:03 +00003064#ifdef CONFIG_PPC64
3065#ifdef CONFIG_RELOCATABLE
3066static void reloc_toc(void)
3067{
3068}
3069
3070static void unreloc_toc(void)
3071{
3072}
3073#else
Anton Blanchard16744002013-03-12 01:51:51 +00003074static void __reloc_toc(unsigned long offset, unsigned long nr_entries)
Anton Blanchard5ac47f72012-11-26 17:39:03 +00003075{
3076 unsigned long i;
Anton Blanchard16744002013-03-12 01:51:51 +00003077 unsigned long *toc_entry;
3078
3079 /* Get the start of the TOC by using r2 directly. */
3080 asm volatile("addi %0,2,-0x8000" : "=b" (toc_entry));
Anton Blanchard5ac47f72012-11-26 17:39:03 +00003081
3082 for (i = 0; i < nr_entries; i++) {
3083 *toc_entry = *toc_entry + offset;
3084 toc_entry++;
3085 }
3086}
3087
3088static void reloc_toc(void)
3089{
3090 unsigned long offset = reloc_offset();
3091 unsigned long nr_entries =
3092 (__prom_init_toc_end - __prom_init_toc_start) / sizeof(long);
3093
Anton Blanchard16744002013-03-12 01:51:51 +00003094 __reloc_toc(offset, nr_entries);
Anton Blanchard5ac47f72012-11-26 17:39:03 +00003095
3096 mb();
3097}
3098
3099static void unreloc_toc(void)
3100{
3101 unsigned long offset = reloc_offset();
3102 unsigned long nr_entries =
3103 (__prom_init_toc_end - __prom_init_toc_start) / sizeof(long);
3104
3105 mb();
3106
Anton Blanchard16744002013-03-12 01:51:51 +00003107 __reloc_toc(-offset, nr_entries);
Anton Blanchard5ac47f72012-11-26 17:39:03 +00003108}
3109#endif
3110#endif
Benjamin Herrenschmidt27f44882011-09-19 18:27:58 +00003111
Paul Mackerras9b6b5632005-10-06 12:06:20 +10003112/*
3113 * We enter here early on, when the Open Firmware prom is still
3114 * handling exceptions and the MMU hash table for us.
3115 */
3116
3117unsigned long __init prom_init(unsigned long r3, unsigned long r4,
3118 unsigned long pp,
Paul Mackerras549e8152008-08-30 11:43:47 +10003119 unsigned long r6, unsigned long r7,
3120 unsigned long kbase)
Paul Mackerras9b6b5632005-10-06 12:06:20 +10003121{
Paul Mackerras9b6b5632005-10-06 12:06:20 +10003122 unsigned long hdr;
Paul Mackerras9b6b5632005-10-06 12:06:20 +10003123
3124#ifdef CONFIG_PPC32
Paul Mackerras549e8152008-08-30 11:43:47 +10003125 unsigned long offset = reloc_offset();
Paul Mackerras9b6b5632005-10-06 12:06:20 +10003126 reloc_got2(offset);
Anton Blanchard5ac47f72012-11-26 17:39:03 +00003127#else
3128 reloc_toc();
Paul Mackerras9b6b5632005-10-06 12:06:20 +10003129#endif
3130
Paul Mackerras9b6b5632005-10-06 12:06:20 +10003131 /*
3132 * First zero the BSS
3133 */
Anton Blanchard5827d412012-11-26 17:40:03 +00003134 memset(&__bss_start, 0, __bss_stop - __bss_start);
Paul Mackerras9b6b5632005-10-06 12:06:20 +10003135
3136 /*
3137 * Init interface to Open Firmware, get some node references,
3138 * like /chosen
3139 */
3140 prom_init_client_services(pp);
3141
3142 /*
Paul Mackerrasa23414b2005-11-10 12:00:55 +11003143 * See if this OF is old enough that we need to do explicit maps
3144 * and other workarounds
3145 */
3146 prom_find_mmu();
3147
3148 /*
Paul Mackerras9b6b5632005-10-06 12:06:20 +10003149 * Init prom stdout device
3150 */
3151 prom_init_stdout();
3152
Anton Blanchard5827d412012-11-26 17:40:03 +00003153 prom_printf("Preparing to boot %s", linux_banner);
Michael Ellermane7943fb2009-03-04 19:02:01 +00003154
Paul Mackerras9b6b5632005-10-06 12:06:20 +10003155 /*
3156 * Get default machine type. At this point, we do not differentiate
3157 * between pSeries SMP and pSeries LPAR
3158 */
Anton Blanchard5827d412012-11-26 17:40:03 +00003159 of_platform = prom_find_machine_type();
3160 prom_printf("Detected machine type: %x\n", of_platform);
Paul Mackerras9b6b5632005-10-06 12:06:20 +10003161
Suzuki Poulose0f890c82011-12-14 22:57:15 +00003162#ifndef CONFIG_NONSTATIC_KERNEL
Olaf Heringadd60ef2006-03-23 22:03:57 +01003163 /* Bail if this is a kdump kernel. */
3164 if (PHYSICAL_START > 0)
3165 prom_panic("Error: You can't boot a kdump kernel from OF!\n");
Paul Mackerras549e8152008-08-30 11:43:47 +10003166#endif
Olaf Heringadd60ef2006-03-23 22:03:57 +01003167
3168 /*
3169 * Check for an initrd
3170 */
3171 prom_check_initrd(r3, r4);
3172
Suraj Jitindar Singh12cc9fd2017-02-28 17:03:47 +11003173 /*
3174 * Do early parsing of command line
3175 */
3176 early_cmdline_parse();
3177
Benjamin Herrenschmidt27f44882011-09-19 18:27:58 +00003178#if defined(CONFIG_PPC_PSERIES) || defined(CONFIG_PPC_POWERNV)
Paul Mackerras9b6b5632005-10-06 12:06:20 +10003179 /*
3180 * On pSeries, inform the firmware about our capabilities
3181 */
Anton Blanchard5827d412012-11-26 17:40:03 +00003182 if (of_platform == PLATFORM_PSERIES ||
3183 of_platform == PLATFORM_PSERIES_LPAR)
Paul Mackerras9b6b5632005-10-06 12:06:20 +10003184 prom_send_capabilities();
3185#endif
3186
Paul Mackerras9b6b5632005-10-06 12:06:20 +10003187 /*
Arnd Bergmannf3f66f52005-10-31 20:08:37 -05003188 * Copy the CPU hold code
Paul Mackerras9b6b5632005-10-06 12:06:20 +10003189 */
Anton Blanchard5827d412012-11-26 17:40:03 +00003190 if (of_platform != PLATFORM_POWERMAC)
Paul Mackerras549e8152008-08-30 11:43:47 +10003191 copy_and_flush(0, kbase, 0x100, 0);
Paul Mackerras9b6b5632005-10-06 12:06:20 +10003192
3193 /*
Paul Mackerras9b6b5632005-10-06 12:06:20 +10003194 * Initialize memory management within prom_init
3195 */
3196 prom_init_mem();
3197
3198 /*
3199 * Determine which cpu is actually running right _now_
3200 */
3201 prom_find_boot_cpu();
3202
3203 /*
3204 * Initialize display devices
3205 */
3206 prom_check_displays();
3207
Benjamin Herrenschmidt493adff2013-08-07 02:01:38 +10003208#if defined(CONFIG_PPC64) && defined(__BIG_ENDIAN__)
Paul Mackerras9b6b5632005-10-06 12:06:20 +10003209 /*
3210 * Initialize IOMMU (TCE tables) on pSeries. Do that before anything else
3211 * that uses the allocator, we need to make sure we get the top of memory
3212 * available for us here...
3213 */
Anton Blanchard5827d412012-11-26 17:40:03 +00003214 if (of_platform == PLATFORM_PSERIES)
Paul Mackerras9b6b5632005-10-06 12:06:20 +10003215 prom_initialize_tce_table();
3216#endif
3217
3218 /*
Benjamin Herrenschmidt27f44882011-09-19 18:27:58 +00003219 * On non-powermacs, try to instantiate RTAS. PowerMacs don't
3220 * have a usable RTAS implementation.
Paul Mackerras9b6b5632005-10-06 12:06:20 +10003221 */
Anton Blanchard5827d412012-11-26 17:40:03 +00003222 if (of_platform != PLATFORM_POWERMAC &&
3223 of_platform != PLATFORM_OPAL)
Paul Mackerras9b6b5632005-10-06 12:06:20 +10003224 prom_instantiate_rtas();
Benjamin Herrenschmidt27f44882011-09-19 18:27:58 +00003225
3226#ifdef CONFIG_PPC_POWERNV
Benjamin Herrenschmidt493adff2013-08-07 02:01:38 +10003227 if (of_platform == PLATFORM_OPAL)
Benjamin Herrenschmidt6e35d5d2011-09-19 18:28:01 +00003228 prom_instantiate_opal();
Benjamin Herrenschmidt493adff2013-08-07 02:01:38 +10003229#endif /* CONFIG_PPC_POWERNV */
Benjamin Herrenschmidt27f44882011-09-19 18:27:58 +00003230
Ashley Lai4a727422012-08-14 18:34:57 -05003231#ifdef CONFIG_PPC64
3232 /* instantiate sml */
3233 prom_instantiate_sml();
3234#endif
3235
Benjamin Herrenschmidt27f44882011-09-19 18:27:58 +00003236 /*
3237 * On non-powermacs, put all CPUs in spin-loops.
3238 *
3239 * PowerMacs use a different mechanism to spin CPUs
Benjamin Herrenschmidtdbe78b42013-09-25 14:02:50 +10003240 *
3241 * (This must be done after instanciating RTAS)
Benjamin Herrenschmidt27f44882011-09-19 18:27:58 +00003242 */
Anton Blanchard5827d412012-11-26 17:40:03 +00003243 if (of_platform != PLATFORM_POWERMAC &&
3244 of_platform != PLATFORM_OPAL)
Benjamin Herrenschmidt27f44882011-09-19 18:27:58 +00003245 prom_hold_cpus();
Paul Mackerras9b6b5632005-10-06 12:06:20 +10003246
3247 /*
3248 * Fill in some infos for use by the kernel later on
3249 */
Benjamin Herrenschmidt493adff2013-08-07 02:01:38 +10003250 if (prom_memory_limit) {
3251 __be64 val = cpu_to_be64(prom_memory_limit);
Anton Blanchard5827d412012-11-26 17:40:03 +00003252 prom_setprop(prom.chosen, "/chosen", "linux,memory-limit",
Benjamin Herrenschmidt493adff2013-08-07 02:01:38 +10003253 &val, sizeof(val));
3254 }
Paul Mackerras9b6b5632005-10-06 12:06:20 +10003255#ifdef CONFIG_PPC64
Anton Blanchard5827d412012-11-26 17:40:03 +00003256 if (prom_iommu_off)
3257 prom_setprop(prom.chosen, "/chosen", "linux,iommu-off",
Paul Mackerrasa23414b2005-11-10 12:00:55 +11003258 NULL, 0);
Paul Mackerras9b6b5632005-10-06 12:06:20 +10003259
Anton Blanchard5827d412012-11-26 17:40:03 +00003260 if (prom_iommu_force_on)
3261 prom_setprop(prom.chosen, "/chosen", "linux,iommu-force-on",
Paul Mackerrasa23414b2005-11-10 12:00:55 +11003262 NULL, 0);
Paul Mackerras9b6b5632005-10-06 12:06:20 +10003263
Anton Blanchard5827d412012-11-26 17:40:03 +00003264 if (prom_tce_alloc_start) {
3265 prom_setprop(prom.chosen, "/chosen", "linux,tce-alloc-start",
3266 &prom_tce_alloc_start,
Paul Mackerras9b6b5632005-10-06 12:06:20 +10003267 sizeof(prom_tce_alloc_start));
Anton Blanchard5827d412012-11-26 17:40:03 +00003268 prom_setprop(prom.chosen, "/chosen", "linux,tce-alloc-end",
3269 &prom_tce_alloc_end,
Paul Mackerras9b6b5632005-10-06 12:06:20 +10003270 sizeof(prom_tce_alloc_end));
3271 }
3272#endif
3273
3274 /*
3275 * Fixup any known bugs in the device-tree
3276 */
3277 fixup_device_tree();
3278
3279 /*
3280 * Now finally create the flattened device-tree
3281 */
Anton Blanchard1f8737a2009-03-31 20:06:15 +00003282 prom_printf("copying OF device tree...\n");
Paul Mackerras9b6b5632005-10-06 12:06:20 +10003283 flatten_device_tree();
3284
Paul Mackerras3825ac02005-11-08 22:48:08 +11003285 /*
3286 * in case stdin is USB and still active on IBM machines...
3287 * Unfortunately quiesce crashes on some powermacs if we have
Benjamin Herrenschmidt40dfef62011-11-29 18:22:56 +00003288 * closed stdin already (in particular the powerbook 101). It
3289 * appears that the OPAL version of OFW doesn't like it either.
Paul Mackerras3825ac02005-11-08 22:48:08 +11003290 */
Anton Blanchard5827d412012-11-26 17:40:03 +00003291 if (of_platform != PLATFORM_POWERMAC &&
3292 of_platform != PLATFORM_OPAL)
Paul Mackerras3825ac02005-11-08 22:48:08 +11003293 prom_close_stdin();
Paul Mackerras9b6b5632005-10-06 12:06:20 +10003294
3295 /*
3296 * Call OF "quiesce" method to shut down pending DMA's from
3297 * devices etc...
3298 */
Michael Ellerman7e862d72015-03-30 17:38:09 +11003299 prom_printf("Quiescing Open Firmware ...\n");
Paul Mackerras9b6b5632005-10-06 12:06:20 +10003300 call_prom("quiesce", 0, 0);
3301
3302 /*
3303 * And finally, call the kernel passing it the flattened device
3304 * tree and NULL as r5, thus triggering the new entry point which
3305 * is common to us and kexec
3306 */
Anton Blanchard5827d412012-11-26 17:40:03 +00003307 hdr = dt_header_start;
Benjamin Herrenschmidt40dfef62011-11-29 18:22:56 +00003308
3309 /* Don't print anything after quiesce under OPAL, it crashes OFW */
Anton Blanchard5827d412012-11-26 17:40:03 +00003310 if (of_platform != PLATFORM_OPAL) {
Benjamin Herrenschmidt7d70c632016-08-10 17:29:29 +10003311 prom_printf("Booting Linux via __start() @ 0x%lx ...\n", kbase);
Mathieu Malaterreeae5f702018-04-06 22:12:19 +02003312 prom_debug("->dt_header_start=0x%lx\n", hdr);
Benjamin Herrenschmidt40dfef62011-11-29 18:22:56 +00003313 }
Paul Mackerras9b6b5632005-10-06 12:06:20 +10003314
3315#ifdef CONFIG_PPC32
3316 reloc_got2(-offset);
Anton Blanchard5ac47f72012-11-26 17:39:03 +00003317#else
3318 unreloc_toc();
Paul Mackerras9b6b5632005-10-06 12:06:20 +10003319#endif
3320
Benjamin Herrenschmidt6e35d5d2011-09-19 18:28:01 +00003321#ifdef CONFIG_PPC_EARLY_DEBUG_OPAL
3322 /* OPAL early debug gets the OPAL base & entry in r8 and r9 */
3323 __start(hdr, kbase, 0, 0, 0,
Anton Blanchard5827d412012-11-26 17:40:03 +00003324 prom_opal_base, prom_opal_entry);
Benjamin Herrenschmidt6e35d5d2011-09-19 18:28:01 +00003325#else
3326 __start(hdr, kbase, 0, 0, 0, 0, 0);
3327#endif
Paul Mackerras9b6b5632005-10-06 12:06:20 +10003328
3329 return 0;
3330}