blob: 7a5eb019256203aed0c6cc012be51e5e4ce7c6f2 [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
791struct ibm_arch_vec __cacheline_aligned ibm_architecture_vec = {
792 .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 Herrenschmidt493adff2013-08-07 02:01:38 +1000929/* Old method - ELF header with PT_NOTE sections only works on BE */
930#ifdef __BIG_ENDIAN__
Benjamin Herrenschmidt30c69ca2018-05-31 14:33:40 +1000931static const struct fake_elf {
Paul Mackerras9b6b5632005-10-06 12:06:20 +1000932 Elf32_Ehdr elfhdr;
933 Elf32_Phdr phdr[2];
934 struct chrpnote {
935 u32 namesz;
936 u32 descsz;
937 u32 type;
938 char name[8]; /* "PowerPC" */
939 struct chrpdesc {
940 u32 real_mode;
941 u32 real_base;
942 u32 real_size;
943 u32 virt_base;
944 u32 virt_size;
945 u32 load_base;
946 } chrpdesc;
947 } chrpnote;
948 struct rpanote {
949 u32 namesz;
950 u32 descsz;
951 u32 type;
952 char name[24]; /* "IBM,RPA-Client-Config" */
953 struct rpadesc {
954 u32 lpar_affinity;
955 u32 min_rmo_size;
956 u32 min_rmo_percent;
957 u32 max_pft_size;
958 u32 splpar;
959 u32 min_load;
960 u32 new_mem_def;
961 u32 ignore_me;
962 } rpadesc;
963 } rpanote;
Paul Mackerras5663a122008-10-31 22:27:17 +1100964} fake_elf = {
Paul Mackerras9b6b5632005-10-06 12:06:20 +1000965 .elfhdr = {
966 .e_ident = { 0x7f, 'E', 'L', 'F',
967 ELFCLASS32, ELFDATA2MSB, EV_CURRENT },
968 .e_type = ET_EXEC, /* yeah right */
969 .e_machine = EM_PPC,
970 .e_version = EV_CURRENT,
971 .e_phoff = offsetof(struct fake_elf, phdr),
972 .e_phentsize = sizeof(Elf32_Phdr),
973 .e_phnum = 2
974 },
975 .phdr = {
976 [0] = {
977 .p_type = PT_NOTE,
978 .p_offset = offsetof(struct fake_elf, chrpnote),
979 .p_filesz = sizeof(struct chrpnote)
980 }, [1] = {
981 .p_type = PT_NOTE,
982 .p_offset = offsetof(struct fake_elf, rpanote),
983 .p_filesz = sizeof(struct rpanote)
984 }
985 },
986 .chrpnote = {
987 .namesz = sizeof("PowerPC"),
988 .descsz = sizeof(struct chrpdesc),
989 .type = 0x1275,
990 .name = "PowerPC",
991 .chrpdesc = {
992 .real_mode = ~0U, /* ~0 means "don't care" */
993 .real_base = ~0U,
994 .real_size = ~0U,
995 .virt_base = ~0U,
996 .virt_size = ~0U,
997 .load_base = ~0U
998 },
999 },
1000 .rpanote = {
1001 .namesz = sizeof("IBM,RPA-Client-Config"),
1002 .descsz = sizeof(struct rpadesc),
1003 .type = 0x12759999,
1004 .name = "IBM,RPA-Client-Config",
1005 .rpadesc = {
Paul Mackerras5663a122008-10-31 22:27:17 +11001006 .lpar_affinity = 0,
1007 .min_rmo_size = 64, /* in megabytes */
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001008 .min_rmo_percent = 0,
Paul Mackerras5663a122008-10-31 22:27:17 +11001009 .max_pft_size = 48, /* 2^48 bytes max PFT size */
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001010 .splpar = 1,
1011 .min_load = ~0U,
Paul Mackerras5663a122008-10-31 22:27:17 +11001012 .new_mem_def = 0
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001013 }
1014 }
1015};
Benjamin Herrenschmidt493adff2013-08-07 02:01:38 +10001016#endif /* __BIG_ENDIAN__ */
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001017
Benjamin Herrenschmidtefec9592010-02-04 14:33:54 +11001018static int __init prom_count_smt_threads(void)
1019{
1020 phandle node;
1021 char type[64];
1022 unsigned int plen;
1023
1024 /* Pick up th first CPU node we can find */
1025 for (node = 0; prom_next_node(&node); ) {
1026 type[0] = 0;
1027 prom_getprop(node, "device_type", type, sizeof(type));
1028
Anton Blanchard5827d412012-11-26 17:40:03 +00001029 if (strcmp(type, "cpu"))
Benjamin Herrenschmidtefec9592010-02-04 14:33:54 +11001030 continue;
1031 /*
1032 * There is an entry for each smt thread, each entry being
1033 * 4 bytes long. All cpus should have the same number of
1034 * smt threads, so return after finding the first.
1035 */
1036 plen = prom_getproplen(node, "ibm,ppc-interrupt-server#s");
1037 if (plen == PROM_ERROR)
1038 break;
1039 plen >>= 2;
Michael Neuling2c48a7d2010-07-27 18:26:21 +00001040 prom_debug("Found %lu smt threads per core\n", (unsigned long)plen);
Benjamin Herrenschmidtefec9592010-02-04 14:33:54 +11001041
1042 /* Sanity check */
1043 if (plen < 1 || plen > 64) {
Michael Neuling2c48a7d2010-07-27 18:26:21 +00001044 prom_printf("Threads per core %lu out of bounds, assuming 1\n",
Benjamin Herrenschmidtefec9592010-02-04 14:33:54 +11001045 (unsigned long)plen);
1046 return 1;
1047 }
1048 return plen;
1049 }
1050 prom_debug("No threads found, assuming 1 per core\n");
1051
1052 return 1;
1053
1054}
1055
Suraj Jitindar Singh014d02c2017-02-28 17:03:48 +11001056static void __init prom_parse_mmu_model(u8 val,
1057 struct platform_support *support)
1058{
1059 switch (val) {
1060 case OV5_FEAT(OV5_MMU_DYNAMIC):
1061 case OV5_FEAT(OV5_MMU_EITHER): /* Either Available */
1062 prom_debug("MMU - either supported\n");
1063 support->radix_mmu = !prom_radix_disable;
1064 support->hash_mmu = true;
1065 break;
1066 case OV5_FEAT(OV5_MMU_RADIX): /* Only Radix */
1067 prom_debug("MMU - radix only\n");
1068 if (prom_radix_disable) {
1069 /*
1070 * If we __have__ to do radix, we're better off ignoring
1071 * the command line rather than not booting.
1072 */
1073 prom_printf("WARNING: Ignoring cmdline option disable_radix\n");
1074 }
1075 support->radix_mmu = true;
1076 break;
1077 case OV5_FEAT(OV5_MMU_HASH):
1078 prom_debug("MMU - hash only\n");
1079 support->hash_mmu = true;
1080 break;
1081 default:
1082 prom_debug("Unknown mmu support option: 0x%x\n", val);
1083 break;
1084 }
1085}
1086
Cédric Le Goaterac5e5a52017-08-30 21:46:16 +02001087static void __init prom_parse_xive_model(u8 val,
1088 struct platform_support *support)
1089{
1090 switch (val) {
1091 case OV5_FEAT(OV5_XIVE_EITHER): /* Either Available */
1092 prom_debug("XIVE - either mode supported\n");
1093 support->xive = true;
1094 break;
1095 case OV5_FEAT(OV5_XIVE_EXPLOIT): /* Only Exploitation mode */
1096 prom_debug("XIVE - exploitation mode supported\n");
1097 support->xive = true;
1098 break;
1099 case OV5_FEAT(OV5_XIVE_LEGACY): /* Only Legacy mode */
1100 prom_debug("XIVE - legacy mode supported\n");
1101 break;
1102 default:
1103 prom_debug("Unknown xive support option: 0x%x\n", val);
1104 break;
1105 }
1106}
1107
Suraj Jitindar Singh014d02c2017-02-28 17:03:48 +11001108static void __init prom_parse_platform_support(u8 index, u8 val,
1109 struct platform_support *support)
1110{
1111 switch (index) {
1112 case OV5_INDX(OV5_MMU_SUPPORT): /* MMU Model */
1113 prom_parse_mmu_model(val & OV5_FEAT(OV5_MMU_SUPPORT), support);
1114 break;
1115 case OV5_INDX(OV5_RADIX_GTSE): /* Radix Extensions */
1116 if (val & OV5_FEAT(OV5_RADIX_GTSE)) {
1117 prom_debug("Radix - GTSE supported\n");
1118 support->radix_gtse = true;
1119 }
1120 break;
Cédric Le Goaterac5e5a52017-08-30 21:46:16 +02001121 case OV5_INDX(OV5_XIVE_SUPPORT): /* Interrupt mode */
1122 prom_parse_xive_model(val & OV5_FEAT(OV5_XIVE_SUPPORT),
1123 support);
1124 break;
Suraj Jitindar Singh014d02c2017-02-28 17:03:48 +11001125 }
1126}
1127
1128static void __init prom_check_platform_support(void)
1129{
1130 struct platform_support supported = {
1131 .hash_mmu = false,
1132 .radix_mmu = false,
Cédric Le Goaterac5e5a52017-08-30 21:46:16 +02001133 .radix_gtse = false,
1134 .xive = false
Suraj Jitindar Singh014d02c2017-02-28 17:03:48 +11001135 };
1136 int prop_len = prom_getproplen(prom.chosen,
1137 "ibm,arch-vec-5-platform-support");
1138 if (prop_len > 1) {
1139 int i;
Suraj Jitindar Singhab912392018-09-05 12:09:50 +10001140 u8 vec[8];
Suraj Jitindar Singh014d02c2017-02-28 17:03:48 +11001141 prom_debug("Found ibm,arch-vec-5-platform-support, len: %d\n",
1142 prop_len);
Suraj Jitindar Singhab912392018-09-05 12:09:50 +10001143 if (prop_len > sizeof(vec))
1144 prom_printf("WARNING: ibm,arch-vec-5-platform-support longer than expected (len: %d)\n",
1145 prop_len);
Suraj Jitindar Singh014d02c2017-02-28 17:03:48 +11001146 prom_getprop(prom.chosen, "ibm,arch-vec-5-platform-support",
1147 &vec, sizeof(vec));
Suraj Jitindar Singhab912392018-09-05 12:09:50 +10001148 for (i = 0; i < sizeof(vec); i += 2) {
Suraj Jitindar Singh014d02c2017-02-28 17:03:48 +11001149 prom_debug("%d: index = 0x%x val = 0x%x\n", i / 2
1150 , vec[i]
1151 , vec[i + 1]);
1152 prom_parse_platform_support(vec[i], vec[i + 1],
1153 &supported);
1154 }
1155 }
1156
Alexey Kardashevskiy79b46862018-01-09 16:45:20 +11001157 if (supported.radix_mmu && supported.radix_gtse &&
1158 IS_ENABLED(CONFIG_PPC_RADIX_MMU)) {
Suraj Jitindar Singh014d02c2017-02-28 17:03:48 +11001159 /* Radix preferred - but we require GTSE for now */
1160 prom_debug("Asking for radix with GTSE\n");
1161 ibm_architecture_vec.vec5.mmu = OV5_FEAT(OV5_MMU_RADIX);
1162 ibm_architecture_vec.vec5.radix_ext = OV5_FEAT(OV5_RADIX_GTSE);
1163 } else if (supported.hash_mmu) {
1164 /* Default to hash mmu (if we can) */
1165 prom_debug("Asking for hash\n");
1166 ibm_architecture_vec.vec5.mmu = OV5_FEAT(OV5_MMU_HASH);
1167 } else {
1168 /* We're probably on a legacy hypervisor */
1169 prom_debug("Assuming legacy hash support\n");
1170 }
Cédric Le Goaterac5e5a52017-08-30 21:46:16 +02001171
1172 if (supported.xive) {
1173 prom_debug("Asking for XIVE\n");
1174 ibm_architecture_vec.vec5.intarch = OV5_FEAT(OV5_XIVE_EXPLOIT);
1175 }
Suraj Jitindar Singh014d02c2017-02-28 17:03:48 +11001176}
Benjamin Herrenschmidtefec9592010-02-04 14:33:54 +11001177
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001178static void __init prom_send_capabilities(void)
1179{
Benjamin Herrenschmidt493adff2013-08-07 02:01:38 +10001180 ihandle root;
Paul Mackerrasf709bfa2006-04-28 16:28:35 +10001181 prom_arg_t ret;
Laurent Dufourdbd0c5d2013-09-17 11:52:48 +02001182 u32 cores;
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001183
Suraj Jitindar Singh014d02c2017-02-28 17:03:48 +11001184 /* Check ibm,arch-vec-5-platform-support and fixup vec5 if required */
1185 prom_check_platform_support();
1186
Paul Mackerrasf709bfa2006-04-28 16:28:35 +10001187 root = call_prom("open", 1, 1, ADDR("/"));
1188 if (root != 0) {
Benjamin Herrenschmidtefec9592010-02-04 14:33:54 +11001189 /* We need to tell the FW about the number of cores we support.
1190 *
1191 * To do that, we count the number of threads on the first core
1192 * (we assume this is the same for all cores) and use it to
1193 * divide NR_CPUS.
1194 */
Laurent Dufourdbd0c5d2013-09-17 11:52:48 +02001195
Michael Ellerman76ffb572016-11-18 23:15:42 +11001196 cores = DIV_ROUND_UP(NR_CPUS, prom_count_smt_threads());
Mathieu Malaterreeae5f702018-04-06 22:12:19 +02001197 prom_printf("Max number of cores passed to firmware: %u (NR_CPUS = %d)\n",
Michael Ellerman76ffb572016-11-18 23:15:42 +11001198 cores, NR_CPUS);
1199
1200 ibm_architecture_vec.vec5.max_cpus = cpu_to_be32(cores);
Benjamin Herrenschmidtefec9592010-02-04 14:33:54 +11001201
Paul Mackerrasf709bfa2006-04-28 16:28:35 +10001202 /* try calling the ibm,client-architecture-support method */
Anton Blanchard049d0492009-09-21 20:47:39 +00001203 prom_printf("Calling ibm,client-architecture-support...");
Paul Mackerrasf709bfa2006-04-28 16:28:35 +10001204 if (call_prom_ret("call-method", 3, 2, &ret,
1205 ADDR("ibm,client-architecture-support"),
Benjamin Herrenschmidt33b74972006-06-07 12:01:32 +10001206 root,
Michael Ellerman76ffb572016-11-18 23:15:42 +11001207 ADDR(&ibm_architecture_vec)) == 0) {
Paul Mackerrasf709bfa2006-04-28 16:28:35 +10001208 /* the call exists... */
1209 if (ret)
Anton Blanchard4da727a2009-03-31 20:06:14 +00001210 prom_printf("\nWARNING: ibm,client-architecture"
Paul Mackerrasf709bfa2006-04-28 16:28:35 +10001211 "-support call FAILED!\n");
1212 call_prom("close", 1, 0, root);
Anton Blanchard4da727a2009-03-31 20:06:14 +00001213 prom_printf(" done\n");
Paul Mackerrasf709bfa2006-04-28 16:28:35 +10001214 return;
1215 }
1216 call_prom("close", 1, 0, root);
Anton Blanchard049d0492009-09-21 20:47:39 +00001217 prom_printf(" not implemented\n");
Paul Mackerrasf709bfa2006-04-28 16:28:35 +10001218 }
1219
Benjamin Herrenschmidt493adff2013-08-07 02:01:38 +10001220#ifdef __BIG_ENDIAN__
1221 {
1222 ihandle elfloader;
1223
1224 /* no ibm,client-architecture-support call, try the old way */
1225 elfloader = call_prom("open", 1, 1,
1226 ADDR("/packages/elf-loader"));
1227 if (elfloader == 0) {
1228 prom_printf("couldn't open /packages/elf-loader\n");
1229 return;
1230 }
1231 call_prom("call-method", 3, 1, ADDR("process-elf-header"),
1232 elfloader, ADDR(&fake_elf));
1233 call_prom("close", 1, 0, elfloader);
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001234 }
Benjamin Herrenschmidt493adff2013-08-07 02:01:38 +10001235#endif /* __BIG_ENDIAN__ */
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001236}
Benjamin Herrenschmidt11fdb302018-10-15 13:49:53 +11001237#endif /* CONFIG_PPC_PSERIES */
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001238
1239/*
1240 * Memory allocation strategy... our layout is normally:
1241 *
1242 * at 14Mb or more we have vmlinux, then a gap and initrd. In some
1243 * rare cases, initrd might end up being before the kernel though.
1244 * We assume this won't override the final kernel at 0, we have no
1245 * provision to handle that in this version, but it should hopefully
1246 * never happen.
1247 *
1248 * alloc_top is set to the top of RMO, eventually shrink down if the
1249 * TCEs overlap
1250 *
1251 * alloc_bottom is set to the top of kernel/initrd
1252 *
1253 * from there, allocations are done this way : rtas is allocated
1254 * topmost, and the device-tree is allocated from the bottom. We try
1255 * to grow the device-tree allocation as we progress. If we can't,
1256 * then we fail, we don't currently have a facility to restart
1257 * elsewhere, but that shouldn't be necessary.
1258 *
1259 * Note that calls to reserve_mem have to be done explicitly, memory
1260 * allocated with either alloc_up or alloc_down isn't automatically
1261 * reserved.
1262 */
1263
1264
1265/*
1266 * Allocates memory in the RMO upward from the kernel/initrd
1267 *
1268 * When align is 0, this is a special case, it means to allocate in place
1269 * at the current location of alloc_bottom or fail (that is basically
1270 * extending the previous allocation). Used for the device-tree flattening
1271 */
1272static unsigned long __init alloc_up(unsigned long size, unsigned long align)
1273{
Anton Blanchard5827d412012-11-26 17:40:03 +00001274 unsigned long base = alloc_bottom;
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001275 unsigned long addr = 0;
1276
Paul Mackerrasc49888202005-10-26 21:52:53 +10001277 if (align)
1278 base = _ALIGN_UP(base, align);
Mathieu Malaterreeae5f702018-04-06 22:12:19 +02001279 prom_debug("%s(%lx, %lx)\n", __func__, size, align);
Anton Blanchard5827d412012-11-26 17:40:03 +00001280 if (ram_top == 0)
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001281 prom_panic("alloc_up() called with mem not initialized\n");
1282
1283 if (align)
Anton Blanchard5827d412012-11-26 17:40:03 +00001284 base = _ALIGN_UP(alloc_bottom, align);
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001285 else
Anton Blanchard5827d412012-11-26 17:40:03 +00001286 base = alloc_bottom;
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001287
Anton Blanchard5827d412012-11-26 17:40:03 +00001288 for(; (base + size) <= alloc_top;
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001289 base = _ALIGN_UP(base + 0x100000, align)) {
Mathieu Malaterreeae5f702018-04-06 22:12:19 +02001290 prom_debug(" trying: 0x%lx\n\r", base);
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001291 addr = (unsigned long)prom_claim(base, size, 0);
Paul Mackerrasc49888202005-10-26 21:52:53 +10001292 if (addr != PROM_ERROR && addr != 0)
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001293 break;
1294 addr = 0;
1295 if (align == 0)
1296 break;
1297 }
1298 if (addr == 0)
1299 return 0;
Anton Blanchard5827d412012-11-26 17:40:03 +00001300 alloc_bottom = addr + size;
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001301
Mathieu Malaterreeae5f702018-04-06 22:12:19 +02001302 prom_debug(" -> %lx\n", addr);
1303 prom_debug(" alloc_bottom : %lx\n", alloc_bottom);
1304 prom_debug(" alloc_top : %lx\n", alloc_top);
1305 prom_debug(" alloc_top_hi : %lx\n", alloc_top_high);
1306 prom_debug(" rmo_top : %lx\n", rmo_top);
1307 prom_debug(" ram_top : %lx\n", ram_top);
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001308
1309 return addr;
1310}
1311
1312/*
1313 * Allocates memory downward, either from top of RMO, or if highmem
1314 * is set, from the top of RAM. Note that this one doesn't handle
1315 * failures. It does claim memory if highmem is not set.
1316 */
1317static unsigned long __init alloc_down(unsigned long size, unsigned long align,
1318 int highmem)
1319{
1320 unsigned long base, addr = 0;
1321
Mathieu Malaterreeae5f702018-04-06 22:12:19 +02001322 prom_debug("%s(%lx, %lx, %s)\n", __func__, size, align,
Anton Blanchard5827d412012-11-26 17:40:03 +00001323 highmem ? "(high)" : "(low)");
1324 if (ram_top == 0)
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001325 prom_panic("alloc_down() called with mem not initialized\n");
1326
1327 if (highmem) {
1328 /* Carve out storage for the TCE table. */
Anton Blanchard5827d412012-11-26 17:40:03 +00001329 addr = _ALIGN_DOWN(alloc_top_high - size, align);
1330 if (addr <= alloc_bottom)
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001331 return 0;
1332 /* Will we bump into the RMO ? If yes, check out that we
1333 * didn't overlap existing allocations there, if we did,
1334 * we are dead, we must be the first in town !
1335 */
Anton Blanchard5827d412012-11-26 17:40:03 +00001336 if (addr < rmo_top) {
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001337 /* Good, we are first */
Anton Blanchard5827d412012-11-26 17:40:03 +00001338 if (alloc_top == rmo_top)
1339 alloc_top = rmo_top = addr;
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001340 else
1341 return 0;
1342 }
Anton Blanchard5827d412012-11-26 17:40:03 +00001343 alloc_top_high = addr;
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001344 goto bail;
1345 }
1346
Anton Blanchard5827d412012-11-26 17:40:03 +00001347 base = _ALIGN_DOWN(alloc_top - size, align);
1348 for (; base > alloc_bottom;
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001349 base = _ALIGN_DOWN(base - 0x100000, align)) {
Mathieu Malaterreeae5f702018-04-06 22:12:19 +02001350 prom_debug(" trying: 0x%lx\n\r", base);
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001351 addr = (unsigned long)prom_claim(base, size, 0);
Paul Mackerrasc49888202005-10-26 21:52:53 +10001352 if (addr != PROM_ERROR && addr != 0)
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001353 break;
1354 addr = 0;
1355 }
1356 if (addr == 0)
1357 return 0;
Anton Blanchard5827d412012-11-26 17:40:03 +00001358 alloc_top = addr;
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001359
1360 bail:
Mathieu Malaterreeae5f702018-04-06 22:12:19 +02001361 prom_debug(" -> %lx\n", addr);
1362 prom_debug(" alloc_bottom : %lx\n", alloc_bottom);
1363 prom_debug(" alloc_top : %lx\n", alloc_top);
1364 prom_debug(" alloc_top_hi : %lx\n", alloc_top_high);
1365 prom_debug(" rmo_top : %lx\n", rmo_top);
1366 prom_debug(" ram_top : %lx\n", ram_top);
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001367
1368 return addr;
1369}
1370
1371/*
1372 * Parse a "reg" cell
1373 */
1374static unsigned long __init prom_next_cell(int s, cell_t **cellp)
1375{
1376 cell_t *p = *cellp;
1377 unsigned long r = 0;
1378
1379 /* Ignore more than 2 cells */
1380 while (s > sizeof(unsigned long) / 4) {
1381 p++;
1382 s--;
1383 }
Benjamin Herrenschmidt493adff2013-08-07 02:01:38 +10001384 r = be32_to_cpu(*p++);
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001385#ifdef CONFIG_PPC64
Paul Mackerras35499c02005-10-22 16:02:39 +10001386 if (s > 1) {
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001387 r <<= 32;
Benjamin Herrenschmidt493adff2013-08-07 02:01:38 +10001388 r |= be32_to_cpu(*(p++));
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001389 }
1390#endif
1391 *cellp = p;
1392 return r;
1393}
1394
1395/*
1396 * Very dumb function for adding to the memory reserve list, but
1397 * we don't need anything smarter at this point
1398 *
1399 * XXX Eventually check for collisions. They should NEVER happen.
1400 * If problems seem to show up, it would be a good start to track
1401 * them down.
1402 */
Michael Ellerman0108d3f2007-05-07 15:58:28 +10001403static void __init reserve_mem(u64 base, u64 size)
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001404{
Kumar Galacbbcf342006-01-11 17:57:13 -06001405 u64 top = base + size;
Anton Blanchard5827d412012-11-26 17:40:03 +00001406 unsigned long cnt = mem_reserve_cnt;
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001407
1408 if (size == 0)
1409 return;
1410
1411 /* We need to always keep one empty entry so that we
1412 * have our terminator with "size" set to 0 since we are
1413 * dumb and just copy this entire array to the boot params
1414 */
1415 base = _ALIGN_DOWN(base, PAGE_SIZE);
1416 top = _ALIGN_UP(top, PAGE_SIZE);
1417 size = top - base;
1418
1419 if (cnt >= (MEM_RESERVE_MAP_SIZE - 1))
1420 prom_panic("Memory reserve map exhausted !\n");
Benjamin Herrenschmidt493adff2013-08-07 02:01:38 +10001421 mem_reserve_map[cnt].base = cpu_to_be64(base);
1422 mem_reserve_map[cnt].size = cpu_to_be64(size);
Anton Blanchard5827d412012-11-26 17:40:03 +00001423 mem_reserve_cnt = cnt + 1;
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001424}
1425
1426/*
Adrian Bunkb3c2ffd2006-06-30 18:20:44 +02001427 * Initialize memory allocation mechanism, parse "memory" nodes and
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001428 * obtain that way the top of memory and RMO to setup out local allocator
1429 */
1430static void __init prom_init_mem(void)
1431{
1432 phandle node;
Mathieu Malaterreeab00a22018-04-04 22:08:35 +02001433#ifdef DEBUG_PROM
1434 char *path;
1435#endif
1436 char type[64];
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001437 unsigned int plen;
1438 cell_t *p, *endp;
Benjamin Herrenschmidt493adff2013-08-07 02:01:38 +10001439 __be32 val;
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001440 u32 rac, rsc;
1441
1442 /*
1443 * We iterate the memory nodes to find
1444 * 1) top of RMO (first node)
1445 * 2) top of memory
1446 */
Benjamin Herrenschmidt493adff2013-08-07 02:01:38 +10001447 val = cpu_to_be32(2);
1448 prom_getprop(prom.root, "#address-cells", &val, sizeof(val));
1449 rac = be32_to_cpu(val);
1450 val = cpu_to_be32(1);
1451 prom_getprop(prom.root, "#size-cells", &val, sizeof(rsc));
1452 rsc = be32_to_cpu(val);
1453 prom_debug("root_addr_cells: %x\n", rac);
1454 prom_debug("root_size_cells: %x\n", rsc);
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001455
1456 prom_debug("scanning memory:\n");
Mathieu Malaterreeab00a22018-04-04 22:08:35 +02001457#ifdef DEBUG_PROM
Anton Blanchard5827d412012-11-26 17:40:03 +00001458 path = prom_scratch;
Mathieu Malaterreeab00a22018-04-04 22:08:35 +02001459#endif
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001460
1461 for (node = 0; prom_next_node(&node); ) {
1462 type[0] = 0;
1463 prom_getprop(node, "device_type", type, sizeof(type));
1464
Paul Mackerrasc49888202005-10-26 21:52:53 +10001465 if (type[0] == 0) {
1466 /*
1467 * CHRP Longtrail machines have no device_type
1468 * on the memory node, so check the name instead...
1469 */
1470 prom_getprop(node, "name", type, sizeof(type));
1471 }
Anton Blanchard5827d412012-11-26 17:40:03 +00001472 if (strcmp(type, "memory"))
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001473 continue;
Paul Mackerrasc49888202005-10-26 21:52:53 +10001474
Anton Blanchard5827d412012-11-26 17:40:03 +00001475 plen = prom_getprop(node, "reg", regbuf, sizeof(regbuf));
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001476 if (plen > sizeof(regbuf)) {
1477 prom_printf("memory node too large for buffer !\n");
1478 plen = sizeof(regbuf);
1479 }
Anton Blanchard5827d412012-11-26 17:40:03 +00001480 p = regbuf;
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001481 endp = p + (plen / sizeof(cell_t));
1482
1483#ifdef DEBUG_PROM
1484 memset(path, 0, PROM_SCRATCH_SIZE);
1485 call_prom("package-to-path", 3, 1, node, path, PROM_SCRATCH_SIZE-1);
1486 prom_debug(" node %s :\n", path);
1487#endif /* DEBUG_PROM */
1488
1489 while ((endp - p) >= (rac + rsc)) {
1490 unsigned long base, size;
1491
1492 base = prom_next_cell(rac, &p);
1493 size = prom_next_cell(rsc, &p);
1494
1495 if (size == 0)
1496 continue;
Mathieu Malaterreeae5f702018-04-06 22:12:19 +02001497 prom_debug(" %lx %lx\n", base, size);
Anton Blanchard5827d412012-11-26 17:40:03 +00001498 if (base == 0 && (of_platform & PLATFORM_LPAR))
1499 rmo_top = size;
1500 if ((base + size) > ram_top)
1501 ram_top = base + size;
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001502 }
1503 }
1504
Anton Blanchard5827d412012-11-26 17:40:03 +00001505 alloc_bottom = PAGE_ALIGN((unsigned long)&_end + 0x4000);
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001506
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001507 /*
Benjamin Krillcf687872009-07-27 22:02:39 +00001508 * If prom_memory_limit is set we reduce the upper limits *except* for
1509 * alloc_top_high. This must be the real top of RAM so we can put
1510 * TCE's up there.
1511 */
1512
Anton Blanchard5827d412012-11-26 17:40:03 +00001513 alloc_top_high = ram_top;
Benjamin Krillcf687872009-07-27 22:02:39 +00001514
Anton Blanchard5827d412012-11-26 17:40:03 +00001515 if (prom_memory_limit) {
1516 if (prom_memory_limit <= alloc_bottom) {
Mathieu Malaterreeae5f702018-04-06 22:12:19 +02001517 prom_printf("Ignoring mem=%lx <= alloc_bottom.\n",
1518 prom_memory_limit);
Anton Blanchard5827d412012-11-26 17:40:03 +00001519 prom_memory_limit = 0;
1520 } else if (prom_memory_limit >= ram_top) {
Mathieu Malaterreeae5f702018-04-06 22:12:19 +02001521 prom_printf("Ignoring mem=%lx >= ram_top.\n",
1522 prom_memory_limit);
Anton Blanchard5827d412012-11-26 17:40:03 +00001523 prom_memory_limit = 0;
Benjamin Krillcf687872009-07-27 22:02:39 +00001524 } else {
Anton Blanchard5827d412012-11-26 17:40:03 +00001525 ram_top = prom_memory_limit;
1526 rmo_top = min(rmo_top, prom_memory_limit);
Benjamin Krillcf687872009-07-27 22:02:39 +00001527 }
1528 }
1529
1530 /*
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001531 * Setup our top alloc point, that is top of RMO or top of
1532 * segment 0 when running non-LPAR.
1533 * Some RS64 machines have buggy firmware where claims up at
1534 * 1GB fail. Cap at 768MB as a workaround.
1535 * Since 768MB is plenty of room, and we need to cap to something
1536 * reasonable on 32-bit, cap at 768MB on all machines.
1537 */
Anton Blanchard5827d412012-11-26 17:40:03 +00001538 if (!rmo_top)
1539 rmo_top = ram_top;
1540 rmo_top = min(0x30000000ul, rmo_top);
1541 alloc_top = rmo_top;
1542 alloc_top_high = ram_top;
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001543
Paul Mackerras64968f62011-12-13 17:54:13 +00001544 /*
1545 * Check if we have an initrd after the kernel but still inside
1546 * the RMO. If we do move our bottom point to after it.
1547 */
Anton Blanchard5827d412012-11-26 17:40:03 +00001548 if (prom_initrd_start &&
1549 prom_initrd_start < rmo_top &&
1550 prom_initrd_end > alloc_bottom)
1551 alloc_bottom = PAGE_ALIGN(prom_initrd_end);
Paul Mackerras64968f62011-12-13 17:54:13 +00001552
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001553 prom_printf("memory layout at init:\n");
Mathieu Malaterreeae5f702018-04-06 22:12:19 +02001554 prom_printf(" memory_limit : %lx (16 MB aligned)\n",
1555 prom_memory_limit);
1556 prom_printf(" alloc_bottom : %lx\n", alloc_bottom);
1557 prom_printf(" alloc_top : %lx\n", alloc_top);
1558 prom_printf(" alloc_top_hi : %lx\n", alloc_top_high);
1559 prom_printf(" rmo_top : %lx\n", rmo_top);
1560 prom_printf(" ram_top : %lx\n", ram_top);
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001561}
1562
Benjamin Herrenschmidt27f44882011-09-19 18:27:58 +00001563static void __init prom_close_stdin(void)
1564{
Benjamin Herrenschmidt493adff2013-08-07 02:01:38 +10001565 __be32 val;
1566 ihandle stdin;
Benjamin Herrenschmidt27f44882011-09-19 18:27:58 +00001567
Benjamin Herrenschmidt493adff2013-08-07 02:01:38 +10001568 if (prom_getprop(prom.chosen, "stdin", &val, sizeof(val)) > 0) {
1569 stdin = be32_to_cpu(val);
1570 call_prom("close", 1, 0, stdin);
1571 }
Benjamin Herrenschmidt27f44882011-09-19 18:27:58 +00001572}
1573
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001574/*
1575 * Allocate room for and instantiate RTAS
1576 */
1577static void __init prom_instantiate_rtas(void)
1578{
1579 phandle rtas_node;
1580 ihandle rtas_inst;
1581 u32 base, entry = 0;
Benjamin Herrenschmidt493adff2013-08-07 02:01:38 +10001582 __be32 val;
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001583 u32 size = 0;
1584
1585 prom_debug("prom_instantiate_rtas: start...\n");
1586
1587 rtas_node = call_prom("finddevice", 1, 1, ADDR("/rtas"));
1588 prom_debug("rtas_node: %x\n", rtas_node);
1589 if (!PHANDLE_VALID(rtas_node))
1590 return;
1591
Benjamin Herrenschmidt493adff2013-08-07 02:01:38 +10001592 val = 0;
1593 prom_getprop(rtas_node, "rtas-size", &val, sizeof(size));
1594 size = be32_to_cpu(val);
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001595 if (size == 0)
1596 return;
1597
1598 base = alloc_down(size, PAGE_SIZE, 0);
Anton Blanchard6d1e2c62011-11-14 12:55:47 +00001599 if (base == 0)
1600 prom_panic("Could not allocate memory for RTAS\n");
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001601
1602 rtas_inst = call_prom("open", 1, 1, ADDR("/rtas"));
1603 if (!IHANDLE_VALID(rtas_inst)) {
Paul Mackerrasa23414b2005-11-10 12:00:55 +11001604 prom_printf("opening rtas package failed (%x)\n", rtas_inst);
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001605 return;
1606 }
1607
Anton Blanchard1f8737a2009-03-31 20:06:15 +00001608 prom_printf("instantiating rtas at 0x%x...", base);
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001609
1610 if (call_prom_ret("call-method", 3, 2, &entry,
1611 ADDR("instantiate-rtas"),
Paul Mackerrasa23414b2005-11-10 12:00:55 +11001612 rtas_inst, base) != 0
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001613 || entry == 0) {
1614 prom_printf(" failed\n");
1615 return;
1616 }
1617 prom_printf(" done\n");
1618
1619 reserve_mem(base, size);
1620
Benjamin Herrenschmidt493adff2013-08-07 02:01:38 +10001621 val = cpu_to_be32(base);
Paul Mackerrasa23414b2005-11-10 12:00:55 +11001622 prom_setprop(rtas_node, "/rtas", "linux,rtas-base",
Benjamin Herrenschmidt493adff2013-08-07 02:01:38 +10001623 &val, sizeof(val));
1624 val = cpu_to_be32(entry);
Paul Mackerrasa23414b2005-11-10 12:00:55 +11001625 prom_setprop(rtas_node, "/rtas", "linux,rtas-entry",
Benjamin Herrenschmidt493adff2013-08-07 02:01:38 +10001626 &val, sizeof(val));
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001627
Benjamin Herrenschmidtdbe78b42013-09-25 14:02:50 +10001628 /* Check if it supports "query-cpu-stopped-state" */
1629 if (prom_getprop(rtas_node, "query-cpu-stopped-state",
1630 &val, sizeof(val)) != PROM_ERROR)
1631 rtas_has_query_cpu_stopped = true;
1632
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001633 prom_debug("rtas base = 0x%x\n", base);
1634 prom_debug("rtas entry = 0x%x\n", entry);
Mathieu Malaterreeae5f702018-04-06 22:12:19 +02001635 prom_debug("rtas size = 0x%x\n", size);
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001636
1637 prom_debug("prom_instantiate_rtas: end...\n");
1638}
1639
1640#ifdef CONFIG_PPC64
1641/*
Ashley Lai4a727422012-08-14 18:34:57 -05001642 * Allocate room for and instantiate Stored Measurement Log (SML)
1643 */
1644static void __init prom_instantiate_sml(void)
1645{
1646 phandle ibmvtpm_node;
1647 ihandle ibmvtpm_inst;
Hon Ching \(Vicky\) Lob4ed0462015-10-07 20:11:53 -04001648 u32 entry = 0, size = 0, succ = 0;
Ashley Lai4a727422012-08-14 18:34:57 -05001649 u64 base;
Hon Ching \(Vicky\) Lob4ed0462015-10-07 20:11:53 -04001650 __be32 val;
Ashley Lai4a727422012-08-14 18:34:57 -05001651
1652 prom_debug("prom_instantiate_sml: start...\n");
1653
Hon Ching \(Vicky\) Lo2f82e982015-10-07 20:11:52 -04001654 ibmvtpm_node = call_prom("finddevice", 1, 1, ADDR("/vdevice/vtpm"));
Ashley Lai4a727422012-08-14 18:34:57 -05001655 prom_debug("ibmvtpm_node: %x\n", ibmvtpm_node);
1656 if (!PHANDLE_VALID(ibmvtpm_node))
1657 return;
1658
Hon Ching \(Vicky\) Lo2f82e982015-10-07 20:11:52 -04001659 ibmvtpm_inst = call_prom("open", 1, 1, ADDR("/vdevice/vtpm"));
Ashley Lai4a727422012-08-14 18:34:57 -05001660 if (!IHANDLE_VALID(ibmvtpm_inst)) {
1661 prom_printf("opening vtpm package failed (%x)\n", ibmvtpm_inst);
1662 return;
1663 }
1664
Hon Ching \(Vicky\) Lob4ed0462015-10-07 20:11:53 -04001665 if (prom_getprop(ibmvtpm_node, "ibm,sml-efi-reformat-supported",
1666 &val, sizeof(val)) != PROM_ERROR) {
1667 if (call_prom_ret("call-method", 2, 2, &succ,
1668 ADDR("reformat-sml-to-efi-alignment"),
1669 ibmvtpm_inst) != 0 || succ == 0) {
1670 prom_printf("Reformat SML to EFI alignment failed\n");
1671 return;
1672 }
Hon Ching \(Vicky\) Lob4ed0462015-10-07 20:11:53 -04001673
Hon Ching \(Vicky\) Lo9e5d4af2015-10-07 20:11:54 -04001674 if (call_prom_ret("call-method", 2, 2, &size,
1675 ADDR("sml-get-allocated-size"),
1676 ibmvtpm_inst) != 0 || size == 0) {
1677 prom_printf("SML get allocated size failed\n");
1678 return;
1679 }
1680 } else {
1681 if (call_prom_ret("call-method", 2, 2, &size,
1682 ADDR("sml-get-handover-size"),
1683 ibmvtpm_inst) != 0 || size == 0) {
1684 prom_printf("SML get handover size failed\n");
1685 return;
1686 }
Ashley Lai4a727422012-08-14 18:34:57 -05001687 }
1688
1689 base = alloc_down(size, PAGE_SIZE, 0);
1690 if (base == 0)
1691 prom_panic("Could not allocate memory for sml\n");
1692
Mathieu Malaterreeae5f702018-04-06 22:12:19 +02001693 prom_printf("instantiating sml at 0x%llx...", base);
Ashley Lai4a727422012-08-14 18:34:57 -05001694
Hon Ching \(Vicky\) Lo9e5d4af2015-10-07 20:11:54 -04001695 memset((void *)base, 0, size);
1696
Ashley Lai4a727422012-08-14 18:34:57 -05001697 if (call_prom_ret("call-method", 4, 2, &entry,
1698 ADDR("sml-handover"),
1699 ibmvtpm_inst, size, base) != 0 || entry == 0) {
1700 prom_printf("SML handover failed\n");
1701 return;
1702 }
1703 prom_printf(" done\n");
1704
1705 reserve_mem(base, size);
1706
Hon Ching \(Vicky\) Lo2f82e982015-10-07 20:11:52 -04001707 prom_setprop(ibmvtpm_node, "/vdevice/vtpm", "linux,sml-base",
Ashley Lai4a727422012-08-14 18:34:57 -05001708 &base, sizeof(base));
Hon Ching \(Vicky\) Lo2f82e982015-10-07 20:11:52 -04001709 prom_setprop(ibmvtpm_node, "/vdevice/vtpm", "linux,sml-size",
Ashley Lai4a727422012-08-14 18:34:57 -05001710 &size, sizeof(size));
1711
Mathieu Malaterreeae5f702018-04-06 22:12:19 +02001712 prom_debug("sml base = 0x%llx\n", base);
1713 prom_debug("sml size = 0x%x\n", size);
Ashley Lai4a727422012-08-14 18:34:57 -05001714
1715 prom_debug("prom_instantiate_sml: end...\n");
1716}
1717
1718/*
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001719 * Allocate room for and initialize TCE tables
1720 */
Benjamin Herrenschmidt493adff2013-08-07 02:01:38 +10001721#ifdef __BIG_ENDIAN__
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001722static void __init prom_initialize_tce_table(void)
1723{
1724 phandle node;
1725 ihandle phb_node;
1726 char compatible[64], type[64], model[64];
Anton Blanchard5827d412012-11-26 17:40:03 +00001727 char *path = prom_scratch;
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001728 u64 base, align;
1729 u32 minalign, minsize;
1730 u64 tce_entry, *tce_entryp;
1731 u64 local_alloc_top, local_alloc_bottom;
1732 u64 i;
1733
Anton Blanchard5827d412012-11-26 17:40:03 +00001734 if (prom_iommu_off)
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001735 return;
1736
1737 prom_debug("starting prom_initialize_tce_table\n");
1738
1739 /* Cache current top of allocs so we reserve a single block */
Anton Blanchard5827d412012-11-26 17:40:03 +00001740 local_alloc_top = alloc_top_high;
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001741 local_alloc_bottom = local_alloc_top;
1742
1743 /* Search all nodes looking for PHBs. */
1744 for (node = 0; prom_next_node(&node); ) {
1745 compatible[0] = 0;
1746 type[0] = 0;
1747 model[0] = 0;
1748 prom_getprop(node, "compatible",
1749 compatible, sizeof(compatible));
1750 prom_getprop(node, "device_type", type, sizeof(type));
1751 prom_getprop(node, "model", model, sizeof(model));
1752
Anton Blanchard5827d412012-11-26 17:40:03 +00001753 if ((type[0] == 0) || (strstr(type, "pci") == NULL))
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001754 continue;
1755
Linas Vepstase788ff12007-09-07 03:45:21 +10001756 /* Keep the old logic intact to avoid regression. */
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001757 if (compatible[0] != 0) {
Anton Blanchard5827d412012-11-26 17:40:03 +00001758 if ((strstr(compatible, "python") == NULL) &&
1759 (strstr(compatible, "Speedwagon") == NULL) &&
1760 (strstr(compatible, "Winnipeg") == NULL))
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001761 continue;
1762 } else if (model[0] != 0) {
Anton Blanchard5827d412012-11-26 17:40:03 +00001763 if ((strstr(model, "ython") == NULL) &&
1764 (strstr(model, "peedwagon") == NULL) &&
1765 (strstr(model, "innipeg") == NULL))
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001766 continue;
1767 }
1768
1769 if (prom_getprop(node, "tce-table-minalign", &minalign,
1770 sizeof(minalign)) == PROM_ERROR)
1771 minalign = 0;
1772 if (prom_getprop(node, "tce-table-minsize", &minsize,
1773 sizeof(minsize)) == PROM_ERROR)
1774 minsize = 4UL << 20;
1775
1776 /*
1777 * Even though we read what OF wants, we just set the table
1778 * size to 4 MB. This is enough to map 2GB of PCI DMA space.
1779 * By doing this, we avoid the pitfalls of trying to DMA to
1780 * MMIO space and the DMA alias hole.
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001781 */
Nicholas Piggin471d7ff2018-02-21 05:08:29 +10001782 minsize = 4UL << 20;
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001783
1784 /* Align to the greater of the align or size */
1785 align = max(minalign, minsize);
1786 base = alloc_down(minsize, align, 1);
1787 if (base == 0)
1788 prom_panic("ERROR, cannot find space for TCE table.\n");
1789 if (base < local_alloc_bottom)
1790 local_alloc_bottom = base;
1791
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001792 /* It seems OF doesn't null-terminate the path :-( */
Li Zefanaca71ef2007-11-05 13:21:56 +11001793 memset(path, 0, PROM_SCRATCH_SIZE);
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001794 /* Call OF to setup the TCE hardware */
1795 if (call_prom("package-to-path", 3, 1, node,
1796 path, PROM_SCRATCH_SIZE-1) == PROM_ERROR) {
1797 prom_printf("package-to-path failed\n");
1798 }
1799
Paul Mackerrasa23414b2005-11-10 12:00:55 +11001800 /* Save away the TCE table attributes for later use. */
1801 prom_setprop(node, path, "linux,tce-base", &base, sizeof(base));
1802 prom_setprop(node, path, "linux,tce-size", &minsize, sizeof(minsize));
1803
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001804 prom_debug("TCE table: %s\n", path);
1805 prom_debug("\tnode = 0x%x\n", node);
Mathieu Malaterreeae5f702018-04-06 22:12:19 +02001806 prom_debug("\tbase = 0x%llx\n", base);
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001807 prom_debug("\tsize = 0x%x\n", minsize);
1808
1809 /* Initialize the table to have a one-to-one mapping
1810 * over the allocated size.
1811 */
Ingo Molnar2b931fb2009-01-06 13:56:52 +00001812 tce_entryp = (u64 *)base;
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001813 for (i = 0; i < (minsize >> 3) ;tce_entryp++, i++) {
1814 tce_entry = (i << PAGE_SHIFT);
1815 tce_entry |= 0x3;
1816 *tce_entryp = tce_entry;
1817 }
1818
1819 prom_printf("opening PHB %s", path);
1820 phb_node = call_prom("open", 1, 1, path);
1821 if (phb_node == 0)
1822 prom_printf("... failed\n");
1823 else
1824 prom_printf("... done\n");
1825
1826 call_prom("call-method", 6, 0, ADDR("set-64-bit-addressing"),
1827 phb_node, -1, minsize,
1828 (u32) base, (u32) (base >> 32));
1829 call_prom("close", 1, 0, phb_node);
1830 }
1831
1832 reserve_mem(local_alloc_bottom, local_alloc_top - local_alloc_bottom);
1833
Michael Ellerman2babf5c2006-05-17 18:00:46 +10001834 /* These are only really needed if there is a memory limit in
1835 * effect, but we don't know so export them always. */
Anton Blanchard5827d412012-11-26 17:40:03 +00001836 prom_tce_alloc_start = local_alloc_bottom;
1837 prom_tce_alloc_end = local_alloc_top;
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001838
1839 /* Flag the first invalid entry */
1840 prom_debug("ending prom_initialize_tce_table\n");
1841}
Benjamin Herrenschmidt493adff2013-08-07 02:01:38 +10001842#endif /* __BIG_ENDIAN__ */
1843#endif /* CONFIG_PPC64 */
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001844
1845/*
1846 * With CHRP SMP we need to use the OF to start the other processors.
1847 * We can't wait until smp_boot_cpus (the OF is trashed by then)
1848 * so we have to put the processors into a holding pattern controlled
1849 * by the kernel (not OF) before we destroy the OF.
1850 *
1851 * This uses a chunk of low memory, puts some holding pattern
1852 * code there and sends the other processors off to there until
1853 * smp_boot_cpus tells them to do something. The holding pattern
1854 * checks that address until its cpu # is there, when it is that
1855 * cpu jumps to __secondary_start(). smp_boot_cpus() takes care
1856 * of setting those values.
1857 *
1858 * We also use physical address 0x4 here to tell when a cpu
1859 * is in its holding pattern code.
1860 *
1861 * -- Cort
1862 */
Paul Mackerrasbbd0abd2005-10-26 21:45:56 +10001863/*
1864 * We want to reference the copy of __secondary_hold_* in the
1865 * 0 - 0x100 address range
1866 */
1867#define LOW_ADDR(x) (((unsigned long) &(x)) & 0xff)
1868
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001869static void __init prom_hold_cpus(void)
1870{
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001871 unsigned long i;
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001872 phandle node;
1873 char type[64];
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001874 unsigned long *spinloop
Paul Mackerrasbbd0abd2005-10-26 21:45:56 +10001875 = (void *) LOW_ADDR(__secondary_hold_spinloop);
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001876 unsigned long *acknowledge
Paul Mackerrasbbd0abd2005-10-26 21:45:56 +10001877 = (void *) LOW_ADDR(__secondary_hold_acknowledge);
Paul Mackerrasbbd0abd2005-10-26 21:45:56 +10001878 unsigned long secondary_hold = LOW_ADDR(__secondary_hold);
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001879
Benjamin Herrenschmidtdbe78b42013-09-25 14:02:50 +10001880 /*
1881 * On pseries, if RTAS supports "query-cpu-stopped-state",
1882 * we skip this stage, the CPUs will be started by the
1883 * kernel using RTAS.
1884 */
1885 if ((of_platform == PLATFORM_PSERIES ||
1886 of_platform == PLATFORM_PSERIES_LPAR) &&
1887 rtas_has_query_cpu_stopped) {
1888 prom_printf("prom_hold_cpus: skipped\n");
1889 return;
1890 }
1891
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001892 prom_debug("prom_hold_cpus: start...\n");
Mathieu Malaterreeae5f702018-04-06 22:12:19 +02001893 prom_debug(" 1) spinloop = 0x%lx\n", (unsigned long)spinloop);
1894 prom_debug(" 1) *spinloop = 0x%lx\n", *spinloop);
1895 prom_debug(" 1) acknowledge = 0x%lx\n",
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001896 (unsigned long)acknowledge);
Mathieu Malaterreeae5f702018-04-06 22:12:19 +02001897 prom_debug(" 1) *acknowledge = 0x%lx\n", *acknowledge);
1898 prom_debug(" 1) secondary_hold = 0x%lx\n", secondary_hold);
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001899
1900 /* Set the common spinloop variable, so all of the secondary cpus
1901 * will block when they are awakened from their OF spinloop.
1902 * This must occur for both SMP and non SMP kernels, since OF will
1903 * be trashed when we move the kernel.
1904 */
1905 *spinloop = 0;
1906
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001907 /* look for cpus */
1908 for (node = 0; prom_next_node(&node); ) {
Benjamin Herrenschmidt493adff2013-08-07 02:01:38 +10001909 unsigned int cpu_no;
1910 __be32 reg;
1911
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001912 type[0] = 0;
1913 prom_getprop(node, "device_type", type, sizeof(type));
Anton Blanchard5827d412012-11-26 17:40:03 +00001914 if (strcmp(type, "cpu") != 0)
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001915 continue;
1916
1917 /* Skip non-configured cpus. */
1918 if (prom_getprop(node, "status", type, sizeof(type)) > 0)
Anton Blanchard5827d412012-11-26 17:40:03 +00001919 if (strcmp(type, "okay") != 0)
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001920 continue;
1921
Benjamin Herrenschmidt493adff2013-08-07 02:01:38 +10001922 reg = cpu_to_be32(-1); /* make sparse happy */
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001923 prom_getprop(node, "reg", &reg, sizeof(reg));
Benjamin Herrenschmidt493adff2013-08-07 02:01:38 +10001924 cpu_no = be32_to_cpu(reg);
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001925
Mathieu Malaterreeae5f702018-04-06 22:12:19 +02001926 prom_debug("cpu hw idx = %u\n", cpu_no);
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001927
1928 /* Init the acknowledge var which will be reset by
1929 * the secondary cpu when it awakens from its OF
1930 * spinloop.
1931 */
1932 *acknowledge = (unsigned long)-1;
1933
Benjamin Herrenschmidt493adff2013-08-07 02:01:38 +10001934 if (cpu_no != prom.cpu) {
Benjamin Herrenschmidt27f44882011-09-19 18:27:58 +00001935 /* Primary Thread of non-boot cpu or any thread */
Mathieu Malaterreeae5f702018-04-06 22:12:19 +02001936 prom_printf("starting cpu hw idx %u... ", cpu_no);
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001937 call_prom("start-cpu", 3, 0, node,
Benjamin Herrenschmidt493adff2013-08-07 02:01:38 +10001938 secondary_hold, cpu_no);
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001939
Paul Mackerrasbbd0abd2005-10-26 21:45:56 +10001940 for (i = 0; (i < 100000000) &&
1941 (*acknowledge == ((unsigned long)-1)); i++ )
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001942 mb();
1943
Benjamin Herrenschmidt493adff2013-08-07 02:01:38 +10001944 if (*acknowledge == cpu_no)
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001945 prom_printf("done\n");
Paul Mackerrasbbd0abd2005-10-26 21:45:56 +10001946 else
Mathieu Malaterreeae5f702018-04-06 22:12:19 +02001947 prom_printf("failed: %lx\n", *acknowledge);
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001948 }
1949#ifdef CONFIG_SMP
1950 else
Mathieu Malaterreeae5f702018-04-06 22:12:19 +02001951 prom_printf("boot cpu hw idx %u\n", cpu_no);
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001952#endif /* CONFIG_SMP */
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001953 }
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001954
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001955 prom_debug("prom_hold_cpus: end...\n");
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001956}
1957
1958
1959static void __init prom_init_client_services(unsigned long pp)
1960{
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001961 /* Get a handle to the prom entry point before anything else */
Anton Blanchard5827d412012-11-26 17:40:03 +00001962 prom_entry = pp;
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001963
1964 /* get a handle for the stdout device */
Anton Blanchard5827d412012-11-26 17:40:03 +00001965 prom.chosen = call_prom("finddevice", 1, 1, ADDR("/chosen"));
1966 if (!PHANDLE_VALID(prom.chosen))
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001967 prom_panic("cannot find chosen"); /* msg won't be printed :( */
1968
1969 /* get device tree root */
Anton Blanchard5827d412012-11-26 17:40:03 +00001970 prom.root = call_prom("finddevice", 1, 1, ADDR("/"));
1971 if (!PHANDLE_VALID(prom.root))
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001972 prom_panic("cannot find device tree root"); /* msg won't be printed :( */
Paul Mackerrasa575b802005-10-23 17:23:21 +10001973
Anton Blanchard5827d412012-11-26 17:40:03 +00001974 prom.mmumap = 0;
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001975}
1976
Paul Mackerrasa575b802005-10-23 17:23:21 +10001977#ifdef CONFIG_PPC32
1978/*
1979 * For really old powermacs, we need to map things we claim.
1980 * For that, we need the ihandle of the mmu.
Paul Mackerrasa23414b2005-11-10 12:00:55 +11001981 * Also, on the longtrail, we need to work around other bugs.
Paul Mackerrasa575b802005-10-23 17:23:21 +10001982 */
1983static void __init prom_find_mmu(void)
1984{
Paul Mackerrasa575b802005-10-23 17:23:21 +10001985 phandle oprom;
1986 char version[64];
1987
1988 oprom = call_prom("finddevice", 1, 1, ADDR("/openprom"));
1989 if (!PHANDLE_VALID(oprom))
1990 return;
1991 if (prom_getprop(oprom, "model", version, sizeof(version)) <= 0)
1992 return;
1993 version[sizeof(version) - 1] = 0;
Paul Mackerrasa575b802005-10-23 17:23:21 +10001994 /* XXX might need to add other versions here */
Paul Mackerrasa23414b2005-11-10 12:00:55 +11001995 if (strcmp(version, "Open Firmware, 1.0.5") == 0)
1996 of_workarounds = OF_WA_CLAIM;
1997 else if (strncmp(version, "FirmWorks,3.", 12) == 0) {
1998 of_workarounds = OF_WA_CLAIM | OF_WA_LONGTRAIL;
1999 call_prom("interpret", 1, 1, "dev /memory 0 to allow-reclaim");
2000 } else
Paul Mackerrasa575b802005-10-23 17:23:21 +10002001 return;
Anton Blanchard5827d412012-11-26 17:40:03 +00002002 prom.memory = call_prom("open", 1, 1, ADDR("/memory"));
2003 prom_getprop(prom.chosen, "mmu", &prom.mmumap,
2004 sizeof(prom.mmumap));
Benjamin Herrenschmidt493adff2013-08-07 02:01:38 +10002005 prom.mmumap = be32_to_cpu(prom.mmumap);
Anton Blanchard5827d412012-11-26 17:40:03 +00002006 if (!IHANDLE_VALID(prom.memory) || !IHANDLE_VALID(prom.mmumap))
Paul Mackerrasa23414b2005-11-10 12:00:55 +11002007 of_workarounds &= ~OF_WA_CLAIM; /* hmmm */
Paul Mackerrasa575b802005-10-23 17:23:21 +10002008}
2009#else
2010#define prom_find_mmu()
2011#endif
2012
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002013static void __init prom_init_stdout(void)
2014{
Anton Blanchard5827d412012-11-26 17:40:03 +00002015 char *path = of_stdout_device;
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002016 char type[16];
Benjamin Herrenschmidt493adff2013-08-07 02:01:38 +10002017 phandle stdout_node;
2018 __be32 val;
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002019
Anton Blanchard5827d412012-11-26 17:40:03 +00002020 if (prom_getprop(prom.chosen, "stdout", &val, sizeof(val)) <= 0)
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002021 prom_panic("cannot find stdout");
2022
Benjamin Herrenschmidt493adff2013-08-07 02:01:38 +10002023 prom.stdout = be32_to_cpu(val);
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002024
2025 /* Get the full OF pathname of the stdout device */
2026 memset(path, 0, 256);
Anton Blanchard5827d412012-11-26 17:40:03 +00002027 call_prom("instance-to-path", 3, 1, prom.stdout, path, 255);
Anton Blanchard5827d412012-11-26 17:40:03 +00002028 prom_printf("OF stdout device is: %s\n", of_stdout_device);
2029 prom_setprop(prom.chosen, "/chosen", "linux,stdout-path",
Paul Mackerrasa23414b2005-11-10 12:00:55 +11002030 path, strlen(path) + 1);
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002031
Benjamin Herrenschmidt10348f52014-01-13 09:49:17 +11002032 /* instance-to-package fails on PA-Semi */
2033 stdout_node = call_prom("instance-to-package", 1, 1, prom.stdout);
2034 if (stdout_node != PROM_ERROR) {
2035 val = cpu_to_be32(stdout_node);
Benjamin Herrenschmidt10348f52014-01-13 09:49:17 +11002036
2037 /* If it's a display, note it */
2038 memset(type, 0, sizeof(type));
2039 prom_getprop(stdout_node, "device_type", type, sizeof(type));
2040 if (strcmp(type, "display") == 0)
2041 prom_setprop(stdout_node, path, "linux,boot-display", NULL, 0);
2042 }
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002043}
2044
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002045static int __init prom_find_machine_type(void)
2046{
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002047 char compat[256];
2048 int len, i = 0;
Benjamin Herrenschmidt21fe3302005-11-07 16:41:59 +11002049#ifdef CONFIG_PPC64
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002050 phandle rtas;
Benjamin Herrenschmidte8222502006-03-28 23:15:54 +11002051 int x;
Benjamin Herrenschmidt21fe3302005-11-07 16:41:59 +11002052#endif
Benjamin Herrenschmidte8222502006-03-28 23:15:54 +11002053
Benjamin Herrenschmidt6e35d5d2011-09-19 18:28:01 +00002054 /* Look for a PowerMac or a Cell */
Anton Blanchard5827d412012-11-26 17:40:03 +00002055 len = prom_getprop(prom.root, "compatible",
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002056 compat, sizeof(compat)-1);
2057 if (len > 0) {
2058 compat[len] = 0;
2059 while (i < len) {
2060 char *p = &compat[i];
2061 int sl = strlen(p);
2062 if (sl == 0)
2063 break;
Anton Blanchard5827d412012-11-26 17:40:03 +00002064 if (strstr(p, "Power Macintosh") ||
2065 strstr(p, "MacRISC"))
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002066 return PLATFORM_POWERMAC;
Arnd Bergmann133dda12006-06-07 12:04:18 +10002067#ifdef CONFIG_PPC64
2068 /* We must make sure we don't detect the IBM Cell
2069 * blades as pSeries due to some firmware issues,
2070 * so we do it here.
2071 */
Anton Blanchard5827d412012-11-26 17:40:03 +00002072 if (strstr(p, "IBM,CBEA") ||
2073 strstr(p, "IBM,CPBW-1.0"))
Arnd Bergmann133dda12006-06-07 12:04:18 +10002074 return PLATFORM_GENERIC;
2075#endif /* CONFIG_PPC64 */
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002076 i += sl + 1;
2077 }
2078 }
2079#ifdef CONFIG_PPC64
Benjamin Herrenschmidt6e35d5d2011-09-19 18:28:01 +00002080 /* Try to figure out if it's an IBM pSeries or any other
Benjamin Herrenschmidte8222502006-03-28 23:15:54 +11002081 * PAPR compliant platform. We assume it is if :
2082 * - /device_type is "chrp" (please, do NOT use that for future
2083 * non-IBM designs !
2084 * - it has /rtas
2085 */
Anton Blanchard5827d412012-11-26 17:40:03 +00002086 len = prom_getprop(prom.root, "device_type",
Benjamin Herrenschmidte8222502006-03-28 23:15:54 +11002087 compat, sizeof(compat)-1);
2088 if (len <= 0)
2089 return PLATFORM_GENERIC;
Anton Blanchard5827d412012-11-26 17:40:03 +00002090 if (strcmp(compat, "chrp"))
Benjamin Herrenschmidte8222502006-03-28 23:15:54 +11002091 return PLATFORM_GENERIC;
2092
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002093 /* Default to pSeries. We need to know if we are running LPAR */
2094 rtas = call_prom("finddevice", 1, 1, ADDR("/rtas"));
Benjamin Herrenschmidte8222502006-03-28 23:15:54 +11002095 if (!PHANDLE_VALID(rtas))
2096 return PLATFORM_GENERIC;
2097 x = prom_getproplen(rtas, "ibm,hypertas-functions");
2098 if (x != PROM_ERROR) {
Anton Blanchard4da727a2009-03-31 20:06:14 +00002099 prom_debug("Hypertas detected, assuming LPAR !\n");
Benjamin Herrenschmidte8222502006-03-28 23:15:54 +11002100 return PLATFORM_PSERIES_LPAR;
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002101 }
2102 return PLATFORM_PSERIES;
2103#else
Benjamin Herrenschmidte8222502006-03-28 23:15:54 +11002104 return PLATFORM_GENERIC;
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002105#endif
2106}
2107
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002108static int __init prom_set_color(ihandle ih, int i, int r, int g, int b)
2109{
2110 return call_prom("call-method", 6, 1, ADDR("color!"), ih, i, b, g, r);
2111}
2112
2113/*
2114 * If we have a display that we don't know how to drive,
2115 * we will want to try to execute OF's open method for it
2116 * later. However, OF will probably fall over if we do that
2117 * we've taken over the MMU.
2118 * So we check whether we will need to open the display,
2119 * and if so, open it now.
2120 */
2121static void __init prom_check_displays(void)
2122{
2123 char type[16], *path;
2124 phandle node;
2125 ihandle ih;
2126 int i;
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002127
Benjamin Herrenschmidt7f995d32018-05-31 14:33:41 +10002128 static const unsigned char default_colors[] = {
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002129 0x00, 0x00, 0x00,
2130 0x00, 0x00, 0xaa,
2131 0x00, 0xaa, 0x00,
2132 0x00, 0xaa, 0xaa,
2133 0xaa, 0x00, 0x00,
2134 0xaa, 0x00, 0xaa,
2135 0xaa, 0xaa, 0x00,
2136 0xaa, 0xaa, 0xaa,
2137 0x55, 0x55, 0x55,
2138 0x55, 0x55, 0xff,
2139 0x55, 0xff, 0x55,
2140 0x55, 0xff, 0xff,
2141 0xff, 0x55, 0x55,
2142 0xff, 0x55, 0xff,
2143 0xff, 0xff, 0x55,
2144 0xff, 0xff, 0xff
2145 };
2146 const unsigned char *clut;
2147
Anton Blanchard4da727a2009-03-31 20:06:14 +00002148 prom_debug("Looking for displays\n");
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002149 for (node = 0; prom_next_node(&node); ) {
2150 memset(type, 0, sizeof(type));
2151 prom_getprop(node, "device_type", type, sizeof(type));
Anton Blanchard5827d412012-11-26 17:40:03 +00002152 if (strcmp(type, "display") != 0)
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002153 continue;
2154
2155 /* It seems OF doesn't null-terminate the path :-( */
Anton Blanchard5827d412012-11-26 17:40:03 +00002156 path = prom_scratch;
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002157 memset(path, 0, PROM_SCRATCH_SIZE);
2158
2159 /*
2160 * leave some room at the end of the path for appending extra
2161 * arguments
2162 */
2163 if (call_prom("package-to-path", 3, 1, node, path,
2164 PROM_SCRATCH_SIZE-10) == PROM_ERROR)
2165 continue;
Anton Blanchard1f8737a2009-03-31 20:06:15 +00002166 prom_printf("found display : %s, opening... ", path);
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002167
2168 ih = call_prom("open", 1, 1, path);
2169 if (ih == 0) {
2170 prom_printf("failed\n");
2171 continue;
2172 }
2173
2174 /* Success */
2175 prom_printf("done\n");
Paul Mackerrasa23414b2005-11-10 12:00:55 +11002176 prom_setprop(node, path, "linux,opened", NULL, 0);
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002177
2178 /* Setup a usable color table when the appropriate
2179 * method is available. Should update this to set-colors */
Anton Blanchard5827d412012-11-26 17:40:03 +00002180 clut = default_colors;
Benjamin Herrenschmidt3f536382011-12-14 13:55:11 +00002181 for (i = 0; i < 16; i++, clut += 3)
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002182 if (prom_set_color(ih, i, clut[0], clut[1],
2183 clut[2]) != 0)
2184 break;
2185
2186#ifdef CONFIG_LOGO_LINUX_CLUT224
Anton Blanchard5827d412012-11-26 17:40:03 +00002187 clut = PTRRELOC(logo_linux_clut224.clut);
2188 for (i = 0; i < logo_linux_clut224.clutsize; i++, clut += 3)
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002189 if (prom_set_color(ih, i + 32, clut[0], clut[1],
2190 clut[2]) != 0)
2191 break;
2192#endif /* CONFIG_LOGO_LINUX_CLUT224 */
Benjamin Herrenschmidt7191b612013-07-25 12:12:32 +10002193
2194#ifdef CONFIG_PPC_EARLY_DEBUG_BOOTX
2195 if (prom_getprop(node, "linux,boot-display", NULL, 0) !=
2196 PROM_ERROR) {
2197 u32 width, height, pitch, addr;
2198
2199 prom_printf("Setting btext !\n");
2200 prom_getprop(node, "width", &width, 4);
2201 prom_getprop(node, "height", &height, 4);
2202 prom_getprop(node, "linebytes", &pitch, 4);
2203 prom_getprop(node, "address", &addr, 4);
2204 prom_printf("W=%d H=%d LB=%d addr=0x%x\n",
2205 width, height, pitch, addr);
2206 btext_setup_display(width, height, 8, pitch, addr);
2207 }
2208#endif /* CONFIG_PPC_EARLY_DEBUG_BOOTX */
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002209 }
2210}
2211
2212
2213/* Return (relocated) pointer to this much memory: moves initrd if reqd. */
2214static void __init *make_room(unsigned long *mem_start, unsigned long *mem_end,
2215 unsigned long needed, unsigned long align)
2216{
2217 void *ret;
2218
2219 *mem_start = _ALIGN(*mem_start, align);
2220 while ((*mem_start + needed) > *mem_end) {
2221 unsigned long room, chunk;
2222
Mathieu Malaterreeae5f702018-04-06 22:12:19 +02002223 prom_debug("Chunk exhausted, claiming more at %lx...\n",
Anton Blanchard5827d412012-11-26 17:40:03 +00002224 alloc_bottom);
2225 room = alloc_top - alloc_bottom;
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002226 if (room > DEVTREE_CHUNK_SIZE)
2227 room = DEVTREE_CHUNK_SIZE;
2228 if (room < PAGE_SIZE)
Anton Blanchardfbafd722011-07-25 20:47:51 +00002229 prom_panic("No memory for flatten_device_tree "
2230 "(no room)\n");
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002231 chunk = alloc_up(room, 0);
2232 if (chunk == 0)
Anton Blanchardfbafd722011-07-25 20:47:51 +00002233 prom_panic("No memory for flatten_device_tree "
2234 "(claim failed)\n");
Anton Blanchard966728d2011-07-25 20:47:07 +00002235 *mem_end = chunk + room;
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002236 }
2237
2238 ret = (void *)*mem_start;
2239 *mem_start += needed;
2240
2241 return ret;
2242}
2243
Benjamin Herrenschmidt493adff2013-08-07 02:01:38 +10002244#define dt_push_token(token, mem_start, mem_end) do { \
2245 void *room = make_room(mem_start, mem_end, 4, 4); \
2246 *(__be32 *)room = cpu_to_be32(token); \
2247 } while(0)
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002248
2249static unsigned long __init dt_find_string(char *str)
2250{
2251 char *s, *os;
2252
Anton Blanchard5827d412012-11-26 17:40:03 +00002253 s = os = (char *)dt_string_start;
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002254 s += 4;
Anton Blanchard5827d412012-11-26 17:40:03 +00002255 while (s < (char *)dt_string_end) {
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002256 if (strcmp(s, str) == 0)
2257 return s - os;
2258 s += strlen(s) + 1;
2259 }
2260 return 0;
2261}
2262
2263/*
2264 * The Open Firmware 1275 specification states properties must be 31 bytes or
2265 * less, however not all firmwares obey this. Make it 64 bytes to be safe.
2266 */
2267#define MAX_PROPERTY_NAME 64
2268
2269static void __init scan_dt_build_strings(phandle node,
2270 unsigned long *mem_start,
2271 unsigned long *mem_end)
2272{
2273 char *prev_name, *namep, *sstart;
2274 unsigned long soff;
2275 phandle child;
2276
Anton Blanchard5827d412012-11-26 17:40:03 +00002277 sstart = (char *)dt_string_start;
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002278
2279 /* get and store all property names */
Anton Blanchard5827d412012-11-26 17:40:03 +00002280 prev_name = "";
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002281 for (;;) {
2282 /* 64 is max len of name including nul. */
2283 namep = make_room(mem_start, mem_end, MAX_PROPERTY_NAME, 1);
2284 if (call_prom("nextprop", 3, 1, node, prev_name, namep) != 1) {
2285 /* No more nodes: unwind alloc */
2286 *mem_start = (unsigned long)namep;
2287 break;
2288 }
2289
2290 /* skip "name" */
Anton Blanchard5827d412012-11-26 17:40:03 +00002291 if (strcmp(namep, "name") == 0) {
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002292 *mem_start = (unsigned long)namep;
Anton Blanchard5827d412012-11-26 17:40:03 +00002293 prev_name = "name";
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002294 continue;
2295 }
2296 /* get/create string entry */
2297 soff = dt_find_string(namep);
2298 if (soff != 0) {
2299 *mem_start = (unsigned long)namep;
2300 namep = sstart + soff;
2301 } else {
2302 /* Trim off some if we can */
2303 *mem_start = (unsigned long)namep + strlen(namep) + 1;
Anton Blanchard5827d412012-11-26 17:40:03 +00002304 dt_string_end = *mem_start;
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002305 }
2306 prev_name = namep;
2307 }
2308
2309 /* do all our children */
2310 child = call_prom("child", 1, 1, node);
2311 while (child != 0) {
2312 scan_dt_build_strings(child, mem_start, mem_end);
2313 child = call_prom("peer", 1, 1, child);
2314 }
2315}
2316
2317static void __init scan_dt_build_struct(phandle node, unsigned long *mem_start,
2318 unsigned long *mem_end)
2319{
2320 phandle child;
2321 char *namep, *prev_name, *sstart, *p, *ep, *lp, *path;
2322 unsigned long soff;
2323 unsigned char *valp;
2324 static char pname[MAX_PROPERTY_NAME];
Benjamin Herrenschmidt6e35d5d2011-09-19 18:28:01 +00002325 int l, room, has_phandle = 0;
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002326
2327 dt_push_token(OF_DT_BEGIN_NODE, mem_start, mem_end);
2328
2329 /* get the node's full name */
2330 namep = (char *)*mem_start;
Paul Mackerrasc49888202005-10-26 21:52:53 +10002331 room = *mem_end - *mem_start;
2332 if (room > 255)
2333 room = 255;
2334 l = call_prom("package-to-path", 3, 1, node, namep, room);
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002335 if (l >= 0) {
2336 /* Didn't fit? Get more room. */
Paul Mackerrasc49888202005-10-26 21:52:53 +10002337 if (l >= room) {
2338 if (l >= *mem_end - *mem_start)
2339 namep = make_room(mem_start, mem_end, l+1, 1);
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002340 call_prom("package-to-path", 3, 1, node, namep, l);
2341 }
2342 namep[l] = '\0';
2343
2344 /* Fixup an Apple bug where they have bogus \0 chars in the
Paul Mackerrasa575b802005-10-23 17:23:21 +10002345 * middle of the path in some properties, and extract
2346 * the unit name (everything after the last '/').
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002347 */
Paul Mackerrasa575b802005-10-23 17:23:21 +10002348 for (lp = p = namep, ep = namep + l; p < ep; p++) {
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002349 if (*p == '/')
Paul Mackerrasa575b802005-10-23 17:23:21 +10002350 lp = namep;
2351 else if (*p != 0)
2352 *lp++ = *p;
2353 }
2354 *lp = 0;
2355 *mem_start = _ALIGN((unsigned long)lp + 1, 4);
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002356 }
2357
2358 /* get it again for debugging */
Anton Blanchard5827d412012-11-26 17:40:03 +00002359 path = prom_scratch;
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002360 memset(path, 0, PROM_SCRATCH_SIZE);
2361 call_prom("package-to-path", 3, 1, node, path, PROM_SCRATCH_SIZE-1);
2362
2363 /* get and store all properties */
Anton Blanchard5827d412012-11-26 17:40:03 +00002364 prev_name = "";
2365 sstart = (char *)dt_string_start;
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002366 for (;;) {
2367 if (call_prom("nextprop", 3, 1, node, prev_name,
Anton Blanchard5827d412012-11-26 17:40:03 +00002368 pname) != 1)
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002369 break;
2370
2371 /* skip "name" */
Anton Blanchard5827d412012-11-26 17:40:03 +00002372 if (strcmp(pname, "name") == 0) {
2373 prev_name = "name";
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002374 continue;
2375 }
2376
2377 /* find string offset */
Anton Blanchard5827d412012-11-26 17:40:03 +00002378 soff = dt_find_string(pname);
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002379 if (soff == 0) {
2380 prom_printf("WARNING: Can't find string index for"
Anton Blanchard5827d412012-11-26 17:40:03 +00002381 " <%s>, node %s\n", pname, path);
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002382 break;
2383 }
2384 prev_name = sstart + soff;
2385
2386 /* get length */
Anton Blanchard5827d412012-11-26 17:40:03 +00002387 l = call_prom("getproplen", 2, 1, node, pname);
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002388
2389 /* sanity checks */
2390 if (l == PROM_ERROR)
2391 continue;
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002392
2393 /* push property head */
2394 dt_push_token(OF_DT_PROP, mem_start, mem_end);
2395 dt_push_token(l, mem_start, mem_end);
2396 dt_push_token(soff, mem_start, mem_end);
2397
2398 /* push property content */
2399 valp = make_room(mem_start, mem_end, l, 4);
Anton Blanchard5827d412012-11-26 17:40:03 +00002400 call_prom("getprop", 4, 1, node, pname, valp, l);
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002401 *mem_start = _ALIGN(*mem_start, 4);
Benjamin Herrenschmidt6e35d5d2011-09-19 18:28:01 +00002402
Anton Blanchard5827d412012-11-26 17:40:03 +00002403 if (!strcmp(pname, "phandle"))
Benjamin Herrenschmidt6e35d5d2011-09-19 18:28:01 +00002404 has_phandle = 1;
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002405 }
2406
Benjamin Herrenschmidt6e35d5d2011-09-19 18:28:01 +00002407 /* Add a "linux,phandle" property if no "phandle" property already
Benjamin Herrenschmidt11fdb302018-10-15 13:49:53 +11002408 * existed.
Benjamin Herrenschmidt6e35d5d2011-09-19 18:28:01 +00002409 */
2410 if (!has_phandle) {
Anton Blanchard5827d412012-11-26 17:40:03 +00002411 soff = dt_find_string("linux,phandle");
Benjamin Herrenschmidt6e35d5d2011-09-19 18:28:01 +00002412 if (soff == 0)
2413 prom_printf("WARNING: Can't find string index for"
2414 " <linux-phandle> node %s\n", path);
2415 else {
2416 dt_push_token(OF_DT_PROP, mem_start, mem_end);
2417 dt_push_token(4, mem_start, mem_end);
2418 dt_push_token(soff, mem_start, mem_end);
2419 valp = make_room(mem_start, mem_end, 4, 4);
Benjamin Herrenschmidt493adff2013-08-07 02:01:38 +10002420 *(__be32 *)valp = cpu_to_be32(node);
Benjamin Herrenschmidt6e35d5d2011-09-19 18:28:01 +00002421 }
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002422 }
2423
2424 /* do all our children */
2425 child = call_prom("child", 1, 1, node);
2426 while (child != 0) {
2427 scan_dt_build_struct(child, mem_start, mem_end);
2428 child = call_prom("peer", 1, 1, child);
2429 }
2430
2431 dt_push_token(OF_DT_END_NODE, mem_start, mem_end);
2432}
2433
2434static void __init flatten_device_tree(void)
2435{
2436 phandle root;
2437 unsigned long mem_start, mem_end, room;
2438 struct boot_param_header *hdr;
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002439 char *namep;
2440 u64 *rsvmap;
2441
2442 /*
2443 * Check how much room we have between alloc top & bottom (+/- a
Anton Blanchardfbafd722011-07-25 20:47:51 +00002444 * few pages), crop to 1MB, as this is our "chunk" size
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002445 */
Anton Blanchard5827d412012-11-26 17:40:03 +00002446 room = alloc_top - alloc_bottom - 0x4000;
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002447 if (room > DEVTREE_CHUNK_SIZE)
2448 room = DEVTREE_CHUNK_SIZE;
Mathieu Malaterreeae5f702018-04-06 22:12:19 +02002449 prom_debug("starting device tree allocs at %lx\n", alloc_bottom);
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002450
2451 /* Now try to claim that */
2452 mem_start = (unsigned long)alloc_up(room, PAGE_SIZE);
2453 if (mem_start == 0)
2454 prom_panic("Can't allocate initial device-tree chunk\n");
Anton Blanchard966728d2011-07-25 20:47:07 +00002455 mem_end = mem_start + room;
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002456
2457 /* Get root of tree */
2458 root = call_prom("peer", 1, 1, (phandle)0);
2459 if (root == (phandle)0)
2460 prom_panic ("couldn't get device tree root\n");
2461
2462 /* Build header and make room for mem rsv map */
2463 mem_start = _ALIGN(mem_start, 4);
2464 hdr = make_room(&mem_start, &mem_end,
2465 sizeof(struct boot_param_header), 4);
Anton Blanchard5827d412012-11-26 17:40:03 +00002466 dt_header_start = (unsigned long)hdr;
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002467 rsvmap = make_room(&mem_start, &mem_end, sizeof(mem_reserve_map), 8);
2468
2469 /* Start of strings */
2470 mem_start = PAGE_ALIGN(mem_start);
Anton Blanchard5827d412012-11-26 17:40:03 +00002471 dt_string_start = mem_start;
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002472 mem_start += 4; /* hole */
2473
2474 /* Add "linux,phandle" in there, we'll need it */
2475 namep = make_room(&mem_start, &mem_end, 16, 1);
Anton Blanchard5827d412012-11-26 17:40:03 +00002476 strcpy(namep, "linux,phandle");
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002477 mem_start = (unsigned long)namep + strlen(namep) + 1;
2478
2479 /* Build string array */
2480 prom_printf("Building dt strings...\n");
2481 scan_dt_build_strings(root, &mem_start, &mem_end);
Anton Blanchard5827d412012-11-26 17:40:03 +00002482 dt_string_end = mem_start;
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002483
2484 /* Build structure */
2485 mem_start = PAGE_ALIGN(mem_start);
Anton Blanchard5827d412012-11-26 17:40:03 +00002486 dt_struct_start = mem_start;
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002487 prom_printf("Building dt structure...\n");
2488 scan_dt_build_struct(root, &mem_start, &mem_end);
2489 dt_push_token(OF_DT_END, &mem_start, &mem_end);
Anton Blanchard5827d412012-11-26 17:40:03 +00002490 dt_struct_end = PAGE_ALIGN(mem_start);
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002491
2492 /* Finish header */
Benjamin Herrenschmidt493adff2013-08-07 02:01:38 +10002493 hdr->boot_cpuid_phys = cpu_to_be32(prom.cpu);
2494 hdr->magic = cpu_to_be32(OF_DT_HEADER);
2495 hdr->totalsize = cpu_to_be32(dt_struct_end - dt_header_start);
2496 hdr->off_dt_struct = cpu_to_be32(dt_struct_start - dt_header_start);
2497 hdr->off_dt_strings = cpu_to_be32(dt_string_start - dt_header_start);
2498 hdr->dt_strings_size = cpu_to_be32(dt_string_end - dt_string_start);
2499 hdr->off_mem_rsvmap = cpu_to_be32(((unsigned long)rsvmap) - dt_header_start);
2500 hdr->version = cpu_to_be32(OF_DT_VERSION);
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002501 /* Version 16 is not backward compatible */
Benjamin Herrenschmidt493adff2013-08-07 02:01:38 +10002502 hdr->last_comp_version = cpu_to_be32(0x10);
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002503
Jimi Xenidis4d1f3f22006-05-18 17:03:05 -05002504 /* Copy the reserve map in */
Anton Blanchard5827d412012-11-26 17:40:03 +00002505 memcpy(rsvmap, mem_reserve_map, sizeof(mem_reserve_map));
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002506
2507#ifdef DEBUG_PROM
2508 {
2509 int i;
2510 prom_printf("reserved memory map:\n");
Anton Blanchard5827d412012-11-26 17:40:03 +00002511 for (i = 0; i < mem_reserve_cnt; i++)
Mathieu Malaterreeae5f702018-04-06 22:12:19 +02002512 prom_printf(" %llx - %llx\n",
Benjamin Herrenschmidt493adff2013-08-07 02:01:38 +10002513 be64_to_cpu(mem_reserve_map[i].base),
2514 be64_to_cpu(mem_reserve_map[i].size));
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002515 }
2516#endif
Jimi Xenidis4d1f3f22006-05-18 17:03:05 -05002517 /* Bump mem_reserve_cnt to cause further reservations to fail
2518 * since it's too late.
2519 */
Anton Blanchard5827d412012-11-26 17:40:03 +00002520 mem_reserve_cnt = MEM_RESERVE_MAP_SIZE;
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002521
Mathieu Malaterreeae5f702018-04-06 22:12:19 +02002522 prom_printf("Device tree strings 0x%lx -> 0x%lx\n",
Anton Blanchard5827d412012-11-26 17:40:03 +00002523 dt_string_start, dt_string_end);
Mathieu Malaterreeae5f702018-04-06 22:12:19 +02002524 prom_printf("Device tree struct 0x%lx -> 0x%lx\n",
Anton Blanchard5827d412012-11-26 17:40:03 +00002525 dt_struct_start, dt_struct_end);
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002526}
2527
Hollis Blanchard54f4ee12006-05-25 16:36:53 -05002528#ifdef CONFIG_PPC_MAPLE
2529/* PIBS Version 1.05.0000 04/26/2005 has an incorrect /ht/isa/ranges property.
2530 * The values are bad, and it doesn't even have the right number of cells. */
2531static void __init fixup_device_tree_maple(void)
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002532{
Hollis Blanchard54f4ee12006-05-25 16:36:53 -05002533 phandle isa;
Benjamin Herrenschmidt980a6512006-07-03 17:22:05 +10002534 u32 rloc = 0x01002000; /* IO space; PCI device = 4 */
Hollis Blanchard54f4ee12006-05-25 16:36:53 -05002535 u32 isa_ranges[6];
Benjamin Herrenschmidt980a6512006-07-03 17:22:05 +10002536 char *name;
Hollis Blanchard54f4ee12006-05-25 16:36:53 -05002537
Benjamin Herrenschmidt980a6512006-07-03 17:22:05 +10002538 name = "/ht@0/isa@4";
2539 isa = call_prom("finddevice", 1, 1, ADDR(name));
2540 if (!PHANDLE_VALID(isa)) {
2541 name = "/ht@0/isa@6";
2542 isa = call_prom("finddevice", 1, 1, ADDR(name));
2543 rloc = 0x01003000; /* IO space; PCI device = 6 */
2544 }
Hollis Blanchard54f4ee12006-05-25 16:36:53 -05002545 if (!PHANDLE_VALID(isa))
2546 return;
2547
Benjamin Herrenschmidt980a6512006-07-03 17:22:05 +10002548 if (prom_getproplen(isa, "ranges") != 12)
2549 return;
Hollis Blanchard54f4ee12006-05-25 16:36:53 -05002550 if (prom_getprop(isa, "ranges", isa_ranges, sizeof(isa_ranges))
2551 == PROM_ERROR)
2552 return;
2553
2554 if (isa_ranges[0] != 0x1 ||
2555 isa_ranges[1] != 0xf4000000 ||
2556 isa_ranges[2] != 0x00010000)
2557 return;
2558
Benjamin Herrenschmidt980a6512006-07-03 17:22:05 +10002559 prom_printf("Fixing up bogus ISA range on Maple/Apache...\n");
Hollis Blanchard54f4ee12006-05-25 16:36:53 -05002560
2561 isa_ranges[0] = 0x1;
2562 isa_ranges[1] = 0x0;
Benjamin Herrenschmidt980a6512006-07-03 17:22:05 +10002563 isa_ranges[2] = rloc;
Hollis Blanchard54f4ee12006-05-25 16:36:53 -05002564 isa_ranges[3] = 0x0;
2565 isa_ranges[4] = 0x0;
2566 isa_ranges[5] = 0x00010000;
Benjamin Herrenschmidt980a6512006-07-03 17:22:05 +10002567 prom_setprop(isa, name, "ranges",
Hollis Blanchard54f4ee12006-05-25 16:36:53 -05002568 isa_ranges, sizeof(isa_ranges));
2569}
Harry Ciao8f101a052009-06-17 16:28:00 -07002570
2571#define CPC925_MC_START 0xf8000000
2572#define CPC925_MC_LENGTH 0x1000000
2573/* The values for memory-controller don't have right number of cells */
2574static void __init fixup_device_tree_maple_memory_controller(void)
2575{
2576 phandle mc;
2577 u32 mc_reg[4];
2578 char *name = "/hostbridge@f8000000";
Harry Ciao8f101a052009-06-17 16:28:00 -07002579 u32 ac, sc;
2580
2581 mc = call_prom("finddevice", 1, 1, ADDR(name));
2582 if (!PHANDLE_VALID(mc))
2583 return;
2584
2585 if (prom_getproplen(mc, "reg") != 8)
2586 return;
2587
Anton Blanchard5827d412012-11-26 17:40:03 +00002588 prom_getprop(prom.root, "#address-cells", &ac, sizeof(ac));
2589 prom_getprop(prom.root, "#size-cells", &sc, sizeof(sc));
Harry Ciao8f101a052009-06-17 16:28:00 -07002590 if ((ac != 2) || (sc != 2))
2591 return;
2592
2593 if (prom_getprop(mc, "reg", mc_reg, sizeof(mc_reg)) == PROM_ERROR)
2594 return;
2595
2596 if (mc_reg[0] != CPC925_MC_START || mc_reg[1] != CPC925_MC_LENGTH)
2597 return;
2598
2599 prom_printf("Fixing up bogus hostbridge on Maple...\n");
2600
2601 mc_reg[0] = 0x0;
2602 mc_reg[1] = CPC925_MC_START;
2603 mc_reg[2] = 0x0;
2604 mc_reg[3] = CPC925_MC_LENGTH;
2605 prom_setprop(mc, name, "reg", mc_reg, sizeof(mc_reg));
2606}
Hollis Blanchard54f4ee12006-05-25 16:36:53 -05002607#else
2608#define fixup_device_tree_maple()
Harry Ciao8f101a052009-06-17 16:28:00 -07002609#define fixup_device_tree_maple_memory_controller()
Hollis Blanchard54f4ee12006-05-25 16:36:53 -05002610#endif
2611
Benjamin Herrenschmidte8c0acf2006-07-04 14:06:29 +10002612#ifdef CONFIG_PPC_CHRP
Olaf Heringe4805922007-04-04 18:20:04 +02002613/*
2614 * Pegasos and BriQ lacks the "ranges" property in the isa node
2615 * Pegasos needs decimal IRQ 14/15, not hexadecimal
Olaf Hering556ecf92007-08-18 04:27:17 +10002616 * Pegasos has the IDE configured in legacy mode, but advertised as native
Olaf Heringe4805922007-04-04 18:20:04 +02002617 */
Benjamin Herrenschmidte8c0acf2006-07-04 14:06:29 +10002618static void __init fixup_device_tree_chrp(void)
2619{
Olaf Heringe4805922007-04-04 18:20:04 +02002620 phandle ph;
2621 u32 prop[6];
Benjamin Herrenschmidt26c50322006-07-04 14:16:28 +10002622 u32 rloc = 0x01006000; /* IO space; PCI device = 12 */
Benjamin Herrenschmidte8c0acf2006-07-04 14:06:29 +10002623 char *name;
2624 int rc;
2625
2626 name = "/pci@80000000/isa@c";
Olaf Heringe4805922007-04-04 18:20:04 +02002627 ph = call_prom("finddevice", 1, 1, ADDR(name));
2628 if (!PHANDLE_VALID(ph)) {
Benjamin Herrenschmidt26c50322006-07-04 14:16:28 +10002629 name = "/pci@ff500000/isa@6";
Olaf Heringe4805922007-04-04 18:20:04 +02002630 ph = call_prom("finddevice", 1, 1, ADDR(name));
Benjamin Herrenschmidt26c50322006-07-04 14:16:28 +10002631 rloc = 0x01003000; /* IO space; PCI device = 6 */
2632 }
Olaf Heringe4805922007-04-04 18:20:04 +02002633 if (PHANDLE_VALID(ph)) {
2634 rc = prom_getproplen(ph, "ranges");
2635 if (rc == 0 || rc == PROM_ERROR) {
2636 prom_printf("Fixing up missing ISA range on Pegasos...\n");
Benjamin Herrenschmidte8c0acf2006-07-04 14:06:29 +10002637
Olaf Heringe4805922007-04-04 18:20:04 +02002638 prop[0] = 0x1;
2639 prop[1] = 0x0;
2640 prop[2] = rloc;
2641 prop[3] = 0x0;
2642 prop[4] = 0x0;
2643 prop[5] = 0x00010000;
2644 prom_setprop(ph, name, "ranges", prop, sizeof(prop));
2645 }
2646 }
Benjamin Herrenschmidte8c0acf2006-07-04 14:06:29 +10002647
Olaf Heringe4805922007-04-04 18:20:04 +02002648 name = "/pci@80000000/ide@C,1";
2649 ph = call_prom("finddevice", 1, 1, ADDR(name));
2650 if (PHANDLE_VALID(ph)) {
2651 prom_printf("Fixing up IDE interrupt on Pegasos...\n");
2652 prop[0] = 14;
2653 prop[1] = 0x0;
Olaf Hering556ecf92007-08-18 04:27:17 +10002654 prom_setprop(ph, name, "interrupts", prop, 2*sizeof(u32));
2655 prom_printf("Fixing up IDE class-code on Pegasos...\n");
2656 rc = prom_getprop(ph, "class-code", prop, sizeof(u32));
2657 if (rc == sizeof(u32)) {
2658 prop[0] &= ~0x5;
2659 prom_setprop(ph, name, "class-code", prop, sizeof(u32));
2660 }
Olaf Heringe4805922007-04-04 18:20:04 +02002661 }
Benjamin Herrenschmidte8c0acf2006-07-04 14:06:29 +10002662}
2663#else
2664#define fixup_device_tree_chrp()
2665#endif
2666
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002667#if defined(CONFIG_PPC64) && defined(CONFIG_PPC_PMAC)
Hollis Blanchard54f4ee12006-05-25 16:36:53 -05002668static void __init fixup_device_tree_pmac(void)
2669{
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002670 phandle u3, i2c, mpic;
2671 u32 u3_rev;
2672 u32 interrupts[2];
2673 u32 parent;
2674
2675 /* Some G5s have a missing interrupt definition, fix it up here */
2676 u3 = call_prom("finddevice", 1, 1, ADDR("/u3@0,f8000000"));
2677 if (!PHANDLE_VALID(u3))
2678 return;
2679 i2c = call_prom("finddevice", 1, 1, ADDR("/u3@0,f8000000/i2c@f8001000"));
2680 if (!PHANDLE_VALID(i2c))
2681 return;
2682 mpic = call_prom("finddevice", 1, 1, ADDR("/u3@0,f8000000/mpic@f8040000"));
2683 if (!PHANDLE_VALID(mpic))
2684 return;
2685
2686 /* check if proper rev of u3 */
2687 if (prom_getprop(u3, "device-rev", &u3_rev, sizeof(u3_rev))
2688 == PROM_ERROR)
2689 return;
Benjamin Herrenschmidt7d496972005-11-07 14:36:21 +11002690 if (u3_rev < 0x35 || u3_rev > 0x39)
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002691 return;
2692 /* does it need fixup ? */
2693 if (prom_getproplen(i2c, "interrupts") > 0)
2694 return;
2695
2696 prom_printf("fixing up bogus interrupts for u3 i2c...\n");
2697
2698 /* interrupt on this revision of u3 is number 0 and level */
2699 interrupts[0] = 0;
2700 interrupts[1] = 1;
Paul Mackerrasa23414b2005-11-10 12:00:55 +11002701 prom_setprop(i2c, "/u3@0,f8000000/i2c@f8001000", "interrupts",
2702 &interrupts, sizeof(interrupts));
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002703 parent = (u32)mpic;
Paul Mackerrasa23414b2005-11-10 12:00:55 +11002704 prom_setprop(i2c, "/u3@0,f8000000/i2c@f8001000", "interrupt-parent",
2705 &parent, sizeof(parent));
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002706}
Hollis Blanchard54f4ee12006-05-25 16:36:53 -05002707#else
2708#define fixup_device_tree_pmac()
2709#endif
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002710
Sylvain Munaut88fd2a92007-02-12 23:13:20 +01002711#ifdef CONFIG_PPC_EFIKA
Grant Likely94d2dde2008-01-24 22:25:32 -07002712/*
2713 * The MPC5200 FEC driver requires an phy-handle property to tell it how
2714 * to talk to the phy. If the phy-handle property is missing, then this
2715 * function is called to add the appropriate nodes and link it to the
2716 * ethernet node.
2717 */
2718static void __init fixup_device_tree_efika_add_phy(void)
Sylvain Munaut88fd2a92007-02-12 23:13:20 +01002719{
Sylvain Munaut88fd2a92007-02-12 23:13:20 +01002720 u32 node;
2721 char prop[64];
Grant Likely94d2dde2008-01-24 22:25:32 -07002722 int rv;
Sylvain Munaut88fd2a92007-02-12 23:13:20 +01002723
Grant Likely94d2dde2008-01-24 22:25:32 -07002724 /* Check if /builtin/ethernet exists - bail if it doesn't */
2725 node = call_prom("finddevice", 1, 1, ADDR("/builtin/ethernet"));
Sylvain Munaut88fd2a92007-02-12 23:13:20 +01002726 if (!PHANDLE_VALID(node))
2727 return;
2728
Grant Likely94d2dde2008-01-24 22:25:32 -07002729 /* Check if the phy-handle property exists - bail if it does */
2730 rv = prom_getprop(node, "phy-handle", prop, sizeof(prop));
2731 if (!rv)
Sylvain Munaut88fd2a92007-02-12 23:13:20 +01002732 return;
2733
Grant Likely94d2dde2008-01-24 22:25:32 -07002734 /*
2735 * At this point the ethernet device doesn't have a phy described.
2736 * Now we need to add the missing phy node and linkage
2737 */
Sylvain Munaut88fd2a92007-02-12 23:13:20 +01002738
Grant Likely94d2dde2008-01-24 22:25:32 -07002739 /* Check for an MDIO bus node - if missing then create one */
Olaf Hering6f4347c2008-01-10 01:06:08 +11002740 node = call_prom("finddevice", 1, 1, ADDR("/builtin/mdio"));
2741 if (!PHANDLE_VALID(node)) {
2742 prom_printf("Adding Ethernet MDIO node\n");
2743 call_prom("interpret", 1, 1,
2744 " s\" /builtin\" find-device"
2745 " new-device"
2746 " 1 encode-int s\" #address-cells\" property"
2747 " 0 encode-int s\" #size-cells\" property"
Grant Likely94d2dde2008-01-24 22:25:32 -07002748 " s\" mdio\" device-name"
2749 " s\" fsl,mpc5200b-mdio\" encode-string"
Olaf Hering6f4347c2008-01-10 01:06:08 +11002750 " s\" compatible\" property"
2751 " 0xf0003000 0x400 reg"
2752 " 0x2 encode-int"
2753 " 0x5 encode-int encode+"
2754 " 0x3 encode-int encode+"
2755 " s\" interrupts\" property"
2756 " finish-device");
2757 };
2758
Grant Likely94d2dde2008-01-24 22:25:32 -07002759 /* Check for a PHY device node - if missing then create one and
2760 * give it's phandle to the ethernet node */
2761 node = call_prom("finddevice", 1, 1,
2762 ADDR("/builtin/mdio/ethernet-phy"));
Olaf Hering6f4347c2008-01-10 01:06:08 +11002763 if (!PHANDLE_VALID(node)) {
2764 prom_printf("Adding Ethernet PHY node\n");
2765 call_prom("interpret", 1, 1,
2766 " s\" /builtin/mdio\" find-device"
2767 " new-device"
2768 " s\" ethernet-phy\" device-name"
2769 " 0x10 encode-int s\" reg\" property"
2770 " my-self"
2771 " ihandle>phandle"
2772 " finish-device"
2773 " s\" /builtin/ethernet\" find-device"
2774 " encode-int"
2775 " s\" phy-handle\" property"
2776 " device-end");
2777 }
Grant Likely94d2dde2008-01-24 22:25:32 -07002778}
Olaf Hering6f4347c2008-01-10 01:06:08 +11002779
Grant Likely94d2dde2008-01-24 22:25:32 -07002780static void __init fixup_device_tree_efika(void)
2781{
2782 int sound_irq[3] = { 2, 2, 0 };
2783 int bcomm_irq[3*16] = { 3,0,0, 3,1,0, 3,2,0, 3,3,0,
2784 3,4,0, 3,5,0, 3,6,0, 3,7,0,
2785 3,8,0, 3,9,0, 3,10,0, 3,11,0,
2786 3,12,0, 3,13,0, 3,14,0, 3,15,0 };
2787 u32 node;
2788 char prop[64];
2789 int rv, len;
2790
2791 /* Check if we're really running on a EFIKA */
2792 node = call_prom("finddevice", 1, 1, ADDR("/"));
2793 if (!PHANDLE_VALID(node))
2794 return;
2795
2796 rv = prom_getprop(node, "model", prop, sizeof(prop));
2797 if (rv == PROM_ERROR)
2798 return;
2799 if (strcmp(prop, "EFIKA5K2"))
2800 return;
2801
2802 prom_printf("Applying EFIKA device tree fixups\n");
2803
2804 /* Claiming to be 'chrp' is death */
2805 node = call_prom("finddevice", 1, 1, ADDR("/"));
2806 rv = prom_getprop(node, "device_type", prop, sizeof(prop));
2807 if (rv != PROM_ERROR && (strcmp(prop, "chrp") == 0))
2808 prom_setprop(node, "/", "device_type", "efika", sizeof("efika"));
2809
David Woodhouse7f4392c2008-04-14 02:52:38 +10002810 /* CODEGEN,description is exposed in /proc/cpuinfo so
2811 fix that too */
2812 rv = prom_getprop(node, "CODEGEN,description", prop, sizeof(prop));
2813 if (rv != PROM_ERROR && (strstr(prop, "CHRP")))
2814 prom_setprop(node, "/", "CODEGEN,description",
2815 "Efika 5200B PowerPC System",
2816 sizeof("Efika 5200B PowerPC System"));
2817
Grant Likely94d2dde2008-01-24 22:25:32 -07002818 /* Fixup bestcomm interrupts property */
2819 node = call_prom("finddevice", 1, 1, ADDR("/builtin/bestcomm"));
2820 if (PHANDLE_VALID(node)) {
2821 len = prom_getproplen(node, "interrupts");
2822 if (len == 12) {
2823 prom_printf("Fixing bestcomm interrupts property\n");
2824 prom_setprop(node, "/builtin/bestcom", "interrupts",
2825 bcomm_irq, sizeof(bcomm_irq));
2826 }
2827 }
2828
2829 /* Fixup sound interrupts property */
2830 node = call_prom("finddevice", 1, 1, ADDR("/builtin/sound"));
2831 if (PHANDLE_VALID(node)) {
2832 rv = prom_getprop(node, "interrupts", prop, sizeof(prop));
2833 if (rv == PROM_ERROR) {
2834 prom_printf("Adding sound interrupts property\n");
2835 prom_setprop(node, "/builtin/sound", "interrupts",
2836 sound_irq, sizeof(sound_irq));
2837 }
2838 }
2839
2840 /* Make sure ethernet phy-handle property exists */
2841 fixup_device_tree_efika_add_phy();
Sylvain Munaut88fd2a92007-02-12 23:13:20 +01002842}
2843#else
2844#define fixup_device_tree_efika()
2845#endif
2846
Darren Stevens50246782016-08-31 13:24:40 +01002847#ifdef CONFIG_PPC_PASEMI_NEMO
2848/*
2849 * CFE supplied on Nemo is broken in several ways, biggest
2850 * problem is that it reassigns ISA interrupts to unused mpic ints.
2851 * Add an interrupt-controller property for the io-bridge to use
2852 * and correct the ints so we can attach them to an irq_domain
2853 */
2854static void __init fixup_device_tree_pasemi(void)
2855{
2856 u32 interrupts[2], parent, rval, val = 0;
2857 char *name, *pci_name;
2858 phandle iob, node;
2859
2860 /* Find the root pci node */
2861 name = "/pxp@0,e0000000";
2862 iob = call_prom("finddevice", 1, 1, ADDR(name));
2863 if (!PHANDLE_VALID(iob))
2864 return;
2865
2866 /* check if interrupt-controller node set yet */
2867 if (prom_getproplen(iob, "interrupt-controller") !=PROM_ERROR)
2868 return;
2869
2870 prom_printf("adding interrupt-controller property for SB600...\n");
2871
2872 prom_setprop(iob, name, "interrupt-controller", &val, 0);
2873
2874 pci_name = "/pxp@0,e0000000/pci@11";
2875 node = call_prom("finddevice", 1, 1, ADDR(pci_name));
2876 parent = ADDR(iob);
2877
2878 for( ; prom_next_node(&node); ) {
2879 /* scan each node for one with an interrupt */
2880 if (!PHANDLE_VALID(node))
2881 continue;
2882
2883 rval = prom_getproplen(node, "interrupts");
2884 if (rval == 0 || rval == PROM_ERROR)
2885 continue;
2886
2887 prom_getprop(node, "interrupts", &interrupts, sizeof(interrupts));
2888 if ((interrupts[0] < 212) || (interrupts[0] > 222))
2889 continue;
2890
2891 /* found a node, update both interrupts and interrupt-parent */
2892 if ((interrupts[0] >= 212) && (interrupts[0] <= 215))
2893 interrupts[0] -= 203;
2894 if ((interrupts[0] >= 216) && (interrupts[0] <= 220))
2895 interrupts[0] -= 213;
2896 if (interrupts[0] == 221)
2897 interrupts[0] = 14;
2898 if (interrupts[0] == 222)
2899 interrupts[0] = 8;
2900
2901 prom_setprop(node, pci_name, "interrupts", interrupts,
2902 sizeof(interrupts));
2903 prom_setprop(node, pci_name, "interrupt-parent", &parent,
2904 sizeof(parent));
2905 }
Darren Stevens687e16b2016-08-31 13:24:45 +01002906
2907 /*
2908 * The io-bridge has device_type set to 'io-bridge' change it to 'isa'
2909 * so that generic isa-bridge code can add the SB600 and its on-board
2910 * peripherals.
2911 */
2912 name = "/pxp@0,e0000000/io-bridge@0";
2913 iob = call_prom("finddevice", 1, 1, ADDR(name));
2914 if (!PHANDLE_VALID(iob))
2915 return;
2916
2917 /* device_type is already set, just change it. */
2918
2919 prom_printf("Changing device_type of SB600 node...\n");
2920
2921 prom_setprop(iob, name, "device_type", "isa", sizeof("isa"));
Darren Stevens50246782016-08-31 13:24:40 +01002922}
2923#else /* !CONFIG_PPC_PASEMI_NEMO */
2924static inline void fixup_device_tree_pasemi(void) { }
2925#endif
2926
Hollis Blanchard54f4ee12006-05-25 16:36:53 -05002927static void __init fixup_device_tree(void)
2928{
2929 fixup_device_tree_maple();
Harry Ciao8f101a052009-06-17 16:28:00 -07002930 fixup_device_tree_maple_memory_controller();
Benjamin Herrenschmidte8c0acf2006-07-04 14:06:29 +10002931 fixup_device_tree_chrp();
Hollis Blanchard54f4ee12006-05-25 16:36:53 -05002932 fixup_device_tree_pmac();
Sylvain Munaut88fd2a92007-02-12 23:13:20 +01002933 fixup_device_tree_efika();
Darren Stevens50246782016-08-31 13:24:40 +01002934 fixup_device_tree_pasemi();
Hollis Blanchard54f4ee12006-05-25 16:36:53 -05002935}
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002936
2937static void __init prom_find_boot_cpu(void)
2938{
Benjamin Herrenschmidt493adff2013-08-07 02:01:38 +10002939 __be32 rval;
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002940 ihandle prom_cpu;
2941 phandle cpu_pkg;
2942
Benjamin Herrenschmidt493adff2013-08-07 02:01:38 +10002943 rval = 0;
2944 if (prom_getprop(prom.chosen, "cpu", &rval, sizeof(rval)) <= 0)
Paul Mackerrasa575b802005-10-23 17:23:21 +10002945 return;
Benjamin Herrenschmidt493adff2013-08-07 02:01:38 +10002946 prom_cpu = be32_to_cpu(rval);
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002947
2948 cpu_pkg = call_prom("instance-to-package", 1, 1, prom_cpu);
2949
Darren Stevensaf2b7fa2017-01-23 19:42:54 +00002950 if (!PHANDLE_VALID(cpu_pkg))
2951 return;
2952
Benjamin Herrenschmidt493adff2013-08-07 02:01:38 +10002953 prom_getprop(cpu_pkg, "reg", &rval, sizeof(rval));
2954 prom.cpu = be32_to_cpu(rval);
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002955
Mathieu Malaterreeae5f702018-04-06 22:12:19 +02002956 prom_debug("Booting CPU hw index = %d\n", prom.cpu);
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002957}
2958
2959static void __init prom_check_initrd(unsigned long r3, unsigned long r4)
2960{
2961#ifdef CONFIG_BLK_DEV_INITRD
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002962 if (r3 && r4 && r4 != 0xdeadbeef) {
Benjamin Herrenschmidt493adff2013-08-07 02:01:38 +10002963 __be64 val;
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002964
Anton Blanchard5827d412012-11-26 17:40:03 +00002965 prom_initrd_start = is_kernel_addr(r3) ? __pa(r3) : r3;
2966 prom_initrd_end = prom_initrd_start + r4;
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002967
Benjamin Herrenschmidt493adff2013-08-07 02:01:38 +10002968 val = cpu_to_be64(prom_initrd_start);
Anton Blanchard5827d412012-11-26 17:40:03 +00002969 prom_setprop(prom.chosen, "/chosen", "linux,initrd-start",
Paul Mackerrasa23414b2005-11-10 12:00:55 +11002970 &val, sizeof(val));
Benjamin Herrenschmidt493adff2013-08-07 02:01:38 +10002971 val = cpu_to_be64(prom_initrd_end);
Anton Blanchard5827d412012-11-26 17:40:03 +00002972 prom_setprop(prom.chosen, "/chosen", "linux,initrd-end",
Paul Mackerrasa23414b2005-11-10 12:00:55 +11002973 &val, sizeof(val));
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002974
Anton Blanchard5827d412012-11-26 17:40:03 +00002975 reserve_mem(prom_initrd_start,
2976 prom_initrd_end - prom_initrd_start);
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002977
Mathieu Malaterreeae5f702018-04-06 22:12:19 +02002978 prom_debug("initrd_start=0x%lx\n", prom_initrd_start);
2979 prom_debug("initrd_end=0x%lx\n", prom_initrd_end);
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002980 }
2981#endif /* CONFIG_BLK_DEV_INITRD */
2982}
2983
Anton Blanchard5ac47f72012-11-26 17:39:03 +00002984#ifdef CONFIG_PPC64
2985#ifdef CONFIG_RELOCATABLE
2986static void reloc_toc(void)
2987{
2988}
2989
2990static void unreloc_toc(void)
2991{
2992}
2993#else
Anton Blanchard16744002013-03-12 01:51:51 +00002994static void __reloc_toc(unsigned long offset, unsigned long nr_entries)
Anton Blanchard5ac47f72012-11-26 17:39:03 +00002995{
2996 unsigned long i;
Anton Blanchard16744002013-03-12 01:51:51 +00002997 unsigned long *toc_entry;
2998
2999 /* Get the start of the TOC by using r2 directly. */
3000 asm volatile("addi %0,2,-0x8000" : "=b" (toc_entry));
Anton Blanchard5ac47f72012-11-26 17:39:03 +00003001
3002 for (i = 0; i < nr_entries; i++) {
3003 *toc_entry = *toc_entry + offset;
3004 toc_entry++;
3005 }
3006}
3007
3008static void reloc_toc(void)
3009{
3010 unsigned long offset = reloc_offset();
3011 unsigned long nr_entries =
3012 (__prom_init_toc_end - __prom_init_toc_start) / sizeof(long);
3013
Anton Blanchard16744002013-03-12 01:51:51 +00003014 __reloc_toc(offset, nr_entries);
Anton Blanchard5ac47f72012-11-26 17:39:03 +00003015
3016 mb();
3017}
3018
3019static void unreloc_toc(void)
3020{
3021 unsigned long offset = reloc_offset();
3022 unsigned long nr_entries =
3023 (__prom_init_toc_end - __prom_init_toc_start) / sizeof(long);
3024
3025 mb();
3026
Anton Blanchard16744002013-03-12 01:51:51 +00003027 __reloc_toc(-offset, nr_entries);
Anton Blanchard5ac47f72012-11-26 17:39:03 +00003028}
3029#endif
3030#endif
Benjamin Herrenschmidt27f44882011-09-19 18:27:58 +00003031
Paul Mackerras9b6b5632005-10-06 12:06:20 +10003032/*
3033 * We enter here early on, when the Open Firmware prom is still
3034 * handling exceptions and the MMU hash table for us.
3035 */
3036
3037unsigned long __init prom_init(unsigned long r3, unsigned long r4,
3038 unsigned long pp,
Paul Mackerras549e8152008-08-30 11:43:47 +10003039 unsigned long r6, unsigned long r7,
3040 unsigned long kbase)
Paul Mackerras9b6b5632005-10-06 12:06:20 +10003041{
Paul Mackerras9b6b5632005-10-06 12:06:20 +10003042 unsigned long hdr;
Paul Mackerras9b6b5632005-10-06 12:06:20 +10003043
3044#ifdef CONFIG_PPC32
Paul Mackerras549e8152008-08-30 11:43:47 +10003045 unsigned long offset = reloc_offset();
Paul Mackerras9b6b5632005-10-06 12:06:20 +10003046 reloc_got2(offset);
Anton Blanchard5ac47f72012-11-26 17:39:03 +00003047#else
3048 reloc_toc();
Paul Mackerras9b6b5632005-10-06 12:06:20 +10003049#endif
3050
Paul Mackerras9b6b5632005-10-06 12:06:20 +10003051 /*
3052 * First zero the BSS
3053 */
Anton Blanchard5827d412012-11-26 17:40:03 +00003054 memset(&__bss_start, 0, __bss_stop - __bss_start);
Paul Mackerras9b6b5632005-10-06 12:06:20 +10003055
3056 /*
3057 * Init interface to Open Firmware, get some node references,
3058 * like /chosen
3059 */
3060 prom_init_client_services(pp);
3061
3062 /*
Paul Mackerrasa23414b2005-11-10 12:00:55 +11003063 * See if this OF is old enough that we need to do explicit maps
3064 * and other workarounds
3065 */
3066 prom_find_mmu();
3067
3068 /*
Paul Mackerras9b6b5632005-10-06 12:06:20 +10003069 * Init prom stdout device
3070 */
3071 prom_init_stdout();
3072
Anton Blanchard5827d412012-11-26 17:40:03 +00003073 prom_printf("Preparing to boot %s", linux_banner);
Michael Ellermane7943fb2009-03-04 19:02:01 +00003074
Paul Mackerras9b6b5632005-10-06 12:06:20 +10003075 /*
3076 * Get default machine type. At this point, we do not differentiate
3077 * between pSeries SMP and pSeries LPAR
3078 */
Anton Blanchard5827d412012-11-26 17:40:03 +00003079 of_platform = prom_find_machine_type();
3080 prom_printf("Detected machine type: %x\n", of_platform);
Paul Mackerras9b6b5632005-10-06 12:06:20 +10003081
Suzuki Poulose0f890c82011-12-14 22:57:15 +00003082#ifndef CONFIG_NONSTATIC_KERNEL
Olaf Heringadd60ef2006-03-23 22:03:57 +01003083 /* Bail if this is a kdump kernel. */
3084 if (PHYSICAL_START > 0)
3085 prom_panic("Error: You can't boot a kdump kernel from OF!\n");
Paul Mackerras549e8152008-08-30 11:43:47 +10003086#endif
Olaf Heringadd60ef2006-03-23 22:03:57 +01003087
3088 /*
3089 * Check for an initrd
3090 */
3091 prom_check_initrd(r3, r4);
3092
Suraj Jitindar Singh12cc9fd2017-02-28 17:03:47 +11003093 /*
3094 * Do early parsing of command line
3095 */
3096 early_cmdline_parse();
3097
Benjamin Herrenschmidt11fdb302018-10-15 13:49:53 +11003098#ifdef CONFIG_PPC_PSERIES
Paul Mackerras9b6b5632005-10-06 12:06:20 +10003099 /*
3100 * On pSeries, inform the firmware about our capabilities
3101 */
Anton Blanchard5827d412012-11-26 17:40:03 +00003102 if (of_platform == PLATFORM_PSERIES ||
3103 of_platform == PLATFORM_PSERIES_LPAR)
Paul Mackerras9b6b5632005-10-06 12:06:20 +10003104 prom_send_capabilities();
3105#endif
3106
Paul Mackerras9b6b5632005-10-06 12:06:20 +10003107 /*
Arnd Bergmannf3f66f52005-10-31 20:08:37 -05003108 * Copy the CPU hold code
Paul Mackerras9b6b5632005-10-06 12:06:20 +10003109 */
Anton Blanchard5827d412012-11-26 17:40:03 +00003110 if (of_platform != PLATFORM_POWERMAC)
Paul Mackerras549e8152008-08-30 11:43:47 +10003111 copy_and_flush(0, kbase, 0x100, 0);
Paul Mackerras9b6b5632005-10-06 12:06:20 +10003112
3113 /*
Paul Mackerras9b6b5632005-10-06 12:06:20 +10003114 * Initialize memory management within prom_init
3115 */
3116 prom_init_mem();
3117
3118 /*
3119 * Determine which cpu is actually running right _now_
3120 */
3121 prom_find_boot_cpu();
3122
3123 /*
3124 * Initialize display devices
3125 */
3126 prom_check_displays();
3127
Benjamin Herrenschmidt493adff2013-08-07 02:01:38 +10003128#if defined(CONFIG_PPC64) && defined(__BIG_ENDIAN__)
Paul Mackerras9b6b5632005-10-06 12:06:20 +10003129 /*
3130 * Initialize IOMMU (TCE tables) on pSeries. Do that before anything else
3131 * that uses the allocator, we need to make sure we get the top of memory
3132 * available for us here...
3133 */
Anton Blanchard5827d412012-11-26 17:40:03 +00003134 if (of_platform == PLATFORM_PSERIES)
Paul Mackerras9b6b5632005-10-06 12:06:20 +10003135 prom_initialize_tce_table();
3136#endif
3137
3138 /*
Benjamin Herrenschmidt27f44882011-09-19 18:27:58 +00003139 * On non-powermacs, try to instantiate RTAS. PowerMacs don't
3140 * have a usable RTAS implementation.
Paul Mackerras9b6b5632005-10-06 12:06:20 +10003141 */
Benjamin Herrenschmidt11fdb302018-10-15 13:49:53 +11003142 if (of_platform != PLATFORM_POWERMAC)
Paul Mackerras9b6b5632005-10-06 12:06:20 +10003143 prom_instantiate_rtas();
Benjamin Herrenschmidt27f44882011-09-19 18:27:58 +00003144
Ashley Lai4a727422012-08-14 18:34:57 -05003145#ifdef CONFIG_PPC64
3146 /* instantiate sml */
3147 prom_instantiate_sml();
3148#endif
3149
Benjamin Herrenschmidt27f44882011-09-19 18:27:58 +00003150 /*
3151 * On non-powermacs, put all CPUs in spin-loops.
3152 *
3153 * PowerMacs use a different mechanism to spin CPUs
Benjamin Herrenschmidtdbe78b42013-09-25 14:02:50 +10003154 *
3155 * (This must be done after instanciating RTAS)
Benjamin Herrenschmidt27f44882011-09-19 18:27:58 +00003156 */
Benjamin Herrenschmidt11fdb302018-10-15 13:49:53 +11003157 if (of_platform != PLATFORM_POWERMAC)
Benjamin Herrenschmidt27f44882011-09-19 18:27:58 +00003158 prom_hold_cpus();
Paul Mackerras9b6b5632005-10-06 12:06:20 +10003159
3160 /*
3161 * Fill in some infos for use by the kernel later on
3162 */
Benjamin Herrenschmidt493adff2013-08-07 02:01:38 +10003163 if (prom_memory_limit) {
3164 __be64 val = cpu_to_be64(prom_memory_limit);
Anton Blanchard5827d412012-11-26 17:40:03 +00003165 prom_setprop(prom.chosen, "/chosen", "linux,memory-limit",
Benjamin Herrenschmidt493adff2013-08-07 02:01:38 +10003166 &val, sizeof(val));
3167 }
Paul Mackerras9b6b5632005-10-06 12:06:20 +10003168#ifdef CONFIG_PPC64
Anton Blanchard5827d412012-11-26 17:40:03 +00003169 if (prom_iommu_off)
3170 prom_setprop(prom.chosen, "/chosen", "linux,iommu-off",
Paul Mackerrasa23414b2005-11-10 12:00:55 +11003171 NULL, 0);
Paul Mackerras9b6b5632005-10-06 12:06:20 +10003172
Anton Blanchard5827d412012-11-26 17:40:03 +00003173 if (prom_iommu_force_on)
3174 prom_setprop(prom.chosen, "/chosen", "linux,iommu-force-on",
Paul Mackerrasa23414b2005-11-10 12:00:55 +11003175 NULL, 0);
Paul Mackerras9b6b5632005-10-06 12:06:20 +10003176
Anton Blanchard5827d412012-11-26 17:40:03 +00003177 if (prom_tce_alloc_start) {
3178 prom_setprop(prom.chosen, "/chosen", "linux,tce-alloc-start",
3179 &prom_tce_alloc_start,
Paul Mackerras9b6b5632005-10-06 12:06:20 +10003180 sizeof(prom_tce_alloc_start));
Anton Blanchard5827d412012-11-26 17:40:03 +00003181 prom_setprop(prom.chosen, "/chosen", "linux,tce-alloc-end",
3182 &prom_tce_alloc_end,
Paul Mackerras9b6b5632005-10-06 12:06:20 +10003183 sizeof(prom_tce_alloc_end));
3184 }
3185#endif
3186
3187 /*
3188 * Fixup any known bugs in the device-tree
3189 */
3190 fixup_device_tree();
3191
3192 /*
3193 * Now finally create the flattened device-tree
3194 */
Anton Blanchard1f8737a2009-03-31 20:06:15 +00003195 prom_printf("copying OF device tree...\n");
Paul Mackerras9b6b5632005-10-06 12:06:20 +10003196 flatten_device_tree();
3197
Paul Mackerras3825ac02005-11-08 22:48:08 +11003198 /*
3199 * in case stdin is USB and still active on IBM machines...
3200 * Unfortunately quiesce crashes on some powermacs if we have
Benjamin Herrenschmidt11fdb302018-10-15 13:49:53 +11003201 * closed stdin already (in particular the powerbook 101).
Paul Mackerras3825ac02005-11-08 22:48:08 +11003202 */
Benjamin Herrenschmidt11fdb302018-10-15 13:49:53 +11003203 if (of_platform != PLATFORM_POWERMAC)
Paul Mackerras3825ac02005-11-08 22:48:08 +11003204 prom_close_stdin();
Paul Mackerras9b6b5632005-10-06 12:06:20 +10003205
3206 /*
3207 * Call OF "quiesce" method to shut down pending DMA's from
3208 * devices etc...
3209 */
Michael Ellerman7e862d72015-03-30 17:38:09 +11003210 prom_printf("Quiescing Open Firmware ...\n");
Paul Mackerras9b6b5632005-10-06 12:06:20 +10003211 call_prom("quiesce", 0, 0);
3212
3213 /*
3214 * And finally, call the kernel passing it the flattened device
3215 * tree and NULL as r5, thus triggering the new entry point which
3216 * is common to us and kexec
3217 */
Anton Blanchard5827d412012-11-26 17:40:03 +00003218 hdr = dt_header_start;
Benjamin Herrenschmidt40dfef62011-11-29 18:22:56 +00003219
3220 /* Don't print anything after quiesce under OPAL, it crashes OFW */
Benjamin Herrenschmidt11fdb302018-10-15 13:49:53 +11003221 prom_printf("Booting Linux via __start() @ 0x%lx ...\n", kbase);
3222 prom_debug("->dt_header_start=0x%lx\n", hdr);
Paul Mackerras9b6b5632005-10-06 12:06:20 +10003223
3224#ifdef CONFIG_PPC32
3225 reloc_got2(-offset);
Anton Blanchard5ac47f72012-11-26 17:39:03 +00003226#else
3227 unreloc_toc();
Paul Mackerras9b6b5632005-10-06 12:06:20 +10003228#endif
3229
Benjamin Herrenschmidt6e35d5d2011-09-19 18:28:01 +00003230 __start(hdr, kbase, 0, 0, 0, 0, 0);
Paul Mackerras9b6b5632005-10-06 12:06:20 +10003231
3232 return 0;
3233}