blob: dec8f7f689a2e068cefbeb71fa5d0c377fa0b7bb [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>
Daniel Axtens0545d542016-09-06 15:32:43 +100046#include <asm/asm-prototypes.h>
Paul Mackerras9b6b5632005-10-06 12:06:20 +100047
Paul Mackerras9b6b5632005-10-06 12:06:20 +100048#include <linux/linux_logo.h>
Paul Mackerras9b6b5632005-10-06 12:06:20 +100049
Benjamin Herrenschmidte63334e2018-10-15 13:49:52 +110050/* All of prom_init bss lives here */
51#define __prombss __initdata
52
Paul Mackerras9b6b5632005-10-06 12:06:20 +100053/*
Paul Mackerras9b6b5632005-10-06 12:06:20 +100054 * Eventually bump that one up
55 */
56#define DEVTREE_CHUNK_SIZE 0x100000
57
58/*
59 * This is the size of the local memory reserve map that gets copied
60 * into the boot params passed to the kernel. That size is totally
61 * flexible as the kernel just reads the list until it encounters an
62 * entry with size 0, so it can be changed without breaking binary
63 * compatibility
64 */
65#define MEM_RESERVE_MAP_SIZE 8
66
67/*
68 * prom_init() is called very early on, before the kernel text
69 * and data have been mapped to KERNELBASE. At this point the code
70 * is running at whatever address it has been loaded at.
71 * On ppc32 we compile with -mrelocatable, which means that references
72 * to extern and static variables get relocated automatically.
Anton Blanchard5ac47f72012-11-26 17:39:03 +000073 * ppc64 objects are always relocatable, we just need to relocate the
74 * TOC.
Paul Mackerras9b6b5632005-10-06 12:06:20 +100075 *
76 * Because OF may have mapped I/O devices into the area starting at
77 * KERNELBASE, particularly on CHRP machines, we can't safely call
78 * OF once the kernel has been mapped to KERNELBASE. Therefore all
79 * OF calls must be done within prom_init().
80 *
81 * ADDR is used in calls to call_prom. The 4th and following
82 * arguments to call_prom should be 32-bit values.
83 * On ppc64, 64 bit values are truncated to 32 bits (and
84 * fortunately don't get interpreted as two arguments).
85 */
Anton Blanchard5ac47f72012-11-26 17:39:03 +000086#define ADDR(x) (u32)(unsigned long)(x)
87
Paul Mackerras9b6b5632005-10-06 12:06:20 +100088#ifdef CONFIG_PPC64
Paul Mackerrasa23414b2005-11-10 12:00:55 +110089#define OF_WORKAROUNDS 0
Paul Mackerras9b6b5632005-10-06 12:06:20 +100090#else
Paul Mackerrasa23414b2005-11-10 12:00:55 +110091#define OF_WORKAROUNDS of_workarounds
Benjamin Herrenschmidte63334e2018-10-15 13:49:52 +110092static int of_workarounds __prombss;
Paul Mackerras9b6b5632005-10-06 12:06:20 +100093#endif
94
Paul Mackerrasa23414b2005-11-10 12:00:55 +110095#define OF_WA_CLAIM 1 /* do phys/virt claim separately, then map */
96#define OF_WA_LONGTRAIL 2 /* work around longtrail bugs */
97
Paul Mackerras9b6b5632005-10-06 12:06:20 +100098#define PROM_BUG() do { \
99 prom_printf("kernel BUG at %s line 0x%x!\n", \
Anton Blanchard5827d412012-11-26 17:40:03 +0000100 __FILE__, __LINE__); \
Paul Mackerras9b6b5632005-10-06 12:06:20 +1000101 __asm__ __volatile__(".long " BUG_ILLEGAL_INSTR); \
102} while (0)
103
104#ifdef DEBUG_PROM
105#define prom_debug(x...) prom_printf(x)
106#else
Mathieu Malaterre85aa4b92018-04-23 21:36:38 +0200107#define prom_debug(x...) do { } while (0)
Paul Mackerras9b6b5632005-10-06 12:06:20 +1000108#endif
109
Paul Mackerras9b6b5632005-10-06 12:06:20 +1000110
111typedef u32 prom_arg_t;
112
113struct prom_args {
Benjamin Herrenschmidt493adff2013-08-07 02:01:38 +1000114 __be32 service;
115 __be32 nargs;
116 __be32 nret;
117 __be32 args[10];
Paul Mackerras9b6b5632005-10-06 12:06:20 +1000118};
119
120struct prom_t {
121 ihandle root;
Paul Mackerrasa23414b2005-11-10 12:00:55 +1100122 phandle chosen;
Paul Mackerras9b6b5632005-10-06 12:06:20 +1000123 int cpu;
124 ihandle stdout;
Paul Mackerrasa575b802005-10-23 17:23:21 +1000125 ihandle mmumap;
Paul Mackerrasa23414b2005-11-10 12:00:55 +1100126 ihandle memory;
Paul Mackerras9b6b5632005-10-06 12:06:20 +1000127};
128
129struct mem_map_entry {
Benjamin Herrenschmidt493adff2013-08-07 02:01:38 +1000130 __be64 base;
131 __be64 size;
Paul Mackerras9b6b5632005-10-06 12:06:20 +1000132};
133
Benjamin Herrenschmidt493adff2013-08-07 02:01:38 +1000134typedef __be32 cell_t;
Paul Mackerras9b6b5632005-10-06 12:06:20 +1000135
Benjamin Herrenschmidt6e35d5d2011-09-19 18:28:01 +0000136extern void __start(unsigned long r3, unsigned long r4, unsigned long r5,
137 unsigned long r6, unsigned long r7, unsigned long r8,
138 unsigned long r9);
Paul Mackerras9b6b5632005-10-06 12:06:20 +1000139
140#ifdef CONFIG_PPC64
Paul Mackerrasc49888202005-10-26 21:52:53 +1000141extern int enter_prom(struct prom_args *args, unsigned long entry);
Paul Mackerras9b6b5632005-10-06 12:06:20 +1000142#else
Paul Mackerrasc49888202005-10-26 21:52:53 +1000143static inline int enter_prom(struct prom_args *args, unsigned long entry)
Paul Mackerras9b6b5632005-10-06 12:06:20 +1000144{
Paul Mackerrasc49888202005-10-26 21:52:53 +1000145 return ((int (*)(struct prom_args *))entry)(args);
Paul Mackerras9b6b5632005-10-06 12:06:20 +1000146}
147#endif
148
149extern void copy_and_flush(unsigned long dest, unsigned long src,
150 unsigned long size, unsigned long offset);
151
152/* prom structure */
Benjamin Herrenschmidte63334e2018-10-15 13:49:52 +1100153static struct prom_t __prombss prom;
Paul Mackerras9b6b5632005-10-06 12:06:20 +1000154
Benjamin Herrenschmidte63334e2018-10-15 13:49:52 +1100155static unsigned long __prombss prom_entry;
Paul Mackerras9b6b5632005-10-06 12:06:20 +1000156
157#define PROM_SCRATCH_SIZE 256
158
Benjamin Herrenschmidte63334e2018-10-15 13:49:52 +1100159static char __prombss of_stdout_device[256];
160static char __prombss prom_scratch[PROM_SCRATCH_SIZE];
Paul Mackerras9b6b5632005-10-06 12:06:20 +1000161
Benjamin Herrenschmidte63334e2018-10-15 13:49:52 +1100162static unsigned long __prombss dt_header_start;
163static unsigned long __prombss dt_struct_start, dt_struct_end;
164static unsigned long __prombss dt_string_start, dt_string_end;
Paul Mackerras9b6b5632005-10-06 12:06:20 +1000165
Benjamin Herrenschmidte63334e2018-10-15 13:49:52 +1100166static unsigned long __prombss prom_initrd_start, prom_initrd_end;
Paul Mackerras9b6b5632005-10-06 12:06:20 +1000167
168#ifdef CONFIG_PPC64
Benjamin Herrenschmidte63334e2018-10-15 13:49:52 +1100169static int __prombss prom_iommu_force_on;
170static int __prombss prom_iommu_off;
171static unsigned long __prombss prom_tce_alloc_start;
172static unsigned long __prombss prom_tce_alloc_end;
Paul Mackerras9b6b5632005-10-06 12:06:20 +1000173#endif
174
Benjamin Herrenschmidtc8860872018-10-15 13:49:54 +1100175#ifdef CONFIG_PPC_PSERIES
176static bool prom_radix_disable __prombss;
177#endif
Suraj Jitindar Singh014d02c2017-02-28 17:03:48 +1100178
179struct platform_support {
180 bool hash_mmu;
181 bool radix_mmu;
182 bool radix_gtse;
Cédric Le Goaterac5e5a52017-08-30 21:46:16 +0200183 bool xive;
Suraj Jitindar Singh014d02c2017-02-28 17:03:48 +1100184};
185
Benjamin Herrenschmidte8222502006-03-28 23:15:54 +1100186/* Platforms codes are now obsolete in the kernel. Now only used within this
187 * file and ultimately gone too. Feel free to change them if you need, they
188 * are not shared with anything outside of this file anymore
189 */
190#define PLATFORM_PSERIES 0x0100
191#define PLATFORM_PSERIES_LPAR 0x0101
192#define PLATFORM_LPAR 0x0001
193#define PLATFORM_POWERMAC 0x0400
194#define PLATFORM_GENERIC 0x0500
195
Benjamin Herrenschmidte63334e2018-10-15 13:49:52 +1100196static int __prombss of_platform;
Paul Mackerras9b6b5632005-10-06 12:06:20 +1000197
Benjamin Herrenschmidte63334e2018-10-15 13:49:52 +1100198static char __prombss prom_cmd_line[COMMAND_LINE_SIZE];
Paul Mackerras9b6b5632005-10-06 12:06:20 +1000199
Benjamin Herrenschmidte63334e2018-10-15 13:49:52 +1100200static unsigned long __prombss prom_memory_limit;
Benjamin Krillcf687872009-07-27 22:02:39 +0000201
Benjamin Herrenschmidte63334e2018-10-15 13:49:52 +1100202static unsigned long __prombss alloc_top;
203static unsigned long __prombss alloc_top_high;
204static unsigned long __prombss alloc_bottom;
205static unsigned long __prombss rmo_top;
206static unsigned long __prombss ram_top;
Paul Mackerras9b6b5632005-10-06 12:06:20 +1000207
Benjamin Herrenschmidte63334e2018-10-15 13:49:52 +1100208static struct mem_map_entry __prombss mem_reserve_map[MEM_RESERVE_MAP_SIZE];
209static int __prombss mem_reserve_cnt;
Paul Mackerras9b6b5632005-10-06 12:06:20 +1000210
Benjamin Herrenschmidte63334e2018-10-15 13:49:52 +1100211static cell_t __prombss regbuf[1024];
Paul Mackerras9b6b5632005-10-06 12:06:20 +1000212
Benjamin Herrenschmidtdbe78b42013-09-25 14:02:50 +1000213static bool rtas_has_query_cpu_stopped;
214
Paul Mackerras9b6b5632005-10-06 12:06:20 +1000215
Paul Mackerras9b6b5632005-10-06 12:06:20 +1000216/*
217 * Error results ... some OF calls will return "-1" on error, some
218 * will return 0, some will return either. To simplify, here are
219 * macros to use with any ihandle or phandle return value to check if
220 * it is valid
221 */
222
223#define PROM_ERROR (-1u)
224#define PHANDLE_VALID(p) ((p) != 0 && (p) != PROM_ERROR)
225#define IHANDLE_VALID(i) ((i) != 0 && (i) != PROM_ERROR)
226
227
228/* This is the one and *ONLY* place where we actually call open
229 * firmware.
230 */
231
232static int __init call_prom(const char *service, int nargs, int nret, ...)
233{
234 int i;
235 struct prom_args args;
236 va_list list;
237
Benjamin Herrenschmidt493adff2013-08-07 02:01:38 +1000238 args.service = cpu_to_be32(ADDR(service));
239 args.nargs = cpu_to_be32(nargs);
240 args.nret = cpu_to_be32(nret);
Paul Mackerras9b6b5632005-10-06 12:06:20 +1000241
242 va_start(list, nret);
243 for (i = 0; i < nargs; i++)
Benjamin Herrenschmidt493adff2013-08-07 02:01:38 +1000244 args.args[i] = cpu_to_be32(va_arg(list, prom_arg_t));
Paul Mackerras9b6b5632005-10-06 12:06:20 +1000245 va_end(list);
246
247 for (i = 0; i < nret; i++)
248 args.args[nargs+i] = 0;
249
Anton Blanchard5827d412012-11-26 17:40:03 +0000250 if (enter_prom(&args, prom_entry) < 0)
Paul Mackerrasc49888202005-10-26 21:52:53 +1000251 return PROM_ERROR;
Paul Mackerras9b6b5632005-10-06 12:06:20 +1000252
Benjamin Herrenschmidt493adff2013-08-07 02:01:38 +1000253 return (nret > 0) ? be32_to_cpu(args.args[nargs]) : 0;
Paul Mackerras9b6b5632005-10-06 12:06:20 +1000254}
255
256static int __init call_prom_ret(const char *service, int nargs, int nret,
257 prom_arg_t *rets, ...)
258{
259 int i;
260 struct prom_args args;
261 va_list list;
262
Benjamin Herrenschmidt493adff2013-08-07 02:01:38 +1000263 args.service = cpu_to_be32(ADDR(service));
264 args.nargs = cpu_to_be32(nargs);
265 args.nret = cpu_to_be32(nret);
Paul Mackerras9b6b5632005-10-06 12:06:20 +1000266
267 va_start(list, rets);
268 for (i = 0; i < nargs; i++)
Benjamin Herrenschmidt493adff2013-08-07 02:01:38 +1000269 args.args[i] = cpu_to_be32(va_arg(list, prom_arg_t));
Paul Mackerras9b6b5632005-10-06 12:06:20 +1000270 va_end(list);
271
272 for (i = 0; i < nret; i++)
Olaf Heringed1189b72005-11-29 14:04:05 +0100273 args.args[nargs+i] = 0;
Paul Mackerras9b6b5632005-10-06 12:06:20 +1000274
Anton Blanchard5827d412012-11-26 17:40:03 +0000275 if (enter_prom(&args, prom_entry) < 0)
Paul Mackerrasc49888202005-10-26 21:52:53 +1000276 return PROM_ERROR;
Paul Mackerras9b6b5632005-10-06 12:06:20 +1000277
278 if (rets != NULL)
279 for (i = 1; i < nret; ++i)
Benjamin Herrenschmidt493adff2013-08-07 02:01:38 +1000280 rets[i-1] = be32_to_cpu(args.args[nargs+i]);
Paul Mackerras9b6b5632005-10-06 12:06:20 +1000281
Benjamin Herrenschmidt493adff2013-08-07 02:01:38 +1000282 return (nret > 0) ? be32_to_cpu(args.args[nargs]) : 0;
Paul Mackerras9b6b5632005-10-06 12:06:20 +1000283}
284
285
Paul Mackerras9b6b5632005-10-06 12:06:20 +1000286static void __init prom_print(const char *msg)
287{
288 const char *p, *q;
Paul Mackerras9b6b5632005-10-06 12:06:20 +1000289
Anton Blanchard5827d412012-11-26 17:40:03 +0000290 if (prom.stdout == 0)
Paul Mackerras9b6b5632005-10-06 12:06:20 +1000291 return;
292
293 for (p = msg; *p != 0; p = q) {
294 for (q = p; *q != 0 && *q != '\n'; ++q)
295 ;
296 if (q > p)
Anton Blanchard5827d412012-11-26 17:40:03 +0000297 call_prom("write", 3, 1, prom.stdout, p, q - p);
Paul Mackerras9b6b5632005-10-06 12:06:20 +1000298 if (*q == 0)
299 break;
300 ++q;
Anton Blanchard5827d412012-11-26 17:40:03 +0000301 call_prom("write", 3, 1, prom.stdout, ADDR("\r\n"), 2);
Paul Mackerras9b6b5632005-10-06 12:06:20 +1000302 }
303}
304
305
Mathieu Malaterre8af1da42018-05-29 21:20:01 +0200306/*
307 * Both prom_print_hex & prom_print_dec takes an unsigned long as input so that
308 * we do not need __udivdi3 or __umoddi3 on 32bits.
309 */
Paul Mackerras9b6b5632005-10-06 12:06:20 +1000310static void __init prom_print_hex(unsigned long val)
311{
312 int i, nibbles = sizeof(val)*2;
313 char buf[sizeof(val)*2+1];
Paul Mackerras9b6b5632005-10-06 12:06:20 +1000314
315 for (i = nibbles-1; i >= 0; i--) {
316 buf[i] = (val & 0xf) + '0';
317 if (buf[i] > '9')
318 buf[i] += ('a'-'0'-10);
319 val >>= 4;
320 }
321 buf[nibbles] = '\0';
Anton Blanchard5827d412012-11-26 17:40:03 +0000322 call_prom("write", 3, 1, prom.stdout, buf, nibbles);
Paul Mackerras9b6b5632005-10-06 12:06:20 +1000323}
324
Michael Neuling2c48a7d2010-07-27 18:26:21 +0000325/* max number of decimal digits in an unsigned long */
326#define UL_DIGITS 21
327static void __init prom_print_dec(unsigned long val)
328{
329 int i, size;
330 char buf[UL_DIGITS+1];
Michael Neuling2c48a7d2010-07-27 18:26:21 +0000331
332 for (i = UL_DIGITS-1; i >= 0; i--) {
333 buf[i] = (val % 10) + '0';
334 val = val/10;
335 if (val == 0)
336 break;
337 }
338 /* shift stuff down */
339 size = UL_DIGITS - i;
Anton Blanchard5827d412012-11-26 17:40:03 +0000340 call_prom("write", 3, 1, prom.stdout, buf+i, size);
Michael Neuling2c48a7d2010-07-27 18:26:21 +0000341}
Paul Mackerras9b6b5632005-10-06 12:06:20 +1000342
Mathieu Malaterreeae5f702018-04-06 22:12:19 +0200343__printf(1, 2)
Paul Mackerras9b6b5632005-10-06 12:06:20 +1000344static void __init prom_printf(const char *format, ...)
345{
346 const char *p, *q, *s;
347 va_list args;
348 unsigned long v;
Benjamin Herrenschmidtaf277142011-04-06 10:51:17 +1000349 long vs;
Mathieu Malaterre8af1da42018-05-29 21:20:01 +0200350 int n = 0;
Paul Mackerras9b6b5632005-10-06 12:06:20 +1000351
352 va_start(args, format);
Paul Mackerras9b6b5632005-10-06 12:06:20 +1000353 for (p = format; *p != 0; p = q) {
354 for (q = p; *q != 0 && *q != '\n' && *q != '%'; ++q)
355 ;
356 if (q > p)
Anton Blanchard5827d412012-11-26 17:40:03 +0000357 call_prom("write", 3, 1, prom.stdout, p, q - p);
Paul Mackerras9b6b5632005-10-06 12:06:20 +1000358 if (*q == 0)
359 break;
360 if (*q == '\n') {
361 ++q;
Anton Blanchard5827d412012-11-26 17:40:03 +0000362 call_prom("write", 3, 1, prom.stdout,
Paul Mackerras9b6b5632005-10-06 12:06:20 +1000363 ADDR("\r\n"), 2);
364 continue;
365 }
366 ++q;
367 if (*q == 0)
368 break;
Mathieu Malaterre8af1da42018-05-29 21:20:01 +0200369 while (*q == 'l') {
370 ++q;
371 ++n;
372 }
Paul Mackerras9b6b5632005-10-06 12:06:20 +1000373 switch (*q) {
374 case 's':
375 ++q;
376 s = va_arg(args, const char *);
377 prom_print(s);
378 break;
379 case 'x':
380 ++q;
Mathieu Malaterre8af1da42018-05-29 21:20:01 +0200381 switch (n) {
382 case 0:
383 v = va_arg(args, unsigned int);
384 break;
385 case 1:
386 v = va_arg(args, unsigned long);
387 break;
388 case 2:
389 default:
390 v = va_arg(args, unsigned long long);
391 break;
392 }
Paul Mackerras9b6b5632005-10-06 12:06:20 +1000393 prom_print_hex(v);
394 break;
Mathieu Malaterre8af1da42018-05-29 21:20:01 +0200395 case 'u':
396 ++q;
397 switch (n) {
398 case 0:
399 v = va_arg(args, unsigned int);
400 break;
401 case 1:
402 v = va_arg(args, unsigned long);
403 break;
404 case 2:
405 default:
406 v = va_arg(args, unsigned long long);
407 break;
408 }
409 prom_print_dec(v);
410 break;
Benjamin Herrenschmidtaf277142011-04-06 10:51:17 +1000411 case 'd':
412 ++q;
Mathieu Malaterre8af1da42018-05-29 21:20:01 +0200413 switch (n) {
414 case 0:
415 vs = va_arg(args, int);
416 break;
417 case 1:
418 vs = va_arg(args, long);
419 break;
420 case 2:
421 default:
422 vs = va_arg(args, long long);
423 break;
424 }
Benjamin Herrenschmidtaf277142011-04-06 10:51:17 +1000425 if (vs < 0) {
Anton Blanchard5827d412012-11-26 17:40:03 +0000426 prom_print("-");
Benjamin Herrenschmidtaf277142011-04-06 10:51:17 +1000427 vs = -vs;
428 }
429 prom_print_dec(vs);
430 break;
Paul Mackerras9b6b5632005-10-06 12:06:20 +1000431 }
432 }
Daniel Axtens1b855e12015-12-17 19:41:00 +1100433 va_end(args);
Paul Mackerras9b6b5632005-10-06 12:06:20 +1000434}
435
436
Paul Mackerrasa575b802005-10-23 17:23:21 +1000437static unsigned int __init prom_claim(unsigned long virt, unsigned long size,
438 unsigned long align)
439{
Paul Mackerrasa575b802005-10-23 17:23:21 +1000440
Paul Mackerrasa23414b2005-11-10 12:00:55 +1100441 if (align == 0 && (OF_WORKAROUNDS & OF_WA_CLAIM)) {
442 /*
443 * Old OF requires we claim physical and virtual separately
444 * and then map explicitly (assuming virtual mode)
445 */
446 int ret;
447 prom_arg_t result;
448
449 ret = call_prom_ret("call-method", 5, 2, &result,
Anton Blanchard5827d412012-11-26 17:40:03 +0000450 ADDR("claim"), prom.memory,
Paul Mackerrasa23414b2005-11-10 12:00:55 +1100451 align, size, virt);
452 if (ret != 0 || result == -1)
453 return -1;
454 ret = call_prom_ret("call-method", 5, 2, &result,
Anton Blanchard5827d412012-11-26 17:40:03 +0000455 ADDR("claim"), prom.mmumap,
Paul Mackerrasa23414b2005-11-10 12:00:55 +1100456 align, size, virt);
457 if (ret != 0) {
458 call_prom("call-method", 4, 1, ADDR("release"),
Anton Blanchard5827d412012-11-26 17:40:03 +0000459 prom.memory, size, virt);
Paul Mackerrasa23414b2005-11-10 12:00:55 +1100460 return -1;
461 }
462 /* the 0x12 is M (coherence) + PP == read/write */
Paul Mackerrasa575b802005-10-23 17:23:21 +1000463 call_prom("call-method", 6, 1,
Anton Blanchard5827d412012-11-26 17:40:03 +0000464 ADDR("map"), prom.mmumap, 0x12, size, virt, virt);
Paul Mackerrasa23414b2005-11-10 12:00:55 +1100465 return virt;
466 }
467 return call_prom("claim", 3, 1, (prom_arg_t)virt, (prom_arg_t)size,
468 (prom_arg_t)align);
Paul Mackerrasa575b802005-10-23 17:23:21 +1000469}
470
Paul Mackerras9b6b5632005-10-06 12:06:20 +1000471static void __init __attribute__((noreturn)) prom_panic(const char *reason)
472{
Paul Mackerras9b6b5632005-10-06 12:06:20 +1000473 prom_print(reason);
Olaf Heringadd60ef2006-03-23 22:03:57 +0100474 /* Do not call exit because it clears the screen on pmac
475 * it also causes some sort of double-fault on early pmacs */
Anton Blanchard5827d412012-11-26 17:40:03 +0000476 if (of_platform == PLATFORM_POWERMAC)
Olaf Heringadd60ef2006-03-23 22:03:57 +0100477 asm("trap\n");
478
Stephen Rothwell1d9a4732012-03-21 18:23:27 +0000479 /* ToDo: should put up an SRC here on pSeries */
Paul Mackerras9b6b5632005-10-06 12:06:20 +1000480 call_prom("exit", 0, 0);
481
482 for (;;) /* should never get here */
483 ;
484}
485
486
487static int __init prom_next_node(phandle *nodep)
488{
489 phandle node;
490
491 if ((node = *nodep) != 0
492 && (*nodep = call_prom("child", 1, 1, node)) != 0)
493 return 1;
494 if ((*nodep = call_prom("peer", 1, 1, node)) != 0)
495 return 1;
496 for (;;) {
497 if ((node = call_prom("parent", 1, 1, node)) == 0)
498 return 0;
499 if ((*nodep = call_prom("peer", 1, 1, node)) != 0)
500 return 1;
501 }
502}
503
Tobias Klauser60d862e2016-11-17 17:20:24 +0100504static inline int prom_getprop(phandle node, const char *pname,
Paul Mackerras9b6b5632005-10-06 12:06:20 +1000505 void *value, size_t valuelen)
506{
507 return call_prom("getprop", 4, 1, node, ADDR(pname),
508 (u32)(unsigned long) value, (u32) valuelen);
509}
510
Tobias Klauser60d862e2016-11-17 17:20:24 +0100511static inline int prom_getproplen(phandle node, const char *pname)
Paul Mackerras9b6b5632005-10-06 12:06:20 +1000512{
513 return call_prom("getproplen", 2, 1, node, ADDR(pname));
514}
515
Paul Mackerrasa23414b2005-11-10 12:00:55 +1100516static void add_string(char **str, const char *q)
Paul Mackerras9b6b5632005-10-06 12:06:20 +1000517{
Paul Mackerrasa23414b2005-11-10 12:00:55 +1100518 char *p = *str;
519
520 while (*q)
521 *p++ = *q++;
522 *p++ = ' ';
523 *str = p;
524}
525
526static char *tohex(unsigned int x)
527{
528 static char digits[] = "0123456789abcdef";
529 static char result[9];
530 int i;
531
532 result[8] = 0;
533 i = 8;
534 do {
535 --i;
536 result[i] = digits[x & 0xf];
537 x >>= 4;
538 } while (x != 0 && i > 0);
539 return &result[i];
540}
541
542static int __init prom_setprop(phandle node, const char *nodename,
543 const char *pname, void *value, size_t valuelen)
544{
545 char cmd[256], *p;
546
547 if (!(OF_WORKAROUNDS & OF_WA_LONGTRAIL))
548 return call_prom("setprop", 4, 1, node, ADDR(pname),
549 (u32)(unsigned long) value, (u32) valuelen);
550
551 /* gah... setprop doesn't work on longtrail, have to use interpret */
552 p = cmd;
553 add_string(&p, "dev");
554 add_string(&p, nodename);
555 add_string(&p, tohex((u32)(unsigned long) value));
556 add_string(&p, tohex(valuelen));
557 add_string(&p, tohex(ADDR(pname)));
Anton Blanchard5827d412012-11-26 17:40:03 +0000558 add_string(&p, tohex(strlen(pname)));
Paul Mackerrasa23414b2005-11-10 12:00:55 +1100559 add_string(&p, "property");
560 *p = 0;
561 return call_prom("interpret", 1, 1, (u32)(unsigned long) cmd);
Paul Mackerras9b6b5632005-10-06 12:06:20 +1000562}
563
Anton Blanchard5827d412012-11-26 17:40:03 +0000564/* We can't use the standard versions because of relocation headaches. */
Benjamin Krillcf687872009-07-27 22:02:39 +0000565#define isxdigit(c) (('0' <= (c) && (c) <= '9') \
566 || ('a' <= (c) && (c) <= 'f') \
567 || ('A' <= (c) && (c) <= 'F'))
568
569#define isdigit(c) ('0' <= (c) && (c) <= '9')
570#define islower(c) ('a' <= (c) && (c) <= 'z')
571#define toupper(c) (islower(c) ? ((c) - 'a' + 'A') : (c))
572
Benjamin Herrenschmidt493adff2013-08-07 02:01:38 +1000573static unsigned long prom_strtoul(const char *cp, const char **endp)
Benjamin Krillcf687872009-07-27 22:02:39 +0000574{
575 unsigned long result = 0, base = 10, value;
576
577 if (*cp == '0') {
578 base = 8;
579 cp++;
580 if (toupper(*cp) == 'X') {
581 cp++;
582 base = 16;
583 }
584 }
585
586 while (isxdigit(*cp) &&
587 (value = isdigit(*cp) ? *cp - '0' : toupper(*cp) - 'A' + 10) < base) {
588 result = result * base + value;
589 cp++;
590 }
591
592 if (endp)
593 *endp = cp;
594
595 return result;
596}
597
Benjamin Herrenschmidt493adff2013-08-07 02:01:38 +1000598static unsigned long prom_memparse(const char *ptr, const char **retptr)
Benjamin Krillcf687872009-07-27 22:02:39 +0000599{
600 unsigned long ret = prom_strtoul(ptr, retptr);
601 int shift = 0;
602
603 /*
604 * We can't use a switch here because GCC *may* generate a
605 * jump table which won't work, because we're not running at
606 * the address we're linked at.
607 */
608 if ('G' == **retptr || 'g' == **retptr)
609 shift = 30;
610
611 if ('M' == **retptr || 'm' == **retptr)
612 shift = 20;
613
614 if ('K' == **retptr || 'k' == **retptr)
615 shift = 10;
616
617 if (shift) {
618 ret <<= shift;
619 (*retptr)++;
620 }
621
622 return ret;
623}
624
Paul Mackerras9b6b5632005-10-06 12:06:20 +1000625/*
626 * Early parsing of the command line passed to the kernel, used for
627 * "mem=x" and the options that affect the iommu
628 */
629static void __init early_cmdline_parse(void)
630{
Benjamin Herrenschmidtcc5d0182005-12-13 18:01:21 +1100631 const char *opt;
Benjamin Krillcf687872009-07-27 22:02:39 +0000632
Benjamin Herrenschmidtcc5d0182005-12-13 18:01:21 +1100633 char *p;
Mathieu Malaterreeab00a22018-04-04 22:08:35 +0200634 int l __maybe_unused = 0;
Paul Mackerras9b6b5632005-10-06 12:06:20 +1000635
Anton Blanchard5827d412012-11-26 17:40:03 +0000636 prom_cmd_line[0] = 0;
637 p = prom_cmd_line;
638 if ((long)prom.chosen > 0)
639 l = prom_getprop(prom.chosen, "bootargs", p, COMMAND_LINE_SIZE-1);
Paul Mackerras9b6b5632005-10-06 12:06:20 +1000640#ifdef CONFIG_CMDLINE
Amos Waterland0e4aa9c2006-06-12 23:45:02 -0400641 if (l <= 0 || p[0] == '\0') /* dbl check */
Anton Blanchard5827d412012-11-26 17:40:03 +0000642 strlcpy(prom_cmd_line,
643 CONFIG_CMDLINE, sizeof(prom_cmd_line));
Paul Mackerras9b6b5632005-10-06 12:06:20 +1000644#endif /* CONFIG_CMDLINE */
Anton Blanchard5827d412012-11-26 17:40:03 +0000645 prom_printf("command line: %s\n", prom_cmd_line);
Paul Mackerras9b6b5632005-10-06 12:06:20 +1000646
647#ifdef CONFIG_PPC64
Anton Blanchard5827d412012-11-26 17:40:03 +0000648 opt = strstr(prom_cmd_line, "iommu=");
Paul Mackerras9b6b5632005-10-06 12:06:20 +1000649 if (opt) {
650 prom_printf("iommu opt is: %s\n", opt);
651 opt += 6;
652 while (*opt && *opt == ' ')
653 opt++;
Anton Blanchard5827d412012-11-26 17:40:03 +0000654 if (!strncmp(opt, "off", 3))
655 prom_iommu_off = 1;
656 else if (!strncmp(opt, "force", 5))
657 prom_iommu_force_on = 1;
Paul Mackerras9b6b5632005-10-06 12:06:20 +1000658 }
659#endif
Anton Blanchard5827d412012-11-26 17:40:03 +0000660 opt = strstr(prom_cmd_line, "mem=");
Benjamin Krillcf687872009-07-27 22:02:39 +0000661 if (opt) {
662 opt += 4;
Anton Blanchard5827d412012-11-26 17:40:03 +0000663 prom_memory_limit = prom_memparse(opt, (const char **)&opt);
Benjamin Krillcf687872009-07-27 22:02:39 +0000664#ifdef CONFIG_PPC64
665 /* Align to 16 MB == size of ppc64 large page */
Anton Blanchard5827d412012-11-26 17:40:03 +0000666 prom_memory_limit = ALIGN(prom_memory_limit, 0x1000000);
Benjamin Krillcf687872009-07-27 22:02:39 +0000667#endif
668 }
Suraj Jitindar Singh014d02c2017-02-28 17:03:48 +1100669
Benjamin Herrenschmidtc8860872018-10-15 13:49:54 +1100670#ifdef CONFIG_PPC_PSERIES
671 prom_radix_disable = !IS_ENABLED(CONFIG_PPC_RADIX_MMU_DEFAULT);
Suraj Jitindar Singh014d02c2017-02-28 17:03:48 +1100672 opt = strstr(prom_cmd_line, "disable_radix");
673 if (opt) {
Aneesh Kumar K.V7a22d632018-03-30 17:39:02 +0530674 opt += 13;
675 if (*opt && *opt == '=') {
676 bool val;
677
678 if (kstrtobool(++opt, &val))
679 prom_radix_disable = false;
680 else
681 prom_radix_disable = val;
682 } else
683 prom_radix_disable = true;
Suraj Jitindar Singh014d02c2017-02-28 17:03:48 +1100684 }
Aneesh Kumar K.V7a22d632018-03-30 17:39:02 +0530685 if (prom_radix_disable)
686 prom_debug("Radix disabled from cmdline\n");
Benjamin Herrenschmidtc8860872018-10-15 13:49:54 +1100687#endif /* CONFIG_PPC_PSERIES */
Paul Mackerras9b6b5632005-10-06 12:06:20 +1000688}
689
Benjamin Herrenschmidt11fdb302018-10-15 13:49:53 +1100690#ifdef CONFIG_PPC_PSERIES
Paul Mackerras9b6b5632005-10-06 12:06:20 +1000691/*
Nathan Fontenot530b5e12013-04-24 05:53:10 +0000692 * The architecture vector has an array of PVR mask/value pairs,
693 * followed by # option vectors - 1, followed by the option vectors.
694 *
695 * See prom.h for the definition of the bits specified in the
696 * architecture vector.
Paul Mackerrasf709bfa2006-04-28 16:28:35 +1000697 */
Paul Mackerrasf709bfa2006-04-28 16:28:35 +1000698
Michael Ellermane8a4fd02014-08-29 17:01:43 +1000699/* Firmware expects the value to be n - 1, where n is the # of vectors */
700#define NUM_VECTORS(n) ((n) - 1)
701
702/*
703 * Firmware expects 1 + n - 2, where n is the length of the option vector in
704 * bytes. The 1 accounts for the length byte itself, the - 2 .. ?
705 */
706#define VECTOR_LENGTH(n) (1 + (n) - 2)
707
Michael Ellermand03d1d62016-11-18 23:15:41 +1100708struct option_vector1 {
709 u8 byte1;
710 u8 arch_versions;
Paul Mackerrascc3d2942017-01-30 21:21:36 +1100711 u8 arch_versions3;
Michael Ellermand03d1d62016-11-18 23:15:41 +1100712} __packed;
713
714struct option_vector2 {
715 u8 byte1;
716 __be16 reserved;
717 __be32 real_base;
718 __be32 real_size;
719 __be32 virt_base;
720 __be32 virt_size;
721 __be32 load_base;
722 __be32 min_rma;
723 __be32 min_load;
724 u8 min_rma_percent;
725 u8 max_pft_size;
726} __packed;
727
728struct option_vector3 {
729 u8 byte1;
730 u8 byte2;
731} __packed;
732
733struct option_vector4 {
734 u8 byte1;
735 u8 min_vp_cap;
736} __packed;
737
738struct option_vector5 {
739 u8 byte1;
740 u8 byte2;
741 u8 byte3;
742 u8 cmo;
743 u8 associativity;
744 u8 bin_opts;
745 u8 micro_checkpoint;
746 u8 reserved0;
747 __be32 max_cpus;
748 __be16 papr_level;
749 __be16 reserved1;
750 u8 platform_facilities;
751 u8 reserved2;
752 __be16 reserved3;
753 u8 subprocessors;
Paul Mackerrascc3d2942017-01-30 21:21:36 +1100754 u8 byte22;
755 u8 intarch;
756 u8 mmu;
Suraj Jitindar Singh014d02c2017-02-28 17:03:48 +1100757 u8 hash_ext;
758 u8 radix_ext;
Michael Ellermand03d1d62016-11-18 23:15:41 +1100759} __packed;
760
761struct option_vector6 {
762 u8 reserved;
763 u8 secondary_pteg;
764 u8 os_name;
765} __packed;
766
Michael Ellerman76ffb572016-11-18 23:15:42 +1100767struct ibm_arch_vec {
Paul Mackerrascc3d2942017-01-30 21:21:36 +1100768 struct { u32 mask, val; } pvrs[12];
Michael Ellerman76ffb572016-11-18 23:15:42 +1100769
770 u8 num_vectors;
771
772 u8 vec1_len;
773 struct option_vector1 vec1;
774
775 u8 vec2_len;
776 struct option_vector2 vec2;
777
778 u8 vec3_len;
779 struct option_vector3 vec3;
780
781 u8 vec4_len;
782 struct option_vector4 vec4;
783
784 u8 vec5_len;
785 struct option_vector5 vec5;
786
787 u8 vec6_len;
788 struct option_vector6 vec6;
789} __packed;
790
Benjamin Herrenschmidta614f522018-10-15 13:49:55 +1100791static const struct ibm_arch_vec ibm_architecture_vec_template = {
Michael Ellerman76ffb572016-11-18 23:15:42 +1100792 .pvrs = {
793 {
794 .mask = cpu_to_be32(0xfffe0000), /* POWER5/POWER5+ */
795 .val = cpu_to_be32(0x003a0000),
796 },
797 {
798 .mask = cpu_to_be32(0xffff0000), /* POWER6 */
799 .val = cpu_to_be32(0x003e0000),
800 },
801 {
802 .mask = cpu_to_be32(0xffff0000), /* POWER7 */
803 .val = cpu_to_be32(0x003f0000),
804 },
805 {
806 .mask = cpu_to_be32(0xffff0000), /* POWER8E */
807 .val = cpu_to_be32(0x004b0000),
808 },
809 {
810 .mask = cpu_to_be32(0xffff0000), /* POWER8NVL */
811 .val = cpu_to_be32(0x004c0000),
812 },
813 {
814 .mask = cpu_to_be32(0xffff0000), /* POWER8 */
815 .val = cpu_to_be32(0x004d0000),
816 },
817 {
Paul Mackerrascc3d2942017-01-30 21:21:36 +1100818 .mask = cpu_to_be32(0xffff0000), /* POWER9 */
819 .val = cpu_to_be32(0x004e0000),
820 },
821 {
822 .mask = cpu_to_be32(0xffffffff), /* all 3.00-compliant */
823 .val = cpu_to_be32(0x0f000005),
824 },
825 {
Michael Ellerman76ffb572016-11-18 23:15:42 +1100826 .mask = cpu_to_be32(0xffffffff), /* all 2.07-compliant */
827 .val = cpu_to_be32(0x0f000004),
828 },
829 {
830 .mask = cpu_to_be32(0xffffffff), /* all 2.06-compliant */
831 .val = cpu_to_be32(0x0f000003),
832 },
833 {
834 .mask = cpu_to_be32(0xffffffff), /* all 2.05-compliant */
835 .val = cpu_to_be32(0x0f000002),
836 },
837 {
838 .mask = cpu_to_be32(0xfffffffe), /* all 2.04-compliant and earlier */
839 .val = cpu_to_be32(0x0f000001),
840 },
841 },
842
843 .num_vectors = NUM_VECTORS(6),
844
845 .vec1_len = VECTOR_LENGTH(sizeof(struct option_vector1)),
846 .vec1 = {
847 .byte1 = 0,
848 .arch_versions = OV1_PPC_2_00 | OV1_PPC_2_01 | OV1_PPC_2_02 | OV1_PPC_2_03 |
849 OV1_PPC_2_04 | OV1_PPC_2_05 | OV1_PPC_2_06 | OV1_PPC_2_07,
Paul Mackerrascc3d2942017-01-30 21:21:36 +1100850 .arch_versions3 = OV1_PPC_3_00,
Michael Ellerman76ffb572016-11-18 23:15:42 +1100851 },
852
853 .vec2_len = VECTOR_LENGTH(sizeof(struct option_vector2)),
854 /* option vector 2: Open Firmware options supported */
855 .vec2 = {
856 .byte1 = OV2_REAL_MODE,
857 .reserved = 0,
858 .real_base = cpu_to_be32(0xffffffff),
859 .real_size = cpu_to_be32(0xffffffff),
860 .virt_base = cpu_to_be32(0xffffffff),
861 .virt_size = cpu_to_be32(0xffffffff),
862 .load_base = cpu_to_be32(0xffffffff),
Sukadev Bhattiprolu687da8f2017-03-27 19:43:14 -0400863 .min_rma = cpu_to_be32(512), /* 512MB min RMA */
Michael Ellerman76ffb572016-11-18 23:15:42 +1100864 .min_load = cpu_to_be32(0xffffffff), /* full client load */
865 .min_rma_percent = 0, /* min RMA percentage of total RAM */
866 .max_pft_size = 48, /* max log_2(hash table size) */
867 },
868
869 .vec3_len = VECTOR_LENGTH(sizeof(struct option_vector3)),
870 /* option vector 3: processor options supported */
871 .vec3 = {
872 .byte1 = 0, /* don't ignore, don't halt */
873 .byte2 = OV3_FP | OV3_VMX | OV3_DFP,
874 },
875
876 .vec4_len = VECTOR_LENGTH(sizeof(struct option_vector4)),
877 /* option vector 4: IBM PAPR implementation */
878 .vec4 = {
879 .byte1 = 0, /* don't halt */
880 .min_vp_cap = OV4_MIN_ENT_CAP, /* minimum VP entitled capacity */
881 },
882
883 .vec5_len = VECTOR_LENGTH(sizeof(struct option_vector5)),
884 /* option vector 5: PAPR/OF options */
885 .vec5 = {
886 .byte1 = 0, /* don't ignore, don't halt */
887 .byte2 = OV5_FEAT(OV5_LPAR) | OV5_FEAT(OV5_SPLPAR) | OV5_FEAT(OV5_LARGE_PAGES) |
888 OV5_FEAT(OV5_DRCONF_MEMORY) | OV5_FEAT(OV5_DONATE_DEDICATE_CPU) |
889#ifdef CONFIG_PCI_MSI
890 /* PCIe/MSI support. Without MSI full PCIe is not supported */
891 OV5_FEAT(OV5_MSI),
892#else
893 0,
894#endif
895 .byte3 = 0,
896 .cmo =
897#ifdef CONFIG_PPC_SMLPAR
898 OV5_FEAT(OV5_CMO) | OV5_FEAT(OV5_XCMO),
899#else
900 0,
901#endif
902 .associativity = OV5_FEAT(OV5_TYPE1_AFFINITY) | OV5_FEAT(OV5_PRRN),
Michael Roth3dbbaf22017-02-20 19:12:18 -0600903 .bin_opts = OV5_FEAT(OV5_RESIZE_HPT) | OV5_FEAT(OV5_HP_EVT),
Michael Ellerman76ffb572016-11-18 23:15:42 +1100904 .micro_checkpoint = 0,
905 .reserved0 = 0,
906 .max_cpus = cpu_to_be32(NR_CPUS), /* number of cores supported */
907 .papr_level = 0,
908 .reserved1 = 0,
909 .platform_facilities = OV5_FEAT(OV5_PFO_HW_RNG) | OV5_FEAT(OV5_PFO_HW_ENCR) | OV5_FEAT(OV5_PFO_HW_842),
910 .reserved2 = 0,
911 .reserved3 = 0,
912 .subprocessors = 1,
Nathan Fontenot0c38ed62017-12-01 10:48:03 -0600913 .byte22 = OV5_FEAT(OV5_DRMEM_V2),
Paul Mackerrascc3d2942017-01-30 21:21:36 +1100914 .intarch = 0,
Suraj Jitindar Singh014d02c2017-02-28 17:03:48 +1100915 .mmu = 0,
916 .hash_ext = 0,
917 .radix_ext = 0,
Michael Ellerman76ffb572016-11-18 23:15:42 +1100918 },
919
920 /* option vector 6: IBM PAPR hints */
921 .vec6_len = VECTOR_LENGTH(sizeof(struct option_vector6)),
922 .vec6 = {
923 .reserved = 0,
924 .secondary_pteg = 0,
925 .os_name = OV6_LINUX,
926 },
927};
928
Benjamin Herrenschmidta614f522018-10-15 13:49:55 +1100929static struct ibm_arch_vec __prombss ibm_architecture_vec ____cacheline_aligned;
930
Benjamin Herrenschmidt493adff2013-08-07 02:01:38 +1000931/* Old method - ELF header with PT_NOTE sections only works on BE */
932#ifdef __BIG_ENDIAN__
Benjamin Herrenschmidt30c69ca2018-05-31 14:33:40 +1000933static const struct fake_elf {
Paul Mackerras9b6b5632005-10-06 12:06:20 +1000934 Elf32_Ehdr elfhdr;
935 Elf32_Phdr phdr[2];
936 struct chrpnote {
937 u32 namesz;
938 u32 descsz;
939 u32 type;
940 char name[8]; /* "PowerPC" */
941 struct chrpdesc {
942 u32 real_mode;
943 u32 real_base;
944 u32 real_size;
945 u32 virt_base;
946 u32 virt_size;
947 u32 load_base;
948 } chrpdesc;
949 } chrpnote;
950 struct rpanote {
951 u32 namesz;
952 u32 descsz;
953 u32 type;
954 char name[24]; /* "IBM,RPA-Client-Config" */
955 struct rpadesc {
956 u32 lpar_affinity;
957 u32 min_rmo_size;
958 u32 min_rmo_percent;
959 u32 max_pft_size;
960 u32 splpar;
961 u32 min_load;
962 u32 new_mem_def;
963 u32 ignore_me;
964 } rpadesc;
965 } rpanote;
Paul Mackerras5663a122008-10-31 22:27:17 +1100966} fake_elf = {
Paul Mackerras9b6b5632005-10-06 12:06:20 +1000967 .elfhdr = {
968 .e_ident = { 0x7f, 'E', 'L', 'F',
969 ELFCLASS32, ELFDATA2MSB, EV_CURRENT },
970 .e_type = ET_EXEC, /* yeah right */
971 .e_machine = EM_PPC,
972 .e_version = EV_CURRENT,
973 .e_phoff = offsetof(struct fake_elf, phdr),
974 .e_phentsize = sizeof(Elf32_Phdr),
975 .e_phnum = 2
976 },
977 .phdr = {
978 [0] = {
979 .p_type = PT_NOTE,
980 .p_offset = offsetof(struct fake_elf, chrpnote),
981 .p_filesz = sizeof(struct chrpnote)
982 }, [1] = {
983 .p_type = PT_NOTE,
984 .p_offset = offsetof(struct fake_elf, rpanote),
985 .p_filesz = sizeof(struct rpanote)
986 }
987 },
988 .chrpnote = {
989 .namesz = sizeof("PowerPC"),
990 .descsz = sizeof(struct chrpdesc),
991 .type = 0x1275,
992 .name = "PowerPC",
993 .chrpdesc = {
994 .real_mode = ~0U, /* ~0 means "don't care" */
995 .real_base = ~0U,
996 .real_size = ~0U,
997 .virt_base = ~0U,
998 .virt_size = ~0U,
999 .load_base = ~0U
1000 },
1001 },
1002 .rpanote = {
1003 .namesz = sizeof("IBM,RPA-Client-Config"),
1004 .descsz = sizeof(struct rpadesc),
1005 .type = 0x12759999,
1006 .name = "IBM,RPA-Client-Config",
1007 .rpadesc = {
Paul Mackerras5663a122008-10-31 22:27:17 +11001008 .lpar_affinity = 0,
1009 .min_rmo_size = 64, /* in megabytes */
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001010 .min_rmo_percent = 0,
Paul Mackerras5663a122008-10-31 22:27:17 +11001011 .max_pft_size = 48, /* 2^48 bytes max PFT size */
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001012 .splpar = 1,
1013 .min_load = ~0U,
Paul Mackerras5663a122008-10-31 22:27:17 +11001014 .new_mem_def = 0
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001015 }
1016 }
1017};
Benjamin Herrenschmidt493adff2013-08-07 02:01:38 +10001018#endif /* __BIG_ENDIAN__ */
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001019
Benjamin Herrenschmidtefec9592010-02-04 14:33:54 +11001020static int __init prom_count_smt_threads(void)
1021{
1022 phandle node;
1023 char type[64];
1024 unsigned int plen;
1025
1026 /* Pick up th first CPU node we can find */
1027 for (node = 0; prom_next_node(&node); ) {
1028 type[0] = 0;
1029 prom_getprop(node, "device_type", type, sizeof(type));
1030
Anton Blanchard5827d412012-11-26 17:40:03 +00001031 if (strcmp(type, "cpu"))
Benjamin Herrenschmidtefec9592010-02-04 14:33:54 +11001032 continue;
1033 /*
1034 * There is an entry for each smt thread, each entry being
1035 * 4 bytes long. All cpus should have the same number of
1036 * smt threads, so return after finding the first.
1037 */
1038 plen = prom_getproplen(node, "ibm,ppc-interrupt-server#s");
1039 if (plen == PROM_ERROR)
1040 break;
1041 plen >>= 2;
Michael Neuling2c48a7d2010-07-27 18:26:21 +00001042 prom_debug("Found %lu smt threads per core\n", (unsigned long)plen);
Benjamin Herrenschmidtefec9592010-02-04 14:33:54 +11001043
1044 /* Sanity check */
1045 if (plen < 1 || plen > 64) {
Michael Neuling2c48a7d2010-07-27 18:26:21 +00001046 prom_printf("Threads per core %lu out of bounds, assuming 1\n",
Benjamin Herrenschmidtefec9592010-02-04 14:33:54 +11001047 (unsigned long)plen);
1048 return 1;
1049 }
1050 return plen;
1051 }
1052 prom_debug("No threads found, assuming 1 per core\n");
1053
1054 return 1;
1055
1056}
1057
Suraj Jitindar Singh014d02c2017-02-28 17:03:48 +11001058static void __init prom_parse_mmu_model(u8 val,
1059 struct platform_support *support)
1060{
1061 switch (val) {
1062 case OV5_FEAT(OV5_MMU_DYNAMIC):
1063 case OV5_FEAT(OV5_MMU_EITHER): /* Either Available */
1064 prom_debug("MMU - either supported\n");
1065 support->radix_mmu = !prom_radix_disable;
1066 support->hash_mmu = true;
1067 break;
1068 case OV5_FEAT(OV5_MMU_RADIX): /* Only Radix */
1069 prom_debug("MMU - radix only\n");
1070 if (prom_radix_disable) {
1071 /*
1072 * If we __have__ to do radix, we're better off ignoring
1073 * the command line rather than not booting.
1074 */
1075 prom_printf("WARNING: Ignoring cmdline option disable_radix\n");
1076 }
1077 support->radix_mmu = true;
1078 break;
1079 case OV5_FEAT(OV5_MMU_HASH):
1080 prom_debug("MMU - hash only\n");
1081 support->hash_mmu = true;
1082 break;
1083 default:
1084 prom_debug("Unknown mmu support option: 0x%x\n", val);
1085 break;
1086 }
1087}
1088
Cédric Le Goaterac5e5a52017-08-30 21:46:16 +02001089static void __init prom_parse_xive_model(u8 val,
1090 struct platform_support *support)
1091{
1092 switch (val) {
1093 case OV5_FEAT(OV5_XIVE_EITHER): /* Either Available */
1094 prom_debug("XIVE - either mode supported\n");
1095 support->xive = true;
1096 break;
1097 case OV5_FEAT(OV5_XIVE_EXPLOIT): /* Only Exploitation mode */
1098 prom_debug("XIVE - exploitation mode supported\n");
1099 support->xive = true;
1100 break;
1101 case OV5_FEAT(OV5_XIVE_LEGACY): /* Only Legacy mode */
1102 prom_debug("XIVE - legacy mode supported\n");
1103 break;
1104 default:
1105 prom_debug("Unknown xive support option: 0x%x\n", val);
1106 break;
1107 }
1108}
1109
Suraj Jitindar Singh014d02c2017-02-28 17:03:48 +11001110static void __init prom_parse_platform_support(u8 index, u8 val,
1111 struct platform_support *support)
1112{
1113 switch (index) {
1114 case OV5_INDX(OV5_MMU_SUPPORT): /* MMU Model */
1115 prom_parse_mmu_model(val & OV5_FEAT(OV5_MMU_SUPPORT), support);
1116 break;
1117 case OV5_INDX(OV5_RADIX_GTSE): /* Radix Extensions */
1118 if (val & OV5_FEAT(OV5_RADIX_GTSE)) {
1119 prom_debug("Radix - GTSE supported\n");
1120 support->radix_gtse = true;
1121 }
1122 break;
Cédric Le Goaterac5e5a52017-08-30 21:46:16 +02001123 case OV5_INDX(OV5_XIVE_SUPPORT): /* Interrupt mode */
1124 prom_parse_xive_model(val & OV5_FEAT(OV5_XIVE_SUPPORT),
1125 support);
1126 break;
Suraj Jitindar Singh014d02c2017-02-28 17:03:48 +11001127 }
1128}
1129
1130static void __init prom_check_platform_support(void)
1131{
1132 struct platform_support supported = {
1133 .hash_mmu = false,
1134 .radix_mmu = false,
Cédric Le Goaterac5e5a52017-08-30 21:46:16 +02001135 .radix_gtse = false,
1136 .xive = false
Suraj Jitindar Singh014d02c2017-02-28 17:03:48 +11001137 };
1138 int prop_len = prom_getproplen(prom.chosen,
1139 "ibm,arch-vec-5-platform-support");
Benjamin Herrenschmidta614f522018-10-15 13:49:55 +11001140
1141 /* First copy the architecture vec template */
1142 ibm_architecture_vec = ibm_architecture_vec_template;
1143
Suraj Jitindar Singh014d02c2017-02-28 17:03:48 +11001144 if (prop_len > 1) {
1145 int i;
Suraj Jitindar Singhab912392018-09-05 12:09:50 +10001146 u8 vec[8];
Suraj Jitindar Singh014d02c2017-02-28 17:03:48 +11001147 prom_debug("Found ibm,arch-vec-5-platform-support, len: %d\n",
1148 prop_len);
Suraj Jitindar Singhab912392018-09-05 12:09:50 +10001149 if (prop_len > sizeof(vec))
1150 prom_printf("WARNING: ibm,arch-vec-5-platform-support longer than expected (len: %d)\n",
1151 prop_len);
Suraj Jitindar Singh014d02c2017-02-28 17:03:48 +11001152 prom_getprop(prom.chosen, "ibm,arch-vec-5-platform-support",
1153 &vec, sizeof(vec));
Suraj Jitindar Singhab912392018-09-05 12:09:50 +10001154 for (i = 0; i < sizeof(vec); i += 2) {
Suraj Jitindar Singh014d02c2017-02-28 17:03:48 +11001155 prom_debug("%d: index = 0x%x val = 0x%x\n", i / 2
1156 , vec[i]
1157 , vec[i + 1]);
1158 prom_parse_platform_support(vec[i], vec[i + 1],
1159 &supported);
1160 }
1161 }
1162
Alexey Kardashevskiy79b46862018-01-09 16:45:20 +11001163 if (supported.radix_mmu && supported.radix_gtse &&
1164 IS_ENABLED(CONFIG_PPC_RADIX_MMU)) {
Suraj Jitindar Singh014d02c2017-02-28 17:03:48 +11001165 /* Radix preferred - but we require GTSE for now */
1166 prom_debug("Asking for radix with GTSE\n");
1167 ibm_architecture_vec.vec5.mmu = OV5_FEAT(OV5_MMU_RADIX);
1168 ibm_architecture_vec.vec5.radix_ext = OV5_FEAT(OV5_RADIX_GTSE);
1169 } else if (supported.hash_mmu) {
1170 /* Default to hash mmu (if we can) */
1171 prom_debug("Asking for hash\n");
1172 ibm_architecture_vec.vec5.mmu = OV5_FEAT(OV5_MMU_HASH);
1173 } else {
1174 /* We're probably on a legacy hypervisor */
1175 prom_debug("Assuming legacy hash support\n");
1176 }
Cédric Le Goaterac5e5a52017-08-30 21:46:16 +02001177
1178 if (supported.xive) {
1179 prom_debug("Asking for XIVE\n");
1180 ibm_architecture_vec.vec5.intarch = OV5_FEAT(OV5_XIVE_EXPLOIT);
1181 }
Suraj Jitindar Singh014d02c2017-02-28 17:03:48 +11001182}
Benjamin Herrenschmidtefec9592010-02-04 14:33:54 +11001183
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001184static void __init prom_send_capabilities(void)
1185{
Benjamin Herrenschmidt493adff2013-08-07 02:01:38 +10001186 ihandle root;
Paul Mackerrasf709bfa2006-04-28 16:28:35 +10001187 prom_arg_t ret;
Laurent Dufourdbd0c5d2013-09-17 11:52:48 +02001188 u32 cores;
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001189
Suraj Jitindar Singh014d02c2017-02-28 17:03:48 +11001190 /* Check ibm,arch-vec-5-platform-support and fixup vec5 if required */
1191 prom_check_platform_support();
1192
Paul Mackerrasf709bfa2006-04-28 16:28:35 +10001193 root = call_prom("open", 1, 1, ADDR("/"));
1194 if (root != 0) {
Benjamin Herrenschmidtefec9592010-02-04 14:33:54 +11001195 /* We need to tell the FW about the number of cores we support.
1196 *
1197 * To do that, we count the number of threads on the first core
1198 * (we assume this is the same for all cores) and use it to
1199 * divide NR_CPUS.
1200 */
Laurent Dufourdbd0c5d2013-09-17 11:52:48 +02001201
Michael Ellerman76ffb572016-11-18 23:15:42 +11001202 cores = DIV_ROUND_UP(NR_CPUS, prom_count_smt_threads());
Mathieu Malaterreeae5f702018-04-06 22:12:19 +02001203 prom_printf("Max number of cores passed to firmware: %u (NR_CPUS = %d)\n",
Michael Ellerman76ffb572016-11-18 23:15:42 +11001204 cores, NR_CPUS);
1205
1206 ibm_architecture_vec.vec5.max_cpus = cpu_to_be32(cores);
Benjamin Herrenschmidtefec9592010-02-04 14:33:54 +11001207
Paul Mackerrasf709bfa2006-04-28 16:28:35 +10001208 /* try calling the ibm,client-architecture-support method */
Anton Blanchard049d0492009-09-21 20:47:39 +00001209 prom_printf("Calling ibm,client-architecture-support...");
Paul Mackerrasf709bfa2006-04-28 16:28:35 +10001210 if (call_prom_ret("call-method", 3, 2, &ret,
1211 ADDR("ibm,client-architecture-support"),
Benjamin Herrenschmidt33b74972006-06-07 12:01:32 +10001212 root,
Michael Ellerman76ffb572016-11-18 23:15:42 +11001213 ADDR(&ibm_architecture_vec)) == 0) {
Paul Mackerrasf709bfa2006-04-28 16:28:35 +10001214 /* the call exists... */
1215 if (ret)
Anton Blanchard4da727a2009-03-31 20:06:14 +00001216 prom_printf("\nWARNING: ibm,client-architecture"
Paul Mackerrasf709bfa2006-04-28 16:28:35 +10001217 "-support call FAILED!\n");
1218 call_prom("close", 1, 0, root);
Anton Blanchard4da727a2009-03-31 20:06:14 +00001219 prom_printf(" done\n");
Paul Mackerrasf709bfa2006-04-28 16:28:35 +10001220 return;
1221 }
1222 call_prom("close", 1, 0, root);
Anton Blanchard049d0492009-09-21 20:47:39 +00001223 prom_printf(" not implemented\n");
Paul Mackerrasf709bfa2006-04-28 16:28:35 +10001224 }
1225
Benjamin Herrenschmidt493adff2013-08-07 02:01:38 +10001226#ifdef __BIG_ENDIAN__
1227 {
1228 ihandle elfloader;
1229
1230 /* no ibm,client-architecture-support call, try the old way */
1231 elfloader = call_prom("open", 1, 1,
1232 ADDR("/packages/elf-loader"));
1233 if (elfloader == 0) {
1234 prom_printf("couldn't open /packages/elf-loader\n");
1235 return;
1236 }
1237 call_prom("call-method", 3, 1, ADDR("process-elf-header"),
1238 elfloader, ADDR(&fake_elf));
1239 call_prom("close", 1, 0, elfloader);
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001240 }
Benjamin Herrenschmidt493adff2013-08-07 02:01:38 +10001241#endif /* __BIG_ENDIAN__ */
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001242}
Benjamin Herrenschmidt11fdb302018-10-15 13:49:53 +11001243#endif /* CONFIG_PPC_PSERIES */
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001244
1245/*
1246 * Memory allocation strategy... our layout is normally:
1247 *
1248 * at 14Mb or more we have vmlinux, then a gap and initrd. In some
1249 * rare cases, initrd might end up being before the kernel though.
1250 * We assume this won't override the final kernel at 0, we have no
1251 * provision to handle that in this version, but it should hopefully
1252 * never happen.
1253 *
1254 * alloc_top is set to the top of RMO, eventually shrink down if the
1255 * TCEs overlap
1256 *
1257 * alloc_bottom is set to the top of kernel/initrd
1258 *
1259 * from there, allocations are done this way : rtas is allocated
1260 * topmost, and the device-tree is allocated from the bottom. We try
1261 * to grow the device-tree allocation as we progress. If we can't,
1262 * then we fail, we don't currently have a facility to restart
1263 * elsewhere, but that shouldn't be necessary.
1264 *
1265 * Note that calls to reserve_mem have to be done explicitly, memory
1266 * allocated with either alloc_up or alloc_down isn't automatically
1267 * reserved.
1268 */
1269
1270
1271/*
1272 * Allocates memory in the RMO upward from the kernel/initrd
1273 *
1274 * When align is 0, this is a special case, it means to allocate in place
1275 * at the current location of alloc_bottom or fail (that is basically
1276 * extending the previous allocation). Used for the device-tree flattening
1277 */
1278static unsigned long __init alloc_up(unsigned long size, unsigned long align)
1279{
Anton Blanchard5827d412012-11-26 17:40:03 +00001280 unsigned long base = alloc_bottom;
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001281 unsigned long addr = 0;
1282
Paul Mackerrasc49888202005-10-26 21:52:53 +10001283 if (align)
1284 base = _ALIGN_UP(base, align);
Mathieu Malaterreeae5f702018-04-06 22:12:19 +02001285 prom_debug("%s(%lx, %lx)\n", __func__, size, align);
Anton Blanchard5827d412012-11-26 17:40:03 +00001286 if (ram_top == 0)
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001287 prom_panic("alloc_up() called with mem not initialized\n");
1288
1289 if (align)
Anton Blanchard5827d412012-11-26 17:40:03 +00001290 base = _ALIGN_UP(alloc_bottom, align);
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001291 else
Anton Blanchard5827d412012-11-26 17:40:03 +00001292 base = alloc_bottom;
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001293
Anton Blanchard5827d412012-11-26 17:40:03 +00001294 for(; (base + size) <= alloc_top;
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001295 base = _ALIGN_UP(base + 0x100000, align)) {
Mathieu Malaterreeae5f702018-04-06 22:12:19 +02001296 prom_debug(" trying: 0x%lx\n\r", base);
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001297 addr = (unsigned long)prom_claim(base, size, 0);
Paul Mackerrasc49888202005-10-26 21:52:53 +10001298 if (addr != PROM_ERROR && addr != 0)
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001299 break;
1300 addr = 0;
1301 if (align == 0)
1302 break;
1303 }
1304 if (addr == 0)
1305 return 0;
Anton Blanchard5827d412012-11-26 17:40:03 +00001306 alloc_bottom = addr + size;
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001307
Mathieu Malaterreeae5f702018-04-06 22:12:19 +02001308 prom_debug(" -> %lx\n", addr);
1309 prom_debug(" alloc_bottom : %lx\n", alloc_bottom);
1310 prom_debug(" alloc_top : %lx\n", alloc_top);
1311 prom_debug(" alloc_top_hi : %lx\n", alloc_top_high);
1312 prom_debug(" rmo_top : %lx\n", rmo_top);
1313 prom_debug(" ram_top : %lx\n", ram_top);
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001314
1315 return addr;
1316}
1317
1318/*
1319 * Allocates memory downward, either from top of RMO, or if highmem
1320 * is set, from the top of RAM. Note that this one doesn't handle
1321 * failures. It does claim memory if highmem is not set.
1322 */
1323static unsigned long __init alloc_down(unsigned long size, unsigned long align,
1324 int highmem)
1325{
1326 unsigned long base, addr = 0;
1327
Mathieu Malaterreeae5f702018-04-06 22:12:19 +02001328 prom_debug("%s(%lx, %lx, %s)\n", __func__, size, align,
Anton Blanchard5827d412012-11-26 17:40:03 +00001329 highmem ? "(high)" : "(low)");
1330 if (ram_top == 0)
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001331 prom_panic("alloc_down() called with mem not initialized\n");
1332
1333 if (highmem) {
1334 /* Carve out storage for the TCE table. */
Anton Blanchard5827d412012-11-26 17:40:03 +00001335 addr = _ALIGN_DOWN(alloc_top_high - size, align);
1336 if (addr <= alloc_bottom)
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001337 return 0;
1338 /* Will we bump into the RMO ? If yes, check out that we
1339 * didn't overlap existing allocations there, if we did,
1340 * we are dead, we must be the first in town !
1341 */
Anton Blanchard5827d412012-11-26 17:40:03 +00001342 if (addr < rmo_top) {
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001343 /* Good, we are first */
Anton Blanchard5827d412012-11-26 17:40:03 +00001344 if (alloc_top == rmo_top)
1345 alloc_top = rmo_top = addr;
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001346 else
1347 return 0;
1348 }
Anton Blanchard5827d412012-11-26 17:40:03 +00001349 alloc_top_high = addr;
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001350 goto bail;
1351 }
1352
Anton Blanchard5827d412012-11-26 17:40:03 +00001353 base = _ALIGN_DOWN(alloc_top - size, align);
1354 for (; base > alloc_bottom;
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001355 base = _ALIGN_DOWN(base - 0x100000, align)) {
Mathieu Malaterreeae5f702018-04-06 22:12:19 +02001356 prom_debug(" trying: 0x%lx\n\r", base);
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001357 addr = (unsigned long)prom_claim(base, size, 0);
Paul Mackerrasc49888202005-10-26 21:52:53 +10001358 if (addr != PROM_ERROR && addr != 0)
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001359 break;
1360 addr = 0;
1361 }
1362 if (addr == 0)
1363 return 0;
Anton Blanchard5827d412012-11-26 17:40:03 +00001364 alloc_top = addr;
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001365
1366 bail:
Mathieu Malaterreeae5f702018-04-06 22:12:19 +02001367 prom_debug(" -> %lx\n", addr);
1368 prom_debug(" alloc_bottom : %lx\n", alloc_bottom);
1369 prom_debug(" alloc_top : %lx\n", alloc_top);
1370 prom_debug(" alloc_top_hi : %lx\n", alloc_top_high);
1371 prom_debug(" rmo_top : %lx\n", rmo_top);
1372 prom_debug(" ram_top : %lx\n", ram_top);
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001373
1374 return addr;
1375}
1376
1377/*
1378 * Parse a "reg" cell
1379 */
1380static unsigned long __init prom_next_cell(int s, cell_t **cellp)
1381{
1382 cell_t *p = *cellp;
1383 unsigned long r = 0;
1384
1385 /* Ignore more than 2 cells */
1386 while (s > sizeof(unsigned long) / 4) {
1387 p++;
1388 s--;
1389 }
Benjamin Herrenschmidt493adff2013-08-07 02:01:38 +10001390 r = be32_to_cpu(*p++);
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001391#ifdef CONFIG_PPC64
Paul Mackerras35499c02005-10-22 16:02:39 +10001392 if (s > 1) {
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001393 r <<= 32;
Benjamin Herrenschmidt493adff2013-08-07 02:01:38 +10001394 r |= be32_to_cpu(*(p++));
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001395 }
1396#endif
1397 *cellp = p;
1398 return r;
1399}
1400
1401/*
1402 * Very dumb function for adding to the memory reserve list, but
1403 * we don't need anything smarter at this point
1404 *
1405 * XXX Eventually check for collisions. They should NEVER happen.
1406 * If problems seem to show up, it would be a good start to track
1407 * them down.
1408 */
Michael Ellerman0108d3f2007-05-07 15:58:28 +10001409static void __init reserve_mem(u64 base, u64 size)
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001410{
Kumar Galacbbcf342006-01-11 17:57:13 -06001411 u64 top = base + size;
Anton Blanchard5827d412012-11-26 17:40:03 +00001412 unsigned long cnt = mem_reserve_cnt;
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001413
1414 if (size == 0)
1415 return;
1416
1417 /* We need to always keep one empty entry so that we
1418 * have our terminator with "size" set to 0 since we are
1419 * dumb and just copy this entire array to the boot params
1420 */
1421 base = _ALIGN_DOWN(base, PAGE_SIZE);
1422 top = _ALIGN_UP(top, PAGE_SIZE);
1423 size = top - base;
1424
1425 if (cnt >= (MEM_RESERVE_MAP_SIZE - 1))
1426 prom_panic("Memory reserve map exhausted !\n");
Benjamin Herrenschmidt493adff2013-08-07 02:01:38 +10001427 mem_reserve_map[cnt].base = cpu_to_be64(base);
1428 mem_reserve_map[cnt].size = cpu_to_be64(size);
Anton Blanchard5827d412012-11-26 17:40:03 +00001429 mem_reserve_cnt = cnt + 1;
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001430}
1431
1432/*
Adrian Bunkb3c2ffd2006-06-30 18:20:44 +02001433 * Initialize memory allocation mechanism, parse "memory" nodes and
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001434 * obtain that way the top of memory and RMO to setup out local allocator
1435 */
1436static void __init prom_init_mem(void)
1437{
1438 phandle node;
Mathieu Malaterreeab00a22018-04-04 22:08:35 +02001439#ifdef DEBUG_PROM
1440 char *path;
1441#endif
1442 char type[64];
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001443 unsigned int plen;
1444 cell_t *p, *endp;
Benjamin Herrenschmidt493adff2013-08-07 02:01:38 +10001445 __be32 val;
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001446 u32 rac, rsc;
1447
1448 /*
1449 * We iterate the memory nodes to find
1450 * 1) top of RMO (first node)
1451 * 2) top of memory
1452 */
Benjamin Herrenschmidt493adff2013-08-07 02:01:38 +10001453 val = cpu_to_be32(2);
1454 prom_getprop(prom.root, "#address-cells", &val, sizeof(val));
1455 rac = be32_to_cpu(val);
1456 val = cpu_to_be32(1);
1457 prom_getprop(prom.root, "#size-cells", &val, sizeof(rsc));
1458 rsc = be32_to_cpu(val);
1459 prom_debug("root_addr_cells: %x\n", rac);
1460 prom_debug("root_size_cells: %x\n", rsc);
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001461
1462 prom_debug("scanning memory:\n");
Mathieu Malaterreeab00a22018-04-04 22:08:35 +02001463#ifdef DEBUG_PROM
Anton Blanchard5827d412012-11-26 17:40:03 +00001464 path = prom_scratch;
Mathieu Malaterreeab00a22018-04-04 22:08:35 +02001465#endif
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001466
1467 for (node = 0; prom_next_node(&node); ) {
1468 type[0] = 0;
1469 prom_getprop(node, "device_type", type, sizeof(type));
1470
Paul Mackerrasc49888202005-10-26 21:52:53 +10001471 if (type[0] == 0) {
1472 /*
1473 * CHRP Longtrail machines have no device_type
1474 * on the memory node, so check the name instead...
1475 */
1476 prom_getprop(node, "name", type, sizeof(type));
1477 }
Anton Blanchard5827d412012-11-26 17:40:03 +00001478 if (strcmp(type, "memory"))
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001479 continue;
Paul Mackerrasc49888202005-10-26 21:52:53 +10001480
Anton Blanchard5827d412012-11-26 17:40:03 +00001481 plen = prom_getprop(node, "reg", regbuf, sizeof(regbuf));
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001482 if (plen > sizeof(regbuf)) {
1483 prom_printf("memory node too large for buffer !\n");
1484 plen = sizeof(regbuf);
1485 }
Anton Blanchard5827d412012-11-26 17:40:03 +00001486 p = regbuf;
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001487 endp = p + (plen / sizeof(cell_t));
1488
1489#ifdef DEBUG_PROM
1490 memset(path, 0, PROM_SCRATCH_SIZE);
1491 call_prom("package-to-path", 3, 1, node, path, PROM_SCRATCH_SIZE-1);
1492 prom_debug(" node %s :\n", path);
1493#endif /* DEBUG_PROM */
1494
1495 while ((endp - p) >= (rac + rsc)) {
1496 unsigned long base, size;
1497
1498 base = prom_next_cell(rac, &p);
1499 size = prom_next_cell(rsc, &p);
1500
1501 if (size == 0)
1502 continue;
Mathieu Malaterreeae5f702018-04-06 22:12:19 +02001503 prom_debug(" %lx %lx\n", base, size);
Anton Blanchard5827d412012-11-26 17:40:03 +00001504 if (base == 0 && (of_platform & PLATFORM_LPAR))
1505 rmo_top = size;
1506 if ((base + size) > ram_top)
1507 ram_top = base + size;
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001508 }
1509 }
1510
Anton Blanchard5827d412012-11-26 17:40:03 +00001511 alloc_bottom = PAGE_ALIGN((unsigned long)&_end + 0x4000);
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001512
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001513 /*
Benjamin Krillcf687872009-07-27 22:02:39 +00001514 * If prom_memory_limit is set we reduce the upper limits *except* for
1515 * alloc_top_high. This must be the real top of RAM so we can put
1516 * TCE's up there.
1517 */
1518
Anton Blanchard5827d412012-11-26 17:40:03 +00001519 alloc_top_high = ram_top;
Benjamin Krillcf687872009-07-27 22:02:39 +00001520
Anton Blanchard5827d412012-11-26 17:40:03 +00001521 if (prom_memory_limit) {
1522 if (prom_memory_limit <= alloc_bottom) {
Mathieu Malaterreeae5f702018-04-06 22:12:19 +02001523 prom_printf("Ignoring mem=%lx <= alloc_bottom.\n",
1524 prom_memory_limit);
Anton Blanchard5827d412012-11-26 17:40:03 +00001525 prom_memory_limit = 0;
1526 } else if (prom_memory_limit >= ram_top) {
Mathieu Malaterreeae5f702018-04-06 22:12:19 +02001527 prom_printf("Ignoring mem=%lx >= ram_top.\n",
1528 prom_memory_limit);
Anton Blanchard5827d412012-11-26 17:40:03 +00001529 prom_memory_limit = 0;
Benjamin Krillcf687872009-07-27 22:02:39 +00001530 } else {
Anton Blanchard5827d412012-11-26 17:40:03 +00001531 ram_top = prom_memory_limit;
1532 rmo_top = min(rmo_top, prom_memory_limit);
Benjamin Krillcf687872009-07-27 22:02:39 +00001533 }
1534 }
1535
1536 /*
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001537 * Setup our top alloc point, that is top of RMO or top of
1538 * segment 0 when running non-LPAR.
1539 * Some RS64 machines have buggy firmware where claims up at
1540 * 1GB fail. Cap at 768MB as a workaround.
1541 * Since 768MB is plenty of room, and we need to cap to something
1542 * reasonable on 32-bit, cap at 768MB on all machines.
1543 */
Anton Blanchard5827d412012-11-26 17:40:03 +00001544 if (!rmo_top)
1545 rmo_top = ram_top;
1546 rmo_top = min(0x30000000ul, rmo_top);
1547 alloc_top = rmo_top;
1548 alloc_top_high = ram_top;
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001549
Paul Mackerras64968f62011-12-13 17:54:13 +00001550 /*
1551 * Check if we have an initrd after the kernel but still inside
1552 * the RMO. If we do move our bottom point to after it.
1553 */
Anton Blanchard5827d412012-11-26 17:40:03 +00001554 if (prom_initrd_start &&
1555 prom_initrd_start < rmo_top &&
1556 prom_initrd_end > alloc_bottom)
1557 alloc_bottom = PAGE_ALIGN(prom_initrd_end);
Paul Mackerras64968f62011-12-13 17:54:13 +00001558
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001559 prom_printf("memory layout at init:\n");
Mathieu Malaterreeae5f702018-04-06 22:12:19 +02001560 prom_printf(" memory_limit : %lx (16 MB aligned)\n",
1561 prom_memory_limit);
1562 prom_printf(" alloc_bottom : %lx\n", alloc_bottom);
1563 prom_printf(" alloc_top : %lx\n", alloc_top);
1564 prom_printf(" alloc_top_hi : %lx\n", alloc_top_high);
1565 prom_printf(" rmo_top : %lx\n", rmo_top);
1566 prom_printf(" ram_top : %lx\n", ram_top);
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001567}
1568
Benjamin Herrenschmidt27f44882011-09-19 18:27:58 +00001569static void __init prom_close_stdin(void)
1570{
Benjamin Herrenschmidt493adff2013-08-07 02:01:38 +10001571 __be32 val;
1572 ihandle stdin;
Benjamin Herrenschmidt27f44882011-09-19 18:27:58 +00001573
Benjamin Herrenschmidt493adff2013-08-07 02:01:38 +10001574 if (prom_getprop(prom.chosen, "stdin", &val, sizeof(val)) > 0) {
1575 stdin = be32_to_cpu(val);
1576 call_prom("close", 1, 0, stdin);
1577 }
Benjamin Herrenschmidt27f44882011-09-19 18:27:58 +00001578}
1579
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001580/*
1581 * Allocate room for and instantiate RTAS
1582 */
1583static void __init prom_instantiate_rtas(void)
1584{
1585 phandle rtas_node;
1586 ihandle rtas_inst;
1587 u32 base, entry = 0;
Benjamin Herrenschmidt493adff2013-08-07 02:01:38 +10001588 __be32 val;
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001589 u32 size = 0;
1590
1591 prom_debug("prom_instantiate_rtas: start...\n");
1592
1593 rtas_node = call_prom("finddevice", 1, 1, ADDR("/rtas"));
1594 prom_debug("rtas_node: %x\n", rtas_node);
1595 if (!PHANDLE_VALID(rtas_node))
1596 return;
1597
Benjamin Herrenschmidt493adff2013-08-07 02:01:38 +10001598 val = 0;
1599 prom_getprop(rtas_node, "rtas-size", &val, sizeof(size));
1600 size = be32_to_cpu(val);
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001601 if (size == 0)
1602 return;
1603
1604 base = alloc_down(size, PAGE_SIZE, 0);
Anton Blanchard6d1e2c62011-11-14 12:55:47 +00001605 if (base == 0)
1606 prom_panic("Could not allocate memory for RTAS\n");
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001607
1608 rtas_inst = call_prom("open", 1, 1, ADDR("/rtas"));
1609 if (!IHANDLE_VALID(rtas_inst)) {
Paul Mackerrasa23414b2005-11-10 12:00:55 +11001610 prom_printf("opening rtas package failed (%x)\n", rtas_inst);
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001611 return;
1612 }
1613
Anton Blanchard1f8737a2009-03-31 20:06:15 +00001614 prom_printf("instantiating rtas at 0x%x...", base);
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001615
1616 if (call_prom_ret("call-method", 3, 2, &entry,
1617 ADDR("instantiate-rtas"),
Paul Mackerrasa23414b2005-11-10 12:00:55 +11001618 rtas_inst, base) != 0
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001619 || entry == 0) {
1620 prom_printf(" failed\n");
1621 return;
1622 }
1623 prom_printf(" done\n");
1624
1625 reserve_mem(base, size);
1626
Benjamin Herrenschmidt493adff2013-08-07 02:01:38 +10001627 val = cpu_to_be32(base);
Paul Mackerrasa23414b2005-11-10 12:00:55 +11001628 prom_setprop(rtas_node, "/rtas", "linux,rtas-base",
Benjamin Herrenschmidt493adff2013-08-07 02:01:38 +10001629 &val, sizeof(val));
1630 val = cpu_to_be32(entry);
Paul Mackerrasa23414b2005-11-10 12:00:55 +11001631 prom_setprop(rtas_node, "/rtas", "linux,rtas-entry",
Benjamin Herrenschmidt493adff2013-08-07 02:01:38 +10001632 &val, sizeof(val));
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001633
Benjamin Herrenschmidtdbe78b42013-09-25 14:02:50 +10001634 /* Check if it supports "query-cpu-stopped-state" */
1635 if (prom_getprop(rtas_node, "query-cpu-stopped-state",
1636 &val, sizeof(val)) != PROM_ERROR)
1637 rtas_has_query_cpu_stopped = true;
1638
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001639 prom_debug("rtas base = 0x%x\n", base);
1640 prom_debug("rtas entry = 0x%x\n", entry);
Mathieu Malaterreeae5f702018-04-06 22:12:19 +02001641 prom_debug("rtas size = 0x%x\n", size);
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001642
1643 prom_debug("prom_instantiate_rtas: end...\n");
1644}
1645
1646#ifdef CONFIG_PPC64
1647/*
Ashley Lai4a727422012-08-14 18:34:57 -05001648 * Allocate room for and instantiate Stored Measurement Log (SML)
1649 */
1650static void __init prom_instantiate_sml(void)
1651{
1652 phandle ibmvtpm_node;
1653 ihandle ibmvtpm_inst;
Hon Ching \(Vicky\) Lob4ed0462015-10-07 20:11:53 -04001654 u32 entry = 0, size = 0, succ = 0;
Ashley Lai4a727422012-08-14 18:34:57 -05001655 u64 base;
Hon Ching \(Vicky\) Lob4ed0462015-10-07 20:11:53 -04001656 __be32 val;
Ashley Lai4a727422012-08-14 18:34:57 -05001657
1658 prom_debug("prom_instantiate_sml: start...\n");
1659
Hon Ching \(Vicky\) Lo2f82e982015-10-07 20:11:52 -04001660 ibmvtpm_node = call_prom("finddevice", 1, 1, ADDR("/vdevice/vtpm"));
Ashley Lai4a727422012-08-14 18:34:57 -05001661 prom_debug("ibmvtpm_node: %x\n", ibmvtpm_node);
1662 if (!PHANDLE_VALID(ibmvtpm_node))
1663 return;
1664
Hon Ching \(Vicky\) Lo2f82e982015-10-07 20:11:52 -04001665 ibmvtpm_inst = call_prom("open", 1, 1, ADDR("/vdevice/vtpm"));
Ashley Lai4a727422012-08-14 18:34:57 -05001666 if (!IHANDLE_VALID(ibmvtpm_inst)) {
1667 prom_printf("opening vtpm package failed (%x)\n", ibmvtpm_inst);
1668 return;
1669 }
1670
Hon Ching \(Vicky\) Lob4ed0462015-10-07 20:11:53 -04001671 if (prom_getprop(ibmvtpm_node, "ibm,sml-efi-reformat-supported",
1672 &val, sizeof(val)) != PROM_ERROR) {
1673 if (call_prom_ret("call-method", 2, 2, &succ,
1674 ADDR("reformat-sml-to-efi-alignment"),
1675 ibmvtpm_inst) != 0 || succ == 0) {
1676 prom_printf("Reformat SML to EFI alignment failed\n");
1677 return;
1678 }
Hon Ching \(Vicky\) Lob4ed0462015-10-07 20:11:53 -04001679
Hon Ching \(Vicky\) Lo9e5d4af2015-10-07 20:11:54 -04001680 if (call_prom_ret("call-method", 2, 2, &size,
1681 ADDR("sml-get-allocated-size"),
1682 ibmvtpm_inst) != 0 || size == 0) {
1683 prom_printf("SML get allocated size failed\n");
1684 return;
1685 }
1686 } else {
1687 if (call_prom_ret("call-method", 2, 2, &size,
1688 ADDR("sml-get-handover-size"),
1689 ibmvtpm_inst) != 0 || size == 0) {
1690 prom_printf("SML get handover size failed\n");
1691 return;
1692 }
Ashley Lai4a727422012-08-14 18:34:57 -05001693 }
1694
1695 base = alloc_down(size, PAGE_SIZE, 0);
1696 if (base == 0)
1697 prom_panic("Could not allocate memory for sml\n");
1698
Mathieu Malaterreeae5f702018-04-06 22:12:19 +02001699 prom_printf("instantiating sml at 0x%llx...", base);
Ashley Lai4a727422012-08-14 18:34:57 -05001700
Hon Ching \(Vicky\) Lo9e5d4af2015-10-07 20:11:54 -04001701 memset((void *)base, 0, size);
1702
Ashley Lai4a727422012-08-14 18:34:57 -05001703 if (call_prom_ret("call-method", 4, 2, &entry,
1704 ADDR("sml-handover"),
1705 ibmvtpm_inst, size, base) != 0 || entry == 0) {
1706 prom_printf("SML handover failed\n");
1707 return;
1708 }
1709 prom_printf(" done\n");
1710
1711 reserve_mem(base, size);
1712
Hon Ching \(Vicky\) Lo2f82e982015-10-07 20:11:52 -04001713 prom_setprop(ibmvtpm_node, "/vdevice/vtpm", "linux,sml-base",
Ashley Lai4a727422012-08-14 18:34:57 -05001714 &base, sizeof(base));
Hon Ching \(Vicky\) Lo2f82e982015-10-07 20:11:52 -04001715 prom_setprop(ibmvtpm_node, "/vdevice/vtpm", "linux,sml-size",
Ashley Lai4a727422012-08-14 18:34:57 -05001716 &size, sizeof(size));
1717
Mathieu Malaterreeae5f702018-04-06 22:12:19 +02001718 prom_debug("sml base = 0x%llx\n", base);
1719 prom_debug("sml size = 0x%x\n", size);
Ashley Lai4a727422012-08-14 18:34:57 -05001720
1721 prom_debug("prom_instantiate_sml: end...\n");
1722}
1723
1724/*
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001725 * Allocate room for and initialize TCE tables
1726 */
Benjamin Herrenschmidt493adff2013-08-07 02:01:38 +10001727#ifdef __BIG_ENDIAN__
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001728static void __init prom_initialize_tce_table(void)
1729{
1730 phandle node;
1731 ihandle phb_node;
1732 char compatible[64], type[64], model[64];
Anton Blanchard5827d412012-11-26 17:40:03 +00001733 char *path = prom_scratch;
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001734 u64 base, align;
1735 u32 minalign, minsize;
1736 u64 tce_entry, *tce_entryp;
1737 u64 local_alloc_top, local_alloc_bottom;
1738 u64 i;
1739
Anton Blanchard5827d412012-11-26 17:40:03 +00001740 if (prom_iommu_off)
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001741 return;
1742
1743 prom_debug("starting prom_initialize_tce_table\n");
1744
1745 /* Cache current top of allocs so we reserve a single block */
Anton Blanchard5827d412012-11-26 17:40:03 +00001746 local_alloc_top = alloc_top_high;
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001747 local_alloc_bottom = local_alloc_top;
1748
1749 /* Search all nodes looking for PHBs. */
1750 for (node = 0; prom_next_node(&node); ) {
1751 compatible[0] = 0;
1752 type[0] = 0;
1753 model[0] = 0;
1754 prom_getprop(node, "compatible",
1755 compatible, sizeof(compatible));
1756 prom_getprop(node, "device_type", type, sizeof(type));
1757 prom_getprop(node, "model", model, sizeof(model));
1758
Anton Blanchard5827d412012-11-26 17:40:03 +00001759 if ((type[0] == 0) || (strstr(type, "pci") == NULL))
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001760 continue;
1761
Linas Vepstase788ff12007-09-07 03:45:21 +10001762 /* Keep the old logic intact to avoid regression. */
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001763 if (compatible[0] != 0) {
Anton Blanchard5827d412012-11-26 17:40:03 +00001764 if ((strstr(compatible, "python") == NULL) &&
1765 (strstr(compatible, "Speedwagon") == NULL) &&
1766 (strstr(compatible, "Winnipeg") == NULL))
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001767 continue;
1768 } else if (model[0] != 0) {
Anton Blanchard5827d412012-11-26 17:40:03 +00001769 if ((strstr(model, "ython") == NULL) &&
1770 (strstr(model, "peedwagon") == NULL) &&
1771 (strstr(model, "innipeg") == NULL))
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001772 continue;
1773 }
1774
1775 if (prom_getprop(node, "tce-table-minalign", &minalign,
1776 sizeof(minalign)) == PROM_ERROR)
1777 minalign = 0;
1778 if (prom_getprop(node, "tce-table-minsize", &minsize,
1779 sizeof(minsize)) == PROM_ERROR)
1780 minsize = 4UL << 20;
1781
1782 /*
1783 * Even though we read what OF wants, we just set the table
1784 * size to 4 MB. This is enough to map 2GB of PCI DMA space.
1785 * By doing this, we avoid the pitfalls of trying to DMA to
1786 * MMIO space and the DMA alias hole.
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001787 */
Nicholas Piggin471d7ff2018-02-21 05:08:29 +10001788 minsize = 4UL << 20;
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001789
1790 /* Align to the greater of the align or size */
1791 align = max(minalign, minsize);
1792 base = alloc_down(minsize, align, 1);
1793 if (base == 0)
1794 prom_panic("ERROR, cannot find space for TCE table.\n");
1795 if (base < local_alloc_bottom)
1796 local_alloc_bottom = base;
1797
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001798 /* It seems OF doesn't null-terminate the path :-( */
Li Zefanaca71ef2007-11-05 13:21:56 +11001799 memset(path, 0, PROM_SCRATCH_SIZE);
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001800 /* Call OF to setup the TCE hardware */
1801 if (call_prom("package-to-path", 3, 1, node,
1802 path, PROM_SCRATCH_SIZE-1) == PROM_ERROR) {
1803 prom_printf("package-to-path failed\n");
1804 }
1805
Paul Mackerrasa23414b2005-11-10 12:00:55 +11001806 /* Save away the TCE table attributes for later use. */
1807 prom_setprop(node, path, "linux,tce-base", &base, sizeof(base));
1808 prom_setprop(node, path, "linux,tce-size", &minsize, sizeof(minsize));
1809
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001810 prom_debug("TCE table: %s\n", path);
1811 prom_debug("\tnode = 0x%x\n", node);
Mathieu Malaterreeae5f702018-04-06 22:12:19 +02001812 prom_debug("\tbase = 0x%llx\n", base);
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001813 prom_debug("\tsize = 0x%x\n", minsize);
1814
1815 /* Initialize the table to have a one-to-one mapping
1816 * over the allocated size.
1817 */
Ingo Molnar2b931fb2009-01-06 13:56:52 +00001818 tce_entryp = (u64 *)base;
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001819 for (i = 0; i < (minsize >> 3) ;tce_entryp++, i++) {
1820 tce_entry = (i << PAGE_SHIFT);
1821 tce_entry |= 0x3;
1822 *tce_entryp = tce_entry;
1823 }
1824
1825 prom_printf("opening PHB %s", path);
1826 phb_node = call_prom("open", 1, 1, path);
1827 if (phb_node == 0)
1828 prom_printf("... failed\n");
1829 else
1830 prom_printf("... done\n");
1831
1832 call_prom("call-method", 6, 0, ADDR("set-64-bit-addressing"),
1833 phb_node, -1, minsize,
1834 (u32) base, (u32) (base >> 32));
1835 call_prom("close", 1, 0, phb_node);
1836 }
1837
1838 reserve_mem(local_alloc_bottom, local_alloc_top - local_alloc_bottom);
1839
Michael Ellerman2babf5c2006-05-17 18:00:46 +10001840 /* These are only really needed if there is a memory limit in
1841 * effect, but we don't know so export them always. */
Anton Blanchard5827d412012-11-26 17:40:03 +00001842 prom_tce_alloc_start = local_alloc_bottom;
1843 prom_tce_alloc_end = local_alloc_top;
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001844
1845 /* Flag the first invalid entry */
1846 prom_debug("ending prom_initialize_tce_table\n");
1847}
Benjamin Herrenschmidt493adff2013-08-07 02:01:38 +10001848#endif /* __BIG_ENDIAN__ */
1849#endif /* CONFIG_PPC64 */
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001850
1851/*
1852 * With CHRP SMP we need to use the OF to start the other processors.
1853 * We can't wait until smp_boot_cpus (the OF is trashed by then)
1854 * so we have to put the processors into a holding pattern controlled
1855 * by the kernel (not OF) before we destroy the OF.
1856 *
1857 * This uses a chunk of low memory, puts some holding pattern
1858 * code there and sends the other processors off to there until
1859 * smp_boot_cpus tells them to do something. The holding pattern
1860 * checks that address until its cpu # is there, when it is that
1861 * cpu jumps to __secondary_start(). smp_boot_cpus() takes care
1862 * of setting those values.
1863 *
1864 * We also use physical address 0x4 here to tell when a cpu
1865 * is in its holding pattern code.
1866 *
1867 * -- Cort
1868 */
Paul Mackerrasbbd0abd2005-10-26 21:45:56 +10001869/*
1870 * We want to reference the copy of __secondary_hold_* in the
1871 * 0 - 0x100 address range
1872 */
1873#define LOW_ADDR(x) (((unsigned long) &(x)) & 0xff)
1874
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001875static void __init prom_hold_cpus(void)
1876{
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001877 unsigned long i;
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001878 phandle node;
1879 char type[64];
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001880 unsigned long *spinloop
Paul Mackerrasbbd0abd2005-10-26 21:45:56 +10001881 = (void *) LOW_ADDR(__secondary_hold_spinloop);
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001882 unsigned long *acknowledge
Paul Mackerrasbbd0abd2005-10-26 21:45:56 +10001883 = (void *) LOW_ADDR(__secondary_hold_acknowledge);
Paul Mackerrasbbd0abd2005-10-26 21:45:56 +10001884 unsigned long secondary_hold = LOW_ADDR(__secondary_hold);
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001885
Benjamin Herrenschmidtdbe78b42013-09-25 14:02:50 +10001886 /*
1887 * On pseries, if RTAS supports "query-cpu-stopped-state",
1888 * we skip this stage, the CPUs will be started by the
1889 * kernel using RTAS.
1890 */
1891 if ((of_platform == PLATFORM_PSERIES ||
1892 of_platform == PLATFORM_PSERIES_LPAR) &&
1893 rtas_has_query_cpu_stopped) {
1894 prom_printf("prom_hold_cpus: skipped\n");
1895 return;
1896 }
1897
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001898 prom_debug("prom_hold_cpus: start...\n");
Mathieu Malaterreeae5f702018-04-06 22:12:19 +02001899 prom_debug(" 1) spinloop = 0x%lx\n", (unsigned long)spinloop);
1900 prom_debug(" 1) *spinloop = 0x%lx\n", *spinloop);
1901 prom_debug(" 1) acknowledge = 0x%lx\n",
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001902 (unsigned long)acknowledge);
Mathieu Malaterreeae5f702018-04-06 22:12:19 +02001903 prom_debug(" 1) *acknowledge = 0x%lx\n", *acknowledge);
1904 prom_debug(" 1) secondary_hold = 0x%lx\n", secondary_hold);
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001905
1906 /* Set the common spinloop variable, so all of the secondary cpus
1907 * will block when they are awakened from their OF spinloop.
1908 * This must occur for both SMP and non SMP kernels, since OF will
1909 * be trashed when we move the kernel.
1910 */
1911 *spinloop = 0;
1912
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001913 /* look for cpus */
1914 for (node = 0; prom_next_node(&node); ) {
Benjamin Herrenschmidt493adff2013-08-07 02:01:38 +10001915 unsigned int cpu_no;
1916 __be32 reg;
1917
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001918 type[0] = 0;
1919 prom_getprop(node, "device_type", type, sizeof(type));
Anton Blanchard5827d412012-11-26 17:40:03 +00001920 if (strcmp(type, "cpu") != 0)
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001921 continue;
1922
1923 /* Skip non-configured cpus. */
1924 if (prom_getprop(node, "status", type, sizeof(type)) > 0)
Anton Blanchard5827d412012-11-26 17:40:03 +00001925 if (strcmp(type, "okay") != 0)
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001926 continue;
1927
Benjamin Herrenschmidt493adff2013-08-07 02:01:38 +10001928 reg = cpu_to_be32(-1); /* make sparse happy */
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001929 prom_getprop(node, "reg", &reg, sizeof(reg));
Benjamin Herrenschmidt493adff2013-08-07 02:01:38 +10001930 cpu_no = be32_to_cpu(reg);
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001931
Mathieu Malaterreeae5f702018-04-06 22:12:19 +02001932 prom_debug("cpu hw idx = %u\n", cpu_no);
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001933
1934 /* Init the acknowledge var which will be reset by
1935 * the secondary cpu when it awakens from its OF
1936 * spinloop.
1937 */
1938 *acknowledge = (unsigned long)-1;
1939
Benjamin Herrenschmidt493adff2013-08-07 02:01:38 +10001940 if (cpu_no != prom.cpu) {
Benjamin Herrenschmidt27f44882011-09-19 18:27:58 +00001941 /* Primary Thread of non-boot cpu or any thread */
Mathieu Malaterreeae5f702018-04-06 22:12:19 +02001942 prom_printf("starting cpu hw idx %u... ", cpu_no);
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001943 call_prom("start-cpu", 3, 0, node,
Benjamin Herrenschmidt493adff2013-08-07 02:01:38 +10001944 secondary_hold, cpu_no);
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001945
Paul Mackerrasbbd0abd2005-10-26 21:45:56 +10001946 for (i = 0; (i < 100000000) &&
1947 (*acknowledge == ((unsigned long)-1)); i++ )
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001948 mb();
1949
Benjamin Herrenschmidt493adff2013-08-07 02:01:38 +10001950 if (*acknowledge == cpu_no)
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001951 prom_printf("done\n");
Paul Mackerrasbbd0abd2005-10-26 21:45:56 +10001952 else
Mathieu Malaterreeae5f702018-04-06 22:12:19 +02001953 prom_printf("failed: %lx\n", *acknowledge);
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001954 }
1955#ifdef CONFIG_SMP
1956 else
Mathieu Malaterreeae5f702018-04-06 22:12:19 +02001957 prom_printf("boot cpu hw idx %u\n", cpu_no);
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001958#endif /* CONFIG_SMP */
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001959 }
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001960
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001961 prom_debug("prom_hold_cpus: end...\n");
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001962}
1963
1964
1965static void __init prom_init_client_services(unsigned long pp)
1966{
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001967 /* Get a handle to the prom entry point before anything else */
Anton Blanchard5827d412012-11-26 17:40:03 +00001968 prom_entry = pp;
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001969
1970 /* get a handle for the stdout device */
Anton Blanchard5827d412012-11-26 17:40:03 +00001971 prom.chosen = call_prom("finddevice", 1, 1, ADDR("/chosen"));
1972 if (!PHANDLE_VALID(prom.chosen))
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001973 prom_panic("cannot find chosen"); /* msg won't be printed :( */
1974
1975 /* get device tree root */
Anton Blanchard5827d412012-11-26 17:40:03 +00001976 prom.root = call_prom("finddevice", 1, 1, ADDR("/"));
1977 if (!PHANDLE_VALID(prom.root))
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001978 prom_panic("cannot find device tree root"); /* msg won't be printed :( */
Paul Mackerrasa575b802005-10-23 17:23:21 +10001979
Anton Blanchard5827d412012-11-26 17:40:03 +00001980 prom.mmumap = 0;
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001981}
1982
Paul Mackerrasa575b802005-10-23 17:23:21 +10001983#ifdef CONFIG_PPC32
1984/*
1985 * For really old powermacs, we need to map things we claim.
1986 * For that, we need the ihandle of the mmu.
Paul Mackerrasa23414b2005-11-10 12:00:55 +11001987 * Also, on the longtrail, we need to work around other bugs.
Paul Mackerrasa575b802005-10-23 17:23:21 +10001988 */
1989static void __init prom_find_mmu(void)
1990{
Paul Mackerrasa575b802005-10-23 17:23:21 +10001991 phandle oprom;
1992 char version[64];
1993
1994 oprom = call_prom("finddevice", 1, 1, ADDR("/openprom"));
1995 if (!PHANDLE_VALID(oprom))
1996 return;
1997 if (prom_getprop(oprom, "model", version, sizeof(version)) <= 0)
1998 return;
1999 version[sizeof(version) - 1] = 0;
Paul Mackerrasa575b802005-10-23 17:23:21 +10002000 /* XXX might need to add other versions here */
Paul Mackerrasa23414b2005-11-10 12:00:55 +11002001 if (strcmp(version, "Open Firmware, 1.0.5") == 0)
2002 of_workarounds = OF_WA_CLAIM;
2003 else if (strncmp(version, "FirmWorks,3.", 12) == 0) {
2004 of_workarounds = OF_WA_CLAIM | OF_WA_LONGTRAIL;
2005 call_prom("interpret", 1, 1, "dev /memory 0 to allow-reclaim");
2006 } else
Paul Mackerrasa575b802005-10-23 17:23:21 +10002007 return;
Anton Blanchard5827d412012-11-26 17:40:03 +00002008 prom.memory = call_prom("open", 1, 1, ADDR("/memory"));
2009 prom_getprop(prom.chosen, "mmu", &prom.mmumap,
2010 sizeof(prom.mmumap));
Benjamin Herrenschmidt493adff2013-08-07 02:01:38 +10002011 prom.mmumap = be32_to_cpu(prom.mmumap);
Anton Blanchard5827d412012-11-26 17:40:03 +00002012 if (!IHANDLE_VALID(prom.memory) || !IHANDLE_VALID(prom.mmumap))
Paul Mackerrasa23414b2005-11-10 12:00:55 +11002013 of_workarounds &= ~OF_WA_CLAIM; /* hmmm */
Paul Mackerrasa575b802005-10-23 17:23:21 +10002014}
2015#else
2016#define prom_find_mmu()
2017#endif
2018
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002019static void __init prom_init_stdout(void)
2020{
Anton Blanchard5827d412012-11-26 17:40:03 +00002021 char *path = of_stdout_device;
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002022 char type[16];
Benjamin Herrenschmidt493adff2013-08-07 02:01:38 +10002023 phandle stdout_node;
2024 __be32 val;
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002025
Anton Blanchard5827d412012-11-26 17:40:03 +00002026 if (prom_getprop(prom.chosen, "stdout", &val, sizeof(val)) <= 0)
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002027 prom_panic("cannot find stdout");
2028
Benjamin Herrenschmidt493adff2013-08-07 02:01:38 +10002029 prom.stdout = be32_to_cpu(val);
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002030
2031 /* Get the full OF pathname of the stdout device */
2032 memset(path, 0, 256);
Anton Blanchard5827d412012-11-26 17:40:03 +00002033 call_prom("instance-to-path", 3, 1, prom.stdout, path, 255);
Anton Blanchard5827d412012-11-26 17:40:03 +00002034 prom_printf("OF stdout device is: %s\n", of_stdout_device);
2035 prom_setprop(prom.chosen, "/chosen", "linux,stdout-path",
Paul Mackerrasa23414b2005-11-10 12:00:55 +11002036 path, strlen(path) + 1);
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002037
Benjamin Herrenschmidt10348f52014-01-13 09:49:17 +11002038 /* instance-to-package fails on PA-Semi */
2039 stdout_node = call_prom("instance-to-package", 1, 1, prom.stdout);
2040 if (stdout_node != PROM_ERROR) {
2041 val = cpu_to_be32(stdout_node);
Benjamin Herrenschmidt10348f52014-01-13 09:49:17 +11002042
2043 /* If it's a display, note it */
2044 memset(type, 0, sizeof(type));
2045 prom_getprop(stdout_node, "device_type", type, sizeof(type));
2046 if (strcmp(type, "display") == 0)
2047 prom_setprop(stdout_node, path, "linux,boot-display", NULL, 0);
2048 }
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002049}
2050
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002051static int __init prom_find_machine_type(void)
2052{
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002053 char compat[256];
2054 int len, i = 0;
Benjamin Herrenschmidt21fe3302005-11-07 16:41:59 +11002055#ifdef CONFIG_PPC64
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002056 phandle rtas;
Benjamin Herrenschmidte8222502006-03-28 23:15:54 +11002057 int x;
Benjamin Herrenschmidt21fe3302005-11-07 16:41:59 +11002058#endif
Benjamin Herrenschmidte8222502006-03-28 23:15:54 +11002059
Benjamin Herrenschmidt6e35d5d2011-09-19 18:28:01 +00002060 /* Look for a PowerMac or a Cell */
Anton Blanchard5827d412012-11-26 17:40:03 +00002061 len = prom_getprop(prom.root, "compatible",
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002062 compat, sizeof(compat)-1);
2063 if (len > 0) {
2064 compat[len] = 0;
2065 while (i < len) {
2066 char *p = &compat[i];
2067 int sl = strlen(p);
2068 if (sl == 0)
2069 break;
Anton Blanchard5827d412012-11-26 17:40:03 +00002070 if (strstr(p, "Power Macintosh") ||
2071 strstr(p, "MacRISC"))
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002072 return PLATFORM_POWERMAC;
Arnd Bergmann133dda12006-06-07 12:04:18 +10002073#ifdef CONFIG_PPC64
2074 /* We must make sure we don't detect the IBM Cell
2075 * blades as pSeries due to some firmware issues,
2076 * so we do it here.
2077 */
Anton Blanchard5827d412012-11-26 17:40:03 +00002078 if (strstr(p, "IBM,CBEA") ||
2079 strstr(p, "IBM,CPBW-1.0"))
Arnd Bergmann133dda12006-06-07 12:04:18 +10002080 return PLATFORM_GENERIC;
2081#endif /* CONFIG_PPC64 */
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002082 i += sl + 1;
2083 }
2084 }
2085#ifdef CONFIG_PPC64
Benjamin Herrenschmidt6e35d5d2011-09-19 18:28:01 +00002086 /* Try to figure out if it's an IBM pSeries or any other
Benjamin Herrenschmidte8222502006-03-28 23:15:54 +11002087 * PAPR compliant platform. We assume it is if :
2088 * - /device_type is "chrp" (please, do NOT use that for future
2089 * non-IBM designs !
2090 * - it has /rtas
2091 */
Anton Blanchard5827d412012-11-26 17:40:03 +00002092 len = prom_getprop(prom.root, "device_type",
Benjamin Herrenschmidte8222502006-03-28 23:15:54 +11002093 compat, sizeof(compat)-1);
2094 if (len <= 0)
2095 return PLATFORM_GENERIC;
Anton Blanchard5827d412012-11-26 17:40:03 +00002096 if (strcmp(compat, "chrp"))
Benjamin Herrenschmidte8222502006-03-28 23:15:54 +11002097 return PLATFORM_GENERIC;
2098
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002099 /* Default to pSeries. We need to know if we are running LPAR */
2100 rtas = call_prom("finddevice", 1, 1, ADDR("/rtas"));
Benjamin Herrenschmidte8222502006-03-28 23:15:54 +11002101 if (!PHANDLE_VALID(rtas))
2102 return PLATFORM_GENERIC;
2103 x = prom_getproplen(rtas, "ibm,hypertas-functions");
2104 if (x != PROM_ERROR) {
Anton Blanchard4da727a2009-03-31 20:06:14 +00002105 prom_debug("Hypertas detected, assuming LPAR !\n");
Benjamin Herrenschmidte8222502006-03-28 23:15:54 +11002106 return PLATFORM_PSERIES_LPAR;
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002107 }
2108 return PLATFORM_PSERIES;
2109#else
Benjamin Herrenschmidte8222502006-03-28 23:15:54 +11002110 return PLATFORM_GENERIC;
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002111#endif
2112}
2113
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002114static int __init prom_set_color(ihandle ih, int i, int r, int g, int b)
2115{
2116 return call_prom("call-method", 6, 1, ADDR("color!"), ih, i, b, g, r);
2117}
2118
2119/*
2120 * If we have a display that we don't know how to drive,
2121 * we will want to try to execute OF's open method for it
2122 * later. However, OF will probably fall over if we do that
2123 * we've taken over the MMU.
2124 * So we check whether we will need to open the display,
2125 * and if so, open it now.
2126 */
2127static void __init prom_check_displays(void)
2128{
2129 char type[16], *path;
2130 phandle node;
2131 ihandle ih;
2132 int i;
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002133
Benjamin Herrenschmidt7f995d32018-05-31 14:33:41 +10002134 static const unsigned char default_colors[] = {
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002135 0x00, 0x00, 0x00,
2136 0x00, 0x00, 0xaa,
2137 0x00, 0xaa, 0x00,
2138 0x00, 0xaa, 0xaa,
2139 0xaa, 0x00, 0x00,
2140 0xaa, 0x00, 0xaa,
2141 0xaa, 0xaa, 0x00,
2142 0xaa, 0xaa, 0xaa,
2143 0x55, 0x55, 0x55,
2144 0x55, 0x55, 0xff,
2145 0x55, 0xff, 0x55,
2146 0x55, 0xff, 0xff,
2147 0xff, 0x55, 0x55,
2148 0xff, 0x55, 0xff,
2149 0xff, 0xff, 0x55,
2150 0xff, 0xff, 0xff
2151 };
2152 const unsigned char *clut;
2153
Anton Blanchard4da727a2009-03-31 20:06:14 +00002154 prom_debug("Looking for displays\n");
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002155 for (node = 0; prom_next_node(&node); ) {
2156 memset(type, 0, sizeof(type));
2157 prom_getprop(node, "device_type", type, sizeof(type));
Anton Blanchard5827d412012-11-26 17:40:03 +00002158 if (strcmp(type, "display") != 0)
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002159 continue;
2160
2161 /* It seems OF doesn't null-terminate the path :-( */
Anton Blanchard5827d412012-11-26 17:40:03 +00002162 path = prom_scratch;
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002163 memset(path, 0, PROM_SCRATCH_SIZE);
2164
2165 /*
2166 * leave some room at the end of the path for appending extra
2167 * arguments
2168 */
2169 if (call_prom("package-to-path", 3, 1, node, path,
2170 PROM_SCRATCH_SIZE-10) == PROM_ERROR)
2171 continue;
Anton Blanchard1f8737a2009-03-31 20:06:15 +00002172 prom_printf("found display : %s, opening... ", path);
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002173
2174 ih = call_prom("open", 1, 1, path);
2175 if (ih == 0) {
2176 prom_printf("failed\n");
2177 continue;
2178 }
2179
2180 /* Success */
2181 prom_printf("done\n");
Paul Mackerrasa23414b2005-11-10 12:00:55 +11002182 prom_setprop(node, path, "linux,opened", NULL, 0);
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002183
2184 /* Setup a usable color table when the appropriate
2185 * method is available. Should update this to set-colors */
Anton Blanchard5827d412012-11-26 17:40:03 +00002186 clut = default_colors;
Benjamin Herrenschmidt3f536382011-12-14 13:55:11 +00002187 for (i = 0; i < 16; i++, clut += 3)
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002188 if (prom_set_color(ih, i, clut[0], clut[1],
2189 clut[2]) != 0)
2190 break;
2191
2192#ifdef CONFIG_LOGO_LINUX_CLUT224
Anton Blanchard5827d412012-11-26 17:40:03 +00002193 clut = PTRRELOC(logo_linux_clut224.clut);
2194 for (i = 0; i < logo_linux_clut224.clutsize; i++, clut += 3)
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002195 if (prom_set_color(ih, i + 32, clut[0], clut[1],
2196 clut[2]) != 0)
2197 break;
2198#endif /* CONFIG_LOGO_LINUX_CLUT224 */
Benjamin Herrenschmidt7191b612013-07-25 12:12:32 +10002199
2200#ifdef CONFIG_PPC_EARLY_DEBUG_BOOTX
2201 if (prom_getprop(node, "linux,boot-display", NULL, 0) !=
2202 PROM_ERROR) {
2203 u32 width, height, pitch, addr;
2204
2205 prom_printf("Setting btext !\n");
2206 prom_getprop(node, "width", &width, 4);
2207 prom_getprop(node, "height", &height, 4);
2208 prom_getprop(node, "linebytes", &pitch, 4);
2209 prom_getprop(node, "address", &addr, 4);
2210 prom_printf("W=%d H=%d LB=%d addr=0x%x\n",
2211 width, height, pitch, addr);
2212 btext_setup_display(width, height, 8, pitch, addr);
2213 }
2214#endif /* CONFIG_PPC_EARLY_DEBUG_BOOTX */
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002215 }
2216}
2217
2218
2219/* Return (relocated) pointer to this much memory: moves initrd if reqd. */
2220static void __init *make_room(unsigned long *mem_start, unsigned long *mem_end,
2221 unsigned long needed, unsigned long align)
2222{
2223 void *ret;
2224
2225 *mem_start = _ALIGN(*mem_start, align);
2226 while ((*mem_start + needed) > *mem_end) {
2227 unsigned long room, chunk;
2228
Mathieu Malaterreeae5f702018-04-06 22:12:19 +02002229 prom_debug("Chunk exhausted, claiming more at %lx...\n",
Anton Blanchard5827d412012-11-26 17:40:03 +00002230 alloc_bottom);
2231 room = alloc_top - alloc_bottom;
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002232 if (room > DEVTREE_CHUNK_SIZE)
2233 room = DEVTREE_CHUNK_SIZE;
2234 if (room < PAGE_SIZE)
Anton Blanchardfbafd722011-07-25 20:47:51 +00002235 prom_panic("No memory for flatten_device_tree "
2236 "(no room)\n");
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002237 chunk = alloc_up(room, 0);
2238 if (chunk == 0)
Anton Blanchardfbafd722011-07-25 20:47:51 +00002239 prom_panic("No memory for flatten_device_tree "
2240 "(claim failed)\n");
Anton Blanchard966728d2011-07-25 20:47:07 +00002241 *mem_end = chunk + room;
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002242 }
2243
2244 ret = (void *)*mem_start;
2245 *mem_start += needed;
2246
2247 return ret;
2248}
2249
Benjamin Herrenschmidt493adff2013-08-07 02:01:38 +10002250#define dt_push_token(token, mem_start, mem_end) do { \
2251 void *room = make_room(mem_start, mem_end, 4, 4); \
2252 *(__be32 *)room = cpu_to_be32(token); \
2253 } while(0)
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002254
2255static unsigned long __init dt_find_string(char *str)
2256{
2257 char *s, *os;
2258
Anton Blanchard5827d412012-11-26 17:40:03 +00002259 s = os = (char *)dt_string_start;
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002260 s += 4;
Anton Blanchard5827d412012-11-26 17:40:03 +00002261 while (s < (char *)dt_string_end) {
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002262 if (strcmp(s, str) == 0)
2263 return s - os;
2264 s += strlen(s) + 1;
2265 }
2266 return 0;
2267}
2268
2269/*
2270 * The Open Firmware 1275 specification states properties must be 31 bytes or
2271 * less, however not all firmwares obey this. Make it 64 bytes to be safe.
2272 */
2273#define MAX_PROPERTY_NAME 64
2274
2275static void __init scan_dt_build_strings(phandle node,
2276 unsigned long *mem_start,
2277 unsigned long *mem_end)
2278{
2279 char *prev_name, *namep, *sstart;
2280 unsigned long soff;
2281 phandle child;
2282
Anton Blanchard5827d412012-11-26 17:40:03 +00002283 sstart = (char *)dt_string_start;
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002284
2285 /* get and store all property names */
Anton Blanchard5827d412012-11-26 17:40:03 +00002286 prev_name = "";
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002287 for (;;) {
2288 /* 64 is max len of name including nul. */
2289 namep = make_room(mem_start, mem_end, MAX_PROPERTY_NAME, 1);
2290 if (call_prom("nextprop", 3, 1, node, prev_name, namep) != 1) {
2291 /* No more nodes: unwind alloc */
2292 *mem_start = (unsigned long)namep;
2293 break;
2294 }
2295
2296 /* skip "name" */
Anton Blanchard5827d412012-11-26 17:40:03 +00002297 if (strcmp(namep, "name") == 0) {
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002298 *mem_start = (unsigned long)namep;
Anton Blanchard5827d412012-11-26 17:40:03 +00002299 prev_name = "name";
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002300 continue;
2301 }
2302 /* get/create string entry */
2303 soff = dt_find_string(namep);
2304 if (soff != 0) {
2305 *mem_start = (unsigned long)namep;
2306 namep = sstart + soff;
2307 } else {
2308 /* Trim off some if we can */
2309 *mem_start = (unsigned long)namep + strlen(namep) + 1;
Anton Blanchard5827d412012-11-26 17:40:03 +00002310 dt_string_end = *mem_start;
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002311 }
2312 prev_name = namep;
2313 }
2314
2315 /* do all our children */
2316 child = call_prom("child", 1, 1, node);
2317 while (child != 0) {
2318 scan_dt_build_strings(child, mem_start, mem_end);
2319 child = call_prom("peer", 1, 1, child);
2320 }
2321}
2322
2323static void __init scan_dt_build_struct(phandle node, unsigned long *mem_start,
2324 unsigned long *mem_end)
2325{
2326 phandle child;
2327 char *namep, *prev_name, *sstart, *p, *ep, *lp, *path;
2328 unsigned long soff;
2329 unsigned char *valp;
2330 static char pname[MAX_PROPERTY_NAME];
Benjamin Herrenschmidt6e35d5d2011-09-19 18:28:01 +00002331 int l, room, has_phandle = 0;
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002332
2333 dt_push_token(OF_DT_BEGIN_NODE, mem_start, mem_end);
2334
2335 /* get the node's full name */
2336 namep = (char *)*mem_start;
Paul Mackerrasc49888202005-10-26 21:52:53 +10002337 room = *mem_end - *mem_start;
2338 if (room > 255)
2339 room = 255;
2340 l = call_prom("package-to-path", 3, 1, node, namep, room);
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002341 if (l >= 0) {
2342 /* Didn't fit? Get more room. */
Paul Mackerrasc49888202005-10-26 21:52:53 +10002343 if (l >= room) {
2344 if (l >= *mem_end - *mem_start)
2345 namep = make_room(mem_start, mem_end, l+1, 1);
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002346 call_prom("package-to-path", 3, 1, node, namep, l);
2347 }
2348 namep[l] = '\0';
2349
2350 /* Fixup an Apple bug where they have bogus \0 chars in the
Paul Mackerrasa575b802005-10-23 17:23:21 +10002351 * middle of the path in some properties, and extract
2352 * the unit name (everything after the last '/').
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002353 */
Paul Mackerrasa575b802005-10-23 17:23:21 +10002354 for (lp = p = namep, ep = namep + l; p < ep; p++) {
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002355 if (*p == '/')
Paul Mackerrasa575b802005-10-23 17:23:21 +10002356 lp = namep;
2357 else if (*p != 0)
2358 *lp++ = *p;
2359 }
2360 *lp = 0;
2361 *mem_start = _ALIGN((unsigned long)lp + 1, 4);
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002362 }
2363
2364 /* get it again for debugging */
Anton Blanchard5827d412012-11-26 17:40:03 +00002365 path = prom_scratch;
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002366 memset(path, 0, PROM_SCRATCH_SIZE);
2367 call_prom("package-to-path", 3, 1, node, path, PROM_SCRATCH_SIZE-1);
2368
2369 /* get and store all properties */
Anton Blanchard5827d412012-11-26 17:40:03 +00002370 prev_name = "";
2371 sstart = (char *)dt_string_start;
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002372 for (;;) {
2373 if (call_prom("nextprop", 3, 1, node, prev_name,
Anton Blanchard5827d412012-11-26 17:40:03 +00002374 pname) != 1)
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002375 break;
2376
2377 /* skip "name" */
Anton Blanchard5827d412012-11-26 17:40:03 +00002378 if (strcmp(pname, "name") == 0) {
2379 prev_name = "name";
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002380 continue;
2381 }
2382
2383 /* find string offset */
Anton Blanchard5827d412012-11-26 17:40:03 +00002384 soff = dt_find_string(pname);
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002385 if (soff == 0) {
2386 prom_printf("WARNING: Can't find string index for"
Anton Blanchard5827d412012-11-26 17:40:03 +00002387 " <%s>, node %s\n", pname, path);
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002388 break;
2389 }
2390 prev_name = sstart + soff;
2391
2392 /* get length */
Anton Blanchard5827d412012-11-26 17:40:03 +00002393 l = call_prom("getproplen", 2, 1, node, pname);
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002394
2395 /* sanity checks */
2396 if (l == PROM_ERROR)
2397 continue;
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002398
2399 /* push property head */
2400 dt_push_token(OF_DT_PROP, mem_start, mem_end);
2401 dt_push_token(l, mem_start, mem_end);
2402 dt_push_token(soff, mem_start, mem_end);
2403
2404 /* push property content */
2405 valp = make_room(mem_start, mem_end, l, 4);
Anton Blanchard5827d412012-11-26 17:40:03 +00002406 call_prom("getprop", 4, 1, node, pname, valp, l);
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002407 *mem_start = _ALIGN(*mem_start, 4);
Benjamin Herrenschmidt6e35d5d2011-09-19 18:28:01 +00002408
Anton Blanchard5827d412012-11-26 17:40:03 +00002409 if (!strcmp(pname, "phandle"))
Benjamin Herrenschmidt6e35d5d2011-09-19 18:28:01 +00002410 has_phandle = 1;
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002411 }
2412
Benjamin Herrenschmidt6e35d5d2011-09-19 18:28:01 +00002413 /* Add a "linux,phandle" property if no "phandle" property already
Benjamin Herrenschmidt11fdb302018-10-15 13:49:53 +11002414 * existed.
Benjamin Herrenschmidt6e35d5d2011-09-19 18:28:01 +00002415 */
2416 if (!has_phandle) {
Anton Blanchard5827d412012-11-26 17:40:03 +00002417 soff = dt_find_string("linux,phandle");
Benjamin Herrenschmidt6e35d5d2011-09-19 18:28:01 +00002418 if (soff == 0)
2419 prom_printf("WARNING: Can't find string index for"
2420 " <linux-phandle> node %s\n", path);
2421 else {
2422 dt_push_token(OF_DT_PROP, mem_start, mem_end);
2423 dt_push_token(4, mem_start, mem_end);
2424 dt_push_token(soff, mem_start, mem_end);
2425 valp = make_room(mem_start, mem_end, 4, 4);
Benjamin Herrenschmidt493adff2013-08-07 02:01:38 +10002426 *(__be32 *)valp = cpu_to_be32(node);
Benjamin Herrenschmidt6e35d5d2011-09-19 18:28:01 +00002427 }
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002428 }
2429
2430 /* do all our children */
2431 child = call_prom("child", 1, 1, node);
2432 while (child != 0) {
2433 scan_dt_build_struct(child, mem_start, mem_end);
2434 child = call_prom("peer", 1, 1, child);
2435 }
2436
2437 dt_push_token(OF_DT_END_NODE, mem_start, mem_end);
2438}
2439
2440static void __init flatten_device_tree(void)
2441{
2442 phandle root;
2443 unsigned long mem_start, mem_end, room;
2444 struct boot_param_header *hdr;
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002445 char *namep;
2446 u64 *rsvmap;
2447
2448 /*
2449 * Check how much room we have between alloc top & bottom (+/- a
Anton Blanchardfbafd722011-07-25 20:47:51 +00002450 * few pages), crop to 1MB, as this is our "chunk" size
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002451 */
Anton Blanchard5827d412012-11-26 17:40:03 +00002452 room = alloc_top - alloc_bottom - 0x4000;
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002453 if (room > DEVTREE_CHUNK_SIZE)
2454 room = DEVTREE_CHUNK_SIZE;
Mathieu Malaterreeae5f702018-04-06 22:12:19 +02002455 prom_debug("starting device tree allocs at %lx\n", alloc_bottom);
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002456
2457 /* Now try to claim that */
2458 mem_start = (unsigned long)alloc_up(room, PAGE_SIZE);
2459 if (mem_start == 0)
2460 prom_panic("Can't allocate initial device-tree chunk\n");
Anton Blanchard966728d2011-07-25 20:47:07 +00002461 mem_end = mem_start + room;
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002462
2463 /* Get root of tree */
2464 root = call_prom("peer", 1, 1, (phandle)0);
2465 if (root == (phandle)0)
2466 prom_panic ("couldn't get device tree root\n");
2467
2468 /* Build header and make room for mem rsv map */
2469 mem_start = _ALIGN(mem_start, 4);
2470 hdr = make_room(&mem_start, &mem_end,
2471 sizeof(struct boot_param_header), 4);
Anton Blanchard5827d412012-11-26 17:40:03 +00002472 dt_header_start = (unsigned long)hdr;
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002473 rsvmap = make_room(&mem_start, &mem_end, sizeof(mem_reserve_map), 8);
2474
2475 /* Start of strings */
2476 mem_start = PAGE_ALIGN(mem_start);
Anton Blanchard5827d412012-11-26 17:40:03 +00002477 dt_string_start = mem_start;
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002478 mem_start += 4; /* hole */
2479
2480 /* Add "linux,phandle" in there, we'll need it */
2481 namep = make_room(&mem_start, &mem_end, 16, 1);
Anton Blanchard5827d412012-11-26 17:40:03 +00002482 strcpy(namep, "linux,phandle");
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002483 mem_start = (unsigned long)namep + strlen(namep) + 1;
2484
2485 /* Build string array */
2486 prom_printf("Building dt strings...\n");
2487 scan_dt_build_strings(root, &mem_start, &mem_end);
Anton Blanchard5827d412012-11-26 17:40:03 +00002488 dt_string_end = mem_start;
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002489
2490 /* Build structure */
2491 mem_start = PAGE_ALIGN(mem_start);
Anton Blanchard5827d412012-11-26 17:40:03 +00002492 dt_struct_start = mem_start;
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002493 prom_printf("Building dt structure...\n");
2494 scan_dt_build_struct(root, &mem_start, &mem_end);
2495 dt_push_token(OF_DT_END, &mem_start, &mem_end);
Anton Blanchard5827d412012-11-26 17:40:03 +00002496 dt_struct_end = PAGE_ALIGN(mem_start);
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002497
2498 /* Finish header */
Benjamin Herrenschmidt493adff2013-08-07 02:01:38 +10002499 hdr->boot_cpuid_phys = cpu_to_be32(prom.cpu);
2500 hdr->magic = cpu_to_be32(OF_DT_HEADER);
2501 hdr->totalsize = cpu_to_be32(dt_struct_end - dt_header_start);
2502 hdr->off_dt_struct = cpu_to_be32(dt_struct_start - dt_header_start);
2503 hdr->off_dt_strings = cpu_to_be32(dt_string_start - dt_header_start);
2504 hdr->dt_strings_size = cpu_to_be32(dt_string_end - dt_string_start);
2505 hdr->off_mem_rsvmap = cpu_to_be32(((unsigned long)rsvmap) - dt_header_start);
2506 hdr->version = cpu_to_be32(OF_DT_VERSION);
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002507 /* Version 16 is not backward compatible */
Benjamin Herrenschmidt493adff2013-08-07 02:01:38 +10002508 hdr->last_comp_version = cpu_to_be32(0x10);
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002509
Jimi Xenidis4d1f3f22006-05-18 17:03:05 -05002510 /* Copy the reserve map in */
Anton Blanchard5827d412012-11-26 17:40:03 +00002511 memcpy(rsvmap, mem_reserve_map, sizeof(mem_reserve_map));
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002512
2513#ifdef DEBUG_PROM
2514 {
2515 int i;
2516 prom_printf("reserved memory map:\n");
Anton Blanchard5827d412012-11-26 17:40:03 +00002517 for (i = 0; i < mem_reserve_cnt; i++)
Mathieu Malaterreeae5f702018-04-06 22:12:19 +02002518 prom_printf(" %llx - %llx\n",
Benjamin Herrenschmidt493adff2013-08-07 02:01:38 +10002519 be64_to_cpu(mem_reserve_map[i].base),
2520 be64_to_cpu(mem_reserve_map[i].size));
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002521 }
2522#endif
Jimi Xenidis4d1f3f22006-05-18 17:03:05 -05002523 /* Bump mem_reserve_cnt to cause further reservations to fail
2524 * since it's too late.
2525 */
Anton Blanchard5827d412012-11-26 17:40:03 +00002526 mem_reserve_cnt = MEM_RESERVE_MAP_SIZE;
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002527
Mathieu Malaterreeae5f702018-04-06 22:12:19 +02002528 prom_printf("Device tree strings 0x%lx -> 0x%lx\n",
Anton Blanchard5827d412012-11-26 17:40:03 +00002529 dt_string_start, dt_string_end);
Mathieu Malaterreeae5f702018-04-06 22:12:19 +02002530 prom_printf("Device tree struct 0x%lx -> 0x%lx\n",
Anton Blanchard5827d412012-11-26 17:40:03 +00002531 dt_struct_start, dt_struct_end);
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002532}
2533
Hollis Blanchard54f4ee12006-05-25 16:36:53 -05002534#ifdef CONFIG_PPC_MAPLE
2535/* PIBS Version 1.05.0000 04/26/2005 has an incorrect /ht/isa/ranges property.
2536 * The values are bad, and it doesn't even have the right number of cells. */
2537static void __init fixup_device_tree_maple(void)
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002538{
Hollis Blanchard54f4ee12006-05-25 16:36:53 -05002539 phandle isa;
Benjamin Herrenschmidt980a6512006-07-03 17:22:05 +10002540 u32 rloc = 0x01002000; /* IO space; PCI device = 4 */
Hollis Blanchard54f4ee12006-05-25 16:36:53 -05002541 u32 isa_ranges[6];
Benjamin Herrenschmidt980a6512006-07-03 17:22:05 +10002542 char *name;
Hollis Blanchard54f4ee12006-05-25 16:36:53 -05002543
Benjamin Herrenschmidt980a6512006-07-03 17:22:05 +10002544 name = "/ht@0/isa@4";
2545 isa = call_prom("finddevice", 1, 1, ADDR(name));
2546 if (!PHANDLE_VALID(isa)) {
2547 name = "/ht@0/isa@6";
2548 isa = call_prom("finddevice", 1, 1, ADDR(name));
2549 rloc = 0x01003000; /* IO space; PCI device = 6 */
2550 }
Hollis Blanchard54f4ee12006-05-25 16:36:53 -05002551 if (!PHANDLE_VALID(isa))
2552 return;
2553
Benjamin Herrenschmidt980a6512006-07-03 17:22:05 +10002554 if (prom_getproplen(isa, "ranges") != 12)
2555 return;
Hollis Blanchard54f4ee12006-05-25 16:36:53 -05002556 if (prom_getprop(isa, "ranges", isa_ranges, sizeof(isa_ranges))
2557 == PROM_ERROR)
2558 return;
2559
2560 if (isa_ranges[0] != 0x1 ||
2561 isa_ranges[1] != 0xf4000000 ||
2562 isa_ranges[2] != 0x00010000)
2563 return;
2564
Benjamin Herrenschmidt980a6512006-07-03 17:22:05 +10002565 prom_printf("Fixing up bogus ISA range on Maple/Apache...\n");
Hollis Blanchard54f4ee12006-05-25 16:36:53 -05002566
2567 isa_ranges[0] = 0x1;
2568 isa_ranges[1] = 0x0;
Benjamin Herrenschmidt980a6512006-07-03 17:22:05 +10002569 isa_ranges[2] = rloc;
Hollis Blanchard54f4ee12006-05-25 16:36:53 -05002570 isa_ranges[3] = 0x0;
2571 isa_ranges[4] = 0x0;
2572 isa_ranges[5] = 0x00010000;
Benjamin Herrenschmidt980a6512006-07-03 17:22:05 +10002573 prom_setprop(isa, name, "ranges",
Hollis Blanchard54f4ee12006-05-25 16:36:53 -05002574 isa_ranges, sizeof(isa_ranges));
2575}
Harry Ciao8f101a052009-06-17 16:28:00 -07002576
2577#define CPC925_MC_START 0xf8000000
2578#define CPC925_MC_LENGTH 0x1000000
2579/* The values for memory-controller don't have right number of cells */
2580static void __init fixup_device_tree_maple_memory_controller(void)
2581{
2582 phandle mc;
2583 u32 mc_reg[4];
2584 char *name = "/hostbridge@f8000000";
Harry Ciao8f101a052009-06-17 16:28:00 -07002585 u32 ac, sc;
2586
2587 mc = call_prom("finddevice", 1, 1, ADDR(name));
2588 if (!PHANDLE_VALID(mc))
2589 return;
2590
2591 if (prom_getproplen(mc, "reg") != 8)
2592 return;
2593
Anton Blanchard5827d412012-11-26 17:40:03 +00002594 prom_getprop(prom.root, "#address-cells", &ac, sizeof(ac));
2595 prom_getprop(prom.root, "#size-cells", &sc, sizeof(sc));
Harry Ciao8f101a052009-06-17 16:28:00 -07002596 if ((ac != 2) || (sc != 2))
2597 return;
2598
2599 if (prom_getprop(mc, "reg", mc_reg, sizeof(mc_reg)) == PROM_ERROR)
2600 return;
2601
2602 if (mc_reg[0] != CPC925_MC_START || mc_reg[1] != CPC925_MC_LENGTH)
2603 return;
2604
2605 prom_printf("Fixing up bogus hostbridge on Maple...\n");
2606
2607 mc_reg[0] = 0x0;
2608 mc_reg[1] = CPC925_MC_START;
2609 mc_reg[2] = 0x0;
2610 mc_reg[3] = CPC925_MC_LENGTH;
2611 prom_setprop(mc, name, "reg", mc_reg, sizeof(mc_reg));
2612}
Hollis Blanchard54f4ee12006-05-25 16:36:53 -05002613#else
2614#define fixup_device_tree_maple()
Harry Ciao8f101a052009-06-17 16:28:00 -07002615#define fixup_device_tree_maple_memory_controller()
Hollis Blanchard54f4ee12006-05-25 16:36:53 -05002616#endif
2617
Benjamin Herrenschmidte8c0acf2006-07-04 14:06:29 +10002618#ifdef CONFIG_PPC_CHRP
Olaf Heringe4805922007-04-04 18:20:04 +02002619/*
2620 * Pegasos and BriQ lacks the "ranges" property in the isa node
2621 * Pegasos needs decimal IRQ 14/15, not hexadecimal
Olaf Hering556ecf9b2007-08-18 04:27:17 +10002622 * Pegasos has the IDE configured in legacy mode, but advertised as native
Olaf Heringe4805922007-04-04 18:20:04 +02002623 */
Benjamin Herrenschmidte8c0acf2006-07-04 14:06:29 +10002624static void __init fixup_device_tree_chrp(void)
2625{
Olaf Heringe4805922007-04-04 18:20:04 +02002626 phandle ph;
2627 u32 prop[6];
Benjamin Herrenschmidt26c50322006-07-04 14:16:28 +10002628 u32 rloc = 0x01006000; /* IO space; PCI device = 12 */
Benjamin Herrenschmidte8c0acf2006-07-04 14:06:29 +10002629 char *name;
2630 int rc;
2631
2632 name = "/pci@80000000/isa@c";
Olaf Heringe4805922007-04-04 18:20:04 +02002633 ph = call_prom("finddevice", 1, 1, ADDR(name));
2634 if (!PHANDLE_VALID(ph)) {
Benjamin Herrenschmidt26c50322006-07-04 14:16:28 +10002635 name = "/pci@ff500000/isa@6";
Olaf Heringe4805922007-04-04 18:20:04 +02002636 ph = call_prom("finddevice", 1, 1, ADDR(name));
Benjamin Herrenschmidt26c50322006-07-04 14:16:28 +10002637 rloc = 0x01003000; /* IO space; PCI device = 6 */
2638 }
Olaf Heringe4805922007-04-04 18:20:04 +02002639 if (PHANDLE_VALID(ph)) {
2640 rc = prom_getproplen(ph, "ranges");
2641 if (rc == 0 || rc == PROM_ERROR) {
2642 prom_printf("Fixing up missing ISA range on Pegasos...\n");
Benjamin Herrenschmidte8c0acf2006-07-04 14:06:29 +10002643
Olaf Heringe4805922007-04-04 18:20:04 +02002644 prop[0] = 0x1;
2645 prop[1] = 0x0;
2646 prop[2] = rloc;
2647 prop[3] = 0x0;
2648 prop[4] = 0x0;
2649 prop[5] = 0x00010000;
2650 prom_setprop(ph, name, "ranges", prop, sizeof(prop));
2651 }
2652 }
Benjamin Herrenschmidte8c0acf2006-07-04 14:06:29 +10002653
Olaf Heringe4805922007-04-04 18:20:04 +02002654 name = "/pci@80000000/ide@C,1";
2655 ph = call_prom("finddevice", 1, 1, ADDR(name));
2656 if (PHANDLE_VALID(ph)) {
2657 prom_printf("Fixing up IDE interrupt on Pegasos...\n");
2658 prop[0] = 14;
2659 prop[1] = 0x0;
Olaf Hering556ecf9b2007-08-18 04:27:17 +10002660 prom_setprop(ph, name, "interrupts", prop, 2*sizeof(u32));
2661 prom_printf("Fixing up IDE class-code on Pegasos...\n");
2662 rc = prom_getprop(ph, "class-code", prop, sizeof(u32));
2663 if (rc == sizeof(u32)) {
2664 prop[0] &= ~0x5;
2665 prom_setprop(ph, name, "class-code", prop, sizeof(u32));
2666 }
Olaf Heringe4805922007-04-04 18:20:04 +02002667 }
Benjamin Herrenschmidte8c0acf2006-07-04 14:06:29 +10002668}
2669#else
2670#define fixup_device_tree_chrp()
2671#endif
2672
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002673#if defined(CONFIG_PPC64) && defined(CONFIG_PPC_PMAC)
Hollis Blanchard54f4ee12006-05-25 16:36:53 -05002674static void __init fixup_device_tree_pmac(void)
2675{
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002676 phandle u3, i2c, mpic;
2677 u32 u3_rev;
2678 u32 interrupts[2];
2679 u32 parent;
2680
2681 /* Some G5s have a missing interrupt definition, fix it up here */
2682 u3 = call_prom("finddevice", 1, 1, ADDR("/u3@0,f8000000"));
2683 if (!PHANDLE_VALID(u3))
2684 return;
2685 i2c = call_prom("finddevice", 1, 1, ADDR("/u3@0,f8000000/i2c@f8001000"));
2686 if (!PHANDLE_VALID(i2c))
2687 return;
2688 mpic = call_prom("finddevice", 1, 1, ADDR("/u3@0,f8000000/mpic@f8040000"));
2689 if (!PHANDLE_VALID(mpic))
2690 return;
2691
2692 /* check if proper rev of u3 */
2693 if (prom_getprop(u3, "device-rev", &u3_rev, sizeof(u3_rev))
2694 == PROM_ERROR)
2695 return;
Benjamin Herrenschmidt7d496972005-11-07 14:36:21 +11002696 if (u3_rev < 0x35 || u3_rev > 0x39)
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002697 return;
2698 /* does it need fixup ? */
2699 if (prom_getproplen(i2c, "interrupts") > 0)
2700 return;
2701
2702 prom_printf("fixing up bogus interrupts for u3 i2c...\n");
2703
2704 /* interrupt on this revision of u3 is number 0 and level */
2705 interrupts[0] = 0;
2706 interrupts[1] = 1;
Paul Mackerrasa23414b2005-11-10 12:00:55 +11002707 prom_setprop(i2c, "/u3@0,f8000000/i2c@f8001000", "interrupts",
2708 &interrupts, sizeof(interrupts));
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002709 parent = (u32)mpic;
Paul Mackerrasa23414b2005-11-10 12:00:55 +11002710 prom_setprop(i2c, "/u3@0,f8000000/i2c@f8001000", "interrupt-parent",
2711 &parent, sizeof(parent));
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002712}
Hollis Blanchard54f4ee12006-05-25 16:36:53 -05002713#else
2714#define fixup_device_tree_pmac()
2715#endif
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002716
Sylvain Munaut88fd2a92007-02-12 23:13:20 +01002717#ifdef CONFIG_PPC_EFIKA
Grant Likely94d2dde2008-01-24 22:25:32 -07002718/*
2719 * The MPC5200 FEC driver requires an phy-handle property to tell it how
2720 * to talk to the phy. If the phy-handle property is missing, then this
2721 * function is called to add the appropriate nodes and link it to the
2722 * ethernet node.
2723 */
2724static void __init fixup_device_tree_efika_add_phy(void)
Sylvain Munaut88fd2a92007-02-12 23:13:20 +01002725{
Sylvain Munaut88fd2a92007-02-12 23:13:20 +01002726 u32 node;
2727 char prop[64];
Grant Likely94d2dde2008-01-24 22:25:32 -07002728 int rv;
Sylvain Munaut88fd2a92007-02-12 23:13:20 +01002729
Grant Likely94d2dde2008-01-24 22:25:32 -07002730 /* Check if /builtin/ethernet exists - bail if it doesn't */
2731 node = call_prom("finddevice", 1, 1, ADDR("/builtin/ethernet"));
Sylvain Munaut88fd2a92007-02-12 23:13:20 +01002732 if (!PHANDLE_VALID(node))
2733 return;
2734
Grant Likely94d2dde2008-01-24 22:25:32 -07002735 /* Check if the phy-handle property exists - bail if it does */
2736 rv = prom_getprop(node, "phy-handle", prop, sizeof(prop));
2737 if (!rv)
Sylvain Munaut88fd2a92007-02-12 23:13:20 +01002738 return;
2739
Grant Likely94d2dde2008-01-24 22:25:32 -07002740 /*
2741 * At this point the ethernet device doesn't have a phy described.
2742 * Now we need to add the missing phy node and linkage
2743 */
Sylvain Munaut88fd2a92007-02-12 23:13:20 +01002744
Grant Likely94d2dde2008-01-24 22:25:32 -07002745 /* Check for an MDIO bus node - if missing then create one */
Olaf Hering6f4347c2008-01-10 01:06:08 +11002746 node = call_prom("finddevice", 1, 1, ADDR("/builtin/mdio"));
2747 if (!PHANDLE_VALID(node)) {
2748 prom_printf("Adding Ethernet MDIO node\n");
2749 call_prom("interpret", 1, 1,
2750 " s\" /builtin\" find-device"
2751 " new-device"
2752 " 1 encode-int s\" #address-cells\" property"
2753 " 0 encode-int s\" #size-cells\" property"
Grant Likely94d2dde2008-01-24 22:25:32 -07002754 " s\" mdio\" device-name"
2755 " s\" fsl,mpc5200b-mdio\" encode-string"
Olaf Hering6f4347c2008-01-10 01:06:08 +11002756 " s\" compatible\" property"
2757 " 0xf0003000 0x400 reg"
2758 " 0x2 encode-int"
2759 " 0x5 encode-int encode+"
2760 " 0x3 encode-int encode+"
2761 " s\" interrupts\" property"
2762 " finish-device");
2763 };
2764
Grant Likely94d2dde2008-01-24 22:25:32 -07002765 /* Check for a PHY device node - if missing then create one and
2766 * give it's phandle to the ethernet node */
2767 node = call_prom("finddevice", 1, 1,
2768 ADDR("/builtin/mdio/ethernet-phy"));
Olaf Hering6f4347c2008-01-10 01:06:08 +11002769 if (!PHANDLE_VALID(node)) {
2770 prom_printf("Adding Ethernet PHY node\n");
2771 call_prom("interpret", 1, 1,
2772 " s\" /builtin/mdio\" find-device"
2773 " new-device"
2774 " s\" ethernet-phy\" device-name"
2775 " 0x10 encode-int s\" reg\" property"
2776 " my-self"
2777 " ihandle>phandle"
2778 " finish-device"
2779 " s\" /builtin/ethernet\" find-device"
2780 " encode-int"
2781 " s\" phy-handle\" property"
2782 " device-end");
2783 }
Grant Likely94d2dde2008-01-24 22:25:32 -07002784}
Olaf Hering6f4347c2008-01-10 01:06:08 +11002785
Grant Likely94d2dde2008-01-24 22:25:32 -07002786static void __init fixup_device_tree_efika(void)
2787{
2788 int sound_irq[3] = { 2, 2, 0 };
2789 int bcomm_irq[3*16] = { 3,0,0, 3,1,0, 3,2,0, 3,3,0,
2790 3,4,0, 3,5,0, 3,6,0, 3,7,0,
2791 3,8,0, 3,9,0, 3,10,0, 3,11,0,
2792 3,12,0, 3,13,0, 3,14,0, 3,15,0 };
2793 u32 node;
2794 char prop[64];
2795 int rv, len;
2796
2797 /* Check if we're really running on a EFIKA */
2798 node = call_prom("finddevice", 1, 1, ADDR("/"));
2799 if (!PHANDLE_VALID(node))
2800 return;
2801
2802 rv = prom_getprop(node, "model", prop, sizeof(prop));
2803 if (rv == PROM_ERROR)
2804 return;
2805 if (strcmp(prop, "EFIKA5K2"))
2806 return;
2807
2808 prom_printf("Applying EFIKA device tree fixups\n");
2809
2810 /* Claiming to be 'chrp' is death */
2811 node = call_prom("finddevice", 1, 1, ADDR("/"));
2812 rv = prom_getprop(node, "device_type", prop, sizeof(prop));
2813 if (rv != PROM_ERROR && (strcmp(prop, "chrp") == 0))
2814 prom_setprop(node, "/", "device_type", "efika", sizeof("efika"));
2815
David Woodhouse7f4392c2008-04-14 02:52:38 +10002816 /* CODEGEN,description is exposed in /proc/cpuinfo so
2817 fix that too */
2818 rv = prom_getprop(node, "CODEGEN,description", prop, sizeof(prop));
2819 if (rv != PROM_ERROR && (strstr(prop, "CHRP")))
2820 prom_setprop(node, "/", "CODEGEN,description",
2821 "Efika 5200B PowerPC System",
2822 sizeof("Efika 5200B PowerPC System"));
2823
Grant Likely94d2dde2008-01-24 22:25:32 -07002824 /* Fixup bestcomm interrupts property */
2825 node = call_prom("finddevice", 1, 1, ADDR("/builtin/bestcomm"));
2826 if (PHANDLE_VALID(node)) {
2827 len = prom_getproplen(node, "interrupts");
2828 if (len == 12) {
2829 prom_printf("Fixing bestcomm interrupts property\n");
2830 prom_setprop(node, "/builtin/bestcom", "interrupts",
2831 bcomm_irq, sizeof(bcomm_irq));
2832 }
2833 }
2834
2835 /* Fixup sound interrupts property */
2836 node = call_prom("finddevice", 1, 1, ADDR("/builtin/sound"));
2837 if (PHANDLE_VALID(node)) {
2838 rv = prom_getprop(node, "interrupts", prop, sizeof(prop));
2839 if (rv == PROM_ERROR) {
2840 prom_printf("Adding sound interrupts property\n");
2841 prom_setprop(node, "/builtin/sound", "interrupts",
2842 sound_irq, sizeof(sound_irq));
2843 }
2844 }
2845
2846 /* Make sure ethernet phy-handle property exists */
2847 fixup_device_tree_efika_add_phy();
Sylvain Munaut88fd2a92007-02-12 23:13:20 +01002848}
2849#else
2850#define fixup_device_tree_efika()
2851#endif
2852
Darren Stevens50246782016-08-31 13:24:40 +01002853#ifdef CONFIG_PPC_PASEMI_NEMO
2854/*
2855 * CFE supplied on Nemo is broken in several ways, biggest
2856 * problem is that it reassigns ISA interrupts to unused mpic ints.
2857 * Add an interrupt-controller property for the io-bridge to use
2858 * and correct the ints so we can attach them to an irq_domain
2859 */
2860static void __init fixup_device_tree_pasemi(void)
2861{
2862 u32 interrupts[2], parent, rval, val = 0;
2863 char *name, *pci_name;
2864 phandle iob, node;
2865
2866 /* Find the root pci node */
2867 name = "/pxp@0,e0000000";
2868 iob = call_prom("finddevice", 1, 1, ADDR(name));
2869 if (!PHANDLE_VALID(iob))
2870 return;
2871
2872 /* check if interrupt-controller node set yet */
2873 if (prom_getproplen(iob, "interrupt-controller") !=PROM_ERROR)
2874 return;
2875
2876 prom_printf("adding interrupt-controller property for SB600...\n");
2877
2878 prom_setprop(iob, name, "interrupt-controller", &val, 0);
2879
2880 pci_name = "/pxp@0,e0000000/pci@11";
2881 node = call_prom("finddevice", 1, 1, ADDR(pci_name));
2882 parent = ADDR(iob);
2883
2884 for( ; prom_next_node(&node); ) {
2885 /* scan each node for one with an interrupt */
2886 if (!PHANDLE_VALID(node))
2887 continue;
2888
2889 rval = prom_getproplen(node, "interrupts");
2890 if (rval == 0 || rval == PROM_ERROR)
2891 continue;
2892
2893 prom_getprop(node, "interrupts", &interrupts, sizeof(interrupts));
2894 if ((interrupts[0] < 212) || (interrupts[0] > 222))
2895 continue;
2896
2897 /* found a node, update both interrupts and interrupt-parent */
2898 if ((interrupts[0] >= 212) && (interrupts[0] <= 215))
2899 interrupts[0] -= 203;
2900 if ((interrupts[0] >= 216) && (interrupts[0] <= 220))
2901 interrupts[0] -= 213;
2902 if (interrupts[0] == 221)
2903 interrupts[0] = 14;
2904 if (interrupts[0] == 222)
2905 interrupts[0] = 8;
2906
2907 prom_setprop(node, pci_name, "interrupts", interrupts,
2908 sizeof(interrupts));
2909 prom_setprop(node, pci_name, "interrupt-parent", &parent,
2910 sizeof(parent));
2911 }
Darren Stevens687e16b2016-08-31 13:24:45 +01002912
2913 /*
2914 * The io-bridge has device_type set to 'io-bridge' change it to 'isa'
2915 * so that generic isa-bridge code can add the SB600 and its on-board
2916 * peripherals.
2917 */
2918 name = "/pxp@0,e0000000/io-bridge@0";
2919 iob = call_prom("finddevice", 1, 1, ADDR(name));
2920 if (!PHANDLE_VALID(iob))
2921 return;
2922
2923 /* device_type is already set, just change it. */
2924
2925 prom_printf("Changing device_type of SB600 node...\n");
2926
2927 prom_setprop(iob, name, "device_type", "isa", sizeof("isa"));
Darren Stevens50246782016-08-31 13:24:40 +01002928}
2929#else /* !CONFIG_PPC_PASEMI_NEMO */
2930static inline void fixup_device_tree_pasemi(void) { }
2931#endif
2932
Hollis Blanchard54f4ee12006-05-25 16:36:53 -05002933static void __init fixup_device_tree(void)
2934{
2935 fixup_device_tree_maple();
Harry Ciao8f101a052009-06-17 16:28:00 -07002936 fixup_device_tree_maple_memory_controller();
Benjamin Herrenschmidte8c0acf2006-07-04 14:06:29 +10002937 fixup_device_tree_chrp();
Hollis Blanchard54f4ee12006-05-25 16:36:53 -05002938 fixup_device_tree_pmac();
Sylvain Munaut88fd2a92007-02-12 23:13:20 +01002939 fixup_device_tree_efika();
Darren Stevens50246782016-08-31 13:24:40 +01002940 fixup_device_tree_pasemi();
Hollis Blanchard54f4ee12006-05-25 16:36:53 -05002941}
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002942
2943static void __init prom_find_boot_cpu(void)
2944{
Benjamin Herrenschmidt493adff2013-08-07 02:01:38 +10002945 __be32 rval;
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002946 ihandle prom_cpu;
2947 phandle cpu_pkg;
2948
Benjamin Herrenschmidt493adff2013-08-07 02:01:38 +10002949 rval = 0;
2950 if (prom_getprop(prom.chosen, "cpu", &rval, sizeof(rval)) <= 0)
Paul Mackerrasa575b802005-10-23 17:23:21 +10002951 return;
Benjamin Herrenschmidt493adff2013-08-07 02:01:38 +10002952 prom_cpu = be32_to_cpu(rval);
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002953
2954 cpu_pkg = call_prom("instance-to-package", 1, 1, prom_cpu);
2955
Darren Stevensaf2b7fa2017-01-23 19:42:54 +00002956 if (!PHANDLE_VALID(cpu_pkg))
2957 return;
2958
Benjamin Herrenschmidt493adff2013-08-07 02:01:38 +10002959 prom_getprop(cpu_pkg, "reg", &rval, sizeof(rval));
2960 prom.cpu = be32_to_cpu(rval);
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002961
Mathieu Malaterreeae5f702018-04-06 22:12:19 +02002962 prom_debug("Booting CPU hw index = %d\n", prom.cpu);
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002963}
2964
2965static void __init prom_check_initrd(unsigned long r3, unsigned long r4)
2966{
2967#ifdef CONFIG_BLK_DEV_INITRD
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002968 if (r3 && r4 && r4 != 0xdeadbeef) {
Benjamin Herrenschmidt493adff2013-08-07 02:01:38 +10002969 __be64 val;
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002970
Anton Blanchard5827d412012-11-26 17:40:03 +00002971 prom_initrd_start = is_kernel_addr(r3) ? __pa(r3) : r3;
2972 prom_initrd_end = prom_initrd_start + r4;
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002973
Benjamin Herrenschmidt493adff2013-08-07 02:01:38 +10002974 val = cpu_to_be64(prom_initrd_start);
Anton Blanchard5827d412012-11-26 17:40:03 +00002975 prom_setprop(prom.chosen, "/chosen", "linux,initrd-start",
Paul Mackerrasa23414b2005-11-10 12:00:55 +11002976 &val, sizeof(val));
Benjamin Herrenschmidt493adff2013-08-07 02:01:38 +10002977 val = cpu_to_be64(prom_initrd_end);
Anton Blanchard5827d412012-11-26 17:40:03 +00002978 prom_setprop(prom.chosen, "/chosen", "linux,initrd-end",
Paul Mackerrasa23414b2005-11-10 12:00:55 +11002979 &val, sizeof(val));
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002980
Anton Blanchard5827d412012-11-26 17:40:03 +00002981 reserve_mem(prom_initrd_start,
2982 prom_initrd_end - prom_initrd_start);
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002983
Mathieu Malaterreeae5f702018-04-06 22:12:19 +02002984 prom_debug("initrd_start=0x%lx\n", prom_initrd_start);
2985 prom_debug("initrd_end=0x%lx\n", prom_initrd_end);
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002986 }
2987#endif /* CONFIG_BLK_DEV_INITRD */
2988}
2989
Anton Blanchard5ac47f72012-11-26 17:39:03 +00002990#ifdef CONFIG_PPC64
2991#ifdef CONFIG_RELOCATABLE
2992static void reloc_toc(void)
2993{
2994}
2995
2996static void unreloc_toc(void)
2997{
2998}
2999#else
Anton Blanchard16744002013-03-12 01:51:51 +00003000static void __reloc_toc(unsigned long offset, unsigned long nr_entries)
Anton Blanchard5ac47f72012-11-26 17:39:03 +00003001{
3002 unsigned long i;
Anton Blanchard16744002013-03-12 01:51:51 +00003003 unsigned long *toc_entry;
3004
3005 /* Get the start of the TOC by using r2 directly. */
3006 asm volatile("addi %0,2,-0x8000" : "=b" (toc_entry));
Anton Blanchard5ac47f72012-11-26 17:39:03 +00003007
3008 for (i = 0; i < nr_entries; i++) {
3009 *toc_entry = *toc_entry + offset;
3010 toc_entry++;
3011 }
3012}
3013
3014static void reloc_toc(void)
3015{
3016 unsigned long offset = reloc_offset();
3017 unsigned long nr_entries =
3018 (__prom_init_toc_end - __prom_init_toc_start) / sizeof(long);
3019
Anton Blanchard16744002013-03-12 01:51:51 +00003020 __reloc_toc(offset, nr_entries);
Anton Blanchard5ac47f72012-11-26 17:39:03 +00003021
3022 mb();
3023}
3024
3025static void unreloc_toc(void)
3026{
3027 unsigned long offset = reloc_offset();
3028 unsigned long nr_entries =
3029 (__prom_init_toc_end - __prom_init_toc_start) / sizeof(long);
3030
3031 mb();
3032
Anton Blanchard16744002013-03-12 01:51:51 +00003033 __reloc_toc(-offset, nr_entries);
Anton Blanchard5ac47f72012-11-26 17:39:03 +00003034}
3035#endif
3036#endif
Benjamin Herrenschmidt27f44882011-09-19 18:27:58 +00003037
Paul Mackerras9b6b5632005-10-06 12:06:20 +10003038/*
3039 * We enter here early on, when the Open Firmware prom is still
3040 * handling exceptions and the MMU hash table for us.
3041 */
3042
3043unsigned long __init prom_init(unsigned long r3, unsigned long r4,
3044 unsigned long pp,
Paul Mackerras549e8152008-08-30 11:43:47 +10003045 unsigned long r6, unsigned long r7,
3046 unsigned long kbase)
Paul Mackerras9b6b5632005-10-06 12:06:20 +10003047{
Paul Mackerras9b6b5632005-10-06 12:06:20 +10003048 unsigned long hdr;
Paul Mackerras9b6b5632005-10-06 12:06:20 +10003049
3050#ifdef CONFIG_PPC32
Paul Mackerras549e8152008-08-30 11:43:47 +10003051 unsigned long offset = reloc_offset();
Paul Mackerras9b6b5632005-10-06 12:06:20 +10003052 reloc_got2(offset);
Anton Blanchard5ac47f72012-11-26 17:39:03 +00003053#else
3054 reloc_toc();
Paul Mackerras9b6b5632005-10-06 12:06:20 +10003055#endif
3056
Paul Mackerras9b6b5632005-10-06 12:06:20 +10003057 /*
3058 * First zero the BSS
3059 */
Anton Blanchard5827d412012-11-26 17:40:03 +00003060 memset(&__bss_start, 0, __bss_stop - __bss_start);
Paul Mackerras9b6b5632005-10-06 12:06:20 +10003061
3062 /*
3063 * Init interface to Open Firmware, get some node references,
3064 * like /chosen
3065 */
3066 prom_init_client_services(pp);
3067
3068 /*
Paul Mackerrasa23414b2005-11-10 12:00:55 +11003069 * See if this OF is old enough that we need to do explicit maps
3070 * and other workarounds
3071 */
3072 prom_find_mmu();
3073
3074 /*
Paul Mackerras9b6b5632005-10-06 12:06:20 +10003075 * Init prom stdout device
3076 */
3077 prom_init_stdout();
3078
Anton Blanchard5827d412012-11-26 17:40:03 +00003079 prom_printf("Preparing to boot %s", linux_banner);
Michael Ellermane7943fb2009-03-04 19:02:01 +00003080
Paul Mackerras9b6b5632005-10-06 12:06:20 +10003081 /*
3082 * Get default machine type. At this point, we do not differentiate
3083 * between pSeries SMP and pSeries LPAR
3084 */
Anton Blanchard5827d412012-11-26 17:40:03 +00003085 of_platform = prom_find_machine_type();
3086 prom_printf("Detected machine type: %x\n", of_platform);
Paul Mackerras9b6b5632005-10-06 12:06:20 +10003087
Suzuki Poulose0f890c82011-12-14 22:57:15 +00003088#ifndef CONFIG_NONSTATIC_KERNEL
Olaf Heringadd60ef2006-03-23 22:03:57 +01003089 /* Bail if this is a kdump kernel. */
3090 if (PHYSICAL_START > 0)
3091 prom_panic("Error: You can't boot a kdump kernel from OF!\n");
Paul Mackerras549e8152008-08-30 11:43:47 +10003092#endif
Olaf Heringadd60ef2006-03-23 22:03:57 +01003093
3094 /*
3095 * Check for an initrd
3096 */
3097 prom_check_initrd(r3, r4);
3098
Suraj Jitindar Singh12cc9fd2017-02-28 17:03:47 +11003099 /*
3100 * Do early parsing of command line
3101 */
3102 early_cmdline_parse();
3103
Benjamin Herrenschmidt11fdb302018-10-15 13:49:53 +11003104#ifdef CONFIG_PPC_PSERIES
Paul Mackerras9b6b5632005-10-06 12:06:20 +10003105 /*
3106 * On pSeries, inform the firmware about our capabilities
3107 */
Anton Blanchard5827d412012-11-26 17:40:03 +00003108 if (of_platform == PLATFORM_PSERIES ||
3109 of_platform == PLATFORM_PSERIES_LPAR)
Paul Mackerras9b6b5632005-10-06 12:06:20 +10003110 prom_send_capabilities();
3111#endif
3112
Paul Mackerras9b6b5632005-10-06 12:06:20 +10003113 /*
Arnd Bergmannf3f66f52005-10-31 20:08:37 -05003114 * Copy the CPU hold code
Paul Mackerras9b6b5632005-10-06 12:06:20 +10003115 */
Anton Blanchard5827d412012-11-26 17:40:03 +00003116 if (of_platform != PLATFORM_POWERMAC)
Paul Mackerras549e8152008-08-30 11:43:47 +10003117 copy_and_flush(0, kbase, 0x100, 0);
Paul Mackerras9b6b5632005-10-06 12:06:20 +10003118
3119 /*
Paul Mackerras9b6b5632005-10-06 12:06:20 +10003120 * Initialize memory management within prom_init
3121 */
3122 prom_init_mem();
3123
3124 /*
3125 * Determine which cpu is actually running right _now_
3126 */
3127 prom_find_boot_cpu();
3128
3129 /*
3130 * Initialize display devices
3131 */
3132 prom_check_displays();
3133
Benjamin Herrenschmidt493adff2013-08-07 02:01:38 +10003134#if defined(CONFIG_PPC64) && defined(__BIG_ENDIAN__)
Paul Mackerras9b6b5632005-10-06 12:06:20 +10003135 /*
3136 * Initialize IOMMU (TCE tables) on pSeries. Do that before anything else
3137 * that uses the allocator, we need to make sure we get the top of memory
3138 * available for us here...
3139 */
Anton Blanchard5827d412012-11-26 17:40:03 +00003140 if (of_platform == PLATFORM_PSERIES)
Paul Mackerras9b6b5632005-10-06 12:06:20 +10003141 prom_initialize_tce_table();
3142#endif
3143
3144 /*
Benjamin Herrenschmidt27f44882011-09-19 18:27:58 +00003145 * On non-powermacs, try to instantiate RTAS. PowerMacs don't
3146 * have a usable RTAS implementation.
Paul Mackerras9b6b5632005-10-06 12:06:20 +10003147 */
Benjamin Herrenschmidt11fdb302018-10-15 13:49:53 +11003148 if (of_platform != PLATFORM_POWERMAC)
Paul Mackerras9b6b5632005-10-06 12:06:20 +10003149 prom_instantiate_rtas();
Benjamin Herrenschmidt27f44882011-09-19 18:27:58 +00003150
Ashley Lai4a727422012-08-14 18:34:57 -05003151#ifdef CONFIG_PPC64
3152 /* instantiate sml */
3153 prom_instantiate_sml();
3154#endif
3155
Benjamin Herrenschmidt27f44882011-09-19 18:27:58 +00003156 /*
3157 * On non-powermacs, put all CPUs in spin-loops.
3158 *
3159 * PowerMacs use a different mechanism to spin CPUs
Benjamin Herrenschmidtdbe78b42013-09-25 14:02:50 +10003160 *
3161 * (This must be done after instanciating RTAS)
Benjamin Herrenschmidt27f44882011-09-19 18:27:58 +00003162 */
Benjamin Herrenschmidt11fdb302018-10-15 13:49:53 +11003163 if (of_platform != PLATFORM_POWERMAC)
Benjamin Herrenschmidt27f44882011-09-19 18:27:58 +00003164 prom_hold_cpus();
Paul Mackerras9b6b5632005-10-06 12:06:20 +10003165
3166 /*
3167 * Fill in some infos for use by the kernel later on
3168 */
Benjamin Herrenschmidt493adff2013-08-07 02:01:38 +10003169 if (prom_memory_limit) {
3170 __be64 val = cpu_to_be64(prom_memory_limit);
Anton Blanchard5827d412012-11-26 17:40:03 +00003171 prom_setprop(prom.chosen, "/chosen", "linux,memory-limit",
Benjamin Herrenschmidt493adff2013-08-07 02:01:38 +10003172 &val, sizeof(val));
3173 }
Paul Mackerras9b6b5632005-10-06 12:06:20 +10003174#ifdef CONFIG_PPC64
Anton Blanchard5827d412012-11-26 17:40:03 +00003175 if (prom_iommu_off)
3176 prom_setprop(prom.chosen, "/chosen", "linux,iommu-off",
Paul Mackerrasa23414b2005-11-10 12:00:55 +11003177 NULL, 0);
Paul Mackerras9b6b5632005-10-06 12:06:20 +10003178
Anton Blanchard5827d412012-11-26 17:40:03 +00003179 if (prom_iommu_force_on)
3180 prom_setprop(prom.chosen, "/chosen", "linux,iommu-force-on",
Paul Mackerrasa23414b2005-11-10 12:00:55 +11003181 NULL, 0);
Paul Mackerras9b6b5632005-10-06 12:06:20 +10003182
Anton Blanchard5827d412012-11-26 17:40:03 +00003183 if (prom_tce_alloc_start) {
3184 prom_setprop(prom.chosen, "/chosen", "linux,tce-alloc-start",
3185 &prom_tce_alloc_start,
Paul Mackerras9b6b5632005-10-06 12:06:20 +10003186 sizeof(prom_tce_alloc_start));
Anton Blanchard5827d412012-11-26 17:40:03 +00003187 prom_setprop(prom.chosen, "/chosen", "linux,tce-alloc-end",
3188 &prom_tce_alloc_end,
Paul Mackerras9b6b5632005-10-06 12:06:20 +10003189 sizeof(prom_tce_alloc_end));
3190 }
3191#endif
3192
3193 /*
3194 * Fixup any known bugs in the device-tree
3195 */
3196 fixup_device_tree();
3197
3198 /*
3199 * Now finally create the flattened device-tree
3200 */
Anton Blanchard1f8737a2009-03-31 20:06:15 +00003201 prom_printf("copying OF device tree...\n");
Paul Mackerras9b6b5632005-10-06 12:06:20 +10003202 flatten_device_tree();
3203
Paul Mackerras3825ac02005-11-08 22:48:08 +11003204 /*
3205 * in case stdin is USB and still active on IBM machines...
3206 * Unfortunately quiesce crashes on some powermacs if we have
Benjamin Herrenschmidt11fdb302018-10-15 13:49:53 +11003207 * closed stdin already (in particular the powerbook 101).
Paul Mackerras3825ac02005-11-08 22:48:08 +11003208 */
Benjamin Herrenschmidt11fdb302018-10-15 13:49:53 +11003209 if (of_platform != PLATFORM_POWERMAC)
Paul Mackerras3825ac02005-11-08 22:48:08 +11003210 prom_close_stdin();
Paul Mackerras9b6b5632005-10-06 12:06:20 +10003211
3212 /*
3213 * Call OF "quiesce" method to shut down pending DMA's from
3214 * devices etc...
3215 */
Michael Ellerman7e862d72015-03-30 17:38:09 +11003216 prom_printf("Quiescing Open Firmware ...\n");
Paul Mackerras9b6b5632005-10-06 12:06:20 +10003217 call_prom("quiesce", 0, 0);
3218
3219 /*
3220 * And finally, call the kernel passing it the flattened device
3221 * tree and NULL as r5, thus triggering the new entry point which
3222 * is common to us and kexec
3223 */
Anton Blanchard5827d412012-11-26 17:40:03 +00003224 hdr = dt_header_start;
Benjamin Herrenschmidt40dfef62011-11-29 18:22:56 +00003225
3226 /* Don't print anything after quiesce under OPAL, it crashes OFW */
Benjamin Herrenschmidt11fdb302018-10-15 13:49:53 +11003227 prom_printf("Booting Linux via __start() @ 0x%lx ...\n", kbase);
3228 prom_debug("->dt_header_start=0x%lx\n", hdr);
Paul Mackerras9b6b5632005-10-06 12:06:20 +10003229
3230#ifdef CONFIG_PPC32
3231 reloc_got2(-offset);
Anton Blanchard5ac47f72012-11-26 17:39:03 +00003232#else
3233 unreloc_toc();
Paul Mackerras9b6b5632005-10-06 12:06:20 +10003234#endif
3235
Benjamin Herrenschmidt6e35d5d2011-09-19 18:28:01 +00003236 __start(hdr, kbase, 0, 0, 0, 0, 0);
Paul Mackerras9b6b5632005-10-06 12:06:20 +10003237
3238 return 0;
3239}