blob: 17f1ae7fae2c2ffe6652d6c7c6c1f3147f0a79cd [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 */
Benjamin Herrenschmidt5f69e382018-10-15 13:49:58 +110051#define __prombss __section(.bss.prominit)
Benjamin Herrenschmidte63334e2018-10-15 13:49:52 +110052
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
Benjamin Herrenschmidte63334e2018-10-15 13:49:52 +1100157static char __prombss of_stdout_device[256];
Christophe Leroyd7fbe2a2019-04-02 09:08:38 +0000158static char __prombss prom_scratch[256];
Paul Mackerras9b6b5632005-10-06 12:06:20 +1000159
Benjamin Herrenschmidte63334e2018-10-15 13:49:52 +1100160static unsigned long __prombss dt_header_start;
161static unsigned long __prombss dt_struct_start, dt_struct_end;
162static unsigned long __prombss dt_string_start, dt_string_end;
Paul Mackerras9b6b5632005-10-06 12:06:20 +1000163
Benjamin Herrenschmidte63334e2018-10-15 13:49:52 +1100164static unsigned long __prombss prom_initrd_start, prom_initrd_end;
Paul Mackerras9b6b5632005-10-06 12:06:20 +1000165
166#ifdef CONFIG_PPC64
Benjamin Herrenschmidte63334e2018-10-15 13:49:52 +1100167static int __prombss prom_iommu_force_on;
168static int __prombss prom_iommu_off;
169static unsigned long __prombss prom_tce_alloc_start;
170static unsigned long __prombss prom_tce_alloc_end;
Paul Mackerras9b6b5632005-10-06 12:06:20 +1000171#endif
172
Benjamin Herrenschmidtc8860872018-10-15 13:49:54 +1100173#ifdef CONFIG_PPC_PSERIES
Benjamin Herrenschmidt8ca2d512018-10-15 13:49:57 +1100174static bool __prombss prom_radix_disable;
Greg Kurza3bf9fb2019-05-15 12:05:01 +0200175static bool __prombss prom_xive_disable;
Benjamin Herrenschmidtc8860872018-10-15 13:49:54 +1100176#endif
Suraj Jitindar Singh014d02c2017-02-28 17:03:48 +1100177
178struct platform_support {
179 bool hash_mmu;
180 bool radix_mmu;
181 bool radix_gtse;
Cédric Le Goaterac5e5a52017-08-30 21:46:16 +0200182 bool xive;
Suraj Jitindar Singh014d02c2017-02-28 17:03:48 +1100183};
184
Benjamin Herrenschmidte8222502006-03-28 23:15:54 +1100185/* Platforms codes are now obsolete in the kernel. Now only used within this
186 * file and ultimately gone too. Feel free to change them if you need, they
187 * are not shared with anything outside of this file anymore
188 */
189#define PLATFORM_PSERIES 0x0100
190#define PLATFORM_PSERIES_LPAR 0x0101
191#define PLATFORM_LPAR 0x0001
192#define PLATFORM_POWERMAC 0x0400
193#define PLATFORM_GENERIC 0x0500
194
Benjamin Herrenschmidte63334e2018-10-15 13:49:52 +1100195static int __prombss of_platform;
Paul Mackerras9b6b5632005-10-06 12:06:20 +1000196
Benjamin Herrenschmidte63334e2018-10-15 13:49:52 +1100197static char __prombss prom_cmd_line[COMMAND_LINE_SIZE];
Paul Mackerras9b6b5632005-10-06 12:06:20 +1000198
Benjamin Herrenschmidte63334e2018-10-15 13:49:52 +1100199static unsigned long __prombss prom_memory_limit;
Benjamin Krillcf687872009-07-27 22:02:39 +0000200
Benjamin Herrenschmidte63334e2018-10-15 13:49:52 +1100201static unsigned long __prombss alloc_top;
202static unsigned long __prombss alloc_top_high;
203static unsigned long __prombss alloc_bottom;
204static unsigned long __prombss rmo_top;
205static unsigned long __prombss ram_top;
Paul Mackerras9b6b5632005-10-06 12:06:20 +1000206
Benjamin Herrenschmidte63334e2018-10-15 13:49:52 +1100207static struct mem_map_entry __prombss mem_reserve_map[MEM_RESERVE_MAP_SIZE];
208static int __prombss mem_reserve_cnt;
Paul Mackerras9b6b5632005-10-06 12:06:20 +1000209
Benjamin Herrenschmidte63334e2018-10-15 13:49:52 +1100210static cell_t __prombss regbuf[1024];
Paul Mackerras9b6b5632005-10-06 12:06:20 +1000211
Benjamin Herrenschmidt8ca2d512018-10-15 13:49:57 +1100212static bool __prombss rtas_has_query_cpu_stopped;
Benjamin Herrenschmidtdbe78b42013-09-25 14:02:50 +1000213
Paul Mackerras9b6b5632005-10-06 12:06:20 +1000214
Paul Mackerras9b6b5632005-10-06 12:06:20 +1000215/*
216 * Error results ... some OF calls will return "-1" on error, some
217 * will return 0, some will return either. To simplify, here are
218 * macros to use with any ihandle or phandle return value to check if
219 * it is valid
220 */
221
222#define PROM_ERROR (-1u)
223#define PHANDLE_VALID(p) ((p) != 0 && (p) != PROM_ERROR)
224#define IHANDLE_VALID(i) ((i) != 0 && (i) != PROM_ERROR)
225
Christophe Leroy450e7dd2019-04-26 16:23:28 +0000226/* Copied from lib/string.c and lib/kstrtox.c */
227
228static int __init prom_strcmp(const char *cs, const char *ct)
229{
230 unsigned char c1, c2;
231
232 while (1) {
233 c1 = *cs++;
234 c2 = *ct++;
235 if (c1 != c2)
236 return c1 < c2 ? -1 : 1;
237 if (!c1)
238 break;
239 }
240 return 0;
241}
242
243static char __init *prom_strcpy(char *dest, const char *src)
244{
245 char *tmp = dest;
246
247 while ((*dest++ = *src++) != '\0')
248 /* nothing */;
249 return tmp;
250}
251
252static int __init prom_strncmp(const char *cs, const char *ct, size_t count)
253{
254 unsigned char c1, c2;
255
256 while (count) {
257 c1 = *cs++;
258 c2 = *ct++;
259 if (c1 != c2)
260 return c1 < c2 ? -1 : 1;
261 if (!c1)
262 break;
263 count--;
264 }
265 return 0;
266}
267
268static size_t __init prom_strlen(const char *s)
269{
270 const char *sc;
271
272 for (sc = s; *sc != '\0'; ++sc)
273 /* nothing */;
274 return sc - s;
275}
276
277static int __init prom_memcmp(const void *cs, const void *ct, size_t count)
278{
279 const unsigned char *su1, *su2;
280 int res = 0;
281
282 for (su1 = cs, su2 = ct; 0 < count; ++su1, ++su2, count--)
283 if ((res = *su1 - *su2) != 0)
284 break;
285 return res;
286}
287
288static char __init *prom_strstr(const char *s1, const char *s2)
289{
290 size_t l1, l2;
291
292 l2 = prom_strlen(s2);
293 if (!l2)
294 return (char *)s1;
295 l1 = prom_strlen(s1);
296 while (l1 >= l2) {
297 l1--;
298 if (!prom_memcmp(s1, s2, l2))
299 return (char *)s1;
300 s1++;
301 }
302 return NULL;
303}
304
305static size_t __init prom_strlcpy(char *dest, const char *src, size_t size)
306{
307 size_t ret = prom_strlen(src);
308
309 if (size) {
310 size_t len = (ret >= size) ? size - 1 : ret;
311 memcpy(dest, src, len);
312 dest[len] = '\0';
313 }
314 return ret;
315}
316
317#ifdef CONFIG_PPC_PSERIES
318static int __init prom_strtobool(const char *s, bool *res)
319{
320 if (!s)
321 return -EINVAL;
322
323 switch (s[0]) {
324 case 'y':
325 case 'Y':
326 case '1':
327 *res = true;
328 return 0;
329 case 'n':
330 case 'N':
331 case '0':
332 *res = false;
333 return 0;
334 case 'o':
335 case 'O':
336 switch (s[1]) {
337 case 'n':
338 case 'N':
339 *res = true;
340 return 0;
341 case 'f':
342 case 'F':
343 *res = false;
344 return 0;
345 default:
346 break;
347 }
348 default:
349 break;
350 }
351
352 return -EINVAL;
353}
354#endif
Paul Mackerras9b6b5632005-10-06 12:06:20 +1000355
356/* This is the one and *ONLY* place where we actually call open
357 * firmware.
358 */
359
360static int __init call_prom(const char *service, int nargs, int nret, ...)
361{
362 int i;
363 struct prom_args args;
364 va_list list;
365
Benjamin Herrenschmidt493adff2013-08-07 02:01:38 +1000366 args.service = cpu_to_be32(ADDR(service));
367 args.nargs = cpu_to_be32(nargs);
368 args.nret = cpu_to_be32(nret);
Paul Mackerras9b6b5632005-10-06 12:06:20 +1000369
370 va_start(list, nret);
371 for (i = 0; i < nargs; i++)
Benjamin Herrenschmidt493adff2013-08-07 02:01:38 +1000372 args.args[i] = cpu_to_be32(va_arg(list, prom_arg_t));
Paul Mackerras9b6b5632005-10-06 12:06:20 +1000373 va_end(list);
374
375 for (i = 0; i < nret; i++)
376 args.args[nargs+i] = 0;
377
Anton Blanchard5827d412012-11-26 17:40:03 +0000378 if (enter_prom(&args, prom_entry) < 0)
Paul Mackerrasc49888202005-10-26 21:52:53 +1000379 return PROM_ERROR;
Paul Mackerras9b6b5632005-10-06 12:06:20 +1000380
Benjamin Herrenschmidt493adff2013-08-07 02:01:38 +1000381 return (nret > 0) ? be32_to_cpu(args.args[nargs]) : 0;
Paul Mackerras9b6b5632005-10-06 12:06:20 +1000382}
383
384static int __init call_prom_ret(const char *service, int nargs, int nret,
385 prom_arg_t *rets, ...)
386{
387 int i;
388 struct prom_args args;
389 va_list list;
390
Benjamin Herrenschmidt493adff2013-08-07 02:01:38 +1000391 args.service = cpu_to_be32(ADDR(service));
392 args.nargs = cpu_to_be32(nargs);
393 args.nret = cpu_to_be32(nret);
Paul Mackerras9b6b5632005-10-06 12:06:20 +1000394
395 va_start(list, rets);
396 for (i = 0; i < nargs; i++)
Benjamin Herrenschmidt493adff2013-08-07 02:01:38 +1000397 args.args[i] = cpu_to_be32(va_arg(list, prom_arg_t));
Paul Mackerras9b6b5632005-10-06 12:06:20 +1000398 va_end(list);
399
400 for (i = 0; i < nret; i++)
Olaf Heringed1189b72005-11-29 14:04:05 +0100401 args.args[nargs+i] = 0;
Paul Mackerras9b6b5632005-10-06 12:06:20 +1000402
Anton Blanchard5827d412012-11-26 17:40:03 +0000403 if (enter_prom(&args, prom_entry) < 0)
Paul Mackerrasc49888202005-10-26 21:52:53 +1000404 return PROM_ERROR;
Paul Mackerras9b6b5632005-10-06 12:06:20 +1000405
406 if (rets != NULL)
407 for (i = 1; i < nret; ++i)
Benjamin Herrenschmidt493adff2013-08-07 02:01:38 +1000408 rets[i-1] = be32_to_cpu(args.args[nargs+i]);
Paul Mackerras9b6b5632005-10-06 12:06:20 +1000409
Benjamin Herrenschmidt493adff2013-08-07 02:01:38 +1000410 return (nret > 0) ? be32_to_cpu(args.args[nargs]) : 0;
Paul Mackerras9b6b5632005-10-06 12:06:20 +1000411}
412
413
Paul Mackerras9b6b5632005-10-06 12:06:20 +1000414static void __init prom_print(const char *msg)
415{
416 const char *p, *q;
Paul Mackerras9b6b5632005-10-06 12:06:20 +1000417
Anton Blanchard5827d412012-11-26 17:40:03 +0000418 if (prom.stdout == 0)
Paul Mackerras9b6b5632005-10-06 12:06:20 +1000419 return;
420
421 for (p = msg; *p != 0; p = q) {
422 for (q = p; *q != 0 && *q != '\n'; ++q)
423 ;
424 if (q > p)
Anton Blanchard5827d412012-11-26 17:40:03 +0000425 call_prom("write", 3, 1, prom.stdout, p, q - p);
Paul Mackerras9b6b5632005-10-06 12:06:20 +1000426 if (*q == 0)
427 break;
428 ++q;
Anton Blanchard5827d412012-11-26 17:40:03 +0000429 call_prom("write", 3, 1, prom.stdout, ADDR("\r\n"), 2);
Paul Mackerras9b6b5632005-10-06 12:06:20 +1000430 }
431}
432
433
Mathieu Malaterre8af1da42018-05-29 21:20:01 +0200434/*
435 * Both prom_print_hex & prom_print_dec takes an unsigned long as input so that
436 * we do not need __udivdi3 or __umoddi3 on 32bits.
437 */
Paul Mackerras9b6b5632005-10-06 12:06:20 +1000438static void __init prom_print_hex(unsigned long val)
439{
440 int i, nibbles = sizeof(val)*2;
441 char buf[sizeof(val)*2+1];
Paul Mackerras9b6b5632005-10-06 12:06:20 +1000442
443 for (i = nibbles-1; i >= 0; i--) {
444 buf[i] = (val & 0xf) + '0';
445 if (buf[i] > '9')
446 buf[i] += ('a'-'0'-10);
447 val >>= 4;
448 }
449 buf[nibbles] = '\0';
Anton Blanchard5827d412012-11-26 17:40:03 +0000450 call_prom("write", 3, 1, prom.stdout, buf, nibbles);
Paul Mackerras9b6b5632005-10-06 12:06:20 +1000451}
452
Michael Neuling2c48a7d2010-07-27 18:26:21 +0000453/* max number of decimal digits in an unsigned long */
454#define UL_DIGITS 21
455static void __init prom_print_dec(unsigned long val)
456{
457 int i, size;
458 char buf[UL_DIGITS+1];
Michael Neuling2c48a7d2010-07-27 18:26:21 +0000459
460 for (i = UL_DIGITS-1; i >= 0; i--) {
461 buf[i] = (val % 10) + '0';
462 val = val/10;
463 if (val == 0)
464 break;
465 }
466 /* shift stuff down */
467 size = UL_DIGITS - i;
Anton Blanchard5827d412012-11-26 17:40:03 +0000468 call_prom("write", 3, 1, prom.stdout, buf+i, size);
Michael Neuling2c48a7d2010-07-27 18:26:21 +0000469}
Paul Mackerras9b6b5632005-10-06 12:06:20 +1000470
Mathieu Malaterreeae5f702018-04-06 22:12:19 +0200471__printf(1, 2)
Paul Mackerras9b6b5632005-10-06 12:06:20 +1000472static void __init prom_printf(const char *format, ...)
473{
474 const char *p, *q, *s;
475 va_list args;
476 unsigned long v;
Benjamin Herrenschmidtaf277142011-04-06 10:51:17 +1000477 long vs;
Mathieu Malaterre8af1da42018-05-29 21:20:01 +0200478 int n = 0;
Paul Mackerras9b6b5632005-10-06 12:06:20 +1000479
480 va_start(args, format);
Paul Mackerras9b6b5632005-10-06 12:06:20 +1000481 for (p = format; *p != 0; p = q) {
482 for (q = p; *q != 0 && *q != '\n' && *q != '%'; ++q)
483 ;
484 if (q > p)
Anton Blanchard5827d412012-11-26 17:40:03 +0000485 call_prom("write", 3, 1, prom.stdout, p, q - p);
Paul Mackerras9b6b5632005-10-06 12:06:20 +1000486 if (*q == 0)
487 break;
488 if (*q == '\n') {
489 ++q;
Anton Blanchard5827d412012-11-26 17:40:03 +0000490 call_prom("write", 3, 1, prom.stdout,
Paul Mackerras9b6b5632005-10-06 12:06:20 +1000491 ADDR("\r\n"), 2);
492 continue;
493 }
494 ++q;
495 if (*q == 0)
496 break;
Mathieu Malaterre8af1da42018-05-29 21:20:01 +0200497 while (*q == 'l') {
498 ++q;
499 ++n;
500 }
Paul Mackerras9b6b5632005-10-06 12:06:20 +1000501 switch (*q) {
502 case 's':
503 ++q;
504 s = va_arg(args, const char *);
505 prom_print(s);
506 break;
507 case 'x':
508 ++q;
Mathieu Malaterre8af1da42018-05-29 21:20:01 +0200509 switch (n) {
510 case 0:
511 v = va_arg(args, unsigned int);
512 break;
513 case 1:
514 v = va_arg(args, unsigned long);
515 break;
516 case 2:
517 default:
518 v = va_arg(args, unsigned long long);
519 break;
520 }
Paul Mackerras9b6b5632005-10-06 12:06:20 +1000521 prom_print_hex(v);
522 break;
Mathieu Malaterre8af1da42018-05-29 21:20:01 +0200523 case 'u':
524 ++q;
525 switch (n) {
526 case 0:
527 v = va_arg(args, unsigned int);
528 break;
529 case 1:
530 v = va_arg(args, unsigned long);
531 break;
532 case 2:
533 default:
534 v = va_arg(args, unsigned long long);
535 break;
536 }
537 prom_print_dec(v);
538 break;
Benjamin Herrenschmidtaf277142011-04-06 10:51:17 +1000539 case 'd':
540 ++q;
Mathieu Malaterre8af1da42018-05-29 21:20:01 +0200541 switch (n) {
542 case 0:
543 vs = va_arg(args, int);
544 break;
545 case 1:
546 vs = va_arg(args, long);
547 break;
548 case 2:
549 default:
550 vs = va_arg(args, long long);
551 break;
552 }
Benjamin Herrenschmidtaf277142011-04-06 10:51:17 +1000553 if (vs < 0) {
Anton Blanchard5827d412012-11-26 17:40:03 +0000554 prom_print("-");
Benjamin Herrenschmidtaf277142011-04-06 10:51:17 +1000555 vs = -vs;
556 }
557 prom_print_dec(vs);
558 break;
Paul Mackerras9b6b5632005-10-06 12:06:20 +1000559 }
560 }
Daniel Axtens1b855e12015-12-17 19:41:00 +1100561 va_end(args);
Paul Mackerras9b6b5632005-10-06 12:06:20 +1000562}
563
564
Paul Mackerrasa575b802005-10-23 17:23:21 +1000565static unsigned int __init prom_claim(unsigned long virt, unsigned long size,
566 unsigned long align)
567{
Paul Mackerrasa575b802005-10-23 17:23:21 +1000568
Paul Mackerrasa23414b2005-11-10 12:00:55 +1100569 if (align == 0 && (OF_WORKAROUNDS & OF_WA_CLAIM)) {
570 /*
571 * Old OF requires we claim physical and virtual separately
572 * and then map explicitly (assuming virtual mode)
573 */
574 int ret;
575 prom_arg_t result;
576
577 ret = call_prom_ret("call-method", 5, 2, &result,
Anton Blanchard5827d412012-11-26 17:40:03 +0000578 ADDR("claim"), prom.memory,
Paul Mackerrasa23414b2005-11-10 12:00:55 +1100579 align, size, virt);
580 if (ret != 0 || result == -1)
581 return -1;
582 ret = call_prom_ret("call-method", 5, 2, &result,
Anton Blanchard5827d412012-11-26 17:40:03 +0000583 ADDR("claim"), prom.mmumap,
Paul Mackerrasa23414b2005-11-10 12:00:55 +1100584 align, size, virt);
585 if (ret != 0) {
586 call_prom("call-method", 4, 1, ADDR("release"),
Anton Blanchard5827d412012-11-26 17:40:03 +0000587 prom.memory, size, virt);
Paul Mackerrasa23414b2005-11-10 12:00:55 +1100588 return -1;
589 }
590 /* the 0x12 is M (coherence) + PP == read/write */
Paul Mackerrasa575b802005-10-23 17:23:21 +1000591 call_prom("call-method", 6, 1,
Anton Blanchard5827d412012-11-26 17:40:03 +0000592 ADDR("map"), prom.mmumap, 0x12, size, virt, virt);
Paul Mackerrasa23414b2005-11-10 12:00:55 +1100593 return virt;
594 }
595 return call_prom("claim", 3, 1, (prom_arg_t)virt, (prom_arg_t)size,
596 (prom_arg_t)align);
Paul Mackerrasa575b802005-10-23 17:23:21 +1000597}
598
Paul Mackerras9b6b5632005-10-06 12:06:20 +1000599static void __init __attribute__((noreturn)) prom_panic(const char *reason)
600{
Paul Mackerras9b6b5632005-10-06 12:06:20 +1000601 prom_print(reason);
Olaf Heringadd60ef2006-03-23 22:03:57 +0100602 /* Do not call exit because it clears the screen on pmac
603 * it also causes some sort of double-fault on early pmacs */
Anton Blanchard5827d412012-11-26 17:40:03 +0000604 if (of_platform == PLATFORM_POWERMAC)
Olaf Heringadd60ef2006-03-23 22:03:57 +0100605 asm("trap\n");
606
Stephen Rothwell1d9a4732012-03-21 18:23:27 +0000607 /* ToDo: should put up an SRC here on pSeries */
Paul Mackerras9b6b5632005-10-06 12:06:20 +1000608 call_prom("exit", 0, 0);
609
610 for (;;) /* should never get here */
611 ;
612}
613
614
615static int __init prom_next_node(phandle *nodep)
616{
617 phandle node;
618
619 if ((node = *nodep) != 0
620 && (*nodep = call_prom("child", 1, 1, node)) != 0)
621 return 1;
622 if ((*nodep = call_prom("peer", 1, 1, node)) != 0)
623 return 1;
624 for (;;) {
625 if ((node = call_prom("parent", 1, 1, node)) == 0)
626 return 0;
627 if ((*nodep = call_prom("peer", 1, 1, node)) != 0)
628 return 1;
629 }
630}
631
Masahiro Yamada480795a2019-05-14 15:42:14 -0700632static inline int __init prom_getprop(phandle node, const char *pname,
633 void *value, size_t valuelen)
Paul Mackerras9b6b5632005-10-06 12:06:20 +1000634{
635 return call_prom("getprop", 4, 1, node, ADDR(pname),
636 (u32)(unsigned long) value, (u32) valuelen);
637}
638
Masahiro Yamada480795a2019-05-14 15:42:14 -0700639static inline int __init prom_getproplen(phandle node, const char *pname)
Paul Mackerras9b6b5632005-10-06 12:06:20 +1000640{
641 return call_prom("getproplen", 2, 1, node, ADDR(pname));
642}
643
Paul Mackerrasa23414b2005-11-10 12:00:55 +1100644static void add_string(char **str, const char *q)
Paul Mackerras9b6b5632005-10-06 12:06:20 +1000645{
Paul Mackerrasa23414b2005-11-10 12:00:55 +1100646 char *p = *str;
647
648 while (*q)
649 *p++ = *q++;
650 *p++ = ' ';
651 *str = p;
652}
653
654static char *tohex(unsigned int x)
655{
Benjamin Herrenschmidt8ca2d512018-10-15 13:49:57 +1100656 static const char digits[] __initconst = "0123456789abcdef";
657 static char result[9] __prombss;
Paul Mackerrasa23414b2005-11-10 12:00:55 +1100658 int i;
659
660 result[8] = 0;
661 i = 8;
662 do {
663 --i;
664 result[i] = digits[x & 0xf];
665 x >>= 4;
666 } while (x != 0 && i > 0);
667 return &result[i];
668}
669
670static int __init prom_setprop(phandle node, const char *nodename,
671 const char *pname, void *value, size_t valuelen)
672{
673 char cmd[256], *p;
674
675 if (!(OF_WORKAROUNDS & OF_WA_LONGTRAIL))
676 return call_prom("setprop", 4, 1, node, ADDR(pname),
677 (u32)(unsigned long) value, (u32) valuelen);
678
679 /* gah... setprop doesn't work on longtrail, have to use interpret */
680 p = cmd;
681 add_string(&p, "dev");
682 add_string(&p, nodename);
683 add_string(&p, tohex((u32)(unsigned long) value));
684 add_string(&p, tohex(valuelen));
685 add_string(&p, tohex(ADDR(pname)));
Christophe Leroy450e7dd2019-04-26 16:23:28 +0000686 add_string(&p, tohex(prom_strlen(pname)));
Paul Mackerrasa23414b2005-11-10 12:00:55 +1100687 add_string(&p, "property");
688 *p = 0;
689 return call_prom("interpret", 1, 1, (u32)(unsigned long) cmd);
Paul Mackerras9b6b5632005-10-06 12:06:20 +1000690}
691
Anton Blanchard5827d412012-11-26 17:40:03 +0000692/* We can't use the standard versions because of relocation headaches. */
Benjamin Krillcf687872009-07-27 22:02:39 +0000693#define isxdigit(c) (('0' <= (c) && (c) <= '9') \
694 || ('a' <= (c) && (c) <= 'f') \
695 || ('A' <= (c) && (c) <= 'F'))
696
697#define isdigit(c) ('0' <= (c) && (c) <= '9')
698#define islower(c) ('a' <= (c) && (c) <= 'z')
699#define toupper(c) (islower(c) ? ((c) - 'a' + 'A') : (c))
700
Benjamin Herrenschmidt493adff2013-08-07 02:01:38 +1000701static unsigned long prom_strtoul(const char *cp, const char **endp)
Benjamin Krillcf687872009-07-27 22:02:39 +0000702{
703 unsigned long result = 0, base = 10, value;
704
705 if (*cp == '0') {
706 base = 8;
707 cp++;
708 if (toupper(*cp) == 'X') {
709 cp++;
710 base = 16;
711 }
712 }
713
714 while (isxdigit(*cp) &&
715 (value = isdigit(*cp) ? *cp - '0' : toupper(*cp) - 'A' + 10) < base) {
716 result = result * base + value;
717 cp++;
718 }
719
720 if (endp)
721 *endp = cp;
722
723 return result;
724}
725
Benjamin Herrenschmidt493adff2013-08-07 02:01:38 +1000726static unsigned long prom_memparse(const char *ptr, const char **retptr)
Benjamin Krillcf687872009-07-27 22:02:39 +0000727{
728 unsigned long ret = prom_strtoul(ptr, retptr);
729 int shift = 0;
730
731 /*
732 * We can't use a switch here because GCC *may* generate a
733 * jump table which won't work, because we're not running at
734 * the address we're linked at.
735 */
736 if ('G' == **retptr || 'g' == **retptr)
737 shift = 30;
738
739 if ('M' == **retptr || 'm' == **retptr)
740 shift = 20;
741
742 if ('K' == **retptr || 'k' == **retptr)
743 shift = 10;
744
745 if (shift) {
746 ret <<= shift;
747 (*retptr)++;
748 }
749
750 return ret;
751}
752
Paul Mackerras9b6b5632005-10-06 12:06:20 +1000753/*
754 * Early parsing of the command line passed to the kernel, used for
755 * "mem=x" and the options that affect the iommu
756 */
757static void __init early_cmdline_parse(void)
758{
Benjamin Herrenschmidtcc5d0182005-12-13 18:01:21 +1100759 const char *opt;
Benjamin Krillcf687872009-07-27 22:02:39 +0000760
Benjamin Herrenschmidtcc5d0182005-12-13 18:01:21 +1100761 char *p;
Christophe Leroycbe46bd2019-04-26 16:23:27 +0000762 int l = 0;
Paul Mackerras9b6b5632005-10-06 12:06:20 +1000763
Anton Blanchard5827d412012-11-26 17:40:03 +0000764 prom_cmd_line[0] = 0;
765 p = prom_cmd_line;
766 if ((long)prom.chosen > 0)
767 l = prom_getprop(prom.chosen, "bootargs", p, COMMAND_LINE_SIZE-1);
Christophe Leroycbe46bd2019-04-26 16:23:27 +0000768 if (IS_ENABLED(CONFIG_CMDLINE_BOOL) && (l <= 0 || p[0] == '\0')) /* dbl check */
Christophe Leroy450e7dd2019-04-26 16:23:28 +0000769 prom_strlcpy(prom_cmd_line, CONFIG_CMDLINE, sizeof(prom_cmd_line));
Anton Blanchard5827d412012-11-26 17:40:03 +0000770 prom_printf("command line: %s\n", prom_cmd_line);
Paul Mackerras9b6b5632005-10-06 12:06:20 +1000771
772#ifdef CONFIG_PPC64
Christophe Leroy450e7dd2019-04-26 16:23:28 +0000773 opt = prom_strstr(prom_cmd_line, "iommu=");
Paul Mackerras9b6b5632005-10-06 12:06:20 +1000774 if (opt) {
775 prom_printf("iommu opt is: %s\n", opt);
776 opt += 6;
777 while (*opt && *opt == ' ')
778 opt++;
Christophe Leroy450e7dd2019-04-26 16:23:28 +0000779 if (!prom_strncmp(opt, "off", 3))
Anton Blanchard5827d412012-11-26 17:40:03 +0000780 prom_iommu_off = 1;
Christophe Leroy450e7dd2019-04-26 16:23:28 +0000781 else if (!prom_strncmp(opt, "force", 5))
Anton Blanchard5827d412012-11-26 17:40:03 +0000782 prom_iommu_force_on = 1;
Paul Mackerras9b6b5632005-10-06 12:06:20 +1000783 }
784#endif
Christophe Leroy450e7dd2019-04-26 16:23:28 +0000785 opt = prom_strstr(prom_cmd_line, "mem=");
Benjamin Krillcf687872009-07-27 22:02:39 +0000786 if (opt) {
787 opt += 4;
Anton Blanchard5827d412012-11-26 17:40:03 +0000788 prom_memory_limit = prom_memparse(opt, (const char **)&opt);
Benjamin Krillcf687872009-07-27 22:02:39 +0000789#ifdef CONFIG_PPC64
790 /* Align to 16 MB == size of ppc64 large page */
Anton Blanchard5827d412012-11-26 17:40:03 +0000791 prom_memory_limit = ALIGN(prom_memory_limit, 0x1000000);
Benjamin Krillcf687872009-07-27 22:02:39 +0000792#endif
793 }
Suraj Jitindar Singh014d02c2017-02-28 17:03:48 +1100794
Benjamin Herrenschmidtc8860872018-10-15 13:49:54 +1100795#ifdef CONFIG_PPC_PSERIES
796 prom_radix_disable = !IS_ENABLED(CONFIG_PPC_RADIX_MMU_DEFAULT);
Christophe Leroy450e7dd2019-04-26 16:23:28 +0000797 opt = prom_strstr(prom_cmd_line, "disable_radix");
Suraj Jitindar Singh014d02c2017-02-28 17:03:48 +1100798 if (opt) {
Aneesh Kumar K.V7a22d632018-03-30 17:39:02 +0530799 opt += 13;
800 if (*opt && *opt == '=') {
801 bool val;
802
Christophe Leroy450e7dd2019-04-26 16:23:28 +0000803 if (prom_strtobool(++opt, &val))
Aneesh Kumar K.V7a22d632018-03-30 17:39:02 +0530804 prom_radix_disable = false;
805 else
806 prom_radix_disable = val;
807 } else
808 prom_radix_disable = true;
Suraj Jitindar Singh014d02c2017-02-28 17:03:48 +1100809 }
Aneesh Kumar K.V7a22d632018-03-30 17:39:02 +0530810 if (prom_radix_disable)
811 prom_debug("Radix disabled from cmdline\n");
Greg Kurza3bf9fb2019-05-15 12:05:01 +0200812
813 opt = prom_strstr(prom_cmd_line, "xive=off");
814 if (opt) {
815 prom_xive_disable = true;
816 prom_debug("XIVE disabled from cmdline\n");
817 }
Benjamin Herrenschmidtc8860872018-10-15 13:49:54 +1100818#endif /* CONFIG_PPC_PSERIES */
Paul Mackerras9b6b5632005-10-06 12:06:20 +1000819}
820
Benjamin Herrenschmidt11fdb302018-10-15 13:49:53 +1100821#ifdef CONFIG_PPC_PSERIES
Paul Mackerras9b6b5632005-10-06 12:06:20 +1000822/*
Nathan Fontenot530b5e12013-04-24 05:53:10 +0000823 * The architecture vector has an array of PVR mask/value pairs,
824 * followed by # option vectors - 1, followed by the option vectors.
825 *
826 * See prom.h for the definition of the bits specified in the
827 * architecture vector.
Paul Mackerrasf709bfa2006-04-28 16:28:35 +1000828 */
Paul Mackerrasf709bfa2006-04-28 16:28:35 +1000829
Michael Ellermane8a4fd02014-08-29 17:01:43 +1000830/* Firmware expects the value to be n - 1, where n is the # of vectors */
831#define NUM_VECTORS(n) ((n) - 1)
832
833/*
834 * Firmware expects 1 + n - 2, where n is the length of the option vector in
835 * bytes. The 1 accounts for the length byte itself, the - 2 .. ?
836 */
837#define VECTOR_LENGTH(n) (1 + (n) - 2)
838
Michael Ellermand03d1d62016-11-18 23:15:41 +1100839struct option_vector1 {
840 u8 byte1;
841 u8 arch_versions;
Paul Mackerrascc3d2942017-01-30 21:21:36 +1100842 u8 arch_versions3;
Michael Ellermand03d1d62016-11-18 23:15:41 +1100843} __packed;
844
845struct option_vector2 {
846 u8 byte1;
847 __be16 reserved;
848 __be32 real_base;
849 __be32 real_size;
850 __be32 virt_base;
851 __be32 virt_size;
852 __be32 load_base;
853 __be32 min_rma;
854 __be32 min_load;
855 u8 min_rma_percent;
856 u8 max_pft_size;
857} __packed;
858
859struct option_vector3 {
860 u8 byte1;
861 u8 byte2;
862} __packed;
863
864struct option_vector4 {
865 u8 byte1;
866 u8 min_vp_cap;
867} __packed;
868
869struct option_vector5 {
870 u8 byte1;
871 u8 byte2;
872 u8 byte3;
873 u8 cmo;
874 u8 associativity;
875 u8 bin_opts;
876 u8 micro_checkpoint;
877 u8 reserved0;
878 __be32 max_cpus;
879 __be16 papr_level;
880 __be16 reserved1;
881 u8 platform_facilities;
882 u8 reserved2;
883 __be16 reserved3;
884 u8 subprocessors;
Paul Mackerrascc3d2942017-01-30 21:21:36 +1100885 u8 byte22;
886 u8 intarch;
887 u8 mmu;
Suraj Jitindar Singh014d02c2017-02-28 17:03:48 +1100888 u8 hash_ext;
889 u8 radix_ext;
Michael Ellermand03d1d62016-11-18 23:15:41 +1100890} __packed;
891
892struct option_vector6 {
893 u8 reserved;
894 u8 secondary_pteg;
895 u8 os_name;
896} __packed;
897
Michael Ellerman76ffb572016-11-18 23:15:42 +1100898struct ibm_arch_vec {
Paul Mackerrascc3d2942017-01-30 21:21:36 +1100899 struct { u32 mask, val; } pvrs[12];
Michael Ellerman76ffb572016-11-18 23:15:42 +1100900
901 u8 num_vectors;
902
903 u8 vec1_len;
904 struct option_vector1 vec1;
905
906 u8 vec2_len;
907 struct option_vector2 vec2;
908
909 u8 vec3_len;
910 struct option_vector3 vec3;
911
912 u8 vec4_len;
913 struct option_vector4 vec4;
914
915 u8 vec5_len;
916 struct option_vector5 vec5;
917
918 u8 vec6_len;
919 struct option_vector6 vec6;
920} __packed;
921
Benjamin Herrenschmidtd00e34b2018-10-15 13:49:56 +1100922static const struct ibm_arch_vec ibm_architecture_vec_template __initconst = {
Michael Ellerman76ffb572016-11-18 23:15:42 +1100923 .pvrs = {
924 {
925 .mask = cpu_to_be32(0xfffe0000), /* POWER5/POWER5+ */
926 .val = cpu_to_be32(0x003a0000),
927 },
928 {
929 .mask = cpu_to_be32(0xffff0000), /* POWER6 */
930 .val = cpu_to_be32(0x003e0000),
931 },
932 {
933 .mask = cpu_to_be32(0xffff0000), /* POWER7 */
934 .val = cpu_to_be32(0x003f0000),
935 },
936 {
937 .mask = cpu_to_be32(0xffff0000), /* POWER8E */
938 .val = cpu_to_be32(0x004b0000),
939 },
940 {
941 .mask = cpu_to_be32(0xffff0000), /* POWER8NVL */
942 .val = cpu_to_be32(0x004c0000),
943 },
944 {
945 .mask = cpu_to_be32(0xffff0000), /* POWER8 */
946 .val = cpu_to_be32(0x004d0000),
947 },
948 {
Paul Mackerrascc3d2942017-01-30 21:21:36 +1100949 .mask = cpu_to_be32(0xffff0000), /* POWER9 */
950 .val = cpu_to_be32(0x004e0000),
951 },
952 {
953 .mask = cpu_to_be32(0xffffffff), /* all 3.00-compliant */
954 .val = cpu_to_be32(0x0f000005),
955 },
956 {
Michael Ellerman76ffb572016-11-18 23:15:42 +1100957 .mask = cpu_to_be32(0xffffffff), /* all 2.07-compliant */
958 .val = cpu_to_be32(0x0f000004),
959 },
960 {
961 .mask = cpu_to_be32(0xffffffff), /* all 2.06-compliant */
962 .val = cpu_to_be32(0x0f000003),
963 },
964 {
965 .mask = cpu_to_be32(0xffffffff), /* all 2.05-compliant */
966 .val = cpu_to_be32(0x0f000002),
967 },
968 {
969 .mask = cpu_to_be32(0xfffffffe), /* all 2.04-compliant and earlier */
970 .val = cpu_to_be32(0x0f000001),
971 },
972 },
973
974 .num_vectors = NUM_VECTORS(6),
975
976 .vec1_len = VECTOR_LENGTH(sizeof(struct option_vector1)),
977 .vec1 = {
978 .byte1 = 0,
979 .arch_versions = OV1_PPC_2_00 | OV1_PPC_2_01 | OV1_PPC_2_02 | OV1_PPC_2_03 |
980 OV1_PPC_2_04 | OV1_PPC_2_05 | OV1_PPC_2_06 | OV1_PPC_2_07,
Paul Mackerrascc3d2942017-01-30 21:21:36 +1100981 .arch_versions3 = OV1_PPC_3_00,
Michael Ellerman76ffb572016-11-18 23:15:42 +1100982 },
983
984 .vec2_len = VECTOR_LENGTH(sizeof(struct option_vector2)),
985 /* option vector 2: Open Firmware options supported */
986 .vec2 = {
987 .byte1 = OV2_REAL_MODE,
988 .reserved = 0,
989 .real_base = cpu_to_be32(0xffffffff),
990 .real_size = cpu_to_be32(0xffffffff),
991 .virt_base = cpu_to_be32(0xffffffff),
992 .virt_size = cpu_to_be32(0xffffffff),
993 .load_base = cpu_to_be32(0xffffffff),
Sukadev Bhattiprolu687da8f2017-03-27 19:43:14 -0400994 .min_rma = cpu_to_be32(512), /* 512MB min RMA */
Michael Ellerman76ffb572016-11-18 23:15:42 +1100995 .min_load = cpu_to_be32(0xffffffff), /* full client load */
996 .min_rma_percent = 0, /* min RMA percentage of total RAM */
997 .max_pft_size = 48, /* max log_2(hash table size) */
998 },
999
1000 .vec3_len = VECTOR_LENGTH(sizeof(struct option_vector3)),
1001 /* option vector 3: processor options supported */
1002 .vec3 = {
1003 .byte1 = 0, /* don't ignore, don't halt */
1004 .byte2 = OV3_FP | OV3_VMX | OV3_DFP,
1005 },
1006
1007 .vec4_len = VECTOR_LENGTH(sizeof(struct option_vector4)),
1008 /* option vector 4: IBM PAPR implementation */
1009 .vec4 = {
1010 .byte1 = 0, /* don't halt */
1011 .min_vp_cap = OV4_MIN_ENT_CAP, /* minimum VP entitled capacity */
1012 },
1013
1014 .vec5_len = VECTOR_LENGTH(sizeof(struct option_vector5)),
1015 /* option vector 5: PAPR/OF options */
1016 .vec5 = {
1017 .byte1 = 0, /* don't ignore, don't halt */
1018 .byte2 = OV5_FEAT(OV5_LPAR) | OV5_FEAT(OV5_SPLPAR) | OV5_FEAT(OV5_LARGE_PAGES) |
1019 OV5_FEAT(OV5_DRCONF_MEMORY) | OV5_FEAT(OV5_DONATE_DEDICATE_CPU) |
1020#ifdef CONFIG_PCI_MSI
1021 /* PCIe/MSI support. Without MSI full PCIe is not supported */
1022 OV5_FEAT(OV5_MSI),
1023#else
1024 0,
1025#endif
1026 .byte3 = 0,
1027 .cmo =
1028#ifdef CONFIG_PPC_SMLPAR
1029 OV5_FEAT(OV5_CMO) | OV5_FEAT(OV5_XCMO),
1030#else
1031 0,
1032#endif
1033 .associativity = OV5_FEAT(OV5_TYPE1_AFFINITY) | OV5_FEAT(OV5_PRRN),
Michael Roth3dbbaf22017-02-20 19:12:18 -06001034 .bin_opts = OV5_FEAT(OV5_RESIZE_HPT) | OV5_FEAT(OV5_HP_EVT),
Michael Ellerman76ffb572016-11-18 23:15:42 +11001035 .micro_checkpoint = 0,
1036 .reserved0 = 0,
1037 .max_cpus = cpu_to_be32(NR_CPUS), /* number of cores supported */
1038 .papr_level = 0,
1039 .reserved1 = 0,
1040 .platform_facilities = OV5_FEAT(OV5_PFO_HW_RNG) | OV5_FEAT(OV5_PFO_HW_ENCR) | OV5_FEAT(OV5_PFO_HW_842),
1041 .reserved2 = 0,
1042 .reserved3 = 0,
1043 .subprocessors = 1,
Nathan Fontenot0c38ed62017-12-01 10:48:03 -06001044 .byte22 = OV5_FEAT(OV5_DRMEM_V2),
Paul Mackerrascc3d2942017-01-30 21:21:36 +11001045 .intarch = 0,
Suraj Jitindar Singh014d02c2017-02-28 17:03:48 +11001046 .mmu = 0,
1047 .hash_ext = 0,
1048 .radix_ext = 0,
Michael Ellerman76ffb572016-11-18 23:15:42 +11001049 },
1050
1051 /* option vector 6: IBM PAPR hints */
1052 .vec6_len = VECTOR_LENGTH(sizeof(struct option_vector6)),
1053 .vec6 = {
1054 .reserved = 0,
1055 .secondary_pteg = 0,
1056 .os_name = OV6_LINUX,
1057 },
1058};
1059
Benjamin Herrenschmidta614f522018-10-15 13:49:55 +11001060static struct ibm_arch_vec __prombss ibm_architecture_vec ____cacheline_aligned;
1061
Benjamin Herrenschmidt493adff2013-08-07 02:01:38 +10001062/* Old method - ELF header with PT_NOTE sections only works on BE */
1063#ifdef __BIG_ENDIAN__
Benjamin Herrenschmidt30c69ca2018-05-31 14:33:40 +10001064static const struct fake_elf {
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001065 Elf32_Ehdr elfhdr;
1066 Elf32_Phdr phdr[2];
1067 struct chrpnote {
1068 u32 namesz;
1069 u32 descsz;
1070 u32 type;
1071 char name[8]; /* "PowerPC" */
1072 struct chrpdesc {
1073 u32 real_mode;
1074 u32 real_base;
1075 u32 real_size;
1076 u32 virt_base;
1077 u32 virt_size;
1078 u32 load_base;
1079 } chrpdesc;
1080 } chrpnote;
1081 struct rpanote {
1082 u32 namesz;
1083 u32 descsz;
1084 u32 type;
1085 char name[24]; /* "IBM,RPA-Client-Config" */
1086 struct rpadesc {
1087 u32 lpar_affinity;
1088 u32 min_rmo_size;
1089 u32 min_rmo_percent;
1090 u32 max_pft_size;
1091 u32 splpar;
1092 u32 min_load;
1093 u32 new_mem_def;
1094 u32 ignore_me;
1095 } rpadesc;
1096 } rpanote;
Benjamin Herrenschmidtd00e34b2018-10-15 13:49:56 +11001097} fake_elf __initconst = {
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001098 .elfhdr = {
1099 .e_ident = { 0x7f, 'E', 'L', 'F',
1100 ELFCLASS32, ELFDATA2MSB, EV_CURRENT },
1101 .e_type = ET_EXEC, /* yeah right */
1102 .e_machine = EM_PPC,
1103 .e_version = EV_CURRENT,
1104 .e_phoff = offsetof(struct fake_elf, phdr),
1105 .e_phentsize = sizeof(Elf32_Phdr),
1106 .e_phnum = 2
1107 },
1108 .phdr = {
1109 [0] = {
1110 .p_type = PT_NOTE,
1111 .p_offset = offsetof(struct fake_elf, chrpnote),
1112 .p_filesz = sizeof(struct chrpnote)
1113 }, [1] = {
1114 .p_type = PT_NOTE,
1115 .p_offset = offsetof(struct fake_elf, rpanote),
1116 .p_filesz = sizeof(struct rpanote)
1117 }
1118 },
1119 .chrpnote = {
1120 .namesz = sizeof("PowerPC"),
1121 .descsz = sizeof(struct chrpdesc),
1122 .type = 0x1275,
1123 .name = "PowerPC",
1124 .chrpdesc = {
1125 .real_mode = ~0U, /* ~0 means "don't care" */
1126 .real_base = ~0U,
1127 .real_size = ~0U,
1128 .virt_base = ~0U,
1129 .virt_size = ~0U,
1130 .load_base = ~0U
1131 },
1132 },
1133 .rpanote = {
1134 .namesz = sizeof("IBM,RPA-Client-Config"),
1135 .descsz = sizeof(struct rpadesc),
1136 .type = 0x12759999,
1137 .name = "IBM,RPA-Client-Config",
1138 .rpadesc = {
Paul Mackerras5663a122008-10-31 22:27:17 +11001139 .lpar_affinity = 0,
1140 .min_rmo_size = 64, /* in megabytes */
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001141 .min_rmo_percent = 0,
Paul Mackerras5663a122008-10-31 22:27:17 +11001142 .max_pft_size = 48, /* 2^48 bytes max PFT size */
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001143 .splpar = 1,
1144 .min_load = ~0U,
Paul Mackerras5663a122008-10-31 22:27:17 +11001145 .new_mem_def = 0
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001146 }
1147 }
1148};
Benjamin Herrenschmidt493adff2013-08-07 02:01:38 +10001149#endif /* __BIG_ENDIAN__ */
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001150
Benjamin Herrenschmidtefec9592010-02-04 14:33:54 +11001151static int __init prom_count_smt_threads(void)
1152{
1153 phandle node;
1154 char type[64];
1155 unsigned int plen;
1156
1157 /* Pick up th first CPU node we can find */
1158 for (node = 0; prom_next_node(&node); ) {
1159 type[0] = 0;
1160 prom_getprop(node, "device_type", type, sizeof(type));
1161
Christophe Leroy450e7dd2019-04-26 16:23:28 +00001162 if (prom_strcmp(type, "cpu"))
Benjamin Herrenschmidtefec9592010-02-04 14:33:54 +11001163 continue;
1164 /*
1165 * There is an entry for each smt thread, each entry being
1166 * 4 bytes long. All cpus should have the same number of
1167 * smt threads, so return after finding the first.
1168 */
1169 plen = prom_getproplen(node, "ibm,ppc-interrupt-server#s");
1170 if (plen == PROM_ERROR)
1171 break;
1172 plen >>= 2;
Michael Neuling2c48a7d2010-07-27 18:26:21 +00001173 prom_debug("Found %lu smt threads per core\n", (unsigned long)plen);
Benjamin Herrenschmidtefec9592010-02-04 14:33:54 +11001174
1175 /* Sanity check */
1176 if (plen < 1 || plen > 64) {
Michael Neuling2c48a7d2010-07-27 18:26:21 +00001177 prom_printf("Threads per core %lu out of bounds, assuming 1\n",
Benjamin Herrenschmidtefec9592010-02-04 14:33:54 +11001178 (unsigned long)plen);
1179 return 1;
1180 }
1181 return plen;
1182 }
1183 prom_debug("No threads found, assuming 1 per core\n");
1184
1185 return 1;
1186
1187}
1188
Suraj Jitindar Singh014d02c2017-02-28 17:03:48 +11001189static void __init prom_parse_mmu_model(u8 val,
1190 struct platform_support *support)
1191{
1192 switch (val) {
1193 case OV5_FEAT(OV5_MMU_DYNAMIC):
1194 case OV5_FEAT(OV5_MMU_EITHER): /* Either Available */
1195 prom_debug("MMU - either supported\n");
1196 support->radix_mmu = !prom_radix_disable;
1197 support->hash_mmu = true;
1198 break;
1199 case OV5_FEAT(OV5_MMU_RADIX): /* Only Radix */
1200 prom_debug("MMU - radix only\n");
1201 if (prom_radix_disable) {
1202 /*
1203 * If we __have__ to do radix, we're better off ignoring
1204 * the command line rather than not booting.
1205 */
1206 prom_printf("WARNING: Ignoring cmdline option disable_radix\n");
1207 }
1208 support->radix_mmu = true;
1209 break;
1210 case OV5_FEAT(OV5_MMU_HASH):
1211 prom_debug("MMU - hash only\n");
1212 support->hash_mmu = true;
1213 break;
1214 default:
1215 prom_debug("Unknown mmu support option: 0x%x\n", val);
1216 break;
1217 }
1218}
1219
Cédric Le Goaterac5e5a52017-08-30 21:46:16 +02001220static void __init prom_parse_xive_model(u8 val,
1221 struct platform_support *support)
1222{
1223 switch (val) {
1224 case OV5_FEAT(OV5_XIVE_EITHER): /* Either Available */
1225 prom_debug("XIVE - either mode supported\n");
Greg Kurza3bf9fb2019-05-15 12:05:01 +02001226 support->xive = !prom_xive_disable;
Cédric Le Goaterac5e5a52017-08-30 21:46:16 +02001227 break;
1228 case OV5_FEAT(OV5_XIVE_EXPLOIT): /* Only Exploitation mode */
1229 prom_debug("XIVE - exploitation mode supported\n");
Greg Kurza3bf9fb2019-05-15 12:05:01 +02001230 if (prom_xive_disable) {
1231 /*
1232 * If we __have__ to do XIVE, we're better off ignoring
1233 * the command line rather than not booting.
1234 */
1235 prom_printf("WARNING: Ignoring cmdline option xive=off\n");
1236 }
Cédric Le Goaterac5e5a52017-08-30 21:46:16 +02001237 support->xive = true;
1238 break;
1239 case OV5_FEAT(OV5_XIVE_LEGACY): /* Only Legacy mode */
1240 prom_debug("XIVE - legacy mode supported\n");
1241 break;
1242 default:
1243 prom_debug("Unknown xive support option: 0x%x\n", val);
1244 break;
1245 }
1246}
1247
Suraj Jitindar Singh014d02c2017-02-28 17:03:48 +11001248static void __init prom_parse_platform_support(u8 index, u8 val,
1249 struct platform_support *support)
1250{
1251 switch (index) {
1252 case OV5_INDX(OV5_MMU_SUPPORT): /* MMU Model */
1253 prom_parse_mmu_model(val & OV5_FEAT(OV5_MMU_SUPPORT), support);
1254 break;
1255 case OV5_INDX(OV5_RADIX_GTSE): /* Radix Extensions */
1256 if (val & OV5_FEAT(OV5_RADIX_GTSE)) {
1257 prom_debug("Radix - GTSE supported\n");
1258 support->radix_gtse = true;
1259 }
1260 break;
Cédric Le Goaterac5e5a52017-08-30 21:46:16 +02001261 case OV5_INDX(OV5_XIVE_SUPPORT): /* Interrupt mode */
1262 prom_parse_xive_model(val & OV5_FEAT(OV5_XIVE_SUPPORT),
1263 support);
1264 break;
Suraj Jitindar Singh014d02c2017-02-28 17:03:48 +11001265 }
1266}
1267
1268static void __init prom_check_platform_support(void)
1269{
1270 struct platform_support supported = {
1271 .hash_mmu = false,
1272 .radix_mmu = false,
Cédric Le Goaterac5e5a52017-08-30 21:46:16 +02001273 .radix_gtse = false,
1274 .xive = false
Suraj Jitindar Singh014d02c2017-02-28 17:03:48 +11001275 };
1276 int prop_len = prom_getproplen(prom.chosen,
1277 "ibm,arch-vec-5-platform-support");
Benjamin Herrenschmidta614f522018-10-15 13:49:55 +11001278
Christophe Leroyadcf5912019-04-26 16:23:29 +00001279 /*
1280 * First copy the architecture vec template
1281 *
1282 * use memcpy() instead of *vec = *vec_template so that GCC replaces it
1283 * by __memcpy() when KASAN is active
1284 */
1285 memcpy(&ibm_architecture_vec, &ibm_architecture_vec_template,
1286 sizeof(ibm_architecture_vec));
Benjamin Herrenschmidta614f522018-10-15 13:49:55 +11001287
Suraj Jitindar Singh014d02c2017-02-28 17:03:48 +11001288 if (prop_len > 1) {
1289 int i;
Suraj Jitindar Singhab912392018-09-05 12:09:50 +10001290 u8 vec[8];
Suraj Jitindar Singh014d02c2017-02-28 17:03:48 +11001291 prom_debug("Found ibm,arch-vec-5-platform-support, len: %d\n",
1292 prop_len);
Suraj Jitindar Singhab912392018-09-05 12:09:50 +10001293 if (prop_len > sizeof(vec))
1294 prom_printf("WARNING: ibm,arch-vec-5-platform-support longer than expected (len: %d)\n",
1295 prop_len);
Suraj Jitindar Singh014d02c2017-02-28 17:03:48 +11001296 prom_getprop(prom.chosen, "ibm,arch-vec-5-platform-support",
1297 &vec, sizeof(vec));
Suraj Jitindar Singhab912392018-09-05 12:09:50 +10001298 for (i = 0; i < sizeof(vec); i += 2) {
Suraj Jitindar Singh014d02c2017-02-28 17:03:48 +11001299 prom_debug("%d: index = 0x%x val = 0x%x\n", i / 2
1300 , vec[i]
1301 , vec[i + 1]);
1302 prom_parse_platform_support(vec[i], vec[i + 1],
1303 &supported);
1304 }
1305 }
1306
Alexey Kardashevskiy79b46862018-01-09 16:45:20 +11001307 if (supported.radix_mmu && supported.radix_gtse &&
1308 IS_ENABLED(CONFIG_PPC_RADIX_MMU)) {
Suraj Jitindar Singh014d02c2017-02-28 17:03:48 +11001309 /* Radix preferred - but we require GTSE for now */
1310 prom_debug("Asking for radix with GTSE\n");
1311 ibm_architecture_vec.vec5.mmu = OV5_FEAT(OV5_MMU_RADIX);
1312 ibm_architecture_vec.vec5.radix_ext = OV5_FEAT(OV5_RADIX_GTSE);
1313 } else if (supported.hash_mmu) {
1314 /* Default to hash mmu (if we can) */
1315 prom_debug("Asking for hash\n");
1316 ibm_architecture_vec.vec5.mmu = OV5_FEAT(OV5_MMU_HASH);
1317 } else {
1318 /* We're probably on a legacy hypervisor */
1319 prom_debug("Assuming legacy hash support\n");
1320 }
Cédric Le Goaterac5e5a52017-08-30 21:46:16 +02001321
1322 if (supported.xive) {
1323 prom_debug("Asking for XIVE\n");
1324 ibm_architecture_vec.vec5.intarch = OV5_FEAT(OV5_XIVE_EXPLOIT);
1325 }
Suraj Jitindar Singh014d02c2017-02-28 17:03:48 +11001326}
Benjamin Herrenschmidtefec9592010-02-04 14:33:54 +11001327
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001328static void __init prom_send_capabilities(void)
1329{
Benjamin Herrenschmidt493adff2013-08-07 02:01:38 +10001330 ihandle root;
Paul Mackerrasf709bfa2006-04-28 16:28:35 +10001331 prom_arg_t ret;
Laurent Dufourdbd0c5d2013-09-17 11:52:48 +02001332 u32 cores;
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001333
Suraj Jitindar Singh014d02c2017-02-28 17:03:48 +11001334 /* Check ibm,arch-vec-5-platform-support and fixup vec5 if required */
1335 prom_check_platform_support();
1336
Paul Mackerrasf709bfa2006-04-28 16:28:35 +10001337 root = call_prom("open", 1, 1, ADDR("/"));
1338 if (root != 0) {
Benjamin Herrenschmidtefec9592010-02-04 14:33:54 +11001339 /* We need to tell the FW about the number of cores we support.
1340 *
1341 * To do that, we count the number of threads on the first core
1342 * (we assume this is the same for all cores) and use it to
1343 * divide NR_CPUS.
1344 */
Laurent Dufourdbd0c5d2013-09-17 11:52:48 +02001345
Michael Ellerman76ffb572016-11-18 23:15:42 +11001346 cores = DIV_ROUND_UP(NR_CPUS, prom_count_smt_threads());
Mathieu Malaterreeae5f702018-04-06 22:12:19 +02001347 prom_printf("Max number of cores passed to firmware: %u (NR_CPUS = %d)\n",
Michael Ellerman76ffb572016-11-18 23:15:42 +11001348 cores, NR_CPUS);
1349
1350 ibm_architecture_vec.vec5.max_cpus = cpu_to_be32(cores);
Benjamin Herrenschmidtefec9592010-02-04 14:33:54 +11001351
Paul Mackerrasf709bfa2006-04-28 16:28:35 +10001352 /* try calling the ibm,client-architecture-support method */
Anton Blanchard049d0492009-09-21 20:47:39 +00001353 prom_printf("Calling ibm,client-architecture-support...");
Paul Mackerrasf709bfa2006-04-28 16:28:35 +10001354 if (call_prom_ret("call-method", 3, 2, &ret,
1355 ADDR("ibm,client-architecture-support"),
Benjamin Herrenschmidt33b74972006-06-07 12:01:32 +10001356 root,
Michael Ellerman76ffb572016-11-18 23:15:42 +11001357 ADDR(&ibm_architecture_vec)) == 0) {
Paul Mackerrasf709bfa2006-04-28 16:28:35 +10001358 /* the call exists... */
1359 if (ret)
Anton Blanchard4da727a2009-03-31 20:06:14 +00001360 prom_printf("\nWARNING: ibm,client-architecture"
Paul Mackerrasf709bfa2006-04-28 16:28:35 +10001361 "-support call FAILED!\n");
1362 call_prom("close", 1, 0, root);
Anton Blanchard4da727a2009-03-31 20:06:14 +00001363 prom_printf(" done\n");
Paul Mackerrasf709bfa2006-04-28 16:28:35 +10001364 return;
1365 }
1366 call_prom("close", 1, 0, root);
Anton Blanchard049d0492009-09-21 20:47:39 +00001367 prom_printf(" not implemented\n");
Paul Mackerrasf709bfa2006-04-28 16:28:35 +10001368 }
1369
Benjamin Herrenschmidt493adff2013-08-07 02:01:38 +10001370#ifdef __BIG_ENDIAN__
1371 {
1372 ihandle elfloader;
1373
1374 /* no ibm,client-architecture-support call, try the old way */
1375 elfloader = call_prom("open", 1, 1,
1376 ADDR("/packages/elf-loader"));
1377 if (elfloader == 0) {
1378 prom_printf("couldn't open /packages/elf-loader\n");
1379 return;
1380 }
1381 call_prom("call-method", 3, 1, ADDR("process-elf-header"),
1382 elfloader, ADDR(&fake_elf));
1383 call_prom("close", 1, 0, elfloader);
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001384 }
Benjamin Herrenschmidt493adff2013-08-07 02:01:38 +10001385#endif /* __BIG_ENDIAN__ */
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001386}
Benjamin Herrenschmidt11fdb302018-10-15 13:49:53 +11001387#endif /* CONFIG_PPC_PSERIES */
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001388
1389/*
1390 * Memory allocation strategy... our layout is normally:
1391 *
1392 * at 14Mb or more we have vmlinux, then a gap and initrd. In some
1393 * rare cases, initrd might end up being before the kernel though.
1394 * We assume this won't override the final kernel at 0, we have no
1395 * provision to handle that in this version, but it should hopefully
1396 * never happen.
1397 *
1398 * alloc_top is set to the top of RMO, eventually shrink down if the
1399 * TCEs overlap
1400 *
1401 * alloc_bottom is set to the top of kernel/initrd
1402 *
1403 * from there, allocations are done this way : rtas is allocated
1404 * topmost, and the device-tree is allocated from the bottom. We try
1405 * to grow the device-tree allocation as we progress. If we can't,
1406 * then we fail, we don't currently have a facility to restart
1407 * elsewhere, but that shouldn't be necessary.
1408 *
1409 * Note that calls to reserve_mem have to be done explicitly, memory
1410 * allocated with either alloc_up or alloc_down isn't automatically
1411 * reserved.
1412 */
1413
1414
1415/*
1416 * Allocates memory in the RMO upward from the kernel/initrd
1417 *
1418 * When align is 0, this is a special case, it means to allocate in place
1419 * at the current location of alloc_bottom or fail (that is basically
1420 * extending the previous allocation). Used for the device-tree flattening
1421 */
1422static unsigned long __init alloc_up(unsigned long size, unsigned long align)
1423{
Anton Blanchard5827d412012-11-26 17:40:03 +00001424 unsigned long base = alloc_bottom;
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001425 unsigned long addr = 0;
1426
Paul Mackerrasc49888202005-10-26 21:52:53 +10001427 if (align)
1428 base = _ALIGN_UP(base, align);
Mathieu Malaterreeae5f702018-04-06 22:12:19 +02001429 prom_debug("%s(%lx, %lx)\n", __func__, size, align);
Anton Blanchard5827d412012-11-26 17:40:03 +00001430 if (ram_top == 0)
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001431 prom_panic("alloc_up() called with mem not initialized\n");
1432
1433 if (align)
Anton Blanchard5827d412012-11-26 17:40:03 +00001434 base = _ALIGN_UP(alloc_bottom, align);
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001435 else
Anton Blanchard5827d412012-11-26 17:40:03 +00001436 base = alloc_bottom;
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001437
Anton Blanchard5827d412012-11-26 17:40:03 +00001438 for(; (base + size) <= alloc_top;
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001439 base = _ALIGN_UP(base + 0x100000, align)) {
Mathieu Malaterreeae5f702018-04-06 22:12:19 +02001440 prom_debug(" trying: 0x%lx\n\r", base);
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001441 addr = (unsigned long)prom_claim(base, size, 0);
Paul Mackerrasc49888202005-10-26 21:52:53 +10001442 if (addr != PROM_ERROR && addr != 0)
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001443 break;
1444 addr = 0;
1445 if (align == 0)
1446 break;
1447 }
1448 if (addr == 0)
1449 return 0;
Anton Blanchard5827d412012-11-26 17:40:03 +00001450 alloc_bottom = addr + size;
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001451
Mathieu Malaterreeae5f702018-04-06 22:12:19 +02001452 prom_debug(" -> %lx\n", addr);
1453 prom_debug(" alloc_bottom : %lx\n", alloc_bottom);
1454 prom_debug(" alloc_top : %lx\n", alloc_top);
1455 prom_debug(" alloc_top_hi : %lx\n", alloc_top_high);
1456 prom_debug(" rmo_top : %lx\n", rmo_top);
1457 prom_debug(" ram_top : %lx\n", ram_top);
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001458
1459 return addr;
1460}
1461
1462/*
1463 * Allocates memory downward, either from top of RMO, or if highmem
1464 * is set, from the top of RAM. Note that this one doesn't handle
1465 * failures. It does claim memory if highmem is not set.
1466 */
1467static unsigned long __init alloc_down(unsigned long size, unsigned long align,
1468 int highmem)
1469{
1470 unsigned long base, addr = 0;
1471
Mathieu Malaterreeae5f702018-04-06 22:12:19 +02001472 prom_debug("%s(%lx, %lx, %s)\n", __func__, size, align,
Anton Blanchard5827d412012-11-26 17:40:03 +00001473 highmem ? "(high)" : "(low)");
1474 if (ram_top == 0)
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001475 prom_panic("alloc_down() called with mem not initialized\n");
1476
1477 if (highmem) {
1478 /* Carve out storage for the TCE table. */
Anton Blanchard5827d412012-11-26 17:40:03 +00001479 addr = _ALIGN_DOWN(alloc_top_high - size, align);
1480 if (addr <= alloc_bottom)
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001481 return 0;
1482 /* Will we bump into the RMO ? If yes, check out that we
1483 * didn't overlap existing allocations there, if we did,
1484 * we are dead, we must be the first in town !
1485 */
Anton Blanchard5827d412012-11-26 17:40:03 +00001486 if (addr < rmo_top) {
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001487 /* Good, we are first */
Anton Blanchard5827d412012-11-26 17:40:03 +00001488 if (alloc_top == rmo_top)
1489 alloc_top = rmo_top = addr;
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001490 else
1491 return 0;
1492 }
Anton Blanchard5827d412012-11-26 17:40:03 +00001493 alloc_top_high = addr;
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001494 goto bail;
1495 }
1496
Anton Blanchard5827d412012-11-26 17:40:03 +00001497 base = _ALIGN_DOWN(alloc_top - size, align);
1498 for (; base > alloc_bottom;
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001499 base = _ALIGN_DOWN(base - 0x100000, align)) {
Mathieu Malaterreeae5f702018-04-06 22:12:19 +02001500 prom_debug(" trying: 0x%lx\n\r", base);
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001501 addr = (unsigned long)prom_claim(base, size, 0);
Paul Mackerrasc49888202005-10-26 21:52:53 +10001502 if (addr != PROM_ERROR && addr != 0)
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001503 break;
1504 addr = 0;
1505 }
1506 if (addr == 0)
1507 return 0;
Anton Blanchard5827d412012-11-26 17:40:03 +00001508 alloc_top = addr;
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001509
1510 bail:
Mathieu Malaterreeae5f702018-04-06 22:12:19 +02001511 prom_debug(" -> %lx\n", addr);
1512 prom_debug(" alloc_bottom : %lx\n", alloc_bottom);
1513 prom_debug(" alloc_top : %lx\n", alloc_top);
1514 prom_debug(" alloc_top_hi : %lx\n", alloc_top_high);
1515 prom_debug(" rmo_top : %lx\n", rmo_top);
1516 prom_debug(" ram_top : %lx\n", ram_top);
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001517
1518 return addr;
1519}
1520
1521/*
1522 * Parse a "reg" cell
1523 */
1524static unsigned long __init prom_next_cell(int s, cell_t **cellp)
1525{
1526 cell_t *p = *cellp;
1527 unsigned long r = 0;
1528
1529 /* Ignore more than 2 cells */
1530 while (s > sizeof(unsigned long) / 4) {
1531 p++;
1532 s--;
1533 }
Benjamin Herrenschmidt493adff2013-08-07 02:01:38 +10001534 r = be32_to_cpu(*p++);
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001535#ifdef CONFIG_PPC64
Paul Mackerras35499c02005-10-22 16:02:39 +10001536 if (s > 1) {
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001537 r <<= 32;
Benjamin Herrenschmidt493adff2013-08-07 02:01:38 +10001538 r |= be32_to_cpu(*(p++));
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001539 }
1540#endif
1541 *cellp = p;
1542 return r;
1543}
1544
1545/*
1546 * Very dumb function for adding to the memory reserve list, but
1547 * we don't need anything smarter at this point
1548 *
1549 * XXX Eventually check for collisions. They should NEVER happen.
1550 * If problems seem to show up, it would be a good start to track
1551 * them down.
1552 */
Michael Ellerman0108d3f2007-05-07 15:58:28 +10001553static void __init reserve_mem(u64 base, u64 size)
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001554{
Kumar Galacbbcf342006-01-11 17:57:13 -06001555 u64 top = base + size;
Anton Blanchard5827d412012-11-26 17:40:03 +00001556 unsigned long cnt = mem_reserve_cnt;
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001557
1558 if (size == 0)
1559 return;
1560
1561 /* We need to always keep one empty entry so that we
1562 * have our terminator with "size" set to 0 since we are
1563 * dumb and just copy this entire array to the boot params
1564 */
1565 base = _ALIGN_DOWN(base, PAGE_SIZE);
1566 top = _ALIGN_UP(top, PAGE_SIZE);
1567 size = top - base;
1568
1569 if (cnt >= (MEM_RESERVE_MAP_SIZE - 1))
1570 prom_panic("Memory reserve map exhausted !\n");
Benjamin Herrenschmidt493adff2013-08-07 02:01:38 +10001571 mem_reserve_map[cnt].base = cpu_to_be64(base);
1572 mem_reserve_map[cnt].size = cpu_to_be64(size);
Anton Blanchard5827d412012-11-26 17:40:03 +00001573 mem_reserve_cnt = cnt + 1;
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001574}
1575
1576/*
Adrian Bunkb3c2ffd2006-06-30 18:20:44 +02001577 * Initialize memory allocation mechanism, parse "memory" nodes and
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001578 * obtain that way the top of memory and RMO to setup out local allocator
1579 */
1580static void __init prom_init_mem(void)
1581{
1582 phandle node;
Mathieu Malaterreeab00a22018-04-04 22:08:35 +02001583 char type[64];
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001584 unsigned int plen;
1585 cell_t *p, *endp;
Benjamin Herrenschmidt493adff2013-08-07 02:01:38 +10001586 __be32 val;
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001587 u32 rac, rsc;
1588
1589 /*
1590 * We iterate the memory nodes to find
1591 * 1) top of RMO (first node)
1592 * 2) top of memory
1593 */
Benjamin Herrenschmidt493adff2013-08-07 02:01:38 +10001594 val = cpu_to_be32(2);
1595 prom_getprop(prom.root, "#address-cells", &val, sizeof(val));
1596 rac = be32_to_cpu(val);
1597 val = cpu_to_be32(1);
1598 prom_getprop(prom.root, "#size-cells", &val, sizeof(rsc));
1599 rsc = be32_to_cpu(val);
1600 prom_debug("root_addr_cells: %x\n", rac);
1601 prom_debug("root_size_cells: %x\n", rsc);
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001602
1603 prom_debug("scanning memory:\n");
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001604
1605 for (node = 0; prom_next_node(&node); ) {
1606 type[0] = 0;
1607 prom_getprop(node, "device_type", type, sizeof(type));
1608
Paul Mackerrasc49888202005-10-26 21:52:53 +10001609 if (type[0] == 0) {
1610 /*
1611 * CHRP Longtrail machines have no device_type
1612 * on the memory node, so check the name instead...
1613 */
1614 prom_getprop(node, "name", type, sizeof(type));
1615 }
Christophe Leroy450e7dd2019-04-26 16:23:28 +00001616 if (prom_strcmp(type, "memory"))
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001617 continue;
Paul Mackerrasc49888202005-10-26 21:52:53 +10001618
Anton Blanchard5827d412012-11-26 17:40:03 +00001619 plen = prom_getprop(node, "reg", regbuf, sizeof(regbuf));
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001620 if (plen > sizeof(regbuf)) {
1621 prom_printf("memory node too large for buffer !\n");
1622 plen = sizeof(regbuf);
1623 }
Anton Blanchard5827d412012-11-26 17:40:03 +00001624 p = regbuf;
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001625 endp = p + (plen / sizeof(cell_t));
1626
1627#ifdef DEBUG_PROM
Mathieu Malaterrec806a6f2019-05-23 12:25:20 +02001628 memset(prom_scratch, 0, sizeof(prom_scratch));
1629 call_prom("package-to-path", 3, 1, node, prom_scratch,
1630 sizeof(prom_scratch) - 1);
1631 prom_debug(" node %s :\n", prom_scratch);
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001632#endif /* DEBUG_PROM */
1633
1634 while ((endp - p) >= (rac + rsc)) {
1635 unsigned long base, size;
1636
1637 base = prom_next_cell(rac, &p);
1638 size = prom_next_cell(rsc, &p);
1639
1640 if (size == 0)
1641 continue;
Mathieu Malaterreeae5f702018-04-06 22:12:19 +02001642 prom_debug(" %lx %lx\n", base, size);
Anton Blanchard5827d412012-11-26 17:40:03 +00001643 if (base == 0 && (of_platform & PLATFORM_LPAR))
1644 rmo_top = size;
1645 if ((base + size) > ram_top)
1646 ram_top = base + size;
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001647 }
1648 }
1649
Anton Blanchard5827d412012-11-26 17:40:03 +00001650 alloc_bottom = PAGE_ALIGN((unsigned long)&_end + 0x4000);
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001651
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001652 /*
Benjamin Krillcf687872009-07-27 22:02:39 +00001653 * If prom_memory_limit is set we reduce the upper limits *except* for
1654 * alloc_top_high. This must be the real top of RAM so we can put
1655 * TCE's up there.
1656 */
1657
Anton Blanchard5827d412012-11-26 17:40:03 +00001658 alloc_top_high = ram_top;
Benjamin Krillcf687872009-07-27 22:02:39 +00001659
Anton Blanchard5827d412012-11-26 17:40:03 +00001660 if (prom_memory_limit) {
1661 if (prom_memory_limit <= alloc_bottom) {
Mathieu Malaterreeae5f702018-04-06 22:12:19 +02001662 prom_printf("Ignoring mem=%lx <= alloc_bottom.\n",
1663 prom_memory_limit);
Anton Blanchard5827d412012-11-26 17:40:03 +00001664 prom_memory_limit = 0;
1665 } else if (prom_memory_limit >= ram_top) {
Mathieu Malaterreeae5f702018-04-06 22:12:19 +02001666 prom_printf("Ignoring mem=%lx >= ram_top.\n",
1667 prom_memory_limit);
Anton Blanchard5827d412012-11-26 17:40:03 +00001668 prom_memory_limit = 0;
Benjamin Krillcf687872009-07-27 22:02:39 +00001669 } else {
Anton Blanchard5827d412012-11-26 17:40:03 +00001670 ram_top = prom_memory_limit;
1671 rmo_top = min(rmo_top, prom_memory_limit);
Benjamin Krillcf687872009-07-27 22:02:39 +00001672 }
1673 }
1674
1675 /*
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001676 * Setup our top alloc point, that is top of RMO or top of
1677 * segment 0 when running non-LPAR.
1678 * Some RS64 machines have buggy firmware where claims up at
1679 * 1GB fail. Cap at 768MB as a workaround.
1680 * Since 768MB is plenty of room, and we need to cap to something
1681 * reasonable on 32-bit, cap at 768MB on all machines.
1682 */
Anton Blanchard5827d412012-11-26 17:40:03 +00001683 if (!rmo_top)
1684 rmo_top = ram_top;
1685 rmo_top = min(0x30000000ul, rmo_top);
1686 alloc_top = rmo_top;
1687 alloc_top_high = ram_top;
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001688
Paul Mackerras64968f62011-12-13 17:54:13 +00001689 /*
1690 * Check if we have an initrd after the kernel but still inside
1691 * the RMO. If we do move our bottom point to after it.
1692 */
Anton Blanchard5827d412012-11-26 17:40:03 +00001693 if (prom_initrd_start &&
1694 prom_initrd_start < rmo_top &&
1695 prom_initrd_end > alloc_bottom)
1696 alloc_bottom = PAGE_ALIGN(prom_initrd_end);
Paul Mackerras64968f62011-12-13 17:54:13 +00001697
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001698 prom_printf("memory layout at init:\n");
Mathieu Malaterreeae5f702018-04-06 22:12:19 +02001699 prom_printf(" memory_limit : %lx (16 MB aligned)\n",
1700 prom_memory_limit);
1701 prom_printf(" alloc_bottom : %lx\n", alloc_bottom);
1702 prom_printf(" alloc_top : %lx\n", alloc_top);
1703 prom_printf(" alloc_top_hi : %lx\n", alloc_top_high);
1704 prom_printf(" rmo_top : %lx\n", rmo_top);
1705 prom_printf(" ram_top : %lx\n", ram_top);
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001706}
1707
Benjamin Herrenschmidt27f44882011-09-19 18:27:58 +00001708static void __init prom_close_stdin(void)
1709{
Benjamin Herrenschmidt493adff2013-08-07 02:01:38 +10001710 __be32 val;
1711 ihandle stdin;
Benjamin Herrenschmidt27f44882011-09-19 18:27:58 +00001712
Benjamin Herrenschmidt493adff2013-08-07 02:01:38 +10001713 if (prom_getprop(prom.chosen, "stdin", &val, sizeof(val)) > 0) {
1714 stdin = be32_to_cpu(val);
1715 call_prom("close", 1, 0, stdin);
1716 }
Benjamin Herrenschmidt27f44882011-09-19 18:27:58 +00001717}
1718
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001719/*
1720 * Allocate room for and instantiate RTAS
1721 */
1722static void __init prom_instantiate_rtas(void)
1723{
1724 phandle rtas_node;
1725 ihandle rtas_inst;
1726 u32 base, entry = 0;
Benjamin Herrenschmidt493adff2013-08-07 02:01:38 +10001727 __be32 val;
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001728 u32 size = 0;
1729
1730 prom_debug("prom_instantiate_rtas: start...\n");
1731
1732 rtas_node = call_prom("finddevice", 1, 1, ADDR("/rtas"));
1733 prom_debug("rtas_node: %x\n", rtas_node);
1734 if (!PHANDLE_VALID(rtas_node))
1735 return;
1736
Benjamin Herrenschmidt493adff2013-08-07 02:01:38 +10001737 val = 0;
1738 prom_getprop(rtas_node, "rtas-size", &val, sizeof(size));
1739 size = be32_to_cpu(val);
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001740 if (size == 0)
1741 return;
1742
1743 base = alloc_down(size, PAGE_SIZE, 0);
Anton Blanchard6d1e2c62011-11-14 12:55:47 +00001744 if (base == 0)
1745 prom_panic("Could not allocate memory for RTAS\n");
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001746
1747 rtas_inst = call_prom("open", 1, 1, ADDR("/rtas"));
1748 if (!IHANDLE_VALID(rtas_inst)) {
Paul Mackerrasa23414b2005-11-10 12:00:55 +11001749 prom_printf("opening rtas package failed (%x)\n", rtas_inst);
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001750 return;
1751 }
1752
Anton Blanchard1f8737a2009-03-31 20:06:15 +00001753 prom_printf("instantiating rtas at 0x%x...", base);
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001754
1755 if (call_prom_ret("call-method", 3, 2, &entry,
1756 ADDR("instantiate-rtas"),
Paul Mackerrasa23414b2005-11-10 12:00:55 +11001757 rtas_inst, base) != 0
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001758 || entry == 0) {
1759 prom_printf(" failed\n");
1760 return;
1761 }
1762 prom_printf(" done\n");
1763
1764 reserve_mem(base, size);
1765
Benjamin Herrenschmidt493adff2013-08-07 02:01:38 +10001766 val = cpu_to_be32(base);
Paul Mackerrasa23414b2005-11-10 12:00:55 +11001767 prom_setprop(rtas_node, "/rtas", "linux,rtas-base",
Benjamin Herrenschmidt493adff2013-08-07 02:01:38 +10001768 &val, sizeof(val));
1769 val = cpu_to_be32(entry);
Paul Mackerrasa23414b2005-11-10 12:00:55 +11001770 prom_setprop(rtas_node, "/rtas", "linux,rtas-entry",
Benjamin Herrenschmidt493adff2013-08-07 02:01:38 +10001771 &val, sizeof(val));
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001772
Benjamin Herrenschmidtdbe78b42013-09-25 14:02:50 +10001773 /* Check if it supports "query-cpu-stopped-state" */
1774 if (prom_getprop(rtas_node, "query-cpu-stopped-state",
1775 &val, sizeof(val)) != PROM_ERROR)
1776 rtas_has_query_cpu_stopped = true;
1777
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001778 prom_debug("rtas base = 0x%x\n", base);
1779 prom_debug("rtas entry = 0x%x\n", entry);
Mathieu Malaterreeae5f702018-04-06 22:12:19 +02001780 prom_debug("rtas size = 0x%x\n", size);
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001781
1782 prom_debug("prom_instantiate_rtas: end...\n");
1783}
1784
1785#ifdef CONFIG_PPC64
1786/*
Ashley Lai4a727422012-08-14 18:34:57 -05001787 * Allocate room for and instantiate Stored Measurement Log (SML)
1788 */
1789static void __init prom_instantiate_sml(void)
1790{
1791 phandle ibmvtpm_node;
1792 ihandle ibmvtpm_inst;
Hon Ching \(Vicky\) Lob4ed0462015-10-07 20:11:53 -04001793 u32 entry = 0, size = 0, succ = 0;
Ashley Lai4a727422012-08-14 18:34:57 -05001794 u64 base;
Hon Ching \(Vicky\) Lob4ed0462015-10-07 20:11:53 -04001795 __be32 val;
Ashley Lai4a727422012-08-14 18:34:57 -05001796
1797 prom_debug("prom_instantiate_sml: start...\n");
1798
Hon Ching \(Vicky\) Lo2f82e982015-10-07 20:11:52 -04001799 ibmvtpm_node = call_prom("finddevice", 1, 1, ADDR("/vdevice/vtpm"));
Ashley Lai4a727422012-08-14 18:34:57 -05001800 prom_debug("ibmvtpm_node: %x\n", ibmvtpm_node);
1801 if (!PHANDLE_VALID(ibmvtpm_node))
1802 return;
1803
Hon Ching \(Vicky\) Lo2f82e982015-10-07 20:11:52 -04001804 ibmvtpm_inst = call_prom("open", 1, 1, ADDR("/vdevice/vtpm"));
Ashley Lai4a727422012-08-14 18:34:57 -05001805 if (!IHANDLE_VALID(ibmvtpm_inst)) {
1806 prom_printf("opening vtpm package failed (%x)\n", ibmvtpm_inst);
1807 return;
1808 }
1809
Hon Ching \(Vicky\) Lob4ed0462015-10-07 20:11:53 -04001810 if (prom_getprop(ibmvtpm_node, "ibm,sml-efi-reformat-supported",
1811 &val, sizeof(val)) != PROM_ERROR) {
1812 if (call_prom_ret("call-method", 2, 2, &succ,
1813 ADDR("reformat-sml-to-efi-alignment"),
1814 ibmvtpm_inst) != 0 || succ == 0) {
1815 prom_printf("Reformat SML to EFI alignment failed\n");
1816 return;
1817 }
Hon Ching \(Vicky\) Lob4ed0462015-10-07 20:11:53 -04001818
Hon Ching \(Vicky\) Lo9e5d4af2015-10-07 20:11:54 -04001819 if (call_prom_ret("call-method", 2, 2, &size,
1820 ADDR("sml-get-allocated-size"),
1821 ibmvtpm_inst) != 0 || size == 0) {
1822 prom_printf("SML get allocated size failed\n");
1823 return;
1824 }
1825 } else {
1826 if (call_prom_ret("call-method", 2, 2, &size,
1827 ADDR("sml-get-handover-size"),
1828 ibmvtpm_inst) != 0 || size == 0) {
1829 prom_printf("SML get handover size failed\n");
1830 return;
1831 }
Ashley Lai4a727422012-08-14 18:34:57 -05001832 }
1833
1834 base = alloc_down(size, PAGE_SIZE, 0);
1835 if (base == 0)
1836 prom_panic("Could not allocate memory for sml\n");
1837
Mathieu Malaterreeae5f702018-04-06 22:12:19 +02001838 prom_printf("instantiating sml at 0x%llx...", base);
Ashley Lai4a727422012-08-14 18:34:57 -05001839
Hon Ching \(Vicky\) Lo9e5d4af2015-10-07 20:11:54 -04001840 memset((void *)base, 0, size);
1841
Ashley Lai4a727422012-08-14 18:34:57 -05001842 if (call_prom_ret("call-method", 4, 2, &entry,
1843 ADDR("sml-handover"),
1844 ibmvtpm_inst, size, base) != 0 || entry == 0) {
1845 prom_printf("SML handover failed\n");
1846 return;
1847 }
1848 prom_printf(" done\n");
1849
1850 reserve_mem(base, size);
1851
Hon Ching \(Vicky\) Lo2f82e982015-10-07 20:11:52 -04001852 prom_setprop(ibmvtpm_node, "/vdevice/vtpm", "linux,sml-base",
Ashley Lai4a727422012-08-14 18:34:57 -05001853 &base, sizeof(base));
Hon Ching \(Vicky\) Lo2f82e982015-10-07 20:11:52 -04001854 prom_setprop(ibmvtpm_node, "/vdevice/vtpm", "linux,sml-size",
Ashley Lai4a727422012-08-14 18:34:57 -05001855 &size, sizeof(size));
1856
Mathieu Malaterreeae5f702018-04-06 22:12:19 +02001857 prom_debug("sml base = 0x%llx\n", base);
1858 prom_debug("sml size = 0x%x\n", size);
Ashley Lai4a727422012-08-14 18:34:57 -05001859
1860 prom_debug("prom_instantiate_sml: end...\n");
1861}
1862
1863/*
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001864 * Allocate room for and initialize TCE tables
1865 */
Benjamin Herrenschmidt493adff2013-08-07 02:01:38 +10001866#ifdef __BIG_ENDIAN__
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001867static void __init prom_initialize_tce_table(void)
1868{
1869 phandle node;
1870 ihandle phb_node;
1871 char compatible[64], type[64], model[64];
Anton Blanchard5827d412012-11-26 17:40:03 +00001872 char *path = prom_scratch;
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001873 u64 base, align;
1874 u32 minalign, minsize;
1875 u64 tce_entry, *tce_entryp;
1876 u64 local_alloc_top, local_alloc_bottom;
1877 u64 i;
1878
Anton Blanchard5827d412012-11-26 17:40:03 +00001879 if (prom_iommu_off)
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001880 return;
1881
1882 prom_debug("starting prom_initialize_tce_table\n");
1883
1884 /* Cache current top of allocs so we reserve a single block */
Anton Blanchard5827d412012-11-26 17:40:03 +00001885 local_alloc_top = alloc_top_high;
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001886 local_alloc_bottom = local_alloc_top;
1887
1888 /* Search all nodes looking for PHBs. */
1889 for (node = 0; prom_next_node(&node); ) {
1890 compatible[0] = 0;
1891 type[0] = 0;
1892 model[0] = 0;
1893 prom_getprop(node, "compatible",
1894 compatible, sizeof(compatible));
1895 prom_getprop(node, "device_type", type, sizeof(type));
1896 prom_getprop(node, "model", model, sizeof(model));
1897
Christophe Leroy450e7dd2019-04-26 16:23:28 +00001898 if ((type[0] == 0) || (prom_strstr(type, "pci") == NULL))
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001899 continue;
1900
Linas Vepstase788ff12007-09-07 03:45:21 +10001901 /* Keep the old logic intact to avoid regression. */
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001902 if (compatible[0] != 0) {
Christophe Leroy450e7dd2019-04-26 16:23:28 +00001903 if ((prom_strstr(compatible, "python") == NULL) &&
1904 (prom_strstr(compatible, "Speedwagon") == NULL) &&
1905 (prom_strstr(compatible, "Winnipeg") == NULL))
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001906 continue;
1907 } else if (model[0] != 0) {
Christophe Leroy450e7dd2019-04-26 16:23:28 +00001908 if ((prom_strstr(model, "ython") == NULL) &&
1909 (prom_strstr(model, "peedwagon") == NULL) &&
1910 (prom_strstr(model, "innipeg") == NULL))
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001911 continue;
1912 }
1913
1914 if (prom_getprop(node, "tce-table-minalign", &minalign,
1915 sizeof(minalign)) == PROM_ERROR)
1916 minalign = 0;
1917 if (prom_getprop(node, "tce-table-minsize", &minsize,
1918 sizeof(minsize)) == PROM_ERROR)
1919 minsize = 4UL << 20;
1920
1921 /*
1922 * Even though we read what OF wants, we just set the table
1923 * size to 4 MB. This is enough to map 2GB of PCI DMA space.
1924 * By doing this, we avoid the pitfalls of trying to DMA to
1925 * MMIO space and the DMA alias hole.
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001926 */
Nicholas Piggin471d7ff2018-02-21 05:08:29 +10001927 minsize = 4UL << 20;
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001928
1929 /* Align to the greater of the align or size */
1930 align = max(minalign, minsize);
1931 base = alloc_down(minsize, align, 1);
1932 if (base == 0)
1933 prom_panic("ERROR, cannot find space for TCE table.\n");
1934 if (base < local_alloc_bottom)
1935 local_alloc_bottom = base;
1936
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001937 /* It seems OF doesn't null-terminate the path :-( */
Christophe Leroyd7fbe2a2019-04-02 09:08:38 +00001938 memset(path, 0, sizeof(prom_scratch));
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001939 /* Call OF to setup the TCE hardware */
1940 if (call_prom("package-to-path", 3, 1, node,
Christophe Leroyd7fbe2a2019-04-02 09:08:38 +00001941 path, sizeof(prom_scratch) - 1) == PROM_ERROR) {
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001942 prom_printf("package-to-path failed\n");
1943 }
1944
Paul Mackerrasa23414b2005-11-10 12:00:55 +11001945 /* Save away the TCE table attributes for later use. */
1946 prom_setprop(node, path, "linux,tce-base", &base, sizeof(base));
1947 prom_setprop(node, path, "linux,tce-size", &minsize, sizeof(minsize));
1948
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001949 prom_debug("TCE table: %s\n", path);
1950 prom_debug("\tnode = 0x%x\n", node);
Mathieu Malaterreeae5f702018-04-06 22:12:19 +02001951 prom_debug("\tbase = 0x%llx\n", base);
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001952 prom_debug("\tsize = 0x%x\n", minsize);
1953
1954 /* Initialize the table to have a one-to-one mapping
1955 * over the allocated size.
1956 */
Ingo Molnar2b931fb2009-01-06 13:56:52 +00001957 tce_entryp = (u64 *)base;
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001958 for (i = 0; i < (minsize >> 3) ;tce_entryp++, i++) {
1959 tce_entry = (i << PAGE_SHIFT);
1960 tce_entry |= 0x3;
1961 *tce_entryp = tce_entry;
1962 }
1963
1964 prom_printf("opening PHB %s", path);
1965 phb_node = call_prom("open", 1, 1, path);
1966 if (phb_node == 0)
1967 prom_printf("... failed\n");
1968 else
1969 prom_printf("... done\n");
1970
1971 call_prom("call-method", 6, 0, ADDR("set-64-bit-addressing"),
1972 phb_node, -1, minsize,
1973 (u32) base, (u32) (base >> 32));
1974 call_prom("close", 1, 0, phb_node);
1975 }
1976
1977 reserve_mem(local_alloc_bottom, local_alloc_top - local_alloc_bottom);
1978
Michael Ellerman2babf5c2006-05-17 18:00:46 +10001979 /* These are only really needed if there is a memory limit in
1980 * effect, but we don't know so export them always. */
Anton Blanchard5827d412012-11-26 17:40:03 +00001981 prom_tce_alloc_start = local_alloc_bottom;
1982 prom_tce_alloc_end = local_alloc_top;
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001983
1984 /* Flag the first invalid entry */
1985 prom_debug("ending prom_initialize_tce_table\n");
1986}
Benjamin Herrenschmidt493adff2013-08-07 02:01:38 +10001987#endif /* __BIG_ENDIAN__ */
1988#endif /* CONFIG_PPC64 */
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001989
1990/*
1991 * With CHRP SMP we need to use the OF to start the other processors.
1992 * We can't wait until smp_boot_cpus (the OF is trashed by then)
1993 * so we have to put the processors into a holding pattern controlled
1994 * by the kernel (not OF) before we destroy the OF.
1995 *
1996 * This uses a chunk of low memory, puts some holding pattern
1997 * code there and sends the other processors off to there until
1998 * smp_boot_cpus tells them to do something. The holding pattern
1999 * checks that address until its cpu # is there, when it is that
2000 * cpu jumps to __secondary_start(). smp_boot_cpus() takes care
2001 * of setting those values.
2002 *
2003 * We also use physical address 0x4 here to tell when a cpu
2004 * is in its holding pattern code.
2005 *
2006 * -- Cort
2007 */
Paul Mackerrasbbd0abd2005-10-26 21:45:56 +10002008/*
2009 * We want to reference the copy of __secondary_hold_* in the
2010 * 0 - 0x100 address range
2011 */
2012#define LOW_ADDR(x) (((unsigned long) &(x)) & 0xff)
2013
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002014static void __init prom_hold_cpus(void)
2015{
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002016 unsigned long i;
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002017 phandle node;
2018 char type[64];
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002019 unsigned long *spinloop
Paul Mackerrasbbd0abd2005-10-26 21:45:56 +10002020 = (void *) LOW_ADDR(__secondary_hold_spinloop);
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002021 unsigned long *acknowledge
Paul Mackerrasbbd0abd2005-10-26 21:45:56 +10002022 = (void *) LOW_ADDR(__secondary_hold_acknowledge);
Paul Mackerrasbbd0abd2005-10-26 21:45:56 +10002023 unsigned long secondary_hold = LOW_ADDR(__secondary_hold);
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002024
Benjamin Herrenschmidtdbe78b42013-09-25 14:02:50 +10002025 /*
2026 * On pseries, if RTAS supports "query-cpu-stopped-state",
2027 * we skip this stage, the CPUs will be started by the
2028 * kernel using RTAS.
2029 */
2030 if ((of_platform == PLATFORM_PSERIES ||
2031 of_platform == PLATFORM_PSERIES_LPAR) &&
2032 rtas_has_query_cpu_stopped) {
2033 prom_printf("prom_hold_cpus: skipped\n");
2034 return;
2035 }
2036
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002037 prom_debug("prom_hold_cpus: start...\n");
Mathieu Malaterreeae5f702018-04-06 22:12:19 +02002038 prom_debug(" 1) spinloop = 0x%lx\n", (unsigned long)spinloop);
2039 prom_debug(" 1) *spinloop = 0x%lx\n", *spinloop);
2040 prom_debug(" 1) acknowledge = 0x%lx\n",
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002041 (unsigned long)acknowledge);
Mathieu Malaterreeae5f702018-04-06 22:12:19 +02002042 prom_debug(" 1) *acknowledge = 0x%lx\n", *acknowledge);
2043 prom_debug(" 1) secondary_hold = 0x%lx\n", secondary_hold);
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002044
2045 /* Set the common spinloop variable, so all of the secondary cpus
2046 * will block when they are awakened from their OF spinloop.
2047 * This must occur for both SMP and non SMP kernels, since OF will
2048 * be trashed when we move the kernel.
2049 */
2050 *spinloop = 0;
2051
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002052 /* look for cpus */
2053 for (node = 0; prom_next_node(&node); ) {
Benjamin Herrenschmidt493adff2013-08-07 02:01:38 +10002054 unsigned int cpu_no;
2055 __be32 reg;
2056
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002057 type[0] = 0;
2058 prom_getprop(node, "device_type", type, sizeof(type));
Christophe Leroy450e7dd2019-04-26 16:23:28 +00002059 if (prom_strcmp(type, "cpu") != 0)
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002060 continue;
2061
2062 /* Skip non-configured cpus. */
2063 if (prom_getprop(node, "status", type, sizeof(type)) > 0)
Christophe Leroy450e7dd2019-04-26 16:23:28 +00002064 if (prom_strcmp(type, "okay") != 0)
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002065 continue;
2066
Benjamin Herrenschmidt493adff2013-08-07 02:01:38 +10002067 reg = cpu_to_be32(-1); /* make sparse happy */
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002068 prom_getprop(node, "reg", &reg, sizeof(reg));
Benjamin Herrenschmidt493adff2013-08-07 02:01:38 +10002069 cpu_no = be32_to_cpu(reg);
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002070
Mathieu Malaterreeae5f702018-04-06 22:12:19 +02002071 prom_debug("cpu hw idx = %u\n", cpu_no);
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002072
2073 /* Init the acknowledge var which will be reset by
2074 * the secondary cpu when it awakens from its OF
2075 * spinloop.
2076 */
2077 *acknowledge = (unsigned long)-1;
2078
Benjamin Herrenschmidt493adff2013-08-07 02:01:38 +10002079 if (cpu_no != prom.cpu) {
Benjamin Herrenschmidt27f44882011-09-19 18:27:58 +00002080 /* Primary Thread of non-boot cpu or any thread */
Mathieu Malaterreeae5f702018-04-06 22:12:19 +02002081 prom_printf("starting cpu hw idx %u... ", cpu_no);
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002082 call_prom("start-cpu", 3, 0, node,
Benjamin Herrenschmidt493adff2013-08-07 02:01:38 +10002083 secondary_hold, cpu_no);
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002084
Paul Mackerrasbbd0abd2005-10-26 21:45:56 +10002085 for (i = 0; (i < 100000000) &&
2086 (*acknowledge == ((unsigned long)-1)); i++ )
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002087 mb();
2088
Benjamin Herrenschmidt493adff2013-08-07 02:01:38 +10002089 if (*acknowledge == cpu_no)
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002090 prom_printf("done\n");
Paul Mackerrasbbd0abd2005-10-26 21:45:56 +10002091 else
Mathieu Malaterreeae5f702018-04-06 22:12:19 +02002092 prom_printf("failed: %lx\n", *acknowledge);
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002093 }
2094#ifdef CONFIG_SMP
2095 else
Mathieu Malaterreeae5f702018-04-06 22:12:19 +02002096 prom_printf("boot cpu hw idx %u\n", cpu_no);
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002097#endif /* CONFIG_SMP */
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002098 }
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002099
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002100 prom_debug("prom_hold_cpus: end...\n");
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002101}
2102
2103
2104static void __init prom_init_client_services(unsigned long pp)
2105{
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002106 /* Get a handle to the prom entry point before anything else */
Anton Blanchard5827d412012-11-26 17:40:03 +00002107 prom_entry = pp;
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002108
2109 /* get a handle for the stdout device */
Anton Blanchard5827d412012-11-26 17:40:03 +00002110 prom.chosen = call_prom("finddevice", 1, 1, ADDR("/chosen"));
2111 if (!PHANDLE_VALID(prom.chosen))
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002112 prom_panic("cannot find chosen"); /* msg won't be printed :( */
2113
2114 /* get device tree root */
Anton Blanchard5827d412012-11-26 17:40:03 +00002115 prom.root = call_prom("finddevice", 1, 1, ADDR("/"));
2116 if (!PHANDLE_VALID(prom.root))
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002117 prom_panic("cannot find device tree root"); /* msg won't be printed :( */
Paul Mackerrasa575b802005-10-23 17:23:21 +10002118
Anton Blanchard5827d412012-11-26 17:40:03 +00002119 prom.mmumap = 0;
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002120}
2121
Paul Mackerrasa575b802005-10-23 17:23:21 +10002122#ifdef CONFIG_PPC32
2123/*
2124 * For really old powermacs, we need to map things we claim.
2125 * For that, we need the ihandle of the mmu.
Paul Mackerrasa23414b2005-11-10 12:00:55 +11002126 * Also, on the longtrail, we need to work around other bugs.
Paul Mackerrasa575b802005-10-23 17:23:21 +10002127 */
2128static void __init prom_find_mmu(void)
2129{
Paul Mackerrasa575b802005-10-23 17:23:21 +10002130 phandle oprom;
2131 char version[64];
2132
2133 oprom = call_prom("finddevice", 1, 1, ADDR("/openprom"));
2134 if (!PHANDLE_VALID(oprom))
2135 return;
2136 if (prom_getprop(oprom, "model", version, sizeof(version)) <= 0)
2137 return;
2138 version[sizeof(version) - 1] = 0;
Paul Mackerrasa575b802005-10-23 17:23:21 +10002139 /* XXX might need to add other versions here */
Christophe Leroy450e7dd2019-04-26 16:23:28 +00002140 if (prom_strcmp(version, "Open Firmware, 1.0.5") == 0)
Paul Mackerrasa23414b2005-11-10 12:00:55 +11002141 of_workarounds = OF_WA_CLAIM;
Christophe Leroy450e7dd2019-04-26 16:23:28 +00002142 else if (prom_strncmp(version, "FirmWorks,3.", 12) == 0) {
Paul Mackerrasa23414b2005-11-10 12:00:55 +11002143 of_workarounds = OF_WA_CLAIM | OF_WA_LONGTRAIL;
2144 call_prom("interpret", 1, 1, "dev /memory 0 to allow-reclaim");
2145 } else
Paul Mackerrasa575b802005-10-23 17:23:21 +10002146 return;
Anton Blanchard5827d412012-11-26 17:40:03 +00002147 prom.memory = call_prom("open", 1, 1, ADDR("/memory"));
2148 prom_getprop(prom.chosen, "mmu", &prom.mmumap,
2149 sizeof(prom.mmumap));
Benjamin Herrenschmidt493adff2013-08-07 02:01:38 +10002150 prom.mmumap = be32_to_cpu(prom.mmumap);
Anton Blanchard5827d412012-11-26 17:40:03 +00002151 if (!IHANDLE_VALID(prom.memory) || !IHANDLE_VALID(prom.mmumap))
Paul Mackerrasa23414b2005-11-10 12:00:55 +11002152 of_workarounds &= ~OF_WA_CLAIM; /* hmmm */
Paul Mackerrasa575b802005-10-23 17:23:21 +10002153}
2154#else
2155#define prom_find_mmu()
2156#endif
2157
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002158static void __init prom_init_stdout(void)
2159{
Anton Blanchard5827d412012-11-26 17:40:03 +00002160 char *path = of_stdout_device;
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002161 char type[16];
Benjamin Herrenschmidt493adff2013-08-07 02:01:38 +10002162 phandle stdout_node;
2163 __be32 val;
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002164
Anton Blanchard5827d412012-11-26 17:40:03 +00002165 if (prom_getprop(prom.chosen, "stdout", &val, sizeof(val)) <= 0)
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002166 prom_panic("cannot find stdout");
2167
Benjamin Herrenschmidt493adff2013-08-07 02:01:38 +10002168 prom.stdout = be32_to_cpu(val);
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002169
2170 /* Get the full OF pathname of the stdout device */
2171 memset(path, 0, 256);
Anton Blanchard5827d412012-11-26 17:40:03 +00002172 call_prom("instance-to-path", 3, 1, prom.stdout, path, 255);
Anton Blanchard5827d412012-11-26 17:40:03 +00002173 prom_printf("OF stdout device is: %s\n", of_stdout_device);
2174 prom_setprop(prom.chosen, "/chosen", "linux,stdout-path",
Christophe Leroy450e7dd2019-04-26 16:23:28 +00002175 path, prom_strlen(path) + 1);
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002176
Benjamin Herrenschmidt10348f52014-01-13 09:49:17 +11002177 /* instance-to-package fails on PA-Semi */
2178 stdout_node = call_prom("instance-to-package", 1, 1, prom.stdout);
2179 if (stdout_node != PROM_ERROR) {
2180 val = cpu_to_be32(stdout_node);
Benjamin Herrenschmidt10348f52014-01-13 09:49:17 +11002181
2182 /* If it's a display, note it */
2183 memset(type, 0, sizeof(type));
2184 prom_getprop(stdout_node, "device_type", type, sizeof(type));
Christophe Leroy450e7dd2019-04-26 16:23:28 +00002185 if (prom_strcmp(type, "display") == 0)
Benjamin Herrenschmidt10348f52014-01-13 09:49:17 +11002186 prom_setprop(stdout_node, path, "linux,boot-display", NULL, 0);
2187 }
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002188}
2189
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002190static int __init prom_find_machine_type(void)
2191{
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002192 char compat[256];
2193 int len, i = 0;
Benjamin Herrenschmidt21fe3302005-11-07 16:41:59 +11002194#ifdef CONFIG_PPC64
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002195 phandle rtas;
Benjamin Herrenschmidte8222502006-03-28 23:15:54 +11002196 int x;
Benjamin Herrenschmidt21fe3302005-11-07 16:41:59 +11002197#endif
Benjamin Herrenschmidte8222502006-03-28 23:15:54 +11002198
Benjamin Herrenschmidt6e35d5d2011-09-19 18:28:01 +00002199 /* Look for a PowerMac or a Cell */
Anton Blanchard5827d412012-11-26 17:40:03 +00002200 len = prom_getprop(prom.root, "compatible",
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002201 compat, sizeof(compat)-1);
2202 if (len > 0) {
2203 compat[len] = 0;
2204 while (i < len) {
2205 char *p = &compat[i];
Christophe Leroy450e7dd2019-04-26 16:23:28 +00002206 int sl = prom_strlen(p);
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002207 if (sl == 0)
2208 break;
Christophe Leroy450e7dd2019-04-26 16:23:28 +00002209 if (prom_strstr(p, "Power Macintosh") ||
2210 prom_strstr(p, "MacRISC"))
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002211 return PLATFORM_POWERMAC;
Arnd Bergmann133dda12006-06-07 12:04:18 +10002212#ifdef CONFIG_PPC64
2213 /* We must make sure we don't detect the IBM Cell
2214 * blades as pSeries due to some firmware issues,
2215 * so we do it here.
2216 */
Christophe Leroy450e7dd2019-04-26 16:23:28 +00002217 if (prom_strstr(p, "IBM,CBEA") ||
2218 prom_strstr(p, "IBM,CPBW-1.0"))
Arnd Bergmann133dda12006-06-07 12:04:18 +10002219 return PLATFORM_GENERIC;
2220#endif /* CONFIG_PPC64 */
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002221 i += sl + 1;
2222 }
2223 }
2224#ifdef CONFIG_PPC64
Benjamin Herrenschmidt6e35d5d2011-09-19 18:28:01 +00002225 /* Try to figure out if it's an IBM pSeries or any other
Benjamin Herrenschmidte8222502006-03-28 23:15:54 +11002226 * PAPR compliant platform. We assume it is if :
2227 * - /device_type is "chrp" (please, do NOT use that for future
2228 * non-IBM designs !
2229 * - it has /rtas
2230 */
Anton Blanchard5827d412012-11-26 17:40:03 +00002231 len = prom_getprop(prom.root, "device_type",
Benjamin Herrenschmidte8222502006-03-28 23:15:54 +11002232 compat, sizeof(compat)-1);
2233 if (len <= 0)
2234 return PLATFORM_GENERIC;
Christophe Leroy450e7dd2019-04-26 16:23:28 +00002235 if (prom_strcmp(compat, "chrp"))
Benjamin Herrenschmidte8222502006-03-28 23:15:54 +11002236 return PLATFORM_GENERIC;
2237
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002238 /* Default to pSeries. We need to know if we are running LPAR */
2239 rtas = call_prom("finddevice", 1, 1, ADDR("/rtas"));
Benjamin Herrenschmidte8222502006-03-28 23:15:54 +11002240 if (!PHANDLE_VALID(rtas))
2241 return PLATFORM_GENERIC;
2242 x = prom_getproplen(rtas, "ibm,hypertas-functions");
2243 if (x != PROM_ERROR) {
Anton Blanchard4da727a2009-03-31 20:06:14 +00002244 prom_debug("Hypertas detected, assuming LPAR !\n");
Benjamin Herrenschmidte8222502006-03-28 23:15:54 +11002245 return PLATFORM_PSERIES_LPAR;
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002246 }
2247 return PLATFORM_PSERIES;
2248#else
Benjamin Herrenschmidte8222502006-03-28 23:15:54 +11002249 return PLATFORM_GENERIC;
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002250#endif
2251}
2252
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002253static int __init prom_set_color(ihandle ih, int i, int r, int g, int b)
2254{
2255 return call_prom("call-method", 6, 1, ADDR("color!"), ih, i, b, g, r);
2256}
2257
2258/*
2259 * If we have a display that we don't know how to drive,
2260 * we will want to try to execute OF's open method for it
2261 * later. However, OF will probably fall over if we do that
2262 * we've taken over the MMU.
2263 * So we check whether we will need to open the display,
2264 * and if so, open it now.
2265 */
2266static void __init prom_check_displays(void)
2267{
2268 char type[16], *path;
2269 phandle node;
2270 ihandle ih;
2271 int i;
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002272
Benjamin Herrenschmidtd00e34b2018-10-15 13:49:56 +11002273 static const unsigned char default_colors[] __initconst = {
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002274 0x00, 0x00, 0x00,
2275 0x00, 0x00, 0xaa,
2276 0x00, 0xaa, 0x00,
2277 0x00, 0xaa, 0xaa,
2278 0xaa, 0x00, 0x00,
2279 0xaa, 0x00, 0xaa,
2280 0xaa, 0xaa, 0x00,
2281 0xaa, 0xaa, 0xaa,
2282 0x55, 0x55, 0x55,
2283 0x55, 0x55, 0xff,
2284 0x55, 0xff, 0x55,
2285 0x55, 0xff, 0xff,
2286 0xff, 0x55, 0x55,
2287 0xff, 0x55, 0xff,
2288 0xff, 0xff, 0x55,
2289 0xff, 0xff, 0xff
2290 };
2291 const unsigned char *clut;
2292
Anton Blanchard4da727a2009-03-31 20:06:14 +00002293 prom_debug("Looking for displays\n");
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002294 for (node = 0; prom_next_node(&node); ) {
2295 memset(type, 0, sizeof(type));
2296 prom_getprop(node, "device_type", type, sizeof(type));
Christophe Leroy450e7dd2019-04-26 16:23:28 +00002297 if (prom_strcmp(type, "display") != 0)
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002298 continue;
2299
2300 /* It seems OF doesn't null-terminate the path :-( */
Anton Blanchard5827d412012-11-26 17:40:03 +00002301 path = prom_scratch;
Christophe Leroyd7fbe2a2019-04-02 09:08:38 +00002302 memset(path, 0, sizeof(prom_scratch));
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002303
2304 /*
2305 * leave some room at the end of the path for appending extra
2306 * arguments
2307 */
2308 if (call_prom("package-to-path", 3, 1, node, path,
Christophe Leroyd7fbe2a2019-04-02 09:08:38 +00002309 sizeof(prom_scratch) - 10) == PROM_ERROR)
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002310 continue;
Anton Blanchard1f8737a2009-03-31 20:06:15 +00002311 prom_printf("found display : %s, opening... ", path);
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002312
2313 ih = call_prom("open", 1, 1, path);
2314 if (ih == 0) {
2315 prom_printf("failed\n");
2316 continue;
2317 }
2318
2319 /* Success */
2320 prom_printf("done\n");
Paul Mackerrasa23414b2005-11-10 12:00:55 +11002321 prom_setprop(node, path, "linux,opened", NULL, 0);
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002322
2323 /* Setup a usable color table when the appropriate
2324 * method is available. Should update this to set-colors */
Anton Blanchard5827d412012-11-26 17:40:03 +00002325 clut = default_colors;
Benjamin Herrenschmidt3f536382011-12-14 13:55:11 +00002326 for (i = 0; i < 16; i++, clut += 3)
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002327 if (prom_set_color(ih, i, clut[0], clut[1],
2328 clut[2]) != 0)
2329 break;
2330
2331#ifdef CONFIG_LOGO_LINUX_CLUT224
Anton Blanchard5827d412012-11-26 17:40:03 +00002332 clut = PTRRELOC(logo_linux_clut224.clut);
2333 for (i = 0; i < logo_linux_clut224.clutsize; i++, clut += 3)
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002334 if (prom_set_color(ih, i + 32, clut[0], clut[1],
2335 clut[2]) != 0)
2336 break;
2337#endif /* CONFIG_LOGO_LINUX_CLUT224 */
Benjamin Herrenschmidt7191b612013-07-25 12:12:32 +10002338
2339#ifdef CONFIG_PPC_EARLY_DEBUG_BOOTX
2340 if (prom_getprop(node, "linux,boot-display", NULL, 0) !=
2341 PROM_ERROR) {
2342 u32 width, height, pitch, addr;
2343
2344 prom_printf("Setting btext !\n");
2345 prom_getprop(node, "width", &width, 4);
2346 prom_getprop(node, "height", &height, 4);
2347 prom_getprop(node, "linebytes", &pitch, 4);
2348 prom_getprop(node, "address", &addr, 4);
2349 prom_printf("W=%d H=%d LB=%d addr=0x%x\n",
2350 width, height, pitch, addr);
2351 btext_setup_display(width, height, 8, pitch, addr);
2352 }
2353#endif /* CONFIG_PPC_EARLY_DEBUG_BOOTX */
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002354 }
2355}
2356
2357
2358/* Return (relocated) pointer to this much memory: moves initrd if reqd. */
2359static void __init *make_room(unsigned long *mem_start, unsigned long *mem_end,
2360 unsigned long needed, unsigned long align)
2361{
2362 void *ret;
2363
2364 *mem_start = _ALIGN(*mem_start, align);
2365 while ((*mem_start + needed) > *mem_end) {
2366 unsigned long room, chunk;
2367
Mathieu Malaterreeae5f702018-04-06 22:12:19 +02002368 prom_debug("Chunk exhausted, claiming more at %lx...\n",
Anton Blanchard5827d412012-11-26 17:40:03 +00002369 alloc_bottom);
2370 room = alloc_top - alloc_bottom;
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002371 if (room > DEVTREE_CHUNK_SIZE)
2372 room = DEVTREE_CHUNK_SIZE;
2373 if (room < PAGE_SIZE)
Anton Blanchardfbafd722011-07-25 20:47:51 +00002374 prom_panic("No memory for flatten_device_tree "
2375 "(no room)\n");
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002376 chunk = alloc_up(room, 0);
2377 if (chunk == 0)
Anton Blanchardfbafd722011-07-25 20:47:51 +00002378 prom_panic("No memory for flatten_device_tree "
2379 "(claim failed)\n");
Anton Blanchard966728d2011-07-25 20:47:07 +00002380 *mem_end = chunk + room;
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002381 }
2382
2383 ret = (void *)*mem_start;
2384 *mem_start += needed;
2385
2386 return ret;
2387}
2388
Benjamin Herrenschmidt493adff2013-08-07 02:01:38 +10002389#define dt_push_token(token, mem_start, mem_end) do { \
2390 void *room = make_room(mem_start, mem_end, 4, 4); \
2391 *(__be32 *)room = cpu_to_be32(token); \
2392 } while(0)
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002393
2394static unsigned long __init dt_find_string(char *str)
2395{
2396 char *s, *os;
2397
Anton Blanchard5827d412012-11-26 17:40:03 +00002398 s = os = (char *)dt_string_start;
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002399 s += 4;
Anton Blanchard5827d412012-11-26 17:40:03 +00002400 while (s < (char *)dt_string_end) {
Christophe Leroy450e7dd2019-04-26 16:23:28 +00002401 if (prom_strcmp(s, str) == 0)
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002402 return s - os;
Christophe Leroy450e7dd2019-04-26 16:23:28 +00002403 s += prom_strlen(s) + 1;
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002404 }
2405 return 0;
2406}
2407
2408/*
2409 * The Open Firmware 1275 specification states properties must be 31 bytes or
2410 * less, however not all firmwares obey this. Make it 64 bytes to be safe.
2411 */
2412#define MAX_PROPERTY_NAME 64
2413
2414static void __init scan_dt_build_strings(phandle node,
2415 unsigned long *mem_start,
2416 unsigned long *mem_end)
2417{
2418 char *prev_name, *namep, *sstart;
2419 unsigned long soff;
2420 phandle child;
2421
Anton Blanchard5827d412012-11-26 17:40:03 +00002422 sstart = (char *)dt_string_start;
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002423
2424 /* get and store all property names */
Anton Blanchard5827d412012-11-26 17:40:03 +00002425 prev_name = "";
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002426 for (;;) {
2427 /* 64 is max len of name including nul. */
2428 namep = make_room(mem_start, mem_end, MAX_PROPERTY_NAME, 1);
2429 if (call_prom("nextprop", 3, 1, node, prev_name, namep) != 1) {
2430 /* No more nodes: unwind alloc */
2431 *mem_start = (unsigned long)namep;
2432 break;
2433 }
2434
2435 /* skip "name" */
Christophe Leroy450e7dd2019-04-26 16:23:28 +00002436 if (prom_strcmp(namep, "name") == 0) {
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002437 *mem_start = (unsigned long)namep;
Anton Blanchard5827d412012-11-26 17:40:03 +00002438 prev_name = "name";
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002439 continue;
2440 }
2441 /* get/create string entry */
2442 soff = dt_find_string(namep);
2443 if (soff != 0) {
2444 *mem_start = (unsigned long)namep;
2445 namep = sstart + soff;
2446 } else {
2447 /* Trim off some if we can */
Christophe Leroy450e7dd2019-04-26 16:23:28 +00002448 *mem_start = (unsigned long)namep + prom_strlen(namep) + 1;
Anton Blanchard5827d412012-11-26 17:40:03 +00002449 dt_string_end = *mem_start;
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002450 }
2451 prev_name = namep;
2452 }
2453
2454 /* do all our children */
2455 child = call_prom("child", 1, 1, node);
2456 while (child != 0) {
2457 scan_dt_build_strings(child, mem_start, mem_end);
2458 child = call_prom("peer", 1, 1, child);
2459 }
2460}
2461
2462static void __init scan_dt_build_struct(phandle node, unsigned long *mem_start,
2463 unsigned long *mem_end)
2464{
2465 phandle child;
2466 char *namep, *prev_name, *sstart, *p, *ep, *lp, *path;
2467 unsigned long soff;
2468 unsigned char *valp;
Benjamin Herrenschmidt8ca2d512018-10-15 13:49:57 +11002469 static char pname[MAX_PROPERTY_NAME] __prombss;
Benjamin Herrenschmidt6e35d5d2011-09-19 18:28:01 +00002470 int l, room, has_phandle = 0;
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002471
2472 dt_push_token(OF_DT_BEGIN_NODE, mem_start, mem_end);
2473
2474 /* get the node's full name */
2475 namep = (char *)*mem_start;
Paul Mackerrasc49888202005-10-26 21:52:53 +10002476 room = *mem_end - *mem_start;
2477 if (room > 255)
2478 room = 255;
2479 l = call_prom("package-to-path", 3, 1, node, namep, room);
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002480 if (l >= 0) {
2481 /* Didn't fit? Get more room. */
Paul Mackerrasc49888202005-10-26 21:52:53 +10002482 if (l >= room) {
2483 if (l >= *mem_end - *mem_start)
2484 namep = make_room(mem_start, mem_end, l+1, 1);
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002485 call_prom("package-to-path", 3, 1, node, namep, l);
2486 }
2487 namep[l] = '\0';
2488
2489 /* Fixup an Apple bug where they have bogus \0 chars in the
Paul Mackerrasa575b802005-10-23 17:23:21 +10002490 * middle of the path in some properties, and extract
2491 * the unit name (everything after the last '/').
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002492 */
Paul Mackerrasa575b802005-10-23 17:23:21 +10002493 for (lp = p = namep, ep = namep + l; p < ep; p++) {
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002494 if (*p == '/')
Paul Mackerrasa575b802005-10-23 17:23:21 +10002495 lp = namep;
2496 else if (*p != 0)
2497 *lp++ = *p;
2498 }
2499 *lp = 0;
2500 *mem_start = _ALIGN((unsigned long)lp + 1, 4);
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002501 }
2502
2503 /* get it again for debugging */
Anton Blanchard5827d412012-11-26 17:40:03 +00002504 path = prom_scratch;
Christophe Leroyd7fbe2a2019-04-02 09:08:38 +00002505 memset(path, 0, sizeof(prom_scratch));
2506 call_prom("package-to-path", 3, 1, node, path, sizeof(prom_scratch) - 1);
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002507
2508 /* get and store all properties */
Anton Blanchard5827d412012-11-26 17:40:03 +00002509 prev_name = "";
2510 sstart = (char *)dt_string_start;
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002511 for (;;) {
2512 if (call_prom("nextprop", 3, 1, node, prev_name,
Anton Blanchard5827d412012-11-26 17:40:03 +00002513 pname) != 1)
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002514 break;
2515
2516 /* skip "name" */
Christophe Leroy450e7dd2019-04-26 16:23:28 +00002517 if (prom_strcmp(pname, "name") == 0) {
Anton Blanchard5827d412012-11-26 17:40:03 +00002518 prev_name = "name";
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002519 continue;
2520 }
2521
2522 /* find string offset */
Anton Blanchard5827d412012-11-26 17:40:03 +00002523 soff = dt_find_string(pname);
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002524 if (soff == 0) {
2525 prom_printf("WARNING: Can't find string index for"
Anton Blanchard5827d412012-11-26 17:40:03 +00002526 " <%s>, node %s\n", pname, path);
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002527 break;
2528 }
2529 prev_name = sstart + soff;
2530
2531 /* get length */
Anton Blanchard5827d412012-11-26 17:40:03 +00002532 l = call_prom("getproplen", 2, 1, node, pname);
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002533
2534 /* sanity checks */
2535 if (l == PROM_ERROR)
2536 continue;
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002537
2538 /* push property head */
2539 dt_push_token(OF_DT_PROP, mem_start, mem_end);
2540 dt_push_token(l, mem_start, mem_end);
2541 dt_push_token(soff, mem_start, mem_end);
2542
2543 /* push property content */
2544 valp = make_room(mem_start, mem_end, l, 4);
Anton Blanchard5827d412012-11-26 17:40:03 +00002545 call_prom("getprop", 4, 1, node, pname, valp, l);
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002546 *mem_start = _ALIGN(*mem_start, 4);
Benjamin Herrenschmidt6e35d5d2011-09-19 18:28:01 +00002547
Christophe Leroy450e7dd2019-04-26 16:23:28 +00002548 if (!prom_strcmp(pname, "phandle"))
Benjamin Herrenschmidt6e35d5d2011-09-19 18:28:01 +00002549 has_phandle = 1;
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002550 }
2551
Benjamin Herrenschmidtf1f208e2018-10-15 13:50:00 +11002552 /* Add a "phandle" property if none already exist */
Benjamin Herrenschmidt6e35d5d2011-09-19 18:28:01 +00002553 if (!has_phandle) {
Benjamin Herrenschmidtf1f208e2018-10-15 13:50:00 +11002554 soff = dt_find_string("phandle");
Benjamin Herrenschmidt6e35d5d2011-09-19 18:28:01 +00002555 if (soff == 0)
Benjamin Herrenschmidtf1f208e2018-10-15 13:50:00 +11002556 prom_printf("WARNING: Can't find string index for <phandle> node %s\n", path);
Benjamin Herrenschmidt6e35d5d2011-09-19 18:28:01 +00002557 else {
2558 dt_push_token(OF_DT_PROP, mem_start, mem_end);
2559 dt_push_token(4, mem_start, mem_end);
2560 dt_push_token(soff, mem_start, mem_end);
2561 valp = make_room(mem_start, mem_end, 4, 4);
Benjamin Herrenschmidt493adff2013-08-07 02:01:38 +10002562 *(__be32 *)valp = cpu_to_be32(node);
Benjamin Herrenschmidt6e35d5d2011-09-19 18:28:01 +00002563 }
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002564 }
2565
2566 /* do all our children */
2567 child = call_prom("child", 1, 1, node);
2568 while (child != 0) {
2569 scan_dt_build_struct(child, mem_start, mem_end);
2570 child = call_prom("peer", 1, 1, child);
2571 }
2572
2573 dt_push_token(OF_DT_END_NODE, mem_start, mem_end);
2574}
2575
2576static void __init flatten_device_tree(void)
2577{
2578 phandle root;
2579 unsigned long mem_start, mem_end, room;
2580 struct boot_param_header *hdr;
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002581 char *namep;
2582 u64 *rsvmap;
2583
2584 /*
2585 * Check how much room we have between alloc top & bottom (+/- a
Anton Blanchardfbafd722011-07-25 20:47:51 +00002586 * few pages), crop to 1MB, as this is our "chunk" size
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002587 */
Anton Blanchard5827d412012-11-26 17:40:03 +00002588 room = alloc_top - alloc_bottom - 0x4000;
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002589 if (room > DEVTREE_CHUNK_SIZE)
2590 room = DEVTREE_CHUNK_SIZE;
Mathieu Malaterreeae5f702018-04-06 22:12:19 +02002591 prom_debug("starting device tree allocs at %lx\n", alloc_bottom);
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002592
2593 /* Now try to claim that */
2594 mem_start = (unsigned long)alloc_up(room, PAGE_SIZE);
2595 if (mem_start == 0)
2596 prom_panic("Can't allocate initial device-tree chunk\n");
Anton Blanchard966728d2011-07-25 20:47:07 +00002597 mem_end = mem_start + room;
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002598
2599 /* Get root of tree */
2600 root = call_prom("peer", 1, 1, (phandle)0);
2601 if (root == (phandle)0)
2602 prom_panic ("couldn't get device tree root\n");
2603
2604 /* Build header and make room for mem rsv map */
2605 mem_start = _ALIGN(mem_start, 4);
2606 hdr = make_room(&mem_start, &mem_end,
2607 sizeof(struct boot_param_header), 4);
Anton Blanchard5827d412012-11-26 17:40:03 +00002608 dt_header_start = (unsigned long)hdr;
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002609 rsvmap = make_room(&mem_start, &mem_end, sizeof(mem_reserve_map), 8);
2610
2611 /* Start of strings */
2612 mem_start = PAGE_ALIGN(mem_start);
Anton Blanchard5827d412012-11-26 17:40:03 +00002613 dt_string_start = mem_start;
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002614 mem_start += 4; /* hole */
2615
Benjamin Herrenschmidtf1f208e2018-10-15 13:50:00 +11002616 /* Add "phandle" in there, we'll need it */
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002617 namep = make_room(&mem_start, &mem_end, 16, 1);
Christophe Leroy450e7dd2019-04-26 16:23:28 +00002618 prom_strcpy(namep, "phandle");
2619 mem_start = (unsigned long)namep + prom_strlen(namep) + 1;
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002620
2621 /* Build string array */
2622 prom_printf("Building dt strings...\n");
2623 scan_dt_build_strings(root, &mem_start, &mem_end);
Anton Blanchard5827d412012-11-26 17:40:03 +00002624 dt_string_end = mem_start;
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002625
2626 /* Build structure */
2627 mem_start = PAGE_ALIGN(mem_start);
Anton Blanchard5827d412012-11-26 17:40:03 +00002628 dt_struct_start = mem_start;
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002629 prom_printf("Building dt structure...\n");
2630 scan_dt_build_struct(root, &mem_start, &mem_end);
2631 dt_push_token(OF_DT_END, &mem_start, &mem_end);
Anton Blanchard5827d412012-11-26 17:40:03 +00002632 dt_struct_end = PAGE_ALIGN(mem_start);
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002633
2634 /* Finish header */
Benjamin Herrenschmidt493adff2013-08-07 02:01:38 +10002635 hdr->boot_cpuid_phys = cpu_to_be32(prom.cpu);
2636 hdr->magic = cpu_to_be32(OF_DT_HEADER);
2637 hdr->totalsize = cpu_to_be32(dt_struct_end - dt_header_start);
2638 hdr->off_dt_struct = cpu_to_be32(dt_struct_start - dt_header_start);
2639 hdr->off_dt_strings = cpu_to_be32(dt_string_start - dt_header_start);
2640 hdr->dt_strings_size = cpu_to_be32(dt_string_end - dt_string_start);
2641 hdr->off_mem_rsvmap = cpu_to_be32(((unsigned long)rsvmap) - dt_header_start);
2642 hdr->version = cpu_to_be32(OF_DT_VERSION);
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002643 /* Version 16 is not backward compatible */
Benjamin Herrenschmidt493adff2013-08-07 02:01:38 +10002644 hdr->last_comp_version = cpu_to_be32(0x10);
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002645
Jimi Xenidis4d1f3f22006-05-18 17:03:05 -05002646 /* Copy the reserve map in */
Anton Blanchard5827d412012-11-26 17:40:03 +00002647 memcpy(rsvmap, mem_reserve_map, sizeof(mem_reserve_map));
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002648
2649#ifdef DEBUG_PROM
2650 {
2651 int i;
2652 prom_printf("reserved memory map:\n");
Anton Blanchard5827d412012-11-26 17:40:03 +00002653 for (i = 0; i < mem_reserve_cnt; i++)
Mathieu Malaterreeae5f702018-04-06 22:12:19 +02002654 prom_printf(" %llx - %llx\n",
Benjamin Herrenschmidt493adff2013-08-07 02:01:38 +10002655 be64_to_cpu(mem_reserve_map[i].base),
2656 be64_to_cpu(mem_reserve_map[i].size));
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002657 }
2658#endif
Jimi Xenidis4d1f3f22006-05-18 17:03:05 -05002659 /* Bump mem_reserve_cnt to cause further reservations to fail
2660 * since it's too late.
2661 */
Anton Blanchard5827d412012-11-26 17:40:03 +00002662 mem_reserve_cnt = MEM_RESERVE_MAP_SIZE;
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002663
Mathieu Malaterreeae5f702018-04-06 22:12:19 +02002664 prom_printf("Device tree strings 0x%lx -> 0x%lx\n",
Anton Blanchard5827d412012-11-26 17:40:03 +00002665 dt_string_start, dt_string_end);
Mathieu Malaterreeae5f702018-04-06 22:12:19 +02002666 prom_printf("Device tree struct 0x%lx -> 0x%lx\n",
Anton Blanchard5827d412012-11-26 17:40:03 +00002667 dt_struct_start, dt_struct_end);
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002668}
2669
Hollis Blanchard54f4ee12006-05-25 16:36:53 -05002670#ifdef CONFIG_PPC_MAPLE
2671/* PIBS Version 1.05.0000 04/26/2005 has an incorrect /ht/isa/ranges property.
2672 * The values are bad, and it doesn't even have the right number of cells. */
2673static void __init fixup_device_tree_maple(void)
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002674{
Hollis Blanchard54f4ee12006-05-25 16:36:53 -05002675 phandle isa;
Benjamin Herrenschmidt980a6512006-07-03 17:22:05 +10002676 u32 rloc = 0x01002000; /* IO space; PCI device = 4 */
Hollis Blanchard54f4ee12006-05-25 16:36:53 -05002677 u32 isa_ranges[6];
Benjamin Herrenschmidt980a6512006-07-03 17:22:05 +10002678 char *name;
Hollis Blanchard54f4ee12006-05-25 16:36:53 -05002679
Benjamin Herrenschmidt980a6512006-07-03 17:22:05 +10002680 name = "/ht@0/isa@4";
2681 isa = call_prom("finddevice", 1, 1, ADDR(name));
2682 if (!PHANDLE_VALID(isa)) {
2683 name = "/ht@0/isa@6";
2684 isa = call_prom("finddevice", 1, 1, ADDR(name));
2685 rloc = 0x01003000; /* IO space; PCI device = 6 */
2686 }
Hollis Blanchard54f4ee12006-05-25 16:36:53 -05002687 if (!PHANDLE_VALID(isa))
2688 return;
2689
Benjamin Herrenschmidt980a6512006-07-03 17:22:05 +10002690 if (prom_getproplen(isa, "ranges") != 12)
2691 return;
Hollis Blanchard54f4ee12006-05-25 16:36:53 -05002692 if (prom_getprop(isa, "ranges", isa_ranges, sizeof(isa_ranges))
2693 == PROM_ERROR)
2694 return;
2695
2696 if (isa_ranges[0] != 0x1 ||
2697 isa_ranges[1] != 0xf4000000 ||
2698 isa_ranges[2] != 0x00010000)
2699 return;
2700
Benjamin Herrenschmidt980a6512006-07-03 17:22:05 +10002701 prom_printf("Fixing up bogus ISA range on Maple/Apache...\n");
Hollis Blanchard54f4ee12006-05-25 16:36:53 -05002702
2703 isa_ranges[0] = 0x1;
2704 isa_ranges[1] = 0x0;
Benjamin Herrenschmidt980a6512006-07-03 17:22:05 +10002705 isa_ranges[2] = rloc;
Hollis Blanchard54f4ee12006-05-25 16:36:53 -05002706 isa_ranges[3] = 0x0;
2707 isa_ranges[4] = 0x0;
2708 isa_ranges[5] = 0x00010000;
Benjamin Herrenschmidt980a6512006-07-03 17:22:05 +10002709 prom_setprop(isa, name, "ranges",
Hollis Blanchard54f4ee12006-05-25 16:36:53 -05002710 isa_ranges, sizeof(isa_ranges));
2711}
Harry Ciao8f101a052009-06-17 16:28:00 -07002712
2713#define CPC925_MC_START 0xf8000000
2714#define CPC925_MC_LENGTH 0x1000000
2715/* The values for memory-controller don't have right number of cells */
2716static void __init fixup_device_tree_maple_memory_controller(void)
2717{
2718 phandle mc;
2719 u32 mc_reg[4];
2720 char *name = "/hostbridge@f8000000";
Harry Ciao8f101a052009-06-17 16:28:00 -07002721 u32 ac, sc;
2722
2723 mc = call_prom("finddevice", 1, 1, ADDR(name));
2724 if (!PHANDLE_VALID(mc))
2725 return;
2726
2727 if (prom_getproplen(mc, "reg") != 8)
2728 return;
2729
Anton Blanchard5827d412012-11-26 17:40:03 +00002730 prom_getprop(prom.root, "#address-cells", &ac, sizeof(ac));
2731 prom_getprop(prom.root, "#size-cells", &sc, sizeof(sc));
Harry Ciao8f101a052009-06-17 16:28:00 -07002732 if ((ac != 2) || (sc != 2))
2733 return;
2734
2735 if (prom_getprop(mc, "reg", mc_reg, sizeof(mc_reg)) == PROM_ERROR)
2736 return;
2737
2738 if (mc_reg[0] != CPC925_MC_START || mc_reg[1] != CPC925_MC_LENGTH)
2739 return;
2740
2741 prom_printf("Fixing up bogus hostbridge on Maple...\n");
2742
2743 mc_reg[0] = 0x0;
2744 mc_reg[1] = CPC925_MC_START;
2745 mc_reg[2] = 0x0;
2746 mc_reg[3] = CPC925_MC_LENGTH;
2747 prom_setprop(mc, name, "reg", mc_reg, sizeof(mc_reg));
2748}
Hollis Blanchard54f4ee12006-05-25 16:36:53 -05002749#else
2750#define fixup_device_tree_maple()
Harry Ciao8f101a052009-06-17 16:28:00 -07002751#define fixup_device_tree_maple_memory_controller()
Hollis Blanchard54f4ee12006-05-25 16:36:53 -05002752#endif
2753
Benjamin Herrenschmidte8c0acf2006-07-04 14:06:29 +10002754#ifdef CONFIG_PPC_CHRP
Olaf Heringe4805922007-04-04 18:20:04 +02002755/*
2756 * Pegasos and BriQ lacks the "ranges" property in the isa node
2757 * Pegasos needs decimal IRQ 14/15, not hexadecimal
Olaf Hering556ecf92007-08-18 04:27:17 +10002758 * Pegasos has the IDE configured in legacy mode, but advertised as native
Olaf Heringe4805922007-04-04 18:20:04 +02002759 */
Benjamin Herrenschmidte8c0acf2006-07-04 14:06:29 +10002760static void __init fixup_device_tree_chrp(void)
2761{
Olaf Heringe4805922007-04-04 18:20:04 +02002762 phandle ph;
2763 u32 prop[6];
Benjamin Herrenschmidt26c50322006-07-04 14:16:28 +10002764 u32 rloc = 0x01006000; /* IO space; PCI device = 12 */
Benjamin Herrenschmidte8c0acf2006-07-04 14:06:29 +10002765 char *name;
2766 int rc;
2767
2768 name = "/pci@80000000/isa@c";
Olaf Heringe4805922007-04-04 18:20:04 +02002769 ph = call_prom("finddevice", 1, 1, ADDR(name));
2770 if (!PHANDLE_VALID(ph)) {
Benjamin Herrenschmidt26c50322006-07-04 14:16:28 +10002771 name = "/pci@ff500000/isa@6";
Olaf Heringe4805922007-04-04 18:20:04 +02002772 ph = call_prom("finddevice", 1, 1, ADDR(name));
Benjamin Herrenschmidt26c50322006-07-04 14:16:28 +10002773 rloc = 0x01003000; /* IO space; PCI device = 6 */
2774 }
Olaf Heringe4805922007-04-04 18:20:04 +02002775 if (PHANDLE_VALID(ph)) {
2776 rc = prom_getproplen(ph, "ranges");
2777 if (rc == 0 || rc == PROM_ERROR) {
2778 prom_printf("Fixing up missing ISA range on Pegasos...\n");
Benjamin Herrenschmidte8c0acf2006-07-04 14:06:29 +10002779
Olaf Heringe4805922007-04-04 18:20:04 +02002780 prop[0] = 0x1;
2781 prop[1] = 0x0;
2782 prop[2] = rloc;
2783 prop[3] = 0x0;
2784 prop[4] = 0x0;
2785 prop[5] = 0x00010000;
2786 prom_setprop(ph, name, "ranges", prop, sizeof(prop));
2787 }
2788 }
Benjamin Herrenschmidte8c0acf2006-07-04 14:06:29 +10002789
Olaf Heringe4805922007-04-04 18:20:04 +02002790 name = "/pci@80000000/ide@C,1";
2791 ph = call_prom("finddevice", 1, 1, ADDR(name));
2792 if (PHANDLE_VALID(ph)) {
2793 prom_printf("Fixing up IDE interrupt on Pegasos...\n");
2794 prop[0] = 14;
2795 prop[1] = 0x0;
Olaf Hering556ecf92007-08-18 04:27:17 +10002796 prom_setprop(ph, name, "interrupts", prop, 2*sizeof(u32));
2797 prom_printf("Fixing up IDE class-code on Pegasos...\n");
2798 rc = prom_getprop(ph, "class-code", prop, sizeof(u32));
2799 if (rc == sizeof(u32)) {
2800 prop[0] &= ~0x5;
2801 prom_setprop(ph, name, "class-code", prop, sizeof(u32));
2802 }
Olaf Heringe4805922007-04-04 18:20:04 +02002803 }
Benjamin Herrenschmidte8c0acf2006-07-04 14:06:29 +10002804}
2805#else
2806#define fixup_device_tree_chrp()
2807#endif
2808
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002809#if defined(CONFIG_PPC64) && defined(CONFIG_PPC_PMAC)
Hollis Blanchard54f4ee12006-05-25 16:36:53 -05002810static void __init fixup_device_tree_pmac(void)
2811{
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002812 phandle u3, i2c, mpic;
2813 u32 u3_rev;
2814 u32 interrupts[2];
2815 u32 parent;
2816
2817 /* Some G5s have a missing interrupt definition, fix it up here */
2818 u3 = call_prom("finddevice", 1, 1, ADDR("/u3@0,f8000000"));
2819 if (!PHANDLE_VALID(u3))
2820 return;
2821 i2c = call_prom("finddevice", 1, 1, ADDR("/u3@0,f8000000/i2c@f8001000"));
2822 if (!PHANDLE_VALID(i2c))
2823 return;
2824 mpic = call_prom("finddevice", 1, 1, ADDR("/u3@0,f8000000/mpic@f8040000"));
2825 if (!PHANDLE_VALID(mpic))
2826 return;
2827
2828 /* check if proper rev of u3 */
2829 if (prom_getprop(u3, "device-rev", &u3_rev, sizeof(u3_rev))
2830 == PROM_ERROR)
2831 return;
Benjamin Herrenschmidt7d496972005-11-07 14:36:21 +11002832 if (u3_rev < 0x35 || u3_rev > 0x39)
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002833 return;
2834 /* does it need fixup ? */
2835 if (prom_getproplen(i2c, "interrupts") > 0)
2836 return;
2837
2838 prom_printf("fixing up bogus interrupts for u3 i2c...\n");
2839
2840 /* interrupt on this revision of u3 is number 0 and level */
2841 interrupts[0] = 0;
2842 interrupts[1] = 1;
Paul Mackerrasa23414b2005-11-10 12:00:55 +11002843 prom_setprop(i2c, "/u3@0,f8000000/i2c@f8001000", "interrupts",
2844 &interrupts, sizeof(interrupts));
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002845 parent = (u32)mpic;
Paul Mackerrasa23414b2005-11-10 12:00:55 +11002846 prom_setprop(i2c, "/u3@0,f8000000/i2c@f8001000", "interrupt-parent",
2847 &parent, sizeof(parent));
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002848}
Hollis Blanchard54f4ee12006-05-25 16:36:53 -05002849#else
2850#define fixup_device_tree_pmac()
2851#endif
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002852
Sylvain Munaut88fd2a92007-02-12 23:13:20 +01002853#ifdef CONFIG_PPC_EFIKA
Grant Likely94d2dde2008-01-24 22:25:32 -07002854/*
2855 * The MPC5200 FEC driver requires an phy-handle property to tell it how
2856 * to talk to the phy. If the phy-handle property is missing, then this
2857 * function is called to add the appropriate nodes and link it to the
2858 * ethernet node.
2859 */
2860static void __init fixup_device_tree_efika_add_phy(void)
Sylvain Munaut88fd2a92007-02-12 23:13:20 +01002861{
Sylvain Munaut88fd2a92007-02-12 23:13:20 +01002862 u32 node;
2863 char prop[64];
Grant Likely94d2dde2008-01-24 22:25:32 -07002864 int rv;
Sylvain Munaut88fd2a92007-02-12 23:13:20 +01002865
Grant Likely94d2dde2008-01-24 22:25:32 -07002866 /* Check if /builtin/ethernet exists - bail if it doesn't */
2867 node = call_prom("finddevice", 1, 1, ADDR("/builtin/ethernet"));
Sylvain Munaut88fd2a92007-02-12 23:13:20 +01002868 if (!PHANDLE_VALID(node))
2869 return;
2870
Grant Likely94d2dde2008-01-24 22:25:32 -07002871 /* Check if the phy-handle property exists - bail if it does */
2872 rv = prom_getprop(node, "phy-handle", prop, sizeof(prop));
2873 if (!rv)
Sylvain Munaut88fd2a92007-02-12 23:13:20 +01002874 return;
2875
Grant Likely94d2dde2008-01-24 22:25:32 -07002876 /*
2877 * At this point the ethernet device doesn't have a phy described.
2878 * Now we need to add the missing phy node and linkage
2879 */
Sylvain Munaut88fd2a92007-02-12 23:13:20 +01002880
Grant Likely94d2dde2008-01-24 22:25:32 -07002881 /* Check for an MDIO bus node - if missing then create one */
Olaf Hering6f4347c2008-01-10 01:06:08 +11002882 node = call_prom("finddevice", 1, 1, ADDR("/builtin/mdio"));
2883 if (!PHANDLE_VALID(node)) {
2884 prom_printf("Adding Ethernet MDIO node\n");
2885 call_prom("interpret", 1, 1,
2886 " s\" /builtin\" find-device"
2887 " new-device"
2888 " 1 encode-int s\" #address-cells\" property"
2889 " 0 encode-int s\" #size-cells\" property"
Grant Likely94d2dde2008-01-24 22:25:32 -07002890 " s\" mdio\" device-name"
2891 " s\" fsl,mpc5200b-mdio\" encode-string"
Olaf Hering6f4347c2008-01-10 01:06:08 +11002892 " s\" compatible\" property"
2893 " 0xf0003000 0x400 reg"
2894 " 0x2 encode-int"
2895 " 0x5 encode-int encode+"
2896 " 0x3 encode-int encode+"
2897 " s\" interrupts\" property"
2898 " finish-device");
2899 };
2900
Grant Likely94d2dde2008-01-24 22:25:32 -07002901 /* Check for a PHY device node - if missing then create one and
2902 * give it's phandle to the ethernet node */
2903 node = call_prom("finddevice", 1, 1,
2904 ADDR("/builtin/mdio/ethernet-phy"));
Olaf Hering6f4347c2008-01-10 01:06:08 +11002905 if (!PHANDLE_VALID(node)) {
2906 prom_printf("Adding Ethernet PHY node\n");
2907 call_prom("interpret", 1, 1,
2908 " s\" /builtin/mdio\" find-device"
2909 " new-device"
2910 " s\" ethernet-phy\" device-name"
2911 " 0x10 encode-int s\" reg\" property"
2912 " my-self"
2913 " ihandle>phandle"
2914 " finish-device"
2915 " s\" /builtin/ethernet\" find-device"
2916 " encode-int"
2917 " s\" phy-handle\" property"
2918 " device-end");
2919 }
Grant Likely94d2dde2008-01-24 22:25:32 -07002920}
Olaf Hering6f4347c2008-01-10 01:06:08 +11002921
Grant Likely94d2dde2008-01-24 22:25:32 -07002922static void __init fixup_device_tree_efika(void)
2923{
2924 int sound_irq[3] = { 2, 2, 0 };
2925 int bcomm_irq[3*16] = { 3,0,0, 3,1,0, 3,2,0, 3,3,0,
2926 3,4,0, 3,5,0, 3,6,0, 3,7,0,
2927 3,8,0, 3,9,0, 3,10,0, 3,11,0,
2928 3,12,0, 3,13,0, 3,14,0, 3,15,0 };
2929 u32 node;
2930 char prop[64];
2931 int rv, len;
2932
2933 /* Check if we're really running on a EFIKA */
2934 node = call_prom("finddevice", 1, 1, ADDR("/"));
2935 if (!PHANDLE_VALID(node))
2936 return;
2937
2938 rv = prom_getprop(node, "model", prop, sizeof(prop));
2939 if (rv == PROM_ERROR)
2940 return;
Christophe Leroy450e7dd2019-04-26 16:23:28 +00002941 if (prom_strcmp(prop, "EFIKA5K2"))
Grant Likely94d2dde2008-01-24 22:25:32 -07002942 return;
2943
2944 prom_printf("Applying EFIKA device tree fixups\n");
2945
2946 /* Claiming to be 'chrp' is death */
2947 node = call_prom("finddevice", 1, 1, ADDR("/"));
2948 rv = prom_getprop(node, "device_type", prop, sizeof(prop));
Christophe Leroy450e7dd2019-04-26 16:23:28 +00002949 if (rv != PROM_ERROR && (prom_strcmp(prop, "chrp") == 0))
Grant Likely94d2dde2008-01-24 22:25:32 -07002950 prom_setprop(node, "/", "device_type", "efika", sizeof("efika"));
2951
David Woodhouse7f4392c2008-04-14 02:52:38 +10002952 /* CODEGEN,description is exposed in /proc/cpuinfo so
2953 fix that too */
2954 rv = prom_getprop(node, "CODEGEN,description", prop, sizeof(prop));
Christophe Leroy450e7dd2019-04-26 16:23:28 +00002955 if (rv != PROM_ERROR && (prom_strstr(prop, "CHRP")))
David Woodhouse7f4392c2008-04-14 02:52:38 +10002956 prom_setprop(node, "/", "CODEGEN,description",
2957 "Efika 5200B PowerPC System",
2958 sizeof("Efika 5200B PowerPC System"));
2959
Grant Likely94d2dde2008-01-24 22:25:32 -07002960 /* Fixup bestcomm interrupts property */
2961 node = call_prom("finddevice", 1, 1, ADDR("/builtin/bestcomm"));
2962 if (PHANDLE_VALID(node)) {
2963 len = prom_getproplen(node, "interrupts");
2964 if (len == 12) {
2965 prom_printf("Fixing bestcomm interrupts property\n");
2966 prom_setprop(node, "/builtin/bestcom", "interrupts",
2967 bcomm_irq, sizeof(bcomm_irq));
2968 }
2969 }
2970
2971 /* Fixup sound interrupts property */
2972 node = call_prom("finddevice", 1, 1, ADDR("/builtin/sound"));
2973 if (PHANDLE_VALID(node)) {
2974 rv = prom_getprop(node, "interrupts", prop, sizeof(prop));
2975 if (rv == PROM_ERROR) {
2976 prom_printf("Adding sound interrupts property\n");
2977 prom_setprop(node, "/builtin/sound", "interrupts",
2978 sound_irq, sizeof(sound_irq));
2979 }
2980 }
2981
2982 /* Make sure ethernet phy-handle property exists */
2983 fixup_device_tree_efika_add_phy();
Sylvain Munaut88fd2a92007-02-12 23:13:20 +01002984}
2985#else
2986#define fixup_device_tree_efika()
2987#endif
2988
Darren Stevens50246782016-08-31 13:24:40 +01002989#ifdef CONFIG_PPC_PASEMI_NEMO
2990/*
2991 * CFE supplied on Nemo is broken in several ways, biggest
2992 * problem is that it reassigns ISA interrupts to unused mpic ints.
2993 * Add an interrupt-controller property for the io-bridge to use
2994 * and correct the ints so we can attach them to an irq_domain
2995 */
2996static void __init fixup_device_tree_pasemi(void)
2997{
2998 u32 interrupts[2], parent, rval, val = 0;
2999 char *name, *pci_name;
3000 phandle iob, node;
3001
3002 /* Find the root pci node */
3003 name = "/pxp@0,e0000000";
3004 iob = call_prom("finddevice", 1, 1, ADDR(name));
3005 if (!PHANDLE_VALID(iob))
3006 return;
3007
3008 /* check if interrupt-controller node set yet */
3009 if (prom_getproplen(iob, "interrupt-controller") !=PROM_ERROR)
3010 return;
3011
3012 prom_printf("adding interrupt-controller property for SB600...\n");
3013
3014 prom_setprop(iob, name, "interrupt-controller", &val, 0);
3015
3016 pci_name = "/pxp@0,e0000000/pci@11";
3017 node = call_prom("finddevice", 1, 1, ADDR(pci_name));
3018 parent = ADDR(iob);
3019
3020 for( ; prom_next_node(&node); ) {
3021 /* scan each node for one with an interrupt */
3022 if (!PHANDLE_VALID(node))
3023 continue;
3024
3025 rval = prom_getproplen(node, "interrupts");
3026 if (rval == 0 || rval == PROM_ERROR)
3027 continue;
3028
3029 prom_getprop(node, "interrupts", &interrupts, sizeof(interrupts));
3030 if ((interrupts[0] < 212) || (interrupts[0] > 222))
3031 continue;
3032
3033 /* found a node, update both interrupts and interrupt-parent */
3034 if ((interrupts[0] >= 212) && (interrupts[0] <= 215))
3035 interrupts[0] -= 203;
3036 if ((interrupts[0] >= 216) && (interrupts[0] <= 220))
3037 interrupts[0] -= 213;
3038 if (interrupts[0] == 221)
3039 interrupts[0] = 14;
3040 if (interrupts[0] == 222)
3041 interrupts[0] = 8;
3042
3043 prom_setprop(node, pci_name, "interrupts", interrupts,
3044 sizeof(interrupts));
3045 prom_setprop(node, pci_name, "interrupt-parent", &parent,
3046 sizeof(parent));
3047 }
Darren Stevens687e16b2016-08-31 13:24:45 +01003048
3049 /*
3050 * The io-bridge has device_type set to 'io-bridge' change it to 'isa'
3051 * so that generic isa-bridge code can add the SB600 and its on-board
3052 * peripherals.
3053 */
3054 name = "/pxp@0,e0000000/io-bridge@0";
3055 iob = call_prom("finddevice", 1, 1, ADDR(name));
3056 if (!PHANDLE_VALID(iob))
3057 return;
3058
3059 /* device_type is already set, just change it. */
3060
3061 prom_printf("Changing device_type of SB600 node...\n");
3062
3063 prom_setprop(iob, name, "device_type", "isa", sizeof("isa"));
Darren Stevens50246782016-08-31 13:24:40 +01003064}
3065#else /* !CONFIG_PPC_PASEMI_NEMO */
3066static inline void fixup_device_tree_pasemi(void) { }
3067#endif
3068
Hollis Blanchard54f4ee12006-05-25 16:36:53 -05003069static void __init fixup_device_tree(void)
3070{
3071 fixup_device_tree_maple();
Harry Ciao8f101a052009-06-17 16:28:00 -07003072 fixup_device_tree_maple_memory_controller();
Benjamin Herrenschmidte8c0acf2006-07-04 14:06:29 +10003073 fixup_device_tree_chrp();
Hollis Blanchard54f4ee12006-05-25 16:36:53 -05003074 fixup_device_tree_pmac();
Sylvain Munaut88fd2a92007-02-12 23:13:20 +01003075 fixup_device_tree_efika();
Darren Stevens50246782016-08-31 13:24:40 +01003076 fixup_device_tree_pasemi();
Hollis Blanchard54f4ee12006-05-25 16:36:53 -05003077}
Paul Mackerras9b6b5632005-10-06 12:06:20 +10003078
3079static void __init prom_find_boot_cpu(void)
3080{
Benjamin Herrenschmidt493adff2013-08-07 02:01:38 +10003081 __be32 rval;
Paul Mackerras9b6b5632005-10-06 12:06:20 +10003082 ihandle prom_cpu;
3083 phandle cpu_pkg;
3084
Benjamin Herrenschmidt493adff2013-08-07 02:01:38 +10003085 rval = 0;
3086 if (prom_getprop(prom.chosen, "cpu", &rval, sizeof(rval)) <= 0)
Paul Mackerrasa575b802005-10-23 17:23:21 +10003087 return;
Benjamin Herrenschmidt493adff2013-08-07 02:01:38 +10003088 prom_cpu = be32_to_cpu(rval);
Paul Mackerras9b6b5632005-10-06 12:06:20 +10003089
3090 cpu_pkg = call_prom("instance-to-package", 1, 1, prom_cpu);
3091
Darren Stevensaf2b7fa2017-01-23 19:42:54 +00003092 if (!PHANDLE_VALID(cpu_pkg))
3093 return;
3094
Benjamin Herrenschmidt493adff2013-08-07 02:01:38 +10003095 prom_getprop(cpu_pkg, "reg", &rval, sizeof(rval));
3096 prom.cpu = be32_to_cpu(rval);
Paul Mackerras9b6b5632005-10-06 12:06:20 +10003097
Mathieu Malaterreeae5f702018-04-06 22:12:19 +02003098 prom_debug("Booting CPU hw index = %d\n", prom.cpu);
Paul Mackerras9b6b5632005-10-06 12:06:20 +10003099}
3100
3101static void __init prom_check_initrd(unsigned long r3, unsigned long r4)
3102{
3103#ifdef CONFIG_BLK_DEV_INITRD
Paul Mackerras9b6b5632005-10-06 12:06:20 +10003104 if (r3 && r4 && r4 != 0xdeadbeef) {
Benjamin Herrenschmidt493adff2013-08-07 02:01:38 +10003105 __be64 val;
Paul Mackerras9b6b5632005-10-06 12:06:20 +10003106
Anton Blanchard5827d412012-11-26 17:40:03 +00003107 prom_initrd_start = is_kernel_addr(r3) ? __pa(r3) : r3;
3108 prom_initrd_end = prom_initrd_start + r4;
Paul Mackerras9b6b5632005-10-06 12:06:20 +10003109
Benjamin Herrenschmidt493adff2013-08-07 02:01:38 +10003110 val = cpu_to_be64(prom_initrd_start);
Anton Blanchard5827d412012-11-26 17:40:03 +00003111 prom_setprop(prom.chosen, "/chosen", "linux,initrd-start",
Paul Mackerrasa23414b2005-11-10 12:00:55 +11003112 &val, sizeof(val));
Benjamin Herrenschmidt493adff2013-08-07 02:01:38 +10003113 val = cpu_to_be64(prom_initrd_end);
Anton Blanchard5827d412012-11-26 17:40:03 +00003114 prom_setprop(prom.chosen, "/chosen", "linux,initrd-end",
Paul Mackerrasa23414b2005-11-10 12:00:55 +11003115 &val, sizeof(val));
Paul Mackerras9b6b5632005-10-06 12:06:20 +10003116
Anton Blanchard5827d412012-11-26 17:40:03 +00003117 reserve_mem(prom_initrd_start,
3118 prom_initrd_end - prom_initrd_start);
Paul Mackerras9b6b5632005-10-06 12:06:20 +10003119
Mathieu Malaterreeae5f702018-04-06 22:12:19 +02003120 prom_debug("initrd_start=0x%lx\n", prom_initrd_start);
3121 prom_debug("initrd_end=0x%lx\n", prom_initrd_end);
Paul Mackerras9b6b5632005-10-06 12:06:20 +10003122 }
3123#endif /* CONFIG_BLK_DEV_INITRD */
3124}
3125
Anton Blanchard5ac47f72012-11-26 17:39:03 +00003126#ifdef CONFIG_PPC64
3127#ifdef CONFIG_RELOCATABLE
3128static void reloc_toc(void)
3129{
3130}
3131
3132static void unreloc_toc(void)
3133{
3134}
3135#else
Anton Blanchard16744002013-03-12 01:51:51 +00003136static void __reloc_toc(unsigned long offset, unsigned long nr_entries)
Anton Blanchard5ac47f72012-11-26 17:39:03 +00003137{
3138 unsigned long i;
Anton Blanchard16744002013-03-12 01:51:51 +00003139 unsigned long *toc_entry;
3140
3141 /* Get the start of the TOC by using r2 directly. */
3142 asm volatile("addi %0,2,-0x8000" : "=b" (toc_entry));
Anton Blanchard5ac47f72012-11-26 17:39:03 +00003143
3144 for (i = 0; i < nr_entries; i++) {
3145 *toc_entry = *toc_entry + offset;
3146 toc_entry++;
3147 }
3148}
3149
3150static void reloc_toc(void)
3151{
3152 unsigned long offset = reloc_offset();
3153 unsigned long nr_entries =
3154 (__prom_init_toc_end - __prom_init_toc_start) / sizeof(long);
3155
Anton Blanchard16744002013-03-12 01:51:51 +00003156 __reloc_toc(offset, nr_entries);
Anton Blanchard5ac47f72012-11-26 17:39:03 +00003157
3158 mb();
3159}
3160
3161static void unreloc_toc(void)
3162{
3163 unsigned long offset = reloc_offset();
3164 unsigned long nr_entries =
3165 (__prom_init_toc_end - __prom_init_toc_start) / sizeof(long);
3166
3167 mb();
3168
Anton Blanchard16744002013-03-12 01:51:51 +00003169 __reloc_toc(-offset, nr_entries);
Anton Blanchard5ac47f72012-11-26 17:39:03 +00003170}
3171#endif
3172#endif
Benjamin Herrenschmidt27f44882011-09-19 18:27:58 +00003173
Paul Mackerras9b6b5632005-10-06 12:06:20 +10003174/*
3175 * We enter here early on, when the Open Firmware prom is still
3176 * handling exceptions and the MMU hash table for us.
3177 */
3178
3179unsigned long __init prom_init(unsigned long r3, unsigned long r4,
3180 unsigned long pp,
Paul Mackerras549e8152008-08-30 11:43:47 +10003181 unsigned long r6, unsigned long r7,
3182 unsigned long kbase)
Paul Mackerras9b6b5632005-10-06 12:06:20 +10003183{
Paul Mackerras9b6b5632005-10-06 12:06:20 +10003184 unsigned long hdr;
Paul Mackerras9b6b5632005-10-06 12:06:20 +10003185
3186#ifdef CONFIG_PPC32
Paul Mackerras549e8152008-08-30 11:43:47 +10003187 unsigned long offset = reloc_offset();
Paul Mackerras9b6b5632005-10-06 12:06:20 +10003188 reloc_got2(offset);
Anton Blanchard5ac47f72012-11-26 17:39:03 +00003189#else
3190 reloc_toc();
Paul Mackerras9b6b5632005-10-06 12:06:20 +10003191#endif
3192
Paul Mackerras9b6b5632005-10-06 12:06:20 +10003193 /*
3194 * First zero the BSS
3195 */
Anton Blanchard5827d412012-11-26 17:40:03 +00003196 memset(&__bss_start, 0, __bss_stop - __bss_start);
Paul Mackerras9b6b5632005-10-06 12:06:20 +10003197
3198 /*
3199 * Init interface to Open Firmware, get some node references,
3200 * like /chosen
3201 */
3202 prom_init_client_services(pp);
3203
3204 /*
Paul Mackerrasa23414b2005-11-10 12:00:55 +11003205 * See if this OF is old enough that we need to do explicit maps
3206 * and other workarounds
3207 */
3208 prom_find_mmu();
3209
3210 /*
Paul Mackerras9b6b5632005-10-06 12:06:20 +10003211 * Init prom stdout device
3212 */
3213 prom_init_stdout();
3214
Anton Blanchard5827d412012-11-26 17:40:03 +00003215 prom_printf("Preparing to boot %s", linux_banner);
Michael Ellermane7943fb2009-03-04 19:02:01 +00003216
Paul Mackerras9b6b5632005-10-06 12:06:20 +10003217 /*
3218 * Get default machine type. At this point, we do not differentiate
3219 * between pSeries SMP and pSeries LPAR
3220 */
Anton Blanchard5827d412012-11-26 17:40:03 +00003221 of_platform = prom_find_machine_type();
3222 prom_printf("Detected machine type: %x\n", of_platform);
Paul Mackerras9b6b5632005-10-06 12:06:20 +10003223
Suzuki Poulose0f890c82011-12-14 22:57:15 +00003224#ifndef CONFIG_NONSTATIC_KERNEL
Olaf Heringadd60ef2006-03-23 22:03:57 +01003225 /* Bail if this is a kdump kernel. */
3226 if (PHYSICAL_START > 0)
3227 prom_panic("Error: You can't boot a kdump kernel from OF!\n");
Paul Mackerras549e8152008-08-30 11:43:47 +10003228#endif
Olaf Heringadd60ef2006-03-23 22:03:57 +01003229
3230 /*
3231 * Check for an initrd
3232 */
3233 prom_check_initrd(r3, r4);
3234
Suraj Jitindar Singh12cc9fd2017-02-28 17:03:47 +11003235 /*
3236 * Do early parsing of command line
3237 */
3238 early_cmdline_parse();
3239
Benjamin Herrenschmidt11fdb302018-10-15 13:49:53 +11003240#ifdef CONFIG_PPC_PSERIES
Paul Mackerras9b6b5632005-10-06 12:06:20 +10003241 /*
3242 * On pSeries, inform the firmware about our capabilities
3243 */
Anton Blanchard5827d412012-11-26 17:40:03 +00003244 if (of_platform == PLATFORM_PSERIES ||
3245 of_platform == PLATFORM_PSERIES_LPAR)
Paul Mackerras9b6b5632005-10-06 12:06:20 +10003246 prom_send_capabilities();
3247#endif
3248
Paul Mackerras9b6b5632005-10-06 12:06:20 +10003249 /*
Arnd Bergmannf3f66f52005-10-31 20:08:37 -05003250 * Copy the CPU hold code
Paul Mackerras9b6b5632005-10-06 12:06:20 +10003251 */
Anton Blanchard5827d412012-11-26 17:40:03 +00003252 if (of_platform != PLATFORM_POWERMAC)
Paul Mackerras549e8152008-08-30 11:43:47 +10003253 copy_and_flush(0, kbase, 0x100, 0);
Paul Mackerras9b6b5632005-10-06 12:06:20 +10003254
3255 /*
Paul Mackerras9b6b5632005-10-06 12:06:20 +10003256 * Initialize memory management within prom_init
3257 */
3258 prom_init_mem();
3259
3260 /*
3261 * Determine which cpu is actually running right _now_
3262 */
3263 prom_find_boot_cpu();
3264
3265 /*
3266 * Initialize display devices
3267 */
3268 prom_check_displays();
3269
Benjamin Herrenschmidt493adff2013-08-07 02:01:38 +10003270#if defined(CONFIG_PPC64) && defined(__BIG_ENDIAN__)
Paul Mackerras9b6b5632005-10-06 12:06:20 +10003271 /*
3272 * Initialize IOMMU (TCE tables) on pSeries. Do that before anything else
3273 * that uses the allocator, we need to make sure we get the top of memory
3274 * available for us here...
3275 */
Anton Blanchard5827d412012-11-26 17:40:03 +00003276 if (of_platform == PLATFORM_PSERIES)
Paul Mackerras9b6b5632005-10-06 12:06:20 +10003277 prom_initialize_tce_table();
3278#endif
3279
3280 /*
Benjamin Herrenschmidt27f44882011-09-19 18:27:58 +00003281 * On non-powermacs, try to instantiate RTAS. PowerMacs don't
3282 * have a usable RTAS implementation.
Paul Mackerras9b6b5632005-10-06 12:06:20 +10003283 */
Benjamin Herrenschmidt11fdb302018-10-15 13:49:53 +11003284 if (of_platform != PLATFORM_POWERMAC)
Paul Mackerras9b6b5632005-10-06 12:06:20 +10003285 prom_instantiate_rtas();
Benjamin Herrenschmidt27f44882011-09-19 18:27:58 +00003286
Ashley Lai4a727422012-08-14 18:34:57 -05003287#ifdef CONFIG_PPC64
3288 /* instantiate sml */
3289 prom_instantiate_sml();
3290#endif
3291
Benjamin Herrenschmidt27f44882011-09-19 18:27:58 +00003292 /*
3293 * On non-powermacs, put all CPUs in spin-loops.
3294 *
3295 * PowerMacs use a different mechanism to spin CPUs
Benjamin Herrenschmidtdbe78b42013-09-25 14:02:50 +10003296 *
3297 * (This must be done after instanciating RTAS)
Benjamin Herrenschmidt27f44882011-09-19 18:27:58 +00003298 */
Benjamin Herrenschmidt11fdb302018-10-15 13:49:53 +11003299 if (of_platform != PLATFORM_POWERMAC)
Benjamin Herrenschmidt27f44882011-09-19 18:27:58 +00003300 prom_hold_cpus();
Paul Mackerras9b6b5632005-10-06 12:06:20 +10003301
3302 /*
3303 * Fill in some infos for use by the kernel later on
3304 */
Benjamin Herrenschmidt493adff2013-08-07 02:01:38 +10003305 if (prom_memory_limit) {
3306 __be64 val = cpu_to_be64(prom_memory_limit);
Anton Blanchard5827d412012-11-26 17:40:03 +00003307 prom_setprop(prom.chosen, "/chosen", "linux,memory-limit",
Benjamin Herrenschmidt493adff2013-08-07 02:01:38 +10003308 &val, sizeof(val));
3309 }
Paul Mackerras9b6b5632005-10-06 12:06:20 +10003310#ifdef CONFIG_PPC64
Anton Blanchard5827d412012-11-26 17:40:03 +00003311 if (prom_iommu_off)
3312 prom_setprop(prom.chosen, "/chosen", "linux,iommu-off",
Paul Mackerrasa23414b2005-11-10 12:00:55 +11003313 NULL, 0);
Paul Mackerras9b6b5632005-10-06 12:06:20 +10003314
Anton Blanchard5827d412012-11-26 17:40:03 +00003315 if (prom_iommu_force_on)
3316 prom_setprop(prom.chosen, "/chosen", "linux,iommu-force-on",
Paul Mackerrasa23414b2005-11-10 12:00:55 +11003317 NULL, 0);
Paul Mackerras9b6b5632005-10-06 12:06:20 +10003318
Anton Blanchard5827d412012-11-26 17:40:03 +00003319 if (prom_tce_alloc_start) {
3320 prom_setprop(prom.chosen, "/chosen", "linux,tce-alloc-start",
3321 &prom_tce_alloc_start,
Paul Mackerras9b6b5632005-10-06 12:06:20 +10003322 sizeof(prom_tce_alloc_start));
Anton Blanchard5827d412012-11-26 17:40:03 +00003323 prom_setprop(prom.chosen, "/chosen", "linux,tce-alloc-end",
3324 &prom_tce_alloc_end,
Paul Mackerras9b6b5632005-10-06 12:06:20 +10003325 sizeof(prom_tce_alloc_end));
3326 }
3327#endif
3328
3329 /*
3330 * Fixup any known bugs in the device-tree
3331 */
3332 fixup_device_tree();
3333
3334 /*
3335 * Now finally create the flattened device-tree
3336 */
Anton Blanchard1f8737a2009-03-31 20:06:15 +00003337 prom_printf("copying OF device tree...\n");
Paul Mackerras9b6b5632005-10-06 12:06:20 +10003338 flatten_device_tree();
3339
Paul Mackerras3825ac02005-11-08 22:48:08 +11003340 /*
3341 * in case stdin is USB and still active on IBM machines...
3342 * Unfortunately quiesce crashes on some powermacs if we have
Benjamin Herrenschmidt11fdb302018-10-15 13:49:53 +11003343 * closed stdin already (in particular the powerbook 101).
Paul Mackerras3825ac02005-11-08 22:48:08 +11003344 */
Benjamin Herrenschmidt11fdb302018-10-15 13:49:53 +11003345 if (of_platform != PLATFORM_POWERMAC)
Paul Mackerras3825ac02005-11-08 22:48:08 +11003346 prom_close_stdin();
Paul Mackerras9b6b5632005-10-06 12:06:20 +10003347
3348 /*
3349 * Call OF "quiesce" method to shut down pending DMA's from
3350 * devices etc...
3351 */
Michael Ellerman7e862d72015-03-30 17:38:09 +11003352 prom_printf("Quiescing Open Firmware ...\n");
Paul Mackerras9b6b5632005-10-06 12:06:20 +10003353 call_prom("quiesce", 0, 0);
3354
3355 /*
3356 * And finally, call the kernel passing it the flattened device
3357 * tree and NULL as r5, thus triggering the new entry point which
3358 * is common to us and kexec
3359 */
Anton Blanchard5827d412012-11-26 17:40:03 +00003360 hdr = dt_header_start;
Benjamin Herrenschmidt40dfef62011-11-29 18:22:56 +00003361
3362 /* Don't print anything after quiesce under OPAL, it crashes OFW */
Benjamin Herrenschmidt11fdb302018-10-15 13:49:53 +11003363 prom_printf("Booting Linux via __start() @ 0x%lx ...\n", kbase);
3364 prom_debug("->dt_header_start=0x%lx\n", hdr);
Paul Mackerras9b6b5632005-10-06 12:06:20 +10003365
3366#ifdef CONFIG_PPC32
3367 reloc_got2(-offset);
Anton Blanchard5ac47f72012-11-26 17:39:03 +00003368#else
3369 unreloc_toc();
Paul Mackerras9b6b5632005-10-06 12:06:20 +10003370#endif
3371
Benjamin Herrenschmidt6e35d5d2011-09-19 18:28:01 +00003372 __start(hdr, kbase, 0, 0, 0, 0, 0);
Paul Mackerras9b6b5632005-10-06 12:06:20 +10003373
3374 return 0;
3375}