blob: 38ae5933d91741ddd15c7e065f2e03297b4acce5 [file] [log] [blame]
Thomas Gleixner2874c5f2019-05-27 08:55:01 +02001// SPDX-License-Identifier: GPL-2.0-or-later
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002/*
3 * Procedures for interfacing to Open Firmware.
4 *
5 * Paul Mackerras August 1996.
6 * Copyright (C) 1996-2005 Paul Mackerras.
7 *
8 * Adapted for 64bit PowerPC by Dave Engebretsen and Peter Bergner.
9 * {engebret|bergner}@us.ibm.com
Paul Mackerras9b6b5632005-10-06 12:06:20 +100010 */
11
12#undef DEBUG_PROM
13
Daniel Axtens054f3672017-07-12 14:36:04 -070014/* we cannot use FORTIFY as it brings in new symbols */
15#define __NO_FORTIFY
16
Paul Mackerras9b6b5632005-10-06 12:06:20 +100017#include <stdarg.h>
Paul Mackerras9b6b5632005-10-06 12:06:20 +100018#include <linux/kernel.h>
19#include <linux/string.h>
20#include <linux/init.h>
21#include <linux/threads.h>
22#include <linux/spinlock.h>
23#include <linux/types.h>
24#include <linux/pci.h>
25#include <linux/proc_fs.h>
Paul Mackerras9b6b5632005-10-06 12:06:20 +100026#include <linux/delay.h>
27#include <linux/initrd.h>
28#include <linux/bitops.h>
Mike Rapoport65fddcf2020-06-08 21:32:42 -070029#include <linux/pgtable.h>
Paul Mackerras9b6b5632005-10-06 12:06:20 +100030#include <asm/prom.h>
31#include <asm/rtas.h>
32#include <asm/page.h>
33#include <asm/processor.h>
34#include <asm/irq.h>
35#include <asm/io.h>
36#include <asm/smp.h>
Paul Mackerras9b6b5632005-10-06 12:06:20 +100037#include <asm/mmu.h>
Paul Mackerras9b6b5632005-10-06 12:06:20 +100038#include <asm/iommu.h>
Paul Mackerras9b6b5632005-10-06 12:06:20 +100039#include <asm/btext.h>
40#include <asm/sections.h>
41#include <asm/machdep.h>
Daniel Axtens0545d542016-09-06 15:32:43 +100042#include <asm/asm-prototypes.h>
Ram Pai6a9c9302019-08-19 23:13:14 -030043#include <asm/ultravisor-api.h>
Paul Mackerras9b6b5632005-10-06 12:06:20 +100044
Paul Mackerras9b6b5632005-10-06 12:06:20 +100045#include <linux/linux_logo.h>
Paul Mackerras9b6b5632005-10-06 12:06:20 +100046
Benjamin Herrenschmidte63334e2018-10-15 13:49:52 +110047/* All of prom_init bss lives here */
Joe Perches33def842020-10-21 19:36:07 -070048#define __prombss __section(".bss.prominit")
Benjamin Herrenschmidte63334e2018-10-15 13:49:52 +110049
Paul Mackerras9b6b5632005-10-06 12:06:20 +100050/*
Paul Mackerras9b6b5632005-10-06 12:06:20 +100051 * Eventually bump that one up
52 */
53#define DEVTREE_CHUNK_SIZE 0x100000
54
55/*
56 * This is the size of the local memory reserve map that gets copied
57 * into the boot params passed to the kernel. That size is totally
58 * flexible as the kernel just reads the list until it encounters an
59 * entry with size 0, so it can be changed without breaking binary
60 * compatibility
61 */
62#define MEM_RESERVE_MAP_SIZE 8
63
64/*
65 * prom_init() is called very early on, before the kernel text
66 * and data have been mapped to KERNELBASE. At this point the code
67 * is running at whatever address it has been loaded at.
68 * On ppc32 we compile with -mrelocatable, which means that references
69 * to extern and static variables get relocated automatically.
Anton Blanchard5ac47f72012-11-26 17:39:03 +000070 * ppc64 objects are always relocatable, we just need to relocate the
71 * TOC.
Paul Mackerras9b6b5632005-10-06 12:06:20 +100072 *
73 * Because OF may have mapped I/O devices into the area starting at
74 * KERNELBASE, particularly on CHRP machines, we can't safely call
75 * OF once the kernel has been mapped to KERNELBASE. Therefore all
76 * OF calls must be done within prom_init().
77 *
78 * ADDR is used in calls to call_prom. The 4th and following
79 * arguments to call_prom should be 32-bit values.
80 * On ppc64, 64 bit values are truncated to 32 bits (and
81 * fortunately don't get interpreted as two arguments).
82 */
Anton Blanchard5ac47f72012-11-26 17:39:03 +000083#define ADDR(x) (u32)(unsigned long)(x)
84
Paul Mackerras9b6b5632005-10-06 12:06:20 +100085#ifdef CONFIG_PPC64
Paul Mackerrasa23414b2005-11-10 12:00:55 +110086#define OF_WORKAROUNDS 0
Paul Mackerras9b6b5632005-10-06 12:06:20 +100087#else
Paul Mackerrasa23414b2005-11-10 12:00:55 +110088#define OF_WORKAROUNDS of_workarounds
Benjamin Herrenschmidte63334e2018-10-15 13:49:52 +110089static int of_workarounds __prombss;
Paul Mackerras9b6b5632005-10-06 12:06:20 +100090#endif
91
Paul Mackerrasa23414b2005-11-10 12:00:55 +110092#define OF_WA_CLAIM 1 /* do phys/virt claim separately, then map */
93#define OF_WA_LONGTRAIL 2 /* work around longtrail bugs */
94
Paul Mackerras9b6b5632005-10-06 12:06:20 +100095#define PROM_BUG() do { \
96 prom_printf("kernel BUG at %s line 0x%x!\n", \
Anton Blanchard5827d412012-11-26 17:40:03 +000097 __FILE__, __LINE__); \
Christophe Leroy63ce2712019-08-26 11:10:23 +000098 __builtin_trap(); \
Paul Mackerras9b6b5632005-10-06 12:06:20 +100099} while (0)
100
101#ifdef DEBUG_PROM
102#define prom_debug(x...) prom_printf(x)
103#else
Mathieu Malaterre85aa4b92018-04-23 21:36:38 +0200104#define prom_debug(x...) do { } while (0)
Paul Mackerras9b6b5632005-10-06 12:06:20 +1000105#endif
106
Paul Mackerras9b6b5632005-10-06 12:06:20 +1000107
108typedef u32 prom_arg_t;
109
110struct prom_args {
Benjamin Herrenschmidt493adff2013-08-07 02:01:38 +1000111 __be32 service;
112 __be32 nargs;
113 __be32 nret;
114 __be32 args[10];
Paul Mackerras9b6b5632005-10-06 12:06:20 +1000115};
116
117struct prom_t {
118 ihandle root;
Paul Mackerrasa23414b2005-11-10 12:00:55 +1100119 phandle chosen;
Paul Mackerras9b6b5632005-10-06 12:06:20 +1000120 int cpu;
121 ihandle stdout;
Paul Mackerrasa575b802005-10-23 17:23:21 +1000122 ihandle mmumap;
Paul Mackerrasa23414b2005-11-10 12:00:55 +1100123 ihandle memory;
Paul Mackerras9b6b5632005-10-06 12:06:20 +1000124};
125
126struct mem_map_entry {
Benjamin Herrenschmidt493adff2013-08-07 02:01:38 +1000127 __be64 base;
128 __be64 size;
Paul Mackerras9b6b5632005-10-06 12:06:20 +1000129};
130
Benjamin Herrenschmidt493adff2013-08-07 02:01:38 +1000131typedef __be32 cell_t;
Paul Mackerras9b6b5632005-10-06 12:06:20 +1000132
Benjamin Herrenschmidt6e35d5d2011-09-19 18:28:01 +0000133extern void __start(unsigned long r3, unsigned long r4, unsigned long r5,
134 unsigned long r6, unsigned long r7, unsigned long r8,
135 unsigned long r9);
Paul Mackerras9b6b5632005-10-06 12:06:20 +1000136
137#ifdef CONFIG_PPC64
Paul Mackerrasc49888202005-10-26 21:52:53 +1000138extern int enter_prom(struct prom_args *args, unsigned long entry);
Paul Mackerras9b6b5632005-10-06 12:06:20 +1000139#else
Paul Mackerrasc49888202005-10-26 21:52:53 +1000140static inline int enter_prom(struct prom_args *args, unsigned long entry)
Paul Mackerras9b6b5632005-10-06 12:06:20 +1000141{
Paul Mackerrasc49888202005-10-26 21:52:53 +1000142 return ((int (*)(struct prom_args *))entry)(args);
Paul Mackerras9b6b5632005-10-06 12:06:20 +1000143}
144#endif
145
146extern void copy_and_flush(unsigned long dest, unsigned long src,
147 unsigned long size, unsigned long offset);
148
149/* prom structure */
Benjamin Herrenschmidte63334e2018-10-15 13:49:52 +1100150static struct prom_t __prombss prom;
Paul Mackerras9b6b5632005-10-06 12:06:20 +1000151
Benjamin Herrenschmidte63334e2018-10-15 13:49:52 +1100152static unsigned long __prombss prom_entry;
Paul Mackerras9b6b5632005-10-06 12:06:20 +1000153
Benjamin Herrenschmidte63334e2018-10-15 13:49:52 +1100154static char __prombss of_stdout_device[256];
Christophe Leroyd7fbe2a2019-04-02 09:08:38 +0000155static char __prombss prom_scratch[256];
Paul Mackerras9b6b5632005-10-06 12:06:20 +1000156
Benjamin Herrenschmidte63334e2018-10-15 13:49:52 +1100157static unsigned long __prombss dt_header_start;
158static unsigned long __prombss dt_struct_start, dt_struct_end;
159static unsigned long __prombss dt_string_start, dt_string_end;
Paul Mackerras9b6b5632005-10-06 12:06:20 +1000160
Benjamin Herrenschmidte63334e2018-10-15 13:49:52 +1100161static unsigned long __prombss prom_initrd_start, prom_initrd_end;
Paul Mackerras9b6b5632005-10-06 12:06:20 +1000162
163#ifdef CONFIG_PPC64
Benjamin Herrenschmidte63334e2018-10-15 13:49:52 +1100164static int __prombss prom_iommu_force_on;
165static int __prombss prom_iommu_off;
166static unsigned long __prombss prom_tce_alloc_start;
167static unsigned long __prombss prom_tce_alloc_end;
Paul Mackerras9b6b5632005-10-06 12:06:20 +1000168#endif
169
Benjamin Herrenschmidtc8860872018-10-15 13:49:54 +1100170#ifdef CONFIG_PPC_PSERIES
Benjamin Herrenschmidt8ca2d512018-10-15 13:49:57 +1100171static bool __prombss prom_radix_disable;
Aneesh Kumar K.Vbf6b7662020-07-27 14:29:08 +0530172static bool __prombss prom_radix_gtse_disable;
Greg Kurza3bf9fb2019-05-15 12:05:01 +0200173static bool __prombss prom_xive_disable;
Benjamin Herrenschmidtc8860872018-10-15 13:49:54 +1100174#endif
Suraj Jitindar Singh014d02c2017-02-28 17:03:48 +1100175
Ram Pai6a9c9302019-08-19 23:13:14 -0300176#ifdef CONFIG_PPC_SVM
177static bool __prombss prom_svm_enable;
178#endif
179
Suraj Jitindar Singh014d02c2017-02-28 17:03:48 +1100180struct platform_support {
181 bool hash_mmu;
182 bool radix_mmu;
183 bool radix_gtse;
Cédric Le Goaterac5e5a52017-08-30 21:46:16 +0200184 bool xive;
Suraj Jitindar Singh014d02c2017-02-28 17:03:48 +1100185};
186
Benjamin Herrenschmidte8222502006-03-28 23:15:54 +1100187/* Platforms codes are now obsolete in the kernel. Now only used within this
188 * file and ultimately gone too. Feel free to change them if you need, they
189 * are not shared with anything outside of this file anymore
190 */
191#define PLATFORM_PSERIES 0x0100
192#define PLATFORM_PSERIES_LPAR 0x0101
193#define PLATFORM_LPAR 0x0001
194#define PLATFORM_POWERMAC 0x0400
195#define PLATFORM_GENERIC 0x0500
196
Benjamin Herrenschmidte63334e2018-10-15 13:49:52 +1100197static int __prombss of_platform;
Paul Mackerras9b6b5632005-10-06 12:06:20 +1000198
Benjamin Herrenschmidte63334e2018-10-15 13:49:52 +1100199static char __prombss prom_cmd_line[COMMAND_LINE_SIZE];
Paul Mackerras9b6b5632005-10-06 12:06:20 +1000200
Benjamin Herrenschmidte63334e2018-10-15 13:49:52 +1100201static unsigned long __prombss prom_memory_limit;
Benjamin Krillcf687872009-07-27 22:02:39 +0000202
Benjamin Herrenschmidte63334e2018-10-15 13:49:52 +1100203static unsigned long __prombss alloc_top;
204static unsigned long __prombss alloc_top_high;
205static unsigned long __prombss alloc_bottom;
206static unsigned long __prombss rmo_top;
207static unsigned long __prombss ram_top;
Paul Mackerras9b6b5632005-10-06 12:06:20 +1000208
Benjamin Herrenschmidte63334e2018-10-15 13:49:52 +1100209static struct mem_map_entry __prombss mem_reserve_map[MEM_RESERVE_MAP_SIZE];
210static int __prombss mem_reserve_cnt;
Paul Mackerras9b6b5632005-10-06 12:06:20 +1000211
Benjamin Herrenschmidte63334e2018-10-15 13:49:52 +1100212static cell_t __prombss regbuf[1024];
Paul Mackerras9b6b5632005-10-06 12:06:20 +1000213
Benjamin Herrenschmidt8ca2d512018-10-15 13:49:57 +1100214static bool __prombss rtas_has_query_cpu_stopped;
Benjamin Herrenschmidtdbe78b42013-09-25 14:02:50 +1000215
Paul Mackerras9b6b5632005-10-06 12:06:20 +1000216
Paul Mackerras9b6b5632005-10-06 12:06:20 +1000217/*
218 * Error results ... some OF calls will return "-1" on error, some
219 * will return 0, some will return either. To simplify, here are
220 * macros to use with any ihandle or phandle return value to check if
221 * it is valid
222 */
223
224#define PROM_ERROR (-1u)
225#define PHANDLE_VALID(p) ((p) != 0 && (p) != PROM_ERROR)
226#define IHANDLE_VALID(i) ((i) != 0 && (i) != PROM_ERROR)
227
Christophe Leroy450e7dd2019-04-26 16:23:28 +0000228/* Copied from lib/string.c and lib/kstrtox.c */
229
230static int __init prom_strcmp(const char *cs, const char *ct)
231{
232 unsigned char c1, c2;
233
234 while (1) {
235 c1 = *cs++;
236 c2 = *ct++;
237 if (c1 != c2)
238 return c1 < c2 ? -1 : 1;
239 if (!c1)
240 break;
241 }
242 return 0;
243}
244
245static char __init *prom_strcpy(char *dest, const char *src)
246{
247 char *tmp = dest;
248
249 while ((*dest++ = *src++) != '\0')
250 /* nothing */;
251 return tmp;
252}
253
254static int __init prom_strncmp(const char *cs, const char *ct, size_t count)
255{
256 unsigned char c1, c2;
257
258 while (count) {
259 c1 = *cs++;
260 c2 = *ct++;
261 if (c1 != c2)
262 return c1 < c2 ? -1 : 1;
263 if (!c1)
264 break;
265 count--;
266 }
267 return 0;
268}
269
270static size_t __init prom_strlen(const char *s)
271{
272 const char *sc;
273
274 for (sc = s; *sc != '\0'; ++sc)
275 /* nothing */;
276 return sc - s;
277}
278
279static int __init prom_memcmp(const void *cs, const void *ct, size_t count)
280{
281 const unsigned char *su1, *su2;
282 int res = 0;
283
284 for (su1 = cs, su2 = ct; 0 < count; ++su1, ++su2, count--)
285 if ((res = *su1 - *su2) != 0)
286 break;
287 return res;
288}
289
290static char __init *prom_strstr(const char *s1, const char *s2)
291{
292 size_t l1, l2;
293
294 l2 = prom_strlen(s2);
295 if (!l2)
296 return (char *)s1;
297 l1 = prom_strlen(s1);
298 while (l1 >= l2) {
299 l1--;
300 if (!prom_memcmp(s1, s2, l2))
301 return (char *)s1;
302 s1++;
303 }
304 return NULL;
305}
306
Chris Packhamd79fbb32019-08-02 10:50:06 +1200307static size_t __init prom_strlcat(char *dest, const char *src, size_t count)
Christophe Leroy450e7dd2019-04-26 16:23:28 +0000308{
Chris Packhamd79fbb32019-08-02 10:50:06 +1200309 size_t dsize = prom_strlen(dest);
310 size_t len = prom_strlen(src);
311 size_t res = dsize + len;
Christophe Leroy450e7dd2019-04-26 16:23:28 +0000312
Chris Packhamd79fbb32019-08-02 10:50:06 +1200313 /* This would be a bug */
314 if (dsize >= count)
315 return count;
316
317 dest += dsize;
318 count -= dsize;
319 if (len >= count)
320 len = count-1;
321 memcpy(dest, src, len);
322 dest[len] = 0;
323 return res;
324
Christophe Leroy450e7dd2019-04-26 16:23:28 +0000325}
326
327#ifdef CONFIG_PPC_PSERIES
328static int __init prom_strtobool(const char *s, bool *res)
329{
330 if (!s)
331 return -EINVAL;
332
333 switch (s[0]) {
334 case 'y':
335 case 'Y':
336 case '1':
337 *res = true;
338 return 0;
339 case 'n':
340 case 'N':
341 case '0':
342 *res = false;
343 return 0;
344 case 'o':
345 case 'O':
346 switch (s[1]) {
347 case 'n':
348 case 'N':
349 *res = true;
350 return 0;
351 case 'f':
352 case 'F':
353 *res = false;
354 return 0;
355 default:
356 break;
357 }
358 default:
359 break;
360 }
361
362 return -EINVAL;
363}
364#endif
Paul Mackerras9b6b5632005-10-06 12:06:20 +1000365
366/* This is the one and *ONLY* place where we actually call open
367 * firmware.
368 */
369
370static int __init call_prom(const char *service, int nargs, int nret, ...)
371{
372 int i;
373 struct prom_args args;
374 va_list list;
375
Benjamin Herrenschmidt493adff2013-08-07 02:01:38 +1000376 args.service = cpu_to_be32(ADDR(service));
377 args.nargs = cpu_to_be32(nargs);
378 args.nret = cpu_to_be32(nret);
Paul Mackerras9b6b5632005-10-06 12:06:20 +1000379
380 va_start(list, nret);
381 for (i = 0; i < nargs; i++)
Benjamin Herrenschmidt493adff2013-08-07 02:01:38 +1000382 args.args[i] = cpu_to_be32(va_arg(list, prom_arg_t));
Paul Mackerras9b6b5632005-10-06 12:06:20 +1000383 va_end(list);
384
385 for (i = 0; i < nret; i++)
386 args.args[nargs+i] = 0;
387
Anton Blanchard5827d412012-11-26 17:40:03 +0000388 if (enter_prom(&args, prom_entry) < 0)
Paul Mackerrasc49888202005-10-26 21:52:53 +1000389 return PROM_ERROR;
Paul Mackerras9b6b5632005-10-06 12:06:20 +1000390
Benjamin Herrenschmidt493adff2013-08-07 02:01:38 +1000391 return (nret > 0) ? be32_to_cpu(args.args[nargs]) : 0;
Paul Mackerras9b6b5632005-10-06 12:06:20 +1000392}
393
394static int __init call_prom_ret(const char *service, int nargs, int nret,
395 prom_arg_t *rets, ...)
396{
397 int i;
398 struct prom_args args;
399 va_list list;
400
Benjamin Herrenschmidt493adff2013-08-07 02:01:38 +1000401 args.service = cpu_to_be32(ADDR(service));
402 args.nargs = cpu_to_be32(nargs);
403 args.nret = cpu_to_be32(nret);
Paul Mackerras9b6b5632005-10-06 12:06:20 +1000404
405 va_start(list, rets);
406 for (i = 0; i < nargs; i++)
Benjamin Herrenschmidt493adff2013-08-07 02:01:38 +1000407 args.args[i] = cpu_to_be32(va_arg(list, prom_arg_t));
Paul Mackerras9b6b5632005-10-06 12:06:20 +1000408 va_end(list);
409
410 for (i = 0; i < nret; i++)
Olaf Heringed1189b72005-11-29 14:04:05 +0100411 args.args[nargs+i] = 0;
Paul Mackerras9b6b5632005-10-06 12:06:20 +1000412
Anton Blanchard5827d412012-11-26 17:40:03 +0000413 if (enter_prom(&args, prom_entry) < 0)
Paul Mackerrasc49888202005-10-26 21:52:53 +1000414 return PROM_ERROR;
Paul Mackerras9b6b5632005-10-06 12:06:20 +1000415
416 if (rets != NULL)
417 for (i = 1; i < nret; ++i)
Benjamin Herrenschmidt493adff2013-08-07 02:01:38 +1000418 rets[i-1] = be32_to_cpu(args.args[nargs+i]);
Paul Mackerras9b6b5632005-10-06 12:06:20 +1000419
Benjamin Herrenschmidt493adff2013-08-07 02:01:38 +1000420 return (nret > 0) ? be32_to_cpu(args.args[nargs]) : 0;
Paul Mackerras9b6b5632005-10-06 12:06:20 +1000421}
422
423
Paul Mackerras9b6b5632005-10-06 12:06:20 +1000424static void __init prom_print(const char *msg)
425{
426 const char *p, *q;
Paul Mackerras9b6b5632005-10-06 12:06:20 +1000427
Anton Blanchard5827d412012-11-26 17:40:03 +0000428 if (prom.stdout == 0)
Paul Mackerras9b6b5632005-10-06 12:06:20 +1000429 return;
430
431 for (p = msg; *p != 0; p = q) {
432 for (q = p; *q != 0 && *q != '\n'; ++q)
433 ;
434 if (q > p)
Anton Blanchard5827d412012-11-26 17:40:03 +0000435 call_prom("write", 3, 1, prom.stdout, p, q - p);
Paul Mackerras9b6b5632005-10-06 12:06:20 +1000436 if (*q == 0)
437 break;
438 ++q;
Anton Blanchard5827d412012-11-26 17:40:03 +0000439 call_prom("write", 3, 1, prom.stdout, ADDR("\r\n"), 2);
Paul Mackerras9b6b5632005-10-06 12:06:20 +1000440 }
441}
442
443
Mathieu Malaterre8af1da42018-05-29 21:20:01 +0200444/*
445 * Both prom_print_hex & prom_print_dec takes an unsigned long as input so that
446 * we do not need __udivdi3 or __umoddi3 on 32bits.
447 */
Paul Mackerras9b6b5632005-10-06 12:06:20 +1000448static void __init prom_print_hex(unsigned long val)
449{
450 int i, nibbles = sizeof(val)*2;
451 char buf[sizeof(val)*2+1];
Paul Mackerras9b6b5632005-10-06 12:06:20 +1000452
453 for (i = nibbles-1; i >= 0; i--) {
454 buf[i] = (val & 0xf) + '0';
455 if (buf[i] > '9')
456 buf[i] += ('a'-'0'-10);
457 val >>= 4;
458 }
459 buf[nibbles] = '\0';
Anton Blanchard5827d412012-11-26 17:40:03 +0000460 call_prom("write", 3, 1, prom.stdout, buf, nibbles);
Paul Mackerras9b6b5632005-10-06 12:06:20 +1000461}
462
Michael Neuling2c48a7d2010-07-27 18:26:21 +0000463/* max number of decimal digits in an unsigned long */
464#define UL_DIGITS 21
465static void __init prom_print_dec(unsigned long val)
466{
467 int i, size;
468 char buf[UL_DIGITS+1];
Michael Neuling2c48a7d2010-07-27 18:26:21 +0000469
470 for (i = UL_DIGITS-1; i >= 0; i--) {
471 buf[i] = (val % 10) + '0';
472 val = val/10;
473 if (val == 0)
474 break;
475 }
476 /* shift stuff down */
477 size = UL_DIGITS - i;
Anton Blanchard5827d412012-11-26 17:40:03 +0000478 call_prom("write", 3, 1, prom.stdout, buf+i, size);
Michael Neuling2c48a7d2010-07-27 18:26:21 +0000479}
Paul Mackerras9b6b5632005-10-06 12:06:20 +1000480
Mathieu Malaterreeae5f702018-04-06 22:12:19 +0200481__printf(1, 2)
Paul Mackerras9b6b5632005-10-06 12:06:20 +1000482static void __init prom_printf(const char *format, ...)
483{
484 const char *p, *q, *s;
485 va_list args;
486 unsigned long v;
Benjamin Herrenschmidtaf277142011-04-06 10:51:17 +1000487 long vs;
Mathieu Malaterre8af1da42018-05-29 21:20:01 +0200488 int n = 0;
Paul Mackerras9b6b5632005-10-06 12:06:20 +1000489
490 va_start(args, format);
Paul Mackerras9b6b5632005-10-06 12:06:20 +1000491 for (p = format; *p != 0; p = q) {
492 for (q = p; *q != 0 && *q != '\n' && *q != '%'; ++q)
493 ;
494 if (q > p)
Anton Blanchard5827d412012-11-26 17:40:03 +0000495 call_prom("write", 3, 1, prom.stdout, p, q - p);
Paul Mackerras9b6b5632005-10-06 12:06:20 +1000496 if (*q == 0)
497 break;
498 if (*q == '\n') {
499 ++q;
Anton Blanchard5827d412012-11-26 17:40:03 +0000500 call_prom("write", 3, 1, prom.stdout,
Paul Mackerras9b6b5632005-10-06 12:06:20 +1000501 ADDR("\r\n"), 2);
502 continue;
503 }
504 ++q;
505 if (*q == 0)
506 break;
Mathieu Malaterre8af1da42018-05-29 21:20:01 +0200507 while (*q == 'l') {
508 ++q;
509 ++n;
510 }
Paul Mackerras9b6b5632005-10-06 12:06:20 +1000511 switch (*q) {
512 case 's':
513 ++q;
514 s = va_arg(args, const char *);
515 prom_print(s);
516 break;
517 case 'x':
518 ++q;
Mathieu Malaterre8af1da42018-05-29 21:20:01 +0200519 switch (n) {
520 case 0:
521 v = va_arg(args, unsigned int);
522 break;
523 case 1:
524 v = va_arg(args, unsigned long);
525 break;
526 case 2:
527 default:
528 v = va_arg(args, unsigned long long);
529 break;
530 }
Paul Mackerras9b6b5632005-10-06 12:06:20 +1000531 prom_print_hex(v);
532 break;
Mathieu Malaterre8af1da42018-05-29 21:20:01 +0200533 case 'u':
534 ++q;
535 switch (n) {
536 case 0:
537 v = va_arg(args, unsigned int);
538 break;
539 case 1:
540 v = va_arg(args, unsigned long);
541 break;
542 case 2:
543 default:
544 v = va_arg(args, unsigned long long);
545 break;
546 }
547 prom_print_dec(v);
548 break;
Benjamin Herrenschmidtaf277142011-04-06 10:51:17 +1000549 case 'd':
550 ++q;
Mathieu Malaterre8af1da42018-05-29 21:20:01 +0200551 switch (n) {
552 case 0:
553 vs = va_arg(args, int);
554 break;
555 case 1:
556 vs = va_arg(args, long);
557 break;
558 case 2:
559 default:
560 vs = va_arg(args, long long);
561 break;
562 }
Benjamin Herrenschmidtaf277142011-04-06 10:51:17 +1000563 if (vs < 0) {
Anton Blanchard5827d412012-11-26 17:40:03 +0000564 prom_print("-");
Benjamin Herrenschmidtaf277142011-04-06 10:51:17 +1000565 vs = -vs;
566 }
567 prom_print_dec(vs);
568 break;
Paul Mackerras9b6b5632005-10-06 12:06:20 +1000569 }
570 }
Daniel Axtens1b855e12015-12-17 19:41:00 +1100571 va_end(args);
Paul Mackerras9b6b5632005-10-06 12:06:20 +1000572}
573
574
Paul Mackerrasa575b802005-10-23 17:23:21 +1000575static unsigned int __init prom_claim(unsigned long virt, unsigned long size,
576 unsigned long align)
577{
Paul Mackerrasa575b802005-10-23 17:23:21 +1000578
Paul Mackerrasa23414b2005-11-10 12:00:55 +1100579 if (align == 0 && (OF_WORKAROUNDS & OF_WA_CLAIM)) {
580 /*
581 * Old OF requires we claim physical and virtual separately
582 * and then map explicitly (assuming virtual mode)
583 */
584 int ret;
585 prom_arg_t result;
586
587 ret = call_prom_ret("call-method", 5, 2, &result,
Anton Blanchard5827d412012-11-26 17:40:03 +0000588 ADDR("claim"), prom.memory,
Paul Mackerrasa23414b2005-11-10 12:00:55 +1100589 align, size, virt);
590 if (ret != 0 || result == -1)
591 return -1;
592 ret = call_prom_ret("call-method", 5, 2, &result,
Anton Blanchard5827d412012-11-26 17:40:03 +0000593 ADDR("claim"), prom.mmumap,
Paul Mackerrasa23414b2005-11-10 12:00:55 +1100594 align, size, virt);
595 if (ret != 0) {
596 call_prom("call-method", 4, 1, ADDR("release"),
Anton Blanchard5827d412012-11-26 17:40:03 +0000597 prom.memory, size, virt);
Paul Mackerrasa23414b2005-11-10 12:00:55 +1100598 return -1;
599 }
600 /* the 0x12 is M (coherence) + PP == read/write */
Paul Mackerrasa575b802005-10-23 17:23:21 +1000601 call_prom("call-method", 6, 1,
Anton Blanchard5827d412012-11-26 17:40:03 +0000602 ADDR("map"), prom.mmumap, 0x12, size, virt, virt);
Paul Mackerrasa23414b2005-11-10 12:00:55 +1100603 return virt;
604 }
605 return call_prom("claim", 3, 1, (prom_arg_t)virt, (prom_arg_t)size,
606 (prom_arg_t)align);
Paul Mackerrasa575b802005-10-23 17:23:21 +1000607}
608
Paul Mackerras9b6b5632005-10-06 12:06:20 +1000609static void __init __attribute__((noreturn)) prom_panic(const char *reason)
610{
Paul Mackerras9b6b5632005-10-06 12:06:20 +1000611 prom_print(reason);
Olaf Heringadd60ef2006-03-23 22:03:57 +0100612 /* Do not call exit because it clears the screen on pmac
613 * it also causes some sort of double-fault on early pmacs */
Anton Blanchard5827d412012-11-26 17:40:03 +0000614 if (of_platform == PLATFORM_POWERMAC)
Olaf Heringadd60ef2006-03-23 22:03:57 +0100615 asm("trap\n");
616
Stephen Rothwell1d9a4732012-03-21 18:23:27 +0000617 /* ToDo: should put up an SRC here on pSeries */
Paul Mackerras9b6b5632005-10-06 12:06:20 +1000618 call_prom("exit", 0, 0);
619
620 for (;;) /* should never get here */
621 ;
622}
623
624
625static int __init prom_next_node(phandle *nodep)
626{
627 phandle node;
628
629 if ((node = *nodep) != 0
630 && (*nodep = call_prom("child", 1, 1, node)) != 0)
631 return 1;
632 if ((*nodep = call_prom("peer", 1, 1, node)) != 0)
633 return 1;
634 for (;;) {
635 if ((node = call_prom("parent", 1, 1, node)) == 0)
636 return 0;
637 if ((*nodep = call_prom("peer", 1, 1, node)) != 0)
638 return 1;
639 }
640}
641
Masahiro Yamada480795a2019-05-14 15:42:14 -0700642static inline int __init prom_getprop(phandle node, const char *pname,
643 void *value, size_t valuelen)
Paul Mackerras9b6b5632005-10-06 12:06:20 +1000644{
645 return call_prom("getprop", 4, 1, node, ADDR(pname),
646 (u32)(unsigned long) value, (u32) valuelen);
647}
648
Masahiro Yamada480795a2019-05-14 15:42:14 -0700649static inline int __init prom_getproplen(phandle node, const char *pname)
Paul Mackerras9b6b5632005-10-06 12:06:20 +1000650{
651 return call_prom("getproplen", 2, 1, node, ADDR(pname));
652}
653
Paul Mackerrasa23414b2005-11-10 12:00:55 +1100654static void add_string(char **str, const char *q)
Paul Mackerras9b6b5632005-10-06 12:06:20 +1000655{
Paul Mackerrasa23414b2005-11-10 12:00:55 +1100656 char *p = *str;
657
658 while (*q)
659 *p++ = *q++;
660 *p++ = ' ';
661 *str = p;
662}
663
664static char *tohex(unsigned int x)
665{
Benjamin Herrenschmidt8ca2d512018-10-15 13:49:57 +1100666 static const char digits[] __initconst = "0123456789abcdef";
667 static char result[9] __prombss;
Paul Mackerrasa23414b2005-11-10 12:00:55 +1100668 int i;
669
670 result[8] = 0;
671 i = 8;
672 do {
673 --i;
674 result[i] = digits[x & 0xf];
675 x >>= 4;
676 } while (x != 0 && i > 0);
677 return &result[i];
678}
679
680static int __init prom_setprop(phandle node, const char *nodename,
681 const char *pname, void *value, size_t valuelen)
682{
683 char cmd[256], *p;
684
685 if (!(OF_WORKAROUNDS & OF_WA_LONGTRAIL))
686 return call_prom("setprop", 4, 1, node, ADDR(pname),
687 (u32)(unsigned long) value, (u32) valuelen);
688
689 /* gah... setprop doesn't work on longtrail, have to use interpret */
690 p = cmd;
691 add_string(&p, "dev");
692 add_string(&p, nodename);
693 add_string(&p, tohex((u32)(unsigned long) value));
694 add_string(&p, tohex(valuelen));
695 add_string(&p, tohex(ADDR(pname)));
Christophe Leroy450e7dd2019-04-26 16:23:28 +0000696 add_string(&p, tohex(prom_strlen(pname)));
Paul Mackerrasa23414b2005-11-10 12:00:55 +1100697 add_string(&p, "property");
698 *p = 0;
699 return call_prom("interpret", 1, 1, (u32)(unsigned long) cmd);
Paul Mackerras9b6b5632005-10-06 12:06:20 +1000700}
701
Anton Blanchard5827d412012-11-26 17:40:03 +0000702/* We can't use the standard versions because of relocation headaches. */
Benjamin Krillcf687872009-07-27 22:02:39 +0000703#define isxdigit(c) (('0' <= (c) && (c) <= '9') \
704 || ('a' <= (c) && (c) <= 'f') \
705 || ('A' <= (c) && (c) <= 'F'))
706
707#define isdigit(c) ('0' <= (c) && (c) <= '9')
708#define islower(c) ('a' <= (c) && (c) <= 'z')
709#define toupper(c) (islower(c) ? ((c) - 'a' + 'A') : (c))
710
Benjamin Herrenschmidt493adff2013-08-07 02:01:38 +1000711static unsigned long prom_strtoul(const char *cp, const char **endp)
Benjamin Krillcf687872009-07-27 22:02:39 +0000712{
713 unsigned long result = 0, base = 10, value;
714
715 if (*cp == '0') {
716 base = 8;
717 cp++;
718 if (toupper(*cp) == 'X') {
719 cp++;
720 base = 16;
721 }
722 }
723
724 while (isxdigit(*cp) &&
725 (value = isdigit(*cp) ? *cp - '0' : toupper(*cp) - 'A' + 10) < base) {
726 result = result * base + value;
727 cp++;
728 }
729
730 if (endp)
731 *endp = cp;
732
733 return result;
734}
735
Benjamin Herrenschmidt493adff2013-08-07 02:01:38 +1000736static unsigned long prom_memparse(const char *ptr, const char **retptr)
Benjamin Krillcf687872009-07-27 22:02:39 +0000737{
738 unsigned long ret = prom_strtoul(ptr, retptr);
739 int shift = 0;
740
741 /*
742 * We can't use a switch here because GCC *may* generate a
743 * jump table which won't work, because we're not running at
744 * the address we're linked at.
745 */
746 if ('G' == **retptr || 'g' == **retptr)
747 shift = 30;
748
749 if ('M' == **retptr || 'm' == **retptr)
750 shift = 20;
751
752 if ('K' == **retptr || 'k' == **retptr)
753 shift = 10;
754
755 if (shift) {
756 ret <<= shift;
757 (*retptr)++;
758 }
759
760 return ret;
761}
762
Paul Mackerras9b6b5632005-10-06 12:06:20 +1000763/*
764 * Early parsing of the command line passed to the kernel, used for
765 * "mem=x" and the options that affect the iommu
766 */
767static void __init early_cmdline_parse(void)
768{
Benjamin Herrenschmidtcc5d0182005-12-13 18:01:21 +1100769 const char *opt;
Benjamin Krillcf687872009-07-27 22:02:39 +0000770
Benjamin Herrenschmidtcc5d0182005-12-13 18:01:21 +1100771 char *p;
Christophe Leroycbe46bd2019-04-26 16:23:27 +0000772 int l = 0;
Paul Mackerras9b6b5632005-10-06 12:06:20 +1000773
Anton Blanchard5827d412012-11-26 17:40:03 +0000774 prom_cmd_line[0] = 0;
775 p = prom_cmd_line;
Chris Packhamd79fbb32019-08-02 10:50:06 +1200776
777 if (!IS_ENABLED(CONFIG_CMDLINE_FORCE) && (long)prom.chosen > 0)
Anton Blanchard5827d412012-11-26 17:40:03 +0000778 l = prom_getprop(prom.chosen, "bootargs", p, COMMAND_LINE_SIZE-1);
Chris Packhamd79fbb32019-08-02 10:50:06 +1200779
780 if (IS_ENABLED(CONFIG_CMDLINE_EXTEND) || l <= 0 || p[0] == '\0')
781 prom_strlcat(prom_cmd_line, " " CONFIG_CMDLINE,
782 sizeof(prom_cmd_line));
783
Anton Blanchard5827d412012-11-26 17:40:03 +0000784 prom_printf("command line: %s\n", prom_cmd_line);
Paul Mackerras9b6b5632005-10-06 12:06:20 +1000785
786#ifdef CONFIG_PPC64
Christophe Leroy450e7dd2019-04-26 16:23:28 +0000787 opt = prom_strstr(prom_cmd_line, "iommu=");
Paul Mackerras9b6b5632005-10-06 12:06:20 +1000788 if (opt) {
789 prom_printf("iommu opt is: %s\n", opt);
790 opt += 6;
791 while (*opt && *opt == ' ')
792 opt++;
Christophe Leroy450e7dd2019-04-26 16:23:28 +0000793 if (!prom_strncmp(opt, "off", 3))
Anton Blanchard5827d412012-11-26 17:40:03 +0000794 prom_iommu_off = 1;
Christophe Leroy450e7dd2019-04-26 16:23:28 +0000795 else if (!prom_strncmp(opt, "force", 5))
Anton Blanchard5827d412012-11-26 17:40:03 +0000796 prom_iommu_force_on = 1;
Paul Mackerras9b6b5632005-10-06 12:06:20 +1000797 }
798#endif
Christophe Leroy450e7dd2019-04-26 16:23:28 +0000799 opt = prom_strstr(prom_cmd_line, "mem=");
Benjamin Krillcf687872009-07-27 22:02:39 +0000800 if (opt) {
801 opt += 4;
Anton Blanchard5827d412012-11-26 17:40:03 +0000802 prom_memory_limit = prom_memparse(opt, (const char **)&opt);
Benjamin Krillcf687872009-07-27 22:02:39 +0000803#ifdef CONFIG_PPC64
804 /* Align to 16 MB == size of ppc64 large page */
Anton Blanchard5827d412012-11-26 17:40:03 +0000805 prom_memory_limit = ALIGN(prom_memory_limit, 0x1000000);
Benjamin Krillcf687872009-07-27 22:02:39 +0000806#endif
807 }
Suraj Jitindar Singh014d02c2017-02-28 17:03:48 +1100808
Benjamin Herrenschmidtc8860872018-10-15 13:49:54 +1100809#ifdef CONFIG_PPC_PSERIES
810 prom_radix_disable = !IS_ENABLED(CONFIG_PPC_RADIX_MMU_DEFAULT);
Christophe Leroy450e7dd2019-04-26 16:23:28 +0000811 opt = prom_strstr(prom_cmd_line, "disable_radix");
Suraj Jitindar Singh014d02c2017-02-28 17:03:48 +1100812 if (opt) {
Aneesh Kumar K.V7a22d632018-03-30 17:39:02 +0530813 opt += 13;
814 if (*opt && *opt == '=') {
815 bool val;
816
Christophe Leroy450e7dd2019-04-26 16:23:28 +0000817 if (prom_strtobool(++opt, &val))
Aneesh Kumar K.V7a22d632018-03-30 17:39:02 +0530818 prom_radix_disable = false;
819 else
820 prom_radix_disable = val;
821 } else
822 prom_radix_disable = true;
Suraj Jitindar Singh014d02c2017-02-28 17:03:48 +1100823 }
Aneesh Kumar K.V7a22d632018-03-30 17:39:02 +0530824 if (prom_radix_disable)
825 prom_debug("Radix disabled from cmdline\n");
Greg Kurza3bf9fb2019-05-15 12:05:01 +0200826
Aneesh Kumar K.Vbf6b7662020-07-27 14:29:08 +0530827 opt = prom_strstr(prom_cmd_line, "radix_hcall_invalidate=on");
828 if (opt) {
829 prom_radix_gtse_disable = true;
830 prom_debug("Radix GTSE disabled from cmdline\n");
831 }
832
Greg Kurza3bf9fb2019-05-15 12:05:01 +0200833 opt = prom_strstr(prom_cmd_line, "xive=off");
834 if (opt) {
835 prom_xive_disable = true;
836 prom_debug("XIVE disabled from cmdline\n");
837 }
Benjamin Herrenschmidtc8860872018-10-15 13:49:54 +1100838#endif /* CONFIG_PPC_PSERIES */
Ram Pai6a9c9302019-08-19 23:13:14 -0300839
840#ifdef CONFIG_PPC_SVM
841 opt = prom_strstr(prom_cmd_line, "svm=");
842 if (opt) {
843 bool val;
844
845 opt += sizeof("svm=") - 1;
846 if (!prom_strtobool(opt, &val))
847 prom_svm_enable = val;
848 }
849#endif /* CONFIG_PPC_SVM */
Paul Mackerras9b6b5632005-10-06 12:06:20 +1000850}
851
Benjamin Herrenschmidt11fdb302018-10-15 13:49:53 +1100852#ifdef CONFIG_PPC_PSERIES
Paul Mackerras9b6b5632005-10-06 12:06:20 +1000853/*
Nathan Fontenot530b5e12013-04-24 05:53:10 +0000854 * The architecture vector has an array of PVR mask/value pairs,
855 * followed by # option vectors - 1, followed by the option vectors.
856 *
857 * See prom.h for the definition of the bits specified in the
858 * architecture vector.
Paul Mackerrasf709bfa2006-04-28 16:28:35 +1000859 */
Paul Mackerrasf709bfa2006-04-28 16:28:35 +1000860
Michael Ellermane8a4fd02014-08-29 17:01:43 +1000861/* Firmware expects the value to be n - 1, where n is the # of vectors */
862#define NUM_VECTORS(n) ((n) - 1)
863
864/*
865 * Firmware expects 1 + n - 2, where n is the length of the option vector in
866 * bytes. The 1 accounts for the length byte itself, the - 2 .. ?
867 */
868#define VECTOR_LENGTH(n) (1 + (n) - 2)
869
Michael Ellermand03d1d62016-11-18 23:15:41 +1100870struct option_vector1 {
871 u8 byte1;
872 u8 arch_versions;
Paul Mackerrascc3d2942017-01-30 21:21:36 +1100873 u8 arch_versions3;
Michael Ellermand03d1d62016-11-18 23:15:41 +1100874} __packed;
875
876struct option_vector2 {
877 u8 byte1;
878 __be16 reserved;
879 __be32 real_base;
880 __be32 real_size;
881 __be32 virt_base;
882 __be32 virt_size;
883 __be32 load_base;
884 __be32 min_rma;
885 __be32 min_load;
886 u8 min_rma_percent;
887 u8 max_pft_size;
888} __packed;
889
890struct option_vector3 {
891 u8 byte1;
892 u8 byte2;
893} __packed;
894
895struct option_vector4 {
896 u8 byte1;
897 u8 min_vp_cap;
898} __packed;
899
900struct option_vector5 {
901 u8 byte1;
902 u8 byte2;
903 u8 byte3;
904 u8 cmo;
905 u8 associativity;
906 u8 bin_opts;
907 u8 micro_checkpoint;
908 u8 reserved0;
909 __be32 max_cpus;
910 __be16 papr_level;
911 __be16 reserved1;
912 u8 platform_facilities;
913 u8 reserved2;
914 __be16 reserved3;
915 u8 subprocessors;
Paul Mackerrascc3d2942017-01-30 21:21:36 +1100916 u8 byte22;
917 u8 intarch;
918 u8 mmu;
Suraj Jitindar Singh014d02c2017-02-28 17:03:48 +1100919 u8 hash_ext;
920 u8 radix_ext;
Michael Ellermand03d1d62016-11-18 23:15:41 +1100921} __packed;
922
923struct option_vector6 {
924 u8 reserved;
925 u8 secondary_pteg;
926 u8 os_name;
927} __packed;
928
Michael Ellerman76ffb572016-11-18 23:15:42 +1100929struct ibm_arch_vec {
Alistair Popplea3ea40d2020-05-21 11:43:41 +1000930 struct { u32 mask, val; } pvrs[14];
Michael Ellerman76ffb572016-11-18 23:15:42 +1100931
932 u8 num_vectors;
933
934 u8 vec1_len;
935 struct option_vector1 vec1;
936
937 u8 vec2_len;
938 struct option_vector2 vec2;
939
940 u8 vec3_len;
941 struct option_vector3 vec3;
942
943 u8 vec4_len;
944 struct option_vector4 vec4;
945
946 u8 vec5_len;
947 struct option_vector5 vec5;
948
949 u8 vec6_len;
950 struct option_vector6 vec6;
951} __packed;
952
Benjamin Herrenschmidtd00e34b2018-10-15 13:49:56 +1100953static const struct ibm_arch_vec ibm_architecture_vec_template __initconst = {
Michael Ellerman76ffb572016-11-18 23:15:42 +1100954 .pvrs = {
955 {
956 .mask = cpu_to_be32(0xfffe0000), /* POWER5/POWER5+ */
957 .val = cpu_to_be32(0x003a0000),
958 },
959 {
960 .mask = cpu_to_be32(0xffff0000), /* POWER6 */
961 .val = cpu_to_be32(0x003e0000),
962 },
963 {
964 .mask = cpu_to_be32(0xffff0000), /* POWER7 */
965 .val = cpu_to_be32(0x003f0000),
966 },
967 {
968 .mask = cpu_to_be32(0xffff0000), /* POWER8E */
969 .val = cpu_to_be32(0x004b0000),
970 },
971 {
972 .mask = cpu_to_be32(0xffff0000), /* POWER8NVL */
973 .val = cpu_to_be32(0x004c0000),
974 },
975 {
976 .mask = cpu_to_be32(0xffff0000), /* POWER8 */
977 .val = cpu_to_be32(0x004d0000),
978 },
979 {
Paul Mackerrascc3d2942017-01-30 21:21:36 +1100980 .mask = cpu_to_be32(0xffff0000), /* POWER9 */
981 .val = cpu_to_be32(0x004e0000),
982 },
983 {
Alistair Popplea3ea40d2020-05-21 11:43:41 +1000984 .mask = cpu_to_be32(0xffff0000), /* POWER10 */
985 .val = cpu_to_be32(0x00800000),
986 },
987 {
988 .mask = cpu_to_be32(0xffffffff), /* all 3.1-compliant */
989 .val = cpu_to_be32(0x0f000006),
990 },
991 {
Paul Mackerrascc3d2942017-01-30 21:21:36 +1100992 .mask = cpu_to_be32(0xffffffff), /* all 3.00-compliant */
993 .val = cpu_to_be32(0x0f000005),
994 },
995 {
Michael Ellerman76ffb572016-11-18 23:15:42 +1100996 .mask = cpu_to_be32(0xffffffff), /* all 2.07-compliant */
997 .val = cpu_to_be32(0x0f000004),
998 },
999 {
1000 .mask = cpu_to_be32(0xffffffff), /* all 2.06-compliant */
1001 .val = cpu_to_be32(0x0f000003),
1002 },
1003 {
1004 .mask = cpu_to_be32(0xffffffff), /* all 2.05-compliant */
1005 .val = cpu_to_be32(0x0f000002),
1006 },
1007 {
1008 .mask = cpu_to_be32(0xfffffffe), /* all 2.04-compliant and earlier */
1009 .val = cpu_to_be32(0x0f000001),
1010 },
1011 },
1012
1013 .num_vectors = NUM_VECTORS(6),
1014
1015 .vec1_len = VECTOR_LENGTH(sizeof(struct option_vector1)),
1016 .vec1 = {
1017 .byte1 = 0,
1018 .arch_versions = OV1_PPC_2_00 | OV1_PPC_2_01 | OV1_PPC_2_02 | OV1_PPC_2_03 |
1019 OV1_PPC_2_04 | OV1_PPC_2_05 | OV1_PPC_2_06 | OV1_PPC_2_07,
Alistair Popplea3ea40d2020-05-21 11:43:41 +10001020 .arch_versions3 = OV1_PPC_3_00 | OV1_PPC_3_1,
Michael Ellerman76ffb572016-11-18 23:15:42 +11001021 },
1022
1023 .vec2_len = VECTOR_LENGTH(sizeof(struct option_vector2)),
1024 /* option vector 2: Open Firmware options supported */
1025 .vec2 = {
1026 .byte1 = OV2_REAL_MODE,
1027 .reserved = 0,
1028 .real_base = cpu_to_be32(0xffffffff),
1029 .real_size = cpu_to_be32(0xffffffff),
1030 .virt_base = cpu_to_be32(0xffffffff),
1031 .virt_size = cpu_to_be32(0xffffffff),
1032 .load_base = cpu_to_be32(0xffffffff),
Sukadev Bhattiprolu687da8f2017-03-27 19:43:14 -04001033 .min_rma = cpu_to_be32(512), /* 512MB min RMA */
Michael Ellerman76ffb572016-11-18 23:15:42 +11001034 .min_load = cpu_to_be32(0xffffffff), /* full client load */
1035 .min_rma_percent = 0, /* min RMA percentage of total RAM */
1036 .max_pft_size = 48, /* max log_2(hash table size) */
1037 },
1038
1039 .vec3_len = VECTOR_LENGTH(sizeof(struct option_vector3)),
1040 /* option vector 3: processor options supported */
1041 .vec3 = {
1042 .byte1 = 0, /* don't ignore, don't halt */
1043 .byte2 = OV3_FP | OV3_VMX | OV3_DFP,
1044 },
1045
1046 .vec4_len = VECTOR_LENGTH(sizeof(struct option_vector4)),
1047 /* option vector 4: IBM PAPR implementation */
1048 .vec4 = {
1049 .byte1 = 0, /* don't halt */
1050 .min_vp_cap = OV4_MIN_ENT_CAP, /* minimum VP entitled capacity */
1051 },
1052
1053 .vec5_len = VECTOR_LENGTH(sizeof(struct option_vector5)),
1054 /* option vector 5: PAPR/OF options */
1055 .vec5 = {
1056 .byte1 = 0, /* don't ignore, don't halt */
1057 .byte2 = OV5_FEAT(OV5_LPAR) | OV5_FEAT(OV5_SPLPAR) | OV5_FEAT(OV5_LARGE_PAGES) |
1058 OV5_FEAT(OV5_DRCONF_MEMORY) | OV5_FEAT(OV5_DONATE_DEDICATE_CPU) |
1059#ifdef CONFIG_PCI_MSI
1060 /* PCIe/MSI support. Without MSI full PCIe is not supported */
1061 OV5_FEAT(OV5_MSI),
1062#else
1063 0,
1064#endif
1065 .byte3 = 0,
1066 .cmo =
1067#ifdef CONFIG_PPC_SMLPAR
1068 OV5_FEAT(OV5_CMO) | OV5_FEAT(OV5_XCMO),
1069#else
1070 0,
1071#endif
1072 .associativity = OV5_FEAT(OV5_TYPE1_AFFINITY) | OV5_FEAT(OV5_PRRN),
Michael Roth3dbbaf22017-02-20 19:12:18 -06001073 .bin_opts = OV5_FEAT(OV5_RESIZE_HPT) | OV5_FEAT(OV5_HP_EVT),
Michael Ellerman76ffb572016-11-18 23:15:42 +11001074 .micro_checkpoint = 0,
1075 .reserved0 = 0,
1076 .max_cpus = cpu_to_be32(NR_CPUS), /* number of cores supported */
1077 .papr_level = 0,
1078 .reserved1 = 0,
1079 .platform_facilities = OV5_FEAT(OV5_PFO_HW_RNG) | OV5_FEAT(OV5_PFO_HW_ENCR) | OV5_FEAT(OV5_PFO_HW_842),
1080 .reserved2 = 0,
1081 .reserved3 = 0,
1082 .subprocessors = 1,
Tyrel Datwyler0a87ccd2019-11-10 23:21:37 -06001083 .byte22 = OV5_FEAT(OV5_DRMEM_V2) | OV5_FEAT(OV5_DRC_INFO),
Paul Mackerrascc3d2942017-01-30 21:21:36 +11001084 .intarch = 0,
Suraj Jitindar Singh014d02c2017-02-28 17:03:48 +11001085 .mmu = 0,
1086 .hash_ext = 0,
1087 .radix_ext = 0,
Michael Ellerman76ffb572016-11-18 23:15:42 +11001088 },
1089
1090 /* option vector 6: IBM PAPR hints */
1091 .vec6_len = VECTOR_LENGTH(sizeof(struct option_vector6)),
1092 .vec6 = {
1093 .reserved = 0,
1094 .secondary_pteg = 0,
1095 .os_name = OV6_LINUX,
1096 },
1097};
1098
Benjamin Herrenschmidta614f522018-10-15 13:49:55 +11001099static struct ibm_arch_vec __prombss ibm_architecture_vec ____cacheline_aligned;
1100
Benjamin Herrenschmidt493adff2013-08-07 02:01:38 +10001101/* Old method - ELF header with PT_NOTE sections only works on BE */
1102#ifdef __BIG_ENDIAN__
Benjamin Herrenschmidt30c69ca2018-05-31 14:33:40 +10001103static const struct fake_elf {
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001104 Elf32_Ehdr elfhdr;
1105 Elf32_Phdr phdr[2];
1106 struct chrpnote {
1107 u32 namesz;
1108 u32 descsz;
1109 u32 type;
1110 char name[8]; /* "PowerPC" */
1111 struct chrpdesc {
1112 u32 real_mode;
1113 u32 real_base;
1114 u32 real_size;
1115 u32 virt_base;
1116 u32 virt_size;
1117 u32 load_base;
1118 } chrpdesc;
1119 } chrpnote;
1120 struct rpanote {
1121 u32 namesz;
1122 u32 descsz;
1123 u32 type;
1124 char name[24]; /* "IBM,RPA-Client-Config" */
1125 struct rpadesc {
1126 u32 lpar_affinity;
1127 u32 min_rmo_size;
1128 u32 min_rmo_percent;
1129 u32 max_pft_size;
1130 u32 splpar;
1131 u32 min_load;
1132 u32 new_mem_def;
1133 u32 ignore_me;
1134 } rpadesc;
1135 } rpanote;
Benjamin Herrenschmidtd00e34b2018-10-15 13:49:56 +11001136} fake_elf __initconst = {
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001137 .elfhdr = {
1138 .e_ident = { 0x7f, 'E', 'L', 'F',
1139 ELFCLASS32, ELFDATA2MSB, EV_CURRENT },
1140 .e_type = ET_EXEC, /* yeah right */
1141 .e_machine = EM_PPC,
1142 .e_version = EV_CURRENT,
1143 .e_phoff = offsetof(struct fake_elf, phdr),
1144 .e_phentsize = sizeof(Elf32_Phdr),
1145 .e_phnum = 2
1146 },
1147 .phdr = {
1148 [0] = {
1149 .p_type = PT_NOTE,
1150 .p_offset = offsetof(struct fake_elf, chrpnote),
1151 .p_filesz = sizeof(struct chrpnote)
1152 }, [1] = {
1153 .p_type = PT_NOTE,
1154 .p_offset = offsetof(struct fake_elf, rpanote),
1155 .p_filesz = sizeof(struct rpanote)
1156 }
1157 },
1158 .chrpnote = {
1159 .namesz = sizeof("PowerPC"),
1160 .descsz = sizeof(struct chrpdesc),
1161 .type = 0x1275,
1162 .name = "PowerPC",
1163 .chrpdesc = {
1164 .real_mode = ~0U, /* ~0 means "don't care" */
1165 .real_base = ~0U,
1166 .real_size = ~0U,
1167 .virt_base = ~0U,
1168 .virt_size = ~0U,
1169 .load_base = ~0U
1170 },
1171 },
1172 .rpanote = {
1173 .namesz = sizeof("IBM,RPA-Client-Config"),
1174 .descsz = sizeof(struct rpadesc),
1175 .type = 0x12759999,
1176 .name = "IBM,RPA-Client-Config",
1177 .rpadesc = {
Paul Mackerras5663a122008-10-31 22:27:17 +11001178 .lpar_affinity = 0,
1179 .min_rmo_size = 64, /* in megabytes */
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001180 .min_rmo_percent = 0,
Paul Mackerras5663a122008-10-31 22:27:17 +11001181 .max_pft_size = 48, /* 2^48 bytes max PFT size */
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001182 .splpar = 1,
1183 .min_load = ~0U,
Paul Mackerras5663a122008-10-31 22:27:17 +11001184 .new_mem_def = 0
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001185 }
1186 }
1187};
Benjamin Herrenschmidt493adff2013-08-07 02:01:38 +10001188#endif /* __BIG_ENDIAN__ */
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001189
Benjamin Herrenschmidtefec9592010-02-04 14:33:54 +11001190static int __init prom_count_smt_threads(void)
1191{
1192 phandle node;
1193 char type[64];
1194 unsigned int plen;
1195
1196 /* Pick up th first CPU node we can find */
1197 for (node = 0; prom_next_node(&node); ) {
1198 type[0] = 0;
1199 prom_getprop(node, "device_type", type, sizeof(type));
1200
Christophe Leroy450e7dd2019-04-26 16:23:28 +00001201 if (prom_strcmp(type, "cpu"))
Benjamin Herrenschmidtefec9592010-02-04 14:33:54 +11001202 continue;
1203 /*
1204 * There is an entry for each smt thread, each entry being
1205 * 4 bytes long. All cpus should have the same number of
1206 * smt threads, so return after finding the first.
1207 */
1208 plen = prom_getproplen(node, "ibm,ppc-interrupt-server#s");
1209 if (plen == PROM_ERROR)
1210 break;
1211 plen >>= 2;
Michael Neuling2c48a7d2010-07-27 18:26:21 +00001212 prom_debug("Found %lu smt threads per core\n", (unsigned long)plen);
Benjamin Herrenschmidtefec9592010-02-04 14:33:54 +11001213
1214 /* Sanity check */
1215 if (plen < 1 || plen > 64) {
Michael Neuling2c48a7d2010-07-27 18:26:21 +00001216 prom_printf("Threads per core %lu out of bounds, assuming 1\n",
Benjamin Herrenschmidtefec9592010-02-04 14:33:54 +11001217 (unsigned long)plen);
1218 return 1;
1219 }
1220 return plen;
1221 }
1222 prom_debug("No threads found, assuming 1 per core\n");
1223
1224 return 1;
1225
1226}
1227
Suraj Jitindar Singh014d02c2017-02-28 17:03:48 +11001228static void __init prom_parse_mmu_model(u8 val,
1229 struct platform_support *support)
1230{
1231 switch (val) {
1232 case OV5_FEAT(OV5_MMU_DYNAMIC):
1233 case OV5_FEAT(OV5_MMU_EITHER): /* Either Available */
1234 prom_debug("MMU - either supported\n");
1235 support->radix_mmu = !prom_radix_disable;
1236 support->hash_mmu = true;
1237 break;
1238 case OV5_FEAT(OV5_MMU_RADIX): /* Only Radix */
1239 prom_debug("MMU - radix only\n");
1240 if (prom_radix_disable) {
1241 /*
1242 * If we __have__ to do radix, we're better off ignoring
1243 * the command line rather than not booting.
1244 */
1245 prom_printf("WARNING: Ignoring cmdline option disable_radix\n");
1246 }
1247 support->radix_mmu = true;
1248 break;
1249 case OV5_FEAT(OV5_MMU_HASH):
1250 prom_debug("MMU - hash only\n");
1251 support->hash_mmu = true;
1252 break;
1253 default:
1254 prom_debug("Unknown mmu support option: 0x%x\n", val);
1255 break;
1256 }
1257}
1258
Cédric Le Goaterac5e5a52017-08-30 21:46:16 +02001259static void __init prom_parse_xive_model(u8 val,
1260 struct platform_support *support)
1261{
1262 switch (val) {
1263 case OV5_FEAT(OV5_XIVE_EITHER): /* Either Available */
1264 prom_debug("XIVE - either mode supported\n");
Greg Kurza3bf9fb2019-05-15 12:05:01 +02001265 support->xive = !prom_xive_disable;
Cédric Le Goaterac5e5a52017-08-30 21:46:16 +02001266 break;
1267 case OV5_FEAT(OV5_XIVE_EXPLOIT): /* Only Exploitation mode */
1268 prom_debug("XIVE - exploitation mode supported\n");
Greg Kurza3bf9fb2019-05-15 12:05:01 +02001269 if (prom_xive_disable) {
1270 /*
1271 * If we __have__ to do XIVE, we're better off ignoring
1272 * the command line rather than not booting.
1273 */
1274 prom_printf("WARNING: Ignoring cmdline option xive=off\n");
1275 }
Cédric Le Goaterac5e5a52017-08-30 21:46:16 +02001276 support->xive = true;
1277 break;
1278 case OV5_FEAT(OV5_XIVE_LEGACY): /* Only Legacy mode */
1279 prom_debug("XIVE - legacy mode supported\n");
1280 break;
1281 default:
1282 prom_debug("Unknown xive support option: 0x%x\n", val);
1283 break;
1284 }
1285}
1286
Suraj Jitindar Singh014d02c2017-02-28 17:03:48 +11001287static void __init prom_parse_platform_support(u8 index, u8 val,
1288 struct platform_support *support)
1289{
1290 switch (index) {
1291 case OV5_INDX(OV5_MMU_SUPPORT): /* MMU Model */
1292 prom_parse_mmu_model(val & OV5_FEAT(OV5_MMU_SUPPORT), support);
1293 break;
1294 case OV5_INDX(OV5_RADIX_GTSE): /* Radix Extensions */
Aneesh Kumar K.Vbf6b7662020-07-27 14:29:08 +05301295 if (val & OV5_FEAT(OV5_RADIX_GTSE))
1296 support->radix_gtse = !prom_radix_gtse_disable;
Suraj Jitindar Singh014d02c2017-02-28 17:03:48 +11001297 break;
Cédric Le Goaterac5e5a52017-08-30 21:46:16 +02001298 case OV5_INDX(OV5_XIVE_SUPPORT): /* Interrupt mode */
1299 prom_parse_xive_model(val & OV5_FEAT(OV5_XIVE_SUPPORT),
1300 support);
1301 break;
Suraj Jitindar Singh014d02c2017-02-28 17:03:48 +11001302 }
1303}
1304
1305static void __init prom_check_platform_support(void)
1306{
1307 struct platform_support supported = {
1308 .hash_mmu = false,
1309 .radix_mmu = false,
Cédric Le Goaterac5e5a52017-08-30 21:46:16 +02001310 .radix_gtse = false,
1311 .xive = false
Suraj Jitindar Singh014d02c2017-02-28 17:03:48 +11001312 };
1313 int prop_len = prom_getproplen(prom.chosen,
1314 "ibm,arch-vec-5-platform-support");
Benjamin Herrenschmidta614f522018-10-15 13:49:55 +11001315
Christophe Leroyadcf5912019-04-26 16:23:29 +00001316 /*
1317 * First copy the architecture vec template
1318 *
1319 * use memcpy() instead of *vec = *vec_template so that GCC replaces it
1320 * by __memcpy() when KASAN is active
1321 */
1322 memcpy(&ibm_architecture_vec, &ibm_architecture_vec_template,
1323 sizeof(ibm_architecture_vec));
Benjamin Herrenschmidta614f522018-10-15 13:49:55 +11001324
Suraj Jitindar Singh014d02c2017-02-28 17:03:48 +11001325 if (prop_len > 1) {
1326 int i;
Suraj Jitindar Singhab912392018-09-05 12:09:50 +10001327 u8 vec[8];
Suraj Jitindar Singh014d02c2017-02-28 17:03:48 +11001328 prom_debug("Found ibm,arch-vec-5-platform-support, len: %d\n",
1329 prop_len);
Suraj Jitindar Singhab912392018-09-05 12:09:50 +10001330 if (prop_len > sizeof(vec))
1331 prom_printf("WARNING: ibm,arch-vec-5-platform-support longer than expected (len: %d)\n",
1332 prop_len);
Suraj Jitindar Singh014d02c2017-02-28 17:03:48 +11001333 prom_getprop(prom.chosen, "ibm,arch-vec-5-platform-support",
1334 &vec, sizeof(vec));
Suraj Jitindar Singhab912392018-09-05 12:09:50 +10001335 for (i = 0; i < sizeof(vec); i += 2) {
Suraj Jitindar Singh014d02c2017-02-28 17:03:48 +11001336 prom_debug("%d: index = 0x%x val = 0x%x\n", i / 2
1337 , vec[i]
1338 , vec[i + 1]);
1339 prom_parse_platform_support(vec[i], vec[i + 1],
1340 &supported);
1341 }
1342 }
1343
Bharata B Rao029ab302020-07-03 11:06:06 +05301344 if (supported.radix_mmu && IS_ENABLED(CONFIG_PPC_RADIX_MMU)) {
1345 /* Radix preferred - Check if GTSE is also supported */
1346 prom_debug("Asking for radix\n");
Suraj Jitindar Singh014d02c2017-02-28 17:03:48 +11001347 ibm_architecture_vec.vec5.mmu = OV5_FEAT(OV5_MMU_RADIX);
Bharata B Rao029ab302020-07-03 11:06:06 +05301348 if (supported.radix_gtse)
1349 ibm_architecture_vec.vec5.radix_ext =
1350 OV5_FEAT(OV5_RADIX_GTSE);
1351 else
1352 prom_debug("Radix GTSE isn't supported\n");
Suraj Jitindar Singh014d02c2017-02-28 17:03:48 +11001353 } else if (supported.hash_mmu) {
1354 /* Default to hash mmu (if we can) */
1355 prom_debug("Asking for hash\n");
1356 ibm_architecture_vec.vec5.mmu = OV5_FEAT(OV5_MMU_HASH);
1357 } else {
1358 /* We're probably on a legacy hypervisor */
1359 prom_debug("Assuming legacy hash support\n");
1360 }
Cédric Le Goaterac5e5a52017-08-30 21:46:16 +02001361
1362 if (supported.xive) {
1363 prom_debug("Asking for XIVE\n");
1364 ibm_architecture_vec.vec5.intarch = OV5_FEAT(OV5_XIVE_EXPLOIT);
1365 }
Suraj Jitindar Singh014d02c2017-02-28 17:03:48 +11001366}
Benjamin Herrenschmidtefec9592010-02-04 14:33:54 +11001367
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001368static void __init prom_send_capabilities(void)
1369{
Benjamin Herrenschmidt493adff2013-08-07 02:01:38 +10001370 ihandle root;
Paul Mackerrasf709bfa2006-04-28 16:28:35 +10001371 prom_arg_t ret;
Laurent Dufourdbd0c5d2013-09-17 11:52:48 +02001372 u32 cores;
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001373
Suraj Jitindar Singh014d02c2017-02-28 17:03:48 +11001374 /* Check ibm,arch-vec-5-platform-support and fixup vec5 if required */
1375 prom_check_platform_support();
1376
Paul Mackerrasf709bfa2006-04-28 16:28:35 +10001377 root = call_prom("open", 1, 1, ADDR("/"));
1378 if (root != 0) {
Benjamin Herrenschmidtefec9592010-02-04 14:33:54 +11001379 /* We need to tell the FW about the number of cores we support.
1380 *
1381 * To do that, we count the number of threads on the first core
1382 * (we assume this is the same for all cores) and use it to
1383 * divide NR_CPUS.
1384 */
Laurent Dufourdbd0c5d2013-09-17 11:52:48 +02001385
Michael Ellerman76ffb572016-11-18 23:15:42 +11001386 cores = DIV_ROUND_UP(NR_CPUS, prom_count_smt_threads());
Mathieu Malaterreeae5f702018-04-06 22:12:19 +02001387 prom_printf("Max number of cores passed to firmware: %u (NR_CPUS = %d)\n",
Michael Ellerman76ffb572016-11-18 23:15:42 +11001388 cores, NR_CPUS);
1389
1390 ibm_architecture_vec.vec5.max_cpus = cpu_to_be32(cores);
Benjamin Herrenschmidtefec9592010-02-04 14:33:54 +11001391
Paul Mackerrasf709bfa2006-04-28 16:28:35 +10001392 /* try calling the ibm,client-architecture-support method */
Anton Blanchard049d0492009-09-21 20:47:39 +00001393 prom_printf("Calling ibm,client-architecture-support...");
Paul Mackerrasf709bfa2006-04-28 16:28:35 +10001394 if (call_prom_ret("call-method", 3, 2, &ret,
1395 ADDR("ibm,client-architecture-support"),
Benjamin Herrenschmidt33b74972006-06-07 12:01:32 +10001396 root,
Michael Ellerman76ffb572016-11-18 23:15:42 +11001397 ADDR(&ibm_architecture_vec)) == 0) {
Paul Mackerrasf709bfa2006-04-28 16:28:35 +10001398 /* the call exists... */
1399 if (ret)
Anton Blanchard4da727a2009-03-31 20:06:14 +00001400 prom_printf("\nWARNING: ibm,client-architecture"
Paul Mackerrasf709bfa2006-04-28 16:28:35 +10001401 "-support call FAILED!\n");
1402 call_prom("close", 1, 0, root);
Anton Blanchard4da727a2009-03-31 20:06:14 +00001403 prom_printf(" done\n");
Paul Mackerrasf709bfa2006-04-28 16:28:35 +10001404 return;
1405 }
1406 call_prom("close", 1, 0, root);
Anton Blanchard049d0492009-09-21 20:47:39 +00001407 prom_printf(" not implemented\n");
Paul Mackerrasf709bfa2006-04-28 16:28:35 +10001408 }
1409
Benjamin Herrenschmidt493adff2013-08-07 02:01:38 +10001410#ifdef __BIG_ENDIAN__
1411 {
1412 ihandle elfloader;
1413
1414 /* no ibm,client-architecture-support call, try the old way */
1415 elfloader = call_prom("open", 1, 1,
1416 ADDR("/packages/elf-loader"));
1417 if (elfloader == 0) {
1418 prom_printf("couldn't open /packages/elf-loader\n");
1419 return;
1420 }
1421 call_prom("call-method", 3, 1, ADDR("process-elf-header"),
1422 elfloader, ADDR(&fake_elf));
1423 call_prom("close", 1, 0, elfloader);
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001424 }
Benjamin Herrenschmidt493adff2013-08-07 02:01:38 +10001425#endif /* __BIG_ENDIAN__ */
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001426}
Benjamin Herrenschmidt11fdb302018-10-15 13:49:53 +11001427#endif /* CONFIG_PPC_PSERIES */
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001428
1429/*
1430 * Memory allocation strategy... our layout is normally:
1431 *
1432 * at 14Mb or more we have vmlinux, then a gap and initrd. In some
1433 * rare cases, initrd might end up being before the kernel though.
1434 * We assume this won't override the final kernel at 0, we have no
1435 * provision to handle that in this version, but it should hopefully
1436 * never happen.
1437 *
1438 * alloc_top is set to the top of RMO, eventually shrink down if the
1439 * TCEs overlap
1440 *
1441 * alloc_bottom is set to the top of kernel/initrd
1442 *
1443 * from there, allocations are done this way : rtas is allocated
1444 * topmost, and the device-tree is allocated from the bottom. We try
1445 * to grow the device-tree allocation as we progress. If we can't,
1446 * then we fail, we don't currently have a facility to restart
1447 * elsewhere, but that shouldn't be necessary.
1448 *
1449 * Note that calls to reserve_mem have to be done explicitly, memory
1450 * allocated with either alloc_up or alloc_down isn't automatically
1451 * reserved.
1452 */
1453
1454
1455/*
1456 * Allocates memory in the RMO upward from the kernel/initrd
1457 *
1458 * When align is 0, this is a special case, it means to allocate in place
1459 * at the current location of alloc_bottom or fail (that is basically
1460 * extending the previous allocation). Used for the device-tree flattening
1461 */
1462static unsigned long __init alloc_up(unsigned long size, unsigned long align)
1463{
Anton Blanchard5827d412012-11-26 17:40:03 +00001464 unsigned long base = alloc_bottom;
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001465 unsigned long addr = 0;
1466
Paul Mackerrasc49888202005-10-26 21:52:53 +10001467 if (align)
Christophe Leroyb7115312020-04-20 18:36:36 +00001468 base = ALIGN(base, align);
Mathieu Malaterreeae5f702018-04-06 22:12:19 +02001469 prom_debug("%s(%lx, %lx)\n", __func__, size, align);
Anton Blanchard5827d412012-11-26 17:40:03 +00001470 if (ram_top == 0)
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001471 prom_panic("alloc_up() called with mem not initialized\n");
1472
1473 if (align)
Christophe Leroyb7115312020-04-20 18:36:36 +00001474 base = ALIGN(alloc_bottom, align);
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001475 else
Anton Blanchard5827d412012-11-26 17:40:03 +00001476 base = alloc_bottom;
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001477
Anton Blanchard5827d412012-11-26 17:40:03 +00001478 for(; (base + size) <= alloc_top;
Christophe Leroyb7115312020-04-20 18:36:36 +00001479 base = ALIGN(base + 0x100000, align)) {
Mathieu Malaterreeae5f702018-04-06 22:12:19 +02001480 prom_debug(" trying: 0x%lx\n\r", base);
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001481 addr = (unsigned long)prom_claim(base, size, 0);
Paul Mackerrasc49888202005-10-26 21:52:53 +10001482 if (addr != PROM_ERROR && addr != 0)
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001483 break;
1484 addr = 0;
1485 if (align == 0)
1486 break;
1487 }
1488 if (addr == 0)
1489 return 0;
Anton Blanchard5827d412012-11-26 17:40:03 +00001490 alloc_bottom = addr + size;
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001491
Mathieu Malaterreeae5f702018-04-06 22:12:19 +02001492 prom_debug(" -> %lx\n", addr);
1493 prom_debug(" alloc_bottom : %lx\n", alloc_bottom);
1494 prom_debug(" alloc_top : %lx\n", alloc_top);
1495 prom_debug(" alloc_top_hi : %lx\n", alloc_top_high);
1496 prom_debug(" rmo_top : %lx\n", rmo_top);
1497 prom_debug(" ram_top : %lx\n", ram_top);
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001498
1499 return addr;
1500}
1501
1502/*
1503 * Allocates memory downward, either from top of RMO, or if highmem
1504 * is set, from the top of RAM. Note that this one doesn't handle
1505 * failures. It does claim memory if highmem is not set.
1506 */
1507static unsigned long __init alloc_down(unsigned long size, unsigned long align,
1508 int highmem)
1509{
1510 unsigned long base, addr = 0;
1511
Mathieu Malaterreeae5f702018-04-06 22:12:19 +02001512 prom_debug("%s(%lx, %lx, %s)\n", __func__, size, align,
Anton Blanchard5827d412012-11-26 17:40:03 +00001513 highmem ? "(high)" : "(low)");
1514 if (ram_top == 0)
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001515 prom_panic("alloc_down() called with mem not initialized\n");
1516
1517 if (highmem) {
1518 /* Carve out storage for the TCE table. */
Christophe Leroye96d9042020-04-20 18:36:35 +00001519 addr = ALIGN_DOWN(alloc_top_high - size, align);
Anton Blanchard5827d412012-11-26 17:40:03 +00001520 if (addr <= alloc_bottom)
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001521 return 0;
1522 /* Will we bump into the RMO ? If yes, check out that we
1523 * didn't overlap existing allocations there, if we did,
1524 * we are dead, we must be the first in town !
1525 */
Anton Blanchard5827d412012-11-26 17:40:03 +00001526 if (addr < rmo_top) {
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001527 /* Good, we are first */
Anton Blanchard5827d412012-11-26 17:40:03 +00001528 if (alloc_top == rmo_top)
1529 alloc_top = rmo_top = addr;
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001530 else
1531 return 0;
1532 }
Anton Blanchard5827d412012-11-26 17:40:03 +00001533 alloc_top_high = addr;
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001534 goto bail;
1535 }
1536
Christophe Leroye96d9042020-04-20 18:36:35 +00001537 base = ALIGN_DOWN(alloc_top - size, align);
Anton Blanchard5827d412012-11-26 17:40:03 +00001538 for (; base > alloc_bottom;
Christophe Leroye96d9042020-04-20 18:36:35 +00001539 base = ALIGN_DOWN(base - 0x100000, align)) {
Mathieu Malaterreeae5f702018-04-06 22:12:19 +02001540 prom_debug(" trying: 0x%lx\n\r", base);
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001541 addr = (unsigned long)prom_claim(base, size, 0);
Paul Mackerrasc49888202005-10-26 21:52:53 +10001542 if (addr != PROM_ERROR && addr != 0)
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001543 break;
1544 addr = 0;
1545 }
1546 if (addr == 0)
1547 return 0;
Anton Blanchard5827d412012-11-26 17:40:03 +00001548 alloc_top = addr;
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001549
1550 bail:
Mathieu Malaterreeae5f702018-04-06 22:12:19 +02001551 prom_debug(" -> %lx\n", addr);
1552 prom_debug(" alloc_bottom : %lx\n", alloc_bottom);
1553 prom_debug(" alloc_top : %lx\n", alloc_top);
1554 prom_debug(" alloc_top_hi : %lx\n", alloc_top_high);
1555 prom_debug(" rmo_top : %lx\n", rmo_top);
1556 prom_debug(" ram_top : %lx\n", ram_top);
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001557
1558 return addr;
1559}
1560
1561/*
1562 * Parse a "reg" cell
1563 */
1564static unsigned long __init prom_next_cell(int s, cell_t **cellp)
1565{
1566 cell_t *p = *cellp;
1567 unsigned long r = 0;
1568
1569 /* Ignore more than 2 cells */
1570 while (s > sizeof(unsigned long) / 4) {
1571 p++;
1572 s--;
1573 }
Benjamin Herrenschmidt493adff2013-08-07 02:01:38 +10001574 r = be32_to_cpu(*p++);
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001575#ifdef CONFIG_PPC64
Paul Mackerras35499c02005-10-22 16:02:39 +10001576 if (s > 1) {
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001577 r <<= 32;
Benjamin Herrenschmidt493adff2013-08-07 02:01:38 +10001578 r |= be32_to_cpu(*(p++));
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001579 }
1580#endif
1581 *cellp = p;
1582 return r;
1583}
1584
1585/*
1586 * Very dumb function for adding to the memory reserve list, but
1587 * we don't need anything smarter at this point
1588 *
1589 * XXX Eventually check for collisions. They should NEVER happen.
1590 * If problems seem to show up, it would be a good start to track
1591 * them down.
1592 */
Michael Ellerman0108d3f2007-05-07 15:58:28 +10001593static void __init reserve_mem(u64 base, u64 size)
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001594{
Kumar Galacbbcf342006-01-11 17:57:13 -06001595 u64 top = base + size;
Anton Blanchard5827d412012-11-26 17:40:03 +00001596 unsigned long cnt = mem_reserve_cnt;
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001597
1598 if (size == 0)
1599 return;
1600
1601 /* We need to always keep one empty entry so that we
1602 * have our terminator with "size" set to 0 since we are
1603 * dumb and just copy this entire array to the boot params
1604 */
Christophe Leroye96d9042020-04-20 18:36:35 +00001605 base = ALIGN_DOWN(base, PAGE_SIZE);
Christophe Leroyb7115312020-04-20 18:36:36 +00001606 top = ALIGN(top, PAGE_SIZE);
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001607 size = top - base;
1608
1609 if (cnt >= (MEM_RESERVE_MAP_SIZE - 1))
1610 prom_panic("Memory reserve map exhausted !\n");
Benjamin Herrenschmidt493adff2013-08-07 02:01:38 +10001611 mem_reserve_map[cnt].base = cpu_to_be64(base);
1612 mem_reserve_map[cnt].size = cpu_to_be64(size);
Anton Blanchard5827d412012-11-26 17:40:03 +00001613 mem_reserve_cnt = cnt + 1;
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001614}
1615
1616/*
Adrian Bunkb3c2ffd2006-06-30 18:20:44 +02001617 * Initialize memory allocation mechanism, parse "memory" nodes and
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001618 * obtain that way the top of memory and RMO to setup out local allocator
1619 */
1620static void __init prom_init_mem(void)
1621{
1622 phandle node;
Mathieu Malaterreeab00a22018-04-04 22:08:35 +02001623 char type[64];
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001624 unsigned int plen;
1625 cell_t *p, *endp;
Benjamin Herrenschmidt493adff2013-08-07 02:01:38 +10001626 __be32 val;
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001627 u32 rac, rsc;
1628
1629 /*
1630 * We iterate the memory nodes to find
1631 * 1) top of RMO (first node)
1632 * 2) top of memory
1633 */
Benjamin Herrenschmidt493adff2013-08-07 02:01:38 +10001634 val = cpu_to_be32(2);
1635 prom_getprop(prom.root, "#address-cells", &val, sizeof(val));
1636 rac = be32_to_cpu(val);
1637 val = cpu_to_be32(1);
1638 prom_getprop(prom.root, "#size-cells", &val, sizeof(rsc));
1639 rsc = be32_to_cpu(val);
1640 prom_debug("root_addr_cells: %x\n", rac);
1641 prom_debug("root_size_cells: %x\n", rsc);
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001642
1643 prom_debug("scanning memory:\n");
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001644
1645 for (node = 0; prom_next_node(&node); ) {
1646 type[0] = 0;
1647 prom_getprop(node, "device_type", type, sizeof(type));
1648
Paul Mackerrasc49888202005-10-26 21:52:53 +10001649 if (type[0] == 0) {
1650 /*
1651 * CHRP Longtrail machines have no device_type
1652 * on the memory node, so check the name instead...
1653 */
1654 prom_getprop(node, "name", type, sizeof(type));
1655 }
Christophe Leroy450e7dd2019-04-26 16:23:28 +00001656 if (prom_strcmp(type, "memory"))
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001657 continue;
Paul Mackerrasc49888202005-10-26 21:52:53 +10001658
Anton Blanchard5827d412012-11-26 17:40:03 +00001659 plen = prom_getprop(node, "reg", regbuf, sizeof(regbuf));
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001660 if (plen > sizeof(regbuf)) {
1661 prom_printf("memory node too large for buffer !\n");
1662 plen = sizeof(regbuf);
1663 }
Anton Blanchard5827d412012-11-26 17:40:03 +00001664 p = regbuf;
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001665 endp = p + (plen / sizeof(cell_t));
1666
1667#ifdef DEBUG_PROM
Mathieu Malaterrec806a6f2019-05-23 12:25:20 +02001668 memset(prom_scratch, 0, sizeof(prom_scratch));
1669 call_prom("package-to-path", 3, 1, node, prom_scratch,
1670 sizeof(prom_scratch) - 1);
1671 prom_debug(" node %s :\n", prom_scratch);
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001672#endif /* DEBUG_PROM */
1673
1674 while ((endp - p) >= (rac + rsc)) {
1675 unsigned long base, size;
1676
1677 base = prom_next_cell(rac, &p);
1678 size = prom_next_cell(rsc, &p);
1679
1680 if (size == 0)
1681 continue;
Mathieu Malaterreeae5f702018-04-06 22:12:19 +02001682 prom_debug(" %lx %lx\n", base, size);
Anton Blanchard5827d412012-11-26 17:40:03 +00001683 if (base == 0 && (of_platform & PLATFORM_LPAR))
1684 rmo_top = size;
1685 if ((base + size) > ram_top)
1686 ram_top = base + size;
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001687 }
1688 }
1689
Anton Blanchard5827d412012-11-26 17:40:03 +00001690 alloc_bottom = PAGE_ALIGN((unsigned long)&_end + 0x4000);
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001691
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001692 /*
Benjamin Krillcf687872009-07-27 22:02:39 +00001693 * If prom_memory_limit is set we reduce the upper limits *except* for
1694 * alloc_top_high. This must be the real top of RAM so we can put
1695 * TCE's up there.
1696 */
1697
Anton Blanchard5827d412012-11-26 17:40:03 +00001698 alloc_top_high = ram_top;
Benjamin Krillcf687872009-07-27 22:02:39 +00001699
Anton Blanchard5827d412012-11-26 17:40:03 +00001700 if (prom_memory_limit) {
1701 if (prom_memory_limit <= alloc_bottom) {
Mathieu Malaterreeae5f702018-04-06 22:12:19 +02001702 prom_printf("Ignoring mem=%lx <= alloc_bottom.\n",
1703 prom_memory_limit);
Anton Blanchard5827d412012-11-26 17:40:03 +00001704 prom_memory_limit = 0;
1705 } else if (prom_memory_limit >= ram_top) {
Mathieu Malaterreeae5f702018-04-06 22:12:19 +02001706 prom_printf("Ignoring mem=%lx >= ram_top.\n",
1707 prom_memory_limit);
Anton Blanchard5827d412012-11-26 17:40:03 +00001708 prom_memory_limit = 0;
Benjamin Krillcf687872009-07-27 22:02:39 +00001709 } else {
Anton Blanchard5827d412012-11-26 17:40:03 +00001710 ram_top = prom_memory_limit;
1711 rmo_top = min(rmo_top, prom_memory_limit);
Benjamin Krillcf687872009-07-27 22:02:39 +00001712 }
1713 }
1714
1715 /*
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001716 * Setup our top alloc point, that is top of RMO or top of
1717 * segment 0 when running non-LPAR.
1718 * Some RS64 machines have buggy firmware where claims up at
1719 * 1GB fail. Cap at 768MB as a workaround.
1720 * Since 768MB is plenty of room, and we need to cap to something
1721 * reasonable on 32-bit, cap at 768MB on all machines.
1722 */
Anton Blanchard5827d412012-11-26 17:40:03 +00001723 if (!rmo_top)
1724 rmo_top = ram_top;
1725 rmo_top = min(0x30000000ul, rmo_top);
1726 alloc_top = rmo_top;
1727 alloc_top_high = ram_top;
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001728
Paul Mackerras64968f62011-12-13 17:54:13 +00001729 /*
1730 * Check if we have an initrd after the kernel but still inside
1731 * the RMO. If we do move our bottom point to after it.
1732 */
Anton Blanchard5827d412012-11-26 17:40:03 +00001733 if (prom_initrd_start &&
1734 prom_initrd_start < rmo_top &&
1735 prom_initrd_end > alloc_bottom)
1736 alloc_bottom = PAGE_ALIGN(prom_initrd_end);
Paul Mackerras64968f62011-12-13 17:54:13 +00001737
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001738 prom_printf("memory layout at init:\n");
Mathieu Malaterreeae5f702018-04-06 22:12:19 +02001739 prom_printf(" memory_limit : %lx (16 MB aligned)\n",
1740 prom_memory_limit);
1741 prom_printf(" alloc_bottom : %lx\n", alloc_bottom);
1742 prom_printf(" alloc_top : %lx\n", alloc_top);
1743 prom_printf(" alloc_top_hi : %lx\n", alloc_top_high);
1744 prom_printf(" rmo_top : %lx\n", rmo_top);
1745 prom_printf(" ram_top : %lx\n", ram_top);
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001746}
1747
Benjamin Herrenschmidt27f44882011-09-19 18:27:58 +00001748static void __init prom_close_stdin(void)
1749{
Benjamin Herrenschmidt493adff2013-08-07 02:01:38 +10001750 __be32 val;
1751 ihandle stdin;
Benjamin Herrenschmidt27f44882011-09-19 18:27:58 +00001752
Benjamin Herrenschmidt493adff2013-08-07 02:01:38 +10001753 if (prom_getprop(prom.chosen, "stdin", &val, sizeof(val)) > 0) {
1754 stdin = be32_to_cpu(val);
1755 call_prom("close", 1, 0, stdin);
1756 }
Benjamin Herrenschmidt27f44882011-09-19 18:27:58 +00001757}
1758
Ram Pai6a9c9302019-08-19 23:13:14 -03001759#ifdef CONFIG_PPC_SVM
1760static int prom_rtas_hcall(uint64_t args)
1761{
1762 register uint64_t arg1 asm("r3") = H_RTAS;
1763 register uint64_t arg2 asm("r4") = args;
1764
1765 asm volatile("sc 1\n" : "=r" (arg1) :
1766 "r" (arg1),
1767 "r" (arg2) :);
1768 return arg1;
1769}
1770
1771static struct rtas_args __prombss os_term_args;
1772
1773static void __init prom_rtas_os_term(char *str)
1774{
1775 phandle rtas_node;
1776 __be32 val;
1777 u32 token;
1778
1779 prom_debug("%s: start...\n", __func__);
1780 rtas_node = call_prom("finddevice", 1, 1, ADDR("/rtas"));
1781 prom_debug("rtas_node: %x\n", rtas_node);
1782 if (!PHANDLE_VALID(rtas_node))
1783 return;
1784
1785 val = 0;
1786 prom_getprop(rtas_node, "ibm,os-term", &val, sizeof(val));
1787 token = be32_to_cpu(val);
1788 prom_debug("ibm,os-term: %x\n", token);
1789 if (token == 0)
1790 prom_panic("Could not get token for ibm,os-term\n");
1791 os_term_args.token = cpu_to_be32(token);
Alexey Kardashevskiy74bb84e2020-03-12 18:44:04 +11001792 os_term_args.nargs = cpu_to_be32(1);
1793 os_term_args.nret = cpu_to_be32(1);
1794 os_term_args.args[0] = cpu_to_be32(__pa(str));
Ram Pai6a9c9302019-08-19 23:13:14 -03001795 prom_rtas_hcall((uint64_t)&os_term_args);
1796}
1797#endif /* CONFIG_PPC_SVM */
1798
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001799/*
1800 * Allocate room for and instantiate RTAS
1801 */
1802static void __init prom_instantiate_rtas(void)
1803{
1804 phandle rtas_node;
1805 ihandle rtas_inst;
1806 u32 base, entry = 0;
Benjamin Herrenschmidt493adff2013-08-07 02:01:38 +10001807 __be32 val;
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001808 u32 size = 0;
1809
1810 prom_debug("prom_instantiate_rtas: start...\n");
1811
1812 rtas_node = call_prom("finddevice", 1, 1, ADDR("/rtas"));
1813 prom_debug("rtas_node: %x\n", rtas_node);
1814 if (!PHANDLE_VALID(rtas_node))
1815 return;
1816
Benjamin Herrenschmidt493adff2013-08-07 02:01:38 +10001817 val = 0;
1818 prom_getprop(rtas_node, "rtas-size", &val, sizeof(size));
1819 size = be32_to_cpu(val);
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001820 if (size == 0)
1821 return;
1822
1823 base = alloc_down(size, PAGE_SIZE, 0);
Anton Blanchard6d1e2c62011-11-14 12:55:47 +00001824 if (base == 0)
1825 prom_panic("Could not allocate memory for RTAS\n");
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001826
1827 rtas_inst = call_prom("open", 1, 1, ADDR("/rtas"));
1828 if (!IHANDLE_VALID(rtas_inst)) {
Paul Mackerrasa23414b2005-11-10 12:00:55 +11001829 prom_printf("opening rtas package failed (%x)\n", rtas_inst);
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001830 return;
1831 }
1832
Anton Blanchard1f8737a2009-03-31 20:06:15 +00001833 prom_printf("instantiating rtas at 0x%x...", base);
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001834
1835 if (call_prom_ret("call-method", 3, 2, &entry,
1836 ADDR("instantiate-rtas"),
Paul Mackerrasa23414b2005-11-10 12:00:55 +11001837 rtas_inst, base) != 0
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001838 || entry == 0) {
1839 prom_printf(" failed\n");
1840 return;
1841 }
1842 prom_printf(" done\n");
1843
1844 reserve_mem(base, size);
1845
Benjamin Herrenschmidt493adff2013-08-07 02:01:38 +10001846 val = cpu_to_be32(base);
Paul Mackerrasa23414b2005-11-10 12:00:55 +11001847 prom_setprop(rtas_node, "/rtas", "linux,rtas-base",
Benjamin Herrenschmidt493adff2013-08-07 02:01:38 +10001848 &val, sizeof(val));
1849 val = cpu_to_be32(entry);
Paul Mackerrasa23414b2005-11-10 12:00:55 +11001850 prom_setprop(rtas_node, "/rtas", "linux,rtas-entry",
Benjamin Herrenschmidt493adff2013-08-07 02:01:38 +10001851 &val, sizeof(val));
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001852
Benjamin Herrenschmidtdbe78b42013-09-25 14:02:50 +10001853 /* Check if it supports "query-cpu-stopped-state" */
1854 if (prom_getprop(rtas_node, "query-cpu-stopped-state",
1855 &val, sizeof(val)) != PROM_ERROR)
1856 rtas_has_query_cpu_stopped = true;
1857
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001858 prom_debug("rtas base = 0x%x\n", base);
1859 prom_debug("rtas entry = 0x%x\n", entry);
Mathieu Malaterreeae5f702018-04-06 22:12:19 +02001860 prom_debug("rtas size = 0x%x\n", size);
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001861
1862 prom_debug("prom_instantiate_rtas: end...\n");
1863}
1864
1865#ifdef CONFIG_PPC64
1866/*
Ashley Lai4a727422012-08-14 18:34:57 -05001867 * Allocate room for and instantiate Stored Measurement Log (SML)
1868 */
1869static void __init prom_instantiate_sml(void)
1870{
1871 phandle ibmvtpm_node;
1872 ihandle ibmvtpm_inst;
Hon Ching \(Vicky\) Lob4ed0462015-10-07 20:11:53 -04001873 u32 entry = 0, size = 0, succ = 0;
Ashley Lai4a727422012-08-14 18:34:57 -05001874 u64 base;
Hon Ching \(Vicky\) Lob4ed0462015-10-07 20:11:53 -04001875 __be32 val;
Ashley Lai4a727422012-08-14 18:34:57 -05001876
1877 prom_debug("prom_instantiate_sml: start...\n");
1878
Hon Ching \(Vicky\) Lo2f82e982015-10-07 20:11:52 -04001879 ibmvtpm_node = call_prom("finddevice", 1, 1, ADDR("/vdevice/vtpm"));
Ashley Lai4a727422012-08-14 18:34:57 -05001880 prom_debug("ibmvtpm_node: %x\n", ibmvtpm_node);
1881 if (!PHANDLE_VALID(ibmvtpm_node))
1882 return;
1883
Hon Ching \(Vicky\) Lo2f82e982015-10-07 20:11:52 -04001884 ibmvtpm_inst = call_prom("open", 1, 1, ADDR("/vdevice/vtpm"));
Ashley Lai4a727422012-08-14 18:34:57 -05001885 if (!IHANDLE_VALID(ibmvtpm_inst)) {
1886 prom_printf("opening vtpm package failed (%x)\n", ibmvtpm_inst);
1887 return;
1888 }
1889
Hon Ching \(Vicky\) Lob4ed0462015-10-07 20:11:53 -04001890 if (prom_getprop(ibmvtpm_node, "ibm,sml-efi-reformat-supported",
1891 &val, sizeof(val)) != PROM_ERROR) {
1892 if (call_prom_ret("call-method", 2, 2, &succ,
1893 ADDR("reformat-sml-to-efi-alignment"),
1894 ibmvtpm_inst) != 0 || succ == 0) {
1895 prom_printf("Reformat SML to EFI alignment failed\n");
1896 return;
1897 }
Hon Ching \(Vicky\) Lob4ed0462015-10-07 20:11:53 -04001898
Hon Ching \(Vicky\) Lo9e5d4af2015-10-07 20:11:54 -04001899 if (call_prom_ret("call-method", 2, 2, &size,
1900 ADDR("sml-get-allocated-size"),
1901 ibmvtpm_inst) != 0 || size == 0) {
1902 prom_printf("SML get allocated size failed\n");
1903 return;
1904 }
1905 } else {
1906 if (call_prom_ret("call-method", 2, 2, &size,
1907 ADDR("sml-get-handover-size"),
1908 ibmvtpm_inst) != 0 || size == 0) {
1909 prom_printf("SML get handover size failed\n");
1910 return;
1911 }
Ashley Lai4a727422012-08-14 18:34:57 -05001912 }
1913
1914 base = alloc_down(size, PAGE_SIZE, 0);
1915 if (base == 0)
1916 prom_panic("Could not allocate memory for sml\n");
1917
Mathieu Malaterreeae5f702018-04-06 22:12:19 +02001918 prom_printf("instantiating sml at 0x%llx...", base);
Ashley Lai4a727422012-08-14 18:34:57 -05001919
Hon Ching \(Vicky\) Lo9e5d4af2015-10-07 20:11:54 -04001920 memset((void *)base, 0, size);
1921
Ashley Lai4a727422012-08-14 18:34:57 -05001922 if (call_prom_ret("call-method", 4, 2, &entry,
1923 ADDR("sml-handover"),
1924 ibmvtpm_inst, size, base) != 0 || entry == 0) {
1925 prom_printf("SML handover failed\n");
1926 return;
1927 }
1928 prom_printf(" done\n");
1929
1930 reserve_mem(base, size);
1931
Hon Ching \(Vicky\) Lo2f82e982015-10-07 20:11:52 -04001932 prom_setprop(ibmvtpm_node, "/vdevice/vtpm", "linux,sml-base",
Ashley Lai4a727422012-08-14 18:34:57 -05001933 &base, sizeof(base));
Hon Ching \(Vicky\) Lo2f82e982015-10-07 20:11:52 -04001934 prom_setprop(ibmvtpm_node, "/vdevice/vtpm", "linux,sml-size",
Ashley Lai4a727422012-08-14 18:34:57 -05001935 &size, sizeof(size));
1936
Mathieu Malaterreeae5f702018-04-06 22:12:19 +02001937 prom_debug("sml base = 0x%llx\n", base);
1938 prom_debug("sml size = 0x%x\n", size);
Ashley Lai4a727422012-08-14 18:34:57 -05001939
1940 prom_debug("prom_instantiate_sml: end...\n");
1941}
1942
1943/*
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001944 * Allocate room for and initialize TCE tables
1945 */
Benjamin Herrenschmidt493adff2013-08-07 02:01:38 +10001946#ifdef __BIG_ENDIAN__
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001947static void __init prom_initialize_tce_table(void)
1948{
1949 phandle node;
1950 ihandle phb_node;
1951 char compatible[64], type[64], model[64];
Anton Blanchard5827d412012-11-26 17:40:03 +00001952 char *path = prom_scratch;
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001953 u64 base, align;
1954 u32 minalign, minsize;
1955 u64 tce_entry, *tce_entryp;
1956 u64 local_alloc_top, local_alloc_bottom;
1957 u64 i;
1958
Anton Blanchard5827d412012-11-26 17:40:03 +00001959 if (prom_iommu_off)
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001960 return;
1961
1962 prom_debug("starting prom_initialize_tce_table\n");
1963
1964 /* Cache current top of allocs so we reserve a single block */
Anton Blanchard5827d412012-11-26 17:40:03 +00001965 local_alloc_top = alloc_top_high;
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001966 local_alloc_bottom = local_alloc_top;
1967
1968 /* Search all nodes looking for PHBs. */
1969 for (node = 0; prom_next_node(&node); ) {
1970 compatible[0] = 0;
1971 type[0] = 0;
1972 model[0] = 0;
1973 prom_getprop(node, "compatible",
1974 compatible, sizeof(compatible));
1975 prom_getprop(node, "device_type", type, sizeof(type));
1976 prom_getprop(node, "model", model, sizeof(model));
1977
Christophe Leroy450e7dd2019-04-26 16:23:28 +00001978 if ((type[0] == 0) || (prom_strstr(type, "pci") == NULL))
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001979 continue;
1980
Linas Vepstase788ff12007-09-07 03:45:21 +10001981 /* Keep the old logic intact to avoid regression. */
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001982 if (compatible[0] != 0) {
Christophe Leroy450e7dd2019-04-26 16:23:28 +00001983 if ((prom_strstr(compatible, "python") == NULL) &&
1984 (prom_strstr(compatible, "Speedwagon") == NULL) &&
1985 (prom_strstr(compatible, "Winnipeg") == NULL))
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001986 continue;
1987 } else if (model[0] != 0) {
Christophe Leroy450e7dd2019-04-26 16:23:28 +00001988 if ((prom_strstr(model, "ython") == NULL) &&
1989 (prom_strstr(model, "peedwagon") == NULL) &&
1990 (prom_strstr(model, "innipeg") == NULL))
Paul Mackerras9b6b5632005-10-06 12:06:20 +10001991 continue;
1992 }
1993
1994 if (prom_getprop(node, "tce-table-minalign", &minalign,
1995 sizeof(minalign)) == PROM_ERROR)
1996 minalign = 0;
1997 if (prom_getprop(node, "tce-table-minsize", &minsize,
1998 sizeof(minsize)) == PROM_ERROR)
1999 minsize = 4UL << 20;
2000
2001 /*
2002 * Even though we read what OF wants, we just set the table
2003 * size to 4 MB. This is enough to map 2GB of PCI DMA space.
2004 * By doing this, we avoid the pitfalls of trying to DMA to
2005 * MMIO space and the DMA alias hole.
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002006 */
Nicholas Piggin471d7ff2018-02-21 05:08:29 +10002007 minsize = 4UL << 20;
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002008
2009 /* Align to the greater of the align or size */
2010 align = max(minalign, minsize);
2011 base = alloc_down(minsize, align, 1);
2012 if (base == 0)
2013 prom_panic("ERROR, cannot find space for TCE table.\n");
2014 if (base < local_alloc_bottom)
2015 local_alloc_bottom = base;
2016
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002017 /* It seems OF doesn't null-terminate the path :-( */
Christophe Leroyd7fbe2a2019-04-02 09:08:38 +00002018 memset(path, 0, sizeof(prom_scratch));
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002019 /* Call OF to setup the TCE hardware */
2020 if (call_prom("package-to-path", 3, 1, node,
Christophe Leroyd7fbe2a2019-04-02 09:08:38 +00002021 path, sizeof(prom_scratch) - 1) == PROM_ERROR) {
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002022 prom_printf("package-to-path failed\n");
2023 }
2024
Paul Mackerrasa23414b2005-11-10 12:00:55 +11002025 /* Save away the TCE table attributes for later use. */
2026 prom_setprop(node, path, "linux,tce-base", &base, sizeof(base));
2027 prom_setprop(node, path, "linux,tce-size", &minsize, sizeof(minsize));
2028
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002029 prom_debug("TCE table: %s\n", path);
2030 prom_debug("\tnode = 0x%x\n", node);
Mathieu Malaterreeae5f702018-04-06 22:12:19 +02002031 prom_debug("\tbase = 0x%llx\n", base);
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002032 prom_debug("\tsize = 0x%x\n", minsize);
2033
2034 /* Initialize the table to have a one-to-one mapping
2035 * over the allocated size.
2036 */
Ingo Molnar2b931fb2009-01-06 13:56:52 +00002037 tce_entryp = (u64 *)base;
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002038 for (i = 0; i < (minsize >> 3) ;tce_entryp++, i++) {
2039 tce_entry = (i << PAGE_SHIFT);
2040 tce_entry |= 0x3;
2041 *tce_entryp = tce_entry;
2042 }
2043
2044 prom_printf("opening PHB %s", path);
2045 phb_node = call_prom("open", 1, 1, path);
2046 if (phb_node == 0)
2047 prom_printf("... failed\n");
2048 else
2049 prom_printf("... done\n");
2050
2051 call_prom("call-method", 6, 0, ADDR("set-64-bit-addressing"),
2052 phb_node, -1, minsize,
2053 (u32) base, (u32) (base >> 32));
2054 call_prom("close", 1, 0, phb_node);
2055 }
2056
2057 reserve_mem(local_alloc_bottom, local_alloc_top - local_alloc_bottom);
2058
Michael Ellerman2babf5c2006-05-17 18:00:46 +10002059 /* These are only really needed if there is a memory limit in
2060 * effect, but we don't know so export them always. */
Anton Blanchard5827d412012-11-26 17:40:03 +00002061 prom_tce_alloc_start = local_alloc_bottom;
2062 prom_tce_alloc_end = local_alloc_top;
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002063
2064 /* Flag the first invalid entry */
2065 prom_debug("ending prom_initialize_tce_table\n");
2066}
Benjamin Herrenschmidt493adff2013-08-07 02:01:38 +10002067#endif /* __BIG_ENDIAN__ */
2068#endif /* CONFIG_PPC64 */
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002069
2070/*
2071 * With CHRP SMP we need to use the OF to start the other processors.
2072 * We can't wait until smp_boot_cpus (the OF is trashed by then)
2073 * so we have to put the processors into a holding pattern controlled
2074 * by the kernel (not OF) before we destroy the OF.
2075 *
2076 * This uses a chunk of low memory, puts some holding pattern
2077 * code there and sends the other processors off to there until
2078 * smp_boot_cpus tells them to do something. The holding pattern
2079 * checks that address until its cpu # is there, when it is that
2080 * cpu jumps to __secondary_start(). smp_boot_cpus() takes care
2081 * of setting those values.
2082 *
2083 * We also use physical address 0x4 here to tell when a cpu
2084 * is in its holding pattern code.
2085 *
2086 * -- Cort
2087 */
Paul Mackerrasbbd0abd2005-10-26 21:45:56 +10002088/*
2089 * We want to reference the copy of __secondary_hold_* in the
2090 * 0 - 0x100 address range
2091 */
2092#define LOW_ADDR(x) (((unsigned long) &(x)) & 0xff)
2093
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002094static void __init prom_hold_cpus(void)
2095{
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002096 unsigned long i;
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002097 phandle node;
2098 char type[64];
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002099 unsigned long *spinloop
Paul Mackerrasbbd0abd2005-10-26 21:45:56 +10002100 = (void *) LOW_ADDR(__secondary_hold_spinloop);
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002101 unsigned long *acknowledge
Paul Mackerrasbbd0abd2005-10-26 21:45:56 +10002102 = (void *) LOW_ADDR(__secondary_hold_acknowledge);
Paul Mackerrasbbd0abd2005-10-26 21:45:56 +10002103 unsigned long secondary_hold = LOW_ADDR(__secondary_hold);
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002104
Benjamin Herrenschmidtdbe78b42013-09-25 14:02:50 +10002105 /*
2106 * On pseries, if RTAS supports "query-cpu-stopped-state",
2107 * we skip this stage, the CPUs will be started by the
2108 * kernel using RTAS.
2109 */
2110 if ((of_platform == PLATFORM_PSERIES ||
2111 of_platform == PLATFORM_PSERIES_LPAR) &&
2112 rtas_has_query_cpu_stopped) {
2113 prom_printf("prom_hold_cpus: skipped\n");
2114 return;
2115 }
2116
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002117 prom_debug("prom_hold_cpus: start...\n");
Mathieu Malaterreeae5f702018-04-06 22:12:19 +02002118 prom_debug(" 1) spinloop = 0x%lx\n", (unsigned long)spinloop);
2119 prom_debug(" 1) *spinloop = 0x%lx\n", *spinloop);
2120 prom_debug(" 1) acknowledge = 0x%lx\n",
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002121 (unsigned long)acknowledge);
Mathieu Malaterreeae5f702018-04-06 22:12:19 +02002122 prom_debug(" 1) *acknowledge = 0x%lx\n", *acknowledge);
2123 prom_debug(" 1) secondary_hold = 0x%lx\n", secondary_hold);
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002124
2125 /* Set the common spinloop variable, so all of the secondary cpus
2126 * will block when they are awakened from their OF spinloop.
2127 * This must occur for both SMP and non SMP kernels, since OF will
2128 * be trashed when we move the kernel.
2129 */
2130 *spinloop = 0;
2131
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002132 /* look for cpus */
2133 for (node = 0; prom_next_node(&node); ) {
Benjamin Herrenschmidt493adff2013-08-07 02:01:38 +10002134 unsigned int cpu_no;
2135 __be32 reg;
2136
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002137 type[0] = 0;
2138 prom_getprop(node, "device_type", type, sizeof(type));
Christophe Leroy450e7dd2019-04-26 16:23:28 +00002139 if (prom_strcmp(type, "cpu") != 0)
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002140 continue;
2141
2142 /* Skip non-configured cpus. */
2143 if (prom_getprop(node, "status", type, sizeof(type)) > 0)
Christophe Leroy450e7dd2019-04-26 16:23:28 +00002144 if (prom_strcmp(type, "okay") != 0)
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002145 continue;
2146
Benjamin Herrenschmidt493adff2013-08-07 02:01:38 +10002147 reg = cpu_to_be32(-1); /* make sparse happy */
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002148 prom_getprop(node, "reg", &reg, sizeof(reg));
Benjamin Herrenschmidt493adff2013-08-07 02:01:38 +10002149 cpu_no = be32_to_cpu(reg);
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002150
Mathieu Malaterreeae5f702018-04-06 22:12:19 +02002151 prom_debug("cpu hw idx = %u\n", cpu_no);
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002152
2153 /* Init the acknowledge var which will be reset by
2154 * the secondary cpu when it awakens from its OF
2155 * spinloop.
2156 */
2157 *acknowledge = (unsigned long)-1;
2158
Benjamin Herrenschmidt493adff2013-08-07 02:01:38 +10002159 if (cpu_no != prom.cpu) {
Benjamin Herrenschmidt27f44882011-09-19 18:27:58 +00002160 /* Primary Thread of non-boot cpu or any thread */
Mathieu Malaterreeae5f702018-04-06 22:12:19 +02002161 prom_printf("starting cpu hw idx %u... ", cpu_no);
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002162 call_prom("start-cpu", 3, 0, node,
Benjamin Herrenschmidt493adff2013-08-07 02:01:38 +10002163 secondary_hold, cpu_no);
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002164
Paul Mackerrasbbd0abd2005-10-26 21:45:56 +10002165 for (i = 0; (i < 100000000) &&
2166 (*acknowledge == ((unsigned long)-1)); i++ )
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002167 mb();
2168
Benjamin Herrenschmidt493adff2013-08-07 02:01:38 +10002169 if (*acknowledge == cpu_no)
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002170 prom_printf("done\n");
Paul Mackerrasbbd0abd2005-10-26 21:45:56 +10002171 else
Mathieu Malaterreeae5f702018-04-06 22:12:19 +02002172 prom_printf("failed: %lx\n", *acknowledge);
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002173 }
2174#ifdef CONFIG_SMP
2175 else
Mathieu Malaterreeae5f702018-04-06 22:12:19 +02002176 prom_printf("boot cpu hw idx %u\n", cpu_no);
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002177#endif /* CONFIG_SMP */
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002178 }
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002179
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002180 prom_debug("prom_hold_cpus: end...\n");
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002181}
2182
2183
2184static void __init prom_init_client_services(unsigned long pp)
2185{
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002186 /* Get a handle to the prom entry point before anything else */
Anton Blanchard5827d412012-11-26 17:40:03 +00002187 prom_entry = pp;
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002188
2189 /* get a handle for the stdout device */
Anton Blanchard5827d412012-11-26 17:40:03 +00002190 prom.chosen = call_prom("finddevice", 1, 1, ADDR("/chosen"));
2191 if (!PHANDLE_VALID(prom.chosen))
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002192 prom_panic("cannot find chosen"); /* msg won't be printed :( */
2193
2194 /* get device tree root */
Anton Blanchard5827d412012-11-26 17:40:03 +00002195 prom.root = call_prom("finddevice", 1, 1, ADDR("/"));
2196 if (!PHANDLE_VALID(prom.root))
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002197 prom_panic("cannot find device tree root"); /* msg won't be printed :( */
Paul Mackerrasa575b802005-10-23 17:23:21 +10002198
Anton Blanchard5827d412012-11-26 17:40:03 +00002199 prom.mmumap = 0;
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002200}
2201
Paul Mackerrasa575b802005-10-23 17:23:21 +10002202#ifdef CONFIG_PPC32
2203/*
2204 * For really old powermacs, we need to map things we claim.
2205 * For that, we need the ihandle of the mmu.
Paul Mackerrasa23414b2005-11-10 12:00:55 +11002206 * Also, on the longtrail, we need to work around other bugs.
Paul Mackerrasa575b802005-10-23 17:23:21 +10002207 */
2208static void __init prom_find_mmu(void)
2209{
Paul Mackerrasa575b802005-10-23 17:23:21 +10002210 phandle oprom;
2211 char version[64];
2212
2213 oprom = call_prom("finddevice", 1, 1, ADDR("/openprom"));
2214 if (!PHANDLE_VALID(oprom))
2215 return;
2216 if (prom_getprop(oprom, "model", version, sizeof(version)) <= 0)
2217 return;
2218 version[sizeof(version) - 1] = 0;
Paul Mackerrasa575b802005-10-23 17:23:21 +10002219 /* XXX might need to add other versions here */
Christophe Leroy450e7dd2019-04-26 16:23:28 +00002220 if (prom_strcmp(version, "Open Firmware, 1.0.5") == 0)
Paul Mackerrasa23414b2005-11-10 12:00:55 +11002221 of_workarounds = OF_WA_CLAIM;
Christophe Leroy450e7dd2019-04-26 16:23:28 +00002222 else if (prom_strncmp(version, "FirmWorks,3.", 12) == 0) {
Paul Mackerrasa23414b2005-11-10 12:00:55 +11002223 of_workarounds = OF_WA_CLAIM | OF_WA_LONGTRAIL;
2224 call_prom("interpret", 1, 1, "dev /memory 0 to allow-reclaim");
2225 } else
Paul Mackerrasa575b802005-10-23 17:23:21 +10002226 return;
Anton Blanchard5827d412012-11-26 17:40:03 +00002227 prom.memory = call_prom("open", 1, 1, ADDR("/memory"));
2228 prom_getprop(prom.chosen, "mmu", &prom.mmumap,
2229 sizeof(prom.mmumap));
Benjamin Herrenschmidt493adff2013-08-07 02:01:38 +10002230 prom.mmumap = be32_to_cpu(prom.mmumap);
Anton Blanchard5827d412012-11-26 17:40:03 +00002231 if (!IHANDLE_VALID(prom.memory) || !IHANDLE_VALID(prom.mmumap))
Paul Mackerrasa23414b2005-11-10 12:00:55 +11002232 of_workarounds &= ~OF_WA_CLAIM; /* hmmm */
Paul Mackerrasa575b802005-10-23 17:23:21 +10002233}
2234#else
2235#define prom_find_mmu()
2236#endif
2237
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002238static void __init prom_init_stdout(void)
2239{
Anton Blanchard5827d412012-11-26 17:40:03 +00002240 char *path = of_stdout_device;
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002241 char type[16];
Benjamin Herrenschmidt493adff2013-08-07 02:01:38 +10002242 phandle stdout_node;
2243 __be32 val;
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002244
Anton Blanchard5827d412012-11-26 17:40:03 +00002245 if (prom_getprop(prom.chosen, "stdout", &val, sizeof(val)) <= 0)
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002246 prom_panic("cannot find stdout");
2247
Benjamin Herrenschmidt493adff2013-08-07 02:01:38 +10002248 prom.stdout = be32_to_cpu(val);
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002249
2250 /* Get the full OF pathname of the stdout device */
2251 memset(path, 0, 256);
Anton Blanchard5827d412012-11-26 17:40:03 +00002252 call_prom("instance-to-path", 3, 1, prom.stdout, path, 255);
Anton Blanchard5827d412012-11-26 17:40:03 +00002253 prom_printf("OF stdout device is: %s\n", of_stdout_device);
2254 prom_setprop(prom.chosen, "/chosen", "linux,stdout-path",
Christophe Leroy450e7dd2019-04-26 16:23:28 +00002255 path, prom_strlen(path) + 1);
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002256
Benjamin Herrenschmidt10348f52014-01-13 09:49:17 +11002257 /* instance-to-package fails on PA-Semi */
2258 stdout_node = call_prom("instance-to-package", 1, 1, prom.stdout);
2259 if (stdout_node != PROM_ERROR) {
2260 val = cpu_to_be32(stdout_node);
Benjamin Herrenschmidt10348f52014-01-13 09:49:17 +11002261
2262 /* If it's a display, note it */
2263 memset(type, 0, sizeof(type));
2264 prom_getprop(stdout_node, "device_type", type, sizeof(type));
Christophe Leroy450e7dd2019-04-26 16:23:28 +00002265 if (prom_strcmp(type, "display") == 0)
Benjamin Herrenschmidt10348f52014-01-13 09:49:17 +11002266 prom_setprop(stdout_node, path, "linux,boot-display", NULL, 0);
2267 }
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002268}
2269
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002270static int __init prom_find_machine_type(void)
2271{
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002272 char compat[256];
2273 int len, i = 0;
Benjamin Herrenschmidt21fe3302005-11-07 16:41:59 +11002274#ifdef CONFIG_PPC64
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002275 phandle rtas;
Benjamin Herrenschmidte8222502006-03-28 23:15:54 +11002276 int x;
Benjamin Herrenschmidt21fe3302005-11-07 16:41:59 +11002277#endif
Benjamin Herrenschmidte8222502006-03-28 23:15:54 +11002278
Benjamin Herrenschmidt6e35d5d2011-09-19 18:28:01 +00002279 /* Look for a PowerMac or a Cell */
Anton Blanchard5827d412012-11-26 17:40:03 +00002280 len = prom_getprop(prom.root, "compatible",
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002281 compat, sizeof(compat)-1);
2282 if (len > 0) {
2283 compat[len] = 0;
2284 while (i < len) {
2285 char *p = &compat[i];
Christophe Leroy450e7dd2019-04-26 16:23:28 +00002286 int sl = prom_strlen(p);
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002287 if (sl == 0)
2288 break;
Christophe Leroy450e7dd2019-04-26 16:23:28 +00002289 if (prom_strstr(p, "Power Macintosh") ||
2290 prom_strstr(p, "MacRISC"))
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002291 return PLATFORM_POWERMAC;
Arnd Bergmann133dda12006-06-07 12:04:18 +10002292#ifdef CONFIG_PPC64
2293 /* We must make sure we don't detect the IBM Cell
2294 * blades as pSeries due to some firmware issues,
2295 * so we do it here.
2296 */
Christophe Leroy450e7dd2019-04-26 16:23:28 +00002297 if (prom_strstr(p, "IBM,CBEA") ||
2298 prom_strstr(p, "IBM,CPBW-1.0"))
Arnd Bergmann133dda12006-06-07 12:04:18 +10002299 return PLATFORM_GENERIC;
2300#endif /* CONFIG_PPC64 */
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002301 i += sl + 1;
2302 }
2303 }
2304#ifdef CONFIG_PPC64
Benjamin Herrenschmidt6e35d5d2011-09-19 18:28:01 +00002305 /* Try to figure out if it's an IBM pSeries or any other
Benjamin Herrenschmidte8222502006-03-28 23:15:54 +11002306 * PAPR compliant platform. We assume it is if :
2307 * - /device_type is "chrp" (please, do NOT use that for future
2308 * non-IBM designs !
2309 * - it has /rtas
2310 */
Anton Blanchard5827d412012-11-26 17:40:03 +00002311 len = prom_getprop(prom.root, "device_type",
Benjamin Herrenschmidte8222502006-03-28 23:15:54 +11002312 compat, sizeof(compat)-1);
2313 if (len <= 0)
2314 return PLATFORM_GENERIC;
Christophe Leroy450e7dd2019-04-26 16:23:28 +00002315 if (prom_strcmp(compat, "chrp"))
Benjamin Herrenschmidte8222502006-03-28 23:15:54 +11002316 return PLATFORM_GENERIC;
2317
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002318 /* Default to pSeries. We need to know if we are running LPAR */
2319 rtas = call_prom("finddevice", 1, 1, ADDR("/rtas"));
Benjamin Herrenschmidte8222502006-03-28 23:15:54 +11002320 if (!PHANDLE_VALID(rtas))
2321 return PLATFORM_GENERIC;
2322 x = prom_getproplen(rtas, "ibm,hypertas-functions");
2323 if (x != PROM_ERROR) {
Anton Blanchard4da727a2009-03-31 20:06:14 +00002324 prom_debug("Hypertas detected, assuming LPAR !\n");
Benjamin Herrenschmidte8222502006-03-28 23:15:54 +11002325 return PLATFORM_PSERIES_LPAR;
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002326 }
2327 return PLATFORM_PSERIES;
2328#else
Benjamin Herrenschmidte8222502006-03-28 23:15:54 +11002329 return PLATFORM_GENERIC;
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002330#endif
2331}
2332
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002333static int __init prom_set_color(ihandle ih, int i, int r, int g, int b)
2334{
2335 return call_prom("call-method", 6, 1, ADDR("color!"), ih, i, b, g, r);
2336}
2337
2338/*
2339 * If we have a display that we don't know how to drive,
2340 * we will want to try to execute OF's open method for it
2341 * later. However, OF will probably fall over if we do that
2342 * we've taken over the MMU.
2343 * So we check whether we will need to open the display,
2344 * and if so, open it now.
2345 */
2346static void __init prom_check_displays(void)
2347{
2348 char type[16], *path;
2349 phandle node;
2350 ihandle ih;
2351 int i;
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002352
Benjamin Herrenschmidtd00e34b2018-10-15 13:49:56 +11002353 static const unsigned char default_colors[] __initconst = {
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002354 0x00, 0x00, 0x00,
2355 0x00, 0x00, 0xaa,
2356 0x00, 0xaa, 0x00,
2357 0x00, 0xaa, 0xaa,
2358 0xaa, 0x00, 0x00,
2359 0xaa, 0x00, 0xaa,
2360 0xaa, 0xaa, 0x00,
2361 0xaa, 0xaa, 0xaa,
2362 0x55, 0x55, 0x55,
2363 0x55, 0x55, 0xff,
2364 0x55, 0xff, 0x55,
2365 0x55, 0xff, 0xff,
2366 0xff, 0x55, 0x55,
2367 0xff, 0x55, 0xff,
2368 0xff, 0xff, 0x55,
2369 0xff, 0xff, 0xff
2370 };
2371 const unsigned char *clut;
2372
Anton Blanchard4da727a2009-03-31 20:06:14 +00002373 prom_debug("Looking for displays\n");
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002374 for (node = 0; prom_next_node(&node); ) {
2375 memset(type, 0, sizeof(type));
2376 prom_getprop(node, "device_type", type, sizeof(type));
Christophe Leroy450e7dd2019-04-26 16:23:28 +00002377 if (prom_strcmp(type, "display") != 0)
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002378 continue;
2379
2380 /* It seems OF doesn't null-terminate the path :-( */
Anton Blanchard5827d412012-11-26 17:40:03 +00002381 path = prom_scratch;
Christophe Leroyd7fbe2a2019-04-02 09:08:38 +00002382 memset(path, 0, sizeof(prom_scratch));
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002383
2384 /*
2385 * leave some room at the end of the path for appending extra
2386 * arguments
2387 */
2388 if (call_prom("package-to-path", 3, 1, node, path,
Christophe Leroyd7fbe2a2019-04-02 09:08:38 +00002389 sizeof(prom_scratch) - 10) == PROM_ERROR)
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002390 continue;
Anton Blanchard1f8737a2009-03-31 20:06:15 +00002391 prom_printf("found display : %s, opening... ", path);
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002392
2393 ih = call_prom("open", 1, 1, path);
2394 if (ih == 0) {
2395 prom_printf("failed\n");
2396 continue;
2397 }
2398
2399 /* Success */
2400 prom_printf("done\n");
Paul Mackerrasa23414b2005-11-10 12:00:55 +11002401 prom_setprop(node, path, "linux,opened", NULL, 0);
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002402
2403 /* Setup a usable color table when the appropriate
2404 * method is available. Should update this to set-colors */
Anton Blanchard5827d412012-11-26 17:40:03 +00002405 clut = default_colors;
Benjamin Herrenschmidt3f536382011-12-14 13:55:11 +00002406 for (i = 0; i < 16; i++, clut += 3)
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002407 if (prom_set_color(ih, i, clut[0], clut[1],
2408 clut[2]) != 0)
2409 break;
2410
2411#ifdef CONFIG_LOGO_LINUX_CLUT224
Anton Blanchard5827d412012-11-26 17:40:03 +00002412 clut = PTRRELOC(logo_linux_clut224.clut);
2413 for (i = 0; i < logo_linux_clut224.clutsize; i++, clut += 3)
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002414 if (prom_set_color(ih, i + 32, clut[0], clut[1],
2415 clut[2]) != 0)
2416 break;
2417#endif /* CONFIG_LOGO_LINUX_CLUT224 */
Benjamin Herrenschmidt7191b612013-07-25 12:12:32 +10002418
2419#ifdef CONFIG_PPC_EARLY_DEBUG_BOOTX
2420 if (prom_getprop(node, "linux,boot-display", NULL, 0) !=
2421 PROM_ERROR) {
2422 u32 width, height, pitch, addr;
2423
2424 prom_printf("Setting btext !\n");
Michael Ellerman6c71cfc2020-08-21 20:34:07 +10002425
2426 if (prom_getprop(node, "width", &width, 4) == PROM_ERROR)
2427 return;
2428
2429 if (prom_getprop(node, "height", &height, 4) == PROM_ERROR)
2430 return;
2431
2432 if (prom_getprop(node, "linebytes", &pitch, 4) == PROM_ERROR)
2433 return;
2434
2435 if (prom_getprop(node, "address", &addr, 4) == PROM_ERROR)
2436 return;
2437
Benjamin Herrenschmidt7191b612013-07-25 12:12:32 +10002438 prom_printf("W=%d H=%d LB=%d addr=0x%x\n",
2439 width, height, pitch, addr);
2440 btext_setup_display(width, height, 8, pitch, addr);
Christophe Leroyc21f5a92019-06-03 13:00:51 +00002441 btext_prepare_BAT();
Benjamin Herrenschmidt7191b612013-07-25 12:12:32 +10002442 }
2443#endif /* CONFIG_PPC_EARLY_DEBUG_BOOTX */
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002444 }
2445}
2446
2447
2448/* Return (relocated) pointer to this much memory: moves initrd if reqd. */
2449static void __init *make_room(unsigned long *mem_start, unsigned long *mem_end,
2450 unsigned long needed, unsigned long align)
2451{
2452 void *ret;
2453
Christophe Leroyd3f3d3b2020-04-20 18:36:37 +00002454 *mem_start = ALIGN(*mem_start, align);
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002455 while ((*mem_start + needed) > *mem_end) {
2456 unsigned long room, chunk;
2457
Mathieu Malaterreeae5f702018-04-06 22:12:19 +02002458 prom_debug("Chunk exhausted, claiming more at %lx...\n",
Anton Blanchard5827d412012-11-26 17:40:03 +00002459 alloc_bottom);
2460 room = alloc_top - alloc_bottom;
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002461 if (room > DEVTREE_CHUNK_SIZE)
2462 room = DEVTREE_CHUNK_SIZE;
2463 if (room < PAGE_SIZE)
Anton Blanchardfbafd722011-07-25 20:47:51 +00002464 prom_panic("No memory for flatten_device_tree "
2465 "(no room)\n");
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002466 chunk = alloc_up(room, 0);
2467 if (chunk == 0)
Anton Blanchardfbafd722011-07-25 20:47:51 +00002468 prom_panic("No memory for flatten_device_tree "
2469 "(claim failed)\n");
Anton Blanchard966728d2011-07-25 20:47:07 +00002470 *mem_end = chunk + room;
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002471 }
2472
2473 ret = (void *)*mem_start;
2474 *mem_start += needed;
2475
2476 return ret;
2477}
2478
Benjamin Herrenschmidt493adff2013-08-07 02:01:38 +10002479#define dt_push_token(token, mem_start, mem_end) do { \
2480 void *room = make_room(mem_start, mem_end, 4, 4); \
2481 *(__be32 *)room = cpu_to_be32(token); \
2482 } while(0)
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002483
2484static unsigned long __init dt_find_string(char *str)
2485{
2486 char *s, *os;
2487
Anton Blanchard5827d412012-11-26 17:40:03 +00002488 s = os = (char *)dt_string_start;
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002489 s += 4;
Anton Blanchard5827d412012-11-26 17:40:03 +00002490 while (s < (char *)dt_string_end) {
Christophe Leroy450e7dd2019-04-26 16:23:28 +00002491 if (prom_strcmp(s, str) == 0)
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002492 return s - os;
Christophe Leroy450e7dd2019-04-26 16:23:28 +00002493 s += prom_strlen(s) + 1;
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002494 }
2495 return 0;
2496}
2497
2498/*
2499 * The Open Firmware 1275 specification states properties must be 31 bytes or
2500 * less, however not all firmwares obey this. Make it 64 bytes to be safe.
2501 */
2502#define MAX_PROPERTY_NAME 64
2503
2504static void __init scan_dt_build_strings(phandle node,
2505 unsigned long *mem_start,
2506 unsigned long *mem_end)
2507{
2508 char *prev_name, *namep, *sstart;
2509 unsigned long soff;
2510 phandle child;
2511
Anton Blanchard5827d412012-11-26 17:40:03 +00002512 sstart = (char *)dt_string_start;
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002513
2514 /* get and store all property names */
Anton Blanchard5827d412012-11-26 17:40:03 +00002515 prev_name = "";
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002516 for (;;) {
2517 /* 64 is max len of name including nul. */
2518 namep = make_room(mem_start, mem_end, MAX_PROPERTY_NAME, 1);
2519 if (call_prom("nextprop", 3, 1, node, prev_name, namep) != 1) {
2520 /* No more nodes: unwind alloc */
2521 *mem_start = (unsigned long)namep;
2522 break;
2523 }
2524
2525 /* skip "name" */
Christophe Leroy450e7dd2019-04-26 16:23:28 +00002526 if (prom_strcmp(namep, "name") == 0) {
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002527 *mem_start = (unsigned long)namep;
Anton Blanchard5827d412012-11-26 17:40:03 +00002528 prev_name = "name";
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002529 continue;
2530 }
2531 /* get/create string entry */
2532 soff = dt_find_string(namep);
2533 if (soff != 0) {
2534 *mem_start = (unsigned long)namep;
2535 namep = sstart + soff;
2536 } else {
2537 /* Trim off some if we can */
Christophe Leroy450e7dd2019-04-26 16:23:28 +00002538 *mem_start = (unsigned long)namep + prom_strlen(namep) + 1;
Anton Blanchard5827d412012-11-26 17:40:03 +00002539 dt_string_end = *mem_start;
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002540 }
2541 prev_name = namep;
2542 }
2543
2544 /* do all our children */
2545 child = call_prom("child", 1, 1, node);
2546 while (child != 0) {
2547 scan_dt_build_strings(child, mem_start, mem_end);
2548 child = call_prom("peer", 1, 1, child);
2549 }
2550}
2551
2552static void __init scan_dt_build_struct(phandle node, unsigned long *mem_start,
2553 unsigned long *mem_end)
2554{
2555 phandle child;
2556 char *namep, *prev_name, *sstart, *p, *ep, *lp, *path;
2557 unsigned long soff;
2558 unsigned char *valp;
Benjamin Herrenschmidt8ca2d512018-10-15 13:49:57 +11002559 static char pname[MAX_PROPERTY_NAME] __prombss;
Benjamin Herrenschmidt6e35d5d2011-09-19 18:28:01 +00002560 int l, room, has_phandle = 0;
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002561
2562 dt_push_token(OF_DT_BEGIN_NODE, mem_start, mem_end);
2563
2564 /* get the node's full name */
2565 namep = (char *)*mem_start;
Paul Mackerrasc49888202005-10-26 21:52:53 +10002566 room = *mem_end - *mem_start;
2567 if (room > 255)
2568 room = 255;
2569 l = call_prom("package-to-path", 3, 1, node, namep, room);
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002570 if (l >= 0) {
2571 /* Didn't fit? Get more room. */
Paul Mackerrasc49888202005-10-26 21:52:53 +10002572 if (l >= room) {
2573 if (l >= *mem_end - *mem_start)
2574 namep = make_room(mem_start, mem_end, l+1, 1);
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002575 call_prom("package-to-path", 3, 1, node, namep, l);
2576 }
2577 namep[l] = '\0';
2578
2579 /* Fixup an Apple bug where they have bogus \0 chars in the
Paul Mackerrasa575b802005-10-23 17:23:21 +10002580 * middle of the path in some properties, and extract
2581 * the unit name (everything after the last '/').
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002582 */
Paul Mackerrasa575b802005-10-23 17:23:21 +10002583 for (lp = p = namep, ep = namep + l; p < ep; p++) {
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002584 if (*p == '/')
Paul Mackerrasa575b802005-10-23 17:23:21 +10002585 lp = namep;
2586 else if (*p != 0)
2587 *lp++ = *p;
2588 }
2589 *lp = 0;
Christophe Leroyd3f3d3b2020-04-20 18:36:37 +00002590 *mem_start = ALIGN((unsigned long)lp + 1, 4);
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002591 }
2592
2593 /* get it again for debugging */
Anton Blanchard5827d412012-11-26 17:40:03 +00002594 path = prom_scratch;
Christophe Leroyd7fbe2a2019-04-02 09:08:38 +00002595 memset(path, 0, sizeof(prom_scratch));
2596 call_prom("package-to-path", 3, 1, node, path, sizeof(prom_scratch) - 1);
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002597
2598 /* get and store all properties */
Anton Blanchard5827d412012-11-26 17:40:03 +00002599 prev_name = "";
2600 sstart = (char *)dt_string_start;
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002601 for (;;) {
2602 if (call_prom("nextprop", 3, 1, node, prev_name,
Anton Blanchard5827d412012-11-26 17:40:03 +00002603 pname) != 1)
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002604 break;
2605
2606 /* skip "name" */
Christophe Leroy450e7dd2019-04-26 16:23:28 +00002607 if (prom_strcmp(pname, "name") == 0) {
Anton Blanchard5827d412012-11-26 17:40:03 +00002608 prev_name = "name";
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002609 continue;
2610 }
2611
2612 /* find string offset */
Anton Blanchard5827d412012-11-26 17:40:03 +00002613 soff = dt_find_string(pname);
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002614 if (soff == 0) {
2615 prom_printf("WARNING: Can't find string index for"
Anton Blanchard5827d412012-11-26 17:40:03 +00002616 " <%s>, node %s\n", pname, path);
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002617 break;
2618 }
2619 prev_name = sstart + soff;
2620
2621 /* get length */
Anton Blanchard5827d412012-11-26 17:40:03 +00002622 l = call_prom("getproplen", 2, 1, node, pname);
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002623
2624 /* sanity checks */
2625 if (l == PROM_ERROR)
2626 continue;
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002627
2628 /* push property head */
2629 dt_push_token(OF_DT_PROP, mem_start, mem_end);
2630 dt_push_token(l, mem_start, mem_end);
2631 dt_push_token(soff, mem_start, mem_end);
2632
2633 /* push property content */
2634 valp = make_room(mem_start, mem_end, l, 4);
Anton Blanchard5827d412012-11-26 17:40:03 +00002635 call_prom("getprop", 4, 1, node, pname, valp, l);
Christophe Leroyd3f3d3b2020-04-20 18:36:37 +00002636 *mem_start = ALIGN(*mem_start, 4);
Benjamin Herrenschmidt6e35d5d2011-09-19 18:28:01 +00002637
Christophe Leroy450e7dd2019-04-26 16:23:28 +00002638 if (!prom_strcmp(pname, "phandle"))
Benjamin Herrenschmidt6e35d5d2011-09-19 18:28:01 +00002639 has_phandle = 1;
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002640 }
2641
Benjamin Herrenschmidtf1f208e2018-10-15 13:50:00 +11002642 /* Add a "phandle" property if none already exist */
Benjamin Herrenschmidt6e35d5d2011-09-19 18:28:01 +00002643 if (!has_phandle) {
Benjamin Herrenschmidtf1f208e2018-10-15 13:50:00 +11002644 soff = dt_find_string("phandle");
Benjamin Herrenschmidt6e35d5d2011-09-19 18:28:01 +00002645 if (soff == 0)
Benjamin Herrenschmidtf1f208e2018-10-15 13:50:00 +11002646 prom_printf("WARNING: Can't find string index for <phandle> node %s\n", path);
Benjamin Herrenschmidt6e35d5d2011-09-19 18:28:01 +00002647 else {
2648 dt_push_token(OF_DT_PROP, mem_start, mem_end);
2649 dt_push_token(4, mem_start, mem_end);
2650 dt_push_token(soff, mem_start, mem_end);
2651 valp = make_room(mem_start, mem_end, 4, 4);
Benjamin Herrenschmidt493adff2013-08-07 02:01:38 +10002652 *(__be32 *)valp = cpu_to_be32(node);
Benjamin Herrenschmidt6e35d5d2011-09-19 18:28:01 +00002653 }
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002654 }
2655
2656 /* do all our children */
2657 child = call_prom("child", 1, 1, node);
2658 while (child != 0) {
2659 scan_dt_build_struct(child, mem_start, mem_end);
2660 child = call_prom("peer", 1, 1, child);
2661 }
2662
2663 dt_push_token(OF_DT_END_NODE, mem_start, mem_end);
2664}
2665
2666static void __init flatten_device_tree(void)
2667{
2668 phandle root;
2669 unsigned long mem_start, mem_end, room;
2670 struct boot_param_header *hdr;
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002671 char *namep;
2672 u64 *rsvmap;
2673
2674 /*
2675 * Check how much room we have between alloc top & bottom (+/- a
Anton Blanchardfbafd722011-07-25 20:47:51 +00002676 * few pages), crop to 1MB, as this is our "chunk" size
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002677 */
Anton Blanchard5827d412012-11-26 17:40:03 +00002678 room = alloc_top - alloc_bottom - 0x4000;
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002679 if (room > DEVTREE_CHUNK_SIZE)
2680 room = DEVTREE_CHUNK_SIZE;
Mathieu Malaterreeae5f702018-04-06 22:12:19 +02002681 prom_debug("starting device tree allocs at %lx\n", alloc_bottom);
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002682
2683 /* Now try to claim that */
2684 mem_start = (unsigned long)alloc_up(room, PAGE_SIZE);
2685 if (mem_start == 0)
2686 prom_panic("Can't allocate initial device-tree chunk\n");
Anton Blanchard966728d2011-07-25 20:47:07 +00002687 mem_end = mem_start + room;
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002688
2689 /* Get root of tree */
2690 root = call_prom("peer", 1, 1, (phandle)0);
2691 if (root == (phandle)0)
2692 prom_panic ("couldn't get device tree root\n");
2693
2694 /* Build header and make room for mem rsv map */
Christophe Leroyd3f3d3b2020-04-20 18:36:37 +00002695 mem_start = ALIGN(mem_start, 4);
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002696 hdr = make_room(&mem_start, &mem_end,
2697 sizeof(struct boot_param_header), 4);
Anton Blanchard5827d412012-11-26 17:40:03 +00002698 dt_header_start = (unsigned long)hdr;
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002699 rsvmap = make_room(&mem_start, &mem_end, sizeof(mem_reserve_map), 8);
2700
2701 /* Start of strings */
2702 mem_start = PAGE_ALIGN(mem_start);
Anton Blanchard5827d412012-11-26 17:40:03 +00002703 dt_string_start = mem_start;
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002704 mem_start += 4; /* hole */
2705
Benjamin Herrenschmidtf1f208e2018-10-15 13:50:00 +11002706 /* Add "phandle" in there, we'll need it */
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002707 namep = make_room(&mem_start, &mem_end, 16, 1);
Christophe Leroy450e7dd2019-04-26 16:23:28 +00002708 prom_strcpy(namep, "phandle");
2709 mem_start = (unsigned long)namep + prom_strlen(namep) + 1;
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002710
2711 /* Build string array */
2712 prom_printf("Building dt strings...\n");
2713 scan_dt_build_strings(root, &mem_start, &mem_end);
Anton Blanchard5827d412012-11-26 17:40:03 +00002714 dt_string_end = mem_start;
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002715
2716 /* Build structure */
2717 mem_start = PAGE_ALIGN(mem_start);
Anton Blanchard5827d412012-11-26 17:40:03 +00002718 dt_struct_start = mem_start;
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002719 prom_printf("Building dt structure...\n");
2720 scan_dt_build_struct(root, &mem_start, &mem_end);
2721 dt_push_token(OF_DT_END, &mem_start, &mem_end);
Anton Blanchard5827d412012-11-26 17:40:03 +00002722 dt_struct_end = PAGE_ALIGN(mem_start);
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002723
2724 /* Finish header */
Benjamin Herrenschmidt493adff2013-08-07 02:01:38 +10002725 hdr->boot_cpuid_phys = cpu_to_be32(prom.cpu);
2726 hdr->magic = cpu_to_be32(OF_DT_HEADER);
2727 hdr->totalsize = cpu_to_be32(dt_struct_end - dt_header_start);
2728 hdr->off_dt_struct = cpu_to_be32(dt_struct_start - dt_header_start);
2729 hdr->off_dt_strings = cpu_to_be32(dt_string_start - dt_header_start);
2730 hdr->dt_strings_size = cpu_to_be32(dt_string_end - dt_string_start);
2731 hdr->off_mem_rsvmap = cpu_to_be32(((unsigned long)rsvmap) - dt_header_start);
2732 hdr->version = cpu_to_be32(OF_DT_VERSION);
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002733 /* Version 16 is not backward compatible */
Benjamin Herrenschmidt493adff2013-08-07 02:01:38 +10002734 hdr->last_comp_version = cpu_to_be32(0x10);
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002735
Jimi Xenidis4d1f3f22006-05-18 17:03:05 -05002736 /* Copy the reserve map in */
Anton Blanchard5827d412012-11-26 17:40:03 +00002737 memcpy(rsvmap, mem_reserve_map, sizeof(mem_reserve_map));
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002738
2739#ifdef DEBUG_PROM
2740 {
2741 int i;
2742 prom_printf("reserved memory map:\n");
Anton Blanchard5827d412012-11-26 17:40:03 +00002743 for (i = 0; i < mem_reserve_cnt; i++)
Mathieu Malaterreeae5f702018-04-06 22:12:19 +02002744 prom_printf(" %llx - %llx\n",
Benjamin Herrenschmidt493adff2013-08-07 02:01:38 +10002745 be64_to_cpu(mem_reserve_map[i].base),
2746 be64_to_cpu(mem_reserve_map[i].size));
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002747 }
2748#endif
Jimi Xenidis4d1f3f22006-05-18 17:03:05 -05002749 /* Bump mem_reserve_cnt to cause further reservations to fail
2750 * since it's too late.
2751 */
Anton Blanchard5827d412012-11-26 17:40:03 +00002752 mem_reserve_cnt = MEM_RESERVE_MAP_SIZE;
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002753
Mathieu Malaterreeae5f702018-04-06 22:12:19 +02002754 prom_printf("Device tree strings 0x%lx -> 0x%lx\n",
Anton Blanchard5827d412012-11-26 17:40:03 +00002755 dt_string_start, dt_string_end);
Mathieu Malaterreeae5f702018-04-06 22:12:19 +02002756 prom_printf("Device tree struct 0x%lx -> 0x%lx\n",
Anton Blanchard5827d412012-11-26 17:40:03 +00002757 dt_struct_start, dt_struct_end);
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002758}
2759
Hollis Blanchard54f4ee12006-05-25 16:36:53 -05002760#ifdef CONFIG_PPC_MAPLE
2761/* PIBS Version 1.05.0000 04/26/2005 has an incorrect /ht/isa/ranges property.
2762 * The values are bad, and it doesn't even have the right number of cells. */
2763static void __init fixup_device_tree_maple(void)
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002764{
Hollis Blanchard54f4ee12006-05-25 16:36:53 -05002765 phandle isa;
Benjamin Herrenschmidt980a6512006-07-03 17:22:05 +10002766 u32 rloc = 0x01002000; /* IO space; PCI device = 4 */
Hollis Blanchard54f4ee12006-05-25 16:36:53 -05002767 u32 isa_ranges[6];
Benjamin Herrenschmidt980a6512006-07-03 17:22:05 +10002768 char *name;
Hollis Blanchard54f4ee12006-05-25 16:36:53 -05002769
Benjamin Herrenschmidt980a6512006-07-03 17:22:05 +10002770 name = "/ht@0/isa@4";
2771 isa = call_prom("finddevice", 1, 1, ADDR(name));
2772 if (!PHANDLE_VALID(isa)) {
2773 name = "/ht@0/isa@6";
2774 isa = call_prom("finddevice", 1, 1, ADDR(name));
2775 rloc = 0x01003000; /* IO space; PCI device = 6 */
2776 }
Hollis Blanchard54f4ee12006-05-25 16:36:53 -05002777 if (!PHANDLE_VALID(isa))
2778 return;
2779
Benjamin Herrenschmidt980a6512006-07-03 17:22:05 +10002780 if (prom_getproplen(isa, "ranges") != 12)
2781 return;
Hollis Blanchard54f4ee12006-05-25 16:36:53 -05002782 if (prom_getprop(isa, "ranges", isa_ranges, sizeof(isa_ranges))
2783 == PROM_ERROR)
2784 return;
2785
2786 if (isa_ranges[0] != 0x1 ||
2787 isa_ranges[1] != 0xf4000000 ||
2788 isa_ranges[2] != 0x00010000)
2789 return;
2790
Benjamin Herrenschmidt980a6512006-07-03 17:22:05 +10002791 prom_printf("Fixing up bogus ISA range on Maple/Apache...\n");
Hollis Blanchard54f4ee12006-05-25 16:36:53 -05002792
2793 isa_ranges[0] = 0x1;
2794 isa_ranges[1] = 0x0;
Benjamin Herrenschmidt980a6512006-07-03 17:22:05 +10002795 isa_ranges[2] = rloc;
Hollis Blanchard54f4ee12006-05-25 16:36:53 -05002796 isa_ranges[3] = 0x0;
2797 isa_ranges[4] = 0x0;
2798 isa_ranges[5] = 0x00010000;
Benjamin Herrenschmidt980a6512006-07-03 17:22:05 +10002799 prom_setprop(isa, name, "ranges",
Hollis Blanchard54f4ee12006-05-25 16:36:53 -05002800 isa_ranges, sizeof(isa_ranges));
2801}
Harry Ciao8f101a052009-06-17 16:28:00 -07002802
2803#define CPC925_MC_START 0xf8000000
2804#define CPC925_MC_LENGTH 0x1000000
2805/* The values for memory-controller don't have right number of cells */
2806static void __init fixup_device_tree_maple_memory_controller(void)
2807{
2808 phandle mc;
2809 u32 mc_reg[4];
2810 char *name = "/hostbridge@f8000000";
Harry Ciao8f101a052009-06-17 16:28:00 -07002811 u32 ac, sc;
2812
2813 mc = call_prom("finddevice", 1, 1, ADDR(name));
2814 if (!PHANDLE_VALID(mc))
2815 return;
2816
2817 if (prom_getproplen(mc, "reg") != 8)
2818 return;
2819
Anton Blanchard5827d412012-11-26 17:40:03 +00002820 prom_getprop(prom.root, "#address-cells", &ac, sizeof(ac));
2821 prom_getprop(prom.root, "#size-cells", &sc, sizeof(sc));
Harry Ciao8f101a052009-06-17 16:28:00 -07002822 if ((ac != 2) || (sc != 2))
2823 return;
2824
2825 if (prom_getprop(mc, "reg", mc_reg, sizeof(mc_reg)) == PROM_ERROR)
2826 return;
2827
2828 if (mc_reg[0] != CPC925_MC_START || mc_reg[1] != CPC925_MC_LENGTH)
2829 return;
2830
2831 prom_printf("Fixing up bogus hostbridge on Maple...\n");
2832
2833 mc_reg[0] = 0x0;
2834 mc_reg[1] = CPC925_MC_START;
2835 mc_reg[2] = 0x0;
2836 mc_reg[3] = CPC925_MC_LENGTH;
2837 prom_setprop(mc, name, "reg", mc_reg, sizeof(mc_reg));
2838}
Hollis Blanchard54f4ee12006-05-25 16:36:53 -05002839#else
2840#define fixup_device_tree_maple()
Harry Ciao8f101a052009-06-17 16:28:00 -07002841#define fixup_device_tree_maple_memory_controller()
Hollis Blanchard54f4ee12006-05-25 16:36:53 -05002842#endif
2843
Benjamin Herrenschmidte8c0acf2006-07-04 14:06:29 +10002844#ifdef CONFIG_PPC_CHRP
Olaf Heringe4805922007-04-04 18:20:04 +02002845/*
2846 * Pegasos and BriQ lacks the "ranges" property in the isa node
2847 * Pegasos needs decimal IRQ 14/15, not hexadecimal
Olaf Hering556ecf92007-08-18 04:27:17 +10002848 * Pegasos has the IDE configured in legacy mode, but advertised as native
Olaf Heringe4805922007-04-04 18:20:04 +02002849 */
Benjamin Herrenschmidte8c0acf2006-07-04 14:06:29 +10002850static void __init fixup_device_tree_chrp(void)
2851{
Olaf Heringe4805922007-04-04 18:20:04 +02002852 phandle ph;
2853 u32 prop[6];
Benjamin Herrenschmidt26c50322006-07-04 14:16:28 +10002854 u32 rloc = 0x01006000; /* IO space; PCI device = 12 */
Benjamin Herrenschmidte8c0acf2006-07-04 14:06:29 +10002855 char *name;
2856 int rc;
2857
2858 name = "/pci@80000000/isa@c";
Olaf Heringe4805922007-04-04 18:20:04 +02002859 ph = call_prom("finddevice", 1, 1, ADDR(name));
2860 if (!PHANDLE_VALID(ph)) {
Benjamin Herrenschmidt26c50322006-07-04 14:16:28 +10002861 name = "/pci@ff500000/isa@6";
Olaf Heringe4805922007-04-04 18:20:04 +02002862 ph = call_prom("finddevice", 1, 1, ADDR(name));
Benjamin Herrenschmidt26c50322006-07-04 14:16:28 +10002863 rloc = 0x01003000; /* IO space; PCI device = 6 */
2864 }
Olaf Heringe4805922007-04-04 18:20:04 +02002865 if (PHANDLE_VALID(ph)) {
2866 rc = prom_getproplen(ph, "ranges");
2867 if (rc == 0 || rc == PROM_ERROR) {
2868 prom_printf("Fixing up missing ISA range on Pegasos...\n");
Benjamin Herrenschmidte8c0acf2006-07-04 14:06:29 +10002869
Olaf Heringe4805922007-04-04 18:20:04 +02002870 prop[0] = 0x1;
2871 prop[1] = 0x0;
2872 prop[2] = rloc;
2873 prop[3] = 0x0;
2874 prop[4] = 0x0;
2875 prop[5] = 0x00010000;
2876 prom_setprop(ph, name, "ranges", prop, sizeof(prop));
2877 }
2878 }
Benjamin Herrenschmidte8c0acf2006-07-04 14:06:29 +10002879
Olaf Heringe4805922007-04-04 18:20:04 +02002880 name = "/pci@80000000/ide@C,1";
2881 ph = call_prom("finddevice", 1, 1, ADDR(name));
2882 if (PHANDLE_VALID(ph)) {
2883 prom_printf("Fixing up IDE interrupt on Pegasos...\n");
2884 prop[0] = 14;
2885 prop[1] = 0x0;
Olaf Hering556ecf92007-08-18 04:27:17 +10002886 prom_setprop(ph, name, "interrupts", prop, 2*sizeof(u32));
2887 prom_printf("Fixing up IDE class-code on Pegasos...\n");
2888 rc = prom_getprop(ph, "class-code", prop, sizeof(u32));
2889 if (rc == sizeof(u32)) {
2890 prop[0] &= ~0x5;
2891 prom_setprop(ph, name, "class-code", prop, sizeof(u32));
2892 }
Olaf Heringe4805922007-04-04 18:20:04 +02002893 }
Benjamin Herrenschmidte8c0acf2006-07-04 14:06:29 +10002894}
2895#else
2896#define fixup_device_tree_chrp()
2897#endif
2898
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002899#if defined(CONFIG_PPC64) && defined(CONFIG_PPC_PMAC)
Hollis Blanchard54f4ee12006-05-25 16:36:53 -05002900static void __init fixup_device_tree_pmac(void)
2901{
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002902 phandle u3, i2c, mpic;
2903 u32 u3_rev;
2904 u32 interrupts[2];
2905 u32 parent;
2906
2907 /* Some G5s have a missing interrupt definition, fix it up here */
2908 u3 = call_prom("finddevice", 1, 1, ADDR("/u3@0,f8000000"));
2909 if (!PHANDLE_VALID(u3))
2910 return;
2911 i2c = call_prom("finddevice", 1, 1, ADDR("/u3@0,f8000000/i2c@f8001000"));
2912 if (!PHANDLE_VALID(i2c))
2913 return;
2914 mpic = call_prom("finddevice", 1, 1, ADDR("/u3@0,f8000000/mpic@f8040000"));
2915 if (!PHANDLE_VALID(mpic))
2916 return;
2917
2918 /* check if proper rev of u3 */
2919 if (prom_getprop(u3, "device-rev", &u3_rev, sizeof(u3_rev))
2920 == PROM_ERROR)
2921 return;
Benjamin Herrenschmidt7d496972005-11-07 14:36:21 +11002922 if (u3_rev < 0x35 || u3_rev > 0x39)
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002923 return;
2924 /* does it need fixup ? */
2925 if (prom_getproplen(i2c, "interrupts") > 0)
2926 return;
2927
2928 prom_printf("fixing up bogus interrupts for u3 i2c...\n");
2929
2930 /* interrupt on this revision of u3 is number 0 and level */
2931 interrupts[0] = 0;
2932 interrupts[1] = 1;
Paul Mackerrasa23414b2005-11-10 12:00:55 +11002933 prom_setprop(i2c, "/u3@0,f8000000/i2c@f8001000", "interrupts",
2934 &interrupts, sizeof(interrupts));
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002935 parent = (u32)mpic;
Paul Mackerrasa23414b2005-11-10 12:00:55 +11002936 prom_setprop(i2c, "/u3@0,f8000000/i2c@f8001000", "interrupt-parent",
2937 &parent, sizeof(parent));
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002938}
Hollis Blanchard54f4ee12006-05-25 16:36:53 -05002939#else
2940#define fixup_device_tree_pmac()
2941#endif
Paul Mackerras9b6b5632005-10-06 12:06:20 +10002942
Sylvain Munaut88fd2a92007-02-12 23:13:20 +01002943#ifdef CONFIG_PPC_EFIKA
Grant Likely94d2dde2008-01-24 22:25:32 -07002944/*
2945 * The MPC5200 FEC driver requires an phy-handle property to tell it how
2946 * to talk to the phy. If the phy-handle property is missing, then this
2947 * function is called to add the appropriate nodes and link it to the
2948 * ethernet node.
2949 */
2950static void __init fixup_device_tree_efika_add_phy(void)
Sylvain Munaut88fd2a92007-02-12 23:13:20 +01002951{
Sylvain Munaut88fd2a92007-02-12 23:13:20 +01002952 u32 node;
2953 char prop[64];
Grant Likely94d2dde2008-01-24 22:25:32 -07002954 int rv;
Sylvain Munaut88fd2a92007-02-12 23:13:20 +01002955
Grant Likely94d2dde2008-01-24 22:25:32 -07002956 /* Check if /builtin/ethernet exists - bail if it doesn't */
2957 node = call_prom("finddevice", 1, 1, ADDR("/builtin/ethernet"));
Sylvain Munaut88fd2a92007-02-12 23:13:20 +01002958 if (!PHANDLE_VALID(node))
2959 return;
2960
Grant Likely94d2dde2008-01-24 22:25:32 -07002961 /* Check if the phy-handle property exists - bail if it does */
2962 rv = prom_getprop(node, "phy-handle", prop, sizeof(prop));
2963 if (!rv)
Sylvain Munaut88fd2a92007-02-12 23:13:20 +01002964 return;
2965
Grant Likely94d2dde2008-01-24 22:25:32 -07002966 /*
2967 * At this point the ethernet device doesn't have a phy described.
2968 * Now we need to add the missing phy node and linkage
2969 */
Sylvain Munaut88fd2a92007-02-12 23:13:20 +01002970
Grant Likely94d2dde2008-01-24 22:25:32 -07002971 /* Check for an MDIO bus node - if missing then create one */
Olaf Hering6f4347c2008-01-10 01:06:08 +11002972 node = call_prom("finddevice", 1, 1, ADDR("/builtin/mdio"));
2973 if (!PHANDLE_VALID(node)) {
2974 prom_printf("Adding Ethernet MDIO node\n");
2975 call_prom("interpret", 1, 1,
2976 " s\" /builtin\" find-device"
2977 " new-device"
2978 " 1 encode-int s\" #address-cells\" property"
2979 " 0 encode-int s\" #size-cells\" property"
Grant Likely94d2dde2008-01-24 22:25:32 -07002980 " s\" mdio\" device-name"
2981 " s\" fsl,mpc5200b-mdio\" encode-string"
Olaf Hering6f4347c2008-01-10 01:06:08 +11002982 " s\" compatible\" property"
2983 " 0xf0003000 0x400 reg"
2984 " 0x2 encode-int"
2985 " 0x5 encode-int encode+"
2986 " 0x3 encode-int encode+"
2987 " s\" interrupts\" property"
2988 " finish-device");
2989 };
2990
Grant Likely94d2dde2008-01-24 22:25:32 -07002991 /* Check for a PHY device node - if missing then create one and
2992 * give it's phandle to the ethernet node */
2993 node = call_prom("finddevice", 1, 1,
2994 ADDR("/builtin/mdio/ethernet-phy"));
Olaf Hering6f4347c2008-01-10 01:06:08 +11002995 if (!PHANDLE_VALID(node)) {
2996 prom_printf("Adding Ethernet PHY node\n");
2997 call_prom("interpret", 1, 1,
2998 " s\" /builtin/mdio\" find-device"
2999 " new-device"
3000 " s\" ethernet-phy\" device-name"
3001 " 0x10 encode-int s\" reg\" property"
3002 " my-self"
3003 " ihandle>phandle"
3004 " finish-device"
3005 " s\" /builtin/ethernet\" find-device"
3006 " encode-int"
3007 " s\" phy-handle\" property"
3008 " device-end");
3009 }
Grant Likely94d2dde2008-01-24 22:25:32 -07003010}
Olaf Hering6f4347c2008-01-10 01:06:08 +11003011
Grant Likely94d2dde2008-01-24 22:25:32 -07003012static void __init fixup_device_tree_efika(void)
3013{
3014 int sound_irq[3] = { 2, 2, 0 };
3015 int bcomm_irq[3*16] = { 3,0,0, 3,1,0, 3,2,0, 3,3,0,
3016 3,4,0, 3,5,0, 3,6,0, 3,7,0,
3017 3,8,0, 3,9,0, 3,10,0, 3,11,0,
3018 3,12,0, 3,13,0, 3,14,0, 3,15,0 };
3019 u32 node;
3020 char prop[64];
3021 int rv, len;
3022
3023 /* Check if we're really running on a EFIKA */
3024 node = call_prom("finddevice", 1, 1, ADDR("/"));
3025 if (!PHANDLE_VALID(node))
3026 return;
3027
3028 rv = prom_getprop(node, "model", prop, sizeof(prop));
3029 if (rv == PROM_ERROR)
3030 return;
Christophe Leroy450e7dd2019-04-26 16:23:28 +00003031 if (prom_strcmp(prop, "EFIKA5K2"))
Grant Likely94d2dde2008-01-24 22:25:32 -07003032 return;
3033
3034 prom_printf("Applying EFIKA device tree fixups\n");
3035
3036 /* Claiming to be 'chrp' is death */
3037 node = call_prom("finddevice", 1, 1, ADDR("/"));
3038 rv = prom_getprop(node, "device_type", prop, sizeof(prop));
Christophe Leroy450e7dd2019-04-26 16:23:28 +00003039 if (rv != PROM_ERROR && (prom_strcmp(prop, "chrp") == 0))
Grant Likely94d2dde2008-01-24 22:25:32 -07003040 prom_setprop(node, "/", "device_type", "efika", sizeof("efika"));
3041
David Woodhouse7f4392c2008-04-14 02:52:38 +10003042 /* CODEGEN,description is exposed in /proc/cpuinfo so
3043 fix that too */
3044 rv = prom_getprop(node, "CODEGEN,description", prop, sizeof(prop));
Christophe Leroy450e7dd2019-04-26 16:23:28 +00003045 if (rv != PROM_ERROR && (prom_strstr(prop, "CHRP")))
David Woodhouse7f4392c2008-04-14 02:52:38 +10003046 prom_setprop(node, "/", "CODEGEN,description",
3047 "Efika 5200B PowerPC System",
3048 sizeof("Efika 5200B PowerPC System"));
3049
Grant Likely94d2dde2008-01-24 22:25:32 -07003050 /* Fixup bestcomm interrupts property */
3051 node = call_prom("finddevice", 1, 1, ADDR("/builtin/bestcomm"));
3052 if (PHANDLE_VALID(node)) {
3053 len = prom_getproplen(node, "interrupts");
3054 if (len == 12) {
3055 prom_printf("Fixing bestcomm interrupts property\n");
3056 prom_setprop(node, "/builtin/bestcom", "interrupts",
3057 bcomm_irq, sizeof(bcomm_irq));
3058 }
3059 }
3060
3061 /* Fixup sound interrupts property */
3062 node = call_prom("finddevice", 1, 1, ADDR("/builtin/sound"));
3063 if (PHANDLE_VALID(node)) {
3064 rv = prom_getprop(node, "interrupts", prop, sizeof(prop));
3065 if (rv == PROM_ERROR) {
3066 prom_printf("Adding sound interrupts property\n");
3067 prom_setprop(node, "/builtin/sound", "interrupts",
3068 sound_irq, sizeof(sound_irq));
3069 }
3070 }
3071
3072 /* Make sure ethernet phy-handle property exists */
3073 fixup_device_tree_efika_add_phy();
Sylvain Munaut88fd2a92007-02-12 23:13:20 +01003074}
3075#else
3076#define fixup_device_tree_efika()
3077#endif
3078
Darren Stevens50246782016-08-31 13:24:40 +01003079#ifdef CONFIG_PPC_PASEMI_NEMO
3080/*
3081 * CFE supplied on Nemo is broken in several ways, biggest
3082 * problem is that it reassigns ISA interrupts to unused mpic ints.
3083 * Add an interrupt-controller property for the io-bridge to use
3084 * and correct the ints so we can attach them to an irq_domain
3085 */
3086static void __init fixup_device_tree_pasemi(void)
3087{
3088 u32 interrupts[2], parent, rval, val = 0;
3089 char *name, *pci_name;
3090 phandle iob, node;
3091
3092 /* Find the root pci node */
3093 name = "/pxp@0,e0000000";
3094 iob = call_prom("finddevice", 1, 1, ADDR(name));
3095 if (!PHANDLE_VALID(iob))
3096 return;
3097
3098 /* check if interrupt-controller node set yet */
3099 if (prom_getproplen(iob, "interrupt-controller") !=PROM_ERROR)
3100 return;
3101
3102 prom_printf("adding interrupt-controller property for SB600...\n");
3103
3104 prom_setprop(iob, name, "interrupt-controller", &val, 0);
3105
3106 pci_name = "/pxp@0,e0000000/pci@11";
3107 node = call_prom("finddevice", 1, 1, ADDR(pci_name));
3108 parent = ADDR(iob);
3109
3110 for( ; prom_next_node(&node); ) {
3111 /* scan each node for one with an interrupt */
3112 if (!PHANDLE_VALID(node))
3113 continue;
3114
3115 rval = prom_getproplen(node, "interrupts");
3116 if (rval == 0 || rval == PROM_ERROR)
3117 continue;
3118
3119 prom_getprop(node, "interrupts", &interrupts, sizeof(interrupts));
3120 if ((interrupts[0] < 212) || (interrupts[0] > 222))
3121 continue;
3122
3123 /* found a node, update both interrupts and interrupt-parent */
3124 if ((interrupts[0] >= 212) && (interrupts[0] <= 215))
3125 interrupts[0] -= 203;
3126 if ((interrupts[0] >= 216) && (interrupts[0] <= 220))
3127 interrupts[0] -= 213;
3128 if (interrupts[0] == 221)
3129 interrupts[0] = 14;
3130 if (interrupts[0] == 222)
3131 interrupts[0] = 8;
3132
3133 prom_setprop(node, pci_name, "interrupts", interrupts,
3134 sizeof(interrupts));
3135 prom_setprop(node, pci_name, "interrupt-parent", &parent,
3136 sizeof(parent));
3137 }
Darren Stevens687e16b2016-08-31 13:24:45 +01003138
3139 /*
3140 * The io-bridge has device_type set to 'io-bridge' change it to 'isa'
3141 * so that generic isa-bridge code can add the SB600 and its on-board
3142 * peripherals.
3143 */
3144 name = "/pxp@0,e0000000/io-bridge@0";
3145 iob = call_prom("finddevice", 1, 1, ADDR(name));
3146 if (!PHANDLE_VALID(iob))
3147 return;
3148
3149 /* device_type is already set, just change it. */
3150
3151 prom_printf("Changing device_type of SB600 node...\n");
3152
3153 prom_setprop(iob, name, "device_type", "isa", sizeof("isa"));
Darren Stevens50246782016-08-31 13:24:40 +01003154}
3155#else /* !CONFIG_PPC_PASEMI_NEMO */
3156static inline void fixup_device_tree_pasemi(void) { }
3157#endif
3158
Hollis Blanchard54f4ee12006-05-25 16:36:53 -05003159static void __init fixup_device_tree(void)
3160{
3161 fixup_device_tree_maple();
Harry Ciao8f101a052009-06-17 16:28:00 -07003162 fixup_device_tree_maple_memory_controller();
Benjamin Herrenschmidte8c0acf2006-07-04 14:06:29 +10003163 fixup_device_tree_chrp();
Hollis Blanchard54f4ee12006-05-25 16:36:53 -05003164 fixup_device_tree_pmac();
Sylvain Munaut88fd2a92007-02-12 23:13:20 +01003165 fixup_device_tree_efika();
Darren Stevens50246782016-08-31 13:24:40 +01003166 fixup_device_tree_pasemi();
Hollis Blanchard54f4ee12006-05-25 16:36:53 -05003167}
Paul Mackerras9b6b5632005-10-06 12:06:20 +10003168
3169static void __init prom_find_boot_cpu(void)
3170{
Benjamin Herrenschmidt493adff2013-08-07 02:01:38 +10003171 __be32 rval;
Paul Mackerras9b6b5632005-10-06 12:06:20 +10003172 ihandle prom_cpu;
3173 phandle cpu_pkg;
3174
Benjamin Herrenschmidt493adff2013-08-07 02:01:38 +10003175 rval = 0;
3176 if (prom_getprop(prom.chosen, "cpu", &rval, sizeof(rval)) <= 0)
Paul Mackerrasa575b802005-10-23 17:23:21 +10003177 return;
Benjamin Herrenschmidt493adff2013-08-07 02:01:38 +10003178 prom_cpu = be32_to_cpu(rval);
Paul Mackerras9b6b5632005-10-06 12:06:20 +10003179
3180 cpu_pkg = call_prom("instance-to-package", 1, 1, prom_cpu);
3181
Darren Stevensaf2b7fa2017-01-23 19:42:54 +00003182 if (!PHANDLE_VALID(cpu_pkg))
3183 return;
3184
Benjamin Herrenschmidt493adff2013-08-07 02:01:38 +10003185 prom_getprop(cpu_pkg, "reg", &rval, sizeof(rval));
3186 prom.cpu = be32_to_cpu(rval);
Paul Mackerras9b6b5632005-10-06 12:06:20 +10003187
Mathieu Malaterreeae5f702018-04-06 22:12:19 +02003188 prom_debug("Booting CPU hw index = %d\n", prom.cpu);
Paul Mackerras9b6b5632005-10-06 12:06:20 +10003189}
3190
3191static void __init prom_check_initrd(unsigned long r3, unsigned long r4)
3192{
3193#ifdef CONFIG_BLK_DEV_INITRD
Paul Mackerras9b6b5632005-10-06 12:06:20 +10003194 if (r3 && r4 && r4 != 0xdeadbeef) {
Benjamin Herrenschmidt493adff2013-08-07 02:01:38 +10003195 __be64 val;
Paul Mackerras9b6b5632005-10-06 12:06:20 +10003196
Anton Blanchard5827d412012-11-26 17:40:03 +00003197 prom_initrd_start = is_kernel_addr(r3) ? __pa(r3) : r3;
3198 prom_initrd_end = prom_initrd_start + r4;
Paul Mackerras9b6b5632005-10-06 12:06:20 +10003199
Benjamin Herrenschmidt493adff2013-08-07 02:01:38 +10003200 val = cpu_to_be64(prom_initrd_start);
Anton Blanchard5827d412012-11-26 17:40:03 +00003201 prom_setprop(prom.chosen, "/chosen", "linux,initrd-start",
Paul Mackerrasa23414b2005-11-10 12:00:55 +11003202 &val, sizeof(val));
Benjamin Herrenschmidt493adff2013-08-07 02:01:38 +10003203 val = cpu_to_be64(prom_initrd_end);
Anton Blanchard5827d412012-11-26 17:40:03 +00003204 prom_setprop(prom.chosen, "/chosen", "linux,initrd-end",
Paul Mackerrasa23414b2005-11-10 12:00:55 +11003205 &val, sizeof(val));
Paul Mackerras9b6b5632005-10-06 12:06:20 +10003206
Anton Blanchard5827d412012-11-26 17:40:03 +00003207 reserve_mem(prom_initrd_start,
3208 prom_initrd_end - prom_initrd_start);
Paul Mackerras9b6b5632005-10-06 12:06:20 +10003209
Mathieu Malaterreeae5f702018-04-06 22:12:19 +02003210 prom_debug("initrd_start=0x%lx\n", prom_initrd_start);
3211 prom_debug("initrd_end=0x%lx\n", prom_initrd_end);
Paul Mackerras9b6b5632005-10-06 12:06:20 +10003212 }
3213#endif /* CONFIG_BLK_DEV_INITRD */
3214}
3215
Anton Blanchard5ac47f72012-11-26 17:39:03 +00003216#ifdef CONFIG_PPC64
3217#ifdef CONFIG_RELOCATABLE
3218static void reloc_toc(void)
3219{
3220}
3221
3222static void unreloc_toc(void)
3223{
3224}
3225#else
Anton Blanchard16744002013-03-12 01:51:51 +00003226static void __reloc_toc(unsigned long offset, unsigned long nr_entries)
Anton Blanchard5ac47f72012-11-26 17:39:03 +00003227{
3228 unsigned long i;
Anton Blanchard16744002013-03-12 01:51:51 +00003229 unsigned long *toc_entry;
3230
3231 /* Get the start of the TOC by using r2 directly. */
3232 asm volatile("addi %0,2,-0x8000" : "=b" (toc_entry));
Anton Blanchard5ac47f72012-11-26 17:39:03 +00003233
3234 for (i = 0; i < nr_entries; i++) {
3235 *toc_entry = *toc_entry + offset;
3236 toc_entry++;
3237 }
3238}
3239
3240static void reloc_toc(void)
3241{
3242 unsigned long offset = reloc_offset();
3243 unsigned long nr_entries =
3244 (__prom_init_toc_end - __prom_init_toc_start) / sizeof(long);
3245
Anton Blanchard16744002013-03-12 01:51:51 +00003246 __reloc_toc(offset, nr_entries);
Anton Blanchard5ac47f72012-11-26 17:39:03 +00003247
3248 mb();
3249}
3250
3251static void unreloc_toc(void)
3252{
3253 unsigned long offset = reloc_offset();
3254 unsigned long nr_entries =
3255 (__prom_init_toc_end - __prom_init_toc_start) / sizeof(long);
3256
3257 mb();
3258
Anton Blanchard16744002013-03-12 01:51:51 +00003259 __reloc_toc(-offset, nr_entries);
Anton Blanchard5ac47f72012-11-26 17:39:03 +00003260}
3261#endif
3262#endif
Benjamin Herrenschmidt27f44882011-09-19 18:27:58 +00003263
Ram Pai6a9c9302019-08-19 23:13:14 -03003264#ifdef CONFIG_PPC_SVM
3265/*
3266 * Perform the Enter Secure Mode ultracall.
3267 */
3268static int enter_secure_mode(unsigned long kbase, unsigned long fdt)
3269{
3270 register unsigned long r3 asm("r3") = UV_ESM;
3271 register unsigned long r4 asm("r4") = kbase;
3272 register unsigned long r5 asm("r5") = fdt;
3273
3274 asm volatile("sc 2" : "+r"(r3) : "r"(r4), "r"(r5));
3275
3276 return r3;
3277}
3278
3279/*
3280 * Call the Ultravisor to transfer us to secure memory if we have an ESM blob.
3281 */
Vladis Dronovaff77952020-07-29 15:37:41 +02003282static void __init setup_secure_guest(unsigned long kbase, unsigned long fdt)
Ram Pai6a9c9302019-08-19 23:13:14 -03003283{
3284 int ret;
3285
3286 if (!prom_svm_enable)
3287 return;
3288
3289 /* Switch to secure mode. */
3290 prom_printf("Switching to secure mode.\n");
3291
Thiago Jung Bauermann05d9a952019-09-11 13:34:33 -03003292 /*
3293 * The ultravisor will do an integrity check of the kernel image but we
3294 * relocated it so the check will fail. Restore the original image by
3295 * relocating it back to the kernel virtual base address.
3296 */
3297 if (IS_ENABLED(CONFIG_RELOCATABLE))
3298 relocate(KERNELBASE);
3299
Ram Pai6a9c9302019-08-19 23:13:14 -03003300 ret = enter_secure_mode(kbase, fdt);
Thiago Jung Bauermann05d9a952019-09-11 13:34:33 -03003301
3302 /* Relocate the kernel again. */
3303 if (IS_ENABLED(CONFIG_RELOCATABLE))
3304 relocate(kbase);
3305
Ram Pai6a9c9302019-08-19 23:13:14 -03003306 if (ret != U_SUCCESS) {
3307 prom_printf("Returned %d from switching to secure mode.\n", ret);
3308 prom_rtas_os_term("Switch to secure mode failed.\n");
3309 }
3310}
3311#else
Vladis Dronovaff77952020-07-29 15:37:41 +02003312static void __init setup_secure_guest(unsigned long kbase, unsigned long fdt)
Ram Pai6a9c9302019-08-19 23:13:14 -03003313{
3314}
3315#endif /* CONFIG_PPC_SVM */
3316
Paul Mackerras9b6b5632005-10-06 12:06:20 +10003317/*
3318 * We enter here early on, when the Open Firmware prom is still
3319 * handling exceptions and the MMU hash table for us.
3320 */
3321
3322unsigned long __init prom_init(unsigned long r3, unsigned long r4,
3323 unsigned long pp,
Paul Mackerras549e8152008-08-30 11:43:47 +10003324 unsigned long r6, unsigned long r7,
3325 unsigned long kbase)
Paul Mackerras9b6b5632005-10-06 12:06:20 +10003326{
Paul Mackerras9b6b5632005-10-06 12:06:20 +10003327 unsigned long hdr;
Paul Mackerras9b6b5632005-10-06 12:06:20 +10003328
3329#ifdef CONFIG_PPC32
Paul Mackerras549e8152008-08-30 11:43:47 +10003330 unsigned long offset = reloc_offset();
Paul Mackerras9b6b5632005-10-06 12:06:20 +10003331 reloc_got2(offset);
Anton Blanchard5ac47f72012-11-26 17:39:03 +00003332#else
3333 reloc_toc();
Paul Mackerras9b6b5632005-10-06 12:06:20 +10003334#endif
3335
Paul Mackerras9b6b5632005-10-06 12:06:20 +10003336 /*
3337 * First zero the BSS
3338 */
Anton Blanchard5827d412012-11-26 17:40:03 +00003339 memset(&__bss_start, 0, __bss_stop - __bss_start);
Paul Mackerras9b6b5632005-10-06 12:06:20 +10003340
3341 /*
3342 * Init interface to Open Firmware, get some node references,
3343 * like /chosen
3344 */
3345 prom_init_client_services(pp);
3346
3347 /*
Paul Mackerrasa23414b2005-11-10 12:00:55 +11003348 * See if this OF is old enough that we need to do explicit maps
3349 * and other workarounds
3350 */
3351 prom_find_mmu();
3352
3353 /*
Paul Mackerras9b6b5632005-10-06 12:06:20 +10003354 * Init prom stdout device
3355 */
3356 prom_init_stdout();
3357
Anton Blanchard5827d412012-11-26 17:40:03 +00003358 prom_printf("Preparing to boot %s", linux_banner);
Michael Ellermane7943fb2009-03-04 19:02:01 +00003359
Paul Mackerras9b6b5632005-10-06 12:06:20 +10003360 /*
3361 * Get default machine type. At this point, we do not differentiate
3362 * between pSeries SMP and pSeries LPAR
3363 */
Anton Blanchard5827d412012-11-26 17:40:03 +00003364 of_platform = prom_find_machine_type();
3365 prom_printf("Detected machine type: %x\n", of_platform);
Paul Mackerras9b6b5632005-10-06 12:06:20 +10003366
Suzuki Poulose0f890c82011-12-14 22:57:15 +00003367#ifndef CONFIG_NONSTATIC_KERNEL
Olaf Heringadd60ef2006-03-23 22:03:57 +01003368 /* Bail if this is a kdump kernel. */
3369 if (PHYSICAL_START > 0)
3370 prom_panic("Error: You can't boot a kdump kernel from OF!\n");
Paul Mackerras549e8152008-08-30 11:43:47 +10003371#endif
Olaf Heringadd60ef2006-03-23 22:03:57 +01003372
3373 /*
3374 * Check for an initrd
3375 */
3376 prom_check_initrd(r3, r4);
3377
Suraj Jitindar Singh12cc9fd2017-02-28 17:03:47 +11003378 /*
3379 * Do early parsing of command line
3380 */
3381 early_cmdline_parse();
3382
Benjamin Herrenschmidt11fdb302018-10-15 13:49:53 +11003383#ifdef CONFIG_PPC_PSERIES
Paul Mackerras9b6b5632005-10-06 12:06:20 +10003384 /*
3385 * On pSeries, inform the firmware about our capabilities
3386 */
Anton Blanchard5827d412012-11-26 17:40:03 +00003387 if (of_platform == PLATFORM_PSERIES ||
3388 of_platform == PLATFORM_PSERIES_LPAR)
Paul Mackerras9b6b5632005-10-06 12:06:20 +10003389 prom_send_capabilities();
3390#endif
3391
Paul Mackerras9b6b5632005-10-06 12:06:20 +10003392 /*
Arnd Bergmannf3f66f52005-10-31 20:08:37 -05003393 * Copy the CPU hold code
Paul Mackerras9b6b5632005-10-06 12:06:20 +10003394 */
Anton Blanchard5827d412012-11-26 17:40:03 +00003395 if (of_platform != PLATFORM_POWERMAC)
Paul Mackerras549e8152008-08-30 11:43:47 +10003396 copy_and_flush(0, kbase, 0x100, 0);
Paul Mackerras9b6b5632005-10-06 12:06:20 +10003397
3398 /*
Paul Mackerras9b6b5632005-10-06 12:06:20 +10003399 * Initialize memory management within prom_init
3400 */
3401 prom_init_mem();
3402
3403 /*
3404 * Determine which cpu is actually running right _now_
3405 */
3406 prom_find_boot_cpu();
3407
3408 /*
3409 * Initialize display devices
3410 */
3411 prom_check_displays();
3412
Benjamin Herrenschmidt493adff2013-08-07 02:01:38 +10003413#if defined(CONFIG_PPC64) && defined(__BIG_ENDIAN__)
Paul Mackerras9b6b5632005-10-06 12:06:20 +10003414 /*
3415 * Initialize IOMMU (TCE tables) on pSeries. Do that before anything else
3416 * that uses the allocator, we need to make sure we get the top of memory
3417 * available for us here...
3418 */
Anton Blanchard5827d412012-11-26 17:40:03 +00003419 if (of_platform == PLATFORM_PSERIES)
Paul Mackerras9b6b5632005-10-06 12:06:20 +10003420 prom_initialize_tce_table();
3421#endif
3422
3423 /*
Benjamin Herrenschmidt27f44882011-09-19 18:27:58 +00003424 * On non-powermacs, try to instantiate RTAS. PowerMacs don't
3425 * have a usable RTAS implementation.
Paul Mackerras9b6b5632005-10-06 12:06:20 +10003426 */
Benjamin Herrenschmidt11fdb302018-10-15 13:49:53 +11003427 if (of_platform != PLATFORM_POWERMAC)
Paul Mackerras9b6b5632005-10-06 12:06:20 +10003428 prom_instantiate_rtas();
Benjamin Herrenschmidt27f44882011-09-19 18:27:58 +00003429
Ashley Lai4a727422012-08-14 18:34:57 -05003430#ifdef CONFIG_PPC64
3431 /* instantiate sml */
3432 prom_instantiate_sml();
3433#endif
3434
Benjamin Herrenschmidt27f44882011-09-19 18:27:58 +00003435 /*
3436 * On non-powermacs, put all CPUs in spin-loops.
3437 *
3438 * PowerMacs use a different mechanism to spin CPUs
Benjamin Herrenschmidtdbe78b42013-09-25 14:02:50 +10003439 *
3440 * (This must be done after instanciating RTAS)
Benjamin Herrenschmidt27f44882011-09-19 18:27:58 +00003441 */
Benjamin Herrenschmidt11fdb302018-10-15 13:49:53 +11003442 if (of_platform != PLATFORM_POWERMAC)
Benjamin Herrenschmidt27f44882011-09-19 18:27:58 +00003443 prom_hold_cpus();
Paul Mackerras9b6b5632005-10-06 12:06:20 +10003444
3445 /*
3446 * Fill in some infos for use by the kernel later on
3447 */
Benjamin Herrenschmidt493adff2013-08-07 02:01:38 +10003448 if (prom_memory_limit) {
3449 __be64 val = cpu_to_be64(prom_memory_limit);
Anton Blanchard5827d412012-11-26 17:40:03 +00003450 prom_setprop(prom.chosen, "/chosen", "linux,memory-limit",
Benjamin Herrenschmidt493adff2013-08-07 02:01:38 +10003451 &val, sizeof(val));
3452 }
Paul Mackerras9b6b5632005-10-06 12:06:20 +10003453#ifdef CONFIG_PPC64
Anton Blanchard5827d412012-11-26 17:40:03 +00003454 if (prom_iommu_off)
3455 prom_setprop(prom.chosen, "/chosen", "linux,iommu-off",
Paul Mackerrasa23414b2005-11-10 12:00:55 +11003456 NULL, 0);
Paul Mackerras9b6b5632005-10-06 12:06:20 +10003457
Anton Blanchard5827d412012-11-26 17:40:03 +00003458 if (prom_iommu_force_on)
3459 prom_setprop(prom.chosen, "/chosen", "linux,iommu-force-on",
Paul Mackerrasa23414b2005-11-10 12:00:55 +11003460 NULL, 0);
Paul Mackerras9b6b5632005-10-06 12:06:20 +10003461
Anton Blanchard5827d412012-11-26 17:40:03 +00003462 if (prom_tce_alloc_start) {
3463 prom_setprop(prom.chosen, "/chosen", "linux,tce-alloc-start",
3464 &prom_tce_alloc_start,
Paul Mackerras9b6b5632005-10-06 12:06:20 +10003465 sizeof(prom_tce_alloc_start));
Anton Blanchard5827d412012-11-26 17:40:03 +00003466 prom_setprop(prom.chosen, "/chosen", "linux,tce-alloc-end",
3467 &prom_tce_alloc_end,
Paul Mackerras9b6b5632005-10-06 12:06:20 +10003468 sizeof(prom_tce_alloc_end));
3469 }
3470#endif
3471
3472 /*
3473 * Fixup any known bugs in the device-tree
3474 */
3475 fixup_device_tree();
3476
3477 /*
3478 * Now finally create the flattened device-tree
3479 */
Anton Blanchard1f8737a2009-03-31 20:06:15 +00003480 prom_printf("copying OF device tree...\n");
Paul Mackerras9b6b5632005-10-06 12:06:20 +10003481 flatten_device_tree();
3482
Paul Mackerras3825ac02005-11-08 22:48:08 +11003483 /*
3484 * in case stdin is USB and still active on IBM machines...
3485 * Unfortunately quiesce crashes on some powermacs if we have
Benjamin Herrenschmidt11fdb302018-10-15 13:49:53 +11003486 * closed stdin already (in particular the powerbook 101).
Paul Mackerras3825ac02005-11-08 22:48:08 +11003487 */
Benjamin Herrenschmidt11fdb302018-10-15 13:49:53 +11003488 if (of_platform != PLATFORM_POWERMAC)
Paul Mackerras3825ac02005-11-08 22:48:08 +11003489 prom_close_stdin();
Paul Mackerras9b6b5632005-10-06 12:06:20 +10003490
3491 /*
3492 * Call OF "quiesce" method to shut down pending DMA's from
3493 * devices etc...
3494 */
Michael Ellerman7e862d72015-03-30 17:38:09 +11003495 prom_printf("Quiescing Open Firmware ...\n");
Paul Mackerras9b6b5632005-10-06 12:06:20 +10003496 call_prom("quiesce", 0, 0);
3497
3498 /*
3499 * And finally, call the kernel passing it the flattened device
3500 * tree and NULL as r5, thus triggering the new entry point which
3501 * is common to us and kexec
3502 */
Anton Blanchard5827d412012-11-26 17:40:03 +00003503 hdr = dt_header_start;
Benjamin Herrenschmidt40dfef62011-11-29 18:22:56 +00003504
Benjamin Herrenschmidt11fdb302018-10-15 13:49:53 +11003505 prom_printf("Booting Linux via __start() @ 0x%lx ...\n", kbase);
3506 prom_debug("->dt_header_start=0x%lx\n", hdr);
Paul Mackerras9b6b5632005-10-06 12:06:20 +10003507
3508#ifdef CONFIG_PPC32
3509 reloc_got2(-offset);
Anton Blanchard5ac47f72012-11-26 17:39:03 +00003510#else
3511 unreloc_toc();
Paul Mackerras9b6b5632005-10-06 12:06:20 +10003512#endif
3513
Ram Pai6a9c9302019-08-19 23:13:14 -03003514 /* Move to secure memory if we're supposed to be secure guests. */
3515 setup_secure_guest(kbase, hdr);
3516
Benjamin Herrenschmidt6e35d5d2011-09-19 18:28:01 +00003517 __start(hdr, kbase, 0, 0, 0, 0, 0);
Paul Mackerras9b6b5632005-10-06 12:06:20 +10003518
3519 return 0;
3520}